DA: Skip initializing failed_bssids list when eapol failure case
[platform/upstream/connman.git] / vpn / plugins / ipsec.c
1 /*
2  *
3  *  ConnMan VPN daemon
4  *
5  *  This program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License version 2 as
7  *  published by the Free Software Foundation.
8  *
9  *  This program is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *  GNU General Public License for more details.
13  *
14  *  You should have received a copy of the GNU General Public License
15  *  along with this program; if not, write to the Free Software
16  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17  *
18  */
19
20 #ifdef HAVE_CONFIG_H
21 #include <config.h>
22 #endif
23
24 #include <stdlib.h>
25 #include <string.h>
26 #include <errno.h>
27 #include <unistd.h>
28 #include <stdio.h>
29 #include <sys/stat.h>
30 #include <net/if.h>
31
32 #include <glib.h>
33 #include <gio/gio.h>
34
35 #define CONNMAN_API_SUBJECT_TO_CHANGE
36 #include <connman/plugin.h>
37 #include <connman/log.h>
38 #include <connman/task.h>
39 #include <connman/dbus.h>
40 #include <connman/ipconfig.h>
41
42 #include "../vpn-provider.h"
43
44 #include "vpn.h"
45 #include "ipsec.h"
46 #include "vici-client.h"
47
48 #define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0]))
49
50 typedef enum {
51         CERT_TYPE_NONE,
52         CERT_TYPE_DER,
53         CERT_TYPE_PEM,
54         CERT_TYPE_PKCS12,
55         CERT_TYPE_MAX,
56 } cert_type_e;
57
58 static DBusConnection *connection;
59 static VICIClient *vici_client;
60 static GFileMonitor* monitor;
61
62 struct ipsec_private_data {
63         struct vpn_provider *provider;
64         vpn_provider_connect_cb_t connect_cb;
65         void *connect_user_data;
66 };
67
68 struct ipsec_event_data {
69         vpn_event_callback event_cb;
70         void *event_user_data;
71 };
72
73 struct {
74         const char *cm_opt;
75         const char *vici_key;
76         const char *subsection;
77         vici_add_element add_elem;
78 } ipsec_conn_options[] = {
79         {"IPsec.Version", "version", NULL, vici_add_kv},
80         {"IPsec.LeftAddrs", "local_addrs", NULL, vici_add_kvl},
81         {"IPsec.RightAddrs", "remote_addrs", NULL, vici_add_kvl},
82
83         {"IPsec.LocalAuth", "auth", "local", vici_add_kv},
84         {"IPsec.LocalID", "id", "local", vici_add_kv},
85         {"IPsec.LocalXauthID", "xauth_id", "local", vici_add_kv},
86         {"IPsec.LocalXauthAuth", "auth", "local-xauth", vici_add_kv},
87         {"IPsec.LocalXauthXauthID", "xauth_id", "local-xauth", vici_add_kv},
88         {"IPsec.RemoteAuth", "auth", "remote", vici_add_kv},
89         {"IPsec.RemoteID", "id", "remote", vici_add_kv},
90         {"IPsec.RemoteXauthID", "xauth_id", "remote", vici_add_kv},
91         {"IPsec.RemoteXauthAuth", "auth", "remote-xauth", vici_add_kv},
92         {"IPsec.RemoteXauthXauthID", "xauth_id", "remote-xauth", vici_add_kv},
93         {"IPsec.ChildrenLocalTS", "local_ts", "children", vici_add_kvl},
94         {"IPsec.ChildrenRemoteTS", "remote_ts", "children", vici_add_kvl},
95 };
96
97 struct {
98         const char *cm_opt;
99         const char *vici_type;
100 } ipsec_shared_options[] = {
101         {"IPsec.IKEData", "data"},
102         {"IPsec.IKEOwners", "owners"},
103         {"IPsec.XauthData", "data"},
104         {"IPsec.XauthOwners", "owners"},
105 };
106
107 struct {
108         const char *cm_opt;
109         const char *vici_type;
110         const char *vici_flag;
111 } ipsec_cert_options[] = {
112         {"IPsec.CertType", "type", NULL},
113         {"IPsec.CertFlag", "flag", NULL},
114         {"IPsec.CertData", "data", NULL},
115         {"IPsec.CertPass", "data", NULL},
116 };
117
118 struct {
119         const char *cm_opt;
120         const char *vici_type;
121 } ipsec_pkey_options[] = {
122         {"IPsec.PKeyType", "type"},
123         {"IPsec.PKeyData", "data"},
124 };
125
126 static const char *ikev1_esp_proposals [] ={
127                 "aes256-sha256",
128                 "aes128-sha256",
129                 "aes256-sha1",
130                 "aes128-sha1",
131                 "aes256-md5",
132                 "aes128-md5",
133                 "3des-sha1",
134                 "3des-md5",
135                 NULL,
136 };
137
138 static const char *ikev1_proposals [] ={
139                 "aes256-sha256-modp1024",
140                 "aes128-sha256-modp1024",
141                 "aes256-sha1-modp1024",
142                 "aes128-sha1-modp1024",
143                 "aes256-md5-modp1024",
144                 "aes128-md5-modp1024",
145                 "3des-sha1-modp1024",
146                 "3des-md5-modp1024",
147                 NULL,
148 };
149
150 static const char *ikev2_esp_proposals = "aes256-aes128-sha256-sha1";
151
152 static const char *ikev2_proposals = "aes256-aes128-sha512-sha384-sha256-sha1-modp2048-modp1536-modp1024";
153
154 static struct ipsec_event_data event_data;
155
156 static void free_private_data(struct ipsec_private_data *data)
157 {
158         g_free(data);
159 }
160
161 static int ipsec_notify(DBusMessage *msg, struct vpn_provider *provider)
162 {
163         return 0;
164 }
165
166 static void ipsec_set_event_cb(vpn_event_callback event_cb, struct vpn_provider *provider)
167 {
168         DBG("set event cb!");
169         event_data.event_cb = event_cb;
170         event_data.event_user_data = provider;
171         return;
172 }
173
174 static int ipsec_is_same_auth(const char* req, const char* target)
175 {
176         if (req == NULL || target == NULL)
177                 return 0;
178         return (g_strcmp0(req, target) == 0);
179 }
180
181 static int vici_load_cert(const char* type, const char* flag, const char* data)
182 {
183         VICISection *sect;
184         int ret = 0;
185
186         sect = vici_create_section(NULL);
187         if (!sect)
188                 return -ENOMEM;
189
190         vici_add_kv(sect, "type", type, NULL);
191         vici_add_kv(sect, "flag", flag, NULL);
192         vici_add_kv(sect, "data", data, NULL);
193
194         ret = vici_send_request(vici_client, VICI_CMD_LOAD_CERT, sect);
195         if (ret < 0)
196                 connman_error("vici_send_request failed");
197
198         vici_destroy_section(sect);
199
200         return ret;
201 }
202
203 static void ipsec_add_default_child_sa_data(struct vpn_provider *provider, VICISection *child)
204 {
205         const char *version = vpn_provider_get_string(provider, "IPsec.Version");
206         if (g_strcmp0(version, "1") == 0) {
207                 int i = 0;
208                 GSList *list;
209
210                 for (list = NULL; ikev1_esp_proposals[i] != NULL; i++)
211                         list = g_slist_append(list, g_strdup(ikev1_esp_proposals[i]));
212                 vici_add_list(child, "esp_proposals", list, "net");
213                 g_slist_free_full(list, g_free);
214                 list = NULL;
215         } else {
216                 vici_add_kvl(child, "esp_proposals", ikev2_esp_proposals, "net");
217         }
218         return;
219 }
220
221 static void ipsec_add_default_conn_data(struct vpn_provider *provider, VICISection *conn)
222 {
223         const char *version = vpn_provider_get_string(provider, "IPsec.Version");
224         const char *remote_addr = vpn_provider_get_string(provider, "Host");
225
226         vici_add_kvl(conn, "remote_addrs", remote_addr, NULL);
227         if (g_strcmp0(version, "1") == 0) {
228                 int i = 0;
229                 GSList *list;
230
231                 for (list = NULL; ikev1_proposals[i] != NULL; i++)
232                         list = g_slist_append(list, g_strdup(ikev1_proposals[i]));
233                 vici_add_list(conn, "proposals", list, NULL);
234                 g_slist_free_full(list, g_free);
235                 list = NULL;
236
237                 if (g_strcmp0(vpn_provider_get_string(provider, "IPsec.LocalAuth"), "psk") == 0)
238                         vici_add_kv(conn, "aggressive", "yes", NULL);
239         } else {
240                 vici_add_kvl(conn, "proposals", ikev2_proposals, NULL);
241         }
242
243         vici_add_kvl(conn, "vips", "0.0.0.0", NULL);
244         return;
245 }
246
247 static char *load_file_from_path(const char *path)
248 {
249         struct stat st;
250         FILE *fp = NULL;
251         int fd = 0;
252         size_t  file_size = 0;
253         char *file_buff = NULL;
254
255         if (!path) {
256                 connman_error("File path is NULL\n");
257                 return NULL;
258         }
259
260         fp = fopen(path, "rb");
261         if (!fp) {
262                 connman_error("fopen %s is failed\n", path);
263                 return NULL;
264         }
265
266         fd = fileno(fp);
267         if (fd == -1) {
268                 connman_error("fp is not a valid stream");
269                 fclose(fp);
270                 return NULL;
271         }
272
273         if (fstat(fd, &st) != 0) {
274                 connman_error("fstat failed");
275                 fclose(fp);
276                 return NULL;
277         }
278
279         file_size = st.st_size;
280         file_buff = g_try_malloc0(sizeof(char)*st.st_size);
281         if (file_buff == NULL) {
282                 connman_error("g_try_malloc0 failed\n");
283                 fclose(fp);
284                 return NULL;
285         }
286
287         if (fread(file_buff, 1, file_size, fp) != file_size) {
288                 connman_error("file size not matched\n");
289                 g_free(file_buff);
290                 file_buff = NULL;
291         }
292
293         fclose(fp);
294         return file_buff;
295 }
296
297 static char * get_local_cert_str(struct vpn_provider *provider)
298 {
299         const char *path;
300
301         if (!provider)
302                 return NULL;
303
304         path = vpn_provider_get_string(provider, "IPsec.LocalCerts");
305
306         return load_file_from_path(path);
307 }
308
309 static int ipsec_load_conn(struct vpn_provider *provider, struct ipsec_private_data *data)
310 {
311         const char *key;
312         const char *value;
313         const char *subsection;
314         char *local_cert_str;
315         VICISection *conn;
316         VICISection *children;
317         int i;
318         int ret = 0;
319
320         if (!provider || !data) {
321                 connman_error("invalid provider or data");
322                 return -EINVAL;
323         }
324
325         value = vpn_provider_get_string(provider, "Name");
326         DBG("Name: %s", value);
327         conn = vici_create_section(value);
328         children = vici_create_section("children");
329         add_subsection("children", children, conn);
330
331         for (i = 0; i < (int)ARRAY_SIZE(ipsec_conn_options); i++) {
332                 value = vpn_provider_get_string(provider, ipsec_conn_options[i].cm_opt);
333                 if (!value)
334                         continue;
335
336                 key = ipsec_conn_options[i].vici_key;
337                 subsection = ipsec_conn_options[i].subsection;
338                 ipsec_conn_options[i].add_elem(conn, key, value, subsection);
339         }
340
341         local_cert_str = get_local_cert_str(provider);
342         if (local_cert_str) {
343                 /* TODO :remove this after debug */
344                 DBG("There's local certification to add local section");
345                 vici_add_kvl(conn, "certs", local_cert_str, "local");
346                 g_free(local_cert_str);
347         }
348
349         ipsec_add_default_conn_data(provider, conn);
350         ipsec_add_default_child_sa_data(provider, children);
351
352         ret = vici_send_request(vici_client, VICI_CMD_LOAD_CONN, conn);
353         if (ret < 0)
354                 connman_error("vici_send_request failed");
355
356         vici_destroy_section(conn);
357
358         return ret;
359 }
360
361 static int ipsec_load_shared_psk(struct vpn_provider *provider)
362 {
363         const char *data;
364         const char *owner;
365         VICISection *sect;
366         int ret = 0;
367
368         if (!provider) {
369                 connman_error("invalid provider");
370                 return -EINVAL;
371         }
372
373         data = vpn_provider_get_string(provider, "IPsec.IKEData");
374         owner = vpn_provider_get_string(provider, "IPsec.IKEOwners");
375         DBG("IKEData: %s, IKEOwners: %s", data, owner);
376
377         if (!data)
378                 return 0;
379
380         sect = vici_create_section(NULL);
381         if (!sect) {
382                 return -ENOMEM;
383         }
384
385         vici_add_kv(sect, "type", VICI_SHARED_TYPE_PSK, NULL);
386         vici_add_kv(sect, "data", data, NULL);
387         vici_add_kvl(sect, "owners", owner, NULL);
388
389         ret = vici_send_request(vici_client, VICI_CMD_LOAD_SHARED, sect);
390         if (ret < 0)
391                 connman_error("vici_send_request failed");
392
393         vici_destroy_section(sect);
394
395         return ret;
396 }
397
398 static int ipsec_load_shared_xauth(struct vpn_provider *provider)
399 {
400         const char *data;
401         const char *owner;
402         VICISection *sect;
403         int ret = 0;
404
405         if (!provider) {
406                 connman_error("invalid provider");
407                 return -EINVAL;
408         }
409
410         data = vpn_provider_get_string(provider, "IPsec.XauthData");
411         owner = vpn_provider_get_string(provider, "IPsec.XauthOwners");
412         DBG("XauthData: %s, XauthOwners: %s", data, owner);
413
414         if (!data)
415                 return 0;
416
417         sect = vici_create_section(NULL);
418
419         vici_add_kv(sect, "type", VICI_SHARED_TYPE_XAUTH, NULL);
420         vici_add_kv(sect, "data", data, NULL);
421         vici_add_kvl(sect, "owners", owner, NULL);
422
423         ret = vici_send_request(vici_client, VICI_CMD_LOAD_SHARED, sect);
424         if (ret < 0)
425                 connman_error("vici_send_request failed");
426
427         vici_destroy_section(sect);
428
429         return ret;
430 }
431
432 static int ipsec_load_key(struct vpn_provider *provider)
433 {
434         const char *type;
435         const char *path;
436         char *data;
437         VICISection *sect;
438         int ret = 0;
439
440         if (!provider) {
441                 connman_error("invalid provider");
442                 return -EINVAL;
443         }
444
445         type = vpn_provider_get_string(provider, "IPsec.PKeyType");
446         path = vpn_provider_get_string(provider, "IPsec.PKeyData");
447         DBG("PKeyType: %s, PKeyData: %s", type, path);
448
449         if (!type || !path)
450                 return 0;
451
452         data = load_file_from_path(path);
453         if (!data)
454                 return 0;
455
456         sect = vici_create_section(NULL);
457         if (!sect) {
458                 g_free(data);
459                 return -ENOMEM;
460         }
461
462         vici_add_kv(sect, "type", type, NULL);
463         vici_add_kv(sect, "data", data, NULL);
464
465         ret = vici_send_request(vici_client, VICI_CMD_LOAD_KEY, sect);
466         if (ret < 0)
467                 connman_error("vici_send_request failed");
468
469         vici_destroy_section(sect);
470         g_free(data);
471
472         return ret;
473 }
474
475 static int ipsec_initiate(struct vpn_provider *provider)
476 {
477         VICISection *sect;
478         int ret = 0;
479
480         sect = vici_create_section(NULL);
481         if (!sect)
482                 return -ENOMEM;
483
484         vici_add_kv(sect, "child", "net", NULL);
485         ret = vici_send_request(vici_client, VICI_CMD_INITIATE, sect);
486         if (ret < 0)
487                 connman_error("vici_send_request failed");
488
489         vici_destroy_section(sect);
490
491         return ret;
492 }
493
494 static int ipsec_load_cert(struct vpn_provider *provider)
495 {
496         const char *type;
497         const char *flag;
498         char *data;
499         const char *local_auth_type;
500         const char *remote_auth_type;
501         int ret = 0;
502
503         if (!provider) {
504                 connman_error("invalid provider");
505                 return -EINVAL;
506         }
507
508         local_auth_type = vpn_provider_get_string(provider, "IPsec.LocalAuth");
509         remote_auth_type = vpn_provider_get_string(provider, "IPsec.RemoteAuth");
510         if (!ipsec_is_same_auth(local_auth_type, "pubkey") &&
511                         !ipsec_is_same_auth(remote_auth_type, "pubkey")) {
512                 DBG("invalid auth type");
513                 return 0;
514         }
515
516         type = vpn_provider_get_string(provider, "IPsec.CertType");
517         flag = vpn_provider_get_string(provider, "IPsec.CertFlag");
518         data = load_file_from_path(vpn_provider_get_string(provider, "IPsec.CertData"));
519         DBG("CertType: %s, CertFalg: %s,CertData: %s", type, flag, data);
520         if (!type || ! flag || !data) {
521                 connman_error("invalid certification information");
522                 g_free(data);
523                 return -EINVAL;
524         }
525
526         ret = vici_load_cert(type, flag, data);
527         if (ret < 0)
528                 connman_error("failed to load cert");
529
530         g_free(data);
531
532         return ret;
533 }
534
535 static int ipsec_terminate(struct vpn_provider *provider)
536 {
537         VICISection *sect;
538         int ret = 0;
539
540         sect = vici_create_section(NULL);
541         if (!sect)
542                 return -ENOMEM;
543
544         vici_add_kv(sect, "child", "net", NULL);
545         vici_add_kv(sect, "ike", vpn_provider_get_string(provider, "Name"), NULL);
546         vici_add_kv(sect, "timeout", "-1", NULL);
547         ret = vici_send_request(vici_client, VICI_CMD_TERMINATE, sect);
548         if (ret < 0)
549                 connman_error("vici_send_request failed");
550
551         vici_destroy_section(sect);
552
553         return ret;
554 }
555
556 static void request_reply_cb(int err, void *user_data)
557 {
558         struct ipsec_private_data *data;
559
560         data = (struct ipsec_private_data *)user_data;
561         DBG("request reply cb");
562
563         if(err != 0) {
564                 if (event_data.event_cb)
565                         event_data.event_cb(event_data.event_user_data, VPN_STATE_FAILURE);
566                 /* TODO: Does close socket needed? */
567         } else {
568                 DBG("Series of requests are succeeded");
569                 /* TODO: Not sure about below */
570                 if (event_data.event_cb)
571                         event_data.event_cb(event_data.event_user_data, VPN_STATE_CONNECT);
572         }
573
574         free_private_data(data);
575 }
576
577 static void ipsec_vici_event_cb(VICIClientEvent event, void *user_data)
578 {
579         struct vpn_provider *provider;
580
581         provider = (struct vpn_provider *)user_data;
582         if (!provider) {
583                 DBG("Invalid user data");
584                 return;
585         }
586
587         if(event == VICI_EVENT_CHILD_UP) {
588                 if (event_data.event_cb)
589                         event_data.event_cb(event_data.event_user_data, VPN_STATE_READY);
590         } else if (event == VICI_EVENT_CHILD_DOWN) {
591                 if (event_data.event_cb)
592                         event_data.event_cb(event_data.event_user_data, VPN_STATE_DISCONNECT);
593         } else {
594                 DBG("Unknown event");
595         }
596
597         return;
598 }
599
600 static struct ipsec_private_data* create_ipsec_private_data(struct vpn_provider *provider,
601                 vpn_provider_connect_cb_t cb, void* user_data)
602 {
603         struct ipsec_private_data *data;
604         data = g_try_new0(struct ipsec_private_data, 1);
605         if (!data) {
606                 connman_error("out of memory");
607                 return NULL;
608         }
609
610         data->provider = provider;
611         data->connect_cb = cb;
612         data->connect_user_data = user_data;
613         return data;
614 }
615
616 static void vici_connect(struct ipsec_private_data *data)
617 {
618         struct vpn_provider *provider = NULL;
619         vpn_provider_connect_cb_t cb = NULL;
620         int err = 0;
621
622         if (!data)
623                 IPSEC_ERROR_CHECK_GOTO(-1, done, "Invalid data parameter");
624
625         provider = data->provider;
626         cb = data->connect_cb;
627         if (!provider || !cb)
628                 IPSEC_ERROR_CHECK_GOTO(-1, done, "Invalid provider or callback");
629
630         DBG("data %p, provider %p", data, provider);
631
632         /*
633          * Initialize vici client
634          */
635         err = vici_initialize(&vici_client);
636         IPSEC_ERROR_CHECK_GOTO(err, done, "failed to initialize vici_client");
637
638         /* TODO :remove this after debug */
639         DBG("success to initialize vici socket");
640
641         vici_set_request_reply_cb(vici_client, (vici_request_reply_cb)request_reply_cb, data);
642         /*
643          * Sets child-updown event
644          */
645         err = vici_set_event_cb(vici_client, (vici_event_cb)ipsec_vici_event_cb, provider);
646         IPSEC_ERROR_CHECK_GOTO(err, done, "register event failed");
647
648         /* TODO :remove this after debug */
649         DBG("success to vici_set_event_cb");
650         /*
651          * Send the load-conn command
652          */
653         err = ipsec_load_conn(provider, data);
654         IPSEC_ERROR_CHECK_GOTO(err, done, "load-conn failed");
655
656         /* TODO :remove this after debug */
657         DBG("success to ipsec_load_conn");
658
659         /*
660          * Send the load-shared command for PSK
661          */
662         err = ipsec_load_shared_psk(provider);
663         IPSEC_ERROR_CHECK_GOTO(err, done, "load-shared failed");
664
665         /* TODO :remove this after debug */
666         DBG("success to ipsec_load_shared_psk");
667
668         /*
669          * Send the load-shared command for XAUTH
670          */
671         err = ipsec_load_shared_xauth(provider);
672         IPSEC_ERROR_CHECK_GOTO(err, done, "load-shared failed");
673
674         /* TODO :remove this after debug */
675         DBG("success to ipsec_load_shared_xauth");
676         /*
677          * Send the load-cert command
678          */
679         err = ipsec_load_cert(provider);
680         IPSEC_ERROR_CHECK_GOTO(err, done, "load-cert failed");
681
682         /* TODO :remove this after debug */
683         DBG("success to ipsec_load_cert");
684
685         /*
686          * Send the load-key command
687          */
688         err = ipsec_load_key(provider);
689         IPSEC_ERROR_CHECK_GOTO(err, done, "load-key failed");
690
691         /* TODO :remove this after debug */
692         DBG("success to ipsec_load_cert");
693         /*
694          * Send the initiate command
695          */
696         err = ipsec_initiate(provider);
697         IPSEC_ERROR_CHECK_GOTO(err, done, "initiate failed");
698
699         /* TODO :remove this after debug */
700         DBG("success to ipsec_initiate");
701
702 done:
703         /* refer to connect_cb on vpn-provider.c for cb */
704         if(cb)
705                 cb(provider, data->connect_user_data, -err);
706         /* TODO: Does close socket needed? when err is not zero */
707
708         return;
709 }
710
711 static void monitor_changed(GFileMonitor *monitor, GFile *file, GFile *other_file,
712                 GFileMonitorEvent  event_type, gpointer user_data)
713 {
714         DBG("file %s", g_file_get_path(file));
715         if (event_type == G_FILE_MONITOR_EVENT_CREATED) {
716                 if (g_file_test(VICI_DEFAULT_URI, G_FILE_TEST_EXISTS)) {
717                         DBG("file created: %s", VICI_DEFAULT_URI);
718                         struct ipsec_private_data *data = user_data;
719                         vici_connect(data);
720                         g_object_unref(monitor);
721                 }
722         }
723 }
724
725 static void monitor_vici_socket(struct ipsec_private_data *data)
726 {
727         GError *error = NULL;
728         GFile* file;
729
730         file = g_file_new_for_path(VICI_DEFAULT_URI);
731         monitor = g_file_monitor_file(file, G_FILE_MONITOR_SEND_MOVED, NULL, &error);
732         if (error) {
733                 connman_error("g_file_monitor_directory failed: %s / %d", error->message, error->code);
734                 g_error_free(error);
735                 if(event_data.event_cb)
736                         event_data.event_cb(event_data.event_user_data, VPN_STATE_FAILURE);
737                 return;
738         }
739         /* TODO :remove this after debug */
740         DBG("starting to monitor vici socket");
741         g_signal_connect(monitor, "changed", G_CALLBACK(monitor_changed), data);
742         g_object_unref(file);
743 }
744
745 static void check_vici_socket(struct ipsec_private_data *data)
746 {
747         DBG("data %p", data);
748         if (g_file_test(VICI_DEFAULT_URI, G_FILE_TEST_EXISTS)) {
749                 DBG("file exists: %s", VICI_DEFAULT_URI);
750                 vici_connect(data);
751         } else {
752                 monitor_vici_socket(data);
753         }
754 }
755
756 static void ipsec_died(struct connman_task *task, int exit_code, void *user_data)
757 {
758        DBG("task %p exit_code %d", task, exit_code);
759        unlink(VICI_DEFAULT_URI);
760        vpn_died(task, exit_code, user_data);
761 }
762
763 static int ipsec_connect(struct vpn_provider *provider,
764                         struct connman_task *task, const char *if_name,
765                         vpn_provider_connect_cb_t cb, const char *dbus_sender,
766                         void *user_data)
767 {
768         struct ipsec_private_data *data;
769         int err = 0;
770
771         data = create_ipsec_private_data(provider, cb, user_data);
772         if (!data) {
773                 connman_error("create ipsec private data failed");
774                 return -ENOMEM;
775         }
776         /*
777          * Start charon daemon using ipsec script of strongSwan.
778          */
779         err = connman_task_run(task, ipsec_died, provider, NULL, NULL, NULL);
780         if (err < 0) {
781                 connman_error("charon start failed");
782                 if (cb)
783                         cb(provider, user_data, err);
784
785                 g_free(data);
786                 return err;
787         }
788
789         check_vici_socket(data);
790 //      g_usleep(G_USEC_PER_SEC);
791
792         return err;
793 }
794
795 static int ipsec_error_code(struct vpn_provider *provider, int exit_code)
796 {
797         return 0;
798 }
799
800 static int ipsec_save(struct vpn_provider *provider, GKeyFile *keyfile)
801 {
802         int i;
803         const char *option;
804
805         DBG("");
806         /*
807          * Save IKE connection configurations
808          */
809         for (i = 0; i < (int)ARRAY_SIZE(ipsec_conn_options); i++) {
810                 option = vpn_provider_get_string(provider, ipsec_conn_options[i].cm_opt);
811                 if (option)
812                         g_key_file_set_string(keyfile,
813                                         vpn_provider_get_save_group(provider),
814                                         ipsec_conn_options[i].cm_opt,
815                                         option);
816         }
817
818         /*
819          * Save shared IKE PSK, EAP or XAUTH secret
820          */
821         for (i = 0; i < (int)ARRAY_SIZE(ipsec_shared_options); i++) {
822                 option = vpn_provider_get_string(provider, ipsec_shared_options[i].cm_opt);
823                 if (option)
824                         g_key_file_set_string(keyfile,
825                                         vpn_provider_get_save_group(provider),
826                                         ipsec_shared_options[i].cm_opt,
827                                         option);
828         }
829
830         /*
831          * Save certification
832          */
833         for (i = 0; i < (int)ARRAY_SIZE(ipsec_cert_options); i++) {
834                 option = vpn_provider_get_string(provider, ipsec_cert_options[i].cm_opt);
835                 if (option)
836                         g_key_file_set_string(keyfile,
837                                         vpn_provider_get_save_group(provider),
838                                         ipsec_cert_options[i].cm_opt,
839                                         option);
840         }
841
842         /*
843          * Save private key
844          */
845         for (i = 0; i < (int)ARRAY_SIZE(ipsec_pkey_options); i++) {
846                 option = vpn_provider_get_string(provider, ipsec_pkey_options[i].cm_opt);
847                 if (option)
848                         g_key_file_set_string(keyfile,
849                                         vpn_provider_get_save_group(provider),
850                                         ipsec_pkey_options[i].cm_opt,
851                                         option);
852         }
853
854         /*
855          * Save local certification
856          */
857         option = vpn_provider_get_string(provider, "IPsec.LocalCerts");
858         if (option)
859                 g_key_file_set_string(keyfile,
860                                 vpn_provider_get_save_group(provider),
861                                 "IPsec.LocalCerts",
862                                 option);
863         option = vpn_provider_get_string(provider, "IPsec.LocalCertPass");
864         if (option)
865                 g_key_file_set_string(keyfile,
866                                 vpn_provider_get_save_group(provider),
867                                 "IPsec.LocalCertPass",
868                                 option);
869         /*
870          * Save CA certification directory
871          */
872         option = vpn_provider_get_string(provider, "IPsec.CACertsDir");
873         if (option)
874                 g_key_file_set_string(keyfile,
875                                 vpn_provider_get_save_group(provider),
876                                 "IPsec.CACertsDir",
877                                 option);
878
879         return 0;
880 }
881
882 static void ipsec_disconnect(struct vpn_provider *provider)
883 {
884         int err = 0;
885         /*
886          * Send the terminate command
887          */
888         err = ipsec_terminate(provider);
889         IPSEC_ERROR_CHECK_RETURN(err, "terminate failed");
890
891         err = vici_deinitialize(vici_client);
892         IPSEC_ERROR_CHECK_RETURN(err, "failed to deinitialize vici_client");
893
894         return;
895 }
896
897 static struct vpn_driver vpn_driver = {
898         .flags = VPN_FLAG_NO_TUN,
899         .notify = ipsec_notify,
900         .set_event_cb = ipsec_set_event_cb,
901         .connect = ipsec_connect,
902         .error_code = ipsec_error_code,
903         .save = ipsec_save,
904         .disconnect = ipsec_disconnect,
905 };
906
907 static int ipsec_init(void)
908 {
909         connection = connman_dbus_get_connection();
910
911         event_data.event_cb = NULL;
912         event_data.event_user_data = NULL;
913
914         return vpn_register("ipsec", &vpn_driver, IPSEC);
915 }
916
917 static void ipsec_exit(void)
918 {
919         vpn_unregister("ipsec");
920
921         dbus_connection_unref(connection);
922 }
923
924 CONNMAN_PLUGIN_DEFINE(ipsec, "IPSec plugin", VERSION,
925         CONNMAN_PLUGIN_PRIORITY_DEFAULT, ipsec_init, ipsec_exit)