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:
parent
3cf7a59d4f
commit
d7645d239d
6 changed files with 150 additions and 11 deletions
|
@ -27,6 +27,7 @@ enum wsc_op_code {
|
||||||
struct wps_registrar;
|
struct wps_registrar;
|
||||||
struct upnp_wps_device_sm;
|
struct upnp_wps_device_sm;
|
||||||
struct wps_er;
|
struct wps_er;
|
||||||
|
struct wps_parse_attr;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct wps_credential - WPS Credential
|
* 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 wps_process_oob(struct wps_context *wps, struct oob_device_data *oob_dev,
|
||||||
int registrar);
|
int registrar);
|
||||||
struct wpabuf * wps_get_oob_cred(struct wps_context *wps);
|
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);
|
int wps_attr_text(struct wpabuf *data, char *buf, char *end);
|
||||||
|
|
||||||
struct wps_er * wps_er_init(struct wps_context *wps, const char *ifname,
|
struct wps_er * wps_er_init(struct wps_context *wps, const char *ifname,
|
||||||
|
|
|
@ -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 wpabuf msg;
|
||||||
struct wps_parse_attr attr;
|
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
if (wps_parse_msg(data, &attr) < 0 || attr.num_cred <= 0) {
|
for (i = 0; i < attr->num_cred; i++) {
|
||||||
wpa_printf(MSG_ERROR, "WPS: OOB credential not found");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < attr.num_cred; i++) {
|
|
||||||
struct wps_credential local_cred;
|
struct wps_credential local_cred;
|
||||||
struct wps_parse_attr cattr;
|
struct wps_parse_attr cattr;
|
||||||
|
|
||||||
os_memset(&local_cred, 0, sizeof(local_cred));
|
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 ||
|
if (wps_parse_msg(&msg, &cattr) < 0 ||
|
||||||
wps_process_cred(&cattr, &local_cred)) {
|
wps_process_cred(&cattr, &local_cred)) {
|
||||||
wpa_printf(MSG_ERROR, "WPS: Failed to parse OOB "
|
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 wps_process_oob(struct wps_context *wps, struct oob_device_data *oob_dev,
|
||||||
int registrar)
|
int registrar)
|
||||||
{
|
{
|
||||||
|
|
|
@ -662,6 +662,33 @@ static int wpa_supplicant_ctrl_iface_wps_nfc_token(
|
||||||
|
|
||||||
return res;
|
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 */
|
#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) {
|
} else if (os_strncmp(buf, "WPS_NFC_TOKEN ", 14) == 0) {
|
||||||
reply_len = wpa_supplicant_ctrl_iface_wps_nfc_token(
|
reply_len = wpa_supplicant_ctrl_iface_wps_nfc_token(
|
||||||
wpa_s, buf + 14, reply, reply_size);
|
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 */
|
#endif /* CONFIG_WPS_OOB */
|
||||||
} else if (os_strncmp(buf, "WPS_REG ", 8) == 0) {
|
} else if (os_strncmp(buf, "WPS_REG ", 8) == 0) {
|
||||||
if (wpa_supplicant_ctrl_iface_wps_reg(wpa_s, buf + 8))
|
if (wpa_supplicant_ctrl_iface_wps_reg(wpa_s, buf + 8))
|
||||||
|
|
|
@ -887,6 +887,32 @@ static int wpa_cli_cmd_wps_nfc_token(struct wpa_ctrl *ctrl, int argc,
|
||||||
}
|
}
|
||||||
return wpa_ctrl_command(ctrl, cmd);
|
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 */
|
#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,
|
{ "wps_nfc_token", wpa_cli_cmd_wps_nfc_token,
|
||||||
cli_cmd_flag_none,
|
cli_cmd_flag_none,
|
||||||
"<WPS|NDEF> = create password token" },
|
"<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 */
|
#endif /* CONFIG_WPS_OOB */
|
||||||
{ "wps_reg", wpa_cli_cmd_wps_reg,
|
{ "wps_reg", wpa_cli_cmd_wps_reg,
|
||||||
cli_cmd_flag_sensitive,
|
cli_cmd_flag_sensitive,
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* wpa_supplicant / WPS integration
|
* 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.
|
* This software may be distributed under the terms of the BSD license.
|
||||||
* See README for more details.
|
* See README for more details.
|
||||||
|
@ -21,6 +21,7 @@
|
||||||
#include "eap_peer/eap.h"
|
#include "eap_peer/eap.h"
|
||||||
#include "eapol_supp/eapol_supp_sm.h"
|
#include "eapol_supp/eapol_supp_sm.h"
|
||||||
#include "rsn_supp/wpa.h"
|
#include "rsn_supp/wpa.h"
|
||||||
|
#include "wps/wps_attr_parse.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "wpa_supplicant_i.h"
|
#include "wpa_supplicant_i.h"
|
||||||
#include "driver_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);
|
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 */
|
#endif /* CONFIG_WPS_NFC */
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* wpa_supplicant / WPS integration
|
* 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.
|
* This software may be distributed under the terms of the BSD license.
|
||||||
* See README for more details.
|
* 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);
|
void wpas_wps_update_config(struct wpa_supplicant *wpa_s);
|
||||||
struct wpabuf * wpas_wps_nfc_token(struct wpa_supplicant *wpa_s, int ndef);
|
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_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 */
|
#else /* CONFIG_WPS */
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue