2 * WPA Supplicant / Configuration backend: text file
3 * Copyright (c) 2003-2008, Jouni Malinen <j@w1.fi>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
9 * Alternatively, this software may be distributed under the terms of BSD
12 * See README and COPYING for more details.
14 * This file implements a configuration backend for text files. All the
15 * configuration information is stored in a text file that uses a format
16 * described in the sample configuration file, wpa_supplicant.conf.
28 * wpa_config_get_line - Read the next configuration file line
29 * @s: Buffer for the line
30 * @size: The buffer length
31 * @stream: File stream to read from
32 * @line: Pointer to a variable storing the file line number
33 * @_pos: Buffer for the pointer to the beginning of data on the text line or
34 * %NULL if not needed (returned value used instead)
35 * Returns: Pointer to the beginning of data on the text line or %NULL if no
36 * more text lines are available.
38 * This function reads the next non-empty line from the configuration file and
39 * removes comments. The returned string is guaranteed to be null-terminated.
41 static char * wpa_config_get_line(char *s
, int size
, FILE *stream
, int *line
,
44 char *pos
, *end
, *sstart
;
46 while (fgets(s
, size
, stream
)) {
51 /* Skip white space from the beginning of line. */
52 while (*pos
== ' ' || *pos
== '\t' || *pos
== '\r')
55 /* Skip comment lines and empty lines */
56 if (*pos
== '#' || *pos
== '\n' || *pos
== '\0')
60 * Remove # comments unless they are within a double quoted
63 sstart
= os_strchr(pos
, '"');
65 sstart
= os_strrchr(sstart
+ 1, '"');
68 end
= os_strchr(sstart
, '#');
72 end
= pos
+ os_strlen(pos
) - 1;
74 /* Remove trailing white space. */
76 (*end
== '\n' || *end
== ' ' || *end
== '\t' ||
94 static int wpa_config_validate_network(struct wpa_ssid
*ssid
, int line
)
98 if (ssid
->passphrase
) {
100 wpa_printf(MSG_ERROR
, "Line %d: both PSK and "
101 "passphrase configured.", line
);
104 wpa_config_update_psk(ssid
);
107 if ((ssid
->key_mgmt
& (WPA_KEY_MGMT_PSK
| WPA_KEY_MGMT_FT_PSK
|
108 WPA_KEY_MGMT_PSK_SHA256
)) &&
110 wpa_printf(MSG_ERROR
, "Line %d: WPA-PSK accepted for key "
111 "management, but no PSK configured.", line
);
115 if ((ssid
->group_cipher
& WPA_CIPHER_CCMP
) &&
116 !(ssid
->pairwise_cipher
& WPA_CIPHER_CCMP
) &&
117 !(ssid
->pairwise_cipher
& WPA_CIPHER_NONE
)) {
118 /* Group cipher cannot be stronger than the pairwise cipher. */
119 wpa_printf(MSG_DEBUG
, "Line %d: removed CCMP from group cipher"
120 " list since it was not allowed for pairwise "
122 ssid
->group_cipher
&= ~WPA_CIPHER_CCMP
;
129 static struct wpa_ssid
* wpa_config_read_network(FILE *f
, int *line
, int id
)
131 struct wpa_ssid
*ssid
;
132 int errors
= 0, end
= 0;
133 char buf
[256], *pos
, *pos2
;
135 wpa_printf(MSG_MSGDUMP
, "Line: %d - start of a new network block",
137 ssid
= os_zalloc(sizeof(*ssid
));
142 wpa_config_set_network_defaults(ssid
);
144 while (wpa_config_get_line(buf
, sizeof(buf
), f
, line
, &pos
)) {
145 if (os_strcmp(pos
, "}") == 0) {
150 pos2
= os_strchr(pos
, '=');
152 wpa_printf(MSG_ERROR
, "Line %d: Invalid SSID line "
153 "'%s'.", *line
, pos
);
160 if (os_strchr(pos2
+ 1, '"') == NULL
) {
161 wpa_printf(MSG_ERROR
, "Line %d: invalid "
162 "quotation '%s'.", *line
, pos2
);
168 if (wpa_config_set(ssid
, pos
, pos2
, *line
) < 0)
173 wpa_printf(MSG_ERROR
, "Line %d: network block was not "
174 "terminated properly.", *line
);
178 errors
+= wpa_config_validate_network(ssid
, *line
);
181 wpa_config_free_ssid(ssid
);
189 #ifndef CONFIG_NO_CONFIG_BLOBS
190 static struct wpa_config_blob
* wpa_config_read_blob(FILE *f
, int *line
,
193 struct wpa_config_blob
*blob
;
195 unsigned char *encoded
= NULL
, *nencoded
;
197 size_t encoded_len
= 0, len
;
199 wpa_printf(MSG_MSGDUMP
, "Line: %d - start of a new named blob '%s'",
202 while (wpa_config_get_line(buf
, sizeof(buf
), f
, line
, &pos
)) {
203 if (os_strcmp(pos
, "}") == 0) {
208 len
= os_strlen(pos
);
209 nencoded
= os_realloc(encoded
, encoded_len
+ len
);
210 if (nencoded
== NULL
) {
211 wpa_printf(MSG_ERROR
, "Line %d: not enough memory for "
217 os_memcpy(encoded
+ encoded_len
, pos
, len
);
222 wpa_printf(MSG_ERROR
, "Line %d: blob was not terminated "
228 blob
= os_zalloc(sizeof(*blob
));
233 blob
->name
= os_strdup(name
);
234 blob
->data
= base64_decode(encoded
, encoded_len
, &blob
->len
);
237 if (blob
->name
== NULL
|| blob
->data
== NULL
) {
238 wpa_config_free_blob(blob
);
246 static int wpa_config_process_blob(struct wpa_config
*config
, FILE *f
,
247 int *line
, char *bname
)
250 struct wpa_config_blob
*blob
;
252 name_end
= os_strchr(bname
, '=');
253 if (name_end
== NULL
) {
254 wpa_printf(MSG_ERROR
, "Line %d: no blob name terminator",
260 blob
= wpa_config_read_blob(f
, line
, bname
);
262 wpa_printf(MSG_ERROR
, "Line %d: failed to read blob %s",
266 wpa_config_set_blob(config
, blob
);
269 #endif /* CONFIG_NO_CONFIG_BLOBS */
272 struct wpa_config
* wpa_config_read(const char *name
)
276 int errors
= 0, line
= 0;
277 struct wpa_ssid
*ssid
, *tail
= NULL
, *head
= NULL
;
278 struct wpa_config
*config
;
281 config
= wpa_config_alloc_empty(NULL
, NULL
);
284 wpa_printf(MSG_DEBUG
, "Reading configuration file '%s'", name
);
285 f
= fopen(name
, "r");
291 while (wpa_config_get_line(buf
, sizeof(buf
), f
, &line
, &pos
)) {
292 if (os_strcmp(pos
, "network={") == 0) {
293 ssid
= wpa_config_read_network(f
, &line
, id
++);
295 wpa_printf(MSG_ERROR
, "Line %d: failed to "
296 "parse network block.", line
);
306 if (wpa_config_add_prio_network(config
, ssid
)) {
307 wpa_printf(MSG_ERROR
, "Line %d: failed to add "
308 "network block to priority list.",
313 #ifndef CONFIG_NO_CONFIG_BLOBS
314 } else if (os_strncmp(pos
, "blob-base64-", 12) == 0) {
315 if (wpa_config_process_blob(config
, f
, &line
, pos
+ 12)
320 #endif /* CONFIG_NO_CONFIG_BLOBS */
321 } else if (wpa_config_process_global(config
, pos
, line
) < 0) {
322 wpa_printf(MSG_ERROR
, "Line %d: Invalid configuration "
323 "line '%s'.", line
, pos
);
332 wpa_config_debug_dump_networks(config
);
335 wpa_config_free(config
);
344 #ifndef CONFIG_NO_CONFIG_WRITE
346 static void write_str(FILE *f
, const char *field
, struct wpa_ssid
*ssid
)
348 char *value
= wpa_config_get(ssid
, field
);
351 fprintf(f
, "\t%s=%s\n", field
, value
);
356 static void write_int(FILE *f
, const char *field
, int value
, int def
)
360 fprintf(f
, "\t%s=%d\n", field
, value
);
364 static void write_bssid(FILE *f
, struct wpa_ssid
*ssid
)
366 char *value
= wpa_config_get(ssid
, "bssid");
369 fprintf(f
, "\tbssid=%s\n", value
);
374 static void write_psk(FILE *f
, struct wpa_ssid
*ssid
)
376 char *value
= wpa_config_get(ssid
, "psk");
379 fprintf(f
, "\tpsk=%s\n", value
);
384 static void write_proto(FILE *f
, struct wpa_ssid
*ssid
)
388 if (ssid
->proto
== DEFAULT_PROTO
)
391 value
= wpa_config_get(ssid
, "proto");
395 fprintf(f
, "\tproto=%s\n", value
);
400 static void write_key_mgmt(FILE *f
, struct wpa_ssid
*ssid
)
404 if (ssid
->key_mgmt
== DEFAULT_KEY_MGMT
)
407 value
= wpa_config_get(ssid
, "key_mgmt");
411 fprintf(f
, "\tkey_mgmt=%s\n", value
);
416 static void write_pairwise(FILE *f
, struct wpa_ssid
*ssid
)
420 if (ssid
->pairwise_cipher
== DEFAULT_PAIRWISE
)
423 value
= wpa_config_get(ssid
, "pairwise");
427 fprintf(f
, "\tpairwise=%s\n", value
);
432 static void write_group(FILE *f
, struct wpa_ssid
*ssid
)
436 if (ssid
->group_cipher
== DEFAULT_GROUP
)
439 value
= wpa_config_get(ssid
, "group");
443 fprintf(f
, "\tgroup=%s\n", value
);
448 static void write_auth_alg(FILE *f
, struct wpa_ssid
*ssid
)
452 if (ssid
->auth_alg
== 0)
455 value
= wpa_config_get(ssid
, "auth_alg");
459 fprintf(f
, "\tauth_alg=%s\n", value
);
464 #ifdef IEEE8021X_EAPOL
465 static void write_eap(FILE *f
, struct wpa_ssid
*ssid
)
469 value
= wpa_config_get(ssid
, "eap");
474 fprintf(f
, "\teap=%s\n", value
);
477 #endif /* IEEE8021X_EAPOL */
480 static void write_wep_key(FILE *f
, int idx
, struct wpa_ssid
*ssid
)
482 char field
[20], *value
;
485 res
= os_snprintf(field
, sizeof(field
), "wep_key%d", idx
);
486 if (res
< 0 || (size_t) res
>= sizeof(field
))
488 value
= wpa_config_get(ssid
, field
);
490 fprintf(f
, "\t%s=%s\n", field
, value
);
496 static void wpa_config_write_network(FILE *f
, struct wpa_ssid
*ssid
)
500 #define STR(t) write_str(f, #t, ssid)
501 #define INT(t) write_int(f, #t, ssid->t, 0)
502 #define INTe(t) write_int(f, #t, ssid->eap.t, 0)
503 #define INT_DEF(t, def) write_int(f, #t, ssid->t, def)
504 #define INT_DEFe(t, def) write_int(f, #t, ssid->eap.t, def)
508 write_bssid(f
, ssid
);
510 write_proto(f
, ssid
);
511 write_key_mgmt(f
, ssid
);
512 write_pairwise(f
, ssid
);
513 write_group(f
, ssid
);
514 write_auth_alg(f
, ssid
);
515 #ifdef IEEE8021X_EAPOL
518 STR(anonymous_identity
);
524 STR(private_key_passwd
);
527 STR(altsubject_match
);
532 STR(private_key2_passwd
);
535 STR(altsubject_match2
);
551 INT_DEF(eapol_flags
, DEFAULT_EAPOL_FLAGS
);
552 #endif /* IEEE8021X_EAPOL */
553 for (i
= 0; i
< 4; i
++)
554 write_wep_key(f
, i
, ssid
);
557 #ifdef IEEE8021X_EAPOL
558 INT_DEF(eap_workaround
, DEFAULT_EAP_WORKAROUND
);
560 INT_DEFe(fragment_size
, DEFAULT_FRAGMENT_SIZE
);
561 #endif /* IEEE8021X_EAPOL */
563 INT(proactive_key_caching
);
566 #ifdef CONFIG_IEEE80211W
568 #endif /* CONFIG_IEEE80211W */
577 #ifndef CONFIG_NO_CONFIG_BLOBS
578 static int wpa_config_write_blob(FILE *f
, struct wpa_config_blob
*blob
)
580 unsigned char *encoded
;
582 encoded
= base64_encode(blob
->data
, blob
->len
, NULL
);
586 fprintf(f
, "\nblob-base64-%s={\n%s}\n", blob
->name
, encoded
);
590 #endif /* CONFIG_NO_CONFIG_BLOBS */
593 static void wpa_config_write_global(FILE *f
, struct wpa_config
*config
)
595 #ifdef CONFIG_CTRL_IFACE
596 if (config
->ctrl_interface
)
597 fprintf(f
, "ctrl_interface=%s\n", config
->ctrl_interface
);
598 if (config
->ctrl_interface_group
)
599 fprintf(f
, "ctrl_interface_group=%s\n",
600 config
->ctrl_interface_group
);
601 #endif /* CONFIG_CTRL_IFACE */
602 if (config
->eapol_version
!= DEFAULT_EAPOL_VERSION
)
603 fprintf(f
, "eapol_version=%d\n", config
->eapol_version
);
604 if (config
->ap_scan
!= DEFAULT_AP_SCAN
)
605 fprintf(f
, "ap_scan=%d\n", config
->ap_scan
);
606 if (config
->fast_reauth
!= DEFAULT_FAST_REAUTH
)
607 fprintf(f
, "fast_reauth=%d\n", config
->fast_reauth
);
608 if (config
->opensc_engine_path
)
609 fprintf(f
, "opensc_engine_path=%s\n",
610 config
->opensc_engine_path
);
611 if (config
->pkcs11_engine_path
)
612 fprintf(f
, "pkcs11_engine_path=%s\n",
613 config
->pkcs11_engine_path
);
614 if (config
->pkcs11_module_path
)
615 fprintf(f
, "pkcs11_module_path=%s\n",
616 config
->pkcs11_module_path
);
617 if (config
->driver_param
)
618 fprintf(f
, "driver_param=%s\n", config
->driver_param
);
619 if (config
->dot11RSNAConfigPMKLifetime
)
620 fprintf(f
, "dot11RSNAConfigPMKLifetime=%d\n",
621 config
->dot11RSNAConfigPMKLifetime
);
622 if (config
->dot11RSNAConfigPMKReauthThreshold
)
623 fprintf(f
, "dot11RSNAConfigPMKReauthThreshold=%d\n",
624 config
->dot11RSNAConfigPMKReauthThreshold
);
625 if (config
->dot11RSNAConfigSATimeout
)
626 fprintf(f
, "dot11RSNAConfigSATimeout=%d\n",
627 config
->dot11RSNAConfigSATimeout
);
628 if (config
->update_config
)
629 fprintf(f
, "update_config=%d\n", config
->update_config
);
631 if (!is_nil_uuid(config
->uuid
)) {
633 uuid_bin2str(config
->uuid
, buf
, sizeof(buf
));
634 fprintf(f
, "uuid=%s\n", buf
);
636 if (config
->device_name
)
637 fprintf(f
, "device_name=%s\n", config
->device_name
);
638 if (config
->manufacturer
)
639 fprintf(f
, "manufacturer=%s\n", config
->manufacturer
);
640 if (config
->model_name
)
641 fprintf(f
, "model_name=%s\n", config
->model_name
);
642 if (config
->model_number
)
643 fprintf(f
, "model_number=%s\n", config
->model_number
);
644 if (config
->serial_number
)
645 fprintf(f
, "serial_number=%s\n", config
->serial_number
);
646 if (config
->device_type
)
647 fprintf(f
, "device_type=%s\n", config
->device_type
);
648 if (WPA_GET_BE32(config
->os_version
))
649 fprintf(f
, "os_version=%08x\n",
650 WPA_GET_BE32(config
->os_version
));
651 if (config
->config_methods
)
652 fprintf(f
, "config_methods=%s\n", config
->config_methods
);
653 if (config
->wps_cred_processing
)
654 fprintf(f
, "wps_cred_processing=%d\n",
655 config
->wps_cred_processing
);
656 #endif /* CONFIG_WPS */
658 if (config
->p2p_listen_reg_class
)
659 fprintf(f
, "p2p_listen_reg_class=%u\n",
660 config
->p2p_listen_reg_class
);
661 if (config
->p2p_listen_channel
)
662 fprintf(f
, "p2p_listen_channel=%u\n",
663 config
->p2p_listen_channel
);
664 if (config
->p2p_oper_reg_class
)
665 fprintf(f
, "p2p_oper_reg_class=%u\n",
666 config
->p2p_oper_reg_class
);
667 if (config
->p2p_oper_channel
)
668 fprintf(f
, "p2p_oper_channel=%u\n", config
->p2p_oper_channel
);
669 if (config
->p2p_go_intent
!= DEFAULT_P2P_GO_INTENT
)
670 fprintf(f
, "p2p_go_intent=%u\n", config
->p2p_go_intent
);
671 if (config
->p2p_ssid_postfix
)
672 fprintf(f
, "p2p_ssid_postfix=%s\n", config
->p2p_ssid_postfix
);
673 if (config
->persistent_reconnect
)
674 fprintf(f
, "persistent_reconnect=%u\n",
675 config
->persistent_reconnect
);
676 if (config
->p2p_intra_bss
!= DEFAULT_P2P_INTRA_BSS
)
677 fprintf(f
, "p2p_intra_bss=%u\n", config
->p2p_intra_bss
);
679 #endif /* CONFIG_P2P */
680 if (config
->country
[0] && config
->country
[1]) {
681 fprintf(f
, "country=%c%c\n",
682 config
->country
[0], config
->country
[1]);
684 if (config
->bss_max_count
!= DEFAULT_BSS_MAX_COUNT
)
685 fprintf(f
, "bss_max_count=%u\n", config
->bss_max_count
);
686 if (config
->filter_ssids
)
687 fprintf(f
, "filter_ssids=%d\n", config
->filter_ssids
);
688 if (config
->max_num_sta
!= DEFAULT_MAX_NUM_STA
)
689 fprintf(f
, "max_num_sta=%u\n", config
->max_num_sta
);
692 #endif /* CONFIG_NO_CONFIG_WRITE */
695 int wpa_config_write(const char *name
, struct wpa_config
*config
)
697 #ifndef CONFIG_NO_CONFIG_WRITE
699 struct wpa_ssid
*ssid
;
700 #ifndef CONFIG_NO_CONFIG_BLOBS
701 struct wpa_config_blob
*blob
;
702 #endif /* CONFIG_NO_CONFIG_BLOBS */
705 wpa_printf(MSG_DEBUG
, "Writing configuration file '%s'", name
);
707 f
= fopen(name
, "w");
709 wpa_printf(MSG_DEBUG
, "Failed to open '%s' for writing", name
);
713 wpa_config_write_global(f
, config
);
715 for (ssid
= config
->ssid
; ssid
; ssid
= ssid
->next
) {
716 if (ssid
->key_mgmt
== WPA_KEY_MGMT_WPS
|| ssid
->temporary
)
717 continue; /* do not save temporary networks */
718 fprintf(f
, "\nnetwork={\n");
719 wpa_config_write_network(f
, ssid
);
723 #ifndef CONFIG_NO_CONFIG_BLOBS
724 for (blob
= config
->blobs
; blob
; blob
= blob
->next
) {
725 ret
= wpa_config_write_blob(f
, blob
);
729 #endif /* CONFIG_NO_CONFIG_BLOBS */
733 wpa_printf(MSG_DEBUG
, "Configuration file '%s' written %ssuccessfully",
734 name
, ret
? "un" : "");
736 #else /* CONFIG_NO_CONFIG_WRITE */
738 #endif /* CONFIG_NO_CONFIG_WRITE */