forked from espressif/esp-idf
Merge branch 'feature/wps_registrar_support' into 'master'
wpa_supplicant: wps registrar support See merge request espressif/esp-idf!17659
This commit is contained in:
@@ -4,6 +4,7 @@ set(srcs "port/os_xtensa.c"
|
||||
"src/ap/ieee802_1x.c"
|
||||
"src/ap/wpa_auth.c"
|
||||
"src/ap/wpa_auth_ie.c"
|
||||
"src/ap/sta_info.c"
|
||||
"src/common/sae.c"
|
||||
"src/common/wpa_common.c"
|
||||
"src/utils/bitfield.c"
|
||||
@@ -24,6 +25,7 @@ set(srcs "port/os_xtensa.c"
|
||||
"src/crypto/md4-internal.c"
|
||||
"src/crypto/sha1-tprf.c"
|
||||
"src/eap_common/eap_wsc_common.c"
|
||||
"src/common/ieee802_11_common.c"
|
||||
"src/eap_peer/chap.c"
|
||||
"src/eap_peer/eap.c"
|
||||
"src/eap_peer/eap_common.c"
|
||||
@@ -54,7 +56,6 @@ set(srcs "port/os_xtensa.c"
|
||||
"src/wps/wps_common.c"
|
||||
"src/wps/wps_dev_attr.c"
|
||||
"src/wps/wps_enrollee.c")
|
||||
# "src/wps/wps_registrar.c")
|
||||
|
||||
set(esp_srcs "esp_supplicant/src/esp_wpa2.c"
|
||||
"esp_supplicant/src/esp_wpa_main.c"
|
||||
@@ -176,8 +177,23 @@ else()
|
||||
set(dpp_src "")
|
||||
endif()
|
||||
|
||||
idf_component_register(SRCS "${srcs}" ${esp_srcs} "${tls_src}" "${roaming_src}"
|
||||
"${crypto_src}" "${mbo_src}" "${dpp_src}"
|
||||
if(CONFIG_WPA_WPS_SOFTAP_REGISTRAR)
|
||||
set(wps_registrar_src
|
||||
"src/ap/wps_hostapd.c"
|
||||
"src/eap_server/eap_server.c"
|
||||
"src/eap_server/eap_server_methods.c"
|
||||
"src/eap_server/eap_server_wsc.c"
|
||||
"src/ap/eap_user_db.c"
|
||||
"src/eapol_auth/eapol_auth_sm.c"
|
||||
"src/eap_server/eap_server_identity.c"
|
||||
"esp_supplicant/src/esp_hostpad_wps.c"
|
||||
"src/wps/wps_registrar.c")
|
||||
else()
|
||||
set(wps_registrar_src "")
|
||||
endif()
|
||||
|
||||
idf_component_register(SRCS "${srcs}" "${esp_srcs}" "${tls_src}" "${roaming_src}"
|
||||
"${crypto_src}" "${mbo_src}" "${dpp_src}" "${wps_registrar_src}"
|
||||
INCLUDE_DIRS include port/include esp_supplicant/include
|
||||
PRIV_INCLUDE_DIRS src src/utils esp_supplicant/src src/crypto
|
||||
PRIV_REQUIRES mbedtls esp_timer)
|
||||
@@ -193,14 +209,14 @@ target_compile_definitions(${COMPONENT_LIB} PRIVATE
|
||||
EAP_TLS
|
||||
EAP_PEAP
|
||||
USE_WPA2_TASK
|
||||
CONFIG_WPS2
|
||||
CONFIG_WPS_PIN
|
||||
CONFIG_WPS
|
||||
USE_WPS_TASK
|
||||
ESPRESSIF_USE
|
||||
ESP32_WORKAROUND
|
||||
CONFIG_ECC
|
||||
CONFIG_IEEE80211W
|
||||
CONFIG_SHA256
|
||||
CONFIG_NO_RADIUS
|
||||
)
|
||||
|
||||
if(CONFIG_ESP32_WIFI_ENABLE_WPA3_SAE)
|
||||
@@ -242,4 +258,7 @@ if(CONFIG_WPA_MBEDTLS_CRYPTO)
|
||||
else()
|
||||
target_compile_definitions(${COMPONENT_LIB} PRIVATE CONFIG_CRYPTO_INTERNAL)
|
||||
endif()
|
||||
if(CONFIG_WPA_WPS_SOFTAP_REGISTRAR)
|
||||
target_compile_definitions(${COMPONENT_LIB} PRIVATE CONFIG_WPS_REGISTRAR)
|
||||
endif()
|
||||
set_property(TARGET ${COMPONENT_LIB} APPEND PROPERTY LINK_INTERFACE_MULTIPLICITY 3)
|
||||
|
@@ -105,9 +105,16 @@ menu "Supplicant"
|
||||
Select this option to enable WiFi Easy Connect Support.
|
||||
|
||||
config WPA_11R_SUPPORT
|
||||
bool "Enable 802.11R (Fast Transition)"
|
||||
bool "Enable 802.11R (Fast Transition) Support"
|
||||
default n
|
||||
help
|
||||
Select this option to enable WiFi Fast Transition Support.
|
||||
|
||||
config WPA_WPS_SOFTAP_REGISTRAR
|
||||
bool "Add WPS Registrar support in SoftAP mode"
|
||||
depends on ESP_WIFI_SOFTAP_SUPPORT
|
||||
default n
|
||||
help
|
||||
Select this option to enable WPS registrar support in softAP mode.
|
||||
|
||||
endmenu
|
||||
|
@@ -25,13 +25,6 @@ extern "C" {
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** \defgroup WPS_APIs WPS APIs
|
||||
* @brief ESP32 WPS APIs
|
||||
*
|
||||
* WPS can only be used when ESP32 station is enabled.
|
||||
*
|
||||
*/
|
||||
|
||||
/** @addtogroup WPS_APIs
|
||||
* @{
|
||||
*/
|
||||
@@ -59,9 +52,11 @@ typedef struct {
|
||||
char device_name[WPS_MAX_DEVICE_NAME_LEN]; /*!< Device name, null-terminated string. The default device name is used if the string is empty */
|
||||
} wps_factory_information_t;
|
||||
|
||||
#define PIN_LEN 9
|
||||
typedef struct {
|
||||
wps_type_t wps_type;
|
||||
wps_factory_information_t factory_info;
|
||||
char pin[PIN_LEN];
|
||||
} esp_wps_config_t;
|
||||
|
||||
#define WPS_CONFIG_INIT_DEFAULT(type) { \
|
||||
@@ -70,14 +65,15 @@ typedef struct {
|
||||
ESP_COMPILER_DESIGNATED_INIT_AGGREGATE_TYPE_STR(manufacturer, "ESPRESSIF") \
|
||||
ESP_COMPILER_DESIGNATED_INIT_AGGREGATE_TYPE_STR(model_number, "ESP32") \
|
||||
ESP_COMPILER_DESIGNATED_INIT_AGGREGATE_TYPE_STR(model_name, "ESPRESSIF IOT") \
|
||||
ESP_COMPILER_DESIGNATED_INIT_AGGREGATE_TYPE_STR(device_name, "ESP STATION") \
|
||||
} \
|
||||
ESP_COMPILER_DESIGNATED_INIT_AGGREGATE_TYPE_STR(device_name, "ESP DEVICE") \
|
||||
}, \
|
||||
ESP_COMPILER_DESIGNATED_INIT_AGGREGATE_TYPE_STR(pin, "00000000") \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable Wi-Fi WPS function.
|
||||
*
|
||||
* @attention WPS can only be used when ESP32 station is enabled.
|
||||
* @attention WPS can only be used when station is enabled.
|
||||
*
|
||||
* @param wps_type_t wps_type : WPS type, so far only WPS_TYPE_PBC and WPS_TYPE_PIN is supported
|
||||
*
|
||||
@@ -103,7 +99,7 @@ esp_err_t esp_wifi_wps_disable(void);
|
||||
/**
|
||||
* @brief WPS starts to work.
|
||||
*
|
||||
* @attention WPS can only be used when ESP32 station is enabled.
|
||||
* @attention WPS can only be used when station is enabled.
|
||||
*
|
||||
* @param timeout_ms : maximum blocking time before API return.
|
||||
* - 0 : non-blocking
|
||||
@@ -118,6 +114,47 @@ esp_err_t esp_wifi_wps_disable(void);
|
||||
*/
|
||||
esp_err_t esp_wifi_wps_start(int timeout_ms);
|
||||
|
||||
/**
|
||||
* @brief Enable Wi-Fi AP WPS function.
|
||||
*
|
||||
* @attention WPS can only be used when softAP is enabled.
|
||||
*
|
||||
* @param wps_type_t wps_type : WPS type, so far only WPS_TYPE_PBC and WPS_TYPE_PIN is supported
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK : succeed
|
||||
* - ESP_ERR_WIFI_WPS_TYPE : wps type is invalid
|
||||
* - ESP_ERR_WIFI_WPS_MODE : wifi is not in station mode or sniffer mode is on
|
||||
* - ESP_FAIL : wps initialization fails
|
||||
*/
|
||||
esp_err_t esp_wifi_ap_wps_enable(const esp_wps_config_t *config);
|
||||
|
||||
/**
|
||||
* @brief Disable Wi-Fi SoftAP WPS function and release resource it taken.
|
||||
*
|
||||
* @param null
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK : succeed
|
||||
* - ESP_ERR_WIFI_WPS_MODE : wifi is not in station mode or sniffer mode is on
|
||||
*/
|
||||
esp_err_t esp_wifi_ap_wps_disable(void);
|
||||
|
||||
/**
|
||||
* @brief WPS starts to work.
|
||||
*
|
||||
* @attention WPS can only be used when softAP is enabled.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK : succeed
|
||||
* - ESP_ERR_WIFI_WPS_TYPE : wps type is invalid
|
||||
* - ESP_ERR_WIFI_WPS_MODE : wifi is not in station mode or sniffer mode is on
|
||||
* - ESP_ERR_WIFI_WPS_SM : wps state machine is not initialized
|
||||
* - ESP_FAIL : wps initialization fails
|
||||
*/
|
||||
esp_err_t esp_wifi_ap_wps_start(const unsigned char *pin);
|
||||
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
@@ -866,6 +866,7 @@ void esp_set_scan_ie(void) { }
|
||||
void esp_set_assoc_ie(uint8_t *bssid, const u8 *ies, size_t ies_len, bool mdie) { }
|
||||
int esp_supplicant_common_init(struct wpa_funcs *wpa_cb)
|
||||
{
|
||||
wpa_cb->wpa_sta_rx_mgmt = NULL;
|
||||
return 0;
|
||||
}
|
||||
void esp_supplicant_common_deinit(void) { }
|
||||
|
@@ -18,12 +18,18 @@
|
||||
#include "esp_wifi_driver.h"
|
||||
#include "esp_wifi_types.h"
|
||||
|
||||
struct hostapd_data *global_hapd;
|
||||
|
||||
struct hostapd_data *hostapd_get_hapd_data(void)
|
||||
{
|
||||
return global_hapd;
|
||||
}
|
||||
|
||||
void *hostap_init(void)
|
||||
{
|
||||
struct wifi_ssid *ssid = esp_wifi_ap_get_prof_ap_ssid_internal();
|
||||
struct hostapd_data *hapd = NULL;
|
||||
struct wpa_auth_config *auth_conf;
|
||||
u8 mac[6];
|
||||
u16 spp_attrubute = 0;
|
||||
u8 pairwise_cipher;
|
||||
wifi_pmf_config_t pmf_cfg;
|
||||
@@ -40,6 +46,7 @@ void *hostap_init(void)
|
||||
os_free(hapd);
|
||||
return NULL;
|
||||
}
|
||||
hapd->conf->max_num_sta = MAX_STA_COUNT;
|
||||
|
||||
auth_conf = (struct wpa_auth_config *)os_zalloc(sizeof(struct wpa_auth_config));
|
||||
|
||||
@@ -122,11 +129,12 @@ void *hostap_init(void)
|
||||
hapd->conf->ap_max_inactivity = 5 * 60;
|
||||
hostapd_setup_wpa_psk(hapd->conf);
|
||||
|
||||
esp_wifi_get_macaddr_internal(WIFI_IF_AP, mac);
|
||||
esp_wifi_get_macaddr_internal(WIFI_IF_AP, hapd->own_addr);
|
||||
|
||||
hapd->wpa_auth = wpa_init(mac, auth_conf, NULL);
|
||||
hapd->wpa_auth = wpa_init(hapd->own_addr, auth_conf, NULL);
|
||||
esp_wifi_set_appie_internal(WIFI_APPIE_WPA, hapd->wpa_auth->wpa_ie, (uint16_t)hapd->wpa_auth->wpa_ie_len, 0);
|
||||
os_free(auth_conf);
|
||||
global_hapd = hapd;
|
||||
|
||||
return (void *)hapd;
|
||||
}
|
||||
@@ -161,6 +169,7 @@ bool hostap_deinit(void *data)
|
||||
|
||||
os_free(hapd);
|
||||
esp_wifi_unset_appie_internal(WIFI_APPIE_WPA);
|
||||
global_hapd = NULL;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
254
components/wpa_supplicant/esp_supplicant/src/esp_hostpad_wps.c
Normal file
254
components/wpa_supplicant/esp_supplicant/src/esp_hostpad_wps.c
Normal file
@@ -0,0 +1,254 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2019-2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "utils/common.h"
|
||||
|
||||
#include "rsn_supp/wpa.h"
|
||||
#include "common/eapol_common.h"
|
||||
#include "utils/wpa_debug.h"
|
||||
#include "common/ieee802_11_defs.h"
|
||||
#include "wps/wps_i.h"
|
||||
#include "wps/wps_dev_attr.h"
|
||||
#include "eap_peer/eap_defs.h"
|
||||
#include "eap_peer/eap_common.h"
|
||||
#include "esp_wifi_driver.h"
|
||||
#include "esp_event.h"
|
||||
#include "esp_wifi.h"
|
||||
#include "esp_err.h"
|
||||
#include "esp_private/wifi.h"
|
||||
#include "esp_wps.h"
|
||||
#include "esp_wps_i.h"
|
||||
#include "eap_common/eap_wsc_common.h"
|
||||
#include "esp_wpas_glue.h"
|
||||
#include "ap/hostapd.h"
|
||||
#include "ap/ap_config.h"
|
||||
#include "ap/wps_hostapd.h"
|
||||
|
||||
extern struct wps_sm *gWpsSm;
|
||||
extern void *s_wps_api_lock;
|
||||
extern void *s_wps_api_sem;
|
||||
extern bool s_wps_enabled;
|
||||
|
||||
static int wifi_ap_wps_init(void)
|
||||
{
|
||||
struct wps_sm *sm = NULL;
|
||||
uint8_t mac[ETH_ALEN];
|
||||
struct wps_config cfg = {0};
|
||||
|
||||
if (gWpsSm) {
|
||||
goto _out;
|
||||
}
|
||||
|
||||
wpa_printf(MSG_DEBUG, "wifi wps init");
|
||||
|
||||
gWpsSm = os_zalloc(sizeof(struct wps_sm)); /* alloc Wps_sm */
|
||||
if (!gWpsSm) {
|
||||
goto _out;
|
||||
}
|
||||
|
||||
sm = gWpsSm;
|
||||
|
||||
esp_wifi_get_macaddr_internal(WIFI_IF_AP, mac);
|
||||
os_memcpy(sm->ownaddr, mac, ETH_ALEN);
|
||||
|
||||
sm->identity_len = WSC_ID_REGISTRAR_LEN;
|
||||
os_memcpy(sm->identity, WSC_ID_REGISTRAR, sm->identity_len);
|
||||
|
||||
sm->wps_ctx = os_zalloc(sizeof(struct wps_context)); /* alloc wps_ctx */
|
||||
if (!sm->wps_ctx) {
|
||||
goto _err;
|
||||
}
|
||||
|
||||
if (wps_dev_init() != 0) {
|
||||
goto _err;
|
||||
}
|
||||
|
||||
cfg.registrar = 1;
|
||||
cfg.wps = sm->wps_ctx;
|
||||
|
||||
wps_init_cfg_pin(&cfg);
|
||||
os_memcpy(cfg.wps->uuid, sm->uuid, WPS_UUID_LEN);
|
||||
if ((sm->wps = wps_init(&cfg)) == NULL) { /* alloc wps_data */
|
||||
goto _err;
|
||||
}
|
||||
|
||||
hostapd_init_wps(hostapd_get_hapd_data(), sm->wps, sm->wps_ctx);
|
||||
return ESP_OK;
|
||||
|
||||
_err:
|
||||
if (sm->dev) {
|
||||
wps_dev_deinit(sm->dev);
|
||||
sm->dev = NULL;
|
||||
}
|
||||
if (sm->wps_ctx) {
|
||||
os_free(sm->wps_ctx);
|
||||
sm->wps_ctx = NULL;
|
||||
}
|
||||
if (sm->wps) {
|
||||
wps_deinit(sm->wps);
|
||||
sm->wps = NULL;
|
||||
}
|
||||
os_free(gWpsSm);
|
||||
gWpsSm = NULL;
|
||||
return ESP_FAIL;
|
||||
_out:
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
int wifi_ap_wps_deinit(void)
|
||||
{
|
||||
struct wps_sm *sm = gWpsSm;
|
||||
|
||||
hostapd_deinit_wps(hostapd_get_hapd_data());
|
||||
if (gWpsSm == NULL) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
if (sm->dev) {
|
||||
wps_dev_deinit(sm->dev);
|
||||
sm->dev = NULL;
|
||||
}
|
||||
if (sm->wps_ctx) {
|
||||
os_free(sm->wps_ctx);
|
||||
sm->wps_ctx = NULL;
|
||||
}
|
||||
if (sm->wps) {
|
||||
wps_deinit(sm->wps);
|
||||
sm->wps = NULL;
|
||||
}
|
||||
os_free(gWpsSm);
|
||||
gWpsSm = NULL;
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
int wifi_ap_wps_enable_internal(const esp_wps_config_t *config)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "ESP WPS crypto initialize!");
|
||||
if (config->wps_type == WPS_TYPE_DISABLE) {
|
||||
wpa_printf(MSG_ERROR, "wps enable: invalid wps type");
|
||||
return ESP_ERR_WIFI_WPS_TYPE;
|
||||
}
|
||||
|
||||
wpa_printf(MSG_DEBUG, "Set factory information.");
|
||||
ret = wps_set_factory_info(config);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
wpa_printf(MSG_INFO, "wifi_wps_enable\n");
|
||||
|
||||
wps_set_type(config->wps_type);
|
||||
wps_set_status(WPS_STATUS_DISABLE);
|
||||
|
||||
ret = wifi_ap_wps_init();
|
||||
|
||||
if (ret != 0) {
|
||||
wps_set_type(WPS_STATUS_DISABLE);
|
||||
wps_set_status(WPS_STATUS_DISABLE);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
int esp_wifi_ap_wps_enable(const esp_wps_config_t *config)
|
||||
{
|
||||
int ret;
|
||||
wifi_mode_t mode = WIFI_MODE_NULL;
|
||||
|
||||
ret = esp_wifi_get_mode(&mode);
|
||||
if (mode != WIFI_MODE_AP) {
|
||||
return ESP_ERR_WIFI_MODE;
|
||||
}
|
||||
|
||||
API_MUTEX_TAKE();
|
||||
if (s_wps_enabled) {
|
||||
API_MUTEX_GIVE();
|
||||
wpa_printf(MSG_DEBUG, "wps enable: already enabled");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
ret = wifi_ap_wps_enable_internal(config);
|
||||
s_wps_enabled = true;
|
||||
API_MUTEX_GIVE();
|
||||
return ret;
|
||||
}
|
||||
|
||||
int esp_wifi_ap_wps_disable(void)
|
||||
{
|
||||
int ret = 0;
|
||||
wifi_mode_t mode = WIFI_MODE_NULL;
|
||||
|
||||
ret = esp_wifi_get_mode(&mode);
|
||||
if (mode != WIFI_MODE_AP) {
|
||||
return ESP_ERR_WIFI_MODE;
|
||||
}
|
||||
|
||||
API_MUTEX_TAKE();
|
||||
|
||||
if (!s_wps_enabled) {
|
||||
wpa_printf(MSG_DEBUG, "wps disable: already disabled");
|
||||
API_MUTEX_GIVE();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
wpa_printf(MSG_INFO, "wifi_wps_disable");
|
||||
wps_set_status(WPS_STATUS_DISABLE);
|
||||
wps_set_type(WPS_TYPE_DISABLE);
|
||||
|
||||
wifi_ap_wps_deinit();
|
||||
|
||||
if (ESP_OK != ret) {
|
||||
wpa_printf(MSG_ERROR, "wps disable: failed to disable wps, ret=%d", ret);
|
||||
}
|
||||
|
||||
s_wps_enabled = false;
|
||||
API_MUTEX_GIVE();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
int esp_wifi_ap_wps_start(const unsigned char *pin)
|
||||
{
|
||||
wifi_mode_t mode = WIFI_MODE_NULL;
|
||||
|
||||
esp_wifi_get_mode(&mode);
|
||||
if (mode != WIFI_MODE_AP) {
|
||||
wpa_printf(MSG_ERROR, "wps start: mode=%d is not AP", mode);
|
||||
return ESP_ERR_WIFI_MODE;
|
||||
}
|
||||
|
||||
API_MUTEX_TAKE();
|
||||
|
||||
if (!s_wps_enabled) {
|
||||
wpa_printf(MSG_ERROR, "wps start: wps not enabled");
|
||||
API_MUTEX_GIVE();
|
||||
return ESP_ERR_WIFI_WPS_SM;
|
||||
}
|
||||
|
||||
if (wps_get_type() == WPS_TYPE_DISABLE || (wps_get_status() != WPS_STATUS_DISABLE && wps_get_status() != WPS_STATUS_SCANNING)) {
|
||||
API_MUTEX_GIVE();
|
||||
return ESP_ERR_WIFI_WPS_TYPE;
|
||||
}
|
||||
|
||||
if (esp_wifi_get_user_init_flag_internal() == 0) {
|
||||
API_MUTEX_GIVE();
|
||||
return ESP_ERR_WIFI_STATE;
|
||||
}
|
||||
|
||||
/* TODO ideally SoftAP mode should also do a single scan in PBC mode
|
||||
* however softAP scanning is not available at the moment */
|
||||
wps_set_status(WPS_STATUS_PENDING);
|
||||
if (wps_get_type() == WPS_TYPE_PBC) {
|
||||
hostapd_wps_button_pushed(hostapd_get_hapd_data(), NULL);
|
||||
} else if (wps_get_type() == WPS_TYPE_PIN) {
|
||||
hostapd_wps_add_pin(hostapd_get_hapd_data(), pin);
|
||||
}
|
||||
API_MUTEX_GIVE();
|
||||
return ESP_OK;
|
||||
}
|
@@ -11,6 +11,7 @@
|
||||
#include "rsn_supp/wpa_i.h"
|
||||
#include "common/eapol_common.h"
|
||||
#include "common/ieee802_11_defs.h"
|
||||
#include "common/ieee802_11_common.h"
|
||||
#include "rsn_supp/wpa_ie.h"
|
||||
#include "ap/wpa_auth.h"
|
||||
#include "ap/wpa_auth_i.h"
|
||||
@@ -30,6 +31,13 @@
|
||||
#include "esp_wpa2.h"
|
||||
#include "esp_common_i.h"
|
||||
|
||||
#include "esp_wps.h"
|
||||
#include "eap_server/eap.h"
|
||||
#include "eapol_auth/eapol_auth_sm.h"
|
||||
#include "ap/ieee802_1x.h"
|
||||
#include "ap/sta_info.h"
|
||||
#include "wps/wps_defs.h"
|
||||
|
||||
void wpa_install_key(enum wpa_alg alg, u8 *addr, int key_idx, int set_tx,
|
||||
u8 *seq, size_t seq_len, u8 *key, size_t key_len, enum key_flag key_flag)
|
||||
{
|
||||
@@ -134,16 +142,24 @@ uint8_t *wpa_ap_get_wpa_ie(uint8_t *ie_len)
|
||||
return hapd->wpa_auth->wpa_ie;
|
||||
}
|
||||
|
||||
bool wpa_ap_rx_eapol(void *hapd_data, void *sm_data, u8 *data, size_t data_len)
|
||||
bool wpa_ap_rx_eapol(void *hapd_data, void *sm_data, u8 *data, size_t data_len)
|
||||
{
|
||||
struct hostapd_data *hapd = (struct hostapd_data *)hapd_data;
|
||||
struct wpa_state_machine *sm = (struct wpa_state_machine *)sm_data;
|
||||
|
||||
if (!hapd || !sm) {
|
||||
struct sta_info *sta = (struct sta_info *)sm_data;
|
||||
if (!hapd || !sta) {
|
||||
wpa_printf(MSG_DEBUG, "hapd=%p sta=%p", hapd, sta);
|
||||
return false;
|
||||
}
|
||||
#ifdef CONFIG_WPS_REGISTRAR
|
||||
int wps_type = esp_wifi_get_wps_type_internal();
|
||||
|
||||
wpa_receive(hapd->wpa_auth, sm, data, data_len);
|
||||
if ((wps_type == WPS_TYPE_PBC) ||
|
||||
(wps_type == WPS_TYPE_PIN)) {
|
||||
ieee802_1x_receive(hapd, sta->addr, data, data_len);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
wpa_receive(hapd->wpa_auth, sta->wpa_sm, data, data_len);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -226,6 +242,60 @@ static void wpa_sta_disconnected_cb(uint8_t reason_code)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ESP_WIFI_SOFTAP_SUPPORT
|
||||
|
||||
#ifdef CONFIG_WPS_REGISTRAR
|
||||
static int check_n_add_wps_sta(struct hostapd_data *hapd, struct sta_info *sta_info, u8 *ies, u8 ies_len, bool *pmf_enable)
|
||||
{
|
||||
struct wpabuf *wps_ie = ieee802_11_vendor_ie_concat(ies, ies_len, WPS_DEV_OUI_WFA);
|
||||
int wps_type = esp_wifi_get_wps_type_internal();
|
||||
|
||||
/* Condition for this, WPS is running and WPS IEs are part of assoc req */
|
||||
if (!wps_ie || (wps_type == WPS_TYPE_DISABLE)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
sta_info->wps_ie = wps_ie;
|
||||
sta_info->eapol_sm = ieee802_1x_alloc_eapol_sm(hapd, sta_info);
|
||||
|
||||
if (sta_info->eapol_sm) {
|
||||
wpa_printf(MSG_DEBUG, "considering station " MACSTR " for WPS", MAC2STR(sta_info->addr));
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static bool hostap_sta_join(void **sm, u8 *bssid, u8 *wpa_ie, u8 wpa_ie_len, bool *pmf_enable)
|
||||
{
|
||||
struct sta_info *sta_info;
|
||||
struct hostapd_data *hapd = hostapd_get_hapd_data();
|
||||
|
||||
if (!hapd) {
|
||||
return 0;
|
||||
}
|
||||
sta_info = ap_sta_add(hapd, bssid);
|
||||
if (!sta_info) {
|
||||
wpa_printf(MSG_ERROR, "failed to add station " MACSTR, MAC2STR(bssid));
|
||||
return 0;
|
||||
}
|
||||
#ifdef CONFIG_WPS_REGISTRAR
|
||||
if (check_n_add_wps_sta(hapd, sta_info, wpa_ie, wpa_ie_len, pmf_enable)) {
|
||||
*sm = sta_info;
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
if (wpa_ap_join(sm, bssid, wpa_ie, wpa_ie_len, pmf_enable)) {
|
||||
sta_info->wpa_sm = *sm;
|
||||
*sm = sta_info;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
int esp_supplicant_init(void)
|
||||
{
|
||||
int ret = ESP_OK;
|
||||
@@ -244,7 +314,7 @@ int esp_supplicant_init(void)
|
||||
wpa_cb->wpa_sta_in_4way_handshake = wpa_sta_in_4way_handshake;
|
||||
|
||||
#ifdef CONFIG_ESP_WIFI_SOFTAP_SUPPORT
|
||||
wpa_cb->wpa_ap_join = wpa_ap_join;
|
||||
wpa_cb->wpa_ap_join = hostap_sta_join;
|
||||
wpa_cb->wpa_ap_remove = wpa_ap_remove;
|
||||
wpa_cb->wpa_ap_get_wpa_ie = wpa_ap_get_wpa_ie;
|
||||
wpa_cb->wpa_ap_rx_eapol = wpa_ap_rx_eapol;
|
||||
|
@@ -73,6 +73,28 @@ int wpa_ether_send(void *ctx, const u8 *dest, u16 proto,
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
int hostapd_send_eapol(const u8 *source, const u8 *sta_addr,
|
||||
const u8 *data, size_t data_len)
|
||||
{
|
||||
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, sta_addr, ETH_ALEN);
|
||||
memcpy(eth->h_source, source, 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(WIFI_IF_AP, buffer, sizeof(struct l2_ethhdr) + data_len);
|
||||
os_free(buffer);
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
u8 *wpa_sm_alloc_eapol(struct wpa_sm *sm, u8 type,
|
||||
const void *data, u16 data_len,
|
||||
size_t *msg_len, void **data_pos)
|
||||
|
@@ -31,4 +31,6 @@ void wpa_free_eapol(u8 *buffer);
|
||||
int wpa_ether_send(void *ctx, const u8 *dest, u16 proto,
|
||||
const u8 *data, size_t data_len);
|
||||
|
||||
int hostapd_send_eapol(const u8 *source, const u8 *sta_addr,
|
||||
const u8 *data, size_t data_len);
|
||||
#endif /* WPAS_GLUE_H */
|
||||
|
@@ -31,25 +31,12 @@
|
||||
#include "eap_common/eap_wsc_common.h"
|
||||
#include "esp_wpas_glue.h"
|
||||
|
||||
#define API_MUTEX_TAKE() do {\
|
||||
if (!s_wps_api_lock) {\
|
||||
s_wps_api_lock = xSemaphoreCreateRecursiveMutex();\
|
||||
if (!s_wps_api_lock) {\
|
||||
wpa_printf(MSG_ERROR, "wps api lock create failed");\
|
||||
return ESP_ERR_NO_MEM;\
|
||||
}\
|
||||
}\
|
||||
xSemaphoreTakeRecursive(s_wps_api_lock, portMAX_DELAY);\
|
||||
} while(0)
|
||||
|
||||
#define API_MUTEX_GIVE() xSemaphoreGiveRecursive(s_wps_api_lock)
|
||||
#define DATA_MUTEX_TAKE() xSemaphoreTakeRecursive(s_wps_data_lock, portMAX_DELAY)
|
||||
#define DATA_MUTEX_GIVE() xSemaphoreGiveRecursive(s_wps_data_lock)
|
||||
|
||||
#define WPS_ADDR_LEN 6
|
||||
void *s_wps_api_lock = NULL; /* Used in WPS public API only, never be freed */
|
||||
void *s_wps_api_sem = NULL; /* Sync semaphore used between WPS publi API caller task and WPS task */
|
||||
bool s_wps_enabled = false;
|
||||
#ifdef USE_WPS_TASK
|
||||
struct wps_rx_param {
|
||||
u8 sa[WPS_ADDR_LEN];
|
||||
u8 sa[ETH_ALEN];
|
||||
u8 *buf;
|
||||
int len;
|
||||
STAILQ_ENTRY(wps_rx_param) bqentry;
|
||||
@@ -63,11 +50,8 @@ typedef struct {
|
||||
|
||||
static TaskHandle_t s_wps_task_hdl = NULL;
|
||||
static void *s_wps_queue = NULL;
|
||||
static void *s_wps_api_lock = NULL; /* Used in WPS public API only, never be freed */
|
||||
static void *s_wps_api_sem = NULL; /* Sync semaphore used between WPS publi API caller task and WPS task */
|
||||
static void *s_wps_data_lock = NULL;
|
||||
static void *s_wps_task_create_sem = NULL;
|
||||
static bool s_wps_enabled = false;
|
||||
static uint8_t s_wps_sig_cnt[SIG_WPS_NUM] = {0};
|
||||
|
||||
#endif
|
||||
@@ -89,31 +73,6 @@ void wps_add_discard_ap(u8 *bssid);
|
||||
struct wps_sm *gWpsSm = NULL;
|
||||
static wps_factory_information_t *s_factory_info = NULL;
|
||||
|
||||
#ifdef CONFIG_WPS_TESTING
|
||||
int wps_version_number = 0x20;
|
||||
int wps_testing_dummy_cred = 0;
|
||||
#endif /* CONFIG_WPS_TESTING */
|
||||
|
||||
int wps_get_type(void)
|
||||
{
|
||||
return esp_wifi_get_wps_type_internal();
|
||||
}
|
||||
|
||||
int wps_set_type(uint32_t type)
|
||||
{
|
||||
return esp_wifi_set_wps_type_internal(type);
|
||||
}
|
||||
|
||||
int wps_get_status(void)
|
||||
{
|
||||
return esp_wifi_get_wps_status_internal();
|
||||
}
|
||||
|
||||
int wps_set_status(uint32_t status)
|
||||
{
|
||||
return esp_wifi_set_wps_status_internal(status);
|
||||
}
|
||||
|
||||
static void wps_rxq_init(void)
|
||||
{
|
||||
DATA_MUTEX_TAKE();
|
||||
@@ -395,7 +354,7 @@ wps_parse_scan_result(struct wps_scan_ie *scan)
|
||||
}
|
||||
|
||||
if (!scan->rsn && !scan->wpa && (scan->capinfo & WLAN_CAPABILITY_PRIVACY)) {
|
||||
wpa_printf(MSG_INFO, "WEP not suppported in WPS");
|
||||
wpa_printf(MSG_DEBUG, "WEP not suppported in WPS");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -916,7 +875,7 @@ int wps_sm_rx_eapol(u8 *src_addr, u8 *buf, u32 len)
|
||||
}
|
||||
os_memcpy(param->buf, buf, len);
|
||||
param->len = len;
|
||||
os_memcpy(param->sa, src_addr, WPS_ADDR_LEN);
|
||||
os_memcpy(param->sa, src_addr, ETH_ALEN);
|
||||
|
||||
wps_rxq_enqueue(param);
|
||||
return wps_post(SIG_WPS_RX, 0);
|
||||
@@ -1041,7 +1000,7 @@ int wps_sm_rx_eapol_internal(u8 *src_addr, u8 *buf, u32 len)
|
||||
|
||||
tmp = (u8 *)(ehdr + 1) + 1;
|
||||
ret = wps_process_wps_mX_req(tmp, plen - sizeof(*ehdr) - 1, &res);
|
||||
if (ret == 0 && res != WPS_FAILURE && res != WPS_IGNORE && res != WPS_FRAGMENT) {
|
||||
if (ret == 0 && res != WPS_FAILURE && res != WPS_FRAGMENT) {
|
||||
ret = wps_send_wps_mX_rsp(ehdr->identifier);
|
||||
if (ret == 0) {
|
||||
wpa_printf(MSG_DEBUG, "sm->wps->state = %d", sm->wps->state);
|
||||
@@ -1050,9 +1009,6 @@ int wps_sm_rx_eapol_internal(u8 *src_addr, u8 *buf, u32 len)
|
||||
} else if (ret == 0 && res == WPS_FRAGMENT) {
|
||||
wpa_printf(MSG_DEBUG, "wps frag, continue...");
|
||||
ret = ESP_OK;
|
||||
} else if (res == WPS_IGNORE) {
|
||||
wpa_printf(MSG_DEBUG, "IGNORE overlap Mx");
|
||||
ret = ESP_OK; /* IGNORE the overlap */
|
||||
} else {
|
||||
ret = ESP_FAIL;
|
||||
}
|
||||
@@ -1382,12 +1338,32 @@ static int save_credentials_cb(void *ctx, const struct wps_credential *cred)
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
int wps_init_cfg_pin(struct wps_config *cfg)
|
||||
{
|
||||
if (wps_get_type() != WPS_TYPE_PIN) {
|
||||
cfg->pbc = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
cfg->pbc = 0;
|
||||
if (os_strncmp((char *)cfg->pin, "00000000", 8) != 0) {
|
||||
unsigned int spin = 0;
|
||||
cfg->dev_pw_id = DEV_PW_DEFAULT;
|
||||
cfg->pin_len = 8;
|
||||
if (wps_generate_pin(&spin) < 0) {
|
||||
return -1;
|
||||
}
|
||||
os_sprintf((char *)cfg->pin, "%08d", spin);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
wifi_station_wps_init(void)
|
||||
{
|
||||
struct wps_funcs *wps_cb;
|
||||
struct wps_sm *sm = NULL;
|
||||
uint8_t mac[6];
|
||||
struct wps_config cfg = {0};
|
||||
|
||||
if (gWpsSm) {
|
||||
@@ -1403,8 +1379,7 @@ wifi_station_wps_init(void)
|
||||
|
||||
sm = gWpsSm;
|
||||
|
||||
esp_wifi_get_macaddr_internal(WIFI_IF_STA, mac);
|
||||
os_memcpy(sm->ownaddr, mac, ETH_ALEN);
|
||||
esp_wifi_get_macaddr_internal(WIFI_IF_STA, sm->ownaddr);
|
||||
|
||||
sm->identity_len = WSC_ID_ENROLLEE_LEN;
|
||||
os_memcpy(sm->identity, WSC_ID_ENROLLEE, sm->identity_len);
|
||||
@@ -1419,34 +1394,17 @@ wifi_station_wps_init(void)
|
||||
}
|
||||
|
||||
cfg.wps = sm->wps_ctx;
|
||||
if (IS_WPS_REGISTRAR(wps_get_type())) {
|
||||
cfg.registrar = 1;
|
||||
}
|
||||
|
||||
/* TODO add for Registrar */
|
||||
if (wps_get_type() == WPS_TYPE_PIN) {
|
||||
unsigned int spin = 0;
|
||||
cfg.dev_pw_id = DEV_PW_DEFAULT;
|
||||
cfg.pin_len = 8;
|
||||
cfg.pin = os_zalloc(cfg.pin_len + 1);
|
||||
if (!cfg.pin) {
|
||||
goto _err;
|
||||
}
|
||||
if (wps_generate_pin(&spin) < 0) {
|
||||
goto _err;
|
||||
}
|
||||
os_sprintf((char *)cfg.pin, "%08d", spin);
|
||||
} else if (wps_get_type() == WPS_TYPE_PBC) {
|
||||
cfg.pbc = 1;
|
||||
|
||||
if (wps_init_cfg_pin(&cfg) < 0) {
|
||||
goto _err;
|
||||
}
|
||||
|
||||
os_memcpy(cfg.wps->uuid, sm->uuid, WPS_UUID_LEN);
|
||||
if ((sm->wps = wps_init(&cfg)) == NULL) { /* alloc wps_data */
|
||||
goto _err;
|
||||
}
|
||||
|
||||
if (cfg.pin) {
|
||||
os_free((u8 *)cfg.pin);
|
||||
}
|
||||
/* Report PIN */
|
||||
if (wps_get_type() == WPS_TYPE_PIN) {
|
||||
wifi_event_sta_wps_er_pin_t evt;
|
||||
os_memcpy(evt.pin_code, sm->wps->dev_password, 8);
|
||||
@@ -1478,13 +1436,12 @@ wifi_station_wps_init(void)
|
||||
wps_cb = os_malloc(sizeof(struct wps_funcs));
|
||||
if (wps_cb == NULL) {
|
||||
goto _err;
|
||||
} else {
|
||||
wps_cb->wps_parse_scan_result = wps_parse_scan_result;
|
||||
wps_cb->wifi_station_wps_start = wifi_station_wps_start;
|
||||
wps_cb->wps_sm_rx_eapol = wps_sm_rx_eapol;
|
||||
wps_cb->wps_start_pending = wps_start_pending;
|
||||
esp_wifi_set_wps_cb_internal(wps_cb);
|
||||
}
|
||||
wps_cb->wps_parse_scan_result = wps_parse_scan_result;
|
||||
wps_cb->wifi_station_wps_start = wifi_station_wps_start;
|
||||
wps_cb->wps_sm_rx_eapol = wps_sm_rx_eapol;
|
||||
wps_cb->wps_start_pending = wps_start_pending;
|
||||
esp_wifi_set_wps_cb_internal(wps_cb);
|
||||
|
||||
return ESP_OK;
|
||||
|
||||
@@ -1647,6 +1604,11 @@ void wifi_wps_scan(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
static int wps_rf_band_cb(void *ctx)
|
||||
{
|
||||
return WPS_RF_24GHZ;
|
||||
}
|
||||
|
||||
int wifi_station_wps_start(void)
|
||||
{
|
||||
struct wps_sm *sm = wps_sm_get();
|
||||
@@ -1666,7 +1628,7 @@ int wifi_station_wps_start(void)
|
||||
sm->wps->wps->dh_privkey = wpabuf_dup(sm->wps->dh_privkey);
|
||||
sm->wps->wps->dh_ctx = sm->wps->dh_ctx;
|
||||
sm->wps->wps->dh_pubkey = sm->wps->dh_pubkey_e;
|
||||
sm->wps->wps->rf_band_cb = NULL;
|
||||
sm->wps->wps->rf_band_cb = wps_rf_band_cb;
|
||||
wpabuf_clear_free(sm->wps->dh_privkey);
|
||||
sm->wps->dh_privkey = NULL;
|
||||
wifi_wps_scan();
|
||||
@@ -1872,12 +1834,6 @@ int wifi_wps_enable_internal(const esp_wps_config_t *config)
|
||||
return ESP_ERR_WIFI_WPS_TYPE;
|
||||
}
|
||||
|
||||
/* currently , we don't support REGISTRAR */
|
||||
if (IS_WPS_REGISTRAR(config->wps_type)) {
|
||||
wpa_printf(MSG_ERROR, "wps enable: not support registrar");
|
||||
return ESP_ERR_WIFI_WPS_TYPE;
|
||||
}
|
||||
|
||||
wpa_printf(MSG_DEBUG, "Set factory information.");
|
||||
ret = wps_set_factory_info(config);
|
||||
if (ret != 0) {
|
||||
@@ -1974,13 +1930,11 @@ int esp_wifi_wps_start(int timeout_ms)
|
||||
}
|
||||
|
||||
wpa_printf(MSG_DEBUG, "wps scan");
|
||||
|
||||
#ifdef USE_WPS_TASK
|
||||
wps_post_block(SIG_WPS_START, 0);
|
||||
#else
|
||||
ic_pp_post(SIG_PP_WPS, 0);
|
||||
#endif
|
||||
|
||||
API_MUTEX_GIVE();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
@@ -4,6 +4,9 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "esp_wifi_driver.h"
|
||||
#include "esp_wps.h"
|
||||
|
||||
/* WPS message flag */
|
||||
enum wps_msg_flag {
|
||||
WPS_MSG_FLAG_MORE = 0x01,
|
||||
@@ -38,6 +41,10 @@ struct discard_ap_list_t{
|
||||
#define MAX_PASSPHRASE_LEN 64
|
||||
#endif
|
||||
|
||||
#ifndef MAX_CRED_COUNT
|
||||
#define MAX_CRED_COUNT 10
|
||||
#endif
|
||||
|
||||
#define WPS_OUTBUF_SIZE 500
|
||||
struct wps_sm {
|
||||
struct wps_config *wps_cfg;
|
||||
@@ -72,9 +79,47 @@ struct wps_sm {
|
||||
u8 discard_ap_cnt;
|
||||
};
|
||||
|
||||
#define API_MUTEX_TAKE() do {\
|
||||
if (!s_wps_api_lock) {\
|
||||
s_wps_api_lock = xSemaphoreCreateRecursiveMutex();\
|
||||
if (!s_wps_api_lock) {\
|
||||
wpa_printf(MSG_ERROR, "wps api lock create failed");\
|
||||
return ESP_ERR_NO_MEM;\
|
||||
}\
|
||||
}\
|
||||
xSemaphoreTakeRecursive(s_wps_api_lock, portMAX_DELAY);\
|
||||
} while(0)
|
||||
|
||||
#define API_MUTEX_GIVE() xSemaphoreGiveRecursive(s_wps_api_lock)
|
||||
#define DATA_MUTEX_TAKE() xSemaphoreTakeRecursive(s_wps_data_lock, portMAX_DELAY)
|
||||
#define DATA_MUTEX_GIVE() xSemaphoreGiveRecursive(s_wps_data_lock)
|
||||
|
||||
struct wps_sm *wps_sm_get(void);
|
||||
int wps_station_wps_unregister_cb(void);
|
||||
int wps_start_pending(void);
|
||||
int wps_sm_rx_eapol(u8 *src_addr, u8 *buf, u32 len);
|
||||
|
||||
int wps_dev_deinit(struct wps_device_data *dev);
|
||||
int wps_dev_init(void);
|
||||
int wps_set_factory_info(const esp_wps_config_t *config);
|
||||
|
||||
static inline int wps_get_type(void)
|
||||
{
|
||||
return esp_wifi_get_wps_type_internal();
|
||||
}
|
||||
|
||||
static inline int wps_set_type(uint32_t type)
|
||||
{
|
||||
return esp_wifi_set_wps_type_internal(type);
|
||||
}
|
||||
|
||||
static inline int wps_get_status(void)
|
||||
{
|
||||
return esp_wifi_get_wps_status_internal();
|
||||
}
|
||||
|
||||
static inline int wps_set_status(uint32_t status)
|
||||
{
|
||||
return esp_wifi_set_wps_status_internal(status);
|
||||
}
|
||||
int wps_init_cfg_pin(struct wps_config *cfg);
|
||||
|
@@ -65,14 +65,6 @@ void wpa_debug_print_timestamp(void);
|
||||
#define wpa_dbg(ctx, level, fmt, args...) wpa_printf(level, fmt, ##args)
|
||||
|
||||
void wpa_dump_mem(char* desc, uint8_t *addr, uint16_t len);
|
||||
static inline void wpa_hexdump_ascii(int level, const char *title, const void *buf, size_t len)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
static inline void wpa_hexdump_ascii_key(int level, const char *title, const void *buf, size_t len)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* wpa_hexdump - conditional hex dump
|
||||
@@ -87,6 +79,16 @@ static inline void wpa_hexdump_ascii_key(int level, const char *title, const voi
|
||||
*/
|
||||
void wpa_hexdump(int level, const char *title, const u8 *buf, size_t len);
|
||||
|
||||
static inline void wpa_hexdump_ascii(int level, const char *title, const void *buf, size_t len)
|
||||
{
|
||||
wpa_hexdump(level, title, buf, len);
|
||||
}
|
||||
|
||||
static inline void wpa_hexdump_ascii_key(int level, const char *title, const void *buf, size_t len)
|
||||
{
|
||||
wpa_hexdump(level, title, buf, len);
|
||||
}
|
||||
|
||||
static inline void wpa_hexdump_buf(int level, const char *title,
|
||||
const struct wpabuf *buf)
|
||||
{
|
||||
@@ -108,7 +110,6 @@ static inline void wpa_hexdump_buf(int level, const char *title,
|
||||
*/
|
||||
void wpa_hexdump_key(int level, const char *title, const u8 *buf, size_t len);
|
||||
|
||||
|
||||
static inline void wpa_hexdump_buf_key(int level, const char *title,
|
||||
const struct wpabuf *buf)
|
||||
{
|
||||
|
@@ -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;
|
||||
|
268
components/wpa_supplicant/src/ap/eap_user_db.c
Normal file
268
components/wpa_supplicant/src/ap/eap_user_db.c
Normal file
@@ -0,0 +1,268 @@
|
||||
/*
|
||||
* hostapd / EAP user database
|
||||
* Copyright (c) 2012, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#ifdef CONFIG_SQLITE
|
||||
#include <sqlite3.h>
|
||||
#endif /* CONFIG_SQLITE */
|
||||
|
||||
#include "common.h"
|
||||
#include "eap_common/eap_wsc_common.h"
|
||||
#include "eap_server/eap_methods.h"
|
||||
#include "eap_server/eap.h"
|
||||
#include "ap_config.h"
|
||||
#include "hostapd.h"
|
||||
|
||||
#ifdef CONFIG_SQLITE
|
||||
|
||||
static void set_user_methods(struct hostapd_eap_user *user, const char *methods)
|
||||
{
|
||||
char *buf, *start;
|
||||
int num_methods;
|
||||
|
||||
buf = os_strdup(methods);
|
||||
if (buf == NULL)
|
||||
return;
|
||||
|
||||
os_memset(&user->methods, 0, sizeof(user->methods));
|
||||
num_methods = 0;
|
||||
start = buf;
|
||||
while (*start) {
|
||||
char *pos3 = os_strchr(start, ',');
|
||||
if (pos3)
|
||||
*pos3++ = '\0';
|
||||
user->methods[num_methods].method =
|
||||
eap_server_get_type(start,
|
||||
&user->methods[num_methods].vendor);
|
||||
if (user->methods[num_methods].vendor == EAP_VENDOR_IETF &&
|
||||
user->methods[num_methods].method == EAP_TYPE_NONE) {
|
||||
if (os_strcmp(start, "TTLS-PAP") == 0) {
|
||||
user->ttls_auth |= EAP_TTLS_AUTH_PAP;
|
||||
goto skip_eap;
|
||||
}
|
||||
if (os_strcmp(start, "TTLS-CHAP") == 0) {
|
||||
user->ttls_auth |= EAP_TTLS_AUTH_CHAP;
|
||||
goto skip_eap;
|
||||
}
|
||||
if (os_strcmp(start, "TTLS-MSCHAP") == 0) {
|
||||
user->ttls_auth |= EAP_TTLS_AUTH_MSCHAP;
|
||||
goto skip_eap;
|
||||
}
|
||||
if (os_strcmp(start, "TTLS-MSCHAPV2") == 0) {
|
||||
user->ttls_auth |= EAP_TTLS_AUTH_MSCHAPV2;
|
||||
goto skip_eap;
|
||||
}
|
||||
wpa_printf(MSG_INFO, "DB: Unsupported EAP type '%s'",
|
||||
start);
|
||||
os_free(buf);
|
||||
return;
|
||||
}
|
||||
|
||||
num_methods++;
|
||||
if (num_methods >= EAP_MAX_METHODS)
|
||||
break;
|
||||
skip_eap:
|
||||
if (pos3 == NULL)
|
||||
break;
|
||||
start = pos3;
|
||||
}
|
||||
|
||||
os_free(buf);
|
||||
}
|
||||
|
||||
|
||||
static int get_user_cb(void *ctx, int argc, char *argv[], char *col[])
|
||||
{
|
||||
struct hostapd_eap_user *user = ctx;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < argc; i++) {
|
||||
if (os_strcmp(col[i], "password") == 0 && argv[i]) {
|
||||
bin_clear_free(user->password, user->password_len);
|
||||
user->password_len = os_strlen(argv[i]);
|
||||
user->password = (u8 *) os_strdup(argv[i]);
|
||||
user->next = (void *) 1;
|
||||
} else if (os_strcmp(col[i], "methods") == 0 && argv[i]) {
|
||||
set_user_methods(user, argv[i]);
|
||||
} else if (os_strcmp(col[i], "remediation") == 0 && argv[i]) {
|
||||
user->remediation = strlen(argv[i]) > 0;
|
||||
} else if (os_strcmp(col[i], "t_c_timestamp") == 0 && argv[i]) {
|
||||
user->t_c_timestamp = strtol(argv[i], NULL, 10);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int get_wildcard_cb(void *ctx, int argc, char *argv[], char *col[])
|
||||
{
|
||||
struct hostapd_eap_user *user = ctx;
|
||||
int i, id = -1, methods = -1;
|
||||
size_t len;
|
||||
|
||||
for (i = 0; i < argc; i++) {
|
||||
if (os_strcmp(col[i], "identity") == 0 && argv[i])
|
||||
id = i;
|
||||
else if (os_strcmp(col[i], "methods") == 0 && argv[i])
|
||||
methods = i;
|
||||
}
|
||||
|
||||
if (id < 0 || methods < 0)
|
||||
return 0;
|
||||
|
||||
len = os_strlen(argv[id]);
|
||||
if (len <= user->identity_len &&
|
||||
os_memcmp(argv[id], user->identity, len) == 0 &&
|
||||
(user->password == NULL || len > user->password_len)) {
|
||||
bin_clear_free(user->password, user->password_len);
|
||||
user->password_len = os_strlen(argv[id]);
|
||||
user->password = (u8 *) os_strdup(argv[id]);
|
||||
user->next = (void *) 1;
|
||||
set_user_methods(user, argv[methods]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static const struct hostapd_eap_user *
|
||||
eap_user_sqlite_get(struct hostapd_data *hapd, const u8 *identity,
|
||||
size_t identity_len, int phase2)
|
||||
{
|
||||
sqlite3 *db;
|
||||
struct hostapd_eap_user *user = NULL;
|
||||
char id_str[256], cmd[300];
|
||||
size_t i;
|
||||
int res;
|
||||
|
||||
if (identity_len >= sizeof(id_str)) {
|
||||
wpa_printf(MSG_DEBUG, "%s: identity len too big: %d >= %d",
|
||||
__func__, (int) identity_len,
|
||||
(int) (sizeof(id_str)));
|
||||
return NULL;
|
||||
}
|
||||
os_memcpy(id_str, identity, identity_len);
|
||||
id_str[identity_len] = '\0';
|
||||
for (i = 0; i < identity_len; i++) {
|
||||
if (id_str[i] >= 'a' && id_str[i] <= 'z')
|
||||
continue;
|
||||
if (id_str[i] >= 'A' && id_str[i] <= 'Z')
|
||||
continue;
|
||||
if (id_str[i] >= '0' && id_str[i] <= '9')
|
||||
continue;
|
||||
if (id_str[i] == '-' || id_str[i] == '_' || id_str[i] == '.' ||
|
||||
id_str[i] == ',' || id_str[i] == '@' || id_str[i] == '\\' ||
|
||||
id_str[i] == '!' || id_str[i] == '#' || id_str[i] == '%' ||
|
||||
id_str[i] == '=' || id_str[i] == ' ')
|
||||
continue;
|
||||
wpa_printf(MSG_INFO, "DB: Unsupported character in identity");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bin_clear_free(hapd->tmp_eap_user.identity,
|
||||
hapd->tmp_eap_user.identity_len);
|
||||
bin_clear_free(hapd->tmp_eap_user.password,
|
||||
hapd->tmp_eap_user.password_len);
|
||||
os_memset(&hapd->tmp_eap_user, 0, sizeof(hapd->tmp_eap_user));
|
||||
hapd->tmp_eap_user.phase2 = phase2;
|
||||
hapd->tmp_eap_user.identity = os_zalloc(identity_len + 1);
|
||||
if (hapd->tmp_eap_user.identity == NULL)
|
||||
return NULL;
|
||||
os_memcpy(hapd->tmp_eap_user.identity, identity, identity_len);
|
||||
hapd->tmp_eap_user.identity_len = identity_len;
|
||||
|
||||
if (sqlite3_open(hapd->conf->eap_user_sqlite, &db)) {
|
||||
wpa_printf(MSG_INFO, "DB: Failed to open database %s: %s",
|
||||
hapd->conf->eap_user_sqlite, sqlite3_errmsg(db));
|
||||
sqlite3_close(db);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
res = os_snprintf(cmd, sizeof(cmd),
|
||||
"SELECT * FROM users WHERE identity='%s' AND phase2=%d;",
|
||||
id_str, phase2);
|
||||
if (os_snprintf_error(sizeof(cmd), res))
|
||||
goto fail;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "DB: %s", cmd);
|
||||
if (sqlite3_exec(db, cmd, get_user_cb, &hapd->tmp_eap_user, NULL) !=
|
||||
SQLITE_OK) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"DB: Failed to complete SQL operation: %s db: %s",
|
||||
sqlite3_errmsg(db), hapd->conf->eap_user_sqlite);
|
||||
} else if (hapd->tmp_eap_user.next)
|
||||
user = &hapd->tmp_eap_user;
|
||||
|
||||
if (user == NULL && !phase2) {
|
||||
os_snprintf(cmd, sizeof(cmd),
|
||||
"SELECT identity,methods FROM wildcards;");
|
||||
wpa_printf(MSG_DEBUG, "DB: %s", cmd);
|
||||
if (sqlite3_exec(db, cmd, get_wildcard_cb, &hapd->tmp_eap_user,
|
||||
NULL) != SQLITE_OK) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"DB: Failed to complete SQL operation: %s db: %s",
|
||||
sqlite3_errmsg(db),
|
||||
hapd->conf->eap_user_sqlite);
|
||||
} else if (hapd->tmp_eap_user.next) {
|
||||
user = &hapd->tmp_eap_user;
|
||||
os_free(user->identity);
|
||||
user->identity = user->password;
|
||||
user->identity_len = user->password_len;
|
||||
user->password = NULL;
|
||||
user->password_len = 0;
|
||||
}
|
||||
}
|
||||
|
||||
fail:
|
||||
sqlite3_close(db);
|
||||
|
||||
return user;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_SQLITE */
|
||||
|
||||
|
||||
const struct hostapd_eap_user *
|
||||
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;
|
||||
|
||||
#ifdef CONFIG_WPS
|
||||
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));
|
||||
wsc_enrollee.methods[0].method = eap_server_get_type(
|
||||
"WSC", &wsc_enrollee.methods[0].vendor);
|
||||
return &wsc_enrollee;
|
||||
}
|
||||
|
||||
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));
|
||||
wsc_registrar.methods[0].method = eap_server_get_type(
|
||||
"WSC", &wsc_registrar.methods[0].vendor);
|
||||
wsc_registrar.password = (u8 *) conf->ap_pin;
|
||||
wsc_registrar.password_len = conf->ap_pin ?
|
||||
os_strlen(conf->ap_pin) : 0;
|
||||
return &wsc_registrar;
|
||||
}
|
||||
#endif /* CONFIG_WPS */
|
||||
|
||||
#ifdef CONFIG_SQLITE
|
||||
if (user == NULL && conf->eap_user_sqlite) {
|
||||
return eap_user_sqlite_get(hapd, identity, identity_len,
|
||||
phase2);
|
||||
}
|
||||
#endif /* CONFIG_SQLITE */
|
||||
|
||||
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 */
|
||||
|
208
components/wpa_supplicant/src/ap/sta_info.c
Normal file
208
components/wpa_supplicant/src/ap/sta_info.c
Normal file
@@ -0,0 +1,208 @@
|
||||
/*
|
||||
* hostapd / Station table
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "utils/includes.h"
|
||||
|
||||
#include "utils/common.h"
|
||||
#include "utils/eloop.h"
|
||||
#include "common/ieee802_11_defs.h"
|
||||
#include "crypto/crypto.h"
|
||||
#include "hostapd.h"
|
||||
#include "ieee802_1x.h"
|
||||
#include "wpa_auth.h"
|
||||
#include "ap_config.h"
|
||||
#include "sta_info.h"
|
||||
|
||||
static void ap_sta_delayed_1x_auth_fail_cb(void *eloop_ctx, void *timeout_ctx);
|
||||
void hostapd_wps_eap_completed(struct hostapd_data *hapd);
|
||||
|
||||
int ap_for_each_sta(struct hostapd_data *hapd,
|
||||
int (*cb)(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
void *ctx),
|
||||
void *ctx)
|
||||
{
|
||||
struct sta_info *sta;
|
||||
|
||||
for (sta = hapd->sta_list; sta; sta = sta->next) {
|
||||
if (cb(hapd, sta, ctx))
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
struct sta_info * ap_get_sta(struct hostapd_data *hapd, const u8 *sta)
|
||||
{
|
||||
struct sta_info *s;
|
||||
|
||||
s = hapd->sta_hash[STA_HASH(sta)];
|
||||
while (s != NULL && os_memcmp(s->addr, sta, 6) != 0)
|
||||
s = s->hnext;
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
static void ap_sta_list_del(struct hostapd_data *hapd, struct sta_info *sta)
|
||||
{
|
||||
struct sta_info *tmp;
|
||||
|
||||
if (hapd->sta_list == sta) {
|
||||
hapd->sta_list = sta->next;
|
||||
return;
|
||||
}
|
||||
|
||||
tmp = hapd->sta_list;
|
||||
while (tmp != NULL && tmp->next != sta)
|
||||
tmp = tmp->next;
|
||||
if (tmp == NULL) {
|
||||
wpa_printf(MSG_DEBUG, "Could not remove STA " MACSTR " from "
|
||||
"list.", MAC2STR(sta->addr));
|
||||
} else
|
||||
tmp->next = sta->next;
|
||||
}
|
||||
|
||||
|
||||
void ap_sta_hash_add(struct hostapd_data *hapd, struct sta_info *sta)
|
||||
{
|
||||
sta->hnext = hapd->sta_hash[STA_HASH(sta->addr)];
|
||||
hapd->sta_hash[STA_HASH(sta->addr)] = sta;
|
||||
}
|
||||
|
||||
|
||||
static void ap_sta_hash_del(struct hostapd_data *hapd, struct sta_info *sta)
|
||||
{
|
||||
struct sta_info *s;
|
||||
|
||||
s = hapd->sta_hash[STA_HASH(sta->addr)];
|
||||
if (s == NULL) return;
|
||||
if (os_memcmp(s->addr, sta->addr, 6) == 0) {
|
||||
hapd->sta_hash[STA_HASH(sta->addr)] = s->hnext;
|
||||
return;
|
||||
}
|
||||
|
||||
while (s->hnext != NULL &&
|
||||
os_memcmp(s->hnext->addr, sta->addr, ETH_ALEN) != 0)
|
||||
s = s->hnext;
|
||||
if (s->hnext != NULL)
|
||||
s->hnext = s->hnext->hnext;
|
||||
else
|
||||
wpa_printf(MSG_DEBUG, "AP: could not remove STA " MACSTR
|
||||
" from hash table", MAC2STR(sta->addr));
|
||||
}
|
||||
|
||||
void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
|
||||
{
|
||||
ap_sta_hash_del(hapd, sta);
|
||||
ap_sta_list_del(hapd, sta);
|
||||
|
||||
hapd->num_sta--;
|
||||
|
||||
wpa_auth_sta_deinit(sta->wpa_sm);
|
||||
#ifdef CONFIG_WPS_REGISTRAR
|
||||
if (ap_sta_pending_delayed_1x_auth_fail_disconnect(hapd, sta))
|
||||
eloop_cancel_timeout(ap_sta_delayed_1x_auth_fail_cb, hapd, sta);
|
||||
|
||||
ieee802_1x_free_station(hapd, sta);
|
||||
|
||||
wpabuf_free(sta->wps_ie);
|
||||
#endif
|
||||
|
||||
os_free(sta);
|
||||
}
|
||||
|
||||
|
||||
void hostapd_free_stas(struct hostapd_data *hapd)
|
||||
{
|
||||
struct sta_info *sta, *prev;
|
||||
|
||||
sta = hapd->sta_list;
|
||||
|
||||
while (sta) {
|
||||
prev = sta;
|
||||
sta = sta->next;
|
||||
wpa_printf(MSG_DEBUG, "Removing station " MACSTR,
|
||||
MAC2STR(prev->addr));
|
||||
ap_free_sta(hapd, prev);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
struct sta_info * ap_sta_add(struct hostapd_data *hapd, const u8 *addr)
|
||||
{
|
||||
struct sta_info *sta;
|
||||
|
||||
sta = ap_get_sta(hapd, addr);
|
||||
if (sta)
|
||||
return sta;
|
||||
|
||||
wpa_printf(MSG_DEBUG, " New STA");
|
||||
if (hapd->num_sta >= hapd->conf->max_num_sta) {
|
||||
/* FIX: might try to remove some old STAs first? */
|
||||
wpa_printf(MSG_DEBUG, "no more room for new STAs (%d/%d)",
|
||||
hapd->num_sta, hapd->conf->max_num_sta);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sta = os_zalloc(sizeof(struct sta_info));
|
||||
if (sta == NULL) {
|
||||
wpa_printf(MSG_ERROR, "malloc failed");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* initialize STA info data */
|
||||
os_memcpy(sta->addr, addr, ETH_ALEN);
|
||||
sta->next = hapd->sta_list;
|
||||
hapd->sta_list = sta;
|
||||
hapd->num_sta++;
|
||||
ap_sta_hash_add(hapd, sta);
|
||||
|
||||
return sta;
|
||||
}
|
||||
|
||||
static void ap_sta_delayed_1x_auth_fail_cb(void *eloop_ctx, void *timeout_ctx)
|
||||
{
|
||||
struct hostapd_data *hapd = eloop_ctx;
|
||||
struct sta_info *sta = timeout_ctx;
|
||||
u16 reason;
|
||||
|
||||
wpa_dbg(hapd->msg_ctx, MSG_DEBUG,
|
||||
"IEEE 802.1X: Scheduled disconnection of " MACSTR
|
||||
" after EAP-Failure", MAC2STR(sta->addr));
|
||||
|
||||
reason = WLAN_REASON_IEEE_802_1X_AUTH_FAILED;
|
||||
esp_wifi_ap_deauth_internal(sta->addr, reason);
|
||||
if (sta->flags & WLAN_STA_WPS)
|
||||
hostapd_wps_eap_completed(hapd);
|
||||
}
|
||||
|
||||
|
||||
void ap_sta_delayed_1x_auth_fail_disconnect(struct hostapd_data *hapd,
|
||||
struct sta_info *sta)
|
||||
{
|
||||
wpa_dbg(hapd->msg_ctx, MSG_DEBUG,
|
||||
"IEEE 802.1X: Force disconnection of " MACSTR
|
||||
" after EAP-Failure in 10 ms", MAC2STR(sta->addr));
|
||||
|
||||
/*
|
||||
* Add a small sleep to increase likelihood of previously requested
|
||||
* EAP-Failure TX getting out before this should the driver reorder
|
||||
* operations.
|
||||
*/
|
||||
eloop_cancel_timeout(ap_sta_delayed_1x_auth_fail_cb, hapd, sta);
|
||||
eloop_register_timeout(0, 10000, ap_sta_delayed_1x_auth_fail_cb,
|
||||
hapd, sta);
|
||||
}
|
||||
|
||||
|
||||
int ap_sta_pending_delayed_1x_auth_fail_disconnect(struct hostapd_data *hapd,
|
||||
struct sta_info *sta)
|
||||
{
|
||||
return eloop_is_timeout_registered(ap_sta_delayed_1x_auth_fail_cb,
|
||||
hapd, sta);
|
||||
}
|
@@ -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;
|
||||
}
|
78
components/wpa_supplicant/src/ap/wps_hostapd.h
Normal file
78
components/wpa_supplicant/src/ap/wps_hostapd.h
Normal file
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* hostapd / WPS integration
|
||||
* Copyright (c) 2008-2012, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef WPS_HOSTAPD_H
|
||||
#define WPS_HOSTAPD_H
|
||||
|
||||
#ifdef CONFIG_WPS
|
||||
|
||||
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 *pin);
|
||||
int hostapd_wps_button_pushed(struct hostapd_data *hapd,
|
||||
const u8 *p2p_dev_addr);
|
||||
int hostapd_wps_cancel(struct hostapd_data *hapd);
|
||||
int hostapd_wps_get_mib_sta(struct hostapd_data *hapd, const u8 *addr,
|
||||
char *buf, size_t buflen);
|
||||
void hostapd_wps_ap_pin_disable(struct hostapd_data *hapd);
|
||||
const char * hostapd_wps_ap_pin_random(struct hostapd_data *hapd, int timeout);
|
||||
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, struct wps_data *wps_data);
|
||||
int hostapd_wps_nfc_tag_read(struct hostapd_data *hapd,
|
||||
const struct wpabuf *data);
|
||||
#else /* CONFIG_WPS */
|
||||
|
||||
static inline int hostapd_init_wps(struct hostapd_data *hapd, struct wps_data *wps_data, struct wps_context *wps)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void hostapd_deinit_wps(struct hostapd_data *hapd)
|
||||
{
|
||||
}
|
||||
|
||||
static inline int hostapd_init_wps_complete(struct hostapd_data *hapd)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void hostapd_update_wps(struct hostapd_data *hapd)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void hostapd_wps_eap_completed(struct hostapd_data *hapd)
|
||||
{
|
||||
}
|
||||
|
||||
static inline int hostapd_wps_get_mib_sta(struct hostapd_data *hapd,
|
||||
const u8 *addr,
|
||||
char *buf, size_t buflen)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int hostapd_wps_button_pushed(struct hostapd_data *hapd,
|
||||
const u8 *p2p_dev_addr)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int hostapd_wps_cancel(struct hostapd_data *hapd)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_WPS */
|
||||
|
||||
#endif /* WPS_HOSTAPD_H */
|
@@ -228,6 +228,39 @@ int ieee802_11_parse_elems(struct wpa_supplicant *wpa_s, const u8 *start, size_t
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct wpabuf * ieee802_11_vendor_ie_concat(const u8 *ies, size_t ies_len,
|
||||
u32 oui_type)
|
||||
{
|
||||
struct wpabuf *buf;
|
||||
const struct element *elem, *found = NULL;
|
||||
|
||||
for_each_element_id(elem, WLAN_EID_VENDOR_SPECIFIC, ies, ies_len) {
|
||||
if (elem->datalen >= 4 &&
|
||||
WPA_GET_BE32(elem->data) == oui_type) {
|
||||
found = elem;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
return NULL; /* No specified vendor IE found */
|
||||
|
||||
buf = wpabuf_alloc(ies_len);
|
||||
if (buf == NULL)
|
||||
return NULL;
|
||||
|
||||
/*
|
||||
* There may be multiple vendor IEs in the message, so need to
|
||||
* concatenate their data fields.
|
||||
*/
|
||||
for_each_element_id(elem, WLAN_EID_VENDOR_SPECIFIC, ies, ies_len) {
|
||||
if (elem->datalen >= 4 && WPA_GET_BE32(elem->data) == oui_type)
|
||||
wpabuf_put_data(buf, elem->data + 4, elem->datalen - 4);
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
int ieee802_11_ext_capab(const u8 *ie, unsigned int capab)
|
||||
{
|
||||
if (!ie || ie[1] <= capab / 8)
|
||||
|
@@ -43,4 +43,6 @@ const u8 * get_vendor_ie(const u8 *ies, size_t len, u32 vendor_type);
|
||||
size_t mbo_add_ie(u8 *buf, size_t len, const u8 *attr, size_t attr_len);
|
||||
u8 get_operating_class(u8 chan, int sec_channel);
|
||||
int ieee802_11_ie_count(const u8 *ies, size_t ies_len);
|
||||
struct wpabuf * ieee802_11_vendor_ie_concat(const u8 *ies, size_t ies_len,
|
||||
u32 oui_type);
|
||||
#endif /* IEEE802_11_COMMON_H */
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* EAP server/peer: Shared EAP definitions
|
||||
* Copyright (c) 2004-2007, Jouni Malinen <j@w1.fi>
|
||||
* Copyright (c) 2004-2014, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
@@ -22,22 +22,49 @@ struct eap_hdr {
|
||||
/* followed by length-4 octets of data */
|
||||
} STRUCT_PACKED;
|
||||
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma pack(pop)
|
||||
#endif /* _MSC_VER */
|
||||
|
||||
enum { EAP_CODE_REQUEST = 1, EAP_CODE_RESPONSE = 2, EAP_CODE_SUCCESS = 3,
|
||||
EAP_CODE_FAILURE = 4 };
|
||||
EAP_CODE_FAILURE = 4, EAP_CODE_INITIATE = 5, EAP_CODE_FINISH = 6 };
|
||||
|
||||
/* EAP Request and Response data begins with one octet Type. Success and
|
||||
* Failure do not have additional data. */
|
||||
|
||||
/* Type field in EAP-Initiate and EAP-Finish messages */
|
||||
enum eap_erp_type {
|
||||
EAP_ERP_TYPE_REAUTH_START = 1,
|
||||
EAP_ERP_TYPE_REAUTH = 2,
|
||||
};
|
||||
|
||||
/* ERP TV/TLV types */
|
||||
enum eap_erp_tlv_type {
|
||||
EAP_ERP_TLV_KEYNAME_NAI = 1,
|
||||
EAP_ERP_TV_RRK_LIFETIME = 2,
|
||||
EAP_ERP_TV_RMSK_LIFETIME = 3,
|
||||
EAP_ERP_TLV_DOMAIN_NAME = 4,
|
||||
EAP_ERP_TLV_CRYPTOSUITES = 5,
|
||||
EAP_ERP_TLV_AUTHORIZATION_INDICATION = 6,
|
||||
EAP_ERP_TLV_CALLED_STATION_ID = 128,
|
||||
EAP_ERP_TLV_CALLING_STATION_ID = 129,
|
||||
EAP_ERP_TLV_NAS_IDENTIFIER = 130,
|
||||
EAP_ERP_TLV_NAS_IP_ADDRESS = 131,
|
||||
EAP_ERP_TLV_NAS_IPV6_ADDRESS = 132,
|
||||
};
|
||||
|
||||
/* ERP Cryptosuite */
|
||||
enum eap_erp_cryptosuite {
|
||||
EAP_ERP_CS_HMAC_SHA256_64 = 1,
|
||||
EAP_ERP_CS_HMAC_SHA256_128 = 2,
|
||||
EAP_ERP_CS_HMAC_SHA256_256 = 3,
|
||||
};
|
||||
|
||||
/*
|
||||
* EAP Method Types as allocated by IANA:
|
||||
* http://www.iana.org/assignments/eap-numbers
|
||||
*/
|
||||
typedef enum {
|
||||
typedef enum eap_type {
|
||||
EAP_TYPE_NONE = 0,
|
||||
EAP_TYPE_IDENTITY = 1 /* RFC 3748 */,
|
||||
EAP_TYPE_NOTIFICATION = 2 /* RFC 3748 */,
|
||||
@@ -65,6 +92,7 @@ typedef enum {
|
||||
EAP_TYPE_GPSK = 51 /* RFC 5433 */,
|
||||
EAP_TYPE_PWD = 52 /* RFC 5931 */,
|
||||
EAP_TYPE_EKE = 53 /* RFC 6124 */,
|
||||
EAP_TYPE_TEAP = 55 /* RFC 7170 */,
|
||||
EAP_TYPE_EXPANDED = 254 /* RFC 3748 */
|
||||
} EapType;
|
||||
|
||||
@@ -73,8 +101,9 @@ typedef enum {
|
||||
enum {
|
||||
EAP_VENDOR_IETF = 0,
|
||||
EAP_VENDOR_MICROSOFT = 0x000137 /* Microsoft */,
|
||||
EAP_VENDOR_WFA = 0x00372A /* Wi-Fi Alliance */,
|
||||
EAP_VENDOR_HOSTAP = 39068 /* hostapd/wpa_supplicant project */
|
||||
EAP_VENDOR_WFA = 0x00372A /* Wi-Fi Alliance (moved to WBA) */,
|
||||
EAP_VENDOR_HOSTAP = 39068 /* hostapd/wpa_supplicant project */,
|
||||
EAP_VENDOR_WFA_NEW = 40808 /* Wi-Fi Alliance */
|
||||
};
|
||||
|
||||
struct eap_expand {
|
||||
@@ -86,7 +115,11 @@ struct eap_expand {
|
||||
#define EAP_VENDOR_UNAUTH_TLS EAP_VENDOR_HOSTAP
|
||||
#define EAP_VENDOR_TYPE_UNAUTH_TLS 1
|
||||
|
||||
#define EAP_VENDOR_WFA_UNAUTH_TLS 13
|
||||
|
||||
#define EAP_MSK_LEN 64
|
||||
#define EAP_EMSK_LEN 64
|
||||
#define EAP_EMSK_NAME_LEN 8
|
||||
#define ERP_MAX_KEY_LEN 64
|
||||
|
||||
#endif /* EAP_DEFS_H */
|
||||
|
297
components/wpa_supplicant/src/eap_server/eap.h
Normal file
297
components/wpa_supplicant/src/eap_server/eap.h
Normal file
@@ -0,0 +1,297 @@
|
||||
/*
|
||||
* hostapd / EAP Full Authenticator state machine (RFC 4137)
|
||||
* Copyright (c) 2004-2014, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef EAP_H
|
||||
#define EAP_H
|
||||
|
||||
#include "common/defs.h"
|
||||
#include "utils/list.h"
|
||||
#include "eap_peer/eap_defs.h"
|
||||
#include "eap_server/eap_methods.h"
|
||||
#include "utils/wpabuf.h"
|
||||
|
||||
struct eap_sm;
|
||||
|
||||
#define EAP_TTLS_AUTH_PAP 1
|
||||
#define EAP_TTLS_AUTH_CHAP 2
|
||||
#define EAP_TTLS_AUTH_MSCHAP 4
|
||||
#define EAP_TTLS_AUTH_MSCHAPV2 8
|
||||
|
||||
struct eap_user {
|
||||
struct {
|
||||
int vendor;
|
||||
u32 method;
|
||||
} methods[EAP_MAX_METHODS];
|
||||
u8 *password;
|
||||
size_t password_len;
|
||||
int password_hash; /* whether password is hashed with
|
||||
* nt_password_hash() */
|
||||
u8 *salt;
|
||||
size_t salt_len;
|
||||
int phase2;
|
||||
int force_version;
|
||||
unsigned int remediation:1;
|
||||
unsigned int macacl:1;
|
||||
int ttls_auth; /* bitfield of
|
||||
* EAP_TTLS_AUTH_{PAP,CHAP,MSCHAP,MSCHAPV2} */
|
||||
struct hostapd_radius_attr *accept_attr;
|
||||
u32 t_c_timestamp;
|
||||
};
|
||||
|
||||
struct eap_eapol_interface {
|
||||
/* Lower layer to full authenticator variables */
|
||||
bool eapResp; /* shared with EAPOL Backend Authentication */
|
||||
struct wpabuf *eapRespData;
|
||||
bool portEnabled;
|
||||
int retransWhile;
|
||||
bool eapRestart; /* shared with EAPOL Authenticator PAE */
|
||||
int eapSRTT;
|
||||
int eapRTTVAR;
|
||||
|
||||
/* Full authenticator to lower layer variables */
|
||||
bool eapReq; /* shared with EAPOL Backend Authentication */
|
||||
bool eapNoReq; /* shared with EAPOL Backend Authentication */
|
||||
bool eapSuccess;
|
||||
bool eapFail;
|
||||
bool eapTimeout;
|
||||
struct wpabuf *eapReqData;
|
||||
u8 *eapKeyData;
|
||||
size_t eapKeyDataLen;
|
||||
u8 *eapSessionId;
|
||||
size_t eapSessionIdLen;
|
||||
bool eapKeyAvailable; /* called keyAvailable in IEEE 802.1X-2004 */
|
||||
|
||||
#ifndef ESP_SUPPLICANT
|
||||
/* AAA interface to full authenticator variables */
|
||||
bool aaaEapReq;
|
||||
bool aaaEapNoReq;
|
||||
bool aaaSuccess;
|
||||
bool aaaFail;
|
||||
struct wpabuf *aaaEapReqData;
|
||||
u8 *aaaEapKeyData;
|
||||
size_t aaaEapKeyDataLen;
|
||||
bool aaaEapKeyAvailable;
|
||||
int aaaMethodTimeout;
|
||||
|
||||
/* Full authenticator to AAA interface variables */
|
||||
bool aaaEapResp;
|
||||
struct wpabuf *aaaEapRespData;
|
||||
/* aaaIdentity -> eap_get_identity() */
|
||||
bool aaaTimeout;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct eap_server_erp_key {
|
||||
struct dl_list list;
|
||||
size_t rRK_len;
|
||||
size_t rIK_len;
|
||||
u8 rRK[ERP_MAX_KEY_LEN];
|
||||
u8 rIK[ERP_MAX_KEY_LEN];
|
||||
u32 recv_seq;
|
||||
u8 cryptosuite;
|
||||
char keyname_nai[];
|
||||
};
|
||||
|
||||
struct eapol_callbacks {
|
||||
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);
|
||||
void (*log_msg)(void *ctx, const char *msg);
|
||||
int (*get_erp_send_reauth_start)(void *ctx);
|
||||
const char * (*get_erp_domain)(void *ctx);
|
||||
struct eap_server_erp_key * (*erp_get_key)(void *ctx,
|
||||
const char *keyname);
|
||||
int (*erp_add_key)(void *ctx, struct eap_server_erp_key *erp);
|
||||
};
|
||||
|
||||
struct eap_config {
|
||||
/**
|
||||
* ssl_ctx - TLS context
|
||||
*
|
||||
* This is passed to the EAP server implementation as a callback
|
||||
* context for TLS operations.
|
||||
*/
|
||||
void *ssl_ctx;
|
||||
void *msg_ctx;
|
||||
|
||||
/**
|
||||
* eap_sim_db_priv - EAP-SIM/AKA database context
|
||||
*
|
||||
* This is passed to the EAP-SIM/AKA server implementation as a
|
||||
* callback context.
|
||||
*/
|
||||
void *eap_sim_db_priv;
|
||||
bool backend_auth;
|
||||
int eap_server;
|
||||
|
||||
/**
|
||||
* pwd_group - The D-H group assigned for EAP-pwd
|
||||
*
|
||||
* If EAP-pwd is not used it can be set to zero.
|
||||
*/
|
||||
u16 pwd_group;
|
||||
|
||||
/**
|
||||
* pac_opaque_encr_key - PAC-Opaque encryption key for EAP-FAST
|
||||
*
|
||||
* This parameter is used to set a key for EAP-FAST to encrypt the
|
||||
* PAC-Opaque data. It can be set to %NULL if EAP-FAST is not used. If
|
||||
* set, must point to a 16-octet key.
|
||||
*/
|
||||
u8 *pac_opaque_encr_key;
|
||||
|
||||
/**
|
||||
* eap_fast_a_id - EAP-FAST authority identity (A-ID)
|
||||
*
|
||||
* If EAP-FAST is not used, this can be set to %NULL. In theory, this
|
||||
* is a variable length field, but due to some existing implementations
|
||||
* requiring A-ID to be 16 octets in length, it is recommended to use
|
||||
* that length for the field to provide interoperability with deployed
|
||||
* peer implementations.
|
||||
*/
|
||||
u8 *eap_fast_a_id;
|
||||
|
||||
/**
|
||||
* eap_fast_a_id_len - Length of eap_fast_a_id buffer in octets
|
||||
*/
|
||||
size_t eap_fast_a_id_len;
|
||||
/**
|
||||
* eap_fast_a_id_info - EAP-FAST authority identifier information
|
||||
*
|
||||
* This A-ID-Info contains a user-friendly name for the A-ID. For
|
||||
* example, this could be the enterprise and server names in
|
||||
* human-readable format. This field is encoded as UTF-8. If EAP-FAST
|
||||
* is not used, this can be set to %NULL.
|
||||
*/
|
||||
char *eap_fast_a_id_info;
|
||||
|
||||
/**
|
||||
* eap_fast_prov - EAP-FAST provisioning modes
|
||||
*
|
||||
* 0 = provisioning disabled, 1 = only anonymous provisioning allowed,
|
||||
* 2 = only authenticated provisioning allowed, 3 = both provisioning
|
||||
* modes allowed.
|
||||
*/
|
||||
enum {
|
||||
NO_PROV, ANON_PROV, AUTH_PROV, BOTH_PROV
|
||||
} eap_fast_prov;
|
||||
|
||||
/**
|
||||
* pac_key_lifetime - EAP-FAST PAC-Key lifetime in seconds
|
||||
*
|
||||
* This is the hard limit on how long a provisioned PAC-Key can be
|
||||
* used.
|
||||
*/
|
||||
int pac_key_lifetime;
|
||||
|
||||
/**
|
||||
* pac_key_refresh_time - EAP-FAST PAC-Key refresh time in seconds
|
||||
*
|
||||
* This is a soft limit on the PAC-Key. The server will automatically
|
||||
* generate a new PAC-Key when this number of seconds (or fewer) of the
|
||||
* lifetime remains.
|
||||
*/
|
||||
int pac_key_refresh_time;
|
||||
int eap_teap_auth;
|
||||
int eap_teap_pac_no_inner;
|
||||
int eap_teap_separate_result;
|
||||
enum eap_teap_id {
|
||||
EAP_TEAP_ID_ALLOW_ANY = 0,
|
||||
EAP_TEAP_ID_REQUIRE_USER = 1,
|
||||
EAP_TEAP_ID_REQUIRE_MACHINE = 2,
|
||||
EAP_TEAP_ID_REQUEST_USER_ACCEPT_MACHINE = 3,
|
||||
EAP_TEAP_ID_REQUEST_MACHINE_ACCEPT_USER = 4,
|
||||
EAP_TEAP_ID_REQUIRE_USER_AND_MACHINE = 5,
|
||||
} eap_teap_id;
|
||||
|
||||
/**
|
||||
* eap_sim_aka_result_ind - EAP-SIM/AKA protected success indication
|
||||
*
|
||||
* This controls whether the protected success/failure indication
|
||||
* (AT_RESULT_IND) is used with EAP-SIM and EAP-AKA.
|
||||
*/
|
||||
int eap_sim_aka_result_ind;
|
||||
int eap_sim_id;
|
||||
|
||||
/**
|
||||
* tnc - Trusted Network Connect (TNC)
|
||||
*
|
||||
* This controls whether TNC is enabled and will be required before the
|
||||
* peer is allowed to connect. Note: This is only used with EAP-TTLS
|
||||
* and EAP-FAST. If any other EAP method is enabled, the peer will be
|
||||
* allowed to connect without TNC.
|
||||
*/
|
||||
int tnc;
|
||||
|
||||
/**
|
||||
* wps - Wi-Fi Protected Setup context
|
||||
*
|
||||
* If WPS is used with an external RADIUS server (which is quite
|
||||
* unlikely configuration), this is used to provide a pointer to WPS
|
||||
* context data. Normally, this can be set to %NULL.
|
||||
*/
|
||||
struct wps_context *wps;
|
||||
int fragment_size;
|
||||
|
||||
int pbc_in_m1;
|
||||
|
||||
/**
|
||||
* server_id - Server identity
|
||||
*/
|
||||
u8 *server_id;
|
||||
size_t server_id_len;
|
||||
|
||||
/**
|
||||
* erp - Whether EAP Re-authentication Protocol (ERP) is enabled
|
||||
*
|
||||
* This controls whether the authentication server derives ERP key
|
||||
* hierarchy (rRK and rIK) from full EAP authentication and allows
|
||||
* these keys to be used to perform ERP to derive rMSK instead of full
|
||||
* EAP authentication to derive MSK.
|
||||
*/
|
||||
int erp;
|
||||
unsigned int tls_session_lifetime;
|
||||
unsigned int tls_flags;
|
||||
|
||||
unsigned int max_auth_rounds;
|
||||
unsigned int max_auth_rounds_short;
|
||||
};
|
||||
|
||||
struct eap_session_data {
|
||||
const struct wpabuf *assoc_wps_ie;
|
||||
const struct wpabuf *assoc_p2p_ie;
|
||||
const u8 *peer_addr;
|
||||
#ifdef CONFIG_TESTING_OPTIONS
|
||||
u32 tls_test_flags;
|
||||
#endif /* CONFIG_TESTING_OPTIONS */
|
||||
};
|
||||
|
||||
|
||||
struct eap_sm * eap_server_sm_init(void *eapol_ctx,
|
||||
const struct eapol_callbacks *eapol_cb,
|
||||
const struct eap_config *conf,
|
||||
const struct eap_session_data *sess);
|
||||
void eap_server_sm_deinit(struct eap_sm *sm);
|
||||
int eap_server_sm_step(struct eap_sm *sm);
|
||||
void eap_sm_notify_cached(struct eap_sm *sm);
|
||||
void eap_sm_pending_cb(struct eap_sm *sm);
|
||||
int eap_sm_method_pending(struct eap_sm *sm);
|
||||
const u8 * eap_get_identity(struct eap_sm *sm, size_t *len);
|
||||
const char * eap_get_serial_num(struct eap_sm *sm);
|
||||
const char * eap_get_method(struct eap_sm *sm);
|
||||
const char * eap_get_imsi(struct eap_sm *sm);
|
||||
struct eap_eapol_interface * eap_get_interface(struct eap_sm *sm);
|
||||
void eap_server_clear_identity(struct eap_sm *sm);
|
||||
void eap_server_mschap_rx_callback(struct eap_sm *sm, const char *source,
|
||||
const u8 *username, size_t username_len,
|
||||
const u8 *challenge, const u8 *response);
|
||||
void eap_erp_update_identity(struct eap_sm *sm, const u8 *eap, size_t len);
|
||||
void eap_user_free(struct eap_user *user);
|
||||
void eap_server_config_free(struct eap_config *cfg);
|
||||
|
||||
#endif /* EAP_H */
|
203
components/wpa_supplicant/src/eap_server/eap_i.h
Normal file
203
components/wpa_supplicant/src/eap_server/eap_i.h
Normal file
@@ -0,0 +1,203 @@
|
||||
/*
|
||||
* hostapd / EAP Authenticator state machine internal structures (RFC 4137)
|
||||
* Copyright (c) 2004-2007, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef EAP_I_H
|
||||
#define EAP_I_H
|
||||
|
||||
#include "utils/wpabuf.h"
|
||||
#include "eap_server/eap.h"
|
||||
#include "eap_peer/eap_common.h"
|
||||
|
||||
/* RFC 4137 - EAP Standalone Authenticator */
|
||||
|
||||
/**
|
||||
* struct eap_method - EAP method interface
|
||||
* This structure defines the EAP method interface. Each method will need to
|
||||
* register its own EAP type, EAP name, and set of function pointers for method
|
||||
* specific operations. This interface is based on section 5.4 of RFC 4137.
|
||||
*/
|
||||
struct eap_method {
|
||||
int vendor;
|
||||
enum eap_type method;
|
||||
const char *name;
|
||||
|
||||
void * (*init)(struct eap_sm *sm);
|
||||
void * (*initPickUp)(struct eap_sm *sm);
|
||||
void (*reset)(struct eap_sm *sm, void *priv);
|
||||
|
||||
struct wpabuf * (*buildReq)(struct eap_sm *sm, void *priv, u8 id);
|
||||
int (*getTimeout)(struct eap_sm *sm, void *priv);
|
||||
bool (*check)(struct eap_sm *sm, void *priv, struct wpabuf *respData);
|
||||
void (*process)(struct eap_sm *sm, void *priv,
|
||||
struct wpabuf *respData);
|
||||
bool (*isDone)(struct eap_sm *sm, void *priv);
|
||||
u8 * (*getKey)(struct eap_sm *sm, void *priv, size_t *len);
|
||||
/* isSuccess is not specified in draft-ietf-eap-statemachine-05.txt,
|
||||
* but it is useful in implementing Policy.getDecision() */
|
||||
bool (*isSuccess)(struct eap_sm *sm, void *priv);
|
||||
|
||||
/**
|
||||
* free - Free EAP method data
|
||||
* @method: Pointer to the method data registered with
|
||||
* eap_server_method_register().
|
||||
*
|
||||
* This function will be called when the EAP method is being
|
||||
* unregistered. If the EAP method allocated resources during
|
||||
* registration (e.g., allocated struct eap_method), they should be
|
||||
* freed in this function. No other method functions will be called
|
||||
* after this call. If this function is not defined (i.e., function
|
||||
* pointer is %NULL), a default handler is used to release the method
|
||||
* data with free(method). This is suitable for most cases.
|
||||
*/
|
||||
void (*free)(struct eap_method *method);
|
||||
|
||||
#define EAP_SERVER_METHOD_INTERFACE_VERSION 1
|
||||
/**
|
||||
* version - Version of the EAP server method interface
|
||||
*
|
||||
* The EAP server method implementation should set this variable to
|
||||
* EAP_SERVER_METHOD_INTERFACE_VERSION. This is used to verify that the
|
||||
* EAP method is using supported API version when using dynamically
|
||||
* loadable EAP methods.
|
||||
*/
|
||||
int version;
|
||||
|
||||
/**
|
||||
* next - Pointer to the next EAP method
|
||||
*
|
||||
* This variable is used internally in the EAP method registration code
|
||||
* to create a linked list of registered EAP methods.
|
||||
*/
|
||||
struct eap_method *next;
|
||||
|
||||
/**
|
||||
* get_emsk - Get EAP method specific keying extended material (EMSK)
|
||||
* @sm: Pointer to EAP state machine allocated with eap_sm_init()
|
||||
* @priv: Pointer to private EAP method data from eap_method::init()
|
||||
* @len: Pointer to a variable to store EMSK length
|
||||
* Returns: EMSK or %NULL if not available
|
||||
*
|
||||
* This function can be used to get the extended keying material from
|
||||
* the EAP method. The key may already be stored in the method-specific
|
||||
* private data or this function may derive the key.
|
||||
*/
|
||||
u8 * (*get_emsk)(struct eap_sm *sm, void *priv, size_t *len);
|
||||
|
||||
/**
|
||||
* getSessionId - Get EAP method specific Session-Id
|
||||
* @sm: Pointer to EAP state machine allocated with eap_server_sm_init()
|
||||
* @priv: Pointer to private EAP method data from eap_method::init()
|
||||
* @len: Pointer to a variable to store Session-Id length
|
||||
* Returns: Session-Id or %NULL if not available
|
||||
*
|
||||
* This function can be used to get the Session-Id from the EAP method.
|
||||
* The Session-Id may already be stored in the method-specific private
|
||||
* data or this function may derive the Session-Id.
|
||||
*/
|
||||
u8 * (*getSessionId)(struct eap_sm *sm, void *priv, size_t *len);
|
||||
};
|
||||
|
||||
/**
|
||||
* struct eap_sm - EAP server state machine data
|
||||
*/
|
||||
struct eap_sm {
|
||||
enum {
|
||||
EAP_DISABLED, EAP_INITIALIZE, EAP_IDLE, EAP_RECEIVED,
|
||||
EAP_INTEGRITY_CHECK, EAP_METHOD_RESPONSE, EAP_METHOD_REQUEST,
|
||||
EAP_PROPOSE_METHOD, EAP_SELECT_ACTION, EAP_SEND_REQUEST,
|
||||
EAP_DISCARD, EAP_NAK, EAP_RETRANSMIT, EAP_SUCCESS, EAP_FAILURE,
|
||||
EAP_TIMEOUT_FAILURE, EAP_PICK_UP_METHOD,
|
||||
EAP_INITIALIZE_PASSTHROUGH, EAP_IDLE2, EAP_RETRANSMIT2,
|
||||
EAP_RECEIVED2, EAP_DISCARD2, EAP_SEND_REQUEST2,
|
||||
EAP_AAA_REQUEST, EAP_AAA_RESPONSE, EAP_AAA_IDLE,
|
||||
EAP_TIMEOUT_FAILURE2, EAP_FAILURE2, EAP_SUCCESS2,
|
||||
EAP_INITIATE_REAUTH_START, EAP_INITIATE_RECEIVED
|
||||
} EAP_state;
|
||||
|
||||
/* Constants */
|
||||
int MaxRetrans;
|
||||
|
||||
struct eap_eapol_interface eap_if;
|
||||
|
||||
/* Full authenticator state machine local variables */
|
||||
|
||||
/* Long-term (maintained between packets) */
|
||||
enum eap_type currentMethod;
|
||||
int currentId;
|
||||
enum {
|
||||
METHOD_PROPOSED, METHOD_CONTINUE, METHOD_END
|
||||
} methodState;
|
||||
int retransCount;
|
||||
struct wpabuf *lastReqData;
|
||||
int methodTimeout;
|
||||
|
||||
/* Short-term (not maintained between packets) */
|
||||
bool rxResp;
|
||||
bool rxInitiate;
|
||||
int respId;
|
||||
enum eap_type respMethod;
|
||||
int respVendor;
|
||||
u32 respVendorMethod;
|
||||
bool ignore;
|
||||
enum {
|
||||
DECISION_SUCCESS, DECISION_FAILURE, DECISION_CONTINUE,
|
||||
DECISION_PASSTHROUGH, DECISION_INITIATE_REAUTH_START
|
||||
} decision;
|
||||
|
||||
/* Miscellaneous variables */
|
||||
const struct eap_method *m; /* selected EAP method */
|
||||
/* not defined in RFC 4137 */
|
||||
bool changed;
|
||||
void *eapol_ctx;
|
||||
const struct eapol_callbacks *eapol_cb;
|
||||
void *eap_method_priv;
|
||||
u8 *identity;
|
||||
size_t identity_len;
|
||||
char *serial_num;
|
||||
char imsi[20];
|
||||
/* Whether Phase 2 method should validate identity match */
|
||||
int require_identity_match;
|
||||
int lastId; /* Identifier used in the last EAP-Packet */
|
||||
struct eap_user *user;
|
||||
int user_eap_method_index;
|
||||
int init_phase2;
|
||||
const struct eap_config *cfg;
|
||||
struct eap_config cfg_buf;
|
||||
bool update_user;
|
||||
|
||||
unsigned int num_rounds;
|
||||
unsigned int num_rounds_short;
|
||||
enum {
|
||||
METHOD_PENDING_NONE, METHOD_PENDING_WAIT, METHOD_PENDING_CONT
|
||||
} method_pending;
|
||||
|
||||
u8 *auth_challenge;
|
||||
u8 *peer_challenge;
|
||||
|
||||
struct wpabuf *assoc_wps_ie;
|
||||
struct wpabuf *assoc_p2p_ie;
|
||||
|
||||
bool start_reauth;
|
||||
|
||||
u8 peer_addr[ETH_ALEN];
|
||||
|
||||
bool initiate_reauth_start_sent;
|
||||
bool try_initiate_reauth;
|
||||
|
||||
#ifdef CONFIG_TESTING_OPTIONS
|
||||
u32 tls_test_flags;
|
||||
#endif /* CONFIG_TESTING_OPTIONS */
|
||||
};
|
||||
|
||||
int eap_user_get(struct eap_sm *sm, const u8 *identity, size_t identity_len,
|
||||
int phase2);
|
||||
void eap_log_msg(struct eap_sm *sm, const char *fmt, ...)
|
||||
PRINTF_FORMAT(2, 3);
|
||||
void eap_sm_process_nak(struct eap_sm *sm, const u8 *nak_list, size_t len);
|
||||
|
||||
#endif /* EAP_I_H */
|
52
components/wpa_supplicant/src/eap_server/eap_methods.h
Normal file
52
components/wpa_supplicant/src/eap_server/eap_methods.h
Normal file
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* EAP server method registration
|
||||
* Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef EAP_SERVER_METHODS_H
|
||||
#define EAP_SERVER_METHODS_H
|
||||
|
||||
#include "eap_peer/eap_defs.h"
|
||||
|
||||
const struct eap_method * eap_server_get_eap_method(int vendor,
|
||||
enum eap_type method);
|
||||
struct eap_method * eap_server_method_alloc(int version, int vendor,
|
||||
enum eap_type method,
|
||||
const char *name);
|
||||
int eap_server_method_register(struct eap_method *method);
|
||||
|
||||
enum eap_type eap_server_get_type(const char *name, int *vendor);
|
||||
void eap_server_unregister_methods(void);
|
||||
const char * eap_server_get_name(int vendor, enum eap_type type);
|
||||
|
||||
/* EAP server method registration calls for statically linked in methods */
|
||||
int eap_server_identity_register(void);
|
||||
int eap_server_md5_register(void);
|
||||
int eap_server_tls_register(void);
|
||||
int eap_server_unauth_tls_register(void);
|
||||
int eap_server_wfa_unauth_tls_register(void);
|
||||
int eap_server_mschapv2_register(void);
|
||||
int eap_server_peap_register(void);
|
||||
int eap_server_tlv_register(void);
|
||||
int eap_server_gtc_register(void);
|
||||
int eap_server_ttls_register(void);
|
||||
int eap_server_sim_register(void);
|
||||
int eap_server_aka_register(void);
|
||||
int eap_server_aka_prime_register(void);
|
||||
int eap_server_pax_register(void);
|
||||
int eap_server_psk_register(void);
|
||||
int eap_server_sake_register(void);
|
||||
int eap_server_gpsk_register(void);
|
||||
int eap_server_vendor_test_register(void);
|
||||
int eap_server_fast_register(void);
|
||||
int eap_server_teap_register(void);
|
||||
int eap_server_wsc_register(void);
|
||||
int eap_server_ikev2_register(void);
|
||||
int eap_server_tnc_register(void);
|
||||
int eap_server_pwd_register(void);
|
||||
int eap_server_eke_register(void);
|
||||
|
||||
#endif /* EAP_SERVER_METHODS_H */
|
2118
components/wpa_supplicant/src/eap_server/eap_server.c
Normal file
2118
components/wpa_supplicant/src/eap_server/eap_server.c
Normal file
File diff suppressed because it is too large
Load Diff
177
components/wpa_supplicant/src/eap_server/eap_server_identity.c
Normal file
177
components/wpa_supplicant/src/eap_server/eap_server_identity.c
Normal file
@@ -0,0 +1,177 @@
|
||||
/*
|
||||
* hostapd / EAP-Identity
|
||||
* Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "eap_i.h"
|
||||
|
||||
|
||||
struct eap_identity_data {
|
||||
enum { CONTINUE, SUCCESS, FAILURE } state;
|
||||
int pick_up;
|
||||
};
|
||||
|
||||
|
||||
static void * eap_identity_init(struct eap_sm *sm)
|
||||
{
|
||||
struct eap_identity_data *data;
|
||||
|
||||
data = os_zalloc(sizeof(*data));
|
||||
if (data == NULL)
|
||||
return NULL;
|
||||
data->state = CONTINUE;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
static void * eap_identity_initPickUp(struct eap_sm *sm)
|
||||
{
|
||||
struct eap_identity_data *data;
|
||||
data = eap_identity_init(sm);
|
||||
if (data) {
|
||||
data->pick_up = 1;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
static void eap_identity_reset(struct eap_sm *sm, void *priv)
|
||||
{
|
||||
struct eap_identity_data *data = priv;
|
||||
os_free(data);
|
||||
}
|
||||
|
||||
|
||||
static struct wpabuf * eap_identity_buildReq(struct eap_sm *sm, void *priv,
|
||||
u8 id)
|
||||
{
|
||||
struct eap_identity_data *data = priv;
|
||||
struct wpabuf *req;
|
||||
const char *req_data;
|
||||
size_t req_data_len;
|
||||
|
||||
if (sm->eapol_cb->get_eap_req_id_text) {
|
||||
req_data = sm->eapol_cb->get_eap_req_id_text(sm->eapol_ctx,
|
||||
&req_data_len);
|
||||
} else {
|
||||
req_data = NULL;
|
||||
req_data_len = 0;
|
||||
}
|
||||
req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_IDENTITY, req_data_len,
|
||||
EAP_CODE_REQUEST, id);
|
||||
if (req == NULL) {
|
||||
wpa_printf(MSG_ERROR, "EAP-Identity: Failed to allocate "
|
||||
"memory for request");
|
||||
data->state = FAILURE;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
wpabuf_put_data(req, req_data, req_data_len);
|
||||
|
||||
return req;
|
||||
}
|
||||
|
||||
|
||||
static bool eap_identity_check(struct eap_sm *sm, void *priv,
|
||||
struct wpabuf *respData)
|
||||
{
|
||||
const u8 *pos;
|
||||
size_t len;
|
||||
|
||||
pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_IDENTITY,
|
||||
respData, &len);
|
||||
if (pos == NULL) {
|
||||
wpa_printf(MSG_INFO, "EAP-Identity: Invalid frame");
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
static void eap_identity_process(struct eap_sm *sm, void *priv,
|
||||
struct wpabuf *respData)
|
||||
{
|
||||
struct eap_identity_data *data = priv;
|
||||
const u8 *pos;
|
||||
size_t len;
|
||||
char *buf;
|
||||
|
||||
if (data->pick_up) {
|
||||
if (eap_identity_check(sm, data, respData)) {
|
||||
wpa_printf(MSG_DEBUG, "EAP-Identity: failed to pick "
|
||||
"up already started negotiation");
|
||||
data->state = FAILURE;
|
||||
return;
|
||||
}
|
||||
data->pick_up = 0;
|
||||
}
|
||||
|
||||
pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_IDENTITY,
|
||||
respData, &len);
|
||||
if (pos == NULL)
|
||||
return; /* Should not happen - frame already validated */
|
||||
|
||||
wpa_hexdump_ascii(MSG_DEBUG, "EAP-Identity: Peer identity", pos, len);
|
||||
buf = os_malloc(len * 4 + 1);
|
||||
if (buf) {
|
||||
printf_encode(buf, len * 4 + 1, pos, len);
|
||||
wpa_printf(MSG_DEBUG, "EAP-Response/Identity '%s'", buf);
|
||||
os_free(buf);
|
||||
}
|
||||
if (sm->identity)
|
||||
sm->update_user = true;
|
||||
os_free(sm->identity);
|
||||
sm->identity = os_malloc(len ? len : 1);
|
||||
if (sm->identity == NULL) {
|
||||
data->state = FAILURE;
|
||||
} else {
|
||||
os_memcpy(sm->identity, pos, len);
|
||||
sm->identity_len = len;
|
||||
data->state = SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static bool eap_identity_isDone(struct eap_sm *sm, void *priv)
|
||||
{
|
||||
struct eap_identity_data *data = priv;
|
||||
return data->state != CONTINUE;
|
||||
}
|
||||
|
||||
|
||||
static bool eap_identity_isSuccess(struct eap_sm *sm, void *priv)
|
||||
{
|
||||
struct eap_identity_data *data = priv;
|
||||
return data->state == SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
int eap_server_identity_register(void)
|
||||
{
|
||||
struct eap_method *eap;
|
||||
|
||||
eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION,
|
||||
EAP_VENDOR_IETF, EAP_TYPE_IDENTITY,
|
||||
"Identity");
|
||||
if (eap == NULL)
|
||||
return -1;
|
||||
|
||||
eap->init = eap_identity_init;
|
||||
eap->initPickUp = eap_identity_initPickUp;
|
||||
eap->reset = eap_identity_reset;
|
||||
eap->buildReq = eap_identity_buildReq;
|
||||
eap->check = eap_identity_check;
|
||||
eap->process = eap_identity_process;
|
||||
eap->isDone = eap_identity_isDone;
|
||||
eap->isSuccess = eap_identity_isSuccess;
|
||||
|
||||
return eap_server_method_register(eap);
|
||||
}
|
178
components/wpa_supplicant/src/eap_server/eap_server_methods.c
Normal file
178
components/wpa_supplicant/src/eap_server/eap_server_methods.c
Normal file
@@ -0,0 +1,178 @@
|
||||
/*
|
||||
* EAP server method registration
|
||||
* Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "eap_i.h"
|
||||
#include "eap_methods.h"
|
||||
|
||||
|
||||
static struct eap_method *eap_methods;
|
||||
|
||||
|
||||
/**
|
||||
* eap_server_get_eap_method - Get EAP method based on type number
|
||||
* @vendor: EAP Vendor-Id (0 = IETF)
|
||||
* @method: EAP type number
|
||||
* Returns: Pointer to EAP method or %NULL if not found
|
||||
*/
|
||||
const struct eap_method * eap_server_get_eap_method(int vendor,
|
||||
enum eap_type method)
|
||||
{
|
||||
struct eap_method *m;
|
||||
for (m = eap_methods; m; m = m->next) {
|
||||
if (m->vendor == vendor && m->method == method)
|
||||
return m;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* eap_server_get_type - Get EAP type for the given EAP method name
|
||||
* @name: EAP method name, e.g., TLS
|
||||
* @vendor: Buffer for returning EAP Vendor-Id
|
||||
* Returns: EAP method type or %EAP_TYPE_NONE if not found
|
||||
*
|
||||
* This function maps EAP type names into EAP type numbers based on the list of
|
||||
* EAP methods included in the build.
|
||||
*/
|
||||
enum eap_type eap_server_get_type(const char *name, int *vendor)
|
||||
{
|
||||
struct eap_method *m;
|
||||
for (m = eap_methods; m; m = m->next) {
|
||||
if (os_strcmp(m->name, name) == 0) {
|
||||
*vendor = m->vendor;
|
||||
return m->method;
|
||||
}
|
||||
}
|
||||
*vendor = EAP_VENDOR_IETF;
|
||||
return EAP_TYPE_NONE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* eap_server_method_alloc - Allocate EAP server method structure
|
||||
* @version: Version of the EAP server method interface (set to
|
||||
* EAP_SERVER_METHOD_INTERFACE_VERSION)
|
||||
* @vendor: EAP Vendor-ID (EAP_VENDOR_*) (0 = IETF)
|
||||
* @method: EAP type number (EAP_TYPE_*)
|
||||
* @name: Name of the method (e.g., "TLS")
|
||||
* Returns: Allocated EAP method structure or %NULL on failure
|
||||
*
|
||||
* The returned structure should be freed with eap_server_method_free() when it
|
||||
* is not needed anymore.
|
||||
*/
|
||||
struct eap_method * eap_server_method_alloc(int version, int vendor,
|
||||
enum eap_type method,
|
||||
const char *name)
|
||||
{
|
||||
struct eap_method *eap;
|
||||
eap = os_zalloc(sizeof(*eap));
|
||||
if (eap == NULL)
|
||||
return NULL;
|
||||
eap->version = version;
|
||||
eap->vendor = vendor;
|
||||
eap->method = method;
|
||||
eap->name = name;
|
||||
return eap;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* eap_server_method_free - Free EAP server method structure
|
||||
* @method: Method structure allocated with eap_server_method_alloc()
|
||||
*/
|
||||
static void eap_server_method_free(struct eap_method *method)
|
||||
{
|
||||
os_free(method);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* eap_server_method_register - Register an EAP server method
|
||||
* @method: EAP method to register from eap_server_method_alloc()
|
||||
* Returns: 0 on success, -1 on invalid method, or -2 if a matching EAP method
|
||||
* has already been registered
|
||||
*
|
||||
* Each EAP server method needs to call this function to register itself as a
|
||||
* supported EAP method. The caller must not free the allocated method data
|
||||
* regardless of the return value.
|
||||
*/
|
||||
int eap_server_method_register(struct eap_method *method)
|
||||
{
|
||||
struct eap_method *m, *last = NULL;
|
||||
|
||||
if (method == NULL || method->name == NULL ||
|
||||
method->version != EAP_SERVER_METHOD_INTERFACE_VERSION) {
|
||||
eap_server_method_free(method);
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (m = eap_methods; m; m = m->next) {
|
||||
if ((m->vendor == method->vendor &&
|
||||
m->method == method->method) ||
|
||||
os_strcmp(m->name, method->name) == 0) {
|
||||
eap_server_method_free(method);
|
||||
return -2;
|
||||
}
|
||||
last = m;
|
||||
}
|
||||
|
||||
if (last)
|
||||
last->next = method;
|
||||
else
|
||||
eap_methods = method;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* eap_server_unregister_methods - Unregister EAP server methods
|
||||
*
|
||||
* This function is called at program termination to unregister all EAP server
|
||||
* methods.
|
||||
*/
|
||||
void eap_server_unregister_methods(void)
|
||||
{
|
||||
struct eap_method *m;
|
||||
|
||||
while (eap_methods) {
|
||||
m = eap_methods;
|
||||
eap_methods = eap_methods->next;
|
||||
|
||||
if (m->free)
|
||||
m->free(m);
|
||||
else
|
||||
eap_server_method_free(m);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* eap_server_get_name - Get EAP method name for the given EAP type
|
||||
* @vendor: EAP Vendor-Id (0 = IETF)
|
||||
* @type: EAP method type
|
||||
* Returns: EAP method name, e.g., TLS, or "unknown" if not found
|
||||
*
|
||||
* This function maps EAP type numbers into EAP type names based on the list of
|
||||
* EAP methods included in the build.
|
||||
*/
|
||||
const char * eap_server_get_name(int vendor, enum eap_type type)
|
||||
{
|
||||
struct eap_method *m;
|
||||
if (vendor == EAP_VENDOR_IETF && type == EAP_TYPE_EXPANDED)
|
||||
return "expanded";
|
||||
for (m = eap_methods; m; m = m->next) {
|
||||
if (m->vendor == vendor && m->method == type)
|
||||
return m->name;
|
||||
}
|
||||
return "unknown";
|
||||
}
|
450
components/wpa_supplicant/src/eap_server/eap_server_wsc.c
Normal file
450
components/wpa_supplicant/src/eap_server/eap_server_wsc.c
Normal file
@@ -0,0 +1,450 @@
|
||||
/*
|
||||
* EAP-WSC server for Wi-Fi Protected Setup
|
||||
* Copyright (c) 2007-2008, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "eloop.h"
|
||||
#include "eap_i.h"
|
||||
#include "eap_common/eap_wsc_common.h"
|
||||
#include "wps/wps.h"
|
||||
#include "esp_wps_i.h"
|
||||
|
||||
|
||||
struct eap_wsc_data {
|
||||
enum { START, MESG, FRAG_ACK, WAIT_FRAG_ACK, DONE, WSC_FAIL } state;
|
||||
int registrar;
|
||||
struct wpabuf *in_buf;
|
||||
struct wpabuf *out_buf;
|
||||
enum wsc_op_code in_op_code, out_op_code;
|
||||
size_t out_used;
|
||||
size_t fragment_size;
|
||||
struct wps_data *wps;
|
||||
int ext_reg_timeout;
|
||||
};
|
||||
|
||||
#ifdef DEBUG_PRINT
|
||||
static const char * eap_wsc_state_txt(int state)
|
||||
{
|
||||
switch (state) {
|
||||
case START:
|
||||
return "START";
|
||||
case MESG:
|
||||
return "MESG";
|
||||
case FRAG_ACK:
|
||||
return "FRAG_ACK";
|
||||
case WAIT_FRAG_ACK:
|
||||
return "WAIT_FRAG_ACK";
|
||||
case DONE:
|
||||
return "DONE";
|
||||
case WSC_FAIL:
|
||||
return "FAIL";
|
||||
default:
|
||||
return "?";
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static void eap_wsc_state(struct eap_wsc_data *data, int state)
|
||||
{
|
||||
wpa_printf(MSG_DEBUG, "EAP-WSC: %s -> %s",
|
||||
eap_wsc_state_txt(data->state),
|
||||
eap_wsc_state_txt(state));
|
||||
data->state = state;
|
||||
}
|
||||
|
||||
|
||||
static void * eap_wsc_init(struct eap_sm *sm)
|
||||
{
|
||||
struct eap_wsc_data *data;
|
||||
int registrar;
|
||||
|
||||
if (sm->identity && sm->identity_len == WSC_ID_REGISTRAR_LEN &&
|
||||
os_memcmp(sm->identity, WSC_ID_REGISTRAR, WSC_ID_REGISTRAR_LEN) ==
|
||||
0)
|
||||
registrar = 0; /* Supplicant is Registrar */
|
||||
else if (sm->identity && sm->identity_len == WSC_ID_ENROLLEE_LEN &&
|
||||
os_memcmp(sm->identity, WSC_ID_ENROLLEE, WSC_ID_ENROLLEE_LEN)
|
||||
== 0)
|
||||
registrar = 1; /* Supplicant is Enrollee */
|
||||
else {
|
||||
wpa_hexdump_ascii(MSG_INFO, "EAP-WSC: Unexpected identity",
|
||||
sm->identity, sm->identity_len);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
data = os_zalloc(sizeof(*data));
|
||||
if (data == NULL)
|
||||
return NULL;
|
||||
data->state = registrar ? START : MESG;
|
||||
data->registrar = registrar;
|
||||
|
||||
struct wps_sm *wps_sm = wps_sm_get();
|
||||
data->wps = wps_sm->wps;
|
||||
if (data->wps == NULL) {
|
||||
os_free(data);
|
||||
return NULL;
|
||||
}
|
||||
data->fragment_size = WSC_FRAGMENT_SIZE;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
static void eap_wsc_reset(struct eap_sm *sm, void *priv)
|
||||
{
|
||||
struct eap_wsc_data *data = priv;
|
||||
wpabuf_free(data->in_buf);
|
||||
wpabuf_free(data->out_buf);
|
||||
wps_deinit(data->wps);
|
||||
os_free(data);
|
||||
}
|
||||
|
||||
|
||||
static struct wpabuf * eap_wsc_build_start(struct eap_sm *sm,
|
||||
struct eap_wsc_data *data, u8 id)
|
||||
{
|
||||
struct wpabuf *req;
|
||||
|
||||
req = eap_msg_alloc(EAP_VENDOR_WFA, EAP_VENDOR_TYPE_WSC, 2,
|
||||
EAP_CODE_REQUEST, id);
|
||||
if (req == NULL) {
|
||||
wpa_printf(MSG_ERROR, "EAP-WSC: Failed to allocate memory for "
|
||||
"request");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
wpa_printf(MSG_DEBUG, "EAP-WSC: Send WSC/Start");
|
||||
wpabuf_put_u8(req, WSC_Start); /* Op-Code */
|
||||
wpabuf_put_u8(req, 0); /* Flags */
|
||||
|
||||
return req;
|
||||
}
|
||||
|
||||
|
||||
static struct wpabuf * eap_wsc_build_msg(struct eap_wsc_data *data, u8 id)
|
||||
{
|
||||
struct wpabuf *req;
|
||||
u8 flags;
|
||||
size_t send_len, plen;
|
||||
|
||||
flags = 0;
|
||||
send_len = wpabuf_len(data->out_buf) - data->out_used;
|
||||
if (2 + send_len > data->fragment_size) {
|
||||
send_len = data->fragment_size - 2;
|
||||
flags |= WSC_FLAGS_MF;
|
||||
if (data->out_used == 0) {
|
||||
flags |= WSC_FLAGS_LF;
|
||||
send_len -= 2;
|
||||
}
|
||||
}
|
||||
plen = 2 + send_len;
|
||||
if (flags & WSC_FLAGS_LF)
|
||||
plen += 2;
|
||||
req = eap_msg_alloc(EAP_VENDOR_WFA, EAP_VENDOR_TYPE_WSC, plen,
|
||||
EAP_CODE_REQUEST, id);
|
||||
if (req == NULL) {
|
||||
wpa_printf(MSG_ERROR, "EAP-WSC: Failed to allocate memory for "
|
||||
"request");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
wpabuf_put_u8(req, data->out_op_code); /* Op-Code */
|
||||
wpabuf_put_u8(req, flags); /* Flags */
|
||||
if (flags & WSC_FLAGS_LF)
|
||||
wpabuf_put_be16(req, wpabuf_len(data->out_buf));
|
||||
|
||||
wpabuf_put_data(req, wpabuf_head_u8(data->out_buf) + data->out_used,
|
||||
send_len);
|
||||
data->out_used += send_len;
|
||||
|
||||
if (data->out_used == wpabuf_len(data->out_buf)) {
|
||||
wpa_printf(MSG_DEBUG, "EAP-WSC: Sending out %lu bytes "
|
||||
"(message sent completely)",
|
||||
(unsigned long) send_len);
|
||||
wpabuf_free(data->out_buf);
|
||||
data->out_buf = NULL;
|
||||
data->out_used = 0;
|
||||
eap_wsc_state(data, MESG);
|
||||
} else {
|
||||
wpa_printf(MSG_DEBUG, "EAP-WSC: Sending out %lu bytes "
|
||||
"(%lu more to send)", (unsigned long) send_len,
|
||||
(unsigned long) wpabuf_len(data->out_buf) -
|
||||
data->out_used);
|
||||
eap_wsc_state(data, WAIT_FRAG_ACK);
|
||||
}
|
||||
|
||||
return req;
|
||||
}
|
||||
|
||||
|
||||
static struct wpabuf * eap_wsc_buildReq(struct eap_sm *sm, void *priv, u8 id)
|
||||
{
|
||||
struct eap_wsc_data *data = priv;
|
||||
|
||||
switch (data->state) {
|
||||
case START:
|
||||
return eap_wsc_build_start(sm, data, id);
|
||||
case MESG:
|
||||
if (data->out_buf == NULL) {
|
||||
data->out_buf = wps_get_msg(data->wps,
|
||||
&data->out_op_code);
|
||||
if (data->out_buf == NULL) {
|
||||
wpa_printf(MSG_DEBUG, "EAP-WSC: Failed to "
|
||||
"receive message from WPS");
|
||||
return NULL;
|
||||
}
|
||||
data->out_used = 0;
|
||||
}
|
||||
/* fall through */
|
||||
case WAIT_FRAG_ACK:
|
||||
return eap_wsc_build_msg(data, id);
|
||||
case FRAG_ACK:
|
||||
return eap_wsc_build_frag_ack(id, EAP_CODE_REQUEST);
|
||||
default:
|
||||
wpa_printf(MSG_DEBUG, "EAP-WSC: Unexpected state %d in "
|
||||
"buildReq", data->state);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static bool eap_wsc_check(struct eap_sm *sm, void *priv,
|
||||
struct wpabuf *respData)
|
||||
{
|
||||
const u8 *pos;
|
||||
size_t len;
|
||||
|
||||
pos = eap_hdr_validate(EAP_VENDOR_WFA, EAP_VENDOR_TYPE_WSC,
|
||||
respData, &len);
|
||||
if (pos == NULL || len < 2) {
|
||||
wpa_printf(MSG_INFO, "EAP-WSC: Invalid frame");
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
static int eap_wsc_process_cont(struct eap_wsc_data *data,
|
||||
const u8 *buf, size_t len, u8 op_code)
|
||||
{
|
||||
/* Process continuation of a pending message */
|
||||
if (op_code != data->in_op_code) {
|
||||
wpa_printf(MSG_DEBUG, "EAP-WSC: Unexpected Op-Code %d in "
|
||||
"fragment (expected %d)",
|
||||
op_code, data->in_op_code);
|
||||
eap_wsc_state(data, WSC_FAIL);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (len > wpabuf_tailroom(data->in_buf)) {
|
||||
wpa_printf(MSG_DEBUG, "EAP-WSC: Fragment overflow");
|
||||
eap_wsc_state(data, WSC_FAIL);
|
||||
return -1;
|
||||
}
|
||||
|
||||
wpabuf_put_data(data->in_buf, buf, len);
|
||||
wpa_printf(MSG_DEBUG, "EAP-WSC: Received %lu bytes, waiting for %lu "
|
||||
"bytes more", (unsigned long) len,
|
||||
(unsigned long) wpabuf_tailroom(data->in_buf));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int eap_wsc_process_fragment(struct eap_wsc_data *data,
|
||||
u8 flags, u8 op_code, u16 message_length,
|
||||
const u8 *buf, size_t len)
|
||||
{
|
||||
/* Process a fragment that is not the last one of the message */
|
||||
if (data->in_buf == NULL && !(flags & WSC_FLAGS_LF)) {
|
||||
wpa_printf(MSG_DEBUG, "EAP-WSC: No Message Length "
|
||||
"field in a fragmented packet");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (data->in_buf == NULL) {
|
||||
/* First fragment of the message */
|
||||
data->in_buf = wpabuf_alloc(message_length);
|
||||
if (data->in_buf == NULL) {
|
||||
wpa_printf(MSG_DEBUG, "EAP-WSC: No memory for "
|
||||
"message");
|
||||
return -1;
|
||||
}
|
||||
data->in_op_code = op_code;
|
||||
wpabuf_put_data(data->in_buf, buf, len);
|
||||
wpa_printf(MSG_DEBUG, "EAP-WSC: Received %lu bytes in "
|
||||
"first fragment, waiting for %lu bytes more",
|
||||
(unsigned long) len,
|
||||
(unsigned long) wpabuf_tailroom(data->in_buf));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void eap_wsc_process(struct eap_sm *sm, void *priv,
|
||||
struct wpabuf *respData)
|
||||
{
|
||||
struct eap_wsc_data *data = priv;
|
||||
const u8 *start, *pos, *end;
|
||||
size_t len;
|
||||
u8 op_code, flags;
|
||||
u16 message_length = 0;
|
||||
enum wps_process_res res;
|
||||
struct wpabuf tmpbuf;
|
||||
|
||||
if (data->ext_reg_timeout) {
|
||||
eap_wsc_state(data, WSC_FAIL);
|
||||
return;
|
||||
}
|
||||
|
||||
pos = eap_hdr_validate(EAP_VENDOR_WFA, EAP_VENDOR_TYPE_WSC,
|
||||
respData, &len);
|
||||
if (pos == NULL || len < 2)
|
||||
return; /* Should not happen; message already verified */
|
||||
|
||||
start = pos;
|
||||
end = start + len;
|
||||
|
||||
op_code = *pos++;
|
||||
flags = *pos++;
|
||||
if (flags & WSC_FLAGS_LF) {
|
||||
if (end - pos < 2) {
|
||||
wpa_printf(MSG_DEBUG, "EAP-WSC: Message underflow");
|
||||
return;
|
||||
}
|
||||
message_length = WPA_GET_BE16(pos);
|
||||
pos += 2;
|
||||
|
||||
if (message_length < end - pos || message_length > 50000) {
|
||||
wpa_printf(MSG_DEBUG, "EAP-WSC: Invalid Message "
|
||||
"Length");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
wpa_printf(MSG_DEBUG, "EAP-WSC: Received packet: Op-Code %d "
|
||||
"Flags 0x%x Message Length %d",
|
||||
op_code, flags, message_length);
|
||||
|
||||
if (data->state == WAIT_FRAG_ACK) {
|
||||
if (op_code != WSC_FRAG_ACK) {
|
||||
wpa_printf(MSG_DEBUG, "EAP-WSC: Unexpected Op-Code %d "
|
||||
"in WAIT_FRAG_ACK state", op_code);
|
||||
eap_wsc_state(data, WSC_FAIL);
|
||||
return;
|
||||
}
|
||||
wpa_printf(MSG_DEBUG, "EAP-WSC: Fragment acknowledged");
|
||||
eap_wsc_state(data, MESG);
|
||||
return;
|
||||
}
|
||||
|
||||
if (op_code != WSC_ACK && op_code != WSC_NACK && op_code != WSC_MSG &&
|
||||
op_code != WSC_Done) {
|
||||
wpa_printf(MSG_DEBUG, "EAP-WSC: Unexpected Op-Code %d",
|
||||
op_code);
|
||||
eap_wsc_state(data, WSC_FAIL);
|
||||
return;
|
||||
}
|
||||
|
||||
if (data->in_buf &&
|
||||
eap_wsc_process_cont(data, pos, end - pos, op_code) < 0) {
|
||||
eap_wsc_state(data, WSC_FAIL);
|
||||
return;
|
||||
}
|
||||
|
||||
if (flags & WSC_FLAGS_MF) {
|
||||
if (eap_wsc_process_fragment(data, flags, op_code,
|
||||
message_length, pos, end - pos) <
|
||||
0)
|
||||
eap_wsc_state(data, WSC_FAIL);
|
||||
else
|
||||
eap_wsc_state(data, FRAG_ACK);
|
||||
return;
|
||||
}
|
||||
|
||||
if (data->in_buf == NULL) {
|
||||
/* Wrap unfragmented messages as wpabuf without extra copy */
|
||||
wpabuf_set(&tmpbuf, pos, end - pos);
|
||||
data->in_buf = &tmpbuf;
|
||||
}
|
||||
|
||||
res = wps_process_msg(data->wps, op_code, data->in_buf);
|
||||
switch (res) {
|
||||
case WPS_DONE:
|
||||
wpa_printf(MSG_DEBUG, "EAP-WSC: WPS processing completed "
|
||||
"successfully - report EAP failure");
|
||||
eap_wsc_state(data, WSC_FAIL);
|
||||
break;
|
||||
case WPS_CONTINUE:
|
||||
eap_wsc_state(data, MESG);
|
||||
break;
|
||||
case WPS_FAILURE:
|
||||
wpa_printf(MSG_DEBUG, "EAP-WSC: WPS processing failed");
|
||||
eap_wsc_state(data, WSC_FAIL);
|
||||
break;
|
||||
case WPS_PENDING:
|
||||
eap_wsc_state(data, MESG);
|
||||
sm->method_pending = METHOD_PENDING_WAIT;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (data->in_buf != &tmpbuf)
|
||||
wpabuf_free(data->in_buf);
|
||||
data->in_buf = NULL;
|
||||
}
|
||||
|
||||
|
||||
static bool eap_wsc_isDone(struct eap_sm *sm, void *priv)
|
||||
{
|
||||
struct eap_wsc_data *data = priv;
|
||||
return data->state == WSC_FAIL;
|
||||
}
|
||||
|
||||
|
||||
static bool eap_wsc_isSuccess(struct eap_sm *sm, void *priv)
|
||||
{
|
||||
/* EAP-WSC will always result in EAP-Failure */
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
static int eap_wsc_getTimeout(struct eap_sm *sm, void *priv)
|
||||
{
|
||||
/* Recommended retransmit times: retransmit timeout 5 seconds,
|
||||
* per-message timeout 15 seconds, i.e., 3 tries. */
|
||||
sm->MaxRetrans = 2; /* total 3 attempts */
|
||||
return 5;
|
||||
}
|
||||
|
||||
|
||||
int eap_server_wsc_register(void)
|
||||
{
|
||||
struct eap_method *eap;
|
||||
|
||||
eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION,
|
||||
EAP_VENDOR_WFA, EAP_VENDOR_TYPE_WSC,
|
||||
"WSC");
|
||||
if (eap == NULL)
|
||||
return -1;
|
||||
|
||||
eap->init = eap_wsc_init;
|
||||
eap->reset = eap_wsc_reset;
|
||||
eap->buildReq = eap_wsc_buildReq;
|
||||
eap->check = eap_wsc_check;
|
||||
eap->process = eap_wsc_process;
|
||||
eap->isDone = eap_wsc_isDone;
|
||||
eap->isSuccess = eap_wsc_isSuccess;
|
||||
eap->getTimeout = eap_wsc_getTimeout;
|
||||
|
||||
return eap_server_method_register(eap);
|
||||
}
|
1266
components/wpa_supplicant/src/eapol_auth/eapol_auth_sm.c
Normal file
1266
components/wpa_supplicant/src/eapol_auth/eapol_auth_sm.c
Normal file
File diff suppressed because it is too large
Load Diff
82
components/wpa_supplicant/src/eapol_auth/eapol_auth_sm.h
Normal file
82
components/wpa_supplicant/src/eapol_auth/eapol_auth_sm.h
Normal file
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* IEEE 802.1X-2004 Authenticator - EAPOL state machine
|
||||
* Copyright (c) 2002-2015, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef EAPOL_AUTH_SM_H
|
||||
#define EAPOL_AUTH_SM_H
|
||||
|
||||
#define EAPOL_SM_PREAUTH BIT(0)
|
||||
#define EAPOL_SM_WAIT_START BIT(1)
|
||||
#define EAPOL_SM_USES_WPA BIT(2)
|
||||
#define EAPOL_SM_FROM_PMKSA_CACHE BIT(3)
|
||||
|
||||
struct eapol_auth_config {
|
||||
const struct eap_config *eap_cfg;
|
||||
int eap_reauth_period;
|
||||
int wpa;
|
||||
int individual_wep_key_len;
|
||||
char *eap_req_id_text; /* a copy of this will be allocated */
|
||||
size_t eap_req_id_text_len;
|
||||
int erp_send_reauth_start;
|
||||
char *erp_domain; /* a copy of this will be allocated */
|
||||
|
||||
/* Opaque context pointer to owner data for callback functions */
|
||||
void *ctx;
|
||||
};
|
||||
|
||||
struct eap_user;
|
||||
struct eap_server_erp_key;
|
||||
|
||||
typedef enum {
|
||||
EAPOL_LOGGER_DEBUG, EAPOL_LOGGER_INFO, EAPOL_LOGGER_WARNING
|
||||
} eapol_logger_level;
|
||||
|
||||
enum eapol_event {
|
||||
EAPOL_AUTH_SM_CHANGE,
|
||||
EAPOL_AUTH_REAUTHENTICATE
|
||||
};
|
||||
|
||||
struct eapol_auth_cb {
|
||||
void (*eapol_send)(void *ctx, void *sta_ctx, u8 type, const u8 *data,
|
||||
size_t datalen);
|
||||
void (*aaa_send)(void *ctx, void *sta_ctx, const u8 *data,
|
||||
size_t datalen);
|
||||
void (*finished)(void *ctx, void *sta_ctx, int success, int preauth,
|
||||
int remediation);
|
||||
int (*get_eap_user)(void *ctx, const u8 *identity, size_t identity_len,
|
||||
int phase2, struct eap_user *user);
|
||||
int (*sta_entry_alive)(void *ctx, const u8 *addr);
|
||||
void (*logger)(void *ctx, const u8 *addr, eapol_logger_level level,
|
||||
const char *txt);
|
||||
void (*set_port_authorized)(void *ctx, void *sta_ctx, int authorized);
|
||||
void (*abort_auth)(void *ctx, void *sta_ctx);
|
||||
void (*tx_key)(void *ctx, void *sta_ctx);
|
||||
void (*eapol_event)(void *ctx, void *sta_ctx, enum eapol_event type);
|
||||
struct eap_server_erp_key * (*erp_get_key)(void *ctx,
|
||||
const char *keyname);
|
||||
int (*erp_add_key)(void *ctx, struct eap_server_erp_key *erp);
|
||||
};
|
||||
|
||||
|
||||
struct eapol_authenticator * eapol_auth_init(struct eapol_auth_config *conf,
|
||||
struct eapol_auth_cb *cb);
|
||||
void eapol_auth_deinit(struct eapol_authenticator *eapol);
|
||||
struct eapol_state_machine *
|
||||
eapol_auth_alloc(struct eapol_authenticator *eapol, const u8 *addr,
|
||||
int flags, const struct wpabuf *assoc_wps_ie,
|
||||
const struct wpabuf *assoc_p2p_ie, void *sta_ctx,
|
||||
const char *identity, const char *radius_cui);
|
||||
void eapol_auth_free(struct eapol_state_machine *sm);
|
||||
void eapol_auth_step(struct eapol_state_machine *sm);
|
||||
int eapol_auth_dump_state(struct eapol_state_machine *sm, char *buf,
|
||||
size_t buflen);
|
||||
int eapol_auth_eap_pending_cb(struct eapol_state_machine *sm, void *ctx);
|
||||
void eapol_auth_reauthenticate(struct eapol_state_machine *sm);
|
||||
int eapol_auth_set_conf(struct eapol_state_machine *sm, const char *param,
|
||||
const char *value);
|
||||
|
||||
#endif /* EAPOL_AUTH_SM_H */
|
176
components/wpa_supplicant/src/eapol_auth/eapol_auth_sm_i.h
Normal file
176
components/wpa_supplicant/src/eapol_auth/eapol_auth_sm_i.h
Normal file
@@ -0,0 +1,176 @@
|
||||
/*
|
||||
* IEEE 802.1X-2004 Authenticator - EAPOL state machine (internal definitions)
|
||||
* Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef EAPOL_AUTH_SM_I_H
|
||||
#define EAPOL_AUTH_SM_I_H
|
||||
|
||||
#include "common/defs.h"
|
||||
|
||||
/* IEEE Std 802.1X-2004, Ch. 8.2 */
|
||||
|
||||
typedef enum { ForceUnauthorized = 1, ForceAuthorized = 3, Auto = 2 }
|
||||
PortTypes;
|
||||
typedef enum { Unauthorized = 2, Authorized = 1 } PortState;
|
||||
typedef enum { Both = 0, In = 1 } ControlledDirection;
|
||||
typedef unsigned int Counter;
|
||||
|
||||
|
||||
/**
|
||||
* struct eapol_authenticator - Global EAPOL authenticator data
|
||||
*/
|
||||
struct eapol_authenticator {
|
||||
struct eapol_auth_config conf;
|
||||
struct eapol_auth_cb cb;
|
||||
|
||||
u8 *default_wep_key;
|
||||
u8 default_wep_key_idx;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* struct eapol_state_machine - Per-Supplicant Authenticator state machines
|
||||
*/
|
||||
struct eapol_state_machine {
|
||||
/* timers */
|
||||
int aWhile;
|
||||
int quietWhile;
|
||||
int reAuthWhen;
|
||||
|
||||
/* global variables */
|
||||
bool authAbort;
|
||||
bool authFail;
|
||||
PortState authPortStatus;
|
||||
bool authStart;
|
||||
bool authTimeout;
|
||||
bool authSuccess;
|
||||
bool eapolEap;
|
||||
bool initialize;
|
||||
bool keyDone;
|
||||
bool keyRun;
|
||||
bool keyTxEnabled;
|
||||
PortTypes portControl;
|
||||
bool portValid;
|
||||
bool reAuthenticate;
|
||||
|
||||
/* Port Timers state machine */
|
||||
/* 'bool tick' implicitly handled as registered timeout */
|
||||
|
||||
/* Authenticator PAE state machine */
|
||||
enum { AUTH_PAE_INITIALIZE, AUTH_PAE_DISCONNECTED, AUTH_PAE_CONNECTING,
|
||||
AUTH_PAE_AUTHENTICATING, AUTH_PAE_AUTHENTICATED,
|
||||
AUTH_PAE_ABORTING, AUTH_PAE_HELD, AUTH_PAE_FORCE_AUTH,
|
||||
AUTH_PAE_FORCE_UNAUTH, AUTH_PAE_RESTART } auth_pae_state;
|
||||
/* variables */
|
||||
bool eapolLogoff;
|
||||
bool eapolStart;
|
||||
PortTypes portMode;
|
||||
unsigned int reAuthCount;
|
||||
/* constants */
|
||||
unsigned int quietPeriod; /* default 60; 0..65535 */
|
||||
#define AUTH_PAE_DEFAULT_quietPeriod 60
|
||||
unsigned int reAuthMax; /* default 2 */
|
||||
#define AUTH_PAE_DEFAULT_reAuthMax 2
|
||||
/* counters */
|
||||
Counter authEntersConnecting;
|
||||
Counter authEapLogoffsWhileConnecting;
|
||||
Counter authEntersAuthenticating;
|
||||
Counter authAuthSuccessesWhileAuthenticating;
|
||||
Counter authAuthTimeoutsWhileAuthenticating;
|
||||
Counter authAuthFailWhileAuthenticating;
|
||||
Counter authAuthEapStartsWhileAuthenticating;
|
||||
Counter authAuthEapLogoffWhileAuthenticating;
|
||||
Counter authAuthReauthsWhileAuthenticated;
|
||||
Counter authAuthEapStartsWhileAuthenticated;
|
||||
Counter authAuthEapLogoffWhileAuthenticated;
|
||||
|
||||
/* Backend Authentication state machine */
|
||||
enum { BE_AUTH_REQUEST, BE_AUTH_RESPONSE, BE_AUTH_SUCCESS,
|
||||
BE_AUTH_FAIL, BE_AUTH_TIMEOUT, BE_AUTH_IDLE, BE_AUTH_INITIALIZE,
|
||||
BE_AUTH_IGNORE
|
||||
} be_auth_state;
|
||||
/* constants */
|
||||
unsigned int serverTimeout; /* default 30; 1..X */
|
||||
#define BE_AUTH_DEFAULT_serverTimeout 30
|
||||
/* counters */
|
||||
Counter backendResponses;
|
||||
Counter backendAccessChallenges;
|
||||
Counter backendOtherRequestsToSupplicant;
|
||||
Counter backendAuthSuccesses;
|
||||
Counter backendAuthFails;
|
||||
|
||||
/* Reauthentication Timer state machine */
|
||||
enum { REAUTH_TIMER_INITIALIZE, REAUTH_TIMER_REAUTHENTICATE
|
||||
} reauth_timer_state;
|
||||
/* constants */
|
||||
unsigned int reAuthPeriod; /* default 3600 s */
|
||||
bool reAuthEnabled;
|
||||
|
||||
/* Authenticator Key Transmit state machine */
|
||||
enum { AUTH_KEY_TX_NO_KEY_TRANSMIT, AUTH_KEY_TX_KEY_TRANSMIT
|
||||
} auth_key_tx_state;
|
||||
|
||||
/* Key Receive state machine */
|
||||
enum { KEY_RX_NO_KEY_RECEIVE, KEY_RX_KEY_RECEIVE } key_rx_state;
|
||||
/* variables */
|
||||
bool rxKey;
|
||||
|
||||
/* Controlled Directions state machine */
|
||||
enum { CTRL_DIR_FORCE_BOTH, CTRL_DIR_IN_OR_BOTH } ctrl_dir_state;
|
||||
/* variables */
|
||||
ControlledDirection adminControlledDirections;
|
||||
ControlledDirection operControlledDirections;
|
||||
bool operEdge;
|
||||
|
||||
/* Authenticator Statistics Table */
|
||||
Counter dot1xAuthEapolFramesRx;
|
||||
Counter dot1xAuthEapolFramesTx;
|
||||
Counter dot1xAuthEapolStartFramesRx;
|
||||
Counter dot1xAuthEapolLogoffFramesRx;
|
||||
Counter dot1xAuthEapolRespIdFramesRx;
|
||||
Counter dot1xAuthEapolRespFramesRx;
|
||||
Counter dot1xAuthEapolReqIdFramesTx;
|
||||
Counter dot1xAuthEapolReqFramesTx;
|
||||
Counter dot1xAuthInvalidEapolFramesRx;
|
||||
Counter dot1xAuthEapLengthErrorFramesRx;
|
||||
Counter dot1xAuthLastEapolFrameVersion;
|
||||
|
||||
/* Other variables - not defined in IEEE 802.1X */
|
||||
u8 addr[ETH_ALEN]; /* Supplicant address */
|
||||
int flags; /* EAPOL_SM_* */
|
||||
|
||||
/* EAPOL/AAA <-> EAP full authenticator interface */
|
||||
struct eap_eapol_interface *eap_if;
|
||||
|
||||
int radius_identifier;
|
||||
/* TODO: check when the last messages can be released */
|
||||
struct radius_msg *last_recv_radius;
|
||||
u8 last_eap_id; /* last used EAP Identifier */
|
||||
u8 *identity;
|
||||
size_t identity_len;
|
||||
u8 eap_type_authsrv; /* EAP type of the last EAP packet from
|
||||
* Authentication server */
|
||||
u8 eap_type_supp; /* EAP type of the last EAP packet from Supplicant */
|
||||
#ifndef CONFIG_NO_RADIUS
|
||||
struct wpabuf *radius_cui; /* Chargeable-User-Identity */
|
||||
#endif
|
||||
|
||||
struct eap_sm *eap;
|
||||
|
||||
bool initializing; /* in process of initializing state machines */
|
||||
bool changed;
|
||||
|
||||
struct eapol_authenticator *eapol;
|
||||
|
||||
void *sta; /* station context pointer to use in callbacks */
|
||||
|
||||
int remediation;
|
||||
|
||||
u64 acct_multi_session_id;
|
||||
};
|
||||
|
||||
#endif /* EAPOL_AUTH_SM_I_H */
|
@@ -49,7 +49,7 @@ struct wps_data * wps_init(const struct wps_config *cfg)
|
||||
os_memcpy(data->mac_addr_e, cfg->wps->dev.mac_addr, ETH_ALEN);
|
||||
os_memcpy(data->uuid_e, cfg->wps->uuid, WPS_UUID_LEN);
|
||||
}
|
||||
if (cfg->pin) {
|
||||
if (cfg->pbc == 0 && cfg->pin_len) {
|
||||
data->dev_pw_id = cfg->dev_pw_id;
|
||||
data->dev_password = os_memdup(cfg->pin, cfg->pin_len);
|
||||
if (data->dev_password == NULL) {
|
||||
@@ -226,10 +226,7 @@ enum wps_process_res wps_process_msg(struct wps_data *wps,
|
||||
*/
|
||||
struct wpabuf * wps_get_msg(struct wps_data *wps, enum wsc_op_code *op_code)
|
||||
{
|
||||
if (wps->registrar)
|
||||
return wps_registrar_get_msg(wps, op_code);
|
||||
else
|
||||
return wps_enrollee_get_msg(wps, op_code);
|
||||
}
|
||||
|
||||
|
||||
|
@@ -121,7 +121,7 @@ struct wps_config {
|
||||
/**
|
||||
* pin - Enrollee Device Password (%NULL for Registrar or PBC)
|
||||
*/
|
||||
const u8 *pin;
|
||||
const u8 pin[9];
|
||||
|
||||
/**
|
||||
* pin_len - Length on pin in octets
|
||||
@@ -132,7 +132,7 @@ struct wps_config {
|
||||
* pbc - Whether this is protocol run uses PBC
|
||||
*/
|
||||
int pbc;
|
||||
#ifndef ESP_SUPPLICANT
|
||||
#ifdef CONFIG_WPS_REGISTRAR
|
||||
/**
|
||||
* assoc_wps_ie: (Re)AssocReq WPS IE (in AP; %NULL if not AP)
|
||||
*/
|
||||
@@ -161,7 +161,6 @@ struct wps_config {
|
||||
* struct wpa_context::psk.
|
||||
*/
|
||||
int use_psk_key;
|
||||
|
||||
#endif
|
||||
/**
|
||||
* dev_pw_id - Device Password ID for Enrollee when PIN is used
|
||||
@@ -228,7 +227,6 @@ enum wps_process_res {
|
||||
* event (e.g., UPnP message from an external Registrar)
|
||||
*/
|
||||
WPS_PENDING,
|
||||
WPS_IGNORE, /* snake, ignore the re-packge */
|
||||
|
||||
WPS_FRAGMENT /* Tim, send wsc fragment ack */
|
||||
};
|
||||
|
@@ -152,11 +152,7 @@ static struct wpabuf * wps_build_m1(struct wps_data *wps)
|
||||
wps_build_wps_state(wps, msg) ||
|
||||
wps_build_device_attrs(&wps->wps->dev, msg) ||
|
||||
wps_build_rf_bands(&wps->wps->dev, msg,
|
||||
#ifdef ESP_SUPPLICANT
|
||||
wps->wps->dev.rf_bands) ||
|
||||
#else
|
||||
wps->wps->rf_band_cb(wps->wps->cb_ctx)) ||
|
||||
#endif
|
||||
wps_build_assoc_state(wps, msg) ||
|
||||
wps_build_dev_password_id(msg, wps->dev_pw_id) ||
|
||||
wps_build_config_error(msg, WPS_CFG_NO_ERROR) ||
|
||||
@@ -245,6 +241,7 @@ static struct wpabuf * wps_build_m5(struct wps_data *wps)
|
||||
}
|
||||
|
||||
|
||||
#ifndef ESP_SUPPLICANT
|
||||
static int wps_build_cred_ssid(struct wps_data *wps, struct wpabuf *msg)
|
||||
{
|
||||
wpa_printf(MSG_DEBUG, "WPS: * SSID");
|
||||
@@ -351,13 +348,12 @@ static int wps_build_cred_mac_addr(struct wps_data *wps, struct wpabuf *msg)
|
||||
wpabuf_put_data(msg, wps->wps->dev.mac_addr, ETH_ALEN);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static int wps_build_ap_settings(struct wps_data *wps, struct wpabuf *plain)
|
||||
{
|
||||
#ifdef DEBUG_PRINT
|
||||
#ifndef ESP_SUPPLICANT
|
||||
const u8 *start, *end;
|
||||
#endif
|
||||
int ret;
|
||||
|
||||
if (wps->wps->ap_settings) {
|
||||
@@ -368,22 +364,21 @@ static int wps_build_ap_settings(struct wps_data *wps, struct wpabuf *plain)
|
||||
}
|
||||
|
||||
wpa_printf(MSG_DEBUG, "WPS: * AP Settings based on current configuration");
|
||||
#ifdef DEBUG_PRINT
|
||||
start = wpabuf_put(plain, 0);
|
||||
#endif
|
||||
ret = wps_build_cred_ssid(wps, plain) ||
|
||||
wps_build_cred_mac_addr(wps, plain) ||
|
||||
wps_build_cred_auth_type(wps, plain) ||
|
||||
wps_build_cred_encr_type(wps, plain) ||
|
||||
wps_build_cred_network_key(wps, plain);
|
||||
#ifdef DEBUG_PRINT
|
||||
end = wpabuf_put(plain, 0);
|
||||
|
||||
wpa_hexdump_key(MSG_DEBUG, "WPS: Plaintext AP Settings",
|
||||
start, end - start);
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
@@ -10,6 +10,7 @@
|
||||
|
||||
#include "utils/common.h"
|
||||
#include "utils/base64.h"
|
||||
#include "utils/eloop.h"
|
||||
#include "utils/uuid.h"
|
||||
#include "utils/list.h"
|
||||
#include "crypto/crypto.h"
|
||||
@@ -699,6 +700,7 @@ wps_registrar_init(struct wps_context *wps,
|
||||
reg->dualband = cfg->dualband;
|
||||
reg->force_per_enrollee_psk = cfg->force_per_enrollee_psk;
|
||||
|
||||
#ifndef ESP_SUPPLICANT
|
||||
if (cfg->multi_ap_backhaul_ssid) {
|
||||
os_memcpy(reg->multi_ap_backhaul_ssid,
|
||||
cfg->multi_ap_backhaul_ssid,
|
||||
@@ -714,6 +716,7 @@ wps_registrar_init(struct wps_context *wps,
|
||||
reg->multi_ap_backhaul_network_key_len =
|
||||
cfg->multi_ap_backhaul_network_key_len;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (wps_set_ie(reg)) {
|
||||
wps_registrar_deinit(reg);
|
||||
@@ -1291,6 +1294,7 @@ static void wps_cb_set_sel_reg(struct wps_registrar *reg)
|
||||
}
|
||||
|
||||
|
||||
#ifndef ESP_SUPPLICANT
|
||||
static int wps_cp_lookup_pskfile(struct wps_registrar *reg, const u8 *mac_addr,
|
||||
const u8 **psk)
|
||||
{
|
||||
@@ -1298,7 +1302,7 @@ static int wps_cp_lookup_pskfile(struct wps_registrar *reg, const u8 *mac_addr,
|
||||
return 0;
|
||||
return reg->lookup_pskfile_cb(reg->cb_ctx, mac_addr, psk);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static int wps_set_ie(struct wps_registrar *reg)
|
||||
{
|
||||
@@ -1619,9 +1623,11 @@ int wps_build_credential_wrap(struct wpabuf *msg,
|
||||
int wps_build_cred(struct wps_data *wps, struct wpabuf *msg)
|
||||
{
|
||||
struct wpabuf *cred;
|
||||
#ifndef ESP_SUPPLICANT
|
||||
struct wps_registrar *reg = wps->wps->registrar;
|
||||
const u8 *pskfile_psk;
|
||||
char hex[65];
|
||||
#endif
|
||||
|
||||
if (wps->wps->registrar->skip_cred_build)
|
||||
goto skip_cred_build;
|
||||
@@ -1631,6 +1637,7 @@ int wps_build_cred(struct wps_data *wps, struct wpabuf *msg)
|
||||
os_memcpy(&wps->cred, wps->use_cred, sizeof(wps->cred));
|
||||
goto use_provided;
|
||||
}
|
||||
#ifndef ESP_SUPPLICANT
|
||||
os_memset(&wps->cred, 0, sizeof(wps->cred));
|
||||
|
||||
if (wps->peer_dev.multi_ap_ext == MULTI_AP_BACKHAUL_STA &&
|
||||
@@ -1741,12 +1748,23 @@ int wps_build_cred(struct wps_data *wps, struct wpabuf *msg)
|
||||
wps->new_psk, wps->new_psk_len);
|
||||
os_memcpy(wps->cred.key, wps->new_psk, wps->new_psk_len);
|
||||
wps->cred.key_len = wps->new_psk_len;
|
||||
} else if (wps->use_psk_key && wps->wps->psk_set) {
|
||||
char hex[65] = {0};
|
||||
wpa_printf(MSG_DEBUG, "WPS: Use PSK format for Network Key");
|
||||
os_memcpy(wps->cred.key, hex, 32 * 2);
|
||||
wps->cred.key_len = 32 * 2;
|
||||
} else if (wps->wps->network_key) {
|
||||
} else if (wps_cp_lookup_pskfile(reg, wps->mac_addr_e, &pskfile_psk)) {
|
||||
wpa_hexdump_key(MSG_DEBUG, "WPS: Use PSK from wpa_psk_file",
|
||||
pskfile_psk, PMK_LEN);
|
||||
wpa_snprintf_hex(hex, sizeof(hex), pskfile_psk, PMK_LEN);
|
||||
os_memcpy(wps->cred.key, hex, PMK_LEN * 2);
|
||||
wps->cred.key_len = PMK_LEN * 2;
|
||||
} else if (!wps->wps->registrar->force_per_enrollee_psk &&
|
||||
wps->use_psk_key && wps->wps->psk_set) {
|
||||
wpa_printf(MSG_DEBUG, "WPS: Use PSK format for Network Key");
|
||||
wpa_snprintf_hex(hex, sizeof(hex), wps->wps->psk, PMK_LEN);
|
||||
os_memcpy(wps->cred.key, hex, PMK_LEN * 2);
|
||||
wps->cred.key_len = PMK_LEN * 2;
|
||||
} else
|
||||
if ((!wps->wps->registrar->force_per_enrollee_psk ||
|
||||
wps->wps->use_passphrase) && wps->wps->network_key) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"WPS: Use passphrase format for Network key");
|
||||
os_memcpy(wps->cred.key, wps->wps->network_key,
|
||||
wps->wps->network_key_len);
|
||||
wps->cred.key_len = wps->wps->network_key_len;
|
||||
@@ -1772,6 +1790,7 @@ int wps_build_cred(struct wps_data *wps, struct wpabuf *msg)
|
||||
os_memcpy(wps->cred.key, hex, wps->new_psk_len * 2);
|
||||
wps->cred.key_len = wps->new_psk_len * 2;
|
||||
}
|
||||
#endif
|
||||
|
||||
use_provided:
|
||||
#ifdef CONFIG_WPS_TESTING
|
||||
@@ -1836,6 +1855,7 @@ static int wps_build_ap_settings(struct wps_data *wps, struct wpabuf *msg)
|
||||
}
|
||||
|
||||
|
||||
#ifndef ESP_SUPPLICANT
|
||||
static struct wpabuf * wps_build_ap_cred(struct wps_data *wps)
|
||||
{
|
||||
struct wpabuf *msg, *plain;
|
||||
@@ -1863,6 +1883,7 @@ static struct wpabuf * wps_build_ap_cred(struct wps_data *wps)
|
||||
|
||||
return msg;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static struct wpabuf * wps_build_m2(struct wps_data *wps)
|
||||
@@ -2563,32 +2584,22 @@ static int wps_process_wps_state(struct wps_data *wps, const u8 *state)
|
||||
|
||||
static int wps_process_assoc_state(struct wps_data *wps, const u8 *assoc)
|
||||
{
|
||||
u16 a;
|
||||
|
||||
if (assoc == NULL) {
|
||||
wpa_printf(MSG_DEBUG, "WPS: No Association State received");
|
||||
return -1;
|
||||
}
|
||||
|
||||
a = WPA_GET_BE16(assoc);
|
||||
wpa_printf(MSG_DEBUG, "WPS: Enrollee Association State %d", a);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int wps_process_config_error(struct wps_data *wps, const u8 *err)
|
||||
{
|
||||
u16 e;
|
||||
|
||||
if (err == NULL) {
|
||||
wpa_printf(MSG_DEBUG, "WPS: No Configuration Error received");
|
||||
return -1;
|
||||
}
|
||||
|
||||
e = WPA_GET_BE16(err);
|
||||
wpa_printf(MSG_DEBUG, "WPS: Enrollee Configuration Error %d", e);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -2863,6 +2874,7 @@ static enum wps_process_res wps_process_m5(struct wps_data *wps,
|
||||
}
|
||||
|
||||
|
||||
#ifndef ESP_SUPPLICANT
|
||||
static void wps_sta_cred_cb(struct wps_data *wps)
|
||||
{
|
||||
/*
|
||||
@@ -2949,8 +2961,15 @@ static int wps_process_ap_settings_r(struct wps_data *wps,
|
||||
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else
|
||||
static int wps_process_ap_settings_r(struct wps_data *wps,
|
||||
struct wps_parse_attr *attr)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static enum wps_process_res wps_process_m7(struct wps_data *wps,
|
||||
const struct wpabuf *msg,
|
||||
@@ -3301,6 +3320,7 @@ static enum wps_process_res wps_process_wsc_done(struct wps_data *wps,
|
||||
}
|
||||
|
||||
wpa_printf(MSG_DEBUG, "WPS: Negotiation completed successfully");
|
||||
#ifndef ESP_SUPPLICANT
|
||||
wps_device_store(wps->wps->registrar, &wps->peer_dev,
|
||||
wps->uuid_e);
|
||||
|
||||
@@ -3349,6 +3369,7 @@ static enum wps_process_res wps_process_wsc_done(struct wps_data *wps,
|
||||
wps->new_psk = NULL;
|
||||
}
|
||||
|
||||
#endif
|
||||
wps_cb_reg_success(wps->wps->registrar, wps->mac_addr_e, wps->uuid_e,
|
||||
wps->dev_password, wps->dev_password_len);
|
||||
|
||||
|
Reference in New Issue
Block a user