WPS: Add support for NFC configuration token from external program

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>
This commit is contained in:
Jouni Malinen 2012-06-28 13:59:29 +03:00
parent 3cf7a59d4f
commit d7645d239d
6 changed files with 150 additions and 11 deletions

View 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,

View 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)
{

View 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))

View 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,

View 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 */

View 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 */