Parcourir la source

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.
Jouni Malinen il y a 13 ans
Parent
commit
ae9c400358
3 fichiers modifiés avec 50 ajouts et 3 suppressions
  1. 2 2
      src/wps/upnp_xml.c
  2. 2 0
      src/wps/upnp_xml.h
  3. 46 1
      src/wps/wps_er.c

+ 2 - 2
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++;

+ 2 - 0
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);

+ 46 - 1
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 <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);