1 /*
2  * OpenConnect (SSL + DTLS) VPN client
3  *
4  * Copyright © 2008-2015 Intel Corporation.
5  *
6  * Author: David Woodhouse <dwmw2@infradead.org>
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public License
10  * version 2.1, as published by the Free Software Foundation.
11  *
12  * This program is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  */
17 
18 #include <config.h>
19 
20 #include <errno.h>
21 #include <limits.h>
22 #include <stdlib.h>
23 #include <unistd.h>
24 #include <string.h>
25 #ifndef _WIN32
26 /* for setgroups() */
27 # include <sys/types.h>
28 # include <grp.h>
29 #endif
30 
31 #include "openconnect-internal.h"
32 
queue_new_packet(struct pkt_q * q,void * buf,int len)33 int queue_new_packet(struct pkt_q *q, void *buf, int len)
34 {
35 	struct pkt *new = malloc(sizeof(struct pkt) + len);
36 	if (!new)
37 		return -ENOMEM;
38 
39 	new->len = len;
40 	new->next = NULL;
41 	memcpy(new->data, buf, len);
42 	queue_packet(q, new);
43 	return 0;
44 }
45 
46 /* This is here because it's generic and hence can't live in either of the
47    tun*.c files for specific platforms */
tun_mainloop(struct openconnect_info * vpninfo,int * timeout,int readable)48 int tun_mainloop(struct openconnect_info *vpninfo, int *timeout, int readable)
49 {
50 	struct pkt *this;
51 	int work_done = 0;
52 
53 	if (!tun_is_up(vpninfo)) {
54 		/* no tun yet; clear any queued packets */
55 		while ((this = dequeue_packet(&vpninfo->incoming_queue)))
56 			free(this);
57 
58 		return 0;
59 	}
60 
61 	if (readable && read_fd_monitored(vpninfo, tun)) {
62 		struct pkt *out_pkt = vpninfo->tun_pkt;
63 		while (1) {
64 			int len = vpninfo->ip_info.mtu;
65 
66 			if (!out_pkt) {
67 				out_pkt = malloc(sizeof(struct pkt) + len + vpninfo->pkt_trailer);
68 				if (!out_pkt) {
69 					vpn_progress(vpninfo, PRG_ERR, _("Allocation failed\n"));
70 					break;
71 				}
72 				out_pkt->len = len;
73 			}
74 
75 			if (os_read_tun(vpninfo, out_pkt))
76 				break;
77 
78 			vpninfo->stats.tx_pkts++;
79 			vpninfo->stats.tx_bytes += out_pkt->len;
80 			work_done = 1;
81 
82 			if (queue_packet(&vpninfo->outgoing_queue, out_pkt) +
83 			    vpninfo->oncp_control_queue.count >= vpninfo->max_qlen) {
84 				out_pkt = NULL;
85 				unmonitor_read_fd(vpninfo, tun);
86 				break;
87 			}
88 			out_pkt = NULL;
89 		}
90 		vpninfo->tun_pkt = out_pkt;
91 	} else if (vpninfo->outgoing_queue.count + vpninfo->oncp_control_queue.count < vpninfo->max_qlen) {
92 		monitor_read_fd(vpninfo, tun);
93 	}
94 
95 	while ((this = dequeue_packet(&vpninfo->incoming_queue))) {
96 
97 		unmonitor_write_fd(vpninfo, tun);
98 
99 		if (os_write_tun(vpninfo, this)) {
100 			requeue_packet(&vpninfo->incoming_queue, this);
101 			break;
102 		}
103 
104 		vpninfo->stats.rx_pkts++;
105 		vpninfo->stats.rx_bytes += this->len;
106 
107 		free(this);
108 	}
109 	/* Work is not done if we just got rid of packets off the queue */
110 	return work_done;
111 }
112 
setup_tun_device(struct openconnect_info * vpninfo)113 static int setup_tun_device(struct openconnect_info *vpninfo)
114 {
115 	int ret;
116 
117 	if (vpninfo->setup_tun) {
118 		vpninfo->setup_tun(vpninfo->cbdata);
119 		if (tun_is_up(vpninfo))
120 			return 0;
121 	}
122 
123 #ifndef _WIN32
124 	if (vpninfo->use_tun_script) {
125 		ret = openconnect_setup_tun_script(vpninfo, vpninfo->vpnc_script);
126 		if (ret) {
127 			fprintf(stderr, _("Set up tun script failed\n"));
128 			return ret;
129 		}
130 	} else
131 #endif
132 	ret = openconnect_setup_tun_device(vpninfo, vpninfo->vpnc_script, vpninfo->ifname);
133 	if (ret) {
134 		fprintf(stderr, _("Set up tun device failed\n"));
135 		return ret;
136 	}
137 
138 #if !defined(_WIN32) && !defined(__native_client__)
139 	if (vpninfo->uid != getuid()) {
140 		int e;
141 
142 		if (setgid(vpninfo->gid)) {
143 			e = errno;
144 			fprintf(stderr, _("Failed to set gid %ld: %s\n"),
145 				(long)vpninfo->gid, strerror(e));
146 			return -EPERM;
147 		}
148 
149 		if (setgroups(1, &vpninfo->gid)) {
150 			e = errno;
151 			fprintf(stderr, _("Failed to set groups to %ld: %s\n"),
152 				(long)vpninfo->gid, strerror(e));
153 			return -EPERM;
154 		}
155 
156 		if (setuid(vpninfo->uid)) {
157 			e = errno;
158 			fprintf(stderr, _("Failed to set uid %ld: %s\n"),
159 				(long)vpninfo->uid, strerror(e));
160 			return -EPERM;
161 		}
162 	}
163 #endif
164 	return 0;
165 }
166 
167 /* Return value:
168  *  = 0, when successfully paused (may call again)
169  *  = -EINTR, if aborted locally via OC_CMD_CANCEL
170  *  = -ECONNABORTED, if aborted locally via OC_CMD_DETACH
171  *  = -EPIPE, if the remote end explicitly terminated the session
172  *  = -EPERM, if the gateway sent 401 Unauthorized (cookie expired)
173  *  < 0, for any other error
174  */
openconnect_mainloop(struct openconnect_info * vpninfo,int reconnect_timeout,int reconnect_interval)175 int openconnect_mainloop(struct openconnect_info *vpninfo,
176 			 int reconnect_timeout,
177 			 int reconnect_interval)
178 {
179 	int ret = 0;
180 	int tun_r = 1, udp_r = 1, tcp_r = 1;
181 	vpninfo->reconnect_timeout = reconnect_timeout;
182 	vpninfo->reconnect_interval = reconnect_interval;
183 
184 	if (vpninfo->cmd_fd != -1) {
185 		monitor_fd_new(vpninfo, cmd);
186 		monitor_read_fd(vpninfo, cmd);
187 	}
188 
189 	while (!vpninfo->quit_reason) {
190 		int did_work = 0;
191 		int timeout;
192 #ifdef _WIN32
193 		HANDLE events[4];
194 		int nr_events = 0;
195 #else
196 		struct timeval tv;
197 		fd_set rfds, wfds, efds;
198 #endif
199 
200 		/* If tun is not up, loop more often to detect
201 		 * a DTLS timeout (due to a firewall block) as soon. */
202 		if (tun_is_up(vpninfo))
203 			timeout = INT_MAX;
204 		else
205 			timeout = 1000;
206 
207 		if (vpninfo->dtls_state > DTLS_DISABLED) {
208 			/* Postpone tun device creation after DTLS is connected so
209 			 * we have a better knowledge of the link MTU. We also
210 			 * force the creation if DTLS enters sleeping mode - i.e.,
211 			 * we failed to connect on time. */
212 			if (!tun_is_up(vpninfo) && (vpninfo->dtls_state == DTLS_CONNECTED ||
213 			    vpninfo->dtls_state == DTLS_SLEEPING)) {
214 				ret = setup_tun_device(vpninfo);
215 				if (ret) {
216 					break;
217 				}
218 			}
219 
220 			ret = vpninfo->proto->udp_mainloop(vpninfo, &timeout, udp_r);
221 			if (vpninfo->quit_reason)
222 				break;
223 			did_work += ret;
224 
225 		} else if (!tun_is_up(vpninfo)) {
226 			/* No DTLS - setup TUN device unconditionally */
227 			ret = setup_tun_device(vpninfo);
228 			if (ret)
229 				break;
230 		}
231 
232 		ret = vpninfo->proto->tcp_mainloop(vpninfo, &timeout, tcp_r);
233 		if (vpninfo->quit_reason)
234 			break;
235 		did_work += ret;
236 
237 		/* Tun must be last because it will set/clear its bit
238 		   in the select_rfds according to the queue length */
239 		did_work += tun_mainloop(vpninfo, &timeout, tun_r);
240 		if (vpninfo->quit_reason)
241 			break;
242 
243 		poll_cmd_fd(vpninfo, 0);
244 		if (vpninfo->got_cancel_cmd) {
245 			if (vpninfo->cancel_type == OC_CMD_CANCEL) {
246 				vpninfo->quit_reason = "Aborted by caller";
247 				ret = -EINTR;
248 			} else {
249 				ret = -ECONNABORTED;
250 			}
251 			vpninfo->got_cancel_cmd = 0;
252 			break;
253 		}
254 
255 		if (vpninfo->got_pause_cmd) {
256 			/* close all connections and wait for the user to call
257 			   openconnect_mainloop() again */
258 			openconnect_close_https(vpninfo, 0);
259 			if (vpninfo->dtls_state > DTLS_DISABLED) {
260 				vpninfo->proto->udp_close(vpninfo);
261 				vpninfo->new_dtls_started = 0;
262 			}
263 
264 			vpninfo->got_pause_cmd = 0;
265 			vpn_progress(vpninfo, PRG_INFO, _("Caller paused the connection\n"));
266 			return 0;
267 		}
268 
269 		if (did_work)
270 			continue;
271 
272 		vpn_progress(vpninfo, PRG_TRACE,
273 			     _("No work to do; sleeping for %d ms...\n"), timeout);
274 
275 #ifdef _WIN32
276 		if (vpninfo->dtls_monitored) {
277 			WSAEventSelect(vpninfo->dtls_fd, vpninfo->dtls_event, vpninfo->dtls_monitored);
278 			events[nr_events++] = vpninfo->dtls_event;
279 		}
280 		if (vpninfo->ssl_monitored) {
281 			WSAEventSelect(vpninfo->ssl_fd, vpninfo->ssl_event, vpninfo->ssl_monitored);
282 			events[nr_events++] = vpninfo->ssl_event;
283 		}
284 		if (vpninfo->cmd_monitored) {
285 			WSAEventSelect(vpninfo->cmd_fd, vpninfo->cmd_event, vpninfo->cmd_monitored);
286 			events[nr_events++] = vpninfo->cmd_event;
287 		}
288 		if (vpninfo->tun_monitored) {
289 			events[nr_events++] = vpninfo->tun_rd_overlap.hEvent;
290 		}
291 		if (WaitForMultipleObjects(nr_events, events, FALSE, timeout) == WAIT_FAILED) {
292 			char *errstr = openconnect__win32_strerror(GetLastError());
293 			vpn_progress(vpninfo, PRG_ERR,
294 				     _("WaitForMultipleObjects failed: %s\n"),
295 				     errstr);
296 			free(errstr);
297 		}
298 #else
299 		memcpy(&rfds, &vpninfo->_select_rfds, sizeof(rfds));
300 		memcpy(&wfds, &vpninfo->_select_wfds, sizeof(wfds));
301 		memcpy(&efds, &vpninfo->_select_efds, sizeof(efds));
302 
303 		tv.tv_sec = timeout / 1000;
304 		tv.tv_usec = (timeout % 1000) * 1000;
305 
306 		if (select(vpninfo->_select_nfds, &rfds, &wfds, &efds, &tv) < 0 &&
307 		    errno != EINTR) {
308 			ret = -errno;
309 			vpn_perror(vpninfo, _("Failed select() in mainloop"));
310 			break;
311 		}
312 
313 		if (vpninfo->tun_fd >= 0)
314 			tun_r = FD_ISSET(vpninfo->tun_fd, &rfds);
315 		if (vpninfo->dtls_fd >= 0)
316 			udp_r = FD_ISSET(vpninfo->dtls_fd, &rfds);
317 		if (vpninfo->ssl_fd >= 0)
318 			tcp_r = FD_ISSET(vpninfo->ssl_fd, &rfds);
319 #endif
320 	}
321 
322 	if (vpninfo->quit_reason && vpninfo->proto->vpn_close_session)
323 		vpninfo->proto->vpn_close_session(vpninfo, vpninfo->quit_reason);
324 
325 	if (tun_is_up(vpninfo))
326 		os_shutdown_tun(vpninfo);
327 	return ret < 0 ? ret : -EIO;
328 }
329 
ka_check_deadline(int * timeout,time_t now,time_t due)330 int ka_check_deadline(int *timeout, time_t now, time_t due)
331 {
332 	if (now >= due)
333 		return 1;
334 	if (*timeout > (due - now) * 1000)
335 		*timeout = (due - now) * 1000;
336 	return 0;
337 }
338 
339 /* Called when the socket is unwritable, to get the deadline for DPD.
340    Returns 1 if DPD deadline has already arrived. */
ka_stalled_action(struct keepalive_info * ka,int * timeout)341 int ka_stalled_action(struct keepalive_info *ka, int *timeout)
342 {
343 	time_t now = time(NULL);
344 
345 	/* We only support the new-tunnel rekey method for now. */
346 	if (ka->rekey_method != REKEY_NONE &&
347 	    ka_check_deadline(timeout, now, ka->last_rekey + ka->rekey)) {
348 		ka->last_rekey = now;
349 		return KA_REKEY;
350 	}
351 
352 	if (ka->dpd &&
353 	    ka_check_deadline(timeout, now, ka->last_rx + (2 * ka->dpd)))
354 		return KA_DPD_DEAD;
355 
356 	return KA_NONE;
357 }
358 
359 
keepalive_action(struct keepalive_info * ka,int * timeout)360 int keepalive_action(struct keepalive_info *ka, int *timeout)
361 {
362 	time_t now = time(NULL);
363 
364 	if (ka->rekey_method != REKEY_NONE &&
365 	    ka_check_deadline(timeout, now, ka->last_rekey + ka->rekey)) {
366 		ka->last_rekey = now;
367 		return KA_REKEY;
368 	}
369 
370 	/* DPD is bidirectional -- PKT 3 out, PKT 4 back */
371 	if (ka->dpd) {
372 		time_t due = ka->last_rx + ka->dpd;
373 		time_t overdue = ka->last_rx + (2 * ka->dpd);
374 
375 		/* Peer didn't respond */
376 		if (now > overdue)
377 			return KA_DPD_DEAD;
378 
379 		/* If we already have DPD outstanding, don't flood. Repeat by
380 		   all means, but only after half the DPD period. */
381 		if (ka->last_dpd > ka->last_rx)
382 			due = ka->last_dpd + ka->dpd / 2;
383 
384 		/* We haven't seen a packet from this host for $DPD seconds.
385 		   Prod it to see if it's still alive */
386 		if (ka_check_deadline(timeout, now, due)) {
387 			ka->last_dpd = now;
388 			return KA_DPD;
389 		}
390 	}
391 
392 	/* Keepalive is just client -> server.
393 	   If we haven't sent anything for $KEEPALIVE seconds, send a
394 	   dummy packet (which the server will discard) */
395 	if (ka->keepalive &&
396 	    ka_check_deadline(timeout, now, ka->last_tx + ka->keepalive))
397 		return KA_KEEPALIVE;
398 
399 	return KA_NONE;
400 }
401 
trojan_check_deadline(struct openconnect_info * vpninfo,int * timeout)402 int trojan_check_deadline(struct openconnect_info *vpninfo, int *timeout)
403 {
404 	time_t now = time(NULL);
405 
406 	if (vpninfo->trojan_interval &&
407 	    ka_check_deadline(timeout, now,
408 			      vpninfo->last_trojan + vpninfo->trojan_interval)) {
409 		vpninfo->last_trojan = now;
410 		return 1;
411 	} else {
412 		return 0;
413 	}
414 }
415