~ubuntu-branches/ubuntu/saucy/wpasupplicant/saucy

« back to all changes in this revision

Viewing changes to src/wps/wps_upnp_web.c

  • Committer: Bazaar Package Importer
  • Author(s): Mathieu Trudel-Lapierre
  • Date: 2010-11-22 09:43:43 UTC
  • mfrom: (1.1.16 upstream)
  • Revision ID: james.westby@ubuntu.com-20101122094343-qgsxaojvmswfri77
Tags: 0.7.3-0ubuntu1
* Get wpasupplicant 0.7.3 from Debian's SVN. Leaving 0.7.3-1 as unreleased
  for now.
* Build-Depend on debhelper 8, since the packaging from Debian uses compat 8.

Show diffs side-by-side

added added

removed removed

Lines of Context:
9
9
 */
10
10
 
11
11
#include "includes.h"
12
 
#include <fcntl.h>
13
12
 
14
13
#include "common.h"
15
14
#include "base64.h"
16
 
#include "eloop.h"
17
15
#include "uuid.h"
18
16
#include "httpread.h"
 
17
#include "http_server.h"
19
18
#include "wps_i.h"
20
19
#include "wps_upnp.h"
21
20
#include "wps_upnp_i.h"
 
21
#include "upnp_xml.h"
22
22
 
23
23
/***************************************************************************
24
24
 * Web connections (we serve pages of info about ourselves, handle
38
38
        "Connection: close\r\n";
39
39
 
40
40
/*
41
 
 * Incoming web connections are recorded in this struct.
42
 
 * A web connection is a TCP connection to us, the server;
43
 
 * it is called a "web connection" because we use http and serve
44
 
 * data that looks like web pages.
45
 
 * State information is need to track the connection until we figure
46
 
 * out what they want and what we want to do about it.
47
 
 */
48
 
struct web_connection {
49
 
        /* double linked list */
50
 
        struct web_connection *next;
51
 
        struct web_connection *prev;
52
 
        struct upnp_wps_device_sm *sm; /* parent */
53
 
        int sd; /* socket to read from */
54
 
        struct sockaddr_in cli_addr;
55
 
        int sd_registered; /* nonzero if we must cancel registration */
56
 
        struct httpread *hread; /* state machine for reading socket */
57
 
        int n_rcvd_data; /* how much data read so far */
58
 
        int done; /* internal flag, set when we've finished */
59
 
};
60
 
 
61
 
 
62
 
/*
63
 
 * XML parsing and formatting
64
 
 *
65
 
 * XML is a markup language based on unicode; usually (and in our case,
66
 
 * always!) based on utf-8. utf-8 uses a variable number of bytes per
67
 
 * character. utf-8 has the advantage that all non-ASCII unicode characters are
68
 
 * represented by sequences of non-ascii (high bit set) bytes, whereas ASCII
69
 
 * characters are single ascii bytes, thus we can use typical text processing.
70
 
 *
71
 
 * (One other interesting thing about utf-8 is that it is possible to look at
72
 
 * any random byte and determine if it is the first byte of a character as
73
 
 * versus a continuation byte).
74
 
 *
75
 
 * The base syntax of XML uses a few ASCII punctionation characters; any
76
 
 * characters that would appear in the payload data are rewritten using
77
 
 * sequences, e.g., &amp; for ampersand(&) and &lt for left angle bracket (<).
78
 
 * Five such escapes total (more can be defined but that does not apply to our
79
 
 * case). Thus we can safely parse for angle brackets etc.
80
 
 *
81
 
 * XML describes tree structures of tagged data, with each element beginning
82
 
 * with an opening tag <label> and ending with a closing tag </label> with
83
 
 * matching label. (There is also a self-closing tag <label/> which is supposed
84
 
 * to be equivalent to <label></label>, i.e., no payload, but we are unlikely
85
 
 * to see it for our purpose).
86
 
 *
87
 
 * Actually the opening tags are a little more complicated because they can
88
 
 * contain "attributes" after the label (delimited by ascii space or tab chars)
89
 
 * of the form attribute_label="value" or attribute_label='value'; as it turns
90
 
 * out we do not have to read any of these attributes, just ignore them.
91
 
 *
92
 
 * Labels are any sequence of chars other than space, tab, right angle bracket
93
 
 * (and ?), but may have an inner structure of <namespace><colon><plain_label>.
94
 
 * As it turns out, we can ignore the namespaces, in fact we can ignore the
95
 
 * entire tree hierarchy, because the plain labels we are looking for will be
96
 
 * unique (not in general, but for this application). We do however have to be
97
 
 * careful to skip over the namespaces.
98
 
 *
99
 
 * In generating XML we have to be more careful, but that is easy because
100
 
 * everything we do is pretty canned. The only real care to take is to escape
101
 
 * any special chars in our payload.
102
 
 */
103
 
 
104
 
/**
105
 
 * xml_next_tag - Advance to next tag
106
 
 * @in: Input
107
 
 * @out: OUT: start of tag just after '<'
108
 
 * @out_tagname: OUT: start of name of tag, skipping namespace
109
 
 * @end: OUT: one after tag
110
 
 * Returns: 0 on success, 1 on failure
111
 
 *
112
 
 * A tag has form:
113
 
 *     <left angle bracket><...><right angle bracket>
114
 
 * Within the angle brackets, there is an optional leading forward slash (which
115
 
 * makes the tag an ending tag), then an optional leading label (followed by
116
 
 * colon) and then the tag name itself.
117
 
 *
118
 
 * Note that angle brackets present in the original data must have been encoded
119
 
 * as &lt; and &gt; so they will not trouble us.
120
 
 */
121
 
static int xml_next_tag(char *in, char **out, char **out_tagname,
122
 
                        char **end)
123
 
{
124
 
        while (*in && *in != '<')
125
 
                in++;
126
 
        if (*in != '<')
127
 
                return 1;
128
 
        *out = ++in;
129
 
        if (*in == '/')
130
 
                in++;
131
 
        *out_tagname = in; /* maybe */
132
 
        while (isalnum(*in) || *in == '-')
133
 
                in++;
134
 
        if (*in == ':')
135
 
                *out_tagname = ++in;
136
 
        while (*in && *in != '>')
137
 
                in++;
138
 
        if (*in != '>')
139
 
                return 1;
140
 
        *end = ++in;
141
 
        return 0;
142
 
}
143
 
 
144
 
 
145
 
/* xml_data_encode -- format data for xml file, escaping special characters.
146
 
 *
147
 
 * Note that we assume we are using utf8 both as input and as output!
148
 
 * In utf8, characters may be classed as follows:
149
 
 *     0xxxxxxx(2) -- 1 byte ascii char
150
 
 *     11xxxxxx(2) -- 1st byte of multi-byte char w/ unicode value >= 0x80
151
 
 *         110xxxxx(2) -- 1st byte of 2 byte sequence (5 payload bits here)
152
 
 *         1110xxxx(2) -- 1st byte of 3 byte sequence (4 payload bits here)
153
 
 *         11110xxx(2) -- 1st byte of 4 byte sequence (3 payload bits here)
154
 
 *      10xxxxxx(2) -- extension byte (6 payload bits per byte)
155
 
 *      Some values implied by the above are however illegal because they
156
 
 *      do not represent unicode chars or are not the shortest encoding.
157
 
 * Actually, we can almost entirely ignore the above and just do
158
 
 * text processing same as for ascii text.
159
 
 *
160
 
 * XML is written with arbitrary unicode characters, except that five
161
 
 * characters have special meaning and so must be escaped where they
162
 
 * appear in payload data... which we do here.
163
 
 */
164
 
static void xml_data_encode(struct wpabuf *buf, const char *data, int len)
165
 
