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