Interworking: Add support for multiple credentials
[mech_eap.git] / wpa_supplicant / config_file.c
index fa39f64..01e2a3d 100644 (file)
@@ -1,15 +1,9 @@
 /*
  * WPA Supplicant / Configuration backend: text file
- * Copyright (c) 2003-2007, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2003-2008, Jouni Malinen <j@w1.fi>
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Alternatively, this software may be distributed under the terms of BSD
- * license.
- *
- * See README and COPYING for more details.
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
  *
  * This file implements a configuration backend for text files. All the
  * configuration information is stored in a text file that uses a format
@@ -21,7 +15,7 @@
 #include "common.h"
 #include "config.h"
 #include "base64.h"
-#include "eap_peer/eap_methods.h"
+#include "uuid.h"
 
 
 /**
@@ -104,8 +98,7 @@ static int wpa_config_validate_network(struct wpa_ssid *ssid, int line)
                wpa_config_update_psk(ssid);
        }
 
-       if ((ssid->key_mgmt & (WPA_KEY_MGMT_PSK | WPA_KEY_MGMT_FT_PSK)) &&
-           !ssid->psk_set) {
+       if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && !ssid->psk_set) {
                wpa_printf(MSG_ERROR, "Line %d: WPA-PSK accepted for key "
                           "management, but no PSK configured.", line);
                errors++;
@@ -185,6 +178,61 @@ static struct wpa_ssid * wpa_config_read_network(FILE *f, int *line, int id)
 }
 
 
+static struct wpa_cred * wpa_config_read_cred(FILE *f, int *line, int id)
+{
+       struct wpa_cred *cred;
+       int errors = 0, end = 0;
+       char buf[256], *pos, *pos2;
+
+       wpa_printf(MSG_MSGDUMP, "Line: %d - start of a new cred block", *line);
+       cred = os_zalloc(sizeof(*cred));
+       if (cred == NULL)
+               return NULL;
+       cred->id = id;
+
+       while (wpa_config_get_line(buf, sizeof(buf), f, line, &pos)) {
+               if (os_strcmp(pos, "}") == 0) {
+                       end = 1;
+                       break;
+               }
+
+               pos2 = os_strchr(pos, '=');
+               if (pos2 == NULL) {
+                       wpa_printf(MSG_ERROR, "Line %d: Invalid cred line "
+                                  "'%s'.", *line, pos);
+                       errors++;
+                       continue;
+               }
+
+               *pos2++ = '\0';
+               if (*pos2 == '"') {
+                       if (os_strchr(pos2 + 1, '"') == NULL) {
+                               wpa_printf(MSG_ERROR, "Line %d: invalid "
+                                          "quotation '%s'.", *line, pos2);
+                               errors++;
+                               continue;
+                       }
+               }
+
+               if (wpa_config_set_cred(cred, pos, pos2, *line) < 0)
+                       errors++;
+       }
+
+       if (!end) {
+               wpa_printf(MSG_ERROR, "Line %d: cred block was not "
+                          "terminated properly.", *line);
+               errors++;
+       }
+
+       if (errors) {
+               wpa_config_free_cred(cred);
+               cred = NULL;
+       }
+
+       return cred;
+}
+
+
 #ifndef CONFIG_NO_CONFIG_BLOBS
 static struct wpa_config_blob * wpa_config_read_blob(FILE *f, int *line,
                                                     const char *name)
@@ -268,230 +316,16 @@ static int wpa_config_process_blob(struct wpa_config *config, FILE *f,
 #endif /* CONFIG_NO_CONFIG_BLOBS */
 
 
