2 * Network Configuration Module
4 * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved.
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
28 #include "wifi-agent.h"
29 #include "wifi-state.h"
30 #include "wifi-eap-config.h"
33 #define CONNMAN_CONFIG_FIELD_TYPE "Type"
34 #define CONNMAN_CONFIG_FIELD_NAME "Name"
35 #define CONNMAN_CONFIG_FIELD_SSID "SSID"
36 #define CONNMAN_CONFIG_FIELD_EAP_METHOD "EAP"
37 #define CONNMAN_CONFIG_FIELD_IDENTITY "Identity"
38 #define CONNMAN_CONFIG_FIELD_PASSPHRASE "Passphrase"
39 #define CONNMAN_CONFIG_FIELD_PHASE2 "Phase2"
40 #define CONNMAN_CONFIG_FIELD_CA_CERT_FILE "CACertFile"
41 #define CONNMAN_CONFIG_FIELD_CLIENT_CERT_FILE "ClientCertFile"
42 #define CONNMAN_CONFIG_FIELD_PVT_KEY_FILE "PrivateKeyFile"
43 #define CONNMAN_CONFIG_FIELD_PVT_KEY_PASSPHRASE "PrivateKeyPassphrase"
45 static char *__get_encoded_ssid(const char *name)
56 str = g_try_malloc0(len * 2 + 1);
61 for (i = 0; i < len; i++) {
62 g_snprintf(pstr, 3, "%02x", name[i]);
69 static int __config_save(const char *ssid, GKeyFile *keyfile)
72 gchar *config_file = NULL;
77 config_file = g_strdup_printf("%s/%s.config", CONNMAN_STORAGEDIR, ssid);
78 if (config_file == NULL) {
83 data = g_key_file_to_data(keyfile, &length, NULL);
85 file = fopen(config_file, "w");
87 ERR("Failed to open %s", config_file);
93 /* Do POSIX file operation to create and remove config files,
94 * Do not use g_file_set_contents, it breaks inotify operations */
95 if (fputs(data, file) < 0) {
96 ERR("Failed to write %s", config_file);
112 static int __config_delete(const char *ssid)
115 gchar *group_name = NULL;
116 gchar *config_file = NULL;
117 gchar *dirname = NULL;
118 gchar *cert_path = NULL;
119 GKeyFile *keyfile = NULL;
120 GError *error = NULL;
122 config_file = g_strdup_printf("%s/%s.config", CONNMAN_STORAGEDIR, ssid);
123 if (config_file == NULL)
126 keyfile = g_key_file_new();
128 if (g_key_file_load_from_file(keyfile, config_file, 0, &error) != TRUE) {
129 ERR("Unable to load %s[%s]", config_file, error->message);
130 g_clear_error(&error);
136 group_name = g_strdup_printf("service_%s", ssid);
138 cert_path = g_key_file_get_string(keyfile, group_name,
139 CONNMAN_CONFIG_FIELD_CA_CERT_FILE, NULL);
140 DBG("Temporal %s", cert_path);
141 if (cert_path != NULL && remove(cert_path) != 0)
142 ERR("Failed to remove %s", cert_path);
145 cert_path = g_key_file_get_string(keyfile, group_name,
146 CONNMAN_CONFIG_FIELD_CLIENT_CERT_FILE, NULL);
147 DBG("Temporal %s", cert_path);
148 if (cert_path != NULL && remove(cert_path) != 0)
149 ERR("Failed to remove %s", cert_path);
152 cert_path = g_key_file_get_string(keyfile, group_name,
153 CONNMAN_CONFIG_FIELD_PVT_KEY_FILE, NULL);
154 DBG("Temporal %s", cert_path);
155 if (cert_path != NULL && remove(cert_path) != 0)
156 ERR("Failed to remove %s", cert_path);
159 cert_path = g_key_file_get_string(keyfile, group_name,
160 CONNMAN_CONFIG_FIELD_PVT_KEY_PASSPHRASE, NULL);
161 DBG("Temporal %s", cert_path);
162 if (cert_path != NULL && remove(cert_path) != 0)
163 ERR("Failed to remove %s", cert_path);
166 dirname = g_strdup_printf("%s/%s", WIFI_CERT_STORAGEDIR, ssid);
167 if (dirname != NULL) {
168 if (g_file_test(dirname, G_FILE_TEST_EXISTS) == TRUE)
169 if (g_file_test(dirname, G_FILE_TEST_IS_DIR) == TRUE)
175 if (remove(config_file) != 0) {
181 g_key_file_free(keyfile);
188 static gboolean __netconfig_copy_config(const char *src, const char *dst)
192 GError *error = NULL;
195 result = g_file_get_contents(src, &buf, &length, &error);
196 if (result != TRUE) {
197 ERR("Failed to read %s[%s]", error->message);
203 result = g_file_set_contents(dst, buf, length, &error);
204 if (result != TRUE) {
205 ERR("Failed to write %s[%s]", error->message);
209 INFO("Successfully installed[%d]", length);
212 if (remove(src) != 0)
213 WARN("Failed to remove %s", src);
218 static gboolean __netconfig_create_config(GVariant *fields)
220 GKeyFile *keyfile = NULL;
222 gchar *encoded_ssid = NULL;
223 gchar *dirname = NULL;
224 gchar *group_name = NULL;
225 gchar *field, *value;
226 gboolean updated = FALSE;
227 gchar *cert_file = NULL;
228 gchar *cert_path = NULL;
231 g_variant_get(fields, "a{ss}", &iter);
232 while (g_variant_iter_loop(iter, "{ss}", &field, &value)) {
234 if (g_strcmp0(field, CONNMAN_CONFIG_FIELD_NAME) == 0) {
235 encoded_ssid = __get_encoded_ssid(value);
240 } else if (g_strcmp0(field, CONNMAN_CONFIG_FIELD_SSID) == 0) {
241 encoded_ssid = g_strdup(value);
250 if (encoded_ssid == NULL) {
251 ERR("Failed to fetch SSID");
255 /* Create unique service group name */
256 group_name = g_strdup_printf("service_%s", encoded_ssid);
257 if (group_name == NULL) {
258 ERR("Failed to create service group name");
262 keyfile = g_key_file_new();
263 if (keyfile == NULL) {
264 ERR("Failed to g_key_file_new");
268 g_variant_iter_free(iter);
270 g_variant_get(fields, "a{ss}", &iter);
271 while (g_variant_iter_loop(iter, "{ss}", &field, &value)) {
272 if (g_strcmp0(field, CONNMAN_CONFIG_FIELD_SSID) == 0 ||
273 g_strcmp0(field, CONNMAN_CONFIG_FIELD_EAP_METHOD) == 0 ||
274 g_strcmp0(field, CONNMAN_CONFIG_FIELD_PHASE2) == 0) {
275 DBG("field: %s, value: %s", field, value);
278 g_key_file_set_string(keyfile, group_name, field, value);
279 } else if (g_strcmp0(field, CONNMAN_CONFIG_FIELD_CA_CERT_FILE) == 0 ||
280 g_strcmp0(field, CONNMAN_CONFIG_FIELD_CLIENT_CERT_FILE) == 0 ||
281 g_strcmp0(field, CONNMAN_CONFIG_FIELD_PVT_KEY_FILE) == 0 ||
282 g_strcmp0(field, CONNMAN_CONFIG_FIELD_PVT_KEY_PASSPHRASE) == 0) {
284 cert_file = strrchr(value, '/');
285 if (cert_file == NULL) {
286 ERR("Failed to get cert file: %s", value);
291 DBG("field: %s, value: %s", field, cert_file);
293 dirname = g_strdup_printf("%s/%s",
294 WIFI_CERT_STORAGEDIR, encoded_ssid);
295 if (dirname == NULL) {
296 ERR("Failed to create dirname");
299 if (g_file_test(dirname, G_FILE_TEST_IS_DIR) != TRUE) {
300 if (mkdir(dirname, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP |
301 S_IXGRP | S_IROTH | S_IXOTH) < 0) {
302 if (errno != EEXIST) {
310 cert_path = g_strdup_printf("%s/%s/%s",
311 WIFI_CERT_STORAGEDIR, encoded_ssid, cert_file);
312 if (cert_path == NULL) {
313 ERR("Failed to create cert path");
316 if (__netconfig_copy_config(value, cert_path) != TRUE) {
317 ERR("Failed to read cert file %s", value);
322 g_key_file_set_string(keyfile, group_name, field, cert_path);
326 //DBG("field: %s, value:", field);
327 DBG("Temporal field: %s, value: %s", field, value);
330 g_key_file_set_string(keyfile, group_name, field, value);
334 err = __config_save((const char *)encoded_ssid, keyfile);
336 ERR("Failed to create configuration %s[%d]", encoded_ssid, err);
338 DBG("Successfully created %s", encoded_ssid);
344 g_key_file_free(keyfile);
346 g_variant_iter_free(iter);
355 g_free(encoded_ssid);
360 static gboolean __netconfig_delete_config(const char *profile)
362 char *wifi_ident = NULL;
369 if (NULL == profile) {
370 ERR("Invalid profile name");
374 wifi_ident = strstr(profile, "wifi_");
375 if (wifi_ident == NULL) {
376 ERR("Invalid profile name");
380 essid = strchr(wifi_ident + 5, '_');
382 ERR("Invalid profile name");
387 mode = strchr(essid, '_');
389 ssid_len = mode - essid;
391 ssid = g_try_malloc0(ssid_len + 1);
393 ERR("Memory allocation failed");
397 g_strlcpy(ssid, essid, ssid_len + 1); /* include NULL-terminated */
398 err = __config_delete((const char *)ssid);
400 ERR("Failed to delete configuration %s[%d]", ssid, err);
405 DBG("Successfully deleted %s with length %d", ssid, ssid_len);
411 static void __netconfig_eap_state(
412 enum netconfig_wifi_service_state state, void *user_data);
414 static struct netconfig_wifi_state_notifier netconfig_eap_notifier = {
415 .netconfig_wifi_state_changed = __netconfig_eap_state,
419 static void __netconfig_eap_state(
420 enum netconfig_wifi_service_state state, void *user_data)
422 const char *wifi_profile = (const char *)user_data;
424 if (wifi_profile == NULL) {
425 netconfig_wifi_state_notifier_unregister(&netconfig_eap_notifier);
429 if (state != NETCONFIG_WIFI_CONNECTED && state != NETCONFIG_WIFI_FAILURE)
432 if (state == NETCONFIG_WIFI_FAILURE)
433 __netconfig_delete_config(wifi_profile);
435 g_free(netconfig_eap_notifier.user_data);
436 netconfig_eap_notifier.user_data = NULL;
438 netconfig_wifi_state_notifier_unregister(&netconfig_eap_notifier);
441 gboolean handle_create_eap_config(Wifi *wifi, GDBusMethodInvocation *context,
442 const gchar *service, GVariant *fields)
444 gboolean updated = FALSE;
445 gboolean reply = FALSE;
446 gboolean result = FALSE;
448 g_return_val_if_fail(wifi != NULL, FALSE);
450 DBG("Set agent fields for %s", service);
452 if (netconfig_is_wifi_profile(service) != TRUE) {
453 netconfig_error_dbus_method_return(context, NETCONFIG_ERROR_WRONG_PROFILE, "InvalidService");
457 updated = __netconfig_create_config(fields);
458 if (updated == TRUE) {
459 wifi_complete_create_eap_config(wifi, context);
461 if (g_strstr_len(service, strlen(service), "_hidden_") != NULL) {
464 const char *name = NULL;
465 const char *identity = NULL;
466 const char *passphrase = NULL;
468 g_variant_get(fields, "a{ss}", &iter);
470 while (g_variant_iter_loop(iter, "{ss}", &field, &value)) {
471 if (g_strcmp0(field, CONNMAN_CONFIG_FIELD_NAME) == 0)
472 name = (const char *)value;
473 else if (g_strcmp0(field, CONNMAN_CONFIG_FIELD_SSID) == 0)
474 name = (const char *)value;
475 else if (g_strcmp0(field, CONNMAN_CONFIG_FIELD_IDENTITY) == 0)
476 identity = (const char *)value;
477 else if (g_strcmp0(field, CONNMAN_CONFIG_FIELD_PASSPHRASE) == 0)
478 passphrase = (const char *)value;
481 netconfig_wifi_set_agent_field_for_eap_network(
482 name, identity, passphrase);
484 g_variant_iter_free(iter);
487 result = netconfig_invoke_dbus_method_nonblock(CONNMAN_SERVICE,
488 service, CONNMAN_SERVICE_INTERFACE, "Connect", NULL, NULL);
490 if (netconfig_eap_notifier.user_data != NULL) {
491 g_free(netconfig_eap_notifier.user_data);
492 netconfig_eap_notifier.user_data = NULL;
494 netconfig_wifi_state_notifier_unregister(&netconfig_eap_notifier);
497 netconfig_eap_notifier.user_data = g_strdup(service);
498 netconfig_wifi_state_notifier_register(&netconfig_eap_notifier);
500 netconfig_error_dbus_method_return(context, NETCONFIG_ERROR_INVALID_PARAMETER, "InvalidArguments");
504 ERR("Fail to connect %s", service);
511 gboolean handle_delete_eap_config(Wifi *wifi, GDBusMethodInvocation *context,
512 const gchar *profile)
514 g_return_val_if_fail(wifi != NULL, FALSE);
516 wifi_complete_delete_eap_config(wifi, context);
518 gboolean ret = __netconfig_delete_config((const char *)profile);