📄 wps_registrar.c
字号:
* PINs matched */ pin = reg->pins; while (pin) { if (pin->wildcard_uuid == 1) { wpa_printf(MSG_DEBUG, "WPS: Found a wildcard " "PIN. Assigned it for this UUID-E"); pin->wildcard_uuid = 2; os_memcpy(pin->uuid, uuid, WPS_UUID_LEN); break; } pin = pin->next; } } if (!pin) return NULL; /* * Lock the PIN to avoid attacks based on concurrent re-use of the PIN * that could otherwise avoid PIN invalidations. */ if (pin->locked) { wpa_printf(MSG_DEBUG, "WPS: Selected PIN locked - do not " "allow concurrent re-use"); return NULL; } *pin_len = pin->pin_len; pin->locked = 1; return pin->pin;}/** * wps_registrar_unlock_pin - Unlock a PIN for a specific UUID-E * @reg: Registrar data from wps_registrar_init() * @uuid: UUID-E * Returns: 0 on success, -1 on failure * * PINs are locked to enforce only one concurrent use. This function unlocks a * PIN to allow it to be used again. If the specified PIN was configured using * a wildcard UUID, it will be removed instead of allowing multiple uses. */int wps_registrar_unlock_pin(struct wps_registrar *reg, const u8 *uuid){ struct wps_uuid_pin *pin; pin = reg->pins; while (pin) { if (os_memcmp(pin->uuid, uuid, WPS_UUID_LEN) == 0) { if (pin->wildcard_uuid == 2) { wpa_printf(MSG_DEBUG, "WPS: Invalidating used " "wildcard PIN"); return wps_registrar_invalidate_pin(reg, uuid); } pin->locked = 0; return 0; } pin = pin->next; } return -1;}static void wps_registrar_stop_pbc(struct wps_registrar *reg){ reg->selected_registrar = 0; reg->pbc = 0; wps_set_ie(reg);}static void wps_registrar_pbc_timeout(void *eloop_ctx, void *timeout_ctx){ struct wps_registrar *reg = eloop_ctx; wpa_printf(MSG_DEBUG, "WPS: PBC timed out - disable PBC mode"); wps_registrar_stop_pbc(reg);}/** * wps_registrar_button_pushed - Notify Registrar that AP button was pushed * @reg: Registrar data from wps_registrar_init() * Returns: 0 on success, -1 on failure * * This function is called on an AP when a push button is pushed to activate * PBC mode. The PBC mode will be stopped after walk time (2 minutes) timeout * or when a PBC registration is completed. */int wps_registrar_button_pushed(struct wps_registrar *reg){ if (wps_registrar_pbc_overlap(reg, NULL, NULL)) { wpa_printf(MSG_DEBUG, "WPS: PBC overlap - do not start PBC " "mode"); return -1; } wpa_printf(MSG_DEBUG, "WPS: Button pushed - PBC mode started"); reg->selected_registrar = 1; reg->pbc = 1; wps_set_ie(reg); eloop_cancel_timeout(wps_registrar_pbc_timeout, reg, NULL); eloop_register_timeout(WPS_PBC_WALK_TIME, 0, wps_registrar_pbc_timeout, reg, NULL); return 0;}static void wps_registrar_pbc_completed(struct wps_registrar *reg){ wpa_printf(MSG_DEBUG, "WPS: PBC completed - stopping PBC mode"); eloop_cancel_timeout(wps_registrar_pbc_timeout, reg, NULL); wps_registrar_stop_pbc(reg);}/** * wps_registrar_probe_req_rx - Notify Registrar of Probe Request * @reg: Registrar data from wps_registrar_init() * @addr: MAC address of the Probe Request sender * @wps_data: WPS IE contents * * This function is called on an AP when a Probe Request with WPS IE is * received. This is used to track PBC mode use and to detect possible overlap * situation with other WPS APs. */void wps_registrar_probe_req_rx(struct wps_registrar *reg, const u8 *addr, const struct wpabuf *wps_data){ struct wps_parse_attr attr; u16 methods; wpa_hexdump_buf(MSG_MSGDUMP, "WPS: Probe Request with WPS data received", wps_data); if (wps_parse_msg(wps_data, &attr) < 0) return; if (!wps_version_supported(attr.version)) { wpa_printf(MSG_DEBUG, "WPS: Unsupported ProbeReq WPS IE " "version 0x%x", attr.version ? *attr.version : 0); return; } if (attr.config_methods == NULL) { wpa_printf(MSG_DEBUG, "WPS: No Config Methods attribute in " "Probe Request"); return; } methods = WPA_GET_BE16(attr.config_methods); if (!(methods & WPS_CONFIG_PUSHBUTTON)) return; /* Not PBC */ wpa_printf(MSG_DEBUG, "WPS: Probe Request for PBC received from " MACSTR, MAC2STR(addr)); wps_registrar_add_pbc_session(reg, addr, attr.uuid_e);}static int wps_cb_new_psk(struct wps_registrar *reg, const u8 *mac_addr, const u8 *psk, size_t psk_len){ if (reg->new_psk_cb == NULL) return 0; return reg->new_psk_cb(reg->cb_ctx, mac_addr, psk, psk_len);}static void wps_cb_pin_needed(struct wps_registrar *reg, const u8 *uuid_e, const struct wps_device_data *dev){ if (reg->pin_needed_cb == NULL) return; reg->pin_needed_cb(reg->cb_ctx, uuid_e, dev);}static void wps_cb_reg_success(struct wps_registrar *reg, const u8 *mac_addr, const u8 *uuid_e){ if (reg->reg_success_cb == NULL) return; reg->reg_success_cb(reg->cb_ctx, mac_addr, uuid_e);}static int wps_cb_set_ie(struct wps_registrar *reg, const struct wpabuf *beacon_ie, const struct wpabuf *probe_resp_ie){ if (reg->set_ie_cb == NULL) return 0; return reg->set_ie_cb(reg->cb_ctx, wpabuf_head(beacon_ie), wpabuf_len(beacon_ie), wpabuf_head(probe_resp_ie), wpabuf_len(probe_resp_ie));}/* Encapsulate WPS IE data with one (or more, if needed) IE headers */static struct wpabuf * wps_ie_encapsulate(struct wpabuf *data){ struct wpabuf *ie; const u8 *pos, *end; ie = wpabuf_alloc(wpabuf_len(data) + 100); if (ie == NULL) { wpabuf_free(data); return NULL; } pos = wpabuf_head(data); end = pos + wpabuf_len(data); while (end > pos) { size_t frag_len = end - pos; if (frag_len > 251) frag_len = 251; wpabuf_put_u8(ie, WLAN_EID_VENDOR_SPECIFIC); wpabuf_put_u8(ie, 4 + frag_len); wpabuf_put_be32(ie, WPS_DEV_OUI_WFA); wpabuf_put_data(ie, pos, frag_len); pos += frag_len; } wpabuf_free(data); return ie;}static int wps_set_ie(struct wps_registrar *reg){ struct wpabuf *beacon; struct wpabuf *probe; int ret; wpa_printf(MSG_DEBUG, "WPS: Build Beacon and Probe Response IEs"); beacon = wpabuf_alloc(300); if (beacon == NULL) return -1; probe = wpabuf_alloc(400); if (probe == NULL) { wpabuf_free(beacon); return -1; } if (wps_build_version(beacon) || wps_build_wps_state(reg->wps, beacon) || wps_build_ap_setup_locked(reg->wps, beacon) || wps_build_selected_registrar(reg, beacon) || wps_build_sel_reg_dev_password_id(reg, beacon) || wps_build_sel_reg_config_methods(reg, beacon) || wps_build_version(probe) || wps_build_wps_state(reg->wps, probe) || wps_build_ap_setup_locked(reg->wps, probe) || wps_build_selected_registrar(reg, probe) || wps_build_sel_reg_dev_password_id(reg, probe) || wps_build_sel_reg_config_methods(reg, probe) || wps_build_resp_type(reg, probe) || wps_build_uuid_e(probe, reg->wps->uuid) || wps_build_device_attrs(®->wps->dev, probe) || wps_build_probe_config_methods(reg, probe) || wps_build_rf_bands(®->wps->dev, probe)) { wpabuf_free(beacon); wpabuf_free(probe); return -1; } beacon = wps_ie_encapsulate(beacon); probe = wps_ie_encapsulate(probe); if (!beacon || !probe) { wpabuf_free(beacon); wpabuf_free(probe); return -1; } if (reg->static_wep_only) { /* * Windows XP and Vista clients can get confused about * EAP-Identity/Request when they probe the network with * EAPOL-Start. In such a case, they may assume the network is * using IEEE 802.1X and prompt user for a certificate while * the correct (non-WPS) behavior would be to ask for the * static WEP key. As a workaround, use Microsoft Provisioning * IE to advertise that legacy 802.1X is not supported. */ const u8 ms_wps[7] = { WLAN_EID_VENDOR_SPECIFIC, 5, /* Microsoft Provisioning IE (00:50:f2:5) */ 0x00, 0x50, 0xf2, 5, 0x00 /* no legacy 802.1X or MS WPS */ }; wpa_printf(MSG_DEBUG, "WPS: Add Microsoft Provisioning IE " "into Beacon/Probe Response frames"); wpabuf_put_data(beacon, ms_wps, sizeof(ms_wps)); wpabuf_put_data(probe, ms_wps, sizeof(ms_wps)); } ret = wps_cb_set_ie(reg, beacon, probe); wpabuf_free(beacon); wpabuf_free(probe); return ret;}static int wps_get_dev_password(struct wps_data *wps){ const u8 *pin; size_t pin_len = 0; os_free(wps->dev_password); wps->dev_password = NULL; if (wps->pbc) { wpa_printf(MSG_DEBUG, "WPS: Use default PIN for PBC"); pin = (const u8 *) "00000000"; pin_len = 8; } else { pin = wps_registrar_get_pin(wps->wps->registrar, wps->uuid_e, &pin_len); } if (pin == NULL) { wpa_printf(MSG_DEBUG, "WPS: No Device Password available for " "the Enrollee"); wps_cb_pin_needed(wps->wps->registrar, wps->uuid_e, &wps->peer_dev); return -1; } wps->dev_password = os_malloc(pin_len); if (wps->dev_password == NULL) return -1; os_memcpy(wps->dev_password, pin, pin_len); wps->dev_password_len = pin_len; return 0;}static int wps_build_uuid_r(struct wps_data *wps, struct wpabuf *msg){ wpa_printf(MSG_DEBUG, "WPS: * UUID-R"); wpabuf_put_be16(msg, ATTR_UUID_R); wpabuf_put_be16(msg, WPS_UUID_LEN); wpabuf_put_data(msg, wps->uuid_r, WPS_UUID_LEN); return 0;}static int wps_build_r_hash(struct wps_data *wps, struct wpabuf *msg){ u8 *hash; const u8 *addr[4]; size_t len[4]; if (os_get_random(wps->snonce, 2 * WPS_SECRET_NONCE_LEN) < 0) return -1; wpa_hexdump(MSG_DEBUG, "WPS: R-S1", wps->snonce, WPS_SECRET_NONCE_LEN); wpa_hexdump(MSG_DEBUG, "WPS: R-S2", wps->snonce + WPS_SECRET_NONCE_LEN, WPS_SECRET_NONCE_LEN); if (wps->dh_pubkey_e == NULL || wps->dh_pubkey_r == NULL) { wpa_printf(MSG_DEBUG, "WPS: DH public keys not available for " "R-Hash derivation"); return -1; } wpa_printf(MSG_DEBUG, "WPS: * R-Hash1"); wpabuf_put_be16(msg, ATTR_R_HASH1); wpabuf_put_be16(msg, SHA256_MAC_LEN); hash = wpabuf_put(msg, SHA256_MAC_LEN); /* R-Hash1 = HMAC_AuthKey(R-S1 || PSK1 || PK_E || PK_R) */ addr[0] = wps->snonce; len[0] = WPS_SECRET_NONCE_LEN; addr[1] = wps->psk1; len[1] = WPS_PSK_LEN; addr[2] = wpabuf_head(wps->dh_pubkey_e); len[2] = wpabuf_len(wps->dh_pubkey_e); addr[3] = wpabuf_head(wps->dh_pubkey_r); len[3] = wpabuf_len(wps->dh_pubkey_r); hmac_sha256_vector(wps->authkey, WPS_AUTHKEY_LEN, 4, addr, len, hash); wpa_hexdump(MSG_DEBUG, "WPS: R-Hash1", hash, SHA256_MAC_LEN); wpa_printf(MSG_DEBUG, "WPS: * R-Hash2"); wpabuf_put_be16(msg, ATTR_R_HASH2); wpabuf_put_be16(msg, SHA256_MAC_LEN); hash = wpabuf_put(msg, SHA256_MAC_LEN); /* R-Hash2 = HMAC_AuthKey(R-S2 || PSK2 || PK_E || PK_R) */ addr[0] = wps->snonce + WPS_SECRET_NONCE_LEN; addr[1] = wps->psk2; hmac_sha256_vector(wps->authkey, WPS_AUTHKEY_LEN, 4, addr, len, hash); wpa_hexdump(MSG_DEBUG, "WPS: R-Hash2", hash, SHA256_MAC_LEN); return 0;}static int wps_build_r_snonce1(struct wps_data *wps, struct wpabuf *msg){ wpa_printf(MSG_DEBUG, "WPS: * R-SNonce1"); wpabuf_put_be16(msg, ATTR_R_SNONCE1); wpabuf_put_be16(msg, WPS_SECRET_NONCE_LEN); wpabuf_put_data(msg, wps->snonce, WPS_SECRET_NONCE_LEN); return 0;}static int wps_build_r_snonce2(struct wps_data *wps, struct wpabuf *msg){ wpa_printf(MSG_DEBUG, "WPS: * R-SNonce2"); wpabuf_put_be16(msg, ATTR_R_SNONCE2); wpabuf_put_be16(msg, WPS_SECRET_NONCE_LEN); wpabuf_put_data(msg, wps->snonce + WPS_SECRET_NONCE_LEN, WPS_SECRET_NONCE_LEN); return 0;}static int wps_build_cred_network_idx(struct wpabuf *msg, struct wps_credential *cred){ wpa_printf(MSG_DEBUG, "WPS: * Network Index"); wpabuf_put_be16(msg, ATTR_NETWORK_INDEX); wpabuf_put_be16(msg, 1); wpabuf_put_u8(msg, 1); return 0;}static int wps_build_cred_ssid(struct wpabuf *msg, struct wps_credential *cred){ wpa_printf(MSG_DEBUG, "WPS: * SSID"); wpabuf_put_be16(msg, ATTR_SSID); wpabuf_put_be16(msg, cred->ssid_len); wpabuf_put_data(msg, cred->ssid, cred->ssid_len); return 0;}static int wps_build_cred_auth_type(struct wpabuf *msg, struct wps_credential *cred){ wpa_printf(MSG_DEBUG, "WPS: * Authentication Type (0x%x)", cred->auth_type); wpabuf_put_be16(msg, ATTR_AUTH_TYPE); wpabuf_put_be16(msg, 2); wpabuf_put_be16(msg, cred->auth_type); return 0;}static int wps_build_cred_encr_type(struct wpabuf *msg, struct wps_credential *cred){ wpa_printf(MSG_DEBUG, "WPS: * Encryption Type (0x%x)", cred->encr_type); wpabuf_put_be16(msg, ATTR_ENCR_TYPE); wpabuf_put_be16(msg, 2); wpabuf_put_be16(msg, cred->encr_type); return 0;}static int wps_build_cred_network_key(struct wpabuf *msg, struct wps_credential *cred){ wpa_printf(MSG_DEBUG, "WPS: * Network Key"); wpabuf_put_be16(msg, ATTR_NETWORK_KEY); wpabuf_put_be16(msg, cred->key_len); wpabuf_put_data(msg, cred->key, cred->key_len); return 0;}static int wps_build_cred_mac_addr(struct wpabuf *msg, struct wps_credential *cred){ wpa_printf(MSG_DEBUG, "WPS: * MAC Address (" MACSTR ")", MAC2STR(cred->mac_addr)); wpabuf_put_be16(msg, ATTR_MAC_ADDR); wpabuf_put_be16(msg, ETH_ALEN); wpabuf_put_data(msg, cred->mac_addr, ETH_ALEN); return 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -