📄 wpa_supplicant.c
字号:
"blacklist", MAC2STR(bssid)); os_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)); os_free(prev); }}/** * 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; const u8 *bssid = wpa_s->bssid; if (os_memcmp(bssid, "\x00\x00\x00\x00\x00\x00", ETH_ALEN) == 0) bssid = wpa_s->pending_bssid; wpa_msg(wpa_s, MSG_INFO, "Authentication with " MACSTR " timed out.", MAC2STR(bssid)); wpa_blacklist_add(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 && os_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){#ifdef IEEE8021X_EAPOL 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); os_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 && os_strcmp(wpa_s->driver->name, "wired") == 0) { eapol_conf.required_keys = 0; } } if (wpa_s->conf) 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);#endif /* IEEE8021X_EAPOL */}/** * 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; wpa_s->mgmt_group_cipher = 0; 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);#ifdef CONFIG_IEEE80211W wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP, wpa_s->mgmt_group_cipher);#endif /* CONFIG_IEEE80211W */ 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; if (wpa_s->l2_br) { l2_packet_deinit(wpa_s->l2_br); wpa_s->l2_br = NULL; } if (wpa_s->ctrl_iface) { wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface); wpa_s->ctrl_iface = NULL; } if (wpa_s->conf != NULL) { wpa_config_free(wpa_s->conf); wpa_s->conf = NULL; } os_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); wpa_sm_deinit(wpa_s->wpa); wpa_s->wpa = NULL; wpa_blacklist_clear(wpa_s); os_free(wpa_s->scan_results); wpa_s->scan_results = NULL; wpa_s->num_scan_results = 0; wpa_supplicant_cancel_scan(wpa_s); wpa_supplicant_cancel_auth_timeout(wpa_s); ieee80211_sta_deinit(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; } /* MLME-DELETEKEYS.request */ 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); /* MLME-SETPROTECTION.request(None) */ wpa_drv_mlme_setprotection( wpa_s, addr, MLME_SETPROTECTION_PROTECT_TYPE_NONE, MLME_SETPROTECTION_KEY_TYPE_PAIRWISE); } 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)); wpa_supplicant_dbus_notify_state_change(wpa_s, state, wpa_s->wpa_state); if (state == WPA_COMPLETED && wpa_s->new_connection) {#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG) struct wpa_ssid *ssid = wpa_s->current_ssid; wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_CONNECTED "- Connection to " MACSTR " completed %s [id=%d id_str=%s]", MAC2STR(wpa_s->bssid), wpa_s->reassociated_connection ? "(reauth)" : "(auth)", ssid ? ssid->id : -1, ssid && ssid->id_str ? ssid->id_str : "");#endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */ wpa_s->new_connection = 0; wpa_s->reassociated_connection = 1; wpa_drv_set_operstate(wpa_s, 1); } else if (state == WPA_DISCONNECTED || state == WPA_ASSOCIATING || state == WPA_ASSOCIATED) { wpa_s->new_connection = 1; wpa_drv_set_operstate(wpa_s, 0); } 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();}static void wpa_supplicant_clear_status(struct wpa_supplicant *wpa_s){ wpa_s->pairwise_cipher = 0; wpa_s->group_cipher = 0; wpa_s->mgmt_group_cipher = 0; wpa_s->key_mgmt = 0; wpa_s->wpa_state = WPA_DISCONNECTED;}/** * 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 && os_strcmp(conf->ctrl_interface, wpa_s->conf->ctrl_interface) != 0); if (reconf_ctrl && wpa_s->ctrl_iface) { wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface); wpa_s->ctrl_iface = NULL; } eapol_sm_invalidate_cached_session(wpa_s->eapol); wpa_s->current_ssid = NULL; /* * TODO: should notify EAPOL SM about changes in opensc_engine_path, * pkcs11_engine_path, pkcs11_module_path.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -