summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSamuel Ortiz <sameo@linux.intel.com>2009-12-23 23:16:41 +0100
committerMarcel Holtmann <marcel@holtmann.org>2009-12-23 14:30:57 -0800
commit5d5dd0f33a2f4f1fb282b14d93f9f51eebd82cf2 (patch)
tree1a96fed55b756ad2d224866e40f291b55265c798 /src
parent13175359d3d87d9510cb3f46481e9bfd49beb49d (diff)
downloadconnman-5d5dd0f33a2f4f1fb282b14d93f9f51eebd82cf2.tar.gz
connman-5d5dd0f33a2f4f1fb282b14d93f9f51eebd82cf2.tar.bz2
connman-5d5dd0f33a2f4f1fb282b14d93f9f51eebd82cf2.zip
Load service entries from configuration files
For IEEE 802.1x networks, the various certificate paths, private key paths and identities are configured through an external configuration file. They belong to a "service" group in this file and loaded at startup. Any matching service with the corresponding service group will be provisioned with this configuration. These settings will also be then propagated to the network structure at connection time.
Diffstat (limited to 'src')
-rw-r--r--src/config.c199
-rw-r--r--src/connman.h3
-rw-r--r--src/service.c57
3 files changed, 258 insertions, 1 deletions
diff --git a/src/config.c b/src/config.c
index cf8e42aa..d5cfd9eb 100644
--- a/src/config.c
+++ b/src/config.c
@@ -23,22 +23,141 @@
#include <config.h>
#endif
+#include <stdio.h>
+#include <string.h>
#include <glib.h>
#include "connman.h"
+struct connman_config_service {
+ char *type;
+ void *ssid;
+ unsigned int ssid_len;
+ char *eap;
+ char *identity;
+ char *ca_cert_file;
+ char *client_cert_file;
+ char *private_key_file;
+ char *private_key_passphrase;
+ char *phase2;
+};
+
struct connman_config {
char *ident;
char *name;
char *description;
+ struct connman_config_service *service;
};
static GHashTable *config_hash = NULL;
+static int load_service(GKeyFile *keyfile, struct connman_config *config)
+{
+ char *str, *hex_ssid;
+ struct connman_config_service *service;
+
+ service = g_try_new0(struct connman_config_service, 1);
+ if (service == NULL)
+ return -ENOMEM;
+
+ config->service = service;
+
+ str = g_key_file_get_string(keyfile, "service", "Type", NULL);
+ if (str != NULL) {
+ g_free(service->ssid);
+ service->type = str;
+ }
+
+ hex_ssid = g_key_file_get_string(keyfile, "service", "Type", NULL);
+ if (hex_ssid != NULL) {
+ char *ssid;
+ unsigned int i, j = 0, hex;
+ size_t hex_ssid_len = strlen(hex_ssid);
+
+ ssid = g_try_malloc0(hex_ssid_len / 2);
+ if (ssid == NULL) {
+ g_free(hex_ssid);
+ return -ENOMEM;
+ }
+
+ for (i = 0; i < hex_ssid_len; i += 2) {
+ sscanf(hex_ssid + i, "%02x", &hex);
+ ssid[j++] = hex;
+ }
+
+ g_free(hex_ssid);
+
+ g_free(service->type);
+ service->ssid = ssid;
+ service->ssid_len = hex_ssid_len / 2;
+ }
+
+ str = g_key_file_get_string(keyfile, "service", "EAP", NULL);
+ if (str != NULL) {
+ g_free(service->eap);
+ service->eap = str;
+ }
+
+ str = g_key_file_get_string(keyfile, "service", "CACertFile", NULL);
+ if (str != NULL) {
+ g_free(service->ca_cert_file);
+ service->ca_cert_file = str;
+ }
+
+ str = g_key_file_get_string(keyfile, "service", "ClientCertFile", NULL);
+ if (str != NULL) {
+ g_free(service->client_cert_file);
+ service->client_cert_file = str;
+ }
+
+ str = g_key_file_get_string(keyfile, "service", "PrivateKeyFile", NULL);
+ if (str != NULL) {
+ g_free(service->private_key_file);
+ service->private_key_file = str;
+ }
+
+ str = g_key_file_get_string(keyfile, "service", "PrivateKeyPassphrase",
+ NULL);
+ if (str != NULL) {
+ g_free(service->private_key_passphrase);
+ service->private_key_passphrase = str;
+ }
+
+ str = g_key_file_get_string(keyfile, "service", "Identity", NULL);
+ if (str != NULL) {
+ g_free(service->identity);
+ service->identity = str;
+ }
+
+ str = g_key_file_get_string(keyfile, "service", "Phase2", NULL);
+ if (str != NULL) {
+ g_free(service->phase2);
+ service->phase2 = str;
+ }
+
+
+ return 0;
+}
+
+static void free_service(struct connman_config_service *service)
+{
+ g_free(service->type);
+ g_free(service->ssid);
+ g_free(service->eap);
+ g_free(service->identity);
+ g_free(service->ca_cert_file);
+ g_free(service->client_cert_file);
+ g_free(service->private_key_file);
+ g_free(service->private_key_passphrase);
+ g_free(service->phase2);
+ g_free(service);
+}
+
static int load_config(struct connman_config *config)
{
GKeyFile *keyfile;
char *str;
+ int err;
DBG("config %p", config);
@@ -58,9 +177,18 @@ static int load_config(struct connman_config *config)
config->description = str;
}
+ if (g_key_file_has_group(keyfile, "service") == TRUE) {
+ err = load_service(keyfile, config);
+ if (err < 0)
+ goto done;
+ }
+
+ err = 0;
+
+done:
__connman_storage_close_config(config->ident, keyfile, FALSE);
- return 0;
+ return err;
}
static void free_config(struct connman_config *config)
@@ -68,6 +196,7 @@ static void free_config(struct connman_config *config)
g_free(config->description);
g_free(config->name);
g_free(config->ident);
+ free_service(config->service);
g_free(config);
}
@@ -149,6 +278,39 @@ static int config_init(void)
return 0;
}
+static void config_service_setup(struct connman_service *service,
+ struct connman_config_service *config)
+{
+ if (config == NULL)
+ return;
+
+ if (config->eap)
+ __connman_service_set_string(service, "EAP", config->eap);
+
+ if (config->identity)
+ __connman_service_set_string(service, "Identity",
+ config->identity);
+
+ if (config->ca_cert_file)
+ __connman_service_set_string(service, "CACertFile",
+ config->ca_cert_file);
+
+ if (config->client_cert_file)
+ __connman_service_set_string(service, "ClientCertFile",
+ config->client_cert_file);
+
+ if (config->private_key_file)
+ __connman_service_set_string(service, "PrivateKeyFile",
+ config->private_key_file);
+
+ if (config->private_key_passphrase)
+ __connman_service_set_string(service, "PrivateKeyPassphrase",
+ config->private_key_passphrase);
+
+ if (config->phase2)
+ __connman_service_set_string(service, "Phase2", config->phase2);
+}
+
int __connman_config_init(void)
{
DBG("");
@@ -169,7 +331,42 @@ void __connman_config_cleanup(void)
int __connman_config_provision_service(struct connman_service *service)
{
+ GHashTableIter iter;
+ gpointer value, key;
+ struct connman_network *network;
+ struct connman_config *config = NULL;
+ const void *ssid;
+ unsigned int ssid_len;
+
DBG("service %p", service);
+ network = __connman_service_get_network(service);
+ if (network == NULL) {
+ connman_error("Network not set");
+ return -EINVAL;
+ }
+
+ ssid = connman_network_get_blob(network, "WiFi.SSID", &ssid_len);
+ if (ssid == NULL) {
+ connman_error("Network SSID not set");
+ return -EINVAL;
+ }
+
+ g_hash_table_iter_init(&iter, config_hash);
+ while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
+ config = value;
+
+ /* For now we only support wifi services entries */
+ if (config->service &&
+ g_strcmp0(config->service->type, "wifi") == 0 &&
+ ssid_len == config->service->ssid_len)
+ if (config->service->ssid &&
+ memcmp(config->service->ssid, ssid,
+ ssid_len) == 0)
+ break;
+ }
+
+ config_service_setup(service, config->service);
+
return 0;
}
diff --git a/src/connman.h b/src/connman.h
index 6a36331c..e7869f9c 100644
--- a/src/connman.h
+++ b/src/connman.h
@@ -375,7 +375,10 @@ void __connman_service_remove_from_network(struct connman_network *network);
const char *__connman_service_get_path(struct connman_service *service);
unsigned int __connman_service_get_order(struct connman_service *service);
+struct connman_network *__connman_service_get_network(struct connman_service *service);
+void __connman_service_set_string(struct connman_service *service,
+ const char *key, const char *value);
int __connman_service_indicate_state(struct connman_service *service,
enum connman_service_state state);
int __connman_service_indicate_error(struct connman_service *service,
diff --git a/src/service.c b/src/service.c
index 3092f673..167cef48 100644
--- a/src/service.c
+++ b/src/service.c
@@ -65,6 +65,14 @@ struct connman_service {
connman_bool_t roaming;
struct connman_ipconfig *ipconfig;
struct connman_network *network;
+ /* 802.1x settings from the config files */
+ char *eap;
+ char *identity;
+ char *ca_cert_file;
+ char *client_cert_file;
+ char *private_key_file;
+ char *private_key_passphrase;
+ char *phase2;
DBusMessage *pending;
guint timeout;
};
@@ -1181,6 +1189,13 @@ static void service_free(gpointer user_data)
g_free(service->name);
g_free(service->passphrase);
g_free(service->identifier);
+ g_free(service->eap);
+ g_free(service->identity);
+ g_free(service->ca_cert_file);
+ g_free(service->client_cert_file);
+ g_free(service->private_key_file);
+ g_free(service->private_key_passphrase);
+ g_free(service->phase2);
g_free(service);
}
@@ -1357,6 +1372,21 @@ char *connman_service_get_interface(struct connman_service *service)
}
/**
+ * connman_service_get_network:
+ * @service: service structure
+ *
+ * Get the service network
+ */
+struct connman_network *
+__connman_service_get_network(struct connman_service *service)
+{
+ if (service == NULL)
+ return NULL;
+
+ return service->network;
+}
+
+/**
* connman_service_set_favorite:
* @service: service structure
* @favorite: favorite value
@@ -1386,6 +1416,33 @@ int connman_service_set_favorite(struct connman_service *service,
return 0;
}
+void __connman_service_set_string(struct connman_service *service,
+ const char *key, const char *value)
+{
+ if (g_str_equal(key, "EAP") == TRUE) {
+ g_free(service->eap);
+ service->eap = g_strdup(value);
+ } else if (g_str_equal(key, "Identity") == TRUE) {
+ g_free(service->identity);
+ service->identity = g_strdup(value);
+ } else if (g_str_equal(key, "CACertFile") == TRUE) {
+ g_free(service->ca_cert_file);
+ service->ca_cert_file = g_strdup(value);
+ } else if (g_str_equal(key, "ClientCertFile") == TRUE) {
+ g_free(service->client_cert_file);
+ service->client_cert_file = g_strdup(value);
+ } else if (g_str_equal(key, "PrivateKeyFile") == TRUE) {
+ g_free(service->private_key_file);
+ service->private_key_file = g_strdup(value);
+ } else if (g_str_equal(key, "PrivateKeyPassphrase") == TRUE) {
+ g_free(service->private_key_passphrase);
+ service->private_key_passphrase = g_strdup(value);
+ } else if (g_str_equal(key, "Phase2") == TRUE) {
+ g_free(service->phase2);
+ service->phase2 = g_strdup(value);
+ }
+}
+
int __connman_service_indicate_state(struct connman_service *service,
enum connman_service_state state)
{