wps_er.c

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

Generated on Sat Nov 21 23:16:54 2009 for hostapd by  doxygen 1.6.1