mirror of
https://github.com/espressif/esp-idf.git
synced 2025-08-20 08:39:05 +00:00
wpa_supplicant: Add WPS registrar support for softAP mode
This commit is contained in:
@@ -12,7 +12,7 @@
|
||||
#include "common/defs.h"
|
||||
#include "common/wpa_common.h"
|
||||
|
||||
#define MAX_STA_COUNT 4
|
||||
#define MAX_STA_COUNT 10
|
||||
#define MAX_VLAN_ID 4094
|
||||
|
||||
typedef u8 macaddr[ETH_ALEN];
|
||||
@@ -105,7 +105,6 @@ struct hostapd_wpa_psk {
|
||||
u8 addr[ETH_ALEN];
|
||||
};
|
||||
|
||||
#if 0
|
||||
struct hostapd_eap_user {
|
||||
struct hostapd_eap_user *next;
|
||||
u8 *identity;
|
||||
@@ -124,6 +123,7 @@ struct hostapd_eap_user {
|
||||
int ttls_auth; /* EAP_TTLS_AUTH_* bitfield */
|
||||
};
|
||||
|
||||
#if 0
|
||||
struct hostapd_radius_attr {
|
||||
u8 type;
|
||||
struct wpabuf *val;
|
||||
@@ -247,7 +247,11 @@ struct hostapd_bss_config {
|
||||
*/
|
||||
u16 max_listen_interval;
|
||||
|
||||
int wps_state;
|
||||
#ifdef CONFIG_WPS
|
||||
#define WPS_DEV_TYPE_LEN 8
|
||||
/* maximum number of advertised WPS vendor extension attributes */
|
||||
#define MAX_WPS_VENDOR_EXTENSIONS 10
|
||||
int ap_setup_locked;
|
||||
u8 uuid[16];
|
||||
char *wps_pin_requests;
|
||||
|
@@ -233,10 +233,9 @@ hostapd_get_eap_user(struct hostapd_data *hapd, const u8 *identity,
|
||||
size_t identity_len, int phase2)
|
||||
{
|
||||
const struct hostapd_bss_config *conf = hapd->conf;
|
||||
struct hostapd_eap_user *user = conf->eap_user;
|
||||
|
||||
#ifdef CONFIG_WPS
|
||||
if (conf->wps_state && identity_len == WSC_ID_ENROLLEE_LEN &&
|
||||
if (identity_len == WSC_ID_ENROLLEE_LEN &&
|
||||
os_memcmp(identity, WSC_ID_ENROLLEE, WSC_ID_ENROLLEE_LEN) == 0) {
|
||||
static struct hostapd_eap_user wsc_enrollee;
|
||||
os_memset(&wsc_enrollee, 0, sizeof(wsc_enrollee));
|
||||
@@ -245,7 +244,7 @@ hostapd_get_eap_user(struct hostapd_data *hapd, const u8 *identity,
|
||||
return &wsc_enrollee;
|
||||
}
|
||||
|
||||
if (conf->wps_state && identity_len == WSC_ID_REGISTRAR_LEN &&
|
||||
if (identity_len == WSC_ID_REGISTRAR_LEN &&
|
||||
os_memcmp(identity, WSC_ID_REGISTRAR, WSC_ID_REGISTRAR_LEN) == 0) {
|
||||
static struct hostapd_eap_user wsc_registrar;
|
||||
os_memset(&wsc_registrar, 0, sizeof(wsc_registrar));
|
||||
@@ -258,27 +257,6 @@ hostapd_get_eap_user(struct hostapd_data *hapd, const u8 *identity,
|
||||
}
|
||||
#endif /* CONFIG_WPS */
|
||||
|
||||
while (user) {
|
||||
if (!phase2 && user->identity == NULL) {
|
||||
/* Wildcard match */
|
||||
break;
|
||||
}
|
||||
|
||||
if (user->phase2 == !!phase2 && user->wildcard_prefix &&
|
||||
identity_len >= user->identity_len &&
|
||||
os_memcmp(user->identity, identity, user->identity_len) ==
|
||||
0) {
|
||||
/* Wildcard prefix match */
|
||||
break;
|
||||
}
|
||||
|
||||
if (user->phase2 == !!phase2 &&
|
||||
user->identity_len == identity_len &&
|
||||
os_memcmp(user->identity, identity, identity_len) == 0)
|
||||
break;
|
||||
user = user->next;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SQLITE
|
||||
if (user == NULL && conf->eap_user_sqlite) {
|
||||
return eap_user_sqlite_get(hapd, identity, identity_len,
|
||||
@@ -286,5 +264,5 @@ hostapd_get_eap_user(struct hostapd_data *hapd, const u8 *identity,
|
||||
}
|
||||
#endif /* CONFIG_SQLITE */
|
||||
|
||||
return user;
|
||||
return NULL;
|
||||
}
|
||||
|
@@ -63,6 +63,25 @@ struct hostapd_frame_info {
|
||||
int ssi_signal; /* dBm */
|
||||
};
|
||||
|
||||
#ifdef CONFIG_WPS
|
||||
enum hapd_wps_status {
|
||||
WPS_SUCCESS_STATUS = 1,
|
||||
WPS_FAILURE_STATUS
|
||||
};
|
||||
|
||||
enum pbc_status {
|
||||
WPS_PBC_STATUS_DISABLE,
|
||||
WPS_PBC_STATUS_ACTIVE,
|
||||
WPS_PBC_STATUS_TIMEOUT,
|
||||
WPS_PBC_STATUS_OVERLAP
|
||||
};
|
||||
|
||||
struct wps_stat {
|
||||
enum hapd_wps_status status;
|
||||
enum pbc_status pbc_status;
|
||||
u8 peer_addr[ETH_ALEN];
|
||||
};
|
||||
#endif
|
||||
|
||||
/**
|
||||
* struct hostapd_data - hostapd per-BSS data structure
|
||||
@@ -73,9 +92,13 @@ struct hostapd_data {
|
||||
int interface_added; /* virtual interface added for this BSS */
|
||||
|
||||
u8 own_addr[ETH_ALEN];
|
||||
|
||||
struct sta_info *sta_list; /* STA info list head */
|
||||
#define STA_HASH_SIZE 10
|
||||
#define STA_HASH(sta) (sta[5] & 0xa)
|
||||
struct sta_info *sta_hash[STA_HASH_SIZE];
|
||||
int num_sta; /* number of entries in sta_list */
|
||||
|
||||
struct eapol_authenticator *eapol_auth;
|
||||
struct wpa_authenticator *wpa_auth;
|
||||
|
||||
#ifdef CONFIG_FULL_DYNAMIC_VLAN
|
||||
@@ -83,10 +106,15 @@ struct hostapd_data {
|
||||
#endif /* CONFIG_FULL_DYNAMIC_VLAN */
|
||||
|
||||
#ifdef CONFIG_WPS
|
||||
struct wps_context *wps;
|
||||
unsigned int ap_pin_failures;
|
||||
unsigned int ap_pin_failures_consecutive;
|
||||
struct upnp_wps_device_sm *wps_upnp;
|
||||
unsigned int ap_pin_lockout_time;
|
||||
|
||||
struct wps_stat wps_stats;
|
||||
void (*wps_event_cb)(void *ctx, enum wps_event event,
|
||||
union wps_event_data *data);
|
||||
#endif /* CONFIG_WPS */
|
||||
|
||||
#ifdef CONFIG_P2P
|
||||
@@ -112,4 +140,10 @@ struct hostapd_data {
|
||||
#endif /* CONFIG_SQLITE */
|
||||
};
|
||||
|
||||
struct hostapd_data *hostapd_get_hapd_data(void);
|
||||
|
||||
const struct hostapd_eap_user *
|
||||
hostapd_get_eap_user(struct hostapd_data *hapd, const u8 *identity,
|
||||
size_t identity_len, int phase2);
|
||||
|
||||
#endif /* HOSTAPD_H */
|
||||
|
@@ -9,14 +9,138 @@
|
||||
#include "utils/includes.h"
|
||||
|
||||
#include "utils/common.h"
|
||||
#include "utils/eloop.h"
|
||||
#include "crypto/crypto.h"
|
||||
#include "common/ieee802_11_defs.h"
|
||||
#include "hostapd.h"
|
||||
#include "ap/sta_info.h"
|
||||
#include "ap/wpa_auth.h"
|
||||
#include "eap_server/eap.h"
|
||||
#include "ap/ap_config.h"
|
||||
#include "eap_common/eap_wsc_common.h"
|
||||
#include "ap/ieee802_1x.h"
|
||||
#include "utils/wpa_debug.h"
|
||||
#include "eapol_auth/eapol_auth_sm.h"
|
||||
#include "eapol_auth/eapol_auth_sm_i.h"
|
||||
#include "eap_server/eap.h"
|
||||
#include "sta_info.h"
|
||||
#include "ieee802_1x.h"
|
||||
|
||||
int hostapd_send_eapol(const u8 *source, const u8 *sta_addr,
|
||||
const u8 *data, size_t data_len);
|
||||
|
||||
static void ieee802_1x_finished(struct hostapd_data *hapd,
|
||||
struct sta_info *sta, int success,
|
||||
int remediation);
|
||||
|
||||
static void ieee802_1x_send(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
u8 type, const u8 *data, size_t datalen)
|
||||
{
|
||||
u8 *buf;
|
||||
struct ieee802_1x_hdr *xhdr;
|
||||
size_t len;
|
||||
|
||||
len = sizeof(*xhdr) + datalen;
|
||||
buf = os_zalloc(len);
|
||||
if (!buf) {
|
||||
wpa_printf(MSG_ERROR, "malloc() failed for %s(len=%lu)",
|
||||
__func__, (unsigned long) len);
|
||||
return;
|
||||
}
|
||||
|
||||
xhdr = (struct ieee802_1x_hdr *) buf;
|
||||
xhdr->version = EAPOL_VERSION;
|
||||
xhdr->type = type;
|
||||
xhdr->length = host_to_be16(datalen);
|
||||
|
||||
if (datalen > 0 && data != NULL)
|
||||
os_memcpy(xhdr + 1, data, datalen);
|
||||
|
||||
hostapd_send_eapol(hapd->own_addr, sta->addr, buf, len);
|
||||
os_free(buf);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void handle_eap_response(struct hostapd_data *hapd,
|
||||
struct sta_info *sta, struct eap_hdr *eap,
|
||||
size_t len)
|
||||
{
|
||||
u8 type, *data;
|
||||
struct eapol_state_machine *sm = sta->eapol_sm;
|
||||
|
||||
if (!sm)
|
||||
return;
|
||||
|
||||
data = (u8 *) (eap + 1);
|
||||
|
||||
if (len < sizeof(*eap) + 1) {
|
||||
wpa_printf(MSG_INFO, "%s: too short response data", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
sm->eap_type_supp = type = data[0];
|
||||
|
||||
sm->dot1xAuthEapolRespFramesRx++;
|
||||
|
||||
wpabuf_free(sm->eap_if->eapRespData);
|
||||
sm->eap_if->eapRespData = wpabuf_alloc_copy(eap, len);
|
||||
sm->eapolEap = true;
|
||||
}
|
||||
|
||||
/* Process incoming EAP packet from Supplicant */
|
||||
static void handle_eap(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
u8 *buf, size_t len)
|
||||
{
|
||||
struct eap_hdr *eap;
|
||||
u16 eap_len;
|
||||
|
||||
if (len < sizeof(*eap)) {
|
||||
wpa_printf(MSG_INFO, " too short EAP packet");
|
||||
return;
|
||||
}
|
||||
|
||||
eap = (struct eap_hdr *) buf;
|
||||
|
||||
eap_len = be_to_host16(eap->length);
|
||||
wpa_printf(MSG_DEBUG, "EAP: code=%d identifier=%d length=%d",
|
||||
eap->code, eap->identifier,
|
||||
eap_len);
|
||||
if (eap_len < sizeof(*eap)) {
|
||||
wpa_printf(MSG_DEBUG, " Invalid EAP length");
|
||||
return;
|
||||
} else if (eap_len > len) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
" Too short frame to contain this EAP packet");
|
||||
return;
|
||||
} else if (eap_len < len) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
" Ignoring %lu extra bytes after EAP packet",
|
||||
(unsigned long) len - eap_len);
|
||||
}
|
||||
|
||||
switch (eap->code) {
|
||||
case EAP_CODE_RESPONSE:
|
||||
handle_eap_response(hapd, sta, eap, eap_len);
|
||||
break;
|
||||
case EAP_CODE_INITIATE:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
struct eapol_state_machine *
|
||||
ieee802_1x_alloc_eapol_sm(struct hostapd_data *hapd, struct sta_info *sta)
|
||||
{
|
||||
int flags = 0;
|
||||
|
||||
if (sta->wpa_sm) {
|
||||
flags |= EAPOL_SM_USES_WPA;
|
||||
}
|
||||
return eapol_auth_alloc(hapd->eapol_auth, sta->addr, flags,
|
||||
sta->wps_ie, NULL, sta,
|
||||
sta->identity, NULL);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* ieee802_1x_receive - Process the EAPOL frames from the Supplicant
|
||||
@@ -35,35 +159,44 @@ void ieee802_1x_receive(struct hostapd_data *hapd, const u8 *sa, const u8 *buf,
|
||||
struct ieee802_1x_eapol_key *key;
|
||||
u16 datalen;
|
||||
|
||||
wpa_printf( MSG_DEBUG, "IEEE 802.1X: %lu bytes from " MACSTR,
|
||||
wpa_printf(MSG_DEBUG, "IEEE 802.1X: %lu bytes from " MACSTR,
|
||||
(unsigned long) len, MAC2STR(sa));
|
||||
sta = ap_get_sta(hapd, sa);
|
||||
if (!sta || !(sta->flags & (WLAN_STA_ASSOC | WLAN_STA_PREAUTH))) {
|
||||
wpa_printf( MSG_DEBUG, "IEEE 802.1X data frame from not "
|
||||
"associated/Pre-authenticating STA");
|
||||
if (!sta) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"IEEE 802.1X data frame from not associated/Pre-authenticating STA");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (len < sizeof(*hdr)) {
|
||||
wpa_printf( MSG_DEBUG, " too short IEEE 802.1X packet\n");
|
||||
wpa_printf(MSG_INFO, " too short IEEE 802.1X packet");
|
||||
return;
|
||||
}
|
||||
|
||||
hdr = (struct ieee802_1x_hdr *) buf;
|
||||
datalen = be_to_host16(hdr->length);
|
||||
wpa_printf( MSG_DEBUG, " IEEE 802.1X: version=%d type=%d length=%d",
|
||||
wpa_printf(MSG_DEBUG, " IEEE 802.1X: version=%d type=%d length=%d",
|
||||
hdr->version, hdr->type, datalen);
|
||||
|
||||
if (len - sizeof(*hdr) < datalen) {
|
||||
wpa_printf( MSG_DEBUG, " frame too short for this IEEE 802.1X packet\n");
|
||||
wpa_printf(MSG_INFO,
|
||||
" frame too short for this IEEE 802.1X packet");
|
||||
if (sta->eapol_sm)
|
||||
sta->eapol_sm->dot1xAuthEapLengthErrorFramesRx++;
|
||||
return;
|
||||
}
|
||||
if (len - sizeof(*hdr) > datalen) {
|
||||
wpa_printf( MSG_DEBUG, " ignoring %lu extra octets after "
|
||||
"IEEE 802.1X packet",
|
||||
wpa_printf(MSG_DEBUG,
|
||||
" ignoring %lu extra octets after IEEE 802.1X packet",
|
||||
(unsigned long) len - sizeof(*hdr) - datalen);
|
||||
}
|
||||
|
||||
if (sta->eapol_sm) {
|
||||
sta->eapol_sm->dot1xAuthLastEapolFrameVersion = hdr->version;
|
||||
sta->eapol_sm->dot1xAuthEapolFramesRx++;
|
||||
}
|
||||
|
||||
key = (struct ieee802_1x_eapol_key *) (hdr + 1);
|
||||
if (datalen >= sizeof(struct ieee802_1x_eapol_key) &&
|
||||
hdr->type == IEEE802_1X_TYPE_EAPOL_KEY &&
|
||||
@@ -73,4 +206,274 @@ void ieee802_1x_receive(struct hostapd_data *hapd, const u8 *sa, const u8 *buf,
|
||||
sizeof(*hdr) + datalen);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!sta->eapol_sm) {
|
||||
sta->eapol_sm = ieee802_1x_alloc_eapol_sm(hapd, sta);
|
||||
if (!sta->eapol_sm)
|
||||
return;
|
||||
|
||||
#ifdef CONFIG_WPS
|
||||
if (!hapd->conf->ieee802_1x && hapd->conf->wps_state) {
|
||||
u32 wflags = sta->flags & (WLAN_STA_WPS |
|
||||
WLAN_STA_WPS2 |
|
||||
WLAN_STA_MAYBE_WPS);
|
||||
if (wflags == WLAN_STA_MAYBE_WPS ||
|
||||
wflags == (WLAN_STA_WPS | WLAN_STA_MAYBE_WPS)) {
|
||||
/*
|
||||
* Delay EAPOL frame transmission until a
|
||||
* possible WPS STA initiates the handshake
|
||||
* with EAPOL-Start. Only allow the wait to be
|
||||
* skipped if the STA is known to support WPS
|
||||
* 2.0.
|
||||
*/
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"WPS: Do not start EAPOL until EAPOL-Start is received");
|
||||
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
|
||||
* as specified in version 1 standard [IEEE Std 802.1X-2001, 7.5.5] */
|
||||
/* TODO: actually, we are not version 1 anymore.. However, Version 2
|
||||
* does not change frame contents, so should be ok to process frames
|
||||
* more or less identically. Some changes might be needed for
|
||||
* verification of fields. */
|
||||
|
||||
switch (hdr->type) {
|
||||
case IEEE802_1X_TYPE_EAP_PACKET:
|
||||
handle_eap(hapd, sta, (u8 *) (hdr + 1), datalen);
|
||||
break;
|
||||
|
||||
case IEEE802_1X_TYPE_EAPOL_START:
|
||||
sta->eapol_sm->flags &= ~EAPOL_SM_WAIT_START;
|
||||
sta->eapol_sm->eapolStart = true;
|
||||
sta->eapol_sm->dot1xAuthEapolStartFramesRx++;
|
||||
eap_server_clear_identity(sta->eapol_sm->eap);
|
||||
wpa_auth_sm_event(sta->wpa_sm, WPA_REAUTH_EAPOL);
|
||||
break;
|
||||
|
||||
|
||||
case IEEE802_1X_TYPE_EAPOL_LOGOFF:
|
||||
break;
|
||||
|
||||
case IEEE802_1X_TYPE_EAPOL_KEY:
|
||||
wpa_printf(MSG_DEBUG, " EAPOL-Key");
|
||||
break;
|
||||
|
||||
case IEEE802_1X_TYPE_EAPOL_ENCAPSULATED_ASF_ALERT:
|
||||
wpa_printf(MSG_DEBUG, " EAPOL-Encapsulated-ASF-Alert");
|
||||
/* TODO: implement support for this; show data */
|
||||
break;
|
||||
|
||||
default:
|
||||
wpa_printf(MSG_DEBUG, " unknown IEEE 802.1X packet type");
|
||||
sta->eapol_sm->dot1xAuthInvalidEapolFramesRx++;
|
||||
break;
|
||||
}
|
||||
|
||||
eapol_auth_step(sta->eapol_sm);
|
||||
}
|
||||
|
||||
|
||||
void ieee802_1x_free_station(struct hostapd_data *hapd, struct sta_info *sta)
|
||||
{
|
||||
struct eapol_state_machine *sm = sta->eapol_sm;
|
||||
|
||||
if (!sm)
|
||||
return;
|
||||
|
||||
sta->eapol_sm = NULL;
|
||||
eapol_auth_free(sm);
|
||||
}
|
||||
|
||||
|
||||
static void ieee802_1x_eapol_send(void *ctx, void *sta_ctx, u8 type,
|
||||
const u8 *data, size_t datalen)
|
||||
{
|
||||
#ifdef CONFIG_WPS
|
||||
struct sta_info *sta = sta_ctx;
|
||||
|
||||
if ((sta->flags & (WLAN_STA_WPS | WLAN_STA_MAYBE_WPS)) ==
|
||||
WLAN_STA_MAYBE_WPS) {
|
||||
const u8 *identity;
|
||||
size_t identity_len;
|
||||
struct eapol_state_machine *sm = sta->eapol_sm;
|
||||
|
||||
identity = eap_get_identity(sm->eap, &identity_len);
|
||||
if (identity &&
|
||||
((identity_len == WSC_ID_ENROLLEE_LEN &&
|
||||
os_memcmp(identity, WSC_ID_ENROLLEE,
|
||||
WSC_ID_ENROLLEE_LEN) == 0) ||
|
||||
(identity_len == WSC_ID_REGISTRAR_LEN &&
|
||||
os_memcmp(identity, WSC_ID_REGISTRAR,
|
||||
WSC_ID_REGISTRAR_LEN) == 0))) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"WPS: WLAN_STA_MAYBE_WPS -> WLAN_STA_WPS");
|
||||
sta->flags |= WLAN_STA_WPS;
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_WPS */
|
||||
|
||||
ieee802_1x_send(ctx, sta_ctx, type, data, datalen);
|
||||
}
|
||||
|
||||
|
||||
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_finished(void *ctx, void *sta_ctx, int success,
|
||||
int preauth, int remediation)
|
||||
{
|
||||
struct hostapd_data *hapd = ctx;
|
||||
struct sta_info *sta = sta_ctx;
|
||||
ieee802_1x_finished(hapd, sta, success, remediation);
|
||||
}
|
||||
|
||||
|
||||
static int ieee802_1x_get_eap_user(void *ctx, const u8 *identity,
|
||||
size_t identity_len, int phase2,
|
||||
struct eap_user *user)
|
||||
{
|
||||
struct hostapd_data *hapd = ctx;
|
||||
const struct hostapd_eap_user *eap_user;
|
||||
int i;
|
||||
int rv = -1;
|
||||
|
||||
eap_user = hostapd_get_eap_user(hapd, identity, identity_len, phase2);
|
||||
if (!eap_user)
|
||||
goto out;
|
||||
|
||||
os_memset(user, 0, sizeof(*user));
|
||||
user->phase2 = phase2;
|
||||
for (i = 0; i < EAP_MAX_METHODS; i++) {
|
||||
user->methods[i].vendor = eap_user->methods[i].vendor;
|
||||
user->methods[i].method = eap_user->methods[i].method;
|
||||
}
|
||||
|
||||
if (eap_user->password) {
|
||||
user->password = os_memdup(eap_user->password,
|
||||
eap_user->password_len);
|
||||
if (!user->password)
|
||||
goto out;
|
||||
user->password_len = eap_user->password_len;
|
||||
user->password_hash = eap_user->password_hash;
|
||||
}
|
||||
user->force_version = eap_user->force_version;
|
||||
user->ttls_auth = eap_user->ttls_auth;
|
||||
rv = 0;
|
||||
|
||||
out:
|
||||
if (rv)
|
||||
wpa_printf(MSG_DEBUG, "%s: Failed to find user", __func__);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
static int ieee802_1x_sta_entry_alive(void *ctx, const u8 *addr)
|
||||
{
|
||||
struct hostapd_data *hapd = ctx;
|
||||
struct sta_info *sta;
|
||||
|
||||
sta = ap_get_sta(hapd, addr);
|
||||
if (!sta || !sta->eapol_sm)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static void ieee802_1x_set_port_authorized(void *ctx, void *sta_ctx,
|
||||
int authorized)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
static void _ieee802_1x_abort_auth(void *ctx, void *sta_ctx)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
static void ieee802_1x_eapol_event(void *ctx, void *sta_ctx,
|
||||
enum eapol_event type)
|
||||
{
|
||||
#if 0
|
||||
/* 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;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
int ieee802_1x_init(struct hostapd_data *hapd)
|
||||
{
|
||||
struct eapol_auth_config conf;
|
||||
struct eapol_auth_cb cb;
|
||||
struct eap_config *eap_cfg;
|
||||
|
||||
os_memset(&conf, 0, sizeof(conf));
|
||||
eap_cfg = os_zalloc(sizeof(struct eap_config));
|
||||
eap_cfg->max_auth_rounds = 100;
|
||||
eap_cfg->max_auth_rounds_short = 50;
|
||||
//eap_cfg->backend_auth = 1;
|
||||
eap_cfg->eap_server = 1;
|
||||
conf.eap_cfg = eap_cfg;
|
||||
conf.ctx = hapd;
|
||||
conf.wpa = hapd->conf->wpa;
|
||||
|
||||
os_memset(&cb, 0, sizeof(cb));
|
||||
cb.eapol_send = ieee802_1x_eapol_send;
|
||||
cb.aaa_send = ieee802_1x_aaa_send;
|
||||
cb.finished = _ieee802_1x_finished;
|
||||
cb.get_eap_user = ieee802_1x_get_eap_user;
|
||||
cb.sta_entry_alive = ieee802_1x_sta_entry_alive;
|
||||
cb.set_port_authorized = ieee802_1x_set_port_authorized;
|
||||
cb.abort_auth = _ieee802_1x_abort_auth;
|
||||
cb.eapol_event = ieee802_1x_eapol_event;
|
||||
|
||||
hapd->eapol_auth = eapol_auth_init(&conf, &cb);
|
||||
if (!hapd->eapol_auth)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void ieee802_1x_finished(struct hostapd_data *hapd,
|
||||
struct sta_info *sta, int success,
|
||||
int remediation)
|
||||
{
|
||||
if (!success) {
|
||||
/*
|
||||
* Many devices require deauthentication after WPS provisioning
|
||||
* and some may not be be able to do that themselves, so
|
||||
* disconnect the client here. In addition, this may also
|
||||
* benefit IEEE 802.1X/EAPOL authentication cases, too since
|
||||
* the EAPOL PAE state machine would remain in HELD state for
|
||||
* considerable amount of time and some EAP methods, like
|
||||
* EAP-FAST with anonymous provisioning, may require another
|
||||
* EAPOL authentication to be started to complete connection.
|
||||
*/
|
||||
ap_sta_delayed_1x_auth_fail_disconnect(hapd, sta);
|
||||
}
|
||||
}
|
||||
|
@@ -17,8 +17,12 @@ struct hostapd_bss_config;
|
||||
struct hostapd_radius_attr;
|
||||
struct radius_msg;
|
||||
|
||||
|
||||
void ieee802_1x_receive(struct hostapd_data *hapd, const u8 *sa, const u8 *buf,
|
||||
size_t len);
|
||||
|
||||
void ieee802_1x_free_station(struct hostapd_data *hapd, struct sta_info *sta);
|
||||
int ieee802_1x_init(struct hostapd_data *hapd);
|
||||
struct eapol_state_machine *
|
||||
ieee802_1x_alloc_eapol_sm(struct hostapd_data *hapd, struct sta_info *sta);
|
||||
|
||||
#endif /* IEEE802_1X_H */
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* hostapd / Station table
|
||||
* Copyright (c) 2002-2011, Jouni Malinen <j@w1.fi>
|
||||
* Copyright (c) 2002-2017, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
@@ -42,36 +42,20 @@ struct sta_info {
|
||||
struct sta_info *next; /* next entry in sta list */
|
||||
struct sta_info *hnext; /* next entry in hash table list */
|
||||
u8 addr[6];
|
||||
u16 aid; /* STA's unique AID (1 .. 2007) or 0 if not yet assigned */
|
||||
u32 flags; /* Bitfield of WLAN_STA_* */
|
||||
u16 capability;
|
||||
u16 listen_interval; /* or beacon_int for APs */
|
||||
u8 supported_rates[WLAN_SUPP_RATES_MAX];
|
||||
int supported_rates_len;
|
||||
|
||||
u16 auth_alg;
|
||||
|
||||
enum {
|
||||
STA_NULLFUNC = 0, STA_DISASSOC, STA_DEAUTH, STA_REMOVE
|
||||
} timeout_next;
|
||||
|
||||
/* IEEE 802.1X related data */
|
||||
struct eapol_state_machine *eapol_sm;
|
||||
struct wpa_state_machine *wpa_sm;
|
||||
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
int sa_query_count; /* number of pending SA Query requests;
|
||||
* 0 = no SA Query in progress */
|
||||
int sa_query_timed_out;
|
||||
u8 *sa_query_trans_id; /* buffer of WLAN_SA_QUERY_TR_ID_LEN *
|
||||
* sa_query_count octets of pending SA Query
|
||||
* transaction identifiers */
|
||||
struct os_time sa_query_start;
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
char *identity; /* User-Name from RADIUS */
|
||||
|
||||
#ifdef CONFIG_INTERWORKING
|
||||
#define GAS_DIALOG_MAX 8 /* Max concurrent dialog number */
|
||||
struct gas_dialog_info *gas_dialog;
|
||||
u8 gas_dialog_next;
|
||||
#endif /* CONFIG_INTERWORKING */
|
||||
struct wpabuf *wps_ie; /* WPS IE from (Re)Association Request */
|
||||
|
||||
#ifdef CONFIG_SAE
|
||||
enum { SAE_INIT, SAE_COMMIT, SAE_CONFIRM } sae_state;
|
||||
@@ -137,5 +121,16 @@ static inline int ap_sta_is_authorized(struct sta_info *sta)
|
||||
|
||||
void ap_sta_deauth_cb(struct hostapd_data *hapd, struct sta_info *sta);
|
||||
void ap_sta_disassoc_cb(struct hostapd_data *hapd, struct sta_info *sta);
|
||||
void ap_sta_clear_disconnect_timeouts(struct hostapd_data *hapd,
|
||||
struct sta_info *sta);
|
||||
|
||||
int ap_sta_flags_txt(u32 flags, char *buf, size_t buflen);
|
||||
void ap_sta_delayed_1x_auth_fail_disconnect(struct hostapd_data *hapd,
|
||||
struct sta_info *sta);
|
||||
int ap_sta_pending_delayed_1x_auth_fail_disconnect(struct hostapd_data *hapd,
|
||||
struct sta_info *sta);
|
||||
int ap_sta_re_add(struct hostapd_data *hapd, struct sta_info *sta);
|
||||
|
||||
void ap_free_sta_pasn(struct hostapd_data *hapd, struct sta_info *sta);
|
||||
|
||||
#endif /* STA_INFO_H */
|
||||
|
@@ -18,6 +18,7 @@
|
||||
#include "hostapd.h"
|
||||
#include "rsn_supp/wpa.h"
|
||||
#include "ap/ap_config.h"
|
||||
#include "ap/sta_info.h"
|
||||
#include "common/wpa_common.h"
|
||||
|
||||
#include "crypto/aes_wrap.h"
|
||||
@@ -29,6 +30,7 @@
|
||||
#include "esp_wifi_driver.h"
|
||||
#include "esp_wifi.h"
|
||||
#include "esp_private/wifi.h"
|
||||
#include "esp_wpas_glue.h"
|
||||
|
||||
#define STATE_MACHINE_DATA struct wpa_state_machine
|
||||
#define STATE_MACHINE_DEBUG_PREFIX "WPA"
|
||||
@@ -183,22 +185,7 @@ static inline int
|
||||
wpa_auth_send_eapol(struct wpa_authenticator *wpa_auth, const u8 *addr,
|
||||
const u8 *data, size_t data_len, int encrypt)
|
||||
{
|
||||
void *buffer = os_malloc(data_len + sizeof(struct l2_ethhdr));
|
||||
struct l2_ethhdr *eth = buffer;
|
||||
|
||||
if (!buffer){
|
||||
wpa_printf( MSG_DEBUG, "send_eapol, buffer=%p\n", buffer);
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy(eth->h_dest, addr, ETH_ALEN);
|
||||
memcpy(eth->h_source, wpa_auth->addr, ETH_ALEN);
|
||||
eth->h_proto = host_to_be16(ETH_P_EAPOL);
|
||||
|
||||
memcpy((char *)buffer + sizeof(struct l2_ethhdr), data, data_len);
|
||||
esp_wifi_internal_tx(1, buffer, sizeof(struct l2_ethhdr) + data_len);
|
||||
os_free(buffer);
|
||||
return 0;
|
||||
return hostapd_send_eapol(wpa_auth->addr, addr, data, data_len);
|
||||
}
|
||||
|
||||
int wpa_auth_for_each_sta(struct wpa_authenticator *wpa_auth,
|
||||
@@ -2406,11 +2393,12 @@ bool wpa_ap_join(void** sm, uint8_t *bssid, uint8_t *wpa_ie, uint8_t wpa_ie_len,
|
||||
|
||||
bool wpa_ap_remove(void* sm)
|
||||
{
|
||||
struct wpa_state_machine *wpa_sm;
|
||||
if (!sm) return false;
|
||||
struct hostapd_data *hapd = hostapd_get_hapd_data();
|
||||
if (!sm || !hapd) {
|
||||
return false;
|
||||
}
|
||||
|
||||
wpa_sm = (struct wpa_state_machine*)sm;
|
||||
wpa_auth_sta_deinit(wpa_sm);
|
||||
ap_free_sta(hapd, sm);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
586
components/wpa_supplicant/src/ap/wps_hostapd.c
Normal file
586
components/wpa_supplicant/src/ap/wps_hostapd.c
Normal file
@@ -0,0 +1,586 @@
|
||||
/*
|
||||
* hostapd / WPS integration
|
||||
* Copyright (c) 2008-2016, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#include "utils/includes.h"
|
||||
|
||||
#include "utils/common.h"
|
||||
#include "utils/eloop.h"
|
||||
#include "utils/uuid.h"
|
||||
#include "common/wpa_ctrl.h"
|
||||
#include "common/ieee802_11_defs.h"
|
||||
#include "common/ieee802_11_common.h"
|
||||
#include "wps/wps.h"
|
||||
#include "wps/wps_defs.h"
|
||||
#include "wps/wps_dev_attr.h"
|
||||
#include "wps/wps_attr_parse.h"
|
||||
#include "hostapd.h"
|
||||
#include "ap_config.h"
|
||||
#include "wpa_auth.h"
|
||||
#include "wpa_auth_i.h"
|
||||
#include "sta_info.h"
|
||||
#include "wps/wps_i.h"
|
||||
#include "wps_hostapd.h"
|
||||
#include "eap_server/eap_methods.h"
|
||||
#include "ieee802_1x.h"
|
||||
#include "esp_wps_i.h"
|
||||
|
||||
static void hostapd_wps_ap_pin_timeout(void *eloop_data, void *user_ctx);
|
||||
|
||||
static int hostapd_wps_set_ie_cb(void *ctx, struct wpabuf *beacon_ie,
|
||||
struct wpabuf *probe_resp_ie)
|
||||
{
|
||||
int ret;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "WPS: Updating beacon IEs(%d) to driver", beacon_ie->used);
|
||||
ret = esp_wifi_set_appie_internal(WIFI_APPIE_RAM_BEACON,
|
||||
(uint8_t *)wpabuf_head(beacon_ie), beacon_ie->used, 0);
|
||||
if (ret != ESP_OK) {
|
||||
wpa_printf(MSG_ERROR, "WPS: Failed to update beacon IEs");
|
||||
goto cleanup;
|
||||
}
|
||||
wpa_printf(MSG_DEBUG, "WPS: Updating probe IEs(%d) to driver", probe_resp_ie->used);
|
||||
ret = esp_wifi_set_appie_internal(WIFI_APPIE_RAM_PROBE_RSP,
|
||||
(uint8_t *)wpabuf_head(probe_resp_ie), probe_resp_ie->used, 0);
|
||||
|
||||
cleanup:
|
||||
wpabuf_free(beacon_ie);
|
||||
wpabuf_free(probe_resp_ie);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct wps_stop_reg_data {
|
||||
struct hostapd_data *current_hapd;
|
||||
const u8 *uuid_e;
|
||||
const u8 *dev_pw;
|
||||
size_t dev_pw_len;
|
||||
};
|
||||
|
||||
static int wps_stop_registrar(struct hostapd_data *hapd, void *ctx)
|
||||
{
|
||||
struct wps_stop_reg_data *data = ctx;
|
||||
if (hapd != data->current_hapd && hapd->wps != NULL)
|
||||
wps_registrar_complete(hapd->wps->registrar, data->uuid_e,
|
||||
data->dev_pw, data->dev_pw_len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void hostapd_wps_eap_completed(struct hostapd_data *hapd)
|
||||
{
|
||||
}
|
||||
|
||||
static void hostapd_wps_reg_success_cb(void *ctx, const u8 *mac_addr,
|
||||
const u8 *uuid_e, const u8 *dev_pw,
|
||||
size_t dev_pw_len)
|
||||
{
|
||||
struct hostapd_data *hapd = ctx;
|
||||
char uuid[40];
|
||||
struct wps_stop_reg_data data;
|
||||
if (uuid_bin2str(uuid_e, uuid, sizeof(uuid)))
|
||||
return;
|
||||
wpa_msg(hapd->msg_ctx, MSG_INFO, WPS_EVENT_REG_SUCCESS MACSTR " %s",
|
||||
MAC2STR(mac_addr), uuid);
|
||||
data.current_hapd = hapd;
|
||||
data.uuid_e = uuid_e;
|
||||
data.dev_pw = dev_pw;
|
||||
data.dev_pw_len = dev_pw_len;
|
||||
wps_stop_registrar(hapd, &data);
|
||||
wps_set_status(WPS_STATUS_DISABLE);
|
||||
|
||||
/* TODO add callback event for freeRTOS */
|
||||
}
|
||||
|
||||
|
||||
static void hostapd_wps_reenable_ap_pin(void *eloop_data, void *user_ctx)
|
||||
{
|
||||
struct hostapd_data *hapd = eloop_data;
|
||||
|
||||
if (hapd->conf->ap_setup_locked)
|
||||
return;
|
||||
if (hapd->ap_pin_failures_consecutive >= 10)
|
||||
return;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "WPS: Re-enable AP PIN");
|
||||
wpa_msg(hapd->msg_ctx, MSG_INFO, WPS_EVENT_AP_SETUP_UNLOCKED);
|
||||
hapd->wps->ap_setup_locked = 0;
|
||||
wps_registrar_update_ie(hapd->wps->registrar);
|
||||
}
|
||||
|
||||
|
||||
static int wps_pwd_auth_fail(struct hostapd_data *hapd, void *ctx)
|
||||
{
|
||||
struct wps_event_pwd_auth_fail *data = ctx;
|
||||
|
||||
if (!data->enrollee || hapd->conf->ap_pin == NULL || hapd->wps == NULL)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Registrar failed to prove its knowledge of the AP PIN. Lock AP setup
|
||||
* for some time if this happens multiple times to slow down brute
|
||||
* force attacks.
|
||||
*/
|
||||
hapd->ap_pin_failures++;
|
||||
hapd->ap_pin_failures_consecutive++;
|
||||
wpa_printf(MSG_DEBUG, "WPS: AP PIN authentication failure number %u "
|
||||
"(%u consecutive)",
|
||||
hapd->ap_pin_failures, hapd->ap_pin_failures_consecutive);
|
||||
if (hapd->ap_pin_failures < 3)
|
||||
return 0;
|
||||
|
||||
wpa_msg(hapd->msg_ctx, MSG_INFO, WPS_EVENT_AP_SETUP_LOCKED);
|
||||
hapd->wps->ap_setup_locked = 1;
|
||||
|
||||
wps_registrar_update_ie(hapd->wps->registrar);
|
||||
|
||||
if (!hapd->conf->ap_setup_locked &&
|
||||
hapd->ap_pin_failures_consecutive >= 10) {
|
||||
/*
|
||||
* In indefinite lockdown - disable automatic AP PIN
|
||||
* reenablement.
|
||||
*/
|
||||
eloop_cancel_timeout(hostapd_wps_reenable_ap_pin, hapd, NULL);
|
||||
wpa_printf(MSG_DEBUG, "WPS: AP PIN disabled indefinitely");
|
||||
} else if (!hapd->conf->ap_setup_locked) {
|
||||
if (hapd->ap_pin_lockout_time == 0)
|
||||
hapd->ap_pin_lockout_time = 60;
|
||||
else if (hapd->ap_pin_lockout_time < 365 * 24 * 60 * 60 &&
|
||||
(hapd->ap_pin_failures % 3) == 0)
|
||||
hapd->ap_pin_lockout_time *= 2;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "WPS: Disable AP PIN for %u seconds",
|
||||
hapd->ap_pin_lockout_time);
|
||||
eloop_cancel_timeout(hostapd_wps_reenable_ap_pin, hapd, NULL);
|
||||
eloop_register_timeout(hapd->ap_pin_lockout_time, 0,
|
||||
hostapd_wps_reenable_ap_pin, hapd,
|
||||
NULL);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void hostapd_pwd_auth_fail(struct hostapd_data *hapd,
|
||||
struct wps_event_pwd_auth_fail *data)
|
||||
{
|
||||
/* Update WPS Status - Authentication Failure */
|
||||
wpa_printf(MSG_DEBUG, "WPS: Authentication failure update");
|
||||
hapd->wps_stats.status = WPS_FAILURE_STATUS;
|
||||
os_memcpy(hapd->wps_stats.peer_addr, data->peer_macaddr, ETH_ALEN);
|
||||
|
||||
wps_pwd_auth_fail(hapd, data);
|
||||
}
|
||||
|
||||
|
||||
static int wps_ap_pin_success(struct hostapd_data *hapd, void *ctx)
|
||||
{
|
||||
if (hapd->conf->ap_pin == NULL || hapd->wps == NULL)
|
||||
return 0;
|
||||
|
||||
if (hapd->ap_pin_failures_consecutive == 0)
|
||||
return 0;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "WPS: Clear consecutive AP PIN failure counter "
|
||||
"- total validation failures %u (%u consecutive)",
|
||||
hapd->ap_pin_failures, hapd->ap_pin_failures_consecutive);
|
||||
hapd->ap_pin_failures_consecutive = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void hostapd_wps_ap_pin_success(struct hostapd_data *hapd)
|
||||
{
|
||||
wps_ap_pin_success(hapd, NULL);
|
||||
}
|
||||
|
||||
|
||||
static void hostapd_wps_event_pbc_overlap(struct hostapd_data *hapd)
|
||||
{
|
||||
/* Update WPS Status - PBC Overlap */
|
||||
hapd->wps_stats.pbc_status = WPS_PBC_STATUS_OVERLAP;
|
||||
}
|
||||
|
||||
|
||||
static void hostapd_wps_event_pbc_timeout(struct hostapd_data *hapd)
|
||||
{
|
||||
/* Update WPS PBC Status:PBC Timeout */
|
||||
hapd->wps_stats.pbc_status = WPS_PBC_STATUS_TIMEOUT;
|
||||
}
|
||||
|
||||
|
||||
static void hostapd_wps_event_pbc_active(struct hostapd_data *hapd)
|
||||
{
|
||||
/* Update WPS PBC status - Active */
|
||||
hapd->wps_stats.pbc_status = WPS_PBC_STATUS_ACTIVE;
|
||||
}
|
||||
|
||||
|
||||
static void hostapd_wps_event_pbc_disable(struct hostapd_data *hapd)
|
||||
{
|
||||
/* Update WPS PBC status - Active */
|
||||
hapd->wps_stats.pbc_status = WPS_PBC_STATUS_DISABLE;
|
||||
}
|
||||
|
||||
|
||||
static void hostapd_wps_event_success(struct hostapd_data *hapd,
|
||||
struct wps_event_success *success)
|
||||
{
|
||||
/* Update WPS status - Success */
|
||||
hapd->wps_stats.pbc_status = WPS_PBC_STATUS_DISABLE;
|
||||
hapd->wps_stats.status = WPS_SUCCESS_STATUS;
|
||||
os_memcpy(hapd->wps_stats.peer_addr, success->peer_macaddr, ETH_ALEN);
|
||||
}
|
||||
|
||||
|
||||
static void hostapd_wps_event_fail(struct hostapd_data *hapd,
|
||||
struct wps_event_fail *fail)
|
||||
{
|
||||
/* Update WPS status - Failure */
|
||||
hapd->wps_stats.status = WPS_FAILURE_STATUS;
|
||||
os_memcpy(hapd->wps_stats.peer_addr, fail->peer_macaddr, ETH_ALEN);
|
||||
|
||||
if (fail->error_indication > 0 &&
|
||||
fail->error_indication < NUM_WPS_EI_VALUES) {
|
||||
wpa_msg(hapd->msg_ctx, MSG_INFO,
|
||||
WPS_EVENT_FAIL "msg=%d config_error=%d reason=%d (%s)",
|
||||
fail->msg, fail->config_error, fail->error_indication,
|
||||
wps_ei_str(fail->error_indication));
|
||||
} else {
|
||||
wpa_msg(hapd->msg_ctx, MSG_INFO,
|
||||
WPS_EVENT_FAIL "msg=%d config_error=%d",
|
||||
fail->msg, fail->config_error);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void hostapd_wps_event_cb(void *ctx, enum wps_event event,
|
||||
union wps_event_data *data)
|
||||
{
|
||||
struct hostapd_data *hapd = ctx;
|
||||
|
||||
switch (event) {
|
||||
case WPS_EV_M2D:
|
||||
wpa_msg(hapd->msg_ctx, MSG_INFO, WPS_EVENT_M2D);
|
||||
break;
|
||||
case WPS_EV_FAIL:
|
||||
hostapd_wps_event_fail(hapd, &data->fail);
|
||||
break;
|
||||
case WPS_EV_SUCCESS:
|
||||
hostapd_wps_event_success(hapd, &data->success);
|
||||
wpa_msg(hapd->msg_ctx, MSG_INFO, WPS_EVENT_SUCCESS);
|
||||
break;
|
||||
case WPS_EV_PWD_AUTH_FAIL:
|
||||
hostapd_pwd_auth_fail(hapd, &data->pwd_auth_fail);
|
||||
break;
|
||||
case WPS_EV_PBC_OVERLAP:
|
||||
hostapd_wps_event_pbc_overlap(hapd);
|
||||
wpa_msg(hapd->msg_ctx, MSG_INFO, WPS_EVENT_OVERLAP);
|
||||
break;
|
||||
case WPS_EV_PBC_TIMEOUT:
|
||||
hostapd_wps_event_pbc_timeout(hapd);
|
||||
wpa_msg(hapd->msg_ctx, MSG_INFO, WPS_EVENT_TIMEOUT);
|
||||
break;
|
||||
case WPS_EV_PBC_ACTIVE:
|
||||
hostapd_wps_event_pbc_active(hapd);
|
||||
wpa_msg(hapd->msg_ctx, MSG_INFO, WPS_EVENT_ACTIVE);
|
||||
break;
|
||||
case WPS_EV_PBC_DISABLE:
|
||||
hostapd_wps_event_pbc_disable(hapd);
|
||||
wpa_msg(hapd->msg_ctx, MSG_INFO, WPS_EVENT_DISABLE);
|
||||
break;
|
||||
case WPS_EV_ER_AP_ADD:
|
||||
break;
|
||||
case WPS_EV_ER_AP_REMOVE:
|
||||
break;
|
||||
case WPS_EV_ER_ENROLLEE_ADD:
|
||||
break;
|
||||
case WPS_EV_ER_ENROLLEE_REMOVE:
|
||||
break;
|
||||
case WPS_EV_ER_AP_SETTINGS:
|
||||
break;
|
||||
case WPS_EV_ER_SET_SELECTED_REGISTRAR:
|
||||
break;
|
||||
case WPS_EV_AP_PIN_SUCCESS:
|
||||
hostapd_wps_ap_pin_success(hapd);
|
||||
break;
|
||||
}
|
||||
if (hapd->wps_event_cb)
|
||||
hapd->wps_event_cb(hapd, event, data);
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_wps_rf_band_cb(void *ctx)
|
||||
{
|
||||
return WPS_RF_24GHZ;
|
||||
}
|
||||
|
||||
|
||||
static void hostapd_wps_clear_ies(struct hostapd_data *hapd, int deinit_only)
|
||||
{
|
||||
esp_wifi_unset_appie_internal(WIFI_APPIE_RAM_BEACON);
|
||||
esp_wifi_unset_appie_internal(WIFI_APPIE_RAM_PROBE_RSP);
|
||||
}
|
||||
|
||||
static void hostapd_free_wps(struct wps_context *wps)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MAX_WPS_VENDOR_EXTENSIONS; i++)
|
||||
wpabuf_free(wps->dev.vendor_ext[i]);
|
||||
wps_device_data_free(&wps->dev);
|
||||
os_free(wps->network_key);
|
||||
wpabuf_free(wps->dh_pubkey);
|
||||
wpabuf_free(wps->dh_privkey);
|
||||
os_free(wps);
|
||||
}
|
||||
|
||||
int hostapd_init_wps(struct hostapd_data *hapd, struct wps_data *wps_data, struct wps_context *wps)
|
||||
{
|
||||
struct wps_registrar_config cfg;
|
||||
|
||||
wps->event_cb = hostapd_wps_event_cb;
|
||||
wps->rf_band_cb = hostapd_wps_rf_band_cb;
|
||||
wps->cb_ctx = hapd;
|
||||
|
||||
wps->wps_state = WPS_STATE_CONFIGURED;
|
||||
wps->ap_setup_locked = 0;
|
||||
wps->ap = 1;
|
||||
|
||||
/* build credentials to be given */
|
||||
hostapd_wps_config_ap(hapd, wps_data);
|
||||
|
||||
os_memset(&cfg, 0, sizeof(cfg));
|
||||
cfg.set_ie_cb = hostapd_wps_set_ie_cb;
|
||||
cfg.reg_success_cb = hostapd_wps_reg_success_cb;
|
||||
cfg.cb_ctx = hapd;
|
||||
cfg.disable_auto_conf = 1;
|
||||
|
||||
wps->registrar = wps_registrar_init(wps, &cfg);
|
||||
if (wps->registrar == NULL) {
|
||||
wpa_printf(MSG_ERROR, "Failed to initialize WPS Registrar");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
hapd->wps = wps;
|
||||
|
||||
eap_server_identity_register();
|
||||
if (eap_server_wsc_register() < 0) {
|
||||
wpa_printf(MSG_ERROR, "Failed to register for wsc server");
|
||||
}
|
||||
if (ieee802_1x_init(hapd) < 0) {
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
hostapd_free_wps(wps);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
void hostapd_deinit_wps(struct hostapd_data *hapd)
|
||||
{
|
||||
eloop_cancel_timeout(hostapd_wps_reenable_ap_pin, hapd, NULL);
|
||||
eloop_cancel_timeout(hostapd_wps_ap_pin_timeout, hapd, NULL);
|
||||
if (hapd->wps == NULL) {
|
||||
hostapd_wps_clear_ies(hapd, 1);
|
||||
return;
|
||||
}
|
||||
wps_registrar_deinit(hapd->wps->registrar);
|
||||
hostapd_free_wps(hapd->wps);
|
||||
hapd->wps = NULL;
|
||||
hostapd_wps_clear_ies(hapd, 1);
|
||||
}
|
||||
|
||||
|
||||
void hostapd_update_wps(struct hostapd_data *hapd)
|
||||
{
|
||||
struct wps_context *wps = hapd->wps;
|
||||
struct hostapd_bss_config *conf = hapd->conf;
|
||||
|
||||
if (!wps)
|
||||
return;
|
||||
|
||||
os_memcpy(wps->ssid, conf->ssid.ssid, conf->ssid.ssid_len);
|
||||
wps->ssid_len = conf->ssid.ssid_len;
|
||||
|
||||
/* Clear WPS settings, then fill them again */
|
||||
hostapd_wps_config_ap(hapd, NULL);
|
||||
|
||||
wps_registrar_update_ie(wps->registrar);
|
||||
}
|
||||
|
||||
int hostapd_wps_add_pin(struct hostapd_data *hapd, const u8 *pin)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (hapd->wps == NULL)
|
||||
return 0;
|
||||
ret = wps_registrar_add_pin(hapd->wps->registrar, NULL,
|
||||
NULL, pin, 8, 120);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int hostapd_wps_button_pushed(struct hostapd_data *hapd,
|
||||
const u8 *p2p_dev_addr)
|
||||
{
|
||||
if (hapd->wps) {
|
||||
return wps_registrar_button_pushed(hapd->wps->registrar,
|
||||
p2p_dev_addr);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int wps_cancel(struct hostapd_data *hapd)
|
||||
{
|
||||
if (hapd->wps) {
|
||||
wps_registrar_wps_cancel(hapd->wps->registrar);
|
||||
wpa_msg(hapd->msg_ctx, MSG_INFO, WPS_EVENT_CANCEL);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int hostapd_wps_cancel(struct hostapd_data *hapd)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = wps_cancel(hapd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static void hostapd_wps_ap_pin_timeout(void *eloop_data, void *user_ctx)
|
||||
{
|
||||
struct hostapd_data *hapd = eloop_data;
|
||||
wpa_printf(MSG_DEBUG, "WPS: AP PIN timed out");
|
||||
hostapd_wps_ap_pin_disable(hapd);
|
||||
wpa_msg(hapd->msg_ctx, MSG_INFO, WPS_EVENT_AP_PIN_DISABLED);
|
||||
}
|
||||
|
||||
|
||||
static void hostapd_wps_ap_pin_enable(struct hostapd_data *hapd, int timeout)
|
||||
{
|
||||
wpa_printf(MSG_DEBUG, "WPS: Enabling AP PIN (timeout=%d)", timeout);
|
||||
hapd->ap_pin_failures = 0;
|
||||
hapd->ap_pin_failures_consecutive = 0;
|
||||
hapd->conf->ap_setup_locked = 0;
|
||||
if (hapd->wps->ap_setup_locked) {
|
||||
wpa_msg(hapd->msg_ctx, MSG_INFO, WPS_EVENT_AP_SETUP_UNLOCKED);
|
||||
hapd->wps->ap_setup_locked = 0;
|
||||
wps_registrar_update_ie(hapd->wps->registrar);
|
||||
}
|
||||
eloop_cancel_timeout(hostapd_wps_ap_pin_timeout, hapd, NULL);
|
||||
if (timeout > 0)
|
||||
eloop_register_timeout(timeout, 0,
|
||||
hostapd_wps_ap_pin_timeout, hapd, NULL);
|
||||
}
|
||||
|
||||
static int wps_ap_pin_disable(struct hostapd_data *hapd)
|
||||
{
|
||||
os_free(hapd->conf->ap_pin);
|
||||
hapd->conf->ap_pin = NULL;
|
||||
eloop_cancel_timeout(hostapd_wps_ap_pin_timeout, hapd, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void hostapd_wps_ap_pin_disable(struct hostapd_data *hapd)
|
||||
{
|
||||
wpa_printf(MSG_DEBUG, "WPS: Disabling AP PIN");
|
||||
wps_ap_pin_disable(hapd);
|
||||
}
|
||||
|
||||
|
||||
struct wps_ap_pin_data {
|
||||
char pin_txt[9];
|
||||
int timeout;
|
||||
};
|
||||
|
||||
|
||||
static int wps_ap_pin_set(struct hostapd_data *hapd, void *ctx)
|
||||
{
|
||||
struct wps_ap_pin_data *data = ctx;
|
||||
|
||||
if (!hapd->wps)
|
||||
return 0;
|
||||
|
||||
os_free(hapd->conf->ap_pin);
|
||||
hapd->conf->ap_pin = os_strdup(data->pin_txt);
|
||||
hostapd_wps_ap_pin_enable(hapd, data->timeout);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
const char * hostapd_wps_ap_pin_random(struct hostapd_data *hapd, int timeout)
|
||||
{
|
||||
unsigned int pin;
|
||||
struct wps_ap_pin_data data;
|
||||
|
||||
if (wps_generate_pin(&pin) < 0)
|
||||
return NULL;
|
||||
os_snprintf(data.pin_txt, sizeof(data.pin_txt), "%08u", pin);
|
||||
data.timeout = timeout;
|
||||
wps_ap_pin_set(hapd, &data);
|
||||
return hapd->conf->ap_pin;
|
||||
}
|
||||
|
||||
const char * hostapd_wps_ap_pin_get(struct hostapd_data *hapd)
|
||||
{
|
||||
return hapd->conf->ap_pin;
|
||||
}
|
||||
|
||||
|
||||
int hostapd_wps_ap_pin_set(struct hostapd_data *hapd, const char *pin,
|
||||
int timeout)
|
||||
{
|
||||
struct wps_ap_pin_data data;
|
||||
int ret;
|
||||
|
||||
ret = os_snprintf(data.pin_txt, sizeof(data.pin_txt), "%s", pin);
|
||||
if (os_snprintf_error(sizeof(data.pin_txt), ret))
|
||||
return -1;
|
||||
data.timeout = timeout;
|
||||
return wps_ap_pin_set(hapd, &data);
|
||||
}
|
||||
|
||||
|
||||
int hostapd_wps_config_ap(struct hostapd_data *hapd, struct wps_data *wps_data)
|
||||
{
|
||||
struct wps_credential cred = {0};
|
||||
|
||||
os_memcpy(cred.ssid, hapd->conf->ssid.ssid, hapd->conf->ssid.ssid_len);
|
||||
cred.ssid_len = hapd->conf->ssid.ssid_len;
|
||||
cred.encr_type = WPS_ENCR_NONE;
|
||||
cred.auth_type = WPS_AUTH_OPEN;
|
||||
|
||||
if (hapd->wpa_auth->conf.wpa == WPA_PROTO_WPA) {
|
||||
cred.auth_type = WPS_AUTH_WPAPSK;
|
||||
cred.encr_type = WPS_ENCR_TKIP;
|
||||
} else if (hapd->wpa_auth->conf.wpa == WPA_PROTO_RSN) {
|
||||
cred.auth_type = WPS_AUTH_WPA2PSK;
|
||||
cred.encr_type = WPS_ENCR_AES;
|
||||
} else if (hapd->wpa_auth->conf.wpa == (WPA_PROTO_RSN | WPA_PROTO_WPA)) {
|
||||
cred.auth_type = WPS_AUTH_WPA2PSK | WPS_AUTH_WPAPSK;
|
||||
cred.encr_type = WPS_ENCR_AES;
|
||||
}
|
||||
|
||||
if (hapd->conf->ssid.wpa_passphrase) {
|
||||
cred.key_len = os_strlen(hapd->conf->ssid.wpa_passphrase);
|
||||
memcpy(cred.key, hapd->conf->ssid.wpa_passphrase, cred.key_len);
|
||||
}
|
||||
wps_data->use_cred = os_malloc(sizeof(struct wps_credential));
|
||||
if (!wps_data->use_cred) {
|
||||
wpa_printf(MSG_ERROR, "WPS: Disabling AP PIN");
|
||||
return -1;
|
||||
}
|
||||
os_memcpy(wps_data->use_cred, &cred, sizeof(struct wps_credential));
|
||||
return 0;
|
||||
}
|
@@ -11,14 +11,12 @@
|
||||
|
||||
#ifdef CONFIG_WPS
|
||||
|
||||
int hostapd_init_wps(struct hostapd_data *hapd,
|
||||
struct hostapd_bss_config *conf);
|
||||
int hostapd_init_wps(struct hostapd_data *hapd, struct wps_data *wps_data, struct wps_context *wps);
|
||||
int hostapd_init_wps_complete(struct hostapd_data *hapd);
|
||||
void hostapd_deinit_wps(struct hostapd_data *hapd);
|
||||
void hostapd_update_wps(struct hostapd_data *hapd);
|
||||
void hostapd_wps_eap_completed(struct hostapd_data *hapd);
|
||||
int hostapd_wps_add_pin(struct hostapd_data *hapd, const u8 *addr,
|
||||
const char *uuid, const char *pin, int timeout);
|
||||
int hostapd_wps_add_pin(struct hostapd_data *hapd, const u8 *pin);
|
||||
int hostapd_wps_button_pushed(struct hostapd_data *hapd,
|
||||
const u8 *p2p_dev_addr);
|
||||
int hostapd_wps_cancel(struct hostapd_data *hapd);
|
||||
@@ -30,24 +28,12 @@ const char * hostapd_wps_ap_pin_get(struct hostapd_data *hapd);
|
||||
int hostapd_wps_ap_pin_set(struct hostapd_data *hapd, const char *pin,
|
||||
int timeout);
|
||||
void hostapd_wps_update_ie(struct hostapd_data *hapd);
|
||||
int hostapd_wps_config_ap(struct hostapd_data *hapd, const char *ssid,
|
||||
const char *auth, const char *encr, const char *key);
|
||||
int hostapd_wps_config_ap(struct hostapd_data *hapd, struct wps_data *wps_data);
|
||||
int hostapd_wps_nfc_tag_read(struct hostapd_data *hapd,
|
||||
const struct wpabuf *data);
|
||||
struct wpabuf * hostapd_wps_nfc_config_token(struct hostapd_data *hapd,
|
||||
int ndef);
|
||||
struct wpabuf * hostapd_wps_nfc_hs_cr(struct hostapd_data *hapd, int ndef);
|
||||
int hostapd_wps_nfc_report_handover(struct hostapd_data *hapd,
|
||||
const struct wpabuf *req,
|
||||
const struct wpabuf *sel);
|
||||
struct wpabuf * hostapd_wps_nfc_token_gen(struct hostapd_data *hapd, int ndef);
|
||||
int hostapd_wps_nfc_token_enable(struct hostapd_data *hapd);
|
||||
void hostapd_wps_nfc_token_disable(struct hostapd_data *hapd);
|
||||
|
||||
#else /* CONFIG_WPS */
|
||||
|
||||
static inline int hostapd_init_wps(struct hostapd_data *hapd,
|
||||
struct hostapd_bss_config *conf)
|
||||
static inline int hostapd_init_wps(struct hostapd_data *hapd, struct wps_data *wps_data, struct wps_context *wps)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
Reference in New Issue
Block a user