Browse Source

Add Acct-Multi-Session-Id into RADIUS Accounting messages

This allows multiple sessions using the same PMKSA cache entry to be
combined more easily at the server side. Acct-Session-Id is still a
unique identifier for each association, while Acct-Multi-Session-Id will
maintain its value for all associations that use the same PMKSA.

Signed-off-by: Jouni Malinen <j@w1.fi>
Jouni Malinen 10 years ago
parent
commit
fcc306e3cc

+ 17 - 0
src/ap/accounting.c

@@ -10,6 +10,8 @@
 
 #include "utils/common.h"
 #include "utils/eloop.h"
+#include "eapol_auth/eapol_auth_sm.h"
+#include "eapol_auth/eapol_auth_sm_i.h"
 #include "radius/radius.h"
 #include "radius/radius_client.h"
 #include "hostapd.h"
@@ -49,6 +51,21 @@ static struct radius_msg * accounting_msg(struct hostapd_data *hapd,
 
 	if (sta) {
 		radius_msg_make_authenticator(msg, (u8 *) sta, sizeof(*sta));
+
+		if ((hapd->conf->wpa & 2) &&
+		    !hapd->conf->disable_pmksa_caching &&
+		    sta->eapol_sm && sta->eapol_sm->acct_multi_session_id_hi) {
+			os_snprintf(buf, sizeof(buf), "%08X+%08X",
+				    sta->eapol_sm->acct_multi_session_id_hi,
+				    sta->eapol_sm->acct_multi_session_id_lo);
+			if (!radius_msg_add_attr(
+				    msg, RADIUS_ATTR_ACCT_MULTI_SESSION_ID,
+				    (u8 *) buf, os_strlen(buf))) {
+				wpa_printf(MSG_INFO,
+					   "Could not add Acct-Multi-Session-Id");
+				goto fail;
+			}
+		}
 	} else {
 		radius_msg_make_authenticator(msg, (u8 *) hapd, sizeof(*hapd));
 	}

+ 6 - 0
src/ap/pmksa_cache_auth.c

@@ -146,6 +146,9 @@ static void pmksa_cache_from_eapol_data(struct rsn_pmksa_cache_entry *entry,
 
 	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;
 }
 
 
@@ -183,6 +186,9 @@ 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;
+
+	eapol->acct_multi_session_id_hi = entry->acct_multi_session_id_hi;
+	eapol->acct_multi_session_id_lo = entry->acct_multi_session_id_lo;
 }
 
 

+ 3 - 0
src/ap/pmksa_cache_auth.h

@@ -30,6 +30,9 @@ struct rsn_pmksa_cache_entry {
 	u8 eap_type_authsrv;
 	int vlan_id;
 	int opportunistic;
+
+	u32 acct_multi_session_id_hi;
+	u32 acct_multi_session_id_lo;
 };
 
 struct rsn_pmksa_cache;

+ 12 - 0
src/eapol_auth/eapol_auth_sm.c

@@ -851,6 +851,11 @@ eapol_auth_alloc(struct eapol_authenticator *eapol, const u8 *addr,
 		sm->radius_cui = wpabuf_alloc_copy(radius_cui,
 						   os_strlen(radius_cui));
 
+	sm->acct_multi_session_id_lo = eapol->acct_multi_session_id_lo++;
+	if (eapol->acct_multi_session_id_lo == 0)
+		eapol->acct_multi_session_id_hi++;
+	sm->acct_multi_session_id_hi = eapol->acct_multi_session_id_hi;
+
 	return sm;
 }
 
@@ -1127,6 +1132,7 @@ struct eapol_authenticator * eapol_auth_init(struct eapol_auth_config *conf,
 					     struct eapol_auth_cb *cb)
 {
 	struct eapol_authenticator *eapol;
+	struct os_time now;
 
 	eapol = os_zalloc(sizeof(*eapol));
 	if (eapol == NULL)
@@ -1153,6 +1159,12 @@ struct eapol_authenticator * eapol_auth_init(struct eapol_auth_config *conf,
 	eapol->cb.tx_key = cb->tx_key;
 	eapol->cb.eapol_event = cb->eapol_event;
 
+	/* Acct-Multi-Session-Id should be unique over reboots. If reliable
+	 * clock is not available, this could be replaced with reboot counter,
+	 * etc. */
+	os_get_time(&now);
+	eapol->acct_multi_session_id_hi = now.sec;
+
 	return eapol;
 }
 

+ 6 - 0
src/eapol_auth/eapol_auth_sm_i.h

@@ -30,6 +30,9 @@ struct eapol_authenticator {
 
 	u8 *default_wep_key;
 	u8 default_wep_key_idx;
+
+	u32 acct_multi_session_id_hi;
+	u32 acct_multi_session_id_lo;
 };
 
 
@@ -175,6 +178,9 @@ struct eapol_state_machine {
 	void *sta; /* station context pointer to use in callbacks */
 
 	int remediation;
+
+	u32 acct_multi_session_id_hi;
+	u32 acct_multi_session_id_lo;
 };
 
 #endif /* EAPOL_AUTH_SM_I_H */