WPS: Add configurable option for processing credentials externally
authorJouni Malinen <j@w1.fi>
Sun, 18 Jan 2009 10:27:12 +0000 (12:27 +0200)
committerJouni Malinen <j@w1.fi>
Sun, 18 Jan 2009 10:27:12 +0000 (12:27 +0200)
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.

wpa_supplicant/config.h
wpa_supplicant/config_file.c
wpa_supplicant/config_winreg.c
wpa_supplicant/ctrl_iface_dbus.c
wpa_supplicant/ctrl_iface_dbus.h
wpa_supplicant/wpa_supplicant.conf
wpa_supplicant/wps_supplicant.c

index 0cea4dc..4484e91 100644 (file)
@@ -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;
 };
 
 
index f544a56..29e494c 100644 (file)
@@ -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",
index 0199642..456d417 100644 (file)
@@ -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;
index 7f2fba4..b772247 100644 (file)
@@ -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
index b66c179..68919de 100644 (file)
@@ -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)
 {
index cfcea88..4b1f90b 100644 (file)
@@ -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
 #
index fb1d833..14f1f86 100644 (file)
@@ -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 &&