Parcourir la source

WPS: Add configurable option for processing credentials externally

The wps_cred_process option can be used to configure wpa_supplicant to
send received Credential attributes for external processing over
ctrl_iface and dbus. This allows external programs to update their
configuration when WPS is used to provision new networks.
Jouni Malinen il y a 16 ans
Parent
commit
476621644c

+ 11 - 0
wpa_supplicant/config.h

@@ -312,6 +312,17 @@ struct wpa_config {
 	 * in
 	 */
 	char country[2];
+
+	/**
+	 * wps_cred_processing - Credential processing
+	 *
+	 *   0 = process received credentials internally
+	 *   1 = do not process received credentials; just pass them over
+	 *	ctrl_iface to external program(s)
+	 *   2 = process received credentials internally and pass them over
+	 *	ctrl_iface to external program(s)
+	 */
+	int wps_cred_processing;
 };
 
 

+ 4 - 0
wpa_supplicant/config_file.c

@@ -456,6 +456,7 @@ static const struct global_parse_data global_fields[] = {
 	{ STR_RANGE(serial_number, 0, 32) },
 	{ STR(device_type) },
 	{ FUNC(os_version) },
+	{ INT_RANGE(wps_cred_processing, 0, 2) },
 #endif /* CONFIG_WPS */
 	{ FUNC(country) }
 };
@@ -881,6 +882,9 @@ static void wpa_config_write_global(FILE *f, struct wpa_config *config)
 	if (WPA_GET_BE32(config->os_version))
 		fprintf(f, "os_version=%08x\n",
 			WPA_GET_BE32(config->os_version));
+	if (config->wps_cred_processing)
+		fprintf(f, "wps_cred_processing=%d\n",
+			config->wps_cred_processing);
 #endif /* CONFIG_WPS */
 	if (config->country[0] && config->country[1]) {
 		fprintf(f, "country=%c%c\n",

+ 4 - 0
wpa_supplicant/config_winreg.c

@@ -251,6 +251,8 @@ static int wpa_config_read_global(struct wpa_config *config, HKEY hk)
 		hk, TEXT("device_type"));
 	if (wpa_config_read_global_os_version(config, hk))
 		errors++;
+	wpa_config_read_reg_dword(hk, TEXT("wps_cred_processing"),
+				  &config->wps_cred_processing);
 #endif /* CONFIG_WPS */
 
 	return errors ? -1 : 0;
@@ -573,6 +575,8 @@ static int wpa_config_write_global(struct wpa_config *config, HKEY hk)
 			    WPA_GET_BE32(config->os_version));
 		wpa_config_write_reg_string(hk, "os_version", vbuf);
 	}
+	wpa_config_write_reg_dword(hk, TEXT("wps_cred_processing"),
+				   config->wps_cred_processing, 0);
 #endif /* CONFIG_WPS */
 
 	return 0;

+ 58 - 0
wpa_supplicant/ctrl_iface_dbus.c

@@ -18,6 +18,7 @@
 #include "eloop.h"
 #include "config.h"
 #include "wpa_supplicant_i.h"
+#include "wps/wps.h"
 #include "ctrl_iface_dbus.h"
 #include "ctrl_iface_dbus_handlers.h"
 
@@ -738,6 +739,63 @@ out:
 }
 
 
