diff --git a/src/ap/accounting.c b/src/ap/accounting.c index edda88b53..82443a1f3 100644 --- a/src/ap/accounting.c +++ b/src/ap/accounting.c @@ -1,6 +1,6 @@ /* * hostapd / RADIUS Accounting - * Copyright (c) 2002-2009, Jouni Malinen + * Copyright (c) 2002-2009, 2012, Jouni Malinen * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -39,6 +39,7 @@ static struct radius_msg * accounting_msg(struct hostapd_data *hapd, u8 *val; size_t len; int i; + struct wpabuf *b; msg = radius_msg_new(RADIUS_CODE_ACCOUNTING_REQUEST, radius_client_get_id(hapd->radius)); @@ -167,6 +168,15 @@ static struct radius_msg * accounting_msg(struct hostapd_data *hapd, goto fail; } } + + b = ieee802_1x_get_radius_cui(sta->eapol_sm); + if (b && + !radius_msg_add_attr(msg, + RADIUS_ATTR_CHARGEABLE_USER_IDENTITY, + wpabuf_head(b), wpabuf_len(b))) { + wpa_printf(MSG_ERROR, "Could not add CUI"); + goto fail; + } } return msg; diff --git a/src/ap/ieee802_1x.c b/src/ap/ieee802_1x.c index 8a25242dc..b12ed51e6 100644 --- a/src/ap/ieee802_1x.c +++ b/src/ap/ieee802_1x.c @@ -978,6 +978,7 @@ void ieee802_1x_free_station(struct sta_info *sta) #ifndef CONFIG_NO_RADIUS radius_msg_free(sm->last_recv_radius); radius_free_class(&sm->radius_class); + wpabuf_free(sm->radius_cui); #endif /* CONFIG_NO_RADIUS */ os_free(sm->identity); @@ -1199,6 +1200,32 @@ static void ieee802_1x_update_sta_identity(struct hostapd_data *hapd, } +/* Update CUI based on Chargeable-User-Identity attribute in Access-Accept */ +static void ieee802_1x_update_sta_cui(struct hostapd_data *hapd, + struct sta_info *sta, + struct radius_msg *msg) +{ + struct eapol_state_machine *sm = sta->eapol_sm; + struct wpabuf *cui; + u8 *buf; + size_t len; + + if (sm == NULL) + return; + + if (radius_msg_get_attr_ptr(msg, RADIUS_ATTR_CHARGEABLE_USER_IDENTITY, + &buf, &len, NULL) < 0) + return; + + cui = wpabuf_alloc_copy(buf, len); + if (cui == NULL) + return; + + wpabuf_free(sm->radius_cui); + sm->radius_cui = cui; +} + + struct sta_id_search { u8 identifier; struct eapol_state_machine *sm; @@ -1358,6 +1385,7 @@ ieee802_1x_receive_auth(struct radius_msg *msg, struct radius_msg *req, shared_secret_len); ieee802_1x_store_radius_class(hapd, sta, msg); ieee802_1x_update_sta_identity(hapd, sta, msg); + ieee802_1x_update_sta_cui(hapd, sta, msg); if (sm->eap_if->eapKeyAvailable && wpa_auth_pmksa_add(sta->wpa_sm, sm->eapol_key_crypt, session_timeout_set ? @@ -1875,6 +1903,14 @@ u8 * ieee802_1x_get_radius_class(struct eapol_state_machine *sm, size_t *len, } +struct wpabuf * ieee802_1x_get_radius_cui(struct eapol_state_machine *sm) +{ + if (sm == NULL) + return NULL; + return sm->radius_cui; +} + + const u8 * ieee802_1x_get_key(struct eapol_state_machine *sm, size_t *len) { *len = 0; diff --git a/src/ap/ieee802_1x.h b/src/ap/ieee802_1x.h index 58f6084ed..f9b05cafd 100644 --- a/src/ap/ieee802_1x.h +++ b/src/ap/ieee802_1x.h @@ -67,6 +67,7 @@ int ieee802_1x_eapol_tx_status(struct hostapd_data *hapd, struct sta_info *sta, 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); +struct wpabuf * ieee802_1x_get_radius_cui(struct eapol_state_machine *sm); const u8 * ieee802_1x_get_key(struct eapol_state_machine *sm, size_t *len); void ieee802_1x_notify_port_enabled(struct eapol_state_machine *sm, int enabled); diff --git a/src/eapol_auth/eapol_auth_sm_i.h b/src/eapol_auth/eapol_auth_sm_i.h index d0b7641f2..d7f893a1d 100644 --- a/src/eapol_auth/eapol_auth_sm_i.h +++ b/src/eapol_auth/eapol_auth_sm_i.h @@ -157,6 +157,7 @@ struct eapol_state_machine { * Authentication server */ u8 eap_type_supp; /* EAP type of the last EAP packet from Supplicant */ struct radius_class_data radius_class; + struct wpabuf *radius_cui; /* Chargeable-User-Identity */ /* Keys for encrypting and signing EAPOL-Key frames */ u8 *eapol_key_sign;