-#ifdef CONFIG_CTRL_IFACE
-static int wpa_config_process_ctrl_interface(struct wpa_config *config,
-                                            char *pos)
-{
-       os_free(config->ctrl_interface);
-       config->ctrl_interface = os_strdup(pos);
-       wpa_printf(MSG_DEBUG, "ctrl_interface='%s'", config->ctrl_interface);
-       return 0;
-}
-
-
-static int wpa_config_process_ctrl_interface_group(struct wpa_config *config,
-                                                  char *pos)
-{
-       os_free(config->ctrl_interface_group);
-       config->ctrl_interface_group = os_strdup(pos);
-       wpa_printf(MSG_DEBUG, "ctrl_interface_group='%s' (DEPRECATED)",
-                  config->ctrl_interface_group);
-       return 0;
-}
-#endif /* CONFIG_CTRL_IFACE */
-
-
-static int wpa_config_process_eapol_version(struct wpa_config *config,
-                                           int line, char *pos)
-{
-       config->eapol_version = atoi(pos);
-       if (config->eapol_version < 1 || config->eapol_version > 2) {
-               wpa_printf(MSG_ERROR, "Line %d: Invalid EAPOL version (%d): "
-                          "'%s'.", line, config->eapol_version, pos);
-               return -1;
-       }
-       wpa_printf(MSG_DEBUG, "eapol_version=%d", config->eapol_version);
-       return 0;
-}
-
-
-static int wpa_config_process_ap_scan(struct wpa_config *config, char *pos)
-{
-       config->ap_scan = atoi(pos);
-       wpa_printf(MSG_DEBUG, "ap_scan=%d", config->ap_scan);
-       return 0;
-}
-
-
-static int wpa_config_process_fast_reauth(struct wpa_config *config, char *pos)
-{
-       config->fast_reauth = atoi(pos);
-       wpa_printf(MSG_DEBUG, "fast_reauth=%d", config->fast_reauth);
-       return 0;
-}
-
-
-#ifdef EAP_TLS_OPENSSL
-
-static int wpa_config_process_opensc_engine_path(struct wpa_config *config,
-                                                char *pos)
-{
-       os_free(config->opensc_engine_path);
-       config->opensc_engine_path = os_strdup(pos);
-       wpa_printf(MSG_DEBUG, "opensc_engine_path='%s'",
-                  config->opensc_engine_path);
-       return 0;
-}
-
-
-static int wpa_config_process_pkcs11_engine_path(struct wpa_config *config,
-                                                char *pos)
-{
-       os_free(config->pkcs11_engine_path);
-       config->pkcs11_engine_path = os_strdup(pos);
-       wpa_printf(MSG_DEBUG, "pkcs11_engine_path='%s'",
-                  config->pkcs11_engine_path);
-       return 0;
-}
-
-
-static int wpa_config_process_pkcs11_module_path(struct wpa_config *config,
-                                                char *pos)
-{
-       os_free(config->pkcs11_module_path);
-       config->pkcs11_module_path = os_strdup(pos);
-       wpa_printf(MSG_DEBUG, "pkcs11_module_path='%s'",
-                  config->pkcs11_module_path);
-       return 0;
-}
-
-#endif /* EAP_TLS_OPENSSL */
-
-
-static int wpa_config_process_driver_param(struct wpa_config *config,
-                                          char *pos)
-{
-       os_free(config->driver_param);
-       config->driver_param = os_strdup(pos);
-       wpa_printf(MSG_DEBUG, "driver_param='%s'", config->driver_param);
-       return 0;
-}
-
-
-static int wpa_config_process_pmk_lifetime(struct wpa_config *config,
-                                          char *pos)
-{
-       config->dot11RSNAConfigPMKLifetime = atoi(pos);
-       wpa_printf(MSG_DEBUG, "dot11RSNAConfigPMKLifetime=%d",
-                  config->dot11RSNAConfigPMKLifetime);
-       return 0;
-}
-
-
-static int wpa_config_process_pmk_reauth_threshold(struct wpa_config *config,
-                                                  char *pos)
-{
-       config->dot11RSNAConfigPMKReauthThreshold = atoi(pos);
-       wpa_printf(MSG_DEBUG, "dot11RSNAConfigPMKReauthThreshold=%d",
-                  config->dot11RSNAConfigPMKReauthThreshold);
-       return 0;
-}
-
-
-static int wpa_config_process_sa_timeout(struct wpa_config *config, char *pos)
-{
-       config->dot11RSNAConfigSATimeout = atoi(pos);
-       wpa_printf(MSG_DEBUG, "dot11RSNAConfigSATimeout=%d",
-                  config->dot11RSNAConfigSATimeout);
-       return 0;
-}
-
-
-#ifndef CONFIG_NO_CONFIG_WRITE
-static int wpa_config_process_update_config(struct wpa_config *config,
-                                           char *pos)
-{
-       config->update_config = atoi(pos);
-       wpa_printf(MSG_DEBUG, "update_config=%d", config->update_config);
-       return 0;
-}
-#endif /* CONFIG_NO_CONFIG_WRITE */
-
-
-static int wpa_config_process_load_dynamic_eap(int line, char *so)
-{
-       int ret;
-       wpa_printf(MSG_DEBUG, "load_dynamic_eap=%s", so);
-       ret = eap_peer_method_load(so);
-       if (ret == -2) {
-               wpa_printf(MSG_DEBUG, "This EAP type was already loaded - not "
-                          "reloading.");
-       } else if (ret) {
-               wpa_printf(MSG_ERROR, "Line %d: Failed to load dynamic EAP "
-                          "method '%s'.", line, so);
-               return -1;
-       }
-
-       return 0;
-}
-
-
-static int wpa_config_process_global(struct wpa_config *config, char *pos,
-                                    int line)
-{
-#ifdef CONFIG_CTRL_IFACE
-       if (os_strncmp(pos, "ctrl_interface=", 15) == 0)
-               return wpa_config_process_ctrl_interface(config, pos + 15);
-
-       if (os_strncmp(pos, "ctrl_interface_group=", 21) == 0)
-               return wpa_config_process_ctrl_interface_group(config,
-                                                              pos + 21);
-#endif /* CONFIG_CTRL_IFACE */
-
-       if (os_strncmp(pos, "eapol_version=", 14) == 0)
-               return wpa_config_process_eapol_version(config, line,
-                                                       pos + 14);
-
-       if (os_strncmp(pos, "ap_scan=", 8) == 0)
-               return wpa_config_process_ap_scan(config, pos + 8);
-
-       if (os_strncmp(pos, "fast_reauth=", 12) == 0)
-               return wpa_config_process_fast_reauth(config, pos + 12);
-
-#ifdef EAP_TLS_OPENSSL
-       if (os_strncmp(pos, "opensc_engine_path=", 19) == 0)
-               return wpa_config_process_opensc_engine_path(config, pos + 19);
-
-       if (os_strncmp(pos, "pkcs11_engine_path=", 19) == 0)
-               return wpa_config_process_pkcs11_engine_path(config, pos + 19);
-
-       if (os_strncmp(pos, "pkcs11_module_path=", 19) == 0)
-               return wpa_config_process_pkcs11_module_path(config, pos + 19);
-#endif /* EAP_TLS_OPENSSL */
-
-       if (os_strncmp(pos, "driver_param=", 13) == 0)
-               return wpa_config_process_driver_param(config, pos + 13);
-
-       if (os_strncmp(pos, "dot11RSNAConfigPMKLifetime=", 27) == 0)
-               return wpa_config_process_pmk_lifetime(config, pos + 27);
-
-       if (os_strncmp(pos, "dot11RSNAConfigPMKReauthThreshold=", 34) == 0)
-               return wpa_config_process_pmk_reauth_threshold(config,
-                                                              pos + 34);
-
-       if (os_strncmp(pos, "dot11RSNAConfigSATimeout=", 25) == 0)
-               return wpa_config_process_sa_timeout(config, pos + 25);
-
-#ifndef CONFIG_NO_CONFIG_WRITE
-       if (os_strncmp(pos, "update_config=", 14) == 0)
-               return wpa_config_process_update_config(config, pos + 14);
-#endif /* CONFIG_NO_CONFIG_WRITE */
-
-       if (os_strncmp(pos, "load_dynamic_eap=", 17) == 0)
-               return wpa_config_process_load_dynamic_eap(line, pos + 17);
-
-       return -1;
-}
-
-
 struct wpa_config * wpa_config_read(const char *name)
 {
        FILE *f;
        char buf[256], *pos;
        int errors = 0, line = 0;
        struct wpa_ssid *ssid, *tail = NULL, *head = NULL;
+       struct wpa_cred *cred, *cred_tail = NULL, *cred_head = NULL;
        struct wpa_config *config;
        int id = 0;
+       int cred_id = 0;
 
        config = wpa_config_alloc_empty(NULL, NULL);
        if (config == NULL)
@@ -525,6 +359,20 @@ struct wpa_config * wpa_config_read(const char *name)
                                errors++;
                                continue;
                        }
