00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
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
00215
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
00272
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
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
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
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
00660
00661
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
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
01067
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
01360
01361
01362
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
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
01646 wps_registrar_add_pin(er->wps->registrar, uuid, pin, pin_len, 0);
01647
01648 return 0;
01649 }