int wpas_wps_ssid_wildcard_ok(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid, struct wpa_scan_res *bss) { struct wpabuf *wps_ie = NULL; int ret = 0; if (eap_is_wps_pbc_enrollee(&ssid->eap)) { wps_ie = wpa_scan_get_vendor_ie_multi(bss, WPS_IE_VENDOR_TYPE); if (wps_ie && wps_is_selected_pbc_registrar(wps_ie)) { /* allow wildcard SSID for WPS PBC */ ret = 1; } } else if (eap_is_wps_pin_enrollee(&ssid->eap)) { wps_ie = wpa_scan_get_vendor_ie_multi(bss, WPS_IE_VENDOR_TYPE); if (wps_ie && (wps_is_selected_pin_registrar(wps_ie) || wpa_s->scan_runs >= WPS_PIN_SCAN_IGNORE_SEL_REG)) { /* allow wildcard SSID for WPS PIN */ ret = 1; } } if (!ret && ssid->bssid_set && os_memcmp(ssid->bssid, bss->bssid, ETH_ALEN) == 0) { /* allow wildcard SSID due to hardcoded BSSID match */ ret = 1; } wpabuf_free(wps_ie); return ret; }
enum wps_request_type wpas_wps_get_req_type(struct wpa_ssid *ssid) { if (eap_is_wps_pbc_enrollee(&ssid->eap) || eap_is_wps_pin_enrollee(&ssid->eap)) return WPS_REQ_ENROLLEE; else return WPS_REQ_REGISTRAR; }
int wpas_wps_ssid_wildcard_ok(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid, struct wpa_scan_res *bss) { struct wpabuf *wps_ie = NULL; int ret = 0; if (eap_is_wps_pbc_enrollee(&ssid->eap)) { wps_ie = wpa_scan_get_vendor_ie_multi(bss, WPS_IE_VENDOR_TYPE); if (wps_ie && wps_is_selected_pbc_registrar(wps_ie)) { /* allow wildcard SSID for WPS PBC */ ret = 1; } } else if (eap_is_wps_pin_enrollee(&ssid->eap)) { wps_ie = wpa_scan_get_vendor_ie_multi(bss, WPS_IE_VENDOR_TYPE); if (wps_ie && (wps_is_addr_authorized(wps_ie, wpa_s->own_addr, 1) || wpa_s->scan_runs >= WPS_PIN_SCAN_IGNORE_SEL_REG)) { /* allow wildcard SSID for WPS PIN */ ret = 1; } } if (!ret && ssid->bssid_set && os_memcmp(ssid->bssid, bss->bssid, ETH_ALEN) == 0) { /* allow wildcard SSID due to hardcoded BSSID match */ ret = 1; } #ifdef CONFIG_WPS_STRICT if (wps_ie) { if (wps_validate_beacon_probe_resp(wps_ie, bss->beacon_ie_len > 0, bss->bssid) < 0) ret = 0; if (bss->beacon_ie_len) { struct wpabuf *bcn_wps; bcn_wps = wpa_scan_get_vendor_ie_multi_beacon( bss, WPS_IE_VENDOR_TYPE); if (bcn_wps == NULL) { wpa_printf(MSG_DEBUG, "WPS: Mandatory WPS IE " "missing from AP Beacon"); ret = 0; } else { if (wps_validate_beacon(wps_ie) < 0) ret = 0; wpabuf_free(bcn_wps); } } } #endif /* CONFIG_WPS_STRICT */ wpabuf_free(wps_ie); return ret; }
int wpas_wps_scan_pbc_overlap(struct wpa_supplicant *wpa_s, struct wpa_scan_res *selected, struct wpa_ssid *ssid) { const u8 *sel_uuid, *uuid; size_t i; struct wpabuf *wps_ie; int ret = 0; if (!eap_is_wps_pbc_enrollee(&ssid->eap)) return 0; /* Make sure that only one AP is in active PBC mode */ wps_ie = wpa_scan_get_vendor_ie_multi(selected, WPS_IE_VENDOR_TYPE); if (wps_ie) sel_uuid = wps_get_uuid_e(wps_ie); else sel_uuid = NULL; for (i = 0; i < wpa_s->scan_res->num; i++) { struct wpa_scan_res *bss = wpa_s->scan_res->res[i]; struct wpabuf *ie; if (bss == selected) continue; ie = wpa_scan_get_vendor_ie_multi(bss, WPS_IE_VENDOR_TYPE); if (!ie) continue; if (!wps_is_selected_pbc_registrar(ie)) { wpabuf_free(ie); continue; } uuid = wps_get_uuid_e(ie); if (sel_uuid == NULL || uuid == NULL || os_memcmp(sel_uuid, uuid, 16) != 0) { ret = 1; /* PBC overlap */ wpabuf_free(ie); break; } /* TODO: verify that this is reasonable dual-band situation */ wpabuf_free(ie); } wpabuf_free(wps_ie); return ret; }
int wpas_wps_ssid_bss_match(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid, struct wpa_scan_res *bss) { struct wpabuf *wps_ie; if (!(ssid->key_mgmt & WPA_KEY_MGMT_WPS)) return -1; wps_ie = wpa_scan_get_vendor_ie_multi(bss, WPS_IE_VENDOR_TYPE); if (eap_is_wps_pbc_enrollee(&ssid->eap)) { if (!wps_ie) { wpa_printf(MSG_DEBUG, " skip - non-WPS AP"); return 0; } if (!wps_is_selected_pbc_registrar(wps_ie)) { wpa_printf(MSG_DEBUG, " skip - WPS AP " "without active PBC Registrar"); wpabuf_free(wps_ie); return 0; } /* TODO: overlap detection */ wpa_printf(MSG_DEBUG, " selected based on WPS IE " "(Active PBC)"); wpabuf_free(wps_ie); return 1; } if (eap_is_wps_pin_enrollee(&ssid->eap)) { if (!wps_ie) { wpa_printf(MSG_DEBUG, " skip - non-WPS AP"); return 0; } /* * Start with WPS APs that advertise active PIN Registrar and * allow any WPS AP after third scan since some APs do not set * Selected Registrar attribute properly when using external * Registrar. */ if (!wps_is_selected_pin_registrar(wps_ie)) { if (wpa_s->scan_runs < WPS_PIN_SCAN_IGNORE_SEL_REG) { wpa_printf(MSG_DEBUG, " skip - WPS AP " "without active PIN Registrar"); wpabuf_free(wps_ie); return 0; } wpa_printf(MSG_DEBUG, " selected based on WPS IE"); } else { wpa_printf(MSG_DEBUG, " selected based on WPS IE " "(Active PIN)"); } wpabuf_free(wps_ie); return 1; } if (wps_ie) { wpa_printf(MSG_DEBUG, " selected based on WPS IE"); wpabuf_free(wps_ie); return 1; } return -1; }
static void wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s) { int prio, timeout; struct wpa_scan_res *selected = NULL; struct wpa_ssid *ssid = NULL; wpa_supplicant_notify_scanning(wpa_s, 0); if (wpa_supplicant_get_scan_results(wpa_s) < 0) { if (wpa_s->conf->ap_scan == 2) return; wpa_printf(MSG_DEBUG, "Failed to get scan results - try " "scanning again"); timeout = 1; goto req_scan; } /* * Don't post the results if this was the initial cached * and there were no results. */ if (wpa_s->scan_res_tried == 1 && wpa_s->conf->ap_scan == 1 && wpa_s->scan_res->num == 0) { wpa_msg(wpa_s, MSG_DEBUG, "Cached scan results are " "empty - not posting"); } else { wpa_printf(MSG_DEBUG, "New scan results available"); wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_SCAN_RESULTS); wpa_supplicant_dbus_notify_scan_results(wpa_s); /* WPS availability is fetched from scan results. Reduce logging. */ #ifndef ANDROID wpas_wps_notify_scan_results(wpa_s); #endif } if ((wpa_s->conf->ap_scan == 2 && !wpas_wps_searching(wpa_s))) return; if (wpa_s->disconnected) { wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED); return; } while (selected == NULL) { #ifdef CONFIG_ORANGE_SUPPORT for (prio = 0; prio < wpa_s->conf->num_prio; prio++) { selected = wpa_supplicant_select_bss_private( wpa_s, wpa_s->conf->pssid[prio], &ssid); if (selected) break; } if(selected == NULL) { for (prio = 0; prio < wpa_s->conf->num_prio; prio++) { selected = wpa_supplicant_select_bss_public( wpa_s, wpa_s->conf->pssid[prio], &ssid); if (selected) break; } } #else for (prio = 0; prio < wpa_s->conf->num_prio; prio++) { selected = wpa_supplicant_select_bss( wpa_s, wpa_s->conf->pssid[prio], &ssid); if (selected) break; } #endif if (selected == NULL && wpa_s->blacklist) { wpa_printf(MSG_DEBUG, "No APs found - clear blacklist " "and try again"); wpa_blacklist_clear(wpa_s); wpa_s->blacklist_cleared++; } else if (selected == NULL) { break; } } if (selected) { if (wpas_wps_scan_pbc_overlap(wpa_s, selected, ssid)) { wpa_msg(wpa_s, MSG_INFO, WPS_EVENT_OVERLAP "PBC session overlap"); timeout = 10; goto req_scan; } else { if(eap_is_wps_pbc_enrollee(&ssid->eap)) { wpa_msg(wpa_s, MSG_INFO, WPS_EVENT_NO_OVERLAP); } } /* Do not trigger new association unless the BSSID has changed * or if reassociation is requested. If we are in process of * associating with the selected BSSID, do not trigger new * attempt. */ wpa_printf(MSG_DEBUG, "[associate] %s:: wpa_s->reassociate = %d, selected->bssid =" MACSTR "\nwpa_s->bssid = " MACSTR "wpa_s->wpa_state = %d" "wpa_s->pending_bssid = " MACSTR, __FUNCTION__, wpa_s->reassociate, MAC2STR(selected->bssid), MAC2STR(wpa_s->bssid), wpa_s->wpa_state, MAC2STR(wpa_s->pending_bssid) ); if (wpa_s->reassociate || (os_memcmp(selected->bssid, wpa_s->bssid, ETH_ALEN) != 0 && (wpa_s->wpa_state != WPA_ASSOCIATING || os_memcmp(selected->bssid, wpa_s->pending_bssid, ETH_ALEN) != 0))) { if (wpa_supplicant_scard_init(wpa_s, ssid)) { wpa_supplicant_req_scan(wpa_s, 10, 0); return; } wpa_supplicant_associate(wpa_s, selected, ssid); } else { wpa_printf(MSG_DEBUG, "Already associated with the " "selected AP."); } rsn_preauth_scan_results(wpa_s->wpa, wpa_s->scan_res); } else { wpa_printf(MSG_DEBUG, "No suitable AP found."); #ifdef ANDROID timeout = wpa_s->scan_interval; if (wpas_wps_searching(wpa_s)) { timeout = 5; } else { wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_NO_SUITABLE_AP); } #else timeout = 5; #endif goto req_scan; } return; req_scan: if (wpa_s->scan_res_tried == 1 && wpa_s->conf->ap_scan == 1) { /* * Quick recovery if the initial scan results were not * complete when fetched before the first scan request. */ wpa_s->scan_res_tried++; timeout = 0; } else if (!wpa_supplicant_enabled_networks(wpa_s->conf)) { /* * No networks are enabled; short-circuit request so * we don't wait timeout seconds before transitioning * to INACTIVE state. */ wpa_supplicant_set_state(wpa_s, WPA_INACTIVE); return; } wpa_supplicant_req_scan(wpa_s, timeout, 0); }
int wpas_wps_scan_pbc_overlap(struct wpa_supplicant *wpa_s, struct wpa_bss *selected, struct wpa_ssid *ssid) { const u8 *sel_uuid, *uuid; struct wpabuf *wps_ie; int ret = 0; struct wpa_bss *bss; if (!eap_is_wps_pbc_enrollee(&ssid->eap)) return 0; wpa_printf(MSG_DEBUG, "WPS: Check whether PBC session overlap is " "present in scan results; selected BSSID " MACSTR, MAC2STR(selected->bssid)); /* Make sure that only one AP is in active PBC mode */ wps_ie = wpa_bss_get_vendor_ie_multi(selected, WPS_IE_VENDOR_TYPE); if (wps_ie) { sel_uuid = wps_get_uuid_e(wps_ie); wpa_hexdump(MSG_DEBUG, "WPS: UUID of the selected BSS", sel_uuid, UUID_LEN); } else { wpa_printf(MSG_DEBUG, "WPS: Selected BSS does not include " "WPS IE?!"); sel_uuid = NULL; } dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) { struct wpabuf *ie; if (bss == selected) continue; ie = wpa_bss_get_vendor_ie_multi(bss, WPS_IE_VENDOR_TYPE); if (!ie) continue; if (!wps_is_selected_pbc_registrar(ie)) { wpabuf_free(ie); continue; } wpa_printf(MSG_DEBUG, "WPS: Another BSS in active PBC mode: " MACSTR, MAC2STR(bss->bssid)); uuid = wps_get_uuid_e(ie); wpa_hexdump(MSG_DEBUG, "WPS: UUID of the other BSS", uuid, UUID_LEN); if (sel_uuid == NULL || uuid == NULL || os_memcmp(sel_uuid, uuid, UUID_LEN) != 0) { ret = 1; /* PBC overlap */ wpa_msg(wpa_s, MSG_INFO, "WPS: PBC overlap detected: " MACSTR " and " MACSTR, MAC2STR(selected->bssid), MAC2STR(bss->bssid)); wpabuf_free(ie); break; } /* TODO: verify that this is reasonable dual-band situation */ wpabuf_free(ie); } wpabuf_free(wps_ie); return ret; }