Update to new version 0.8.16 from BRCM
Sync with main tree commit b8349523e460493fa0b4de36c689595109e45e91
Author: Neeraj Kumar Garg <neerajkg@broadcom.com>
Date: Tue Dec 27 23:21:45 2011 +0200
P2P: Reject p2p_group_add if forced frequency is not acceptable
Change-Id: Icb4541a371b05c270e80440d7a7fdea7f33ff61e
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
diff --git a/src/wps/upnp_xml.c b/src/wps/upnp_xml.c
index b1b1e2b..a9958ee 100644
--- a/src/wps/upnp_xml.c
+++ b/src/wps/upnp_xml.c
@@ -75,8 +75,8 @@
* Note that angle brackets present in the original data must have been encoded
* as < and > so they will not trouble us.
*/
-static int xml_next_tag(const char *in, const char **out,
- const char **out_tagname, const char **end)
+int xml_next_tag(const char *in, const char **out,
+ const char **out_tagname, const char **end)
{
while (*in && *in != '<')
in++;
diff --git a/src/wps/upnp_xml.h b/src/wps/upnp_xml.h
index 62dbe60..616af3d 100644
--- a/src/wps/upnp_xml.h
+++ b/src/wps/upnp_xml.h
@@ -16,6 +16,8 @@
void xml_data_encode(struct wpabuf *buf, const char *data, int len);
void xml_add_tagged_data(struct wpabuf *buf, const char *tag,
const char *data);
+int xml_next_tag(const char *in, const char **out,
+ const char **out_tagname, const char **end);
char * xml_get_first_item(const char *doc, const char *item);
struct wpabuf * xml_get_base64_item(const char *data, const char *name,
enum http_reply_code *ret);
diff --git a/src/wps/wps.c b/src/wps/wps.c
index 5c8c25f..2ba3d4b 100644
--- a/src/wps/wps.c
+++ b/src/wps/wps.c
@@ -67,12 +67,11 @@
/* Use special PIN '00000000' for PBC */
data->dev_pw_id = DEV_PW_PUSHBUTTON;
os_free(data->dev_password);
- data->dev_password = os_malloc(8);
+ data->dev_password = (u8 *) os_strdup("00000000");
if (data->dev_password == NULL) {
os_free(data);
return NULL;
}
- os_memset(data->dev_password, '0', 8);
data->dev_password_len = 8;
}
@@ -355,6 +354,19 @@
/**
+ * wps_is_20 - Check whether WPS attributes claim support for WPS 2.0
+ */
+int wps_is_20(const struct wpabuf *msg)
+{
+ struct wps_parse_attr attr;
+
+ if (msg == NULL || wps_parse_msg(msg, &attr) < 0)
+ return 0;
+ return attr.version2 != NULL;
+}
+
+
+/**
* wps_build_assoc_req_ie - Build WPS IE for (Re)Association Request
* @req_type: Value for Request Type attribute
* Returns: WPS IE or %NULL on failure
@@ -443,7 +455,6 @@
const u8 *req_dev_types)
{
struct wpabuf *ie;
- u16 methods = 0;
wpa_printf(MSG_DEBUG, "WPS: Building WPS IE for Probe Request");
@@ -451,35 +462,9 @@
if (ie == NULL)
return NULL;
- methods |= WPS_CONFIG_PUSHBUTTON;
-#ifdef CONFIG_WPS2
- /*
- * TODO: Should figure out whether this device has a physical or
- * virtual pushbutton.
- */
- methods |= WPS_CONFIG_VIRT_PUSHBUTTON;
-#endif /* CONFIG_WPS2 */
-
- /*
- * TODO: Should figure out whether this Probe Request was triggered
- * using physical or virtual display. Also, if the device has a PIN on
- * a label, that should be indicated here.
- */
- methods |= WPS_CONFIG_DISPLAY |
-#ifdef CONFIG_WPS2
- WPS_CONFIG_VIRT_DISPLAY |
-#endif /* CONFIG_WPS2 */
- WPS_CONFIG_KEYPAD;
-#ifdef CONFIG_WPS_UFD
- methods |= WPS_CONFIG_USBA;
-#endif /* CONFIG_WPS_UFD */
-#ifdef CONFIG_WPS_NFC
- methods |= WPS_CONFIG_NFC_INTERFACE;
-#endif /* CONFIG_WPS_NFC */
-
if (wps_build_version(ie) ||
wps_build_req_type(ie, req_type) ||
- wps_build_config_methods(ie, methods) ||
+ wps_build_config_methods(ie, dev->config_methods) ||
wps_build_uuid_e(ie, uuid) ||
wps_build_primary_dev_type(dev, ie) ||
wps_build_rf_bands(dev, ie) ||
diff --git a/src/wps/wps.h b/src/wps/wps.h
index 3e4c218..4986881 100644
--- a/src/wps/wps.h
+++ b/src/wps/wps.h
@@ -99,6 +99,7 @@
u8 num_sec_dev_types;
u32 os_version;
u8 rf_bands;
+ u16 config_methods;
struct wpabuf *vendor_ext[MAX_WPS_VENDOR_EXTENSIONS];
int p2p;
@@ -239,6 +240,7 @@
int wps_is_addr_authorized(const struct wpabuf *msg, const u8 *addr,
int ver1_compat);
const u8 * wps_get_uuid_e(const struct wpabuf *msg);
+int wps_is_20(const struct wpabuf *msg);
struct wpabuf * wps_build_assoc_req_ie(enum wps_request_type req_type);
struct wpabuf * wps_build_assoc_resp_ie(void);
@@ -782,6 +784,7 @@
int wps_registrar_unlock_pin(struct wps_registrar *reg, const u8 *uuid);
int wps_registrar_button_pushed(struct wps_registrar *reg,
const u8 *p2p_dev_addr);
+void wps_registrar_complete(struct wps_registrar *registrar, const u8 *uuid_e);
void wps_registrar_probe_req_rx(struct wps_registrar *reg, const u8 *addr,
const struct wpabuf *wps_data,
int p2p_wildcard);
@@ -791,6 +794,9 @@
int wps_registrar_config_ap(struct wps_registrar *reg,
struct wps_credential *cred);
+int wps_build_credential_wrap(struct wpabuf *msg,
+ const struct wps_credential *cred);
+
unsigned int wps_pin_checksum(unsigned int pin);
unsigned int wps_pin_valid(unsigned int pin);
unsigned int wps_generate_pin(void);
diff --git a/src/wps/wps_attr_parse.c b/src/wps/wps_attr_parse.c
index 7b462d3..55b5573 100644
--- a/src/wps/wps_attr_parse.c
+++ b/src/wps/wps_attr_parse.c
@@ -557,7 +557,9 @@
{
const u8 *pos, *end;
u16 type, len;
+#ifdef WPS_WORKAROUNDS
u16 prev_type = 0;
+#endif /* WPS_WORKAROUNDS */
os_memset(attr, 0, sizeof(*attr));
pos = wpabuf_head(msg);
@@ -622,7 +624,9 @@
if (wps_set_attr(attr, type, pos, len) < 0)
return -1;
+#ifdef WPS_WORKAROUNDS
prev_type = type;
+#endif /* WPS_WORKAROUNDS */
pos += len;
}
diff --git a/src/wps/wps_common.c b/src/wps/wps_common.c
index 5d0508c..505837b 100644
--- a/src/wps/wps_common.c
+++ b/src/wps/wps_common.c
@@ -22,7 +22,6 @@
#include "crypto/sha256.h"
#include "crypto/random.h"
#include "wps_i.h"
-#include "wps_dev_attr.h"
void wps_kdf(const u8 *key, const u8 *label_prefix, size_t label_prefix_len,
diff --git a/src/wps/wps_enrollee.c b/src/wps/wps_enrollee.c
index 5b3c045..0fbaa3f 100644
--- a/src/wps/wps_enrollee.c
+++ b/src/wps/wps_enrollee.c
@@ -967,7 +967,7 @@
return WPS_CONTINUE;
}
- if (wps_validate_m4_encr(decrypted, attr->version2 != 0) < 0) {
+ if (wps_validate_m4_encr(decrypted, attr->version2 != NULL) < 0) {
wpabuf_free(decrypted);
wps->state = SEND_WSC_NACK;
return WPS_CONTINUE;
@@ -1020,7 +1020,7 @@
return WPS_CONTINUE;
}
- if (wps_validate_m6_encr(decrypted, attr->version2 != 0) < 0) {
+ if (wps_validate_m6_encr(decrypted, attr->version2 != NULL) < 0) {
wpabuf_free(decrypted);
wps->state = SEND_WSC_NACK;
return WPS_CONTINUE;
@@ -1086,8 +1086,8 @@
return WPS_CONTINUE;
}
- if (wps_validate_m8_encr(decrypted, wps->wps->ap, attr->version2 != 0)
- < 0) {
+ if (wps_validate_m8_encr(decrypted, wps->wps->ap,
+ attr->version2 != NULL) < 0) {
wpabuf_free(decrypted);
wps->state = SEND_WSC_NACK;
return WPS_CONTINUE;
diff --git a/src/wps/wps_er.c b/src/wps/wps_er.c
index a461836..856e9fb 100644
--- a/src/wps/wps_er.c
+++ b/src/wps/wps_er.c
@@ -502,16 +502,61 @@
}
+static const char * wps_er_find_wfadevice(const char *data)
+{
+ const char *tag, *tagname, *end;
+ char *val;
+ int found = 0;
+
+ while (!found) {
+ /* Find next <device> */
+ for (;;) {
+ if (xml_next_tag(data, &tag, &tagname, &end))
+ return NULL;
+ data = end;
+ if (!os_strncasecmp(tagname, "device", 6) &&
+ *tag != '/' &&
+ (tagname[6] == '>' || !isgraph(tagname[6]))) {
+ break;
+ }
+ }
+
+ /* Check whether deviceType is WFADevice */
+ val = xml_get_first_item(data, "deviceType");
+ if (val == NULL)
+ return NULL;
+ wpa_printf(MSG_DEBUG, "WPS ER: Found deviceType '%s'", val);
+ found = os_strcasecmp(val, "urn:schemas-wifialliance-org:"
+ "device:WFADevice:1") == 0;
+ os_free(val);
+ }
+
+ return data;
+}
+
+
static void wps_er_parse_device_description(struct wps_er_ap *ap,
struct wpabuf *reply)
{
/* Note: reply includes null termination after the buffer data */
- const char *data = wpabuf_head(reply);
+ const char *tmp, *data = wpabuf_head(reply);
char *pos;
wpa_hexdump_ascii(MSG_MSGDUMP, "WPS ER: Device info",
wpabuf_head(reply), wpabuf_len(reply));
+ /*
+ * The root device description may include multiple devices, so first
+ * find the beginning of the WFADevice description to allow the
+ * simplistic parser to pick the correct entries.
+ */
+ tmp = wps_er_find_wfadevice(data);
+ if (tmp == NULL) {
+ wpa_printf(MSG_DEBUG, "WPS ER: WFADevice:1 device not found - "
+ "trying to parse invalid data");
+ } else
+ data = tmp;
+
ap->friendly_name = xml_get_first_item(data, "friendlyName");
wpa_printf(MSG_DEBUG, "WPS ER: friendlyName='%s'", ap->friendly_name);
diff --git a/src/wps/wps_registrar.c b/src/wps/wps_registrar.c
index 65ff40d..eda1c70 100644
--- a/src/wps/wps_registrar.c
+++ b/src/wps/wps_registrar.c
@@ -310,13 +310,17 @@
static void wps_registrar_remove_pbc_session(struct wps_registrar *reg,
- const u8 *uuid_e)
+ const u8 *uuid_e,
+ const u8 *p2p_dev_addr)
{
struct wps_pbc_session *pbc, *prev = NULL, *tmp;
pbc = reg->pbc_sessions;
while (pbc) {
- if (os_memcmp(pbc->uuid_e, uuid_e, WPS_UUID_LEN) == 0) {
+ if (os_memcmp(pbc->uuid_e, uuid_e, WPS_UUID_LEN) == 0 ||
+ (p2p_dev_addr && !is_zero_ether_addr(reg->p2p_dev_addr) &&
+ os_memcmp(reg->p2p_dev_addr, p2p_dev_addr, ETH_ALEN) ==
+ 0)) {
if (prev)
prev->next = pbc->next;
else
@@ -485,10 +489,8 @@
*methods |= WPS_CONFIG_VIRT_PUSHBUTTON;
if (conf_methods & WPS_CONFIG_PHY_PUSHBUTTON)
*methods |= WPS_CONFIG_PHY_PUSHBUTTON;
- if ((*methods & WPS_CONFIG_VIRT_PUSHBUTTON) !=
- WPS_CONFIG_VIRT_PUSHBUTTON ||
- (*methods & WPS_CONFIG_PHY_PUSHBUTTON) !=
- WPS_CONFIG_PHY_PUSHBUTTON) {
+ if (!(*methods & (WPS_CONFIG_VIRT_PUSHBUTTON |
+ WPS_CONFIG_PHY_PUSHBUTTON))) {
/*
* Required to include virtual/physical flag, but we were not
* configured with push button type, so have to default to one
@@ -549,15 +551,7 @@
static int wps_build_config_methods_r(struct wps_registrar *reg,
struct wpabuf *msg)
{
- u16 methods;
- methods = reg->wps->config_methods & ~WPS_CONFIG_PUSHBUTTON;
-#ifdef CONFIG_WPS2
- methods &= ~(WPS_CONFIG_VIRT_PUSHBUTTON |
- WPS_CONFIG_PHY_PUSHBUTTON);
-#endif /* CONFIG_WPS2 */
- if (reg->pbc)
- wps_set_pushbutton(&methods, reg->wps->config_methods);
- return wps_build_config_methods(msg, methods);
+ return wps_build_config_methods(msg, reg->wps->config_methods);
}
@@ -901,8 +895,8 @@
* PBC mode. The PBC mode will be stopped after walk time (2 minutes) timeout
* or when a PBC registration is completed. If more than one Enrollee in active
* PBC mode has been detected during the monitor time (previous 2 minutes), the
- * PBC mode is not actived and -2 is returned to indicate session overlap. This
- * is skipped if a specific Enrollee is selected.
+ * PBC mode is not activated and -2 is returned to indicate session overlap.
+ * This is skipped if a specific Enrollee is selected.
*/
int wps_registrar_button_pushed(struct wps_registrar *reg,
const u8 *p2p_dev_addr)
@@ -951,6 +945,18 @@
}
+void wps_registrar_complete(struct wps_registrar *registrar, const u8 *uuid_e)
+{
+ if (registrar->pbc) {
+ wps_registrar_remove_pbc_session(registrar,
+ uuid_e, NULL);
+ wps_registrar_pbc_completed(registrar);
+ } else {
+ wps_registrar_pin_completed(registrar);
+ }
+}
+
+
int wps_registrar_wps_cancel(struct wps_registrar *reg)
{
if (reg->pbc) {
@@ -1420,6 +1426,25 @@
}
+int wps_build_credential_wrap(struct wpabuf *msg,
+ const struct wps_credential *cred)
+{
+ struct wpabuf *wbuf;
+ wbuf = wpabuf_alloc(200);
+ if (wbuf == NULL)
+ return -1;
+ if (wps_build_credential(wbuf, cred)) {
+ wpabuf_free(wbuf);
+ return -1;
+ }
+ wpabuf_put_be16(msg, ATTR_CRED);
+ wpabuf_put_be16(msg, wpabuf_len(wbuf));
+ wpabuf_put_buf(msg, wbuf);
+ wpabuf_free(wbuf);
+ return 0;
+}
+
+
int wps_build_cred(struct wps_data *wps, struct wpabuf *msg)
{
struct wpabuf *cred;
@@ -1593,6 +1618,35 @@
}
+static struct wpabuf * wps_build_ap_cred(struct wps_data *wps)
+{
+ struct wpabuf *msg, *plain;
+
+ msg = wpabuf_alloc(1000);
+ if (msg == NULL)
+ return NULL;
+
+ plain = wpabuf_alloc(200);
+ if (plain == NULL) {
+ wpabuf_free(msg);
+ return NULL;
+ }
+
+ if (wps_build_ap_settings(wps, plain)) {
+ wpabuf_free(plain);
+ wpabuf_free(msg);
+ return NULL;
+ }
+
+ wpabuf_put_be16(msg, ATTR_CRED);
+ wpabuf_put_be16(msg, wpabuf_len(plain));
+ wpabuf_put_buf(msg, plain);
+ wpabuf_free(plain);
+
+ return msg;
+}
+
+
static struct wpabuf * wps_build_m2(struct wps_data *wps)
{
struct wpabuf *msg;
@@ -2551,6 +2605,8 @@
static int wps_process_ap_settings_r(struct wps_data *wps,
struct wps_parse_attr *attr)
{
+ struct wpabuf *msg;
+
if (wps->wps->ap || wps->er)
return 0;
@@ -2577,12 +2633,24 @@
*/
wps_registrar_pin_completed(wps->wps->registrar);
+ msg = wps_build_ap_cred(wps);
+ if (msg == NULL)
+ return -1;
+ wps->cred.cred_attr = wpabuf_head(msg);
+ wps->cred.cred_attr_len = wpabuf_len(msg);
+
if (wps->ap_settings_cb) {
wps->ap_settings_cb(wps->ap_settings_cb_ctx,
&wps->cred);
+ wpabuf_free(msg);
return 1;
}
wps_sta_cred_cb(wps);
+
+ wps->cred.cred_attr = NULL;
+ wps->cred.cred_attr_len = 0;
+ wpabuf_free(msg);
+
return 1;
}
}
@@ -2983,7 +3051,8 @@
if (wps->pbc) {
wps_registrar_remove_pbc_session(wps->wps->registrar,
- wps->uuid_e);
+ wps->uuid_e,
+ wps->p2p_dev_addr);
wps_registrar_pbc_completed(wps->wps->registrar);
} else {
wps_registrar_pin_completed(wps->wps->registrar);
diff --git a/src/wps/wps_ufd.c b/src/wps/wps_ufd.c
index 1a911e1..61f6553 100644
--- a/src/wps/wps_ufd.c
+++ b/src/wps/wps_ufd.c
@@ -16,7 +16,6 @@
#include "common.h"
#include <sys/types.h>
#include <sys/stat.h>
-#include <sys/wait.h>
#include <fcntl.h>
#include <dirent.h>
diff --git a/src/wps/wps_upnp.c b/src/wps/wps_upnp.c
index 763dcaf..06dcd20 100644
--- a/src/wps/wps_upnp.c
+++ b/src/wps/wps_upnp.c
@@ -47,7 +47,7 @@
* -- Needs renaming with module prefix to avoid polluting the debugger
* namespace and causing possible collisions with other static fncs
* and structure declarations when using the debugger.
- * -- The http error code generation is pretty bogus, hopefully noone cares.
+ * -- The http error code generation is pretty bogus, hopefully no one cares.
*
* Author: Ted Merrill, Atheros Communications, based upon earlier work
* as explained above and below.
@@ -172,7 +172,7 @@
#include "includes.h"
-#include <assert.h>
+#include <time.h>
#include <net/if.h>
#include <netdb.h>
#include <sys/ioctl.h>
diff --git a/src/wps/wps_upnp_ssdp.c b/src/wps/wps_upnp_ssdp.c
index c7fb158..4c4aebf 100644
--- a/src/wps/wps_upnp_ssdp.c
+++ b/src/wps/wps_upnp_ssdp.c
@@ -97,16 +97,6 @@
}
-/* No. of chars excluding trailing whitespace */
-static int line_length_stripped(const char *l)
-{
- const char *lp = l + line_length(l);
- while (lp > l && !isgraph(lp[-1]))
- lp--;
- return lp - l;
-}
-
-
static int str_starts(const char *str, const char *start)
{
return os_strncmp(str, start, os_strlen(start)) == 0;
@@ -530,7 +520,6 @@
#ifndef CONFIG_NO_STDOUT_DEBUG
const char *start = data;
#endif /* CONFIG_NO_STDOUT_DEBUG */
- const char *end;
int got_host = 0;
int got_st = 0, st_match = 0;
int got_man = 0;
@@ -545,7 +534,6 @@
/* Parse remaining lines */
for (; *data != '\0'; data += line_length(data)) {
- end = data + line_length_stripped(data);
if (token_eq(data, "host")) {
/* The host line indicates who the packet
* is addressed to... but do we really care?
diff --git a/src/wps/wps_upnp_web.c b/src/wps/wps_upnp_web.c
index 917f60b..ce0bede 100644
--- a/src/wps/wps_upnp_web.c
+++ b/src/wps/wps_upnp_web.c
@@ -956,7 +956,7 @@
break; /* no unterminated lines allowed */
/* NT assures that it is our type of subscription;
- * not used for a renewl.
+ * not used for a renewal.
**/
match = "NT:";
match_len = os_strlen(match);