+               } else if (os_strcmp(pos, "cred={") == 0) {
+                       cred = wpa_config_read_cred(f, &line, cred_id++);
+                       if (cred == NULL) {
+                               wpa_printf(MSG_ERROR, "Line %d: failed to "
+                                          "parse cred block.", line);
+                               errors++;
+                               continue;
+                       }
+                       if (cred_head == NULL) {
+                               cred_head = cred_tail = cred;
+                       } else {
+                               cred_tail->next = cred;
+                               cred_tail = cred;
+                       }
 #ifndef CONFIG_NO_CONFIG_BLOBS
                } else if (os_strncmp(pos, "blob-base64-", 12) == 0) {
                        if (wpa_config_process_blob(config, f, &line, pos + 12)
@@ -545,12 +393,15 @@ struct wpa_config * wpa_config_read(const char *name)
 
        config->ssid = head;
        wpa_config_debug_dump_networks(config);
+       config->cred = cred_head;
 
+#ifndef WPA_IGNORE_CONFIG_ERRORS
        if (errors) {
                wpa_config_free(config);
                config = NULL;
                head = NULL;
        }
+#endif /* WPA_IGNORE_CONFIG_ERRORS */
 
        return config;
 }
@@ -708,6 +559,18 @@ static void write_wep_key(FILE *f, int idx, struct wpa_ssid *ssid)
 }
 
 
