Added preliminary Wi-Fi Protected Setup (WPS) implementation
This adds WPS support for both hostapd and wpa_supplicant. Both programs can be configured to act as WPS Enrollee and Registrar. Both PBC and PIN methods are supported. Currently, hostapd has more complete configuration option for WPS parameters and wpa_supplicant configuration style will likely change in the future. External Registrars are not yet supported in hostapd or wpa_supplicant. While wpa_supplicant has initial support for acting as an Registrar to configure an AP, this is still using number of hardcoded parameters which will need to be made configurable for proper operation.
This commit is contained in:
parent
6e89cc438e
commit
ad08c3633c
71 changed files with 8602 additions and 47 deletions
|
@ -493,6 +493,26 @@ endif
|
|||
NEED_SHA256=y
|
||||
endif
|
||||
|
||||
ifdef CONFIG_WPS
|
||||
# EAP-WSC
|
||||
ifeq ($(CONFIG_EAP_WSC), dyn)
|
||||
CFLAGS += -DCONFIG_WPS -DEAP_WSC_DYNAMIC
|
||||
EAPDYN += ../src/eap_peer/eap_wsc.so
|
||||
else
|
||||
CFLAGS += -DCONFIG_WPS -DEAP_WSC
|
||||
OBJS += ../src/utils/uuid.o
|
||||
OBJS += ../src/eap_peer/eap_wsc.o ../src/eap_common/eap_wsc_common.o
|
||||
OBJS += ../src/wps/wps.o
|
||||
OBJS += ../src/wps/wps_common.o
|
||||
OBJS += ../src/wps/wps_dev_attr.o
|
||||
OBJS += ../src/wps/wps_enrollee.o
|
||||
OBJS += ../src/wps/wps_registrar.o
|
||||
OBJS_h += ../src/eap_server/eap_wsc.o
|
||||
endif
|
||||
CONFIG_IEEE8021X_EAPOL=y
|
||||
NEED_DH_GROUPS=y
|
||||
endif
|
||||
|
||||
ifdef CONFIG_EAP_IKEV2
|
||||
# EAP-IKEv2
|
||||
ifeq ($(CONFIG_EAP_IKEV2), dyn)
|
||||
|
@ -1080,6 +1100,10 @@ eap_sake.so: ../src/eap_peer/eap_sake.c ../src/eap_common/eap_sake_common.c
|
|||
$(CC) -o $@ $(CFLAGS) -shared -rdynamic -fPIC $^ \
|
||||
-Deap_peer_sake_register=eap_peer_method_dynamic_init
|
||||
|
||||
eap_wsc.so: ../src/eap_peer/eap_wsc.c ../src/eap_common/eap_wsc_common.c ../src/wps/wps.c
|
||||
$(CC) -o $@ $(CFLAGS) -shared -rdynamic -fPIC $^ \
|
||||
-Deap_peer_wsc_register=eap_peer_method_dynamic_init
|
||||
|
||||
eap_ikev2.so: ../src/eap_peer/eap_ikev2.c ../src/eap_peer/ikev2.c ../src/eap_common/eap_ikev2_common.o ../src/eap_common/ikev2_common.c
|
||||
$(CC) -o $@ $(CFLAGS) -shared -rdynamic -fPIC $^ \
|
||||
-Deap_peer_ikev2_register=eap_peer_method_dynamic_init
|
||||
|
|
|
@ -515,6 +515,10 @@ static int wpa_config_parse_key_mgmt(const struct parse_data *data,
|
|||
else if (os_strcmp(start, "WPA-EAP-SHA256") == 0)
|
||||
val |= WPA_KEY_MGMT_IEEE8021X_SHA256;
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
#ifdef CONFIG_WPS
|
||||
else if (os_strcmp(start, "WPS") == 0)
|
||||
val |= WPA_KEY_MGMT_WPS;
|
||||
#endif /* CONFIG_WPS */
|
||||
else {
|
||||
wpa_printf(MSG_ERROR, "Line %d: invalid key_mgmt '%s'",
|
||||
line, start);
|
||||
|
|
|
@ -871,6 +871,8 @@ int wpa_config_write(const char *name, struct wpa_config *config)
|
|||
wpa_config_write_global(f, config);
|
||||
|
||||
for (ssid = config->ssid; ssid; ssid = ssid->next) {
|
||||
if (ssid->key_mgmt == WPA_KEY_MGMT_WPS)
|
||||
continue; /* do not save temporary WPS networks */
|
||||
fprintf(f, "\nnetwork={\n");
|
||||
wpa_config_write_network(f, ssid);
|
||||
fprintf(f, "}\n");
|
||||
|
|
|
@ -874,6 +874,8 @@ int wpa_config_write(const char *name, struct wpa_config *config)
|
|||
|
||||
wpa_config_delete_subkeys(hk, TEXT("networks"));
|
||||
for (ssid = config->ssid, id = 0; ssid; ssid = ssid->next, id++) {
|
||||
if (ssid->key_mgmt == WPA_KEY_MGMT_WPS)
|
||||
continue; /* do not save temporary WPS networks */
|
||||
if (wpa_config_write_network(hk, ssid, id))
|
||||
errors++;
|
||||
}
|
||||
|
|
|
@ -420,6 +420,14 @@ DBusMessage * wpas_dbus_bssid_properties(DBusMessage *message,
|
|||
goto error;
|
||||
}
|
||||
|
||||
ie = wpa_scan_get_vendor_ie(res, WPS_IE_VENDOR_TYPE);
|
||||
if (ie) {
|
||||
if (!wpa_dbus_dict_append_byte_array(&iter_dict, "wpsie",
|
||||
(const char *) ie,
|
||||
ie[1] + 2))
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (res->freq) {
|
||||
if (!wpa_dbus_dict_append_int32(&iter_dict, "frequency",
|
||||
res->freq))
|
||||
|
|
|
@ -170,6 +170,9 @@ CONFIG_EAP_LEAP=y
|
|||
# EAP-TNC and related Trusted Network Connect support (experimental)
|
||||
#CONFIG_EAP_TNC=y
|
||||
|
||||
# Wi-Fi Protected Setup (WPS)
|
||||
#CONFIG_WPS=y
|
||||
|
||||
# EAP-IKEv2
|
||||
#CONFIG_EAP_IKEV2=y
|
||||
|
||||
|
|
|
@ -336,6 +336,7 @@ static int test_eapol(struct eapol_test_data *e, struct wpa_supplicant *wpa_s,
|
|||
ctx->pkcs11_engine_path = wpa_s->conf->pkcs11_engine_path;
|
||||
ctx->pkcs11_module_path = wpa_s->conf->pkcs11_module_path;
|
||||
#endif /* EAP_TLS_OPENSSL */
|
||||
ctx->mac_addr = wpa_s->own_addr;
|
||||
|
||||
wpa_s->eapol = eapol_sm_init(ctx);
|
||||
if (wpa_s->eapol == NULL) {
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include "ieee802_11_defs.h"
|
||||
#include "blacklist.h"
|
||||
#include "wpas_glue.h"
|
||||
#include "wps/wps.h"
|
||||
|
||||
|
||||
static int wpa_supplicant_select_config(struct wpa_supplicant *wpa_s)
|
||||
|
@ -276,6 +277,53 @@ static int wpa_supplicant_ssid_bss_match(struct wpa_ssid *ssid,
|
|||
int proto_match = 0;
|
||||
const u8 *rsn_ie, *wpa_ie;
|
||||
|
||||
#ifdef CONFIG_WPS
|
||||
if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) {
|
||||
const u8 *wps_ie;
|
||||
wps_ie = wpa_scan_get_vendor_ie(bss, WPS_IE_VENDOR_TYPE);
|
||||
if (eap_is_wps_pbc_enrollee(&ssid->eap)) {
|
||||
if (!wps_ie) {
|
||||
wpa_printf(MSG_DEBUG, " skip - non-WPS AP");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!wps_is_selected_pbc_registrar(wps_ie + 6,
|
||||
wps_ie[1] - 4)) {
|
||||
wpa_printf(MSG_DEBUG, " skip - WPS AP "
|
||||
"without active PBC Registrar");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* TODO: overlap detection */
|
||||
wpa_printf(MSG_DEBUG, " selected based on WPS IE "
|
||||
"(Active PBC)");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (eap_is_wps_pin_enrollee(&ssid->eap)) {
|
||||
if (!wps_ie) {
|
||||
wpa_printf(MSG_DEBUG, " skip - non-WPS AP");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!wps_is_selected_pin_registrar(wps_ie + 6,
|
||||
wps_ie[1] - 4)) {
|
||||
wpa_printf(MSG_DEBUG, " skip - WPS AP "
|
||||
"without active PIN Registrar");
|
||||
return 0;
|
||||
}
|
||||
wpa_printf(MSG_DEBUG, " selected based on WPS IE "
|
||||
"(Active PIN)");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (wps_ie) {
|
||||
wpa_printf(MSG_DEBUG, " selected based on WPS IE");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_WPS */
|
||||
|
||||
rsn_ie = wpa_scan_get_ie(bss, WLAN_EID_RSN);
|
||||
while ((ssid->proto & WPA_PROTO_RSN) && rsn_ie) {
|
||||
proto_match++;
|
||||
|
@ -364,6 +412,34 @@ static int wpa_supplicant_ssid_bss_match(struct wpa_ssid *ssid,
|
|||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_WPS
|
||||
static int wps_ssid_wildcard_ok(struct wpa_ssid *ssid,
|
||||
struct wpa_scan_res *bss)
|
||||
{
|
||||
const u8 *wps_ie;
|
||||
|
||||
if (eap_is_wps_pbc_enrollee(&ssid->eap)) {
|
||||
wps_ie = wpa_scan_get_vendor_ie(bss, WPS_IE_VENDOR_TYPE);
|
||||
if (wps_ie &&
|
||||
wps_is_selected_pbc_registrar(wps_ie + 6, wps_ie[1] - 4)) {
|
||||
/* allow wildcard SSID for WPS PBC */
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (eap_is_wps_pin_enrollee(&ssid->eap)) {
|
||||
wps_ie = wpa_scan_get_vendor_ie(bss, WPS_IE_VENDOR_TYPE);
|
||||
if (wps_ie &&
|
||||
wps_is_selected_pin_registrar(wps_ie + 6, wps_ie[1] - 4)) {
|
||||
/* allow wildcard SSID for WPS PIN */
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_WPS */
|
||||
|
||||
static struct wpa_scan_res *
|
||||
wpa_supplicant_select_bss_wpa(struct wpa_supplicant *wpa_s,
|
||||
struct wpa_ssid *group,
|
||||
|
@ -409,13 +485,22 @@ wpa_supplicant_select_bss_wpa(struct wpa_supplicant *wpa_s,
|
|||
}
|
||||
|
||||
for (ssid = group; ssid; ssid = ssid->pnext) {
|
||||
int check_ssid = 1;
|
||||
|
||||
if (ssid->disabled) {
|
||||
wpa_printf(MSG_DEBUG, " skip - disabled");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ssid_len != ssid->ssid_len ||
|
||||
os_memcmp(ssid_, ssid->ssid, ssid_len) != 0) {
|
||||
#ifdef CONFIG_WPS
|
||||
if (ssid->ssid_len == 0 &&
|
||||
wps_ssid_wildcard_ok(ssid, bss))
|
||||
check_ssid = 0;
|
||||
#endif /* CONFIG_WPS */
|
||||
|
||||
if (check_ssid &&
|
||||
(ssid_len != ssid->ssid_len ||
|
||||
os_memcmp(ssid_, ssid->ssid, ssid_len) != 0)) {
|
||||
wpa_printf(MSG_DEBUG, " skip - "
|
||||
"SSID mismatch");
|
||||
continue;
|
||||
|
@ -485,12 +570,26 @@ wpa_supplicant_select_bss_non_wpa(struct wpa_supplicant *wpa_s,
|
|||
}
|
||||
|
||||
for (ssid = group; ssid; ssid = ssid->pnext) {
|
||||
int check_ssid = ssid->ssid_len != 0;
|
||||
|
||||
if (ssid->disabled) {
|
||||
wpa_printf(MSG_DEBUG, " skip - disabled");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ssid->ssid_len != 0 &&
|
||||
#ifdef CONFIG_WPS
|
||||
if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) {
|
||||
/* Only allow wildcard SSID match if an AP
|
||||
* advertises active WPS operation that matches
|
||||
* with our mode. */
|
||||
check_ssid = 1;
|
||||
if (ssid->ssid_len == 0 &&
|
||||
wps_ssid_wildcard_ok(ssid, bss))
|
||||
check_ssid = 0;
|
||||
}
|
||||
#endif /* CONFIG_WPS */
|
||||
|
||||
if (check_ssid &&
|
||||
(ssid_len != ssid->ssid_len ||
|
||||
os_memcmp(ssid_, ssid->ssid, ssid_len) != 0)) {
|
||||
wpa_printf(MSG_DEBUG, " skip - "
|
||||
|
@ -507,6 +606,7 @@ wpa_supplicant_select_bss_non_wpa(struct wpa_supplicant *wpa_s,
|
|||
}
|
||||
|
||||
if (!(ssid->key_mgmt & WPA_KEY_MGMT_NONE) &&
|
||||
!(ssid->key_mgmt & WPA_KEY_MGMT_WPS) &&
|
||||
!(ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA))
|
||||
{
|
||||
wpa_printf(MSG_DEBUG, " skip - "
|
||||
|
@ -570,6 +670,65 @@ wpa_supplicant_select_bss(struct wpa_supplicant *wpa_s, struct wpa_ssid *group,
|
|||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_WPS
|
||||
|
||||
static int wpa_scan_pbc_overlap(struct wpa_supplicant *wpa_s,
|
||||
struct wpa_scan_res *selected,
|
||||
struct wpa_ssid *ssid)
|
||||
{
|
||||
const u8 *sel_uuid, *uuid;
|
||||
size_t i;
|
||||
const u8 *wps_ie;
|
||||
|
||||
if (!eap_is_wps_pbc_enrollee(&ssid->eap))
|
||||
return 0;
|
||||
|
||||
/* Make sure that only one AP is in active PBC mode */
|
||||
wps_ie = wpa_scan_get_vendor_ie(selected, WPS_IE_VENDOR_TYPE);
|
||||
if (wps_ie)
|
||||
sel_uuid = wps_get_uuid_e(wps_ie + 6, wps_ie[1] - 4);
|
||||
else
|
||||
sel_uuid = NULL;
|
||||
if (!sel_uuid) {
|
||||
wpa_printf(MSG_DEBUG, "WPS: UUID-E not "
|
||||
"available for PBC overlap "
|
||||
"detection");
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (i = 0; i < wpa_s->scan_res->num; i++) {
|
||||
struct wpa_scan_res *bss = wpa_s->scan_res->res[i];
|
||||
if (bss == selected)
|
||||
continue;
|
||||
wps_ie = wpa_scan_get_vendor_ie(bss, WPS_IE_VENDOR_TYPE);
|
||||
if (!wps_ie)
|
||||
continue;
|
||||
if (!wps_is_selected_pbc_registrar(wps_ie + 6,
|
||||
wps_ie[1] - 4))
|
||||
continue;
|
||||
uuid = wps_get_uuid_e(wps_ie + 6, wps_ie[1] - 4);
|
||||
if (uuid == NULL) {
|
||||
wpa_printf(MSG_DEBUG, "WPS: UUID-E not "
|
||||
"available for PBC overlap "
|
||||
"detection (other BSS)");
|
||||
return 1;
|
||||
}
|
||||
if (os_memcmp(sel_uuid, uuid, 16) != 0)
|
||||
return 1; /* PBC overlap */
|
||||
|
||||
/* TODO: verify that this is reasonable dual-band situation */
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else /* CONFIG_WPS */
|
||||
|
||||
#define wpa_scan_pbc_overlap(w, s, i) 0
|
||||
|
||||
#endif /* CONFIG_WPS */
|
||||
|
||||
|
||||
static void wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s)
|
||||
{
|
||||
int prio, timeout;
|
||||
|
@ -619,6 +778,13 @@ static void wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s)
|
|||
}
|
||||
|
||||
if (selected) {
|
||||
if (wpa_scan_pbc_overlap(wpa_s, selected, ssid)) {
|
||||
wpa_msg(wpa_s, MSG_INFO, WPS_EVENT_OVERLAP
|
||||
"PBC session overlap");
|
||||
timeout = 10;
|
||||
goto req_scan;
|
||||
}
|
||||
|
||||
/* Do not trigger new association unless the BSSID has changed
|
||||
* or if reassociation is requested. If we are in process of
|
||||
* associating with the selected BSSID, do not trigger new
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "wpa_supplicant_i.h"
|
||||
#include "mlme.h"
|
||||
#include "uuid.h"
|
||||
#include "wps/wps.h"
|
||||
|
||||
|
||||
static void wpa_supplicant_gen_assoc_event(struct wpa_supplicant *wpa_s)
|
||||
|
@ -41,13 +42,45 @@ static void wpa_supplicant_gen_assoc_event(struct wpa_supplicant *wpa_s)
|
|||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_WPS
|
||||
static int wpas_wps_in_use(struct wpa_config *conf, u8 *uuid)
|
||||
{
|
||||
struct wpa_ssid *ssid;
|
||||
int wps = 0;
|
||||
const char *pos;
|
||||
|
||||
for (ssid = conf->ssid; ssid; ssid = ssid->next) {
|
||||
if (!(ssid->key_mgmt & WPA_KEY_MGMT_WPS))
|
||||
continue;
|
||||
|
||||
wps = 1;
|
||||
if (!ssid->eap.phase1)
|
||||
continue;
|
||||
|
||||
pos = os_strstr(ssid->eap.phase1, "uuid=");
|
||||
if (pos)
|
||||
uuid_str2bin(pos + 5, uuid);
|
||||
|
||||
if (os_strstr(ssid->eap.phase1, "pbc=1"))
|
||||
return 2;
|
||||
}
|
||||
|
||||
return wps;
|
||||
}
|
||||
#endif /* CONFIG_WPS */
|
||||
|
||||
static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx)
|
||||
{
|
||||
struct wpa_supplicant *wpa_s = eloop_ctx;
|
||||
struct wpa_ssid *ssid;
|
||||
int enabled, scan_req = 0, ret;
|
||||
struct wpabuf *wps_ie = NULL;
|
||||
const u8 *extra_ie = NULL;
|
||||
size_t extra_ie_len = 0;
|
||||
int wps = 0;
|
||||
#ifdef CONFIG_WPS
|
||||
u8 uuid[UUID_LEN];
|
||||
#endif /* CONFIG_WPS */
|
||||
|
||||
if (wpa_s->disconnected && !wpa_s->scan_req)
|
||||
return;
|
||||
|
@ -134,8 +167,12 @@ static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx)
|
|||
} else
|
||||
wpa_s->prev_scan_ssid = BROADCAST_SSID_SCAN;
|
||||
|
||||
#ifdef CONFIG_WPS
|
||||
wps = wpas_wps_in_use(wpa_s->conf, uuid);
|
||||
#endif /* CONFIG_WPS */
|
||||
|
||||
if (wpa_s->scan_res_tried == 0 && wpa_s->conf->ap_scan == 1 &&
|
||||
!wpa_s->use_client_mlme) {
|
||||
!wpa_s->use_client_mlme && wps != 2) {
|
||||
wpa_s->scan_res_tried++;
|
||||
wpa_s->scan_req = scan_req;
|
||||
wpa_printf(MSG_DEBUG, "Trying to get current scan results "
|
||||
|
@ -145,6 +182,16 @@ static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx)
|
|||
return;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_WPS
|
||||
if (wps) {
|
||||
wps_ie = wps_enrollee_build_probe_req_ie(wps == 2, uuid);
|
||||
if (wps_ie) {
|
||||
extra_ie = wpabuf_head(wps_ie);
|
||||
extra_ie_len = wpabuf_len(wps_ie);
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_WPS */
|
||||
|
||||
if (wpa_s->use_client_mlme) {
|
||||
ieee80211_sta_set_probe_req_ie(wpa_s, extra_ie, extra_ie_len);
|
||||
ret = ieee80211_sta_req_scan(wpa_s, ssid ? ssid->ssid : NULL,
|
||||
|
@ -155,6 +202,8 @@ static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx)
|
|||
ssid ? ssid->ssid_len : 0);
|
||||
}
|
||||
|
||||
wpabuf_free(wps_ie);
|
||||
|
||||
if (ret) {
|
||||
wpa_printf(MSG_WARNING, "Failed to initiate AP scan.");
|
||||
wpa_supplicant_req_scan(wpa_s, 10, 0);
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#include "ieee802_11_defs.h"
|
||||
#include "blacklist.h"
|
||||
#include "wpas_glue.h"
|
||||
#include "wps/wps.h"
|
||||
|
||||
const char *wpa_supplicant_version =
|
||||
"wpa_supplicant v" VERSION_STR "\n"
|
||||
|
@ -282,7 +283,8 @@ void wpa_supplicant_initiate_eapol(struct wpa_supplicant *wpa_s)
|
|||
eapol_conf.workaround = ssid->eap_workaround;
|
||||
eapol_conf.eap_disabled =
|
||||
!wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) &&
|
||||
wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA;
|
||||
wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA &&
|
||||
wpa_s->key_mgmt != WPA_KEY_MGMT_WPS;
|
||||
eapol_sm_notify_config(wpa_s->eapol, &ssid->eap, &eapol_conf);
|
||||
#endif /* IEEE8021X_EAPOL */
|
||||
}
|
||||
|
@ -302,7 +304,9 @@ void wpa_supplicant_set_non_wpa_policy(struct wpa_supplicant *wpa_s,
|
|||
{
|
||||
int i;
|
||||
|
||||
if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA)
|
||||
if (ssid->key_mgmt & WPA_KEY_MGMT_WPS)
|
||||
wpa_s->key_mgmt = WPA_KEY_MGMT_WPS;
|
||||
else if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA)
|
||||
wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_NO_WPA;
|
||||
else
|
||||
wpa_s->key_mgmt = WPA_KEY_MGMT_NONE;
|
||||
|
@ -635,6 +639,8 @@ static wpa_key_mgmt key_mgmt2driver(int key_mgmt)
|
|||
return KEY_MGMT_802_1X_SHA256;
|
||||
case WPA_KEY_MGMT_PSK_SHA256:
|
||||
return KEY_MGMT_PSK_SHA256;
|
||||
case WPA_KEY_MGMT_WPS:
|
||||
return KEY_MGMT_WPS;
|
||||
case WPA_KEY_MGMT_PSK:
|
||||
default:
|
||||
return KEY_MGMT_PSK;
|
||||
|
@ -1001,6 +1007,16 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
|
|||
"results)");
|
||||
return;
|
||||
}
|
||||
#ifdef CONFIG_WPS
|
||||
} else if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) {
|
||||
struct wpabuf *wps_ie = wps_enrollee_build_assoc_req_ie();
|
||||
if (wps_ie && wpabuf_len(wps_ie) <= sizeof(wpa_ie)) {
|
||||
wpa_ie_len = wpabuf_len(wps_ie);
|
||||
os_memcpy(wpa_ie, wpabuf_head(wps_ie), wpa_ie_len);
|
||||
}
|
||||
wpabuf_free(wps_ie);
|
||||
wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
|
||||
#endif /* CONFIG_WPS */
|
||||
} else {
|
||||
wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
|
||||
wpa_ie_len = 0;
|
||||
|
@ -1019,6 +1035,8 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
|
|||
wep_keys_set = 1;
|
||||
}
|
||||
}
|
||||
if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS)
|
||||
use_crypt = 0;
|
||||
|
||||
#ifdef IEEE8021X_EAPOL
|
||||
if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
|
||||
|
|
|
@ -397,6 +397,8 @@ fast_reauth=1
|
|||
# * 0 = do not use cryptobinding (default)
|
||||
# * 1 = use cryptobinding if server supports it
|
||||
# * 2 = require cryptobinding
|
||||
# EAP-WSC (WPS) uses following options: pin=<Device Password> and
|
||||
# uuid=<Device UUID>.
|
||||
# phase2: Phase2 (inner authentication with TLS tunnel) parameters
|
||||
# (string with field-value pairs, e.g., "auth=MSCHAPV2" for EAP-PEAP or
|
||||
# "autheap=MSCHAPV2 autheap=MD5" for EAP-TTLS)
|
||||
|
|
|
@ -25,6 +25,8 @@
|
|||
#include "pmksa_cache.h"
|
||||
#include "mlme.h"
|
||||
#include "ieee802_11_defs.h"
|
||||
#include "wps/wps.h"
|
||||
#include "wps/wps_defs.h"
|
||||
#include "wpa_ctrl.h"
|
||||
#include "wpas_glue.h"
|
||||
|
||||
|
@ -228,6 +230,19 @@ static void wpa_supplicant_eapol_cb(struct eapol_sm *eapol, int success,
|
|||
wpa_printf(MSG_DEBUG, "EAPOL authentication completed %ssuccessfully",
|
||||
success ? "" : "un");
|
||||
|
||||
#ifdef CONFIG_WPS
|
||||
if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS && wpa_s->current_ssid &&
|
||||
!(wpa_s->current_ssid->key_mgmt & WPA_KEY_MGMT_WPS)) {
|
||||
wpa_printf(MSG_DEBUG, "WPS: Network configuration replaced - "
|
||||
"try to associate with the received credential");
|
||||
wpa_supplicant_deauthenticate(wpa_s,
|
||||
WLAN_REASON_DEAUTH_LEAVING);
|
||||
wpa_s->reassociate = 1;
|
||||
wpa_supplicant_req_scan(wpa_s, 0, 0);
|
||||
return;
|
||||
}
|
||||
#endif /* CONFIG_WPS */
|
||||
|
||||
if (!success) {
|
||||
/*
|
||||
* Make sure we do not get stuck here waiting for long EAPOL
|
||||
|
@ -491,6 +506,139 @@ static int wpa_supplicant_send_ft_action(void *ctx, u8 action,
|
|||
#endif /* CONFIG_NO_WPA */
|
||||
|
||||
|
||||
#ifdef CONFIG_WPS
|
||||
static int wpa_supplicant_wps_cred(void *ctx, struct wps_credential *cred)
|
||||
{
|
||||
struct wpa_supplicant *wpa_s = ctx;
|
||||
struct wpa_ssid *ssid = wpa_s->current_ssid;
|
||||
|
||||
wpa_msg(wpa_s, MSG_INFO, "WPS: New credential received");
|
||||
|
||||
if (ssid && (ssid->key_mgmt & WPA_KEY_MGMT_WPS)) {
|
||||
wpa_printf(MSG_DEBUG, "WPS: Replace WPS network block based "
|
||||
"on the received credential");
|
||||
os_free(ssid->eap.identity);
|
||||
ssid->eap.identity = NULL;
|
||||
ssid->eap.identity_len = 0;
|
||||
os_free(ssid->eap.phase1);
|
||||
ssid->eap.phase1 = NULL;
|
||||
os_free(ssid->eap.eap_methods);
|
||||
ssid->eap.eap_methods = NULL;
|
||||
} else {
|
||||
wpa_printf(MSG_DEBUG, "WPS: Create a new network based on the "
|
||||
"received credential");
|
||||
ssid = wpa_config_add_network(wpa_s->conf);
|
||||
if (ssid == NULL)
|
||||
return -1;
|
||||
}
|
||||
|
||||
wpa_config_set_network_defaults(ssid);
|
||||
|
||||
os_free(ssid->ssid);
|
||||
ssid->ssid = os_malloc(cred->ssid_len);
|
||||
if (ssid->ssid) {
|
||||
os_memcpy(ssid->ssid, cred->ssid, cred->ssid_len);
|
||||
ssid->ssid_len = cred->ssid_len;
|
||||
}
|
||||
|
||||
switch (cred->encr_type) {
|
||||
case WPS_ENCR_NONE:
|
||||
ssid->pairwise_cipher = ssid->group_cipher = WPA_CIPHER_NONE;
|
||||
break;
|
||||
case WPS_ENCR_WEP:
|
||||
ssid->pairwise_cipher = ssid->group_cipher =
|
||||
WPA_CIPHER_WEP40 | WPA_CIPHER_WEP104;
|
||||
if (cred->key_len > 0 && cred->key_len <= MAX_WEP_KEY_LEN &&
|
||||
cred->key_idx < NUM_WEP_KEYS) {
|
||||
os_memcpy(ssid->wep_key[cred->key_idx], cred->key,
|
||||
cred->key_len);
|
||||
ssid->wep_key_len[cred->key_idx] = cred->key_len;
|
||||
ssid->wep_tx_keyidx = cred->key_idx;
|
||||
}
|
||||
break;
|
||||
case WPS_ENCR_TKIP:
|
||||
ssid->pairwise_cipher = WPA_CIPHER_TKIP;
|
||||
ssid->group_cipher = WPA_CIPHER_TKIP;
|
||||
break;
|
||||
case WPS_ENCR_AES:
|
||||
ssid->pairwise_cipher = WPA_CIPHER_CCMP;
|
||||
ssid->group_cipher = WPA_CIPHER_CCMP | WPA_CIPHER_TKIP;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (cred->auth_type) {
|
||||
case WPS_AUTH_OPEN:
|
||||
ssid->auth_alg = WPA_AUTH_ALG_OPEN;
|
||||
ssid->key_mgmt = WPA_KEY_MGMT_NONE;
|
||||
ssid->proto = 0;
|
||||
break;
|
||||
case WPS_AUTH_SHARED:
|
||||
ssid->auth_alg = WPA_AUTH_ALG_SHARED;
|
||||
ssid->key_mgmt = WPA_KEY_MGMT_NONE;
|
||||
ssid->proto = 0;
|
||||
break;
|
||||
case WPS_AUTH_WPAPSK:
|
||||
ssid->auth_alg = WPA_AUTH_ALG_OPEN;
|
||||
ssid->key_mgmt = WPA_KEY_MGMT_PSK;
|
||||
ssid->proto = WPA_PROTO_WPA;
|
||||
break;
|
||||
case WPS_AUTH_WPA:
|
||||
ssid->auth_alg = WPA_AUTH_ALG_OPEN;
|
||||
ssid->key_mgmt = WPA_KEY_MGMT_IEEE8021X;
|
||||
ssid->proto = WPA_PROTO_WPA;
|
||||
break;
|
||||
case WPS_AUTH_WPA2:
|
||||
ssid->auth_alg = WPA_AUTH_ALG_OPEN;
|
||||
ssid->key_mgmt = WPA_KEY_MGMT_IEEE8021X;
|
||||
ssid->proto = WPA_PROTO_RSN;
|
||||
break;
|
||||
case WPS_AUTH_WPA2PSK:
|
||||
ssid->auth_alg = WPA_AUTH_ALG_OPEN;
|
||||
ssid->key_mgmt = WPA_KEY_MGMT_PSK;
|
||||
ssid->proto = WPA_PROTO_RSN;
|
||||
break;
|
||||
}
|
||||
|
||||
if (ssid->key_mgmt == WPA_KEY_MGMT_PSK) {
|
||||
if (cred->key_len == 2 * PMK_LEN) {
|
||||
if (hexstr2bin((const char *) cred->key, ssid->psk,
|
||||
PMK_LEN)) {
|
||||
wpa_printf(MSG_ERROR, "WPS: Invalid Network "
|
||||
"Key");
|
||||
return -1;
|
||||
}
|
||||
ssid->psk_set = 1;
|
||||
} else if (cred->key_len >= 8 && cred->key_len < 2 * PMK_LEN) {
|
||||
os_free(ssid->passphrase);
|
||||
ssid->passphrase = os_malloc(cred->key_len + 1);
|
||||
if (ssid->passphrase == NULL)
|
||||
return -1;
|
||||
os_memcpy(ssid->passphrase, cred->key, cred->key_len);
|
||||
ssid->passphrase[cred->key_len] = '\0';
|
||||
wpa_config_update_psk(ssid);
|
||||
} else {
|
||||
wpa_printf(MSG_ERROR, "WPS: Invalid Network Key "
|
||||
"length %lu",
|
||||
(unsigned long) cred->key_len);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef CONFIG_NO_CONFIG_WRITE
|
||||
if (wpa_s->conf->update_config &&
|
||||
wpa_config_write(wpa_s->confname, wpa_s->conf)) {
|
||||
wpa_printf(MSG_DEBUG, "WPS: Failed to update configuration");
|
||||
return -1;
|
||||
}
|
||||
#endif /* CONFIG_NO_CONFIG_WRITE */
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else /* CONFIG_WPS */
|
||||
#define wpa_supplicant_wps_cred NULL
|
||||
#endif /* CONFIG_WPS */
|
||||
|
||||
|
||||
#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
|
||||
static void wpa_supplicant_eap_param_needed(void *ctx, const char *field,
|
||||
const char *txt)
|
||||
|
@ -554,6 +702,8 @@ int wpa_supplicant_init_eapol(struct wpa_supplicant *wpa_s)
|
|||
ctx->pkcs11_engine_path = wpa_s->conf->pkcs11_engine_path;
|
||||
ctx->pkcs11_module_path = wpa_s->conf->pkcs11_module_path;
|
||||
#endif /* EAP_TLS_OPENSSL */
|
||||
ctx->mac_addr = wpa_s->own_addr;
|
||||
ctx->wps_cred = wpa_supplicant_wps_cred;
|
||||
ctx->eap_param_needed = wpa_supplicant_eap_param_needed;
|
||||
ctx->cb = wpa_supplicant_eapol_cb;
|
||||
ctx->cb_ctx = wpa_s;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue