2 * Wi-Fi Protected Setup - External Registrar
3 * Copyright (c) 2009, Jouni Malinen <j@w1.fi>
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.
9 * Alternatively, this software may be distributed under the terms of BSD
12 * See README and COPYING for more details.
22 #include "http_client.h"
23 #include "http_server.h"
27 #include "wps_upnp_i.h"
31 static void wps_er_deinit_finish(void *eloop_data
, void *user_ctx
);
32 static void wps_er_ap_timeout(void *eloop_data
, void *user_ctx
);
33 static void wps_er_sta_timeout(void *eloop_data
, void *user_ctx
);
34 static void wps_er_ap_process(struct wps_er_ap
*ap
, struct wpabuf
*msg
);
35 static int wps_er_send_get_device_info(struct wps_er_ap
*ap
,
36 void (*m1_handler
)(struct wps_er_ap
*ap
,
40 static void wps_er_sta_event(struct wps_context
*wps
, struct wps_er_sta
*sta
,
43 union wps_event_data data
;
44 struct wps_event_er_enrollee
*ev
= &data
.enrollee
;
46 if (wps
->event_cb
== NULL
)
49 os_memset(&data
, 0, sizeof(data
));
51 ev
->mac_addr
= sta
->addr
;
52 ev
->m1_received
= sta
->m1_received
;
53 ev
->config_methods
= sta
->config_methods
;
54 ev
->dev_passwd_id
= sta
->dev_passwd_id
;
55 ev
->pri_dev_type
= sta
->pri_dev_type
;
56 ev
->dev_name
= sta
->dev_name
;
57 ev
->manufacturer
= sta
->manufacturer
;
58 ev
->model_name
= sta
->model_name
;
59 ev
->model_number
= sta
->model_number
;
60 ev
->serial_number
= sta
->serial_number
;
61 wps
->event_cb(wps
->cb_ctx
, event
, &data
);
65 static struct wps_er_sta
* wps_er_sta_get(struct wps_er_ap
*ap
, const u8
*addr
,
68 struct wps_er_sta
*sta
;
69 dl_list_for_each(sta
, &ap
->sta
, struct wps_er_sta
, list
) {
71 os_memcmp(sta
->addr
, addr
, ETH_ALEN
) == 0) &&
73 os_memcmp(uuid
, sta
->uuid
, WPS_UUID_LEN
) == 0))
80 static void wps_er_sta_free(struct wps_er_sta
*sta
)
82 wps_er_sta_event(sta
->ap
->er
->wps
, sta
, WPS_EV_ER_ENROLLEE_REMOVE
);
85 os_free(sta
->manufacturer
);
86 os_free(sta
->model_name
);
87 os_free(sta
->model_number
);
88 os_free(sta
->serial_number
);
89 os_free(sta
->dev_name
);
90 http_client_free(sta
->http
);
91 eloop_cancel_timeout(wps_er_sta_timeout
, sta
, NULL
);
97 static void wps_er_sta_remove_all(struct wps_er_ap
*ap
)
99 struct wps_er_sta
*prev
, *sta
;
100 dl_list_for_each_safe(sta
, prev
, &ap
->sta
, struct wps_er_sta
, list
)
101 wps_er_sta_free(sta
);
105 static struct wps_er_ap
* wps_er_ap_get(struct wps_er
*er
,
106 struct in_addr
*addr
, const u8
*uuid
)
108 struct wps_er_ap
*ap
;
109 dl_list_for_each(ap
, &er
->ap
, struct wps_er_ap
, list
) {
110 if ((addr
== NULL
|| ap
->addr
.s_addr
== addr
->s_addr
) &&
112 os_memcmp(uuid
, ap
->uuid
, WPS_UUID_LEN
) == 0))
119 static struct wps_er_ap
* wps_er_ap_get_id(struct wps_er
*er
, unsigned int id
)
121 struct wps_er_ap
*ap
;
122 dl_list_for_each(ap
, &er
->ap
, struct wps_er_ap
, list
) {
130 static void wps_er_ap_event(struct wps_context
*wps
, struct wps_er_ap
*ap
,
131 enum wps_event event
)
133 union wps_event_data data
;
134 struct wps_event_er_ap
*evap
= &data
.ap
;
136 if (wps
->event_cb
== NULL
)
139 os_memset(&data
, 0, sizeof(data
));
140 evap
->uuid
= ap
->uuid
;
141 evap
->friendly_name
= ap
->friendly_name
;
142 evap
->manufacturer
= ap
->manufacturer
;
143 evap
->manufacturer_url
= ap
->manufacturer_url
;
144 evap
->model_description
= ap
->model_description
;
145 evap
->model_name
= ap
->model_name
;
146 evap
->model_number
= ap
->model_number
;
147 evap
->model_url
= ap
->model_url
;
148 evap
->serial_number
= ap
->serial_number
;
150 evap
->pri_dev_type
= ap
->pri_dev_type
;
151 evap
->wps_state
= ap
->wps_state
;
152 evap
->mac_addr
= ap
->mac_addr
;
153 wps
->event_cb(wps
->cb_ctx
, event
, &data
);
157 static void wps_er_ap_free(struct wps_er_ap
*ap
)
159 http_client_free(ap
->http
);
162 os_free(ap
->location
);
163 os_free(ap
->friendly_name
);
164 os_free(ap
->manufacturer
);
165 os_free(ap
->manufacturer_url
);
166 os_free(ap
->model_description
);
167 os_free(ap
->model_name
);
168 os_free(ap
->model_number
);
169 os_free(ap
->model_url
);
170 os_free(ap
->serial_number
);
174 os_free(ap
->scpd_url
);
175 os_free(ap
->control_url
);
176 os_free(ap
->event_sub_url
);
178 os_free(ap
->ap_settings
);
184 static void wps_er_ap_unsubscribed(struct wps_er
*er
, struct wps_er_ap
*ap
)
186 wpa_printf(MSG_DEBUG
, "WPS ER: Unsubscribed from AP %s (%s)",
187 inet_ntoa(ap
->addr
), ap
->location
);
188 dl_list_del(&ap
->list
);
191 if (er
->deinitializing
&& dl_list_empty(&er
->ap_unsubscribing
)) {
192 eloop_cancel_timeout(wps_er_deinit_finish
, er
, NULL
);
193 wps_er_deinit_finish(er
, NULL
);
198 static void wps_er_http_unsubscribe_cb(void *ctx
, struct http_client
*c
,
199 enum http_client_event event
)
201 struct wps_er_ap
*ap
= ctx
;
205 wpa_printf(MSG_DEBUG
, "WPS ER: Unsubscribed from events");
208 case HTTP_CLIENT_FAILED
:
209 case HTTP_CLIENT_INVALID_REPLY
:
210 case HTTP_CLIENT_TIMEOUT
:
211 wpa_printf(MSG_DEBUG
, "WPS ER: Failed to unsubscribe from "
215 http_client_free(ap
->http
);
219 * Need to get rid of the AP entry regardless of whether we managed to
220 * unsubscribe cleanly or not.
222 wps_er_ap_unsubscribed(ap
->er
, ap
);
226 static void wps_er_ap_unsubscribe(struct wps_er
*er
, struct wps_er_ap
*ap
)
229 struct sockaddr_in dst
;
233 if (ap
->event_sub_url
== NULL
) {
234 wpa_printf(MSG_DEBUG
, "WPS ER: No eventSubURL - cannot "
239 wpa_printf(MSG_DEBUG
, "WPS ER: Pending HTTP request - cannot "
240 "send subscribe request");
244 url
= http_client_url_parse(ap
->event_sub_url
, &dst
, &path
);
246 wpa_printf(MSG_DEBUG
, "WPS ER: Failed to parse eventSubURL");
250 req
= wpabuf_alloc(os_strlen(ap
->event_sub_url
) + 1000);
255 uuid_bin2str(ap
->sid
, sid
, sizeof(sid
));
257 "UNSUBSCRIBE %s HTTP/1.1\r\n"
261 path
, inet_ntoa(dst
.sin_addr
), ntohs(dst
.sin_port
), sid
);
263 wpa_hexdump_ascii(MSG_MSGDUMP
, "WPS ER: Unsubscription request",
264 wpabuf_head(req
), wpabuf_len(req
));
266 ap
->http
= http_client_addr(&dst
, req
, 1000,
267 wps_er_http_unsubscribe_cb
, ap
);
268 if (ap
->http
== NULL
) {
276 * Need to get rid of the AP entry even when we fail to unsubscribe
279 wps_er_ap_unsubscribed(ap
->er
, ap
);
283 static struct wps_er_ap_settings
* wps_er_ap_get_settings(struct wps_er
*er
,
286 struct wps_er_ap_settings
*s
;
287 dl_list_for_each(s
, &er
->ap_settings
, struct wps_er_ap_settings
, list
)
288 if (os_memcmp(uuid
, s
->uuid
, WPS_UUID_LEN
) == 0)
294 int wps_er_ap_cache_settings(struct wps_er
*er
, struct in_addr
*addr
)
296 struct wps_er_ap
*ap
;
297 struct wps_er_ap_settings
*settings
;
299 ap
= wps_er_ap_get(er
, addr
, NULL
);
300 if (ap
== NULL
|| ap
->ap_settings
== NULL
)
303 settings
= wps_er_ap_get_settings(er
, ap
->uuid
);
305 settings
= os_zalloc(sizeof(*settings
));
306 if (settings
== NULL
)
308 os_memcpy(settings
->uuid
, ap
->uuid
, WPS_UUID_LEN
);
309 dl_list_add(&er
->ap_settings
, &settings
->list
);
311 os_memcpy(&settings
->ap_settings
, ap
->ap_settings
,
312 sizeof(struct wps_credential
));
318 static int wps_er_ap_use_cached_settings(struct wps_er
*er
,
319 struct wps_er_ap
*ap
)
321 struct wps_er_ap_settings
*s
;
326 s
= wps_er_ap_get_settings(ap
->er
, ap
->uuid
);
330 ap
->ap_settings
= os_malloc(sizeof(*ap
->ap_settings
));
331 if (ap
->ap_settings
== NULL
)
334 os_memcpy(ap
->ap_settings
, &s
->ap_settings
, sizeof(*ap
->ap_settings
));
335 wpa_printf(MSG_DEBUG
, "WPS ER: Use cached AP settings");
340 static void wps_er_ap_remove_entry(struct wps_er
*er
, struct wps_er_ap
*ap
)
342 wpa_printf(MSG_DEBUG
, "WPS ER: Removing AP entry for %s (%s)",
343 inet_ntoa(ap
->addr
), ap
->location
);
344 eloop_cancel_timeout(wps_er_ap_timeout
, er
, ap
);
345 wps_er_sta_remove_all(ap
);
346 wps_er_ap_event(er
->wps
, ap
, WPS_EV_ER_AP_REMOVE
);
347 http_client_free(ap
->http
);
354 dl_list_del(&ap
->list
);
355 if (ap
->subscribed
) {
356 dl_list_add(&er
->ap_unsubscribing
, &ap
->list
);
357 wps_er_ap_unsubscribe(er
, ap
);
363 static void wps_er_ap_timeout(void *eloop_data
, void *user_ctx
)
365 struct wps_er
*er
= eloop_data
;
366 struct wps_er_ap
*ap
= user_ctx
;
367 wpa_printf(MSG_DEBUG
, "WPS ER: AP advertisement timed out");
368 wps_er_ap_remove_entry(er
, ap
);
372 static int wps_er_get_sid(struct wps_er_ap
*ap
, char *sid
)
378 wpa_printf(MSG_DEBUG
, "WPS ER: No SID received from %s (%s)",
379 inet_ntoa(ap
->addr
), ap
->location
);
383 pos
= os_strstr(sid
, "uuid:");
385 wpa_printf(MSG_DEBUG
, "WPS ER: Invalid SID received from "
386 "%s (%s): '%s'", inet_ntoa(ap
->addr
), ap
->location
,
392 if (uuid_str2bin(pos
, ap
->sid
) < 0) {
393 wpa_printf(MSG_DEBUG
, "WPS ER: Invalid SID received from "
394 "%s (%s): '%s'", inet_ntoa(ap
->addr
), ap
->location
,
399 uuid_bin2str(ap
->sid
, txt
, sizeof(txt
));
400 wpa_printf(MSG_DEBUG
, "WPS ER: SID for subscription with %s (%s): %s",
401 inet_ntoa(ap
->addr
), ap
->location
, txt
);
407 static void wps_er_http_subscribe_cb(void *ctx
, struct http_client
*c
,
408 enum http_client_event event
)
410 struct wps_er_ap
*ap
= ctx
;
414 wpa_printf(MSG_DEBUG
, "WPS ER: Subscribed to events");
416 wps_er_get_sid(ap
, http_client_get_hdr_line(c
, "SID"));
417 wps_er_ap_use_cached_settings(ap
->er
, ap
);
418 wps_er_ap_event(ap
->er
->wps
, ap
, WPS_EV_ER_AP_ADD
);
420 case HTTP_CLIENT_FAILED
:
421 case HTTP_CLIENT_INVALID_REPLY
:
422 case HTTP_CLIENT_TIMEOUT
:
423 wpa_printf(MSG_DEBUG
, "WPS ER: Failed to subscribe to events");
426 http_client_free(ap
->http
);
431 static void wps_er_subscribe(struct wps_er_ap
*ap
)
434 struct sockaddr_in dst
;
437 if (ap
->event_sub_url
== NULL
) {
438 wpa_printf(MSG_DEBUG
, "WPS ER: No eventSubURL - cannot "
443 wpa_printf(MSG_DEBUG
, "WPS ER: Pending HTTP request - cannot "
444 "send subscribe request");
448 url
= http_client_url_parse(ap
->event_sub_url
, &dst
, &path
);
450 wpa_printf(MSG_DEBUG
, "WPS ER: Failed to parse eventSubURL");
454 req
= wpabuf_alloc(os_strlen(ap
->event_sub_url
) + 1000);
460 "SUBSCRIBE %s HTTP/1.1\r\n"
462 "CALLBACK: <http://%s:%d/event/%u/%u>\r\n"
464 "TIMEOUT: Second-%d\r\n"
466 path
, inet_ntoa(dst
.sin_addr
), ntohs(dst
.sin_port
),
467 ap
->er
->ip_addr_text
, ap
->er
->http_port
,
468 ap
->er
->event_id
, ap
->id
, 1800);
470 wpa_hexdump_ascii(MSG_MSGDUMP
, "WPS ER: Subscription request",
471 wpabuf_head(req
), wpabuf_len(req
));
473 ap
->http
= http_client_addr(&dst
, req
, 1000, wps_er_http_subscribe_cb
,
475 if (ap
->http
== NULL
)
480 static void wps_er_ap_get_m1(struct wps_er_ap
*ap
, struct wpabuf
*m1
)
482 struct wps_parse_attr attr
;
484 if (wps_parse_msg(m1
, &attr
) < 0) {
485 wpa_printf(MSG_DEBUG
, "WPS ER: Failed to parse M1");
488 if (attr
.primary_dev_type
)
489 os_memcpy(ap
->pri_dev_type
, attr
.primary_dev_type
, 8);
491 ap
->wps_state
= *attr
.wps_state
;
493 os_memcpy(ap
->mac_addr
, attr
.mac_addr
, ETH_ALEN
);
495 wps_er_subscribe(ap
);
499 static void wps_er_get_device_info(struct wps_er_ap
*ap
)
501 wps_er_send_get_device_info(ap
, wps_er_ap_get_m1
);
505 static const char * wps_er_find_wfadevice(const char *data
)
507 const char *tag
, *tagname
, *end
;
512 /* Find next <device> */
514 if (xml_next_tag(data
, &tag
, &tagname
, &end
))
517 if (!os_strncasecmp(tagname
, "device", 6) &&
519 (tagname
[6] == '>' || !isgraph(tagname
[6]))) {
524 /* Check whether deviceType is WFADevice */
525 val
= xml_get_first_item(data
, "deviceType");
528 wpa_printf(MSG_DEBUG
, "WPS ER: Found deviceType '%s'", val
);
529 found
= os_strcasecmp(val
, "urn:schemas-wifialliance-org:"
530 "device:WFADevice:1") == 0;
538 static void wps_er_parse_device_description(struct wps_er_ap
*ap
,
539 struct wpabuf
*reply
)
541 /* Note: reply includes null termination after the buffer data */
542 const char *tmp
, *data
= wpabuf_head(reply
);
545 wpa_hexdump_ascii(MSG_MSGDUMP
, "WPS ER: Device info",
546 wpabuf_head(reply
), wpabuf_len(reply
));
549 * The root device description may include multiple devices, so first
550 * find the beginning of the WFADevice description to allow the
551 * simplistic parser to pick the correct entries.
553 tmp
= wps_er_find_wfadevice(data
);
555 wpa_printf(MSG_DEBUG
, "WPS ER: WFADevice:1 device not found - "
556 "trying to parse invalid data");
560 ap
->friendly_name
= xml_get_first_item(data
, "friendlyName");
561 wpa_printf(MSG_DEBUG
, "WPS ER: friendlyName='%s'", ap
->friendly_name
);
563 ap
->manufacturer
= xml_get_first_item(data
, "manufacturer");
564 wpa_printf(MSG_DEBUG
, "WPS ER: manufacturer='%s'", ap
->manufacturer
);
566 ap
->manufacturer_url
= xml_get_first_item(data
, "manufacturerURL");
567 wpa_printf(MSG_DEBUG
, "WPS ER: manufacturerURL='%s'",
568 ap
->manufacturer_url
);
570 ap
->model_description
= xml_get_first_item(data
, "modelDescription");
571 wpa_printf(MSG_DEBUG
, "WPS ER: modelDescription='%s'",
572 ap
->model_description
);
574 ap
->model_name
= xml_get_first_item(data
, "modelName");
575 wpa_printf(MSG_DEBUG
, "WPS ER: modelName='%s'", ap
->model_name
);
577 ap
->model_number
= xml_get_first_item(data
, "modelNumber");
578 wpa_printf(MSG_DEBUG
, "WPS ER: modelNumber='%s'", ap
->model_number
);
580 ap
->model_url
= xml_get_first_item(data
, "modelURL");
581 wpa_printf(MSG_DEBUG
, "WPS ER: modelURL='%s'", ap
->model_url
);
583 ap
->serial_number
= xml_get_first_item(data
, "serialNumber");
584 wpa_printf(MSG_DEBUG
, "WPS ER: serialNumber='%s'", ap
->serial_number
);
586 ap
->udn
= xml_get_first_item(data
, "UDN");
587 wpa_printf(MSG_DEBUG
, "WPS ER: UDN='%s'", ap
->udn
);
588 pos
= os_strstr(ap
->udn
, "uuid:");
591 if (uuid_str2bin(pos
, ap
->uuid
) < 0)
592 wpa_printf(MSG_DEBUG
, "WPS ER: Invalid UUID in UDN");
595 ap
->upc
= xml_get_first_item(data
, "UPC");
596 wpa_printf(MSG_DEBUG
, "WPS ER: UPC='%s'", ap
->upc
);
598 ap
->scpd_url
= http_link_update(
599 xml_get_first_item(data
, "SCPDURL"), ap
->location
);
600 wpa_printf(MSG_DEBUG
, "WPS ER: SCPDURL='%s'", ap
->scpd_url
);
602 ap
->control_url
= http_link_update(
603 xml_get_first_item(data
, "controlURL"), ap
->location
);
604 wpa_printf(MSG_DEBUG
, "WPS ER: controlURL='%s'", ap
->control_url
);
606 ap
->event_sub_url
= http_link_update(
607 xml_get_first_item(data
, "eventSubURL"), ap
->location
);
608 wpa_printf(MSG_DEBUG
, "WPS ER: eventSubURL='%s'", ap
->event_sub_url
);
612 static void wps_er_http_dev_desc_cb(void *ctx
, struct http_client
*c
,
613 enum http_client_event event
)
615 struct wps_er_ap
*ap
= ctx
;
616 struct wpabuf
*reply
;
621 reply
= http_client_get_body(c
);
624 wps_er_parse_device_description(ap
, reply
);
627 case HTTP_CLIENT_FAILED
:
628 case HTTP_CLIENT_INVALID_REPLY
:
629 case HTTP_CLIENT_TIMEOUT
:
630 wpa_printf(MSG_DEBUG
, "WPS ER: Failed to fetch device info");
633 http_client_free(ap
->http
);
636 wps_er_get_device_info(ap
);
640 void wps_er_ap_add(struct wps_er
*er
, const u8
*uuid
, struct in_addr
*addr
,
641 const char *location
, int max_age
)
643 struct wps_er_ap
*ap
;
645 ap
= wps_er_ap_get(er
, addr
, uuid
);
647 /* Update advertisement timeout */
648 eloop_cancel_timeout(wps_er_ap_timeout
, er
, ap
);
649 eloop_register_timeout(max_age
, 0, wps_er_ap_timeout
, er
, ap
);
653 ap
= os_zalloc(sizeof(*ap
));
656 dl_list_init(&ap
->sta
);
658 ap
->id
= ++er
->next_ap_id
;
659 ap
->location
= os_strdup(location
);
660 if (ap
->location
== NULL
) {
664 dl_list_add(&er
->ap
, &ap
->list
);
666 ap
->addr
.s_addr
= addr
->s_addr
;
667 os_memcpy(ap
->uuid
, uuid
, WPS_UUID_LEN
);
668 eloop_register_timeout(max_age
, 0, wps_er_ap_timeout
, er
, ap
);
670 wpa_printf(MSG_DEBUG
, "WPS ER: Added AP entry for %s (%s)",
671 inet_ntoa(ap
->addr
), ap
->location
);
673 /* Fetch device description */
674 ap
->http
= http_client_url(ap
->location
, NULL
, 10000,
675 wps_er_http_dev_desc_cb
, ap
);
679 void wps_er_ap_remove(struct wps_er
*er
, struct in_addr
*addr
)
681 struct wps_er_ap
*ap
;
682 dl_list_for_each(ap
, &er
->ap
, struct wps_er_ap
, list
) {
683 if (ap
->addr
.s_addr
== addr
->s_addr
) {
684 wps_er_ap_remove_entry(er
, ap
);
691 static void wps_er_ap_remove_all(struct wps_er
*er
)
693 struct wps_er_ap
*prev
, *ap
;
694 struct wps_er_ap_settings
*prev_s
, *s
;
695 dl_list_for_each_safe(ap
, prev
, &er
->ap
, struct wps_er_ap
, list
)
696 wps_er_ap_remove_entry(er
, ap
);
697 dl_list_for_each_safe(s
, prev_s
, &er
->ap_settings
,
698 struct wps_er_ap_settings
, list
)
703 static void http_put_date(struct wpabuf
*buf
)
705 wpabuf_put_str(buf
, "Date: ");
707 wpabuf_put_str(buf
, "\r\n");
711 static void wps_er_http_resp_not_found(struct http_request
*req
)
714 buf
= wpabuf_alloc(200);
716 http_request_deinit(req
);
721 "HTTP/1.1 404 Not Found\r\n"
722 "Server: unspecified, UPnP/1.0, unspecified\r\n"
723 "Connection: close\r\n");
725 wpabuf_put_str(buf
, "\r\n");
726 http_request_send_and_deinit(req
, buf
);
730 static void wps_er_http_resp_ok(struct http_request
*req
)
733 buf
= wpabuf_alloc(200);
735 http_request_deinit(req
);
740 "HTTP/1.1 200 OK\r\n"
741 "Server: unspecified, UPnP/1.0, unspecified\r\n"
742 "Connection: close\r\n"
743 "Content-Length: 0\r\n");
745 wpabuf_put_str(buf
, "\r\n");
746 http_request_send_and_deinit(req
, buf
);
750 static void wps_er_sta_timeout(void *eloop_data
, void *user_ctx
)
752 struct wps_er_sta
*sta
= eloop_data
;
753 wpa_printf(MSG_DEBUG
, "WPS ER: STA entry timed out");
754 dl_list_del(&sta
->list
);
755 wps_er_sta_free(sta
);
759 static struct wps_er_sta
* wps_er_add_sta_data(struct wps_er_ap
*ap
,
761 struct wps_parse_attr
*attr
,
764 struct wps_er_sta
*sta
= wps_er_sta_get(ap
, addr
, NULL
);
768 m1
= !probe_req
&& attr
->msg_type
&& *attr
->msg_type
== WPS_M1
;
772 * Only allow new STA entry to be added based on Probe Request
773 * or M1. This will filter out bogus events and anything that
774 * may have been ongoing at the time ER subscribed for events.
776 if (!probe_req
&& !m1
)
779 sta
= os_zalloc(sizeof(*sta
));
782 os_memcpy(sta
->addr
, addr
, ETH_ALEN
);
784 dl_list_add(&ap
->sta
, &sta
->list
);
789 sta
->m1_received
= 1;
791 if (attr
->config_methods
&& (!probe_req
|| !sta
->m1_received
))
792 sta
->config_methods
= WPA_GET_BE16(attr
->config_methods
);
793 if (attr
->uuid_e
&& (!probe_req
|| !sta
->m1_received
))
794 os_memcpy(sta
->uuid
, attr
->uuid_e
, WPS_UUID_LEN
);
795 if (attr
->primary_dev_type
&& (!probe_req
|| !sta
->m1_received
))
796 os_memcpy(sta
->pri_dev_type
, attr
->primary_dev_type
, 8);
797 if (attr
->dev_password_id
&& (!probe_req
|| !sta
->m1_received
))
798 sta
->dev_passwd_id
= WPA_GET_BE16(attr
->dev_password_id
);
800 if (attr
->manufacturer
) {
801 os_free(sta
->manufacturer
);
802 sta
->manufacturer
= os_malloc(attr
->manufacturer_len
+ 1);
803 if (sta
->manufacturer
) {
804 os_memcpy(sta
->manufacturer
, attr
->manufacturer
,
805 attr
->manufacturer_len
);
806 sta
->manufacturer
[attr
->manufacturer_len
] = '\0';
810 if (attr
->model_name
) {
811 os_free(sta
->model_name
);
812 sta
->model_name
= os_malloc(attr
->model_name_len
+ 1);
813 if (sta
->model_name
) {
814 os_memcpy(sta
->model_name
, attr
->model_name
,
815 attr
->model_name_len
);
816 sta
->model_name
[attr
->model_name_len
] = '\0';
820 if (attr
->model_number
) {
821 os_free(sta
->model_number
);
822 sta
->model_number
= os_malloc(attr
->model_number_len
+ 1);
823 if (sta
->model_number
) {
824 os_memcpy(sta
->model_number
, attr
->model_number
,
825 attr
->model_number_len
);
826 sta
->model_number
[attr
->model_number_len
] = '\0';
830 if (attr
->serial_number
) {
831 os_free(sta
->serial_number
);
832 sta
->serial_number
= os_malloc(attr
->serial_number_len
+ 1);
833 if (sta
->serial_number
) {
834 os_memcpy(sta
->serial_number
, attr
->serial_number
,
835 attr
->serial_number_len
);
836 sta
->serial_number
[attr
->serial_number_len
] = '\0';
840 if (attr
->dev_name
) {
841 os_free(sta
->dev_name
);
842 sta
->dev_name
= os_malloc(attr
->dev_name_len
+ 1);
844 os_memcpy(sta
->dev_name
, attr
->dev_name
,
846 sta
->dev_name
[attr
->dev_name_len
] = '\0';
850 eloop_cancel_timeout(wps_er_sta_timeout
, sta
, NULL
);
851 eloop_register_timeout(300, 0, wps_er_sta_timeout
, sta
, NULL
);
854 wps_er_sta_event(ap
->er
->wps
, sta
, WPS_EV_ER_ENROLLEE_ADD
);
860 static void wps_er_process_wlanevent_probe_req(struct wps_er_ap
*ap
,
864 struct wps_parse_attr attr
;
866 wpa_printf(MSG_DEBUG
, "WPS ER: WLANEvent - Probe Request - from "
867 MACSTR
, MAC2STR(addr
));
868 wpa_hexdump_buf(MSG_MSGDUMP
, "WPS ER: WLANEvent - Enrollee's message "
869 "(TLVs from Probe Request)", msg
);
871 if (wps_validate_probe_req(msg
, addr
) < 0) {
872 wpa_printf(MSG_INFO
, "WPS-STRICT: ER: Ignore invalid proxied "
873 "Probe Request frame from " MACSTR
, MAC2STR(addr
));
877 if (wps_parse_msg(msg
, &attr
) < 0) {
878 wpa_printf(MSG_DEBUG
, "WPS ER: Failed to parse TLVs in "
879 "WLANEvent message");
883 wps_er_add_sta_data(ap
, addr
, &attr
, 1);
884 wps_registrar_probe_req_rx(ap
->er
->wps
->registrar
, addr
, msg
, 0);
888 static void wps_er_http_put_wlan_response_cb(void *ctx
, struct http_client
*c
,
889 enum http_client_event event
)
891 struct wps_er_sta
*sta
= ctx
;
895 wpa_printf(MSG_DEBUG
, "WPS ER: PutWLANResponse OK");
897 case HTTP_CLIENT_FAILED
:
898 case HTTP_CLIENT_INVALID_REPLY
:
899 case HTTP_CLIENT_TIMEOUT
:
900 wpa_printf(MSG_DEBUG
, "WPS ER: PutWLANResponse failed");
903 http_client_free(sta
->http
);
908 static const char *soap_prefix
=
909 "<?xml version=\"1.0\"?>\n"
910 "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" "
911 "s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">\n"
913 static const char *soap_postfix
=
914 "</s:Body>\n</s:Envelope>\n";
915 static const char *urn_wfawlanconfig
=
916 "urn:schemas-wifialliance-org:service:WFAWLANConfig:1";
918 static struct wpabuf
* wps_er_soap_hdr(const struct wpabuf
*msg
,
919 const char *name
, const char *arg_name
,
921 const struct sockaddr_in
*dst
,
922 char **len_ptr
, char **body_ptr
)
924 unsigned char *encoded
;
929 encoded
= base64_encode(wpabuf_head(msg
), wpabuf_len(msg
),
938 buf
= wpabuf_alloc(1000 + encoded_len
);
945 "POST %s HTTP/1.1\r\n"
947 "Content-Type: text/xml; charset=\"utf-8\"\r\n"
949 path
, inet_ntoa(dst
->sin_addr
), ntohs(dst
->sin_port
));
951 *len_ptr
= wpabuf_put(buf
, 0);
954 "SOAPACTION: \"%s#%s\"\r\n"
956 urn_wfawlanconfig
, name
);
958 *body_ptr
= wpabuf_put(buf
, 0);
960 wpabuf_put_str(buf
, soap_prefix
);
961 wpabuf_printf(buf
, "<u:%s xmlns:u=\"", name
);
962 wpabuf_put_str(buf
, urn_wfawlanconfig
);
963 wpabuf_put_str(buf
, "\">\n");
965 wpabuf_printf(buf
, "<%s>%s</%s>\n",
966 arg_name
, (char *) encoded
, arg_name
);
974 static void wps_er_soap_end(struct wpabuf
*buf
, const char *name
,
975 char *len_ptr
, char *body_ptr
)
978 wpabuf_printf(buf
, "</u:%s>\n", name
);
979 wpabuf_put_str(buf
, soap_postfix
);
980 os_snprintf(len_buf
, sizeof(len_buf
), "%d",
981 (int) ((char *) wpabuf_put(buf
, 0) - body_ptr
));
982 os_memcpy(len_ptr
, len_buf
, os_strlen(len_buf
));
986 static void wps_er_sta_send_msg(struct wps_er_sta
*sta
, struct wpabuf
*msg
)
989 char *len_ptr
, *body_ptr
;
990 struct sockaddr_in dst
;
994 wpa_printf(MSG_DEBUG
, "WPS ER: Pending HTTP request for STA - "
995 "ignore new request");
1000 if (sta
->ap
->control_url
== NULL
) {
1001 wpa_printf(MSG_DEBUG
, "WPS ER: No controlURL for AP");
1006 url
= http_client_url_parse(sta
->ap
->control_url
, &dst
, &path
);
1008 wpa_printf(MSG_DEBUG
, "WPS ER: Failed to parse controlURL");
1013 buf
= wps_er_soap_hdr(msg
, "PutWLANResponse", "NewMessage", path
, &dst
,
1014 &len_ptr
, &body_ptr
);
1019 wpabuf_printf(buf
, "<NewWLANEventType>%d</NewWLANEventType>\n",
1020 UPNP_WPS_WLANEVENT_TYPE_EAP
);
1021 wpabuf_printf(buf
, "<NewWLANEventMAC>" MACSTR
"</NewWLANEventMAC>\n",
1022 MAC2STR(sta
->addr
));
1024 wps_er_soap_end(buf
, "PutWLANResponse", len_ptr
, body_ptr
);
1026 sta
->http
= http_client_addr(&dst
, buf
, 1000,
1027 wps_er_http_put_wlan_response_cb
, sta
);
1028 if (sta
->http
== NULL
)
1033 static void wps_er_sta_process(struct wps_er_sta
*sta
, struct wpabuf
*msg
,
1034 enum wsc_op_code op_code
)
1036 enum wps_process_res res
;
1038 res
= wps_process_msg(sta
->wps
, op_code
, msg
);
1039 if (res
== WPS_CONTINUE
) {
1040 struct wpabuf
*next
= wps_get_msg(sta
->wps
, &op_code
);
1042 wps_er_sta_send_msg(sta
, next
);
1044 wpa_printf(MSG_DEBUG
, "WPS ER: Protocol run %s with the "
1045 "enrollee (res=%d)",
1046 res
== WPS_DONE
? "succeeded" : "failed", res
);
1047 wps_deinit(sta
->wps
);
1049 if (res
== WPS_DONE
) {
1050 /* Remove the STA entry after short timeout */
1051 eloop_cancel_timeout(wps_er_sta_timeout
, sta
, NULL
);
1052 eloop_register_timeout(10, 0, wps_er_sta_timeout
, sta
,
1059 static void wps_er_sta_start(struct wps_er_sta
*sta
, struct wpabuf
*msg
)
1061 struct wps_config cfg
;
1064 wps_deinit(sta
->wps
);
1066 os_memset(&cfg
, 0, sizeof(cfg
));
1067 cfg
.wps
= sta
->ap
->er
->wps
;
1069 cfg
.peer_addr
= sta
->addr
;
1071 sta
->wps
= wps_init(&cfg
);
1072 if (sta
->wps
== NULL
)
1075 sta
->wps
->use_cred
= sta
->ap
->ap_settings
;
1076 if (sta
->ap
->ap_settings
) {
1078 sta
->cred
= os_malloc(sizeof(*sta
->cred
));
1080 os_memcpy(sta
->cred
, sta
->ap
->ap_settings
,
1081 sizeof(*sta
->cred
));
1082 sta
->cred
->cred_attr
= NULL
;
1083 os_memcpy(sta
->cred
->mac_addr
, sta
->addr
, ETH_ALEN
);
1084 sta
->wps
->use_cred
= sta
->cred
;
1088 wps_er_sta_process(sta
, msg
, WSC_MSG
);
1092 static void wps_er_process_wlanevent_eap(struct wps_er_ap
*ap
, const u8
*addr
,
1095 struct wps_parse_attr attr
;
1096 struct wps_er_sta
*sta
;
1098 wpa_printf(MSG_DEBUG
, "WPS ER: WLANEvent - EAP - from " MACSTR
,
1100 wpa_hexdump_buf(MSG_MSGDUMP
, "WPS ER: WLANEvent - Enrollee's message "
1101 "(TLVs from EAP-WSC)", msg
);
1103 if (wps_parse_msg(msg
, &attr
) < 0) {
1104 wpa_printf(MSG_DEBUG
, "WPS ER: Failed to parse TLVs in "
1105 "WLANEvent message");
1109 sta
= wps_er_add_sta_data(ap
, addr
, &attr
, 0);
1113 if (attr
.msg_type
&& *attr
.msg_type
== WPS_M1
)
1114 wps_er_sta_start(sta
, msg
);
1115 else if (sta
->wps
) {
1116 enum wsc_op_code op_code
= WSC_MSG
;
1117 if (attr
.msg_type
) {
1118 switch (*attr
.msg_type
) {
1130 wps_er_sta_process(sta
, msg
, op_code
);
1135 static void wps_er_process_wlanevent(struct wps_er_ap
*ap
,
1136 struct wpabuf
*event
)
1140 u8 wlan_event_mac
[ETH_ALEN
];
1143 wpa_hexdump(MSG_MSGDUMP
, "WPS ER: Received WLANEvent",
1144 wpabuf_head(event
), wpabuf_len(event
));
1145 if (wpabuf_len(event
) < 1 + 17) {
1146 wpa_printf(MSG_DEBUG
, "WPS ER: Too short WLANEvent");
1150 data
= wpabuf_mhead(event
);
1151 wlan_event_type
= data
[0];
1152 if (hwaddr_aton((char *) data
+ 1, wlan_event_mac
) < 0) {
1153 wpa_printf(MSG_DEBUG
, "WPS ER: Invalid WLANEventMAC in "
1158 wpabuf_set(&msg
, data
+ 1 + 17, wpabuf_len(event
) - (1 + 17));
1160 switch (wlan_event_type
) {
1162 wps_er_process_wlanevent_probe_req(ap
, wlan_event_mac
, &msg
);
1165 wps_er_process_wlanevent_eap(ap
, wlan_event_mac
, &msg
);
1168 wpa_printf(MSG_DEBUG
, "WPS ER: Unknown WLANEventType %d",
1175 static void wps_er_http_event(struct wps_er
*er
, struct http_request
*req
,
1178 struct wps_er_ap
*ap
= wps_er_ap_get_id(er
, ap_id
);
1179 struct wpabuf
*event
;
1180 enum http_reply_code ret
;
1183 wpa_printf(MSG_DEBUG
, "WPS ER: HTTP event from unknown AP id "
1185 wps_er_http_resp_not_found(req
);
1188 wpa_printf(MSG_MSGDUMP
, "WPS ER: HTTP event from AP id %u: %s",
1189 ap_id
, http_request_get_data(req
));
1191 event
= xml_get_base64_item(http_request_get_data(req
), "WLANEvent",
1193 if (event
== NULL
) {
1194 wpa_printf(MSG_DEBUG
, "WPS ER: Could not extract WLANEvent "
1195 "from the event notification");
1197 * Reply with OK anyway to avoid getting unregistered from
1200 wps_er_http_resp_ok(req
);
1204 wps_er_process_wlanevent(ap
, event
);
1207 wps_er_http_resp_ok(req
);
1211 static void wps_er_http_notify(struct wps_er
*er
, struct http_request
*req
)
1213 char *uri
= http_request_get_uri(req
);
1215 if (os_strncmp(uri
, "/event/", 7) == 0) {
1216 unsigned int event_id
;
1218 event_id
= atoi(uri
+ 7);
1219 if (event_id
!= er
->event_id
) {
1220 wpa_printf(MSG_DEBUG
, "WPS ER: HTTP event for an "
1221 "unknown event id %u", event_id
);
1224 pos
= os_strchr(uri
+ 7, '/');
1228 wps_er_http_event(er
, req
, atoi(pos
));
1230 wpa_printf(MSG_DEBUG
, "WPS ER: Unknown HTTP NOTIFY for '%s'",
1232 wps_er_http_resp_not_found(req
);
1237 static void wps_er_http_req(void *ctx
, struct http_request
*req
)
1239 struct wps_er
*er
= ctx
;
1240 struct sockaddr_in
*cli
= http_request_get_cli_addr(req
);
1241 enum httpread_hdr_type type
= http_request_get_type(req
);
1244 wpa_printf(MSG_DEBUG
, "WPS ER: HTTP request: '%s' (type %d) from "
1246 http_request_get_uri(req
), type
,
1247 inet_ntoa(cli
->sin_addr
), ntohs(cli
->sin_port
));
1250 case HTTPREAD_HDR_TYPE_NOTIFY
:
1251 wps_er_http_notify(er
, req
);
1254 wpa_printf(MSG_DEBUG
, "WPS ER: Unsupported HTTP request type "
1256 buf
= wpabuf_alloc(200);
1258 http_request_deinit(req
);
1262 "HTTP/1.1 501 Unimplemented\r\n"
1263 "Connection: close\r\n");
1265 wpabuf_put_str(buf
, "\r\n");
1266 http_request_send_and_deinit(req
, buf
);
1273 wps_er_init(struct wps_context
*wps
, const char *ifname
, const char *filter
)
1276 struct in_addr addr
;
1278 er
= os_zalloc(sizeof(*er
));
1281 dl_list_init(&er
->ap
);
1282 dl_list_init(&er
->ap_unsubscribing
);
1283 dl_list_init(&er
->ap_settings
);
1285 er
->multicast_sd
= -1;
1288 os_strlcpy(er
->ifname
, ifname
, sizeof(er
->ifname
));
1290 if (os_get_random((unsigned char *) &er
->event_id
,
1291 sizeof(er
->event_id
)) < 0) {
1292 wps_er_deinit(er
, NULL
, NULL
);
1295 /* Limit event_id to < 32 bits to avoid issues with atoi() */
1296 er
->event_id
&= 0x0fffffff;
1299 if (inet_aton(filter
, &er
->filter_addr
) == 0) {
1300 wpa_printf(MSG_INFO
, "WPS UPnP: Invalid filter "
1301 "address %s", filter
);
1302 wps_er_deinit(er
, NULL
, NULL
);
1305 wpa_printf(MSG_DEBUG
, "WPS UPnP: Only accepting connections "
1308 if (get_netif_info(ifname
, &er
->ip_addr
, &er
->ip_addr_text
,
1310 wpa_printf(MSG_INFO
, "WPS UPnP: Could not get IP/MAC address "
1311 "for %s. Does it have IP address?", ifname
);
1312 wps_er_deinit(er
, NULL
, NULL
);
1316 if (wps_er_ssdp_init(er
) < 0) {
1317 wpa_printf(MSG_INFO
, "WPS UPnP: SSDP initialization failed");
1318 wps_er_deinit(er
, NULL
, NULL
);
1322 addr
.s_addr
= er
->ip_addr
;
1323 er
->http_srv
= http_server_init(&addr
, -1, wps_er_http_req
, er
);
1324 if (er
->http_srv
== NULL
) {
1325 wpa_printf(MSG_INFO
, "WPS UPnP: HTTP initialization failed");
1326 wps_er_deinit(er
, NULL
, NULL
);
1329 er
->http_port
= http_server_get_port(er
->http_srv
);
1331 wpa_printf(MSG_DEBUG
, "WPS ER: Start (ifname=%s ip_addr=%s)",
1332 er
->ifname
, er
->ip_addr_text
);
1338 void wps_er_refresh(struct wps_er
*er
)
1340 struct wps_er_ap
*ap
;
1341 struct wps_er_sta
*sta
;
1343 dl_list_for_each(ap
, &er
->ap
, struct wps_er_ap
, list
) {
1344 wps_er_ap_event(er
->wps
, ap
, WPS_EV_ER_AP_ADD
);
1345 dl_list_for_each(sta
, &ap
->sta
, struct wps_er_sta
, list
)
1346 wps_er_sta_event(er
->wps
, sta
, WPS_EV_ER_ENROLLEE_ADD
);
1349 wps_er_send_ssdp_msearch(er
);
1353 static void wps_er_deinit_finish(void *eloop_data
, void *user_ctx
)
1355 struct wps_er
*er
= eloop_data
;
1356 void (*deinit_done_cb
)(void *ctx
);
1357 void *deinit_done_ctx
;
1359 wpa_printf(MSG_DEBUG
, "WPS ER: Finishing deinit");
1361 deinit_done_cb
= er
->deinit_done_cb
;
1362 deinit_done_ctx
= er
->deinit_done_ctx
;
1363 os_free(er
->ip_addr_text
);
1367 deinit_done_cb(deinit_done_ctx
);
1371 void wps_er_deinit(struct wps_er
*er
, void (*cb
)(void *ctx
), void *ctx
)
1375 http_server_deinit(er
->http_srv
);
1376 wps_er_ap_remove_all(er
);
1377 wps_er_ssdp_deinit(er
);
1378 eloop_register_timeout(dl_list_empty(&er
->ap_unsubscribing
) ? 0 : 5, 0,
1379 wps_er_deinit_finish
, er
, NULL
);
1380 wpa_printf(MSG_DEBUG
, "WPS ER: Finish deinit from timeout");
1381 er
->deinitializing
= 1;
1382 er
->deinit_done_cb
= cb
;
1383 er
->deinit_done_ctx
= ctx
;
1387 static void wps_er_http_set_sel_reg_cb(void *ctx
, struct http_client
*c
,
1388 enum http_client_event event
)
1390 struct wps_er_ap
*ap
= ctx
;
1391 union wps_event_data data
;
1393 os_memset(&data
, 0, sizeof(data
));
1396 case HTTP_CLIENT_OK
:
1397 wpa_printf(MSG_DEBUG
, "WPS ER: SetSelectedRegistrar OK");
1398 data
.set_sel_reg
.state
= WPS_ER_SET_SEL_REG_DONE
;
1399 data
.set_sel_reg
.uuid
= ap
->uuid
;
1401 case HTTP_CLIENT_FAILED
:
1402 case HTTP_CLIENT_INVALID_REPLY
:
1403 case HTTP_CLIENT_TIMEOUT
:
1404 wpa_printf(MSG_DEBUG
, "WPS ER: SetSelectedRegistrar failed");
1405 data
.set_sel_reg
.state
= WPS_ER_SET_SEL_REG_FAILED
;
1406 data
.set_sel_reg
.uuid
= ap
->uuid
;
1409 http_client_free(ap
->http
);
1412 if (data
.set_sel_reg
.uuid
)
1413 ap
->er
->wps
->event_cb(ap
->er
->wps
->cb_ctx
,
1414 WPS_EV_ER_SET_SELECTED_REGISTRAR
, &data
);
1418 static void wps_er_send_set_sel_reg(struct wps_er_ap
*ap
, struct wpabuf
*msg
)
1421 char *len_ptr
, *body_ptr
;
1422 struct sockaddr_in dst
;
1425 if (ap
->control_url
== NULL
) {
1426 wpa_printf(MSG_DEBUG
, "WPS ER: No controlURL for AP");
1431 wpa_printf(MSG_DEBUG
, "WPS ER: Pending HTTP request for AP - "
1432 "ignore new request");
1437 wpa_printf(MSG_DEBUG
, "WPS ER: Pending WPS operation for AP - "
1438 "skip SetSelectedRegistrar");
1442 url
= http_client_url_parse(ap
->control_url
, &dst
, &path
);
1444 wpa_printf(MSG_DEBUG
, "WPS ER: Failed to parse controlURL");
1448 buf
= wps_er_soap_hdr(msg
, "SetSelectedRegistrar", "NewMessage", path
,
1449 &dst
, &len_ptr
, &body_ptr
);
1454 wps_er_soap_end(buf
, "SetSelectedRegistrar", len_ptr
, body_ptr
);
1456 ap
->http
= http_client_addr(&dst
, buf
, 1000,
1457 wps_er_http_set_sel_reg_cb
, ap
);
1458 if (ap
->http
== NULL
)
1463 static int wps_er_build_selected_registrar(struct wpabuf
*msg
, int sel_reg
)
1465 wpabuf_put_be16(msg
, ATTR_SELECTED_REGISTRAR
);
1466 wpabuf_put_be16(msg
, 1);
1467 wpabuf_put_u8(msg
, !!sel_reg
);
1472 static int wps_er_build_dev_password_id(struct wpabuf
*msg
, u16 dev_passwd_id
)
1474 wpabuf_put_be16(msg
, ATTR_DEV_PASSWORD_ID
);
1475 wpabuf_put_be16(msg
, 2);
1476 wpabuf_put_be16(msg
, dev_passwd_id
);
1481 static int wps_er_build_sel_reg_config_methods(struct wpabuf
*msg
,
1482 u16 sel_reg_config_methods
)
1484 wpabuf_put_be16(msg
, ATTR_SELECTED_REGISTRAR_CONFIG_METHODS
);
1485 wpabuf_put_be16(msg
, 2);
1486 wpabuf_put_be16(msg
, sel_reg_config_methods
);
1491 static int wps_er_build_uuid_r(struct wpabuf
*msg
, const u8
*uuid_r
)
1494 wpabuf_put_be16(msg
, ATTR_UUID_R
);
1495 wpabuf_put_be16(msg
, WPS_UUID_LEN
);
1496 wpabuf_put_data(msg
, uuid_r
, WPS_UUID_LEN
);
1497 #endif /* CONFIG_WPS2 */
1502 void wps_er_set_sel_reg(struct wps_er
*er
, int sel_reg
, u16 dev_passwd_id
,
1503 u16 sel_reg_config_methods
)
1506 struct wps_er_ap
*ap
;
1507 struct wps_registrar
*reg
= er
->wps
->registrar
;
1508 const u8
*auth_macs
;
1511 #endif /* CONFIG_WPS2 */
1513 union wps_event_data data
;
1515 if (er
->skip_set_sel_reg
) {
1516 wpa_printf(MSG_DEBUG
, "WPS ER: Skip SetSelectedRegistrar");
1520 msg
= wpabuf_alloc(500);
1524 auth_macs
= wps_authorized_macs(reg
, &count
);
1527 os_memset(bcast
, 0xff, ETH_ALEN
);
1531 #endif /* CONFIG_WPS2 */
1533 if (wps_build_version(msg
) ||
1534 wps_er_build_selected_registrar(msg
, sel_reg
) ||
1535 wps_er_build_dev_password_id(msg
, dev_passwd_id
) ||
1536 wps_er_build_sel_reg_config_methods(msg
, sel_reg_config_methods
) ||
1537 wps_build_wfa_ext(msg
, 0, auth_macs
, count
) ||
1538 wps_er_build_uuid_r(msg
, er
->wps
->uuid
)) {
1543 os_memset(&data
, 0, sizeof(data
));
1544 data
.set_sel_reg
.sel_reg
= sel_reg
;
1545 data
.set_sel_reg
.dev_passwd_id
= dev_passwd_id
;
1546 data
.set_sel_reg
.sel_reg_config_methods
= sel_reg_config_methods
;
1547 data
.set_sel_reg
.state
= WPS_ER_SET_SEL_REG_START
;
1549 dl_list_for_each(ap
, &er
->ap
, struct wps_er_ap
, list
) {
1550 if (er
->set_sel_reg_uuid_filter
&&
1551 os_memcmp(ap
->uuid
, er
->set_sel_reg_uuid_filter
,
1554 data
.set_sel_reg
.uuid
= ap
->uuid
;
1555 er
->wps
->event_cb(er
->wps
->cb_ctx
,
1556 WPS_EV_ER_SET_SELECTED_REGISTRAR
, &data
);
1557 wps_er_send_set_sel_reg(ap
, msg
);
1564 int wps_er_pbc(struct wps_er
*er
, const u8
*uuid
)
1567 struct wps_er_ap
*ap
;
1569 if (er
== NULL
|| er
->wps
== NULL
)
1572 if (wps_registrar_pbc_overlap(er
->wps
->registrar
, NULL
, NULL
)) {
1573 wpa_printf(MSG_DEBUG
, "WPS ER: PBC overlap - do not start PBC "
1578 ap
= wps_er_ap_get(er
, NULL
, uuid
);
1580 struct wps_er_sta
*sta
= NULL
;
1581 dl_list_for_each(ap
, &er
->ap
, struct wps_er_ap
, list
) {
1582 sta
= wps_er_sta_get(ap
, NULL
, uuid
);
1589 return -3; /* Unknown UUID */
1592 if (ap
->ap_settings
== NULL
) {
1593 wpa_printf(MSG_DEBUG
, "WPS ER: AP settings not known");
1597 er
->set_sel_reg_uuid_filter
= uuid
;
1598 res
= wps_registrar_button_pushed(er
->wps
->registrar
, NULL
);
1599 er
->set_sel_reg_uuid_filter
= NULL
;
1607 static void wps_er_ap_settings_cb(void *ctx
, const struct wps_credential
*cred
)
1609 struct wps_er_ap
*ap
= ctx
;
1610 union wps_event_data data
;
1612 wpa_printf(MSG_DEBUG
, "WPS ER: AP Settings received");
1613 os_free(ap
->ap_settings
);
1614 ap
->ap_settings
= os_malloc(sizeof(*cred
));
1615 if (ap
->ap_settings
) {
1616 os_memcpy(ap
->ap_settings
, cred
, sizeof(*cred
));
1617 ap
->ap_settings
->cred_attr
= NULL
;
1620 os_memset(&data
, 0, sizeof(data
));
1621 data
.ap_settings
.uuid
= ap
->uuid
;
1622 data
.ap_settings
.cred
= cred
;
1623 ap
->er
->wps
->event_cb(ap
->er
->wps
->cb_ctx
, WPS_EV_ER_AP_SETTINGS
,
1628 static void wps_er_http_put_message_cb(void *ctx
, struct http_client
*c
,
1629 enum http_client_event event
)
1631 struct wps_er_ap
*ap
= ctx
;
1632 struct wpabuf
*reply
;
1636 case HTTP_CLIENT_OK
:
1637 wpa_printf(MSG_DEBUG
, "WPS ER: PutMessage OK");
1638 reply
= http_client_get_body(c
);
1641 msg
= os_zalloc(wpabuf_len(reply
) + 1);
1644 os_memcpy(msg
, wpabuf_head(reply
), wpabuf_len(reply
));
1646 case HTTP_CLIENT_FAILED
:
1647 case HTTP_CLIENT_INVALID_REPLY
:
1648 case HTTP_CLIENT_TIMEOUT
:
1649 wpa_printf(MSG_DEBUG
, "WPS ER: PutMessage failed");
1651 wps_deinit(ap
->wps
);
1656 http_client_free(ap
->http
);
1661 enum http_reply_code ret
;
1662 buf
= xml_get_base64_item(msg
, "NewOutMessage", &ret
);
1665 wpa_printf(MSG_DEBUG
, "WPS ER: Could not extract "
1666 "NewOutMessage from PutMessage response");
1667 wps_deinit(ap
->wps
);
1671 wps_er_ap_process(ap
, buf
);
1677 static void wps_er_ap_put_message(struct wps_er_ap
*ap
,
1678 const struct wpabuf
*msg
)
1681 char *len_ptr
, *body_ptr
;
1682 struct sockaddr_in dst
;
1686 wpa_printf(MSG_DEBUG
, "WPS ER: Pending HTTP operation ongoing "
1687 "with the AP - cannot continue learn");
1691 if (ap
->control_url
== NULL
) {
1692 wpa_printf(MSG_DEBUG
, "WPS ER: No controlURL for AP");
1696 url
= http_client_url_parse(ap
->control_url
, &dst
, &path
);
1698 wpa_printf(MSG_DEBUG
, "WPS ER: Failed to parse controlURL");
1702 buf
= wps_er_soap_hdr(msg
, "PutMessage", "NewInMessage", path
, &dst
,
1703 &len_ptr
, &body_ptr
);
1708 wps_er_soap_end(buf
, "PutMessage", len_ptr
, body_ptr
);
1710 ap
->http
= http_client_addr(&dst
, buf
, 10000,
1711 wps_er_http_put_message_cb
, ap
);
1712 if (ap
->http
== NULL
)
1717 static void wps_er_ap_process(struct wps_er_ap
*ap
, struct wpabuf
*msg
)
1719 enum wps_process_res res
;
1720 struct wps_parse_attr attr
;
1721 enum wsc_op_code op_code
;
1724 if (wps_parse_msg(msg
, &attr
) == 0 && attr
.msg_type
) {
1725 switch (*attr
.msg_type
) {
1738 res
= wps_process_msg(ap
->wps
, op_code
, msg
);
1739 if (res
== WPS_CONTINUE
) {
1740 struct wpabuf
*next
= wps_get_msg(ap
->wps
, &op_code
);
1742 wps_er_ap_put_message(ap
, next
);
1745 wpa_printf(MSG_DEBUG
, "WPS ER: Failed to build "
1747 wps_deinit(ap
->wps
);
1750 } else if (res
== WPS_DONE
) {
1751 wpa_printf(MSG_DEBUG
, "WPS ER: Protocol run done");
1752 wps_deinit(ap
->wps
);
1755 wpa_printf(MSG_DEBUG
, "WPS ER: Failed to process message from "
1756 "AP (res=%d)", res
);
1757 wps_deinit(ap
->wps
);
1763 static void wps_er_ap_learn_m1(struct wps_er_ap
*ap
, struct wpabuf
*m1
)
1765 struct wps_config cfg
;
1768 wpa_printf(MSG_DEBUG
, "WPS ER: Protocol run already in "
1769 "progress with this AP");
1773 os_memset(&cfg
, 0, sizeof(cfg
));
1774 cfg
.wps
= ap
->er
->wps
;
1776 ap
->wps
= wps_init(&cfg
);
1777 if (ap
->wps
== NULL
)
1779 ap
->wps
->ap_settings_cb
= wps_er_ap_settings_cb
;
1780 ap
->wps
->ap_settings_cb_ctx
= ap
;
1782 wps_er_ap_process(ap
, m1
);
1786 static void wps_er_ap_learn(struct wps_er_ap
*ap
, const char *dev_info
)
1788 struct wpabuf
*info
;
1789 enum http_reply_code ret
;
1791 wpa_printf(MSG_DEBUG
, "WPS ER: Received GetDeviceInfo response (M1) "
1793 info
= xml_get_base64_item(dev_info
, "NewDeviceInfo", &ret
);
1795 wpa_printf(MSG_DEBUG
, "WPS ER: Could not extract "
1796 "NewDeviceInfo from GetDeviceInfo response");
1800 ap
->m1_handler(ap
, info
);
1805 static void wps_er_http_get_dev_info_cb(void *ctx
, struct http_client
*c
,
1806 enum http_client_event event
)
1808 struct wps_er_ap
*ap
= ctx
;
1809 struct wpabuf
*reply
;
1810 char *dev_info
= NULL
;
1813 case HTTP_CLIENT_OK
:
1814 wpa_printf(MSG_DEBUG
, "WPS ER: GetDeviceInfo OK");
1815 reply
= http_client_get_body(c
);
1818 dev_info
= os_zalloc(wpabuf_len(reply
) + 1);
1819 if (dev_info
== NULL
)
1821 os_memcpy(dev_info
, wpabuf_head(reply
), wpabuf_len(reply
));
1823 case HTTP_CLIENT_FAILED
:
1824 case HTTP_CLIENT_INVALID_REPLY
:
1825 case HTTP_CLIENT_TIMEOUT
:
1826 wpa_printf(MSG_DEBUG
, "WPS ER: GetDeviceInfo failed");
1829 http_client_free(ap
->http
);
1833 wps_er_ap_learn(ap
, dev_info
);
1839 static int wps_er_send_get_device_info(struct wps_er_ap
*ap
,
1840 void (*m1_handler
)(struct wps_er_ap
*ap
,
1844 char *len_ptr
, *body_ptr
;
1845 struct sockaddr_in dst
;
1849 wpa_printf(MSG_DEBUG
, "WPS ER: Pending HTTP operation ongoing "
1850 "with the AP - cannot get device info");
1854 if (ap
->control_url
== NULL
) {
1855 wpa_printf(MSG_DEBUG
, "WPS ER: No controlURL for AP");
1859 url
= http_client_url_parse(ap
->control_url
, &dst
, &path
);
1861 wpa_printf(MSG_DEBUG
, "WPS ER: Failed to parse controlURL");
1865 buf
= wps_er_soap_hdr(NULL
, "GetDeviceInfo", NULL
, path
, &dst
,
1866 &len_ptr
, &body_ptr
);
1871 wps_er_soap_end(buf
, "GetDeviceInfo", len_ptr
, body_ptr
);
1873 ap
->http
= http_client_addr(&dst
, buf
, 10000,
1874 wps_er_http_get_dev_info_cb
, ap
);
1875 if (ap
->http
== NULL
) {
1880 ap
->m1_handler
= m1_handler
;
1886 int wps_er_learn(struct wps_er
*er
, const u8
*uuid
, const u8
*pin
,
1889 struct wps_er_ap
*ap
;
1894 ap
= wps_er_ap_get(er
, NULL
, uuid
);
1896 wpa_printf(MSG_DEBUG
, "WPS ER: AP not found for learn "
1901 wpa_printf(MSG_DEBUG
, "WPS ER: Pending operation ongoing "
1902 "with the AP - cannot start learn");
1906 if (wps_er_send_get_device_info(ap
, wps_er_ap_learn_m1
) < 0)
1909 er
->skip_set_sel_reg
= 1;
1910 wps_registrar_add_pin(er
->wps
->registrar
, NULL
, uuid
, pin
, pin_len
, 0);
1911 er
->skip_set_sel_reg
= 0;
1917 int wps_er_set_config(struct wps_er
*er
, const u8
*uuid
,
1918 const struct wps_credential
*cred
)
1920 struct wps_er_ap
*ap
;
1925 ap
= wps_er_ap_get(er
, NULL
, uuid
);
1927 wpa_printf(MSG_DEBUG
, "WPS ER: AP not found for set config "
1932 os_free(ap
->ap_settings
);
1933 ap
->ap_settings
= os_malloc(sizeof(*cred
));
1934 if (ap
->ap_settings
== NULL
)
1936 os_memcpy(ap
->ap_settings
, cred
, sizeof(*cred
));
1937 ap
->ap_settings
->cred_attr
= NULL
;
1938 wpa_printf(MSG_DEBUG
, "WPS ER: Updated local AP settings based set "
1945 static void wps_er_ap_config_m1(struct wps_er_ap
*ap
, struct wpabuf
*m1
)
1947 struct wps_config cfg
;
1950 wpa_printf(MSG_DEBUG
, "WPS ER: Protocol run already in "
1951 "progress with this AP");
1955 os_memset(&cfg
, 0, sizeof(cfg
));
1956 cfg
.wps
= ap
->er
->wps
;
1958 cfg
.new_ap_settings
= ap
->ap_settings
;
1959 ap
->wps
= wps_init(&cfg
);
1960 if (ap
->wps
== NULL
)
1962 ap
->wps
->ap_settings_cb
= NULL
;
1963 ap
->wps
->ap_settings_cb_ctx
= NULL
;
1965 wps_er_ap_process(ap
, m1
);
1969 int wps_er_config(struct wps_er
*er
, const u8
*uuid
, const u8
*pin
,
1970 size_t pin_len
, const struct wps_credential
*cred
)
1972 struct wps_er_ap
*ap
;
1977 ap
= wps_er_ap_get(er
, NULL
, uuid
);
1979 wpa_printf(MSG_DEBUG
, "WPS ER: AP not found for config "
1984 wpa_printf(MSG_DEBUG
, "WPS ER: Pending operation ongoing "
1985 "with the AP - cannot start config");
1989 os_free(ap
->ap_settings
);
1990 ap
->ap_settings
= os_malloc(sizeof(*cred
));
1991 if (ap
->ap_settings
== NULL
)
1993 os_memcpy(ap
->ap_settings
, cred
, sizeof(*cred
));
1994 ap
->ap_settings
->cred_attr
= NULL
;
1996 if (wps_er_send_get_device_info(ap
, wps_er_ap_config_m1
) < 0)
1999 er
->skip_set_sel_reg
= 1;
2000 wps_registrar_add_pin(er
->wps
->registrar
, NULL
, uuid
, pin
, pin_len
, 0);
2001 er
->skip_set_sel_reg
= 0;