Updated connman to version 1.35
[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  *
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License version 2 as
9  *  published by the Free Software Foundation.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19  *
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <stdlib.h>
27 #include <string.h>
28 #include <errno.h>
29 #include <unistd.h>
30 #include <stdio.h>
31 #include <net/if.h>
32 #include <linux/if_tun.h>
33
34 #include <glib.h>
35
36 #define CONNMAN_API_SUBJECT_TO_CHANGE
37 #include <connman/plugin.h>
38 #include <connman/log.h>
39 #include <connman/task.h>
40 #include <connman/dbus.h>
41 #include <connman/ipconfig.h>
42
43 #include "../vpn-provider.h"
44
45 #include "vpn.h"
46
47 #define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0]))
48
49 static DBusConnection *connection;
50
51 struct {
52         const char *cm_opt;
53         const char *ov_opt;
54         char       has_value;
55 } ov_options[] = {
56         { "Host", "--remote", 1 },
57         { "OpenVPN.CACert", "--ca", 1 },
58         { "OpenVPN.Cert", "--cert", 1 },
59         { "OpenVPN.Key", "--key", 1 },
60         { "OpenVPN.MTU", "--mtu", 1 },
61         { "OpenVPN.NSCertType", "--ns-cert-type", 1 },
62         { "OpenVPN.Proto", "--proto", 1 },
63         { "OpenVPN.Port", "--port", 1 },
64         { "OpenVPN.AuthUserPass", "--auth-user-pass", 1 },
65         { "OpenVPN.AskPass", "--askpass", 1 },
66         { "OpenVPN.AuthNoCache", "--auth-nocache", 0 },
67         { "OpenVPN.TLSRemote", "--tls-remote", 1 },
68         { "OpenVPN.TLSAuth", NULL, 1 },
69         { "OpenVPN.TLSAuthDir", NULL, 1 },
70         { "OpenVPN.Cipher", "--cipher", 1 },
71         { "OpenVPN.Auth", "--auth", 1 },
72         { "OpenVPN.CompLZO", "--comp-lzo", 0 },
73         { "OpenVPN.RemoteCertTls", "--remote-cert-tls", 1 },
74         { "OpenVPN.ConfigFile", "--config", 1 },
75         { "OpenVPN.DeviceType", NULL, 1 },
76         { "OpenVPN.Verb", "--verb", 1 },
77 };
78
79 struct nameserver_entry {
80         int id;
81         char *nameserver;
82 };
83
84 static struct nameserver_entry *ov_append_dns_entries(const char *key,
85                                                 const char *value)
86 {
87         struct nameserver_entry *entry = NULL;
88         gchar **options;
89
90         if (!g_str_has_prefix(key, "foreign_option_"))
91                 return NULL;
92
93         options = g_strsplit(value, " ", 3);
94         if (options[0] &&
95                 !strcmp(options[0], "dhcp-option") &&
96                         options[1] &&
97                         !strcmp(options[1], "DNS") &&
98                                 options[2]) {
99
100                 entry = g_try_new(struct nameserver_entry, 1);
101                 if (!entry)
102                         return NULL;
103
104                 entry->nameserver = g_strdup(options[2]);
105                 entry->id = atoi(key + 15); /* foreign_option_XXX */
106         }
107
108         g_strfreev(options);
109
110         return entry;
111 }
112
113 static char *ov_get_domain_name(const char *key, const char *value)
114 {
115         gchar **options;
116         char *domain = NULL;
117
118         if (!g_str_has_prefix(key, "foreign_option_"))
119                 return NULL;
120
121         options = g_strsplit(value, " ", 3);
122         if (options[0] &&
123                 !strcmp(options[0], "dhcp-option") &&
124                         options[1] &&
125                         !strcmp(options[1], "DOMAIN") &&
126                                 options[2]) {
127
128                 domain = g_strdup(options[2]);
129         }
130
131         g_strfreev(options);
132
133         return domain;
134 }
135
136 static gint cmp_ns(gconstpointer a, gconstpointer b)
137 {
138         struct nameserver_entry *entry_a = (struct nameserver_entry *)a;
139         struct nameserver_entry *entry_b = (struct nameserver_entry *)b;
140
141         if (entry_a->id < entry_b->id)
142                 return -1;
143
144         if (entry_a->id > entry_b->id)
145                 return 1;
146
147         return 0;
148 }
149
150 static void free_ns_entry(gpointer data)
151 {
152         struct nameserver_entry *entry = data;
153
154         g_free(entry->nameserver);
155         g_free(entry);
156 }
157
158 static int ov_notify(DBusMessage *msg, struct vpn_provider *provider)
159 {
160         DBusMessageIter iter, dict;
161         const char *reason, *key, *value;
162         char *address = NULL, *gateway = NULL, *peer = NULL, *netmask = NULL;
163         struct connman_ipaddress *ipaddress;
164         GSList *nameserver_list = NULL;
165
166         dbus_message_iter_init(msg, &iter);
167
168         dbus_message_iter_get_basic(&iter, &reason);
169         dbus_message_iter_next(&iter);
170
171         if (!provider) {
172                 connman_error("No provider found");
173                 return VPN_STATE_FAILURE;
174         }
175
176         if (strcmp(reason, "up"))
177                 return VPN_STATE_DISCONNECT;
178
179         dbus_message_iter_recurse(&iter, &dict);
180
181         while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
182                 struct nameserver_entry *ns_entry = NULL;
183                 DBusMessageIter entry;
184
185                 dbus_message_iter_recurse(&dict, &entry);
186                 dbus_message_iter_get_basic(&entry, &key);
187                 dbus_message_iter_next(&entry);
188                 dbus_message_iter_get_basic(&entry, &value);
189
190                 DBG("%s = %s", key, value);
191
192                 if (!strcmp(key, "trusted_ip"))
193                         gateway = g_strdup(value);
194
195                 if (!strcmp(key, "ifconfig_local"))
196                         address = g_strdup(value);
197
198                 if (!strcmp(key, "ifconfig_netmask"))
199                         netmask = g_strdup(value);
200
201                 if (!strcmp(key, "ifconfig_remote"))
202                         peer = g_strdup(value);
203
204                 if (g_str_has_prefix(key, "route_"))
205                         vpn_provider_append_route(provider, key, value);
206
207                 if ((ns_entry = ov_append_dns_entries(key, value)))
208                         nameserver_list = g_slist_prepend(nameserver_list,
209                                                         ns_entry);
210                 else {
211                         char *domain = ov_get_domain_name(key, value);
212                         if (domain) {
213                                 vpn_provider_set_domain(provider, domain);
214                                 g_free(domain);
215                         }
216                 }
217
218                 dbus_message_iter_next(&dict);
219         }
220
221         ipaddress = connman_ipaddress_alloc(AF_INET);
222         if (!ipaddress) {
223                 g_slist_free_full(nameserver_list, free_ns_entry);
224                 g_free(address);
225                 g_free(gateway);
226                 g_free(peer);
227                 g_free(netmask);
228
229                 return VPN_STATE_FAILURE;
230         }
231
232         connman_ipaddress_set_ipv4(ipaddress, address, netmask, gateway);
233         connman_ipaddress_set_peer(ipaddress, peer);
234         vpn_provider_set_ipaddress(provider, ipaddress);
235
236         if (nameserver_list) {
237                 char *nameservers = NULL;
238                 GSList *tmp;
239
240                 nameserver_list = g_slist_sort(nameserver_list, cmp_ns);
241                 for (tmp = nameserver_list; tmp;
242                                                 tmp = g_slist_next(tmp)) {
243                         struct nameserver_entry *ns = tmp->data;
244
245                         if (!nameservers) {
246                                 nameservers = g_strdup(ns->nameserver);
247                         } else {
248                                 char *str;
249                                 str = g_strjoin(" ", nameservers,
250                                                 ns->nameserver, NULL);
251                                 g_free(nameservers);
252                                 nameservers = str;
253                         }
254                 }
255
256                 g_slist_free_full(nameserver_list, free_ns_entry);
257
258                 vpn_provider_set_nameservers(provider, nameservers);
259
260                 g_free(nameservers);
261         }
262
263         g_free(address);
264         g_free(gateway);
265         g_free(peer);
266         g_free(netmask);
267         connman_ipaddress_free(ipaddress);
268
269         return VPN_STATE_CONNECT;
270 }
271
272 static int ov_save(struct vpn_provider *provider, GKeyFile *keyfile)
273 {
274         const char *option;
275         int i;
276
277         for (i = 0; i < (int)ARRAY_SIZE(ov_options); i++) {
278                 if (strncmp(ov_options[i].cm_opt, "OpenVPN.", 8) == 0) {
279                         option = vpn_provider_get_string(provider,
280                                                         ov_options[i].cm_opt);
281                         if (!option)
282                                 continue;
283
284                         g_key_file_set_string(keyfile,
285                                         vpn_provider_get_save_group(provider),
286                                         ov_options[i].cm_opt, option);
287                 }
288         }
289         return 0;
290 }
291
292 static int task_append_config_data(struct vpn_provider *provider,
293                                         struct connman_task *task)
294 {
295         const char *option;
296         int i;
297
298         for (i = 0; i < (int)ARRAY_SIZE(ov_options); i++) {
299                 if (!ov_options[i].ov_opt)
300                         continue;
301
302                 option = vpn_provider_get_string(provider,
303                                         ov_options[i].cm_opt);
304                 if (!option)
305                         continue;
306
307                 if (connman_task_add_argument(task,
308                                 ov_options[i].ov_opt,
309                                 ov_options[i].has_value ? option : NULL) < 0) {
310                         return -EIO;
311                 }
312         }
313
314         return 0;
315 }
316
317 static gboolean can_read_data(GIOChannel *chan,
318                                 GIOCondition cond, gpointer data)
319 {
320         void (*cbf)(const char *format, ...) = data;
321         gchar *str;
322         gsize size;
323
324         if (cond & (G_IO_NVAL | G_IO_ERR | G_IO_HUP))
325                 return FALSE;
326
327         g_io_channel_read_line(chan, &str, &size, NULL, NULL);
328         cbf(str);
329         g_free(str);
330
331         return TRUE;
332 }
333
334 static int setup_log_read(int stdout_fd, int stderr_fd)
335 {
336         GIOChannel *chan;
337         int watch;
338
339         chan = g_io_channel_unix_new(stdout_fd);
340         g_io_channel_set_close_on_unref(chan, TRUE);
341         watch = g_io_add_watch(chan, G_IO_IN | G_IO_NVAL | G_IO_ERR | G_IO_HUP,
342                                can_read_data, connman_debug);
343         g_io_channel_unref(chan);
344
345         if (watch == 0)
346                 return -EIO;
347
348         chan = g_io_channel_unix_new(stderr_fd);
349         g_io_channel_set_close_on_unref(chan, TRUE);
350         watch = g_io_add_watch(chan, G_IO_IN | G_IO_NVAL | G_IO_ERR | G_IO_HUP,
351                                can_read_data, connman_error);
352         g_io_channel_unref(chan);
353
354         return watch == 0? -EIO : 0;
355 }
356
357 static int ov_connect(struct vpn_provider *provider,
358                         struct connman_task *task, const char *if_name,
359                         vpn_provider_connect_cb_t cb, const char *dbus_sender,
360                         void *user_data)
361 {
362         const char *option;
363         int stdout_fd, stderr_fd;
364         int err = 0;
365
366         option = vpn_provider_get_string(provider, "Host");
367         if (!option) {
368                 connman_error("Host not set; cannot enable VPN");
369                 return -EINVAL;
370         }
371
372         task_append_config_data(provider, task);
373
374         option = vpn_provider_get_string(provider, "OpenVPN.ConfigFile");
375         if (!option) {
376                 /*
377                  * Set some default options if user has no config file.
378                  */
379                 option = vpn_provider_get_string(provider, "OpenVPN.TLSAuth");
380                 if (option) {
381                         connman_task_add_argument(task, "--tls-auth", option);
382                         option = vpn_provider_get_string(provider,
383                                                         "OpenVPN.TLSAuthDir");
384                         if (option)
385                                 connman_task_add_argument(task, option, NULL);
386                 }
387
388                 connman_task_add_argument(task, "--nobind", NULL);
389                 connman_task_add_argument(task, "--persist-key", NULL);
390                 connman_task_add_argument(task, "--client", NULL);
391         }
392
393         connman_task_add_argument(task, "--script-security", "2");
394
395         connman_task_add_argument(task, "--up",
396                                         SCRIPTDIR "/openvpn-script");
397         connman_task_add_argument(task, "--up-restart", NULL);
398
399         connman_task_add_argument(task, "--setenv", NULL);
400         connman_task_add_argument(task, "CONNMAN_BUSNAME",
401                                         dbus_bus_get_unique_name(connection));
402
403         connman_task_add_argument(task, "--setenv", NULL);
404         connman_task_add_argument(task, "CONNMAN_INTERFACE",
405                                         CONNMAN_TASK_INTERFACE);
406
407         connman_task_add_argument(task, "--setenv", NULL);
408         connman_task_add_argument(task, "CONNMAN_PATH",
409                                         connman_task_get_path(task));
410
411         connman_task_add_argument(task, "--dev", if_name);
412         option = vpn_provider_get_string(provider, "OpenVPN.DeviceType");
413         if (option) {
414                 connman_task_add_argument(task, "--dev-type", option);
415         } else {
416                 /*
417                  * Default to tun for backwards compatibility.
418                  */
419                 connman_task_add_argument(task, "--dev-type", "tun");
420         }
421
422         connman_task_add_argument(task, "--persist-tun", NULL);
423
424 #if !defined TIZEN_EXT
425         connman_task_add_argument(task, "--route-noexec", NULL);
426         connman_task_add_argument(task, "--ifconfig-noexec", NULL);
427 #endif
428
429         /*
430          * Disable client restarts because we can't handle this at the
431          * moment. The problem is that when OpenVPN decides to switch
432          * from CONNECTED state to RECONNECTING and then to RESOLVE,
433          * it is not possible to do a DNS lookup. The DNS server is
434          * not accessable through the tunnel anymore and so we end up
435          * trying to resolve the OpenVPN servers address.
436          */
437         connman_task_add_argument(task, "--ping-restart", "0");
438
439         err = connman_task_run(task, vpn_died, provider,
440                         NULL, &stdout_fd, &stderr_fd);
441         if (err < 0) {
442                 connman_error("openvpn failed to start");
443                 err = -EIO;
444                 goto done;
445         }
446
447         err = setup_log_read(stdout_fd, stderr_fd);
448 done:
449         if (cb)
450                 cb(provider, user_data, err);
451
452         return err;
453 }
454
455 static int ov_device_flags(struct vpn_provider *provider)
456 {
457         const char *option;
458
459         option = vpn_provider_get_string(provider, "OpenVPN.DeviceType");
460         if (!option) {
461                 return IFF_TUN;
462         }
463
464         if (g_str_equal(option, "tap")) {
465                 return IFF_TAP;
466         }
467
468         if (!g_str_equal(option, "tun")) {
469                 connman_warn("bad OpenVPN.DeviceType value, falling back to tun");
470         }
471
472         return IFF_TUN;
473 }
474
475 static struct vpn_driver vpn_driver = {
476         .notify = ov_notify,
477         .connect        = ov_connect,
478         .save           = ov_save,
479         .device_flags = ov_device_flags,
480 };
481
482 static int openvpn_init(void)
483 {
484         connection = connman_dbus_get_connection();
485
486         return vpn_register("openvpn", &vpn_driver, OPENVPN);
487 }
488
489 static void openvpn_exit(void)
490 {
491         vpn_unregister("openvpn");
492
493         dbus_connection_unref(connection);
494 }
495
496 CONNMAN_PLUGIN_DEFINE(openvpn, "OpenVPN plugin", VERSION,
497         CONNMAN_PLUGIN_PRIORITY_DEFAULT, openvpn_init, openvpn_exit)