13ff40c12SJohn Marino /*
23ff40c12SJohn Marino * hostapd / Configuration helper functions
33ff40c12SJohn Marino * Copyright (c) 2003-2014, Jouni Malinen <j@w1.fi>
43ff40c12SJohn Marino *
53ff40c12SJohn Marino * This software may be distributed under the terms of the BSD license.
63ff40c12SJohn Marino * See README for more details.
73ff40c12SJohn Marino */
83ff40c12SJohn Marino
93ff40c12SJohn Marino #include "utils/includes.h"
103ff40c12SJohn Marino
113ff40c12SJohn Marino #include "utils/common.h"
123ff40c12SJohn Marino #include "crypto/sha1.h"
13*a1157835SDaniel Fojt #include "crypto/tls.h"
143ff40c12SJohn Marino #include "radius/radius_client.h"
153ff40c12SJohn Marino #include "common/ieee802_11_defs.h"
16*a1157835SDaniel Fojt #include "common/ieee802_1x_defs.h"
173ff40c12SJohn Marino #include "common/eapol_common.h"
18*a1157835SDaniel Fojt #include "common/dhcp.h"
193ff40c12SJohn Marino #include "eap_common/eap_wsc_common.h"
203ff40c12SJohn Marino #include "eap_server/eap.h"
213ff40c12SJohn Marino #include "wpa_auth.h"
223ff40c12SJohn Marino #include "sta_info.h"
23*a1157835SDaniel Fojt #include "airtime_policy.h"
243ff40c12SJohn Marino #include "ap_config.h"
253ff40c12SJohn Marino
263ff40c12SJohn Marino
hostapd_config_free_vlan(struct hostapd_bss_config * bss)273ff40c12SJohn Marino static void hostapd_config_free_vlan(struct hostapd_bss_config *bss)
283ff40c12SJohn Marino {
293ff40c12SJohn Marino struct hostapd_vlan *vlan, *prev;
303ff40c12SJohn Marino
313ff40c12SJohn Marino vlan = bss->vlan;
323ff40c12SJohn Marino prev = NULL;
333ff40c12SJohn Marino while (vlan) {
343ff40c12SJohn Marino prev = vlan;
353ff40c12SJohn Marino vlan = vlan->next;
363ff40c12SJohn Marino os_free(prev);
373ff40c12SJohn Marino }
383ff40c12SJohn Marino
393ff40c12SJohn Marino bss->vlan = NULL;
403ff40c12SJohn Marino }
413ff40c12SJohn Marino
423ff40c12SJohn Marino
43*a1157835SDaniel Fojt #ifndef DEFAULT_WPA_DISABLE_EAPOL_KEY_RETRIES
44*a1157835SDaniel Fojt #define DEFAULT_WPA_DISABLE_EAPOL_KEY_RETRIES 0
45*a1157835SDaniel Fojt #endif /* DEFAULT_WPA_DISABLE_EAPOL_KEY_RETRIES */
46*a1157835SDaniel Fojt
hostapd_config_defaults_bss(struct hostapd_bss_config * bss)473ff40c12SJohn Marino void hostapd_config_defaults_bss(struct hostapd_bss_config *bss)
483ff40c12SJohn Marino {
49*a1157835SDaniel Fojt dl_list_init(&bss->anqp_elem);
50*a1157835SDaniel Fojt
513ff40c12SJohn Marino bss->logger_syslog_level = HOSTAPD_LEVEL_INFO;
523ff40c12SJohn Marino bss->logger_stdout_level = HOSTAPD_LEVEL_INFO;
533ff40c12SJohn Marino bss->logger_syslog = (unsigned int) -1;
543ff40c12SJohn Marino bss->logger_stdout = (unsigned int) -1;
553ff40c12SJohn Marino
563ff40c12SJohn Marino bss->auth_algs = WPA_AUTH_ALG_OPEN | WPA_AUTH_ALG_SHARED;
573ff40c12SJohn Marino
583ff40c12SJohn Marino bss->wep_rekeying_period = 300;
593ff40c12SJohn Marino /* use key0 in individual key and key1 in broadcast key */
603ff40c12SJohn Marino bss->broadcast_key_idx_min = 1;
613ff40c12SJohn Marino bss->broadcast_key_idx_max = 2;
623ff40c12SJohn Marino bss->eap_reauth_period = 3600;
633ff40c12SJohn Marino
643ff40c12SJohn Marino bss->wpa_group_rekey = 600;
653ff40c12SJohn Marino bss->wpa_gmk_rekey = 86400;
66*a1157835SDaniel Fojt bss->wpa_group_update_count = 4;
67*a1157835SDaniel Fojt bss->wpa_pairwise_update_count = 4;
68*a1157835SDaniel Fojt bss->wpa_disable_eapol_key_retries =
69*a1157835SDaniel Fojt DEFAULT_WPA_DISABLE_EAPOL_KEY_RETRIES;
703ff40c12SJohn Marino bss->wpa_key_mgmt = WPA_KEY_MGMT_PSK;
713ff40c12SJohn Marino bss->wpa_pairwise = WPA_CIPHER_TKIP;
723ff40c12SJohn Marino bss->wpa_group = WPA_CIPHER_TKIP;
733ff40c12SJohn Marino bss->rsn_pairwise = 0;
743ff40c12SJohn Marino
753ff40c12SJohn Marino bss->max_num_sta = MAX_STA_COUNT;
763ff40c12SJohn Marino
773ff40c12SJohn Marino bss->dtim_period = 2;
783ff40c12SJohn Marino
793ff40c12SJohn Marino bss->radius_server_auth_port = 1812;
80*a1157835SDaniel Fojt bss->eap_sim_db_timeout = 1;
81*a1157835SDaniel Fojt bss->eap_sim_id = 3;
823ff40c12SJohn Marino bss->ap_max_inactivity = AP_MAX_INACTIVITY;
833ff40c12SJohn Marino bss->eapol_version = EAPOL_VERSION;
843ff40c12SJohn Marino
853ff40c12SJohn Marino bss->max_listen_interval = 65535;
863ff40c12SJohn Marino
873ff40c12SJohn Marino bss->pwd_group = 19; /* ECC: GF(p=256) */
883ff40c12SJohn Marino
893ff40c12SJohn Marino #ifdef CONFIG_IEEE80211W
903ff40c12SJohn Marino bss->assoc_sa_query_max_timeout = 1000;
913ff40c12SJohn Marino bss->assoc_sa_query_retry_timeout = 201;
92*a1157835SDaniel Fojt bss->group_mgmt_cipher = WPA_CIPHER_AES_128_CMAC;
933ff40c12SJohn Marino #endif /* CONFIG_IEEE80211W */
943ff40c12SJohn Marino #ifdef EAP_SERVER_FAST
953ff40c12SJohn Marino /* both anonymous and authenticated provisioning */
963ff40c12SJohn Marino bss->eap_fast_prov = 3;
973ff40c12SJohn Marino bss->pac_key_lifetime = 7 * 24 * 60 * 60;
983ff40c12SJohn Marino bss->pac_key_refresh_time = 1 * 24 * 60 * 60;
993ff40c12SJohn Marino #endif /* EAP_SERVER_FAST */
1003ff40c12SJohn Marino
1013ff40c12SJohn Marino /* Set to -1 as defaults depends on HT in setup */
1023ff40c12SJohn Marino bss->wmm_enabled = -1;
1033ff40c12SJohn Marino
104*a1157835SDaniel Fojt #ifdef CONFIG_IEEE80211R_AP
1053ff40c12SJohn Marino bss->ft_over_ds = 1;
106*a1157835SDaniel Fojt bss->rkh_pos_timeout = 86400;
107*a1157835SDaniel Fojt bss->rkh_neg_timeout = 60;
108*a1157835SDaniel Fojt bss->rkh_pull_timeout = 1000;
109*a1157835SDaniel Fojt bss->rkh_pull_retries = 4;
110*a1157835SDaniel Fojt bss->r0_key_lifetime = 1209600;
111*a1157835SDaniel Fojt #endif /* CONFIG_IEEE80211R_AP */
1123ff40c12SJohn Marino
1133ff40c12SJohn Marino bss->radius_das_time_window = 300;
1143ff40c12SJohn Marino
1153ff40c12SJohn Marino bss->sae_anti_clogging_threshold = 5;
116*a1157835SDaniel Fojt bss->sae_sync = 5;
117*a1157835SDaniel Fojt
118*a1157835SDaniel Fojt bss->gas_frag_limit = 1400;
119*a1157835SDaniel Fojt
120*a1157835SDaniel Fojt #ifdef CONFIG_FILS
121*a1157835SDaniel Fojt dl_list_init(&bss->fils_realms);
122*a1157835SDaniel Fojt bss->fils_hlp_wait_time = 30;
123*a1157835SDaniel Fojt bss->dhcp_server_port = DHCP_SERVER_PORT;
124*a1157835SDaniel Fojt bss->dhcp_relay_port = DHCP_SERVER_PORT;
125*a1157835SDaniel Fojt #endif /* CONFIG_FILS */
126*a1157835SDaniel Fojt
127*a1157835SDaniel Fojt bss->broadcast_deauth = 1;
128*a1157835SDaniel Fojt
129*a1157835SDaniel Fojt #ifdef CONFIG_MBO
130*a1157835SDaniel Fojt bss->mbo_cell_data_conn_pref = -1;
131*a1157835SDaniel Fojt #endif /* CONFIG_MBO */
132*a1157835SDaniel Fojt
133*a1157835SDaniel Fojt /* Disable TLS v1.3 by default for now to avoid interoperability issue.
134*a1157835SDaniel Fojt * This can be enabled by default once the implementation has been fully
135*a1157835SDaniel Fojt * completed and tested with other implementations. */
136*a1157835SDaniel Fojt bss->tls_flags = TLS_CONN_DISABLE_TLSv1_3;
137*a1157835SDaniel Fojt
138*a1157835SDaniel Fojt bss->send_probe_response = 1;
139*a1157835SDaniel Fojt
140*a1157835SDaniel Fojt #ifdef CONFIG_HS20
141*a1157835SDaniel Fojt bss->hs20_release = (HS20_VERSION >> 4) + 1;
142*a1157835SDaniel Fojt #endif /* CONFIG_HS20 */
143*a1157835SDaniel Fojt
144*a1157835SDaniel Fojt #ifdef CONFIG_MACSEC
145*a1157835SDaniel Fojt bss->mka_priority = DEFAULT_PRIO_NOT_KEY_SERVER;
146*a1157835SDaniel Fojt bss->macsec_port = 1;
147*a1157835SDaniel Fojt #endif /* CONFIG_MACSEC */
148*a1157835SDaniel Fojt
149*a1157835SDaniel Fojt /* Default to strict CRL checking. */
150*a1157835SDaniel Fojt bss->check_crl_strict = 1;
1513ff40c12SJohn Marino }
1523ff40c12SJohn Marino
1533ff40c12SJohn Marino
hostapd_config_defaults(void)1543ff40c12SJohn Marino struct hostapd_config * hostapd_config_defaults(void)
1553ff40c12SJohn Marino {
1563ff40c12SJohn Marino #define ecw2cw(ecw) ((1 << (ecw)) - 1)
1573ff40c12SJohn Marino
1583ff40c12SJohn Marino struct hostapd_config *conf;
1593ff40c12SJohn Marino struct hostapd_bss_config *bss;
1603ff40c12SJohn Marino const int aCWmin = 4, aCWmax = 10;
1613ff40c12SJohn Marino const struct hostapd_wmm_ac_params ac_bk =
1623ff40c12SJohn Marino { aCWmin, aCWmax, 7, 0, 0 }; /* background traffic */
1633ff40c12SJohn Marino const struct hostapd_wmm_ac_params ac_be =
1643ff40c12SJohn Marino { aCWmin, aCWmax, 3, 0, 0 }; /* best effort traffic */
1653ff40c12SJohn Marino const struct hostapd_wmm_ac_params ac_vi = /* video traffic */
166*a1157835SDaniel Fojt { aCWmin - 1, aCWmin, 2, 3008 / 32, 0 };
1673ff40c12SJohn Marino const struct hostapd_wmm_ac_params ac_vo = /* voice traffic */
168*a1157835SDaniel Fojt { aCWmin - 2, aCWmin - 1, 2, 1504 / 32, 0 };
1693ff40c12SJohn Marino const struct hostapd_tx_queue_params txq_bk =
1703ff40c12SJohn Marino { 7, ecw2cw(aCWmin), ecw2cw(aCWmax), 0 };
1713ff40c12SJohn Marino const struct hostapd_tx_queue_params txq_be =
1723ff40c12SJohn Marino { 3, ecw2cw(aCWmin), 4 * (ecw2cw(aCWmin) + 1) - 1, 0};
1733ff40c12SJohn Marino const struct hostapd_tx_queue_params txq_vi =
1743ff40c12SJohn Marino { 1, (ecw2cw(aCWmin) + 1) / 2 - 1, ecw2cw(aCWmin), 30};
1753ff40c12SJohn Marino const struct hostapd_tx_queue_params txq_vo =
1763ff40c12SJohn Marino { 1, (ecw2cw(aCWmin) + 1) / 4 - 1,
1773ff40c12SJohn Marino (ecw2cw(aCWmin) + 1) / 2 - 1, 15};
1783ff40c12SJohn Marino
1793ff40c12SJohn Marino #undef ecw2cw
1803ff40c12SJohn Marino
1813ff40c12SJohn Marino conf = os_zalloc(sizeof(*conf));
1823ff40c12SJohn Marino bss = os_zalloc(sizeof(*bss));
1833ff40c12SJohn Marino if (conf == NULL || bss == NULL) {
1843ff40c12SJohn Marino wpa_printf(MSG_ERROR, "Failed to allocate memory for "
1853ff40c12SJohn Marino "configuration data.");
1863ff40c12SJohn Marino os_free(conf);
1873ff40c12SJohn Marino os_free(bss);
1883ff40c12SJohn Marino return NULL;
1893ff40c12SJohn Marino }
1903ff40c12SJohn Marino conf->bss = os_calloc(1, sizeof(struct hostapd_bss_config *));
1913ff40c12SJohn Marino if (conf->bss == NULL) {
1923ff40c12SJohn Marino os_free(conf);
1933ff40c12SJohn Marino os_free(bss);
1943ff40c12SJohn Marino return NULL;
1953ff40c12SJohn Marino }
1963ff40c12SJohn Marino conf->bss[0] = bss;
1973ff40c12SJohn Marino
1983ff40c12SJohn Marino bss->radius = os_zalloc(sizeof(*bss->radius));
1993ff40c12SJohn Marino if (bss->radius == NULL) {
2003ff40c12SJohn Marino os_free(conf->bss);
2013ff40c12SJohn Marino os_free(conf);
2023ff40c12SJohn Marino os_free(bss);
2033ff40c12SJohn Marino return NULL;
2043ff40c12SJohn Marino }
2053ff40c12SJohn Marino
2063ff40c12SJohn Marino hostapd_config_defaults_bss(bss);
2073ff40c12SJohn Marino
2083ff40c12SJohn Marino conf->num_bss = 1;
2093ff40c12SJohn Marino
2103ff40c12SJohn Marino conf->beacon_int = 100;
211*a1157835SDaniel Fojt conf->rts_threshold = -2; /* use driver default: 2347 */
212*a1157835SDaniel Fojt conf->fragm_threshold = -2; /* user driver default: 2346 */
213*a1157835SDaniel Fojt /* Set to invalid value means do not add Power Constraint IE */
214*a1157835SDaniel Fojt conf->local_pwr_constraint = -1;
2153ff40c12SJohn Marino
2163ff40c12SJohn Marino conf->wmm_ac_params[0] = ac_be;
2173ff40c12SJohn Marino conf->wmm_ac_params[1] = ac_bk;
2183ff40c12SJohn Marino conf->wmm_ac_params[2] = ac_vi;
2193ff40c12SJohn Marino conf->wmm_ac_params[3] = ac_vo;
2203ff40c12SJohn Marino
2213ff40c12SJohn Marino conf->tx_queue[0] = txq_vo;
2223ff40c12SJohn Marino conf->tx_queue[1] = txq_vi;
2233ff40c12SJohn Marino conf->tx_queue[2] = txq_be;
2243ff40c12SJohn Marino conf->tx_queue[3] = txq_bk;
2253ff40c12SJohn Marino
2263ff40c12SJohn Marino conf->ht_capab = HT_CAP_INFO_SMPS_DISABLED;
2273ff40c12SJohn Marino
2283ff40c12SJohn Marino conf->ap_table_max_size = 255;
2293ff40c12SJohn Marino conf->ap_table_expiration_time = 60;
230*a1157835SDaniel Fojt conf->track_sta_max_age = 180;
2313ff40c12SJohn Marino
2323ff40c12SJohn Marino #ifdef CONFIG_TESTING_OPTIONS
233*a1157835SDaniel Fojt conf->ignore_probe_probability = 0.0;
234*a1157835SDaniel Fojt conf->ignore_auth_probability = 0.0;
235*a1157835SDaniel Fojt conf->ignore_assoc_probability = 0.0;
236*a1157835SDaniel Fojt conf->ignore_reassoc_probability = 0.0;
237*a1157835SDaniel Fojt conf->corrupt_gtk_rekey_mic_probability = 0.0;
238*a1157835SDaniel Fojt conf->ecsa_ie_only = 0;
2393ff40c12SJohn Marino #endif /* CONFIG_TESTING_OPTIONS */
2403ff40c12SJohn Marino
241*a1157835SDaniel Fojt conf->acs = 0;
242*a1157835SDaniel Fojt conf->acs_ch_list.num = 0;
2433ff40c12SJohn Marino #ifdef CONFIG_ACS
2443ff40c12SJohn Marino conf->acs_num_scans = 5;
2453ff40c12SJohn Marino #endif /* CONFIG_ACS */
2463ff40c12SJohn Marino
247*a1157835SDaniel Fojt #ifdef CONFIG_IEEE80211AX
248*a1157835SDaniel Fojt conf->he_op.he_rts_threshold = HE_OPERATION_RTS_THRESHOLD_MASK >>
249*a1157835SDaniel Fojt HE_OPERATION_RTS_THRESHOLD_OFFSET;
250*a1157835SDaniel Fojt /* Set default basic MCS/NSS set to single stream MCS 0-7 */
251*a1157835SDaniel Fojt conf->he_op.he_basic_mcs_nss_set = 0xfffc;
252*a1157835SDaniel Fojt #endif /* CONFIG_IEEE80211AX */
253*a1157835SDaniel Fojt
254*a1157835SDaniel Fojt /* The third octet of the country string uses an ASCII space character
255*a1157835SDaniel Fojt * by default to indicate that the regulations encompass all
256*a1157835SDaniel Fojt * environments for the current frequency band in the country. */
257*a1157835SDaniel Fojt conf->country[2] = ' ';
258*a1157835SDaniel Fojt
259*a1157835SDaniel Fojt conf->rssi_reject_assoc_rssi = 0;
260*a1157835SDaniel Fojt conf->rssi_reject_assoc_timeout = 30;
261*a1157835SDaniel Fojt
262*a1157835SDaniel Fojt #ifdef CONFIG_AIRTIME_POLICY
263*a1157835SDaniel Fojt conf->airtime_update_interval = AIRTIME_DEFAULT_UPDATE_INTERVAL;
264*a1157835SDaniel Fojt #endif /* CONFIG_AIRTIME_POLICY */
265*a1157835SDaniel Fojt
2663ff40c12SJohn Marino return conf;
2673ff40c12SJohn Marino }
2683ff40c12SJohn Marino
2693ff40c12SJohn Marino
hostapd_mac_comp(const void * a,const void * b)2703ff40c12SJohn Marino int hostapd_mac_comp(const void *a, const void *b)
2713ff40c12SJohn Marino {
2723ff40c12SJohn Marino return os_memcmp(a, b, sizeof(macaddr));
2733ff40c12SJohn Marino }
2743ff40c12SJohn Marino
2753ff40c12SJohn Marino
hostapd_config_read_wpa_psk(const char * fname,struct hostapd_ssid * ssid)2763ff40c12SJohn Marino static int hostapd_config_read_wpa_psk(const char *fname,
2773ff40c12SJohn Marino struct hostapd_ssid *ssid)
2783ff40c12SJohn Marino {
2793ff40c12SJohn Marino FILE *f;
2803ff40c12SJohn Marino char buf[128], *pos;
281*a1157835SDaniel Fojt const char *keyid;
282*a1157835SDaniel Fojt char *context;
283*a1157835SDaniel Fojt char *context2;
284*a1157835SDaniel Fojt char *token;
285*a1157835SDaniel Fojt char *name;
286*a1157835SDaniel Fojt char *value;
2873ff40c12SJohn Marino int line = 0, ret = 0, len, ok;
2883ff40c12SJohn Marino u8 addr[ETH_ALEN];
2893ff40c12SJohn Marino struct hostapd_wpa_psk *psk;
2903ff40c12SJohn Marino
2913ff40c12SJohn Marino if (!fname)
2923ff40c12SJohn Marino return 0;
2933ff40c12SJohn Marino
2943ff40c12SJohn Marino f = fopen(fname, "r");
2953ff40c12SJohn Marino if (!f) {
2963ff40c12SJohn Marino wpa_printf(MSG_ERROR, "WPA PSK file '%s' not found.", fname);
2973ff40c12SJohn Marino return -1;
2983ff40c12SJohn Marino }
2993ff40c12SJohn Marino
3003ff40c12SJohn Marino while (fgets(buf, sizeof(buf), f)) {
301*a1157835SDaniel Fojt int vlan_id = 0;
302*a1157835SDaniel Fojt
3033ff40c12SJohn Marino line++;
3043ff40c12SJohn Marino
3053ff40c12SJohn Marino if (buf[0] == '#')
3063ff40c12SJohn Marino continue;
3073ff40c12SJohn Marino pos = buf;
3083ff40c12SJohn Marino while (*pos != '\0') {
3093ff40c12SJohn Marino if (*pos == '\n') {
3103ff40c12SJohn Marino *pos = '\0';
3113ff40c12SJohn Marino break;
3123ff40c12SJohn Marino }
3133ff40c12SJohn Marino pos++;
3143ff40c12SJohn Marino }
3153ff40c12SJohn Marino if (buf[0] == '\0')
3163ff40c12SJohn Marino continue;
3173ff40c12SJohn Marino
318*a1157835SDaniel Fojt context = NULL;
319*a1157835SDaniel Fojt keyid = NULL;
320*a1157835SDaniel Fojt while ((token = str_token(buf, " ", &context))) {
321*a1157835SDaniel Fojt if (!os_strchr(token, '='))
322*a1157835SDaniel Fojt break;
323*a1157835SDaniel Fojt context2 = NULL;
324*a1157835SDaniel Fojt name = str_token(token, "=", &context2);
325*a1157835SDaniel Fojt if (!name)
326*a1157835SDaniel Fojt break;
327*a1157835SDaniel Fojt value = str_token(token, "", &context2);
328*a1157835SDaniel Fojt if (!value)
329*a1157835SDaniel Fojt value = "";
330*a1157835SDaniel Fojt if (!os_strcmp(name, "keyid")) {
331*a1157835SDaniel Fojt keyid = value;
332*a1157835SDaniel Fojt } else if (!os_strcmp(name, "vlanid")) {
333*a1157835SDaniel Fojt vlan_id = atoi(value);
334*a1157835SDaniel Fojt } else {
335*a1157835SDaniel Fojt wpa_printf(MSG_ERROR,
336*a1157835SDaniel Fojt "Unrecognized '%s=%s' on line %d in '%s'",
337*a1157835SDaniel Fojt name, value, line, fname);
338*a1157835SDaniel Fojt ret = -1;
339*a1157835SDaniel Fojt break;
340*a1157835SDaniel Fojt }
341*a1157835SDaniel Fojt }
342*a1157835SDaniel Fojt
343*a1157835SDaniel Fojt if (ret == -1)
344*a1157835SDaniel Fojt break;
345*a1157835SDaniel Fojt
346*a1157835SDaniel Fojt if (!token)
347*a1157835SDaniel Fojt token = "";
348*a1157835SDaniel Fojt if (hwaddr_aton(token, addr)) {
3493ff40c12SJohn Marino wpa_printf(MSG_ERROR, "Invalid MAC address '%s' on "
350*a1157835SDaniel Fojt "line %d in '%s'", token, line, fname);
3513ff40c12SJohn Marino ret = -1;
3523ff40c12SJohn Marino break;
3533ff40c12SJohn Marino }
3543ff40c12SJohn Marino
3553ff40c12SJohn Marino psk = os_zalloc(sizeof(*psk));
3563ff40c12SJohn Marino if (psk == NULL) {
3573ff40c12SJohn Marino wpa_printf(MSG_ERROR, "WPA PSK allocation failed");
3583ff40c12SJohn Marino ret = -1;
3593ff40c12SJohn Marino break;
3603ff40c12SJohn Marino }
361*a1157835SDaniel Fojt psk->vlan_id = vlan_id;
3623ff40c12SJohn Marino if (is_zero_ether_addr(addr))
3633ff40c12SJohn Marino psk->group = 1;
3643ff40c12SJohn Marino else
3653ff40c12SJohn Marino os_memcpy(psk->addr, addr, ETH_ALEN);
3663ff40c12SJohn Marino
367*a1157835SDaniel Fojt pos = str_token(buf, "", &context);
368*a1157835SDaniel Fojt if (!pos) {
3693ff40c12SJohn Marino wpa_printf(MSG_ERROR, "No PSK on line %d in '%s'",
3703ff40c12SJohn Marino line, fname);
3713ff40c12SJohn Marino os_free(psk);
3723ff40c12SJohn Marino ret = -1;
3733ff40c12SJohn Marino break;
3743ff40c12SJohn Marino }
3753ff40c12SJohn Marino
3763ff40c12SJohn Marino ok = 0;
3773ff40c12SJohn Marino len = os_strlen(pos);
3783ff40c12SJohn Marino if (len == 64 && hexstr2bin(pos, psk->psk, PMK_LEN) == 0)
3793ff40c12SJohn Marino ok = 1;
3803ff40c12SJohn Marino else if (len >= 8 && len < 64) {
3813ff40c12SJohn Marino pbkdf2_sha1(pos, ssid->ssid, ssid->ssid_len,
3823ff40c12SJohn Marino 4096, psk->psk, PMK_LEN);
3833ff40c12SJohn Marino ok = 1;
3843ff40c12SJohn Marino }
3853ff40c12SJohn Marino if (!ok) {
3863ff40c12SJohn Marino wpa_printf(MSG_ERROR, "Invalid PSK '%s' on line %d in "
3873ff40c12SJohn Marino "'%s'", pos, line, fname);
3883ff40c12SJohn Marino os_free(psk);
3893ff40c12SJohn Marino ret = -1;
3903ff40c12SJohn Marino break;
3913ff40c12SJohn Marino }
3923ff40c12SJohn Marino
393*a1157835SDaniel Fojt if (keyid) {
394*a1157835SDaniel Fojt len = os_strlcpy(psk->keyid, keyid, sizeof(psk->keyid));
395*a1157835SDaniel Fojt if ((size_t) len >= sizeof(psk->keyid)) {
396*a1157835SDaniel Fojt wpa_printf(MSG_ERROR,
397*a1157835SDaniel Fojt "PSK keyid too long on line %d in '%s'",
398*a1157835SDaniel Fojt line, fname);
399*a1157835SDaniel Fojt os_free(psk);
400*a1157835SDaniel Fojt ret = -1;
401*a1157835SDaniel Fojt break;
402*a1157835SDaniel Fojt }
403*a1157835SDaniel Fojt }
404*a1157835SDaniel Fojt
4053ff40c12SJohn Marino psk->next = ssid->wpa_psk;
4063ff40c12SJohn Marino ssid->wpa_psk = psk;
4073ff40c12SJohn Marino }
4083ff40c12SJohn Marino
4093ff40c12SJohn Marino fclose(f);
4103ff40c12SJohn Marino
4113ff40c12SJohn Marino return ret;
4123ff40c12SJohn Marino }
4133ff40c12SJohn Marino
4143ff40c12SJohn Marino
hostapd_derive_psk(struct hostapd_ssid * ssid)4153ff40c12SJohn Marino static int hostapd_derive_psk(struct hostapd_ssid *ssid)
4163ff40c12SJohn Marino {
4173ff40c12SJohn Marino ssid->wpa_psk = os_zalloc(sizeof(struct hostapd_wpa_psk));
4183ff40c12SJohn Marino if (ssid->wpa_psk == NULL) {
4193ff40c12SJohn Marino wpa_printf(MSG_ERROR, "Unable to alloc space for PSK");
4203ff40c12SJohn Marino return -1;
4213ff40c12SJohn Marino }
4223ff40c12SJohn Marino wpa_hexdump_ascii(MSG_DEBUG, "SSID",
4233ff40c12SJohn Marino (u8 *) ssid->ssid, ssid->ssid_len);
4243ff40c12SJohn Marino wpa_hexdump_ascii_key(MSG_DEBUG, "PSK (ASCII passphrase)",
4253ff40c12SJohn Marino (u8 *) ssid->wpa_passphrase,
4263ff40c12SJohn Marino os_strlen(ssid->wpa_passphrase));
4273ff40c12SJohn Marino pbkdf2_sha1(ssid->wpa_passphrase,
4283ff40c12SJohn Marino ssid->ssid, ssid->ssid_len,
4293ff40c12SJohn Marino 4096, ssid->wpa_psk->psk, PMK_LEN);
4303ff40c12SJohn Marino wpa_hexdump_key(MSG_DEBUG, "PSK (from passphrase)",
4313ff40c12SJohn Marino ssid->wpa_psk->psk, PMK_LEN);
4323ff40c12SJohn Marino return 0;
4333ff40c12SJohn Marino }
4343ff40c12SJohn Marino
4353ff40c12SJohn Marino
hostapd_setup_wpa_psk(struct hostapd_bss_config * conf)4363ff40c12SJohn Marino int hostapd_setup_wpa_psk(struct hostapd_bss_config *conf)
4373ff40c12SJohn Marino {
4383ff40c12SJohn Marino struct hostapd_ssid *ssid = &conf->ssid;
4393ff40c12SJohn Marino
4403ff40c12SJohn Marino if (ssid->wpa_passphrase != NULL) {
4413ff40c12SJohn Marino if (ssid->wpa_psk != NULL) {
4423ff40c12SJohn Marino wpa_printf(MSG_DEBUG, "Using pre-configured WPA PSK "
4433ff40c12SJohn Marino "instead of passphrase");
4443ff40c12SJohn Marino } else {
4453ff40c12SJohn Marino wpa_printf(MSG_DEBUG, "Deriving WPA PSK based on "
4463ff40c12SJohn Marino "passphrase");
4473ff40c12SJohn Marino if (hostapd_derive_psk(ssid) < 0)
4483ff40c12SJohn Marino return -1;
4493ff40c12SJohn Marino }
4503ff40c12SJohn Marino ssid->wpa_psk->group = 1;
4513ff40c12SJohn Marino }
4523ff40c12SJohn Marino
453*a1157835SDaniel Fojt return hostapd_config_read_wpa_psk(ssid->wpa_psk_file, &conf->ssid);
4543ff40c12SJohn Marino }
4553ff40c12SJohn Marino
4563ff40c12SJohn Marino
hostapd_config_free_radius(struct hostapd_radius_server * servers,int num_servers)4573ff40c12SJohn Marino static void hostapd_config_free_radius(struct hostapd_radius_server *servers,
4583ff40c12SJohn Marino int num_servers)
4593ff40c12SJohn Marino {
4603ff40c12SJohn Marino int i;
4613ff40c12SJohn Marino
4623ff40c12SJohn Marino for (i = 0; i < num_servers; i++) {
4633ff40c12SJohn Marino os_free(servers[i].shared_secret);
4643ff40c12SJohn Marino }
4653ff40c12SJohn Marino os_free(servers);
4663ff40c12SJohn Marino }
4673ff40c12SJohn Marino
4683ff40c12SJohn Marino
4693ff40c12SJohn Marino struct hostapd_radius_attr *
hostapd_config_get_radius_attr(struct hostapd_radius_attr * attr,u8 type)4703ff40c12SJohn Marino hostapd_config_get_radius_attr(struct hostapd_radius_attr *attr, u8 type)
4713ff40c12SJohn Marino {
4723ff40c12SJohn Marino for (; attr; attr = attr->next) {
4733ff40c12SJohn Marino if (attr->type == type)
4743ff40c12SJohn Marino return attr;
4753ff40c12SJohn Marino }
4763ff40c12SJohn Marino return NULL;
4773ff40c12SJohn Marino }
4783ff40c12SJohn Marino
4793ff40c12SJohn Marino
hostapd_parse_radius_attr(const char * value)480*a1157835SDaniel Fojt struct hostapd_radius_attr * hostapd_parse_radius_attr(const char *value)
481*a1157835SDaniel Fojt {
482*a1157835SDaniel Fojt const char *pos;
483*a1157835SDaniel Fojt char syntax;
484*a1157835SDaniel Fojt struct hostapd_radius_attr *attr;
485*a1157835SDaniel Fojt size_t len;
486*a1157835SDaniel Fojt
487*a1157835SDaniel Fojt attr = os_zalloc(sizeof(*attr));
488*a1157835SDaniel Fojt if (!attr)
489*a1157835SDaniel Fojt return NULL;
490*a1157835SDaniel Fojt
491*a1157835SDaniel Fojt attr->type = atoi(value);
492*a1157835SDaniel Fojt
493*a1157835SDaniel Fojt pos = os_strchr(value, ':');
494*a1157835SDaniel Fojt if (!pos) {
495*a1157835SDaniel Fojt attr->val = wpabuf_alloc(1);
496*a1157835SDaniel Fojt if (!attr->val) {
497*a1157835SDaniel Fojt os_free(attr);
498*a1157835SDaniel Fojt return NULL;
499*a1157835SDaniel Fojt }
500*a1157835SDaniel Fojt wpabuf_put_u8(attr->val, 0);
501*a1157835SDaniel Fojt return attr;
502*a1157835SDaniel Fojt }
503*a1157835SDaniel Fojt
504*a1157835SDaniel Fojt pos++;
505*a1157835SDaniel Fojt if (pos[0] == '\0' || pos[1] != ':') {
506*a1157835SDaniel Fojt os_free(attr);
507*a1157835SDaniel Fojt return NULL;
508*a1157835SDaniel Fojt }
509*a1157835SDaniel Fojt syntax = *pos++;
510*a1157835SDaniel Fojt pos++;
511*a1157835SDaniel Fojt
512*a1157835SDaniel Fojt switch (syntax) {
513*a1157835SDaniel Fojt case 's':
514*a1157835SDaniel Fojt attr->val = wpabuf_alloc_copy(pos, os_strlen(pos));
515*a1157835SDaniel Fojt break;
516*a1157835SDaniel Fojt case 'x':
517*a1157835SDaniel Fojt len = os_strlen(pos);
518*a1157835SDaniel Fojt if (len & 1)
519*a1157835SDaniel Fojt break;
520*a1157835SDaniel Fojt len /= 2;
521*a1157835SDaniel Fojt attr->val = wpabuf_alloc(len);
522*a1157835SDaniel Fojt if (!attr->val)
523*a1157835SDaniel Fojt break;
524*a1157835SDaniel Fojt if (hexstr2bin(pos, wpabuf_put(attr->val, len), len) < 0) {
525*a1157835SDaniel Fojt wpabuf_free(attr->val);
526*a1157835SDaniel Fojt os_free(attr);
527*a1157835SDaniel Fojt return NULL;
528*a1157835SDaniel Fojt }
529*a1157835SDaniel Fojt break;
530*a1157835SDaniel Fojt case 'd':
531*a1157835SDaniel Fojt attr->val = wpabuf_alloc(4);
532*a1157835SDaniel Fojt if (attr->val)
533*a1157835SDaniel Fojt wpabuf_put_be32(attr->val, atoi(pos));
534*a1157835SDaniel Fojt break;
535*a1157835SDaniel Fojt default:
536*a1157835SDaniel Fojt os_free(attr);
537*a1157835SDaniel Fojt return NULL;
538*a1157835SDaniel Fojt }
539*a1157835SDaniel Fojt
540*a1157835SDaniel Fojt if (!attr->val) {
541*a1157835SDaniel Fojt os_free(attr);
542*a1157835SDaniel Fojt return NULL;
543*a1157835SDaniel Fojt }
544*a1157835SDaniel Fojt
545*a1157835SDaniel Fojt return attr;
546*a1157835SDaniel Fojt }
547*a1157835SDaniel Fojt
548*a1157835SDaniel Fojt
hostapd_config_free_radius_attr(struct hostapd_radius_attr * attr)549*a1157835SDaniel Fojt void hostapd_config_free_radius_attr(struct hostapd_radius_attr *attr)
5503ff40c12SJohn Marino {
5513ff40c12SJohn Marino struct hostapd_radius_attr *prev;
5523ff40c12SJohn Marino
5533ff40c12SJohn Marino while (attr) {
5543ff40c12SJohn Marino prev = attr;
5553ff40c12SJohn Marino attr = attr->next;
5563ff40c12SJohn Marino wpabuf_free(prev->val);
5573ff40c12SJohn Marino os_free(prev);
5583ff40c12SJohn Marino }
5593ff40c12SJohn Marino }
5603ff40c12SJohn Marino
5613ff40c12SJohn Marino
hostapd_config_free_eap_user(struct hostapd_eap_user * user)562*a1157835SDaniel Fojt void hostapd_config_free_eap_user(struct hostapd_eap_user *user)
5633ff40c12SJohn Marino {
564*a1157835SDaniel Fojt hostapd_config_free_radius_attr(user->accept_attr);
5653ff40c12SJohn Marino os_free(user->identity);
566*a1157835SDaniel Fojt bin_clear_free(user->password, user->password_len);
567*a1157835SDaniel Fojt bin_clear_free(user->salt, user->salt_len);
5683ff40c12SJohn Marino os_free(user);
5693ff40c12SJohn Marino }
5703ff40c12SJohn Marino
5713ff40c12SJohn Marino
hostapd_config_free_eap_users(struct hostapd_eap_user * user)572*a1157835SDaniel Fojt void hostapd_config_free_eap_users(struct hostapd_eap_user *user)
573*a1157835SDaniel Fojt {
574*a1157835SDaniel Fojt struct hostapd_eap_user *prev_user;
575*a1157835SDaniel Fojt
576*a1157835SDaniel Fojt while (user) {
577*a1157835SDaniel Fojt prev_user = user;
578*a1157835SDaniel Fojt user = user->next;
579*a1157835SDaniel Fojt hostapd_config_free_eap_user(prev_user);
580*a1157835SDaniel Fojt }
581*a1157835SDaniel Fojt }
582*a1157835SDaniel Fojt
583*a1157835SDaniel Fojt
hostapd_config_free_wep(struct hostapd_wep_keys * keys)5843ff40c12SJohn Marino static void hostapd_config_free_wep(struct hostapd_wep_keys *keys)
5853ff40c12SJohn Marino {
5863ff40c12SJohn Marino int i;
5873ff40c12SJohn Marino for (i = 0; i < NUM_WEP_KEYS; i++) {
588*a1157835SDaniel Fojt bin_clear_free(keys->key[i], keys->len[i]);
5893ff40c12SJohn Marino keys->key[i] = NULL;
5903ff40c12SJohn Marino }
5913ff40c12SJohn Marino }
5923ff40c12SJohn Marino
5933ff40c12SJohn Marino
hostapd_config_clear_wpa_psk(struct hostapd_wpa_psk ** l)594*a1157835SDaniel Fojt void hostapd_config_clear_wpa_psk(struct hostapd_wpa_psk **l)
595*a1157835SDaniel Fojt {
596*a1157835SDaniel Fojt struct hostapd_wpa_psk *psk, *tmp;
597*a1157835SDaniel Fojt
598*a1157835SDaniel Fojt for (psk = *l; psk;) {
599*a1157835SDaniel Fojt tmp = psk;
600*a1157835SDaniel Fojt psk = psk->next;
601*a1157835SDaniel Fojt bin_clear_free(tmp, sizeof(*tmp));
602*a1157835SDaniel Fojt }
603*a1157835SDaniel Fojt *l = NULL;
604*a1157835SDaniel Fojt }
605*a1157835SDaniel Fojt
606*a1157835SDaniel Fojt
hostapd_config_free_anqp_elem(struct hostapd_bss_config * conf)607*a1157835SDaniel Fojt static void hostapd_config_free_anqp_elem(struct hostapd_bss_config *conf)
608*a1157835SDaniel Fojt {
609*a1157835SDaniel Fojt struct anqp_element *elem;
610*a1157835SDaniel Fojt
611*a1157835SDaniel Fojt while ((elem = dl_list_first(&conf->anqp_elem, struct anqp_element,
612*a1157835SDaniel Fojt list))) {
613*a1157835SDaniel Fojt dl_list_del(&elem->list);
614*a1157835SDaniel Fojt wpabuf_free(elem->payload);
615*a1157835SDaniel Fojt os_free(elem);
616*a1157835SDaniel Fojt }
617*a1157835SDaniel Fojt }
618*a1157835SDaniel Fojt
619*a1157835SDaniel Fojt
hostapd_config_free_fils_realms(struct hostapd_bss_config * conf)620*a1157835SDaniel Fojt static void hostapd_config_free_fils_realms(struct hostapd_bss_config *conf)
621*a1157835SDaniel Fojt {
622*a1157835SDaniel Fojt #ifdef CONFIG_FILS
623*a1157835SDaniel Fojt struct fils_realm *realm;
624*a1157835SDaniel Fojt
625*a1157835SDaniel Fojt while ((realm = dl_list_first(&conf->fils_realms, struct fils_realm,
626*a1157835SDaniel Fojt list))) {
627*a1157835SDaniel Fojt dl_list_del(&realm->list);
628*a1157835SDaniel Fojt os_free(realm);
629*a1157835SDaniel Fojt }
630*a1157835SDaniel Fojt #endif /* CONFIG_FILS */
631*a1157835SDaniel Fojt }
632*a1157835SDaniel Fojt
633*a1157835SDaniel Fojt
hostapd_config_free_sae_passwords(struct hostapd_bss_config * conf)634*a1157835SDaniel Fojt static void hostapd_config_free_sae_passwords(struct hostapd_bss_config *conf)
635*a1157835SDaniel Fojt {
636*a1157835SDaniel Fojt struct sae_password_entry *pw, *tmp;
637*a1157835SDaniel Fojt
638*a1157835SDaniel Fojt pw = conf->sae_passwords;
639*a1157835SDaniel Fojt conf->sae_passwords = NULL;
640*a1157835SDaniel Fojt while (pw) {
641*a1157835SDaniel Fojt tmp = pw;
642*a1157835SDaniel Fojt pw = pw->next;
643*a1157835SDaniel Fojt str_clear_free(tmp->password);
644*a1157835SDaniel Fojt os_free(tmp->identifier);
645*a1157835SDaniel Fojt os_free(tmp);
646*a1157835SDaniel Fojt }
647*a1157835SDaniel Fojt }
648*a1157835SDaniel Fojt
649*a1157835SDaniel Fojt
650*a1157835SDaniel Fojt #ifdef CONFIG_DPP2
hostapd_dpp_controller_conf_free(struct dpp_controller_conf * conf)651*a1157835SDaniel Fojt static void hostapd_dpp_controller_conf_free(struct dpp_controller_conf *conf)
652*a1157835SDaniel Fojt {
653*a1157835SDaniel Fojt struct dpp_controller_conf *prev;
654*a1157835SDaniel Fojt
655*a1157835SDaniel Fojt while (conf) {
656*a1157835SDaniel Fojt prev = conf;
657*a1157835SDaniel Fojt conf = conf->next;
658*a1157835SDaniel Fojt os_free(prev);
659*a1157835SDaniel Fojt }
660*a1157835SDaniel Fojt }
661*a1157835SDaniel Fojt #endif /* CONFIG_DPP2 */
662*a1157835SDaniel Fojt
663*a1157835SDaniel Fojt
hostapd_config_free_bss(struct hostapd_bss_config * conf)6643ff40c12SJohn Marino void hostapd_config_free_bss(struct hostapd_bss_config *conf)
6653ff40c12SJohn Marino {
666*a1157835SDaniel Fojt #if defined(CONFIG_WPS) || defined(CONFIG_HS20)
667*a1157835SDaniel Fojt size_t i;
668*a1157835SDaniel Fojt #endif
6693ff40c12SJohn Marino
6703ff40c12SJohn Marino if (conf == NULL)
6713ff40c12SJohn Marino return;
6723ff40c12SJohn Marino
673*a1157835SDaniel Fojt hostapd_config_clear_wpa_psk(&conf->ssid.wpa_psk);
6743ff40c12SJohn Marino
675*a1157835SDaniel Fojt str_clear_free(conf->ssid.wpa_passphrase);
6763ff40c12SJohn Marino os_free(conf->ssid.wpa_psk_file);
6773ff40c12SJohn Marino hostapd_config_free_wep(&conf->ssid.wep);
6783ff40c12SJohn Marino #ifdef CONFIG_FULL_DYNAMIC_VLAN
6793ff40c12SJohn Marino os_free(conf->ssid.vlan_tagged_interface);
6803ff40c12SJohn Marino #endif /* CONFIG_FULL_DYNAMIC_VLAN */
6813ff40c12SJohn Marino
682*a1157835SDaniel Fojt hostapd_config_free_eap_users(conf->eap_user);
6833ff40c12SJohn Marino os_free(conf->eap_user_sqlite);
6843ff40c12SJohn Marino
6853ff40c12SJohn Marino os_free(conf->eap_req_id_text);
686*a1157835SDaniel Fojt os_free(conf->erp_domain);
6873ff40c12SJohn Marino os_free(conf->accept_mac);
6883ff40c12SJohn Marino os_free(conf->deny_mac);
6893ff40c12SJohn Marino os_free(conf->nas_identifier);
6903ff40c12SJohn Marino if (conf->radius) {
6913ff40c12SJohn Marino hostapd_config_free_radius(conf->radius->auth_servers,
6923ff40c12SJohn Marino conf->radius->num_auth_servers);
6933ff40c12SJohn Marino hostapd_config_free_radius(conf->radius->acct_servers,
6943ff40c12SJohn Marino conf->radius->num_acct_servers);
6953ff40c12SJohn Marino }
6963ff40c12SJohn Marino hostapd_config_free_radius_attr(conf->radius_auth_req_attr);
6973ff40c12SJohn Marino hostapd_config_free_radius_attr(conf->radius_acct_req_attr);
698*a1157835SDaniel Fojt os_free(conf->radius_req_attr_sqlite);
6993ff40c12SJohn Marino os_free(conf->rsn_preauth_interfaces);
7003ff40c12SJohn Marino os_free(conf->ctrl_interface);
7013ff40c12SJohn Marino os_free(conf->ca_cert);
7023ff40c12SJohn Marino os_free(conf->server_cert);
703*a1157835SDaniel Fojt os_free(conf->server_cert2);
7043ff40c12SJohn Marino os_free(conf->private_key);
705*a1157835SDaniel Fojt os_free(conf->private_key2);
7063ff40c12SJohn Marino os_free(conf->private_key_passwd);
707*a1157835SDaniel Fojt os_free(conf->private_key_passwd2);
708*a1157835SDaniel Fojt os_free(conf->check_cert_subject);
7093ff40c12SJohn Marino os_free(conf->ocsp_stapling_response);
710*a1157835SDaniel Fojt os_free(conf->ocsp_stapling_response_multi);
7113ff40c12SJohn Marino os_free(conf->dh_file);
712*a1157835SDaniel Fojt os_free(conf->openssl_ciphers);
713*a1157835SDaniel Fojt os_free(conf->openssl_ecdh_curves);
7143ff40c12SJohn Marino os_free(conf->pac_opaque_encr_key);
7153ff40c12SJohn Marino os_free(conf->eap_fast_a_id);
7163ff40c12SJohn Marino os_free(conf->eap_fast_a_id_info);
7173ff40c12SJohn Marino os_free(conf->eap_sim_db);
7183ff40c12SJohn Marino os_free(conf->radius_server_clients);
7193ff40c12SJohn Marino os_free(conf->radius);
7203ff40c12SJohn Marino os_free(conf->radius_das_shared_secret);
7213ff40c12SJohn Marino hostapd_config_free_vlan(conf);
7223ff40c12SJohn Marino os_free(conf->time_zone);
7233ff40c12SJohn Marino
724*a1157835SDaniel Fojt #ifdef CONFIG_IEEE80211R_AP
7253ff40c12SJohn Marino {
7263ff40c12SJohn Marino struct ft_remote_r0kh *r0kh, *r0kh_prev;
7273ff40c12SJohn Marino struct ft_remote_r1kh *r1kh, *r1kh_prev;
7283ff40c12SJohn Marino
7293ff40c12SJohn Marino r0kh = conf->r0kh_list;
7303ff40c12SJohn Marino conf->r0kh_list = NULL;
7313ff40c12SJohn Marino while (r0kh) {
7323ff40c12SJohn Marino r0kh_prev = r0kh;
7333ff40c12SJohn Marino r0kh = r0kh->next;
7343ff40c12SJohn Marino os_free(r0kh_prev);
7353ff40c12SJohn Marino }
7363ff40c12SJohn Marino
7373ff40c12SJohn Marino r1kh = conf->r1kh_list;
7383ff40c12SJohn Marino conf->r1kh_list = NULL;
7393ff40c12SJohn Marino while (r1kh) {
7403ff40c12SJohn Marino r1kh_prev = r1kh;
7413ff40c12SJohn Marino r1kh = r1kh->next;
7423ff40c12SJohn Marino os_free(r1kh_prev);
7433ff40c12SJohn Marino }
7443ff40c12SJohn Marino }
745*a1157835SDaniel Fojt #endif /* CONFIG_IEEE80211R_AP */
7463ff40c12SJohn Marino
7473ff40c12SJohn Marino #ifdef CONFIG_WPS
7483ff40c12SJohn Marino os_free(conf->wps_pin_requests);
7493ff40c12SJohn Marino os_free(conf->device_name);
7503ff40c12SJohn Marino os_free(conf->manufacturer);
7513ff40c12SJohn Marino os_free(conf->model_name);
7523ff40c12SJohn Marino os_free(conf->model_number);
7533ff40c12SJohn Marino os_free(conf->serial_number);
7543ff40c12SJohn Marino os_free(conf->config_methods);
7553ff40c12SJohn Marino os_free(conf->ap_pin);
7563ff40c12SJohn Marino os_free(conf->extra_cred);
7573ff40c12SJohn Marino os_free(conf->ap_settings);
758*a1157835SDaniel Fojt hostapd_config_clear_wpa_psk(&conf->multi_ap_backhaul_ssid.wpa_psk);
759*a1157835SDaniel Fojt str_clear_free(conf->multi_ap_backhaul_ssid.wpa_passphrase);
7603ff40c12SJohn Marino os_free(conf->upnp_iface);
7613ff40c12SJohn Marino os_free(conf->friendly_name);
7623ff40c12SJohn Marino os_free(conf->manufacturer_url);
7633ff40c12SJohn Marino os_free(conf->model_description);
7643ff40c12SJohn Marino os_free(conf->model_url);
7653ff40c12SJohn Marino os_free(conf->upc);
766*a1157835SDaniel Fojt for (i = 0; i < MAX_WPS_VENDOR_EXTENSIONS; i++)
767*a1157835SDaniel Fojt wpabuf_free(conf->wps_vendor_ext[i]);
7683ff40c12SJohn Marino wpabuf_free(conf->wps_nfc_dh_pubkey);
7693ff40c12SJohn Marino wpabuf_free(conf->wps_nfc_dh_privkey);
7703ff40c12SJohn Marino wpabuf_free(conf->wps_nfc_dev_pw);
7713ff40c12SJohn Marino #endif /* CONFIG_WPS */
7723ff40c12SJohn Marino
7733ff40c12SJohn Marino os_free(conf->roaming_consortium);
7743ff40c12SJohn Marino os_free(conf->venue_name);
775*a1157835SDaniel Fojt os_free(conf->venue_url);
7763ff40c12SJohn Marino os_free(conf->nai_realm_data);
7773ff40c12SJohn Marino os_free(conf->network_auth_type);
7783ff40c12SJohn Marino os_free(conf->anqp_3gpp_cell_net);
7793ff40c12SJohn Marino os_free(conf->domain_name);
780*a1157835SDaniel Fojt hostapd_config_free_anqp_elem(conf);
7813ff40c12SJohn Marino
7823ff40c12SJohn Marino #ifdef CONFIG_RADIUS_TEST
7833ff40c12SJohn Marino os_free(conf->dump_msk_file);
7843ff40c12SJohn Marino #endif /* CONFIG_RADIUS_TEST */
7853ff40c12SJohn Marino
7863ff40c12SJohn Marino #ifdef CONFIG_HS20
7873ff40c12SJohn Marino os_free(conf->hs20_oper_friendly_name);
7883ff40c12SJohn Marino os_free(conf->hs20_wan_metrics);
7893ff40c12SJohn Marino os_free(conf->hs20_connection_capability);
7903ff40c12SJohn Marino os_free(conf->hs20_operating_class);
791*a1157835SDaniel Fojt os_free(conf->hs20_icons);
792*a1157835SDaniel Fojt if (conf->hs20_osu_providers) {
793*a1157835SDaniel Fojt for (i = 0; i < conf->hs20_osu_providers_count; i++) {
794*a1157835SDaniel Fojt struct hs20_osu_provider *p;
795*a1157835SDaniel Fojt size_t j;
796*a1157835SDaniel Fojt p = &conf->hs20_osu_providers[i];
797*a1157835SDaniel Fojt os_free(p->friendly_name);
798*a1157835SDaniel Fojt os_free(p->server_uri);
799*a1157835SDaniel Fojt os_free(p->method_list);
800*a1157835SDaniel Fojt for (j = 0; j < p->icons_count; j++)
801*a1157835SDaniel Fojt os_free(p->icons[j]);
802*a1157835SDaniel Fojt os_free(p->icons);
803*a1157835SDaniel Fojt os_free(p->osu_nai);
804*a1157835SDaniel Fojt os_free(p->osu_nai2);
805*a1157835SDaniel Fojt os_free(p->service_desc);
806*a1157835SDaniel Fojt }
807*a1157835SDaniel Fojt os_free(conf->hs20_osu_providers);
808*a1157835SDaniel Fojt }
809*a1157835SDaniel Fojt if (conf->hs20_operator_icon) {
810*a1157835SDaniel Fojt for (i = 0; i < conf->hs20_operator_icon_count; i++)
811*a1157835SDaniel Fojt os_free(conf->hs20_operator_icon[i]);
812*a1157835SDaniel Fojt os_free(conf->hs20_operator_icon);
813*a1157835SDaniel Fojt }
814*a1157835SDaniel Fojt os_free(conf->subscr_remediation_url);
815*a1157835SDaniel Fojt os_free(conf->hs20_sim_provisioning_url);
816*a1157835SDaniel Fojt os_free(conf->t_c_filename);
817*a1157835SDaniel Fojt os_free(conf->t_c_server_url);
8183ff40c12SJohn Marino #endif /* CONFIG_HS20 */
8193ff40c12SJohn Marino
8203ff40c12SJohn Marino wpabuf_free(conf->vendor_elements);
821*a1157835SDaniel Fojt wpabuf_free(conf->assocresp_elements);
8223ff40c12SJohn Marino
8233ff40c12SJohn Marino os_free(conf->sae_groups);
824*a1157835SDaniel Fojt #ifdef CONFIG_OWE
825*a1157835SDaniel Fojt os_free(conf->owe_groups);
826*a1157835SDaniel Fojt #endif /* CONFIG_OWE */
827*a1157835SDaniel Fojt
828*a1157835SDaniel Fojt os_free(conf->wowlan_triggers);
8293ff40c12SJohn Marino
8303ff40c12SJohn Marino os_free(conf->server_id);
8313ff40c12SJohn Marino
832*a1157835SDaniel Fojt #ifdef CONFIG_TESTING_OPTIONS
833*a1157835SDaniel Fojt wpabuf_free(conf->own_ie_override);
834*a1157835SDaniel Fojt wpabuf_free(conf->sae_commit_override);
835*a1157835SDaniel Fojt #endif /* CONFIG_TESTING_OPTIONS */
836*a1157835SDaniel Fojt
837*a1157835SDaniel Fojt os_free(conf->no_probe_resp_if_seen_on);
838*a1157835SDaniel Fojt os_free(conf->no_auth_if_seen_on);
839*a1157835SDaniel Fojt
840*a1157835SDaniel Fojt hostapd_config_free_fils_realms(conf);
841*a1157835SDaniel Fojt
842*a1157835SDaniel Fojt #ifdef CONFIG_DPP
843*a1157835SDaniel Fojt os_free(conf->dpp_connector);
844*a1157835SDaniel Fojt wpabuf_free(conf->dpp_netaccesskey);
845*a1157835SDaniel Fojt wpabuf_free(conf->dpp_csign);
846*a1157835SDaniel Fojt #ifdef CONFIG_DPP2
847*a1157835SDaniel Fojt hostapd_dpp_controller_conf_free(conf->dpp_controller);
848*a1157835SDaniel Fojt #endif /* CONFIG_DPP2 */
849*a1157835SDaniel Fojt #endif /* CONFIG_DPP */
850*a1157835SDaniel Fojt
851*a1157835SDaniel Fojt hostapd_config_free_sae_passwords(conf);
852*a1157835SDaniel Fojt
853*a1157835SDaniel Fojt #ifdef CONFIG_AIRTIME_POLICY
854*a1157835SDaniel Fojt {
855*a1157835SDaniel Fojt struct airtime_sta_weight *wt, *wt_prev;
856*a1157835SDaniel Fojt
857*a1157835SDaniel Fojt wt = conf->airtime_weight_list;
858*a1157835SDaniel Fojt conf->airtime_weight_list = NULL;
859*a1157835SDaniel Fojt while (wt) {
860*a1157835SDaniel Fojt wt_prev = wt;
861*a1157835SDaniel Fojt wt = wt->next;
862*a1157835SDaniel Fojt os_free(wt_prev);
863*a1157835SDaniel Fojt }
864*a1157835SDaniel Fojt }
865*a1157835SDaniel Fojt #endif /* CONFIG_AIRTIME_POLICY */
866*a1157835SDaniel Fojt
8673ff40c12SJohn Marino os_free(conf);
8683ff40c12SJohn Marino }
8693ff40c12SJohn Marino
8703ff40c12SJohn Marino
8713ff40c12SJohn Marino /**
8723ff40c12SJohn Marino * hostapd_config_free - Free hostapd configuration
8733ff40c12SJohn Marino * @conf: Configuration data from hostapd_config_read().
8743ff40c12SJohn Marino */
hostapd_config_free(struct hostapd_config * conf)8753ff40c12SJohn Marino void hostapd_config_free(struct hostapd_config *conf)
8763ff40c12SJohn Marino {
8773ff40c12SJohn Marino size_t i;
8783ff40c12SJohn Marino
8793ff40c12SJohn Marino if (conf == NULL)
8803ff40c12SJohn Marino return;
8813ff40c12SJohn Marino
8823ff40c12SJohn Marino for (i = 0; i < conf->num_bss; i++)
8833ff40c12SJohn Marino hostapd_config_free_bss(conf->bss[i]);
8843ff40c12SJohn Marino os_free(conf->bss);
8853ff40c12SJohn Marino os_free(conf->supported_rates);
8863ff40c12SJohn Marino os_free(conf->basic_rates);
887*a1157835SDaniel Fojt os_free(conf->acs_ch_list.range);
888*a1157835SDaniel Fojt os_free(conf->driver_params);
889*a1157835SDaniel Fojt #ifdef CONFIG_ACS
890*a1157835SDaniel Fojt os_free(conf->acs_chan_bias);
891*a1157835SDaniel Fojt #endif /* CONFIG_ACS */
892*a1157835SDaniel Fojt wpabuf_free(conf->lci);
893*a1157835SDaniel Fojt wpabuf_free(conf->civic);
8943ff40c12SJohn Marino
8953ff40c12SJohn Marino os_free(conf);
8963ff40c12SJohn Marino }
8973ff40c12SJohn Marino
8983ff40c12SJohn Marino
8993ff40c12SJohn Marino /**
9003ff40c12SJohn Marino * hostapd_maclist_found - Find a MAC address from a list
9013ff40c12SJohn Marino * @list: MAC address list
9023ff40c12SJohn Marino * @num_entries: Number of addresses in the list
9033ff40c12SJohn Marino * @addr: Address to search for
9043ff40c12SJohn Marino * @vlan_id: Buffer for returning VLAN ID or %NULL if not needed
9053ff40c12SJohn Marino * Returns: 1 if address is in the list or 0 if not.
9063ff40c12SJohn Marino *
9073ff40c12SJohn Marino * Perform a binary search for given MAC address from a pre-sorted list.
9083ff40c12SJohn Marino */
hostapd_maclist_found(struct mac_acl_entry * list,int num_entries,const u8 * addr,struct vlan_description * vlan_id)9093ff40c12SJohn Marino int hostapd_maclist_found(struct mac_acl_entry *list, int num_entries,
910*a1157835SDaniel Fojt const u8 *addr, struct vlan_description *vlan_id)
9113ff40c12SJohn Marino {
9123ff40c12SJohn Marino int start, end, middle, res;
9133ff40c12SJohn Marino
9143ff40c12SJohn Marino start = 0;
9153ff40c12SJohn Marino end = num_entries - 1;
9163ff40c12SJohn Marino
9173ff40c12SJohn Marino while (start <= end) {
9183ff40c12SJohn Marino middle = (start + end) / 2;
9193ff40c12SJohn Marino res = os_memcmp(list[middle].addr, addr, ETH_ALEN);
9203ff40c12SJohn Marino if (res == 0) {
9213ff40c12SJohn Marino if (vlan_id)
9223ff40c12SJohn Marino *vlan_id = list[middle].vlan_id;
9233ff40c12SJohn Marino return 1;
9243ff40c12SJohn Marino }
9253ff40c12SJohn Marino if (res < 0)
9263ff40c12SJohn Marino start = middle + 1;
9273ff40c12SJohn Marino else
9283ff40c12SJohn Marino end = middle - 1;
9293ff40c12SJohn Marino }
9303ff40c12SJohn Marino
9313ff40c12SJohn Marino return 0;
9323ff40c12SJohn Marino }
9333ff40c12SJohn Marino
9343ff40c12SJohn Marino
hostapd_rate_found(int * list,int rate)9353ff40c12SJohn Marino int hostapd_rate_found(int *list, int rate)
9363ff40c12SJohn Marino {
9373ff40c12SJohn Marino int i;
9383ff40c12SJohn Marino
9393ff40c12SJohn Marino if (list == NULL)
9403ff40c12SJohn Marino return 0;
9413ff40c12SJohn Marino
9423ff40c12SJohn Marino for (i = 0; list[i] >= 0; i++)
9433ff40c12SJohn Marino if (list[i] == rate)
9443ff40c12SJohn Marino return 1;
9453ff40c12SJohn Marino
9463ff40c12SJohn Marino return 0;
9473ff40c12SJohn Marino }
9483ff40c12SJohn Marino
9493ff40c12SJohn Marino
hostapd_vlan_valid(struct hostapd_vlan * vlan,struct vlan_description * vlan_desc)950*a1157835SDaniel Fojt int hostapd_vlan_valid(struct hostapd_vlan *vlan,
951*a1157835SDaniel Fojt struct vlan_description *vlan_desc)
9523ff40c12SJohn Marino {
9533ff40c12SJohn Marino struct hostapd_vlan *v = vlan;
954*a1157835SDaniel Fojt int i;
955*a1157835SDaniel Fojt
956*a1157835SDaniel Fojt if (!vlan_desc->notempty || vlan_desc->untagged < 0 ||
957*a1157835SDaniel Fojt vlan_desc->untagged > MAX_VLAN_ID)
958*a1157835SDaniel Fojt return 0;
959*a1157835SDaniel Fojt for (i = 0; i < MAX_NUM_TAGGED_VLAN; i++) {
960*a1157835SDaniel Fojt if (vlan_desc->tagged[i] < 0 ||
961*a1157835SDaniel Fojt vlan_desc->tagged[i] > MAX_VLAN_ID)
962*a1157835SDaniel Fojt return 0;
963*a1157835SDaniel Fojt }
964*a1157835SDaniel Fojt if (!vlan_desc->untagged && !vlan_desc->tagged[0])
965*a1157835SDaniel Fojt return 0;
966*a1157835SDaniel Fojt
9673ff40c12SJohn Marino while (v) {
968*a1157835SDaniel Fojt if (!vlan_compare(&v->vlan_desc, vlan_desc) ||
969*a1157835SDaniel Fojt v->vlan_id == VLAN_ID_WILDCARD)
9703ff40c12SJohn Marino return 1;
9713ff40c12SJohn Marino v = v->next;
9723ff40c12SJohn Marino }
9733ff40c12SJohn Marino return 0;
9743ff40c12SJohn Marino }
9753ff40c12SJohn Marino
9763ff40c12SJohn Marino
hostapd_get_vlan_id_ifname(struct hostapd_vlan * vlan,int vlan_id)9773ff40c12SJohn Marino const char * hostapd_get_vlan_id_ifname(struct hostapd_vlan *vlan, int vlan_id)
9783ff40c12SJohn Marino {
9793ff40c12SJohn Marino struct hostapd_vlan *v = vlan;
9803ff40c12SJohn Marino while (v) {
9813ff40c12SJohn Marino if (v->vlan_id == vlan_id)
9823ff40c12SJohn Marino return v->ifname;
9833ff40c12SJohn Marino v = v->next;
9843ff40c12SJohn Marino }
9853ff40c12SJohn Marino return NULL;
9863ff40c12SJohn Marino }
9873ff40c12SJohn Marino
9883ff40c12SJohn Marino
hostapd_get_psk(const struct hostapd_bss_config * conf,const u8 * addr,const u8 * p2p_dev_addr,const u8 * prev_psk,int * vlan_id)9893ff40c12SJohn Marino const u8 * hostapd_get_psk(const struct hostapd_bss_config *conf,
9903ff40c12SJohn Marino const u8 *addr, const u8 *p2p_dev_addr,
991*a1157835SDaniel Fojt const u8 *prev_psk, int *vlan_id)
9923ff40c12SJohn Marino {
9933ff40c12SJohn Marino struct hostapd_wpa_psk *psk;
9943ff40c12SJohn Marino int next_ok = prev_psk == NULL;
9953ff40c12SJohn Marino
996*a1157835SDaniel Fojt if (vlan_id)
997*a1157835SDaniel Fojt *vlan_id = 0;
998*a1157835SDaniel Fojt
999*a1157835SDaniel Fojt if (p2p_dev_addr && !is_zero_ether_addr(p2p_dev_addr)) {
10003ff40c12SJohn Marino wpa_printf(MSG_DEBUG, "Searching a PSK for " MACSTR
10013ff40c12SJohn Marino " p2p_dev_addr=" MACSTR " prev_psk=%p",
10023ff40c12SJohn Marino MAC2STR(addr), MAC2STR(p2p_dev_addr), prev_psk);
10033ff40c12SJohn Marino addr = NULL; /* Use P2P Device Address for matching */
10043ff40c12SJohn Marino } else {
10053ff40c12SJohn Marino wpa_printf(MSG_DEBUG, "Searching a PSK for " MACSTR
10063ff40c12SJohn Marino " prev_psk=%p",
10073ff40c12SJohn Marino MAC2STR(addr), prev_psk);
10083ff40c12SJohn Marino }
10093ff40c12SJohn Marino
10103ff40c12SJohn Marino for (psk = conf->ssid.wpa_psk; psk != NULL; psk = psk->next) {
10113ff40c12SJohn Marino if (next_ok &&
10123ff40c12SJohn Marino (psk->group ||
10133ff40c12SJohn Marino (addr && os_memcmp(psk->addr, addr, ETH_ALEN) == 0) ||
10143ff40c12SJohn Marino (!addr && p2p_dev_addr &&
10153ff40c12SJohn Marino os_memcmp(psk->p2p_dev_addr, p2p_dev_addr, ETH_ALEN) ==
1016*a1157835SDaniel Fojt 0))) {
1017*a1157835SDaniel Fojt if (vlan_id)
1018*a1157835SDaniel Fojt *vlan_id = psk->vlan_id;
10193ff40c12SJohn Marino return psk->psk;
1020*a1157835SDaniel Fojt }
10213ff40c12SJohn Marino
10223ff40c12SJohn Marino if (psk->psk == prev_psk)
10233ff40c12SJohn Marino next_ok = 1;
10243ff40c12SJohn Marino }
10253ff40c12SJohn Marino
10263ff40c12SJohn Marino return NULL;
10273ff40c12SJohn Marino }
10283ff40c12SJohn Marino
10293ff40c12SJohn Marino
hostapd_config_check_bss(struct hostapd_bss_config * bss,struct hostapd_config * conf,int full_config)10303ff40c12SJohn Marino static int hostapd_config_check_bss(struct hostapd_bss_config *bss,
10313ff40c12SJohn Marino struct hostapd_config *conf,
10323ff40c12SJohn Marino int full_config)
10333ff40c12SJohn Marino {
10343ff40c12SJohn Marino if (full_config && bss->ieee802_1x && !bss->eap_server &&
10353ff40c12SJohn Marino !bss->radius->auth_servers) {
10363ff40c12SJohn Marino wpa_printf(MSG_ERROR, "Invalid IEEE 802.1X configuration (no "
10373ff40c12SJohn Marino "EAP authenticator configured).");
10383ff40c12SJohn Marino return -1;
10393ff40c12SJohn Marino }
10403ff40c12SJohn Marino
10413ff40c12SJohn Marino if (bss->wpa) {
10423ff40c12SJohn Marino int wep, i;
10433ff40c12SJohn Marino
10443ff40c12SJohn Marino wep = bss->default_wep_key_len > 0 ||
10453ff40c12SJohn Marino bss->individual_wep_key_len > 0;
10463ff40c12SJohn Marino for (i = 0; i < NUM_WEP_KEYS; i++) {
10473ff40c12SJohn Marino if (bss->ssid.wep.keys_set) {
10483ff40c12SJohn Marino wep = 1;
10493ff40c12SJohn Marino break;
10503ff40c12SJohn Marino }
10513ff40c12SJohn Marino }
10523ff40c12SJohn Marino
10533ff40c12SJohn Marino if (wep) {
10543ff40c12SJohn Marino wpa_printf(MSG_ERROR, "WEP configuration in a WPA network is not supported");
10553ff40c12SJohn Marino return -1;
10563ff40c12SJohn Marino }
10573ff40c12SJohn Marino }
10583ff40c12SJohn Marino
10593ff40c12SJohn Marino if (full_config && bss->wpa &&
10603ff40c12SJohn Marino bss->wpa_psk_radius != PSK_RADIUS_IGNORED &&
10613ff40c12SJohn Marino bss->macaddr_acl != USE_EXTERNAL_RADIUS_AUTH) {
10623ff40c12SJohn Marino wpa_printf(MSG_ERROR, "WPA-PSK using RADIUS enabled, but no "
10633ff40c12SJohn Marino "RADIUS checking (macaddr_acl=2) enabled.");
10643ff40c12SJohn Marino return -1;
10653ff40c12SJohn Marino }
10663ff40c12SJohn Marino
10673ff40c12SJohn Marino if (full_config && bss->wpa && (bss->wpa_key_mgmt & WPA_KEY_MGMT_PSK) &&
10683ff40c12SJohn Marino bss->ssid.wpa_psk == NULL && bss->ssid.wpa_passphrase == NULL &&
10693ff40c12SJohn Marino bss->ssid.wpa_psk_file == NULL &&
10703ff40c12SJohn Marino (bss->wpa_psk_radius != PSK_RADIUS_REQUIRED ||
10713ff40c12SJohn Marino bss->macaddr_acl != USE_EXTERNAL_RADIUS_AUTH)) {
10723ff40c12SJohn Marino wpa_printf(MSG_ERROR, "WPA-PSK enabled, but PSK or passphrase "
10733ff40c12SJohn Marino "is not configured.");
10743ff40c12SJohn Marino return -1;
10753ff40c12SJohn Marino }
10763ff40c12SJohn Marino
1077*a1157835SDaniel Fojt if (full_config && !is_zero_ether_addr(bss->bssid)) {
10783ff40c12SJohn Marino size_t i;
10793ff40c12SJohn Marino
10803ff40c12SJohn Marino for (i = 0; i < conf->num_bss; i++) {
10813ff40c12SJohn Marino if (conf->bss[i] != bss &&
10823ff40c12SJohn Marino (hostapd_mac_comp(conf->bss[i]->bssid,
10833ff40c12SJohn Marino bss->bssid) == 0)) {
10843ff40c12SJohn Marino wpa_printf(MSG_ERROR, "Duplicate BSSID " MACSTR
10853ff40c12SJohn Marino " on interface '%s' and '%s'.",
10863ff40c12SJohn Marino MAC2STR(bss->bssid),
10873ff40c12SJohn Marino conf->bss[i]->iface, bss->iface);
10883ff40c12SJohn Marino return -1;
10893ff40c12SJohn Marino }
10903ff40c12SJohn Marino }
10913ff40c12SJohn Marino }
10923ff40c12SJohn Marino
1093*a1157835SDaniel Fojt #ifdef CONFIG_IEEE80211R_AP
10943ff40c12SJohn Marino if (full_config && wpa_key_mgmt_ft(bss->wpa_key_mgmt) &&
10953ff40c12SJohn Marino (bss->nas_identifier == NULL ||
10963ff40c12SJohn Marino os_strlen(bss->nas_identifier) < 1 ||
10973ff40c12SJohn Marino os_strlen(bss->nas_identifier) > FT_R0KH_ID_MAX_LEN)) {
10983ff40c12SJohn Marino wpa_printf(MSG_ERROR, "FT (IEEE 802.11r) requires "
10993ff40c12SJohn Marino "nas_identifier to be configured as a 1..48 octet "
11003ff40c12SJohn Marino "string");
11013ff40c12SJohn Marino return -1;
11023ff40c12SJohn Marino }
1103*a1157835SDaniel Fojt #endif /* CONFIG_IEEE80211R_AP */
11043ff40c12SJohn Marino
11053ff40c12SJohn Marino #ifdef CONFIG_IEEE80211N
11063ff40c12SJohn Marino if (full_config && conf->ieee80211n &&
11073ff40c12SJohn Marino conf->hw_mode == HOSTAPD_MODE_IEEE80211B) {
11083ff40c12SJohn Marino bss->disable_11n = 1;
11093ff40c12SJohn Marino wpa_printf(MSG_ERROR, "HT (IEEE 802.11n) in 11b mode is not "
1110*a1157835SDaniel Fojt "allowed, disabling HT capabilities");
11113ff40c12SJohn Marino }
11123ff40c12SJohn Marino
11133ff40c12SJohn Marino if (full_config && conf->ieee80211n &&
11143ff40c12SJohn Marino bss->ssid.security_policy == SECURITY_STATIC_WEP) {
11153ff40c12SJohn Marino bss->disable_11n = 1;
11163ff40c12SJohn Marino wpa_printf(MSG_ERROR, "HT (IEEE 802.11n) with WEP is not "
11173ff40c12SJohn Marino "allowed, disabling HT capabilities");
11183ff40c12SJohn Marino }
11193ff40c12SJohn Marino
11203ff40c12SJohn Marino if (full_config && conf->ieee80211n && bss->wpa &&
11213ff40c12SJohn Marino !(bss->wpa_pairwise & WPA_CIPHER_CCMP) &&
11223ff40c12SJohn Marino !(bss->rsn_pairwise & (WPA_CIPHER_CCMP | WPA_CIPHER_GCMP |
11233ff40c12SJohn Marino WPA_CIPHER_CCMP_256 | WPA_CIPHER_GCMP_256)))
11243ff40c12SJohn Marino {
11253ff40c12SJohn Marino bss->disable_11n = 1;
11263ff40c12SJohn Marino wpa_printf(MSG_ERROR, "HT (IEEE 802.11n) with WPA/WPA2 "
11273ff40c12SJohn Marino "requires CCMP/GCMP to be enabled, disabling HT "
11283ff40c12SJohn Marino "capabilities");
11293ff40c12SJohn Marino }
11303ff40c12SJohn Marino #endif /* CONFIG_IEEE80211N */
11313ff40c12SJohn Marino
1132*a1157835SDaniel Fojt #ifdef CONFIG_IEEE80211AC
1133*a1157835SDaniel Fojt if (full_config && conf->ieee80211ac &&
1134*a1157835SDaniel Fojt bss->ssid.security_policy == SECURITY_STATIC_WEP) {
1135*a1157835SDaniel Fojt bss->disable_11ac = 1;
1136*a1157835SDaniel Fojt wpa_printf(MSG_ERROR,
1137*a1157835SDaniel Fojt "VHT (IEEE 802.11ac) with WEP is not allowed, disabling VHT capabilities");
1138*a1157835SDaniel Fojt }
1139*a1157835SDaniel Fojt
1140*a1157835SDaniel Fojt if (full_config && conf->ieee80211ac && bss->wpa &&
1141*a1157835SDaniel Fojt !(bss->wpa_pairwise & WPA_CIPHER_CCMP) &&
1142*a1157835SDaniel Fojt !(bss->rsn_pairwise & (WPA_CIPHER_CCMP | WPA_CIPHER_GCMP |
1143*a1157835SDaniel Fojt WPA_CIPHER_CCMP_256 | WPA_CIPHER_GCMP_256)))
1144*a1157835SDaniel Fojt {
1145*a1157835SDaniel Fojt bss->disable_11ac = 1;
1146*a1157835SDaniel Fojt wpa_printf(MSG_ERROR,
1147*a1157835SDaniel Fojt "VHT (IEEE 802.11ac) with WPA/WPA2 requires CCMP/GCMP to be enabled, disabling VHT capabilities");
1148*a1157835SDaniel Fojt }
1149*a1157835SDaniel Fojt #endif /* CONFIG_IEEE80211AC */
1150*a1157835SDaniel Fojt
1151*a1157835SDaniel Fojt #ifdef CONFIG_WPS
11523ff40c12SJohn Marino if (full_config && bss->wps_state && bss->ignore_broadcast_ssid) {
11533ff40c12SJohn Marino wpa_printf(MSG_INFO, "WPS: ignore_broadcast_ssid "
11543ff40c12SJohn Marino "configuration forced WPS to be disabled");
11553ff40c12SJohn Marino bss->wps_state = 0;
11563ff40c12SJohn Marino }
11573ff40c12SJohn Marino
11583ff40c12SJohn Marino if (full_config && bss->wps_state &&
11593ff40c12SJohn Marino bss->ssid.wep.keys_set && bss->wpa == 0) {
11603ff40c12SJohn Marino wpa_printf(MSG_INFO, "WPS: WEP configuration forced WPS to be "
11613ff40c12SJohn Marino "disabled");
11623ff40c12SJohn Marino bss->wps_state = 0;
11633ff40c12SJohn Marino }
11643ff40c12SJohn Marino
11653ff40c12SJohn Marino if (full_config && bss->wps_state && bss->wpa &&
11663ff40c12SJohn Marino (!(bss->wpa & 2) ||
1167*a1157835SDaniel Fojt !(bss->rsn_pairwise & (WPA_CIPHER_CCMP | WPA_CIPHER_GCMP |
1168*a1157835SDaniel Fojt WPA_CIPHER_CCMP_256 |
1169*a1157835SDaniel Fojt WPA_CIPHER_GCMP_256)))) {
11703ff40c12SJohn Marino wpa_printf(MSG_INFO, "WPS: WPA/TKIP configuration without "
1171*a1157835SDaniel Fojt "WPA2/CCMP/GCMP forced WPS to be disabled");
11723ff40c12SJohn Marino bss->wps_state = 0;
11733ff40c12SJohn Marino }
1174*a1157835SDaniel Fojt #endif /* CONFIG_WPS */
11753ff40c12SJohn Marino
11763ff40c12SJohn Marino #ifdef CONFIG_HS20
11773ff40c12SJohn Marino if (full_config && bss->hs20 &&
11783ff40c12SJohn Marino (!(bss->wpa & 2) ||
11793ff40c12SJohn Marino !(bss->rsn_pairwise & (WPA_CIPHER_CCMP | WPA_CIPHER_GCMP |
11803ff40c12SJohn Marino WPA_CIPHER_CCMP_256 |
11813ff40c12SJohn Marino WPA_CIPHER_GCMP_256)))) {
11823ff40c12SJohn Marino wpa_printf(MSG_ERROR, "HS 2.0: WPA2-Enterprise/CCMP "
11833ff40c12SJohn Marino "configuration is required for Hotspot 2.0 "
11843ff40c12SJohn Marino "functionality");
11853ff40c12SJohn Marino return -1;
11863ff40c12SJohn Marino }
11873ff40c12SJohn Marino #endif /* CONFIG_HS20 */
11883ff40c12SJohn Marino
1189*a1157835SDaniel Fojt #ifdef CONFIG_MBO
1190*a1157835SDaniel Fojt if (full_config && bss->mbo_enabled && (bss->wpa & 2) &&
1191*a1157835SDaniel Fojt bss->ieee80211w == NO_MGMT_FRAME_PROTECTION) {
1192*a1157835SDaniel Fojt wpa_printf(MSG_ERROR,
1193*a1157835SDaniel Fojt "MBO: PMF needs to be enabled whenever using WPA2 with MBO");
1194*a1157835SDaniel Fojt return -1;
1195*a1157835SDaniel Fojt }
1196*a1157835SDaniel Fojt #endif /* CONFIG_MBO */
1197*a1157835SDaniel Fojt
1198*a1157835SDaniel Fojt #ifdef CONFIG_OCV
1199*a1157835SDaniel Fojt if (full_config && bss->ieee80211w == NO_MGMT_FRAME_PROTECTION &&
1200*a1157835SDaniel Fojt bss->ocv) {
1201*a1157835SDaniel Fojt wpa_printf(MSG_ERROR,
1202*a1157835SDaniel Fojt "OCV: PMF needs to be enabled whenever using OCV");
1203*a1157835SDaniel Fojt return -1;
1204*a1157835SDaniel Fojt }
1205*a1157835SDaniel Fojt #endif /* CONFIG_OCV */
1206*a1157835SDaniel Fojt
1207*a1157835SDaniel Fojt return 0;
1208*a1157835SDaniel Fojt }
1209*a1157835SDaniel Fojt
1210*a1157835SDaniel Fojt
hostapd_config_check_cw(struct hostapd_config * conf,int queue)1211*a1157835SDaniel Fojt static int hostapd_config_check_cw(struct hostapd_config *conf, int queue)
1212*a1157835SDaniel Fojt {
1213*a1157835SDaniel Fojt int tx_cwmin = conf->tx_queue[queue].cwmin;
1214*a1157835SDaniel Fojt int tx_cwmax = conf->tx_queue[queue].cwmax;
1215*a1157835SDaniel Fojt int ac_cwmin = conf->wmm_ac_params[queue].cwmin;
1216*a1157835SDaniel Fojt int ac_cwmax = conf->wmm_ac_params[queue].cwmax;
1217*a1157835SDaniel Fojt
1218*a1157835SDaniel Fojt if (tx_cwmin > tx_cwmax) {
1219*a1157835SDaniel Fojt wpa_printf(MSG_ERROR,
1220*a1157835SDaniel Fojt "Invalid TX queue cwMin/cwMax values. cwMin(%d) greater than cwMax(%d)",
1221*a1157835SDaniel Fojt tx_cwmin, tx_cwmax);
1222*a1157835SDaniel Fojt return -1;
1223*a1157835SDaniel Fojt }
1224*a1157835SDaniel Fojt if (ac_cwmin > ac_cwmax) {
1225*a1157835SDaniel Fojt wpa_printf(MSG_ERROR,
1226*a1157835SDaniel Fojt "Invalid WMM AC cwMin/cwMax values. cwMin(%d) greater than cwMax(%d)",
1227*a1157835SDaniel Fojt ac_cwmin, ac_cwmax);
1228*a1157835SDaniel Fojt return -1;
1229*a1157835SDaniel Fojt }
12303ff40c12SJohn Marino return 0;
12313ff40c12SJohn Marino }
12323ff40c12SJohn Marino
12333ff40c12SJohn Marino
hostapd_config_check(struct hostapd_config * conf,int full_config)12343ff40c12SJohn Marino int hostapd_config_check(struct hostapd_config *conf, int full_config)
12353ff40c12SJohn Marino {
12363ff40c12SJohn Marino size_t i;
12373ff40c12SJohn Marino
12383ff40c12SJohn Marino if (full_config && conf->ieee80211d &&
12393ff40c12SJohn Marino (!conf->country[0] || !conf->country[1])) {
12403ff40c12SJohn Marino wpa_printf(MSG_ERROR, "Cannot enable IEEE 802.11d without "
12413ff40c12SJohn Marino "setting the country_code");
12423ff40c12SJohn Marino return -1;
12433ff40c12SJohn Marino }
12443ff40c12SJohn Marino
12453ff40c12SJohn Marino if (full_config && conf->ieee80211h && !conf->ieee80211d) {
12463ff40c12SJohn Marino wpa_printf(MSG_ERROR, "Cannot enable IEEE 802.11h without "
12473ff40c12SJohn Marino "IEEE 802.11d enabled");
12483ff40c12SJohn Marino return -1;
12493ff40c12SJohn Marino }
12503ff40c12SJohn Marino
1251*a1157835SDaniel Fojt if (full_config && conf->local_pwr_constraint != -1 &&
1252*a1157835SDaniel Fojt !conf->ieee80211d) {
1253*a1157835SDaniel Fojt wpa_printf(MSG_ERROR, "Cannot add Power Constraint element without Country element");
1254*a1157835SDaniel Fojt return -1;
1255*a1157835SDaniel Fojt }
1256*a1157835SDaniel Fojt
1257*a1157835SDaniel Fojt if (full_config && conf->spectrum_mgmt_required &&
1258*a1157835SDaniel Fojt conf->local_pwr_constraint == -1) {
1259*a1157835SDaniel Fojt wpa_printf(MSG_ERROR, "Cannot set Spectrum Management bit without Country and Power Constraint elements");
1260*a1157835SDaniel Fojt return -1;
1261*a1157835SDaniel Fojt }
1262*a1157835SDaniel Fojt
1263*a1157835SDaniel Fojt #ifdef CONFIG_AIRTIME_POLICY
1264*a1157835SDaniel Fojt if (full_config && conf->airtime_mode > AIRTIME_MODE_STATIC &&
1265*a1157835SDaniel Fojt !conf->airtime_update_interval) {
1266*a1157835SDaniel Fojt wpa_printf(MSG_ERROR, "Airtime update interval cannot be zero");
1267*a1157835SDaniel Fojt return -1;
1268*a1157835SDaniel Fojt }
1269*a1157835SDaniel Fojt #endif /* CONFIG_AIRTIME_POLICY */
1270*a1157835SDaniel Fojt for (i = 0; i < NUM_TX_QUEUES; i++) {
1271*a1157835SDaniel Fojt if (hostapd_config_check_cw(conf, i))
1272*a1157835SDaniel Fojt return -1;
1273*a1157835SDaniel Fojt }
1274*a1157835SDaniel Fojt
12753ff40c12SJohn Marino for (i = 0; i < conf->num_bss; i++) {
12763ff40c12SJohn Marino if (hostapd_config_check_bss(conf->bss[i], conf, full_config))
12773ff40c12SJohn Marino return -1;
12783ff40c12SJohn Marino }
12793ff40c12SJohn Marino
12803ff40c12SJohn Marino return 0;
12813ff40c12SJohn Marino }
12823ff40c12SJohn Marino
12833ff40c12SJohn Marino
hostapd_set_security_params(struct hostapd_bss_config * bss,int full_config)1284*a1157835SDaniel Fojt void hostapd_set_security_params(struct hostapd_bss_config *bss,
1285*a1157835SDaniel Fojt int full_config)
12863ff40c12SJohn Marino {
12873ff40c12SJohn Marino if (bss->individual_wep_key_len == 0) {
12883ff40c12SJohn Marino /* individual keys are not use; can use key idx0 for
12893ff40c12SJohn Marino * broadcast keys */
12903ff40c12SJohn Marino bss->broadcast_key_idx_min = 0;
12913ff40c12SJohn Marino }
12923ff40c12SJohn Marino
12933ff40c12SJohn Marino if ((bss->wpa & 2) && bss->rsn_pairwise == 0)
12943ff40c12SJohn Marino bss->rsn_pairwise = bss->wpa_pairwise;
1295*a1157835SDaniel Fojt if (bss->group_cipher)
1296*a1157835SDaniel Fojt bss->wpa_group = bss->group_cipher;
1297*a1157835SDaniel Fojt else
1298*a1157835SDaniel Fojt bss->wpa_group = wpa_select_ap_group_cipher(bss->wpa,
1299*a1157835SDaniel Fojt bss->wpa_pairwise,
13003ff40c12SJohn Marino bss->rsn_pairwise);
1301*a1157835SDaniel Fojt if (!bss->wpa_group_rekey_set)
1302*a1157835SDaniel Fojt bss->wpa_group_rekey = bss->wpa_group == WPA_CIPHER_TKIP ?
1303*a1157835SDaniel Fojt 600 : 86400;
13043ff40c12SJohn Marino
1305*a1157835SDaniel Fojt if (full_config) {
13063ff40c12SJohn Marino bss->radius->auth_server = bss->radius->auth_servers;
13073ff40c12SJohn Marino bss->radius->acct_server = bss->radius->acct_servers;
1308*a1157835SDaniel Fojt }
13093ff40c12SJohn Marino
13103ff40c12SJohn Marino if (bss->wpa && bss->ieee802_1x) {
13113ff40c12SJohn Marino bss->ssid.security_policy = SECURITY_WPA;
13123ff40c12SJohn Marino } else if (bss->wpa) {
13133ff40c12SJohn Marino bss->ssid.security_policy = SECURITY_WPA_PSK;
13143ff40c12SJohn Marino } else if (bss->ieee802_1x) {
13153ff40c12SJohn Marino int cipher = WPA_CIPHER_NONE;
13163ff40c12SJohn Marino bss->ssid.security_policy = SECURITY_IEEE_802_1X;
13173ff40c12SJohn Marino bss->ssid.wep.default_len = bss->default_wep_key_len;
1318*a1157835SDaniel Fojt if (full_config && bss->default_wep_key_len) {
13193ff40c12SJohn Marino cipher = bss->default_wep_key_len >= 13 ?
13203ff40c12SJohn Marino WPA_CIPHER_WEP104 : WPA_CIPHER_WEP40;
1321*a1157835SDaniel Fojt } else if (full_config && bss->ssid.wep.keys_set) {
1322*a1157835SDaniel Fojt if (bss->ssid.wep.len[0] >= 13)
1323*a1157835SDaniel Fojt cipher = WPA_CIPHER_WEP104;
1324*a1157835SDaniel Fojt else
1325*a1157835SDaniel Fojt cipher = WPA_CIPHER_WEP40;
1326*a1157835SDaniel Fojt }
13273ff40c12SJohn Marino bss->wpa_group = cipher;
13283ff40c12SJohn Marino bss->wpa_pairwise = cipher;
13293ff40c12SJohn Marino bss->rsn_pairwise = cipher;
1330*a1157835SDaniel Fojt if (full_config)
1331*a1157835SDaniel Fojt bss->wpa_key_mgmt = WPA_KEY_MGMT_IEEE8021X_NO_WPA;
13323ff40c12SJohn Marino } else if (bss->ssid.wep.keys_set) {
13333ff40c12SJohn Marino int cipher = WPA_CIPHER_WEP40;
13343ff40c12SJohn Marino if (bss->ssid.wep.len[0] >= 13)
13353ff40c12SJohn Marino cipher = WPA_CIPHER_WEP104;
13363ff40c12SJohn Marino bss->ssid.security_policy = SECURITY_STATIC_WEP;
13373ff40c12SJohn Marino bss->wpa_group = cipher;
13383ff40c12SJohn Marino bss->wpa_pairwise = cipher;
13393ff40c12SJohn Marino bss->rsn_pairwise = cipher;
1340*a1157835SDaniel Fojt if (full_config)
1341*a1157835SDaniel Fojt bss->wpa_key_mgmt = WPA_KEY_MGMT_NONE;
1342*a1157835SDaniel Fojt } else if (bss->osen) {
1343*a1157835SDaniel Fojt bss->ssid.security_policy = SECURITY_OSEN;
1344*a1157835SDaniel Fojt bss->wpa_group = WPA_CIPHER_CCMP;
1345*a1157835SDaniel Fojt bss->wpa_pairwise = 0;
1346*a1157835SDaniel Fojt bss->rsn_pairwise = WPA_CIPHER_CCMP;
13473ff40c12SJohn Marino } else {
13483ff40c12SJohn Marino bss->ssid.security_policy = SECURITY_PLAINTEXT;
1349*a1157835SDaniel Fojt if (full_config) {
13503ff40c12SJohn Marino bss->wpa_group = WPA_CIPHER_NONE;
13513ff40c12SJohn Marino bss->wpa_pairwise = WPA_CIPHER_NONE;
13523ff40c12SJohn Marino bss->rsn_pairwise = WPA_CIPHER_NONE;
1353*a1157835SDaniel Fojt bss->wpa_key_mgmt = WPA_KEY_MGMT_NONE;
13543ff40c12SJohn Marino }
13553ff40c12SJohn Marino }
1356*a1157835SDaniel Fojt }
1357*a1157835SDaniel Fojt
1358*a1157835SDaniel Fojt
hostapd_sae_pw_id_in_use(struct hostapd_bss_config * conf)1359*a1157835SDaniel Fojt int hostapd_sae_pw_id_in_use(struct hostapd_bss_config *conf)
1360*a1157835SDaniel Fojt {
1361*a1157835SDaniel Fojt int with_id = 0, without_id = 0;
1362*a1157835SDaniel Fojt struct sae_password_entry *pw;
1363*a1157835SDaniel Fojt
1364*a1157835SDaniel Fojt if (conf->ssid.wpa_passphrase)
1365*a1157835SDaniel Fojt without_id = 1;
1366*a1157835SDaniel Fojt
1367*a1157835SDaniel Fojt for (pw = conf->sae_passwords; pw; pw = pw->next) {
1368*a1157835SDaniel Fojt if (pw->identifier)
1369*a1157835SDaniel Fojt with_id = 1;
1370*a1157835SDaniel Fojt else
1371*a1157835SDaniel Fojt without_id = 1;
1372*a1157835SDaniel Fojt if (with_id && without_id)
1373*a1157835SDaniel Fojt break;
1374*a1157835SDaniel Fojt }
1375*a1157835SDaniel Fojt
1376*a1157835SDaniel Fojt if (with_id && !without_id)
1377*a1157835SDaniel Fojt return 2;
1378*a1157835SDaniel Fojt return with_id;
1379*a1157835SDaniel Fojt }
1380