Просмотр исходного кода

wpa_supplicant: Add WPS registrar support for softAP mode

Kapil Gupta 3 лет назад
Родитель
Сommit
a6811adac7
37 измененных файлов с 1809 добавлено и 1705 удалено
  1. 24 5
      components/wpa_supplicant/CMakeLists.txt
  2. 8 1
      components/wpa_supplicant/Kconfig
  3. 48 11
      components/wpa_supplicant/esp_supplicant/include/esp_wps.h
  4. 1 0
      components/wpa_supplicant/esp_supplicant/src/esp_common.c
  5. 12 3
      components/wpa_supplicant/esp_supplicant/src/esp_hostap.c
  6. 254 0
      components/wpa_supplicant/esp_supplicant/src/esp_hostpad_wps.c
  7. 76 6
      components/wpa_supplicant/esp_supplicant/src/esp_wpa_main.c
  8. 22 0
      components/wpa_supplicant/esp_supplicant/src/esp_wpas_glue.c
  9. 2 0
      components/wpa_supplicant/esp_supplicant/src/esp_wpas_glue.h
  10. 44 90
      components/wpa_supplicant/esp_supplicant/src/esp_wps.c
  11. 45 0
      components/wpa_supplicant/esp_supplicant/src/esp_wps_i.h
  12. 10 9
      components/wpa_supplicant/include/utils/wpa_debug.h
  13. 6 2
      components/wpa_supplicant/src/ap/ap_config.h
  14. 3 25
      components/wpa_supplicant/src/ap/eap_user_db.c
  15. 35 1
      components/wpa_supplicant/src/ap/hostapd.h
  16. 412 9
      components/wpa_supplicant/src/ap/ieee802_1x.c
  17. 5 1
      components/wpa_supplicant/src/ap/ieee802_1x.h
  18. 6 1333
      components/wpa_supplicant/src/ap/sta_info.c
  19. 16 21
      components/wpa_supplicant/src/ap/sta_info.h
  20. 8 20
      components/wpa_supplicant/src/ap/wpa_auth.c
  21. 586 0
      components/wpa_supplicant/src/ap/wps_hostapd.c
  22. 4 18
      components/wpa_supplicant/src/ap/wps_hostapd.h
  23. 33 0
      components/wpa_supplicant/src/common/ieee802_11_common.c
  24. 2 0
      components/wpa_supplicant/src/common/ieee802_11_common.h
  25. 39 6
      components/wpa_supplicant/src/eap_peer/eap_defs.h
  26. 4 2
      components/wpa_supplicant/src/eap_server/eap.h
  27. 2 2
      components/wpa_supplicant/src/eap_server/eap_i.h
  28. 1 1
      components/wpa_supplicant/src/eap_server/eap_methods.h
  29. 18 4
      components/wpa_supplicant/src/eap_server/eap_server.c
  30. 1 1
      components/wpa_supplicant/src/eap_server/eap_server_identity.c
  31. 20 80
      components/wpa_supplicant/src/eap_server/eap_server_wsc.c
  32. 12 15
      components/wpa_supplicant/src/eapol_auth/eapol_auth_sm.c
  33. 2 2
      components/wpa_supplicant/src/eapol_auth/eapol_auth_sm_i.h
  34. 1 4
      components/wpa_supplicant/src/wps/wps.c
  35. 2 4
      components/wpa_supplicant/src/wps/wps.h
  36. 6 11
      components/wpa_supplicant/src/wps/wps_enrollee.c
  37. 39 18
      components/wpa_supplicant/src/wps/wps_registrar.c

+ 24 - 5
components/wpa_supplicant/CMakeLists.txt

@@ -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)

+ 8 - 1
components/wpa_supplicant/Kconfig

@@ -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

+ 48 - 11
components/wpa_supplicant/esp_supplicant/include/esp_wps.h

@@ -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);
+
+
 /**
   * @}
   */

+ 1 - 0
components/wpa_supplicant/esp_supplicant/src/esp_common.c

@@ -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) { }

+ 12 - 3
components/wpa_supplicant/esp_supplicant/src/esp_hostap.c

@@ -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 - 0
components/wpa_supplicant/esp_supplicant/src/esp_hostpad_wps.c

@@ -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;
+}

