WPS: Add support for NFC configuration token from external program
authorJouni Malinen <j@w1.fi>
Thu, 28 Jun 2012 10:59:29 +0000 (13:59 +0300)
committerJouni Malinen <j@w1.fi>
Thu, 28 Jun 2012 10:59:29 +0000 (13:59 +0300)
The new wpa_supplicant ctrl_iface command WPS_NFC_TAG_READ can now be
used to process NFC tags read by external programs to initiate
wpa_supplicant to use NFC Configuration Token to create a new network.

Signed-hostap: Jouni Malinen <j@w1.fi>

src/wps/wps.h
src/wps/wps_common.c
wpa_supplicant/ctrl_iface.c
wpa_supplicant/wpa_cli.c
wpa_supplicant/wps_supplicant.c
wpa_supplicant/wps_supplicant.h

index ca2f55c..dd84f1b 100644 (file)
@@ -27,6 +27,7 @@ enum wsc_op_code {
 struct wps_registrar;
 struct upnp_wps_device_sm;
 struct wps_er;
+struct wps_parse_attr;
 
 /**
  * struct wps_credential - WPS Credential
@@ -818,6 +819,7 @@ int wps_get_oob_method(char *method);
 int wps_process_oob(struct wps_context *wps, struct oob_device_data *oob_dev,
                    int registrar);
 struct wpabuf * wps_get_oob_cred(struct wps_context *wps);
+int wps_oob_use_cred(struct wps_context *wps, struct wps_parse_attr *attr);
 int wps_attr_text(struct wpabuf *data, char *buf, char *end);
 
 struct wps_er * wps_er_init(struct wps_context *wps, const char *ifname,
index 35ebec0..16412ca 100644 (file)
@@ -437,23 +437,17 @@ static int wps_parse_oob_dev_pwd(struct wps_context *wps,
 }
 
 
-static int wps_parse_oob_cred(struct wps_context *wps, struct wpabuf *data)
+int wps_oob_use_cred(struct wps_context *wps, struct wps_parse_attr *attr)
 {
        struct wpabuf msg;
-       struct wps_parse_attr attr;
        size_t i;
 
-       if (wps_parse_msg(data, &attr) < 0 || attr.num_cred <= 0) {
-               wpa_printf(MSG_ERROR, "WPS: OOB credential not found");
-               return -1;
-       }
-
-       for (i = 0; i < attr.num_cred; i++) {
+       for (i = 0; i < attr->num_cred; i++) {
                struct wps_credential local_cred;
                struct wps_parse_attr cattr;
 
                os_memset(&local_cred, 0, sizeof(local_cred));
-               wpabuf_set(&msg, attr.cred[i], attr.cred_len[i]);
+               wpabuf_set(&msg, attr->cred[i], attr->cred_len[i]);
                if (wps_parse_msg(&msg, &cattr) < 0 ||
                    wps_process_cred(&cattr, &local_cred)) {
                        wpa_printf(MSG_ERROR, "WPS: Failed to parse OOB "
@@ -467,6 +461,19 @@ static int wps_parse_oob_cred(struct wps_context *wps, struct wpabuf *data)
 }
 
 
+static int wps_parse_oob_cred(struct wps_context *wps, struct wpabuf *data)
+{
+       struct wps_parse_attr attr;
+
+       if (wps_parse_msg(data, &attr) < 0 || attr.num_cred <= 0) {
+               wpa_printf(MSG_ERROR, "WPS: OOB credential not found");
+               return -1;
+       }
+
+       return wps_oob_use_cred(wps, &attr);
+}
+
+
 int wps_process_oob(struct wps_context *wps, struct oob_device_data *oob_dev,
                    int registrar)
 {
index 2ef42ac..4a8478c 100644 (file)
@@ -662,6 +662,33 @@ static int wpa_supplicant_ctrl_iface_wps_nfc_token(
 
        return res;
 }
+
+
+static int wpa_supplicant_ctrl_iface_wps_nfc_tag_read(
+       struct wpa_supplicant *wpa_s, char *pos)
+{
+       size_t len;
+       struct wpabuf *buf;
+       int ret;
+
+       len = os_strlen(pos);
+       if (len & 0x01)
+               return -1;
+       len /= 2;
+
+       buf = wpabuf_alloc(len);
+       if (buf == NULL)
+               return -1;
+       if (hexstr2bin(pos, wpabuf_put(buf, len), len) < 0) {
+               wpabuf_free(buf);
+               return -1;
+       }
+
+       ret = wpas_wps_nfc_tag_read(wpa_s, buf);
+       wpabuf_free(buf);
+
+       return ret;
+}
 #endif /* CONFIG_WPS_OOB */
 
 
@@ -4100,6 +4127,10 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
        } else if (os_strncmp(buf, "WPS_NFC_TOKEN ", 14) == 0) {
                reply_len = wpa_supplicant_ctrl_iface_wps_nfc_token(
                        wpa_s, buf + 14, reply, reply_size);
+       } else if (os_strncmp(buf, "WPS_NFC_TAG_READ ", 17) == 0) {
+               if (wpa_supplicant_ctrl_iface_wps_nfc_tag_read(wpa_s,
+                                                              buf + 17))
+                       reply_len = -1;
 #endif /* CONFIG_WPS_OOB */
        } else if (os_strncmp(buf, "WPS_REG ", 8) == 0) {
                if (wpa_supplicant_ctrl_iface_wps_reg(wpa_s, buf + 8))
index ba311df..4d2d313 100644 (file)
@@ -887,6 +887,32 @@ static int wpa_cli_cmd_wps_nfc_token(struct wpa_ctrl *ctrl, int argc,
        }
        return wpa_ctrl_command(ctrl, cmd);
 }
