1 /* 2 * Wi-Fi Protected Setup - External Registrar 3 * Copyright (c) 2009, Jouni Malinen <j@w1.fi> 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License version 2 as 7 * published by the Free Software Foundation. 8 * 9 * Alternatively, this software may be distributed under the terms of BSD 10 * license. 11 * 12 * See README and COPYING for more details. 13 */ 14 15 #include "includes.h" 16 17 #include "common.h" 18 #include "base64.h" 19 #include "uuid.h" 20 #include "eloop.h" 21 #include "httpread.h" 22 #include "http_client.h" 23 #include "http_server.h" 24 #include "upnp_xml.h" 25 #include "wps_i.h" 26 #include "wps_upnp.h" 27 #include "wps_upnp_i.h" 28 #include "wps_er.h" 29 30 31 static void wps_er_deinit_finish(void *eloop_data, void *user_ctx); 32 static void wps_er_ap_timeout(void *eloop_data, void *user_ctx); 33 static void wps_er_sta_timeout(void *eloop_data, void *user_ctx); 34 static void wps_er_ap_process(struct wps_er_ap *ap, struct wpabuf *msg); 35 static int wps_er_send_get_device_info(struct wps_er_ap *ap, 36 void (*m1_handler)(struct wps_er_ap *ap, 37 struct wpabuf *m1)); 38 39 40 static void wps_er_sta_event(struct wps_context *wps, struct wps_er_sta *sta, 41 enum wps_event event) 42 { 43 union wps_event_data data; 44 struct wps_event_er_enrollee *ev = &data.enrollee; 45 46 if (wps->event_cb == NULL) 47 return; 48 49 os_memset(&data, 0, sizeof(data)); 50 ev->uuid = sta->uuid; 51 ev->mac_addr = sta->addr; 52 ev->m1_received = sta->m1_received; 53 ev->config_methods = sta->config_methods; 54 ev->dev_passwd_id = sta->dev_passwd_id; 55 ev->pri_dev_type = sta->pri_dev_type; 56 ev->dev_name = sta->dev_name; 57 ev->manufacturer = sta->manufacturer; 58 ev->model_name = sta->model_name; 59 ev->model_number = sta->model_number; 60 ev->serial_number = sta->serial_number; 61 wps->event_cb(wps->cb_ctx, event, &data); 62 } 63 64 65 static struct wps_er_sta * wps_er_sta_get(struct wps_er_ap *ap, const u8 *addr) 66 { 67 struct wps_er_sta *sta; 68 dl_list_for_each(sta, &ap->sta, struct wps_er_sta, list) { 69 if (os_memcmp(sta->addr, addr, ETH_ALEN) == 0) 70 return sta; 71 } 72 return NULL; 73 } 74 75 76 static void wps_er_sta_free(struct wps_er_sta *sta) 77 { 78 wps_er_sta_event(sta->ap->er->wps, sta, WPS_EV_ER_ENROLLEE_REMOVE); 79 if (sta->wps) 80 wps_deinit(sta->wps); 81 os_free(sta->manufacturer); 82 os_free(sta->model_name); 83 os_free(sta->model_number); 84 os_free(sta->serial_number); 85 os_free(sta->dev_name); 86 http_client_free(sta->http); 87 eloop_cancel_timeout(wps_er_sta_timeout, sta, NULL); 88 os_free(sta->cred); 89 os_free(sta); 90 } 91 92 93 static void wps_er_sta_remove_all(struct wps_er_ap *ap) 94 { 95 struct wps_er_sta *prev, *sta; 96 dl_list_for_each_safe(sta, prev, &ap->sta, struct wps_er_sta, list) 97 wps_er_sta_free(sta); 98 } 99 100 101 static struct wps_er_ap * wps_er_ap_get(struct wps_er *er, 102 struct in_addr *addr, const u8 *uuid) 103 { 104 struct wps_er_ap *ap; 105 dl_list_for_each(ap, &er->ap, struct wps_er_ap, list) { 106 if ((addr == NULL || ap->addr.s_addr == addr->s_addr) && 107 (uuid == NULL || 108 os_memcmp(uuid, ap->uuid, WPS_UUID_LEN) == 0)) 109 return ap; 110 } 111 return NULL; 112 } 113 114 115 static struct wps_er_ap * wps_er_ap_get_id(struct wps_er *er, unsigned int id) 116 { 117 struct wps_er_ap *ap; 118 dl_list_for_each(ap, &er->ap, struct wps_er_ap, list) { 119 if (ap->id == id) 120 return ap; 121 } 122 return NULL; 123 } 124 125 126 static void wps_er_ap_event(struct wps_context *wps, struct wps_er_ap *ap, 127 enum wps_event event) 128 { 129 union wps_event_data data; 130 struct wps_event_er_ap *evap = &data.ap; 131 132 if (wps->event_cb == NULL) 133 return; 134 135 os_memset(&data, 0, sizeof(data)); 136 evap->uuid = ap->uuid; 137 evap->friendly_name = ap->friendly_name; 138 evap->manufacturer = ap->manufacturer; 139 evap->manufacturer_url = ap->manufacturer_url; 140 evap->model_description = ap->model_description; 141 evap->model_name = ap->model_name; 142 evap->model_number = ap->model_number; 143 evap->model_url = ap->model_url; 144 evap->serial_number = ap->serial_number; 145 evap->upc = ap->upc; 146 evap->pri_dev_type = ap->pri_dev_type; 147 evap->wps_state = ap->wps_state; 148 evap->mac_addr = ap->mac_addr; 149 wps->event_cb(wps->cb_ctx, event, &data); 150 } 151 152 153 static void wps_er_ap_free(struct wps_er_ap *ap) 154 { 155 http_client_free(ap->http); 156 ap->http = NULL; 157 158 os_free(ap->location); 159 os_free(ap->friendly_name); 160 os_free(ap->manufacturer); 161 os_free(ap->manufacturer_url); 162 os_free(ap->model_description); 163 os_free(ap->model_name); 164 os_free(ap->model_number); 165 os_free(ap->model_url); 166 os_free(ap->serial_number); 167 os_free(ap->udn); 168 os_free(ap->upc); 169 170 os_free(ap->scpd_url); 171 os_free(ap->control_url); 172 os_free(ap->event_sub_url); 173 174 os_free(ap->ap_settings); 175 176 os_free(ap); 177 } 178 179 180 static void wps_er_ap_unsubscribed(struct wps_er *er, struct wps_er_ap *ap) 181 { 182 wpa_printf(MSG_DEBUG, "WPS ER: Unsubscribed from AP %s (%s)", 183 inet_ntoa(ap->addr), ap->location); 184 dl_list_del(&ap->list); 185 wps_er_ap_free(ap); 186 187 if (er->deinitializing && dl_list_empty(&er->ap_unsubscribing)) { 188 eloop_cancel_timeout(wps_er_deinit_finish, er, NULL); 189 wps_er_deinit_finish(er, NULL); 190 } 191 } 192 193 194 static void wps_er_http_unsubscribe_cb(void *ctx, struct http_client *c, 195 enum http_client_event event) 196 { 197 struct wps_er_ap *ap = ctx; 198 199 switch (event) { 200 case HTTP_CLIENT_OK: 201 wpa_printf(MSG_DEBUG, "WPS ER: Unsubscribed from events"); 202 ap->subscribed = 0; 203 break; 204 case HTTP_CLIENT_FAILED: 205 case HTTP_CLIENT_INVALID_REPLY: 206 case HTTP_CLIENT_TIMEOUT: 207 wpa_printf(MSG_DEBUG, "WPS ER: Failed to unsubscribe from " 208 "events"); 209 break; 210 } 211 http_client_free(ap->http); 212 ap->http = NULL; 213 214 /* 215 * Need to get rid of the AP entry regardless of whether we managed to 216 * unsubscribe cleanly or not. 217 */ 218 wps_er_ap_unsubscribed(ap->er, ap); 219 } 220 221 222 static void wps_er_ap_unsubscribe(struct wps_er *er, struct wps_er_ap *ap) 223 { 224 struct wpabuf *req; 225 struct sockaddr_in dst; 226 char *url, *path; 227 char sid[100]; 228 229 if (ap->event_sub_url == NULL) { 230 wpa_printf(MSG_DEBUG, "WPS ER: No eventSubURL - cannot " 231 "subscribe"); 232 goto fail; 233 } 234 if (ap->http) { 235 wpa_printf(MSG_DEBUG, "WPS ER: Pending HTTP request - cannot " 236 "send subscribe request"); 237 goto fail; 238 } 239 240 url = http_client_url_parse(ap->event_sub_url, &dst, &path); 241 if (url == NULL) { 242 wpa_printf(MSG_DEBUG, "WPS ER: Failed to parse eventSubURL"); 243 goto fail; 244 } 245 246 req = wpabuf_alloc(os_strlen(ap->event_sub_url) + 1000); 247 if (req == NULL) { 248 os_free(url); 249 goto fail; 250 } 251 uuid_bin2str(ap->sid, sid, sizeof(sid)); 252 wpabuf_printf(req, 253 "UNSUBSCRIBE %s HTTP/1.1\r\n" 254 "HOST: %s:%d\r\n" 255 "SID: uuid:%s\r\n" 256 "\r\n", 257 path, inet_ntoa(dst.sin_addr), ntohs(dst.sin_port), sid); 258 os_free(url); 259 wpa_hexdump_ascii(MSG_MSGDUMP, "WPS ER: Unsubscription request", 260 wpabuf_head(req), wpabuf_len(req)); 261 262 ap->http = http_client_addr(&dst, req, 1000, 263 wps_er_http_unsubscribe_cb, ap); 264 if (ap->http == NULL) { 265 wpabuf_free(req); 266 goto fail; 267 } 268 return; 269 270 fail: 271 /* 272 * Need to get rid of the AP entry even when we fail to unsubscribe 273 * cleanly. 274 */ 275 wps_er_ap_unsubscribed(ap->er, ap); 276 } 277 278 static void wps_er_ap_remove_entry(struct wps_er *er, struct wps_er_ap *ap) 279 { 280 wpa_printf(MSG_DEBUG, "WPS ER: Removing AP entry for %s (%s)", 281 inet_ntoa(ap->addr), ap->location); 282 eloop_cancel_timeout(wps_er_ap_timeout, er, ap); 283 wps_er_sta_remove_all(ap); 284 wps_er_ap_event(er->wps, ap, WPS_EV_ER_AP_REMOVE); 285 http_client_free(ap->http); 286 ap->http = NULL; 287 if (ap->wps) { 288 wps_deinit(ap->wps); 289 ap->wps = NULL; 290 } 291 292 dl_list_del(&ap->list); 293 if (ap->subscribed) { 294 dl_list_add(&er->ap_unsubscribing, &ap->list); 295 wps_er_ap_unsubscribe(er, ap); 296 } else 297 wps_er_ap_free(ap); 298 } 299 300 301 static void wps_er_ap_timeout(void *eloop_data, void *user_ctx) 302 { 303 struct wps_er *er = eloop_data; 304 struct wps_er_ap *ap = user_ctx; 305 wpa_printf(MSG_DEBUG, "WPS ER: AP advertisement timed out"); 306 wps_er_ap_remove_entry(er, ap); 307 } 308 309 310 static int wps_er_get_sid(struct wps_er_ap *ap, char *sid) 311 { 312 char *pos; 313 char txt[100]; 314 315 if (!sid) { 316 wpa_printf(MSG_DEBUG, "WPS ER: No SID received from %s (%s)", 317 inet_ntoa(ap->addr), ap->location); 318 return -1; 319 } 320 321 pos = os_strstr(sid, "uuid:"); 322 if (!pos) { 323 wpa_printf(MSG_DEBUG, "WPS ER: Invalid SID received from " 324 "%s (%s): '%s'", inet_ntoa(ap->addr), ap->location, 325 sid); 326 return -1; 327 } 328 329 pos += 5; 330 if (uuid_str2bin(pos, ap->sid) < 0) { 331 wpa_printf(MSG_DEBUG, "WPS ER: Invalid SID received from " 332 "%s (%s): '%s'", inet_ntoa(ap->addr), ap->location, 333 sid); 334 return -1; 335 } 336 337 uuid_bin2str(ap->sid, txt, sizeof(txt)); 338 wpa_printf(MSG_DEBUG, "WPS ER: SID for subscription with %s (%s): %s", 339 inet_ntoa(ap->addr), ap->location, txt); 340 341 return 0; 342 } 343 344 345 static void wps_er_http_subscribe_cb(void *ctx, struct http_client *c, 346 enum http_client_event event) 347 { 348 struct wps_er_ap *ap = ctx; 349 350 switch (event) { 351 case HTTP_CLIENT_OK: 352 wpa_printf(MSG_DEBUG, "WPS ER: Subscribed to events"); 353 ap->subscribed = 1; 354 wps_er_get_sid(ap, http_client_get_hdr_line(c, "SID")); 355 wps_er_ap_event(ap->er->wps, ap, WPS_EV_ER_AP_ADD); 356 break; 357 case HTTP_CLIENT_FAILED: 358 case HTTP_CLIENT_INVALID_REPLY: 359 case HTTP_CLIENT_TIMEOUT: 360 wpa_printf(MSG_DEBUG, "WPS ER: Failed to subscribe to events"); 361 break; 362 } 363 http_client_free(ap->http); 364 ap->http = NULL; 365 } 366 367 368 static void wps_er_subscribe(struct wps_er_ap *ap) 369 { 370 struct wpabuf *req; 371 struct sockaddr_in dst; 372 char *url, *path; 373 374 if (ap->event_sub_url == NULL) { 375 wpa_printf(MSG_DEBUG, "WPS ER: No eventSubURL - cannot " 376 "subscribe"); 377 return; 378 } 379 if (ap->http) { 380 wpa_printf(MSG_DEBUG, "WPS ER: Pending HTTP request - cannot " 381 "send subscribe request"); 382 return; 383 } 384 385 url = http_client_url_parse(ap->event_sub_url, &dst, &path); 386 if (url == NULL) { 387 wpa_printf(MSG_DEBUG, "WPS ER: Failed to parse eventSubURL"); 388 return; 389 } 390 391 req = wpabuf_alloc(os_strlen(ap->event_sub_url) + 1000); 392 if (req == NULL) { 393 os_free(url); 394 return; 395 } 396 wpabuf_printf(req, 397 "SUBSCRIBE %s HTTP/1.1\r\n" 398 "HOST: %s:%d\r\n" 399 "CALLBACK: <http://%s:%d/event/%u/%u>\r\n" 400 "NT: upnp:event\r\n" 401 "TIMEOUT: Second-%d\r\n" 402 "\r\n", 403 path, inet_ntoa(dst.sin_addr), ntohs(dst.sin_port), 404 ap->er->ip_addr_text, ap->er->http_port, 405 ap->er->event_id, ap->id, 1800); 406 os_free(url); 407 wpa_hexdump_ascii(MSG_MSGDUMP, "WPS ER: Subscription request", 408 wpabuf_head(req), wpabuf_len(req)); 409 410 ap->http = http_client_addr(&dst, req, 1000, wps_er_http_subscribe_cb, 411 ap); 412 if (ap->http == NULL) 413 wpabuf_free(req); 414 } 415 416 417 static void wps_er_ap_get_m1(struct wps_er_ap *ap, struct wpabuf *m1) 418 { 419 struct wps_parse_attr attr; 420 421 if (wps_parse_msg(m1, &attr) < 0) { 422 wpa_printf(MSG_DEBUG, "WPS ER: Failed to parse M1"); 423 return; 424 } 425 if (attr.primary_dev_type) 426 os_memcpy(ap->pri_dev_type, attr.primary_dev_type, 8); 427 if (attr.wps_state) 428 ap->wps_state = *attr.wps_state; 429 if (attr.mac_addr) 430 os_memcpy(ap->mac_addr, attr.mac_addr, ETH_ALEN); 431 432 wps_er_subscribe(ap); 433 } 434 435 436 static void wps_er_get_device_info(struct wps_er_ap *ap) 437 { 438 wps_er_send_get_device_info(ap, wps_er_ap_get_m1); 439 } 440 441 442 static void wps_er_parse_device_description(struct wps_er_ap *ap, 443 struct wpabuf *reply) 444 { 445 /* Note: reply includes null termination after the buffer data */ 446 const char *data = wpabuf_head(reply); 447 char *pos; 448 449 wpa_hexdump_ascii(MSG_MSGDUMP, "WPS ER: Device info", 450 wpabuf_head(reply), wpabuf_len(reply)); 451 452 ap->friendly_name = xml_get_first_item(data, "friendlyName"); 453 wpa_printf(MSG_DEBUG, "WPS ER: friendlyName='%s'", ap->friendly_name); 454 455 ap->manufacturer = xml_get_first_item(data, "manufacturer"); 456 wpa_printf(MSG_DEBUG, "WPS ER: manufacturer='%s'", ap->manufacturer); 457 458 ap->manufacturer_url = xml_get_first_item(data, "manufacturerURL"); 459 wpa_printf(MSG_DEBUG, "WPS ER: manufacturerURL='%s'", 460 ap->manufacturer_url); 461 462 ap->model_description = xml_get_first_item(data, "modelDescription"); 463 wpa_printf(MSG_DEBUG, "WPS ER: modelDescription='%s'", 464 ap->model_description); 465 466 ap->model_name = xml_get_first_item(data, "modelName"); 467 wpa_printf(MSG_DEBUG, "WPS ER: modelName='%s'", ap->model_name); 468 469 ap->model_number = xml_get_first_item(data, "modelNumber"); 470 wpa_printf(MSG_DEBUG, "WPS ER: modelNumber='%s'", ap->model_number); 471 472 ap->model_url = xml_get_first_item(data, "modelURL"); 473 wpa_printf(MSG_DEBUG, "WPS ER: modelURL='%s'", ap->model_url); 474 475 ap->serial_number = xml_get_first_item(data, "serialNumber"); 476 wpa_printf(MSG_DEBUG, "WPS ER: serialNumber='%s'", ap->serial_number); 477 478 ap->udn = xml_get_first_item(data, "UDN"); 479 wpa_printf(MSG_DEBUG, "WPS ER: UDN='%s'", ap->udn); 480 pos = os_strstr(ap->udn, "uuid:"); 481 if (pos) { 482 pos += 5; 483 if (uuid_str2bin(pos, ap->uuid) < 0) 484 wpa_printf(MSG_DEBUG, "WPS ER: Invalid UUID in UDN"); 485 } 486 487 ap->upc = xml_get_first_item(data, "UPC"); 488 wpa_printf(MSG_DEBUG, "WPS ER: UPC='%s'", ap->upc); 489 490 ap->scpd_url = http_link_update( 491 xml_get_first_item(data, "SCPDURL"), ap->location); 492 wpa_printf(MSG_DEBUG, "WPS ER: SCPDURL='%s'", ap->scpd_url); 493 494 ap->control_url = http_link_update( 495 xml_get_first_item(data, "controlURL"), ap->location); 496 wpa_printf(MSG_DEBUG, "WPS ER: controlURL='%s'", ap->control_url); 497 498 ap->event_sub_url = http_link_update( 499 xml_get_first_item(data, "eventSubURL"), ap->location); 500 wpa_printf(MSG_DEBUG, "WPS ER: eventSubURL='%s'", ap->event_sub_url); 501 } 502 503 504 static void wps_er_http_dev_desc_cb(void *ctx, struct http_client *c, 505 enum http_client_event event) 506 { 507 struct wps_er_ap *ap = ctx; 508 struct wpabuf *reply; 509 int ok = 0; 510 511 switch (event) { 512 case HTTP_CLIENT_OK: 513 reply = http_client_get_body(c); 514 if (reply == NULL) 515 break; 516 wps_er_parse_device_description(ap, reply); 517 ok = 1; 518 break; 519 case HTTP_CLIENT_FAILED: 520 case HTTP_CLIENT_INVALID_REPLY: 521 case HTTP_CLIENT_TIMEOUT: 522 wpa_printf(MSG_DEBUG, "WPS ER: Failed to fetch device info"); 523 break; 524 } 525 http_client_free(ap->http); 526 ap->http = NULL; 527 if (ok) 528 wps_er_get_device_info(ap); 529 } 530 531 532 void wps_er_ap_add(struct wps_er *er, const u8 *uuid, struct in_addr *addr, 533 const char *location, int max_age) 534 { 535 struct wps_er_ap *ap; 536 537 ap = wps_er_ap_get(er, addr, uuid); 538 if (ap) { 539 /* Update advertisement timeout */ 540 eloop_cancel_timeout(wps_er_ap_timeout, er, ap); 541 eloop_register_timeout(max_age, 0, wps_er_ap_timeout, er, ap); 542 return; 543 } 544 545 ap = os_zalloc(sizeof(*ap)); 546 if (ap == NULL) 547 return; 548 dl_list_init(&ap->sta); 549 ap->er = er; 550 ap->id = ++er->next_ap_id; 551 ap->location = os_strdup(location); 552 if (ap->location == NULL) { 553 os_free(ap); 554 return; 555 } 556 dl_list_add(&er->ap, &ap->list); 557 558 ap->addr.s_addr = addr->s_addr; 559 os_memcpy(ap->uuid, uuid, WPS_UUID_LEN); 560 eloop_register_timeout(max_age, 0, wps_er_ap_timeout, er, ap); 561 562 wpa_printf(MSG_DEBUG, "WPS ER: Added AP entry for %s (%s)", 563 inet_ntoa(ap->addr), ap->location); 564 565 /* Fetch device description */ 566 ap->http = http_client_url(ap->location, NULL, 10000, 567 wps_er_http_dev_desc_cb, ap); 568 } 569 570 571 void wps_er_ap_remove(struct wps_er *er, struct in_addr *addr) 572 { 573 struct wps_er_ap *ap; 574 dl_list_for_each(ap, &er->ap, struct wps_er_ap, list) { 575 if (ap->addr.s_addr == addr->s_addr) { 576 wps_er_ap_remove_entry(er, ap); 577 return; 578 } 579 } 580 } 581 582 583 static void wps_er_ap_remove_all(struct wps_er *er) 584 { 585 struct wps_er_ap *prev, *ap; 586 dl_list_for_each_safe(ap, prev, &er->ap, struct wps_er_ap, list) 587 wps_er_ap_remove_entry(er, ap); 588 } 589 590 591 static void http_put_date(struct wpabuf *buf) 592 { 593 wpabuf_put_str(buf, "Date: "); 594 format_date(buf); 595 wpabuf_put_str(buf, "\r\n"); 596 } 597 598 599 static void wps_er_http_resp_not_found(struct http_request *req) 600 { 601 struct wpabuf *buf; 602 buf = wpabuf_alloc(200); 603 if (buf == NULL) { 604 http_request_deinit(req); 605 return; 606 } 607 608 wpabuf_put_str(buf, 609 "HTTP/1.1 404 Not Found\r\n" 610 "Server: unspecified, UPnP/1.0, unspecified\r\n" 611 "Connection: close\r\n"); 612 http_put_date(buf); 613 wpabuf_put_str(buf, "\r\n"); 614 http_request_send_and_deinit(req, buf); 615 } 616 617 618 static void wps_er_http_resp_ok(struct http_request *req) 619 { 620 struct wpabuf *buf; 621 buf = wpabuf_alloc(200); 622 if (buf == NULL) { 623 http_request_deinit(req); 624 return; 625 } 626 627 wpabuf_put_str(buf, 628 "HTTP/1.1 200 OK\r\n" 629 "Server: unspecified, UPnP/1.0, unspecified\r\n" 630 "Connection: close\r\n" 631 "Content-Length: 0\r\n"); 632 http_put_date(buf); 633 wpabuf_put_str(buf, "\r\n"); 634 http_request_send_and_deinit(req, buf); 635 } 636 637 638 static void wps_er_sta_timeout(void *eloop_data, void *user_ctx) 639 { 640 struct wps_er_sta *sta = eloop_data; 641 wpa_printf(MSG_DEBUG, "WPS ER: STA entry timed out"); 642 dl_list_del(&sta->list); 643 wps_er_sta_free(sta); 644 } 645 646 647 static struct wps_er_sta * wps_er_add_sta_data(struct wps_er_ap *ap, 648 const u8 *addr, 649 struct wps_parse_attr *attr, 650 int probe_req) 651 { 652 struct wps_er_sta *sta = wps_er_sta_get(ap, addr); 653 int new_sta = 0; 654 int m1; 655 656 m1 = !probe_req && attr->msg_type && *attr->msg_type == WPS_M1; 657 658 if (sta == NULL) { 659 /* 660 * Only allow new STA entry to be added based on Probe Request 661 * or M1. This will filter out bogus events and anything that 662 * may have been ongoing at the time ER subscribed for events. 663 */ 664 if (!probe_req && !m1) 665 return NULL; 666 667 sta = os_zalloc(sizeof(*sta)); 668 if (sta == NULL) 669 return NULL; 670 os_memcpy(sta->addr, addr, ETH_ALEN); 671 sta->ap = ap; 672 dl_list_add(&ap->sta, &sta->list); 673 new_sta = 1; 674 } 675 676 if (m1) 677 sta->m1_received = 1; 678 679 if (attr->config_methods && (!probe_req || !sta->m1_received)) 680 sta->config_methods = WPA_GET_BE16(attr->config_methods); 681 if (attr->uuid_e && (!probe_req || !sta->m1_received)) 682 os_memcpy(sta->uuid, attr->uuid_e, WPS_UUID_LEN); 683 if (attr->primary_dev_type && (!probe_req || !sta->m1_received)) 684 os_memcpy(sta->pri_dev_type, attr->primary_dev_type, 8); 685 if (attr->dev_password_id && (!probe_req || !sta->m1_received)) 686 sta->dev_passwd_id = WPA_GET_BE16(attr->dev_password_id); 687 688 if (attr->manufacturer) { 689 os_free(sta->manufacturer); 690 sta->manufacturer = os_malloc(attr->manufacturer_len + 1); 691 if (sta->manufacturer) { 692 os_memcpy(sta->manufacturer, attr->manufacturer, 693 attr->manufacturer_len); 694 sta->manufacturer[attr->manufacturer_len] = '\0'; 695 } 696 } 697 698 if (attr->model_name) { 699 os_free(sta->model_name); 700 sta->model_name = os_malloc(attr->model_name_len + 1); 701 if (sta->model_name) { 702 os_memcpy(sta->model_name, attr->model_name, 703 attr->model_name_len); 704 sta->model_name[attr->model_name_len] = '\0'; 705 } 706 } 707 708 if (attr->model_number) { 709 os_free(sta->model_number); 710 sta->model_number = os_malloc(attr->model_number_len + 1); 711 if (sta->model_number) { 712 os_memcpy(sta->model_number, attr->model_number, 713 attr->model_number_len); 714 sta->model_number[attr->model_number_len] = '\0'; 715 } 716 } 717 718 if (attr->serial_number) { 719 os_free(sta->serial_number); 720 sta->serial_number = os_malloc(attr->serial_number_len + 1); 721 if (sta->serial_number) { 722 os_memcpy(sta->serial_number, attr->serial_number, 723 attr->serial_number_len); 724 sta->serial_number[attr->serial_number_len] = '\0'; 725 } 726 } 727 728 if (attr->dev_name) { 729 os_free(sta->dev_name); 730 sta->dev_name = os_malloc(attr->dev_name_len + 1); 731 if (sta->dev_name) { 732 os_memcpy(sta->dev_name, attr->dev_name, 733 attr->dev_name_len); 734 sta->dev_name[attr->dev_name_len] = '\0'; 735 } 736 } 737 738 eloop_cancel_timeout(wps_er_sta_timeout, sta, NULL); 739 eloop_register_timeout(300, 0, wps_er_sta_timeout, sta, NULL); 740 741 if (m1 || new_sta) 742 wps_er_sta_event(ap->er->wps, sta, WPS_EV_ER_ENROLLEE_ADD); 743 744 return sta; 745 } 746 747 748 static void wps_er_process_wlanevent_probe_req(struct wps_er_ap *ap, 749 const u8 *addr, 750 struct wpabuf *msg) 751 { 752 struct wps_parse_attr attr; 753 754 wpa_printf(MSG_DEBUG, "WPS ER: WLANEvent - Probe Request - from " 755 MACSTR, MAC2STR(addr)); 756 wpa_hexdump_buf(MSG_MSGDUMP, "WPS ER: WLANEvent - Enrollee's message " 757 "(TLVs from Probe Request)", msg); 758 759 if (wps_parse_msg(msg, &attr) < 0) { 760 wpa_printf(MSG_DEBUG, "WPS ER: Failed to parse TLVs in " 761 "WLANEvent message"); 762 return; 763 } 764 765 wps_er_add_sta_data(ap, addr, &attr, 1); 766 } 767 768 769 static void wps_er_http_put_wlan_response_cb(void *ctx, struct http_client *c, 770 enum http_client_event event) 771 { 772 struct wps_er_sta *sta = ctx; 773 774 switch (event) { 775 case HTTP_CLIENT_OK: 776 wpa_printf(MSG_DEBUG, "WPS ER: PutWLANResponse OK"); 777 break; 778 case HTTP_CLIENT_FAILED: 779 case HTTP_CLIENT_INVALID_REPLY: 780 case HTTP_CLIENT_TIMEOUT: 781 wpa_printf(MSG_DEBUG, "WPS ER: PutWLANResponse failed"); 782 break; 783 } 784 http_client_free(sta->http); 785 sta->http = NULL; 786 } 787 788 789 static const char *soap_prefix = 790 "<?xml version=\"1.0\"?>\n" 791 "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" " 792 "s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">\n" 793 "<s:Body>\n"; 794 static const char *soap_postfix = 795 "</s:Body>\n</s:Envelope>\n"; 796 static const char *urn_wfawlanconfig = 797 "urn:schemas-wifialliance-org:service:WFAWLANConfig:1"; 798 799 static struct wpabuf * wps_er_soap_hdr(const struct wpabuf *msg, 800 const char *name, const char *arg_name, 801 const char *path, 802 const struct sockaddr_in *dst, 803 char **len_ptr, char **body_ptr) 804 { 805 unsigned char *encoded; 806 size_t encoded_len; 807 struct wpabuf *buf; 808 809 if (msg) { 810 encoded = base64_encode(wpabuf_head(msg), wpabuf_len(msg), 811 &encoded_len); 812 if (encoded == NULL) 813 return NULL; 814 } else { 815 encoded = NULL; 816 encoded_len = 0; 817 } 818 819 buf = wpabuf_alloc(1000 + encoded_len); 820 if (buf == NULL) { 821 os_free(encoded); 822 return NULL; 823 } 824 825 wpabuf_printf(buf, 826 "POST %s HTTP/1.1\r\n" 827 "Host: %s:%d\r\n" 828 "Content-Type: text/xml; charset=\"utf-8\"\r\n" 829 "Content-Length: ", 830 path, inet_ntoa(dst->sin_addr), ntohs(dst->sin_port)); 831 832 *len_ptr = wpabuf_put(buf, 0); 833 wpabuf_printf(buf, 834 " \r\n" 835 "SOAPACTION: \"%s#%s\"\r\n" 836 "\r\n", 837 urn_wfawlanconfig, name); 838 839 *body_ptr = wpabuf_put(buf, 0); 840 841 wpabuf_put_str(buf, soap_prefix); 842 wpabuf_printf(buf, "<u:%s xmlns:u=\"", name); 843 wpabuf_put_str(buf, urn_wfawlanconfig); 844 wpabuf_put_str(buf, "\">\n"); 845 if (encoded) { 846 wpabuf_printf(buf, "<%s>%s</%s>\n", 847 arg_name, (char *) encoded, arg_name); 848 os_free(encoded); 849 } 850 851 return buf; 852 } 853 854 855 static void wps_er_soap_end(struct wpabuf *buf, const char *name, 856 char *len_ptr, char *body_ptr) 857 { 858 char len_buf[10]; 859 wpabuf_printf(buf, "</u:%s>\n", name); 860 wpabuf_put_str(buf, soap_postfix); 861 os_snprintf(len_buf, sizeof(len_buf), "%d", 862 (int) ((char *) wpabuf_put(buf, 0) - body_ptr)); 863 os_memcpy(len_ptr, len_buf, os_strlen(len_buf)); 864 } 865 866 867 static void wps_er_sta_send_msg(struct wps_er_sta *sta, struct wpabuf *msg) 868 { 869 struct wpabuf *buf; 870 char *len_ptr, *body_ptr; 871 struct sockaddr_in dst; 872 char *url, *path; 873 874 if (sta->http) { 875 wpa_printf(MSG_DEBUG, "WPS ER: Pending HTTP request for STA - " 876 "ignore new request"); 877 wpabuf_free(msg); 878 return; 879 } 880 881 if (sta->ap->control_url == NULL) { 882 wpa_printf(MSG_DEBUG, "WPS ER: No controlURL for AP"); 883 wpabuf_free(msg); 884 return; 885 } 886 887 url = http_client_url_parse(sta->ap->control_url, &dst, &path); 888 if (url == NULL) { 889 wpa_printf(MSG_DEBUG, "WPS ER: Failed to parse controlURL"); 890 wpabuf_free(msg); 891 return; 892 } 893 894 buf = wps_er_soap_hdr(msg, "PutWLANResponse", "NewMessage", path, &dst, 895 &len_ptr, &body_ptr); 896 wpabuf_free(msg); 897 os_free(url); 898 if (buf == NULL) 899 return; 900 wpabuf_printf(buf, "<NewWLANEventType>%d</NewWLANEventType>\n", 901 UPNP_WPS_WLANEVENT_TYPE_EAP); 902 wpabuf_printf(buf, "<NewWLANEventMAC>" MACSTR "</NewWLANEventMAC>\n", 903 MAC2STR(sta->addr)); 904 905 wps_er_soap_end(buf, "PutWLANResponse", len_ptr, body_ptr); 906 907 sta->http = http_client_addr(&dst, buf, 1000, 908 wps_er_http_put_wlan_response_cb, sta); 909 if (sta->http == NULL) 910 wpabuf_free(buf); 911 } 912 913 914 static void wps_er_sta_process(struct wps_er_sta *sta, struct wpabuf *msg, 915 enum wsc_op_code op_code) 916 { 917 enum wps_process_res res; 918 919 res = wps_process_msg(sta->wps, op_code, msg); 920 if (res == WPS_CONTINUE) { 921 struct wpabuf *next = wps_get_msg(sta->wps, &op_code); 922 if (next) 923 wps_er_sta_send_msg(sta, next); 924 } else { 925 wpa_printf(MSG_DEBUG, "WPS ER: Protocol run %s with the " 926 "enrollee (res=%d)", 927 res == WPS_DONE ? "succeeded" : "failed", res); 928 wps_deinit(sta->wps); 929 sta->wps = NULL; 930 if (res == WPS_DONE) { 931 /* Remove the STA entry after short timeout */ 932 eloop_cancel_timeout(wps_er_sta_timeout, sta, NULL); 933 eloop_register_timeout(10, 0, wps_er_sta_timeout, sta, 934 NULL); 935 } 936 } 937 } 938 939 940 static void wps_er_sta_start(struct wps_er_sta *sta, struct wpabuf *msg) 941 { 942 struct wps_config cfg; 943 944 if (sta->wps) 945 wps_deinit(sta->wps); 946 947 os_memset(&cfg, 0, sizeof(cfg)); 948 cfg.wps = sta->ap->er->wps; 949 cfg.registrar = 1; 950 cfg.peer_addr = sta->addr; 951 952 sta->wps = wps_init(&cfg); 953 if (sta->wps == NULL) 954 return; 955 sta->wps->er = 1; 956 sta->wps->use_cred = sta->ap->ap_settings; 957 if (sta->ap->ap_settings) { 958 os_free(sta->cred); 959 sta->cred = os_malloc(sizeof(*sta->cred)); 960 if (sta->cred) { 961 os_memcpy(sta->cred, sta->ap->ap_settings, 962 sizeof(*sta->cred)); 963 sta->cred->cred_attr = NULL; 964 os_memcpy(sta->cred->mac_addr, sta->addr, ETH_ALEN); 965 sta->wps->use_cred = sta->cred; 966 } 967 } 968 969 wps_er_sta_process(sta, msg, WSC_MSG); 970 } 971 972 973 static void wps_er_process_wlanevent_eap(struct wps_er_ap *ap, const u8 *addr, 974 struct wpabuf *msg) 975 { 976 struct wps_parse_attr attr; 977 struct wps_er_sta *sta; 978 979 wpa_printf(MSG_DEBUG, "WPS ER: WLANEvent - EAP - from " MACSTR, 980 MAC2STR(addr)); 981 wpa_hexdump_buf(MSG_MSGDUMP, "WPS ER: WLANEvent - Enrollee's message " 982 "(TLVs from EAP-WSC)", msg); 983 984 if (wps_parse_msg(msg, &attr) < 0) { 985 wpa_printf(MSG_DEBUG, "WPS ER: Failed to parse TLVs in " 986 "WLANEvent message"); 987 return; 988 } 989 990 sta = wps_er_add_sta_data(ap, addr, &attr, 0); 991 if (sta == NULL) 992 return; 993 994 if (attr.msg_type && *attr.msg_type == WPS_M1) 995 wps_er_sta_start(sta, msg); 996 else if (sta->wps) { 997 enum wsc_op_code op_code = WSC_MSG; 998 if (attr.msg_type) { 999 switch (*attr.msg_type) { 1000 case WPS_WSC_ACK: 1001 op_code = WSC_ACK; 1002 break; 1003 case WPS_WSC_NACK: 1004 op_code = WSC_NACK; 1005 break; 1006 case WPS_WSC_DONE: 1007 op_code = WSC_Done; 1008 break; 1009 } 1010 } 1011 wps_er_sta_process(sta, msg, op_code); 1012 } 1013 } 1014 1015 1016 static void wps_er_process_wlanevent(struct wps_er_ap *ap, 1017 struct wpabuf *event) 1018 { 1019 u8 *data; 1020 u8 wlan_event_type; 1021 u8 wlan_event_mac[ETH_ALEN]; 1022 struct wpabuf msg; 1023 1024 wpa_hexdump(MSG_MSGDUMP, "WPS ER: Received WLANEvent", 1025 wpabuf_head(event), wpabuf_len(event)); 1026 if (wpabuf_len(event) < 1 + 17) { 1027 wpa_printf(MSG_DEBUG, "WPS ER: Too short WLANEvent"); 1028 return; 1029 } 1030 1031 data = wpabuf_mhead(event); 1032 wlan_event_type = data[0]; 1033 if (hwaddr_aton((char *) data + 1, wlan_event_mac) < 0) { 1034 wpa_printf(MSG_DEBUG, "WPS ER: Invalid WLANEventMAC in " 1035 "WLANEvent"); 1036 return; 1037 } 1038 1039 wpabuf_set(&msg, data + 1 + 17, wpabuf_len(event) - (1 + 17)); 1040 1041 switch (wlan_event_type) { 1042 case 1: 1043 wps_er_process_wlanevent_probe_req(ap, wlan_event_mac, &msg); 1044 break; 1045 case 2: 1046 wps_er_process_wlanevent_eap(ap, wlan_event_mac, &msg); 1047 break; 1048 default: 1049 wpa_printf(MSG_DEBUG, "WPS ER: Unknown WLANEventType %d", 1050 wlan_event_type); 1051 break; 1052 } 1053 } 1054 1055 1056 static void wps_er_http_event(struct wps_er *er, struct http_request *req, 1057 unsigned int ap_id) 1058 { 1059 struct wps_er_ap *ap = wps_er_ap_get_id(er, ap_id); 1060 struct wpabuf *event; 1061 enum http_reply_code ret; 1062 1063 if (ap == NULL) { 1064 wpa_printf(MSG_DEBUG, "WPS ER: HTTP event from unknown AP id " 1065 "%u", ap_id); 1066 wps_er_http_resp_not_found(req); 1067 return; 1068 } 1069 wpa_printf(MSG_MSGDUMP, "WPS ER: HTTP event from AP id %u: %s", 1070 ap_id, http_request_get_data(req)); 1071 1072 event = xml_get_base64_item(http_request_get_data(req), "WLANEvent", 1073 &ret); 1074 if (event == NULL) { 1075 wpa_printf(MSG_DEBUG, "WPS ER: Could not extract WLANEvent " 1076 "from the event notification"); 1077 /* 1078 * Reply with OK anyway to avoid getting unregistered from 1079 * events. 1080 */ 1081 wps_er_http_resp_ok(req); 1082 return; 1083 } 1084 1085 wps_er_process_wlanevent(ap, event); 1086 1087 wpabuf_free(event); 1088 wps_er_http_resp_ok(req); 1089 } 1090 1091 1092 static void wps_er_http_notify(struct wps_er *er, struct http_request *req) 1093 { 1094 char *uri = http_request_get_uri(req); 1095 1096 if (os_strncmp(uri, "/event/", 7) == 0) { 1097 unsigned int event_id; 1098 char *pos; 1099 event_id = atoi(uri + 7); 1100 if (event_id != er->event_id) { 1101 wpa_printf(MSG_DEBUG, "WPS ER: HTTP event for an " 1102 "unknown event id %u", event_id); 1103 return; 1104 } 1105 pos = os_strchr(uri + 7, '/'); 1106 if (pos == NULL) 1107 return; 1108 pos++; 1109 wps_er_http_event(er, req, atoi(pos)); 1110 } else { 1111 wpa_printf(MSG_DEBUG, "WPS ER: Unknown HTTP NOTIFY for '%s'", 1112 uri); 1113 wps_er_http_resp_not_found(req); 1114 } 1115 } 1116 1117 1118 static void wps_er_http_req(void *ctx, struct http_request *req) 1119 { 1120 struct wps_er *er = ctx; 1121 struct sockaddr_in *cli = http_request_get_cli_addr(req); 1122 enum httpread_hdr_type type = http_request_get_type(req); 1123 struct wpabuf *buf; 1124 1125 wpa_printf(MSG_DEBUG, "WPS ER: HTTP request: '%s' (type %d) from " 1126 "%s:%d", 1127 http_request_get_uri(req), type, 1128 inet_ntoa(cli->sin_addr), ntohs(cli->sin_port)); 1129 1130 switch (type) { 1131 case HTTPREAD_HDR_TYPE_NOTIFY: 1132 wps_er_http_notify(er, req); 1133 break; 1134 default: 1135 wpa_printf(MSG_DEBUG, "WPS ER: Unsupported HTTP request type " 1136 "%d", type); 1137 buf = wpabuf_alloc(200); 1138 if (buf == NULL) { 1139 http_request_deinit(req); 1140 return; 1141 } 1142 wpabuf_put_str(buf, 1143 "HTTP/1.1 501 Unimplemented\r\n" 1144 "Connection: close\r\n"); 1145 http_put_date(buf); 1146 wpabuf_put_str(buf, "\r\n"); 1147 http_request_send_and_deinit(req, buf); 1148 break; 1149 } 1150 } 1151 1152 1153 struct wps_er * 1154 wps_er_init(struct wps_context *wps, const char *ifname) 1155 { 1156 struct wps_er *er; 1157 struct in_addr addr; 1158 1159 er = os_zalloc(sizeof(*er)); 1160 if (er == NULL) 1161 return NULL; 1162 dl_list_init(&er->ap); 1163 dl_list_init(&er->ap_unsubscribing); 1164 1165 er->multicast_sd = -1; 1166 er->ssdp_sd = -1; 1167 1168 os_strlcpy(er->ifname, ifname, sizeof(er->ifname)); 1169 er->wps = wps; 1170 if (os_get_random((unsigned char *) &er->event_id, 1171 sizeof(er->event_id)) < 0) { 1172 wps_er_deinit(er, NULL, NULL); 1173 return NULL; 1174 } 1175 /* Limit event_id to < 32 bits to avoid issues with atoi() */ 1176 er->event_id &= 0x0fffffff; 1177 1178 if (get_netif_info(ifname, &er->ip_addr, &er->ip_addr_text, 1179 er->mac_addr)) { 1180 wpa_printf(MSG_INFO, "WPS UPnP: Could not get IP/MAC address " 1181 "for %s. Does it have IP address?", ifname); 1182 wps_er_deinit(er, NULL, NULL); 1183 return NULL; 1184 } 1185 1186 if (wps_er_ssdp_init(er) < 0) { 1187 wps_er_deinit(er, NULL, NULL); 1188 return NULL; 1189 } 1190 1191 addr.s_addr = er->ip_addr; 1192 er->http_srv = http_server_init(&addr, -1, wps_er_http_req, er); 1193 if (er->http_srv == NULL) { 1194 wps_er_deinit(er, NULL, NULL); 1195 return NULL; 1196 } 1197 er->http_port = http_server_get_port(er->http_srv); 1198 1199 wpa_printf(MSG_DEBUG, "WPS ER: Start (ifname=%s ip_addr=%s)", 1200 er->ifname, er->ip_addr_text); 1201 1202 return er; 1203 } 1204 1205 1206 void wps_er_refresh(struct wps_er *er) 1207 { 1208 struct wps_er_ap *ap; 1209 struct wps_er_sta *sta; 1210 1211 dl_list_for_each(ap, &er->ap, struct wps_er_ap, list) { 1212 wps_er_ap_event(er->wps, ap, WPS_EV_ER_AP_ADD); 1213 dl_list_for_each(sta, &ap->sta, struct wps_er_sta, list) 1214 wps_er_sta_event(er->wps, sta, WPS_EV_ER_ENROLLEE_ADD); 1215 } 1216 1217 wps_er_send_ssdp_msearch(er); 1218 } 1219 1220 1221 static void wps_er_deinit_finish(void *eloop_data, void *user_ctx) 1222 { 1223 struct wps_er *er = eloop_data; 1224 void (*deinit_done_cb)(void *ctx); 1225 void *deinit_done_ctx; 1226 1227 wpa_printf(MSG_DEBUG, "WPS ER: Finishing deinit"); 1228 1229 deinit_done_cb = er->deinit_done_cb; 1230 deinit_done_ctx = er->deinit_done_ctx; 1231 os_free(er->ip_addr_text); 1232 os_free(er); 1233 1234 if (deinit_done_cb) 1235 deinit_done_cb(deinit_done_ctx); 1236 } 1237 1238 1239 void wps_er_deinit(struct wps_er *er, void (*cb)(void *ctx), void *ctx) 1240 { 1241 if (er == NULL) 1242 return; 1243 http_server_deinit(er->http_srv); 1244 wps_er_ap_remove_all(er); 1245 wps_er_ssdp_deinit(er); 1246 eloop_register_timeout(dl_list_empty(&er->ap_unsubscribing) ? 0 : 5, 0, 1247 wps_er_deinit_finish, er, NULL); 1248 wpa_printf(MSG_DEBUG, "WPS ER: Finish deinit from timeout"); 1249 er->deinitializing = 1; 1250 er->deinit_done_cb = cb; 1251 er->deinit_done_ctx = ctx; 1252 } 1253 1254 1255 static void wps_er_http_set_sel_reg_cb(void *ctx, struct http_client *c, 1256 enum http_client_event event) 1257 { 1258 struct wps_er_ap *ap = ctx; 1259 1260 switch (event) { 1261 case HTTP_CLIENT_OK: 1262 wpa_printf(MSG_DEBUG, "WPS ER: SetSelectedRegistrar OK"); 1263 break; 1264 case HTTP_CLIENT_FAILED: 1265 case HTTP_CLIENT_INVALID_REPLY: 1266 case HTTP_CLIENT_TIMEOUT: 1267 wpa_printf(MSG_DEBUG, "WPS ER: SetSelectedRegistrar failed"); 1268 break; 1269 } 1270 http_client_free(ap->http); 1271 ap->http = NULL; 1272 } 1273 1274 1275 static void wps_er_send_set_sel_reg(struct wps_er_ap *ap, struct wpabuf *msg) 1276 { 1277 struct wpabuf *buf; 1278 char *len_ptr, *body_ptr; 1279 struct sockaddr_in dst; 1280 char *url, *path; 1281 1282 if (ap->control_url == NULL) { 1283 wpa_printf(MSG_DEBUG, "WPS ER: No controlURL for AP"); 1284 return; 1285 } 1286 1287 if (ap->http) { 1288 wpa_printf(MSG_DEBUG, "WPS ER: Pending HTTP request for AP - " 1289 "ignore new request"); 1290 return; 1291 } 1292 1293 url = http_client_url_parse(ap->control_url, &dst, &path); 1294 if (url == NULL) { 1295 wpa_printf(MSG_DEBUG, "WPS ER: Failed to parse controlURL"); 1296 return; 1297 } 1298 1299 buf = wps_er_soap_hdr(msg, "SetSelectedRegistrar", "NewMessage", path, 1300 &dst, &len_ptr, &body_ptr); 1301 os_free(url); 1302 if (buf == NULL) 1303 return; 1304 1305 wps_er_soap_end(buf, "SetSelectedRegistrar", len_ptr, body_ptr); 1306 1307 ap->http = http_client_addr(&dst, buf, 1000, 1308 wps_er_http_set_sel_reg_cb, ap); 1309 if (ap->http == NULL) 1310 wpabuf_free(buf); 1311 } 1312 1313 1314 static int wps_er_build_selected_registrar(struct wpabuf *msg, int sel_reg) 1315 { 1316 wpabuf_put_be16(msg, ATTR_SELECTED_REGISTRAR); 1317 wpabuf_put_be16(msg, 1); 1318 wpabuf_put_u8(msg, !!sel_reg); 1319 return 0; 1320 } 1321 1322 1323 static int wps_er_build_dev_password_id(struct wpabuf *msg, u16 dev_passwd_id) 1324 { 1325 wpabuf_put_be16(msg, ATTR_DEV_PASSWORD_ID); 1326 wpabuf_put_be16(msg, 2); 1327 wpabuf_put_be16(msg, dev_passwd_id); 1328 return 0; 1329 } 1330 1331 1332 static int wps_er_build_sel_reg_config_methods(struct wpabuf *msg, 1333 u16 sel_reg_config_methods) 1334 { 1335 wpabuf_put_be16(msg, ATTR_SELECTED_REGISTRAR_CONFIG_METHODS); 1336 wpabuf_put_be16(msg, 2); 1337 wpabuf_put_be16(msg, sel_reg_config_methods); 1338 return 0; 1339 } 1340 1341 1342 void wps_er_set_sel_reg(struct wps_er *er, int sel_reg, u16 dev_passwd_id, 1343 u16 sel_reg_config_methods) 1344 { 1345 struct wpabuf *msg; 1346 struct wps_er_ap *ap; 1347 1348 msg = wpabuf_alloc(500); 1349 if (msg == NULL) 1350 return; 1351 1352 if (wps_build_version(msg) || 1353 wps_er_build_selected_registrar(msg, sel_reg) || 1354 wps_er_build_dev_password_id(msg, dev_passwd_id) || 1355 wps_er_build_sel_reg_config_methods(msg, sel_reg_config_methods)) { 1356 wpabuf_free(msg); 1357 return; 1358 } 1359 1360 dl_list_for_each(ap, &er->ap, struct wps_er_ap, list) 1361 wps_er_send_set_sel_reg(ap, msg); 1362 1363 wpabuf_free(msg); 1364 } 1365 1366 1367 int wps_er_pbc(struct wps_er *er, const u8 *uuid) 1368 { 1369 if (er == NULL || er->wps == NULL) 1370 return -1; 1371 1372 /* 1373 * TODO: Should enable PBC mode only in a single AP based on which AP 1374 * the Enrollee (uuid) is using. Now, we may end up enabling multiple 1375 * APs in PBC mode which could result in session overlap at the 1376 * Enrollee. 1377 */ 1378 if (wps_registrar_button_pushed(er->wps->registrar)) 1379 return -1; 1380 1381 return 0; 1382 } 1383 1384 1385 static void wps_er_ap_settings_cb(void *ctx, const struct wps_credential *cred) 1386 { 1387 struct wps_er_ap *ap = ctx; 1388 wpa_printf(MSG_DEBUG, "WPS ER: AP Settings received"); 1389 os_free(ap->ap_settings); 1390 ap->ap_settings = os_malloc(sizeof(*cred)); 1391 if (ap->ap_settings) { 1392 os_memcpy(ap->ap_settings, cred, sizeof(*cred)); 1393 ap->ap_settings->cred_attr = NULL; 1394 } 1395 1396 /* TODO: send info through ctrl_iface */ 1397 } 1398 1399 1400 static void wps_er_http_put_message_cb(void *ctx, struct http_client *c, 1401 enum http_client_event event) 1402 { 1403 struct wps_er_ap *ap = ctx; 1404 struct wpabuf *reply; 1405 char *msg = NULL; 1406 1407 switch (event) { 1408 case HTTP_CLIENT_OK: 1409 wpa_printf(MSG_DEBUG, "WPS ER: PutMessage OK"); 1410 reply = http_client_get_body(c); 1411 if (reply == NULL) 1412 break; 1413 msg = os_zalloc(wpabuf_len(reply) + 1); 1414 if (msg == NULL) 1415 break; 1416 os_memcpy(msg, wpabuf_head(reply), wpabuf_len(reply)); 1417 break; 1418 case HTTP_CLIENT_FAILED: 1419 case HTTP_CLIENT_INVALID_REPLY: 1420 case HTTP_CLIENT_TIMEOUT: 1421 wpa_printf(MSG_DEBUG, "WPS ER: PutMessage failed"); 1422 if (ap->wps) { 1423 wps_deinit(ap->wps); 1424 ap->wps = NULL; 1425 } 1426 break; 1427 } 1428 http_client_free(ap->http); 1429 ap->http = NULL; 1430 1431 if (msg) { 1432 struct wpabuf *buf; 1433 enum http_reply_code ret; 1434 buf = xml_get_base64_item(msg, "NewOutMessage", &ret); 1435 os_free(msg); 1436 if (buf == NULL) { 1437 wpa_printf(MSG_DEBUG, "WPS ER: Could not extract " 1438 "NewOutMessage from PutMessage response"); 1439 return; 1440 } 1441 wps_er_ap_process(ap, buf); 1442 wpabuf_free(buf); 1443 } 1444 } 1445 1446 1447 static void wps_er_ap_put_message(struct wps_er_ap *ap, 1448 const struct wpabuf *msg) 1449 { 1450 struct wpabuf *buf; 1451 char *len_ptr, *body_ptr; 1452 struct sockaddr_in dst; 1453 char *url, *path; 1454 1455 if (ap->http) { 1456 wpa_printf(MSG_DEBUG, "WPS ER: Pending HTTP operation ongoing " 1457 "with the AP - cannot continue learn"); 1458 return; 1459 } 1460 1461 if (ap->control_url == NULL) { 1462 wpa_printf(MSG_DEBUG, "WPS ER: No controlURL for AP"); 1463 return; 1464 } 1465 1466 url = http_client_url_parse(ap->control_url, &dst, &path); 1467 if (url == NULL) { 1468 wpa_printf(MSG_DEBUG, "WPS ER: Failed to parse controlURL"); 1469 return; 1470 } 1471 1472 buf = wps_er_soap_hdr(msg, "PutMessage", "NewInMessage", path, &dst, 1473 &len_ptr, &body_ptr); 1474 os_free(url); 1475 if (buf == NULL) 1476 return; 1477 1478 wps_er_soap_end(buf, "PutMessage", len_ptr, body_ptr); 1479 1480 ap->http = http_client_addr(&dst, buf, 10000, 1481 wps_er_http_put_message_cb, ap); 1482 if (ap->http == NULL) 1483 wpabuf_free(buf); 1484 } 1485 1486 1487 static void wps_er_ap_process(struct wps_er_ap *ap, struct wpabuf *msg) 1488 { 1489 enum wps_process_res res; 1490 1491 res = wps_process_msg(ap->wps, WSC_MSG, msg); 1492 if (res == WPS_CONTINUE) { 1493 enum wsc_op_code op_code; 1494 struct wpabuf *next = wps_get_msg(ap->wps, &op_code); 1495 if (next) { 1496 wps_er_ap_put_message(ap, next); 1497 wpabuf_free(next); 1498 } else { 1499 wpa_printf(MSG_DEBUG, "WPS ER: Failed to build " 1500 "message"); 1501 wps_deinit(ap->wps); 1502 ap->wps = NULL; 1503 } 1504 } else { 1505 wpa_printf(MSG_DEBUG, "WPS ER: Failed to process message from " 1506 "AP (res=%d)", res); 1507 wps_deinit(ap->wps); 1508 ap->wps = NULL; 1509 } 1510 } 1511 1512 1513 static void wps_er_ap_learn_m1(struct wps_er_ap *ap, struct wpabuf *m1) 1514 { 1515 struct wps_config cfg; 1516 1517 if (ap->wps) { 1518 wpa_printf(MSG_DEBUG, "WPS ER: Protocol run already in " 1519 "progress with this AP"); 1520 return; 1521 } 1522 1523 os_memset(&cfg, 0, sizeof(cfg)); 1524 cfg.wps = ap->er->wps; 1525 cfg.registrar = 1; 1526 ap->wps = wps_init(&cfg); 1527 if (ap->wps == NULL) 1528 return; 1529 ap->wps->ap_settings_cb = wps_er_ap_settings_cb; 1530 ap->wps->ap_settings_cb_ctx = ap; 1531 1532 wps_er_ap_process(ap, m1); 1533 } 1534 1535 1536 static void wps_er_ap_learn(struct wps_er_ap *ap, const char *dev_info) 1537 { 1538 struct wpabuf *info; 1539 enum http_reply_code ret; 1540 1541 wpa_printf(MSG_DEBUG, "WPS ER: Received GetDeviceInfo response (M1) " 1542 "from the AP"); 1543 info = xml_get_base64_item(dev_info, "NewDeviceInfo", &ret); 1544 if (info == NULL) { 1545 wpa_printf(MSG_DEBUG, "WPS ER: Could not extract " 1546 "NewDeviceInfo from GetDeviceInfo response"); 1547 return; 1548 } 1549 1550 ap->m1_handler(ap, info); 1551 wpabuf_free(info); 1552 } 1553 1554 1555 static void wps_er_http_get_dev_info_cb(void *ctx, struct http_client *c, 1556 enum http_client_event event) 1557 { 1558 struct wps_er_ap *ap = ctx; 1559 struct wpabuf *reply; 1560 char *dev_info = NULL; 1561 1562 switch (event) { 1563 case HTTP_CLIENT_OK: 1564 wpa_printf(MSG_DEBUG, "WPS ER: GetDeviceInfo OK"); 1565 reply = http_client_get_body(c); 1566 if (reply == NULL) 1567 break; 1568 dev_info = os_zalloc(wpabuf_len(reply) + 1); 1569 if (dev_info == NULL) 1570 break; 1571 os_memcpy(dev_info, wpabuf_head(reply), wpabuf_len(reply)); 1572 break; 1573 case HTTP_CLIENT_FAILED: 1574 case HTTP_CLIENT_INVALID_REPLY: 1575 case HTTP_CLIENT_TIMEOUT: 1576 wpa_printf(MSG_DEBUG, "WPS ER: GetDeviceInfo failed"); 1577 break; 1578 } 1579 http_client_free(ap->http); 1580 ap->http = NULL; 1581 1582 if (dev_info) { 1583 wps_er_ap_learn(ap, dev_info); 1584 os_free(dev_info); 1585 } 1586 } 1587 1588 1589 static int wps_er_send_get_device_info(struct wps_er_ap *ap, 1590 void (*m1_handler)(struct wps_er_ap *ap, 1591 struct wpabuf *m1)) 1592 { 1593 struct wpabuf *buf; 1594 char *len_ptr, *body_ptr; 1595 struct sockaddr_in dst; 1596 char *url, *path; 1597 1598 if (ap->http) { 1599 wpa_printf(MSG_DEBUG, "WPS ER: Pending HTTP operation ongoing " 1600 "with the AP - cannot get device info"); 1601 return -1; 1602 } 1603 1604 if (ap->control_url == NULL) { 1605 wpa_printf(MSG_DEBUG, "WPS ER: No controlURL for AP"); 1606 return -1; 1607 } 1608 1609 url = http_client_url_parse(ap->control_url, &dst, &path); 1610 if (url == NULL) { 1611 wpa_printf(MSG_DEBUG, "WPS ER: Failed to parse controlURL"); 1612 return -1; 1613 } 1614 1615 buf = wps_er_soap_hdr(NULL, "GetDeviceInfo", NULL, path, &dst, 1616 &len_ptr, &body_ptr); 1617 os_free(url); 1618 if (buf == NULL) 1619 return -1; 1620 1621 wps_er_soap_end(buf, "GetDeviceInfo", len_ptr, body_ptr); 1622 1623 ap->http = http_client_addr(&dst, buf, 10000, 1624 wps_er_http_get_dev_info_cb, ap); 1625 if (ap->http == NULL) { 1626 wpabuf_free(buf); 1627 return -1; 1628 } 1629 1630 ap->m1_handler = m1_handler; 1631 1632 return 0; 1633 } 1634 1635 1636 int wps_er_learn(struct wps_er *er, const u8 *uuid, const u8 *pin, 1637 size_t pin_len) 1638 { 1639 struct wps_er_ap *ap; 1640 1641 if (er == NULL) 1642 return -1; 1643 1644 ap = wps_er_ap_get(er, NULL, uuid); 1645 if (ap == NULL) { 1646 wpa_printf(MSG_DEBUG, "WPS ER: AP not found for learn " 1647 "request"); 1648 return -1; 1649 } 1650 if (ap->wps) { 1651 wpa_printf(MSG_DEBUG, "WPS ER: Pending operation ongoing " 1652 "with the AP - cannot start learn"); 1653 return -1; 1654 } 1655 1656 if (wps_er_send_get_device_info(ap, wps_er_ap_learn_m1) < 0) 1657 return -1; 1658 1659 /* TODO: add PIN without SetSelectedRegistrar trigger to all APs */ 1660 wps_registrar_add_pin(er->wps->registrar, uuid, pin, pin_len, 0); 1661 1662 return 0; 1663 } 1664