+ 76 - 6
components/wpa_supplicant/esp_supplicant/src/esp_wpa_main.c

@@ -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;

+ 22 - 0
components/wpa_supplicant/esp_supplicant/src/esp_wpas_glue.c

@@ -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)

+ 2 - 0
components/wpa_supplicant/esp_supplicant/src/esp_wpas_glue.h

@@ -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 */

+ 44 - 90
components/wpa_supplicant/esp_supplicant/src/esp_wps.c

@@ -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;
 }

+ 45 - 0
components/wpa_supplicant/esp_supplicant/src/esp_wps_i.h

@@ -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);

+ 10 - 9
components/wpa_supplicant/include/utils/wpa_debug.h

@@ -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)
 {

+ 6 - 2
components/wpa_supplicant/src/ap/ap_config.h

@@ -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;

+ 3 - 25
components/wpa_supplicant/src/ap/eap_user_db.c

@@ -233,10 +233,9 @@ hostapd_get_eap_user(struct hostapd_data *hapd, const u8 *identity,
 		     size_t identity_len, int phase2)
 {
 	const struct hostapd_bss_config *conf = hapd->conf;
-	struct hostapd_eap_user *user = conf->eap_user;
 
 #ifdef CONFIG_WPS
-	if (conf->wps_state && identity_len == WSC_ID_ENROLLEE_LEN &&
+	if (identity_len == WSC_ID_ENROLLEE_LEN &&
 	    os_memcmp(identity, WSC_ID_ENROLLEE, WSC_ID_ENROLLEE_LEN) == 0) {
 		static struct hostapd_eap_user wsc_enrollee;
 		os_memset(&wsc_enrollee, 0, sizeof(wsc_enrollee));
@@ -245,7 +244,7 @@ hostapd_get_eap_user(struct hostapd_data *hapd, const u8 *identity,
 		return &wsc_enrollee;
 	}
 
-	if (conf->wps_state && identity_len == WSC_ID_REGISTRAR_LEN &&
+	if (identity_len == WSC_ID_REGISTRAR_LEN &&
 	    os_memcmp(identity, WSC_ID_REGISTRAR, WSC_ID_REGISTRAR_LEN) == 0) {
 		static struct hostapd_eap_user wsc_registrar;
 		os_memset(&wsc_registrar, 0, sizeof(wsc_registrar));
@@ -258,27 +257,6 @@ hostapd_get_eap_user(struct hostapd_data *hapd, const u8 *identity,
 	}
 #endif /* CONFIG_WPS */
 
-	while (user) {
-		if (!phase2 && user->identity == NULL) {
-			/* Wildcard match */
-			break;
-		}
-
-		if (user->phase2 == !!phase2 && user->wildcard_prefix &&
-		    identity_len >= user->identity_len &&
-		    os_memcmp(user->identity, identity, user->identity_len) ==
-		    0) {
-			/* Wildcard prefix match */
-			break;
-		}
-
-		if (user->phase2 == !!phase2 &&
-		    user->identity_len == identity_len &&
-		    os_memcmp(user->identity, identity, identity_len) == 0)
-			break;
-		user = user->next;
-	}
-
 #ifdef CONFIG_SQLITE
 	if (user == NULL && conf->eap_user_sqlite) {
 		return eap_user_sqlite_get(hapd, identity, identity_len,
@@ -286,5 +264,5 @@ hostapd_get_eap_user(struct hostapd_data *hapd, const u8 *identity,
 	}
 #endif /* CONFIG_SQLITE */
 
-	return user;
+	return NULL;
 }

+ 35 - 1
components/wpa_supplicant/src/ap/hostapd.h

@@ -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 */

+ 412 - 9
components/wpa_supplicant/src/ap/ieee802_1x.c

@@ -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);
+	}
 }

+ 5 - 1
components/wpa_supplicant/src/ap/ieee802_1x.h

@@ -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 */

Разница между файлами не показана из-за своего большого размера
+ 6 - 1333
components/wpa_supplicant/src/ap/sta_info.c


+ 16 - 21
components/wpa_supplicant/src/ap/sta_info.h

@@ -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 */

+ 8 - 20
components/wpa_supplicant/src/ap/wpa_auth.c

@@ -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 - 0
components/wpa_supplicant/src/ap/wps_hostapd.c

@@ -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;
+}

+ 4 - 18
components/wpa_supplicant/src/ap/wps_hostapd.h

@@ -11,14 +11,12 @@
 
 #ifdef CONFIG_WPS
 
-int hostapd_init_wps(struct hostapd_data *hapd,
-		     struct hostapd_bss_config *conf);
+int hostapd_init_wps(struct hostapd_data *hapd, struct wps_data *wps_data, struct wps_context *wps);
 int hostapd_init_wps_complete(struct hostapd_data *hapd);
 void hostapd_deinit_wps(struct hostapd_data *hapd);
 void hostapd_update_wps(struct hostapd_data *hapd);
 void hostapd_wps_eap_completed(struct hostapd_data *hapd);
-int hostapd_wps_add_pin(struct hostapd_data *hapd, const u8 *addr,
-			const char *uuid, const char *pin, int timeout);
+int hostapd_wps_add_pin(struct hostapd_data *hapd, const u8 *pin);
 int hostapd_wps_button_pushed(struct hostapd_data *hapd,
 			      const u8 *p2p_dev_addr);
 int hostapd_wps_cancel(struct hostapd_data *hapd);
@@ -30,24 +28,12 @@ const char * hostapd_wps_ap_pin_get(struct hostapd_data *hapd);
 int hostapd_wps_ap_pin_set(struct hostapd_data *hapd, const char *pin,
 			   int timeout);
 void hostapd_wps_update_ie(struct hostapd_data *hapd);
-int hostapd_wps_config_ap(struct hostapd_data *hapd, const char *ssid,
-			  const char *auth, const char *encr, const char *key);
+int hostapd_wps_config_ap(struct hostapd_data *hapd, struct wps_data *wps_data);
 int hostapd_wps_nfc_tag_read(struct hostapd_data *hapd,
 			     const struct wpabuf *data);
-struct wpabuf * hostapd_wps_nfc_config_token(struct hostapd_data *hapd,
-					     int ndef);
-struct wpabuf * hostapd_wps_nfc_hs_cr(struct hostapd_data *hapd, int ndef);
-int hostapd_wps_nfc_report_handover(struct hostapd_data *hapd,
-				    const struct wpabuf *req,
-				    const struct wpabuf *sel);
-struct wpabuf * hostapd_wps_nfc_token_gen(struct hostapd_data *hapd, int ndef);
-int hostapd_wps_nfc_token_enable(struct hostapd_data *hapd);
-void hostapd_wps_nfc_token_disable(struct hostapd_data *hapd);
-
 #else /* CONFIG_WPS */
 
-static inline int hostapd_init_wps(struct hostapd_data *hapd,
-				   struct hostapd_bss_config *conf)
+static inline int hostapd_init_wps(struct hostapd_data *hapd, struct wps_data *wps_data, struct wps_context *wps)
 {
 	return 0;
 }

+ 33 - 0
components/wpa_supplicant/src/common/ieee802_11_common.c

@@ -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)

+ 2 - 0
components/wpa_supplicant/src/common/ieee802_11_common.h

@@ -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 */

+ 39 - 6
components/wpa_supplicant/src/eap_peer/eap_defs.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 */

+ 4 - 2
components/wpa_supplicant/src/eap_server/eap.h

@@ -11,9 +11,9 @@
 
 #include "common/defs.h"
 #include "utils/list.h"
-#include "eap_common/eap_defs.h"
+#include "eap_peer/eap_defs.h"
 #include "eap_server/eap_methods.h"
-#include "wpabuf.h"
+#include "utils/wpabuf.h"
 
 struct eap_sm;
 
@@ -66,6 +66,7 @@ struct eap_eapol_interface {
 	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;
@@ -82,6 +83,7 @@ struct eap_eapol_interface {
 	struct wpabuf *aaaEapRespData;
 	/* aaaIdentity -> eap_get_identity() */
 	bool aaaTimeout;
+#endif
 };
 
 struct eap_server_erp_key {

+ 2 - 2
components/wpa_supplicant/src/eap_server/eap_i.h

@@ -9,9 +9,9 @@
 #ifndef EAP_I_H
 #define EAP_I_H
 
-#include "wpabuf.h"
+#include "utils/wpabuf.h"
 #include "eap_server/eap.h"
-#include "eap_common/eap_common.h"
+#include "eap_peer/eap_common.h"
 
 /* RFC 4137 - EAP Standalone Authenticator */
 

+ 1 - 1
components/wpa_supplicant/src/eap_server/eap_methods.h

@@ -9,7 +9,7 @@
 #ifndef EAP_SERVER_METHODS_H
 #define EAP_SERVER_METHODS_H
 
-#include "eap_common/eap_defs.h"
+#include "eap_peer/eap_defs.h"
 
 const struct eap_method * eap_server_get_eap_method(int vendor,
 						    enum eap_type method);

+ 18 - 4
components/wpa_supplicant/src/eap_server/eap_server.c

@@ -29,7 +29,9 @@ static int eap_sm_calculateTimeout(struct eap_sm *sm, int retransCount,
 				   int eapSRTT, int eapRTTVAR,
 				   int methodTimeout);
 static void eap_sm_parseEapResp(struct eap_sm *sm, const struct wpabuf *resp);
+#ifndef ESP_SUPPLICANT
 static int eap_sm_getId(const struct wpabuf *data);
+#endif
 static struct wpabuf * eap_sm_buildSuccess(struct eap_sm *sm, u8 id);
 static struct wpabuf * eap_sm_buildFailure(struct eap_sm *sm, u8 id);
 static int eap_sm_nextId(struct eap_sm *sm, int id);
@@ -43,8 +45,6 @@ static bool eap_sm_Policy_doPickUp(struct eap_sm *sm, enum eap_type method);
 
 static int eap_get_erp_send_reauth_start(struct eap_sm *sm)
 {
-	if (sm->eapol_cb->get_erp_send_reauth_start)
-		return sm->eapol_cb->get_erp_send_reauth_start(sm->eapol_ctx);
 	return 0;
 }
 
@@ -120,6 +120,7 @@ static int eap_copy_buf(struct wpabuf **dst, const struct wpabuf *src)
 }
 
 
+#ifndef ESP_SUPPLICANT
 static int eap_copy_data(u8 **dst, size_t *dst_len,
 			 const u8 *src, size_t src_len)
 {
@@ -137,6 +138,7 @@ static int eap_copy_data(u8 **dst, size_t *dst_len,
 		return -1;
 	}
 }
+#endif
 
 #define EAP_COPY(dst, src) \
 	eap_copy_data((dst), (dst ## Len), (src), (src ## Len))
@@ -994,6 +996,7 @@ fail:
 #endif /* CONFIG_ERP */
 
 
+#ifndef ESP_SUPPLICANT
 SM_STATE(EAP, INITIALIZE_PASSTHROUGH)
 {
 	SM_ENTRY(EAP, INITIALIZE_PASSTHROUGH);
@@ -1161,6 +1164,7 @@ SM_STATE(EAP, SUCCESS2)
 	wpa_msg(sm->cfg->msg_ctx, MSG_INFO, WPA_EVENT_EAP_SUCCESS2 MACSTR,
 		MAC2STR(sm->peer_addr));
 }
+#endif
 
 
 SM_STEP(EAP)
@@ -1346,8 +1350,10 @@ SM_STEP(EAP)
 			SM_ENTER(EAP, FAILURE);
 		else if (sm->decision == DECISION_SUCCESS)
 			SM_ENTER(EAP, SUCCESS);
+#ifndef ESP_SUPPLICANT
 		else if (sm->decision == DECISION_PASSTHROUGH)
 			SM_ENTER(EAP, INITIALIZE_PASSTHROUGH);
+#endif
 		else if (sm->decision == DECISION_INITIATE_REAUTH_START)
 			SM_ENTER(EAP, INITIATE_REAUTH_START);
 #ifdef CONFIG_ERP
@@ -1370,7 +1376,7 @@ SM_STEP(EAP)
 		break;
 	case EAP_SUCCESS:
 		break;
-
+#ifndef ESP_SUPPLICANT
 	case EAP_INITIALIZE_PASSTHROUGH:
 		if (sm->currentId == -1)
 			SM_ENTER(EAP, AAA_IDLE);
@@ -1423,6 +1429,10 @@ SM_STEP(EAP)
 		break;
 	case EAP_SUCCESS2:
 		break;
+#else
+	default:
+		break;
+#endif
 	}
 }
 
@@ -1545,6 +1555,7 @@ static void eap_sm_parseEapResp(struct eap_sm *sm, const struct wpabuf *resp)
 }
 
 
+#ifndef ESP_SUPPLICANT
 static int eap_sm_getId(const struct wpabuf *data)
 {
 	const struct eap_hdr *hdr;
@@ -1556,7 +1567,7 @@ static int eap_sm_getId(const struct wpabuf *data)
 	wpa_printf(MSG_DEBUG, "EAP: getId: id=%d", hdr->identifier);
 	return hdr->identifier;
 }
-
+#endif
 
 static struct wpabuf * eap_sm_buildSuccess(struct eap_sm *sm, u8 id)
 {
@@ -1873,6 +1884,7 @@ struct eap_sm * eap_server_sm_init(void *eapol_ctx,
 #ifdef CONFIG_TESTING_OPTIONS
 	sm->tls_test_flags = sess->tls_test_flags;
 #endif /* CONFIG_TESTING_OPTIONS */
+	sm->eap_if.portEnabled = 1;
 
 	wpa_printf(MSG_DEBUG, "EAP: Server state machine created");
 
@@ -1901,9 +1913,11 @@ void eap_server_sm_deinit(struct eap_sm *sm)
 	wpabuf_free(sm->eap_if.eapRespData);
 	os_free(sm->identity);
 	os_free(sm->serial_num);
+#ifndef ESP_SUPPLICANT
 	wpabuf_free(sm->eap_if.aaaEapReqData);
 	wpabuf_free(sm->eap_if.aaaEapRespData);
 	bin_clear_free(sm->eap_if.aaaEapKeyData, sm->eap_if.aaaEapKeyDataLen);
+#endif
 	eap_user_free(sm->user);
 	wpabuf_free(sm->assoc_wps_ie);
 	wpabuf_free(sm->assoc_p2p_ie);

+ 1 - 1
components/wpa_supplicant/src/eap_server/eap_server_identity.c

@@ -123,7 +123,7 @@ static void eap_identity_process(struct eap_sm *sm, void *priv,
 	buf = os_malloc(len * 4 + 1);
 	if (buf) {
 		printf_encode(buf, len * 4 + 1, pos, len);
-		eap_log_msg(sm, "EAP-Response/Identity '%s'", buf);
+		wpa_printf(MSG_DEBUG, "EAP-Response/Identity '%s'", buf);
 		os_free(buf);
 	}
 	if (sm->identity)

+ 20 - 80
components/wpa_supplicant/src/eap_server/eap_server_wsc.c

@@ -12,12 +12,12 @@
 #include "eloop.h"
 #include "eap_i.h"
 #include "eap_common/eap_wsc_common.h"
-#include "p2p/p2p.h"
 #include "wps/wps.h"
+#include "esp_wps_i.h"
 
 
 struct eap_wsc_data {
-	enum { START, MESG, FRAG_ACK, WAIT_FRAG_ACK, DONE, FAIL } state;
+	enum { START, MESG, FRAG_ACK, WAIT_FRAG_ACK, DONE, WSC_FAIL } state;
 	int registrar;
 	struct wpabuf *in_buf;
 	struct wpabuf *out_buf;
@@ -28,8 +28,7 @@ struct eap_wsc_data {
 	int ext_reg_timeout;
 };
 
-
-#ifndef CONFIG_NO_STDOUT_DEBUG
+#ifdef DEBUG_PRINT
 static const char * eap_wsc_state_txt(int state)
 {
 	switch (state) {
@@ -43,14 +42,13 @@ static const char * eap_wsc_state_txt(int state)
 		return "WAIT_FRAG_ACK";
 	case DONE:
 		return "DONE";
-	case FAIL:
+	case WSC_FAIL:
 		return "FAIL";
 	default:
 		return "?";
 	}
 }
-#endif /* CONFIG_NO_STDOUT_DEBUG */
-
+#endif
 
 static void eap_wsc_state(struct eap_wsc_data *data, int state)
 {
@@ -61,26 +59,10 @@ static void eap_wsc_state(struct eap_wsc_data *data, int state)
 }
 
 
-static void eap_wsc_ext_reg_timeout(void *eloop_ctx, void *timeout_ctx)
-{
-	struct eap_sm *sm = eloop_ctx;
-	struct eap_wsc_data *data = timeout_ctx;
-
-	if (sm->method_pending != METHOD_PENDING_WAIT)
-		return;
-
-	wpa_printf(MSG_DEBUG, "EAP-WSC: Timeout while waiting for an External "
-		   "Registrar");
-	data->ext_reg_timeout = 1;
-	eap_sm_pending_cb(sm);
-}
-
-
 static void * eap_wsc_init(struct eap_sm *sm)
 {
 	struct eap_wsc_data *data;
 	int registrar;
-	struct wps_config cfg;
 
 	if (sm->identity && sm->identity_len == WSC_ID_REGISTRAR_LEN &&
 	    os_memcmp(sm->identity, WSC_ID_REGISTRAR, WSC_ID_REGISTRAR_LEN) ==
@@ -102,52 +84,13 @@ static void * eap_wsc_init(struct eap_sm *sm)
 	data->state = registrar ? START : MESG;
 	data->registrar = registrar;
 
-	os_memset(&cfg, 0, sizeof(cfg));
-	cfg.wps = sm->cfg->wps;
-	cfg.registrar = registrar;
-	if (registrar) {
-		if (!sm->cfg->wps || !sm->cfg->wps->registrar) {
-			wpa_printf(MSG_INFO, "EAP-WSC: WPS Registrar not "
-				   "initialized");
-			os_free(data);
-			return NULL;
-		}
-	} else {
-		if (sm->user == NULL || sm->user->password == NULL) {
-			/*
-			 * In theory, this should not really be needed, but
-			 * Windows 7 uses Registrar mode to probe AP's WPS
-			 * capabilities before trying to use Enrollee and fails
-			 * if the AP does not allow that probing to happen..
-			 */
-			wpa_printf(MSG_DEBUG, "EAP-WSC: No AP PIN (password) "
-				   "configured for Enrollee functionality - "
-				   "allow for probing capabilities (M1)");
-		} else {
-			cfg.pin = sm->user->password;
-			cfg.pin_len = sm->user->password_len;
-		}
-	}
-	cfg.assoc_wps_ie = sm->assoc_wps_ie;
-	cfg.peer_addr = sm->peer_addr;
-#ifdef CONFIG_P2P
-	if (sm->assoc_p2p_ie) {
-		if (!sm->cfg->wps->use_passphrase) {
-			wpa_printf(MSG_DEBUG,
-				   "EAP-WSC: Prefer PSK format for non-6 GHz P2P client");
-			cfg.use_psk_key = 1;
-		}
-		cfg.p2p_dev_addr = p2p_get_go_dev_addr(sm->assoc_p2p_ie);
-	}
-#endif /* CONFIG_P2P */
-	cfg.pbc_in_m1 = sm->cfg->pbc_in_m1;
-	data->wps = wps_init(&cfg);
+	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 = sm->cfg->fragment_size > 0 ?
-		sm->cfg->fragment_size : WSC_FRAGMENT_SIZE;
+	data->fragment_size = WSC_FRAGMENT_SIZE;
 
 	return data;
 }
@@ -156,7 +99,6 @@ static void * eap_wsc_init(struct eap_sm *sm)
 static void eap_wsc_reset(struct eap_sm *sm, void *priv)
 {
 	struct eap_wsc_data *data = priv;
-	eloop_cancel_timeout(eap_wsc_ext_reg_timeout, sm, data);
 	wpabuf_free(data->in_buf);
 	wpabuf_free(data->out_buf);
 	wps_deinit(data->wps);
@@ -297,13 +239,13 @@ static int eap_wsc_process_cont(struct eap_wsc_data *data,
 		wpa_printf(MSG_DEBUG, "EAP-WSC: Unexpected Op-Code %d in "
 			   "fragment (expected %d)",
 			   op_code, data->in_op_code);
-		eap_wsc_state(data, FAIL);
+		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, FAIL);
+		eap_wsc_state(data, WSC_FAIL);
 		return -1;
 	}
 
@@ -358,9 +300,8 @@ static void eap_wsc_process(struct eap_sm *sm, void *priv,
 	enum wps_process_res res;
 	struct wpabuf tmpbuf;
 
-	eloop_cancel_timeout(eap_wsc_ext_reg_timeout, sm, data);
 	if (data->ext_reg_timeout) {
-		eap_wsc_state(data, FAIL);
+		eap_wsc_state(data, WSC_FAIL);
 		return;
 	}
 
@@ -397,7 +338,7 @@ static void eap_wsc_process(struct eap_sm *sm, void *priv,
 		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, FAIL);
+			eap_wsc_state(data, WSC_FAIL);
 			return;
 		}
 		wpa_printf(MSG_DEBUG, "EAP-WSC: Fragment acknowledged");
@@ -409,13 +350,13 @@ static void eap_wsc_process(struct eap_sm *sm, void *priv,
 	    op_code != WSC_Done) {
 		wpa_printf(MSG_DEBUG, "EAP-WSC: Unexpected Op-Code %d",
 			   op_code);
-		eap_wsc_state(data, FAIL);
+		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, FAIL);
+		eap_wsc_state(data, WSC_FAIL);
 		return;
 	}
 
@@ -423,7 +364,7 @@ static void eap_wsc_process(struct eap_sm *sm, void *priv,
 		if (eap_wsc_process_fragment(data, flags, op_code,
 					     message_length, pos, end - pos) <
 		    0)
-			eap_wsc_state(data, FAIL);
+			eap_wsc_state(data, WSC_FAIL);
 		else
 			eap_wsc_state(data, FRAG_ACK);
 		return;
@@ -440,21 +381,20 @@ static void eap_wsc_process(struct eap_sm *sm, void *priv,
 	case WPS_DONE:
 		wpa_printf(MSG_DEBUG, "EAP-WSC: WPS processing completed "
 			   "successfully - report EAP failure");
-		eap_wsc_state(data, FAIL);
+		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, FAIL);
+		eap_wsc_state(data, WSC_FAIL);
 		break;
 	case WPS_PENDING:
 		eap_wsc_state(data, MESG);
 		sm->method_pending = METHOD_PENDING_WAIT;
-		eloop_cancel_timeout(eap_wsc_ext_reg_timeout, sm, data);
-		eloop_register_timeout(5, 0, eap_wsc_ext_reg_timeout,
-				       sm, data);
+		break;
+	default:
 		break;
 	}
 
@@ -467,7 +407,7 @@ static void eap_wsc_process(struct eap_sm *sm, void *priv,
 static bool eap_wsc_isDone(struct eap_sm *sm, void *priv)
 {
 	struct eap_wsc_data *data = priv;
-	return data->state == FAIL;
+	return data->state == WSC_FAIL;
 }
 
 

+ 12 - 15
components/wpa_supplicant/src/eapol_auth/eapol_auth_sm.c

@@ -12,8 +12,8 @@
 #include "eloop.h"
 #include "state_machine.h"
 #include "common/eapol_common.h"
-#include "eap_common/eap_defs.h"
-#include "eap_common/eap_common.h"
+#include "eap_peer/eap_defs.h"
+#include "eap_peer/eap_common.h"
 #include "eap_server/eap.h"
 #include "eapol_auth_sm.h"
 #include "eapol_auth_sm_i.h"
@@ -45,7 +45,7 @@ static void eapol_sm_step_cb(void *eloop_ctx, void *timeout_ctx);
 static void eapol_auth_initialize(struct eapol_state_machine *sm);
 static void eapol_auth_conf_free(struct eapol_auth_config *conf);
 
-
+#ifndef ESP_SUPPLICANT
 static void eapol_auth_logger(struct eapol_authenticator *eapol,
 			      const u8 *addr, eapol_logger_level level,
 			      const char *txt)
@@ -81,7 +81,11 @@ static void eapol_auth_vlogger(struct eapol_authenticator *eapol,
 
 	os_free(format);
 }
+#else
 
+#define eapol_auth_logger(...) do {} while(0)
+#define eapol_auth_vlogger(...) do {} while (0)
+#endif
 
 static void eapol_auth_tx_canned_eap(struct eapol_state_machine *sm,
 				     int success)
@@ -297,8 +301,6 @@ SM_STATE(AUTH_PAE, HELD)
 
 SM_STATE(AUTH_PAE, AUTHENTICATED)
 {
-	char *extra = "";
-
 	if (sm->auth_pae_state == AUTH_PAE_AUTHENTICATING && sm->authSuccess)
 		sm->authAuthSuccessesWhileAuthenticating++;
 
@@ -307,15 +309,6 @@ SM_STATE(AUTH_PAE, AUTHENTICATED)
 	sm->authPortStatus = Authorized;
 	setPortAuthorized();
 	sm->reAuthCount = 0;
-	if (sm->flags & EAPOL_SM_PREAUTH)
-		extra = " (pre-authentication)";
-	else if (sm->flags & EAPOL_SM_FROM_PMKSA_CACHE)
-		extra = " (PMKSA cache)";
-	eapol_auth_vlogger(sm->eapol, sm->addr, EAPOL_LOGGER_INFO,
-			   "authenticated - EAP type: %d (%s)%s",
-			   sm->eap_type_authsrv,
-			   eap_server_get_name(0, sm->eap_type_authsrv),
-			   extra);
 	sm->eapol->cb.finished(sm->eapol->conf.ctx, sm->sta, 1,
 			       sm->flags & EAPOL_SM_PREAUTH, sm->remediation);
 }
@@ -849,11 +842,11 @@ eapol_auth_alloc(struct eapol_authenticator *eapol, const u8 *addr,
 		if (sm->identity)
 			sm->identity_len = os_strlen(identity);
 	}
+#ifndef CONFIG_NO_RADIUS
 	if (radius_cui)
 		sm->radius_cui = wpabuf_alloc_copy(radius_cui,
 						   os_strlen(radius_cui));
 
-#ifndef CONFIG_NO_RADIUS
 	if (radius_gen_session_id((u8 *) &sm->acct_multi_session_id,
 				  sizeof(sm->acct_multi_session_id)) < 0) {
 		eapol_auth_free(sm);
@@ -875,7 +868,9 @@ void eapol_auth_free(struct eapol_state_machine *sm)
 	if (sm->eap)
 		eap_server_sm_deinit(sm->eap);
 
+#ifndef CONFIG_NO_RADIUS
 	wpabuf_free(sm->radius_cui);
+#endif /* CONFIG_NO_RADIUS */
 	os_free(sm->identity);
 	os_free(sm);
 }
@@ -948,6 +943,7 @@ restart:
 			return;
 		}
 
+#ifndef ESP_SUPPLICANT
 		/* TODO: find a better location for this */
 		if (sm->eap_if->aaaEapResp) {
 			sm->eap_if->aaaEapResp = false;
@@ -961,6 +957,7 @@ restart:
 				wpabuf_head(sm->eap_if->aaaEapRespData),
 				wpabuf_len(sm->eap_if->aaaEapRespData));
 		}
+#endif
 	}
 
 	if (eapol_sm_sta_entry_alive(eapol, addr))

+ 2 - 2
components/wpa_supplicant/src/eapol_auth/eapol_auth_sm_i.h

@@ -10,7 +10,6 @@
 #define EAPOL_AUTH_SM_I_H
 
 #include "common/defs.h"
-#include "radius/radius.h"
 
 /* IEEE Std 802.1X-2004, Ch. 8.2 */
 
@@ -156,8 +155,9 @@ struct eapol_state_machine {
 	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 */
-	struct radius_class_data radius_class;
+#ifndef CONFIG_NO_RADIUS
 	struct wpabuf *radius_cui; /* Chargeable-User-Identity */
+#endif
 
 	struct eap_sm *eap;
 

+ 1 - 4
components/wpa_supplicant/src/wps/wps.c

@@ -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);
 }
 
 

+ 2 - 4
components/wpa_supplicant/src/wps/wps.h

@@ -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 */
 };

+ 6 - 11
components/wpa_supplicant/src/wps/wps_enrollee.c

@@ -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
 }
 
 

+ 39 - 18
components/wpa_supplicant/src/wps/wps_registrar.c

@@ -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);
 

Некоторые файлы не были показаны из-за большого количества измененных файлов