summaryrefslogtreecommitdiff
path: root/src/wps/wps_er.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/wps/wps_er.c')
-rw-r--r--src/wps/wps_er.c211
1 files changed, 135 insertions, 76 deletions
diff --git a/src/wps/wps_er.c b/src/wps/wps_er.c
index 95a0dec0533cb..078ff72781a6f 100644
--- a/src/wps/wps_er.c
+++ b/src/wps/wps_er.c
@@ -1,6 +1,6 @@
/*
* Wi-Fi Protected Setup - External Registrar
- * Copyright (c) 2009-2012, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2009-2013, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -97,13 +97,16 @@ static void wps_er_sta_remove_all(struct wps_er_ap *ap)
static struct wps_er_ap * wps_er_ap_get(struct wps_er *er,
- struct in_addr *addr, const u8 *uuid)
+ struct in_addr *addr, const u8 *uuid,
+ const u8 *mac_addr)
{
struct wps_er_ap *ap;
dl_list_for_each(ap, &er->ap, struct wps_er_ap, list) {
if ((addr == NULL || ap->addr.s_addr == addr->s_addr) &&
(uuid == NULL ||
- os_memcmp(uuid, ap->uuid, WPS_UUID_LEN) == 0))
+ os_memcmp(uuid, ap->uuid, WPS_UUID_LEN) == 0) &&
+ (mac_addr == NULL ||
+ os_memcmp(mac_addr, ap->mac_addr, ETH_ALEN) == 0))
return ap;
}
return NULL;
@@ -182,10 +185,8 @@ static void wps_er_ap_unsubscribed(struct wps_er *er, struct wps_er_ap *ap)
dl_list_del(&ap->list);
wps_er_ap_free(ap);
- if (er->deinitializing && dl_list_empty(&er->ap_unsubscribing)) {
- eloop_cancel_timeout(wps_er_deinit_finish, er, NULL);
+ if (er->deinitializing && dl_list_empty(&er->ap_unsubscribing))
wps_er_deinit_finish(er, NULL);
- }
}
@@ -290,7 +291,7 @@ int wps_er_ap_cache_settings(struct wps_er *er, struct in_addr *addr)
struct wps_er_ap *ap;
struct wps_er_ap_settings *settings;
- ap = wps_er_ap_get(er, addr, NULL);
+ ap = wps_er_ap_get(er, addr, NULL, NULL);
if (ap == NULL || ap->ap_settings == NULL)
return -1;
@@ -578,12 +579,15 @@ static void wps_er_parse_device_description(struct wps_er_ap *ap,
wpa_printf(MSG_DEBUG, "WPS ER: serialNumber='%s'", ap->serial_number);
ap->udn = xml_get_first_item(data, "UDN");
- wpa_printf(MSG_DEBUG, "WPS ER: UDN='%s'", ap->udn);
- pos = os_strstr(ap->udn, "uuid:");
- if (pos) {
- pos += 5;
- if (uuid_str2bin(pos, ap->uuid) < 0)
- wpa_printf(MSG_DEBUG, "WPS ER: Invalid UUID in UDN");
+ if (ap->udn) {
+ wpa_printf(MSG_DEBUG, "WPS ER: UDN='%s'", ap->udn);
+ pos = os_strstr(ap->udn, "uuid:");
+ if (pos) {
+ pos += 5;
+ if (uuid_str2bin(pos, ap->uuid) < 0)
+ wpa_printf(MSG_DEBUG,
+ "WPS ER: Invalid UUID in UDN");
+ }
}
ap->upc = xml_get_first_item(data, "UPC");
@@ -636,7 +640,7 @@ void wps_er_ap_add(struct wps_er *er, const u8 *uuid, struct in_addr *addr,
{
struct wps_er_ap *ap;
- ap = wps_er_ap_get(er, addr, uuid);
+ ap = wps_er_ap_get(er, addr, uuid, NULL);
if (ap) {
/* Update advertisement timeout */
eloop_cancel_timeout(wps_er_ap_timeout, er, ap);
@@ -793,52 +797,31 @@ static struct wps_er_sta * wps_er_add_sta_data(struct wps_er_ap *ap,
if (attr->manufacturer) {
os_free(sta->manufacturer);
- sta->manufacturer = os_malloc(attr->manufacturer_len + 1);
- if (sta->manufacturer) {
- os_memcpy(sta->manufacturer, attr->manufacturer,
- attr->manufacturer_len);
- sta->manufacturer[attr->manufacturer_len] = '\0';
- }
+ sta->manufacturer = dup_binstr(attr->manufacturer,
+ attr->manufacturer_len);
}
if (attr->model_name) {
os_free(sta->model_name);
- sta->model_name = os_malloc(attr->model_name_len + 1);
- if (sta->model_name) {
- os_memcpy(sta->model_name, attr->model_name,
- attr->model_name_len);
- sta->model_name[attr->model_name_len] = '\0';
- }
+ sta->model_name = dup_binstr(attr->model_name,
+ attr->model_name_len);
}
if (attr->model_number) {
os_free(sta->model_number);
- sta->model_number = os_malloc(attr->model_number_len + 1);
- if (sta->model_number) {
- os_memcpy(sta->model_number, attr->model_number,
- attr->model_number_len);
- sta->model_number[attr->model_number_len] = '\0';
- }
+ sta->model_number = dup_binstr(attr->model_number,
+ attr->model_number_len);
}
if (attr->serial_number) {
os_free(sta->serial_number);
- sta->serial_number = os_malloc(attr->serial_number_len + 1);
- if (sta->serial_number) {
- os_memcpy(sta->serial_number, attr->serial_number,
- attr->serial_number_len);
- sta->serial_number[attr->serial_number_len] = '\0';
- }
+ sta->serial_number = dup_binstr(attr->serial_number,
+ attr->serial_number_len);
}
if (attr->dev_name) {
os_free(sta->dev_name);
- sta->dev_name = os_malloc(attr->dev_name_len + 1);
- if (sta->dev_name) {
- os_memcpy(sta->dev_name, attr->dev_name,
- attr->dev_name_len);
- sta->dev_name[attr->dev_name_len] = '\0';
- }
+ sta->dev_name = dup_binstr(attr->dev_name, attr->dev_name_len);
}
eloop_cancel_timeout(wps_er_sta_timeout, sta, NULL);
@@ -1289,6 +1272,22 @@ wps_er_init(struct wps_context *wps, const char *ifname, const char *filter)
/* Limit event_id to < 32 bits to avoid issues with atoi() */
er->event_id &= 0x0fffffff;
+ if (filter && os_strncmp(filter, "ifname=", 7) == 0) {
+ const char *pos, *end;
+ pos = filter + 7;
+ end = os_strchr(pos, ' ');
+ if (end) {
+ size_t len = end - pos;
+ os_strlcpy(er->ifname, pos, len < sizeof(er->ifname) ?
+ len + 1 : sizeof(er->ifname));
+ filter = end + 1;
+ } else {
+ os_strlcpy(er->ifname, pos, sizeof(er->ifname));
+ filter = NULL;
+ }
+ er->forced_ifname = 1;
+ }
+
if (filter) {
if (inet_aton(filter, &er->filter_addr) == 0) {
wpa_printf(MSG_INFO, "WPS UPnP: Invalid filter "
@@ -1299,10 +1298,10 @@ wps_er_init(struct wps_context *wps, const char *ifname, const char *filter)
wpa_printf(MSG_DEBUG, "WPS UPnP: Only accepting connections "
"with %s", filter);
}
- if (get_netif_info(ifname, &er->ip_addr, &er->ip_addr_text,
+ if (get_netif_info(er->ifname, &er->ip_addr, &er->ip_addr_text,
er->mac_addr)) {
wpa_printf(MSG_INFO, "WPS UPnP: Could not get IP/MAC address "
- "for %s. Does it have IP address?", ifname);
+ "for %s. Does it have IP address?", er->ifname);
wps_er_deinit(er, NULL, NULL);
return NULL;
}
@@ -1349,9 +1348,19 @@ static void wps_er_deinit_finish(void *eloop_data, void *user_ctx)
struct wps_er *er = eloop_data;
void (*deinit_done_cb)(void *ctx);
void *deinit_done_ctx;
+ struct wps_er_ap *ap, *tmp;
wpa_printf(MSG_DEBUG, "WPS ER: Finishing deinit");
+ dl_list_for_each_safe(ap, tmp, &er->ap_unsubscribing, struct wps_er_ap,
+ list) {
+ wpa_printf(MSG_DEBUG, "WPS ER: AP entry for %s (%s) still in ap_unsubscribing list - free it",
+ inet_ntoa(ap->addr), ap->location);
+ dl_list_del(&ap->list);
+ wps_er_ap_free(ap);
+ }
+
+ eloop_cancel_timeout(wps_er_deinit_finish, er, NULL);
deinit_done_cb = er->deinit_done_cb;
deinit_done_ctx = er->deinit_done_ctx;
os_free(er->ip_addr_text);
@@ -1484,11 +1493,9 @@ static int wps_er_build_sel_reg_config_methods(struct wpabuf *msg,
static int wps_er_build_uuid_r(struct wpabuf *msg, const u8 *uuid_r)
{
-#ifdef CONFIG_WPS2
wpabuf_put_be16(msg, ATTR_UUID_R);
wpabuf_put_be16(msg, WPS_UUID_LEN);
wpabuf_put_data(msg, uuid_r, WPS_UUID_LEN);
-#endif /* CONFIG_WPS2 */
return 0;
}
@@ -1500,9 +1507,7 @@ void wps_er_set_sel_reg(struct wps_er *er, int sel_reg, u16 dev_passwd_id,
struct wps_er_ap *ap;
struct wps_registrar *reg = er->wps->registrar;
const u8 *auth_macs;
-#ifdef CONFIG_WPS2
u8 bcast[ETH_ALEN];
-#endif /* CONFIG_WPS2 */
size_t count;
union wps_event_data data;
@@ -1516,13 +1521,11 @@ void wps_er_set_sel_reg(struct wps_er *er, int sel_reg, u16 dev_passwd_id,
return;
auth_macs = wps_authorized_macs(reg, &count);
-#ifdef CONFIG_WPS2
if (count == 0) {
os_memset(bcast, 0xff, ETH_ALEN);
auth_macs = bcast;
count = 1;
}
-#endif /* CONFIG_WPS2 */
if (wps_build_version(msg) ||
wps_er_build_selected_registrar(msg, sel_reg) ||
@@ -1555,7 +1558,7 @@ void wps_er_set_sel_reg(struct wps_er *er, int sel_reg, u16 dev_passwd_id,
}
-int wps_er_pbc(struct wps_er *er, const u8 *uuid)
+int wps_er_pbc(struct wps_er *er, const u8 *uuid, const u8 *addr)
{
int res;
struct wps_er_ap *ap;
@@ -1569,11 +1572,14 @@ int wps_er_pbc(struct wps_er *er, const u8 *uuid)
return -2;
}
- ap = wps_er_ap_get(er, NULL, uuid);
+ if (uuid)
+ ap = wps_er_ap_get(er, NULL, uuid, NULL);
+ else
+ ap = NULL;
if (ap == NULL) {
struct wps_er_sta *sta = NULL;
dl_list_for_each(ap, &er->ap, struct wps_er_ap, list) {
- sta = wps_er_sta_get(ap, NULL, uuid);
+ sta = wps_er_sta_get(ap, addr, uuid);
if (sta) {
uuid = ap->uuid;
break;
@@ -1619,6 +1625,19 @@ static void wps_er_ap_settings_cb(void *ctx, const struct wps_credential *cred)
}
+const u8 * wps_er_get_sta_uuid(struct wps_er *er, const u8 *addr)
+{
+ struct wps_er_ap *ap;
+ dl_list_for_each(ap, &er->ap, struct wps_er_ap, list) {
+ struct wps_er_sta *sta;
+ sta = wps_er_sta_get(ap, addr, NULL);
+ if (sta)
+ return sta->uuid;
+ }
+ return NULL;
+}
+
+
static void wps_er_http_put_message_cb(void *ctx, struct http_client *c,
enum http_client_event event)
{
@@ -1877,20 +1896,22 @@ static int wps_er_send_get_device_info(struct wps_er_ap *ap,
}
-int wps_er_learn(struct wps_er *er, const u8 *uuid, const u8 *pin,
- size_t pin_len)
+int wps_er_learn(struct wps_er *er, const u8 *uuid, const u8 *addr,
+ const u8 *pin, size_t pin_len)
{
struct wps_er_ap *ap;
if (er == NULL)
return -1;
- ap = wps_er_ap_get(er, NULL, uuid);
+ ap = wps_er_ap_get(er, NULL, uuid, addr);
if (ap == NULL) {
wpa_printf(MSG_DEBUG, "WPS ER: AP not found for learn "
"request");
return -1;
}
+ if (uuid == NULL)
+ uuid = ap->uuid;
if (ap->wps) {
wpa_printf(MSG_DEBUG, "WPS ER: Pending operation ongoing "
"with the AP - cannot start learn");
@@ -1908,7 +1929,7 @@ int wps_er_learn(struct wps_er *er, const u8 *uuid, const u8 *pin,
}
-int wps_er_set_config(struct wps_er *er, const u8 *uuid,
+int wps_er_set_config(struct wps_er *er, const u8 *uuid, const u8 *addr,
const struct wps_credential *cred)
{
struct wps_er_ap *ap;
@@ -1916,7 +1937,7 @@ int wps_er_set_config(struct wps_er *er, const u8 *uuid,
if (er == NULL)
return -1;
- ap = wps_er_ap_get(er, NULL, uuid);
+ ap = wps_er_ap_get(er, NULL, uuid, addr);
if (ap == NULL) {
wpa_printf(MSG_DEBUG, "WPS ER: AP not found for set config "
"request");
@@ -1960,20 +1981,23 @@ static void wps_er_ap_config_m1(struct wps_er_ap *ap, struct wpabuf *m1)
}
-int wps_er_config(struct wps_er *er, const u8 *uuid, const u8 *pin,
- size_t pin_len, const struct wps_credential *cred)
+int wps_er_config(struct wps_er *er, const u8 *uuid, const u8 *addr,
+ const u8 *pin, size_t pin_len,
+ const struct wps_credential *cred)
{
struct wps_er_ap *ap;
if (er == NULL)
return -1;
- ap = wps_er_ap_get(er, NULL, uuid);
+ ap = wps_er_ap_get(er, NULL, uuid, addr);
if (ap == NULL) {
wpa_printf(MSG_DEBUG, "WPS ER: AP not found for config "
"request");
return -1;
}
+ if (uuid == NULL)
+ uuid = ap->uuid;
if (ap->wps) {
wpa_printf(MSG_DEBUG, "WPS ER: Pending operation ongoing "
"with the AP - cannot start config");
@@ -1999,16 +2023,39 @@ int wps_er_config(struct wps_er *er, const u8 *uuid, const u8 *pin,
#ifdef CONFIG_WPS_NFC
-struct wpabuf * wps_er_nfc_config_token(struct wps_er *er, const u8 *uuid)
+
+struct wpabuf * wps_er_config_token_from_cred(struct wps_context *wps,
+ struct wps_credential *cred)
{
- struct wps_er_ap *ap;
struct wpabuf *ret;
struct wps_data data;
+ ret = wpabuf_alloc(500);
+ if (ret == NULL)
+ return NULL;
+
+ os_memset(&data, 0, sizeof(data));
+ data.wps = wps;
+ data.use_cred = cred;
+ if (wps_build_cred(&data, ret) ||
+ wps_build_wfa_ext(ret, 0, NULL, 0)) {
+ wpabuf_free(ret);
+ return NULL;
+ }
+
+ return ret;
+}
+
+
+struct wpabuf * wps_er_nfc_config_token(struct wps_er *er, const u8 *uuid,
+ const u8 *addr)
+{
+ struct wps_er_ap *ap;
+
if (er == NULL)
return NULL;
- ap = wps_er_ap_get(er, NULL, uuid);
+ ap = wps_er_ap_get(er, NULL, uuid, addr);
if (ap == NULL)
return NULL;
if (ap->ap_settings == NULL) {
@@ -2017,20 +2064,32 @@ struct wpabuf * wps_er_nfc_config_token(struct wps_er *er, const u8 *uuid)
return NULL;
}
- ret = wpabuf_alloc(500);
- if (ret == NULL)
+ return wps_er_config_token_from_cred(er->wps, ap->ap_settings);
+}
+
+
+struct wpabuf * wps_er_nfc_handover_sel(struct wps_er *er,
+ struct wps_context *wps, const u8 *uuid,
+ const u8 *addr, struct wpabuf *pubkey)
+{
+ struct wps_er_ap *ap;
+
+ if (er == NULL)
return NULL;
- os_memset(&data, 0, sizeof(data));
- data.wps = er->wps;
- data.use_cred = ap->ap_settings;
- if (wps_build_version(ret) ||
- wps_build_cred(&data, ret) ||
- wps_build_wfa_ext(ret, 0, NULL, 0)) {
- wpabuf_free(ret);
+ ap = wps_er_ap_get(er, NULL, uuid, addr);
+ if (ap == NULL)
+ return NULL;
+ if (ap->ap_settings == NULL) {
+ wpa_printf(MSG_DEBUG, "WPS ER: No settings known for the "
+ "selected AP");
return NULL;
}
- return ret;
+ os_memcpy(wps->ssid, ap->ap_settings->ssid, ap->ap_settings->ssid_len);
+ wps->ssid_len = ap->ap_settings->ssid_len;
+
+ return wps_build_nfc_handover_sel(wps, pubkey, addr, 0);
}
+
#endif /* CONFIG_WPS_NFC */