Imported Upstream version 1.40
[platform/upstream/connman.git] / vpn / plugins / openvpn.c
1 /*
2  *
3  *  ConnMan VPN daemon
4  *
5  *  Copyright (C) 2010-2014  BMW Car IT GmbH.
6  *  Copyright (C) 2016-2019  Jolla Ltd.
7  *
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.
11  *
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.
16  *
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
20  *
21  */
22
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26
27 #include <stdlib.h>
28 #include <string.h>
29 #include <errno.h>
30 #include <unistd.h>
31 #include <stdio.h>
32 #include <net/if.h>
33 #include <linux/if_tun.h>
34 #include <sys/types.h>
35 #include <sys/socket.h>
36 #include <sys/un.h>
37
38 #include <glib.h>
39
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>
49
50 #include "../vpn-provider.h"
51 #include "../vpn-agent.h"
52
53 #include "vpn.h"
54
55 #define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0]))
56
57 static DBusConnection *connection;
58
59 struct {
60         const char *cm_opt;
61         const char *ov_opt;
62         char       has_value;
63 } ov_options[] = {
64         { "Host", "--remote", 1 },
65         { "OpenVPN.CACert", "--ca", 1 },
66         { "OpenVPN.Cert", "--cert", 1 },
67         { "OpenVPN.Key", "--key", 1 },
68         { "OpenVPN.MTU", "--tun-mtu", 1 },
69         { "OpenVPN.NSCertType", "--ns-cert-type", 1 },
70         { "OpenVPN.Proto", "--proto", 1 },
71         { "OpenVPN.Port", "--port", 1 },
72         { "OpenVPN.AuthUserPass", "--auth-user-pass", 1 },
73         { "OpenVPN.AskPass", "--askpass", 1 },
74         { "OpenVPN.AuthNoCache", "--auth-nocache", 0 },
75         { "OpenVPN.TLSRemote", "--tls-remote", 1 },
76         { "OpenVPN.TLSAuth", NULL, 1 },
77         { "OpenVPN.TLSAuthDir", NULL, 1 },
78         { "OpenVPN.TLSCipher", "--tls-cipher", 1},
79         { "OpenVPN.Cipher", "--cipher", 1 },
80         { "OpenVPN.Auth", "--auth", 1 },
81         { "OpenVPN.CompLZO", "--comp-lzo", 0 },
82         { "OpenVPN.RemoteCertTls", "--remote-cert-tls", 1 },
83         { "OpenVPN.ConfigFile", "--config", 1 },
84         { "OpenVPN.DeviceType", NULL, 1 },
85         { "OpenVPN.Verb", "--verb", 1 },
86         { "OpenVPN.Ping", "--ping", 1},
87         { "OpenVPN.PingExit", "--ping-exit", 1},
88         { "OpenVPN.RemapUsr1", "--remap-usr1", 1},
89 };
90
91 struct ov_private_data {
92         struct vpn_provider *provider;
93         struct connman_task *task;
94         char *dbus_sender;
95         char *if_name;
96         vpn_provider_connect_cb_t cb;
97         void *user_data;
98         char *mgmt_path;
99         guint mgmt_timer_id;
100         guint mgmt_event_id;
101         GIOChannel *mgmt_channel;
102         int connect_attempts;
103         int failed_attempts_privatekey;
104 };
105
106 static void ov_connect_done(struct ov_private_data *data, int err)
107 {
108         if (data && data->cb) {
109                 vpn_provider_connect_cb_t cb = data->cb;
110                 void *user_data = data->user_data;
111
112                 /* Make sure we don't invoke this callback twice */
113                 data->cb = NULL;
114                 data->user_data = NULL;
115                 cb(data->provider, user_data, err);
116         }
117
118         if (!err)
119                 data->failed_attempts_privatekey = 0;
120 }
121
122 static void free_private_data(struct ov_private_data *data)
123 {
124         if (vpn_provider_get_plugin_data(data->provider) == data)
125                 vpn_provider_set_plugin_data(data->provider, NULL);
126
127         ov_connect_done(data, EIO);
128         vpn_provider_unref(data->provider);
129         g_free(data->dbus_sender);
130         g_free(data->if_name);
131         g_free(data->mgmt_path);
132         g_free(data);
133 }
134
135 struct nameserver_entry {
136         int id;
137         char *nameserver;
138 };
139
140 static struct nameserver_entry *ov_append_dns_entries(const char *key,
141                                                 const char *value)
142 {
143         struct nameserver_entry *entry = NULL;
144         gchar **options;
145
146         if (!g_str_has_prefix(key, "foreign_option_"))
147                 return NULL;
148
149         options = g_strsplit(value, " ", 3);
150         if (options[0] &&
151                 !strcmp(options[0], "dhcp-option") &&
152                         options[1] &&
153                         !strcmp(options[1], "DNS") &&
154                                 options[2]) {
155
156                 entry = g_try_new(struct nameserver_entry, 1);
157                 if (!entry)
158                         return NULL;
159
160                 entry->nameserver = g_strdup(options[2]);
161                 entry->id = atoi(key + 15); /* foreign_option_XXX */
162         }
163
164         g_strfreev(options);
165
166         return entry;
167 }
168
169 static char *ov_get_domain_name(const char *key, const char *value)
170 {
171         gchar **options;
172         char *domain = NULL;
173
174         if (!g_str_has_prefix(key, "foreign_option_"))
175                 return NULL;
176
177         options = g_strsplit(value, " ", 3);
178         if (options[0] &&
179                 !strcmp(options[0], "dhcp-option") &&
180                         options[1] &&
181                         !strcmp(options[1], "DOMAIN") &&
182                                 options[2]) {
183
184                 domain = g_strdup(options[2]);
185         }
186
187         g_strfreev(options);
188
189         return domain;
190 }
191
192 static gint cmp_ns(gconstpointer a, gconstpointer b)
193 {
194         struct nameserver_entry *entry_a = (struct nameserver_entry *)a;
195         struct nameserver_entry *entry_b = (struct nameserver_entry *)b;
196
197         if (entry_a->id < entry_b->id)
198                 return -1;
199
200         if (entry_a->id > entry_b->id)
201                 return 1;
202
203         return 0;
204 }
205
206 static void free_ns_entry(gpointer data)
207 {
208         struct nameserver_entry *entry = data;
209
210         g_free(entry->nameserver);
211         g_free(entry);
212 }
213
214 static int ov_notify(DBusMessage *msg, struct vpn_provider *provider)
215 {
216         DBusMessageIter iter, dict;
217         const char *reason, *key, *value;
218         char *address = NULL, *gateway = NULL, *peer = NULL, *netmask = NULL;
219         struct connman_ipaddress *ipaddress;
220         GSList *nameserver_list = NULL;
221         struct ov_private_data *data = vpn_provider_get_plugin_data(provider);
222
223         dbus_message_iter_init(msg, &iter);
224
225         dbus_message_iter_get_basic(&iter, &reason);
226         dbus_message_iter_next(&iter);
227
228         if (!provider) {
229                 connman_error("No provider found");
230                 return VPN_STATE_FAILURE;
231         }
232
233         DBG("%p %s", vpn_provider_get_name(provider), reason);
234
235         if (strcmp(reason, "up")) {
236                 ov_connect_done(data, EIO);
237                 return VPN_STATE_DISCONNECT;
238         }
239
240         dbus_message_iter_recurse(&iter, &dict);
241
242         while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
243                 struct nameserver_entry *ns_entry = NULL;
244                 DBusMessageIter entry;
245
246                 dbus_message_iter_recurse(&dict, &entry);
247                 dbus_message_iter_get_basic(&entry, &key);
248                 dbus_message_iter_next(&entry);
249                 dbus_message_iter_get_basic(&entry, &value);
250
251                 DBG("%s = %s", key, value);
252
253                 if (!strcmp(key, "trusted_ip"))
254                         gateway = g_strdup(value);
255
256                 if (!strcmp(key, "ifconfig_local"))
257                         address = g_strdup(value);
258
259                 if (!strcmp(key, "ifconfig_netmask"))
260                         netmask = g_strdup(value);
261
262                 if (!strcmp(key, "ifconfig_remote"))
263                         peer = g_strdup(value);
264
265                 if (g_str_has_prefix(key, "route_"))
266                         vpn_provider_append_route(provider, key, value);
267
268                 if ((ns_entry = ov_append_dns_entries(key, value)))
269                         nameserver_list = g_slist_prepend(nameserver_list,
270                                                         ns_entry);
271                 else {
272                         char *domain = ov_get_domain_name(key, value);
273                         if (domain) {
274                                 vpn_provider_set_domain(provider, domain);
275                                 g_free(domain);
276                         }
277                 }
278
279                 dbus_message_iter_next(&dict);
280         }
281
282         ipaddress = connman_ipaddress_alloc(AF_INET);
283         if (!ipaddress) {
284                 g_slist_free_full(nameserver_list, free_ns_entry);
285                 g_free(address);
286                 g_free(gateway);
287                 g_free(peer);
288                 g_free(netmask);
289
290                 return VPN_STATE_FAILURE;
291         }
292
293         connman_ipaddress_set_ipv4(ipaddress, address, netmask, gateway);
294         connman_ipaddress_set_peer(ipaddress, peer);
295         connman_ipaddress_set_p2p(ipaddress, true);
296         vpn_provider_set_ipaddress(provider, ipaddress);
297
298         if (nameserver_list) {
299                 char *nameservers = NULL;
300                 GSList *tmp;
301
302                 nameserver_list = g_slist_sort(nameserver_list, cmp_ns);
303                 for (tmp = nameserver_list; tmp;
304                                                 tmp = g_slist_next(tmp)) {
305                         struct nameserver_entry *ns = tmp->data;
306
307                         if (!nameservers) {
308                                 nameservers = g_strdup(ns->nameserver);
309                         } else {
310                                 char *str;
311                                 str = g_strjoin(" ", nameservers,
312                                                 ns->nameserver, NULL);
313                                 g_free(nameservers);
314                                 nameservers = str;
315                         }
316                 }
317
318                 g_slist_free_full(nameserver_list, free_ns_entry);
319
320                 vpn_provider_set_nameservers(provider, nameservers);
321
322                 g_free(nameservers);
323         }
324
325         g_free(address);
326         g_free(gateway);
327         g_free(peer);
328         g_free(netmask);
329         connman_ipaddress_free(ipaddress);
330
331         ov_connect_done(data, 0);
332         return VPN_STATE_CONNECT;
333 }
334
335 static int ov_save(struct vpn_provider *provider, GKeyFile *keyfile)
336 {
337         const char *option;
338         int i;
339
340         for (i = 0; i < (int)ARRAY_SIZE(ov_options); i++) {
341                 if (strncmp(ov_options[i].cm_opt, "OpenVPN.", 8) == 0) {
342                         option = vpn_provider_get_string(provider,
343                                                         ov_options[i].cm_opt);
344                         if (!option)
345                                 continue;
346
347                         g_key_file_set_string(keyfile,
348                                         vpn_provider_get_save_group(provider),
349                                         ov_options[i].cm_opt, option);
350                 }
351         }
352         return 0;
353 }
354
355 static int task_append_config_data(struct vpn_provider *provider,
356                                         struct connman_task *task)
357 {
358         const char *option;
359         int i;
360
361         for (i = 0; i < (int)ARRAY_SIZE(ov_options); i++) {
362                 if (!ov_options[i].ov_opt)
363                         continue;
364
365                 option = vpn_provider_get_string(provider,
366                                         ov_options[i].cm_opt);
367                 if (!option)
368                         continue;
369
370                 /*
371                  * If the AuthUserPass option is "-", provide the input
372                  * via management interface
373                  */
374                 if (!strcmp(ov_options[i].cm_opt, "OpenVPN.AuthUserPass") &&
375                                                 !strcmp(option, "-"))
376                         option = NULL;
377
378                 if (connman_task_add_argument(task,
379                                 ov_options[i].ov_opt,
380                                 ov_options[i].has_value ? option : NULL) < 0)
381                         return -EIO;
382
383         }
384
385         return 0;
386 }
387
388 static void close_management_interface(struct ov_private_data *data)
389 {
390         if (data->mgmt_path) {
391                 if (unlink(data->mgmt_path) && errno != ENOENT)
392                         connman_warn("Unable to unlink management socket %s: "
393                                                 "%d", data->mgmt_path, errno);
394
395                 g_free(data->mgmt_path);
396                 data->mgmt_path = NULL;
397         }
398
399         if (data->mgmt_timer_id != 0) {
400                 g_source_remove(data->mgmt_timer_id);
401                 data->mgmt_timer_id = 0;
402         }
403
404         if (data->mgmt_event_id) {
405                 g_source_remove(data->mgmt_event_id);
406                 data->mgmt_event_id = 0;
407         }
408
409         if (data->mgmt_channel) {
410                 g_io_channel_shutdown(data->mgmt_channel, FALSE, NULL);
411                 g_io_channel_unref(data->mgmt_channel);
412                 data->mgmt_channel = NULL;
413         }
414 }
415
416 static void ov_died(struct connman_task *task, int exit_code, void *user_data)
417 {
418         struct ov_private_data *data = user_data;
419
420         /* Cancel any pending agent requests */
421         connman_agent_cancel(data->provider);
422
423         close_management_interface(data);
424
425         vpn_died(task, exit_code, data->provider);
426
427         free_private_data(data);
428 }
429
430 static int run_connect(struct ov_private_data *data,
431                         vpn_provider_connect_cb_t cb, void *user_data)
432 {
433         struct vpn_provider *provider = data->provider;
434         struct connman_task *task = data->task;
435         const char *option;
436         int err = 0;
437
438         option = vpn_provider_get_string(provider, "OpenVPN.ConfigFile");
439         if (!option) {
440                 /*
441                  * Set some default options if user has no config file.
442                  */
443                 option = vpn_provider_get_string(provider, "OpenVPN.TLSAuth");
444                 if (option) {
445                         connman_task_add_argument(task, "--tls-auth", option);
446                         option = vpn_provider_get_string(provider,
447                                                         "OpenVPN.TLSAuthDir");
448                         if (option)
449                                 connman_task_add_argument(task, option, NULL);
450                 }
451
452                 connman_task_add_argument(task, "--nobind", NULL);
453                 connman_task_add_argument(task, "--persist-key", NULL);
454                 connman_task_add_argument(task, "--client", NULL);
455         }
456
457         if (data->mgmt_path) {
458                 connman_task_add_argument(task, "--management", NULL);
459                 connman_task_add_argument(task, data->mgmt_path, NULL);
460                 connman_task_add_argument(task, "unix", NULL);
461                 connman_task_add_argument(task, "--management-query-passwords",
462                                                                 NULL);
463                 connman_task_add_argument(task, "--auth-retry", "interact");
464         }
465
466         connman_task_add_argument(task, "--syslog", NULL);
467
468         connman_task_add_argument(task, "--script-security", "2");
469
470         connman_task_add_argument(task, "--up",
471                                         SCRIPTDIR "/openvpn-script");
472         connman_task_add_argument(task, "--up-restart", NULL);
473
474         connman_task_add_argument(task, "--setenv", NULL);
475         connman_task_add_argument(task, "CONNMAN_BUSNAME",
476                                         dbus_bus_get_unique_name(connection));
477
478         connman_task_add_argument(task, "--setenv", NULL);
479         connman_task_add_argument(task, "CONNMAN_INTERFACE",
480                                         CONNMAN_TASK_INTERFACE);
481
482         connman_task_add_argument(task, "--setenv", NULL);
483         connman_task_add_argument(task, "CONNMAN_PATH",
484                                         connman_task_get_path(task));
485
486         connman_task_add_argument(task, "--dev", data->if_name);
487         option = vpn_provider_get_string(provider, "OpenVPN.DeviceType");
488         if (option) {
489                 connman_task_add_argument(task, "--dev-type", option);
490         } else {
491                 /*
492                  * Default to tun for backwards compatibility.
493                  */
494                 connman_task_add_argument(task, "--dev-type", "tun");
495         }
496
497         connman_task_add_argument(task, "--persist-tun", NULL);
498
499         connman_task_add_argument(task, "--route-noexec", NULL);
500         connman_task_add_argument(task, "--ifconfig-noexec", NULL);
501
502         /*
503          * Disable client restarts with TCP because we can't handle this at
504          * the moment. The problem is that when OpenVPN decides to switch
505          * from CONNECTED state to RECONNECTING and then to RESOLVE,
506          * it is not possible to do a DNS lookup. The DNS server is
507          * not accessible through the tunnel anymore and so we end up
508          * trying to resolve the OpenVPN servers address.
509          *
510          * Disable connetion retrying when OpenVPN is connected over TCP.
511          * With TCP OpenVPN attempts to handle reconnection silently without
512          * reporting the error back when establishing a connection or
513          * reconnecting as succesful one. The latter causes trouble if the
514          * retries are not limited to 1 (no retry) as the interface is up and
515          * connman regards it as the default route and network ceases to work,
516          * including DNS.
517         */
518         option = vpn_provider_get_string(provider, "OpenVPN.Proto");
519         if (option && g_str_has_prefix(option, "tcp")) {
520                 option = vpn_provider_get_string(provider, "OpenVPN.PingExit");
521                 if (!option)
522                         connman_task_add_argument(task, "--ping-restart", "0");
523
524                 connman_task_add_argument(task, "--connect-retry-max", "1");
525         /* Apply defaults for --ping and --ping-exit only with UDP protocol. */
526         } else {
527                 /* Apply default of 10 second interval for ping if omitted. */
528                 option = vpn_provider_get_string(provider, "OpenVPN.Ping");
529                 if (!option)
530                         connman_task_add_argument(task, "--ping", "10");
531
532                 /* Apply default of 60 seconds for ping exit if omitted. */
533                 option = vpn_provider_get_string(provider, "OpenVPN.PingExit");
534                 if (!option)
535                         connman_task_add_argument(task, "--ping-exit", "60");
536         }
537
538         err = connman_task_run(task, ov_died, data, NULL, NULL, NULL);
539         if (err < 0) {
540                 data->cb = NULL;
541                 data->user_data = NULL;
542                 connman_error("openvpn failed to start");
543                 return -EIO;
544         } else {
545                 /* This lets the caller know that the actual result of
546                  * the operation will be reported to the callback */
547                 return -EINPROGRESS;
548         }
549 }
550
551 static void ov_quote_credential(GString *line, const char *cred)
552 {
553         if (!line)
554                 return;
555
556         g_string_append_c(line, '"');
557
558         while (*cred != '\0') {
559
560                 switch (*cred) {
561                 case ' ':
562                 case '"':
563                 case '\\':
564                         g_string_append_c(line, '\\');
565                         break;
566                 default:
567                         break;
568                 }
569
570                 g_string_append_c(line, *cred++);
571         }
572
573         g_string_append_c(line, '"');
574 }
575
576 static void ov_return_credentials(struct ov_private_data *data,
577                                 const char *username, const char *password)
578 {
579         GString *reply_string;
580         gchar *reply;
581         gsize len;
582
583         reply_string = g_string_new(NULL);
584
585         g_string_append(reply_string, "username \"Auth\" ");
586         ov_quote_credential(reply_string, username);
587         g_string_append_c(reply_string, '\n');
588
589         g_string_append(reply_string, "password \"Auth\" ");
590         ov_quote_credential(reply_string, password);
591         g_string_append_c(reply_string, '\n');
592
593         len = reply_string->len;
594         reply = g_string_free(reply_string, FALSE);
595
596         g_io_channel_write_chars(data->mgmt_channel, reply, len, NULL, NULL);
597         g_io_channel_flush(data->mgmt_channel, NULL);
598
599         memset(reply, 0, len);
600         g_free(reply);
601 }
602
603 static void ov_return_private_key_password(struct ov_private_data *data,
604                                 const char *privatekeypass)
605 {
606         GString *reply_string;
607         gchar *reply;
608         gsize len;
609
610         reply_string = g_string_new(NULL);
611
612         g_string_append(reply_string, "password \"Private Key\" ");
613         ov_quote_credential(reply_string, privatekeypass);
614         g_string_append_c(reply_string, '\n');
615
616         len = reply_string->len;
617         reply = g_string_free(reply_string, FALSE);
618
619         g_io_channel_write_chars(data->mgmt_channel, reply, len, NULL, NULL);
620         g_io_channel_flush(data->mgmt_channel, NULL);
621
622         memset(reply, 0, len);
623         g_free(reply);
624 }
625
626 static void request_input_append_informational(DBusMessageIter *iter,
627                 void *user_data)
628 {
629         char *str = "string";
630
631         connman_dbus_dict_append_basic(iter, "Type",
632                                 DBUS_TYPE_STRING, &str);
633         str = "informational";
634         connman_dbus_dict_append_basic(iter, "Requirement",
635                                 DBUS_TYPE_STRING, &str);
636 }
637
638 static void request_input_append_mandatory(DBusMessageIter *iter,
639                 void *user_data)
640 {
641         char *str = "string";
642
643         connman_dbus_dict_append_basic(iter, "Type",
644                                 DBUS_TYPE_STRING, &str);
645         str = "mandatory";
646         connman_dbus_dict_append_basic(iter, "Requirement",
647                                 DBUS_TYPE_STRING, &str);
648 }
649
650 static void request_input_append_password(DBusMessageIter *iter,
651                 void *user_data)
652 {
653         char *str = "password";
654
655         connman_dbus_dict_append_basic(iter, "Type",
656                                 DBUS_TYPE_STRING, &str);
657         str = "mandatory";
658         connman_dbus_dict_append_basic(iter, "Requirement",
659                                 DBUS_TYPE_STRING, &str);
660 }
661
662 static void request_input_credentials_reply(DBusMessage *reply,
663                                                         void *user_data)
664 {
665         struct ov_private_data *data = user_data;
666         char *username = NULL;
667         char *password = NULL;
668         char *key;
669         DBusMessageIter iter, dict;
670         DBusError error;
671         int err = 0;
672
673         connman_info("provider %p", data->provider);
674
675         /*
676          * When connmand calls disconnect because of connection timeout no
677          * reply is received.
678          */
679         if (!reply) {
680                 err = ENOENT;
681                 goto err;
682         }
683
684         dbus_error_init(&error);
685
686         err = vpn_agent_check_and_process_reply_error(reply, data->provider,
687                                 data->task, data->cb, data->user_data);
688         if (err) {
689                 /* Ensure cb is called only once */
690                 data->cb = NULL;
691                 data->user_data = NULL;
692                 return;
693         }
694
695         if (!vpn_agent_check_reply_has_dict(reply)) {
696                 err = ENOENT;
697                 goto err;
698         }
699
700         dbus_message_iter_init(reply, &iter);
701         dbus_message_iter_recurse(&iter, &dict);
702         while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
703                 DBusMessageIter entry, value;
704
705                 dbus_message_iter_recurse(&dict, &entry);
706                 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
707                         break;
708
709                 dbus_message_iter_get_basic(&entry, &key);
710
711                 if (g_str_equal(key, "OpenVPN.Password")) {
712                         dbus_message_iter_next(&entry);
713                         if (dbus_message_iter_get_arg_type(&entry)
714                                                         != DBUS_TYPE_VARIANT)
715                                 break;
716                         dbus_message_iter_recurse(&entry, &value);
717                         if (dbus_message_iter_get_arg_type(&value)
718                                                         != DBUS_TYPE_STRING)
719                                 break;
720                         dbus_message_iter_get_basic(&value, &password);
721                         vpn_provider_set_string_hide_value(data->provider,
722                                         key, password);
723
724                 } else if (g_str_equal(key, "OpenVPN.Username")) {
725                         dbus_message_iter_next(&entry);
726                         if (dbus_message_iter_get_arg_type(&entry)
727                                                         != DBUS_TYPE_VARIANT)
728                                 break;
729                         dbus_message_iter_recurse(&entry, &value);
730                         if (dbus_message_iter_get_arg_type(&value)
731                                                         != DBUS_TYPE_STRING)
732                                 break;
733                         dbus_message_iter_get_basic(&value, &username);
734                         vpn_provider_set_string_hide_value(data->provider,
735                                         key, username);
736                 }
737
738                 dbus_message_iter_next(&dict);
739         }
740
741         if (!password || !username) {
742                 vpn_provider_indicate_error(data->provider,
743                                         VPN_PROVIDER_ERROR_AUTH_FAILED);
744                 err = EACCES;
745                 goto err;
746         }
747
748         ov_return_credentials(data, username, password);
749
750         return;
751
752 err:
753         ov_connect_done(data, err);
754 }
755
756 static int request_credentials_input(struct ov_private_data *data)
757 {
758         DBusMessage *message;
759         const char *path, *agent_sender, *agent_path;
760         DBusMessageIter iter;
761         DBusMessageIter dict;
762         int err;
763         void *agent;
764
765         agent = connman_agent_get_info(data->dbus_sender, &agent_sender,
766                                                         &agent_path);
767         if (!agent || !agent_path)
768                 return -ESRCH;
769
770         message = dbus_message_new_method_call(agent_sender, agent_path,
771                                         VPN_AGENT_INTERFACE,
772                                         "RequestInput");
773         if (!message)
774                 return -ENOMEM;
775
776         dbus_message_iter_init_append(message, &iter);
777
778         path = vpn_provider_get_path(data->provider);
779         dbus_message_iter_append_basic(&iter,
780                                 DBUS_TYPE_OBJECT_PATH, &path);
781
782         connman_dbus_dict_open(&iter, &dict);
783
784         if (vpn_provider_get_authentication_errors(data->provider))
785                 vpn_agent_append_auth_failure(&dict, data->provider, NULL);
786
787         /* Request temporary properties to pass on to openvpn */
788         connman_dbus_dict_append_dict(&dict, "OpenVPN.Username",
789                         request_input_append_mandatory, NULL);
790
791         connman_dbus_dict_append_dict(&dict, "OpenVPN.Password",
792                         request_input_append_password, NULL);
793
794         vpn_agent_append_host_and_name(&dict, data->provider);
795
796         connman_dbus_dict_close(&iter, &dict);
797
798         err = connman_agent_queue_message(data->provider, message,
799                         connman_timeout_input_request(),
800                         request_input_credentials_reply, data, agent);
801
802         if (err < 0 && err != -EBUSY) {
803                 connman_error("error %d sending agent request", err);
804                 dbus_message_unref(message);
805
806                 return err;
807         }
808
809         dbus_message_unref(message);
810
811         return -EINPROGRESS;
812 }
813
814 static void request_input_private_key_reply(DBusMessage *reply,
815                                                         void *user_data)
816 {
817         struct ov_private_data *data = user_data;
818         const char *privatekeypass = NULL;
819         const char *key;
820         DBusMessageIter iter, dict;
821         DBusError error;
822         int err = 0;
823
824         connman_info("provider %p", data->provider);
825
826         /*
827          * When connmand calls disconnect because of connection timeout no
828          * reply is received.
829          */
830         if (!reply) {
831                 err = ENOENT;
832                 goto err;
833         }
834
835         dbus_error_init(&error);
836
837         err = vpn_agent_check_and_process_reply_error(reply, data->provider,
838                                 data->task, data->cb, data->user_data);
839         if (err) {
840                 /* Ensure cb is called only once */
841                 data->cb = NULL;
842                 data->user_data = NULL;
843                 return;
844         }
845
846         if (!vpn_agent_check_reply_has_dict(reply)) {
847                 err = ENOENT;
848                 goto err;
849         }
850
851         dbus_message_iter_init(reply, &iter);
852         dbus_message_iter_recurse(&iter, &dict);
853         while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
854                 DBusMessageIter entry, value;
855
856                 dbus_message_iter_recurse(&dict, &entry);
857                 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
858                         break;
859
860                 dbus_message_iter_get_basic(&entry, &key);
861
862                 if (g_str_equal(key, "OpenVPN.PrivateKeyPassword")) {
863                         dbus_message_iter_next(&entry);
864                         if (dbus_message_iter_get_arg_type(&entry)
865                                                         != DBUS_TYPE_VARIANT)
866                                 break;
867                         dbus_message_iter_recurse(&entry, &value);
868                         if (dbus_message_iter_get_arg_type(&value)
869                                                         != DBUS_TYPE_STRING)
870                                 break;
871                         dbus_message_iter_get_basic(&value, &privatekeypass);
872                         vpn_provider_set_string_hide_value(data->provider,
873                                         key, privatekeypass);
874
875                 }
876
877                 dbus_message_iter_next(&dict);
878         }
879
880         if (!privatekeypass) {
881                 vpn_provider_indicate_error(data->provider,
882                                         VPN_PROVIDER_ERROR_AUTH_FAILED);
883
884                 err = EACCES;
885                 goto err;
886         }
887
888         ov_return_private_key_password(data, privatekeypass);
889
890         return;
891
892 err:
893         ov_connect_done(data, err);
894 }
895
896 static int request_private_key_input(struct ov_private_data *data)
897 {
898         DBusMessage *message;
899         const char *path, *agent_sender, *agent_path;
900         const char *privatekeypass;
901         DBusMessageIter iter;
902         DBusMessageIter dict;
903         int err;
904         void *agent;
905
906         /*
907          * First check if this is the second attempt to get the key within
908          * this connection. In such case there has been invalid Private Key
909          * Password and it must be reset, and queried from user.
910          */
911         if (data->failed_attempts_privatekey) {
912                 vpn_provider_set_string_hide_value(data->provider,
913                                         "OpenVPN.PrivateKeyPassword", NULL);
914         } else {
915                 /* If the encrypted Private key password is kept in memory and
916                  * use it first. If authentication fails this is cleared,
917                  * likewise it is when connman-vpnd is restarted.
918                  */
919                 privatekeypass = vpn_provider_get_string(data->provider,
920                                         "OpenVPN.PrivateKeyPassword");
921                 if (privatekeypass) {
922                         ov_return_private_key_password(data, privatekeypass);
923                         goto out;
924                 }
925         }
926
927         agent = connman_agent_get_info(data->dbus_sender, &agent_sender,
928                                                         &agent_path);
929         if (!agent || !agent_path)
930                 return -ESRCH;
931
932         message = dbus_message_new_method_call(agent_sender, agent_path,
933                                         VPN_AGENT_INTERFACE,
934                                         "RequestInput");
935         if (!message)
936                 return -ENOMEM;
937
938         dbus_message_iter_init_append(message, &iter);
939
940         path = vpn_provider_get_path(data->provider);
941         dbus_message_iter_append_basic(&iter,
942                                 DBUS_TYPE_OBJECT_PATH, &path);
943
944         connman_dbus_dict_open(&iter, &dict);
945
946         connman_dbus_dict_append_dict(&dict, "OpenVPN.PrivateKeyPassword",
947                         request_input_append_password, NULL);
948
949         vpn_agent_append_host_and_name(&dict, data->provider);
950
951         /* Do not allow to store or retrieve the encrypted Private Key pass */
952         vpn_agent_append_allow_credential_storage(&dict, false);
953         vpn_agent_append_allow_credential_retrieval(&dict, false);
954
955         /*
956          * Indicate to keep credentials, the enc Private Key password should
957          * not affect the credential storing.
958          */
959         vpn_agent_append_keep_credentials(&dict, true);
960
961         connman_dbus_dict_append_dict(&dict, "Enter Private Key password",
962                         request_input_append_informational, NULL);
963
964         connman_dbus_dict_close(&iter, &dict);
965
966         err = connman_agent_queue_message(data->provider, message,
967                         connman_timeout_input_request(),
968                         request_input_private_key_reply, data, agent);
969
970         if (err < 0 && err != -EBUSY) {
971                 connman_error("error %d sending agent request", err);
972                 dbus_message_unref(message);
973
974                 return err;
975         }
976
977         dbus_message_unref(message);
978
979 out:
980         return -EINPROGRESS;
981 }
982
983 static gboolean ov_management_handle_input(GIOChannel *source,
984                                 GIOCondition condition, gpointer user_data)
985 {
986         struct ov_private_data *data = user_data;
987         char *str = NULL;
988         int err = 0;
989         bool close = false;
990
991         if (condition & G_IO_IN) {
992                 /*
993                  * Just return if line is not read and str is not allocated.
994                  * Condition check handles closing of the channel later.
995                  */
996                 if (g_io_channel_read_line(source, &str, NULL, NULL, NULL) !=
997                                                         G_IO_STATUS_NORMAL)
998                         return true;
999
1000                 str[strlen(str) - 1] = '\0';
1001                 connman_warn("openvpn request %s", str);
1002
1003                 if (g_str_has_prefix(str, ">PASSWORD:Need 'Auth'")) {
1004                         /*
1005                          * Request credentials from the user
1006                          */
1007                         err = request_credentials_input(data);
1008                         if (err != -EINPROGRESS)
1009                                 close = true;
1010                 } else if (g_str_has_prefix(str,
1011                                 ">PASSWORD:Need 'Private Key'")) {
1012                         err = request_private_key_input(data);
1013                         if (err != -EINPROGRESS)
1014                                 close = true;
1015                 } else if (g_str_has_prefix(str,
1016                                 ">PASSWORD:Verification Failed: 'Auth'")) {
1017                         /*
1018                          * Add error only, state change indication causes
1019                          * signal to be sent, which is not desired when
1020                          * OpenVPN is in interactive mode.
1021                          */
1022                         vpn_provider_add_error(data->provider,
1023                                         VPN_PROVIDER_ERROR_AUTH_FAILED);
1024                 /*
1025                  * According to the OpenVPN manual about management interface
1026                  * https://openvpn.net/community-resources/management-interface/
1027                  * this should be received but it does not seem to be reported
1028                  * when decrypting private key fails. This requires following
1029                  * patch for OpenVPN (at least <= 2.4.5) in order to work:
1030                  * https://git.sailfishos.org/mer-core/openvpn/blob/
1031                  * 4f4b4af116292a207416c8a990392e35a6fc41af/rpm/privatekey-
1032                  * passphrase-handling.diff
1033                  */
1034                 } else if (g_str_has_prefix(str, ">PASSWORD:Verification "
1035                                 "Failed: 'Private Key'")) {
1036                         data->failed_attempts_privatekey++;
1037                 }
1038
1039                 g_free(str);
1040         } else if (condition & (G_IO_ERR | G_IO_HUP)) {
1041                 connman_warn("Management channel termination");
1042                 close = true;
1043         }
1044
1045         if (close)
1046                 close_management_interface(data);
1047
1048         return true;
1049 }
1050
1051 static int ov_management_connect_timer_cb(gpointer user_data)
1052 {
1053         struct ov_private_data *data = user_data;
1054
1055         if (!data->mgmt_channel) {
1056                 int fd = socket(AF_UNIX, SOCK_STREAM, 0);
1057                 if (fd >= 0) {
1058                         struct sockaddr_un remote;
1059                         int err;
1060
1061                         memset(&remote, 0, sizeof(remote));
1062                         remote.sun_family = AF_UNIX;
1063                         g_strlcpy(remote.sun_path, data->mgmt_path,
1064                                                 sizeof(remote.sun_path));
1065
1066                         err = connect(fd, (struct sockaddr *)&remote,
1067                                                 sizeof(remote));
1068                         if (err == 0) {
1069                                 data->mgmt_channel = g_io_channel_unix_new(fd);
1070                                 data->mgmt_event_id =
1071                                         g_io_add_watch(data->mgmt_channel,
1072                                                 G_IO_IN | G_IO_ERR | G_IO_HUP,
1073                                                 ov_management_handle_input,
1074                                                 data);
1075
1076                                 connman_warn("Connected management socket");
1077                                 data->mgmt_timer_id = 0;
1078                                 return G_SOURCE_REMOVE;
1079                         }
1080                         close(fd);
1081                 }
1082         }
1083
1084         data->connect_attempts++;
1085         if (data->connect_attempts > 30) {
1086                 connman_warn("Unable to connect management socket");
1087                 data->mgmt_timer_id = 0;
1088                 return G_SOURCE_REMOVE;
1089         }
1090
1091         return G_SOURCE_CONTINUE;
1092 }
1093
1094 static int ov_connect(struct vpn_provider *provider,
1095                         struct connman_task *task, const char *if_name,
1096                         vpn_provider_connect_cb_t cb, const char *dbus_sender,
1097                         void *user_data)
1098 {
1099         const char *tmpdir;
1100         struct ov_private_data *data;
1101
1102         data = g_try_new0(struct ov_private_data, 1);
1103         if (!data)
1104                 return -ENOMEM;
1105
1106         vpn_provider_set_plugin_data(provider, data);
1107         data->provider = vpn_provider_ref(provider);
1108         data->task = task;
1109         data->dbus_sender = g_strdup(dbus_sender);
1110         data->if_name = g_strdup(if_name);
1111         data->cb = cb;
1112         data->user_data = user_data;
1113
1114         /*
1115          * We need to use the management interface to provide
1116          * the user credentials and password for decrypting private key.
1117          */
1118
1119         /* Use env TMPDIR for creating management socket, fall back to /tmp */
1120         tmpdir = getenv("TMPDIR");
1121         if (!tmpdir || !*tmpdir)
1122                 tmpdir = "/tmp";
1123
1124         /* Set up the path for the management interface */
1125         data->mgmt_path = g_strconcat(tmpdir, "/connman-vpn-management-",
1126                 vpn_provider_get_ident(provider), NULL);
1127         if (unlink(data->mgmt_path) != 0 && errno != ENOENT) {
1128                 connman_warn("Unable to unlink management socket %s: %d",
1129                                         data->mgmt_path, errno);
1130         }
1131
1132         data->mgmt_timer_id = g_timeout_add(200,
1133                                 ov_management_connect_timer_cb, data);
1134
1135         task_append_config_data(provider, task);
1136
1137         return run_connect(data, cb, user_data);
1138 }
1139
1140 static void ov_disconnect(struct vpn_provider *provider)
1141 {
1142         if (!provider)
1143                 return;
1144
1145         connman_agent_cancel(provider);
1146
1147         vpn_provider_set_state(provider, VPN_PROVIDER_STATE_DISCONNECT);
1148 }
1149
1150 static int ov_device_flags(struct vpn_provider *provider)
1151 {
1152         const char *option;
1153
1154         option = vpn_provider_get_string(provider, "OpenVPN.DeviceType");
1155         if (!option) {
1156                 return IFF_TUN;
1157         }
1158
1159         if (g_str_equal(option, "tap")) {
1160                 return IFF_TAP;
1161         }
1162
1163         if (!g_str_equal(option, "tun")) {
1164                 connman_warn("bad OpenVPN.DeviceType value "
1165                                         "falling back to tun");
1166         }
1167
1168         return IFF_TUN;
1169 }
1170
1171 static int ov_route_env_parse(struct vpn_provider *provider, const char *key,
1172                                         int *family, unsigned long *idx,
1173                                         enum vpn_provider_route_type *type)
1174 {
1175         char *end;
1176         const char *start;
1177
1178         if (g_str_has_prefix(key, "route_network_")) {
1179                 start = key + strlen("route_network_");
1180                 *type = VPN_PROVIDER_ROUTE_TYPE_ADDR;
1181         } else if (g_str_has_prefix(key, "route_netmask_")) {
1182                 start = key + strlen("route_netmask_");
1183                 *type = VPN_PROVIDER_ROUTE_TYPE_MASK;
1184         } else if (g_str_has_prefix(key, "route_gateway_")) {
1185                 start = key + strlen("route_gateway_");
1186                 *type = VPN_PROVIDER_ROUTE_TYPE_GW;
1187         } else
1188                 return -EINVAL;
1189
1190         *family = AF_INET;
1191         *idx = g_ascii_strtoull(start, &end, 10);
1192
1193         return 0;
1194 }
1195
1196 static struct vpn_driver vpn_driver = {
1197         .notify = ov_notify,
1198         .connect        = ov_connect,
1199         .disconnect     = ov_disconnect,
1200         .save           = ov_save,
1201         .device_flags = ov_device_flags,
1202         .route_env_parse = ov_route_env_parse,
1203 };
1204
1205 static int openvpn_init(void)
1206 {
1207         connection = connman_dbus_get_connection();
1208
1209         return vpn_register("openvpn", &vpn_driver, OPENVPN);
1210 }
1211
1212 static void openvpn_exit(void)
1213 {
1214         vpn_unregister("openvpn");
1215
1216         dbus_connection_unref(connection);
1217 }
1218
1219 CONNMAN_PLUGIN_DEFINE(openvpn, "OpenVPN plugin", VERSION,
1220         CONNMAN_PLUGIN_PRIORITY_DEFAULT, openvpn_init, openvpn_exit)