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