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 <j@w1.fi>
This commit is contained in:
Jouni Malinen 2014-01-07 20:14:53 +02:00
parent f19ee5b7f7
commit 08081ad8ef
4 changed files with 33 additions and 23 deletions

View file

@ -2989,7 +2989,7 @@ struct hostapd_config * hostapd_config_read(const char *fname)
for (i = 0; i < conf->num_bss; i++) for (i = 0; i < conf->num_bss; i++)
hostapd_set_security_params(conf->bss[i]); hostapd_set_security_params(conf->bss[i]);
if (hostapd_config_check(conf)) if (hostapd_config_check(conf, 1))
errors++; errors++;
#ifndef WPA_IGNORE_CONFIG_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++) for (i = 0; i < conf->num_bss; i++)
hostapd_set_security_params(conf->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"); wpa_printf(MSG_ERROR, "Configuration check failed");
return -1; return -1;
} }

View file

@ -1,6 +1,6 @@
/* /*
* hostapd / Configuration helper functions * hostapd / Configuration helper functions
* Copyright (c) 2003-2013, Jouni Malinen <j@w1.fi> * Copyright (c) 2003-2014, Jouni Malinen <j@w1.fi>
* *
* This software may be distributed under the terms of the BSD license. * This software may be distributed under the terms of the BSD license.
* See README for more details. * 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, 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) { !bss->radius->auth_servers) {
wpa_printf(MSG_ERROR, "Invalid IEEE 802.1X configuration (no " wpa_printf(MSG_ERROR, "Invalid IEEE 802.1X configuration (no "
"EAP authenticator configured)."); "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) { bss->macaddr_acl != USE_EXTERNAL_RADIUS_AUTH) {
wpa_printf(MSG_ERROR, "WPA-PSK using RADIUS enabled, but no " wpa_printf(MSG_ERROR, "WPA-PSK using RADIUS enabled, but no "
"RADIUS checking (macaddr_acl=2) enabled."); "RADIUS checking (macaddr_acl=2) enabled.");
return -1; 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 == NULL && bss->ssid.wpa_passphrase == NULL &&
bss->ssid.wpa_psk_file == NULL && bss->ssid.wpa_psk_file == NULL &&
(bss->wpa_psk_radius != PSK_RADIUS_REQUIRED || (bss->wpa_psk_radius != PSK_RADIUS_REQUIRED ||
@ -714,7 +716,7 @@ static int hostapd_config_check_bss(struct hostapd_bss_config *bss,
return -1; return -1;
} }
if (hostapd_mac_comp_empty(bss->bssid) != 0) { if (full_config && hostapd_mac_comp_empty(bss->bssid) != 0) {
size_t i; size_t i;
for (i = 0; i < conf->num_bss; 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 #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 || (bss->nas_identifier == NULL ||
os_strlen(bss->nas_identifier) < 1 || os_strlen(bss->nas_identifier) < 1 ||
os_strlen(bss->nas_identifier) > FT_R0KH_ID_MAX_LEN)) { 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 */ #endif /* CONFIG_IEEE80211R */
#ifdef CONFIG_IEEE80211N #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; bss->disable_11n = 1;
wpa_printf(MSG_ERROR, "HT (IEEE 802.11n) in 11b mode is not " wpa_printf(MSG_ERROR, "HT (IEEE 802.11n) in 11b mode is not "
"allowed, disabling HT capabilites"); "allowed, disabling HT capabilites");
} }
if (conf->ieee80211n && if (full_config && conf->ieee80211n &&
bss->ssid.security_policy == SECURITY_STATIC_WEP) { bss->ssid.security_policy == SECURITY_STATIC_WEP) {
bss->disable_11n = 1; bss->disable_11n = 1;
wpa_printf(MSG_ERROR, "HT (IEEE 802.11n) with WEP is not " wpa_printf(MSG_ERROR, "HT (IEEE 802.11n) with WEP is not "
"allowed, disabling HT capabilities"); "allowed, disabling HT capabilities");
} }
if (conf->ieee80211n && bss->wpa && if (full_config && conf->ieee80211n && bss->wpa &&
!(bss->wpa_pairwise & WPA_CIPHER_CCMP) && !(bss->wpa_pairwise & WPA_CIPHER_CCMP) &&
!(bss->rsn_pairwise & (WPA_CIPHER_CCMP | WPA_CIPHER_GCMP | !(bss->rsn_pairwise & (WPA_CIPHER_CCMP | WPA_CIPHER_GCMP |
WPA_CIPHER_CCMP_256 | WPA_CIPHER_GCMP_256))) 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 */ #endif /* CONFIG_IEEE80211N */
#ifdef CONFIG_WPS2 #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 " wpa_printf(MSG_INFO, "WPS: ignore_broadcast_ssid "
"configuration forced WPS to be disabled"); "configuration forced WPS to be disabled");
bss->wps_state = 0; 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 " wpa_printf(MSG_INFO, "WPS: WEP configuration forced WPS to be "
"disabled"); "disabled");
bss->wps_state = 0; bss->wps_state = 0;
} }
if (bss->wps_state && bss->wpa && if (full_config && bss->wps_state && bss->wpa &&
(!(bss->wpa & 2) || (!(bss->wpa & 2) ||
!(bss->rsn_pairwise & WPA_CIPHER_CCMP))) { !(bss->rsn_pairwise & WPA_CIPHER_CCMP))) {
wpa_printf(MSG_INFO, "WPS: WPA/TKIP configuration without " 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 */ #endif /* CONFIG_WPS2 */
#ifdef CONFIG_HS20 #ifdef CONFIG_HS20
if (bss->hs20 && if (full_config && bss->hs20 &&
(!(bss->wpa & 2) || (!(bss->wpa & 2) ||
!(bss->rsn_pairwise & (WPA_CIPHER_CCMP | WPA_CIPHER_GCMP | !(bss->rsn_pairwise & (WPA_CIPHER_CCMP | WPA_CIPHER_GCMP |
WPA_CIPHER_CCMP_256 | 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; 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 " wpa_printf(MSG_ERROR, "Cannot enable IEEE 802.11d without "
"setting the country_code"); "setting the country_code");
return -1; return -1;
} }
if (conf->ieee80211h && !conf->ieee80211d) { if (full_config && conf->ieee80211h && !conf->ieee80211d) {
wpa_printf(MSG_ERROR, "Cannot enable IEEE 802.11h without " wpa_printf(MSG_ERROR, "Cannot enable IEEE 802.11h without "
"IEEE 802.11d enabled"); "IEEE 802.11d enabled");
return -1; return -1;
} }
for (i = 0; i < conf->num_bss; i++) { 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; return -1;
} }

View file

@ -570,7 +570,7 @@ const char * hostapd_get_vlan_id_ifname(struct hostapd_vlan *vlan,
int vlan_id); int vlan_id);
struct hostapd_radius_attr * struct hostapd_radius_attr *
hostapd_config_get_radius_attr(struct hostapd_radius_attr *attr, u8 type); 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); void hostapd_set_security_params(struct hostapd_bss_config *bss);
#endif /* HOSTAPD_CONFIG_H */ #endif /* HOSTAPD_CONFIG_H */

View file

@ -1,6 +1,6 @@
/* /*
* hostapd / Initialization and configuration * hostapd / Initialization and configuration
* Copyright (c) 2002-2013, Jouni Malinen <j@w1.fi> * Copyright (c) 2002-2014, Jouni Malinen <j@w1.fi>
* *
* This software may be distributed under the terms of the BSD license. * This software may be distributed under the terms of the BSD license.
* See README for more details. * 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", wpa_printf(MSG_DEBUG, "Enable interface %s",
hapd_iface->conf->bss[0]->iface); 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 || if (hapd_iface->interfaces == NULL ||
hapd_iface->interfaces->driver_init == NULL || hapd_iface->interfaces->driver_init == NULL ||
hapd_iface->interfaces->driver_init(hapd_iface)) 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); hapd_iface->conf->bss[0]->iface);
for (j = 0; j < hapd_iface->num_bss; j++) for (j = 0; j < hapd_iface->num_bss; j++)
hostapd_set_security_params(hapd_iface->conf->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"); wpa_printf(MSG_ERROR, "Updated configuration is invalid");
return -1; return -1;
} }