1 /*	ptunnel.c
2 	ptunnel is licensed under the BSD license:
3 
4 	Copyright (c) 2004-2011, Daniel Stoedle <daniels@cs.uit.no>,
5 	Yellow Lemon Software. All rights reserved.
6 
7 	Redistribution and use in source and binary forms, with or without
8 	modification, are permitted provided that the following conditions are met:
9 
10 	- Redistributions of source code must retain the above copyright notice,
11 	  this list of conditions and the following disclaimer.
12 
13 	- Redistributions in binary form must reproduce the above copyright notice,
14 	  this list of conditions and the following disclaimer in the documentation
15 	  and/or other materials provided with the distribution.
16 
17 	- Neither the name of the Yellow Lemon Software nor the names of its
18 	  contributors may be used to endorse or promote products derived from this
19 	  software without specific prior written permission.
20 
21 	THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 	AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 	IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 	ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
25 	LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 	CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 	SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 	INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 	CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 	ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 	POSSIBILITY OF SUCH DAMAGE.
32 
33 	Contacting the author:
34 	You can get in touch with me, Daniel St�dle (that's the Norwegian letter oe,
35 	in case your text editor didn't realize), here: <daniels@cs.uit.no>
36 
37 	The official ptunnel website is here:
38 	<http://www.cs.uit.no/~daniels/PingTunnel/>
39 
40 	Note that the source code is best viewed with tabs set to 4 spaces.
41 */
42 
43 #include	"ptunnel.h"
44 #include	"md5.h"
45 
46 #ifdef WIN32
47 	/* pthread porting to windows */
48 	typedef CRITICAL_SECTION  pthread_mutex_t;
49 	typedef unsigned long     pthread_t;
50 	#define pthread_mutex_init    InitializeCriticalSectionAndSpinCount
51 	#define pthread_mutex_lock    EnterCriticalSection
52 	#define pthread_mutex_unlock  LeaveCriticalSection
53 
54 	#include <winsock2.h>
55 	/* Map errno (which Winsock doesn't use) to GetLastError; include the code in the strerror */
56 	#ifdef errno
57 		#undef errno
58 	#endif /* errno */
59 	#define errno GetLastError()
60 	/* Local error string storage */
61 	static char errorstr[255];
print_last_windows_error()62 	static char * print_last_windows_error()  {
63 		DWORD last_error = GetLastError();
64 		memset(errorstr, 0, sizeof(errorstr));
65 		FormatMessage(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM, NULL, last_error, 0, errorstr, sizeof(errorstr), NULL);
66 		snprintf(errorstr, sizeof(errorstr), "%s (%d)", errorstr, last_error);
67 		return errorstr;
68 	}
69 	#define strerror(x) print_last_windows_error()
70 #else
71 #ifdef HAVE_SELINUX
72 	#include <selinux/selinux.h>
73 	static char		*selinux_context = NULL;
74 #endif
75 	static uid_t		uid = 0;
76 	static gid_t		gid = 0;
77 	static char		*root_dir = NULL;
78 	static bool		daemonize = false;
79 	static FILE		*pid_file = NULL;
80 #endif /* WIN32 */
81 
82 
83 //	Lots of globals
84 pthread_mutex_t		chain_lock,				//	Lock protecting the chain of connections
85   					num_threads_lock;		//	Lock protecting the num_threads variable
86 
87 bool				unprivileged			= false,	//	True if user wants to run without root
88 					pcap					= false,	//	True if user wants packet capturing
89 					print_stats				= false,	//	True if user wants continuous statistics printed.
90 					use_syslog              = false;	//  True if user wants to log to syslog
91 FILE				*log_file				= 0;		//	Usually stdout, but can be altered by the user
92 
93 int					tcp_port				= -1,		//	Port to send data to from the proxy
94 					tcp_listen_port			= -1,		//	Port the client listens on
95 					log_level				= kLog_event,	//	Default log level
96 					mode					= kMode_proxy,	//	Default mode (proxy)
97 					num_threads				= 0,			//	Current thread count
98 					max_tunnels				= kMax_tunnels,	//	Default maximum number of tunnels to support at once
99 					num_tunnels				= 0,			//	Current tunnel count
100 					use_udp					= 0;			//	True if UDP should be used for transport (proxy runs on port 53)
101 uint32_t			*seq_expiry_tbl			= 0,			//	Table indicating when a connection ID is allowable (used by proxy)
102 					given_proxy_ip			= 0,			//	Proxy's internet address
103 					given_dst_ip			= 0;			//	Destination client wants data forwarded to
104 char				*password				= 0,			//	Password (must be the same on proxy and client for authentication to succeed)
105 					password_digest[kMD5_digest_size],		//	MD5 digest of password
106 					*pcap_device			= 0;			//	Device to capture packets from
107 
108 //	Some buffer constants
109 const int			tcp_receive_buf_len		= kDefault_buf_size,
110 					icmp_receive_buf_len	= kDefault_buf_size + kIP_header_size + kICMP_header_size + sizeof(ping_tunnel_pkt_t),
111 					pcap_buf_size			= (kDefault_buf_size + kIP_header_size + kICMP_header_size + sizeof(ping_tunnel_pkt_t)+64)*64;
112 char				pcap_filter_program[]	= "icmp"; // && (icmp[icmptype] = icmp-echo || icmp[icmptype] = icmp-echoreply)";
113 
114 //	The chain of client/proxy connections
115 proxy_desc_t		*chain					= 0;
116 const char			*state_name[kNum_proto_types]	= { "start", "ack", "data", "close", "authenticate" };
117 
118 //	Let the fun begin!
main(int argc,char * argv[])119 int		main(int argc, char *argv[]) {
120 	int				i, opt;
121 	md5_state_t		state;
122 	struct hostent	*host_ent;
123 #ifndef WIN32
124 	struct passwd	*pwnam;
125 	struct group	*grnam;
126 	pid_t			pid;
127 #endif
128 #ifdef WIN32
129 	WORD wVersionRequested;
130 	WSADATA wsaData;
131 	int err;
132 
133 	wVersionRequested = MAKEWORD( 2, 2 );
134 
135 	err = WSAStartup( wVersionRequested, &wsaData );
136 	if ( err != 0 ) {
137 		return -1;
138 	}
139 
140 	if ( LOBYTE( wsaData.wVersion ) != 2 ||
141 		HIBYTE( wsaData.wVersion ) != 2 ) {
142 		WSACleanup();
143 		return -1;
144 	}
145 #endif /* WIN32 */
146 
147 
148 	//	Seed random generator; it'll be used in combination with a timestamp
149 	//	when generating authentication challenges.
150 	srand(time(0));
151 	memset(password_digest, 0, kMD5_digest_size);
152 
153 	/*	The seq_expiry_tbl is used to prevent the remote ends from prematurely
154 		re-using a sequence number.
155 	*/
156 	seq_expiry_tbl	= calloc(65536, sizeof(uint32_t));
157 
158 	log_file		= stdout;
159 
160 	//	Parse options
161 	opt				= kOpt_undefined;
162 	mode			= kMode_proxy;
163 	for (i=1;i<argc;i++) {
164 		if (strcmp(argv[i], "-p") == 0) {
165 			mode	= kMode_forward;
166 			opt		= kOpt_set_proxy_addr;
167 		}
168 		else if (strcmp(argv[i], "-x") == 0)
169 			opt	= kOpt_set_password;
170 		else if (strcmp(argv[i], "-lp") == 0)
171 			opt	= kOpt_set_tcp_port;
172 		else if (strcmp(argv[i], "-da") == 0)
173 			opt	= kOpt_set_tcp_dest_addr;
174 		else if (strcmp(argv[i], "-dp") == 0)
175 			opt	= kOpt_set_tcp_dest_port;
176 		else if (strcmp(argv[i], "-v") == 0)
177 			opt	= kOpt_set_verbosity;
178 		else if (strcmp(argv[i], "-m") == 0)
179 			opt = kOpt_set_max_tunnels;
180 		else if (strcmp(argv[i], "-u") == 0)
181 			unprivileged	= !unprivileged;
182 		else if (strcmp(argv[i], "-c") == 0)
183 			opt	= kOpt_set_pcap_device;
184 		else if (strcmp(argv[i], "-f") == 0)
185 			opt = kOpt_set_log_file;
186 		else if (strcmp(argv[i], "-s") == 0)
187 			print_stats		= !print_stats;
188 		#ifndef WIN32
189 		else if (strcmp(argv[i], "-syslog") == 0)
190 			use_syslog		= !use_syslog;
191 		else if (strcmp(argv[i], "-setuid") == 0)
192 			opt	= kOpt_set_unpriv_user;
193 		else if (strcmp(argv[i], "-setgid") == 0)
194 			opt	= kOpt_set_unpriv_group;
195 		else if (strcmp(argv[i], "-chroot") == 0)
196 			opt	= kOpt_set_root_dir;
197 		else if (strcmp(argv[i], "-setcon") == 0)
198 			opt	= kOpt_set_selinux_context;
199 		else if (strcmp(argv[i], "-daemon") == 0)
200 			opt	= kOpt_daemonize;
201 		#endif /* !WIN32 */
202 		else if (strcmp(argv[i], "-udp") == 0)
203 			use_udp			= 1;
204 		else {
205 			switch (opt) {
206 				case kOpt_set_proxy_addr:
207 					if (NULL == (host_ent = gethostbyname(argv[i]))) {
208 						pt_log(kLog_error, "Failed to look up %s as proxy address\n", argv[i]);
209 						return 1;
210 					}
211 					given_proxy_ip = *(uint32_t*)host_ent->h_addr_list[0];
212 					break;
213 				case kOpt_set_password:
214 					password				= argv[i];
215 					pt_log(kLog_debug, "Password set - unauthenicated connections will be refused.\n");
216 					//	Compute the password digest
217 					md5_init(&state);
218 					md5_append(&state, (md5_byte_t*)password, strlen(password));
219 					md5_finish(&state, (md5_byte_t*)password_digest);
220 					//	Hide the password in process listing
221 					memset(argv[i], ' ', strlen(argv[i]));
222 					break;
223 				case kOpt_set_tcp_port:
224 					tcp_listen_port			= atoi(argv[i]);
225 					break;
226 				case kOpt_set_tcp_dest_addr:
227 					if (NULL == (host_ent = gethostbyname(argv[i]))) {
228 						pt_log(kLog_error, "Failed to look up %s as destination address\n", argv[i]);
229 						return 1;
230 					}
231 					given_dst_ip = *(uint32_t*)host_ent->h_addr_list[0];
232 					break;
233 				case kOpt_set_tcp_dest_port:
234 					tcp_port				= atoi(argv[i]);
235 					break;
236 				case kOpt_set_max_tunnels:
237 					max_tunnels	= atoi(argv[i]);
238 					if (max_tunnels <= 0)
239 						max_tunnels	= kMax_tunnels;
240 					break;
241 				case kOpt_set_verbosity:
242 					log_level		= atoi(argv[i]);
243 					break;
244 				case kOpt_set_pcap_device:
245 					pcap_device		= argv[i];
246 					pcap			= 1;
247 					break;
248 				case kOpt_set_log_file:
249 					log_file		= fopen(argv[i], "a");
250 					if (!log_file) {
251 						log_file	= stdout;
252 						pt_log(kLog_error, "Failed to open log file: '%s'. Cause: %s\n", argv[i], strerror(errno));
253 						pt_log(kLog_error, "Reverting log to standard out.\n");
254 					}
255 					break;
256 				#ifndef WIN32
257 				case kOpt_set_unpriv_user:
258 					errno = 0;
259 					if (NULL == (pwnam = getpwnam(argv[i]))) {
260 						pt_log(kLog_error, "%s: %s\n", argv[i], errno ? strerror(errno) : "unknown user");
261 						exit(1);
262 					}
263 					uid = pwnam->pw_uid;
264 					if (!gid)
265 						gid = pwnam->pw_gid;
266 					break;
267 				case kOpt_set_unpriv_group:
268 					errno = 0;
269 					if (NULL == (grnam = getgrnam(argv[i]))) {
270 						pt_log(kLog_error, "%s: %s\n", argv[i], errno ? strerror(errno) : "unknown group");
271 						exit(1);
272 					}
273 					gid = grnam->gr_gid;
274 					break;
275 				case kOpt_set_root_dir:
276 					root_dir = strdup(argv[i]);
277 					break;
278 				case kOpt_set_selinux_context:
279 				#ifdef HAVE_SELINUX
280 					selinux_context = strdup(argv[i]);
281 				#else
282 					pt_log(kLog_error, "Sorry: SELinux support missing, please recompile with libselinux.\n");
283 					return 1;
284 				#endif
285 					break;
286 				case kOpt_daemonize:
287 					daemonize = true;
288 					if (NULL == (pid_file = fopen(argv[i], "w")))
289 						pt_log(kLog_error, "%s: %s\n", argv[i], strerror(errno));
290 					break;
291 				#endif /* !WIN32 */
292 				case kOpt_undefined:
293 					usage(argv[0]);
294 					return 1;
295 			}
296 			opt	= kOpt_undefined;
297 		}
298 	}
299 	if (opt != kOpt_undefined) {
300 		usage(argv[0]);
301 		exit(1);
302 	}
303 	if (pcap && use_udp) {
304 		pt_log(kLog_error, "Packet capture is not supported (or needed) when using UDP for transport.\n");
305 		pcap	= 0;
306 	}
307 	pt_log(kLog_info, "Starting ptunnel v %d.%.2d.\n", kMajor_version, kMinor_version);
308 	pt_log(kLog_info, "(c) 2004-2011 Daniel Stoedle, <daniels@cs.uit.no>\n");
309 	#ifdef WIN32
310 	pt_log(kLog_info, "Windows version by Mike Miller, <mike@mikeage.net>\n");
311 	#else
312 	pt_log(kLog_info, "Security features by Sebastien Raveau, <sebastien.raveau@epita.fr>\n");
313 	#endif
314 	pt_log(kLog_info, "%s.\n", (mode == kMode_forward ? "Relaying packets from incoming TCP streams" : "Forwarding incoming ping packets over TCP"));
315 	if (use_udp)
316 		pt_log(kLog_info, "UDP transport enabled.\n");
317 
318 #ifndef WIN32
319   	signal(SIGPIPE, SIG_IGN);
320 	if (use_syslog) {
321 		if (log_file != stdout) {
322 			pt_log(kLog_error, "Logging using syslog overrides the use of a specified logfile (using -f).\n");
323 			fclose(log_file);
324 			log_file	= stdout;
325 		}
326 		openlog("ptunnel", LOG_PID, LOG_USER);
327 	}
328 	if (NULL != root_dir) {
329 		pt_log(kLog_info, "Restricting file access to %s\n", root_dir);
330 		if (-1 == chdir(root_dir) || -1 == chroot(root_dir)) {
331 			pt_log(kLog_error, "%s: %s\n", root_dir, strerror(errno));
332 			exit(1);
333 		}
334 	}
335 	if (daemonize) {
336 		pt_log(kLog_info, "Going to the background.\n");
337 		if (0 < (pid = fork()))
338 			exit(0);
339 		if (0 > pid)
340 			pt_log(kLog_error, "fork: %s\n", strerror(errno));
341 		else
342 			if (-1 == setsid())
343 				pt_log(kLog_error, "setsid: %s\n", strerror(errno));
344 			else {
345 				if (0 < (pid = fork()))
346 					exit(0);
347 				if (0 > pid)
348 					pt_log(kLog_error, "fork: %s\n", strerror(errno));
349 				else {
350 					if (NULL != pid_file) {
351 						fprintf(pid_file, "%d\n", getpid());
352 						fclose(pid_file);
353 					}
354 					freopen("/dev/null", "r", stdin);
355 					freopen("/dev/null", "w", stdout);
356 					freopen("/dev/null", "w", stderr);
357 				}
358 			}
359 	}
360 #endif /* !WIN32 */
361 
362 #ifdef WIN32
363 	WORD wVersionRequested;
364 	WSADATA wsaData;
365 	int err;
366 
367 	wVersionRequested = MAKEWORD( 2, 2 );
368 
369 	err = WSAStartup( wVersionRequested, &wsaData );
370 	if ( err != 0 ) {
371 		return -1;
372 	}
373 
374 	if ( LOBYTE( wsaData.wVersion ) != 2 ||
375 		HIBYTE( wsaData.wVersion ) != 2 ) {
376 		WSACleanup();
377 		return -1;
378 	}
379 #endif /* WIN32 */
380   	pthread_mutex_init(&chain_lock, 0);
381   	pthread_mutex_init(&num_threads_lock, 0);
382 
383 	//	Check mode, validate arguments and start either client or proxy.
384 	if (mode == kMode_forward) {
385 		if (!given_proxy_ip || !given_dst_ip || !tcp_port || !tcp_listen_port) {
386 			printf("One of the options are missing or invalid.\n");
387 			usage(argv[0]);
388 			return -1;
389 		}
390 		pt_forwarder();
391 	}
392 	else
393 		pt_proxy(0);
394 
395 	//	Clean up
396 	if (log_file != stdout)
397 		fclose(log_file);
398 
399 #ifdef WIN32
400 	WSACleanup();
401 #else
402 	if (NULL != root_dir)
403 		free(root_dir);
404 	#ifdef HAVE_SELINUX
405 	if (NULL != selinux_context)
406 		free(selinux_context);
407 	#endif
408 #endif /* WIN32 */
409 
410 	pt_log(kLog_info, "ptunnel is exiting.\n");
411 	return 0;
412 }
413 
414 
usage(char * exec_name)415 void		usage(char *exec_name) {
416 	printf("ptunnel v %d.%.2d.\n", kMajor_version, kMinor_version);
417 	printf("Usage:   %s -p <addr> -lp <port> -da <dest_addr> -dp <dest_port> [-m max_tunnels] [-v verbosity] [-f logfile]\n", exec_name);
418 	printf("         %s [-m max_threads] [-v verbosity] [-c <device>]\n", exec_name);
419 	printf("     -p: Set address of peer running packet forwarder. This causes\n");
420 	printf("         ptunnel to operate in forwarding mode - the absence of this\n");
421 	printf("         option causes ptunnel to operate in proxy mode.\n");
422 	printf("    -lp: Set TCP listening port (only used when operating in forward mode)\n");
423 	printf("    -da: Set remote proxy destination address if client\n");
424 	printf("         Restrict to only this destination address if server\n");
425 	printf("    -dp: Set remote proxy destionation port if client\n");
426 	printf("         Restrict to only this destination port if server\n");
427 	printf("     -m: Set maximum number of concurrent tunnels\n");
428 	printf("     -v: Verbosity level (-1 to 4, where -1 is no output, and 4 is all output)\n");
429 	printf("     -c: Enable libpcap on the given device.\n");
430 	printf("     -f: Specify a file to log to, rather than printing to standard out.\n");
431 	printf("     -s: Client only. Enables continuous output of statistics (packet loss, etc.)\n");
432 	#ifndef WIN32
433 	printf("-daemon: Run in background, the PID will be written in the file supplied as argument\n");
434 	printf("-syslog: Output debug to syslog instead of standard out.\n");
435 	#endif /* !WIN32 */
436 	printf("   -udp: Toggle use of UDP instead of ICMP. Proxy will listen on port 53 (must be root).\n\n");
437 
438 	printf("Security features:  [-x password] [-u] [-setuid user] [-setgid group] [-chroot dir]\n");
439 	printf("     -x: Set password (must be same on client and proxy)\n");
440 	printf("     -u: Run proxy in unprivileged mode. This causes the proxy to forward\n");
441 	printf("         packets using standard echo requests, instead of crafting custom echo replies.\n");
442 	printf("         Unprivileged mode will only work on some systems, and is in general less reliable\n");
443 	printf("         than running in privileged mode.\n");
444 	#ifndef WIN32
445 	printf("         Please consider combining the following three options instead:\n");
446 	printf("-setuid: When started in privileged mode, drop down to user's rights as soon as possible\n");
447 	printf("-setgid: When started in privileged mode, drop down to group's rights as soon as possible\n");
448 	printf("-chroot: When started in privileged mode, restrict file access to the specified directory\n");
449 	printf("-setcon: Set SELinux context when all there is left to do are network I/O operations\n");
450 	printf("         To combine with -chroot you will have to `mount --bind /proc /chrootdir/proc`\n");
451 	#endif /* !WIN32 */
452 
453 	printf("\nStarting the proxy (needs to run as root):\n");
454 	printf(" [root #] %s\n", exec_name);
455 	printf("Starting a client (also needs root):\n");
456 	printf(" [root #] %s -p proxy.pingtunnel.com -lp 8000 -da login.domain.com -dp 22 -c eth0\n", exec_name);
457 	printf("And then using the tunnel to ssh to login.domain.com:\n");
458 	printf(" [user $] ssh -p 8000 localhost\n");
459 	printf("And that's it. Enjoy your tunnel!\n\n");
460 }
461 
462 
463 /*	pt_forwarder:
464 	Sets up a listening TCP socket, and forwards incoming connections
465 	over ping packets.
466 */
pt_forwarder(void)467 void		pt_forwarder(void) {
468 	int					server_sock, new_sock, sock, yes = 1;
469 	fd_set				set;
470 	struct timeval		time;
471 	struct sockaddr_in	addr, dest_addr;
472 	socklen_t			addr_len;
473 	pthread_t			pid;
474 	uint16_t			rand_id;
475 
476 	pt_log(kLog_debug, "Starting forwarder..\n");
477 	//	Open our listening socket
478 	sock					= socket(AF_INET, SOCK_STREAM, 0);
479 	if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const void *) &yes, sizeof(int)) == -1) {
480 		pt_log(kLog_error, "Failed to set SO_REUSEADDR option on listening socket: %s\n", strerror(errno));
481 		close(sock);
482 		return;
483 	}
484 	addr.sin_family			= AF_INET;
485 	addr.sin_port			= htons(tcp_listen_port);
486 	addr.sin_addr.s_addr	= INADDR_ANY;
487 	memset(&(addr.sin_zero), 0, 8);
488 	if (bind(sock, (struct sockaddr*)&addr, sizeof(struct sockaddr)) == -1) {
489 		pt_log(kLog_error, "Failed to bind listening socket: %s\n", strerror(errno));
490 		close(sock);
491 		return;
492 	}
493 	server_sock		= sock;
494 	//	Fill out address structure
495 	memset(&dest_addr, 0, sizeof(struct sockaddr_in));
496 	dest_addr.sin_family			= AF_INET;
497 	if (use_udp)
498 		dest_addr.sin_port			= htons(kDNS_port /* dns port.. */);
499 	else
500 		dest_addr.sin_port			= 0;
501 	dest_addr.sin_addr.s_addr		= given_proxy_ip;
502 	pt_log(kLog_verbose, "Proxy IP address: %s\n", inet_ntoa(*((struct in_addr*)&given_proxy_ip)));
503 
504 	listen(server_sock, 10);
505 	while (1) {
506 		FD_ZERO(&set);
507 		FD_SET(server_sock, &set);
508 		time.tv_sec		= 1;
509 		time.tv_usec	= 0;
510 		if (select(server_sock+1, &set, 0, 0, &time) > 0) {
511 			pt_log(kLog_info, "Incoming connection.\n");
512 			addr_len	= sizeof(struct sockaddr_in);
513 			new_sock	= accept(server_sock, (struct sockaddr*)&addr, &addr_len);
514 			if (new_sock < 0) {
515 				pt_log(kLog_error, "Accepting incoming connection failed.\n");
516 				continue;
517 			}
518 			pthread_mutex_lock(&num_threads_lock);
519 			if (num_threads <= 0) {
520 				pt_log(kLog_event, "No running proxy thread - starting it.\n");
521 #ifndef WIN32
522 				if (pthread_create(&pid, 0, pt_proxy, 0) != 0)
523 #else
524 				if (0 == (pid = _beginthreadex(0, 0, (unsigned int (__stdcall *)(void *))pt_proxy, 0, 0, 0)))
525 #endif
526 				{
527 					pt_log(kLog_error, "Couldn't create thread! Dropping incoming connection.\n");
528 					close(new_sock);
529 					pthread_mutex_unlock(&num_threads_lock);
530 					continue;
531 				}
532 			}
533 			addr	= dest_addr;
534 			rand_id	= (uint16_t)rand();
535 			create_and_insert_proxy_desc(rand_id, rand_id, new_sock, &addr, given_dst_ip, tcp_port, kProxy_start, kUser_flag);
536 			pthread_mutex_unlock(&num_threads_lock);
537 		}
538 	}
539 }
540 
541 
pt_create_udp_socket(int port)542 int			pt_create_udp_socket(int port) {
543 	struct sockaddr_in	addr;
544 	int					sock, yes = 1;
545 
546 	sock = socket(AF_INET, SOCK_DGRAM, 0);
547 	if (sock < 0) {
548 		pt_log(kLog_error, "Failed to set create UDP socket..\n");
549 		return 0;
550 	}
551 	if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const void*)&yes, sizeof(int)) < 0) {
552 		pt_log(kLog_error, "Failed to set UDP REUSEADDR socket option. (Not fatal, hopefully.)\n");
553 		close(sock);
554 		return 0;
555 	}
556 	#ifdef SO_REUSEPORT
557 	yes = 1;
558 	if (setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, (const void*)&yes, sizeof(int)) < 0)
559 		pt_log(kLog_error, "Failed to set UDP REUSEPORT socket option. (Not fatal, hopefully.)\n");
560 	#endif //SO_REUSEPORT
561 
562 	memset(&addr, 0, sizeof(struct sockaddr_in));
563 	addr.sin_family			= AF_INET;
564 	addr.sin_addr.s_addr	= htonl(INADDR_ANY);
565 	addr.sin_port			= htons(port);
566 	if (bind(sock, (struct sockaddr*) &addr, sizeof(struct sockaddr_in)) < 0) {
567 		pt_log(kLog_error, "Failed to bind UDP socket to port %d (try running as root).\n", port);
568 		close(sock);
569 		return 0;
570 	}
571 	return sock;
572 }
573 
574 #define	kPT_add_iphdr	0
575 
576 /*	pt_proxy: This function does all the client and proxy stuff.
577 */
pt_proxy(void * args)578 void*		pt_proxy(void *args) {
579 	fd_set				set;
580 	struct timeval		timeout;
581 	int					bytes;
582 	struct sockaddr_in	addr;
583 	socklen_t			addr_len;
584 	int					fwd_sock	= 0,
585 						max_sock	= 0,
586 						idx;
587 	char				*buf;
588 	double				now, last_status_update = 0.0;
589 	proxy_desc_t		*cur, *prev, *tmp;
590 	pcap_info_t			pc;
591 	xfer_stats_t		xfer;
592 
593 	//	Start the thread, initialize protocol and ring states.
594 	pt_log(kLog_debug, "Starting ping proxy..\n");
595 	if (use_udp) {
596 		pt_log(kLog_debug, "Creating UDP socket..\n");
597 		if (mode == kMode_proxy)
598 			fwd_sock	= pt_create_udp_socket(kDNS_port);
599 		else
600 			fwd_sock	= pt_create_udp_socket(0);
601 		if (!fwd_sock) {
602 			pt_log(kLog_error, "Failed to create UDP socket.\n");
603 			return 0;
604 		}
605 	}
606 	else {
607 		if (unprivileged) {
608 			pt_log(kLog_debug, "Attempting to create unprivileged ICMP datagram socket..\n");
609 			fwd_sock		= socket(AF_INET, SOCK_DGRAM, IPPROTO_ICMP);
610 		}
611 		else {
612 			#if kPT_add_iphdr
613 			int		opt = 1;
614 			#endif
615 			pt_log(kLog_debug, "Attempting to create privileged ICMP raw socket..\n");
616 			#if kPT_add_iphdr
617 			//	experimental
618 			fwd_sock		= socket(AF_INET, SOCK_RAW, IPPROTO_IP);
619 			printf("Set ip-hdr-inc; result = %d\n", setsockopt(fwd_sock, IPPROTO_IP, IP_HDRINCL, &opt, sizeof(opt)));
620 			#else
621 			fwd_sock		= socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
622 			#endif
623 		}
624 		if (fwd_sock < 0) {
625 			pt_log(kLog_error, "Couldn't create %s socket: %s\n", (unprivileged ? "unprivileged datagram" : "privileged raw"), strerror(errno));
626 			return 0;
627 		}
628 	}
629 	max_sock			= fwd_sock+1;
630 	if (pcap) {
631 		if (use_udp) {
632 			pt_log(kLog_error, "Packet capture is not useful with UDP [should not get here!]!\n");
633 			close(fwd_sock);
634 			return 0;
635 		}
636 		if (!unprivileged) {
637 			pt_log(kLog_info, "Initializing pcap.\n");
638 			pc.pcap_err_buf		= malloc(PCAP_ERRBUF_SIZE);
639 			pc.pcap_data_buf	= malloc(pcap_buf_size);
640 			pc.pcap_desc		= pcap_open_live(pcap_device, pcap_buf_size, 0 /* promiscous */, 50 /* ms */, pc.pcap_err_buf);
641 			if (pc.pcap_desc) {
642 				if (pcap_lookupnet(pcap_device, &pc.netp, &pc.netmask, pc.pcap_err_buf) == -1) {
643 
644 					pt_log(kLog_error, "pcap error: %s\n", pc.pcap_err_buf);
645 					pcap	= 0;
646 				}
647 				pt_log(kLog_verbose, "Network: %s\n", inet_ntoa(*(struct in_addr*)&pc.netp));
648 				pt_log(kLog_verbose, "Netmask: %s\n", inet_ntoa(*(struct in_addr*)&pc.netmask));
649 				if (pcap_compile(pc.pcap_desc, &pc.fp, pcap_filter_program, 0, pc.netp) == -1) {
650 					pt_log(kLog_error, "Failed to compile pcap filter program.\n");
651 					pcap_close(pc.pcap_desc);
652 					pcap	= 0;
653 				}
654 				else if (pcap_setfilter(pc.pcap_desc, &pc.fp) == -1) {
655 					pt_log(kLog_error, "Failed to set pcap filter program.\n");
656 					pcap_close(pc.pcap_desc);
657 					pcap	= 0;
658 				}
659 			}
660 			else {
661 				pt_log(kLog_error, "pcap error: %s\n", pc.pcap_err_buf);
662 				pcap	= 0;
663 			}
664 			pc.pkt_q.head	= 0;
665 			pc.pkt_q.tail	= 0;
666 			pc.pkt_q.elems	= 0;
667 			//	Check if we have succeeded, and free stuff if not
668 			if (!pcap) {
669 				pt_log(kLog_error, "There were errors enabling pcap - pcap has been disabled.\n");
670 				free(pc.pcap_err_buf);
671 				free(pc.pcap_data_buf);
672 				return 0;
673 			}
674 		}
675 		else
676 			pt_log(kLog_info, "pcap disabled since we're running in unprivileged mode.\n");
677 	}
678 
679 	pthread_mutex_lock(&num_threads_lock);
680 	num_threads++;
681 	pthread_mutex_unlock(&num_threads_lock);
682 
683 	//	Allocate icmp receive buffer
684 	buf					= malloc(icmp_receive_buf_len);
685 
686 	//	Start forwarding :)
687 	pt_log(kLog_info, "Ping proxy is listening in %s mode.\n", (unprivileged ? "unprivileged" : "privileged"));
688 
689 	#ifndef WIN32
690 	#ifdef HAVE_SELINUX
691 	if (uid || gid || selinux_context)
692 	#else
693 	if (uid || gid)
694 	#endif
695 		pt_log(kLog_info, "Dropping privileges now.\n");
696 	if (gid && -1 == setgid(gid))
697 		pt_log(kLog_error, "setgid(%d): %s\n", gid, strerror(errno));
698 	if (uid && -1 == setuid(uid))
699 		pt_log(kLog_error, "setuid(%d): %s\n", uid, strerror(errno));
700 	#ifdef HAVE_SELINUX
701 	if (NULL != selinux_context && -1 == setcon(selinux_context))
702 		pt_log(kLog_error, "setcon(%s) failed: %s\n", selinux_context, strerror(errno));
703 	#endif
704 	#endif
705 
706 	while (1) {
707 		FD_ZERO(&set);
708 		FD_SET(fwd_sock, &set);
709 		max_sock		= fwd_sock+1;
710 		pthread_mutex_lock(&chain_lock);
711 		for (cur=chain;cur;cur=cur->next) {
712 			if (cur->sock) {
713 				FD_SET(cur->sock, &set);
714 				if (cur->sock >= max_sock)
715 					max_sock	= cur->sock+1;
716 			}
717 		}
718 		pthread_mutex_unlock(&chain_lock);
719 		timeout.tv_sec		= 0;
720 		timeout.tv_usec		= 10000;
721 		select(max_sock, &set, 0, 0, &timeout);	//	Don't care about return val, since we need to check for new states anyway..
722 
723 		pthread_mutex_lock(&chain_lock);
724 		for (prev=0,cur=chain;cur && cur->sock;cur=tmp) {
725 			//	Client: If we're starting up, send a message to the remote end saying so,
726 			//	causing him to connect to our desired endpoint.
727 			if (cur->state == kProxy_start) {
728 				pt_log(kLog_verbose, "Sending proxy request.\n");
729 				cur->last_ack	= time_as_double();
730 				queue_packet(fwd_sock, cur->pkt_type, 0, 0, cur->id_no, cur->id_no, &cur->my_seq, cur->send_ring, &cur->send_idx, &cur->send_wait_ack, cur->dst_ip, cur->dst_port, cur->state | cur->type_flag, &cur->dest_addr, cur->next_remote_seq, &cur->send_first_ack, &cur->ping_seq);
731 				cur->xfer.icmp_out++;
732 				cur->state		= kProto_data;
733 			}
734 			if (cur->should_remove) {
735 				pt_log(kLog_info, "\nSession statistics:\n");
736 				print_statistics(&cur->xfer, 0);
737 				pt_log(kLog_info, "\n");
738 				tmp	= cur->next;
739 				remove_proxy_desc(cur, prev);
740 				continue;
741 			}
742 			//	Only handle traffic if there is traffic on the socket, we have
743 			//	room in our send window AND we either don't use a password, or
744 			//	have been authenticated.
745 			if (FD_ISSET(cur->sock, &set) && cur->send_wait_ack < kPing_window_size && (!password || cur->authenticated)) {
746 				bytes		= recv(cur->sock, cur->buf, tcp_receive_buf_len, 0);
747 				if (bytes <= 0) {
748 					pt_log(kLog_info, "Connection closed or lost.\n");
749 					tmp	= cur->next;
750 					send_termination_msg(cur, fwd_sock);
751 					pt_log(kLog_info, "Session statistics:\n");
752 					print_statistics(&cur->xfer, 0);
753 					remove_proxy_desc(cur, prev);
754 					//	No need to update prev
755 					continue;
756 				}
757 				cur->xfer.bytes_out	+= bytes;
758 				cur->xfer.icmp_out++;
759 				queue_packet(fwd_sock, cur->pkt_type, cur->buf, bytes, cur->id_no, cur->icmp_id, &cur->my_seq, cur->send_ring, &cur->send_idx, &cur->send_wait_ack, 0, 0, cur->state | cur->type_flag, &cur->dest_addr, cur->next_remote_seq, &cur->send_first_ack, &cur->ping_seq);
760 			}
761 			prev	= cur;
762 			tmp		= cur->next;
763 		}
764 		pthread_mutex_unlock(&chain_lock);
765 
766 		if (FD_ISSET(fwd_sock, &set)) {
767 			//	Handle ping traffic
768 			addr_len	= sizeof(struct sockaddr);
769 			bytes		= recvfrom(fwd_sock, buf, icmp_receive_buf_len, 0, (struct sockaddr*)&addr, &addr_len);
770 			if (bytes < 0) {
771 				pt_log(kLog_error, "Error receiving packet on ICMP socket: %s\n", strerror(errno));
772 				break;
773 			}
774 			handle_packet(buf, bytes, 0, &addr, fwd_sock);
775 		}
776 
777 		//	Check for packets needing resend, and figure out if any connections
778 		//	should be closed down due to inactivity.
779 		pthread_mutex_lock(&chain_lock);
780 		now		= time_as_double();
781 		for (cur=chain;cur;cur=cur->next) {
782 			if (cur->last_activity + kAutomatic_close_timeout < now) {
783 				pt_log(kLog_info, "Dropping tunnel to %s:%d due to inactivity.\n", inet_ntoa(*(struct in_addr*)&cur->dst_ip), cur->dst_port, cur->id_no);
784 				cur->should_remove	= 1;
785 				continue;
786 			}
787 			if (cur->recv_wait_send && cur->sock)
788 				cur->xfer.bytes_in	+= send_packets(cur->recv_ring, &cur->recv_xfer_idx, &cur->recv_wait_send, &cur->sock);
789 
790 			//	Check for any icmp packets requiring resend, and resend _only_ the first packet.
791 			idx	= cur->send_first_ack;
792 			if (cur->send_ring[idx].pkt && cur->send_ring[idx].last_resend+kResend_interval < now) {
793 				pt_log(kLog_debug, "Resending packet with seq-no %d.\n", cur->send_ring[idx].seq_no);
794 				cur->send_ring[idx].last_resend		= now;
795 				cur->send_ring[idx].pkt->seq		= htons(cur->ping_seq);
796 				cur->ping_seq++;
797 				cur->send_ring[idx].pkt->checksum	= 0;
798 				cur->send_ring[idx].pkt->checksum	= htons(calc_icmp_checksum((uint16_t*)cur->send_ring[idx].pkt, cur->send_ring[idx].pkt_len));
799 				//printf("ID: %d\n", htons(cur->send_ring[idx].pkt->identifier));
800 				sendto(fwd_sock, (const void*)cur->send_ring[idx].pkt, cur->send_ring[idx].pkt_len, 0, (struct sockaddr*)&cur->dest_addr, sizeof(struct sockaddr));
801 				cur->xfer.icmp_resent++;
802 			}
803 			//	Figure out if it's time to send an explicit acknowledgement
804 			if (cur->last_ack+1.0 < now && cur->send_wait_ack < kPing_window_size && cur->remote_ack_val+1 != cur->next_remote_seq) {
805 				cur->last_ack	= now;
806 				queue_packet(fwd_sock, cur->pkt_type, 0, 0, cur->id_no, cur->icmp_id, &cur->my_seq, cur->send_ring, &cur->send_idx, &cur->send_wait_ack, cur->dst_ip, cur->dst_port, kProto_ack | cur->type_flag, &cur->dest_addr, cur->next_remote_seq, &cur->send_first_ack, &cur->ping_seq);
807 				cur->xfer.icmp_ack_out++;
808 			}
809 		}
810 		pthread_mutex_unlock(&chain_lock);
811 		if (pcap) {
812 			if (pcap_dispatch(pc.pcap_desc, 32, pcap_packet_handler, (u_char*)&pc.pkt_q) > 0) {
813 				pqueue_elem_t	*cur;
814 				//pt_log(kLog_verbose, "pcap captured %d packets - handling them..\n", pc.pkt_q.elems);
815 				while (pc.pkt_q.head) {
816 					cur						= pc.pkt_q.head;
817 					memset(&addr, sizeof(struct sockaddr), 0);
818 					addr.sin_family			= AF_INET;
819 					addr.sin_addr.s_addr	= *(in_addr_t*)&(((ip_packet_t*)(cur->data))->src_ip);
820 					handle_packet(cur->data, cur->bytes, 1, &addr, fwd_sock);
821 					pc.pkt_q.head			= cur->next;
822 					free(cur);
823 					pc.pkt_q.elems--;
824 				}
825 				pc.pkt_q.tail		= 0;
826 				pc.pkt_q.head		= 0;
827 			}
828 		}
829 		//	Update running statistics, if requested (only once every second)
830 		if (print_stats && mode == kMode_forward && now > last_status_update+1) {
831 			pthread_mutex_lock(&chain_lock);
832 			memset(&xfer, 0, sizeof(xfer_stats_t));
833 			for (cur=chain;cur;cur=cur->next) {
834 				xfer.bytes_in		+= cur->xfer.bytes_in;
835 				xfer.bytes_out		+= cur->xfer.bytes_out;
836 				xfer.icmp_in		+= cur->xfer.icmp_in;
837 				xfer.icmp_out		+= cur->xfer.icmp_out;
838 				xfer.icmp_resent	+= cur->xfer.icmp_resent;
839 			}
840 			pthread_mutex_unlock(&chain_lock);
841 			print_statistics(&xfer, 1);
842 			last_status_update		= now;
843 		}
844 	}
845 	pt_log(kLog_debug, "Proxy exiting..\n");
846 	if (fwd_sock)
847 		close(fwd_sock);
848 	//	TODO: Clean up the other descs. Not really a priority since there's no
849 	//	real way to quit ptunnel in the first place..
850 	free(buf);
851 	pt_log(kLog_debug, "Ping proxy done\n");
852 	return 0;
853 }
854 
855 
856 /*	print_statistics: Prints transfer statistics for the given xfer block. The
857 	is_continuous variable controls the output mode, either printing a new line
858 	or overwriting the old line.
859 */
print_statistics(xfer_stats_t * xfer,int is_continuous)860 void		print_statistics(xfer_stats_t *xfer, int is_continuous) {
861 	const double	mb		= 1024.0*1024.0;
862 	double			loss	= 0.0;
863 
864 	if (xfer->icmp_out > 0)
865 		loss	= (double)xfer->icmp_resent/(double)xfer->icmp_out;
866 
867 	if (is_continuous)
868 		printf("\r");
869 
870 	printf("[inf]: I/O: %6.2f/%6.2f mb ICMP I/O/R: %8d/%8d/%8d Loss: %4.1f%%",
871 			xfer->bytes_in/mb, xfer->bytes_out/mb, xfer->icmp_in, xfer->icmp_out, xfer->icmp_resent, loss);
872 
873 	if (!is_continuous)
874 		printf("\n");
875 	else
876 		fflush(stdout);
877 }
878 
879 
880 /*	pcap_packet_handler:
881 	This is our callback function handling captured packets. We already know that the packets
882 	are ICMP echo or echo-reply messages, so all we need to do is strip off the ethernet header
883 	and append it to the queue descriptor (the refcon argument).
884 
885 	Ok, the above isn't entirely correct (we can get other ICMP types as well). This function
886 	also has problems when it captures packets on the loopback interface. The moral of the
887 	story: Don't do ping forwarding over the loopback interface.
888 
889 	Also, we currently don't support anything else than ethernet when in pcap mode. The reason
890 	is that I haven't read up on yet on how to remove the frame header from the packet..
891 */
pcap_packet_handler(u_char * refcon,const struct pcap_pkthdr * hdr,const u_char * pkt)892 void		pcap_packet_handler(u_char *refcon, const struct pcap_pkthdr *hdr, const u_char* pkt) {
893 	pqueue_t		*q;
894 	pqueue_elem_t	*elem;
895 	ip_packet_t		*ip;
896 
897 	//pt_log(kLog_verbose, "Packet handler: %d =? %d\n", hdr->caplen, hdr->len);
898 	q		= (pqueue_t*)refcon;
899 	elem	= malloc(sizeof(pqueue_elem_t)+hdr->caplen-sizeof(struct ether_header));
900 	memcpy(elem->data, pkt+sizeof(struct ether_header), hdr->caplen-sizeof(struct ether_header));
901 	ip		= (ip_packet_t*)elem->data;
902 	//	TODO: Add fragment support
903 	elem->bytes	= ntohs(ip->pkt_len);
904 	if (elem->bytes > hdr->caplen-sizeof(struct ether_header)) {
905 		pt_log(kLog_error, "Received fragmented packet - unable to reconstruct!\n");
906 		pt_log(kLog_error, "This error usually occurs because pcap is used on devices that are not wlan or ethernet.\n");
907 		free(elem);
908 		return;
909 	}
910 	//elem->bytes	= hdr->caplen-sizeof(struct ether_header);
911 	elem->next	= 0;
912 	if (q->tail) {
913 		q->tail->next	= elem;
914 		q->tail			= elem;
915 	}
916 	else {
917 		q->head	= elem;
918 		q->tail	= elem;
919 	}
920 	q->elems++;
921 }
922 
923 
924 
925 /*	handle_proxy_packet:
926 	Processes incoming ICMP packets for the proxy. The packet can come either from the
927 	packet capture lib, or from the actual socket or both.
928 	Input:	A buffer pointing at the start of an IP header, the buffer length and the proxy
929 			descriptor chain.
930 */
handle_packet(char * buf,int bytes,int is_pcap,struct sockaddr_in * addr,int icmp_sock)931 void		handle_packet(char *buf, int bytes, int is_pcap, struct sockaddr_in *addr, int icmp_sock) {
932 	ip_packet_t			*ip_pkt;
933 	icmp_echo_packet_t	*pkt;
934 	ping_tunnel_pkt_t	*pt_pkt;
935 	proxy_desc_t		*cur;
936 	uint32_t			type_flag, pkt_flag, init_state;
937 	challenge_t			*challenge;
938 	struct timeval		tt;
939 
940 	if (bytes < sizeof(icmp_echo_packet_t)+sizeof(ping_tunnel_pkt_t))
941 		pt_log(kLog_verbose, "Skipping this packet - too short. Expect: %d+%d = %d ; Got: %d\n", sizeof(icmp_echo_packet_t), sizeof(ping_tunnel_pkt_t), sizeof(icmp_echo_packet_t)+sizeof(ping_tunnel_pkt_t), bytes);
942 	else {
943 		if (use_udp) {
944 			ip_pkt		= 0;
945 			pkt			= (icmp_echo_packet_t*)buf;
946 			pt_pkt		= (ping_tunnel_pkt_t*)pkt->data;
947 		}
948 		else {
949 			ip_pkt		= (ip_packet_t*)buf;
950 			pkt			= (icmp_echo_packet_t*)ip_pkt->data;
951 			pt_pkt		= (ping_tunnel_pkt_t*)pkt->data;
952 		}
953 		if (ntohl(pt_pkt->magic) == kPing_tunnel_magic) {
954 			pt_pkt->state		= ntohl(pt_pkt->state);
955 			pkt->identifier		= ntohs(pkt->identifier);
956 			pt_pkt->id_no		= ntohs(pt_pkt->id_no);
957 			pt_pkt->seq_no		= ntohs(pt_pkt->seq_no);
958 			//	Find the relevant connection, if it exists
959 			pthread_mutex_lock(&chain_lock);
960 			for (cur=chain;cur;cur=cur->next) {
961 				if (cur->id_no == pt_pkt->id_no)
962 					break;
963 			}
964 			pthread_mutex_unlock(&chain_lock);
965 
966 			/*	Handle the packet if it comes from "the other end." This is a bit tricky
967 				to get right, since we receive both our own and the other end's packets.
968 				Basically, a proxy will accept any packet from a user, regardless if it
969 				has a valid connection or not. A user will only accept the packet if there
970 				exists a connection to handle it.
971 			*/
972 			if (cur) {
973 				type_flag			= cur->type_flag;
974 				if (type_flag == kProxy_flag)
975 					cur->icmp_id	= pkt->identifier;
976 
977 				if (!is_pcap)
978 					cur->xfer.icmp_in++;
979 			}
980 			else
981 				type_flag			= kProxy_flag;
982 
983 			pkt_flag		= pt_pkt->state & kFlag_mask;
984 			pt_pkt->state	&= ~kFlag_mask;
985 			pt_log(kLog_sendrecv, "Recv: %d [%d] bytes [seq = %d] [type = %s] [ack = %d] [icmp = %d] [user = %s] [pcap = %d]\n",
986 								bytes, ntohl(pt_pkt->data_len), pt_pkt->seq_no, state_name[pt_pkt->state & (~kFlag_mask)],
987 								ntohl(pt_pkt->ack), pkt->type, (pkt_flag == kUser_flag ? "yes" : "no"), is_pcap);
988 
989 			//	This test essentially verifies that the packet comes from someone who isn't us.
990 			if ((pkt_flag == kUser_flag && type_flag == kProxy_flag) || (pkt_flag == kProxy_flag && type_flag == kUser_flag)) {
991 				pt_pkt->data_len	= ntohl(pt_pkt->data_len);
992 				pt_pkt->ack			= ntohl(pt_pkt->ack);
993 				if (pt_pkt->state == kProxy_start) {
994 					if (!cur && type_flag == kProxy_flag) {
995 						pt_log(kLog_info, "Incoming tunnel request from %s.\n", inet_ntoa(*(struct in_addr*)&addr->sin_addr));
996 						gettimeofday(&tt, 0);
997 						if (tt.tv_sec < seq_expiry_tbl[pt_pkt->id_no]) {
998 							pt_log(kLog_verbose, "Dropping request: ID was recently in use.\n");
999 							return;
1000 						}
1001 						pt_log(kLog_info, "Starting new session to %s:%d with ID %d\n", inet_ntoa(*(struct in_addr*)&pt_pkt->dst_ip), ntohl(pt_pkt->dst_port), pt_pkt->id_no);
1002 						if ((given_dst_ip && given_dst_ip != pt_pkt->dst_ip) || (-1 != tcp_port && tcp_port != ntohl(pt_pkt->dst_port))) {
1003 							pt_log(kLog_info, "Destination administratively prohibited!\n");
1004 							return;
1005 						}
1006 						if (password)
1007 							init_state	= kProto_authenticate;
1008 						else
1009 							init_state	= kProto_data;
1010 						cur			= create_and_insert_proxy_desc(pt_pkt->id_no, pkt->identifier, 0, addr, pt_pkt->dst_ip, ntohl(pt_pkt->dst_port), init_state, kProxy_flag);
1011 						if (init_state == kProto_authenticate) {
1012 							pt_log(kLog_debug, "Sending authentication challenge..\n");
1013 							//	Send challenge
1014 							cur->challenge	= generate_challenge();
1015 							memcpy(cur->buf, cur->challenge, sizeof(challenge_t));
1016 							queue_packet(icmp_sock, cur->pkt_type, cur->buf, sizeof(challenge_t), cur->id_no, cur->icmp_id, &cur->my_seq, cur->send_ring, &cur->send_idx, &cur->send_wait_ack, 0, 0, kProto_authenticate | cur->type_flag, &cur->dest_addr, cur->next_remote_seq, &cur->send_first_ack, &cur->ping_seq);
1017 						}
1018 					}
1019 					else if (type_flag == kUser_flag) {
1020 						pt_log(kLog_error, "Dropping proxy session request - we are not a proxy!\n");
1021 						return;
1022 					}
1023 					else
1024 						pt_log(kLog_error, "Dropping duplicate proxy session request.\n");
1025 				}
1026 				else if (cur && pt_pkt->state == kProto_authenticate) {
1027 					//	Sanity check packet length, and make sure it matches what we expect
1028 					if (pt_pkt->data_len != sizeof(challenge_t)) {
1029 						pt_log(kLog_error, "Received challenge packet, but data length is not as expected.\n");
1030 						pt_log(kLog_debug, "Data length: %d  Expected: %d\n", pt_pkt->data_len, sizeof(challenge_t));
1031 						cur->should_remove				= 1;
1032 						return;
1033 					}
1034 					//	Prevent packet data from being forwarded over TCP!
1035 					pt_pkt->data_len	= 0;
1036 					challenge			= (challenge_t*)pt_pkt->data;
1037 					//	If client: Compute response to challenge
1038 					if (type_flag == kUser_flag) {
1039 						if (!password) {
1040 							pt_log(kLog_error, "This proxy requires a password! Please supply one using the -x switch.\n");
1041 							send_termination_msg(cur, icmp_sock);
1042 							cur->should_remove	= 1;
1043 							return;
1044 						}
1045 						pt_log(kLog_debug, "Got authentication challenge - sending response\n");
1046 						generate_response(challenge);
1047 						queue_packet(icmp_sock, cur->pkt_type, (char*)challenge, sizeof(challenge_t), cur->id_no, cur->icmp_id, &cur->my_seq, cur->send_ring, &cur->send_idx, &cur->send_wait_ack, 0, 0, kProto_authenticate | cur->type_flag, &cur->dest_addr, cur->next_remote_seq, &cur->send_first_ack, &cur->ping_seq);
1048 						//	We have authenticated locally. It's up to the proxy now if it accepts our response or not..
1049 						cur->authenticated	= 1;
1050 						handle_data(pkt, bytes, cur->recv_ring, &cur->recv_wait_send, &cur->recv_idx, &cur->next_remote_seq);
1051 						return;
1052 					}
1053 					//	If proxy: Handle client's response to challenge
1054 					else if (type_flag == kProxy_flag) {
1055 						pt_log(kLog_debug, "Received remote challenge response.\n");
1056 						if (validate_challenge(cur->challenge, challenge) || cur->authenticated) {
1057 							pt_log(kLog_verbose, "Remote end authenticated successfully.\n");
1058 							//	Authentication has succeeded, so now we can proceed to handle incoming TCP data.
1059 							cur->authenticated	= 1;
1060 							cur->state			= kProto_data;
1061 							//	Insert the packet into the receive ring, to avoid confusing the	reliability mechanism.
1062 							handle_data(pkt, bytes, cur->recv_ring, &cur->recv_wait_send, &cur->recv_idx, &cur->next_remote_seq);
1063 						}
1064 						else {
1065 							pt_log(kLog_info, "Remote end failed authentication.\n");
1066 							send_termination_msg(cur, icmp_sock);
1067 							cur->should_remove				= 1;
1068 						}
1069 						return;
1070 					}
1071 				}
1072 				//	Handle close-messages for connections we know about
1073 				if (cur && pt_pkt->state == kProto_close) {
1074 					pt_log(kLog_info, "Received session close from remote peer.\n");
1075 					cur->should_remove	= 1;
1076 					return;
1077 				}
1078 				//	The proxy will ignore any other packets from the client
1079 				//	until it has been authenticated. The packet resend mechanism
1080 				//	insures that this isn't problematic.
1081 				if (type_flag == kProxy_flag && password && cur && !cur->authenticated) {
1082 					pt_log(kLog_debug, "Ignoring packet with seq-no %d - not authenticated yet.\n", pt_pkt->seq_no);
1083 					return;
1084 				}
1085 
1086 				if (cur && cur->sock) {
1087 					if (pt_pkt->state == kProto_data || pt_pkt->state == kProxy_start || pt_pkt->state == kProto_ack)
1088 						handle_data(pkt, bytes, cur->recv_ring, &cur->recv_wait_send, &cur->recv_idx, &cur->next_remote_seq);
1089 					handle_ack((uint16_t)pt_pkt->ack, cur->send_ring, &cur->send_wait_ack, 0, cur->send_idx, &cur->send_first_ack, &cur->remote_ack_val, is_pcap);
1090 					cur->last_activity		= time_as_double();
1091 				}
1092 			}
1093 		}
1094 		else
1095 			pt_log(kLog_verbose, "Ignored incoming packet.\n");
1096 	}
1097 }
1098 
1099 
1100 
1101 /*	create_and_insert_proxy_desc: Creates a new proxy descriptor, linking it into
1102 	the descriptor chain. If the sock argument is 0, the function will establish
1103 	a TCP connection to the ip and port given by dst_ip, dst_port.
1104 */
create_and_insert_proxy_desc(uint16_t id_no,uint16_t icmp_id,int sock,struct sockaddr_in * addr,uint32_t dst_ip,uint32_t dst_port,uint32_t init_state,uint32_t type)1105 proxy_desc_t*		create_and_insert_proxy_desc(uint16_t id_no, uint16_t icmp_id, int sock, struct sockaddr_in *addr, uint32_t dst_ip, uint32_t dst_port, uint32_t init_state, uint32_t type) {
1106 	proxy_desc_t	*cur;
1107 
1108 	pthread_mutex_lock(&chain_lock);
1109 	if (num_tunnels >= max_tunnels) {
1110 		pt_log(kLog_info, "Discarding incoming connection - too many tunnels! Maximum count is %d (adjust with the -m switch).\n", max_tunnels);
1111 		if (sock)
1112 			close(sock);
1113 		pthread_mutex_unlock(&chain_lock);
1114 		return 0;
1115 	}
1116 	num_tunnels++;
1117 	pthread_mutex_unlock(&chain_lock);
1118 
1119 	pt_log(kLog_debug, "Adding proxy desc to run loop. Type is %s. Will create socket: %s\n", (type == kUser_flag ? "user" : "proxy"), (sock ? "No" : "Yes"));
1120 	cur						= calloc(1, sizeof(proxy_desc_t));
1121 	cur->id_no				= id_no;
1122 	cur->dest_addr			= *addr;
1123 	cur->dst_ip				= dst_ip;
1124 	cur->dst_port			= dst_port;
1125 	cur->icmp_id			= icmp_id;
1126 	if (!sock) {
1127 		cur->sock				= socket(AF_INET, SOCK_STREAM, 0);
1128 		memset(addr, 0, sizeof(struct sockaddr_in));
1129 		addr->sin_port			= htons((uint16_t)dst_port);
1130 		addr->sin_addr.s_addr	= dst_ip;
1131 		addr->sin_family		= AF_INET;
1132 		//	Let's just assume success, shall we?
1133 		if (connect(cur->sock, (struct sockaddr*)addr, sizeof(struct sockaddr_in)) < 0) {
1134 			pt_log(kLog_error, "Connect to %s:%d failed: %s\n", inet_ntoa(*(struct in_addr*)&addr->sin_addr.s_addr), ntohs(addr->sin_port), strerror(errno));
1135 		}
1136 	}
1137 	else
1138 		cur->sock			= sock;
1139 	cur->state				= init_state;
1140 	cur->type_flag			= type;
1141 	if (cur->type_flag == kUser_flag)
1142 		cur->pkt_type		= kICMP_echo_request;
1143 	else
1144 		cur->pkt_type		= (unprivileged ? kICMP_echo_request : kICMP_echo_reply);
1145 	cur->buf				= malloc(icmp_receive_buf_len);
1146 	cur->last_activity		= time_as_double();
1147 	cur->authenticated		= 0;
1148 
1149 	pthread_mutex_lock(&chain_lock);
1150 	cur->next				= chain;
1151 	chain					= cur;
1152 	pthread_mutex_unlock(&chain_lock);
1153 	cur->xfer.bytes_in		= 0.0;
1154 	cur->xfer.bytes_out		= 0.0;
1155 	return cur;
1156 }
1157 
1158 
1159 /*	remove_proxy_desc: Removes the given proxy desc, freeing its resources.
1160 	Assumes that we hold the chain_lock.
1161 */
remove_proxy_desc(proxy_desc_t * cur,proxy_desc_t * prev)1162 void		remove_proxy_desc(proxy_desc_t *cur, proxy_desc_t *prev) {
1163 	int				i;
1164 	struct timeval	tt;
1165 
1166 	pt_log(kLog_debug, "Removing proxy descriptor.\n");
1167 	//	Get a timestamp, for making an entry in the seq_expiry_tbl
1168 	gettimeofday(&tt, 0);
1169 	seq_expiry_tbl[cur->id_no]	= tt.tv_sec+(2*kAutomatic_close_timeout);
1170 
1171 	//	Free resources associated with connection
1172 	if (cur->buf)
1173 		free(cur->buf);
1174 	cur->buf	= 0;
1175 	for (i=0;i<kPing_window_size;i++) {
1176 		if (cur->send_ring[i].pkt)
1177 			free(cur->send_ring[i].pkt);
1178 		cur->send_ring[i].pkt	= 0;
1179 		if (cur->recv_ring[i])
1180 			free(cur->recv_ring[i]);
1181 		cur->recv_ring[i]		= 0;
1182 	}
1183 	close(cur->sock);
1184 	cur->sock	= 0;
1185 
1186 	//	Keep list up-to-date
1187 	if (prev)
1188 		prev->next	= cur->next;
1189 	else
1190 		chain		= cur->next;
1191 	if (cur->challenge)
1192 		free(cur->challenge);
1193 	free(cur);
1194 	num_tunnels--;
1195 }
1196 
1197 #if kPT_add_iphdr
1198 static int ip_id_counter	= 1;
1199 #endif
1200 
1201 /*	queue_packet:
1202 	Creates an ICMP packet descriptor, and sends it. The packet descriptor is added
1203 	to the given send ring, for potential resends later on.
1204 */
queue_packet(int icmp_sock,uint8_t type,char * buf,int num_bytes,uint16_t id_no,uint16_t icmp_id,uint16_t * seq,icmp_desc_t ring[],int * insert_idx,int * await_send,uint32_t ip,uint32_t port,uint32_t state,struct sockaddr_in * dest_addr,uint16_t next_expected_seq,int * first_ack,uint16_t * ping_seq)1205 int			queue_packet(int icmp_sock, uint8_t type, char *buf, int num_bytes, uint16_t id_no, uint16_t icmp_id, uint16_t *seq, icmp_desc_t ring[], int *insert_idx, int *await_send, uint32_t ip, uint32_t port, uint32_t state, struct sockaddr_in *dest_addr, uint16_t next_expected_seq, int *first_ack, uint16_t *ping_seq) {
1206 	#if kPT_add_iphdr
1207 	ip_packet_t			*ip_pkt	= 0;
1208 	int					pkt_len	= sizeof(ip_packet_t)+sizeof(icmp_echo_packet_t)+sizeof(ping_tunnel_pkt_t)+num_bytes,
1209 	#else
1210 	int					pkt_len	= sizeof(icmp_echo_packet_t)+sizeof(ping_tunnel_pkt_t)+num_bytes,
1211 	#endif
1212 						err		= 0;
1213 	icmp_echo_packet_t	*pkt	= 0;
1214 	ping_tunnel_pkt_t	*pt_pkt	= 0;
1215 	uint16_t			ack_val	= next_expected_seq-1;
1216 
1217 
1218 	if (pkt_len % 2)
1219 		pkt_len++;
1220 
1221 	#if kPT_add_iphdr
1222 	printf("add header\n");
1223 	ip_pkt						= malloc(pkt_len);
1224 	pkt							= (icmp_echo_packet_t*)ip_pkt->data;
1225 	memset(ip_pkt, 0, sizeof(ip_packet_t));
1226 	ip_pkt->vers_ihl			= 0x45;//|(pkt_len>>2);//5;//(IPVERSION << 4) | (sizeof(ip_packet_t) >> 2);
1227 	ip_pkt->tos					= IPTOS_LOWDELAY;
1228 	ip_pkt->pkt_len				= pkt_len;
1229 	ip_pkt->id					= 0;	//kernel sets proper value htons(ip_id_counter);
1230 	ip_pkt->flags_frag_offset	= 0;
1231 	ip_pkt->ttl					= IPDEFTTL;	//	default time to live (64)
1232 	ip_pkt->proto				= 1;	//	ICMP
1233 	ip_pkt->checksum			= 0;	//	maybe the kernel helps us out..?
1234 	ip_pkt->src_ip				= htonl(0x0);	//	insert source IP address here
1235 	ip_pkt->dst_ip				= dest_addr->sin_addr.s_addr;//htonl(0x7f000001);	//	localhost..
1236 	#else
1237 	pkt						= malloc(pkt_len);
1238 	#endif
1239 
1240 	pkt->type				= type;		//	ICMP Echo request or reply
1241 	pkt->code				= 0;		//	Must be zero (non-zero requires root)
1242 	pkt->identifier			= htons(icmp_id);
1243 	pkt->seq				= htons(*ping_seq);
1244 	pkt->checksum			= 0;
1245 	(*ping_seq)++;
1246 	//	Add our information
1247 	pt_pkt					= (ping_tunnel_pkt_t*)pkt->data;
1248 	pt_pkt->magic			= htonl(kPing_tunnel_magic);
1249 	pt_pkt->dst_ip			= ip;
1250 	pt_pkt->dst_port		= htonl(port);
1251 	pt_pkt->ack				= htonl(ack_val);
1252 	pt_pkt->data_len		= htonl(num_bytes);
1253 	pt_pkt->state			= htonl(state);
1254 	pt_pkt->seq_no			= htons(*seq);
1255 	pt_pkt->id_no			= htons(id_no);
1256 	//	Copy user data
1257 	if (buf && num_bytes > 0)
1258 		memcpy(pt_pkt->data, buf, num_bytes);
1259 	#if kPT_add_iphdr
1260 	pkt->checksum			= htons(calc_icmp_checksum((uint16_t*)pkt, pkt_len-sizeof(ip_packet_t)));
1261 	ip_pkt->checksum		= htons(calc_icmp_checksum((uint16_t*)ip_pkt, sizeof(ip_packet_t)));
1262 	#else
1263 	pkt->checksum			= htons(calc_icmp_checksum((uint16_t*)pkt, pkt_len));
1264 	#endif
1265 
1266 	//	Send it!
1267 	pt_log(kLog_sendrecv, "Send: %d [%d] bytes [seq = %d] [type = %s] [ack = %d] [icmp = %d] [user = %s]\n",
1268 			pkt_len, num_bytes, *seq, state_name[state & (~kFlag_mask)], ack_val, type, ((state & kUser_flag) == kUser_flag ? "yes" : "no"));
1269 	#if kPT_add_iphdr
1270 	err						= sendto(icmp_sock, (const void*)ip_pkt, pkt_len, 0, (struct sockaddr*)dest_addr, sizeof(struct sockaddr));
1271 	#else
1272 	err						= sendto(icmp_sock, (const void*)pkt, pkt_len, 0, (struct sockaddr*)dest_addr, sizeof(struct sockaddr));
1273 	#endif
1274 	if (err < 0) {
1275 		pt_log(kLog_error, "Failed to send ICMP packet: %s\n", strerror(errno));
1276 		return -1;
1277 	}
1278 	else if (err != pkt_len)
1279 		pt_log(kLog_error, "WARNING WARNING, didn't send entire packet\n");
1280 
1281 	//	Update sequence no's and so on
1282 	#if kPT_add_iphdr
1283 	//	NOTE: Retry mechanism needs update for PT_add_ip_hdr
1284 	ring[*insert_idx].pkt			= ip_pkt;
1285 	#else
1286 	ring[*insert_idx].pkt			= pkt;
1287 	#endif
1288 	ring[*insert_idx].pkt_len		= pkt_len;
1289 	ring[*insert_idx].last_resend	= time_as_double();
1290 	ring[*insert_idx].seq_no		= *seq;
1291 	ring[*insert_idx].icmp_id		= icmp_id;
1292 	(*seq)++;
1293 	if (!ring[*first_ack].pkt)
1294 		*first_ack					= *insert_idx;
1295 	(*await_send)++;
1296 	(*insert_idx)++;
1297 	if (*insert_idx >= kPing_window_size)
1298 		*insert_idx	= 0;
1299 	return 0;
1300 }
1301 
1302 
1303 /*	send_packets:
1304 	Examines the passed-in ring, and forwards data in it over TCP.
1305 */
send_packets(forward_desc_t * ring[],int * xfer_idx,int * await_send,int * sock)1306 uint32_t	send_packets(forward_desc_t *ring[], int *xfer_idx, int *await_send, int *sock) {
1307 	forward_desc_t		*fwd_desc;
1308 	int					bytes, total = 0;
1309 
1310 	while (*await_send > 0) {
1311 		fwd_desc	= ring[*xfer_idx];
1312 		if (!fwd_desc)	//	We haven't got this packet yet..
1313 			break;
1314 		if (fwd_desc->length > 0) {
1315 			bytes		= send(*sock, &fwd_desc->data[fwd_desc->length - fwd_desc->remaining], fwd_desc->remaining, 0);
1316 			if (bytes < 0) {
1317 				printf("Weirdness.\n");
1318 				//	TODO: send close stuff
1319 				close(*sock);
1320 				*sock	= 0;
1321 				break;
1322 			}
1323 			fwd_desc->remaining	-= bytes;
1324 			total				+= bytes;
1325 		}
1326 		if (!fwd_desc->remaining) {
1327 			ring[*xfer_idx]	= 0;
1328 			free(fwd_desc);
1329 			(*xfer_idx)++;
1330 			(*await_send)--;
1331 			if (*xfer_idx >= kPing_window_size)
1332 				*xfer_idx	= 0;
1333 		}
1334 		else
1335 			break;
1336 	}
1337 	return total;
1338 }
1339 
1340 
1341 /*	handle_data:
1342 	Utility function for handling kProto_data packets, and place the data it contains
1343 	onto the passed-in receive ring.
1344 */
handle_data(icmp_echo_packet_t * pkt,int total_len,forward_desc_t * ring[],int * await_send,int * insert_idx,uint16_t * next_expected_seq)1345 void		handle_data(icmp_echo_packet_t *pkt, int total_len, forward_desc_t *ring[], int *await_send, int *insert_idx,  uint16_t *next_expected_seq) {
1346 	ping_tunnel_pkt_t	*pt_pkt			= (ping_tunnel_pkt_t*)pkt->data;
1347 	int					expected_len	= sizeof(ip_packet_t) + sizeof(icmp_echo_packet_t) + sizeof(ping_tunnel_pkt_t); // 20+8+28
1348 
1349 	/*	Place packet in the receive ring, in its proper place.
1350 		This works as follows:
1351 		-1. Packet == ack packet? Perform ack, and continue.
1352 		0. seq_no < next_remote_seq, and absolute difference is bigger than w size => discard
1353 		1. If seq_no == next_remote_seq, we have no problems; just put it in the ring.
1354 		2. If seq_no > next_remote_seq + remaining window size, discard packet. Send resend request for missing packets.
1355 		3. Else, put packet in the proper place in the ring (don't overwrite if one is already there), but don't increment next_remote_seq_no
1356 		4. If packed was not discarded, process ack info in packet.
1357 	*/
1358 	expected_len	+= pt_pkt->data_len;
1359 	expected_len	+= expected_len % 2;
1360 	if (use_udp)
1361 		expected_len	-= sizeof(ip_packet_t);
1362 	if (total_len < expected_len) {
1363 		pt_log(kLog_error, "Packet not completely received: %d Should be: %d. For some reason, this error is fatal.\n", total_len, expected_len);
1364 		pt_log(kLog_debug, "Data length: %d Total length: %d\n", pt_pkt->data_len, total_len);
1365 		//	TODO: This error isn't fatal, so it should definitely be handled in some way. We could simply discard it.
1366 		exit(0);
1367 	}
1368 	if (pt_pkt->seq_no == *next_expected_seq) {
1369 		//	hmm, what happens if this test is true?
1370 		if (!ring[*insert_idx]) {	//  && pt_pkt->state == kProto_data
1371 		//	pt_log(kLog_debug, "Queing data packet: %d\n", pt_pkt->seq_no);
1372 			ring[*insert_idx]	= create_fwd_desc(pt_pkt->seq_no, pt_pkt->data_len, pt_pkt->data);
1373 			(*await_send)++;
1374 			(*insert_idx)++;
1375 		}
1376 		else if (ring[*insert_idx])
1377 			pt_log(kLog_debug, "Dup packet?\n");
1378 
1379 		(*next_expected_seq)++;
1380 		if (*insert_idx >= kPing_window_size)
1381 			*insert_idx	= 0;
1382 		//	Check if we have already received some of the next packets
1383 		while (ring[*insert_idx]) {
1384 			if (ring[*insert_idx]->seq_no == *next_expected_seq) {
1385 				(*next_expected_seq)++;
1386 				(*insert_idx)++;
1387 				if (*insert_idx >= kPing_window_size)
1388 					*insert_idx	= 0;
1389 			}
1390 			else
1391 				break;
1392 		}
1393 	}
1394 	else {
1395 		int	r, s, d, pos;
1396 		pos	= -1;		//	If pos ends up staying -1, packet is discarded.
1397 		r	= *next_expected_seq;
1398 		s	= pt_pkt->seq_no;
1399 		d	= s - r;
1400 		if (d < 0) {	//	This packet _may_ be old, or seq_no may have wrapped around
1401 			d	= (s+0xFFFF) - r;
1402 			if (d < kPing_window_size) {
1403 				//	Counter has wrapped, so we should add this packet to the recv ring
1404 				pos	= ((*insert_idx)+d) % kPing_window_size;
1405 			}
1406 		}
1407 		else if (d < kPing_window_size)
1408 			pos	= ((*insert_idx)+d) % kPing_window_size;
1409 
1410 		if (pos != -1) {
1411 			if (!ring[pos]) {
1412 				pt_log(kLog_verbose, "Out of order. Expected: %d  Got: %d  Inserted: %d (cur = %d)\n", *next_expected_seq, pt_pkt->seq_no, pos, (*insert_idx));
1413 				ring[pos]	= create_fwd_desc(pt_pkt->seq_no, pt_pkt->data_len, pt_pkt->data);
1414 				(*await_send)++;
1415 			}
1416 		}
1417 		//else
1418 		//	pt_log(kLog_debug, "Packet discarded - outside receive window.\n");
1419 	}
1420 }
1421 
1422 
handle_ack(uint16_t seq_no,icmp_desc_t ring[],int * packets_awaiting_ack,int one_ack_only,int insert_idx,int * first_ack,uint16_t * remote_ack,int is_pcap)1423 void		handle_ack(uint16_t seq_no, icmp_desc_t ring[], int *packets_awaiting_ack, int one_ack_only, int insert_idx, int *first_ack, uint16_t *remote_ack, int is_pcap) {
1424 	int		i, j, k;
1425 	ping_tunnel_pkt_t	*pt_pkt;
1426 
1427 	if (*packets_awaiting_ack > 0) {
1428 		if (one_ack_only) {
1429 			for (i=0;i<kPing_window_size;i++) {
1430 				if (ring[i].pkt && ring[i].seq_no == seq_no && !is_pcap) {
1431 					pt_log(kLog_debug, "Received ack for only seq %d\n", seq_no);
1432 					pt_pkt	= (ping_tunnel_pkt_t*)ring[i].pkt->data;
1433 					*remote_ack	= (uint16_t)ntohl(pt_pkt->ack);	//	WARNING: We make the dangerous assumption here that packets arrive in order!
1434 					free(ring[i].pkt);
1435 					ring[i].pkt	= 0;
1436 					(*packets_awaiting_ack)--;
1437 					if (i == *first_ack) {
1438 						for (j=1;j<kPing_window_size;j++) {
1439 							k	= (i+j)%kPing_window_size;
1440 							if (ring[k].pkt) {
1441 								*first_ack	= k;
1442 								break;
1443 							}
1444 							if (k == i)	//	we have looped through everything
1445 								*first_ack	= insert_idx;
1446 							j++;
1447 						}
1448 					}
1449 					return;
1450 				}
1451 			}
1452 		}
1453 		else {
1454 			int	i, can_ack = 0, count = 0;
1455 			i	= insert_idx-1;
1456 			if (i < 0)
1457 				i	= kPing_window_size - 1;
1458 
1459 			pt_log(kLog_debug, "Received ack-series starting at seq %d\n", seq_no);
1460 			while (count < kPing_window_size) {
1461 				if (!ring[i].pkt)
1462 					break;
1463 
1464 				if (ring[i].seq_no == seq_no)
1465 					can_ack	= 1;
1466 				else if (!can_ack)
1467 					*first_ack	= i;
1468 
1469 				if (can_ack) {
1470 					free(ring[i].pkt);
1471 					ring[i].pkt	= 0;
1472 					(*packets_awaiting_ack)--;
1473 				}
1474 				i--;
1475 				if (i < 0)
1476 					i	= kPing_window_size - 1;
1477 				count++;
1478 			}
1479 		}
1480 	}
1481 //	else
1482 //		pt_log(kLog_verbose, "Dropping superfluous acknowledgement (no outstanding packets needing ack.)\n");
1483 }
1484 
1485 
1486 
create_fwd_desc(uint16_t seq_no,uint32_t data_len,char * data)1487 forward_desc_t*	create_fwd_desc(uint16_t seq_no, uint32_t data_len, char *data) {
1488 	forward_desc_t	*fwd_desc;
1489 	fwd_desc			= malloc(sizeof(forward_desc_t)+data_len);
1490 	fwd_desc->seq_no	= seq_no;
1491 	fwd_desc->length	= data_len;
1492 	fwd_desc->remaining	= data_len;
1493 	if (data_len > 0)
1494 		memcpy(fwd_desc->data, data, data_len);
1495 	return fwd_desc;
1496 }
1497 
1498 
calc_icmp_checksum(uint16_t * data,int bytes)1499 uint16_t	calc_icmp_checksum(uint16_t *data, int bytes) {
1500 	uint32_t		sum;
1501 	int				i;
1502 
1503 	sum	= 0;
1504 	for (i=0;i<bytes/2;i++) {
1505 		//	WARNING; this might be a bug, but might explain why I occasionally
1506 		//	see buggy checksums.. (added htons, that might be the correct behaviour)
1507 		sum	+= data[i];
1508 	}
1509 	sum	= (sum & 0xFFFF) + (sum >> 16);
1510 	sum	= htons(0xFFFF - sum);
1511 	return sum;
1512 }
1513 
1514 
1515 /*	generate_challenge: Generates a random challenge, incorporating the current
1516 	local timestamp to avoid replay attacks.
1517 */
generate_challenge(void)1518 challenge_t*	generate_challenge(void) {
1519 	struct timeval	tt;
1520 	challenge_t		*c;
1521 	int				i;
1522 
1523 	c	= calloc(1, sizeof(challenge_t));
1524 	gettimeofday(&tt, 0);
1525 	c->sec		= tt.tv_sec;
1526 	c->usec_rnd	= tt.tv_usec + rand();
1527 	for (i=0;i<6;i++)
1528 		c->random[i]	= rand();
1529 
1530 	return c;
1531 }
1532 
1533 
1534 /*	generate_response: Generates a response to the given challenge. The response
1535 	is generated by combining the concatenating the challenge data with the
1536 	md5 digest of the password, and then calculating the MD5 digest of the
1537 	entire buffer. The result is stored in the passed-in challenge, overwriting
1538 	the challenge data.
1539 */
generate_response(challenge_t * challenge)1540 void			generate_response(challenge_t *challenge) {
1541 	md5_byte_t	*buf;
1542 	md5_state_t	state;
1543 
1544 	buf	= malloc(sizeof(challenge_t)+kMD5_digest_size);
1545 	memcpy(buf, challenge, sizeof(challenge_t));
1546 	memcpy(&buf[sizeof(challenge_t)], password_digest, kMD5_digest_size);
1547 	memset(challenge, 0, sizeof(challenge_t));
1548 	md5_init(&state);
1549 	md5_append(&state, buf, sizeof(challenge_t)+kMD5_digest_size);
1550 	md5_finish(&state, (md5_byte_t*)challenge);
1551 }
1552 
1553 
1554 /*	validate_challenge: Checks whether a given response matches the expected
1555 	response, returning 1 if validation succeeded, and 0 otherwise. Note that
1556 	overwriting the local challenge with the challenge result is not a problem,
1557 	as the data will not be used again anyway (authentication either succeeds,
1558 	or the connection is closed down).
1559 */
validate_challenge(challenge_t * local,challenge_t * remote)1560 int				validate_challenge(challenge_t *local, challenge_t *remote) {
1561 	generate_response(local);
1562 	if (memcmp(local, remote, sizeof(challenge_t)) == 0)
1563 		return 1;
1564 	return 0;
1565 }
1566 
1567 
1568 /*	send_termination_msg: Sends two packets to the remote end, informing it that
1569 	the tunnel is being closed down.
1570 */
send_termination_msg(proxy_desc_t * cur,int icmp_sock)1571 void		send_termination_msg(proxy_desc_t *cur, int icmp_sock) {
1572 	//	Send packet twice, hoping at least one of them makes it through..
1573 	queue_packet(icmp_sock, cur->pkt_type, 0, 0, cur->id_no, cur->icmp_id, &cur->my_seq, cur->send_ring, &cur->send_idx, &cur->send_wait_ack, 0, 0, kProto_close | cur->type_flag, &cur->dest_addr, cur->next_remote_seq, &cur->send_first_ack, &cur->ping_seq);
1574 	queue_packet(icmp_sock, cur->pkt_type, 0, 0, cur->id_no, cur->icmp_id, &cur->my_seq, cur->send_ring, &cur->send_idx, &cur->send_wait_ack, 0, 0, kProto_close | cur->type_flag, &cur->dest_addr, cur->next_remote_seq, &cur->send_first_ack, &cur->ping_seq);
1575 	cur->xfer.icmp_out	+= 2;
1576 }
1577 
1578 
pt_log(int level,char * fmt,...)1579 void	pt_log(int level, char *fmt, ...) {
1580 	va_list	args;
1581 	const char *header[]	= { "[err]: ",
1582 								"[inf]: ",
1583 								"[evt]: ",
1584 								"[vbs]: ",
1585 								"[dbg]: ",
1586 								"[xfr]: " };
1587 #ifndef WIN32
1588 	int syslog_levels[] = {LOG_ERR, LOG_NOTICE, LOG_NOTICE, LOG_INFO, LOG_DEBUG, LOG_DEBUG};
1589 #endif /* !WIN32 */
1590 
1591 	if (level <= log_level) {
1592 		va_start(args, fmt);
1593 #ifndef WIN32
1594 		if (use_syslog) {
1595 			char log[255];
1596 			int header_len;
1597 			header_len = snprintf(log,sizeof(log),"%s",header[level]);
1598 			vsnprintf(log+header_len,sizeof(log)-header_len,fmt,args);
1599 			syslog(syslog_levels[level], "%s", log);
1600 		}
1601 		else
1602 #endif /* !WIN32 */
1603 			fprintf(log_file, "%s", header[level]), vfprintf(log_file, fmt, args);
1604 		va_end(args);
1605 #ifndef WIN32
1606 		if (log_file != stdout && !use_syslog)
1607 #else
1608 		if (log_file != stdout)
1609 #endif
1610 			fflush(log_file);
1611 	}
1612 }
1613 
1614 
time_as_double(void)1615 double			time_as_double(void) {
1616 	double			result;
1617 	struct timeval	tt;
1618 
1619 	gettimeofday(&tt, 0);
1620 	result		= (double)tt.tv_sec + ((double)tt.tv_usec / (double)10e5);
1621 	return result;
1622 }
1623