[PATCH v2 08/33] FT: negative caching when using wilcard r0kh
Michael Braun
michael-dev at fami-braun.de
Sat Sep 24 13:53:49 PDT 2016
When a station uses an invalid or offline r0kh_id, requests are always
broadcasted. To avoid this, r0kh is required to always reply using a NACK
and target ap uses a timer to detect non replying r0kh.
If r0kh does not reply, a temporary blacklist entry is added to r0kh_list.
Signed-off-by: Michael Braun <michael-dev at fami-braun.de>
---
hostapd/config_file.c | 2 ++
hostapd/hostapd.conf | 6 +++++
src/ap/ap_config.c | 1 +
src/ap/ap_config.h | 1 +
src/ap/wpa_auth.h | 3 ++-
src/ap/wpa_auth_ft.c | 71 +++++++++++++++++++++++++++++++++++---------------
src/ap/wpa_auth_glue.c | 1 +
7 files changed, 63 insertions(+), 22 deletions(-)
diff --git a/hostapd/config_file.c b/hostapd/config_file.c
index 1a8b5f2..5bd0336 100644
--- a/hostapd/config_file.c
+++ b/hostapd/config_file.c
@@ -2545,6 +2545,8 @@ static int hostapd_config_fill(struct hostapd_config *conf,
bss->reassociation_deadline = atoi(pos);
} else if (os_strcmp(buf, "rkh_pos_timeout") == 0) {
bss->rkh_pos_timeout = atoi(pos);
+ } else if (os_strcmp(buf, "rkh_neg_timeout") == 0) {
+ bss->rkh_neg_timeout = atoi(pos);
} else if (os_strcmp(buf, "rkh_pull_timeout") == 0) {
bss->rkh_pull_timeout = atoi(pos);
} else if (os_strcmp(buf, "rkh_pull_retries") == 0) {
diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf
index 24cd3e1..8aa4248 100644
--- a/hostapd/hostapd.conf
+++ b/hostapd/hostapd.conf
@@ -1309,6 +1309,7 @@ own_ip_addr=127.0.0.1
# Wildcard entry: Upon receiving a request from an R1KH not yet known,
# it will be added to this list and thus receive push
# notifications.
+# If R0KH does not reply, it will be blacklisted.
#r0kh=ff:ff:ff:ff:ff:ff * 00112233445566778899aabbccddeeff
# List of R1KHs in the same Mobility Domain
@@ -1332,6 +1333,11 @@ own_ip_addr=127.0.0.1
#rkh_pull_timeout = 1000 (default = 1s)
#rkh_pull_retries = 4 (default)
+# Timeout (seconds) for non replying R0KH (see wildcard entries above)
+# Special values: 0 -> do not cache
+# default: 60 seconds
+#rkh_neg_timeout = 86400
+
# Whether PMK-R1 push is enabled at R0KH
# 0 = do not push PMK-R1 to all configured R1KHs (default)
# 1 = push PMK-R1 to all configured R1KHs whenever a new PMK-R0 is derived
diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c
index 35fe74d..accd9a3 100644
--- a/src/ap/ap_config.c
+++ b/src/ap/ap_config.c
@@ -91,6 +91,7 @@ void hostapd_config_defaults_bss(struct hostapd_bss_config *bss)
#ifdef CONFIG_IEEE80211R
bss->ft_over_ds = 1;
bss->rkh_pos_timeout = 86400;
+ bss->rkh_neg_timeout = 60;
bss->rkh_pull_timeout = 1000;
bss->rkh_pull_retries = 4;
#endif /* CONFIG_IEEE80211R */
diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
index 438da47..8c03504 100644
--- a/src/ap/ap_config.h
+++ b/src/ap/ap_config.h
@@ -335,6 +335,7 @@ struct hostapd_bss_config {
u8 r1_key_holder[FT_R1KH_ID_LEN];
u32 r0_key_lifetime;
int rkh_pos_timeout;
+ int rkh_neg_timeout;
int rkh_pull_timeout; /* ms */
int rkh_pull_retries;
u32 reassociation_deadline;
diff --git a/src/ap/wpa_auth.h b/src/ap/wpa_auth.h
index 6a3497a..0e5ad1a 100644
--- a/src/ap/wpa_auth.h
+++ b/src/ap/wpa_auth.h
@@ -80,7 +80,7 @@ struct ft_r0kh_r1kh_resp_frame {
u8 s1kh_id[ETH_ALEN]; /* copied from pull */
u8 pmk_r1[PMK_LEN];
u8 pmk_r1_name[WPA_PMK_NAME_LEN];
- le16 pairwise;
+ le16 pairwise; /* zero if no entry found */
u8 pad[FT_R0KH_R1KH_RESP_PAD_LEN]; /* 8-octet boundary for AES block */
u8 key_wrap_extra[8];
} STRUCT_PACKED;
@@ -169,6 +169,7 @@ struct wpa_auth_config {
u8 r1_key_holder[FT_R1KH_ID_LEN];
u32 r0_key_lifetime;
int rkh_pos_timeout;
+ int rkh_neg_timeout;
int rkh_pull_timeout; /* ms */
int rkh_pull_retries;
u32 reassociation_deadline;
diff --git a/src/ap/wpa_auth_ft.c b/src/ap/wpa_auth_ft.c
index 4e66fde..0c92d40 100644
--- a/src/ap/wpa_auth_ft.c
+++ b/src/ap/wpa_auth_ft.c
@@ -430,9 +430,21 @@ void wpa_ft_deinit(struct wpa_authenticator *wpa_auth)
static void wpa_ft_expire_pull(void *eloop_ctx, void *timeout_ctx)
{
+ struct wpa_state_machine *sm = eloop_ctx;
+
+ if (sm->ft_pending_pull_left_retries <= 0 &&
+ sm->wpa_auth->conf.rkh_neg_timeout) {
+ /* final timeout, block this r0kh_id */
+ wpa_hexdump(MSG_DEBUG, "FT: Blacklist R0KH-ID",
+ sm->r0kh_id, sm->r0kh_id_len);
+ wpa_ft_rrb_add_r0kh(sm->wpa_auth, NULL,
+ (u8 *) "\x00\x00\x00\x00\x00\x00",
+ sm->r0kh_id, sm->r0kh_id_len,
+ sm->wpa_auth->conf.rkh_neg_timeout);
+ }
/* cancel multiple timeouts */
- eloop_cancel_timeout(wpa_ft_expire_pull, eloop_ctx, NULL);
- eloop_cancel_timeout(ft_pull_resp_cb_finish, eloop_ctx, NULL);
+ eloop_cancel_timeout(wpa_ft_expire_pull, sm, NULL);
+ eloop_cancel_timeout(ft_pull_resp_cb_finish, sm, NULL);
ft_pull_resp_cb_finish(eloop_ctx, timeout_ctx);
}
@@ -473,6 +485,11 @@ static int wpa_ft_pull_pmk_r1(struct wpa_state_machine *sm,
sm->r0kh_id, sm->r0kh_id_len);
return -1;
}
+ if (is_zero_ether_addr(r0kh->addr)) {
+ wpa_hexdump(MSG_DEBUG, "FT: R0KH-ID is blacklisted",
+ sm->r0kh_id, sm->r0kh_id_len);
+ return -1;
+ }
wpa_printf(MSG_DEBUG, "FT: Send PMK-R1 pull request to remote R0KH "
"address " MACSTR, MAC2STR(r0kh->addr));
@@ -1653,15 +1670,15 @@ static int wpa_ft_rrb_rx_pull(struct wpa_authenticator *wpa_auth,
&pairwise) < 0) {
wpa_printf(MSG_DEBUG, "FT: No matching PMKR0Name found for "
"PMK-R1 pull");
- return -1;
+ r.pairwise = 0;
+ } else {
+ wpa_derive_pmk_r1(pmk_r0, f.pmk_r0_name, f.r1kh_id, f.s1kh_id,
+ r.pmk_r1, r.pmk_r1_name);
+ wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1", r.pmk_r1, PMK_LEN);
+ wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name", r.pmk_r1_name,
+ WPA_PMK_NAME_LEN);
+ r.pairwise = host_to_le16(pairwise);
}
-
- wpa_derive_pmk_r1(pmk_r0, f.pmk_r0_name, f.r1kh_id, f.s1kh_id,
- r.pmk_r1, r.pmk_r1_name);
- wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1", r.pmk_r1, PMK_LEN);
- wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name", r.pmk_r1_name,
- WPA_PMK_NAME_LEN);
- r.pairwise = host_to_le16(pairwise);
os_memset(r.pad, 0, sizeof(r.pad));
if (aes_wrap(r1kh->key, sizeof(r1kh->key),
@@ -1734,6 +1751,8 @@ static int ft_pull_resp_cb(struct wpa_state_machine *sm, void *ctx)
wpa_printf(MSG_DEBUG, "FT: Response to a pending pull request for "
MACSTR " - process from timeout", MAC2STR(sm->addr));
+ if (frame->pairwise == 0)
+ sm->ft_pending_pull_left_retries = 0;
eloop_cancel_timeout(wpa_ft_expire_pull, sm, NULL);
eloop_cancel_timeout(ft_pull_resp_cb_finish, sm, NULL);
@@ -1807,18 +1826,28 @@ static int wpa_ft_rrb_rx_resp(struct wpa_authenticator *wpa_auth,
}
pairwise = le_to_host16(f.pairwise);
- wpa_hexdump(MSG_DEBUG, "FT: PMK-R1 pull - nonce",
- f.nonce, sizeof(f.nonce));
- wpa_printf(MSG_DEBUG, "FT: PMK-R1 pull - R1KH-ID=" MACSTR " S1KH-ID="
- MACSTR " pairwise=0x%x",
- MAC2STR(f.r1kh_id), MAC2STR(f.s1kh_id), pairwise);
- wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1 pull - PMK-R1",
- f.pmk_r1, PMK_LEN);
- wpa_hexdump(MSG_DEBUG, "FT: PMK-R1 pull - PMKR1Name",
- f.pmk_r1_name, WPA_PMK_NAME_LEN);
+ if (f.pairwise == 0) {
+ res = 0;
+ wpa_hexdump(MSG_DEBUG, "FT: PMK-R1 pull - nonce",
+ f.nonce, sizeof(f.nonce));
+ wpa_printf(MSG_DEBUG, "FT: PMK-R1 pull - R1KH-ID=" MACSTR
+ " S1KH-ID=" MACSTR " NACK",
+ MAC2STR(f.r1kh_id), MAC2STR(f.s1kh_id));
+ } else {
+ wpa_hexdump(MSG_DEBUG, "FT: PMK-R1 pull - nonce",
+ f.nonce, sizeof(f.nonce));
+ wpa_printf(MSG_DEBUG, "FT: PMK-R1 pull - R1KH-ID=" MACSTR
+ " S1KH-ID=" MACSTR " pairwise=0x%x",
+ MAC2STR(f.r1kh_id), MAC2STR(f.s1kh_id), pairwise);
+ wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1 pull - PMK-R1",
+ f.pmk_r1, PMK_LEN);
+ wpa_hexdump(MSG_DEBUG, "FT: PMK-R1 pull - PMKR1Name",
+ f.pmk_r1_name, WPA_PMK_NAME_LEN);
+
+ res = wpa_ft_store_pmk_r1(wpa_auth, f.s1kh_id, f.pmk_r1,
+ f.pmk_r1_name, pairwise);
+ }
- res = wpa_ft_store_pmk_r1(wpa_auth, f.s1kh_id, f.pmk_r1, f.pmk_r1_name,
- pairwise);
wpa_printf(MSG_DEBUG, "FT: Look for pending pull request");
ctx.frame = &f;
diff --git a/src/ap/wpa_auth_glue.c b/src/ap/wpa_auth_glue.c
index 57ca999..fe926a4 100644
--- a/src/ap/wpa_auth_glue.c
+++ b/src/ap/wpa_auth_glue.c
@@ -70,6 +70,7 @@ static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf,
wconf->r0_key_lifetime = conf->r0_key_lifetime;
wconf->reassociation_deadline = conf->reassociation_deadline;
wconf->rkh_pos_timeout = conf->rkh_pos_timeout;
+ wconf->rkh_neg_timeout = conf->rkh_neg_timeout;
wconf->rkh_pull_timeout = conf->rkh_pull_timeout;
wconf->rkh_pull_retries = conf->rkh_pull_retries;
wconf->r0kh_list = &conf->r0kh_list;
--
2.1.4
More information about the Hostap
mailing list