1 /*
2 * Copyright (c) 2009, Atheros Communications, Inc.
3 * Copyright (c) 2011-2013, Qualcomm Atheros, Inc.
4 *
5 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
7 */
8
9 #include "includes.h"
10 #include <sys/stat.h>
11
12 #include "common.h"
13 #include "eloop.h"
14 #include "common/ieee802_11_common.h"
15 #include "common/ieee802_11_defs.h"
16 #include "common/gas.h"
17 #include "common/wpa_ctrl.h"
18 #include "rsn_supp/wpa.h"
19 #include "wpa_supplicant_i.h"
20 #include "driver_i.h"
21 #include "config.h"
22 #include "scan.h"
23 #include "notify.h"
24 #include "bss.h"
25 #include "bssid_ignore.h"
26 #include "gas_query.h"
27 #include "interworking.h"
28 #include "hs20_supplicant.h"
29 #include "base64.h"
30 #include "notify.h"
31
32
33 #define OSU_MAX_ITEMS 10
34
35 struct osu_lang_string {
36 char lang[4];
37 char text[253];
38 };
39
40 struct osu_icon {
41 u16 width;
42 u16 height;
43 char lang[4];
44 char icon_type[256];
45 char filename[256];
46 unsigned int id;
47 unsigned int failed:1;
48 };
49
50 struct osu_provider {
51 u8 bssid[ETH_ALEN];
52 u8 osu_ssid[SSID_MAX_LEN];
53 u8 osu_ssid_len;
54 u8 osu_ssid2[SSID_MAX_LEN];
55 u8 osu_ssid2_len;
56 char server_uri[256];
57 u32 osu_methods; /* bit 0 = OMA-DM, bit 1 = SOAP-XML SPP */
58 char osu_nai[256];
59 char osu_nai2[256];
60 struct osu_lang_string friendly_name[OSU_MAX_ITEMS];
61 size_t friendly_name_count;
62 struct osu_lang_string serv_desc[OSU_MAX_ITEMS];
63 size_t serv_desc_count;
64 struct osu_icon icon[OSU_MAX_ITEMS];
65 size_t icon_count;
66 };
67
68
hs20_configure_frame_filters(struct wpa_supplicant * wpa_s)69 void hs20_configure_frame_filters(struct wpa_supplicant *wpa_s)
70 {
71 struct wpa_bss *bss = wpa_s->current_bss;
72 const u8 *ie;
73 const u8 *ext_capa;
74 u32 filter = 0;
75
76 if (!bss || !is_hs20_network(wpa_s, wpa_s->current_ssid, bss)
77 #ifndef ANDROID
78 // HS 2.0 Configuration is not used in AOSP
79 || !is_hs20_config(wpa_s)
80 #endif
81 ) {
82 /* Not configuring frame filtering - BSS is not a Hotspot 2.0
83 * network */
84 return;
85 }
86
87 ie = wpa_bss_get_vendor_ie(bss, HS20_IE_VENDOR_TYPE);
88
89 /* Check if DGAF disabled bit is zero (5th byte in the IE) */
90 if (!ie || ie[1] < 5)
91 wpa_printf(MSG_DEBUG,
92 "Not configuring frame filtering - Can't extract DGAF bit");
93 else if (!(ie[6] & HS20_DGAF_DISABLED))
94 filter |= WPA_DATA_FRAME_FILTER_FLAG_GTK;
95
96 ext_capa = wpa_bss_get_ie(bss, WLAN_EID_EXT_CAPAB);
97 if (!ext_capa || ext_capa[1] < 2) {
98 wpa_printf(MSG_DEBUG,
99 "Not configuring frame filtering - Can't extract Proxy ARP bit");
100 return;
101 }
102
103 if (wpa_bss_ext_capab(bss, WLAN_EXT_CAPAB_PROXY_ARP))
104 filter |= WPA_DATA_FRAME_FILTER_FLAG_ARP |
105 WPA_DATA_FRAME_FILTER_FLAG_NA;
106
107 wpa_drv_configure_frame_filters(wpa_s, filter);
108 }
109
110
wpas_hs20_add_indication(struct wpabuf * buf,int pps_mo_id,int ap_release)111 void wpas_hs20_add_indication(struct wpabuf *buf, int pps_mo_id, int ap_release)
112 {
113 int release;
114 u8 conf;
115
116 release = (HS20_VERSION >> 4) + 1;
117 if (ap_release > 0 && release > ap_release)
118 release = ap_release;
119 if (release < 2)
120 pps_mo_id = -1;
121
122 wpabuf_put_u8(buf, WLAN_EID_VENDOR_SPECIFIC);
123 wpabuf_put_u8(buf, pps_mo_id >= 0 ? 7 : 5);
124 wpabuf_put_be24(buf, OUI_WFA);
125 wpabuf_put_u8(buf, HS20_INDICATION_OUI_TYPE);
126 conf = (release - 1) << 4;
127 if (pps_mo_id >= 0)
128 conf |= HS20_PPS_MO_ID_PRESENT;
129 wpabuf_put_u8(buf, conf);
130 if (pps_mo_id >= 0)
131 wpabuf_put_le16(buf, pps_mo_id);
132 }
133
134
wpas_hs20_add_roam_cons_sel(struct wpabuf * buf,const struct wpa_ssid * ssid)135 void wpas_hs20_add_roam_cons_sel(struct wpabuf *buf,
136 const struct wpa_ssid *ssid)
137 {
138 if (!ssid->roaming_consortium_selection ||
139 !ssid->roaming_consortium_selection_len)
140 return;
141
142 wpabuf_put_u8(buf, WLAN_EID_VENDOR_SPECIFIC);
143 wpabuf_put_u8(buf, 4 + ssid->roaming_consortium_selection_len);
144 wpabuf_put_be24(buf, OUI_WFA);
145 wpabuf_put_u8(buf, HS20_ROAMING_CONS_SEL_OUI_TYPE);
146 wpabuf_put_data(buf, ssid->roaming_consortium_selection,
147 ssid->roaming_consortium_selection_len);
148 }
149
150
get_hs20_version(struct wpa_bss * bss)151 int get_hs20_version(struct wpa_bss *bss)
152 {
153 const u8 *ie;
154
155 if (!bss)
156 return 0;
157
158 ie = wpa_bss_get_vendor_ie(bss, HS20_IE_VENDOR_TYPE);
159 if (!ie || ie[1] < 5)
160 return 0;
161
162 return ((ie[6] >> 4) & 0x0f) + 1;
163 }
164
is_hs20_config(struct wpa_supplicant * wpa_s)165 int is_hs20_config(struct wpa_supplicant *wpa_s)
166 {
167 return wpa_s->conf->hs20;
168 }
169
is_hs20_network(struct wpa_supplicant * wpa_s,struct wpa_ssid * ssid,struct wpa_bss * bss)170 int is_hs20_network(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
171 struct wpa_bss *bss)
172 {
173 if (!ssid)
174 return 0;
175
176 if (ssid->parent_cred)
177 return 1;
178
179 if (bss && !wpa_bss_get_vendor_ie(bss, HS20_IE_VENDOR_TYPE))
180 return 0;
181
182 /*
183 * This may catch some non-Hotspot 2.0 cases, but it is safer to do that
184 * than cause Hotspot 2.0 connections without indication element getting
185 * added. Non-Hotspot 2.0 APs should ignore the unknown vendor element.
186 */
187
188 if (!(ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X))
189 return 0;
190 if (!(ssid->pairwise_cipher & WPA_CIPHER_CCMP))
191 return 0;
192 if (ssid->proto != WPA_PROTO_RSN)
193 return 0;
194
195 return 1;
196 }
197
198
hs20_get_pps_mo_id(struct wpa_supplicant * wpa_s,struct wpa_ssid * ssid)199 int hs20_get_pps_mo_id(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
200 {
201 struct wpa_cred *cred;
202
203 if (ssid == NULL)
204 return 0;
205
206 if (ssid->update_identifier)
207 return ssid->update_identifier;
208
209 if (ssid->parent_cred == NULL)
210 return 0;
211
212 for (cred = wpa_s->conf->cred; cred; cred = cred->next) {
213 if (ssid->parent_cred == cred)
214 return cred->update_identifier;
215 }
216
217 return 0;
218 }
219
220
hs20_put_anqp_req(u32 stypes,const u8 * payload,size_t payload_len,struct wpabuf * buf)221 void hs20_put_anqp_req(u32 stypes, const u8 *payload, size_t payload_len,
222 struct wpabuf *buf)
223 {
224 u8 *len_pos;
225
226 if (buf == NULL)
227 return;
228
229 len_pos = gas_anqp_add_element(buf, ANQP_VENDOR_SPECIFIC);
230 wpabuf_put_be24(buf, OUI_WFA);
231 wpabuf_put_u8(buf, HS20_ANQP_OUI_TYPE);
232 if (stypes == BIT(HS20_STYPE_NAI_HOME_REALM_QUERY)) {
233 wpabuf_put_u8(buf, HS20_STYPE_NAI_HOME_REALM_QUERY);
234 wpabuf_put_u8(buf, 0); /* Reserved */
235 if (payload)
236 wpabuf_put_data(buf, payload, payload_len);
237 } else if (stypes == BIT(HS20_STYPE_ICON_REQUEST)) {
238 wpabuf_put_u8(buf, HS20_STYPE_ICON_REQUEST);
239 wpabuf_put_u8(buf, 0); /* Reserved */
240 if (payload)
241 wpabuf_put_data(buf, payload, payload_len);
242 } else {
243 u8 i;
244 wpabuf_put_u8(buf, HS20_STYPE_QUERY_LIST);
245 wpabuf_put_u8(buf, 0); /* Reserved */
246 for (i = 0; i < 32; i++) {
247 if (stypes & BIT(i))
248 wpabuf_put_u8(buf, i);
249 }
250 }
251 gas_anqp_set_element_len(buf, len_pos);
252
253 gas_anqp_set_len(buf);
254 }
255
256
hs20_build_anqp_req(u32 stypes,const u8 * payload,size_t payload_len)257 static struct wpabuf * hs20_build_anqp_req(u32 stypes, const u8 *payload,
258 size_t payload_len)
259 {
260 struct wpabuf *buf;
261
262 buf = gas_anqp_build_initial_req(0, 100 + payload_len);
263 if (buf == NULL)
264 return NULL;
265
266 hs20_put_anqp_req(stypes, payload, payload_len, buf);
267
268 return buf;
269 }
270
271
hs20_anqp_send_req(struct wpa_supplicant * wpa_s,const u8 * dst,u32 stypes,const u8 * payload,size_t payload_len,int inmem)272 int hs20_anqp_send_req(struct wpa_supplicant *wpa_s, const u8 *dst, u32 stypes,
273 const u8 *payload, size_t payload_len, int inmem)
274 {
275 struct wpabuf *buf;
276 int ret = 0;
277 int freq;
278 struct wpa_bss *bss;
279 int res;
280 struct icon_entry *icon_entry;
281
282 bss = wpa_bss_get_bssid(wpa_s, dst);
283 if (!bss) {
284 wpa_printf(MSG_WARNING,
285 "ANQP: Cannot send query to unknown BSS "
286 MACSTR, MAC2STR(dst));
287 return -1;
288 }
289
290 wpa_bss_anqp_unshare_alloc(bss);
291 freq = bss->freq;
292
293 wpa_printf(MSG_DEBUG, "HS20: ANQP Query Request to " MACSTR " for "
294 "subtypes 0x%x", MAC2STR(dst), stypes);
295
296 buf = hs20_build_anqp_req(stypes, payload, payload_len);
297 if (buf == NULL)
298 return -1;
299
300 res = gas_query_req(wpa_s->gas, dst, freq, 0, 0, buf, anqp_resp_cb,
301 wpa_s);
302 if (res < 0) {
303 wpa_printf(MSG_DEBUG, "ANQP: Failed to send Query Request");
304 wpabuf_free(buf);
305 return -1;
306 } else
307 wpa_printf(MSG_DEBUG, "ANQP: Query started with dialog token "
308 "%u", res);
309
310 if (inmem) {
311 icon_entry = os_zalloc(sizeof(struct icon_entry));
312 if (!icon_entry)
313 return -1;
314 os_memcpy(icon_entry->bssid, dst, ETH_ALEN);
315 icon_entry->file_name = os_malloc(payload_len + 1);
316 if (!icon_entry->file_name) {
317 os_free(icon_entry);
318 return -1;
319 }
320 os_memcpy(icon_entry->file_name, payload, payload_len);
321 icon_entry->file_name[payload_len] = '\0';
322 icon_entry->dialog_token = res;
323
324 dl_list_add(&wpa_s->icon_head, &icon_entry->list);
325 }
326
327 return ret;
328 }
329
330
hs20_find_icon(struct wpa_supplicant * wpa_s,const u8 * bssid,const char * file_name)331 static struct icon_entry * hs20_find_icon(struct wpa_supplicant *wpa_s,
332 const u8 *bssid,
333 const char *file_name)
334 {
335 struct icon_entry *icon;
336
337 dl_list_for_each(icon, &wpa_s->icon_head, struct icon_entry, list) {
338 if (ether_addr_equal(icon->bssid, bssid) &&
339 os_strcmp(icon->file_name, file_name) == 0 && icon->image)
340 return icon;
341 }
342
343 return NULL;
344 }
345
346
hs20_get_icon(struct wpa_supplicant * wpa_s,const u8 * bssid,const char * file_name,size_t offset,size_t size,char * reply,size_t buf_len)347 int hs20_get_icon(struct wpa_supplicant *wpa_s, const u8 *bssid,
348 const char *file_name, size_t offset, size_t size,
349 char *reply, size_t buf_len)
350 {
351 struct icon_entry *icon;
352 size_t out_size;
353 char *b64;
354 size_t b64_size;
355 int reply_size;
356
357 wpa_printf(MSG_DEBUG, "HS20: Get icon " MACSTR " %s @ %u +%u (%u)",
358 MAC2STR(bssid), file_name, (unsigned int) offset,
359 (unsigned int) size, (unsigned int) buf_len);
360
361 icon = hs20_find_icon(wpa_s, bssid, file_name);
362 if (!icon || !icon->image || offset >= icon->image_len)
363 return -1;
364 if (size > icon->image_len - offset)
365 size = icon->image_len - offset;
366 out_size = buf_len - 3 /* max base64 padding */;
367 if (size * 4 > out_size * 3)
368 size = out_size * 3 / 4;
369 if (size == 0)
370 return -1;
371
372 b64 = base64_encode(&icon->image[offset], size, &b64_size);
373 if (b64 && buf_len >= b64_size) {
374 os_memcpy(reply, b64, b64_size);
375 reply_size = b64_size;
376 } else {
377 reply_size = -1;
378 }
379 os_free(b64);
380 return reply_size;
381 }
382
383
hs20_free_icon_entry(struct icon_entry * icon)384 static void hs20_free_icon_entry(struct icon_entry *icon)
385 {
386 wpa_printf(MSG_DEBUG, "HS20: Free stored icon from " MACSTR
387 " dialog_token=%u file_name=%s image_len=%u",
388 MAC2STR(icon->bssid), icon->dialog_token,
389 icon->file_name ? icon->file_name : "N/A",
390 (unsigned int) icon->image_len);
391 os_free(icon->file_name);
392 os_free(icon->image);
393 os_free(icon);
394 }
395
396
hs20_del_icon(struct wpa_supplicant * wpa_s,const u8 * bssid,const char * file_name)397 int hs20_del_icon(struct wpa_supplicant *wpa_s, const u8 *bssid,
398 const char *file_name)
399 {
400 struct icon_entry *icon, *tmp;
401 int count = 0;
402
403 if (!bssid)
404 wpa_printf(MSG_DEBUG, "HS20: Delete all stored icons");
405 else if (!file_name)
406 wpa_printf(MSG_DEBUG, "HS20: Delete all stored icons for "
407 MACSTR, MAC2STR(bssid));
408 else
409 wpa_printf(MSG_DEBUG, "HS20: Delete stored icons for "
410 MACSTR " file name %s", MAC2STR(bssid), file_name);
411
412 dl_list_for_each_safe(icon, tmp, &wpa_s->icon_head, struct icon_entry,
413 list) {
414 if ((!bssid || ether_addr_equal(icon->bssid, bssid)) &&
415 (!file_name ||
416 os_strcmp(icon->file_name, file_name) == 0)) {
417 dl_list_del(&icon->list);
418 hs20_free_icon_entry(icon);
419 count++;
420 }
421 }
422 return count == 0 ? -1 : 0;
423 }
424
425
hs20_set_osu_access_permission(const char * osu_dir,const char * fname)426 static void hs20_set_osu_access_permission(const char *osu_dir,
427 const char *fname)
428 {
429 struct stat statbuf;
430
431 /* Get OSU directory information */
432 if (stat(osu_dir, &statbuf) < 0) {
433 wpa_printf(MSG_WARNING, "Cannot stat the OSU directory %s",
434 osu_dir);
435 return;
436 }
437
438 if (chmod(fname, statbuf.st_mode) < 0) {
439 wpa_printf(MSG_WARNING,
440 "Cannot change the permissions for %s", fname);
441 return;
442 }
443
444 if (lchown(fname, statbuf.st_uid, statbuf.st_gid) < 0) {
445 wpa_printf(MSG_WARNING, "Cannot change the ownership for %s",
446 fname);
447 }
448 }
449
450
hs20_remove_duplicate_icons(struct wpa_supplicant * wpa_s,struct icon_entry * new_icon)451 static void hs20_remove_duplicate_icons(struct wpa_supplicant *wpa_s,
452 struct icon_entry *new_icon)
453 {
454 struct icon_entry *icon, *tmp;
455
456 dl_list_for_each_safe(icon, tmp, &wpa_s->icon_head, struct icon_entry,
457 list) {
458 if (icon == new_icon)
459 continue;
460 if (ether_addr_equal(icon->bssid, new_icon->bssid) &&
461 os_strcmp(icon->file_name, new_icon->file_name) == 0) {
462 dl_list_del(&icon->list);
463 hs20_free_icon_entry(icon);
464 }
465 }
466 }
467
468
hs20_process_icon_binary_file(struct wpa_supplicant * wpa_s,const u8 * sa,const u8 * pos,size_t slen,u8 dialog_token)469 static int hs20_process_icon_binary_file(struct wpa_supplicant *wpa_s,
470 const u8 *sa, const u8 *pos,
471 size_t slen, u8 dialog_token)
472 {
473 char fname[256];
474 int png;
475 FILE *f;
476 u16 data_len;
477 struct icon_entry *icon;
478
479 dl_list_for_each(icon, &wpa_s->icon_head, struct icon_entry, list) {
480 if (icon->dialog_token == dialog_token && !icon->image &&
481 ether_addr_equal(icon->bssid, sa)) {
482 icon->image = os_memdup(pos, slen);
483 if (!icon->image)
484 return -1;
485 icon->image_len = slen;
486 hs20_remove_duplicate_icons(wpa_s, icon);
487 wpa_msg(wpa_s, MSG_INFO,
488 RX_HS20_ICON MACSTR " %s %u",
489 MAC2STR(sa), icon->file_name,
490 (unsigned int) icon->image_len);
491 wpas_notify_hs20_icon_query_done(wpa_s, sa,
492 icon->file_name,
493 icon->image,
494 icon->image_len);
495 return 0;
496 }
497 }
498
499 wpa_msg(wpa_s, MSG_INFO, RX_HS20_ANQP MACSTR " Icon Binary File",
500 MAC2STR(sa));
501
502 if (slen < 4) {
503 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: Too short Icon Binary File "
504 "value from " MACSTR, MAC2STR(sa));
505 return -1;
506 }
507
508 wpa_printf(MSG_DEBUG, "HS 2.0: Download Status Code %u", *pos);
509 if (*pos != 0)
510 return -1;
511 pos++;
512 slen--;
513
514 if ((size_t) 1 + pos[0] > slen) {
515 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: Too short Icon Binary File "
516 "value from " MACSTR, MAC2STR(sa));
517 return -1;
518 }
519 wpa_hexdump_ascii(MSG_DEBUG, "Icon Type", pos + 1, pos[0]);
520 png = os_strncasecmp((char *) pos + 1, "image/png", 9) == 0;
521 slen -= 1 + pos[0];
522 pos += 1 + pos[0];
523
524 if (slen < 2) {
525 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: Too short Icon Binary File "
526 "value from " MACSTR, MAC2STR(sa));
527 return -1;
528 }
529 data_len = WPA_GET_LE16(pos);
530 pos += 2;
531 slen -= 2;
532
533 if (data_len > slen) {
534 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: Too short Icon Binary File "
535 "value from " MACSTR, MAC2STR(sa));
536 return -1;
537 }
538
539 wpa_printf(MSG_DEBUG, "Icon Binary Data: %u bytes", data_len);
540 if (wpa_s->conf->osu_dir == NULL)
541 return -1;
542
543 wpa_s->osu_icon_id++;
544 if (wpa_s->osu_icon_id == 0)
545 wpa_s->osu_icon_id++;
546 snprintf(fname, sizeof(fname), "%s/osu-icon-%u.%s",
547 wpa_s->conf->osu_dir, wpa_s->osu_icon_id,
548 png ? "png" : "icon");
549 f = fopen(fname, "wb");
550 if (f == NULL)
551 return -1;
552
553 hs20_set_osu_access_permission(wpa_s->conf->osu_dir, fname);
554
555 if (fwrite(pos, slen, 1, f) != 1) {
556 fclose(f);
557 unlink(fname);
558 return -1;
559 }
560 fclose(f);
561
562 wpa_msg(wpa_s, MSG_INFO, RX_HS20_ANQP_ICON "%s", fname);
563 return 0;
564 }
565
566
hs20_continue_icon_fetch(void * eloop_ctx,void * sock_ctx)567 static void hs20_continue_icon_fetch(void *eloop_ctx, void *sock_ctx)
568 {
569 struct wpa_supplicant *wpa_s = eloop_ctx;
570 if (wpa_s->fetch_osu_icon_in_progress)
571 hs20_next_osu_icon(wpa_s);
572 }
573
574
hs20_osu_icon_fetch_result(struct wpa_supplicant * wpa_s,int res)575 static void hs20_osu_icon_fetch_result(struct wpa_supplicant *wpa_s, int res)
576 {
577 size_t i, j;
578 struct os_reltime now, tmp;
579 int dur;
580
581 os_get_reltime(&now);
582 os_reltime_sub(&now, &wpa_s->osu_icon_fetch_start, &tmp);
583 dur = tmp.sec * 1000 + tmp.usec / 1000;
584 wpa_printf(MSG_DEBUG, "HS 2.0: Icon fetch dur=%d ms res=%d",
585 dur, res);
586
587 for (i = 0; i < wpa_s->osu_prov_count; i++) {
588 struct osu_provider *osu = &wpa_s->osu_prov[i];
589 for (j = 0; j < osu->icon_count; j++) {
590 struct osu_icon *icon = &osu->icon[j];
591 if (icon->id || icon->failed)
592 continue;
593 if (res < 0)
594 icon->failed = 1;
595 else
596 icon->id = wpa_s->osu_icon_id;
597 return;
598 }
599 }
600 }
601
602
hs20_parse_rx_hs20_anqp_resp(struct wpa_supplicant * wpa_s,struct wpa_bss * bss,const u8 * sa,const u8 * data,size_t slen,u8 dialog_token)603 void hs20_parse_rx_hs20_anqp_resp(struct wpa_supplicant *wpa_s,
604 struct wpa_bss *bss, const u8 *sa,
605 const u8 *data, size_t slen, u8 dialog_token)
606 {
607 const u8 *pos = data;
608 u8 subtype;
609 struct wpa_bss_anqp *anqp = NULL;
610 int ret;
611
612 if (slen < 2)
613 return;
614
615 if (bss)
616 anqp = bss->anqp;
617
618 subtype = *pos++;
619 slen--;
620
621 pos++; /* Reserved */
622 slen--;
623
624 switch (subtype) {
625 case HS20_STYPE_CAPABILITY_LIST:
626 wpa_msg(wpa_s, MSG_INFO, RX_HS20_ANQP MACSTR
627 " HS Capability List", MAC2STR(sa));
628 wpa_hexdump_ascii(MSG_DEBUG, "HS Capability List", pos, slen);
629 if (anqp) {
630 wpabuf_free(anqp->hs20_capability_list);
631 anqp->hs20_capability_list =
632 wpabuf_alloc_copy(pos, slen);
633 }
634 break;
635 case HS20_STYPE_OPERATOR_FRIENDLY_NAME:
636 wpa_msg(wpa_s, MSG_INFO, RX_HS20_ANQP MACSTR
637 " Operator Friendly Name", MAC2STR(sa));
638 wpa_hexdump_ascii(MSG_DEBUG, "oper friendly name", pos, slen);
639 if (anqp) {
640 wpabuf_free(anqp->hs20_operator_friendly_name);
641 anqp->hs20_operator_friendly_name =
642 wpabuf_alloc_copy(pos, slen);
643 }
644 break;
645 case HS20_STYPE_WAN_METRICS:
646 wpa_hexdump(MSG_DEBUG, "WAN Metrics", pos, slen);
647 if (slen < 13) {
648 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: Too short WAN "
649 "Metrics value from " MACSTR, MAC2STR(sa));
650 break;
651 }
652 wpa_msg(wpa_s, MSG_INFO, RX_HS20_ANQP MACSTR
653 " WAN Metrics %02x:%u:%u:%u:%u:%u", MAC2STR(sa),
654 pos[0], WPA_GET_LE32(pos + 1), WPA_GET_LE32(pos + 5),
655 pos[9], pos[10], WPA_GET_LE16(pos + 11));
656 if (anqp) {
657 wpabuf_free(anqp->hs20_wan_metrics);
658 anqp->hs20_wan_metrics = wpabuf_alloc_copy(pos, slen);
659 }
660 break;
661 case HS20_STYPE_CONNECTION_CAPABILITY:
662 wpa_msg(wpa_s, MSG_INFO, RX_HS20_ANQP MACSTR
663 " Connection Capability", MAC2STR(sa));
664 wpa_hexdump_ascii(MSG_DEBUG, "conn capability", pos, slen);
665 if (anqp) {
666 wpabuf_free(anqp->hs20_connection_capability);
667 anqp->hs20_connection_capability =
668 wpabuf_alloc_copy(pos, slen);
669 }
670 break;
671 case HS20_STYPE_OPERATING_CLASS:
672 wpa_msg(wpa_s, MSG_INFO, RX_HS20_ANQP MACSTR
673 " Operating Class", MAC2STR(sa));
674 wpa_hexdump_ascii(MSG_DEBUG, "Operating Class", pos, slen);
675 if (anqp) {
676 wpabuf_free(anqp->hs20_operating_class);
677 anqp->hs20_operating_class =
678 wpabuf_alloc_copy(pos, slen);
679 }
680 break;
681 case HS20_STYPE_OSU_PROVIDERS_LIST:
682 wpa_msg(wpa_s, MSG_INFO, RX_HS20_ANQP MACSTR
683 " OSU Providers list", MAC2STR(sa));
684 wpa_s->num_prov_found++;
685 if (anqp) {
686 wpabuf_free(anqp->hs20_osu_providers_list);
687 anqp->hs20_osu_providers_list =
688 wpabuf_alloc_copy(pos, slen);
689 }
690 break;
691 case HS20_STYPE_ICON_BINARY_FILE:
692 ret = hs20_process_icon_binary_file(wpa_s, sa, pos, slen,
693 dialog_token);
694 if (wpa_s->fetch_osu_icon_in_progress) {
695 hs20_osu_icon_fetch_result(wpa_s, ret);
696 eloop_cancel_timeout(hs20_continue_icon_fetch,
697 wpa_s, NULL);
698 eloop_register_timeout(0, 0, hs20_continue_icon_fetch,
699 wpa_s, NULL);
700 }
701 break;
702 case HS20_STYPE_OPERATOR_ICON_METADATA:
703 wpa_msg(wpa_s, MSG_INFO, RX_HS20_ANQP MACSTR
704 " Operator Icon Metadata", MAC2STR(sa));
705 wpa_hexdump(MSG_DEBUG, "Operator Icon Metadata", pos, slen);
706 if (anqp) {
707 wpabuf_free(anqp->hs20_operator_icon_metadata);
708 anqp->hs20_operator_icon_metadata =
709 wpabuf_alloc_copy(pos, slen);
710 }
711 break;
712 case HS20_STYPE_OSU_PROVIDERS_NAI_LIST:
713 wpa_msg(wpa_s, MSG_INFO, RX_HS20_ANQP MACSTR
714 " OSU Providers NAI List", MAC2STR(sa));
715 if (anqp) {
716 wpabuf_free(anqp->hs20_osu_providers_nai_list);
717 anqp->hs20_osu_providers_nai_list =
718 wpabuf_alloc_copy(pos, slen);
719 }
720 break;
721 default:
722 wpa_printf(MSG_DEBUG, "HS20: Unsupported subtype %u", subtype);
723 break;
724 }
725 }
726
727
hs20_notify_parse_done(struct wpa_supplicant * wpa_s)728 void hs20_notify_parse_done(struct wpa_supplicant *wpa_s)
729 {
730 if (!wpa_s->fetch_osu_icon_in_progress)
731 return;
732 if (eloop_is_timeout_registered(hs20_continue_icon_fetch, wpa_s, NULL))
733 return;
734 /*
735 * We are going through icon fetch, but no icon response was received.
736 * Assume this means the current AP could not provide an answer to avoid
737 * getting stuck in fetch iteration.
738 */
739 hs20_icon_fetch_failed(wpa_s);
740 }
741
742
hs20_free_osu_prov_entry(struct osu_provider * prov)743 static void hs20_free_osu_prov_entry(struct osu_provider *prov)
744 {
745 }
746
747
hs20_free_osu_prov(struct wpa_supplicant * wpa_s)748 void hs20_free_osu_prov(struct wpa_supplicant *wpa_s)
749 {
750 size_t i;
751 for (i = 0; i < wpa_s->osu_prov_count; i++)
752 hs20_free_osu_prov_entry(&wpa_s->osu_prov[i]);
753 os_free(wpa_s->osu_prov);
754 wpa_s->osu_prov = NULL;
755 wpa_s->osu_prov_count = 0;
756 }
757
758
hs20_osu_fetch_done(struct wpa_supplicant * wpa_s)759 static void hs20_osu_fetch_done(struct wpa_supplicant *wpa_s)
760 {
761 char fname[256];
762 FILE *f;
763 size_t i, j;
764
765 wpa_s->fetch_osu_info = 0;
766 wpa_s->fetch_osu_icon_in_progress = 0;
767
768 if (wpa_s->conf->osu_dir == NULL) {
769 hs20_free_osu_prov(wpa_s);
770 wpa_s->fetch_anqp_in_progress = 0;
771 return;
772 }
773
774 snprintf(fname, sizeof(fname), "%s/osu-providers.txt",
775 wpa_s->conf->osu_dir);
776 f = fopen(fname, "w");
777 if (f == NULL) {
778 wpa_msg(wpa_s, MSG_INFO,
779 "Could not write OSU provider information");
780 hs20_free_osu_prov(wpa_s);
781 wpa_s->fetch_anqp_in_progress = 0;
782 return;
783 }
784
785 hs20_set_osu_access_permission(wpa_s->conf->osu_dir, fname);
786
787 for (i = 0; i < wpa_s->osu_prov_count; i++) {
788 struct osu_provider *osu = &wpa_s->osu_prov[i];
789 if (i > 0)
790 fprintf(f, "\n");
791 fprintf(f, "OSU-PROVIDER " MACSTR "\n"
792 "uri=%s\n"
793 "methods=%08x\n",
794 MAC2STR(osu->bssid), osu->server_uri, osu->osu_methods);
795 if (osu->osu_ssid_len) {
796 fprintf(f, "osu_ssid=%s\n",
797 wpa_ssid_txt(osu->osu_ssid,
798 osu->osu_ssid_len));
799 }
800 if (osu->osu_ssid2_len) {
801 fprintf(f, "osu_ssid2=%s\n",
802 wpa_ssid_txt(osu->osu_ssid2,
803 osu->osu_ssid2_len));
804 }
805 if (osu->osu_nai[0])
806 fprintf(f, "osu_nai=%s\n", osu->osu_nai);
807 if (osu->osu_nai2[0])
808 fprintf(f, "osu_nai2=%s\n", osu->osu_nai2);
809 for (j = 0; j < osu->friendly_name_count; j++) {
810 fprintf(f, "friendly_name=%s:%s\n",
811 osu->friendly_name[j].lang,
812 osu->friendly_name[j].text);
813 }
814 for (j = 0; j < osu->serv_desc_count; j++) {
815 fprintf(f, "desc=%s:%s\n",
816 osu->serv_desc[j].lang,
817 osu->serv_desc[j].text);
818 }
819 for (j = 0; j < osu->icon_count; j++) {
820 struct osu_icon *icon = &osu->icon[j];
821 if (icon->failed)
822 continue; /* could not fetch icon */
823 fprintf(f, "icon=%u:%u:%u:%s:%s:%s\n",
824 icon->id, icon->width, icon->height, icon->lang,
825 icon->icon_type, icon->filename);
826 }
827 }
828 fclose(f);
829 hs20_free_osu_prov(wpa_s);
830
831 wpa_msg(wpa_s, MSG_INFO, "OSU provider fetch completed");
832 wpa_s->fetch_anqp_in_progress = 0;
833 }
834
835
hs20_next_osu_icon(struct wpa_supplicant * wpa_s)836 void hs20_next_osu_icon(struct wpa_supplicant *wpa_s)
837 {
838 size_t i, j;
839
840 wpa_printf(MSG_DEBUG, "HS 2.0: Ready to fetch next icon");
841
842 for (i = 0; i < wpa_s->osu_prov_count; i++) {
843 struct osu_provider *osu = &wpa_s->osu_prov[i];
844 for (j = 0; j < osu->icon_count; j++) {
845 struct osu_icon *icon = &osu->icon[j];
846 if (icon->id || icon->failed)
847 continue;
848
849 wpa_printf(MSG_DEBUG, "HS 2.0: Try to fetch icon '%s' "
850 "from " MACSTR, icon->filename,
851 MAC2STR(osu->bssid));
852 os_get_reltime(&wpa_s->osu_icon_fetch_start);
853 if (hs20_anqp_send_req(wpa_s, osu->bssid,
854 BIT(HS20_STYPE_ICON_REQUEST),
855 (u8 *) icon->filename,
856 os_strlen(icon->filename),
857 0) < 0) {
858 icon->failed = 1;
859 continue;
860 }
861 return;
862 }
863 }
864
865 wpa_printf(MSG_DEBUG, "HS 2.0: No more icons to fetch");
866 hs20_osu_fetch_done(wpa_s);
867 }
868
869
hs20_osu_add_prov(struct wpa_supplicant * wpa_s,struct wpa_bss * bss,const u8 * osu_ssid,u8 osu_ssid_len,const u8 * osu_ssid2,u8 osu_ssid2_len,const u8 * pos,size_t len)870 static void hs20_osu_add_prov(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
871 const u8 *osu_ssid, u8 osu_ssid_len,
872 const u8 *osu_ssid2, u8 osu_ssid2_len,
873 const u8 *pos, size_t len)
874 {
875 struct osu_provider *prov;
876 const u8 *end = pos + len;
877 u16 len2;
878 const u8 *pos2;
879 u8 uri_len, osu_method_len, osu_nai_len;
880
881 wpa_hexdump(MSG_DEBUG, "HS 2.0: Parsing OSU Provider", pos, len);
882 prov = os_realloc_array(wpa_s->osu_prov,
883 wpa_s->osu_prov_count + 1,
884 sizeof(*prov));
885 if (prov == NULL)
886 return;
887 wpa_s->osu_prov = prov;
888 prov = &prov[wpa_s->osu_prov_count];
889 os_memset(prov, 0, sizeof(*prov));
890
891 os_memcpy(prov->bssid, bss->bssid, ETH_ALEN);
892 os_memcpy(prov->osu_ssid, osu_ssid, osu_ssid_len);
893 prov->osu_ssid_len = osu_ssid_len;
894 if (osu_ssid2)
895 os_memcpy(prov->osu_ssid2, osu_ssid2, osu_ssid2_len);
896 prov->osu_ssid2_len = osu_ssid2_len;
897
898 /* OSU Friendly Name Length */
899 if (end - pos < 2) {
900 wpa_printf(MSG_DEBUG, "HS 2.0: Not enough room for OSU "
901 "Friendly Name Length");
902 return;
903 }
904 len2 = WPA_GET_LE16(pos);
905 pos += 2;
906 if (len2 > end - pos) {
907 wpa_printf(MSG_DEBUG, "HS 2.0: Not enough room for OSU "
908 "Friendly Name Duples");
909 return;
910 }
911 pos2 = pos;
912 pos += len2;
913
914 /* OSU Friendly Name Duples */
915 while (pos - pos2 >= 4 && prov->friendly_name_count < OSU_MAX_ITEMS) {
916 struct osu_lang_string *f;
917 u8 slen;
918
919 slen = pos2[0];
920 if (1 + slen > pos - pos2) {
921 wpa_printf(MSG_DEBUG, "Invalid OSU Friendly Name");
922 break;
923 }
924 if (slen < 3) {
925 wpa_printf(MSG_DEBUG,
926 "Invalid OSU Friendly Name (no room for language)");
927 break;
928 }
929 f = &prov->friendly_name[prov->friendly_name_count++];
930 pos2++;
931 os_memcpy(f->lang, pos2, 3);
932 pos2 += 3;
933 slen -= 3;
934 os_memcpy(f->text, pos2, slen);
935 pos2 += slen;
936 }
937
938 /* OSU Server URI */
939 if (end - pos < 1) {
940 wpa_printf(MSG_DEBUG,
941 "HS 2.0: Not enough room for OSU Server URI length");
942 return;
943 }
944 uri_len = *pos++;
945 if (uri_len > end - pos) {
946 wpa_printf(MSG_DEBUG, "HS 2.0: Not enough room for OSU Server "
947 "URI");
948 return;
949 }
950 os_memcpy(prov->server_uri, pos, uri_len);
951 pos += uri_len;
952
953 /* OSU Method list */
954 if (end - pos < 1) {
955 wpa_printf(MSG_DEBUG, "HS 2.0: Not enough room for OSU Method "
956 "list length");
957 return;
958 }
959 osu_method_len = pos[0];
960 if (osu_method_len > end - pos - 1) {
961 wpa_printf(MSG_DEBUG, "HS 2.0: Not enough room for OSU Method "
962 "list");
963 return;
964 }
965 pos2 = pos + 1;
966 pos += 1 + osu_method_len;
967 while (pos2 < pos) {
968 if (*pos2 < 32)
969 prov->osu_methods |= BIT(*pos2);
970 pos2++;
971 }
972
973 /* Icons Available Length */
974 if (end - pos < 2) {
975 wpa_printf(MSG_DEBUG, "HS 2.0: Not enough room for Icons "
976 "Available Length");
977 return;
978 }
979 len2 = WPA_GET_LE16(pos);
980 pos += 2;
981 if (len2 > end - pos) {
982 wpa_printf(MSG_DEBUG, "HS 2.0: Not enough room for Icons "
983 "Available");
984 return;
985 }
986 pos2 = pos;
987 pos += len2;
988
989 /* Icons Available */
990 while (pos2 < pos) {
991 struct osu_icon *icon = &prov->icon[prov->icon_count];
992 u8 flen;
993
994 if (2 + 2 + 3 + 1 + 1 > pos - pos2) {
995 wpa_printf(MSG_DEBUG, "HS 2.0: Invalid Icon Metadata");
996 break;
997 }
998
999 icon->width = WPA_GET_LE16(pos2);
1000 pos2 += 2;
1001 icon->height = WPA_GET_LE16(pos2);
1002 pos2 += 2;
1003 os_memcpy(icon->lang, pos2, 3);
1004 pos2 += 3;
1005
1006 flen = *pos2++;
1007 if (flen > pos - pos2) {
1008 wpa_printf(MSG_DEBUG, "HS 2.0: Not room for Icon Type");
1009 break;
1010 }
1011 os_memcpy(icon->icon_type, pos2, flen);
1012 pos2 += flen;
1013
1014 if (pos - pos2 < 1) {
1015 wpa_printf(MSG_DEBUG, "HS 2.0: Not room for Icon "
1016 "Filename length");
1017 break;
1018 }
1019 flen = *pos2++;
1020 if (flen > pos - pos2) {
1021 wpa_printf(MSG_DEBUG, "HS 2.0: Not room for Icon "
1022 "Filename");
1023 break;
1024 }
1025 os_memcpy(icon->filename, pos2, flen);
1026 pos2 += flen;
1027
1028 prov->icon_count++;
1029 }
1030
1031 /* OSU_NAI */
1032 if (end - pos < 1) {
1033 wpa_printf(MSG_DEBUG, "HS 2.0: Not enough room for OSU_NAI");
1034 return;
1035 }
1036 osu_nai_len = *pos++;
1037 if (osu_nai_len > end - pos) {
1038 wpa_printf(MSG_DEBUG, "HS 2.0: Not enough room for OSU_NAI");
1039 return;
1040 }
1041 os_memcpy(prov->osu_nai, pos, osu_nai_len);
1042 pos += osu_nai_len;
1043
1044 /* OSU Service Description Length */
1045 if (end - pos < 2) {
1046 wpa_printf(MSG_DEBUG, "HS 2.0: Not enough room for OSU "
1047 "Service Description Length");
1048 return;
1049 }
1050 len2 = WPA_GET_LE16(pos);
1051 pos += 2;
1052 if (len2 > end - pos) {
1053 wpa_printf(MSG_DEBUG, "HS 2.0: Not enough room for OSU "
1054 "Service Description Duples");
1055 return;
1056 }
1057 pos2 = pos;
1058 pos += len2;
1059
1060 /* OSU Service Description Duples */
1061 while (pos - pos2 >= 4 && prov->serv_desc_count < OSU_MAX_ITEMS) {
1062 struct osu_lang_string *f;
1063 u8 descr_len;
1064
1065 descr_len = *pos2++;
1066 if (descr_len > pos - pos2 || descr_len < 3) {
1067 wpa_printf(MSG_DEBUG, "Invalid OSU Service "
1068 "Description");
1069 break;
1070 }
1071 f = &prov->serv_desc[prov->serv_desc_count++];
1072 os_memcpy(f->lang, pos2, 3);
1073 os_memcpy(f->text, pos2 + 3, descr_len - 3);
1074 pos2 += descr_len;
1075 }
1076
1077 wpa_printf(MSG_DEBUG, "HS 2.0: Added OSU Provider through " MACSTR,
1078 MAC2STR(bss->bssid));
1079 wpa_s->osu_prov_count++;
1080 }
1081
1082
hs20_osu_icon_fetch(struct wpa_supplicant * wpa_s)1083 void hs20_osu_icon_fetch(struct wpa_supplicant *wpa_s)
1084 {
1085 struct wpa_bss *bss;
1086 struct wpabuf *prov_anqp;
1087 const u8 *pos, *end;
1088 u16 len;
1089 const u8 *osu_ssid, *osu_ssid2;
1090 u8 osu_ssid_len, osu_ssid2_len;
1091 u8 num_providers;
1092
1093 hs20_free_osu_prov(wpa_s);
1094
1095 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
1096 struct wpa_ie_data data;
1097 const u8 *ie;
1098
1099 if (bss->anqp == NULL)
1100 continue;
1101 prov_anqp = bss->anqp->hs20_osu_providers_list;
1102 if (prov_anqp == NULL)
1103 continue;
1104 ie = wpa_bss_get_rsne(wpa_s, bss, NULL, false);
1105 if (ie && wpa_parse_wpa_ie(ie, 2 + ie[1], &data) == 0 &&
1106 (data.key_mgmt & WPA_KEY_MGMT_OSEN)) {
1107 osu_ssid2 = bss->ssid;
1108 osu_ssid2_len = bss->ssid_len;
1109 } else {
1110 osu_ssid2 = NULL;
1111 osu_ssid2_len = 0;
1112 }
1113 wpa_printf(MSG_DEBUG, "HS 2.0: Parsing OSU Providers list from "
1114 MACSTR, MAC2STR(bss->bssid));
1115 wpa_hexdump_buf(MSG_DEBUG, "HS 2.0: OSU Providers list",
1116 prov_anqp);
1117 pos = wpabuf_head(prov_anqp);
1118 end = pos + wpabuf_len(prov_anqp);
1119
1120 /* OSU SSID */
1121 if (end - pos < 1)
1122 continue;
1123 if (1 + pos[0] > end - pos) {
1124 wpa_printf(MSG_DEBUG, "HS 2.0: Not enough room for "
1125 "OSU SSID");
1126 continue;
1127 }
1128 osu_ssid_len = *pos++;
1129 if (osu_ssid_len > SSID_MAX_LEN) {
1130 wpa_printf(MSG_DEBUG, "HS 2.0: Invalid OSU SSID "
1131 "Length %u", osu_ssid_len);
1132 continue;
1133 }
1134 osu_ssid = pos;
1135 pos += osu_ssid_len;
1136
1137 if (end - pos < 1) {
1138 wpa_printf(MSG_DEBUG, "HS 2.0: Not enough room for "
1139 "Number of OSU Providers");
1140 continue;
1141 }
1142 num_providers = *pos++;
1143 wpa_printf(MSG_DEBUG, "HS 2.0: Number of OSU Providers: %u",
1144 num_providers);
1145
1146 /* OSU Providers */
1147 while (end - pos > 2 && num_providers > 0) {
1148 num_providers--;
1149 len = WPA_GET_LE16(pos);
1150 pos += 2;
1151 if (len > (unsigned int) (end - pos))
1152 break;
1153 hs20_osu_add_prov(wpa_s, bss, osu_ssid,
1154 osu_ssid_len, osu_ssid2,
1155 osu_ssid2_len, pos, len);
1156 pos += len;
1157 }
1158
1159 if (pos != end) {
1160 wpa_printf(MSG_DEBUG, "HS 2.0: Ignored %d bytes of "
1161 "extra data after OSU Providers",
1162 (int) (end - pos));
1163 }
1164
1165 prov_anqp = bss->anqp->hs20_osu_providers_nai_list;
1166 if (!prov_anqp)
1167 continue;
1168 wpa_printf(MSG_DEBUG,
1169 "HS 2.0: Parsing OSU Providers NAI List from "
1170 MACSTR, MAC2STR(bss->bssid));
1171 wpa_hexdump_buf(MSG_DEBUG, "HS 2.0: OSU Providers NAI List",
1172 prov_anqp);
1173 pos = wpabuf_head(prov_anqp);
1174 end = pos + wpabuf_len(prov_anqp);
1175 num_providers = 0;
1176 while (end - pos > 0) {
1177 len = *pos++;
1178 if (end - pos < len) {
1179 wpa_printf(MSG_DEBUG,
1180 "HS 2.0: Not enough room for OSU_NAI");
1181 break;
1182 }
1183 if (num_providers >= wpa_s->osu_prov_count) {
1184 wpa_printf(MSG_DEBUG,
1185 "HS 2.0: Ignore unexpected OSU Provider NAI List entries");
1186 break;
1187 }
1188 os_memcpy(wpa_s->osu_prov[num_providers].osu_nai2,
1189 pos, len);
1190 pos += len;
1191 num_providers++;
1192 }
1193 }
1194
1195 wpa_s->fetch_osu_icon_in_progress = 1;
1196 hs20_next_osu_icon(wpa_s);
1197 }
1198
1199
hs20_osu_scan_res_handler(struct wpa_supplicant * wpa_s,struct wpa_scan_results * scan_res)1200 static void hs20_osu_scan_res_handler(struct wpa_supplicant *wpa_s,
1201 struct wpa_scan_results *scan_res)
1202 {
1203 wpa_printf(MSG_DEBUG, "OSU provisioning fetch scan completed");
1204 if (!wpa_s->fetch_osu_waiting_scan) {
1205 wpa_printf(MSG_DEBUG, "OSU fetch have been canceled");
1206 return;
1207 }
1208 wpa_s->network_select = 0;
1209 wpa_s->fetch_all_anqp = 1;
1210 wpa_s->fetch_osu_info = 1;
1211 wpa_s->fetch_osu_icon_in_progress = 0;
1212
1213 interworking_start_fetch_anqp(wpa_s);
1214 }
1215
1216
hs20_fetch_osu(struct wpa_supplicant * wpa_s,int skip_scan)1217 int hs20_fetch_osu(struct wpa_supplicant *wpa_s, int skip_scan)
1218 {
1219 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
1220 wpa_printf(MSG_DEBUG, "HS 2.0: Cannot start fetch_osu - "
1221 "interface disabled");
1222 return -1;
1223 }
1224
1225 if (wpa_s->scanning) {
1226 wpa_printf(MSG_DEBUG, "HS 2.0: Cannot start fetch_osu - "
1227 "scanning");
1228 return -1;
1229 }
1230
1231 if (wpa_s->conf->osu_dir == NULL) {
1232 wpa_printf(MSG_DEBUG, "HS 2.0: Cannot start fetch_osu - "
1233 "osu_dir not configured");
1234 return -1;
1235 }
1236
1237 if (wpa_s->fetch_anqp_in_progress || wpa_s->network_select) {
1238 wpa_printf(MSG_DEBUG, "HS 2.0: Cannot start fetch_osu - "
1239 "fetch in progress (%d, %d)",
1240 wpa_s->fetch_anqp_in_progress,
1241 wpa_s->network_select);
1242 return -1;
1243 }
1244
1245 wpa_msg(wpa_s, MSG_INFO, "Starting OSU provisioning information fetch");
1246 wpa_s->num_osu_scans = 0;
1247 wpa_s->num_prov_found = 0;
1248 if (skip_scan) {
1249 wpa_s->network_select = 0;
1250 wpa_s->fetch_all_anqp = 1;
1251 wpa_s->fetch_osu_info = 1;
1252 wpa_s->fetch_osu_icon_in_progress = 0;
1253
1254 interworking_start_fetch_anqp(wpa_s);
1255 } else {
1256 hs20_start_osu_scan(wpa_s);
1257 }
1258
1259 return 0;
1260 }
1261
1262
hs20_start_osu_scan(struct wpa_supplicant * wpa_s)1263 void hs20_start_osu_scan(struct wpa_supplicant *wpa_s)
1264 {
1265 wpa_s->fetch_osu_waiting_scan = 1;
1266 wpa_s->num_osu_scans++;
1267 wpa_s->scan_req = MANUAL_SCAN_REQ;
1268 wpa_s->scan_res_handler = hs20_osu_scan_res_handler;
1269 wpa_supplicant_req_scan(wpa_s, 0, 0);
1270 }
1271
1272
hs20_cancel_fetch_osu(struct wpa_supplicant * wpa_s)1273 void hs20_cancel_fetch_osu(struct wpa_supplicant *wpa_s)
1274 {
1275 wpa_printf(MSG_DEBUG, "Cancel OSU fetch");
1276 interworking_stop_fetch_anqp(wpa_s);
1277 wpa_s->fetch_osu_waiting_scan = 0;
1278 wpa_s->network_select = 0;
1279 wpa_s->fetch_osu_info = 0;
1280 wpa_s->fetch_osu_icon_in_progress = 0;
1281 }
1282
1283
hs20_icon_fetch_failed(struct wpa_supplicant * wpa_s)1284 void hs20_icon_fetch_failed(struct wpa_supplicant *wpa_s)
1285 {
1286 hs20_osu_icon_fetch_result(wpa_s, -1);
1287 eloop_cancel_timeout(hs20_continue_icon_fetch, wpa_s, NULL);
1288 eloop_register_timeout(0, 0, hs20_continue_icon_fetch, wpa_s, NULL);
1289 }
1290
1291
hs20_rx_subscription_remediation(struct wpa_supplicant * wpa_s,const char * url,u8 osu_method)1292 void hs20_rx_subscription_remediation(struct wpa_supplicant *wpa_s,
1293 const char *url, u8 osu_method)
1294 {
1295 if (url)
1296 wpa_msg(wpa_s, MSG_INFO, HS20_SUBSCRIPTION_REMEDIATION "%u %s",
1297 osu_method, url);
1298 else
1299 wpa_msg(wpa_s, MSG_INFO, HS20_SUBSCRIPTION_REMEDIATION);
1300 wpas_notify_hs20_rx_subscription_remediation(wpa_s, url, osu_method);
1301 }
1302
1303
hs20_rx_deauth_imminent_notice(struct wpa_supplicant * wpa_s,u8 code,u16 reauth_delay,const char * url)1304 void hs20_rx_deauth_imminent_notice(struct wpa_supplicant *wpa_s, u8 code,
1305 u16 reauth_delay, const char *url)
1306 {
1307 if (!wpa_sm_pmf_enabled(wpa_s->wpa)) {
1308 wpa_printf(MSG_DEBUG, "HS 2.0: Ignore deauthentication imminent notice since PMF was not enabled");
1309 return;
1310 }
1311
1312 wpa_msg(wpa_s, MSG_INFO, HS20_DEAUTH_IMMINENT_NOTICE "%u %u %s",
1313 code, reauth_delay, url);
1314 wpas_notify_hs20_rx_deauth_imminent_notice(wpa_s, code, reauth_delay, url);
1315
1316 if (code == HS20_DEAUTH_REASON_CODE_BSS) {
1317 wpa_printf(MSG_DEBUG, "HS 2.0: Add BSS to ignore list");
1318 wpa_bssid_ignore_add(wpa_s, wpa_s->bssid);
1319 /* TODO: For now, disable full ESS since some drivers may not
1320 * support disabling per BSS. */
1321 if (wpa_s->current_ssid) {
1322 struct os_reltime now;
1323 os_get_reltime(&now);
1324 if (now.sec + reauth_delay <=
1325 wpa_s->current_ssid->disabled_until.sec)
1326 return;
1327 wpa_printf(MSG_DEBUG, "HS 2.0: Disable network for %u seconds (BSS)",
1328 reauth_delay);
1329 wpa_s->current_ssid->disabled_until.sec =
1330 now.sec + reauth_delay;
1331 }
1332 }
1333
1334 if (code == HS20_DEAUTH_REASON_CODE_ESS && wpa_s->current_ssid) {
1335 struct os_reltime now;
1336 os_get_reltime(&now);
1337 if (now.sec + reauth_delay <=
1338 wpa_s->current_ssid->disabled_until.sec)
1339 return;
1340 wpa_printf(MSG_DEBUG, "HS 2.0: Disable network for %u seconds",
1341 reauth_delay);
1342 wpa_s->current_ssid->disabled_until.sec =
1343 now.sec + reauth_delay;
1344 }
1345 }
1346
1347
hs20_rx_t_c_acceptance(struct wpa_supplicant * wpa_s,const char * url)1348 void hs20_rx_t_c_acceptance(struct wpa_supplicant *wpa_s, const char *url)
1349 {
1350 if (!wpa_sm_pmf_enabled(wpa_s->wpa)) {
1351 wpa_printf(MSG_DEBUG,
1352 "HS 2.0: Ignore Terms and Conditions Acceptance since PMF was not enabled");
1353 return;
1354 }
1355
1356 wpas_notify_hs20_t_c_acceptance(wpa_s, url);
1357 }
1358
1359
hs20_init(struct wpa_supplicant * wpa_s)1360 void hs20_init(struct wpa_supplicant *wpa_s)
1361 {
1362 dl_list_init(&wpa_s->icon_head);
1363 }
1364
1365
hs20_deinit(struct wpa_supplicant * wpa_s)1366 void hs20_deinit(struct wpa_supplicant *wpa_s)
1367 {
1368 eloop_cancel_timeout(hs20_continue_icon_fetch, wpa_s, NULL);
1369 hs20_free_osu_prov(wpa_s);
1370 if (wpa_s->icon_head.next)
1371 hs20_del_icon(wpa_s, NULL, NULL);
1372 }
1373