Add setter/getter for handling MAC randomization policy
[platform/upstream/connman.git] / vpn / vpn-config.c
old mode 100644 (file)
new mode 100755 (executable)
index 1ece7e9..2fe0307
@@ -2,7 +2,7 @@
  *
  *  Connection Manager
  *
- *  Copyright (C) 2012  Intel Corporation. All rights reserved.
+ *  Copyright (C) 2012-2013  Intel Corporation. All rights reserved.
  *
  *  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
@@ -59,24 +59,20 @@ struct vpn_config {
        char *ident;
        char *name;
        char *description;
-       connman_bool_t protected;
        GHashTable *provider_table;
 };
 
 static GHashTable *config_table = NULL;
-static GSList *protected_providers = NULL;
 
-static connman_bool_t cleanup = FALSE;
+static bool cleanup = false;
 
 /* Definition of possible strings in the .config files */
 #define CONFIG_KEY_NAME                "Name"
 #define CONFIG_KEY_DESC                "Description"
-#define CONFIG_KEY_PROT                "Protected"
 
 static const char *config_possible_keys[] = {
        CONFIG_KEY_NAME,
        CONFIG_KEY_DESC,
-       CONFIG_KEY_PROT,
        NULL,
 };
 
@@ -100,7 +96,7 @@ static void unregister_provider(gpointer data)
        struct vpn_provider *provider;
        char *provider_id;
 
-       if (cleanup == TRUE)
+       if (cleanup)
                goto free_only;
 
        provider_id = config_provider->provider_identifier;
@@ -108,14 +104,11 @@ static void unregister_provider(gpointer data)
        connman_info("Removing provider configuration %s provider %s",
                                config_provider->ident, provider_id);
 
-       protected_providers = g_slist_remove(protected_providers,
-                                               config_provider);
-
        provider = __vpn_provider_lookup(provider_id);
-       if (provider != NULL)
+       if (provider)
                __vpn_provider_delete(provider);
        else {
-               if (__connman_storage_remove_provider(provider_id) == FALSE)
+               if (!__connman_storage_remove_provider(provider_id))
                        DBG("Could not remove all files for provider %s",
                                                                provider_id);
        }
@@ -134,60 +127,24 @@ free_only:
        g_free(config_provider);
 }
 
