]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
RADIUS DAS: Allow PMKSA cache entry to be removed without association
authorJouni Malinen <jouni@qca.qualcomm.com>
Fri, 16 Jan 2015 13:55:39 +0000 (15:55 +0200)
committerJouni Malinen <j@w1.fi>
Fri, 16 Jan 2015 13:55:39 +0000 (15:55 +0200)
This extends Disconnect-Request processing to check against PMKSA cache
entries if no active session (STA association) match the request.

Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
src/ap/hostapd.c
src/ap/pmksa_cache_auth.c
src/ap/pmksa_cache_auth.h
src/ap/wpa_auth.c
src/ap/wpa_auth.h

index 81e9b2b15bedde24c5f650a5b096e73260be1986..b641503c7360eec018ce3898cbfeee6254bf3df5 100644 (file)
@@ -794,6 +794,15 @@ static struct sta_info * hostapd_das_find_sta(struct hostapd_data *hapd,
 }
 
 
+static int hostapd_das_disconnect_pmksa(struct hostapd_data *hapd,
+                                       struct radius_das_attrs *attr)
+{
+       if (!hapd->wpa_auth)
+               return -1;
+       return wpa_auth_radius_das_disconnect_pmksa(hapd->wpa_auth, attr);
+}
+
+
 static enum radius_das_res
 hostapd_das_disconnect(void *ctx, struct radius_das_attrs *attr)
 {
@@ -811,6 +820,11 @@ hostapd_das_disconnect(void *ctx, struct radius_das_attrs *attr)
                                   "RADIUS DAS: Multiple sessions match - not supported");
                        return RADIUS_DAS_MULTI_SESSION_MATCH;
                }
+               if (hostapd_das_disconnect_pmksa(hapd, attr) == 0) {
+                       wpa_printf(MSG_DEBUG,
+                                  "RADIUS DAS: PMKSA cache entry matched");
+                       return RADIUS_DAS_SUCCESS;
+               }
                wpa_printf(MSG_DEBUG, "RADIUS DAS: No matching session found");
                return RADIUS_DAS_SESSION_NOT_FOUND;
        }
index 427038217da338c09d91f468cc30702b24de7c23..650e9a81daf5bb02b7b00847504dfc7a92a8f451 100644 (file)
@@ -12,6 +12,7 @@
 #include "utils/eloop.h"
 #include "eapol_auth/eapol_auth_sm.h"
 #include "eapol_auth/eapol_auth_sm_i.h"
+#include "radius/radius_das.h"
 #include "sta_info.h"
 #include "ap_config.h"
 #include "pmksa_cache_auth.h"
@@ -452,3 +453,74 @@ pmksa_cache_auth_init(void (*free_cb)(struct rsn_pmksa_cache_entry *entry,
 
        return pmksa;
 }
+
+
+static int das_attr_match(struct rsn_pmksa_cache_entry *entry,
+                         struct radius_das_attrs *attr)
+{
+       int match = 0;
+
+       if (attr->sta_addr) {
+               if (os_memcmp(attr->sta_addr, entry->spa, ETH_ALEN) != 0)
+                       return 0;
+               match++;
+       }
+
+       if (attr->acct_multi_session_id) {
+               char buf[20];
+
+               if (attr->acct_multi_session_id_len != 17)
+                       return 0;
+               os_snprintf(buf, sizeof(buf), "%08X+%08X",
+                           entry->acct_multi_session_id_hi,
+                           entry->acct_multi_session_id_lo);
+               if (os_memcmp(attr->acct_multi_session_id, buf, 17) != 0)
+                       return 0;
+               match++;
+       }
+
+       if (attr->cui) {
+               if (!entry->cui ||
+                   attr->cui_len != wpabuf_len(entry->cui) ||
+                   os_memcmp(attr->cui, wpabuf_head(entry->cui),
+                             attr->cui_len) != 0)
+                       return 0;
+               match++;
+       }
+
+       if (attr->user_name) {
+               if (!entry->identity ||
+                   attr->user_name_len != entry->identity_len ||
+                   os_memcmp(attr->user_name, entry->identity,
+                             attr->user_name_len) != 0)
+                       return 0;
+               match++;
+       }
+
+       return match;
+}
+
+
+int pmksa_cache_auth_radius_das_disconnect(struct rsn_pmksa_cache *pmksa,
+                                          struct radius_das_attrs *attr)
+{
+       int found = 0;
+       struct rsn_pmksa_cache_entry *entry, *prev;
+
+       if (attr->acct_session_id)
+               return -1;
+
+       entry = pmksa->pmksa;
+       while (entry) {
+               if (das_attr_match(entry, attr)) {
+                       found++;
+                       prev = entry;
+                       entry = entry->next;
+                       pmksa_cache_free_entry(pmksa, prev);
+                       continue;
+               }
+               entry = entry->next;
+       }
+
+       return found ? 0 : -1;
+}
index 519555f8aa5149c24eed225d504eb844c405b019..8b7be1291b53a7dda2e023659409b518386071d1 100644 (file)
@@ -61,5 +61,7 @@ void pmksa_cache_to_eapol_data(struct rsn_pmksa_cache_entry *entry,
                               struct eapol_state_machine *eapol);
 void pmksa_cache_free_entry(struct rsn_pmksa_cache *pmksa,
                            struct rsn_pmksa_cache_entry *entry);
+int pmksa_cache_auth_radius_das_disconnect(struct rsn_pmksa_cache *pmksa,
+                                          struct radius_das_attrs *attr);
 
 #endif /* PMKSA_CACHE_H */
index 059b8848da135ed6e02af118ffc81b17f3f3cc2d..f71b0285706ec3ddfcf958973ec53d85020d90af 100644 (file)
@@ -3340,3 +3340,10 @@ int wpa_auth_get_ip_addr(struct wpa_state_machine *sm, u8 *addr)
        return 0;
 }
 #endif /* CONFIG_P2P */
+
+
+int wpa_auth_radius_das_disconnect_pmksa(struct wpa_authenticator *wpa_auth,
+                                        struct radius_das_attrs *attr)
+{
+       return pmksa_cache_auth_radius_das_disconnect(wpa_auth->pmksa, attr);
+}
index 757e49e44a130fdd8c9d13f78c415a4499e90026..b34b84dd6cc74870229f534f6e252032620a0f04 100644 (file)
@@ -315,4 +315,8 @@ int wpa_auth_uses_ft_sae(struct wpa_state_machine *sm);
 
 int wpa_auth_get_ip_addr(struct wpa_state_machine *sm, u8 *addr);
 
+struct radius_das_attrs;
+int wpa_auth_radius_das_disconnect_pmksa(struct wpa_authenticator *wpa_auth,
+                                        struct radius_das_attrs *attr);
+
 #endif /* WPA_AUTH_H */