Compare commits

...

6 commits

Author SHA1 Message Date
Tom Barthe
48e0ed037b Retrieve and use a per-PSK vlan_description
Signed-off-by: Tom Barthe <jeltz+hostap@auro.re>
2021-11-03 23:35:24 +01:00
Tom Barthe
0b17c48b9b Add default_radius_vlan in sta_info
Used to store the vlan_description corresponding to RADIUS tag 0.

Signed-off-by: Tom Barthe <jeltz+hostap@auro.re>
2021-11-03 23:35:15 +01:00
Tom Barthe
a6fc725f4b Fix selection of Tunnel* attributes by tag
The initial implementation was doing useless work.

Signed-off-by: Tom Barthe <jeltz+hostap@auro.re>
2021-10-11 04:56:57 +02:00
Tom Barthe
2ebf3674f5 Add a per PSK vlan_description
Signed-off-by: Tom Barthe <jeltz+hostap@auro.re>
2021-10-11 04:56:55 +02:00
Tom Barthe
12c14a8dd5 Replace some vlan_ids with vlan_descriptions
It should ease the integration of PPSK.

Signed-off-by: Tom Barthe <jeltz+hostap@auro.re>
2021-10-11 04:56:51 +02:00
Tom Barthe
7ac437a745 Support for RADIUS attributes filtering by tag
Signed-off-by: Tom Barthe <jeltz+hostap@auro.re>
2021-10-11 04:56:46 +02:00
12 changed files with 140 additions and 86 deletions

View file

