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 */ 1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void format_wps_device_xml(struct upnp_wps_device_sm *sm, 1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *buf) 1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const char *s; 1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char uuid_string[80]; 1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct upnp_wps_device_interface *iface; 1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iface = dl_list_first(&sm->interfaces, 1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct upnp_wps_device_interface, list); 1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_str(buf, wps_device_xml_prefix); 1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Add required fields with default values if not configured. Add 1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * optional and recommended fields only if configured. 1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt s = iface->wps->friendly_name; 1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt s = ((s && *s) ? s : "WPS Access Point"); 2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt xml_add_tagged_data(buf, "friendlyName", s); 2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt s = iface->wps->dev.manufacturer; 2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt s = ((s && *s) ? s : ""); 2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt xml_add_tagged_data(buf, "manufacturer", s); 2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (iface->wps->manufacturer_url) 2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt xml_add_tagged_data(buf, "manufacturerURL", 2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iface->wps->manufacturer_url); 2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (iface->wps->model_description) 2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt xml_add_tagged_data(buf, "modelDescription", 2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iface->wps->model_description); 2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt s = iface->wps->dev.model_name; 2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt s = ((s && *s) ? s : ""); 2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt xml_add_tagged_data(buf, "modelName", s); 2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (iface->wps->dev.model_number) 2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt xml_add_tagged_data(buf, "modelNumber", 2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iface->wps->dev.model_number); 2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (iface->wps->model_url) 2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt xml_add_tagged_data(buf, "modelURL", iface->wps->model_url); 2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (iface->wps->dev.serial_number) 2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt xml_add_tagged_data(buf, "serialNumber", 2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iface->wps->dev.serial_number); 2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt uuid_bin2str(iface->wps->uuid, uuid_string, sizeof(uuid_string)); 2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt s = uuid_string; 2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Need "uuid:" prefix, thus we can't use xml_add_tagged_data() 2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * easily... 2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_str(buf, "<UDN>uuid:"); 2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt xml_data_encode(buf, s, os_strlen(s)); 2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_str(buf, "</UDN>\n"); 2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (iface->wps->upc) 2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt xml_add_tagged_data(buf, "UPC", iface->wps->upc); 2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_str(buf, wps_device_xml_postfix); 2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void http_put_reply_code(struct wpabuf *buf, enum http_reply_code code) 2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_str(buf, "HTTP/1.1 "); 2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (code) { 2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case HTTP_OK: 2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_str(buf, "200 OK\r\n"); 2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case HTTP_BAD_REQUEST: 2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_str(buf, "400 Bad request\r\n"); 2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case HTTP_PRECONDITION_FAILED: 2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_str(buf, "412 Precondition failed\r\n"); 2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case HTTP_UNIMPLEMENTED: 2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_str(buf, "501 Unimplemented\r\n"); 2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case HTTP_INTERNAL_SERVER_ERROR: 2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_str(buf, "500 Internal server error\r\n"); 2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void http_put_date(struct wpabuf *buf) 2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_str(buf, "Date: "); 2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt format_date(buf); 2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_str(buf, "\r\n"); 2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void http_put_empty(struct wpabuf *buf, enum http_reply_code code) 2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt http_put_reply_code(buf, code); 2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_str(buf, http_server_hdr); 2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_str(buf, http_connection_close); 2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_str(buf, "Content-Length: 0\r\n" 2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "\r\n"); 2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* Given that we have received a header w/ GET, act upon it 2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Format of GET (case-insensitive): 2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * First line must be: 2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * GET /<file> HTTP/1.1 2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Since we don't do anything fancy we just ignore other lines. 2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Our response (if no error) which includes only required lines is: 2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * HTTP/1.1 200 OK 2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Connection: close 2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Content-Type: text/xml 2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Date: <rfc1123-date> 3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Header lines must end with \r\n 3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Per RFC 2616, content-length: is not required but connection:close 3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * would appear to be required (given that we will be closing it!). 3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void web_connection_parse_get(struct upnp_wps_device_sm *sm, 3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct http_request *hreq, char *filename) 3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *buf; /* output buffer, allocated */ 3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *put_length_here; 3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *body_start; 3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum { 3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt GET_DEVICE_XML_FILE, 3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt GET_SCPD_XML_FILE 3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } req; 3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t extra_len = 0; 3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int body_length; 3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char len_buf[10]; 3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct upnp_wps_device_interface *iface; 3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iface = dl_list_first(&sm->interfaces, 3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct upnp_wps_device_interface, list); 3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * It is not required that filenames be case insensitive but it is 3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * allowed and cannot hurt here. 3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (filename == NULL) 3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt filename = "(null)"; /* just in case */ 3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strcasecmp(filename, UPNP_WPS_DEVICE_XML_FILE) == 0) { 3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS UPnP: HTTP GET for device XML"); 3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt req = GET_DEVICE_XML_FILE; 3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt extra_len = 3000; 3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (iface->wps->friendly_name) 3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt extra_len += os_strlen(iface->wps->friendly_name); 3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (iface->wps->manufacturer_url) 3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt extra_len += os_strlen(iface->wps->manufacturer_url); 3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (iface->wps->model_description) 3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt extra_len += os_strlen(iface->wps->model_description); 3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (iface->wps->model_url) 3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt extra_len += os_strlen(iface->wps->model_url); 3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (iface->wps->upc) 3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt extra_len += os_strlen(iface->wps->upc); 3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (!os_strcasecmp(filename, UPNP_WPS_SCPD_XML_FILE)) { 3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS UPnP: HTTP GET for SCPD XML"); 3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt req = GET_SCPD_XML_FILE; 3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt extra_len = os_strlen(wps_scpd_xml); 3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* File not found */ 3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS UPnP: HTTP GET file not found: %s", 3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt filename); 3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf = wpabuf_alloc(200); 3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (buf == NULL) { 3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt http_request_deinit(hreq); 3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_str(buf, 3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "HTTP/1.1 404 Not Found\r\n" 3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Connection: close\r\n"); 3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt http_put_date(buf); 3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* terminating empty line */ 3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_str(buf, "\r\n"); 3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto send_buf; 3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf = wpabuf_alloc(1000 + extra_len); 3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (buf == NULL) { 3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt http_request_deinit(hreq); 3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_str(buf, 3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "HTTP/1.1 200 OK\r\n" 3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Content-Type: text/xml; charset=\"utf-8\"\r\n"); 3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_str(buf, "Server: Unspecified, UPnP/1.0, Unspecified\r\n"); 3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_str(buf, "Connection: close\r\n"); 3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_str(buf, "Content-Length: "); 3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * We will paste the length in later, leaving some extra whitespace. 3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * HTTP code is supposed to be tolerant of extra whitespace. 3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt put_length_here = wpabuf_put(buf, 0); 3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_str(buf, " \r\n"); 3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt http_put_date(buf); 3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* terminating empty line */ 3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_str(buf, "\r\n"); 3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt body_start = wpabuf_put(buf, 0); 3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (req) { 3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case GET_DEVICE_XML_FILE: 3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt format_wps_device_xml(sm, buf); 3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case GET_SCPD_XML_FILE: 3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_str(buf, wps_scpd_xml); 4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Now patch in the content length at the end */ 4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt body_length = (char *) wpabuf_put(buf, 0) - body_start; 4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_snprintf(len_buf, 10, "%d", body_length); 4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(put_length_here, len_buf, os_strlen(len_buf)); 4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtsend_buf: 4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt http_request_send_and_deinit(hreq, buf); 4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic enum http_reply_code 4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtweb_process_get_device_info(struct upnp_wps_device_sm *sm, 4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf **reply, const char **replyname) 4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt static const char *name = "NewDeviceInfo"; 4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wps_config cfg; 4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct upnp_wps_device_interface *iface; 4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct upnp_wps_peer *peer; 4218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iface = dl_list_first(&sm->interfaces, 4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct upnp_wps_device_interface, list); 4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer = &iface->peer; 4258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS UPnP: GetDeviceInfo"); 4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (iface->ctx->ap_pin == NULL) 4298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return HTTP_INTERNAL_SERVER_ERROR; 4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry 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); 4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * PutMessage is used by external UPnP-based Registrar to perform WPS 4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * operation with the access point itself; as compared with 4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * PutWLANResponse which is for proxying. 4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 4848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS UPnP: PutMessage"); 4858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = xml_get_base64_item(data, "NewInMessage", &ret); 4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (msg == NULL) 4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = wps_process_msg(iface->peer.wps, WSC_UPnP, msg); 4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res == WPS_FAILURE) 4908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *reply = NULL; 4918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *reply = wps_get_msg(iface->peer.wps, &op_code); 4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(msg); 4948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (*reply == NULL) 4958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return HTTP_INTERNAL_SERVER_ERROR; 4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *replyname = name; 4978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return HTTP_OK; 4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic enum http_reply_code 5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtweb_process_put_wlan_response(struct upnp_wps_device_sm *sm, char *data, 5038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf **reply, const char **replyname) 5048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *msg; 5068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum http_reply_code ret; 5078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 macaddr[ETH_ALEN]; 5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ev_type; 5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int type; 5108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *val; 5118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct upnp_wps_device_interface *iface; 5128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ok = 0; 5138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 5158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * External UPnP-based Registrar is passing us a message to be proxied 5168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * over to a Wi-Fi -based client of ours. 5178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 5188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS UPnP: PutWLANResponse"); 5208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = xml_get_base64_item(data, "NewMessage", &ret); 5218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (msg == NULL) { 5228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS UPnP: Could not extract NewMessage " 5238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "from PutWLANResponse"); 5248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 5258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt val = xml_get_first_item(data, "NewWLANEventType"); 5278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (val == NULL) { 5288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS UPnP: No NewWLANEventType in " 5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "PutWLANResponse"); 5308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(msg); 5318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return UPNP_ARG_VALUE_INVALID; 5328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ev_type = atol(val); 5348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(val); 5358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt val = xml_get_first_item(data, "NewWLANEventMAC"); 5368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (val == NULL) { 5378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS UPnP: No NewWLANEventMAC in " 5388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "PutWLANResponse"); 5398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(msg); 5408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return UPNP_ARG_VALUE_INVALID; 5418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hwaddr_aton(val, macaddr)) { 5438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS UPnP: Invalid NewWLANEventMAC in " 5448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "PutWLANResponse: '%s'", val); 5458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_WPS_STRICT 5468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt { 5478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wps_parse_attr attr; 5488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wps_parse_msg(msg, &attr) < 0 || attr.version2) { 5498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(msg); 5508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(val); 5518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return UPNP_ARG_VALUE_INVALID; 5528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_WPS_STRICT */ 5558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hwaddr_aton2(val, macaddr) > 0) { 5568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 5578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * At least some versions of Intel PROset seem to be 5588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * using dot-deliminated MAC address format here. 5598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 5608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS UPnP: Workaround - allow " 5618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "incorrect MAC address format in " 5628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "NewWLANEventMAC: %s -> " MACSTR, 5638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt val, MAC2STR(macaddr)); 5648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 5658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(msg); 5668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(val); 5678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return UPNP_ARG_VALUE_INVALID; 5688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(val); 5718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ev_type == UPNP_WPS_WLANEVENT_TYPE_EAP) { 5728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wps_parse_attr attr; 5738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wps_parse_msg(msg, &attr) < 0 || 5748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt attr.msg_type == NULL) 5758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt type = -1; 5768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 5778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt type = *attr.msg_type; 5788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS UPnP: Message Type %d", type); 5798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else 5808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt type = -1; 5818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dl_list_for_each(iface, &sm->interfaces, 5828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct upnp_wps_device_interface, list) { 5838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (iface->ctx->rx_req_put_wlan_response && 5848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iface->ctx->rx_req_put_wlan_response(iface->priv, ev_type, 5858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt macaddr, msg, type) 5868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt == 0) 5878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ok = 1; 5888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!ok) { 5918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "WPS UPnP: Fail: sm->ctx->" 5928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "rx_req_put_wlan_response"); 5938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(msg); 5948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return HTTP_INTERNAL_SERVER_ERROR; 5958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(msg); 5978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *replyname = NULL; 5988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *reply = NULL; 5998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return HTTP_OK; 6008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int find_er_addr(struct subscription *s, struct sockaddr_in *cli) 6048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct subscr_addr *a; 6068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dl_list_for_each(a, &s->addr_list, struct subscr_addr, list) { 6088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (cli->sin_addr.s_addr == a->saddr.sin_addr.s_addr) 6098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 1; 6108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 6128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct subscription * find_er(struct upnp_wps_device_sm *sm, 6168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct sockaddr_in *cli) 6178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct subscription *s; 6198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dl_list_for_each(s, &sm->subscriptions, struct subscription, list) 6208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (find_er_addr(s, cli)) 6218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return s; 6228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 6238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic enum http_reply_code 6278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtweb_process_set_selected_registrar(struct upnp_wps_device_sm *sm, 6288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct sockaddr_in *cli, char *data, 6298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf **reply, 6308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const char **replyname) 6318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *msg; 6338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum http_reply_code ret; 6348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct subscription *s; 6358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct upnp_wps_device_interface *iface; 6368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int err = 0; 6378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS UPnP: SetSelectedRegistrar"); 6398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt s = find_er(sm, cli); 6408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (s == NULL) { 6418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS UPnP: Ignore SetSelectedRegistrar " 6428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "from unknown ER"); 6438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return UPNP_ACTION_FAILED; 6448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = xml_get_base64_item(data, "NewMessage", &ret); 6468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (msg == NULL) 6478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 6488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dl_list_for_each(iface, &sm->interfaces, 6498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct upnp_wps_device_interface, list) { 6508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (upnp_er_set_selected_registrar(iface->wps->registrar, s, 6518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg)) 6528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt err = 1; 6538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(msg); 6558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (err) 6568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return HTTP_INTERNAL_SERVER_ERROR; 6578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *replyname = NULL; 6588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *reply = NULL; 6598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return HTTP_OK; 6608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const char *soap_prefix = 6648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "<?xml version=\"1.0\"?>\n" 6658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" " 6668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">\n" 6678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "<s:Body>\n"; 6688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const char *soap_postfix = 6698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "</s:Body>\n</s:Envelope>\n"; 6708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const char *soap_error_prefix = 6728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "<s:Fault>\n" 6738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "<faultcode>s:Client</faultcode>\n" 6748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "<faultstring>UPnPError</faultstring>\n" 6758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "<detail>\n" 6768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "<UPnPError xmlns=\"urn:schemas-upnp-org:control-1-0\">\n"; 6778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const char *soap_error_postfix = 6788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "<errorDescription>Error</errorDescription>\n" 6798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "</UPnPError>\n" 6808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "</detail>\n" 6818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "</s:Fault>\n"; 6828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void web_connection_send_reply(struct http_request *req, 6848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum http_reply_code ret, 6858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const char *action, int action_len, 6868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpabuf *reply, 6878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const char *replyname) 6888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *buf; 6908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *replydata; 6918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *put_length_here = NULL; 6928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *body_start = NULL; 6938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (reply) { 6958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len; 6968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt replydata = (char *) base64_encode(wpabuf_head(reply), 6978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_len(reply), &len); 6988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else 6998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt replydata = NULL; 7008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Parameters of the response: 7028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * action(action_len) -- action we are responding to 7038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * replyname -- a name we need for the reply 7048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * replydata -- NULL or null-terminated string 7058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 7068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf = wpabuf_alloc(1000 + (replydata ? os_strlen(replydata) : 0U) + 7078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (action_len > 0 ? action_len * 2 : 0)); 7088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (buf == NULL) { 7098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "WPS UPnP: Cannot allocate reply to " 7108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "POST"); 7118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(replydata); 7128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt http_request_deinit(req); 7138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 7148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 7178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Assuming we will be successful, put in the output header first. 7188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Note: we do not keep connections alive (and httpread does 7198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * not support it)... therefore we must have Connection: close. 7208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 7218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret == HTTP_OK) { 7228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_str(buf, 7238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "HTTP/1.1 200 OK\r\n" 7248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Content-Type: text/xml; " 7258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "charset=\"utf-8\"\r\n"); 7268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 7278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_printf(buf, "HTTP/1.1 %d Error\r\n", ret); 7288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_str(buf, http_connection_close); 7308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_str(buf, "Content-Length: "); 7328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 7338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * We will paste the length in later, leaving some extra whitespace. 7348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * HTTP code is supposed to be tolerant of extra whitespace. 7358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 7368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt put_length_here = wpabuf_put(buf, 0); 7378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_str(buf, " \r\n"); 7388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt http_put_date(buf); 7408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* terminating empty line */ 7428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_str(buf, "\r\n"); 7438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt body_start = wpabuf_put(buf, 0); 7458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret == HTTP_OK) { 7478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_str(buf, soap_prefix); 7488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_str(buf, "<u:"); 7498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_data(buf, action, action_len); 7508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_str(buf, "Response xmlns:u=\""); 7518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_str(buf, urn_wfawlanconfig); 7528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_str(buf, "\">\n"); 7538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (replydata && replyname) { 7548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: might possibly need to escape part of reply 7558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * data? ... 7568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * probably not, unlikely to have ampersand(&) or left 7578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * angle bracket (<) in it... 7588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 7598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_printf(buf, "<%s>", replyname); 7608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_str(buf, replydata); 7618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_printf(buf, "</%s>\n", replyname); 7628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_str(buf, "</u:"); 7648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_data(buf, action, action_len); 7658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_str(buf, "Response>\n"); 7668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_str(buf, soap_postfix); 7678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 7688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Error case */ 7698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_str(buf, soap_prefix); 7708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_str(buf, soap_error_prefix); 7718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_printf(buf, "<errorCode>%d</errorCode>\n", ret); 7728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_str(buf, soap_error_postfix); 7738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_str(buf, soap_postfix); 7748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(replydata); 7768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Now patch in the content length at the end */ 7788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (body_start && put_length_here) { 7798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int body_length = (char *) wpabuf_put(buf, 0) - body_start; 7808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char len_buf[10]; 7818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_snprintf(len_buf, sizeof(len_buf), "%d", body_length); 7828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(put_length_here, len_buf, os_strlen(len_buf)); 7838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt http_request_send_and_deinit(req, buf); 7868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const char * web_get_action(struct http_request *req, 7908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t *action_len) 7918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const char *match; 7938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int match_len; 7948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *b; 7958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *action; 7968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *action_len = 0; 7988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* The SOAPAction line of the header tells us what we want to do */ 7998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt b = http_request_get_hdr_line(req, "SOAPAction:"); 8008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (b == NULL) 8018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 8028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (*b == '"') 8038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt b++; 8048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 8058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 8068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt match = urn_wfawlanconfig; 8078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt match_len = os_strlen(urn_wfawlanconfig) - 1; 8088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strncasecmp(b, match, match_len)) 8098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 8108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt b += match_len; 8118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* skip over version */ 8128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (isgraph(*b) && *b != '#') 8138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt b++; 8148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (*b != '#') 8158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 8168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt b++; 8178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Following the sharp(#) should be the action and a double quote */ 8188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt action = b; 8198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (isgraph(*b) && *b != '"') 8208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt b++; 8218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (*b != '"') 8228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 8238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *action_len = b - action; 8248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return action; 8258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 8268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* Given that we have received a header w/ POST, act upon it 8298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 8308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Format of POST (case-insensitive): 8318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 8328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * First line must be: 8338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * POST /<file> HTTP/1.1 8348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Since we don't do anything fancy we just ignore other lines. 8358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 8368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Our response (if no error) which includes only required lines is: 8378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * HTTP/1.1 200 OK 8388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Connection: close 8398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Content-Type: text/xml 8408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Date: <rfc1123-date> 8418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 8428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Header lines must end with \r\n 8438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Per RFC 2616, content-length: is not required but connection:close 8448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * would appear to be required (given that we will be closing it!). 8458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 8468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void web_connection_parse_post(struct upnp_wps_device_sm *sm, 8478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct sockaddr_in *cli, 8488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct http_request *req, 8498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const char *filename) 8508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 8518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum http_reply_code ret; 8528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *data = http_request_get_data(req); /* body of http msg */ 8538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const char *action = NULL; 8548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t action_len = 0; 8558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const char *replyname = NULL; /* argument name for the reply */ 8568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *reply = NULL; /* data for the reply */ 8578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strcasecmp(filename, UPNP_WPS_DEVICE_CONTROL_FILE)) { 8598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "WPS UPnP: Invalid POST filename %s", 8608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt filename); 8618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = HTTP_NOT_FOUND; 8628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto bad; 8638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = UPNP_INVALID_ACTION; 8668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt action = web_get_action(req, &action_len); 8678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (action == NULL) 8688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto bad; 8698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!os_strncasecmp("GetDeviceInfo", action, action_len)) 8718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = web_process_get_device_info(sm, &reply, &replyname); 8728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (!os_strncasecmp("PutMessage", action, action_len)) 8738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = web_process_put_message(sm, data, &reply, &replyname); 8748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (!os_strncasecmp("PutWLANResponse", action, action_len)) 8758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = web_process_put_wlan_response(sm, data, &reply, 8768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &replyname); 8778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (!os_strncasecmp("SetSelectedRegistrar", action, action_len)) 8788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = web_process_set_selected_registrar(sm, cli, data, &reply, 8798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &replyname); 8808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 8818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "WPS UPnP: Unknown POST type"); 8828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtbad: 8848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret != HTTP_OK) 8858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "WPS UPnP: POST failure ret=%d", ret); 8868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt web_connection_send_reply(req, ret, action, action_len, reply, 8878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt replyname); 8888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(reply); 8898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 8908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* Given that we have received a header w/ SUBSCRIBE, act upon it 8938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 8948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Format of SUBSCRIBE (case-insensitive): 8958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 8968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * First line must be: 8978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * SUBSCRIBE /wps_event HTTP/1.1 8988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 8998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Our response (if no error) which includes only required lines is: 9008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * HTTP/1.1 200 OK 9018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Server: xx, UPnP/1.0, xx 9028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * SID: uuid:xxxxxxxxx 9038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Timeout: Second-<n> 9048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Content-Length: 0 9058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Date: xxxx 9068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 9078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Header lines must end with \r\n 9088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Per RFC 2616, content-length: is not required but connection:close 9098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * would appear to be required (given that we will be closing it!). 9108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 9118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void web_connection_parse_subscribe(struct upnp_wps_device_sm *sm, 9128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct http_request *req, 9138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const char *filename) 9148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 9158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *buf; 9168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *b; 9178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *hdr = http_request_get_hdr(req); 9188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *h; 9198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *match; 9208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int match_len; 9218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *end; 9228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int len; 9238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int got_nt = 0; 9248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 uuid[UUID_LEN]; 9258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int got_uuid = 0; 9268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *callback_urls = NULL; 9278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct subscription *s = NULL; 9288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum http_reply_code ret = HTTP_INTERNAL_SERVER_ERROR; 9298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf = wpabuf_alloc(1000); 9318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (buf == NULL) { 9328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt http_request_deinit(req); 9338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 9348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "WPS UPnP: HTTP SUBSCRIBE", 9378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) hdr, os_strlen(hdr)); 9388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Parse/validate headers */ 9408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt h = hdr; 9418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* First line: SUBSCRIBE /wps_event HTTP/1.1 9428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * has already been parsed. 9438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 9448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strcasecmp(filename, UPNP_WPS_DEVICE_EVENT_FILE) != 0) { 9458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = HTTP_PRECONDITION_FAILED; 9468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto error; 9478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS UPnP: HTTP SUBSCRIBE for event"); 9498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt end = os_strchr(h, '\n'); 9508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (; end != NULL; h = end + 1) { 9528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Option line by option line */ 9538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt h = end + 1; 9548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt end = os_strchr(h, '\n'); 9558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (end == NULL) 9568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; /* no unterminated lines allowed */ 9578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* NT assures that it is our type of subscription; 9591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * not used for a renewal. 9608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt **/ 9618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt match = "NT:"; 9628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt match_len = os_strlen(match); 9638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strncasecmp(h, match, match_len) == 0) { 9648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt h += match_len; 9658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (*h == ' ' || *h == '\t') 9668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt h++; 9678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt match = "upnp:event"; 9688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt match_len = os_strlen(match); 9698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strncasecmp(h, match, match_len) != 0) { 9708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = HTTP_BAD_REQUEST; 9718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto error; 9728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt got_nt = 1; 9748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt continue; 9758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* HOST should refer to us */ 9778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#if 0 9788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt match = "HOST:"; 9798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt match_len = os_strlen(match); 9808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strncasecmp(h, match, match_len) == 0) { 9818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt h += match_len; 9828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (*h == ' ' || *h == '\t') 9838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt h++; 9848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ..... 9858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif 9878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* CALLBACK gives one or more URLs for NOTIFYs 9888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * to be sent as a result of the subscription. 9898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Each URL is enclosed in angle brackets. 9908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 9918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt match = "CALLBACK:"; 9928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt match_len = os_strlen(match); 9938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strncasecmp(h, match, match_len) == 0) { 9948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt h += match_len; 9958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (*h == ' ' || *h == '\t') 9968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt h++; 9978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len = end - h; 9988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(callback_urls); 9994b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt callback_urls = dup_binstr(h, len); 10008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (callback_urls == NULL) { 10018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = HTTP_INTERNAL_SERVER_ERROR; 10028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto error; 10038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt continue; 10058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* SID is only for renewal */ 10078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt match = "SID:"; 10088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt match_len = os_strlen(match); 10098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strncasecmp(h, match, match_len) == 0) { 10108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt h += match_len; 10118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (*h == ' ' || *h == '\t') 10128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt h++; 10138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt match = "uuid:"; 10148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt match_len = os_strlen(match); 10158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strncasecmp(h, match, match_len) != 0) { 10168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = HTTP_BAD_REQUEST; 10178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto error; 10188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt h += match_len; 10208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (*h == ' ' || *h == '\t') 10218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt h++; 10228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (uuid_str2bin(h, uuid)) { 10238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = HTTP_BAD_REQUEST; 10248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto error; 10258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt got_uuid = 1; 10278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt continue; 10288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TIMEOUT is requested timeout, but apparently we can 10308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * just ignore this. 10318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 10328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (got_uuid) { 10358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* renewal */ 10368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS UPnP: Subscription renewal"); 10378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (callback_urls) { 10388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = HTTP_BAD_REQUEST; 10398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto error; 10408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt s = subscription_renew(sm, uuid); 10428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (s == NULL) { 10438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char str[80]; 10448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt uuid_bin2str(uuid, str, sizeof(str)); 10458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS UPnP: Could not find " 10468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "SID %s", str); 10478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = HTTP_PRECONDITION_FAILED; 10488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto error; 10498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (callback_urls) { 10518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS UPnP: New subscription"); 10528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!got_nt) { 10538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = HTTP_PRECONDITION_FAILED; 10548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto error; 10558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt s = subscription_start(sm, callback_urls); 10578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (s == NULL) { 10588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = HTTP_INTERNAL_SERVER_ERROR; 10598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto error; 10608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 10628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = HTTP_PRECONDITION_FAILED; 10638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto error; 10648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* success */ 10678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt http_put_reply_code(buf, HTTP_OK); 10688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_str(buf, http_server_hdr); 10698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_str(buf, http_connection_close); 10708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_str(buf, "Content-Length: 0\r\n"); 10718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_str(buf, "SID: uuid:"); 10728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* subscription id */ 10738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt b = wpabuf_put(buf, 0); 10748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt uuid_bin2str(s->uuid, b, 80); 10758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS UPnP: Assigned SID %s", b); 10768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put(buf, os_strlen(b)); 10778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_str(buf, "\r\n"); 10788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_printf(buf, "Timeout: Second-%d\r\n", UPNP_SUBSCRIBE_SEC); 10798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt http_put_date(buf); 10808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* And empty line to terminate header: */ 10818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_str(buf, "\r\n"); 10828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(callback_urls); 10848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt http_request_send_and_deinit(req, buf); 10858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 10868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidterror: 10888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Per UPnP spec: 10898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Errors 10908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Incompatible headers 10918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 400 Bad Request. If SID header and one of NT or CALLBACK headers 10928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * are present, the publisher must respond with HTTP error 10938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 400 Bad Request. 10948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Missing or invalid CALLBACK 10958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 412 Precondition Failed. If CALLBACK header is missing or does not 10968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * contain a valid HTTP URL, the publisher must respond with HTTP 10978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * error 412 Precondition Failed. 10988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Invalid NT 10998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 412 Precondition Failed. If NT header does not equal upnp:event, 11008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * the publisher must respond with HTTP error 412 Precondition 11018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Failed. 11028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * [For resubscription, use 412 if unknown uuid]. 11038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Unable to accept subscription 11048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 5xx. If a publisher is not able to accept a subscription (such as 11058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * due to insufficient resources), it must respond with a 11068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * HTTP 500-series error code. 11078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 599 Too many subscriptions (not a standard HTTP error) 11088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 11098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS UPnP: SUBSCRIBE failed - return %d", ret); 11108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt http_put_empty(buf, ret); 11118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt http_request_send_and_deinit(req, buf); 11128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(callback_urls); 11138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 11148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* Given that we have received a header w/ UNSUBSCRIBE, act upon it 11178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 11188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Format of UNSUBSCRIBE (case-insensitive): 11198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 11208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * First line must be: 11218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * UNSUBSCRIBE /wps_event HTTP/1.1 11228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 11238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Our response (if no error) which includes only required lines is: 11248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * HTTP/1.1 200 OK 11258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Content-Length: 0 11268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 11278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Header lines must end with \r\n 11288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Per RFC 2616, content-length: is not required but connection:close 11298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * would appear to be required (given that we will be closing it!). 11308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 11318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void web_connection_parse_unsubscribe(struct upnp_wps_device_sm *sm, 11328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct http_request *req, 11338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const char *filename) 11348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 11358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *buf; 11368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *hdr = http_request_get_hdr(req); 11378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *h; 11388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *match; 11398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int match_len; 11408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *end; 11418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 uuid[UUID_LEN]; 11428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int got_uuid = 0; 11438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct subscription *s = NULL; 11448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum http_reply_code ret = HTTP_INTERNAL_SERVER_ERROR; 11458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Parse/validate headers */ 11478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt h = hdr; 11488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* First line: UNSUBSCRIBE /wps_event HTTP/1.1 11498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * has already been parsed. 11508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 11518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strcasecmp(filename, UPNP_WPS_DEVICE_EVENT_FILE) != 0) { 11528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = HTTP_PRECONDITION_FAILED; 11538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto send_msg; 11548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS UPnP: HTTP UNSUBSCRIBE for event"); 11568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt end = os_strchr(h, '\n'); 11578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (; end != NULL; h = end + 1) { 11598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Option line by option line */ 11608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt h = end + 1; 11618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt end = os_strchr(h, '\n'); 11628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (end == NULL) 11638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; /* no unterminated lines allowed */ 11648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* HOST should refer to us */ 11668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#if 0 11678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt match = "HOST:"; 11688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt match_len = os_strlen(match); 11698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strncasecmp(h, match, match_len) == 0) { 11708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt h += match_len; 11718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (*h == ' ' || *h == '\t') 11728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt h++; 11738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ..... 11748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif 11768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* SID is only for renewal */ 11778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt match = "SID:"; 11788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt match_len = os_strlen(match); 11798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strncasecmp(h, match, match_len) == 0) { 11808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt h += match_len; 11818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (*h == ' ' || *h == '\t') 11828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt h++; 11838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt match = "uuid:"; 11848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt match_len = os_strlen(match); 11858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strncasecmp(h, match, match_len) != 0) { 11868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = HTTP_BAD_REQUEST; 11878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto send_msg; 11888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt h += match_len; 11908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (*h == ' ' || *h == '\t') 11918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt h++; 11928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (uuid_str2bin(h, uuid)) { 11938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = HTTP_BAD_REQUEST; 11948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto send_msg; 11958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt got_uuid = 1; 11978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt continue; 11988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (got_uuid) { 12028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt s = subscription_find(sm, uuid); 12038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (s) { 12048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct subscr_addr *sa; 12058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sa = dl_list_first(&s->addr_list, struct subscr_addr, 12068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt list); 12078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS UPnP: Unsubscribing %p %s", 12088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt s, (sa && sa->domain_and_port) ? 12098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sa->domain_and_port : "-null-"); 12108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dl_list_del(&s->list); 12118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt subscription_destroy(s); 12128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 12148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "WPS UPnP: Unsubscribe fails (not " 12158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "found)"); 12168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = HTTP_PRECONDITION_FAILED; 12178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto send_msg; 12188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = HTTP_OK; 12218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtsend_msg: 12238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf = wpabuf_alloc(200); 12248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (buf == NULL) { 12258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt http_request_deinit(req); 12268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 12278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt http_put_empty(buf, ret); 12298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt http_request_send_and_deinit(req, buf); 12308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 12318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* Send error in response to unknown requests */ 12348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void web_connection_unimplemented(struct http_request *req) 12358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 12368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *buf; 12378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf = wpabuf_alloc(200); 12388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (buf == NULL) { 12398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt http_request_deinit(req); 12408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 12418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt http_put_empty(buf, HTTP_UNIMPLEMENTED); 12438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt http_request_send_and_deinit(req, buf); 12448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 12458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* Called when we have gotten an apparently valid http request. 12498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 12508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void web_connection_check_data(void *ctx, struct http_request *req) 12518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 12528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct upnp_wps_device_sm *sm = ctx; 12538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum httpread_hdr_type htype = http_request_get_type(req); 12548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *filename = http_request_get_uri(req); 12558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct sockaddr_in *cli = http_request_get_cli_addr(req); 12568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!filename) { 12588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "WPS UPnP: Could not get HTTP URI"); 12598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt http_request_deinit(req); 12608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 12618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Trim leading slashes from filename */ 12638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (*filename == '/') 12648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt filename++; 12658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS UPnP: Got HTTP request type %d from %s:%d", 12678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt htype, inet_ntoa(cli->sin_addr), htons(cli->sin_port)); 12688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (htype) { 12708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case HTTPREAD_HDR_TYPE_GET: 12718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt web_connection_parse_get(sm, req, filename); 12728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 12738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case HTTPREAD_HDR_TYPE_POST: 12748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt web_connection_parse_post(sm, cli, req, filename); 12758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 12768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case HTTPREAD_HDR_TYPE_SUBSCRIBE: 12778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt web_connection_parse_subscribe(sm, req, filename); 12788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 12798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case HTTPREAD_HDR_TYPE_UNSUBSCRIBE: 12808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt web_connection_parse_unsubscribe(sm, req, filename); 12818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 12828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* We are not required to support M-POST; just plain 12848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * POST is supposed to work, so we only support that. 12858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * If for some reason we need to support M-POST, it is 12868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * mostly the same as POST, with small differences. 12878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 12888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 12898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Send 501 for anything else */ 12908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt web_connection_unimplemented(req); 12918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 12928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 12948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* 12978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Listening for web connections 12988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * We have a single TCP listening port, and hand off connections as we get 12998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * them. 13008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 13018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid web_listener_stop(struct upnp_wps_device_sm *sm) 13038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 13048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt http_server_deinit(sm->web_srv); 13058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->web_srv = NULL; 13068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 13078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint web_listener_start(struct upnp_wps_device_sm *sm) 13108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 13118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct in_addr addr; 13128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr.s_addr = sm->ip_addr; 13138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->web_srv = http_server_init(&addr, -1, web_connection_check_data, 13148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm); 13158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->web_srv == NULL) { 13168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt web_listener_stop(sm); 13178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 13188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->web_port = http_server_get_port(sm->web_srv); 13208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 13228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1323