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 if (ap->udn) { 583 wpa_printf(MSG_DEBUG, "WPS ER: UDN='%s'", ap->udn); 584 pos = os_strstr(ap->udn, "uuid:"); 585 if (pos) { 586 pos += 5; 587 if (uuid_str2bin(pos, ap->uuid) < 0) 588 wpa_printf(MSG_DEBUG, 589 "WPS ER: Invalid UUID in UDN"); 590 } 591 } 592 593 ap->upc = xml_get_first_item(data, "UPC"); 594 wpa_printf(MSG_DEBUG, "WPS ER: UPC='%s'", ap->upc); 595 596 ap->scpd_url = http_link_update( 597 xml_get_first_item(data, "SCPDURL"), ap->location); 598 wpa_printf(MSG_DEBUG, "WPS ER: SCPDURL='%s'", ap->scpd_url); 599 600 ap->control_url = http_link_update( 601 xml_get_first_item(data, "controlURL"), ap->location); 602 wpa_printf(MSG_DEBUG, "WPS ER: controlURL='%s'", ap->control_url); 603 604 ap->event_sub_url = http_link_update( 605 xml_get_first_item(data, "eventSubURL"), ap->location); 606 wpa_printf(MSG_DEBUG, "WPS ER: eventSubURL='%s'", ap->event_sub_url); 607} 608 609 610static void wps_er_http_dev_desc_cb(void *ctx, struct http_client *c, 611 enum http_client_event event) 612{ 613 struct wps_er_ap *ap = ctx; 614 struct wpabuf *reply; 615 int ok = 0; 616 617 switch (event) { 618 case HTTP_CLIENT_OK: 619 reply = http_client_get_body(c); 620 if (reply == NULL) 621 break; 622 wps_er_parse_device_description(ap, reply); 623 ok = 1; 624 break; 625 case HTTP_CLIENT_FAILED: 626 case HTTP_CLIENT_INVALID_REPLY: 627 case HTTP_CLIENT_TIMEOUT: 628 wpa_printf(MSG_DEBUG, "WPS ER: Failed to fetch device info"); 629 break; 630 } 631 http_client_free(ap->http); 632 ap->http = NULL; 633 if (ok) 634 wps_er_get_device_info(ap); 635} 636 637 638void wps_er_ap_add(struct wps_er *er, const u8 *uuid, struct in_addr *addr, 639 const char *location, int max_age) 640{ 641 struct wps_er_ap *ap; 642 643 ap = wps_er_ap_get(er, addr, uuid, NULL); 644 if (ap) { 645 /* Update advertisement timeout */ 646 eloop_cancel_timeout(wps_er_ap_timeout, er, ap); 647 eloop_register_timeout(max_age, 0, wps_er_ap_timeout, er, ap); 648 return; 649 } 650 651 ap = os_zalloc(sizeof(*ap)); 652 if (ap == NULL) 653 return; 654 dl_list_init(&ap->sta); 655 ap->er = er; 656 ap->id = ++er->next_ap_id; 657 ap->location = os_strdup(location); 658 if (ap->location == NULL) { 659 os_free(ap); 660 return; 661 } 662 dl_list_add(&er->ap, &ap->list); 663 664 ap->addr.s_addr = addr->s_addr; 665 os_memcpy(ap->uuid, uuid, WPS_UUID_LEN); 666 eloop_register_timeout(max_age, 0, wps_er_ap_timeout, er, ap); 667 668 wpa_printf(MSG_DEBUG, "WPS ER: Added AP entry for %s (%s)", 669 inet_ntoa(ap->addr), ap->location); 670 671 /* Fetch device description */ 672 ap->http = http_client_url(ap->location, NULL, 10000, 673 wps_er_http_dev_desc_cb, ap); 674} 675 676 677void wps_er_ap_remove(struct wps_er *er, struct in_addr *addr) 678{ 679 struct wps_er_ap *ap; 680 dl_list_for_each(ap, &er->ap, struct wps_er_ap, list) { 681 if (ap->addr.s_addr == addr->s_addr) { 682 wps_er_ap_remove_entry(er, ap); 683 return; 684 } 685 } 686} 687 688 689static void wps_er_ap_remove_all(struct wps_er *er) 690{ 691 struct wps_er_ap *prev, *ap; 692 struct wps_er_ap_settings *prev_s, *s; 693 dl_list_for_each_safe(ap, prev, &er->ap, struct wps_er_ap, list) 694 wps_er_ap_remove_entry(er, ap); 695 dl_list_for_each_safe(s, prev_s, &er->ap_settings, 696 struct wps_er_ap_settings, list) 697 os_free(s); 698} 699 700 701static void http_put_date(struct wpabuf *buf) 702{ 703 wpabuf_put_str(buf, "Date: "); 704 format_date(buf); 705 wpabuf_put_str(buf, "\r\n"); 706} 707 708 709static void wps_er_http_resp_not_found(struct http_request *req) 710{ 711 struct wpabuf *buf; 712 buf = wpabuf_alloc(200); 713 if (buf == NULL) { 714 http_request_deinit(req); 715 return; 716 } 717 718 wpabuf_put_str(buf, 719 "HTTP/1.1 404 Not Found\r\n" 720 "Server: unspecified, UPnP/1.0, unspecified\r\n" 721 "Connection: close\r\n"); 722 http_put_date(buf); 723 wpabuf_put_str(buf, "\r\n"); 724 http_request_send_and_deinit(req, buf); 725} 726 727 728static void wps_er_http_resp_ok(struct http_request *req) 729{ 730 struct wpabuf *buf; 731 buf = wpabuf_alloc(200); 732 if (buf == NULL) { 733 http_request_deinit(req); 734 return; 735 } 736 737 wpabuf_put_str(buf, 738 "HTTP/1.1 200 OK\r\n" 739 "Server: unspecified, UPnP/1.0, unspecified\r\n" 740 "Connection: close\r\n" 741 "Content-Length: 0\r\n"); 742 http_put_date(buf); 743 wpabuf_put_str(buf, "\r\n"); 744 http_request_send_and_deinit(req, buf); 745} 746 747 748static void wps_er_sta_timeout(void *eloop_data, void *user_ctx) 749{ 750 struct wps_er_sta *sta = eloop_data; 751 wpa_printf(MSG_DEBUG, "WPS ER: STA entry timed out"); 752 dl_list_del(&sta->list); 753 wps_er_sta_free(sta); 754} 755 756 757static struct wps_er_sta * wps_er_add_sta_data(struct wps_er_ap *ap, 758 const u8 *addr, 759 struct wps_parse_attr *attr, 760 int probe_req) 761{ 762 struct wps_er_sta *sta = wps_er_sta_get(ap, addr, NULL); 763 int new_sta = 0; 764 int m1; 765 766 m1 = !probe_req && attr->msg_type && *attr->msg_type == WPS_M1; 767 768 if (sta == NULL) { 769 /* 770 * Only allow new STA entry to be added based on Probe Request 771 * or M1. This will filter out bogus events and anything that 772 * may have been ongoing at the time ER subscribed for events. 773 */ 774 if (!probe_req && !m1) 775 return NULL; 776 777 sta = os_zalloc(sizeof(*sta)); 778 if (sta == NULL) 779 return NULL; 780 os_memcpy(sta->addr, addr, ETH_ALEN); 781 sta->ap = ap; 782 dl_list_add(&ap->sta, &sta->list); 783 new_sta = 1; 784 } 785 786 if (m1) 787 sta->m1_received = 1; 788 789 if (attr->config_methods && (!probe_req || !sta->m1_received)) 790 sta->config_methods = WPA_GET_BE16(attr->config_methods); 791 if (attr->uuid_e && (!probe_req || !sta->m1_received)) 792 os_memcpy(sta->uuid, attr->uuid_e, WPS_UUID_LEN); 793 if (attr->primary_dev_type && (!probe_req || !sta->m1_received)) 794 os_memcpy(sta->pri_dev_type, attr->primary_dev_type, 8); 795 if (attr->dev_password_id && (!probe_req || !sta->m1_received)) 796 sta->dev_passwd_id = WPA_GET_BE16(attr->dev_password_id); 797 798 if (attr->manufacturer) { 799 os_free(sta->manufacturer); 800 sta->manufacturer = dup_binstr(attr->manufacturer, 801 attr->manufacturer_len); 802 } 803 804 if (attr->model_name) { 805 os_free(sta->model_name); 806 sta->model_name = dup_binstr(attr->model_name, 807 attr->model_name_len); 808 } 809 810 if (attr->model_number) { 811 os_free(sta->model_number); 812 sta->model_number = dup_binstr(attr->model_number, 813 attr->model_number_len); 814 } 815 816 if (attr->serial_number) { 817 os_free(sta->serial_number); 818 sta->serial_number = dup_binstr(attr->serial_number, 819 attr->serial_number_len); 820 } 821 822 if (attr->dev_name) { 823 os_free(sta->dev_name); 824 sta->dev_name = dup_binstr(attr->dev_name, attr->dev_name_len); 825 } 826 827 eloop_cancel_timeout(wps_er_sta_timeout, sta, NULL); 828 eloop_register_timeout(300, 0, wps_er_sta_timeout, sta, NULL); 829 830 if (m1 || new_sta) 831 wps_er_sta_event(ap->er->wps, sta, WPS_EV_ER_ENROLLEE_ADD); 832 833 return sta; 834} 835 836 837static void wps_er_process_wlanevent_probe_req(struct wps_er_ap *ap, 838 const u8 *addr, 839 struct wpabuf *msg) 840{ 841 struct wps_parse_attr attr; 842 843 wpa_printf(MSG_DEBUG, "WPS ER: WLANEvent - Probe Request - from " 844 MACSTR, MAC2STR(addr)); 845 wpa_hexdump_buf(MSG_MSGDUMP, "WPS ER: WLANEvent - Enrollee's message " 846 "(TLVs from Probe Request)", msg); 847 848 if (wps_validate_probe_req(msg, addr) < 0) { 849 wpa_printf(MSG_INFO, "WPS-STRICT: ER: Ignore invalid proxied " 850 "Probe Request frame from " MACSTR, MAC2STR(addr)); 851 return; 852 } 853 854 if (wps_parse_msg(msg, &attr) < 0) { 855 wpa_printf(MSG_DEBUG, "WPS ER: Failed to parse TLVs in " 856 "WLANEvent message"); 857 return; 858 } 859 860 wps_er_add_sta_data(ap, addr, &attr, 1); 861 wps_registrar_probe_req_rx(ap->er->wps->registrar, addr, msg, 0); 862} 863 864 865static void wps_er_http_put_wlan_response_cb(void *ctx, struct http_client *c, 866 enum http_client_event event) 867{ 868 struct wps_er_sta *sta = ctx; 869 870 switch (event) { 871 case HTTP_CLIENT_OK: 872 wpa_printf(MSG_DEBUG, "WPS ER: PutWLANResponse OK"); 873 break; 874 case HTTP_CLIENT_FAILED: 875 case HTTP_CLIENT_INVALID_REPLY: 876 case HTTP_CLIENT_TIMEOUT: 877 wpa_printf(MSG_DEBUG, "WPS ER: PutWLANResponse failed"); 878 break; 879 } 880 http_client_free(sta->http); 881 sta->http = NULL; 882} 883 884 885static const char *soap_prefix = 886 "<?xml version=\"1.0\"?>\n" 887 "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" " 888 "s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">\n" 889 "<s:Body>\n"; 890static const char *soap_postfix = 891 "</s:Body>\n</s:Envelope>\n"; 892static const char *urn_wfawlanconfig = 893 "urn:schemas-wifialliance-org:service:WFAWLANConfig:1"; 894 895static struct wpabuf * wps_er_soap_hdr(const struct wpabuf *msg, 896 const char *name, const char *arg_name, 897 const char *path, 898 const struct sockaddr_in *dst, 899 char **len_ptr, char **body_ptr) 900{ 901 unsigned char *encoded; 902 size_t encoded_len; 903 struct wpabuf *buf; 904 905 if (msg) { 906 encoded = base64_encode(wpabuf_head(msg), wpabuf_len(msg), 907 &encoded_len); 908 if (encoded == NULL) 909 return NULL; 910 } else { 911 encoded = NULL; 912 encoded_len = 0; 913 } 914 915 buf = wpabuf_alloc(1000 + encoded_len); 916 if (buf == NULL) { 917 os_free(encoded); 918 return NULL; 919 } 920 921 wpabuf_printf(buf, 922 "POST %s HTTP/1.1\r\n" 923 "Host: %s:%d\r\n" 924 "Content-Type: text/xml; charset=\"utf-8\"\r\n" 925 "Content-Length: ", 926 path, inet_ntoa(dst->sin_addr), ntohs(dst->sin_port)); 927 928 *len_ptr = wpabuf_put(buf, 0); 929 wpabuf_printf(buf, 930 " \r\n" 931 "SOAPACTION: \"%s#%s\"\r\n" 932 "\r\n", 933 urn_wfawlanconfig, name); 934 935 *body_ptr = wpabuf_put(buf, 0); 936 937 wpabuf_put_str(buf, soap_prefix); 938 wpabuf_printf(buf, "<u:%s xmlns:u=\"", name); 939 wpabuf_put_str(buf, urn_wfawlanconfig); 940 wpabuf_put_str(buf, "\">\n"); 941 if (encoded) { 942 wpabuf_printf(buf, "<%s>%s</%s>\n", 943 arg_name, (char *) encoded, arg_name); 944 os_free(encoded); 945 } 946 947 return buf; 948} 949 950 951static void wps_er_soap_end(struct wpabuf *buf, const char *name, 952 char *len_ptr, char *body_ptr) 953{ 954 char len_buf[10]; 955 wpabuf_printf(buf, "</u:%s>\n", name); 956 wpabuf_put_str(buf, soap_postfix); 957 os_snprintf(len_buf, sizeof(len_buf), "%d", 958 (int) ((char *) wpabuf_put(buf, 0) - body_ptr)); 959 os_memcpy(len_ptr, len_buf, os_strlen(len_buf)); 960} 961 962 963static void wps_er_sta_send_msg(struct wps_er_sta *sta, struct wpabuf *msg) 964{ 965 struct wpabuf *buf; 966 char *len_ptr, *body_ptr; 967 struct sockaddr_in dst; 968 char *url, *path; 969 970 if (sta->http) { 971 wpa_printf(MSG_DEBUG, "WPS ER: Pending HTTP request for STA - " 972 "ignore new request"); 973 wpabuf_free(msg); 974 return; 975 } 976 977 if (sta->ap->control_url == NULL) { 978 wpa_printf(MSG_DEBUG, "WPS ER: No controlURL for AP"); 979 wpabuf_free(msg); 980 return; 981 } 982 983 url = http_client_url_parse(sta->ap->control_url, &dst, &path); 984 if (url == NULL) { 985 wpa_printf(MSG_DEBUG, "WPS ER: Failed to parse controlURL"); 986 wpabuf_free(msg); 987 return; 988 } 989 990 buf = wps_er_soap_hdr(msg, "PutWLANResponse", "NewMessage", path, &dst, 991 &len_ptr, &body_ptr); 992 wpabuf_free(msg); 993 os_free(url); 994 if (buf == NULL) 995 return; 996 wpabuf_printf(buf, "<NewWLANEventType>%d</NewWLANEventType>\n", 997 UPNP_WPS_WLANEVENT_TYPE_EAP); 998 wpabuf_printf(buf, "<NewWLANEventMAC>" MACSTR "</NewWLANEventMAC>\n", 999 MAC2STR(sta->addr)); 1000 1001 wps_er_soap_end(buf, "PutWLANResponse", len_ptr, body_ptr); 1002 1003 sta->http = http_client_addr(&dst, buf, 1000, 1004 wps_er_http_put_wlan_response_cb, sta); 1005 if (sta->http == NULL) 1006 wpabuf_free(buf); 1007} 1008 1009 1010static void wps_er_sta_process(struct wps_er_sta *sta, struct wpabuf *msg, 1011 enum wsc_op_code op_code) 1012{ 1013 enum wps_process_res res; 1014 1015 res = wps_process_msg(sta->wps, op_code, msg); 1016 if (res == WPS_CONTINUE) { 1017 struct wpabuf *next = wps_get_msg(sta->wps, &op_code); 1018 if (next) 1019 wps_er_sta_send_msg(sta, next); 1020 } else { 1021 wpa_printf(MSG_DEBUG, "WPS ER: Protocol run %s with the " 1022 "enrollee (res=%d)", 1023 res == WPS_DONE ? "succeeded" : "failed", res); 1024 wps_deinit(sta->wps); 1025 sta->wps = NULL; 1026 if (res == WPS_DONE) { 1027 /* Remove the STA entry after short timeout */ 1028 eloop_cancel_timeout(wps_er_sta_timeout, sta, NULL); 1029 eloop_register_timeout(10, 0, wps_er_sta_timeout, sta, 1030 NULL); 1031 } 1032 } 1033} 1034 1035 1036static void wps_er_sta_start(struct wps_er_sta *sta, struct wpabuf *msg) 1037{ 1038 struct wps_config cfg; 1039 1040 if (sta->wps) 1041 wps_deinit(sta->wps); 1042 1043 os_memset(&cfg, 0, sizeof(cfg)); 1044 cfg.wps = sta->ap->er->wps; 1045 cfg.registrar = 1; 1046 cfg.peer_addr = sta->addr; 1047 1048 sta->wps = wps_init(&cfg); 1049 if (sta->wps == NULL) 1050 return; 1051 sta->wps->er = 1; 1052 sta->wps->use_cred = sta->ap->ap_settings; 1053 if (sta->ap->ap_settings) { 1054 os_free(sta->cred); 1055 sta->cred = os_malloc(sizeof(*sta->cred)); 1056 if (sta->cred) { 1057 os_memcpy(sta->cred, sta->ap->ap_settings, 1058 sizeof(*sta->cred)); 1059 sta->cred->cred_attr = NULL; 1060 os_memcpy(sta->cred->mac_addr, sta->addr, ETH_ALEN); 1061 sta->wps->use_cred = sta->cred; 1062 } 1063 } 1064 1065 wps_er_sta_process(sta, msg, WSC_MSG); 1066} 1067 1068 1069static void wps_er_process_wlanevent_eap(struct wps_er_ap *ap, const u8 *addr, 1070 struct wpabuf *msg) 1071{ 1072 struct wps_parse_attr attr; 1073 struct wps_er_sta *sta; 1074 1075 wpa_printf(MSG_DEBUG, "WPS ER: WLANEvent - EAP - from " MACSTR, 1076 MAC2STR(addr)); 1077 wpa_hexdump_buf(MSG_MSGDUMP, "WPS ER: WLANEvent - Enrollee's message " 1078 "(TLVs from EAP-WSC)", msg); 1079 1080 if (wps_parse_msg(msg, &attr) < 0) { 1081 wpa_printf(MSG_DEBUG, "WPS ER: Failed to parse TLVs in " 1082 "WLANEvent message"); 1083 return; 1084 } 1085 1086 sta = wps_er_add_sta_data(ap, addr, &attr, 0); 1087 if (sta == NULL) 1088 return; 1089 1090 if (attr.msg_type && *attr.msg_type == WPS_M1) 1091 wps_er_sta_start(sta, msg); 1092 else if (sta->wps) { 1093 enum wsc_op_code op_code = WSC_MSG; 1094 if (attr.msg_type) { 1095 switch (*attr.msg_type) { 1096 case WPS_WSC_ACK: 1097 op_code = WSC_ACK; 1098 break; 1099 case WPS_WSC_NACK: 1100 op_code = WSC_NACK; 1101 break; 1102 case WPS_WSC_DONE: 1103 op_code = WSC_Done; 1104 break; 1105 } 1106 } 1107 wps_er_sta_process(sta, msg, op_code); 1108 } 1109} 1110 1111 1112static void wps_er_process_wlanevent(struct wps_er_ap *ap, 1113 struct wpabuf *event) 1114{ 1115 u8 *data; 1116 u8 wlan_event_type; 1117 u8 wlan_event_mac[ETH_ALEN]; 1118 struct wpabuf msg; 1119 1120 wpa_hexdump(MSG_MSGDUMP, "WPS ER: Received WLANEvent", 1121 wpabuf_head(event), wpabuf_len(event)); 1122 if (wpabuf_len(event) < 1 + 17) { 1123 wpa_printf(MSG_DEBUG, "WPS ER: Too short WLANEvent"); 1124 return; 1125 } 1126 1127 data = wpabuf_mhead(event); 1128 wlan_event_type = data[0]; 1129 if (hwaddr_aton((char *) data + 1, wlan_event_mac) < 0) { 1130 wpa_printf(MSG_DEBUG, "WPS ER: Invalid WLANEventMAC in " 1131 "WLANEvent"); 1132 return; 1133 } 1134 1135 wpabuf_set(&msg, data + 1 + 17, wpabuf_len(event) - (1 + 17)); 1136 1137 switch (wlan_event_type) { 1138 case 1: 1139 wps_er_process_wlanevent_probe_req(ap, wlan_event_mac, &msg); 1140 break; 1141 case 2: 1142 wps_er_process_wlanevent_eap(ap, wlan_event_mac, &msg); 1143 break; 1144 default: 1145 wpa_printf(MSG_DEBUG, "WPS ER: Unknown WLANEventType %d", 1146 wlan_event_type); 1147 break; 1148 } 1149} 1150 1151 1152static void wps_er_http_event(struct wps_er *er, struct http_request *req, 1153 unsigned int ap_id) 1154{ 1155 struct wps_er_ap *ap = wps_er_ap_get_id(er, ap_id); 1156 struct wpabuf *event; 1157 enum http_reply_code ret; 1158 1159 if (ap == NULL) { 1160 wpa_printf(MSG_DEBUG, "WPS ER: HTTP event from unknown AP id " 1161 "%u", ap_id); 1162 wps_er_http_resp_not_found(req); 1163 return; 1164 } 1165 wpa_printf(MSG_MSGDUMP, "WPS ER: HTTP event from AP id %u: %s", 1166 ap_id, http_request_get_data(req)); 1167 1168 event = xml_get_base64_item(http_request_get_data(req), "WLANEvent", 1169 &ret); 1170 if (event == NULL) { 1171 wpa_printf(MSG_DEBUG, "WPS ER: Could not extract WLANEvent " 1172 "from the event notification"); 1173 /* 1174 * Reply with OK anyway to avoid getting unregistered from 1175 * events. 1176 */ 1177 wps_er_http_resp_ok(req); 1178 return; 1179 } 1180 1181 wps_er_process_wlanevent(ap, event); 1182 1183 wpabuf_free(event); 1184 wps_er_http_resp_ok(req); 1185} 1186 1187 1188static void wps_er_http_notify(struct wps_er *er, struct http_request *req) 1189{ 1190 char *uri = http_request_get_uri(req); 1191 1192 if (os_strncmp(uri, "/event/", 7) == 0) { 1193 unsigned int event_id; 1194 char *pos; 1195 event_id = atoi(uri + 7); 1196 if (event_id != er->event_id) { 1197 wpa_printf(MSG_DEBUG, "WPS ER: HTTP event for an " 1198 "unknown event id %u", event_id); 1199 return; 1200 } 1201 pos = os_strchr(uri + 7, '/'); 1202 if (pos == NULL) 1203 return; 1204 pos++; 1205 wps_er_http_event(er, req, atoi(pos)); 1206 } else { 1207 wpa_printf(MSG_DEBUG, "WPS ER: Unknown HTTP NOTIFY for '%s'", 1208 uri); 1209 wps_er_http_resp_not_found(req); 1210 } 1211} 1212 1213 1214static void wps_er_http_req(void *ctx, struct http_request *req) 1215{ 1216 struct wps_er *er = ctx; 1217 struct sockaddr_in *cli = http_request_get_cli_addr(req); 1218 enum httpread_hdr_type type = http_request_get_type(req); 1219 struct wpabuf *buf; 1220 1221 wpa_printf(MSG_DEBUG, "WPS ER: HTTP request: '%s' (type %d) from " 1222 "%s:%d", 1223 http_request_get_uri(req), type, 1224 inet_ntoa(cli->sin_addr), ntohs(cli->sin_port)); 1225 1226 switch (type) { 1227 case HTTPREAD_HDR_TYPE_NOTIFY: 1228 wps_er_http_notify(er, req); 1229 break; 1230 default: 1231 wpa_printf(MSG_DEBUG, "WPS ER: Unsupported HTTP request type " 1232 "%d", type); 1233 buf = wpabuf_alloc(200); 1234 if (buf == NULL) { 1235 http_request_deinit(req); 1236 return; 1237 } 1238 wpabuf_put_str(buf, 1239 "HTTP/1.1 501 Unimplemented\r\n" 1240 "Connection: close\r\n"); 1241 http_put_date(buf); 1242 wpabuf_put_str(buf, "\r\n"); 1243 http_request_send_and_deinit(req, buf); 1244 break; 1245 } 1246} 1247 1248 1249struct wps_er * 1250wps_er_init(struct wps_context *wps, const char *ifname, const char *filter) 1251{ 1252 struct wps_er *er; 1253 struct in_addr addr; 1254 1255 er = os_zalloc(sizeof(*er)); 1256 if (er == NULL) 1257 return NULL; 1258 dl_list_init(&er->ap); 1259 dl_list_init(&er->ap_unsubscribing); 1260 dl_list_init(&er->ap_settings); 1261 1262 er->multicast_sd = -1; 1263 er->ssdp_sd = -1; 1264 1265 os_strlcpy(er->ifname, ifname, sizeof(er->ifname)); 1266 er->wps = wps; 1267 if (os_get_random((unsigned char *) &er->event_id, 1268 sizeof(er->event_id)) < 0) { 1269 wps_er_deinit(er, NULL, NULL); 1270 return NULL; 1271 } 1272 /* Limit event_id to < 32 bits to avoid issues with atoi() */ 1273 er->event_id &= 0x0fffffff; 1274 1275 if (filter && os_strncmp(filter, "ifname=", 7) == 0) { 1276 const char *pos, *end; 1277 pos = filter + 7; 1278 end = os_strchr(pos, ' '); 1279 if (end) { 1280 size_t len = end - pos; 1281 os_strlcpy(er->ifname, pos, len < sizeof(er->ifname) ? 1282 len + 1 : sizeof(er->ifname)); 1283 filter = end + 1; 1284 } else { 1285 os_strlcpy(er->ifname, pos, sizeof(er->ifname)); 1286 filter = NULL; 1287 } 1288 er->forced_ifname = 1; 1289 } 1290 1291 if (filter) { 1292 if (inet_aton(filter, &er->filter_addr) == 0) { 1293 wpa_printf(MSG_INFO, "WPS UPnP: Invalid filter " 1294 "address %s", filter); 1295 wps_er_deinit(er, NULL, NULL); 1296 return NULL; 1297 } 1298 wpa_printf(MSG_DEBUG, "WPS UPnP: Only accepting connections " 1299 "with %s", filter); 1300 } 1301 if (get_netif_info(er->ifname, &er->ip_addr, &er->ip_addr_text, 1302 er->mac_addr)) { 1303 wpa_printf(MSG_INFO, "WPS UPnP: Could not get IP/MAC address " 1304 "for %s. Does it have IP address?", er->ifname); 1305 wps_er_deinit(er, NULL, NULL); 1306 return NULL; 1307 } 1308 1309 if (wps_er_ssdp_init(er) < 0) { 1310 wpa_printf(MSG_INFO, "WPS UPnP: SSDP initialization failed"); 1311 wps_er_deinit(er, NULL, NULL); 1312 return NULL; 1313 } 1314 1315 addr.s_addr = er->ip_addr; 1316 er->http_srv = http_server_init(&addr, -1, wps_er_http_req, er); 1317 if (er->http_srv == NULL) { 1318 wpa_printf(MSG_INFO, "WPS UPnP: HTTP initialization failed"); 1319 wps_er_deinit(er, NULL, NULL); 1320 return NULL; 1321 } 1322 er->http_port = http_server_get_port(er->http_srv); 1323 1324 wpa_printf(MSG_DEBUG, "WPS ER: Start (ifname=%s ip_addr=%s)", 1325 er->ifname, er->ip_addr_text); 1326 1327 return er; 1328} 1329 1330 1331void wps_er_refresh(struct wps_er *er) 1332{ 1333 struct wps_er_ap *ap; 1334 struct wps_er_sta *sta; 1335 1336 dl_list_for_each(ap, &er->ap, struct wps_er_ap, list) { 1337 wps_er_ap_event(er->wps, ap, WPS_EV_ER_AP_ADD); 1338 dl_list_for_each(sta, &ap->sta, struct wps_er_sta, list) 1339 wps_er_sta_event(er->wps, sta, WPS_EV_ER_ENROLLEE_ADD); 1340 } 1341 1342 wps_er_send_ssdp_msearch(er); 1343} 1344 1345 1346static void wps_er_deinit_finish(void *eloop_data, void *user_ctx) 1347{ 1348 struct wps_er *er = eloop_data; 1349 void (*deinit_done_cb)(void *ctx); 1350 void *deinit_done_ctx; 1351 struct wps_er_ap *ap, *tmp; 1352 1353 wpa_printf(MSG_DEBUG, "WPS ER: Finishing deinit"); 1354 1355 dl_list_for_each_safe(ap, tmp, &er->ap_unsubscribing, struct wps_er_ap, 1356 list) { 1357 wpa_printf(MSG_DEBUG, "WPS ER: AP entry for %s (%s) still in ap_unsubscribing list - free it", 1358 inet_ntoa(ap->addr), ap->location); 1359 dl_list_del(&ap->list); 1360 wps_er_ap_free(ap); 1361 } 1362 1363 eloop_cancel_timeout(wps_er_deinit_finish, er, NULL); 1364 deinit_done_cb = er->deinit_done_cb; 1365 deinit_done_ctx = er->deinit_done_ctx; 1366 os_free(er->ip_addr_text); 1367 os_free(er); 1368 1369 if (deinit_done_cb) 1370 deinit_done_cb(deinit_done_ctx); 1371} 1372 1373 1374void wps_er_deinit(struct wps_er *er, void (*cb)(void *ctx), void *ctx) 1375{ 1376 if (er == NULL) 1377 return; 1378 http_server_deinit(er->http_srv); 1379 wps_er_ap_remove_all(er); 1380 wps_er_ssdp_deinit(er); 1381 eloop_register_timeout(dl_list_empty(&er->ap_unsubscribing) ? 0 : 5, 0, 1382 wps_er_deinit_finish, er, NULL); 1383 wpa_printf(MSG_DEBUG, "WPS ER: Finish deinit from timeout"); 1384 er->deinitializing = 1; 1385 er->deinit_done_cb = cb; 1386 er->deinit_done_ctx = ctx; 1387} 1388 1389 1390static void wps_er_http_set_sel_reg_cb(void *ctx, struct http_client *c, 1391 enum http_client_event event) 1392{ 1393 struct wps_er_ap *ap = ctx; 1394 union wps_event_data data; 1395 1396 os_memset(&data, 0, sizeof(data)); 1397 1398 switch (event) { 1399 case HTTP_CLIENT_OK: 1400 wpa_printf(MSG_DEBUG, "WPS ER: SetSelectedRegistrar OK"); 1401 data.set_sel_reg.state = WPS_ER_SET_SEL_REG_DONE; 1402 data.set_sel_reg.uuid = ap->uuid; 1403 break; 1404 case HTTP_CLIENT_FAILED: 1405 case HTTP_CLIENT_INVALID_REPLY: 1406 case HTTP_CLIENT_TIMEOUT: 1407 wpa_printf(MSG_DEBUG, "WPS ER: SetSelectedRegistrar failed"); 1408 data.set_sel_reg.state = WPS_ER_SET_SEL_REG_FAILED; 1409 data.set_sel_reg.uuid = ap->uuid; 1410 break; 1411 } 1412 http_client_free(ap->http); 1413 ap->http = NULL; 1414 1415 if (data.set_sel_reg.uuid) 1416 ap->er->wps->event_cb(ap->er->wps->cb_ctx, 1417 WPS_EV_ER_SET_SELECTED_REGISTRAR, &data); 1418} 1419 1420 1421static void wps_er_send_set_sel_reg(struct wps_er_ap *ap, struct wpabuf *msg) 1422{ 1423 struct wpabuf *buf; 1424 char *len_ptr, *body_ptr; 1425 struct sockaddr_in dst; 1426 char *url, *path; 1427 1428 if (ap->control_url == NULL) { 1429 wpa_printf(MSG_DEBUG, "WPS ER: No controlURL for AP"); 1430 return; 1431 } 1432 1433 if (ap->http) { 1434 wpa_printf(MSG_DEBUG, "WPS ER: Pending HTTP request for AP - " 1435 "ignore new request"); 1436 return; 1437 } 1438 1439 if (ap->wps) { 1440 wpa_printf(MSG_DEBUG, "WPS ER: Pending WPS operation for AP - " 1441 "skip SetSelectedRegistrar"); 1442 return; 1443 } 1444 1445 url = http_client_url_parse(ap->control_url, &dst, &path); 1446 if (url == NULL) { 1447 wpa_printf(MSG_DEBUG, "WPS ER: Failed to parse controlURL"); 1448 return; 1449 } 1450 1451 buf = wps_er_soap_hdr(msg, "SetSelectedRegistrar", "NewMessage", path, 1452 &dst, &len_ptr, &body_ptr); 1453 os_free(url); 1454 if (buf == NULL) 1455 return; 1456 1457 wps_er_soap_end(buf, "SetSelectedRegistrar", len_ptr, body_ptr); 1458 1459 ap->http = http_client_addr(&dst, buf, 1000, 1460 wps_er_http_set_sel_reg_cb, ap); 1461 if (ap->http == NULL) 1462 wpabuf_free(buf); 1463} 1464 1465 1466static int wps_er_build_selected_registrar(struct wpabuf *msg, int sel_reg) 1467{ 1468 wpabuf_put_be16(msg, ATTR_SELECTED_REGISTRAR); 1469 wpabuf_put_be16(msg, 1); 1470 wpabuf_put_u8(msg, !!sel_reg); 1471 return 0; 1472} 1473 1474 1475static int wps_er_build_dev_password_id(struct wpabuf *msg, u16 dev_passwd_id) 1476{ 1477 wpabuf_put_be16(msg, ATTR_DEV_PASSWORD_ID); 1478 wpabuf_put_be16(msg, 2); 1479 wpabuf_put_be16(msg, dev_passwd_id); 1480 return 0; 1481} 1482 1483 1484static int wps_er_build_sel_reg_config_methods(struct wpabuf *msg, 1485 u16 sel_reg_config_methods) 1486{ 1487 wpabuf_put_be16(msg, ATTR_SELECTED_REGISTRAR_CONFIG_METHODS); 1488 wpabuf_put_be16(msg, 2); 1489 wpabuf_put_be16(msg, sel_reg_config_methods); 1490 return 0; 1491} 1492 1493 1494static int wps_er_build_uuid_r(struct wpabuf *msg, const u8 *uuid_r) 1495{ 1496 wpabuf_put_be16(msg, ATTR_UUID_R); 1497 wpabuf_put_be16(msg, WPS_UUID_LEN); 1498 wpabuf_put_data(msg, uuid_r, WPS_UUID_LEN); 1499 return 0; 1500} 1501 1502 1503void wps_er_set_sel_reg(struct wps_er *er, int sel_reg, u16 dev_passwd_id, 1504 u16 sel_reg_config_methods) 1505{ 1506 struct wpabuf *msg; 1507 struct wps_er_ap *ap; 1508 struct wps_registrar *reg = er->wps->registrar; 1509 const u8 *auth_macs; 1510 u8 bcast[ETH_ALEN]; 1511 size_t count; 1512 union wps_event_data data; 1513 1514 if (er->skip_set_sel_reg) { 1515 wpa_printf(MSG_DEBUG, "WPS ER: Skip SetSelectedRegistrar"); 1516 return; 1517 } 1518 1519 msg = wpabuf_alloc(500); 1520 if (msg == NULL) 1521 return; 1522 1523 auth_macs = wps_authorized_macs(reg, &count); 1524 if (count == 0) { 1525 os_memset(bcast, 0xff, ETH_ALEN); 1526 auth_macs = bcast; 1527 count = 1; 1528 } 1529 1530 if (wps_build_version(msg) || 1531 wps_er_build_selected_registrar(msg, sel_reg) || 1532 wps_er_build_dev_password_id(msg, dev_passwd_id) || 1533 wps_er_build_sel_reg_config_methods(msg, sel_reg_config_methods) || 1534 wps_build_wfa_ext(msg, 0, auth_macs, count) || 1535 wps_er_build_uuid_r(msg, er->wps->uuid)) { 1536 wpabuf_free(msg); 1537 return; 1538 } 1539 1540 os_memset(&data, 0, sizeof(data)); 1541 data.set_sel_reg.sel_reg = sel_reg; 1542 data.set_sel_reg.dev_passwd_id = dev_passwd_id; 1543 data.set_sel_reg.sel_reg_config_methods = sel_reg_config_methods; 1544 data.set_sel_reg.state = WPS_ER_SET_SEL_REG_START; 1545 1546 dl_list_for_each(ap, &er->ap, struct wps_er_ap, list) { 1547 if (er->set_sel_reg_uuid_filter && 1548 os_memcmp(ap->uuid, er->set_sel_reg_uuid_filter, 1549 WPS_UUID_LEN) != 0) 1550 continue; 1551 data.set_sel_reg.uuid = ap->uuid; 1552 er->wps->event_cb(er->wps->cb_ctx, 1553 WPS_EV_ER_SET_SELECTED_REGISTRAR, &data); 1554 wps_er_send_set_sel_reg(ap, msg); 1555 } 1556 1557 wpabuf_free(msg); 1558} 1559 1560 1561int wps_er_pbc(struct wps_er *er, const u8 *uuid, const u8 *addr) 1562{ 1563 int res; 1564 struct wps_er_ap *ap; 1565 1566 if (er == NULL || er->wps == NULL) 1567 return -1; 1568 1569 if (wps_registrar_pbc_overlap(er->wps->registrar, NULL, NULL)) { 1570 wpa_printf(MSG_DEBUG, "WPS ER: PBC overlap - do not start PBC " 1571 "mode"); 1572 return -2; 1573 } 1574 1575 if (uuid) 1576 ap = wps_er_ap_get(er, NULL, uuid, NULL); 1577 else 1578 ap = NULL; 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, addr, 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 1607static 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 1628const u8 * wps_er_get_sta_uuid(struct wps_er *er, const u8 *addr) 1629{ 1630 struct wps_er_ap *ap; 1631 dl_list_for_each(ap, &er->ap, struct wps_er_ap, list) { 1632 struct wps_er_sta *sta; 1633 sta = wps_er_sta_get(ap, addr, NULL); 1634 if (sta) 1635 return sta->uuid; 1636 } 1637 return NULL; 1638} 1639 1640 1641static void wps_er_http_put_message_cb(void *ctx, struct http_client *c, 1642 enum http_client_event event) 1643{ 1644 struct wps_er_ap *ap = ctx; 1645 struct wpabuf *reply; 1646 char *msg = NULL; 1647 1648 switch (event) { 1649 case HTTP_CLIENT_OK: 1650 wpa_printf(MSG_DEBUG, "WPS ER: PutMessage OK"); 1651 reply = http_client_get_body(c); 1652 if (reply == NULL) 1653 break; 1654 msg = os_zalloc(wpabuf_len(reply) + 1); 1655 if (msg == NULL) 1656 break; 1657 os_memcpy(msg, wpabuf_head(reply), wpabuf_len(reply)); 1658 break; 1659 case HTTP_CLIENT_FAILED: 1660 case HTTP_CLIENT_INVALID_REPLY: 1661 case HTTP_CLIENT_TIMEOUT: 1662 wpa_printf(MSG_DEBUG, "WPS ER: PutMessage failed"); 1663 if (ap->wps) { 1664 wps_deinit(ap->wps); 1665 ap->wps = NULL; 1666 } 1667 break; 1668 } 1669 http_client_free(ap->http); 1670 ap->http = NULL; 1671 1672 if (msg) { 1673 struct wpabuf *buf; 1674 enum http_reply_code ret; 1675 buf = xml_get_base64_item(msg, "NewOutMessage", &ret); 1676 os_free(msg); 1677 if (buf == NULL) { 1678 wpa_printf(MSG_DEBUG, "WPS ER: Could not extract " 1679 "NewOutMessage from PutMessage response"); 1680 wps_deinit(ap->wps); 1681 ap->wps = NULL; 1682 return; 1683 } 1684 wps_er_ap_process(ap, buf); 1685 wpabuf_free(buf); 1686 } 1687} 1688 1689 1690static void wps_er_ap_put_message(struct wps_er_ap *ap, 1691 const struct wpabuf *msg) 1692{ 1693 struct wpabuf *buf; 1694 char *len_ptr, *body_ptr; 1695 struct sockaddr_in dst; 1696 char *url, *path; 1697 1698 if (ap->http) { 1699 wpa_printf(MSG_DEBUG, "WPS ER: Pending HTTP operation ongoing " 1700 "with the AP - cannot continue learn"); 1701 return; 1702 } 1703 1704 if (ap->control_url == NULL) { 1705 wpa_printf(MSG_DEBUG, "WPS ER: No controlURL for AP"); 1706 return; 1707 } 1708 1709 url = http_client_url_parse(ap->control_url, &dst, &path); 1710 if (url == NULL) { 1711 wpa_printf(MSG_DEBUG, "WPS ER: Failed to parse controlURL"); 1712 return; 1713 } 1714 1715 buf = wps_er_soap_hdr(msg, "PutMessage", "NewInMessage", path, &dst, 1716 &len_ptr, &body_ptr); 1717 os_free(url); 1718 if (buf == NULL) 1719 return; 1720 1721 wps_er_soap_end(buf, "PutMessage", len_ptr, body_ptr); 1722 1723 ap->http = http_client_addr(&dst, buf, 10000, 1724 wps_er_http_put_message_cb, ap); 1725 if (ap->http == NULL) 1726 wpabuf_free(buf); 1727} 1728 1729 1730static void wps_er_ap_process(struct wps_er_ap *ap, struct wpabuf *msg) 1731{ 1732 enum wps_process_res res; 1733 struct wps_parse_attr attr; 1734 enum wsc_op_code op_code; 1735 1736 op_code = WSC_MSG; 1737 if (wps_parse_msg(msg, &attr) == 0 && attr.msg_type) { 1738 switch (*attr.msg_type) { 1739 case WPS_WSC_ACK: 1740 op_code = WSC_ACK; 1741 break; 1742 case WPS_WSC_NACK: 1743 op_code = WSC_NACK; 1744 break; 1745 case WPS_WSC_DONE: 1746 op_code = WSC_Done; 1747 break; 1748 } 1749 } 1750 1751 res = wps_process_msg(ap->wps, op_code, msg); 1752 if (res == WPS_CONTINUE) { 1753 struct wpabuf *next = wps_get_msg(ap->wps, &op_code); 1754 if (next) { 1755 wps_er_ap_put_message(ap, next); 1756 wpabuf_free(next); 1757 } else { 1758 wpa_printf(MSG_DEBUG, "WPS ER: Failed to build " 1759 "message"); 1760 wps_deinit(ap->wps); 1761 ap->wps = NULL; 1762 } 1763 } else if (res == WPS_DONE) { 1764 wpa_printf(MSG_DEBUG, "WPS ER: Protocol run done"); 1765 wps_deinit(ap->wps); 1766 ap->wps = NULL; 1767 } else { 1768 wpa_printf(MSG_DEBUG, "WPS ER: Failed to process message from " 1769 "AP (res=%d)", res); 1770 wps_deinit(ap->wps); 1771 ap->wps = NULL; 1772 } 1773} 1774 1775 1776static void wps_er_ap_learn_m1(struct wps_er_ap *ap, struct wpabuf *m1) 1777{ 1778 struct wps_config cfg; 1779 1780 if (ap->wps) { 1781 wpa_printf(MSG_DEBUG, "WPS ER: Protocol run already in " 1782 "progress with this AP"); 1783 return; 1784 } 1785 1786 os_memset(&cfg, 0, sizeof(cfg)); 1787 cfg.wps = ap->er->wps; 1788 cfg.registrar = 1; 1789 ap->wps = wps_init(&cfg); 1790 if (ap->wps == NULL) 1791 return; 1792 ap->wps->ap_settings_cb = wps_er_ap_settings_cb; 1793 ap->wps->ap_settings_cb_ctx = ap; 1794 1795 wps_er_ap_process(ap, m1); 1796} 1797 1798 1799static void wps_er_ap_learn(struct wps_er_ap *ap, const char *dev_info) 1800{ 1801 struct wpabuf *info; 1802 enum http_reply_code ret; 1803 1804 wpa_printf(MSG_DEBUG, "WPS ER: Received GetDeviceInfo response (M1) " 1805 "from the AP"); 1806 info = xml_get_base64_item(dev_info, "NewDeviceInfo", &ret); 1807 if (info == NULL) { 1808 wpa_printf(MSG_DEBUG, "WPS ER: Could not extract " 1809 "NewDeviceInfo from GetDeviceInfo response"); 1810 return; 1811 } 1812 1813 ap->m1_handler(ap, info); 1814 wpabuf_free(info); 1815} 1816 1817 1818static void wps_er_http_get_dev_info_cb(void *ctx, struct http_client *c, 1819 enum http_client_event event) 1820{ 1821 struct wps_er_ap *ap = ctx; 1822 struct wpabuf *reply; 1823 char *dev_info = NULL; 1824 1825 switch (event) { 1826 case HTTP_CLIENT_OK: 1827 wpa_printf(MSG_DEBUG, "WPS ER: GetDeviceInfo OK"); 1828 reply = http_client_get_body(c); 1829 if (reply == NULL) 1830 break; 1831 dev_info = os_zalloc(wpabuf_len(reply) + 1); 1832 if (dev_info == NULL) 1833 break; 1834 os_memcpy(dev_info, wpabuf_head(reply), wpabuf_len(reply)); 1835 break; 1836 case HTTP_CLIENT_FAILED: 1837 case HTTP_CLIENT_INVALID_REPLY: 1838 case HTTP_CLIENT_TIMEOUT: 1839 wpa_printf(MSG_DEBUG, "WPS ER: GetDeviceInfo failed"); 1840 break; 1841 } 1842 http_client_free(ap->http); 1843 ap->http = NULL; 1844 1845 if (dev_info) { 1846 wps_er_ap_learn(ap, dev_info); 1847 os_free(dev_info); 1848 } 1849} 1850 1851 1852static int wps_er_send_get_device_info(struct wps_er_ap *ap, 1853 void (*m1_handler)(struct wps_er_ap *ap, 1854 struct wpabuf *m1)) 1855{ 1856 struct wpabuf *buf; 1857 char *len_ptr, *body_ptr; 1858 struct sockaddr_in dst; 1859 char *url, *path; 1860 1861 if (ap->http) { 1862 wpa_printf(MSG_DEBUG, "WPS ER: Pending HTTP operation ongoing " 1863 "with the AP - cannot get device info"); 1864 return -1; 1865 } 1866 1867 if (ap->control_url == NULL) { 1868 wpa_printf(MSG_DEBUG, "WPS ER: No controlURL for AP"); 1869 return -1; 1870 } 1871 1872 url = http_client_url_parse(ap->control_url, &dst, &path); 1873 if (url == NULL) { 1874 wpa_printf(MSG_DEBUG, "WPS ER: Failed to parse controlURL"); 1875 return -1; 1876 } 1877 1878 buf = wps_er_soap_hdr(NULL, "GetDeviceInfo", NULL, path, &dst, 1879 &len_ptr, &body_ptr); 1880 os_free(url); 1881 if (buf == NULL) 1882 return -1; 1883 1884 wps_er_soap_end(buf, "GetDeviceInfo", len_ptr, body_ptr); 1885 1886 ap->http = http_client_addr(&dst, buf, 10000, 1887 wps_er_http_get_dev_info_cb, ap); 1888 if (ap->http == NULL) { 1889 wpabuf_free(buf); 1890 return -1; 1891 } 1892 1893 ap->m1_handler = m1_handler; 1894 1895 return 0; 1896} 1897 1898 1899int wps_er_learn(struct wps_er *er, const u8 *uuid, const u8 *addr, 1900 const u8 *pin, size_t pin_len) 1901{ 1902 struct wps_er_ap *ap; 1903 1904 if (er == NULL) 1905 return -1; 1906 1907 ap = wps_er_ap_get(er, NULL, uuid, addr); 1908 if (ap == NULL) { 1909 wpa_printf(MSG_DEBUG, "WPS ER: AP not found for learn " 1910 "request"); 1911 return -1; 1912 } 1913 if (uuid == NULL) 1914 uuid = ap->uuid; 1915 if (ap->wps) { 1916 wpa_printf(MSG_DEBUG, "WPS ER: Pending operation ongoing " 1917 "with the AP - cannot start learn"); 1918 return -1; 1919 } 1920 1921 if (wps_er_send_get_device_info(ap, wps_er_ap_learn_m1) < 0) 1922 return -1; 1923 1924 er->skip_set_sel_reg = 1; 1925 wps_registrar_add_pin(er->wps->registrar, NULL, uuid, pin, pin_len, 0); 1926 er->skip_set_sel_reg = 0; 1927 1928 return 0; 1929} 1930 1931 1932int wps_er_set_config(struct wps_er *er, const u8 *uuid, const u8 *addr, 1933 const struct wps_credential *cred) 1934{ 1935 struct wps_er_ap *ap; 1936 1937 if (er == NULL) 1938 return -1; 1939 1940 ap = wps_er_ap_get(er, NULL, uuid, addr); 1941 if (ap == NULL) { 1942 wpa_printf(MSG_DEBUG, "WPS ER: AP not found for set config " 1943 "request"); 1944 return -1; 1945 } 1946 1947 os_free(ap->ap_settings); 1948 ap->ap_settings = os_malloc(sizeof(*cred)); 1949 if (ap->ap_settings == NULL) 1950 return -1; 1951 os_memcpy(ap->ap_settings, cred, sizeof(*cred)); 1952 ap->ap_settings->cred_attr = NULL; 1953 wpa_printf(MSG_DEBUG, "WPS ER: Updated local AP settings based set " 1954 "config request"); 1955 1956 return 0; 1957} 1958 1959 1960static void wps_er_ap_config_m1(struct wps_er_ap *ap, struct wpabuf *m1) 1961{ 1962 struct wps_config cfg; 1963 1964 if (ap->wps) { 1965 wpa_printf(MSG_DEBUG, "WPS ER: Protocol run already in " 1966 "progress with this AP"); 1967 return; 1968 } 1969 1970 os_memset(&cfg, 0, sizeof(cfg)); 1971 cfg.wps = ap->er->wps; 1972 cfg.registrar = 1; 1973 cfg.new_ap_settings = ap->ap_settings; 1974 ap->wps = wps_init(&cfg); 1975 if (ap->wps == NULL) 1976 return; 1977 ap->wps->ap_settings_cb = NULL; 1978 ap->wps->ap_settings_cb_ctx = NULL; 1979 1980 wps_er_ap_process(ap, m1); 1981} 1982 1983 1984int wps_er_config(struct wps_er *er, const u8 *uuid, const u8 *addr, 1985 const u8 *pin, size_t pin_len, 1986 const struct wps_credential *cred) 1987{ 1988 struct wps_er_ap *ap; 1989 1990 if (er == NULL) 1991 return -1; 1992 1993 ap = wps_er_ap_get(er, NULL, uuid, addr); 1994 if (ap == NULL) { 1995 wpa_printf(MSG_DEBUG, "WPS ER: AP not found for config " 1996 "request"); 1997 return -1; 1998 } 1999 if (uuid == NULL) 2000 uuid = ap->uuid; 2001 if (ap->wps) { 2002 wpa_printf(MSG_DEBUG, "WPS ER: Pending operation ongoing " 2003 "with the AP - cannot start config"); 2004 return -1; 2005 } 2006 2007 os_free(ap->ap_settings); 2008 ap->ap_settings = os_malloc(sizeof(*cred)); 2009 if (ap->ap_settings == NULL) 2010 return -1; 2011 os_memcpy(ap->ap_settings, cred, sizeof(*cred)); 2012 ap->ap_settings->cred_attr = NULL; 2013 2014 if (wps_er_send_get_device_info(ap, wps_er_ap_config_m1) < 0) 2015 return -1; 2016 2017 er->skip_set_sel_reg = 1; 2018 wps_registrar_add_pin(er->wps->registrar, NULL, uuid, pin, pin_len, 0); 2019 er->skip_set_sel_reg = 0; 2020 2021 return 0; 2022} 2023 2024 2025#ifdef CONFIG_WPS_NFC 2026 2027struct wpabuf * wps_er_config_token_from_cred(struct wps_context *wps, 2028 struct wps_credential *cred) 2029{ 2030 struct wpabuf *ret; 2031 struct wps_data data; 2032 2033 ret = wpabuf_alloc(500); 2034 if (ret == NULL) 2035 return NULL; 2036 2037 os_memset(&data, 0, sizeof(data)); 2038 data.wps = wps; 2039 data.use_cred = cred; 2040 if (wps_build_cred(&data, ret) || 2041 wps_build_wfa_ext(ret, 0, NULL, 0)) { 2042 wpabuf_free(ret); 2043 return NULL; 2044 } 2045 2046 return ret; 2047} 2048 2049 2050struct wpabuf * wps_er_nfc_config_token(struct wps_er *er, const u8 *uuid, 2051 const u8 *addr) 2052{ 2053 struct wps_er_ap *ap; 2054 2055 if (er == NULL) 2056 return NULL; 2057 2058 ap = wps_er_ap_get(er, NULL, uuid, addr); 2059 if (ap == NULL) 2060 return NULL; 2061 if (ap->ap_settings == NULL) { 2062 wpa_printf(MSG_DEBUG, "WPS ER: No settings known for the " 2063 "selected AP"); 2064 return NULL; 2065 } 2066 2067 return wps_er_config_token_from_cred(er->wps, ap->ap_settings); 2068} 2069 2070 2071struct wpabuf * wps_er_nfc_handover_sel(struct wps_er *er, 2072 struct wps_context *wps, const u8 *uuid, 2073 const u8 *addr, struct wpabuf *pubkey) 2074{ 2075 struct wps_er_ap *ap; 2076 2077 if (er == NULL) 2078 return NULL; 2079 2080 ap = wps_er_ap_get(er, NULL, uuid, addr); 2081 if (ap == NULL) 2082 return NULL; 2083 if (ap->ap_settings == NULL) { 2084 wpa_printf(MSG_DEBUG, "WPS ER: No settings known for the " 2085 "selected AP"); 2086 return NULL; 2087 } 2088 2089 os_memcpy(wps->ssid, ap->ap_settings->ssid, ap->ap_settings->ssid_len); 2090 wps->ssid_len = ap->ap_settings->ssid_len; 2091 2092 return wps_build_nfc_handover_sel(wps, pubkey, addr, 0); 2093} 2094 2095#endif /* CONFIG_WPS_NFC */ 2096