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