]>
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, |
221519de JM |
96 | pmk->pmk, sizeof(pmk->pmk)) < 0) { |
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); | |
104 | wpa_hexdump(MSG_DEBUG, "Possible PMK", pmk->pmk, sizeof(pmk->pmk)); | |
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 | ||
b50111fb JM |
157 | |
158 | if (elems->rsn_ie == NULL) { | |
159 | if (bss->rsnie[0]) { | |
160 | wpa_printf(MSG_INFO, "BSS " MACSTR " - RSN IE removed", | |
161 | MAC2STR(bss->bssid)); | |
162 | bss->rsnie[0] = 0; | |
327f7160 | 163 | update = 1; |
b50111fb JM |
164 | } |
165 | } else { | |
166 | if (bss->rsnie[0] == 0 || | |
167 | os_memcmp(bss->rsnie, elems->rsn_ie - 2, | |
168 | elems->rsn_ie_len + 2) != 0) { | |
169 | wpa_printf(MSG_INFO, "BSS " MACSTR " - RSN IE " | |
170 | "stored", MAC2STR(bss->bssid)); | |
171 | wpa_hexdump(MSG_DEBUG, "RSN IE", elems->rsn_ie - 2, | |
172 | elems->rsn_ie_len + 2); | |
327f7160 | 173 | update = 1; |
b50111fb JM |
174 | } |
175 | os_memcpy(bss->rsnie, elems->rsn_ie - 2, | |
176 | elems->rsn_ie_len + 2); | |
177 | } | |
178 | ||
179 | if (elems->wpa_ie == NULL) { | |
180 | if (bss->wpaie[0]) { | |
181 | wpa_printf(MSG_INFO, "BSS " MACSTR " - WPA IE removed", | |
182 | MAC2STR(bss->bssid)); | |
183 | bss->wpaie[0] = 0; | |
327f7160 | 184 | update = 1; |
b50111fb JM |
185 | } |
186 | } else { | |
187 | if (bss->wpaie[0] == 0 || | |
188 | os_memcmp(bss->wpaie, elems->wpa_ie - 2, | |
189 | elems->wpa_ie_len + 2) != 0) { | |
190 | wpa_printf(MSG_INFO, "BSS " MACSTR " - WPA IE " | |
191 | "stored", MAC2STR(bss->bssid)); | |
192 | wpa_hexdump(MSG_DEBUG, "WPA IE", elems->wpa_ie - 2, | |
193 | elems->wpa_ie_len + 2); | |
327f7160 | 194 | update = 1; |
b50111fb JM |
195 | } |
196 | os_memcpy(bss->wpaie, elems->wpa_ie - 2, | |
197 | elems->wpa_ie_len + 2); | |
198 | } | |
327f7160 JM |
199 | |
200 | if (!update) | |
201 | return; | |
202 | ||
2e479416 | 203 | bss->prev_capab_info = bss->capab_info; |
327f7160 JM |
204 | bss->proto = 0; |
205 | bss->pairwise_cipher = 0; | |
206 | bss->group_cipher = 0; | |
207 | bss->key_mgmt = 0; | |
208 | bss->rsn_capab = 0; | |
209 | bss->mgmt_group_cipher = 0; | |
210 | ||
211 | if (bss->wpaie[0]) { | |
212 | if (wpa_parse_wpa_ie_wpa(bss->wpaie, 2 + bss->wpaie[1], &data) | |
213 | < 0) { | |
214 | wpa_printf(MSG_INFO, "Failed to parse WPA IE from " | |
215 | MACSTR, MAC2STR(bss->bssid)); | |
216 | } else { | |
217 | bss->proto |= data.proto; | |
218 | bss->pairwise_cipher |= data.pairwise_cipher; | |
219 | bss->group_cipher |= data.group_cipher; | |
220 | bss->key_mgmt |= data.key_mgmt; | |
221 | bss->rsn_capab = data.capabilities; | |
222 | bss->mgmt_group_cipher |= data.mgmt_group_cipher; | |
223 | } | |
224 | } | |
225 | ||
226 | if (bss->rsnie[0]) { | |
227 | if (wpa_parse_wpa_ie_rsn(bss->rsnie, 2 + bss->rsnie[1], &data) | |
228 | < 0) { | |
229 | wpa_printf(MSG_INFO, "Failed to parse RSN IE from " | |
230 | MACSTR, MAC2STR(bss->bssid)); | |
231 | } else { | |
232 | bss->proto |= data.proto; | |
233 | bss->pairwise_cipher |= data.pairwise_cipher; | |
234 | bss->group_cipher |= data.group_cipher; | |
235 | bss->key_mgmt |= data.key_mgmt; | |
236 | bss->rsn_capab = data.capabilities; | |
237 | bss->mgmt_group_cipher |= data.mgmt_group_cipher; | |
238 | } | |
239 | } | |
240 | ||
241 | if (!(bss->proto & WPA_PROTO_RSN) || | |
242 | !(bss->rsn_capab & WPA_CAPABILITY_MFPC)) | |
243 | bss->mgmt_group_cipher = 0; | |
244 | ||
2e479416 JM |
245 | if (!bss->wpaie[0] && !bss->rsnie[0] && |
246 | (bss->capab_info & WLAN_CAPABILITY_PRIVACY)) | |
247 | bss->group_cipher = WPA_CIPHER_WEP40; | |
248 | ||
327f7160 JM |
249 | wpa_printf(MSG_INFO, "BSS " MACSTR |
250 | " proto=%s%s%s" | |
251 | "pairwise=%s%s%s%s" | |
252 | "group=%s%s%s%s%s%s" | |
253 | "mgmt_group_cipher=%s" | |
254 | "key_mgmt=%s%s%s%s%s%s%s%s" | |
255 | "rsn_capab=%s%s%s%s%s", | |
256 | MAC2STR(bss->bssid), | |
257 | bss->proto == 0 ? "OPEN " : "", | |
258 | bss->proto & WPA_PROTO_WPA ? "WPA " : "", | |
259 | bss->proto & WPA_PROTO_RSN ? "WPA2 " : "", | |
260 | bss->pairwise_cipher == 0 ? "N/A " : "", | |
261 | bss->pairwise_cipher & WPA_CIPHER_NONE ? "NONE " : "", | |
262 | bss->pairwise_cipher & WPA_CIPHER_TKIP ? "TKIP " : "", | |
263 | bss->pairwise_cipher & WPA_CIPHER_CCMP ? "CCMP " : "", | |
264 | bss->group_cipher == 0 ? "N/A " : "", | |
265 | bss->group_cipher & WPA_CIPHER_NONE ? "NONE " : "", | |
266 | bss->group_cipher & WPA_CIPHER_WEP40 ? "WEP40 " : "", | |
267 | bss->group_cipher & WPA_CIPHER_WEP104 ? "WEP104 " : "", | |
268 | bss->group_cipher & WPA_CIPHER_TKIP ? "TKIP " : "", | |
269 | bss->group_cipher & WPA_CIPHER_CCMP ? "CCMP " : "", | |
270 | bss->mgmt_group_cipher & WPA_CIPHER_AES_128_CMAC ? "BIP " : | |
271 | "N/A ", | |
272 | bss->key_mgmt == 0 ? "N/A " : "", | |
273 | bss->key_mgmt & WPA_KEY_MGMT_IEEE8021X ? "EAP " : "", | |
274 | bss->key_mgmt & WPA_KEY_MGMT_PSK ? "PSK " : "", | |
275 | bss->key_mgmt & WPA_KEY_MGMT_WPA_NONE ? "WPA-NONE " : "", | |
276 | bss->key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X ? "FT-EAP " : "", | |
277 | bss->key_mgmt & WPA_KEY_MGMT_FT_PSK ? "FT-PSK " : "", | |
278 | bss->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256 ? | |
279 | "EAP-SHA256 " : "", | |
280 | bss->key_mgmt & WPA_KEY_MGMT_PSK_SHA256 ? | |
281 | "PSK-SHA256 " : "", | |
282 | bss->rsn_capab & WPA_CAPABILITY_PREAUTH ? "PREAUTH " : "", | |
283 | bss->rsn_capab & WPA_CAPABILITY_NO_PAIRWISE ? | |
284 | "NO_PAIRWISE " : "", | |
285 | bss->rsn_capab & WPA_CAPABILITY_MFPR ? "MFPR " : "", | |
286 | bss->rsn_capab & WPA_CAPABILITY_MFPC ? "MFPC " : "", | |
287 | bss->rsn_capab & WPA_CAPABILITY_PEERKEY_ENABLED ? | |
288 | "PEERKEY " : ""); | |
b50111fb | 289 | } |
d356bd63 JM |
290 | |
291 | ||
292 | void bss_flush(struct wlantest *wt) | |
293 | { | |
294 | struct wlantest_bss *bss, *n; | |
295 | dl_list_for_each_safe(bss, n, &wt->bss, struct wlantest_bss, list) | |
296 | bss_deinit(bss); | |
297 | } |