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