From ae9c40035829b6b5fbb4ff48bd50781df54642b3 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Wed, 31 Aug 2011 13:56:03 +0300 Subject: [PATCH] WPS ER: Fix UPnP XML Device Description parser to find correct device The device description file may include multiple devices. Improve the simplistic parser by first trying to find the WFADevice:1 device before fetching the device parameters. While this is still far from complete XML parsing, this should address the most common root device specifications. --- src/wps/upnp_xml.c | 4 ++-- src/wps/upnp_xml.h | 2 ++ src/wps/wps_er.c | 47 +++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 50 insertions(+), 3 deletions(-) diff --git a/src/wps/upnp_xml.c b/src/wps/upnp_xml.c index b1b1e2b16..a9958eeda 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 62dbe602d..616af3dad 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_er.c b/src/wps/wps_er.c index a46183695..856e9fbf1 100644 --- a/src/wps/wps_er.c +++ b/src/wps/wps_er.c @@ -502,16 +502,61 @@ static void wps_er_get_device_info(struct wps_er_ap *ap) } +static const char * wps_er_find_wfadevice(const char *data) +{ + const char *tag, *tagname, *end; + char *val; + int found = 0; + + while (!found) { + /* Find next */ + 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);