Parcourir la source

wpa_supplicant AP: Add preliminary support for WPS Internal Registrar

When in AP mode, wpa_supplicant is now enabling WPS (only Internal
Registrar). wpa_cli wps_pbc and wps_pin commands can be used to initiate
WPS negotiation similarly to how this is done in station mode (though,
the BSSID parameter is ignored).
Jouni Malinen il y a 16 ans
Parent
commit
3ec97afe57

+ 3 - 3
src/eap_server/eap_methods.h

@@ -12,8 +12,8 @@
  * See README and COPYING for more details.
  */
 
-#ifndef EAP_METHODS_H
-#define EAP_METHODS_H
+#ifndef EAP_SERVER_METHODS_H
+#define EAP_SERVER_METHODS_H
 
 const struct eap_method * eap_server_get_eap_method(int vendor,
 						    EapType method);
@@ -26,4 +26,4 @@ EapType eap_server_get_type(const char *name, int *vendor);
 int eap_server_register_methods(void);
 void eap_server_unregister_methods(void);
 
-#endif /* EAP_METHODS_H */
+#endif /* EAP_SERVER_METHODS_H */

+ 41 - 0
wpa_supplicant/ap.c

@@ -21,9 +21,11 @@
 #ifdef NEED_MLME
 #include "../hostapd/ieee802_11.h"
 #endif /* NEED_MLME */
+#include "../hostapd/wps_hostapd.h"
 #include "eap_common/eap_defs.h"
 #include "eap_server/eap_methods.h"
 #include "eap_common/eap_wsc_common.h"
+#include "wps/wps.h"
 #include "config_ssid.h"
 #include "wpa_supplicant_i.h"
 #include "driver_i.h"
@@ -382,6 +384,17 @@ static int wpa_supplicant_conf_ap(struct wpa_supplicant *wpa_s,
 	else
 		bss->ssid.security_policy = SECURITY_PLAINTEXT;
 
+#ifdef CONFIG_WPS
+	/*
+	 * Enable WPS by default, but require user interaction to actually use
+	 * it. Only the internal Registrar is supported.
+	 */
+	bss->eap_server = 1;
+	bss->wps_state = 2;
+	bss->ap_setup_locked = 1;
+	bss->config_methods = os_strdup("display push_button");
+#endif /* CONFIG_WPS */
+
 	return 0;
 }
 