{
166
 
        int i;
167
 
        for (i = 0; i < len; i++) {
168
 
                u8 c = ((u8 *) data)[i];
169
 
                if (c == '<') {
170
 
                        wpabuf_put_str(buf, "&lt;");
171
 
                        continue;
172
 
                }
173
 
                if (c == '>') {
174
 
                        wpabuf_put_str(buf, "&gt;");
175
 
                        continue;
176
 
                }
177
 
                if (c == '&') {
178
 
                        wpabuf_put_str(buf, "&amp;");
179
 
                        continue;
180
 
                }
181
 
                if (c == '\'') {
182
 
                        wpabuf_put_str(buf, "&apos;");
183
 
                        continue;
184
 
                }
185
 
                if (c == '"') {
186
 
                        wpabuf_put_str(buf, "&quot;");
187
 
                        continue;
188
 
                }
189
 
                /*
190
 
                 * We could try to represent control characters using the
191
 
                 * sequence: &#x; where x is replaced by a hex numeral, but not
192
 
                 * clear why we would do this.
193
 
                 */
194
 
                wpabuf_put_u8(buf, c);
195
 
        }
196
 
}
197
 
 
198
 
 
199
 
/* xml_add_tagged_data -- format tagged data as a new xml line.
200
 
 *
201
 
 * tag must not have any special chars.
202
 
 * data may have special chars, which are escaped.
203
 
 */
204
 
static void xml_add_tagged_data(struct wpabuf *buf, const char *tag,
205
 
                                const char *data)
206
 
{
207
 
        wpabuf_printf(buf, "<%s>", tag);
208
 
        xml_data_encode(buf, data, os_strlen(data));
209
 
        wpabuf_printf(buf, "</%s>\n", tag);
210
 
}
211
 
 
212
 
 
213
 
/* A POST body looks something like (per upnp spec):
214
 
 * <?xml version="1.0"?>
215
 
 * <s:Envelope
216
 
 *     xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"
217
 
 *     s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
218
 
 *   <s:Body>
219
 
 *     <u:actionName xmlns:u="urn:schemas-upnp-org:service:serviceType:v">
220
 
 *       <argumentName>in arg value</argumentName>
221
 
 *       other in args and their values go here, if any
222
 
 *     </u:actionName>
223
 
 *   </s:Body>
224
 
 * </s:Envelope>
225
 
 *
226
 
 * where :
227
 
 *      s: might be some other namespace name followed by colon
228
 
 *      u: might be some other namespace name followed by colon
229
 
 *      actionName will be replaced according to action requested
230
 
 *      schema following actionName will be WFA scheme instead
231
 
 *      argumentName will be actual argument name
232
 
 *      (in arg value) will be actual argument value
233
 
 */
234
 
static int
235
 
upnp_get_first_document_item(char *doc, const char *item, char **value)
236
 
{
237
 
        const char *match = item;
238
 
        int match_len = os_strlen(item);
239
 
        char *tag;
240
 
        char *tagname;
241
 
        char *end;
242
 
 
243
 
        *value = NULL;          /* default, bad */
244
 
 
245
 
        /*
246
 
         * This is crude: ignore any possible tag name conflicts and go right
247
 
         * to the first tag of this name. This should be ok for the limited
248
 
         * domain of UPnP messages.
249
 
         */
250
 
        for (;;) {
251
 
                if (xml_next_tag(doc, &tag, &tagname, &end))
252
 
                        return 1;
253
 
                doc = end;
254
 
                if (!os_strncasecmp(tagname, match, match_len) &&
255
 
                    *tag != '/' &&
256
 
                    (tagname[match_len] == '>' ||
257
 
                     !isgraph(tagname[match_len]))) {
258
 
                        break;
259
 
                }
260
 
        }
261
 
        end = doc;
262
 
        while (*end && *end != '<')
263
 
                end++;
264
 
        *value = os_zalloc(1 + (end - doc));
265
 
        if (*value == NULL)
266
 
                return 1;
267
 
        os_memcpy(*value, doc, end - doc);
268
 
        return 0;
269
 
}
270
 
 
271
 
 
272
 
/*
273
41
 * "Files" that we serve via HTTP. The format of these files is given by
274
42
 * WFA WPS specifications. Extra white space has been removed to save space.
275
43
 */
305
73
"</argumentList>\n"
306
74
"</action>\n"
307
75
"<action>\n"
308
 
"<name>GetAPSettings</name>\n"
309
 
"<argumentList>\n"
310
 
"<argument>\n"
311
 
"<name>NewMessage</name>\n"
312
 
"<direction>in</direction>\n"
313
 
"<relatedStateVariable>Message</relatedStateVariable>\n"
314
 
"</argument>\n"
315
 
"<argument>\n"
316
 
"<name>NewAPSettings</name>\n"
317
 
"<direction>out</direction>\n"
318
 
"<relatedStateVariable>APSettings</relatedStateVariable>\n"
319
 
"</argument>\n"
320
 
"</argumentList>\n"
321
 
"</action>\n"
322
 
"<action>\n"
323
 
"<name>SetAPSettings</name>\n"
324
 
"<argumentList>\n"
325
 
"<argument>\n"
326
 
"<name>APSettings</name>\n"
327
 
"<direction>in</direction>\n"
328
 
"<relatedStateVariable>APSettings</relatedStateVariable>\n"
329
 
"</argument>\n"
330
 
"</argumentList>\n"
331
 
"</action>\n"
332
 
"<action>\n"
333
 
"<name>DelAPSettings</name>\n"
334
 
"<argumentList>\n"
335
 
"<argument>\n"
336
 
"<name>NewAPSettings</name>\n"
337
 
"<direction>in</direction>\n"
338
 
"<relatedStateVariable>APSettings</relatedStateVariable>\n"
339
 
"</argument>\n"
340
 
"</argumentList>\n"
341
 
"</action>\n"
342
 
"<action>\n"
343
 
"<name>GetSTASettings</name>\n"
344
 
"<argumentList>\n"
345
 
"<argument>\n"
346
 
"<name>NewMessage</name>\n"
347
 
"<direction>in</direction>\n"
348
 
"<relatedStateVariable>Message</relatedStateVariable>\n"
349
 
"</argument>\n"
350
 
"<argument>\n"
351
 
"<name>NewSTASettings</name>\n"
352
 
"<direction>out</direction>\n"
353
 
"<relatedStateVariable>STASettings</relatedStateVariable>\n"
354
 
"</argument>\n"
355
 
"</argumentList>\n"
356
 
"</action>\n"
357
 
"<action>\n"
358
 
"<name>SetSTASettings</name>\n"
359
 
"<argumentList>\n"
360
 
"<argument>\n"
361
 
"<name>NewSTASettings</name>\n"
362
 
"<direction>out</direction>\n"
363
 
"<relatedStateVariable>STASettings</relatedStateVariable>\n"
364
 
"</argument>\n"
365
 
"</argumentList>\n"
366
 
"</action>\n"
367
 
"<action>\n"
368
 
"<name>DelSTASettings</name>\n"
369
 
"<argumentList>\n"
370
 
"<argument>\n"
371
 
"<name>NewSTASettings</name>\n"
372
 
"<direction>in</direction>\n"
373
 
"<relatedStateVariable>STASettings</relatedStateVariable>\n"
374
 
"</argument>\n"
375
 
"</argumentList>\n"
376
 
"</action>\n"
377
 
"<action>\n"
378
76
"<name>PutWLANResponse</name>\n"
379
77
"<argumentList>\n"
380
78
"<argument>\n"
404
102
"</argument>\n"
405
103
"</argumentList>\n"
406
104
"</action>\n"
407
 
"<action>\n"
408
 
"<name>RebootAP</name>\n"
409
 
"<argumentList>\n"
410
 
"<argument>\n"
411
 
"<name>NewAPSettings</name>\n"
412
 
"<direction>in</direction>\n"
413
 
"<relatedStateVariable>APSettings</relatedStateVariable>\n"
414
 
"</argument>\n"
415
 
"</argumentList>\n"
416
 
"</action>\n"
417
 
"<action>\n"
418
 
"<name>ResetAP</name>\n"
419
 
"<argumentList>\n"
420
 
"<argument>\n"
421
 
"<name>NewMessage</name>\n"
422
 
"<direction>in</direction>\n"
423
 
"<relatedStateVariable>Message</relatedStateVariable>\n"
424
 
