diff options
Diffstat (limited to 'src/rsn_supp/preauth.c')
-rw-r--r-- | src/rsn_supp/preauth.c | 175 |
1 files changed, 82 insertions, 93 deletions
diff --git a/src/rsn_supp/preauth.c b/src/rsn_supp/preauth.c index b00c004..6109f5e 100644 --- a/src/rsn_supp/preauth.c +++ b/src/rsn_supp/preauth.c @@ -1,6 +1,6 @@ /* - * WPA Supplicant - RSN pre-authentication - * Copyright (c) 2003-2008, Jouni Malinen <j@w1.fi> + * RSN pre-authentication (supplicant) + * Copyright (c) 2003-2010, Jouni Malinen <j@w1.fi> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -16,14 +16,13 @@ #include "common.h" #include "wpa.h" -#include "drivers/driver.h" #include "eloop.h" #include "l2_packet/l2_packet.h" #include "eapol_supp/eapol_supp_sm.h" #include "preauth.h" #include "pmksa_cache.h" #include "wpa_i.h" -#include "ieee802_11_defs.h" +#include "common/ieee802_11_defs.h" #if defined(IEEE8021X_EAPOL) && !defined(CONFIG_NO_WPA2) @@ -32,7 +31,7 @@ struct rsn_pmksa_candidate { - struct rsn_pmksa_candidate *next; + struct dl_list list; u8 bssid[ETH_ALEN]; int priority; }; @@ -44,17 +43,15 @@ struct rsn_pmksa_candidate { */ void pmksa_candidate_free(struct wpa_sm *sm) { - struct rsn_pmksa_candidate *entry, *prev; + struct rsn_pmksa_candidate *entry, *n; if (sm == NULL) return; - entry = sm->pmksa_candidates; - sm->pmksa_candidates = NULL; - while (entry) { - prev = entry; - entry = entry->next; - os_free(prev); + dl_list_for_each_safe(entry, n, &sm->pmksa_candidates, + struct rsn_pmksa_candidate, list) { + dl_list_del(&entry->list); + os_free(entry); } } @@ -107,15 +104,15 @@ static void rsn_preauth_eapol_cb(struct eapol_sm *eapol, int success, sm->network_ctx, WPA_KEY_MGMT_IEEE8021X); } else { - wpa_msg(sm->ctx->ctx, MSG_INFO, "RSN: failed to get " - "master session key from pre-auth EAPOL state " - "machines"); + wpa_msg(sm->ctx->msg_ctx, MSG_INFO, + "RSN: failed to get master session key from " + "pre-auth EAPOL state machines"); success = 0; } } - wpa_msg(sm->ctx->ctx, MSG_INFO, "RSN: pre-authentication with " MACSTR - " %s", MAC2STR(sm->preauth_bssid), + wpa_msg(sm->ctx->msg_ctx, MSG_INFO, "RSN: pre-authentication with " + MACSTR " %s", MAC2STR(sm->preauth_bssid), success ? "completed successfully" : "failed"); rsn_preauth_deinit(sm); @@ -127,8 +124,8 @@ static void rsn_preauth_timeout(void *eloop_ctx, void *timeout_ctx) { struct wpa_sm *sm = eloop_ctx; - wpa_msg(sm->ctx->ctx, MSG_INFO, "RSN: pre-authentication with " MACSTR - " timed out", MAC2STR(sm->preauth_bssid)); + wpa_msg(sm->ctx->msg_ctx, MSG_INFO, "RSN: pre-authentication with " + MACSTR " timed out", MAC2STR(sm->preauth_bssid)); rsn_preauth_deinit(sm); rsn_preauth_candidate_process(sm); } @@ -183,8 +180,8 @@ int rsn_preauth_init(struct wpa_sm *sm, const u8 *dst, if (sm->preauth_eapol) return -1; - wpa_msg(sm->ctx->ctx, MSG_DEBUG, "RSN: starting pre-authentication " - "with " MACSTR, MAC2STR(dst)); + wpa_msg(sm->ctx->msg_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, @@ -293,42 +290,42 @@ void rsn_preauth_deinit(struct wpa_sm *sm) */ void rsn_preauth_candidate_process(struct wpa_sm *sm) { - struct rsn_pmksa_candidate *candidate; + struct rsn_pmksa_candidate *candidate, *n; - if (sm->pmksa_candidates == NULL) + if (dl_list_empty(&sm->pmksa_candidates)) return; /* TODO: drop priority for old candidate entries */ - wpa_msg(sm->ctx->ctx, MSG_DEBUG, "RSN: processing PMKSA candidate " + wpa_msg(sm->ctx->msg_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"); + wpa_msg(sm->ctx->msg_ctx, MSG_DEBUG, "RSN: not in suitable " + "state for new pre-authentication"); return; /* invalid state for new pre-auth */ } - while (sm->pmksa_candidates) { + dl_list_for_each_safe(candidate, n, &sm->pmksa_candidates, + struct rsn_pmksa_candidate, list) { 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 " + wpa_msg(sm->ctx->msg_ctx, MSG_DEBUG, "RSN: PMKSA " "candidate " MACSTR " selected for pre-authentication", MAC2STR(candidate->bssid)); - sm->pmksa_candidates = candidate->next; + dl_list_del(&candidate->list); rsn_preauth_init(sm, candidate->bssid, sm->eap_conf_ctx); os_free(candidate); return; } - wpa_msg(sm->ctx->ctx, MSG_DEBUG, "RSN: PMKSA candidate " + wpa_msg(sm->ctx->msg_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 @@ -337,10 +334,10 @@ void rsn_preauth_candidate_process(struct wpa_sm *sm) wpa_sm_add_pmkid(sm, candidate->bssid, p->pmkid); } - sm->pmksa_candidates = candidate->next; + dl_list_del(&candidate->list); os_free(candidate); } - wpa_msg(sm->ctx->ctx, MSG_DEBUG, "RSN: no more pending PMKSA " + wpa_msg(sm->ctx->msg_ctx, MSG_DEBUG, "RSN: no more pending PMKSA " "candidates"); } @@ -359,7 +356,7 @@ void rsn_preauth_candidate_process(struct wpa_sm *sm) void pmksa_candidate_add(struct wpa_sm *sm, const u8 *bssid, int prio, int preauth) { - struct rsn_pmksa_candidate *cand, *prev, *pos; + struct rsn_pmksa_candidate *cand, *pos; if (sm->network_ctx && sm->proactive_key_caching) pmksa_cache_get_opportunistic(sm->pmksa, sm->network_ctx, @@ -373,21 +370,17 @@ void pmksa_candidate_add(struct wpa_sm *sm, const u8 *bssid, /* If BSSID already on candidate list, update the priority of the old * entry. Do not override priority based on normal scan results. */ - prev = NULL; - cand = sm->pmksa_candidates; - while (cand) { - if (os_memcmp(cand->bssid, bssid, ETH_ALEN) == 0) { - if (prev) - prev->next = cand->next; - else - sm->pmksa_candidates = cand->next; + cand = NULL; + dl_list_for_each(pos, &sm->pmksa_candidates, + struct rsn_pmksa_candidate, list) { + if (os_memcmp(pos->bssid, bssid, ETH_ALEN) == 0) { + cand = pos; break; } - prev = cand; - cand = cand->next; } if (cand) { + dl_list_del(&cand->list); if (prio < PMKID_CANDIDATE_PRIO_SCAN) cand->priority = prio; } else { @@ -400,21 +393,18 @@ void pmksa_candidate_add(struct wpa_sm *sm, const u8 *bssid, /* Add candidate to the list; order by increasing priority value. i.e., * highest priority (smallest value) first. */ - prev = NULL; - pos = sm->pmksa_candidates; - while (pos) { - if (cand->priority <= pos->priority) + dl_list_for_each(pos, &sm->pmksa_candidates, + struct rsn_pmksa_candidate, list) { + if (cand->priority <= pos->priority) { + dl_list_add(pos->list.prev, &cand->list); + cand = NULL; break; - prev = pos; - pos = pos->next; + } } - cand->next = pos; - if (prev) - prev->next = cand; - else - sm->pmksa_candidates = cand; + if (cand) + dl_list_add_tail(&sm->pmksa_candidates, &cand->list); - wpa_msg(sm->ctx->ctx, MSG_DEBUG, "RSN: added PMKSA cache " + wpa_msg(sm->ctx->msg_ctx, MSG_DEBUG, "RSN: added PMKSA cache " "candidate " MACSTR " prio %d", MAC2STR(bssid), prio); rsn_preauth_candidate_process(sm); } @@ -423,23 +413,18 @@ void pmksa_candidate_add(struct wpa_sm *sm, const u8 *bssid, /* TODO: schedule periodic scans if current AP supports preauth */ /** - * rsn_preauth_scan_results - Process scan results to find PMKSA candidates + * rsn_preauth_scan_results - Start processing scan results for canditates * @sm: Pointer to WPA state machine data from wpa_sm_init() - * @results: Scan results + * Returns: 0 if ready to process results or -1 to skip processing * - * This functions goes through the scan results and adds all suitable APs - * (Authenticators) into PMKSA candidate list. + * This functions is used to notify RSN code about start of new scan results + * processing. The actual scan results will be provided by calling + * rsn_preauth_scan_result() for each BSS if this function returned 0. */ -void rsn_preauth_scan_results(struct wpa_sm *sm, - struct wpa_scan_results *results) +int rsn_preauth_scan_results(struct wpa_sm *sm) { - struct wpa_scan_res *r; - struct wpa_ie_data ie; - int i; - struct rsn_pmksa_cache_entry *pmksa; - if (sm->ssid_len == 0) - return; + return -1; /* * TODO: is it ok to free all candidates? What about the entries @@ -447,37 +432,41 @@ void rsn_preauth_scan_results(struct wpa_sm *sm, */ pmksa_candidate_free(sm); - for (i = results->num - 1; i >= 0; i--) { - const u8 *ssid, *rsn; + return 0; +} - r = results->res[i]; - ssid = wpa_scan_get_ie(r, WLAN_EID_SSID); - if (ssid == NULL || ssid[1] != sm->ssid_len || - os_memcmp(ssid + 2, sm->ssid, ssid[1]) != 0) - continue; +/** + * rsn_preauth_scan_result - Processing scan result for PMKSA canditates + * @sm: Pointer to WPA state machine data from wpa_sm_init() + * + * Add all suitable APs (Authenticators) from scan results into PMKSA + * candidate list. + */ +void rsn_preauth_scan_result(struct wpa_sm *sm, const u8 *bssid, + const u8 *ssid, const u8 *rsn) +{ + struct wpa_ie_data ie; + struct rsn_pmksa_cache_entry *pmksa; - if (os_memcmp(r->bssid, sm->bssid, ETH_ALEN) == 0) - continue; + if (ssid[1] != sm->ssid_len || + os_memcmp(ssid + 2, sm->ssid, sm->ssid_len) != 0) + return; /* Not for the current SSID */ - rsn = wpa_scan_get_ie(r, WLAN_EID_RSN); - if (rsn == NULL || wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ie)) - continue; + if (os_memcmp(bssid, sm->bssid, ETH_ALEN) == 0) + return; /* Ignore current AP */ - pmksa = pmksa_cache_get(sm->pmksa, r->bssid, NULL); - if (pmksa && - (!pmksa->opportunistic || - !(ie.capabilities & WPA_CAPABILITY_PREAUTH))) - continue; + if (wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ie)) + return; - /* - * Give less priority to candidates found from normal - * scan results. - */ - pmksa_candidate_add(sm, r->bssid, - PMKID_CANDIDATE_PRIO_SCAN, - ie.capabilities & WPA_CAPABILITY_PREAUTH); - } + pmksa = pmksa_cache_get(sm->pmksa, bssid, NULL); + if (pmksa && (!pmksa->opportunistic || + !(ie.capabilities & WPA_CAPABILITY_PREAUTH))) + return; + + /* Give less priority to candidates found from normal scan results. */ + pmksa_candidate_add(sm, bssid, PMKID_CANDIDATE_PRIO_SCAN, + ie.capabilities & WPA_CAPABILITY_PREAUTH); } |