blob: bd75d5b5cd8467a11be2d8872f0707934932f0ec [file] [log] [blame]
Scott Baker8461e152019-10-01 14:44:30 -07001package types
2
3// Reference: https://www.ietf.org/rfc/rfc4120.txt
4// Section: 5.2.8
5
6import (
7 "github.com/jcmturner/gofork/encoding/asn1"
8)
9
10/*
11KerberosFlags
12
13For several message types, a specific constrained bit string type,
14KerberosFlags, is used.
15
16KerberosFlags ::= BIT STRING (SIZE (32..MAX))
17-- minimum number of bits shall be sent,
18-- but no fewer than 32
19
20Compatibility note: The following paragraphs describe a change from
21the RFC 1510 description of bit strings that would result in
22incompatility in the case of an implementation that strictly
23conformed to ASN.1 DER and RFC 1510.
24
25ASN.1 bit strings have multiple uses. The simplest use of a bit
26string is to contain a vector of bits, with no particular meaning
27attached to individual bits. This vector of bits is not necessarily
28a multiple of eight bits long. The use in Kerberos of a bit string
29as a compact boolean vector wherein each element has a distinct
30meaning poses some problems. The natural notation for a compact
31boolean vector is the ASN.1 "NamedBit" notation, and the DER require
32that encodings of a bit string using "NamedBit" notation exclude any
33trailing zero bits. This truncation is easy to neglect, especially
34given C language implementations that naturally choose to store
35boolean vectors as 32-bit integers.
36
37For example, if the notation for KDCOptions were to include the
38"NamedBit" notation, as in RFC 1510, and a KDCOptions value to be
39encoded had only the "forwardable" (bit number one) bit set, the DER
40encoding MUST include only two bits: the first reserved bit
41("reserved", bit number zero, value zero) and the one-valued bit (bit
42number one) for "forwardable".
43
44Most existing implementations of Kerberos unconditionally send 32
45bits on the wire when encoding bit strings used as boolean vectors.
46This behavior violates the ASN.1 syntax used for flag values in RFC
471510, but it occurs on such a widely installed base that the protocol
48description is being modified to accommodate it.
49
50Consequently, this document removes the "NamedBit" notations for
51individual bits, relegating them to comments. The size constraint on
52the KerberosFlags type requires that at least 32 bits be encoded at
53all times, though a lenient implementation MAY choose to accept fewer
54than 32 bits and to treat the missing bits as set to zero.
55
56Currently, no uses of KerberosFlags specify more than 32 bits' worth
57of flags, although future revisions of this document may do so. When
58more than 32 bits are to be transmitted in a KerberosFlags value,
59future revisions to this document will likely specify that the
60smallest number of bits needed to encode the highest-numbered one-
61valued bit should be sent. This is somewhat similar to the DER
62encoding of a bit string that is declared with the "NamedBit"
63notation.
64*/
65
66// NewKrbFlags returns an ASN1 BitString struct of the right size for KrbFlags.
67func NewKrbFlags() asn1.BitString {
68 f := asn1.BitString{}
69 f.Bytes = make([]byte, 4)
70 f.BitLength = len(f.Bytes) * 8
71 return f
72}
73
74// SetFlags sets the flags of an ASN1 BitString.
75func SetFlags(f *asn1.BitString, j []int) {
76 for _, i := range j {
77 SetFlag(f, i)
78 }
79}
80
81// SetFlag sets a flag in an ASN1 BitString.
82func SetFlag(f *asn1.BitString, i int) {
83 for l := len(f.Bytes); l < 4; l++ {
84 (*f).Bytes = append((*f).Bytes, byte(0))
85 (*f).BitLength = len((*f).Bytes) * 8
86 }
87 //Which byte?
88 b := i / 8
89 //Which bit in byte
90 p := uint(7 - (i - 8*b))
91 (*f).Bytes[b] = (*f).Bytes[b] | (1 << p)
92}
93
94// UnsetFlags unsets flags in an ASN1 BitString.
95func UnsetFlags(f *asn1.BitString, j []int) {
96 for _, i := range j {
97 UnsetFlag(f, i)
98 }
99}
100
101// UnsetFlag unsets a flag in an ASN1 BitString.
102func UnsetFlag(f *asn1.BitString, i int) {
103 for l := len(f.Bytes); l < 4; l++ {
104 (*f).Bytes = append((*f).Bytes, byte(0))
105 (*f).BitLength = len((*f).Bytes) * 8
106 }
107 //Which byte?
108 b := i / 8
109 //Which bit in byte
110 p := uint(7 - (i - 8*b))
111 (*f).Bytes[b] = (*f).Bytes[b] &^ (1 << p)
112}
113
114// IsFlagSet tests if a flag is set in the ASN1 BitString.
115func IsFlagSet(f *asn1.BitString, i int) bool {
116 //Which byte?
117 b := i / 8
118 //Which bit in byte
119 p := uint(7 - (i - 8*b))
120 if (*f).Bytes[b]&(1<<p) != 0 {
121 return true
122 }
123 return false
124}