$search
00001 /* 00002 * WPA Supplicant / Configuration backend: text file 00003 * Copyright (c) 2003-2008, Jouni Malinen <j@w1.fi> 00004 * 00005 * This program is free software; you can redistribute it and/or modify 00006 * it under the terms of the GNU General Public License version 2 as 00007 * published by the Free Software Foundation. 00008 * 00009 * Alternatively, this software may be distributed under the terms of BSD 00010 * license. 00011 * 00012 * See README and COPYING for more details. 00013 * 00014 * This file implements a configuration backend for text files. All the 00015 * configuration information is stored in a text file that uses a format 00016 * described in the sample configuration file, wpa_supplicant.conf. 00017 */ 00018 00019 #include "includes.h" 00020 00021 #include "common.h" 00022 #include "config.h" 00023 #include "base64.h" 00024 #include "uuid.h" 00025 #include "eap_peer/eap_methods.h" 00026 00027 00042 static char * wpa_config_get_line(char *s, int size, FILE *stream, int *line, 00043 char **_pos) 00044 { 00045 char *pos, *end, *sstart; 00046 00047 while (fgets(s, size, stream)) { 00048 (*line)++; 00049 s[size - 1] = '\0'; 00050 pos = s; 00051 00052 /* Skip white space from the beginning of line. */ 00053 while (*pos == ' ' || *pos == '\t' || *pos == '\r') 00054 pos++; 00055 00056 /* Skip comment lines and empty lines */ 00057 if (*pos == '#' || *pos == '\n' || *pos == '\0') 00058 continue; 00059 00060 /* 00061 * Remove # comments unless they are within a double quoted 00062 * string. 00063 */ 00064 sstart = os_strchr(pos, '"'); 00065 if (sstart) 00066 sstart = os_strrchr(sstart + 1, '"'); 00067 if (!sstart) 00068 sstart = pos; 00069 end = os_strchr(sstart, '#'); 00070 if (end) 00071 *end-- = '\0'; 00072 else 00073 end = pos + os_strlen(pos) - 1; 00074 00075 /* Remove trailing white space. */ 00076 while (end > pos && 00077 (*end == '\n' || *end == ' ' || *end == '\t' || 00078 *end == '\r')) 00079 *end-- = '\0'; 00080 00081 if (*pos == '\0') 00082 continue; 00083 00084 if (_pos) 00085 *_pos = pos; 00086 return pos; 00087 } 00088 00089 if (_pos) 00090 *_pos = NULL; 00091 return NULL; 00092 } 00093 00094 00095 static int wpa_config_validate_network(struct wpa_ssid *ssid, int line) 00096 { 00097 int errors = 0; 00098 00099 if (ssid->passphrase) { 00100 if (ssid->psk_set) { 00101 wpa_printf(MSG_ERROR, "Line %d: both PSK and " 00102 "passphrase configured.", line); 00103 errors++; 00104 } 00105 wpa_config_update_psk(ssid); 00106 } 00107 00108 if ((ssid->key_mgmt & (WPA_KEY_MGMT_PSK | WPA_KEY_MGMT_FT_PSK | 00109 WPA_KEY_MGMT_PSK_SHA256)) && 00110 !ssid->psk_set) { 00111 wpa_printf(MSG_ERROR, "Line %d: WPA-PSK accepted for key " 00112 "management, but no PSK configured.", line); 00113 errors++; 00114 } 00115 00116 if ((ssid->group_cipher & WPA_CIPHER_CCMP) && 00117 !(ssid->pairwise_cipher & WPA_CIPHER_CCMP) && 00118 !(ssid->pairwise_cipher & WPA_CIPHER_NONE)) { 00119 /* Group cipher cannot be stronger than the pairwise cipher. */ 00120 wpa_printf(MSG_DEBUG, "Line %d: removed CCMP from group cipher" 00121 " list since it was not allowed for pairwise " 00122 "cipher", line); 00123 ssid->group_cipher &= ~WPA_CIPHER_CCMP; 00124 } 00125 00126 return errors; 00127 } 00128 00129 00130 static struct wpa_ssid * wpa_config_read_network(FILE *f, int *line, int id) 00131 { 00132 struct wpa_ssid *ssid; 00133 int errors = 0, end = 0; 00134 char buf[256], *pos, *pos2; 00135 00136 wpa_printf(MSG_MSGDUMP, "Line: %d - start of a new network block", 00137 *line); 00138 ssid = os_zalloc(sizeof(*ssid)); 00139 if (ssid == NULL) 00140 return NULL; 00141 ssid->id = id; 00142 00143 wpa_config_set_network_defaults(ssid); 00144 00145 while (wpa_config_get_line(buf, sizeof(buf), f, line, &pos)) { 00146 if (os_strcmp(pos, "}") == 0) { 00147 end = 1; 00148 break; 00149 } 00150 00151 pos2 = os_strchr(pos, '='); 00152 if (pos2 == NULL) { 00153 wpa_printf(MSG_ERROR, "Line %d: Invalid SSID line " 00154 "'%s'.", *line, pos); 00155 errors++; 00156 continue; 00157 } 00158 00159 *pos2++ = '\0'; 00160 if (*pos2 == '"') { 00161 if (os_strchr(pos2 + 1, '"') == NULL) { 00162 wpa_printf(MSG_ERROR, "Line %d: invalid " 00163 "quotation '%s'.", *line, pos2); 00164 errors++; 00165 continue; 00166 } 00167 } 00168 00169 if (wpa_config_set(ssid, pos, pos2, *line) < 0) 00170 errors++; 00171 } 00172 00173 if (!end) { 00174 wpa_printf(MSG_ERROR, "Line %d: network block was not " 00175 "terminated properly.", *line); 00176 errors++; 00177 } 00178 00179 errors += wpa_config_validate_network(ssid, *line); 00180 00181 if (errors) { 00182 wpa_config_free_ssid(ssid); 00183 ssid = NULL; 00184 } 00185 00186 return ssid; 00187 } 00188 00189 00190 #ifndef CONFIG_NO_CONFIG_BLOBS 00191 static struct wpa_config_blob * wpa_config_read_blob(FILE *f, int *line, 00192 const char *name) 00193 { 00194 struct wpa_config_blob *blob; 00195 char buf[256], *pos; 00196 unsigned char *encoded = NULL, *nencoded; 00197 int end = 0; 00198 size_t encoded_len = 0, len; 00199 00200 wpa_printf(MSG_MSGDUMP, "Line: %d - start of a new named blob '%s'", 00201 *line, name); 00202 00203 while (wpa_config_get_line(buf, sizeof(buf), f, line, &pos)) { 00204 if (os_strcmp(pos, "}") == 0) { 00205 end = 1; 00206 break; 00207 } 00208 00209 len = os_strlen(pos); 00210 nencoded = os_realloc(encoded, encoded_len + len); 00211 if (nencoded == NULL) { 00212 wpa_printf(MSG_ERROR, "Line %d: not enough memory for " 00213 "blob", *line); 00214 os_free(encoded); 00215 return NULL; 00216 } 00217 encoded = nencoded; 00218 os_memcpy(encoded + encoded_len, pos, len); 00219 encoded_len += len; 00220 } 00221 00222 if (!end) { 00223 wpa_printf(MSG_ERROR, "Line %d: blob was not terminated " 00224 "properly", *line); 00225 os_free(encoded); 00226 return NULL; 00227 } 00228 00229 blob = os_zalloc(sizeof(*blob)); 00230 if (blob == NULL) { 00231 os_free(encoded); 00232 return NULL; 00233 } 00234 blob->name = os_strdup(name); 00235 blob->data = base64_decode(encoded, encoded_len, &blob->len); 00236 os_free(encoded); 00237 00238 if (blob->name == NULL || blob->data == NULL) { 00239 wpa_config_free_blob(blob); 00240 return NULL; 00241 } 00242 00243 return blob; 00244 } 00245 00246 00247 static int wpa_config_process_blob(struct wpa_config *config, FILE *f, 00248 int *line, char *bname) 00249 { 00250 char *name_end; 00251 struct wpa_config_blob *blob; 00252 00253 name_end = os_strchr(bname, '='); 00254 if (name_end == NULL) { 00255 wpa_printf(MSG_ERROR, "Line %d: no blob name terminator", 00256 *line); 00257 return -1; 00258 } 00259 *name_end = '\0'; 00260 00261 blob = wpa_config_read_blob(f, line, bname); 00262 if (blob == NULL) { 00263 wpa_printf(MSG_ERROR, "Line %d: failed to read blob %s", 00264 *line, bname); 00265 return -1; 00266 } 00267 wpa_config_set_blob(config, blob); 00268 return 0; 00269 } 00270 #endif /* CONFIG_NO_CONFIG_BLOBS */ 00271 00272 00273 struct global_parse_data { 00274 char *name; 00275 int (*parser)(const struct global_parse_data *data, 00276 struct wpa_config *config, int line, const char *value); 00277 void *param1, *param2, *param3; 00278 }; 00279 00280 00281 static int wpa_config_parse_int(const struct global_parse_data *data, 00282 struct wpa_config *config, int line, 00283 const char *pos) 00284 { 00285 int *dst; 00286 dst = (int *) (((u8 *) config) + (long) data->param1); 00287 *dst = atoi(pos); 00288 wpa_printf(MSG_DEBUG, "%s=%d", data->name, *dst); 00289 00290 if (data->param2 && *dst < (long) data->param2) { 00291 wpa_printf(MSG_ERROR, "Line %d: too small %s (value=%d " 00292 "min_value=%ld)", line, data->name, *dst, 00293 (long) data->param2); 00294 *dst = (long) data->param2; 00295 return -1; 00296 } 00297 00298 if (data->param3 && *dst > (long) data->param3) { 00299 wpa_printf(MSG_ERROR, "Line %d: too large %s (value=%d " 00300 "max_value=%ld)", line, data->name, *dst, 00301 (long) data->param3); 00302 *dst = (long) data->param3; 00303 return -1; 00304 } 00305 00306 return 0; 00307 } 00308 00309 00310 static int wpa_config_parse_str(const struct global_parse_data *data, 00311 struct wpa_config *config, int line, 00312 const char *pos) 00313 { 00314 size_t len; 00315 char **dst, *tmp; 00316 00317 len = os_strlen(pos); 00318 if (data->param2 && len < (size_t) data->param2) { 00319 wpa_printf(MSG_ERROR, "Line %d: too short %s (len=%lu " 00320 "min_len=%ld)", line, data->name, 00321 (unsigned long) len, (long) data->param2); 00322 return -1; 00323 } 00324 00325 if (data->param3 && len > (size_t) data->param3) { 00326 wpa_printf(MSG_ERROR, "Line %d: too long %s (len=%lu " 00327 "max_len=%ld)", line, data->name, 00328 (unsigned long) len, (long) data->param3); 00329 return -1; 00330 } 00331 00332 tmp = os_strdup(pos); 00333 if (tmp == NULL) 00334 return -1; 00335 00336 dst = (char **) (((u8 *) config) + (long) data->param1); 00337 os_free(*dst); 00338 *dst = tmp; 00339 wpa_printf(MSG_DEBUG, "%s='%s'", data->name, *dst); 00340 00341 return 0; 00342 } 00343 00344 00345 static int wpa_config_process_country(const struct global_parse_data *data, 00346 struct wpa_config *config, int line, 00347 const char *pos) 00348 { 00349 if (!pos[0] || !pos[1]) { 00350 wpa_printf(MSG_DEBUG, "Invalid country set"); 00351 return -1; 00352 } 00353 config->country[0] = pos[0]; 00354 config->country[1] = pos[1]; 00355 wpa_printf(MSG_DEBUG, "country='%c%c'", 00356 config->country[0], config->country[1]); 00357 return 0; 00358 } 00359 00360 00361 static int wpa_config_process_load_dynamic_eap( 00362 const struct global_parse_data *data, struct wpa_config *config, 00363 int line, const char *so) 00364 { 00365 int ret; 00366 wpa_printf(MSG_DEBUG, "load_dynamic_eap=%s", so); 00367 ret = eap_peer_method_load(so); 00368 if (ret == -2) { 00369 wpa_printf(MSG_DEBUG, "This EAP type was already loaded - not " 00370 "reloading."); 00371 } else if (ret) { 00372 wpa_printf(MSG_ERROR, "Line %d: Failed to load dynamic EAP " 00373 "method '%s'.", line, so); 00374 return -1; 00375 } 00376 00377 return 0; 00378 } 00379 00380 00381 #ifdef CONFIG_WPS 00382 00383 static int wpa_config_process_uuid(const struct global_parse_data *data, 00384 struct wpa_config *config, int line, 00385 const char *pos) 00386 { 00387 char buf[40]; 00388 if (uuid_str2bin(pos, config->uuid)) { 00389 wpa_printf(MSG_ERROR, "Line %d: invalid UUID", line); 00390 return -1; 00391 } 00392 uuid_bin2str(config->uuid, buf, sizeof(buf)); 00393 wpa_printf(MSG_DEBUG, "uuid=%s", buf); 00394 return 0; 00395 } 00396 00397 00398 static int wpa_config_process_os_version(const struct global_parse_data *data, 00399 struct wpa_config *config, int line, 00400 const char *pos) 00401 { 00402 if (hexstr2bin(pos, config->os_version, 4)) { 00403 wpa_printf(MSG_ERROR, "Line %d: invalid os_version", line); 00404 return -1; 00405 } 00406 wpa_printf(MSG_DEBUG, "os_version=%08x", 00407 WPA_GET_BE32(config->os_version)); 00408 return 0; 00409 } 00410 00411 #endif /* CONFIG_WPS */ 00412 00413 00414 #ifdef OFFSET 00415 #undef OFFSET 00416 #endif /* OFFSET */ 00417 /* OFFSET: Get offset of a variable within the wpa_config structure */ 00418 #define OFFSET(v) ((void *) &((struct wpa_config *) 0)->v) 00419 00420 #define FUNC(f) #f, wpa_config_process_ ## f, OFFSET(f), NULL, NULL 00421 #define FUNC_NO_VAR(f) #f, wpa_config_process_ ## f, NULL, NULL, NULL 00422 #define _INT(f) #f, wpa_config_parse_int, OFFSET(f) 00423 #define INT(f) _INT(f), NULL, NULL 00424 #define INT_RANGE(f, min, max) _INT(f), (void *) min, (void *) max 00425 #define _STR(f) #f, wpa_config_parse_str, OFFSET(f) 00426 #define STR(f) _STR(f), NULL, NULL 00427 #define STR_RANGE(f, min, max) _STR(f), (void *) min, (void *) max 00428 00429 static const struct global_parse_data global_fields[] = { 00430 #ifdef CONFIG_CTRL_IFACE 00431 { STR(ctrl_interface) }, 00432 { STR(ctrl_interface_group) } /* deprecated */, 00433 #endif /* CONFIG_CTRL_IFACE */ 00434 { INT_RANGE(eapol_version, 1, 2) }, 00435 { INT(ap_scan) }, 00436 { INT(fast_reauth) }, 00437 { STR(opensc_engine_path) }, 00438 { STR(pkcs11_engine_path) }, 00439 { STR(pkcs11_module_path) }, 00440 { STR(driver_param) }, 00441 { INT(dot11RSNAConfigPMKLifetime) }, 00442 { INT(dot11RSNAConfigPMKReauthThreshold) }, 00443 { INT(dot11RSNAConfigSATimeout) }, 00444 #ifndef CONFIG_NO_CONFIG_WRITE 00445 { INT(update_config) }, 00446 #endif /* CONFIG_NO_CONFIG_WRITE */ 00447 { FUNC_NO_VAR(load_dynamic_eap) }, 00448 #ifdef CONFIG_WPS 00449 { FUNC(uuid) }, 00450 { STR_RANGE(device_name, 0, 32) }, 00451 { STR_RANGE(manufacturer, 0, 64) }, 00452 { STR_RANGE(model_name, 0, 32) }, 00453 { STR_RANGE(model_number, 0, 32) }, 00454 { STR_RANGE(serial_number, 0, 32) }, 00455 { STR(device_type) }, 00456 { FUNC(os_version) }, 00457 { STR(config_methods) }, 00458 { INT_RANGE(wps_cred_processing, 0, 2) }, 00459 #endif /* CONFIG_WPS */ 00460 { FUNC(country) }, 00461 { INT(bss_max_count) }, 00462 { INT_RANGE(filter_ssids, 0, 1) } 00463 }; 00464 00465 #undef FUNC 00466 #undef _INT 00467 #undef INT 00468 #undef INT_RANGE 00469 #undef _STR 00470 #undef STR 00471 #undef STR_RANGE 00472 #define NUM_GLOBAL_FIELDS (sizeof(global_fields) / sizeof(global_fields[0])) 00473 00474 00475 static int wpa_config_process_global(struct wpa_config *config, char *pos, 00476 int line) 00477 { 00478 size_t i; 00479 int ret = 0; 00480 00481 for (i = 0; i < NUM_GLOBAL_FIELDS; i++) { 00482 const struct global_parse_data *field = &global_fields[i]; 00483 size_t flen = os_strlen(field->name); 00484 if (os_strncmp(pos, field->name, flen) != 0 || 00485 pos[flen] != '=') 00486 continue; 00487 00488 if (field->parser(field, config, line, pos + flen + 1)) { 00489 wpa_printf(MSG_ERROR, "Line %d: failed to " 00490 "parse '%s'.", line, pos); 00491 ret = -1; 00492 } 00493 break; 00494 } 00495 if (i == NUM_GLOBAL_FIELDS) { 00496 wpa_printf(MSG_ERROR, "Line %d: unknown global field '%s'.", 00497 line, pos); 00498 ret = -1; 00499 } 00500 00501 return ret; 00502 } 00503 00504 00505 struct wpa_config * wpa_config_read(const char *name) 00506 { 00507 FILE *f; 00508 char buf[256], *pos; 00509 int errors = 0, line = 0; 00510 struct wpa_ssid *ssid, *tail = NULL, *head = NULL; 00511 struct wpa_config *config; 00512 int id = 0; 00513 00514 config = wpa_config_alloc_empty(NULL, NULL); 00515 if (config == NULL) 00516 return NULL; 00517 wpa_printf(MSG_DEBUG, "Reading configuration file '%s'", name); 00518 f = fopen(name, "r"); 00519 if (f == NULL) { 00520 os_free(config); 00521 return NULL; 00522 } 00523 00524 while (wpa_config_get_line(buf, sizeof(buf), f, &line, &pos)) { 00525 if (os_strcmp(pos, "network={") == 0) { 00526 ssid = wpa_config_read_network(f, &line, id++); 00527 if (ssid == NULL) { 00528 wpa_printf(MSG_ERROR, "Line %d: failed to " 00529 "parse network block.", line); 00530 errors++; 00531 continue; 00532 } 00533 if (head == NULL) { 00534 head = tail = ssid; 00535 } else { 00536 tail->next = ssid; 00537 tail = ssid; 00538 } 00539 if (wpa_config_add_prio_network(config, ssid)) { 00540 wpa_printf(MSG_ERROR, "Line %d: failed to add " 00541 "network block to priority list.", 00542 line); 00543 errors++; 00544 continue; 00545 } 00546 #ifndef CONFIG_NO_CONFIG_BLOBS 00547 } else if (os_strncmp(pos, "blob-base64-", 12) == 0) { 00548 if (wpa_config_process_blob(config, f, &line, pos + 12) 00549 < 0) { 00550 errors++; 00551 continue; 00552 } 00553 #endif /* CONFIG_NO_CONFIG_BLOBS */ 00554 } else if (wpa_config_process_global(config, pos, line) < 0) { 00555 wpa_printf(MSG_ERROR, "Line %d: Invalid configuration " 00556 "line '%s'.", line, pos); 00557 errors++; 00558 continue; 00559 } 00560 } 00561 00562 fclose(f); 00563 00564 config->ssid = head; 00565 wpa_config_debug_dump_networks(config); 00566 00567 if (errors) { 00568 wpa_config_free(config); 00569 config = NULL; 00570 head = NULL; 00571 } 00572 00573 return config; 00574 } 00575 00576 00577 #ifndef CONFIG_NO_CONFIG_WRITE 00578 00579 static void write_str(FILE *f, const char *field, struct wpa_ssid *ssid) 00580 { 00581 char *value = wpa_config_get(ssid, field); 00582 if (value == NULL) 00583 return; 00584 fprintf(f, "\t%s=%s\n", field, value); 00585 os_free(value); 00586 } 00587 00588 00589 static void write_int(FILE *f, const char *field, int value, int def) 00590 { 00591 if (value == def) 00592 return; 00593 fprintf(f, "\t%s=%d\n", field, value); 00594 } 00595 00596 00597 static void write_bssid(FILE *f, struct wpa_ssid *ssid) 00598 { 00599 char *value = wpa_config_get(ssid, "bssid"); 00600 if (value == NULL) 00601 return; 00602 fprintf(f, "\tbssid=%s\n", value); 00603 os_free(value); 00604 } 00605 00606 00607 static void write_psk(FILE *f, struct wpa_ssid *ssid) 00608 { 00609 char *value = wpa_config_get(ssid, "psk"); 00610 if (value == NULL) 00611 return; 00612 fprintf(f, "\tpsk=%s\n", value); 00613 os_free(value); 00614 } 00615 00616 00617 static void write_proto(FILE *f, struct wpa_ssid *ssid) 00618 { 00619 char *value; 00620 00621 if (ssid->proto == DEFAULT_PROTO) 00622 return; 00623 00624 value = wpa_config_get(ssid, "proto"); 00625 if (value == NULL) 00626 return; 00627 if (value[0]) 00628 fprintf(f, "\tproto=%s\n", value); 00629 os_free(value); 00630 } 00631 00632 00633 static void write_key_mgmt(FILE *f, struct wpa_ssid *ssid) 00634 { 00635 char *value; 00636 00637 if (ssid->key_mgmt == DEFAULT_KEY_MGMT) 00638 return; 00639 00640 value = wpa_config_get(ssid, "key_mgmt"); 00641 if (value == NULL) 00642 return; 00643 if (value[0]) 00644 fprintf(f, "\tkey_mgmt=%s\n", value); 00645 os_free(value); 00646 } 00647 00648 00649 static void write_pairwise(FILE *f, struct wpa_ssid *ssid) 00650 { 00651 char *value; 00652 00653 if (ssid->pairwise_cipher == DEFAULT_PAIRWISE) 00654 return; 00655 00656 value = wpa_config_get(ssid, "pairwise"); 00657 if (value == NULL) 00658 return; 00659 if (value[0]) 00660 fprintf(f, "\tpairwise=%s\n", value); 00661 os_free(value); 00662 } 00663 00664 00665 static void write_group(FILE *f, struct wpa_ssid *ssid) 00666 { 00667 char *value; 00668 00669 if (ssid->group_cipher == DEFAULT_GROUP) 00670 return; 00671 00672 value = wpa_config_get(ssid, "group"); 00673 if (value == NULL) 00674 return; 00675 if (value[0]) 00676 fprintf(f, "\tgroup=%s\n", value); 00677 os_free(value); 00678 } 00679 00680 00681 static void write_auth_alg(FILE *f, struct wpa_ssid *ssid) 00682 { 00683 char *value; 00684 00685 if (ssid->auth_alg == 0) 00686 return; 00687 00688 value = wpa_config_get(ssid, "auth_alg"); 00689 if (value == NULL) 00690 return; 00691 if (value[0]) 00692 fprintf(f, "\tauth_alg=%s\n", value); 00693 os_free(value); 00694 } 00695 00696 00697 #ifdef IEEE8021X_EAPOL 00698 static void write_eap(FILE *f, struct wpa_ssid *ssid) 00699 { 00700 char *value; 00701 00702 value = wpa_config_get(ssid, "eap"); 00703 if (value == NULL) 00704 return; 00705 00706 if (value[0]) 00707 fprintf(f, "\teap=%s\n", value); 00708 os_free(value); 00709 } 00710 #endif /* IEEE8021X_EAPOL */ 00711 00712 00713 static void write_wep_key(FILE *f, int idx, struct wpa_ssid *ssid) 00714 { 00715 char field[20], *value; 00716 int res; 00717 00718 res = os_snprintf(field, sizeof(field), "wep_key%d", idx); 00719 if (res < 0 || (size_t) res >= sizeof(field)) 00720 return; 00721 value = wpa_config_get(ssid, field); 00722 if (value) { 00723 fprintf(f, "\t%s=%s\n", field, value); 00724 os_free(value); 00725 } 00726 } 00727 00728 00729 static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid) 00730 { 00731 int i; 00732 00733 #define STR(t) write_str(f, #t, ssid) 00734 #define INT(t) write_int(f, #t, ssid->t, 0) 00735 #define INTe(t) write_int(f, #t, ssid->eap.t, 0) 00736 #define INT_DEF(t, def) write_int(f, #t, ssid->t, def) 00737 #define INT_DEFe(t, def) write_int(f, #t, ssid->eap.t, def) 00738 00739 STR(ssid); 00740 INT(scan_ssid); 00741 write_bssid(f, ssid); 00742 write_psk(f, ssid); 00743 write_proto(f, ssid); 00744 write_key_mgmt(f, ssid); 00745 write_pairwise(f, ssid); 00746 write_group(f, ssid); 00747 write_auth_alg(f, ssid); 00748 #ifdef IEEE8021X_EAPOL 00749 write_eap(f, ssid); 00750 STR(identity); 00751 STR(anonymous_identity); 00752 STR(password); 00753 STR(ca_cert); 00754 STR(ca_path); 00755 STR(client_cert); 00756 STR(private_key); 00757 STR(private_key_passwd); 00758 STR(dh_file); 00759 STR(subject_match); 00760 STR(altsubject_match); 00761 STR(ca_cert2); 00762 STR(ca_path2); 00763 STR(client_cert2); 00764 STR(private_key2); 00765 STR(private_key2_passwd); 00766 STR(dh_file2); 00767 STR(subject_match2); 00768 STR(altsubject_match2); 00769 STR(phase1); 00770 STR(phase2); 00771 STR(pcsc); 00772 STR(pin); 00773 STR(engine_id); 00774 STR(key_id); 00775 STR(cert_id); 00776 STR(ca_cert_id); 00777 STR(key2_id); 00778 STR(pin2); 00779 STR(engine2_id); 00780 STR(cert2_id); 00781 STR(ca_cert2_id); 00782 INTe(engine); 00783 INTe(engine2); 00784 INT_DEF(eapol_flags, DEFAULT_EAPOL_FLAGS); 00785 #endif /* IEEE8021X_EAPOL */ 00786 for (i = 0; i < 4; i++) 00787 write_wep_key(f, i, ssid); 00788 INT(wep_tx_keyidx); 00789 INT(priority); 00790 #ifdef IEEE8021X_EAPOL 00791 INT_DEF(eap_workaround, DEFAULT_EAP_WORKAROUND); 00792 STR(pac_file); 00793 INT_DEFe(fragment_size, DEFAULT_FRAGMENT_SIZE); 00794 #endif /* IEEE8021X_EAPOL */ 00795 INT(mode); 00796 INT(proactive_key_caching); 00797 INT(disabled); 00798 INT(peerkey); 00799 #ifdef CONFIG_IEEE80211W 00800 INT(ieee80211w); 00801 #endif /* CONFIG_IEEE80211W */ 00802 STR(id_str); 00803 00804 #undef STR 00805 #undef INT 00806 #undef INT_DEF 00807 } 00808 00809 00810 #ifndef CONFIG_NO_CONFIG_BLOBS 00811 static int wpa_config_write_blob(FILE *f, struct wpa_config_blob *blob) 00812 { 00813 unsigned char *encoded; 00814 00815 encoded = base64_encode(blob->data, blob->len, NULL); 00816 if (encoded == NULL) 00817 return -1; 00818 00819 fprintf(f, "\nblob-base64-%s={\n%s}\n", blob->name, encoded); 00820 os_free(encoded); 00821 return 0; 00822 } 00823 #endif /* CONFIG_NO_CONFIG_BLOBS */ 00824 00825 00826 static void wpa_config_write_global(FILE *f, struct wpa_config *config) 00827 { 00828 #ifdef CONFIG_CTRL_IFACE 00829 if (config->ctrl_interface) 00830 fprintf(f, "ctrl_interface=%s\n", config->ctrl_interface); 00831 if (config->ctrl_interface_group) 00832 fprintf(f, "ctrl_interface_group=%s\n", 00833 config->ctrl_interface_group); 00834 #endif /* CONFIG_CTRL_IFACE */ 00835 if (config->eapol_version != DEFAULT_EAPOL_VERSION) 00836 fprintf(f, "eapol_version=%d\n", config->eapol_version); 00837 if (config->ap_scan != DEFAULT_AP_SCAN) 00838 fprintf(f, "ap_scan=%d\n", config->ap_scan); 00839 if (config->fast_reauth != DEFAULT_FAST_REAUTH) 00840 fprintf(f, "fast_reauth=%d\n", config->fast_reauth); 00841 if (config->opensc_engine_path) 00842 fprintf(f, "opensc_engine_path=%s\n", 00843 config->opensc_engine_path); 00844 if (config->pkcs11_engine_path) 00845 fprintf(f, "pkcs11_engine_path=%s\n", 00846 config->pkcs11_engine_path); 00847 if (config->pkcs11_module_path) 00848 fprintf(f, "pkcs11_module_path=%s\n", 00849 config->pkcs11_module_path); 00850 if (config->driver_param) 00851 fprintf(f, "driver_param=%s\n", config->driver_param); 00852 if (config->dot11RSNAConfigPMKLifetime) 00853 fprintf(f, "dot11RSNAConfigPMKLifetime=%d\n", 00854 config->dot11RSNAConfigPMKLifetime); 00855 if (config->dot11RSNAConfigPMKReauthThreshold) 00856 fprintf(f, "dot11RSNAConfigPMKReauthThreshold=%d\n", 00857 config->dot11RSNAConfigPMKReauthThreshold); 00858 if (config->dot11RSNAConfigSATimeout) 00859 fprintf(f, "dot11RSNAConfigSATimeout=%d\n", 00860 config->dot11RSNAConfigSATimeout); 00861 if (config->update_config) 00862 fprintf(f, "update_config=%d\n", config->update_config); 00863 #ifdef CONFIG_WPS 00864 if (!is_nil_uuid(config->uuid)) { 00865 char buf[40]; 00866 uuid_bin2str(config->uuid, buf, sizeof(buf)); 00867 fprintf(f, "uuid=%s\n", buf); 00868 } 00869 if (config->device_name) 00870 fprintf(f, "device_name=%s\n", config->device_name); 00871 if (config->manufacturer) 00872 fprintf(f, "manufacturer=%s\n", config->manufacturer); 00873 if (config->model_name) 00874 fprintf(f, "model_name=%s\n", config->model_name); 00875 if (config->model_number) 00876 fprintf(f, "model_number=%s\n", config->model_number); 00877 if (config->serial_number) 00878 fprintf(f, "serial_number=%s\n", config->serial_number); 00879 if (config->device_type) 00880 fprintf(f, "device_type=%s\n", config->device_type); 00881 if (WPA_GET_BE32(config->os_version)) 00882 fprintf(f, "os_version=%08x\n", 00883 WPA_GET_BE32(config->os_version)); 00884 if (config->config_methods) 00885 fprintf(f, "config_methods=%s\n", config->config_methods); 00886 if (config->wps_cred_processing) 00887 fprintf(f, "wps_cred_processing=%d\n", 00888 config->wps_cred_processing); 00889 #endif /* CONFIG_WPS */ 00890 if (config->country[0] && config->country[1]) { 00891 fprintf(f, "country=%c%c\n", 00892 config->country[0], config->country[1]); 00893 } 00894 if (config->bss_max_count != DEFAULT_BSS_MAX_COUNT) 00895 fprintf(f, "bss_max_count=%u\n", config->bss_max_count); 00896 if (config->filter_ssids) 00897 fprintf(f, "filter_ssids=%d\n", config->filter_ssids); 00898 } 00899 00900 #endif /* CONFIG_NO_CONFIG_WRITE */ 00901 00902 00903 int wpa_config_write(const char *name, struct wpa_config *config) 00904 { 00905 #ifndef CONFIG_NO_CONFIG_WRITE 00906 FILE *f; 00907 struct wpa_ssid *ssid; 00908 #ifndef CONFIG_NO_CONFIG_BLOBS 00909 struct wpa_config_blob *blob; 00910 #endif /* CONFIG_NO_CONFIG_BLOBS */ 00911 int ret = 0; 00912 00913 wpa_printf(MSG_DEBUG, "Writing configuration file '%s'", name); 00914 00915 f = fopen(name, "w"); 00916 if (f == NULL) { 00917 wpa_printf(MSG_DEBUG, "Failed to open '%s' for writing", name); 00918 return -1; 00919 } 00920 00921 wpa_config_write_global(f, config); 00922 00923 for (ssid = config->ssid; ssid; ssid = ssid->next) { 00924 if (ssid->key_mgmt == WPA_KEY_MGMT_WPS) 00925 continue; /* do not save temporary WPS networks */ 00926 fprintf(f, "\nnetwork={\n"); 00927 wpa_config_write_network(f, ssid); 00928 fprintf(f, "}\n"); 00929 } 00930 00931 #ifndef CONFIG_NO_CONFIG_BLOBS 00932 for (blob = config->blobs; blob; blob = blob->next) { 00933 ret = wpa_config_write_blob(f, blob); 00934 if (ret) 00935 break; 00936 } 00937 #endif /* CONFIG_NO_CONFIG_BLOBS */ 00938 00939 fclose(f); 00940 00941 wpa_printf(MSG_DEBUG, "Configuration file '%s' written %ssuccessfully", 00942 name, ret ? "un" : ""); 00943 return ret; 00944 #else /* CONFIG_NO_CONFIG_WRITE */ 00945 return -1; 00946 #endif /* CONFIG_NO_CONFIG_WRITE */ 00947 }