From 1affa36cb5c044aef6425918263431b728428381 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Wed, 29 Feb 2012 20:42:48 +0200 Subject: [PATCH] WPS: Invalidate wildcard PIN on other radios after successful use If a wildcard PIN is used on any of the radios that hostapd is controlling, invalidate the matching PIN on all the other radios to avoid multiple uses of the same PIN. Signed-hostap: Jouni Malinen --- src/ap/wps_hostapd.c | 10 ++++++++-- src/wps/wps.h | 8 ++++++-- src/wps/wps_registrar.c | 33 ++++++++++++++++++++++++++------- 3 files changed, 40 insertions(+), 11 deletions(-) diff --git a/src/ap/wps_hostapd.c b/src/ap/wps_hostapd.c index 89992179e..94eea255e 100644 --- a/src/ap/wps_hostapd.c +++ b/src/ap/wps_hostapd.c @@ -183,19 +183,23 @@ static void hostapd_wps_pin_needed_cb(void *ctx, const u8 *uuid_e, struct wps_stop_reg_data { struct hostapd_data *current_hapd; const u8 *uuid_e; + const u8 *dev_pw; + size_t dev_pw_len; }; static int wps_stop_registrar(struct hostapd_data *hapd, void *ctx) { struct wps_stop_reg_data *data = ctx; if (hapd != data->current_hapd && hapd->wps != NULL) - wps_registrar_complete(hapd->wps->registrar, data->uuid_e); + wps_registrar_complete(hapd->wps->registrar, data->uuid_e, + data->dev_pw, data->dev_pw_len); return 0; } static void hostapd_wps_reg_success_cb(void *ctx, const u8 *mac_addr, - const u8 *uuid_e) + const u8 *uuid_e, const u8 *dev_pw, + size_t dev_pw_len) { struct hostapd_data *hapd = ctx; char uuid[40]; @@ -209,6 +213,8 @@ static void hostapd_wps_reg_success_cb(void *ctx, const u8 *mac_addr, mac_addr, uuid_e); data.current_hapd = hapd; data.uuid_e = uuid_e; + data.dev_pw = dev_pw; + data.dev_pw_len = dev_pw_len; hostapd_wps_for_each(hapd, wps_stop_registrar, &data); } diff --git a/src/wps/wps.h b/src/wps/wps.h index 18446cb0d..435f36a67 100644 --- a/src/wps/wps.h +++ b/src/wps/wps.h @@ -294,12 +294,15 @@ struct wps_registrar_config { * @ctx: Higher layer context data (cb_ctx) * @mac_addr: MAC address of the Enrollee * @uuid_e: UUID-E of the Enrollee + * @dev_pw: Device Password (PIN) used during registration + * @dev_pw_len: Length of dev_pw in octets * * This callback is called whenever an Enrollee completes registration * successfully. */ void (*reg_success_cb)(void *ctx, const u8 *mac_addr, - const u8 *uuid_e); + const u8 *uuid_e, const u8 *dev_pw, + size_t dev_pw_len); /** * set_sel_reg_cb - Callback for reporting selected registrar changes @@ -783,7 +786,8 @@ int wps_registrar_wps_cancel(struct wps_registrar *reg); int wps_registrar_unlock_pin(struct wps_registrar *reg, const u8 *uuid); int wps_registrar_button_pushed(struct wps_registrar *reg, const u8 *p2p_dev_addr); -void wps_registrar_complete(struct wps_registrar *registrar, const u8 *uuid_e); +void wps_registrar_complete(struct wps_registrar *registrar, const u8 *uuid_e, + const u8 *dev_pw, size_t dev_pw_len); void wps_registrar_probe_req_rx(struct wps_registrar *reg, const u8 *addr, const struct wpabuf *wps_data, int p2p_wildcard); diff --git a/src/wps/wps_registrar.c b/src/wps/wps_registrar.c index 85ec3172f..e6ec04cf7 100644 --- a/src/wps/wps_registrar.c +++ b/src/wps/wps_registrar.c @@ -102,7 +102,8 @@ struct wps_registrar { void (*pin_needed_cb)(void *ctx, const u8 *uuid_e, const struct wps_device_data *dev); void (*reg_success_cb)(void *ctx, const u8 *mac_addr, - const u8 *uuid_e); + const u8 *uuid_e, const u8 *dev_pw, + size_t dev_pw_len); void (*set_sel_reg_cb)(void *ctx, int sel_reg, u16 dev_passwd_id, u16 sel_reg_config_methods); void (*enrollee_seen_cb)(void *ctx, const u8 *addr, const u8 *uuid_e, @@ -735,14 +736,22 @@ static void wps_registrar_expire_pins(struct wps_registrar *reg) /** * wps_registrar_invalidate_wildcard_pin - Invalidate a wildcard PIN * @reg: Registrar data from wps_registrar_init() + * @dev_pw: PIN to search for or %NULL to match any + * @dev_pw_len: Length of dev_pw in octets * Returns: 0 on success, -1 if not wildcard PIN is enabled */ -static int wps_registrar_invalidate_wildcard_pin(struct wps_registrar *reg) +static int wps_registrar_invalidate_wildcard_pin(struct wps_registrar *reg, + const u8 *dev_pw, + size_t dev_pw_len) { struct wps_uuid_pin *pin, *prev; dl_list_for_each_safe(pin, prev, ®->pins, struct wps_uuid_pin, list) { + if (dev_pw && pin->pin && + (dev_pw_len != pin->pin_len || + os_memcmp(dev_pw, pin->pin, dev_pw_len) != 0)) + continue; /* different PIN */ if (pin->wildcard_uuid) { wpa_hexdump(MSG_DEBUG, "WPS: Invalidated PIN for UUID", pin->uuid, WPS_UUID_LEN); @@ -940,7 +949,8 @@ static void wps_registrar_pin_completed(struct wps_registrar *reg) } -void wps_registrar_complete(struct wps_registrar *registrar, const u8 *uuid_e) +void wps_registrar_complete(struct wps_registrar *registrar, const u8 *uuid_e, + const u8 *dev_pw, size_t dev_pw_len) { if (registrar->pbc) { wps_registrar_remove_pbc_session(registrar, @@ -949,6 +959,13 @@ void wps_registrar_complete(struct wps_registrar *registrar, const u8 *uuid_e) } else { wps_registrar_pin_completed(registrar); } + + if (dev_pw && + wps_registrar_invalidate_wildcard_pin(registrar, dev_pw, + dev_pw_len) == 0) { + wpa_hexdump_key(MSG_DEBUG, "WPS: Invalidated wildcard PIN", + dev_pw, dev_pw_len); + } } @@ -963,7 +980,7 @@ int wps_registrar_wps_cancel(struct wps_registrar *reg) /* PIN Method */ wpa_printf(MSG_DEBUG, "WPS: PIN is set - cancelling it"); wps_registrar_pin_completed(reg); - wps_registrar_invalidate_wildcard_pin(reg); + wps_registrar_invalidate_wildcard_pin(reg, NULL, 0); return 1; } return 0; @@ -1066,12 +1083,13 @@ static void wps_cb_pin_needed(struct wps_registrar *reg, const u8 *uuid_e, static void wps_cb_reg_success(struct wps_registrar *reg, const u8 *mac_addr, - const u8 *uuid_e) + const u8 *uuid_e, const u8 *dev_pw, + size_t dev_pw_len) { if (reg->reg_success_cb == NULL) return; - reg->reg_success_cb(reg->cb_ctx, mac_addr, uuid_e); + reg->reg_success_cb(reg->cb_ctx, mac_addr, uuid_e, dev_pw, dev_pw_len); } @@ -3050,7 +3068,8 @@ static enum wps_process_res wps_process_wsc_done(struct wps_data *wps, wps->new_psk = NULL; } - wps_cb_reg_success(wps->wps->registrar, wps->mac_addr_e, wps->uuid_e); + wps_cb_reg_success(wps->wps->registrar, wps->mac_addr_e, wps->uuid_e, + wps->dev_password, wps->dev_password_len); if (wps->pbc) { wps_registrar_remove_pbc_session(wps->wps->registrar,