"</argument>\n"
425
 
"</argumentList>\n"
426
 
"</action>\n"
427
 
"<action>\n"
428
 
"<name>RebootSTA</name>\n"
429
 
"<argumentList>\n"
430
 
"<argument>\n"
431
 
"<name>NewSTASettings</name>\n"
432
 
"<direction>in</direction>\n"
433
 
"<relatedStateVariable>APSettings</relatedStateVariable>\n"
434
 
"</argument>\n"
435
 
"</argumentList>\n"
436
 
"</action>\n"
437
 
"<action>\n"
438
 
"<name>ResetSTA</name>\n"
439
 
"<argumentList>\n"
440
 
"<argument>\n"
441
 
"<name>NewMessage</name>\n"
442
 
"<direction>in</direction>\n"
443
 
"<relatedStateVariable>Message</relatedStateVariable>\n"
444
 
"</argument>\n"
445
 
"</argumentList>\n"
446
 
"</action>\n"
447
105
"</actionList>\n"
448
106
"<serviceStateTable>\n"
449
107
"<stateVariable sendEvents=\"no\">\n"
462
120
"<name>DeviceInfo</name>\n"
463
121
"<dataType>bin.base64</dataType>\n"
464
122
"</stateVariable>\n"
465
 
"<stateVariable sendEvents=\"no\">\n"
466
 
"<name>APSettings</name>\n"
467
 
"<dataType>bin.base64</dataType>\n"
468
 
"</stateVariable>\n"
469
123
"<stateVariable sendEvents=\"yes\">\n"
470
124
"<name>APStatus</name>\n"
471
125
"<dataType>ui1</dataType>\n"
472
126
"</stateVariable>\n"
473
 
"<stateVariable sendEvents=\"no\">\n"
474
 
"<name>STASettings</name>\n"
475
 
"<dataType>bin.base64</dataType>\n"
476
 
"</stateVariable>\n"
477
127
"<stateVariable sendEvents=\"yes\">\n"
478
128
"<name>STAStatus</name>\n"
479
129
"<dataType>ui1</dataType>\n"
588
238
}
589
239
 
590
240
 
591
 
void web_connection_stop(struct web_connection *c)
592
 
{
593
 
        struct upnp_wps_device_sm *sm = c->sm;
594
 
 
595
 
        httpread_destroy(c->hread);
596
 
        c->hread = NULL;
597
 
        close(c->sd);
598
 
        c->sd = -1;
599
 
        if (c->next == c) {
600
 
                sm->web_connections = NULL;
601
 
        } else {
602
 
                if (sm->web_connections == c)
603
 
                        sm->web_connections = c->next;
604
 
                c->next->prev = c->prev;
605
 
                c->prev->next = c->next;
606
 
        }
607
 
        os_free(c);
608
 
        sm->n_web_connections--;
609
 
}
610
 
 
611
 
 
612
241
static void http_put_reply_code(struct wpabuf *buf, enum http_reply_code code)
613
242
{
614
243
        wpabuf_put_str(buf, "HTTP/1.1 ");
669
298
 * Per RFC 2616, content-length: is not required but connection:close
670
299
 * would appear to be required (given that we will be closing it!).
671
300
 */
672
 
static void web_connection_parse_get(struct web_connection *c, char *filename)
 
301
static void web_connection_parse_get(struct upnp_wps_device_sm *sm,
 
302
                                     struct http_request *hreq, char *filename)
673
303
{
674
 
        struct upnp_wps_device_sm *sm = c->sm;
675
304
        struct wpabuf *buf; /* output buffer, allocated */
676
305
        char *put_length_here;
677
306
        char *body_start;
712
341
                wpa_printf(MSG_DEBUG, "WPS UPnP: HTTP GET file not found: %s",
713
342
                           filename);
714
343
                buf = wpabuf_alloc(200);
715
 
                if (buf == NULL)
 
344
                if (buf == NULL) {
 
345
                        http_request_deinit(hreq);
716
346
                        return;
 
347
                }
717
348
                wpabuf_put_str(buf,
718
349
                               "HTTP/1.1 404 Not Found\r\n"
719
350
                               "Connection: close\r\n");
727
358
        }
728
359
 
729
360
        buf = wpabuf_alloc(1000 + extra_len);
730
 
        if (buf == NULL)
 
361
        if (buf == NULL) {
 
362
                http_request_deinit(hreq);
731
363
                return;
 
364
        }
732
365
 
733
366
        wpabuf_put_str(buf,
734
367
                       "HTTP/1.1 200 OK\r\n"
765
398
        os_memcpy(put_length_here, len_buf, os_strlen(len_buf));
766
399
 
767
400
send_buf:
768
 
        send_wpabuf(c->sd, buf);
769
 
        wpabuf_free(buf);
770
 
}
771
 
 
772
 
 
773
 
static struct wpabuf * web_get_item(char *data, const char *name,
774
 
                                    enum http_reply_code *ret)
775
 
{
776
 
        char *msg;
777
 
        struct wpabuf *buf;
778
 
        unsigned char *decoded;
779
 
        size_t len;
780
 
 
781
 
        if (upnp_get_first_document_item(data, name, &msg)) {
782
 
                *ret = UPNP_ARG_VALUE_INVALID;
783
 
                return NULL;
784
 
        }
785
 
 
786
 
        decoded = base64_decode((unsigned char *) msg, os_strlen(msg), &len);
787
 
        os_free(msg);
788
 
        if (decoded == NULL) {
789
 
                *ret = UPNP_OUT_OF_MEMORY;
790
 
                return NULL;
791
 
        }
792
 
 
793
 
        buf = wpabuf_alloc_ext_data(decoded, len);
794
 
        if (buf == NULL) {
795
 
                os_free(decoded);
796
 
                *ret = UPNP_OUT_OF_MEMORY;
797
 
                return NULL;
798
 
        }
799
 
        return buf;
 
401
        http_request_send_and_deinit(hreq, buf);
800
402
}
801
403
 
802
404
 
805
407
                            struct wpabuf **reply, const char **replyname)
