static enum http_reply_code web_process_put_wlan_response(struct upnp_wps_device_sm *sm, char *data, struct wpabuf **reply, const char **replyname) { struct wpabuf *msg; enum http_reply_code ret; u8 macaddr[ETH_ALEN]; int ev_type; int type; char *val; /* * External UPnP-based Registrar is passing us a message to be proxied * over to a Wi-Fi -based client of ours. */ wpa_printf(MSG_DEBUG, "WPS UPnP: PutWLANResponse"); msg = xml_get_base64_item(data, "NewMessage", &ret); if (msg == NULL) return ret; val = xml_get_first_item(data, "NewWLANEventType"); if (val == NULL) { wpabuf_free(msg); return UPNP_ARG_VALUE_INVALID; } ev_type = atol(val); os_free(val); val = xml_get_first_item(data, "NewWLANEventMAC"); if (val == NULL || hwaddr_aton(val, macaddr)) { wpabuf_free(msg); os_free(val); return UPNP_ARG_VALUE_INVALID; } os_free(val); if (ev_type == UPNP_WPS_WLANEVENT_TYPE_EAP) { struct wps_parse_attr attr; if (wps_parse_msg(msg, &attr) < 0 || attr.msg_type == NULL) type = -1; else type = *attr.msg_type; wpa_printf(MSG_DEBUG, "WPS UPnP: Message Type %d", type); } else type = -1; if (!sm->ctx->rx_req_put_wlan_response || sm->ctx->rx_req_put_wlan_response(sm->priv, ev_type, macaddr, msg, type)) { wpa_printf(MSG_INFO, "WPS UPnP: Fail: sm->ctx->" "rx_req_put_wlan_response"); wpabuf_free(msg); return HTTP_INTERNAL_SERVER_ERROR; } wpabuf_free(msg); *replyname = NULL; *reply = NULL; return HTTP_OK; }
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; }
struct wpabuf * xml_get_base64_item(const char *data, const char *name, enum http_reply_code *ret) { char *msg; struct wpabuf *buf; unsigned char *decoded; size_t len; msg = xml_get_first_item(data, name); if (msg == NULL) { *ret = UPNP_ARG_VALUE_INVALID; return NULL; } decoded = base64_decode((unsigned char *) msg, os_strlen(msg), &len); os_free(msg); if (decoded == NULL) { *ret = UPNP_OUT_OF_MEMORY; return NULL; } buf = wpabuf_alloc_ext_data(decoded, len); if (buf == NULL) { os_free(decoded); *ret = UPNP_OUT_OF_MEMORY; return NULL; } return buf; }
static enum http_reply_code web_process_put_wlan_response(struct upnp_wps_device_sm *sm, char *data, struct wpabuf **reply, const char **replyname) { struct wpabuf *msg; enum http_reply_code ret; u8 macaddr[ETH_ALEN]; int ev_type; int type; char *val; struct upnp_wps_device_interface *iface; int ok = 0; /* * External UPnP-based Registrar is passing us a message to be proxied * over to a Wi-Fi -based client of ours. */ wpa_printf(MSG_DEBUG, "WPS UPnP: PutWLANResponse"); msg = xml_get_base64_item(data, "NewMessage", &ret); if (msg == NULL) { wpa_printf(MSG_DEBUG, "WPS UPnP: Could not extract NewMessage " "from PutWLANResponse"); return ret; } val = xml_get_first_item(data, "NewWLANEventType"); if (val == NULL) { wpa_printf(MSG_DEBUG, "WPS UPnP: No NewWLANEventType in " "PutWLANResponse"); wpabuf_free(msg); return UPNP_ARG_VALUE_INVALID; } ev_type = atol(val); os_free(val); val = xml_get_first_item(data, "NewWLANEventMAC"); if (val == NULL) { wpa_printf(MSG_DEBUG, "WPS UPnP: No NewWLANEventMAC in " "PutWLANResponse"); wpabuf_free(msg); return UPNP_ARG_VALUE_INVALID; } if (hwaddr_aton(val, macaddr)) { wpa_printf(MSG_DEBUG, "WPS UPnP: Invalid NewWLANEventMAC in " "PutWLANResponse: '%s'", val); #ifdef CONFIG_WPS_STRICT { struct wps_parse_attr attr; if (wps_parse_msg(msg, &attr) < 0 || attr.version2) { wpabuf_free(msg); os_free(val); return UPNP_ARG_VALUE_INVALID; } } #endif /* CONFIG_WPS_STRICT */ if (hwaddr_aton2(val, macaddr) > 0) { /* * At least some versions of Intel PROset seem to be * using dot-deliminated MAC address format here. */ wpa_printf(MSG_DEBUG, "WPS UPnP: Workaround - allow " "incorrect MAC address format in " "NewWLANEventMAC: %s -> " MACSTR, val, MAC2STR(macaddr)); } else { wpabuf_free(msg); os_free(val); return UPNP_ARG_VALUE_INVALID; } } os_free(val); if (ev_type == UPNP_WPS_WLANEVENT_TYPE_EAP) { struct wps_parse_attr attr; if (wps_parse_msg(msg, &attr) < 0 || attr.msg_type == NULL) type = -1; else type = *attr.msg_type; wpa_printf(MSG_DEBUG, "WPS UPnP: Message Type %d", type); } else type = -1; dl_list_for_each(iface, &sm->interfaces, struct upnp_wps_device_interface, list) { if (iface->ctx->rx_req_put_wlan_response && iface->ctx->rx_req_put_wlan_response(iface->priv, ev_type, macaddr, msg, type) == 0) ok = 1; } if (!ok) { wpa_printf(MSG_INFO, "WPS UPnP: Fail: sm->ctx->" "rx_req_put_wlan_response"); wpabuf_free(msg); return HTTP_INTERNAL_SERVER_ERROR; } wpabuf_free(msg); *replyname = NULL; *reply = NULL; return HTTP_OK; }
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); char *pos; wpa_hexdump_ascii(MSG_MSGDUMP, "WPS ER: Device info", wpabuf_head(reply), wpabuf_len(reply)); ap->friendly_name = xml_get_first_item(data, "friendlyName"); wpa_printf(MSG_DEBUG, "WPS ER: friendlyName='%s'", ap->friendly_name); ap->manufacturer = xml_get_first_item(data, "manufacturer"); wpa_printf(MSG_DEBUG, "WPS ER: manufacturer='%s'", ap->manufacturer); ap->manufacturer_url = xml_get_first_item(data, "manufacturerURL"); wpa_printf(MSG_DEBUG, "WPS ER: manufacturerURL='%s'", ap->manufacturer_url); ap->model_description = xml_get_first_item(data, "modelDescription"); wpa_printf(MSG_DEBUG, "WPS ER: modelDescription='%s'", ap->model_description); ap->model_name = xml_get_first_item(data, "modelName"); wpa_printf(MSG_DEBUG, "WPS ER: modelName='%s'", ap->model_name); ap->model_number = xml_get_first_item(data, "modelNumber"); wpa_printf(MSG_DEBUG, "WPS ER: modelNumber='%s'", ap->model_number); ap->model_url = xml_get_first_item(data, "modelURL"); wpa_printf(MSG_DEBUG, "WPS ER: modelURL='%s'", ap->model_url); ap->serial_number = xml_get_first_item(data, "serialNumber"); wpa_printf(MSG_DEBUG, "WPS ER: serialNumber='%s'", ap->serial_number); ap->udn = xml_get_first_item(data, "UDN"); wpa_printf(MSG_DEBUG, "WPS ER: UDN='%s'", ap->udn); pos = os_strstr(ap->udn, "uuid:"); if (pos) { pos += 5; if (uuid_str2bin(pos, ap->uuid) < 0) wpa_printf(MSG_DEBUG, "WPS ER: Invalid UUID in UDN"); } ap->upc = xml_get_first_item(data, "UPC"); wpa_printf(MSG_DEBUG, "WPS ER: UPC='%s'", ap->upc); ap->scpd_url = http_link_update( xml_get_first_item(data, "SCPDURL"), ap->location); wpa_printf(MSG_DEBUG, "WPS ER: SCPDURL='%s'", ap->scpd_url); ap->control_url = http_link_update( xml_get_first_item(data, "controlURL"), ap->location); wpa_printf(MSG_DEBUG, "WPS ER: controlURL='%s'", ap->control_url); ap->event_sub_url = http_link_update( xml_get_first_item(data, "eventSubURL"), ap->location); wpa_printf(MSG_DEBUG, "WPS ER: eventSubURL='%s'", ap->event_sub_url); }
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 *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); ap->manufacturer = xml_get_first_item(data, "manufacturer"); wpa_printf(MSG_DEBUG, "WPS ER: manufacturer='%s'", ap->manufacturer); ap->manufacturer_url = xml_get_first_item(data, "manufacturerURL"); wpa_printf(MSG_DEBUG, "WPS ER: manufacturerURL='%s'", ap->manufacturer_url); ap->model_description = xml_get_first_item(data, "modelDescription"); wpa_printf(MSG_DEBUG, "WPS ER: modelDescription='%s'", ap->model_description); ap->model_name = xml_get_first_item(data, "modelName"); wpa_printf(MSG_DEBUG, "WPS ER: modelName='%s'", ap->model_name); ap->model_number = xml_get_first_item(data, "modelNumber"); wpa_printf(MSG_DEBUG, "WPS ER: modelNumber='%s'", ap->model_number); ap->model_url = xml_get_first_item(data, "modelURL"); wpa_printf(MSG_DEBUG, "WPS ER: modelURL='%s'", ap->model_url); ap->serial_number = xml_get_first_item(data, "serialNumber"); wpa_printf(MSG_DEBUG, "WPS ER: serialNumber='%s'", ap->serial_number); ap->udn = xml_get_first_item(data, "UDN"); wpa_printf(MSG_DEBUG, "WPS ER: UDN='%s'", ap->udn); pos = os_strstr(ap->udn, "uuid:"); if (pos) { pos += 5; if (uuid_str2bin(pos, ap->uuid) < 0) wpa_printf(MSG_DEBUG, "WPS ER: Invalid UUID in UDN"); } ap->upc = xml_get_first_item(data, "UPC"); wpa_printf(MSG_DEBUG, "WPS ER: UPC='%s'", ap->upc); ap->scpd_url = http_link_update( xml_get_first_item(data, "SCPDURL"), ap->location); wpa_printf(MSG_DEBUG, "WPS ER: SCPDURL='%s'", ap->scpd_url); ap->control_url = http_link_update( xml_get_first_item(data, "controlURL"), ap->location); wpa_printf(MSG_DEBUG, "WPS ER: controlURL='%s'", ap->control_url); ap->event_sub_url = http_link_update( xml_get_first_item(data, "eventSubURL"), ap->location); wpa_printf(MSG_DEBUG, "WPS ER: eventSubURL='%s'", ap->event_sub_url); }