-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathrequirements.go
161 lines (147 loc) · 3.79 KB
/
requirements.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
package jess
import (
"fmt"
"strings"
)
// Security requirements of a letter.
const (
Confidentiality uint8 = iota
Integrity
RecipientAuthentication
SenderAuthentication
)
// Requirements describe security properties.
type Requirements struct {
all []uint8
}
// newEmptyRequirements returns an empty requirements instance.
func newEmptyRequirements() *Requirements {
return &Requirements{}
}
// NewRequirements returns an attribute instance with all requirements.
func NewRequirements() *Requirements {
return &Requirements{
all: []uint8{
Confidentiality,
Integrity,
RecipientAuthentication,
SenderAuthentication,
},
}
}
// Empty returns whether the requirements are empty.
func (requirements *Requirements) Empty() bool {
return len(requirements.all) == 0
}
// Has returns whether the requirements contain the given attribute.
func (requirements *Requirements) Has(attribute uint8) bool {
for _, attr := range requirements.all {
if attr == attribute {
return true
}
}
return false
}
// Add adds an attribute.
func (requirements *Requirements) Add(attribute uint8) *Requirements {
if !requirements.Has(attribute) {
requirements.all = append(requirements.all, attribute)
}
return requirements
}
// Remove removes an attribute.
func (requirements *Requirements) Remove(attribute uint8) *Requirements {
for i, attr := range requirements.all {
if attr == attribute {
requirements.all = append(requirements.all[:i], requirements.all[i+1:]...)
return requirements
}
}
return requirements
}
// CheckComplianceTo checks if the requirements are compliant to the given required requirements.
func (requirements *Requirements) CheckComplianceTo(requirement *Requirements) error {
var missing *Requirements
for _, attr := range requirement.all {
if !requirements.Has(attr) {
if missing == nil {
missing = newEmptyRequirements()
}
missing.Add(attr)
}
}
if missing != nil {
return fmt.Errorf("missing security requirements: %s", missing.String())
}
return nil
}
// String returns a string representation of the requirements.
func (requirements *Requirements) String() string {
var names []string
for _, attr := range requirements.all {
switch attr {
case Confidentiality:
names = append(names, "Confidentiality")
case Integrity:
names = append(names, "Integrity")
case RecipientAuthentication:
names = append(names, "RecipientAuthentication")
case SenderAuthentication:
names = append(names, "SenderAuthentication")
}
}
return strings.Join(names, ", ")
}
// ShortString returns a short string representation of the requirements.
func (requirements *Requirements) ShortString() string {
var s string
if requirements.Has(Confidentiality) {
s += "C"
}
if requirements.Has(Integrity) {
s += "I"
}
if requirements.Has(RecipientAuthentication) {
s += "R"
}
if requirements.Has(SenderAuthentication) {
s += "S"
}
return s
}
// SerializeToNoSpec returns the requirements as a negated "No" string.
func (requirements *Requirements) SerializeToNoSpec() string {
var s string
if !requirements.Has(Confidentiality) {
s += "C"
}
if !requirements.Has(Integrity) {
s += "I"
}
if !requirements.Has(RecipientAuthentication) {
s += "R"
}
if !requirements.Has(SenderAuthentication) {
s += "S"
}
return s
}
// ParseRequirementsFromNoSpec parses the requirements from a negated "No" string.
func ParseRequirementsFromNoSpec(no string) (*Requirements, error) {
requirements := NewRequirements()
for _, id := range no {
switch id {
case 'C':
requirements.Remove(Confidentiality)
case 'I':
requirements.Remove(Integrity)
case 'R':
requirements.Remove(RecipientAuthentication)
case 'S':
requirements.Remove(SenderAuthentication)
default:
return nil, fmt.Errorf("unknown attribute identifier: %c", id)
}
}
return requirements, nil
}