+#ifdef CONFIG_P2P
+static void write_p2p_client_list(FILE *f, struct wpa_ssid *ssid)
+{
+       char *value = wpa_config_get(ssid, "p2p_client_list");
+       if (value == NULL)
+               return;
+       fprintf(f, "\tp2p_client_list=%s\n", value);
+       os_free(value);
+}
+#endif /* CONFIG_P2P */
+
+
 static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid)
 {
        int i;
@@ -754,7 +617,15 @@ static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid)
        STR(pin);
        STR(engine_id);
        STR(key_id);
+       STR(cert_id);
+       STR(ca_cert_id);
+       STR(key2_id);
+       STR(pin2);
+       STR(engine2_id);
+       STR(cert2_id);
+       STR(ca_cert2_id);
        INTe(engine);
+       INTe(engine2);
        INT_DEF(eapol_flags, DEFAULT_EAPOL_FLAGS);
 #endif /* IEEE8021X_EAPOL */
        for (i = 0; i < 4; i++)
@@ -774,6 +645,9 @@ static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid)
        INT(ieee80211w);
 #endif /* CONFIG_IEEE80211W */
        STR(id_str);
+#ifdef CONFIG_P2P
+       write_p2p_client_list(f, ssid);
+#endif /* CONFIG_P2P */
 
 #undef STR
 #undef INT
@@ -812,7 +686,6 @@ static void wpa_config_write_global(FILE *f, struct wpa_config *config)
                fprintf(f, "ap_scan=%d\n", config->ap_scan);
        if (config->fast_reauth != DEFAULT_FAST_REAUTH)
                fprintf(f, "fast_reauth=%d\n", config->fast_reauth);
-#ifdef EAP_TLS_OPENSSL
        if (config->opensc_engine_path)
                fprintf(f, "opensc_engine_path=%s\n",
                        config->opensc_engine_path);
@@ -822,7 +695,6 @@ static void wpa_config_write_global(FILE *f, struct wpa_config *config)
        if (config->pkcs11_module_path)
                fprintf(f, "pkcs11_module_path=%s\n",
                        config->pkcs11_module_path);
-#endif /* EAP_TLS_OPENSSL */
        if (config->driver_param)
                fprintf(f, "driver_param=%s\n", config->driver_param);
        if (config->dot11RSNAConfigPMKLifetime)
@@ -836,6 +708,90 @@ static void wpa_config_write_global(FILE *f, struct wpa_config *config)
                        config->dot11RSNAConfigSATimeout);
        if (config->update_config)
                fprintf(f, "update_config=%d\n", config->update_config);
