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.
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.
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
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>
42 #include "../vpn-provider.h"
46 #include "vici-client.h"
48 #define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0]))
58 static DBusConnection *connection;
59 static VICIClient *vici_client;
60 static GFileMonitor* monitor;
62 struct ipsec_private_data {
63 struct vpn_provider *provider;
64 vpn_provider_connect_cb_t connect_cb;
65 void *connect_user_data;
68 struct ipsec_event_data {
69 vpn_event_callback event_cb;
70 void *event_user_data;
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},
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},
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"},
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},
120 const char *vici_type;
121 } ipsec_pkey_options[] = {
122 {"IPsec.PKeyType", "type"},
123 {"IPsec.PKeyData", "data"},
126 static const char *ikev1_esp_proposals [] ={
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",
150 static const char *ikev2_esp_proposals = "aes256-aes128-sha256-sha1";
152 static const char *ikev2_proposals = "aes256-aes128-sha512-sha384-sha256-sha1-modp2048-modp1536-modp1024";
154 static struct ipsec_event_data event_data;
156 static void free_private_data(struct ipsec_private_data *data)
161 static int ipsec_notify(DBusMessage *msg, struct vpn_provider *provider)
166 static void ipsec_set_event_cb(vpn_event_callback event_cb, struct vpn_provider *provider)
168 DBG("set event cb!");
169 event_data.event_cb = event_cb;
170 event_data.event_user_data = provider;
174 static int ipsec_is_same_auth(const char* req, const char* target)
176 if (req == NULL || target == NULL)
178 return (g_strcmp0(req, target) == 0);
181 static int vici_load_cert(const char* type, const char* flag, const char* data)
186 sect = vici_create_section(NULL);
190 vici_add_kv(sect, "type", type, NULL);
191 vici_add_kv(sect, "flag", flag, NULL);
192 vici_add_kv(sect, "data", data, NULL);
194 ret = vici_send_request(vici_client, VICI_CMD_LOAD_CERT, sect);
196 connman_error("vici_send_request failed");
198 vici_destroy_section(sect);
203 static void ipsec_add_default_child_sa_data(struct vpn_provider *provider, VICISection *child)
205 const char *version = vpn_provider_get_string(provider, "IPsec.Version");
206 if (g_strcmp0(version, "1") == 0) {
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);
216 vici_add_kvl(child, "esp_proposals", ikev2_esp_proposals, "net");
221 static void ipsec_add_default_conn_data(struct vpn_provider *provider, VICISection *conn)
223 const char *version = vpn_provider_get_string(provider, "IPsec.Version");
224 const char *remote_addr = vpn_provider_get_string(provider, "Host");
226 vici_add_kvl(conn, "remote_addrs", remote_addr, NULL);
227 if (g_strcmp0(version, "1") == 0) {
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);
237 if (g_strcmp0(vpn_provider_get_string(provider, "IPsec.LocalAuth"), "psk") == 0)
238 vici_add_kv(conn, "aggressive", "yes", NULL);
240 vici_add_kvl(conn, "proposals", ikev2_proposals, NULL);
243 vici_add_kvl(conn, "vips", "0.0.0.0", NULL);
247 static char *load_file_from_path(const char *path)
252 size_t file_size = 0;
253 char *file_buff = NULL;
256 connman_error("File path is NULL\n");
260 fp = fopen(path, "rb");
262 connman_error("fopen %s is failed\n", path);
268 connman_error("fp is not a valid stream");
273 if (fstat(fd, &st) != 0) {
274 connman_error("fstat failed");
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");
287 if (fread(file_buff, 1, file_size, fp) != file_size) {
288 connman_error("file size not matched\n");
297 static char * get_local_cert_str(struct vpn_provider *provider)
304 path = vpn_provider_get_string(provider, "IPsec.LocalCerts");
306 return load_file_from_path(path);
309 static int ipsec_load_conn(struct vpn_provider *provider, struct ipsec_private_data *data)
313 const char *subsection;
314 char *local_cert_str;
316 VICISection *children;
320 if (!provider || !data) {
321 connman_error("invalid provider or data");
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);
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);
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);
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);
349 ipsec_add_default_conn_data(provider, conn);
350 ipsec_add_default_child_sa_data(provider, children);
352 ret = vici_send_request(vici_client, VICI_CMD_LOAD_CONN, conn);
354 connman_error("vici_send_request failed");
356 vici_destroy_section(conn);
361 static int ipsec_load_shared_psk(struct vpn_provider *provider)
369 connman_error("invalid provider");
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);
380 sect = vici_create_section(NULL);
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);
389 ret = vici_send_request(vici_client, VICI_CMD_LOAD_SHARED, sect);
391 connman_error("vici_send_request failed");
393 vici_destroy_section(sect);
398 static int ipsec_load_shared_xauth(struct vpn_provider *provider)
406 connman_error("invalid provider");
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);
417 sect = vici_create_section(NULL);
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);
423 ret = vici_send_request(vici_client, VICI_CMD_LOAD_SHARED, sect);
425 connman_error("vici_send_request failed");
427 vici_destroy_section(sect);
432 static int ipsec_load_key(struct vpn_provider *provider)
441 connman_error("invalid provider");
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);
452 data = load_file_from_path(path);
456 sect = vici_create_section(NULL);
462 vici_add_kv(sect, "type", type, NULL);
463 vici_add_kv(sect, "data", data, NULL);
465 ret = vici_send_request(vici_client, VICI_CMD_LOAD_KEY, sect);
467 connman_error("vici_send_request failed");
469 vici_destroy_section(sect);
475 static int ipsec_initiate(struct vpn_provider *provider)
480 sect = vici_create_section(NULL);
484 vici_add_kv(sect, "child", "net", NULL);
485 ret = vici_send_request(vici_client, VICI_CMD_INITIATE, sect);
487 connman_error("vici_send_request failed");
489 vici_destroy_section(sect);
494 static int ipsec_load_cert(struct vpn_provider *provider)
499 const char *local_auth_type;
500 const char *remote_auth_type;
504 connman_error("invalid provider");
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");
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");
526 ret = vici_load_cert(type, flag, data);
528 connman_error("failed to load cert");
535 static int ipsec_terminate(struct vpn_provider *provider)
540 sect = vici_create_section(NULL);
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);
549 connman_error("vici_send_request failed");
551 vici_destroy_section(sect);
556 static void request_reply_cb(int err, void *user_data)
558 struct ipsec_private_data *data;
560 data = (struct ipsec_private_data *)user_data;
561 DBG("request reply cb");
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? */
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);
574 free_private_data(data);
577 static void ipsec_vici_event_cb(VICIClientEvent event, void *user_data)
579 struct vpn_provider *provider;
581 provider = (struct vpn_provider *)user_data;
583 DBG("Invalid user data");
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);
594 DBG("Unknown event");
600 static struct ipsec_private_data* create_ipsec_private_data(struct vpn_provider *provider,
601 vpn_provider_connect_cb_t cb, void* user_data)
603 struct ipsec_private_data *data;
604 data = g_try_new0(struct ipsec_private_data, 1);
606 connman_error("out of memory");
610 data->provider = provider;
611 data->connect_cb = cb;
612 data->connect_user_data = user_data;
616 static void vici_connect(struct ipsec_private_data *data)
618 struct vpn_provider *provider = NULL;
619 vpn_provider_connect_cb_t cb = NULL;
623 IPSEC_ERROR_CHECK_GOTO(-1, done, "Invalid data parameter");
625 provider = data->provider;
626 cb = data->connect_cb;
627 if (!provider || !cb)
628 IPSEC_ERROR_CHECK_GOTO(-1, done, "Invalid provider or callback");
630 DBG("data %p, provider %p", data, provider);
633 * Initialize vici client
635 err = vici_initialize(&vici_client);
636 IPSEC_ERROR_CHECK_GOTO(err, done, "failed to initialize vici_client");
638 /* TODO :remove this after debug */
639 DBG("success to initialize vici socket");
641 vici_set_request_reply_cb(vici_client, (vici_request_reply_cb)request_reply_cb, data);
643 * Sets child-updown event
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");
648 /* TODO :remove this after debug */
649 DBG("success to vici_set_event_cb");
651 * Send the load-conn command
653 err = ipsec_load_conn(provider, data);
654 IPSEC_ERROR_CHECK_GOTO(err, done, "load-conn failed");
656 /* TODO :remove this after debug */
657 DBG("success to ipsec_load_conn");
660 * Send the load-shared command for PSK
662 err = ipsec_load_shared_psk(provider);
663 IPSEC_ERROR_CHECK_GOTO(err, done, "load-shared failed");
665 /* TODO :remove this after debug */
666 DBG("success to ipsec_load_shared_psk");
669 * Send the load-shared command for XAUTH
671 err = ipsec_load_shared_xauth(provider);
672 IPSEC_ERROR_CHECK_GOTO(err, done, "load-shared failed");
674 /* TODO :remove this after debug */
675 DBG("success to ipsec_load_shared_xauth");
677 * Send the load-cert command
679 err = ipsec_load_cert(provider);
680 IPSEC_ERROR_CHECK_GOTO(err, done, "load-cert failed");
682 /* TODO :remove this after debug */
683 DBG("success to ipsec_load_cert");
686 * Send the load-key command
688 err = ipsec_load_key(provider);
689 IPSEC_ERROR_CHECK_GOTO(err, done, "load-key failed");
691 /* TODO :remove this after debug */
692 DBG("success to ipsec_load_cert");
694 * Send the initiate command
696 err = ipsec_initiate(provider);
697 IPSEC_ERROR_CHECK_GOTO(err, done, "initiate failed");
699 /* TODO :remove this after debug */
700 DBG("success to ipsec_initiate");
703 /* refer to connect_cb on vpn-provider.c for cb */
705 cb(provider, data->connect_user_data, -err);
706 /* TODO: Does close socket needed? when err is not zero */
711 static void monitor_changed(GFileMonitor *monitor, GFile *file, GFile *other_file,
712 GFileMonitorEvent event_type, gpointer user_data)
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;
720 g_object_unref(monitor);
725 static void monitor_vici_socket(struct ipsec_private_data *data)
727 GError *error = NULL;
730 file = g_file_new_for_path(VICI_DEFAULT_URI);
731 monitor = g_file_monitor_file(file, G_FILE_MONITOR_SEND_MOVED, NULL, &error);
733 connman_error("g_file_monitor_directory failed: %s / %d", error->message, error->code);
735 if(event_data.event_cb)
736 event_data.event_cb(event_data.event_user_data, VPN_STATE_FAILURE);
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);
745 static void check_vici_socket(struct ipsec_private_data *data)
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);
752 monitor_vici_socket(data);
756 static void ipsec_died(struct connman_task *task, int exit_code, void *user_data)
758 DBG("task %p exit_code %d", task, exit_code);
759 unlink(VICI_DEFAULT_URI);
760 vpn_died(task, exit_code, user_data);
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,
768 struct ipsec_private_data *data;
771 data = create_ipsec_private_data(provider, cb, user_data);
773 connman_error("create ipsec private data failed");
777 * Start charon daemon using ipsec script of strongSwan.
779 err = connman_task_run(task, ipsec_died, provider, NULL, NULL, NULL);
781 connman_error("charon start failed");
783 cb(provider, user_data, err);
789 check_vici_socket(data);
790 // g_usleep(G_USEC_PER_SEC);
795 static int ipsec_error_code(struct vpn_provider *provider, int exit_code)
800 static int ipsec_save(struct vpn_provider *provider, GKeyFile *keyfile)
807 * Save IKE connection configurations
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);
812 g_key_file_set_string(keyfile,
813 vpn_provider_get_save_group(provider),
814 ipsec_conn_options[i].cm_opt,
819 * Save shared IKE PSK, EAP or XAUTH secret
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);
824 g_key_file_set_string(keyfile,
825 vpn_provider_get_save_group(provider),
826 ipsec_shared_options[i].cm_opt,
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);
836 g_key_file_set_string(keyfile,
837 vpn_provider_get_save_group(provider),
838 ipsec_cert_options[i].cm_opt,
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);
848 g_key_file_set_string(keyfile,
849 vpn_provider_get_save_group(provider),
850 ipsec_pkey_options[i].cm_opt,
855 * Save local certification
857 option = vpn_provider_get_string(provider, "IPsec.LocalCerts");
859 g_key_file_set_string(keyfile,
860 vpn_provider_get_save_group(provider),
863 option = vpn_provider_get_string(provider, "IPsec.LocalCertPass");
865 g_key_file_set_string(keyfile,
866 vpn_provider_get_save_group(provider),
867 "IPsec.LocalCertPass",
870 * Save CA certification directory
872 option = vpn_provider_get_string(provider, "IPsec.CACertsDir");
874 g_key_file_set_string(keyfile,
875 vpn_provider_get_save_group(provider),
882 static void ipsec_disconnect(struct vpn_provider *provider)
886 * Send the terminate command
888 err = ipsec_terminate(provider);
889 IPSEC_ERROR_CHECK_RETURN(err, "terminate failed");
891 err = vici_deinitialize(vici_client);
892 IPSEC_ERROR_CHECK_RETURN(err, "failed to deinitialize vici_client");
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,
904 .disconnect = ipsec_disconnect,
907 static int ipsec_init(void)
909 connection = connman_dbus_get_connection();
911 event_data.event_cb = NULL;
912 event_data.event_user_data = NULL;
914 return vpn_register("ipsec", &vpn_driver, IPSEC);
917 static void ipsec_exit(void)
919 vpn_unregister("ipsec");
921 dbus_connection_unref(connection);
924 CONNMAN_PLUGIN_DEFINE(ipsec, "IPSec plugin", VERSION,
925 CONNMAN_PLUGIN_PRIORITY_DEFAULT, ipsec_init, ipsec_exit)