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 25 static void wps_er_deinit_finish(void *eloop_data, void *user_ctx); 26 static void wps_er_ap_timeout(void *eloop_data, void *user_ctx); 27 static void wps_er_sta_timeout(void *eloop_data, void *user_ctx); 28 static void wps_er_ap_process(struct wps_er_ap *ap, struct wpabuf *msg); 29 static 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 34 static 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 59 static 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 74 static 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 91 static 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 99 static 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 116 static 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 127 static 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 154 static 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 181 static 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 193 static 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 221 static 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 269 fail: 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 278 static 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 289 int 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 313 static 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_memdup(&s->ap_settings, sizeof(*ap->ap_settings)); 326 if (ap->ap_settings == NULL) 327 return -1; 328 329 wpa_printf(MSG_DEBUG, "WPS ER: Use cached AP settings"); 330 return 0; 331 } 332 333 334 static void wps_er_ap_remove_entry(struct wps_er *er, struct wps_er_ap *ap) 335 { 336 wpa_printf(MSG_DEBUG, "WPS ER: Removing AP entry for %s (%s)", 337 inet_ntoa(ap->addr), ap->location); 338 eloop_cancel_timeout(wps_er_ap_timeout, er, ap); 339 wps_er_sta_remove_all(ap); 340 wps_er_ap_event(er->wps, ap, WPS_EV_ER_AP_REMOVE); 341 http_client_free(ap->http); 342 ap->http = NULL; 343 if (ap->wps) { 344 wps_deinit(ap->wps); 345 ap->wps = NULL; 346 } 347 348 dl_list_del(&ap->list); 349 if (ap->subscribed) { 350 dl_list_add(&er->ap_unsubscribing, &ap->list); 351 wps_er_ap_unsubscribe(er, ap); 352 } else 353 wps_er_ap_free(ap); 354 } 355 356 357 static void wps_er_ap_timeout(void *eloop_data, void *user_ctx) 358 { 359 struct wps_er *er = eloop_data; 360 struct wps_er_ap *ap = user_ctx; 361 wpa_printf(MSG_DEBUG, "WPS ER: AP advertisement timed out"); 362 wps_er_ap_remove_entry(er, ap); 363 } 364 365 366 static int wps_er_get_sid(struct wps_er_ap *ap, char *sid) 367 { 368 char *pos; 369 char txt[100]; 370 371 if (!sid) { 372 wpa_printf(MSG_DEBUG, "WPS ER: No SID received from %s (%s)", 373 inet_ntoa(ap->addr), ap->location); 374 return -1; 375 } 376 377 pos = os_strstr(sid, "uuid:"); 378 if (!pos) { 379 wpa_printf(MSG_DEBUG, "WPS ER: Invalid SID received from " 380 "%s (%s): '%s'", inet_ntoa(ap->addr), ap->location, 381 sid); 382 return -1; 383 } 384 385 pos += 5; 386 if (uuid_str2bin(pos, ap->sid) < 0) { 387 wpa_printf(MSG_DEBUG, "WPS ER: Invalid SID received from " 388 "%s (%s): '%s'", inet_ntoa(ap->addr), ap->location, 389 sid); 390 return -1; 391 } 392 393 uuid_bin2str(ap->sid, txt, sizeof(txt)); 394 wpa_printf(MSG_DEBUG, "WPS ER: SID for subscription with %s (%s): %s", 395 inet_ntoa(ap->addr), ap->location, txt); 396 397 return 0; 398 } 399 400 401 static void wps_er_http_subscribe_cb(void *ctx, struct http_client *c, 402 enum http_client_event event) 403 { 404 struct wps_er_ap *ap = ctx; 405 406 switch (event) { 407 case HTTP_CLIENT_OK: 408 wpa_printf(MSG_DEBUG, "WPS ER: Subscribed to events"); 409 ap->subscribed = 1; 410 wps_er_get_sid(ap, http_client_get_hdr_line(c, "SID")); 411 wps_er_ap_use_cached_settings(ap->er, ap); 412 wps_er_ap_event(ap->er->wps, ap, WPS_EV_ER_AP_ADD); 413 break; 414 case HTTP_CLIENT_FAILED: 415 case HTTP_CLIENT_INVALID_REPLY: 416 case HTTP_CLIENT_TIMEOUT: 417 wpa_printf(MSG_DEBUG, "WPS ER: Failed to subscribe to events"); 418 break; 419 } 420 http_client_free(ap->http); 421 ap->http = NULL; 422 } 423 424 425 static void wps_er_subscribe(struct wps_er_ap *ap) 426 { 427 struct wpabuf *req; 428 struct sockaddr_in dst; 429 char *url, *path; 430 431 if (ap->event_sub_url == NULL) { 432 wpa_printf(MSG_DEBUG, "WPS ER: No eventSubURL - cannot " 433 "subscribe"); 434 return; 435 } 436 if (ap->http) { 437 wpa_printf(MSG_DEBUG, "WPS ER: Pending HTTP request - cannot " 438 "send subscribe request"); 439 return; 440 } 441 442 url = http_client_url_parse(ap->event_sub_url, &dst, &path); 443 if (url == NULL) { 444 wpa_printf(MSG_DEBUG, "WPS ER: Failed to parse eventSubURL"); 445 return; 446 } 447 448 req = wpabuf_alloc(os_strlen(ap->event_sub_url) + 1000); 449 if (req == NULL) { 450 os_free(url); 451 return; 452 } 453 wpabuf_printf(req, 454 "SUBSCRIBE %s HTTP/1.1\r\n" 455 "HOST: %s:%d\r\n" 456 "CALLBACK: <http://%s:%d/event/%u/%u>\r\n" 457 "NT: upnp:event\r\n" 458 "TIMEOUT: Second-%d\r\n" 459 "\r\n", 460 path, inet_ntoa(dst.sin_addr), ntohs(dst.sin_port), 461 ap->er->ip_addr_text, ap->er->http_port, 462 ap->er->event_id, ap->id, 1800); 463 os_free(url); 464 wpa_hexdump_ascii(MSG_MSGDUMP, "WPS ER: Subscription request", 465 wpabuf_head(req), wpabuf_len(req)); 466 467 ap->http = http_client_addr(&dst, req, 1000, wps_er_http_subscribe_cb, 468 ap); 469 if (ap->http == NULL) 470 wpabuf_free(req); 471 } 472 473 474 static void wps_er_ap_get_m1(struct wps_er_ap *ap, struct wpabuf *m1) 475 { 476 struct wps_parse_attr attr; 477 478 if (wps_parse_msg(m1, &attr) < 0) { 479 wpa_printf(MSG_DEBUG, "WPS ER: Failed to parse M1"); 480 return; 481 } 482 if (attr.primary_dev_type) 483 os_memcpy(ap->pri_dev_type, attr.primary_dev_type, 8); 484 if (attr.wps_state) 485 ap->wps_state = *attr.wps_state; 486 if (attr.mac_addr) 487 os_memcpy(ap->mac_addr, attr.mac_addr, ETH_ALEN); 488 489 wps_er_subscribe(ap); 490 } 491 492 493 static void wps_er_get_device_info(struct wps_er_ap *ap) 494 { 495 wps_er_send_get_device_info(ap, wps_er_ap_get_m1); 496 } 497 498 499 static const char * wps_er_find_wfadevice(const char *data) 500 { 501 const char *tag, *tagname, *end; 502 char *val; 503 int found = 0; 504 505 while (!found) { 506 /* Find next <device> */ 507 for (;;) { 508 if (xml_next_tag(data, &tag, &tagname, &end)) 509 return NULL; 510 data = end; 511 if (!os_strncasecmp(tagname, "device", 6) && 512 *tag != '/' && 513 (tagname[6] == '>' || !isgraph(tagname[6]))) { 514 break; 515 } 516 } 517 518 /* Check whether deviceType is WFADevice */ 519 val = xml_get_first_item(data, "deviceType"); 520 if (val == NULL) 521 return NULL; 522 wpa_printf(MSG_DEBUG, "WPS ER: Found deviceType '%s'", val); 523 found = os_strcasecmp(val, "urn:schemas-wifialliance-org:" 524 "device:WFADevice:1") == 0; 525 os_free(val); 526 } 527 528 return data; 529 } 530 531 532 static void wps_er_parse_device_description(struct wps_er_ap *ap, 533 struct wpabuf *reply) 534 { 535 /* Note: reply includes null termination after the buffer data */ 536 const char *tmp, *data = wpabuf_head(reply); 537 char *pos; 538 539 wpa_hexdump_ascii(MSG_MSGDUMP, "WPS ER: Device info", 540 wpabuf_head(reply), wpabuf_len(reply)); 541 542 /* 543 * The root device description may include multiple devices, so first 544 * find the beginning of the WFADevice description to allow the 545 * simplistic parser to pick the correct entries. 546 */ 547 tmp = wps_er_find_wfadevice(data); 548 if (tmp == NULL) { 549 wpa_printf(MSG_DEBUG, "WPS ER: WFADevice:1 device not found - " 550 "trying to parse invalid data"); 551 } else 552 data = tmp; 553 554 ap->friendly_name = xml_get_first_item(data, "friendlyName"); 555 wpa_printf(MSG_DEBUG, "WPS ER: friendlyName='%s'", ap->friendly_name); 556 557 ap->manufacturer = xml_get_first_item(data, "manufacturer"); 558 wpa_printf(MSG_DEBUG, "WPS ER: manufacturer='%s'", ap->manufacturer); 559 560 ap->manufacturer_url = xml_get_first_item(data, "manufacturerURL"); 561 wpa_printf(MSG_DEBUG, "WPS ER: manufacturerURL='%s'", 562 ap->manufacturer_url); 563 564 ap->model_description = xml_get_first_item(data, "modelDescription"); 565 wpa_printf(MSG_DEBUG, "WPS ER: modelDescription='%s'", 566 ap->model_description); 567 568 ap->model_name = xml_get_first_item(data, "modelName"); 569 wpa_printf(MSG_DEBUG, "WPS ER: modelName='%s'", ap->model_name); 570 571 ap->model_number = xml_get_first_item(data, "modelNumber"); 572 wpa_printf(MSG_DEBUG, "WPS ER: modelNumber='%s'", ap->model_number); 573 574 ap->model_url = xml_get_first_item(data, "modelURL"); 575 wpa_printf(MSG_DEBUG, "WPS ER: modelURL='%s'", ap->model_url); 576 577 ap->serial_number = xml_get_first_item(data, "serialNumber"); 578 wpa_printf(MSG_DEBUG, "WPS ER: serialNumber='%s'", ap->serial_number); 579 580 ap->udn = xml_get_first_item(data, "UDN"); 581 if (ap->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, 588 "WPS ER: Invalid UUID in UDN"); 589 } 590 } 591 592 ap->upc = xml_get_first_item(data, "UPC"); 593 wpa_printf(MSG_DEBUG, "WPS ER: UPC='%s'", ap->upc); 594 595 ap->scpd_url = http_link_update( 596 xml_get_first_item(data, "SCPDURL"), ap->location); 597 wpa_printf(MSG_DEBUG, "WPS ER: SCPDURL='%s'", ap->scpd_url); 598 599 ap->control_url = http_link_update( 600 xml_get_first_item(data, "controlURL"), ap->location); 601 wpa_printf(MSG_DEBUG, "WPS ER: controlURL='%s'", ap->control_url); 602 603 ap->event_sub_url = http_link_update( 604 xml_get_first_item(data, "eventSubURL"), ap->location); 605 wpa_printf(MSG_DEBUG, "WPS ER: eventSubURL='%s'", ap->event_sub_url); 606 } 607 608 609 static void wps_er_http_dev_desc_cb(void *ctx, struct http_client *c, 610 enum http_client_event event) 611 { 612 struct wps_er_ap *ap = ctx; 613 struct wpabuf *reply; 614 int ok = 0; 615 616 switch (event) { 617 case HTTP_CLIENT_OK: 618 reply = http_client_get_body(c); 619 if (reply == NULL) 620 break; 621 wps_er_parse_device_description(ap, reply); 622 ok = 1; 623 break; 624 case HTTP_CLIENT_FAILED: 625 case HTTP_CLIENT_INVALID_REPLY: 626 case HTTP_CLIENT_TIMEOUT: 627 wpa_printf(MSG_DEBUG, "WPS ER: Failed to fetch device info"); 628 break; 629 } 630 http_client_free(ap->http); 631 ap->http = NULL; 632 if (ok) 633 wps_er_get_device_info(ap); 634 } 635 636 637 void wps_er_ap_add(struct wps_er *er, const u8 *uuid, struct in_addr *addr, 638 const char *location, int max_age) 639 { 640 struct wps_er_ap *ap; 641 642 ap = wps_er_ap_get(er, addr, uuid, NULL); 643 if (ap) { 644 /* Update advertisement timeout */ 645 eloop_cancel_timeout(wps_er_ap_timeout, er, ap); 646 eloop_register_timeout(max_age, 0, wps_er_ap_timeout, er, ap); 647 return; 648 } 649 650 ap = os_zalloc(sizeof(*ap)); 651 if (ap == NULL) 652 return; 653 dl_list_init(&ap->sta); 654 ap->er = er; 655 ap->id = ++er->next_ap_id; 656 ap->location = os_strdup(location); 657 if (ap->location == NULL) { 658 os_free(ap); 659 return; 660 } 661 dl_list_add(&er->ap, &ap->list); 662 663 ap->addr.s_addr = addr->s_addr; 664 os_memcpy(ap->uuid, uuid, WPS_UUID_LEN); 665 eloop_register_timeout(max_age, 0, wps_er_ap_timeout, er, ap); 666 667 wpa_printf(MSG_DEBUG, "WPS ER: Added AP entry for %s (%s)", 668 inet_ntoa(ap->addr), ap->location); 669 670 /* Fetch device description */ 671 ap->http = http_client_url(ap->location, NULL, 10000, 672 wps_er_http_dev_desc_cb, ap); 673 } 674 675 676 void wps_er_ap_remove(struct wps_er *er, struct in_addr *addr) 677 { 678 struct wps_er_ap *ap; 679 dl_list_for_each(ap, &er->ap, struct wps_er_ap, list) { 680 if (ap->addr.s_addr == addr->s_addr) { 681 wps_er_ap_remove_entry(er, ap); 682 return; 683 } 684 } 685 } 686 687 688 static void wps_er_ap_remove_all(struct wps_er *er) 689 { 690 struct wps_er_ap *prev, *ap; 691 struct wps_er_ap_settings *prev_s, *s; 692 dl_list_for_each_safe(ap, prev, &er->ap, struct wps_er_ap, list) 693 wps_er_ap_remove_entry(er, ap); 694 dl_list_for_each_safe(s, prev_s, &er->ap_settings, 695 struct wps_er_ap_settings, list) 696 os_free(s); 697 } 698 699 700 static void http_put_date(struct wpabuf *buf) 701 { 702 wpabuf_put_str(buf, "Date: "); 703 format_date(buf); 704 wpabuf_put_str(buf, "\r\n"); 705 } 706 707 708 static void wps_er_http_resp_not_found(struct http_request *req) 709 { 710 struct wpabuf *buf; 711 buf = wpabuf_alloc(200); 712 if (buf == NULL) { 713 http_request_deinit(req); 714 return; 715 } 716 717 wpabuf_put_str(buf, 718 "HTTP/1.1 404 Not Found\r\n" 719 "Server: unspecified, UPnP/1.0, unspecified\r\n" 720 "Connection: close\r\n"); 721 http_put_date(buf); 722 wpabuf_put_str(buf, "\r\n"); 723 http_request_send_and_deinit(req, buf); 724 } 725 726 727 static void wps_er_http_resp_ok(struct http_request *req) 728 { 729 struct wpabuf *buf; 730 buf = wpabuf_alloc(200); 731 if (buf == NULL) { 732 http_request_deinit(req); 733 return; 734 } 735 736 wpabuf_put_str(buf, 737 "HTTP/1.1 200 OK\r\n" 738 "Server: unspecified, UPnP/1.0, unspecified\r\n" 739 "Connection: close\r\n" 740 "Content-Length: 0\r\n"); 741 http_put_date(buf); 742 wpabuf_put_str(buf, "\r\n"); 743 http_request_send_and_deinit(req, buf); 744 } 745 746 747 static void wps_er_sta_timeout(void *eloop_data, void *user_ctx) 748 { 749 struct wps_er_sta *sta = eloop_data; 750 wpa_printf(MSG_DEBUG, "WPS ER: STA entry timed out"); 751 dl_list_del(&sta->list); 752 wps_er_sta_free(sta); 753 } 754 755 756 static struct wps_er_sta * wps_er_add_sta_data(struct wps_er_ap *ap, 757 const u8 *addr, 758 struct wps_parse_attr *attr, 759 int probe_req) 760 { 761 struct wps_er_sta *sta = wps_er_sta_get(ap, addr, NULL); 762 int new_sta = 0; 763 int m1; 764 765 m1 = !probe_req && attr->msg_type && *attr->msg_type == WPS_M1; 766 767 if (sta == NULL) { 768 /* 769 * Only allow new STA entry to be added based on Probe Request 770 * or M1. This will filter out bogus events and anything that 771 * may have been ongoing at the time ER subscribed for events. 772 */ 773 if (!probe_req && !m1) 774 return NULL; 775 776 sta = os_zalloc(sizeof(*sta)); 777 if (sta == NULL) 778 return NULL; 779 os_memcpy(sta->addr, addr, ETH_ALEN); 780 sta->ap = ap; 781 dl_list_add(&ap->sta, &sta->list); 782 new_sta = 1; 783 } 784 785 if (m1) 786 sta->m1_received = 1; 787 788 if (attr->config_methods && (!probe_req || !sta->m1_received)) 789 sta->config_methods = WPA_GET_BE16(attr->config_methods); 790 if (attr->uuid_e && (!probe_req || !sta->m1_received)) 791 os_memcpy(sta->uuid, attr->uuid_e, WPS_UUID_LEN); 792 if (attr->primary_dev_type && (!probe_req || !sta->m1_received)) 793 os_memcpy(sta->pri_dev_type, attr->primary_dev_type, 8); 794 if (attr->dev_password_id && (!probe_req || !sta->m1_received)) 795 sta->dev_passwd_id = WPA_GET_BE16(attr->dev_password_id); 796 797 if (attr->manufacturer) { 798 os_free(sta->manufacturer); 799 sta->manufacturer = dup_binstr(attr->manufacturer, 800 attr->manufacturer_len); 801 } 802 803 if (attr->model_name) { 804 os_free(sta->model_name); 805 sta->model_name = dup_binstr(attr->model_name, 806 attr->model_name_len); 807 } 808 809 if (attr->model_number) { 810 os_free(sta->model_number); 811 sta->model_number = dup_binstr(attr->model_number, 812 attr->model_number_len); 813 } 814 815 if (attr->serial_number) { 816 os_free(sta->serial_number); 817 sta->serial_number = dup_binstr(attr->serial_number, 818 attr->serial_number_len); 819 } 820 821 if (attr->dev_name) { 822 os_free(sta->dev_name); 823 sta->dev_name = dup_binstr(attr->dev_name, attr->dev_name_len); 824 } 825 826 eloop_cancel_timeout(wps_er_sta_timeout, sta, NULL); 827 eloop_register_timeout(300, 0, wps_er_sta_timeout, sta, NULL); 828 829 if (m1 || new_sta) 830 wps_er_sta_event(ap->er->wps, sta, WPS_EV_ER_ENROLLEE_ADD); 831 832 return sta; 833 } 834 835 836 static void wps_er_process_wlanevent_probe_req(struct wps_er_ap *ap, 837 const u8 *addr, 838 struct wpabuf *msg) 839 { 840 struct wps_parse_attr attr; 841 842 wpa_printf(MSG_DEBUG, "WPS ER: WLANEvent - Probe Request - from " 843 MACSTR, MAC2STR(addr)); 844 wpa_hexdump_buf(MSG_MSGDUMP, "WPS ER: WLANEvent - Enrollee's message " 845 "(TLVs from Probe Request)", msg); 846 847 if (wps_validate_probe_req(msg, addr) < 0) { 848 wpa_printf(MSG_INFO, "WPS-STRICT: ER: Ignore invalid proxied " 849 "Probe Request frame from " MACSTR, MAC2STR(addr)); 850 return; 851 } 852 853 if (wps_parse_msg(msg, &attr) < 0) { 854 wpa_printf(MSG_DEBUG, "WPS ER: Failed to parse TLVs in " 855 "WLANEvent message"); 856 return; 857 } 858 859 wps_er_add_sta_data(ap, addr, &attr, 1); 860 wps_registrar_probe_req_rx(ap->er->wps->registrar, addr, msg, 0); 861 } 862 863 864 static void wps_er_http_put_wlan_response_cb(void *ctx, struct http_client *c, 865 enum http_client_event event) 866 { 867 struct wps_er_sta *sta = ctx; 868 869 switch (event) { 870 case HTTP_CLIENT_OK: 871 wpa_printf(MSG_DEBUG, "WPS ER: PutWLANResponse OK"); 872 break; 873 case HTTP_CLIENT_FAILED: 874 case HTTP_CLIENT_INVALID_REPLY: 875 case HTTP_CLIENT_TIMEOUT: 876 wpa_printf(MSG_DEBUG, "WPS ER: PutWLANResponse failed"); 877 break; 878 } 879 http_client_free(sta->http); 880 sta->http = NULL; 881 } 882 883 884 static const char *soap_prefix = 885 "<?xml version=\"1.0\"?>\n" 886 "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" " 887 "s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">\n" 888 "<s:Body>\n"; 889 static const char *soap_postfix = 890 "</s:Body>\n</s:Envelope>\n"; 891 static const char *urn_wfawlanconfig = 892 "urn:schemas-wifialliance-org:service:WFAWLANConfig:1"; 893 894 static struct wpabuf * wps_er_soap_hdr(const struct wpabuf *msg, 895 const char *name, const char *arg_name, 896 const char *path, 897 const struct sockaddr_in *dst, 898 char **len_ptr, char **body_ptr) 899 { 900 char *encoded; 901 size_t encoded_len; 902 struct wpabuf *buf; 903 904 if (msg) { 905 encoded = base64_encode(wpabuf_head(msg), wpabuf_len(msg), 906 &encoded_len); 907 if (encoded == NULL) 908 return NULL; 909 } else { 910 encoded = NULL; 911 encoded_len = 0; 912 } 913 914 buf = wpabuf_alloc(1000 + encoded_len); 915 if (buf == NULL) { 916 os_free(encoded); 917 return NULL; 918 } 919 920 wpabuf_printf(buf, 921 "POST %s HTTP/1.1\r\n" 922 "Host: %s:%d\r\n" 923 "Content-Type: text/xml; charset=\"utf-8\"\r\n" 924 "Content-Length: ", 925 path, inet_ntoa(dst->sin_addr), ntohs(dst->sin_port)); 926 927 *len_ptr = wpabuf_put(buf, 0); 928 wpabuf_printf(buf, 929 " \r\n" 930 "SOAPACTION: \"%s#%s\"\r\n" 931 "\r\n", 932 urn_wfawlanconfig, name); 933 934 *body_ptr = wpabuf_put(buf, 0); 935 936 wpabuf_put_str(buf, soap_prefix); 937 wpabuf_printf(buf, "<u:%s xmlns:u=\"", name); 938 wpabuf_put_str(buf, urn_wfawlanconfig); 939 wpabuf_put_str(buf, "\">\n"); 940 if (encoded) { 941 wpabuf_printf(buf, "<%s>%s</%s>\n", 942 arg_name, encoded, arg_name); 943 os_free(encoded); 944 } 945 946 return buf; 947 } 948 949 950 static void wps_er_soap_end(struct wpabuf *buf, const char *name, 951 char *len_ptr, char *body_ptr) 952 { 953 char len_buf[10]; 954 wpabuf_printf(buf, "</u:%s>\n", name); 955 wpabuf_put_str(buf, soap_postfix); 956 os_snprintf(len_buf, sizeof(len_buf), "%d", 957 (int) ((char *) wpabuf_put(buf, 0) - body_ptr)); 958 os_memcpy(len_ptr, len_buf, os_strlen(len_buf)); 959 } 960 961 962 static void wps_er_sta_send_msg(struct wps_er_sta *sta, struct wpabuf *msg) 963 { 964 struct wpabuf *buf; 965 char *len_ptr, *body_ptr; 966 struct sockaddr_in dst; 967 char *url, *path; 968 969 if (sta->http) { 970 wpa_printf(MSG_DEBUG, "WPS ER: Pending HTTP request for STA - " 971 "ignore new request"); 972 wpabuf_free(msg); 973 return; 974 } 975 976 if (sta->ap->control_url == NULL) { 977 wpa_printf(MSG_DEBUG, "WPS ER: No controlURL for AP"); 978 wpabuf_free(msg); 979 return; 980 } 981 982 url = http_client_url_parse(sta->ap->control_url, &dst, &path); 983 if (url == NULL) { 984 wpa_printf(MSG_DEBUG, "WPS ER: Failed to parse controlURL"); 985 wpabuf_free(msg); 986 return; 987 } 988 989 buf = wps_er_soap_hdr(msg, "PutWLANResponse", "NewMessage", path, &dst, 990 &len_ptr, &body_ptr); 991 wpabuf_free(msg); 992 os_free(url); 993 if (buf == NULL) 994 return; 995 wpabuf_printf(buf, "<NewWLANEventType>%d</NewWLANEventType>\n", 996 UPNP_WPS_WLANEVENT_TYPE_EAP); 997 wpabuf_printf(buf, "<NewWLANEventMAC>" MACSTR "</NewWLANEventMAC>\n", 998 MAC2STR(sta->addr)); 999 1000 wps_er_soap_end(buf, "PutWLANResponse", len_ptr, body_ptr); 1001 1002 sta->http = http_client_addr(&dst, buf, 1000, 1003 wps_er_http_put_wlan_response_cb, sta); 1004 if (sta->http == NULL) 1005 wpabuf_free(buf); 1006 } 1007 1008 1009 static void wps_er_sta_process(struct wps_er_sta *sta, struct wpabuf *msg, 1010 enum wsc_op_code op_code) 1011 { 1012 enum wps_process_res res; 1013 1014 res = wps_process_msg(sta->wps, op_code, msg); 1015 if (res == WPS_CONTINUE) { 1016 struct wpabuf *next = wps_get_msg(sta->wps, &op_code); 1017 if (next) 1018 wps_er_sta_send_msg(sta, next); 1019 } else { 1020 wpa_printf(MSG_DEBUG, "WPS ER: Protocol run %s with the " 1021 "enrollee (res=%d)", 1022 res == WPS_DONE ? "succeeded" : "failed", res); 1023 wps_deinit(sta->wps); 1024 sta->wps = NULL; 1025 if (res == WPS_DONE) { 1026 /* Remove the STA entry after short timeout */ 1027 eloop_cancel_timeout(wps_er_sta_timeout, sta, NULL); 1028 eloop_register_timeout(10, 0, wps_er_sta_timeout, sta, 1029 NULL); 1030 } 1031 } 1032 } 1033 1034 1035 static void wps_er_sta_start(struct wps_er_sta *sta, struct wpabuf *msg) 1036 { 1037 struct wps_config cfg; 1038 1039 if (sta->wps) 1040 wps_deinit(sta->wps); 1041 1042 os_memset(&cfg, 0, sizeof(cfg)); 1043 cfg.wps = sta->ap->er->wps; 1044 cfg.registrar = 1; 1045 cfg.peer_addr = sta->addr; 1046 1047 sta->wps = wps_init(&cfg); 1048 if (sta->wps == NULL) 1049 return; 1050 sta->wps->er = 1; 1051 sta->wps->use_cred = sta->ap->ap_settings; 1052 if (sta->ap->ap_settings) { 1053 os_free(sta->cred); 1054 sta->cred = os_malloc(sizeof(*sta->cred)); 1055 if (sta->cred) { 1056 os_memcpy(sta->cred, sta->ap->ap_settings, 1057 sizeof(*sta->cred)); 1058 sta->cred->cred_attr = NULL; 1059 os_memcpy(sta->cred->mac_addr, sta->addr, ETH_ALEN); 1060 sta->wps->use_cred = sta->cred; 1061 } 1062 } 1063 1064 wps_er_sta_process(sta, msg, WSC_MSG); 1065 } 1066 1067 1068 static void wps_er_process_wlanevent_eap(struct wps_er_ap *ap, const u8 *addr, 1069 struct wpabuf *msg) 1070 { 1071 struct wps_parse_attr attr; 1072 struct wps_er_sta *sta; 1073 1074 wpa_printf(MSG_DEBUG, "WPS ER: WLANEvent - EAP - from " MACSTR, 1075 MAC2STR(addr)); 1076 wpa_hexdump_buf(MSG_MSGDUMP, "WPS ER: WLANEvent - Enrollee's message " 1077 "(TLVs from EAP-WSC)", msg); 1078 1079 if (wps_parse_msg(msg, &attr) < 0) { 1080 wpa_printf(MSG_DEBUG, "WPS ER: Failed to parse TLVs in " 1081 "WLANEvent message"); 1082 return; 1083 } 1084 1085 sta = wps_er_add_sta_data(ap, addr, &attr, 0); 1086 if (sta == NULL) 1087 return; 1088 1089 if (attr.msg_type && *attr.msg_type == WPS_M1) 1090 wps_er_sta_start(sta, msg); 1091 else if (sta->wps) { 1092 enum wsc_op_code op_code = WSC_MSG; 1093 if (attr.msg_type) { 1094 switch (*attr.msg_type) { 1095 case WPS_WSC_ACK: 1096 op_code = WSC_ACK; 1097 break; 1098 case WPS_WSC_NACK: 1099 op_code = WSC_NACK; 1100 break; 1101 case WPS_WSC_DONE: 1102 op_code = WSC_Done; 1103 break; 1104 } 1105 } 1106 wps_er_sta_process(sta, msg, op_code); 1107 } 1108 } 1109 1110 1111 static void wps_er_process_wlanevent(struct wps_er_ap *ap, 1112 struct wpabuf *event) 1113 { 1114 u8 *data; 1115 u8 wlan_event_type; 1116 u8 wlan_event_mac[ETH_ALEN]; 1117 struct wpabuf msg; 1118 1119 wpa_hexdump(MSG_MSGDUMP, "WPS ER: Received WLANEvent", 1120 wpabuf_head(event), wpabuf_len(event)); 1121 if (wpabuf_len(event) < 1 + 17) { 1122 wpa_printf(MSG_DEBUG, "WPS ER: Too short WLANEvent"); 1123 return; 1124 } 1125 1126 data = wpabuf_mhead(event); 1127 wlan_event_type = data[0]; 1128 if (hwaddr_aton((char *) data + 1, wlan_event_mac) < 0) { 1129 wpa_printf(MSG_DEBUG, "WPS ER: Invalid WLANEventMAC in " 1130 "WLANEvent"); 1131 return; 1132 } 1133 1134 wpabuf_set(&msg, data + 1 + 17, wpabuf_len(event) - (1 + 17)); 1135 1136 switch (wlan_event_type) { 1137 case 1: 1138 wps_er_process_wlanevent_probe_req(ap, wlan_event_mac, &msg); 1139 break; 1140 case 2: 1141 wps_er_process_wlanevent_eap(ap, wlan_event_mac, &msg); 1142 break; 1143 default: 1144 wpa_printf(MSG_DEBUG, "WPS ER: Unknown WLANEventType %d", 1145 wlan_event_type); 1146 break; 1147 } 1148 } 1149 1150 1151 static void wps_er_http_event(struct wps_er *er, struct http_request *req, 1152 unsigned int ap_id) 1153 { 1154 struct wps_er_ap *ap = wps_er_ap_get_id(er, ap_id); 1155 struct wpabuf *event; 1156 enum http_reply_code ret; 1157 1158 if (ap == NULL) { 1159 wpa_printf(MSG_DEBUG, "WPS ER: HTTP event from unknown AP id " 1160 "%u", ap_id); 1161 wps_er_http_resp_not_found(req); 1162 return; 1163 } 1164 wpa_printf(MSG_MSGDUMP, "WPS ER: HTTP event from AP id %u: %s", 1165 ap_id, http_request_get_data(req)); 1166 1167 event = xml_get_base64_item(http_request_get_data(req), "WLANEvent", 1168 &ret); 1169 if (event == NULL) { 1170 wpa_printf(MSG_DEBUG, "WPS ER: Could not extract WLANEvent " 1171 "from the event notification"); 1172 /* 1173 * Reply with OK anyway to avoid getting unregistered from 1174 * events. 1175 */ 1176 wps_er_http_resp_ok(req); 1177 return; 1178 } 1179 1180 wps_er_process_wlanevent(ap, event); 1181 1182 wpabuf_free(event); 1183 wps_er_http_resp_ok(req); 1184 } 1185 1186 1187 static void wps_er_http_notify(struct wps_er *er, struct http_request *req) 1188 { 1189 char *uri = http_request_get_uri(req); 1190 1191 if (os_strncmp(uri, "/event/", 7) == 0) { 1192 unsigned int event_id; 1193 char *pos; 1194 event_id = atoi(uri + 7); 1195 if (event_id != er->event_id) { 1196 wpa_printf(MSG_DEBUG, "WPS ER: HTTP event for an " 1197 "unknown event id %u", event_id); 1198 return; 1199 } 1200 pos = os_strchr(uri + 7, '/'); 1201 if (pos == NULL) 1202 return; 1203 pos++; 1204 wps_er_http_event(er, req, atoi(pos)); 1205 } else { 1206 wpa_printf(MSG_DEBUG, "WPS ER: Unknown HTTP NOTIFY for '%s'", 1207 uri); 1208 wps_er_http_resp_not_found(req); 1209 } 1210 } 1211 1212 1213 static void wps_er_http_req(void *ctx, struct http_request *req) 1214 { 1215 struct wps_er *er = ctx; 1216 struct sockaddr_in *cli = http_request_get_cli_addr(req); 1217 enum httpread_hdr_type type = http_request_get_type(req); 1218 struct wpabuf *buf; 1219 1220 wpa_printf(MSG_DEBUG, "WPS ER: HTTP request: '%s' (type %d) from " 1221 "%s:%d", 1222 http_request_get_uri(req), type, 1223 inet_ntoa(cli->sin_addr), ntohs(cli->sin_port)); 1224 1225 switch (type) { 1226 case HTTPREAD_HDR_TYPE_NOTIFY: 1227 wps_er_http_notify(er, req); 1228 break; 1229 default: 1230 wpa_printf(MSG_DEBUG, "WPS ER: Unsupported HTTP request type " 1231 "%d", type); 1232 buf = wpabuf_alloc(200); 1233 if (buf == NULL) { 1234 http_request_deinit(req); 1235 return; 1236 } 1237 wpabuf_put_str(buf, 1238 "HTTP/1.1 501 Unimplemented\r\n" 1239 "Connection: close\r\n"); 1240 http_put_date(buf); 1241 wpabuf_put_str(buf, "\r\n"); 1242 http_request_send_and_deinit(req, buf); 1243 break; 1244 } 1245 } 1246 1247 1248 struct wps_er * 1249 wps_er_init(struct wps_context *wps, const char *ifname, const char *filter) 1250 { 1251 struct wps_er *er; 1252 struct in_addr addr; 1253 1254 er = os_zalloc(sizeof(*er)); 1255 if (er == NULL) 1256 return NULL; 1257 dl_list_init(&er->ap); 1258 dl_list_init(&er->ap_unsubscribing); 1259 dl_list_init(&er->ap_settings); 1260 1261 er->multicast_sd = -1; 1262 er->ssdp_sd = -1; 1263 1264 os_strlcpy(er->ifname, ifname, sizeof(er->ifname)); 1265 er->wps = wps; 1266 if (os_get_random((unsigned char *) &er->event_id, 1267 sizeof(er->event_id)) < 0) { 1268 wps_er_deinit(er, NULL, NULL); 1269 return NULL; 1270 } 1271 /* Limit event_id to < 32 bits to avoid issues with atoi() */ 1272 er->event_id &= 0x0fffffff; 1273 1274 if (filter && os_strncmp(filter, "ifname=", 7) == 0) { 1275 const char *pos, *end; 1276 pos = filter + 7; 1277 end = os_strchr(pos, ' '); 1278 if (end) { 1279 size_t len = end - pos; 1280 os_strlcpy(er->ifname, pos, len < sizeof(er->ifname) ? 1281 len + 1 : sizeof(er->ifname)); 1282 filter = end + 1; 1283 } else { 1284 os_strlcpy(er->ifname, pos, sizeof(er->ifname)); 1285 filter = NULL; 1286 } 1287 er->forced_ifname = 1; 1288 } 1289 1290 if (filter) { 1291 if (inet_aton(filter, &er->filter_addr) == 0) { 1292 wpa_printf(MSG_INFO, "WPS UPnP: Invalid filter " 1293 "address %s", filter); 1294 wps_er_deinit(er, NULL, NULL); 1295 return NULL; 1296 } 1297 wpa_printf(MSG_DEBUG, "WPS UPnP: Only accepting connections " 1298 "with %s", filter); 1299 } 1300 if (get_netif_info(er->ifname, &er->ip_addr, &er->ip_addr_text, 1301 NULL, er->mac_addr)) { 1302 wpa_printf(MSG_INFO, "WPS UPnP: Could not get IP/MAC address " 1303 "for %s. Does it have IP address?", er->ifname); 1304 wps_er_deinit(er, NULL, NULL); 1305 return NULL; 1306 } 1307 1308 if (wps_er_ssdp_init(er) < 0) { 1309 wpa_printf(MSG_INFO, "WPS UPnP: SSDP initialization failed"); 1310 wps_er_deinit(er, NULL, NULL); 1311 return NULL; 1312 } 1313 1314 addr.s_addr = er->ip_addr; 1315 er->http_srv = http_server_init(&addr, -1, wps_er_http_req, er); 1316 if (er->http_srv == NULL) { 1317 wpa_printf(MSG_INFO, "WPS UPnP: HTTP initialization failed"); 1318 wps_er_deinit(er, NULL, NULL); 1319 return NULL; 1320 } 1321 er->http_port = http_server_get_port(er->http_srv); 1322 1323 wpa_printf(MSG_DEBUG, "WPS ER: Start (ifname=%s ip_addr=%s)", 1324 er->ifname, er->ip_addr_text); 1325 1326 return er; 1327 } 1328 1329 1330 void wps_er_refresh(struct wps_er *er) 1331 { 1332 struct wps_er_ap *ap; 1333 struct wps_er_sta *sta; 1334 1335 dl_list_for_each(ap, &er->ap, struct wps_er_ap, list) { 1336 wps_er_ap_event(er->wps, ap, WPS_EV_ER_AP_ADD); 1337 dl_list_for_each(sta, &ap->sta, struct wps_er_sta, list) 1338 wps_er_sta_event(er->wps, sta, WPS_EV_ER_ENROLLEE_ADD); 1339 } 1340 1341 wps_er_send_ssdp_msearch(er); 1342 } 1343 1344 1345 static void wps_er_deinit_finish(void *eloop_data, void *user_ctx) 1346 { 1347 struct wps_er *er = eloop_data; 1348 void (*deinit_done_cb)(void *ctx); 1349 void *deinit_done_ctx; 1350 struct wps_er_ap *ap, *tmp; 1351 1352 wpa_printf(MSG_DEBUG, "WPS ER: Finishing deinit"); 1353 1354 dl_list_for_each_safe(ap, tmp, &er->ap_unsubscribing, struct wps_er_ap, 1355 list) { 1356 wpa_printf(MSG_DEBUG, "WPS ER: AP entry for %s (%s) still in ap_unsubscribing list - free it", 1357 inet_ntoa(ap->addr), ap->location); 1358 dl_list_del(&ap->list); 1359 wps_er_ap_free(ap); 1360 } 1361 1362 eloop_cancel_timeout(wps_er_deinit_finish, er, NULL); 1363 deinit_done_cb = er->deinit_done_cb; 1364 deinit_done_ctx = er->deinit_done_ctx; 1365 os_free(er->ip_addr_text); 1366 os_free(er); 1367 1368 if (deinit_done_cb) 1369 deinit_done_cb(deinit_done_ctx); 1370 } 1371 1372 1373 void wps_er_deinit(struct wps_er *er, void (*cb)(void *ctx), void *ctx) 1374 { 1375 if (er == NULL) 1376 return; 1377 http_server_deinit(er->http_srv); 1378 wps_er_ap_remove_all(er); 1379 wps_er_ssdp_deinit(er); 1380 eloop_register_timeout(dl_list_empty(&er->ap_unsubscribing) ? 0 : 5, 0, 1381 wps_er_deinit_finish, er, NULL); 1382 wpa_printf(MSG_DEBUG, "WPS ER: Finish deinit from timeout"); 1383 er->deinitializing = 1; 1384 er->deinit_done_cb = cb; 1385 er->deinit_done_ctx = ctx; 1386 } 1387 1388 1389 static void wps_er_http_set_sel_reg_cb(void *ctx, struct http_client *c, 1390 enum http_client_event event) 1391 { 1392 struct wps_er_ap *ap = ctx; 1393 union wps_event_data data; 1394 1395 os_memset(&data, 0, sizeof(data)); 1396 1397 switch (event) { 1398 case HTTP_CLIENT_OK: 1399 wpa_printf(MSG_DEBUG, "WPS ER: SetSelectedRegistrar OK"); 1400 data.set_sel_reg.state = WPS_ER_SET_SEL_REG_DONE; 1401 data.set_sel_reg.uuid = ap->uuid; 1402 break; 1403 case HTTP_CLIENT_FAILED: 1404 case HTTP_CLIENT_INVALID_REPLY: 1405 case HTTP_CLIENT_TIMEOUT: 1406 wpa_printf(MSG_DEBUG, "WPS ER: SetSelectedRegistrar failed"); 1407 data.set_sel_reg.state = WPS_ER_SET_SEL_REG_FAILED; 1408 data.set_sel_reg.uuid = ap->uuid; 1409 break; 1410 } 1411 http_client_free(ap->http); 1412 ap->http = NULL; 1413 1414 if (data.set_sel_reg.uuid) 1415 ap->er->wps->event_cb(ap->er->wps->cb_ctx, 1416 WPS_EV_ER_SET_SELECTED_REGISTRAR, &data); 1417 } 1418 1419 1420 static void wps_er_send_set_sel_reg(struct wps_er_ap *ap, struct wpabuf *msg) 1421 { 1422 struct wpabuf *buf; 1423 char *len_ptr, *body_ptr; 1424 struct sockaddr_in dst; 1425 char *url, *path; 1426 1427 if (ap->control_url == NULL) { 1428 wpa_printf(MSG_DEBUG, "WPS ER: No controlURL for AP"); 1429 return; 1430 } 1431 1432 if (ap->http) { 1433 wpa_printf(MSG_DEBUG, "WPS ER: Pending HTTP request for AP - " 1434 "ignore new request"); 1435 return; 1436 } 1437 1438 if (ap->wps) { 1439 wpa_printf(MSG_DEBUG, "WPS ER: Pending WPS operation for AP - " 1440 "skip SetSelectedRegistrar"); 1441 return; 1442 } 1443 1444 url = http_client_url_parse(ap->control_url, &dst, &path); 1445 if (url == NULL) { 1446 wpa_printf(MSG_DEBUG, "WPS ER: Failed to parse controlURL"); 1447 return; 1448 } 1449 1450 buf = wps_er_soap_hdr(msg, "SetSelectedRegistrar", "NewMessage", path, 1451 &dst, &len_ptr, &body_ptr); 1452 os_free(url); 1453 if (buf == NULL) 1454 return; 1455 1456 wps_er_soap_end(buf, "SetSelectedRegistrar", len_ptr, body_ptr); 1457 1458 ap->http = http_client_addr(&dst, buf, 1000, 1459 wps_er_http_set_sel_reg_cb, ap); 1460 if (ap->http == NULL) 1461 wpabuf_free(buf); 1462 } 1463 1464 1465 static int wps_er_build_selected_registrar(struct wpabuf *msg, int sel_reg) 1466 { 1467 wpabuf_put_be16(msg, ATTR_SELECTED_REGISTRAR); 1468 wpabuf_put_be16(msg, 1); 1469 wpabuf_put_u8(msg, !!sel_reg); 1470 return 0; 1471 } 1472 1473 1474 static int wps_er_build_dev_password_id(struct wpabuf *msg, u16 dev_passwd_id) 1475 { 1476 wpabuf_put_be16(msg, ATTR_DEV_PASSWORD_ID); 1477 wpabuf_put_be16(msg, 2); 1478 wpabuf_put_be16(msg, dev_passwd_id); 1479 return 0; 1480 } 1481 1482 1483 static int wps_er_build_sel_reg_config_methods(struct wpabuf *msg, 1484 u16 sel_reg_config_methods) 1485 { 1486 wpabuf_put_be16(msg, ATTR_SELECTED_REGISTRAR_CONFIG_METHODS); 1487 wpabuf_put_be16(msg, 2); 1488 wpabuf_put_be16(msg, sel_reg_config_methods); 1489 return 0; 1490 } 1491 1492 1493 static int wps_er_build_uuid_r(struct wpabuf *msg, const u8 *uuid_r) 1494 { 1495 wpabuf_put_be16(msg, ATTR_UUID_R); 1496 wpabuf_put_be16(msg, WPS_UUID_LEN); 1497 wpabuf_put_data(msg, uuid_r, WPS_UUID_LEN); 1498 return 0; 1499 } 1500 1501 1502 void wps_er_set_sel_reg(struct wps_er *er, int sel_reg, u16 dev_passwd_id, 1503 u16 sel_reg_config_methods) 1504 { 1505 struct wpabuf *msg; 1506 struct wps_er_ap *ap; 1507 struct wps_registrar *reg = er->wps->registrar; 1508 const u8 *auth_macs; 1509 u8 bcast[ETH_ALEN]; 1510 size_t count; 1511 union wps_event_data data; 1512 1513 if (er->skip_set_sel_reg) { 1514 wpa_printf(MSG_DEBUG, "WPS ER: Skip SetSelectedRegistrar"); 1515 return; 1516 } 1517 1518 msg = wpabuf_alloc(500); 1519 if (msg == NULL) 1520 return; 1521 1522 auth_macs = wps_authorized_macs(reg, &count); 1523 if (count == 0) { 1524 os_memset(bcast, 0xff, ETH_ALEN); 1525 auth_macs = bcast; 1526 count = 1; 1527 } 1528 1529 if (wps_build_version(msg) || 1530 wps_er_build_selected_registrar(msg, sel_reg) || 1531 wps_er_build_dev_password_id(msg, dev_passwd_id) || 1532 wps_er_build_sel_reg_config_methods(msg, sel_reg_config_methods) || 1533 wps_build_wfa_ext(msg, 0, auth_macs, count, 0) || 1534 wps_er_build_uuid_r(msg, er->wps->uuid)) { 1535 wpabuf_free(msg); 1536 return; 1537 } 1538 1539 os_memset(&data, 0, sizeof(data)); 1540 data.set_sel_reg.sel_reg = sel_reg; 1541 data.set_sel_reg.dev_passwd_id = dev_passwd_id; 1542 data.set_sel_reg.sel_reg_config_methods = sel_reg_config_methods; 1543 data.set_sel_reg.state = WPS_ER_SET_SEL_REG_START; 1544 1545 dl_list_for_each(ap, &er->ap, struct wps_er_ap, list) { 1546 if (er->set_sel_reg_uuid_filter && 1547 os_memcmp(ap->uuid, er->set_sel_reg_uuid_filter, 1548 WPS_UUID_LEN) != 0) 1549 continue; 1550 data.set_sel_reg.uuid = ap->uuid; 1551 er->wps->event_cb(er->wps->cb_ctx, 1552 WPS_EV_ER_SET_SELECTED_REGISTRAR, &data); 1553 wps_er_send_set_sel_reg(ap, msg); 1554 } 1555 1556 wpabuf_free(msg); 1557 } 1558 1559 1560 int wps_er_pbc(struct wps_er *er, const u8 *uuid, const u8 *addr) 1561 { 1562 int res; 1563 struct wps_er_ap *ap; 1564 1565 if (er == NULL || er->wps == NULL) 1566 return -1; 1567 1568 if (wps_registrar_pbc_overlap(er->wps->registrar, NULL, NULL)) { 1569 wpa_printf(MSG_DEBUG, "WPS ER: PBC overlap - do not start PBC " 1570 "mode"); 1571 return -2; 1572 } 1573 1574 if (uuid) 1575 ap = wps_er_ap_get(er, NULL, uuid, NULL); 1576 else 1577 ap = NULL; 1578 if (ap == NULL) { 1579 struct wps_er_sta *sta = NULL; 1580 dl_list_for_each(ap, &er->ap, struct wps_er_ap, list) { 1581 sta = wps_er_sta_get(ap, addr, uuid); 1582 if (sta) { 1583 uuid = ap->uuid; 1584 break; 1585 } 1586 } 1587 if (sta == NULL) 1588 return -3; /* Unknown UUID */ 1589 } 1590 1591 if (ap->ap_settings == NULL) { 1592 wpa_printf(MSG_DEBUG, "WPS ER: AP settings not known"); 1593 return -4; 1594 } 1595 1596 er->set_sel_reg_uuid_filter = uuid; 1597 res = wps_registrar_button_pushed(er->wps->registrar, NULL); 1598 er->set_sel_reg_uuid_filter = NULL; 1599 if (res) 1600 return -1; 1601 1602 return 0; 1603 } 1604 1605 1606 static void wps_er_ap_settings_cb(void *ctx, const struct wps_credential *cred) 1607 { 1608 struct wps_er_ap *ap = ctx; 1609 union wps_event_data data; 1610 1611 wpa_printf(MSG_DEBUG, "WPS ER: AP Settings received"); 1612 os_free(ap->ap_settings); 1613 ap->ap_settings = os_malloc(sizeof(*cred)); 1614 if (ap->ap_settings) { 1615 os_memcpy(ap->ap_settings, cred, sizeof(*cred)); 1616 ap->ap_settings->cred_attr = NULL; 1617 } 1618 1619 os_memset(&data, 0, sizeof(data)); 1620 data.ap_settings.uuid = ap->uuid; 1621 data.ap_settings.cred = cred; 1622 ap->er->wps->event_cb(ap->er->wps->cb_ctx, WPS_EV_ER_AP_SETTINGS, 1623 &data); 1624 } 1625 1626 1627 const u8 * wps_er_get_sta_uuid(struct wps_er *er, const u8 *addr) 1628 { 1629 struct wps_er_ap *ap; 1630 dl_list_for_each(ap, &er->ap, struct wps_er_ap, list) { 1631 struct wps_er_sta *sta; 1632 sta = wps_er_sta_get(ap, addr, NULL); 1633 if (sta) 1634 return sta->uuid; 1635 } 1636 return NULL; 1637 } 1638 1639 1640 static void wps_er_http_put_message_cb(void *ctx, struct http_client *c, 1641 enum http_client_event event) 1642 { 1643 struct wps_er_ap *ap = ctx; 1644 struct wpabuf *reply; 1645 char *msg = NULL; 1646 1647 switch (event) { 1648 case HTTP_CLIENT_OK: 1649 wpa_printf(MSG_DEBUG, "WPS ER: PutMessage OK"); 1650 reply = http_client_get_body(c); 1651 if (reply) 1652 msg = os_zalloc(wpabuf_len(reply) + 1); 1653 if (msg == NULL) { 1654 if (ap->wps) { 1655 wps_deinit(ap->wps); 1656 ap->wps = NULL; 1657 } 1658 break; 1659 } 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 1693 static 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 goto fail; 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 goto fail; 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 goto fail; 1731 } 1732 return; 1733 1734 fail: 1735 if (ap->wps) { 1736 wps_deinit(ap->wps); 1737 ap->wps = NULL; 1738 } 1739 } 1740 1741 1742 static void wps_er_ap_process(struct wps_er_ap *ap, struct wpabuf *msg) 1743 { 1744 enum wps_process_res res; 1745 struct wps_parse_attr attr; 1746 enum wsc_op_code op_code; 1747 1748 op_code = WSC_MSG; 1749 if (wps_parse_msg(msg, &attr) == 0 && attr.msg_type) { 1750 switch (*attr.msg_type) { 1751 case WPS_WSC_ACK: 1752 op_code = WSC_ACK; 1753 break; 1754 case WPS_WSC_NACK: 1755 op_code = WSC_NACK; 1756 break; 1757 case WPS_WSC_DONE: 1758 op_code = WSC_Done; 1759 break; 1760 } 1761 } 1762 1763 res = wps_process_msg(ap->wps, op_code, msg); 1764 if (res == WPS_CONTINUE) { 1765 struct wpabuf *next = wps_get_msg(ap->wps, &op_code); 1766 if (next) { 1767 wps_er_ap_put_message(ap, next); 1768 wpabuf_free(next); 1769 } else { 1770 wpa_printf(MSG_DEBUG, "WPS ER: Failed to build " 1771 "message"); 1772 wps_deinit(ap->wps); 1773 ap->wps = NULL; 1774 } 1775 } else if (res == WPS_DONE) { 1776 wpa_printf(MSG_DEBUG, "WPS ER: Protocol run done"); 1777 wps_deinit(ap->wps); 1778 ap->wps = NULL; 1779 } else { 1780 wpa_printf(MSG_DEBUG, "WPS ER: Failed to process message from " 1781 "AP (res=%d)", res); 1782 wps_deinit(ap->wps); 1783 ap->wps = NULL; 1784 } 1785 } 1786 1787 1788 static void wps_er_ap_learn_m1(struct wps_er_ap *ap, struct wpabuf *m1) 1789 { 1790 struct wps_config cfg; 1791 1792 if (ap->wps) { 1793 wpa_printf(MSG_DEBUG, "WPS ER: Protocol run already in " 1794 "progress with this AP"); 1795 return; 1796 } 1797 1798 os_memset(&cfg, 0, sizeof(cfg)); 1799 cfg.wps = ap->er->wps; 1800 cfg.registrar = 1; 1801 ap->wps = wps_init(&cfg); 1802 if (ap->wps == NULL) 1803 return; 1804 ap->wps->ap_settings_cb = wps_er_ap_settings_cb; 1805 ap->wps->ap_settings_cb_ctx = ap; 1806 1807 wps_er_ap_process(ap, m1); 1808 } 1809 1810 1811 static void wps_er_ap_learn(struct wps_er_ap *ap, const char *dev_info) 1812 { 1813 struct wpabuf *info; 1814 enum http_reply_code ret; 1815 1816 wpa_printf(MSG_DEBUG, "WPS ER: Received GetDeviceInfo response (M1) " 1817 "from the AP"); 1818 info = xml_get_base64_item(dev_info, "NewDeviceInfo", &ret); 1819 if (info == NULL) { 1820 wpa_printf(MSG_DEBUG, "WPS ER: Could not extract " 1821 "NewDeviceInfo from GetDeviceInfo response"); 1822 return; 1823 } 1824 1825 ap->m1_handler(ap, info); 1826 wpabuf_free(info); 1827 } 1828 1829 1830 static void wps_er_http_get_dev_info_cb(void *ctx, struct http_client *c, 1831 enum http_client_event event) 1832 { 1833 struct wps_er_ap *ap = ctx; 1834 struct wpabuf *reply; 1835 char *dev_info = NULL; 1836 1837 switch (event) { 1838 case HTTP_CLIENT_OK: 1839 wpa_printf(MSG_DEBUG, "WPS ER: GetDeviceInfo OK"); 1840 reply = http_client_get_body(c); 1841 if (reply == NULL) 1842 break; 1843 dev_info = os_zalloc(wpabuf_len(reply) + 1); 1844 if (dev_info == NULL) 1845 break; 1846 os_memcpy(dev_info, wpabuf_head(reply), wpabuf_len(reply)); 1847 break; 1848 case HTTP_CLIENT_FAILED: 1849 case HTTP_CLIENT_INVALID_REPLY: 1850 case HTTP_CLIENT_TIMEOUT: 1851 wpa_printf(MSG_DEBUG, "WPS ER: GetDeviceInfo failed"); 1852 break; 1853 } 1854 http_client_free(ap->http); 1855 ap->http = NULL; 1856 1857 if (dev_info) { 1858 wps_er_ap_learn(ap, dev_info); 1859 os_free(dev_info); 1860 } 1861 } 1862 1863 1864 static int wps_er_send_get_device_info(struct wps_er_ap *ap, 1865 void (*m1_handler)(struct wps_er_ap *ap, 1866 struct wpabuf *m1)) 1867 { 1868 struct wpabuf *buf; 1869 char *len_ptr, *body_ptr; 1870 struct sockaddr_in dst; 1871 char *url, *path; 1872 1873 if (ap->http) { 1874 wpa_printf(MSG_DEBUG, "WPS ER: Pending HTTP operation ongoing " 1875 "with the AP - cannot get device info"); 1876 return -1; 1877 } 1878 1879 if (ap->control_url == NULL) { 1880 wpa_printf(MSG_DEBUG, "WPS ER: No controlURL for AP"); 1881 return -1; 1882 } 1883 1884 url = http_client_url_parse(ap->control_url, &dst, &path); 1885 if (url == NULL) { 1886 wpa_printf(MSG_DEBUG, "WPS ER: Failed to parse controlURL"); 1887 return -1; 1888 } 1889 1890 buf = wps_er_soap_hdr(NULL, "GetDeviceInfo", NULL, path, &dst, 1891 &len_ptr, &body_ptr); 1892 os_free(url); 1893 if (buf == NULL) 1894 return -1; 1895 1896 wps_er_soap_end(buf, "GetDeviceInfo", len_ptr, body_ptr); 1897 1898 ap->http = http_client_addr(&dst, buf, 10000, 1899 wps_er_http_get_dev_info_cb, ap); 1900 if (ap->http == NULL) { 1901 wpabuf_free(buf); 1902 return -1; 1903 } 1904 1905 ap->m1_handler = m1_handler; 1906 1907 return 0; 1908 } 1909 1910 1911 int wps_er_learn(struct wps_er *er, const u8 *uuid, const u8 *addr, 1912 const u8 *pin, size_t pin_len) 1913 { 1914 struct wps_er_ap *ap; 1915 1916 if (er == NULL) 1917 return -1; 1918 1919 ap = wps_er_ap_get(er, NULL, uuid, addr); 1920 if (ap == NULL) { 1921 wpa_printf(MSG_DEBUG, "WPS ER: AP not found for learn " 1922 "request"); 1923 return -1; 1924 } 1925 if (uuid == NULL) 1926 uuid = ap->uuid; 1927 if (ap->wps) { 1928 wpa_printf(MSG_DEBUG, "WPS ER: Pending operation ongoing " 1929 "with the AP - cannot start learn"); 1930 return -1; 1931 } 1932 1933 if (wps_er_send_get_device_info(ap, wps_er_ap_learn_m1) < 0) 1934 return -1; 1935 1936 er->skip_set_sel_reg = 1; 1937 wps_registrar_add_pin(er->wps->registrar, NULL, uuid, pin, pin_len, 0); 1938 er->skip_set_sel_reg = 0; 1939 1940 return 0; 1941 } 1942 1943 1944 int wps_er_set_config(struct wps_er *er, const u8 *uuid, const u8 *addr, 1945 const struct wps_credential *cred) 1946 { 1947 struct wps_er_ap *ap; 1948 1949 if (er == NULL) 1950 return -1; 1951 1952 ap = wps_er_ap_get(er, NULL, uuid, addr); 1953 if (ap == NULL) { 1954 wpa_printf(MSG_DEBUG, "WPS ER: AP not found for set config " 1955 "request"); 1956 return -1; 1957 } 1958 1959 os_free(ap->ap_settings); 1960 ap->ap_settings = os_memdup(cred, sizeof(*cred)); 1961 if (ap->ap_settings == NULL) 1962 return -1; 1963 ap->ap_settings->cred_attr = NULL; 1964 wpa_printf(MSG_DEBUG, "WPS ER: Updated local AP settings based set " 1965 "config request"); 1966 1967 return 0; 1968 } 1969 1970 1971 static void wps_er_ap_config_m1(struct wps_er_ap *ap, struct wpabuf *m1) 1972 { 1973 struct wps_config cfg; 1974 1975 if (ap->wps) { 1976 wpa_printf(MSG_DEBUG, "WPS ER: Protocol run already in " 1977 "progress with this AP"); 1978 return; 1979 } 1980 1981 os_memset(&cfg, 0, sizeof(cfg)); 1982 cfg.wps = ap->er->wps; 1983 cfg.registrar = 1; 1984 cfg.new_ap_settings = ap->ap_settings; 1985 ap->wps = wps_init(&cfg); 1986 if (ap->wps == NULL) 1987 return; 1988 ap->wps->ap_settings_cb = NULL; 1989 ap->wps->ap_settings_cb_ctx = NULL; 1990 1991 wps_er_ap_process(ap, m1); 1992 } 1993 1994 1995 int wps_er_config(struct wps_er *er, const u8 *uuid, const u8 *addr, 1996 const u8 *pin, size_t pin_len, 1997 const struct wps_credential *cred) 1998 { 1999 struct wps_er_ap *ap; 2000 2001 if (er == NULL) 2002 return -1; 2003 2004 ap = wps_er_ap_get(er, NULL, uuid, addr); 2005 if (ap == NULL) { 2006 wpa_printf(MSG_DEBUG, "WPS ER: AP not found for config " 2007 "request"); 2008 return -1; 2009 } 2010 if (uuid == NULL) 2011 uuid = ap->uuid; 2012 if (ap->wps) { 2013 wpa_printf(MSG_DEBUG, "WPS ER: Pending operation ongoing " 2014 "with the AP - cannot start config"); 2015 return -1; 2016 } 2017 2018 os_free(ap->ap_settings); 2019 ap->ap_settings = os_memdup(cred, sizeof(*cred)); 2020 if (ap->ap_settings == NULL) 2021 return -1; 2022 ap->ap_settings->cred_attr = NULL; 2023 2024 if (wps_er_send_get_device_info(ap, wps_er_ap_config_m1) < 0) 2025 return -1; 2026 2027 er->skip_set_sel_reg = 1; 2028 wps_registrar_add_pin(er->wps->registrar, NULL, uuid, pin, pin_len, 0); 2029 er->skip_set_sel_reg = 0; 2030 2031 return 0; 2032 } 2033 2034 2035 #ifdef CONFIG_WPS_NFC 2036 2037 struct wpabuf * wps_er_config_token_from_cred(struct wps_context *wps, 2038 struct wps_credential *cred) 2039 { 2040 struct wpabuf *ret; 2041 struct wps_data data; 2042 2043 ret = wpabuf_alloc(500); 2044 if (ret == NULL) 2045 return NULL; 2046 2047 os_memset(&data, 0, sizeof(data)); 2048 data.wps = wps; 2049 data.use_cred = cred; 2050 if (wps_build_cred(&data, ret) || 2051 wps_build_wfa_ext(ret, 0, NULL, 0, 0)) { 2052 wpabuf_free(ret); 2053 return NULL; 2054 } 2055 2056 return ret; 2057 } 2058 2059 2060 struct wpabuf * wps_er_nfc_config_token(struct wps_er *er, const u8 *uuid, 2061 const u8 *addr) 2062 { 2063 struct wps_er_ap *ap; 2064 2065 if (er == NULL) 2066 return NULL; 2067 2068 ap = wps_er_ap_get(er, NULL, uuid, addr); 2069 if (ap == NULL) 2070 return NULL; 2071 if (ap->ap_settings == NULL) { 2072 wpa_printf(MSG_DEBUG, "WPS ER: No settings known for the " 2073 "selected AP"); 2074 return NULL; 2075 } 2076 2077 return wps_er_config_token_from_cred(er->wps, ap->ap_settings); 2078 } 2079 2080 2081 struct wpabuf * wps_er_nfc_handover_sel(struct wps_er *er, 2082 struct wps_context *wps, const u8 *uuid, 2083 const u8 *addr, struct wpabuf *pubkey) 2084 { 2085 struct wps_er_ap *ap; 2086 2087 if (er == NULL) 2088 return NULL; 2089 2090 ap = wps_er_ap_get(er, NULL, uuid, addr); 2091 if (ap == NULL) 2092 return NULL; 2093 if (ap->ap_settings == NULL) { 2094 wpa_printf(MSG_DEBUG, "WPS ER: No settings known for the " 2095 "selected AP"); 2096 return NULL; 2097 } 2098 2099 os_memcpy(wps->ssid, ap->ap_settings->ssid, ap->ap_settings->ssid_len); 2100 wps->ssid_len = ap->ap_settings->ssid_len; 2101 2102 return wps_build_nfc_handover_sel(wps, pubkey, addr, 0); 2103 } 2104 2105 #endif /* CONFIG_WPS_NFC */ 2106