]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
SAE: Only allow SAE AKMP for PMKSA caching attempts
authorJouni Malinen <j@w1.fi>
Sun, 8 Apr 2018 17:06:40 +0000 (20:06 +0300)
committerJouni Malinen <j@w1.fi>
Mon, 9 Apr 2018 16:34:44 +0000 (19:34 +0300)
Explicitly check the PMKSA cache entry to have matching SAE AKMP for the
case where determining whether to use PMKSA caching instead of new SAE
authentication. Previously, only the network context was checked, but a
single network configuration profile could be used with both WPA2-PSK
and SAE, so should check the AKMP as well.

Signed-off-by: Jouni Malinen <j@w1.fi>
src/rsn_supp/pmksa_cache.c
src/rsn_supp/pmksa_cache.h
src/rsn_supp/preauth.c
src/rsn_supp/wpa.c
wpa_supplicant/events.c
wpa_supplicant/preauth_test.c
wpa_supplicant/sme.c
wpa_supplicant/wpa_supplicant.c

index f5024f20f9e1de5e8a71e3db344ca8697b36a86c..fdd522087dbc9c6e0f677eb7aed9c85403962aa0 100644 (file)
@@ -96,7 +96,7 @@ static void pmksa_cache_set_expiration(struct rsn_pmksa_cache *pmksa)
        eloop_register_timeout(sec + 1, 0, pmksa_cache_expire, pmksa, NULL);
 
        entry = pmksa->sm->cur_pmksa ? pmksa->sm->cur_pmksa :
