/
dot11_types.go
221 lines (193 loc) · 4.82 KB
/
dot11_types.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
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
package packets
import (
"encoding/binary"
"fmt"
)
type Dot11CipherType uint8
const (
Dot11CipherWep Dot11CipherType = 1
Dot11CipherTkip Dot11CipherType = 2
Dot11CipherWrap Dot11CipherType = 3
Dot11CipherCcmp Dot11CipherType = 4
Dot11CipherWep104 Dot11CipherType = 5
)
func (a Dot11CipherType) String() string {
switch a {
case Dot11CipherWep:
return "WEP"
case Dot11CipherTkip:
return "TKIP"
case Dot11CipherWrap:
return "WRAP"
case Dot11CipherCcmp:
return "CCMP"
case Dot11CipherWep104:
return "WEP104"
default:
return "UNK"
}
}
type Dot11AuthType uint8
const (
Dot11AuthMgt Dot11AuthType = 1
Dot11AuthPsk Dot11AuthType = 2
)
func (a Dot11AuthType) String() string {
switch a {
case Dot11AuthMgt:
return "MGT"
case Dot11AuthPsk:
return "PSK"
default:
return "UNK"
}
}
type CipherSuite struct {
OUI []byte // 3 bytes
Type Dot11CipherType
}
type AuthSuite struct {
OUI []byte // 3 bytes
Type Dot11AuthType
}
type CipherSuiteSelector struct {
Count uint16
Suites []CipherSuite
}
type AuthSuiteSelector struct {
Count uint16
Suites []AuthSuite
}
type RSNInfo struct {
Version uint16
Group CipherSuite
Pairwise CipherSuiteSelector
AuthKey AuthSuiteSelector
}
type VendorInfo struct {
WPAVersion uint16
Multicast CipherSuite
Unicast CipherSuiteSelector
AuthKey AuthSuiteSelector
}
func canParse(what string, buf []byte, need int) error {
available := len(buf)
if need > available {
return fmt.Errorf("Malformed 802.11 packet, could not parse %s: needed %d bytes but only %d are available.", what, need, available)
}
return nil
}
func parsePairwiseSuite(buf []byte) (suite CipherSuite, err error) {
if err = canParse("RSN.Pairwise.Suite", buf, 4); err == nil {
suite.OUI = buf[0:3]
suite.Type = Dot11CipherType(buf[3])
}
return
}
func parseAuthkeySuite(buf []byte) (suite AuthSuite, err error) {
if err = canParse("RSN.AuthKey.Suite", buf, 4); err == nil {
suite.OUI = buf[0:3]
suite.Type = Dot11AuthType(buf[3])
}
return
}
func Dot11InformationElementVendorInfoDecode(buf []byte) (v VendorInfo, err error) {
if err = canParse("Vendor", buf, 8); err == nil {
v.WPAVersion = binary.LittleEndian.Uint16(buf[0:2])
v.Multicast.OUI = buf[2:5]
v.Multicast.Type = Dot11CipherType(buf[5])
v.Unicast.Count = binary.LittleEndian.Uint16(buf[6:8])
buf = buf[8:]
} else {
v.Unicast.Count = 0
return
}
// check what we're left with
if err = canParse("Vendor.Unicast.Suites", buf, int(v.Unicast.Count)*4); err == nil {
for i := uint16(0); i < v.Unicast.Count; i++ {
if suite, err := parsePairwiseSuite(buf); err == nil {
v.Unicast.Suites = append(v.Unicast.Suites, suite)
buf = buf[4:]
} else {
return v, err
}
}
} else {
v.Unicast.Count = 0
return
}
if err = canParse("Vendor.AuthKey.Count", buf, 2); err == nil {
v.AuthKey.Count = binary.LittleEndian.Uint16(buf[0:2])
buf = buf[2:]
} else {
v.AuthKey.Count = 0
return
}
// just like before, check if we have enough data
if err = canParse("Vendor.AuthKey.Suites", buf, int(v.AuthKey.Count)*4); err == nil {
for i := uint16(0); i < v.AuthKey.Count; i++ {
if suite, err := parseAuthkeySuite(buf); err == nil {
v.AuthKey.Suites = append(v.AuthKey.Suites, suite)
buf = buf[4:]
} else {
return v, err
}
}
} else {
v.AuthKey.Count = 0
}
return
}
func Dot11InformationElementRSNInfoDecode(buf []byte) (rsn RSNInfo, err error) {
if err = canParse("RSN", buf, 8); err == nil {
rsn.Version = binary.LittleEndian.Uint16(buf[0:2])
rsn.Group.OUI = buf[2:5]
rsn.Group.Type = Dot11CipherType(buf[5])
rsn.Pairwise.Count = binary.LittleEndian.Uint16(buf[6:8])
buf = buf[8:]
} else {
rsn.Pairwise.Count = 0
return
}
// check what we're left with
if err = canParse("RSN.Pairwise.Suites", buf, int(rsn.Pairwise.Count)*4); err == nil {
for i := uint16(0); i < rsn.Pairwise.Count; i++ {
if suite, err := parsePairwiseSuite(buf); err == nil {
rsn.Pairwise.Suites = append(rsn.Pairwise.Suites, suite)
buf = buf[4:]
} else {
return rsn, err
}
}
} else {
rsn.Pairwise.Count = 0
return
}
if err = canParse("RSN.AuthKey.Count", buf, 2); err == nil {
rsn.AuthKey.Count = binary.LittleEndian.Uint16(buf[0:2])
buf = buf[2:]
} else {
rsn.AuthKey.Count = 0
return
}
// just like before, check if we have enough data
if err = canParse("RSN.AuthKey.Suites", buf, int(rsn.AuthKey.Count)*4); err == nil {
for i := uint16(0); i < rsn.AuthKey.Count; i++ {
if suite, err := parseAuthkeySuite(buf); err == nil {
rsn.AuthKey.Suites = append(rsn.AuthKey.Suites, suite)
buf = buf[4:]
} else {
return rsn, err
}
}
} else {
rsn.AuthKey.Count = 0
}
return
}
func Dot11InformationElementIDDSSetDecode(buf []byte) (channel int, err error) {
if err = canParse("DSSet.channel", buf, 1); err == nil {
channel = int(buf[0])
}
return
}