Remove debug log for field value
[platform/core/connectivity/net-config.git] / src / wifi-eap-config.c
1 /*
2  * Network Configuration Module
3  *
4  * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved.
5  *
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
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
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.
17  *
18  */
19
20 #include <errno.h>
21 #include <stdio.h>
22 #include <unistd.h>
23 #include <sys/stat.h>
24
25 #include "log.h"
26 #include "util.h"
27 #include "netdbus.h"
28 #include "wifi-agent.h"
29 #include "wifi-state.h"
30 #include "wifi-config.h"
31 #include "wifi-eap-config.h"
32 #include "neterror.h"
33
34 #define CONNMAN_CONFIG_FIELD_TYPE                       "Type"
35 #define CONNMAN_CONFIG_FIELD_NAME                       "Name"
36 #define CONNMAN_CONFIG_FIELD_SSID                       "SSID"
37 #define CONNMAN_CONFIG_FIELD_EAP_METHOD         "EAP"
38 #define CONNMAN_CONFIG_FIELD_IDENTITY           "Identity"
39 #define CONNMAN_CONFIG_FIELD_PASSPHRASE         "Passphrase"
40 #define CONNMAN_CONFIG_FIELD_PHASE2                     "Phase2"
41 #define CONNMAN_CONFIG_FIELD_CA_CERT_FILE                       "CACertFile"
42 #define CONNMAN_CONFIG_FIELD_CLIENT_CERT_FILE           "ClientCertFile"
43 #define CONNMAN_CONFIG_FIELD_PVT_KEY_FILE                       "PrivateKeyFile"
44 #define CONNMAN_CONFIG_FIELD_PVT_KEY_PASSPHRASE         "PrivateKeyPassphrase"
45 #define CONNMAN_CONFIG_FIELD_KEYMGMT_TYPE                       "KeymgmtType"
46
47 static char *__get_encoded_ssid(const char *name)
48 {
49         char *str = NULL;
50         char *pstr = NULL;
51         int i = 0, len = 0;
52
53         if (name == NULL)
54                 return NULL;
55
56         len = strlen(name);
57
58         str = g_try_malloc0(len * 2 + 1);
59         if (str == NULL)
60                 return NULL;
61
62         pstr = str;
63         for (i = 0; i < len; i++) {
64                 g_snprintf(pstr, 3, "%02x", name[i]);
65                 pstr += 2;
66         }
67
68         return str;
69 }
70
71 static int __config_save(const char *ssid, GKeyFile *keyfile)
72 {
73         gchar *data = NULL;
74         gchar *config_file = NULL;
75         gsize length = 0;
76         FILE *file = NULL;
77         int err = 0;
78
79         config_file = g_strdup_printf("%s/%s.config", CONNMAN_STORAGEDIR, ssid);
80         if (config_file == NULL) {
81                 err = -ENOMEM;
82                 goto out;
83         }
84
85         data = g_key_file_to_data(keyfile, &length, NULL);
86
87         file = fopen(config_file, "w");
88         if (file == NULL) {
89                 ERR("Failed to open %s", config_file);
90
91                 err = -EIO;
92                 goto out;
93         }
94
95         /* Do POSIX file operation to create and remove config files,
96          * Do not use g_file_set_contents, it breaks inotify operations */
97         if (data && fputs(data, file) < 0) {
98                 ERR("Failed to write %s", config_file);
99
100                 err = -EIO;
101                 goto out;
102         }
103
104 out:
105         if (file != NULL)
106                 fclose(file);
107
108         g_free(data);
109         g_free(config_file);
110
111         return err;
112 }
113
114 static int __config_delete(const char *ssid)
115 {
116         int err = 0;
117         gchar *group_name = NULL;
118         gchar *config_file = NULL;
119         gchar *dirname = NULL;
120         gchar *cert_path = NULL;
121         GKeyFile *keyfile = NULL;
122         GError *error = NULL;
123
124         config_file = g_strdup_printf("%s/%s.config", CONNMAN_STORAGEDIR, ssid);
125         if (config_file == NULL)
126                 return -ENOMEM;
127
128         keyfile = g_key_file_new();
129
130         if (g_key_file_load_from_file(keyfile, config_file, 0, &error) != TRUE) {
131                 ERR("Unable to load %s[%s]", config_file, error->message);
132                 g_clear_error(&error);
133
134                 err = -EIO;
135                 goto out;
136         }
137
138         group_name = g_strdup_printf("service_%s", ssid);
139
140         cert_path = g_key_file_get_string(keyfile, group_name,
141                         CONNMAN_CONFIG_FIELD_CA_CERT_FILE, NULL);
142         DBG("Temporal %s", cert_path);
143         if (cert_path != NULL && remove(cert_path) != 0)
144                 ERR("Failed to remove %s", cert_path);
145         g_free(cert_path);
146
147         cert_path = g_key_file_get_string(keyfile, group_name,
148                         CONNMAN_CONFIG_FIELD_CLIENT_CERT_FILE, NULL);
149         DBG("Temporal %s", cert_path);
150         if (cert_path != NULL && remove(cert_path) != 0)
151                 ERR("Failed to remove %s", cert_path);
152         g_free(cert_path);
153
154         cert_path = g_key_file_get_string(keyfile, group_name,
155                         CONNMAN_CONFIG_FIELD_PVT_KEY_FILE, NULL);
156         DBG("Temporal %s", cert_path);
157         if (cert_path != NULL && remove(cert_path) != 0)
158                 ERR("Failed to remove %s", cert_path);
159         g_free(cert_path);
160
161         cert_path = g_key_file_get_string(keyfile, group_name,
162                         CONNMAN_CONFIG_FIELD_PVT_KEY_PASSPHRASE, NULL);
163         DBG("Temporal %s", cert_path);
164         if (cert_path != NULL && remove(cert_path) != 0)
165                 ERR("Failed to remove %s", cert_path);
166         g_free(cert_path);
167
168         dirname = g_strdup_printf("%s/%s", WIFI_CERT_STORAGEDIR, ssid);
169         if (dirname != NULL) {
170                 if (g_file_test(dirname, G_FILE_TEST_EXISTS) == TRUE)
171                         if (g_file_test(dirname, G_FILE_TEST_IS_DIR) == TRUE)
172                                 rmdir(dirname);
173
174                 g_free(dirname);
175         }
176
177         if (remove(config_file) != 0) {
178                 err = -EIO;
179                 goto out;
180         }
181
182 out:
183         g_key_file_free(keyfile);
184         g_free(config_file);
185         g_free(group_name);
186
187         return err;
188 }
189
190 static gboolean __netconfig_copy_config(const char *src, const char *dst)
191 {
192         gchar *buf = NULL;
193         gsize length = 0;
194         GError *error = NULL;
195         gboolean result;
196
197         result = g_file_get_contents(src, &buf, &length, &error);
198         if (result != TRUE) {
199                 ERR("Failed to read [%s]", error->message);
200                 g_error_free(error);
201
202                 return result;
203         }
204
205         result = g_file_set_contents(dst, buf, length, &error);
206         if (result != TRUE) {
207                 ERR("Failed to write [%s]", error->message);
208                 g_error_free(error);
209         }
210
211         INFO("Successfully installed[%zd]", length);
212         g_free(buf);
213
214         if (remove(src) != 0)
215                 WARN("Failed to remove %s", src);
216
217         return result;
218 }
219
220 static gboolean __netconfig_create_config(GVariant *fields)
221 {
222         GKeyFile *keyfile = NULL;
223         GVariantIter *iter;
224         gchar *encoded_ssid = NULL;
225         gchar *dirname = NULL;
226         gchar *group_name = NULL;
227         gchar *field, *value;
228         gboolean updated = FALSE;
229         gchar *cert_file = NULL;
230         gchar *cert_path = NULL;
231         int err = 0;
232
233         g_variant_get(fields, "a{ss}", &iter);
234         while (g_variant_iter_loop(iter, "{ss}", &field, &value)) {
235                 if (value != NULL) {
236                         if (g_strcmp0(field, CONNMAN_CONFIG_FIELD_NAME) == 0) {
237                                 encoded_ssid = __get_encoded_ssid(value);
238
239                                 g_free(value);
240                                 g_free(field);
241                                 break;
242                         } else if (g_strcmp0(field, CONNMAN_CONFIG_FIELD_SSID) == 0) {
243                                 encoded_ssid = g_strdup(value);
244
245                                 g_free(field);
246                                 g_free(value);
247                                 break;
248                         }
249                 }
250         }
251
252         if (encoded_ssid == NULL) {
253                 ERR("Failed to fetch SSID");
254                 goto out;
255         }
256
257         /* Create unique service group name */
258         group_name = g_strdup_printf("service_%s", encoded_ssid);
259         if (group_name == NULL) {
260                 ERR("Failed to create service group name");
261                 goto out;
262         }
263
264         keyfile = g_key_file_new();
265         if (keyfile == NULL) {
266                 ERR("Failed to g_key_file_new");
267                 goto out;
268         }
269
270         g_variant_iter_free(iter);
271
272         g_variant_get(fields, "a{ss}", &iter);
273         while (g_variant_iter_loop(iter, "{ss}", &field, &value)) {
274                 if (g_strcmp0(field, CONNMAN_CONFIG_FIELD_SSID) == 0 ||
275                                 g_strcmp0(field, CONNMAN_CONFIG_FIELD_EAP_METHOD) == 0 ||
276                                 g_strcmp0(field, CONNMAN_CONFIG_FIELD_PHASE2) ||
277                                 g_strcmp0(field, CONNMAN_CONFIG_FIELD_KEYMGMT_TYPE) == 0) {
278                         if (value != NULL)
279                                 g_key_file_set_string(keyfile, group_name, field, value);
280                 } else if (g_strcmp0(field, CONNMAN_CONFIG_FIELD_CA_CERT_FILE) == 0 ||
281                                 g_strcmp0(field, CONNMAN_CONFIG_FIELD_CLIENT_CERT_FILE) == 0 ||
282                                 g_strcmp0(field, CONNMAN_CONFIG_FIELD_PVT_KEY_FILE) == 0 ||
283                                 g_strcmp0(field, CONNMAN_CONFIG_FIELD_PVT_KEY_PASSPHRASE) == 0) {
284                         if (value != NULL) {
285                                 cert_file = strrchr(value, '/');
286                                 if (cert_file == NULL) {
287                                         ERR("Failed to get cert file: %s", value);
288                                         g_free(field);
289                                         g_free(value);
290                                         goto out;
291                                 }
292
293                                 cert_file++;
294
295                                 dirname = g_strdup_printf("%s/%s",
296                                                 WIFI_CERT_STORAGEDIR, encoded_ssid);
297                                 if (dirname == NULL) {
298                                         ERR("Failed to create dirname");
299                                         g_free(field);
300                                         g_free(value);
301                                         goto out;
302                                 }
303                                 if (g_file_test(dirname, G_FILE_TEST_IS_DIR) != TRUE) {
304                                         if (mkdir(dirname, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP |
305                                                         S_IXGRP | S_IROTH | S_IXOTH) < 0) {
306                                                 if (errno != EEXIST) {
307                                                         g_free(dirname);
308                                                         g_free(field);
309                                                         g_free(value);
310                                                         goto out;
311                                                 }
312                                         }
313                                 }
314                                 g_free(dirname);
315
316                                 cert_path = g_strdup_printf("%s/%s/%s",
317                                                 WIFI_CERT_STORAGEDIR, encoded_ssid, cert_file);
318                                 if (cert_path == NULL) {
319                                         ERR("Failed to create cert path");
320                                         g_free(field);
321                                         g_free(value);
322                                         goto out;
323                                 }
324                                 if (__netconfig_copy_config(value, cert_path) != TRUE) {
325                                         ERR("Failed to read cert file %s", value);
326                                         g_free(cert_path);
327                                         g_free(field);
328                                         g_free(value);
329                                         goto out;
330                                 }
331
332                                 g_key_file_set_string(keyfile, group_name, field, cert_path);
333                                 g_free(cert_path);
334                         }
335                 } else {
336                         if (value != NULL)
337                                 g_key_file_set_string(keyfile, group_name, field, value);
338                 }
339         }
340
341         err = __config_save((const char *)encoded_ssid, keyfile);
342         if (err < 0)
343                 ERR("Failed to create configuration %s[%d]", encoded_ssid, err);
344         else {
345                 DBG("Successfully created %s", encoded_ssid);
346                 updated = TRUE;
347         }
348
349 out:
350         if (keyfile)
351                 g_key_file_free(keyfile);
352
353         g_variant_iter_free(iter);
354
355         g_free(group_name);
356         g_free(encoded_ssid);
357
358         return updated;
359 }
360
361 static gboolean _delete_configuration(const gchar *profile)
362 {
363         gboolean ret = FALSE;
364         gchar *config_id = NULL;
365
366         ret = wifi_config_get_config_id(profile, &config_id);
367         if (ret != TRUE) {
368                 ERR("Fail to get config_id from [%s]", profile);
369                 return ret;
370         }
371         ERR("get config_id [%s] from [%s]", config_id, profile);
372
373         ret = wifi_config_remove_configuration(config_id);
374         if (ret != TRUE)
375                 ERR("Fail to wifi_config_remove_configuration [%s]", config_id);
376
377         if (config_id != NULL)
378                 g_free(config_id);
379
380         return ret;
381 }
382
383 static gboolean __netconfig_delete_config(const char *profile)
384 {
385         char *wifi_ident = NULL;
386         char *essid = NULL;
387         char *mode = NULL;
388         char *ssid = NULL;
389         int ssid_len = 0;
390         int err = 0;
391
392         if (NULL == profile) {
393                 ERR("Invalid profile name");
394                 return FALSE;
395         }
396
397         if (_delete_configuration(profile) != TRUE)
398                 ERR("Fail to delete configuration [%s]", profile);
399
400         wifi_ident = strstr(profile, "wifi_");
401         if (wifi_ident == NULL) {
402                 ERR("Invalid profile name");
403                 return FALSE;
404         }
405
406         essid = strchr(wifi_ident + 5, '_');
407         if (essid == NULL) {
408                 ERR("Invalid profile name");
409                 return FALSE;
410         }
411
412         essid++;
413         mode = strchr(essid, '_');
414
415         ssid_len = mode - essid;
416
417         ssid = g_try_malloc0(ssid_len + 1);
418         if (ssid == NULL) {
419                 ERR("Memory allocation failed");
420                 return FALSE;
421         }
422
423         g_strlcpy(ssid, essid, ssid_len + 1); /* include NULL-terminated */
424         err = __config_delete((const char *)ssid);
425         if (err < 0) {
426                 ERR("Failed to delete configuration %s[%d]", ssid, err);
427                 g_free(ssid);
428                 return FALSE;
429         }
430
431         DBG("Successfully deleted %s with length %d", ssid, ssid_len);
432
433         g_free(ssid);
434         return TRUE;
435 }
436
437 static void __netconfig_eap_state(
438                 wifi_service_state_e state, void *user_data);
439
440 static wifi_state_notifier netconfig_eap_notifier = {
441                 .wifi_state_changed = __netconfig_eap_state,
442                 .user_data = NULL,
443 };
444
445 static void __netconfig_eap_state(
446                 wifi_service_state_e state, void *user_data)
447 {
448         const char *wifi_profile = (const char *)user_data;
449
450         if (wifi_profile == NULL) {
451                 wifi_state_notifier_unregister(&netconfig_eap_notifier);
452                 return;
453         }
454
455         if (state != NETCONFIG_WIFI_CONNECTED && state != NETCONFIG_WIFI_FAILURE)
456                 return;
457
458         if (state == NETCONFIG_WIFI_FAILURE)
459                 __netconfig_delete_config(wifi_profile);
460
461         g_free(netconfig_eap_notifier.user_data);
462         netconfig_eap_notifier.user_data = NULL;
463
464         wifi_state_notifier_unregister(&netconfig_eap_notifier);
465 }
466
467 gboolean handle_create_eap_config(Wifi *wifi, GDBusMethodInvocation *context,
468                 const gchar *service, GVariant *fields)
469 {
470         gboolean updated = FALSE;
471         gboolean result = FALSE;
472
473         g_return_val_if_fail(wifi != NULL, TRUE);
474
475         DBG("Set agent fields for %s", service);
476
477         if (netconfig_is_wifi_profile(service) != TRUE) {
478                 netconfig_error_dbus_method_return(context, NETCONFIG_ERROR_WRONG_PROFILE, "InvalidService");
479                 return TRUE;
480         }
481
482         updated = __netconfig_create_config(fields);
483         if (updated == TRUE) {
484                 wifi_complete_create_eap_config(wifi, context);
485
486                 if (g_strstr_len(service, strlen(service), "_hidden_") != NULL) {
487                         GVariantIter *iter;
488                         char *field, *value;
489                         const char *name = NULL;
490                         const char *identity = NULL;
491                         const char *passphrase = NULL;
492
493                         g_variant_get(fields, "a{ss}", &iter);
494
495                         while (g_variant_iter_loop(iter, "{ss}", &field, &value)) {
496                                 if (g_strcmp0(field, CONNMAN_CONFIG_FIELD_NAME) == 0)
497                                         name = (const char *)value;
498                                 else if (g_strcmp0(field, CONNMAN_CONFIG_FIELD_SSID) == 0)
499                                         name = (const char *)value;
500                                 else if (g_strcmp0(field, CONNMAN_CONFIG_FIELD_IDENTITY) == 0)
501                                         identity = (const char *)value;
502                                 else if (g_strcmp0(field, CONNMAN_CONFIG_FIELD_PASSPHRASE) == 0)
503                                         passphrase = (const char *)value;
504                         }
505
506                         netconfig_wifi_set_agent_field_for_eap_network(
507                                                                         name, identity, passphrase);
508
509                         g_variant_iter_free(iter);
510                 }
511
512                 result = netconfig_invoke_dbus_method_nonblock(CONNMAN_SERVICE,
513                                 service, CONNMAN_SERVICE_INTERFACE, "Connect",
514                                 NULL, __netconfig_wifi_connect_reply);
515
516                 if (netconfig_eap_notifier.user_data != NULL) {
517                         g_free(netconfig_eap_notifier.user_data);
518                         netconfig_eap_notifier.user_data = NULL;
519
520                         wifi_state_notifier_unregister(&netconfig_eap_notifier);
521                 }
522
523                 netconfig_eap_notifier.user_data = g_strdup(service);
524                 wifi_state_notifier_register(&netconfig_eap_notifier);
525         } else {
526                 netconfig_error_dbus_method_return(context, NETCONFIG_ERROR_INVALID_PARAMETER, "InvalidArguments");
527         }
528
529         if (result != TRUE)
530                 ERR("Fail to connect %s", service);
531
532         return TRUE;
533 }
534
535 gboolean handle_delete_eap_config(Wifi *wifi, GDBusMethodInvocation *context,
536                 const gchar *profile)
537 {
538         g_return_val_if_fail(wifi != NULL, TRUE);
539
540         wifi_complete_delete_eap_config(wifi, context);
541
542         __netconfig_delete_config((const char *)profile);
543
544         return TRUE;
545 }