int rsn_preauth_init(struct wpa_supplicant *wpa_s, u8 *dst) { struct eapol_config eapol_conf; struct eapol_ctx *ctx; if (wpa_s->preauth_eapol) return -1; wpa_msg(wpa_s, MSG_DEBUG, "RSN: starting pre-authentication with " MACSTR, MAC2STR(dst)); wpa_s->l2_preauth = l2_packet_init(wpa_s->ifname, wpa_drv_get_mac_addr(wpa_s), ETH_P_RSN_PREAUTH, rsn_preauth_receive, wpa_s); if (wpa_s->l2_preauth == NULL) { wpa_printf(MSG_WARNING, "RSN: Failed to initialize L2 packet " "processing for pre-authentication"); return -2; } ctx = malloc(sizeof(*ctx)); if (ctx == NULL) { wpa_printf(MSG_WARNING, "Failed to allocate EAPOL context."); return -4; } memset(ctx, 0, sizeof(*ctx)); ctx->ctx = wpa_s; ctx->preauth = 1; ctx->cb = rsn_preauth_eapol_cb; ctx->cb_ctx = wpa_s; ctx->scard_ctx = wpa_s->scard; ctx->eapol_done_cb = wpa_supplicant_notify_eapol_done; ctx->eapol_send = wpa_eapol_send_preauth; wpa_s->preauth_eapol = eapol_sm_init(ctx); if (wpa_s->preauth_eapol == NULL) { free(ctx); wpa_printf(MSG_WARNING, "RSN: Failed to initialize EAPOL " "state machines for pre-authentication"); return -3; } memset(&eapol_conf, 0, sizeof(eapol_conf)); eapol_conf.accept_802_1x_keys = 0; eapol_conf.required_keys = 0; eapol_conf.fast_reauth = wpa_s->conf->fast_reauth; if (wpa_s->current_ssid) eapol_conf.workaround = wpa_s->current_ssid->eap_workaround; eapol_sm_notify_config(wpa_s->preauth_eapol, wpa_s->current_ssid, &eapol_conf); memcpy(wpa_s->preauth_bssid, dst, ETH_ALEN); eapol_sm_notify_portValid(wpa_s->preauth_eapol, TRUE); /* 802.1X::portControl = Auto */ eapol_sm_notify_portEnabled(wpa_s->preauth_eapol, TRUE); eloop_register_timeout(60, 0, rsn_preauth_timeout, wpa_s, NULL); return 0; }
void wpa_supplicant_mark_disassoc(struct wpa_supplicant *wpa_s) { wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED); os_memset(wpa_s->bssid, 0, ETH_ALEN); os_memset(wpa_s->pending_bssid, 0, ETH_ALEN); eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE); eapol_sm_notify_portValid(wpa_s->eapol, FALSE); if (wpa_s->key_mgmt == WPA_KEY_MGMT_PSK) eapol_sm_notify_eap_success(wpa_s->eapol, FALSE); }
static int test_eapol(struct eapol_test_data *e, struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid) { struct eapol_config eapol_conf; struct eapol_ctx *ctx; ctx = os_zalloc(sizeof(*ctx)); if (ctx == NULL) { printf("Failed to allocate EAPOL context.\n"); return -1; } ctx->ctx = e; ctx->msg_ctx = wpa_s; ctx->scard_ctx = wpa_s->scard; ctx->cb = eapol_sm_cb; ctx->cb_ctx = e; ctx->eapol_send_ctx = wpa_s; ctx->preauth = 0; ctx->eapol_done_cb = eapol_test_eapol_done_cb; ctx->eapol_send = eapol_test_eapol_send; ctx->set_config_blob = eapol_test_set_config_blob; ctx->get_config_blob = eapol_test_get_config_blob; ctx->opensc_engine_path = wpa_s->conf->opensc_engine_path; ctx->pkcs11_engine_path = wpa_s->conf->pkcs11_engine_path; ctx->pkcs11_module_path = wpa_s->conf->pkcs11_module_path; ctx->openssl_ciphers = wpa_s->conf->openssl_ciphers; ctx->eap_param_needed = eapol_test_eap_param_needed; ctx->cert_cb = eapol_test_cert_cb; ctx->cert_in_cb = 1; ctx->set_anon_id = eapol_test_set_anon_id; wpa_s->eapol = eapol_sm_init(ctx); if (wpa_s->eapol == NULL) { os_free(ctx); printf("Failed to initialize EAPOL state machines.\n"); return -1; } wpa_s->current_ssid = ssid; os_memset(&eapol_conf, 0, sizeof(eapol_conf)); eapol_conf.accept_802_1x_keys = 1; eapol_conf.required_keys = 0; eapol_conf.fast_reauth = wpa_s->conf->fast_reauth; eapol_conf.workaround = ssid->eap_workaround; eapol_conf.external_sim = wpa_s->conf->external_sim; eapol_sm_notify_config(wpa_s->eapol, &ssid->eap, &eapol_conf); eapol_sm_register_scard_ctx(wpa_s->eapol, wpa_s->scard); eapol_sm_notify_portValid(wpa_s->eapol, FALSE); /* 802.1X::portControl = Auto */ eapol_sm_notify_portEnabled(wpa_s->eapol, TRUE); return 0; }
void wpa_supplicant_mark_disassoc(struct wpa_supplicant *wpa_s) { wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED); os_memset(wpa_s->bssid, 0, ETH_ALEN); os_memset(wpa_s->pending_bssid, 0, ETH_ALEN); eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE); eapol_sm_notify_portValid(wpa_s->eapol, FALSE); if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt)) eapol_sm_notify_eap_success(wpa_s->eapol, FALSE); wpa_s->ap_ies_from_associnfo = 0; }
void wpa_supplicant_mark_disassoc(struct wpa_supplicant *wpa_s) { #if ICS_LEGACY_WLAN_SUPPORT if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) return; #endif wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED); wpa_s->conf->ap_scan = DEFAULT_AP_SCAN; os_memset(wpa_s->bssid, 0, ETH_ALEN); os_memset(wpa_s->pending_bssid, 0, ETH_ALEN); eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE); eapol_sm_notify_portValid(wpa_s->eapol, FALSE); if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt)) eapol_sm_notify_eap_success(wpa_s->eapol, FALSE); wpa_s->ap_ies_from_associnfo = 0; }
void wpa_supplicant_mark_disassoc(struct wpa_supplicant *wpa_s) { int bssid_changed; wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED); bssid_changed = !is_zero_ether_addr(wpa_s->bssid); os_memset(wpa_s->bssid, 0, ETH_ALEN); os_memset(wpa_s->pending_bssid, 0, ETH_ALEN); wpa_s->current_bss = NULL; if (bssid_changed) wpas_notify_bssid_changed(wpa_s); eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE); eapol_sm_notify_portValid(wpa_s->eapol, FALSE); if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt)) eapol_sm_notify_eap_success(wpa_s->eapol, FALSE); wpa_s->ap_ies_from_associnfo = 0; }
static int test_eapol(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid) { struct eapol_config eapol_conf; struct eapol_ctx *ctx; ctx = malloc(sizeof(*ctx)); if (ctx == NULL) { printf("Failed to allocate EAPOL context.\n"); return -1; } memset(ctx, 0, sizeof(*ctx)); ctx->ctx = wpa_s; ctx->msg_ctx = wpa_s; ctx->scard_ctx = wpa_s->scard; ctx->cb = eapol_sm_cb; ctx->cb_ctx = wpa_s; ctx->preauth = 0; ctx->eapol_done_cb = eapol_test_eapol_done_cb; ctx->eapol_send = eapol_test_eapol_send; wpa_s->eapol = eapol_sm_init(ctx); if (wpa_s->eapol == NULL) { free(ctx); printf("Failed to initialize EAPOL state machines.\n"); return -1; } wpa_s->current_ssid = ssid; memset(&eapol_conf, 0, sizeof(eapol_conf)); eapol_conf.accept_802_1x_keys = 1; eapol_conf.required_keys = 0; eapol_conf.fast_reauth = wpa_s->conf->fast_reauth; eapol_conf.workaround = ssid->eap_workaround; eapol_sm_notify_config(wpa_s->eapol, ssid, &eapol_conf); eapol_sm_register_scard_ctx(wpa_s->eapol, wpa_s->scard); eapol_sm_notify_portValid(wpa_s->eapol, FALSE); /* 802.1X::portControl = Auto */ eapol_sm_notify_portEnabled(wpa_s->eapol, TRUE); return 0; }
static void wpa_supplicant_key_neg_complete(struct wpa_sm *sm, const u8 *addr, int secure) { wpa_msg(sm->ctx->msg_ctx, MSG_INFO, "WPA: Key negotiation completed with " MACSTR " [PTK=%s GTK=%s]", MAC2STR(addr), wpa_cipher_txt(sm->pairwise_cipher), wpa_cipher_txt(sm->group_cipher)); wpa_sm_cancel_auth_timeout(sm); wpa_sm_set_state(sm, WPA_COMPLETED); if (secure) { wpa_sm_mlme_setprotection( sm, addr, MLME_SETPROTECTION_PROTECT_TYPE_RX_TX, MLME_SETPROTECTION_KEY_TYPE_PAIRWISE); eapol_sm_notify_portValid(sm->eapol, TRUE); if (wpa_key_mgmt_wpa_psk(sm->key_mgmt)) eapol_sm_notify_eap_success(sm->eapol, TRUE); /* * Start preauthentication after a short wait to avoid a * possible race condition between the data receive and key * configuration after the 4-Way Handshake. This increases the * likelyhood of the first preauth EAPOL-Start frame getting to * the target AP. */ eloop_register_timeout(1, 0, wpa_sm_start_preauth, sm, NULL); } if (sm->cur_pmksa && sm->cur_pmksa->opportunistic) { wpa_printf(MSG_DEBUG, "RSN: Authenticator accepted " "opportunistic PMKSA entry - marking it valid"); sm->cur_pmksa->opportunistic = 0; } #ifdef CONFIG_IEEE80211R if (wpa_key_mgmt_ft(sm->key_mgmt)) { /* Prepare for the next transition */ wpa_ft_prepare_auth_request(sm, NULL); } #endif /* CONFIG_IEEE80211R */ }
static void wpa_supplicant_event_assoc(struct wpa_supplicant *wpa_s, union wpa_event_data *data) { u8 bssid[ETH_ALEN]; int ft_completed = wpa_ft_is_completed(wpa_s->wpa); if (data) wpa_supplicant_event_associnfo(wpa_s, data); wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATED); if (wpa_s->use_client_mlme) os_memcpy(bssid, wpa_s->bssid, ETH_ALEN); if (wpa_s->use_client_mlme || (wpa_drv_get_bssid(wpa_s, bssid) >= 0 && os_memcmp(bssid, wpa_s->bssid, ETH_ALEN) != 0)) { wpa_msg(wpa_s, MSG_DEBUG, "Associated to a new BSS: BSSID=" MACSTR, MAC2STR(bssid)); os_memcpy(wpa_s->bssid, bssid, ETH_ALEN); os_memset(wpa_s->pending_bssid, 0, ETH_ALEN); if (wpa_supplicant_dynamic_keys(wpa_s) && !ft_completed) { wpa_clear_keys(wpa_s, bssid); } if (wpa_supplicant_select_config(wpa_s) < 0) { wpa_supplicant_disassociate( wpa_s, WLAN_REASON_DEAUTH_LEAVING); return; } } wpa_msg(wpa_s, MSG_INFO, "Associated with " MACSTR, MAC2STR(bssid)); if (wpa_s->current_ssid) { /* When using scanning (ap_scan=1), SIM PC/SC interface can be * initialized before association, but for other modes, * initialize PC/SC here, if the current configuration needs * smartcard or SIM/USIM. */ wpa_supplicant_scard_init(wpa_s, wpa_s->current_ssid); } wpa_sm_notify_assoc(wpa_s->wpa, bssid); l2_packet_notify_auth_start(wpa_s->l2); /* * Set portEnabled first to FALSE in order to get EAP state machine out * of the SUCCESS state and eapSuccess cleared. Without this, EAPOL PAE * state machine may transit to AUTHENTICATING state based on obsolete * eapSuccess and then trigger BE_AUTH to SUCCESS and PAE to * AUTHENTICATED without ever giving chance to EAP state machine to * reset the state. */ if (!ft_completed) { eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE); eapol_sm_notify_portValid(wpa_s->eapol, FALSE); } if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) || ft_completed) eapol_sm_notify_eap_success(wpa_s->eapol, FALSE); /* 802.1X::portControl = Auto */ eapol_sm_notify_portEnabled(wpa_s->eapol, TRUE); wpa_s->eapol_received = 0; if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE || wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) { wpa_supplicant_cancel_auth_timeout(wpa_s); wpa_supplicant_set_state(wpa_s, WPA_COMPLETED); } else if (!ft_completed) { /* Timeout for receiving the first EAPOL packet */ wpa_supplicant_req_auth_timeout(wpa_s, 10, 0); } wpa_supplicant_cancel_scan(wpa_s); if (wpa_s->driver_4way_handshake && wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt)) { /* * We are done; the driver will take care of RSN 4-way * handshake. */ wpa_supplicant_cancel_auth_timeout(wpa_s); wpa_supplicant_set_state(wpa_s, WPA_COMPLETED); eapol_sm_notify_portValid(wpa_s->eapol, TRUE); eapol_sm_notify_eap_success(wpa_s->eapol, TRUE); } if (wpa_s->pending_eapol_rx) { struct os_time now, age; os_get_time(&now); os_time_sub(&now, &wpa_s->pending_eapol_rx_time, &age); if (age.sec == 0 && age.usec < 100000 && os_memcmp(wpa_s->pending_eapol_rx_src, bssid, ETH_ALEN) == 0) { wpa_printf(MSG_DEBUG, "Process pending EAPOL frame " "that was received just before association " "notification"); wpa_supplicant_rx_eapol( wpa_s, wpa_s->pending_eapol_rx_src, wpabuf_head(wpa_s->pending_eapol_rx), wpabuf_len(wpa_s->pending_eapol_rx)); } wpabuf_free(wpa_s->pending_eapol_rx); wpa_s->pending_eapol_rx = NULL; } }
static void wpa_supplicant_event_assoc(struct wpa_supplicant *wpa_s, union wpa_event_data *data) { u8 bssid[ETH_ALEN]; int ft_completed = wpa_ft_is_completed(wpa_s->wpa); if (data) wpa_supplicant_event_associnfo(wpa_s, data); #ifdef CONFIG_WAPI_SUPPORT if (wpa_s->key_mgmt == WAPI_KEY_MGMT_CERT || wpa_s->key_mgmt == WAPI_KEY_MGMT_PSK) { static int loop = 0; /* To avoiding state LOOP case, otherwise HAL will disable interface*/ /*[ALPS00127420][Wi-Fi] Can not auto-reconnect WAPI-PSK AP after power off--> power on WAPI AP*/ if((wpa_s->wpa_state == WPA_4WAY_HANDSHAKE || wpa_s->wpa_state == WPA_GROUP_HANDSHAKE) && (loop >= 1 && loop <= 20)){ /*dont set state*/ wpa_printf(MSG_INFO, "%s: [Loop = %d] dont set_state", __FUNCTION__, loop); loop++; }else{ wpa_printf(MSG_INFO, "%s: [Loop = %d] set_state", __FUNCTION__, loop); loop=1; wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATED); } } else { wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATED); } #else wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATED); #endif if (wpa_s->use_client_mlme) os_memcpy(bssid, wpa_s->bssid, ETH_ALEN); if (wpa_s->use_client_mlme || (wpa_drv_get_bssid(wpa_s, bssid) >= 0 && os_memcmp(bssid, wpa_s->bssid, ETH_ALEN) != 0)) { wpa_msg(wpa_s, MSG_DEBUG, "Associated to a new BSS: BSSID=" MACSTR, MAC2STR(bssid)); os_memcpy(wpa_s->bssid, bssid, ETH_ALEN); os_memset(wpa_s->pending_bssid, 0, ETH_ALEN); if (wpa_supplicant_dynamic_keys(wpa_s) && !ft_completed) { wpa_clear_keys(wpa_s, bssid); } if (wpa_supplicant_select_config(wpa_s) < 0) { wpa_supplicant_disassociate( wpa_s, WLAN_REASON_DEAUTH_LEAVING); return; } } wpa_msg(wpa_s, MSG_INFO, "associated with " MACSTR, MAC2STR(bssid)); #ifdef CONFIG_WAPI_SUPPORT if (wpa_s->key_mgmt == WAPI_KEY_MGMT_CERT || wpa_s->key_mgmt == WAPI_KEY_MGMT_PSK) { MAC_ADDRESS bssid_s; MAC_ADDRESS own_s; /* stop WPA and other time out use WAPI time only */ wpa_supplicant_cancel_auth_timeout(wpa_s); wpa_printf(MSG_DEBUG,"[Debug-WAPI] AP MAC address "MACSTR" Own MAC address"MACSTR"!!", MAC2STR(wpa_s->bssid), MAC2STR(wpa_s->own_addr)); if (is_zero_ether_addr(wpa_s->bssid)){ wpa_printf(MSG_DEBUG,"[Debug-WAPI] Not to set msg to WAPI SM\n"); /*Have been disassociated with the WAPI AP*/ return; } memcpy(bssid_s.v, wpa_s->bssid, sizeof(bssid_s.v)); memcpy(own_s.v, wpa_s->own_addr, sizeof(own_s.v)); wpa_printf(MSG_DEBUG,"[Debug-WAPI ^_^!!] Ready send associate complete evert to WAPI Modules!!!"); wapi_set_msg(CONN_ASSOC, &bssid_s, &own_s, wpa_s->bss_wapi_ie , wpa_s->bss_wapi_ie_len); return; } #endif if (wpa_s->current_ssid) { /* When using scanning (ap_scan=1), SIM PC/SC interface can be * initialized before association, but for other modes, * initialize PC/SC here, if the current configuration needs * smartcard or SIM/USIM. */ wpa_supplicant_scard_init(wpa_s, wpa_s->current_ssid); } wpa_sm_notify_assoc(wpa_s->wpa, bssid); l2_packet_notify_auth_start(wpa_s->l2); /* * Set portEnabled first to FALSE in order to get EAP state machine out * of the SUCCESS state and eapSuccess cleared. Without this, EAPOL PAE * state machine may transit to AUTHENTICATING state based on obsolete * eapSuccess and then trigger BE_AUTH to SUCCESS and PAE to * AUTHENTICATED without ever giving chance to EAP state machine to * reset the state. */ if (!ft_completed) { eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE); eapol_sm_notify_portValid(wpa_s->eapol, FALSE); } if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) || ft_completed) eapol_sm_notify_eap_success(wpa_s->eapol, FALSE); /* 802.1X::portControl = Auto */ eapol_sm_notify_portEnabled(wpa_s->eapol, TRUE); wpa_s->eapol_received = 0; if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE || wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) { wpa_supplicant_cancel_auth_timeout(wpa_s); wpa_supplicant_set_state(wpa_s, WPA_COMPLETED); } else if (!ft_completed) { /* Timeout for receiving the first EAPOL packet */ wpa_supplicant_req_auth_timeout(wpa_s, 10, 0); } wpa_supplicant_cancel_scan(wpa_s); if (wpa_s->driver_4way_handshake && wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt)) { /* * We are done; the driver will take care of RSN 4-way * handshake. */ wpa_supplicant_cancel_auth_timeout(wpa_s); wpa_supplicant_set_state(wpa_s, WPA_COMPLETED); eapol_sm_notify_portValid(wpa_s->eapol, TRUE); eapol_sm_notify_eap_success(wpa_s->eapol, TRUE); } if (wpa_s->pending_eapol_rx) { struct os_time now, age; os_get_time(&now); os_time_sub(&now, &wpa_s->pending_eapol_rx_time, &age); if (age.sec == 0 && age.usec < 100000 && os_memcmp(wpa_s->pending_eapol_rx_src, bssid, ETH_ALEN) == 0) { wpa_printf(MSG_DEBUG, "Process pending EAPOL frame " "that was received just before association " "notification"); wpa_supplicant_rx_eapol( wpa_s, wpa_s->pending_eapol_rx_src, wpabuf_head(wpa_s->pending_eapol_rx), wpabuf_len(wpa_s->pending_eapol_rx)); } wpabuf_free(wpa_s->pending_eapol_rx); wpa_s->pending_eapol_rx = NULL; } }
static void wpa_supplicant_event_assoc(struct wpa_supplicant *wpa_s, union wpa_event_data *data) { u8 bssid[ETH_ALEN]; int ft_completed; int bssid_changed; struct wpa_driver_capa capa; #ifdef CONFIG_AP if (wpa_s->ap_iface) { hostapd_notif_assoc(wpa_s->ap_iface->bss[0], data->assoc_info.addr, data->assoc_info.req_ies, data->assoc_info.req_ies_len); return; } #endif /* CONFIG_AP */ ft_completed = wpa_ft_is_completed(wpa_s->wpa); if (data && wpa_supplicant_event_associnfo(wpa_s, data) < 0) return; wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATED); if (wpa_drv_get_bssid(wpa_s, bssid) >= 0 && os_memcmp(bssid, wpa_s->bssid, ETH_ALEN) != 0) { wpa_msg(wpa_s, MSG_DEBUG, "Associated to a new BSS: BSSID=" MACSTR, MAC2STR(bssid)); bssid_changed = os_memcmp(wpa_s->bssid, bssid, ETH_ALEN); os_memcpy(wpa_s->bssid, bssid, ETH_ALEN); os_memset(wpa_s->pending_bssid, 0, ETH_ALEN); if (bssid_changed) wpas_notify_bssid_changed(wpa_s); if (wpa_supplicant_dynamic_keys(wpa_s) && !ft_completed) { wpa_clear_keys(wpa_s, bssid); } if (wpa_supplicant_select_config(wpa_s) < 0) { wpa_supplicant_disassociate( wpa_s, WLAN_REASON_DEAUTH_LEAVING); return; } if (wpa_s->current_ssid) { struct wpa_bss *bss = NULL; struct wpa_ssid *ssid = wpa_s->current_ssid; if (ssid->ssid_len > 0) bss = wpa_bss_get(wpa_s, bssid, ssid->ssid, ssid->ssid_len); if (!bss) bss = wpa_bss_get_bssid(wpa_s, bssid); if (bss) wpa_s->current_bss = bss; } } #ifdef CONFIG_SME os_memcpy(wpa_s->sme.prev_bssid, bssid, ETH_ALEN); wpa_s->sme.prev_bssid_set = 1; #endif /* CONFIG_SME */ wpa_msg(wpa_s, MSG_INFO, "Associated with " MACSTR, MAC2STR(bssid)); if (wpa_s->current_ssid) { /* When using scanning (ap_scan=1), SIM PC/SC interface can be * initialized before association, but for other modes, * initialize PC/SC here, if the current configuration needs * smartcard or SIM/USIM. */ wpa_supplicant_scard_init(wpa_s, wpa_s->current_ssid); } wpa_sm_notify_assoc(wpa_s->wpa, bssid); if (wpa_s->l2) l2_packet_notify_auth_start(wpa_s->l2); /* * Set portEnabled first to FALSE in order to get EAP state machine out * of the SUCCESS state and eapSuccess cleared. Without this, EAPOL PAE * state machine may transit to AUTHENTICATING state based on obsolete * eapSuccess and then trigger BE_AUTH to SUCCESS and PAE to * AUTHENTICATED without ever giving chance to EAP state machine to * reset the state. */ if (!ft_completed) { eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE); eapol_sm_notify_portValid(wpa_s->eapol, FALSE); } if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) || ft_completed) eapol_sm_notify_eap_success(wpa_s->eapol, FALSE); /* 802.1X::portControl = Auto */ eapol_sm_notify_portEnabled(wpa_s->eapol, TRUE); wpa_s->eapol_received = 0; if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE || wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE || (wpa_s->current_ssid && wpa_s->current_ssid->mode == IEEE80211_MODE_IBSS)) { wpa_supplicant_cancel_auth_timeout(wpa_s); wpa_supplicant_set_state(wpa_s, WPA_COMPLETED); } else if (!ft_completed) { /* Timeout for receiving the first EAPOL packet */ wpa_supplicant_req_auth_timeout(wpa_s, 10, 0); } wpa_supplicant_cancel_scan(wpa_s); if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) && wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt)) { /* * We are done; the driver will take care of RSN 4-way * handshake. */ wpa_supplicant_cancel_auth_timeout(wpa_s); wpa_supplicant_set_state(wpa_s, WPA_COMPLETED); eapol_sm_notify_portValid(wpa_s->eapol, TRUE); eapol_sm_notify_eap_success(wpa_s->eapol, TRUE); } if (wpa_s->pending_eapol_rx) { struct os_time now, age; os_get_time(&now); os_time_sub(&now, &wpa_s->pending_eapol_rx_time, &age); if (age.sec == 0 && age.usec < 100000 && os_memcmp(wpa_s->pending_eapol_rx_src, bssid, ETH_ALEN) == 0) { wpa_printf(MSG_DEBUG, "Process pending EAPOL frame " "that was received just before association " "notification"); wpa_supplicant_rx_eapol( wpa_s, wpa_s->pending_eapol_rx_src, wpabuf_head(wpa_s->pending_eapol_rx), wpabuf_len(wpa_s->pending_eapol_rx)); } wpabuf_free(wpa_s->pending_eapol_rx); wpa_s->pending_eapol_rx = NULL; } if ((wpa_s->key_mgmt == WPA_KEY_MGMT_NONE || wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) && wpa_s->current_ssid && wpa_drv_get_capa(wpa_s, &capa) == 0 && capa.flags & WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC_DONE) { /* Set static WEP keys again */ wpa_set_wep_keys(wpa_s, wpa_s->current_ssid); } }
/** * rsn_preauth_init - Start new RSN pre-authentication * @sm: Pointer to WPA state machine data from wpa_sm_init() * @dst: Authenticator address (BSSID) with which to preauthenticate * @eap_conf: Current EAP configuration * Returns: 0 on success, -1 on another pre-authentication is in progress, * -2 on layer 2 packet initialization failure, -3 on EAPOL state machine * initialization failure, -4 on memory allocation failure * * This function request an RSN pre-authentication with a given destination * address. This is usually called for PMKSA candidates found from scan results * or from driver reports. In addition, ctrl_iface PREAUTH command can trigger * pre-authentication. */ int rsn_preauth_init(struct wpa_sm *sm, const u8 *dst, struct eap_peer_config *eap_conf) { struct eapol_config eapol_conf; struct eapol_ctx *ctx; if (sm->preauth_eapol) return -1; wpa_msg(sm->ctx->ctx, MSG_DEBUG, "RSN: starting pre-authentication " "with " MACSTR, MAC2STR(dst)); sm->l2_preauth = l2_packet_init(sm->ifname, sm->own_addr, ETH_P_RSN_PREAUTH, rsn_preauth_receive, sm, 0); if (sm->l2_preauth == NULL) { wpa_printf(MSG_WARNING, "RSN: Failed to initialize L2 packet " "processing for pre-authentication"); return -2; } if (sm->bridge_ifname) { sm->l2_preauth_br = l2_packet_init(sm->bridge_ifname, sm->own_addr, ETH_P_RSN_PREAUTH, rsn_preauth_receive, sm, 0); if (sm->l2_preauth_br == NULL) { wpa_printf(MSG_WARNING, "RSN: Failed to initialize L2 " "packet processing (bridge) for " "pre-authentication"); return -2; } } ctx = os_zalloc(sizeof(*ctx)); if (ctx == NULL) { wpa_printf(MSG_WARNING, "Failed to allocate EAPOL context."); return -4; } ctx->ctx = sm->ctx->ctx; ctx->msg_ctx = sm->ctx->ctx; ctx->preauth = 1; ctx->cb = rsn_preauth_eapol_cb; ctx->cb_ctx = sm; ctx->scard_ctx = sm->scard_ctx; ctx->eapol_send = rsn_preauth_eapol_send; ctx->eapol_send_ctx = sm; ctx->set_config_blob = sm->ctx->set_config_blob; ctx->get_config_blob = sm->ctx->get_config_blob; sm->preauth_eapol = eapol_sm_init(ctx); if (sm->preauth_eapol == NULL) { os_free(ctx); wpa_printf(MSG_WARNING, "RSN: Failed to initialize EAPOL " "state machines for pre-authentication"); return -3; } os_memset(&eapol_conf, 0, sizeof(eapol_conf)); eapol_conf.accept_802_1x_keys = 0; eapol_conf.required_keys = 0; eapol_conf.fast_reauth = sm->fast_reauth; eapol_conf.workaround = sm->eap_workaround; eapol_sm_notify_config(sm->preauth_eapol, eap_conf, &eapol_conf); /* * Use a shorter startPeriod with preauthentication since the first * preauth EAPOL-Start frame may end up being dropped due to race * condition in the AP between the data receive and key configuration * after the 4-Way Handshake. */ eapol_sm_configure(sm->preauth_eapol, -1, -1, 5, 6); os_memcpy(sm->preauth_bssid, dst, ETH_ALEN); eapol_sm_notify_portValid(sm->preauth_eapol, TRUE); /* 802.1X::portControl = Auto */ eapol_sm_notify_portEnabled(sm->preauth_eapol, TRUE); eloop_register_timeout(sm->dot11RSNAConfigSATimeout, 0, rsn_preauth_timeout, sm, NULL); return 0; }
static void wpa_supplicant_process_3_of_4(struct wpa_sm *sm, const struct wpa_eapol_key *key, u16 ver) { u16 key_info, keylen, len; const u8 *pos; struct wpa_eapol_ie_parse ie; wpa_sm_set_state(sm, WPA_4WAY_HANDSHAKE); wpa_printf(MSG_DEBUG, "WPA: RX message 3 of 4-Way Handshake from " MACSTR " (ver=%d)", MAC2STR(sm->bssid), ver); key_info = WPA_GET_BE16(key->key_info); pos = (const u8 *) (key + 1); len = WPA_GET_BE16(key->key_data_length); wpa_hexdump(MSG_DEBUG, "WPA: IE KeyData", pos, len); wpa_supplicant_parse_ies(pos, len, &ie); if (ie.gtk && !(key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) { wpa_printf(MSG_WARNING, "WPA: GTK IE in unencrypted key data"); goto failed; } #ifdef CONFIG_IEEE80211W if (ie.igtk && !(key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) { wpa_printf(MSG_WARNING, "WPA: IGTK KDE in unencrypted key " "data"); goto failed; } if (ie.igtk && ie.igtk_len != sizeof(struct wpa_igtk_kde)) { wpa_printf(MSG_WARNING, "WPA: Invalid IGTK KDE length %lu", (unsigned long) ie.igtk_len); goto failed; } #endif /* CONFIG_IEEE80211W */ if (wpa_supplicant_validate_ie(sm, sm->bssid, &ie) < 0) goto failed; if (os_memcmp(sm->anonce, key->key_nonce, WPA_NONCE_LEN) != 0) { wpa_printf(MSG_WARNING, "WPA: ANonce from message 1 of 4-Way " "Handshake differs from 3 of 4-Way Handshake - drop" " packet (src=" MACSTR ")", MAC2STR(sm->bssid)); goto failed; } keylen = WPA_GET_BE16(key->key_length); switch (sm->pairwise_cipher) { case WPA_CIPHER_CCMP: if (keylen != 16) { wpa_printf(MSG_WARNING, "WPA: Invalid CCMP key length " "%d (src=" MACSTR ")", keylen, MAC2STR(sm->bssid)); goto failed; } break; case WPA_CIPHER_TKIP: if (keylen != 32) { wpa_printf(MSG_WARNING, "WPA: Invalid TKIP key length " "%d (src=" MACSTR ")", keylen, MAC2STR(sm->bssid)); goto failed; } break; } if (wpa_supplicant_send_4_of_4(sm, sm->bssid, key, ver, key_info, NULL, 0, &sm->ptk)) { goto failed; } /* SNonce was successfully used in msg 3/4, so mark it to be renewed * for the next 4-Way Handshake. If msg 3 is received again, the old * SNonce will still be used to avoid changing PTK. */ sm->renew_snonce = 1; if (key_info & WPA_KEY_INFO_INSTALL) { if (wpa_supplicant_install_ptk(sm, key)) goto failed; } if (key_info & WPA_KEY_INFO_SECURE) { wpa_sm_mlme_setprotection( sm, sm->bssid, MLME_SETPROTECTION_PROTECT_TYPE_RX, MLME_SETPROTECTION_KEY_TYPE_PAIRWISE); eapol_sm_notify_portValid(sm->eapol, TRUE); } wpa_sm_set_state(sm, WPA_GROUP_HANDSHAKE); if (ie.gtk && wpa_supplicant_pairwise_gtk(sm, key, ie.gtk, ie.gtk_len, key_info) < 0) { wpa_printf(MSG_INFO, "RSN: Failed to configure GTK"); goto failed; } if (ieee80211w_set_keys(sm, &ie) < 0) { wpa_printf(MSG_INFO, "RSN: Failed to configure IGTK"); goto failed; } return; failed: wpa_sm_deauthenticate(sm, WLAN_REASON_UNSPECIFIED); }
static void wpa_supplicant_event_assoc(struct wpa_supplicant *wpa_s, union wpa_event_data *data) { u8 bssid[ETH_ALEN]; if (data) wpa_supplicant_event_associnfo(wpa_s, data); wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATED); if (wpa_s->use_client_mlme) os_memcpy(bssid, wpa_s->bssid, ETH_ALEN); if (wpa_s->use_client_mlme || (wpa_drv_get_bssid(wpa_s, bssid) >= 0 && os_memcmp(bssid, wpa_s->bssid, ETH_ALEN) != 0)) { wpa_msg(wpa_s, MSG_DEBUG, "Associated to a new BSS: BSSID=" MACSTR, MAC2STR(bssid)); os_memcpy(wpa_s->bssid, bssid, ETH_ALEN); os_memset(wpa_s->pending_bssid, 0, ETH_ALEN); if (wpa_supplicant_dynamic_keys(wpa_s)) { wpa_clear_keys(wpa_s, bssid); } if (wpa_supplicant_select_config(wpa_s) < 0) { /* carell modfy */ #if 0 wpa_supplicant_disassociate(wpa_s, REASON_DEAUTH_LEAVING); return; #endif } } wpa_msg(wpa_s, MSG_INFO, "Associated with " MACSTR, MAC2STR(bssid)); if (wpa_s->current_ssid) { /* When using scanning (ap_scan=1), SIM PC/SC interface can be * initialized before association, but for other modes, * initialize PC/SC here, if the current configuration needs * smartcard or SIM/USIM. */ wpa_supplicant_scard_init(wpa_s, wpa_s->current_ssid); } wpa_sm_notify_assoc(wpa_s->wpa, bssid); l2_packet_notify_auth_start(wpa_s->l2); /* * Set portEnabled first to FALSE in order to get EAP state machine out * of the SUCCESS state and eapSuccess cleared. Without this, EAPOL PAE * state machine may transit to AUTHENTICATING state based on obsolete * eapSuccess and then trigger BE_AUTH to SUCCESS and PAE to * AUTHENTICATED without ever giving chance to EAP state machine to * reset the state. */ eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE); eapol_sm_notify_portValid(wpa_s->eapol, FALSE); if (wpa_s->key_mgmt == WPA_KEY_MGMT_PSK) eapol_sm_notify_eap_success(wpa_s->eapol, FALSE); /* 802.1X::portControl = Auto */ eapol_sm_notify_portEnabled(wpa_s->eapol, TRUE); wpa_s->eapol_received = 0; if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE || wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) { wpa_supplicant_cancel_auth_timeout(wpa_s); wpa_supplicant_set_state(wpa_s, WPA_COMPLETED); } else { /* Timeout for receiving the first EAPOL packet */ wpa_supplicant_req_auth_timeout(wpa_s, 10, 0); } wpa_supplicant_cancel_scan(wpa_s); }