-static connman_bool_t check_type(const char *type)
-{
-       if (g_strcmp0(type, "OpenConnect") == 0)
-               return TRUE;
-       if (g_strcmp0(type, "OpenVPN") == 0)
-               return TRUE;
-       if (g_strcmp0(type, "VPNC") == 0)
-               return TRUE;
-       if (g_strcmp0(type, "L2TP") == 0)
-               return TRUE;
-       if (g_strcmp0(type, "PPTP") == 0)
-               return TRUE;
-
-       return FALSE;
-}
-
-static connman_bool_t
-is_protected_provider(struct vpn_config_provider *config_provider)
-{
-       GSList *list;
-
-       DBG("ident %s", config_provider->ident);
-
-       for (list = protected_providers; list; list = list->next) {
-               struct vpn_config_provider *p = list->data;
-
-               if (g_strcmp0(p->type, config_provider->type) != 0)
-                       continue;
-
-               if (check_type(config_provider->type) == TRUE)
-                       return TRUE;
-       }
-
-       return FALSE;
-}
-
 static int set_string(struct vpn_config_provider *config_provider,
                                        const char *key, const char *value)
 {
        DBG("provider %p key %s value %s", config_provider, key, value);
 
-       if (g_str_equal(key, "Type") == TRUE) {
+       if (g_str_equal(key, "Type")) {
                g_free(config_provider->type);
                config_provider->type = g_strdup(value);
-       } else if (g_str_equal(key, "Name") == TRUE) {
+       } else if (g_str_equal(key, "Name")) {
                g_free(config_provider->name);
                config_provider->name = g_strdup(value);
-       } else if (g_str_equal(key, "Host") == TRUE) {
+       } else if (g_str_equal(key, "Host")) {
                g_free(config_provider->host);
                config_provider->host = g_strdup(value);
-       } else if (g_str_equal(key, "Domain") == TRUE) {
+       } else if (g_str_equal(key, "Domain")) {
                g_free(config_provider->domain);
                config_provider->domain = g_strdup(value);
-       } else if (g_str_equal(key, "Networks") == TRUE) {
+       } else if (g_str_equal(key, "Networks")) {
                g_free(config_provider->networks);
                config_provider->networks = g_strdup(value);
        }
@@ -202,15 +159,15 @@ static const char *get_string(struct vpn_config_provider *config_provider,
 {
        DBG("provider %p key %s", config_provider, key);
 
-       if (g_str_equal(key, "Type") == TRUE)
+       if (g_str_equal(key, "Type"))
                return config_provider->type;
-       else if (g_str_equal(key, "Name") == TRUE)
+       else if (g_str_equal(key, "Name"))
                return config_provider->name;
-       else if (g_str_equal(key, "Host") == TRUE)
+       else if (g_str_equal(key, "Host"))
                return config_provider->host;
-       else if (g_str_equal(key, "Domain") == TRUE)
+       else if (g_str_equal(key, "Domain"))
                return config_provider->domain;
-       else if (g_str_equal(key, "Networks") == TRUE)
+       else if (g_str_equal(key, "Networks"))
                return config_provider->networks;
 
        return g_hash_table_lookup(config_provider->setting_strings, key);
@@ -223,13 +180,13 @@ static void add_keys(struct vpn_config_provider *config_provider,
        gsize nb_avail_keys, i;
 
        avail_keys = g_key_file_get_keys(keyfile, group, &nb_avail_keys, NULL);
-       if (avail_keys == NULL)
+       if (!avail_keys)
                return;
 
        for (i = 0 ; i < nb_avail_keys; i++) {
                char *value = g_key_file_get_value(keyfile, group,
                                                avail_keys[i], NULL);
-               if (value == NULL) {
+               if (!value) {
                        connman_warn("Cannot find value for %s",
                                                        avail_keys[i]);
                        continue;
@@ -246,7 +203,11 @@ static int load_provider(GKeyFile *keyfile, const char *group,
                                struct vpn_config *config, enum what action)
 {
        struct vpn_config_provider *config_provider;
+#if !defined TIZEN_EXT
        const char *ident, *host, *domain;
+#else
+       const char *ident, *host, *domain, *name;
+#endif
        int err;
 
        /* Strip off "provider_" prefix */
@@ -256,11 +217,11 @@ static int load_provider(GKeyFile *keyfile, const char *group,
                return -EINVAL;
 
        config_provider = g_hash_table_lookup(config->provider_table, ident);
-       if (config_provider != NULL)
+       if (config_provider)
                return -EALREADY;
 
        config_provider = g_try_new0(struct vpn_config_provider, 1);
-       if (config_provider == NULL)
+       if (!config_provider)
                return -ENOMEM;
 
        config_provider->ident = g_strdup(ident);
@@ -272,17 +233,28 @@ static int load_provider(GKeyFile *keyfile, const char *group,
 
        host = get_string(config_provider, "Host");
        domain = get_string(config_provider, "Domain");
-       if (host != NULL && domain != NULL) {
+#if !defined TIZEN_EXT
+       if (host && domain) {
                char *id = __vpn_provider_create_identifier(host, domain);
+#else
+       name = get_string(config_provider, "Name");
+       if (host && domain && name) {
+               char *id = __vpn_provider_create_identifier(host, domain, name);
+#endif
 
                struct vpn_provider *provider;
                provider = __vpn_provider_lookup(id);
-               if (provider != NULL) {
-                       if (action == REMOVE)
+               if (provider) {
+                       if (action == REMOVE) {
                                __vpn_provider_delete(provider);
+                               err = 0;
+                       } else {
+                               connman_warn("Provider configuration %s "
+                                               "already exist", id);
+                               err = -EALREADY;
+                       }
 
                        g_free(id);
-                       err = -EALREADY;
                        goto err;
                }
 
@@ -290,28 +262,19 @@ static int load_provider(GKeyFile *keyfile, const char *group,
 
                DBG("provider identifier %s", id);
        } else {
+#if !defined TIZEN_EXT
                DBG("invalid values host %s domain %s", host, domain);
+#else
+               DBG("invalid values host %s domain %s name %s", host, domain, name);
+#endif
                err = -EINVAL;
                goto err;
        }
 
-       if (is_protected_provider(config_provider) == TRUE) {
-               connman_error("Trying to provision a protected service");
-               err = -EACCES;
-               goto err;
-       }
-
        config_provider->config_ident = g_strdup(config->ident);
        config_provider->config_entry = g_strdup_printf("provider_%s",
                                                config_provider->ident);
 
-       g_hash_table_insert(config->provider_table,
-                               config_provider->ident, config_provider);
-
-       if (config->protected == TRUE)
-               protected_providers =
-                       g_slist_prepend(protected_providers, config_provider);
-
        err = __vpn_provider_create_from_config(
                                        config_provider->setting_strings,
                                        config_provider->config_ident,
@@ -322,6 +285,10 @@ static int load_provider(GKeyFile *keyfile, const char *group,
                goto err;
        }
 
+       g_hash_table_insert(config->provider_table, config_provider->ident,
+                               config_provider);
+
+
        connman_info("Added provider configuration %s",
                                                config_provider->ident);
        return 0;
@@ -346,7 +313,7 @@ static void check_keys(GKeyFile *keyfile, const char *group,
        gsize nb_avail_keys, i, j;
 
        avail_keys = g_key_file_get_keys(keyfile, group, &nb_avail_keys, NULL);
-       if (avail_keys == NULL)
+       if (!avail_keys)
                return;
 
        for (i = 0 ; i < nb_avail_keys; i++) {
@@ -354,7 +321,7 @@ static void check_keys(GKeyFile *keyfile, const char *group,
                        if (g_strcmp0(avail_keys[i], possible_keys[j]) == 0)
                                break;
 
-               if (possible_keys[j] == NULL)
+               if (!possible_keys[j])
                        connman_warn("Unknown configuration key %s in [%s]",
                                        avail_keys[i], group);
        }
@@ -365,54 +332,45 @@ static void check_keys(GKeyFile *keyfile, const char *group,
 static int load_config(struct vpn_config *config, char *path, enum what action)
 {
        GKeyFile *keyfile;
-       GError *error = NULL;
        gsize length;
        char **groups;
        char *str;
-       gboolean protected, found = FALSE;
+       bool found = false;
        int i;
 
        DBG("config %p", config);
 
        keyfile = __connman_storage_load_provider_config(config->ident);
-       if (keyfile == NULL)
+       if (!keyfile)
                return -EIO;
 
        /* Verify keys validity of the global section */
        check_keys(keyfile, "global", config_possible_keys);
 
-       str = g_key_file_get_string(keyfile, "global", CONFIG_KEY_NAME, NULL);
-       if (str != NULL) {
+       str = __vpn_config_get_string(keyfile, "global", CONFIG_KEY_NAME, NULL);
+       if (str) {
                g_free(config->name);
                config->name = str;
        }
 
-       str = g_key_file_get_string(keyfile, "global", CONFIG_KEY_DESC, NULL);
-       if (str != NULL) {
+       str = __vpn_config_get_string(keyfile, "global", CONFIG_KEY_DESC, NULL);
+       if (str) {
                g_free(config->description);
                config->description = str;
        }
 
-       protected = g_key_file_get_boolean(keyfile, "global",
-                                       CONFIG_KEY_PROT, &error);
-       if (error == NULL)
-               config->protected = protected;
-       else
-               config->protected = TRUE;
-       g_clear_error(&error);
-
        groups = g_key_file_get_groups(keyfile, &length);
 
-       for (i = 0; groups[i] != NULL; i++) {
-               if (g_str_has_prefix(groups[i], "provider_") == TRUE) {
+       for (i = 0; groups[i]; i++) {
+               if (g_str_has_prefix(groups[i], "provider_")) {
                        int ret = load_provider(keyfile, groups[i], config,
                                                action);
                        if (ret == 0 || ret == -EALREADY)
-                               found = TRUE;
+                               found = true;
                }
        }
 
-       if (found == FALSE)
+       if (!found)
                connman_warn("Config file %s/%s.config does not contain any "
                        "configuration that can be provisioned!",
                        path, config->ident);
@@ -430,11 +388,11 @@ static struct vpn_config *create_config(const char *ident)
 
        DBG("ident %s", ident);
 
-       if (g_hash_table_lookup(config_table, ident) != NULL)
+       if (g_hash_table_lookup(config_table, ident))
                return NULL;
 
        config = g_try_new0(struct vpn_config, 1);
-       if (config == NULL)
+       if (!config)
                return NULL;
 
        config->ident = g_strdup(ident);
@@ -449,21 +407,21 @@ static struct vpn_config *create_config(const char *ident)
        return config;
 }
 
-static connman_bool_t validate_ident(const char *ident)
+static bool validate_ident(const char *ident)
 {
        unsigned int i;
 
-       if (ident == NULL)
-               return FALSE;
+       if (!ident)
+               return false;
 
        for (i = 0; i < strlen(ident); i++)
-               if (g_ascii_isprint(ident[i]) == FALSE)
-                       return FALSE;
+               if (!g_ascii_isprint(ident[i]))
+                       return false;
 
-       return TRUE;
+       return true;
 }
 
-static char *get_dir()
+static char *get_dir(void)
 {
        return g_strdup_printf("%s", VPN_STORAGEDIR);
 }
@@ -476,31 +434,31 @@ static int read_configs(void)
        DBG("path %s", path);
 
        dir = g_dir_open(path, 0, NULL);
-       if (dir != NULL) {
+       if (dir) {
                const gchar *file;
 
-               while ((file = g_dir_read_name(dir)) != NULL) {
+               while ((file = g_dir_read_name(dir))) {
                        GString *str;
                        gchar *ident;
 
-                       if (g_str_has_suffix(file, ".config") == FALSE)
+                       if (!g_str_has_suffix(file, ".config"))
                                continue;
 
                        ident = g_strrstr(file, ".config");
-                       if (ident == NULL)
+                       if (!ident)
                                continue;
 
                        str = g_string_new_len(file, ident - file);
-                       if (str == NULL)
+                       if (!str)
                                continue;
 
                        ident = g_string_free(str, FALSE);
 
-                       if (validate_ident(ident) == TRUE) {
+                       if (validate_ident(ident)) {
                                struct vpn_config *config;
 
                                config = create_config(ident);
-                               if (config != NULL)
+                               if (config)
                                        load_config(config, path, ADD);
                        } else {
                                connman_error("Invalid config ident %s", ident);
@@ -521,46 +479,58 @@ static void config_notify_handler(struct inotify_event *event,
 {
        char *ext;
 
-       if (ident == NULL)
+       if (!ident)
                return;
 
-       if (g_str_has_suffix(ident, ".config") == FALSE)
+       if (!g_str_has_suffix(ident, ".config"))
                return;
 
        ext = g_strrstr(ident, ".config");
-       if (ext == NULL)
+       if (!ext)
                return;
 
        *ext = '\0';
 
-       if (validate_ident(ident) == FALSE) {
+       if (!validate_ident(ident)) {
                connman_error("Invalid config ident %s", ident);
                return;
        }
 
        if (event->mask & IN_CREATE)
-               create_config(ident);
+               return;
+
+       if (event->mask & (IN_DELETE | IN_MOVED_FROM)) {
+               g_hash_table_remove(config_table, ident);
+               return;
+       }
 
-       if (event->mask & IN_MODIFY) {
+       if (event->mask & (IN_MODIFY | IN_MOVED_TO)) {
                struct vpn_config *config;
+               char *path = get_dir();
 
                config = g_hash_table_lookup(config_table, ident);
-               if (config != NULL) {
-                       char *path = get_dir();
-
+               if (config) {
                        g_hash_table_remove_all(config->provider_table);
                        load_config(config, path, REMOVE);
 
                        /* Re-scan the config file for any changes */
                        g_hash_table_remove_all(config->provider_table);
                        load_config(config, path, ADD);
-
-                       g_free(path);
+               } else {
+                       /*
+                        * Inotify will send create event followed by modify
+                        * event for any config file that is copied to
+                        * monitored directory. So in practice we should just
+                        * ignore the create event and trust only the modify
+                        * one in order to avoid create/remove/create loop
+                        */
+                       config = create_config(ident);
+                       if (config)
+                               load_config(config, path, ADD);
                }
-       }
 
-       if (event->mask & IN_DELETE)
-               g_hash_table_remove(config_table, ident);
+               g_free(path);
+       }
 }
 
 int __vpn_config_init(void)
@@ -585,7 +555,7 @@ void __vpn_config_cleanup(void)
 
        DBG("");
 
-       cleanup = TRUE;
+       cleanup = true;
 
        connman_inotify_unregister(dir, config_notify_handler);
 
@@ -594,5 +564,33 @@ void __vpn_config_cleanup(void)
        g_hash_table_destroy(config_table);
        config_table = NULL;
 
-       cleanup = FALSE;
+       cleanup = false;
+}
+
+char *__vpn_config_get_string(GKeyFile *key_file,
+       const char *group_name, const char *key, GError **error)
+{
+       char *str = g_key_file_get_string(key_file, group_name, key, error);
+       if (!str)
+               return NULL;
+
+       return g_strchomp(str);
+}
+
+char **__vpn_config_get_string_list(GKeyFile *key_file,
+       const char *group_name, const char *key, gsize *length, GError **error)
+{
+       char **p;
+       char **strlist = g_key_file_get_string_list(key_file, group_name, key,
+               length, error);
+       if (!strlist)
+               return NULL;
+
+       p = strlist;
+       while (*p) {
+               *p = g_strstrip(*p);
+               p++;
+       }
+
+       return strlist;
 }