/** * rsn_preauth_candidate_process - Process PMKSA candidates * @sm: Pointer to WPA state machine data from wpa_sm_init() * * Go through the PMKSA candidates and start pre-authentication if a candidate * without an existing PMKSA cache entry is found. Processed candidates will be * removed from the list. */ void rsn_preauth_candidate_process(struct wpa_sm *sm) { struct rsn_pmksa_candidate *candidate; if (sm->pmksa_candidates == NULL) return; /* TODO: drop priority for old candidate entries */ wpa_msg(sm->ctx->ctx, MSG_DEBUG, "RSN: processing PMKSA candidate " "list"); if (sm->preauth_eapol || sm->proto != WPA_PROTO_RSN || wpa_sm_get_state(sm) != WPA_COMPLETED || (sm->key_mgmt != WPA_KEY_MGMT_IEEE8021X && sm->key_mgmt != WPA_KEY_MGMT_IEEE8021X_SHA256)) { wpa_msg(sm->ctx->ctx, MSG_DEBUG, "RSN: not in suitable state " "for new pre-authentication"); return; /* invalid state for new pre-auth */ } while (sm->pmksa_candidates) { struct rsn_pmksa_cache_entry *p = NULL; candidate = sm->pmksa_candidates; p = pmksa_cache_get(sm->pmksa, candidate->bssid, NULL); if (os_memcmp(sm->bssid, candidate->bssid, ETH_ALEN) != 0 && (p == NULL || p->opportunistic)) { wpa_msg(sm->ctx->ctx, MSG_DEBUG, "RSN: PMKSA " "candidate " MACSTR " selected for pre-authentication", MAC2STR(candidate->bssid)); sm->pmksa_candidates = candidate->next; rsn_preauth_init(sm, candidate->bssid, sm->eap_conf_ctx); os_free(candidate); return; } wpa_msg(sm->ctx->ctx, MSG_DEBUG, "RSN: PMKSA candidate " MACSTR " does not need pre-authentication anymore", MAC2STR(candidate->bssid)); /* Some drivers (e.g., NDIS) expect to get notified about the * PMKIDs again, so report the existing data now. */ if (p) { wpa_sm_add_pmkid(sm, candidate->bssid, p->pmkid); } sm->pmksa_candidates = candidate->next; os_free(candidate); } wpa_msg(sm->ctx->ctx, MSG_DEBUG, "RSN: no more pending PMKSA " "candidates"); }
void rsn_preauth_candidate_process(struct wpa_supplicant *wpa_s) { struct rsn_pmksa_candidate *candidate; if (wpa_s->pmksa_candidates == NULL) return; /* TODO: drop priority for old candidate entries */ wpa_msg(wpa_s, MSG_DEBUG, "RSN: processing PMKSA candidate list"); if (wpa_s->preauth_eapol || wpa_s->proto != WPA_PROTO_RSN || wpa_s->wpa_state != WPA_COMPLETED || wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X) { wpa_msg(wpa_s, MSG_DEBUG, "RSN: not in suitable state for new " "pre-authentication"); return; /* invalid state for new pre-auth */ } while (wpa_s->pmksa_candidates) { struct rsn_pmksa_cache *p = NULL; candidate = wpa_s->pmksa_candidates; p = pmksa_cache_get(wpa_s, candidate->bssid, NULL); if (memcmp(wpa_s->bssid, candidate->bssid, ETH_ALEN) != 0 && (p == NULL || p->opportunistic)) { wpa_msg(wpa_s, MSG_DEBUG, "RSN: PMKSA candidate " MACSTR " selected for pre-authentication", MAC2STR(candidate->bssid)); wpa_s->pmksa_candidates = candidate->next; rsn_preauth_init(wpa_s, candidate->bssid); free(candidate); return; } wpa_msg(wpa_s, MSG_DEBUG, "RSN: PMKSA candidate " MACSTR " does not need pre-authentication anymore", MAC2STR(candidate->bssid)); /* Some drivers (e.g., NDIS) expect to get notified about the * PMKIDs again, so report the existing data now. */ if (p) wpa_drv_add_pmkid(wpa_s, candidate->bssid, p->pmkid); wpa_s->pmksa_candidates = candidate->next; free(candidate); } wpa_msg(wpa_s, MSG_DEBUG, "RSN: no more pending PMKSA candidates"); }
static int wpa_supplicant_ctrl_iface_preauth(struct wpa_supplicant *wpa_s, char *addr) { u8 bssid[ETH_ALEN]; if (hwaddr_aton(addr, bssid)) { wpa_printf(MSG_DEBUG, "CTRL_IFACE PREAUTH: invalid address " "'%s'", addr); return -1; } wpa_printf(MSG_DEBUG, "CTRL_IFACE PREAUTH " MACSTR, MAC2STR(bssid)); rsn_preauth_deinit(wpa_s->wpa); if (rsn_preauth_init(wpa_s->wpa, bssid, wpa_s->current_ssid)) return -1; return 0; }
int main(int argc, char *argv[]) { struct wpa_supplicant wpa_s; int ret = 1; u8 bssid[ETH_ALEN]; struct preauth_test_data preauth_test; if (os_program_init()) return -1; os_memset(&preauth_test, 0, sizeof(preauth_test)); wpa_debug_level = 0; wpa_debug_show_keys = 1; if (argc != 4) { printf("usage: preauth_test <conf> <target MAC address> " "<ifname>\n"); return -1; } if (hwaddr_aton(argv[2], bssid)) { printf("Failed to parse target address '%s'.\n", argv[2]); return -1; } if (eap_register_methods()) { wpa_printf(MSG_ERROR, "Failed to register EAP methods"); return -1; } #ifdef WAPI if (eloop_init(&wpa_s)) { #else if (eloop_init()) { #endif wpa_printf(MSG_ERROR, "Failed to initialize event loop"); return -1; } os_memset(&wpa_s, 0, sizeof(wpa_s)); wpa_s.conf = wpa_config_read(argv[1]); if (wpa_s.conf == NULL) { printf("Failed to parse configuration file '%s'.\n", argv[1]); return -1; } if (wpa_s.conf->ssid == NULL) { printf("No networks defined.\n"); return -1; } wpa_init_conf(&wpa_s, argv[3]); wpa_s.ctrl_iface = wpa_supplicant_ctrl_iface_init(&wpa_s); if (wpa_s.ctrl_iface == NULL) { printf("Failed to initialize control interface '%s'.\n" "You may have another preauth_test process already " "running or the file was\n" "left by an unclean termination of preauth_test in " "which case you will need\n" "to manually remove this file before starting " "preauth_test again.\n", wpa_s.conf->ctrl_interface); return -1; } if (wpa_supplicant_scard_init(&wpa_s, wpa_s.conf->ssid)) return -1; if (rsn_preauth_init(wpa_s.wpa, bssid, &wpa_s.conf->ssid->eap)) return -1; eloop_register_timeout(30, 0, eapol_test_timeout, &preauth_test, NULL); eloop_register_timeout(0, 100000, eapol_test_poll, &wpa_s, NULL); eloop_register_signal_terminate(eapol_test_terminate, &wpa_s); eloop_register_signal_reconfig(eapol_test_terminate, &wpa_s); eloop_run(); if (preauth_test.auth_timed_out) ret = -2; else { ret = pmksa_cache_set_current(wpa_s.wpa, NULL, bssid, NULL, 0) ? 0 : -3; } test_eapol_clean(&wpa_s); eap_peer_unregister_methods(); eloop_destroy(); os_program_deinit(); return ret; }