]>
Commit | Line | Data |
---|---|---|
d84d3893 JM |
1 | /* |
2 | * BSS list | |
3 | * Copyright (c) 2010, Jouni Malinen <j@w1.fi> | |
4 | * | |
0f3d578e JM |
5 | * This software may be distributed under the terms of the BSD license. |
6 | * See README for more details. | |
d84d3893 JM |
7 | */ |
8 | ||
9 | #include "utils/includes.h" | |
10 | ||
11 | #include "utils/common.h" | |
327f7160 | 12 | #include "common/defs.h" |
2e479416 | 13 | #include "common/ieee802_11_defs.h" |
b50111fb | 14 | #include "common/ieee802_11_common.h" |
53650bca | 15 | #include "crypto/sha1.h" |
d84d3893 JM |
16 | #include "wlantest.h" |
17 | ||
18 | ||
57f7d03f | 19 | struct wlantest_bss * bss_find(struct wlantest *wt, const u8 *bssid) |
d84d3893 JM |
20 | { |
21 | struct wlantest_bss *bss; | |
22 | ||
d84d3893 JM |
23 | dl_list_for_each(bss, &wt->bss, struct wlantest_bss, list) { |
24 | if (os_memcmp(bss->bssid, bssid, ETH_ALEN) == 0) | |
25 | return bss; | |
26 | } | |
27 | ||
57f7d03f JM |
28 | return NULL; |
29 | } | |
30 | ||
31 | ||
32 | struct wlantest_bss * bss_get(struct wlantest *wt, const u8 *bssid) | |
33 | { | |
34 | struct wlantest_bss *bss; | |
35 | ||
36 | if (bssid[0] & 0x01) | |
37 | return NULL; /* Skip group addressed frames */ | |
38 | ||
39 | bss = bss_find(wt, bssid); | |
40 | if (bss) | |
41 | return bss; | |
42 | ||
d84d3893 JM |
43 | bss = os_zalloc(sizeof(*bss)); |
44 | if (bss == NULL) | |
45 | return NULL; | |
422ef7d2 | 46 | dl_list_init(&bss->sta); |
53650bca | 47 | dl_list_init(&bss->pmk); |
b39f5834 | 48 | dl_list_init(&bss->tdls); |
d84d3893 JM |
49 | os_memcpy(bss->bssid, bssid, ETH_ALEN); |
50 | dl_list_add(&wt->bss, &bss->list); | |
51 | wpa_printf(MSG_DEBUG, "Discovered new BSS - " MACSTR, | |
52 | MAC2STR(bss->bssid)); | |
53 | return bss; | |
54 | } | |
55 | ||
56 | ||
d06df64d | 57 | void pmk_deinit(struct wlantest_pmk *pmk) |
53650bca JM |
58 | { |
59 | dl_list_del(&pmk->list); | |
60 | os_free(pmk); | |
61 | } | |
62 | ||
63 | ||
0d2e395d JM |
64 | void tdls_deinit(struct wlantest_tdls *tdls) |
65 | { | |
66 | dl_list_del(&tdls->list); | |
67 | os_free(tdls); | |
68 | } | |
69 | ||
70 | ||
d84d3893 JM |
71 | void bss_deinit(struct wlantest_bss *bss) |
72 | { | |
422ef7d2 | 73 | struct wlantest_sta *sta, *n; |
53650bca | 74 | struct wlantest_pmk *pmk, *np; |
b39f5834 | 75 | struct wlantest_tdls *tdls, *nt; |
422ef7d2 JM |
76 | dl_list_for_each_safe(sta, n, &bss->sta, struct wlantest_sta, list) |
77 | sta_deinit(sta); | |
53650bca JM |
78 | dl_list_for_each_safe(pmk, np, &bss->pmk, struct wlantest_pmk, list) |
79 | pmk_deinit(pmk); | |
b39f5834 | 80 | dl_list_for_each_safe(tdls, nt, &bss->tdls, struct wlantest_tdls, list) |
0d2e395d | 81 | tdls_deinit(tdls); |
d84d3893 JM |
82 | dl_list_del(&bss->list); |
83 | os_free(bss); | |
84 | } | |
b50111fb JM |
85 | |
86 | ||
221519de JM |
87 | int bss_add_pmk_from_passphrase(struct wlantest_bss *bss, |
88 | const char *passphrase) | |
89 | { | |
90 | struct wlantest_pmk *pmk; | |
91 | ||
92 | pmk = os_zalloc(sizeof(*pmk)); | |
93 | if (pmk == NULL) | |
94 | return -1; | |
add11058 | 95 | if (pbkdf2_sha1(passphrase, bss->ssid, bss->ssid_len, 4096, |
6c29d95a | 96 | pmk->pmk, PMK_LEN) < 0) { |
221519de JM |
97 | os_free(pmk); |
98 | return -1; | |
99 | } | |
100 | ||
101 | wpa_printf(MSG_INFO, "Add possible PMK for BSSID " MACSTR | |
102 | " based on passphrase '%s'", | |
103 | MAC2STR(bss->bssid), passphrase); | |
6c29d95a | 104 | wpa_hexdump(MSG_DEBUG, "Possible PMK", pmk->pmk, PMK_LEN); |
221519de JM |
105 | dl_list_add(&bss->pmk, &pmk->list); |
106 | ||
107 | return 0; | |
108 | } | |
109 | ||
110 | ||
53650bca JM |
111 | static void bss_add_pmk(struct wlantest *wt, struct wlantest_bss *bss) |
112 | { | |
113 | struct wlantest_passphrase *p; | |
53650bca JM |
114 | |
115 | dl_list_for_each(p, &wt->passphrase, struct wlantest_passphrase, list) | |
116 | { | |
117 | if (!is_zero_ether_addr(p->bssid) && | |
118 | os_memcmp(p->bssid, bss->bssid, ETH_ALEN) != 0) | |
119 | continue; | |
120 | if (p->ssid_len && | |
121 | (p->ssid_len != bss->ssid_len || | |
122 | os_memcmp(p->ssid, bss->ssid, p->ssid_len) != 0)) | |
123 | continue; | |
124 | ||
221519de | 125 | if (bss_add_pmk_from_passphrase(bss, p->passphrase) < 0) |
53650bca | 126 | break; |
53650bca JM |
127 | } |
128 | } | |
129 | ||
130 | ||
131 | void bss_update(struct wlantest *wt, struct wlantest_bss *bss, | |
132 | struct ieee802_11_elems *elems) | |
b50111fb | 133 | { |
327f7160 JM |
134 | struct wpa_ie_data data; |
135 | int update = 0; | |
136 | ||
2e479416 JM |
137 | if (bss->capab_info != bss->prev_capab_info) |
138 | update = 1; | |
139 | ||
b50111fb JM |
140 | if (elems->ssid == NULL || elems->ssid_len > 32) { |
141 | wpa_printf(MSG_INFO, "Invalid or missing SSID in a Beacon " | |
142 | "frame for " MACSTR, MAC2STR(bss->bssid)); | |
143 | bss->parse_error_reported = 1; | |
144 | return; | |
145 | } | |
146 | ||
53650bca JM |
147 | if (bss->ssid_len != elems->ssid_len || |
148 | os_memcmp(bss->ssid, elems->ssid, bss->ssid_len) != 0) { | |
149 | wpa_printf(MSG_DEBUG, "Store SSID '%s' for BSSID " MACSTR, | |
150 | wpa_ssid_txt(elems->ssid, elems->ssid_len), | |
151 | MAC2STR(bss->bssid)); | |
152 | os_memcpy(bss->ssid, elems->ssid, elems->ssid_len); | |
153 | bss->ssid_len = elems->ssid_len; | |
154 | bss_add_pmk(wt, bss); | |
155 | } | |
156 | ||
f6ff5160 JM |
157 | if (elems->osen == NULL) { |
158 | if (bss->osenie[0]) { | |
159 | add_note(wt, MSG_INFO, "BSS " MACSTR | |
160 | " - OSEN IE removed", MAC2STR(bss->bssid)); | |
161 | bss->rsnie[0] = 0; | |
162 | update = 1; | |
163 | } | |
164 | } else { | |
165 | if (bss->osenie[0] == 0 || | |
166 | os_memcmp(bss->osenie, elems->osen - 2, | |
167 | elems->osen_len + 2) != 0) { | |
168 | wpa_printf(MSG_INFO, "BSS " MACSTR " - OSEN IE " | |
169 | "stored", MAC2STR(bss->bssid)); | |
170 | wpa_hexdump(MSG_DEBUG, "OSEN IE", elems->osen - 2, | |
171 | elems->osen_len + 2); | |
172 | update = 1; | |
173 | } | |
174 | os_memcpy(bss->osenie, elems->osen - 2, | |
175 | elems->osen_len + 2); | |
176 | } | |
b50111fb JM |
177 | |
178 | if (elems->rsn_ie == NULL) { | |
179 | if (bss->rsnie[0]) { | |
e4d99217 JM |
180 | add_note(wt, MSG_INFO, "BSS " MACSTR |
181 | " - RSN IE removed", MAC2STR(bss->bssid)); | |
b50111fb | 182 | bss->rsnie[0] = 0; |
327f7160 | 183 | update = 1; |
b50111fb JM |
184 | } |
185 | } else { | |
186 | if (bss->rsnie[0] == 0 || | |
187 | os_memcmp(bss->rsnie, elems->rsn_ie - 2, | |
188 | elems->rsn_ie_len + 2) != 0) { | |
189 | wpa_printf(MSG_INFO, "BSS " MACSTR " - RSN IE " | |
190 | "stored", MAC2STR(bss->bssid)); | |
191 | wpa_hexdump(MSG_DEBUG, "RSN IE", elems->rsn_ie - 2, | |
192 | elems->rsn_ie_len + 2); | |
327f7160 | 193 | update = 1; |
b50111fb JM |
194 | } |
195 | os_memcpy(bss->rsnie, elems->rsn_ie - 2, | |
196 | elems->rsn_ie_len + 2); | |
197 | } | |
198 | ||
199 | if (elems->wpa_ie == NULL) { | |
200 | if (bss->wpaie[0]) { | |
e4d99217 JM |
201 | add_note(wt, MSG_INFO, "BSS " MACSTR |
202 | " - WPA IE removed", MAC2STR(bss->bssid)); | |
b50111fb | 203 | bss->wpaie[0] = 0; |
327f7160 | 204 | update = 1; |
b50111fb JM |
205 | } |
206 | } else { | |
207 | if (bss->wpaie[0] == 0 || | |
208 | os_memcmp(bss->wpaie, elems->wpa_ie - 2, | |
209 | elems->wpa_ie_len + 2) != 0) { | |
210 | wpa_printf(MSG_INFO, "BSS " MACSTR " - WPA IE " | |
211 | "stored", MAC2STR(bss->bssid)); | |
212 | wpa_hexdump(MSG_DEBUG, "WPA IE", elems->wpa_ie - 2, | |
213 | elems->wpa_ie_len + 2); | |
327f7160 | 214 | update = 1; |
b50111fb JM |
215 | } |
216 | os_memcpy(bss->wpaie, elems->wpa_ie - 2, | |
217 | elems->wpa_ie_len + 2); | |
218 | } | |
327f7160 | 219 | |
3fb62bda JM |
220 | if (elems->mdie) |
221 | os_memcpy(bss->mdid, elems->mdie, 2); | |
222 | ||
327f7160 JM |
223 | if (!update) |
224 | return; | |
225 | ||
878723b9 | 226 | bss->beacon_seen = 1; |
2e479416 | 227 | bss->prev_capab_info = bss->capab_info; |
327f7160 JM |
228 | bss->proto = 0; |
229 | bss->pairwise_cipher = 0; | |
230 | bss->group_cipher = 0; | |
231 | bss->key_mgmt = 0; | |
232 | bss->rsn_capab = 0; | |
233 | bss->mgmt_group_cipher = 0; | |
234 | ||
235 | if (bss->wpaie[0]) { | |
236 | if (wpa_parse_wpa_ie_wpa(bss->wpaie, 2 + bss->wpaie[1], &data) | |
237 | < 0) { | |
e4d99217 JM |
238 | add_note(wt, MSG_INFO, "Failed to parse WPA IE from " |
239 | MACSTR, MAC2STR(bss->bssid)); | |
327f7160 JM |
240 | } else { |
241 | bss->proto |= data.proto; | |
242 | bss->pairwise_cipher |= data.pairwise_cipher; | |
243 | bss->group_cipher |= data.group_cipher; | |
244 | bss->key_mgmt |= data.key_mgmt; | |
245 | bss->rsn_capab = data.capabilities; | |
246 | bss->mgmt_group_cipher |= data.mgmt_group_cipher; | |
247 | } | |
248 | } | |
249 | ||
250 | if (bss->rsnie[0]) { | |
251 | if (wpa_parse_wpa_ie_rsn(bss->rsnie, 2 + bss->rsnie[1], &data) | |
252 | < 0) { | |
e4d99217 JM |
253 | add_note(wt, MSG_INFO, "Failed to parse RSN IE from " |
254 | MACSTR, MAC2STR(bss->bssid)); | |
327f7160 JM |
255 | } else { |
256 | bss->proto |= data.proto; | |
257 | bss->pairwise_cipher |= data.pairwise_cipher; | |
258 | bss->group_cipher |= data.group_cipher; | |
259 | bss->key_mgmt |= data.key_mgmt; | |
260 | bss->rsn_capab = data.capabilities; | |
261 | bss->mgmt_group_cipher |= data.mgmt_group_cipher; | |
262 | } | |
263 | } | |
264 | ||
f6ff5160 JM |
265 | if (bss->osenie[0]) { |
266 | bss->proto |= WPA_PROTO_OSEN; | |
267 | bss->pairwise_cipher |= WPA_CIPHER_CCMP; | |
268 | bss->group_cipher |= WPA_CIPHER_CCMP; | |
269 | bss->key_mgmt |= WPA_KEY_MGMT_OSEN; | |
270 | } | |
271 | ||
327f7160 JM |
272 | if (!(bss->proto & WPA_PROTO_RSN) || |
273 | !(bss->rsn_capab & WPA_CAPABILITY_MFPC)) | |
274 | bss->mgmt_group_cipher = 0; | |
275 | ||
f6ff5160 | 276 | if (!bss->wpaie[0] && !bss->rsnie[0] && !bss->osenie[0] && |
2e479416 JM |
277 | (bss->capab_info & WLAN_CAPABILITY_PRIVACY)) |
278 | bss->group_cipher = WPA_CIPHER_WEP40; | |
279 | ||
327f7160 | 280 | wpa_printf(MSG_INFO, "BSS " MACSTR |
f6ff5160 | 281 | " proto=%s%s%s%s" |
fa6fff18 AKP |
282 | "pairwise=%s%s%s%s%s%s%s" |
283 | "group=%s%s%s%s%s%s%s%s%s" | |
cd3b5cc0 | 284 | "mgmt_group_cipher=%s%s%s%s%s" |
f6ff5160 | 285 | "key_mgmt=%s%s%s%s%s%s%s%s%s" |
dce96218 | 286 | "rsn_capab=%s%s%s%s%s%s", |
327f7160 JM |
287 | MAC2STR(bss->bssid), |
288 | bss->proto == 0 ? "OPEN " : "", | |
289 | bss->proto & WPA_PROTO_WPA ? "WPA " : "", | |
290 | bss->proto & WPA_PROTO_RSN ? "WPA2 " : "", | |
f6ff5160 | 291 | bss->proto & WPA_PROTO_OSEN ? "OSEN " : "", |
327f7160 JM |
292 | bss->pairwise_cipher == 0 ? "N/A " : "", |
293 | bss->pairwise_cipher & WPA_CIPHER_NONE ? "NONE " : "", | |
294 | bss->pairwise_cipher & WPA_CIPHER_TKIP ? "TKIP " : "", | |
295 | bss->pairwise_cipher & WPA_CIPHER_CCMP ? "CCMP " : "", | |
fa6fff18 AKP |
296 | bss->pairwise_cipher & WPA_CIPHER_CCMP_256 ? "CCMP-256 " : |
297 | "", | |
298 | bss->pairwise_cipher & WPA_CIPHER_GCMP ? "GCMP " : "", | |
299 | bss->pairwise_cipher & WPA_CIPHER_GCMP_256 ? "GCMP-256 " : | |
300 | "", | |
327f7160 JM |
301 | bss->group_cipher == 0 ? "N/A " : "", |
302 | bss->group_cipher & WPA_CIPHER_NONE ? "NONE " : "", | |
303 | bss->group_cipher & WPA_CIPHER_WEP40 ? "WEP40 " : "", | |
304 | bss->group_cipher & WPA_CIPHER_WEP104 ? "WEP104 " : "", | |
305 | bss->group_cipher & WPA_CIPHER_TKIP ? "TKIP " : "", | |
306 | bss->group_cipher & WPA_CIPHER_CCMP ? "CCMP " : "", | |
fa6fff18 AKP |
307 | bss->group_cipher & WPA_CIPHER_CCMP_256 ? "CCMP-256 " : "", |
308 | bss->group_cipher & WPA_CIPHER_GCMP ? "GCMP " : "", | |
309 | bss->group_cipher & WPA_CIPHER_GCMP_256 ? "GCMP-256 " : "", | |
cd3b5cc0 JM |
310 | bss->mgmt_group_cipher == 0 ? "N/A " : "", |
311 | bss->mgmt_group_cipher & WPA_CIPHER_AES_128_CMAC ? | |
312 | "BIP " : "", | |
313 | bss->mgmt_group_cipher & WPA_CIPHER_BIP_GMAC_128 ? | |
314 | "BIP-GMAC-128 " : "", | |
315 | bss->mgmt_group_cipher & WPA_CIPHER_BIP_GMAC_256 ? | |
316 | "BIP-GMAC-256 " : "", | |
317 | bss->mgmt_group_cipher & WPA_CIPHER_BIP_CMAC_256 ? | |
318 | "BIP-CMAC-256 " : "", | |
327f7160 JM |
319 | bss->key_mgmt == 0 ? "N/A " : "", |
320 | bss->key_mgmt & WPA_KEY_MGMT_IEEE8021X ? "EAP " : "", | |
321 | bss->key_mgmt & WPA_KEY_MGMT_PSK ? "PSK " : "", | |
322 | bss->key_mgmt & WPA_KEY_MGMT_WPA_NONE ? "WPA-NONE " : "", | |
323 | bss->key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X ? "FT-EAP " : "", | |
324 | bss->key_mgmt & WPA_KEY_MGMT_FT_PSK ? "FT-PSK " : "", | |
325 | bss->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256 ? | |
326 | "EAP-SHA256 " : "", | |
327 | bss->key_mgmt & WPA_KEY_MGMT_PSK_SHA256 ? | |
328 | "PSK-SHA256 " : "", | |
f6ff5160 | 329 | bss->key_mgmt & WPA_KEY_MGMT_OSEN ? "OSEN " : "", |
327f7160 JM |
330 | bss->rsn_capab & WPA_CAPABILITY_PREAUTH ? "PREAUTH " : "", |
331 | bss->rsn_capab & WPA_CAPABILITY_NO_PAIRWISE ? | |
332 | "NO_PAIRWISE " : "", | |
333 | bss->rsn_capab & WPA_CAPABILITY_MFPR ? "MFPR " : "", | |
334 | bss->rsn_capab & WPA_CAPABILITY_MFPC ? "MFPC " : "", | |
335 | bss->rsn_capab & WPA_CAPABILITY_PEERKEY_ENABLED ? | |
dce96218 MV |
336 | "PEERKEY " : "", |
337 | bss->rsn_capab & WPA_CAPABILITY_OCVC ? "OCVC " : ""); | |
b50111fb | 338 | } |
d356bd63 JM |
339 | |
340 | ||
341 | void bss_flush(struct wlantest *wt) | |
342 | { | |
343 | struct wlantest_bss *bss, *n; | |
344 | dl_list_for_each_safe(bss, n, &wt->bss, struct wlantest_bss, list) | |
345 | bss_deinit(bss); | |
346 | } |