-               pmksa_cache_get(pmksa, pmksa->sm->bssid, NULL, NULL);
+               pmksa_cache_get(pmksa, pmksa->sm->bssid, NULL, NULL, 0);
        if (entry) {
                sec = pmksa->pmksa->reauth_time - now.sec;
                if (sec < 0)
@@ -341,17 +341,20 @@ void pmksa_cache_deinit(struct rsn_pmksa_cache *pmksa)
  * @aa: Authenticator address or %NULL to match any
  * @pmkid: PMKID or %NULL to match any
  * @network_ctx: Network context or %NULL to match any
+ * @akmp: Specific AKMP to search for or 0 for any
  * Returns: Pointer to PMKSA cache entry or %NULL if no match was found
  */
 struct rsn_pmksa_cache_entry * pmksa_cache_get(struct rsn_pmksa_cache *pmksa,
                                               const u8 *aa, const u8 *pmkid,
-                                              const void *network_ctx)
+                                              const void *network_ctx,
+                                              int akmp)
 {
        struct rsn_pmksa_cache_entry *entry = pmksa->pmksa;
        while (entry) {
                if ((aa == NULL || os_memcmp(entry->aa, aa, ETH_ALEN) == 0) &&
                    (pmkid == NULL ||
                     os_memcmp(entry->pmkid, pmkid, PMKID_LEN) == 0) &&
+                   (!akmp || akmp == entry->akmp) &&
                    (network_ctx == NULL || network_ctx == entry->network_ctx))
                        return entry;
                entry = entry->next;
@@ -390,6 +393,7 @@ pmksa_cache_clone_entry(struct rsn_pmksa_cache *pmksa,
  * @pmksa: Pointer to PMKSA cache data from pmksa_cache_init()
  * @network_ctx: Network configuration context
  * @aa: Authenticator address for the new AP
+ * @akmp: Specific AKMP to search for or 0 for any
  * Returns: Pointer to a new PMKSA cache entry or %NULL if not available
  *
  * Try to create a new PMKSA cache entry opportunistically by guessing that the
@@ -398,7 +402,7 @@ pmksa_cache_clone_entry(struct rsn_pmksa_cache *pmksa,
  */
 struct rsn_pmksa_cache_entry *
 pmksa_cache_get_opportunistic(struct rsn_pmksa_cache *pmksa, void *network_ctx,
-                             const u8 *aa)
+                             const u8 *aa, int akmp)
 {
        struct rsn_pmksa_cache_entry *entry = pmksa->pmksa;
 
@@ -406,7 +410,8 @@ pmksa_cache_get_opportunistic(struct rsn_pmksa_cache *pmksa, void *network_ctx,
        if (network_ctx == NULL)
                return NULL;
        while (entry) {
-               if (entry->network_ctx == network_ctx) {
+               if (entry->network_ctx == network_ctx &&
+                   (!akmp || entry->akmp == akmp)) {
                        entry = pmksa_cache_clone_entry(pmksa, entry, aa);
                        if (entry) {
                                wpa_printf(MSG_DEBUG, "RSN: added "
@@ -476,11 +481,13 @@ void pmksa_cache_clear_current(struct wpa_sm *sm)
  */
 int pmksa_cache_set_current(struct wpa_sm *sm, const u8 *pmkid,
                            const u8 *bssid, void *network_ctx,
-                           int try_opportunistic, const u8 *fils_cache_id)
+                           int try_opportunistic, const u8 *fils_cache_id,
+                           int akmp)
 {
        struct rsn_pmksa_cache *pmksa = sm->pmksa;
        wpa_printf(MSG_DEBUG, "RSN: PMKSA cache search - network_ctx=%p "
-                  "try_opportunistic=%d", network_ctx, try_opportunistic);
+                  "try_opportunistic=%d akmp=0x%x",
+                  network_ctx, try_opportunistic, akmp);
        if (pmkid)
                wpa_hexdump(MSG_DEBUG, "RSN: Search for PMKID",
                            pmkid, PMKID_LEN);
@@ -495,14 +502,14 @@ int pmksa_cache_set_current(struct wpa_sm *sm, const u8 *pmkid,
        sm->cur_pmksa = NULL;
        if (pmkid)
                sm->cur_pmksa = pmksa_cache_get(pmksa, NULL, pmkid,
-                                               network_ctx);
+                                               network_ctx, akmp);
        if (sm->cur_pmksa == NULL && bssid)
                sm->cur_pmksa = pmksa_cache_get(pmksa, bssid, NULL,
-                                               network_ctx);
+                                               network_ctx, akmp);
        if (sm->cur_pmksa == NULL && try_opportunistic && bssid)
                sm->cur_pmksa = pmksa_cache_get_opportunistic(pmksa,
                                                              network_ctx,
-                                                             bssid);
+                                                             bssid, akmp);
        if (sm->cur_pmksa == NULL && fils_cache_id)
                sm->cur_pmksa = pmksa_cache_get_fils_cache_id(pmksa,
                                                              network_ctx,
index f9a72a6f63beae09fa616df8ee515e2f9c340d92..626761dea32dc332daa2a75b9ca66e0d562a8098 100644 (file)
@@ -61,7 +61,8 @@ pmksa_cache_init(void (*free_cb)(struct rsn_pmksa_cache_entry *entry,
 void pmksa_cache_deinit(struct rsn_pmksa_cache *pmksa);
 struct rsn_pmksa_cache_entry * pmksa_cache_get(struct rsn_pmksa_cache *pmksa,
                                               const u8 *aa, const u8 *pmkid,
-                                              const void *network_ctx);
+                                              const void *network_ctx,
+                                              int akmp);
 int pmksa_cache_list(struct rsn_pmksa_cache *pmksa, char *buf, size_t len);
 struct rsn_pmksa_cache_entry * pmksa_cache_head(struct rsn_pmksa_cache *pmksa);
 struct rsn_pmksa_cache_entry *
@@ -76,10 +77,11 @@ struct rsn_pmksa_cache_entry * pmksa_cache_get_current(struct wpa_sm *sm);
 void pmksa_cache_clear_current(struct wpa_sm *sm);
 int pmksa_cache_set_current(struct wpa_sm *sm, const u8 *pmkid,
                            const u8 *bssid, void *network_ctx,
-                           int try_opportunistic, const u8 *fils_cache_id);
+                           int try_opportunistic, const u8 *fils_cache_id,
+                           int akmp);
 struct rsn_pmksa_cache_entry *
 pmksa_cache_get_opportunistic(struct rsn_pmksa_cache *pmksa,
-                             void *network_ctx, const u8 *aa);
+                             void *network_ctx, const u8 *aa, int akmp);
 void pmksa_cache_flush(struct rsn_pmksa_cache *pmksa, void *network_ctx,
                       const u8 *pmk, size_t pmk_len);
 
index d4276b9533072b04920181f14139bb56f60f9df1..d0c43f464e27d4cdf017a7be1ce5f5eb59e7bb9a 100644 (file)
@@ -323,7 +323,7 @@ void rsn_preauth_candidate_process(struct wpa_sm *sm)
        dl_list_for_each_safe(candidate, n, &sm->pmksa_candidates,
                              struct rsn_pmksa_candidate, list) {
                struct rsn_pmksa_cache_entry *p = NULL;
-               p = pmksa_cache_get(sm->pmksa, candidate->bssid, NULL, NULL);
+               p = pmksa_cache_get(sm->pmksa, candidate->bssid, NULL, NULL, 0);
                if (os_memcmp(sm->bssid, candidate->bssid, ETH_ALEN) != 0 &&
                    (p == NULL || p->opportunistic)) {
                        wpa_msg(sm->ctx->msg_ctx, MSG_DEBUG, "RSN: PMKSA "
@@ -372,7 +372,7 @@ void pmksa_candidate_add(struct wpa_sm *sm, const u8 *bssid,
 
        if (sm->network_ctx && sm->proactive_key_caching)
                pmksa_cache_get_opportunistic(sm->pmksa, sm->network_ctx,
-                                             bssid);
+                                             bssid, 0);
 
        if (!preauth) {
                wpa_printf(MSG_DEBUG, "RSN: Ignored PMKID candidate without "
@@ -483,7 +483,7 @@ void rsn_preauth_scan_result(struct wpa_sm *sm, const u8 *bssid,
        if (wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ie))
                return;
 
-       pmksa = pmksa_cache_get(sm->pmksa, bssid, NULL, NULL);
+       pmksa = pmksa_cache_get(sm->pmksa, bssid, NULL, NULL, 0);
        if (pmksa && (!pmksa->opportunistic ||
                      !(ie.capabilities & WPA_CAPABILITY_PREAUTH)))
                return;
index f84d7d01c0c03cfb6cb480d1f40234fdec68469a..da01494a3a241b6b2eca5932234f4dcdf7281684 100644 (file)
@@ -268,7 +268,7 @@ static int wpa_supplicant_get_pmk(struct wpa_sm *sm,
                 * event before receiving this 1/4 message, so try to find a
                 * matching PMKSA cache entry here. */
                sm->cur_pmksa = pmksa_cache_get(sm->pmksa, src_addr, pmkid,
-                                               NULL);
+                                               NULL, 0);
                if (sm->cur_pmksa) {
                        wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
                                "RSN: found matching PMKID from PMKSA cache");
@@ -354,8 +354,8 @@ static int wpa_supplicant_get_pmk(struct wpa_sm *sm,
                                                     fils_cache_id);
                        }
                        if (!sm->cur_pmksa && pmkid &&
-                           pmksa_cache_get(sm->pmksa, src_addr, pmkid, NULL))
-                       {
+                           pmksa_cache_get(sm->pmksa, src_addr, pmkid, NULL,
+                                   0)) {
                                wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
                                        "RSN: the new PMK matches with the "
                                        "PMKID");
@@ -3130,7 +3130,7 @@ void wpa_sm_pmksa_cache_add(struct wpa_sm *sm, const u8 *pmk, size_t pmk_len,
 int wpa_sm_pmksa_exists(struct wpa_sm *sm, const u8 *bssid,
                        const void *network_ctx)
 {
-       return pmksa_cache_get(sm->pmksa, bssid, NULL, network_ctx) != NULL;
+       return pmksa_cache_get(sm->pmksa, bssid, NULL, network_ctx, 0) != NULL;
 }
 
 
index 19c8475b60ae62d7424ce0900b4d42a72f873e83..7c5452802fd0e64c06d887327d768b40a9813222 100644 (file)
@@ -335,7 +335,7 @@ static void wpa_find_assoc_pmkid(struct wpa_supplicant *wpa_s)
        for (i = 0; i < ie.num_pmkid; i++) {
                pmksa_set = pmksa_cache_set_current(wpa_s->wpa,
                                                    ie.pmkid + i * PMKID_LEN,
-                                                   NULL, NULL, 0, NULL);
+                                                   NULL, NULL, 0, NULL, 0);
                if (pmksa_set == 0) {
                        eapol_sm_notify_pmkid_attempt(wpa_s->eapol);
                        break;
@@ -3805,7 +3805,7 @@ static void wpa_supplicant_event_assoc_auth(struct wpa_supplicant *wpa_s,
                        /* Update the current PMKSA used for this connection */
                        pmksa_cache_set_current(wpa_s->wpa,
                                                data->assoc_info.fils_pmkid,
-                                               NULL, NULL, 0, NULL);
+                                               NULL, NULL, 0, NULL, 0);
                }
        }
 #endif /* CONFIG_FILS */
index a213a30f1e3130b85edf2d6838a05f457df9a9a6..f2fff550aa81e79d98baeca784ca316fb0f2d108 100644 (file)
@@ -348,7 +348,7 @@ int main(int argc, char *argv[])
                ret = -2;
        else {
                ret = pmksa_cache_set_current(wpa_s.wpa, NULL, bssid, NULL, 0,
-                                             NULL) ? 0 : -3;
+                                             NULL, 0) ? 0 : -3;
        }
 
        test_eapol_clean(&wpa_s);
index 460e4e6a70b0388af2e88d8fce665bab3f24bd09..8481b9aab670fecaba7bc04e8c9e40ee29f81a09 100644 (file)
@@ -333,7 +333,8 @@ static void sme_send_authentication(struct wpa_supplicant *wpa_s,
 #endif /* CONFIG_FILS */
                if (pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid,
                                            wpa_s->current_ssid,
-                                           try_opportunistic, cache_id) == 0)
+                                           try_opportunistic, cache_id,
+                                           0) == 0)
                        eapol_sm_notify_pmkid_attempt(wpa_s->eapol);
                wpa_s->sme.assoc_req_ie_len = sizeof(wpa_s->sme.assoc_req_ie);
                if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
@@ -548,7 +549,7 @@ static void sme_send_authentication(struct wpa_supplicant *wpa_s,
 #ifdef CONFIG_SAE
        if (!skip_auth && params.auth_alg == WPA_AUTH_ALG_SAE &&
            pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid, ssid, 0,
-                                   NULL) == 0) {
+                                   NULL, WPA_KEY_MGMT_SAE) == 0) {
                wpa_dbg(wpa_s, MSG_DEBUG,
                        "PMKSA cache entry found - try to use PMKSA caching instead of new SAE authentication");
                wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
@@ -616,8 +617,8 @@ static void sme_send_authentication(struct wpa_supplicant *wpa_s,
 
                if (pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid,
                                            ssid, 0,
-                                           wpa_bss_get_fils_cache_id(bss)) ==
-                   0)
+                                           wpa_bss_get_fils_cache_id(bss),
+                                           0) == 0)
                        wpa_printf(MSG_DEBUG,
                                   "SME: Try to use FILS with PMKSA caching");
                resp = fils_build_auth(wpa_s->wpa, ssid->fils_dh_group, md);
index 9808640eac1c752191b7ff5fc2adedd758d7b9d2..9ee0996138c9d866cc8e836d323b59f7a93c30a0 100644 (file)
@@ -2427,7 +2427,7 @@ static u8 * wpas_populate_assoc_ies(
 #endif /* CONFIG_FILS */
                if (pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid,
                                            ssid, try_opportunistic,
-                                           cache_id) == 0)
+                                           cache_id, 0) == 0)
                        eapol_sm_notify_pmkid_attempt(wpa_s->eapol);
                wpa_ie_len = max_wpa_ie_len;
                if (wpa_supplicant_set_suites(wpa_s, bss, ssid,