mirror of
https://github.com/vanhoefm/fragattacks.git
synced 2024-11-28 18:28:23 -05:00
WPS: Make it possible to use PSKs loaded from the PSK file
By default, when configuration file set wpa_psk_file, hostapd generated a random PSK for each Enrollee provisioned using WPS and appended that PSK to wpa_psk_file. Changes that behavior by adding a new step. WPS will first try to use a PSK from wpa_psk_file. It will only try PSKs with wps=1 tag. Additionally it'll try to match enrollee's MAC address (if provided). If it fails to find an appropriate PSK, it falls back to generating a new PSK. Signed-off-by: Tomasz Jankowski <tomasz.jankowski@plume.com>
This commit is contained in:
parent
b1977a652d
commit
fde8e79463
@ -7,9 +7,15 @@
|
|||||||
# keyid=<keyid_string>
|
# keyid=<keyid_string>
|
||||||
# An optional VLAN ID can be specified by prefixing the line with
|
# An optional VLAN ID can be specified by prefixing the line with
|
||||||
# vlanid=<VLAN ID>.
|
# vlanid=<VLAN ID>.
|
||||||
|
# An optional WPS tag can be added by prefixing the line with
|
||||||
|
# wps=<0/1> (default: 0). Any matching entry with that tag will be used when
|
||||||
|
# generating a PSK for a WPS Enrollee instead of generating a new random
|
||||||
|
# per-Enrollee PSK.
|
||||||
00:00:00:00:00:00 secret passphrase
|
00:00:00:00:00:00 secret passphrase
|
||||||
00:11:22:33:44:55 another passphrase
|
00:11:22:33:44:55 another passphrase
|
||||||
00:22:33:44:55:66 0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef
|
00:22:33:44:55:66 0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef
|
||||||
keyid=example_id 00:11:22:33:44:77 passphrase with keyid
|
keyid=example_id 00:11:22:33:44:77 passphrase with keyid
|
||||||
vlanid=3 00:00:00:00:00:00 passphrase with vlanid
|
vlanid=3 00:00:00:00:00:00 passphrase with vlanid
|
||||||
|
wps=1 00:00:00:00:00:00 passphrase for WPS
|
||||||
|
wps=1 11:22:33:44:55:00 dev-specific passphrase for WPS
|
||||||
00:00:00:00:00:00 another passphrase for all STAs
|
00:00:00:00:00:00 another passphrase for all STAs
|
||||||
|
@ -301,6 +301,7 @@ static int hostapd_config_read_wpa_psk(const char *fname,
|
|||||||
|
|
||||||
while (fgets(buf, sizeof(buf), f)) {
|
while (fgets(buf, sizeof(buf), f)) {
|
||||||
int vlan_id = 0;
|
int vlan_id = 0;
|
||||||
|
int wps = 0;
|
||||||
|
|
||||||
line++;
|
line++;
|
||||||
|
|
||||||
@ -331,6 +332,8 @@ static int hostapd_config_read_wpa_psk(const char *fname,
|
|||||||
value = "";
|
value = "";
|
||||||
if (!os_strcmp(name, "keyid")) {
|
if (!os_strcmp(name, "keyid")) {
|
||||||
keyid = value;
|
keyid = value;
|
||||||
|
} else if (!os_strcmp(name, "wps")) {
|
||||||
|
wps = atoi(value);
|
||||||
} else if (!os_strcmp(name, "vlanid")) {
|
} else if (!os_strcmp(name, "vlanid")) {
|
||||||
vlan_id = atoi(value);
|
vlan_id = atoi(value);
|
||||||
} else {
|
} else {
|
||||||
@ -406,6 +409,8 @@ static int hostapd_config_read_wpa_psk(const char *fname,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
psk->wps = wps;
|
||||||
|
|
||||||
psk->next = ssid->wpa_psk;
|
psk->next = ssid->wpa_psk;
|
||||||
ssid->wpa_psk = psk;
|
ssid->wpa_psk = psk;
|
||||||
}
|
}
|
||||||
|
@ -152,6 +152,7 @@ struct hostapd_wpa_psk {
|
|||||||
struct hostapd_wpa_psk *next;
|
struct hostapd_wpa_psk *next;
|
||||||
int group;
|
int group;
|
||||||
char keyid[KEYID_LEN];
|
char keyid[KEYID_LEN];
|
||||||
|
int wps;
|
||||||
u8 psk[PMK_LEN];
|
u8 psk[PMK_LEN];
|
||||||
u8 addr[ETH_ALEN];
|
u8 addr[ETH_ALEN];
|
||||||
u8 p2p_dev_addr[ETH_ALEN];
|
u8 p2p_dev_addr[ETH_ALEN];
|
||||||
|
@ -269,6 +269,44 @@ static void hostapd_wps_enrollee_seen_cb(void *ctx, const u8 *addr,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int hostapd_wps_lookup_pskfile_cb(void *ctx, const u8 *mac_addr,
|
||||||
|
const u8 **psk)
|
||||||
|
{
|
||||||
|
const struct hostapd_data *hapd = ctx;
|
||||||
|
const struct hostapd_wpa_psk *wpa_psk;
|
||||||
|
const u8 *any_psk = NULL;
|
||||||
|
const u8 *dev_psk = NULL;
|
||||||
|
|
||||||
|
for (wpa_psk = hapd->conf->ssid.wpa_psk; wpa_psk;
|
||||||
|
wpa_psk = wpa_psk->next) {
|
||||||
|
if (!wpa_psk->wps)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!any_psk && is_zero_ether_addr(wpa_psk->addr))
|
||||||
|
any_psk = wpa_psk->psk;
|
||||||
|
|
||||||
|
if (mac_addr && !dev_psk &&
|
||||||
|
os_memcmp(mac_addr, wpa_psk->addr, ETH_ALEN) == 0) {
|
||||||
|
dev_psk = wpa_psk->psk;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dev_psk) {
|
||||||
|
*psk = dev_psk;
|
||||||
|
} else if (any_psk) {
|
||||||
|
*psk = any_psk;
|
||||||
|
} else {
|
||||||
|
*psk = NULL;
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"WPS: No appropriate PSK in wpa_psk_file");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void wps_reload_config(void *eloop_data, void *user_ctx)
|
static void wps_reload_config(void *eloop_data, void *user_ctx)
|
||||||
{
|
{
|
||||||
struct hostapd_iface *iface = eloop_data;
|
struct hostapd_iface *iface = eloop_data;
|
||||||
@ -1213,6 +1251,7 @@ int hostapd_init_wps(struct hostapd_data *hapd,
|
|||||||
cfg.pin_needed_cb = hostapd_wps_pin_needed_cb;
|
cfg.pin_needed_cb = hostapd_wps_pin_needed_cb;
|
||||||
cfg.reg_success_cb = hostapd_wps_reg_success_cb;
|
cfg.reg_success_cb = hostapd_wps_reg_success_cb;
|
||||||
cfg.enrollee_seen_cb = hostapd_wps_enrollee_seen_cb;
|
cfg.enrollee_seen_cb = hostapd_wps_enrollee_seen_cb;
|
||||||
|
cfg.lookup_pskfile_cb = hostapd_wps_lookup_pskfile_cb;
|
||||||
cfg.cb_ctx = hapd;
|
cfg.cb_ctx = hapd;
|
||||||
cfg.skip_cred_build = conf->skip_cred_build;
|
cfg.skip_cred_build = conf->skip_cred_build;
|
||||||
cfg.extra_cred = conf->extra_cred;
|
cfg.extra_cred = conf->extra_cred;
|
||||||
|
@ -344,6 +344,14 @@ struct wps_registrar_config {
|
|||||||
u16 dev_password_id, u8 request_type,
|
u16 dev_password_id, u8 request_type,
|
||||||
const char *dev_name);
|
const char *dev_name);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* lookup_pskfile_cb - Callback for searching for PSK in wpa_psk_file
|
||||||
|
* @ctx: Higher layer context data (cb_ctx)
|
||||||
|
* @addr: Enrollee's MAC address
|
||||||
|
* @psk: Pointer to found PSK (output arg)
|
||||||
|
*/
|
||||||
|
int (*lookup_pskfile_cb)(void *ctx, const u8 *mac_addr, const u8 **psk);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* cb_ctx: Higher layer context data for Registrar callbacks
|
* cb_ctx: Higher layer context data for Registrar callbacks
|
||||||
*/
|
*/
|
||||||
|
@ -160,6 +160,7 @@ struct wps_registrar {
|
|||||||
const u8 *pri_dev_type, u16 config_methods,
|
const u8 *pri_dev_type, u16 config_methods,
|
||||||
u16 dev_password_id, u8 request_type,
|
u16 dev_password_id, u8 request_type,
|
||||||
const char *dev_name);
|
const char *dev_name);
|
||||||
|
int (*lookup_pskfile_cb)(void *ctx, const u8 *mac_addr, const u8 **psk);
|
||||||
void *cb_ctx;
|
void *cb_ctx;
|
||||||
|
|
||||||
struct dl_list pins;
|
struct dl_list pins;
|
||||||
@ -682,6 +683,7 @@ wps_registrar_init(struct wps_context *wps,
|
|||||||
reg->reg_success_cb = cfg->reg_success_cb;
|
reg->reg_success_cb = cfg->reg_success_cb;
|
||||||
reg->set_sel_reg_cb = cfg->set_sel_reg_cb;
|
reg->set_sel_reg_cb = cfg->set_sel_reg_cb;
|
||||||
reg->enrollee_seen_cb = cfg->enrollee_seen_cb;
|
reg->enrollee_seen_cb = cfg->enrollee_seen_cb;
|
||||||
|
reg->lookup_pskfile_cb = cfg->lookup_pskfile_cb;
|
||||||
reg->cb_ctx = cfg->cb_ctx;
|
reg->cb_ctx = cfg->cb_ctx;
|
||||||
reg->skip_cred_build = cfg->skip_cred_build;
|
reg->skip_cred_build = cfg->skip_cred_build;
|
||||||
if (cfg->extra_cred) {
|
if (cfg->extra_cred) {
|
||||||
@ -1291,6 +1293,15 @@ static void wps_cb_set_sel_reg(struct wps_registrar *reg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int wps_cp_lookup_pskfile(struct wps_registrar *reg, const u8 *mac_addr,
|
||||||
|
const u8 **psk)
|
||||||
|
{
|
||||||
|
if (!reg->lookup_pskfile_cb)
|
||||||
|
return 0;
|
||||||
|
return reg->lookup_pskfile_cb(reg->cb_ctx, mac_addr, psk);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int wps_set_ie(struct wps_registrar *reg)
|
static int wps_set_ie(struct wps_registrar *reg)
|
||||||
{
|
{
|
||||||
struct wpabuf *beacon;
|
struct wpabuf *beacon;
|
||||||
@ -1645,6 +1656,8 @@ int wps_build_cred(struct wps_data *wps, struct wpabuf *msg)
|
|||||||
{
|
{
|
||||||
struct wpabuf *cred;
|
struct wpabuf *cred;
|
||||||
struct wps_registrar *reg = wps->wps->registrar;
|
struct wps_registrar *reg = wps->wps->registrar;
|
||||||
|
const u8 *pskfile_psk;
|
||||||
|
char hex[65];
|
||||||
|
|
||||||
if (wps->wps->registrar->skip_cred_build)
|
if (wps->wps->registrar->skip_cred_build)
|
||||||
goto skip_cred_build;
|
goto skip_cred_build;
|
||||||
@ -1760,9 +1773,14 @@ int wps_build_cred(struct wps_data *wps, struct wpabuf *msg)
|
|||||||
wps->new_psk, wps->new_psk_len);
|
wps->new_psk, wps->new_psk_len);
|
||||||
os_memcpy(wps->cred.key, wps->new_psk, wps->new_psk_len);
|
os_memcpy(wps->cred.key, wps->new_psk, wps->new_psk_len);
|
||||||
wps->cred.key_len = wps->new_psk_len;
|
wps->cred.key_len = wps->new_psk_len;
|
||||||
|
} else if (wps_cp_lookup_pskfile(reg, wps->mac_addr_e, &pskfile_psk)) {
|
||||||
|
wpa_hexdump_key(MSG_DEBUG, "WPS: Use PSK from wpa_psk_file",
|
||||||
|
pskfile_psk, PMK_LEN);
|
||||||
|
wpa_snprintf_hex(hex, sizeof(hex), pskfile_psk, PMK_LEN);
|
||||||
|
os_memcpy(wps->cred.key, hex, PMK_LEN * 2);
|
||||||
|
wps->cred.key_len = PMK_LEN * 2;
|
||||||
} else if (!wps->wps->registrar->force_per_enrollee_psk &&
|
} else if (!wps->wps->registrar->force_per_enrollee_psk &&
|
||||||
wps->use_psk_key && wps->wps->psk_set) {
|
wps->use_psk_key && wps->wps->psk_set) {
|
||||||
char hex[65];
|
|
||||||
wpa_printf(MSG_DEBUG, "WPS: Use PSK format for Network Key");
|
wpa_printf(MSG_DEBUG, "WPS: Use PSK format for Network Key");
|
||||||
wpa_snprintf_hex(hex, sizeof(hex), wps->wps->psk, PMK_LEN);
|
wpa_snprintf_hex(hex, sizeof(hex), wps->wps->psk, PMK_LEN);
|
||||||
os_memcpy(wps->cred.key, hex, PMK_LEN * 2);
|
os_memcpy(wps->cred.key, hex, PMK_LEN * 2);
|
||||||
@ -1773,7 +1791,6 @@ int wps_build_cred(struct wps_data *wps, struct wpabuf *msg)
|
|||||||
wps->wps->network_key_len);
|
wps->wps->network_key_len);
|
||||||
wps->cred.key_len = wps->wps->network_key_len;
|
wps->cred.key_len = wps->wps->network_key_len;
|
||||||
} else if (wps->auth_type & (WPS_AUTH_WPAPSK | WPS_AUTH_WPA2PSK)) {
|
} else if (wps->auth_type & (WPS_AUTH_WPAPSK | WPS_AUTH_WPA2PSK)) {
|
||||||
char hex[65];
|
|
||||||
/* Generate a random per-device PSK */
|
/* Generate a random per-device PSK */
|
||||||
os_free(wps->new_psk);
|
os_free(wps->new_psk);
|
||||||
wps->new_psk_len = PMK_LEN;
|
wps->new_psk_len = PMK_LEN;
|
||||||
|
Loading…
Reference in New Issue
Block a user