Browse 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 16 years ago
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])