wps_er.c
Go to the documentation of this file.
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 }


wpa_supplicant
Author(s): Package maintained by Blaise Gassend
autogenerated on Thu Jan 2 2014 11:26:39