2bd428f5fcb3b0f37cea9561855acf5be2598eed
[libeap.git] / src / wps / wps_er.c
1 /*
2  * Wi-Fi Protected Setup - External Registrar
3  * Copyright (c) 2009, Jouni Malinen <j@w1.fi>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation.
8  *
9  * Alternatively, this software may be distributed under the terms of BSD
10  * license.
11  *
12  * See README and COPYING for more details.
13  */
14
15 #include "includes.h"
16
17 #include "common.h"
18 #include "base64.h"
19 #include "uuid.h"
20 #include "eloop.h"
21 #include "httpread.h"
22 #include "http_client.h"
23 #include "http_server.h"
24 #include "upnp_xml.h"
25 #include "wps_i.h"
26 #include "wps_upnp.h"
27 #include "wps_upnp_i.h"
28
29
30 /* TODO:
31  * send notification of new AP device with wpa_msg
32  * re-send notifications with wpa_msg if ER re-started (to update wpa_gui-qt4)
33  * (also re-send SSDP M-SEARCH in this case to find new APs)
34  * parse UPnP event messages
35  */
36
37 static void wps_er_ap_timeout(void *eloop_data, void *user_ctx);
38 static void wps_er_sta_timeout(void *eloop_data, void *user_ctx);
39
40
41 struct wps_er_sta {
42         struct wps_er_sta *next;
43         struct wps_er_ap *ap;
44         u8 addr[ETH_ALEN];
45         u16 config_methods;
46         u8 uuid[WPS_UUID_LEN];
47         u8 pri_dev_type[8];
48         u16 dev_passwd_id;
49         int m1_received;
50         char *manufacturer;
51         char *model_name;
52         char *model_number;
53         char *serial_number;
54         char *dev_name;
55         struct wps_data *wps;
56         struct http_client *http;
57 };
58
59 struct wps_er_ap {
60         struct wps_er_ap *next;
61         struct wps_er *er;
62         struct wps_er_sta *sta; /* list of STAs/Enrollees using this AP */
63         struct in_addr addr;
64         char *location;
65         struct http_client *http;
66
67         u8 uuid[WPS_UUID_LEN];
68         char *friendly_name;
69         char *manufacturer;
70         char *manufacturer_url;
71         char *model_description;
72         char *model_name;
73         char *model_number;
74         char *model_url;
75         char *serial_number;
76         char *udn;
77         char *upc;
78
79         char *scpd_url;
80         char *control_url;
81         char *event_sub_url;
82
83         int subscribed;
84         unsigned int id;
85 };
86
87 struct wps_er {
88         struct wps_context *wps;
89         char ifname[17];
90         char *mac_addr_text; /* mac addr of network i.f. we use */
91         u8 mac_addr[ETH_ALEN]; /* mac addr of network i.f. we use */
92         char *ip_addr_text; /* IP address of network i.f. we use */
93         unsigned ip_addr; /* IP address of network i.f. we use (host order) */
94         int multicast_sd;
95         int ssdp_sd;
96         struct wps_er_ap *ap;
97         struct http_server *http_srv;
98         int http_port;
99         unsigned int next_ap_id;
100 };
101
102
103 static struct wps_er_sta * wps_er_sta_get(struct wps_er_ap *ap, const u8 *addr)
104 {
105         struct wps_er_sta *sta = ap->sta;
106         while (sta) {
107                 if (os_memcmp(sta->addr, addr, ETH_ALEN) == 0)
108                         return sta;
109                 sta = sta->next;
110         }
111         return NULL;
112 }
113
114
115 static void wps_er_sta_free(struct wps_er_sta *sta)
116 {
117         if (sta->wps)
118                 wps_deinit(sta->wps);
119         os_free(sta->manufacturer);
120         os_free(sta->model_name);
121         os_free(sta->model_number);
122         os_free(sta->serial_number);
123         os_free(sta->dev_name);
124         http_client_free(sta->http);
125         eloop_cancel_timeout(wps_er_sta_timeout, sta, NULL);
126         os_free(sta);
127 }
128
129
130 static void wps_er_sta_remove_all(struct wps_er_ap *ap)
131 {
132         struct wps_er_sta *prev, *sta;
133
134         sta = ap->sta;
135         ap->sta = NULL;
136
137         while (sta) {
138                 prev = sta;
139                 sta = sta->next;
140                 wps_er_sta_free(prev);
141         }
142 }
143
144
145 static struct wps_er_ap * wps_er_ap_get(struct wps_er *er,
146                                         struct in_addr *addr)
147 {
148         struct wps_er_ap *ap;
149         for (ap = er->ap; ap; ap = ap->next) {
150                 if (ap->addr.s_addr == addr->s_addr)
151                         break;
152         }
153         return ap;
154 }
155
156
157 static struct wps_er_ap * wps_er_ap_get_id(struct wps_er *er, unsigned int id)
158 {
159         struct wps_er_ap *ap;
160         for (ap = er->ap; ap; ap = ap->next) {
161                 if (ap->id == id)
162                         break;
163         }
164         return ap;
165 }
166
167
168 static void wps_er_ap_free(struct wps_er *er, struct wps_er_ap *ap)
169 {
170         /* TODO: if ap->subscribed, unsubscribe from events if the AP is still
171          * alive */
172         wpa_printf(MSG_DEBUG, "WPS ER: Removing AP entry for %s (%s)",
173                    inet_ntoa(ap->addr), ap->location);
174         eloop_cancel_timeout(wps_er_ap_timeout, er, ap);
175         os_free(ap->location);
176         http_client_free(ap->http);
177
178         os_free(ap->friendly_name);
179         os_free(ap->manufacturer);
180         os_free(ap->manufacturer_url);
181         os_free(ap->model_description);
182         os_free(ap->model_name);
183         os_free(ap->model_number);
184         os_free(ap->model_url);
185         os_free(ap->serial_number);
186         os_free(ap->udn);
187         os_free(ap->upc);
188
189         os_free(ap->scpd_url);
190         os_free(ap->control_url);
191         os_free(ap->event_sub_url);
192
193         wps_er_sta_remove_all(ap);
194
195         os_free(ap);
196 }
197
198
199 static void wps_er_ap_timeout(void *eloop_data, void *user_ctx)
200 {
201         struct wps_er *er = eloop_data;
202         struct wps_er_ap *ap = user_ctx;
203         wpa_printf(MSG_DEBUG, "WPS ER: AP advertisement timed out");
204         wps_er_ap_free(er, ap);
205 }
206
207
208 static void wps_er_http_subscribe_cb(void *ctx, struct http_client *c,
209                                      enum http_client_event event)
210 {
211         struct wps_er_ap *ap = ctx;
212
213         switch (event) {
214         case HTTP_CLIENT_OK:
215                 wpa_printf(MSG_DEBUG, "WPS ER: Subscribed to events");
216                 break;
217         case HTTP_CLIENT_FAILED:
218         case HTTP_CLIENT_INVALID_REPLY:
219         case HTTP_CLIENT_TIMEOUT:
220                 wpa_printf(MSG_DEBUG, "WPS ER: Failed to subscribe to events");
221                 break;
222         }
223         http_client_free(ap->http);
224         ap->http = NULL;
225 }
226
227
228 static void wps_er_subscribe(struct wps_er_ap *ap)
229 {
230         struct wpabuf *req;
231         struct sockaddr_in dst;
232         char *url, *path;
233
234         if (ap->event_sub_url == NULL) {
235                 wpa_printf(MSG_DEBUG, "WPS ER: No eventSubURL - cannot "
236                            "subscribe");
237                 return;
238         }
239         if (ap->http) {
240                 wpa_printf(MSG_DEBUG, "WPS ER: Pending HTTP request - cannot "
241                            "send subscribe request");
242                 return;
243         }
244
245         url = http_client_url_parse(ap->event_sub_url, &dst, &path);
246         if (url == NULL) {
247                 wpa_printf(MSG_DEBUG, "WPS ER: Failed to parse eventSubURL");
248                 return;
249         }
250
251         req = wpabuf_alloc(os_strlen(ap->event_sub_url) + 1000);
252         if (req == NULL) {
253                 os_free(url);
254                 return;
255         }
256         wpabuf_printf(req,
257                       "SUBSCRIBE %s HTTP/1.1\r\n"
258                       "HOST: %s:%d\r\n"
259                       "CALLBACK: <http://%s:%d/event/%d>\r\n"
260                       "NT: upnp:event\r\n"
261                       "TIMEOUT: Second-%d\r\n"
262                       "\r\n",
263                       path, inet_ntoa(dst.sin_addr), ntohs(dst.sin_port),
264                       ap->er->ip_addr_text, ap->er->http_port, ap->id, 1800);
265         os_free(url);
266         wpa_hexdump_ascii(MSG_MSGDUMP, "WPS ER: Subscription request",
267                           wpabuf_head(req), wpabuf_len(req));
268
269         ap->http = http_client_addr(&dst, req, 1000, wps_er_http_subscribe_cb,
270                                     ap);
271         if (ap->http == NULL)
272                 wpabuf_free(req);
273 }
274
275
276 static void wps_er_parse_device_description(struct wps_er_ap *ap,
277                                             struct wpabuf *reply)
278 {
279         /* Note: reply includes null termination after the buffer data */
280         const char *data = wpabuf_head(reply);
281         char *pos;
282
283         wpa_hexdump_ascii(MSG_MSGDUMP, "WPS ER: Device info",
284                           wpabuf_head(reply), wpabuf_len(reply));
285
286         ap->friendly_name = xml_get_first_item(data, "friendlyName");
287         wpa_printf(MSG_DEBUG, "WPS ER: friendlyName='%s'", ap->friendly_name);
288
289         ap->manufacturer = xml_get_first_item(data, "manufacturer");
290         wpa_printf(MSG_DEBUG, "WPS ER: manufacturer='%s'", ap->manufacturer);
291
292         ap->manufacturer_url = xml_get_first_item(data, "manufacturerURL");
293         wpa_printf(MSG_DEBUG, "WPS ER: manufacturerURL='%s'",
294                    ap->manufacturer_url);
295
296         ap->model_description = xml_get_first_item(data, "modelDescription");
297         wpa_printf(MSG_DEBUG, "WPS ER: modelDescription='%s'",
298                    ap->model_description);
299
300         ap->model_name = xml_get_first_item(data, "modelName");
301         wpa_printf(MSG_DEBUG, "WPS ER: modelName='%s'", ap->model_name);
302
303         ap->model_number = xml_get_first_item(data, "modelNumber");
304         wpa_printf(MSG_DEBUG, "WPS ER: modelNumber='%s'", ap->model_number);
305
306         ap->model_url = xml_get_first_item(data, "modelURL");
307         wpa_printf(MSG_DEBUG, "WPS ER: modelURL='%s'", ap->model_url);
308
309         ap->serial_number = xml_get_first_item(data, "serialNumber");
310         wpa_printf(MSG_DEBUG, "WPS ER: serialNumber='%s'", ap->serial_number);
311
312         ap->udn = xml_get_first_item(data, "UDN");
313         wpa_printf(MSG_DEBUG, "WPS ER: UDN='%s'", ap->udn);
314         pos = os_strstr(ap->udn, "uuid:");
315         if (pos) {
316                 pos += 5;
317                 uuid_str2bin(pos, ap->uuid);
318         }
319
320         ap->upc = xml_get_first_item(data, "UPC");
321         wpa_printf(MSG_DEBUG, "WPS ER: UPC='%s'", ap->upc);
322
323         ap->scpd_url = http_link_update(
324                 xml_get_first_item(data, "SCPDURL"), ap->location);
325         wpa_printf(MSG_DEBUG, "WPS ER: SCPDURL='%s'", ap->scpd_url);
326
327         ap->control_url = http_link_update(
328                 xml_get_first_item(data, "controlURL"), ap->location);
329         wpa_printf(MSG_DEBUG, "WPS ER: controlURL='%s'", ap->control_url);
330
331         ap->event_sub_url = http_link_update(
332                 xml_get_first_item(data, "eventSubURL"), ap->location);
333         wpa_printf(MSG_DEBUG, "WPS ER: eventSubURL='%s'", ap->event_sub_url);
334 }
335
336
337 static void wps_er_http_dev_desc_cb(void *ctx, struct http_client *c,
338                                     enum http_client_event event)
339 {
340         struct wps_er_ap *ap = ctx;
341         struct wpabuf *reply;
342         int subscribe = 0;
343
344         switch (event) {
345         case HTTP_CLIENT_OK:
346                 reply = http_client_get_body(c);
347                 if (reply == NULL)
348                         break;
349                 wps_er_parse_device_description(ap, reply);
350                 subscribe = 1;
351                 break;
352         case HTTP_CLIENT_FAILED:
353         case HTTP_CLIENT_INVALID_REPLY:
354         case HTTP_CLIENT_TIMEOUT:
355                 wpa_printf(MSG_DEBUG, "WPS ER: Failed to fetch device info");
356                 break;
357         }
358         http_client_free(ap->http);
359         ap->http = NULL;
360         if (subscribe)
361                 wps_er_subscribe(ap);
362 }
363
364
365 static void wps_er_ap_add(struct wps_er *er, struct in_addr *addr,
366                           const char *location, int max_age)
367 {
368         struct wps_er_ap *ap;
369
370         ap = wps_er_ap_get(er, addr);
371         if (ap) {
372                 /* Update advertisement timeout */
373                 eloop_cancel_timeout(wps_er_ap_timeout, er, ap);
374                 eloop_register_timeout(max_age, 0, wps_er_ap_timeout, er, ap);
375                 return;
376         }
377
378         ap = os_zalloc(sizeof(*ap));
379         if (ap == NULL)
380                 return;
381         ap->er = er;
382         ap->id = ++er->next_ap_id;
383         ap->location = os_strdup(location);
384         if (ap->location == NULL) {
385                 os_free(ap);
386                 return;
387         }
388         ap->next = er->ap;
389         er->ap = ap;
390
391         ap->addr.s_addr = addr->s_addr;
392         eloop_register_timeout(max_age, 0, wps_er_ap_timeout, er, ap);
393
394         wpa_printf(MSG_DEBUG, "WPS ER: Added AP entry for %s (%s)",
395                    inet_ntoa(ap->addr), ap->location);
396
397         /* Fetch device description */
398         ap->http = http_client_url(ap->location, NULL, 10000,
399                                    wps_er_http_dev_desc_cb, ap);
400 }
401
402
403 static void wps_er_ap_remove(struct wps_er *er, struct in_addr *addr)
404 {
405         struct wps_er_ap *prev = NULL, *ap = er->ap;
406
407         while (ap) {
408                 if (ap->addr.s_addr == addr->s_addr) {
409                         if (prev)
410                                 prev->next = ap->next;
411                         else
412                                 er->ap = ap->next;
413                         wps_er_ap_free(er, ap);
414                         return;
415                 }
416                 prev = ap;
417                 ap = ap->next;
418         }
419 }
420
421
422 static void wps_er_ap_remove_all(struct wps_er *er)
423 {
424         struct wps_er_ap *prev, *ap;
425
426         ap = er->ap;
427         er->ap = NULL;
428
429         while (ap) {
430                 prev = ap;
431                 ap = ap->next;
432                 wps_er_ap_free(er, prev);
433         }
434 }
435
436
437 static void wps_er_ssdp_rx(int sd, void *eloop_ctx, void *sock_ctx)
438 {
439         struct wps_er *er = eloop_ctx;
440         struct sockaddr_in addr; /* client address */
441         socklen_t addr_len;
442         int nread;
443         char buf[MULTICAST_MAX_READ], *pos, *pos2, *start;
444         int wfa = 0, byebye = 0;
445         int max_age = -1;
446         char *location = NULL;
447
448         addr_len = sizeof(addr);
449         nread = recvfrom(sd, buf, sizeof(buf) - 1, 0,
450                          (struct sockaddr *) &addr, &addr_len);
451         if (nread <= 0)
452                 return;
453         buf[nread] = '\0';
454
455         wpa_printf(MSG_DEBUG, "WPS ER: Received SSDP from %s",
456                    inet_ntoa(addr.sin_addr));
457         wpa_hexdump_ascii(MSG_MSGDUMP, "WPS ER: Received SSDP contents",
458                           (u8 *) buf, nread);
459
460         if (sd == er->multicast_sd) {
461                 /* Reply to M-SEARCH */
462                 if (os_strncmp(buf, "HTTP/1.1 200 OK", 15) != 0)
463                         return; /* unexpected response header */
464         } else {
465                 /* Unsolicited message (likely NOTIFY or M-SEARCH) */
466                 if (os_strncmp(buf, "NOTIFY ", 7) != 0)
467                         return; /* only process notifications */
468         }
469
470         for (start = buf; start && *start; start = pos) {
471                 pos = os_strchr(start, '\n');
472                 if (pos) {
473                         if (pos[-1] == '\r')
474                                 pos[-1] = '\0';
475                         *pos++ = '\0';
476                 }
477                 if (os_strstr(start, "schemas-wifialliance-org:device:"
478                               "WFADevice:1"))
479                         wfa = 1;
480                 if (os_strstr(start, "schemas-wifialliance-org:service:"
481                               "WFAWLANConfig:1"))
482                         wfa = 1;
483                 if (os_strncasecmp(start, "LOCATION:", 9) == 0) {
484                         start += 9;
485                         while (*start == ' ')
486                                 start++;
487                         location = start;
488                 } else if (os_strncasecmp(start, "NTS:", 4) == 0) {
489                         if (os_strstr(start, "ssdp:byebye"))
490                                 byebye = 1;
491                 } else if (os_strncasecmp(start, "CACHE-CONTROL:", 14) == 0) {
492                         start += 9;
493                         while (*start == ' ')
494                                 start++;
495                         pos2 = os_strstr(start, "max-age=");
496                         if (pos2 == NULL)
497                                 continue;
498                         pos2 += 8;
499                         max_age = atoi(pos2);
500                 }
501         }
502
503         if (!wfa)
504                 return; /* Not WPS advertisement/reply */
505
506         if (byebye) {
507                 wps_er_ap_remove(er, &addr.sin_addr);
508                 return;
509         }
510
511         if (!location)
512                 return; /* Unknown location */
513
514         if (max_age < 1)
515                 return; /* No max-age reported */
516
517         wpa_printf(MSG_DEBUG, "WPS ER: AP discovered: %s "
518                    "(packet source: %s  max-age: %d)",
519                    location, inet_ntoa(addr.sin_addr), max_age);
520
521         wps_er_ap_add(er, &addr.sin_addr, location, max_age);
522 }
523
524
525 static void wps_er_send_ssdp_msearch(struct wps_er *er)
526 {
527         struct wpabuf *msg;
528         struct sockaddr_in dest;
529
530         msg = wpabuf_alloc(500);
531         if (msg == NULL)
532                 return;
533
534         wpabuf_put_str(msg,
535                        "M-SEARCH * HTTP/1.1\r\n"
536                        "HOST: 239.255.255.250:1900\r\n"
537                        "MAN: \"ssdp:discover\"\r\n"
538                        "MX: 3\r\n"
539                        "ST: urn:schemas-wifialliance-org:device:WFADevice:1"
540                        "\r\n"
541                        "\r\n");
542
543         os_memset(&dest, 0, sizeof(dest));
544         dest.sin_family = AF_INET;
545         dest.sin_addr.s_addr = inet_addr(UPNP_MULTICAST_ADDRESS);
546         dest.sin_port = htons(UPNP_MULTICAST_PORT);
547
548         if (sendto(er->multicast_sd, wpabuf_head(msg), wpabuf_len(msg), 0,
549                    (struct sockaddr *) &dest, sizeof(dest)) < 0)
550                 wpa_printf(MSG_DEBUG, "WPS ER: M-SEARCH sendto failed: "
551                            "%d (%s)", errno, strerror(errno));
552
553         wpabuf_free(msg);
554 }
555
556
557 static void http_put_date(struct wpabuf *buf)
558 {
559         wpabuf_put_str(buf, "Date: ");
560         format_date(buf);
561         wpabuf_put_str(buf, "\r\n");
562 }
563
564
565 static void wps_er_http_resp_not_found(struct http_request *req)
566 {
567         struct wpabuf *buf;
568         buf = wpabuf_alloc(200);
569         if (buf == NULL) {
570                 http_request_deinit(req);
571                 return;
572         }
573
574         wpabuf_put_str(buf,
575                        "HTTP/1.1 404 Not Found\r\n"
576                        "Server: unspecified, UPnP/1.0, unspecified\r\n"
577                        "Connection: close\r\n");
578         http_put_date(buf);
579         wpabuf_put_str(buf, "\r\n");
580         http_request_send_and_deinit(req, buf);
581 }
582
583
584 static void wps_er_http_resp_ok(struct http_request *req)
585 {
586         struct wpabuf *buf;
587         buf = wpabuf_alloc(200);
588         if (buf == NULL) {
589                 http_request_deinit(req);
590                 return;
591         }
592
593         wpabuf_put_str(buf,
594                        "HTTP/1.1 200 OK\r\n"
595                        "Server: unspecified, UPnP/1.0, unspecified\r\n"
596                        "Connection: close\r\n"
597                        "Content-Length: 0\r\n");
598         http_put_date(buf);
599         wpabuf_put_str(buf, "\r\n");
600         http_request_send_and_deinit(req, buf);
601 }
602
603
604 static void wps_er_sta_timeout(void *eloop_data, void *user_ctx)
605 {
606         struct wps_er_sta *sta = eloop_data;
607         wpa_printf(MSG_DEBUG, "WPS ER: STA entry timed out");
608         wps_er_sta_free(sta);
609 }
610
611
612 static struct wps_er_sta * wps_er_add_sta_data(struct wps_er_ap *ap,
613                                                const u8 *addr,
614                                                struct wps_parse_attr *attr,
615                                                int probe_req)
616 {
617         struct wps_er_sta *sta = wps_er_sta_get(ap, addr);
618
619         if (sta == NULL) {
620                 sta = os_zalloc(sizeof(*sta));
621                 if (sta == NULL)
622                         return NULL;
623                 os_memcpy(sta->addr, addr, ETH_ALEN);
624                 sta->ap = ap;
625                 sta->next = ap->sta;
626                 ap->sta = sta;
627         }
628
629         if (!probe_req)
630                 sta->m1_received = 1;
631
632         if (attr->config_methods && (!probe_req || !sta->m1_received))
633                 sta->config_methods = WPA_GET_BE16(attr->config_methods);
634         if (attr->uuid_e && (!probe_req || !sta->m1_received))
635                 os_memcpy(sta->uuid, attr->uuid_e, WPS_UUID_LEN);
636         if (attr->primary_dev_type && (!probe_req || !sta->m1_received))
637                 os_memcpy(sta->pri_dev_type, attr->primary_dev_type, 8);
638         if (attr->dev_password_id && (!probe_req || !sta->m1_received))
639                 sta->dev_passwd_id = WPA_GET_BE16(attr->dev_password_id);
640
641         if (attr->manufacturer) {
642                 os_free(sta->manufacturer);
643                 sta->manufacturer = os_malloc(attr->manufacturer_len + 1);
644                 if (sta->manufacturer) {
645                         os_memcpy(sta->manufacturer, attr->manufacturer,
646                                   attr->manufacturer_len);
647                         sta->manufacturer[attr->manufacturer_len] = '\0';
648                 }
649         }
650
651         if (attr->model_name) {
652                 os_free(sta->model_name);
653                 sta->model_name = os_malloc(attr->model_name_len + 1);
654                 if (sta->model_name) {
655                         os_memcpy(sta->model_name, attr->model_name,
656                                   attr->model_name_len);
657                         sta->model_name[attr->model_name_len] = '\0';
658                 }
659         }
660
661         if (attr->model_number) {
662                 os_free(sta->model_number);
663                 sta->model_number = os_malloc(attr->model_number_len + 1);
664                 if (sta->model_number) {
665                         os_memcpy(sta->model_number, attr->model_number,
666                                   attr->model_number_len);
667                         sta->model_number[attr->model_number_len] = '\0';
668                 }
669         }
670
671         if (attr->serial_number) {
672                 os_free(sta->serial_number);
673                 sta->serial_number = os_malloc(attr->serial_number_len + 1);
674                 if (sta->serial_number) {
675                         os_memcpy(sta->serial_number, attr->serial_number,
676                                   attr->serial_number_len);
677                         sta->serial_number[attr->serial_number_len] = '\0';
678                 }
679         }
680
681         if (attr->dev_name) {
682                 os_free(sta->dev_name);
683                 sta->dev_name = os_malloc(attr->dev_name_len + 1);
684                 if (sta->dev_name) {
685                         os_memcpy(sta->dev_name, attr->dev_name,
686                                   attr->dev_name_len);
687                         sta->dev_name[attr->dev_name_len] = '\0';
688                 }
689         }
690
691         eloop_cancel_timeout(wps_er_sta_timeout, sta, NULL);
692         eloop_register_timeout(300, 0, wps_er_sta_timeout, sta, NULL);
693
694         /* TODO: wpa_msg indication if new STA */
695
696         return sta;
697 }
698
699
700 static void wps_er_process_wlanevent_probe_req(struct wps_er_ap *ap,
701                                                const u8 *addr,
702                                                struct wpabuf *msg)
703 {
704         struct wps_parse_attr attr;
705
706         wpa_printf(MSG_DEBUG, "WPS ER: WLANEvent - Probe Request - from "
707                    MACSTR, MAC2STR(addr));
708         wpa_hexdump_buf(MSG_MSGDUMP, "WPS ER: WLANEvent - Enrollee's message "
709                         "(TLVs from Probe Request)", msg);
710
711         if (wps_parse_msg(msg, &attr) < 0) {
712                 wpa_printf(MSG_DEBUG, "WPS ER: Failed to parse TLVs in "
713                            "WLANEvent message");
714                 return;
715         }
716
717         wps_er_add_sta_data(ap, addr, &attr, 1);
718 }
719
720
721 static void wps_er_http_put_wlan_response_cb(void *ctx, struct http_client *c,
722                                              enum http_client_event event)
723 {
724         struct wps_er_sta *sta = ctx;
725
726         switch (event) {
727         case HTTP_CLIENT_OK:
728                 wpa_printf(MSG_DEBUG, "WPS ER: PutWLANResponse OK");
729                 break;
730         case HTTP_CLIENT_FAILED:
731         case HTTP_CLIENT_INVALID_REPLY:
732         case HTTP_CLIENT_TIMEOUT:
733                 wpa_printf(MSG_DEBUG, "WPS ER: PutWLANResponse failed");
734                 break;
735         }
736         http_client_free(sta->http);
737         sta->http = NULL;
738 }
739
740
741 static const char *soap_prefix =
742         "<?xml version=\"1.0\"?>\n"
743         "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" "
744         "s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">\n"
745         "<s:Body>\n";
746 static const char *soap_postfix =
747         "</s:Body>\n</s:Envelope>\n";
748 static const char *urn_wfawlanconfig =
749         "urn:schemas-wifialliance-org:service:WFAWLANConfig:1";
750
751 static struct wpabuf * wps_er_soap_hdr(const struct wpabuf *msg,
752                                        const char *name, const char *path,
753                                        const struct sockaddr_in *dst,
754                                        char **len_ptr, char **body_ptr)
755 {
756         unsigned char *encoded;
757         size_t encoded_len;
758         struct wpabuf *buf;
759
760         encoded = base64_encode(wpabuf_head(msg), wpabuf_len(msg),
761                                 &encoded_len);
762         if (encoded == NULL)
763                 return NULL;
764
765         buf = wpabuf_alloc(1000 + encoded_len);
766         if (buf == NULL) {
767                 os_free(encoded);
768                 return NULL;
769         }
770
771         wpabuf_printf(buf,
772                       "POST %s HTTP/1.1\r\n"
773                       "Host: %s:%d\r\n"
774                       "Content-Type: text/xml; charset=\"utf-8\"\r\n"
775                       "Content-Length: ",
776                       path, inet_ntoa(dst->sin_addr), ntohs(dst->sin_port));
777
778         *len_ptr = wpabuf_put(buf, 0);
779         wpabuf_printf(buf,
780                       "        \r\n"
781                       "SOAPACTION: \"%s#%s\"\r\n"
782                       "\r\n",
783                       urn_wfawlanconfig, name);
784
785         *body_ptr = wpabuf_put(buf, 0);
786
787         wpabuf_put_str(buf, soap_prefix);
788         wpabuf_printf(buf, "<u:%s xmlns:u=\"", name);
789         wpabuf_put_str(buf, urn_wfawlanconfig);
790         wpabuf_put_str(buf, "\">\n");
791         wpabuf_printf(buf, "<NewMessage>%s</NewMessage>\n", (char *) encoded);
792         os_free(encoded);
793
794         return buf;
795 }
796
797
798 static void wps_er_soap_end(struct wpabuf *buf, const char *name,
799                             char *len_ptr, char *body_ptr)
800 {
801         char len_buf[10];
802         wpabuf_printf(buf, "</u:%s>\n", name);
803         wpabuf_put_str(buf, soap_postfix);
804         os_snprintf(len_buf, sizeof(len_buf), "%d",
805                     (int) ((char *) wpabuf_put(buf, 0) - body_ptr));
806         os_memcpy(len_ptr, len_buf, os_strlen(len_buf));
807 }
808
809
810 static void wps_er_sta_send_msg(struct wps_er_sta *sta, struct wpabuf *msg)
811 {
812         struct wpabuf *buf;
813         char *len_ptr, *body_ptr;
814         struct sockaddr_in dst;
815         char *url, *path;
816
817         if (sta->http) {
818                 wpa_printf(MSG_DEBUG, "WPS ER: Pending HTTP request for STA - "
819                            "ignore new request");
820                 wpabuf_free(msg);
821                 return;
822         }
823
824         if (sta->ap->control_url == NULL) {
825                 wpa_printf(MSG_DEBUG, "WPS ER: No controlURL for AP");
826                 wpabuf_free(msg);
827                 return;
828         }
829
830         url = http_client_url_parse(sta->ap->control_url, &dst, &path);
831         if (url == NULL) {
832                 wpa_printf(MSG_DEBUG, "WPS ER: Failed to parse controlURL");
833                 wpabuf_free(msg);
834                 return;
835         }
836
837         buf = wps_er_soap_hdr(msg, "PutWLANResponse", path, &dst, &len_ptr,
838                               &body_ptr);
839         wpabuf_free(msg);
840         os_free(url);
841         if (buf == NULL)
842                 return;
843         wpabuf_printf(buf, "<NewWLANEventType>%d</NewWLANEventType>\n",
844                       UPNP_WPS_WLANEVENT_TYPE_EAP);
845         wpabuf_printf(buf, "<NewWLANEventMAC>" MACSTR "</NewWLANEventMAC>\n",
846                       MAC2STR(sta->addr));
847
848         wps_er_soap_end(buf, "PutWLANResponse", len_ptr, body_ptr);
849
850         sta->http = http_client_addr(&dst, buf, 1000,
851                                      wps_er_http_put_wlan_response_cb, sta);
852         if (sta->http == NULL)
853                 wpabuf_free(buf);
854 }
855
856
857 static void wps_er_sta_process(struct wps_er_sta *sta, struct wpabuf *msg,
858                                enum wsc_op_code op_code)
859 {
860         enum wps_process_res res;
861
862         res = wps_process_msg(sta->wps, op_code, msg);
863         if (res == WPS_CONTINUE) {
864                 struct wpabuf *next = wps_get_msg(sta->wps, &op_code);
865                 if (next)
866                         wps_er_sta_send_msg(sta, next);
867         }
868 }
869
870
871 static void wps_er_sta_start(struct wps_er_sta *sta, struct wpabuf *msg)
872 {
873         struct wps_config cfg;
874
875         if (sta->wps)
876                 wps_deinit(sta->wps);
877
878         os_memset(&cfg, 0, sizeof(cfg));
879         cfg.wps = sta->ap->er->wps;
880         cfg.registrar = 1;
881         cfg.peer_addr = sta->addr;
882
883         sta->wps = wps_init(&cfg);
884         if (sta->wps == NULL)
885                 return;
886
887         wps_er_sta_process(sta, msg, WSC_MSG);
888 }
889
890
891 static void wps_er_process_wlanevent_eap(struct wps_er_ap *ap, const u8 *addr,
892                                          struct wpabuf *msg)
893 {
894         struct wps_parse_attr attr;
895         struct wps_er_sta *sta;
896
897         wpa_printf(MSG_DEBUG, "WPS ER: WLANEvent - EAP - from " MACSTR,
898                    MAC2STR(addr));
899         wpa_hexdump_buf(MSG_MSGDUMP, "WPS ER: WLANEvent - Enrollee's message "
900                         "(TLVs from EAP-WSC)", msg);
901
902         if (wps_parse_msg(msg, &attr) < 0) {
903                 wpa_printf(MSG_DEBUG, "WPS ER: Failed to parse TLVs in "
904                            "WLANEvent message");
905                 return;
906         }
907
908         sta = wps_er_add_sta_data(ap, addr, &attr, 0);
909
910         if (attr.msg_type && *attr.msg_type == WPS_M1)
911                 wps_er_sta_start(sta, msg);
912         else if (sta->wps) {
913                 enum wsc_op_code op_code = WSC_MSG;
914                 if (attr.msg_type) {
915                         switch (*attr.msg_type) {
916                         case WPS_WSC_ACK:
917                                 op_code = WSC_ACK;
918                                 break;
919                         case WPS_WSC_NACK:
920                                 op_code = WSC_NACK;
921                                 break;
922                         case WPS_WSC_DONE:
923                                 op_code = WSC_Done;
924                                 break;
925                         }
926                 }
927                 wps_er_sta_process(sta, msg, op_code);
928         }
929 }
930
931
932 static void wps_er_process_wlanevent(struct wps_er_ap *ap,
933                                      struct wpabuf *event)
934 {
935         u8 *data;
936         u8 wlan_event_type;
937         u8 wlan_event_mac[ETH_ALEN];
938         struct wpabuf msg;
939
940         wpa_hexdump(MSG_MSGDUMP, "WPS ER: Received WLANEvent",
941                     wpabuf_head(event), wpabuf_len(event));
942         if (wpabuf_len(event) < 1 + 17) {
943                 wpa_printf(MSG_DEBUG, "WPS ER: Too short WLANEvent");
944                 return;
945         }
946
947         data = wpabuf_mhead(event);
948         wlan_event_type = data[0];
949         if (hwaddr_aton((char *) data + 1, wlan_event_mac) < 0) {
950                 wpa_printf(MSG_DEBUG, "WPS ER: Invalid WLANEventMAC in "
951                            "WLANEvent");
952                 return;
953         }
954
955         wpabuf_set(&msg, data + 1 + 17, wpabuf_len(event) - (1 + 17));
956
957         switch (wlan_event_type) {
958         case 1:
959                 wps_er_process_wlanevent_probe_req(ap, wlan_event_mac, &msg);
960                 break;
961         case 2:
962                 wps_er_process_wlanevent_eap(ap, wlan_event_mac, &msg);
963                 break;
964         default:
965                 wpa_printf(MSG_DEBUG, "WPS ER: Unknown WLANEventType %d",
966                            wlan_event_type);
967                 break;
968         }
969 }
970
971
972 static void wps_er_http_event(struct wps_er *er, struct http_request *req,
973                               unsigned int ap_id)
974 {
975         struct wps_er_ap *ap = wps_er_ap_get_id(er, ap_id);
976         struct wpabuf *event;
977         enum http_reply_code ret;
978
979         if (ap == NULL) {
980                 wpa_printf(MSG_DEBUG, "WPS ER: HTTP event from unknown AP id "
981                            "%u", ap_id);
982                 wps_er_http_resp_not_found(req);
983                 return;
984         }
985         wpa_printf(MSG_MSGDUMP, "WPS ER: HTTP event from AP id %u: %s",
986                    ap_id, http_request_get_data(req));
987
988         event = xml_get_base64_item(http_request_get_data(req), "WLANEvent",
989                                     &ret);
990         if (event == NULL) {
991                 wpa_printf(MSG_DEBUG, "WPS ER: Could not extract WLANEvent "
992                            "from the event notification");
993                 /*
994                  * Reply with OK anyway to avoid getting unregistered from
995                  * events.
996                  */
997                 wps_er_http_resp_ok(req);
998                 return;
999         }
1000
1001         wps_er_process_wlanevent(ap, event);
1002
1003         wpabuf_free(event);
1004         wps_er_http_resp_ok(req);
1005 }
1006
1007
1008 static void wps_er_http_notify(struct wps_er *er, struct http_request *req)
1009 {
1010         char *uri = http_request_get_uri(req);
1011
1012         if (os_strncmp(uri, "/event/", 7) == 0) {
1013                 wps_er_http_event(er, req, atoi(uri + 7));
1014         } else {
1015                 wpa_printf(MSG_DEBUG, "WPS ER: Unknown HTTP NOTIFY for '%s'",
1016                            uri);
1017                 wps_er_http_resp_not_found(req);
1018         }
1019 }
1020
1021
1022 static void wps_er_http_req(void *ctx, struct http_request *req)
1023 {
1024         struct wps_er *er = ctx;
1025         struct sockaddr_in *cli = http_request_get_cli_addr(req);
1026         enum httpread_hdr_type type = http_request_get_type(req);
1027         struct wpabuf *buf;
1028
1029         wpa_printf(MSG_DEBUG, "WPS ER: HTTP request: '%s' (type %d) from "
1030                    "%s:%d",
1031                    http_request_get_uri(req), type,
1032                    inet_ntoa(cli->sin_addr), ntohs(cli->sin_port));
1033
1034         switch (type) {
1035         case HTTPREAD_HDR_TYPE_NOTIFY:
1036                 wps_er_http_notify(er, req);
1037                 break;
1038         default:
1039                 wpa_printf(MSG_DEBUG, "WPS ER: Unsupported HTTP request type "
1040                            "%d", type);
1041                 buf = wpabuf_alloc(200);
1042                 if (buf == NULL) {
1043                         http_request_deinit(req);
1044                         return;
1045                 }
1046                 wpabuf_put_str(buf,
1047                                "HTTP/1.1 501 Unimplemented\r\n"
1048                                "Connection: close\r\n");
1049                 http_put_date(buf);
1050                 wpabuf_put_str(buf, "\r\n");
1051                 http_request_send_and_deinit(req, buf);
1052                 break;
1053         }
1054 }
1055
1056
1057 struct wps_er *
1058 wps_er_init(struct wps_context *wps, const char *ifname)
1059 {
1060         struct wps_er *er;
1061         struct in_addr addr;
1062
1063         er = os_zalloc(sizeof(*er));
1064         if (er == NULL)
1065                 return NULL;
1066
1067         er->multicast_sd = -1;
1068         er->ssdp_sd = -1;
1069
1070         os_strlcpy(er->ifname, ifname, sizeof(er->ifname));
1071         er->wps = wps;
1072
1073         if (get_netif_info(ifname,
1074                            &er->ip_addr, &er->ip_addr_text,
1075                            er->mac_addr, &er->mac_addr_text)) {
1076                 wpa_printf(MSG_INFO, "WPS UPnP: Could not get IP/MAC address "
1077                            "for %s. Does it have IP address?", ifname);
1078                 wps_er_deinit(er);
1079                 return NULL;
1080         }
1081
1082         if (add_ssdp_network(ifname)) {
1083                 wps_er_deinit(er);
1084                 return NULL;
1085         }
1086
1087         er->multicast_sd = ssdp_open_multicast_sock(er->ip_addr);
1088         if (er->multicast_sd < 0) {
1089                 wps_er_deinit(er);
1090                 return NULL;
1091         }
1092
1093         er->ssdp_sd = ssdp_listener_open();
1094         if (er->ssdp_sd < 0) {
1095                 wps_er_deinit(er);
1096                 return NULL;
1097         }
1098         if (eloop_register_sock(er->multicast_sd, EVENT_TYPE_READ,
1099                                 wps_er_ssdp_rx, er, NULL) ||
1100             eloop_register_sock(er->ssdp_sd, EVENT_TYPE_READ,
1101                                 wps_er_ssdp_rx, er, NULL)) {
1102                 wps_er_deinit(er);
1103                 return NULL;
1104         }
1105
1106         addr.s_addr = er->ip_addr;
1107         er->http_srv = http_server_init(&addr, -1, wps_er_http_req, er);
1108         if (er->http_srv == NULL) {
1109                 wps_er_deinit(er);
1110                 return NULL;
1111         }
1112         er->http_port = http_server_get_port(er->http_srv);
1113
1114         wpa_printf(MSG_DEBUG, "WPS ER: Start (ifname=%s ip_addr=%s "
1115                    "mac_addr=%s)",
1116                    er->ifname, er->ip_addr_text, er->mac_addr_text);
1117
1118         wps_er_send_ssdp_msearch(er);
1119
1120         return er;
1121 }
1122
1123
1124 void wps_er_deinit(struct wps_er *er)
1125 {
1126         if (er == NULL)
1127                 return;
1128         http_server_deinit(er->http_srv);
1129         wps_er_ap_remove_all(er);
1130         if (er->multicast_sd >= 0) {
1131                 eloop_unregister_sock(er->multicast_sd, EVENT_TYPE_READ);
1132                 close(er->multicast_sd);
1133         }
1134         if (er->ssdp_sd >= 0) {
1135                 eloop_unregister_sock(er->ssdp_sd, EVENT_TYPE_READ);
1136                 close(er->ssdp_sd);
1137         }
1138         os_free(er->ip_addr_text);
1139         os_free(er->mac_addr_text);
1140         os_free(er);
1141 }
1142
1143
1144 static void wps_er_http_set_sel_reg_cb(void *ctx, struct http_client *c,
1145                                        enum http_client_event event)
1146 {
1147         struct wps_er_ap *ap = ctx;
1148
1149         switch (event) {
1150         case HTTP_CLIENT_OK:
1151                 wpa_printf(MSG_DEBUG, "WPS ER: SetSelectedRegistrar OK");
1152                 break;
1153         case HTTP_CLIENT_FAILED:
1154         case HTTP_CLIENT_INVALID_REPLY:
1155         case HTTP_CLIENT_TIMEOUT:
1156                 wpa_printf(MSG_DEBUG, "WPS ER: SetSelectedRegistrar failed");
1157                 break;
1158         }
1159         http_client_free(ap->http);
1160         ap->http = NULL;
1161 }
1162
1163
1164 static void wps_er_send_set_sel_reg(struct wps_er_ap *ap, struct wpabuf *msg)
1165 {
1166         struct wpabuf *buf;
1167         char *len_ptr, *body_ptr;
1168         struct sockaddr_in dst;
1169         char *url, *path;
1170
1171         if (ap->control_url == NULL) {
1172                 wpa_printf(MSG_DEBUG, "WPS ER: No controlURL for AP");
1173                 return;
1174         }
1175
1176         if (ap->http) {
1177                 wpa_printf(MSG_DEBUG, "WPS ER: Pending HTTP request for AP - "
1178                            "ignore new request");
1179                 return;
1180         }
1181
1182         url = http_client_url_parse(ap->control_url, &dst, &path);
1183         if (url == NULL) {
1184                 wpa_printf(MSG_DEBUG, "WPS ER: Failed to parse controlURL");
1185                 return;
1186         }
1187
1188         buf = wps_er_soap_hdr(msg, "SetSelectedRegistrar", path, &dst,
1189                               &len_ptr, &body_ptr);
1190         os_free(url);
1191         if (buf == NULL)
1192                 return;
1193
1194         wps_er_soap_end(buf, "SetSelectedRegistrar", len_ptr, body_ptr);
1195
1196         ap->http = http_client_addr(&dst, buf, 1000,
1197                                     wps_er_http_set_sel_reg_cb, ap);
1198         if (ap->http == NULL)
1199                 wpabuf_free(buf);
1200 }
1201
1202
1203 static int wps_er_build_selected_registrar(struct wpabuf *msg, int sel_reg)
1204 {
1205         wpabuf_put_be16(msg, ATTR_SELECTED_REGISTRAR);
1206         wpabuf_put_be16(msg, 1);
1207         wpabuf_put_u8(msg, !!sel_reg);
1208         return 0;
1209 }
1210
1211
1212 static int wps_er_build_dev_password_id(struct wpabuf *msg, u16 dev_passwd_id)
1213 {
1214         wpabuf_put_be16(msg, ATTR_DEV_PASSWORD_ID);
1215         wpabuf_put_be16(msg, 2);
1216         wpabuf_put_be16(msg, dev_passwd_id);
1217         return 0;
1218 }
1219
1220
1221 static int wps_er_build_sel_reg_config_methods(struct wpabuf *msg,
1222                                                u16 sel_reg_config_methods)
1223 {
1224         wpabuf_put_be16(msg, ATTR_SELECTED_REGISTRAR_CONFIG_METHODS);
1225         wpabuf_put_be16(msg, 2);
1226         wpabuf_put_be16(msg, sel_reg_config_methods);
1227         return 0;
1228 }
1229
1230
1231 void wps_er_set_sel_reg(struct wps_er *er, int sel_reg, u16 dev_passwd_id,
1232                         u16 sel_reg_config_methods)
1233 {
1234         struct wpabuf *msg;
1235         struct wps_er_ap *ap;
1236
1237         msg = wpabuf_alloc(500);
1238         if (msg == NULL)
1239                 return;
1240
1241         if (wps_build_version(msg) ||
1242             wps_er_build_selected_registrar(msg, sel_reg) ||
1243             wps_er_build_dev_password_id(msg, dev_passwd_id) ||
1244             wps_er_build_sel_reg_config_methods(msg, sel_reg_config_methods)) {
1245                 wpabuf_free(msg);
1246                 return;
1247         }
1248
1249         for (ap = er->ap; ap; ap = ap->next)
1250                 wps_er_send_set_sel_reg(ap, msg);
1251
1252         wpabuf_free(msg);
1253 }