@ -1094,15 +1094,28 @@ const char * hostapd_get_vlan_id_ifname(struct hostapd_vlan *vlan, int vlan_id)
} }
static struct vlan_description vlan_desc_from_id(int vlan_id)
{
struct vlan_description vlan_desc;
os_memset(&vlan_desc, 0, sizeof(vlan_desc));
vlan_desc.notempty = 1;
vlan_desc.untagged = vlan_id;
return vlan_desc;
}
const u8 * hostapd_get_psk(const struct hostapd_bss_config *conf, const u8 * hostapd_get_psk(const struct hostapd_bss_config *conf,
const u8 *addr, const u8 *p2p_dev_addr, const u8 *addr, const u8 *p2p_dev_addr,
const u8 *prev_psk, int *vlan_id) const u8 *prev_psk, struct vlan_description *vlan_desc)
{ {
struct hostapd_wpa_psk *psk; struct hostapd_wpa_psk *psk;
int next_ok = prev_psk == NULL; int next_ok = prev_psk == NULL;
if (vlan_id) if (vlan_desc)
*vlan_id = 0; vlan_desc->notempty = 0;
if (p2p_dev_addr && !is_zero_ether_addr(p2p_dev_addr)) { if (p2p_dev_addr && !is_zero_ether_addr(p2p_dev_addr)) {
wpa_printf(MSG_DEBUG, "Searching a PSK for " MACSTR wpa_printf(MSG_DEBUG, "Searching a PSK for " MACSTR
@ -1122,8 +1135,8 @@ const u8 * hostapd_get_psk(const struct hostapd_bss_config *conf,
(!addr && p2p_dev_addr && (!addr && p2p_dev_addr &&
os_memcmp(psk->p2p_dev_addr, p2p_dev_addr, ETH_ALEN) == os_memcmp(psk->p2p_dev_addr, p2p_dev_addr, ETH_ALEN) ==
0))) { 0))) {
if (vlan_id) if (vlan_desc)
*vlan_id = psk->vlan_id; *vlan_desc = vlan_desc_from_id(psk->vlan_id);
return psk->psk; return psk->psk;
} }

View file

@ -152,6 +152,8 @@ struct hostapd_sta_wpa_psk_short {
u8 psk[PMK_LEN]; u8 psk[PMK_LEN];
char passphrase[MAX_PASSPHRASE_LEN + 1]; char passphrase[MAX_PASSPHRASE_LEN + 1];
int ref; /* (number of references held) - 1 */ int ref; /* (number of references held) - 1 */
struct vlan_description vlan;
u8 tag;
}; };
struct hostapd_wpa_psk { struct hostapd_wpa_psk {
@ -1174,7 +1176,8 @@ int hostapd_maclist_found(struct mac_acl_entry *list, int num_entries,
int hostapd_rate_found(int *list, int rate); int hostapd_rate_found(int *list, int rate);
const u8 * hostapd_get_psk(const struct hostapd_bss_config *conf, const u8 * hostapd_get_psk(const struct hostapd_bss_config *conf,
const u8 *addr, const u8 *p2p_dev_addr, const u8 *addr, const u8 *p2p_dev_addr,
const u8 *prev_psk, int *vlan_id); const u8 *prev_psk,
struct vlan_description *vlan_desc);
int hostapd_setup_wpa_psk(struct hostapd_bss_config *conf); int hostapd_setup_wpa_psk(struct hostapd_bss_config *conf);
int hostapd_vlan_valid(struct hostapd_vlan *vlan, int hostapd_vlan_valid(struct hostapd_vlan *vlan,
struct vlan_description *vlan_desc); struct vlan_description *vlan_desc);

View file

@ -2321,25 +2321,11 @@ ieee802_11_set_radius_info(struct hostapd_data *hapd, struct sta_info *sta,
{ {
u32 session_timeout = info->session_timeout; u32 session_timeout = info->session_timeout;
u32 acct_interim_interval = info->acct_interim_interval; u32 acct_interim_interval = info->acct_interim_interval;
struct vlan_description *vlan_id = &info->vlan_id;
struct hostapd_sta_wpa_psk_short *psk = info->psk; struct hostapd_sta_wpa_psk_short *psk = info->psk;
char *identity = info->identity; char *identity = info->identity;
char *radius_cui = info->radius_cui; char *radius_cui = info->radius_cui;
if (vlan_id->notempty && sta->default_radius_vlan = info->vlan_id;
!hostapd_vlan_valid(hapd->conf->vlan, vlan_id)) {
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_RADIUS,
HOSTAPD_LEVEL_INFO,
"Invalid VLAN %d%s received from RADIUS server",
vlan_id->untagged,
vlan_id->tagged[0] ? "+" : "");
return -1;
}
if (ap_sta_set_vlan(hapd, sta, vlan_id) < 0)
return -1;
if (sta->vlan_id)
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_RADIUS,
HOSTAPD_LEVEL_INFO, "VLAN ID %d", sta->vlan_id);
hostapd_free_psk_list(sta->psk); hostapd_free_psk_list(sta->psk);
if (hapd->conf->wpa_psk_radius != PSK_RADIUS_IGNORED) if (hapd->conf->wpa_psk_radius != PSK_RADIUS_IGNORED)

View file

@ -380,6 +380,7 @@ static void decode_tunnel_passwords(struct hostapd_data *hapd,
char *passphrase; char *passphrase;
size_t i; size_t i;
struct hostapd_sta_wpa_psk_short *psk; struct hostapd_sta_wpa_psk_short *psk;
u8 tag = 0;
/* /*
* Decode all tunnel passwords as PSK and save them into a linked list. * Decode all tunnel passwords as PSK and save them into a linked list.
@ -387,7 +388,7 @@ static void decode_tunnel_passwords(struct hostapd_data *hapd,
for (i = 0; ; i++) { for (i = 0; ; i++) {
passphrase = radius_msg_get_tunnel_password( passphrase = radius_msg_get_tunnel_password(
msg, &passphraselen, shared_secret, shared_secret_len, msg, &passphraselen, shared_secret, shared_secret_len,
req, i); req, i, &tag);
/* /*
* Passphrase is NULL iff there is no i-th Tunnel-Password * Passphrase is NULL iff there is no i-th Tunnel-Password
* attribute in msg. * attribute in msg.
@ -424,6 +425,7 @@ static void decode_tunnel_passwords(struct hostapd_data *hapd,
psk->is_passphrase = 1; psk->is_passphrase = 1;
} }
psk->next = cache->info.psk; psk->next = cache->info.psk;
psk->tag = tag;
cache->info.psk = psk; cache->info.psk = psk;
psk = NULL; psk = NULL;
} }
@ -455,6 +457,8 @@ hostapd_acl_recv_radius(struct radius_msg *msg, struct radius_msg *req,
struct hostapd_cached_radius_acl *cache; struct hostapd_cached_radius_acl *cache;
struct radius_sta *info; struct radius_sta *info;
struct radius_hdr *hdr = radius_msg_get_hdr(msg); struct radius_hdr *hdr = radius_msg_get_hdr(msg);
struct hostapd_sta_wpa_psk_short *psk;
int vlan_psk_notempty = 1;
query = hapd->acl_queries; query = hapd->acl_queries;
prev = NULL; prev = NULL;
@ -513,14 +517,26 @@ hostapd_acl_recv_radius(struct radius_msg *msg, struct radius_msg *req,
info->acct_interim_interval = 0; info->acct_interim_interval = 0;
} }
if (hapd->conf->ssid.dynamic_vlan != DYNAMIC_VLAN_DISABLED)
info->vlan_id.notempty = !!radius_msg_get_vlanid(
msg, &info->vlan_id.untagged,
MAX_NUM_TAGGED_VLAN, info->vlan_id.tagged);
decode_tunnel_passwords(hapd, shared_secret, shared_secret_len, decode_tunnel_passwords(hapd, shared_secret, shared_secret_len,
msg, req, cache); msg, req, cache);
if (hapd->conf->ssid.dynamic_vlan != DYNAMIC_VLAN_DISABLED) {
/*
* Fill in the "default" VLAN (in case there is no
* Tunnel* attribute associated with the PSK)
*/
info->vlan_id.notempty = !!radius_msg_get_vlanid(
msg, &info->vlan_id.untagged,
MAX_NUM_TAGGED_VLAN, info->vlan_id.tagged, 0);
/* Fill in per PSK VLAN descriptions */
for (psk = info->psk; psk; psk = psk->next) {
psk->vlan.notempty = !!radius_msg_get_vlanid(
msg, &psk->vlan.untagged,
MAX_NUM_TAGGED_VLAN, psk->vlan.tagged,
psk->tag);
}
}
if (radius_msg_get_attr_ptr(msg, RADIUS_ATTR_USER_NAME, if (radius_msg_get_attr_ptr(msg, RADIUS_ATTR_USER_NAME,
&buf, &len, NULL) == 0) { &buf, &len, NULL) == 0) {
info->identity = os_zalloc(len + 1); info->identity = os_zalloc(len + 1);
@ -549,8 +565,22 @@ hostapd_acl_recv_radius(struct radius_msg *msg, struct radius_msg *req,
info->vlan_id.tagged[0] ? "+" : ""); info->vlan_id.tagged[0] ? "+" : "");
os_memset(&info->vlan_id, 0, sizeof(info->vlan_id)); os_memset(&info->vlan_id, 0, sizeof(info->vlan_id));
} }
for (psk = info->psk; psk; psk = psk->next) {
if (psk->vlan.notempty &&
!hostapd_vlan_valid(hapd->conf->vlan, &psk->vlan)) {
hostapd_logger(hapd, query->addr,
HOSTAPD_MODULE_RADIUS,
HOSTAPD_LEVEL_INFO,
"Invalid VLAN %d%s received from RADIUS server",
psk->vlan.untagged,
psk->vlan.tagged[0] ? "+" : "");
os_memset(&psk->vlan, 0, sizeof(psk->vlan));
}
vlan_psk_notempty &= psk->vlan.notempty;
}
if (hapd->conf->ssid.dynamic_vlan == DYNAMIC_VLAN_REQUIRED && if (hapd->conf->ssid.dynamic_vlan == DYNAMIC_VLAN_REQUIRED &&
!info->vlan_id.notempty) !info->vlan_id.notempty && !vlan_psk_notempty)
cache->accepted = HOSTAPD_ACL_REJECT; cache->accepted = HOSTAPD_ACL_REJECT;
} else } else
cache->accepted = HOSTAPD_ACL_REJECT; cache->accepted = HOSTAPD_ACL_REJECT;

View file

@ -1876,7 +1876,7 @@ static int ieee802_1x_update_vlan(struct radius_msg *msg,
os_memset(&vlan_desc, 0, sizeof(vlan_desc)); os_memset(&vlan_desc, 0, sizeof(vlan_desc));
vlan_desc.notempty = !!radius_msg_get_vlanid(msg, &vlan_desc.untagged, vlan_desc.notempty = !!radius_msg_get_vlanid(msg, &vlan_desc.untagged,
MAX_NUM_TAGGED_VLAN, MAX_NUM_TAGGED_VLAN,
vlan_desc.tagged); vlan_desc.tagged, 0);
if (vlan_desc.notempty && if (vlan_desc.notempty &&
!hostapd_vlan_valid(hapd->conf->vlan, &vlan_desc)) { !hostapd_vlan_valid(hapd->conf->vlan, &vlan_desc)) {

View file

@ -200,8 +200,9 @@ struct sta_info {
int vlan_id; /* 0: none, >0: VID */ int vlan_id; /* 0: none, >0: VID */
struct vlan_description *vlan_desc; struct vlan_description *vlan_desc;
int vlan_id_bound; /* updated by ap_sta_bind_vlan() */ int vlan_id_bound; /* updated by ap_sta_bind_vlan() */
/* PSKs from RADIUS authentication server */ /* PSKs from RADIUS authentication server */
struct hostapd_sta_wpa_psk_short *psk; struct hostapd_sta_wpa_psk_short *psk;
struct vlan_description default_radius_vlan;
char *identity; /* User-Name from RADIUS */ char *identity; /* User-Name from RADIUS */
char *radius_cui; /* Chargeable-User-Identity from RADIUS */ char *radius_cui; /* Chargeable-User-Identity from RADIUS */

View file

@ -118,12 +118,12 @@ static inline const u8 * wpa_auth_get_psk(struct wpa_authenticator *wpa_auth,
const u8 *addr, const u8 *addr,
const u8 *p2p_dev_addr, const u8 *p2p_dev_addr,
const u8 *prev_psk, size_t *psk_len, const u8 *prev_psk, size_t *psk_len,
int *vlan_id) struct vlan_description *vlan_desc)
{ {
if (!wpa_auth->cb->get_psk) if (!wpa_auth->cb->get_psk)
return NULL; return NULL;
return wpa_auth->cb->get_psk(wpa_auth->cb_ctx, addr, p2p_dev_addr, return wpa_auth->cb->get_psk(wpa_auth->cb_ctx, addr, p2p_dev_addr,
prev_psk, psk_len, vlan_id); prev_psk, psk_len, vlan_desc);
} }
@ -298,11 +298,12 @@ static int wpa_channel_info(struct wpa_authenticator *wpa_auth,
static int wpa_auth_update_vlan(struct wpa_authenticator *wpa_auth, static int wpa_auth_update_vlan(struct wpa_authenticator *wpa_auth,
const u8 *addr, int vlan_id) const u8 *addr,
struct vlan_description *vlan_desc)
{ {
if (!wpa_auth->cb->update_vlan) if (!wpa_auth->cb->update_vlan)
return -1; return -1;
return wpa_auth->cb->update_vlan(wpa_auth->cb_ctx, addr, vlan_id); return wpa_auth->cb->update_vlan(wpa_auth->cb_ctx, addr, vlan_desc);
} }
@ -937,15 +938,16 @@ static int wpa_try_alt_snonce(struct wpa_state_machine *sm, u8 *data,
int ok = 0; int ok = 0;
const u8 *pmk = NULL; const u8 *pmk = NULL;
size_t pmk_len; size_t pmk_len;
int vlan_id = 0; struct vlan_description vlan_desc;
os_memset(&vlan_desc, 0, sizeof(vlan_desc));
os_memset(&PTK, 0, sizeof(PTK)); os_memset(&PTK, 0, sizeof(PTK));
for (;;) { for (;;) {
if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) && if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) &&
!wpa_key_mgmt_sae(sm->wpa_key_mgmt)) { !wpa_key_mgmt_sae(sm->wpa_key_mgmt)) {
pmk = wpa_auth_get_psk(sm->wpa_auth, sm->addr, pmk = wpa_auth_get_psk(sm->wpa_auth, sm->addr,
sm->p2p_dev_addr, pmk, &pmk_len, sm->p2p_dev_addr, pmk, &pmk_len,
&vlan_id); &vlan_desc);
if (!pmk) if (!pmk)
break; break;
#ifdef CONFIG_IEEE80211R_AP #ifdef CONFIG_IEEE80211R_AP
@ -988,8 +990,8 @@ static int wpa_try_alt_snonce(struct wpa_state_machine *sm, u8 *data,
"WPA: Earlier SNonce resulted in matching MIC"); "WPA: Earlier SNonce resulted in matching MIC");
sm->alt_snonce_valid = 0; sm->alt_snonce_valid = 0;
if (vlan_id && wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) && if (vlan_desc.notempty && wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) &&
wpa_auth_update_vlan(sm->wpa_auth, sm->addr, vlan_id) < 0) wpa_auth_update_vlan(sm->wpa_auth, sm->addr, &vlan_desc) < 0)
return -1; return -1;
os_memcpy(sm->SNonce, sm->alt_SNonce, WPA_NONCE_LEN); os_memcpy(sm->SNonce, sm->alt_SNonce, WPA_NONCE_LEN);
@ -2938,9 +2940,11 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING)
struct ieee802_1x_hdr *hdr; struct ieee802_1x_hdr *hdr;
struct wpa_eapol_key *key; struct wpa_eapol_key *key;
struct wpa_eapol_ie_parse kde; struct wpa_eapol_ie_parse kde;
int vlan_id = 0; struct vlan_description vlan_desc;
int owe_ptk_workaround = !!wpa_auth->conf.owe_ptk_workaround; int owe_ptk_workaround = !!wpa_auth->conf.owe_ptk_workaround;
os_memset(&vlan_desc, 0, sizeof(vlan_desc));
SM_ENTRY_MA(WPA_PTK, PTKCALCNEGOTIATING, wpa_ptk); SM_ENTRY_MA(WPA_PTK, PTKCALCNEGOTIATING, wpa_ptk);
sm->EAPOLKeyReceived = false; sm->EAPOLKeyReceived = false;
sm->update_snonce = false; sm->update_snonce = false;
@ -2956,7 +2960,7 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING)
!wpa_key_mgmt_sae(sm->wpa_key_mgmt)) { !wpa_key_mgmt_sae(sm->wpa_key_mgmt)) {
pmk = wpa_auth_get_psk(sm->wpa_auth, sm->addr, pmk = wpa_auth_get_psk(sm->wpa_auth, sm->addr,
sm->p2p_dev_addr, pmk, &pmk_len, sm->p2p_dev_addr, pmk, &pmk_len,
&vlan_id); &vlan_desc);
if (!pmk) if (!pmk)
break; break;
psk_found = 1; psk_found = 1;
@ -3086,6 +3090,7 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING)
WLAN_REASON_PREV_AUTH_NOT_VALID); WLAN_REASON_PREV_AUTH_NOT_VALID);
return; return;
} }
#ifdef CONFIG_OCV #ifdef CONFIG_OCV
if (wpa_auth_uses_ocv(sm)) { if (wpa_auth_uses_ocv(sm)) {
struct wpa_channel_info ci; struct wpa_channel_info ci;
@ -3189,8 +3194,8 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING)
} }
#endif /* CONFIG_IEEE80211R_AP */ #endif /* CONFIG_IEEE80211R_AP */
if (vlan_id && wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) && if (vlan_desc.notempty && wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) &&
wpa_auth_update_vlan(wpa_auth, sm->addr, vlan_id) < 0) { wpa_auth_update_vlan(wpa_auth, sm->addr, &vlan_desc) < 0) {
wpa_sta_disconnect(wpa_auth, sm->addr, wpa_sta_disconnect(wpa_auth, sm->addr,
WLAN_REASON_PREV_AUTH_NOT_VALID); WLAN_REASON_PREV_AUTH_NOT_VALID);
return; return;

View file

@ -296,7 +296,7 @@ struct wpa_auth_callbacks {
int (*get_eapol)(void *ctx, const u8 *addr, wpa_eapol_variable var); int (*get_eapol)(void *ctx, const u8 *addr, wpa_eapol_variable var);
const u8 * (*get_psk)(void *ctx, const u8 *addr, const u8 *p2p_dev_addr, const u8 * (*get_psk)(void *ctx, const u8 *addr, const u8 *p2p_dev_addr,
const u8 *prev_psk, size_t *psk_len, const u8 *prev_psk, size_t *psk_len,
int *vlan_id); struct vlan_description *vlan);
int (*get_msk)(void *ctx, const u8 *addr, u8 *msk, size_t *len); int (*get_msk)(void *ctx, const u8 *addr, u8 *msk, size_t *len);
int (*set_key)(void *ctx, int vlan_id, enum wpa_alg alg, int (*set_key)(void *ctx, int vlan_id, enum wpa_alg alg,
const u8 *addr, int idx, u8 *key, size_t key_len, const u8 *addr, int idx, u8 *key, size_t key_len,
@ -313,7 +313,8 @@ struct wpa_auth_callbacks {
int (*send_oui)(void *ctx, const u8 *dst, u8 oui_suffix, const u8 *data, int (*send_oui)(void *ctx, const u8 *dst, u8 oui_suffix, const u8 *data,
size_t data_len); size_t data_len);
int (*channel_info)(void *ctx, struct wpa_channel_info *ci); int (*channel_info)(void *ctx, struct wpa_channel_info *ci);
int (*update_vlan)(void *ctx, const u8 *addr, int vlan_id); int (*update_vlan)(void *ctx, const u8 *addr,
struct vlan_description *vlan);
int (*get_sta_tx_params)(void *ctx, const u8 *addr, int (*get_sta_tx_params)(void *ctx, const u8 *addr,
int ap_max_chanwidth, int ap_seg1_idx, int ap_max_chanwidth, int ap_seg1_idx,
int *bandwidth, int *seg1_idx); int *bandwidth, int *seg1_idx);

View file

@ -330,14 +330,13 @@ static int hostapd_wpa_auth_get_eapol(void *ctx, const u8 *addr,
static const u8 * hostapd_wpa_auth_get_psk(void *ctx, const u8 *addr, static const u8 * hostapd_wpa_auth_get_psk(void *ctx, const u8 *addr,
const u8 *p2p_dev_addr, const u8 *p2p_dev_addr,
const u8 *prev_psk, size_t *psk_len, const u8 *prev_psk, size_t *psk_len,
int *vlan_id) struct vlan_description *vlan_desc)
{ {
struct hostapd_data *hapd = ctx; struct hostapd_data *hapd = ctx;
struct sta_info *sta = ap_get_sta(hapd, addr); struct sta_info *sta = ap_get_sta(hapd, addr);
struct vlan_description *vlan = NULL;
const u8 *psk; const u8 *psk;
if (vlan_id)
*vlan_id = 0;
if (psk_len) if (psk_len)
*psk_len = PMK_LEN; *psk_len = PMK_LEN;
@ -374,7 +373,7 @@ static const u8 * hostapd_wpa_auth_get_psk(void *ctx, const u8 *addr,
#endif /* CONFIG_OWE */ #endif /* CONFIG_OWE */
psk = hostapd_get_psk(hapd->conf, addr, p2p_dev_addr, prev_psk, psk = hostapd_get_psk(hapd->conf, addr, p2p_dev_addr, prev_psk,
vlan_id); vlan_desc);
/* /*
* This is about to iterate over all psks, prev_psk gives the last * This is about to iterate over all psks, prev_psk gives the last
* returned psk which should not be returned again. * returned psk which should not be returned again.
@ -383,9 +382,10 @@ static const u8 * hostapd_wpa_auth_get_psk(void *ctx, const u8 *addr,
if (sta && sta->psk && !psk) { if (sta && sta->psk && !psk) {
struct hostapd_sta_wpa_psk_short *pos; struct hostapd_sta_wpa_psk_short *pos;
if (vlan_id) if (vlan_desc)
*vlan_id = 0; vlan_desc->notempty = 0;
psk = sta->psk->psk; psk = sta->psk->psk;
vlan = &sta->psk->vlan;
for (pos = sta->psk; pos; pos = pos->next) { for (pos = sta->psk; pos; pos = pos->next) {
if (pos->is_passphrase) { if (pos->is_passphrase) {
pbkdf2_sha1(pos->passphrase, pbkdf2_sha1(pos->passphrase,
@ -396,10 +396,18 @@ static const u8 * hostapd_wpa_auth_get_psk(void *ctx, const u8 *addr,
} }
if (pos->psk == prev_psk) { if (pos->psk == prev_psk) {
psk = pos->next ? pos->next->psk : NULL; psk = pos->next ? pos->next->psk : NULL;
vlan = pos->next ? &pos->next->vlan : NULL;
break; break;
} }
} }
} }
if (vlan && vlan_desc) {
if (vlan && vlan->notempty)
*vlan_desc = *vlan;
else if (sta->default_radius_vlan.notempty)
*vlan_desc = sta->default_radius_vlan;
}
return psk; return psk;
} }
@ -939,33 +947,31 @@ static void hostapd_clear_ptksa(void *ctx, const u8 *addr, int cipher)
#endif /* CONFIG_PASN */ #endif /* CONFIG_PASN */
static int hostapd_wpa_auth_update_vlan(void *ctx, const u8 *addr, int vlan_id) static int hostapd_wpa_auth_update_vlan(void *ctx, const u8 *addr,
struct vlan_description *vlan_desc)
{ {
#ifndef CONFIG_NO_VLAN #ifndef CONFIG_NO_VLAN
struct hostapd_data *hapd = ctx; struct hostapd_data *hapd = ctx;
struct sta_info *sta; struct sta_info *sta;
int vlan_id = 0;
if (vlan_desc)
vlan_id = vlan_desc->untagged;
sta = ap_get_sta(hapd, addr); sta = ap_get_sta(hapd, addr);
if (!sta) if (!sta)
return -1; return -1;
if (!(hapd->iface->drv_flags & WPA_DRIVER_FLAGS_VLAN_OFFLOAD)) { if (!(hapd->iface->drv_flags & WPA_DRIVER_FLAGS_VLAN_OFFLOAD)) {
struct vlan_description vlan_desc; if (!hostapd_vlan_valid(hapd->conf->vlan, vlan_desc)) {
wpa_printf(MSG_INFO, "Invalid VLAN ID %d", vlan_id);
os_memset(&vlan_desc, 0, sizeof(vlan_desc));
vlan_desc.notempty = 1;
vlan_desc.untagged = vlan_id;
if (!hostapd_vlan_valid(hapd->conf->vlan, &vlan_desc)) {
wpa_printf(MSG_INFO,
"Invalid VLAN ID %d in wpa_psk_file",
vlan_id);
return -1; return -1;
} }
if (ap_sta_set_vlan(hapd, sta, &vlan_desc) < 0) { if (ap_sta_set_vlan(hapd, sta, vlan_desc) < 0) {
wpa_printf(MSG_INFO, wpa_printf(MSG_INFO,
"Failed to assign VLAN ID %d from wpa_psk_file to " "Failed to assign VLAN ID %d to " MACSTR,
MACSTR, vlan_id, MAC2STR(sta->addr)); vlan_id, MAC2STR(sta->addr));
return -1; return -1;
} }
} else { } else {
@ -973,7 +979,7 @@ static int hostapd_wpa_auth_update_vlan(void *ctx, const u8 *addr, int vlan_id)
} }
wpa_printf(MSG_INFO, wpa_printf(MSG_INFO,
"Assigned VLAN ID %d from wpa_psk_file to " MACSTR, "Assigned VLAN ID %d from to " MACSTR,
vlan_id, MAC2STR(sta->addr)); vlan_id, MAC2STR(sta->addr));
if ((sta->flags & WLAN_STA_ASSOC) && if ((sta->flags & WLAN_STA_ASSOC) &&
ap_sta_bind_vlan(hapd, sta) < 0) ap_sta_bind_vlan(hapd, sta) < 0)

View file

@ -1437,6 +1437,11 @@ static int cmp_int(const void *a, const void *b)
} }
static int tag_is_valid(u8 tag) {
return 0x1 <= tag && tag <= 0x1F;
}
/** /**
* radius_msg_get_vlanid - Parse RADIUS attributes for VLAN tunnel information * radius_msg_get_vlanid - Parse RADIUS attributes for VLAN tunnel information
* The k tagged vlans found are sorted by vlan_id and stored in the first k * The k tagged vlans found are sorted by vlan_id and stored in the first k
@ -1450,7 +1455,7 @@ static int cmp_int(const void *a, const void *b)
* Returns: 0 if neither tagged nor untagged configuration is found, 1 otherwise * Returns: 0 if neither tagged nor untagged configuration is found, 1 otherwise
*/ */
int radius_msg_get_vlanid(struct radius_msg *msg, int *untagged, int numtagged, int radius_msg_get_vlanid(struct radius_msg *msg, int *untagged, int numtagged,
int *tagged) int *tagged, u8 tag)
{ {
struct radius_tunnel_attrs tunnel[RADIUS_TUNNEL_TAGS], *tun; struct radius_tunnel_attrs tunnel[RADIUS_TUNNEL_TAGS], *tun;
size_t i; size_t i;
@ -1465,6 +1470,11 @@ int radius_msg_get_vlanid(struct radius_msg *msg, int *untagged, int numtagged,
tagged[j] = 0; tagged[j] = 0;
*untagged = 0; *untagged = 0;
if (tag_is_valid(tag))
tun = &tunnel[tag];
else
tun = &tunnel[0];
for (i = 0; i < msg->attr_used; i++) { for (i = 0; i < msg->attr_used; i++) {
attr = radius_get_attr_hdr(msg, i); attr = radius_get_attr_hdr(msg, i);
if (attr->length < sizeof(*attr)) if (attr->length < sizeof(*attr))
@ -1473,10 +1483,8 @@ int radius_msg_get_vlanid(struct radius_msg *msg, int *untagged, int numtagged,
dlen = attr->length - sizeof(*attr); dlen = attr->length - sizeof(*attr);
if (attr->length < 3) if (attr->length < 3)
continue; continue;
if (data[0] >= RADIUS_TUNNEL_TAGS) if (tag_is_valid(tag) && data[0] != tag)
tun = &tunnel[0]; continue;
else
tun = &tunnel[data[0]];
switch (attr->type) { switch (attr->type) {
case RADIUS_ATTR_TUNNEL_TYPE: case RADIUS_ATTR_TUNNEL_TYPE:
@ -1521,17 +1529,11 @@ int radius_msg_get_vlanid(struct radius_msg *msg, int *untagged, int numtagged,
} }
} }
/* Use tunnel with the lowest tag for untagged VLAN id */ if (tun->tag_used &&
for (i = 0; i < RADIUS_TUNNEL_TAGS; i++) { tun->type == RADIUS_TUNNEL_TYPE_VLAN &&
tun = &tunnel[i]; tun->medium_type == RADIUS_TUNNEL_MEDIUM_TYPE_802 &&
if (tun->tag_used && tun->vlanid > 0)
tun->type == RADIUS_TUNNEL_TYPE_VLAN && *untagged = tun->vlanid;
tun->medium_type == RADIUS_TUNNEL_MEDIUM_TYPE_802 &&
tun->vlanid > 0) {
*untagged = tun->vlanid;
break;
}
}
if (taggedidx) if (taggedidx)
qsort(tagged, taggedidx, sizeof(int), cmp_int); qsort(tagged, taggedidx, sizeof(int), cmp_int);
@ -1554,7 +1556,7 @@ int radius_msg_get_vlanid(struct radius_msg *msg, int *untagged, int numtagged,
*/ */
char * radius_msg_get_tunnel_password(struct radius_msg *msg, int *keylen, char * radius_msg_get_tunnel_password(struct radius_msg *msg, int *keylen,
const u8 *secret, size_t secret_len, const u8 *secret, size_t secret_len,
struct radius_msg *sent_msg, size_t n) struct radius_msg *sent_msg, size_t n, u8 *tag)
{ {
u8 *buf = NULL; u8 *buf = NULL;
size_t buflen; size_t buflen;
@ -1572,6 +1574,9 @@ char * radius_msg_get_tunnel_password(struct radius_msg *msg, int *keylen,
size_t fdlen = -1; size_t fdlen = -1;
char *ret = NULL; char *ret = NULL;
if (tag)
*tag = 0;
/* find n-th valid Tunnel-Password attribute */ /* find n-th valid Tunnel-Password attribute */
for (i = 0; i < msg->attr_used; i++) { for (i = 0; i < msg->attr_used; i++) {
attr = radius_get_attr_hdr(msg, i); attr = radius_get_attr_hdr(msg, i);
@ -1589,6 +1594,9 @@ char * radius_msg_get_tunnel_password(struct radius_msg *msg, int *keylen,
if (j <= n) if (j <= n)
continue; continue;
if (tag_is_valid(data[0]))
*tag = data[0];
fdata = data; fdata = data;
fdlen = dlen; fdlen = dlen;
break; break;

View file

@ -294,10 +294,11 @@ radius_msg_add_attr_user_password(struct radius_msg *msg,
const u8 *secret, size_t secret_len); const u8 *secret, size_t secret_len);
int radius_msg_get_attr(struct radius_msg *msg, u8 type, u8 *buf, size_t len); int radius_msg_get_attr(struct radius_msg *msg, u8 type, u8 *buf, size_t len);
int radius_msg_get_vlanid(struct radius_msg *msg, int *untagged, int numtagged, int radius_msg_get_vlanid(struct radius_msg *msg, int *untagged, int numtagged,
int *tagged); int *tagged, u8 tag);
char * radius_msg_get_tunnel_password(struct radius_msg *msg, int *keylen, char * radius_msg_get_tunnel_password(struct radius_msg *msg, int *keylen,
const u8 *secret, size_t secret_len, const u8 *secret, size_t secret_len,
struct radius_msg *sent_msg, size_t n); struct radius_msg *sent_msg, size_t n,
u8 *tag);
static inline int radius_msg_add_attr_int32(struct radius_msg *msg, u8 type, static inline int radius_msg_add_attr_int32(struct radius_msg *msg, u8 type,
u32 value) u32 value)

View file

@ -141,14 +141,14 @@ static int auth_send_eapol(void *ctx, const u8 *addr, const u8 *data,
static const u8 * auth_get_psk(void *ctx, const u8 *addr, static const u8 * auth_get_psk(void *ctx, const u8 *addr,
const u8 *p2p_dev_addr, const u8 *prev_psk, const u8 *p2p_dev_addr, const u8 *prev_psk,
size_t *psk_len, int *vlan_id) size_t *psk_len, struct vlan_description *vlan_desc)
{ {
struct wpa *wpa = ctx; struct wpa *wpa = ctx;
wpa_printf(MSG_DEBUG, "AUTH: %s (addr=" MACSTR " prev_psk=%p)", wpa_printf(MSG_DEBUG, "AUTH: %s (addr=" MACSTR " prev_psk=%p)",
__func__, MAC2STR(addr), prev_psk); __func__, MAC2STR(addr), prev_psk);
if (vlan_id) if (vlan_desc)
*vlan_id = 0; vlan_desc->notempty = 0;
if (psk_len) if (psk_len)
*psk_len = PMK_LEN; *psk_len = PMK_LEN;
if (prev_psk) if (prev_psk)