5 * Copyright (C) 2010,2013 BMW Car IT GmbH.
6 * Copyright (C) 2010,2012-2013 Intel Corporation. All rights reserved.
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
32 #include <linux/if_tun.h>
33 #include <sys/types.h>
40 #define CONNMAN_API_SUBJECT_TO_CHANGE
41 #include <connman/plugin.h>
42 #include <connman/log.h>
43 #include <connman/task.h>
44 #include <connman/ipconfig.h>
45 #include <connman/dbus.h>
46 #include <connman/agent.h>
47 #include <connman/setting.h>
48 #include <connman/vpn-dbus.h>
50 #include "../vpn-provider.h"
51 #include "../vpn-agent.h"
56 #define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0]))
57 #define PID_PATH_ROOT "/var/run/user"
67 const char *vpnc_default;
71 { "Host", "IPSec gateway", NULL, OPT_STRING, true },
72 { "VPNC.IPSec.ID", "IPSec ID", NULL, OPT_STRING, true },
73 { "VPNC.IPSec.Secret", "IPSec secret", NULL, OPT_STRING, false },
74 { "VPNC.Xauth.Username", "Xauth username", NULL, OPT_STRING, false },
75 { "VPNC.Xauth.Password", "Xauth password", NULL, OPT_STRING, false },
76 { "VPNC.IKE.Authmode", "IKE Authmode", NULL, OPT_STRING, true },
77 { "VPNC.IKE.DHGroup", "IKE DH Group", NULL, OPT_STRING, true },
78 { "VPNC.PFS", "Perfect Forward Secrecy", NULL, OPT_STRING, true },
79 { "VPNC.Domain", "Domain", NULL, OPT_STRING, true },
80 { "VPNC.Vendor", "Vendor", NULL, OPT_STRING, true },
81 { "VPNC.LocalPort", "Local Port", "0", OPT_STRING, true, },
82 { "VPNC.CiscoPort", "Cisco UDP Encapsulation Port", "0", OPT_STRING,
84 { "VPNC.AppVersion", "Application version", NULL, OPT_STRING, true },
85 { "VPNC.NATTMode", "NAT Traversal Mode", "cisco-udp", OPT_STRING,
87 { "VPNC.DPDTimeout", "DPD idle timeout (our side)", NULL, OPT_STRING,
89 { "VPNC.SingleDES", "Enable Single DES", NULL, OPT_BOOLEAN, true },
90 { "VPNC.NoEncryption", "Enable no encryption", NULL, OPT_BOOLEAN,
94 struct vc_private_data {
95 struct vpn_provider *provider;
96 struct connman_task *task;
98 vpn_provider_connect_cb_t cb;
104 static void vc_connect_done(struct vc_private_data *data, int err)
106 DBG("data %p err %d", data, err);
108 if (data && data->cb) {
109 vpn_provider_connect_cb_t cb = data->cb;
110 void *user_data = data->user_data;
112 /* Make sure we don't invoke this callback twice */
114 data->user_data = NULL;
115 cb(data->provider, user_data, err);
119 static void close_io_channel(struct vc_private_data *data, GIOChannel *channel)
121 if (!data || !channel)
124 if (data->err_ch == channel) {
125 DBG("closing stderr");
127 if (data->err_ch_id) {
128 g_source_remove(data->err_ch_id);
135 g_io_channel_shutdown(data->err_ch, FALSE, NULL);
136 g_io_channel_unref(data->err_ch);
142 static void free_private_data(struct vc_private_data *data)
144 DBG("data %p", data);
146 if (!data || !data->provider)
149 DBG("provider %p", data->provider);
151 if (vpn_provider_get_plugin_data(data->provider) == data)
152 vpn_provider_set_plugin_data(data->provider, NULL);
154 vpn_provider_unref(data->provider);
156 g_free(data->if_name);
160 static int vc_notify(DBusMessage *msg, struct vpn_provider *provider)
162 DBusMessageIter iter, dict;
163 char *address = NULL, *netmask = NULL, *gateway = NULL;
164 struct connman_ipaddress *ipaddress;
165 const char *reason, *key, *value;
166 struct vc_private_data *data;
169 data = vpn_provider_get_plugin_data(provider);
171 dbus_message_iter_init(msg, &iter);
173 type = dbus_message_iter_get_arg_type(&iter);
174 if (type != DBUS_TYPE_STRING) {
175 DBG("invalid D-Bus arg type %d", type);
176 return VPN_STATE_FAILURE;
179 dbus_message_iter_get_basic(&iter, &reason);
180 dbus_message_iter_next(&iter);
183 connman_error("No provider found");
184 vc_connect_done(data, ENOENT);
185 return VPN_STATE_FAILURE;
188 if (g_strcmp0(reason, "connect")) {
189 vc_connect_done(data, EIO);
190 return VPN_STATE_DISCONNECT;
193 dbus_message_iter_recurse(&iter, &dict);
195 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
196 DBusMessageIter entry;
198 dbus_message_iter_recurse(&dict, &entry);
200 type = dbus_message_iter_get_arg_type(&entry);
201 if (type != DBUS_TYPE_STRING)
204 dbus_message_iter_get_basic(&entry, &key);
205 dbus_message_iter_next(&entry);
207 type = dbus_message_iter_get_arg_type(&entry);
208 if (type != DBUS_TYPE_STRING)
211 dbus_message_iter_get_basic(&entry, &value);
213 DBG("%s = %s", key, value);
215 if (!strcmp(key, "VPNGATEWAY"))
216 gateway = g_strdup(value);
218 if (!strcmp(key, "INTERNAL_IP4_ADDRESS"))
219 address = g_strdup(value);
221 if (!strcmp(key, "INTERNAL_IP4_NETMASK"))
222 netmask = g_strdup(value);
224 if (!strcmp(key, "INTERNAL_IP4_DNS"))
225 vpn_provider_set_nameservers(provider, value);
227 if (!strcmp(key, "CISCO_DEF_DOMAIN"))
228 vpn_provider_set_domain(provider, value);
230 if (g_str_has_prefix(key, "CISCO_SPLIT_INC") ||
231 g_str_has_prefix(key, "CISCO_IPV6_SPLIT_INC"))
232 vpn_provider_append_route(provider, key, value);
234 dbus_message_iter_next(&dict);
238 ipaddress = connman_ipaddress_alloc(AF_INET);
243 vc_connect_done(data, EIO);
244 return VPN_STATE_FAILURE;
247 connman_ipaddress_set_ipv4(ipaddress, address, netmask, gateway);
248 connman_ipaddress_set_p2p(ipaddress, true);
249 vpn_provider_set_ipaddress(provider, ipaddress);
254 connman_ipaddress_free(ipaddress);
256 vc_connect_done(data, 0);
257 return VPN_STATE_CONNECT;
260 static ssize_t full_write(int fd, const void *buf, size_t len)
265 byte_write = write(fd, buf, len);
266 if (byte_write < 0) {
267 connman_error("failed to write config to vpnc: %s\n",
278 static ssize_t write_option(int fd, const char *key, const char *value)
284 buf = g_strdup_printf("%s %s\n", key, value);
285 ret = full_write(fd, buf, strlen(buf));
293 static ssize_t write_bool_option(int fd, const char *key, const char *value)
299 if (strcasecmp(value, "yes") == 0 ||
300 strcasecmp(value, "true") == 0 ||
301 strcmp(value, "1") == 0) {
302 buf = g_strdup_printf("%s\n", key);
303 ret = full_write(fd, buf, strlen(buf));
312 static int vc_write_config_data(struct vpn_provider *provider, int fd)
317 for (i = 0; i < (int)ARRAY_SIZE(vpnc_options); i++) {
318 opt_s = vpn_provider_get_string(provider,
319 vpnc_options[i].cm_opt);
321 opt_s = vpnc_options[i].vpnc_default;
326 if (vpnc_options[i].type == OPT_STRING) {
328 vpnc_options[i].vpnc_opt, opt_s) < 0)
330 } else if (vpnc_options[i].type == OPT_BOOLEAN) {
331 if (write_bool_option(fd,
332 vpnc_options[i].vpnc_opt, opt_s) < 0)
341 static int vc_save(struct vpn_provider *provider, GKeyFile *keyfile)
346 for (i = 0; i < (int)ARRAY_SIZE(vpnc_options); i++) {
347 if (strncmp(vpnc_options[i].cm_opt, "VPNC.", 5) == 0) {
349 if (!vpnc_options[i].cm_save)
352 option = vpn_provider_get_string(provider,
353 vpnc_options[i].cm_opt);
357 g_key_file_set_string(keyfile,
358 vpn_provider_get_save_group(provider),
359 vpnc_options[i].cm_opt, option);
365 static void vc_died(struct connman_task *task, int exit_code, void *user_data)
367 struct vc_private_data *data = user_data;
369 DBG("task %p data %p exit_code %d user_data %p", task, data, exit_code,
375 if (data->provider) {
376 connman_agent_cancel(data->provider);
379 vpn_died(task, exit_code, data->provider);
382 free_private_data(data);
385 static gboolean io_channel_cb(GIOChannel *source, GIOCondition condition,
388 struct vc_private_data *data;
389 const char *auth_failures[] = {
390 VPNC ": hash comparison failed",
391 VPNC ": authentication unsuccessful",
392 VPNC ": expected xauth packet; rejected",
395 const char *conn_failures[] = {
396 VPNC ": unknown host",
397 VPNC ": no response from target",
398 VPNC ": receiving packet: No route to host",
406 if ((condition & G_IO_IN) &&
407 g_io_channel_read_line(source, &str, NULL, NULL, NULL) ==
408 G_IO_STATUS_NORMAL) {
409 str[strlen(str) - 1] = '\0';
411 for (i = 0; auth_failures[i]; i++) {
412 if (g_str_has_prefix(str, auth_failures[i])) {
413 DBG("authentication failed: %s", str);
415 vpn_provider_indicate_error(data->provider,
416 VPN_PROVIDER_ERROR_AUTH_FAILED);
420 for (i = 0; conn_failures[i]; i++) {
421 if (g_str_has_prefix(str, conn_failures[i])) {
422 DBG("connection failed: %s", str);
424 vpn_provider_indicate_error(data->provider,
425 VPN_PROVIDER_ERROR_CONNECT_FAILED);
430 } else if (condition & (G_IO_ERR | G_IO_HUP)) {
431 DBG("Channel termination");
432 close_io_channel(data, source);
433 return G_SOURCE_REMOVE;
436 return G_SOURCE_CONTINUE;
439 static char *create_pid_path(const char *user, const char *group)
444 char *pid_path = NULL;
445 int mode = S_IRWXU|S_IRWXG;
451 if (vpn_settings_is_system_user(user))
454 pwd = vpn_util_get_passwd(user);
455 uid_str = g_strdup_printf("%d", pwd->pw_uid);
457 grp = vpn_util_get_group(group);
458 gid = grp ? grp->gr_gid : pwd->pw_gid;
460 pid_path = g_build_filename(PID_PATH_ROOT, uid_str, "vpnc", "pid",
462 if (vpn_util_create_path(pid_path, pwd->pw_uid, gid, mode)) {
472 static int run_connect(struct vc_private_data *data)
474 struct vpn_provider *provider;
475 struct connman_task *task;
476 struct vpn_plugin_data *plugin_data;
477 const char *credentials[] = {"VPNC.IPSec.Secret", "VPNC.Xauth.Username",
478 "VPNC.Xauth.Password", NULL};
487 provider = data->provider;
489 if_name = data->if_name;
491 DBG("provider %p task %p interface %s user_data %p", provider, task,
492 if_name, data->user_data);
495 * Change to use C locale, options should be in ASCII according to
496 * documentation. To be on the safe side, set both LANG and LC_ALL.
497 * This is required especially when the VPNC processe is ran using an
498 * user other than root.
500 connman_task_add_variable(task,"LANG", "C");
501 connman_task_add_variable(task,"LC_ALL", "C");
503 connman_task_add_argument(task, "--non-inter", NULL);
504 connman_task_add_argument(task, "--no-detach", NULL);
506 connman_task_add_argument(task, "--ifname", if_name);
507 option = vpn_provider_get_string(provider, "VPNC.DeviceType");
509 connman_task_add_argument(task, "--ifmode", option);
512 * Default to tun for backwards compatibility.
514 connman_task_add_argument(task, "--ifmode", "tun");
517 plugin_data = vpn_settings_get_vpn_plugin_config("vpnc");
519 option = vpn_settings_get_binary_user(plugin_data);
521 pid_path = create_pid_path(option,
522 vpn_settings_get_binary_group(
525 connman_task_add_argument(task, "--pid-file",
531 connman_task_add_argument(task, "--script", SCRIPTDIR "/vpn-script");
533 option = vpn_provider_get_string(provider, "VPNC.Debug");
535 connman_task_add_argument(task, "--debug", option);
537 connman_task_add_argument(task, "-", NULL);
539 err = connman_task_run(data->task, vc_died, data, &fd_in, NULL,
542 connman_error("vpnc failed to start");
547 err = vc_write_config_data(provider, fd_in);
550 DBG("config write error %s", strerror(err));
556 data->err_ch = g_io_channel_unix_new(fd_err);
557 data->err_ch_id = g_io_add_watch(data->err_ch,
558 G_IO_IN | G_IO_ERR | G_IO_HUP,
559 (GIOFunc)io_channel_cb, data);
565 * Clear out credentials if they are non-immutable. If this is called
566 * directly from vc_connect() all credentials are read from config and
567 * are set as immutable, so no change is done. In case a VPN agent is
568 * used these values should be reset to "-" in order to retrieve them
569 * from VPN agent next time VPN connection is established. This supports
570 * then partially defined credentials in .config and some can be
571 * retrieved using an agent.
573 for (i = 0; credentials[i]; i++) {
574 const char *key = credentials[i];
575 if (!vpn_provider_get_string_immutable(provider, key))
576 vpn_provider_set_string(provider, key, "-");
582 static void request_input_append_mandatory(DBusMessageIter *iter,
585 char *str = "string";
587 connman_dbus_dict_append_basic(iter, "Type",
588 DBUS_TYPE_STRING, &str);
590 connman_dbus_dict_append_basic(iter, "Requirement",
591 DBUS_TYPE_STRING, &str);
597 connman_dbus_dict_append_basic(iter, "Value", DBUS_TYPE_STRING, &str);
600 static void request_input_append_password(DBusMessageIter *iter,
603 char *str = "password";
605 connman_dbus_dict_append_basic(iter, "Type",
606 DBUS_TYPE_STRING, &str);
608 connman_dbus_dict_append_basic(iter, "Requirement",
609 DBUS_TYPE_STRING, &str);
615 connman_dbus_dict_append_basic(iter, "Value", DBUS_TYPE_STRING, &str);
618 static void request_input_append_informational(DBusMessageIter *iter,
621 char *str = "password";
623 connman_dbus_dict_append_basic(iter, "Type",
624 DBUS_TYPE_STRING, &str);
625 str = "informational";
626 connman_dbus_dict_append_basic(iter, "Requirement",
627 DBUS_TYPE_STRING, &str);
633 connman_dbus_dict_append_basic(iter, "Value", DBUS_TYPE_STRING, &str);
636 static void request_input_append_to_dict(struct vpn_provider *provider,
637 DBusMessageIter *dict,
638 connman_dbus_append_cb_t function_cb, const char *key)
641 bool immutable = false;
643 if (!provider || !dict || !function_cb || !key)
646 str = vpn_provider_get_string(provider, key);
648 /* If value is "-", it is cleared by VPN agent */
649 if (!g_strcmp0(str, "-"))
653 immutable = vpn_provider_get_string_immutable(provider, key);
656 /* Hide immutable password types */
657 if (function_cb == request_input_append_password)
660 /* Send immutable as informational */
661 function_cb = request_input_append_informational;
664 connman_dbus_dict_append_dict(dict, key, function_cb, (void *)str);
667 static void request_input_credentials_reply(DBusMessage *reply, void *user_data)
669 struct vc_private_data *data = user_data;
670 char *secret = NULL, *username = NULL, *password = NULL;
672 DBusMessageIter iter, dict;
675 DBG("provider %p", data->provider);
682 err = vpn_agent_check_and_process_reply_error(reply, data->provider,
683 data->task, data->cb, data->user_data);
685 /* Ensure cb is called only once */
687 data->user_data = NULL;
691 if (!vpn_agent_check_reply_has_dict(reply)) {
696 dbus_message_iter_init(reply, &iter);
697 dbus_message_iter_recurse(&iter, &dict);
698 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
699 DBusMessageIter entry, value;
701 dbus_message_iter_recurse(&dict, &entry);
702 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
705 dbus_message_iter_get_basic(&entry, &key);
707 if (g_str_equal(key, "VPNC.IPSec.Secret")) {
708 dbus_message_iter_next(&entry);
709 if (dbus_message_iter_get_arg_type(&entry)
710 != DBUS_TYPE_VARIANT)
712 dbus_message_iter_recurse(&entry, &value);
713 if (dbus_message_iter_get_arg_type(&value)
716 dbus_message_iter_get_basic(&value, &secret);
717 vpn_provider_set_string_hide_value(data->provider,
720 } else if (g_str_equal(key, "VPNC.Xauth.Username")) {
721 dbus_message_iter_next(&entry);
722 if (dbus_message_iter_get_arg_type(&entry)
723 != DBUS_TYPE_VARIANT)
725 dbus_message_iter_recurse(&entry, &value);
726 if (dbus_message_iter_get_arg_type(&value)
729 dbus_message_iter_get_basic(&value, &username);
730 vpn_provider_set_string(data->provider, key, username);
732 } else if (g_str_equal(key, "VPNC.Xauth.Password")) {
733 dbus_message_iter_next(&entry);
734 if (dbus_message_iter_get_arg_type(&entry)
735 != DBUS_TYPE_VARIANT)
737 dbus_message_iter_recurse(&entry, &value);
738 if (dbus_message_iter_get_arg_type(&value)
741 dbus_message_iter_get_basic(&value, &password);
742 vpn_provider_set_string_hide_value(data->provider, key,
746 dbus_message_iter_next(&dict);
749 if (!secret || !username || !password) {
750 vpn_provider_indicate_error(data->provider,
751 VPN_PROVIDER_ERROR_AUTH_FAILED);
756 /* vpn_provider.c:connect_cb() expects positive errors */
757 err = -run_connect(data);
758 if (err != EINPROGRESS)
764 vc_connect_done(data, err);
767 static int request_input_credentials(struct vc_private_data *data,
768 const char* dbus_sender)
770 DBusMessage *message;
771 const char *path, *agent_sender, *agent_path;
772 DBusMessageIter iter;
773 DBusMessageIter dict;
777 if (!data || !data->provider)
780 DBG("data %p provider %p sender %s", data, data->provider, dbus_sender);
782 agent = connman_agent_get_info(dbus_sender, &agent_sender, &agent_path);
783 if (!agent || !agent_path)
786 message = dbus_message_new_method_call(agent_sender, agent_path,
792 dbus_message_iter_init_append(message, &iter);
794 path = vpn_provider_get_path(data->provider);
795 dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH, &path);
797 connman_dbus_dict_open(&iter, &dict);
799 if (vpn_provider_get_authentication_errors(data->provider))
800 vpn_agent_append_auth_failure(&dict, data->provider, NULL);
802 request_input_append_to_dict(data->provider, &dict,
803 request_input_append_password,
804 "VPNC.IPSec.Secret");
805 request_input_append_to_dict(data->provider, &dict,
806 request_input_append_mandatory,
807 "VPNC.Xauth.Username");
808 request_input_append_to_dict(data->provider, &dict,
809 request_input_append_password,
810 "VPNC.Xauth.Password");
812 vpn_agent_append_host_and_name(&dict, data->provider);
814 connman_dbus_dict_close(&iter, &dict);
816 err = connman_agent_queue_message(data->provider, message,
817 connman_timeout_input_request(),
818 request_input_credentials_reply, data, agent);
820 dbus_message_unref(message);
822 if (err < 0 && err != -EBUSY) {
823 DBG("error %d sending agent request", err);
830 static int vc_connect(struct vpn_provider *provider,
831 struct connman_task *task, const char *if_name,
832 vpn_provider_connect_cb_t cb, const char *dbus_sender,
835 struct vc_private_data *data;
837 bool username_set = false;
838 bool password_set = false;
839 bool ipsec_secret_set = false;
842 DBG("provider %p if_name %s user_data %p", provider, if_name, user_data);
844 option = vpn_provider_get_string(provider, "VPNC.IPSec.ID");
846 connman_error("Group not set; cannot enable VPN");
850 option = vpn_provider_get_string(provider, "VPNC.IPSec.Secret");
851 if (option && *option && g_strcmp0(option, "-"))
852 ipsec_secret_set = true;
854 option = vpn_provider_get_string(provider, "VPNC.Xauth.Username");
855 if (option && *option && g_strcmp0(option, "-"))
858 option = vpn_provider_get_string(provider, "VPNC.Xauth.Password");
859 if (option && *option && g_strcmp0(option, "-"))
862 data = g_try_new0(struct vc_private_data, 1);
866 vpn_provider_set_plugin_data(provider, data);
867 data->provider = vpn_provider_ref(provider);
869 data->if_name = g_strdup(if_name);
871 data->user_data = user_data;
873 if (!ipsec_secret_set || !username_set || !password_set) {
874 err = request_input_credentials(data, dbus_sender);
875 if (err != -EINPROGRESS) {
876 vc_connect_done(data, ECONNABORTED);
877 vpn_provider_indicate_error(data->provider,
878 VPN_PROVIDER_ERROR_LOGIN_FAILED);
879 free_private_data(data);
885 return run_connect(data);
888 static void vc_disconnect(struct vpn_provider *provider)
893 connman_agent_cancel(provider);
896 static int vc_error_code(struct vpn_provider *provider, int exit_code)
900 return VPN_PROVIDER_ERROR_CONNECT_FAILED;
902 return VPN_PROVIDER_ERROR_LOGIN_FAILED;
904 return VPN_PROVIDER_ERROR_UNKNOWN;
908 static int vc_device_flags(struct vpn_provider *provider)
912 option = vpn_provider_get_string(provider, "VPNC.DeviceType");
917 if (g_str_equal(option, "tap")) {
921 if (!g_str_equal(option, "tun")) {
922 connman_warn("bad VPNC.DeviceType value, falling back to tun");
928 static struct vpn_driver vpn_driver = {
930 .connect = vc_connect,
931 .disconnect = vc_disconnect,
932 .error_code = vc_error_code,
934 .device_flags = vc_device_flags,
937 static int vpnc_init(void)
939 return vpn_register("vpnc", &vpn_driver, VPNC);
942 static void vpnc_exit(void)
944 vpn_unregister("vpnc");
947 CONNMAN_PLUGIN_DEFINE(vpnc, "vpnc plugin", VERSION,
948 CONNMAN_PLUGIN_PRIORITY_DEFAULT, vpnc_init, vpnc_exit)