resolve merge conflicts
MFC after: 2 weeks
This commit is contained in:
parent
ead3cc4315
commit
f40bc3005e
@ -4,7 +4,9 @@ driver.c
|
||||
driver_bsd.c
|
||||
driver_madwifi.c
|
||||
driver_prism54.c
|
||||
l2_packet.c
|
||||
l2_packet_freebsd.c
|
||||
l2_packet_linux.c
|
||||
l2_packet_pcap.c
|
||||
prism54.h
|
||||
priv_netlink.h
|
||||
wireless_copy.h
|
||||
|
@ -6,12 +6,12 @@ WPA/802.1x Authenticator
|
||||
|
||||
For the import files and directories were pruned by:
|
||||
|
||||
tar -X FREEBSD-Xlist -zxf hostapd-0.3.7.tar.gz
|
||||
tar -X FREEBSD-Xlist -zxf hostapd-0.4.8.tar.gz
|
||||
|
||||
then imported by:
|
||||
|
||||
cvs import -m 'Import of hostapd 0.3.7' \
|
||||
src/contrib/hostapd MALINEN v0_3_7
|
||||
cvs import -m 'Import of hostapd 0.4.8' \
|
||||
src/contrib/hostapd MALINEN v0_4_8
|
||||
|
||||
To make local changes to hostapd, simply patch and commit to the
|
||||
main branch (aka HEAD). Never make local changes on the vendor
|
||||
@ -21,4 +21,4 @@ All local changes should be submitted to Jouni Malinen for inclusion in
|
||||
the next vendor release.
|
||||
|
||||
sam@FreeBSD.org
|
||||
4-June-2005
|
||||
6-March-2006
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include "sta_info.h"
|
||||
#include "eap_i.h"
|
||||
|
||||
#define EAP_MAX_AUTH_ROUNDS 50
|
||||
|
||||
extern const struct eap_method eap_method_identity;
|
||||
#ifdef EAP_MD5
|
||||
@ -52,6 +53,12 @@ extern const struct eap_method eap_method_ttls;
|
||||
#ifdef EAP_SIM
|
||||
extern const struct eap_method eap_method_sim;
|
||||
#endif /* EAP_SIM */
|
||||
#ifdef EAP_PAX
|
||||
extern const struct eap_method eap_method_pax;
|
||||
#endif /* EAP_PAX */
|
||||
#ifdef EAP_PSK
|
||||
extern const struct eap_method eap_method_psk;
|
||||
#endif /* EAP_PSK */
|
||||
|
||||
static const struct eap_method *eap_methods[] =
|
||||
{
|
||||
@ -80,6 +87,12 @@ static const struct eap_method *eap_methods[] =
|
||||
#ifdef EAP_SIM
|
||||
&eap_method_sim,
|
||||
#endif /* EAP_SIM */
|
||||
#ifdef EAP_PAX
|
||||
&eap_method_pax,
|
||||
#endif /* EAP_PAX */
|
||||
#ifdef EAP_PSK
|
||||
&eap_method_psk,
|
||||
#endif /* EAP_PSK */
|
||||
};
|
||||
#define NUM_EAP_METHODS (sizeof(eap_methods) / sizeof(eap_methods[0]))
|
||||
|
||||
@ -199,6 +212,7 @@ int eap_user_get(struct eap_sm *sm, const u8 *identity, size_t identity_len,
|
||||
SM_STATE(EAP, DISABLED)
|
||||
{
|
||||
SM_ENTRY(EAP, DISABLED);
|
||||
sm->num_rounds = 0;
|
||||
}
|
||||
|
||||
|
||||
@ -234,6 +248,7 @@ SM_STATE(EAP, INITIALIZE)
|
||||
sm->currentId = sm->respId;
|
||||
}
|
||||
}
|
||||
sm->num_rounds = 0;
|
||||
}
|
||||
|
||||
|
||||
@ -290,6 +305,7 @@ SM_STATE(EAP, RECEIVED)
|
||||
|
||||
/* parse rxResp, respId, respMethod */
|
||||
eap_sm_parseEapResp(sm, sm->eapRespData, sm->eapRespDataLen);
|
||||
sm->num_rounds++;
|
||||
}
|
||||
|
||||
|
||||
@ -505,7 +521,15 @@ SM_STEP(EAP)
|
||||
SM_ENTER_GLOBAL(EAP, INITIALIZE);
|
||||
else if (!eapol_get_bool(sm, EAPOL_portEnabled))
|
||||
SM_ENTER_GLOBAL(EAP, DISABLED);
|
||||
else switch (sm->EAP_state) {
|
||||
else if (sm->num_rounds > EAP_MAX_AUTH_ROUNDS) {
|
||||
if (sm->num_rounds == EAP_MAX_AUTH_ROUNDS + 1) {
|
||||
wpa_printf(MSG_DEBUG, "EAP: more than %d "
|
||||
"authentication rounds - abort",
|
||||
EAP_MAX_AUTH_ROUNDS);
|
||||
sm->num_rounds++;
|
||||
SM_ENTER_GLOBAL(EAP, FAILURE);
|
||||
}
|
||||
} else switch (sm->EAP_state) {
|
||||
case EAP_INITIALIZE:
|
||||
if (sm->backend_auth) {
|
||||
if (!sm->rxResp)
|
||||
@ -912,6 +936,7 @@ void eap_sm_deinit(struct eap_sm *sm)
|
||||
free(sm);
|
||||
}
|
||||
|
||||
|
||||
void eap_sm_notify_cached(struct eap_sm *sm)
|
||||
{
|
||||
if (sm == NULL)
|
||||
|
@ -32,6 +32,7 @@ struct eapol_callbacks {
|
||||
size_t eapKeyDataLen);
|
||||
int (*get_eap_user)(void *ctx, const u8 *identity, size_t identity_len,
|
||||
int phase2, struct eap_user *user);
|
||||
const char * (*get_eap_req_id_text)(void *ctx, size_t *len);
|
||||
};
|
||||
|
||||
struct eap_config {
|
||||
@ -41,7 +42,7 @@ struct eap_config {
|
||||
};
|
||||
|
||||
|
||||
#ifdef EAP_AUTHENTICATOR
|
||||
#ifdef EAP_SERVER
|
||||
|
||||
struct eap_sm * eap_sm_init(void *eapol_ctx, struct eapol_callbacks *eapol_cb,
|
||||
struct eap_config *eap_conf);
|
||||
@ -52,7 +53,7 @@ void eap_set_eapRespData(struct eap_sm *sm, const u8 *eapRespData,
|
||||
size_t eapRespDataLen);
|
||||
void eap_sm_notify_cached(struct eap_sm *sm);
|
||||
|
||||
#else /* EAP_AUTHENTICATOR */
|
||||
#else /* EAP_SERVER */
|
||||
|
||||
static inline struct eap_sm * eap_sm_init(void *eapol_ctx,
|
||||
struct eapol_callbacks *eapol_cb,
|
||||
@ -85,6 +86,6 @@ static inline void eap_sm_notify_cached(struct eap_sm *sm)
|
||||
{
|
||||
}
|
||||
|
||||
#endif /* EAP_AUTHENTICATOR */
|
||||
#endif /* EAP_SERVER */
|
||||
|
||||
#endif /* EAP_H */
|
||||
|
@ -68,6 +68,9 @@ static void sm_ ## machine ## _Step(struct eapol_state_machine *sm)
|
||||
#define SM_STEP_RUN(machine) sm_ ## machine ## _Step(sm)
|
||||
|
||||
|
||||
static void eapol_sm_step_run(struct eapol_state_machine *sm);
|
||||
static void eapol_sm_step_cb(void *eloop_ctx, void *timeout_ctx);
|
||||
|
||||
|
||||
/* Port Timers state machine - implemented as a function that will be called
|
||||
* once a second as a registered event loop timeout */
|
||||
@ -76,19 +79,34 @@ static void eapol_port_timers_tick(void *eloop_ctx, void *timeout_ctx)
|
||||
{
|
||||
struct eapol_state_machine *state = timeout_ctx;
|
||||
|
||||
if (state->aWhile > 0)
|
||||
if (state->aWhile > 0) {
|
||||
state->aWhile--;
|
||||
if (state->quietWhile > 0)
|
||||
if (state->aWhile == 0) {
|
||||
wpa_printf(MSG_DEBUG, "IEEE 802.1X: " MACSTR
|
||||
" - aWhile --> 0",
|
||||
MAC2STR(state->addr));
|
||||
}
|
||||
}
|
||||
|
||||
if (state->quietWhile > 0) {
|
||||
state->quietWhile--;
|
||||
if (state->reAuthWhen > 0)
|
||||
if (state->quietWhile == 0) {
|
||||
wpa_printf(MSG_DEBUG, "IEEE 802.1X: " MACSTR
|
||||
" - quietWhile --> 0",
|
||||
MAC2STR(state->addr));
|
||||
}
|
||||
}
|
||||
|
||||
if (state->reAuthWhen > 0) {
|
||||
state->reAuthWhen--;
|
||||
if (state->reAuthWhen == 0) {
|
||||
wpa_printf(MSG_DEBUG, "IEEE 802.1X: " MACSTR
|
||||
" - reAuthWhen --> 0",
|
||||
MAC2STR(state->addr));
|
||||
}
|
||||
}
|
||||
|
||||
if (state->hapd->conf->debug >= HOSTAPD_DEBUG_MSGDUMPS)
|
||||
printf("IEEE 802.1X: " MACSTR " Port Timers TICK "
|
||||
"(timers: %d %d %d)\n", MAC2STR(state->addr),
|
||||
state->aWhile, state->quietWhile, state->reAuthWhen);
|
||||
|
||||
eapol_sm_step(state);
|
||||
eapol_sm_step_run(state);
|
||||
|
||||
eloop_register_timeout(1, 0, eapol_port_timers_tick, eloop_ctx, state);
|
||||
}
|
||||
@ -359,6 +377,19 @@ SM_STATE(BE_AUTH, REQUEST)
|
||||
txReq();
|
||||
sm->be_auth.eapReq = FALSE;
|
||||
sm->be_auth.backendOtherRequestsToSupplicant++;
|
||||
|
||||
/*
|
||||
* Clearing eapolEap here is not specified in IEEE Std 802.1X-2004, but
|
||||
* it looks like this would be logical thing to do there since the old
|
||||
* EAP response would not be valid anymore after the new EAP request
|
||||
* was sent out.
|
||||
*
|
||||
* A race condition has been reported, in which hostapd ended up
|
||||
* sending out EAP-Response/Identity as a response to the first
|
||||
* EAP-Request from the main EAP method. This can be avoided by
|
||||
* clearing eapolEap here.
|
||||
*/
|
||||
sm->eapolEap = FALSE;
|
||||
}
|
||||
|
||||
|
||||
@ -705,7 +736,7 @@ eapol_sm_alloc(hostapd *hapd, struct sta_info *sta)
|
||||
else
|
||||
sm->portValid = TRUE;
|
||||
|
||||
if (hapd->conf->eap_authenticator) {
|
||||
if (hapd->conf->eap_server) {
|
||||
struct eap_config eap_conf;
|
||||
memset(&eap_conf, 0, sizeof(eap_conf));
|
||||
eap_conf.ssl_ctx = hapd->ssl_ctx;
|
||||
@ -729,6 +760,7 @@ void eapol_sm_free(struct eapol_state_machine *sm)
|
||||
return;
|
||||
|
||||
eloop_cancel_timeout(eapol_port_timers_tick, sm->hapd, sm);
|
||||
eloop_cancel_timeout(eapol_sm_step_cb, sm, NULL);
|
||||
if (sm->eap)
|
||||
eap_sm_deinit(sm->eap);
|
||||
free(sm);
|
||||
@ -745,55 +777,63 @@ static int eapol_sm_sta_entry_alive(struct hostapd_data *hapd, u8 *addr)
|
||||
}
|
||||
|
||||
|
||||
void eapol_sm_step(struct eapol_state_machine *sm)
|
||||
static void eapol_sm_step_run(struct eapol_state_machine *sm)
|
||||
{
|
||||
struct hostapd_data *hapd = sm->hapd;
|
||||
u8 addr[ETH_ALEN];
|
||||
int prev_auth_pae, prev_be_auth, prev_reauth_timer, prev_auth_key_tx,
|
||||
prev_key_rx, prev_ctrl_dir;
|
||||
|
||||
/* FIX: could re-run eapol_sm_step from registered timeout (after
|
||||
* 0 sec) to make sure that other possible timeouts/events are
|
||||
* processed */
|
||||
int max_steps = 100;
|
||||
|
||||
memcpy(addr, sm->sta->addr, ETH_ALEN);
|
||||
restart:
|
||||
do {
|
||||
prev_auth_pae = sm->auth_pae.state;
|
||||
prev_be_auth = sm->be_auth.state;
|
||||
prev_reauth_timer = sm->reauth_timer.state;
|
||||
prev_auth_key_tx = sm->auth_key_tx.state;
|
||||
prev_key_rx = sm->key_rx.state;
|
||||
prev_ctrl_dir = sm->ctrl_dir.state;
|
||||
|
||||
SM_STEP_RUN(AUTH_PAE);
|
||||
if (!sm->initializing && !eapol_sm_sta_entry_alive(hapd, addr))
|
||||
break;
|
||||
/*
|
||||
* Allow EAPOL state machines to run as long as there are state
|
||||
* changes, but exit and return here through event loop if more than
|
||||
* 100 steps is needed as a precaution against infinite loops inside
|
||||
* eloop callback.
|
||||
*/
|
||||
restart:
|
||||
prev_auth_pae = sm->auth_pae.state;
|
||||
prev_be_auth = sm->be_auth.state;
|
||||
prev_reauth_timer = sm->reauth_timer.state;
|
||||
prev_auth_key_tx = sm->auth_key_tx.state;
|
||||
prev_key_rx = sm->key_rx.state;
|
||||
prev_ctrl_dir = sm->ctrl_dir.state;
|
||||
|
||||
SM_STEP_RUN(AUTH_PAE);
|
||||
if (sm->initializing || eapol_sm_sta_entry_alive(hapd, addr))
|
||||
SM_STEP_RUN(BE_AUTH);
|
||||
if (!sm->initializing && !eapol_sm_sta_entry_alive(hapd, addr))
|
||||
break;
|
||||
if (sm->initializing || eapol_sm_sta_entry_alive(hapd, addr))
|
||||
SM_STEP_RUN(REAUTH_TIMER);
|
||||
if (!sm->initializing && !eapol_sm_sta_entry_alive(hapd, addr))
|
||||
break;
|
||||
if (sm->initializing || eapol_sm_sta_entry_alive(hapd, addr))
|
||||
SM_STEP_RUN(AUTH_KEY_TX);
|
||||
if (!sm->initializing && !eapol_sm_sta_entry_alive(hapd, addr))
|
||||
break;
|
||||
if (sm->initializing || eapol_sm_sta_entry_alive(hapd, addr))
|
||||
SM_STEP_RUN(KEY_RX);
|
||||
if (!sm->initializing && !eapol_sm_sta_entry_alive(hapd, addr))
|
||||
break;
|
||||
if (sm->initializing || eapol_sm_sta_entry_alive(hapd, addr))
|
||||
SM_STEP_RUN(CTRL_DIR);
|
||||
if (!sm->initializing && !eapol_sm_sta_entry_alive(hapd, addr))
|
||||
break;
|
||||
} while (prev_auth_pae != sm->auth_pae.state ||
|
||||
prev_be_auth != sm->be_auth.state ||
|
||||
prev_reauth_timer != sm->reauth_timer.state ||
|
||||
prev_auth_key_tx != sm->auth_key_tx.state ||
|
||||
prev_key_rx != sm->key_rx.state ||
|
||||
prev_ctrl_dir != sm->ctrl_dir.state);
|
||||
|
||||
if (prev_auth_pae != sm->auth_pae.state ||
|
||||
prev_be_auth != sm->be_auth.state ||
|
||||
prev_reauth_timer != sm->reauth_timer.state ||
|
||||
prev_auth_key_tx != sm->auth_key_tx.state ||
|
||||
prev_key_rx != sm->key_rx.state ||
|
||||
prev_ctrl_dir != sm->ctrl_dir.state) {
|
||||
if (--max_steps > 0)
|
||||
goto restart;
|
||||
/* Re-run from eloop timeout */
|
||||
eapol_sm_step(sm);
|
||||
return;
|
||||
}
|
||||
|
||||
if (eapol_sm_sta_entry_alive(hapd, addr) && sm->eap) {
|
||||
if (eap_sm_step(sm->eap))
|
||||
goto restart;
|
||||
if (eap_sm_step(sm->eap)) {
|
||||
if (--max_steps > 0)
|
||||
goto restart;
|
||||
/* Re-run from eloop timeout */
|
||||
eapol_sm_step(sm);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (eapol_sm_sta_entry_alive(hapd, addr))
|
||||
@ -801,15 +841,34 @@ void eapol_sm_step(struct eapol_state_machine *sm)
|
||||
}
|
||||
|
||||
|
||||
static void eapol_sm_step_cb(void *eloop_ctx, void *timeout_ctx)
|
||||
{
|
||||
struct eapol_state_machine *sm = eloop_ctx;
|
||||
eapol_sm_step_run(sm);
|
||||
}
|
||||
|
||||
|
||||
void eapol_sm_step(struct eapol_state_machine *sm)
|
||||
{
|
||||
/*
|
||||
* Run eapol_sm_step_run from a registered timeout to make sure that
|
||||
* other possible timeouts/events are processed and to avoid long
|
||||
* function call chains.
|
||||
*/
|
||||
|
||||
eloop_register_timeout(0, 0, eapol_sm_step_cb, sm, NULL);
|
||||
}
|
||||
|
||||
|
||||
void eapol_sm_initialize(struct eapol_state_machine *sm)
|
||||
{
|
||||
sm->initializing = TRUE;
|
||||
/* Initialize the state machines by asserting initialize and then
|
||||
* deasserting it after one step */
|
||||
sm->initialize = TRUE;
|
||||
eapol_sm_step(sm);
|
||||
eapol_sm_step_run(sm);
|
||||
sm->initialize = FALSE;
|
||||
eapol_sm_step(sm);
|
||||
eapol_sm_step_run(sm);
|
||||
sm->initializing = FALSE;
|
||||
|
||||
/* Start one second tick for port timers state machine */
|
||||
@ -1183,6 +1242,14 @@ static int eapol_sm_get_eap_user(void *ctx, const u8 *identity,
|
||||
}
|
||||
|
||||
|
||||
static const char * eapol_sm_get_eap_req_id_text(void *ctx, size_t *len)
|
||||
{
|
||||
struct eapol_state_machine *sm = ctx;
|
||||
*len = sm->hapd->conf->eap_req_id_text_len;
|
||||
return sm->hapd->conf->eap_req_id_text;
|
||||
}
|
||||
|
||||
|
||||
static struct eapol_callbacks eapol_cb =
|
||||
{
|
||||
.get_bool = eapol_sm_get_bool,
|
||||
@ -1190,4 +1257,5 @@ static struct eapol_callbacks eapol_cb =
|
||||
.set_eapReqData = eapol_sm_set_eapReqData,
|
||||
.set_eapKeyData = eapol_sm_set_eapKeyData,
|
||||
.get_eap_user = eapol_sm_get_eap_user,
|
||||
.get_eap_req_id_text = eapol_sm_get_eap_req_id_text,
|
||||
};
|
||||
|
@ -1,188 +0,0 @@
|
||||
/*
|
||||
* hostapd - hostapd control interface library
|
||||
* Copyright (c) 2004, Jouni Malinen <jkmaline@cc.hut.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/un.h>
|
||||
|
||||
#include "hostapd_ctrl.h"
|
||||
|
||||
|
||||
struct hostapd_ctrl {
|
||||
int s;
|
||||
struct sockaddr_un local;
|
||||
struct sockaddr_un dest;
|
||||
};
|
||||
|
||||
|
||||
struct hostapd_ctrl * hostapd_ctrl_open(const char *ctrl_path)
|
||||
{
|
||||
struct hostapd_ctrl *ctrl;
|
||||
static int counter = 0;
|
||||
|
||||
ctrl = malloc(sizeof(*ctrl));
|
||||
if (ctrl == NULL)
|
||||
return NULL;
|
||||
memset(ctrl, 0, sizeof(*ctrl));
|
||||
|
||||
ctrl->s = socket(PF_UNIX, SOCK_DGRAM, 0);
|
||||
if (ctrl->s < 0) {
|
||||
free(ctrl);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ctrl->local.sun_family = AF_UNIX;
|
||||
snprintf(ctrl->local.sun_path, sizeof(ctrl->local.sun_path),
|
||||
"/tmp/hostapd_ctrl_%d-%d", getpid(), counter++);
|
||||
if (bind(ctrl->s, (struct sockaddr *) &ctrl->local,
|
||||
sizeof(ctrl->local.sun_family) +
|
||||
strlen(ctrl->local.sun_path)) < 0) {
|
||||
close(ctrl->s);
|
||||
free(ctrl);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ctrl->dest.sun_family = AF_UNIX;
|
||||
strncpy(ctrl->dest.sun_path, ctrl_path, sizeof(ctrl->dest.sun_path));
|
||||
if (connect(ctrl->s, (struct sockaddr *) &ctrl->dest,
|
||||
sizeof(ctrl->dest.sun_family) +
|
||||
strlen(ctrl->dest.sun_path)) < 0) {
|
||||
close(ctrl->s);
|
||||
unlink(ctrl->local.sun_path);
|
||||
free(ctrl);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ctrl;
|
||||
}
|
||||
|
||||
|
||||
void hostapd_ctrl_close(struct hostapd_ctrl *ctrl)
|
||||
{
|
||||
unlink(ctrl->local.sun_path);
|
||||
close(ctrl->s);
|
||||
free(ctrl);
|
||||
}
|
||||
|
||||
|
||||
int hostapd_ctrl_request(struct hostapd_ctrl *ctrl, char *cmd, size_t cmd_len,
|
||||
char *reply, size_t *reply_len,
|
||||
void (*msg_cb)(char *msg, size_t len))
|
||||
{
|
||||
struct timeval tv;
|
||||
int res;
|
||||
fd_set rfds;
|
||||
|
||||
if (send(ctrl->s, cmd, cmd_len, 0) < 0)
|
||||
return -1;
|
||||
|
||||
for (;;) {
|
||||
tv.tv_sec = 2;
|
||||
tv.tv_usec = 0;
|
||||
FD_ZERO(&rfds);
|
||||
FD_SET(ctrl->s, &rfds);
|
||||
res = select(ctrl->s + 1, &rfds, NULL, NULL, &tv);
|
||||
if (FD_ISSET(ctrl->s, &rfds)) {
|
||||
res = recv(ctrl->s, reply, *reply_len, 0);
|
||||
if (res < 0)
|
||||
return res;
|
||||
if (res > 0 && reply[0] == '<') {
|
||||
/* This is an unsolicited message from
|
||||
* wpa_supplicant, not the reply to the
|
||||
* request. Use msg_cb to report this to the
|
||||
* caller. */
|
||||
if (msg_cb) {
|
||||
/* Make sure the message is nul
|
||||
* terminated. */
|
||||
if (res == *reply_len)
|
||||
res = (*reply_len) - 1;
|
||||
reply[res] = '\0';
|
||||
msg_cb(reply, res);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
*reply_len = res;
|
||||
break;
|
||||
} else {
|
||||
return -2;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_ctrl_attach_helper(struct hostapd_ctrl *ctrl, int attach)
|
||||
{
|
||||
char buf[10];
|
||||
int ret;
|
||||
size_t len = 10;
|
||||
|
||||
ret = hostapd_ctrl_request(ctrl, attach ? "ATTACH" : "DETACH", 6,
|
||||
buf, &len, NULL);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (len == 3 && memcmp(buf, "OK\n", 3) == 0)
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int hostapd_ctrl_attach(struct hostapd_ctrl *ctrl)
|
||||
{
|
||||
return hostapd_ctrl_attach_helper(ctrl, 1);
|
||||
}
|
||||
|
||||
|
||||
int hostapd_ctrl_detach(struct hostapd_ctrl *ctrl)
|
||||
{
|
||||
return hostapd_ctrl_attach_helper(ctrl, 0);
|
||||
}
|
||||
|
||||
|
||||
int hostapd_ctrl_recv(struct hostapd_ctrl *ctrl, char *reply,
|
||||
size_t *reply_len)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = recv(ctrl->s, reply, *reply_len, 0);
|
||||
if (res < 0)
|
||||
return res;
|
||||
*reply_len = res;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int hostapd_ctrl_pending(struct hostapd_ctrl *ctrl)
|
||||
{
|
||||
struct timeval tv;
|
||||
int res;
|
||||
fd_set rfds;
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 0;
|
||||
FD_ZERO(&rfds);
|
||||
FD_SET(ctrl->s, &rfds);
|
||||
res = select(ctrl->s + 1, &rfds, NULL, NULL, &tv);
|
||||
return FD_ISSET(ctrl->s, &rfds);
|
||||
}
|
||||
|
||||
|
||||
int hostapd_ctrl_get_fd(struct hostapd_ctrl *ctrl)
|
||||
{
|
||||
return ctrl->s;
|
||||
}
|
@ -1,18 +0,0 @@
|
||||
#ifndef HOSTAPD_CTRL_H
|
||||
#define HOSTAPD_CTRL_H
|
||||
|
||||
struct hostapd_ctrl;
|
||||
|
||||
struct hostapd_ctrl * hostapd_ctrl_open(const char *ctrl_path);
|
||||
void hostapd_ctrl_close(struct hostapd_ctrl *ctrl);
|
||||
int hostapd_ctrl_request(struct hostapd_ctrl *ctrl, char *cmd, size_t cmd_len,
|
||||
char *reply, size_t *reply_len,
|
||||
void (*msg_cb)(char *msg, size_t len));
|
||||
int hostapd_ctrl_attach(struct hostapd_ctrl *ctrl);
|
||||
int hostapd_ctrl_detach(struct hostapd_ctrl *ctrl);
|
||||
int hostapd_ctrl_recv(struct hostapd_ctrl *ctrl, char *reply,
|
||||
size_t *reply_len);
|
||||
int hostapd_ctrl_pending(struct hostapd_ctrl *ctrl);
|
||||
int hostapd_ctrl_get_fd(struct hostapd_ctrl *ctrl);
|
||||
|
||||
#endif /* HOSTAPD_CTRL_H */
|
@ -135,13 +135,13 @@ void ieee802_1x_request_identity(struct hostapd_data *hapd,
|
||||
{
|
||||
u8 *buf;
|
||||
struct eap_hdr *eap;
|
||||
int extra, tlen;
|
||||
int tlen;
|
||||
u8 *pos;
|
||||
struct eapol_state_machine *sm = sta->eapol_sm;
|
||||
|
||||
if (hapd->conf->eap_authenticator) {
|
||||
if (hapd->conf->eap_server) {
|
||||
HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL,
|
||||
"IEEE 802.1X: Integrated EAP Authenticator in "
|
||||
"IEEE 802.1X: Integrated EAP server in "
|
||||
"use - do not generate EAP-Request/Identity\n");
|
||||
return;
|
||||
}
|
||||
@ -151,12 +151,7 @@ void ieee802_1x_request_identity(struct hostapd_data *hapd,
|
||||
|
||||
ieee802_1x_new_auth_session(hapd, sta);
|
||||
|
||||
if (hapd->conf->eap_req_id_text)
|
||||
extra = strlen(hapd->conf->eap_req_id_text);
|
||||
else
|
||||
extra = 0;
|
||||
|
||||
tlen = sizeof(*eap) + 1 + extra;
|
||||
tlen = sizeof(*eap) + 1 + hapd->conf->eap_req_id_text_len;
|
||||
|
||||
buf = malloc(tlen);
|
||||
if (buf == NULL) {
|
||||
@ -172,8 +167,10 @@ void ieee802_1x_request_identity(struct hostapd_data *hapd,
|
||||
eap->length = htons(tlen);
|
||||
pos = (u8 *) (eap + 1);
|
||||
*pos++ = EAP_TYPE_IDENTITY;
|
||||
if (hapd->conf->eap_req_id_text)
|
||||
memcpy(pos, hapd->conf->eap_req_id_text, extra);
|
||||
if (hapd->conf->eap_req_id_text) {
|
||||
memcpy(pos, hapd->conf->eap_req_id_text,
|
||||
hapd->conf->eap_req_id_text_len);
|
||||
}
|
||||
|
||||
sm->be_auth.eapReq = TRUE;
|
||||
free(sm->last_eap_radius);
|
||||
@ -424,12 +421,22 @@ static void ieee802_1x_encapsulate_radius(hostapd *hapd, struct sta_info *sta,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IP_ADDRESS,
|
||||
(u8 *) &hapd->conf->own_ip_addr, 4)) {
|
||||
if (hapd->conf->own_ip_addr.af == AF_INET &&
|
||||
!radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IP_ADDRESS,
|
||||
(u8 *) &hapd->conf->own_ip_addr.u.v4, 4)) {
|
||||
printf("Could not add NAS-IP-Address\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IPV6
|
||||
if (hapd->conf->own_ip_addr.af == AF_INET6 &&
|
||||
!radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IPV6_ADDRESS,
|
||||
(u8 *) &hapd->conf->own_ip_addr.u.v6, 16)) {
|
||||
printf("Could not add NAS-IPv6-Address\n");
|
||||
goto fail;
|
||||
}
|
||||
#endif /* CONFIG_IPV6 */
|
||||
|
||||
if (hapd->conf->nas_identifier &&
|
||||
!radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IDENTIFIER,
|
||||
(u8 *) hapd->conf->nas_identifier,
|
||||
@ -665,7 +672,8 @@ static void handle_eap(hostapd *hapd, struct sta_info *sta, u8 *buf,
|
||||
|
||||
|
||||
/* Process the EAPOL frames from the Supplicant */
|
||||
void ieee802_1x_receive(hostapd *hapd, u8 *sa, u8 *buf, size_t len)
|
||||
void ieee802_1x_receive(struct hostapd_data *hapd, const u8 *sa, const u8 *buf,
|
||||
size_t len)
|
||||
{
|
||||
struct sta_info *sta;
|
||||
struct ieee802_1x_hdr *hdr;
|
||||
@ -800,20 +808,17 @@ void ieee802_1x_new_station(hostapd *hapd, struct sta_info *sta)
|
||||
if (!hapd->conf->ieee802_1x || sta->wpa_key_mgmt == WPA_KEY_MGMT_PSK)
|
||||
return;
|
||||
|
||||
if (sta->eapol_sm) {
|
||||
sta->eapol_sm->portEnabled = TRUE;
|
||||
eapol_sm_step(sta->eapol_sm);
|
||||
return;
|
||||
}
|
||||
|
||||
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X,
|
||||
HOSTAPD_LEVEL_DEBUG, "start authentication");
|
||||
sta->eapol_sm = eapol_sm_alloc(hapd, sta);
|
||||
if (sta->eapol_sm == NULL) {
|
||||
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X,
|
||||
HOSTAPD_LEVEL_INFO, "failed to allocate "
|
||||
"state machine");
|
||||
return;
|
||||
HOSTAPD_LEVEL_DEBUG, "start authentication");
|
||||
sta->eapol_sm = eapol_sm_alloc(hapd, sta);
|
||||
if (sta->eapol_sm == NULL) {
|
||||
hostapd_logger(hapd, sta->addr,
|
||||
HOSTAPD_MODULE_IEEE8021X,
|
||||
HOSTAPD_LEVEL_INFO,
|
||||
"failed to allocate state machine");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
sta->eapol_sm->portEnabled = TRUE;
|
||||
@ -831,7 +836,49 @@ void ieee802_1x_new_station(hostapd *hapd, struct sta_info *sta)
|
||||
sta->eapol_sm->authSuccess = TRUE;
|
||||
if (sta->eapol_sm->eap)
|
||||
eap_sm_notify_cached(sta->eapol_sm->eap);
|
||||
} else
|
||||
eapol_sm_step(sta->eapol_sm);
|
||||
}
|
||||
|
||||
|
||||
void ieee802_1x_free_radius_class(struct radius_class_data *class)
|
||||
{
|
||||
int i;
|
||||
if (class == NULL)
|
||||
return;
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@ -854,7 +901,7 @@ void ieee802_1x_free_station(struct sta_info *sta)
|
||||
free(sm->last_eap_supp);
|
||||
free(sm->last_eap_radius);
|
||||
free(sm->identity);
|
||||
free(sm->radius_class);
|
||||
ieee802_1x_free_radius_class(&sm->radius_class);
|
||||
free(sm->eapol_key_sign);
|
||||
free(sm->eapol_key_crypt);
|
||||
eapol_sm_free(sm);
|
||||
@ -997,31 +1044,87 @@ static void ieee802_1x_store_radius_class(struct hostapd_data *hapd,
|
||||
u8 *class;
|
||||
size_t class_len;
|
||||
struct eapol_state_machine *sm = sta->eapol_sm;
|
||||
int count, i;
|
||||
struct radius_attr_data *nclass;
|
||||
size_t nclass_count;
|
||||
|
||||
if (!hapd->conf->acct_server || hapd->radius == NULL || sm == NULL)
|
||||
if (!hapd->conf->radius->acct_server || hapd->radius == NULL ||
|
||||
sm == NULL)
|
||||
return;
|
||||
|
||||
if (radius_msg_get_attr_ptr(msg, RADIUS_ATTR_CLASS, &class,
|
||||
&class_len) < 0 ||
|
||||
class_len < 1) {
|
||||
free(sm->radius_class);
|
||||
sm->radius_class = NULL;
|
||||
sm->radius_class_len = 0;
|
||||
ieee802_1x_free_radius_class(&sm->radius_class);
|
||||
count = radius_msg_count_attr(msg, RADIUS_ATTR_CLASS, 1);
|
||||
if (count <= 0)
|
||||
return;
|
||||
|
||||
nclass = malloc(count * sizeof(struct radius_attr_data));
|
||||
if (nclass == NULL)
|
||||
return;
|
||||
|
||||
nclass_count = 0;
|
||||
memset(nclass, 0, count * sizeof(struct radius_attr_data));
|
||||
|
||||
class = NULL;
|
||||
for (i = 0; i < count; i++) {
|
||||
do {
|
||||
if (radius_msg_get_attr_ptr(msg, RADIUS_ATTR_CLASS,
|
||||
&class, &class_len,
|
||||
class) < 0) {
|
||||
i = count;
|
||||
break;
|
||||
}
|
||||
} while (class_len < 1);
|
||||
|
||||
nclass[nclass_count].data = malloc(class_len);
|
||||
if (nclass[nclass_count].data == NULL)
|
||||
break;
|
||||
|
||||
memcpy(nclass[nclass_count].data, class, class_len);
|
||||
nclass[nclass_count].len = class_len;
|
||||
nclass_count++;
|
||||
}
|
||||
|
||||
if (sm->radius_class == NULL ||
|
||||
sm->radius_class_len < class_len) {
|
||||
free(sm->radius_class);
|
||||
sm->radius_class = malloc(class_len);
|
||||
if (sm->radius_class == NULL) {
|
||||
sm->radius_class_len = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
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,
|
||||
MAC2STR(sta->addr));
|
||||
}
|
||||
|
||||
memcpy(sm->radius_class, class, class_len);
|
||||
sm->radius_class_len = class_len;
|
||||
|
||||
/* Update sta->identity based on User-Name attribute in Access-Accept */
|
||||
static void ieee802_1x_update_sta_identity(struct hostapd_data *hapd,
|
||||
struct sta_info *sta,
|
||||
struct radius_msg *msg)
|
||||
{
|
||||
u8 *buf, *identity;
|
||||
size_t len;
|
||||
struct eapol_state_machine *sm = sta->eapol_sm;
|
||||
|
||||
if (sm == NULL)
|
||||
return;
|
||||
|
||||
if (radius_msg_get_attr_ptr(msg, RADIUS_ATTR_USER_NAME, &buf, &len,
|
||||
NULL) < 0)
|
||||
return;
|
||||
|
||||
identity = malloc(len + 1);
|
||||
if (identity == NULL)
|
||||
return;
|
||||
|
||||
memcpy(identity, buf, len);
|
||||
identity[len] = '\0';
|
||||
|
||||
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X,
|
||||
HOSTAPD_LEVEL_DEBUG, "old identity '%s' updated with "
|
||||
"User-Name from Access-Accept '%s'",
|
||||
sm->identity ? (char *) sm->identity : "N/A",
|
||||
(char *) identity);
|
||||
|
||||
free(sm->identity);
|
||||
sm->identity = identity;
|
||||
sm->identity_len = len;
|
||||
}
|
||||
|
||||
|
||||
@ -1066,7 +1169,7 @@ ieee802_1x_receive_auth(struct radius_msg *msg, struct radius_msg *req,
|
||||
{
|
||||
struct hostapd_data *hapd = data;
|
||||
struct sta_info *sta;
|
||||
u32 session_timeout, termination_action, acct_interim_interval;
|
||||
u32 session_timeout = 0, termination_action, acct_interim_interval;
|
||||
int session_timeout_set;
|
||||
int eap_timeout;
|
||||
struct eapol_state_machine *sm;
|
||||
@ -1091,7 +1194,7 @@ ieee802_1x_receive_auth(struct radius_msg *msg, struct radius_msg *req,
|
||||
"Access-Reject without Message-Authenticator "
|
||||
"since it does not include EAP-Message\n");
|
||||
} else if (radius_msg_verify(msg, shared_secret, shared_secret_len,
|
||||
req)) {
|
||||
req, 1)) {
|
||||
printf("Incoming RADIUS packet did not have correct "
|
||||
"Message-Authenticator - dropped\n");
|
||||
return RADIUS_RX_INVALID_AUTHENTICATOR;
|
||||
@ -1123,7 +1226,7 @@ ieee802_1x_receive_auth(struct radius_msg *msg, struct radius_msg *req,
|
||||
&termination_action))
|
||||
termination_action = RADIUS_TERMINATION_ACTION_DEFAULT;
|
||||
|
||||
if (hapd->conf->radius_acct_interim_interval == 0 &&
|
||||
if (hapd->conf->radius->acct_interim_interval == 0 &&
|
||||
msg->hdr->code == RADIUS_CODE_ACCESS_ACCEPT &&
|
||||
radius_msg_get_attr_int32(msg, RADIUS_ATTR_ACCT_INTERIM_INTERVAL,
|
||||
&acct_interim_interval) == 0) {
|
||||
@ -1152,12 +1255,13 @@ 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);
|
||||
ieee802_1x_update_sta_identity(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;
|
||||
@ -1199,7 +1303,7 @@ void ieee802_1x_send_resp_to_server(hostapd *hapd, struct sta_info *sta)
|
||||
if (sm == NULL)
|
||||
return;
|
||||
|
||||
if (hapd->conf->eap_authenticator) {
|
||||
if (hapd->conf->eap_server) {
|
||||
eap_set_eapRespData(sm->eap, sm->last_eap_supp,
|
||||
sm->last_eap_supp_len);
|
||||
} else {
|
||||
@ -1229,9 +1333,6 @@ void ieee802_1x_abort_auth(struct hostapd_data *hapd, struct sta_info *sta)
|
||||
free(sm->last_eap_radius);
|
||||
sm->last_eap_radius = NULL;
|
||||
sm->last_eap_radius_len = 0;
|
||||
free(sm->radius_class);
|
||||
sm->radius_class = NULL;
|
||||
sm->radius_class_len = 0;
|
||||
}
|
||||
|
||||
|
||||
@ -1482,13 +1583,15 @@ 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)
|
||||
u8 * ieee802_1x_get_radius_class(struct eapol_state_machine *sm, size_t *len,
|
||||
int idx)
|
||||
{
|
||||
if (sm == NULL || sm->radius_class == NULL)
|
||||
if (sm == NULL || sm->radius_class.attr == NULL ||
|
||||
idx >= sm->radius_class.count)
|
||||
return NULL;
|
||||
|
||||
*len = sm->radius_class_len;
|
||||
return sm->radius_class;
|
||||
*len = sm->radius_class.attr[idx].len;
|
||||
return sm->radius_class.attr[idx].data;
|
||||
}
|
||||
|
||||
|
||||
@ -1508,6 +1611,7 @@ void ieee802_1x_notify_port_enabled(struct eapol_state_machine *sm,
|
||||
if (sm == NULL)
|
||||
return;
|
||||
sm->portEnabled = enabled ? TRUE : FALSE;
|
||||
eapol_sm_step(sm);
|
||||
}
|
||||
|
||||
|
||||
@ -1517,6 +1621,7 @@ void ieee802_1x_notify_port_valid(struct eapol_state_machine *sm,
|
||||
if (sm == NULL)
|
||||
return;
|
||||
sm->portValid = valid ? TRUE : FALSE;
|
||||
eapol_sm_step(sm);
|
||||
}
|
||||
|
||||
|
||||
|
@ -12,13 +12,7 @@ struct ieee802_1x_hdr {
|
||||
/* followed by length octets of data */
|
||||
} __attribute__ ((packed));
|
||||
|
||||
|
||||
#if defined(IEEE802_1X_EAPOL_VERSION_2)
|
||||
#define EAPOL_VERSION 2
|
||||
#else
|
||||
/* Enable support for older Authenticators/Supplicants using EAPOL Version 1 */
|
||||
#define EAPOL_VERSION 1
|
||||
#endif /* ! IEEE802_1X_EAPOL_VERSION_2 */
|
||||
|
||||
enum { IEEE802_1X_TYPE_EAP_PACKET = 0,
|
||||
IEEE802_1X_TYPE_EAPOL_START = 1,
|
||||
@ -55,7 +49,8 @@ enum { EAPOL_KEY_TYPE_RC4 = 1, EAPOL_KEY_TYPE_RSN = 2,
|
||||
EAPOL_KEY_TYPE_WPA = 254 };
|
||||
|
||||
|
||||
void ieee802_1x_receive(hostapd *hapd, u8 *sa, u8 *buf, size_t len);
|
||||
void ieee802_1x_receive(struct hostapd_data *hapd, const u8 *sa, const u8 *buf,
|
||||
size_t len);
|
||||
void ieee802_1x_new_station(hostapd *hapd, struct sta_info *sta);
|
||||
void ieee802_1x_free_station(struct sta_info *sta);
|
||||
|
||||
@ -77,7 +72,8 @@ void ieee802_1x_deinit(hostapd *hapd);
|
||||
int ieee802_1x_tx_status(hostapd *hapd, struct sta_info *sta, u8 *buf,
|
||||
size_t len, int ack);
|
||||
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);
|
||||
u8 * ieee802_1x_get_radius_class(struct eapol_state_machine *sm, size_t *len,
|
||||
int idx);
|
||||
u8 * ieee802_1x_get_key_crypt(struct eapol_state_machine *sm, size_t *len);
|
||||
void ieee802_1x_notify_port_enabled(struct eapol_state_machine *sm,
|
||||
int enabled);
|
||||
@ -91,4 +87,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 */
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user