18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* 28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * UPnP WPS Device - Web connections 38d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Copyright (c) 2000-2003 Intel Corporation 48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Copyright (c) 2006-2007 Sony Corporation 58d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Copyright (c) 2008-2009 Atheros Communications 68d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Copyright (c) 2009, Jouni Malinen <j@w1.fi> 78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * See wps_upnp.c for more details on licensing and code history. 98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "includes.h" 128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common.h" 148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "base64.h" 158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "uuid.h" 168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "httpread.h" 178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "http_server.h" 188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "wps_i.h" 198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "wps_upnp.h" 208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "wps_upnp_i.h" 218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "upnp_xml.h" 228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*************************************************************************** 248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Web connections (we serve pages of info about ourselves, handle 258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * requests, etc. etc.). 268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt **************************************************************************/ 278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define WEB_CONNECTION_TIMEOUT_SEC 30 /* Drop web connection after t.o. */ 298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define WEB_CONNECTION_MAX_READ 8000 /* Max we'll read for TCP request */ 308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define MAX_WEB_CONNECTIONS 10 /* max simultaneous web connects */ 318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const char *urn_wfawlanconfig = 348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "urn:schemas-wifialliance-org:service:WFAWLANConfig:1"; 358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const char *http_server_hdr = 368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Server: unspecified, UPnP/1.0, unspecified\r\n"; 378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const char *http_connection_close = 388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Connection: close\r\n"; 398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* 418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * "Files" that we serve via HTTP. The format of these files is given by 428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * WFA WPS specifications. Extra white space has been removed to save space. 438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const char wps_scpd_xml[] = 468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"<?xml version=\"1.0\"?>\n" 478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"<scpd xmlns=\"urn:schemas-upnp-org:service-1-0\">\n" 488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"<specVersion><major>1</major><minor>0</minor></specVersion>\n" 498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"<actionList>\n" 508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"<action>\n" 518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"<name>GetDeviceInfo</name>\n" 528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"<argumentList>\n" 538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"<argument>\n" 548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"<name>NewDeviceInfo</name>\n" 558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"<direction>out</direction>\n" 568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"<relatedStateVariable>DeviceInfo</relatedStateVariable>\n" 578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"</argument>\n" 588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"</argumentList>\n" 598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"</action>\n" 608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"<action>\n" 618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"<name>PutMessage</name>\n" 628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"<argumentList>\n" 638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"<argument>\n" 648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"<name>NewInMessage</name>\n" 658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"<direction>in</direction>\n" 668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"<relatedStateVariable>InMessage</relatedStateVariable>\n" 678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"</argument>\n" 688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"<argument>\n" 698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"<name>NewOutMessage</name>\n" 708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"<direction>out</direction>\n" 718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"<relatedStateVariable>OutMessage</relatedStateVariable>\n" 728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"</argument>\n" 738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"</argumentList>\n" 748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"</action>\n" 758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"<action>\n" 768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"<name>PutWLANResponse</name>\n" 778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"<argumentList>\n" 788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"<argument>\n" 798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"<name>NewMessage</name>\n" 808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"<direction>in</direction>\n" 818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"<relatedStateVariable>Message</relatedStateVariable>\n" 828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"</argument>\n" 838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"<argument>\n" 848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"<name>NewWLANEventType</name>\n" 858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"<direction>in</direction>\n" 868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"<relatedStateVariable>WLANEventType</relatedStateVariable>\n" 878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"</argument>\n" 888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"<argument>\n" 898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"<name>NewWLANEventMAC</name>\n" 908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"<direction>in</direction>\n" 918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"<relatedStateVariable>WLANEventMAC</relatedStateVariable>\n" 928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"</argument>\n" 938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"</argumentList>\n" 948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"</action>\n" 958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"<action>\n" 968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"<name>SetSelectedRegistrar</name>\n" 978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"<argumentList>\n" 988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"<argument>\n" 998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"<name>NewMessage</name>\n" 1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"<direction>in</direction>\n" 1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"<relatedStateVariable>Message</relatedStateVariable>\n" 1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"</argument>\n" 1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"</argumentList>\n" 1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"</action>\n" 1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"</actionList>\n" 1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"<serviceStateTable>\n" 1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"<stateVariable sendEvents=\"no\">\n" 1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"<name>Message</name>\n" 1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"<dataType>bin.base64</dataType>\n" 1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"</stateVariable>\n" 1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"<stateVariable sendEvents=\"no\">\n" 1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"<name>InMessage</name>\n" 1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"<dataType>bin.base64</dataType>\n" 1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"</stateVariable>\n" 1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"<stateVariable sendEvents=\"no\">\n" 1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"<name>OutMessage</name>\n" 1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"<dataType>bin.base64</dataType>\n" 1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"</stateVariable>\n" 1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"<stateVariable sendEvents=\"no\">\n" 1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"<name>DeviceInfo</name>\n" 1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"<dataType>bin.base64</dataType>\n" 1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"</stateVariable>\n" 1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"<stateVariable sendEvents=\"yes\">\n" 1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"<name>APStatus</name>\n" 1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"<dataType>ui1</dataType>\n" 1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"</stateVariable>\n" 1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"<stateVariable sendEvents=\"yes\">\n" 1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"<name>STAStatus</name>\n" 1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"<dataType>ui1</dataType>\n" 1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"</stateVariable>\n" 1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"<stateVariable sendEvents=\"yes\">\n" 1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"<name>WLANEvent</name>\n" 1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"<dataType>bin.base64</dataType>\n" 1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"</stateVariable>\n" 1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"<stateVariable sendEvents=\"no\">\n" 1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"<name>WLANEventType</name>\n" 1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"<dataType>ui1</dataType>\n" 1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"</stateVariable>\n" 1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"<stateVariable sendEvents=\"no\">\n" 1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"<name>WLANEventMAC</name>\n" 1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"<dataType>string</dataType>\n" 1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"</stateVariable>\n" 1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"<stateVariable sendEvents=\"no\">\n" 1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"<name>WLANResponse</name>\n" 1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"<dataType>bin.base64</dataType>\n" 1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"</stateVariable>\n" 1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"</serviceStateTable>\n" 1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"</scpd>\n" 1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt; 1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const char *wps_device_xml_prefix = 1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "<?xml version=\"1.0\"?>\n" 1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "<root xmlns=\"urn:schemas-upnp-org:device-1-0\">\n" 1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "<specVersion>\n" 1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "<major>1</major>\n" 1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "<minor>0</minor>\n" 1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "</specVersion>\n" 1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "<device>\n" 1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "<deviceType>urn:schemas-wifialliance-org:device:WFADevice:1" 1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "</deviceType>\n"; 1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const char *wps_device_xml_postfix = 1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "<serviceList>\n" 1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "<service>\n" 1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "<serviceType>urn:schemas-wifialliance-org:service:WFAWLANConfig:1" 1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "</serviceType>\n" 1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "<serviceId>urn:wifialliance-org:serviceId:WFAWLANConfig1</serviceId>" 1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "\n" 1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "<SCPDURL>" UPNP_WPS_SCPD_XML_FILE "</SCPDURL>\n" 1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "<controlURL>" UPNP_WPS_DEVICE_CONTROL_FILE "</controlURL>\n" 1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "<eventSubURL>" UPNP_WPS_DEVICE_EVENT_FILE "</eventSubURL>\n" 1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "</service>\n" 1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "</serviceList>\n" 1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "</device>\n" 1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "</root>\n"; 1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* format_wps_device_xml -- produce content of "file" wps_device.xml 1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * (UPNP_WPS_DEVICE_XML_FILE) 1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 1827832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidtstatic void format_wps_device_xml(struct upnp_wps_device_interface *iface, 1837832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt struct upnp_wps_device_sm *sm, 1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *buf) 1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const char *s; 1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char uuid_string[80]; 1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_str(buf, wps_device_xml_prefix); 1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Add required fields with default values if not configured. Add 1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * optional and recommended fields only if configured. 1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt s = iface->wps->friendly_name; 1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt s = ((s && *s) ? s : "WPS Access Point"); 1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt xml_add_tagged_data(buf, "friendlyName", s); 1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt s = iface->wps->dev.manufacturer; 2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt s = ((s && *s) ? s : ""); 2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt xml_add_tagged_data(buf, "manufacturer", s); 2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (iface->wps->manufacturer_url) 2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt xml_add_tagged_data(buf, "manufacturerURL", 2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iface->wps->manufacturer_url); 2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (iface->wps->model_description) 2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt xml_add_tagged_data(buf, "modelDescription", 2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iface->wps->model_description); 2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt s = iface->wps->dev.model_name; 2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt s = ((s && *s) ? s : ""); 2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt xml_add_tagged_data(buf, "modelName", s); 2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (iface->wps->dev.model_number) 2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt xml_add_tagged_data(buf, "modelNumber", 2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iface->wps->dev.model_number); 2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (iface->wps->model_url) 2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt xml_add_tagged_data(buf, "modelURL", iface->wps->model_url); 2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (iface->wps->dev.serial_number) 2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt xml_add_tagged_data(buf, "serialNumber", 2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iface->wps->dev.serial_number); 2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt uuid_bin2str(iface->wps->uuid, uuid_string, sizeof(uuid_string)); 2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt s = uuid_string; 2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Need "uuid:" prefix, thus we can't use xml_add_tagged_data() 2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * easily... 2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_str(buf, "<UDN>uuid:"); 2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt xml_data_encode(buf, s, os_strlen(s)); 2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_str(buf, "</UDN>\n"); 2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (iface->wps->upc) 2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt xml_add_tagged_data(buf, "UPC", iface->wps->upc); 2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_str(buf, wps_device_xml_postfix); 2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void http_put_reply_code(struct wpabuf *buf, enum http_reply_code code) 2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_str(buf, "HTTP/1.1 "); 2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (code) { 2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case HTTP_OK: 2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_str(buf, "200 OK\r\n"); 2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case HTTP_BAD_REQUEST: 2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_str(buf, "400 Bad request\r\n"); 2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case HTTP_PRECONDITION_FAILED: 2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_str(buf, "412 Precondition failed\r\n"); 2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case HTTP_UNIMPLEMENTED: 2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_str(buf, "501 Unimplemented\r\n"); 2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case HTTP_INTERNAL_SERVER_ERROR: 2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_str(buf, "500 Internal server error\r\n"); 2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void http_put_date(struct wpabuf *buf) 2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_str(buf, "Date: "); 2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt format_date(buf); 2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_str(buf, "\r\n"); 2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void http_put_empty(struct wpabuf *buf, enum http_reply_code code) 2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt http_put_reply_code(buf, code); 2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_str(buf, http_server_hdr); 2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_str(buf, http_connection_close); 2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_str(buf, "Content-Length: 0\r\n" 2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "\r\n"); 2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* Given that we have received a header w/ GET, act upon it 2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Format of GET (case-insensitive): 2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * First line must be: 2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * GET /<file> HTTP/1.1 2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Since we don't do anything fancy we just ignore other lines. 2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Our response (if no error) which includes only required lines is: 2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * HTTP/1.1 200 OK 2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Connection: close 2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Content-Type: text/xml 2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Date: <rfc1123-date> 2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Header lines must end with \r\n 2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Per RFC 2616, content-length: is not required but connection:close 3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * would appear to be required (given that we will be closing it!). 3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void web_connection_parse_get(struct upnp_wps_device_sm *sm, 3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct http_request *hreq, char *filename) 3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *buf; /* output buffer, allocated */ 3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *put_length_here; 3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *body_start; 3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum { 3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt GET_DEVICE_XML_FILE, 3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt GET_SCPD_XML_FILE 3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } req; 3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t extra_len = 0; 3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int body_length; 3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char len_buf[10]; 3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct upnp_wps_device_interface *iface; 3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iface = dl_list_first(&sm->interfaces, 3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct upnp_wps_device_interface, list); 3197832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt if (iface == NULL) { 3207832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt http_request_deinit(hreq); 3217832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt return; 3227832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt } 3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * It is not required that filenames be case insensitive but it is 3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * allowed and cannot hurt here. 3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strcasecmp(filename, UPNP_WPS_DEVICE_XML_FILE) == 0) { 3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS UPnP: HTTP GET for device XML"); 3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt req = GET_DEVICE_XML_FILE; 3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt extra_len = 3000; 3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (iface->wps->friendly_name) 3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt extra_len += os_strlen(iface->wps->friendly_name); 3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (iface->wps->manufacturer_url) 3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt extra_len += os_strlen(iface->wps->manufacturer_url); 3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (iface->wps->model_description) 3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt extra_len += os_strlen(iface->wps->model_description); 3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (iface->wps->model_url) 3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt extra_len += os_strlen(iface->wps->model_url); 3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (iface->wps->upc) 3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt extra_len += os_strlen(iface->wps->upc); 3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (!os_strcasecmp(filename, UPNP_WPS_SCPD_XML_FILE)) { 3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS UPnP: HTTP GET for SCPD XML"); 3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt req = GET_SCPD_XML_FILE; 3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt extra_len = os_strlen(wps_scpd_xml); 3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* File not found */ 3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS UPnP: HTTP GET file not found: %s", 3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt filename); 3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf = wpabuf_alloc(200); 3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (buf == NULL) { 3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt http_request_deinit(hreq); 3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_str(buf, 3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "HTTP/1.1 404 Not Found\r\n" 3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Connection: close\r\n"); 3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt http_put_date(buf); 3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* terminating empty line */ 3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_str(buf, "\r\n"); 3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto send_buf; 3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf = wpabuf_alloc(1000 + extra_len); 3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (buf == NULL) { 3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt http_request_deinit(hreq); 3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_str(buf, 3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "HTTP/1.1 200 OK\r\n" 3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Content-Type: text/xml; charset=\"utf-8\"\r\n"); 3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_str(buf, "Server: Unspecified, UPnP/1.0, Unspecified\r\n"); 3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_str(buf, "Connection: close\r\n"); 3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_str(buf, "Content-Length: "); 3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * We will paste the length in later, leaving some extra whitespace. 3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * HTTP code is supposed to be tolerant of extra whitespace. 3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt put_length_here = wpabuf_put(buf, 0); 3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_str(buf, " \r\n"); 3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt http_put_date(buf); 3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* terminating empty line */ 3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_str(buf, "\r\n"); 3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt body_start = wpabuf_put(buf, 0); 3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (req) { 3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case GET_DEVICE_XML_FILE: 3957832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt format_wps_device_xml(iface, sm, buf); 3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case GET_SCPD_XML_FILE: 3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_str(buf, wps_scpd_xml); 3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Now patch in the content length at the end */ 4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt body_length = (char *) wpabuf_put(buf, 0) - body_start; 4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_snprintf(len_buf, 10, "%d", body_length); 4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(put_length_here, len_buf, os_strlen(len_buf)); 4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtsend_buf: 4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt http_request_send_and_deinit(hreq, buf); 4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic enum http_reply_code 4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtweb_process_get_device_info(struct upnp_wps_device_sm *sm, 4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf **reply, const char **replyname) 4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt static const char *name = "NewDeviceInfo"; 4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wps_config cfg; 4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct upnp_wps_device_interface *iface; 4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct upnp_wps_peer *peer; 4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iface = dl_list_first(&sm->interfaces, 4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct upnp_wps_device_interface, list); 4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS UPnP: GetDeviceInfo"); 4258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4267832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt if (!iface || iface->ctx->ap_pin == NULL) 4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return HTTP_INTERNAL_SERVER_ERROR; 4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4297832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt peer = &iface->peer; 4307832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt 4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Request for DeviceInfo, i.e., M1 TLVs. This is a start of WPS 4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * registration over UPnP with the AP acting as an Enrollee. It should 4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * be noted that this is frequently used just to get the device data, 4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * i.e., there may not be any intent to actually complete the 4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * registration. 4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (peer->wps) 4408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_deinit(peer->wps); 4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&cfg, 0, sizeof(cfg)); 4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cfg.wps = iface->wps; 4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cfg.pin = (u8 *) iface->ctx->ap_pin; 4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cfg.pin_len = os_strlen(iface->ctx->ap_pin); 4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->wps = wps_init(&cfg); 4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (peer->wps) { 4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum wsc_op_code op_code; 4498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *reply = wps_get_msg(peer->wps, &op_code); 4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (*reply == NULL) { 4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_deinit(peer->wps); 4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->wps = NULL; 4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else 4558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *reply = NULL; 4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (*reply == NULL) { 4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "WPS UPnP: Failed to get DeviceInfo"); 4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return HTTP_INTERNAL_SERVER_ERROR; 4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *replyname = name; 4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return HTTP_OK; 4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic enum http_reply_code 4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtweb_process_put_message(struct upnp_wps_device_sm *sm, char *data, 4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf **reply, const char **replyname) 4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *msg; 4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt static const char *name = "NewOutMessage"; 4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum http_reply_code ret; 4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum wps_process_res res; 4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum wsc_op_code op_code; 4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct upnp_wps_device_interface *iface; 4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iface = dl_list_first(&sm->interfaces, 4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct upnp_wps_device_interface, list); 4787832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt if (!iface) 4797832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt return HTTP_INTERNAL_SERVER_ERROR; 4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * PutMessage is used by external UPnP-based Registrar to perform WPS 4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * operation with the access point itself; as compared with 4848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * PutWLANResponse which is for proxying. 4858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS UPnP: PutMessage"); 4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = xml_get_base64_item(data, "NewInMessage", &ret); 4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (msg == NULL) 4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 4908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = wps_process_msg(iface->peer.wps, WSC_UPnP, msg); 4918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res == WPS_FAILURE) 4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *reply = NULL; 4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 4948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *reply = wps_get_msg(iface->peer.wps, &op_code); 4958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(msg); 4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (*reply == NULL) 4978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return HTTP_INTERNAL_SERVER_ERROR; 4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *replyname = name; 4998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return HTTP_OK; 5008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic enum http_reply_code 5048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtweb_process_put_wlan_response(struct upnp_wps_device_sm *sm, char *data, 5058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf **reply, const char **replyname) 5068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *msg; 5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum http_reply_code ret; 5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 macaddr[ETH_ALEN]; 5108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ev_type; 5118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int type; 5128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *val; 5138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct upnp_wps_device_interface *iface; 5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ok = 0; 5158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 5178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * External UPnP-based Registrar is passing us a message to be proxied 5188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * over to a Wi-Fi -based client of ours. 5198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 5208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS UPnP: PutWLANResponse"); 5228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = xml_get_base64_item(data, "NewMessage", &ret); 5238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (msg == NULL) { 5248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS UPnP: Could not extract NewMessage " 5258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "from PutWLANResponse"); 5268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 5278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt val = xml_get_first_item(data, "NewWLANEventType"); 5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (val == NULL) { 5308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS UPnP: No NewWLANEventType in " 5318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "PutWLANResponse"); 5328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(msg); 5338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return UPNP_ARG_VALUE_INVALID; 5348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ev_type = atol(val); 5368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(val); 5378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt val = xml_get_first_item(data, "NewWLANEventMAC"); 5388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (val == NULL) { 5398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS UPnP: No NewWLANEventMAC in " 5408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "PutWLANResponse"); 5418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(msg); 5428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return UPNP_ARG_VALUE_INVALID; 5438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hwaddr_aton(val, macaddr)) { 5458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS UPnP: Invalid NewWLANEventMAC in " 5468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "PutWLANResponse: '%s'", val); 5478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_WPS_STRICT 5488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt { 5498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wps_parse_attr attr; 5508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wps_parse_msg(msg, &attr) < 0 || attr.version2) { 5518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(msg); 5528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(val); 5538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return UPNP_ARG_VALUE_INVALID; 5548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_WPS_STRICT */ 5578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hwaddr_aton2(val, macaddr) > 0) { 5588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 5598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * At least some versions of Intel PROset seem to be 5608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * using dot-deliminated MAC address format here. 5618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 5628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS UPnP: Workaround - allow " 5638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "incorrect MAC address format in " 5648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "NewWLANEventMAC: %s -> " MACSTR, 5658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt val, MAC2STR(macaddr)); 5668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 5678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(msg); 5688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(val); 5698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return UPNP_ARG_VALUE_INVALID; 5708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(val); 5738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ev_type == UPNP_WPS_WLANEVENT_TYPE_EAP) { 5748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wps_parse_attr attr; 5758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wps_parse_msg(msg, &attr) < 0 || 5768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt attr.msg_type == NULL) 5778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt type = -1; 5788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 5798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt type = *attr.msg_type; 5808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS UPnP: Message Type %d", type); 5818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else 5828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt type = -1; 5838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dl_list_for_each(iface, &sm->interfaces, 5848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct upnp_wps_device_interface, list) { 5858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (iface->ctx->rx_req_put_wlan_response && 5868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iface->ctx->rx_req_put_wlan_response(iface->priv, ev_type, 5878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt macaddr, msg, type) 5888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt == 0) 5898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ok = 1; 5908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!ok) { 5938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "WPS UPnP: Fail: sm->ctx->" 5948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "rx_req_put_wlan_response"); 5958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(msg); 5968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return HTTP_INTERNAL_SERVER_ERROR; 5978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(msg); 5998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *replyname = NULL; 6008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *reply = NULL; 6018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return HTTP_OK; 6028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int find_er_addr(struct subscription *s, struct sockaddr_in *cli) 6068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct subscr_addr *a; 6088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dl_list_for_each(a, &s->addr_list, struct subscr_addr, list) { 6108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (cli->sin_addr.s_addr == a->saddr.sin_addr.s_addr) 6118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 1; 6128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 6148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct subscription * find_er(struct upnp_wps_device_sm *sm, 6188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct sockaddr_in *cli) 6198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct subscription *s; 6218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dl_list_for_each(s, &sm->subscriptions, struct subscription, list) 6228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (find_er_addr(s, cli)) 6238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return s; 6248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 6258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic enum http_reply_code 6298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtweb_process_set_selected_registrar(struct upnp_wps_device_sm *sm, 6308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct sockaddr_in *cli, char *data, 6318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf **reply, 6328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const char **replyname) 6338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *msg; 6358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum http_reply_code ret; 6368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct subscription *s; 6378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct upnp_wps_device_interface *iface; 6388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int err = 0; 6398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS UPnP: SetSelectedRegistrar"); 6418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt s = find_er(sm, cli); 6428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (s == NULL) { 6438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS UPnP: Ignore SetSelectedRegistrar " 6448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "from unknown ER"); 6458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return UPNP_ACTION_FAILED; 6468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = xml_get_base64_item(data, "NewMessage", &ret); 6488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (msg == NULL) 6498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 6508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dl_list_for_each(iface, &sm->interfaces, 6518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct upnp_wps_device_interface, list) { 6528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (upnp_er_set_selected_registrar(iface->wps->registrar, s, 6538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg)) 6548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt err = 1; 6558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(msg); 6578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (err) 6588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return HTTP_INTERNAL_SERVER_ERROR; 6598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *replyname = NULL; 6608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *reply = NULL; 6618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return HTTP_OK; 6628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const char *soap_prefix = 6668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "<?xml version=\"1.0\"?>\n" 6678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" " 6688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">\n" 6698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "<s:Body>\n"; 6708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const char *soap_postfix = 6718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "</s:Body>\n</s:Envelope>\n"; 6728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const char *soap_error_prefix = 6748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "<s:Fault>\n" 6758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "<faultcode>s:Client</faultcode>\n" 6768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "<faultstring>UPnPError</faultstring>\n" 6778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "<detail>\n" 6788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "<UPnPError xmlns=\"urn:schemas-upnp-org:control-1-0\">\n"; 6798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const char *soap_error_postfix = 6808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "<errorDescription>Error</errorDescription>\n" 6818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "</UPnPError>\n" 6828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "</detail>\n" 6838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "</s:Fault>\n"; 6848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void web_connection_send_reply(struct http_request *req, 6868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum http_reply_code ret, 6878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const char *action, int action_len, 6888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpabuf *reply, 6898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const char *replyname) 6908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *buf; 6928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *replydata; 6938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *put_length_here = NULL; 6948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *body_start = NULL; 6958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (reply) { 6978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len; 6988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt replydata = (char *) base64_encode(wpabuf_head(reply), 6998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_len(reply), &len); 7008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else 7018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt replydata = NULL; 7028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Parameters of the response: 7048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * action(action_len) -- action we are responding to 7058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * replyname -- a name we need for the reply 7068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * replydata -- NULL or null-terminated string 7078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 7088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf = wpabuf_alloc(1000 + (replydata ? os_strlen(replydata) : 0U) + 7098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (action_len > 0 ? action_len * 2 : 0)); 7108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (buf == NULL) { 7118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "WPS UPnP: Cannot allocate reply to " 7128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "POST"); 7138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(replydata); 7148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt http_request_deinit(req); 7158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 7168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 7198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Assuming we will be successful, put in the output header first. 7208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Note: we do not keep connections alive (and httpread does 7218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * not support it)... therefore we must have Connection: close. 7228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 7238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret == HTTP_OK) { 7248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_str(buf, 7258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "HTTP/1.1 200 OK\r\n" 7268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Content-Type: text/xml; " 7278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "charset=\"utf-8\"\r\n"); 7288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 7298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_printf(buf, "HTTP/1.1 %d Error\r\n", ret); 7308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_str(buf, http_connection_close); 7328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_str(buf, "Content-Length: "); 7348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 7358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * We will paste the length in later, leaving some extra whitespace. 7368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * HTTP code is supposed to be tolerant of extra whitespace. 7378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 7388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt put_length_here = wpabuf_put(buf, 0); 7398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_str(buf, " \r\n"); 7408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt http_put_date(buf); 7428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* terminating empty line */ 7448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_str(buf, "\r\n"); 7458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt body_start = wpabuf_put(buf, 0); 7478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret == HTTP_OK) { 7498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_str(buf, soap_prefix); 7508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_str(buf, "<u:"); 7518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_data(buf, action, action_len); 7528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_str(buf, "Response xmlns:u=\""); 7538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_str(buf, urn_wfawlanconfig); 7548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_str(buf, "\">\n"); 7558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (replydata && replyname) { 7568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: might possibly need to escape part of reply 7578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * data? ... 7588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * probably not, unlikely to have ampersand(&) or left 7598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * angle bracket (<) in it... 7608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 7618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_printf(buf, "<%s>", replyname); 7628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_str(buf, replydata); 7638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_printf(buf, "</%s>\n", replyname); 7648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_str(buf, "</u:"); 7668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_data(buf, action, action_len); 7678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_str(buf, "Response>\n"); 7688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_str(buf, soap_postfix); 7698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 7708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Error case */ 7718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_str(buf, soap_prefix); 7728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_str(buf, soap_error_prefix); 7738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_printf(buf, "<errorCode>%d</errorCode>\n", ret); 7748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_str(buf, soap_error_postfix); 7758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_str(buf, soap_postfix); 7768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(replydata); 7788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Now patch in the content length at the end */ 7808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (body_start && put_length_here) { 7818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int body_length = (char *) wpabuf_put(buf, 0) - body_start; 7828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char len_buf[10]; 7838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_snprintf(len_buf, sizeof(len_buf), "%d", body_length); 7848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(put_length_here, len_buf, os_strlen(len_buf)); 7858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt http_request_send_and_deinit(req, buf); 7888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const char * web_get_action(struct http_request *req, 7928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t *action_len) 7938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const char *match; 7958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int match_len; 7968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *b; 7978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *action; 7988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *action_len = 0; 8008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* The SOAPAction line of the header tells us what we want to do */ 8018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt b = http_request_get_hdr_line(req, "SOAPAction:"); 8028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (b == NULL) 8038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 8048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (*b == '"') 8058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt b++; 8068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 8078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 8088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt match = urn_wfawlanconfig; 8098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt match_len = os_strlen(urn_wfawlanconfig) - 1; 8108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strncasecmp(b, match, match_len)) 8118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 8128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt b += match_len; 8138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* skip over version */ 8148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (isgraph(*b) && *b != '#') 8158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt b++; 8168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (*b != '#') 8178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 8188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt b++; 8198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Following the sharp(#) should be the action and a double quote */ 8208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt action = b; 8218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (isgraph(*b) && *b != '"') 8228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt b++; 8238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (*b != '"') 8248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 8258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *action_len = b - action; 8268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return action; 8278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 8288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* Given that we have received a header w/ POST, act upon it 8318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 8328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Format of POST (case-insensitive): 8338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 8348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * First line must be: 8358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * POST /<file> HTTP/1.1 8368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Since we don't do anything fancy we just ignore other lines. 8378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 8388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Our response (if no error) which includes only required lines is: 8398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * HTTP/1.1 200 OK 8408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Connection: close 8418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Content-Type: text/xml 8428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Date: <rfc1123-date> 8438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 8448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Header lines must end with \r\n 8458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Per RFC 2616, content-length: is not required but connection:close 8468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * would appear to be required (given that we will be closing it!). 8478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 8488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void web_connection_parse_post(struct upnp_wps_device_sm *sm, 8498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct sockaddr_in *cli, 8508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct http_request *req, 8518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const char *filename) 8528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 8538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum http_reply_code ret; 8548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *data = http_request_get_data(req); /* body of http msg */ 8558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const char *action = NULL; 8568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t action_len = 0; 8578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const char *replyname = NULL; /* argument name for the reply */ 8588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *reply = NULL; /* data for the reply */ 8598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strcasecmp(filename, UPNP_WPS_DEVICE_CONTROL_FILE)) { 8618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "WPS UPnP: Invalid POST filename %s", 8628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt filename); 8638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = HTTP_NOT_FOUND; 8648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto bad; 8658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = UPNP_INVALID_ACTION; 8688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt action = web_get_action(req, &action_len); 8698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (action == NULL) 8708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto bad; 8718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!os_strncasecmp("GetDeviceInfo", action, action_len)) 8738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = web_process_get_device_info(sm, &reply, &replyname); 8748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (!os_strncasecmp("PutMessage", action, action_len)) 8758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = web_process_put_message(sm, data, &reply, &replyname); 8768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (!os_strncasecmp("PutWLANResponse", action, action_len)) 8778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = web_process_put_wlan_response(sm, data, &reply, 8788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &replyname); 8798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (!os_strncasecmp("SetSelectedRegistrar", action, action_len)) 8808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = web_process_set_selected_registrar(sm, cli, data, &reply, 8818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &replyname); 8828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 8838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "WPS UPnP: Unknown POST type"); 8848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtbad: 8868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret != HTTP_OK) 8878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "WPS UPnP: POST failure ret=%d", ret); 8888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt web_connection_send_reply(req, ret, action, action_len, reply, 8898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt replyname); 8908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(reply); 8918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 8928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* Given that we have received a header w/ SUBSCRIBE, act upon it 8958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 8968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Format of SUBSCRIBE (case-insensitive): 8978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 8988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * First line must be: 8998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * SUBSCRIBE /wps_event HTTP/1.1 9008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 9018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Our response (if no error) which includes only required lines is: 9028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * HTTP/1.1 200 OK 9038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Server: xx, UPnP/1.0, xx 9048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * SID: uuid:xxxxxxxxx 9058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Timeout: Second-<n> 9068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Content-Length: 0 9078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Date: xxxx 9088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 9098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Header lines must end with \r\n 9108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Per RFC 2616, content-length: is not required but connection:close 9118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * would appear to be required (given that we will be closing it!). 9128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 9138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void web_connection_parse_subscribe(struct upnp_wps_device_sm *sm, 9148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct http_request *req, 9158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const char *filename) 9168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 9178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *buf; 9188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *b; 9198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *hdr = http_request_get_hdr(req); 9208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *h; 9218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *match; 9228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int match_len; 9238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *end; 9248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int len; 9258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int got_nt = 0; 9268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 uuid[UUID_LEN]; 9278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int got_uuid = 0; 9288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *callback_urls = NULL; 9298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct subscription *s = NULL; 9308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum http_reply_code ret = HTTP_INTERNAL_SERVER_ERROR; 9318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf = wpabuf_alloc(1000); 9338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (buf == NULL) { 9348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt http_request_deinit(req); 9358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 9368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "WPS UPnP: HTTP SUBSCRIBE", 9398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) hdr, os_strlen(hdr)); 9408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Parse/validate headers */ 9428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt h = hdr; 9438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* First line: SUBSCRIBE /wps_event HTTP/1.1 9448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * has already been parsed. 9458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 9468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strcasecmp(filename, UPNP_WPS_DEVICE_EVENT_FILE) != 0) { 9478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = HTTP_PRECONDITION_FAILED; 9488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto error; 9498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS UPnP: HTTP SUBSCRIBE for event"); 9518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt end = os_strchr(h, '\n'); 9528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9537d5c8f257a74ac0d12828962a492e8b84ef83923Dmitry Shmidt while (end) { 9548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Option line by option line */ 9558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt h = end + 1; 9568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt end = os_strchr(h, '\n'); 9578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (end == NULL) 9588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; /* no unterminated lines allowed */ 9598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* NT assures that it is our type of subscription; 9611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * not used for a renewal. 9628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt **/ 9638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt match = "NT:"; 9648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt match_len = os_strlen(match); 9658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strncasecmp(h, match, match_len) == 0) { 9668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt h += match_len; 9678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (*h == ' ' || *h == '\t') 9688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt h++; 9698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt match = "upnp:event"; 9708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt match_len = os_strlen(match); 9718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strncasecmp(h, match, match_len) != 0) { 9728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = HTTP_BAD_REQUEST; 9738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto error; 9748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt got_nt = 1; 9768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt continue; 9778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* HOST should refer to us */ 9798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#if 0 9808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt match = "HOST:"; 9818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt match_len = os_strlen(match); 9828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strncasecmp(h, match, match_len) == 0) { 9838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt h += match_len; 9848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (*h == ' ' || *h == '\t') 9858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt h++; 9868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ..... 9878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif 9898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* CALLBACK gives one or more URLs for NOTIFYs 9908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * to be sent as a result of the subscription. 9918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Each URL is enclosed in angle brackets. 9928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 9938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt match = "CALLBACK:"; 9948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt match_len = os_strlen(match); 9958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strncasecmp(h, match, match_len) == 0) { 9968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt h += match_len; 9978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (*h == ' ' || *h == '\t') 9988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt h++; 9998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len = end - h; 10008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(callback_urls); 10014b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt callback_urls = dup_binstr(h, len); 10028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (callback_urls == NULL) { 10038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = HTTP_INTERNAL_SERVER_ERROR; 10048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto error; 10058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt continue; 10078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* SID is only for renewal */ 10098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt match = "SID:"; 10108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt match_len = os_strlen(match); 10118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strncasecmp(h, match, match_len) == 0) { 10128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt h += match_len; 10138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (*h == ' ' || *h == '\t') 10148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt h++; 10158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt match = "uuid:"; 10168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt match_len = os_strlen(match); 10178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strncasecmp(h, match, match_len) != 0) { 10188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = HTTP_BAD_REQUEST; 10198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto error; 10208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt h += match_len; 10228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (*h == ' ' || *h == '\t') 10238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt h++; 10248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (uuid_str2bin(h, uuid)) { 10258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = HTTP_BAD_REQUEST; 10268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto error; 10278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt got_uuid = 1; 10298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt continue; 10308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TIMEOUT is requested timeout, but apparently we can 10328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * just ignore this. 10338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 10348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (got_uuid) { 10378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* renewal */ 10388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS UPnP: Subscription renewal"); 10398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (callback_urls) { 10408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = HTTP_BAD_REQUEST; 10418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto error; 10428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt s = subscription_renew(sm, uuid); 10448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (s == NULL) { 10458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char str[80]; 10468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt uuid_bin2str(uuid, str, sizeof(str)); 10478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS UPnP: Could not find " 10488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "SID %s", str); 10498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = HTTP_PRECONDITION_FAILED; 10508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto error; 10518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (callback_urls) { 10538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS UPnP: New subscription"); 10548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!got_nt) { 10558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = HTTP_PRECONDITION_FAILED; 10568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto error; 10578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt s = subscription_start(sm, callback_urls); 10598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (s == NULL) { 10608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = HTTP_INTERNAL_SERVER_ERROR; 10618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto error; 10628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 10648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = HTTP_PRECONDITION_FAILED; 10658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto error; 10668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* success */ 10698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt http_put_reply_code(buf, HTTP_OK); 10708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_str(buf, http_server_hdr); 10718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_str(buf, http_connection_close); 10728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_str(buf, "Content-Length: 0\r\n"); 10738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_str(buf, "SID: uuid:"); 10748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* subscription id */ 10758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt b = wpabuf_put(buf, 0); 10768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt uuid_bin2str(s->uuid, b, 80); 10778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS UPnP: Assigned SID %s", b); 10788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put(buf, os_strlen(b)); 10798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_str(buf, "\r\n"); 10808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_printf(buf, "Timeout: Second-%d\r\n", UPNP_SUBSCRIBE_SEC); 10818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt http_put_date(buf); 10828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* And empty line to terminate header: */ 10838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_str(buf, "\r\n"); 10848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(callback_urls); 10868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt http_request_send_and_deinit(req, buf); 10878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 10888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidterror: 10908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Per UPnP spec: 10918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Errors 10928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Incompatible headers 10938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 400 Bad Request. If SID header and one of NT or CALLBACK headers 10948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * are present, the publisher must respond with HTTP error 10958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 400 Bad Request. 10968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Missing or invalid CALLBACK 10978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 412 Precondition Failed. If CALLBACK header is missing or does not 10988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * contain a valid HTTP URL, the publisher must respond with HTTP 10998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * error 412 Precondition Failed. 11008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Invalid NT 11018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 412 Precondition Failed. If NT header does not equal upnp:event, 11028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * the publisher must respond with HTTP error 412 Precondition 11038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Failed. 11048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * [For resubscription, use 412 if unknown uuid]. 11058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Unable to accept subscription 11068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 5xx. If a publisher is not able to accept a subscription (such as 11078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * due to insufficient resources), it must respond with a 11088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * HTTP 500-series error code. 11098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 599 Too many subscriptions (not a standard HTTP error) 11108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 11118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS UPnP: SUBSCRIBE failed - return %d", ret); 11128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt http_put_empty(buf, ret); 11138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt http_request_send_and_deinit(req, buf); 11148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(callback_urls); 11158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 11168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* Given that we have received a header w/ UNSUBSCRIBE, act upon it 11198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 11208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Format of UNSUBSCRIBE (case-insensitive): 11218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 11228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * First line must be: 11238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * UNSUBSCRIBE /wps_event HTTP/1.1 11248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 11258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Our response (if no error) which includes only required lines is: 11268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * HTTP/1.1 200 OK 11278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Content-Length: 0 11288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 11298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Header lines must end with \r\n 11308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Per RFC 2616, content-length: is not required but connection:close 11318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * would appear to be required (given that we will be closing it!). 11328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 11338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void web_connection_parse_unsubscribe(struct upnp_wps_device_sm *sm, 11348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct http_request *req, 11358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const char *filename) 11368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 11378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *buf; 11388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *hdr = http_request_get_hdr(req); 11398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *h; 11408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *match; 11418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int match_len; 11428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *end; 11438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 uuid[UUID_LEN]; 11448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int got_uuid = 0; 11458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct subscription *s = NULL; 11468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum http_reply_code ret = HTTP_INTERNAL_SERVER_ERROR; 11478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Parse/validate headers */ 11498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt h = hdr; 11508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* First line: UNSUBSCRIBE /wps_event HTTP/1.1 11518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * has already been parsed. 11528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 11538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strcasecmp(filename, UPNP_WPS_DEVICE_EVENT_FILE) != 0) { 11548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = HTTP_PRECONDITION_FAILED; 11558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto send_msg; 11568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS UPnP: HTTP UNSUBSCRIBE for event"); 11588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt end = os_strchr(h, '\n'); 11598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11607d5c8f257a74ac0d12828962a492e8b84ef83923Dmitry Shmidt while (end) { 11618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Option line by option line */ 11628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt h = end + 1; 11638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt end = os_strchr(h, '\n'); 11648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (end == NULL) 11658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; /* no unterminated lines allowed */ 11668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* HOST should refer to us */ 11688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#if 0 11698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt match = "HOST:"; 11708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt match_len = os_strlen(match); 11718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strncasecmp(h, match, match_len) == 0) { 11728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt h += match_len; 11738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (*h == ' ' || *h == '\t') 11748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt h++; 11758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ..... 11768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif 11788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt match = "SID:"; 11798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt match_len = os_strlen(match); 11808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strncasecmp(h, match, match_len) == 0) { 11818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt h += match_len; 11828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (*h == ' ' || *h == '\t') 11838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt h++; 11848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt match = "uuid:"; 11858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt match_len = os_strlen(match); 11868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strncasecmp(h, match, match_len) != 0) { 11878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = HTTP_BAD_REQUEST; 11888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto send_msg; 11898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt h += match_len; 11918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (*h == ' ' || *h == '\t') 11928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt h++; 11938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (uuid_str2bin(h, uuid)) { 11948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = HTTP_BAD_REQUEST; 11958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto send_msg; 11968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt got_uuid = 1; 11988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt continue; 11998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1200f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 1201f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt match = "NT:"; 1202f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt match_len = os_strlen(match); 1203f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (os_strncasecmp(h, match, match_len) == 0) { 1204f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt ret = HTTP_BAD_REQUEST; 1205f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt goto send_msg; 1206f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 1207f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 1208f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt match = "CALLBACK:"; 1209f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt match_len = os_strlen(match); 1210f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (os_strncasecmp(h, match, match_len) == 0) { 1211f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt ret = HTTP_BAD_REQUEST; 1212f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt goto send_msg; 1213f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 12148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (got_uuid) { 12178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt s = subscription_find(sm, uuid); 12188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (s) { 12198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct subscr_addr *sa; 12208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sa = dl_list_first(&s->addr_list, struct subscr_addr, 12218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt list); 12228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS UPnP: Unsubscribing %p %s", 12238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt s, (sa && sa->domain_and_port) ? 12248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sa->domain_and_port : "-null-"); 12258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dl_list_del(&s->list); 12268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt subscription_destroy(s); 1227f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } else { 1228f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_printf(MSG_INFO, "WPS UPnP: Could not find matching subscription to unsubscribe"); 1229f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt ret = HTTP_PRECONDITION_FAILED; 1230f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt goto send_msg; 12318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 12338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "WPS UPnP: Unsubscribe fails (not " 12348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "found)"); 12358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = HTTP_PRECONDITION_FAILED; 12368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto send_msg; 12378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = HTTP_OK; 12408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtsend_msg: 12428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf = wpabuf_alloc(200); 12438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (buf == NULL) { 12448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt http_request_deinit(req); 12458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 12468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt http_put_empty(buf, ret); 12488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt http_request_send_and_deinit(req, buf); 12498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 12508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* Send error in response to unknown requests */ 12538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void web_connection_unimplemented(struct http_request *req) 12548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 12558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *buf; 12568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf = wpabuf_alloc(200); 12578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (buf == NULL) { 12588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt http_request_deinit(req); 12598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 12608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt http_put_empty(buf, HTTP_UNIMPLEMENTED); 12628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt http_request_send_and_deinit(req, buf); 12638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 12648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* Called when we have gotten an apparently valid http request. 12688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 12698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void web_connection_check_data(void *ctx, struct http_request *req) 12708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 12718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct upnp_wps_device_sm *sm = ctx; 12728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum httpread_hdr_type htype = http_request_get_type(req); 12738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *filename = http_request_get_uri(req); 12748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct sockaddr_in *cli = http_request_get_cli_addr(req); 12758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!filename) { 12778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "WPS UPnP: Could not get HTTP URI"); 12788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt http_request_deinit(req); 12798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 12808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Trim leading slashes from filename */ 12828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (*filename == '/') 12838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt filename++; 12848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS UPnP: Got HTTP request type %d from %s:%d", 12868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt htype, inet_ntoa(cli->sin_addr), htons(cli->sin_port)); 12878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (htype) { 12898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case HTTPREAD_HDR_TYPE_GET: 12908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt web_connection_parse_get(sm, req, filename); 12918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 12928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case HTTPREAD_HDR_TYPE_POST: 12938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt web_connection_parse_post(sm, cli, req, filename); 12948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 12958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case HTTPREAD_HDR_TYPE_SUBSCRIBE: 12968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt web_connection_parse_subscribe(sm, req, filename); 12978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 12988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case HTTPREAD_HDR_TYPE_UNSUBSCRIBE: 12998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt web_connection_parse_unsubscribe(sm, req, filename); 13008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 13018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* We are not required to support M-POST; just plain 13038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * POST is supposed to work, so we only support that. 13048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * If for some reason we need to support M-POST, it is 13058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * mostly the same as POST, with small differences. 13068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 13078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 13088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Send 501 for anything else */ 13098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt web_connection_unimplemented(req); 13108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 13118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 13138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* 13168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Listening for web connections 13178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * We have a single TCP listening port, and hand off connections as we get 13188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * them. 13198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 13208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid web_listener_stop(struct upnp_wps_device_sm *sm) 13228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 13238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt http_server_deinit(sm->web_srv); 13248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->web_srv = NULL; 13258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 13268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint web_listener_start(struct upnp_wps_device_sm *sm) 13298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 13308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct in_addr addr; 13318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr.s_addr = sm->ip_addr; 13328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->web_srv = http_server_init(&addr, -1, web_connection_check_data, 13338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm); 13348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->web_srv == NULL) { 13358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt web_listener_stop(sm); 13368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 13378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->web_port = http_server_get_port(sm->web_srv); 13398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 13418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1342