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