+#ifdef CONFIG_WPS
+void wpa_supplicant_dbus_notify_wps_cred(struct wpa_supplicant *wpa_s,
+					 const struct wps_credential *cred)
+{
+	struct ctrl_iface_dbus_priv *iface;
+	DBusMessage *_signal = NULL;
+	const char *path;
+
+	/* Do nothing if the control interface is not turned on */
+	if (wpa_s->global == NULL)
+		return;
+	iface = wpa_s->global->dbus_ctrl_iface;
+	if (iface == NULL)
+		return;
+
+	path = wpa_supplicant_get_dbus_path(wpa_s);
+	if (path == NULL) {
+		perror("wpa_supplicant_dbus_notify_wps_cred[dbus]: "
+		       "interface didn't have a dbus path");
+		wpa_printf(MSG_ERROR,
+		           "wpa_supplicant_dbus_notify_wps_cred[dbus]: "
+		           "interface didn't have a dbus path; can't send "
+		           "signal.");
+		return;
+	}
+	_signal = dbus_message_new_signal(path, WPAS_DBUS_IFACE_INTERFACE,
+					  "WpsCred");
+	if (_signal == NULL) {
+		perror("wpa_supplicant_dbus_notify_wps_cred[dbus]: "
+		       "couldn't create dbus signal; likely out of memory");
+		wpa_printf(MSG_ERROR,
+		           "wpa_supplicant_dbus_notify_wps_cred[dbus]: "
+		           "couldn't create dbus signal; likely out of "
+		           "memory.");
+		return;
+	}
+
+	if (!dbus_message_append_args(_signal,
+	                              DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
+				      &cred->cred_attr, cred->cred_attr_len,
+	                              DBUS_TYPE_INVALID)) {
+		perror("wpa_supplicant_dbus_notify_wps_cred[dbus]: "
+		       "not enough memory to construct signal.");
+		wpa_printf(MSG_ERROR,
+		           "wpa_supplicant_dbus_notify_wps_cred[dbus]: "
+		           "not enough memory to construct signal.");
+		goto out;
+	}
+
+	dbus_connection_send(iface->con, _signal, NULL);
+
+out:
+	dbus_message_unref(_signal);
+}
+#endif /* CONFIG_WPS */
+
+
 /**
  * integrate_with_eloop - Register our mainloop integration with dbus
  * @connection: connection to the system message bus

+ 10 - 0
wpa_supplicant/ctrl_iface_dbus.h

@@ -15,6 +15,8 @@
 #ifndef CTRL_IFACE_DBUS_H
 #define CTRL_IFACE_DBUS_H
 
+struct wps_credential;
+
 #ifdef CONFIG_CTRL_IFACE_DBUS
 
 #ifndef SIGPOLL
@@ -84,6 +86,8 @@ void wpa_supplicant_dbus_notify_scan_results(struct wpa_supplicant *wpa_s);
 void wpa_supplicant_dbus_notify_state_change(struct wpa_supplicant *wpa_s,
 					     wpa_states new_state,
 					     wpa_states old_state);
+void wpa_supplicant_dbus_notify_wps_cred(struct wpa_supplicant *wpa_s,
+					 const struct wps_credential *cred);
 
 char * wpas_dbus_decompose_object_path(const char *path, char **network,
                                        char **bssid);
@@ -129,6 +133,12 @@ wpa_supplicant_dbus_notify_state_change(struct wpa_supplicant *wpa_s,
 {
 }
 
+static inline void
+wpa_supplicant_dbus_notify_wps_cred(struct wpa_supplicant *wpa_s,
+				    const struct wps_credential *cred)
+{
+}
+
 static inline int
 wpas_dbus_register_iface(struct wpa_supplicant *wpa_s)
 {

+ 7 - 0
wpa_supplicant/wpa_supplicant.conf

@@ -190,6 +190,13 @@ fast_reauth=1
 # 4-octet operating system version number (hex string)
 #os_version=01020300
 
+# Credential processing
+#   0 = process received credentials internally (default)
+#   1 = do not process received credentials; just pass them over ctrl_iface to
+#	external program(s)
+#   2 = process received credentials internally and pass them over ctrl_iface
+#	to external program(s)
+#wps_cred_processing=0
 
 # network block
 #

+ 27 - 1
wpa_supplicant/wps_supplicant.c

@@ -23,6 +23,7 @@
 #include "eloop.h"
 #include "uuid.h"
 #include "wpa_ctrl.h"
+#include "ctrl_iface_dbus.h"
 #include "eap_common/eap_wsc_common.h"
 #include "wps_supplicant.h"
 
@@ -46,6 +47,15 @@ int wpas_wps_eapol_cb(struct wpa_supplicant *wpa_s)
 		return 1;
 	}
 
+	if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS && wpa_s->current_ssid) {
+		wpa_printf(MSG_DEBUG, "WPS: Registration completed - waiting "
+			   "for external credential processing");
+		wpas_clear_wps(wpa_s);
+		wpa_supplicant_deauthenticate(wpa_s,
+					      WLAN_REASON_DEAUTH_LEAVING);
+		return 1;
+	}
+
 	return 0;
 }
 
@@ -56,11 +66,27 @@ static int wpa_supplicant_wps_cred(void *ctx,
 	struct wpa_supplicant *wpa_s = ctx;
 	struct wpa_ssid *ssid = wpa_s->current_ssid;
 
-	wpa_msg(wpa_s, MSG_INFO, WPS_EVENT_CRED_RECEIVED);
+	if ((wpa_s->conf->wps_cred_processing == 1 ||
+	     wpa_s->conf->wps_cred_processing == 2) && cred->cred_attr) {
+		size_t blen = cred->cred_attr_len * 2 + 1;
+		char *buf = os_malloc(blen);
+		if (buf) {
+			wpa_snprintf_hex(buf, blen,
+					 cred->cred_attr, cred->cred_attr_len);
+			wpa_msg(wpa_s, MSG_INFO, "%s%s",
+				WPS_EVENT_CRED_RECEIVED, buf);
+			os_free(buf);
+		}
+		wpa_supplicant_dbus_notify_wps_cred(wpa_s, cred);
+	} else
+		wpa_msg(wpa_s, MSG_INFO, WPS_EVENT_CRED_RECEIVED);
 
 	wpa_hexdump_key(MSG_DEBUG, "WPS: Received Credential attribute",
 			cred->cred_attr, cred->cred_attr_len);
 
+	if (wpa_s->conf->wps_cred_processing == 1)
+		return 0;
+
 	if (cred->auth_type != WPS_AUTH_OPEN &&
 	    cred->auth_type != WPS_AUTH_SHARED &&
 	    cred->auth_type != WPS_AUTH_WPAPSK &&