1 /* 2 * Wi-Fi Protected Setup - External Registrar 3 * Copyright (c) 2009-2013, Jouni Malinen <j (at) 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 eloop_cancel_timeout(wps_er_deinit_finish, er, NULL); 190 wps_er_deinit_finish(er, NULL); 191 } 192 } 193 194 195 static void wps_er_http_unsubscribe_cb(void *ctx, struct http_client *c, 196 enum http_client_event event) 197 { 198 struct wps_er_ap *ap = ctx; 199 200 switch (event) { 201 case HTTP_CLIENT_OK: 202 wpa_printf(MSG_DEBUG, "WPS ER: Unsubscribed from events"); 203 ap->subscribed = 0; 204 break; 205 case HTTP_CLIENT_FAILED: 206 case HTTP_CLIENT_INVALID_REPLY: 207 case HTTP_CLIENT_TIMEOUT: 208 wpa_printf(MSG_DEBUG, "WPS ER: Failed to unsubscribe from " 209 "events"); 210 break; 211 } 212 http_client_free(ap->http); 213 ap->http = NULL; 214 215 /* 216 * Need to get rid of the AP entry regardless of whether we managed to 217 * unsubscribe cleanly or not. 218 */ 219 wps_er_ap_unsubscribed(ap->er, ap); 220 } 221 222 223 static void wps_er_ap_unsubscribe(struct wps_er *er, struct wps_er_ap *ap) 224 { 225 struct wpabuf *req; 226 struct sockaddr_in dst; 227 char *url, *path; 228 char sid[100]; 229 230 if (ap->event_sub_url == NULL) { 231 wpa_printf(MSG_DEBUG, "WPS ER: No eventSubURL - cannot " 232 "subscribe"); 233 goto fail; 234 } 235 if (ap->http) { 236 wpa_printf(MSG_DEBUG, "WPS ER: Pending HTTP request - cannot " 237 "send subscribe request"); 238 goto fail; 239 } 240 241 url = http_client_url_parse(ap->event_sub_url, &dst, &path); 242 if (url == NULL) { 243 wpa_printf(MSG_DEBUG, "WPS ER: Failed to parse eventSubURL"); 244 goto fail; 245 } 246 247 req = wpabuf_alloc(os_strlen(ap->event_sub_url) + 1000); 248 if (req == NULL) { 249 os_free(url); 250 goto fail; 251 } 252 uuid_bin2str(ap->sid, sid, sizeof(sid)); 253 wpabuf_printf(req, 254 "UNSUBSCRIBE %s HTTP/1.1\r\n" 255 "HOST: %s:%d\r\n" 256 "SID: uuid:%s\r\n" 257 "\r\n", 258 path, inet_ntoa(dst.sin_addr), ntohs(dst.sin_port), sid); 259 os_free(url); 260 wpa_hexdump_ascii(MSG_MSGDUMP, "WPS ER: Unsubscription request", 261 wpabuf_head(req), wpabuf_len(req)); 262 263 ap->http = http_client_addr(&dst, req, 1000, 264 wps_er_http_unsubscribe_cb, ap); 265 if (ap->http == NULL) { 266 wpabuf_free(req); 267 goto fail; 268 } 269 return; 270 271 fail: 272 /* 273 * Need to get rid of the AP entry even when we fail to unsubscribe 274 * cleanly. 275 */ 276 wps_er_ap_unsubscribed(ap->er, ap); 277 } 278 279 280 static struct wps_er_ap_settings * wps_er_ap_get_settings(struct wps_er *er, 281 const u8 *uuid) 282 { 283 struct wps_er_ap_settings *s; 284 dl_list_for_each(s, &er->ap_settings, struct wps_er_ap_settings, list) 285 if (os_memcmp(uuid, s->uuid, WPS_UUID_LEN) == 0) 286 return s; 287 return NULL; 288 } 289 290 291 int wps_er_ap_cache_settings(struct wps_er *er, struct in_addr *addr) 292 { 293 struct wps_er_ap *ap; 294 struct wps_er_ap_settings *settings; 295 296 ap = wps_er_ap_get(er, addr, NULL, NULL); 297 if (ap == NULL || ap->ap_settings == NULL) 298 return -1; 299 300 settings = wps_er_ap_get_settings(er, ap->uuid); 301 if (!settings) { 302 settings = os_zalloc(sizeof(*settings)); 303 if (settings == NULL) 304 return -1; 305 os_memcpy(settings->uuid, ap->uuid, WPS_UUID_LEN); 306 dl_list_add(&er->ap_settings, &settings->list); 307 } 308 os_memcpy(&settings->ap_settings, ap->ap_settings, 309 sizeof(struct wps_credential)); 310 311 return 0; 312 } 313 314 315 static int wps_er_ap_use_cached_settings(struct wps_er *er, 316 struct wps_er_ap *ap) 317 { 318 struct wps_er_ap_settings *s; 319 320 if (ap->ap_settings) 321 return 0; 322 323 s = wps_er_ap_get_settings(ap->er, ap->uuid); 324 if (!s) 325 return -1; 326 327 ap->ap_settings = os_malloc(sizeof(*ap->ap_settings)); 328 if (ap->ap_settings == NULL) 329 return -1; 330 331 os_memcpy(ap->ap_settings, &s->ap_settings, sizeof(*ap->ap_settings)); 332 wpa_printf(MSG_DEBUG, "WPS ER: Use cached AP settings"); 333 return 0; 334 } 335 336 337 static void wps_er_ap_remove_entry(struct wps_er *er, struct wps_er_ap *ap) 338 { 339 wpa_printf(MSG_DEBUG, "WPS ER: Removing AP entry for %s (%s)", 340 inet_ntoa(ap->addr), ap->location); 341 eloop_cancel_timeout(wps_er_ap_timeout, er, ap); 342 wps_er_sta_remove_all(ap); 343 wps_er_ap_event(er->wps, ap, WPS_EV_ER_AP_REMOVE); 344 http_client_free(ap->http); 345 ap->http = NULL; 346 if (ap->wps) { 347 wps_deinit(ap->wps); 348 ap->wps = NULL; 349 } 350 351 dl_list_del(&ap->list); 352 if (ap->subscribed) { 353 dl_list_add(&er->ap_unsubscribing, &ap->list); 354 wps_er_ap_unsubscribe(er, ap); 355 } else 356 wps_er_ap_free(ap); 357 } 358 359 360 static void wps_er_ap_timeout(void *eloop_data, void *user_ctx) 361 { 362 struct wps_er *er = eloop_data; 363 struct wps_er_ap *ap = user_ctx; 364 wpa_printf(MSG_DEBUG, "WPS ER: AP advertisement timed out"); 365 wps_er_ap_remove_entry(er, ap); 366 } 367 368 369 static int wps_er_get_sid(struct wps_er_ap *ap, char *sid) 370 { 371 char *pos; 372 char txt[100]; 373 374 if (!sid) { 375 wpa_printf(MSG_DEBUG, "WPS ER: No SID received from %s (%s)", 376 inet_ntoa(ap->addr), ap->location); 377 return -1; 378 } 379 380 pos = os_strstr(sid, "uuid:"); 381 if (!pos) { 382 wpa_printf(MSG_DEBUG, "WPS ER: Invalid SID received from " 383 "%s (%s): '%s'", inet_ntoa(ap->addr), ap->location, 384 sid); 385 return -1; 386 } 387 388 pos += 5; 389 if (uuid_str2bin(pos, ap->sid) < 0) { 390 wpa_printf(MSG_DEBUG, "WPS ER: Invalid SID received from " 391 "%s (%s): '%s'", inet_ntoa(ap->addr), ap->location, 392 sid); 393 return -1; 394 } 395 396 uuid_bin2str(ap->sid, txt, sizeof(txt)); 397 wpa_printf(MSG_DEBUG, "WPS ER: SID for subscription with %s (%s): %s", 398 inet_ntoa(ap->addr), ap->location, txt); 399 400 return 0; 401 } 402 403 404 static void wps_er_http_subscribe_cb(void *ctx, struct http_client *c, 405 enum http_client_event event) 406 { 407 struct wps_er_ap *ap = ctx; 408 409 switch (event) { 410 case HTTP_CLIENT_OK: 411 wpa_printf(MSG_DEBUG, "WPS ER: Subscribed to events"); 412 ap->subscribed = 1; 413 wps_er_get_sid(ap, http_client_get_hdr_line(c, "SID")); 414 wps_er_ap_use_cached_settings(ap->er, ap); 415 wps_er_ap_event(ap->er->wps, ap, WPS_EV_ER_AP_ADD); 416 break; 417 case HTTP_CLIENT_FAILED: 418 case HTTP_CLIENT_INVALID_REPLY: 419 case HTTP_CLIENT_TIMEOUT: 420 wpa_printf(MSG_DEBUG, "WPS ER: Failed to subscribe to events"); 421 break; 422 } 423 http_client_free(ap->http); 424 ap->http = NULL; 425 } 426 427 428 static void wps_er_subscribe(struct wps_er_ap *ap) 429 { 430 struct wpabuf *req; 431 struct sockaddr_in dst; 432 char *url, *path; 433 434 if (ap->event_sub_url == NULL) { 435 wpa_printf(MSG_DEBUG, "WPS ER: No eventSubURL - cannot " 436 "subscribe"); 437 return; 438 } 439 if (ap->http) { 440 wpa_printf(MSG_DEBUG, "WPS ER: Pending HTTP request - cannot " 441 "send subscribe request"); 442 return; 443 } 444 445 url = http_client_url_parse(ap->event_sub_url, &dst, &path); 446 if (url == NULL) { 447 wpa_printf(MSG_DEBUG, "WPS ER: Failed to parse eventSubURL"); 448 return; 449 } 450 451 req = wpabuf_alloc(os_strlen(ap->event_sub_url) + 1000); 452 if (req == NULL) { 453 os_free(url); 454 return; 455 } 456 wpabuf_printf(req, 457 "SUBSCRIBE %s HTTP/1.1\r\n" 458 "HOST: %s:%d\r\n" 459 "CALLBACK: <http://%s:%d/event/%u/%u>\r\n" 460 "NT: upnp:event\r\n" 461 "TIMEOUT: Second-%d\r\n" 462 "\r\n", 463 path, inet_ntoa(dst.sin_addr), ntohs(dst.sin_port), 464 ap->er->ip_addr_text, ap->er->http_port, 465 ap->er->event_id, ap->id, 1800); 466 os_free(url); 467 wpa_hexdump_ascii(MSG_MSGDUMP, "WPS ER: Subscription request", 468 wpabuf_head(req), wpabuf_len(req)); 469 470 ap->http = http_client_addr(&dst, req, 1000, wps_er_http_subscribe_cb, 471 ap); 472 if (ap->http == NULL) 473 wpabuf_free(req); 474 } 475 476 477 static void wps_er_ap_get_m1(struct wps_er_ap *ap, struct wpabuf *m1) 478 { 479 struct wps_parse_attr attr; 480 481 if (wps_parse_msg(m1, &attr) < 0) { 482 wpa_printf(MSG_DEBUG, "WPS ER: Failed to parse M1"); 483 return; 484 } 485 if (attr.primary_dev_type) 486 os_memcpy(ap->pri_dev_type, attr.primary_dev_type, 8); 487 if (attr.wps_state) 488 ap->wps_state = *attr.wps_state; 489 if (attr.mac_addr) 490 os_memcpy(ap->mac_addr, attr.mac_addr, ETH_ALEN); 491 492 wps_er_subscribe(ap); 493 } 494 495 496 static void wps_er_get_device_info(struct wps_er_ap *ap) 497 { 498 wps_er_send_get_device_info(ap, wps_er_ap_get_m1); 499 } 500 501 502 static const char * wps_er_find_wfadevice(const char *data) 503 { 504 const char *tag, *tagname, *end; 505 char *val; 506 int found = 0; 507 508 while (!found) { 509 /* Find next <device> */ 510 for (;;) { 511 if (xml_next_tag(data, &tag, &tagname, &end)) 512 return NULL; 513 data = end; 514 if (!os_strncasecmp(tagname, "device", 6) && 515 *tag != '/' && 516 (tagname[6] == '>' || !isgraph(tagname[6]))) { 517 break; 518 } 519 } 520 521 /* Check whether deviceType is WFADevice */ 522 val = xml_get_first_item(data, "deviceType"); 523 if (val == NULL) 524 return NULL; 525 wpa_printf(MSG_DEBUG, "WPS ER: Found deviceType '%s'", val); 526 found = os_strcasecmp(val, "urn:schemas-wifialliance-org:" 527 "device:WFADevice:1") == 0; 528 os_free(val); 529 } 530 531 return data; 532 } 533 534 535 static void wps_er_parse_device_description(struct wps_er_ap *ap, 536 struct wpabuf *reply) 537 { 538 /* Note: reply includes null termination after the buffer data */ 539 const char *tmp, *data = wpabuf_head(reply); 540 char *pos; 541 542 wpa_hexdump_ascii(MSG_MSGDUMP, "WPS ER: Device info", 543 wpabuf_head(reply), wpabuf_len(reply)); 544 545 /* 546 * The root device description may include multiple devices, so first 547 * find the beginning of the WFADevice description to allow the 548 * simplistic parser to pick the correct entries. 549 */ 550 tmp = wps_er_find_wfadevice(data); 551 if (tmp == NULL) { 552 wpa_printf(MSG_DEBUG, "WPS ER: WFADevice:1 device not found - " 553 "trying to parse invalid data"); 554 } else 555 data = tmp; 556 557 ap->friendly_name = xml_get_first_item(data, "friendlyName"); 558 wpa_printf(MSG_DEBUG, "WPS ER: friendlyName='%s'", ap->friendly_name); 559 560 ap->manufacturer = xml_get_first_item(data, "manufacturer"); 561 wpa_printf(MSG_DEBUG, "WPS ER: manufacturer='%s'", ap->manufacturer); 562 563 ap->manufacturer_url = xml_get_first_item(data, "manufacturerURL"); 564 wpa_printf(MSG_DEBUG, "WPS ER: manufacturerURL='%s'", 565 ap->manufacturer_url); 566 567 ap->model_description = xml_get_first_item(data, "modelDescription"); 568 wpa_printf(MSG_DEBUG, "WPS ER: modelDescription='%s'", 569 ap->model_description); 570 571 ap->model_name = xml_get_first_item(data, "modelName"); 572 wpa_printf(MSG_DEBUG, "WPS ER: modelName='%s'", ap->model_name); 573 574 ap->model_number = xml_get_first_item(data, "modelNumber"); 575 wpa_printf(MSG_DEBUG, "WPS ER: modelNumber='%s'", ap->model_number); 576 577 ap->model_url = xml_get_first_item(data, "modelURL"); 578 wpa_printf(MSG_DEBUG, "WPS ER: modelURL='%s'", ap->model_url); 579 580 ap->serial_number = xml_get_first_item(data, "serialNumber"); 581 wpa_printf(MSG_DEBUG, "WPS ER: serialNumber='%s'", ap->serial_number); 582 583 ap->udn = xml_get_first_item(data, "UDN"); 584 wpa_printf(MSG_DEBUG, "WPS ER: UDN='%s'", ap->udn); 585 pos = os_strstr(ap->udn, "uuid:"); 586 if (pos) { 587 pos += 5; 588 if (uuid_str2bin(pos, ap->uuid) < 0) 589 wpa_printf(MSG_DEBUG, "WPS ER: Invalid UUID in UDN"); 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 unsigned 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, (char *) 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 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 1351 wpa_printf(MSG_DEBUG, "WPS ER: Finishing deinit"); 1352 1353 deinit_done_cb = er->deinit_done_cb; 1354 deinit_done_ctx = er->deinit_done_ctx; 1355 os_free(er->ip_addr_text); 1356 os_free(er); 1357 1358 if (deinit_done_cb) 1359 deinit_done_cb(deinit_done_ctx); 1360 } 1361 1362 1363 void wps_er_deinit(struct wps_er *er, void (*cb)(void *ctx), void *ctx) 1364 { 1365 if (er == NULL) 1366 return; 1367 http_server_deinit(er->http_srv); 1368 wps_er_ap_remove_all(er); 1369 wps_er_ssdp_deinit(er); 1370 eloop_register_timeout(dl_list_empty(&er->ap_unsubscribing) ? 0 : 5, 0, 1371 wps_er_deinit_finish, er, NULL); 1372 wpa_printf(MSG_DEBUG, "WPS ER: Finish deinit from timeout"); 1373 er->deinitializing = 1; 1374 er->deinit_done_cb = cb; 1375 er->deinit_done_ctx = ctx; 1376 } 1377 1378 1379 static void wps_er_http_set_sel_reg_cb(void *ctx, struct http_client *c, 1380 enum http_client_event event) 1381 { 1382 struct wps_er_ap *ap = ctx; 1383 union wps_event_data data; 1384 1385 os_memset(&data, 0, sizeof(data)); 1386 1387 switch (event) { 1388 case HTTP_CLIENT_OK: 1389 wpa_printf(MSG_DEBUG, "WPS ER: SetSelectedRegistrar OK"); 1390 data.set_sel_reg.state = WPS_ER_SET_SEL_REG_DONE; 1391 data.set_sel_reg.uuid = ap->uuid; 1392 break; 1393 case HTTP_CLIENT_FAILED: 1394 case HTTP_CLIENT_INVALID_REPLY: 1395 case HTTP_CLIENT_TIMEOUT: 1396 wpa_printf(MSG_DEBUG, "WPS ER: SetSelectedRegistrar failed"); 1397 data.set_sel_reg.state = WPS_ER_SET_SEL_REG_FAILED; 1398 data.set_sel_reg.uuid = ap->uuid; 1399 break; 1400 } 1401 http_client_free(ap->http); 1402 ap->http = NULL; 1403 1404 if (data.set_sel_reg.uuid) 1405 ap->er->wps->event_cb(ap->er->wps->cb_ctx, 1406 WPS_EV_ER_SET_SELECTED_REGISTRAR, &data); 1407 } 1408 1409 1410 static void wps_er_send_set_sel_reg(struct wps_er_ap *ap, struct wpabuf *msg) 1411 { 1412 struct wpabuf *buf; 1413 char *len_ptr, *body_ptr; 1414 struct sockaddr_in dst; 1415 char *url, *path; 1416 1417 if (ap->control_url == NULL) { 1418 wpa_printf(MSG_DEBUG, "WPS ER: No controlURL for AP"); 1419 return; 1420 } 1421 1422 if (ap->http) { 1423 wpa_printf(MSG_DEBUG, "WPS ER: Pending HTTP request for AP - " 1424 "ignore new request"); 1425 return; 1426 } 1427 1428 if (ap->wps) { 1429 wpa_printf(MSG_DEBUG, "WPS ER: Pending WPS operation for AP - " 1430 "skip SetSelectedRegistrar"); 1431 return; 1432 } 1433 1434 url = http_client_url_parse(ap->control_url, &dst, &path); 1435 if (url == NULL) { 1436 wpa_printf(MSG_DEBUG, "WPS ER: Failed to parse controlURL"); 1437 return; 1438 } 1439 1440 buf = wps_er_soap_hdr(msg, "SetSelectedRegistrar", "NewMessage", path, 1441 &dst, &len_ptr, &body_ptr); 1442 os_free(url); 1443 if (buf == NULL) 1444 return; 1445 1446 wps_er_soap_end(buf, "SetSelectedRegistrar", len_ptr, body_ptr); 1447 1448 ap->http = http_client_addr(&dst, buf, 1000, 1449 wps_er_http_set_sel_reg_cb, ap); 1450 if (ap->http == NULL) 1451 wpabuf_free(buf); 1452 } 1453 1454 1455 static int wps_er_build_selected_registrar(struct wpabuf *msg, int sel_reg) 1456 { 1457 wpabuf_put_be16(msg, ATTR_SELECTED_REGISTRAR); 1458 wpabuf_put_be16(msg, 1); 1459 wpabuf_put_u8(msg, !!sel_reg); 1460 return 0; 1461 } 1462 1463 1464 static int wps_er_build_dev_password_id(struct wpabuf *msg, u16 dev_passwd_id) 1465 { 1466 wpabuf_put_be16(msg, ATTR_DEV_PASSWORD_ID); 1467 wpabuf_put_be16(msg, 2); 1468 wpabuf_put_be16(msg, dev_passwd_id); 1469 return 0; 1470 } 1471 1472 1473 static int wps_er_build_sel_reg_config_methods(struct wpabuf *msg, 1474 u16 sel_reg_config_methods) 1475 { 1476 wpabuf_put_be16(msg, ATTR_SELECTED_REGISTRAR_CONFIG_METHODS); 1477 wpabuf_put_be16(msg, 2); 1478 wpabuf_put_be16(msg, sel_reg_config_methods); 1479 return 0; 1480 } 1481 1482 1483 static int wps_er_build_uuid_r(struct wpabuf *msg, const u8 *uuid_r) 1484 { 1485 #ifdef CONFIG_WPS2 1486 wpabuf_put_be16(msg, ATTR_UUID_R); 1487 wpabuf_put_be16(msg, WPS_UUID_LEN); 1488 wpabuf_put_data(msg, uuid_r, WPS_UUID_LEN); 1489 #endif /* CONFIG_WPS2 */ 1490 return 0; 1491 } 1492 1493 1494 void wps_er_set_sel_reg(struct wps_er *er, int sel_reg, u16 dev_passwd_id, 1495 u16 sel_reg_config_methods) 1496 { 1497 struct wpabuf *msg; 1498 struct wps_er_ap *ap; 1499 struct wps_registrar *reg = er->wps->registrar; 1500 const u8 *auth_macs; 1501 #ifdef CONFIG_WPS2 1502 u8 bcast[ETH_ALEN]; 1503 #endif /* CONFIG_WPS2 */ 1504 size_t count; 1505 union wps_event_data data; 1506 1507 if (er->skip_set_sel_reg) { 1508 wpa_printf(MSG_DEBUG, "WPS ER: Skip SetSelectedRegistrar"); 1509 return; 1510 } 1511 1512 msg = wpabuf_alloc(500); 1513 if (msg == NULL) 1514 return; 1515 1516 auth_macs = wps_authorized_macs(reg, &count); 1517 #ifdef CONFIG_WPS2 1518 if (count == 0) { 1519 os_memset(bcast, 0xff, ETH_ALEN); 1520 auth_macs = bcast; 1521 count = 1; 1522 } 1523 #endif /* CONFIG_WPS2 */ 1524 1525 if (wps_build_version(msg) || 1526 wps_er_build_selected_registrar(msg, sel_reg) || 1527 wps_er_build_dev_password_id(msg, dev_passwd_id) || 1528 wps_er_build_sel_reg_config_methods(msg, sel_reg_config_methods) || 1529 wps_build_wfa_ext(msg, 0, auth_macs, count) || 1530 wps_er_build_uuid_r(msg, er->wps->uuid)) { 1531 wpabuf_free(msg); 1532 return; 1533 } 1534 1535 os_memset(&data, 0, sizeof(data)); 1536 data.set_sel_reg.sel_reg = sel_reg; 1537 data.set_sel_reg.dev_passwd_id = dev_passwd_id; 1538 data.set_sel_reg.sel_reg_config_methods = sel_reg_config_methods; 1539 data.set_sel_reg.state = WPS_ER_SET_SEL_REG_START; 1540 1541 dl_list_for_each(ap, &er->ap, struct wps_er_ap, list) { 1542 if (er->set_sel_reg_uuid_filter && 1543 os_memcmp(ap->uuid, er->set_sel_reg_uuid_filter, 1544 WPS_UUID_LEN) != 0) 1545 continue; 1546 data.set_sel_reg.uuid = ap->uuid; 1547 er->wps->event_cb(er->wps->cb_ctx, 1548 WPS_EV_ER_SET_SELECTED_REGISTRAR, &data); 1549 wps_er_send_set_sel_reg(ap, msg); 1550 } 1551 1552 wpabuf_free(msg); 1553 } 1554 1555 1556 int wps_er_pbc(struct wps_er *er, const u8 *uuid, const u8 *addr) 1557 { 1558 int res; 1559 struct wps_er_ap *ap; 1560 1561 if (er == NULL || er->wps == NULL) 1562 return -1; 1563 1564 if (wps_registrar_pbc_overlap(er->wps->registrar, NULL, NULL)) { 1565 wpa_printf(MSG_DEBUG, "WPS ER: PBC overlap - do not start PBC " 1566 "mode"); 1567 return -2; 1568 } 1569 1570 if (uuid) 1571 ap = wps_er_ap_get(er, NULL, uuid, NULL); 1572 else 1573 ap = NULL; 1574 if (ap == NULL) { 1575 struct wps_er_sta *sta = NULL; 1576 dl_list_for_each(ap, &er->ap, struct wps_er_ap, list) { 1577 sta = wps_er_sta_get(ap, addr, uuid); 1578 if (sta) { 1579 uuid = ap->uuid; 1580 break; 1581 } 1582 } 1583 if (sta == NULL) 1584 return -3; /* Unknown UUID */ 1585 } 1586 1587 if (ap->ap_settings == NULL) { 1588 wpa_printf(MSG_DEBUG, "WPS ER: AP settings not known"); 1589 return -4; 1590 } 1591 1592 er->set_sel_reg_uuid_filter = uuid; 1593 res = wps_registrar_button_pushed(er->wps->registrar, NULL); 1594 er->set_sel_reg_uuid_filter = NULL; 1595 if (res) 1596 return -1; 1597 1598 return 0; 1599 } 1600 1601 1602 static void wps_er_ap_settings_cb(void *ctx, const struct wps_credential *cred) 1603 { 1604 struct wps_er_ap *ap = ctx; 1605 union wps_event_data data; 1606 1607 wpa_printf(MSG_DEBUG, "WPS ER: AP Settings received"); 1608 os_free(ap->ap_settings); 1609 ap->ap_settings = os_malloc(sizeof(*cred)); 1610 if (ap->ap_settings) { 1611 os_memcpy(ap->ap_settings, cred, sizeof(*cred)); 1612 ap->ap_settings->cred_attr = NULL; 1613 } 1614 1615 os_memset(&data, 0, sizeof(data)); 1616 data.ap_settings.uuid = ap->uuid; 1617 data.ap_settings.cred = cred; 1618 ap->er->wps->event_cb(ap->er->wps->cb_ctx, WPS_EV_ER_AP_SETTINGS, 1619 &data); 1620 } 1621 1622 1623 const u8 * wps_er_get_sta_uuid(struct wps_er *er, const u8 *addr) 1624 { 1625 struct wps_er_ap *ap; 1626 dl_list_for_each(ap, &er->ap, struct wps_er_ap, list) { 1627 struct wps_er_sta *sta; 1628 sta = wps_er_sta_get(ap, addr, NULL); 1629 if (sta) 1630 return sta->uuid; 1631 } 1632 return NULL; 1633 } 1634 1635 1636 static void wps_er_http_put_message_cb(void *ctx, struct http_client *c, 1637 enum http_client_event event) 1638 { 1639 struct wps_er_ap *ap = ctx; 1640 struct wpabuf *reply; 1641 char *msg = NULL; 1642 1643 switch (event) { 1644 case HTTP_CLIENT_OK: 1645 wpa_printf(MSG_DEBUG, "WPS ER: PutMessage OK"); 1646 reply = http_client_get_body(c); 1647 if (reply == NULL) 1648 break; 1649 msg = os_zalloc(wpabuf_len(reply) + 1); 1650 if (msg == NULL) 1651 break; 1652 os_memcpy(msg, wpabuf_head(reply), wpabuf_len(reply)); 1653 break; 1654 case HTTP_CLIENT_FAILED: 1655 case HTTP_CLIENT_INVALID_REPLY: 1656 case HTTP_CLIENT_TIMEOUT: 1657 wpa_printf(MSG_DEBUG, "WPS ER: PutMessage failed"); 1658 if (ap->wps) { 1659 wps_deinit(ap->wps); 1660 ap->wps = NULL; 1661 } 1662 break; 1663 } 1664 http_client_free(ap->http); 1665 ap->http = NULL; 1666 1667 if (msg) { 1668 struct wpabuf *buf; 1669 enum http_reply_code ret; 1670 buf = xml_get_base64_item(msg, "NewOutMessage", &ret); 1671 os_free(msg); 1672 if (buf == NULL) { 1673 wpa_printf(MSG_DEBUG, "WPS ER: Could not extract " 1674 "NewOutMessage from PutMessage response"); 1675 wps_deinit(ap->wps); 1676 ap->wps = NULL; 1677 return; 1678 } 1679 wps_er_ap_process(ap, buf); 1680 wpabuf_free(buf); 1681 } 1682 } 1683 1684 1685 static void wps_er_ap_put_message(struct wps_er_ap *ap, 1686 const struct wpabuf *msg) 1687 { 1688 struct wpabuf *buf; 1689 char *len_ptr, *body_ptr; 1690 struct sockaddr_in dst; 1691 char *url, *path; 1692 1693 if (ap->http) { 1694 wpa_printf(MSG_DEBUG, "WPS ER: Pending HTTP operation ongoing " 1695 "with the AP - cannot continue learn"); 1696 return; 1697 } 1698 1699 if (ap->control_url == NULL) { 1700 wpa_printf(MSG_DEBUG, "WPS ER: No controlURL for AP"); 1701 return; 1702 } 1703 1704 url = http_client_url_parse(ap->control_url, &dst, &path); 1705 if (url == NULL) { 1706 wpa_printf(MSG_DEBUG, "WPS ER: Failed to parse controlURL"); 1707 return; 1708 } 1709 1710 buf = wps_er_soap_hdr(msg, "PutMessage", "NewInMessage", path, &dst, 1711 &len_ptr, &body_ptr); 1712 os_free(url); 1713 if (buf == NULL) 1714 return; 1715 1716 wps_er_soap_end(buf, "PutMessage", len_ptr, body_ptr); 1717 1718 ap->http = http_client_addr(&dst, buf, 10000, 1719 wps_er_http_put_message_cb, ap); 1720 if (ap->http == NULL) 1721 wpabuf_free(buf); 1722 } 1723 1724 1725 static void wps_er_ap_process(struct wps_er_ap *ap, struct wpabuf *msg) 1726 { 1727 enum wps_process_res res; 1728 struct wps_parse_attr attr; 1729 enum wsc_op_code op_code; 1730 1731 op_code = WSC_MSG; 1732 if (wps_parse_msg(msg, &attr) == 0 && attr.msg_type) { 1733 switch (*attr.msg_type) { 1734 case WPS_WSC_ACK: 1735 op_code = WSC_ACK; 1736 break; 1737 case WPS_WSC_NACK: 1738 op_code = WSC_NACK; 1739 break; 1740 case WPS_WSC_DONE: 1741 op_code = WSC_Done; 1742 break; 1743 } 1744 } 1745 1746 res = wps_process_msg(ap->wps, op_code, msg); 1747 if (res == WPS_CONTINUE) { 1748 struct wpabuf *next = wps_get_msg(ap->wps, &op_code); 1749 if (next) { 1750 wps_er_ap_put_message(ap, next); 1751 wpabuf_free(next); 1752 } else { 1753 wpa_printf(MSG_DEBUG, "WPS ER: Failed to build " 1754 "message"); 1755 wps_deinit(ap->wps); 1756 ap->wps = NULL; 1757 } 1758 } else if (res == WPS_DONE) { 1759 wpa_printf(MSG_DEBUG, "WPS ER: Protocol run done"); 1760 wps_deinit(ap->wps); 1761 ap->wps = NULL; 1762 } else { 1763 wpa_printf(MSG_DEBUG, "WPS ER: Failed to process message from " 1764 "AP (res=%d)", res); 1765 wps_deinit(ap->wps); 1766 ap->wps = NULL; 1767 } 1768 } 1769 1770 1771 static void wps_er_ap_learn_m1(struct wps_er_ap *ap, struct wpabuf *m1) 1772 { 1773 struct wps_config cfg; 1774 1775 if (ap->wps) { 1776 wpa_printf(MSG_DEBUG, "WPS ER: Protocol run already in " 1777 "progress with this AP"); 1778 return; 1779 } 1780 1781 os_memset(&cfg, 0, sizeof(cfg)); 1782 cfg.wps = ap->er->wps; 1783 cfg.registrar = 1; 1784 ap->wps = wps_init(&cfg); 1785 if (ap->wps == NULL) 1786 return; 1787 ap->wps->ap_settings_cb = wps_er_ap_settings_cb; 1788 ap->wps->ap_settings_cb_ctx = ap; 1789 1790 wps_er_ap_process(ap, m1); 1791 } 1792 1793 1794 static void wps_er_ap_learn(struct wps_er_ap *ap, const char *dev_info) 1795 { 1796 struct wpabuf *info; 1797 enum http_reply_code ret; 1798 1799 wpa_printf(MSG_DEBUG, "WPS ER: Received GetDeviceInfo response (M1) " 1800 "from the AP"); 1801 info = xml_get_base64_item(dev_info, "NewDeviceInfo", &ret); 1802 if (info == NULL) { 1803 wpa_printf(MSG_DEBUG, "WPS ER: Could not extract " 1804 "NewDeviceInfo from GetDeviceInfo response"); 1805 return; 1806 } 1807 1808 ap->m1_handler(ap, info); 1809 wpabuf_free(info); 1810 } 1811 1812 1813 static void wps_er_http_get_dev_info_cb(void *ctx, struct http_client *c, 1814 enum http_client_event event) 1815 { 1816 struct wps_er_ap *ap = ctx; 1817 struct wpabuf *reply; 1818 char *dev_info = NULL; 1819 1820 switch (event) { 1821 case HTTP_CLIENT_OK: 1822 wpa_printf(MSG_DEBUG, "WPS ER: GetDeviceInfo OK"); 1823 reply = http_client_get_body(c); 1824 if (reply == NULL) 1825 break; 1826 dev_info = os_zalloc(wpabuf_len(reply) + 1); 1827 if (dev_info == NULL) 1828 break; 1829 os_memcpy(dev_info, wpabuf_head(reply), wpabuf_len(reply)); 1830 break; 1831 case HTTP_CLIENT_FAILED: 1832 case HTTP_CLIENT_INVALID_REPLY: 1833 case HTTP_CLIENT_TIMEOUT: 1834 wpa_printf(MSG_DEBUG, "WPS ER: GetDeviceInfo failed"); 1835 break; 1836 } 1837 http_client_free(ap->http); 1838 ap->http = NULL; 1839 1840 if (dev_info) { 1841 wps_er_ap_learn(ap, dev_info); 1842 os_free(dev_info); 1843 } 1844 } 1845 1846 1847 static int wps_er_send_get_device_info(struct wps_er_ap *ap, 1848 void (*m1_handler)(struct wps_er_ap *ap, 1849 struct wpabuf *m1)) 1850 { 1851 struct wpabuf *buf; 1852 char *len_ptr, *body_ptr; 1853 struct sockaddr_in dst; 1854 char *url, *path; 1855 1856 if (ap->http) { 1857 wpa_printf(MSG_DEBUG, "WPS ER: Pending HTTP operation ongoing " 1858 "with the AP - cannot get device info"); 1859 return -1; 1860 } 1861 1862 if (ap->control_url == NULL) { 1863 wpa_printf(MSG_DEBUG, "WPS ER: No controlURL for AP"); 1864 return -1; 1865 } 1866 1867 url = http_client_url_parse(ap->control_url, &dst, &path); 1868 if (url == NULL) { 1869 wpa_printf(MSG_DEBUG, "WPS ER: Failed to parse controlURL"); 1870 return -1; 1871 } 1872 1873 buf = wps_er_soap_hdr(NULL, "GetDeviceInfo", NULL, path, &dst, 1874 &len_ptr, &body_ptr); 1875 os_free(url); 1876 if (buf == NULL) 1877 return -1; 1878 1879 wps_er_soap_end(buf, "GetDeviceInfo", len_ptr, body_ptr); 1880 1881 ap->http = http_client_addr(&dst, buf, 10000, 1882 wps_er_http_get_dev_info_cb, ap); 1883 if (ap->http == NULL) { 1884 wpabuf_free(buf); 1885 return -1; 1886 } 1887 1888 ap->m1_handler = m1_handler; 1889 1890 return 0; 1891 } 1892 1893 1894 int wps_er_learn(struct wps_er *er, const u8 *uuid, const u8 *addr, 1895 const u8 *pin, size_t pin_len) 1896 { 1897 struct wps_er_ap *ap; 1898 1899 if (er == NULL) 1900 return -1; 1901 1902 ap = wps_er_ap_get(er, NULL, uuid, addr); 1903 if (ap == NULL) { 1904 wpa_printf(MSG_DEBUG, "WPS ER: AP not found for learn " 1905 "request"); 1906 return -1; 1907 } 1908 if (uuid == NULL) 1909 uuid = ap->uuid; 1910 if (ap->wps) { 1911 wpa_printf(MSG_DEBUG, "WPS ER: Pending operation ongoing " 1912 "with the AP - cannot start learn"); 1913 return -1; 1914 } 1915 1916 if (wps_er_send_get_device_info(ap, wps_er_ap_learn_m1) < 0) 1917 return -1; 1918 1919 er->skip_set_sel_reg = 1; 1920 wps_registrar_add_pin(er->wps->registrar, NULL, uuid, pin, pin_len, 0); 1921 er->skip_set_sel_reg = 0; 1922 1923 return 0; 1924 } 1925 1926 1927 int wps_er_set_config(struct wps_er *er, const u8 *uuid, const u8 *addr, 1928 const struct wps_credential *cred) 1929 { 1930 struct wps_er_ap *ap; 1931 1932 if (er == NULL) 1933 return -1; 1934 1935 ap = wps_er_ap_get(er, NULL, uuid, addr); 1936 if (ap == NULL) { 1937 wpa_printf(MSG_DEBUG, "WPS ER: AP not found for set config " 1938 "request"); 1939 return -1; 1940 } 1941 1942 os_free(ap->ap_settings); 1943 ap->ap_settings = os_malloc(sizeof(*cred)); 1944 if (ap->ap_settings == NULL) 1945 return -1; 1946 os_memcpy(ap->ap_settings, cred, sizeof(*cred)); 1947 ap->ap_settings->cred_attr = NULL; 1948 wpa_printf(MSG_DEBUG, "WPS ER: Updated local AP settings based set " 1949 "config request"); 1950 1951 return 0; 1952 } 1953 1954 1955 static void wps_er_ap_config_m1(struct wps_er_ap *ap, struct wpabuf *m1) 1956 { 1957 struct wps_config cfg; 1958 1959 if (ap->wps) { 1960 wpa_printf(MSG_DEBUG, "WPS ER: Protocol run already in " 1961 "progress with this AP"); 1962 return; 1963 } 1964 1965 os_memset(&cfg, 0, sizeof(cfg)); 1966 cfg.wps = ap->er->wps; 1967 cfg.registrar = 1; 1968 cfg.new_ap_settings = ap->ap_settings; 1969 ap->wps = wps_init(&cfg); 1970 if (ap->wps == NULL) 1971 return; 1972 ap->wps->ap_settings_cb = NULL; 1973 ap->wps->ap_settings_cb_ctx = NULL; 1974 1975 wps_er_ap_process(ap, m1); 1976 } 1977 1978 1979 int wps_er_config(struct wps_er *er, const u8 *uuid, const u8 *addr, 1980 const u8 *pin, size_t pin_len, 1981 const struct wps_credential *cred) 1982 { 1983 struct wps_er_ap *ap; 1984 1985 if (er == NULL) 1986 return -1; 1987 1988 ap = wps_er_ap_get(er, NULL, uuid, addr); 1989 if (ap == NULL) { 1990 wpa_printf(MSG_DEBUG, "WPS ER: AP not found for config " 1991 "request"); 1992 return -1; 1993 } 1994 if (uuid == NULL) 1995 uuid = ap->uuid; 1996 if (ap->wps) { 1997 wpa_printf(MSG_DEBUG, "WPS ER: Pending operation ongoing " 1998 "with the AP - cannot start config"); 1999 return -1; 2000 } 2001 2002 os_free(ap->ap_settings); 2003 ap->ap_settings = os_malloc(sizeof(*cred)); 2004 if (ap->ap_settings == NULL) 2005 return -1; 2006 os_memcpy(ap->ap_settings, cred, sizeof(*cred)); 2007 ap->ap_settings->cred_attr = NULL; 2008 2009 if (wps_er_send_get_device_info(ap, wps_er_ap_config_m1) < 0) 2010 return -1; 2011 2012 er->skip_set_sel_reg = 1; 2013 wps_registrar_add_pin(er->wps->registrar, NULL, uuid, pin, pin_len, 0); 2014 er->skip_set_sel_reg = 0; 2015 2016 return 0; 2017 } 2018 2019 2020 #ifdef CONFIG_WPS_NFC 2021 2022 struct wpabuf * wps_er_config_token_from_cred(struct wps_context *wps, 2023 struct wps_credential *cred) 2024 { 2025 struct wpabuf *ret; 2026 struct wps_data data; 2027 2028 ret = wpabuf_alloc(500); 2029 if (ret == NULL) 2030 return NULL; 2031 2032 os_memset(&data, 0, sizeof(data)); 2033 data.wps = wps; 2034 data.use_cred = cred; 2035 if (wps_build_version(ret) || 2036 wps_build_cred(&data, ret) || 2037 wps_build_wfa_ext(ret, 0, NULL, 0)) { 2038 wpabuf_free(ret); 2039 return NULL; 2040 } 2041 2042 return ret; 2043 } 2044 2045 2046 struct wpabuf * wps_er_nfc_config_token(struct wps_er *er, const u8 *uuid, 2047 const u8 *addr) 2048 { 2049 struct wps_er_ap *ap; 2050 2051 if (er == NULL) 2052 return NULL; 2053 2054 ap = wps_er_ap_get(er, NULL, uuid, addr); 2055 if (ap == NULL) 2056 return NULL; 2057 if (ap->ap_settings == NULL) { 2058 wpa_printf(MSG_DEBUG, "WPS ER: No settings known for the " 2059 "selected AP"); 2060 return NULL; 2061 } 2062 2063 return wps_er_config_token_from_cred(er->wps, ap->ap_settings); 2064 } 2065 2066 #endif /* CONFIG_WPS_NFC */ 2067