blob: 04535a16398bcd53fed3c05876cd8c984f14ab01 [file] [log] [blame]
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001/*
2 * hostapd / Configuration helper functions
Dmitry Shmidt344abd32014-01-14 13:17:00 -08003 * Copyright (c) 2003-2014, Jouni Malinen <j@w1.fi>
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004 *
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007 */
8
9#include "utils/includes.h"
10
11#include "utils/common.h"
12#include "crypto/sha1.h"
Roshan Pius3a1667e2018-07-03 15:17:14 -070013#include "crypto/tls.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070014#include "radius/radius_client.h"
15#include "common/ieee802_11_defs.h"
Hai Shalom81f62d82019-07-22 12:10:00 -070016#include "common/ieee802_1x_defs.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070017#include "common/eapol_common.h"
Dmitry Shmidtebd93af2017-02-21 13:40:44 -080018#include "common/dhcp.h"
Hai Shalomc3565922019-10-28 11:58:20 -070019#include "common/sae.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070020#include "eap_common/eap_wsc_common.h"
21#include "eap_server/eap.h"
22#include "wpa_auth.h"
23#include "sta_info.h"
Hai Shalom81f62d82019-07-22 12:10:00 -070024#include "airtime_policy.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070025#include "ap_config.h"
26
27
28static void hostapd_config_free_vlan(struct hostapd_bss_config *bss)
29{
30 struct hostapd_vlan *vlan, *prev;
31
32 vlan = bss->vlan;
33 prev = NULL;
34 while (vlan) {
35 prev = vlan;
36 vlan = vlan->next;
37 os_free(prev);
38 }
39
40 bss->vlan = NULL;
41}
42
43
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070044#ifndef DEFAULT_WPA_DISABLE_EAPOL_KEY_RETRIES
45#define DEFAULT_WPA_DISABLE_EAPOL_KEY_RETRIES 0
46#endif /* DEFAULT_WPA_DISABLE_EAPOL_KEY_RETRIES */
47
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070048void hostapd_config_defaults_bss(struct hostapd_bss_config *bss)
49{
Dmitry Shmidtd80a4012015-11-05 16:35:40 -080050 dl_list_init(&bss->anqp_elem);
51
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070052 bss->logger_syslog_level = HOSTAPD_LEVEL_INFO;
53 bss->logger_stdout_level = HOSTAPD_LEVEL_INFO;
54 bss->logger_syslog = (unsigned int) -1;
55 bss->logger_stdout = (unsigned int) -1;
56
Hai Shalomfdcde762020-04-02 11:19:20 -070057#ifdef CONFIG_WEP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070058 bss->auth_algs = WPA_AUTH_ALG_OPEN | WPA_AUTH_ALG_SHARED;
59
60 bss->wep_rekeying_period = 300;
61 /* use key0 in individual key and key1 in broadcast key */
62 bss->broadcast_key_idx_min = 1;
63 bss->broadcast_key_idx_max = 2;
Hai Shalomfdcde762020-04-02 11:19:20 -070064#else /* CONFIG_WEP */
65 bss->auth_algs = WPA_AUTH_ALG_OPEN;
66#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070067 bss->eap_reauth_period = 3600;
68
69 bss->wpa_group_rekey = 600;
70 bss->wpa_gmk_rekey = 86400;
Hai Shalomfdcde762020-04-02 11:19:20 -070071 bss->wpa_deny_ptk0_rekey = PTK0_REKEY_ALLOW_ALWAYS;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -080072 bss->wpa_group_update_count = 4;
73 bss->wpa_pairwise_update_count = 4;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070074 bss->wpa_disable_eapol_key_retries =
75 DEFAULT_WPA_DISABLE_EAPOL_KEY_RETRIES;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070076 bss->wpa_key_mgmt = WPA_KEY_MGMT_PSK;
Hai Shalomb755a2a2020-04-23 21:49:02 -070077#ifdef CONFIG_NO_TKIP
78 bss->wpa_pairwise = WPA_CIPHER_CCMP;
79 bss->wpa_group = WPA_CIPHER_CCMP;
80#else /* CONFIG_NO_TKIP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070081 bss->wpa_pairwise = WPA_CIPHER_TKIP;
82 bss->wpa_group = WPA_CIPHER_TKIP;
Hai Shalomb755a2a2020-04-23 21:49:02 -070083#endif /* CONFIG_NO_TKIP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070084 bss->rsn_pairwise = 0;
85
86 bss->max_num_sta = MAX_STA_COUNT;
87
88 bss->dtim_period = 2;
89
90 bss->radius_server_auth_port = 1812;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -080091 bss->eap_sim_db_timeout = 1;
Hai Shalomc3565922019-10-28 11:58:20 -070092 bss->eap_sim_id = 3;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070093 bss->ap_max_inactivity = AP_MAX_INACTIVITY;
94 bss->eapol_version = EAPOL_VERSION;
95
96 bss->max_listen_interval = 65535;
97
98 bss->pwd_group = 19; /* ECC: GF(p=256) */
99
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700100 bss->assoc_sa_query_max_timeout = 1000;
101 bss->assoc_sa_query_retry_timeout = 201;
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -0700102 bss->group_mgmt_cipher = WPA_CIPHER_AES_128_CMAC;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700103#ifdef EAP_SERVER_FAST
104 /* both anonymous and authenticated provisioning */
105 bss->eap_fast_prov = 3;
106 bss->pac_key_lifetime = 7 * 24 * 60 * 60;
107 bss->pac_key_refresh_time = 1 * 24 * 60 * 60;
108#endif /* EAP_SERVER_FAST */
109
110 /* Set to -1 as defaults depends on HT in setup */
111 bss->wmm_enabled = -1;
112
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800113#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700114 bss->ft_over_ds = 1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700115 bss->rkh_pos_timeout = 86400;
116 bss->rkh_neg_timeout = 60;
117 bss->rkh_pull_timeout = 1000;
118 bss->rkh_pull_retries = 4;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700119 bss->r0_key_lifetime = 1209600;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800120#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt04949592012-07-19 12:16:46 -0700121
122 bss->radius_das_time_window = 300;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800123
124 bss->sae_anti_clogging_threshold = 5;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700125 bss->sae_sync = 5;
Dmitry Shmidt29333592017-01-09 12:27:11 -0800126
127 bss->gas_frag_limit = 1400;
128
129#ifdef CONFIG_FILS
130 dl_list_init(&bss->fils_realms);
Dmitry Shmidtebd93af2017-02-21 13:40:44 -0800131 bss->fils_hlp_wait_time = 30;
132 bss->dhcp_server_port = DHCP_SERVER_PORT;
133 bss->dhcp_relay_port = DHCP_SERVER_PORT;
Dmitry Shmidt29333592017-01-09 12:27:11 -0800134#endif /* CONFIG_FILS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700135
136 bss->broadcast_deauth = 1;
137
138#ifdef CONFIG_MBO
139 bss->mbo_cell_data_conn_pref = -1;
140#endif /* CONFIG_MBO */
Roshan Pius3a1667e2018-07-03 15:17:14 -0700141
142 /* Disable TLS v1.3 by default for now to avoid interoperability issue.
143 * This can be enabled by default once the implementation has been fully
144 * completed and tested with other implementations. */
145 bss->tls_flags = TLS_CONN_DISABLE_TLSv1_3;
Hai Shalom74f70d42019-02-11 14:42:39 -0800146
Hai Shalomc3565922019-10-28 11:58:20 -0700147 bss->max_auth_rounds = 100;
148 bss->max_auth_rounds_short = 50;
149
Hai Shalom74f70d42019-02-11 14:42:39 -0800150 bss->send_probe_response = 1;
151
152#ifdef CONFIG_HS20
153 bss->hs20_release = (HS20_VERSION >> 4) + 1;
154#endif /* CONFIG_HS20 */
155
Hai Shalom81f62d82019-07-22 12:10:00 -0700156#ifdef CONFIG_MACSEC
157 bss->mka_priority = DEFAULT_PRIO_NOT_KEY_SERVER;
158 bss->macsec_port = 1;
159#endif /* CONFIG_MACSEC */
160
Hai Shalom74f70d42019-02-11 14:42:39 -0800161 /* Default to strict CRL checking. */
162 bss->check_crl_strict = 1;
Hai Shalom899fcc72020-10-19 14:38:18 -0700163
164#ifdef CONFIG_TESTING_OPTIONS
165 bss->sae_commit_status = -1;
166#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700167}
168
169
170struct hostapd_config * hostapd_config_defaults(void)
171{
172#define ecw2cw(ecw) ((1 << (ecw)) - 1)
173
174 struct hostapd_config *conf;
175 struct hostapd_bss_config *bss;
176 const int aCWmin = 4, aCWmax = 10;
177 const struct hostapd_wmm_ac_params ac_bk =
178 { aCWmin, aCWmax, 7, 0, 0 }; /* background traffic */
179 const struct hostapd_wmm_ac_params ac_be =
180 { aCWmin, aCWmax, 3, 0, 0 }; /* best effort traffic */
181 const struct hostapd_wmm_ac_params ac_vi = /* video traffic */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -0700182 { aCWmin - 1, aCWmin, 2, 3008 / 32, 0 };
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700183 const struct hostapd_wmm_ac_params ac_vo = /* voice traffic */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -0700184 { aCWmin - 2, aCWmin - 1, 2, 1504 / 32, 0 };
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700185 const struct hostapd_tx_queue_params txq_bk =
186 { 7, ecw2cw(aCWmin), ecw2cw(aCWmax), 0 };
187 const struct hostapd_tx_queue_params txq_be =
188 { 3, ecw2cw(aCWmin), 4 * (ecw2cw(aCWmin) + 1) - 1, 0};
189 const struct hostapd_tx_queue_params txq_vi =
190 { 1, (ecw2cw(aCWmin) + 1) / 2 - 1, ecw2cw(aCWmin), 30};
191 const struct hostapd_tx_queue_params txq_vo =
192 { 1, (ecw2cw(aCWmin) + 1) / 4 - 1,
193 (ecw2cw(aCWmin) + 1) / 2 - 1, 15};
194
195#undef ecw2cw
196
197 conf = os_zalloc(sizeof(*conf));
198 bss = os_zalloc(sizeof(*bss));
199 if (conf == NULL || bss == NULL) {
200 wpa_printf(MSG_ERROR, "Failed to allocate memory for "
201 "configuration data.");
202 os_free(conf);
203 os_free(bss);
204 return NULL;
205 }
Dmitry Shmidtcce06662013-11-04 18:44:24 -0800206 conf->bss = os_calloc(1, sizeof(struct hostapd_bss_config *));
207 if (conf->bss == NULL) {
208 os_free(conf);
209 os_free(bss);
210 return NULL;
211 }
212 conf->bss[0] = bss;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700213
214 bss->radius = os_zalloc(sizeof(*bss->radius));
215 if (bss->radius == NULL) {
Dmitry Shmidt97672262014-02-03 13:02:54 -0800216 os_free(conf->bss);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700217 os_free(conf);
218 os_free(bss);
219 return NULL;
220 }
221
222 hostapd_config_defaults_bss(bss);
223
224 conf->num_bss = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700225
226 conf->beacon_int = 100;
Hai Shalom021b0b52019-04-10 11:17:58 -0700227 conf->rts_threshold = -2; /* use driver default: 2347 */
228 conf->fragm_threshold = -2; /* user driver default: 2346 */
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800229 /* Set to invalid value means do not add Power Constraint IE */
230 conf->local_pwr_constraint = -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700231
232 conf->wmm_ac_params[0] = ac_be;
233 conf->wmm_ac_params[1] = ac_bk;
234 conf->wmm_ac_params[2] = ac_vi;
235 conf->wmm_ac_params[3] = ac_vo;
236
237 conf->tx_queue[0] = txq_vo;
238 conf->tx_queue[1] = txq_vi;
239 conf->tx_queue[2] = txq_be;
240 conf->tx_queue[3] = txq_bk;
241
242 conf->ht_capab = HT_CAP_INFO_SMPS_DISABLED;
243
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800244 conf->ap_table_max_size = 255;
245 conf->ap_table_expiration_time = 60;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800246 conf->track_sta_max_age = 180;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800247
Dmitry Shmidt8da800a2013-04-24 12:57:01 -0700248#ifdef CONFIG_TESTING_OPTIONS
Dmitry Shmidt7832adb2014-04-29 10:53:02 -0700249 conf->ignore_probe_probability = 0.0;
250 conf->ignore_auth_probability = 0.0;
251 conf->ignore_assoc_probability = 0.0;
252 conf->ignore_reassoc_probability = 0.0;
253 conf->corrupt_gtk_rekey_mic_probability = 0.0;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800254 conf->ecsa_ie_only = 0;
Dmitry Shmidt8da800a2013-04-24 12:57:01 -0700255#endif /* CONFIG_TESTING_OPTIONS */
256
Dmitry Shmidtdda10c22015-03-24 16:05:01 -0700257 conf->acs = 0;
258 conf->acs_ch_list.num = 0;
Dmitry Shmidt391c59f2013-09-03 12:16:28 -0700259#ifdef CONFIG_ACS
260 conf->acs_num_scans = 5;
261#endif /* CONFIG_ACS */
262
Hai Shalom81f62d82019-07-22 12:10:00 -0700263#ifdef CONFIG_IEEE80211AX
264 conf->he_op.he_rts_threshold = HE_OPERATION_RTS_THRESHOLD_MASK >>
265 HE_OPERATION_RTS_THRESHOLD_OFFSET;
266 /* Set default basic MCS/NSS set to single stream MCS 0-7 */
267 conf->he_op.he_basic_mcs_nss_set = 0xfffc;
Hai Shalomfdcde762020-04-02 11:19:20 -0700268 conf->he_op.he_bss_color_disabled = 1;
269 conf->he_op.he_bss_color_partial = 0;
270 conf->he_op.he_bss_color = 1;
Hai Shalom81f62d82019-07-22 12:10:00 -0700271#endif /* CONFIG_IEEE80211AX */
272
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700273 /* The third octet of the country string uses an ASCII space character
274 * by default to indicate that the regulations encompass all
275 * environments for the current frequency band in the country. */
276 conf->country[2] = ' ';
277
Hai Shalom74f70d42019-02-11 14:42:39 -0800278 conf->rssi_reject_assoc_rssi = 0;
279 conf->rssi_reject_assoc_timeout = 30;
280
Hai Shalom81f62d82019-07-22 12:10:00 -0700281#ifdef CONFIG_AIRTIME_POLICY
282 conf->airtime_update_interval = AIRTIME_DEFAULT_UPDATE_INTERVAL;
283#endif /* CONFIG_AIRTIME_POLICY */
284
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700285 return conf;
286}
287
288
289int hostapd_mac_comp(const void *a, const void *b)
290{
291 return os_memcmp(a, b, sizeof(macaddr));
292}
293
294
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700295static int hostapd_config_read_wpa_psk(const char *fname,
296 struct hostapd_ssid *ssid)
297{
298 FILE *f;
299 char buf[128], *pos;
Hai Shalom74f70d42019-02-11 14:42:39 -0800300 const char *keyid;
301 char *context;
302 char *context2;
303 char *token;
304 char *name;
305 char *value;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700306 int line = 0, ret = 0, len, ok;
307 u8 addr[ETH_ALEN];
308 struct hostapd_wpa_psk *psk;
309
310 if (!fname)
311 return 0;
312
313 f = fopen(fname, "r");
314 if (!f) {
315 wpa_printf(MSG_ERROR, "WPA PSK file '%s' not found.", fname);
316 return -1;
317 }
318
319 while (fgets(buf, sizeof(buf), f)) {
Hai Shalom021b0b52019-04-10 11:17:58 -0700320 int vlan_id = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -0700321 int wps = 0;
Hai Shalom021b0b52019-04-10 11:17:58 -0700322
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700323 line++;
324
325 if (buf[0] == '#')
326 continue;
327 pos = buf;
328 while (*pos != '\0') {
329 if (*pos == '\n') {
330 *pos = '\0';
331 break;
332 }
333 pos++;
334 }
335 if (buf[0] == '\0')
336 continue;
337
Hai Shalom74f70d42019-02-11 14:42:39 -0800338 context = NULL;
339 keyid = NULL;
340 while ((token = str_token(buf, " ", &context))) {
341 if (!os_strchr(token, '='))
342 break;
343 context2 = NULL;
344 name = str_token(token, "=", &context2);
Hai Shalom021b0b52019-04-10 11:17:58 -0700345 if (!name)
346 break;
Hai Shalom74f70d42019-02-11 14:42:39 -0800347 value = str_token(token, "", &context2);
348 if (!value)
349 value = "";
350 if (!os_strcmp(name, "keyid")) {
351 keyid = value;
Hai Shalomfdcde762020-04-02 11:19:20 -0700352 } else if (!os_strcmp(name, "wps")) {
353 wps = atoi(value);
Hai Shalom021b0b52019-04-10 11:17:58 -0700354 } else if (!os_strcmp(name, "vlanid")) {
355 vlan_id = atoi(value);
Hai Shalom74f70d42019-02-11 14:42:39 -0800356 } else {
357 wpa_printf(MSG_ERROR,
358 "Unrecognized '%s=%s' on line %d in '%s'",
359 name, value, line, fname);
360 ret = -1;
361 break;
362 }
363 }
364
365 if (ret == -1)
366 break;
367
368 if (!token)
369 token = "";
370 if (hwaddr_aton(token, addr)) {
Hai Shalomfdcde762020-04-02 11:19:20 -0700371 wpa_printf(MSG_ERROR,
372 "Invalid MAC address '%s' on line %d in '%s'",
373 token, line, fname);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700374 ret = -1;
375 break;
376 }
377
378 psk = os_zalloc(sizeof(*psk));
379 if (psk == NULL) {
380 wpa_printf(MSG_ERROR, "WPA PSK allocation failed");
381 ret = -1;
382 break;
383 }
Hai Shalom021b0b52019-04-10 11:17:58 -0700384 psk->vlan_id = vlan_id;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700385 if (is_zero_ether_addr(addr))
386 psk->group = 1;
387 else
388 os_memcpy(psk->addr, addr, ETH_ALEN);
389
Hai Shalom74f70d42019-02-11 14:42:39 -0800390 pos = str_token(buf, "", &context);
391 if (!pos) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700392 wpa_printf(MSG_ERROR, "No PSK on line %d in '%s'",
393 line, fname);
394 os_free(psk);
395 ret = -1;
396 break;
397 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700398
399 ok = 0;
400 len = os_strlen(pos);
Hai Shalomfdcde762020-04-02 11:19:20 -0700401 if (len == 2 * PMK_LEN &&
402 hexstr2bin(pos, psk->psk, PMK_LEN) == 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700403 ok = 1;
Hai Shalomfdcde762020-04-02 11:19:20 -0700404 else if (len >= 8 && len < 64 &&
405 pbkdf2_sha1(pos, ssid->ssid, ssid->ssid_len,
406 4096, psk->psk, PMK_LEN) == 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700407 ok = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700408 if (!ok) {
Hai Shalomfdcde762020-04-02 11:19:20 -0700409 wpa_printf(MSG_ERROR,
410 "Invalid PSK '%s' on line %d in '%s'",
411 pos, line, fname);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700412 os_free(psk);
413 ret = -1;
414 break;
415 }
416
Hai Shalom74f70d42019-02-11 14:42:39 -0800417 if (keyid) {
418 len = os_strlcpy(psk->keyid, keyid, sizeof(psk->keyid));
419 if ((size_t) len >= sizeof(psk->keyid)) {
420 wpa_printf(MSG_ERROR,
421 "PSK keyid too long on line %d in '%s'",
422 line, fname);
423 os_free(psk);
424 ret = -1;
425 break;
426 }
427 }
428
Hai Shalomfdcde762020-04-02 11:19:20 -0700429 psk->wps = wps;
430
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700431 psk->next = ssid->wpa_psk;
432 ssid->wpa_psk = psk;
433 }
434
435 fclose(f);
436
437 return ret;
438}
439
440
441static int hostapd_derive_psk(struct hostapd_ssid *ssid)
442{
443 ssid->wpa_psk = os_zalloc(sizeof(struct hostapd_wpa_psk));
444 if (ssid->wpa_psk == NULL) {
445 wpa_printf(MSG_ERROR, "Unable to alloc space for PSK");
446 return -1;
447 }
448 wpa_hexdump_ascii(MSG_DEBUG, "SSID",
449 (u8 *) ssid->ssid, ssid->ssid_len);
450 wpa_hexdump_ascii_key(MSG_DEBUG, "PSK (ASCII passphrase)",
451 (u8 *) ssid->wpa_passphrase,
452 os_strlen(ssid->wpa_passphrase));
453 pbkdf2_sha1(ssid->wpa_passphrase,
454 ssid->ssid, ssid->ssid_len,
455 4096, ssid->wpa_psk->psk, PMK_LEN);
456 wpa_hexdump_key(MSG_DEBUG, "PSK (from passphrase)",
457 ssid->wpa_psk->psk, PMK_LEN);
458 return 0;
459}
460
461
Hai Shalomc3565922019-10-28 11:58:20 -0700462int hostapd_setup_sae_pt(struct hostapd_bss_config *conf)
463{
464#ifdef CONFIG_SAE
465 struct hostapd_ssid *ssid = &conf->ssid;
466 struct sae_password_entry *pw;
467
Hai Shalom899fcc72020-10-19 14:38:18 -0700468 if ((conf->sae_pwe == 0 && !hostapd_sae_pw_id_in_use(conf) &&
469 !hostapd_sae_pk_in_use(conf)) ||
Hai Shalomfdcde762020-04-02 11:19:20 -0700470 conf->sae_pwe == 3 ||
471 !wpa_key_mgmt_sae(conf->wpa_key_mgmt))
Hai Shalomc3565922019-10-28 11:58:20 -0700472 return 0; /* PT not needed */
473
474 sae_deinit_pt(ssid->pt);
475 ssid->pt = NULL;
476 if (ssid->wpa_passphrase) {
477 ssid->pt = sae_derive_pt(conf->sae_groups, ssid->ssid,
478 ssid->ssid_len,
479 (const u8 *) ssid->wpa_passphrase,
480 os_strlen(ssid->wpa_passphrase),
481 NULL);
482 if (!ssid->pt)
483 return -1;
484 }
485
486 for (pw = conf->sae_passwords; pw; pw = pw->next) {
487 sae_deinit_pt(pw->pt);
488 pw->pt = sae_derive_pt(conf->sae_groups, ssid->ssid,
489 ssid->ssid_len,
490 (const u8 *) pw->password,
491 os_strlen(pw->password),
492 pw->identifier);
493 if (!pw->pt)
494 return -1;
495 }
496#endif /* CONFIG_SAE */
497
498 return 0;
499}
500
501
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700502int hostapd_setup_wpa_psk(struct hostapd_bss_config *conf)
503{
504 struct hostapd_ssid *ssid = &conf->ssid;
505
Hai Shalomc3565922019-10-28 11:58:20 -0700506 if (hostapd_setup_sae_pt(conf) < 0)
507 return -1;
508
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700509 if (ssid->wpa_passphrase != NULL) {
510 if (ssid->wpa_psk != NULL) {
511 wpa_printf(MSG_DEBUG, "Using pre-configured WPA PSK "
512 "instead of passphrase");
513 } else {
514 wpa_printf(MSG_DEBUG, "Deriving WPA PSK based on "
515 "passphrase");
516 if (hostapd_derive_psk(ssid) < 0)
517 return -1;
518 }
519 ssid->wpa_psk->group = 1;
520 }
521
Dmitry Shmidt29333592017-01-09 12:27:11 -0800522 return hostapd_config_read_wpa_psk(ssid->wpa_psk_file, &conf->ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700523}
524
525
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700526static void hostapd_config_free_radius(struct hostapd_radius_server *servers,
527 int num_servers)
528{
529 int i;
530
531 for (i = 0; i < num_servers; i++) {
532 os_free(servers[i].shared_secret);
533 }
534 os_free(servers);
535}
536
537
Dmitry Shmidt04949592012-07-19 12:16:46 -0700538struct hostapd_radius_attr *
539hostapd_config_get_radius_attr(struct hostapd_radius_attr *attr, u8 type)
540{
541 for (; attr; attr = attr->next) {
542 if (attr->type == type)
543 return attr;
544 }
545 return NULL;
546}
547
548
Hai Shalomc3565922019-10-28 11:58:20 -0700549struct hostapd_radius_attr * hostapd_parse_radius_attr(const char *value)
550{
551 const char *pos;
552 char syntax;
553 struct hostapd_radius_attr *attr;
554 size_t len;
555
556 attr = os_zalloc(sizeof(*attr));
557 if (!attr)
558 return NULL;
559
560 attr->type = atoi(value);
561
562 pos = os_strchr(value, ':');
563 if (!pos) {
564 attr->val = wpabuf_alloc(1);
565 if (!attr->val) {
566 os_free(attr);
567 return NULL;
568 }
569 wpabuf_put_u8(attr->val, 0);
570 return attr;
571 }
572
573 pos++;
574 if (pos[0] == '\0' || pos[1] != ':') {
575 os_free(attr);
576 return NULL;
577 }
578 syntax = *pos++;
579 pos++;
580
581 switch (syntax) {
582 case 's':
583 attr->val = wpabuf_alloc_copy(pos, os_strlen(pos));
584 break;
585 case 'x':
586 len = os_strlen(pos);
587 if (len & 1)
588 break;
589 len /= 2;
590 attr->val = wpabuf_alloc(len);
591 if (!attr->val)
592 break;
593 if (hexstr2bin(pos, wpabuf_put(attr->val, len), len) < 0) {
594 wpabuf_free(attr->val);
595 os_free(attr);
596 return NULL;
597 }
598 break;
599 case 'd':
600 attr->val = wpabuf_alloc(4);
601 if (attr->val)
602 wpabuf_put_be32(attr->val, atoi(pos));
603 break;
604 default:
605 os_free(attr);
606 return NULL;
607 }
608
609 if (!attr->val) {
610 os_free(attr);
611 return NULL;
612 }
613
614 return attr;
615}
616
617
618void hostapd_config_free_radius_attr(struct hostapd_radius_attr *attr)
Dmitry Shmidt04949592012-07-19 12:16:46 -0700619{
620 struct hostapd_radius_attr *prev;
621
622 while (attr) {
623 prev = attr;
624 attr = attr->next;
625 wpabuf_free(prev->val);
626 os_free(prev);
627 }
628}
629
630
Dmitry Shmidt818ea482014-03-10 13:15:21 -0700631void hostapd_config_free_eap_user(struct hostapd_eap_user *user)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700632{
Dmitry Shmidt818ea482014-03-10 13:15:21 -0700633 hostapd_config_free_radius_attr(user->accept_attr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700634 os_free(user->identity);
Dmitry Shmidtc2817022014-07-02 10:32:10 -0700635 bin_clear_free(user->password, user->password_len);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700636 bin_clear_free(user->salt, user->salt_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700637 os_free(user);
638}
639
640
Dmitry Shmidt29333592017-01-09 12:27:11 -0800641void hostapd_config_free_eap_users(struct hostapd_eap_user *user)
642{
643 struct hostapd_eap_user *prev_user;
644
645 while (user) {
646 prev_user = user;
647 user = user->next;
648 hostapd_config_free_eap_user(prev_user);
649 }
650}
651
652
Hai Shalomfdcde762020-04-02 11:19:20 -0700653#ifdef CONFIG_WEP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700654static void hostapd_config_free_wep(struct hostapd_wep_keys *keys)
655{
656 int i;
657 for (i = 0; i < NUM_WEP_KEYS; i++) {
Dmitry Shmidtc2817022014-07-02 10:32:10 -0700658 bin_clear_free(keys->key[i], keys->len[i]);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700659 keys->key[i] = NULL;
660 }
661}
Hai Shalomfdcde762020-04-02 11:19:20 -0700662#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700663
664
Dmitry Shmidt7f656022015-02-25 14:36:37 -0800665void hostapd_config_clear_wpa_psk(struct hostapd_wpa_psk **l)
666{
667 struct hostapd_wpa_psk *psk, *tmp;
668
669 for (psk = *l; psk;) {
670 tmp = psk;
671 psk = psk->next;
672 bin_clear_free(tmp, sizeof(*tmp));
673 }
674 *l = NULL;
675}
676
677
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800678static void hostapd_config_free_anqp_elem(struct hostapd_bss_config *conf)
679{
680 struct anqp_element *elem;
681
682 while ((elem = dl_list_first(&conf->anqp_elem, struct anqp_element,
683 list))) {
684 dl_list_del(&elem->list);
685 wpabuf_free(elem->payload);
686 os_free(elem);
687 }
688}
689
690
Dmitry Shmidt29333592017-01-09 12:27:11 -0800691static void hostapd_config_free_fils_realms(struct hostapd_bss_config *conf)
692{
693#ifdef CONFIG_FILS
694 struct fils_realm *realm;
695
696 while ((realm = dl_list_first(&conf->fils_realms, struct fils_realm,
697 list))) {
698 dl_list_del(&realm->list);
699 os_free(realm);
700 }
701#endif /* CONFIG_FILS */
702}
703
704
Roshan Pius3a1667e2018-07-03 15:17:14 -0700705static void hostapd_config_free_sae_passwords(struct hostapd_bss_config *conf)
706{
707 struct sae_password_entry *pw, *tmp;
708
709 pw = conf->sae_passwords;
710 conf->sae_passwords = NULL;
711 while (pw) {
712 tmp = pw;
713 pw = pw->next;
714 str_clear_free(tmp->password);
715 os_free(tmp->identifier);
Hai Shalomc3565922019-10-28 11:58:20 -0700716#ifdef CONFIG_SAE
717 sae_deinit_pt(tmp->pt);
718#endif /* CONFIG_SAE */
Hai Shalom899fcc72020-10-19 14:38:18 -0700719#ifdef CONFIG_SAE_PK
720 sae_deinit_pk(tmp->pk);
721#endif /* CONFIG_SAE_PK */
Roshan Pius3a1667e2018-07-03 15:17:14 -0700722 os_free(tmp);
723 }
724}
725
726
Hai Shalom81f62d82019-07-22 12:10:00 -0700727#ifdef CONFIG_DPP2
728static void hostapd_dpp_controller_conf_free(struct dpp_controller_conf *conf)
729{
730 struct dpp_controller_conf *prev;
731
732 while (conf) {
733 prev = conf;
734 conf = conf->next;
735 os_free(prev);
736 }
737}
738#endif /* CONFIG_DPP2 */
739
740
Dmitry Shmidtcce06662013-11-04 18:44:24 -0800741void hostapd_config_free_bss(struct hostapd_bss_config *conf)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700742{
Hai Shalom81f62d82019-07-22 12:10:00 -0700743#if defined(CONFIG_WPS) || defined(CONFIG_HS20)
744 size_t i;
745#endif
746
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700747 if (conf == NULL)
748 return;
749
Dmitry Shmidt7f656022015-02-25 14:36:37 -0800750 hostapd_config_clear_wpa_psk(&conf->ssid.wpa_psk);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700751
Dmitry Shmidtc2817022014-07-02 10:32:10 -0700752 str_clear_free(conf->ssid.wpa_passphrase);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700753 os_free(conf->ssid.wpa_psk_file);
Hai Shalomfdcde762020-04-02 11:19:20 -0700754#ifdef CONFIG_WEP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700755 hostapd_config_free_wep(&conf->ssid.wep);
Hai Shalomfdcde762020-04-02 11:19:20 -0700756#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700757#ifdef CONFIG_FULL_DYNAMIC_VLAN
758 os_free(conf->ssid.vlan_tagged_interface);
759#endif /* CONFIG_FULL_DYNAMIC_VLAN */
Hai Shalomc3565922019-10-28 11:58:20 -0700760#ifdef CONFIG_SAE
761 sae_deinit_pt(conf->ssid.pt);
762#endif /* CONFIG_SAE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700763
Dmitry Shmidt29333592017-01-09 12:27:11 -0800764 hostapd_config_free_eap_users(conf->eap_user);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800765 os_free(conf->eap_user_sqlite);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700766
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700767 os_free(conf->eap_req_id_text);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800768 os_free(conf->erp_domain);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700769 os_free(conf->accept_mac);
770 os_free(conf->deny_mac);
771 os_free(conf->nas_identifier);
Dmitry Shmidtcce06662013-11-04 18:44:24 -0800772 if (conf->radius) {
773 hostapd_config_free_radius(conf->radius->auth_servers,
774 conf->radius->num_auth_servers);
775 hostapd_config_free_radius(conf->radius->acct_servers,
776 conf->radius->num_acct_servers);
777 }
Dmitry Shmidt04949592012-07-19 12:16:46 -0700778 hostapd_config_free_radius_attr(conf->radius_auth_req_attr);
779 hostapd_config_free_radius_attr(conf->radius_acct_req_attr);
Hai Shalomc3565922019-10-28 11:58:20 -0700780 os_free(conf->radius_req_attr_sqlite);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700781 os_free(conf->rsn_preauth_interfaces);
782 os_free(conf->ctrl_interface);
783 os_free(conf->ca_cert);
784 os_free(conf->server_cert);
Hai Shalom81f62d82019-07-22 12:10:00 -0700785 os_free(conf->server_cert2);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700786 os_free(conf->private_key);
Hai Shalom81f62d82019-07-22 12:10:00 -0700787 os_free(conf->private_key2);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700788 os_free(conf->private_key_passwd);
Hai Shalom81f62d82019-07-22 12:10:00 -0700789 os_free(conf->private_key_passwd2);
Hai Shalom021b0b52019-04-10 11:17:58 -0700790 os_free(conf->check_cert_subject);
Dmitry Shmidt34af3062013-07-11 10:46:32 -0700791 os_free(conf->ocsp_stapling_response);
Dmitry Shmidt014a3ff2015-12-28 13:27:49 -0800792 os_free(conf->ocsp_stapling_response_multi);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700793 os_free(conf->dh_file);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800794 os_free(conf->openssl_ciphers);
Hai Shalom74f70d42019-02-11 14:42:39 -0800795 os_free(conf->openssl_ecdh_curves);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700796 os_free(conf->pac_opaque_encr_key);
797 os_free(conf->eap_fast_a_id);
798 os_free(conf->eap_fast_a_id_info);
799 os_free(conf->eap_sim_db);
800 os_free(conf->radius_server_clients);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700801 os_free(conf->radius);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700802 os_free(conf->radius_das_shared_secret);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700803 hostapd_config_free_vlan(conf);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800804 os_free(conf->time_zone);
805
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800806#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700807 {
808 struct ft_remote_r0kh *r0kh, *r0kh_prev;
809 struct ft_remote_r1kh *r1kh, *r1kh_prev;
810
811 r0kh = conf->r0kh_list;
812 conf->r0kh_list = NULL;
813 while (r0kh) {
814 r0kh_prev = r0kh;
815 r0kh = r0kh->next;
816 os_free(r0kh_prev);
817 }
818
819 r1kh = conf->r1kh_list;
820 conf->r1kh_list = NULL;
821 while (r1kh) {
822 r1kh_prev = r1kh;
823 r1kh = r1kh->next;
824 os_free(r1kh_prev);
825 }
826 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800827#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700828
829#ifdef CONFIG_WPS
830 os_free(conf->wps_pin_requests);
831 os_free(conf->device_name);
832 os_free(conf->manufacturer);
833 os_free(conf->model_name);
834 os_free(conf->model_number);
835 os_free(conf->serial_number);
836 os_free(conf->config_methods);
837 os_free(conf->ap_pin);
838 os_free(conf->extra_cred);
839 os_free(conf->ap_settings);
Hai Shalom021b0b52019-04-10 11:17:58 -0700840 hostapd_config_clear_wpa_psk(&conf->multi_ap_backhaul_ssid.wpa_psk);
841 str_clear_free(conf->multi_ap_backhaul_ssid.wpa_passphrase);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700842 os_free(conf->upnp_iface);
843 os_free(conf->friendly_name);
844 os_free(conf->manufacturer_url);
845 os_free(conf->model_description);
846 os_free(conf->model_url);
847 os_free(conf->upc);
Hai Shalom81f62d82019-07-22 12:10:00 -0700848 for (i = 0; i < MAX_WPS_VENDOR_EXTENSIONS; i++)
849 wpabuf_free(conf->wps_vendor_ext[i]);
Hai Shalomfdcde762020-04-02 11:19:20 -0700850 wpabuf_free(conf->wps_application_ext);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700851 wpabuf_free(conf->wps_nfc_dh_pubkey);
852 wpabuf_free(conf->wps_nfc_dh_privkey);
853 wpabuf_free(conf->wps_nfc_dev_pw);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700854#endif /* CONFIG_WPS */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800855
856 os_free(conf->roaming_consortium);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700857 os_free(conf->venue_name);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700858 os_free(conf->venue_url);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700859 os_free(conf->nai_realm_data);
860 os_free(conf->network_auth_type);
861 os_free(conf->anqp_3gpp_cell_net);
862 os_free(conf->domain_name);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800863 hostapd_config_free_anqp_elem(conf);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800864
865#ifdef CONFIG_RADIUS_TEST
866 os_free(conf->dump_msk_file);
867#endif /* CONFIG_RADIUS_TEST */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700868
869#ifdef CONFIG_HS20
870 os_free(conf->hs20_oper_friendly_name);
871 os_free(conf->hs20_wan_metrics);
872 os_free(conf->hs20_connection_capability);
873 os_free(conf->hs20_operating_class);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800874 os_free(conf->hs20_icons);
875 if (conf->hs20_osu_providers) {
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800876 for (i = 0; i < conf->hs20_osu_providers_count; i++) {
877 struct hs20_osu_provider *p;
878 size_t j;
879 p = &conf->hs20_osu_providers[i];
880 os_free(p->friendly_name);
881 os_free(p->server_uri);
882 os_free(p->method_list);
883 for (j = 0; j < p->icons_count; j++)
884 os_free(p->icons[j]);
885 os_free(p->icons);
886 os_free(p->osu_nai);
Hai Shalom39ba6fc2019-01-22 12:40:38 -0800887 os_free(p->osu_nai2);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800888 os_free(p->service_desc);
889 }
890 os_free(conf->hs20_osu_providers);
891 }
Roshan Pius3a1667e2018-07-03 15:17:14 -0700892 if (conf->hs20_operator_icon) {
Roshan Pius3a1667e2018-07-03 15:17:14 -0700893 for (i = 0; i < conf->hs20_operator_icon_count; i++)
894 os_free(conf->hs20_operator_icon[i]);
895 os_free(conf->hs20_operator_icon);
896 }
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800897 os_free(conf->subscr_remediation_url);
Hai Shalom74f70d42019-02-11 14:42:39 -0800898 os_free(conf->hs20_sim_provisioning_url);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700899 os_free(conf->t_c_filename);
900 os_free(conf->t_c_server_url);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700901#endif /* CONFIG_HS20 */
902
903 wpabuf_free(conf->vendor_elements);
Dmitry Shmidt849734c2016-05-27 09:59:01 -0700904 wpabuf_free(conf->assocresp_elements);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800905
906 os_free(conf->sae_groups);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700907#ifdef CONFIG_OWE
908 os_free(conf->owe_groups);
909#endif /* CONFIG_OWE */
Dmitry Shmidt34af3062013-07-11 10:46:32 -0700910
Dmitry Shmidt0207e232014-09-03 14:58:37 -0700911 os_free(conf->wowlan_triggers);
912
Dmitry Shmidt34af3062013-07-11 10:46:32 -0700913 os_free(conf->server_id);
Dmitry Shmidtcce06662013-11-04 18:44:24 -0800914
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800915#ifdef CONFIG_TESTING_OPTIONS
916 wpabuf_free(conf->own_ie_override);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700917 wpabuf_free(conf->sae_commit_override);
Hai Shalomfdcde762020-04-02 11:19:20 -0700918 wpabuf_free(conf->rsne_override_eapol);
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -0800919 wpabuf_free(conf->rsnxe_override_eapol);
Hai Shalomfdcde762020-04-02 11:19:20 -0700920 wpabuf_free(conf->rsne_override_ft);
921 wpabuf_free(conf->rsnxe_override_ft);
922 wpabuf_free(conf->gtk_rsc_override);
923 wpabuf_free(conf->igtk_rsc_override);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800924#endif /* CONFIG_TESTING_OPTIONS */
925
926 os_free(conf->no_probe_resp_if_seen_on);
927 os_free(conf->no_auth_if_seen_on);
928
Dmitry Shmidt29333592017-01-09 12:27:11 -0800929 hostapd_config_free_fils_realms(conf);
930
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700931#ifdef CONFIG_DPP
Hai Shalomc3565922019-10-28 11:58:20 -0700932 os_free(conf->dpp_name);
933 os_free(conf->dpp_mud_url);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700934 os_free(conf->dpp_connector);
935 wpabuf_free(conf->dpp_netaccesskey);
936 wpabuf_free(conf->dpp_csign);
Hai Shalom81f62d82019-07-22 12:10:00 -0700937#ifdef CONFIG_DPP2
938 hostapd_dpp_controller_conf_free(conf->dpp_controller);
939#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700940#endif /* CONFIG_DPP */
941
Roshan Pius3a1667e2018-07-03 15:17:14 -0700942 hostapd_config_free_sae_passwords(conf);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700943
Hai Shalom81f62d82019-07-22 12:10:00 -0700944#ifdef CONFIG_AIRTIME_POLICY
945 {
946 struct airtime_sta_weight *wt, *wt_prev;
947
948 wt = conf->airtime_weight_list;
949 conf->airtime_weight_list = NULL;
950 while (wt) {
951 wt_prev = wt;
952 wt = wt->next;
953 os_free(wt_prev);
954 }
955 }
956#endif /* CONFIG_AIRTIME_POLICY */
957
Dmitry Shmidtcce06662013-11-04 18:44:24 -0800958 os_free(conf);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700959}
960
961
962/**
963 * hostapd_config_free - Free hostapd configuration
964 * @conf: Configuration data from hostapd_config_read().
965 */
966void hostapd_config_free(struct hostapd_config *conf)
967{
968 size_t i;
969
970 if (conf == NULL)
971 return;
972
973 for (i = 0; i < conf->num_bss; i++)
Dmitry Shmidtcce06662013-11-04 18:44:24 -0800974 hostapd_config_free_bss(conf->bss[i]);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700975 os_free(conf->bss);
976 os_free(conf->supported_rates);
977 os_free(conf->basic_rates);
Dmitry Shmidtdda10c22015-03-24 16:05:01 -0700978 os_free(conf->acs_ch_list.range);
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -0800979 os_free(conf->acs_freq_list.range);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800980 os_free(conf->driver_params);
Dmitry Shmidt7f656022015-02-25 14:36:37 -0800981#ifdef CONFIG_ACS
982 os_free(conf->acs_chan_bias);
983#endif /* CONFIG_ACS */
Dmitry Shmidt849734c2016-05-27 09:59:01 -0700984 wpabuf_free(conf->lci);
985 wpabuf_free(conf->civic);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700986
987 os_free(conf);
988}
989
990
991/**
992 * hostapd_maclist_found - Find a MAC address from a list
993 * @list: MAC address list
994 * @num_entries: Number of addresses in the list
995 * @addr: Address to search for
996 * @vlan_id: Buffer for returning VLAN ID or %NULL if not needed
997 * Returns: 1 if address is in the list or 0 if not.
998 *
999 * Perform a binary search for given MAC address from a pre-sorted list.
1000 */
1001int hostapd_maclist_found(struct mac_acl_entry *list, int num_entries,
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001002 const u8 *addr, struct vlan_description *vlan_id)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001003{
1004 int start, end, middle, res;
1005
1006 start = 0;
1007 end = num_entries - 1;
1008
1009 while (start <= end) {
1010 middle = (start + end) / 2;
1011 res = os_memcmp(list[middle].addr, addr, ETH_ALEN);
1012 if (res == 0) {
1013 if (vlan_id)
1014 *vlan_id = list[middle].vlan_id;
1015 return 1;
1016 }
1017 if (res < 0)
1018 start = middle + 1;
1019 else
1020 end = middle - 1;
1021 }
1022
1023 return 0;
1024}
1025
1026
1027int hostapd_rate_found(int *list, int rate)
1028{
1029 int i;
1030
1031 if (list == NULL)
1032 return 0;
1033
1034 for (i = 0; list[i] >= 0; i++)
1035 if (list[i] == rate)
1036 return 1;
1037
1038 return 0;
1039}
1040
1041
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001042int hostapd_vlan_valid(struct hostapd_vlan *vlan,
1043 struct vlan_description *vlan_desc)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001044{
1045 struct hostapd_vlan *v = vlan;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001046 int i;
1047
1048 if (!vlan_desc->notempty || vlan_desc->untagged < 0 ||
1049 vlan_desc->untagged > MAX_VLAN_ID)
1050 return 0;
1051 for (i = 0; i < MAX_NUM_TAGGED_VLAN; i++) {
1052 if (vlan_desc->tagged[i] < 0 ||
1053 vlan_desc->tagged[i] > MAX_VLAN_ID)
1054 return 0;
1055 }
1056 if (!vlan_desc->untagged && !vlan_desc->tagged[0])
1057 return 0;
1058
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001059 while (v) {
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001060 if (!vlan_compare(&v->vlan_desc, vlan_desc) ||
1061 v->vlan_id == VLAN_ID_WILDCARD)
Dmitry Shmidt34af3062013-07-11 10:46:32 -07001062 return 1;
1063 v = v->next;
1064 }
1065 return 0;
1066}
1067
1068
1069const char * hostapd_get_vlan_id_ifname(struct hostapd_vlan *vlan, int vlan_id)
1070{
1071 struct hostapd_vlan *v = vlan;
1072 while (v) {
1073 if (v->vlan_id == vlan_id)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001074 return v->ifname;
1075 v = v->next;
1076 }
1077 return NULL;
1078}
1079
1080
1081const u8 * hostapd_get_psk(const struct hostapd_bss_config *conf,
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07001082 const u8 *addr, const u8 *p2p_dev_addr,
Hai Shalom021b0b52019-04-10 11:17:58 -07001083 const u8 *prev_psk, int *vlan_id)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001084{
1085 struct hostapd_wpa_psk *psk;
1086 int next_ok = prev_psk == NULL;
1087
Hai Shalom021b0b52019-04-10 11:17:58 -07001088 if (vlan_id)
1089 *vlan_id = 0;
1090
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07001091 if (p2p_dev_addr && !is_zero_ether_addr(p2p_dev_addr)) {
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07001092 wpa_printf(MSG_DEBUG, "Searching a PSK for " MACSTR
1093 " p2p_dev_addr=" MACSTR " prev_psk=%p",
1094 MAC2STR(addr), MAC2STR(p2p_dev_addr), prev_psk);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07001095 addr = NULL; /* Use P2P Device Address for matching */
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07001096 } else {
1097 wpa_printf(MSG_DEBUG, "Searching a PSK for " MACSTR
1098 " prev_psk=%p",
1099 MAC2STR(addr), prev_psk);
1100 }
1101
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001102 for (psk = conf->ssid.wpa_psk; psk != NULL; psk = psk->next) {
1103 if (next_ok &&
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07001104 (psk->group ||
1105 (addr && os_memcmp(psk->addr, addr, ETH_ALEN) == 0) ||
1106 (!addr && p2p_dev_addr &&
1107 os_memcmp(psk->p2p_dev_addr, p2p_dev_addr, ETH_ALEN) ==
Hai Shalom021b0b52019-04-10 11:17:58 -07001108 0))) {
1109 if (vlan_id)
1110 *vlan_id = psk->vlan_id;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001111 return psk->psk;
Hai Shalom021b0b52019-04-10 11:17:58 -07001112 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001113
1114 if (psk->psk == prev_psk)
1115 next_ok = 1;
1116 }
1117
1118 return NULL;
1119}
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001120
1121
Hai Shalom899fcc72020-10-19 14:38:18 -07001122#ifdef CONFIG_SAE_PK
1123static bool hostapd_sae_pk_password_without_pk(struct hostapd_bss_config *bss)
1124{
1125 struct sae_password_entry *pw;
1126 bool res = false;
1127
1128 if (bss->ssid.wpa_passphrase &&
1129#ifdef CONFIG_TESTING_OPTIONS
1130 !bss->sae_pk_password_check_skip &&
1131#endif /* CONFIG_TESTING_OPTIONS */
1132 sae_pk_valid_password(bss->ssid.wpa_passphrase))
1133 res = true;
1134
1135 for (pw = bss->sae_passwords; pw; pw = pw->next) {
1136 if (!pw->pk &&
1137#ifdef CONFIG_TESTING_OPTIONS
1138 !bss->sae_pk_password_check_skip &&
1139#endif /* CONFIG_TESTING_OPTIONS */
1140 sae_pk_valid_password(pw->password))
1141 return true;
1142
1143 if (bss->ssid.wpa_passphrase && res && pw->pk &&
1144 os_strcmp(bss->ssid.wpa_passphrase, pw->password) == 0)
1145 res = false;
1146 }
1147
1148 return res;
1149}
1150#endif /* CONFIG_SAE_PK */
1151
1152
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001153static int hostapd_config_check_bss(struct hostapd_bss_config *bss,
Dmitry Shmidt344abd32014-01-14 13:17:00 -08001154 struct hostapd_config *conf,
1155 int full_config)
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001156{
Dmitry Shmidt344abd32014-01-14 13:17:00 -08001157 if (full_config && bss->ieee802_1x && !bss->eap_server &&
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001158 !bss->radius->auth_servers) {
1159 wpa_printf(MSG_ERROR, "Invalid IEEE 802.1X configuration (no "
1160 "EAP authenticator configured).");
1161 return -1;
1162 }
1163
Hai Shalomfdcde762020-04-02 11:19:20 -07001164#ifdef CONFIG_WEP
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001165 if (bss->wpa) {
1166 int wep, i;
1167
1168 wep = bss->default_wep_key_len > 0 ||
1169 bss->individual_wep_key_len > 0;
1170 for (i = 0; i < NUM_WEP_KEYS; i++) {
1171 if (bss->ssid.wep.keys_set) {
1172 wep = 1;
1173 break;
1174 }
1175 }
1176
1177 if (wep) {
1178 wpa_printf(MSG_ERROR, "WEP configuration in a WPA network is not supported");
1179 return -1;
1180 }
1181 }
Hai Shalomfdcde762020-04-02 11:19:20 -07001182#endif /* CONFIG_WEP */
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001183
Dmitry Shmidt344abd32014-01-14 13:17:00 -08001184 if (full_config && bss->wpa &&
1185 bss->wpa_psk_radius != PSK_RADIUS_IGNORED &&
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001186 bss->macaddr_acl != USE_EXTERNAL_RADIUS_AUTH) {
1187 wpa_printf(MSG_ERROR, "WPA-PSK using RADIUS enabled, but no "
1188 "RADIUS checking (macaddr_acl=2) enabled.");
1189 return -1;
1190 }
1191
Dmitry Shmidt344abd32014-01-14 13:17:00 -08001192 if (full_config && bss->wpa && (bss->wpa_key_mgmt & WPA_KEY_MGMT_PSK) &&
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001193 bss->ssid.wpa_psk == NULL && bss->ssid.wpa_passphrase == NULL &&
1194 bss->ssid.wpa_psk_file == NULL &&
1195 (bss->wpa_psk_radius != PSK_RADIUS_REQUIRED ||
1196 bss->macaddr_acl != USE_EXTERNAL_RADIUS_AUTH)) {
1197 wpa_printf(MSG_ERROR, "WPA-PSK enabled, but PSK or passphrase "
1198 "is not configured.");
1199 return -1;
1200 }
1201
Dmitry Shmidt9c175262016-03-03 10:20:07 -08001202 if (full_config && !is_zero_ether_addr(bss->bssid)) {
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001203 size_t i;
1204
1205 for (i = 0; i < conf->num_bss; i++) {
1206 if (conf->bss[i] != bss &&
1207 (hostapd_mac_comp(conf->bss[i]->bssid,
1208 bss->bssid) == 0)) {
1209 wpa_printf(MSG_ERROR, "Duplicate BSSID " MACSTR
1210 " on interface '%s' and '%s'.",
1211 MAC2STR(bss->bssid),
1212 conf->bss[i]->iface, bss->iface);
1213 return -1;
1214 }
1215 }
1216 }
1217
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001218#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt344abd32014-01-14 13:17:00 -08001219 if (full_config && wpa_key_mgmt_ft(bss->wpa_key_mgmt) &&
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001220 (bss->nas_identifier == NULL ||
1221 os_strlen(bss->nas_identifier) < 1 ||
1222 os_strlen(bss->nas_identifier) > FT_R0KH_ID_MAX_LEN)) {
1223 wpa_printf(MSG_ERROR, "FT (IEEE 802.11r) requires "
1224 "nas_identifier to be configured as a 1..48 octet "
1225 "string");
1226 return -1;
1227 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001228#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001229
Dmitry Shmidt344abd32014-01-14 13:17:00 -08001230 if (full_config && conf->ieee80211n &&
1231 conf->hw_mode == HOSTAPD_MODE_IEEE80211B) {
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001232 bss->disable_11n = 1;
1233 wpa_printf(MSG_ERROR, "HT (IEEE 802.11n) in 11b mode is not "
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001234 "allowed, disabling HT capabilities");
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001235 }
1236
Hai Shalomfdcde762020-04-02 11:19:20 -07001237#ifdef CONFIG_WEP
Dmitry Shmidt344abd32014-01-14 13:17:00 -08001238 if (full_config && conf->ieee80211n &&
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001239 bss->ssid.security_policy == SECURITY_STATIC_WEP) {
1240 bss->disable_11n = 1;
1241 wpa_printf(MSG_ERROR, "HT (IEEE 802.11n) with WEP is not "
1242 "allowed, disabling HT capabilities");
1243 }
Hai Shalomfdcde762020-04-02 11:19:20 -07001244#endif /* CONFIG_WEP */
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001245
Dmitry Shmidt344abd32014-01-14 13:17:00 -08001246 if (full_config && conf->ieee80211n && bss->wpa &&
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001247 !(bss->wpa_pairwise & WPA_CIPHER_CCMP) &&
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001248 !(bss->rsn_pairwise & (WPA_CIPHER_CCMP | WPA_CIPHER_GCMP |
1249 WPA_CIPHER_CCMP_256 | WPA_CIPHER_GCMP_256)))
1250 {
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001251 bss->disable_11n = 1;
1252 wpa_printf(MSG_ERROR, "HT (IEEE 802.11n) with WPA/WPA2 "
1253 "requires CCMP/GCMP to be enabled, disabling HT "
1254 "capabilities");
1255 }
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001256
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -07001257#ifdef CONFIG_IEEE80211AC
Hai Shalomfdcde762020-04-02 11:19:20 -07001258#ifdef CONFIG_WEP
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -07001259 if (full_config && conf->ieee80211ac &&
1260 bss->ssid.security_policy == SECURITY_STATIC_WEP) {
1261 bss->disable_11ac = 1;
1262 wpa_printf(MSG_ERROR,
1263 "VHT (IEEE 802.11ac) with WEP is not allowed, disabling VHT capabilities");
1264 }
Hai Shalomfdcde762020-04-02 11:19:20 -07001265#endif /* CONFIG_WEP */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001266
1267 if (full_config && conf->ieee80211ac && bss->wpa &&
1268 !(bss->wpa_pairwise & WPA_CIPHER_CCMP) &&
1269 !(bss->rsn_pairwise & (WPA_CIPHER_CCMP | WPA_CIPHER_GCMP |
1270 WPA_CIPHER_CCMP_256 | WPA_CIPHER_GCMP_256)))
1271 {
1272 bss->disable_11ac = 1;
1273 wpa_printf(MSG_ERROR,
1274 "VHT (IEEE 802.11ac) with WPA/WPA2 requires CCMP/GCMP to be enabled, disabling VHT capabilities");
1275 }
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -07001276#endif /* CONFIG_IEEE80211AC */
1277
Dmitry Shmidt15907092014-03-25 10:42:57 -07001278#ifdef CONFIG_WPS
Dmitry Shmidt344abd32014-01-14 13:17:00 -08001279 if (full_config && bss->wps_state && bss->ignore_broadcast_ssid) {
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001280 wpa_printf(MSG_INFO, "WPS: ignore_broadcast_ssid "
1281 "configuration forced WPS to be disabled");
1282 bss->wps_state = 0;
1283 }
1284
Hai Shalomfdcde762020-04-02 11:19:20 -07001285#ifdef CONFIG_WEP
Dmitry Shmidt344abd32014-01-14 13:17:00 -08001286 if (full_config && bss->wps_state &&
1287 bss->ssid.wep.keys_set && bss->wpa == 0) {
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001288 wpa_printf(MSG_INFO, "WPS: WEP configuration forced WPS to be "
1289 "disabled");
1290 bss->wps_state = 0;
1291 }
Hai Shalomfdcde762020-04-02 11:19:20 -07001292#endif /* CONFIG_WEP */
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001293
Dmitry Shmidt344abd32014-01-14 13:17:00 -08001294 if (full_config && bss->wps_state && bss->wpa &&
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001295 (!(bss->wpa & 2) ||
Roshan Pius3a1667e2018-07-03 15:17:14 -07001296 !(bss->rsn_pairwise & (WPA_CIPHER_CCMP | WPA_CIPHER_GCMP |
1297 WPA_CIPHER_CCMP_256 |
1298 WPA_CIPHER_GCMP_256)))) {
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001299 wpa_printf(MSG_INFO, "WPS: WPA/TKIP configuration without "
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07001300 "WPA2/CCMP/GCMP forced WPS to be disabled");
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001301 bss->wps_state = 0;
1302 }
Dmitry Shmidt15907092014-03-25 10:42:57 -07001303#endif /* CONFIG_WPS */
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001304
1305#ifdef CONFIG_HS20
Dmitry Shmidt344abd32014-01-14 13:17:00 -08001306 if (full_config && bss->hs20 &&
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001307 (!(bss->wpa & 2) ||
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001308 !(bss->rsn_pairwise & (WPA_CIPHER_CCMP | WPA_CIPHER_GCMP |
1309 WPA_CIPHER_CCMP_256 |
1310 WPA_CIPHER_GCMP_256)))) {
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001311 wpa_printf(MSG_ERROR, "HS 2.0: WPA2-Enterprise/CCMP "
1312 "configuration is required for Hotspot 2.0 "
1313 "functionality");
1314 return -1;
1315 }
1316#endif /* CONFIG_HS20 */
1317
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001318#ifdef CONFIG_MBO
1319 if (full_config && bss->mbo_enabled && (bss->wpa & 2) &&
1320 bss->ieee80211w == NO_MGMT_FRAME_PROTECTION) {
1321 wpa_printf(MSG_ERROR,
1322 "MBO: PMF needs to be enabled whenever using WPA2 with MBO");
1323 return -1;
1324 }
1325#endif /* CONFIG_MBO */
1326
Hai Shalom74f70d42019-02-11 14:42:39 -08001327#ifdef CONFIG_OCV
1328 if (full_config && bss->ieee80211w == NO_MGMT_FRAME_PROTECTION &&
1329 bss->ocv) {
1330 wpa_printf(MSG_ERROR,
1331 "OCV: PMF needs to be enabled whenever using OCV");
1332 return -1;
1333 }
1334#endif /* CONFIG_OCV */
1335
Hai Shalom899fcc72020-10-19 14:38:18 -07001336#ifdef CONFIG_SAE_PK
1337 if (full_config && hostapd_sae_pk_in_use(bss) &&
1338 hostapd_sae_pk_password_without_pk(bss)) {
1339 wpa_printf(MSG_ERROR,
1340 "SAE-PK: SAE password uses SAE-PK style, but does not have PK configured");
1341 return -1;
1342 }
1343#endif /* CONFIG_SAE_PK */
1344
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001345 return 0;
1346}
1347
1348
Dmitry Shmidt05df46a2015-05-19 11:02:01 -07001349static int hostapd_config_check_cw(struct hostapd_config *conf, int queue)
1350{
1351 int tx_cwmin = conf->tx_queue[queue].cwmin;
1352 int tx_cwmax = conf->tx_queue[queue].cwmax;
1353 int ac_cwmin = conf->wmm_ac_params[queue].cwmin;
1354 int ac_cwmax = conf->wmm_ac_params[queue].cwmax;
1355
1356 if (tx_cwmin > tx_cwmax) {
1357 wpa_printf(MSG_ERROR,
1358 "Invalid TX queue cwMin/cwMax values. cwMin(%d) greater than cwMax(%d)",
1359 tx_cwmin, tx_cwmax);
1360 return -1;
1361 }
1362 if (ac_cwmin > ac_cwmax) {
1363 wpa_printf(MSG_ERROR,
1364 "Invalid WMM AC cwMin/cwMax values. cwMin(%d) greater than cwMax(%d)",
1365 ac_cwmin, ac_cwmax);
1366 return -1;
1367 }
1368 return 0;
1369}
1370
1371
Dmitry Shmidt344abd32014-01-14 13:17:00 -08001372int hostapd_config_check(struct hostapd_config *conf, int full_config)
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001373{
1374 size_t i;
1375
Dmitry Shmidt344abd32014-01-14 13:17:00 -08001376 if (full_config && conf->ieee80211d &&
1377 (!conf->country[0] || !conf->country[1])) {
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001378 wpa_printf(MSG_ERROR, "Cannot enable IEEE 802.11d without "
1379 "setting the country_code");
1380 return -1;
1381 }
1382
Dmitry Shmidt344abd32014-01-14 13:17:00 -08001383 if (full_config && conf->ieee80211h && !conf->ieee80211d) {
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001384 wpa_printf(MSG_ERROR, "Cannot enable IEEE 802.11h without "
1385 "IEEE 802.11d enabled");
1386 return -1;
1387 }
1388
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001389 if (full_config && conf->local_pwr_constraint != -1 &&
1390 !conf->ieee80211d) {
1391 wpa_printf(MSG_ERROR, "Cannot add Power Constraint element without Country element");
1392 return -1;
1393 }
1394
1395 if (full_config && conf->spectrum_mgmt_required &&
1396 conf->local_pwr_constraint == -1) {
1397 wpa_printf(MSG_ERROR, "Cannot set Spectrum Management bit without Country and Power Constraint elements");
1398 return -1;
1399 }
1400
Hai Shalom81f62d82019-07-22 12:10:00 -07001401#ifdef CONFIG_AIRTIME_POLICY
1402 if (full_config && conf->airtime_mode > AIRTIME_MODE_STATIC &&
1403 !conf->airtime_update_interval) {
1404 wpa_printf(MSG_ERROR, "Airtime update interval cannot be zero");
1405 return -1;
1406 }
1407#endif /* CONFIG_AIRTIME_POLICY */
Dmitry Shmidt05df46a2015-05-19 11:02:01 -07001408 for (i = 0; i < NUM_TX_QUEUES; i++) {
1409 if (hostapd_config_check_cw(conf, i))
1410 return -1;
1411 }
1412
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001413 for (i = 0; i < conf->num_bss; i++) {
Dmitry Shmidt344abd32014-01-14 13:17:00 -08001414 if (hostapd_config_check_bss(conf->bss[i], conf, full_config))
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001415 return -1;
1416 }
1417
1418 return 0;
1419}
1420
1421
Dmitry Shmidt71757432014-06-02 13:50:35 -07001422void hostapd_set_security_params(struct hostapd_bss_config *bss,
1423 int full_config)
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001424{
Hai Shalomfdcde762020-04-02 11:19:20 -07001425#ifdef CONFIG_WEP
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001426 if (bss->individual_wep_key_len == 0) {
1427 /* individual keys are not use; can use key idx0 for
1428 * broadcast keys */
1429 bss->broadcast_key_idx_min = 0;
1430 }
Hai Shalomfdcde762020-04-02 11:19:20 -07001431#endif /* CONFIG_WEP */
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001432
1433 if ((bss->wpa & 2) && bss->rsn_pairwise == 0)
1434 bss->rsn_pairwise = bss->wpa_pairwise;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001435 if (bss->group_cipher)
1436 bss->wpa_group = bss->group_cipher;
1437 else
1438 bss->wpa_group = wpa_select_ap_group_cipher(bss->wpa,
1439 bss->wpa_pairwise,
1440 bss->rsn_pairwise);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001441 if (!bss->wpa_group_rekey_set)
1442 bss->wpa_group_rekey = bss->wpa_group == WPA_CIPHER_TKIP ?
1443 600 : 86400;
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001444
Dmitry Shmidt71757432014-06-02 13:50:35 -07001445 if (full_config) {
1446 bss->radius->auth_server = bss->radius->auth_servers;
1447 bss->radius->acct_server = bss->radius->acct_servers;
1448 }
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001449
1450 if (bss->wpa && bss->ieee802_1x) {
1451 bss->ssid.security_policy = SECURITY_WPA;
1452 } else if (bss->wpa) {
1453 bss->ssid.security_policy = SECURITY_WPA_PSK;
1454 } else if (bss->ieee802_1x) {
1455 int cipher = WPA_CIPHER_NONE;
1456 bss->ssid.security_policy = SECURITY_IEEE_802_1X;
Hai Shalomfdcde762020-04-02 11:19:20 -07001457#ifdef CONFIG_WEP
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001458 bss->ssid.wep.default_len = bss->default_wep_key_len;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001459 if (full_config && bss->default_wep_key_len) {
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001460 cipher = bss->default_wep_key_len >= 13 ?
1461 WPA_CIPHER_WEP104 : WPA_CIPHER_WEP40;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001462 } else if (full_config && bss->ssid.wep.keys_set) {
1463 if (bss->ssid.wep.len[0] >= 13)
1464 cipher = WPA_CIPHER_WEP104;
1465 else
1466 cipher = WPA_CIPHER_WEP40;
1467 }
Hai Shalomfdcde762020-04-02 11:19:20 -07001468#endif /* CONFIG_WEP */
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001469 bss->wpa_group = cipher;
1470 bss->wpa_pairwise = cipher;
1471 bss->rsn_pairwise = cipher;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001472 if (full_config)
1473 bss->wpa_key_mgmt = WPA_KEY_MGMT_IEEE8021X_NO_WPA;
Hai Shalomfdcde762020-04-02 11:19:20 -07001474#ifdef CONFIG_WEP
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001475 } else if (bss->ssid.wep.keys_set) {
1476 int cipher = WPA_CIPHER_WEP40;
1477 if (bss->ssid.wep.len[0] >= 13)
1478 cipher = WPA_CIPHER_WEP104;
1479 bss->ssid.security_policy = SECURITY_STATIC_WEP;
1480 bss->wpa_group = cipher;
1481 bss->wpa_pairwise = cipher;
1482 bss->rsn_pairwise = cipher;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001483 if (full_config)
1484 bss->wpa_key_mgmt = WPA_KEY_MGMT_NONE;
Hai Shalomfdcde762020-04-02 11:19:20 -07001485#endif /* CONFIG_WEP */
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001486 } else if (bss->osen) {
1487 bss->ssid.security_policy = SECURITY_OSEN;
1488 bss->wpa_group = WPA_CIPHER_CCMP;
1489 bss->wpa_pairwise = 0;
1490 bss->rsn_pairwise = WPA_CIPHER_CCMP;
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001491 } else {
1492 bss->ssid.security_policy = SECURITY_PLAINTEXT;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001493 if (full_config) {
1494 bss->wpa_group = WPA_CIPHER_NONE;
1495 bss->wpa_pairwise = WPA_CIPHER_NONE;
1496 bss->rsn_pairwise = WPA_CIPHER_NONE;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001497 bss->wpa_key_mgmt = WPA_KEY_MGMT_NONE;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001498 }
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001499 }
1500}
Hai Shalom74f70d42019-02-11 14:42:39 -08001501
1502
1503int hostapd_sae_pw_id_in_use(struct hostapd_bss_config *conf)
1504{
1505 int with_id = 0, without_id = 0;
1506 struct sae_password_entry *pw;
1507
1508 if (conf->ssid.wpa_passphrase)
1509 without_id = 1;
1510
1511 for (pw = conf->sae_passwords; pw; pw = pw->next) {
1512 if (pw->identifier)
1513 with_id = 1;
1514 else
1515 without_id = 1;
1516 if (with_id && without_id)
1517 break;
1518 }
1519
1520 if (with_id && !without_id)
1521 return 2;
1522 return with_id;
1523}
Hai Shalom899fcc72020-10-19 14:38:18 -07001524
1525
1526bool hostapd_sae_pk_in_use(struct hostapd_bss_config *conf)
1527{
1528#ifdef CONFIG_SAE_PK
1529 struct sae_password_entry *pw;
1530
1531 for (pw = conf->sae_passwords; pw; pw = pw->next) {
1532 if (pw->pk)
1533 return true;
1534 }
1535#endif /* CONFIG_SAE_PK */
1536
1537 return false;
1538}
1539
1540
1541#ifdef CONFIG_SAE_PK
1542bool hostapd_sae_pk_exclusively(struct hostapd_bss_config *conf)
1543{
1544 bool with_pk = false;
1545 struct sae_password_entry *pw;
1546
1547 if (conf->ssid.wpa_passphrase)
1548 return false;
1549
1550 for (pw = conf->sae_passwords; pw; pw = pw->next) {
1551 if (!pw->pk)
1552 return false;
1553 with_pk = true;
1554 }
1555
1556 return with_pk;
1557}
1558#endif /* CONFIG_SAE_PK */