📄 wpa_supplicant.c
字号:
{ struct wpa_blacklist *e, *prev = NULL; e = wpa_s->blacklist; while (e) { if (memcmp(e->bssid, bssid, ETH_ALEN) == 0) { if (prev == NULL) { wpa_s->blacklist = e->next; } else { prev->next = e->next; } wpa_printf(MSG_DEBUG, "Removed BSSID " MACSTR " from " "blacklist", MAC2STR(bssid)); free(e); return 0; } prev = e; e = e->next; } return -1;}/** * wpa_blacklist_clear - Clear the blacklist of all entries * @wpa_s: Pointer to wpa_supplicant data */void wpa_blacklist_clear(struct wpa_supplicant *wpa_s){ struct wpa_blacklist *e, *prev; e = wpa_s->blacklist; wpa_s->blacklist = NULL; while (e) { prev = e; e = e->next; wpa_printf(MSG_DEBUG, "Removed BSSID " MACSTR " from " "blacklist (clear)", MAC2STR(prev->bssid)); free(prev); }}/** * wpa_ssid_txt - Convert SSID to a printable string * @ssid: SSID (32-octet string) * @ssid_len: Length of ssid in octets * Returns: Pointer to a printable string * * This function can be used to convert SSIDs into printable form. In most * cases, SSIDs do not use unprintable characters, but IEEE 802.11 standard * does not limit the used character set, so anything could be used in an SSID. * * This function uses a static buffer, so only one call can be used at the * time, i.e., this is not re-entrant and the returned buffer must be used * before calling this again. */const char * wpa_ssid_txt(u8 *ssid, size_t ssid_len){ static char ssid_txt[MAX_SSID_LEN + 1]; char *pos; if (ssid_len > MAX_SSID_LEN) ssid_len = MAX_SSID_LEN; memcpy(ssid_txt, ssid, ssid_len); ssid_txt[ssid_len] = '\0'; for (pos = ssid_txt; *pos != '\0'; pos++) { if ((u8) *pos < 32 || (u8) *pos >= 127) *pos = '_'; } return ssid_txt;}/** * wpa_supplicant_req_scan - Schedule a scan for neighboring access points * @wpa_s: Pointer to wpa_supplicant data * @sec: Number of seconds after which to scan * @usec: Number of microseconds after which to scan * * This function is used to schedule a scan for neighboring access points after * the specified time. */void wpa_supplicant_req_scan(struct wpa_supplicant *wpa_s, int sec, int usec){ wpa_msg(wpa_s, MSG_DEBUG, "Setting scan request: %d sec %d usec", sec, usec); eloop_cancel_timeout(wpa_supplicant_scan, wpa_s, NULL); eloop_register_timeout(sec, usec, wpa_supplicant_scan, wpa_s, NULL);}/** * wpa_supplicant_cancel_scan - Cancel a scheduled scan request * @wpa_s: Pointer to wpa_supplicant data * * This function is used to cancel a scan request scheduled with * wpa_supplicant_req_scan(). */void wpa_supplicant_cancel_scan(struct wpa_supplicant *wpa_s){ wpa_msg(wpa_s, MSG_DEBUG, "Cancelling scan request"); eloop_cancel_timeout(wpa_supplicant_scan, wpa_s, NULL);}static void wpa_supplicant_timeout(void *eloop_ctx, void *timeout_ctx){ struct wpa_supplicant *wpa_s = eloop_ctx; wpa_msg(wpa_s, MSG_INFO, "Authentication with " MACSTR " timed out.", MAC2STR(wpa_s->bssid)); wpa_blacklist_add(wpa_s, wpa_s->bssid); wpa_sm_notify_disassoc(wpa_s->wpa); wpa_supplicant_disassociate(wpa_s, REASON_DEAUTH_LEAVING); wpa_s->reassociate = 1; wpa_supplicant_req_scan(wpa_s, 0, 0);}/** * wpa_supplicant_req_auth_timeout - Schedule a timeout for authentication * @wpa_s: Pointer to wpa_supplicant data * @sec: Number of seconds after which to time out authentication * @usec: Number of microseconds after which to time out authentication * * This function is used to schedule a timeout for the current authentication * attempt. */void wpa_supplicant_req_auth_timeout(struct wpa_supplicant *wpa_s, int sec, int usec){ if (wpa_s->conf && wpa_s->conf->ap_scan == 0 && wpa_s->driver && strcmp(wpa_s->driver->name, "wired") == 0) return; wpa_msg(wpa_s, MSG_DEBUG, "Setting authentication timeout: %d sec " "%d usec", sec, usec); eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL); eloop_register_timeout(sec, usec, wpa_supplicant_timeout, wpa_s, NULL);}/** * wpa_supplicant_cancel_auth_timeout - Cancel authentication timeout * @wpa_s: Pointer to wpa_supplicant data * * This function is used to cancel authentication timeout scheduled with * wpa_supplicant_req_auth_timeout() and it is called when authentication has * been completed. */void wpa_supplicant_cancel_auth_timeout(struct wpa_supplicant *wpa_s){ wpa_msg(wpa_s, MSG_DEBUG, "Cancelling authentication timeout"); eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL); wpa_blacklist_del(wpa_s, wpa_s->bssid);}/** * wpa_supplicant_initiate_eapol - Configure EAPOL state machine * @wpa_s: Pointer to wpa_supplicant data * * This function is used to configure EAPOL state machine based on the selected * authentication mode. */void wpa_supplicant_initiate_eapol(struct wpa_supplicant *wpa_s){ struct eapol_config eapol_conf; struct wpa_ssid *ssid = wpa_s->current_ssid; if (wpa_s->key_mgmt == WPA_KEY_MGMT_PSK) { eapol_sm_notify_eap_success(wpa_s->eapol, FALSE); eapol_sm_notify_eap_fail(wpa_s->eapol, FALSE); } if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE || wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) eapol_sm_notify_portControl(wpa_s->eapol, ForceAuthorized); else eapol_sm_notify_portControl(wpa_s->eapol, Auto); memset(&eapol_conf, 0, sizeof(eapol_conf)); if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) { eapol_conf.accept_802_1x_keys = 1; eapol_conf.required_keys = 0; if (ssid->eapol_flags & EAPOL_FLAG_REQUIRE_KEY_UNICAST) { eapol_conf.required_keys |= EAPOL_REQUIRE_KEY_UNICAST; } if (ssid->eapol_flags & EAPOL_FLAG_REQUIRE_KEY_BROADCAST) { eapol_conf.required_keys |= EAPOL_REQUIRE_KEY_BROADCAST; } if (wpa_s->conf && wpa_s->driver && strcmp(wpa_s->driver->name, "wired") == 0) { eapol_conf.required_keys = 0; } } eapol_conf.fast_reauth = wpa_s->conf->fast_reauth; eapol_conf.workaround = ssid->eap_workaround; eapol_conf.eap_disabled = wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X && wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA; eapol_sm_notify_config(wpa_s->eapol, ssid, &eapol_conf);}/** * wpa_supplicant_set_non_wpa_policy - Set WPA parameters to non-WPA mode * @wpa_s: Pointer to wpa_supplicant data * @ssid: Configuration data for the network * * This function is used to configure WPA state machine and related parameters * to a mode where WPA is not enabled. This is called as part of the * authentication configuration when the selected network does not use WPA. */void wpa_supplicant_set_non_wpa_policy(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid){ int i; if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_NO_WPA; else wpa_s->key_mgmt = WPA_KEY_MGMT_NONE; wpa_sm_set_ap_wpa_ie(wpa_s->wpa, NULL, 0); wpa_sm_set_ap_rsn_ie(wpa_s->wpa, NULL, 0); wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0); wpa_s->pairwise_cipher = WPA_CIPHER_NONE; wpa_s->group_cipher = WPA_CIPHER_NONE; for (i = 0; i < NUM_WEP_KEYS; i++) { if (ssid->wep_key_len[i] > 5) { wpa_s->pairwise_cipher = WPA_CIPHER_WEP104; wpa_s->group_cipher = WPA_CIPHER_WEP104; break; } else if (ssid->wep_key_len[i] > 0) { wpa_s->pairwise_cipher = WPA_CIPHER_WEP40; wpa_s->group_cipher = WPA_CIPHER_WEP40; break; } } wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt); wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE, wpa_s->pairwise_cipher); wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher); pmksa_cache_clear_current(wpa_s->wpa);}static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s){ scard_deinit(wpa_s->scard); wpa_s->scard = NULL; wpa_sm_set_scard_ctx(wpa_s->wpa, NULL); eapol_sm_register_scard_ctx(wpa_s->eapol, NULL); l2_packet_deinit(wpa_s->l2); wpa_s->l2 = NULL; wpa_supplicant_ctrl_iface_deinit(wpa_s); if (wpa_s->conf != NULL) { wpa_config_free(wpa_s->conf); wpa_s->conf = NULL; } free(wpa_s->confname); wpa_s->confname = NULL; wpa_sm_set_eapol(wpa_s->wpa, NULL); eapol_sm_deinit(wpa_s->eapol); wpa_s->eapol = NULL; rsn_preauth_deinit(wpa_s->wpa); pmksa_candidate_free(wpa_s->wpa); pmksa_cache_free(wpa_s->wpa); wpa_sm_deinit(wpa_s->wpa); wpa_s->wpa = NULL; wpa_blacklist_clear(wpa_s); free(wpa_s->scan_results); wpa_s->scan_results = NULL; wpa_s->num_scan_results = 0; wpa_supplicant_cancel_scan(wpa_s);}/** * wpa_clear_keys - Clear keys configured for the driver * @wpa_s: Pointer to wpa_supplicant data * @addr: Previously used BSSID or %NULL if not available * * This function clears the encryption keys that has been previously configured * for the driver. */void wpa_clear_keys(struct wpa_supplicant *wpa_s, const u8 *addr){ u8 *bcast = (u8 *) "\xff\xff\xff\xff\xff\xff"; if (wpa_s->keys_cleared) { /* Some drivers (e.g., ndiswrapper & NDIS drivers) seem to have * timing issues with keys being cleared just before new keys * are set or just after association or something similar. This * shows up in group key handshake failing often because of the * client not receiving the first encrypted packets correctly. * Skipping some of the extra key clearing steps seems to help * in completing group key handshake more reliably. */ wpa_printf(MSG_DEBUG, "No keys have been configured - " "skip key clearing"); return; } wpa_drv_set_key(wpa_s, WPA_ALG_NONE, bcast, 0, 0, NULL, 0, NULL, 0); wpa_drv_set_key(wpa_s, WPA_ALG_NONE, bcast, 1, 0, NULL, 0, NULL, 0); wpa_drv_set_key(wpa_s, WPA_ALG_NONE, bcast, 2, 0, NULL, 0, NULL, 0); wpa_drv_set_key(wpa_s, WPA_ALG_NONE, bcast, 3, 0, NULL, 0, NULL, 0); if (addr) { wpa_drv_set_key(wpa_s, WPA_ALG_NONE, addr, 0, 0, NULL, 0, NULL, 0); } wpa_s->keys_cleared = 1;}/** * wpa_supplicant_state_txt - Get the connection state name as a text string * @state: State (wpa_state; WPA_*) * Returns: The state name as a printable text string */const char * wpa_supplicant_state_txt(int state){ switch (state) { case WPA_DISCONNECTED: return "DISCONNECTED"; case WPA_INACTIVE: return "INACTIVE"; case WPA_SCANNING: return "SCANNING"; case WPA_ASSOCIATING: return "ASSOCIATING"; case WPA_ASSOCIATED: return "ASSOCIATED"; case WPA_4WAY_HANDSHAKE: return "4WAY_HANDSHAKE"; case WPA_GROUP_HANDSHAKE: return "GROUP_HANDSHAKE"; case WPA_COMPLETED: return "COMPLETED"; default: return "UNKNOWN"; }}/** * wpa_supplicant_set_state - Set current connection state * @wpa_s: Pointer to wpa_supplicant data * @state: The new connection state * * This function is called whenever the connection state changes, e.g., * association is completed for WPA/WPA2 4-Way Handshake is started. */void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s, wpa_states state){ wpa_printf(MSG_DEBUG, "State: %s -> %s", wpa_supplicant_state_txt(wpa_s->wpa_state), wpa_supplicant_state_txt(state)); if (state == WPA_COMPLETED && wpa_s->new_connection) { wpa_s->new_connection = 0; wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_CONNECTED "- Connection to " MACSTR " completed %s", MAC2STR(wpa_s->bssid), wpa_s->reassociated_connection ? "(reauth)" : "(auth)"); wpa_s->reassociated_connection = 1; } else if (state == WPA_DISCONNECTED || state == WPA_ASSOCIATING || state == WPA_ASSOCIATED) { wpa_s->new_connection = 1; } wpa_s->wpa_state = state;}/** * wpa_supplicant_get_state - Get the connection state * @wpa_s: Pointer to wpa_supplicant data * Returns: The current connection state (WPA_*) */wpa_states wpa_supplicant_get_state(struct wpa_supplicant *wpa_s){ return wpa_s->wpa_state;}static void wpa_supplicant_terminate(int sig, void *eloop_ctx, void *signal_ctx){ struct wpa_global *global = eloop_ctx; struct wpa_supplicant *wpa_s; for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) { wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TERMINATING "- signal %d " "received", sig); } eloop_terminate();}/** * wpa_supplicant_reload_configuration - Reload configuration data * @wpa_s: Pointer to wpa_supplicant data * Returns: 0 on success or -1 if configuration parsing failed * * This function can be used to request that the configuration data is reloaded * (e.g., after configuration file change). This function is reloading * configuration only for one interface, so this may need to be called multiple * times if %wpa_supplicant is controlling multiple interfaces and all * interfaces need reconfiguration. */int wpa_supplicant_reload_configuration(struct wpa_supplicant *wpa_s){ struct wpa_config *conf; int reconf_ctrl; if (wpa_s->confname == NULL) return -1; conf = wpa_config_read(wpa_s->confname); if (conf == NULL) { wpa_msg(wpa_s, MSG_ERROR, "Failed to parse the configuration " "file '%s' - exiting", wpa_s->confname); return -1; } reconf_ctrl = !!conf->ctrl_interface != !!wpa_s->conf->ctrl_interface || (conf->ctrl_interface && wpa_s->conf->ctrl_interface && strcmp(conf->ctrl_interface, wpa_s->conf->ctrl_interface) != 0); if (reconf_ctrl) wpa_supplicant_ctrl_iface_deinit(wpa_s); wpa_s->current_ssid = NULL; /* * TODO: should notify EAPOL SM about changes in opensc_engine_path, * pkcs11_engine_path, pkcs11_module_path. */ eapol_sm_notify_config(wpa_s->eapol, NULL, NULL); wpa_sm_set_config(wpa_s->wpa, NULL); wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth); pmksa_cache_notify_reconfig(wpa_s->wpa); rsn_preauth_deinit(wpa_s->wpa); wpa_config_free(wpa_s->conf); wpa_s->conf = conf; if (reconf_ctrl) wpa_supplicant_ctrl_iface_init(wpa_s); wpa_s->reassociate = 1; wpa_supplicant_req_scan(wpa_s, 0, 0);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -