Fixed format error
[platform/core/connectivity/net-config.git] / src / wifi-eap-config.c
old mode 100644 (file)
new mode 100755 (executable)
index 1a47507..5b40642
@@ -1,7 +1,7 @@
 /*
  * Network Configuration Module
  *
- * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  *
  */
 
+#include <errno.h>
 #include <stdio.h>
 #include <unistd.h>
+#include <sys/stat.h>
 
-#include "wifi-eap-config.h"
 #include "log.h"
-#include "wifi.h"
-
-static char *__get_ssid(const char *name)
+#include "util.h"
+#include "netdbus.h"
+#include "wifi-agent.h"
+#include "wifi-state.h"
+#include "wifi-config.h"
+#include "wifi-eap-config.h"
+#include "neterror.h"
+
+#define CONNMAN_CONFIG_FIELD_TYPE                      "Type"
+#define CONNMAN_CONFIG_FIELD_NAME                      "Name"
+#define CONNMAN_CONFIG_FIELD_SSID                      "SSID"
+#define CONNMAN_CONFIG_FIELD_EAP_METHOD                "EAP"
+#define CONNMAN_CONFIG_FIELD_IDENTITY          "Identity"
+#define CONNMAN_CONFIG_FIELD_PASSPHRASE                "Passphrase"
+#define CONNMAN_CONFIG_FIELD_PHASE2                    "Phase2"
+#define CONNMAN_CONFIG_FIELD_CA_CERT_FILE                      "CACertFile"
+#define CONNMAN_CONFIG_FIELD_CLIENT_CERT_FILE          "ClientCertFile"
+#define CONNMAN_CONFIG_FIELD_PVT_KEY_FILE                      "PrivateKeyFile"
+#define CONNMAN_CONFIG_FIELD_PVT_KEY_PASSPHRASE                "PrivateKeyPassphrase"
+#define CONNMAN_CONFIG_FIELD_KEYMGMT_TYPE                      "KeymgmtType"
+
+static char *__get_encoded_ssid(const char *name)
 {
-       char *buf = NULL;
-       char buf_tmp[32] = {0,};
-       int i = 0;
-       int len = 0;
+       char *str = NULL;
+       char *pstr = NULL;
+       int i = 0, len = 0;
 
-       if (NULL == name)
+       if (name == NULL)
                return NULL;
 
        len = strlen(name);
 
-       buf = g_try_malloc0(len * 2 + 1);
-       if (buf == NULL)
+       str = g_try_malloc0(len * 2 + 1);
+       if (str == NULL)
                return NULL;
 
+       pstr = str;
        for (i = 0; i < len; i++) {
-               snprintf(buf_tmp, 3, "%02x", name[i]);
-               strcat(buf, buf_tmp);
+               g_snprintf(pstr, 3, "%02x", name[i]);
+               pstr += 2;
        }
 
-       DBG("SSID - [%s]\n", buf);
-
-       return buf;
+       return str;
 }
 
