aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJouni Malinen <j@w1.fi>2005-06-26 18:27:44 (GMT)
committerJouni Malinen <j@w1.fi>2005-06-26 18:27:44 (GMT)
commite5cffc252494e770eed1d28dcc072343ff9577dc (patch)
treec3cfc92ed77f7c8122e789b282582184956c1f2c
parent71ed7a35c0a7c0b9c01cb01c80c5e6ac0e0fbb1b (diff)
downloadhostap-history-e5cffc252494e770eed1d28dcc072343ff9577dc.zip
hostap-history-e5cffc252494e770eed1d28dcc072343ff9577dc.tar.gz
hostap-history-e5cffc252494e770eed1d28dcc072343ff9577dc.tar.bz2
Fixed PMKSA caching to copy User-Name and Class attributes so that
RADIUS accounting gets correct information. This is also needed for RSN pre-authentication. Bug 51
-rw-r--r--hostapd/ChangeLog4
-rw-r--r--hostapd/eapol_sm.h8
-rw-r--r--hostapd/ieee802_1x.c62
-rw-r--r--hostapd/ieee802_1x.h6
-rw-r--r--hostapd/wpa.c64
-rw-r--r--hostapd/wpa.h3
6 files changed, 126 insertions, 21 deletions
diff --git a/hostapd/ChangeLog b/hostapd/ChangeLog
index 6892f41..6defa3d 100644
--- a/hostapd/ChangeLog
+++ b/hostapd/ChangeLog
@@ -1,5 +1,9 @@
ChangeLog for hostapd
+????-??-?? - v0.4.3
+ * fixed PMKSA caching to copy User-Name and Class attributes so that
+ RADIUS accounting gets correct information
+
2005-06-12 - v0.4.2
* EAP-PAX is now registered as EAP type 46
* fixed EAP-PAX MAC calculation
diff --git a/hostapd/eapol_sm.h b/hostapd/eapol_sm.h
index db6fc14..0c34b4f 100644
--- a/hostapd/eapol_sm.h
+++ b/hostapd/eapol_sm.h
@@ -115,6 +115,11 @@ struct radius_attr_data {
size_t len;
};
+struct radius_class_data {
+ struct radius_attr_data *attr;
+ size_t count;
+};
+
struct eapol_state_machine {
/* timers */
int aWhile;
@@ -180,8 +185,7 @@ struct eapol_state_machine {
size_t last_eap_radius_len;
u8 *identity;
size_t identity_len;
- struct radius_attr_data *radius_class;
- size_t radius_class_count;
+ struct radius_class_data radius_class;
/* Keys for encrypting and signing EAPOL-Key frames */
u8 *eapol_key_sign;
diff --git a/hostapd/ieee802_1x.c b/hostapd/ieee802_1x.c
index c9ea8f0..865acb8 100644
--- a/hostapd/ieee802_1x.c
+++ b/hostapd/ieee802_1x.c
@@ -840,16 +840,44 @@ void ieee802_1x_new_station(hostapd *hapd, struct sta_info *sta)
}
-static void ieee802_1x_free_radius_class(struct eapol_state_machine *sm)
+void ieee802_1x_free_radius_class(struct radius_class_data *class)
{
int i;
- if (sm->radius_class == NULL)
+ if (class == NULL)
return;
- for (i = 0; i < sm->radius_class_count; i++)
- free(sm->radius_class[i].data);
- free(sm->radius_class);
- sm->radius_class = NULL;
- sm->radius_class_count = 0;
+ for (i = 0; i < class->count; i++)
+ free(class->attr[i].data);
+ free(class->attr);
+ class->attr = NULL;
+ class->count = 0;
+}
+
+
+int ieee802_1x_copy_radius_class(struct radius_class_data *dst,
+ struct radius_class_data *src)
+{
+ size_t i;
+
+ if (src->attr == NULL)
+ return 0;
+
+ dst->attr = malloc(src->count * sizeof(struct radius_attr_data));
+ if (dst->attr == NULL)
+ return -1;
+
+ memset(dst->attr, 0, src->count * sizeof(struct radius_attr_data));
+ dst->count = 0;
+
+ for (i = 0; i < src->count; i++) {
+ dst->attr[i].data = malloc(src->attr[i].len);
+ if (dst->attr[i].data == NULL)
+ break;
+ dst->count++;
+ memcpy(dst->attr[i].data, src->attr[i].data, src->attr[i].len);
+ dst->attr[i].len = src->attr[i].len;
+ }
+
+ return 0;
}
@@ -872,7 +900,7 @@ void ieee802_1x_free_station(struct sta_info *sta)
free(sm->last_eap_supp);
free(sm->last_eap_radius);
free(sm->identity);
- ieee802_1x_free_radius_class(sm);
+ ieee802_1x_free_radius_class(&sm->radius_class);
free(sm->eapol_key_sign);
free(sm->eapol_key_crypt);
eapol_sm_free(sm);
@@ -1023,7 +1051,7 @@ static void ieee802_1x_store_radius_class(struct hostapd_data *hapd,
sm == NULL)
return;
- ieee802_1x_free_radius_class(sm);
+ ieee802_1x_free_radius_class(&sm->radius_class);
count = radius_msg_count_attr(msg, RADIUS_ATTR_CLASS, 1);
if (count <= 0)
return;
@@ -1055,11 +1083,11 @@ static void ieee802_1x_store_radius_class(struct hostapd_data *hapd,
nclass_count++;
}
- sm->radius_class = nclass;
- sm->radius_class_count = nclass_count;
+ sm->radius_class.attr = nclass;
+ sm->radius_class.count = nclass_count;
HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "IEEE 802.1X: Stored %lu RADIUS "
"Class attributes for " MACSTR "\n",
- (unsigned long) sm->radius_class_count,
+ (unsigned long) sm->radius_class.count,
MAC2STR(sta->addr));
}
@@ -1191,12 +1219,12 @@ ieee802_1x_receive_auth(struct radius_msg *msg, struct radius_msg *req,
override_eapReq = 1;
ieee802_1x_get_keys(hapd, sta, msg, req, shared_secret,
shared_secret_len);
+ ieee802_1x_store_radius_class(hapd, sta, msg);
if (sm->keyAvailable) {
pmksa_cache_add(hapd, sta, sm->eapol_key_crypt,
session_timeout_set ?
session_timeout : -1);
}
- ieee802_1x_store_radius_class(hapd, sta, msg);
break;
case RADIUS_CODE_ACCESS_REJECT:
sm->eapFail = TRUE;
@@ -1521,12 +1549,12 @@ u8 * ieee802_1x_get_identity(struct eapol_state_machine *sm, size_t *len)
u8 * ieee802_1x_get_radius_class(struct eapol_state_machine *sm, size_t *len,
int idx)
{
- if (sm == NULL || sm->radius_class == NULL ||
- idx >= sm->radius_class_count)
+ if (sm == NULL || sm->radius_class.attr == NULL ||
+ idx >= sm->radius_class.count)
return NULL;
- *len = sm->radius_class[idx].len;
- return sm->radius_class[idx].data;
+ *len = sm->radius_class.attr[idx].len;
+ return sm->radius_class.attr[idx].data;
}
diff --git a/hostapd/ieee802_1x.h b/hostapd/ieee802_1x.h
index e544a93..d60221e 100644
--- a/hostapd/ieee802_1x.h
+++ b/hostapd/ieee802_1x.h
@@ -84,4 +84,10 @@ void hostapd_get_ntp_timestamp(u8 *buf);
void ieee802_1x_finished(struct hostapd_data *hapd, struct sta_info *sta,
int success);
+struct radius_class_data;
+
+void ieee802_1x_free_radius_class(struct radius_class_data *class);
+int ieee802_1x_copy_radius_class(struct radius_class_data *dst,
+ struct radius_class_data *src);
+
#endif /* IEEE802_1X_H */
diff --git a/hostapd/wpa.c b/hostapd/wpa.c
index 87916aa..15558eb 100644
--- a/hostapd/wpa.c
+++ b/hostapd/wpa.c
@@ -807,6 +807,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)
{
@@ -846,7 +856,7 @@ static void pmksa_cache_free_entry(struct hostapd_data *hapd,
prev = pos;
pos = pos->next;
}
- free(entry);
+ _pmksa_cache_free_entry(entry);
}
@@ -882,6 +892,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 %d Class attribute(s) from "
+ "PMKSA", eapol->radius_class.count);
+ }
+}
+
+
void pmksa_cache_add(struct hostapd_data *hapd, struct sta_info *sta, u8 *pmk,
int session_timeout)
{
@@ -903,6 +961,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
*/
@@ -959,7 +1018,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++)
@@ -2088,6 +2147,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);
diff --git a/hostapd/wpa.h b/hostapd/wpa.h
index 62e4e1a..62159e7 100644
--- a/hostapd/wpa.h
+++ b/hostapd/wpa.h
@@ -16,6 +16,9 @@ struct rsn_pmksa_cache {
time_t expiration;
int akmp; /* WPA_KEY_MGMT_* */
u8 spa[ETH_ALEN];
+ u8 *identity;
+ size_t identity_len;
+ struct radius_class_data radius_class;
};
struct rsn_preauth_interface {