blob: 9611dc0b3fdb30019ee59a0e869922cbdec17b0e [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"
16#include "common/eapol_common.h"
Dmitry Shmidtebd93af2017-02-21 13:40:44 -080017#include "common/dhcp.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070018#include "eap_common/eap_wsc_common.h"
19#include "eap_server/eap.h"
20#include "wpa_auth.h"
21#include "sta_info.h"
22#include "ap_config.h"
23
24
25static void hostapd_config_free_vlan(struct hostapd_bss_config *bss)
26{
27 struct hostapd_vlan *vlan, *prev;
28
29 vlan = bss->vlan;
30 prev = NULL;
31 while (vlan) {
32 prev = vlan;
33 vlan = vlan->next;
34 os_free(prev);
35 }
36
37 bss->vlan = NULL;
38}
39
40
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070041#ifndef DEFAULT_WPA_DISABLE_EAPOL_KEY_RETRIES
42#define DEFAULT_WPA_DISABLE_EAPOL_KEY_RETRIES 0
43#endif /* DEFAULT_WPA_DISABLE_EAPOL_KEY_RETRIES */
44
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070045void hostapd_config_defaults_bss(struct hostapd_bss_config *bss)
46{
Dmitry Shmidtd80a4012015-11-05 16:35:40 -080047 dl_list_init(&bss->anqp_elem);
48
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070049 bss->logger_syslog_level = HOSTAPD_LEVEL_INFO;
50 bss->logger_stdout_level = HOSTAPD_LEVEL_INFO;
51 bss->logger_syslog = (unsigned int) -1;
52 bss->logger_stdout = (unsigned int) -1;
53
54 bss->auth_algs = WPA_AUTH_ALG_OPEN | WPA_AUTH_ALG_SHARED;
55
56 bss->wep_rekeying_period = 300;
57 /* use key0 in individual key and key1 in broadcast key */
58 bss->broadcast_key_idx_min = 1;
59 bss->broadcast_key_idx_max = 2;
60 bss->eap_reauth_period = 3600;
61
62 bss->wpa_group_rekey = 600;
63 bss->wpa_gmk_rekey = 86400;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -080064 bss->wpa_group_update_count = 4;
65 bss->wpa_pairwise_update_count = 4;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070066 bss->wpa_disable_eapol_key_retries =
67 DEFAULT_WPA_DISABLE_EAPOL_KEY_RETRIES;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070068 bss->wpa_key_mgmt = WPA_KEY_MGMT_PSK;
69 bss->wpa_pairwise = WPA_CIPHER_TKIP;
70 bss->wpa_group = WPA_CIPHER_TKIP;
71 bss->rsn_pairwise = 0;
72
73 bss->max_num_sta = MAX_STA_COUNT;
74
75 bss->dtim_period = 2;
76
77 bss->radius_server_auth_port = 1812;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -080078 bss->eap_sim_db_timeout = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070079 bss->ap_max_inactivity = AP_MAX_INACTIVITY;
80 bss->eapol_version = EAPOL_VERSION;
81
82 bss->max_listen_interval = 65535;
83
84 bss->pwd_group = 19; /* ECC: GF(p=256) */
85
86#ifdef CONFIG_IEEE80211W
87 bss->assoc_sa_query_max_timeout = 1000;
88 bss->assoc_sa_query_retry_timeout = 201;
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -070089 bss->group_mgmt_cipher = WPA_CIPHER_AES_128_CMAC;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070090#endif /* CONFIG_IEEE80211W */
91#ifdef EAP_SERVER_FAST
92 /* both anonymous and authenticated provisioning */
93 bss->eap_fast_prov = 3;
94 bss->pac_key_lifetime = 7 * 24 * 60 * 60;
95 bss->pac_key_refresh_time = 1 * 24 * 60 * 60;
96#endif /* EAP_SERVER_FAST */
97
98 /* Set to -1 as defaults depends on HT in setup */
99 bss->wmm_enabled = -1;
100
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800101#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700102 bss->ft_over_ds = 1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700103 bss->rkh_pos_timeout = 86400;
104 bss->rkh_neg_timeout = 60;
105 bss->rkh_pull_timeout = 1000;
106 bss->rkh_pull_retries = 4;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700107 bss->r0_key_lifetime = 1209600;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800108#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt04949592012-07-19 12:16:46 -0700109
110 bss->radius_das_time_window = 300;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800111
112 bss->sae_anti_clogging_threshold = 5;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700113 bss->sae_sync = 5;
Dmitry Shmidt29333592017-01-09 12:27:11 -0800114
115 bss->gas_frag_limit = 1400;
116
117#ifdef CONFIG_FILS
118 dl_list_init(&bss->fils_realms);
Dmitry Shmidtebd93af2017-02-21 13:40:44 -0800119 bss->fils_hlp_wait_time = 30;
120 bss->dhcp_server_port = DHCP_SERVER_PORT;
121 bss->dhcp_relay_port = DHCP_SERVER_PORT;
Dmitry Shmidt29333592017-01-09 12:27:11 -0800122#endif /* CONFIG_FILS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700123
124 bss->broadcast_deauth = 1;
125
126#ifdef CONFIG_MBO
127 bss->mbo_cell_data_conn_pref = -1;
128#endif /* CONFIG_MBO */
Roshan Pius3a1667e2018-07-03 15:17:14 -0700129
130 /* Disable TLS v1.3 by default for now to avoid interoperability issue.
131 * This can be enabled by default once the implementation has been fully
132 * completed and tested with other implementations. */
133 bss->tls_flags = TLS_CONN_DISABLE_TLSv1_3;
Hai Shalom74f70d42019-02-11 14:42:39 -0800134
135 bss->send_probe_response = 1;
136
137#ifdef CONFIG_HS20
138 bss->hs20_release = (HS20_VERSION >> 4) + 1;
139#endif /* CONFIG_HS20 */
140
141 /* Default to strict CRL checking. */
142 bss->check_crl_strict = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700143}
144
145
146struct hostapd_config * hostapd_config_defaults(void)
147{
148#define ecw2cw(ecw) ((1 << (ecw)) - 1)
149
150 struct hostapd_config *conf;
151 struct hostapd_bss_config *bss;
152 const int aCWmin = 4, aCWmax = 10;
153 const struct hostapd_wmm_ac_params ac_bk =
154 { aCWmin, aCWmax, 7, 0, 0 }; /* background traffic */
155 const struct hostapd_wmm_ac_params ac_be =
156 { aCWmin, aCWmax, 3, 0, 0 }; /* best effort traffic */
157 const struct hostapd_wmm_ac_params ac_vi = /* video traffic */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -0700158 { aCWmin - 1, aCWmin, 2, 3008 / 32, 0 };
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700159 const struct hostapd_wmm_ac_params ac_vo = /* voice traffic */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -0700160 { aCWmin - 2, aCWmin - 1, 2, 1504 / 32, 0 };
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700161 const struct hostapd_tx_queue_params txq_bk =
162 { 7, ecw2cw(aCWmin), ecw2cw(aCWmax), 0 };
163 const struct hostapd_tx_queue_params txq_be =
164 { 3, ecw2cw(aCWmin), 4 * (ecw2cw(aCWmin) + 1) - 1, 0};
165 const struct hostapd_tx_queue_params txq_vi =
166 { 1, (ecw2cw(aCWmin) + 1) / 2 - 1, ecw2cw(aCWmin), 30};
167 const struct hostapd_tx_queue_params txq_vo =
168 { 1, (ecw2cw(aCWmin) + 1) / 4 - 1,
169 (ecw2cw(aCWmin) + 1) / 2 - 1, 15};
170
171#undef ecw2cw
172
173 conf = os_zalloc(sizeof(*conf));
174 bss = os_zalloc(sizeof(*bss));
175 if (conf == NULL || bss == NULL) {
176 wpa_printf(MSG_ERROR, "Failed to allocate memory for "
177 "configuration data.");
178 os_free(conf);
179 os_free(bss);
180 return NULL;
181 }
Dmitry Shmidtcce06662013-11-04 18:44:24 -0800182 conf->bss = os_calloc(1, sizeof(struct hostapd_bss_config *));
183 if (conf->bss == NULL) {
184 os_free(conf);
185 os_free(bss);
186 return NULL;
187 }
188 conf->bss[0] = bss;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700189
190 bss->radius = os_zalloc(sizeof(*bss->radius));
191 if (bss->radius == NULL) {
Dmitry Shmidt97672262014-02-03 13:02:54 -0800192 os_free(conf->bss);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700193 os_free(conf);
194 os_free(bss);
195 return NULL;
196 }
197
198 hostapd_config_defaults_bss(bss);
199
200 conf->num_bss = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700201
202 conf->beacon_int = 100;
203 conf->rts_threshold = -1; /* use driver default: 2347 */
204 conf->fragm_threshold = -1; /* user driver default: 2346 */
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800205 /* Set to invalid value means do not add Power Constraint IE */
206 conf->local_pwr_constraint = -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700207
208 conf->wmm_ac_params[0] = ac_be;
209 conf->wmm_ac_params[1] = ac_bk;
210 conf->wmm_ac_params[2] = ac_vi;
211 conf->wmm_ac_params[3] = ac_vo;
212
213 conf->tx_queue[0] = txq_vo;
214 conf->tx_queue[1] = txq_vi;
215 conf->tx_queue[2] = txq_be;
216 conf->tx_queue[3] = txq_bk;
217
218 conf->ht_capab = HT_CAP_INFO_SMPS_DISABLED;
219
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800220 conf->ap_table_max_size = 255;
221 conf->ap_table_expiration_time = 60;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800222 conf->track_sta_max_age = 180;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800223
Dmitry Shmidt8da800a2013-04-24 12:57:01 -0700224#ifdef CONFIG_TESTING_OPTIONS
Dmitry Shmidt7832adb2014-04-29 10:53:02 -0700225 conf->ignore_probe_probability = 0.0;
226 conf->ignore_auth_probability = 0.0;
227 conf->ignore_assoc_probability = 0.0;
228 conf->ignore_reassoc_probability = 0.0;
229 conf->corrupt_gtk_rekey_mic_probability = 0.0;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800230 conf->ecsa_ie_only = 0;
Dmitry Shmidt8da800a2013-04-24 12:57:01 -0700231#endif /* CONFIG_TESTING_OPTIONS */
232
Dmitry Shmidtdda10c22015-03-24 16:05:01 -0700233 conf->acs = 0;
234 conf->acs_ch_list.num = 0;
Dmitry Shmidt391c59f2013-09-03 12:16:28 -0700235#ifdef CONFIG_ACS
236 conf->acs_num_scans = 5;
237#endif /* CONFIG_ACS */
238
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700239 /* The third octet of the country string uses an ASCII space character
240 * by default to indicate that the regulations encompass all
241 * environments for the current frequency band in the country. */
242 conf->country[2] = ' ';
243
Hai Shalom74f70d42019-02-11 14:42:39 -0800244 conf->rssi_reject_assoc_rssi = 0;
245 conf->rssi_reject_assoc_timeout = 30;
246
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700247 return conf;
248}
249
250
251int hostapd_mac_comp(const void *a, const void *b)
252{
253 return os_memcmp(a, b, sizeof(macaddr));
254}
255
256
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700257static int hostapd_config_read_wpa_psk(const char *fname,
258 struct hostapd_ssid *ssid)
259{
260 FILE *f;
261 char buf[128], *pos;
Hai Shalom74f70d42019-02-11 14:42:39 -0800262 const char *keyid;
263 char *context;
264 char *context2;
265 char *token;
266 char *name;
267 char *value;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700268 int line = 0, ret = 0, len, ok;
269 u8 addr[ETH_ALEN];
270 struct hostapd_wpa_psk *psk;
271
272 if (!fname)
273 return 0;
274
275 f = fopen(fname, "r");
276 if (!f) {
277 wpa_printf(MSG_ERROR, "WPA PSK file '%s' not found.", fname);
278 return -1;
279 }
280
281 while (fgets(buf, sizeof(buf), f)) {
282 line++;
283
284 if (buf[0] == '#')
285 continue;
286 pos = buf;
287 while (*pos != '\0') {
288 if (*pos == '\n') {
289 *pos = '\0';
290 break;
291 }
292 pos++;
293 }
294 if (buf[0] == '\0')
295 continue;
296
Hai Shalom74f70d42019-02-11 14:42:39 -0800297 context = NULL;
298 keyid = NULL;
299 while ((token = str_token(buf, " ", &context))) {
300 if (!os_strchr(token, '='))
301 break;
302 context2 = NULL;
303 name = str_token(token, "=", &context2);
304 value = str_token(token, "", &context2);
305 if (!value)
306 value = "";
307 if (!os_strcmp(name, "keyid")) {
308 keyid = value;
309 } else {
310 wpa_printf(MSG_ERROR,
311 "Unrecognized '%s=%s' on line %d in '%s'",
312 name, value, line, fname);
313 ret = -1;
314 break;
315 }
316 }
317
318 if (ret == -1)
319 break;
320
321 if (!token)
322 token = "";
323 if (hwaddr_aton(token, addr)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700324 wpa_printf(MSG_ERROR, "Invalid MAC address '%s' on "
Hai Shalom74f70d42019-02-11 14:42:39 -0800325 "line %d in '%s'", token, line, fname);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700326 ret = -1;
327 break;
328 }
329
330 psk = os_zalloc(sizeof(*psk));
331 if (psk == NULL) {
332 wpa_printf(MSG_ERROR, "WPA PSK allocation failed");
333 ret = -1;
334 break;
335 }
336 if (is_zero_ether_addr(addr))
337 psk->group = 1;
338 else
339 os_memcpy(psk->addr, addr, ETH_ALEN);
340
Hai Shalom74f70d42019-02-11 14:42:39 -0800341 pos = str_token(buf, "", &context);
342 if (!pos) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700343 wpa_printf(MSG_ERROR, "No PSK on line %d in '%s'",
344 line, fname);
345 os_free(psk);
346 ret = -1;
347 break;
348 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700349
350 ok = 0;
351 len = os_strlen(pos);
352 if (len == 64 && hexstr2bin(pos, psk->psk, PMK_LEN) == 0)
353 ok = 1;
354 else if (len >= 8 && len < 64) {
355 pbkdf2_sha1(pos, ssid->ssid, ssid->ssid_len,
356 4096, psk->psk, PMK_LEN);
357 ok = 1;
358 }
359 if (!ok) {
360 wpa_printf(MSG_ERROR, "Invalid PSK '%s' on line %d in "
361 "'%s'", pos, line, fname);
362 os_free(psk);
363 ret = -1;
364 break;
365 }
366
Hai Shalom74f70d42019-02-11 14:42:39 -0800367 if (keyid) {
368 len = os_strlcpy(psk->keyid, keyid, sizeof(psk->keyid));
369 if ((size_t) len >= sizeof(psk->keyid)) {
370 wpa_printf(MSG_ERROR,
371 "PSK keyid too long on line %d in '%s'",
372 line, fname);
373 os_free(psk);
374 ret = -1;
375 break;
376 }
377 }
378
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700379 psk->next = ssid->wpa_psk;
380 ssid->wpa_psk = psk;
381 }
382
383 fclose(f);
384
385 return ret;
386}
387
388
389static int hostapd_derive_psk(struct hostapd_ssid *ssid)
390{
391 ssid->wpa_psk = os_zalloc(sizeof(struct hostapd_wpa_psk));
392 if (ssid->wpa_psk == NULL) {
393 wpa_printf(MSG_ERROR, "Unable to alloc space for PSK");
394 return -1;
395 }
396 wpa_hexdump_ascii(MSG_DEBUG, "SSID",
397 (u8 *) ssid->ssid, ssid->ssid_len);
398 wpa_hexdump_ascii_key(MSG_DEBUG, "PSK (ASCII passphrase)",
399 (u8 *) ssid->wpa_passphrase,
400 os_strlen(ssid->wpa_passphrase));
401 pbkdf2_sha1(ssid->wpa_passphrase,
402 ssid->ssid, ssid->ssid_len,
403 4096, ssid->wpa_psk->psk, PMK_LEN);
404 wpa_hexdump_key(MSG_DEBUG, "PSK (from passphrase)",
405 ssid->wpa_psk->psk, PMK_LEN);
406 return 0;
407}
408
409
410int hostapd_setup_wpa_psk(struct hostapd_bss_config *conf)
411{
412 struct hostapd_ssid *ssid = &conf->ssid;
413
414 if (ssid->wpa_passphrase != NULL) {
415 if (ssid->wpa_psk != NULL) {
416 wpa_printf(MSG_DEBUG, "Using pre-configured WPA PSK "
417 "instead of passphrase");
418 } else {
419 wpa_printf(MSG_DEBUG, "Deriving WPA PSK based on "
420 "passphrase");
421 if (hostapd_derive_psk(ssid) < 0)
422 return -1;
423 }
424 ssid->wpa_psk->group = 1;
425 }
426
Dmitry Shmidt29333592017-01-09 12:27:11 -0800427 return hostapd_config_read_wpa_psk(ssid->wpa_psk_file, &conf->ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700428}
429
430
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700431static void hostapd_config_free_radius(struct hostapd_radius_server *servers,
432 int num_servers)
433{
434 int i;
435
436 for (i = 0; i < num_servers; i++) {
437 os_free(servers[i].shared_secret);
438 }
439 os_free(servers);
440}
441
442
Dmitry Shmidt04949592012-07-19 12:16:46 -0700443struct hostapd_radius_attr *
444hostapd_config_get_radius_attr(struct hostapd_radius_attr *attr, u8 type)
445{
446 for (; attr; attr = attr->next) {
447 if (attr->type == type)
448 return attr;
449 }
450 return NULL;
451}
452
453
454static void hostapd_config_free_radius_attr(struct hostapd_radius_attr *attr)
455{
456 struct hostapd_radius_attr *prev;
457
458 while (attr) {
459 prev = attr;
460 attr = attr->next;
461 wpabuf_free(prev->val);
462 os_free(prev);
463 }
464}
465
466
Dmitry Shmidt818ea482014-03-10 13:15:21 -0700467void hostapd_config_free_eap_user(struct hostapd_eap_user *user)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700468{
Dmitry Shmidt818ea482014-03-10 13:15:21 -0700469 hostapd_config_free_radius_attr(user->accept_attr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700470 os_free(user->identity);
Dmitry Shmidtc2817022014-07-02 10:32:10 -0700471 bin_clear_free(user->password, user->password_len);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700472 bin_clear_free(user->salt, user->salt_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700473 os_free(user);
474}
475
476
Dmitry Shmidt29333592017-01-09 12:27:11 -0800477void hostapd_config_free_eap_users(struct hostapd_eap_user *user)
478{
479 struct hostapd_eap_user *prev_user;
480
481 while (user) {
482 prev_user = user;
483 user = user->next;
484 hostapd_config_free_eap_user(prev_user);
485 }
486}
487
488
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700489static void hostapd_config_free_wep(struct hostapd_wep_keys *keys)
490{
491 int i;
492 for (i = 0; i < NUM_WEP_KEYS; i++) {
Dmitry Shmidtc2817022014-07-02 10:32:10 -0700493 bin_clear_free(keys->key[i], keys->len[i]);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700494 keys->key[i] = NULL;
495 }
496}
497
498
Dmitry Shmidt7f656022015-02-25 14:36:37 -0800499void hostapd_config_clear_wpa_psk(struct hostapd_wpa_psk **l)
500{
501 struct hostapd_wpa_psk *psk, *tmp;
502
503 for (psk = *l; psk;) {
504 tmp = psk;
505 psk = psk->next;
506 bin_clear_free(tmp, sizeof(*tmp));
507 }
508 *l = NULL;
509}
510
511
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800512static void hostapd_config_free_anqp_elem(struct hostapd_bss_config *conf)
513{
514 struct anqp_element *elem;
515
516 while ((elem = dl_list_first(&conf->anqp_elem, struct anqp_element,
517 list))) {
518 dl_list_del(&elem->list);
519 wpabuf_free(elem->payload);
520 os_free(elem);
521 }
522}
523
524
Dmitry Shmidt29333592017-01-09 12:27:11 -0800525static void hostapd_config_free_fils_realms(struct hostapd_bss_config *conf)
526{
527#ifdef CONFIG_FILS
528 struct fils_realm *realm;
529
530 while ((realm = dl_list_first(&conf->fils_realms, struct fils_realm,
531 list))) {
532 dl_list_del(&realm->list);
533 os_free(realm);
534 }
535#endif /* CONFIG_FILS */
536}
537
538
Roshan Pius3a1667e2018-07-03 15:17:14 -0700539static void hostapd_config_free_sae_passwords(struct hostapd_bss_config *conf)
540{
541 struct sae_password_entry *pw, *tmp;
542
543 pw = conf->sae_passwords;
544 conf->sae_passwords = NULL;
545 while (pw) {
546 tmp = pw;
547 pw = pw->next;
548 str_clear_free(tmp->password);
549 os_free(tmp->identifier);
550 os_free(tmp);
551 }
552}
553
554
Dmitry Shmidtcce06662013-11-04 18:44:24 -0800555void hostapd_config_free_bss(struct hostapd_bss_config *conf)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700556{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700557 if (conf == NULL)
558 return;
559
Dmitry Shmidt7f656022015-02-25 14:36:37 -0800560 hostapd_config_clear_wpa_psk(&conf->ssid.wpa_psk);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700561
Dmitry Shmidtc2817022014-07-02 10:32:10 -0700562 str_clear_free(conf->ssid.wpa_passphrase);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700563 os_free(conf->ssid.wpa_psk_file);
564 hostapd_config_free_wep(&conf->ssid.wep);
565#ifdef CONFIG_FULL_DYNAMIC_VLAN
566 os_free(conf->ssid.vlan_tagged_interface);
567#endif /* CONFIG_FULL_DYNAMIC_VLAN */
568
Dmitry Shmidt29333592017-01-09 12:27:11 -0800569 hostapd_config_free_eap_users(conf->eap_user);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800570 os_free(conf->eap_user_sqlite);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700571
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700572 os_free(conf->eap_req_id_text);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800573 os_free(conf->erp_domain);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700574 os_free(conf->accept_mac);
575 os_free(conf->deny_mac);
576 os_free(conf->nas_identifier);
Dmitry Shmidtcce06662013-11-04 18:44:24 -0800577 if (conf->radius) {
578 hostapd_config_free_radius(conf->radius->auth_servers,
579 conf->radius->num_auth_servers);
580 hostapd_config_free_radius(conf->radius->acct_servers,
581 conf->radius->num_acct_servers);
582 }
Dmitry Shmidt04949592012-07-19 12:16:46 -0700583 hostapd_config_free_radius_attr(conf->radius_auth_req_attr);
584 hostapd_config_free_radius_attr(conf->radius_acct_req_attr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700585 os_free(conf->rsn_preauth_interfaces);
586 os_free(conf->ctrl_interface);
587 os_free(conf->ca_cert);
588 os_free(conf->server_cert);
589 os_free(conf->private_key);
590 os_free(conf->private_key_passwd);
Dmitry Shmidt34af3062013-07-11 10:46:32 -0700591 os_free(conf->ocsp_stapling_response);
Dmitry Shmidt014a3ff2015-12-28 13:27:49 -0800592 os_free(conf->ocsp_stapling_response_multi);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700593 os_free(conf->dh_file);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800594 os_free(conf->openssl_ciphers);
Hai Shalom74f70d42019-02-11 14:42:39 -0800595 os_free(conf->openssl_ecdh_curves);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700596 os_free(conf->pac_opaque_encr_key);
597 os_free(conf->eap_fast_a_id);
598 os_free(conf->eap_fast_a_id_info);
599 os_free(conf->eap_sim_db);
600 os_free(conf->radius_server_clients);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700601 os_free(conf->radius);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700602 os_free(conf->radius_das_shared_secret);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700603 hostapd_config_free_vlan(conf);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800604 os_free(conf->time_zone);
605
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800606#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700607 {
608 struct ft_remote_r0kh *r0kh, *r0kh_prev;
609 struct ft_remote_r1kh *r1kh, *r1kh_prev;
610
611 r0kh = conf->r0kh_list;
612 conf->r0kh_list = NULL;
613 while (r0kh) {
614 r0kh_prev = r0kh;
615 r0kh = r0kh->next;
616 os_free(r0kh_prev);
617 }
618
619 r1kh = conf->r1kh_list;
620 conf->r1kh_list = NULL;
621 while (r1kh) {
622 r1kh_prev = r1kh;
623 r1kh = r1kh->next;
624 os_free(r1kh_prev);
625 }
626 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800627#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700628
629#ifdef CONFIG_WPS
630 os_free(conf->wps_pin_requests);
631 os_free(conf->device_name);
632 os_free(conf->manufacturer);
633 os_free(conf->model_name);
634 os_free(conf->model_number);
635 os_free(conf->serial_number);
636 os_free(conf->config_methods);
637 os_free(conf->ap_pin);
638 os_free(conf->extra_cred);
639 os_free(conf->ap_settings);
640 os_free(conf->upnp_iface);
641 os_free(conf->friendly_name);
642 os_free(conf->manufacturer_url);
643 os_free(conf->model_description);
644 os_free(conf->model_url);
645 os_free(conf->upc);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800646 {
647 unsigned int i;
648
649 for (i = 0; i < MAX_WPS_VENDOR_EXTENSIONS; i++)
650 wpabuf_free(conf->wps_vendor_ext[i]);
651 }
Dmitry Shmidt04949592012-07-19 12:16:46 -0700652 wpabuf_free(conf->wps_nfc_dh_pubkey);
653 wpabuf_free(conf->wps_nfc_dh_privkey);
654 wpabuf_free(conf->wps_nfc_dev_pw);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700655#endif /* CONFIG_WPS */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800656
657 os_free(conf->roaming_consortium);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700658 os_free(conf->venue_name);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700659 os_free(conf->venue_url);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700660 os_free(conf->nai_realm_data);
661 os_free(conf->network_auth_type);
662 os_free(conf->anqp_3gpp_cell_net);
663 os_free(conf->domain_name);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800664 hostapd_config_free_anqp_elem(conf);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800665
666#ifdef CONFIG_RADIUS_TEST
667 os_free(conf->dump_msk_file);
668#endif /* CONFIG_RADIUS_TEST */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700669
670#ifdef CONFIG_HS20
671 os_free(conf->hs20_oper_friendly_name);
672 os_free(conf->hs20_wan_metrics);
673 os_free(conf->hs20_connection_capability);
674 os_free(conf->hs20_operating_class);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800675 os_free(conf->hs20_icons);
676 if (conf->hs20_osu_providers) {
677 size_t i;
678 for (i = 0; i < conf->hs20_osu_providers_count; i++) {
679 struct hs20_osu_provider *p;
680 size_t j;
681 p = &conf->hs20_osu_providers[i];
682 os_free(p->friendly_name);
683 os_free(p->server_uri);
684 os_free(p->method_list);
685 for (j = 0; j < p->icons_count; j++)
686 os_free(p->icons[j]);
687 os_free(p->icons);
688 os_free(p->osu_nai);
Hai Shalom39ba6fc2019-01-22 12:40:38 -0800689 os_free(p->osu_nai2);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800690 os_free(p->service_desc);
691 }
692 os_free(conf->hs20_osu_providers);
693 }
Roshan Pius3a1667e2018-07-03 15:17:14 -0700694 if (conf->hs20_operator_icon) {
695 size_t i;
696
697 for (i = 0; i < conf->hs20_operator_icon_count; i++)
698 os_free(conf->hs20_operator_icon[i]);
699 os_free(conf->hs20_operator_icon);
700 }
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800701 os_free(conf->subscr_remediation_url);
Hai Shalom74f70d42019-02-11 14:42:39 -0800702 os_free(conf->hs20_sim_provisioning_url);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700703 os_free(conf->t_c_filename);
704 os_free(conf->t_c_server_url);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700705#endif /* CONFIG_HS20 */
706
707 wpabuf_free(conf->vendor_elements);
Dmitry Shmidt849734c2016-05-27 09:59:01 -0700708 wpabuf_free(conf->assocresp_elements);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800709
710 os_free(conf->sae_groups);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700711#ifdef CONFIG_OWE
712 os_free(conf->owe_groups);
713#endif /* CONFIG_OWE */
Dmitry Shmidt34af3062013-07-11 10:46:32 -0700714
Dmitry Shmidt0207e232014-09-03 14:58:37 -0700715 os_free(conf->wowlan_triggers);
716
Dmitry Shmidt34af3062013-07-11 10:46:32 -0700717 os_free(conf->server_id);
Dmitry Shmidtcce06662013-11-04 18:44:24 -0800718
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800719#ifdef CONFIG_TESTING_OPTIONS
720 wpabuf_free(conf->own_ie_override);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700721 wpabuf_free(conf->sae_commit_override);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800722#endif /* CONFIG_TESTING_OPTIONS */
723
724 os_free(conf->no_probe_resp_if_seen_on);
725 os_free(conf->no_auth_if_seen_on);
726
Dmitry Shmidt29333592017-01-09 12:27:11 -0800727 hostapd_config_free_fils_realms(conf);
728
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700729#ifdef CONFIG_DPP
730 os_free(conf->dpp_connector);
731 wpabuf_free(conf->dpp_netaccesskey);
732 wpabuf_free(conf->dpp_csign);
733#endif /* CONFIG_DPP */
734
Roshan Pius3a1667e2018-07-03 15:17:14 -0700735 hostapd_config_free_sae_passwords(conf);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700736
Dmitry Shmidtcce06662013-11-04 18:44:24 -0800737 os_free(conf);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700738}
739
740
741/**
742 * hostapd_config_free - Free hostapd configuration
743 * @conf: Configuration data from hostapd_config_read().
744 */
745void hostapd_config_free(struct hostapd_config *conf)
746{
747 size_t i;
748
749 if (conf == NULL)
750 return;
751
752 for (i = 0; i < conf->num_bss; i++)
Dmitry Shmidtcce06662013-11-04 18:44:24 -0800753 hostapd_config_free_bss(conf->bss[i]);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700754 os_free(conf->bss);
755 os_free(conf->supported_rates);
756 os_free(conf->basic_rates);
Dmitry Shmidtdda10c22015-03-24 16:05:01 -0700757 os_free(conf->acs_ch_list.range);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800758 os_free(conf->driver_params);
Dmitry Shmidt7f656022015-02-25 14:36:37 -0800759#ifdef CONFIG_ACS
760 os_free(conf->acs_chan_bias);
761#endif /* CONFIG_ACS */
Dmitry Shmidt849734c2016-05-27 09:59:01 -0700762 wpabuf_free(conf->lci);
763 wpabuf_free(conf->civic);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700764
765 os_free(conf);
766}
767
768
769/**
770 * hostapd_maclist_found - Find a MAC address from a list
771 * @list: MAC address list
772 * @num_entries: Number of addresses in the list
773 * @addr: Address to search for
774 * @vlan_id: Buffer for returning VLAN ID or %NULL if not needed
775 * Returns: 1 if address is in the list or 0 if not.
776 *
777 * Perform a binary search for given MAC address from a pre-sorted list.
778 */
779int hostapd_maclist_found(struct mac_acl_entry *list, int num_entries,
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800780 const u8 *addr, struct vlan_description *vlan_id)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700781{
782 int start, end, middle, res;
783
784 start = 0;
785 end = num_entries - 1;
786
787 while (start <= end) {
788 middle = (start + end) / 2;
789 res = os_memcmp(list[middle].addr, addr, ETH_ALEN);
790 if (res == 0) {
791 if (vlan_id)
792 *vlan_id = list[middle].vlan_id;
793 return 1;
794 }
795 if (res < 0)
796 start = middle + 1;
797 else
798 end = middle - 1;
799 }
800
801 return 0;
802}
803
804
805int hostapd_rate_found(int *list, int rate)
806{
807 int i;
808
809 if (list == NULL)
810 return 0;
811
812 for (i = 0; list[i] >= 0; i++)
813 if (list[i] == rate)
814 return 1;
815
816 return 0;
817}
818
819
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800820int hostapd_vlan_valid(struct hostapd_vlan *vlan,
821 struct vlan_description *vlan_desc)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700822{
823 struct hostapd_vlan *v = vlan;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800824 int i;
825
826 if (!vlan_desc->notempty || vlan_desc->untagged < 0 ||
827 vlan_desc->untagged > MAX_VLAN_ID)
828 return 0;
829 for (i = 0; i < MAX_NUM_TAGGED_VLAN; i++) {
830 if (vlan_desc->tagged[i] < 0 ||
831 vlan_desc->tagged[i] > MAX_VLAN_ID)
832 return 0;
833 }
834 if (!vlan_desc->untagged && !vlan_desc->tagged[0])
835 return 0;
836
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700837 while (v) {
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800838 if (!vlan_compare(&v->vlan_desc, vlan_desc) ||
839 v->vlan_id == VLAN_ID_WILDCARD)
Dmitry Shmidt34af3062013-07-11 10:46:32 -0700840 return 1;
841 v = v->next;
842 }
843 return 0;
844}
845
846
847const char * hostapd_get_vlan_id_ifname(struct hostapd_vlan *vlan, int vlan_id)
848{
849 struct hostapd_vlan *v = vlan;
850 while (v) {
851 if (v->vlan_id == vlan_id)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700852 return v->ifname;
853 v = v->next;
854 }
855 return NULL;
856}
857
858
859const u8 * hostapd_get_psk(const struct hostapd_bss_config *conf,
Dmitry Shmidt391c59f2013-09-03 12:16:28 -0700860 const u8 *addr, const u8 *p2p_dev_addr,
861 const u8 *prev_psk)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700862{
863 struct hostapd_wpa_psk *psk;
864 int next_ok = prev_psk == NULL;
865
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -0700866 if (p2p_dev_addr && !is_zero_ether_addr(p2p_dev_addr)) {
Dmitry Shmidt391c59f2013-09-03 12:16:28 -0700867 wpa_printf(MSG_DEBUG, "Searching a PSK for " MACSTR
868 " p2p_dev_addr=" MACSTR " prev_psk=%p",
869 MAC2STR(addr), MAC2STR(p2p_dev_addr), prev_psk);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -0700870 addr = NULL; /* Use P2P Device Address for matching */
Dmitry Shmidt391c59f2013-09-03 12:16:28 -0700871 } else {
872 wpa_printf(MSG_DEBUG, "Searching a PSK for " MACSTR
873 " prev_psk=%p",
874 MAC2STR(addr), prev_psk);
875 }
876
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700877 for (psk = conf->ssid.wpa_psk; psk != NULL; psk = psk->next) {
878 if (next_ok &&
Dmitry Shmidt391c59f2013-09-03 12:16:28 -0700879 (psk->group ||
880 (addr && os_memcmp(psk->addr, addr, ETH_ALEN) == 0) ||
881 (!addr && p2p_dev_addr &&
882 os_memcmp(psk->p2p_dev_addr, p2p_dev_addr, ETH_ALEN) ==
883 0)))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700884 return psk->psk;
885
886 if (psk->psk == prev_psk)
887 next_ok = 1;
888 }
889
890 return NULL;
891}
Dmitry Shmidtcce06662013-11-04 18:44:24 -0800892
893
894static int hostapd_config_check_bss(struct hostapd_bss_config *bss,
Dmitry Shmidt344abd32014-01-14 13:17:00 -0800895 struct hostapd_config *conf,
896 int full_config)
Dmitry Shmidtcce06662013-11-04 18:44:24 -0800897{
Dmitry Shmidt344abd32014-01-14 13:17:00 -0800898 if (full_config && bss->ieee802_1x && !bss->eap_server &&
Dmitry Shmidtcce06662013-11-04 18:44:24 -0800899 !bss->radius->auth_servers) {
900 wpa_printf(MSG_ERROR, "Invalid IEEE 802.1X configuration (no "
901 "EAP authenticator configured).");
902 return -1;
903 }
904
905 if (bss->wpa) {
906 int wep, i;
907
908 wep = bss->default_wep_key_len > 0 ||
909 bss->individual_wep_key_len > 0;
910 for (i = 0; i < NUM_WEP_KEYS; i++) {
911 if (bss->ssid.wep.keys_set) {
912 wep = 1;
913 break;
914 }
915 }
916
917 if (wep) {
918 wpa_printf(MSG_ERROR, "WEP configuration in a WPA network is not supported");
919 return -1;
920 }
921 }
922
Dmitry Shmidt344abd32014-01-14 13:17:00 -0800923 if (full_config && bss->wpa &&
924 bss->wpa_psk_radius != PSK_RADIUS_IGNORED &&
Dmitry Shmidtcce06662013-11-04 18:44:24 -0800925 bss->macaddr_acl != USE_EXTERNAL_RADIUS_AUTH) {
926 wpa_printf(MSG_ERROR, "WPA-PSK using RADIUS enabled, but no "
927 "RADIUS checking (macaddr_acl=2) enabled.");
928 return -1;
929 }
930
Dmitry Shmidt344abd32014-01-14 13:17:00 -0800931 if (full_config && bss->wpa && (bss->wpa_key_mgmt & WPA_KEY_MGMT_PSK) &&
Dmitry Shmidtcce06662013-11-04 18:44:24 -0800932 bss->ssid.wpa_psk == NULL && bss->ssid.wpa_passphrase == NULL &&
933 bss->ssid.wpa_psk_file == NULL &&
934 (bss->wpa_psk_radius != PSK_RADIUS_REQUIRED ||
935 bss->macaddr_acl != USE_EXTERNAL_RADIUS_AUTH)) {
936 wpa_printf(MSG_ERROR, "WPA-PSK enabled, but PSK or passphrase "
937 "is not configured.");
938 return -1;
939 }
940
Dmitry Shmidt9c175262016-03-03 10:20:07 -0800941 if (full_config && !is_zero_ether_addr(bss->bssid)) {
Dmitry Shmidtcce06662013-11-04 18:44:24 -0800942 size_t i;
943
944 for (i = 0; i < conf->num_bss; i++) {
945 if (conf->bss[i] != bss &&
946 (hostapd_mac_comp(conf->bss[i]->bssid,
947 bss->bssid) == 0)) {
948 wpa_printf(MSG_ERROR, "Duplicate BSSID " MACSTR
949 " on interface '%s' and '%s'.",
950 MAC2STR(bss->bssid),
951 conf->bss[i]->iface, bss->iface);
952 return -1;
953 }
954 }
955 }
956
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800957#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt344abd32014-01-14 13:17:00 -0800958 if (full_config && wpa_key_mgmt_ft(bss->wpa_key_mgmt) &&
Dmitry Shmidtcce06662013-11-04 18:44:24 -0800959 (bss->nas_identifier == NULL ||
960 os_strlen(bss->nas_identifier) < 1 ||
961 os_strlen(bss->nas_identifier) > FT_R0KH_ID_MAX_LEN)) {
962 wpa_printf(MSG_ERROR, "FT (IEEE 802.11r) requires "
963 "nas_identifier to be configured as a 1..48 octet "
964 "string");
965 return -1;
966 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800967#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidtcce06662013-11-04 18:44:24 -0800968
969#ifdef CONFIG_IEEE80211N
Dmitry Shmidt344abd32014-01-14 13:17:00 -0800970 if (full_config && conf->ieee80211n &&
971 conf->hw_mode == HOSTAPD_MODE_IEEE80211B) {
Dmitry Shmidtcce06662013-11-04 18:44:24 -0800972 bss->disable_11n = 1;
973 wpa_printf(MSG_ERROR, "HT (IEEE 802.11n) in 11b mode is not "
Dmitry Shmidt661b4f72014-09-29 14:58:27 -0700974 "allowed, disabling HT capabilities");
Dmitry Shmidtcce06662013-11-04 18:44:24 -0800975 }
976
Dmitry Shmidt344abd32014-01-14 13:17:00 -0800977 if (full_config && conf->ieee80211n &&
Dmitry Shmidtcce06662013-11-04 18:44:24 -0800978 bss->ssid.security_policy == SECURITY_STATIC_WEP) {
979 bss->disable_11n = 1;
980 wpa_printf(MSG_ERROR, "HT (IEEE 802.11n) with WEP is not "
981 "allowed, disabling HT capabilities");
982 }
983
Dmitry Shmidt344abd32014-01-14 13:17:00 -0800984 if (full_config && conf->ieee80211n && bss->wpa &&
Dmitry Shmidtcce06662013-11-04 18:44:24 -0800985 !(bss->wpa_pairwise & WPA_CIPHER_CCMP) &&
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800986 !(bss->rsn_pairwise & (WPA_CIPHER_CCMP | WPA_CIPHER_GCMP |
987 WPA_CIPHER_CCMP_256 | WPA_CIPHER_GCMP_256)))
988 {
Dmitry Shmidtcce06662013-11-04 18:44:24 -0800989 bss->disable_11n = 1;
990 wpa_printf(MSG_ERROR, "HT (IEEE 802.11n) with WPA/WPA2 "
991 "requires CCMP/GCMP to be enabled, disabling HT "
992 "capabilities");
993 }
994#endif /* CONFIG_IEEE80211N */
995
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -0700996#ifdef CONFIG_IEEE80211AC
997 if (full_config && conf->ieee80211ac &&
998 bss->ssid.security_policy == SECURITY_STATIC_WEP) {
999 bss->disable_11ac = 1;
1000 wpa_printf(MSG_ERROR,
1001 "VHT (IEEE 802.11ac) with WEP is not allowed, disabling VHT capabilities");
1002 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001003
1004 if (full_config && conf->ieee80211ac && bss->wpa &&
1005 !(bss->wpa_pairwise & WPA_CIPHER_CCMP) &&
1006 !(bss->rsn_pairwise & (WPA_CIPHER_CCMP | WPA_CIPHER_GCMP |
1007 WPA_CIPHER_CCMP_256 | WPA_CIPHER_GCMP_256)))
1008 {
1009 bss->disable_11ac = 1;
1010 wpa_printf(MSG_ERROR,
1011 "VHT (IEEE 802.11ac) with WPA/WPA2 requires CCMP/GCMP to be enabled, disabling VHT capabilities");
1012 }
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -07001013#endif /* CONFIG_IEEE80211AC */
1014
Dmitry Shmidt15907092014-03-25 10:42:57 -07001015#ifdef CONFIG_WPS
Dmitry Shmidt344abd32014-01-14 13:17:00 -08001016 if (full_config && bss->wps_state && bss->ignore_broadcast_ssid) {
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001017 wpa_printf(MSG_INFO, "WPS: ignore_broadcast_ssid "
1018 "configuration forced WPS to be disabled");
1019 bss->wps_state = 0;
1020 }
1021
Dmitry Shmidt344abd32014-01-14 13:17:00 -08001022 if (full_config && bss->wps_state &&
1023 bss->ssid.wep.keys_set && bss->wpa == 0) {
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001024 wpa_printf(MSG_INFO, "WPS: WEP configuration forced WPS to be "
1025 "disabled");
1026 bss->wps_state = 0;
1027 }
1028
Dmitry Shmidt344abd32014-01-14 13:17:00 -08001029 if (full_config && bss->wps_state && bss->wpa &&
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001030 (!(bss->wpa & 2) ||
Roshan Pius3a1667e2018-07-03 15:17:14 -07001031 !(bss->rsn_pairwise & (WPA_CIPHER_CCMP | WPA_CIPHER_GCMP |
1032 WPA_CIPHER_CCMP_256 |
1033 WPA_CIPHER_GCMP_256)))) {
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001034 wpa_printf(MSG_INFO, "WPS: WPA/TKIP configuration without "
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07001035 "WPA2/CCMP/GCMP forced WPS to be disabled");
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001036 bss->wps_state = 0;
1037 }
Dmitry Shmidt15907092014-03-25 10:42:57 -07001038#endif /* CONFIG_WPS */
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001039
1040#ifdef CONFIG_HS20
Dmitry Shmidt344abd32014-01-14 13:17:00 -08001041 if (full_config && bss->hs20 &&
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001042 (!(bss->wpa & 2) ||
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001043 !(bss->rsn_pairwise & (WPA_CIPHER_CCMP | WPA_CIPHER_GCMP |
1044 WPA_CIPHER_CCMP_256 |
1045 WPA_CIPHER_GCMP_256)))) {
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001046 wpa_printf(MSG_ERROR, "HS 2.0: WPA2-Enterprise/CCMP "
1047 "configuration is required for Hotspot 2.0 "
1048 "functionality");
1049 return -1;
1050 }
1051#endif /* CONFIG_HS20 */
1052
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001053#ifdef CONFIG_MBO
1054 if (full_config && bss->mbo_enabled && (bss->wpa & 2) &&
1055 bss->ieee80211w == NO_MGMT_FRAME_PROTECTION) {
1056 wpa_printf(MSG_ERROR,
1057 "MBO: PMF needs to be enabled whenever using WPA2 with MBO");
1058 return -1;
1059 }
1060#endif /* CONFIG_MBO */
1061
Hai Shalom74f70d42019-02-11 14:42:39 -08001062#ifdef CONFIG_OCV
1063 if (full_config && bss->ieee80211w == NO_MGMT_FRAME_PROTECTION &&
1064 bss->ocv) {
1065 wpa_printf(MSG_ERROR,
1066 "OCV: PMF needs to be enabled whenever using OCV");
1067 return -1;
1068 }
1069#endif /* CONFIG_OCV */
1070
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001071 return 0;
1072}
1073
1074
Dmitry Shmidt05df46a2015-05-19 11:02:01 -07001075static int hostapd_config_check_cw(struct hostapd_config *conf, int queue)
1076{
1077 int tx_cwmin = conf->tx_queue[queue].cwmin;
1078 int tx_cwmax = conf->tx_queue[queue].cwmax;
1079 int ac_cwmin = conf->wmm_ac_params[queue].cwmin;
1080 int ac_cwmax = conf->wmm_ac_params[queue].cwmax;
1081
1082 if (tx_cwmin > tx_cwmax) {
1083 wpa_printf(MSG_ERROR,
1084 "Invalid TX queue cwMin/cwMax values. cwMin(%d) greater than cwMax(%d)",
1085 tx_cwmin, tx_cwmax);
1086 return -1;
1087 }
1088 if (ac_cwmin > ac_cwmax) {
1089 wpa_printf(MSG_ERROR,
1090 "Invalid WMM AC cwMin/cwMax values. cwMin(%d) greater than cwMax(%d)",
1091 ac_cwmin, ac_cwmax);
1092 return -1;
1093 }
1094 return 0;
1095}
1096
1097
Dmitry Shmidt344abd32014-01-14 13:17:00 -08001098int hostapd_config_check(struct hostapd_config *conf, int full_config)
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001099{
1100 size_t i;
1101
Dmitry Shmidt344abd32014-01-14 13:17:00 -08001102 if (full_config && conf->ieee80211d &&
1103 (!conf->country[0] || !conf->country[1])) {
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001104 wpa_printf(MSG_ERROR, "Cannot enable IEEE 802.11d without "
1105 "setting the country_code");
1106 return -1;
1107 }
1108
Dmitry Shmidt344abd32014-01-14 13:17:00 -08001109 if (full_config && conf->ieee80211h && !conf->ieee80211d) {
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001110 wpa_printf(MSG_ERROR, "Cannot enable IEEE 802.11h without "
1111 "IEEE 802.11d enabled");
1112 return -1;
1113 }
1114
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001115 if (full_config && conf->local_pwr_constraint != -1 &&
1116 !conf->ieee80211d) {
1117 wpa_printf(MSG_ERROR, "Cannot add Power Constraint element without Country element");
1118 return -1;
1119 }
1120
1121 if (full_config && conf->spectrum_mgmt_required &&
1122 conf->local_pwr_constraint == -1) {
1123 wpa_printf(MSG_ERROR, "Cannot set Spectrum Management bit without Country and Power Constraint elements");
1124 return -1;
1125 }
1126
Dmitry Shmidt05df46a2015-05-19 11:02:01 -07001127 for (i = 0; i < NUM_TX_QUEUES; i++) {
1128 if (hostapd_config_check_cw(conf, i))
1129 return -1;
1130 }
1131
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001132 for (i = 0; i < conf->num_bss; i++) {
Dmitry Shmidt344abd32014-01-14 13:17:00 -08001133 if (hostapd_config_check_bss(conf->bss[i], conf, full_config))
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001134 return -1;
1135 }
1136
1137 return 0;
1138}
1139
1140
Dmitry Shmidt71757432014-06-02 13:50:35 -07001141void hostapd_set_security_params(struct hostapd_bss_config *bss,
1142 int full_config)
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001143{
1144 if (bss->individual_wep_key_len == 0) {
1145 /* individual keys are not use; can use key idx0 for
1146 * broadcast keys */
1147 bss->broadcast_key_idx_min = 0;
1148 }
1149
1150 if ((bss->wpa & 2) && bss->rsn_pairwise == 0)
1151 bss->rsn_pairwise = bss->wpa_pairwise;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001152 if (bss->group_cipher)
1153 bss->wpa_group = bss->group_cipher;
1154 else
1155 bss->wpa_group = wpa_select_ap_group_cipher(bss->wpa,
1156 bss->wpa_pairwise,
1157 bss->rsn_pairwise);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001158 if (!bss->wpa_group_rekey_set)
1159 bss->wpa_group_rekey = bss->wpa_group == WPA_CIPHER_TKIP ?
1160 600 : 86400;
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001161
Dmitry Shmidt71757432014-06-02 13:50:35 -07001162 if (full_config) {
1163 bss->radius->auth_server = bss->radius->auth_servers;
1164 bss->radius->acct_server = bss->radius->acct_servers;
1165 }
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001166
1167 if (bss->wpa && bss->ieee802_1x) {
1168 bss->ssid.security_policy = SECURITY_WPA;
1169 } else if (bss->wpa) {
1170 bss->ssid.security_policy = SECURITY_WPA_PSK;
1171 } else if (bss->ieee802_1x) {
1172 int cipher = WPA_CIPHER_NONE;
1173 bss->ssid.security_policy = SECURITY_IEEE_802_1X;
1174 bss->ssid.wep.default_len = bss->default_wep_key_len;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001175 if (full_config && bss->default_wep_key_len) {
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001176 cipher = bss->default_wep_key_len >= 13 ?
1177 WPA_CIPHER_WEP104 : WPA_CIPHER_WEP40;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001178 } else if (full_config && bss->ssid.wep.keys_set) {
1179 if (bss->ssid.wep.len[0] >= 13)
1180 cipher = WPA_CIPHER_WEP104;
1181 else
1182 cipher = WPA_CIPHER_WEP40;
1183 }
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001184 bss->wpa_group = cipher;
1185 bss->wpa_pairwise = cipher;
1186 bss->rsn_pairwise = cipher;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001187 if (full_config)
1188 bss->wpa_key_mgmt = WPA_KEY_MGMT_IEEE8021X_NO_WPA;
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001189 } else if (bss->ssid.wep.keys_set) {
1190 int cipher = WPA_CIPHER_WEP40;
1191 if (bss->ssid.wep.len[0] >= 13)
1192 cipher = WPA_CIPHER_WEP104;
1193 bss->ssid.security_policy = SECURITY_STATIC_WEP;
1194 bss->wpa_group = cipher;
1195 bss->wpa_pairwise = cipher;
1196 bss->rsn_pairwise = cipher;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001197 if (full_config)
1198 bss->wpa_key_mgmt = WPA_KEY_MGMT_NONE;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001199 } else if (bss->osen) {
1200 bss->ssid.security_policy = SECURITY_OSEN;
1201 bss->wpa_group = WPA_CIPHER_CCMP;
1202 bss->wpa_pairwise = 0;
1203 bss->rsn_pairwise = WPA_CIPHER_CCMP;
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001204 } else {
1205 bss->ssid.security_policy = SECURITY_PLAINTEXT;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001206 if (full_config) {
1207 bss->wpa_group = WPA_CIPHER_NONE;
1208 bss->wpa_pairwise = WPA_CIPHER_NONE;
1209 bss->rsn_pairwise = WPA_CIPHER_NONE;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001210 bss->wpa_key_mgmt = WPA_KEY_MGMT_NONE;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001211 }
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001212 }
1213}
Hai Shalom74f70d42019-02-11 14:42:39 -08001214
1215
1216int hostapd_sae_pw_id_in_use(struct hostapd_bss_config *conf)
1217{
1218 int with_id = 0, without_id = 0;
1219 struct sae_password_entry *pw;
1220
1221 if (conf->ssid.wpa_passphrase)
1222 without_id = 1;
1223
1224 for (pw = conf->sae_passwords; pw; pw = pw->next) {
1225 if (pw->identifier)
1226 with_id = 1;
1227 else
1228 without_id = 1;
1229 if (with_id && without_id)
1230 break;
1231 }
1232
1233 if (with_id && !without_id)
1234 return 2;
1235 return with_id;
1236}