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,