wps_er.c revision cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50e
1/* 2 * Wi-Fi Protected Setup - External Registrar 3 * Copyright (c) 2009-2013, Jouni Malinen <j@w1.fi> 4 * 5 * This software may be distributed under the terms of the BSD license. 6 * See README for more details. 7 */ 8 9#include "includes.h" 10 11#include "common.h" 12#include "base64.h" 13#include "uuid.h" 14#include "eloop.h" 15#include "httpread.h" 16#include "http_client.h" 17#include "http_server.h" 18#include "upnp_xml.h" 19#include "wps_i.h" 20#include "wps_upnp.h" 21#include "wps_upnp_i.h" 22#include "wps_er.h" 23 24 25static void wps_er_deinit_finish(void *eloop_data, void *user_ctx); 26static void wps_er_ap_timeout(void *eloop_data, void *user_ctx); 27static void wps_er_sta_timeout(void *eloop_data, void *user_ctx); 28static void wps_er_ap_process(struct wps_er_ap *ap, struct wpabuf *msg); 29static int wps_er_send_get_device_info(struct wps_er_ap *ap, 30 void (*m1_handler)(struct wps_er_ap *ap, 31 struct wpabuf *m1)); 32 33 34static void wps_er_sta_event(struct wps_context *wps, struct wps_er_sta *sta, 35 enum wps_event event) 36{ 37 union wps_event_data data; 38 struct wps_event_er_enrollee *ev = &data.enrollee; 39 40 if (wps->event_cb == NULL) 41 return; 42 43 os_memset(&data, 0, sizeof(data)); 44 ev->uuid = sta->uuid; 45 ev->mac_addr = sta->addr; 46 ev->m1_received = sta->m1_received; 47 ev->config_methods = sta->config_methods; 48 ev->dev_passwd_id = sta->dev_passwd_id; 49 ev->pri_dev_type = sta->pri_dev_type; 50 ev->dev_name = sta->dev_name; 51 ev->manufacturer = sta->manufacturer; 52 ev->model_name = sta->model_name; 53 ev->model_number = sta->model_number; 54 ev->serial_number = sta->serial_number; 55 wps->event_cb(wps->cb_ctx, event, &data); 56} 57 58 59static struct wps_er_sta * wps_er_sta_get(struct wps_er_ap *ap, const u8 *addr, 60 const u8 *uuid) 61{ 62 struct wps_er_sta *sta; 63 dl_list_for_each(sta, &ap->sta, struct wps_er_sta, list) { 64 if ((addr == NULL || 65 os_memcmp(sta->addr, addr, ETH_ALEN) == 0) && 66 (uuid == NULL || 67 os_memcmp(uuid, sta->uuid, WPS_UUID_LEN) == 0)) 68 return sta; 69 } 70 return NULL; 71} 72 73 74static void wps_er_sta_free(struct wps_er_sta *sta) 75{ 76 wps_er_sta_event(sta->ap->er->wps, sta, WPS_EV_ER_ENROLLEE_REMOVE); 77 if (sta->wps) 78 wps_deinit(sta->wps); 79 os_free(sta->manufacturer); 80 os_free(sta->model_name); 81 os_free(sta->model_number); 82 os_free(sta->serial_number); 83 os_free(sta->dev_name); 84 http_client_free(sta->http); 85 eloop_cancel_timeout(wps_er_sta_timeout, sta, NULL); 86 os_free(sta->cred); 87 os_free(sta); 88} 89 90 91static void wps_er_sta_remove_all(struct wps_er_ap *ap) 92{ 93 struct wps_er_sta *prev, *sta; 94 dl_list_for_each_safe(sta, prev, &ap->sta, struct wps_er_sta, list) 95 wps_er_sta_free(sta); 96} 97 98 99static struct wps_er_ap * wps_er_ap_get(struct wps_er *er, 100 struct in_addr *addr, const u8 *uuid, 101 const u8 *mac_addr) 102{ 103 struct wps_er_ap *ap; 104 dl_list_for_each(ap, &er->ap, struct wps_er_ap, list) { 105 if ((addr == NULL || ap->addr.s_addr == addr->s_addr) && 106 (uuid == NULL || 107 os_memcmp(uuid, ap->uuid, WPS_UUID_LEN) == 0) && 108 (mac_addr == NULL || 109 os_memcmp(mac_addr, ap->mac_addr, ETH_ALEN) == 0)) 110 return ap; 111 } 112 return NULL; 113} 114 115 116static struct wps_er_ap * wps_er_ap_get_id(struct wps_er *er, unsigned int id) 117{ 118 struct wps_er_ap *ap; 119 dl_list_for_each(ap, &er->ap, struct wps_er_ap, list) { 120 if (ap->id == id) 121 return ap; 122 } 123 return NULL; 124} 125 126 127static void wps_er_ap_event(struct wps_context *wps, struct wps_er_ap *ap, 128 enum wps_event event) 129{ 130 union wps_event_data data; 131 struct wps_event_er_ap *evap = &data.ap; 132 133 if (wps->event_cb == NULL) 134 return; 135 136 os_memset(&data, 0, sizeof(data)); 137 evap->uuid = ap->uuid; 138 evap->friendly_name = ap->friendly_name; 139 evap->manufacturer = ap->manufacturer; 140 evap->manufacturer_url = ap->manufacturer_url; 141 evap->model_description = ap->model_description; 142 evap->model_name = ap->model_name; 143 evap->model_number = ap->model_number; 144 evap->model_url = ap->model_url; 145 evap->serial_number = ap->serial_number; 146 evap->upc = ap->upc; 147 evap->pri_dev_type = ap->pri_dev_type; 148 evap->wps_state = ap->wps_state; 149 evap->mac_addr = ap->mac_addr; 150 wps->event_cb(wps->cb_ctx, event, &data); 151} 152 153 154static void wps_er_ap_free(struct wps_er_ap *ap) 155{ 156 http_client_free(ap->http); 157 ap->http = NULL; 158 159 os_free(ap->location); 160 os_free(ap->friendly_name); 161 os_free(ap->manufacturer); 162 os_free(ap->manufacturer_url); 163 os_free(ap->model_description); 164 os_free(ap->model_name); 165 os_free(ap->model_number); 166 os_free(ap->model_url); 167 os_free(ap->serial_number); 168 os_free(ap->udn); 169 os_free(ap->upc); 170 171 os_free(ap->scpd_url); 172 os_free(ap->control_url); 173 os_free(ap->event_sub_url); 174 175 os_free(ap->ap_settings); 176 177 os_free(ap); 178} 179 180 181static void wps_er_ap_unsubscribed(struct wps_er *er, struct wps_er_ap *ap) 182{ 183 wpa_printf(MSG_DEBUG, "WPS ER: Unsubscribed from AP %s (%s)", 184 inet_ntoa(ap->addr), ap->location); 185 dl_list_del(&ap->list); 186 wps_er_ap_free(ap); 187 188 if (er->deinitializing && dl_list_empty(&er->ap_unsubscribing)) 189 wps_er_deinit_finish(er, NULL); 190} 191 192 193static void wps_er_http_unsubscribe_cb(void *ctx, struct http_client *c, 194 enum http_client_event event) 195{ 196 struct wps_er_ap *ap = ctx; 197 198 switch (event) { 199 case HTTP_CLIENT_OK: 200 wpa_printf(MSG_DEBUG, "WPS ER: Unsubscribed from events"); 201 ap->subscribed = 0; 202 break; 203 case HTTP_CLIENT_FAILED: 204 case HTTP_CLIENT_INVALID_REPLY: 205 case HTTP_CLIENT_TIMEOUT: 206 wpa_printf(MSG_DEBUG, "WPS ER: Failed to unsubscribe from " 207 "events"); 208 break; 209 } 210 http_client_free(ap->http); 211 ap->http = NULL; 212 213 /* 214 * Need to get rid of the AP entry regardless of whether we managed to 215 * unsubscribe cleanly or not. 216 */ 217 wps_er_ap_unsubscribed(ap->er, ap); 218} 219 220 221static void wps_er_ap_unsubscribe(struct wps_er *er, struct wps_er_ap *ap) 222{ 223 struct wpabuf *req; 224 struct sockaddr_in dst; 225 char *url, *path; 226 char sid[100]; 227 228 if (ap->event_sub_url == NULL) { 229 wpa_printf(MSG_DEBUG, "WPS ER: No eventSubURL - cannot " 230 "subscribe"); 231 goto fail; 232 } 233 if (ap->http) { 234 wpa_printf(MSG_DEBUG, "WPS ER: Pending HTTP request - cannot " 235 "send subscribe request"); 236 goto fail; 237 } 238 239 url = http_client_url_parse(ap->event_sub_url, &dst, &path); 240 if (url == NULL) { 241 wpa_printf(MSG_DEBUG, "WPS ER: Failed to parse eventSubURL"); 242 goto fail; 243 } 244 245 req = wpabuf_alloc(os_strlen(ap->event_sub_url) + 1000); 246 if (req == NULL) { 247 os_free(url); 248 goto fail; 249 } 250 uuid_bin2str(ap->sid, sid, sizeof(sid)); 251 wpabuf_printf(req, 252 "UNSUBSCRIBE %s HTTP/1.1\r\n" 253 "HOST: %s:%d\r\n" 254 "SID: uuid:%s\r\n" 255 "\r\n", 256 path, inet_ntoa(dst.sin_addr), ntohs(dst.sin_port), sid); 257 os_free(url); 258 wpa_hexdump_ascii(MSG_MSGDUMP, "WPS ER: Unsubscription request", 259 wpabuf_head(req), wpabuf_len(req)); 260 261 ap->http = http_client_addr(&dst, req, 1000, 262 wps_er_http_unsubscribe_cb, ap); 263 if (ap->http == NULL) { 264 wpabuf_free(req); 265 goto fail; 266 } 267 return; 268 269fail: 270 /* 271 * Need to get rid of the AP entry even when we fail to unsubscribe 272 * cleanly. 273 */ 274 wps_er_ap_unsubscribed(ap->er, ap); 275} 276 277 278static struct wps_er_ap_settings * wps_er_ap_get_settings(struct wps_er *er, 279 const u8 *uuid) 280{ 281 struct wps_er_ap_settings *s; 282 dl_list_for_each(s, &er->ap_settings, struct wps_er_ap_settings, list) 283 if (os_memcmp(uuid, s->uuid, WPS_UUID_LEN) == 0) 284 return s; 285 return NULL; 286} 287 288 289int wps_er_ap_cache_settings(struct wps_er *er, struct in_addr *addr) 290{ 291 struct wps_er_ap *ap; 292 struct wps_er_ap_settings *settings; 293 294 ap = wps_er_ap_get(er, addr, NULL, NULL); 295 if (ap == NULL || ap->ap_settings == NULL) 296 return -1; 297 298 settings = wps_er_ap_get_settings(er, ap->uuid); 299 if (!settings) { 300 settings = os_zalloc(sizeof(*settings)); 301 if (settings == NULL) 302 return -1; 303 os_memcpy(settings->uuid, ap->uuid, WPS_UUID_LEN); 304 dl_list_add(&er->ap_settings, &settings->list); 305 } 306 os_memcpy(&settings->ap_settings, ap->ap_settings, 307 sizeof(struct wps_credential)); 308 309 return 0; 310} 311 312 313static int wps_er_ap_use_cached_settings(struct wps_er *er, 314 struct wps_er_ap *ap) 315{ 316 struct wps_er_ap_settings *s; 317 318 if (ap->ap_settings) 319 return 0; 320 321 s = wps_er_ap_get_settings(ap->er, ap->uuid); 322 if (!s) 323 return -1; 324 325 ap->ap_settings = os_malloc(sizeof(*ap->ap_settings)); 326 if (ap->ap_settings == NULL) 327 return -1; 328 329 os_memcpy(ap->ap_settings, &s->ap_settings, sizeof(*ap->ap_settings)); 330 wpa_printf(MSG_DEBUG, "WPS ER: Use cached AP settings"); 331 return 0; 332} 333 334 335static void wps_er_ap_remove_entry(struct wps_er *er, struct wps_er_ap *ap) 336{ 337 wpa_printf(MSG_DEBUG, "WPS ER: Removing AP entry for %s (%s)", 338 inet_ntoa(ap->addr), ap->location); 339 eloop_cancel_timeout(wps_er_ap_timeout, er, ap); 340 wps_er_sta_remove_all(ap); 341 wps_er_ap_event(er->wps, ap, WPS_EV_ER_AP_REMOVE); 342 http_client_free(ap->http); 343 ap->http = NULL; 344 if (ap->wps) { 345 wps_deinit(ap->wps); 346 ap->wps = NULL; 347 } 348 349 dl_list_del(&ap->list); 350 if (ap->subscribed) { 351 dl_list_add(&er->ap_unsubscribing, &ap->list); 352 wps_er_ap_unsubscribe(er, ap); 353 } else 354 wps_er_ap_free(ap); 355} 356 357 358static void wps_er_ap_timeout(void *eloop_data, void *user_ctx) 359{ 360 struct wps_er *er = eloop_data; 361 struct wps_er_ap *ap = user_ctx; 362 wpa_printf(MSG_DEBUG, "WPS ER: AP advertisement timed out"); 363 wps_er_ap_remove_entry(er, ap); 364} 365 366 367static int wps_er_get_sid(struct wps_er_ap *ap, char *sid) 368{ 369 char *pos; 370 char txt[100]; 371 372 if (!sid) { 373 wpa_printf(MSG_DEBUG, "WPS ER: No SID received from %s (%s)", 374 inet_ntoa(ap->addr), ap->location); 375 return -1; 376 } 377 378 pos = os_strstr(sid, "uuid:"); 379 if (!pos) { 380 wpa_printf(MSG_DEBUG, "WPS ER: Invalid SID received from " 381 "%s (%s): '%s'", inet_ntoa(ap->addr), ap->location, 382 sid); 383 return -1; 384 } 385 386 pos += 5; 387 if (uuid_str2bin(pos, ap->sid) < 0) { 388 wpa_printf(MSG_DEBUG, "WPS ER: Invalid SID received from " 389 "%s (%s): '%s'", inet_ntoa(ap->addr), ap->location, 390 sid); 391 return -1; 392 } 393 394 uuid_bin2str(ap->sid, txt, sizeof(txt)); 395 wpa_printf(MSG_DEBUG, "WPS ER: SID for subscription with %s (%s): %s", 396 inet_ntoa(ap->addr), ap->location, txt); 397 398 return 0; 399} 400 401 402static void wps_er_http_subscribe_cb(void *ctx, struct http_client *c, 403 enum http_client_event event) 404{ 405 struct wps_er_ap *ap = ctx; 406 407 switch (event) { 408 case HTTP_CLIENT_OK: 409 wpa_printf(MSG_DEBUG, "WPS ER: Subscribed to events"); 410 ap->subscribed = 1; 411 wps_er_get_sid(ap, http_client_get_hdr_line(c, "SID")); 412 wps_er_ap_use_cached_settings(ap->er, ap); 413 wps_er_ap_event(ap->er->wps, ap, WPS_EV_ER_AP_ADD); 414 break; 415 case HTTP_CLIENT_FAILED: 416 case HTTP_CLIENT_INVALID_REPLY: 417 case HTTP_CLIENT_TIMEOUT: 418 wpa_printf(MSG_DEBUG, "WPS ER: Failed to subscribe to events"); 419 break; 420 } 421 http_client_free(ap->http); 422 ap->http = NULL; 423} 424 425 426static void wps_er_subscribe(struct wps_er_ap *ap) 427{ 428 struct wpabuf *req; 429 struct sockaddr_in dst; 430 char *url, *path; 431 432 if (ap->event_sub_url == NULL) { 433 wpa_printf(MSG_DEBUG, "WPS ER: No eventSubURL - cannot " 434 "subscribe"); 435 return; 436 } 437 if (ap->http) { 438 wpa_printf(MSG_DEBUG, "WPS ER: Pending HTTP request - cannot " 439 "send subscribe request"); 440 return; 441 } 442 443 url = http_client_url_parse(ap->event_sub_url, &dst, &path); 444 if (url == NULL) { 445 wpa_printf(MSG_DEBUG, "WPS ER: Failed to parse eventSubURL"); 446 return; 447 } 448 449 req = wpabuf_alloc(os_strlen(ap->event_sub_url) + 1000); 450 if (req == NULL) { 451 os_free(url); 452 return; 453 } 454 wpabuf_printf(req, 455 "SUBSCRIBE %s HTTP/1.1\r\n" 456 "HOST: %s:%d\r\n" 457 "CALLBACK: <http://%s:%d/event/%u/%u>\r\n" 458 "NT: upnp:event\r\n" 459 "TIMEOUT: Second-%d\r\n" 460 "\r\n", 461 path, inet_ntoa(dst.sin_addr), ntohs(dst.sin_port), 462 ap->er->ip_addr_text, ap->er->http_port, 463 ap->er->event_id, ap->id, 1800); 464 os_free(url); 465 wpa_hexdump_ascii(MSG_MSGDUMP, "WPS ER: Subscription request", 466 wpabuf_head(req), wpabuf_len(req)); 467 468 ap->http = http_client_addr(&dst, req, 1000, wps_er_http_subscribe_cb, 469 ap); 470 if (ap->http == NULL) 471 wpabuf_free(req); 472} 473 474 475static void wps_er_ap_get_m1(struct wps_er_ap *ap, struct wpabuf *m1) 476{ 477 struct wps_parse_attr attr; 478 479 if (wps_parse_msg(m1, &attr) < 0) { 480 wpa_printf(MSG_DEBUG, "WPS ER: Failed to parse M1"); 481 return; 482 } 483 if (attr.primary_dev_type) 484 os_memcpy(ap->pri_dev_type, attr.primary_dev_type, 8); 485 if (attr.wps_state) 486 ap->wps_state = *attr.wps_state; 487 if (attr.mac_addr) 488 os_memcpy(ap->mac_addr, attr.mac_addr, ETH_ALEN); 489 490 wps_er_subscribe(ap); 491} 492 493 494static void wps_er_get_device_info(struct wps_er_ap *ap) 495{ 496 wps_er_send_get_device_info(ap, wps_er_ap_get_m1); 497} 498 499 500static const char * wps_er_find_wfadevice(const char *data) 501{ 502 const char *tag, *tagname, *end; 503 char *val; 504 int found = 0; 505 506 while (!found) { 507 /* Find next <device> */ 508 for (;;) { 509 if (xml_next_tag(data, &tag, &tagname, &end)) 510 return NULL; 511 data = end; 512 if (!os_strncasecmp(tagname, "device", 6) && 513 *tag != '/' && 514 (tagname[6] == '>' || !isgraph(tagname[6]))) { 515 break; 516 } 517 } 518 519 /* Check whether deviceType is WFADevice */ 520 val = xml_get_first_item(data, "deviceType"); 521 if (val == NULL) 522 return NULL; 523 wpa_printf(MSG_DEBUG, "WPS ER: Found deviceType '%s'", val); 524 found = os_strcasecmp(val, "urn:schemas-wifialliance-org:" 525 "device:WFADevice:1") == 0; 526 os_free(val); 527 } 528 529 return data; 530} 531 532 533static void wps_er_parse_device_description(struct wps_er_ap *ap, 534 struct wpabuf *reply) 535{ 536 /* Note: reply includes null termination after the buffer data */ 537 const char *tmp, *data = wpabuf_head(reply); 538 char *pos; 539 540 wpa_hexdump_ascii(MSG_MSGDUMP, "WPS ER: Device info", 541 wpabuf_head(reply), wpabuf_len(reply)); 542 543 /* 544 * The root device description may include multiple devices, so first 545 * find the beginning of the WFADevice description to allow the 546 * simplistic parser to pick the correct entries. 547 */ 548 tmp = wps_er_find_wfadevice(data); 549 if (tmp == NULL) { 550 wpa_printf(MSG_DEBUG, "WPS ER: WFADevice:1 device not found - " 551 "trying to parse invalid data"); 552 } else 553 data = tmp; 554 555 ap->friendly_name = xml_get_first_item(data, "friendlyName"); 556 wpa_printf(MSG_DEBUG, "WPS ER: friendlyName='%s'", ap->friendly_name); 557 558 ap->manufacturer = xml_get_first_item(data, "manufacturer"); 559 wpa_printf(MSG_DEBUG, "WPS ER: manufacturer='%s'", ap->manufacturer); 560 561 ap->manufacturer_url = xml_get_first_item(data, "manufacturerURL"); 562 wpa_printf(MSG_DEBUG, "WPS ER: manufacturerURL='%s'", 563 ap->manufacturer_url); 564 565 ap->model_description = xml_get_first_item(data, "modelDescription"); 566 wpa_printf(MSG_DEBUG, "WPS ER: modelDescription='%s'", 567 ap->model_description); 568 569 ap->model_name = xml_get_first_item(data, "modelName"); 570 wpa_printf(MSG_DEBUG, "WPS ER: modelName='%s'", ap->model_name); 571 572 ap->model_number = xml_get_first_item(data, "modelNumber"); 573 wpa_printf(MSG_DEBUG, "WPS ER: modelNumber='%s'", ap->model_number); 574 575 ap->model_url = xml_get_first_item(data, "modelURL"); 576 wpa_printf(MSG_DEBUG, "WPS ER: modelURL='%s'", ap->model_url); 577 578 ap->serial_number = xml_get_first_item(data, "serialNumber"); 579 wpa_printf(MSG_DEBUG, "WPS ER: serialNumber='%s'", ap->serial_number); 580 581 ap->udn = xml_get_first_item(data, "UDN"); 582 wpa_printf(MSG_DEBUG, "WPS ER: UDN='%s'", ap->udn); 583 pos = os_strstr(ap->udn, "uuid:"); 584 if (pos) { 585 pos += 5; 586 if (uuid_str2bin(pos, ap->uuid) < 0) 587 wpa_printf(MSG_DEBUG, "WPS ER: Invalid UUID in UDN"); 588 } 589 590 ap->upc = xml_get_first_item(data, "UPC"); 591 wpa_printf(MSG_DEBUG, "WPS ER: UPC='%s'", ap->upc); 592 593 ap->scpd_url = http_link_update( 594 xml_get_first_item(data, "SCPDURL"), ap->location); 595 wpa_printf(MSG_DEBUG, "WPS ER: SCPDURL='%s'", ap->scpd_url); 596 597 ap->control_url = http_link_update( 598 xml_get_first_item(data, "controlURL"), ap->location); 599 wpa_printf(MSG_DEBUG, "WPS ER: controlURL='%s'", ap->control_url); 600 601 ap->event_sub_url = http_link_update( 602 xml_get_first_item(data, "eventSubURL"), ap->location); 603 wpa_printf(MSG_DEBUG, "WPS ER: eventSubURL='%s'", ap->event_sub_url); 604} 605 606 607static void wps_er_http_dev_desc_cb(void *ctx, struct http_client *c, 608 enum http_client_event event) 609{ 610 struct wps_er_ap *ap = ctx; 611 struct wpabuf *reply; 612 int ok = 0; 613 614 switch (event) { 615 case HTTP_CLIENT_OK: 616 reply = http_client_get_body(c); 617 if (reply == NULL) 618 break; 619 wps_er_parse_device_description(ap, reply); 620 ok = 1; 621 break; 622 case HTTP_CLIENT_FAILED: 623 case HTTP_CLIENT_INVALID_REPLY: 624 case HTTP_CLIENT_TIMEOUT: 625 wpa_printf(MSG_DEBUG, "WPS ER: Failed to fetch device info"); 626 break; 627 } 628 http_client_free(ap->http); 629 ap->http = NULL; 630 if (ok) 631 wps_er_get_device_info(ap); 632} 633 634 635void wps_er_ap_add(struct wps_er *er, const u8 *uuid, struct in_addr *addr, 636 const char *location, int max_age) 637{ 638 struct wps_er_ap *ap; 639 640 ap = wps_er_ap_get(er, addr, uuid, NULL); 641 if (ap) { 642 /* Update advertisement timeout */ 643 eloop_cancel_timeout(wps_er_ap_timeout, er, ap); 644 eloop_register_timeout(max_age, 0, wps_er_ap_timeout, er, ap); 645 return; 646 } 647 648 ap = os_zalloc(sizeof(*ap)); 649 if (ap == NULL) 650 return; 651 dl_list_init(&ap->sta); 652 ap->er = er; 653 ap->id = ++er->next_ap_id; 654 ap->location = os_strdup(location); 655 if (ap->location == NULL) { 656 os_free(ap); 657 return; 658 } 659 dl_list_add(&er->ap, &ap->list); 660 661 ap->addr.s_addr = addr->s_addr; 662 os_memcpy(ap->uuid, uuid, WPS_UUID_LEN); 663 eloop_register_timeout(max_age, 0, wps_er_ap_timeout, er, ap); 664 665 wpa_printf(MSG_DEBUG, "WPS ER: Added AP entry for %s (%s)", 666 inet_ntoa(ap->addr), ap->location); 667 668 /* Fetch device description */ 669 ap->http = http_client_url(ap->location, NULL, 10000, 670 wps_er_http_dev_desc_cb, ap); 671} 672 673 674void wps_er_ap_remove(struct wps_er *er, struct in_addr *addr) 675{ 676 struct wps_er_ap *ap; 677 dl_list_for_each(ap, &er->ap, struct wps_er_ap, list) { 678 if (ap->addr.s_addr == addr->s_addr) { 679 wps_er_ap_remove_entry(er, ap); 680 return; 681 } 682 } 683} 684 685 686static void wps_er_ap_remove_all(struct wps_er *er) 687{ 688 struct wps_er_ap *prev, *ap; 689 struct wps_er_ap_settings *prev_s, *s; 690 dl_list_for_each_safe(ap, prev, &er->ap, struct wps_er_ap, list) 691 wps_er_ap_remove_entry(er, ap); 692 dl_list_for_each_safe(s, prev_s, &er->ap_settings, 693 struct wps_er_ap_settings, list) 694 os_free(s); 695} 696 697 698static void http_put_date(struct wpabuf *buf) 699{ 700 wpabuf_put_str(buf, "Date: "); 701 format_date(buf); 702 wpabuf_put_str(buf, "\r\n"); 703} 704 705 706static void wps_er_http_resp_not_found(struct http_request *req) 707{ 708 struct wpabuf *buf; 709 buf = wpabuf_alloc(200); 710 if (buf == NULL) { 711 http_request_deinit(req); 712 return; 713 } 714 715 wpabuf_put_str(buf, 716 "HTTP/1.1 404 Not Found\r\n" 717 "Server: unspecified, UPnP/1.0, unspecified\r\n" 718 "Connection: close\r\n"); 719 http_put_date(buf); 720 wpabuf_put_str(buf, "\r\n"); 721 http_request_send_and_deinit(req, buf); 722} 723 724 725static void wps_er_http_resp_ok(struct http_request *req) 726{ 727 struct wpabuf *buf; 728 buf = wpabuf_alloc(200); 729 if (buf == NULL) { 730 http_request_deinit(req); 731 return; 732 } 733 734 wpabuf_put_str(buf, 735 "HTTP/1.1 200 OK\r\n" 736 "Server: unspecified, UPnP/1.0, unspecified\r\n" 737 "Connection: close\r\n" 738 "Content-Length: 0\r\n"); 739 http_put_date(buf); 740 wpabuf_put_str(buf, "\r\n"); 741 http_request_send_and_deinit(req, buf); 742} 743 744 745static void wps_er_sta_timeout(void *eloop_data, void *user_ctx) 746{ 747 struct wps_er_sta *sta = eloop_data; 748 wpa_printf(MSG_DEBUG, "WPS ER: STA entry timed out"); 749 dl_list_del(&sta->list); 750 wps_er_sta_free(sta); 751} 752 753 754static struct wps_er_sta * wps_er_add_sta_data(struct wps_er_ap *ap, 755 const u8 *addr, 756 struct wps_parse_attr *attr, 757 int probe_req) 758{ 759 struct wps_er_sta *sta = wps_er_sta_get(ap, addr, NULL); 760 int new_sta = 0; 761 int m1; 762 763 m1 = !probe_req && attr->msg_type && *attr->msg_type == WPS_M1; 764 765 if (sta == NULL) { 766 /* 767 * Only allow new STA entry to be added based on Probe Request 768 * or M1. This will filter out bogus events and anything that 769 * may have been ongoing at the time ER subscribed for events. 770 */ 771 if (!probe_req && !m1) 772 return NULL; 773 774 sta = os_zalloc(sizeof(*sta)); 775 if (sta == NULL) 776 return NULL; 777 os_memcpy(sta->addr, addr, ETH_ALEN); 778 sta->ap = ap; 779 dl_list_add(&ap->sta, &sta->list); 780 new_sta = 1; 781 } 782 783 if (m1) 784 sta->m1_received = 1; 785 786 if (attr->config_methods && (!probe_req || !sta->m1_received)) 787 sta->config_methods = WPA_GET_BE16(attr->config_methods); 788 if (attr->uuid_e && (!probe_req || !sta->m1_received)) 789 os_memcpy(sta->uuid, attr->uuid_e, WPS_UUID_LEN); 790 if (attr->primary_dev_type && (!probe_req || !sta->m1_received)) 791 os_memcpy(sta->pri_dev_type, attr->primary_dev_type, 8); 792 if (attr->dev_password_id && (!probe_req || !sta->m1_received)) 793 sta->dev_passwd_id = WPA_GET_BE16(attr->dev_password_id); 794 795 if (attr->manufacturer) { 796 os_free(sta->manufacturer); 797 sta->manufacturer = dup_binstr(attr->manufacturer, 798 attr->manufacturer_len); 799 } 800 801 if (attr->model_name) { 802 os_free(sta->model_name); 803 sta->model_name = dup_binstr(attr->model_name, 804 attr->model_name_len); 805 } 806 807 if (attr->model_number) { 808 os_free(sta->model_number); 809 sta->model_number = dup_binstr(attr->model_number, 810 attr->model_number_len); 811 } 812 813 if (attr->serial_number) { 814 os_free(sta->serial_number); 815 sta->serial_number = dup_binstr(attr->serial_number, 816 attr->serial_number_len); 817 } 818 819 if (attr->dev_name) { 820 os_free(sta->dev_name); 821 sta->dev_name = dup_binstr(attr->dev_name, attr->dev_name_len); 822 } 823 824 eloop_cancel_timeout(wps_er_sta_timeout, sta, NULL); 825 eloop_register_timeout(300, 0, wps_er_sta_timeout, sta, NULL); 826 827 if (m1 || new_sta) 828 wps_er_sta_event(ap->er->wps, sta, WPS_EV_ER_ENROLLEE_ADD); 829 830 return sta; 831} 832 833 834static void wps_er_process_wlanevent_probe_req(struct wps_er_ap *ap, 835 const u8 *addr, 836 struct wpabuf *msg) 837{ 838 struct wps_parse_attr attr; 839 840 wpa_printf(MSG_DEBUG, "WPS ER: WLANEvent - Probe Request - from " 841 MACSTR, MAC2STR(addr)); 842 wpa_hexdump_buf(MSG_MSGDUMP, "WPS ER: WLANEvent - Enrollee's message " 843 "(TLVs from Probe Request)", msg); 844 845 if (wps_validate_probe_req(msg, addr) < 0) { 846 wpa_printf(MSG_INFO, "WPS-STRICT: ER: Ignore invalid proxied " 847 "Probe Request frame from " MACSTR, MAC2STR(addr)); 848 return; 849 } 850 851 if (wps_parse_msg(msg, &attr) < 0) { 852 wpa_printf(MSG_DEBUG, "WPS ER: Failed to parse TLVs in " 853 "WLANEvent message"); 854 return; 855 } 856 857 wps_er_add_sta_data(ap, addr, &attr, 1); 858 wps_registrar_probe_req_rx(ap->er->wps->registrar, addr, msg, 0); 859} 860 861 862static void wps_er_http_put_wlan_response_cb(void *ctx, struct http_client *c, 863 enum http_client_event event) 864{ 865 struct wps_er_sta *sta = ctx; 866 867 switch (event) { 868 case HTTP_CLIENT_OK: 869 wpa_printf(MSG_DEBUG, "WPS ER: PutWLANResponse OK"); 870 break; 871 case HTTP_CLIENT_FAILED: 872 case HTTP_CLIENT_INVALID_REPLY: 873 case HTTP_CLIENT_TIMEOUT: 874 wpa_printf(MSG_DEBUG, "WPS ER: PutWLANResponse failed"); 875 break; 876 } 877 http_client_free(sta->http); 878 sta->http = NULL; 879} 880 881 882static const char *soap_prefix = 883 "<?xml version=\"1.0\"?>\n" 884 "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" " 885 "s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">\n" 886 "<s:Body>\n"; 887static const char *soap_postfix = 888 "</s:Body>\n</s:Envelope>\n"; 889static const char *urn_wfawlanconfig = 890 "urn:schemas-wifialliance-org:service:WFAWLANConfig:1"; 891 892static struct wpabuf * wps_er_soap_hdr(const struct wpabuf *msg, 893 const char *name, const char *arg_name, 894 const char *path, 895 const struct sockaddr_in *dst, 896 char **len_ptr, char **body_ptr) 897{ 898 unsigned char *encoded; 899 size_t encoded_len; 900 struct wpabuf *buf; 901 902 if (msg) { 903 encoded = base64_encode(wpabuf_head(msg), wpabuf_len(msg), 904 &encoded_len); 905 if (encoded == NULL) 906 return NULL; 907 } else { 908 encoded = NULL; 909 encoded_len = 0; 910 } 911 912 buf = wpabuf_alloc(1000 + encoded_len); 913 if (buf == NULL) { 914 os_free(encoded); 915 return NULL; 916 } 917 918 wpabuf_printf(buf, 919 "POST %s HTTP/1.1\r\n" 920 "Host: %s:%d\r\n" 921 "Content-Type: text/xml; charset=\"utf-8\"\r\n" 922 "Content-Length: ", 923 path, inet_ntoa(dst->sin_addr), ntohs(dst->sin_port)); 924 925 *len_ptr = wpabuf_put(buf, 0); 926 wpabuf_printf(buf, 927 " \r\n" 928 "SOAPACTION: \"%s#%s\"\r\n" 929 "\r\n", 930 urn_wfawlanconfig, name); 931 932 *body_ptr = wpabuf_put(buf, 0); 933 934 wpabuf_put_str(buf, soap_prefix); 935 wpabuf_printf(buf, "<u:%s xmlns:u=\"", name); 936 wpabuf_put_str(buf, urn_wfawlanconfig); 937 wpabuf_put_str(buf, "\">\n"); 938 if (encoded) { 939 wpabuf_printf(buf, "<%s>%s</%s>\n", 940 arg_name, (char *) encoded, arg_name); 941 os_free(encoded); 942 } 943 944 return buf; 945} 946 947 948static void wps_er_soap_end(struct wpabuf *buf, const char *name, 949 char *len_ptr, char *body_ptr) 950{ 951 char len_buf[10]; 952 wpabuf_printf(buf, "</u:%s>\n", name); 953 wpabuf_put_str(buf, soap_postfix); 954 os_snprintf(len_buf, sizeof(len_buf), "%d", 955 (int) ((char *) wpabuf_put(buf, 0) - body_ptr)); 956 os_memcpy(len_ptr, len_buf, os_strlen(len_buf)); 957} 958 959 960static void wps_er_sta_send_msg(struct wps_er_sta *sta, struct wpabuf *msg) 961{ 962 struct wpabuf *buf; 963 char *len_ptr, *body_ptr; 964 struct sockaddr_in dst; 965 char *url, *path; 966 967 if (sta->http) { 968 wpa_printf(MSG_DEBUG, "WPS ER: Pending HTTP request for STA - " 969 "ignore new request"); 970 wpabuf_free(msg); 971 return; 972 } 973 974 if (sta->ap->control_url == NULL) { 975 wpa_printf(MSG_DEBUG, "WPS ER: No controlURL for AP"); 976 wpabuf_free(msg); 977 return; 978 } 979 980 url = http_client_url_parse(sta->ap->control_url, &dst, &path); 981 if (url == NULL) { 982 wpa_printf(MSG_DEBUG, "WPS ER: Failed to parse controlURL"); 983 wpabuf_free(msg); 984 return; 985 } 986 987 buf = wps_er_soap_hdr(msg, "PutWLANResponse", "NewMessage", path, &dst, 988 &len_ptr, &body_ptr); 989 wpabuf_free(msg); 990 os_free(url); 991 if (buf == NULL) 992 return; 993 wpabuf_printf(buf, "<NewWLANEventType>%d</NewWLANEventType>\n", 994 UPNP_WPS_WLANEVENT_TYPE_EAP); 995 wpabuf_printf(buf, "<NewWLANEventMAC>" MACSTR "</NewWLANEventMAC>\n", 996 MAC2STR(sta->addr)); 997 998 wps_er_soap_end(buf, "PutWLANResponse", len_ptr, body_ptr); 999 1000 sta->http = http_client_addr(&dst, buf, 1000, 1001 wps_er_http_put_wlan_response_cb, sta); 1002 if (sta->http == NULL) 1003 wpabuf_free(buf); 1004} 1005 1006 1007static void wps_er_sta_process(struct wps_er_sta *sta, struct wpabuf *msg, 1008 enum wsc_op_code op_code) 1009{ 1010 enum wps_process_res res; 1011 1012 res = wps_process_msg(sta->wps, op_code, msg); 1013 if (res == WPS_CONTINUE) { 1014 struct wpabuf *next = wps_get_msg(sta->wps, &op_code); 1015 if (next) 1016 wps_er_sta_send_msg(sta, next); 1017 } else { 1018 wpa_printf(MSG_DEBUG, "WPS ER: Protocol run %s with the " 1019 "enrollee (res=%d)", 1020 res == WPS_DONE ? "succeeded" : "failed", res); 1021 wps_deinit(sta->wps); 1022 sta->wps = NULL; 1023 if (res == WPS_DONE) { 1024 /* Remove the STA entry after short timeout */ 1025 eloop_cancel_timeout(wps_er_sta_timeout, sta, NULL); 1026 eloop_register_timeout(10, 0, wps_er_sta_timeout, sta, 1027 NULL); 1028 } 1029 } 1030} 1031 1032 1033static void wps_er_sta_start(struct wps_er_sta *sta, struct wpabuf *msg) 1034{ 1035 struct wps_config cfg; 1036 1037 if (sta->wps) 1038 wps_deinit(sta->wps); 1039 1040 os_memset(&cfg, 0, sizeof(cfg)); 1041 cfg.wps = sta->ap->er->wps; 1042 cfg.registrar = 1; 1043 cfg.peer_addr = sta->addr; 1044 1045 sta->wps = wps_init(&cfg); 1046 if (sta->wps == NULL) 1047 return; 1048 sta->wps->er = 1; 1049 sta->wps->use_cred = sta->ap->ap_settings; 1050 if (sta->ap->ap_settings) { 1051 os_free(sta->cred); 1052 sta->cred = os_malloc(sizeof(*sta->cred)); 1053 if (sta->cred) { 1054 os_memcpy(sta->cred, sta->ap->ap_settings, 1055 sizeof(*sta->cred)); 1056 sta->cred->cred_attr = NULL; 1057 os_memcpy(sta->cred->mac_addr, sta->addr, ETH_ALEN); 1058 sta->wps->use_cred = sta->cred; 1059 } 1060 } 1061 1062 wps_er_sta_process(sta, msg, WSC_MSG); 1063} 1064 1065 1066static void wps_er_process_wlanevent_eap(struct wps_er_ap *ap, const u8 *addr, 1067 struct wpabuf *msg) 1068{ 1069 struct wps_parse_attr attr; 1070 struct wps_er_sta *sta; 1071 1072 wpa_printf(MSG_DEBUG, "WPS ER: WLANEvent - EAP - from " MACSTR, 1073 MAC2STR(addr)); 1074 wpa_hexdump_buf(MSG_MSGDUMP, "WPS ER: WLANEvent - Enrollee's message " 1075 "(TLVs from EAP-WSC)", msg); 1076 1077 if (wps_parse_msg(msg, &attr) < 0) { 1078 wpa_printf(MSG_DEBUG, "WPS ER: Failed to parse TLVs in " 1079 "WLANEvent message"); 1080 return; 1081 } 1082 1083 sta = wps_er_add_sta_data(ap, addr, &attr, 0); 1084 if (sta == NULL) 1085 return; 1086 1087 if (attr.msg_type && *attr.msg_type == WPS_M1) 1088 wps_er_sta_start(sta, msg); 1089 else if (sta->wps) { 1090 enum wsc_op_code op_code = WSC_MSG; 1091 if (attr.msg_type) { 1092 switch (*attr.msg_type) { 1093 case WPS_WSC_ACK: 1094 op_code = WSC_ACK; 1095 break; 1096 case WPS_WSC_NACK: 1097 op_code = WSC_NACK; 1098 break; 1099 case WPS_WSC_DONE: 1100 op_code = WSC_Done; 1101 break; 1102 } 1103 } 1104 wps_er_sta_process(sta, msg, op_code); 1105 } 1106} 1107 1108 1109static void wps_er_process_wlanevent(struct wps_er_ap *ap, 1110 struct wpabuf *event) 1111{ 1112 u8 *data; 1113 u8 wlan_event_type; 1114 u8 wlan_event_mac[ETH_ALEN]; 1115 struct wpabuf msg; 1116 1117 wpa_hexdump(MSG_MSGDUMP, "WPS ER: Received WLANEvent", 1118 wpabuf_head(event), wpabuf_len(event)); 1119 if (wpabuf_len(event) < 1 + 17) { 1120 wpa_printf(MSG_DEBUG, "WPS ER: Too short WLANEvent"); 1121 return; 1122 } 1123 1124 data = wpabuf_mhead(event); 1125 wlan_event_type = data[0]; 1126 if (hwaddr_aton((char *) data + 1, wlan_event_mac) < 0) { 1127 wpa_printf(MSG_DEBUG, "WPS ER: Invalid WLANEventMAC in " 1128 "WLANEvent"); 1129 return; 1130 } 1131 1132 wpabuf_set(&msg, data + 1 + 17, wpabuf_len(event) - (1 + 17)); 1133 1134 switch (wlan_event_type) { 1135 case 1: 1136 wps_er_process_wlanevent_probe_req(ap, wlan_event_mac, &msg); 1137 break; 1138 case 2: 1139 wps_er_process_wlanevent_eap(ap, wlan_event_mac, &msg); 1140 break; 1141 default: 1142 wpa_printf(MSG_DEBUG, "WPS ER: Unknown WLANEventType %d", 1143 wlan_event_type); 1144 break; 1145 } 1146} 1147 1148 1149static void wps_er_http_event(struct wps_er *er, struct http_request *req, 1150 unsigned int ap_id) 1151{ 1152 struct wps_er_ap *ap = wps_er_ap_get_id(er, ap_id); 1153 struct wpabuf *event; 1154 enum http_reply_code ret; 1155 1156 if (ap == NULL) { 1157 wpa_printf(MSG_DEBUG, "WPS ER: HTTP event from unknown AP id " 1158 "%u", ap_id); 1159 wps_er_http_resp_not_found(req); 1160 return; 1161 } 1162 wpa_printf(MSG_MSGDUMP, "WPS ER: HTTP event from AP id %u: %s", 1163 ap_id, http_request_get_data(req)); 1164 1165 event = xml_get_base64_item(http_request_get_data(req), "WLANEvent", 1166 &ret); 1167 if (event == NULL) { 1168 wpa_printf(MSG_DEBUG, "WPS ER: Could not extract WLANEvent " 1169 "from the event notification"); 1170 /* 1171 * Reply with OK anyway to avoid getting unregistered from 1172 * events. 1173 */ 1174 wps_er_http_resp_ok(req); 1175 return; 1176 } 1177 1178 wps_er_process_wlanevent(ap, event); 1179 1180 wpabuf_free(event); 1181 wps_er_http_resp_ok(req); 1182} 1183 1184 1185static void wps_er_http_notify(struct wps_er *er, struct http_request *req) 1186{ 1187 char *uri = http_request_get_uri(req); 1188 1189 if (os_strncmp(uri, "/event/", 7) == 0) { 1190 unsigned int event_id; 1191 char *pos; 1192 event_id = atoi(uri + 7); 1193 if (event_id != er->event_id) { 1194 wpa_printf(MSG_DEBUG, "WPS ER: HTTP event for an " 1195 "unknown event id %u", event_id); 1196 return; 1197 } 1198 pos = os_strchr(uri + 7, '/'); 1199 if (pos == NULL) 1200 return; 1201 pos++; 1202 wps_er_http_event(er, req, atoi(pos)); 1203 } else { 1204 wpa_printf(MSG_DEBUG, "WPS ER: Unknown HTTP NOTIFY for '%s'", 1205 uri); 1206 wps_er_http_resp_not_found(req); 1207 } 1208} 1209 1210 1211static void wps_er_http_req(void *ctx, struct http_request *req) 1212{ 1213 struct wps_er *er = ctx; 1214 struct sockaddr_in *cli = http_request_get_cli_addr(req); 1215 enum httpread_hdr_type type = http_request_get_type(req); 1216 struct wpabuf *buf; 1217 1218 wpa_printf(MSG_DEBUG, "WPS ER: HTTP request: '%s' (type %d) from " 1219 "%s:%d", 1220 http_request_get_uri(req), type, 1221 inet_ntoa(cli->sin_addr), ntohs(cli->sin_port)); 1222 1223 switch (type) { 1224 case HTTPREAD_HDR_TYPE_NOTIFY: 1225 wps_er_http_notify(er, req); 1226 break; 1227 default: 1228 wpa_printf(MSG_DEBUG, "WPS ER: Unsupported HTTP request type " 1229 "%d", type); 1230 buf = wpabuf_alloc(200); 1231 if (buf == NULL) { 1232 http_request_deinit(req); 1233 return; 1234 } 1235 wpabuf_put_str(buf, 1236 "HTTP/1.1 501 Unimplemented\r\n" 1237 "Connection: close\r\n"); 1238 http_put_date(buf); 1239 wpabuf_put_str(buf, "\r\n"); 1240 http_request_send_and_deinit(req, buf); 1241 break; 1242 } 1243} 1244 1245 1246struct wps_er * 1247wps_er_init(struct wps_context *wps, const char *ifname, const char *filter) 1248{ 1249 struct wps_er *er; 1250 struct in_addr addr; 1251 1252 er = os_zalloc(sizeof(*er)); 1253 if (er == NULL) 1254 return NULL; 1255 dl_list_init(&er->ap); 1256 dl_list_init(&er->ap_unsubscribing); 1257 dl_list_init(&er->ap_settings); 1258 1259 er->multicast_sd = -1; 1260 er->ssdp_sd = -1; 1261 1262 os_strlcpy(er->ifname, ifname, sizeof(er->ifname)); 1263 er->wps = wps; 1264 if (os_get_random((unsigned char *) &er->event_id, 1265 sizeof(er->event_id)) < 0) { 1266 wps_er_deinit(er, NULL, NULL); 1267 return NULL; 1268 } 1269 /* Limit event_id to < 32 bits to avoid issues with atoi() */ 1270 er->event_id &= 0x0fffffff; 1271 1272 if (filter && os_strncmp(filter, "ifname=", 7) == 0) { 1273 const char *pos, *end; 1274 pos = filter + 7; 1275 end = os_strchr(pos, ' '); 1276 if (end) { 1277 size_t len = end - pos; 1278 os_strlcpy(er->ifname, pos, len < sizeof(er->ifname) ? 1279 len + 1 : sizeof(er->ifname)); 1280 filter = end + 1; 1281 } else { 1282 os_strlcpy(er->ifname, pos, sizeof(er->ifname)); 1283 filter = NULL; 1284 } 1285 er->forced_ifname = 1; 1286 } 1287 1288 if (filter) { 1289 if (inet_aton(filter, &er->filter_addr) == 0) { 1290 wpa_printf(MSG_INFO, "WPS UPnP: Invalid filter " 1291 "address %s", filter); 1292 wps_er_deinit(er, NULL, NULL); 1293 return NULL; 1294 } 1295 wpa_printf(MSG_DEBUG, "WPS UPnP: Only accepting connections " 1296 "with %s", filter); 1297 } 1298 if (get_netif_info(er->ifname, &er->ip_addr, &er->ip_addr_text, 1299 er->mac_addr)) { 1300 wpa_printf(MSG_INFO, "WPS UPnP: Could not get IP/MAC address " 1301 "for %s. Does it have IP address?", er->ifname); 1302 wps_er_deinit(er, NULL, NULL); 1303 return NULL; 1304 } 1305 1306 if (wps_er_ssdp_init(er) < 0) { 1307 wpa_printf(MSG_INFO, "WPS UPnP: SSDP initialization failed"); 1308 wps_er_deinit(er, NULL, NULL); 1309 return NULL; 1310 } 1311 1312 addr.s_addr = er->ip_addr; 1313 er->http_srv = http_server_init(&addr, -1, wps_er_http_req, er); 1314 if (er->http_srv == NULL) { 1315 wpa_printf(MSG_INFO, "WPS UPnP: HTTP initialization failed"); 1316 wps_er_deinit(er, NULL, NULL); 1317 return NULL; 1318 } 1319 er->http_port = http_server_get_port(er->http_srv); 1320 1321 wpa_printf(MSG_DEBUG, "WPS ER: Start (ifname=%s ip_addr=%s)", 1322 er->ifname, er->ip_addr_text); 1323 1324 return er; 1325} 1326 1327 1328void wps_er_refresh(struct wps_er *er) 1329{ 1330 struct wps_er_ap *ap; 1331 struct wps_er_sta *sta; 1332 1333 dl_list_for_each(ap, &er->ap, struct wps_er_ap, list) { 1334 wps_er_ap_event(er->wps, ap, WPS_EV_ER_AP_ADD); 1335 dl_list_for_each(sta, &ap->sta, struct wps_er_sta, list) 1336 wps_er_sta_event(er->wps, sta, WPS_EV_ER_ENROLLEE_ADD); 1337 } 1338 1339 wps_er_send_ssdp_msearch(er); 1340} 1341 1342 1343static void wps_er_deinit_finish(void *eloop_data, void *user_ctx) 1344{ 1345 struct wps_er *er = eloop_data; 1346 void (*deinit_done_cb)(void *ctx); 1347 void *deinit_done_ctx; 1348 struct wps_er_ap *ap, *tmp; 1349 1350 wpa_printf(MSG_DEBUG, "WPS ER: Finishing deinit"); 1351 1352 dl_list_for_each_safe(ap, tmp, &er->ap_unsubscribing, struct wps_er_ap, 1353 list) { 1354 wpa_printf(MSG_DEBUG, "WPS ER: AP entry for %s (%s) still in ap_unsubscribing list - free it", 1355 inet_ntoa(ap->addr), ap->location); 1356 dl_list_del(&ap->list); 1357 wps_er_ap_free(ap); 1358 } 1359 1360 eloop_cancel_timeout(wps_er_deinit_finish, er, NULL); 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 1371void 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 1387static 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 1418static 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 1463static 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 1472static 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 1481static 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 1491static 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 1502void 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 1564int wps_er_pbc(struct wps_er *er, const u8 *uuid, const u8 *addr) 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 if (uuid) 1579 ap = wps_er_ap_get(er, NULL, uuid, NULL); 1580 else 1581 ap = NULL; 1582 if (ap == NULL) { 1583 struct wps_er_sta *sta = NULL; 1584 dl_list_for_each(ap, &er->ap, struct wps_er_ap, list) { 1585 sta = wps_er_sta_get(ap, addr, uuid); 1586 if (sta) { 1587 uuid = ap->uuid; 1588 break; 1589 } 1590 } 1591 if (sta == NULL) 1592 return -3; /* Unknown UUID */ 1593 } 1594 1595 if (ap->ap_settings == NULL) { 1596 wpa_printf(MSG_DEBUG, "WPS ER: AP settings not known"); 1597 return -4; 1598 } 1599 1600 er->set_sel_reg_uuid_filter = uuid; 1601 res = wps_registrar_button_pushed(er->wps->registrar, NULL); 1602 er->set_sel_reg_uuid_filter = NULL; 1603 if (res) 1604 return -1; 1605 1606 return 0; 1607} 1608 1609 1610static void wps_er_ap_settings_cb(void *ctx, const struct wps_credential *cred) 1611{ 1612 struct wps_er_ap *ap = ctx; 1613 union wps_event_data data; 1614 1615 wpa_printf(MSG_DEBUG, "WPS ER: AP Settings received"); 1616 os_free(ap->ap_settings); 1617 ap->ap_settings = os_malloc(sizeof(*cred)); 1618 if (ap->ap_settings) { 1619 os_memcpy(ap->ap_settings, cred, sizeof(*cred)); 1620 ap->ap_settings->cred_attr = NULL; 1621 } 1622 1623 os_memset(&data, 0, sizeof(data)); 1624 data.ap_settings.uuid = ap->uuid; 1625 data.ap_settings.cred = cred; 1626 ap->er->wps->event_cb(ap->er->wps->cb_ctx, WPS_EV_ER_AP_SETTINGS, 1627 &data); 1628} 1629 1630 1631const u8 * wps_er_get_sta_uuid(struct wps_er *er, const u8 *addr) 1632{ 1633 struct wps_er_ap *ap; 1634 dl_list_for_each(ap, &er->ap, struct wps_er_ap, list) { 1635 struct wps_er_sta *sta; 1636 sta = wps_er_sta_get(ap, addr, NULL); 1637 if (sta) 1638 return sta->uuid; 1639 } 1640 return NULL; 1641} 1642 1643 1644static void wps_er_http_put_message_cb(void *ctx, struct http_client *c, 1645 enum http_client_event event) 1646{ 1647 struct wps_er_ap *ap = ctx; 1648 struct wpabuf *reply; 1649 char *msg = NULL; 1650 1651 switch (event) { 1652 case HTTP_CLIENT_OK: 1653 wpa_printf(MSG_DEBUG, "WPS ER: PutMessage OK"); 1654 reply = http_client_get_body(c); 1655 if (reply == NULL) 1656 break; 1657 msg = os_zalloc(wpabuf_len(reply) + 1); 1658 if (msg == NULL) 1659 break; 1660 os_memcpy(msg, wpabuf_head(reply), wpabuf_len(reply)); 1661 break; 1662 case HTTP_CLIENT_FAILED: 1663 case HTTP_CLIENT_INVALID_REPLY: 1664 case HTTP_CLIENT_TIMEOUT: 1665 wpa_printf(MSG_DEBUG, "WPS ER: PutMessage failed"); 1666 if (ap->wps) { 1667 wps_deinit(ap->wps); 1668 ap->wps = NULL; 1669 } 1670 break; 1671 } 1672 http_client_free(ap->http); 1673 ap->http = NULL; 1674 1675 if (msg) { 1676 struct wpabuf *buf; 1677 enum http_reply_code ret; 1678 buf = xml_get_base64_item(msg, "NewOutMessage", &ret); 1679 os_free(msg); 1680 if (buf == NULL) { 1681 wpa_printf(MSG_DEBUG, "WPS ER: Could not extract " 1682 "NewOutMessage from PutMessage response"); 1683 wps_deinit(ap->wps); 1684 ap->wps = NULL; 1685 return; 1686 } 1687 wps_er_ap_process(ap, buf); 1688 wpabuf_free(buf); 1689 } 1690} 1691 1692 1693static void wps_er_ap_put_message(struct wps_er_ap *ap, 1694 const struct wpabuf *msg) 1695{ 1696 struct wpabuf *buf; 1697 char *len_ptr, *body_ptr; 1698 struct sockaddr_in dst; 1699 char *url, *path; 1700 1701 if (ap->http) { 1702 wpa_printf(MSG_DEBUG, "WPS ER: Pending HTTP operation ongoing " 1703 "with the AP - cannot continue learn"); 1704 return; 1705 } 1706 1707 if (ap->control_url == NULL) { 1708 wpa_printf(MSG_DEBUG, "WPS ER: No controlURL for AP"); 1709 return; 1710 } 1711 1712 url = http_client_url_parse(ap->control_url, &dst, &path); 1713 if (url == NULL) { 1714 wpa_printf(MSG_DEBUG, "WPS ER: Failed to parse controlURL"); 1715 return; 1716 } 1717 1718 buf = wps_er_soap_hdr(msg, "PutMessage", "NewInMessage", path, &dst, 1719 &len_ptr, &body_ptr); 1720 os_free(url); 1721 if (buf == NULL) 1722 return; 1723 1724 wps_er_soap_end(buf, "PutMessage", len_ptr, body_ptr); 1725 1726 ap->http = http_client_addr(&dst, buf, 10000, 1727 wps_er_http_put_message_cb, ap); 1728 if (ap->http == NULL) 1729 wpabuf_free(buf); 1730} 1731 1732 1733static void wps_er_ap_process(struct wps_er_ap *ap, struct wpabuf *msg) 1734{ 1735 enum wps_process_res res; 1736 struct wps_parse_attr attr; 1737 enum wsc_op_code op_code; 1738 1739 op_code = WSC_MSG; 1740 if (wps_parse_msg(msg, &attr) == 0 && attr.msg_type) { 1741 switch (*attr.msg_type) { 1742 case WPS_WSC_ACK: 1743 op_code = WSC_ACK; 1744 break; 1745 case WPS_WSC_NACK: 1746 op_code = WSC_NACK; 1747 break; 1748 case WPS_WSC_DONE: 1749 op_code = WSC_Done; 1750 break; 1751 } 1752 } 1753 1754 res = wps_process_msg(ap->wps, op_code, msg); 1755 if (res == WPS_CONTINUE) { 1756 struct wpabuf *next = wps_get_msg(ap->wps, &op_code); 1757 if (next) { 1758 wps_er_ap_put_message(ap, next); 1759 wpabuf_free(next); 1760 } else { 1761 wpa_printf(MSG_DEBUG, "WPS ER: Failed to build " 1762 "message"); 1763 wps_deinit(ap->wps); 1764 ap->wps = NULL; 1765 } 1766 } else if (res == WPS_DONE) { 1767 wpa_printf(MSG_DEBUG, "WPS ER: Protocol run done"); 1768 wps_deinit(ap->wps); 1769 ap->wps = NULL; 1770 } else { 1771 wpa_printf(MSG_DEBUG, "WPS ER: Failed to process message from " 1772 "AP (res=%d)", res); 1773 wps_deinit(ap->wps); 1774 ap->wps = NULL; 1775 } 1776} 1777 1778 1779static void wps_er_ap_learn_m1(struct wps_er_ap *ap, struct wpabuf *m1) 1780{ 1781 struct wps_config cfg; 1782 1783 if (ap->wps) { 1784 wpa_printf(MSG_DEBUG, "WPS ER: Protocol run already in " 1785 "progress with this AP"); 1786 return; 1787 } 1788 1789 os_memset(&cfg, 0, sizeof(cfg)); 1790 cfg.wps = ap->er->wps; 1791 cfg.registrar = 1; 1792 ap->wps = wps_init(&cfg); 1793 if (ap->wps == NULL) 1794 return; 1795 ap->wps->ap_settings_cb = wps_er_ap_settings_cb; 1796 ap->wps->ap_settings_cb_ctx = ap; 1797 1798 wps_er_ap_process(ap, m1); 1799} 1800 1801 1802static void wps_er_ap_learn(struct wps_er_ap *ap, const char *dev_info) 1803{ 1804 struct wpabuf *info; 1805 enum http_reply_code ret; 1806 1807 wpa_printf(MSG_DEBUG, "WPS ER: Received GetDeviceInfo response (M1) " 1808 "from the AP"); 1809 info = xml_get_base64_item(dev_info, "NewDeviceInfo", &ret); 1810 if (info == NULL) { 1811 wpa_printf(MSG_DEBUG, "WPS ER: Could not extract " 1812 "NewDeviceInfo from GetDeviceInfo response"); 1813 return; 1814 } 1815 1816 ap->m1_handler(ap, info); 1817 wpabuf_free(info); 1818} 1819 1820 1821static void wps_er_http_get_dev_info_cb(void *ctx, struct http_client *c, 1822 enum http_client_event event) 1823{ 1824 struct wps_er_ap *ap = ctx; 1825 struct wpabuf *reply; 1826 char *dev_info = NULL; 1827 1828 switch (event) { 1829 case HTTP_CLIENT_OK: 1830 wpa_printf(MSG_DEBUG, "WPS ER: GetDeviceInfo OK"); 1831 reply = http_client_get_body(c); 1832 if (reply == NULL) 1833 break; 1834 dev_info = os_zalloc(wpabuf_len(reply) + 1); 1835 if (dev_info == NULL) 1836 break; 1837 os_memcpy(dev_info, wpabuf_head(reply), wpabuf_len(reply)); 1838 break; 1839 case HTTP_CLIENT_FAILED: 1840 case HTTP_CLIENT_INVALID_REPLY: 1841 case HTTP_CLIENT_TIMEOUT: 1842 wpa_printf(MSG_DEBUG, "WPS ER: GetDeviceInfo failed"); 1843 break; 1844 } 1845 http_client_free(ap->http); 1846 ap->http = NULL; 1847 1848 if (dev_info) { 1849 wps_er_ap_learn(ap, dev_info); 1850 os_free(dev_info); 1851 } 1852} 1853 1854 1855static int wps_er_send_get_device_info(struct wps_er_ap *ap, 1856 void (*m1_handler)(struct wps_er_ap *ap, 1857 struct wpabuf *m1)) 1858{ 1859 struct wpabuf *buf; 1860 char *len_ptr, *body_ptr; 1861 struct sockaddr_in dst; 1862 char *url, *path; 1863 1864 if (ap->http) { 1865 wpa_printf(MSG_DEBUG, "WPS ER: Pending HTTP operation ongoing " 1866 "with the AP - cannot get device info"); 1867 return -1; 1868 } 1869 1870 if (ap->control_url == NULL) { 1871 wpa_printf(MSG_DEBUG, "WPS ER: No controlURL for AP"); 1872 return -1; 1873 } 1874 1875 url = http_client_url_parse(ap->control_url, &dst, &path); 1876 if (url == NULL) { 1877 wpa_printf(MSG_DEBUG, "WPS ER: Failed to parse controlURL"); 1878 return -1; 1879 } 1880 1881 buf = wps_er_soap_hdr(NULL, "GetDeviceInfo", NULL, path, &dst, 1882 &len_ptr, &body_ptr); 1883 os_free(url); 1884 if (buf == NULL) 1885 return -1; 1886 1887 wps_er_soap_end(buf, "GetDeviceInfo", len_ptr, body_ptr); 1888 1889 ap->http = http_client_addr(&dst, buf, 10000, 1890 wps_er_http_get_dev_info_cb, ap); 1891 if (ap->http == NULL) { 1892 wpabuf_free(buf); 1893 return -1; 1894 } 1895 1896 ap->m1_handler = m1_handler; 1897 1898 return 0; 1899} 1900 1901 1902int wps_er_learn(struct wps_er *er, const u8 *uuid, const u8 *addr, 1903 const u8 *pin, size_t pin_len) 1904{ 1905 struct wps_er_ap *ap; 1906 1907 if (er == NULL) 1908 return -1; 1909 1910 ap = wps_er_ap_get(er, NULL, uuid, addr); 1911 if (ap == NULL) { 1912 wpa_printf(MSG_DEBUG, "WPS ER: AP not found for learn " 1913 "request"); 1914 return -1; 1915 } 1916 if (uuid == NULL) 1917 uuid = ap->uuid; 1918 if (ap->wps) { 1919 wpa_printf(MSG_DEBUG, "WPS ER: Pending operation ongoing " 1920 "with the AP - cannot start learn"); 1921 return -1; 1922 } 1923 1924 if (wps_er_send_get_device_info(ap, wps_er_ap_learn_m1) < 0) 1925 return -1; 1926 1927 er->skip_set_sel_reg = 1; 1928 wps_registrar_add_pin(er->wps->registrar, NULL, uuid, pin, pin_len, 0); 1929 er->skip_set_sel_reg = 0; 1930 1931 return 0; 1932} 1933 1934 1935int wps_er_set_config(struct wps_er *er, const u8 *uuid, const u8 *addr, 1936 const struct wps_credential *cred) 1937{ 1938 struct wps_er_ap *ap; 1939 1940 if (er == NULL) 1941 return -1; 1942 1943 ap = wps_er_ap_get(er, NULL, uuid, addr); 1944 if (ap == NULL) { 1945 wpa_printf(MSG_DEBUG, "WPS ER: AP not found for set config " 1946 "request"); 1947 return -1; 1948 } 1949 1950 os_free(ap->ap_settings); 1951 ap->ap_settings = os_malloc(sizeof(*cred)); 1952 if (ap->ap_settings == NULL) 1953 return -1; 1954 os_memcpy(ap->ap_settings, cred, sizeof(*cred)); 1955 ap->ap_settings->cred_attr = NULL; 1956 wpa_printf(MSG_DEBUG, "WPS ER: Updated local AP settings based set " 1957 "config request"); 1958 1959 return 0; 1960} 1961 1962 1963static void wps_er_ap_config_m1(struct wps_er_ap *ap, struct wpabuf *m1) 1964{ 1965 struct wps_config cfg; 1966 1967 if (ap->wps) { 1968 wpa_printf(MSG_DEBUG, "WPS ER: Protocol run already in " 1969 "progress with this AP"); 1970 return; 1971 } 1972 1973 os_memset(&cfg, 0, sizeof(cfg)); 1974 cfg.wps = ap->er->wps; 1975 cfg.registrar = 1; 1976 cfg.new_ap_settings = ap->ap_settings; 1977 ap->wps = wps_init(&cfg); 1978 if (ap->wps == NULL) 1979 return; 1980 ap->wps->ap_settings_cb = NULL; 1981 ap->wps->ap_settings_cb_ctx = NULL; 1982 1983 wps_er_ap_process(ap, m1); 1984} 1985 1986 1987int wps_er_config(struct wps_er *er, const u8 *uuid, const u8 *addr, 1988 const u8 *pin, size_t pin_len, 1989 const struct wps_credential *cred) 1990{ 1991 struct wps_er_ap *ap; 1992 1993 if (er == NULL) 1994 return -1; 1995 1996 ap = wps_er_ap_get(er, NULL, uuid, addr); 1997 if (ap == NULL) { 1998 wpa_printf(MSG_DEBUG, "WPS ER: AP not found for config " 1999 "request"); 2000 return -1; 2001 } 2002 if (uuid == NULL) 2003 uuid = ap->uuid; 2004 if (ap->wps) { 2005 wpa_printf(MSG_DEBUG, "WPS ER: Pending operation ongoing " 2006 "with the AP - cannot start config"); 2007 return -1; 2008 } 2009 2010 os_free(ap->ap_settings); 2011 ap->ap_settings = os_malloc(sizeof(*cred)); 2012 if (ap->ap_settings == NULL) 2013 return -1; 2014 os_memcpy(ap->ap_settings, cred, sizeof(*cred)); 2015 ap->ap_settings->cred_attr = NULL; 2016 2017 if (wps_er_send_get_device_info(ap, wps_er_ap_config_m1) < 0) 2018 return -1; 2019 2020 er->skip_set_sel_reg = 1; 2021 wps_registrar_add_pin(er->wps->registrar, NULL, uuid, pin, pin_len, 0); 2022 er->skip_set_sel_reg = 0; 2023 2024 return 0; 2025} 2026 2027 2028#ifdef CONFIG_WPS_NFC 2029 2030struct wpabuf * wps_er_config_token_from_cred(struct wps_context *wps, 2031 struct wps_credential *cred) 2032{ 2033 struct wpabuf *ret; 2034 struct wps_data data; 2035 2036 ret = wpabuf_alloc(500); 2037 if (ret == NULL) 2038 return NULL; 2039 2040 os_memset(&data, 0, sizeof(data)); 2041 data.wps = wps; 2042 data.use_cred = cred; 2043 if (wps_build_cred(&data, ret) || 2044 wps_build_wfa_ext(ret, 0, NULL, 0)) { 2045 wpabuf_free(ret); 2046 return NULL; 2047 } 2048 2049 return ret; 2050} 2051 2052 2053struct wpabuf * wps_er_nfc_config_token(struct wps_er *er, const u8 *uuid, 2054 const u8 *addr) 2055{ 2056 struct wps_er_ap *ap; 2057 2058 if (er == NULL) 2059 return NULL; 2060 2061 ap = wps_er_ap_get(er, NULL, uuid, addr); 2062 if (ap == NULL) 2063 return NULL; 2064 if (ap->ap_settings == NULL) { 2065 wpa_printf(MSG_DEBUG, "WPS ER: No settings known for the " 2066 "selected AP"); 2067 return NULL; 2068 } 2069 2070 return wps_er_config_token_from_cred(er->wps, ap->ap_settings); 2071} 2072 2073 2074struct wpabuf * wps_er_nfc_handover_sel(struct wps_er *er, 2075 struct wps_context *wps, const u8 *uuid, 2076 const u8 *addr, struct wpabuf *pubkey) 2077{ 2078 struct wps_er_ap *ap; 2079 2080 if (er == NULL) 2081 return NULL; 2082 2083 ap = wps_er_ap_get(er, NULL, uuid, addr); 2084 if (ap == NULL) 2085 return NULL; 2086 if (ap->ap_settings == NULL) { 2087 wpa_printf(MSG_DEBUG, "WPS ER: No settings known for the " 2088 "selected AP"); 2089 return NULL; 2090 } 2091 2092 os_memcpy(wps->ssid, ap->ap_settings->ssid, ap->ap_settings->ssid_len); 2093 wps->ssid_len = ap->ap_settings->ssid_len; 2094 2095 return wps_build_nfc_handover_sel(wps, pubkey, addr, 0); 2096} 2097 2098#endif /* CONFIG_WPS_NFC */ 2099