/*
* hostapd / IEEE 802.1X-2004 Authenticator
- * Copyright (c) 2002-2008, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2002-2009, Jouni Malinen <j@w1.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
#include "includes.h"
+#include "common.h"
+#include "eloop.h"
+#include "crypto/md5.h"
+#include "crypto/crypto.h"
+#include "common/ieee802_11_defs.h"
+#include "common/wpa_ctrl.h"
+#include "radius/radius.h"
+#include "radius/radius_client.h"
+#include "eapol_auth/eapol_auth_sm.h"
+#include "eapol_auth/eapol_auth_sm_i.h"
#include "hostapd.h"
#include "ieee802_1x.h"
#include "accounting.h"
-#include "radius/radius.h"
-#include "radius/radius_client.h"
-#include "eapol_sm.h"
-#include "md5.h"
-#include "rc4.h"
-#include "eloop.h"
#include "sta_info.h"
#include "wpa.h"
#include "preauth.h"
#include "pmksa_cache.h"
-#include "driver.h"
+#include "config.h"
#include "hw_features.h"
#include "eap_server/eap.h"
if (sta->flags & WLAN_STA_PREAUTH) {
rsn_preauth_send(hapd, sta, buf, len);
} else {
- hostapd_send_eapol(hapd, sta->addr, buf, len, encrypt);
+ hapd->drv.send_eapol(hapd, sta->addr, buf, len, encrypt);
}
os_free(buf);
return;
if (authorized) {
+ if (!(sta->flags & WLAN_STA_AUTHORIZED))
+ wpa_msg(hapd->msg_ctx, MSG_INFO,
+ AP_STA_CONNECTED MACSTR, MAC2STR(sta->addr));
sta->flags |= WLAN_STA_AUTHORIZED;
- res = hostapd_sta_set_flags(hapd, sta->addr, sta->flags,
- WLAN_STA_AUTHORIZED, ~0);
+ res = hapd->drv.set_authorized(hapd, sta, 1);
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X,
HOSTAPD_LEVEL_DEBUG, "authorizing port");
} else {
+ if ((sta->flags & (WLAN_STA_AUTHORIZED | WLAN_STA_ASSOC)) ==
+ (WLAN_STA_AUTHORIZED | WLAN_STA_ASSOC))
+ wpa_msg(hapd->msg_ctx, MSG_INFO,
+ AP_STA_DISCONNECTED MACSTR,
+ MAC2STR(sta->addr));
sta->flags &= ~WLAN_STA_AUTHORIZED;
- res = hostapd_sta_set_flags(hapd, sta->addr, sta->flags,
- 0, ~WLAN_STA_AUTHORIZED);
+ res = hapd->drv.set_authorized(hapd, sta, 0);
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X,
HOSTAPD_LEVEL_DEBUG, "unauthorizing port");
}
}
-static void ieee802_1x_eap_timeout(void *eloop_ctx, void *timeout_ctx)
-{
- struct sta_info *sta = eloop_ctx;
- struct eapol_state_machine *sm = sta->eapol_sm;
- if (sm == NULL)
- return;
- hostapd_logger(sm->hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X,
- HOSTAPD_LEVEL_DEBUG, "EAP timeout");
- sm->eap_if->eapTimeout = TRUE;
- eapol_auth_step(sm);
-}
-
-
static void ieee802_1x_tx_key_one(struct hostapd_data *hapd,
struct sta_info *sta,
int idx, int broadcast,
}
os_memcpy(ekey, key->key_iv, sizeof(key->key_iv));
os_memcpy(ekey + sizeof(key->key_iv), sm->eap_if->eapKeyData, 32);
- rc4((u8 *) (key + 1), key_len, ekey, ekey_len);
+ rc4_skip(ekey, ekey_len, 0, (u8 *) (key + 1), key_len);
os_free(ekey);
/* This header is needed here for HMAC-MD5, but it will be regenerated
}
+#ifndef CONFIG_NO_VLAN
static struct hostapd_wep_keys *
ieee802_1x_group_alloc(struct hostapd_data *hapd, const char *ifname)
{
wpa_hexdump_key(MSG_DEBUG, "Default WEP key (dynamic VLAN)",
key->key[key->idx], key->len[key->idx]);
- if (hostapd_set_encryption(ifname, hapd, "WEP", NULL, key->idx,
- key->key[key->idx], key->len[key->idx], 1))
+ if (hapd->drv.set_key(ifname, hapd, WPA_ALG_WEP, NULL, key->idx, 1,
+ NULL, 0, key->key[key->idx], key->len[key->idx]))
printf("Could not set dynamic VLAN WEP encryption key.\n");
- hostapd_set_ieee8021x(ifname, hapd, 1);
+ hostapd_set_drv_ieee8021x(hapd, ifname, 1);
return key;
}
return ssid->dyn_vlan_keys[vlan_id];
}
+#endif /* CONFIG_NO_VLAN */
void ieee802_1x_tx_key(struct hostapd_data *hapd, struct sta_info *sta)
{
- struct hostapd_wep_keys *key = NULL;
+ struct eapol_authenticator *eapol = hapd->eapol_auth;
struct eapol_state_machine *sm = sta->eapol_sm;
+#ifndef CONFIG_NO_VLAN
+ struct hostapd_wep_keys *key = NULL;
int vlan_id;
+#endif /* CONFIG_NO_VLAN */
if (sm == NULL || !sm->eap_if->eapKeyData)
return;
wpa_printf(MSG_DEBUG, "IEEE 802.1X: Sending EAPOL-Key(s) to " MACSTR,
MAC2STR(sta->addr));
+#ifndef CONFIG_NO_VLAN
vlan_id = sta->vlan_id;
if (vlan_id < 0 || vlan_id > MAX_VLAN_ID)
vlan_id = 0;
ieee802_1x_tx_key_one(hapd, sta, key->idx, 1,
key->key[key->idx],
key->len[key->idx]);
- } else if (hapd->default_wep_key) {
- ieee802_1x_tx_key_one(hapd, sta, hapd->default_wep_key_idx, 1,
- hapd->default_wep_key,
+ } else
+#endif /* CONFIG_NO_VLAN */
+ if (eapol->default_wep_key) {
+ ieee802_1x_tx_key_one(hapd, sta, eapol->default_wep_key_idx, 1,
+ eapol->default_wep_key,
hapd->conf->default_wep_key_len);
}
/* TODO: set encryption in TX callback, i.e., only after STA
* has ACKed EAPOL-Key frame */
- if (hostapd_set_encryption(hapd->conf->iface, hapd, "WEP",
- sta->addr, 0, ikey,
- hapd->conf->individual_wep_key_len,
- 1)) {
+ if (hapd->drv.set_key(hapd->conf->iface, hapd, WPA_ALG_WEP,
+ sta->addr, 0, 1, NULL, 0, ikey,
+ hapd->conf->individual_wep_key_len)) {
wpa_printf(MSG_ERROR, "Could not set individual WEP "
"encryption.");
}
const char *radius_mode_txt(struct hostapd_data *hapd)
{
- if (hapd->iface->current_mode == NULL)
- return "802.11";
-
- switch (hapd->iface->current_mode->mode) {
+ switch (hapd->iface->conf->hw_mode) {
case HOSTAPD_MODE_IEEE80211A:
return "802.11a";
case HOSTAPD_MODE_IEEE80211G:
}
+#ifndef CONFIG_NO_RADIUS
static void ieee802_1x_learn_identity(struct hostapd_data *hapd,
struct eapol_state_machine *sm,
const u8 *eap, size_t len)
/* State attribute must be copied if and only if this packet is
* Access-Request reply to the previous Access-Challenge */
- if (sm->last_recv_radius && sm->last_recv_radius->hdr->code ==
+ if (sm->last_recv_radius &&
+ radius_msg_get_hdr(sm->last_recv_radius)->code ==
RADIUS_CODE_ACCESS_CHALLENGE) {
int res = radius_msg_copy_attr(msg, sm->last_recv_radius,
RADIUS_ATTR_STATE);
fail:
radius_msg_free(msg);
- os_free(msg);
-}
-
-
-char *eap_type_text(u8 type)
-{
- switch (type) {
- case EAP_TYPE_IDENTITY: return "Identity";
- case EAP_TYPE_NOTIFICATION: return "Notification";
- case EAP_TYPE_NAK: return "Nak";
- case EAP_TYPE_MD5: return "MD5-Challenge";
- case EAP_TYPE_OTP: return "One-Time Password";
- case EAP_TYPE_GTC: return "Generic Token Card";
- case EAP_TYPE_TLS: return "TLS";
- case EAP_TYPE_TTLS: return "TTLS";
- case EAP_TYPE_PEAP: return "PEAP";
- case EAP_TYPE_SIM: return "SIM";
- case EAP_TYPE_FAST: return "FAST";
- case EAP_TYPE_SAKE: return "SAKE";
- case EAP_TYPE_PSK: return "PSK";
- case EAP_TYPE_PAX: return "PAX";
- default: return "Unknown";
- }
}
+#endif /* CONFIG_NO_RADIUS */
static void handle_eap_response(struct hostapd_data *hapd,
}
sm->eap_type_supp = type = data[0];
- eloop_cancel_timeout(ieee802_1x_eap_timeout, sta, NULL);
hostapd_logger(hapd, sm->addr, HOSTAPD_MODULE_IEEE8021X,
HOSTAPD_LEVEL_DEBUG, "received EAP packet (code=%d "
"id=%d len=%d) from STA: EAP Response-%s (%d)",
eap->code, eap->identifier, be_to_host16(eap->length),
- eap_type_text(type), type);
+ eap_server_get_name(0, type), type);
sm->dot1xAuthEapolRespFramesRx++;
}
-/* Process the EAPOL frames from the Supplicant */
+static struct eapol_state_machine *
+ieee802_1x_alloc_eapol_sm(struct hostapd_data *hapd, struct sta_info *sta)
+{
+ int flags = 0;
+ if (sta->flags & WLAN_STA_PREAUTH)
+ flags |= EAPOL_SM_PREAUTH;
+ if (sta->wpa_sm) {
+ if (wpa_auth_sta_get_pmksa(sta->wpa_sm))
+ flags |= EAPOL_SM_USES_WPA;
+ if (wpa_auth_sta_get_pmksa(sta->wpa_sm))
+ flags |= EAPOL_SM_FROM_PMKSA_CACHE;
+ }
+ return eapol_auth_alloc(hapd->eapol_auth, sta->addr, flags,
+ sta->wps_ie, sta);
+}
+
+
+/**
+ * ieee802_1x_receive - Process the EAPOL frames from the Supplicant
+ * @hapd: hostapd BSS data
+ * @sa: Source address (sender of the EAPOL frame)
+ * @buf: EAPOL frame
+ * @len: Length of buf in octets
+ *
+ * This function is called for each incoming EAPOL frame from the interface
+ */
void ieee802_1x_receive(struct hostapd_data *hapd, const u8 *sa, const u8 *buf,
size_t len)
{
u16 datalen;
struct rsn_pmksa_cache_entry *pmksa;
- if (!hapd->conf->ieee802_1x && !hapd->conf->wpa)
+ if (!hapd->conf->ieee802_1x && !hapd->conf->wpa &&
+ !hapd->conf->wps_state)
return;
wpa_printf(MSG_DEBUG, "IEEE 802.1X: %lu bytes from " MACSTR,
(unsigned long) len, MAC2STR(sa));
sta = ap_get_sta(hapd, sa);
- if (!sta) {
- printf(" no station information available\n");
+ if (!sta || !(sta->flags & WLAN_STA_ASSOC)) {
+ wpa_printf(MSG_DEBUG, "IEEE 802.1X data frame from not "
+ "associated STA");
return;
}
return;
}
- if (!hapd->conf->ieee802_1x ||
+ if ((!hapd->conf->ieee802_1x &&
+ !(sta->flags & (WLAN_STA_WPS | WLAN_STA_MAYBE_WPS))) ||
wpa_key_mgmt_wpa_psk(wpa_auth_sta_key_mgmt(sta->wpa_sm)))
return;
if (!sta->eapol_sm) {
- sta->eapol_sm = eapol_auth_alloc(hapd->eapol_auth, sta->addr,
- sta->flags & WLAN_STA_PREAUTH,
- sta);
+ sta->eapol_sm = ieee802_1x_alloc_eapol_sm(hapd, sta);
if (!sta->eapol_sm)
return;
+
+#ifdef CONFIG_WPS
+ if (!hapd->conf->ieee802_1x &&
+ ((sta->flags & (WLAN_STA_WPS | WLAN_STA_MAYBE_WPS)) ==
+ WLAN_STA_MAYBE_WPS)) {
+ /*
+ * Delay EAPOL frame transmission until a possible WPS
+ * STA initiates the handshake with EAPOL-Start.
+ */
+ sta->eapol_sm->flags |= EAPOL_SM_WAIT_START;
+ }
+#endif /* CONFIG_WPS */
+
+ sta->eapol_sm->eap_if->portEnabled = TRUE;
}
/* since we support version 1, we can ignore version field and proceed
"from STA");
sta->acct_terminate_cause =
RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST;
+ accounting_sta_stop(hapd, sta);
sta->eapol_sm->eapolLogoff = TRUE;
sta->eapol_sm->dot1xAuthEapolLogoffFramesRx++;
break;
}
+/**
+ * ieee802_1x_new_station - Start IEEE 802.1X authentication
+ * @hapd: hostapd BSS data
+ * @sta: The station
+ *
+ * This function is called to start IEEE 802.1X authentication when a new
+ * station completes IEEE 802.11 association.
+ */
void ieee802_1x_new_station(struct hostapd_data *hapd, struct sta_info *sta)
{
struct rsn_pmksa_cache_entry *pmksa;
int reassoc = 1;
int force_1x = 0;
+#ifdef CONFIG_WPS
+ if (hapd->conf->wps_state && hapd->conf->wpa &&
+ (sta->flags & (WLAN_STA_WPS | WLAN_STA_MAYBE_WPS))) {
+ /*
+ * Need to enable IEEE 802.1X/EAPOL state machines for possible
+ * WPS handshake even if IEEE 802.1X/EAPOL is not used for
+ * authentication in this BSS.
+ */
+ force_1x = 1;
+ }
+#endif /* CONFIG_WPS */
+
if ((!force_1x && !hapd->conf->ieee802_1x) ||
wpa_key_mgmt_wpa_psk(wpa_auth_sta_key_mgmt(sta->wpa_sm)))
return;
if (sta->eapol_sm == NULL) {
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X,
HOSTAPD_LEVEL_DEBUG, "start authentication");
- sta->eapol_sm = eapol_auth_alloc(hapd->eapol_auth, sta->addr,
- sta->flags & WLAN_STA_PREAUTH,
- sta);
+ sta->eapol_sm = ieee802_1x_alloc_eapol_sm(hapd, sta);
if (sta->eapol_sm == NULL) {
hostapd_logger(hapd, sta->addr,
HOSTAPD_MODULE_IEEE8021X,
reassoc = 0;
}
+#ifdef CONFIG_WPS
+ sta->eapol_sm->flags &= ~EAPOL_SM_WAIT_START;
+ if (!hapd->conf->ieee802_1x && !(sta->flags & WLAN_STA_WPS)) {
+ /*
+ * Delay EAPOL frame transmission until a possible WPS
+ * initiates the handshake with EAPOL-Start.
+ */
+ sta->eapol_sm->flags |= EAPOL_SM_WAIT_START;
+ }
+#endif /* CONFIG_WPS */
+
sta->eapol_sm->eap_if->portEnabled = TRUE;
pmksa = wpa_auth_sta_get_pmksa(sta->wpa_sm);
}
-void ieee802_1x_free_radius_class(struct radius_class_data *class)
-{
- size_t i;
- if (class == NULL)
- return;
- for (i = 0; i < class->count; i++)
- os_free(class->attr[i].data);
- os_free(class->attr);
- class->attr = NULL;
- class->count = 0;
-}
-
-
-int ieee802_1x_copy_radius_class(struct radius_class_data *dst,
- const struct radius_class_data *src)
-{
- size_t i;
-
- if (src->attr == NULL)
- return 0;
-
- dst->attr = os_zalloc(src->count * sizeof(struct radius_attr_data));
- if (dst->attr == NULL)
- return -1;
-
- dst->count = 0;
-
- for (i = 0; i < src->count; i++) {
- dst->attr[i].data = os_malloc(src->attr[i].len);
- if (dst->attr[i].data == NULL)
- break;
- dst->count++;
- os_memcpy(dst->attr[i].data, src->attr[i].data,
- src->attr[i].len);
- dst->attr[i].len = src->attr[i].len;
- }
-
- return 0;
-}
-
-
void ieee802_1x_free_station(struct sta_info *sta)
{
struct eapol_state_machine *sm = sta->eapol_sm;
- eloop_cancel_timeout(ieee802_1x_eap_timeout, sta, NULL);
-
if (sm == NULL)
return;
sta->eapol_sm = NULL;
- if (sm->last_recv_radius) {
- radius_msg_free(sm->last_recv_radius);
- os_free(sm->last_recv_radius);
- }
+#ifndef CONFIG_NO_RADIUS
+ radius_msg_free(sm->last_recv_radius);
+ radius_free_class(&sm->radius_class);
+#endif /* CONFIG_NO_RADIUS */
os_free(sm->identity);
- ieee802_1x_free_radius_class(&sm->radius_class);
eapol_auth_free(sm);
}
+#ifndef CONFIG_NO_RADIUS
static void ieee802_1x_decapsulate_radius(struct hostapd_data *hapd,
struct sta_info *sta)
{
if (eap_type >= 0)
sm->eap_type_authsrv = eap_type;
os_snprintf(buf, sizeof(buf), "EAP-Request-%s (%d)",
- eap_type >= 0 ? eap_type_text(eap_type) : "??",
+ eap_type >= 0 ? eap_server_get_name(0, eap_type) :
+ "??",
eap_type);
break;
case EAP_CODE_RESPONSE:
os_snprintf(buf, sizeof(buf), "EAP Response-%s (%d)",
- eap_type >= 0 ? eap_type_text(eap_type) : "??",
+ eap_type >= 0 ? eap_server_get_name(0, eap_type) :
+ "??",
eap_type);
break;
case EAP_CODE_SUCCESS:
static void ieee802_1x_get_keys(struct hostapd_data *hapd,
struct sta_info *sta, struct radius_msg *msg,
struct radius_msg *req,
- u8 *shared_secret, size_t shared_secret_len)
+ const u8 *shared_secret,
+ size_t shared_secret_len)
{
struct radius_ms_mppe_keys *keys;
struct eapol_state_machine *sm = sta->eapol_sm;
sm == NULL)
return;
- ieee802_1x_free_radius_class(&sm->radius_class);
+ radius_free_class(&sm->radius_class);
count = radius_msg_count_attr(msg, RADIUS_ATTR_CLASS, 1);
if (count <= 0)
return;
}
-/* Process the RADIUS frames from Authentication Server */
+/**
+ * ieee802_1x_receive_auth - Process RADIUS frames from Authentication Server
+ * @msg: RADIUS response message
+ * @req: RADIUS request message
+ * @shared_secret: RADIUS shared secret
+ * @shared_secret_len: Length of shared_secret in octets
+ * @data: Context data (struct hostapd_data *)
+ * Returns: Processing status
+ */
static RadiusRxResult
ieee802_1x_receive_auth(struct radius_msg *msg, struct radius_msg *req,
- u8 *shared_secret, size_t shared_secret_len,
+ const u8 *shared_secret, size_t shared_secret_len,
void *data)
{
struct hostapd_data *hapd = data;
struct sta_info *sta;
u32 session_timeout = 0, termination_action, acct_interim_interval;
int session_timeout_set, old_vlanid = 0;
- int eap_timeout;
struct eapol_state_machine *sm;
int override_eapReq = 0;
+ struct radius_hdr *hdr = radius_msg_get_hdr(msg);
- sm = ieee802_1x_search_radius_identifier(hapd, msg->hdr->identifier);
+ sm = ieee802_1x_search_radius_identifier(hapd, hdr->identifier);
if (sm == NULL) {
wpa_printf(MSG_DEBUG, "IEEE 802.1X: Could not find matching "
"station for this RADIUS message");
/* RFC 2869, Ch. 5.13: valid Message-Authenticator attribute MUST be
* present when packet contains an EAP-Message attribute */
- if (msg->hdr->code == RADIUS_CODE_ACCESS_REJECT &&
+ if (hdr->code == RADIUS_CODE_ACCESS_REJECT &&
radius_msg_get_attr(msg, RADIUS_ATTR_MESSAGE_AUTHENTICATOR, NULL,
0) < 0 &&
radius_msg_get_attr(msg, RADIUS_ATTR_EAP_MESSAGE, NULL, 0) < 0) {
return RADIUS_RX_INVALID_AUTHENTICATOR;
}
- if (msg->hdr->code != RADIUS_CODE_ACCESS_ACCEPT &&
- msg->hdr->code != RADIUS_CODE_ACCESS_REJECT &&
- msg->hdr->code != RADIUS_CODE_ACCESS_CHALLENGE) {
+ if (hdr->code != RADIUS_CODE_ACCESS_ACCEPT &&
+ hdr->code != RADIUS_CODE_ACCESS_REJECT &&
+ hdr->code != RADIUS_CODE_ACCESS_CHALLENGE) {
printf("Unknown RADIUS message code\n");
return RADIUS_RX_UNKNOWN;
}
wpa_printf(MSG_DEBUG, "RADIUS packet matching with station " MACSTR,
MAC2STR(sta->addr));
- if (sm->last_recv_radius) {
- radius_msg_free(sm->last_recv_radius);
- os_free(sm->last_recv_radius);
- }
-
+ radius_msg_free(sm->last_recv_radius);
sm->last_recv_radius = msg;
session_timeout_set =
&termination_action))
termination_action = RADIUS_TERMINATION_ACTION_DEFAULT;
- if (hapd->conf->radius->acct_interim_interval == 0 &&
- msg->hdr->code == RADIUS_CODE_ACCESS_ACCEPT &&
+ if (hapd->conf->acct_interim_interval == 0 &&
+ hdr->code == RADIUS_CODE_ACCESS_ACCEPT &&
radius_msg_get_attr_int32(msg, RADIUS_ATTR_ACCT_INTERIM_INTERVAL,
&acct_interim_interval) == 0) {
if (acct_interim_interval < 60) {
}
- switch (msg->hdr->code) {
+ switch (hdr->code) {
case RADIUS_CODE_ACCESS_ACCEPT:
if (sta->ssid->dynamic_vlan == DYNAMIC_VLAN_DISABLED)
sta->vlan_id = 0;
+#ifndef CONFIG_NO_VLAN
else {
old_vlanid = sta->vlan_id;
sta->vlan_id = radius_msg_get_vlanid(msg);
"ID in Access-Accept");
break;
}
+#endif /* CONFIG_NO_VLAN */
ap_sta_bind_vlan(hapd, sta, old_vlanid);
sm->eap_if->aaaEapReq = TRUE;
if (session_timeout_set) {
/* RFC 2869, Ch. 2.3.2; RFC 3580, Ch. 3.17 */
- eap_timeout = session_timeout;
- } else
- eap_timeout = 30;
- hostapd_logger(hapd, sm->addr, HOSTAPD_MODULE_IEEE8021X,
- HOSTAPD_LEVEL_DEBUG,
- "using EAP timeout of %d seconds%s",
- eap_timeout,
- session_timeout_set ? " (from RADIUS)" : "");
- eloop_cancel_timeout(ieee802_1x_eap_timeout, sta, NULL);
- eloop_register_timeout(eap_timeout, 0, ieee802_1x_eap_timeout,
- sta, NULL);
- sm->eap_if->eapTimeout = FALSE;
+ sm->eap_if->aaaMethodTimeout = session_timeout;
+ hostapd_logger(hapd, sm->addr,
+ HOSTAPD_MODULE_IEEE8021X,
+ HOSTAPD_LEVEL_DEBUG,
+ "using EAP timeout of %d seconds (from "
+ "RADIUS)",
+ sm->eap_if->aaaMethodTimeout);
+ } else {
+ /*
+ * Use dynamic retransmission behavior per EAP
+ * specification.
+ */
+ sm->eap_if->aaaMethodTimeout = 0;
+ }
break;
}
return RADIUS_RX_QUEUED;
}
+#endif /* CONFIG_NO_RADIUS */
void ieee802_1x_abort_auth(struct hostapd_data *hapd, struct sta_info *sta)
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X,
HOSTAPD_LEVEL_DEBUG, "aborting authentication");
- if (sm->last_recv_radius) {
- radius_msg_free(sm->last_recv_radius);
- os_free(sm->last_recv_radius);
- sm->last_recv_radius = NULL;
- }
-}
-
-
-#ifdef HOSTAPD_DUMP_STATE
-static void fprint_char(FILE *f, char c)
-{
- if (c >= 32 && c < 127)
- fprintf(f, "%c", c);
- else
- fprintf(f, "<%02x>", c);
-}
-
-
-void ieee802_1x_dump_state(FILE *f, const char *prefix, struct sta_info *sta)
-{
- struct eapol_state_machine *sm = sta->eapol_sm;
- if (sm == NULL)
- return;
-
- fprintf(f, "%sIEEE 802.1X:\n", prefix);
-
- if (sm->identity) {
- size_t i;
- fprintf(f, "%sidentity=", prefix);
- for (i = 0; i < sm->identity_len; i++)
- fprint_char(f, sm->identity[i]);
- fprintf(f, "\n");
+#ifndef CONFIG_NO_RADIUS
+ radius_msg_free(sm->last_recv_radius);
+ sm->last_recv_radius = NULL;
+#endif /* CONFIG_NO_RADIUS */
+
+ if (sm->eap_if->eapTimeout) {
+ /*
+ * Disconnect the STA since it did not reply to the last EAP
+ * request and we cannot continue EAP processing (EAP-Failure
+ * could only be sent if the EAP peer actually replied).
+ */
+ sm->eap_if->portEnabled = FALSE;
+ ap_sta_disconnect(hapd, sta, sta->addr,
+ WLAN_REASON_PREV_AUTH_NOT_VALID);
}
-
- fprintf(f, "%slast EAP type: Authentication Server: %d (%s) "
- "Supplicant: %d (%s)\n", prefix,
- sm->eap_type_authsrv, eap_type_text(sm->eap_type_authsrv),
- sm->eap_type_supp, eap_type_text(sm->eap_type_supp));
-
- fprintf(f, "%scached_packets=%s\n", prefix,
- sm->last_recv_radius ? "[RX RADIUS]" : "");
-
- eapol_auth_dump_state(f, prefix, sm);
}
-#endif /* HOSTAPD_DUMP_STATE */
static int ieee802_1x_rekey_broadcast(struct hostapd_data *hapd)
{
+ struct eapol_authenticator *eapol = hapd->eapol_auth;
+
if (hapd->conf->default_wep_key_len < 1)
return 0;
- os_free(hapd->default_wep_key);
- hapd->default_wep_key = os_malloc(hapd->conf->default_wep_key_len);
- if (hapd->default_wep_key == NULL ||
- os_get_random(hapd->default_wep_key,
+ os_free(eapol->default_wep_key);
+ eapol->default_wep_key = os_malloc(hapd->conf->default_wep_key_len);
+ if (eapol->default_wep_key == NULL ||
+ os_get_random(eapol->default_wep_key,
hapd->conf->default_wep_key_len)) {
printf("Could not generate random WEP key.\n");
- os_free(hapd->default_wep_key);
- hapd->default_wep_key = NULL;
+ os_free(eapol->default_wep_key);
+ eapol->default_wep_key = NULL;
return -1;
}
wpa_hexdump_key(MSG_DEBUG, "IEEE 802.1X: New default WEP key",
- hapd->default_wep_key,
+ eapol->default_wep_key,
hapd->conf->default_wep_key_len);
return 0;
static void ieee802_1x_rekey(void *eloop_ctx, void *timeout_ctx)
{
struct hostapd_data *hapd = eloop_ctx;
+ struct eapol_authenticator *eapol = hapd->eapol_auth;
- if (hapd->default_wep_key_idx >= 3)
- hapd->default_wep_key_idx =
+ if (eapol->default_wep_key_idx >= 3)
+ eapol->default_wep_key_idx =
hapd->conf->individual_wep_key_len > 0 ? 1 : 0;
else
- hapd->default_wep_key_idx++;
+ eapol->default_wep_key_idx++;
wpa_printf(MSG_DEBUG, "IEEE 802.1X: New default WEP key index %d",
- hapd->default_wep_key_idx);
+ eapol->default_wep_key_idx);
if (ieee802_1x_rekey_broadcast(hapd)) {
hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE8021X,
HOSTAPD_LEVEL_WARNING, "failed to generate a "
"new broadcast key");
- os_free(hapd->default_wep_key);
- hapd->default_wep_key = NULL;
+ os_free(eapol->default_wep_key);
+ eapol->default_wep_key = NULL;
return;
}
/* TODO: Could setup key for RX here, but change default TX keyid only
* after new broadcast key has been sent to all stations. */
- if (hostapd_set_encryption(hapd->conf->iface, hapd, "WEP", NULL,
- hapd->default_wep_key_idx,
- hapd->default_wep_key,
- hapd->conf->default_wep_key_len, 1)) {
+ if (hapd->drv.set_key(hapd->conf->iface, hapd, WPA_ALG_WEP, NULL,
+ eapol->default_wep_key_idx, 1, NULL, 0,
+ eapol->default_wep_key,
+ hapd->conf->default_wep_key_len)) {
hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE8021X,
HOSTAPD_LEVEL_WARNING, "failed to configure a "
"new broadcast key");
- os_free(hapd->default_wep_key);
- hapd->default_wep_key = NULL;
+ os_free(eapol->default_wep_key);
+ eapol->default_wep_key = NULL;
return;
}
static void ieee802_1x_aaa_send(void *ctx, void *sta_ctx,
const u8 *data, size_t datalen)
{
+#ifndef CONFIG_NO_RADIUS
struct hostapd_data *hapd = ctx;
struct sta_info *sta = sta_ctx;
ieee802_1x_encapsulate_radius(hapd, sta, data, datalen);
+#endif /* CONFIG_NO_RADIUS */
}
static void ieee802_1x_logger(void *ctx, const u8 *addr,
eapol_logger_level level, const char *txt)
{
+#ifndef CONFIG_NO_HOSTAPD_LOGGER
struct hostapd_data *hapd = ctx;
int hlevel;
hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE8021X, hlevel, "%s",
txt);
+#endif /* CONFIG_NO_HOSTAPD_LOGGER */
}
}
+static void ieee802_1x_eapol_event(void *ctx, void *sta_ctx,
+ enum eapol_event type)
+{
+ /* struct hostapd_data *hapd = ctx; */
+ struct sta_info *sta = sta_ctx;
+ switch (type) {
+ case EAPOL_AUTH_SM_CHANGE:
+ wpa_auth_sm_notify(sta->wpa_sm);
+ break;
+ case EAPOL_AUTH_REAUTHENTICATE:
+ wpa_auth_sm_event(sta->wpa_sm, WPA_REAUTH_EAPOL);
+ break;
+ }
+}
+
+
int ieee802_1x_init(struct hostapd_data *hapd)
{
int i;
struct eapol_auth_cb cb;
os_memset(&conf, 0, sizeof(conf));
- conf.hapd = hapd;
+ conf.ctx = hapd;
conf.eap_reauth_period = hapd->conf->eap_reauth_period;
conf.wpa = hapd->conf->wpa;
conf.individual_wep_key_len = hapd->conf->individual_wep_key_len;
conf.pac_key_refresh_time = hapd->conf->pac_key_refresh_time;
conf.eap_sim_aka_result_ind = hapd->conf->eap_sim_aka_result_ind;
conf.tnc = hapd->conf->tnc;
+ conf.wps = hapd->wps;
os_memset(&cb, 0, sizeof(cb));
cb.eapol_send = ieee802_1x_eapol_send;
cb.set_port_authorized = ieee802_1x_set_port_authorized;
cb.abort_auth = _ieee802_1x_abort_auth;
cb.tx_key = _ieee802_1x_tx_key;
+ cb.eapol_event = ieee802_1x_eapol_event;
hapd->eapol_auth = eapol_auth_init(&conf, &cb);
if (hapd->eapol_auth == NULL)
return -1;
if ((hapd->conf->ieee802_1x || hapd->conf->wpa) &&
- hostapd_set_ieee8021x(hapd->conf->iface, hapd, 1))
+ hostapd_set_drv_ieee8021x(hapd, hapd->conf->iface, 1))
return -1;
+#ifndef CONFIG_NO_RADIUS
if (radius_client_register(hapd->radius, RADIUS_AUTH,
ieee802_1x_receive_auth, hapd))
return -1;
+#endif /* CONFIG_NO_RADIUS */
if (hapd->conf->default_wep_key_len) {
- hostapd_set_privacy(hapd, 1);
-
for (i = 0; i < 4; i++)
- hostapd_set_encryption(hapd->conf->iface, hapd,
- "none", NULL, i, NULL, 0, 0);
+ hapd->drv.set_key(hapd->conf->iface, hapd,
+ WPA_ALG_NONE, NULL, i, 0, NULL, 0,
+ NULL, 0);
ieee802_1x_rekey(hapd, NULL);
- if (hapd->default_wep_key == NULL)
+ if (hapd->eapol_auth->default_wep_key == NULL)
return -1;
}
if (hapd->driver != NULL &&
(hapd->conf->ieee802_1x || hapd->conf->wpa))
- hostapd_set_ieee8021x(hapd->conf->iface, hapd, 0);
+ hostapd_set_drv_ieee8021x(hapd, hapd->conf->iface, 0);
eapol_auth_deinit(hapd->eapol_auth);
hapd->eapol_auth = NULL;
}
-int ieee802_1x_reconfig(struct hostapd_data *hapd,
- struct hostapd_config *oldconf,
- struct hostapd_bss_config *oldbss)
-{
- ieee802_1x_deinit(hapd);
- return ieee802_1x_init(hapd);
-}
-
-
int ieee802_1x_tx_status(struct hostapd_data *hapd, struct sta_info *sta,
- u8 *buf, size_t len, int ack)
+ const u8 *buf, size_t len, int ack)
{
struct ieee80211_hdr *hdr;
struct ieee802_1x_hdr *xhdr;