18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* 28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * hostapd - PMKSA cache for IEEE 802.11i RSN 340b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt * Copyright (c) 2004-2008, 2012-2015, Jouni Malinen <j@w1.fi> 48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 5c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * This software may be distributed under the terms of the BSD license. 6c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * See README for more details. 78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "utils/includes.h" 108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "utils/common.h" 128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "utils/eloop.h" 138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eapol_auth/eapol_auth_sm.h" 148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eapol_auth/eapol_auth_sm_i.h" 15432d603c922e970f55866c63212d29c997438977Dmitry Shmidt#include "radius/radius_das.h" 168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "sta_info.h" 178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "ap_config.h" 188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "pmksa_cache_auth.h" 198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const int pmksa_cache_max_entries = 1024; 228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const int dot11RSNAConfigPMKLifetime = 43200; 238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct rsn_pmksa_cache { 258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define PMKID_HASH_SIZE 128 268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define PMKID_HASH(pmkid) (unsigned int) ((pmkid)[0] & 0x7f) 278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct rsn_pmksa_cache_entry *pmkid[PMKID_HASH_SIZE]; 288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct rsn_pmksa_cache_entry *pmksa; 298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int pmksa_count; 308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void (*free_cb)(struct rsn_pmksa_cache_entry *entry, void *ctx); 328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void *ctx; 338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}; 348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void pmksa_cache_set_expiration(struct rsn_pmksa_cache *pmksa); 378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void _pmksa_cache_free_entry(struct rsn_pmksa_cache_entry *entry) 408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4157c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt os_free(entry->vlan_desc); 428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(entry->identity); 4304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpabuf_free(entry->cui); 448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef CONFIG_NO_RADIUS 458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius_free_class(&entry->radius_class); 468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NO_RADIUS */ 479ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt bin_clear_free(entry, sizeof(*entry)); 488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 51f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidtvoid pmksa_cache_free_entry(struct rsn_pmksa_cache *pmksa, 52f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt struct rsn_pmksa_cache_entry *entry) 538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct rsn_pmksa_cache_entry *pos, *prev; 559ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt unsigned int hash; 568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pmksa->pmksa_count--; 588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pmksa->free_cb(entry, pmksa->ctx); 599ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt 609ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt /* unlink from hash list */ 619ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt hash = PMKID_HASH(entry->pmkid); 629ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt pos = pmksa->pmkid[hash]; 638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt prev = NULL; 648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (pos) { 658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos == entry) { 669ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt if (prev != NULL) 679ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt prev->hnext = entry->hnext; 689ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt else 699ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt pmksa->pmkid[hash] = entry->hnext; 708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt prev = pos; 738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = pos->hnext; 748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 769ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt /* unlink from entry list */ 778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = pmksa->pmksa; 788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt prev = NULL; 798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (pos) { 808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos == entry) { 818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (prev != NULL) 829ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt prev->next = entry->next; 838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 849ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt pmksa->pmksa = entry->next; 858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt prev = pos; 888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = pos->next; 898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 909ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt 918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt _pmksa_cache_free_entry(entry); 928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 95e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt/** 96e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt * pmksa_cache_auth_flush - Flush all PMKSA cache entries 97e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt * @pmksa: Pointer to PMKSA cache data from pmksa_cache_auth_init() 98e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt */ 99e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidtvoid pmksa_cache_auth_flush(struct rsn_pmksa_cache *pmksa) 100e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt{ 101e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt while (pmksa->pmksa) { 102e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: Flush PMKSA cache entry for " 103e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt MACSTR, MAC2STR(pmksa->pmksa->spa)); 104e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt pmksa_cache_free_entry(pmksa, pmksa->pmksa); 105e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt } 106e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt} 107e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt 108e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt 1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void pmksa_cache_expire(void *eloop_ctx, void *timeout_ctx) 1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct rsn_pmksa_cache *pmksa = eloop_ctx; 112fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt struct os_reltime now; 1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 114fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt os_get_reltime(&now); 1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (pmksa->pmksa && pmksa->pmksa->expiration <= now.sec) { 1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: expired PMKSA cache entry for " 117d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt MACSTR, MAC2STR(pmksa->pmksa->spa)); 118d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt pmksa_cache_free_entry(pmksa, pmksa->pmksa); 1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pmksa_cache_set_expiration(pmksa); 1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void pmksa_cache_set_expiration(struct rsn_pmksa_cache *pmksa) 1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int sec; 128fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt struct os_reltime now; 1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(pmksa_cache_expire, pmksa, NULL); 1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pmksa->pmksa == NULL) 1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 133fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt os_get_reltime(&now); 1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sec = pmksa->pmksa->expiration - now.sec; 1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sec < 0) 1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sec = 0; 1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_register_timeout(sec + 1, 0, pmksa_cache_expire, pmksa, NULL); 1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void pmksa_cache_from_eapol_data(struct rsn_pmksa_cache_entry *entry, 1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eapol_state_machine *eapol) 1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 14457c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt struct vlan_description *vlan_desc; 14557c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt 1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eapol == NULL) 1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eapol->identity) { 1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt entry->identity = os_malloc(eapol->identity_len); 1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (entry->identity) { 1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt entry->identity_len = eapol->identity_len; 1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(entry->identity, eapol->identity, 1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eapol->identity_len); 1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (eapol->radius_cui) 15904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt entry->cui = wpabuf_dup(eapol->radius_cui); 16004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef CONFIG_NO_RADIUS 1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius_copy_class(&entry->radius_class, &eapol->radius_class); 1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NO_RADIUS */ 1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt entry->eap_type_authsrv = eapol->eap_type_authsrv; 16657c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt 16757c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt vlan_desc = ((struct sta_info *) eapol->sta)->vlan_desc; 16857c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt if (vlan_desc && vlan_desc->notempty) { 16957c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt entry->vlan_desc = os_zalloc(sizeof(struct vlan_description)); 17057c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt if (entry->vlan_desc) 17157c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt *entry->vlan_desc = *vlan_desc; 17257c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt } else { 17357c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt entry->vlan_desc = NULL; 17457c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt } 175fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt 176b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt entry->acct_multi_session_id = eapol->acct_multi_session_id; 1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18057c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidtvoid pmksa_cache_to_eapol_data(struct hostapd_data *hapd, 18157c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt struct rsn_pmksa_cache_entry *entry, 1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eapol_state_machine *eapol) 1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (entry == NULL || eapol == NULL) 1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (entry->identity) { 1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(eapol->identity); 1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eapol->identity = os_malloc(entry->identity_len); 1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eapol->identity) { 1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eapol->identity_len = entry->identity_len; 1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(eapol->identity, entry->identity, 1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt entry->identity_len); 1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "STA identity from PMKSA", 1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eapol->identity, eapol->identity_len); 1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (entry->cui) { 20004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpabuf_free(eapol->radius_cui); 20104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt eapol->radius_cui = wpabuf_dup(entry->cui); 20204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 20304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef CONFIG_NO_RADIUS 2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius_free_class(&eapol->radius_class); 2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius_copy_class(&eapol->radius_class, &entry->radius_class); 2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NO_RADIUS */ 2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eapol->radius_class.attr) { 2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "Copied %lu Class attribute(s) from " 2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "PMKSA", (unsigned long) eapol->radius_class.count); 2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eapol->eap_type_authsrv = entry->eap_type_authsrv; 214e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt#ifndef CONFIG_NO_VLAN 215e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt ap_sta_set_vlan(hapd, eapol->sta, entry->vlan_desc); 216e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt#endif /* CONFIG_NO_VLAN */ 217fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt 218b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt eapol->acct_multi_session_id = entry->acct_multi_session_id; 2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void pmksa_cache_link_entry(struct rsn_pmksa_cache *pmksa, 2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct rsn_pmksa_cache_entry *entry) 2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct rsn_pmksa_cache_entry *pos, *prev; 2269ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt int hash; 2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Add the new entry; order by expiration time */ 2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = pmksa->pmksa; 2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt prev = NULL; 2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (pos) { 2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos->expiration > entry->expiration) 2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt prev = pos; 2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = pos->next; 2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (prev == NULL) { 2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt entry->next = pmksa->pmksa; 2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pmksa->pmksa = entry; 2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt entry->next = prev->next; 2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt prev->next = entry; 2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2449ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt 2459ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt hash = PMKID_HASH(entry->pmkid); 2469ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt entry->hnext = pmksa->pmkid[hash]; 2479ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt pmksa->pmkid[hash] = entry; 2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pmksa->pmksa_count++; 250a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (prev == NULL) 251a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt pmksa_cache_set_expiration(pmksa); 2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: added PMKSA cache entry for " MACSTR, 2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(entry->spa)); 2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "RSN: added PMKID", entry->pmkid, PMKID_LEN); 2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * pmksa_cache_auth_add - Add a PMKSA cache entry 2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @pmksa: Pointer to PMKSA cache data from pmksa_cache_auth_init() 2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @pmk: The new pairwise master key 2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @pmk_len: PMK length in bytes, usually PMK_LEN (32) 26357c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt * @pmkid: Calculated PMKID 264fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt * @kck: Key confirmation key or %NULL if not yet derived 265fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt * @kck_len: KCK length in bytes 2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @aa: Authenticator address 2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @spa: Supplicant address 2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @session_timeout: Session timeout 2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @eapol: Pointer to EAPOL state machine data 2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @akmp: WPA_KEY_MGMT_* used in key derivation 2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Pointer to the added PMKSA cache entry or %NULL on error 2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function create a PMKSA entry for a new PMK and adds it to the PMKSA 2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * cache. If an old entry is already in the cache for the same Supplicant, 2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * this entry will be replaced with the new entry. PMKID will be calculated 2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * based on the PMK. 2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct rsn_pmksa_cache_entry * 2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtpmksa_cache_auth_add(struct rsn_pmksa_cache *pmksa, 28057c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt const u8 *pmk, size_t pmk_len, const u8 *pmkid, 281fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt const u8 *kck, size_t kck_len, 282fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt const u8 *aa, const u8 *spa, int session_timeout, 283fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt struct eapol_state_machine *eapol, int akmp) 2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 285092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart struct rsn_pmksa_cache_entry *entry; 286092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart 287092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart entry = pmksa_cache_auth_create_entry(pmk, pmk_len, pmkid, kck, kck_len, 288092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart aa, spa, session_timeout, eapol, 289092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart akmp); 290092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart 291092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart if (pmksa_cache_auth_add_entry(pmksa, entry) < 0) 292092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart return NULL; 293092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart 294092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart return entry; 295092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart} 296092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart 297092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart 298092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart/** 299092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart * pmksa_cache_auth_create_entry - Create a PMKSA cache entry 300092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart * @pmk: The new pairwise master key 301092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart * @pmk_len: PMK length in bytes, usually PMK_LEN (32) 302092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart * @pmkid: Calculated PMKID 303092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart * @kck: Key confirmation key or %NULL if not yet derived 304092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart * @kck_len: KCK length in bytes 305092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart * @aa: Authenticator address 306092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart * @spa: Supplicant address 307092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart * @session_timeout: Session timeout 308092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart * @eapol: Pointer to EAPOL state machine data 309092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart * @akmp: WPA_KEY_MGMT_* used in key derivation 310092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart * Returns: Pointer to the added PMKSA cache entry or %NULL on error 311092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart * 312092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart * This function creates a PMKSA entry. 313092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart */ 314092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewartstruct rsn_pmksa_cache_entry * 315092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewartpmksa_cache_auth_create_entry(const u8 *pmk, size_t pmk_len, const u8 *pmkid, 316092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart const u8 *kck, size_t kck_len, const u8 *aa, 317092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart const u8 *spa, int session_timeout, 318092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart struct eapol_state_machine *eapol, int akmp) 319092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart{ 320092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart struct rsn_pmksa_cache_entry *entry; 321fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt struct os_reltime now; 3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 323d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (pmk_len > PMK_LEN_MAX) 3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 326fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt if (wpa_key_mgmt_suite_b(akmp) && !kck) 327fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt return NULL; 328fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt 3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt entry = os_zalloc(sizeof(*entry)); 3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (entry == NULL) 3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(entry->pmk, pmk, pmk_len); 3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt entry->pmk_len = pmk_len; 33457c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt if (pmkid) 33557c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt os_memcpy(entry->pmkid, pmkid, PMKID_LEN); 33657c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt else if (akmp == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) 33740b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt rsn_pmkid_suite_b_192(kck, kck_len, aa, spa, entry->pmkid); 33840b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt else if (wpa_key_mgmt_suite_b(akmp)) 339fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt rsn_pmkid_suite_b(kck, kck_len, aa, spa, entry->pmkid); 340fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt else 341d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt rsn_pmkid(pmk, pmk_len, aa, spa, entry->pmkid, akmp); 342fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt os_get_reltime(&now); 3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt entry->expiration = now.sec; 3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (session_timeout > 0) 3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt entry->expiration += session_timeout; 3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt entry->expiration += dot11RSNAConfigPMKLifetime; 3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt entry->akmp = akmp; 3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(entry->spa, spa, ETH_ALEN); 3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pmksa_cache_from_eapol_data(entry, eapol); 3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 352092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart return entry; 353092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart} 354092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart 355092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart 356092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart/** 357092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart * pmksa_cache_auth_add_entry - Add a PMKSA cache entry 358092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart * @pmksa: Pointer to PMKSA cache data from pmksa_cache_auth_init() 359092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart * @entry: Pointer to PMKSA cache entry 360092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart * 361092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart * This function adds PMKSA cache entry to the PMKSA cache. If an old entry is 362092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart * already in the cache for the same Supplicant, this entry will be replaced 363092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart * with the new entry. PMKID will be calculated based on the PMK. 364092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart */ 365092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewartint pmksa_cache_auth_add_entry(struct rsn_pmksa_cache *pmksa, 366092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart struct rsn_pmksa_cache_entry *entry) 367092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart{ 368092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart struct rsn_pmksa_cache_entry *pos; 369092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart 370092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart if (entry == NULL) 371092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart return -1; 372092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart 3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Replace an old entry for the same STA (if found) with the new entry 3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 375092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart pos = pmksa_cache_auth_get(pmksa, entry->spa, NULL); 3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos) 3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pmksa_cache_free_entry(pmksa, pos); 3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pmksa->pmksa_count >= pmksa_cache_max_entries && pmksa->pmksa) { 3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Remove the oldest entry to make room for the new entry */ 3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: removed the oldest PMKSA cache " 3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "entry (for " MACSTR ") to make room for new one", 3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(pmksa->pmksa->spa)); 3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pmksa_cache_free_entry(pmksa, pmksa->pmksa); 3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pmksa_cache_link_entry(pmksa, entry); 3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 389092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart return 0; 3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct rsn_pmksa_cache_entry * 3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtpmksa_cache_add_okc(struct rsn_pmksa_cache *pmksa, 3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct rsn_pmksa_cache_entry *old_entry, 3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *aa, const u8 *pmkid) 3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct rsn_pmksa_cache_entry *entry; 3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt entry = os_zalloc(sizeof(*entry)); 4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (entry == NULL) 4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(entry->pmkid, pmkid, PMKID_LEN); 4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(entry->pmk, old_entry->pmk, old_entry->pmk_len); 4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt entry->pmk_len = old_entry->pmk_len; 4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt entry->expiration = old_entry->expiration; 4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt entry->akmp = old_entry->akmp; 4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(entry->spa, old_entry->spa, ETH_ALEN); 4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt entry->opportunistic = 1; 4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (old_entry->identity) { 4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt entry->identity = os_malloc(old_entry->identity_len); 4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (entry->identity) { 4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt entry->identity_len = old_entry->identity_len; 4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(entry->identity, old_entry->identity, 4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt old_entry->identity_len); 4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 41804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (old_entry->cui) 41904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt entry->cui = wpabuf_dup(old_entry->cui); 4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef CONFIG_NO_RADIUS 4218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius_copy_class(&entry->radius_class, &old_entry->radius_class); 4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NO_RADIUS */ 4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt entry->eap_type_authsrv = old_entry->eap_type_authsrv; 42457c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt if (old_entry->vlan_desc) { 42557c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt entry->vlan_desc = os_zalloc(sizeof(struct vlan_description)); 42657c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt if (entry->vlan_desc) 42757c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt *entry->vlan_desc = *old_entry->vlan_desc; 42857c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt } else { 42957c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt entry->vlan_desc = NULL; 43057c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt } 4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt entry->opportunistic = 1; 4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pmksa_cache_link_entry(pmksa, entry); 4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return entry; 4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 4408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * pmksa_cache_auth_deinit - Free all entries in PMKSA cache 4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @pmksa: Pointer to PMKSA cache data from pmksa_cache_auth_init() 4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid pmksa_cache_auth_deinit(struct rsn_pmksa_cache *pmksa) 4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct rsn_pmksa_cache_entry *entry, *prev; 4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int i; 4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pmksa == NULL) 4498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt entry = pmksa->pmksa; 4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (entry) { 4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt prev = entry; 4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt entry = entry->next; 4558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt _pmksa_cache_free_entry(prev); 4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(pmksa_cache_expire, pmksa, NULL); 4589ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt pmksa->pmksa_count = 0; 4599ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt pmksa->pmksa = NULL; 4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < PMKID_HASH_SIZE; i++) 4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pmksa->pmkid[i] = NULL; 4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(pmksa); 4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * pmksa_cache_auth_get - Fetch a PMKSA cache entry 4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @pmksa: Pointer to PMKSA cache data from pmksa_cache_auth_init() 4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @spa: Supplicant address or %NULL to match any 4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @pmkid: PMKID or %NULL to match any 4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Pointer to PMKSA cache entry or %NULL if no match was found 4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct rsn_pmksa_cache_entry * 4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtpmksa_cache_auth_get(struct rsn_pmksa_cache *pmksa, 4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *spa, const u8 *pmkid) 4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct rsn_pmksa_cache_entry *entry; 4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4799ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt if (pmkid) { 4809ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt for (entry = pmksa->pmkid[PMKID_HASH(pmkid)]; entry; 4819ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt entry = entry->hnext) { 4829ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt if ((spa == NULL || 4839ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt os_memcmp(entry->spa, spa, ETH_ALEN) == 0) && 4849ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt os_memcmp(entry->pmkid, pmkid, PMKID_LEN) == 0) 4859ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt return entry; 4869ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt } 4879ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt } else { 4889ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt for (entry = pmksa->pmksa; entry; entry = entry->next) { 4899ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt if (spa == NULL || 4909ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt os_memcmp(entry->spa, spa, ETH_ALEN) == 0) 4919ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt return entry; 4929ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt } 4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4949ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt 4958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 5008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * pmksa_cache_get_okc - Fetch a PMKSA cache entry using OKC 5018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @pmksa: Pointer to PMKSA cache data from pmksa_cache_auth_init() 5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @aa: Authenticator address 5038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @spa: Supplicant address 5048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @pmkid: PMKID 5058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Pointer to PMKSA cache entry or %NULL if no match was found 5068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 5078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Use opportunistic key caching (OKC) to find a PMK for a supplicant. 5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct rsn_pmksa_cache_entry * pmksa_cache_get_okc( 5108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct rsn_pmksa_cache *pmksa, const u8 *aa, const u8 *spa, 5118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pmkid) 5128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct rsn_pmksa_cache_entry *entry; 5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 new_pmkid[PMKID_LEN]; 5158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5169ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt for (entry = pmksa->pmksa; entry; entry = entry->next) { 5178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(entry->spa, spa, ETH_ALEN) != 0) 5188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt continue; 5198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rsn_pmkid(entry->pmk, entry->pmk_len, aa, spa, new_pmkid, 520d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt entry->akmp); 5218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(new_pmkid, pmkid, PMKID_LEN) == 0) 5228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return entry; 5238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 5258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * pmksa_cache_auth_init - Initialize PMKSA cache 5308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @free_cb: Callback function to be called when a PMKSA cache entry is freed 5318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ctx: Context pointer for free_cb function 5328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Pointer to PMKSA cache data or %NULL on failure 5338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 5348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct rsn_pmksa_cache * 5358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtpmksa_cache_auth_init(void (*free_cb)(struct rsn_pmksa_cache_entry *entry, 5368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void *ctx), void *ctx) 5378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct rsn_pmksa_cache *pmksa; 5398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pmksa = os_zalloc(sizeof(*pmksa)); 5418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pmksa) { 5428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pmksa->free_cb = free_cb; 5438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pmksa->ctx = ctx; 5448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return pmksa; 5478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 548432d603c922e970f55866c63212d29c997438977Dmitry Shmidt 549432d603c922e970f55866c63212d29c997438977Dmitry Shmidt 550432d603c922e970f55866c63212d29c997438977Dmitry Shmidtstatic int das_attr_match(struct rsn_pmksa_cache_entry *entry, 551432d603c922e970f55866c63212d29c997438977Dmitry Shmidt struct radius_das_attrs *attr) 552432d603c922e970f55866c63212d29c997438977Dmitry Shmidt{ 553432d603c922e970f55866c63212d29c997438977Dmitry Shmidt int match = 0; 554432d603c922e970f55866c63212d29c997438977Dmitry Shmidt 555432d603c922e970f55866c63212d29c997438977Dmitry Shmidt if (attr->sta_addr) { 556432d603c922e970f55866c63212d29c997438977Dmitry Shmidt if (os_memcmp(attr->sta_addr, entry->spa, ETH_ALEN) != 0) 557432d603c922e970f55866c63212d29c997438977Dmitry Shmidt return 0; 558432d603c922e970f55866c63212d29c997438977Dmitry Shmidt match++; 559432d603c922e970f55866c63212d29c997438977Dmitry Shmidt } 560432d603c922e970f55866c63212d29c997438977Dmitry Shmidt 561432d603c922e970f55866c63212d29c997438977Dmitry Shmidt if (attr->acct_multi_session_id) { 562432d603c922e970f55866c63212d29c997438977Dmitry Shmidt char buf[20]; 563432d603c922e970f55866c63212d29c997438977Dmitry Shmidt 564b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt if (attr->acct_multi_session_id_len != 16) 565432d603c922e970f55866c63212d29c997438977Dmitry Shmidt return 0; 56657c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt os_snprintf(buf, sizeof(buf), "%016llX", 56757c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt (unsigned long long) entry->acct_multi_session_id); 568b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt if (os_memcmp(attr->acct_multi_session_id, buf, 16) != 0) 569432d603c922e970f55866c63212d29c997438977Dmitry Shmidt return 0; 570432d603c922e970f55866c63212d29c997438977Dmitry Shmidt match++; 571432d603c922e970f55866c63212d29c997438977Dmitry Shmidt } 572432d603c922e970f55866c63212d29c997438977Dmitry Shmidt 573432d603c922e970f55866c63212d29c997438977Dmitry Shmidt if (attr->cui) { 574432d603c922e970f55866c63212d29c997438977Dmitry Shmidt if (!entry->cui || 575432d603c922e970f55866c63212d29c997438977Dmitry Shmidt attr->cui_len != wpabuf_len(entry->cui) || 576432d603c922e970f55866c63212d29c997438977Dmitry Shmidt os_memcmp(attr->cui, wpabuf_head(entry->cui), 577432d603c922e970f55866c63212d29c997438977Dmitry Shmidt attr->cui_len) != 0) 578432d603c922e970f55866c63212d29c997438977Dmitry Shmidt return 0; 579432d603c922e970f55866c63212d29c997438977Dmitry Shmidt match++; 580432d603c922e970f55866c63212d29c997438977Dmitry Shmidt } 581432d603c922e970f55866c63212d29c997438977Dmitry Shmidt 582432d603c922e970f55866c63212d29c997438977Dmitry Shmidt if (attr->user_name) { 583432d603c922e970f55866c63212d29c997438977Dmitry Shmidt if (!entry->identity || 584432d603c922e970f55866c63212d29c997438977Dmitry Shmidt attr->user_name_len != entry->identity_len || 585432d603c922e970f55866c63212d29c997438977Dmitry Shmidt os_memcmp(attr->user_name, entry->identity, 586432d603c922e970f55866c63212d29c997438977Dmitry Shmidt attr->user_name_len) != 0) 587432d603c922e970f55866c63212d29c997438977Dmitry Shmidt return 0; 588432d603c922e970f55866c63212d29c997438977Dmitry Shmidt match++; 589432d603c922e970f55866c63212d29c997438977Dmitry Shmidt } 590432d603c922e970f55866c63212d29c997438977Dmitry Shmidt 591432d603c922e970f55866c63212d29c997438977Dmitry Shmidt return match; 592432d603c922e970f55866c63212d29c997438977Dmitry Shmidt} 593432d603c922e970f55866c63212d29c997438977Dmitry Shmidt 594432d603c922e970f55866c63212d29c997438977Dmitry Shmidt 595432d603c922e970f55866c63212d29c997438977Dmitry Shmidtint pmksa_cache_auth_radius_das_disconnect(struct rsn_pmksa_cache *pmksa, 596432d603c922e970f55866c63212d29c997438977Dmitry Shmidt struct radius_das_attrs *attr) 597432d603c922e970f55866c63212d29c997438977Dmitry Shmidt{ 598432d603c922e970f55866c63212d29c997438977Dmitry Shmidt int found = 0; 599432d603c922e970f55866c63212d29c997438977Dmitry Shmidt struct rsn_pmksa_cache_entry *entry, *prev; 600432d603c922e970f55866c63212d29c997438977Dmitry Shmidt 601432d603c922e970f55866c63212d29c997438977Dmitry Shmidt if (attr->acct_session_id) 602432d603c922e970f55866c63212d29c997438977Dmitry Shmidt return -1; 603432d603c922e970f55866c63212d29c997438977Dmitry Shmidt 604432d603c922e970f55866c63212d29c997438977Dmitry Shmidt entry = pmksa->pmksa; 605432d603c922e970f55866c63212d29c997438977Dmitry Shmidt while (entry) { 606432d603c922e970f55866c63212d29c997438977Dmitry Shmidt if (das_attr_match(entry, attr)) { 607432d603c922e970f55866c63212d29c997438977Dmitry Shmidt found++; 608432d603c922e970f55866c63212d29c997438977Dmitry Shmidt prev = entry; 609432d603c922e970f55866c63212d29c997438977Dmitry Shmidt entry = entry->next; 610432d603c922e970f55866c63212d29c997438977Dmitry Shmidt pmksa_cache_free_entry(pmksa, prev); 611432d603c922e970f55866c63212d29c997438977Dmitry Shmidt continue; 612432d603c922e970f55866c63212d29c997438977Dmitry Shmidt } 613432d603c922e970f55866c63212d29c997438977Dmitry Shmidt entry = entry->next; 614432d603c922e970f55866c63212d29c997438977Dmitry Shmidt } 615432d603c922e970f55866c63212d29c997438977Dmitry Shmidt 616432d603c922e970f55866c63212d29c997438977Dmitry Shmidt return found ? 0 : -1; 617432d603c922e970f55866c63212d29c997438977Dmitry Shmidt} 618e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt 619e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt 620e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt/** 621e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt * pmksa_cache_auth_list - Dump text list of entries in PMKSA cache 622e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt * @pmksa: Pointer to PMKSA cache data from pmksa_cache_auth_init() 623e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt * @buf: Buffer for the list 624e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt * @len: Length of the buffer 625e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt * Returns: Number of bytes written to buffer 626e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt * 627e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt * This function is used to generate a text format representation of the 628e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt * current PMKSA cache contents for the ctrl_iface PMKSA command. 629e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt */ 630e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidtint pmksa_cache_auth_list(struct rsn_pmksa_cache *pmksa, char *buf, size_t len) 631e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt{ 632e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt int i, ret; 633e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt char *pos = buf; 634e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt struct rsn_pmksa_cache_entry *entry; 635e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt struct os_reltime now; 636e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt 637e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt os_get_reltime(&now); 638e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt ret = os_snprintf(pos, buf + len - pos, 639e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt "Index / SPA / PMKID / expiration (in seconds) / opportunistic\n"); 640e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt if (os_snprintf_error(buf + len - pos, ret)) 641e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt return pos - buf; 642e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt pos += ret; 643e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt i = 0; 644e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt entry = pmksa->pmksa; 645e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt while (entry) { 646e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt ret = os_snprintf(pos, buf + len - pos, "%d " MACSTR " ", 647e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt i, MAC2STR(entry->spa)); 648e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt if (os_snprintf_error(buf + len - pos, ret)) 649e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt return pos - buf; 650e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt pos += ret; 651e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt pos += wpa_snprintf_hex(pos, buf + len - pos, entry->pmkid, 652e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt PMKID_LEN); 653e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt ret = os_snprintf(pos, buf + len - pos, " %d %d\n", 654e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt (int) (entry->expiration - now.sec), 655e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt entry->opportunistic); 656e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt if (os_snprintf_error(buf + len - pos, ret)) 657e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt return pos - buf; 658e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt pos += ret; 659e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt entry = entry->next; 660e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt } 661e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt return pos - buf; 662e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt} 663092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart 664092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart 665092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart#ifdef CONFIG_PMKSA_CACHE_EXTERNAL 666092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart#ifdef CONFIG_MESH 667092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart 668092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart/** 669092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart * pmksa_cache_auth_list_mesh - Dump text list of entries in PMKSA cache 670092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart * @pmksa: Pointer to PMKSA cache data from pmksa_cache_auth_init() 671092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart * @addr: MAC address of the peer (NULL means any) 672092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart * @buf: Buffer for the list 673092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart * @len: Length of the buffer 674092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart * Returns: Number of bytes written to buffer 675092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart * 676092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart * This function is used to generate a text format representation of the 677092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart * current PMKSA cache contents for the ctrl_iface PMKSA_GET command to store 678092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart * in external storage. 679092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart */ 680092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewartint pmksa_cache_auth_list_mesh(struct rsn_pmksa_cache *pmksa, const u8 *addr, 681092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart char *buf, size_t len) 682092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart{ 683092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart int ret; 684092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart char *pos, *end; 685092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart struct rsn_pmksa_cache_entry *entry; 686092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart struct os_reltime now; 687092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart 688092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart pos = buf; 689092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart end = buf + len; 690092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart os_get_reltime(&now); 691092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart 692092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart 693092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart /* 694092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart * Entry format: 695092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart * <BSSID> <PMKID> <PMK> <expiration in seconds> 696092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart */ 697092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart for (entry = pmksa->pmksa; entry; entry = entry->next) { 698092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart if (addr && os_memcmp(entry->spa, addr, ETH_ALEN) != 0) 699092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart continue; 700092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart 701092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart ret = os_snprintf(pos, end - pos, MACSTR " ", 702092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart MAC2STR(entry->spa)); 703092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart if (os_snprintf_error(end - pos, ret)) 704092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart return 0; 705092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart pos += ret; 706092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart 707092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart pos += wpa_snprintf_hex(pos, end - pos, entry->pmkid, 708092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart PMKID_LEN); 709092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart 710092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart ret = os_snprintf(pos, end - pos, " "); 711092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart if (os_snprintf_error(end - pos, ret)) 712092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart return 0; 713092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart pos += ret; 714092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart 715092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart pos += wpa_snprintf_hex(pos, end - pos, entry->pmk, 716092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart entry->pmk_len); 717092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart 718092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart ret = os_snprintf(pos, end - pos, " %d\n", 719092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart (int) (entry->expiration - now.sec)); 720092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart if (os_snprintf_error(end - pos, ret)) 721092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart return 0; 722092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart pos += ret; 723092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart } 724092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart 725092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart return pos - buf; 726092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart} 727092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart 728092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart#endif /* CONFIG_MESH */ 729092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */ 730