Signed-off-by: Jean-Michel Bachot Signed-off-by: Johannes Berg --- src/p2p/p2p.c | 27 +++++++++++++++++++++++++++ src/p2p/p2p.h | 4 ++++ src/p2p/p2p_i.h | 2 ++ src/p2p/p2p_parse.c | 8 ++++++++ src/wps/wps.h | 4 ++++ src/wps/wps_attr_parse.c | 25 +++++++++++++++++++++---- src/wps/wps_i.h | 4 ++++ 7 files changed, 70 insertions(+), 4 deletions(-) diff --git a/src/p2p/p2p.c b/src/p2p/p2p.c index 11db03c..6e83e38 100644 --- a/src/p2p/p2p.c +++ b/src/p2p/p2p.c @@ -437,6 +437,7 @@ int p2p_add_device(struct p2p_data *p2p, const u8 *addr, int freq, int level, struct p2p_device *dev; struct p2p_message msg; const u8 *p2p_dev_addr; + int i; os_memset(&msg, 0, sizeof(msg)); if (p2p_parse_ies(ies, ies_len, &msg)) { @@ -528,6 +529,26 @@ int p2p_add_device(struct p2p_data *p2p, const u8 *addr, int freq, int level, msg.wps_sec_dev_type_list_len; } + for (i = 0; i < MAX_PEER_WPS_VENDOR_EXTENSIONS; i++) { + wpabuf_free(dev->info.wps_vendor_extension[i]); + dev->info.wps_vendor_extension[i] = NULL; + + if (msg.wps_vendor_extension[i] == NULL) + continue; + dev->info.wps_vendor_extension[i] = + wpabuf_alloc_copy( + msg.wps_vendor_extension[i], + msg.wps_vendor_extension_len[i]); + if (dev->info.wps_vendor_extension[i] != NULL) + continue; + /* error: */ + while (--i >= 0) { + wpabuf_free(dev->info.wps_vendor_extension[i]); + dev->info.wps_vendor_extension[i] = NULL; + } + return -1; + } + if (msg.capability) { dev->info.dev_capab = msg.capability[0]; dev->info.group_capab = msg.capability[1]; @@ -568,6 +589,8 @@ int p2p_add_device(struct p2p_data *p2p, const u8 *addr, int freq, int level, static void p2p_device_free(struct p2p_data *p2p, struct p2p_device *dev) { + int i; + if (p2p->go_neg_peer == dev) p2p->go_neg_peer = NULL; if (p2p->invite_peer == dev) @@ -579,6 +602,10 @@ static void p2p_device_free(struct p2p_data *p2p, struct p2p_device *dev) p2p->cfg->dev_lost(p2p->cfg->cb_ctx, dev->info.p2p_device_addr); + for (i = 0; i < MAX_PEER_WPS_VENDOR_EXTENSIONS; i++) { + wpabuf_free(dev->info.wps_vendor_extension[i]); + dev->info.wps_vendor_extension[i] = NULL; + } os_free(dev); } diff --git a/src/p2p/p2p.h b/src/p2p/p2p.h index 23d0381..354e45c 100644 --- a/src/p2p/p2p.h +++ b/src/p2p/p2p.h @@ -15,6 +15,8 @@ #ifndef P2P_H #define P2P_H +#include "wps/wps.h" + /** * P2P_MAX_REG_CLASSES - Maximum number of regulatory classes */ @@ -156,6 +158,8 @@ struct p2p_peer_info { u8 wps_sec_dev_type_list[128]; size_t wps_sec_dev_type_list_len; +#define MAX_PEER_WPS_VENDOR_EXTENSIONS MAX_WPS_PARSE_VENDOR_EXTENSIONS + struct wpabuf *wps_vendor_extension[MAX_PEER_WPS_VENDOR_EXTENSIONS]; }; /** diff --git a/src/p2p/p2p_i.h b/src/p2p/p2p_i.h index 5f3bea8..017ed6e 100644 --- a/src/p2p/p2p_i.h +++ b/src/p2p/p2p_i.h @@ -456,6 +456,8 @@ struct p2p_message { const u8 *wps_pri_dev_type; const u8 *wps_sec_dev_type_list; size_t wps_sec_dev_type_list_len; + const u8 *wps_vendor_extension[MAX_PEER_WPS_VENDOR_EXTENSIONS]; + size_t wps_vendor_extension_len[MAX_PEER_WPS_VENDOR_EXTENSIONS]; /* DS Parameter Set IE */ const u8 *ds_params; diff --git a/src/p2p/p2p_parse.c b/src/p2p/p2p_parse.c index 56c1e71..2e73a25 100644 --- a/src/p2p/p2p_parse.c +++ b/src/p2p/p2p_parse.c @@ -328,6 +328,7 @@ int p2p_parse_p2p_ie(const struct wpabuf *buf, struct p2p_message *msg) static int p2p_parse_wps_ie(const struct wpabuf *buf, struct p2p_message *msg) { struct wps_parse_attr attr; + int i; wpa_printf(MSG_DEBUG, "P2P: Parsing WPS IE"); if (wps_parse_msg(buf, &attr)) @@ -358,6 +359,13 @@ static int p2p_parse_wps_ie(const struct wpabuf *buf, struct p2p_message *msg) msg->wps_sec_dev_type_list_len = attr.sec_dev_type_list_len; } + for (i = 0; i < MAX_PEER_WPS_VENDOR_EXTENSIONS; i++) { + msg->wps_vendor_extension[i] = + attr.wps_vendor_extension[i]; + msg->wps_vendor_extension_len[i] = + attr.wps_vendor_extension_len[i]; + } + return 0; } diff --git a/src/wps/wps.h b/src/wps/wps.h index 33dec7c..a8c6ffe 100644 --- a/src/wps/wps.h +++ b/src/wps/wps.h @@ -68,6 +68,10 @@ struct wps_credential { #define WPS_SEC_DEV_TYPE_LEN 128 /* maximum number of advertised WPS vendor extension attributes */ #define MAX_WPS_VENDOR_EXTENSIONS 10 +/* maximum size of WPS Vendor extension attribute is 1024 Bytes */ +#define WPS_MAX_VENDOR_EXTENSIONS_SIZE 1024 +/* maximum number of parsed WPS vendor extensions attributes */ +#define MAX_WPS_PARSE_VENDOR_EXTENSIONS 10 /** * struct wps_device_data - WPS Device Data diff --git a/src/wps/wps_attr_parse.c b/src/wps/wps_attr_parse.c index 3efbc75..f6db912 100644 --- a/src/wps/wps_attr_parse.c +++ b/src/wps/wps_attr_parse.c @@ -108,12 +108,29 @@ static int wps_parse_vendor_ext(struct wps_parse_attr *attr, const u8 *pos, switch (vendor_id) { case WPS_VENDOR_ID_WFA: return wps_parse_vendor_ext_wfa(attr, pos + 3, len - 3); - default: - wpa_printf(MSG_MSGDUMP, "WPS: Skip unknown Vendor Extension " - "(Vendor ID %u)", vendor_id); - break; } + /* handle unknown extension */ + + wpa_printf(MSG_MSGDUMP, "WPS: Unknown Vendor Extension (Vendor ID %u)", + vendor_id); + + if (len > WPS_MAX_VENDOR_EXTENSIONS_SIZE) { + wpa_printf(MSG_DEBUG, "WPS: Vendor Extension size > 1024"); + return -1; + } + + if (attr->num_wps_vendor_extensions > MAX_WPS_PARSE_VENDOR_EXTENSIONS) { + wpa_printf(MSG_DEBUG, + "WPS: Skipped Vendor Extension" + "attribute (max %d vendor extensions)", + MAX_WPS_PARSE_VENDOR_EXTENSIONS); + return -1; + } + attr->wps_vendor_extension[attr->num_wps_vendor_extensions] = pos; + attr->wps_vendor_extension_len[attr->num_wps_vendor_extensions] = len; + attr->num_wps_vendor_extensions++; + return 0; } diff --git a/src/wps/wps_i.h b/src/wps/wps_i.h index 5f2afa0..5532bbb 100644 --- a/src/wps/wps_i.h +++ b/src/wps/wps_i.h @@ -203,6 +203,10 @@ struct wps_parse_attr { const u8 *req_dev_type[MAX_REQ_DEV_TYPE_COUNT]; size_t num_req_dev_type; + + const u8 *wps_vendor_extension[MAX_WPS_PARSE_VENDOR_EXTENSIONS]; + size_t wps_vendor_extension_len[MAX_WPS_PARSE_VENDOR_EXTENSIONS]; + size_t num_wps_vendor_extensions; }; /* wps_common.c */ -- 1.7.2.3