5 * Copyright (C) 2010-2014 BMW Car IT GmbH.
6 * Copyright (C) 2016-2019 Jolla Ltd.
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
33 #include <linux/if_tun.h>
34 #include <sys/types.h>
35 #include <sys/socket.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/dbus.h>
45 #include <connman/ipconfig.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"
55 #define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0]))
57 static DBusConnection *connection;
68 const char *ov_opt_to_null;
69 enum opt_type opt_type;
71 { "Host", "--remote", NULL, OPT_STRING},
72 { "OpenVPN.CACert", "--ca", NULL, OPT_STRING},
73 { "OpenVPN.Cert", "--cert", NULL, OPT_STRING},
74 { "OpenVPN.Key", "--key", NULL, OPT_STRING},
75 { "OpenVPN.MTU", "--tun-mtu", NULL, OPT_STRING},
76 { "OpenVPN.NSCertType", "--ns-cert-type", NULL, OPT_STRING},
77 { "OpenVPN.Proto", "--proto", NULL, OPT_STRING},
78 { "OpenVPN.Port", "--port", NULL, OPT_STRING},
80 * If the AuthUserPass option is "-", provide the input via management
81 * interface. To facilitate this set the option as NULL.
83 { "OpenVPN.AuthUserPass", "--auth-user-pass", "-", OPT_STRING},
84 { "OpenVPN.AskPass", "--askpass", NULL, OPT_STRING},
85 { "OpenVPN.AuthNoCache", "--auth-nocache", NULL, OPT_BOOL},
86 { "OpenVPN.TLSRemote", "--tls-remote", NULL, OPT_STRING},
87 { "OpenVPN.TLSAuth", NULL, NULL, OPT_NONE},
88 { "OpenVPN.TLSCipher", "--tls-cipher", NULL, OPT_STRING},
89 { "OpenVPN.TLSAuthDir", NULL, NULL, OPT_NONE},
90 { "OpenVPN.Cipher", "--cipher", NULL, OPT_STRING},
91 { "OpenVPN.Auth", "--auth", NULL, OPT_STRING},
92 /* Is set to adaptive by default if value is omitted */
93 { "OpenVPN.CompLZO", "--comp-lzo", NULL, OPT_STRING},
94 { "OpenVPN.RemoteCertTls", "--remote-cert-tls", NULL, OPT_STRING},
95 { "OpenVPN.ConfigFile", "--config", NULL, OPT_STRING},
96 { "OpenVPN.DeviceType", NULL, NULL, OPT_NONE},
97 { "OpenVPN.Verb", "--verb", NULL, OPT_STRING},
98 { "OpenVPN.Ping", "--ping", NULL, OPT_STRING},
99 { "OpenVPN.PingExit", "--ping-exit", NULL, OPT_STRING},
100 { "OpenVPN.RemapUsr1", "--remap-usr1", NULL, OPT_STRING},
103 struct ov_private_data {
104 struct vpn_provider *provider;
105 struct connman_task *task;
108 vpn_provider_connect_cb_t cb;
113 GIOChannel *mgmt_channel;
114 int connect_attempts;
115 int failed_attempts_privatekey;
118 static void ov_connect_done(struct ov_private_data *data, int err)
120 if (data && data->cb) {
121 vpn_provider_connect_cb_t cb = data->cb;
122 void *user_data = data->user_data;
124 /* Make sure we don't invoke this callback twice */
126 data->user_data = NULL;
127 cb(data->provider, user_data, err);
131 data->failed_attempts_privatekey = 0;
134 static void free_private_data(struct ov_private_data *data)
136 if (vpn_provider_get_plugin_data(data->provider) == data)
137 vpn_provider_set_plugin_data(data->provider, NULL);
139 ov_connect_done(data, EIO);
140 vpn_provider_unref(data->provider);
141 g_free(data->dbus_sender);
142 g_free(data->if_name);
143 g_free(data->mgmt_path);
147 struct nameserver_entry {
152 static struct nameserver_entry *ov_append_dns_entries(const char *key,
155 struct nameserver_entry *entry = NULL;
158 if (!g_str_has_prefix(key, "foreign_option_"))
161 options = g_strsplit(value, " ", 3);
163 !strcmp(options[0], "dhcp-option") &&
165 !strcmp(options[1], "DNS") &&
168 entry = g_try_new(struct nameserver_entry, 1);
169 #if defined TIZEN_EXT
179 entry->nameserver = g_strdup(options[2]);
180 entry->id = atoi(key + 15); /* foreign_option_XXX */
188 static char *ov_get_domain_name(const char *key, const char *value)
193 if (!g_str_has_prefix(key, "foreign_option_"))
196 options = g_strsplit(value, " ", 3);
198 !strcmp(options[0], "dhcp-option") &&
200 !strcmp(options[1], "DOMAIN") &&
203 domain = g_strdup(options[2]);
211 static gint cmp_ns(gconstpointer a, gconstpointer b)
213 struct nameserver_entry *entry_a = (struct nameserver_entry *)a;
214 struct nameserver_entry *entry_b = (struct nameserver_entry *)b;
216 if (entry_a->id < entry_b->id)
219 if (entry_a->id > entry_b->id)
225 static void free_ns_entry(gpointer data)
227 struct nameserver_entry *entry = data;
229 g_free(entry->nameserver);
233 static int ov_notify(DBusMessage *msg, struct vpn_provider *provider)
235 DBusMessageIter iter, dict;
236 const char *reason, *key, *value;
237 char *address = NULL, *gateway = NULL, *peer = NULL, *netmask = NULL;
238 struct connman_ipaddress *ipaddress;
239 GSList *nameserver_list = NULL;
240 struct ov_private_data *data = vpn_provider_get_plugin_data(provider);
242 dbus_message_iter_init(msg, &iter);
244 dbus_message_iter_get_basic(&iter, &reason);
245 dbus_message_iter_next(&iter);
248 connman_error("No provider found");
249 return VPN_STATE_FAILURE;
252 DBG("%p %s", vpn_provider_get_name(provider), reason);
254 if (strcmp(reason, "up")) {
255 ov_connect_done(data, EIO);
256 return VPN_STATE_DISCONNECT;
259 dbus_message_iter_recurse(&iter, &dict);
261 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
262 struct nameserver_entry *ns_entry = NULL;
263 DBusMessageIter entry;
265 dbus_message_iter_recurse(&dict, &entry);
266 dbus_message_iter_get_basic(&entry, &key);
267 dbus_message_iter_next(&entry);
268 dbus_message_iter_get_basic(&entry, &value);
270 DBG("%s = %s", key, value);
272 if (!strcmp(key, "trusted_ip"))
273 gateway = g_strdup(value);
275 if (!strcmp(key, "ifconfig_local"))
276 address = g_strdup(value);
278 if (!strcmp(key, "ifconfig_netmask"))
279 netmask = g_strdup(value);
281 if (!strcmp(key, "ifconfig_remote"))
282 peer = g_strdup(value);
284 if (g_str_has_prefix(key, "route_"))
285 vpn_provider_append_route(provider, key, value);
287 if ((ns_entry = ov_append_dns_entries(key, value)))
288 nameserver_list = g_slist_prepend(nameserver_list,
291 char *domain = ov_get_domain_name(key, value);
293 vpn_provider_set_domain(provider, domain);
298 dbus_message_iter_next(&dict);
301 ipaddress = connman_ipaddress_alloc(AF_INET);
303 g_slist_free_full(nameserver_list, free_ns_entry);
309 return VPN_STATE_FAILURE;
312 connman_ipaddress_set_ipv4(ipaddress, address, netmask, gateway);
313 connman_ipaddress_set_peer(ipaddress, peer);
314 connman_ipaddress_set_p2p(ipaddress, true);
315 vpn_provider_set_ipaddress(provider, ipaddress);
317 if (nameserver_list) {
318 char *nameservers = NULL;
321 nameserver_list = g_slist_sort(nameserver_list, cmp_ns);
322 for (tmp = nameserver_list; tmp;
323 tmp = g_slist_next(tmp)) {
324 struct nameserver_entry *ns = tmp->data;
327 nameservers = g_strdup(ns->nameserver);
330 str = g_strjoin(" ", nameservers,
331 ns->nameserver, NULL);
337 g_slist_free_full(nameserver_list, free_ns_entry);
339 vpn_provider_set_nameservers(provider, nameservers);
348 connman_ipaddress_free(ipaddress);
350 ov_connect_done(data, 0);
351 return VPN_STATE_CONNECT;
354 static int ov_save(struct vpn_provider *provider, GKeyFile *keyfile)
359 for (i = 0; i < (int)ARRAY_SIZE(ov_options); i++) {
360 if (strncmp(ov_options[i].cm_opt, "OpenVPN.", 8) == 0) {
361 option = vpn_provider_get_string(provider,
362 ov_options[i].cm_opt);
366 g_key_file_set_string(keyfile,
367 vpn_provider_get_save_group(provider),
368 ov_options[i].cm_opt, option);
374 static int task_append_config_data(struct vpn_provider *provider,
375 struct connman_task *task)
379 for (i = 0; i < (int)ARRAY_SIZE(ov_options); i++) {
380 const char *ov_opt = ov_options[i].ov_opt;
381 const char *cm_opt = ov_options[i].cm_opt;
382 const char *option = NULL;
383 const char *opt_to_null;
385 switch (ov_options[i].opt_type) {
393 option = vpn_provider_get_string(provider, cm_opt);
395 * A string option may be used alone without a value
396 * in which case the default value is used by OpenVPN.
398 if (!option && !vpn_provider_setting_key_exists(
402 opt_to_null = ov_options[i].ov_opt_to_null;
403 if (opt_to_null && !g_strcmp0(option, opt_to_null))
412 /* Ignore the boolean toggle if option is disabled. */
413 if (!vpn_provider_get_boolean(provider, cm_opt, false))
419 if (connman_task_add_argument(task, ov_opt, option))
427 static void close_management_interface(struct ov_private_data *data)
429 if (data->mgmt_path) {
430 if (unlink(data->mgmt_path) && errno != ENOENT)
431 connman_warn("Unable to unlink management socket %s: "
432 "%d", data->mgmt_path, errno);
434 g_free(data->mgmt_path);
435 data->mgmt_path = NULL;
438 if (data->mgmt_timer_id != 0) {
439 g_source_remove(data->mgmt_timer_id);
440 data->mgmt_timer_id = 0;
443 if (data->mgmt_event_id) {
444 g_source_remove(data->mgmt_event_id);
445 data->mgmt_event_id = 0;
448 if (data->mgmt_channel) {
449 g_io_channel_shutdown(data->mgmt_channel, FALSE, NULL);
450 g_io_channel_unref(data->mgmt_channel);
451 data->mgmt_channel = NULL;
455 static void ov_died(struct connman_task *task, int exit_code, void *user_data)
457 struct ov_private_data *data = user_data;
459 /* Cancel any pending agent requests */
460 connman_agent_cancel(data->provider);
462 close_management_interface(data);
464 vpn_died(task, exit_code, data->provider);
466 free_private_data(data);
469 static int run_connect(struct ov_private_data *data,
470 vpn_provider_connect_cb_t cb, void *user_data)
472 struct vpn_provider *provider = data->provider;
473 struct connman_task *task = data->task;
477 option = vpn_provider_get_string(provider, "OpenVPN.ConfigFile");
480 * Set some default options if user has no config file.
482 option = vpn_provider_get_string(provider, "OpenVPN.TLSAuth");
484 connman_task_add_argument(task, "--tls-auth", option);
485 option = vpn_provider_get_string(provider,
486 "OpenVPN.TLSAuthDir");
488 connman_task_add_argument(task, option, NULL);
491 connman_task_add_argument(task, "--nobind", NULL);
492 connman_task_add_argument(task, "--persist-key", NULL);
493 connman_task_add_argument(task, "--client", NULL);
496 if (data->mgmt_path) {
497 connman_task_add_argument(task, "--management", NULL);
498 connman_task_add_argument(task, data->mgmt_path, NULL);
499 connman_task_add_argument(task, "unix", NULL);
500 connman_task_add_argument(task, "--management-query-passwords",
502 connman_task_add_argument(task, "--auth-retry", "interact");
505 connman_task_add_argument(task, "--syslog", NULL);
507 connman_task_add_argument(task, "--script-security", "2");
509 connman_task_add_argument(task, "--up",
510 SCRIPTDIR "/openvpn-script");
511 connman_task_add_argument(task, "--up-restart", NULL);
513 connman_task_add_argument(task, "--setenv", NULL);
514 connman_task_add_argument(task, "CONNMAN_BUSNAME",
515 dbus_bus_get_unique_name(connection));
517 connman_task_add_argument(task, "--setenv", NULL);
518 connman_task_add_argument(task, "CONNMAN_INTERFACE",
519 CONNMAN_TASK_INTERFACE);
521 connman_task_add_argument(task, "--setenv", NULL);
522 connman_task_add_argument(task, "CONNMAN_PATH",
523 connman_task_get_path(task));
525 connman_task_add_argument(task, "--dev", data->if_name);
526 option = vpn_provider_get_string(provider, "OpenVPN.DeviceType");
528 connman_task_add_argument(task, "--dev-type", option);
531 * Default to tun for backwards compatibility.
533 connman_task_add_argument(task, "--dev-type", "tun");
536 connman_task_add_argument(task, "--persist-tun", NULL);
538 #if !defined TIZEN_EXT
539 connman_task_add_argument(task, "--route-noexec", NULL);
540 connman_task_add_argument(task, "--ifconfig-noexec", NULL);
544 * Disable client restarts with TCP because we can't handle this at
545 * the moment. The problem is that when OpenVPN decides to switch
546 * from CONNECTED state to RECONNECTING and then to RESOLVE,
547 * it is not possible to do a DNS lookup. The DNS server is
548 * not accessible through the tunnel anymore and so we end up
549 * trying to resolve the OpenVPN servers address.
551 * Disable connetion retrying when OpenVPN is connected over TCP.
552 * With TCP OpenVPN attempts to handle reconnection silently without
553 * reporting the error back when establishing a connection or
554 * reconnecting as succesful one. The latter causes trouble if the
555 * retries are not limited to 1 (no retry) as the interface is up and
556 * connman regards it as the default route and network ceases to work,
559 option = vpn_provider_get_string(provider, "OpenVPN.Proto");
560 if (option && g_str_has_prefix(option, "tcp")) {
561 option = vpn_provider_get_string(provider, "OpenVPN.PingExit");
563 connman_task_add_argument(task, "--ping-restart", "0");
565 connman_task_add_argument(task, "--connect-retry-max", "1");
566 /* Apply defaults for --ping and --ping-exit only with UDP protocol. */
568 /* Apply default of 10 second interval for ping if omitted. */
569 option = vpn_provider_get_string(provider, "OpenVPN.Ping");
571 connman_task_add_argument(task, "--ping", "10");
573 /* Apply default of 60 seconds for ping exit if omitted. */
574 option = vpn_provider_get_string(provider, "OpenVPN.PingExit");
576 connman_task_add_argument(task, "--ping-exit", "60");
579 err = connman_task_run(task, ov_died, data, NULL, NULL, NULL);
582 data->user_data = NULL;
583 connman_error("openvpn failed to start");
586 /* This lets the caller know that the actual result of
587 * the operation will be reported to the callback */
592 static void ov_quote_credential(GString *line, const char *cred)
597 g_string_append_c(line, '"');
599 while (*cred != '\0') {
605 g_string_append_c(line, '\\');
611 g_string_append_c(line, *cred++);
614 g_string_append_c(line, '"');
617 static void ov_return_credentials(struct ov_private_data *data,
618 const char *username, const char *password)
620 GString *reply_string;
624 reply_string = g_string_new(NULL);
626 g_string_append(reply_string, "username \"Auth\" ");
627 ov_quote_credential(reply_string, username);
628 g_string_append_c(reply_string, '\n');
630 g_string_append(reply_string, "password \"Auth\" ");
631 ov_quote_credential(reply_string, password);
632 g_string_append_c(reply_string, '\n');
634 len = reply_string->len;
635 reply = g_string_free(reply_string, FALSE);
637 g_io_channel_write_chars(data->mgmt_channel, reply, len, NULL, NULL);
638 g_io_channel_flush(data->mgmt_channel, NULL);
640 memset(reply, 0, len);
644 static void ov_return_private_key_password(struct ov_private_data *data,
645 const char *privatekeypass)
647 GString *reply_string;
651 reply_string = g_string_new(NULL);
653 g_string_append(reply_string, "password \"Private Key\" ");
654 ov_quote_credential(reply_string, privatekeypass);
655 g_string_append_c(reply_string, '\n');
657 len = reply_string->len;
658 reply = g_string_free(reply_string, FALSE);
660 g_io_channel_write_chars(data->mgmt_channel, reply, len, NULL, NULL);
661 g_io_channel_flush(data->mgmt_channel, NULL);
663 memset(reply, 0, len);
667 static void request_input_append_informational(DBusMessageIter *iter,
670 char *str = "string";
672 connman_dbus_dict_append_basic(iter, "Type",
673 DBUS_TYPE_STRING, &str);
674 str = "informational";
675 connman_dbus_dict_append_basic(iter, "Requirement",
676 DBUS_TYPE_STRING, &str);
679 static void request_input_append_mandatory(DBusMessageIter *iter,
682 char *str = "string";
684 connman_dbus_dict_append_basic(iter, "Type",
685 DBUS_TYPE_STRING, &str);
687 connman_dbus_dict_append_basic(iter, "Requirement",
688 DBUS_TYPE_STRING, &str);
691 static void request_input_append_password(DBusMessageIter *iter,
694 char *str = "password";
696 connman_dbus_dict_append_basic(iter, "Type",
697 DBUS_TYPE_STRING, &str);
699 connman_dbus_dict_append_basic(iter, "Requirement",
700 DBUS_TYPE_STRING, &str);
703 static void request_input_credentials_reply(DBusMessage *reply,
706 struct ov_private_data *data = user_data;
707 char *username = NULL;
708 char *password = NULL;
710 DBusMessageIter iter, dict;
714 connman_info("provider %p", data->provider);
717 * When connmand calls disconnect because of connection timeout no
725 dbus_error_init(&error);
727 err = vpn_agent_check_and_process_reply_error(reply, data->provider,
728 data->task, data->cb, data->user_data);
730 /* Ensure cb is called only once */
732 data->user_data = NULL;
736 if (!vpn_agent_check_reply_has_dict(reply)) {
741 dbus_message_iter_init(reply, &iter);
742 dbus_message_iter_recurse(&iter, &dict);
743 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
744 DBusMessageIter entry, value;
746 dbus_message_iter_recurse(&dict, &entry);
747 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
750 dbus_message_iter_get_basic(&entry, &key);
752 if (g_str_equal(key, "OpenVPN.Password")) {
753 dbus_message_iter_next(&entry);
754 if (dbus_message_iter_get_arg_type(&entry)
755 != DBUS_TYPE_VARIANT)
757 dbus_message_iter_recurse(&entry, &value);
758 if (dbus_message_iter_get_arg_type(&value)
761 dbus_message_iter_get_basic(&value, &password);
762 vpn_provider_set_string_hide_value(data->provider,
765 } else if (g_str_equal(key, "OpenVPN.Username")) {
766 dbus_message_iter_next(&entry);
767 if (dbus_message_iter_get_arg_type(&entry)
768 != DBUS_TYPE_VARIANT)
770 dbus_message_iter_recurse(&entry, &value);
771 if (dbus_message_iter_get_arg_type(&value)
774 dbus_message_iter_get_basic(&value, &username);
775 vpn_provider_set_string_hide_value(data->provider,
779 dbus_message_iter_next(&dict);
782 if (!password || !username) {
783 vpn_provider_indicate_error(data->provider,
784 VPN_PROVIDER_ERROR_AUTH_FAILED);
789 ov_return_credentials(data, username, password);
794 ov_connect_done(data, err);
797 static int request_credentials_input(struct ov_private_data *data)
799 DBusMessage *message;
800 const char *path, *agent_sender, *agent_path;
801 DBusMessageIter iter;
802 DBusMessageIter dict;
806 agent = connman_agent_get_info(data->dbus_sender, &agent_sender,
808 if (!agent || !agent_path)
811 message = dbus_message_new_method_call(agent_sender, agent_path,
817 dbus_message_iter_init_append(message, &iter);
819 path = vpn_provider_get_path(data->provider);
820 dbus_message_iter_append_basic(&iter,
821 DBUS_TYPE_OBJECT_PATH, &path);
823 connman_dbus_dict_open(&iter, &dict);
825 if (vpn_provider_get_authentication_errors(data->provider))
826 vpn_agent_append_auth_failure(&dict, data->provider, NULL);
828 /* Request temporary properties to pass on to openvpn */
829 connman_dbus_dict_append_dict(&dict, "OpenVPN.Username",
830 request_input_append_mandatory, NULL);
832 connman_dbus_dict_append_dict(&dict, "OpenVPN.Password",
833 request_input_append_password, NULL);
835 vpn_agent_append_host_and_name(&dict, data->provider);
837 connman_dbus_dict_close(&iter, &dict);
839 err = connman_agent_queue_message(data->provider, message,
840 connman_timeout_input_request(),
841 request_input_credentials_reply, data, agent);
843 if (err < 0 && err != -EBUSY) {
844 connman_error("error %d sending agent request", err);
845 dbus_message_unref(message);
850 dbus_message_unref(message);
855 static void request_input_private_key_reply(DBusMessage *reply,
858 struct ov_private_data *data = user_data;
859 const char *privatekeypass = NULL;
861 DBusMessageIter iter, dict;
865 connman_info("provider %p", data->provider);
868 * When connmand calls disconnect because of connection timeout no
876 dbus_error_init(&error);
878 err = vpn_agent_check_and_process_reply_error(reply, data->provider,
879 data->task, data->cb, data->user_data);
881 /* Ensure cb is called only once */
883 data->user_data = NULL;
887 if (!vpn_agent_check_reply_has_dict(reply)) {
892 dbus_message_iter_init(reply, &iter);
893 dbus_message_iter_recurse(&iter, &dict);
894 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
895 DBusMessageIter entry, value;
897 dbus_message_iter_recurse(&dict, &entry);
898 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
901 dbus_message_iter_get_basic(&entry, &key);
903 if (g_str_equal(key, "OpenVPN.PrivateKeyPassword")) {
904 dbus_message_iter_next(&entry);
905 if (dbus_message_iter_get_arg_type(&entry)
906 != DBUS_TYPE_VARIANT)
908 dbus_message_iter_recurse(&entry, &value);
909 if (dbus_message_iter_get_arg_type(&value)
912 dbus_message_iter_get_basic(&value, &privatekeypass);
913 vpn_provider_set_string_hide_value(data->provider,
914 key, privatekeypass);
918 dbus_message_iter_next(&dict);
921 if (!privatekeypass) {
922 vpn_provider_indicate_error(data->provider,
923 VPN_PROVIDER_ERROR_AUTH_FAILED);
929 ov_return_private_key_password(data, privatekeypass);
934 ov_connect_done(data, err);
937 static int request_private_key_input(struct ov_private_data *data)
939 DBusMessage *message;
940 const char *path, *agent_sender, *agent_path;
941 const char *privatekeypass;
942 DBusMessageIter iter;
943 DBusMessageIter dict;
948 * First check if this is the second attempt to get the key within
949 * this connection. In such case there has been invalid Private Key
950 * Password and it must be reset, and queried from user.
952 if (data->failed_attempts_privatekey) {
953 vpn_provider_set_string_hide_value(data->provider,
954 "OpenVPN.PrivateKeyPassword", NULL);
956 /* If the encrypted Private key password is kept in memory and
957 * use it first. If authentication fails this is cleared,
958 * likewise it is when connman-vpnd is restarted.
960 privatekeypass = vpn_provider_get_string(data->provider,
961 "OpenVPN.PrivateKeyPassword");
962 if (privatekeypass) {
963 ov_return_private_key_password(data, privatekeypass);
968 agent = connman_agent_get_info(data->dbus_sender, &agent_sender,
970 if (!agent || !agent_path)
973 message = dbus_message_new_method_call(agent_sender, agent_path,
979 dbus_message_iter_init_append(message, &iter);
981 path = vpn_provider_get_path(data->provider);
982 dbus_message_iter_append_basic(&iter,
983 DBUS_TYPE_OBJECT_PATH, &path);
985 connman_dbus_dict_open(&iter, &dict);
987 connman_dbus_dict_append_dict(&dict, "OpenVPN.PrivateKeyPassword",
988 request_input_append_password, NULL);
990 vpn_agent_append_host_and_name(&dict, data->provider);
992 /* Do not allow to store or retrieve the encrypted Private Key pass */
993 vpn_agent_append_allow_credential_storage(&dict, false);
994 vpn_agent_append_allow_credential_retrieval(&dict, false);
997 * Indicate to keep credentials, the enc Private Key password should
998 * not affect the credential storing.
1000 vpn_agent_append_keep_credentials(&dict, true);
1002 connman_dbus_dict_append_dict(&dict, "Enter Private Key password",
1003 request_input_append_informational, NULL);
1005 connman_dbus_dict_close(&iter, &dict);
1007 err = connman_agent_queue_message(data->provider, message,
1008 connman_timeout_input_request(),
1009 request_input_private_key_reply, data, agent);
1011 if (err < 0 && err != -EBUSY) {
1012 connman_error("error %d sending agent request", err);
1013 dbus_message_unref(message);
1018 dbus_message_unref(message);
1021 return -EINPROGRESS;
1024 static gboolean ov_management_handle_input(GIOChannel *source,
1025 GIOCondition condition, gpointer user_data)
1027 struct ov_private_data *data = user_data;
1032 if (condition & G_IO_IN) {
1034 * Just return if line is not read and str is not allocated.
1035 * Condition check handles closing of the channel later.
1037 if (g_io_channel_read_line(source, &str, NULL, NULL, NULL) !=
1041 str[strlen(str) - 1] = '\0';
1042 connman_warn("openvpn request %s", str);
1044 if (g_str_has_prefix(str, ">PASSWORD:Need 'Auth'")) {
1046 * Request credentials from the user
1048 err = request_credentials_input(data);
1049 if (err != -EINPROGRESS)
1051 } else if (g_str_has_prefix(str,
1052 ">PASSWORD:Need 'Private Key'")) {
1053 err = request_private_key_input(data);
1054 if (err != -EINPROGRESS)
1056 } else if (g_str_has_prefix(str,
1057 ">PASSWORD:Verification Failed: 'Auth'")) {
1059 * Add error only, state change indication causes
1060 * signal to be sent, which is not desired when
1061 * OpenVPN is in interactive mode.
1063 vpn_provider_add_error(data->provider,
1064 VPN_PROVIDER_ERROR_AUTH_FAILED);
1066 * According to the OpenVPN manual about management interface
1067 * https://openvpn.net/community-resources/management-interface/
1068 * this should be received but it does not seem to be reported
1069 * when decrypting private key fails. This requires following
1070 * patch for OpenVPN (at least <= 2.4.5) in order to work:
1071 * https://git.sailfishos.org/mer-core/openvpn/blob/
1072 * 4f4b4af116292a207416c8a990392e35a6fc41af/rpm/privatekey-
1073 * passphrase-handling.diff
1075 } else if (g_str_has_prefix(str, ">PASSWORD:Verification "
1076 "Failed: 'Private Key'")) {
1077 data->failed_attempts_privatekey++;
1081 } else if (condition & (G_IO_ERR | G_IO_HUP)) {
1082 connman_warn("Management channel termination");
1087 close_management_interface(data);
1092 static int ov_management_connect_timer_cb(gpointer user_data)
1094 struct ov_private_data *data = user_data;
1096 if (!data->mgmt_channel) {
1097 int fd = socket(AF_UNIX, SOCK_STREAM, 0);
1099 struct sockaddr_un remote;
1102 memset(&remote, 0, sizeof(remote));
1103 remote.sun_family = AF_UNIX;
1104 g_strlcpy(remote.sun_path, data->mgmt_path,
1105 sizeof(remote.sun_path));
1107 err = connect(fd, (struct sockaddr *)&remote,
1110 data->mgmt_channel = g_io_channel_unix_new(fd);
1111 data->mgmt_event_id =
1112 g_io_add_watch(data->mgmt_channel,
1113 G_IO_IN | G_IO_ERR | G_IO_HUP,
1114 ov_management_handle_input,
1117 connman_warn("Connected management socket");
1118 data->mgmt_timer_id = 0;
1119 return G_SOURCE_REMOVE;
1125 data->connect_attempts++;
1126 if (data->connect_attempts > 30) {
1127 connman_warn("Unable to connect management socket");
1128 data->mgmt_timer_id = 0;
1129 return G_SOURCE_REMOVE;
1132 return G_SOURCE_CONTINUE;
1135 static int ov_connect(struct vpn_provider *provider,
1136 struct connman_task *task, const char *if_name,
1137 vpn_provider_connect_cb_t cb, const char *dbus_sender,
1141 struct ov_private_data *data;
1144 * Explicitly set limit of 10 for authentication errors. This defines
1145 * the authentication error message limit from the server before VPN
1146 * agent is instructed to clear the credentials. This is effective only
1147 * after a successful connection has been made within CONNECT_OK_DIFF
1148 * time. User defined value for "AuthErrorLimit" overrides this.
1150 vpn_provider_set_auth_error_limit(provider, 10);
1152 data = g_try_new0(struct ov_private_data, 1);
1156 vpn_provider_set_plugin_data(provider, data);
1157 data->provider = vpn_provider_ref(provider);
1159 data->dbus_sender = g_strdup(dbus_sender);
1160 data->if_name = g_strdup(if_name);
1162 data->user_data = user_data;
1165 * We need to use the management interface to provide
1166 * the user credentials and password for decrypting private key.
1169 /* Use env TMPDIR for creating management socket, fall back to /tmp */
1170 tmpdir = getenv("TMPDIR");
1171 if (!tmpdir || !*tmpdir)
1174 /* Set up the path for the management interface */
1175 data->mgmt_path = g_strconcat(tmpdir, "/connman-vpn-management-",
1176 vpn_provider_get_ident(provider), NULL);
1177 if (unlink(data->mgmt_path) != 0 && errno != ENOENT) {
1178 connman_warn("Unable to unlink management socket %s: %d",
1179 data->mgmt_path, errno);
1182 data->mgmt_timer_id = g_timeout_add(200,
1183 ov_management_connect_timer_cb, data);
1185 task_append_config_data(provider, task);
1187 return run_connect(data, cb, user_data);
1190 static void ov_disconnect(struct vpn_provider *provider)
1195 connman_agent_cancel(provider);
1197 vpn_provider_set_state(provider, VPN_PROVIDER_STATE_DISCONNECT);
1200 static int ov_device_flags(struct vpn_provider *provider)
1204 option = vpn_provider_get_string(provider, "OpenVPN.DeviceType");
1209 if (g_str_equal(option, "tap")) {
1213 if (!g_str_equal(option, "tun")) {
1214 connman_warn("bad OpenVPN.DeviceType value "
1215 "falling back to tun");
1221 static int ov_route_env_parse(struct vpn_provider *provider, const char *key,
1222 int *family, unsigned long *idx,
1223 enum vpn_provider_route_type *type)
1228 if (g_str_has_prefix(key, "route_network_")) {
1229 start = key + strlen("route_network_");
1230 *type = VPN_PROVIDER_ROUTE_TYPE_ADDR;
1231 } else if (g_str_has_prefix(key, "route_netmask_")) {
1232 start = key + strlen("route_netmask_");
1233 *type = VPN_PROVIDER_ROUTE_TYPE_MASK;
1234 } else if (g_str_has_prefix(key, "route_gateway_")) {
1235 start = key + strlen("route_gateway_");
1236 *type = VPN_PROVIDER_ROUTE_TYPE_GW;
1241 *idx = g_ascii_strtoull(start, &end, 10);
1246 static struct vpn_driver vpn_driver = {
1247 .notify = ov_notify,
1248 .connect = ov_connect,
1249 .disconnect = ov_disconnect,
1251 .device_flags = ov_device_flags,
1252 .route_env_parse = ov_route_env_parse,
1255 static int openvpn_init(void)
1257 connection = connman_dbus_get_connection();
1259 return vpn_register("openvpn", &vpn_driver, OPENVPN);
1262 static void openvpn_exit(void)
1264 vpn_unregister("openvpn");
1266 dbus_connection_unref(connection);
1269 CONNMAN_PLUGIN_DEFINE(openvpn, "OpenVPN plugin", VERSION,
1270 CONNMAN_PLUGIN_PRIORITY_DEFAULT, openvpn_init, openvpn_exit)