]> git.ipfire.org Git - thirdparty/hostap.git/blob - src/wps/wps_er.c
Do not disconnect STA based on inactivity on driver failure
[thirdparty/hostap.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 #include "wps_er.h"
29
30
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,
37 struct wpabuf *m1));
38
39
40 static void wps_er_sta_event(struct wps_context *wps, struct wps_er_sta *sta,
41 enum wps_event event)
42 {
43 union wps_event_data data;
44 struct wps_event_er_enrollee *ev = &data.enrollee;
45
46 if (wps->event_cb == NULL)
47 return;
48
49 os_memset(&data, 0, sizeof(data));
50 ev->uuid = sta->uuid;
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);
62 }
63
64
65 static struct wps_er_sta * wps_er_sta_get(struct wps_er_ap *ap, const u8 *addr,
66 const u8 *uuid)
67 {
68 struct wps_er_sta *sta;
69 dl_list_for_each(sta, &ap->sta, struct wps_er_sta, list) {
70 if ((addr == NULL ||
71 os_memcmp(sta->addr, addr, ETH_ALEN) == 0) &&
72 (uuid == NULL ||
73 os_memcmp(uuid, sta->uuid, WPS_UUID_LEN) == 0))
74 return sta;
75 }
76 return NULL;
77 }
78
79
80 static void wps_er_sta_free(struct wps_er_sta *sta)
81 {
82 wps_er_sta_event(sta->ap->er->wps, sta, WPS_EV_ER_ENROLLEE_REMOVE);
83 if (sta->wps)
84 wps_deinit(sta->wps);
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);
92 os_free(sta->cred);
93 os_free(sta);
94 }
95
96
97 static void wps_er_sta_remove_all(struct wps_er_ap *ap)
98 {
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);
102 }
103
104
105 static struct wps_er_ap * wps_er_ap_get(struct wps_er *er,
106 struct in_addr *addr, const u8 *uuid)
107 {
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) &&
111 (uuid == NULL ||
112 os_memcmp(uuid, ap->uuid, WPS_UUID_LEN) == 0))
113 return ap;
114 }
115 return NULL;
116 }
117
118
119 static struct wps_er_ap * wps_er_ap_get_id(struct wps_er *er, unsigned int id)
120 {
121 struct wps_er_ap *ap;
122 dl_list_for_each(ap, &er->ap, struct wps_er_ap, list) {
123 if (ap->id == id)
124 return ap;
125 }
126 return NULL;
127 }
128
129
130 static void wps_er_ap_event(struct wps_context *wps, struct wps_er_ap *ap,
131 enum wps_event event)
132 {
133 union wps_event_data data;
134 struct wps_event_er_ap *evap = &data.ap;
135
136 if (wps->event_cb == NULL)
137 return;
138
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;
149 evap->upc = ap->upc;
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);
154 }
155
156
157 static void wps_er_ap_free(struct wps_er_ap *ap)
158 {
159 http_client_free(ap->http);
160 ap->http = NULL;
161
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);
171 os_free(ap->udn);
172 os_free(ap->upc);
173
174 os_free(ap->scpd_url);
175 os_free(ap->control_url);
176 os_free(ap->event_sub_url);
177
178 os_free(ap->ap_settings);
179
180 os_free(ap);
181 }
182
183
184 static void wps_er_ap_unsubscribed(struct wps_er *er, struct wps_er_ap *ap)
185 {
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);
189 wps_er_ap_free(ap);
190
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);
194 }
195 }
196
197
198 static void wps_er_http_unsubscribe_cb(void *ctx, struct http_client *c,
199 enum http_client_event event)
200 {
201 struct wps_er_ap *ap = ctx;
202
203 switch (event) {
204 case HTTP_CLIENT_OK:
205 wpa_printf(MSG_DEBUG, "WPS ER: Unsubscribed from events");
206 ap->subscribed = 0;
207 break;
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 "
212 "events");
213 break;
214 }
215 http_client_free(ap->http);
216 ap->http = NULL;
217
218 /*
219 * Need to get rid of the AP entry regardless of whether we managed to
220 * unsubscribe cleanly or not.
221 */
222 wps_er_ap_unsubscribed(ap->er, ap);
223 }
224
225
226 static void wps_er_ap_unsubscribe(struct wps_er *er, struct wps_er_ap *ap)
227 {
228 struct wpabuf *req;
229 struct sockaddr_in dst;
230 char *url, *path;
231 char sid[100];
232
233 if (ap->event_sub_url == NULL) {
234 wpa_printf(MSG_DEBUG, "WPS ER: No eventSubURL - cannot "
235 "subscribe");
236 goto fail;
237 }
238 if (ap->http) {
239 wpa_printf(MSG_DEBUG, "WPS ER: Pending HTTP request - cannot "
240 "send subscribe request");
241 goto fail;
242 }
243
244 url = http_client_url_parse(ap->event_sub_url, &dst, &path);
245 if (url == NULL) {
246 wpa_printf(MSG_DEBUG, "WPS ER: Failed to parse eventSubURL");
247 goto fail;
248 }
249
250 req = wpabuf_alloc(os_strlen(ap->event_sub_url) + 1000);
251 if (req == NULL) {
252 os_free(url);
253 goto fail;
254 }
255 uuid_bin2str(ap->sid, sid, sizeof(sid));
256 wpabuf_printf(req,
257 "UNSUBSCRIBE %s HTTP/1.1\r\n"
258 "HOST: %s:%d\r\n"
259 "SID: uuid:%s\r\n"
260 "\r\n",
261 path, inet_ntoa(dst.sin_addr), ntohs(dst.sin_port), sid);
262 os_free(url);
263 wpa_hexdump_ascii(MSG_MSGDUMP, "WPS ER: Unsubscription request",
264 wpabuf_head(req), wpabuf_len(req));
265
266 ap->http = http_client_addr(&dst, req, 1000,
267 wps_er_http_unsubscribe_cb, ap);
268 if (ap->http == NULL) {
269 wpabuf_free(req);
270 goto fail;
271 }
272 return;
273
274 fail:
275 /*
276 * Need to get rid of the AP entry even when we fail to unsubscribe
277 * cleanly.
278 */
279 wps_er_ap_unsubscribed(ap->er, ap);
280 }
281
282
283 static struct wps_er_ap_settings * wps_er_ap_get_settings(struct wps_er *er,
284 const u8 *uuid)
285 {
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)
289 return s;
290 return NULL;
291 }
292
293
294 int wps_er_ap_cache_settings(struct wps_er *er, struct in_addr *addr)
295 {
296 struct wps_er_ap *ap;
297 struct wps_er_ap_settings *settings;
298
299 ap = wps_er_ap_get(er, addr, NULL);
300 if (ap == NULL || ap->ap_settings == NULL)
301 return -1;
302
303 settings = wps_er_ap_get_settings(er, ap->uuid);
304 if (!settings) {
305 settings = os_zalloc(sizeof(*settings));
306 if (settings == NULL)
307 return -1;
308 os_memcpy(settings->uuid, ap->uuid, WPS_UUID_LEN);
309 dl_list_add(&er->ap_settings, &settings->list);
310 }
311 os_memcpy(&settings->ap_settings, ap->ap_settings,
312 sizeof(struct wps_credential));
313
314 return 0;
315 }
316
317
318 static int wps_er_ap_use_cached_settings(struct wps_er *er,
319 struct wps_er_ap *ap)
320 {
321 struct wps_er_ap_settings *s;
322
323 if (ap->ap_settings)
324 return 0;
325
326 s = wps_er_ap_get_settings(ap->er, ap->uuid);
327 if (!s)
328 return -1;
329
330 ap->ap_settings = os_malloc(sizeof(*ap->ap_settings));
331 if (ap->ap_settings == NULL)
332 return -1;
333
334 os_memcpy(ap->ap_settings, &s->ap_settings, sizeof(*ap->ap_settings));
335 wpa_printf(MSG_DEBUG, "WPS ER: Use cached AP settings");
336 return 0;
337 }
338
339
340 static void wps_er_ap_remove_entry(struct wps_er *er, struct wps_er_ap *ap)
341 {
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);
348 ap->http = NULL;
349 if (ap->wps) {
350 wps_deinit(ap->wps);
351 ap->wps = NULL;
352 }
353
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);
358 } else
359 wps_er_ap_free(ap);
360 }
361
362
363 static void wps_er_ap_timeout(void *eloop_data, void *user_ctx)
364 {
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);
369 }
370
371
372 static int wps_er_get_sid(struct wps_er_ap *ap, char *sid)
373 {
374 char *pos;
375 char txt[100];
376
377 if (!sid) {
378 wpa_printf(MSG_DEBUG, "WPS ER: No SID received from %s (%s)",
379 inet_ntoa(ap->addr), ap->location);
380 return -1;
381 }
382
383 pos = os_strstr(sid, "uuid:");
384 if (!pos) {
385 wpa_printf(MSG_DEBUG, "WPS ER: Invalid SID received from "
386 "%s (%s): '%s'", inet_ntoa(ap->addr), ap->location,
387 sid);
388 return -1;
389 }
390
391 pos += 5;
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,
395 sid);
396 return -1;
397 }
398
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);
402
403 return 0;
404 }
405
406
407 static void wps_er_http_subscribe_cb(void *ctx, struct http_client *c,
408 enum http_client_event event)
409 {
410 struct wps_er_ap *ap = ctx;
411
412 switch (event) {
413 case HTTP_CLIENT_OK:
414 wpa_printf(MSG_DEBUG, "WPS ER: Subscribed to events");
415 ap->subscribed = 1;
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);
419 break;
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");
424 break;
425 }
426 http_client_free(ap->http);
427 ap->http = NULL;
428 }
429
430
431 static void wps_er_subscribe(struct wps_er_ap *ap)
432 {
433 struct wpabuf *req;
434 struct sockaddr_in dst;
435 char *url, *path;
436
437 if (ap->event_sub_url == NULL) {
438 wpa_printf(MSG_DEBUG, "WPS ER: No eventSubURL - cannot "
439 "subscribe");
440 return;
441 }
442 if (ap->http) {
443 wpa_printf(MSG_DEBUG, "WPS ER: Pending HTTP request - cannot "
444 "send subscribe request");
445 return;
446 }
447
448 url = http_client_url_parse(ap->event_sub_url, &dst, &path);
449 if (url == NULL) {
450 wpa_printf(MSG_DEBUG, "WPS ER: Failed to parse eventSubURL");
451 return;
452 }
453
454 req = wpabuf_alloc(os_strlen(ap->event_sub_url) + 1000);
455 if (req == NULL) {
456 os_free(url);
457 return;
458 }
459 wpabuf_printf(req,
460 "SUBSCRIBE %s HTTP/1.1\r\n"
461 "HOST: %s:%d\r\n"
462 "CALLBACK: <http://%s:%d/event/%u/%u>\r\n"
463 "NT: upnp:event\r\n"
464 "TIMEOUT: Second-%d\r\n"
465 "\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);
469 os_free(url);
470 wpa_hexdump_ascii(MSG_MSGDUMP, "WPS ER: Subscription request",
471 wpabuf_head(req), wpabuf_len(req));
472
473 ap->http = http_client_addr(&dst, req, 1000, wps_er_http_subscribe_cb,
474 ap);
475 if (ap->http == NULL)
476 wpabuf_free(req);
477 }
478
479
480 static void wps_er_ap_get_m1(struct wps_er_ap *ap, struct wpabuf *m1)
481 {
482 struct wps_parse_attr attr;
483
484 if (wps_parse_msg(m1, &attr) < 0) {
485 wpa_printf(MSG_DEBUG, "WPS ER: Failed to parse M1");
486 return;
487 }
488 if (attr.primary_dev_type)
489 os_memcpy(ap->pri_dev_type, attr.primary_dev_type, 8);
490 if (attr.wps_state)
491 ap->wps_state = *attr.wps_state;
492 if (attr.mac_addr)
493 os_memcpy(ap->mac_addr, attr.mac_addr, ETH_ALEN);
494
495 wps_er_subscribe(ap);
496 }
497
498
499 static void wps_er_get_device_info(struct wps_er_ap *ap)
500 {
501 wps_er_send_get_device_info(ap, wps_er_ap_get_m1);
502 }
503
504
505 static const char * wps_er_find_wfadevice(const char *data)
506 {
507 const char *tag, *tagname, *end;
508 char *val;
509 int found = 0;
510
511 while (!found) {
512 /* Find next <device> */
513 for (;;) {
514 if (xml_next_tag(data, &tag, &tagname, &end))
515 return NULL;
516 data = end;
517 if (!os_strncasecmp(tagname, "device", 6) &&
518 *tag != '/' &&
519 (tagname[6] == '>' || !isgraph(tagname[6]))) {
520 break;
521 }
522 }
523
524 /* Check whether deviceType is WFADevice */
525 val = xml_get_first_item(data, "deviceType");
526 if (val == NULL)
527 return NULL;
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;
531 os_free(val);
532 }
533
534 return data;
535 }
536
537
538 static void wps_er_parse_device_description(struct wps_er_ap *ap,
539 struct wpabuf *reply)
540 {
541 /* Note: reply includes null termination after the buffer data */
542 const char *tmp, *data = wpabuf_head(reply);
543 char *pos;
544
545 wpa_hexdump_ascii(MSG_MSGDUMP, "WPS ER: Device info",
546 wpabuf_head(reply), wpabuf_len(reply));
547
548 /*
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.
552 */
553 tmp = wps_er_find_wfadevice(data);
554 if (tmp == NULL) {
555 wpa_printf(MSG_DEBUG, "WPS ER: WFADevice:1 device not found - "
556 "trying to parse invalid data");
557 } else
558 data = tmp;
559
560 ap->friendly_name = xml_get_first_item(data, "friendlyName");
561 wpa_printf(MSG_DEBUG, "WPS ER: friendlyName='%s'", ap->friendly_name);
562
563 ap->manufacturer = xml_get_first_item(data, "manufacturer");
564 wpa_printf(MSG_DEBUG, "WPS ER: manufacturer='%s'", ap->manufacturer);
565
566 ap->manufacturer_url = xml_get_first_item(data, "manufacturerURL");
567 wpa_printf(MSG_DEBUG, "WPS ER: manufacturerURL='%s'",
568 ap->manufacturer_url);
569
570 ap->model_description = xml_get_first_item(data, "modelDescription");
571 wpa_printf(MSG_DEBUG, "WPS ER: modelDescription='%s'",
572 ap->model_description);
573
574 ap->model_name = xml_get_first_item(data, "modelName");
575 wpa_printf(MSG_DEBUG, "WPS ER: modelName='%s'", ap->model_name);
576
577 ap->model_number = xml_get_first_item(data, "modelNumber");
578 wpa_printf(MSG_DEBUG, "WPS ER: modelNumber='%s'", ap->model_number);
579
580 ap->model_url = xml_get_first_item(data, "modelURL");
581 wpa_printf(MSG_DEBUG, "WPS ER: modelURL='%s'", ap->model_url);
582
583 ap->serial_number = xml_get_first_item(data, "serialNumber");
584 wpa_printf(MSG_DEBUG, "WPS ER: serialNumber='%s'", ap->serial_number);
585
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:");
589 if (pos) {
590 pos += 5;
591 if (uuid_str2bin(pos, ap->uuid) < 0)
592 wpa_printf(MSG_DEBUG, "WPS ER: Invalid UUID in UDN");
593 }
594
595 ap->upc = xml_get_first_item(data, "UPC");
596 wpa_printf(MSG_DEBUG, "WPS ER: UPC='%s'", ap->upc);
597
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);
601
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);
605
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);
609 }
610
611
612 static void wps_er_http_dev_desc_cb(void *ctx, struct http_client *c,
613 enum http_client_event event)
614 {
615 struct wps_er_ap *ap = ctx;
616 struct wpabuf *reply;
617 int ok = 0;
618
619 switch (event) {
620 case HTTP_CLIENT_OK:
621 reply = http_client_get_body(c);
622 if (reply == NULL)
623 break;
624 wps_er_parse_device_description(ap, reply);
625 ok = 1;
626 break;
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");
631 break;
632 }
633 http_client_free(ap->http);
634 ap->http = NULL;
635 if (ok)
636 wps_er_get_device_info(ap);
637 }
638
639
640 void wps_er_ap_add(struct wps_er *er, const u8 *uuid, struct in_addr *addr,
641 const char *location, int max_age)
642 {
643 struct wps_er_ap *ap;
644
645 ap = wps_er_ap_get(er, addr, uuid);
646 if (ap) {
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);
650 return;
651 }
652
653 ap = os_zalloc(sizeof(*ap));
654 if (ap == NULL)
655 return;
656 dl_list_init(&ap->sta);
657 ap->er = er;
658 ap->id = ++er->next_ap_id;
659 ap->location = os_strdup(location);
660 if (ap->location == NULL) {
661 os_free(ap);
662 return;
663 }
664 dl_list_add(&er->ap, &ap->list);
665
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);
669
670 wpa_printf(MSG_DEBUG, "WPS ER: Added AP entry for %s (%s)",
671 inet_ntoa(ap->addr), ap->location);
672
673 /* Fetch device description */
674 ap->http = http_client_url(ap->location, NULL, 10000,
675 wps_er_http_dev_desc_cb, ap);
676 }
677
678
679 void wps_er_ap_remove(struct wps_er *er, struct in_addr *addr)
680 {
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);
685 return;
686 }
687 }
688 }
689
690
691 static void wps_er_ap_remove_all(struct wps_er *er)
692 {
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)
699 os_free(s);
700 }
701
702
703 static void http_put_date(struct wpabuf *buf)
704 {
705 wpabuf_put_str(buf, "Date: ");
706 format_date(buf);
707 wpabuf_put_str(buf, "\r\n");
708 }
709
710
711 static void wps_er_http_resp_not_found(struct http_request *req)
712 {
713 struct wpabuf *buf;
714 buf = wpabuf_alloc(200);
715 if (buf == NULL) {
716 http_request_deinit(req);
717 return;
718 }
719
720 wpabuf_put_str(buf,
721 "HTTP/1.1 404 Not Found\r\n"
722 "Server: unspecified, UPnP/1.0, unspecified\r\n"
723 "Connection: close\r\n");
724 http_put_date(buf);
725 wpabuf_put_str(buf, "\r\n");
726 http_request_send_and_deinit(req, buf);
727 }
728
729
730 static void wps_er_http_resp_ok(struct http_request *req)
731 {
732 struct wpabuf *buf;
733 buf = wpabuf_alloc(200);
734 if (buf == NULL) {
735 http_request_deinit(req);
736 return;
737 }
738
739 wpabuf_put_str(buf,
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");
744 http_put_date(buf);
745 wpabuf_put_str(buf, "\r\n");
746 http_request_send_and_deinit(req, buf);
747 }
748
749
750 static void wps_er_sta_timeout(void *eloop_data, void *user_ctx)
751 {
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);
756 }
757
758
759 static struct wps_er_sta * wps_er_add_sta_data(struct wps_er_ap *ap,
760 const u8 *addr,
761 struct wps_parse_attr *attr,
762 int probe_req)
763 {
764 struct wps_er_sta *sta = wps_er_sta_get(ap, addr, NULL);
765 int new_sta = 0;
766 int m1;
767
768 m1 = !probe_req && attr->msg_type && *attr->msg_type == WPS_M1;
769
770 if (sta == NULL) {
771 /*
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.
775 */
776 if (!probe_req && !m1)
777 return NULL;
778
779 sta = os_zalloc(sizeof(*sta));
780 if (sta == NULL)
781 return NULL;
782 os_memcpy(sta->addr, addr, ETH_ALEN);
783 sta->ap = ap;
784 dl_list_add(&ap->sta, &sta->list);
785 new_sta = 1;
786 }
787
788 if (m1)
789 sta->m1_received = 1;
790
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);
799
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';
807 }
808 }
809
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';
817 }
818 }
819
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';
827 }
828 }
829
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';
837 }
838 }
839
840 if (attr->dev_name) {
841 os_free(sta->dev_name);
842 sta->dev_name = os_malloc(attr->dev_name_len + 1);
843 if (sta->dev_name) {
844 os_memcpy(sta->dev_name, attr->dev_name,
845 attr->dev_name_len);
846 sta->dev_name[attr->dev_name_len] = '\0';
847 }
848 }
849
850 eloop_cancel_timeout(wps_er_sta_timeout, sta, NULL);
851 eloop_register_timeout(300, 0, wps_er_sta_timeout, sta, NULL);
852
853 if (m1 || new_sta)
854 wps_er_sta_event(ap->er->wps, sta, WPS_EV_ER_ENROLLEE_ADD);
855
856 return sta;
857 }
858
859
860 static void wps_er_process_wlanevent_probe_req(struct wps_er_ap *ap,
861 const u8 *addr,
862 struct wpabuf *msg)
863 {
864 struct wps_parse_attr attr;
865
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);
870
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));
874 return;
875 }
876
877 if (wps_parse_msg(msg, &attr) < 0) {
878 wpa_printf(MSG_DEBUG, "WPS ER: Failed to parse TLVs in "
879 "WLANEvent message");
880 return;
881 }
882
883 wps_er_add_sta_data(ap, addr, &attr, 1);
884 wps_registrar_probe_req_rx(ap->er->wps->registrar, addr, msg, 0);
885 }
886
887
888 static void wps_er_http_put_wlan_response_cb(void *ctx, struct http_client *c,
889 enum http_client_event event)
890 {
891 struct wps_er_sta *sta = ctx;
892
893 switch (event) {
894 case HTTP_CLIENT_OK:
895 wpa_printf(MSG_DEBUG, "WPS ER: PutWLANResponse OK");
896 break;
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");
901 break;
902 }
903 http_client_free(sta->http);
904 sta->http = NULL;
905 }
906
907
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"
912 "<s:Body>\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";
917
918 static struct wpabuf * wps_er_soap_hdr(const struct wpabuf *msg,
919 const char *name, const char *arg_name,
920 const char *path,
921 const struct sockaddr_in *dst,
922 char **len_ptr, char **body_ptr)
923 {
924 unsigned char *encoded;
925 size_t encoded_len;
926 struct wpabuf *buf;
927
928 if (msg) {
929 encoded = base64_encode(wpabuf_head(msg), wpabuf_len(msg),
930 &encoded_len);
931 if (encoded == NULL)
932 return NULL;
933 } else {
934 encoded = NULL;
935 encoded_len = 0;
936 }
937
938 buf = wpabuf_alloc(1000 + encoded_len);
939 if (buf == NULL) {
940 os_free(encoded);
941 return NULL;
942 }
943
944 wpabuf_printf(buf,
945 "POST %s HTTP/1.1\r\n"
946 "Host: %s:%d\r\n"
947 "Content-Type: text/xml; charset=\"utf-8\"\r\n"
948 "Content-Length: ",
949 path, inet_ntoa(dst->sin_addr), ntohs(dst->sin_port));
950
951 *len_ptr = wpabuf_put(buf, 0);
952 wpabuf_printf(buf,
953 " \r\n"
954 "SOAPACTION: \"%s#%s\"\r\n"
955 "\r\n",
956 urn_wfawlanconfig, name);
957
958 *body_ptr = wpabuf_put(buf, 0);
959
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");
964 if (encoded) {
965 wpabuf_printf(buf, "<%s>%s</%s>\n",
966 arg_name, (char *) encoded, arg_name);
967 os_free(encoded);
968 }
969
970 return buf;
971 }
972
973
974 static void wps_er_soap_end(struct wpabuf *buf, const char *name,
975 char *len_ptr, char *body_ptr)
976 {
977 char len_buf[10];
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));
983 }
984
985
986 static void wps_er_sta_send_msg(struct wps_er_sta *sta, struct wpabuf *msg)
987 {
988 struct wpabuf *buf;
989 char *len_ptr, *body_ptr;
990 struct sockaddr_in dst;
991 char *url, *path;
992
993 if (sta->http) {
994 wpa_printf(MSG_DEBUG, "WPS ER: Pending HTTP request for STA - "
995 "ignore new request");
996 wpabuf_free(msg);
997 return;
998 }
999
1000 if (sta->ap->control_url == NULL) {
1001 wpa_printf(MSG_DEBUG, "WPS ER: No controlURL for AP");
1002 wpabuf_free(msg);
1003 return;
1004 }
1005
1006 url = http_client_url_parse(sta->ap->control_url, &dst, &path);
1007 if (url == NULL) {
1008 wpa_printf(MSG_DEBUG, "WPS ER: Failed to parse controlURL");
1009 wpabuf_free(msg);
1010 return;
1011 }
1012
1013 buf = wps_er_soap_hdr(msg, "PutWLANResponse", "NewMessage", path, &dst,
1014 &len_ptr, &body_ptr);
1015 wpabuf_free(msg);
1016 os_free(url);
1017 if (buf == NULL)
1018 return;
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));
1023
1024 wps_er_soap_end(buf, "PutWLANResponse", len_ptr, body_ptr);
1025
1026 sta->http = http_client_addr(&dst, buf, 1000,
1027 wps_er_http_put_wlan_response_cb, sta);
1028 if (sta->http == NULL)
1029 wpabuf_free(buf);
1030 }
1031
1032
1033 static void wps_er_sta_process(struct wps_er_sta *sta, struct wpabuf *msg,
1034 enum wsc_op_code op_code)
1035 {
1036 enum wps_process_res res;
1037
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);
1041 if (next)
1042 wps_er_sta_send_msg(sta, next);
1043 } else {
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);
1048 sta->wps = NULL;
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,
1053 NULL);
1054 }
1055 }
1056 }
1057
1058
1059 static void wps_er_sta_start(struct wps_er_sta *sta, struct wpabuf *msg)
1060 {
1061 struct wps_config cfg;
1062
1063 if (sta->wps)
1064 wps_deinit(sta->wps);
1065
1066 os_memset(&cfg, 0, sizeof(cfg));
1067 cfg.wps = sta->ap->er->wps;
1068 cfg.registrar = 1;
1069 cfg.peer_addr = sta->addr;
1070
1071 sta->wps = wps_init(&cfg);
1072 if (sta->wps == NULL)
1073 return;
1074 sta->wps->er = 1;
1075 sta->wps->use_cred = sta->ap->ap_settings;
1076 if (sta->ap->ap_settings) {
1077 os_free(sta->cred);
1078 sta->cred = os_malloc(sizeof(*sta->cred));
1079 if (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;
1085 }
1086 }
1087
1088 wps_er_sta_process(sta, msg, WSC_MSG);
1089 }
1090
1091
1092 static void wps_er_process_wlanevent_eap(struct wps_er_ap *ap, const u8 *addr,
1093 struct wpabuf *msg)
1094 {
1095 struct wps_parse_attr attr;
1096 struct wps_er_sta *sta;
1097
1098 wpa_printf(MSG_DEBUG, "WPS ER: WLANEvent - EAP - from " MACSTR,
1099 MAC2STR(addr));
1100 wpa_hexdump_buf(MSG_MSGDUMP, "WPS ER: WLANEvent - Enrollee's message "
1101 "(TLVs from EAP-WSC)", msg);
1102
1103 if (wps_parse_msg(msg, &attr) < 0) {
1104 wpa_printf(MSG_DEBUG, "WPS ER: Failed to parse TLVs in "
1105 "WLANEvent message");
1106 return;
1107 }
1108
1109 sta = wps_er_add_sta_data(ap, addr, &attr, 0);
1110 if (sta == NULL)
1111 return;
1112
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) {
1119 case WPS_WSC_ACK:
1120 op_code = WSC_ACK;
1121 break;
1122 case WPS_WSC_NACK:
1123 op_code = WSC_NACK;
1124 break;
1125 case WPS_WSC_DONE:
1126 op_code = WSC_Done;
1127 break;
1128 }
1129 }
1130 wps_er_sta_process(sta, msg, op_code);
1131 }
1132 }
1133
1134
1135 static void wps_er_process_wlanevent(struct wps_er_ap *ap,
1136 struct wpabuf *event)
1137 {
1138 u8 *data;
1139 u8 wlan_event_type;
1140 u8 wlan_event_mac[ETH_ALEN];
1141 struct wpabuf msg;
1142
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");
1147 return;
1148 }
1149
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 "
1154 "WLANEvent");
1155 return;
1156 }
1157
1158 wpabuf_set(&msg, data + 1 + 17, wpabuf_len(event) - (1 + 17));
1159
1160 switch (wlan_event_type) {
1161 case 1:
1162 wps_er_process_wlanevent_probe_req(ap, wlan_event_mac, &msg);
1163 break;
1164 case 2:
1165 wps_er_process_wlanevent_eap(ap, wlan_event_mac, &msg);
1166 break;
1167 default:
1168 wpa_printf(MSG_DEBUG, "WPS ER: Unknown WLANEventType %d",
1169 wlan_event_type);
1170 break;
1171 }
1172 }
1173
1174
1175 static void wps_er_http_event(struct wps_er *er, struct http_request *req,
1176 unsigned int ap_id)
1177 {
1178 struct wps_er_ap *ap = wps_er_ap_get_id(er, ap_id);
1179 struct wpabuf *event;
1180 enum http_reply_code ret;
1181
1182 if (ap == NULL) {
1183 wpa_printf(MSG_DEBUG, "WPS ER: HTTP event from unknown AP id "
1184 "%u", ap_id);
1185 wps_er_http_resp_not_found(req);
1186 return;
1187 }
1188 wpa_printf(MSG_MSGDUMP, "WPS ER: HTTP event from AP id %u: %s",
1189 ap_id, http_request_get_data(req));
1190
1191 event = xml_get_base64_item(http_request_get_data(req), "WLANEvent",
1192 &ret);
1193 if (event == NULL) {
1194 wpa_printf(MSG_DEBUG, "WPS ER: Could not extract WLANEvent "
1195 "from the event notification");
1196 /*
1197 * Reply with OK anyway to avoid getting unregistered from
1198 * events.
1199 */
1200 wps_er_http_resp_ok(req);
1201 return;
1202 }
1203
1204 wps_er_process_wlanevent(ap, event);
1205
1206 wpabuf_free(event);
1207 wps_er_http_resp_ok(req);
1208 }
1209
1210
1211 static void wps_er_http_notify(struct wps_er *er, struct http_request *req)
1212 {
1213 char *uri = http_request_get_uri(req);
1214
1215 if (os_strncmp(uri, "/event/", 7) == 0) {
1216 unsigned int event_id;
1217 char *pos;
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);
1222 return;
1223 }
1224 pos = os_strchr(uri + 7, '/');
1225 if (pos == NULL)
1226 return;
1227 pos++;
1228 wps_er_http_event(er, req, atoi(pos));
1229 } else {
1230 wpa_printf(MSG_DEBUG, "WPS ER: Unknown HTTP NOTIFY for '%s'",
1231 uri);
1232 wps_er_http_resp_not_found(req);
1233 }
1234 }
1235
1236
1237 static void wps_er_http_req(void *ctx, struct http_request *req)
1238 {
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);
1242 struct wpabuf *buf;
1243
1244 wpa_printf(MSG_DEBUG, "WPS ER: HTTP request: '%s' (type %d) from "
1245 "%s:%d",
1246 http_request_get_uri(req), type,
1247 inet_ntoa(cli->sin_addr), ntohs(cli->sin_port));
1248
1249 switch (type) {
1250 case HTTPREAD_HDR_TYPE_NOTIFY:
1251 wps_er_http_notify(er, req);
1252 break;
1253 default:
1254 wpa_printf(MSG_DEBUG, "WPS ER: Unsupported HTTP request type "
1255 "%d", type);
1256 buf = wpabuf_alloc(200);
1257 if (buf == NULL) {
1258 http_request_deinit(req);
1259 return;
1260 }
1261 wpabuf_put_str(buf,
1262 "HTTP/1.1 501 Unimplemented\r\n"
1263 "Connection: close\r\n");
1264 http_put_date(buf);
1265 wpabuf_put_str(buf, "\r\n");
1266 http_request_send_and_deinit(req, buf);
1267 break;
1268 }
1269 }
1270
1271
1272 struct wps_er *
1273 wps_er_init(struct wps_context *wps, const char *ifname, const char *filter)
1274 {
1275 struct wps_er *er;
1276 struct in_addr addr;
1277
1278 er = os_zalloc(sizeof(*er));
1279 if (er == NULL)
1280 return NULL;
1281 dl_list_init(&er->ap);
1282 dl_list_init(&er->ap_unsubscribing);
1283 dl_list_init(&er->ap_settings);
1284
1285 er->multicast_sd = -1;
1286 er->ssdp_sd = -1;
1287
1288 os_strlcpy(er->ifname, ifname, sizeof(er->ifname));
1289 er->wps = wps;
1290 if (os_get_random((unsigned char *) &er->event_id,
1291 sizeof(er->event_id)) < 0) {
1292 wps_er_deinit(er, NULL, NULL);
1293 return NULL;
1294 }
1295 /* Limit event_id to < 32 bits to avoid issues with atoi() */
1296 er->event_id &= 0x0fffffff;
1297
1298 if (filter) {
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);
1303 return NULL;
1304 }
1305 wpa_printf(MSG_DEBUG, "WPS UPnP: Only accepting connections "
1306 "with %s", filter);
1307 }
1308 if (get_netif_info(ifname, &er->ip_addr, &er->ip_addr_text,
1309 er->mac_addr)) {
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);
1313 return NULL;
1314 }
1315
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);
1319 return NULL;
1320 }
1321
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);
1327 return NULL;
1328 }
1329 er->http_port = http_server_get_port(er->http_srv);
1330
1331 wpa_printf(MSG_DEBUG, "WPS ER: Start (ifname=%s ip_addr=%s)",
1332 er->ifname, er->ip_addr_text);
1333
1334 return er;
1335 }
1336
1337
1338 void wps_er_refresh(struct wps_er *er)
1339 {
1340 struct wps_er_ap *ap;
1341 struct wps_er_sta *sta;
1342
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);
1347 }
1348
1349 wps_er_send_ssdp_msearch(er);
1350 }
1351
1352
1353 static void wps_er_deinit_finish(void *eloop_data, void *user_ctx)
1354 {
1355 struct wps_er *er = eloop_data;
1356 void (*deinit_done_cb)(void *ctx);
1357 void *deinit_done_ctx;
1358
1359 wpa_printf(MSG_DEBUG, "WPS ER: Finishing deinit");
1360
1361 deinit_done_cb = er->deinit_done_cb;
1362 deinit_done_ctx = er->deinit_done_ctx;
1363 os_free(er->ip_addr_text);
1364 os_free(er);
1365
1366 if (deinit_done_cb)
1367 deinit_done_cb(deinit_done_ctx);
1368 }
1369
1370
1371 void wps_er_deinit(struct wps_er *er, void (*cb)(void *ctx), void *ctx)
1372 {
1373 if (er == NULL)
1374 return;
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;
1384 }
1385
1386
1387 static void wps_er_http_set_sel_reg_cb(void *ctx, struct http_client *c,
1388 enum http_client_event event)
1389 {
1390 struct wps_er_ap *ap = ctx;
1391 union wps_event_data data;
1392
1393 os_memset(&data, 0, sizeof(data));
1394
1395 switch (event) {
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;
1400 break;
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;
1407 break;
1408 }
1409 http_client_free(ap->http);
1410 ap->http = NULL;
1411
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);
1415 }
1416
1417
1418 static void wps_er_send_set_sel_reg(struct wps_er_ap *ap, struct wpabuf *msg)
1419 {
1420 struct wpabuf *buf;
1421 char *len_ptr, *body_ptr;
1422 struct sockaddr_in dst;
1423 char *url, *path;
1424
1425 if (ap->control_url == NULL) {
1426 wpa_printf(MSG_DEBUG, "WPS ER: No controlURL for AP");
1427 return;
1428 }
1429
1430 if (ap->http) {
1431 wpa_printf(MSG_DEBUG, "WPS ER: Pending HTTP request for AP - "
1432 "ignore new request");
1433 return;
1434 }
1435
1436 if (ap->wps) {
1437 wpa_printf(MSG_DEBUG, "WPS ER: Pending WPS operation for AP - "
1438 "skip SetSelectedRegistrar");
1439 return;
1440 }
1441
1442 url = http_client_url_parse(ap->control_url, &dst, &path);
1443 if (url == NULL) {
1444 wpa_printf(MSG_DEBUG, "WPS ER: Failed to parse controlURL");
1445 return;
1446 }
1447
1448 buf = wps_er_soap_hdr(msg, "SetSelectedRegistrar", "NewMessage", path,
1449 &dst, &len_ptr, &body_ptr);
1450 os_free(url);
1451 if (buf == NULL)
1452 return;
1453
1454 wps_er_soap_end(buf, "SetSelectedRegistrar", len_ptr, body_ptr);
1455
1456 ap->http = http_client_addr(&dst, buf, 1000,
1457 wps_er_http_set_sel_reg_cb, ap);
1458 if (ap->http == NULL)
1459 wpabuf_free(buf);
1460 }
1461
1462
1463 static int wps_er_build_selected_registrar(struct wpabuf *msg, int sel_reg)
1464 {
1465 wpabuf_put_be16(msg, ATTR_SELECTED_REGISTRAR);
1466 wpabuf_put_be16(msg, 1);
1467 wpabuf_put_u8(msg, !!sel_reg);
1468 return 0;
1469 }
1470
1471
1472 static int wps_er_build_dev_password_id(struct wpabuf *msg, u16 dev_passwd_id)
1473 {
1474 wpabuf_put_be16(msg, ATTR_DEV_PASSWORD_ID);
1475 wpabuf_put_be16(msg, 2);
1476 wpabuf_put_be16(msg, dev_passwd_id);
1477 return 0;
1478 }
1479
1480
1481 static int wps_er_build_sel_reg_config_methods(struct wpabuf *msg,
1482 u16 sel_reg_config_methods)
1483 {
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);
1487 return 0;
1488 }
1489
1490
1491 static int wps_er_build_uuid_r(struct wpabuf *msg, const u8 *uuid_r)
1492 {
1493 #ifdef CONFIG_WPS2
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 */
1498 return 0;
1499 }
1500
1501
1502 void wps_er_set_sel_reg(struct wps_er *er, int sel_reg, u16 dev_passwd_id,
1503 u16 sel_reg_config_methods)
1504 {
1505 struct wpabuf *msg;
1506 struct wps_er_ap *ap;
1507 struct wps_registrar *reg = er->wps->registrar;
1508 const u8 *auth_macs;
1509 #ifdef CONFIG_WPS2
1510 u8 bcast[ETH_ALEN];
1511 #endif /* CONFIG_WPS2 */
1512 size_t count;
1513 union wps_event_data data;
1514
1515 if (er->skip_set_sel_reg) {
1516 wpa_printf(MSG_DEBUG, "WPS ER: Skip SetSelectedRegistrar");
1517 return;
1518 }
1519
1520 msg = wpabuf_alloc(500);
1521 if (msg == NULL)
1522 return;
1523
1524 auth_macs = wps_authorized_macs(reg, &count);
1525 #ifdef CONFIG_WPS2
1526 if (count == 0) {
1527 os_memset(bcast, 0xff, ETH_ALEN);
1528 auth_macs = bcast;
1529 count = 1;
1530 }
1531 #endif /* CONFIG_WPS2 */
1532
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)) {
1539 wpabuf_free(msg);
1540 return;
1541 }
1542
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;
1548
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,
1552 WPS_UUID_LEN) != 0)
1553 continue;
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);
1558 }
1559
1560 wpabuf_free(msg);
1561 }
1562
1563
1564 int wps_er_pbc(struct wps_er *er, const u8 *uuid)
1565 {
1566 int res;
1567 struct wps_er_ap *ap;
1568
1569 if (er == NULL || er->wps == NULL)
1570 return -1;
1571
1572 if (wps_registrar_pbc_overlap(er->wps->registrar, NULL, NULL)) {
1573 wpa_printf(MSG_DEBUG, "WPS ER: PBC overlap - do not start PBC "
1574 "mode");
1575 return -2;
1576 }
1577
1578 ap = wps_er_ap_get(er, NULL, uuid);
1579 if (ap == NULL) {
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);
1583 if (sta) {
1584 uuid = ap->uuid;
1585 break;
1586 }
1587 }
1588 if (sta == NULL)
1589 return -3; /* Unknown UUID */
1590 }
1591
1592 if (ap->ap_settings == NULL) {
1593 wpa_printf(MSG_DEBUG, "WPS ER: AP settings not known");
1594 return -4;
1595 }
1596
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;
1600 if (res)
1601 return -1;
1602
1603 return 0;
1604 }
1605
1606
1607 static void wps_er_ap_settings_cb(void *ctx, const struct wps_credential *cred)
1608 {
1609 struct wps_er_ap *ap = ctx;
1610 union wps_event_data data;
1611
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;
1618 }
1619
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,
1624 &data);
1625 }
1626
1627
1628 static void wps_er_http_put_message_cb(void *ctx, struct http_client *c,
1629 enum http_client_event event)
1630 {
1631 struct wps_er_ap *ap = ctx;
1632 struct wpabuf *reply;
1633 char *msg = NULL;
1634
1635 switch (event) {
1636 case HTTP_CLIENT_OK:
1637 wpa_printf(MSG_DEBUG, "WPS ER: PutMessage OK");
1638 reply = http_client_get_body(c);
1639 if (reply == NULL)
1640 break;
1641 msg = os_zalloc(wpabuf_len(reply) + 1);
1642 if (msg == NULL)
1643 break;
1644 os_memcpy(msg, wpabuf_head(reply), wpabuf_len(reply));
1645 break;
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");
1650 if (ap->wps) {
1651 wps_deinit(ap->wps);
1652 ap->wps = NULL;
1653 }
1654 break;
1655 }
1656 http_client_free(ap->http);
1657 ap->http = NULL;
1658
1659 if (msg) {
1660 struct wpabuf *buf;
1661 enum http_reply_code ret;
1662 buf = xml_get_base64_item(msg, "NewOutMessage", &ret);
1663 os_free(msg);
1664 if (buf == NULL) {
1665 wpa_printf(MSG_DEBUG, "WPS ER: Could not extract "
1666 "NewOutMessage from PutMessage response");
1667 wps_deinit(ap->wps);
1668 ap->wps = NULL;
1669 return;
1670 }
1671 wps_er_ap_process(ap, buf);
1672 wpabuf_free(buf);
1673 }
1674 }
1675
1676
1677 static void wps_er_ap_put_message(struct wps_er_ap *ap,
1678 const struct wpabuf *msg)
1679 {
1680 struct wpabuf *buf;
1681 char *len_ptr, *body_ptr;
1682 struct sockaddr_in dst;
1683 char *url, *path;
1684
1685 if (ap->http) {
1686 wpa_printf(MSG_DEBUG, "WPS ER: Pending HTTP operation ongoing "
1687 "with the AP - cannot continue learn");
1688 return;
1689 }
1690
1691 if (ap->control_url == NULL) {
1692 wpa_printf(MSG_DEBUG, "WPS ER: No controlURL for AP");
1693 return;
1694 }
1695
1696 url = http_client_url_parse(ap->control_url, &dst, &path);
1697 if (url == NULL) {
1698 wpa_printf(MSG_DEBUG, "WPS ER: Failed to parse controlURL");
1699 return;
1700 }
1701
1702 buf = wps_er_soap_hdr(msg, "PutMessage", "NewInMessage", path, &dst,
1703 &len_ptr, &body_ptr);
1704 os_free(url);
1705 if (buf == NULL)
1706 return;
1707
1708 wps_er_soap_end(buf, "PutMessage", len_ptr, body_ptr);
1709
1710 ap->http = http_client_addr(&dst, buf, 10000,
1711 wps_er_http_put_message_cb, ap);
1712 if (ap->http == NULL)
1713 wpabuf_free(buf);
1714 }
1715
1716
1717 static void wps_er_ap_process(struct wps_er_ap *ap, struct wpabuf *msg)
1718 {
1719 enum wps_process_res res;
1720 struct wps_parse_attr attr;
1721 enum wsc_op_code op_code;
1722
1723 op_code = WSC_MSG;
1724 if (wps_parse_msg(msg, &attr) == 0 && attr.msg_type) {
1725 switch (*attr.msg_type) {
1726 case WPS_WSC_ACK:
1727 op_code = WSC_ACK;
1728 break;
1729 case WPS_WSC_NACK:
1730 op_code = WSC_NACK;
1731 break;
1732 case WPS_WSC_DONE:
1733 op_code = WSC_Done;
1734 break;
1735 }
1736 }
1737
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);
1741 if (next) {
1742 wps_er_ap_put_message(ap, next);
1743 wpabuf_free(next);
1744 } else {
1745 wpa_printf(MSG_DEBUG, "WPS ER: Failed to build "
1746 "message");
1747 wps_deinit(ap->wps);
1748 ap->wps = NULL;
1749 }
1750 } else if (res == WPS_DONE) {
1751 wpa_printf(MSG_DEBUG, "WPS ER: Protocol run done");
1752 wps_deinit(ap->wps);
1753 ap->wps = NULL;
1754 } else {
1755 wpa_printf(MSG_DEBUG, "WPS ER: Failed to process message from "
1756 "AP (res=%d)", res);
1757 wps_deinit(ap->wps);
1758 ap->wps = NULL;
1759 }
1760 }
1761
1762
1763 static void wps_er_ap_learn_m1(struct wps_er_ap *ap, struct wpabuf *m1)
1764 {
1765 struct wps_config cfg;
1766
1767 if (ap->wps) {
1768 wpa_printf(MSG_DEBUG, "WPS ER: Protocol run already in "
1769 "progress with this AP");
1770 return;
1771 }
1772
1773 os_memset(&cfg, 0, sizeof(cfg));
1774 cfg.wps = ap->er->wps;
1775 cfg.registrar = 1;
1776 ap->wps = wps_init(&cfg);
1777 if (ap->wps == NULL)
1778 return;
1779 ap->wps->ap_settings_cb = wps_er_ap_settings_cb;
1780 ap->wps->ap_settings_cb_ctx = ap;
1781
1782 wps_er_ap_process(ap, m1);
1783 }
1784
1785
1786 static void wps_er_ap_learn(struct wps_er_ap *ap, const char *dev_info)
1787 {
1788 struct wpabuf *info;
1789 enum http_reply_code ret;
1790
1791 wpa_printf(MSG_DEBUG, "WPS ER: Received GetDeviceInfo response (M1) "
1792 "from the AP");
1793 info = xml_get_base64_item(dev_info, "NewDeviceInfo", &ret);
1794 if (info == NULL) {
1795 wpa_printf(MSG_DEBUG, "WPS ER: Could not extract "
1796 "NewDeviceInfo from GetDeviceInfo response");
1797 return;
1798 }
1799
1800 ap->m1_handler(ap, info);
1801 wpabuf_free(info);
1802 }
1803
1804
1805 static void wps_er_http_get_dev_info_cb(void *ctx, struct http_client *c,
1806 enum http_client_event event)
1807 {
1808 struct wps_er_ap *ap = ctx;
1809 struct wpabuf *reply;
1810 char *dev_info = NULL;
1811
1812 switch (event) {
1813 case HTTP_CLIENT_OK:
1814 wpa_printf(MSG_DEBUG, "WPS ER: GetDeviceInfo OK");
1815 reply = http_client_get_body(c);
1816 if (reply == NULL)
1817 break;
1818 dev_info = os_zalloc(wpabuf_len(reply) + 1);
1819 if (dev_info == NULL)
1820 break;
1821 os_memcpy(dev_info, wpabuf_head(reply), wpabuf_len(reply));
1822 break;
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");
1827 break;
1828 }
1829 http_client_free(ap->http);
1830 ap->http = NULL;
1831
1832 if (dev_info) {
1833 wps_er_ap_learn(ap, dev_info);
1834 os_free(dev_info);
1835 }
1836 }
1837
1838
1839 static int wps_er_send_get_device_info(struct wps_er_ap *ap,
1840 void (*m1_handler)(struct wps_er_ap *ap,
1841 struct wpabuf *m1))
1842 {
1843 struct wpabuf *buf;
1844 char *len_ptr, *body_ptr;
1845 struct sockaddr_in dst;
1846 char *url, *path;
1847
1848 if (ap->http) {
1849 wpa_printf(MSG_DEBUG, "WPS ER: Pending HTTP operation ongoing "
1850 "with the AP - cannot get device info");
1851 return -1;
1852 }
1853
1854 if (ap->control_url == NULL) {
1855 wpa_printf(MSG_DEBUG, "WPS ER: No controlURL for AP");
1856 return -1;
1857 }
1858
1859 url = http_client_url_parse(ap->control_url, &dst, &path);
1860 if (url == NULL) {
1861 wpa_printf(MSG_DEBUG, "WPS ER: Failed to parse controlURL");
1862 return -1;
1863 }
1864
1865 buf = wps_er_soap_hdr(NULL, "GetDeviceInfo", NULL, path, &dst,
1866 &len_ptr, &body_ptr);
1867 os_free(url);
1868 if (buf == NULL)
1869 return -1;
1870
1871 wps_er_soap_end(buf, "GetDeviceInfo", len_ptr, body_ptr);
1872
1873 ap->http = http_client_addr(&dst, buf, 10000,
1874 wps_er_http_get_dev_info_cb, ap);
1875 if (ap->http == NULL) {
1876 wpabuf_free(buf);
1877 return -1;
1878 }
1879
1880 ap->m1_handler = m1_handler;
1881
1882 return 0;
1883 }
1884
1885
1886 int wps_er_learn(struct wps_er *er, const u8 *uuid, const u8 *pin,
1887 size_t pin_len)
1888 {
1889 struct wps_er_ap *ap;
1890
1891 if (er == NULL)
1892 return -1;
1893
1894 ap = wps_er_ap_get(er, NULL, uuid);
1895 if (ap == NULL) {
1896 wpa_printf(MSG_DEBUG, "WPS ER: AP not found for learn "
1897 "request");
1898 return -1;
1899 }
1900 if (ap->wps) {
1901 wpa_printf(MSG_DEBUG, "WPS ER: Pending operation ongoing "
1902 "with the AP - cannot start learn");
1903 return -1;
1904 }
1905
1906 if (wps_er_send_get_device_info(ap, wps_er_ap_learn_m1) < 0)
1907 return -1;
1908
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;
1912
1913 return 0;
1914 }
1915
1916
1917 int wps_er_set_config(struct wps_er *er, const u8 *uuid,
1918 const struct wps_credential *cred)
1919 {
1920 struct wps_er_ap *ap;
1921
1922 if (er == NULL)
1923 return -1;
1924
1925 ap = wps_er_ap_get(er, NULL, uuid);
1926 if (ap == NULL) {
1927 wpa_printf(MSG_DEBUG, "WPS ER: AP not found for set config "
1928 "request");
1929 return -1;
1930 }
1931
1932 os_free(ap->ap_settings);
1933 ap->ap_settings = os_malloc(sizeof(*cred));
1934 if (ap->ap_settings == NULL)
1935 return -1;
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 "
1939 "config request");
1940
1941 return 0;
1942 }
1943
1944
1945 static void wps_er_ap_config_m1(struct wps_er_ap *ap, struct wpabuf *m1)
1946 {
1947 struct wps_config cfg;
1948
1949 if (ap->wps) {
1950 wpa_printf(MSG_DEBUG, "WPS ER: Protocol run already in "
1951 "progress with this AP");
1952 return;
1953 }
1954
1955 os_memset(&cfg, 0, sizeof(cfg));
1956 cfg.wps = ap->er->wps;
1957 cfg.registrar = 1;
1958 cfg.new_ap_settings = ap->ap_settings;
1959 ap->wps = wps_init(&cfg);
1960 if (ap->wps == NULL)
1961 return;
1962 ap->wps->ap_settings_cb = NULL;
1963 ap->wps->ap_settings_cb_ctx = NULL;
1964
1965 wps_er_ap_process(ap, m1);
1966 }
1967
1968
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)
1971 {
1972 struct wps_er_ap *ap;
1973
1974 if (er == NULL)
1975 return -1;
1976
1977 ap = wps_er_ap_get(er, NULL, uuid);
1978 if (ap == NULL) {
1979 wpa_printf(MSG_DEBUG, "WPS ER: AP not found for config "
1980 "request");
1981 return -1;
1982 }
1983 if (ap->wps) {
1984 wpa_printf(MSG_DEBUG, "WPS ER: Pending operation ongoing "
1985 "with the AP - cannot start config");
1986 return -1;
1987 }
1988
1989 os_free(ap->ap_settings);
1990 ap->ap_settings = os_malloc(sizeof(*cred));
1991 if (ap->ap_settings == NULL)
1992 return -1;
1993 os_memcpy(ap->ap_settings, cred, sizeof(*cred));
1994 ap->ap_settings->cred_attr = NULL;
1995
1996 if (wps_er_send_get_device_info(ap, wps_er_ap_config_m1) < 0)
1997 return -1;
1998
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;
2002
2003 return 0;
2004 }