Updated to hostap_2_6
[mech_eap.git] / libeap / src / ap / pmksa_cache_auth.c
index 877affe..d610e7e 100644 (file)
@@ -38,6 +38,7 @@ static void pmksa_cache_set_expiration(struct rsn_pmksa_cache *pmksa);
 
 static void _pmksa_cache_free_entry(struct rsn_pmksa_cache_entry *entry)
 {
+       os_free(entry->vlan_desc);
        os_free(entry->identity);
        wpabuf_free(entry->cui);
 #ifndef CONFIG_NO_RADIUS
@@ -91,6 +92,20 @@ void pmksa_cache_free_entry(struct rsn_pmksa_cache *pmksa,
 }
 
 
+/**
+ * pmksa_cache_auth_flush - Flush all PMKSA cache entries
+ * @pmksa: Pointer to PMKSA cache data from pmksa_cache_auth_init()
+ */
+void pmksa_cache_auth_flush(struct rsn_pmksa_cache *pmksa)
+{
+       while (pmksa->pmksa) {
+               wpa_printf(MSG_DEBUG, "RSN: Flush PMKSA cache entry for "
+                          MACSTR, MAC2STR(pmksa->pmksa->spa));
+               pmksa_cache_free_entry(pmksa, pmksa->pmksa);
+       }
+}
+
+
 static void pmksa_cache_expire(void *eloop_ctx, void *timeout_ctx)
 {
        struct rsn_pmksa_cache *pmksa = eloop_ctx;
@@ -126,6 +141,8 @@ static void pmksa_cache_set_expiration(struct rsn_pmksa_cache *pmksa)
 static void pmksa_cache_from_eapol_data(struct rsn_pmksa_cache_entry *entry,
                                        struct eapol_state_machine *eapol)
 {
+       struct vlan_description *vlan_desc;
+
        if (eapol == NULL)
                return;
 
@@ -146,14 +163,22 @@ static void pmksa_cache_from_eapol_data(struct rsn_pmksa_cache_entry *entry,
 #endif /* CONFIG_NO_RADIUS */
 
        entry->eap_type_authsrv = eapol->eap_type_authsrv;
-       entry->vlan_id = ((struct sta_info *) eapol->sta)->vlan_id;
 
-       entry->acct_multi_session_id_hi = eapol->acct_multi_session_id_hi;
-       entry->acct_multi_session_id_lo = eapol->acct_multi_session_id_lo;
+       vlan_desc = ((struct sta_info *) eapol->sta)->vlan_desc;
+       if (vlan_desc && vlan_desc->notempty) {
+               entry->vlan_desc = os_zalloc(sizeof(struct vlan_description));
+               if (entry->vlan_desc)
+                       *entry->vlan_desc = *vlan_desc;
+       } else {
+               entry->vlan_desc = NULL;
+       }
+
+       entry->acct_multi_session_id = eapol->acct_multi_session_id;
 }
 
 
-void pmksa_cache_to_eapol_data(struct rsn_pmksa_cache_entry *entry,
+void pmksa_cache_to_eapol_data(struct hostapd_data *hapd,
+                              struct rsn_pmksa_cache_entry *entry,
                               struct eapol_state_machine *eapol)
 {
        if (entry == NULL || eapol == NULL)
@@ -186,10 +211,11 @@ void pmksa_cache_to_eapol_data(struct rsn_pmksa_cache_entry *entry,
        }
 
        eapol->eap_type_authsrv = entry->eap_type_authsrv;
-       ((struct sta_info *) eapol->sta)->vlan_id = entry->vlan_id;
+#ifndef CONFIG_NO_VLAN
+       ap_sta_set_vlan(hapd, eapol->sta, entry->vlan_desc);
+#endif /* CONFIG_NO_VLAN */
 
-       eapol->acct_multi_session_id_hi = entry->acct_multi_session_id_hi;
-       eapol->acct_multi_session_id_lo = entry->acct_multi_session_id_lo;
+       eapol->acct_multi_session_id = entry->acct_multi_session_id;
 }
 
 
@@ -234,6 +260,7 @@ static void pmksa_cache_link_entry(struct rsn_pmksa_cache *pmksa,
  * @pmksa: Pointer to PMKSA cache data from pmksa_cache_auth_init()
  * @pmk: The new pairwise master key
  * @pmk_len: PMK length in bytes, usually PMK_LEN (32)
+ * @pmkid: Calculated PMKID
  * @kck: Key confirmation key or %NULL if not yet derived
  * @kck_len: KCK length in bytes
  * @aa: Authenticator address
@@ -250,7 +277,7 @@ static void pmksa_cache_link_entry(struct rsn_pmksa_cache *pmksa,
  */
 struct rsn_pmksa_cache_entry *
 pmksa_cache_auth_add(struct rsn_pmksa_cache *pmksa,
-                    const u8 *pmk, size_t pmk_len,
+                    const u8 *pmk, size_t pmk_len, const u8 *pmkid,
                     const u8 *kck, size_t kck_len,
                     const u8 *aa, const u8 *spa, int session_timeout,
                     struct eapol_state_machine *eapol, int akmp)
@@ -258,7 +285,7 @@ pmksa_cache_auth_add(struct rsn_pmksa_cache *pmksa,
        struct rsn_pmksa_cache_entry *entry, *pos;
        struct os_reltime now;
 
-       if (pmk_len > PMK_LEN)
+       if (pmk_len > PMK_LEN_MAX)
                return NULL;
 
        if (wpa_key_mgmt_suite_b(akmp) && !kck)
@@ -269,7 +296,9 @@ pmksa_cache_auth_add(struct rsn_pmksa_cache *pmksa,
                return NULL;
        os_memcpy(entry->pmk, pmk, pmk_len);
        entry->pmk_len = pmk_len;
-       if (akmp == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)
+       if (pmkid)
+               os_memcpy(entry->pmkid, pmkid, PMKID_LEN);
+       else if (akmp == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)
                rsn_pmkid_suite_b_192(kck, kck_len, aa, spa, entry->pmkid);
        else if (wpa_key_mgmt_suite_b(akmp))
                rsn_pmkid_suite_b(kck, kck_len, aa, spa, entry->pmkid);
@@ -337,7 +366,13 @@ pmksa_cache_add_okc(struct rsn_pmksa_cache *pmksa,
        radius_copy_class(&entry->radius_class, &old_entry->radius_class);
 #endif /* CONFIG_NO_RADIUS */
        entry->eap_type_authsrv = old_entry->eap_type_authsrv;
-       entry->vlan_id = old_entry->vlan_id;
+       if (old_entry->vlan_desc) {
+               entry->vlan_desc = os_zalloc(sizeof(struct vlan_description));
+               if (entry->vlan_desc)
+                       *entry->vlan_desc = *old_entry->vlan_desc;
+       } else {
+               entry->vlan_desc = NULL;
+       }
        entry->opportunistic = 1;
 
        pmksa_cache_link_entry(pmksa, entry);
@@ -471,12 +506,11 @@ static int das_attr_match(struct rsn_pmksa_cache_entry *entry,
        if (attr->acct_multi_session_id) {
                char buf[20];
 
-               if (attr->acct_multi_session_id_len != 17)
+               if (attr->acct_multi_session_id_len != 16)
                        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)
+               os_snprintf(buf, sizeof(buf), "%016llX",
+                           (unsigned long long) entry->acct_multi_session_id);
+               if (os_memcmp(attr->acct_multi_session_id, buf, 16) != 0)
                        return 0;
                match++;
        }
@@ -526,3 +560,48 @@ int pmksa_cache_auth_radius_das_disconnect(struct rsn_pmksa_cache *pmksa,
 
        return found ? 0 : -1;
 }
+
+
+/**
+ * pmksa_cache_auth_list - Dump text list of entries in PMKSA cache
+ * @pmksa: Pointer to PMKSA cache data from pmksa_cache_auth_init()
+ * @buf: Buffer for the list
+ * @len: Length of the buffer
+ * Returns: Number of bytes written to buffer
+ *
+ * This function is used to generate a text format representation of the
+ * current PMKSA cache contents for the ctrl_iface PMKSA command.
+ */
+int pmksa_cache_auth_list(struct rsn_pmksa_cache *pmksa, char *buf, size_t len)
+{
+       int i, ret;
+       char *pos = buf;
+       struct rsn_pmksa_cache_entry *entry;
+       struct os_reltime now;
+
+       os_get_reltime(&now);
+       ret = os_snprintf(pos, buf + len - pos,
+                         "Index / SPA / PMKID / expiration (in seconds) / opportunistic\n");
+       if (os_snprintf_error(buf + len - pos, ret))
+               return pos - buf;
+       pos += ret;
+       i = 0;
+       entry = pmksa->pmksa;
+       while (entry) {
+               ret = os_snprintf(pos, buf + len - pos, "%d " MACSTR " ",
+                                 i, MAC2STR(entry->spa));
+               if (os_snprintf_error(buf + len - pos, ret))
+                       return pos - buf;
+               pos += ret;
+               pos += wpa_snprintf_hex(pos, buf + len - pos, entry->pmkid,
+                                       PMKID_LEN);
+               ret = os_snprintf(pos, buf + len - pos, " %d %d\n",
+                                 (int) (entry->expiration - now.sec),
+                                 entry->opportunistic);
+               if (os_snprintf_error(buf + len - pos, ret))
+                       return pos - buf;
+               pos += ret;
+               entry = entry->next;
+       }
+       return pos - buf;
+}