18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* 28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Wi-Fi Protected Setup - External Registrar 31e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidt * Copyright (c) 2009-2013, Jouni Malinen <j@w1.fi> 48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 5c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * This software may be distributed under the terms of the BSD license. 6c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * See README for more details. 78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "includes.h" 108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common.h" 128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "base64.h" 138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "uuid.h" 148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eloop.h" 158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "httpread.h" 168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "http_client.h" 178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "http_server.h" 188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "upnp_xml.h" 198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "wps_i.h" 208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "wps_upnp.h" 218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "wps_upnp_i.h" 228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "wps_er.h" 238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wps_er_deinit_finish(void *eloop_data, void *user_ctx); 268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wps_er_ap_timeout(void *eloop_data, void *user_ctx); 278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wps_er_sta_timeout(void *eloop_data, void *user_ctx); 288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wps_er_ap_process(struct wps_er_ap *ap, struct wpabuf *msg); 298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wps_er_send_get_device_info(struct wps_er_ap *ap, 308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void (*m1_handler)(struct wps_er_ap *ap, 318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *m1)); 328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wps_er_sta_event(struct wps_context *wps, struct wps_er_sta *sta, 358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum wps_event event) 368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt union wps_event_data data; 388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wps_event_er_enrollee *ev = &data.enrollee; 398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wps->event_cb == NULL) 418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&data, 0, sizeof(data)); 448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ev->uuid = sta->uuid; 458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ev->mac_addr = sta->addr; 468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ev->m1_received = sta->m1_received; 478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ev->config_methods = sta->config_methods; 488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ev->dev_passwd_id = sta->dev_passwd_id; 498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ev->pri_dev_type = sta->pri_dev_type; 508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ev->dev_name = sta->dev_name; 518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ev->manufacturer = sta->manufacturer; 528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ev->model_name = sta->model_name; 538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ev->model_number = sta->model_number; 548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ev->serial_number = sta->serial_number; 558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps->event_cb(wps->cb_ctx, event, &data); 568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wps_er_sta * wps_er_sta_get(struct wps_er_ap *ap, const u8 *addr, 608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *uuid) 618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wps_er_sta *sta; 638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dl_list_for_each(sta, &ap->sta, struct wps_er_sta, list) { 648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((addr == NULL || 658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcmp(sta->addr, addr, ETH_ALEN) == 0) && 668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (uuid == NULL || 678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcmp(uuid, sta->uuid, WPS_UUID_LEN) == 0)) 688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return sta; 698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wps_er_sta_free(struct wps_er_sta *sta) 758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_er_sta_event(sta->ap->er->wps, sta, WPS_EV_ER_ENROLLEE_REMOVE); 778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sta->wps) 788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_deinit(sta->wps); 798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(sta->manufacturer); 808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(sta->model_name); 818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(sta->model_number); 828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(sta->serial_number); 838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(sta->dev_name); 848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt http_client_free(sta->http); 858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(wps_er_sta_timeout, sta, NULL); 868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(sta->cred); 878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(sta); 888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wps_er_sta_remove_all(struct wps_er_ap *ap) 928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wps_er_sta *prev, *sta; 948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dl_list_for_each_safe(sta, prev, &ap->sta, struct wps_er_sta, list) 958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_er_sta_free(sta); 968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wps_er_ap * wps_er_ap_get(struct wps_er *er, 1001e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidt struct in_addr *addr, const u8 *uuid, 1011e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidt const u8 *mac_addr) 1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wps_er_ap *ap; 1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dl_list_for_each(ap, &er->ap, struct wps_er_ap, list) { 1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((addr == NULL || ap->addr.s_addr == addr->s_addr) && 1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (uuid == NULL || 1071e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidt os_memcmp(uuid, ap->uuid, WPS_UUID_LEN) == 0) && 1081e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidt (mac_addr == NULL || 1091e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidt os_memcmp(mac_addr, ap->mac_addr, ETH_ALEN) == 0)) 1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ap; 1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wps_er_ap * wps_er_ap_get_id(struct wps_er *er, unsigned int id) 1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wps_er_ap *ap; 1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dl_list_for_each(ap, &er->ap, struct wps_er_ap, list) { 1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ap->id == id) 1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ap; 1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wps_er_ap_event(struct wps_context *wps, struct wps_er_ap *ap, 1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum wps_event event) 1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt union wps_event_data data; 1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wps_event_er_ap *evap = &data.ap; 1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wps->event_cb == NULL) 1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&data, 0, sizeof(data)); 1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt evap->uuid = ap->uuid; 1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt evap->friendly_name = ap->friendly_name; 1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt evap->manufacturer = ap->manufacturer; 1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt evap->manufacturer_url = ap->manufacturer_url; 1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt evap->model_description = ap->model_description; 1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt evap->model_name = ap->model_name; 1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt evap->model_number = ap->model_number; 1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt evap->model_url = ap->model_url; 1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt evap->serial_number = ap->serial_number; 1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt evap->upc = ap->upc; 1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt evap->pri_dev_type = ap->pri_dev_type; 1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt evap->wps_state = ap->wps_state; 1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt evap->mac_addr = ap->mac_addr; 1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps->event_cb(wps->cb_ctx, event, &data); 1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wps_er_ap_free(struct wps_er_ap *ap) 1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt http_client_free(ap->http); 1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap->http = NULL; 1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(ap->location); 1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(ap->friendly_name); 1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(ap->manufacturer); 1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(ap->manufacturer_url); 1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(ap->model_description); 1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(ap->model_name); 1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(ap->model_number); 1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(ap->model_url); 1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(ap->serial_number); 1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(ap->udn); 1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(ap->upc); 1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(ap->scpd_url); 1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(ap->control_url); 1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(ap->event_sub_url); 1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(ap->ap_settings); 1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(ap); 1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wps_er_ap_unsubscribed(struct wps_er *er, struct wps_er_ap *ap) 1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS ER: Unsubscribed from AP %s (%s)", 1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt inet_ntoa(ap->addr), ap->location); 1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dl_list_del(&ap->list); 1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_er_ap_free(ap); 1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 188fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (er->deinitializing && dl_list_empty(&er->ap_unsubscribing)) 1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_er_deinit_finish(er, NULL); 1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wps_er_http_unsubscribe_cb(void *ctx, struct http_client *c, 1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum http_client_event event) 1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wps_er_ap *ap = ctx; 1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (event) { 1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case HTTP_CLIENT_OK: 2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS ER: Unsubscribed from events"); 2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap->subscribed = 0; 2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case HTTP_CLIENT_FAILED: 2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case HTTP_CLIENT_INVALID_REPLY: 2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case HTTP_CLIENT_TIMEOUT: 2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS ER: Failed to unsubscribe from " 2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "events"); 2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt http_client_free(ap->http); 2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap->http = NULL; 2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Need to get rid of the AP entry regardless of whether we managed to 2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * unsubscribe cleanly or not. 2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_er_ap_unsubscribed(ap->er, ap); 2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wps_er_ap_unsubscribe(struct wps_er *er, struct wps_er_ap *ap) 2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *req; 2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct sockaddr_in dst; 2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *url, *path; 2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char sid[100]; 2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ap->event_sub_url == NULL) { 2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS ER: No eventSubURL - cannot " 2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "subscribe"); 2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ap->http) { 2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS ER: Pending HTTP request - cannot " 2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "send subscribe request"); 2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt url = http_client_url_parse(ap->event_sub_url, &dst, &path); 2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (url == NULL) { 2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS ER: Failed to parse eventSubURL"); 2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt req = wpabuf_alloc(os_strlen(ap->event_sub_url) + 1000); 2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (req == NULL) { 2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(url); 2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt uuid_bin2str(ap->sid, sid, sizeof(sid)); 2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_printf(req, 2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "UNSUBSCRIBE %s HTTP/1.1\r\n" 2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "HOST: %s:%d\r\n" 2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "SID: uuid:%s\r\n" 2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "\r\n", 2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt path, inet_ntoa(dst.sin_addr), ntohs(dst.sin_port), sid); 2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(url); 2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii(MSG_MSGDUMP, "WPS ER: Unsubscription request", 2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_head(req), wpabuf_len(req)); 2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap->http = http_client_addr(&dst, req, 1000, 2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_er_http_unsubscribe_cb, ap); 2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ap->http == NULL) { 2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(req); 2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtfail: 2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Need to get rid of the AP entry even when we fail to unsubscribe 2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * cleanly. 2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_er_ap_unsubscribed(ap->er, ap); 2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wps_er_ap_settings * wps_er_ap_get_settings(struct wps_er *er, 2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *uuid) 2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wps_er_ap_settings *s; 2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dl_list_for_each(s, &er->ap_settings, struct wps_er_ap_settings, list) 2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(uuid, s->uuid, WPS_UUID_LEN) == 0) 2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return s; 2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wps_er_ap_cache_settings(struct wps_er *er, struct in_addr *addr) 2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wps_er_ap *ap; 2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wps_er_ap_settings *settings; 2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2941e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidt ap = wps_er_ap_get(er, addr, NULL, NULL); 2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ap == NULL || ap->ap_settings == NULL) 2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt settings = wps_er_ap_get_settings(er, ap->uuid); 2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!settings) { 3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt settings = os_zalloc(sizeof(*settings)); 3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (settings == NULL) 3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(settings->uuid, ap->uuid, WPS_UUID_LEN); 3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dl_list_add(&er->ap_settings, &settings->list); 3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(&settings->ap_settings, ap->ap_settings, 3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sizeof(struct wps_credential)); 3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wps_er_ap_use_cached_settings(struct wps_er *er, 3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wps_er_ap *ap) 3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wps_er_ap_settings *s; 3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ap->ap_settings) 3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt s = wps_er_ap_get_settings(ap->er, ap->uuid); 3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!s) 3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 325d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt ap->ap_settings = os_memdup(&s->ap_settings, sizeof(*ap->ap_settings)); 3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ap->ap_settings == NULL) 3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS ER: Use cached AP settings"); 3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wps_er_ap_remove_entry(struct wps_er *er, struct wps_er_ap *ap) 3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS ER: Removing AP entry for %s (%s)", 3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt inet_ntoa(ap->addr), ap->location); 3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(wps_er_ap_timeout, er, ap); 3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_er_sta_remove_all(ap); 3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_er_ap_event(er->wps, ap, WPS_EV_ER_AP_REMOVE); 3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt http_client_free(ap->http); 3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap->http = NULL; 3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ap->wps) { 3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_deinit(ap->wps); 3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap->wps = NULL; 3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dl_list_del(&ap->list); 3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ap->subscribed) { 3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dl_list_add(&er->ap_unsubscribing, &ap->list); 3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_er_ap_unsubscribe(er, ap); 3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else 3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_er_ap_free(ap); 3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wps_er_ap_timeout(void *eloop_data, void *user_ctx) 3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wps_er *er = eloop_data; 3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wps_er_ap *ap = user_ctx; 3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS ER: AP advertisement timed out"); 3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_er_ap_remove_entry(er, ap); 3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wps_er_get_sid(struct wps_er_ap *ap, char *sid) 3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *pos; 3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char txt[100]; 3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!sid) { 3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS ER: No SID received from %s (%s)", 3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt inet_ntoa(ap->addr), ap->location); 3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = os_strstr(sid, "uuid:"); 3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!pos) { 3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS ER: Invalid SID received from " 3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "%s (%s): '%s'", inet_ntoa(ap->addr), ap->location, 3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sid); 3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 5; 3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (uuid_str2bin(pos, ap->sid) < 0) { 3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS ER: Invalid SID received from " 3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "%s (%s): '%s'", inet_ntoa(ap->addr), ap->location, 3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sid); 3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt uuid_bin2str(ap->sid, txt, sizeof(txt)); 3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS ER: SID for subscription with %s (%s): %s", 3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt inet_ntoa(ap->addr), ap->location, txt); 3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wps_er_http_subscribe_cb(void *ctx, struct http_client *c, 4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum http_client_event event) 4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wps_er_ap *ap = ctx; 4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (event) { 4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case HTTP_CLIENT_OK: 4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS ER: Subscribed to events"); 4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap->subscribed = 1; 4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_er_get_sid(ap, http_client_get_hdr_line(c, "SID")); 4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_er_ap_use_cached_settings(ap->er, ap); 4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_er_ap_event(ap->er->wps, ap, WPS_EV_ER_AP_ADD); 4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case HTTP_CLIENT_FAILED: 4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case HTTP_CLIENT_INVALID_REPLY: 4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case HTTP_CLIENT_TIMEOUT: 4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS ER: Failed to subscribe to events"); 4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt http_client_free(ap->http); 4218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap->http = NULL; 4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wps_er_subscribe(struct wps_er_ap *ap) 4268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *req; 4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct sockaddr_in dst; 4298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *url, *path; 4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ap->event_sub_url == NULL) { 4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS ER: No eventSubURL - cannot " 4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "subscribe"); 4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ap->http) { 4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS ER: Pending HTTP request - cannot " 4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "send subscribe request"); 4398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 4408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt url = http_client_url_parse(ap->event_sub_url, &dst, &path); 4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (url == NULL) { 4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS ER: Failed to parse eventSubURL"); 4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt req = wpabuf_alloc(os_strlen(ap->event_sub_url) + 1000); 4498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (req == NULL) { 4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(url); 4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_printf(req, 4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "SUBSCRIBE %s HTTP/1.1\r\n" 4558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "HOST: %s:%d\r\n" 4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "CALLBACK: <http://%s:%d/event/%u/%u>\r\n" 4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "NT: upnp:event\r\n" 4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "TIMEOUT: Second-%d\r\n" 4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "\r\n", 4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt path, inet_ntoa(dst.sin_addr), ntohs(dst.sin_port), 4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap->er->ip_addr_text, ap->er->http_port, 4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap->er->event_id, ap->id, 1800); 4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(url); 4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii(MSG_MSGDUMP, "WPS ER: Subscription request", 4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_head(req), wpabuf_len(req)); 4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap->http = http_client_addr(&dst, req, 1000, wps_er_http_subscribe_cb, 4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap); 4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ap->http == NULL) 4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(req); 4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wps_er_ap_get_m1(struct wps_er_ap *ap, struct wpabuf *m1) 4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wps_parse_attr attr; 4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wps_parse_msg(m1, &attr) < 0) { 4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS ER: Failed to parse M1"); 4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (attr.primary_dev_type) 4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(ap->pri_dev_type, attr.primary_dev_type, 8); 4848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (attr.wps_state) 4858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap->wps_state = *attr.wps_state; 4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (attr.mac_addr) 4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(ap->mac_addr, attr.mac_addr, ETH_ALEN); 4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_er_subscribe(ap); 4908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wps_er_get_device_info(struct wps_er_ap *ap) 4948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_er_send_get_device_info(ap, wps_er_ap_get_m1); 4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic const char * wps_er_find_wfadevice(const char *data) 5001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 5011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt const char *tag, *tagname, *end; 5021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt char *val; 5031f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt int found = 0; 5041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 5051f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt while (!found) { 5061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt /* Find next <device> */ 5071f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt for (;;) { 5081f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (xml_next_tag(data, &tag, &tagname, &end)) 5091f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return NULL; 5101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt data = end; 5111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (!os_strncasecmp(tagname, "device", 6) && 5121f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *tag != '/' && 5131f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt (tagname[6] == '>' || !isgraph(tagname[6]))) { 5141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 5151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 5161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 5171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 5181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt /* Check whether deviceType is WFADevice */ 5191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt val = xml_get_first_item(data, "deviceType"); 5201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (val == NULL) 5211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return NULL; 5221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "WPS ER: Found deviceType '%s'", val); 5231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt found = os_strcasecmp(val, "urn:schemas-wifialliance-org:" 5241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "device:WFADevice:1") == 0; 5251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt os_free(val); 5261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 5271f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 5281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return data; 5291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 5301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 5311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 5328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wps_er_parse_device_description(struct wps_er_ap *ap, 5338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *reply) 5348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Note: reply includes null termination after the buffer data */ 5361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt const char *tmp, *data = wpabuf_head(reply); 5378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *pos; 5388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii(MSG_MSGDUMP, "WPS ER: Device info", 5408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_head(reply), wpabuf_len(reply)); 5418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt /* 5431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * The root device description may include multiple devices, so first 5441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * find the beginning of the WFADevice description to allow the 5451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * simplistic parser to pick the correct entries. 5461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt */ 5471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt tmp = wps_er_find_wfadevice(data); 5481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (tmp == NULL) { 5491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "WPS ER: WFADevice:1 device not found - " 5501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "trying to parse invalid data"); 5511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } else 5521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt data = tmp; 5531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 5548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap->friendly_name = xml_get_first_item(data, "friendlyName"); 5558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS ER: friendlyName='%s'", ap->friendly_name); 5568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap->manufacturer = xml_get_first_item(data, "manufacturer"); 5588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS ER: manufacturer='%s'", ap->manufacturer); 5598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap->manufacturer_url = xml_get_first_item(data, "manufacturerURL"); 5618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS ER: manufacturerURL='%s'", 5628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap->manufacturer_url); 5638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap->model_description = xml_get_first_item(data, "modelDescription"); 5658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS ER: modelDescription='%s'", 5668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap->model_description); 5678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap->model_name = xml_get_first_item(data, "modelName"); 5698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS ER: modelName='%s'", ap->model_name); 5708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap->model_number = xml_get_first_item(data, "modelNumber"); 5728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS ER: modelNumber='%s'", ap->model_number); 5738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap->model_url = xml_get_first_item(data, "modelURL"); 5758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS ER: modelURL='%s'", ap->model_url); 5768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap->serial_number = xml_get_first_item(data, "serialNumber"); 5788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS ER: serialNumber='%s'", ap->serial_number); 5798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap->udn = xml_get_first_item(data, "UDN"); 58109f57babfc1e4473db20ced4f58a4c9f082c8ed8Dmitry Shmidt if (ap->udn) { 58209f57babfc1e4473db20ced4f58a4c9f082c8ed8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS ER: UDN='%s'", ap->udn); 58309f57babfc1e4473db20ced4f58a4c9f082c8ed8Dmitry Shmidt pos = os_strstr(ap->udn, "uuid:"); 58409f57babfc1e4473db20ced4f58a4c9f082c8ed8Dmitry Shmidt if (pos) { 58509f57babfc1e4473db20ced4f58a4c9f082c8ed8Dmitry Shmidt pos += 5; 58609f57babfc1e4473db20ced4f58a4c9f082c8ed8Dmitry Shmidt if (uuid_str2bin(pos, ap->uuid) < 0) 58709f57babfc1e4473db20ced4f58a4c9f082c8ed8Dmitry Shmidt wpa_printf(MSG_DEBUG, 58809f57babfc1e4473db20ced4f58a4c9f082c8ed8Dmitry Shmidt "WPS ER: Invalid UUID in UDN"); 58909f57babfc1e4473db20ced4f58a4c9f082c8ed8Dmitry Shmidt } 5908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap->upc = xml_get_first_item(data, "UPC"); 5938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS ER: UPC='%s'", ap->upc); 5948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap->scpd_url = http_link_update( 5968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt xml_get_first_item(data, "SCPDURL"), ap->location); 5978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS ER: SCPDURL='%s'", ap->scpd_url); 5988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap->control_url = http_link_update( 6008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt xml_get_first_item(data, "controlURL"), ap->location); 6018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS ER: controlURL='%s'", ap->control_url); 6028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap->event_sub_url = http_link_update( 6048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt xml_get_first_item(data, "eventSubURL"), ap->location); 6058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS ER: eventSubURL='%s'", ap->event_sub_url); 6068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wps_er_http_dev_desc_cb(void *ctx, struct http_client *c, 6108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum http_client_event event) 6118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wps_er_ap *ap = ctx; 6138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *reply; 6148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ok = 0; 6158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (event) { 6178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case HTTP_CLIENT_OK: 6188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt reply = http_client_get_body(c); 6198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (reply == NULL) 6208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 6218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_er_parse_device_description(ap, reply); 6228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ok = 1; 6238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 6248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case HTTP_CLIENT_FAILED: 6258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case HTTP_CLIENT_INVALID_REPLY: 6268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case HTTP_CLIENT_TIMEOUT: 6278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS ER: Failed to fetch device info"); 6288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 6298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt http_client_free(ap->http); 6318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap->http = NULL; 6328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ok) 6338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_er_get_device_info(ap); 6348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wps_er_ap_add(struct wps_er *er, const u8 *uuid, struct in_addr *addr, 6388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const char *location, int max_age) 6398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wps_er_ap *ap; 6418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6421e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidt ap = wps_er_ap_get(er, addr, uuid, NULL); 6438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ap) { 6448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Update advertisement timeout */ 6458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(wps_er_ap_timeout, er, ap); 6468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_register_timeout(max_age, 0, wps_er_ap_timeout, er, ap); 6478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 6488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap = os_zalloc(sizeof(*ap)); 6518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ap == NULL) 6528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 6538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dl_list_init(&ap->sta); 6548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap->er = er; 6558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap->id = ++er->next_ap_id; 6568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap->location = os_strdup(location); 6578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ap->location == NULL) { 6588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(ap); 6598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 6608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dl_list_add(&er->ap, &ap->list); 6628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap->addr.s_addr = addr->s_addr; 6648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(ap->uuid, uuid, WPS_UUID_LEN); 6658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_register_timeout(max_age, 0, wps_er_ap_timeout, er, ap); 6668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS ER: Added AP entry for %s (%s)", 6688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt inet_ntoa(ap->addr), ap->location); 6698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Fetch device description */ 6718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap->http = http_client_url(ap->location, NULL, 10000, 6728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_er_http_dev_desc_cb, ap); 6738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wps_er_ap_remove(struct wps_er *er, struct in_addr *addr) 6778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wps_er_ap *ap; 6798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dl_list_for_each(ap, &er->ap, struct wps_er_ap, list) { 6808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ap->addr.s_addr == addr->s_addr) { 6818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_er_ap_remove_entry(er, ap); 6828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 6838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wps_er_ap_remove_all(struct wps_er *er) 6898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wps_er_ap *prev, *ap; 6918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wps_er_ap_settings *prev_s, *s; 6928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dl_list_for_each_safe(ap, prev, &er->ap, struct wps_er_ap, list) 6938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_er_ap_remove_entry(er, ap); 6948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dl_list_for_each_safe(s, prev_s, &er->ap_settings, 6958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wps_er_ap_settings, list) 6968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(s); 6978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void http_put_date(struct wpabuf *buf) 7018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_str(buf, "Date: "); 7038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt format_date(buf); 7048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_str(buf, "\r\n"); 7058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wps_er_http_resp_not_found(struct http_request *req) 7098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *buf; 7118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf = wpabuf_alloc(200); 7128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (buf == NULL) { 7138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt http_request_deinit(req); 7148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 7158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_str(buf, 7188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "HTTP/1.1 404 Not Found\r\n" 7198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Server: unspecified, UPnP/1.0, unspecified\r\n" 7208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Connection: close\r\n"); 7218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt http_put_date(buf); 7228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_str(buf, "\r\n"); 7238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt http_request_send_and_deinit(req, buf); 7248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wps_er_http_resp_ok(struct http_request *req) 7288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *buf; 7308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf = wpabuf_alloc(200); 7318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (buf == NULL) { 7328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt http_request_deinit(req); 7338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 7348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_str(buf, 7378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "HTTP/1.1 200 OK\r\n" 7388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Server: unspecified, UPnP/1.0, unspecified\r\n" 7398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Connection: close\r\n" 7408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Content-Length: 0\r\n"); 7418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt http_put_date(buf); 7428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_str(buf, "\r\n"); 7438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt http_request_send_and_deinit(req, buf); 7448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wps_er_sta_timeout(void *eloop_data, void *user_ctx) 7488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wps_er_sta *sta = eloop_data; 7508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS ER: STA entry timed out"); 7518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dl_list_del(&sta->list); 7528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_er_sta_free(sta); 7538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wps_er_sta * wps_er_add_sta_data(struct wps_er_ap *ap, 7578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *addr, 7588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wps_parse_attr *attr, 7598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int probe_req) 7608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wps_er_sta *sta = wps_er_sta_get(ap, addr, NULL); 7628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int new_sta = 0; 7638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int m1; 7648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt m1 = !probe_req && attr->msg_type && *attr->msg_type == WPS_M1; 7668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sta == NULL) { 7688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 7698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Only allow new STA entry to be added based on Probe Request 7708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * or M1. This will filter out bogus events and anything that 7718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * may have been ongoing at the time ER subscribed for events. 7728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 7738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!probe_req && !m1) 7748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 7758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sta = os_zalloc(sizeof(*sta)); 7778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sta == NULL) 7788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 7798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(sta->addr, addr, ETH_ALEN); 7808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sta->ap = ap; 7818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dl_list_add(&ap->sta, &sta->list); 7828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt new_sta = 1; 7838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (m1) 7868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sta->m1_received = 1; 7878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (attr->config_methods && (!probe_req || !sta->m1_received)) 7898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sta->config_methods = WPA_GET_BE16(attr->config_methods); 7908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (attr->uuid_e && (!probe_req || !sta->m1_received)) 7918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(sta->uuid, attr->uuid_e, WPS_UUID_LEN); 7928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (attr->primary_dev_type && (!probe_req || !sta->m1_received)) 7938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(sta->pri_dev_type, attr->primary_dev_type, 8); 7948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (attr->dev_password_id && (!probe_req || !sta->m1_received)) 7958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sta->dev_passwd_id = WPA_GET_BE16(attr->dev_password_id); 7968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (attr->manufacturer) { 7988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(sta->manufacturer); 7994b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt sta->manufacturer = dup_binstr(attr->manufacturer, 8004b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt attr->manufacturer_len); 8018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (attr->model_name) { 8048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(sta->model_name); 8054b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt sta->model_name = dup_binstr(attr->model_name, 8064b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt attr->model_name_len); 8078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (attr->model_number) { 8108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(sta->model_number); 8114b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt sta->model_number = dup_binstr(attr->model_number, 8124b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt attr->model_number_len); 8138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (attr->serial_number) { 8168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(sta->serial_number); 8174b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt sta->serial_number = dup_binstr(attr->serial_number, 8184b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt attr->serial_number_len); 8198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (attr->dev_name) { 8228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(sta->dev_name); 8234b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt sta->dev_name = dup_binstr(attr->dev_name, attr->dev_name_len); 8248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(wps_er_sta_timeout, sta, NULL); 8278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_register_timeout(300, 0, wps_er_sta_timeout, sta, NULL); 8288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (m1 || new_sta) 8308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_er_sta_event(ap->er->wps, sta, WPS_EV_ER_ENROLLEE_ADD); 8318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return sta; 8338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 8348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wps_er_process_wlanevent_probe_req(struct wps_er_ap *ap, 8378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *addr, 8388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *msg) 8398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 8408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wps_parse_attr attr; 8418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS ER: WLANEvent - Probe Request - from " 8438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MACSTR, MAC2STR(addr)); 8448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_buf(MSG_MSGDUMP, "WPS ER: WLANEvent - Enrollee's message " 8458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(TLVs from Probe Request)", msg); 8468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wps_validate_probe_req(msg, addr) < 0) { 8488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "WPS-STRICT: ER: Ignore invalid proxied " 8498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Probe Request frame from " MACSTR, MAC2STR(addr)); 8508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 8518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wps_parse_msg(msg, &attr) < 0) { 8548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS ER: Failed to parse TLVs in " 8558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WLANEvent message"); 8568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 8578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_er_add_sta_data(ap, addr, &attr, 1); 8608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_registrar_probe_req_rx(ap->er->wps->registrar, addr, msg, 0); 8618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 8628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wps_er_http_put_wlan_response_cb(void *ctx, struct http_client *c, 8658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum http_client_event event) 8668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 8678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wps_er_sta *sta = ctx; 8688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (event) { 8708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case HTTP_CLIENT_OK: 8718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS ER: PutWLANResponse OK"); 8728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 8738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case HTTP_CLIENT_FAILED: 8748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case HTTP_CLIENT_INVALID_REPLY: 8758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case HTTP_CLIENT_TIMEOUT: 8768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS ER: PutWLANResponse failed"); 8778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 8788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt http_client_free(sta->http); 8808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sta->http = NULL; 8818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 8828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const char *soap_prefix = 8858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "<?xml version=\"1.0\"?>\n" 8868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" " 8878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">\n" 8888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "<s:Body>\n"; 8898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const char *soap_postfix = 8908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "</s:Body>\n</s:Envelope>\n"; 8918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const char *urn_wfawlanconfig = 8928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "urn:schemas-wifialliance-org:service:WFAWLANConfig:1"; 8938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * wps_er_soap_hdr(const struct wpabuf *msg, 8958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const char *name, const char *arg_name, 8968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const char *path, 8978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct sockaddr_in *dst, 8988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char **len_ptr, char **body_ptr) 8998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 9008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt unsigned char *encoded; 9018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t encoded_len; 9028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *buf; 9038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (msg) { 9058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt encoded = base64_encode(wpabuf_head(msg), wpabuf_len(msg), 9068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &encoded_len); 9078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (encoded == NULL) 9088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 9098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 9108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt encoded = NULL; 9118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt encoded_len = 0; 9128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf = wpabuf_alloc(1000 + encoded_len); 9158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (buf == NULL) { 9168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(encoded); 9178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 9188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_printf(buf, 9218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "POST %s HTTP/1.1\r\n" 9228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Host: %s:%d\r\n" 9238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Content-Type: text/xml; charset=\"utf-8\"\r\n" 9248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Content-Length: ", 9258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt path, inet_ntoa(dst->sin_addr), ntohs(dst->sin_port)); 9268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *len_ptr = wpabuf_put(buf, 0); 9288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_printf(buf, 9298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " \r\n" 9308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "SOAPACTION: \"%s#%s\"\r\n" 9318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "\r\n", 9328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt urn_wfawlanconfig, name); 9338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *body_ptr = wpabuf_put(buf, 0); 9358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_str(buf, soap_prefix); 9378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_printf(buf, "<u:%s xmlns:u=\"", name); 9388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_str(buf, urn_wfawlanconfig); 9398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_str(buf, "\">\n"); 9408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (encoded) { 9418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_printf(buf, "<%s>%s</%s>\n", 9428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt arg_name, (char *) encoded, arg_name); 9438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(encoded); 9448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return buf; 9478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 9488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wps_er_soap_end(struct wpabuf *buf, const char *name, 9518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *len_ptr, char *body_ptr) 9528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 9538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char len_buf[10]; 9548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_printf(buf, "</u:%s>\n", name); 9558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_str(buf, soap_postfix); 9568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_snprintf(len_buf, sizeof(len_buf), "%d", 9578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (int) ((char *) wpabuf_put(buf, 0) - body_ptr)); 9588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(len_ptr, len_buf, os_strlen(len_buf)); 9598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 9608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wps_er_sta_send_msg(struct wps_er_sta *sta, struct wpabuf *msg) 9638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 9648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *buf; 9658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *len_ptr, *body_ptr; 9668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct sockaddr_in dst; 9678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *url, *path; 9688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sta->http) { 9708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS ER: Pending HTTP request for STA - " 9718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "ignore new request"); 9728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(msg); 9738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 9748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sta->ap->control_url == NULL) { 9778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS ER: No controlURL for AP"); 9788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(msg); 9798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 9808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt url = http_client_url_parse(sta->ap->control_url, &dst, &path); 9838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (url == NULL) { 9848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS ER: Failed to parse controlURL"); 9858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(msg); 9868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 9878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf = wps_er_soap_hdr(msg, "PutWLANResponse", "NewMessage", path, &dst, 9908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &len_ptr, &body_ptr); 9918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(msg); 9928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(url); 9938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (buf == NULL) 9948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 9958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_printf(buf, "<NewWLANEventType>%d</NewWLANEventType>\n", 9968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt UPNP_WPS_WLANEVENT_TYPE_EAP); 9978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_printf(buf, "<NewWLANEventMAC>" MACSTR "</NewWLANEventMAC>\n", 9988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(sta->addr)); 9998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_er_soap_end(buf, "PutWLANResponse", len_ptr, body_ptr); 10018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sta->http = http_client_addr(&dst, buf, 1000, 10038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_er_http_put_wlan_response_cb, sta); 10048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sta->http == NULL) 10058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(buf); 10068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 10078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wps_er_sta_process(struct wps_er_sta *sta, struct wpabuf *msg, 10108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum wsc_op_code op_code) 10118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 10128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum wps_process_res res; 10138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = wps_process_msg(sta->wps, op_code, msg); 10158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res == WPS_CONTINUE) { 10168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *next = wps_get_msg(sta->wps, &op_code); 10178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (next) 10188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_er_sta_send_msg(sta, next); 10198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 10208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS ER: Protocol run %s with the " 10218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "enrollee (res=%d)", 10228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res == WPS_DONE ? "succeeded" : "failed", res); 10238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_deinit(sta->wps); 10248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sta->wps = NULL; 10258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res == WPS_DONE) { 10268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Remove the STA entry after short timeout */ 10278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(wps_er_sta_timeout, sta, NULL); 10288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_register_timeout(10, 0, wps_er_sta_timeout, sta, 10298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NULL); 10308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 10338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wps_er_sta_start(struct wps_er_sta *sta, struct wpabuf *msg) 10368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 10378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wps_config cfg; 10388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sta->wps) 10408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_deinit(sta->wps); 10418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&cfg, 0, sizeof(cfg)); 10438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cfg.wps = sta->ap->er->wps; 10448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cfg.registrar = 1; 10458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cfg.peer_addr = sta->addr; 10468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sta->wps = wps_init(&cfg); 10488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sta->wps == NULL) 10498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 10508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sta->wps->er = 1; 10518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sta->wps->use_cred = sta->ap->ap_settings; 10528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sta->ap->ap_settings) { 10538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(sta->cred); 10548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sta->cred = os_malloc(sizeof(*sta->cred)); 10558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sta->cred) { 10568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(sta->cred, sta->ap->ap_settings, 10578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sizeof(*sta->cred)); 10588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sta->cred->cred_attr = NULL; 10598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(sta->cred->mac_addr, sta->addr, ETH_ALEN); 10608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sta->wps->use_cred = sta->cred; 10618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_er_sta_process(sta, msg, WSC_MSG); 10658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 10668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wps_er_process_wlanevent_eap(struct wps_er_ap *ap, const u8 *addr, 10698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *msg) 10708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 10718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wps_parse_attr attr; 10728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wps_er_sta *sta; 10738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS ER: WLANEvent - EAP - from " MACSTR, 10758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(addr)); 10768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_buf(MSG_MSGDUMP, "WPS ER: WLANEvent - Enrollee's message " 10778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(TLVs from EAP-WSC)", msg); 10788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wps_parse_msg(msg, &attr) < 0) { 10808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS ER: Failed to parse TLVs in " 10818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WLANEvent message"); 10828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 10838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sta = wps_er_add_sta_data(ap, addr, &attr, 0); 10868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sta == NULL) 10878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 10888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (attr.msg_type && *attr.msg_type == WPS_M1) 10908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_er_sta_start(sta, msg); 10918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (sta->wps) { 10928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum wsc_op_code op_code = WSC_MSG; 10938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (attr.msg_type) { 10948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (*attr.msg_type) { 10958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPS_WSC_ACK: 10968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt op_code = WSC_ACK; 10978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 10988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPS_WSC_NACK: 10998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt op_code = WSC_NACK; 11008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 11018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPS_WSC_DONE: 11028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt op_code = WSC_Done; 11038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 11048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_er_sta_process(sta, msg, op_code); 11078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 11098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wps_er_process_wlanevent(struct wps_er_ap *ap, 11128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *event) 11138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 11148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *data; 11158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 wlan_event_type; 11168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 wlan_event_mac[ETH_ALEN]; 11178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf msg; 11188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "WPS ER: Received WLANEvent", 11208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_head(event), wpabuf_len(event)); 11218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpabuf_len(event) < 1 + 17) { 11228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS ER: Too short WLANEvent"); 11238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 11248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data = wpabuf_mhead(event); 11278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wlan_event_type = data[0]; 11288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hwaddr_aton((char *) data + 1, wlan_event_mac) < 0) { 11298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS ER: Invalid WLANEventMAC in " 11308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WLANEvent"); 11318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 11328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_set(&msg, data + 1 + 17, wpabuf_len(event) - (1 + 17)); 11358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (wlan_event_type) { 11378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case 1: 11388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_er_process_wlanevent_probe_req(ap, wlan_event_mac, &msg); 11398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 11408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case 2: 11418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_er_process_wlanevent_eap(ap, wlan_event_mac, &msg); 11428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 11438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 11448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS ER: Unknown WLANEventType %d", 11458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wlan_event_type); 11468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 11478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 11498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wps_er_http_event(struct wps_er *er, struct http_request *req, 11528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt unsigned int ap_id) 11538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 11548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wps_er_ap *ap = wps_er_ap_get_id(er, ap_id); 11558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *event; 11568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum http_reply_code ret; 11578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ap == NULL) { 11598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS ER: HTTP event from unknown AP id " 11608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "%u", ap_id); 11618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_er_http_resp_not_found(req); 11628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 11638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_MSGDUMP, "WPS ER: HTTP event from AP id %u: %s", 11658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap_id, http_request_get_data(req)); 11668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt event = xml_get_base64_item(http_request_get_data(req), "WLANEvent", 11688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &ret); 11698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (event == NULL) { 11708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS ER: Could not extract WLANEvent " 11718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "from the event notification"); 11728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 11738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Reply with OK anyway to avoid getting unregistered from 11748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * events. 11758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 11768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_er_http_resp_ok(req); 11778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 11788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_er_process_wlanevent(ap, event); 11818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(event); 11838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_er_http_resp_ok(req); 11848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 11858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wps_er_http_notify(struct wps_er *er, struct http_request *req) 11888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 11898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *uri = http_request_get_uri(req); 11908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strncmp(uri, "/event/", 7) == 0) { 11928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt unsigned int event_id; 11938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *pos; 11948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt event_id = atoi(uri + 7); 11958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (event_id != er->event_id) { 11968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS ER: HTTP event for an " 11978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "unknown event id %u", event_id); 11988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 11998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = os_strchr(uri + 7, '/'); 12018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos == NULL) 12028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 12038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos++; 12048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_er_http_event(er, req, atoi(pos)); 12058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 12068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS ER: Unknown HTTP NOTIFY for '%s'", 12078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt uri); 12088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_er_http_resp_not_found(req); 12098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 12118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wps_er_http_req(void *ctx, struct http_request *req) 12148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 12158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wps_er *er = ctx; 12168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct sockaddr_in *cli = http_request_get_cli_addr(req); 12178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum httpread_hdr_type type = http_request_get_type(req); 12188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *buf; 12198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS ER: HTTP request: '%s' (type %d) from " 12218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "%s:%d", 12228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt http_request_get_uri(req), type, 12238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt inet_ntoa(cli->sin_addr), ntohs(cli->sin_port)); 12248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (type) { 12268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case HTTPREAD_HDR_TYPE_NOTIFY: 12278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_er_http_notify(er, req); 12288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 12298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 12308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS ER: Unsupported HTTP request type " 12318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "%d", type); 12328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf = wpabuf_alloc(200); 12338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (buf == NULL) { 12348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt http_request_deinit(req); 12358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 12368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_str(buf, 12388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "HTTP/1.1 501 Unimplemented\r\n" 12398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Connection: close\r\n"); 12408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt http_put_date(buf); 12418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_str(buf, "\r\n"); 12428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt http_request_send_and_deinit(req, buf); 12438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 12448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 12468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wps_er * 12498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtwps_er_init(struct wps_context *wps, const char *ifname, const char *filter) 12508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 12518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wps_er *er; 12528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct in_addr addr; 12538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt er = os_zalloc(sizeof(*er)); 12558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (er == NULL) 12568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 12578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dl_list_init(&er->ap); 12588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dl_list_init(&er->ap_unsubscribing); 12598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dl_list_init(&er->ap_settings); 12608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt er->multicast_sd = -1; 12628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt er->ssdp_sd = -1; 12638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_strlcpy(er->ifname, ifname, sizeof(er->ifname)); 12658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt er->wps = wps; 12668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_get_random((unsigned char *) &er->event_id, 12678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sizeof(er->event_id)) < 0) { 12688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_er_deinit(er, NULL, NULL); 12698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 12708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Limit event_id to < 32 bits to avoid issues with atoi() */ 12728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt er->event_id &= 0x0fffffff; 12738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12744b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt if (filter && os_strncmp(filter, "ifname=", 7) == 0) { 12754b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt const char *pos, *end; 12764b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt pos = filter + 7; 12774b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt end = os_strchr(pos, ' '); 12784b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt if (end) { 12794b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt size_t len = end - pos; 12804b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt os_strlcpy(er->ifname, pos, len < sizeof(er->ifname) ? 12814b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt len + 1 : sizeof(er->ifname)); 12824b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt filter = end + 1; 12834b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt } else { 12844b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt os_strlcpy(er->ifname, pos, sizeof(er->ifname)); 12854b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt filter = NULL; 12864b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt } 12874b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt er->forced_ifname = 1; 12884b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt } 12894b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt 12908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (filter) { 12918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (inet_aton(filter, &er->filter_addr) == 0) { 12928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "WPS UPnP: Invalid filter " 12938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "address %s", filter); 12948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_er_deinit(er, NULL, NULL); 12958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 12968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS UPnP: Only accepting connections " 12988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "with %s", filter); 12998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13004b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt if (get_netif_info(er->ifname, &er->ip_addr, &er->ip_addr_text, 13018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt er->mac_addr)) { 13028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "WPS UPnP: Could not get IP/MAC address " 13034b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt "for %s. Does it have IP address?", er->ifname); 13048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_er_deinit(er, NULL, NULL); 13058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 13068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wps_er_ssdp_init(er) < 0) { 13098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "WPS UPnP: SSDP initialization failed"); 13108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_er_deinit(er, NULL, NULL); 13118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 13128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr.s_addr = er->ip_addr; 13158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt er->http_srv = http_server_init(&addr, -1, wps_er_http_req, er); 13168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (er->http_srv == NULL) { 13178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "WPS UPnP: HTTP initialization failed"); 13188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_er_deinit(er, NULL, NULL); 13198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 13208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt er->http_port = http_server_get_port(er->http_srv); 13228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS ER: Start (ifname=%s ip_addr=%s)", 13248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt er->ifname, er->ip_addr_text); 13258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return er; 13278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 13288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wps_er_refresh(struct wps_er *er) 13318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 13328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wps_er_ap *ap; 13338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wps_er_sta *sta; 13348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dl_list_for_each(ap, &er->ap, struct wps_er_ap, list) { 13368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_er_ap_event(er->wps, ap, WPS_EV_ER_AP_ADD); 13378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dl_list_for_each(sta, &ap->sta, struct wps_er_sta, list) 13388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_er_sta_event(er->wps, sta, WPS_EV_ER_ENROLLEE_ADD); 13398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_er_send_ssdp_msearch(er); 13428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 13438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wps_er_deinit_finish(void *eloop_data, void *user_ctx) 13468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 13478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wps_er *er = eloop_data; 13488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void (*deinit_done_cb)(void *ctx); 13498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void *deinit_done_ctx; 1350fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt struct wps_er_ap *ap, *tmp; 13518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS ER: Finishing deinit"); 13538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1354fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt dl_list_for_each_safe(ap, tmp, &er->ap_unsubscribing, struct wps_er_ap, 1355fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt list) { 1356fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS ER: AP entry for %s (%s) still in ap_unsubscribing list - free it", 1357fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt inet_ntoa(ap->addr), ap->location); 1358fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt dl_list_del(&ap->list); 1359fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt wps_er_ap_free(ap); 1360fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt } 1361fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt 1362fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt eloop_cancel_timeout(wps_er_deinit_finish, er, NULL); 13638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt deinit_done_cb = er->deinit_done_cb; 13648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt deinit_done_ctx = er->deinit_done_ctx; 13658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(er->ip_addr_text); 13668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(er); 13678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (deinit_done_cb) 13698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt deinit_done_cb(deinit_done_ctx); 13708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 13718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wps_er_deinit(struct wps_er *er, void (*cb)(void *ctx), void *ctx) 13748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 13758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (er == NULL) 13768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 13778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt http_server_deinit(er->http_srv); 13788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_er_ap_remove_all(er); 13798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_er_ssdp_deinit(er); 13808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_register_timeout(dl_list_empty(&er->ap_unsubscribing) ? 0 : 5, 0, 13818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_er_deinit_finish, er, NULL); 13828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS ER: Finish deinit from timeout"); 13838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt er->deinitializing = 1; 13848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt er->deinit_done_cb = cb; 13858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt er->deinit_done_ctx = ctx; 13868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 13878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wps_er_http_set_sel_reg_cb(void *ctx, struct http_client *c, 13908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum http_client_event event) 13918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 13928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wps_er_ap *ap = ctx; 13938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt union wps_event_data data; 13948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&data, 0, sizeof(data)); 13968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (event) { 13988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case HTTP_CLIENT_OK: 13998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS ER: SetSelectedRegistrar OK"); 14008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data.set_sel_reg.state = WPS_ER_SET_SEL_REG_DONE; 14018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data.set_sel_reg.uuid = ap->uuid; 14028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 14038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case HTTP_CLIENT_FAILED: 14048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case HTTP_CLIENT_INVALID_REPLY: 14058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case HTTP_CLIENT_TIMEOUT: 14068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS ER: SetSelectedRegistrar failed"); 14078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data.set_sel_reg.state = WPS_ER_SET_SEL_REG_FAILED; 14088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data.set_sel_reg.uuid = ap->uuid; 14098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 14108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 14118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt http_client_free(ap->http); 14128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap->http = NULL; 14138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data.set_sel_reg.uuid) 14158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap->er->wps->event_cb(ap->er->wps->cb_ctx, 14168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPS_EV_ER_SET_SELECTED_REGISTRAR, &data); 14178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 14188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wps_er_send_set_sel_reg(struct wps_er_ap *ap, struct wpabuf *msg) 14218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 14228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *buf; 14238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *len_ptr, *body_ptr; 14248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct sockaddr_in dst; 14258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *url, *path; 14268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ap->control_url == NULL) { 14288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS ER: No controlURL for AP"); 14298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 14308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 14318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ap->http) { 14338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS ER: Pending HTTP request for AP - " 14348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "ignore new request"); 14358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 14368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 14378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ap->wps) { 14398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS ER: Pending WPS operation for AP - " 14408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "skip SetSelectedRegistrar"); 14418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 14428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 14438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt url = http_client_url_parse(ap->control_url, &dst, &path); 14458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (url == NULL) { 14468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS ER: Failed to parse controlURL"); 14478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 14488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 14498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf = wps_er_soap_hdr(msg, "SetSelectedRegistrar", "NewMessage", path, 14518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &dst, &len_ptr, &body_ptr); 14528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(url); 14538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (buf == NULL) 14548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 14558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_er_soap_end(buf, "SetSelectedRegistrar", len_ptr, body_ptr); 14578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap->http = http_client_addr(&dst, buf, 1000, 14598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_er_http_set_sel_reg_cb, ap); 14608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ap->http == NULL) 14618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(buf); 14628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 14638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wps_er_build_selected_registrar(struct wpabuf *msg, int sel_reg) 14668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 14678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_be16(msg, ATTR_SELECTED_REGISTRAR); 14688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_be16(msg, 1); 14698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_u8(msg, !!sel_reg); 14708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 14718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 14728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wps_er_build_dev_password_id(struct wpabuf *msg, u16 dev_passwd_id) 14758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 14768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_be16(msg, ATTR_DEV_PASSWORD_ID); 14778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_be16(msg, 2); 14788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_be16(msg, dev_passwd_id); 14798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 14808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 14818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wps_er_build_sel_reg_config_methods(struct wpabuf *msg, 14848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 sel_reg_config_methods) 14858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 14868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_be16(msg, ATTR_SELECTED_REGISTRAR_CONFIG_METHODS); 14878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_be16(msg, 2); 14888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_be16(msg, sel_reg_config_methods); 14898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 14908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 14918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wps_er_build_uuid_r(struct wpabuf *msg, const u8 *uuid_r) 14948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 14958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_be16(msg, ATTR_UUID_R); 14968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_be16(msg, WPS_UUID_LEN); 14978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_data(msg, uuid_r, WPS_UUID_LEN); 14988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 14998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 15008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wps_er_set_sel_reg(struct wps_er *er, int sel_reg, u16 dev_passwd_id, 15038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 sel_reg_config_methods) 15048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 15058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *msg; 15068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wps_er_ap *ap; 15078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wps_registrar *reg = er->wps->registrar; 15088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *auth_macs; 15098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 bcast[ETH_ALEN]; 15108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t count; 15118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt union wps_event_data data; 15128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (er->skip_set_sel_reg) { 15148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS ER: Skip SetSelectedRegistrar"); 15158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 15168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 15178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = wpabuf_alloc(500); 15198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (msg == NULL) 15208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 15218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt auth_macs = wps_authorized_macs(reg, &count); 15238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (count == 0) { 15248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(bcast, 0xff, ETH_ALEN); 15258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt auth_macs = bcast; 15268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt count = 1; 15278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 15288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wps_build_version(msg) || 15308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_er_build_selected_registrar(msg, sel_reg) || 15318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_er_build_dev_password_id(msg, dev_passwd_id) || 15328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_er_build_sel_reg_config_methods(msg, sel_reg_config_methods) || 15338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_build_wfa_ext(msg, 0, auth_macs, count) || 15348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_er_build_uuid_r(msg, er->wps->uuid)) { 15358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(msg); 15368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 15378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 15388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&data, 0, sizeof(data)); 15408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data.set_sel_reg.sel_reg = sel_reg; 15418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data.set_sel_reg.dev_passwd_id = dev_passwd_id; 15428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data.set_sel_reg.sel_reg_config_methods = sel_reg_config_methods; 15438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data.set_sel_reg.state = WPS_ER_SET_SEL_REG_START; 15448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dl_list_for_each(ap, &er->ap, struct wps_er_ap, list) { 15468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (er->set_sel_reg_uuid_filter && 15478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcmp(ap->uuid, er->set_sel_reg_uuid_filter, 15488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPS_UUID_LEN) != 0) 15498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt continue; 15508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data.set_sel_reg.uuid = ap->uuid; 15518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt er->wps->event_cb(er->wps->cb_ctx, 15528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPS_EV_ER_SET_SELECTED_REGISTRAR, &data); 15538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_er_send_set_sel_reg(ap, msg); 15548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 15558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(msg); 15578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 15588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15601e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidtint wps_er_pbc(struct wps_er *er, const u8 *uuid, const u8 *addr) 15618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 15628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int res; 15638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wps_er_ap *ap; 15648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (er == NULL || er->wps == NULL) 15668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 15678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wps_registrar_pbc_overlap(er->wps->registrar, NULL, NULL)) { 15698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS ER: PBC overlap - do not start PBC " 15708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "mode"); 15718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -2; 15728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 15738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15741e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidt if (uuid) 15751e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidt ap = wps_er_ap_get(er, NULL, uuid, NULL); 15761e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidt else 15771e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidt ap = NULL; 15788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ap == NULL) { 15798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wps_er_sta *sta = NULL; 15808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dl_list_for_each(ap, &er->ap, struct wps_er_ap, list) { 15811e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidt sta = wps_er_sta_get(ap, addr, uuid); 15828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sta) { 15838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt uuid = ap->uuid; 15848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 15858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 15868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 15878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sta == NULL) 15888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -3; /* Unknown UUID */ 15898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 15908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ap->ap_settings == NULL) { 15928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS ER: AP settings not known"); 15938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -4; 15948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 15958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt er->set_sel_reg_uuid_filter = uuid; 15978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = wps_registrar_button_pushed(er->wps->registrar, NULL); 15988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt er->set_sel_reg_uuid_filter = NULL; 15998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res) 16008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 16018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 16038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 16048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wps_er_ap_settings_cb(void *ctx, const struct wps_credential *cred) 16078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 16088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wps_er_ap *ap = ctx; 16098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt union wps_event_data data; 16108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS ER: AP Settings received"); 16128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(ap->ap_settings); 16138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap->ap_settings = os_malloc(sizeof(*cred)); 16148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ap->ap_settings) { 16158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(ap->ap_settings, cred, sizeof(*cred)); 16168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap->ap_settings->cred_attr = NULL; 16178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 16188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&data, 0, sizeof(data)); 16208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data.ap_settings.uuid = ap->uuid; 16218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data.ap_settings.cred = cred; 16228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap->er->wps->event_cb(ap->er->wps->cb_ctx, WPS_EV_ER_AP_SETTINGS, 16238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &data); 16248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 16258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16271e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidtconst u8 * wps_er_get_sta_uuid(struct wps_er *er, const u8 *addr) 16281e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidt{ 16291e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidt struct wps_er_ap *ap; 16301e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidt dl_list_for_each(ap, &er->ap, struct wps_er_ap, list) { 16311e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidt struct wps_er_sta *sta; 16321e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidt sta = wps_er_sta_get(ap, addr, NULL); 16331e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidt if (sta) 16341e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidt return sta->uuid; 16351e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidt } 16361e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidt return NULL; 16371e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidt} 16381e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidt 16391e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidt 16408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wps_er_http_put_message_cb(void *ctx, struct http_client *c, 16418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum http_client_event event) 16428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 16438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wps_er_ap *ap = ctx; 16448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *reply; 16458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *msg = NULL; 16468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (event) { 16488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case HTTP_CLIENT_OK: 16498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS ER: PutMessage OK"); 16508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt reply = http_client_get_body(c); 1651d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (reply) 1652d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt msg = os_zalloc(wpabuf_len(reply) + 1); 1653d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (msg == NULL) { 1654d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (ap->wps) { 1655d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt wps_deinit(ap->wps); 1656d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt ap->wps = NULL; 1657d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt } 16588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 1659d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt } 16608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(msg, wpabuf_head(reply), wpabuf_len(reply)); 16618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 16628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case HTTP_CLIENT_FAILED: 16638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case HTTP_CLIENT_INVALID_REPLY: 16648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case HTTP_CLIENT_TIMEOUT: 16658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS ER: PutMessage failed"); 16668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ap->wps) { 16678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_deinit(ap->wps); 16688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap->wps = NULL; 16698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 16708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 16718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 16728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt http_client_free(ap->http); 16738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap->http = NULL; 16748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (msg) { 16768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *buf; 16778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum http_reply_code ret; 16788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf = xml_get_base64_item(msg, "NewOutMessage", &ret); 16798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(msg); 16808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (buf == NULL) { 16818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS ER: Could not extract " 16828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "NewOutMessage from PutMessage response"); 16838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_deinit(ap->wps); 16848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap->wps = NULL; 16858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 16868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 16878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_er_ap_process(ap, buf); 16888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(buf); 16898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 16908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 16918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wps_er_ap_put_message(struct wps_er_ap *ap, 16948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpabuf *msg) 16958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 16968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *buf; 16978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *len_ptr, *body_ptr; 16988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct sockaddr_in dst; 16998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *url, *path; 17008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ap->http) { 17028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS ER: Pending HTTP operation ongoing " 17038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "with the AP - cannot continue learn"); 17048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 17058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 17068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ap->control_url == NULL) { 17088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS ER: No controlURL for AP"); 17098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 17108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 17118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt url = http_client_url_parse(ap->control_url, &dst, &path); 17138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (url == NULL) { 17148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS ER: Failed to parse controlURL"); 1715d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt goto fail; 17168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 17178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf = wps_er_soap_hdr(msg, "PutMessage", "NewInMessage", path, &dst, 17198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &len_ptr, &body_ptr); 17208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(url); 17218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (buf == NULL) 1722d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt goto fail; 17238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_er_soap_end(buf, "PutMessage", len_ptr, body_ptr); 17258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap->http = http_client_addr(&dst, buf, 10000, 17278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_er_http_put_message_cb, ap); 1728d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (ap->http == NULL) { 17298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(buf); 1730d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt goto fail; 1731d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt } 1732d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt return; 1733d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 1734d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidtfail: 1735d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (ap->wps) { 1736d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt wps_deinit(ap->wps); 1737d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt ap->wps = NULL; 1738d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt } 17398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 17408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wps_er_ap_process(struct wps_er_ap *ap, struct wpabuf *msg) 17438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 17448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum wps_process_res res; 17458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wps_parse_attr attr; 17468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum wsc_op_code op_code; 17478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt op_code = WSC_MSG; 17498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wps_parse_msg(msg, &attr) == 0 && attr.msg_type) { 17508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (*attr.msg_type) { 17518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPS_WSC_ACK: 17528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt op_code = WSC_ACK; 17538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 17548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPS_WSC_NACK: 17558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt op_code = WSC_NACK; 17568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 17578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPS_WSC_DONE: 17588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt op_code = WSC_Done; 17598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 17608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 17618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 17628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = wps_process_msg(ap->wps, op_code, msg); 17648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res == WPS_CONTINUE) { 17658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *next = wps_get_msg(ap->wps, &op_code); 17668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (next) { 17678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_er_ap_put_message(ap, next); 17688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(next); 17698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 17708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS ER: Failed to build " 17718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "message"); 17728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_deinit(ap->wps); 17738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap->wps = NULL; 17748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 17758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (res == WPS_DONE) { 17768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS ER: Protocol run done"); 17778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_deinit(ap->wps); 17788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap->wps = NULL; 17798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 17808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS ER: Failed to process message from " 17818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "AP (res=%d)", res); 17828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_deinit(ap->wps); 17838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap->wps = NULL; 17848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 17858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 17868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wps_er_ap_learn_m1(struct wps_er_ap *ap, struct wpabuf *m1) 17898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 17908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wps_config cfg; 17918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ap->wps) { 17938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS ER: Protocol run already in " 17948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "progress with this AP"); 17958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 17968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 17978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&cfg, 0, sizeof(cfg)); 17998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cfg.wps = ap->er->wps; 18008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cfg.registrar = 1; 18018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap->wps = wps_init(&cfg); 18028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ap->wps == NULL) 18038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 18048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap->wps->ap_settings_cb = wps_er_ap_settings_cb; 18058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap->wps->ap_settings_cb_ctx = ap; 18068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_er_ap_process(ap, m1); 18088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 18098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wps_er_ap_learn(struct wps_er_ap *ap, const char *dev_info) 18128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 18138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *info; 18148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum http_reply_code ret; 18158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS ER: Received GetDeviceInfo response (M1) " 18178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "from the AP"); 18188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt info = xml_get_base64_item(dev_info, "NewDeviceInfo", &ret); 18198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (info == NULL) { 18208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS ER: Could not extract " 18218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "NewDeviceInfo from GetDeviceInfo response"); 18228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 18238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 18248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap->m1_handler(ap, info); 18268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(info); 18278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 18288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wps_er_http_get_dev_info_cb(void *ctx, struct http_client *c, 18318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum http_client_event event) 18328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 18338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wps_er_ap *ap = ctx; 18348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *reply; 18358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *dev_info = NULL; 18368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (event) { 18388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case HTTP_CLIENT_OK: 18398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS ER: GetDeviceInfo OK"); 18408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt reply = http_client_get_body(c); 18418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (reply == NULL) 18428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 18438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dev_info = os_zalloc(wpabuf_len(reply) + 1); 18448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (dev_info == NULL) 18458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 18468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(dev_info, wpabuf_head(reply), wpabuf_len(reply)); 18478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 18488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case HTTP_CLIENT_FAILED: 18498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case HTTP_CLIENT_INVALID_REPLY: 18508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case HTTP_CLIENT_TIMEOUT: 18518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS ER: GetDeviceInfo failed"); 18528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 18538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 18548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt http_client_free(ap->http); 18558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap->http = NULL; 18568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (dev_info) { 18588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_er_ap_learn(ap, dev_info); 18598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(dev_info); 18608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 18618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 18628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wps_er_send_get_device_info(struct wps_er_ap *ap, 18658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void (*m1_handler)(struct wps_er_ap *ap, 18668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *m1)) 18678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 18688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *buf; 18698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *len_ptr, *body_ptr; 18708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct sockaddr_in dst; 18718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *url, *path; 18728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ap->http) { 18748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS ER: Pending HTTP operation ongoing " 18758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "with the AP - cannot get device info"); 18768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 18778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 18788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ap->control_url == NULL) { 18808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS ER: No controlURL for AP"); 18818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 18828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 18838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt url = http_client_url_parse(ap->control_url, &dst, &path); 18858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (url == NULL) { 18868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS ER: Failed to parse controlURL"); 18878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 18888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 18898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf = wps_er_soap_hdr(NULL, "GetDeviceInfo", NULL, path, &dst, 18918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &len_ptr, &body_ptr); 18928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(url); 18938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (buf == NULL) 18948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 18958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_er_soap_end(buf, "GetDeviceInfo", len_ptr, body_ptr); 18978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap->http = http_client_addr(&dst, buf, 10000, 18998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_er_http_get_dev_info_cb, ap); 19008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ap->http == NULL) { 19018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(buf); 19028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 19038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 19048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap->m1_handler = m1_handler; 19068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 19088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 19098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19111e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidtint wps_er_learn(struct wps_er *er, const u8 *uuid, const u8 *addr, 19121e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidt const u8 *pin, size_t pin_len) 19138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 19148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wps_er_ap *ap; 19158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (er == NULL) 19178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 19188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19191e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidt ap = wps_er_ap_get(er, NULL, uuid, addr); 19208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ap == NULL) { 19218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS ER: AP not found for learn " 19228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "request"); 19238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 19248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 19251e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidt if (uuid == NULL) 19261e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidt uuid = ap->uuid; 19278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ap->wps) { 19288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS ER: Pending operation ongoing " 19298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "with the AP - cannot start learn"); 19308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 19318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 19328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wps_er_send_get_device_info(ap, wps_er_ap_learn_m1) < 0) 19348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 19358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt er->skip_set_sel_reg = 1; 19378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_registrar_add_pin(er->wps->registrar, NULL, uuid, pin, pin_len, 0); 19388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt er->skip_set_sel_reg = 0; 19398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 19418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 19428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19441e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidtint wps_er_set_config(struct wps_er *er, const u8 *uuid, const u8 *addr, 19458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wps_credential *cred) 19468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 19478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wps_er_ap *ap; 19488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (er == NULL) 19508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 19518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19521e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidt ap = wps_er_ap_get(er, NULL, uuid, addr); 19538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ap == NULL) { 19548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS ER: AP not found for set config " 19558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "request"); 19568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 19578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 19588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(ap->ap_settings); 1960d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt ap->ap_settings = os_memdup(cred, sizeof(*cred)); 19618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ap->ap_settings == NULL) 19628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 19638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap->ap_settings->cred_attr = NULL; 19648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS ER: Updated local AP settings based set " 19658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "config request"); 19668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 19688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 19698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wps_er_ap_config_m1(struct wps_er_ap *ap, struct wpabuf *m1) 19728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 19738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wps_config cfg; 19748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ap->wps) { 19768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS ER: Protocol run already in " 19778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "progress with this AP"); 19788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 19798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 19808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&cfg, 0, sizeof(cfg)); 19828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cfg.wps = ap->er->wps; 19838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cfg.registrar = 1; 19848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cfg.new_ap_settings = ap->ap_settings; 19858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap->wps = wps_init(&cfg); 19868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ap->wps == NULL) 19878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 19888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap->wps->ap_settings_cb = NULL; 19898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap->wps->ap_settings_cb_ctx = NULL; 19908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_er_ap_process(ap, m1); 19928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 19938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19951e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidtint wps_er_config(struct wps_er *er, const u8 *uuid, const u8 *addr, 19961e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidt const u8 *pin, size_t pin_len, 19971e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidt const struct wps_credential *cred) 19988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 19998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wps_er_ap *ap; 20008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (er == NULL) 20028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 20038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20041e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidt ap = wps_er_ap_get(er, NULL, uuid, addr); 20058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ap == NULL) { 20068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS ER: AP not found for config " 20078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "request"); 20088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 20098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 20101e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidt if (uuid == NULL) 20111e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidt uuid = ap->uuid; 20128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ap->wps) { 20138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS ER: Pending operation ongoing " 20148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "with the AP - cannot start config"); 20158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 20168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 20178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(ap->ap_settings); 2019d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt ap->ap_settings = os_memdup(cred, sizeof(*cred)); 20208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ap->ap_settings == NULL) 20218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 20228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap->ap_settings->cred_attr = NULL; 20238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wps_er_send_get_device_info(ap, wps_er_ap_config_m1) < 0) 20258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 20268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt er->skip_set_sel_reg = 1; 20288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_registrar_add_pin(er->wps->registrar, NULL, uuid, pin, pin_len, 0); 20298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt er->skip_set_sel_reg = 0; 20308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 20328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 203304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 203404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 203504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#ifdef CONFIG_WPS_NFC 20361e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidt 20371e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidtstruct wpabuf * wps_er_config_token_from_cred(struct wps_context *wps, 20381e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidt struct wps_credential *cred) 203904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{ 204004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt struct wpabuf *ret; 204104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt struct wps_data data; 204204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 204304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt ret = wpabuf_alloc(500); 204404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (ret == NULL) 204504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return NULL; 204604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 204704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt os_memset(&data, 0, sizeof(data)); 20481e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidt data.wps = wps; 20491e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidt data.use_cred = cred; 2050cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt if (wps_build_cred(&data, ret) || 205104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wps_build_wfa_ext(ret, 0, NULL, 0)) { 205204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpabuf_free(ret); 205304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return NULL; 205404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 205504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 205604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return ret; 205704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt} 20581e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidt 20591e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidt 20601e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidtstruct wpabuf * wps_er_nfc_config_token(struct wps_er *er, const u8 *uuid, 20611e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidt const u8 *addr) 20621e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidt{ 20631e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidt struct wps_er_ap *ap; 20641e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidt 20651e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidt if (er == NULL) 20661e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidt return NULL; 20671e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidt 20681e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidt ap = wps_er_ap_get(er, NULL, uuid, addr); 20691e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidt if (ap == NULL) 20701e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidt return NULL; 20711e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidt if (ap->ap_settings == NULL) { 20721e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidt wpa_printf(MSG_DEBUG, "WPS ER: No settings known for the " 20731e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidt "selected AP"); 20741e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidt return NULL; 20751e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidt } 20761e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidt 20771e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidt return wps_er_config_token_from_cred(er->wps, ap->ap_settings); 20781e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidt} 20791e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidt 2080cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 2081cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidtstruct wpabuf * wps_er_nfc_handover_sel(struct wps_er *er, 2082cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt struct wps_context *wps, const u8 *uuid, 2083cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt const u8 *addr, struct wpabuf *pubkey) 2084cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt{ 2085cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt struct wps_er_ap *ap; 2086cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 2087cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt if (er == NULL) 2088cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt return NULL; 2089cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 2090cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt ap = wps_er_ap_get(er, NULL, uuid, addr); 2091cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt if (ap == NULL) 2092cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt return NULL; 2093cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt if (ap->ap_settings == NULL) { 2094cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wpa_printf(MSG_DEBUG, "WPS ER: No settings known for the " 2095cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt "selected AP"); 2096cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt return NULL; 2097cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt } 2098cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 2099cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt os_memcpy(wps->ssid, ap->ap_settings->ssid, ap->ap_settings->ssid_len); 2100cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wps->ssid_len = ap->ap_settings->ssid_len; 2101cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 2102cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt return wps_build_nfc_handover_sel(wps, pubkey, addr, 0); 2103cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt} 2104cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 210504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#endif /* CONFIG_WPS_NFC */ 2106