Add explicit buffer length checks for p2p_build_wps_ie()
Even though the length of this buffer is based only on locally configured information, it is cleaner to include explicit buffer room validation steps when adding the attributes into the buffer. Signed-hostap: Jouni Malinen <j@w1.fi>
This commit is contained in:
parent
0f0120148a
commit
3318376101
5 changed files with 75 additions and 24 deletions
|
@ -1911,7 +1911,11 @@ struct wpabuf * p2p_build_probe_resp_ies(struct p2p_data *p2p)
|
||||||
pw_id = p2p_wps_method_pw_id(p2p->go_neg_peer->wps_method);
|
pw_id = p2p_wps_method_pw_id(p2p->go_neg_peer->wps_method);
|
||||||
}
|
}
|
||||||
|
|
||||||
p2p_build_wps_ie(p2p, buf, pw_id, 1);
|
if (p2p_build_wps_ie(p2p, buf, pw_id, 1) < 0) {
|
||||||
|
p2p_dbg(p2p, "Failed to build WPS IE for Probe Response");
|
||||||
|
wpabuf_free(buf);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_WIFI_DISPLAY
|
#ifdef CONFIG_WIFI_DISPLAY
|
||||||
if (p2p->wfd_ie_probe_resp)
|
if (p2p->wfd_ie_probe_resp)
|
||||||
|
|
|
@ -327,13 +327,15 @@ void p2p_buf_add_p2p_interface(struct wpabuf *buf, struct p2p_data *p2p)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void p2p_add_wps_string(struct wpabuf *buf, enum wps_attribute attr,
|
static int p2p_add_wps_string(struct wpabuf *buf, enum wps_attribute attr,
|
||||||
const char *val)
|
const char *val)
|
||||||
{
|
{
|
||||||
size_t len;
|
size_t len;
|
||||||
|
|
||||||
wpabuf_put_be16(buf, attr);
|
|
||||||
len = val ? os_strlen(val) : 0;
|
len = val ? os_strlen(val) : 0;
|
||||||
|
if (wpabuf_tailroom(buf) < 4 + len)
|
||||||
|
return -1;
|
||||||
|
wpabuf_put_be16(buf, attr);
|
||||||
#ifndef CONFIG_WPS_STRICT
|
#ifndef CONFIG_WPS_STRICT
|
||||||
if (len == 0) {
|
if (len == 0) {
|
||||||
/*
|
/*
|
||||||
|
@ -341,36 +343,46 @@ static void p2p_add_wps_string(struct wpabuf *buf, enum wps_attribute attr,
|
||||||
* attributes. As a workaround, send a space character if the
|
* attributes. As a workaround, send a space character if the
|
||||||
* device attribute string is empty.
|
* device attribute string is empty.
|
||||||
*/
|
*/
|
||||||
|
if (wpabuf_tailroom(buf) < 3)
|
||||||
|
return -1;
|
||||||
wpabuf_put_be16(buf, 1);
|
wpabuf_put_be16(buf, 1);
|
||||||
wpabuf_put_u8(buf, ' ');
|
wpabuf_put_u8(buf, ' ');
|
||||||
return;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_WPS_STRICT */
|
#endif /* CONFIG_WPS_STRICT */
|
||||||
wpabuf_put_be16(buf, len);
|
wpabuf_put_be16(buf, len);
|
||||||
if (val)
|
if (val)
|
||||||
wpabuf_put_data(buf, val, len);
|
wpabuf_put_data(buf, val, len);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void p2p_build_wps_ie(struct p2p_data *p2p, struct wpabuf *buf, int pw_id,
|
int p2p_build_wps_ie(struct p2p_data *p2p, struct wpabuf *buf, int pw_id,
|
||||||
int all_attr)
|
int all_attr)
|
||||||
{
|
{
|
||||||
u8 *len;
|
u8 *len;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
if (wpabuf_tailroom(buf) < 6)
|
||||||
|
return -1;
|
||||||
wpabuf_put_u8(buf, WLAN_EID_VENDOR_SPECIFIC);
|
wpabuf_put_u8(buf, WLAN_EID_VENDOR_SPECIFIC);
|
||||||
len = wpabuf_put(buf, 1);
|
len = wpabuf_put(buf, 1);
|
||||||
wpabuf_put_be32(buf, WPS_DEV_OUI_WFA);
|
wpabuf_put_be32(buf, WPS_DEV_OUI_WFA);
|
||||||
|
|
||||||
wps_build_version(buf);
|
if (wps_build_version(buf) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
if (all_attr) {
|
if (all_attr) {
|
||||||
|
if (wpabuf_tailroom(buf) < 5)
|
||||||
|
return -1;
|
||||||
wpabuf_put_be16(buf, ATTR_WPS_STATE);
|
wpabuf_put_be16(buf, ATTR_WPS_STATE);
|
||||||
wpabuf_put_be16(buf, 1);
|
wpabuf_put_be16(buf, 1);
|
||||||
wpabuf_put_u8(buf, WPS_STATE_NOT_CONFIGURED);
|
wpabuf_put_u8(buf, WPS_STATE_NOT_CONFIGURED);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pw_id >= 0) {
|
if (pw_id >= 0) {
|
||||||
|
if (wpabuf_tailroom(buf) < 6)
|
||||||
|
return -1;
|
||||||
/* Device Password ID */
|
/* Device Password ID */
|
||||||
wpabuf_put_be16(buf, ATTR_DEV_PASSWORD_ID);
|
wpabuf_put_be16(buf, ATTR_DEV_PASSWORD_ID);
|
||||||
wpabuf_put_be16(buf, 2);
|
wpabuf_put_be16(buf, 2);
|
||||||
|
@ -380,33 +392,47 @@ void p2p_build_wps_ie(struct p2p_data *p2p, struct wpabuf *buf, int pw_id,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (all_attr) {
|
if (all_attr) {
|
||||||
|
if (wpabuf_tailroom(buf) < 5)
|
||||||
|
return -1;
|
||||||
wpabuf_put_be16(buf, ATTR_RESPONSE_TYPE);
|
wpabuf_put_be16(buf, ATTR_RESPONSE_TYPE);
|
||||||
wpabuf_put_be16(buf, 1);
|
wpabuf_put_be16(buf, 1);
|
||||||
wpabuf_put_u8(buf, WPS_RESP_ENROLLEE_INFO);
|
wpabuf_put_u8(buf, WPS_RESP_ENROLLEE_INFO);
|
||||||
|
|
||||||
wps_build_uuid_e(buf, p2p->cfg->uuid);
|
if (wps_build_uuid_e(buf, p2p->cfg->uuid) < 0 ||
|
||||||
p2p_add_wps_string(buf, ATTR_MANUFACTURER,
|
p2p_add_wps_string(buf, ATTR_MANUFACTURER,
|
||||||
p2p->cfg->manufacturer);
|
p2p->cfg->manufacturer) < 0 ||
|
||||||
p2p_add_wps_string(buf, ATTR_MODEL_NAME, p2p->cfg->model_name);
|
p2p_add_wps_string(buf, ATTR_MODEL_NAME,
|
||||||
p2p_add_wps_string(buf, ATTR_MODEL_NUMBER,
|
p2p->cfg->model_name) < 0 ||
|
||||||
p2p->cfg->model_number);
|
p2p_add_wps_string(buf, ATTR_MODEL_NUMBER,
|
||||||
p2p_add_wps_string(buf, ATTR_SERIAL_NUMBER,
|
p2p->cfg->model_number) < 0 ||
|
||||||
p2p->cfg->serial_number);
|
p2p_add_wps_string(buf, ATTR_SERIAL_NUMBER,
|
||||||
|
p2p->cfg->serial_number) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (wpabuf_tailroom(buf) < 4 + WPS_DEV_TYPE_LEN)
|
||||||
|
return -1;
|
||||||
wpabuf_put_be16(buf, ATTR_PRIMARY_DEV_TYPE);
|
wpabuf_put_be16(buf, ATTR_PRIMARY_DEV_TYPE);
|
||||||
wpabuf_put_be16(buf, WPS_DEV_TYPE_LEN);
|
wpabuf_put_be16(buf, WPS_DEV_TYPE_LEN);
|
||||||
wpabuf_put_data(buf, p2p->cfg->pri_dev_type, WPS_DEV_TYPE_LEN);
|
wpabuf_put_data(buf, p2p->cfg->pri_dev_type, WPS_DEV_TYPE_LEN);
|
||||||
|
|
||||||
p2p_add_wps_string(buf, ATTR_DEV_NAME, p2p->cfg->dev_name);
|
if (p2p_add_wps_string(buf, ATTR_DEV_NAME, p2p->cfg->dev_name)
|
||||||
|
< 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (wpabuf_tailroom(buf) < 6)
|
||||||
|
return -1;
|
||||||
wpabuf_put_be16(buf, ATTR_CONFIG_METHODS);
|
wpabuf_put_be16(buf, ATTR_CONFIG_METHODS);
|
||||||
wpabuf_put_be16(buf, 2);
|
wpabuf_put_be16(buf, 2);
|
||||||
wpabuf_put_be16(buf, p2p->cfg->config_methods);
|
wpabuf_put_be16(buf, p2p->cfg->config_methods);
|
||||||
}
|
}
|
||||||
|
|
||||||
wps_build_wfa_ext(buf, 0, NULL, 0);
|
if (wps_build_wfa_ext(buf, 0, NULL, 0) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
if (all_attr && p2p->cfg->num_sec_dev_types) {
|
if (all_attr && p2p->cfg->num_sec_dev_types) {
|
||||||
|
if (wpabuf_tailroom(buf) <
|
||||||
|
4 + WPS_DEV_TYPE_LEN * p2p->cfg->num_sec_dev_types)
|
||||||
|
return -1;
|
||||||
wpabuf_put_be16(buf, ATTR_SECONDARY_DEV_TYPE_LIST);
|
wpabuf_put_be16(buf, ATTR_SECONDARY_DEV_TYPE_LIST);
|
||||||
wpabuf_put_be16(buf, WPS_DEV_TYPE_LEN *
|
wpabuf_put_be16(buf, WPS_DEV_TYPE_LEN *
|
||||||
p2p->cfg->num_sec_dev_types);
|
p2p->cfg->num_sec_dev_types);
|
||||||
|
@ -428,4 +454,6 @@ void p2p_build_wps_ie(struct p2p_data *p2p, struct wpabuf *buf, int pw_id,
|
||||||
}
|
}
|
||||||
|
|
||||||
p2p_buf_update_ie_hdr(buf, len);
|
p2p_buf_update_ie_hdr(buf, len);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -172,7 +172,12 @@ static struct wpabuf * p2p_build_go_neg_req(struct p2p_data *p2p,
|
||||||
p2p_buf_update_ie_hdr(buf, len);
|
p2p_buf_update_ie_hdr(buf, len);
|
||||||
|
|
||||||
/* WPS IE with Device Password ID attribute */
|
/* WPS IE with Device Password ID attribute */
|
||||||
p2p_build_wps_ie(p2p, buf, p2p_wps_method_pw_id(peer->wps_method), 0);
|
if (p2p_build_wps_ie(p2p, buf, p2p_wps_method_pw_id(peer->wps_method),
|
||||||
|
0) < 0) {
|
||||||
|
p2p_dbg(p2p, "Failed to build WPS IE for GO Negotiation Request");
|
||||||
|
wpabuf_free(buf);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_WIFI_DISPLAY
|
#ifdef CONFIG_WIFI_DISPLAY
|
||||||
if (p2p->wfd_ie_go_neg)
|
if (p2p->wfd_ie_go_neg)
|
||||||
|
@ -307,9 +312,13 @@ static struct wpabuf * p2p_build_go_neg_resp(struct p2p_data *p2p,
|
||||||
p2p_buf_update_ie_hdr(buf, len);
|
p2p_buf_update_ie_hdr(buf, len);
|
||||||
|
|
||||||
/* WPS IE with Device Password ID attribute */
|
/* WPS IE with Device Password ID attribute */
|
||||||
p2p_build_wps_ie(p2p, buf,
|
if (p2p_build_wps_ie(p2p, buf,
|
||||||
p2p_wps_method_pw_id(peer ? peer->wps_method :
|
p2p_wps_method_pw_id(peer ? peer->wps_method :
|
||||||
WPS_NOT_READY), 0);
|
WPS_NOT_READY), 0) < 0) {
|
||||||
|
p2p_dbg(p2p, "Failed to build WPS IE for GO Negotiation Response");
|
||||||
|
wpabuf_free(buf);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_WIFI_DISPLAY
|
#ifdef CONFIG_WIFI_DISPLAY
|
||||||
if (p2p->wfd_ie_go_neg)
|
if (p2p->wfd_ie_go_neg)
|
||||||
|
|
|
@ -633,8 +633,8 @@ void p2p_buf_add_noa(struct wpabuf *buf, u8 noa_index, u8 opp_ps, u8 ctwindow,
|
||||||
void p2p_buf_add_ext_listen_timing(struct wpabuf *buf, u16 period,
|
void p2p_buf_add_ext_listen_timing(struct wpabuf *buf, u16 period,
|
||||||
u16 interval);
|
u16 interval);
|
||||||
void p2p_buf_add_p2p_interface(struct wpabuf *buf, struct p2p_data *p2p);
|
void p2p_buf_add_p2p_interface(struct wpabuf *buf, struct p2p_data *p2p);
|
||||||
void p2p_build_wps_ie(struct p2p_data *p2p, struct wpabuf *buf, int pw_id,
|
int p2p_build_wps_ie(struct p2p_data *p2p, struct wpabuf *buf, int pw_id,
|
||||||
int all_attr);
|
int all_attr);
|
||||||
|
|
||||||
/* p2p_sd.c */
|
/* p2p_sd.c */
|
||||||
struct p2p_sd_query * p2p_pending_sd_req(struct p2p_data *p2p,
|
struct p2p_sd_query * p2p_pending_sd_req(struct p2p_data *p2p,
|
||||||
|
|
|
@ -118,6 +118,8 @@ int wps_build_config_methods(struct wpabuf *msg, u16 methods)
|
||||||
|
|
||||||
int wps_build_uuid_e(struct wpabuf *msg, const u8 *uuid)
|
int wps_build_uuid_e(struct wpabuf *msg, const u8 *uuid)
|
||||||
{
|
{
|
||||||
|
if (wpabuf_tailroom(msg) < 4 + WPS_UUID_LEN)
|
||||||
|
return -1;
|
||||||
wpa_printf(MSG_DEBUG, "WPS: * UUID-E");
|
wpa_printf(MSG_DEBUG, "WPS: * UUID-E");
|
||||||
wpabuf_put_be16(msg, ATTR_UUID_E);
|
wpabuf_put_be16(msg, ATTR_UUID_E);
|
||||||
wpabuf_put_be16(msg, WPS_UUID_LEN);
|
wpabuf_put_be16(msg, WPS_UUID_LEN);
|
||||||
|
@ -183,6 +185,8 @@ int wps_build_version(struct wpabuf *msg)
|
||||||
* backwards compatibility reasons. The real version negotiation is
|
* backwards compatibility reasons. The real version negotiation is
|
||||||
* done with Version2.
|
* done with Version2.
|
||||||
*/
|
*/
|
||||||
|
if (wpabuf_tailroom(msg) < 5)
|
||||||
|
return -1;
|
||||||
wpa_printf(MSG_DEBUG, "WPS: * Version (hardcoded 0x10)");
|
wpa_printf(MSG_DEBUG, "WPS: * Version (hardcoded 0x10)");
|
||||||
wpabuf_put_be16(msg, ATTR_VERSION);
|
wpabuf_put_be16(msg, ATTR_VERSION);
|
||||||
wpabuf_put_be16(msg, 1);
|
wpabuf_put_be16(msg, 1);
|
||||||
|
@ -197,6 +201,10 @@ int wps_build_wfa_ext(struct wpabuf *msg, int req_to_enroll,
|
||||||
#ifdef CONFIG_WPS2
|
#ifdef CONFIG_WPS2
|
||||||
u8 *len;
|
u8 *len;
|
||||||
|
|
||||||
|
if (wpabuf_tailroom(msg) <
|
||||||
|
7 + 3 + (req_to_enroll ? 3 : 0) +
|
||||||
|
(auth_macs ? 2 + auth_macs_count * ETH_ALEN : 0))
|
||||||
|
return -1;
|
||||||
wpabuf_put_be16(msg, ATTR_VENDOR_EXT);
|
wpabuf_put_be16(msg, ATTR_VENDOR_EXT);
|
||||||
len = wpabuf_put(msg, 2); /* to be filled */
|
len = wpabuf_put(msg, 2); /* to be filled */
|
||||||
wpabuf_put_be24(msg, WPS_VENDOR_ID_WFA);
|
wpabuf_put_be24(msg, WPS_VENDOR_ID_WFA);
|
||||||
|
@ -230,6 +238,8 @@ int wps_build_wfa_ext(struct wpabuf *msg, int req_to_enroll,
|
||||||
|
|
||||||
#ifdef CONFIG_WPS_TESTING
|
#ifdef CONFIG_WPS_TESTING
|
||||||
if (WPS_VERSION > 0x20) {
|
if (WPS_VERSION > 0x20) {
|
||||||
|
if (wpabuf_tailroom(msg) < 5)
|
||||||
|
return -1;
|
||||||
wpa_printf(MSG_DEBUG, "WPS: * Extensibility Testing - extra "
|
wpa_printf(MSG_DEBUG, "WPS: * Extensibility Testing - extra "
|
||||||
"attribute");
|
"attribute");
|
||||||
wpabuf_put_be16(msg, ATTR_EXTENSIBILITY_TEST);
|
wpabuf_put_be16(msg, ATTR_EXTENSIBILITY_TEST);
|
||||||
|
|
Loading…
Reference in a new issue