aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--hostapd/README-WPS9
-rw-r--r--hostapd/ctrl_iface.c13
-rw-r--r--hostapd/hostapd_cli.c12
-rw-r--r--hostapd/wps_hostapd.c5
-rw-r--r--hostapd/wps_hostapd.h2
-rw-r--r--src/eap_peer/eap_wsc.c2
-rw-r--r--src/wps/wps.h2
-rw-r--r--src/wps/wps_registrar.c53
8 files changed, 81 insertions, 17 deletions
diff --git a/hostapd/README-WPS b/hostapd/README-WPS
index b46d767..e0e370b 100644
--- a/hostapd/README-WPS
+++ b/hostapd/README-WPS
@@ -165,10 +165,17 @@ Example command to add a PIN (12345670) for an Enrollee:
hostapd_cli wps_pin 53b63a98-d29e-4457-a2ed-094d7e6a669c 12345670
If the UUID-E is not available (e.g., Enrollee waits for the Registrar
-to be selected before connecting), wildcard UUID may be used to allow the PIN to be used once with any UUID:
+to be selected before connecting), wildcard UUID may be used to allow
+the PIN to be used once with any UUID:
hostapd_cli wps_pin any 12345670
+To reduce likelihood of PIN being used with other devices or of
+forgetting an active PIN available for potential attackers, expiration
+time can be set for the new PIN:
+
+hostapd_cli wps_pin any 12345670 300
+
After this, the Enrollee can connect to the AP again and complete WPS
negotiation. At that point, a new, random WPA PSK is generated for the
diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
index 15c7873..9dec724 100644
--- a/hostapd/ctrl_iface.c
+++ b/hostapd/ctrl_iface.c
@@ -253,10 +253,21 @@ static int hostapd_ctrl_iface_sa_query(struct hostapd_data *hapd,
static int hostapd_ctrl_iface_wps_pin(struct hostapd_data *hapd, char *txt)
{
char *pin = os_strchr(txt, ' ');
+ char *timeout_txt;
+ int timeout;
+
if (pin == NULL)
return -1;
*pin++ = '\0';
- return hostapd_wps_add_pin(hapd, txt, pin);
+
+ timeout_txt = os_strchr(pin, ' ');
+ if (timeout_txt) {
+ *timeout_txt++ = '\0';
+ timeout = atoi(timeout_txt);
+ } else
+ timeout = 0;
+
+ return hostapd_wps_add_pin(hapd, txt, pin, timeout);
}
#endif /* CONFIG_WPS */
diff --git a/hostapd/hostapd_cli.c b/hostapd/hostapd_cli.c
index 2614113..c2ecd4e 100644
--- a/hostapd/hostapd_cli.c
+++ b/hostapd/hostapd_cli.c
@@ -87,7 +87,7 @@ static const char *commands_help =
" sa_query <addr> send SA Query to a station\n"
#endif /* CONFIG_IEEE80211W */
#ifdef CONFIG_WPS
-" wps_pin <uuid> <pin> add WPS Enrollee PIN (Device Password)\n"
+" wps_pin <uuid> <pin> [timeout] add WPS Enrollee PIN (Device Password)\n"
" wps_pbc indicate button pushed to initiate PBC\n"
#endif /* CONFIG_WPS */
" help show this usage help\n"
@@ -260,12 +260,16 @@ static int hostapd_cli_cmd_wps_pin(struct wpa_ctrl *ctrl, int argc,
char *argv[])
{
char buf[64];
- if (argc != 2) {
- printf("Invalid 'wps_pin' command - exactly two arguments, "
+ if (argc < 2) {
+ printf("Invalid 'wps_pin' command - at least two arguments, "
"UUID and PIN, are required.\n");
return -1;
}
- snprintf(buf, sizeof(buf), "WPS_PIN %s %s", argv[0], argv[1]);
+ if (argc > 2)
+ snprintf(buf, sizeof(buf), "WPS_PIN %s %s %s",
+ argv[0], argv[1], argv[2]);
+ else
+ snprintf(buf, sizeof(buf), "WPS_PIN %s %s", argv[0], argv[1]);
return wpa_ctrl_command(ctrl, buf);
}
diff --git a/hostapd/wps_hostapd.c b/hostapd/wps_hostapd.c
index 1634055..818767e 100644
--- a/hostapd/wps_hostapd.c
+++ b/hostapd/wps_hostapd.c
@@ -699,7 +699,7 @@ void hostapd_deinit_wps(struct hostapd_data *hapd)
int hostapd_wps_add_pin(struct hostapd_data *hapd, const char *uuid,
- const char *pin)
+ const char *pin, int timeout)
{
u8 u[UUID_LEN];
int any = 0;
@@ -711,7 +711,8 @@ int hostapd_wps_add_pin(struct hostapd_data *hapd, const char *uuid,
else if (uuid_str2bin(uuid, u))
return -1;
return wps_registrar_add_pin(hapd->wps->registrar, any ? NULL : u,
- (const u8 *) pin, os_strlen(pin));
+ (const u8 *) pin, os_strlen(pin),
+ timeout);
}
diff --git a/hostapd/wps_hostapd.h b/hostapd/wps_hostapd.h
index 6615c62..e949bee 100644
--- a/hostapd/wps_hostapd.h
+++ b/hostapd/wps_hostapd.h
@@ -21,7 +21,7 @@ int hostapd_init_wps(struct hostapd_data *hapd,
struct hostapd_bss_config *conf);
void hostapd_deinit_wps(struct hostapd_data *hapd);
int hostapd_wps_add_pin(struct hostapd_data *hapd, const char *uuid,
- const char *pin);
+ const char *pin, int timeout);
int hostapd_wps_button_pushed(struct hostapd_data *hapd);
void hostapd_wps_probe_req_rx(struct hostapd_data *hapd, const u8 *addr,
const u8 *ie, size_t ie_len);
diff --git a/src/eap_peer/eap_wsc.c b/src/eap_peer/eap_wsc.c
index 17e42f4..7c8ad2f 100644
--- a/src/eap_peer/eap_wsc.c
+++ b/src/eap_peer/eap_wsc.c
@@ -144,7 +144,7 @@ static void * eap_wsc_init(struct eap_sm *sm)
if (registrar && cfg.pin) {
wps_registrar_add_pin(data->wps_ctx->registrar, NULL,
- cfg.pin, cfg.pin_len);
+ cfg.pin, cfg.pin_len, 0);
}
return data;
diff --git a/src/wps/wps.h b/src/wps/wps.h
index 99a3c26..d13db60 100644
--- a/src/wps/wps.h
+++ b/src/wps/wps.h
@@ -505,7 +505,7 @@ wps_registrar_init(struct wps_context *wps,
const struct wps_registrar_config *cfg);
void wps_registrar_deinit(struct wps_registrar *reg);
int wps_registrar_add_pin(struct wps_registrar *reg, const u8 *uuid,
- const u8 *pin, size_t pin_len);
+ const u8 *pin, size_t pin_len, int timeout);
int wps_registrar_invalidate_pin(struct wps_registrar *reg, const u8 *uuid);
int wps_registrar_unlock_pin(struct wps_registrar *reg, const u8 *uuid);
int wps_registrar_button_pushed(struct wps_registrar *reg);
diff --git a/src/wps/wps_registrar.c b/src/wps/wps_registrar.c
index 472b232..5343301 100644
--- a/src/wps/wps_registrar.c
+++ b/src/wps/wps_registrar.c
@@ -31,7 +31,10 @@ struct wps_uuid_pin {
int wildcard_uuid;
u8 *pin;
size_t pin_len;
- int locked;
+#define PIN_LOCKED BIT(0)
+#define PIN_EXPIRES BIT(1)
+ int flags;
+ struct os_time expiration;
};
@@ -412,10 +415,11 @@ void wps_registrar_deinit(struct wps_registrar *reg)
* @uuid: UUID-E or %NULL for wildcard (any UUID)
* @pin: PIN (Device Password)
* @pin_len: Length of pin in octets
+ * @timeout: Time (in seconds) when the PIN will be invalidated; 0 = no timeout
* Returns: 0 on success, -1 on failure
*/
int wps_registrar_add_pin(struct wps_registrar *reg, const u8 *uuid,
- const u8 *pin, size_t pin_len)
+ const u8 *pin, size_t pin_len, int timeout)
{
struct wps_uuid_pin *p;
@@ -434,10 +438,17 @@ int wps_registrar_add_pin(struct wps_registrar *reg, const u8 *uuid,
os_memcpy(p->pin, pin, pin_len);
p->pin_len = pin_len;
+ if (timeout) {
+ p->flags |= PIN_EXPIRES;
+ os_get_time(&p->expiration);
+ p->expiration.sec += timeout;
+ }
+
p->next = reg->pins;
reg->pins = p;
- wpa_printf(MSG_DEBUG, "WPS: A new PIN configured");
+ wpa_printf(MSG_DEBUG, "WPS: A new PIN configured (timeout=%d)",
+ timeout);
wpa_hexdump(MSG_DEBUG, "WPS: UUID", uuid, WPS_UUID_LEN);
wpa_hexdump_ascii_key(MSG_DEBUG, "WPS: PIN", pin, pin_len);
reg->selected_registrar = 1;
@@ -452,6 +463,34 @@ int wps_registrar_add_pin(struct wps_registrar *reg, const u8 *uuid,
}
+static void wps_registrar_expire_pins(struct wps_registrar *reg)
+{
+ struct wps_uuid_pin *pin, *prev, *del;
+ struct os_time now;
+
+ os_get_time(&now);
+ prev = NULL;
+ pin = reg->pins;
+ while (pin) {
+ if ((pin->flags & PIN_EXPIRES) &&
+ os_time_before(&pin->expiration, &now)) {
+ if (prev == NULL)
+ reg->pins = pin->next;
+ else
+ prev->next = pin->next;
+ del = pin;
+ pin = pin->next;
+ wpa_hexdump(MSG_DEBUG, "WPS: Expired PIN for UUID",
+ del->uuid, WPS_UUID_LEN);
+ wps_free_pin(del);
+ continue;
+ }
+ prev = pin;
+ pin = pin->next;
+ }
+}
+
+
/**
* wps_registrar_invalidate_pin - Invalidate a PIN for a specific UUID-E
* @reg: Registrar data from wps_registrar_init()
@@ -488,6 +527,8 @@ static const u8 * wps_registrar_get_pin(struct wps_registrar *reg,
{
struct wps_uuid_pin *pin;
+ wps_registrar_expire_pins(reg);
+
pin = reg->pins;
while (pin) {
if (!pin->wildcard_uuid &&
@@ -519,13 +560,13 @@ static const u8 * wps_registrar_get_pin(struct wps_registrar *reg,
* Lock the PIN to avoid attacks based on concurrent re-use of the PIN
* that could otherwise avoid PIN invalidations.
*/
- if (pin->locked) {
+ if (pin->flags & PIN_LOCKED) {
wpa_printf(MSG_DEBUG, "WPS: Selected PIN locked - do not "
"allow concurrent re-use");
return NULL;
}
*pin_len = pin->pin_len;
- pin->locked = 1;
+ pin->flags |= PIN_LOCKED;
return pin->pin;
}
@@ -552,7 +593,7 @@ int wps_registrar_unlock_pin(struct wps_registrar *reg, const u8 *uuid)
"wildcard PIN");
return wps_registrar_invalidate_pin(reg, uuid);
}
- pin->locked = 0;
+ pin->flags &= ~PIN_LOCKED;
return 0;
}
pin = pin->next;