From 26bf70e3d2af681e1761b0cee00b9ef4c6f37347 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 17 Dec 2016 17:19:34 +0200 Subject: [PATCH] FILS: Separate FILS realm configuration from ERP domain The new hostapd configuration parameter fils_realm= can now be used to configure one or more FILS realms to advertise for ERP domains when using FILS. This replaces the use of erp_domain= parameter for the FILS use case. Signed-off-by: Jouni Malinen --- hostapd/config_file.c | 26 ++++++++++++++++++++++++++ hostapd/hostapd.conf | 7 +++++++ src/ap/ap_config.c | 20 ++++++++++++++++++++ src/ap/ap_config.h | 7 +++++++ src/ap/ieee802_11_shared.c | 18 ++++++++++++++---- 5 files changed, 74 insertions(+), 4 deletions(-) diff --git a/hostapd/config_file.c b/hostapd/config_file.c index d9fdd20b4..32ae6883e 100644 --- a/hostapd/config_file.c +++ b/hostapd/config_file.c @@ -2017,6 +2017,29 @@ static int parse_wpabuf_hex(int line, const char *name, struct wpabuf **buf, } +#ifdef CONFIG_FILS +static int parse_fils_realm(struct hostapd_bss_config *bss, const char *val) +{ + struct fils_realm *realm; + size_t len; + + len = os_strlen(val); + realm = os_zalloc(sizeof(*realm) + len + 1); + if (!realm) + return -1; + + os_memcpy(realm->realm, val, len); + if (fils_domain_name_hash(val, realm->hash) < 0) { + os_free(realm); + return -1; + } + dl_list_add_tail(&bss->fils_realms, &realm->list); + + return 0; +} +#endif /* CONFIG_FILS */ + + static int hostapd_config_fill(struct hostapd_config *conf, struct hostapd_bss_config *bss, const char *buf, char *pos, int line) @@ -3577,6 +3600,9 @@ static int hostapd_config_fill(struct hostapd_config *conf, return 1; } bss->fils_cache_id_set = 1; + } else if (os_strcmp(buf, "fils_realm") == 0) { + if (parse_fils_realm(bss, pos) < 0) + return 1; #endif /* CONFIG_FILS */ } else if (os_strcmp(buf, "multicast_to_unicast") == 0) { bss->multicast_to_unicast = atoi(pos); diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf index 1fd4fcc95..e68874a3e 100644 --- a/hostapd/hostapd.conf +++ b/hostapd/hostapd.conf @@ -1309,6 +1309,13 @@ own_ip_addr=127.0.0.1 # FILS Cache Identifier (16-bit value in hexdump format) #fils_cache_id=0011 +# FILS Realm Information +# One or more FILS realms need to be configured when FILS is enabled. This list +# of realms is used to define which realms (used in keyName-NAI by the client) +# can be used with FILS shared key authentication for ERP. +#fils_realm=example.com +#fils_realm=example.org + ##### IEEE 802.11r configuration ############################################## # Mobility Domain identifier (dot11FTMobilityDomainID, MDID) diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c index c9865740e..97241cf61 100644 --- a/src/ap/ap_config.c +++ b/src/ap/ap_config.c @@ -95,6 +95,10 @@ void hostapd_config_defaults_bss(struct hostapd_bss_config *bss) bss->radius_das_time_window = 300; bss->sae_anti_clogging_threshold = 5; + +#ifdef CONFIG_FILS + dl_list_init(&bss->fils_realms); +#endif /* CONFIG_FILS */ } @@ -420,6 +424,20 @@ static void hostapd_config_free_anqp_elem(struct hostapd_bss_config *conf) } +static void hostapd_config_free_fils_realms(struct hostapd_bss_config *conf) +{ +#ifdef CONFIG_FILS + struct fils_realm *realm; + + while ((realm = dl_list_first(&conf->fils_realms, struct fils_realm, + list))) { + dl_list_del(&realm->list); + os_free(realm); + } +#endif /* CONFIG_FILS */ +} + + void hostapd_config_free_bss(struct hostapd_bss_config *conf) { struct hostapd_eap_user *user, *prev_user; @@ -582,6 +600,8 @@ void hostapd_config_free_bss(struct hostapd_bss_config *conf) os_free(conf->no_probe_resp_if_seen_on); os_free(conf->no_auth_if_seen_on); + hostapd_config_free_fils_realms(conf); + os_free(conf); } diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h index 7d8f28317..c9cc22a2f 100644 --- a/src/ap/ap_config.h +++ b/src/ap/ap_config.h @@ -224,6 +224,12 @@ struct anqp_element { struct wpabuf *payload; }; +struct fils_realm { + struct dl_list list; + u8 hash[2]; + char realm[]; +}; + /** * struct hostapd_bss_config - Per-BSS configuration @@ -600,6 +606,7 @@ struct hostapd_bss_config { #ifdef CONFIG_FILS u8 fils_cache_id[FILS_CACHE_ID_LEN]; int fils_cache_id_set; + struct dl_list fils_realms; /* list of struct fils_realm */ #endif /* CONFIG_FILS */ int multicast_to_unicast; diff --git a/src/ap/ieee802_11_shared.c b/src/ap/ieee802_11_shared.c index d20ddc744..daacf7e44 100644 --- a/src/ap/ieee802_11_shared.c +++ b/src/ap/ieee802_11_shared.c @@ -605,18 +605,23 @@ u8 * hostapd_eid_fils_indic(struct hostapd_data *hapd, u8 *eid, int hessid) #ifdef CONFIG_FILS u8 *len; u16 fils_info = 0; + size_t realms; + struct fils_realm *realm; if (!(hapd->conf->wpa & WPA_PROTO_RSN) || !wpa_key_mgmt_fils(hapd->conf->wpa_key_mgmt)) return pos; + realms = dl_list_len(&hapd->conf->fils_realms); + if (realms > 7) + realms = 7; /* 3 bit count field limits this to max 7 */ + *pos++ = WLAN_EID_FILS_INDICATION; len = pos++; /* TODO: B0..B2: Number of Public Key Identifiers */ if (hapd->conf->erp_domain) { - /* TODO: Support for setting multiple domain identifiers */ /* B3..B5: Number of Realm Identifiers */ - fils_info |= BIT(3); + fils_info |= realms << 3; } /* TODO: B6: FILS IP Address Configuration */ if (hapd->conf->fils_cache_id_set) @@ -638,8 +643,13 @@ u8 * hostapd_eid_fils_indic(struct hostapd_data *hapd, u8 *eid, int hessid) os_memcpy(pos, hapd->conf->hessid, ETH_ALEN); pos += ETH_ALEN; } - if (hapd->conf->erp_domain) { - fils_domain_name_hash(hapd->conf->erp_domain, pos); + + dl_list_for_each(realm, &hapd->conf->fils_realms, struct fils_realm, + list) { + if (realms == 0) + break; + realms--; + os_memcpy(pos, realm->hash, 2); pos += 2; } *len = pos - len - 1;