-static gboolean __config_save(GKeyFile *keyfile, char *file_name)
+static int __config_save(const char *ssid, GKeyFile *keyfile)
 {
        gchar *data = NULL;
+       gchar *config_file = NULL;
        gsize length = 0;
        FILE *file = NULL;
-       int ret = TRUE;
+       int err = 0;
+
+       config_file = g_strdup_printf("%s/%s.config", CONNMAN_STORAGEDIR, ssid);
+       if (config_file == NULL) {
+               err = -ENOMEM;
+               goto out;
+       }
 
        data = g_key_file_to_data(keyfile, &length, NULL);
-       DBG("Data lenght-[%d]", length);
 
-       file = fopen(file_name, "w");
-       if (NULL == file) {
-               DBG("fopen() fails!");
-               ret = FALSE;
-       } else {
-               fputs(data, file);
-               fclose(file);
-               DBG("Wrote data successfully to [%s] file!", file_name);
+       file = fopen(config_file, "w");
+       if (file == NULL) {
+               ERR("Failed to open %s", config_file);
+
+               err = -EIO;
+               goto out;
        }
 
+       /* Do POSIX file operation to create and remove config files,
+        * Do not use g_file_set_contents, it breaks inotify operations */
+       if (data && fputs(data, file) < 0) {
+               ERR("Failed to write %s", config_file);
+
+               err = -EIO;
+               goto out;
+       }
+
+out:
+       if (file != NULL)
+               fclose(file);
+
        g_free(data);
+       g_free(config_file);
 
-       return ret;
+       return err;
 }
 
-static gboolean __config_delete(const char *ssid)
+static int __config_delete(const char *ssid)
 {
+       int err = 0;
+       gchar *group_name = NULL;
        gchar *config_file = NULL;
-       gboolean ret = FALSE;
+       gchar *dirname = NULL;
+       gchar *cert_path = NULL;
+       GKeyFile *keyfile = NULL;
+       GError *error = NULL;
 
-       config_file = g_strdup_printf("%s/%s.config", CONNMAN_STORAGEDIR,
-                       ssid);
-       if(config_file == NULL)
-               return FALSE;
+       config_file = g_strdup_printf("%s/%s.config", CONNMAN_STORAGEDIR, ssid);
+       if (config_file == NULL)
+               return -ENOMEM;
+
+       keyfile = g_key_file_new();
 
-       if (g_file_test(config_file, G_FILE_TEST_EXISTS) == FALSE) {
-               ret = TRUE;
-       } else if (g_file_test(config_file, G_FILE_TEST_IS_REGULAR) == TRUE) {
-               unlink(config_file);
-               ret = TRUE;
+       if (g_key_file_load_from_file(keyfile, config_file, 0, &error) != TRUE) {
+               ERR("Unable to load %s[%s]", config_file, error->message);
+               g_clear_error(&error);
+
+               err = -EIO;
+               goto out;
+       }
+
+       group_name = g_strdup_printf("service_%s", ssid);
+
+       cert_path = g_key_file_get_string(keyfile, group_name,
+                       CONNMAN_CONFIG_FIELD_CA_CERT_FILE, NULL);
+       DBG("Temporal %s", cert_path);
+       if (cert_path != NULL && remove(cert_path) != 0)
+               ERR("Failed to remove %s", cert_path);
+       g_free(cert_path);
+
+       cert_path = g_key_file_get_string(keyfile, group_name,
+                       CONNMAN_CONFIG_FIELD_CLIENT_CERT_FILE, NULL);
+       DBG("Temporal %s", cert_path);
+       if (cert_path != NULL && remove(cert_path) != 0)
+               ERR("Failed to remove %s", cert_path);
+       g_free(cert_path);
+
+       cert_path = g_key_file_get_string(keyfile, group_name,
+                       CONNMAN_CONFIG_FIELD_PVT_KEY_FILE, NULL);
+       DBG("Temporal %s", cert_path);
+       if (cert_path != NULL && remove(cert_path) != 0)
+               ERR("Failed to remove %s", cert_path);
+       g_free(cert_path);
+
+       cert_path = g_key_file_get_string(keyfile, group_name,
+                       CONNMAN_CONFIG_FIELD_PVT_KEY_PASSPHRASE, NULL);
+       DBG("Temporal %s", cert_path);
+       if (cert_path != NULL && remove(cert_path) != 0)
+               ERR("Failed to remove %s", cert_path);
+       g_free(cert_path);
+
+       dirname = g_strdup_printf("%s/%s", WIFI_CERT_STORAGEDIR, ssid);
+       if (dirname != NULL) {
+               if (g_file_test(dirname, G_FILE_TEST_EXISTS) == TRUE)
+                       if (g_file_test(dirname, G_FILE_TEST_IS_DIR) == TRUE)
+                               rmdir(dirname);
+
+               g_free(dirname);
        }
 
+       if (remove(config_file) != 0) {
+               err = -EIO;
+               goto out;
+       }
+
+out:
+       g_key_file_free(keyfile);
        g_free(config_file);
+       g_free(group_name);
 
-       return ret;
+       return err;
 }
 
-gboolean netconfig_iface_wifi_create_config(NetconfigWifi *wifi,
-               GHashTable *fields, GError **error)
+static gboolean __netconfig_copy_config(const char *src, const char *dst)
 {
-       DBG("netconfig_iface_wifi_create_config");
-       g_return_val_if_fail(wifi != NULL, FALSE);
+       gchar *buf = NULL;
+       gsize length = 0;
+       GError *error = NULL;
+       gboolean result;
+
+       result = g_file_get_contents(src, &buf, &length, &error);
+       if (result != TRUE) {
+               ERR("Failed to read [%s]", error->message);
+               g_error_free(error);
+
+               return result;
+       }
+
+       result = g_file_set_contents(dst, buf, length, &error);
+       if (result != TRUE) {
+               ERR("Failed to write [%s]", error->message);
+               g_error_free(error);
+       }
+
+       INFO("Successfully installed[%zd]", length);
+       g_free(buf);
 
-       gboolean ret = TRUE;
+       if (remove(src) != 0)
+               WARN("Failed to remove %s", src);
+
+       return result;
+}
+
+static gboolean __netconfig_create_config(GVariant *fields)
+{
        GKeyFile *keyfile = NULL;
-       GHashTableIter iter;
-       gpointer field, value;
-       gchar *file_name = NULL;
-       gchar *ssid_hex = NULL;
-       gchar *grp_name = NULL;
-
-       g_hash_table_iter_init(&iter, fields);
-       while (g_hash_table_iter_next(&iter, &field, &value)) {
-               if (NULL != value) {
-                       if (!strcmp(field, CONNMAN_CONFIG_FIELD_NAME)) {
-                               ssid_hex = __get_ssid(value);
+       GVariantIter *iter;
+       gchar *encoded_ssid = NULL;
+       gchar *dirname = NULL;
+       gchar *group_name = NULL;
+       gchar *field, *value;
+       gboolean updated = FALSE;
+       gchar *cert_file = NULL;
+       gchar *cert_path = NULL;
+       int err = 0;
+
+       g_variant_get(fields, "a{ss}", &iter);
+       while (g_variant_iter_loop(iter, "{ss}", &field, &value)) {
+               if (value != NULL) {
+                       if (g_strcmp0(field, CONNMAN_CONFIG_FIELD_NAME) == 0) {
+                               encoded_ssid = __get_encoded_ssid(value);
+
+                               g_free(value);
+                               g_free(field);
                                break;
-                       } else if (!strcmp(field, CONNMAN_CONFIG_FIELD_SSID)) {
-                               ssid_hex = g_strdup_printf("%s",
-                                               (gchar *)value);
+                       } else if (g_strcmp0(field, CONNMAN_CONFIG_FIELD_SSID) == 0) {
+                               encoded_ssid = g_strdup(value);
+
+                               g_free(field);
+                               g_free(value);
                                break;
                        }
                }
        }
 
-       if (NULL == ssid_hex) {
-               DBG("Fail! Could not fetch the ssid");
-               return FALSE;
+       if (encoded_ssid == NULL) {
+               ERR("Failed to fetch SSID");
+               goto out;
        }
 
        /* Create unique service group name */
-       grp_name = g_strdup_printf("service_%s", ssid_hex);
-       if(NULL == grp_name) {
-               DBG("Fail! Could not create the service group name");
-               g_free(ssid_hex);
-               return FALSE;
+       group_name = g_strdup_printf("service_%s", encoded_ssid);
+       if (group_name == NULL) {
+               ERR("Failed to create service group name");
+               goto out;
        }
 
        keyfile = g_key_file_new();
-       if (NULL == keyfile) {
-               DBG("g_key_file_new() fails!");
-               g_free(grp_name);
-               g_free(ssid_hex);
-               return FALSE;
+       if (keyfile == NULL) {
+               ERR("Failed to g_key_file_new");
+               goto out;
        }
 
-       g_hash_table_iter_init(&iter, fields);
-       while (g_hash_table_iter_next(&iter, &field, &value)) {
-               DBG("Field - [%s] Value - [%s]", field, value);
+       g_variant_iter_free(iter);
+
+       g_variant_get(fields, "a{ss}", &iter);
+       while (g_variant_iter_loop(iter, "{ss}", &field, &value)) {
+               if (g_strcmp0(field, CONNMAN_CONFIG_FIELD_SSID) == 0 ||
+                               g_strcmp0(field, CONNMAN_CONFIG_FIELD_EAP_METHOD) == 0 ||
+                               g_strcmp0(field, CONNMAN_CONFIG_FIELD_PHASE2) ||
+                               g_strcmp0(field, CONNMAN_CONFIG_FIELD_KEYMGMT_TYPE) == 0) {
+                       DBG("field: %s, value: %s", field, value);
+
+                       if (value != NULL)
+                               g_key_file_set_string(keyfile, group_name, field, value);
+               } else if (g_strcmp0(field, CONNMAN_CONFIG_FIELD_CA_CERT_FILE) == 0 ||
+                               g_strcmp0(field, CONNMAN_CONFIG_FIELD_CLIENT_CERT_FILE) == 0 ||
+                               g_strcmp0(field, CONNMAN_CONFIG_FIELD_PVT_KEY_FILE) == 0 ||
+                               g_strcmp0(field, CONNMAN_CONFIG_FIELD_PVT_KEY_PASSPHRASE) == 0) {
+                       if (value != NULL) {
+                               cert_file = strrchr(value, '/');
+                               if (cert_file == NULL) {
+                                       ERR("Failed to get cert file: %s", value);
+                                       g_free(field);
+                                       g_free(value);
+                                       goto out;
+                               }
+
+                               cert_file++;
+                               DBG("field: %s, value: %s", field, cert_file);
+
+                               dirname = g_strdup_printf("%s/%s",
+                                               WIFI_CERT_STORAGEDIR, encoded_ssid);
+                               if (dirname == NULL) {
+                                       ERR("Failed to create dirname");
+                                       g_free(field);
+                                       g_free(value);
+                                       goto out;
+                               }
+                               if (g_file_test(dirname, G_FILE_TEST_IS_DIR) != TRUE) {
+                                       if (mkdir(dirname, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP |
+                                                       S_IXGRP | S_IROTH | S_IXOTH) < 0) {
+                                               if (errno != EEXIST) {
+                                                       g_free(dirname);
+                                                       g_free(field);
+                                                       g_free(value);
+                                                       goto out;
+                                               }
+                                       }
+                               }
+                               g_free(dirname);
+
+                               cert_path = g_strdup_printf("%s/%s/%s",
+                                               WIFI_CERT_STORAGEDIR, encoded_ssid, cert_file);
+                               if (cert_path == NULL) {
+                                       ERR("Failed to create cert path");
+                                       g_free(field);
+                                       g_free(value);
+                                       goto out;
+                               }
+                               if (__netconfig_copy_config(value, cert_path) != TRUE) {
+                                       ERR("Failed to read cert file %s", value);
+                                       g_free(cert_path);
+                                       g_free(field);
+                                       g_free(value);
+                                       goto out;
+                               }
+
+                               g_key_file_set_string(keyfile, group_name, field, cert_path);
+                               g_free(cert_path);
+                       }
+               } else {
+                       DBG("field: %s, value: %s", field, value);
 
-               if (NULL != value)
-                       g_key_file_set_string(keyfile, grp_name, field, value);
+                       if (value != NULL)
+                               g_key_file_set_string(keyfile, group_name, field, value);
+               }
        }
 
-       file_name = g_strdup_printf("%s/%s.config", CONNMAN_STORAGEDIR,
-                       ssid_hex);
-       if(NULL == file_name) {
-               DBG("g_strdup_printf() fails. Could not save config!");
+       err = __config_save((const char *)encoded_ssid, keyfile);
+       if (err < 0)
+               ERR("Failed to create configuration %s[%d]", encoded_ssid, err);
+       else {
+               DBG("Successfully created %s", encoded_ssid);
+               updated = TRUE;
+       }
+
+out:
+       if (keyfile)
                g_key_file_free(keyfile);
-               g_free(grp_name);
-               g_free(ssid_hex);
-               return FALSE;
+
+       g_variant_iter_free(iter);
+
+       g_free(group_name);
+       g_free(encoded_ssid);
+
+       return updated;
+}
+
+static gboolean _delete_configuration(const gchar *profile)
+{
+       gboolean ret = FALSE;
+       gchar *config_id = NULL;
+
+       ret = wifi_config_get_config_id(profile, &config_id);
+       if (ret != TRUE) {
+               ERR("Fail to get config_id from [%s]", profile);
+               return ret;
        }
+       ERR("get config_id [%s] from [%s]", config_id, profile);
 
-       ret = __config_save(keyfile, file_name);
-       if (FALSE == ret)
-               DBG("Could not save config!");
-       else
-               DBG("Saved config in [%s] successfully", file_name);
+       ret = wifi_config_remove_configuration(config_id);
+       if (ret != TRUE)
+               ERR("Fail to wifi_config_remove_configuration [%s]", config_id);
 
-       g_key_file_free(keyfile);
-       g_free(file_name);
-       g_free(grp_name);
-       g_free(ssid_hex);
+       if (config_id != NULL)
+               g_free(config_id);
 
        return ret;
 }
 
-gboolean netconfig_iface_wifi_delete_config(NetconfigWifi *wifi,
-               gchar *profile, GError **error)
+static gboolean __netconfig_delete_config(const char *profile)
 {
-       DBG("netconfig_iface_wifi_delete_config");
-       g_return_val_if_fail(wifi != NULL, FALSE);
-
-       gboolean ret = TRUE;
-       char *str1 = NULL;
-       char *str2 = NULL;
-       char *str3 = NULL;
-       char ssid[512] = "";
+       char *wifi_ident = NULL;
+       char *essid = NULL;
+       char *mode = NULL;
+       char *ssid = NULL;
        int ssid_len = 0;
+       int err = 0;
 
-       str1 = strstr(profile, "wifi_");
-       if (NULL != str1) {
-               str2 = strchr(str1 + 5, '_');
-               if (NULL != str2) {
-                       str3 = strchr(str2 + 1, '_');
-                       ssid_len = str3 - str2 - 1;
-                       strncpy(ssid, str2 + 1, ssid_len);
-                       DBG("ssid_len - [%d] SSID - [%s]", ssid_len, ssid);
-
-                       ret = __config_delete(ssid);
-                       if (TRUE == ret)
-                               DBG("Deleted the config file successfully");
-                       else
-                               DBG("Deletion of config file failed");
-               } else {
-                       DBG("Fetching of SSID fails");
+       if (NULL == profile) {
+               ERR("Invalid profile name");
+               return FALSE;
+       }
+
+       if (_delete_configuration(profile) != TRUE)
+               ERR("Fail to delete configuration [%s]", profile);
+
+       wifi_ident = strstr(profile, "wifi_");
+       if (wifi_ident == NULL) {
+               ERR("Invalid profile name");
+               return FALSE;
+       }
+
+       essid = strchr(wifi_ident + 5, '_');
+       if (essid == NULL) {
+               ERR("Invalid profile name");
+               return FALSE;
+       }
+
+       essid++;
+       mode = strchr(essid, '_');
+
+       ssid_len = mode - essid;
+
+       ssid = g_try_malloc0(ssid_len + 1);
+       if (ssid == NULL) {
+               ERR("Memory allocation failed");
+               return FALSE;
+       }
+
+       g_strlcpy(ssid, essid, ssid_len + 1); /* include NULL-terminated */
+       err = __config_delete((const char *)ssid);
+       if (err < 0) {
+               ERR("Failed to delete configuration %s[%d]", ssid, err);
+               g_free(ssid);
+               return FALSE;
+       }
+
+       DBG("Successfully deleted %s with length %d", ssid, ssid_len);
+
+       g_free(ssid);
+       return TRUE;
+}
+
+static void __netconfig_eap_state(
+               wifi_service_state_e state, void *user_data);
+
+static wifi_state_notifier netconfig_eap_notifier = {
+               .wifi_state_changed = __netconfig_eap_state,
+               .user_data = NULL,
+};
+
+static void __netconfig_eap_state(
+               wifi_service_state_e state, void *user_data)
+{
+       const char *wifi_profile = (const char *)user_data;
+
+       if (wifi_profile == NULL) {
+               wifi_state_notifier_unregister(&netconfig_eap_notifier);
+               return;
+       }
+
+       if (state != NETCONFIG_WIFI_CONNECTED && state != NETCONFIG_WIFI_FAILURE)
+               return;
+
+       if (state == NETCONFIG_WIFI_FAILURE)
+               __netconfig_delete_config(wifi_profile);
+
+       g_free(netconfig_eap_notifier.user_data);
+       netconfig_eap_notifier.user_data = NULL;
+
+       wifi_state_notifier_unregister(&netconfig_eap_notifier);
+}
+
+gboolean handle_create_eap_config(Wifi *wifi, GDBusMethodInvocation *context,
+               const gchar *service, GVariant *fields)
+{
+       gboolean updated = FALSE;
+       gboolean result = FALSE;
+
+       g_return_val_if_fail(wifi != NULL, TRUE);
+
+       DBG("Set agent fields for %s", service);
+
+       if (netconfig_is_wifi_profile(service) != TRUE) {
+               netconfig_error_dbus_method_return(context, NETCONFIG_ERROR_WRONG_PROFILE, "InvalidService");
+               return TRUE;
+       }
+
+       updated = __netconfig_create_config(fields);
+       if (updated == TRUE) {
+               wifi_complete_create_eap_config(wifi, context);
+
+               if (g_strstr_len(service, strlen(service), "_hidden_") != NULL) {
+                       GVariantIter *iter;
+                       char *field, *value;
+                       const char *name = NULL;
+                       const char *identity = NULL;
+                       const char *passphrase = NULL;
+
+                       g_variant_get(fields, "a{ss}", &iter);
+
+                       while (g_variant_iter_loop(iter, "{ss}", &field, &value)) {
+                               if (g_strcmp0(field, CONNMAN_CONFIG_FIELD_NAME) == 0)
+                                       name = (const char *)value;
+                               else if (g_strcmp0(field, CONNMAN_CONFIG_FIELD_SSID) == 0)
+                                       name = (const char *)value;
+                               else if (g_strcmp0(field, CONNMAN_CONFIG_FIELD_IDENTITY) == 0)
+                                       identity = (const char *)value;
+                               else if (g_strcmp0(field, CONNMAN_CONFIG_FIELD_PASSPHRASE) == 0)
+                                       passphrase = (const char *)value;
+                       }
+
+                       netconfig_wifi_set_agent_field_for_eap_network(
+                                                                       name, identity, passphrase);
+
+                       g_variant_iter_free(iter);
                }
+
+               result = netconfig_invoke_dbus_method_nonblock(CONNMAN_SERVICE,
+                               service, CONNMAN_SERVICE_INTERFACE, "Connect",
+                               NULL, __netconfig_wifi_connect_reply);
+
+               if (netconfig_eap_notifier.user_data != NULL) {
+                       g_free(netconfig_eap_notifier.user_data);
+                       netconfig_eap_notifier.user_data = NULL;
+
+                       wifi_state_notifier_unregister(&netconfig_eap_notifier);
+               }
+
+               netconfig_eap_notifier.user_data = g_strdup(service);
+               wifi_state_notifier_register(&netconfig_eap_notifier);
        } else {
-               DBG("Fetching of SSID fails");
+               netconfig_error_dbus_method_return(context, NETCONFIG_ERROR_INVALID_PARAMETER, "InvalidArguments");
        }
 
-       return ret;
+       if (result != TRUE)
+               ERR("Fail to connect %s", service);
+
+       return TRUE;
+}
+
+gboolean handle_delete_eap_config(Wifi *wifi, GDBusMethodInvocation *context,
+               const gchar *profile)
+{
+       g_return_val_if_fail(wifi != NULL, TRUE);
+
+       wifi_complete_delete_eap_config(wifi, context);
+
+       __netconfig_delete_config((const char *)profile);
+
+       return TRUE;
 }