diff options
author | sam <sam@FreeBSD.org> | 2006-03-07 05:51:52 +0000 |
---|---|---|
committer | sam <sam@FreeBSD.org> | 2006-03-07 05:51:52 +0000 |
commit | 7ec4eb033d83d1150a5d461349c32d7113770a57 (patch) | |
tree | 4c08a6b60d0fad8945a0348eb843f0d8b2bd8d9d /contrib/hostapd/wpa.c | |
parent | 8410a7ea6cb51f8974a9d5506dacff8d565158f5 (diff) | |
download | FreeBSD-src-7ec4eb033d83d1150a5d461349c32d7113770a57.zip FreeBSD-src-7ec4eb033d83d1150a5d461349c32d7113770a57.tar.gz |
resolve merge conflicts
MFC after: 2 weeks
Diffstat (limited to 'contrib/hostapd/wpa.c')
-rw-r--r-- | contrib/hostapd/wpa.c | 110 |
1 files changed, 96 insertions, 14 deletions
diff --git a/contrib/hostapd/wpa.c b/contrib/hostapd/wpa.c index c0948e8..ec07b35 100644 --- a/contrib/hostapd/wpa.c +++ b/contrib/hostapd/wpa.c @@ -36,6 +36,8 @@ #include "eloop.h" #include "sta_info.h" #include "l2_packet.h" +#include "accounting.h" +#include "hostap_common.h" static void wpa_send_eapol_timeout(void *eloop_ctx, void *timeout_ctx); @@ -103,7 +105,7 @@ static const u8 RSN_KEY_DATA_PMKID[] = { 0x00, 0x0f, 0xac, 4 }; * Authenticated Key Management Suite Count (2 octets, little endian) * (default: 1) * Authenticated Key Management Suite List (4 * n octets) - * (default: unspec 802.1x) + * (default: unspec 802.1X) * WPA Capabilities (2 octets, little endian) (default: 0) */ @@ -125,7 +127,7 @@ struct wpa_ie_hdr { * Authenticated Key Management Suite Count (2 octets, little endian) * (default: 1) * Authenticated Key Management Suite List (4 * n octets) - * (default: unspec 802.1x) + * (default: unspec 802.1X) * RSN Capabilities (2 octets, little endian) (default: 0) * PMKID Count (2 octets) (default: 0) * PMKID List (16 * n octets) @@ -398,8 +400,8 @@ static void wpa_rekey_gtk(void *eloop_ctx, void *timeout_ctx) #ifdef CONFIG_RSN_PREAUTH -static void rsn_preauth_receive(void *ctx, unsigned char *src_addr, - unsigned char *buf, size_t len) +static void rsn_preauth_receive(void *ctx, const u8 *src_addr, + const u8 *buf, size_t len) { struct rsn_preauth_interface *piface = ctx; struct hostapd_data *hapd = piface->hapd; @@ -482,13 +484,12 @@ static int rsn_preauth_iface_add(struct hostapd_data *hapd, const char *ifname) } piface->l2 = l2_packet_init(piface->ifname, NULL, ETH_P_PREAUTH, - rsn_preauth_receive, piface); + rsn_preauth_receive, piface, 1); if (piface->l2 == NULL) { printf("Failed to open register layer 2 access to " "ETH_P_PREAUTH\n"); goto fail2; } - l2_packet_set_rx_l2_hdr(piface->l2, 1); piface->next = hapd->preauth_iface; hapd->preauth_iface = piface; @@ -553,6 +554,16 @@ static int rsn_preauth_iface_init(struct hostapd_data *hapd) } +static void rsn_preauth_finished_cb(void *eloop_ctx, void *timeout_ctx) +{ + struct hostapd_data *hapd = eloop_ctx; + struct sta_info *sta = timeout_ctx; + wpa_printf(MSG_DEBUG, "RSN: Removing pre-authentication STA entry for " + MACSTR, MAC2STR(sta->addr)); + ap_free_sta(hapd, sta); +} + + void rsn_preauth_finished(struct hostapd_data *hapd, struct sta_info *sta, int success) { @@ -567,7 +578,11 @@ void rsn_preauth_finished(struct hostapd_data *hapd, struct sta_info *sta, pmksa_cache_add(hapd, sta, key, dot11RSNAConfigPMKLifetime); } - ap_free_sta(hapd, sta); + /* + * Finish STA entry removal from timeout in order to avoid freeing + * STA data before the caller has finished processing. + */ + eloop_register_timeout(0, 0, rsn_preauth_finished_cb, hapd, sta); } @@ -600,8 +615,8 @@ void rsn_preauth_send(struct hostapd_data *hapd, struct sta_info *sta, ethhdr->h_proto = htons(ETH_P_PREAUTH); memcpy(ethhdr + 1, buf, len); - if (l2_packet_send(piface->l2, (u8 *) ethhdr, sizeof(*ethhdr) + len) < - 0) { + if (l2_packet_send(piface->l2, sta->addr, ETH_P_PREAUTH, (u8 *) ethhdr, + sizeof(*ethhdr) + len) < 0) { printf("Failed to send preauth packet using l2_packet_send\n"); } free(ethhdr); @@ -618,6 +633,10 @@ static inline void rsn_preauth_iface_deinit(struct hostapd_data *hapd) { } +static void rsn_preauth_finished_cb(void *eloop_ctx, void *timeout_ctx) +{ +} + void rsn_preauth_finished(struct hostapd_data *hapd, struct sta_info *sta, int success) { @@ -809,6 +828,16 @@ static void rsn_pmkid(const u8 *pmk, const u8 *aa, const u8 *spa, u8 *pmkid) static void pmksa_cache_set_expiration(struct hostapd_data *hapd); +static void _pmksa_cache_free_entry(struct rsn_pmksa_cache *entry) +{ + if (entry == NULL) + return; + free(entry->identity); + ieee802_1x_free_radius_class(&entry->radius_class); + free(entry); +} + + static void pmksa_cache_free_entry(struct hostapd_data *hapd, struct rsn_pmksa_cache *entry) { @@ -848,7 +877,7 @@ static void pmksa_cache_free_entry(struct hostapd_data *hapd, prev = pos; pos = pos->next; } - free(entry); + _pmksa_cache_free_entry(entry); } @@ -884,6 +913,54 @@ static void pmksa_cache_set_expiration(struct hostapd_data *hapd) } +static void pmksa_cache_from_eapol_data(struct rsn_pmksa_cache *entry, + struct eapol_state_machine *eapol) +{ + if (eapol == NULL) + return; + + if (eapol->identity) { + entry->identity = malloc(eapol->identity_len); + if (entry->identity) { + entry->identity_len = eapol->identity_len; + memcpy(entry->identity, eapol->identity, + eapol->identity_len); + } + } + + ieee802_1x_copy_radius_class(&entry->radius_class, + &eapol->radius_class); +} + + +static void pmksa_cache_to_eapol_data(struct rsn_pmksa_cache *entry, + struct eapol_state_machine *eapol) +{ + if (entry == NULL || eapol == NULL) + return; + + if (entry->identity) { + free(eapol->identity); + eapol->identity = malloc(entry->identity_len); + if (eapol->identity) { + eapol->identity_len = entry->identity_len; + memcpy(eapol->identity, entry->identity, + entry->identity_len); + } + wpa_hexdump_ascii(MSG_DEBUG, "STA identity from PMKSA", + eapol->identity, eapol->identity_len); + } + + ieee802_1x_free_radius_class(&eapol->radius_class); + ieee802_1x_copy_radius_class(&eapol->radius_class, + &entry->radius_class); + if (eapol->radius_class.attr) { + wpa_printf(MSG_DEBUG, "Copied %lu Class attribute(s) from " + "PMKSA", (unsigned long) eapol->radius_class.count); + } +} + + void pmksa_cache_add(struct hostapd_data *hapd, struct sta_info *sta, u8 *pmk, int session_timeout) { @@ -905,6 +982,7 @@ void pmksa_cache_add(struct hostapd_data *hapd, struct sta_info *sta, u8 *pmk, entry->expiration += dot11RSNAConfigPMKLifetime; entry->akmp = WPA_KEY_MGMT_IEEE8021X; memcpy(entry->spa, sta->addr, ETH_ALEN); + pmksa_cache_from_eapol_data(entry, sta->eapol_sm); /* Replace an old entry for the same STA (if found) with the new entry */ @@ -961,7 +1039,7 @@ static void pmksa_cache_free(struct hostapd_data *hapd) while (entry) { prev = entry; entry = entry->next; - free(prev); + _pmksa_cache_free_entry(prev); } eloop_cancel_timeout(pmksa_cache_expire, hapd, NULL); for (i = 0; i < PMKID_HASH_SIZE; i++) @@ -1001,7 +1079,7 @@ struct wpa_ie_data { }; -static int wpa_parse_wpa_ie_wpa(u8 *wpa_ie, size_t wpa_ie_len, +static int wpa_parse_wpa_ie_wpa(const u8 *wpa_ie, size_t wpa_ie_len, struct wpa_ie_data *data) { struct wpa_ie_hdr *hdr; @@ -1080,7 +1158,7 @@ static int wpa_parse_wpa_ie_wpa(u8 *wpa_ie, size_t wpa_ie_len, } -static int wpa_parse_wpa_ie_rsn(u8 *rsn_ie, size_t rsn_ie_len, +static int wpa_parse_wpa_ie_rsn(const u8 *rsn_ie, size_t rsn_ie_len, struct wpa_ie_data *data) { struct rsn_ie_hdr *hdr; @@ -1174,7 +1252,7 @@ static int wpa_parse_wpa_ie_rsn(u8 *rsn_ie, size_t rsn_ie_len, int wpa_validate_wpa_ie(struct hostapd_data *hapd, struct sta_info *sta, - u8 *wpa_ie, size_t wpa_ie_len, int version) + const u8 *wpa_ie, size_t wpa_ie_len, int version) { struct wpa_ie_data data; int ciphers, key_mgmt, res, i; @@ -1374,6 +1452,7 @@ void wpa_free_station(struct sta_info *sta) eloop_cancel_timeout(wpa_send_eapol_timeout, sm->hapd, sta); eloop_cancel_timeout(wpa_sm_call_step, sm->hapd, sta->wpa_sm); + eloop_cancel_timeout(rsn_preauth_finished_cb, sm->hapd, sta); free(sm->last_rx_eapol_key); free(sm); sta->wpa_sm = NULL; @@ -2090,6 +2169,7 @@ SM_STATE(WPA_PTK, INITPMK) if (sm->sta->pmksa) { wpa_printf(MSG_DEBUG, "WPA: PMK from PMKSA cache"); memcpy(sm->PMK, sm->sta->pmksa->pmk, WPA_PMK_LEN); + pmksa_cache_to_eapol_data(sm->sta->pmksa, sm->sta->eapol_sm); } else if ((key = ieee802_1x_get_key_crypt(sm->sta->eapol_sm, &len))) { wpa_printf(MSG_DEBUG, "WPA: PMK from EAPOL state machine " "(len=%lu)", (unsigned long) len); @@ -2296,6 +2376,8 @@ SM_STATE(WPA_PTK, PTKINITDONE) HOSTAPD_LEVEL_INFO, "pairwise key handshake completed " "(%s)", sm->sta->wpa == WPA_VERSION_WPA ? "WPA" : "RSN"); + if (sm->sta->wpa_key_mgmt == WPA_KEY_MGMT_PSK) + accounting_sta_start(sm->hapd, sm->sta); } |