1 /*
2 * Copyright (C) 2015 Adrien Vergé
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 *
17 * In addition, as a special exception, the copyright holders give permission
18 * to link the code of portions of this program with the OpenSSL library under
19 * certain conditions as described in each individual source file, and
20 * distribute linked combinations including the two.
21 * You must obey the GNU General Public License in all respects for all of the
22 * code used other than OpenSSL. If you modify file(s) with this exception,
23 * you may extend this exception to your version of the file(s), but you are
24 * not obligated to do so. If you do not wish to do so, delete this exception
25 * statement from your version. If you delete this exception statement from
26 * all source files in the program, then also delete it here.
27 */
28
29 #include "tunnel.h"
30 #include "http.h"
31 #include "log.h"
32 #include "userinput.h"
33 #ifndef HAVE_X509_CHECK_HOST
34 #include "openssl_hostname_validation.h"
35 #endif
36
37 #include <openssl/err.h>
38 #ifndef OPENSSL_NO_ENGINE
39 #include <openssl/engine.h>
40 #endif
41 #include <openssl/ui.h>
42 #include <openssl/x509v3.h>
43 #if HAVE_SYSTEMD
44 #include <systemd/sd-daemon.h>
45 #endif
46
47 #include <unistd.h>
48 #include <arpa/inet.h>
49 #include <fcntl.h>
50 #include <ifaddrs.h>
51 #include <netdb.h>
52 #if HAVE_PTY_H
53 #include <pty.h>
54 #elif HAVE_UTIL_H
55 #include <util.h>
56 #endif
57 #include <sys/types.h>
58 #include <sys/socket.h>
59 #include <sys/wait.h>
60 #include <sys/ioctl.h>
61 #include <termios.h>
62 #if HAVE_LIBUTIL_H
63 #include <libutil.h>
64 #endif
65
66 #include <errno.h>
67 #include <signal.h>
68 #include <string.h>
69 #include <assert.h>
70
71
72 struct ofv_varr {
73 unsigned int cap; // current capacity
74 unsigned int off; // next slot to write, always < max(cap - 1, 1)
75 const char **data; // NULL terminated
76 };
77
ofv_append_varr(struct ofv_varr * p,const char * x)78 static int ofv_append_varr(struct ofv_varr *p, const char *x)
79 {
80 if (p->off + 1 >= p->cap) {
81 const char **ndata;
82 unsigned int ncap = (p->off + 1) * 2;
83
84 if (p->off + 1 >= ncap) {
85 log_error("%s: ncap exceeded\n", __func__);
86 return 1;
87 };
88 ndata = realloc(p->data, ncap * sizeof(const char *));
89 if (ndata) {
90 p->data = ndata;
91 p->cap = ncap;
92 } else {
93 log_error("realloc: %s\n", strerror(errno));
94 return 1;
95 }
96 }
97 if (p->data == NULL) {
98 log_error("%s: NULL data\n", __func__);
99 return 1;
100 }
101 if (p->off + 1 >= p->cap) {
102 log_error("%s: cap exceeded in p\n", __func__);
103 return 1;
104 }
105 p->data[p->off] = x;
106 p->data[++p->off] = NULL;
107 return 0;
108 }
109
on_ppp_if_up(struct tunnel * tunnel)110 static int on_ppp_if_up(struct tunnel *tunnel)
111 {
112 log_info("Interface %s is UP.\n", tunnel->ppp_iface);
113
114 if (tunnel->config->set_routes) {
115 int ret;
116
117 log_info("Setting new routes...\n");
118
119 ret = ipv4_set_tunnel_routes(tunnel);
120
121 if (ret != 0)
122 log_warn("Adding route table is incomplete. Please check route table.\n");
123 }
124
125 if (tunnel->config->set_dns) {
126 log_info("Adding VPN nameservers...\n");
127 ipv4_add_nameservers_to_resolv_conf(tunnel);
128 }
129
130 log_info("Tunnel is up and running.\n");
131
132 #if HAVE_SYSTEMD
133 sd_notify(0, "READY=1");
134 #endif
135
136 return 0;
137 }
138
on_ppp_if_down(struct tunnel * tunnel)139 static int on_ppp_if_down(struct tunnel *tunnel)
140 {
141 #if HAVE_SYSTEMD
142 sd_notify(0, "STOPPING=1");
143 #endif
144
145 log_info("Setting %s interface down.\n", tunnel->ppp_iface);
146
147 if (tunnel->config->set_routes) {
148 log_info("Restoring routes...\n");
149 ipv4_restore_routes(tunnel);
150 }
151
152 if (tunnel->config->set_dns) {
153 log_info("Removing VPN nameservers...\n");
154 ipv4_del_nameservers_from_resolv_conf(tunnel);
155 }
156
157 return 0;
158 }
159
pppd_run(struct tunnel * tunnel)160 static int pppd_run(struct tunnel *tunnel)
161 {
162 pid_t pid;
163 int amaster;
164 int slave_stderr;
165
166 #ifdef HAVE_STRUCT_TERMIOS
167 struct termios termp = {
168 .c_cflag = B9600,
169 .c_cc[VTIME] = 0,
170 .c_cc[VMIN] = 1
171 };
172 #endif
173
174 static const char ppp_path[] = PPP_PATH;
175
176 if (access(ppp_path, F_OK) != 0) {
177 log_error("%s: %s.\n", ppp_path, strerror(errno));
178 return 1;
179 }
180 log_debug("ppp_path: %s\n", ppp_path);
181
182 slave_stderr = dup(STDERR_FILENO);
183
184 if (slave_stderr < 0) {
185 log_error("slave stderr: %s\n", strerror(errno));
186 return 1;
187 }
188
189 #ifdef HAVE_STRUCT_TERMIOS
190 pid = forkpty(&amaster, NULL, &termp, NULL);
191 #else
192 pid = forkpty(&amaster, NULL, NULL, NULL);
193 #endif
194
195 if (pid == 0) { // child process
196
197 struct ofv_varr pppd_args = { 0, 0, NULL };
198
199 dup2(slave_stderr, STDERR_FILENO);
200 if (close(slave_stderr))
201 log_warn("Could not close slave stderr (%s).\n", strerror(errno));
202
203 #if HAVE_USR_SBIN_PPP
204 /*
205 * assume there is a default configuration to start.
206 * Support for taking options from the command line
207 * e.g. the name of the configuration or options
208 * to send interactively to ppp will be added later
209 */
210 static const char *const v[] = {
211 ppp_path,
212 "-direct"
213 };
214 for (unsigned int i = 0; i < ARRAY_SIZE(v); i++)
215 if (ofv_append_varr(&pppd_args, v[i])) {
216 free(pppd_args.data);
217 return 1;
218 }
219 #endif
220 #if HAVE_USR_SBIN_PPPD
221 if (tunnel->config->pppd_call) {
222 if (ofv_append_varr(&pppd_args, ppp_path)) {
223 free(pppd_args.data);
224 return 1;
225 }
226 if (ofv_append_varr(&pppd_args, "call")) {
227 free(pppd_args.data);
228 return 1;
229 }
230 if (ofv_append_varr(&pppd_args, tunnel->config->pppd_call)) {
231 free(pppd_args.data);
232 return 1;
233 }
234 } else {
235 static const char *const v[] = {
236 ppp_path,
237 "230400", // speed
238 ":169.254.2.1", // <local_IP_address>:<remote_IP_address>
239 "noipdefault",
240 "noaccomp",
241 "noauth",
242 "default-asyncmap",
243 "nopcomp",
244 "receive-all",
245 "nodefaultroute",
246 "nodetach",
247 "lcp-max-configure", "40",
248 "mru", "1354"
249 };
250 for (unsigned int i = 0; i < ARRAY_SIZE(v); i++)
251 if (ofv_append_varr(&pppd_args, v[i])) {
252 free(pppd_args.data);
253 return 1;
254 }
255 }
256 if (tunnel->config->pppd_use_peerdns)
257 if (ofv_append_varr(&pppd_args, "usepeerdns")) {
258 free(pppd_args.data);
259 return 1;
260 }
261 if (tunnel->config->pppd_log) {
262 if (ofv_append_varr(&pppd_args, "debug")) {
263 free(pppd_args.data);
264 return 1;
265 }
266 if (ofv_append_varr(&pppd_args, "logfile")) {
267 free(pppd_args.data);
268 return 1;
269 }
270 if (ofv_append_varr(&pppd_args, tunnel->config->pppd_log)) {
271 free(pppd_args.data);
272 return 1;
273 }
274 } else {
275 /*
276 * pppd defaults to logging to fd=1, clobbering the
277 * actual PPP data
278 */
279 if (ofv_append_varr(&pppd_args, "logfd")) {
280 free(pppd_args.data);
281 return 1;
282 }
283 if (ofv_append_varr(&pppd_args, "2")) {
284 free(pppd_args.data);
285 return 1;
286 }
287 }
288 if (tunnel->config->pppd_plugin) {
289 if (ofv_append_varr(&pppd_args, "plugin")) {
290 free(pppd_args.data);
291 return 1;
292 }
293 if (ofv_append_varr(&pppd_args, tunnel->config->pppd_plugin)) {
294 free(pppd_args.data);
295 return 1;
296 }
297 }
298 if (tunnel->config->pppd_ipparam) {
299 if (ofv_append_varr(&pppd_args, "ipparam")) {
300 free(pppd_args.data);
301 return 1;
302 }
303 if (ofv_append_varr(&pppd_args, tunnel->config->pppd_ipparam)) {
304 free(pppd_args.data);
305 return 1;
306 }
307 }
308 if (tunnel->config->pppd_ifname) {
309 if (ofv_append_varr(&pppd_args, "ifname")) {
310 free(pppd_args.data);
311 return 1;
312 }
313 if (ofv_append_varr(&pppd_args, tunnel->config->pppd_ifname)) {
314 free(pppd_args.data);
315 return 1;
316 }
317 }
318 #endif
319 #if HAVE_USR_SBIN_PPP
320 if (tunnel->config->ppp_system) {
321 if (ofv_append_varr(&pppd_args, tunnel->config->ppp_system)) {
322 free(pppd_args.data);
323 return 1;
324 }
325 }
326 #endif
327
328 if (close(tunnel->ssl_socket))
329 log_warn("Could not close ssl socket (%s).\n", strerror(errno));
330 tunnel->ssl_socket = -1;
331 execv(pppd_args.data[0], (char *const *)pppd_args.data);
332 free(pppd_args.data);
333
334 fprintf(stderr, "execv: %s\n", strerror(errno));
335 _exit(EXIT_FAILURE);
336 } else {
337 if (close(slave_stderr))
338 log_error("Could not close slave stderr (%s).\n",
339 strerror(errno));
340 if (pid == -1) {
341 log_error("forkpty: %s\n", strerror(errno));
342 return 1;
343 }
344 }
345
346 // Set non-blocking
347 int flags = fcntl(amaster, F_GETFL, 0);
348
349 if (flags == -1)
350 flags = 0;
351 if (fcntl(amaster, F_SETFL, flags | O_NONBLOCK) == -1) {
352 log_error("fcntl: %s\n", strerror(errno));
353 return 1;
354 }
355
356 tunnel->pppd_pid = pid;
357 tunnel->pppd_pty = amaster;
358
359 return 0;
360 }
361
362 static const char * const ppp_message[] = {
363 #if HAVE_USR_SBIN_PPPD // pppd(8) - https://ppp.samba.org/pppd.html
364 "Has detached, or otherwise the connection was successfully established and terminated at the peer's request.",
365 "An immediately fatal error of some kind occurred, such as an essential system call failing, or running out of virtual memory.",
366 "An error was detected in processing the options given, such as two mutually exclusive options being used.",
367 "Is not setuid-root and the invoking user is not root.",
368 "The kernel does not support PPP, for example, the PPP kernel driver is not included or cannot be loaded.",
369 "Terminated because it was sent a SIGINT, SIGTERM or SIGHUP signal.",
370 "The serial port could not be locked.",
371 "The serial port could not be opened.",
372 "The connect script failed (returned a non-zero exit status).",
373 "The command specified as the argument to the pty option could not be run.",
374 "The PPP negotiation failed, that is, it didn't reach the point where at least one network protocol (e.g. IP) was running.",
375 "The peer system failed (or refused) to authenticate itself.",
376 "The link was established successfully and terminated because it was idle.",
377 "The link was established successfully and terminated because the connect time limit was reached.",
378 "Callback was negotiated and an incoming call should arrive shortly.",
379 "The link was terminated because the peer is not responding to echo requests.",
380 "The link was terminated by the modem hanging up.",
381 "The PPP negotiation failed because serial loopback was detected.",
382 "The init script failed (returned a non-zero exit status).",
383 "We failed to authenticate ourselves to the peer."
384 #else // sysexits(3) - https://www.freebsd.org/cgi/man.cgi?query=sysexits
385 // EX_NORMAL = EX_OK (0)
386 "Successful exit.",
387 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, // 1-9
388 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, // 10-19
389 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, // 20-29
390 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, // 30-39
391 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, // 40-49
392 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, // 50-59
393 NULL, NULL, NULL, NULL, // 60-63
394 // EX_USAGE (64)
395 "The command was used incorrectly, e.g., with the wrong number of arguments, a bad flag, a bad syntax in a parameter, or whatever.",
396 NULL, NULL, NULL, NULL, // 65-68
397 // EX_UNAVAILABLE (69)
398 "A service is unavailable. This can occur if a support program or file does not exist.",
399 // EX_ERRDEAD = EX_SOFTWARE (70)
400 "An internal software error has been detected.",
401 NULL, NULL, NULL, NULL, NULL, NULL, NULL, // 71-77
402 // EX_CONFIG (78)
403 "Something was found in an unconfigured or misconfigured state.",
404 NULL, // 79
405 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, // 80-89
406 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, // 90-98
407 NULL // EX_TERMINATE (99), PPP internal pseudo-code
408 #endif
409 };
410
pppd_terminate(struct tunnel * tunnel)411 static int pppd_terminate(struct tunnel *tunnel)
412 {
413 if (close(tunnel->pppd_pty))
414 log_warn("Could not close pppd pty (%s).\n", strerror(errno));
415
416 log_debug("Waiting for %s to exit...\n", PPP_DAEMON);
417
418 int status;
419
420 /*
421 * Errors outside of the PPP process are returned as negative integers.
422 */
423 if (waitpid(tunnel->pppd_pid, &status, 0) == -1) {
424 log_error("waitpid: %s\n", strerror(errno));
425 return -1;
426 }
427
428 /*
429 * Errors in the PPP process are returned as positive integers.
430 */
431 if (WIFEXITED(status)) {
432 int exit_status = WEXITSTATUS(status);
433
434 /*
435 * PPP exit status codes are positive integers. The way we interpret
436 * their value is not straightforward:
437 * - in the case of "normal" exit, the PPP process may return 0,
438 * but also a strictly positive integer such as 16 in the case of
439 * pppd,
440 * - in the case of failure, the PPP process will return a strictly
441 * positive integer.
442 * For now we process PPP exit status codes as follows:
443 * - exit status codes synonym of success are logged and then
444 * translated to 0 before they are returned to the calling function,
445 * - other exit status codes are considered synonyms of failure and
446 * returned to the calling function as is.
447 */
448 log_debug("waitpid: %s exit status code %d\n",
449 PPP_DAEMON, exit_status);
450 if (exit_status >= ARRAY_SIZE(ppp_message)) {
451 log_error("%s: Returned an unknown exit status code: %d\n",
452 PPP_DAEMON, exit_status);
453 } else {
454 switch (exit_status) {
455 /*
456 * PPP exit status codes considered as success
457 */
458 case 0:
459 log_debug("%s: %s\n",
460 PPP_DAEMON, ppp_message[exit_status]);
461 break;
462 #if HAVE_USR_SBIN_PPPD
463 case 16: // emitted by Ctrl+C or "kill -15"
464 if (get_sig_received() == SIGINT
465 || get_sig_received() == SIGTERM) {
466 log_info("%s: %s\n",
467 PPP_DAEMON, ppp_message[exit_status]);
468 exit_status = 0;
469 break;
470 }
471 #endif
472 /*
473 * PPP exit status codes considered as failure
474 */
475 default:
476 if (ppp_message[exit_status])
477 log_error("%s: %s\n",
478 PPP_DAEMON, ppp_message[exit_status]);
479 else
480 log_error("%s: Returned an unexpected exit status code: %d\n",
481 PPP_DAEMON, exit_status);
482 break;
483 }
484 }
485 return exit_status;
486 } else if (WIFSIGNALED(status)) {
487 int signal_number = WTERMSIG(status);
488
489 /*
490 * For now we do not consider interruption of the PPP process by
491 * a signal as a failure. Should we?
492 */
493 log_debug("waitpid: %s terminated by signal %d\n",
494 PPP_DAEMON, signal_number);
495 log_error("%s: terminated by signal: %s\n",
496 PPP_DAEMON, strsignal(signal_number));
497 }
498
499 return 0;
500 }
501
ppp_interface_is_up(struct tunnel * tunnel)502 int ppp_interface_is_up(struct tunnel *tunnel)
503 {
504 struct ifaddrs *ifap, *ifa;
505
506 log_debug("Got Address: %s\n", inet_ntoa(tunnel->ipv4.ip_addr));
507
508 if (getifaddrs(&ifap)) {
509 log_error("getifaddrs: %s\n", strerror(errno));
510 return 0;
511 }
512
513 for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) {
514 if (
515 #if HAVE_USR_SBIN_PPPD
516 ((tunnel->config->pppd_ifname &&
517 strstr(ifa->ifa_name, tunnel->config->pppd_ifname) != NULL) ||
518 strstr(ifa->ifa_name, "ppp") != NULL) &&
519 #endif
520 #if HAVE_USR_SBIN_PPP
521 strstr(ifa->ifa_name, "tun") != NULL &&
522 #endif
523 ifa->ifa_flags & IFF_UP) {
524 if (ifa->ifa_addr && ifa->ifa_addr->sa_family == AF_INET) {
525 struct in_addr if_ip_addr =
526 cast_addr(ifa->ifa_addr)->sin_addr;
527
528 log_debug("Interface Name: %s\n", ifa->ifa_name);
529 log_debug("Interface Addr: %s\n", inet_ntoa(if_ip_addr));
530
531 if (tunnel->ipv4.ip_addr.s_addr == if_ip_addr.s_addr) {
532 strncpy(tunnel->ppp_iface, ifa->ifa_name,
533 ROUTE_IFACE_LEN - 1);
534 freeifaddrs(ifap);
535 return 1;
536 }
537 }
538 }
539 }
540 freeifaddrs(ifap);
541
542 return 0;
543 }
544
get_gateway_host_ip(struct tunnel * tunnel)545 static int get_gateway_host_ip(struct tunnel *tunnel)
546 {
547 const struct addrinfo hints = { .ai_family = AF_INET };
548 struct addrinfo *result = NULL;
549
550 int ret = getaddrinfo(tunnel->config->gateway_host, NULL, &hints, &result);
551
552 if (ret) {
553 if (ret == EAI_SYSTEM)
554 log_error("getaddrinfo: %s\n", strerror(errno));
555 else
556 log_error("getaddrinfo: %s\n", gai_strerror(ret));
557 return 1;
558 }
559
560 tunnel->config->gateway_ip = ((struct sockaddr_in *)
561 result->ai_addr)->sin_addr;
562 freeaddrinfo(result);
563
564 setenv("VPN_GATEWAY", inet_ntoa(tunnel->config->gateway_ip), 0);
565
566 return 0;
567 }
568
tcp_getsockopt(int sockfd,int optname)569 static int tcp_getsockopt(int sockfd, int optname)
570 {
571 int optval;
572 socklen_t optlen = sizeof(optval);
573
574 if (getsockopt(sockfd, IPPROTO_TCP, optname,
575 (void *)&optval, &optlen))
576 return -1;
577 assert(optlen == sizeof(optval));
578 return optval;
579 }
580
581 /*
582 * Establish a regular TCP connection.
583 */
tcp_connect(struct tunnel * tunnel)584 static int tcp_connect(struct tunnel *tunnel)
585 {
586 int ret, handle;
587 struct sockaddr_in server;
588 char *env_proxy;
589 const int iface_len = strnlen(tunnel->config->iface_name, IF_NAMESIZE);
590
591 handle = socket(AF_INET, SOCK_STREAM, 0);
592
593 if (handle == -1) {
594 log_error("socket: %s\n", strerror(errno));
595 goto err_socket;
596 }
597
598 /*
599 * Attempt to find default TCP socket options on different platforms.
600 */
601 #ifdef SO_KEEPALIVE
602 ret = tcp_getsockopt(handle, SO_KEEPALIVE);
603 if (ret < 0)
604 log_warn("getsockopt: %s: %s\n", "SO_KEEPALIVE", strerror(errno));
605 else
606 log_debug("SO_KEEPALIVE: %d\n", ret);
607 #endif
608 #ifdef TCP_KEEPIDLE
609 ret = tcp_getsockopt(handle, TCP_KEEPIDLE);
610 if (ret < 0)
611 log_warn("getsockopt: %s: %s\n", "TCP_KEEPIDLE", strerror(errno));
612 else
613 log_debug("TCP_KEEPIDLE: %d\n", ret);
614 #endif
615 #ifdef TCP_KEEPALIVE
616 ret = tcp_getsockopt(handle, TCP_KEEPALIVE);
617 if (ret < 0)
618 log_warn("getsockopt: %s: %s\n", "TCP_KEEPALIVE", strerror(errno));
619 else
620 log_debug("TCP_KEEPALIVE: %d\n", ret);
621 #endif
622 #ifdef TCP_KEEPINTVL
623 ret = tcp_getsockopt(handle, TCP_KEEPINTVL);
624 if (ret < 0)
625 log_warn("getsockopt: %s: %s\n", "TCP_KEEPINTVL", strerror(errno));
626 else
627 log_debug("TCP_KEEPINTVL: %d\n", ret);
628 #endif
629 #ifdef TCP_KEEPCNT
630 ret = tcp_getsockopt(handle, TCP_KEEPCNT);
631 if (ret < 0)
632 log_warn("getsockopt: %s: %s\n", "TCP_KEEPCNT", strerror(errno));
633 else
634 log_debug("TCP_KEEPCNT: %d\n", ret);
635 #endif
636 #ifdef SO_SNDBUF
637 ret = tcp_getsockopt(handle, SO_SNDBUF);
638 if (ret < 0)
639 #ifndef __APPLE__
640 log_warn("getsockopt: %s: %s\n", "SO_SNDBUF", strerror(errno));
641 else
642 #endif
643 log_debug("SO_SNDBUF: %d\n", ret);
644 #endif
645 #ifdef SO_RCVBUF
646 ret = tcp_getsockopt(handle, SO_RCVBUF);
647 if (ret < 0)
648 #ifndef __APPLE__
649 log_warn("getsockopt: %s: %s\n", "SO_RCVBUF", strerror(errno));
650 else
651 #endif
652 log_debug("SO_RCVBUF: %d\n", ret);
653 #endif
654
655 if (iface_len == IF_NAMESIZE) {
656 log_error("socket: Too long iface name\n");
657 goto err_post_socket;
658 }
659 if (iface_len > 0) {
660 #if HAVE_SO_BINDTODEVICE
661 ret = setsockopt(handle, SOL_SOCKET, SO_BINDTODEVICE,
662 tunnel->config->iface_name, iface_len);
663 #else
664 struct ifreq ifr;
665
666 memset(&ifr, 0, sizeof(ifr));
667 if (strlcpy(ifr.ifr_name, tunnel->config->iface_name, IF_NAMESIZE)
668 >= IF_NAMESIZE) {
669 log_error("interface name too long\n");
670 goto err_post_socket;
671 }
672 ifr.ifr_addr.sa_family = AF_INET;
673 if (ioctl(handle, SIOCGIFADDR, &ifr) == -1) {
674 log_error("ioctl(%d,SIOCGIFADDR,\"%s\") failed\n", handle,
675 ifr.ifr_name);
676 goto err_post_socket;
677 }
678 ret = bind(handle, &ifr.ifr_addr, ifr.ifr_addr.sa_len);
679 #endif
680 if (ret) {
681 log_error("socket: setting interface name failed with error: %d\n",
682 errno);
683 goto err_post_socket;
684 }
685 }
686
687 env_proxy = getenv("https_proxy");
688 if (env_proxy == NULL)
689 env_proxy = getenv("HTTPS_PROXY");
690 if (env_proxy == NULL)
691 env_proxy = getenv("all_proxy");
692 if (env_proxy == NULL)
693 env_proxy = getenv("ALL_PROXY");
694 if (env_proxy != NULL) {
695 char *proxy_host, *proxy_port;
696 // protect the original environment from modifications
697 env_proxy = strdup(env_proxy);
698 if (env_proxy == NULL) {
699 log_error("strdup: %s\n", strerror(errno));
700 goto err_strdup;
701 }
702 // get rid of a trailing slash
703 if (*env_proxy && env_proxy[strlen(env_proxy) - 1] == '/')
704 env_proxy[strlen(env_proxy) - 1] = '\0';
705 // get rid of a http(s):// prefix in env_proxy
706 proxy_host = strstr(env_proxy, "://");
707 if (proxy_host == NULL)
708 proxy_host = env_proxy;
709 else
710 proxy_host += 3;
711 // split host and port
712 proxy_port = strchr(proxy_host, ':');
713 if (proxy_port != NULL) {
714 proxy_port[0] = '\0';
715 proxy_port++;
716 server.sin_port = htons(strtoul(proxy_port, NULL, 10));
717 } else {
718 server.sin_port = htons(tunnel->config->gateway_port);
719 }
720 // get rid of a trailing slash
721 if (*proxy_host && proxy_host[strlen(proxy_host) - 1] == '/')
722 proxy_host[strlen(proxy_host) - 1] = '\0';
723 log_debug("proxy_host: %s\n", proxy_host);
724 log_debug("proxy_port: %s\n", proxy_port);
725 server.sin_addr.s_addr = inet_addr(proxy_host);
726 // if host is given as a FQDN we have to do a DNS lookup
727 if (server.sin_addr.s_addr == INADDR_NONE) {
728 const struct addrinfo hints = { .ai_family = AF_INET };
729 struct addrinfo *result = NULL;
730
731 ret = getaddrinfo(proxy_host, NULL, &hints, &result);
732 if (ret) {
733 if (ret == EAI_SYSTEM)
734 log_error("getaddrinfo: %s\n", strerror(errno));
735 else
736 log_error("getaddrinfo: %s\n", gai_strerror(ret));
737 goto err_connect;
738 }
739
740 server.sin_addr = ((struct sockaddr_in *)
741 result->ai_addr)->sin_addr;
742 freeaddrinfo(result);
743 }
744 } else {
745 server.sin_port = htons(tunnel->config->gateway_port);
746 server.sin_addr = tunnel->config->gateway_ip;
747 }
748
749 log_debug("server_addr: %s\n", inet_ntoa(server.sin_addr));
750 log_debug("server_port: %u\n", ntohs(server.sin_port));
751 server.sin_family = AF_INET;
752 memset(&(server.sin_zero), '\0', 8);
753 log_debug("gateway_addr: %s\n", inet_ntoa(tunnel->config->gateway_ip));
754 log_debug("gateway_port: %u\n", tunnel->config->gateway_port);
755
756 ret = connect(handle, (struct sockaddr *) &server, sizeof(server));
757 if (ret) {
758 log_error("connect: %s\n", strerror(errno));
759 goto err_connect;
760 }
761
762 if (env_proxy != NULL) {
763 char request[128];
764
765 // https://tools.ietf.org/html/rfc7231#section-4.3.6
766 sprintf(request, "CONNECT %s:%u HTTP/1.1\r\nHost: %s:%u\r\n\r\n",
767 inet_ntoa(tunnel->config->gateway_ip),
768 tunnel->config->gateway_port,
769 inet_ntoa(tunnel->config->gateway_ip),
770 tunnel->config->gateway_port);
771
772 ssize_t bytes_written = write(handle, request, strlen(request));
773
774 if (bytes_written != strlen(request)) {
775 log_error("write error while talking to proxy: %s\n",
776 strerror(errno));
777 goto err_connect;
778 }
779
780 // wait for a "200 OK" reply from the proxy,
781 // be careful not to fetch too many bytes at once
782 const char *response = NULL;
783
784 memset(&(request), '\0', sizeof(request));
785 for (int j = 0; response == NULL; j++) {
786 if (j >= ARRAY_SIZE(request) - 1) {
787 log_error("Proxy response is unexpectedly large and cannot fit in the %lu-bytes buffer.\n",
788 ARRAY_SIZE(request));
789 goto err_proxy_response;
790 }
791
792 ssize_t bytes_read = read(handle, &(request[j]), 1);
793 static const char HTTP_STATUS_200[] = "200";
794
795 // we have reached the end of the data sent by the proxy
796 // and have not seen HTTP status code 200
797 if (bytes_read < 1) {
798 log_error("Proxy response does not contain \"%s\" as expected.\n",
799 HTTP_STATUS_200);
800 goto err_proxy_response;
801 }
802
803 // detect "200"
804 response = strstr(request, HTTP_STATUS_200);
805
806 // detect end-of-line after "200"
807 if (response != NULL) {
808 /*
809 * RFC 2616 states in section 2.2 Basic Rules:
810 * CR = <US-ASCII CR, carriage return (13)>
811 * LF = <US-ASCII LF, linefeed (10)>
812 * HTTP/1.1 defines the sequence CR LF as the
813 * end-of-line marker for all protocol elements
814 * except the entity-body (see appendix 19.3
815 * for tolerant applications).
816 * CRLF = CR LF
817 *
818 * RFC 2616 states in section 19.3 Tolerant Applications:
819 * The line terminator for message-header fields
820 * is the sequence CRLF. However, we recommend
821 * that applications, when parsing such headers,
822 * recognize a single LF as a line terminator
823 * and ignore the leading CR.
824 */
825 static const char *const HTTP_EOL[] = {
826 "\r\n\r\n",
827 "\n\n"
828 };
829 const char *eol = NULL;
830
831 for (int i = 0; (i < ARRAY_SIZE(HTTP_EOL)) &&
832 (eol == NULL); i++)
833 eol = strstr(response, HTTP_EOL[i]);
834 response = eol;
835 }
836 }
837
838 free(env_proxy); // release memory allocated by strdup()
839 }
840
841 return handle;
842
843 err_proxy_response:
844 err_connect:
845 free(env_proxy); // release memory allocated by strdup()
846 err_strdup:
847 err_post_socket:
848 if (close(handle))
849 log_warn("Could not close socket (%s).\n", strerror(errno));
850 err_socket:
851 return -1;
852 }
853
ssl_verify_cert(struct tunnel * tunnel)854 static int ssl_verify_cert(struct tunnel *tunnel)
855 {
856 int ret = -1;
857 int cert_valid = 0;
858 unsigned char digest[SHA256LEN];
859 unsigned int len;
860 struct x509_digest *elem;
861 char digest_str[SHA256STRLEN], *subject, *issuer;
862 char *line;
863 int i;
864 X509_NAME *subj;
865 char *saveptr = NULL;
866
867 SSL_set_verify(tunnel->ssl_handle, SSL_VERIFY_PEER, NULL);
868
869 X509 *cert = SSL_get_peer_certificate(tunnel->ssl_handle);
870
871 if (cert == NULL) {
872 log_error("Unable to get gateway certificate.\n");
873 return 1;
874 }
875
876 subj = X509_get_subject_name(cert);
877
878 #ifdef HAVE_X509_CHECK_HOST
879 // Use OpenSSL native host validation if v >= 1.0.2.
880 // compare against gateway_host and correctly check return value
881 // to fix prior incorrect use of X509_check_host
882 if (X509_check_host(cert, tunnel->config->gateway_host,
883 0, 0, NULL) == 1)
884 cert_valid = 1;
885 #else
886 // Use validate_hostname form iSECPartners if native validation not available
887 // in order to avoid TLS Certificate CommonName NULL Byte Vulnerability
888 if (validate_hostname(tunnel->config->gateway_host, cert) == MatchFound)
889 cert_valid = 1;
890 #endif
891
892 // Try to validate certificate using local PKI
893 if (cert_valid
894 && SSL_get_verify_result(tunnel->ssl_handle) == X509_V_OK) {
895 log_debug("Gateway certificate validation succeeded.\n");
896 ret = 0;
897 goto free_cert;
898 }
899 log_debug("Gateway certificate validation failed.\n");
900
901 // If validation failed, check if cert is in the white list
902 if (X509_digest(cert, EVP_sha256(), digest, &len) <= 0
903 || len != SHA256LEN) {
904 log_error("Could not compute certificate sha256 digest.\n");
905 goto free_cert;
906 }
907 // Encode digest in base16
908 for (i = 0; i < SHA256LEN; i++)
909 sprintf(&digest_str[2 * i], "%02x", digest[i]);
910 digest_str[SHA256STRLEN - 1] = '\0';
911 // Is it in whitelist?
912 for (elem = tunnel->config->cert_whitelist; elem != NULL;
913 elem = elem->next)
914 if (memcmp(digest_str, elem->data, SHA256STRLEN - 1) == 0)
915 break;
916 if (elem != NULL) { // break before end of loop
917 log_debug("Gateway certificate digest found in white list.\n");
918 ret = 0;
919 goto free_cert;
920 }
921
922 log_error("Gateway certificate validation failed, and the certificate digest is not in the local whitelist. If you trust it, rerun with:\n");
923 log_error(" --trusted-cert %s\n", digest_str);
924 log_error("or add this line to your configuration file:\n");
925 log_error(" trusted-cert = %s\n", digest_str);
926 log_error("Gateway certificate:\n");
927 log_error(" subject:\n");
928 subject = X509_NAME_oneline(subj, NULL, 0);
929 if (subject) {
930 for (line = strtok_r(subject, "/", &saveptr); line != NULL;
931 line = strtok_r(NULL, "/", &saveptr))
932 log_error(" %s\n", line);
933 free(subject);
934 }
935 log_error(" issuer:\n");
936 issuer = X509_NAME_oneline(X509_get_issuer_name(cert), NULL, 0);
937 if (issuer) {
938 for (line = strtok_r(issuer, "/", &saveptr); line != NULL;
939 line = strtok_r(NULL, "/", &saveptr))
940 log_error(" %s\n", line);
941 free(issuer);
942 }
943 log_error(" sha256 digest:\n");
944 log_error(" %s\n", digest_str);
945
946 free_cert:
947 X509_free(cert);
948 return ret;
949 }
950
951 /*
952 * Destroy and free the SSL connection to the gateway.
953 */
ssl_disconnect(struct tunnel * tunnel)954 static void ssl_disconnect(struct tunnel *tunnel)
955 {
956 if (!tunnel->ssl_handle)
957 return;
958
959 SSL_shutdown(tunnel->ssl_handle);
960 SSL_free(tunnel->ssl_handle);
961 tunnel->ssl_handle = NULL;
962
963 SSL_CTX_free(tunnel->ssl_context);
964 tunnel->ssl_context = NULL;
965
966 if (close(tunnel->ssl_socket))
967 log_warn("Could not close ssl socket (%s).\n", strerror(errno));
968 tunnel->ssl_socket = -1;
969 }
970
971 /*
972 * Query for the pass phrase used for encrypted PEM structures
973 * (normally only private keys).
974 */
pem_passphrase_cb(char * buf,int size,int rwflag,void * u)975 static int pem_passphrase_cb(char *buf, int size, int rwflag, void *u)
976 {
977 struct vpn_config *cfg = (struct vpn_config *)u;
978
979 /* We expect to only read PEM pass phrases, not write them. */
980 if (rwflag == 0) {
981 if (!cfg->pem_passphrase_set) {
982 if (size > PEM_PASSPHRASE_SIZE) {
983 read_password(NULL, NULL,
984 "Enter PEM pass phrase: ",
985 cfg->pem_passphrase,
986 PEM_PASSPHRASE_SIZE + 1);
987 cfg->pem_passphrase_set = 1;
988 } else {
989 log_error("Buffer too small for PEM pass phrase: %d.",
990 size);
991 }
992 }
993 if (cfg->pem_passphrase_set) {
994 assert(strlen(cfg->pem_passphrase) < size);
995 strncpy(buf, cfg->pem_passphrase, size);
996 buf[size - 1] = '\0';
997 return strlen(buf);
998 }
999 } else {
1000 log_error("We refuse to write PEM pass phrases!");
1001 }
1002
1003 return -1;
1004 }
1005
1006 /*
1007 * Connects to the gateway and initiate an SSL session.
1008 */
ssl_connect(struct tunnel * tunnel)1009 int ssl_connect(struct tunnel *tunnel)
1010 {
1011 ssl_disconnect(tunnel);
1012
1013 tunnel->ssl_socket = tcp_connect(tunnel);
1014 if (tunnel->ssl_socket == -1)
1015 goto err_tcp_connect;
1016
1017 // https://wiki.openssl.org/index.php/Library_Initialization
1018 #if OPENSSL_VERSION_NUMBER < 0x10100000L
1019 // Register the error strings for libcrypto & libssl
1020 SSL_load_error_strings();
1021 // Register the available ciphers and digests
1022 SSL_library_init();
1023
1024 tunnel->ssl_context = SSL_CTX_new(SSLv23_client_method());
1025 #else
1026 tunnel->ssl_context = SSL_CTX_new(TLS_client_method());
1027 #endif
1028 if (tunnel->ssl_context == NULL) {
1029 log_error("SSL_CTX_new: %s\n",
1030 ERR_error_string(ERR_peek_last_error(), NULL));
1031 goto err_ssl_socket;
1032 }
1033
1034 /* Load the OS default CA files */
1035 if (!SSL_CTX_set_default_verify_paths(tunnel->ssl_context))
1036 log_error("Could not load OS OpenSSL files.\n");
1037
1038 if (tunnel->config->ca_file) {
1039 if (!SSL_CTX_load_verify_locations(tunnel->ssl_context,
1040 tunnel->config->ca_file, NULL)) {
1041 log_error("SSL_CTX_load_verify_locations: %s\n",
1042 ERR_error_string(ERR_peek_last_error(), NULL));
1043 goto err_ssl_context;
1044 }
1045 }
1046
1047 /* Disable vulnerable TLS protocols and ciphers by default*/
1048 if (!tunnel->config->cipher_list) {
1049 if (!tunnel->config->insecure_ssl) {
1050 const char *cipher_list;
1051
1052 if (tunnel->config->seclevel_1)
1053 cipher_list = "HIGH:!aNULL:!kRSA:!PSK:!SRP:!MD5:!RC4@SECLEVEL=1";
1054 else
1055 cipher_list = "HIGH:!aNULL:!kRSA:!PSK:!SRP:!MD5:!RC4";
1056 tunnel->config->cipher_list = strdup(cipher_list);
1057 } else if (tunnel->config->seclevel_1) {
1058 const char *cipher_list = "DEFAULT@SECLEVEL=1";
1059
1060 tunnel->config->cipher_list = strdup(cipher_list);
1061 }
1062 }
1063
1064 /* Set the password callback for PEM certificates with encryption. */
1065 SSL_CTX_set_default_passwd_cb(tunnel->ssl_context, &pem_passphrase_cb);
1066 SSL_CTX_set_default_passwd_cb_userdata(tunnel->ssl_context, tunnel->config);
1067
1068 if (tunnel->config->cipher_list) {
1069 log_debug("Setting cipher list to: %s\n", tunnel->config->cipher_list);
1070 if (!SSL_CTX_set_cipher_list(tunnel->ssl_context,
1071 tunnel->config->cipher_list)) {
1072 log_error("SSL_CTX_set_cipher_list failed: %s\n",
1073 ERR_error_string(ERR_peek_last_error(), NULL));
1074 goto err_ssl_context;
1075 }
1076 }
1077
1078 #if OPENSSL_VERSION_NUMBER >= 0x10100000L
1079 if (tunnel->config->min_tls > 0) {
1080 log_debug("Setting minimum protocol version to: 0x%x.\n",
1081 tunnel->config->min_tls);
1082 if (!SSL_CTX_set_min_proto_version(tunnel->ssl_context,
1083 tunnel->config->min_tls)) {
1084 log_error("Cannot set minimum protocol version (%s).\n",
1085 ERR_error_string(ERR_peek_last_error(), NULL));
1086 goto err_ssl_context;
1087 }
1088 }
1089 #else
1090 if (!tunnel->config->insecure_ssl || tunnel->config->min_tls > 0) {
1091 long sslctxopt = 0;
1092 long checkopt;
1093
1094 if (!tunnel->config->insecure_ssl)
1095 sslctxopt |= SSL_OP_NO_SSLv3 | SSL_OP_NO_COMPRESSION;
1096 #ifdef TLS1_VERSION
1097 if (tunnel->config->min_tls > TLS1_VERSION)
1098 sslctxopt |= SSL_OP_NO_TLSv1;
1099 #endif
1100 #ifdef TLS1_1_VERSION
1101 if (tunnel->config->min_tls > TLS1_1_VERSION)
1102 sslctxopt |= SSL_OP_NO_TLSv1_1;
1103 #endif
1104 #ifdef TLS1_2_VERSION
1105 if (tunnel->config->min_tls > TLS1_2_VERSION)
1106 sslctxopt |= SSL_OP_NO_TLSv1_2;
1107 #endif
1108 checkopt = SSL_CTX_set_options(tunnel->ssl_context, sslctxopt);
1109 if ((checkopt & sslctxopt) != sslctxopt) {
1110 log_error("SSL_CTX_set_options didn't set opt: %s\n",
1111 ERR_error_string(ERR_peek_last_error(), NULL));
1112 goto err_ssl_context;
1113 }
1114 }
1115 #endif
1116
1117 /* Use engine for PIV if user-cert config starts with pkcs11 URI: */
1118 #ifndef OPENSSL_NO_ENGINE
1119 if (tunnel->config->use_engine > 0) {
1120 ENGINE *e;
1121
1122 ENGINE_load_builtin_engines();
1123 e = ENGINE_by_id("pkcs11");
1124 if (!e) {
1125 log_error("Could not load pkcs11 Engine: %s\n",
1126 ERR_error_string(ERR_peek_last_error(), NULL));
1127 goto err_ssl_context;
1128 }
1129 if (!ENGINE_init(e)) {
1130 log_error("Could not init pkcs11 Engine: %s\n",
1131 ERR_error_string(ERR_peek_last_error(), NULL));
1132 ENGINE_free(e);
1133 goto err_ssl_context;
1134 }
1135 if (!ENGINE_set_default_RSA(e))
1136 abort();
1137
1138 ENGINE_finish(e);
1139 ENGINE_free(e);
1140
1141 struct token parms;
1142
1143 parms.uri = tunnel->config->user_cert;
1144 parms.cert = NULL;
1145
1146 if (!ENGINE_ctrl_cmd(e, "LOAD_CERT_CTRL", 0, &parms, NULL, 1)) {
1147 log_error("PKCS11 ENGINE_ctrl_cmd: %s\n",
1148 ERR_error_string(ERR_peek_last_error(), NULL));
1149 goto err_ssl_context;
1150 }
1151
1152 if (!SSL_CTX_use_certificate(tunnel->ssl_context, parms.cert)) {
1153 log_error("PKCS11 SSL_CTX_use_certificate: %s\n",
1154 ERR_error_string(ERR_peek_last_error(), NULL));
1155 goto err_ssl_context;
1156 }
1157
1158 EVP_PKEY * privkey = ENGINE_load_private_key(
1159 e, parms.uri, UI_OpenSSL(), NULL);
1160 if (!privkey) {
1161 log_error("PKCS11 ENGINE_load_private_key: %s\n",
1162 ERR_error_string(ERR_peek_last_error(), NULL));
1163 goto err_ssl_context;
1164 }
1165
1166 if (!SSL_CTX_use_PrivateKey(tunnel->ssl_context, privkey)) {
1167 log_error("PKCS11 SSL_CTX_use_PrivateKey_file: %s\n",
1168 ERR_error_string(ERR_peek_last_error(), NULL));
1169 goto err_ssl_context;
1170 }
1171
1172 if (!SSL_CTX_check_private_key(tunnel->ssl_context)) {
1173 log_error("PKCS11 SSL_CTX_check_private_key: %s\n",
1174 ERR_error_string(ERR_peek_last_error(), NULL));
1175 goto err_ssl_context;
1176 }
1177
1178 } else { /* end PKCS11-engine */
1179 #endif
1180
1181 if (tunnel->config->user_cert) {
1182 if (!SSL_CTX_use_certificate_chain_file(
1183 tunnel->ssl_context, tunnel->config->user_cert)) {
1184 log_error("SSL_CTX_use_certificate_chain_file: %s\n",
1185 ERR_error_string(ERR_peek_last_error(), NULL));
1186 goto err_ssl_context;
1187 }
1188 }
1189
1190 if (tunnel->config->user_key) {
1191 if (!SSL_CTX_use_PrivateKey_file(tunnel->ssl_context,
1192 tunnel->config->user_key,
1193 SSL_FILETYPE_PEM)) {
1194 log_error("SSL_CTX_use_PrivateKey_file: %s\n",
1195 ERR_error_string(ERR_peek_last_error(), NULL));
1196 goto err_ssl_context;
1197 }
1198 }
1199
1200 if (tunnel->config->user_cert && tunnel->config->user_key) {
1201 if (!SSL_CTX_check_private_key(tunnel->ssl_context)) {
1202 log_error("SSL_CTX_check_private_key: %s\n",
1203 ERR_error_string(ERR_peek_last_error(), NULL));
1204 goto err_ssl_context;
1205 }
1206 }
1207 #ifndef OPENSSL_NO_ENGINE
1208 }
1209 #endif
1210
1211 tunnel->ssl_handle = SSL_new(tunnel->ssl_context);
1212 if (tunnel->ssl_handle == NULL) {
1213 log_error("SSL_new: %s\n",
1214 ERR_error_string(ERR_peek_last_error(), NULL));
1215 goto err_ssl_context;
1216 }
1217
1218 if (!SSL_set_fd(tunnel->ssl_handle, tunnel->ssl_socket)) {
1219 log_error("SSL_set_fd: %s\n",
1220 ERR_error_string(ERR_peek_last_error(), NULL));
1221 goto err_ssl_handle;
1222 }
1223 SSL_set_mode(tunnel->ssl_handle, SSL_MODE_AUTO_RETRY);
1224
1225 // Initiate SSL handshake
1226 if (SSL_connect(tunnel->ssl_handle) != 1) {
1227 log_error("SSL_connect: %s\n"
1228 "You might want to try --insecure-ssl or specify a different --cipher-list\n",
1229 ERR_error_string(ERR_peek_last_error(), NULL));
1230 goto err_ssl_handle;
1231 }
1232 SSL_set_mode(tunnel->ssl_handle, SSL_MODE_AUTO_RETRY);
1233
1234 if (ssl_verify_cert(tunnel))
1235 goto err_ssl_handle;
1236
1237 // Disable SIGPIPE (occurs when trying to write to an already-closed
1238 // socket).
1239 signal(SIGPIPE, SIG_IGN);
1240
1241 return 0;
1242
1243 err_ssl_handle:
1244 SSL_shutdown(tunnel->ssl_handle);
1245 SSL_free(tunnel->ssl_handle);
1246 tunnel->ssl_handle = NULL;
1247 err_ssl_context:
1248 SSL_CTX_free(tunnel->ssl_context);
1249 tunnel->ssl_context = NULL;
1250 err_ssl_socket:
1251 if (close(tunnel->ssl_socket))
1252 log_warn("Could not close ssl socket (%s).\n", strerror(errno));
1253 tunnel->ssl_socket = -1;
1254 err_tcp_connect:
1255 return 1;
1256 }
1257
run_tunnel(struct vpn_config * config)1258 int run_tunnel(struct vpn_config *config)
1259 {
1260 int ret;
1261 struct tunnel tunnel = {
1262 .config = config,
1263 .state = STATE_DOWN,
1264 .ssl_socket = -1,
1265 .ssl_context = NULL,
1266 .ssl_handle = NULL,
1267 .ipv4.ns1_addr.s_addr = 0,
1268 .ipv4.ns2_addr.s_addr = 0,
1269 .ipv4.dns_suffix = NULL,
1270 .on_ppp_if_up = on_ppp_if_up,
1271 .on_ppp_if_down = on_ppp_if_down
1272 };
1273
1274 // Step 0: get gateway host IP
1275 log_debug("Resolving gateway host ip\n");
1276 ret = get_gateway_host_ip(&tunnel);
1277 if (ret)
1278 goto err_tunnel;
1279
1280 // Step 1: open a SSL connection to the gateway
1281 log_debug("Establishing ssl connection\n");
1282 ret = ssl_connect(&tunnel);
1283 if (ret)
1284 goto err_tunnel;
1285 log_info("Connected to gateway.\n");
1286
1287 // Step 2: connect to the HTTP interface and authenticate to get a
1288 // cookie
1289 ret = auth_log_in(&tunnel);
1290 if (ret != 1) {
1291 log_error("Could not authenticate to gateway. Please check the password, client certificate, etc.\n");
1292 log_debug("%s (%d)\n", err_http_str(ret), ret);
1293 ret = 1;
1294 goto err_tunnel;
1295 }
1296 log_info("Authenticated.\n");
1297 log_debug("Cookie: %s\n", tunnel.cookie);
1298
1299 ret = auth_request_vpn_allocation(&tunnel);
1300 if (ret != 1) {
1301 log_error("VPN allocation request failed (%s).\n",
1302 err_http_str(ret));
1303 ret = 1;
1304 goto err_tunnel;
1305 }
1306 log_info("Remote gateway has allocated a VPN.\n");
1307
1308 ret = ssl_connect(&tunnel);
1309 if (ret)
1310 goto err_tunnel;
1311
1312 // Step 3: get configuration
1313 log_debug("Retrieving configuration\n");
1314 ret = auth_get_config(&tunnel);
1315 if (ret != 1) {
1316 log_error("Could not get VPN configuration (%s).\n",
1317 err_http_str(ret));
1318 ret = 1;
1319 goto err_tunnel;
1320 }
1321
1322 // Step 4: run a pppd process
1323 log_debug("Establishing the tunnel\n");
1324 ret = pppd_run(&tunnel);
1325 if (ret)
1326 goto err_tunnel;
1327
1328 // Step 5: ask gateway to start tunneling
1329 log_debug("Switch to tunneling mode\n");
1330 ret = http_send(&tunnel,
1331 "GET /remote/sslvpn-tunnel HTTP/1.1\r\n"
1332 "Host: sslvpn\r\n"
1333 "Cookie: %s\r\n\r\n",
1334 tunnel.cookie);
1335 if (ret != 1) {
1336 log_error("Could not start tunnel (%s).\n", err_http_str(ret));
1337 goto err_start_tunnel;
1338 }
1339
1340 tunnel.state = STATE_CONNECTING;
1341
1342 // Step 6: perform io between pppd and the gateway, while tunnel is up
1343 log_debug("Starting IO through the tunnel\n");
1344 io_loop(&tunnel);
1345
1346 log_debug("disconnecting\n");
1347 if (tunnel.state == STATE_UP)
1348 if (tunnel.on_ppp_if_down != NULL)
1349 tunnel.on_ppp_if_down(&tunnel);
1350
1351 tunnel.state = STATE_DISCONNECTING;
1352
1353 err_start_tunnel:
1354 ret = pppd_terminate(&tunnel);
1355 log_info("Terminated %s.\n", PPP_DAEMON);
1356 err_tunnel:
1357 log_info("Closed connection to gateway.\n");
1358 tunnel.state = STATE_DOWN;
1359
1360 if (ssl_connect(&tunnel)) {
1361 log_info("Could not log out.\n");
1362 } else {
1363 auth_log_out(&tunnel);
1364 log_info("Logged out.\n");
1365 }
1366
1367 // explicitly free the buffer allocated for split routes of the ipv4 configuration
1368 if (tunnel.ipv4.split_rt != NULL) {
1369 free(tunnel.ipv4.split_rt);
1370 tunnel.ipv4.split_rt = NULL;
1371 }
1372 return ret;
1373 }
1374