@@ -507,3 +520,31 @@ void wpa_supplicant_ap_rx_eapol(struct wpa_supplicant *wpa_s,
 {
 	hostapd_eapol_receive(wpa_s->ap_iface->bss[0], src_addr, buf, len);
 }
+
+
+#ifdef CONFIG_WPS
+
+int wpa_supplicant_ap_wps_pbc(struct wpa_supplicant *wpa_s, const u8 *bssid)
+{
+	return hostapd_wps_button_pushed(wpa_s->ap_iface->bss[0]);
+}
+
+
+int wpa_supplicant_ap_wps_pin(struct wpa_supplicant *wpa_s, const u8 *bssid,
+			      const char *pin, char *buf, size_t buflen)
+{
+	int ret, ret_len = 0;
+
+	if (pin == NULL) {
+		unsigned int rpin = wps_generate_pin();
+		ret_len = os_snprintf(buf, buflen, "%d", rpin);
+		pin = buf;
+	}
+
+	ret = hostapd_wps_add_pin(wpa_s->ap_iface->bss[0], "any", pin);
+	if (ret)
+		return -1;
+	return ret_len;
+}
+
+#endif /* CONFIG_WPS */

+ 3 - 0
wpa_supplicant/ap.h

@@ -21,5 +21,8 @@ int wpa_supplicant_create_ap(struct wpa_supplicant *wpa_s,
 void wpa_supplicant_ap_deinit(struct wpa_supplicant *wpa_s);
 void wpa_supplicant_ap_rx_eapol(struct wpa_supplicant *wpa_s,
 				const u8 *src_addr, const u8 *buf, size_t len);
+int wpa_supplicant_ap_wps_pbc(struct wpa_supplicant *wpa_s, const u8 *bssid);
+int wpa_supplicant_ap_wps_pin(struct wpa_supplicant *wpa_s, const u8 *bssid,
+			      const char *pin, char *buf, size_t buflen);
 
 #endif /* AP_H */

+ 16 - 5
wpa_supplicant/ctrl_iface.c

@@ -31,6 +31,7 @@
 #include "wps_supplicant.h"
 #include "wps/wps.h"
 #include "ibss_rsn.h"
+#include "ap.h"
 
 extern struct wpa_driver_ops *wpa_drivers[];
 
@@ -150,18 +151,22 @@ static int wpa_supplicant_ctrl_iface_ft_ds(
 static int wpa_supplicant_ctrl_iface_wps_pbc(struct wpa_supplicant *wpa_s,
 					     char *cmd)
 {
-	u8 bssid[ETH_ALEN];
+	u8 bssid[ETH_ALEN], *_bssid = bssid;
 
 	if (cmd == NULL || os_strcmp(cmd, "any") == 0)
-		return wpas_wps_start_pbc(wpa_s, NULL);
-
-	if (hwaddr_aton(cmd, bssid)) {
+		_bssid = NULL;
+	else if (hwaddr_aton(cmd, bssid)) {
 		wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PBC: invalid BSSID '%s'",
 			   cmd);
 		return -1;
 	}
 
-	return wpas_wps_start_pbc(wpa_s, bssid);
+#ifdef CONFIG_AP
+	if (wpa_s->ap_iface)
+		return wpa_supplicant_ap_wps_pbc(wpa_s, _bssid);
+#endif /* CONFIG_AP */
+
+	return wpas_wps_start_pbc(wpa_s, _bssid);
 }
 
 
@@ -185,6 +190,12 @@ static int wpa_supplicant_ctrl_iface_wps_pin(struct wpa_supplicant *wpa_s,
 		return -1;
 	}
 
+#ifdef CONFIG_AP
+	if (wpa_s->ap_iface)
+		return wpa_supplicant_ap_wps_pin(wpa_s, _bssid, pin,
+						 buf, buflen);
+#endif /* CONFIG_AP */
+
 	if (pin) {
 		ret = wpas_wps_start_pin(wpa_s, _bssid, pin);
 		if (ret < 0)

+ 15 - 0
wpa_supplicant/wpa_supplicant.c

@@ -21,6 +21,7 @@
 #include "common.h"
 #include "eapol_supp/eapol_supp_sm.h"
 #include "eap_peer/eap.h"
+#include "eap_server/eap_methods.h"
 #include "wpa.h"
 #include "eloop.h"
 #include "config.h"
@@ -2118,6 +2119,17 @@ struct wpa_global * wpa_supplicant_init(struct wpa_params *params)
 		return NULL;
 	}
 
+#ifdef CONFIG_AP
+	ret = eap_server_register_methods();
+	if (ret) {
+		wpa_printf(MSG_ERROR, "Failed to register EAP server methods");
+		if (ret == -2)
+			wpa_printf(MSG_ERROR, "Two or more EAP methods used "
+				   "the same EAP type.");
+		return NULL;
+	}
+#endif /* CONFIG_AP */
+
 	global = os_zalloc(sizeof(*global));
 	if (global == NULL)
 		return NULL;
@@ -2241,6 +2253,9 @@ void wpa_supplicant_deinit(struct wpa_global *global)
 		wpa_supplicant_dbus_ctrl_iface_deinit(global->dbus_ctrl_iface);
 
 	eap_peer_unregister_methods();
+#ifdef CONFIG_AP
+	eap_server_unregister_methods();
+#endif /* CONFIG_AP */
 
 	for (i = 0; wpa_drivers[i] && global->drv_priv; i++) {
 		if (!global->drv_priv[i])