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>
36 #define CONNMAN_API_SUBJECT_TO_CHANGE
37 #include <connman/plugin.h>
38 #include <connman/log.h>
39 #include <connman/task.h>
40 #include <connman/ipconfig.h>
41 #include <connman/dbus.h>
42 #include <connman/agent.h>
43 #include <connman/setting.h>
44 #include <connman/vpn-dbus.h>
46 #include "../vpn-provider.h"
47 #include "../vpn-agent.h"
52 #define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0]))
62 const char *vpnc_default;
66 { "Host", "IPSec gateway", NULL, OPT_STRING, true },
67 { "VPNC.IPSec.ID", "IPSec ID", NULL, OPT_STRING, true },
68 { "VPNC.IPSec.Secret", "IPSec secret", NULL, OPT_STRING, false },
69 { "VPNC.Xauth.Username", "Xauth username", NULL, OPT_STRING, false },
70 { "VPNC.Xauth.Password", "Xauth password", NULL, OPT_STRING, false },
71 { "VPNC.IKE.Authmode", "IKE Authmode", NULL, OPT_STRING, true },
72 { "VPNC.IKE.DHGroup", "IKE DH Group", NULL, OPT_STRING, true },
73 { "VPNC.PFS", "Perfect Forward Secrecy", NULL, OPT_STRING, true },
74 { "VPNC.Domain", "Domain", NULL, OPT_STRING, true },
75 { "VPNC.Vendor", "Vendor", NULL, OPT_STRING, true },
76 { "VPNC.LocalPort", "Local Port", "0", OPT_STRING, true, },
77 { "VPNC.CiscoPort", "Cisco UDP Encapsulation Port", "0", OPT_STRING,
79 { "VPNC.AppVersion", "Application version", NULL, OPT_STRING, true },
80 { "VPNC.NATTMode", "NAT Traversal Mode", "cisco-udp", OPT_STRING,
82 { "VPNC.DPDTimeout", "DPD idle timeout (our side)", NULL, OPT_STRING,
84 { "VPNC.SingleDES", "Enable Single DES", NULL, OPT_BOOLEAN, true },
85 { "VPNC.NoEncryption", "Enable no encryption", NULL, OPT_BOOLEAN,
89 struct vc_private_data {
90 struct vpn_provider *provider;
91 struct connman_task *task;
93 vpn_provider_connect_cb_t cb;
99 static void vc_connect_done(struct vc_private_data *data, int err)
101 DBG("data %p err %d", data, err);
103 if (data && data->cb) {
104 vpn_provider_connect_cb_t cb = data->cb;
105 void *user_data = data->user_data;
107 /* Make sure we don't invoke this callback twice */
109 data->user_data = NULL;
110 cb(data->provider, user_data, err);
114 static void close_io_channel(struct vc_private_data *data, GIOChannel *channel)
116 if (!data || !channel)
119 if (data->err_ch == channel) {
120 DBG("closing stderr");
122 if (data->err_ch_id) {
123 g_source_remove(data->err_ch_id);
130 g_io_channel_shutdown(data->err_ch, FALSE, NULL);
131 g_io_channel_unref(data->err_ch);
137 static void free_private_data(struct vc_private_data *data)
139 DBG("data %p", data);
141 if (!data || !data->provider)
144 DBG("provider %p", data->provider);
146 if (vpn_provider_get_plugin_data(data->provider) == data)
147 vpn_provider_set_plugin_data(data->provider, NULL);
149 vpn_provider_unref(data->provider);
151 g_free(data->if_name);
155 static int vc_notify(DBusMessage *msg, struct vpn_provider *provider)
157 DBusMessageIter iter, dict;
158 char *address = NULL, *netmask = NULL, *gateway = NULL;
159 struct connman_ipaddress *ipaddress;
160 const char *reason, *key, *value;
161 struct vc_private_data *data;
164 data = vpn_provider_get_plugin_data(provider);
166 dbus_message_iter_init(msg, &iter);
168 type = dbus_message_iter_get_arg_type(&iter);
169 if (type != DBUS_TYPE_STRING) {
170 DBG("invalid D-Bus arg type %d", type);
171 return VPN_STATE_FAILURE;
174 dbus_message_iter_get_basic(&iter, &reason);
175 dbus_message_iter_next(&iter);
178 connman_error("No provider found");
179 vc_connect_done(data, ENOENT);
180 return VPN_STATE_FAILURE;
183 if (g_strcmp0(reason, "connect")) {
184 vc_connect_done(data, EIO);
185 return VPN_STATE_DISCONNECT;
188 dbus_message_iter_recurse(&iter, &dict);
190 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
191 DBusMessageIter entry;
193 dbus_message_iter_recurse(&dict, &entry);
195 type = dbus_message_iter_get_arg_type(&entry);
196 if (type != DBUS_TYPE_STRING)
199 dbus_message_iter_get_basic(&entry, &key);
200 dbus_message_iter_next(&entry);
202 type = dbus_message_iter_get_arg_type(&entry);
203 if (type != DBUS_TYPE_STRING)
206 dbus_message_iter_get_basic(&entry, &value);
208 DBG("%s = %s", key, value);
210 if (!strcmp(key, "VPNGATEWAY"))
211 gateway = g_strdup(value);
213 if (!strcmp(key, "INTERNAL_IP4_ADDRESS"))
214 address = g_strdup(value);
216 if (!strcmp(key, "INTERNAL_IP4_NETMASK"))
217 netmask = g_strdup(value);
219 if (!strcmp(key, "INTERNAL_IP4_DNS"))
220 vpn_provider_set_nameservers(provider, value);
222 if (!strcmp(key, "CISCO_DEF_DOMAIN"))
223 vpn_provider_set_domain(provider, value);
225 if (g_str_has_prefix(key, "CISCO_SPLIT_INC") ||
226 g_str_has_prefix(key, "CISCO_IPV6_SPLIT_INC"))
227 vpn_provider_append_route(provider, key, value);
229 dbus_message_iter_next(&dict);
233 ipaddress = connman_ipaddress_alloc(AF_INET);
238 vc_connect_done(data, EIO);
239 return VPN_STATE_FAILURE;
242 connman_ipaddress_set_ipv4(ipaddress, address, netmask, gateway);
243 vpn_provider_set_ipaddress(provider, ipaddress);
248 connman_ipaddress_free(ipaddress);
250 vc_connect_done(data, 0);
251 return VPN_STATE_CONNECT;
254 static ssize_t full_write(int fd, const void *buf, size_t len)
259 byte_write = write(fd, buf, len);
260 if (byte_write < 0) {
261 connman_error("failed to write config to vpnc: %s\n",
272 static ssize_t write_option(int fd, const char *key, const char *value)
278 buf = g_strdup_printf("%s %s\n", key, value);
279 ret = full_write(fd, buf, strlen(buf));
287 static ssize_t write_bool_option(int fd, const char *key, const char *value)
293 if (strcasecmp(value, "yes") == 0 ||
294 strcasecmp(value, "true") == 0 ||
295 strcmp(value, "1") == 0) {
296 buf = g_strdup_printf("%s\n", key);
297 ret = full_write(fd, buf, strlen(buf));
306 static int vc_write_config_data(struct vpn_provider *provider, int fd)
311 for (i = 0; i < (int)ARRAY_SIZE(vpnc_options); i++) {
312 opt_s = vpn_provider_get_string(provider,
313 vpnc_options[i].cm_opt);
315 opt_s = vpnc_options[i].vpnc_default;
320 if (vpnc_options[i].type == OPT_STRING) {
322 vpnc_options[i].vpnc_opt, opt_s) < 0)
324 } else if (vpnc_options[i].type == OPT_BOOLEAN) {
325 if (write_bool_option(fd,
326 vpnc_options[i].vpnc_opt, opt_s) < 0)
335 static int vc_save(struct vpn_provider *provider, GKeyFile *keyfile)
340 for (i = 0; i < (int)ARRAY_SIZE(vpnc_options); i++) {
341 if (strncmp(vpnc_options[i].cm_opt, "VPNC.", 5) == 0) {
343 if (!vpnc_options[i].cm_save)
346 option = vpn_provider_get_string(provider,
347 vpnc_options[i].cm_opt);
351 g_key_file_set_string(keyfile,
352 vpn_provider_get_save_group(provider),
353 vpnc_options[i].cm_opt, option);
359 static void vc_died(struct connman_task *task, int exit_code, void *user_data)
361 struct vc_private_data *data = user_data;
363 DBG("task %p data %p exit_code %d user_data %p", task, data, exit_code,
369 if (data->provider) {
370 connman_agent_cancel(data->provider);
373 vpn_died(task, exit_code, data->provider);
376 free_private_data(data);
379 static gboolean io_channel_cb(GIOChannel *source, GIOCondition condition,
382 struct vc_private_data *data;
383 const char *auth_failures[] = {
384 VPNC ": hash comparison failed",
385 VPNC ": authentication unsuccessful",
386 VPNC ": expected xauth packet; rejected",
389 const char *conn_failures[] = {
390 VPNC ": unknown host",
391 VPNC ": no response from target",
392 VPNC ": receiving packet: No route to host",
400 if ((condition & G_IO_IN) &&
401 g_io_channel_read_line(source, &str, NULL, NULL, NULL) ==
402 G_IO_STATUS_NORMAL) {
403 str[strlen(str) - 1] = '\0';
405 for (i = 0; auth_failures[i]; i++) {
406 if (g_str_has_prefix(str, auth_failures[i])) {
407 DBG("authentication failed: %s", str);
409 vpn_provider_indicate_error(data->provider,
410 VPN_PROVIDER_ERROR_AUTH_FAILED);
414 for (i = 0; conn_failures[i]; i++) {
415 if (g_str_has_prefix(str, conn_failures[i])) {
416 DBG("connection failed: %s", str);
418 vpn_provider_indicate_error(data->provider,
419 VPN_PROVIDER_ERROR_CONNECT_FAILED);
424 } else if (condition & (G_IO_ERR | G_IO_HUP)) {
425 DBG("Channel termination");
426 close_io_channel(data, source);
427 return G_SOURCE_REMOVE;
430 return G_SOURCE_CONTINUE;
433 static int run_connect(struct vc_private_data *data)
435 struct vpn_provider *provider;
436 struct connman_task *task;
437 const char *credentials[] = {"VPNC.IPSec.Secret", "VPNC.Xauth.Username",
438 "VPNC.Xauth.Password", NULL};
446 provider = data->provider;
448 if_name = data->if_name;
450 DBG("provider %p task %p interface %s user_data %p", provider, task,
451 if_name, data->user_data);
454 * Change to use C locale, options should be in ASCII according to
455 * documentation. To be on the safe side, set both LANG and LC_ALL.
456 * This is required especially when the VPNC processe is ran using an
457 * user other than root.
459 connman_task_add_variable(task,"LANG", "C");
460 connman_task_add_variable(task,"LC_ALL", "C");
462 connman_task_add_argument(task, "--non-inter", NULL);
463 connman_task_add_argument(task, "--no-detach", NULL);
465 connman_task_add_argument(task, "--ifname", if_name);
466 option = vpn_provider_get_string(provider, "VPNC.DeviceType");
468 connman_task_add_argument(task, "--ifmode", option);
471 * Default to tun for backwards compatibility.
473 connman_task_add_argument(task, "--ifmode", "tun");
476 connman_task_add_argument(task, "--script", SCRIPTDIR "/vpn-script");
478 option = vpn_provider_get_string(provider, "VPNC.Debug");
480 connman_task_add_argument(task, "--debug", option);
482 connman_task_add_argument(task, "-", NULL);
484 err = connman_task_run(data->task, vc_died, data, &fd_in, NULL,
487 connman_error("vpnc failed to start");
492 err = vc_write_config_data(provider, fd_in);
495 DBG("config write error %s", strerror(err));
501 data->err_ch = g_io_channel_unix_new(fd_err);
502 data->err_ch_id = g_io_add_watch(data->err_ch,
503 G_IO_IN | G_IO_ERR | G_IO_HUP,
504 (GIOFunc)io_channel_cb, data);
510 * Clear out credentials if they are non-immutable. If this is called
511 * directly from vc_connect() all credentials are read from config and
512 * are set as immutable, so no change is done. In case a VPN agent is
513 * used these values should be reset to "-" in order to retrieve them
514 * from VPN agent next time VPN connection is established. This supports
515 * then partially defined credentials in .config and some can be
516 * retrieved using an agent.
518 for (i = 0; credentials[i]; i++) {
519 const char *key = credentials[i];
520 if (!vpn_provider_get_string_immutable(provider, key))
521 vpn_provider_set_string(provider, key, "-");
527 static void request_input_append_mandatory(DBusMessageIter *iter,
530 char *str = "string";
532 connman_dbus_dict_append_basic(iter, "Type",
533 DBUS_TYPE_STRING, &str);
535 connman_dbus_dict_append_basic(iter, "Requirement",
536 DBUS_TYPE_STRING, &str);
542 connman_dbus_dict_append_basic(iter, "Value", DBUS_TYPE_STRING, &str);
545 static void request_input_append_password(DBusMessageIter *iter,
548 char *str = "password";
550 connman_dbus_dict_append_basic(iter, "Type",
551 DBUS_TYPE_STRING, &str);
553 connman_dbus_dict_append_basic(iter, "Requirement",
554 DBUS_TYPE_STRING, &str);
560 connman_dbus_dict_append_basic(iter, "Value", DBUS_TYPE_STRING, &str);
563 static void request_input_append_informational(DBusMessageIter *iter,
566 char *str = "password";
568 connman_dbus_dict_append_basic(iter, "Type",
569 DBUS_TYPE_STRING, &str);
570 str = "informational";
571 connman_dbus_dict_append_basic(iter, "Requirement",
572 DBUS_TYPE_STRING, &str);
578 connman_dbus_dict_append_basic(iter, "Value", DBUS_TYPE_STRING, &str);
581 static void request_input_append_to_dict(struct vpn_provider *provider,
582 DBusMessageIter *dict,
583 connman_dbus_append_cb_t function_cb, const char *key)
586 bool immutable = false;
588 if (!provider || !dict || !function_cb || !key)
591 str = vpn_provider_get_string(provider, key);
593 /* If value is "-", it is cleared by VPN agent */
594 if (!g_strcmp0(str, "-"))
598 immutable = vpn_provider_get_string_immutable(provider, key);
601 /* Hide immutable password types */
602 if (function_cb == request_input_append_password)
605 /* Send immutable as informational */
606 function_cb = request_input_append_informational;
609 connman_dbus_dict_append_dict(dict, key, function_cb, (void *)str);
612 static void request_input_credentials_reply(DBusMessage *reply, void *user_data)
614 struct vc_private_data *data = user_data;
615 char *secret = NULL, *username = NULL, *password = NULL;
617 DBusMessageIter iter, dict;
620 DBG("provider %p", data->provider);
625 err = vpn_agent_check_and_process_reply_error(reply, data->provider,
626 data->task, data->cb, data->user_data);
628 /* Ensure cb is called only once */
630 data->user_data = NULL;
634 if (!vpn_agent_check_reply_has_dict(reply))
637 dbus_message_iter_init(reply, &iter);
638 dbus_message_iter_recurse(&iter, &dict);
639 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
640 DBusMessageIter entry, value;
642 dbus_message_iter_recurse(&dict, &entry);
643 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
646 dbus_message_iter_get_basic(&entry, &key);
648 if (g_str_equal(key, "VPNC.IPSec.Secret")) {
649 dbus_message_iter_next(&entry);
650 if (dbus_message_iter_get_arg_type(&entry)
651 != DBUS_TYPE_VARIANT)
653 dbus_message_iter_recurse(&entry, &value);
654 if (dbus_message_iter_get_arg_type(&value)
657 dbus_message_iter_get_basic(&value, &secret);
658 vpn_provider_set_string_hide_value(data->provider,
661 } else if (g_str_equal(key, "VPNC.Xauth.Username")) {
662 dbus_message_iter_next(&entry);
663 if (dbus_message_iter_get_arg_type(&entry)
664 != DBUS_TYPE_VARIANT)
666 dbus_message_iter_recurse(&entry, &value);
667 if (dbus_message_iter_get_arg_type(&value)
670 dbus_message_iter_get_basic(&value, &username);
671 vpn_provider_set_string(data->provider, key, username);
673 } else if (g_str_equal(key, "VPNC.Xauth.Password")) {
674 dbus_message_iter_next(&entry);
675 if (dbus_message_iter_get_arg_type(&entry)
676 != DBUS_TYPE_VARIANT)
678 dbus_message_iter_recurse(&entry, &value);
679 if (dbus_message_iter_get_arg_type(&value)
682 dbus_message_iter_get_basic(&value, &password);
683 vpn_provider_set_string_hide_value(data->provider, key,
687 dbus_message_iter_next(&dict);
690 if (!secret || !username || !password)
693 err = run_connect(data);
694 if (err != -EINPROGRESS)
700 vc_connect_done(data, EACCES);
703 static int request_input_credentials(struct vc_private_data *data,
704 const char* dbus_sender)
706 DBusMessage *message;
707 const char *path, *agent_sender, *agent_path;
708 DBusMessageIter iter;
709 DBusMessageIter dict;
713 if (!data || !data->provider)
716 DBG("data %p provider %p sender %s", data, data->provider, dbus_sender);
718 agent = connman_agent_get_info(dbus_sender, &agent_sender, &agent_path);
719 if (!agent || !agent_path)
722 message = dbus_message_new_method_call(agent_sender, agent_path,
728 dbus_message_iter_init_append(message, &iter);
730 path = vpn_provider_get_path(data->provider);
731 dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH, &path);
733 connman_dbus_dict_open(&iter, &dict);
735 if (vpn_provider_get_authentication_errors(data->provider))
736 vpn_agent_append_auth_failure(&dict, data->provider, NULL);
738 request_input_append_to_dict(data->provider, &dict,
739 request_input_append_password,
740 "VPNC.IPSec.Secret");
741 request_input_append_to_dict(data->provider, &dict,
742 request_input_append_mandatory,
743 "VPNC.Xauth.Username");
744 request_input_append_to_dict(data->provider, &dict,
745 request_input_append_password,
746 "VPNC.Xauth.Password");
748 vpn_agent_append_host_and_name(&dict, data->provider);
750 connman_dbus_dict_close(&iter, &dict);
752 err = connman_agent_queue_message(data->provider, message,
753 connman_timeout_input_request(),
754 request_input_credentials_reply, data, agent);
756 dbus_message_unref(message);
758 if (err < 0 && err != -EBUSY) {
759 DBG("error %d sending agent request", err);
766 static int vc_connect(struct vpn_provider *provider,
767 struct connman_task *task, const char *if_name,
768 vpn_provider_connect_cb_t cb, const char *dbus_sender,
771 struct vc_private_data *data;
773 bool username_set = false;
774 bool password_set = false;
775 bool ipsec_secret_set = false;
778 DBG("provider %p if_name %s user_data %p", provider, if_name, user_data);
780 option = vpn_provider_get_string(provider, "VPNC.IPSec.ID");
782 connman_error("Group not set; cannot enable VPN");
786 option = vpn_provider_get_string(provider, "VPNC.IPSec.Secret");
787 if (option && *option && g_strcmp0(option, "-"))
788 ipsec_secret_set = true;
790 option = vpn_provider_get_string(provider, "VPNC.Xauth.Username");
791 if (option && *option && g_strcmp0(option, "-"))
794 option = vpn_provider_get_string(provider, "VPNC.Xauth.Password");
795 if (option && *option && g_strcmp0(option, "-"))
798 data = g_try_new0(struct vc_private_data, 1);
802 vpn_provider_set_plugin_data(provider, data);
803 data->provider = vpn_provider_ref(provider);
805 data->if_name = g_strdup(if_name);
807 data->user_data = user_data;
809 if (!ipsec_secret_set || !username_set || !password_set) {
810 err = request_input_credentials(data, dbus_sender);
811 if (err != -EINPROGRESS) {
812 vc_connect_done(data, ECONNABORTED);
813 vpn_provider_indicate_error(data->provider,
814 VPN_PROVIDER_ERROR_LOGIN_FAILED);
815 free_private_data(data);
821 return run_connect(data);
824 static void vc_disconnect(struct vpn_provider *provider)
829 connman_agent_cancel(provider);
832 static int vc_error_code(struct vpn_provider *provider, int exit_code)
836 return VPN_PROVIDER_ERROR_CONNECT_FAILED;
838 return VPN_PROVIDER_ERROR_LOGIN_FAILED;
840 return VPN_PROVIDER_ERROR_UNKNOWN;
844 static int vc_device_flags(struct vpn_provider *provider)
848 option = vpn_provider_get_string(provider, "VPNC.DeviceType");
853 if (g_str_equal(option, "tap")) {
857 if (!g_str_equal(option, "tun")) {
858 connman_warn("bad VPNC.DeviceType value, falling back to tun");
864 static struct vpn_driver vpn_driver = {
866 .connect = vc_connect,
867 .disconnect = vc_disconnect,
868 .error_code = vc_error_code,
870 .device_flags = vc_device_flags,
873 static int vpnc_init(void)
875 return vpn_register("vpnc", &vpn_driver, VPNC);
878 static void vpnc_exit(void)
880 vpn_unregister("vpnc");
883 CONNMAN_PLUGIN_DEFINE(vpnc, "vpnc plugin", VERSION,
884 CONNMAN_PLUGIN_PRIORITY_DEFAULT, vpnc_init, vpnc_exit)