From 08081ad8efbf43eeea15969f9b2c487f9f7f25b8 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 7 Jan 2014 20:14:53 +0200 Subject: [PATCH] hostapd: Skip full AP configuration validation on SET command It is possible for the configuration to be temporarily invalid when adding a new AP through SET commands followed by ENABLE. Avoid this issue by using less strict validation on SET commands and perform full configuration validation only on ENABLE. Use cases with configuration file maintain their previous behavior, i.e., full validation after the file has been read. Signed-hostap: Jouni Malinen --- hostapd/config_file.c | 4 ++-- src/ap/ap_config.c | 41 +++++++++++++++++++++++------------------ src/ap/ap_config.h | 2 +- src/ap/hostapd.c | 9 +++++++-- 4 files changed, 33 insertions(+), 23 deletions(-) diff --git a/hostapd/config_file.c b/hostapd/config_file.c index 41988345b..54e4af9d3 100644 --- a/hostapd/config_file.c +++ b/hostapd/config_file.c @@ -2989,7 +2989,7 @@ struct hostapd_config * hostapd_config_read(const char *fname) for (i = 0; i < conf->num_bss; i++) hostapd_set_security_params(conf->bss[i]); - if (hostapd_config_check(conf)) + if (hostapd_config_check(conf, 1)) errors++; #ifndef WPA_IGNORE_CONFIG_ERRORS @@ -3021,7 +3021,7 @@ int hostapd_set_iface(struct hostapd_config *conf, for (i = 0; i < conf->num_bss; i++) hostapd_set_security_params(conf->bss[i]); - if (hostapd_config_check(conf)) { + if (hostapd_config_check(conf, 0)) { wpa_printf(MSG_ERROR, "Configuration check failed"); return -1; } diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c index a29f4d0e0..79ab4ba10 100644 --- a/src/ap/ap_config.c +++ b/src/ap/ap_config.c @@ -1,6 +1,6 @@ /* * hostapd / Configuration helper functions - * Copyright (c) 2003-2013, Jouni Malinen + * Copyright (c) 2003-2014, Jouni Malinen * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -670,9 +670,10 @@ const u8 * hostapd_get_psk(const struct hostapd_bss_config *conf, static int hostapd_config_check_bss(struct hostapd_bss_config *bss, - struct hostapd_config *conf) + struct hostapd_config *conf, + int full_config) { - if (bss->ieee802_1x && !bss->eap_server && + if (full_config && bss->ieee802_1x && !bss->eap_server && !bss->radius->auth_servers) { wpa_printf(MSG_ERROR, "Invalid IEEE 802.1X configuration (no " "EAP authenticator configured)."); @@ -697,14 +698,15 @@ static int hostapd_config_check_bss(struct hostapd_bss_config *bss, } } - if (bss->wpa && bss->wpa_psk_radius != PSK_RADIUS_IGNORED && + if (full_config && bss->wpa && + bss->wpa_psk_radius != PSK_RADIUS_IGNORED && bss->macaddr_acl != USE_EXTERNAL_RADIUS_AUTH) { wpa_printf(MSG_ERROR, "WPA-PSK using RADIUS enabled, but no " "RADIUS checking (macaddr_acl=2) enabled."); return -1; } - if (bss->wpa && (bss->wpa_key_mgmt & WPA_KEY_MGMT_PSK) && + if (full_config && bss->wpa && (bss->wpa_key_mgmt & WPA_KEY_MGMT_PSK) && bss->ssid.wpa_psk == NULL && bss->ssid.wpa_passphrase == NULL && bss->ssid.wpa_psk_file == NULL && (bss->wpa_psk_radius != PSK_RADIUS_REQUIRED || @@ -714,7 +716,7 @@ static int hostapd_config_check_bss(struct hostapd_bss_config *bss, return -1; } - if (hostapd_mac_comp_empty(bss->bssid) != 0) { + if (full_config && hostapd_mac_comp_empty(bss->bssid) != 0) { size_t i; for (i = 0; i < conf->num_bss; i++) { @@ -731,7 +733,7 @@ static int hostapd_config_check_bss(struct hostapd_bss_config *bss, } #ifdef CONFIG_IEEE80211R - if (wpa_key_mgmt_ft(bss->wpa_key_mgmt) && + if (full_config && wpa_key_mgmt_ft(bss->wpa_key_mgmt) && (bss->nas_identifier == NULL || os_strlen(bss->nas_identifier) < 1 || os_strlen(bss->nas_identifier) > FT_R0KH_ID_MAX_LEN)) { @@ -743,20 +745,21 @@ static int hostapd_config_check_bss(struct hostapd_bss_config *bss, #endif /* CONFIG_IEEE80211R */ #ifdef CONFIG_IEEE80211N - if (conf->ieee80211n && conf->hw_mode == HOSTAPD_MODE_IEEE80211B) { + if (full_config && conf->ieee80211n && + conf->hw_mode == HOSTAPD_MODE_IEEE80211B) { bss->disable_11n = 1; wpa_printf(MSG_ERROR, "HT (IEEE 802.11n) in 11b mode is not " "allowed, disabling HT capabilites"); } - if (conf->ieee80211n && + if (full_config && conf->ieee80211n && bss->ssid.security_policy == SECURITY_STATIC_WEP) { bss->disable_11n = 1; wpa_printf(MSG_ERROR, "HT (IEEE 802.11n) with WEP is not " "allowed, disabling HT capabilities"); } - if (conf->ieee80211n && bss->wpa && + if (full_config && conf->ieee80211n && bss->wpa && !(bss->wpa_pairwise & WPA_CIPHER_CCMP) && !(bss->rsn_pairwise & (WPA_CIPHER_CCMP | WPA_CIPHER_GCMP | WPA_CIPHER_CCMP_256 | WPA_CIPHER_GCMP_256))) @@ -769,19 +772,20 @@ static int hostapd_config_check_bss(struct hostapd_bss_config *bss, #endif /* CONFIG_IEEE80211N */ #ifdef CONFIG_WPS2 - if (bss->wps_state && bss->ignore_broadcast_ssid) { + if (full_config && bss->wps_state && bss->ignore_broadcast_ssid) { wpa_printf(MSG_INFO, "WPS: ignore_broadcast_ssid " "configuration forced WPS to be disabled"); bss->wps_state = 0; } - if (bss->wps_state && bss->ssid.wep.keys_set && bss->wpa == 0) { + if (full_config && bss->wps_state && + bss->ssid.wep.keys_set && bss->wpa == 0) { wpa_printf(MSG_INFO, "WPS: WEP configuration forced WPS to be " "disabled"); bss->wps_state = 0; } - if (bss->wps_state && bss->wpa && + if (full_config && bss->wps_state && bss->wpa && (!(bss->wpa & 2) || !(bss->rsn_pairwise & WPA_CIPHER_CCMP))) { wpa_printf(MSG_INFO, "WPS: WPA/TKIP configuration without " @@ -791,7 +795,7 @@ static int hostapd_config_check_bss(struct hostapd_bss_config *bss, #endif /* CONFIG_WPS2 */ #ifdef CONFIG_HS20 - if (bss->hs20 && + if (full_config && bss->hs20 && (!(bss->wpa & 2) || !(bss->rsn_pairwise & (WPA_CIPHER_CCMP | WPA_CIPHER_GCMP | WPA_CIPHER_CCMP_256 | @@ -807,24 +811,25 @@ static int hostapd_config_check_bss(struct hostapd_bss_config *bss, } -int hostapd_config_check(struct hostapd_config *conf) +int hostapd_config_check(struct hostapd_config *conf, int full_config) { size_t i; - if (conf->ieee80211d && (!conf->country[0] || !conf->country[1])) { + if (full_config && conf->ieee80211d && + (!conf->country[0] || !conf->country[1])) { wpa_printf(MSG_ERROR, "Cannot enable IEEE 802.11d without " "setting the country_code"); return -1; } - if (conf->ieee80211h && !conf->ieee80211d) { + if (full_config && conf->ieee80211h && !conf->ieee80211d) { wpa_printf(MSG_ERROR, "Cannot enable IEEE 802.11h without " "IEEE 802.11d enabled"); return -1; } for (i = 0; i < conf->num_bss; i++) { - if (hostapd_config_check_bss(conf->bss[i], conf)) + if (hostapd_config_check_bss(conf->bss[i], conf, full_config)) return -1; } diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h index af30ac49a..0bb937e0d 100644 --- a/src/ap/ap_config.h +++ b/src/ap/ap_config.h @@ -570,7 +570,7 @@ const char * hostapd_get_vlan_id_ifname(struct hostapd_vlan *vlan, int vlan_id); struct hostapd_radius_attr * hostapd_config_get_radius_attr(struct hostapd_radius_attr *attr, u8 type); -int hostapd_config_check(struct hostapd_config *conf); +int hostapd_config_check(struct hostapd_config *conf, int full_config); void hostapd_set_security_params(struct hostapd_bss_config *bss); #endif /* HOSTAPD_CONFIG_H */ diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c index 44d05c5d8..220211c6b 100644 --- a/src/ap/hostapd.c +++ b/src/ap/hostapd.c @@ -1,6 +1,6 @@ /* * hostapd / Initialization and configuration - * Copyright (c) 2002-2013, Jouni Malinen + * Copyright (c) 2002-2014, Jouni Malinen * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -1537,6 +1537,11 @@ int hostapd_enable_iface(struct hostapd_iface *hapd_iface) wpa_printf(MSG_DEBUG, "Enable interface %s", hapd_iface->conf->bss[0]->iface); + if (hostapd_config_check(hapd_iface->conf, 1) < 0) { + wpa_printf(MSG_INFO, "Invalid configuration - cannot enable"); + return -1; + } + if (hapd_iface->interfaces == NULL || hapd_iface->interfaces->driver_init == NULL || hapd_iface->interfaces->driver_init(hapd_iface)) @@ -1569,7 +1574,7 @@ int hostapd_reload_iface(struct hostapd_iface *hapd_iface) hapd_iface->conf->bss[0]->iface); for (j = 0; j < hapd_iface->num_bss; j++) hostapd_set_security_params(hapd_iface->conf->bss[j]); - if (hostapd_config_check(hapd_iface->conf) < 0) { + if (hostapd_config_check(hapd_iface->conf, 1) < 0) { wpa_printf(MSG_ERROR, "Updated configuration is invalid"); return -1; }