From bde7ba6caf3a2e56b277d9fcf3ff05b0606cb833 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 17 Jun 2012 17:43:36 +0300 Subject: [PATCH] RADIUS DAS: Validate Event-Timestamp DAS will now validate Event-Timestamp value to be within an acceptable time window (300 seconds by default; can be set using radius_das_time_window parameter). In addition, Event-Timestamp can be required in Disconnect-Request and CoA-Request messages with radius_das_require_event_timestamp=1. Signed-hostap: Jouni Malinen --- hostapd/config_file.c | 5 +++++ hostapd/hostapd.conf | 6 ++++++ src/ap/ap_config.c | 2 ++ src/ap/ap_config.h | 2 ++ src/ap/hostapd.c | 3 +++ src/radius/radius_das.c | 30 ++++++++++++++++++++++++++++-- src/radius/radius_das.h | 2 ++ 7 files changed, 48 insertions(+), 2 deletions(-) diff --git a/hostapd/config_file.c b/hostapd/config_file.c index 6729e5c1d..b00ed8fcf 100644 --- a/hostapd/config_file.c +++ b/hostapd/config_file.c @@ -1693,6 +1693,11 @@ static int hostapd_config_fill(struct hostapd_config *conf, "DAS client", line); errors++; } + } else if (os_strcmp(buf, "radius_das_time_window") == 0) { + bss->radius_das_time_window = atoi(pos); + } else if (os_strcmp(buf, "radius_das_require_event_timestamp") + == 0) { + bss->radius_das_require_event_timestamp = atoi(pos); #endif /* CONFIG_NO_RADIUS */ } else if (os_strcmp(buf, "auth_algs") == 0) { bss->auth_algs = atoi(pos); diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf index 611ce952e..a7b8ba6a0 100644 --- a/hostapd/hostapd.conf +++ b/hostapd/hostapd.conf @@ -708,6 +708,12 @@ own_ip_addr=127.0.0.1 # # DAS client (the host that can send Disconnect/CoA requests) and shared secret #radius_das_client=192.168.1.123 shared secret here +# +# DAS Event-Timestamp time window in seconds +#radius_das_time_window=300 +# +# DAS require Event-Timestamp +#radius_das_require_event_timestamp=1 ##### RADIUS authentication server configuration ############################## diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c index e916f1207..d8f55a217 100644 --- a/src/ap/ap_config.c +++ b/src/ap/ap_config.c @@ -87,6 +87,8 @@ void hostapd_config_defaults_bss(struct hostapd_bss_config *bss) #ifdef CONFIG_IEEE80211R bss->ft_over_ds = 1; #endif /* CONFIG_IEEE80211R */ + + bss->radius_das_time_window = 300; } diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h index 78c90689b..1f35f72fe 100644 --- a/src/ap/ap_config.h +++ b/src/ap/ap_config.h @@ -187,6 +187,8 @@ struct hostapd_bss_config { struct hostapd_radius_attr *radius_auth_req_attr; struct hostapd_radius_attr *radius_acct_req_attr; int radius_das_port; + unsigned int radius_das_time_window; + int radius_das_require_event_timestamp; struct hostapd_ip_addr radius_das_client_addr; u8 *radius_das_shared_secret; size_t radius_das_shared_secret_len; diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c index 9d6fd7b3c..50239b0b6 100644 --- a/src/ap/hostapd.c +++ b/src/ap/hostapd.c @@ -639,6 +639,9 @@ static int hostapd_setup_bss(struct hostapd_data *hapd, int first) das_conf.shared_secret_len = hapd->conf->radius_das_shared_secret_len; das_conf.client_addr = &hapd->conf->radius_das_client_addr; + das_conf.time_window = hapd->conf->radius_das_time_window; + das_conf.require_event_timestamp = + hapd->conf->radius_das_require_event_timestamp; hapd->radius_das = radius_das_init(&das_conf); if (hapd->radius_das == NULL) { wpa_printf(MSG_ERROR, "RADIUS DAS initialization " diff --git a/src/radius/radius_das.c b/src/radius/radius_das.c index ae3df8973..20c2fc969 100644 --- a/src/radius/radius_das.c +++ b/src/radius/radius_das.c @@ -24,6 +24,8 @@ struct radius_das_data { u8 *shared_secret; size_t shared_secret_len; struct hostapd_ip_addr client_addr; + unsigned int time_window; + int require_event_timestamp; }; @@ -45,6 +47,8 @@ static void radius_das_receive(int sock, void *eloop_ctx, void *sock_ctx) struct radius_msg *msg, *reply = NULL; struct radius_hdr *hdr; struct wpabuf *rbuf; + u32 val; + int res; fromlen = sizeof(from); len = recvfrom(sock, buf, sizeof(buf), 0, @@ -81,6 +85,27 @@ static void radius_das_receive(int sock, void *eloop_ctx, void *sock_ctx) goto fail; } + res = radius_msg_get_attr(msg, RADIUS_ATTR_EVENT_TIMESTAMP, + (u8 *) &val, 4); + if (res == 4) { + u32 timestamp = ntohl(val); + struct os_time now; + + os_get_time(&now); + if (abs(now.sec - timestamp) > das->time_window) { + wpa_printf(MSG_DEBUG, "DAS: Unacceptable " + "Event-Timestamp (%u; local time %u) in " + "packet from %s:%d - drop", + timestamp, (unsigned int) now.sec, + abuf, from_port); + goto fail; + } + } else if (das->require_event_timestamp) { + wpa_printf(MSG_DEBUG, "DAS: Missing Event-Timestamp in packet " + "from %s:%d - drop", abuf, from_port); + goto fail; + } + hdr = radius_msg_get_hdr(msg); switch (hdr->code) { @@ -110,8 +135,6 @@ static void radius_das_receive(int sock, void *eloop_ctx, void *sock_ctx) } if (reply) { - int res; - wpa_printf(MSG_DEBUG, "DAS: Reply to %s:%d", abuf, from_port); if (radius_msg_finish_das_resp(reply, das->shared_secret, @@ -177,6 +200,9 @@ radius_das_init(struct radius_das_conf *conf) if (das == NULL) return NULL; + das->time_window = conf->time_window; + das->require_event_timestamp = conf->require_event_timestamp; + os_memcpy(&das->client_addr, conf->client_addr, sizeof(das->client_addr)); diff --git a/src/radius/radius_das.h b/src/radius/radius_das.h index 4e21c6d63..c3d501d85 100644 --- a/src/radius/radius_das.h +++ b/src/radius/radius_das.h @@ -16,6 +16,8 @@ struct radius_das_conf { const u8 *shared_secret; size_t shared_secret_len; const struct hostapd_ip_addr *client_addr; + unsigned int time_window; + int require_event_timestamp; }; struct radius_das_data *