+
+
+static int wpa_cli_cmd_wps_nfc_tag_read(struct wpa_ctrl *ctrl, int argc,
+                                       char *argv[])
+{
+       int ret;
+       char *buf;
+       size_t buflen;
+
+       if (argc != 1) {
+               printf("Invalid 'wps_nfc_tag_read' command - one argument "
+                      "is required.\n");
+               return -1;
+       }
+
+       buflen = 18 + os_strlen(argv[0]);
+       buf = os_malloc(buflen);
+       if (buf == NULL)
+               return -1;
+       os_snprintf(buf, buflen, "WPS_NFC_TAG_READ %s", argv[0]);
+
+       ret = wpa_ctrl_command(ctrl, buf);
+       os_free(buf);
+
+       return ret;
+}
 #endif /* CONFIG_WPS_OOB */
 
 
@@ -3089,6 +3115,9 @@ static struct wpa_cli_cmd wpa_cli_commands[] = {
        { "wps_nfc_token", wpa_cli_cmd_wps_nfc_token,
          cli_cmd_flag_none,
          "<WPS|NDEF> = create password token" },
+       { "wps_nfc_tag_read", wpa_cli_cmd_wps_nfc_tag_read,
+         cli_cmd_flag_sensitive,
+         "<hexdump of payload> = report read NFC tag with WPS data" },
 #endif /* CONFIG_WPS_OOB */
        { "wps_reg", wpa_cli_cmd_wps_reg,
          cli_cmd_flag_sensitive,
index bade09f..08dd998 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * wpa_supplicant / WPS integration
- * Copyright (c) 2008-2010, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2008-2012, Jouni Malinen <j@w1.fi>
  *
  * This software may be distributed under the terms of the BSD license.
  * See README for more details.
@@ -21,6 +21,7 @@
 #include "eap_peer/eap.h"
 #include "eapol_supp/eapol_supp_sm.h"
 #include "rsn_supp/wpa.h"
+#include "wps/wps_attr_parse.h"
 #include "config.h"
 #include "wpa_supplicant_i.h"
 #include "driver_i.h"
@@ -1846,4 +1847,71 @@ int wpas_wps_start_nfc(struct wpa_supplicant *wpa_s, const u8 *bssid)
                                  wpa_s->conf->wps_nfc_dev_pw_id);
 }
 
+
+static int wpas_wps_use_cred(struct wpa_supplicant *wpa_s,
+                            struct wps_parse_attr *attr)
+{
+       if (wps_oob_use_cred(wpa_s->wps, attr) < 0)
+               return -1;
+
+       if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED)
+               return 0;
+
+       wpa_printf(MSG_DEBUG, "WPS: Request reconnection with new network "
+                  "based on the received credential added");
+       wpa_s->normal_scans = 0;
+       wpa_supplicant_reinit_autoscan(wpa_s);
+       wpa_s->disconnected = 0;
+       wpa_s->reassociate = 1;
+       wpa_supplicant_req_scan(wpa_s, 0, 0);
+
+       return 0;
+}
+
+
+static int wpas_wps_nfc_tag_process(struct wpa_supplicant *wpa_s,
+                                   const struct wpabuf *wps)
+{
+       struct wps_parse_attr attr;
+
+       wpa_hexdump_buf(MSG_DEBUG, "WPS: Received NFC tag payload", wps);
+
+       if (wps_parse_msg(wps, &attr)) {
+               wpa_printf(MSG_DEBUG, "WPS: Ignore invalid data from NFC tag");
+               return -1;
+       }
+
+       if (attr.num_cred)
+               return wpas_wps_use_cred(wpa_s, &attr);
+
+       wpa_printf(MSG_DEBUG, "WPS: Ignore unrecognized NFC tag");
+       return -1;
+}
+
+
+int wpas_wps_nfc_tag_read(struct wpa_supplicant *wpa_s,
+                         const struct wpabuf *data)
+{
+       const struct wpabuf *wps = data;
+       struct wpabuf *tmp = NULL;
+       int ret;
+
+       if (wpabuf_len(data) < 4)
+               return -1;
+
+       if (*wpabuf_head_u8(data) != 0x10) {
+               /* Assume this contains full NDEF record */
+               tmp = ndef_parse_wifi(data);
+               if (tmp == NULL) {
+                       wpa_printf(MSG_DEBUG, "WPS: Could not parse NDEF");
+                       return -1;
+               }
+               wps = tmp;
+       }
+
+       ret = wpas_wps_nfc_tag_process(wpa_s, wps);
+       wpabuf_free(tmp);
+       return ret;
+}
+
 #endif /* CONFIG_WPS_NFC */
index 6ce0e7b..38b3655 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * wpa_supplicant / WPS integration
- * Copyright (c) 2008-2009, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2008-2012, Jouni Malinen <j@w1.fi>
  *
  * This software may be distributed under the terms of the BSD license.
  * See README for more details.
@@ -64,6 +64,8 @@ int wpas_wps_in_progress(struct wpa_supplicant *wpa_s);
 void wpas_wps_update_config(struct wpa_supplicant *wpa_s);
 struct wpabuf * wpas_wps_nfc_token(struct wpa_supplicant *wpa_s, int ndef);
 int wpas_wps_start_nfc(struct wpa_supplicant *wpa_s, const u8 *bssid);
+int wpas_wps_nfc_tag_read(struct wpa_supplicant *wpa_s,
+                         const struct wpabuf *data);
 
 #else /* CONFIG_WPS */