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