diff --git a/hostapd/README-WPS b/hostapd/README-WPS index 5e8a68d90..2786c602e 100644 --- a/hostapd/README-WPS +++ b/hostapd/README-WPS @@ -154,6 +154,12 @@ 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: + +hostapd_cli wps_pin any 12345670 + + 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 client device and the client can then use that key to connect to the diff --git a/hostapd/wps_hostapd.c b/hostapd/wps_hostapd.c index 76258eec0..4871d9c57 100644 --- a/hostapd/wps_hostapd.c +++ b/hostapd/wps_hostapd.c @@ -543,9 +543,15 @@ int hostapd_wps_add_pin(struct hostapd_data *hapd, const char *uuid, const char *pin) { u8 u[UUID_LEN]; - if (hapd->wps == NULL || uuid_str2bin(uuid, u)) + int any = 0; + + if (hapd->wps == NULL) return -1; - return wps_registrar_add_pin(hapd->wps->registrar, u, + if (os_strcmp(uuid, "any") == 0) + any = 1; + 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)); } diff --git a/src/wps/wps_registrar.c b/src/wps/wps_registrar.c index 4b45c7dcd..01fa767c5 100644 --- a/src/wps/wps_registrar.c +++ b/src/wps/wps_registrar.c @@ -26,6 +26,7 @@ struct wps_uuid_pin { struct wps_uuid_pin *next; u8 uuid[WPS_UUID_LEN]; + int wildcard_uuid; u8 *pin; size_t pin_len; int locked; @@ -339,7 +340,10 @@ int wps_registrar_add_pin(struct wps_registrar *reg, const u8 *uuid, p = os_zalloc(sizeof(*p)); if (p == NULL) return -1; - os_memcpy(p->uuid, uuid, WPS_UUID_LEN); + if (uuid == NULL) + p->wildcard_uuid = 1; + else + os_memcpy(p->uuid, uuid, WPS_UUID_LEN); p->pin = os_malloc(pin_len); if (p->pin == NULL) { os_free(p); @@ -394,26 +398,43 @@ static const u8 * wps_registrar_get_pin(struct wps_registrar *reg, pin = reg->pins; while (pin) { - if (os_memcmp(pin->uuid, uuid, WPS_UUID_LEN) == 0) { - /* - * Lock the PIN to avoid attacks based on concurrent - * re-use of the PIN that could otherwise avoid PIN - * invalidations. - */ - if (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; - return pin->pin; - } + if (!pin->wildcard_uuid && + os_memcmp(pin->uuid, uuid, WPS_UUID_LEN) == 0) + break; pin = pin->next; } - return NULL; + if (!pin) { + /* Check for wildcard UUIDs since none of the UUID-specific + * PINs matched */ + pin = reg->pins; + while (pin) { + if (pin->wildcard_uuid == 1) { + wpa_printf(MSG_DEBUG, "WPS: Found a wildcard " + "PIN. Assigned it for this UUID-E"); + pin->wildcard_uuid = 2; + os_memcpy(pin->uuid, uuid, WPS_UUID_LEN); + break; + } + pin = pin->next; + } + } + + if (!pin) + return NULL; + + /* + * Lock the PIN to avoid attacks based on concurrent re-use of the PIN + * that could otherwise avoid PIN invalidations. + */ + if (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; + return pin->pin; } @@ -424,6 +445,11 @@ int wps_registrar_unlock_pin(struct wps_registrar *reg, const u8 *uuid) pin = reg->pins; while (pin) { if (os_memcmp(pin->uuid, uuid, WPS_UUID_LEN) == 0) { + if (pin->wildcard_uuid == 2) { + wpa_printf(MSG_DEBUG, "WPS: Invalidating used " + "wildcard PIN"); + return wps_registrar_invalidate_pin(reg, uuid); + } pin->locked = 0; return 0; }