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