diff --git a/wpa_supplicant/Makefile b/wpa_supplicant/Makefile index 2a068d764..d6a5b87e9 100644 --- a/wpa_supplicant/Makefile +++ b/wpa_supplicant/Makefile @@ -500,6 +500,7 @@ CFLAGS += -DCONFIG_WPS -DEAP_WSC_DYNAMIC EAPDYN += ../src/eap_peer/eap_wsc.so else CFLAGS += -DCONFIG_WPS -DEAP_WSC +OBJS += wps_supplicant.o OBJS += ../src/utils/uuid.o OBJS += ../src/eap_peer/eap_wsc.o ../src/eap_common/eap_wsc_common.o OBJS += ../src/wps/wps.o diff --git a/wpa_supplicant/wpas_glue.c b/wpa_supplicant/wpas_glue.c index 8ea962291..ddcc0ec5a 100644 --- a/wpa_supplicant/wpas_glue.c +++ b/wpa_supplicant/wpas_glue.c @@ -25,10 +25,9 @@ #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" +#include "wps_supplicant.h" #ifndef CONFIG_NO_CONFIG_BLOBS @@ -230,18 +229,8 @@ 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); + if (wpas_wps_eapol_cb(wpa_s) > 0) return; - } -#endif /* CONFIG_WPS */ if (!success) { /* @@ -506,139 +495,6 @@ 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) @@ -704,7 +560,7 @@ int wpa_supplicant_init_eapol(struct wpa_supplicant *wpa_s) #endif /* EAP_TLS_OPENSSL */ ctx->mac_addr = wpa_s->own_addr; ctx->uuid = wpa_s->conf->uuid; - ctx->wps_cred = wpa_supplicant_wps_cred; + ctx->wps_cred = wpas_wps_get_cred_cb(); ctx->eap_param_needed = wpa_supplicant_eap_param_needed; ctx->cb = wpa_supplicant_eapol_cb; ctx->cb_ctx = wpa_s; diff --git a/wpa_supplicant/wps_supplicant.c b/wpa_supplicant/wps_supplicant.c new file mode 100644 index 000000000..0aca1018b --- /dev/null +++ b/wpa_supplicant/wps_supplicant.c @@ -0,0 +1,176 @@ +/* + * wpa_supplicant / WPS integration + * Copyright (c) 2008, Jouni Malinen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Alternatively, this software may be distributed under the terms of BSD + * license. + * + * See README and COPYING for more details. + */ + +#include "includes.h" + +#include "common.h" +#include "ieee802_11_defs.h" +#include "wpa_common.h" +#include "config.h" +#include "wpa_supplicant_i.h" +#include "wps/wps.h" +#include "wps/wps_defs.h" +#include "wps_supplicant.h" + + +int wpas_wps_eapol_cb(struct wpa_supplicant *wpa_s) +{ + 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 1; + } + + return 0; +} + + +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; +} + + +void * wpas_wps_get_cred_cb(void) +{ + return wpa_supplicant_wps_cred; +} diff --git a/wpa_supplicant/wps_supplicant.h b/wpa_supplicant/wps_supplicant.h new file mode 100644 index 000000000..317362458 --- /dev/null +++ b/wpa_supplicant/wps_supplicant.h @@ -0,0 +1,37 @@ +/* + * wpa_supplicant / WPS integration + * Copyright (c) 2008, Jouni Malinen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Alternatively, this software may be distributed under the terms of BSD + * license. + * + * See README and COPYING for more details. + */ + +#ifndef WPS_SUPPLICANT_H +#define WPS_SUPPLICANT_H + +#ifdef CONFIG_WPS + +int wpas_wps_eapol_cb(struct wpa_supplicant *wpa_s); +void * wpas_wps_get_cred_cb(void); + +#else /* CONFIG_WPS */ + +static inline int wpas_wps_eapol_cb(struct wpa_supplicant *wpa_s) +{ + return 0; +} + +static inline void * wpas_wps_get_cred_cb(void) +{ + return NULL; +} + +#endif /* CONFIG_WPS */ + +#endif /* WPS_SUPPLICANT_H */