/src/hostap/src/ap/ap_config.c
Line | Count | Source |
1 | | /* |
2 | | * hostapd / Configuration helper functions |
3 | | * Copyright (c) 2003-2024, Jouni Malinen <j@w1.fi> |
4 | | * |
5 | | * This software may be distributed under the terms of the BSD license. |
6 | | * See README for more details. |
7 | | */ |
8 | | |
9 | | #include "utils/includes.h" |
10 | | |
11 | | #include "utils/common.h" |
12 | | #include "crypto/sha1.h" |
13 | | #include "crypto/tls.h" |
14 | | #include "radius/radius_client.h" |
15 | | #include "common/ieee802_11_defs.h" |
16 | | #include "common/ieee802_1x_defs.h" |
17 | | #include "common/eapol_common.h" |
18 | | #include "common/dhcp.h" |
19 | | #include "common/sae.h" |
20 | | #include "eap_common/eap_wsc_common.h" |
21 | | #include "eap_server/eap.h" |
22 | | #include "wpa_auth.h" |
23 | | #include "sta_info.h" |
24 | | #include "airtime_policy.h" |
25 | | #include "ap_config.h" |
26 | | |
27 | | |
28 | | static void hostapd_config_free_vlan(struct hostapd_bss_config *bss) |
29 | 2.42k | { |
30 | 2.42k | struct hostapd_vlan *vlan, *prev; |
31 | | |
32 | 2.42k | vlan = bss->vlan; |
33 | 2.42k | prev = NULL; |
34 | 2.42k | while (vlan) { |
35 | 0 | prev = vlan; |
36 | 0 | vlan = vlan->next; |
37 | 0 | os_free(prev); |
38 | 0 | } |
39 | | |
40 | 2.42k | bss->vlan = NULL; |
41 | 2.42k | } |
42 | | |
43 | | |
44 | | #ifndef DEFAULT_WPA_DISABLE_EAPOL_KEY_RETRIES |
45 | 4.84k | #define DEFAULT_WPA_DISABLE_EAPOL_KEY_RETRIES 0 |
46 | | #endif /* DEFAULT_WPA_DISABLE_EAPOL_KEY_RETRIES */ |
47 | | |
48 | | void hostapd_config_defaults_bss(struct hostapd_bss_config *bss) |
49 | 4.84k | { |
50 | 4.84k | dl_list_init(&bss->anqp_elem); |
51 | | |
52 | 4.84k | bss->logger_syslog_level = HOSTAPD_LEVEL_INFO; |
53 | 4.84k | bss->logger_stdout_level = HOSTAPD_LEVEL_INFO; |
54 | 4.84k | bss->logger_syslog = (unsigned int) -1; |
55 | 4.84k | bss->logger_stdout = (unsigned int) -1; |
56 | | |
57 | | #ifdef CONFIG_WEP |
58 | | 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; |
64 | | #else /* CONFIG_WEP */ |
65 | 4.84k | bss->auth_algs = WPA_AUTH_ALG_OPEN; |
66 | 4.84k | #endif /* CONFIG_WEP */ |
67 | 4.84k | bss->eap_reauth_period = 3600; |
68 | | |
69 | 4.84k | bss->wpa_group_rekey = 600; |
70 | 4.84k | bss->wpa_gmk_rekey = 86400; |
71 | 4.84k | bss->wpa_deny_ptk0_rekey = PTK0_REKEY_ALLOW_ALWAYS; |
72 | 4.84k | bss->wpa_group_update_count = 4; |
73 | 4.84k | bss->wpa_pairwise_update_count = 4; |
74 | 4.84k | bss->wpa_disable_eapol_key_retries = |
75 | 4.84k | DEFAULT_WPA_DISABLE_EAPOL_KEY_RETRIES; |
76 | 4.84k | bss->wpa_key_mgmt = WPA_KEY_MGMT_PSK; |
77 | | #ifdef CONFIG_NO_TKIP |
78 | | bss->wpa_pairwise = WPA_CIPHER_CCMP; |
79 | | bss->wpa_group = WPA_CIPHER_CCMP; |
80 | | #else /* CONFIG_NO_TKIP */ |
81 | 4.84k | bss->wpa_pairwise = WPA_CIPHER_TKIP; |
82 | 4.84k | bss->wpa_group = WPA_CIPHER_TKIP; |
83 | 4.84k | #endif /* CONFIG_NO_TKIP */ |
84 | 4.84k | bss->rsn_pairwise = 0; |
85 | | |
86 | 4.84k | bss->max_num_sta = MAX_STA_COUNT; |
87 | | |
88 | 4.84k | bss->dtim_period = 2; |
89 | | |
90 | 4.84k | bss->radius_server_auth_port = 1812; |
91 | 4.84k | bss->eap_sim_db_timeout = 1; |
92 | 4.84k | bss->eap_sim_id = 3; |
93 | 4.84k | bss->eap_sim_aka_fast_reauth_limit = 1000; |
94 | 4.84k | bss->ap_max_inactivity = AP_MAX_INACTIVITY; |
95 | 4.84k | bss->bss_max_idle = 1; |
96 | 4.84k | bss->eapol_version = EAPOL_VERSION; |
97 | | |
98 | 4.84k | bss->max_listen_interval = 65535; |
99 | | |
100 | 4.84k | bss->pwd_group = 19; /* ECC: GF(p=256) */ |
101 | | |
102 | 4.84k | bss->assoc_sa_query_max_timeout = 1000; |
103 | 4.84k | bss->assoc_sa_query_retry_timeout = 201; |
104 | 4.84k | bss->group_mgmt_cipher = WPA_CIPHER_AES_128_CMAC; |
105 | | #ifdef EAP_SERVER_FAST |
106 | | /* both anonymous and authenticated provisioning */ |
107 | | bss->eap_fast_prov = 3; |
108 | | bss->pac_key_lifetime = 7 * 24 * 60 * 60; |
109 | | bss->pac_key_refresh_time = 1 * 24 * 60 * 60; |
110 | | #endif /* EAP_SERVER_FAST */ |
111 | | |
112 | | /* Set to -1 as defaults depends on HT in setup */ |
113 | 4.84k | bss->wmm_enabled = -1; |
114 | | |
115 | 4.84k | #ifdef CONFIG_IEEE80211R_AP |
116 | 4.84k | bss->ft_over_ds = 1; |
117 | 4.84k | bss->rkh_pos_timeout = 86400; |
118 | 4.84k | bss->rkh_neg_timeout = 60; |
119 | 4.84k | bss->rkh_pull_timeout = 1000; |
120 | 4.84k | bss->rkh_pull_retries = 4; |
121 | 4.84k | bss->r0_key_lifetime = 1209600; |
122 | 4.84k | #endif /* CONFIG_IEEE80211R_AP */ |
123 | | |
124 | 4.84k | bss->radius_das_time_window = 300; |
125 | 4.84k | bss->radius_require_message_authenticator = 1; |
126 | | |
127 | 4.84k | bss->anti_clogging_threshold = 5; |
128 | 4.84k | bss->sae_sync = 3; |
129 | | |
130 | 4.84k | bss->gas_frag_limit = 1400; |
131 | | |
132 | | #ifdef CONFIG_FILS |
133 | | dl_list_init(&bss->fils_realms); |
134 | | bss->fils_hlp_wait_time = 30; |
135 | | bss->dhcp_server_port = DHCP_SERVER_PORT; |
136 | | bss->dhcp_relay_port = DHCP_SERVER_PORT; |
137 | | bss->fils_discovery_min_int = 20; |
138 | | #endif /* CONFIG_FILS */ |
139 | | |
140 | 4.84k | bss->broadcast_deauth = 1; |
141 | | |
142 | | #ifdef CONFIG_MBO |
143 | | bss->mbo_cell_data_conn_pref = -1; |
144 | | #endif /* CONFIG_MBO */ |
145 | | |
146 | | /* Disable TLS v1.3 by default for now to avoid interoperability issue. |
147 | | * This can be enabled by default once the implementation has been fully |
148 | | * completed and tested with other implementations. */ |
149 | 4.84k | bss->tls_flags = TLS_CONN_DISABLE_TLSv1_3; |
150 | | |
151 | 4.84k | bss->max_auth_rounds = 100; |
152 | 4.84k | bss->max_auth_rounds_short = 50; |
153 | | |
154 | 4.84k | bss->send_probe_response = 1; |
155 | | |
156 | 4.84k | #ifdef CONFIG_HS20 |
157 | 4.84k | bss->hs20_release = (HS20_VERSION >> 4) + 1; |
158 | 4.84k | #endif /* CONFIG_HS20 */ |
159 | | |
160 | | #ifdef CONFIG_MACSEC |
161 | | bss->mka_priority = DEFAULT_PRIO_NOT_KEY_SERVER; |
162 | | bss->macsec_port = 1; |
163 | | #endif /* CONFIG_MACSEC */ |
164 | | |
165 | | /* Default to strict CRL checking. */ |
166 | 4.84k | bss->check_crl_strict = 1; |
167 | | |
168 | 4.84k | bss->multi_ap_profile = MULTI_AP_PROFILE_2; |
169 | | |
170 | | #ifdef CONFIG_TESTING_OPTIONS |
171 | | bss->sae_commit_status = -1; |
172 | | bss->test_assoc_comeback_type = -1; |
173 | | bss->association_response_status_code = -1; |
174 | | #endif /* CONFIG_TESTING_OPTIONS */ |
175 | | |
176 | | #ifdef CONFIG_PASN |
177 | | /* comeback after 10 TUs */ |
178 | | bss->pasn_comeback_after = 10; |
179 | | bss->pasn_noauth = 1; |
180 | | #endif /* CONFIG_PASN */ |
181 | 4.84k | bss->urnm_mfpr_x20 = -1; |
182 | 4.84k | bss->urnm_mfpr = -1; |
183 | | #ifdef CONFIG_ENC_ASSOC |
184 | | bss->assoc_frame_encryption = 0; |
185 | | bss->pmksa_caching_privacy = 0; |
186 | | bss->eap_using_authentication_frames = 0; |
187 | | #endif /* CONFIG_ENC_ASSOC */ |
188 | 4.84k | } |
189 | | |
190 | | |
191 | | struct hostapd_config * hostapd_config_defaults(void) |
192 | 2.42k | { |
193 | 19.3k | #define ecw2cw(ecw) ((1 << (ecw)) - 1) |
194 | | |
195 | 2.42k | struct hostapd_config *conf; |
196 | 2.42k | struct hostapd_bss_config *bss; |
197 | 2.42k | const int aCWmin = 4, aCWmax = 10; |
198 | 2.42k | const struct hostapd_wmm_ac_params ac_bk = |
199 | 2.42k | { aCWmin, aCWmax, 7, 0, 0 }; /* background traffic */ |
200 | 2.42k | const struct hostapd_wmm_ac_params ac_be = |
201 | 2.42k | { aCWmin, aCWmax, 3, 0, 0 }; /* best effort traffic */ |
202 | 2.42k | const struct hostapd_wmm_ac_params ac_vi = /* video traffic */ |
203 | 2.42k | { aCWmin - 1, aCWmin, 2, 3008 / 32, 0 }; |
204 | 2.42k | const struct hostapd_wmm_ac_params ac_vo = /* voice traffic */ |
205 | 2.42k | { aCWmin - 2, aCWmin - 1, 2, 1504 / 32, 0 }; |
206 | 2.42k | const struct hostapd_tx_queue_params txq_bk = |
207 | 2.42k | { 7, ecw2cw(aCWmin), ecw2cw(aCWmax), 0 }; |
208 | 2.42k | const struct hostapd_tx_queue_params txq_be = |
209 | 2.42k | { 3, ecw2cw(aCWmin), 4 * (ecw2cw(aCWmin) + 1) - 1, 0}; |
210 | 2.42k | const struct hostapd_tx_queue_params txq_vi = |
211 | 2.42k | { 1, (ecw2cw(aCWmin) + 1) / 2 - 1, ecw2cw(aCWmin), 30}; |
212 | 2.42k | const struct hostapd_tx_queue_params txq_vo = |
213 | 2.42k | { 1, (ecw2cw(aCWmin) + 1) / 4 - 1, |
214 | 2.42k | (ecw2cw(aCWmin) + 1) / 2 - 1, 15}; |
215 | | |
216 | 2.42k | #undef ecw2cw |
217 | | |
218 | 2.42k | conf = os_zalloc(sizeof(*conf)); |
219 | 2.42k | bss = os_zalloc(sizeof(*bss)); |
220 | 2.42k | if (conf == NULL || bss == NULL) { |
221 | 0 | wpa_printf(MSG_ERROR, "Failed to allocate memory for " |
222 | 0 | "configuration data."); |
223 | 0 | os_free(conf); |
224 | 0 | os_free(bss); |
225 | 0 | return NULL; |
226 | 0 | } |
227 | 2.42k | conf->bss = os_calloc(1, sizeof(struct hostapd_bss_config *)); |
228 | 2.42k | if (conf->bss == NULL) { |
229 | 0 | os_free(conf); |
230 | 0 | os_free(bss); |
231 | 0 | return NULL; |
232 | 0 | } |
233 | 2.42k | conf->bss[0] = bss; |
234 | | |
235 | 2.42k | bss->radius = os_zalloc(sizeof(*bss->radius)); |
236 | 2.42k | if (bss->radius == NULL) { |
237 | 0 | os_free(conf->bss); |
238 | 0 | os_free(conf); |
239 | 0 | os_free(bss); |
240 | 0 | return NULL; |
241 | 0 | } |
242 | | |
243 | 2.42k | hostapd_config_defaults_bss(bss); |
244 | | |
245 | 2.42k | conf->num_bss = 1; |
246 | | |
247 | 2.42k | conf->beacon_int = 100; |
248 | 2.42k | conf->rts_threshold = -2; /* use driver default: 2347 */ |
249 | 2.42k | conf->fragm_threshold = -2; /* user driver default: 2346 */ |
250 | | /* Set to invalid value means do not add Power Constraint IE */ |
251 | 2.42k | conf->local_pwr_constraint = -1; |
252 | | |
253 | 2.42k | conf->wmm_ac_params[0] = ac_be; |
254 | 2.42k | conf->wmm_ac_params[1] = ac_bk; |
255 | 2.42k | conf->wmm_ac_params[2] = ac_vi; |
256 | 2.42k | conf->wmm_ac_params[3] = ac_vo; |
257 | | |
258 | 2.42k | conf->tx_queue[0] = txq_vo; |
259 | 2.42k | conf->tx_queue[1] = txq_vi; |
260 | 2.42k | conf->tx_queue[2] = txq_be; |
261 | 2.42k | conf->tx_queue[3] = txq_bk; |
262 | | |
263 | 2.42k | conf->ht_capab = HT_CAP_INFO_SMPS_DISABLED; |
264 | | |
265 | 2.42k | conf->ap_table_max_size = 255; |
266 | 2.42k | conf->ap_table_expiration_time = 60; |
267 | 2.42k | conf->track_sta_max_age = 180; |
268 | | |
269 | | #ifdef CONFIG_TESTING_OPTIONS |
270 | | conf->ignore_probe_probability = 0.0; |
271 | | conf->ignore_auth_probability = 0.0; |
272 | | conf->ignore_assoc_probability = 0.0; |
273 | | conf->ignore_reassoc_probability = 0.0; |
274 | | conf->corrupt_gtk_rekey_mic_probability = 0.0; |
275 | | conf->ecsa_ie_only = 0; |
276 | | #endif /* CONFIG_TESTING_OPTIONS */ |
277 | | |
278 | 2.42k | conf->acs = 0; |
279 | 2.42k | conf->acs_ch_list.num = 0; |
280 | | #ifdef CONFIG_ACS |
281 | | conf->acs_num_scans = 5; |
282 | | #endif /* CONFIG_ACS */ |
283 | | |
284 | | #ifdef CONFIG_IEEE80211AX |
285 | | conf->he_op.he_rts_threshold = HE_OPERATION_RTS_THRESHOLD_MASK >> |
286 | | HE_OPERATION_RTS_THRESHOLD_OFFSET; |
287 | | /* Set default basic MCS/NSS set to single stream MCS 0-7 */ |
288 | | conf->he_op.he_basic_mcs_nss_set = 0xfffc; |
289 | | conf->he_op.he_bss_color_disabled = 1; |
290 | | conf->he_op.he_bss_color_partial = 0; |
291 | | conf->he_op.he_bss_color = os_random() % 63 + 1; |
292 | | conf->he_op.he_twt_responder = 1; |
293 | | conf->he_6ghz_max_mpdu = 2; |
294 | | conf->he_6ghz_max_ampdu_len_exp = 7; |
295 | | conf->he_6ghz_rx_ant_pat = 1; |
296 | | conf->he_6ghz_tx_ant_pat = 1; |
297 | | conf->he_6ghz_reg_pwr_type = HE_REG_INFO_6GHZ_AP_TYPE_VLP; |
298 | | conf->reg_def_cli_eirp_psd = -1; |
299 | | conf->reg_sub_cli_eirp_psd = -1; |
300 | | conf->reg_def_cli_eirp = -1; |
301 | | #endif /* CONFIG_IEEE80211AX */ |
302 | | |
303 | | /* The third octet of the country string uses an ASCII space character |
304 | | * by default to indicate that the regulations encompass all |
305 | | * environments for the current frequency band in the country. */ |
306 | 2.42k | conf->country[2] = ' '; |
307 | | |
308 | 2.42k | conf->rssi_reject_assoc_rssi = 0; |
309 | 2.42k | conf->rssi_reject_assoc_timeout = 30; |
310 | | |
311 | 2.42k | #ifdef CONFIG_AIRTIME_POLICY |
312 | 2.42k | conf->airtime_update_interval = AIRTIME_DEFAULT_UPDATE_INTERVAL; |
313 | 2.42k | #endif /* CONFIG_AIRTIME_POLICY */ |
314 | | |
315 | 2.42k | hostapd_set_and_check_bw320_offset(conf, 0); |
316 | | |
317 | 2.42k | conf->disable_mcs15_rx = true; |
318 | | |
319 | 2.42k | return conf; |
320 | 2.42k | } |
321 | | |
322 | | |
323 | | int hostapd_mac_comp(const void *a, const void *b) |
324 | 0 | { |
325 | 0 | return os_memcmp(a, b, sizeof(macaddr)); |
326 | 0 | } |
327 | | |
328 | | |
329 | | static int hostapd_config_read_wpa_psk(const char *fname, |
330 | | struct hostapd_ssid *ssid) |
331 | 0 | { |
332 | 0 | FILE *f; |
333 | 0 | char buf[128], *pos; |
334 | 0 | const char *keyid; |
335 | 0 | char *context; |
336 | 0 | char *context2; |
337 | 0 | char *token; |
338 | 0 | char *name; |
339 | 0 | char *value; |
340 | 0 | int line = 0, ret = 0, len, ok; |
341 | 0 | u8 addr[ETH_ALEN]; |
342 | 0 | struct hostapd_wpa_psk *psk; |
343 | |
|
344 | 0 | if (!fname) |
345 | 0 | return 0; |
346 | | |
347 | 0 | f = fopen(fname, "r"); |
348 | 0 | if (!f) { |
349 | 0 | wpa_printf(MSG_ERROR, "WPA PSK file '%s' not found.", fname); |
350 | 0 | return -1; |
351 | 0 | } |
352 | | |
353 | 0 | while (fgets(buf, sizeof(buf), f)) { |
354 | 0 | int vlan_id = 0; |
355 | 0 | int wps = 0; |
356 | |
|
357 | 0 | line++; |
358 | |
|
359 | 0 | if (buf[0] == '#') |
360 | 0 | continue; |
361 | 0 | pos = buf; |
362 | 0 | while (*pos != '\0') { |
363 | 0 | if (*pos == '\n') { |
364 | 0 | *pos = '\0'; |
365 | 0 | break; |
366 | 0 | } |
367 | 0 | pos++; |
368 | 0 | } |
369 | 0 | if (buf[0] == '\0') |
370 | 0 | continue; |
371 | | |
372 | 0 | context = NULL; |
373 | 0 | keyid = NULL; |
374 | 0 | while ((token = str_token(buf, " ", &context))) { |
375 | 0 | if (!os_strchr(token, '=')) |
376 | 0 | break; |
377 | 0 | context2 = NULL; |
378 | 0 | name = str_token(token, "=", &context2); |
379 | 0 | if (!name) |
380 | 0 | break; |
381 | 0 | value = str_token(token, "", &context2); |
382 | 0 | if (!value) |
383 | 0 | value = ""; |
384 | 0 | if (!os_strcmp(name, "keyid")) { |
385 | 0 | keyid = value; |
386 | 0 | } else if (!os_strcmp(name, "wps")) { |
387 | 0 | wps = atoi(value); |
388 | 0 | } else if (!os_strcmp(name, "vlanid")) { |
389 | 0 | vlan_id = atoi(value); |
390 | 0 | } else { |
391 | 0 | wpa_printf(MSG_ERROR, |
392 | 0 | "Unrecognized '%s=%s' on line %d in '%s'", |
393 | 0 | name, value, line, fname); |
394 | 0 | ret = -1; |
395 | 0 | break; |
396 | 0 | } |
397 | 0 | } |
398 | |
|
399 | 0 | if (ret == -1) |
400 | 0 | break; |
401 | | |
402 | 0 | if (!token) |
403 | 0 | token = ""; |
404 | 0 | if (hwaddr_aton(token, addr)) { |
405 | 0 | wpa_printf(MSG_ERROR, |
406 | 0 | "Invalid MAC address '%s' on line %d in '%s'", |
407 | 0 | token, line, fname); |
408 | 0 | ret = -1; |
409 | 0 | break; |
410 | 0 | } |
411 | | |
412 | 0 | psk = os_zalloc(sizeof(*psk)); |
413 | 0 | if (psk == NULL) { |
414 | 0 | wpa_printf(MSG_ERROR, "WPA PSK allocation failed"); |
415 | 0 | ret = -1; |
416 | 0 | break; |
417 | 0 | } |
418 | 0 | psk->vlan_id = vlan_id; |
419 | 0 | if (is_zero_ether_addr(addr)) |
420 | 0 | psk->group = 1; |
421 | 0 | else |
422 | 0 | os_memcpy(psk->addr, addr, ETH_ALEN); |
423 | |
|
424 | 0 | pos = str_token(buf, "", &context); |
425 | 0 | if (!pos) { |
426 | 0 | wpa_printf(MSG_ERROR, "No PSK on line %d in '%s'", |
427 | 0 | line, fname); |
428 | 0 | os_free(psk); |
429 | 0 | ret = -1; |
430 | 0 | break; |
431 | 0 | } |
432 | | |
433 | 0 | ok = 0; |
434 | 0 | len = os_strlen(pos); |
435 | 0 | if (len == 2 * PMK_LEN && |
436 | 0 | hexstr2bin(pos, psk->psk, PMK_LEN) == 0) |
437 | 0 | ok = 1; |
438 | 0 | else if (len >= 8 && len < 64 && |
439 | 0 | pbkdf2_sha1(pos, ssid->ssid, ssid->ssid_len, |
440 | 0 | 4096, psk->psk, PMK_LEN) == 0) |
441 | 0 | ok = 1; |
442 | 0 | if (!ok) { |
443 | 0 | wpa_printf(MSG_ERROR, |
444 | 0 | "Invalid PSK '%s' on line %d in '%s'", |
445 | 0 | pos, line, fname); |
446 | 0 | os_free(psk); |
447 | 0 | ret = -1; |
448 | 0 | break; |
449 | 0 | } |
450 | | |
451 | 0 | if (keyid) { |
452 | 0 | len = os_strlcpy(psk->keyid, keyid, sizeof(psk->keyid)); |
453 | 0 | if ((size_t) len >= sizeof(psk->keyid)) { |
454 | 0 | wpa_printf(MSG_ERROR, |
455 | 0 | "PSK keyid too long on line %d in '%s'", |
456 | 0 | line, fname); |
457 | 0 | os_free(psk); |
458 | 0 | ret = -1; |
459 | 0 | break; |
460 | 0 | } |
461 | 0 | } |
462 | | |
463 | 0 | psk->wps = wps; |
464 | |
|
465 | 0 | psk->next = ssid->wpa_psk; |
466 | 0 | ssid->wpa_psk = psk; |
467 | 0 | } |
468 | |
|
469 | 0 | fclose(f); |
470 | |
|
471 | 0 | return ret; |
472 | 0 | } |
473 | | |
474 | | |
475 | | static int hostapd_derive_psk(struct hostapd_ssid *ssid) |
476 | 0 | { |
477 | 0 | ssid->wpa_psk = os_zalloc(sizeof(struct hostapd_wpa_psk)); |
478 | 0 | if (ssid->wpa_psk == NULL) { |
479 | 0 | wpa_printf(MSG_ERROR, "Unable to alloc space for PSK"); |
480 | 0 | return -1; |
481 | 0 | } |
482 | 0 | wpa_hexdump_ascii(MSG_DEBUG, "SSID", |
483 | 0 | (u8 *) ssid->ssid, ssid->ssid_len); |
484 | 0 | wpa_hexdump_ascii_key(MSG_DEBUG, "PSK (ASCII passphrase)", |
485 | 0 | (u8 *) ssid->wpa_passphrase, |
486 | 0 | os_strlen(ssid->wpa_passphrase)); |
487 | 0 | if (pbkdf2_sha1(ssid->wpa_passphrase, |
488 | 0 | ssid->ssid, ssid->ssid_len, |
489 | 0 | 4096, ssid->wpa_psk->psk, PMK_LEN) != 0) { |
490 | 0 | wpa_printf(MSG_ERROR, "Error in pbkdf2_sha1()"); |
491 | 0 | return -1; |
492 | 0 | } |
493 | 0 | wpa_hexdump_key(MSG_DEBUG, "PSK (from passphrase)", |
494 | 0 | ssid->wpa_psk->psk, PMK_LEN); |
495 | 0 | return 0; |
496 | 0 | } |
497 | | |
498 | | |
499 | | int hostapd_setup_sae_pt(struct hostapd_bss_config *conf) |
500 | 0 | { |
501 | | #ifdef CONFIG_SAE |
502 | | struct hostapd_ssid *ssid = &conf->ssid; |
503 | | struct sae_password_entry *pw; |
504 | | int *groups = conf->sae_groups; |
505 | | int default_groups[] = { 19, 0, 0 }; |
506 | | |
507 | | if ((conf->sae_pwe == SAE_PWE_HUNT_AND_PECK && |
508 | | !hostapd_sae_pw_id_in_use(conf) && |
509 | | !wpa_key_mgmt_sae_ext_key(conf->wpa_key_mgmt | |
510 | | conf->rsn_override_key_mgmt | |
511 | | conf->rsn_override_key_mgmt_2) && |
512 | | !hostapd_sae_pk_in_use(conf)) || |
513 | | conf->sae_pwe == SAE_PWE_FORCE_HUNT_AND_PECK || |
514 | | !wpa_key_mgmt_sae(conf->wpa_key_mgmt | |
515 | | conf->rsn_override_key_mgmt | |
516 | | conf->rsn_override_key_mgmt_2)) |
517 | | return 0; /* PT not needed */ |
518 | | |
519 | | if (!groups) { |
520 | | groups = default_groups; |
521 | | if (wpa_key_mgmt_sae_ext_key(conf->wpa_key_mgmt | |
522 | | conf->rsn_override_key_mgmt | |
523 | | conf->rsn_override_key_mgmt_2)) |
524 | | default_groups[1] = 20; |
525 | | } |
526 | | |
527 | | sae_deinit_pt(ssid->pt); |
528 | | ssid->pt = NULL; |
529 | | if (ssid->wpa_passphrase) { |
530 | | ssid->pt = sae_derive_pt(groups, ssid->ssid, ssid->ssid_len, |
531 | | (const u8 *) ssid->wpa_passphrase, |
532 | | os_strlen(ssid->wpa_passphrase), |
533 | | NULL, 0); |
534 | | if (!ssid->pt) |
535 | | return -1; |
536 | | } |
537 | | |
538 | | for (pw = conf->sae_passwords; pw; pw = pw->next) { |
539 | | sae_deinit_pt(pw->pt); |
540 | | pw->pt = sae_derive_pt(groups, ssid->ssid, ssid->ssid_len, |
541 | | (const u8 *) pw->password, |
542 | | os_strlen(pw->password), |
543 | | (const u8 *) pw->identifier, |
544 | | pw->identifier ? |
545 | | os_strlen(pw->identifier) : 0); |
546 | | if (!pw->pt) |
547 | | return -1; |
548 | | } |
549 | | #endif /* CONFIG_SAE */ |
550 | |
|
551 | 0 | return 0; |
552 | 0 | } |
553 | | |
554 | | |
555 | | int hostapd_setup_wpa_psk(struct hostapd_bss_config *conf) |
556 | 0 | { |
557 | 0 | struct hostapd_ssid *ssid = &conf->ssid; |
558 | |
|
559 | 0 | if (hostapd_setup_sae_pt(conf) < 0) |
560 | 0 | return -1; |
561 | | |
562 | 0 | if (ssid->wpa_passphrase != NULL) { |
563 | 0 | if (ssid->wpa_psk != NULL) { |
564 | 0 | wpa_printf(MSG_DEBUG, "Using pre-configured WPA PSK " |
565 | 0 | "instead of passphrase"); |
566 | 0 | } else { |
567 | 0 | wpa_printf(MSG_DEBUG, "Deriving WPA PSK based on " |
568 | 0 | "passphrase"); |
569 | 0 | if (hostapd_derive_psk(ssid) < 0) |
570 | 0 | return -1; |
571 | 0 | } |
572 | 0 | ssid->wpa_psk->group = 1; |
573 | 0 | } |
574 | | |
575 | 0 | return hostapd_config_read_wpa_psk(ssid->wpa_psk_file, &conf->ssid); |
576 | 0 | } |
577 | | |
578 | | |
579 | | static void hostapd_config_free_radius(struct hostapd_radius_server *servers, |
580 | | int num_servers) |
581 | 4.84k | { |
582 | 4.84k | int i; |
583 | | |
584 | 4.84k | for (i = 0; i < num_servers; i++) { |
585 | 0 | os_free(servers[i].shared_secret); |
586 | 0 | os_free(servers[i].ca_cert); |
587 | 0 | os_free(servers[i].client_cert); |
588 | 0 | os_free(servers[i].private_key); |
589 | 0 | os_free(servers[i].private_key_passwd); |
590 | 0 | } |
591 | 4.84k | os_free(servers); |
592 | 4.84k | } |
593 | | |
594 | | |
595 | | struct hostapd_radius_attr * |
596 | | hostapd_config_get_radius_attr(struct hostapd_radius_attr *attr, u8 type) |
597 | 0 | { |
598 | 0 | for (; attr; attr = attr->next) { |
599 | 0 | if (attr->type == type) |
600 | 0 | return attr; |
601 | 0 | } |
602 | 0 | return NULL; |
603 | 0 | } |
604 | | |
605 | | |
606 | | struct hostapd_radius_attr * hostapd_parse_radius_attr(const char *value) |
607 | 0 | { |
608 | 0 | const char *pos; |
609 | 0 | char syntax; |
610 | 0 | struct hostapd_radius_attr *attr; |
611 | 0 | size_t len; |
612 | |
|
613 | 0 | attr = os_zalloc(sizeof(*attr)); |
614 | 0 | if (!attr) |
615 | 0 | return NULL; |
616 | | |
617 | 0 | attr->type = atoi(value); |
618 | |
|
619 | 0 | pos = os_strchr(value, ':'); |
620 | 0 | if (!pos) { |
621 | 0 | attr->val = wpabuf_alloc(1); |
622 | 0 | if (!attr->val) { |
623 | 0 | os_free(attr); |
624 | 0 | return NULL; |
625 | 0 | } |
626 | 0 | wpabuf_put_u8(attr->val, 0); |
627 | 0 | return attr; |
628 | 0 | } |
629 | | |
630 | 0 | pos++; |
631 | 0 | if (pos[0] == '\0' || pos[1] != ':') { |
632 | 0 | os_free(attr); |
633 | 0 | return NULL; |
634 | 0 | } |
635 | 0 | syntax = *pos++; |
636 | 0 | pos++; |
637 | |
|
638 | 0 | switch (syntax) { |
639 | 0 | case 's': |
640 | 0 | attr->val = wpabuf_alloc_copy(pos, os_strlen(pos)); |
641 | 0 | break; |
642 | 0 | case 'x': |
643 | 0 | len = os_strlen(pos); |
644 | 0 | if (len & 1) |
645 | 0 | break; |
646 | 0 | len /= 2; |
647 | 0 | attr->val = wpabuf_alloc(len); |
648 | 0 | if (!attr->val) |
649 | 0 | break; |
650 | 0 | if (hexstr2bin(pos, wpabuf_put(attr->val, len), len) < 0) { |
651 | 0 | wpabuf_free(attr->val); |
652 | 0 | os_free(attr); |
653 | 0 | return NULL; |
654 | 0 | } |
655 | 0 | break; |
656 | 0 | case 'd': |
657 | 0 | attr->val = wpabuf_alloc(4); |
658 | 0 | if (attr->val) |
659 | 0 | wpabuf_put_be32(attr->val, atoi(pos)); |
660 | 0 | break; |
661 | 0 | default: |
662 | 0 | os_free(attr); |
663 | 0 | return NULL; |
664 | 0 | } |
665 | | |
666 | 0 | if (!attr->val) { |
667 | 0 | os_free(attr); |
668 | 0 | return NULL; |
669 | 0 | } |
670 | | |
671 | 0 | return attr; |
672 | 0 | } |
673 | | |
674 | | |
675 | | void hostapd_config_free_radius_attr(struct hostapd_radius_attr *attr) |
676 | 4.84k | { |
677 | 4.84k | struct hostapd_radius_attr *prev; |
678 | | |
679 | 4.84k | while (attr) { |
680 | 0 | prev = attr; |
681 | 0 | attr = attr->next; |
682 | 0 | wpabuf_free(prev->val); |
683 | 0 | os_free(prev); |
684 | 0 | } |
685 | 4.84k | } |
686 | | |
687 | | |
688 | | void hostapd_config_free_eap_user(struct hostapd_eap_user *user) |
689 | 0 | { |
690 | 0 | hostapd_config_free_radius_attr(user->accept_attr); |
691 | 0 | os_free(user->identity); |
692 | 0 | bin_clear_free(user->password, user->password_len); |
693 | 0 | bin_clear_free(user->salt, user->salt_len); |
694 | 0 | os_free(user); |
695 | 0 | } |
696 | | |
697 | | |
698 | | void hostapd_config_free_eap_users(struct hostapd_eap_user *user) |
699 | 2.42k | { |
700 | 2.42k | struct hostapd_eap_user *prev_user; |
701 | | |
702 | 2.42k | while (user) { |
703 | 0 | prev_user = user; |
704 | 0 | user = user->next; |
705 | 0 | hostapd_config_free_eap_user(prev_user); |
706 | 0 | } |
707 | 2.42k | } |
708 | | |
709 | | |
710 | | #ifdef CONFIG_WEP |
711 | | static void hostapd_config_free_wep(struct hostapd_wep_keys *keys) |
712 | | { |
713 | | int i; |
714 | | for (i = 0; i < NUM_WEP_KEYS; i++) { |
715 | | bin_clear_free(keys->key[i], keys->len[i]); |
716 | | keys->key[i] = NULL; |
717 | | } |
718 | | } |
719 | | #endif /* CONFIG_WEP */ |
720 | | |
721 | | |
722 | | void hostapd_config_clear_wpa_psk(struct hostapd_wpa_psk **l) |
723 | 4.84k | { |
724 | 4.84k | struct hostapd_wpa_psk *psk, *tmp; |
725 | | |
726 | 4.84k | for (psk = *l; psk;) { |
727 | 0 | tmp = psk; |
728 | 0 | psk = psk->next; |
729 | 0 | bin_clear_free(tmp, sizeof(*tmp)); |
730 | 0 | } |
731 | 4.84k | *l = NULL; |
732 | 4.84k | } |
733 | | |
734 | | |
735 | | #ifdef CONFIG_IEEE80211R_AP |
736 | | |
737 | | void hostapd_config_clear_rxkhs(struct hostapd_bss_config *conf) |
738 | 2.42k | { |
739 | 2.42k | struct ft_remote_r0kh *r0kh, *r0kh_prev; |
740 | 2.42k | struct ft_remote_r1kh *r1kh, *r1kh_prev; |
741 | | |
742 | 2.42k | r0kh = conf->r0kh_list; |
743 | 2.42k | conf->r0kh_list = NULL; |
744 | 2.42k | while (r0kh) { |
745 | 0 | r0kh_prev = r0kh; |
746 | 0 | r0kh = r0kh->next; |
747 | 0 | os_free(r0kh_prev); |
748 | 0 | } |
749 | | |
750 | 2.42k | r1kh = conf->r1kh_list; |
751 | 2.42k | conf->r1kh_list = NULL; |
752 | 2.42k | while (r1kh) { |
753 | 0 | r1kh_prev = r1kh; |
754 | 0 | r1kh = r1kh->next; |
755 | 0 | os_free(r1kh_prev); |
756 | 0 | } |
757 | 2.42k | } |
758 | | |
759 | | #endif /* CONFIG_IEEE80211R_AP */ |
760 | | |
761 | | |
762 | | static void hostapd_config_free_anqp_elem(struct hostapd_bss_config *conf) |
763 | 2.42k | { |
764 | 2.42k | struct anqp_element *elem; |
765 | | |
766 | 2.42k | while ((elem = dl_list_first(&conf->anqp_elem, struct anqp_element, |
767 | 2.42k | list))) { |
768 | 0 | dl_list_del(&elem->list); |
769 | 0 | wpabuf_free(elem->payload); |
770 | 0 | os_free(elem); |
771 | 0 | } |
772 | 2.42k | } |
773 | | |
774 | | |
775 | | static void hostapd_config_free_fils_realms(struct hostapd_bss_config *conf) |
776 | 2.42k | { |
777 | | #ifdef CONFIG_FILS |
778 | | struct fils_realm *realm; |
779 | | |
780 | | while ((realm = dl_list_first(&conf->fils_realms, struct fils_realm, |
781 | | list))) { |
782 | | dl_list_del(&realm->list); |
783 | | os_free(realm); |
784 | | } |
785 | | #endif /* CONFIG_FILS */ |
786 | 2.42k | } |
787 | | |
788 | | |
789 | | static void hostapd_config_free_sae_passwords(struct hostapd_bss_config *conf) |
790 | 2.42k | { |
791 | 2.42k | struct sae_password_entry *pw, *tmp; |
792 | | |
793 | 2.42k | pw = conf->sae_passwords; |
794 | 2.42k | conf->sae_passwords = NULL; |
795 | 2.42k | while (pw) { |
796 | 0 | tmp = pw; |
797 | 0 | pw = pw->next; |
798 | 0 | str_clear_free(tmp->password); |
799 | 0 | os_free(tmp->identifier); |
800 | | #ifdef CONFIG_SAE |
801 | | sae_deinit_pt(tmp->pt); |
802 | | #endif /* CONFIG_SAE */ |
803 | | #ifdef CONFIG_SAE_PK |
804 | | sae_deinit_pk(tmp->pk); |
805 | | #endif /* CONFIG_SAE_PK */ |
806 | 0 | os_free(tmp->success_mac); |
807 | 0 | os_free(tmp->fail_mac); |
808 | 0 | os_free(tmp); |
809 | 0 | } |
810 | 2.42k | } |
811 | | |
812 | | |
813 | | #ifdef CONFIG_DPP2 |
814 | | static void hostapd_dpp_controller_conf_free(struct dpp_controller_conf *conf) |
815 | | { |
816 | | struct dpp_controller_conf *prev; |
817 | | |
818 | | while (conf) { |
819 | | prev = conf; |
820 | | conf = conf->next; |
821 | | os_free(prev); |
822 | | } |
823 | | } |
824 | | #endif /* CONFIG_DPP2 */ |
825 | | |
826 | | |
827 | | void hostapd_config_free_bss(struct hostapd_bss_config *conf) |
828 | 2.42k | { |
829 | 2.42k | #if defined(CONFIG_WPS) || defined(CONFIG_HS20) |
830 | 2.42k | size_t i; |
831 | 2.42k | #endif |
832 | | |
833 | 2.42k | if (conf == NULL) |
834 | 0 | return; |
835 | | |
836 | 2.42k | hostapd_config_clear_wpa_psk(&conf->ssid.wpa_psk); |
837 | | |
838 | 2.42k | str_clear_free(conf->ssid.wpa_passphrase); |
839 | 2.42k | os_free(conf->ssid.wpa_psk_file); |
840 | | #ifdef CONFIG_WEP |
841 | | hostapd_config_free_wep(&conf->ssid.wep); |
842 | | #endif /* CONFIG_WEP */ |
843 | | #ifdef CONFIG_FULL_DYNAMIC_VLAN |
844 | | os_free(conf->ssid.vlan_tagged_interface); |
845 | | #endif /* CONFIG_FULL_DYNAMIC_VLAN */ |
846 | | #ifdef CONFIG_SAE |
847 | | sae_deinit_pt(conf->ssid.pt); |
848 | | #endif /* CONFIG_SAE */ |
849 | | |
850 | 2.42k | hostapd_config_free_eap_users(conf->eap_user); |
851 | 2.42k | os_free(conf->eap_user_sqlite); |
852 | | |
853 | 2.42k | os_free(conf->eap_req_id_text); |
854 | 2.42k | os_free(conf->erp_domain); |
855 | 2.42k | os_free(conf->accept_mac); |
856 | 2.42k | os_free(conf->deny_mac); |
857 | 2.42k | os_free(conf->nas_identifier); |
858 | 2.42k | if (conf->radius) { |
859 | 2.42k | hostapd_config_free_radius(conf->radius->auth_servers, |
860 | 2.42k | conf->radius->num_auth_servers); |
861 | 2.42k | hostapd_config_free_radius(conf->radius->acct_servers, |
862 | 2.42k | conf->radius->num_acct_servers); |
863 | 2.42k | os_free(conf->radius->force_client_dev); |
864 | 2.42k | } |
865 | 2.42k | hostapd_config_free_radius_attr(conf->radius_auth_req_attr); |
866 | 2.42k | hostapd_config_free_radius_attr(conf->radius_acct_req_attr); |
867 | 2.42k | os_free(conf->radius_req_attr_sqlite); |
868 | 2.42k | os_free(conf->rsn_preauth_interfaces); |
869 | 2.42k | os_free(conf->ctrl_interface); |
870 | 2.42k | os_free(conf->config_id); |
871 | 2.42k | os_free(conf->ca_cert); |
872 | 2.42k | os_free(conf->server_cert); |
873 | 2.42k | os_free(conf->server_cert2); |
874 | 2.42k | os_free(conf->private_key); |
875 | 2.42k | os_free(conf->private_key2); |
876 | 2.42k | os_free(conf->private_key_passwd); |
877 | 2.42k | os_free(conf->private_key_passwd2); |
878 | 2.42k | os_free(conf->check_cert_subject); |
879 | 2.42k | os_free(conf->ocsp_stapling_response); |
880 | 2.42k | os_free(conf->ocsp_stapling_response_multi); |
881 | 2.42k | os_free(conf->dh_file); |
882 | 2.42k | os_free(conf->openssl_ciphers); |
883 | 2.42k | os_free(conf->openssl_ecdh_curves); |
884 | 2.42k | os_free(conf->pac_opaque_encr_key); |
885 | 2.42k | os_free(conf->eap_fast_a_id); |
886 | 2.42k | os_free(conf->eap_fast_a_id_info); |
887 | 2.42k | os_free(conf->eap_sim_db); |
888 | 2.42k | os_free(conf->imsi_privacy_key); |
889 | 2.42k | os_free(conf->radius_server_clients); |
890 | 2.42k | os_free(conf->radius); |
891 | 2.42k | os_free(conf->radius_das_shared_secret); |
892 | 2.42k | hostapd_config_free_vlan(conf); |
893 | 2.42k | os_free(conf->time_zone); |
894 | 2.42k | os_free(conf->supported_rates); |
895 | 2.42k | os_free(conf->basic_rates); |
896 | | |
897 | 2.42k | #ifdef CONFIG_IEEE80211R_AP |
898 | 2.42k | hostapd_config_clear_rxkhs(conf); |
899 | 2.42k | os_free(conf->rxkh_file); |
900 | 2.42k | conf->rxkh_file = NULL; |
901 | 2.42k | #endif /* CONFIG_IEEE80211R_AP */ |
902 | | |
903 | 2.42k | #ifdef CONFIG_WPS |
904 | 2.42k | os_free(conf->wps_pin_requests); |
905 | 2.42k | os_free(conf->device_name); |
906 | 2.42k | os_free(conf->manufacturer); |
907 | 2.42k | os_free(conf->model_name); |
908 | 2.42k | os_free(conf->model_number); |
909 | 2.42k | os_free(conf->serial_number); |
910 | 2.42k | os_free(conf->config_methods); |
911 | 2.42k | os_free(conf->ap_pin); |
912 | 2.42k | os_free(conf->extra_cred); |
913 | 2.42k | os_free(conf->ap_settings); |
914 | 2.42k | hostapd_config_clear_wpa_psk(&conf->multi_ap_backhaul_ssid.wpa_psk); |
915 | 2.42k | str_clear_free(conf->multi_ap_backhaul_ssid.wpa_passphrase); |
916 | 2.42k | os_free(conf->upnp_iface); |
917 | 2.42k | os_free(conf->friendly_name); |
918 | 2.42k | os_free(conf->manufacturer_url); |
919 | 2.42k | os_free(conf->model_description); |
920 | 2.42k | os_free(conf->model_url); |
921 | 2.42k | os_free(conf->upc); |
922 | 26.6k | for (i = 0; i < MAX_WPS_VENDOR_EXTENSIONS; i++) |
923 | 24.2k | wpabuf_free(conf->wps_vendor_ext[i]); |
924 | 2.42k | wpabuf_free(conf->wps_application_ext); |
925 | 2.42k | wpabuf_free(conf->wps_nfc_dh_pubkey); |
926 | 2.42k | wpabuf_free(conf->wps_nfc_dh_privkey); |
927 | 2.42k | wpabuf_free(conf->wps_nfc_dev_pw); |
928 | 2.42k | #endif /* CONFIG_WPS */ |
929 | | |
930 | 2.42k | os_free(conf->roaming_consortium); |
931 | 2.42k | os_free(conf->venue_name); |
932 | 2.42k | os_free(conf->venue_url); |
933 | 2.42k | os_free(conf->nai_realm_data); |
934 | 2.42k | os_free(conf->network_auth_type); |
935 | 2.42k | os_free(conf->anqp_3gpp_cell_net); |
936 | 2.42k | os_free(conf->domain_name); |
937 | 2.42k | hostapd_config_free_anqp_elem(conf); |
938 | | |
939 | | #ifdef CONFIG_RADIUS_TEST |
940 | | os_free(conf->dump_msk_file); |
941 | | #endif /* CONFIG_RADIUS_TEST */ |
942 | | |
943 | 2.42k | #ifdef CONFIG_HS20 |
944 | 2.42k | os_free(conf->hs20_oper_friendly_name); |
945 | 2.42k | os_free(conf->hs20_wan_metrics); |
946 | 2.42k | os_free(conf->hs20_connection_capability); |
947 | 2.42k | os_free(conf->hs20_operating_class); |
948 | 2.42k | os_free(conf->t_c_filename); |
949 | 2.42k | os_free(conf->t_c_server_url); |
950 | 2.42k | #endif /* CONFIG_HS20 */ |
951 | | |
952 | 2.42k | wpabuf_free(conf->vendor_elements); |
953 | 2.42k | wpabuf_free(conf->assocresp_elements); |
954 | | |
955 | 2.42k | os_free(conf->sae_groups); |
956 | | #ifdef CONFIG_OWE |
957 | | os_free(conf->owe_groups); |
958 | | #endif /* CONFIG_OWE */ |
959 | | |
960 | 2.42k | os_free(conf->wowlan_triggers); |
961 | | |
962 | 2.42k | os_free(conf->server_id); |
963 | | |
964 | | #ifdef CONFIG_TESTING_OPTIONS |
965 | | wpabuf_free(conf->own_ie_override); |
966 | | wpabuf_free(conf->rsne_override); |
967 | | wpabuf_free(conf->rsnoe_override); |
968 | | wpabuf_free(conf->rsno2e_override); |
969 | | wpabuf_free(conf->rsnxe_override); |
970 | | wpabuf_free(conf->rsnxoe_override); |
971 | | wpabuf_free(conf->sae_commit_override); |
972 | | wpabuf_free(conf->rsne_override_eapol); |
973 | | wpabuf_free(conf->rsnxe_override_eapol); |
974 | | wpabuf_free(conf->rsne_override_ft); |
975 | | wpabuf_free(conf->rsnxe_override_ft); |
976 | | wpabuf_free(conf->gtk_rsc_override); |
977 | | wpabuf_free(conf->igtk_rsc_override); |
978 | | wpabuf_free(conf->eapol_m1_elements); |
979 | | wpabuf_free(conf->eapol_m3_elements); |
980 | | wpabuf_free(conf->presp_elements); |
981 | | #endif /* CONFIG_TESTING_OPTIONS */ |
982 | | |
983 | 2.42k | os_free(conf->no_probe_resp_if_seen_on); |
984 | 2.42k | os_free(conf->no_auth_if_seen_on); |
985 | | |
986 | 2.42k | hostapd_config_free_fils_realms(conf); |
987 | | |
988 | | #ifdef CONFIG_DPP |
989 | | os_free(conf->dpp_name); |
990 | | os_free(conf->dpp_mud_url); |
991 | | os_free(conf->dpp_extra_conf_req_name); |
992 | | os_free(conf->dpp_extra_conf_req_value); |
993 | | os_free(conf->dpp_connector); |
994 | | wpabuf_free(conf->dpp_netaccesskey); |
995 | | wpabuf_free(conf->dpp_csign); |
996 | | #ifdef CONFIG_DPP2 |
997 | | hostapd_dpp_controller_conf_free(conf->dpp_controller); |
998 | | #endif /* CONFIG_DPP2 */ |
999 | | #endif /* CONFIG_DPP */ |
1000 | | |
1001 | 2.42k | hostapd_config_free_sae_passwords(conf); |
1002 | | |
1003 | 2.42k | #ifdef CONFIG_AIRTIME_POLICY |
1004 | 2.42k | { |
1005 | 2.42k | struct airtime_sta_weight *wt, *wt_prev; |
1006 | | |
1007 | 2.42k | wt = conf->airtime_weight_list; |
1008 | 2.42k | conf->airtime_weight_list = NULL; |
1009 | 2.42k | while (wt) { |
1010 | 0 | wt_prev = wt; |
1011 | 0 | wt = wt->next; |
1012 | 0 | os_free(wt_prev); |
1013 | 0 | } |
1014 | 2.42k | } |
1015 | 2.42k | #endif /* CONFIG_AIRTIME_POLICY */ |
1016 | | |
1017 | | #ifdef CONFIG_PASN |
1018 | | os_free(conf->pasn_groups); |
1019 | | #ifdef CONFIG_TESTING_OPTIONS |
1020 | | os_free(conf->pasn_test_groups); |
1021 | | #endif /* CONFIG_TESTING_OPTIONS */ |
1022 | | #endif /* CONFIG_PASN */ |
1023 | | |
1024 | 2.42k | wpabuf_clear_free(conf->sae_pw_id_key); |
1025 | | |
1026 | 2.42k | os_free(conf); |
1027 | 2.42k | } |
1028 | | |
1029 | | |
1030 | | /** |
1031 | | * hostapd_config_free - Free hostapd configuration |
1032 | | * @conf: Configuration data from hostapd_config_read(). |
1033 | | */ |
1034 | | void hostapd_config_free(struct hostapd_config *conf) |
1035 | 2.42k | { |
1036 | 2.42k | size_t i; |
1037 | | |
1038 | 2.42k | if (conf == NULL) |
1039 | 0 | return; |
1040 | | |
1041 | 4.84k | for (i = 0; i < conf->num_bss; i++) |
1042 | 2.42k | hostapd_config_free_bss(conf->bss[i]); |
1043 | 2.42k | os_free(conf->bss); |
1044 | 2.42k | os_free(conf->acs_ch_list.range); |
1045 | 2.42k | os_free(conf->acs_freq_list.range); |
1046 | 2.42k | os_free(conf->driver_params); |
1047 | | #ifdef CONFIG_ACS |
1048 | | os_free(conf->acs_chan_bias); |
1049 | | #endif /* CONFIG_ACS */ |
1050 | 2.42k | wpabuf_free(conf->lci); |
1051 | 2.42k | wpabuf_free(conf->civic); |
1052 | | |
1053 | 2.42k | os_free(conf); |
1054 | 2.42k | } |
1055 | | |
1056 | | |
1057 | | /** |
1058 | | * hostapd_maclist_found - Find a MAC address from a list |
1059 | | * @list: MAC address list |
1060 | | * @num_entries: Number of addresses in the list |
1061 | | * @addr: Address to search for |
1062 | | * @vlan_id: Buffer for returning VLAN ID or %NULL if not needed |
1063 | | * Returns: 1 if address is in the list or 0 if not. |
1064 | | * |
1065 | | * Perform a binary search for given MAC address from a pre-sorted list. |
1066 | | */ |
1067 | | int hostapd_maclist_found(struct mac_acl_entry *list, int num_entries, |
1068 | | const u8 *addr, struct vlan_description *vlan_id) |
1069 | 0 | { |
1070 | 0 | int start, end, middle, res; |
1071 | |
|
1072 | 0 | start = 0; |
1073 | 0 | end = num_entries - 1; |
1074 | |
|
1075 | 0 | while (start <= end) { |
1076 | 0 | middle = (start + end) / 2; |
1077 | 0 | res = os_memcmp(list[middle].addr, addr, ETH_ALEN); |
1078 | 0 | if (res == 0) { |
1079 | 0 | if (vlan_id) |
1080 | 0 | *vlan_id = list[middle].vlan_id; |
1081 | 0 | return 1; |
1082 | 0 | } |
1083 | 0 | if (res < 0) |
1084 | 0 | start = middle + 1; |
1085 | 0 | else |
1086 | 0 | end = middle - 1; |
1087 | 0 | } |
1088 | | |
1089 | 0 | return 0; |
1090 | 0 | } |
1091 | | |
1092 | | |
1093 | | int hostapd_vlan_valid(struct hostapd_vlan *vlan, |
1094 | | struct vlan_description *vlan_desc) |
1095 | 0 | { |
1096 | 0 | struct hostapd_vlan *v = vlan; |
1097 | 0 | int i; |
1098 | |
|
1099 | 0 | if (!vlan_desc->notempty || vlan_desc->untagged < 0 || |
1100 | 0 | vlan_desc->untagged > MAX_VLAN_ID) |
1101 | 0 | return 0; |
1102 | 0 | for (i = 0; i < MAX_NUM_TAGGED_VLAN; i++) { |
1103 | 0 | if (vlan_desc->tagged[i] < 0 || |
1104 | 0 | vlan_desc->tagged[i] > MAX_VLAN_ID) |
1105 | 0 | return 0; |
1106 | 0 | } |
1107 | 0 | if (!vlan_desc->untagged && !vlan_desc->tagged[0]) |
1108 | 0 | return 0; |
1109 | | |
1110 | 0 | while (v) { |
1111 | 0 | if (!vlan_compare(&v->vlan_desc, vlan_desc) || |
1112 | 0 | v->vlan_id == VLAN_ID_WILDCARD) |
1113 | 0 | return 1; |
1114 | 0 | v = v->next; |
1115 | 0 | } |
1116 | 0 | return 0; |
1117 | 0 | } |
1118 | | |
1119 | | |
1120 | | const char * hostapd_get_vlan_id_ifname(struct hostapd_vlan *vlan, int vlan_id) |
1121 | 0 | { |
1122 | 0 | struct hostapd_vlan *v = vlan; |
1123 | 0 | while (v) { |
1124 | 0 | if (v->vlan_id == vlan_id) |
1125 | 0 | return v->ifname; |
1126 | 0 | v = v->next; |
1127 | 0 | } |
1128 | 0 | return NULL; |
1129 | 0 | } |
1130 | | |
1131 | | |
1132 | | const u8 * hostapd_get_psk(const struct hostapd_bss_config *conf, |
1133 | | const u8 *addr, const u8 *p2p_dev_addr, |
1134 | | const u8 *prev_psk, int *vlan_id) |
1135 | 0 | { |
1136 | 0 | struct hostapd_wpa_psk *psk; |
1137 | 0 | int next_ok = prev_psk == NULL; |
1138 | |
|
1139 | 0 | if (vlan_id) |
1140 | 0 | *vlan_id = 0; |
1141 | |
|
1142 | 0 | if (p2p_dev_addr && !is_zero_ether_addr(p2p_dev_addr)) { |
1143 | 0 | wpa_printf(MSG_DEBUG, "Searching a PSK for " MACSTR |
1144 | 0 | " p2p_dev_addr=" MACSTR " prev_psk=%p", |
1145 | 0 | MAC2STR(addr), MAC2STR(p2p_dev_addr), prev_psk); |
1146 | 0 | addr = NULL; /* Use P2P Device Address for matching */ |
1147 | 0 | } else { |
1148 | 0 | wpa_printf(MSG_DEBUG, "Searching a PSK for " MACSTR |
1149 | 0 | " prev_psk=%p", |
1150 | 0 | MAC2STR(addr), prev_psk); |
1151 | 0 | } |
1152 | |
|
1153 | 0 | for (psk = conf->ssid.wpa_psk; psk != NULL; psk = psk->next) { |
1154 | 0 | if (next_ok && |
1155 | 0 | (psk->group || |
1156 | 0 | (addr && ether_addr_equal(psk->addr, addr)) || |
1157 | 0 | (!addr && p2p_dev_addr && |
1158 | 0 | ether_addr_equal(psk->p2p_dev_addr, p2p_dev_addr)))) { |
1159 | 0 | if (vlan_id) |
1160 | 0 | *vlan_id = psk->vlan_id; |
1161 | 0 | return psk->psk; |
1162 | 0 | } |
1163 | | |
1164 | 0 | if (psk->psk == prev_psk) |
1165 | 0 | next_ok = 1; |
1166 | 0 | } |
1167 | | |
1168 | 0 | return NULL; |
1169 | 0 | } |
1170 | | |
1171 | | |
1172 | | #ifdef CONFIG_SAE_PK |
1173 | | static bool hostapd_sae_pk_password_without_pk(struct hostapd_bss_config *bss) |
1174 | | { |
1175 | | struct sae_password_entry *pw; |
1176 | | bool res = false; |
1177 | | |
1178 | | if (bss->ssid.wpa_passphrase && |
1179 | | #ifdef CONFIG_TESTING_OPTIONS |
1180 | | !bss->sae_pk_password_check_skip && |
1181 | | #endif /* CONFIG_TESTING_OPTIONS */ |
1182 | | sae_pk_valid_password(bss->ssid.wpa_passphrase)) |
1183 | | res = true; |
1184 | | |
1185 | | for (pw = bss->sae_passwords; pw; pw = pw->next) { |
1186 | | if (!pw->pk && |
1187 | | #ifdef CONFIG_TESTING_OPTIONS |
1188 | | !bss->sae_pk_password_check_skip && |
1189 | | #endif /* CONFIG_TESTING_OPTIONS */ |
1190 | | sae_pk_valid_password(pw->password)) |
1191 | | return true; |
1192 | | |
1193 | | if (bss->ssid.wpa_passphrase && res && pw->pk && |
1194 | | os_strcmp(bss->ssid.wpa_passphrase, pw->password) == 0) |
1195 | | res = false; |
1196 | | } |
1197 | | |
1198 | | return res; |
1199 | | } |
1200 | | #endif /* CONFIG_SAE_PK */ |
1201 | | |
1202 | | |
1203 | | bool hostapd_config_check_bss_6g(struct hostapd_bss_config *bss) |
1204 | 0 | { |
1205 | 0 | if (bss->wpa != WPA_PROTO_RSN) { |
1206 | 0 | wpa_printf(MSG_ERROR, |
1207 | 0 | "Pre-RSNA security methods are not allowed in 6 GHz"); |
1208 | 0 | return false; |
1209 | 0 | } |
1210 | | |
1211 | 0 | if (bss->ieee80211w != MGMT_FRAME_PROTECTION_REQUIRED) { |
1212 | 0 | wpa_printf(MSG_ERROR, |
1213 | 0 | "Management frame protection is required in 6 GHz"); |
1214 | 0 | return false; |
1215 | 0 | } |
1216 | | |
1217 | 0 | if (bss->wpa_key_mgmt & (WPA_KEY_MGMT_PSK | |
1218 | 0 | WPA_KEY_MGMT_FT_PSK | |
1219 | 0 | WPA_KEY_MGMT_PSK_SHA256)) { |
1220 | 0 | wpa_printf(MSG_ERROR, "Invalid AKM suite for 6 GHz"); |
1221 | 0 | return false; |
1222 | 0 | } |
1223 | | |
1224 | 0 | if (bss->rsn_pairwise & (WPA_CIPHER_WEP40 | |
1225 | 0 | WPA_CIPHER_WEP104 | |
1226 | 0 | WPA_CIPHER_TKIP)) { |
1227 | 0 | wpa_printf(MSG_ERROR, |
1228 | 0 | "Invalid pairwise cipher suite for 6 GHz"); |
1229 | 0 | return false; |
1230 | 0 | } |
1231 | | |
1232 | 0 | if (bss->wpa_group & (WPA_CIPHER_WEP40 | |
1233 | 0 | WPA_CIPHER_WEP104 | |
1234 | 0 | WPA_CIPHER_TKIP)) { |
1235 | 0 | wpa_printf(MSG_ERROR, "Invalid group cipher suite for 6 GHz"); |
1236 | 0 | return false; |
1237 | 0 | } |
1238 | | |
1239 | | #ifdef CONFIG_SAE |
1240 | | if (wpa_key_mgmt_sae(bss->wpa_key_mgmt) && |
1241 | | bss->sae_pwe == SAE_PWE_HUNT_AND_PECK) { |
1242 | | wpa_printf(MSG_INFO, "SAE: Enabling SAE H2E on 6 GHz"); |
1243 | | bss->sae_pwe = SAE_PWE_BOTH; |
1244 | | } |
1245 | | #endif /* CONFIG_SAE */ |
1246 | | |
1247 | 0 | return true; |
1248 | 0 | } |
1249 | | |
1250 | | |
1251 | | static int hostapd_config_check_bss(struct hostapd_bss_config *bss, |
1252 | | struct hostapd_config *conf, |
1253 | | int full_config) |
1254 | 0 | { |
1255 | 0 | if (full_config && is_6ghz_op_class(conf->op_class) && |
1256 | 0 | !hostapd_config_check_bss_6g(bss)) |
1257 | 0 | return -1; |
1258 | | |
1259 | 0 | if (full_config && bss->ieee802_1x && !bss->eap_server && |
1260 | 0 | !bss->radius->auth_servers) { |
1261 | 0 | wpa_printf(MSG_ERROR, "Invalid IEEE 802.1X configuration (no " |
1262 | 0 | "EAP authenticator configured)."); |
1263 | 0 | return -1; |
1264 | 0 | } |
1265 | | |
1266 | | #ifdef CONFIG_WEP |
1267 | | if (bss->wpa) { |
1268 | | int wep, i; |
1269 | | |
1270 | | wep = bss->default_wep_key_len > 0 || |
1271 | | bss->individual_wep_key_len > 0; |
1272 | | for (i = 0; i < NUM_WEP_KEYS; i++) { |
1273 | | if (bss->ssid.wep.keys_set) { |
1274 | | wep = 1; |
1275 | | break; |
1276 | | } |
1277 | | } |
1278 | | |
1279 | | if (wep) { |
1280 | | wpa_printf(MSG_ERROR, "WEP configuration in a WPA network is not supported"); |
1281 | | return -1; |
1282 | | } |
1283 | | } |
1284 | | #endif /* CONFIG_WEP */ |
1285 | | |
1286 | 0 | if (full_config && bss->wpa && |
1287 | 0 | bss->wpa_psk_radius != PSK_RADIUS_IGNORED && |
1288 | 0 | bss->wpa_psk_radius != PSK_RADIUS_DURING_4WAY_HS && |
1289 | 0 | bss->macaddr_acl != USE_EXTERNAL_RADIUS_AUTH) { |
1290 | 0 | wpa_printf(MSG_ERROR, "WPA-PSK using RADIUS enabled, but no " |
1291 | 0 | "RADIUS checking (macaddr_acl=2) enabled."); |
1292 | 0 | return -1; |
1293 | 0 | } |
1294 | | |
1295 | 0 | if (full_config && bss->wpa && |
1296 | 0 | wpa_key_mgmt_wpa_psk_no_sae(bss->wpa_key_mgmt) && |
1297 | 0 | bss->ssid.wpa_psk == NULL && bss->ssid.wpa_passphrase == NULL && |
1298 | 0 | bss->ssid.wpa_psk_file == NULL && |
1299 | 0 | bss->wpa_psk_radius != PSK_RADIUS_DURING_4WAY_HS && |
1300 | 0 | (bss->wpa_psk_radius != PSK_RADIUS_REQUIRED || |
1301 | 0 | bss->macaddr_acl != USE_EXTERNAL_RADIUS_AUTH)) { |
1302 | 0 | wpa_printf(MSG_ERROR, "WPA-PSK enabled, but PSK or passphrase " |
1303 | 0 | "is not configured."); |
1304 | 0 | return -1; |
1305 | 0 | } |
1306 | | |
1307 | 0 | if (full_config && !is_zero_ether_addr(bss->bssid)) { |
1308 | 0 | size_t i; |
1309 | |
|
1310 | 0 | for (i = 0; i < conf->num_bss; i++) { |
1311 | 0 | if (conf->bss[i] != bss && |
1312 | 0 | (hostapd_mac_comp(conf->bss[i]->bssid, |
1313 | 0 | bss->bssid) == 0)) { |
1314 | 0 | wpa_printf(MSG_ERROR, "Duplicate BSSID " MACSTR |
1315 | 0 | " on interface '%s' and '%s'.", |
1316 | 0 | MAC2STR(bss->bssid), |
1317 | 0 | conf->bss[i]->iface, bss->iface); |
1318 | 0 | return -1; |
1319 | 0 | } |
1320 | 0 | } |
1321 | 0 | } |
1322 | | |
1323 | 0 | if (full_config) { |
1324 | 0 | size_t i; |
1325 | |
|
1326 | 0 | for (i = 0; i < conf->num_bss; i++) { |
1327 | 0 | if (conf->bss[i] != bss && |
1328 | 0 | os_strcmp(conf->bss[i]->iface, bss->iface) == 0) { |
1329 | 0 | wpa_printf(MSG_ERROR, |
1330 | 0 | "Duplicate interface '%s' for BSSID " |
1331 | 0 | MACSTR " and " MACSTR, bss->iface, |
1332 | 0 | MAC2STR(conf->bss[i]->bssid), |
1333 | 0 | MAC2STR(bss->bssid)); |
1334 | 0 | return -1; |
1335 | 0 | } |
1336 | 0 | } |
1337 | 0 | } |
1338 | | |
1339 | 0 | #ifdef CONFIG_IEEE80211R_AP |
1340 | 0 | if (full_config && wpa_key_mgmt_ft(bss->wpa_key_mgmt) && |
1341 | 0 | (bss->nas_identifier == NULL || |
1342 | 0 | os_strlen(bss->nas_identifier) < 1 || |
1343 | 0 | os_strlen(bss->nas_identifier) > FT_R0KH_ID_MAX_LEN)) { |
1344 | 0 | wpa_printf(MSG_ERROR, "FT (IEEE 802.11r) requires " |
1345 | 0 | "nas_identifier to be configured as a 1..48 octet " |
1346 | 0 | "string"); |
1347 | 0 | return -1; |
1348 | 0 | } |
1349 | 0 | #endif /* CONFIG_IEEE80211R_AP */ |
1350 | | |
1351 | 0 | if (full_config && conf->ieee80211n && |
1352 | 0 | conf->hw_mode == HOSTAPD_MODE_IEEE80211B) { |
1353 | 0 | bss->disable_11n = true; |
1354 | 0 | wpa_printf(MSG_ERROR, "HT (IEEE 802.11n) in 11b mode is not " |
1355 | 0 | "allowed, disabling HT capabilities"); |
1356 | 0 | } |
1357 | |
|
1358 | | #ifdef CONFIG_WEP |
1359 | | if (full_config && conf->ieee80211n && |
1360 | | bss->ssid.security_policy == SECURITY_STATIC_WEP) { |
1361 | | bss->disable_11n = true; |
1362 | | wpa_printf(MSG_ERROR, "HT (IEEE 802.11n) with WEP is not " |
1363 | | "allowed, disabling HT capabilities"); |
1364 | | } |
1365 | | #endif /* CONFIG_WEP */ |
1366 | |
|
1367 | 0 | if (full_config && conf->ieee80211n && bss->wpa && |
1368 | 0 | !(bss->wpa_pairwise & WPA_CIPHER_CCMP) && |
1369 | 0 | !(bss->rsn_pairwise & (WPA_CIPHER_CCMP | WPA_CIPHER_GCMP | |
1370 | 0 | WPA_CIPHER_CCMP_256 | WPA_CIPHER_GCMP_256))) |
1371 | 0 | { |
1372 | 0 | bss->disable_11n = true; |
1373 | 0 | wpa_printf(MSG_ERROR, "HT (IEEE 802.11n) with WPA/WPA2 " |
1374 | 0 | "requires CCMP/GCMP to be enabled, disabling HT " |
1375 | 0 | "capabilities"); |
1376 | 0 | } |
1377 | |
|
1378 | | #ifdef CONFIG_IEEE80211AC |
1379 | | #ifdef CONFIG_WEP |
1380 | | if (full_config && conf->ieee80211ac && |
1381 | | bss->ssid.security_policy == SECURITY_STATIC_WEP) { |
1382 | | bss->disable_11ac = true; |
1383 | | wpa_printf(MSG_ERROR, |
1384 | | "VHT (IEEE 802.11ac) with WEP is not allowed, disabling VHT capabilities"); |
1385 | | } |
1386 | | #endif /* CONFIG_WEP */ |
1387 | | |
1388 | | if (full_config && conf->ieee80211ac && bss->wpa && |
1389 | | !(bss->wpa_pairwise & WPA_CIPHER_CCMP) && |
1390 | | !(bss->rsn_pairwise & (WPA_CIPHER_CCMP | WPA_CIPHER_GCMP | |
1391 | | WPA_CIPHER_CCMP_256 | WPA_CIPHER_GCMP_256))) |
1392 | | { |
1393 | | bss->disable_11ac = true; |
1394 | | wpa_printf(MSG_ERROR, |
1395 | | "VHT (IEEE 802.11ac) with WPA/WPA2 requires CCMP/GCMP to be enabled, disabling VHT capabilities"); |
1396 | | } |
1397 | | #endif /* CONFIG_IEEE80211AC */ |
1398 | |
|
1399 | | #ifdef CONFIG_IEEE80211AX |
1400 | | #ifdef CONFIG_WEP |
1401 | | if (full_config && conf->ieee80211ax && |
1402 | | bss->ssid.security_policy == SECURITY_STATIC_WEP) { |
1403 | | bss->disable_11ax = true; |
1404 | | wpa_printf(MSG_ERROR, |
1405 | | "HE (IEEE 802.11ax) with WEP is not allowed, disabling HE capabilities"); |
1406 | | } |
1407 | | #endif /* CONFIG_WEP */ |
1408 | | |
1409 | | if (full_config && conf->ieee80211ax && bss->wpa && |
1410 | | !(bss->wpa_pairwise & WPA_CIPHER_CCMP) && |
1411 | | !(bss->rsn_pairwise & (WPA_CIPHER_CCMP | WPA_CIPHER_GCMP | |
1412 | | WPA_CIPHER_CCMP_256 | WPA_CIPHER_GCMP_256))) |
1413 | | { |
1414 | | bss->disable_11ax = true; |
1415 | | wpa_printf(MSG_ERROR, |
1416 | | "HE (IEEE 802.11ax) with WPA/WPA2 requires CCMP/GCMP to be enabled, disabling HE capabilities"); |
1417 | | } |
1418 | | #endif /* CONFIG_IEEE80211AX */ |
1419 | |
|
1420 | 0 | #ifdef CONFIG_WPS |
1421 | 0 | if (full_config && bss->wps_state && bss->ignore_broadcast_ssid) { |
1422 | 0 | wpa_printf(MSG_INFO, "WPS: ignore_broadcast_ssid " |
1423 | 0 | "configuration forced WPS to be disabled"); |
1424 | 0 | bss->wps_state = 0; |
1425 | 0 | } |
1426 | |
|
1427 | | #ifdef CONFIG_WEP |
1428 | | if (full_config && bss->wps_state && |
1429 | | bss->ssid.wep.keys_set && bss->wpa == 0) { |
1430 | | wpa_printf(MSG_INFO, "WPS: WEP configuration forced WPS to be " |
1431 | | "disabled"); |
1432 | | bss->wps_state = 0; |
1433 | | } |
1434 | | #endif /* CONFIG_WEP */ |
1435 | |
|
1436 | 0 | if (full_config && bss->wps_state && bss->wpa && |
1437 | 0 | (!(bss->wpa & 2) || |
1438 | 0 | !(bss->rsn_pairwise & (WPA_CIPHER_CCMP | WPA_CIPHER_GCMP | |
1439 | 0 | WPA_CIPHER_CCMP_256 | |
1440 | 0 | WPA_CIPHER_GCMP_256)))) { |
1441 | 0 | wpa_printf(MSG_INFO, "WPS: WPA/TKIP configuration without " |
1442 | 0 | "WPA2/CCMP/GCMP forced WPS to be disabled"); |
1443 | 0 | bss->wps_state = 0; |
1444 | 0 | } |
1445 | 0 | #endif /* CONFIG_WPS */ |
1446 | |
|
1447 | 0 | #ifdef CONFIG_HS20 |
1448 | 0 | if (full_config && bss->hs20 && |
1449 | 0 | (!(bss->wpa & 2) || |
1450 | 0 | !(bss->rsn_pairwise & (WPA_CIPHER_CCMP | WPA_CIPHER_GCMP | |
1451 | 0 | WPA_CIPHER_CCMP_256 | |
1452 | 0 | WPA_CIPHER_GCMP_256)))) { |
1453 | 0 | wpa_printf(MSG_ERROR, "HS 2.0: WPA2-Enterprise/CCMP " |
1454 | 0 | "configuration is required for Hotspot 2.0 " |
1455 | 0 | "functionality"); |
1456 | 0 | return -1; |
1457 | 0 | } |
1458 | 0 | #endif /* CONFIG_HS20 */ |
1459 | | |
1460 | | #ifdef CONFIG_MBO |
1461 | | if (full_config && bss->mbo_enabled && (bss->wpa & 2) && |
1462 | | bss->ieee80211w == NO_MGMT_FRAME_PROTECTION) { |
1463 | | wpa_printf(MSG_ERROR, |
1464 | | "MBO: PMF needs to be enabled whenever using WPA2 with MBO"); |
1465 | | return -1; |
1466 | | } |
1467 | | #endif /* CONFIG_MBO */ |
1468 | | |
1469 | | #ifdef CONFIG_OCV |
1470 | | if (full_config && bss->ieee80211w == NO_MGMT_FRAME_PROTECTION && |
1471 | | bss->ocv) { |
1472 | | wpa_printf(MSG_ERROR, |
1473 | | "OCV: PMF needs to be enabled whenever using OCV"); |
1474 | | return -1; |
1475 | | } |
1476 | | #endif /* CONFIG_OCV */ |
1477 | | |
1478 | | #ifdef CONFIG_SAE_PK |
1479 | | if (full_config && hostapd_sae_pk_in_use(bss) && |
1480 | | hostapd_sae_pk_password_without_pk(bss)) { |
1481 | | wpa_printf(MSG_ERROR, |
1482 | | "SAE-PK: SAE password uses SAE-PK style, but does not have PK configured"); |
1483 | | return -1; |
1484 | | } |
1485 | | #endif /* CONFIG_SAE_PK */ |
1486 | | |
1487 | | #ifdef CONFIG_FILS |
1488 | | if (full_config && bss->fils_discovery_max_int && |
1489 | | (!conf->ieee80211ax || bss->disable_11ax)) { |
1490 | | wpa_printf(MSG_ERROR, |
1491 | | "Currently IEEE 802.11ax support is mandatory to enable FILS discovery transmission."); |
1492 | | return -1; |
1493 | | } |
1494 | | |
1495 | | if (full_config && bss->fils_discovery_max_int && |
1496 | | bss->unsol_bcast_probe_resp_interval) { |
1497 | | wpa_printf(MSG_ERROR, |
1498 | | "Cannot enable both FILS discovery and unsolicited broadcast Probe Response at the same time"); |
1499 | | return -1; |
1500 | | } |
1501 | | #endif /* CONFIG_FILS */ |
1502 | | |
1503 | | #ifdef CONFIG_IEEE80211BE |
1504 | | if (full_config && !bss->disable_11be && bss->disable_11ax) { |
1505 | | bss->disable_11be = true; |
1506 | | bss->mld_ap = 0; |
1507 | | wpa_printf(MSG_INFO, |
1508 | | "Disabling IEEE 802.11be as IEEE 802.11ax is disabled for this BSS"); |
1509 | | } |
1510 | | |
1511 | | if (full_config && conf->ieee80211be && !bss->disable_11be && |
1512 | | !bss->beacon_prot && ap_pmf_enabled(bss)) { |
1513 | | bss->beacon_prot = 1; |
1514 | | wpa_printf(MSG_INFO, |
1515 | | "Enabling beacon protection as IEEE 802.11be is enabled for this BSS"); |
1516 | | } |
1517 | | |
1518 | | if (full_config && (!conf->ieee80211be || bss->disable_11be) && |
1519 | | bss->mld_ap) { |
1520 | | wpa_printf(MSG_INFO, |
1521 | | "Cannot enable mld_ap when IEEE 802.11be is disabled"); |
1522 | | return -1; |
1523 | | } |
1524 | | #endif /* CONFIG_IEEE80211BE */ |
1525 | | |
1526 | 0 | if (full_config && bss->ignore_broadcast_ssid && conf->mbssid) { |
1527 | 0 | wpa_printf(MSG_ERROR, |
1528 | 0 | "Hidden SSID is not suppored when MBSSID is enabled"); |
1529 | 0 | return -1; |
1530 | 0 | } |
1531 | | |
1532 | | /* Do not advertise SPP A-MSDU support if not using CCMP/GCMP */ |
1533 | 0 | if (full_config && bss->spp_amsdu && |
1534 | 0 | !(bss->wpa && |
1535 | 0 | bss->rsn_pairwise & (WPA_CIPHER_CCMP_256 | WPA_CIPHER_CCMP | |
1536 | 0 | WPA_CIPHER_GCMP_256 | WPA_CIPHER_GCMP))) |
1537 | 0 | bss->spp_amsdu = false; |
1538 | |
|
1539 | 0 | return 0; |
1540 | 0 | } |
1541 | | |
1542 | | |
1543 | | static int hostapd_config_check_cw(struct hostapd_config *conf, int queue) |
1544 | 0 | { |
1545 | 0 | int tx_cwmin = conf->tx_queue[queue].cwmin; |
1546 | 0 | int tx_cwmax = conf->tx_queue[queue].cwmax; |
1547 | 0 | int ac_cwmin = conf->wmm_ac_params[queue].cwmin; |
1548 | 0 | int ac_cwmax = conf->wmm_ac_params[queue].cwmax; |
1549 | |
|
1550 | 0 | if (tx_cwmin > tx_cwmax) { |
1551 | 0 | wpa_printf(MSG_ERROR, |
1552 | 0 | "Invalid TX queue cwMin/cwMax values. cwMin(%d) greater than cwMax(%d)", |
1553 | 0 | tx_cwmin, tx_cwmax); |
1554 | 0 | return -1; |
1555 | 0 | } |
1556 | 0 | if (ac_cwmin > ac_cwmax) { |
1557 | 0 | wpa_printf(MSG_ERROR, |
1558 | 0 | "Invalid WMM AC cwMin/cwMax values. cwMin(%d) greater than cwMax(%d)", |
1559 | 0 | ac_cwmin, ac_cwmax); |
1560 | 0 | return -1; |
1561 | 0 | } |
1562 | 0 | return 0; |
1563 | 0 | } |
1564 | | |
1565 | | |
1566 | | int hostapd_config_check(struct hostapd_config *conf, int full_config) |
1567 | 0 | { |
1568 | 0 | size_t i; |
1569 | |
|
1570 | 0 | if (full_config && is_6ghz_op_class(conf->op_class) && |
1571 | 0 | !conf->hw_mode_set) { |
1572 | | /* Use the appropriate hw_mode value automatically when the |
1573 | | * op_class parameter has been set, but hw_mode was not. */ |
1574 | 0 | conf->hw_mode = HOSTAPD_MODE_IEEE80211A; |
1575 | 0 | } |
1576 | |
|
1577 | 0 | if (full_config && conf->ieee80211d && |
1578 | 0 | (!conf->country[0] || !conf->country[1])) { |
1579 | 0 | wpa_printf(MSG_ERROR, "Cannot enable IEEE 802.11d without " |
1580 | 0 | "setting the country_code"); |
1581 | 0 | return -1; |
1582 | 0 | } |
1583 | | |
1584 | 0 | if (full_config && conf->ieee80211h && !conf->ieee80211d) { |
1585 | 0 | wpa_printf(MSG_ERROR, "Cannot enable IEEE 802.11h without " |
1586 | 0 | "IEEE 802.11d enabled"); |
1587 | 0 | return -1; |
1588 | 0 | } |
1589 | | |
1590 | 0 | if (full_config && conf->local_pwr_constraint != -1 && |
1591 | 0 | !conf->ieee80211d) { |
1592 | 0 | wpa_printf(MSG_ERROR, "Cannot add Power Constraint element without Country element"); |
1593 | 0 | return -1; |
1594 | 0 | } |
1595 | | |
1596 | 0 | if (full_config && conf->spectrum_mgmt_required && |
1597 | 0 | conf->local_pwr_constraint == -1) { |
1598 | 0 | wpa_printf(MSG_ERROR, "Cannot set Spectrum Management bit without Country and Power Constraint elements"); |
1599 | 0 | return -1; |
1600 | 0 | } |
1601 | | |
1602 | 0 | #ifdef CONFIG_AIRTIME_POLICY |
1603 | 0 | if (full_config && conf->airtime_mode > AIRTIME_MODE_STATIC && |
1604 | 0 | !conf->airtime_update_interval) { |
1605 | 0 | wpa_printf(MSG_ERROR, "Airtime update interval cannot be zero"); |
1606 | 0 | return -1; |
1607 | 0 | } |
1608 | 0 | #endif /* CONFIG_AIRTIME_POLICY */ |
1609 | 0 | for (i = 0; i < NUM_TX_QUEUES; i++) { |
1610 | 0 | if (hostapd_config_check_cw(conf, i)) |
1611 | 0 | return -1; |
1612 | 0 | } |
1613 | | |
1614 | | #ifdef CONFIG_IEEE80211BE |
1615 | | if (full_config && conf->ieee80211be && !conf->ieee80211ax) { |
1616 | | wpa_printf(MSG_ERROR, |
1617 | | "Cannot set ieee80211be without ieee80211ax"); |
1618 | | return -1; |
1619 | | } |
1620 | | |
1621 | | if (full_config) |
1622 | | hostapd_set_and_check_bw320_offset(conf, |
1623 | | conf->eht_bw320_offset); |
1624 | | #endif /* CONFIG_IEEE80211BE */ |
1625 | | |
1626 | 0 | if (full_config && conf->mbssid && !conf->ieee80211ax) { |
1627 | 0 | wpa_printf(MSG_ERROR, |
1628 | 0 | "Cannot enable multiple BSSID support without ieee80211ax"); |
1629 | 0 | return -1; |
1630 | 0 | } |
1631 | | |
1632 | 0 | for (i = 0; i < conf->num_bss; i++) { |
1633 | 0 | if (hostapd_config_check_bss(conf->bss[i], conf, full_config)) |
1634 | 0 | return -1; |
1635 | 0 | } |
1636 | | |
1637 | 0 | return 0; |
1638 | 0 | } |
1639 | | |
1640 | | |
1641 | | void hostapd_set_security_params(struct hostapd_bss_config *bss, |
1642 | | int full_config) |
1643 | 0 | { |
1644 | | #ifdef CONFIG_WEP |
1645 | | if (bss->individual_wep_key_len == 0) { |
1646 | | /* individual keys are not use; can use key idx0 for |
1647 | | * broadcast keys */ |
1648 | | bss->broadcast_key_idx_min = 0; |
1649 | | } |
1650 | | #endif /* CONFIG_WEP */ |
1651 | |
|
1652 | 0 | if ((bss->wpa & 2) && bss->rsn_pairwise == 0) |
1653 | 0 | bss->rsn_pairwise = bss->wpa_pairwise; |
1654 | 0 | if (bss->group_cipher) |
1655 | 0 | bss->wpa_group = bss->group_cipher; |
1656 | 0 | else |
1657 | 0 | bss->wpa_group = wpa_select_ap_group_cipher(bss->wpa, |
1658 | 0 | bss->wpa_pairwise, |
1659 | 0 | bss->rsn_pairwise); |
1660 | 0 | if (!bss->wpa_group_rekey_set) |
1661 | 0 | bss->wpa_group_rekey = bss->wpa_group == WPA_CIPHER_TKIP ? |
1662 | 0 | 600 : 86400; |
1663 | |
|
1664 | 0 | if (full_config) { |
1665 | 0 | bss->radius->auth_server = bss->radius->auth_servers; |
1666 | 0 | bss->radius->acct_server = bss->radius->acct_servers; |
1667 | 0 | } |
1668 | |
|
1669 | 0 | if (bss->wpa && bss->ieee802_1x) { |
1670 | 0 | bss->ssid.security_policy = SECURITY_WPA; |
1671 | 0 | } else if (bss->wpa) { |
1672 | 0 | bss->ssid.security_policy = SECURITY_WPA_PSK; |
1673 | 0 | } else if (bss->ieee802_1x) { |
1674 | 0 | int cipher = WPA_CIPHER_NONE; |
1675 | 0 | bss->ssid.security_policy = SECURITY_IEEE_802_1X; |
1676 | | #ifdef CONFIG_WEP |
1677 | | bss->ssid.wep.default_len = bss->default_wep_key_len; |
1678 | | if (full_config && bss->default_wep_key_len) { |
1679 | | cipher = bss->default_wep_key_len >= 13 ? |
1680 | | WPA_CIPHER_WEP104 : WPA_CIPHER_WEP40; |
1681 | | } else if (full_config && bss->ssid.wep.keys_set) { |
1682 | | if (bss->ssid.wep.len[0] >= 13) |
1683 | | cipher = WPA_CIPHER_WEP104; |
1684 | | else |
1685 | | cipher = WPA_CIPHER_WEP40; |
1686 | | } |
1687 | | #endif /* CONFIG_WEP */ |
1688 | 0 | bss->wpa_group = cipher; |
1689 | 0 | bss->wpa_pairwise = cipher; |
1690 | 0 | bss->rsn_pairwise = cipher; |
1691 | 0 | if (full_config) |
1692 | 0 | bss->wpa_key_mgmt = WPA_KEY_MGMT_IEEE8021X_NO_WPA; |
1693 | | #ifdef CONFIG_WEP |
1694 | | } else if (bss->ssid.wep.keys_set) { |
1695 | | int cipher = WPA_CIPHER_WEP40; |
1696 | | if (bss->ssid.wep.len[0] >= 13) |
1697 | | cipher = WPA_CIPHER_WEP104; |
1698 | | bss->ssid.security_policy = SECURITY_STATIC_WEP; |
1699 | | bss->wpa_group = cipher; |
1700 | | bss->wpa_pairwise = cipher; |
1701 | | bss->rsn_pairwise = cipher; |
1702 | | if (full_config) |
1703 | | bss->wpa_key_mgmt = WPA_KEY_MGMT_NONE; |
1704 | | #endif /* CONFIG_WEP */ |
1705 | 0 | } else { |
1706 | 0 | bss->ssid.security_policy = SECURITY_PLAINTEXT; |
1707 | 0 | if (full_config) { |
1708 | 0 | bss->wpa_group = WPA_CIPHER_NONE; |
1709 | 0 | bss->wpa_pairwise = WPA_CIPHER_NONE; |
1710 | 0 | bss->rsn_pairwise = WPA_CIPHER_NONE; |
1711 | 0 | bss->wpa_key_mgmt = WPA_KEY_MGMT_NONE; |
1712 | 0 | } |
1713 | 0 | } |
1714 | 0 | } |
1715 | | |
1716 | | |
1717 | | int hostapd_sae_pw_id_in_use(struct hostapd_bss_config *conf) |
1718 | 0 | { |
1719 | 0 | int with_id = 0, without_id = 0; |
1720 | 0 | struct sae_password_entry *pw; |
1721 | |
|
1722 | 0 | if (conf->ssid.wpa_passphrase) |
1723 | 0 | without_id = 1; |
1724 | |
|
1725 | 0 | for (pw = conf->sae_passwords; pw; pw = pw->next) { |
1726 | 0 | if (pw->identifier) |
1727 | 0 | with_id = 1; |
1728 | 0 | else |
1729 | 0 | without_id = 1; |
1730 | 0 | if (with_id && without_id) |
1731 | 0 | break; |
1732 | 0 | } |
1733 | |
|
1734 | 0 | if (with_id && !without_id) |
1735 | 0 | return 2; |
1736 | 0 | return with_id; |
1737 | 0 | } |
1738 | | |
1739 | | |
1740 | | bool hostapd_sae_pk_in_use(struct hostapd_bss_config *conf) |
1741 | 0 | { |
1742 | | #ifdef CONFIG_SAE_PK |
1743 | | struct sae_password_entry *pw; |
1744 | | |
1745 | | for (pw = conf->sae_passwords; pw; pw = pw->next) { |
1746 | | if (pw->pk) |
1747 | | return true; |
1748 | | } |
1749 | | #endif /* CONFIG_SAE_PK */ |
1750 | |
|
1751 | 0 | return false; |
1752 | 0 | } |
1753 | | |
1754 | | |
1755 | | #ifdef CONFIG_SAE_PK |
1756 | | bool hostapd_sae_pk_exclusively(struct hostapd_bss_config *conf) |
1757 | | { |
1758 | | bool with_pk = false; |
1759 | | struct sae_password_entry *pw; |
1760 | | |
1761 | | if (conf->ssid.wpa_passphrase) |
1762 | | return false; |
1763 | | |
1764 | | for (pw = conf->sae_passwords; pw; pw = pw->next) { |
1765 | | if (!pw->pk) |
1766 | | return false; |
1767 | | with_pk = true; |
1768 | | } |
1769 | | |
1770 | | return with_pk; |
1771 | | } |
1772 | | #endif /* CONFIG_SAE_PK */ |
1773 | | |
1774 | | |
1775 | | int hostapd_acl_comp(const void *a, const void *b) |
1776 | 0 | { |
1777 | 0 | const struct mac_acl_entry *aa = a; |
1778 | 0 | const struct mac_acl_entry *bb = b; |
1779 | 0 | return os_memcmp(aa->addr, bb->addr, sizeof(macaddr)); |
1780 | 0 | } |
1781 | | |
1782 | | |
1783 | | int hostapd_add_acl_maclist(struct mac_acl_entry **acl, int *num, |
1784 | | int vlan_id, const u8 *addr) |
1785 | 0 | { |
1786 | 0 | struct mac_acl_entry *newacl; |
1787 | |
|
1788 | 0 | newacl = os_realloc_array(*acl, *num + 1, sizeof(**acl)); |
1789 | 0 | if (!newacl) { |
1790 | 0 | wpa_printf(MSG_ERROR, "MAC list reallocation failed"); |
1791 | 0 | return -1; |
1792 | 0 | } |
1793 | | |
1794 | 0 | *acl = newacl; |
1795 | 0 | os_memcpy((*acl)[*num].addr, addr, ETH_ALEN); |
1796 | 0 | os_memset(&(*acl)[*num].vlan_id, 0, sizeof((*acl)[*num].vlan_id)); |
1797 | 0 | (*acl)[*num].vlan_id.untagged = vlan_id; |
1798 | 0 | (*acl)[*num].vlan_id.notempty = !!vlan_id; |
1799 | 0 | (*num)++; |
1800 | |
|
1801 | 0 | return 0; |
1802 | 0 | } |
1803 | | |
1804 | | |
1805 | | void hostapd_remove_acl_mac(struct mac_acl_entry **acl, int *num, |
1806 | | const u8 *addr) |
1807 | 0 | { |
1808 | 0 | int i = 0; |
1809 | |
|
1810 | 0 | while (i < *num) { |
1811 | 0 | if (ether_addr_equal((*acl)[i].addr, addr)) { |
1812 | 0 | os_remove_in_array(*acl, *num, sizeof(**acl), i); |
1813 | 0 | (*num)--; |
1814 | 0 | } else { |
1815 | 0 | i++; |
1816 | 0 | } |
1817 | 0 | } |
1818 | 0 | } |