Merge "Fix crash caused by decryption response delay" into tizen
[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 enum opt_type {
60         OPT_NONE = 0,
61         OPT_STRING = 1,
62         OPT_BOOL = 2,
63 };
64
65 struct {
66         const char      *cm_opt;
67         const char      *ov_opt;
68         const char      *ov_opt_to_null;
69         enum opt_type   opt_type;
70 } ov_options[] = {
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},
79         /*
80          * If the AuthUserPass option is "-", provide the input  via management
81          * interface. To facilitate this set the option as NULL.
82          */
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},
101 };
102
103 struct ov_private_data {
104         struct vpn_provider *provider;
105         struct connman_task *task;
106         char *dbus_sender;
107         char *if_name;
108         vpn_provider_connect_cb_t cb;
109         void *user_data;
110         char *mgmt_path;
111         guint mgmt_timer_id;
112         guint mgmt_event_id;
113         GIOChannel *mgmt_channel;
114         int connect_attempts;
115         int failed_attempts_privatekey;
116 };
117
118 static void ov_connect_done(struct ov_private_data *data, int err)
119 {
120         if (data && data->cb) {
121                 vpn_provider_connect_cb_t cb = data->cb;
122                 void *user_data = data->user_data;
123
124                 /* Make sure we don't invoke this callback twice */
125                 data->cb = NULL;
126                 data->user_data = NULL;
127                 cb(data->provider, user_data, err);
128         }
129
130         if (!err)
131                 data->failed_attempts_privatekey = 0;
132 }
133
134 static void free_private_data(struct ov_private_data *data)
135 {
136         if (vpn_provider_get_plugin_data(data->provider) == data)
137                 vpn_provider_set_plugin_data(data->provider, NULL);
138
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);
144         g_free(data);
145 }
146
147 struct nameserver_entry {
148         int id;
149         char *nameserver;
150 };
151
152 static struct nameserver_entry *ov_append_dns_entries(const char *key,
153                                                 const char *value)
154 {
155         struct nameserver_entry *entry = NULL;
156         gchar **options;
157
158         if (!g_str_has_prefix(key, "foreign_option_"))
159                 return NULL;
160
161         options = g_strsplit(value, " ", 3);
162         if (options[0] &&
163                 !strcmp(options[0], "dhcp-option") &&
164                         options[1] &&
165                         !strcmp(options[1], "DNS") &&
166                                 options[2]) {
167
168                 entry = g_try_new(struct nameserver_entry, 1);
169 #if defined TIZEN_EXT
170                 if (!entry) {
171                         g_strfreev(options);
172                         return NULL;
173                 }
174 #else
175                 if (!entry)
176                         return NULL;
177 #endif
178
179                 entry->nameserver = g_strdup(options[2]);
180                 entry->id = atoi(key + 15); /* foreign_option_XXX */
181         }
182
183         g_strfreev(options);
184
185         return entry;
186 }
187
188 static char *ov_get_domain_name(const char *key, const char *value)
189 {
190         gchar **options;
191         char *domain = NULL;
192
193         if (!g_str_has_prefix(key, "foreign_option_"))
194                 return NULL;
195
196         options = g_strsplit(value, " ", 3);
197         if (options[0] &&
198                 !strcmp(options[0], "dhcp-option") &&
199                         options[1] &&
200                         !strcmp(options[1], "DOMAIN") &&
201                                 options[2]) {
202
203                 domain = g_strdup(options[2]);
204         }
205
206         g_strfreev(options);
207
208         return domain;
209 }
210
211 static gint cmp_ns(gconstpointer a, gconstpointer b)
212 {
213         struct nameserver_entry *entry_a = (struct nameserver_entry *)a;
214         struct nameserver_entry *entry_b = (struct nameserver_entry *)b;
215
216         if (entry_a->id < entry_b->id)
217                 return -1;
218
219         if (entry_a->id > entry_b->id)
220                 return 1;
221
222         return 0;
223 }
224
225 static void free_ns_entry(gpointer data)
226 {
227         struct nameserver_entry *entry = data;
228
229         g_free(entry->nameserver);
230         g_free(entry);
231 }
232
233 static int ov_notify(DBusMessage *msg, struct vpn_provider *provider)
234 {
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);
241
242         dbus_message_iter_init(msg, &iter);
243
244         dbus_message_iter_get_basic(&iter, &reason);
245         dbus_message_iter_next(&iter);
246
247         if (!provider) {
248                 connman_error("No provider found");
249                 return VPN_STATE_FAILURE;
250         }
251
252         DBG("%p %s", vpn_provider_get_name(provider), reason);
253
254         if (strcmp(reason, "up")) {
255                 ov_connect_done(data, EIO);
256                 return VPN_STATE_DISCONNECT;
257         }
258
259         dbus_message_iter_recurse(&iter, &dict);
260
261         while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
262                 struct nameserver_entry *ns_entry = NULL;
263                 DBusMessageIter entry;
264
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);
269
270                 DBG("%s = %s", key, value);
271
272                 if (!strcmp(key, "trusted_ip"))
273                         gateway = g_strdup(value);
274
275                 if (!strcmp(key, "ifconfig_local"))
276                         address = g_strdup(value);
277
278                 if (!strcmp(key, "ifconfig_netmask"))
279                         netmask = g_strdup(value);
280
281                 if (!strcmp(key, "ifconfig_remote"))
282                         peer = g_strdup(value);
283
284                 if (g_str_has_prefix(key, "route_"))
285                         vpn_provider_append_route(provider, key, value);
286
287                 if ((ns_entry = ov_append_dns_entries(key, value)))
288                         nameserver_list = g_slist_prepend(nameserver_list,
289                                                         ns_entry);
290                 else {
291                         char *domain = ov_get_domain_name(key, value);
292                         if (domain) {
293                                 vpn_provider_set_domain(provider, domain);
294                                 g_free(domain);
295                         }
296                 }
297
298                 dbus_message_iter_next(&dict);
299         }
300
301         ipaddress = connman_ipaddress_alloc(AF_INET);
302         if (!ipaddress) {
303                 g_slist_free_full(nameserver_list, free_ns_entry);
304                 g_free(address);
305                 g_free(gateway);
306                 g_free(peer);
307                 g_free(netmask);
308
309                 return VPN_STATE_FAILURE;
310         }
311
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);
316
317         if (nameserver_list) {
318                 char *nameservers = NULL;
319                 GSList *tmp;
320
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;
325
326                         if (!nameservers) {
327                                 nameservers = g_strdup(ns->nameserver);
328                         } else {
329                                 char *str;
330                                 str = g_strjoin(" ", nameservers,
331                                                 ns->nameserver, NULL);
332                                 g_free(nameservers);
333                                 nameservers = str;
334                         }
335                 }
336
337                 g_slist_free_full(nameserver_list, free_ns_entry);
338
339                 vpn_provider_set_nameservers(provider, nameservers);
340
341                 g_free(nameservers);
342         }
343
344         g_free(address);
345         g_free(gateway);
346         g_free(peer);
347         g_free(netmask);
348         connman_ipaddress_free(ipaddress);
349
350         ov_connect_done(data, 0);
351         return VPN_STATE_CONNECT;
352 }
353
354 static int ov_save(struct vpn_provider *provider, GKeyFile *keyfile)
355 {
356         const char *option;
357         int i;
358
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);
363                         if (!option)
364                                 continue;
365
366                         g_key_file_set_string(keyfile,
367                                         vpn_provider_get_save_group(provider),
368                                         ov_options[i].cm_opt, option);
369                 }
370         }
371         return 0;
372 }
373
374 static int task_append_config_data(struct vpn_provider *provider,
375                                         struct connman_task *task)
376 {
377         int i;
378
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;
384
385                 switch (ov_options[i].opt_type) {
386                 case OPT_NONE:
387                         continue;
388
389                 case OPT_STRING:
390                         if (!ov_opt)
391                                 continue;
392
393                         option = vpn_provider_get_string(provider, cm_opt);
394                         /*
395                          * A string option may be used alone without a value
396                          * in which case the default value is used by OpenVPN.
397                          */
398                         if (!option && !vpn_provider_setting_key_exists(
399                                                         provider, ov_opt))
400                                 continue;
401
402                         opt_to_null = ov_options[i].ov_opt_to_null;
403                         if (opt_to_null && !g_strcmp0(option, opt_to_null))
404                                 option = NULL;
405
406                         break;
407
408                 case OPT_BOOL:
409                         if (!ov_opt)
410                                 continue;
411
412                         /* Ignore the boolean toggle if option is disabled. */
413                         if (!vpn_provider_get_boolean(provider, cm_opt, false))
414                                 continue;
415
416                         break;
417                 }
418
419                 if (connman_task_add_argument(task, ov_opt, option))
420                         return -EIO;
421
422         }
423
424         return 0;
425 }
426
427 static void close_management_interface(struct ov_private_data *data)
428 {
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);
433
434                 g_free(data->mgmt_path);
435                 data->mgmt_path = NULL;
436         }
437
438         if (data->mgmt_timer_id != 0) {
439                 g_source_remove(data->mgmt_timer_id);
440                 data->mgmt_timer_id = 0;
441         }
442
443         if (data->mgmt_event_id) {
444                 g_source_remove(data->mgmt_event_id);
445                 data->mgmt_event_id = 0;
446         }
447
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;
452         }
453 }
454
455 static void ov_died(struct connman_task *task, int exit_code, void *user_data)
456 {
457         struct ov_private_data *data = user_data;
458
459         /* Cancel any pending agent requests */
460         connman_agent_cancel(data->provider);
461
462         close_management_interface(data);
463
464         vpn_died(task, exit_code, data->provider);
465
466         free_private_data(data);
467 }
468
469 static int run_connect(struct ov_private_data *data,
470                         vpn_provider_connect_cb_t cb, void *user_data)
471 {
472         struct vpn_provider *provider = data->provider;
473         struct connman_task *task = data->task;
474         const char *option;
475         int err = 0;
476
477         option = vpn_provider_get_string(provider, "OpenVPN.ConfigFile");
478         if (!option) {
479                 /*
480                  * Set some default options if user has no config file.
481                  */
482                 option = vpn_provider_get_string(provider, "OpenVPN.TLSAuth");
483                 if (option) {
484                         connman_task_add_argument(task, "--tls-auth", option);
485                         option = vpn_provider_get_string(provider,
486                                                         "OpenVPN.TLSAuthDir");
487                         if (option)
488                                 connman_task_add_argument(task, option, NULL);
489                 }
490
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);
494         }
495
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",
501                                                                 NULL);
502                 connman_task_add_argument(task, "--auth-retry", "interact");
503         }
504
505         connman_task_add_argument(task, "--syslog", NULL);
506
507         connman_task_add_argument(task, "--script-security", "2");
508
509         connman_task_add_argument(task, "--up",
510                                         SCRIPTDIR "/openvpn-script");
511         connman_task_add_argument(task, "--up-restart", NULL);
512
513         connman_task_add_argument(task, "--setenv", NULL);
514         connman_task_add_argument(task, "CONNMAN_BUSNAME",
515                                         dbus_bus_get_unique_name(connection));
516
517         connman_task_add_argument(task, "--setenv", NULL);
518         connman_task_add_argument(task, "CONNMAN_INTERFACE",
519                                         CONNMAN_TASK_INTERFACE);
520
521         connman_task_add_argument(task, "--setenv", NULL);
522         connman_task_add_argument(task, "CONNMAN_PATH",
523                                         connman_task_get_path(task));
524
525         connman_task_add_argument(task, "--dev", data->if_name);
526         option = vpn_provider_get_string(provider, "OpenVPN.DeviceType");
527         if (option) {
528                 connman_task_add_argument(task, "--dev-type", option);
529         } else {
530                 /*
531                  * Default to tun for backwards compatibility.
532                  */
533                 connman_task_add_argument(task, "--dev-type", "tun");
534         }
535
536         connman_task_add_argument(task, "--persist-tun", NULL);
537
538 #if !defined TIZEN_EXT
539         connman_task_add_argument(task, "--route-noexec", NULL);
540         connman_task_add_argument(task, "--ifconfig-noexec", NULL);
541 #endif
542
543         /*
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.
550          *
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,
557          * including DNS.
558         */
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");
562                 if (!option)
563                         connman_task_add_argument(task, "--ping-restart", "0");
564
565                 connman_task_add_argument(task, "--connect-retry-max", "1");
566         /* Apply defaults for --ping and --ping-exit only with UDP protocol. */
567         } else {
568                 /* Apply default of 10 second interval for ping if omitted. */
569                 option = vpn_provider_get_string(provider, "OpenVPN.Ping");
570                 if (!option)
571                         connman_task_add_argument(task, "--ping", "10");
572
573                 /* Apply default of 60 seconds for ping exit if omitted. */
574                 option = vpn_provider_get_string(provider, "OpenVPN.PingExit");
575                 if (!option)
576                         connman_task_add_argument(task, "--ping-exit", "60");
577         }
578
579         err = connman_task_run(task, ov_died, data, NULL, NULL, NULL);
580         if (err < 0) {
581                 data->cb = NULL;
582                 data->user_data = NULL;
583                 connman_error("openvpn failed to start");
584                 return -EIO;
585         } else {
586                 /* This lets the caller know that the actual result of
587                  * the operation will be reported to the callback */
588                 return -EINPROGRESS;
589         }
590 }
591
592 static void ov_quote_credential(GString *line, const char *cred)
593 {
594         if (!line)
595                 return;
596
597         g_string_append_c(line, '"');
598
599         while (*cred != '\0') {
600
601                 switch (*cred) {
602                 case ' ':
603                 case '"':
604                 case '\\':
605                         g_string_append_c(line, '\\');
606                         break;
607                 default:
608                         break;
609                 }
610
611                 g_string_append_c(line, *cred++);
612         }
613
614         g_string_append_c(line, '"');
615 }
616
617 static void ov_return_credentials(struct ov_private_data *data,
618                                 const char *username, const char *password)
619 {
620         GString *reply_string;
621         gchar *reply;
622         gsize len;
623
624         reply_string = g_string_new(NULL);
625
626         g_string_append(reply_string, "username \"Auth\" ");
627         ov_quote_credential(reply_string, username);
628         g_string_append_c(reply_string, '\n');
629
630         g_string_append(reply_string, "password \"Auth\" ");
631         ov_quote_credential(reply_string, password);
632         g_string_append_c(reply_string, '\n');
633
634         len = reply_string->len;
635         reply = g_string_free(reply_string, FALSE);
636
637         g_io_channel_write_chars(data->mgmt_channel, reply, len, NULL, NULL);
638         g_io_channel_flush(data->mgmt_channel, NULL);
639
640         memset(reply, 0, len);
641         g_free(reply);
642 }
643
644 static void ov_return_private_key_password(struct ov_private_data *data,
645                                 const char *privatekeypass)
646 {
647         GString *reply_string;
648         gchar *reply;
649         gsize len;
650
651         reply_string = g_string_new(NULL);
652
653         g_string_append(reply_string, "password \"Private Key\" ");
654         ov_quote_credential(reply_string, privatekeypass);
655         g_string_append_c(reply_string, '\n');
656
657         len = reply_string->len;
658         reply = g_string_free(reply_string, FALSE);
659
660         g_io_channel_write_chars(data->mgmt_channel, reply, len, NULL, NULL);
661         g_io_channel_flush(data->mgmt_channel, NULL);
662
663         memset(reply, 0, len);
664         g_free(reply);
665 }
666
667 static void request_input_append_informational(DBusMessageIter *iter,
668                 void *user_data)
669 {
670         char *str = "string";
671
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);
677 }
678
679 static void request_input_append_mandatory(DBusMessageIter *iter,
680                 void *user_data)
681 {
682         char *str = "string";
683
684         connman_dbus_dict_append_basic(iter, "Type",
685                                 DBUS_TYPE_STRING, &str);
686         str = "mandatory";
687         connman_dbus_dict_append_basic(iter, "Requirement",
688                                 DBUS_TYPE_STRING, &str);
689 }
690
691 static void request_input_append_password(DBusMessageIter *iter,
692                 void *user_data)
693 {
694         char *str = "password";
695
696         connman_dbus_dict_append_basic(iter, "Type",
697                                 DBUS_TYPE_STRING, &str);
698         str = "mandatory";
699         connman_dbus_dict_append_basic(iter, "Requirement",
700                                 DBUS_TYPE_STRING, &str);
701 }
702
703 static void request_input_credentials_reply(DBusMessage *reply,
704                                                         void *user_data)
705 {
706         struct ov_private_data *data = user_data;
707         char *username = NULL;
708         char *password = NULL;
709         char *key;
710         DBusMessageIter iter, dict;
711         DBusError error;
712         int err = 0;
713
714         connman_info("provider %p", data->provider);
715
716         /*
717          * When connmand calls disconnect because of connection timeout no
718          * reply is received.
719          */
720         if (!reply) {
721                 err = ENOENT;
722                 goto err;
723         }
724
725         dbus_error_init(&error);
726
727         err = vpn_agent_check_and_process_reply_error(reply, data->provider,
728                                 data->task, data->cb, data->user_data);
729         if (err) {
730                 /* Ensure cb is called only once */
731                 data->cb = NULL;
732                 data->user_data = NULL;
733                 return;
734         }
735
736         if (!vpn_agent_check_reply_has_dict(reply)) {
737                 err = ENOENT;
738                 goto err;
739         }
740
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;
745
746                 dbus_message_iter_recurse(&dict, &entry);
747                 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
748                         break;
749
750                 dbus_message_iter_get_basic(&entry, &key);
751
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)
756                                 break;
757                         dbus_message_iter_recurse(&entry, &value);
758                         if (dbus_message_iter_get_arg_type(&value)
759                                                         != DBUS_TYPE_STRING)
760                                 break;
761                         dbus_message_iter_get_basic(&value, &password);
762                         vpn_provider_set_string_hide_value(data->provider,
763                                         key, password);
764
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)
769                                 break;
770                         dbus_message_iter_recurse(&entry, &value);
771                         if (dbus_message_iter_get_arg_type(&value)
772                                                         != DBUS_TYPE_STRING)
773                                 break;
774                         dbus_message_iter_get_basic(&value, &username);
775                         vpn_provider_set_string_hide_value(data->provider,
776                                         key, username);
777                 }
778
779                 dbus_message_iter_next(&dict);
780         }
781
782         if (!password || !username) {
783                 vpn_provider_indicate_error(data->provider,
784                                         VPN_PROVIDER_ERROR_AUTH_FAILED);
785                 err = EACCES;
786                 goto err;
787         }
788
789         ov_return_credentials(data, username, password);
790
791         return;
792
793 err:
794         ov_connect_done(data, err);
795 }
796
797 static int request_credentials_input(struct ov_private_data *data)
798 {
799         DBusMessage *message;
800         const char *path, *agent_sender, *agent_path;
801         DBusMessageIter iter;
802         DBusMessageIter dict;
803         int err;
804         void *agent;
805
806         agent = connman_agent_get_info(data->dbus_sender, &agent_sender,
807                                                         &agent_path);
808         if (!agent || !agent_path)
809                 return -ESRCH;
810
811         message = dbus_message_new_method_call(agent_sender, agent_path,
812                                         VPN_AGENT_INTERFACE,
813                                         "RequestInput");
814         if (!message)
815                 return -ENOMEM;
816
817         dbus_message_iter_init_append(message, &iter);
818
819         path = vpn_provider_get_path(data->provider);
820         dbus_message_iter_append_basic(&iter,
821                                 DBUS_TYPE_OBJECT_PATH, &path);
822
823         connman_dbus_dict_open(&iter, &dict);
824
825         if (vpn_provider_get_authentication_errors(data->provider))
826                 vpn_agent_append_auth_failure(&dict, data->provider, NULL);
827
828         /* Request temporary properties to pass on to openvpn */
829         connman_dbus_dict_append_dict(&dict, "OpenVPN.Username",
830                         request_input_append_mandatory, NULL);
831
832         connman_dbus_dict_append_dict(&dict, "OpenVPN.Password",
833                         request_input_append_password, NULL);
834
835         vpn_agent_append_host_and_name(&dict, data->provider);
836
837         connman_dbus_dict_close(&iter, &dict);
838
839         err = connman_agent_queue_message(data->provider, message,
840                         connman_timeout_input_request(),
841                         request_input_credentials_reply, data, agent);
842
843         if (err < 0 && err != -EBUSY) {
844                 connman_error("error %d sending agent request", err);
845                 dbus_message_unref(message);
846
847                 return err;
848         }
849
850         dbus_message_unref(message);
851
852         return -EINPROGRESS;
853 }
854
855 static void request_input_private_key_reply(DBusMessage *reply,
856                                                         void *user_data)
857 {
858         struct ov_private_data *data = user_data;
859         const char *privatekeypass = NULL;
860         const char *key;
861         DBusMessageIter iter, dict;
862         DBusError error;
863         int err = 0;
864
865         connman_info("provider %p", data->provider);
866
867         /*
868          * When connmand calls disconnect because of connection timeout no
869          * reply is received.
870          */
871         if (!reply) {
872                 err = ENOENT;
873                 goto err;
874         }
875
876         dbus_error_init(&error);
877
878         err = vpn_agent_check_and_process_reply_error(reply, data->provider,
879                                 data->task, data->cb, data->user_data);
880         if (err) {
881                 /* Ensure cb is called only once */
882                 data->cb = NULL;
883                 data->user_data = NULL;
884                 return;
885         }
886
887         if (!vpn_agent_check_reply_has_dict(reply)) {
888                 err = ENOENT;
889                 goto err;
890         }
891
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;
896
897                 dbus_message_iter_recurse(&dict, &entry);
898                 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
899                         break;
900
901                 dbus_message_iter_get_basic(&entry, &key);
902
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)
907                                 break;
908                         dbus_message_iter_recurse(&entry, &value);
909                         if (dbus_message_iter_get_arg_type(&value)
910                                                         != DBUS_TYPE_STRING)
911                                 break;
912                         dbus_message_iter_get_basic(&value, &privatekeypass);
913                         vpn_provider_set_string_hide_value(data->provider,
914                                         key, privatekeypass);
915
916                 }
917
918                 dbus_message_iter_next(&dict);
919         }
920
921         if (!privatekeypass) {
922                 vpn_provider_indicate_error(data->provider,
923                                         VPN_PROVIDER_ERROR_AUTH_FAILED);
924
925                 err = EACCES;
926                 goto err;
927         }
928
929         ov_return_private_key_password(data, privatekeypass);
930
931         return;
932
933 err:
934         ov_connect_done(data, err);
935 }
936
937 static int request_private_key_input(struct ov_private_data *data)
938 {
939         DBusMessage *message;
940         const char *path, *agent_sender, *agent_path;
941         const char *privatekeypass;
942         DBusMessageIter iter;
943         DBusMessageIter dict;
944         int err;
945         void *agent;
946
947         /*
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.
951          */
952         if (data->failed_attempts_privatekey) {
953                 vpn_provider_set_string_hide_value(data->provider,
954                                         "OpenVPN.PrivateKeyPassword", NULL);
955         } else {
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.
959                  */
960                 privatekeypass = vpn_provider_get_string(data->provider,
961                                         "OpenVPN.PrivateKeyPassword");
962                 if (privatekeypass) {
963                         ov_return_private_key_password(data, privatekeypass);
964                         goto out;
965                 }
966         }
967
968         agent = connman_agent_get_info(data->dbus_sender, &agent_sender,
969                                                         &agent_path);
970         if (!agent || !agent_path)
971                 return -ESRCH;
972
973         message = dbus_message_new_method_call(agent_sender, agent_path,
974                                         VPN_AGENT_INTERFACE,
975                                         "RequestInput");
976         if (!message)
977                 return -ENOMEM;
978
979         dbus_message_iter_init_append(message, &iter);
980
981         path = vpn_provider_get_path(data->provider);
982         dbus_message_iter_append_basic(&iter,
983                                 DBUS_TYPE_OBJECT_PATH, &path);
984
985         connman_dbus_dict_open(&iter, &dict);
986
987         connman_dbus_dict_append_dict(&dict, "OpenVPN.PrivateKeyPassword",
988                         request_input_append_password, NULL);
989
990         vpn_agent_append_host_and_name(&dict, data->provider);
991
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);
995
996         /*
997          * Indicate to keep credentials, the enc Private Key password should
998          * not affect the credential storing.
999          */
1000         vpn_agent_append_keep_credentials(&dict, true);
1001
1002         connman_dbus_dict_append_dict(&dict, "Enter Private Key password",
1003                         request_input_append_informational, NULL);
1004
1005         connman_dbus_dict_close(&iter, &dict);
1006
1007         err = connman_agent_queue_message(data->provider, message,
1008                         connman_timeout_input_request(),
1009                         request_input_private_key_reply, data, agent);
1010
1011         if (err < 0 && err != -EBUSY) {
1012                 connman_error("error %d sending agent request", err);
1013                 dbus_message_unref(message);
1014
1015                 return err;
1016         }
1017
1018         dbus_message_unref(message);
1019
1020 out:
1021         return -EINPROGRESS;
1022 }
1023
1024 static gboolean ov_management_handle_input(GIOChannel *source,
1025                                 GIOCondition condition, gpointer user_data)
1026 {
1027         struct ov_private_data *data = user_data;
1028         char *str = NULL;
1029         int err = 0;
1030         bool close = false;
1031
1032         if (condition & G_IO_IN) {
1033                 /*
1034                  * Just return if line is not read and str is not allocated.
1035                  * Condition check handles closing of the channel later.
1036                  */
1037                 if (g_io_channel_read_line(source, &str, NULL, NULL, NULL) !=
1038                                                         G_IO_STATUS_NORMAL)
1039                         return true;
1040
1041                 str[strlen(str) - 1] = '\0';
1042                 connman_warn("openvpn request %s", str);
1043
1044                 if (g_str_has_prefix(str, ">PASSWORD:Need 'Auth'")) {
1045                         /*
1046                          * Request credentials from the user
1047                          */
1048                         err = request_credentials_input(data);
1049                         if (err != -EINPROGRESS)
1050                                 close = true;
1051                 } else if (g_str_has_prefix(str,
1052                                 ">PASSWORD:Need 'Private Key'")) {
1053                         err = request_private_key_input(data);
1054                         if (err != -EINPROGRESS)
1055                                 close = true;
1056                 } else if (g_str_has_prefix(str,
1057                                 ">PASSWORD:Verification Failed: 'Auth'")) {
1058                         /*
1059                          * Add error only, state change indication causes
1060                          * signal to be sent, which is not desired when
1061                          * OpenVPN is in interactive mode.
1062                          */
1063                         vpn_provider_add_error(data->provider,
1064                                         VPN_PROVIDER_ERROR_AUTH_FAILED);
1065                 /*
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
1074                  */
1075                 } else if (g_str_has_prefix(str, ">PASSWORD:Verification "
1076                                 "Failed: 'Private Key'")) {
1077                         data->failed_attempts_privatekey++;
1078                 }
1079
1080                 g_free(str);
1081         } else if (condition & (G_IO_ERR | G_IO_HUP)) {
1082                 connman_warn("Management channel termination");
1083                 close = true;
1084         }
1085
1086         if (close)
1087                 close_management_interface(data);
1088
1089         return true;
1090 }
1091
1092 static int ov_management_connect_timer_cb(gpointer user_data)
1093 {
1094         struct ov_private_data *data = user_data;
1095
1096         if (!data->mgmt_channel) {
1097                 int fd = socket(AF_UNIX, SOCK_STREAM, 0);
1098                 if (fd >= 0) {
1099                         struct sockaddr_un remote;
1100                         int err;
1101
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));
1106
1107                         err = connect(fd, (struct sockaddr *)&remote,
1108                                                 sizeof(remote));
1109                         if (err == 0) {
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,
1115                                                 data);
1116
1117                                 connman_warn("Connected management socket");
1118                                 data->mgmt_timer_id = 0;
1119                                 return G_SOURCE_REMOVE;
1120                         }
1121                         close(fd);
1122                 }
1123         }
1124
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;
1130         }
1131
1132         return G_SOURCE_CONTINUE;
1133 }
1134
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,
1138                         void *user_data)
1139 {
1140         const char *tmpdir;
1141         struct ov_private_data *data;
1142
1143         /*
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.
1149          */
1150         vpn_provider_set_auth_error_limit(provider, 10);
1151
1152         data = g_try_new0(struct ov_private_data, 1);
1153         if (!data)
1154                 return -ENOMEM;
1155
1156         vpn_provider_set_plugin_data(provider, data);
1157         data->provider = vpn_provider_ref(provider);
1158         data->task = task;
1159         data->dbus_sender = g_strdup(dbus_sender);
1160         data->if_name = g_strdup(if_name);
1161         data->cb = cb;
1162         data->user_data = user_data;
1163
1164         /*
1165          * We need to use the management interface to provide
1166          * the user credentials and password for decrypting private key.
1167          */
1168
1169         /* Use env TMPDIR for creating management socket, fall back to /tmp */
1170         tmpdir = getenv("TMPDIR");
1171         if (!tmpdir || !*tmpdir)
1172                 tmpdir = "/tmp";
1173
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);
1180         }
1181
1182         data->mgmt_timer_id = g_timeout_add(200,
1183                                 ov_management_connect_timer_cb, data);
1184
1185         task_append_config_data(provider, task);
1186
1187         return run_connect(data, cb, user_data);
1188 }
1189
1190 static void ov_disconnect(struct vpn_provider *provider)
1191 {
1192         if (!provider)
1193                 return;
1194
1195         connman_agent_cancel(provider);
1196
1197         vpn_provider_set_state(provider, VPN_PROVIDER_STATE_DISCONNECT);
1198 }
1199
1200 static int ov_device_flags(struct vpn_provider *provider)
1201 {
1202         const char *option;
1203
1204         option = vpn_provider_get_string(provider, "OpenVPN.DeviceType");
1205         if (!option) {
1206                 return IFF_TUN;
1207         }
1208
1209         if (g_str_equal(option, "tap")) {
1210                 return IFF_TAP;
1211         }
1212
1213         if (!g_str_equal(option, "tun")) {
1214                 connman_warn("bad OpenVPN.DeviceType value "
1215                                         "falling back to tun");
1216         }
1217
1218         return IFF_TUN;
1219 }
1220
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)
1224 {
1225         char *end;
1226         const char *start;
1227
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;
1237         } else
1238                 return -EINVAL;
1239
1240         *family = AF_INET;
1241         *idx = g_ascii_strtoull(start, &end, 10);
1242
1243         return 0;
1244 }
1245
1246 static struct vpn_driver vpn_driver = {
1247         .notify = ov_notify,
1248         .connect        = ov_connect,
1249         .disconnect     = ov_disconnect,
1250         .save           = ov_save,
1251         .device_flags = ov_device_flags,
1252         .route_env_parse = ov_route_env_parse,
1253 };
1254
1255 static int openvpn_init(void)
1256 {
1257         connection = connman_dbus_get_connection();
1258
1259         return vpn_register("openvpn", &vpn_driver, OPENVPN);
1260 }
1261
1262 static void openvpn_exit(void)
1263 {
1264         vpn_unregister("openvpn");
1265
1266         dbus_connection_unref(connection);
1267 }
1268
1269 CONNMAN_PLUGIN_DEFINE(openvpn, "OpenVPN plugin", VERSION,
1270         CONNMAN_PLUGIN_PRIORITY_DEFAULT, openvpn_init, openvpn_exit)