]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
WPS ER: Fix UPnP XML Device Description parser to find correct device
authorJouni Malinen <jouni@qca.qualcomm.com>
Wed, 31 Aug 2011 10:56:03 +0000 (13:56 +0300)
committerJouni Malinen <j@w1.fi>
Wed, 31 Aug 2011 10:56:03 +0000 (13:56 +0300)
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
src/wps/upnp_xml.h
src/wps/wps_er.c

index b1b1e2b165dd023dcf05e2b7d5da6b5bf0d74722..a9958eeda80d1881711485b673e13cecee61a801 100644 (file)
@@ -75,8 +75,8 @@
  * Note that angle brackets present in the original data must have been encoded
  * as &lt; and &gt; 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++;
index 62dbe602de6f348e1e4a26657027dafa42589f9b..616af3dadc804ac0643d7a16004b0a4d8bd36c64 100644 (file)
@@ -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);
index a4618369516c7c5f04355bfb24154951680e3366..856e9fbf15ce473fef3a5d1eadfe95d048b3b3ed 100644 (file)
@@ -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 <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);