$search
00001 /* 00002 * Wi-Fi Protected Setup - External Registrar 00003 * Copyright (c) 2009, Jouni Malinen <j@w1.fi> 00004 * 00005 * This program is free software; you can redistribute it and/or modify 00006 * it under the terms of the GNU General Public License version 2 as 00007 * published by the Free Software Foundation. 00008 * 00009 * Alternatively, this software may be distributed under the terms of BSD 00010 * license. 00011 * 00012 * See README and COPYING for more details. 00013 */ 00014 00015 #include "includes.h" 00016 00017 #include "common.h" 00018 #include "base64.h" 00019 #include "uuid.h" 00020 #include "eloop.h" 00021 #include "httpread.h" 00022 #include "http_client.h" 00023 #include "http_server.h" 00024 #include "upnp_xml.h" 00025 #include "wps_i.h" 00026 #include "wps_upnp.h" 00027 #include "wps_upnp_i.h" 00028 #include "wps_er.h" 00029 00030 00031 static void wps_er_deinit_finish(void *eloop_data, void *user_ctx); 00032 static void wps_er_ap_timeout(void *eloop_data, void *user_ctx); 00033 static void wps_er_sta_timeout(void *eloop_data, void *user_ctx); 00034 static void wps_er_ap_process(struct wps_er_ap *ap, struct wpabuf *msg); 00035 static int wps_er_send_get_device_info(struct wps_er_ap *ap, 00036 void (*m1_handler)(struct wps_er_ap *ap, 00037 struct wpabuf *m1)); 00038 00039 00040 static void wps_er_sta_event(struct wps_context *wps, struct wps_er_sta *sta, 00041 enum wps_event event) 00042 { 00043 union wps_event_data data; 00044 struct wps_event_er_enrollee *ev = &data.enrollee; 00045 00046 if (wps->event_cb == NULL) 00047 return; 00048 00049 os_memset(&data, 0, sizeof(data)); 00050 ev->uuid = sta->uuid; 00051 ev->mac_addr = sta->addr; 00052 ev->m1_received = sta->m1_received; 00053 ev->config_methods = sta->config_methods; 00054 ev->dev_passwd_id = sta->dev_passwd_id; 00055 ev->pri_dev_type = sta->pri_dev_type; 00056 ev->dev_name = sta->dev_name; 00057 ev->manufacturer = sta->manufacturer; 00058 ev->model_name = sta->model_name; 00059 ev->model_number = sta->model_number; 00060 ev->serial_number = sta->serial_number; 00061 wps->event_cb(wps->cb_ctx, event, &data); 00062 } 00063 00064 00065 static struct wps_er_sta * wps_er_sta_get(struct wps_er_ap *ap, const u8 *addr) 00066 { 00067 struct wps_er_sta *sta; 00068 dl_list_for_each(sta, &ap->sta, struct wps_er_sta, list) { 00069 if (os_memcmp(sta->addr, addr, ETH_ALEN) == 0) 00070 return sta; 00071 } 00072 return NULL; 00073 } 00074 00075 00076 static void wps_er_sta_free(struct wps_er_sta *sta) 00077 { 00078 wps_er_sta_event(sta->ap->er->wps, sta, WPS_EV_ER_ENROLLEE_REMOVE); 00079 if (sta->wps) 00080 wps_deinit(sta->wps); 00081 os_free(sta->manufacturer); 00082 os_free(sta->model_name); 00083 os_free(sta->model_number); 00084 os_free(sta->serial_number); 00085 os_free(sta->dev_name); 00086 http_client_free(sta->http); 00087 eloop_cancel_timeout(wps_er_sta_timeout, sta, NULL); 00088 os_free(sta); 00089 } 00090 00091 00092 static void wps_er_sta_remove_all(struct wps_er_ap *ap) 00093 { 00094 struct wps_er_sta *prev, *sta; 00095 dl_list_for_each_safe(sta, prev, &ap->sta, struct wps_er_sta, list) 00096 wps_er_sta_free(sta); 00097 } 00098 00099 00100 static struct wps_er_ap * wps_er_ap_get(struct wps_er *er, 00101 struct in_addr *addr, const u8 *uuid) 00102 { 00103 struct wps_er_ap *ap; 00104 dl_list_for_each(ap, &er->ap, struct wps_er_ap, list) { 00105 if ((addr == NULL || ap->addr.s_addr == addr->s_addr) && 00106 (uuid == NULL || 00107 os_memcmp(uuid, ap->uuid, WPS_UUID_LEN) == 0)) 00108 return ap; 00109 } 00110 return NULL; 00111 } 00112 00113 00114 static struct wps_er_ap * wps_er_ap_get_id(struct wps_er *er, unsigned int id) 00115 { 00116 struct wps_er_ap *ap; 00117 dl_list_for_each(ap, &er->ap, struct wps_er_ap, list) { 00118 if (ap->id == id) 00119 return ap; 00120 } 00121 return NULL; 00122 } 00123 00124 00125 static void wps_er_ap_event(struct wps_context *wps, struct wps_er_ap *ap, 00126 enum wps_event event) 00127 { 00128 union wps_event_data data; 00129 struct wps_event_er_ap *evap = &data.ap; 00130 00131 if (wps->event_cb == NULL) 00132 return; 00133 00134 os_memset(&data, 0, sizeof(data)); 00135 evap->uuid = ap->uuid; 00136 evap->friendly_name = ap->friendly_name; 00137 evap->manufacturer = ap->manufacturer; 00138 evap->manufacturer_url = ap->manufacturer_url; 00139 evap->model_description = ap->model_description; 00140 evap->model_name = ap->model_name; 00141 evap->model_number = ap->model_number; 00142 evap->model_url = ap->model_url; 00143 evap->serial_number = ap->serial_number; 00144 evap->upc = ap->upc; 00145 evap->pri_dev_type = ap->pri_dev_type; 00146 evap->wps_state = ap->wps_state; 00147 evap->mac_addr = ap->mac_addr; 00148 wps->event_cb(wps->cb_ctx, event, &data); 00149 } 00150 00151 00152 static void wps_er_ap_free(struct wps_er_ap *ap) 00153 { 00154 http_client_free(ap->http); 00155 ap->http = NULL; 00156 00157 os_free(ap->location); 00158 os_free(ap->friendly_name); 00159 os_free(ap->manufacturer); 00160 os_free(ap->manufacturer_url); 00161 os_free(ap->model_description); 00162 os_free(ap->model_name); 00163 os_free(ap->model_number); 00164 os_free(ap->model_url); 00165 os_free(ap->serial_number); 00166 os_free(ap->udn); 00167 os_free(ap->upc); 00168 00169 os_free(ap->scpd_url); 00170 os_free(ap->control_url); 00171 os_free(ap->event_sub_url); 00172 00173 os_free(ap->ap_settings); 00174 00175 os_free(ap); 00176 } 00177 00178 00179 static void wps_er_ap_unsubscribed(struct wps_er *er, struct wps_er_ap *ap) 00180 { 00181 wpa_printf(MSG_DEBUG, "WPS ER: Unsubscribed from AP %s (%s)", 00182 inet_ntoa(ap->addr), ap->location); 00183 dl_list_del(&ap->list); 00184 wps_er_ap_free(ap); 00185 00186 if (er->deinitializing && dl_list_empty(&er->ap_unsubscribing)) { 00187 eloop_cancel_timeout(wps_er_deinit_finish, er, NULL); 00188 wps_er_deinit_finish(er, NULL); 00189 } 00190 } 00191 00192 00193 static void wps_er_http_unsubscribe_cb(void *ctx, struct http_client *c, 00194 enum http_client_event event) 00195 { 00196 struct wps_er_ap *ap = ctx; 00197 00198 switch (event) { 00199 case HTTP_CLIENT_OK: 00200 wpa_printf(MSG_DEBUG, "WPS ER: Unsubscribed from events"); 00201 ap->subscribed = 0; 00202 break; 00203 case HTTP_CLIENT_FAILED: 00204 case HTTP_CLIENT_INVALID_REPLY: 00205 case HTTP_CLIENT_TIMEOUT: 00206 wpa_printf(MSG_DEBUG, "WPS ER: Failed to unsubscribe from " 00207 "events"); 00208 break; 00209 } 00210 http_client_free(ap->http); 00211 ap->http = NULL; 00212 00213 /* 00214 * Need to get rid of the AP entry regardless of whether we managed to 00215 * unsubscribe cleanly or not. 00216 */ 00217 wps_er_ap_unsubscribed(ap->er, ap); 00218 } 00219 00220 00221 static void wps_er_ap_unsubscribe(struct wps_er *er, struct wps_er_ap *ap) 00222 { 00223 struct wpabuf *req; 00224 struct sockaddr_in dst; 00225 char *url, *path; 00226 char sid[100]; 00227 00228 if (ap->event_sub_url == NULL) { 00229 wpa_printf(MSG_DEBUG, "WPS ER: No eventSubURL - cannot " 00230 "subscribe"); 00231 goto fail; 00232 } 00233 if (ap->http) { 00234 wpa_printf(MSG_DEBUG, "WPS ER: Pending HTTP request - cannot " 00235 "send subscribe request"); 00236 goto fail; 00237 } 00238 00239 url = http_client_url_parse(ap->event_sub_url, &dst, &path); 00240 if (url == NULL) { 00241 wpa_printf(MSG_DEBUG, "WPS ER: Failed to parse eventSubURL"); 00242 goto fail; 00243 } 00244 00245 req = wpabuf_alloc(os_strlen(ap->event_sub_url) + 1000); 00246 if (req == NULL) { 00247 os_free(url); 00248 goto fail; 00249 } 00250 uuid_bin2str(ap->sid, sid, sizeof(sid)); 00251 wpabuf_printf(req, 00252 "UNSUBSCRIBE %s HTTP/1.1\r\n" 00253 "HOST: %s:%d\r\n" 00254 "SID: uuid:%s\r\n" 00255 "\r\n", 00256 path, inet_ntoa(dst.sin_addr), ntohs(dst.sin_port), sid); 00257 os_free(url); 00258 wpa_hexdump_ascii(MSG_MSGDUMP, "WPS ER: Unsubscription request", 00259 wpabuf_head(req), wpabuf_len(req)); 00260 00261 ap->http = http_client_addr(&dst, req, 1000, 00262 wps_er_http_unsubscribe_cb, ap); 00263 if (ap->http == NULL) { 00264 wpabuf_free(req); 00265 goto fail; 00266 } 00267 return; 00268 00269 fail: 00270 /* 00271 * Need to get rid of the AP entry even when we fail to unsubscribe 00272 * cleanly. 00273 */ 00274 wps_er_ap_unsubscribed(ap->er, ap); 00275 } 00276 00277 static void wps_er_ap_remove_entry(struct wps_er *er, struct wps_er_ap *ap) 00278 { 00279 wpa_printf(MSG_DEBUG, "WPS ER: Removing AP entry for %s (%s)", 00280 inet_ntoa(ap->addr), ap->location); 00281 eloop_cancel_timeout(wps_er_ap_timeout, er, ap); 00282 wps_er_sta_remove_all(ap); 00283 wps_er_ap_event(er->wps, ap, WPS_EV_ER_AP_REMOVE); 00284 http_client_free(ap->http); 00285 ap->http = NULL; 00286 if (ap->wps) { 00287 wps_deinit(ap->wps); 00288 ap->wps = NULL; 00289 } 00290 00291 dl_list_del(&ap->list); 00292 if (ap->subscribed) { 00293 dl_list_add(&er->ap_unsubscribing, &ap->list); 00294 wps_er_ap_unsubscribe(er, ap); 00295 } else 00296 wps_er_ap_free(ap); 00297 } 00298 00299 00300 static void wps_er_ap_timeout(void *eloop_data, void *user_ctx) 00301 { 00302 struct wps_er *er = eloop_data; 00303 struct wps_er_ap *ap = user_ctx; 00304 wpa_printf(MSG_DEBUG, "WPS ER: AP advertisement timed out"); 00305 wps_er_ap_remove_entry(er, ap); 00306 } 00307 00308 00309 static int wps_er_get_sid(struct wps_er_ap *ap, char *sid) 00310 { 00311 char *pos; 00312 char txt[100]; 00313 00314 if (!sid) { 00315 wpa_printf(MSG_DEBUG, "WPS ER: No SID received from %s (%s)", 00316 inet_ntoa(ap->addr), ap->location); 00317 return -1; 00318 } 00319 00320 pos = os_strstr(sid, "uuid:"); 00321 if (!pos) { 00322 wpa_printf(MSG_DEBUG, "WPS ER: Invalid SID received from " 00323 "%s (%s): '%s'", inet_ntoa(ap->addr), ap->location, 00324 sid); 00325 return -1; 00326 } 00327 00328 pos += 5; 00329 if (uuid_str2bin(pos, ap->sid) < 0) { 00330 wpa_printf(MSG_DEBUG, "WPS ER: Invalid SID received from " 00331 "%s (%s): '%s'", inet_ntoa(ap->addr), ap->location, 00332 sid); 00333 return -1; 00334 } 00335 00336 uuid_bin2str(ap->sid, txt, sizeof(txt)); 00337 wpa_printf(MSG_DEBUG, "WPS ER: SID for subscription with %s (%s): %s", 00338 inet_ntoa(ap->addr), ap->location, txt); 00339 00340 return 0; 00341 } 00342 00343 00344 static void wps_er_http_subscribe_cb(void *ctx, struct http_client *c, 00345 enum http_client_event event) 00346 { 00347 struct wps_er_ap *ap = ctx; 00348 00349 switch (event) { 00350 case HTTP_CLIENT_OK: 00351 wpa_printf(MSG_DEBUG, "WPS ER: Subscribed to events"); 00352 ap->subscribed = 1; 00353 wps_er_get_sid(ap, http_client_get_hdr_line(c, "SID")); 00354 wps_er_ap_event(ap->er->wps, ap, WPS_EV_ER_AP_ADD); 00355 break; 00356 case HTTP_CLIENT_FAILED: 00357 case HTTP_CLIENT_INVALID_REPLY: 00358 case HTTP_CLIENT_TIMEOUT: 00359 wpa_printf(MSG_DEBUG, "WPS ER: Failed to subscribe to events"); 00360 break; 00361 } 00362 http_client_free(ap->http); 00363 ap->http = NULL; 00364 } 00365 00366 00367 static void wps_er_subscribe(struct wps_er_ap *ap) 00368 { 00369 struct wpabuf *req; 00370 struct sockaddr_in dst; 00371 char *url, *path; 00372 00373 if (ap->event_sub_url == NULL) { 00374 wpa_printf(MSG_DEBUG, "WPS ER: No eventSubURL - cannot " 00375 "subscribe"); 00376 return; 00377 } 00378 if (ap->http) { 00379 wpa_printf(MSG_DEBUG, "WPS ER: Pending HTTP request - cannot " 00380 "send subscribe request"); 00381 return; 00382 } 00383 00384 url = http_client_url_parse(ap->event_sub_url, &dst, &path); 00385 if (url == NULL) { 00386 wpa_printf(MSG_DEBUG, "WPS ER: Failed to parse eventSubURL"); 00387 return; 00388 } 00389 00390 req = wpabuf_alloc(os_strlen(ap->event_sub_url) + 1000); 00391 if (req == NULL) { 00392 os_free(url); 00393 return; 00394 } 00395 wpabuf_printf(req, 00396 "SUBSCRIBE %s HTTP/1.1\r\n" 00397 "HOST: %s:%d\r\n" 00398 "CALLBACK: <http://%s:%d/event/%u/%u>\r\n" 00399 "NT: upnp:event\r\n" 00400 "TIMEOUT: Second-%d\r\n" 00401 "\r\n", 00402 path, inet_ntoa(dst.sin_addr), ntohs(dst.sin_port), 00403 ap->er->ip_addr_text, ap->er->http_port, 00404 ap->er->event_id, ap->id, 1800); 00405 os_free(url); 00406 wpa_hexdump_ascii(MSG_MSGDUMP, "WPS ER: Subscription request", 00407 wpabuf_head(req), wpabuf_len(req)); 00408 00409 ap->http = http_client_addr(&dst, req, 1000, wps_er_http_subscribe_cb, 00410 ap); 00411 if (ap->http == NULL) 00412 wpabuf_free(req); 00413 } 00414 00415 00416 static void wps_er_ap_get_m1(struct wps_er_ap *ap, struct wpabuf *m1) 00417 { 00418 struct wps_parse_attr attr; 00419 00420 if (wps_parse_msg(m1, &attr) < 0) { 00421 wpa_printf(MSG_DEBUG, "WPS ER: Failed to parse M1"); 00422 return; 00423 } 00424 if (attr.primary_dev_type) 00425 os_memcpy(ap->pri_dev_type, attr.primary_dev_type, 8); 00426 if (attr.wps_state) 00427 ap->wps_state = *attr.wps_state; 00428 if (attr.mac_addr) 00429 os_memcpy(ap->mac_addr, attr.mac_addr, ETH_ALEN); 00430 00431 wps_er_subscribe(ap); 00432 } 00433 00434 00435 static void wps_er_get_device_info(struct wps_er_ap *ap) 00436 { 00437 wps_er_send_get_device_info(ap, wps_er_ap_get_m1); 00438 } 00439 00440 00441 static void wps_er_parse_device_description(struct wps_er_ap *ap, 00442 struct wpabuf *reply) 00443 { 00444 /* Note: reply includes null termination after the buffer data */ 00445 const char *data = wpabuf_head(reply); 00446 char *pos; 00447 00448 wpa_hexdump_ascii(MSG_MSGDUMP, "WPS ER: Device info", 00449 wpabuf_head(reply), wpabuf_len(reply)); 00450 00451 ap->friendly_name = xml_get_first_item(data, "friendlyName"); 00452 wpa_printf(MSG_DEBUG, "WPS ER: friendlyName='%s'", ap->friendly_name); 00453 00454 ap->manufacturer = xml_get_first_item(data, "manufacturer"); 00455 wpa_printf(MSG_DEBUG, "WPS ER: manufacturer='%s'", ap->manufacturer); 00456 00457 ap->manufacturer_url = xml_get_first_item(data, "manufacturerURL"); 00458 wpa_printf(MSG_DEBUG, "WPS ER: manufacturerURL='%s'", 00459 ap->manufacturer_url); 00460 00461 ap->model_description = xml_get_first_item(data, "modelDescription"); 00462 wpa_printf(MSG_DEBUG, "WPS ER: modelDescription='%s'", 00463 ap->model_description); 00464 00465 ap->model_name = xml_get_first_item(data, "modelName"); 00466 wpa_printf(MSG_DEBUG, "WPS ER: modelName='%s'", ap->model_name); 00467 00468 ap->model_number = xml_get_first_item(data, "modelNumber"); 00469 wpa_printf(MSG_DEBUG, "WPS ER: modelNumber='%s'", ap->model_number); 00470 00471 ap->model_url = xml_get_first_item(data, "modelURL"); 00472 wpa_printf(MSG_DEBUG, "WPS ER: modelURL='%s'", ap->model_url); 00473 00474 ap->serial_number = xml_get_first_item(data, "serialNumber"); 00475 wpa_printf(MSG_DEBUG, "WPS ER: serialNumber='%s'", ap->serial_number); 00476 00477 ap->udn = xml_get_first_item(data, "UDN"); 00478 wpa_printf(MSG_DEBUG, "WPS ER: UDN='%s'", ap->udn); 00479 pos = os_strstr(ap->udn, "uuid:"); 00480 if (pos) { 00481 pos += 5; 00482 if (uuid_str2bin(pos, ap->uuid) < 0) 00483 wpa_printf(MSG_DEBUG, "WPS ER: Invalid UUID in UDN"); 00484 } 00485 00486 ap->upc = xml_get_first_item(data, "UPC"); 00487 wpa_printf(MSG_DEBUG, "WPS ER: UPC='%s'", ap->upc); 00488 00489 ap->scpd_url = http_link_update( 00490 xml_get_first_item(data, "SCPDURL"), ap->location); 00491 wpa_printf(MSG_DEBUG, "WPS ER: SCPDURL='%s'", ap->scpd_url); 00492 00493 ap->control_url = http_link_update( 00494 xml_get_first_item(data, "controlURL"), ap->location); 00495 wpa_printf(MSG_DEBUG, "WPS ER: controlURL='%s'", ap->control_url); 00496 00497 ap->event_sub_url = http_link_update( 00498 xml_get_first_item(data, "eventSubURL"), ap->location); 00499 wpa_printf(MSG_DEBUG, "WPS ER: eventSubURL='%s'", ap->event_sub_url); 00500 } 00501 00502 00503 static void wps_er_http_dev_desc_cb(void *ctx, struct http_client *c, 00504 enum http_client_event event) 00505 { 00506 struct wps_er_ap *ap = ctx; 00507 struct wpabuf *reply; 00508 int ok = 0; 00509 00510 switch (event) { 00511 case HTTP_CLIENT_OK: 00512 reply = http_client_get_body(c); 00513 if (reply == NULL) 00514 break; 00515 wps_er_parse_device_description(ap, reply); 00516 ok = 1; 00517 break; 00518 case HTTP_CLIENT_FAILED: 00519 case HTTP_CLIENT_INVALID_REPLY: 00520 case HTTP_CLIENT_TIMEOUT: 00521 wpa_printf(MSG_DEBUG, "WPS ER: Failed to fetch device info"); 00522 break; 00523 } 00524 http_client_free(ap->http); 00525 ap->http = NULL; 00526 if (ok) 00527 wps_er_get_device_info(ap); 00528 } 00529 00530 00531 void wps_er_ap_add(struct wps_er *er, const u8 *uuid, struct in_addr *addr, 00532 const char *location, int max_age) 00533 { 00534 struct wps_er_ap *ap; 00535 00536 ap = wps_er_ap_get(er, addr, uuid); 00537 if (ap) { 00538 /* Update advertisement timeout */ 00539 eloop_cancel_timeout(wps_er_ap_timeout, er, ap); 00540 eloop_register_timeout(max_age, 0, wps_er_ap_timeout, er, ap); 00541 return; 00542 } 00543 00544 ap = os_zalloc(sizeof(*ap)); 00545 if (ap == NULL) 00546 return; 00547 dl_list_init(&ap->sta); 00548 ap->er = er; 00549 ap->id = ++er->next_ap_id; 00550 ap->location = os_strdup(location); 00551 if (ap->location == NULL) { 00552 os_free(ap); 00553 return; 00554 } 00555 dl_list_add(&er->ap, &ap->list); 00556 00557 ap->addr.s_addr = addr->s_addr; 00558 os_memcpy(ap->uuid, uuid, WPS_UUID_LEN); 00559 eloop_register_timeout(max_age, 0, wps_er_ap_timeout, er, ap); 00560 00561 wpa_printf(MSG_DEBUG, "WPS ER: Added AP entry for %s (%s)", 00562 inet_ntoa(ap->addr), ap->location); 00563 00564 /* Fetch device description */ 00565 ap->http = http_client_url(ap->location, NULL, 10000, 00566 wps_er_http_dev_desc_cb, ap); 00567 } 00568 00569 00570 void wps_er_ap_remove(struct wps_er *er, struct in_addr *addr) 00571 { 00572 struct wps_er_ap *ap; 00573 dl_list_for_each(ap, &er->ap, struct wps_er_ap, list) { 00574 if (ap->addr.s_addr == addr->s_addr) { 00575 wps_er_ap_remove_entry(er, ap); 00576 return; 00577 } 00578 } 00579 } 00580 00581 00582 static void wps_er_ap_remove_all(struct wps_er *er) 00583 { 00584 struct wps_er_ap *prev, *ap; 00585 dl_list_for_each_safe(ap, prev, &er->ap, struct wps_er_ap, list) 00586 wps_er_ap_remove_entry(er, ap); 00587 } 00588 00589 00590 static void http_put_date(struct wpabuf *buf) 00591 { 00592 wpabuf_put_str(buf, "Date: "); 00593 format_date(buf); 00594 wpabuf_put_str(buf, "\r\n"); 00595 } 00596 00597 00598 static void wps_er_http_resp_not_found(struct http_request *req) 00599 { 00600 struct wpabuf *buf; 00601 buf = wpabuf_alloc(200); 00602 if (buf == NULL) { 00603 http_request_deinit(req); 00604 return; 00605 } 00606 00607 wpabuf_put_str(buf, 00608 "HTTP/1.1 404 Not Found\r\n" 00609 "Server: unspecified, UPnP/1.0, unspecified\r\n" 00610 "Connection: close\r\n"); 00611 http_put_date(buf); 00612 wpabuf_put_str(buf, "\r\n"); 00613 http_request_send_and_deinit(req, buf); 00614 } 00615 00616 00617 static void wps_er_http_resp_ok(struct http_request *req) 00618 { 00619 struct wpabuf *buf; 00620 buf = wpabuf_alloc(200); 00621 if (buf == NULL) { 00622 http_request_deinit(req); 00623 return; 00624 } 00625 00626 wpabuf_put_str(buf, 00627 "HTTP/1.1 200 OK\r\n" 00628 "Server: unspecified, UPnP/1.0, unspecified\r\n" 00629 "Connection: close\r\n" 00630 "Content-Length: 0\r\n"); 00631 http_put_date(buf); 00632 wpabuf_put_str(buf, "\r\n"); 00633 http_request_send_and_deinit(req, buf); 00634 } 00635 00636 00637 static void wps_er_sta_timeout(void *eloop_data, void *user_ctx) 00638 { 00639 struct wps_er_sta *sta = eloop_data; 00640 wpa_printf(MSG_DEBUG, "WPS ER: STA entry timed out"); 00641 dl_list_del(&sta->list); 00642 wps_er_sta_free(sta); 00643 } 00644 00645 00646 static struct wps_er_sta * wps_er_add_sta_data(struct wps_er_ap *ap, 00647 const u8 *addr, 00648 struct wps_parse_attr *attr, 00649 int probe_req) 00650 { 00651 struct wps_er_sta *sta = wps_er_sta_get(ap, addr); 00652 int new_sta = 0; 00653 int m1; 00654 00655 m1 = !probe_req && attr->msg_type && *attr->msg_type == WPS_M1; 00656 00657 if (sta == NULL) { 00658 /* 00659 * Only allow new STA entry to be added based on Probe Request 00660 * or M1. This will filter out bogus events and anything that 00661 * may have been ongoing at the time ER subscribed for events. 00662 */ 00663 if (!probe_req && !m1) 00664 return NULL; 00665 00666 sta = os_zalloc(sizeof(*sta)); 00667 if (sta == NULL) 00668 return NULL; 00669 os_memcpy(sta->addr, addr, ETH_ALEN); 00670 sta->ap = ap; 00671 dl_list_add(&ap->sta, &sta->list); 00672 new_sta = 1; 00673 } 00674 00675 if (m1) 00676 sta->m1_received = 1; 00677 00678 if (attr->config_methods && (!probe_req || !sta->m1_received)) 00679 sta->config_methods = WPA_GET_BE16(attr->config_methods); 00680 if (attr->uuid_e && (!probe_req || !sta->m1_received)) 00681 os_memcpy(sta->uuid, attr->uuid_e, WPS_UUID_LEN); 00682 if (attr->primary_dev_type && (!probe_req || !sta->m1_received)) 00683 os_memcpy(sta->pri_dev_type, attr->primary_dev_type, 8); 00684 if (attr->dev_password_id && (!probe_req || !sta->m1_received)) 00685 sta->dev_passwd_id = WPA_GET_BE16(attr->dev_password_id); 00686 00687 if (attr->manufacturer) { 00688 os_free(sta->manufacturer); 00689 sta->manufacturer = os_malloc(attr->manufacturer_len + 1); 00690 if (sta->manufacturer) { 00691 os_memcpy(sta->manufacturer, attr->manufacturer, 00692 attr->manufacturer_len); 00693 sta->manufacturer[attr->manufacturer_len] = '\0'; 00694 } 00695 } 00696 00697 if (attr->model_name) { 00698 os_free(sta->model_name); 00699 sta->model_name = os_malloc(attr->model_name_len + 1); 00700 if (sta->model_name) { 00701 os_memcpy(sta->model_name, attr->model_name, 00702 attr->model_name_len); 00703 sta->model_name[attr->model_name_len] = '\0'; 00704 } 00705 } 00706 00707 if (attr->model_number) { 00708 os_free(sta->model_number); 00709 sta->model_number = os_malloc(attr->model_number_len + 1); 00710 if (sta->model_number) { 00711 os_memcpy(sta->model_number, attr->model_number, 00712 attr->model_number_len); 00713 sta->model_number[attr->model_number_len] = '\0'; 00714 } 00715 } 00716 00717 if (attr->serial_number) { 00718 os_free(sta->serial_number); 00719 sta->serial_number = os_malloc(attr->serial_number_len + 1); 00720 if (sta->serial_number) { 00721 os_memcpy(sta->serial_number, attr->serial_number, 00722 attr->serial_number_len); 00723 sta->serial_number[attr->serial_number_len] = '\0'; 00724 } 00725 } 00726 00727 if (attr->dev_name) { 00728 os_free(sta->dev_name); 00729 sta->dev_name = os_malloc(attr->dev_name_len + 1); 00730 if (sta->dev_name) { 00731 os_memcpy(sta->dev_name, attr->dev_name, 00732 attr->dev_name_len); 00733 sta->dev_name[attr->dev_name_len] = '\0'; 00734 } 00735 } 00736 00737 eloop_cancel_timeout(wps_er_sta_timeout, sta, NULL); 00738 eloop_register_timeout(300, 0, wps_er_sta_timeout, sta, NULL); 00739 00740 if (m1 || new_sta) 00741 wps_er_sta_event(ap->er->wps, sta, WPS_EV_ER_ENROLLEE_ADD); 00742 00743 return sta; 00744 } 00745 00746 00747 static void wps_er_process_wlanevent_probe_req(struct wps_er_ap *ap, 00748 const u8 *addr, 00749 struct wpabuf *msg) 00750 { 00751 struct wps_parse_attr attr; 00752 00753 wpa_printf(MSG_DEBUG, "WPS ER: WLANEvent - Probe Request - from " 00754 MACSTR, MAC2STR(addr)); 00755 wpa_hexdump_buf(MSG_MSGDUMP, "WPS ER: WLANEvent - Enrollee's message " 00756 "(TLVs from Probe Request)", msg); 00757 00758 if (wps_parse_msg(msg, &attr) < 0) { 00759 wpa_printf(MSG_DEBUG, "WPS ER: Failed to parse TLVs in " 00760 "WLANEvent message"); 00761 return; 00762 } 00763 00764 wps_er_add_sta_data(ap, addr, &attr, 1); 00765 } 00766 00767 00768 static void wps_er_http_put_wlan_response_cb(void *ctx, struct http_client *c, 00769 enum http_client_event event) 00770 { 00771 struct wps_er_sta *sta = ctx; 00772 00773 switch (event) { 00774 case HTTP_CLIENT_OK: 00775 wpa_printf(MSG_DEBUG, "WPS ER: PutWLANResponse OK"); 00776 break; 00777 case HTTP_CLIENT_FAILED: 00778 case HTTP_CLIENT_INVALID_REPLY: 00779 case HTTP_CLIENT_TIMEOUT: 00780 wpa_printf(MSG_DEBUG, "WPS ER: PutWLANResponse failed"); 00781 break; 00782 } 00783 http_client_free(sta->http); 00784 sta->http = NULL; 00785 } 00786 00787 00788 static const char *soap_prefix = 00789 "<?xml version=\"1.0\"?>\n" 00790 "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" " 00791 "s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">\n" 00792 "<s:Body>\n"; 00793 static const char *soap_postfix = 00794 "</s:Body>\n</s:Envelope>\n"; 00795 static const char *urn_wfawlanconfig = 00796 "urn:schemas-wifialliance-org:service:WFAWLANConfig:1"; 00797 00798 static struct wpabuf * wps_er_soap_hdr(const struct wpabuf *msg, 00799 const char *name, const char *arg_name, 00800 const char *path, 00801 const struct sockaddr_in *dst, 00802 char **len_ptr, char **body_ptr) 00803 { 00804 unsigned char *encoded; 00805 size_t encoded_len; 00806 struct wpabuf *buf; 00807 00808 if (msg) { 00809 encoded = base64_encode(wpabuf_head(msg), wpabuf_len(msg), 00810 &encoded_len); 00811 if (encoded == NULL) 00812 return NULL; 00813 } else { 00814 encoded = NULL; 00815 encoded_len = 0; 00816 } 00817 00818 buf = wpabuf_alloc(1000 + encoded_len); 00819 if (buf == NULL) { 00820 os_free(encoded); 00821 return NULL; 00822 } 00823 00824 wpabuf_printf(buf, 00825 "POST %s HTTP/1.1\r\n" 00826 "Host: %s:%d\r\n" 00827 "Content-Type: text/xml; charset=\"utf-8\"\r\n" 00828 "Content-Length: ", 00829 path, inet_ntoa(dst->sin_addr), ntohs(dst->sin_port)); 00830 00831 *len_ptr = wpabuf_put(buf, 0); 00832 wpabuf_printf(buf, 00833 " \r\n" 00834 "SOAPACTION: \"%s#%s\"\r\n" 00835 "\r\n", 00836 urn_wfawlanconfig, name); 00837 00838 *body_ptr = wpabuf_put(buf, 0); 00839 00840 wpabuf_put_str(buf, soap_prefix); 00841 wpabuf_printf(buf, "<u:%s xmlns:u=\"", name); 00842 wpabuf_put_str(buf, urn_wfawlanconfig); 00843 wpabuf_put_str(buf, "\">\n"); 00844 if (encoded) { 00845 wpabuf_printf(buf, "<%s>%s</%s>\n", 00846 arg_name, (char *) encoded, arg_name); 00847 os_free(encoded); 00848 } 00849 00850 return buf; 00851 } 00852 00853 00854 static void wps_er_soap_end(struct wpabuf *buf, const char *name, 00855 char *len_ptr, char *body_ptr) 00856 { 00857 char len_buf[10]; 00858 wpabuf_printf(buf, "</u:%s>\n", name); 00859 wpabuf_put_str(buf, soap_postfix); 00860 os_snprintf(len_buf, sizeof(len_buf), "%d", 00861 (int) ((char *) wpabuf_put(buf, 0) - body_ptr)); 00862 os_memcpy(len_ptr, len_buf, os_strlen(len_buf)); 00863 } 00864 00865 00866 static void wps_er_sta_send_msg(struct wps_er_sta *sta, struct wpabuf *msg) 00867 { 00868 struct wpabuf *buf; 00869 char *len_ptr, *body_ptr; 00870 struct sockaddr_in dst; 00871 char *url, *path; 00872 00873 if (sta->http) { 00874 wpa_printf(MSG_DEBUG, "WPS ER: Pending HTTP request for STA - " 00875 "ignore new request"); 00876 wpabuf_free(msg); 00877 return; 00878 } 00879 00880 if (sta->ap->control_url == NULL) { 00881 wpa_printf(MSG_DEBUG, "WPS ER: No controlURL for AP"); 00882 wpabuf_free(msg); 00883 return; 00884 } 00885 00886 url = http_client_url_parse(sta->ap->control_url, &dst, &path); 00887 if (url == NULL) { 00888 wpa_printf(MSG_DEBUG, "WPS ER: Failed to parse controlURL"); 00889 wpabuf_free(msg); 00890 return; 00891 } 00892 00893 buf = wps_er_soap_hdr(msg, "PutWLANResponse", "NewMessage", path, &dst, 00894 &len_ptr, &body_ptr); 00895 wpabuf_free(msg); 00896 os_free(url); 00897 if (buf == NULL) 00898 return; 00899 wpabuf_printf(buf, "<NewWLANEventType>%d</NewWLANEventType>\n", 00900 UPNP_WPS_WLANEVENT_TYPE_EAP); 00901 wpabuf_printf(buf, "<NewWLANEventMAC>" MACSTR "</NewWLANEventMAC>\n", 00902 MAC2STR(sta->addr)); 00903 00904 wps_er_soap_end(buf, "PutWLANResponse", len_ptr, body_ptr); 00905 00906 sta->http = http_client_addr(&dst, buf, 1000, 00907 wps_er_http_put_wlan_response_cb, sta); 00908 if (sta->http == NULL) 00909 wpabuf_free(buf); 00910 } 00911 00912 00913 static void wps_er_sta_process(struct wps_er_sta *sta, struct wpabuf *msg, 00914 enum wsc_op_code op_code) 00915 { 00916 enum wps_process_res res; 00917 00918 res = wps_process_msg(sta->wps, op_code, msg); 00919 if (res == WPS_CONTINUE) { 00920 struct wpabuf *next = wps_get_msg(sta->wps, &op_code); 00921 if (next) 00922 wps_er_sta_send_msg(sta, next); 00923 } else { 00924 wpa_printf(MSG_DEBUG, "WPS ER: Protocol run %s with the " 00925 "enrollee (res=%d)", 00926 res == WPS_DONE ? "succeeded" : "failed", res); 00927 wps_deinit(sta->wps); 00928 sta->wps = NULL; 00929 if (res == WPS_DONE) { 00930 /* Remove the STA entry after short timeout */ 00931 eloop_cancel_timeout(wps_er_sta_timeout, sta, NULL); 00932 eloop_register_timeout(10, 0, wps_er_sta_timeout, sta, 00933 NULL); 00934 } 00935 } 00936 } 00937 00938 00939 static void wps_er_sta_start(struct wps_er_sta *sta, struct wpabuf *msg) 00940 { 00941 struct wps_config cfg; 00942 00943 if (sta->wps) 00944 wps_deinit(sta->wps); 00945 00946 os_memset(&cfg, 0, sizeof(cfg)); 00947 cfg.wps = sta->ap->er->wps; 00948 cfg.registrar = 1; 00949 cfg.peer_addr = sta->addr; 00950 00951 sta->wps = wps_init(&cfg); 00952 if (sta->wps == NULL) 00953 return; 00954 sta->wps->er = 1; 00955 sta->wps->use_cred = sta->ap->ap_settings; 00956 00957 wps_er_sta_process(sta, msg, WSC_MSG); 00958 } 00959 00960 00961 static void wps_er_process_wlanevent_eap(struct wps_er_ap *ap, const u8 *addr, 00962 struct wpabuf *msg) 00963 { 00964 struct wps_parse_attr attr; 00965 struct wps_er_sta *sta; 00966 00967 wpa_printf(MSG_DEBUG, "WPS ER: WLANEvent - EAP - from " MACSTR, 00968 MAC2STR(addr)); 00969 wpa_hexdump_buf(MSG_MSGDUMP, "WPS ER: WLANEvent - Enrollee's message " 00970 "(TLVs from EAP-WSC)", msg); 00971 00972 if (wps_parse_msg(msg, &attr) < 0) { 00973 wpa_printf(MSG_DEBUG, "WPS ER: Failed to parse TLVs in " 00974 "WLANEvent message"); 00975 return; 00976 } 00977 00978 sta = wps_er_add_sta_data(ap, addr, &attr, 0); 00979 if (sta == NULL) 00980 return; 00981 00982 if (attr.msg_type && *attr.msg_type == WPS_M1) 00983 wps_er_sta_start(sta, msg); 00984 else if (sta->wps) { 00985 enum wsc_op_code op_code = WSC_MSG; 00986 if (attr.msg_type) { 00987 switch (*attr.msg_type) { 00988 case WPS_WSC_ACK: 00989 op_code = WSC_ACK; 00990 break; 00991 case WPS_WSC_NACK: 00992 op_code = WSC_NACK; 00993 break; 00994 case WPS_WSC_DONE: 00995 op_code = WSC_Done; 00996 break; 00997 } 00998 } 00999 wps_er_sta_process(sta, msg, op_code); 01000 } 01001 } 01002 01003 01004 static void wps_er_process_wlanevent(struct wps_er_ap *ap, 01005 struct wpabuf *event) 01006 { 01007 u8 *data; 01008 u8 wlan_event_type; 01009 u8 wlan_event_mac[ETH_ALEN]; 01010 struct wpabuf msg; 01011 01012 wpa_hexdump(MSG_MSGDUMP, "WPS ER: Received WLANEvent", 01013 wpabuf_head(event), wpabuf_len(event)); 01014 if (wpabuf_len(event) < 1 + 17) { 01015 wpa_printf(MSG_DEBUG, "WPS ER: Too short WLANEvent"); 01016 return; 01017 } 01018 01019 data = wpabuf_mhead(event); 01020 wlan_event_type = data[0]; 01021 if (hwaddr_aton((char *) data + 1, wlan_event_mac) < 0) { 01022 wpa_printf(MSG_DEBUG, "WPS ER: Invalid WLANEventMAC in " 01023 "WLANEvent"); 01024 return; 01025 } 01026 01027 wpabuf_set(&msg, data + 1 + 17, wpabuf_len(event) - (1 + 17)); 01028 01029 switch (wlan_event_type) { 01030 case 1: 01031 wps_er_process_wlanevent_probe_req(ap, wlan_event_mac, &msg); 01032 break; 01033 case 2: 01034 wps_er_process_wlanevent_eap(ap, wlan_event_mac, &msg); 01035 break; 01036 default: 01037 wpa_printf(MSG_DEBUG, "WPS ER: Unknown WLANEventType %d", 01038 wlan_event_type); 01039 break; 01040 } 01041 } 01042 01043 01044 static void wps_er_http_event(struct wps_er *er, struct http_request *req, 01045 unsigned int ap_id) 01046 { 01047 struct wps_er_ap *ap = wps_er_ap_get_id(er, ap_id); 01048 struct wpabuf *event; 01049 enum http_reply_code ret; 01050 01051 if (ap == NULL) { 01052 wpa_printf(MSG_DEBUG, "WPS ER: HTTP event from unknown AP id " 01053 "%u", ap_id); 01054 wps_er_http_resp_not_found(req); 01055 return; 01056 } 01057 wpa_printf(MSG_MSGDUMP, "WPS ER: HTTP event from AP id %u: %s", 01058 ap_id, http_request_get_data(req)); 01059 01060 event = xml_get_base64_item(http_request_get_data(req), "WLANEvent", 01061 &ret); 01062 if (event == NULL) { 01063 wpa_printf(MSG_DEBUG, "WPS ER: Could not extract WLANEvent " 01064 "from the event notification"); 01065 /* 01066 * Reply with OK anyway to avoid getting unregistered from 01067 * events. 01068 */ 01069 wps_er_http_resp_ok(req); 01070 return; 01071 } 01072 01073 wps_er_process_wlanevent(ap, event); 01074 01075 wpabuf_free(event); 01076 wps_er_http_resp_ok(req); 01077 } 01078 01079 01080 static void wps_er_http_notify(struct wps_er *er, struct http_request *req) 01081 { 01082 char *uri = http_request_get_uri(req); 01083 01084 if (os_strncmp(uri, "/event/", 7) == 0) { 01085 unsigned int event_id; 01086 char *pos; 01087 event_id = atoi(uri + 7); 01088 if (event_id != er->event_id) { 01089 wpa_printf(MSG_DEBUG, "WPS ER: HTTP event for an " 01090 "unknown event id %u", event_id); 01091 return; 01092 } 01093 pos = os_strchr(uri + 7, '/'); 01094 if (pos == NULL) 01095 return; 01096 pos++; 01097 wps_er_http_event(er, req, atoi(pos)); 01098 } else { 01099 wpa_printf(MSG_DEBUG, "WPS ER: Unknown HTTP NOTIFY for '%s'", 01100 uri); 01101 wps_er_http_resp_not_found(req); 01102 } 01103 } 01104 01105 01106 static void wps_er_http_req(void *ctx, struct http_request *req) 01107 { 01108 struct wps_er *er = ctx; 01109 struct sockaddr_in *cli = http_request_get_cli_addr(req); 01110 enum httpread_hdr_type type = http_request_get_type(req); 01111 struct wpabuf *buf; 01112 01113 wpa_printf(MSG_DEBUG, "WPS ER: HTTP request: '%s' (type %d) from " 01114 "%s:%d", 01115 http_request_get_uri(req), type, 01116 inet_ntoa(cli->sin_addr), ntohs(cli->sin_port)); 01117 01118 switch (type) { 01119 case HTTPREAD_HDR_TYPE_NOTIFY: 01120 wps_er_http_notify(er, req); 01121 break; 01122 default: 01123 wpa_printf(MSG_DEBUG, "WPS ER: Unsupported HTTP request type " 01124 "%d", type); 01125 buf = wpabuf_alloc(200); 01126 if (buf == NULL) { 01127 http_request_deinit(req); 01128 return; 01129 } 01130 wpabuf_put_str(buf, 01131 "HTTP/1.1 501 Unimplemented\r\n" 01132 "Connection: close\r\n"); 01133 http_put_date(buf); 01134 wpabuf_put_str(buf, "\r\n"); 01135 http_request_send_and_deinit(req, buf); 01136 break; 01137 } 01138 } 01139 01140 01141 struct wps_er * 01142 wps_er_init(struct wps_context *wps, const char *ifname) 01143 { 01144 struct wps_er *er; 01145 struct in_addr addr; 01146 01147 er = os_zalloc(sizeof(*er)); 01148 if (er == NULL) 01149 return NULL; 01150 dl_list_init(&er->ap); 01151 dl_list_init(&er->ap_unsubscribing); 01152 01153 er->multicast_sd = -1; 01154 er->ssdp_sd = -1; 01155 01156 os_strlcpy(er->ifname, ifname, sizeof(er->ifname)); 01157 er->wps = wps; 01158 if (os_get_random((unsigned char *) &er->event_id, 01159 sizeof(er->event_id)) < 0) { 01160 wps_er_deinit(er, NULL, NULL); 01161 return NULL; 01162 } 01163 01164 if (get_netif_info(ifname, &er->ip_addr, &er->ip_addr_text, 01165 er->mac_addr)) { 01166 wpa_printf(MSG_INFO, "WPS UPnP: Could not get IP/MAC address " 01167 "for %s. Does it have IP address?", ifname); 01168 wps_er_deinit(er, NULL, NULL); 01169 return NULL; 01170 } 01171 01172 if (wps_er_ssdp_init(er) < 0) { 01173 wps_er_deinit(er, NULL, NULL); 01174 return NULL; 01175 } 01176 01177 addr.s_addr = er->ip_addr; 01178 er->http_srv = http_server_init(&addr, -1, wps_er_http_req, er); 01179 if (er->http_srv == NULL) { 01180 wps_er_deinit(er, NULL, NULL); 01181 return NULL; 01182 } 01183 er->http_port = http_server_get_port(er->http_srv); 01184 01185 wpa_printf(MSG_DEBUG, "WPS ER: Start (ifname=%s ip_addr=%s)", 01186 er->ifname, er->ip_addr_text); 01187 01188 return er; 01189 } 01190 01191 01192 void wps_er_refresh(struct wps_er *er) 01193 { 01194 struct wps_er_ap *ap; 01195 struct wps_er_sta *sta; 01196 01197 dl_list_for_each(ap, &er->ap, struct wps_er_ap, list) { 01198 wps_er_ap_event(er->wps, ap, WPS_EV_ER_AP_ADD); 01199 dl_list_for_each(sta, &ap->sta, struct wps_er_sta, list) 01200 wps_er_sta_event(er->wps, sta, WPS_EV_ER_ENROLLEE_ADD); 01201 } 01202 01203 wps_er_send_ssdp_msearch(er); 01204 } 01205 01206 01207 static void wps_er_deinit_finish(void *eloop_data, void *user_ctx) 01208 { 01209 struct wps_er *er = eloop_data; 01210 void (*deinit_done_cb)(void *ctx); 01211 void *deinit_done_ctx; 01212 01213 wpa_printf(MSG_DEBUG, "WPS ER: Finishing deinit"); 01214 01215 deinit_done_cb = er->deinit_done_cb; 01216 deinit_done_ctx = er->deinit_done_ctx; 01217 os_free(er->ip_addr_text); 01218 os_free(er); 01219 01220 if (deinit_done_cb) 01221 deinit_done_cb(deinit_done_ctx); 01222 } 01223 01224 01225 void wps_er_deinit(struct wps_er *er, void (*cb)(void *ctx), void *ctx) 01226 { 01227 if (er == NULL) 01228 return; 01229 http_server_deinit(er->http_srv); 01230 wps_er_ap_remove_all(er); 01231 wps_er_ssdp_deinit(er); 01232 eloop_register_timeout(dl_list_empty(&er->ap_unsubscribing) ? 0 : 5, 0, 01233 wps_er_deinit_finish, er, NULL); 01234 wpa_printf(MSG_DEBUG, "WPS ER: Finish deinit from timeout"); 01235 er->deinitializing = 1; 01236 er->deinit_done_cb = cb; 01237 er->deinit_done_ctx = ctx; 01238 } 01239 01240 01241 static void wps_er_http_set_sel_reg_cb(void *ctx, struct http_client *c, 01242 enum http_client_event event) 01243 { 01244 struct wps_er_ap *ap = ctx; 01245 01246 switch (event) { 01247 case HTTP_CLIENT_OK: 01248 wpa_printf(MSG_DEBUG, "WPS ER: SetSelectedRegistrar OK"); 01249 break; 01250 case HTTP_CLIENT_FAILED: 01251 case HTTP_CLIENT_INVALID_REPLY: 01252 case HTTP_CLIENT_TIMEOUT: 01253 wpa_printf(MSG_DEBUG, "WPS ER: SetSelectedRegistrar failed"); 01254 break; 01255 } 01256 http_client_free(ap->http); 01257 ap->http = NULL; 01258 } 01259 01260 01261 static void wps_er_send_set_sel_reg(struct wps_er_ap *ap, struct wpabuf *msg) 01262 { 01263 struct wpabuf *buf; 01264 char *len_ptr, *body_ptr; 01265 struct sockaddr_in dst; 01266 char *url, *path; 01267 01268 if (ap->control_url == NULL) { 01269 wpa_printf(MSG_DEBUG, "WPS ER: No controlURL for AP"); 01270 return; 01271 } 01272 01273 if (ap->http) { 01274 wpa_printf(MSG_DEBUG, "WPS ER: Pending HTTP request for AP - " 01275 "ignore new request"); 01276 return; 01277 } 01278 01279 url = http_client_url_parse(ap->control_url, &dst, &path); 01280 if (url == NULL) { 01281 wpa_printf(MSG_DEBUG, "WPS ER: Failed to parse controlURL"); 01282 return; 01283 } 01284 01285 buf = wps_er_soap_hdr(msg, "SetSelectedRegistrar", "NewMessage", path, 01286 &dst, &len_ptr, &body_ptr); 01287 os_free(url); 01288 if (buf == NULL) 01289 return; 01290 01291 wps_er_soap_end(buf, "SetSelectedRegistrar", len_ptr, body_ptr); 01292 01293 ap->http = http_client_addr(&dst, buf, 1000, 01294 wps_er_http_set_sel_reg_cb, ap); 01295 if (ap->http == NULL) 01296 wpabuf_free(buf); 01297 } 01298 01299 01300 static int wps_er_build_selected_registrar(struct wpabuf *msg, int sel_reg) 01301 { 01302 wpabuf_put_be16(msg, ATTR_SELECTED_REGISTRAR); 01303 wpabuf_put_be16(msg, 1); 01304 wpabuf_put_u8(msg, !!sel_reg); 01305 return 0; 01306 } 01307 01308 01309 static int wps_er_build_dev_password_id(struct wpabuf *msg, u16 dev_passwd_id) 01310 { 01311 wpabuf_put_be16(msg, ATTR_DEV_PASSWORD_ID); 01312 wpabuf_put_be16(msg, 2); 01313 wpabuf_put_be16(msg, dev_passwd_id); 01314 return 0; 01315 } 01316 01317 01318 static int wps_er_build_sel_reg_config_methods(struct wpabuf *msg, 01319 u16 sel_reg_config_methods) 01320 { 01321 wpabuf_put_be16(msg, ATTR_SELECTED_REGISTRAR_CONFIG_METHODS); 01322 wpabuf_put_be16(msg, 2); 01323 wpabuf_put_be16(msg, sel_reg_config_methods); 01324 return 0; 01325 } 01326 01327 01328 void wps_er_set_sel_reg(struct wps_er *er, int sel_reg, u16 dev_passwd_id, 01329 u16 sel_reg_config_methods) 01330 { 01331 struct wpabuf *msg; 01332 struct wps_er_ap *ap; 01333 01334 msg = wpabuf_alloc(500); 01335 if (msg == NULL) 01336 return; 01337 01338 if (wps_build_version(msg) || 01339 wps_er_build_selected_registrar(msg, sel_reg) || 01340 wps_er_build_dev_password_id(msg, dev_passwd_id) || 01341 wps_er_build_sel_reg_config_methods(msg, sel_reg_config_methods)) { 01342 wpabuf_free(msg); 01343 return; 01344 } 01345 01346 dl_list_for_each(ap, &er->ap, struct wps_er_ap, list) 01347 wps_er_send_set_sel_reg(ap, msg); 01348 01349 wpabuf_free(msg); 01350 } 01351 01352 01353 int wps_er_pbc(struct wps_er *er, const u8 *uuid) 01354 { 01355 if (er == NULL || er->wps == NULL) 01356 return -1; 01357 01358 /* 01359 * TODO: Should enable PBC mode only in a single AP based on which AP 01360 * the Enrollee (uuid) is using. Now, we may end up enabling multiple 01361 * APs in PBC mode which could result in session overlap at the 01362 * Enrollee. 01363 */ 01364 if (wps_registrar_button_pushed(er->wps->registrar)) 01365 return -1; 01366 01367 return 0; 01368 } 01369 01370 01371 static void wps_er_ap_settings_cb(void *ctx, const struct wps_credential *cred) 01372 { 01373 struct wps_er_ap *ap = ctx; 01374 wpa_printf(MSG_DEBUG, "WPS ER: AP Settings received"); 01375 os_free(ap->ap_settings); 01376 ap->ap_settings = os_malloc(sizeof(*cred)); 01377 if (ap->ap_settings) { 01378 os_memcpy(ap->ap_settings, cred, sizeof(*cred)); 01379 ap->ap_settings->cred_attr = NULL; 01380 } 01381 01382 /* TODO: send info through ctrl_iface */ 01383 } 01384 01385 01386 static void wps_er_http_put_message_cb(void *ctx, struct http_client *c, 01387 enum http_client_event event) 01388 { 01389 struct wps_er_ap *ap = ctx; 01390 struct wpabuf *reply; 01391 char *msg = NULL; 01392 01393 switch (event) { 01394 case HTTP_CLIENT_OK: 01395 wpa_printf(MSG_DEBUG, "WPS ER: PutMessage OK"); 01396 reply = http_client_get_body(c); 01397 if (reply == NULL) 01398 break; 01399 msg = os_zalloc(wpabuf_len(reply) + 1); 01400 if (msg == NULL) 01401 break; 01402 os_memcpy(msg, wpabuf_head(reply), wpabuf_len(reply)); 01403 break; 01404 case HTTP_CLIENT_FAILED: 01405 case HTTP_CLIENT_INVALID_REPLY: 01406 case HTTP_CLIENT_TIMEOUT: 01407 wpa_printf(MSG_DEBUG, "WPS ER: PutMessage failed"); 01408 if (ap->wps) { 01409 wps_deinit(ap->wps); 01410 ap->wps = NULL; 01411 } 01412 break; 01413 } 01414 http_client_free(ap->http); 01415 ap->http = NULL; 01416 01417 if (msg) { 01418 struct wpabuf *buf; 01419 enum http_reply_code ret; 01420 buf = xml_get_base64_item(msg, "NewOutMessage", &ret); 01421 os_free(msg); 01422 if (buf == NULL) { 01423 wpa_printf(MSG_DEBUG, "WPS ER: Could not extract " 01424 "NewOutMessage from PutMessage response"); 01425 return; 01426 } 01427 wps_er_ap_process(ap, buf); 01428 wpabuf_free(buf); 01429 } 01430 } 01431 01432 01433 static void wps_er_ap_put_message(struct wps_er_ap *ap, 01434 const struct wpabuf *msg) 01435 { 01436 struct wpabuf *buf; 01437 char *len_ptr, *body_ptr; 01438 struct sockaddr_in dst; 01439 char *url, *path; 01440 01441 if (ap->http) { 01442 wpa_printf(MSG_DEBUG, "WPS ER: Pending HTTP operation ongoing " 01443 "with the AP - cannot continue learn"); 01444 return; 01445 } 01446 01447 if (ap->control_url == NULL) { 01448 wpa_printf(MSG_DEBUG, "WPS ER: No controlURL for AP"); 01449 return; 01450 } 01451 01452 url = http_client_url_parse(ap->control_url, &dst, &path); 01453 if (url == NULL) { 01454 wpa_printf(MSG_DEBUG, "WPS ER: Failed to parse controlURL"); 01455 return; 01456 } 01457 01458 buf = wps_er_soap_hdr(msg, "PutMessage", "NewInMessage", path, &dst, 01459 &len_ptr, &body_ptr); 01460 os_free(url); 01461 if (buf == NULL) 01462 return; 01463 01464 wps_er_soap_end(buf, "PutMessage", len_ptr, body_ptr); 01465 01466 ap->http = http_client_addr(&dst, buf, 10000, 01467 wps_er_http_put_message_cb, ap); 01468 if (ap->http == NULL) 01469 wpabuf_free(buf); 01470 } 01471 01472 01473 static void wps_er_ap_process(struct wps_er_ap *ap, struct wpabuf *msg) 01474 { 01475 enum wps_process_res res; 01476 01477 res = wps_process_msg(ap->wps, WSC_MSG, msg); 01478 if (res == WPS_CONTINUE) { 01479 enum wsc_op_code op_code; 01480 struct wpabuf *next = wps_get_msg(ap->wps, &op_code); 01481 if (next) { 01482 wps_er_ap_put_message(ap, next); 01483 wpabuf_free(next); 01484 } else { 01485 wpa_printf(MSG_DEBUG, "WPS ER: Failed to build " 01486 "message"); 01487 wps_deinit(ap->wps); 01488 ap->wps = NULL; 01489 } 01490 } else { 01491 wpa_printf(MSG_DEBUG, "WPS ER: Failed to process message from " 01492 "AP (res=%d)", res); 01493 wps_deinit(ap->wps); 01494 ap->wps = NULL; 01495 } 01496 } 01497 01498 01499 static void wps_er_ap_learn_m1(struct wps_er_ap *ap, struct wpabuf *m1) 01500 { 01501 struct wps_config cfg; 01502 01503 if (ap->wps) { 01504 wpa_printf(MSG_DEBUG, "WPS ER: Protocol run already in " 01505 "progress with this AP"); 01506 return; 01507 } 01508 01509 os_memset(&cfg, 0, sizeof(cfg)); 01510 cfg.wps = ap->er->wps; 01511 cfg.registrar = 1; 01512 ap->wps = wps_init(&cfg); 01513 if (ap->wps == NULL) 01514 return; 01515 ap->wps->ap_settings_cb = wps_er_ap_settings_cb; 01516 ap->wps->ap_settings_cb_ctx = ap; 01517 01518 wps_er_ap_process(ap, m1); 01519 } 01520 01521 01522 static void wps_er_ap_learn(struct wps_er_ap *ap, const char *dev_info) 01523 { 01524 struct wpabuf *info; 01525 enum http_reply_code ret; 01526 01527 wpa_printf(MSG_DEBUG, "WPS ER: Received GetDeviceInfo response (M1) " 01528 "from the AP"); 01529 info = xml_get_base64_item(dev_info, "NewDeviceInfo", &ret); 01530 if (info == NULL) { 01531 wpa_printf(MSG_DEBUG, "WPS ER: Could not extract " 01532 "NewDeviceInfo from GetDeviceInfo response"); 01533 return; 01534 } 01535 01536 ap->m1_handler(ap, info); 01537 wpabuf_free(info); 01538 } 01539 01540 01541 static void wps_er_http_get_dev_info_cb(void *ctx, struct http_client *c, 01542 enum http_client_event event) 01543 { 01544 struct wps_er_ap *ap = ctx; 01545 struct wpabuf *reply; 01546 char *dev_info = NULL; 01547 01548 switch (event) { 01549 case HTTP_CLIENT_OK: 01550 wpa_printf(MSG_DEBUG, "WPS ER: GetDeviceInfo OK"); 01551 reply = http_client_get_body(c); 01552 if (reply == NULL) 01553 break; 01554 dev_info = os_zalloc(wpabuf_len(reply) + 1); 01555 if (dev_info == NULL) 01556 break; 01557 os_memcpy(dev_info, wpabuf_head(reply), wpabuf_len(reply)); 01558 break; 01559 case HTTP_CLIENT_FAILED: 01560 case HTTP_CLIENT_INVALID_REPLY: 01561 case HTTP_CLIENT_TIMEOUT: 01562 wpa_printf(MSG_DEBUG, "WPS ER: GetDeviceInfo failed"); 01563 break; 01564 } 01565 http_client_free(ap->http); 01566 ap->http = NULL; 01567 01568 if (dev_info) { 01569 wps_er_ap_learn(ap, dev_info); 01570 os_free(dev_info); 01571 } 01572 } 01573 01574 01575 static int wps_er_send_get_device_info(struct wps_er_ap *ap, 01576 void (*m1_handler)(struct wps_er_ap *ap, 01577 struct wpabuf *m1)) 01578 { 01579 struct wpabuf *buf; 01580 char *len_ptr, *body_ptr; 01581 struct sockaddr_in dst; 01582 char *url, *path; 01583 01584 if (ap->http) { 01585 wpa_printf(MSG_DEBUG, "WPS ER: Pending HTTP operation ongoing " 01586 "with the AP - cannot get device info"); 01587 return -1; 01588 } 01589 01590 if (ap->control_url == NULL) { 01591 wpa_printf(MSG_DEBUG, "WPS ER: No controlURL for AP"); 01592 return -1; 01593 } 01594 01595 url = http_client_url_parse(ap->control_url, &dst, &path); 01596 if (url == NULL) { 01597 wpa_printf(MSG_DEBUG, "WPS ER: Failed to parse controlURL"); 01598 return -1; 01599 } 01600 01601 buf = wps_er_soap_hdr(NULL, "GetDeviceInfo", NULL, path, &dst, 01602 &len_ptr, &body_ptr); 01603 os_free(url); 01604 if (buf == NULL) 01605 return -1; 01606 01607 wps_er_soap_end(buf, "GetDeviceInfo", len_ptr, body_ptr); 01608 01609 ap->http = http_client_addr(&dst, buf, 10000, 01610 wps_er_http_get_dev_info_cb, ap); 01611 if (ap->http == NULL) { 01612 wpabuf_free(buf); 01613 return -1; 01614 } 01615 01616 ap->m1_handler = m1_handler; 01617 01618 return 0; 01619 } 01620 01621 01622 int wps_er_learn(struct wps_er *er, const u8 *uuid, const u8 *pin, 01623 size_t pin_len) 01624 { 01625 struct wps_er_ap *ap; 01626 01627 if (er == NULL) 01628 return -1; 01629 01630 ap = wps_er_ap_get(er, NULL, uuid); 01631 if (ap == NULL) { 01632 wpa_printf(MSG_DEBUG, "WPS ER: AP not found for learn " 01633 "request"); 01634 return -1; 01635 } 01636 if (ap->wps) { 01637 wpa_printf(MSG_DEBUG, "WPS ER: Pending operation ongoing " 01638 "with the AP - cannot start learn"); 01639 return -1; 01640 } 01641 01642 if (wps_er_send_get_device_info(ap, wps_er_ap_learn_m1) < 0) 01643 return -1; 01644 01645 /* TODO: add PIN without SetSelectedRegistrar trigger to all APs */ 01646 wps_registrar_add_pin(er->wps->registrar, uuid, pin, pin_len, 0); 01647 01648 return 0; 01649 }