From aabe26a136459ca8d6e0926a0bcd85835ddafc9a Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Wed, 21 Jan 2009 13:48:10 +0200 Subject: [PATCH] WPS: Added option to disable AP auto-config on first registration This operation can now be moved into an external program by configuring hostapd with wps_cred_processing=1 and skip_cred_build=1. A new ctrl_iface message (WPS-REG-SUCCESS ) will be used to notify external programs of each successful registration and that can be used as a tricker to move from unconfigured to configured state. --- hostapd/hostapd.conf | 2 ++ hostapd/wps_hostapd.c | 15 +++++++++++++++ src/common/wpa_ctrl.h | 1 + src/wps/wps.h | 24 ++++++++++++++++++++++++ src/wps/wps_registrar.c | 22 ++++++++++++++++++++-- 5 files changed, 62 insertions(+), 2 deletions(-) diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf index bd24f1774..b423be564 100644 --- a/hostapd/hostapd.conf +++ b/hostapd/hostapd.conf @@ -954,6 +954,8 @@ own_ip_addr=127.0.0.1 # external program(s) # 2 = process received credentials internally and pass them over ctrl_iface # to external program(s) +# Note: With wps_cred_processing=1, skip_cred_build should be set to 1 and +# extra_cred be used to provide the Credential data for Enrollees. #wps_cred_processing=0 diff --git a/hostapd/wps_hostapd.c b/hostapd/wps_hostapd.c index 916844bf9..a1560c981 100644 --- a/hostapd/wps_hostapd.c +++ b/hostapd/wps_hostapd.c @@ -152,6 +152,18 @@ static void hostapd_wps_pin_needed_cb(void *ctx, const u8 *uuid_e, } +static void hostapd_wps_reg_success_cb(void *ctx, const u8 *mac_addr, + const u8 *uuid_e) +{ + struct hostapd_data *hapd = ctx; + char uuid[40]; + if (uuid_bin2str(uuid_e, uuid, sizeof(uuid))) + return; + wpa_msg(hapd, MSG_INFO, WPS_EVENT_REG_SUCCESS MACSTR " %s", + MAC2STR(mac_addr), uuid); +} + + static int str_starts(const char *str, const char *start) { return os_strncmp(str, start, os_strlen(start)) == 0; @@ -531,10 +543,13 @@ int hostapd_init_wps(struct hostapd_data *hapd, cfg.new_psk_cb = hostapd_wps_new_psk_cb; cfg.set_ie_cb = hostapd_wps_set_ie_cb; cfg.pin_needed_cb = hostapd_wps_pin_needed_cb; + cfg.reg_success_cb = hostapd_wps_reg_success_cb; cfg.cb_ctx = hapd; cfg.skip_cred_build = conf->skip_cred_build; cfg.extra_cred = conf->extra_cred; cfg.extra_cred_len = conf->extra_cred_len; + cfg.disable_auto_conf = (hapd->conf->wps_cred_processing == 1) && + conf->skip_cred_build; wps->registrar = wps_registrar_init(wps, &cfg); if (wps->registrar == NULL) { diff --git a/src/common/wpa_ctrl.h b/src/common/wpa_ctrl.h index 9306a3332..87a4c6b84 100644 --- a/src/common/wpa_ctrl.h +++ b/src/common/wpa_ctrl.h @@ -70,6 +70,7 @@ extern "C" { /* hostapd control interface - fixed message prefixes */ #define WPS_EVENT_PIN_NEEDED "WPS-PIN-NEEDED " #define WPS_EVENT_NEW_AP_SETTINGS "WPS-NEW-AP-SETTINGS " +#define WPS_EVENT_REG_SUCCESS "WPS-REG-SUCCESS " /* wpa_supplicant/hostapd control interface access */ diff --git a/src/wps/wps.h b/src/wps/wps.h index 1736d9e84..484733287 100644 --- a/src/wps/wps.h +++ b/src/wps/wps.h @@ -205,6 +205,18 @@ struct wps_registrar_config { void (*pin_needed_cb)(void *ctx, const u8 *uuid_e, const struct wps_device_data *dev); + /** + * reg_success_cb - Callback for reporting successful registration + * @ctx: Higher layer context data (cb_ctx) + * @mac_addr: MAC address of the Enrollee + * @uuid_e: UUID-E of the Enrollee + * + * This callback is called whenever an Enrollee completes registration + * successfully. + */ + void (*reg_success_cb)(void *ctx, const u8 *mac_addr, + const u8 *uuid_e); + /** * cb_ctx: Higher layer context data for Registrar callbacks */ @@ -234,6 +246,18 @@ struct wps_registrar_config { * extra_cred_len: Length of extra_cred in octets */ size_t extra_cred_len; + + /** + * disable_auto_conf - Disable auto-configuration on first registration + * + * By default, the AP that is started in not configured state will + * generate a random PSK and move to configured state when the first + * registration protocol run is completed successfully. This option can + * be used to disable this functionality and leave it up to an external + * program to take care of configuration. This requires the extra_cred + * to be set with a suitable Credential and skip_cred_build being used. + */ + int disable_auto_conf; }; diff --git a/src/wps/wps_registrar.c b/src/wps/wps_registrar.c index 246c1e9dd..7ddd6494b 100644 --- a/src/wps/wps_registrar.c +++ b/src/wps/wps_registrar.c @@ -85,6 +85,8 @@ struct wps_registrar { const u8 *probe_resp_ie, size_t probe_resp_ie_len); 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); void *cb_ctx; struct wps_uuid_pin *pins; @@ -92,6 +94,7 @@ struct wps_registrar { int skip_cred_build; struct wpabuf *extra_cred; + int disable_auto_conf; }; @@ -325,6 +328,7 @@ wps_registrar_init(struct wps_context *wps, reg->new_psk_cb = cfg->new_psk_cb; reg->set_ie_cb = cfg->set_ie_cb; reg->pin_needed_cb = cfg->pin_needed_cb; + reg->reg_success_cb = cfg->reg_success_cb; reg->cb_ctx = cfg->cb_ctx; reg->skip_cred_build = cfg->skip_cred_build; if (cfg->extra_cred) { @@ -335,6 +339,7 @@ wps_registrar_init(struct wps_context *wps, return NULL; } } + reg->disable_auto_conf = cfg->disable_auto_conf; if (wps_set_ie(reg)) { wps_registrar_deinit(reg); @@ -630,6 +635,16 @@ 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) +{ + if (reg->reg_success_cb == NULL) + return; + + reg->reg_success_cb(reg->cb_ctx, mac_addr, uuid_e); +} + + static int wps_cb_set_ie(struct wps_registrar *reg, const struct wpabuf *beacon_ie, const struct wpabuf *probe_resp_ie) @@ -983,7 +998,8 @@ static int wps_build_cred(struct wps_data *wps, struct wpabuf *msg) /* Set MAC address in the Credential to be the AP's address (BSSID) */ os_memcpy(wps->cred.mac_addr, wps->wps->dev.mac_addr, ETH_ALEN); - if (wps->wps->wps_state == WPS_STATE_NOT_CONFIGURED && wps->wps->ap) { + if (wps->wps->wps_state == WPS_STATE_NOT_CONFIGURED && wps->wps->ap && + !wps->wps->registrar->disable_auto_conf) { u8 r[16]; /* Generate a random passphrase */ if (os_get_random(r, sizeof(r)) < 0) @@ -2118,7 +2134,7 @@ static enum wps_process_res wps_process_wsc_done(struct wps_data *wps, wpa_printf(MSG_DEBUG, "WPS: Negotiation completed successfully"); if (wps->wps->wps_state == WPS_STATE_NOT_CONFIGURED && wps->new_psk && - wps->wps->ap) { + wps->wps->ap && !wps->wps->registrar->disable_auto_conf) { struct wps_credential cred; wpa_printf(MSG_DEBUG, "WPS: Moving to Configured state based " @@ -2160,6 +2176,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); + if (wps->pbc) { wps_registrar_remove_pbc_session(wps->wps->registrar, wps->mac_addr_e, wps->uuid_e);