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