/src/hostap/wpa_supplicant/config_file.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * WPA Supplicant / Configuration backend: text file |
3 | | * Copyright (c) 2003-2019, 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 | | * This file implements a configuration backend for text files. All the |
9 | | * configuration information is stored in a text file that uses a format |
10 | | * described in the sample configuration file, wpa_supplicant.conf. |
11 | | */ |
12 | | |
13 | | #include "includes.h" |
14 | | #ifdef ANDROID |
15 | | #include <sys/stat.h> |
16 | | #endif /* ANDROID */ |
17 | | |
18 | | #include "common.h" |
19 | | #include "config.h" |
20 | | #include "base64.h" |
21 | | #include "uuid.h" |
22 | | #include "common/ieee802_1x_defs.h" |
23 | | #include "p2p/p2p.h" |
24 | | #include "eap_peer/eap_methods.h" |
25 | | #include "eap_peer/eap.h" |
26 | | #include "utils/config.h" |
27 | | |
28 | | |
29 | | static int wpa_config_validate_network(struct wpa_ssid *ssid, int line) |
30 | 0 | { |
31 | 0 | int errors = 0; |
32 | |
|
33 | 0 | if (ssid->passphrase) { |
34 | 0 | if (ssid->psk_set) { |
35 | 0 | wpa_printf(MSG_ERROR, "Line %d: both PSK and " |
36 | 0 | "passphrase configured.", line); |
37 | 0 | errors++; |
38 | 0 | } |
39 | 0 | wpa_config_update_psk(ssid); |
40 | 0 | } |
41 | |
|
42 | 0 | if (ssid->disabled == 2) |
43 | 0 | ssid->p2p_persistent_group = 1; |
44 | |
|
45 | 0 | if ((ssid->group_cipher & WPA_CIPHER_CCMP) && |
46 | 0 | !(ssid->pairwise_cipher & (WPA_CIPHER_CCMP | WPA_CIPHER_CCMP_256 | |
47 | 0 | WPA_CIPHER_GCMP | WPA_CIPHER_GCMP_256 | |
48 | 0 | WPA_CIPHER_NONE))) { |
49 | | /* Group cipher cannot be stronger than the pairwise cipher. */ |
50 | 0 | wpa_printf(MSG_DEBUG, "Line %d: removed CCMP from group cipher" |
51 | 0 | " list since it was not allowed for pairwise " |
52 | 0 | "cipher", line); |
53 | 0 | ssid->group_cipher &= ~WPA_CIPHER_CCMP; |
54 | 0 | } |
55 | |
|
56 | 0 | if (is_6ghz_freq(ssid->frequency) && ssid->mode == WPAS_MODE_MESH && |
57 | 0 | ssid->key_mgmt == WPA_KEY_MGMT_NONE) { |
58 | 0 | wpa_printf(MSG_ERROR, |
59 | 0 | "Line %d: key_mgmt for mesh network in 6 GHz should be SAE", |
60 | 0 | line); |
61 | 0 | errors++; |
62 | 0 | } |
63 | 0 | if (ssid->mode == WPAS_MODE_MESH && |
64 | 0 | (ssid->key_mgmt != WPA_KEY_MGMT_NONE && |
65 | 0 | ssid->key_mgmt != WPA_KEY_MGMT_SAE)) { |
66 | 0 | wpa_printf(MSG_ERROR, |
67 | 0 | "Line %d: key_mgmt for mesh network should be open or SAE", |
68 | 0 | line); |
69 | 0 | errors++; |
70 | 0 | } |
71 | |
|
72 | | #ifdef CONFIG_OCV |
73 | | if (ssid->ocv && ssid->ieee80211w == NO_MGMT_FRAME_PROTECTION) { |
74 | | wpa_printf(MSG_ERROR, |
75 | | "Line %d: PMF needs to be enabled whenever using OCV", |
76 | | line); |
77 | | errors++; |
78 | | } |
79 | | #endif /* CONFIG_OCV */ |
80 | |
|
81 | 0 | return errors; |
82 | 0 | } |
83 | | |
84 | | |
85 | | static struct wpa_ssid * wpa_config_read_network(FILE *f, int *line, int id) |
86 | 0 | { |
87 | 0 | struct wpa_ssid *ssid; |
88 | 0 | int errors = 0, end = 0; |
89 | 0 | char buf[2000], *pos, *pos2; |
90 | |
|
91 | 0 | wpa_printf(MSG_MSGDUMP, "Line: %d - start of a new network block", |
92 | 0 | *line); |
93 | 0 | ssid = os_zalloc(sizeof(*ssid)); |
94 | 0 | if (ssid == NULL) |
95 | 0 | return NULL; |
96 | 0 | dl_list_init(&ssid->psk_list); |
97 | 0 | ssid->id = id; |
98 | |
|
99 | 0 | wpa_config_set_network_defaults(ssid); |
100 | |
|
101 | 0 | while (wpa_config_get_line(buf, sizeof(buf), f, line, &pos)) { |
102 | 0 | if (os_strcmp(pos, "}") == 0) { |
103 | 0 | end = 1; |
104 | 0 | break; |
105 | 0 | } |
106 | | |
107 | 0 | pos2 = os_strchr(pos, '='); |
108 | 0 | if (pos2 == NULL) { |
109 | 0 | wpa_printf(MSG_ERROR, "Line %d: Invalid SSID line " |
110 | 0 | "'%s'.", *line, pos); |
111 | 0 | errors++; |
112 | 0 | continue; |
113 | 0 | } |
114 | | |
115 | 0 | *pos2++ = '\0'; |
116 | 0 | if (*pos2 == '"') { |
117 | 0 | if (os_strchr(pos2 + 1, '"') == NULL) { |
118 | 0 | wpa_printf(MSG_ERROR, "Line %d: invalid " |
119 | 0 | "quotation '%s'.", *line, pos2); |
120 | 0 | errors++; |
121 | 0 | continue; |
122 | 0 | } |
123 | 0 | } |
124 | | |
125 | 0 | if (wpa_config_set(ssid, pos, pos2, *line) < 0) { |
126 | 0 | #ifndef CONFIG_WEP |
127 | 0 | if (os_strcmp(pos, "wep_key0") == 0 || |
128 | 0 | os_strcmp(pos, "wep_key1") == 0 || |
129 | 0 | os_strcmp(pos, "wep_key2") == 0 || |
130 | 0 | os_strcmp(pos, "wep_key3") == 0 || |
131 | 0 | os_strcmp(pos, "wep_tx_keyidx") == 0) { |
132 | 0 | wpa_printf(MSG_ERROR, |
133 | 0 | "Line %d: unsupported WEP parameter", |
134 | 0 | *line); |
135 | 0 | ssid->disabled = 1; |
136 | 0 | continue; |
137 | 0 | } |
138 | 0 | #endif /* CONFIG_WEP */ |
139 | 0 | errors++; |
140 | 0 | } |
141 | 0 | } |
142 | |
|
143 | 0 | if (!end) { |
144 | 0 | wpa_printf(MSG_ERROR, "Line %d: network block was not " |
145 | 0 | "terminated properly.", *line); |
146 | 0 | errors++; |
147 | 0 | } |
148 | |
|
149 | 0 | errors += wpa_config_validate_network(ssid, *line); |
150 | |
|
151 | 0 | if (errors) { |
152 | 0 | wpa_config_free_ssid(ssid); |
153 | 0 | ssid = NULL; |
154 | 0 | } |
155 | |
|
156 | 0 | return ssid; |
157 | 0 | } |
158 | | |
159 | | |
160 | | static struct wpa_cred * wpa_config_read_cred(FILE *f, int *line, int id) |
161 | 0 | { |
162 | 0 | struct wpa_cred *cred; |
163 | 0 | int errors = 0, end = 0; |
164 | 0 | char buf[256], *pos, *pos2; |
165 | |
|
166 | 0 | wpa_printf(MSG_MSGDUMP, "Line: %d - start of a new cred block", *line); |
167 | 0 | cred = os_zalloc(sizeof(*cred)); |
168 | 0 | if (cred == NULL) |
169 | 0 | return NULL; |
170 | 0 | cred->id = id; |
171 | 0 | cred->sim_num = DEFAULT_USER_SELECTED_SIM; |
172 | |
|
173 | 0 | while (wpa_config_get_line(buf, sizeof(buf), f, line, &pos)) { |
174 | 0 | if (os_strcmp(pos, "}") == 0) { |
175 | 0 | end = 1; |
176 | 0 | break; |
177 | 0 | } |
178 | | |
179 | 0 | pos2 = os_strchr(pos, '='); |
180 | 0 | if (pos2 == NULL) { |
181 | 0 | wpa_printf(MSG_ERROR, "Line %d: Invalid cred line " |
182 | 0 | "'%s'.", *line, pos); |
183 | 0 | errors++; |
184 | 0 | continue; |
185 | 0 | } |
186 | | |
187 | 0 | *pos2++ = '\0'; |
188 | 0 | if (*pos2 == '"') { |
189 | 0 | if (os_strchr(pos2 + 1, '"') == NULL) { |
190 | 0 | wpa_printf(MSG_ERROR, "Line %d: invalid " |
191 | 0 | "quotation '%s'.", *line, pos2); |
192 | 0 | errors++; |
193 | 0 | continue; |
194 | 0 | } |
195 | 0 | } |
196 | | |
197 | 0 | if (wpa_config_set_cred(cred, pos, pos2, *line) < 0) |
198 | 0 | errors++; |
199 | 0 | } |
200 | |
|
201 | 0 | if (!end) { |
202 | 0 | wpa_printf(MSG_ERROR, "Line %d: cred block was not " |
203 | 0 | "terminated properly.", *line); |
204 | 0 | errors++; |
205 | 0 | } |
206 | |
|
207 | 0 | if (errors) { |
208 | 0 | wpa_config_free_cred(cred); |
209 | 0 | cred = NULL; |
210 | 0 | } |
211 | |
|
212 | 0 | return cred; |
213 | 0 | } |
214 | | |
215 | | |
216 | | #ifndef CONFIG_NO_CONFIG_BLOBS |
217 | | static struct wpa_config_blob * wpa_config_read_blob(FILE *f, int *line, |
218 | | const char *name) |
219 | 0 | { |
220 | 0 | struct wpa_config_blob *blob; |
221 | 0 | char buf[256], *pos; |
222 | 0 | char *encoded = NULL, *nencoded; |
223 | 0 | int end = 0; |
224 | 0 | size_t encoded_len = 0, len; |
225 | |
|
226 | 0 | wpa_printf(MSG_MSGDUMP, "Line: %d - start of a new named blob '%s'", |
227 | 0 | *line, name); |
228 | |
|
229 | 0 | while (wpa_config_get_line(buf, sizeof(buf), f, line, &pos)) { |
230 | 0 | if (os_strcmp(pos, "}") == 0) { |
231 | 0 | end = 1; |
232 | 0 | break; |
233 | 0 | } |
234 | | |
235 | 0 | len = os_strlen(pos); |
236 | 0 | nencoded = os_realloc(encoded, encoded_len + len); |
237 | 0 | if (nencoded == NULL) { |
238 | 0 | wpa_printf(MSG_ERROR, "Line %d: not enough memory for " |
239 | 0 | "blob", *line); |
240 | 0 | os_free(encoded); |
241 | 0 | return NULL; |
242 | 0 | } |
243 | 0 | encoded = nencoded; |
244 | 0 | os_memcpy(encoded + encoded_len, pos, len); |
245 | 0 | encoded_len += len; |
246 | 0 | } |
247 | | |
248 | 0 | if (!end || !encoded) { |
249 | 0 | wpa_printf(MSG_ERROR, "Line %d: blob was not terminated " |
250 | 0 | "properly", *line); |
251 | 0 | os_free(encoded); |
252 | 0 | return NULL; |
253 | 0 | } |
254 | | |
255 | 0 | blob = os_zalloc(sizeof(*blob)); |
256 | 0 | if (blob == NULL) { |
257 | 0 | os_free(encoded); |
258 | 0 | return NULL; |
259 | 0 | } |
260 | 0 | blob->name = os_strdup(name); |
261 | 0 | blob->data = base64_decode(encoded, encoded_len, &blob->len); |
262 | 0 | os_free(encoded); |
263 | |
|
264 | 0 | if (blob->name == NULL || blob->data == NULL) { |
265 | 0 | wpa_config_free_blob(blob); |
266 | 0 | return NULL; |
267 | 0 | } |
268 | | |
269 | 0 | return blob; |
270 | 0 | } |
271 | | |
272 | | |
273 | | static int wpa_config_process_blob(struct wpa_config *config, FILE *f, |
274 | | int *line, char *bname) |
275 | 0 | { |
276 | 0 | char *name_end; |
277 | 0 | struct wpa_config_blob *blob; |
278 | |
|
279 | 0 | name_end = os_strchr(bname, '='); |
280 | 0 | if (name_end == NULL) { |
281 | 0 | wpa_printf(MSG_ERROR, "Line %d: no blob name terminator", |
282 | 0 | *line); |
283 | 0 | return -1; |
284 | 0 | } |
285 | 0 | *name_end = '\0'; |
286 | |
|
287 | 0 | blob = wpa_config_read_blob(f, line, bname); |
288 | 0 | if (blob == NULL) { |
289 | 0 | wpa_printf(MSG_ERROR, "Line %d: failed to read blob %s", |
290 | 0 | *line, bname); |
291 | 0 | return -1; |
292 | 0 | } |
293 | 0 | wpa_config_set_blob(config, blob); |
294 | 0 | return 0; |
295 | 0 | } |
296 | | #endif /* CONFIG_NO_CONFIG_BLOBS */ |
297 | | |
298 | | |
299 | | struct wpa_config * wpa_config_read(const char *name, struct wpa_config *cfgp, |
300 | | bool ro) |
301 | 0 | { |
302 | 0 | FILE *f; |
303 | 0 | char buf[512], *pos; |
304 | 0 | int errors = 0, line = 0; |
305 | 0 | struct wpa_ssid *ssid, *tail, *head; |
306 | 0 | struct wpa_cred *cred, *cred_tail, *cred_head; |
307 | 0 | struct wpa_config *config; |
308 | 0 | static int id = 0; |
309 | 0 | static int cred_id = 0; |
310 | |
|
311 | 0 | if (name == NULL) |
312 | 0 | return NULL; |
313 | 0 | if (cfgp) |
314 | 0 | config = cfgp; |
315 | 0 | else |
316 | 0 | config = wpa_config_alloc_empty(NULL, NULL); |
317 | 0 | if (config == NULL) { |
318 | 0 | wpa_printf(MSG_ERROR, "Failed to allocate config file " |
319 | 0 | "structure"); |
320 | 0 | return NULL; |
321 | 0 | } |
322 | 0 | tail = head = config->ssid; |
323 | 0 | while (tail && tail->next) |
324 | 0 | tail = tail->next; |
325 | 0 | cred_tail = cred_head = config->cred; |
326 | 0 | while (cred_tail && cred_tail->next) |
327 | 0 | cred_tail = cred_tail->next; |
328 | |
|
329 | 0 | wpa_printf(MSG_DEBUG, "Reading configuration file '%s'", name); |
330 | 0 | f = fopen(name, "r"); |
331 | 0 | if (f == NULL) { |
332 | 0 | wpa_printf(MSG_ERROR, "Failed to open config file '%s', " |
333 | 0 | "error: %s", name, strerror(errno)); |
334 | 0 | if (config != cfgp) |
335 | 0 | os_free(config); |
336 | 0 | return NULL; |
337 | 0 | } |
338 | | |
339 | 0 | while (wpa_config_get_line(buf, sizeof(buf), f, &line, &pos)) { |
340 | 0 | if (os_strcmp(pos, "network={") == 0) { |
341 | 0 | ssid = wpa_config_read_network(f, &line, id++); |
342 | 0 | if (ssid == NULL) { |
343 | 0 | wpa_printf(MSG_ERROR, "Line %d: failed to " |
344 | 0 | "parse network block.", line); |
345 | 0 | errors++; |
346 | 0 | continue; |
347 | 0 | } |
348 | 0 | ssid->ro = ro; |
349 | 0 | if (head == NULL) { |
350 | 0 | head = tail = ssid; |
351 | 0 | } else { |
352 | 0 | tail->next = ssid; |
353 | 0 | tail = ssid; |
354 | 0 | } |
355 | 0 | if (wpa_config_add_prio_network(config, ssid)) { |
356 | 0 | wpa_printf(MSG_ERROR, "Line %d: failed to add " |
357 | 0 | "network block to priority list.", |
358 | 0 | line); |
359 | 0 | errors++; |
360 | 0 | continue; |
361 | 0 | } |
362 | 0 | } else if (os_strcmp(pos, "cred={") == 0) { |
363 | 0 | cred = wpa_config_read_cred(f, &line, cred_id++); |
364 | 0 | if (cred == NULL) { |
365 | 0 | wpa_printf(MSG_ERROR, "Line %d: failed to " |
366 | 0 | "parse cred block.", line); |
367 | 0 | errors++; |
368 | 0 | continue; |
369 | 0 | } |
370 | 0 | if (cred_head == NULL) { |
371 | 0 | cred_head = cred_tail = cred; |
372 | 0 | } else { |
373 | 0 | cred_tail->next = cred; |
374 | 0 | cred_tail = cred; |
375 | 0 | } |
376 | 0 | #ifndef CONFIG_NO_CONFIG_BLOBS |
377 | 0 | } else if (os_strncmp(pos, "blob-base64-", 12) == 0) { |
378 | 0 | if (wpa_config_process_blob(config, f, &line, pos + 12) |
379 | 0 | < 0) { |
380 | 0 | wpa_printf(MSG_ERROR, "Line %d: failed to " |
381 | 0 | "process blob.", line); |
382 | 0 | errors++; |
383 | 0 | continue; |
384 | 0 | } |
385 | 0 | #endif /* CONFIG_NO_CONFIG_BLOBS */ |
386 | 0 | } else if (wpa_config_process_global(config, pos, line) < 0) { |
387 | 0 | wpa_printf(MSG_ERROR, "Line %d: Invalid configuration " |
388 | 0 | "line '%s'.", line, pos); |
389 | 0 | errors++; |
390 | 0 | continue; |
391 | 0 | } |
392 | 0 | } |
393 | |
|
394 | 0 | fclose(f); |
395 | |
|
396 | 0 | config->ssid = head; |
397 | 0 | wpa_config_debug_dump_networks(config); |
398 | 0 | config->cred = cred_head; |
399 | |
|
400 | 0 | #ifndef WPA_IGNORE_CONFIG_ERRORS |
401 | 0 | if (errors) { |
402 | 0 | if (config != cfgp) |
403 | 0 | wpa_config_free(config); |
404 | 0 | config = NULL; |
405 | 0 | head = NULL; |
406 | 0 | } |
407 | 0 | #endif /* WPA_IGNORE_CONFIG_ERRORS */ |
408 | |
|
409 | 0 | return config; |
410 | 0 | } |
411 | | |
412 | | |
413 | | #ifndef CONFIG_NO_CONFIG_WRITE |
414 | | |
415 | | static void write_str(FILE *f, const char *field, struct wpa_ssid *ssid) |
416 | 0 | { |
417 | 0 | char *value = wpa_config_get(ssid, field); |
418 | 0 | if (value == NULL) |
419 | 0 | return; |
420 | 0 | fprintf(f, "\t%s=%s\n", field, value); |
421 | 0 | str_clear_free(value); |
422 | 0 | } |
423 | | |
424 | | |
425 | | static void write_int(FILE *f, const char *field, int value, int def) |
426 | 0 | { |
427 | 0 | if (value == def) |
428 | 0 | return; |
429 | 0 | fprintf(f, "\t%s=%d\n", field, value); |
430 | 0 | } |
431 | | |
432 | | |
433 | | static void write_bssid(FILE *f, struct wpa_ssid *ssid) |
434 | 0 | { |
435 | 0 | char *value = wpa_config_get(ssid, "bssid"); |
436 | 0 | if (value == NULL) |
437 | 0 | return; |
438 | 0 | fprintf(f, "\tbssid=%s\n", value); |
439 | 0 | os_free(value); |
440 | 0 | } |
441 | | |
442 | | |
443 | | static void write_bssid_hint(FILE *f, struct wpa_ssid *ssid) |
444 | 0 | { |
445 | 0 | char *value = wpa_config_get(ssid, "bssid_hint"); |
446 | |
|
447 | 0 | if (!value) |
448 | 0 | return; |
449 | 0 | fprintf(f, "\tbssid_hint=%s\n", value); |
450 | 0 | os_free(value); |
451 | 0 | } |
452 | | |
453 | | |
454 | | static void write_psk(FILE *f, struct wpa_ssid *ssid) |
455 | 0 | { |
456 | 0 | char *value; |
457 | |
|
458 | 0 | if (ssid->mem_only_psk) |
459 | 0 | return; |
460 | | |
461 | 0 | value = wpa_config_get(ssid, "psk"); |
462 | 0 | if (value == NULL) |
463 | 0 | return; |
464 | 0 | fprintf(f, "\tpsk=%s\n", value); |
465 | 0 | os_free(value); |
466 | 0 | } |
467 | | |
468 | | |
469 | | static void write_proto(FILE *f, struct wpa_ssid *ssid) |
470 | 0 | { |
471 | 0 | char *value; |
472 | |
|
473 | 0 | if (ssid->proto == DEFAULT_PROTO) |
474 | 0 | return; |
475 | | |
476 | 0 | value = wpa_config_get(ssid, "proto"); |
477 | 0 | if (value == NULL) |
478 | 0 | return; |
479 | 0 | if (value[0]) |
480 | 0 | fprintf(f, "\tproto=%s\n", value); |
481 | 0 | os_free(value); |
482 | 0 | } |
483 | | |
484 | | |
485 | | static void write_key_mgmt(FILE *f, struct wpa_ssid *ssid) |
486 | 0 | { |
487 | 0 | char *value; |
488 | |
|
489 | 0 | if (ssid->key_mgmt == DEFAULT_KEY_MGMT) |
490 | 0 | return; |
491 | | |
492 | 0 | value = wpa_config_get(ssid, "key_mgmt"); |
493 | 0 | if (value == NULL) |
494 | 0 | return; |
495 | 0 | if (value[0]) |
496 | 0 | fprintf(f, "\tkey_mgmt=%s\n", value); |
497 | 0 | os_free(value); |
498 | 0 | } |
499 | | |
500 | | |
501 | | static void write_pairwise(FILE *f, struct wpa_ssid *ssid) |
502 | 0 | { |
503 | 0 | char *value; |
504 | |
|
505 | 0 | if (ssid->pairwise_cipher == DEFAULT_PAIRWISE) |
506 | 0 | return; |
507 | | |
508 | 0 | value = wpa_config_get(ssid, "pairwise"); |
509 | 0 | if (value == NULL) |
510 | 0 | return; |
511 | 0 | if (value[0]) |
512 | 0 | fprintf(f, "\tpairwise=%s\n", value); |
513 | 0 | os_free(value); |
514 | 0 | } |
515 | | |
516 | | |
517 | | static void write_group(FILE *f, struct wpa_ssid *ssid) |
518 | 0 | { |
519 | 0 | char *value; |
520 | |
|
521 | 0 | if (ssid->group_cipher == DEFAULT_GROUP) |
522 | 0 | return; |
523 | | |
524 | 0 | value = wpa_config_get(ssid, "group"); |
525 | 0 | if (value == NULL) |
526 | 0 | return; |
527 | 0 | if (value[0]) |
528 | 0 | fprintf(f, "\tgroup=%s\n", value); |
529 | 0 | os_free(value); |
530 | 0 | } |
531 | | |
532 | | |
533 | | static void write_group_mgmt(FILE *f, struct wpa_ssid *ssid) |
534 | 0 | { |
535 | 0 | char *value; |
536 | |
|
537 | 0 | if (!ssid->group_mgmt_cipher) |
538 | 0 | return; |
539 | | |
540 | 0 | value = wpa_config_get(ssid, "group_mgmt"); |
541 | 0 | if (!value) |
542 | 0 | return; |
543 | 0 | if (value[0]) |
544 | 0 | fprintf(f, "\tgroup_mgmt=%s\n", value); |
545 | 0 | os_free(value); |
546 | 0 | } |
547 | | |
548 | | |
549 | | static void write_auth_alg(FILE *f, struct wpa_ssid *ssid) |
550 | 0 | { |
551 | 0 | char *value; |
552 | |
|
553 | 0 | if (ssid->auth_alg == 0) |
554 | 0 | return; |
555 | | |
556 | 0 | value = wpa_config_get(ssid, "auth_alg"); |
557 | 0 | if (value == NULL) |
558 | 0 | return; |
559 | 0 | if (value[0]) |
560 | 0 | fprintf(f, "\tauth_alg=%s\n", value); |
561 | 0 | os_free(value); |
562 | 0 | } |
563 | | |
564 | | |
565 | | #ifdef IEEE8021X_EAPOL |
566 | | static void write_eap(FILE *f, struct wpa_ssid *ssid) |
567 | 0 | { |
568 | 0 | char *value; |
569 | |
|
570 | 0 | value = wpa_config_get(ssid, "eap"); |
571 | 0 | if (value == NULL) |
572 | 0 | return; |
573 | | |
574 | 0 | if (value[0]) |
575 | 0 | fprintf(f, "\teap=%s\n", value); |
576 | 0 | os_free(value); |
577 | 0 | } |
578 | | #endif /* IEEE8021X_EAPOL */ |
579 | | |
580 | | |
581 | | #ifdef CONFIG_WEP |
582 | | static void write_wep_key(FILE *f, int idx, struct wpa_ssid *ssid) |
583 | | { |
584 | | char field[20], *value; |
585 | | int res; |
586 | | |
587 | | res = os_snprintf(field, sizeof(field), "wep_key%d", idx); |
588 | | if (os_snprintf_error(sizeof(field), res)) |
589 | | return; |
590 | | value = wpa_config_get(ssid, field); |
591 | | if (value) { |
592 | | fprintf(f, "\t%s=%s\n", field, value); |
593 | | os_free(value); |
594 | | } |
595 | | } |
596 | | #endif /* CONFIG_WEP */ |
597 | | |
598 | | |
599 | | #ifdef CONFIG_P2P |
600 | | |
601 | | static void write_go_p2p_dev_addr(FILE *f, struct wpa_ssid *ssid) |
602 | | { |
603 | | char *value = wpa_config_get(ssid, "go_p2p_dev_addr"); |
604 | | if (value == NULL) |
605 | | return; |
606 | | fprintf(f, "\tgo_p2p_dev_addr=%s\n", value); |
607 | | os_free(value); |
608 | | } |
609 | | |
610 | | static void write_p2p_client_list(FILE *f, struct wpa_ssid *ssid) |
611 | | { |
612 | | char *value = wpa_config_get(ssid, "p2p_client_list"); |
613 | | if (value == NULL) |
614 | | return; |
615 | | fprintf(f, "\tp2p_client_list=%s\n", value); |
616 | | os_free(value); |
617 | | } |
618 | | |
619 | | |
620 | | static void write_psk_list(FILE *f, struct wpa_ssid *ssid) |
621 | | { |
622 | | struct psk_list_entry *psk; |
623 | | char hex[32 * 2 + 1]; |
624 | | |
625 | | dl_list_for_each(psk, &ssid->psk_list, struct psk_list_entry, list) { |
626 | | wpa_snprintf_hex(hex, sizeof(hex), psk->psk, sizeof(psk->psk)); |
627 | | fprintf(f, "\tpsk_list=%s" MACSTR "-%s\n", |
628 | | psk->p2p ? "P2P-" : "", MAC2STR(psk->addr), hex); |
629 | | } |
630 | | } |
631 | | |
632 | | #endif /* CONFIG_P2P */ |
633 | | |
634 | | |
635 | | #ifdef CONFIG_MACSEC |
636 | | |
637 | | static void write_mka_cak(FILE *f, struct wpa_ssid *ssid) |
638 | | { |
639 | | char *value; |
640 | | |
641 | | if (!(ssid->mka_psk_set & MKA_PSK_SET_CAK)) |
642 | | return; |
643 | | |
644 | | value = wpa_config_get(ssid, "mka_cak"); |
645 | | if (!value) |
646 | | return; |
647 | | fprintf(f, "\tmka_cak=%s\n", value); |
648 | | os_free(value); |
649 | | } |
650 | | |
651 | | |
652 | | static void write_mka_ckn(FILE *f, struct wpa_ssid *ssid) |
653 | | { |
654 | | char *value; |
655 | | |
656 | | if (!(ssid->mka_psk_set & MKA_PSK_SET_CKN)) |
657 | | return; |
658 | | |
659 | | value = wpa_config_get(ssid, "mka_ckn"); |
660 | | if (!value) |
661 | | return; |
662 | | fprintf(f, "\tmka_ckn=%s\n", value); |
663 | | os_free(value); |
664 | | } |
665 | | |
666 | | #endif /* CONFIG_MACSEC */ |
667 | | |
668 | | |
669 | | static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid) |
670 | 0 | { |
671 | 0 | #define STR(t) write_str(f, #t, ssid) |
672 | 0 | #define INT(t) write_int(f, #t, ssid->t, 0) |
673 | 0 | #define INTe(t, m) write_int(f, #t, ssid->eap.m, 0) |
674 | 0 | #define INT_DEF(t, def) write_int(f, #t, ssid->t, def) |
675 | 0 | #define INT_DEFe(t, m, def) write_int(f, #t, ssid->eap.m, def) |
676 | |
|
677 | 0 | STR(ssid); |
678 | 0 | INT(scan_ssid); |
679 | 0 | write_bssid(f, ssid); |
680 | 0 | write_bssid_hint(f, ssid); |
681 | 0 | write_str(f, "bssid_ignore", ssid); |
682 | 0 | write_str(f, "bssid_accept", ssid); |
683 | 0 | write_psk(f, ssid); |
684 | 0 | INT(mem_only_psk); |
685 | 0 | STR(sae_password); |
686 | 0 | STR(sae_password_id); |
687 | 0 | write_int(f, "sae_pwe", ssid->sae_pwe, DEFAULT_SAE_PWE); |
688 | 0 | write_proto(f, ssid); |
689 | 0 | write_key_mgmt(f, ssid); |
690 | 0 | INT_DEF(bg_scan_period, DEFAULT_BG_SCAN_PERIOD); |
691 | 0 | write_pairwise(f, ssid); |
692 | 0 | write_group(f, ssid); |
693 | 0 | write_group_mgmt(f, ssid); |
694 | 0 | write_auth_alg(f, ssid); |
695 | 0 | STR(bgscan); |
696 | 0 | STR(autoscan); |
697 | 0 | STR(scan_freq); |
698 | 0 | #ifdef IEEE8021X_EAPOL |
699 | 0 | write_eap(f, ssid); |
700 | 0 | STR(identity); |
701 | 0 | STR(anonymous_identity); |
702 | 0 | STR(imsi_identity); |
703 | 0 | STR(machine_identity); |
704 | 0 | STR(password); |
705 | 0 | STR(machine_password); |
706 | 0 | STR(ca_cert); |
707 | 0 | STR(ca_path); |
708 | 0 | STR(client_cert); |
709 | 0 | STR(private_key); |
710 | 0 | STR(private_key_passwd); |
711 | 0 | STR(subject_match); |
712 | 0 | STR(check_cert_subject); |
713 | 0 | STR(altsubject_match); |
714 | 0 | STR(domain_suffix_match); |
715 | 0 | STR(domain_match); |
716 | 0 | STR(ca_cert2); |
717 | 0 | STR(ca_path2); |
718 | 0 | STR(client_cert2); |
719 | 0 | STR(private_key2); |
720 | 0 | STR(private_key2_passwd); |
721 | 0 | STR(subject_match2); |
722 | 0 | STR(check_cert_subject2); |
723 | 0 | STR(altsubject_match2); |
724 | 0 | STR(domain_suffix_match2); |
725 | 0 | STR(domain_match2); |
726 | 0 | STR(machine_ca_cert); |
727 | 0 | STR(machine_ca_path); |
728 | 0 | STR(machine_client_cert); |
729 | 0 | STR(machine_private_key); |
730 | 0 | STR(machine_private_key_passwd); |
731 | 0 | STR(machine_subject_match); |
732 | 0 | STR(machine_check_cert_subject); |
733 | 0 | STR(machine_altsubject_match); |
734 | 0 | STR(machine_domain_suffix_match); |
735 | 0 | STR(machine_domain_match); |
736 | 0 | STR(phase1); |
737 | 0 | STR(phase2); |
738 | 0 | STR(machine_phase2); |
739 | 0 | STR(pcsc); |
740 | 0 | STR(pin); |
741 | 0 | STR(engine_id); |
742 | 0 | STR(key_id); |
743 | 0 | STR(cert_id); |
744 | 0 | STR(ca_cert_id); |
745 | 0 | STR(key2_id); |
746 | 0 | STR(pin2); |
747 | 0 | STR(engine2_id); |
748 | 0 | STR(cert2_id); |
749 | 0 | STR(ca_cert2_id); |
750 | 0 | INTe(engine, cert.engine); |
751 | 0 | INTe(engine2, phase2_cert.engine); |
752 | 0 | INTe(machine_engine, machine_cert.engine); |
753 | 0 | INT_DEF(eapol_flags, DEFAULT_EAPOL_FLAGS); |
754 | 0 | STR(openssl_ciphers); |
755 | 0 | INTe(erp, erp); |
756 | 0 | #endif /* IEEE8021X_EAPOL */ |
757 | | #ifdef CONFIG_WEP |
758 | | { |
759 | | int i; |
760 | | |
761 | | for (i = 0; i < 4; i++) |
762 | | write_wep_key(f, i, ssid); |
763 | | INT(wep_tx_keyidx); |
764 | | } |
765 | | #endif /* CONFIG_WEP */ |
766 | 0 | INT(priority); |
767 | 0 | #ifdef IEEE8021X_EAPOL |
768 | 0 | INT_DEF(eap_workaround, DEFAULT_EAP_WORKAROUND); |
769 | 0 | STR(pac_file); |
770 | 0 | INT_DEFe(fragment_size, fragment_size, DEFAULT_FRAGMENT_SIZE); |
771 | 0 | INTe(ocsp, cert.ocsp); |
772 | 0 | INTe(ocsp2, phase2_cert.ocsp); |
773 | 0 | INTe(machine_ocsp, machine_cert.ocsp); |
774 | 0 | INT_DEFe(sim_num, sim_num, DEFAULT_USER_SELECTED_SIM); |
775 | 0 | #endif /* IEEE8021X_EAPOL */ |
776 | 0 | INT(mode); |
777 | 0 | INT(no_auto_peer); |
778 | 0 | INT(mesh_fwding); |
779 | 0 | INT(frequency); |
780 | 0 | INT(enable_edmg); |
781 | 0 | INT(edmg_channel); |
782 | 0 | INT(fixed_freq); |
783 | | #ifdef CONFIG_ACS |
784 | | INT(acs); |
785 | | #endif /* CONFIG_ACS */ |
786 | 0 | write_int(f, "proactive_key_caching", ssid->proactive_key_caching, -1); |
787 | 0 | INT(disabled); |
788 | 0 | INT(mixed_cell); |
789 | 0 | INT_DEF(vht, 1); |
790 | 0 | INT_DEF(ht, 1); |
791 | 0 | INT(ht40); |
792 | 0 | INT_DEF(he, 1); |
793 | 0 | INT_DEF(max_oper_chwidth, DEFAULT_MAX_OPER_CHWIDTH); |
794 | 0 | INT(vht_center_freq1); |
795 | 0 | INT(vht_center_freq2); |
796 | 0 | INT(pbss); |
797 | 0 | INT(wps_disabled); |
798 | 0 | INT(fils_dh_group); |
799 | 0 | write_int(f, "ieee80211w", ssid->ieee80211w, |
800 | 0 | MGMT_FRAME_PROTECTION_DEFAULT); |
801 | 0 | STR(id_str); |
802 | | #ifdef CONFIG_P2P |
803 | | write_go_p2p_dev_addr(f, ssid); |
804 | | write_p2p_client_list(f, ssid); |
805 | | write_psk_list(f, ssid); |
806 | | #endif /* CONFIG_P2P */ |
807 | 0 | INT(ap_max_inactivity); |
808 | 0 | INT(dtim_period); |
809 | 0 | INT(beacon_int); |
810 | | #ifdef CONFIG_MACSEC |
811 | | INT(macsec_policy); |
812 | | write_mka_cak(f, ssid); |
813 | | write_mka_ckn(f, ssid); |
814 | | INT(macsec_integ_only); |
815 | | INT(macsec_replay_protect); |
816 | | INT(macsec_replay_window); |
817 | | INT(macsec_offload); |
818 | | INT(macsec_port); |
819 | | INT_DEF(mka_priority, DEFAULT_PRIO_NOT_KEY_SERVER); |
820 | | INT(macsec_csindex); |
821 | | #endif /* CONFIG_MACSEC */ |
822 | 0 | #ifdef CONFIG_HS20 |
823 | 0 | INT(update_identifier); |
824 | 0 | STR(roaming_consortium_selection); |
825 | 0 | #endif /* CONFIG_HS20 */ |
826 | 0 | write_int(f, "mac_addr", ssid->mac_addr, -1); |
827 | | #ifdef CONFIG_MESH |
828 | | STR(mesh_basic_rates); |
829 | | INT_DEF(dot11MeshMaxRetries, DEFAULT_MESH_MAX_RETRIES); |
830 | | INT_DEF(dot11MeshRetryTimeout, DEFAULT_MESH_RETRY_TIMEOUT); |
831 | | INT_DEF(dot11MeshConfirmTimeout, DEFAULT_MESH_CONFIRM_TIMEOUT); |
832 | | INT_DEF(dot11MeshHoldingTimeout, DEFAULT_MESH_HOLDING_TIMEOUT); |
833 | | INT_DEF(mesh_rssi_threshold, DEFAULT_MESH_RSSI_THRESHOLD); |
834 | | #endif /* CONFIG_MESH */ |
835 | 0 | INT(wpa_ptk_rekey); |
836 | 0 | INT(wpa_deny_ptk0_rekey); |
837 | 0 | INT(group_rekey); |
838 | 0 | INT(ignore_broadcast_ssid); |
839 | | #ifdef CONFIG_DPP |
840 | | STR(dpp_connector); |
841 | | STR(dpp_netaccesskey); |
842 | | INT(dpp_netaccesskey_expiry); |
843 | | STR(dpp_csign); |
844 | | STR(dpp_pp_key); |
845 | | INT(dpp_pfs); |
846 | | INT(dpp_connector_privacy); |
847 | | #endif /* CONFIG_DPP */ |
848 | 0 | INT(owe_group); |
849 | 0 | INT(owe_only); |
850 | 0 | INT(owe_ptk_workaround); |
851 | 0 | INT(multi_ap_backhaul_sta); |
852 | 0 | INT(ft_eap_pmksa_caching); |
853 | 0 | INT(beacon_prot); |
854 | 0 | INT(transition_disable); |
855 | 0 | INT(sae_pk); |
856 | | #ifdef CONFIG_HT_OVERRIDES |
857 | | INT_DEF(disable_ht, DEFAULT_DISABLE_HT); |
858 | | INT_DEF(disable_ht40, DEFAULT_DISABLE_HT40); |
859 | | INT_DEF(disable_sgi, DEFAULT_DISABLE_SGI); |
860 | | INT_DEF(disable_ldpc, DEFAULT_DISABLE_LDPC); |
861 | | INT(ht40_intolerant); |
862 | | INT_DEF(tx_stbc, DEFAULT_TX_STBC); |
863 | | INT_DEF(rx_stbc, DEFAULT_RX_STBC); |
864 | | INT_DEF(disable_max_amsdu, DEFAULT_DISABLE_MAX_AMSDU); |
865 | | INT_DEF(ampdu_factor, DEFAULT_AMPDU_FACTOR); |
866 | | INT_DEF(ampdu_density, DEFAULT_AMPDU_DENSITY); |
867 | | STR(ht_mcs); |
868 | | #endif /* CONFIG_HT_OVERRIDES */ |
869 | | #ifdef CONFIG_VHT_OVERRIDES |
870 | | INT(disable_vht); |
871 | | INT(vht_capa); |
872 | | INT(vht_capa_mask); |
873 | | INT_DEF(vht_rx_mcs_nss_1, -1); |
874 | | INT_DEF(vht_rx_mcs_nss_2, -1); |
875 | | INT_DEF(vht_rx_mcs_nss_3, -1); |
876 | | INT_DEF(vht_rx_mcs_nss_4, -1); |
877 | | INT_DEF(vht_rx_mcs_nss_5, -1); |
878 | | INT_DEF(vht_rx_mcs_nss_6, -1); |
879 | | INT_DEF(vht_rx_mcs_nss_7, -1); |
880 | | INT_DEF(vht_rx_mcs_nss_8, -1); |
881 | | INT_DEF(vht_tx_mcs_nss_1, -1); |
882 | | INT_DEF(vht_tx_mcs_nss_2, -1); |
883 | | INT_DEF(vht_tx_mcs_nss_3, -1); |
884 | | INT_DEF(vht_tx_mcs_nss_4, -1); |
885 | | INT_DEF(vht_tx_mcs_nss_5, -1); |
886 | | INT_DEF(vht_tx_mcs_nss_6, -1); |
887 | | INT_DEF(vht_tx_mcs_nss_7, -1); |
888 | | INT_DEF(vht_tx_mcs_nss_8, -1); |
889 | | #endif /* CONFIG_VHT_OVERRIDES */ |
890 | | #ifdef CONFIG_HE_OVERRIDES |
891 | | INT(disable_he); |
892 | | #endif /* CONFIG_HE_OVERRIDES */ |
893 | 0 | INT(disable_eht); |
894 | 0 | INT(enable_4addr_mode); |
895 | |
|
896 | 0 | #undef STR |
897 | 0 | #undef INT |
898 | 0 | #undef INT_DEF |
899 | 0 | } |
900 | | |
901 | | |
902 | | static void wpa_config_write_cred(FILE *f, struct wpa_cred *cred) |
903 | 0 | { |
904 | 0 | size_t i; |
905 | |
|
906 | 0 | if (cred->priority) |
907 | 0 | fprintf(f, "\tpriority=%d\n", cred->priority); |
908 | 0 | if (cred->pcsc) |
909 | 0 | fprintf(f, "\tpcsc=%d\n", cred->pcsc); |
910 | 0 | if (cred->realm) |
911 | 0 | fprintf(f, "\trealm=\"%s\"\n", cred->realm); |
912 | 0 | if (cred->username) |
913 | 0 | fprintf(f, "\tusername=\"%s\"\n", cred->username); |
914 | 0 | if (cred->password && cred->ext_password) |
915 | 0 | fprintf(f, "\tpassword=ext:%s\n", cred->password); |
916 | 0 | else if (cred->password) |
917 | 0 | fprintf(f, "\tpassword=\"%s\"\n", cred->password); |
918 | 0 | if (cred->ca_cert) |
919 | 0 | fprintf(f, "\tca_cert=\"%s\"\n", cred->ca_cert); |
920 | 0 | if (cred->client_cert) |
921 | 0 | fprintf(f, "\tclient_cert=\"%s\"\n", cred->client_cert); |
922 | 0 | if (cred->private_key) |
923 | 0 | fprintf(f, "\tprivate_key=\"%s\"\n", cred->private_key); |
924 | 0 | if (cred->private_key_passwd) |
925 | 0 | fprintf(f, "\tprivate_key_passwd=\"%s\"\n", |
926 | 0 | cred->private_key_passwd); |
927 | 0 | if (cred->imsi) |
928 | 0 | fprintf(f, "\timsi=\"%s\"\n", cred->imsi); |
929 | 0 | if (cred->milenage) |
930 | 0 | fprintf(f, "\tmilenage=\"%s\"\n", cred->milenage); |
931 | 0 | for (i = 0; i < cred->num_domain; i++) |
932 | 0 | fprintf(f, "\tdomain=\"%s\"\n", cred->domain[i]); |
933 | 0 | if (cred->domain_suffix_match) |
934 | 0 | fprintf(f, "\tdomain_suffix_match=\"%s\"\n", |
935 | 0 | cred->domain_suffix_match); |
936 | 0 | if (cred->eap_method) { |
937 | 0 | const char *name; |
938 | 0 | name = eap_get_name(cred->eap_method[0].vendor, |
939 | 0 | cred->eap_method[0].method); |
940 | 0 | if (name) |
941 | 0 | fprintf(f, "\teap=%s\n", name); |
942 | 0 | } |
943 | 0 | if (cred->phase1) |
944 | 0 | fprintf(f, "\tphase1=\"%s\"\n", cred->phase1); |
945 | 0 | if (cred->phase2) |
946 | 0 | fprintf(f, "\tphase2=\"%s\"\n", cred->phase2); |
947 | 0 | if (cred->excluded_ssid) { |
948 | 0 | size_t j; |
949 | 0 | for (i = 0; i < cred->num_excluded_ssid; i++) { |
950 | 0 | struct excluded_ssid *e = &cred->excluded_ssid[i]; |
951 | 0 | fprintf(f, "\texcluded_ssid="); |
952 | 0 | for (j = 0; j < e->ssid_len; j++) |
953 | 0 | fprintf(f, "%02x", e->ssid[j]); |
954 | 0 | fprintf(f, "\n"); |
955 | 0 | } |
956 | 0 | } |
957 | 0 | if (cred->roaming_partner) { |
958 | 0 | for (i = 0; i < cred->num_roaming_partner; i++) { |
959 | 0 | struct roaming_partner *p = &cred->roaming_partner[i]; |
960 | 0 | fprintf(f, "\troaming_partner=\"%s,%d,%u,%s\"\n", |
961 | 0 | p->fqdn, p->exact_match, p->priority, |
962 | 0 | p->country); |
963 | 0 | } |
964 | 0 | } |
965 | 0 | if (cred->update_identifier) |
966 | 0 | fprintf(f, "\tupdate_identifier=%d\n", cred->update_identifier); |
967 | |
|
968 | 0 | if (cred->provisioning_sp) |
969 | 0 | fprintf(f, "\tprovisioning_sp=\"%s\"\n", cred->provisioning_sp); |
970 | 0 | if (cred->sp_priority) |
971 | 0 | fprintf(f, "\tsp_priority=%d\n", cred->sp_priority); |
972 | |
|
973 | 0 | if (cred->min_dl_bandwidth_home) |
974 | 0 | fprintf(f, "\tmin_dl_bandwidth_home=%u\n", |
975 | 0 | cred->min_dl_bandwidth_home); |
976 | 0 | if (cred->min_ul_bandwidth_home) |
977 | 0 | fprintf(f, "\tmin_ul_bandwidth_home=%u\n", |
978 | 0 | cred->min_ul_bandwidth_home); |
979 | 0 | if (cred->min_dl_bandwidth_roaming) |
980 | 0 | fprintf(f, "\tmin_dl_bandwidth_roaming=%u\n", |
981 | 0 | cred->min_dl_bandwidth_roaming); |
982 | 0 | if (cred->min_ul_bandwidth_roaming) |
983 | 0 | fprintf(f, "\tmin_ul_bandwidth_roaming=%u\n", |
984 | 0 | cred->min_ul_bandwidth_roaming); |
985 | |
|
986 | 0 | if (cred->max_bss_load) |
987 | 0 | fprintf(f, "\tmax_bss_load=%u\n", |
988 | 0 | cred->max_bss_load); |
989 | |
|
990 | 0 | if (cred->ocsp) |
991 | 0 | fprintf(f, "\tocsp=%d\n", cred->ocsp); |
992 | |
|
993 | 0 | if (cred->num_req_conn_capab) { |
994 | 0 | for (i = 0; i < cred->num_req_conn_capab; i++) { |
995 | 0 | int *ports; |
996 | |
|
997 | 0 | fprintf(f, "\treq_conn_capab=%u", |
998 | 0 | cred->req_conn_capab_proto[i]); |
999 | 0 | ports = cred->req_conn_capab_port[i]; |
1000 | 0 | if (ports) { |
1001 | 0 | int j; |
1002 | 0 | for (j = 0; ports[j] != -1; j++) { |
1003 | 0 | fprintf(f, "%s%d", j > 0 ? "," : ":", |
1004 | 0 | ports[j]); |
1005 | 0 | } |
1006 | 0 | } |
1007 | 0 | fprintf(f, "\n"); |
1008 | 0 | } |
1009 | 0 | } |
1010 | |
|
1011 | 0 | if (cred->num_home_ois) { |
1012 | 0 | size_t j; |
1013 | |
|
1014 | 0 | fprintf(f, "\thome_ois=\""); |
1015 | 0 | for (i = 0; i < cred->num_home_ois; i++) { |
1016 | 0 | if (i > 0) |
1017 | 0 | fprintf(f, ","); |
1018 | 0 | for (j = 0; j < cred->home_ois_len[i]; j++) |
1019 | 0 | fprintf(f, "%02x", |
1020 | 0 | cred->home_ois[i][j]); |
1021 | 0 | } |
1022 | 0 | fprintf(f, "\"\n"); |
1023 | 0 | } |
1024 | |
|
1025 | 0 | if (cred->num_required_home_ois) { |
1026 | 0 | size_t j; |
1027 | |
|
1028 | 0 | fprintf(f, "\trequired_home_ois=\""); |
1029 | 0 | for (i = 0; i < cred->num_required_home_ois; i++) { |
1030 | 0 | if (i > 0) |
1031 | 0 | fprintf(f, ","); |
1032 | 0 | for (j = 0; j < cred->required_home_ois_len[i]; j++) |
1033 | 0 | fprintf(f, "%02x", |
1034 | 0 | cred->required_home_ois[i][j]); |
1035 | 0 | } |
1036 | 0 | fprintf(f, "\"\n"); |
1037 | 0 | } |
1038 | |
|
1039 | 0 | if (cred->num_roaming_consortiums) { |
1040 | 0 | size_t j; |
1041 | |
|
1042 | 0 | fprintf(f, "\troaming_consortiums=\""); |
1043 | 0 | for (i = 0; i < cred->num_roaming_consortiums; i++) { |
1044 | 0 | if (i > 0) |
1045 | 0 | fprintf(f, ","); |
1046 | 0 | for (j = 0; j < cred->roaming_consortiums_len[i]; j++) |
1047 | 0 | fprintf(f, "%02x", |
1048 | 0 | cred->roaming_consortiums[i][j]); |
1049 | 0 | } |
1050 | 0 | fprintf(f, "\"\n"); |
1051 | 0 | } |
1052 | |
|
1053 | 0 | if (cred->sim_num != DEFAULT_USER_SELECTED_SIM) |
1054 | 0 | fprintf(f, "\tsim_num=%d\n", cred->sim_num); |
1055 | |
|
1056 | 0 | if (cred->engine) |
1057 | 0 | fprintf(f, "\tengine=%d\n", cred->engine); |
1058 | 0 | if (cred->engine_id) |
1059 | 0 | fprintf(f, "\tengine_id=\"%s\"\n", cred->engine_id); |
1060 | 0 | if (cred->key_id) |
1061 | 0 | fprintf(f, "\tkey_id=\"%s\"\n", cred->key_id); |
1062 | 0 | if (cred->cert_id) |
1063 | 0 | fprintf(f, "\tcert_id=\"%s\"\n", cred->cert_id); |
1064 | 0 | if (cred->ca_cert_id) |
1065 | 0 | fprintf(f, "\tca_cert_id=\"%s\"\n", cred->ca_cert_id); |
1066 | |
|
1067 | 0 | if (cred->imsi_privacy_cert) |
1068 | 0 | fprintf(f, "\timsi_privacy_cert=\"%s\"\n", |
1069 | 0 | cred->imsi_privacy_cert); |
1070 | 0 | if (cred->imsi_privacy_attr) |
1071 | 0 | fprintf(f, "\timsi_privacy_attr=\"%s\"\n", |
1072 | 0 | cred->imsi_privacy_attr); |
1073 | 0 | } |
1074 | | |
1075 | | |
1076 | | #ifndef CONFIG_NO_CONFIG_BLOBS |
1077 | | static int wpa_config_write_blob(FILE *f, struct wpa_config_blob *blob) |
1078 | 0 | { |
1079 | 0 | char *encoded; |
1080 | |
|
1081 | 0 | encoded = base64_encode(blob->data, blob->len, NULL); |
1082 | 0 | if (encoded == NULL) |
1083 | 0 | return -1; |
1084 | | |
1085 | 0 | fprintf(f, "\nblob-base64-%s={\n%s}\n", blob->name, encoded); |
1086 | 0 | os_free(encoded); |
1087 | 0 | return 0; |
1088 | 0 | } |
1089 | | #endif /* CONFIG_NO_CONFIG_BLOBS */ |
1090 | | |
1091 | | |
1092 | | static void write_global_bin(FILE *f, const char *field, |
1093 | | const struct wpabuf *val) |
1094 | 0 | { |
1095 | 0 | size_t i; |
1096 | 0 | const u8 *pos; |
1097 | |
|
1098 | 0 | if (val == NULL) |
1099 | 0 | return; |
1100 | | |
1101 | 0 | fprintf(f, "%s=", field); |
1102 | 0 | pos = wpabuf_head(val); |
1103 | 0 | for (i = 0; i < wpabuf_len(val); i++) |
1104 | 0 | fprintf(f, "%02X", *pos++); |
1105 | 0 | fprintf(f, "\n"); |
1106 | 0 | } |
1107 | | |
1108 | | |
1109 | | static void wpa_config_write_global(FILE *f, struct wpa_config *config) |
1110 | 0 | { |
1111 | | #ifdef CONFIG_CTRL_IFACE |
1112 | | if (config->ctrl_interface) |
1113 | | fprintf(f, "ctrl_interface=%s\n", config->ctrl_interface); |
1114 | | if (config->ctrl_interface_group) |
1115 | | fprintf(f, "ctrl_interface_group=%s\n", |
1116 | | config->ctrl_interface_group); |
1117 | | #endif /* CONFIG_CTRL_IFACE */ |
1118 | 0 | if (config->eapol_version != DEFAULT_EAPOL_VERSION) |
1119 | 0 | fprintf(f, "eapol_version=%d\n", config->eapol_version); |
1120 | 0 | if (config->ap_scan != DEFAULT_AP_SCAN) |
1121 | 0 | fprintf(f, "ap_scan=%d\n", config->ap_scan); |
1122 | 0 | if (config->disable_scan_offload) |
1123 | 0 | fprintf(f, "disable_scan_offload=%d\n", |
1124 | 0 | config->disable_scan_offload); |
1125 | 0 | if (config->fast_reauth != DEFAULT_FAST_REAUTH) |
1126 | 0 | fprintf(f, "fast_reauth=%d\n", config->fast_reauth); |
1127 | 0 | if (config->opensc_engine_path) |
1128 | 0 | fprintf(f, "opensc_engine_path=%s\n", |
1129 | 0 | config->opensc_engine_path); |
1130 | 0 | if (config->pkcs11_engine_path) |
1131 | 0 | fprintf(f, "pkcs11_engine_path=%s\n", |
1132 | 0 | config->pkcs11_engine_path); |
1133 | 0 | if (config->pkcs11_module_path) |
1134 | 0 | fprintf(f, "pkcs11_module_path=%s\n", |
1135 | 0 | config->pkcs11_module_path); |
1136 | 0 | if (config->openssl_ciphers) |
1137 | 0 | fprintf(f, "openssl_ciphers=%s\n", config->openssl_ciphers); |
1138 | 0 | if (config->pcsc_reader) |
1139 | 0 | fprintf(f, "pcsc_reader=%s\n", config->pcsc_reader); |
1140 | 0 | if (config->pcsc_pin) |
1141 | 0 | fprintf(f, "pcsc_pin=%s\n", config->pcsc_pin); |
1142 | 0 | if (config->driver_param) |
1143 | 0 | fprintf(f, "driver_param=%s\n", config->driver_param); |
1144 | 0 | if (config->dot11RSNAConfigPMKLifetime) |
1145 | 0 | fprintf(f, "dot11RSNAConfigPMKLifetime=%u\n", |
1146 | 0 | config->dot11RSNAConfigPMKLifetime); |
1147 | 0 | if (config->dot11RSNAConfigPMKReauthThreshold) |
1148 | 0 | fprintf(f, "dot11RSNAConfigPMKReauthThreshold=%u\n", |
1149 | 0 | config->dot11RSNAConfigPMKReauthThreshold); |
1150 | 0 | if (config->dot11RSNAConfigSATimeout) |
1151 | 0 | fprintf(f, "dot11RSNAConfigSATimeout=%u\n", |
1152 | 0 | config->dot11RSNAConfigSATimeout); |
1153 | 0 | if (config->update_config) |
1154 | 0 | fprintf(f, "update_config=%d\n", config->update_config); |
1155 | | #ifdef CONFIG_WPS |
1156 | | if (!is_nil_uuid(config->uuid)) { |
1157 | | char buf[40]; |
1158 | | uuid_bin2str(config->uuid, buf, sizeof(buf)); |
1159 | | fprintf(f, "uuid=%s\n", buf); |
1160 | | } |
1161 | | if (config->auto_uuid) |
1162 | | fprintf(f, "auto_uuid=%d\n", config->auto_uuid); |
1163 | | if (config->device_name) |
1164 | | fprintf(f, "device_name=%s\n", config->device_name); |
1165 | | if (config->manufacturer) |
1166 | | fprintf(f, "manufacturer=%s\n", config->manufacturer); |
1167 | | if (config->model_name) |
1168 | | fprintf(f, "model_name=%s\n", config->model_name); |
1169 | | if (config->model_number) |
1170 | | fprintf(f, "model_number=%s\n", config->model_number); |
1171 | | if (config->serial_number) |
1172 | | fprintf(f, "serial_number=%s\n", config->serial_number); |
1173 | | { |
1174 | | char _buf[WPS_DEV_TYPE_BUFSIZE], *buf; |
1175 | | buf = wps_dev_type_bin2str(config->device_type, |
1176 | | _buf, sizeof(_buf)); |
1177 | | if (os_strcmp(buf, "0-00000000-0") != 0) |
1178 | | fprintf(f, "device_type=%s\n", buf); |
1179 | | } |
1180 | | if (WPA_GET_BE32(config->os_version)) |
1181 | | fprintf(f, "os_version=%08x\n", |
1182 | | WPA_GET_BE32(config->os_version)); |
1183 | | if (config->config_methods) |
1184 | | fprintf(f, "config_methods=%s\n", config->config_methods); |
1185 | | if (config->wps_cred_processing) |
1186 | | fprintf(f, "wps_cred_processing=%d\n", |
1187 | | config->wps_cred_processing); |
1188 | | if (config->wps_cred_add_sae) |
1189 | | fprintf(f, "wps_cred_add_sae=%d\n", |
1190 | | config->wps_cred_add_sae); |
1191 | | if (config->wps_vendor_ext_m1) { |
1192 | | int i, len = wpabuf_len(config->wps_vendor_ext_m1); |
1193 | | const u8 *p = wpabuf_head_u8(config->wps_vendor_ext_m1); |
1194 | | if (len > 0) { |
1195 | | fprintf(f, "wps_vendor_ext_m1="); |
1196 | | for (i = 0; i < len; i++) |
1197 | | fprintf(f, "%02x", *p++); |
1198 | | fprintf(f, "\n"); |
1199 | | } |
1200 | | } |
1201 | | #endif /* CONFIG_WPS */ |
1202 | | #ifdef CONFIG_P2P |
1203 | | { |
1204 | | int i; |
1205 | | char _buf[WPS_DEV_TYPE_BUFSIZE], *buf; |
1206 | | |
1207 | | for (i = 0; i < config->num_sec_device_types; i++) { |
1208 | | buf = wps_dev_type_bin2str(config->sec_device_type[i], |
1209 | | _buf, sizeof(_buf)); |
1210 | | if (buf) |
1211 | | fprintf(f, "sec_device_type=%s\n", buf); |
1212 | | } |
1213 | | } |
1214 | | if (config->p2p_listen_reg_class) |
1215 | | fprintf(f, "p2p_listen_reg_class=%d\n", |
1216 | | config->p2p_listen_reg_class); |
1217 | | if (config->p2p_listen_channel) |
1218 | | fprintf(f, "p2p_listen_channel=%d\n", |
1219 | | config->p2p_listen_channel); |
1220 | | if (config->p2p_oper_reg_class) |
1221 | | fprintf(f, "p2p_oper_reg_class=%d\n", |
1222 | | config->p2p_oper_reg_class); |
1223 | | if (config->p2p_oper_channel) |
1224 | | fprintf(f, "p2p_oper_channel=%d\n", config->p2p_oper_channel); |
1225 | | if (config->p2p_go_intent != DEFAULT_P2P_GO_INTENT) |
1226 | | fprintf(f, "p2p_go_intent=%d\n", config->p2p_go_intent); |
1227 | | if (config->p2p_ssid_postfix) |
1228 | | fprintf(f, "p2p_ssid_postfix=%s\n", config->p2p_ssid_postfix); |
1229 | | if (config->persistent_reconnect) |
1230 | | fprintf(f, "persistent_reconnect=%d\n", |
1231 | | config->persistent_reconnect); |
1232 | | if (config->p2p_intra_bss != DEFAULT_P2P_INTRA_BSS) |
1233 | | fprintf(f, "p2p_intra_bss=%d\n", config->p2p_intra_bss); |
1234 | | if (config->p2p_group_idle) |
1235 | | fprintf(f, "p2p_group_idle=%d\n", config->p2p_group_idle); |
1236 | | if (config->p2p_passphrase_len) |
1237 | | fprintf(f, "p2p_passphrase_len=%u\n", |
1238 | | config->p2p_passphrase_len); |
1239 | | if (config->p2p_pref_chan) { |
1240 | | unsigned int i; |
1241 | | fprintf(f, "p2p_pref_chan="); |
1242 | | for (i = 0; i < config->num_p2p_pref_chan; i++) { |
1243 | | fprintf(f, "%s%u:%u", i > 0 ? "," : "", |
1244 | | config->p2p_pref_chan[i].op_class, |
1245 | | config->p2p_pref_chan[i].chan); |
1246 | | } |
1247 | | fprintf(f, "\n"); |
1248 | | } |
1249 | | if (config->p2p_no_go_freq.num) { |
1250 | | char *val = freq_range_list_str(&config->p2p_no_go_freq); |
1251 | | if (val) { |
1252 | | fprintf(f, "p2p_no_go_freq=%s\n", val); |
1253 | | os_free(val); |
1254 | | } |
1255 | | } |
1256 | | if (config->p2p_add_cli_chan) |
1257 | | fprintf(f, "p2p_add_cli_chan=%d\n", config->p2p_add_cli_chan); |
1258 | | if (config->p2p_optimize_listen_chan != |
1259 | | DEFAULT_P2P_OPTIMIZE_LISTEN_CHAN) |
1260 | | fprintf(f, "p2p_optimize_listen_chan=%d\n", |
1261 | | config->p2p_optimize_listen_chan); |
1262 | | if (config->p2p_go_ht40) |
1263 | | fprintf(f, "p2p_go_ht40=%d\n", config->p2p_go_ht40); |
1264 | | if (config->p2p_go_vht) |
1265 | | fprintf(f, "p2p_go_vht=%d\n", config->p2p_go_vht); |
1266 | | if (config->p2p_go_he) |
1267 | | fprintf(f, "p2p_go_he=%d\n", config->p2p_go_he); |
1268 | | if (config->p2p_go_edmg) |
1269 | | fprintf(f, "p2p_go_edmg=%d\n", config->p2p_go_edmg); |
1270 | | if (config->p2p_go_ctwindow != DEFAULT_P2P_GO_CTWINDOW) |
1271 | | fprintf(f, "p2p_go_ctwindow=%d\n", config->p2p_go_ctwindow); |
1272 | | if (config->p2p_disabled) |
1273 | | fprintf(f, "p2p_disabled=%d\n", config->p2p_disabled); |
1274 | | if (config->p2p_no_group_iface) |
1275 | | fprintf(f, "p2p_no_group_iface=%d\n", |
1276 | | config->p2p_no_group_iface); |
1277 | | if (config->p2p_ignore_shared_freq) |
1278 | | fprintf(f, "p2p_ignore_shared_freq=%d\n", |
1279 | | config->p2p_ignore_shared_freq); |
1280 | | if (config->p2p_cli_probe) |
1281 | | fprintf(f, "p2p_cli_probe=%d\n", config->p2p_cli_probe); |
1282 | | if (config->p2p_go_freq_change_policy != DEFAULT_P2P_GO_FREQ_MOVE) |
1283 | | fprintf(f, "p2p_go_freq_change_policy=%u\n", |
1284 | | config->p2p_go_freq_change_policy); |
1285 | | |
1286 | | if (config->p2p_6ghz_disable) |
1287 | | fprintf(f, "p2p_6ghz_disable=%d\n", config->p2p_6ghz_disable); |
1288 | | |
1289 | | if (WPA_GET_BE32(config->ip_addr_go)) |
1290 | | fprintf(f, "ip_addr_go=%u.%u.%u.%u\n", |
1291 | | config->ip_addr_go[0], config->ip_addr_go[1], |
1292 | | config->ip_addr_go[2], config->ip_addr_go[3]); |
1293 | | if (WPA_GET_BE32(config->ip_addr_mask)) |
1294 | | fprintf(f, "ip_addr_mask=%u.%u.%u.%u\n", |
1295 | | config->ip_addr_mask[0], config->ip_addr_mask[1], |
1296 | | config->ip_addr_mask[2], config->ip_addr_mask[3]); |
1297 | | if (WPA_GET_BE32(config->ip_addr_start)) |
1298 | | fprintf(f, "ip_addr_start=%u.%u.%u.%u\n", |
1299 | | config->ip_addr_start[0], config->ip_addr_start[1], |
1300 | | config->ip_addr_start[2], config->ip_addr_start[3]); |
1301 | | if (WPA_GET_BE32(config->ip_addr_end)) |
1302 | | fprintf(f, "ip_addr_end=%u.%u.%u.%u\n", |
1303 | | config->ip_addr_end[0], config->ip_addr_end[1], |
1304 | | config->ip_addr_end[2], config->ip_addr_end[3]); |
1305 | | #endif /* CONFIG_P2P */ |
1306 | 0 | if (config->country[0] && config->country[1]) { |
1307 | 0 | fprintf(f, "country=%c%c\n", |
1308 | 0 | config->country[0], config->country[1]); |
1309 | 0 | } |
1310 | 0 | if (config->bss_max_count != DEFAULT_BSS_MAX_COUNT) |
1311 | 0 | fprintf(f, "bss_max_count=%u\n", config->bss_max_count); |
1312 | 0 | if (config->bss_expiration_age != DEFAULT_BSS_EXPIRATION_AGE) |
1313 | 0 | fprintf(f, "bss_expiration_age=%u\n", |
1314 | 0 | config->bss_expiration_age); |
1315 | 0 | if (config->bss_expiration_scan_count != |
1316 | 0 | DEFAULT_BSS_EXPIRATION_SCAN_COUNT) |
1317 | 0 | fprintf(f, "bss_expiration_scan_count=%u\n", |
1318 | 0 | config->bss_expiration_scan_count); |
1319 | 0 | if (config->filter_ssids) |
1320 | 0 | fprintf(f, "filter_ssids=%d\n", config->filter_ssids); |
1321 | 0 | if (config->filter_rssi) |
1322 | 0 | fprintf(f, "filter_rssi=%d\n", config->filter_rssi); |
1323 | 0 | if (config->max_num_sta != DEFAULT_MAX_NUM_STA) |
1324 | 0 | fprintf(f, "max_num_sta=%u\n", config->max_num_sta); |
1325 | 0 | if (config->ap_isolate != DEFAULT_AP_ISOLATE) |
1326 | 0 | fprintf(f, "ap_isolate=%u\n", config->ap_isolate); |
1327 | 0 | if (config->disassoc_low_ack) |
1328 | 0 | fprintf(f, "disassoc_low_ack=%d\n", config->disassoc_low_ack); |
1329 | 0 | #ifdef CONFIG_HS20 |
1330 | 0 | if (config->hs20) |
1331 | 0 | fprintf(f, "hs20=1\n"); |
1332 | 0 | #endif /* CONFIG_HS20 */ |
1333 | 0 | #ifdef CONFIG_INTERWORKING |
1334 | 0 | if (config->interworking) |
1335 | 0 | fprintf(f, "interworking=%d\n", config->interworking); |
1336 | 0 | if (!is_zero_ether_addr(config->hessid)) |
1337 | 0 | fprintf(f, "hessid=" MACSTR "\n", MAC2STR(config->hessid)); |
1338 | 0 | if (config->access_network_type != DEFAULT_ACCESS_NETWORK_TYPE) |
1339 | 0 | fprintf(f, "access_network_type=%d\n", |
1340 | 0 | config->access_network_type); |
1341 | 0 | if (config->go_interworking) |
1342 | 0 | fprintf(f, "go_interworking=%d\n", config->go_interworking); |
1343 | 0 | if (config->go_access_network_type) |
1344 | 0 | fprintf(f, "go_access_network_type=%d\n", |
1345 | 0 | config->go_access_network_type); |
1346 | 0 | if (config->go_internet) |
1347 | 0 | fprintf(f, "go_internet=%d\n", config->go_internet); |
1348 | 0 | if (config->go_venue_group) |
1349 | 0 | fprintf(f, "go_venue_group=%d\n", config->go_venue_group); |
1350 | 0 | if (config->go_venue_type) |
1351 | 0 | fprintf(f, "go_venue_type=%d\n", config->go_venue_type); |
1352 | 0 | #endif /* CONFIG_INTERWORKING */ |
1353 | 0 | if (config->pbc_in_m1) |
1354 | 0 | fprintf(f, "pbc_in_m1=%d\n", config->pbc_in_m1); |
1355 | 0 | if (config->wps_nfc_pw_from_config) { |
1356 | 0 | if (config->wps_nfc_dev_pw_id) |
1357 | 0 | fprintf(f, "wps_nfc_dev_pw_id=%d\n", |
1358 | 0 | config->wps_nfc_dev_pw_id); |
1359 | 0 | write_global_bin(f, "wps_nfc_dh_pubkey", |
1360 | 0 | config->wps_nfc_dh_pubkey); |
1361 | 0 | write_global_bin(f, "wps_nfc_dh_privkey", |
1362 | 0 | config->wps_nfc_dh_privkey); |
1363 | 0 | write_global_bin(f, "wps_nfc_dev_pw", config->wps_nfc_dev_pw); |
1364 | 0 | } |
1365 | |
|
1366 | 0 | if (config->ext_password_backend) |
1367 | 0 | fprintf(f, "ext_password_backend=%s\n", |
1368 | 0 | config->ext_password_backend); |
1369 | 0 | if (config->p2p_go_max_inactivity != DEFAULT_P2P_GO_MAX_INACTIVITY) |
1370 | 0 | fprintf(f, "p2p_go_max_inactivity=%d\n", |
1371 | 0 | config->p2p_go_max_inactivity); |
1372 | 0 | if (config->auto_interworking) |
1373 | 0 | fprintf(f, "auto_interworking=%d\n", |
1374 | 0 | config->auto_interworking); |
1375 | 0 | if (config->okc) |
1376 | 0 | fprintf(f, "okc=%d\n", config->okc); |
1377 | 0 | if (config->pmf) |
1378 | 0 | fprintf(f, "pmf=%d\n", config->pmf); |
1379 | 0 | if (config->dtim_period) |
1380 | 0 | fprintf(f, "dtim_period=%d\n", config->dtim_period); |
1381 | 0 | if (config->beacon_int) |
1382 | 0 | fprintf(f, "beacon_int=%d\n", config->beacon_int); |
1383 | |
|
1384 | 0 | if (config->sae_check_mfp) |
1385 | 0 | fprintf(f, "sae_check_mfp=%d\n", config->sae_check_mfp); |
1386 | |
|
1387 | 0 | if (config->sae_groups) { |
1388 | 0 | int i; |
1389 | 0 | fprintf(f, "sae_groups="); |
1390 | 0 | for (i = 0; config->sae_groups[i] > 0; i++) { |
1391 | 0 | fprintf(f, "%s%d", i > 0 ? " " : "", |
1392 | 0 | config->sae_groups[i]); |
1393 | 0 | } |
1394 | 0 | fprintf(f, "\n"); |
1395 | 0 | } |
1396 | |
|
1397 | 0 | if (config->sae_pwe) |
1398 | 0 | fprintf(f, "sae_pwe=%d\n", config->sae_pwe); |
1399 | |
|
1400 | 0 | if (config->sae_pmkid_in_assoc) |
1401 | 0 | fprintf(f, "sae_pmkid_in_assoc=%d\n", |
1402 | 0 | config->sae_pmkid_in_assoc); |
1403 | |
|
1404 | 0 | if (config->ap_vendor_elements) { |
1405 | 0 | int i, len = wpabuf_len(config->ap_vendor_elements); |
1406 | 0 | const u8 *p = wpabuf_head_u8(config->ap_vendor_elements); |
1407 | 0 | if (len > 0) { |
1408 | 0 | fprintf(f, "ap_vendor_elements="); |
1409 | 0 | for (i = 0; i < len; i++) |
1410 | 0 | fprintf(f, "%02x", *p++); |
1411 | 0 | fprintf(f, "\n"); |
1412 | 0 | } |
1413 | 0 | } |
1414 | |
|
1415 | 0 | if (config->ap_assocresp_elements) { |
1416 | 0 | int i, len = wpabuf_len(config->ap_assocresp_elements); |
1417 | 0 | const u8 *p = wpabuf_head_u8(config->ap_assocresp_elements); |
1418 | |
|
1419 | 0 | if (len > 0) { |
1420 | 0 | fprintf(f, "ap_assocresp_elements="); |
1421 | 0 | for (i = 0; i < len; i++) |
1422 | 0 | fprintf(f, "%02x", *p++); |
1423 | 0 | fprintf(f, "\n"); |
1424 | 0 | } |
1425 | 0 | } |
1426 | |
|
1427 | 0 | if (config->ignore_old_scan_res) |
1428 | 0 | fprintf(f, "ignore_old_scan_res=%d\n", |
1429 | 0 | config->ignore_old_scan_res); |
1430 | |
|
1431 | 0 | if (config->freq_list && config->freq_list[0]) { |
1432 | 0 | int i; |
1433 | 0 | fprintf(f, "freq_list="); |
1434 | 0 | for (i = 0; config->freq_list[i]; i++) { |
1435 | 0 | fprintf(f, "%s%d", i > 0 ? " " : "", |
1436 | 0 | config->freq_list[i]); |
1437 | 0 | } |
1438 | 0 | fprintf(f, "\n"); |
1439 | 0 | } |
1440 | 0 | if (config->initial_freq_list && config->initial_freq_list[0]) { |
1441 | 0 | int i; |
1442 | 0 | fprintf(f, "initial_freq_list="); |
1443 | 0 | for (i = 0; config->initial_freq_list[i]; i++) { |
1444 | 0 | fprintf(f, "%s%d", i > 0 ? " " : "", |
1445 | 0 | config->initial_freq_list[i]); |
1446 | 0 | } |
1447 | 0 | fprintf(f, "\n"); |
1448 | 0 | } |
1449 | 0 | if (config->scan_cur_freq != DEFAULT_SCAN_CUR_FREQ) |
1450 | 0 | fprintf(f, "scan_cur_freq=%d\n", config->scan_cur_freq); |
1451 | |
|
1452 | 0 | if (config->scan_res_valid_for_connect != |
1453 | 0 | DEFAULT_SCAN_RES_VALID_FOR_CONNECT) |
1454 | 0 | fprintf(f, "scan_res_valid_for_connect=%d\n", |
1455 | 0 | config->scan_res_valid_for_connect); |
1456 | |
|
1457 | 0 | if (config->sched_scan_interval) |
1458 | 0 | fprintf(f, "sched_scan_interval=%u\n", |
1459 | 0 | config->sched_scan_interval); |
1460 | |
|
1461 | 0 | if (config->sched_scan_start_delay) |
1462 | 0 | fprintf(f, "sched_scan_start_delay=%u\n", |
1463 | 0 | config->sched_scan_start_delay); |
1464 | |
|
1465 | 0 | if (config->external_sim) |
1466 | 0 | fprintf(f, "external_sim=%d\n", config->external_sim); |
1467 | |
|
1468 | 0 | if (config->tdls_external_control) |
1469 | 0 | fprintf(f, "tdls_external_control=%d\n", |
1470 | 0 | config->tdls_external_control); |
1471 | |
|
1472 | 0 | if (config->wowlan_triggers) |
1473 | 0 | fprintf(f, "wowlan_triggers=%s\n", |
1474 | 0 | config->wowlan_triggers); |
1475 | |
|
1476 | 0 | if (config->bgscan) |
1477 | 0 | fprintf(f, "bgscan=\"%s\"\n", config->bgscan); |
1478 | |
|
1479 | 0 | if (config->autoscan) |
1480 | 0 | fprintf(f, "autoscan=%s\n", config->autoscan); |
1481 | |
|
1482 | 0 | if (config->p2p_search_delay != DEFAULT_P2P_SEARCH_DELAY) |
1483 | 0 | fprintf(f, "p2p_search_delay=%u\n", |
1484 | 0 | config->p2p_search_delay); |
1485 | |
|
1486 | 0 | if (config->mac_addr) |
1487 | 0 | fprintf(f, "mac_addr=%d\n", config->mac_addr); |
1488 | |
|
1489 | 0 | if (config->rand_addr_lifetime != DEFAULT_RAND_ADDR_LIFETIME) |
1490 | 0 | fprintf(f, "rand_addr_lifetime=%u\n", |
1491 | 0 | config->rand_addr_lifetime); |
1492 | |
|
1493 | 0 | if (config->preassoc_mac_addr) |
1494 | 0 | fprintf(f, "preassoc_mac_addr=%d\n", config->preassoc_mac_addr); |
1495 | |
|
1496 | 0 | if (config->key_mgmt_offload != DEFAULT_KEY_MGMT_OFFLOAD) |
1497 | 0 | fprintf(f, "key_mgmt_offload=%d\n", config->key_mgmt_offload); |
1498 | |
|
1499 | 0 | if (config->user_mpm != DEFAULT_USER_MPM) |
1500 | 0 | fprintf(f, "user_mpm=%d\n", config->user_mpm); |
1501 | |
|
1502 | 0 | if (config->max_peer_links != DEFAULT_MAX_PEER_LINKS) |
1503 | 0 | fprintf(f, "max_peer_links=%d\n", config->max_peer_links); |
1504 | |
|
1505 | 0 | if (config->cert_in_cb != DEFAULT_CERT_IN_CB) |
1506 | 0 | fprintf(f, "cert_in_cb=%d\n", config->cert_in_cb); |
1507 | |
|
1508 | 0 | if (config->mesh_max_inactivity != DEFAULT_MESH_MAX_INACTIVITY) |
1509 | 0 | fprintf(f, "mesh_max_inactivity=%d\n", |
1510 | 0 | config->mesh_max_inactivity); |
1511 | |
|
1512 | 0 | if (config->mesh_fwding != DEFAULT_MESH_FWDING) |
1513 | 0 | fprintf(f, "mesh_fwding=%d\n", config->mesh_fwding); |
1514 | |
|
1515 | 0 | if (config->dot11RSNASAERetransPeriod != |
1516 | 0 | DEFAULT_DOT11_RSNA_SAE_RETRANS_PERIOD) |
1517 | 0 | fprintf(f, "dot11RSNASAERetransPeriod=%d\n", |
1518 | 0 | config->dot11RSNASAERetransPeriod); |
1519 | |
|
1520 | 0 | if (config->passive_scan) |
1521 | 0 | fprintf(f, "passive_scan=%d\n", config->passive_scan); |
1522 | |
|
1523 | 0 | if (config->reassoc_same_bss_optim) |
1524 | 0 | fprintf(f, "reassoc_same_bss_optim=%d\n", |
1525 | 0 | config->reassoc_same_bss_optim); |
1526 | |
|
1527 | 0 | if (config->wps_priority) |
1528 | 0 | fprintf(f, "wps_priority=%d\n", config->wps_priority); |
1529 | |
|
1530 | 0 | if (config->wpa_rsc_relaxation != DEFAULT_WPA_RSC_RELAXATION) |
1531 | 0 | fprintf(f, "wpa_rsc_relaxation=%d\n", |
1532 | 0 | config->wpa_rsc_relaxation); |
1533 | |
|
1534 | 0 | if (config->sched_scan_plans) |
1535 | 0 | fprintf(f, "sched_scan_plans=%s\n", config->sched_scan_plans); |
1536 | |
|
1537 | | #ifdef CONFIG_MBO |
1538 | | if (config->non_pref_chan) |
1539 | | fprintf(f, "non_pref_chan=%s\n", config->non_pref_chan); |
1540 | | if (config->mbo_cell_capa != DEFAULT_MBO_CELL_CAPA) |
1541 | | fprintf(f, "mbo_cell_capa=%u\n", config->mbo_cell_capa); |
1542 | | if (config->disassoc_imminent_rssi_threshold != |
1543 | | DEFAULT_DISASSOC_IMMINENT_RSSI_THRESHOLD) |
1544 | | fprintf(f, "disassoc_imminent_rssi_threshold=%d\n", |
1545 | | config->disassoc_imminent_rssi_threshold); |
1546 | | if (config->oce != DEFAULT_OCE_SUPPORT) |
1547 | | fprintf(f, "oce=%u\n", config->oce); |
1548 | | #endif /* CONFIG_MBO */ |
1549 | |
|
1550 | 0 | if (config->gas_address3) |
1551 | 0 | fprintf(f, "gas_address3=%d\n", config->gas_address3); |
1552 | |
|
1553 | 0 | if (config->ftm_responder) |
1554 | 0 | fprintf(f, "ftm_responder=%d\n", config->ftm_responder); |
1555 | 0 | if (config->ftm_initiator) |
1556 | 0 | fprintf(f, "ftm_initiator=%d\n", config->ftm_initiator); |
1557 | |
|
1558 | 0 | if (config->osu_dir) |
1559 | 0 | fprintf(f, "osu_dir=%s\n", config->osu_dir); |
1560 | |
|
1561 | 0 | if (config->fst_group_id) |
1562 | 0 | fprintf(f, "fst_group_id=%s\n", config->fst_group_id); |
1563 | 0 | if (config->fst_priority) |
1564 | 0 | fprintf(f, "fst_priority=%d\n", config->fst_priority); |
1565 | 0 | if (config->fst_llt) |
1566 | 0 | fprintf(f, "fst_llt=%d\n", config->fst_llt); |
1567 | |
|
1568 | 0 | if (config->gas_rand_addr_lifetime != DEFAULT_RAND_ADDR_LIFETIME) |
1569 | 0 | fprintf(f, "gas_rand_addr_lifetime=%u\n", |
1570 | 0 | config->gas_rand_addr_lifetime); |
1571 | 0 | if (config->gas_rand_mac_addr) |
1572 | 0 | fprintf(f, "gas_rand_mac_addr=%d\n", config->gas_rand_mac_addr); |
1573 | 0 | if (config->dpp_config_processing) |
1574 | 0 | fprintf(f, "dpp_config_processing=%d\n", |
1575 | 0 | config->dpp_config_processing); |
1576 | 0 | if (config->dpp_name) |
1577 | 0 | fprintf(f, "dpp_name=%s\n", config->dpp_name); |
1578 | 0 | if (config->dpp_mud_url) |
1579 | 0 | fprintf(f, "dpp_mud_url=%s\n", config->dpp_mud_url); |
1580 | 0 | if (config->dpp_extra_conf_req_name) |
1581 | 0 | fprintf(f, "dpp_extra_conf_req_name=%s\n", |
1582 | 0 | config->dpp_extra_conf_req_name); |
1583 | 0 | if (config->dpp_extra_conf_req_value) |
1584 | 0 | fprintf(f, "dpp_extra_conf_req_value=%s\n", |
1585 | 0 | config->dpp_extra_conf_req_value); |
1586 | 0 | if (config->dpp_connector_privacy_default) |
1587 | 0 | fprintf(f, "dpp_connector_privacy_default=%d\n", |
1588 | 0 | config->dpp_connector_privacy_default); |
1589 | 0 | if (config->coloc_intf_reporting) |
1590 | 0 | fprintf(f, "coloc_intf_reporting=%d\n", |
1591 | 0 | config->coloc_intf_reporting); |
1592 | 0 | if (config->p2p_device_random_mac_addr) |
1593 | 0 | fprintf(f, "p2p_device_random_mac_addr=%d\n", |
1594 | 0 | config->p2p_device_random_mac_addr); |
1595 | 0 | if (!is_zero_ether_addr(config->p2p_device_persistent_mac_addr)) |
1596 | 0 | fprintf(f, "p2p_device_persistent_mac_addr=" MACSTR "\n", |
1597 | 0 | MAC2STR(config->p2p_device_persistent_mac_addr)); |
1598 | 0 | if (config->p2p_interface_random_mac_addr) |
1599 | 0 | fprintf(f, "p2p_interface_random_mac_addr=%d\n", |
1600 | 0 | config->p2p_interface_random_mac_addr); |
1601 | 0 | if (config->disable_btm) |
1602 | 0 | fprintf(f, "disable_btm=1\n"); |
1603 | 0 | if (config->extended_key_id != DEFAULT_EXTENDED_KEY_ID) |
1604 | 0 | fprintf(f, "extended_key_id=%d\n", |
1605 | 0 | config->extended_key_id); |
1606 | 0 | if (config->wowlan_disconnect_on_deinit) |
1607 | 0 | fprintf(f, "wowlan_disconnect_on_deinit=%d\n", |
1608 | 0 | config->wowlan_disconnect_on_deinit); |
1609 | 0 | } |
1610 | | |
1611 | | #endif /* CONFIG_NO_CONFIG_WRITE */ |
1612 | | |
1613 | | |
1614 | | int wpa_config_write(const char *name, struct wpa_config *config) |
1615 | 0 | { |
1616 | 0 | #ifndef CONFIG_NO_CONFIG_WRITE |
1617 | 0 | FILE *f; |
1618 | 0 | struct wpa_ssid *ssid; |
1619 | 0 | struct wpa_cred *cred; |
1620 | 0 | #ifndef CONFIG_NO_CONFIG_BLOBS |
1621 | 0 | struct wpa_config_blob *blob; |
1622 | 0 | #endif /* CONFIG_NO_CONFIG_BLOBS */ |
1623 | 0 | int ret = 0; |
1624 | 0 | const char *orig_name = name; |
1625 | 0 | int tmp_len; |
1626 | 0 | char *tmp_name; |
1627 | |
|
1628 | 0 | if (!name) { |
1629 | 0 | wpa_printf(MSG_ERROR, "No configuration file for writing"); |
1630 | 0 | return -1; |
1631 | 0 | } |
1632 | | |
1633 | 0 | tmp_len = os_strlen(name) + 5; /* allow space for .tmp suffix */ |
1634 | 0 | tmp_name = os_malloc(tmp_len); |
1635 | 0 | if (tmp_name) { |
1636 | 0 | os_snprintf(tmp_name, tmp_len, "%s.tmp", name); |
1637 | 0 | name = tmp_name; |
1638 | 0 | } |
1639 | |
|
1640 | 0 | wpa_printf(MSG_DEBUG, "Writing configuration file '%s'", name); |
1641 | |
|
1642 | 0 | f = fopen(name, "w"); |
1643 | 0 | if (f == NULL) { |
1644 | 0 | wpa_printf(MSG_DEBUG, "Failed to open '%s' for writing", name); |
1645 | 0 | os_free(tmp_name); |
1646 | 0 | return -1; |
1647 | 0 | } |
1648 | | |
1649 | 0 | wpa_config_write_global(f, config); |
1650 | |
|
1651 | 0 | for (cred = config->cred; cred; cred = cred->next) { |
1652 | 0 | if (cred->temporary) |
1653 | 0 | continue; |
1654 | 0 | fprintf(f, "\ncred={\n"); |
1655 | 0 | wpa_config_write_cred(f, cred); |
1656 | 0 | fprintf(f, "}\n"); |
1657 | 0 | } |
1658 | |
|
1659 | 0 | for (ssid = config->ssid; ssid; ssid = ssid->next) { |
1660 | 0 | if (ssid->key_mgmt == WPA_KEY_MGMT_WPS || ssid->temporary || |
1661 | 0 | ssid->ro) |
1662 | 0 | continue; /* do not save temporary networks */ |
1663 | 0 | if (wpa_key_mgmt_wpa_psk_no_sae(ssid->key_mgmt) && |
1664 | 0 | !ssid->psk_set && !ssid->passphrase) |
1665 | 0 | continue; /* do not save invalid network */ |
1666 | 0 | if (wpa_key_mgmt_sae(ssid->key_mgmt) && |
1667 | 0 | !ssid->passphrase && !ssid->sae_password) |
1668 | 0 | continue; /* do not save invalid network */ |
1669 | 0 | fprintf(f, "\nnetwork={\n"); |
1670 | 0 | wpa_config_write_network(f, ssid); |
1671 | 0 | fprintf(f, "}\n"); |
1672 | 0 | } |
1673 | |
|
1674 | 0 | #ifndef CONFIG_NO_CONFIG_BLOBS |
1675 | 0 | for (blob = config->blobs; blob; blob = blob->next) { |
1676 | 0 | ret = wpa_config_write_blob(f, blob); |
1677 | 0 | if (ret) |
1678 | 0 | break; |
1679 | 0 | } |
1680 | 0 | #endif /* CONFIG_NO_CONFIG_BLOBS */ |
1681 | |
|
1682 | 0 | os_fdatasync(f); |
1683 | |
|
1684 | 0 | fclose(f); |
1685 | |
|
1686 | 0 | if (tmp_name) { |
1687 | 0 | int chmod_ret = 0; |
1688 | |
|
1689 | | #ifdef ANDROID |
1690 | | chmod_ret = chmod(tmp_name, |
1691 | | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); |
1692 | | #endif /* ANDROID */ |
1693 | 0 | if (chmod_ret != 0 || rename(tmp_name, orig_name) != 0) |
1694 | 0 | ret = -1; |
1695 | |
|
1696 | 0 | os_free(tmp_name); |
1697 | 0 | } |
1698 | |
|
1699 | 0 | wpa_printf(MSG_DEBUG, "Configuration file '%s' written %ssuccessfully", |
1700 | 0 | orig_name, ret ? "un" : ""); |
1701 | 0 | return ret; |
1702 | | #else /* CONFIG_NO_CONFIG_WRITE */ |
1703 | | return -1; |
1704 | | #endif /* CONFIG_NO_CONFIG_WRITE */ |
1705 | 0 | } |