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-config.h"
31 #include "wifi-eap-config.h"
32 #include "network-state.h"
35 #define CONNMAN_CONFIG_FIELD_TYPE "Type"
36 #define CONNMAN_CONFIG_FIELD_NAME "Name"
37 #define CONNMAN_CONFIG_FIELD_SSID "SSID"
38 #define CONNMAN_CONFIG_FIELD_EAP_METHOD "EAP"
39 #define CONNMAN_CONFIG_FIELD_IDENTITY "Identity"
40 #define CONNMAN_CONFIG_FIELD_PASSPHRASE "Passphrase"
41 #define CONNMAN_CONFIG_FIELD_PHASE2 "Phase2"
42 #define CONNMAN_CONFIG_FIELD_CA_CERT_FILE "CACertFile"
43 #define CONNMAN_CONFIG_FIELD_CLIENT_CERT_FILE "ClientCertFile"
44 #define CONNMAN_CONFIG_FIELD_PVT_KEY_FILE "PrivateKeyFile"
45 #define CONNMAN_CONFIG_FIELD_PVT_KEY_PASSPHRASE "PrivateKeyPassphrase"
46 #define CONNMAN_CONFIG_FIELD_KEYMGMT_TYPE "KeymgmtType"
48 static char *__get_encoded_ssid(const char *name)
59 str = g_try_malloc0(len * 2 + 1);
64 for (i = 0; i < len; i++) {
65 g_snprintf(pstr, 3, "%02x", name[i]);
72 static int __config_save(const char *mac_addr, GKeyFile *keyfile)
75 gchar *config_file = NULL;
80 config_file = g_strdup_printf("%s/%s.config", CONNMAN_STORAGEDIR, mac_addr);
81 if (config_file == NULL) {
86 data = g_key_file_to_data(keyfile, &length, NULL);
88 file = fopen(config_file, "w");
90 ERR("Failed to open %s", config_file);
96 /* Do POSIX file operation to create and remove config files,
97 * Do not use g_file_set_contents, it breaks inotify operations */
98 if (data && fputs(data, file) < 0) {
99 ERR("Failed to write %s", config_file);
115 static int __config_delete(const char *mac_addr, const char *ssid)
118 gchar *group_name = NULL;
119 gchar *config_file = NULL;
120 gchar *dirname = NULL;
121 gchar *cert_path = NULL;
122 GKeyFile *keyfile = NULL;
123 GError *error = NULL;
125 config_file = g_strdup_printf("%s/%s.config", CONNMAN_STORAGEDIR, mac_addr);
126 if (config_file == NULL)
129 keyfile = g_key_file_new();
131 if (g_key_file_load_from_file(keyfile, config_file, 0, &error) != TRUE) {
132 ERR("Unable to load %s[%s]", config_file, error->message);
133 g_clear_error(&error);
139 group_name = g_strdup_printf("service_%s", ssid);
141 cert_path = g_key_file_get_string(keyfile, group_name,
142 CONNMAN_CONFIG_FIELD_CA_CERT_FILE, NULL);
143 DBG("Temporal %s", cert_path);
144 if (cert_path != NULL && remove(cert_path) != 0)
145 ERR("Failed to remove %s", cert_path);
148 cert_path = g_key_file_get_string(keyfile, group_name,
149 CONNMAN_CONFIG_FIELD_CLIENT_CERT_FILE, NULL);
150 DBG("Temporal %s", cert_path);
151 if (cert_path != NULL && remove(cert_path) != 0)
152 ERR("Failed to remove %s", cert_path);
155 cert_path = g_key_file_get_string(keyfile, group_name,
156 CONNMAN_CONFIG_FIELD_PVT_KEY_FILE, NULL);
157 DBG("Temporal %s", cert_path);
158 if (cert_path != NULL && remove(cert_path) != 0)
159 ERR("Failed to remove %s", cert_path);
162 cert_path = g_key_file_get_string(keyfile, group_name,
163 CONNMAN_CONFIG_FIELD_PVT_KEY_PASSPHRASE, NULL);
164 DBG("Temporal %s", cert_path);
165 if (cert_path != NULL && remove(cert_path) != 0)
166 ERR("Failed to remove %s", cert_path);
169 dirname = g_strdup_printf("%s/%s_%s", WIFI_CERT_STORAGEDIR, mac_addr, ssid);
170 if (dirname != NULL) {
171 if (g_file_test(dirname, G_FILE_TEST_EXISTS) == TRUE)
172 if (g_file_test(dirname, G_FILE_TEST_IS_DIR) == TRUE)
178 if (remove(config_file) != 0) {
184 g_key_file_free(keyfile);
191 static gboolean __netconfig_copy_config(const char *src, const char *dst)
195 GError *error = NULL;
198 result = g_file_get_contents(src, &buf, &length, &error);
199 if (result != TRUE) {
200 ERR("Failed to read [%s]", error->message);
206 result = g_file_set_contents(dst, buf, length, &error);
207 if (result != TRUE) {
208 ERR("Failed to write [%s]", error->message);
212 INFO("Successfully installed[%zd]", length);
215 if (remove(src) != 0)
216 WARN("Failed to remove %s", src);
221 static gboolean __netconfig_create_config(const char *profile, GVariant *fields)
223 GKeyFile *keyfile = NULL;
225 gchar *encoded_ssid = NULL;
226 gchar *dirname = NULL;
227 gchar *group_name = NULL;
228 gchar *field, *value;
229 gboolean updated = FALSE;
230 gchar *cert_file = NULL;
231 gchar *cert_path = NULL;
232 char mac_str[13] = { 0, };
235 g_variant_get(fields, "a{ss}", &iter);
236 while (g_variant_iter_loop(iter, "{ss}", &field, &value)) {
238 if (g_strcmp0(field, CONNMAN_CONFIG_FIELD_NAME) == 0) {
239 encoded_ssid = __get_encoded_ssid(value);
244 } else if (g_strcmp0(field, CONNMAN_CONFIG_FIELD_SSID) == 0) {
245 encoded_ssid = g_strdup(value);
254 if (encoded_ssid == NULL) {
255 ERR("Failed to fetch SSID");
259 memcpy(mac_str, &profile[strlen(CONNMAN_WIFI_SERVICE_PROFILE_PREFIX)], 12);
262 /* Create unique service group name */
263 group_name = g_strdup_printf("service_%s", encoded_ssid);
264 if (group_name == NULL) {
265 ERR("Failed to create service group name");
269 keyfile = g_key_file_new();
270 if (keyfile == NULL) {
271 ERR("Failed to g_key_file_new");
275 g_variant_iter_free(iter);
277 g_variant_get(fields, "a{ss}", &iter);
278 while (g_variant_iter_loop(iter, "{ss}", &field, &value)) {
279 if (g_strcmp0(field, CONNMAN_CONFIG_FIELD_SSID) == 0 ||
280 g_strcmp0(field, CONNMAN_CONFIG_FIELD_EAP_METHOD) == 0 ||
281 g_strcmp0(field, CONNMAN_CONFIG_FIELD_PHASE2) ||
282 g_strcmp0(field, CONNMAN_CONFIG_FIELD_KEYMGMT_TYPE) == 0) {
284 g_key_file_set_string(keyfile, group_name, field, value);
285 } else if (g_strcmp0(field, CONNMAN_CONFIG_FIELD_CA_CERT_FILE) == 0 ||
286 g_strcmp0(field, CONNMAN_CONFIG_FIELD_CLIENT_CERT_FILE) == 0 ||
287 g_strcmp0(field, CONNMAN_CONFIG_FIELD_PVT_KEY_FILE) == 0 ||
288 g_strcmp0(field, CONNMAN_CONFIG_FIELD_PVT_KEY_PASSPHRASE) == 0) {
290 cert_file = strrchr(value, '/');
291 if (cert_file == NULL) {
292 ERR("Failed to get cert file: %s", value);
300 dirname = g_strdup_printf("%s/%s_%s", WIFI_CERT_STORAGEDIR,
301 mac_str, encoded_ssid);
302 if (dirname == NULL) {
303 ERR("Failed to create dirname");
308 if (g_file_test(dirname, G_FILE_TEST_IS_DIR) != TRUE) {
309 if (mkdir(dirname, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP |
310 S_IXGRP | S_IROTH | S_IXOTH) < 0) {
311 if (errno != EEXIST) {
321 cert_path = g_strdup_printf("%s/%s_%s/%s", WIFI_CERT_STORAGEDIR,
322 mac_str, encoded_ssid, cert_file);
323 if (cert_path == NULL) {
324 ERR("Failed to create cert path");
329 if (__netconfig_copy_config(value, cert_path) != TRUE) {
330 ERR("Failed to read cert file %s", value);
337 g_key_file_set_string(keyfile, group_name, field, cert_path);
342 g_key_file_set_string(keyfile, group_name, field, value);
346 err = __config_save(mac_str, keyfile);
348 ERR("Failed to create configuration %s[%d]", mac_str, err);
350 DBG("Successfully created %s", mac_str);
356 g_key_file_free(keyfile);
358 g_variant_iter_free(iter);
361 g_free(encoded_ssid);
366 static gboolean _delete_configuration(const char *interface_name, const char *profile)
368 gboolean ret = FALSE;
369 gchar *config_id = NULL;
371 ret = wifi_config_get_config_id(profile, &config_id);
373 ERR("Fail to get config_id from [%s]", profile);
376 ERR("get config_id [%s] from [%s]", config_id, profile);
378 ret = wifi_config_remove_configuration(interface_name, config_id);
380 ERR("Fail to wifi_config_remove_configuration [%s]", config_id);
382 if (config_id != NULL)
388 static gboolean __netconfig_delete_config(const char *profile)
390 char *wifi_ident = NULL;
396 const char *interface_name = NULL;
397 char mac_str[13] = { 0, };
399 if (NULL == profile) {
400 ERR("Invalid profile name");
404 interface_name = netconfig_get_ifname(profile);
405 if (interface_name == NULL) {
406 ERR("Invalid profile name");
410 if (_delete_configuration(interface_name, profile) != TRUE)
411 ERR("Fail to delete configuration [%s]", profile);
413 wifi_ident = strstr(profile, "wifi_");
414 if (wifi_ident == NULL) {
415 ERR("Invalid profile name");
419 essid = strchr(wifi_ident + 5, '_');
421 ERR("Invalid profile name");
426 mode = strchr(essid, '_');
428 ssid_len = mode - essid;
430 ssid = g_try_malloc0(ssid_len + 1);
432 ERR("Memory allocation failed");
436 g_strlcpy(ssid, essid, ssid_len + 1); /* include NULL-terminated */
438 memcpy(mac_str, &profile[strlen(CONNMAN_WIFI_SERVICE_PROFILE_PREFIX)], 12);
441 err = __config_delete(mac_str, ssid);
443 ERR("Failed to delete configuration %s[%d]", ssid, err);
448 DBG("Successfully deleted %s with length %d", ssid, ssid_len);
454 static void __netconfig_eap_state(wifi_state_notifier_s *notifier,
455 char *service, wifi_service_state_e state, void *user_data)
457 if (notifier == NULL)
460 if (service == NULL) {
461 wifi_state_notifier_unregister(notifier);
462 g_free(notifier->service);
463 g_free(notifier->user_data);
468 if (state != NETCONFIG_WIFI_CONNECTED && state != NETCONFIG_WIFI_FAILURE)
471 if (state == NETCONFIG_WIFI_FAILURE)
472 __netconfig_delete_config(service);
474 wifi_state_notifier_unregister(notifier);
475 g_free(notifier->service);
476 g_free(notifier->user_data);
480 gboolean handle_create_eap_config(Wifi *wifi, GDBusMethodInvocation *context,
481 const gchar *service, GVariant *fields)
483 gboolean updated = FALSE;
484 gboolean result = FALSE;
485 wifi_state_notifier_s *state_notifier = NULL;
486 const char *interface_name = NULL;
488 g_return_val_if_fail(wifi != NULL, TRUE);
490 DBG("Set agent fields for %s", service);
492 if (netconfig_is_wifi_profile(service) != TRUE) {
493 netconfig_error_dbus_method_return(context,
494 NETCONFIG_ERROR_WRONG_PROFILE, "InvalidService");
498 interface_name = netconfig_get_ifname(service);
499 if (interface_name == NULL) {
500 netconfig_error_dbus_method_return(context,
501 NETCONFIG_ERROR_WRONG_PROFILE, "InvalidService");
505 updated = __netconfig_create_config(service, fields);
506 if (updated == TRUE) {
507 wifi_complete_create_eap_config(wifi, context);
509 if (g_strstr_len(service, strlen(service), "_hidden_") != NULL) {
512 const char *name = NULL;
513 const char *identity = NULL;
514 const char *passphrase = NULL;
516 g_variant_get(fields, "a{ss}", &iter);
518 while (g_variant_iter_loop(iter, "{ss}", &field, &value)) {
519 if (g_strcmp0(field, CONNMAN_CONFIG_FIELD_NAME) == 0)
520 name = (const char *)value;
521 else if (g_strcmp0(field, CONNMAN_CONFIG_FIELD_SSID) == 0)
522 name = (const char *)value;
523 else if (g_strcmp0(field, CONNMAN_CONFIG_FIELD_IDENTITY) == 0)
524 identity = (const char *)value;
525 else if (g_strcmp0(field, CONNMAN_CONFIG_FIELD_PASSPHRASE) == 0)
526 passphrase = (const char *)value;
529 netconfig_wifi_set_agent_field_for_eap_network(interface_name,
530 name, identity, passphrase);
532 g_variant_iter_free(iter);
535 result = netconfig_invoke_dbus_method_nonblock(CONNMAN_SERVICE,
536 service, CONNMAN_SERVICE_INTERFACE, "Connect",
537 NULL, __netconfig_wifi_connect_reply,
538 g_strdup(interface_name));
540 state_notifier = g_try_malloc0(sizeof(wifi_state_notifier_s));
541 if (state_notifier) {
542 state_notifier->notifier = state_notifier;
543 state_notifier->service = g_strdup(service);
544 state_notifier->wifi_state_changed = __netconfig_eap_state;
545 wifi_state_notifier_register(state_notifier);
548 netconfig_error_dbus_method_return(context, NETCONFIG_ERROR_INVALID_PARAMETER, "InvalidArguments");
552 ERR("Fail to connect %s", service);
557 gboolean handle_delete_eap_config(Wifi *wifi, GDBusMethodInvocation *context,
558 const gchar *profile)
560 g_return_val_if_fail(wifi != NULL, TRUE);
562 __netconfig_delete_config(profile);
564 wifi_complete_delete_eap_config(wifi, context);