+#ifdef CONFIG_WPS
+       if (!is_nil_uuid(config->uuid)) {
+               char buf[40];
+               uuid_bin2str(config->uuid, buf, sizeof(buf));
+               fprintf(f, "uuid=%s\n", buf);
+       }
+       if (config->device_name)
+               fprintf(f, "device_name=%s\n", config->device_name);
+       if (config->manufacturer)
+               fprintf(f, "manufacturer=%s\n", config->manufacturer);
+       if (config->model_name)
+               fprintf(f, "model_name=%s\n", config->model_name);
+       if (config->model_number)
+               fprintf(f, "model_number=%s\n", config->model_number);
+       if (config->serial_number)
+               fprintf(f, "serial_number=%s\n", config->serial_number);
+       {
+               char _buf[WPS_DEV_TYPE_BUFSIZE], *buf;
+               buf = wps_dev_type_bin2str(config->device_type,
+                                          _buf, sizeof(_buf));
+               if (os_strcmp(buf, "0-00000000-0") != 0)
+                       fprintf(f, "device_type=%s\n", buf);
+       }
+       if (WPA_GET_BE32(config->os_version))
+               fprintf(f, "os_version=%08x\n",
+                       WPA_GET_BE32(config->os_version));
+       if (config->config_methods)
+               fprintf(f, "config_methods=%s\n", config->config_methods);
+       if (config->wps_cred_processing)
+               fprintf(f, "wps_cred_processing=%d\n",
+                       config->wps_cred_processing);
+#endif /* CONFIG_WPS */
+#ifdef CONFIG_P2P
+       if (config->p2p_listen_reg_class)
+               fprintf(f, "p2p_listen_reg_class=%u\n",
+                       config->p2p_listen_reg_class);
+       if (config->p2p_listen_channel)
+               fprintf(f, "p2p_listen_channel=%u\n",
+                       config->p2p_listen_channel);
+       if (config->p2p_oper_reg_class)
+               fprintf(f, "p2p_oper_reg_class=%u\n",
+                       config->p2p_oper_reg_class);
+       if (config->p2p_oper_channel)
+               fprintf(f, "p2p_oper_channel=%u\n", config->p2p_oper_channel);
+       if (config->p2p_go_intent != DEFAULT_P2P_GO_INTENT)
+               fprintf(f, "p2p_go_intent=%u\n", config->p2p_go_intent);
+       if (config->p2p_ssid_postfix)
+               fprintf(f, "p2p_ssid_postfix=%s\n", config->p2p_ssid_postfix);
+       if (config->persistent_reconnect)
+               fprintf(f, "persistent_reconnect=%u\n",
+                       config->persistent_reconnect);
+       if (config->p2p_intra_bss != DEFAULT_P2P_INTRA_BSS)
+               fprintf(f, "p2p_intra_bss=%u\n", config->p2p_intra_bss);
+       if (config->p2p_group_idle)
+               fprintf(f, "p2p_group_idle=%u\n", config->p2p_group_idle);
+#endif /* CONFIG_P2P */
+       if (config->country[0] && config->country[1]) {
+               fprintf(f, "country=%c%c\n",
+                       config->country[0], config->country[1]);
+       }
+       if (config->bss_max_count != DEFAULT_BSS_MAX_COUNT)
+               fprintf(f, "bss_max_count=%u\n", config->bss_max_count);
+       if (config->bss_expiration_age != DEFAULT_BSS_EXPIRATION_AGE)
+               fprintf(f, "bss_expiration_age=%u\n",
+                       config->bss_expiration_age);
+       if (config->bss_expiration_scan_count !=
+           DEFAULT_BSS_EXPIRATION_SCAN_COUNT)
+               fprintf(f, "bss_expiration_scan_count=%u\n",
+                       config->bss_expiration_scan_count);
+       if (config->filter_ssids)
+               fprintf(f, "filter_ssids=%d\n", config->filter_ssids);
+       if (config->max_num_sta != DEFAULT_MAX_NUM_STA)
+               fprintf(f, "max_num_sta=%u\n", config->max_num_sta);
+       if (config->disassoc_low_ack)
+               fprintf(f, "disassoc_low_ack=%u\n", config->disassoc_low_ack);
+#ifdef CONFIG_INTERWORKING
+       if (config->interworking)
+               fprintf(f, "interworking=%u\n", config->interworking);
+       if (!is_zero_ether_addr(config->hessid))
+               fprintf(f, "hessid=" MACSTR "\n", MAC2STR(config->hessid));
+       if (config->access_network_type != DEFAULT_ACCESS_NETWORK_TYPE)
+               fprintf(f, "access_network_type=%d\n",
+                       config->access_network_type);
+#endif /* CONFIG_INTERWORKING */
 }
 
 #endif /* CONFIG_NO_CONFIG_WRITE */
@@ -862,6 +818,11 @@ int wpa_config_write(const char *name, struct wpa_config *config)
        wpa_config_write_global(f, config);
 
        for (ssid = config->ssid; ssid; ssid = ssid->next) {
+               if (ssid->key_mgmt == WPA_KEY_MGMT_WPS || ssid->temporary)
+                       continue; /* do not save temporary networks */
+               if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && !ssid->psk_set &&
+                   !ssid->passphrase)
+                       continue; /* do not save invalid network */
                fprintf(f, "\nnetwork={\n");
                wpa_config_write_network(f, ssid);
                fprintf(f, "}\n");