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