806
408
{
807
409
        static const char *name = "NewDeviceInfo";
 
410
        struct wps_config cfg;
 
411
        struct upnp_wps_peer *peer = &sm->peer;
808
412
 
809
413
        wpa_printf(MSG_DEBUG, "WPS UPnP: GetDeviceInfo");
810
 
        if (sm->ctx->rx_req_get_device_info == NULL)
 
414
 
 
415
        if (sm->ctx->ap_pin == NULL)
811
416
                return HTTP_INTERNAL_SERVER_ERROR;
812
 
        *reply = sm->ctx->rx_req_get_device_info(sm->priv, &sm->peer);
 
417
 
 
418
        /*
 
419
         * Request for DeviceInfo, i.e., M1 TLVs. This is a start of WPS
 
420
         * registration over UPnP with the AP acting as an Enrollee. It should
 
421
         * be noted that this is frequently used just to get the device data,
 
422
         * i.e., there may not be any intent to actually complete the
 
423
         * registration.
 
424
         */
 
425
 
 
426
        if (peer->wps)
 
427
                wps_deinit(peer->wps);
 
428
 
 
429
        os_memset(&cfg, 0, sizeof(cfg));
 
430
        cfg.wps = sm->wps;
 
431
        cfg.pin = (u8 *) sm->ctx->ap_pin;
 
432
        cfg.pin_len = os_strlen(sm->ctx->ap_pin);
 
433
        peer->wps = wps_init(&cfg);
 
434
        if (peer->wps) {
 
435
                enum wsc_op_code op_code;
 
436
                *reply = wps_get_msg(peer->wps, &op_code);
 
437
                if (*reply == NULL) {
 
438
                        wps_deinit(peer->wps);
 
439
                        peer->wps = NULL;
 
440
                }
 
441
        } else
 
442
                *reply = NULL;
813
443
        if (*reply == NULL) {
814
444
                wpa_printf(MSG_INFO, "WPS UPnP: Failed to get DeviceInfo");
815
445
                return HTTP_INTERNAL_SERVER_ERROR;
826
456
        struct wpabuf *msg;
827
457
        static const char *name = "NewOutMessage";
828
458
        enum http_reply_code ret;
 
459
        enum wps_process_res res;
 
460
        enum wsc_op_code op_code;
829
461
 
830
462
        /*
831
463
         * PutMessage is used by external UPnP-based Registrar to perform WPS
833
465
         * PutWLANResponse which is for proxying.
834
466
         */
835
467
        wpa_printf(MSG_DEBUG, "WPS UPnP: PutMessage");
836
 
        if (sm->ctx->rx_req_put_message == NULL)
837
 
                return HTTP_INTERNAL_SERVER_ERROR;
838
 
        msg = web_get_item(data, "NewInMessage", &ret);
839
 
        if (msg == NULL)
840
 
                return ret;
841
 
        *reply = sm->ctx->rx_req_put_message(sm->priv, &sm->peer, msg);
842
 
        wpabuf_free(msg);
843
 
        if (*reply == NULL)
844
 
                return HTTP_INTERNAL_SERVER_ERROR;
845
 
        *replyname = name;
846
 
        return HTTP_OK;
847
 
}
848
 
 
849
 
 
850
 
static enum http_reply_code
851
 
web_process_get_ap_settings(struct upnp_wps_device_sm *sm, char *data,
852
 
                            struct wpabuf **reply, const char **replyname)
853
 
{
854
 
        struct wpabuf *msg;
855
 
        static const char *name = "NewAPSettings";
856
 
        enum http_reply_code ret;
857
 
 
858
 
        wpa_printf(MSG_DEBUG, "WPS UPnP: GetAPSettings");
859
 
        if (sm->ctx->rx_req_get_ap_settings == NULL)
860
 
                return HTTP_INTERNAL_SERVER_ERROR;
861
 
        msg = web_get_item(data, "NewMessage", &ret);
862
 
        if (msg == NULL)
863
 
                return ret;
864
 
        *reply = sm->ctx->rx_req_get_ap_settings(sm->priv, msg);
865
 
        wpabuf_free(msg);
866
 
        if (*reply == NULL)
867
 
                return HTTP_INTERNAL_SERVER_ERROR;
868
 
        *replyname = name;
869
 
        return HTTP_OK;
870
 
}
871
 
 
872
 
 
873
 
static enum http_reply_code
874
 
web_process_set_ap_settings(struct upnp_wps_device_sm *sm, char *data,
875
 
                            struct wpabuf **reply, const char **replyname)
876
 
{
877
 
        struct wpabuf *msg;
878
 
        enum http_reply_code ret;
879
 
 
880
 
        wpa_printf(MSG_DEBUG, "WPS UPnP: SetAPSettings");
881
 
        msg = web_get_item(data, "NewAPSettings", &ret);
882
 
        if (msg == NULL)
883
 
                return ret;
884
 
        if (!sm->ctx->rx_req_set_ap_settings ||
885
 
            sm->ctx->rx_req_set_ap_settings(sm->priv, msg)) {
886
 
                wpabuf_free(msg);
887
 
                return HTTP_INTERNAL_SERVER_ERROR;
888
 
        }
889
 
        wpabuf_free(msg);
890
 
        *replyname = NULL;
891
 
        *reply = NULL;
892
 
        return HTTP_OK;
893
 
}
894
 
 
895
 
 
896
 
static enum http_reply_code
897
 
web_process_del_ap_settings(struct upnp_wps_device_sm *sm, char *data,
898
 
                            struct wpabuf **reply, const char **replyname)
899
 
{
900
 
        struct wpabuf *msg;
901
 
        enum http_reply_code ret;
902
 
 
903
 
        wpa_printf(MSG_DEBUG, "WPS UPnP: DelAPSettings");
904
 
        msg = web_get_item(data, "NewAPSettings", &ret);
905
 
        if (msg == NULL)
906
 
                return ret;
907
 
        if (!sm->ctx->rx_req_del_ap_settings ||
908
 
            sm->ctx->rx_req_del_ap_settings(sm->priv, msg)) {
909
 
                wpabuf_free(msg);
910
 
                return HTTP_INTERNAL_SERVER_ERROR;
911
 
        }
912
 
        wpabuf_free(msg);
913
 
        *replyname = NULL;
914
 
        *reply = NULL;
915
 
        return HTTP_OK;
916
 
}
917
 
 
918
 
 
919
 
static enum http_reply_code
920
 
web_process_get_sta_settings(struct upnp_wps_device_sm *sm, char *data,
921
 
                             struct wpabuf **reply, const char **replyname)
922
 
{
923
 
        struct wpabuf *msg;
924
 
        static const char *name = "NewSTASettings";
925
 
        enum http_reply_code ret;
926
 
 
927
 
        wpa_printf(MSG_DEBUG, "WPS UPnP: GetSTASettings");
928
 
        if (sm->ctx->rx_req_get_sta_settings == NULL)
929
 
                return HTTP_INTERNAL_SERVER_ERROR;
930
 
        msg = web_get_item(data, "NewMessage", &ret);
931
 
        if (msg == NULL)
932
 
                return ret;
933
 
        *reply = sm->ctx->rx_req_get_sta_settings(sm->priv, msg);
934
 
        wpabuf_free(msg);
935
 
        if (*reply == NULL)
936
 
                return HTTP_INTERNAL_SERVER_ERROR;
937
 
        *replyname = name;
938
 
        return HTTP_OK;
939
 
}
940
 
 
941
 
 
942
 
static enum http_reply_code
943
 
web_process_set_sta_settings(struct upnp_wps_device_sm *sm, char *data,
944
 
                             struct wpabuf **reply, const char **replyname)
945
 
{
946
 
        struct wpabuf *msg;
947
 
        enum http_reply_code ret;
948
 
 
949
 
        wpa_printf(MSG_DEBUG, "WPS UPnP: SetSTASettings");
950
 
        msg = web_get_item(data, "NewSTASettings", &ret);
951
 
        if (msg == NULL)
952
 
                return ret;
953
 
        if (!sm->ctx->rx_req_set_sta_settings ||
954
 
            sm->ctx->rx_req_set_sta_settings(sm->priv, msg)) {
955
 
                wpabuf_free(msg);
956
 
                return HTTP_INTERNAL_SERVER_ERROR;
957
 
        }
958
 
        wpabuf_free(msg);
959
 
        *replyname = NULL;
960
 
        *reply = NULL;
961
 
        return HTTP_OK;
962
 
}
963
 
 
964
 
 
965
 
static enum http_reply_code
966
 
web_process_del_sta_settings(struct upnp_wps_device_sm *sm, char *data,
967
 
                             struct wpabuf **reply, const char **replyname)
968
 
{
969
 
        struct wpabuf *msg;
970
 
        enum http_reply_code ret;
971
 
 
972
 
        wpa_printf(MSG_DEBUG, "WPS UPnP: DelSTASettings");
973
 
        msg = web_get_item(data, "NewSTASettings", &ret);
974
 
        if (msg == NULL)
975
 
                return ret;
976
 
        if (!sm->ctx->rx_req_del_sta_settings ||
977
 
            sm->ctx->rx_req_del_sta_settings(sm->priv, msg)) {
978
 
                wpabuf_free(msg);
979
 
                return HTTP_INTERNAL_SERVER_ERROR;
980
 
        }
981
 
        wpabuf_free(msg);
982
 
        *replyname = NULL;
983
 
        *reply = NULL;
 
468
        msg = xml_get_base64_item(data, "NewInMessage", &ret);
 
469
        if (msg == NULL)
 
470
                return ret;
 
471
        res = wps_process_msg(sm->peer.wps, WSC_UPnP, msg);
 
472
        if (res == WPS_FAILURE)
 
473
                *reply = NULL;
 
474
        else
 
475
                *reply = wps_get_msg(sm->peer.wps, &op_code);
 
476
        wpabuf_free(msg);
 
477
        if (*reply == NULL)
 
478
                return HTTP_INTERNAL_SERVER_ERROR;
 
479
        *replyname = name;
984
480
        return HTTP_OK;
985
481
}
986
482
 
1002
498
         */
1003
499
 
1004
500
        wpa_printf(MSG_DEBUG, "WPS UPnP: PutWLANResponse");
1005
 
        msg = web_get_item(data, "NewMessage", &ret);
1006
 
        if (msg == NULL)
 
501
        msg = xml_get_base64_item(data, "NewMessage", &ret);
 
502
        if (msg == NULL) {
 
503
                wpa_printf(MSG_DEBUG, "WPS UPnP: Could not extract NewMessage "
 
504
                           "from PutWLANResponse");
1007
505
                return ret;
1008
 
        if (upnp_get_first_document_item(data, "NewWLANEventType", &val)) {
 
506
        }
 
507
        val = xml_get_first_item(data, "NewWLANEventType");
 
508
        if (val == NULL) {
 
509
                wpa_printf(MSG_DEBUG, "WPS UPnP: No NewWLANEventType in "
 
510
                           "PutWLANResponse");
1009
511
                wpabuf_free(msg);
1010
512
                return UPNP_ARG_VALUE_INVALID;
1011
513
        }
1012
514
        ev_type = atol(val);
1013
515
        os_free(val);
1014
 
        val = NULL;
1015
 
        if (upnp_get_first_document_item(data, "NewWLANEventMAC", &val) ||
1016
 
            hwaddr_aton(val, macaddr)) {
 
516
        val = xml_get_first_item(data, "NewWLANEventMAC");
 
517
        if (val == NULL) {
 
518
                wpa_printf(MSG_DEBUG, "WPS UPnP: No NewWLANEventMAC in "
 
519
                           "PutWLANResponse");
1017
520
                wpabuf_free(msg);
1018
 
                os_free(val);
1019
521
                return UPNP_ARG_VALUE_INVALID;
1020
522
        }
 
523
        if (hwaddr_aton(val, macaddr)) {
 
524
                wpa_printf(MSG_DEBUG, "WPS UPnP: Invalid NewWLANEventMAC in "
 
525
                           "PutWLANResponse: '%s'", val);
 
526
                if (hwaddr_aton2(val, macaddr) > 0) {
 
527
                        /*
 
528
                         * At least some versions of Intel PROset seem to be
 
529
                         * using dot-deliminated MAC address format here.
 
530
                         */
 
531
                        wpa_printf(MSG_DEBUG, "WPS UPnP: Workaround - allow "
 
532
                                   "incorrect MAC address format in "
 
533
                                   "NewWLANEventMAC");
 
534
                } else {
 
535
                        wpabuf_free(msg);
 
536
                        os_free(val);
 
537
                        return UPNP_ARG_VALUE_INVALID;
 
538
                }
 
539
        }
1021
540
        os_free(val);
1022
541
        if (ev_type == UPNP_WPS_WLANEVENT_TYPE_EAP) {
1023
542
                struct wps_parse_attr attr;
1044
563
}
1045
564
 
1046
565
 
 
566
static int find_er_addr(struct subscription *s, struct sockaddr_in *cli)
 
567
{
 
568
        struct subscr_addr *a;
 
569
 
 
570
        dl_list_for_each(a, &s->addr_list, struct subscr_addr, list) {
 
571
                if (cli->sin_addr.s_addr == a->saddr.sin_addr.s_addr)
 
572
                        return 1;
 
573
        }
 
574
        return 0;
 
575
}
 
576
 
 
577
 
 
578
static struct subscription * find_er(struct upnp_wps_device_sm *sm,
 
579
                                     struct sockaddr_in *cli)
 
580
{
 
581
        struct subscription *s;
 
582
        dl_list_for_each(s, &sm->subscriptions, struct subscription, list)
 
583
                if (find_er_addr(s, cli))
 
584
                        return s;
 
585
        return NULL;
 
586
}
 
587
 
 
588
 
1047
589
static enum http_reply_code
1048
 
web_process_set_selected_registrar(struct upnp_wps_device_sm *sm, char *data,
 
590
web_process_set_selected_registrar(struct upnp_wps_device_sm *sm,
 
591
                                   struct sockaddr_in *cli, char *data,
1049
592
                                   struct wpabuf **reply,
1050
593
                                   const char **replyname)
1051
594
{
1052
595
        struct wpabuf *msg;
1053
596
        enum http_reply_code ret;
 
597
        struct subscription *s;
1054
598
 
1055
599
        wpa_printf(MSG_DEBUG, "WPS UPnP: SetSelectedRegistrar");
1056
 
        msg = web_get_item(data, "NewMessage", &ret);
1057
 
        if (msg == NULL)
1058
 
                return ret;
1059
 
        if (!sm->ctx->rx_req_set_selected_registrar ||
1060
 
            sm->ctx->rx_req_set_selected_registrar(sm->priv, msg)) {
1061
 
                wpabuf_free(msg);
1062
 
                return HTTP_INTERNAL_SERVER_ERROR;
1063
 
        }
1064
 
        wpabuf_free(msg);
1065
 
        *replyname = NULL;
1066
 
        *reply = NULL;
1067
 
        return HTTP_OK;
1068
 
}
1069
 
 
1070
 
 
1071
 
static enum http_reply_code
1072
 
web_process_reboot_ap(struct upnp_wps_device_sm *sm, char *data,
1073
 
                      struct wpabuf **reply, const char **replyname)
1074
 
{
1075
 
        struct wpabuf *msg;
1076
 
        enum http_reply_code ret;
1077
 
 
1078
 
        wpa_printf(MSG_DEBUG, "WPS UPnP: RebootAP");
1079
 
        msg = web_get_item(data, "NewAPSettings", &ret);
1080
 
        if (msg == NULL)
1081
 
                return ret;
1082
 
        if (!sm->ctx->rx_req_reboot_ap ||
1083
 
            sm->ctx->rx_req_reboot_ap(sm->priv, msg)) {
1084
 
                wpabuf_free(msg);
1085
 
                return HTTP_INTERNAL_SERVER_ERROR;
1086
 
        }
1087
 
        wpabuf_free(msg);
1088
 
        *replyname = NULL;
1089
 
        *reply = NULL;
1090
 
        return HTTP_OK;
1091
 
}
1092
 
 
1093
 
 
1094
 
static enum http_reply_code
1095
 
web_process_reset_ap(struct upnp_wps_device_sm *sm, char *data,
1096
 
                     struct wpabuf **reply, const char **replyname)
1097
 
{
1098
 
        struct wpabuf *msg;
1099
 
        enum http_reply_code ret;
1100
 
 
1101
 
        wpa_printf(MSG_DEBUG, "WPS UPnP: ResetAP");
1102
 
        msg = web_get_item(data, "NewMessage", &ret);
1103
 
        if (msg == NULL)
1104
 
                return ret;
1105
 
        if (!sm->ctx->rx_req_reset_ap ||
1106
 
            sm->ctx->rx_req_reset_ap(sm->priv, msg)) {
1107
 
                wpabuf_free(msg);
1108
 
                return HTTP_INTERNAL_SERVER_ERROR;
1109
 
        }
1110
 
        wpabuf_free(msg);
1111
 
        *replyname = NULL;
1112
 
        *reply = NULL;
1113
 
        return HTTP_OK;
1114
 
}
1115
 
 
1116
 
 
1117
 
static enum http_reply_code
1118
 
web_process_reboot_sta(struct upnp_wps_device_sm *sm, char *data,
1119
 
                       struct wpabuf **reply, const char **replyname)
1120
 
{
1121
 
        struct wpabuf *msg;
1122
 
        enum http_reply_code ret;
1123
 
 
1124
 
        wpa_printf(MSG_DEBUG, "WPS UPnP: RebootSTA");
1125
 
        msg = web_get_item(data, "NewSTASettings", &ret);
1126
 
        if (msg == NULL)
1127
 
                return ret;
1128
 
        if (!sm->ctx->rx_req_reboot_sta ||
1129
 
            sm->ctx->rx_req_reboot_sta(sm->priv, msg)) {
1130
 
                wpabuf_free(msg);
1131
 
                return HTTP_INTERNAL_SERVER_ERROR;
1132
 
        }
1133
 
        wpabuf_free(msg);
1134
 
        *replyname = NULL;
1135
 
        *reply = NULL;
1136
 
        return HTTP_OK;
1137
 
}
1138
 
 
1139
 
 
1140
 
static enum http_reply_code
1141
 
web_process_reset_sta(struct upnp_wps_device_sm *sm, char *data,
1142
 
                      struct wpabuf **reply, const char **replyname)
1143
 
{
1144
 
        struct wpabuf *msg;
1145
 
        enum http_reply_code ret;
1146
 
 
1147
 
        wpa_printf(MSG_DEBUG, "WPS UPnP: ResetSTA");
1148
 
        msg = web_get_item(data, "NewMessage", &ret);
1149
 
        if (msg == NULL)
1150
 
                return ret;
1151
 
        if (!sm->ctx->rx_req_reset_sta ||
1152
 
            sm->ctx->rx_req_reset_sta(sm->priv, msg)) {
 
600
        s = find_er(sm, cli);
 
601
        if (s == NULL) {
 
602
                wpa_printf(MSG_DEBUG, "WPS UPnP: Ignore SetSelectedRegistrar "
 
603
                           "from unknown ER");
 
604
                return UPNP_ACTION_FAILED;
 
605
        }
 
606
        msg = xml_get_base64_item(data, "NewMessage", &ret);
 
607
        if (msg == NULL)
 
608
                return ret;
 
609
        if (upnp_er_set_selected_registrar(sm->wps->registrar, s, msg)) {
1153
610
                wpabuf_free(msg);
1154
611
                return HTTP_INTERNAL_SERVER_ERROR;
1155
612
        }
1180
637
        "</detail>\n"
1181
638
        "</s:Fault>\n";
1182
639
 
1183
 
static void web_connection_send_reply(struct web_connection *c,
 
640
static void web_connection_send_reply(struct http_request *req,
1184
641
                                      enum http_reply_code ret,
1185
642
                                      const char *action, int action_len,
1186
643
                                      const struct wpabuf *reply,
1208
665
        if (buf == NULL) {
1209
666
                wpa_printf(MSG_INFO, "WPS UPnP: Cannot allocate reply to "
1210
667
                           "POST");
1211
 
                wpabuf_free(buf);
1212
668
                os_free(replydata);
 
669
                http_request_deinit(req);
1213
670
                return;
1214
671
        }
1215
672
 
1282
739
                os_memcpy(put_length_here, len_buf, os_strlen(len_buf));
1283
740
        }
1284
741
 
1285
 
        send_wpabuf(c->sd, buf);
1286
 
        wpabuf_free(buf);
 
742
        http_request_send_and_deinit(req, buf);
1287
743
}
1288
744
 
1289
745
 
1290
 
static const char * web_get_action(struct web_connection *c,
1291
 
                                   const char *filename, size_t *action_len)
 
746
static const char * web_get_action(struct http_request *req,
 
747
                                   size_t *action_len)
1292
748
{
1293
749
        const char *match;
1294
750
        int match_len;
1296
752
        char *action;
1297
753
 
1298
754
        *action_len = 0;
1299
 
        if (os_strcasecmp(filename, UPNP_WPS_DEVICE_CONTROL_FILE)) {
1300
 
                wpa_printf(MSG_INFO, "WPS UPnP: Invalid POST filename %s",
1301
 
                           filename);
1302
 
                return NULL;
1303
 
        }
1304
755
        /* The SOAPAction line of the header tells us what we want to do */
1305
 
        b = httpread_hdr_line_get(c->hread, "SOAPAction:");
 
756
        b = http_request_get_hdr_line(req, "SOAPAction:");
1306
757
        if (b == NULL)
1307
758
                return NULL;
1308
759
        if (*b == '"')
1349
800
 * Per RFC 2616, content-length: is not required but connection:close
1350
801
 * would appear to be required (given that we will be closing it!).
1351
802
 */
1352
 
static void web_connection_parse_post(struct web_connection *c,
 
803
static void web_connection_parse_post(struct upnp_wps_device_sm *sm,
 
804
                                      struct sockaddr_in *cli,
 
805
                                      struct http_request *req,
1353
806
                                      const char *filename)
1354
807
{
1355
808
        enum http_reply_code ret;
1356
 
        struct upnp_wps_device_sm *sm = c->sm;
1357
 
        char *data = httpread_data_get(c->hread); /* body of http msg */
1358
 
        const char *action;
1359
 
        size_t action_len;
 
809
        char *data = http_request_get_data(req); /* body of http msg */
 
810
        const char *action = NULL;
 
811
        size_t action_len = 0;
1360
812
        const char *replyname = NULL; /* argument name for the reply */
1361
813
        struct wpabuf *reply = NULL; /* data for the reply */
1362
814
 
 
815
        if (os_strcasecmp(filename, UPNP_WPS_DEVICE_CONTROL_FILE)) {
 
816
                wpa_printf(MSG_INFO, "WPS UPnP: Invalid POST filename %s",
 
817
                           filename);
 
818
                ret = HTTP_NOT_FOUND;
 
819
                goto bad;
 
820
        }
 
821
 
1363
822
        ret = UPNP_INVALID_ACTION;
1364
 
        action = web_get_action(c, filename, &action_len);
 
823
        action = web_get_action(req, &action_len);
1365
824
        if (action == NULL)
1366
825
                goto bad;
1367
826
 
1368
 
        /*
1369
 
         * There are quite a few possible actions. Although we appear to
1370
 
         * support them all here, not all of them are necessarily supported by
1371
 
         * callbacks at higher levels.
1372
 
         */
1373
827
        if (!os_strncasecmp("GetDeviceInfo", action, action_len))
1374
828
                ret = web_process_get_device_info(sm, &reply, &replyname);
1375
829
        else if (!os_strncasecmp("PutMessage", action, action_len))
1376
830
                ret = web_process_put_message(sm, data, &reply, &replyname);
1377
 
        else if (!os_strncasecmp("GetAPSettings", action, action_len))
1378
 
                ret = web_process_get_ap_settings(sm, data, &reply,
1379
 
                                                  &replyname);
1380
 
        else if (!os_strncasecmp("SetAPSettings", action, action_len))
1381
 
                ret = web_process_set_ap_settings(sm, data, &reply,
1382
 
                                                  &replyname);
1383
 
        else if (!os_strncasecmp("DelAPSettings", action, action_len))
1384
 
                ret = web_process_del_ap_settings(sm, data, &reply,
1385
 
                                                  &replyname);
1386
 
        else if (!os_strncasecmp("GetSTASettings", action, action_len))
1387
 
                ret = web_process_get_sta_settings(sm, data, &reply,
1388
 
                                                   &replyname);
1389
 
        else if (!os_strncasecmp("SetSTASettings", action, action_len))
1390
 
                ret = web_process_set_sta_settings(sm, data, &reply,
1391
 
                                                   &replyname);
1392
 
        else if (!os_strncasecmp("DelSTASettings", action, action_len))
1393
 
                ret = web_process_del_sta_settings(sm, data, &reply,
1394
 
                                                  &replyname);
1395
831
        else if (!os_strncasecmp("PutWLANResponse", action, action_len))
1396
832
                ret = web_process_put_wlan_response(sm, data, &reply,
1397
833
                                                    &replyname);
1398
834
        else if (!os_strncasecmp("SetSelectedRegistrar", action, action_len))
1399
 
                ret = web_process_set_selected_registrar(sm, data, &reply,
 
835
                ret = web_process_set_selected_registrar(sm, cli, data, &reply,
1400
836
                                                         &replyname);
1401
 
        else if (!os_strncasecmp("RebootAP", action, action_len))
1402
 
                ret = web_process_reboot_ap(sm, data, &reply, &replyname);
1403
 
        else if (!os_strncasecmp("ResetAP", action, action_len))
1404
 
                ret = web_process_reset_ap(sm, data, &reply, &replyname);
1405
 
        else if (!os_strncasecmp("RebootSTA", action, action_len))
1406
 
                ret = web_process_reboot_sta(sm, data, &reply, &replyname);
1407
 
        else if (!os_strncasecmp("ResetSTA", action, action_len))
1408
 
                ret = web_process_reset_sta(sm, data, &reply, &replyname);
1409
837
        else
1410
838
                wpa_printf(MSG_INFO, "WPS UPnP: Unknown POST type");
1411
839
 
1412
840
bad:
1413
841
        if (ret != HTTP_OK)
1414
842
                wpa_printf(MSG_INFO, "WPS UPnP: POST failure ret=%d", ret);
1415
 
        web_connection_send_reply(c, ret, action, action_len, reply,
 
843
        web_connection_send_reply(req, ret, action, action_len, reply,
1416
844
                                  replyname);
1417
845
        wpabuf_free(reply);
1418
846
}
1437
865
 * Per RFC 2616, content-length: is not required but connection:close
1438
866
 * would appear to be required (given that we will be closing it!).
1439
867
 */
1440
 
static void web_connection_parse_subscribe(struct web_connection *c,
 
868
static void web_connection_parse_subscribe(struct upnp_wps_device_sm *sm,
 
869
                                           struct http_request *req,
1441
870
                                           const char *filename)
1442
871
{
1443
 
        struct upnp_wps_device_sm *sm = c->sm;
1444
872
        struct wpabuf *buf;
1445
873
        char *b;
1446
 
        char *hdr = httpread_hdr_get(c->hread);
 
874
        char *hdr = http_request_get_hdr(req);
1447
875
        char *h;
1448
876
        char *match;
1449
877
        int match_len;
1457
885
        enum http_reply_code ret = HTTP_INTERNAL_SERVER_ERROR;
1458
886
 
1459
887
        buf = wpabuf_alloc(1000);
1460
 
        if (buf == NULL)
 
888
        if (buf == NULL) {
 
889
                http_request_deinit(req);
1461
890
                return;
 
891
        }
1462
892
 
1463
893
        /* Parse/validate headers */
1464
894
        h = hdr;
1599
1029
        /* And empty line to terminate header: */
1600
1030
        wpabuf_put_str(buf, "\r\n");
1601
1031
 
1602
 
        send_wpabuf(c->sd, buf);
1603
 
        wpabuf_free(buf);
1604
1032
        os_free(callback_urls);
 
1033
        http_request_send_and_deinit(req, buf);
1605
1034
        return;
1606
1035
 
1607
1036
error:
1627
1056
        *   599 Too many subscriptions (not a standard HTTP error)
1628
1057
        */
1629
1058
        http_put_empty(buf, ret);
1630
 
        send_wpabuf(c->sd, buf);
1631
 
        wpabuf_free(buf);
 
1059
        http_request_send_and_deinit(req, buf);
1632
1060
        os_free(callback_urls);
1633
1061
}
1634
1062
 
1648
1076
 * Per RFC 2616, content-length: is not required but connection:close
1649
1077
 * would appear to be required (given that we will be closing it!).
1650
1078
 */
1651
 
static void web_connection_parse_unsubscribe(struct web_connection *c,
 
1079
static void web_connection_parse_unsubscribe(struct upnp_wps_device_sm *sm,
 
1080
                                             struct http_request *req,
1652
1081
                                             const char *filename)
1653
1082
{
1654
 
        struct upnp_wps_device_sm *sm = c->sm;
1655
1083
        struct wpabuf *buf;
1656
 
        char *hdr = httpread_hdr_get(c->hread);
 
1084
        char *hdr = http_request_get_hdr(req);
1657
1085
        char *h;
1658
1086
        char *match;
1659
1087
        int match_len;
1721
1149
        if (got_uuid) {
1722
1150
                s = subscription_find(sm, uuid);
1723
1151
                if (s) {
 
1152
                        struct subscr_addr *sa;
 
1153
                        sa = dl_list_first(&s->addr_list, struct subscr_addr,
 
1154
                                           list);
1724
1155
                        wpa_printf(MSG_DEBUG, "WPS UPnP: Unsubscribing %p %s",
1725
 
                                   s,
1726
 
                                   (s && s->addr_list &&
1727
 
                                    s->addr_list->domain_and_port) ?
1728
 
                                   s->addr_list->domain_and_port : "-null-");
1729
 
                        subscription_unlink(s);
 
1156
                                   s, (sa && sa->domain_and_port) ?
 
1157
                                   sa->domain_and_port : "-null-");
 
1158
                        dl_list_del(&s->list);
1730
1159
                        subscription_destroy(s);
1731
1160
                }
1732
1161
        } else {
1740
1169
 
1741
1170
send_msg:
1742
1171
        buf = wpabuf_alloc(200);
1743
 
        if (buf == NULL)
 
1172
        if (buf == NULL) {
 
1173
                http_request_deinit(req);
1744
1174
                return;
 
1175
        }
1745
1176
        http_put_empty(buf, ret);
1746
 
        send_wpabuf(c->sd, buf);
1747
 
        wpabuf_free(buf);
 
1177
        http_request_send_and_deinit(req, buf);
1748
1178
}
1749
1179
 
1750
1180
 
1751
1181
/* Send error in response to unknown requests */
1752
 
static void web_connection_unimplemented(struct web_connection *c)
 
1182
static void web_connection_unimplemented(struct http_request *req)
1753
1183
{
1754
1184
        struct wpabuf *buf;
1755
1185
        buf = wpabuf_alloc(200);
1756
 
        if (buf == NULL)
 
1186
        if (buf == NULL) {
 
1187
                http_request_deinit(req);
1757
1188
                return;
 
1189
        }
1758
1190
        http_put_empty(buf, HTTP_UNIMPLEMENTED);
1759
 
        send_wpabuf(c->sd, buf);
1760
 
        wpabuf_free(buf);
 
1191
        http_request_send_and_deinit(req, buf);
1761
1192
}
1762
1193
 
1763
1194
 
1764
1195
 
1765
1196
/* Called when we have gotten an apparently valid http request.
1766
1197
 */
1767
 
static void web_connection_check_data(struct web_connection *c)
 
1198
static void web_connection_check_data(void *ctx, struct http_request *req)
1768
1199
{
1769
 
        struct httpread *hread = c->hread;
1770
 
        enum httpread_hdr_type htype = httpread_hdr_type_get(hread);
1771
 
        /* char *data = httpread_data_get(hread); */
1772
 
        char *filename = httpread_uri_get(hread);
 
1200
        struct upnp_wps_device_sm *sm = ctx;
 
1201
        enum httpread_hdr_type htype = http_request_get_type(req);
 
1202
        char *filename = http_request_get_uri(req);
 
1203
        struct sockaddr_in *cli = http_request_get_cli_addr(req);
1773
1204
 
1774
 
        c->done = 1;
1775
1205
        if (!filename) {
1776
1206
                wpa_printf(MSG_INFO, "WPS UPnP: Could not get HTTP URI");
 
1207
                http_request_deinit(req);
1777
1208
                return;
1778
1209
        }
1779
1210
        /* Trim leading slashes from filename */
1781
1212
                filename++;
1782
1213
 
1783
1214
        wpa_printf(MSG_DEBUG, "WPS UPnP: Got HTTP request type %d from %s:%d",
1784
 
                   htype, inet_ntoa(c->cli_addr.sin_addr),
1785
 
                   htons(c->cli_addr.sin_port));
 
1215
                   htype, inet_ntoa(cli->sin_addr), htons(cli->sin_port));
1786
1216
 
1787
1217
        switch (htype) {
1788
1218
        case HTTPREAD_HDR_TYPE_GET:
1789
 
                web_connection_parse_get(c, filename);
 
1219
                web_connection_parse_get(sm, req, filename);
1790
1220
                break;
1791
1221
        case HTTPREAD_HDR_TYPE_POST:
1792
 
                web_connection_parse_post(c, filename);
 
1222
                web_connection_parse_post(sm, cli, req, filename);
1793
1223
                break;
1794
1224
        case HTTPREAD_HDR_TYPE_SUBSCRIBE:
1795
 
                web_connection_parse_subscribe(c, filename);
 
1225
                web_connection_parse_subscribe(sm, req, filename);
1796
1226
                break;
1797
1227
        case HTTPREAD_HDR_TYPE_UNSUBSCRIBE:
1798
 
                web_connection_parse_unsubscribe(c, filename);
 
1228
                web_connection_parse_unsubscribe(sm, req, filename);
1799
1229
                break;
 
1230
 
1800
1231
                /* We are not required to support M-POST; just plain
1801
1232
                 * POST is supposed to work, so we only support that.
1802
1233
                 * If for some reason we need to support M-POST, it is
1804
1235
                 */
1805
1236
        default:
1806
1237
                /* Send 501 for anything else */
1807
 
                web_connection_unimplemented(c);
1808
 
                break;
1809
 
        }
1810
 
}
1811
 
 
1812
 
 
1813
 
 
1814
 
/* called back when we have gotten request */
1815
 
static void web_connection_got_file_handler(struct httpread *handle,
1816
 
                                            void *cookie,
1817
 
                                            enum httpread_event en)
1818
 
{
1819
 
        struct web_connection *c = cookie;
1820
 
 
1821
 
        if (en == HTTPREAD_EVENT_FILE_READY)
1822
 
                web_connection_check_data(c);
1823
 
        web_connection_stop(c);
1824
 
}
1825
 
 
1826
 
 
1827
 
/* web_connection_start - Start web connection
1828
 
 * @sm: WPS UPnP state machine from upnp_wps_device_init()
1829
 
 * @sd: Socket descriptor
1830
 
 * @addr: Client address
1831
 
 *
1832
 
 * The socket descriptor sd is handed over for ownership by the WPS UPnP
1833
 
 * state machine.
1834
 
 */
1835
 
static void web_connection_start(struct upnp_wps_device_sm *sm,
1836
 
                                 int sd, struct sockaddr_in *addr)
1837
 
{
1838
 
        struct web_connection *c = NULL;
1839
 
 
1840
 
        /* if too many connections, bail */
1841
 
        if (sm->n_web_connections >= MAX_WEB_CONNECTIONS) {
1842
 
                close(sd);
1843
 
                return;
1844
 
        }
1845
 
 
1846
 
        c = os_zalloc(sizeof(*c));
1847
 
        if (c == NULL)
1848
 
                return;
1849
 
        os_memcpy(&c->cli_addr, addr, sizeof(c->cli_addr));
1850
 
        c->sm = sm;
1851
 
        c->sd = sd;
1852
 
#if 0
1853
 
        /*
1854
 
         * Setting non-blocking should not be necessary for read, and can mess
1855
 
         * up sending where blocking might be better.
1856
 
         */
1857
 
        if (fcntl(sd, F_SETFL, O_NONBLOCK) != 0)
1858
 
                break;
1859
 
#endif
1860
 
        c->hread = httpread_create(c->sd, web_connection_got_file_handler,
1861
 
                                   c /* cookie */,
1862
 
                                   WEB_CONNECTION_MAX_READ,
1863
 
                                   WEB_CONNECTION_TIMEOUT_SEC);
1864
 
        if (c->hread == NULL)
1865
 
                goto fail;
1866
 
        if (sm->web_connections) {
1867
 
                c->next = sm->web_connections;
1868
 
                c->prev = c->next->prev;
1869
 
                c->prev->next = c;
1870
 
                c->next->prev = c;
1871
 
        } else {
1872
 
                sm->web_connections = c->next = c->prev = c;
1873
 
        }
1874
 
        sm->n_web_connections++;
1875
 
        return;
1876
 
 
1877
 
fail:
1878
 
        if (c)
1879
 
                web_connection_stop(c);
 
1238
                web_connection_unimplemented(req);
 
1239
                break;
 
1240
        }
1880
1241
}
1881
1242
 
1882
1243
 
1888
1249
 
1889
1250
void web_listener_stop(struct upnp_wps_device_sm *sm)
1890
1251
{
1891
 
        if (sm->web_sd_registered) {
1892
 
                sm->web_sd_registered = 0;
1893
 
                eloop_unregister_sock(sm->web_sd, EVENT_TYPE_READ);
1894
 
        }
1895
 
        if (sm->web_sd >= 0)
1896
 
                close(sm->web_sd);
1897
 
        sm->web_sd = -1;
1898
 
}
1899
 
 
1900
 
 
1901
 
static void web_listener_handler(int sd, void *eloop_ctx, void *sock_ctx)
1902
 
{
1903
 
        struct sockaddr_in addr;
1904
 
        socklen_t addr_len = sizeof(addr);
1905
 
        struct upnp_wps_device_sm *sm = sock_ctx;
1906
 
        int new_sd;
1907
 
 
1908
 
        /* Create state for new connection */
1909
 
        /* Remember so we can cancel if need be */
1910
 
        new_sd = accept(sm->web_sd, (struct sockaddr *) &addr, &addr_len);
1911
 
        if (new_sd < 0) {
1912
 
                wpa_printf(MSG_ERROR, "WPS UPnP: web listener accept "
1913
 
                           "errno=%d (%s) web_sd=%d",
1914
 
                           errno, strerror(errno), sm->web_sd);
1915
 
                return;
1916
 
        }
1917
 
        web_connection_start(sm, new_sd, &addr);
 
1252
        http_server_deinit(sm->web_srv);
 
1253
        sm->web_srv = NULL;
1918
1254
}
1919
1255
 
1920
1256
 
1921
1257
int web_listener_start(struct upnp_wps_device_sm *sm)
1922
1258
{
1923
 
        struct sockaddr_in addr;
1924
 
        int port;
1925
 
 
1926
 
        sm->web_sd = socket(AF_INET, SOCK_STREAM, 0);
1927
 
        if (sm->web_sd < 0)
1928
 
                goto fail;
1929
 
        if (fcntl(sm->web_sd, F_SETFL, O_NONBLOCK) != 0)
1930
 
                goto fail;
1931
 
        port = 49152;  /* first non-reserved port */
1932
 
        for (;;) {
1933
 
                os_memset(&addr, 0, sizeof(addr));
1934
 
                addr.sin_family = AF_INET;
1935
 
                addr.sin_addr.s_addr = sm->ip_addr;
1936
 
                addr.sin_port = htons(port);
1937
 
                if (bind(sm->web_sd, (struct sockaddr *) &addr,
1938
 
                         sizeof(addr)) == 0)
1939
 
                        break;
1940
 
                if (errno == EADDRINUSE) {
1941
 
                        /* search for unused port */
1942
 
                        if (++port == 65535)
1943
 
                                goto fail;
1944
 
                        continue;
1945
 
                }
1946
 
                goto fail;
 
1259
        struct in_addr addr;
 
1260
        addr.s_addr = sm->ip_addr;
 
1261
        sm->web_srv = http_server_init(&addr, -1, web_connection_check_data,
 
1262
                                       sm);
 
1263
        if (sm->web_srv == NULL) {
 
1264
                web_listener_stop(sm);
 
1265
                return -1;
1947
1266
        }
1948
 
        if (listen(sm->web_sd, 10 /* max backlog */) != 0)
1949
 
                goto fail;
1950
 
        if (fcntl(sm->web_sd, F_SETFL, O_NONBLOCK) != 0)
1951
 
                goto fail;
1952
 
        if (eloop_register_sock(sm->web_sd, EVENT_TYPE_READ,
1953
 
                                web_listener_handler, NULL, sm))
1954
 
                goto fail;
1955
 
        sm->web_sd_registered = 1;
1956
 
        sm->web_port = port;
 
1267
        sm->web_port = http_server_get_port(sm->web_srv);
1957
1268
 
1958
1269
        return 0;
1959
 
 
1960
 
fail:
1961
 
        /* Error */
1962
 
        web_listener_stop(sm);
1963
 
        return -1;
1964
1270
}