From d1c216b79080ac6092c362504bcc44f5d4b929c4 Mon Sep 17 00:00:00 2001 From: Toni Uhlig Date: Sun, 23 Dec 2018 13:56:39 +0100 Subject: improved error logging Signed-off-by: Toni Uhlig --- src/pkt.c | 4 +++- src/ptunnel.c | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/pkt.c b/src/pkt.c index 869cf51..bc85bc7 100644 --- a/src/pkt.c +++ b/src/pkt.c @@ -189,7 +189,9 @@ void handle_packet(char *buf, unsigned bytes, int is_pcap, struct sockaddr_in *a return; } else - pt_log(kLog_error, "Dropping duplicate proxy session request.\n"); + pt_log(kLog_error, "Dropping duplicate proxy session request " + "with ID %d and seq %d.\n", + pt_pkt->id_no, pt_pkt->seq_no); } else if (cur && pt_pkt->state == kProto_authenticate) { /* Sanity check packet length, and make sure it matches what we expect */ diff --git a/src/ptunnel.c b/src/ptunnel.c index a4c5ae5..af164c5 100644 --- a/src/ptunnel.c +++ b/src/ptunnel.c @@ -184,7 +184,7 @@ int main(int argc, char *argv[]) { if (opts.chroot) { pt_log(kLog_info, "Restricting file access to %s\n", opts.root_dir); if (-1 == chdir(opts.root_dir) || -1 == chroot(opts.root_dir)) { - pt_log(kLog_error, "%s: %s\n", opts.root_dir, strerror(errno)); + pt_log(kLog_error, "chdir/chroot `%s': %s\n", opts.root_dir, strerror(errno)); exit(1); } } @@ -210,7 +210,7 @@ int main(int argc, char *argv[]) { if (! freopen("/dev/null", "r", stdin) || ! freopen("/dev/null", "w", stdout) || ! freopen("/dev/null", "w", stderr)) - pt_log(kLog_error, "freopen: %s\n", strerror(errno)); + pt_log(kLog_error, "freopen `%s': %s\n", "/dev/null", strerror(errno)); } } } -- cgit v1.2.3 From 021b6847054cec55303efeec22a179397ce88165 Mon Sep 17 00:00:00 2001 From: Toni Uhlig Date: Mon, 24 Dec 2018 11:59:52 +0100 Subject: introduced icmp_filter for forward socket to filter out unwanted icmp messages via setsockopt Signed-off-by: Toni Uhlig --- src/ptunnel.c | 6 +++++- src/ptunnel.h | 1 + 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/ptunnel.c b/src/ptunnel.c index af164c5..f640d1b 100644 --- a/src/ptunnel.c +++ b/src/ptunnel.c @@ -62,7 +62,7 @@ #define errno GetLastError() /** Local error string storage */ static char errorstr[255]; -static char * print_last_windows_error() { +static char * print_last_windows_error() { char last_errorstr[255]; DWORD last_error = GetLastError(); @@ -388,6 +388,7 @@ void* pt_proxy(void *args) { in_addr_t *adr; #endif struct in_addr in_addr; + struct icmp_filter filt; /* Start the thread, initialize protocol and ring states. */ pt_log(kLog_debug, "Starting ping proxy..\n"); @@ -410,6 +411,9 @@ void* pt_proxy(void *args) { else { pt_log(kLog_debug, "Attempting to create privileged ICMP raw socket..\n"); fwd_sock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); + filt.data = ~((1< #ifdef HAVE_SYS_UNISTD_H #include #endif -- cgit v1.2.3 From 2c7c3b62df2661b3276253fb3d8d624d81c398a2 Mon Sep 17 00:00:00 2001 From: Toni Uhlig Date: Mon, 24 Dec 2018 12:25:15 +0100 Subject: added additional autoconf ICMP_FILTER compile check Signed-off-by: Toni Uhlig --- configure.ac | 20 ++++++++++++++++++++ src/Makefile.am | 4 ++++ src/ptunnel.c | 4 ++++ src/ptunnel.h | 2 ++ 4 files changed, 30 insertions(+) diff --git a/configure.ac b/configure.ac index f45d875..0517201 100644 --- a/configure.ac +++ b/configure.ac @@ -152,6 +152,25 @@ if test x"${selinux_enabled}" != x; then AC_SEARCH_LIBS([setcon], [selinux],,[selinux_enabled=],) fi +dnl Check for ICMP_FILTER +AC_MSG_CHECKING([for working ICMP_FILTER]) +AC_COMPILE_IFELSE( +[AC_LANG_PROGRAM([[ +#include +#include +#include +void foo() { + struct icmp_filter filt; + int sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); + filt.data = ~((1< +#endif #ifdef HAVE_SYS_UNISTD_H #include #endif -- cgit v1.2.3 From 4b33cf8cee7b048ebccfe83b27ce00e8bdd70a50 Mon Sep 17 00:00:00 2001 From: Toni Uhlig Date: Wed, 26 Dec 2018 11:46:11 +0100 Subject: replaced rand() with more "secure" random() // CID 301767 Signed-off-by: Toni Uhlig --- src/challenge.c | 5 +++-- src/ptunnel.c | 2 +- src/utils.c | 12 ++++++++++++ src/utils.h | 2 ++ 4 files changed, 18 insertions(+), 3 deletions(-) diff --git a/src/challenge.c b/src/challenge.c index 24a13f7..4f69298 100644 --- a/src/challenge.c +++ b/src/challenge.c @@ -50,6 +50,7 @@ #include "challenge.h" #include "options.h" #include "md5.h" +#include "utils.h" /* generate_challenge: Generates a random challenge, incorporating the current * local timestamp to avoid replay attacks. @@ -62,9 +63,9 @@ challenge_t* generate_challenge(void) { c = (challenge_t *) calloc(1, sizeof(challenge_t)); gettimeofday(&tt, 0); c->sec = tt.tv_sec; - c->usec_rnd = tt.tv_usec + rand(); + c->usec_rnd = tt.tv_usec + pt_random(); for (i=0;i<6;i++) - c->random[i] = rand(); + c->random[i] = pt_random(); return c; } diff --git a/src/ptunnel.c b/src/ptunnel.c index 9f435f9..1944041 100644 --- a/src/ptunnel.c +++ b/src/ptunnel.c @@ -323,7 +323,7 @@ void pt_forwarder(void) { } } addr = dest_addr; - rand_id = (uint16_t)rand(); + rand_id = (uint16_t) pt_random(); create_and_insert_proxy_desc(rand_id, rand_id, new_sock, &addr, opts.given_dst_ip, opts.given_dst_port, kProxy_start, kUser_flag); pthread_mutex_unlock(&num_threads_lock); } diff --git a/src/utils.c b/src/utils.c index 66ed4c0..12e7992 100644 --- a/src/utils.c +++ b/src/utils.c @@ -43,8 +43,12 @@ * Note that the source code is best viewed with tabs set to 4 spaces. */ +#include +#include #include #include +#include +#include #ifndef WIN32 #include @@ -142,3 +146,11 @@ void print_hexstr(unsigned char *buf, size_t siz) { free(out); } #endif + +int pt_random(void) { + struct timespec ts; + + assert(timespec_get(&ts, TIME_UTC)); + srandom(ts.tv_nsec ^ ts.tv_sec); + return random(); +} diff --git a/src/utils.h b/src/utils.h index 8afa45c..1ad2416 100644 --- a/src/utils.h +++ b/src/utils.h @@ -60,4 +60,6 @@ int host_to_addr(const char *hostname, uint32_t *result); void print_hexstr(unsigned char *buf, size_t siz); #endif +int pt_random(void); + #endif -- cgit v1.2.3 From 5236e631bb3c6f3a31c920709e3fe6c5cd579c14 Mon Sep 17 00:00:00 2001 From: Toni Uhlig Date: Wed, 26 Dec 2018 20:32:56 +0100 Subject: autoconf check for srandom()/random() or fallback to less secure srand()/rand() Signed-off-by: Toni Uhlig --- configure.ac | 6 ++++++ src/Makefile.am | 4 ++++ src/ptunnel.c | 4 ---- src/utils.c | 8 ++++++++ 4 files changed, 18 insertions(+), 4 deletions(-) diff --git a/configure.ac b/configure.ac index 0517201..b0534e0 100644 --- a/configure.ac +++ b/configure.ac @@ -145,6 +145,11 @@ if test x"${pcap_enabled}" != x -a \ [pcap_enabled=]) fi +dnl Check for more secure randomization functions +AC_CHECK_FUNCS([timespec_get srandom random], + [random_enabled=yes], + [random_enabled=]) + dnl Check for SELINUX if test x"${selinux_enabled}" != x; then AC_CHECK_HEADERS([selinux/selinux.h],, @@ -179,6 +184,7 @@ AM_CONDITIONAL([HAVE_PCAP], [test x"${pcap_enabled}" = xyes]) AM_CONDITIONAL([HAVE_SELINUX], [test x"${selinux_enabled}" = xyes]) AM_CONDITIONAL([IS_WINDOWS], [test x"${use_msw}" = xyes]) AM_CONDITIONAL([HAVE_ICMPFILTER], [test x"${with_icmp_filter}" = xyes]) +AM_CONDITIONAL([HAVE_RANDOM], [test x"${random_enabled}" = xyes]) dnl output config headers AC_CONFIG_HEADERS([src/config.h:src/config.h.in]) diff --git a/src/Makefile.am b/src/Makefile.am index 3abddda..da23fd8 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -18,6 +18,10 @@ if HAVE_ICMPFILTER ptunnel_ng_CFLAGS += -DHAVE_ICMPFILTER=1 endif +if HAVE_RANDOM +ptunnel_ng_CFLAGS += -DHAVE_RANDOM=1 +endif + ptunnel_ng_SOURCES = \ md5.c \ challenge.c \ diff --git a/src/ptunnel.c b/src/ptunnel.c index 1944041..52661ae 100644 --- a/src/ptunnel.c +++ b/src/ptunnel.c @@ -126,10 +126,6 @@ int main(int argc, char *argv[]) { } #endif /* WIN32 */ - /* Seed random generator; it'll be used in combination with a timestamp - * when generating authentication challenges. - */ - srand(time(0)); memset(opts.password_digest, 0, kMD5_digest_size); /* The seq_expiry_tbl is used to prevent the remote ends from prematurely diff --git a/src/utils.c b/src/utils.c index 12e7992..6233753 100644 --- a/src/utils.c +++ b/src/utils.c @@ -148,9 +148,17 @@ void print_hexstr(unsigned char *buf, size_t siz) { #endif int pt_random(void) { +#ifdef HAVE_RANDOM +#ifndef TIME_UTC +#define TIME_UTC 1 +#endif struct timespec ts; assert(timespec_get(&ts, TIME_UTC)); srandom(ts.tv_nsec ^ ts.tv_sec); return random(); +#else + srand(time(0)); + return rand(); +#endif } -- cgit v1.2.3 From 85f77e5953ce6a60235ea3d5af5799668183b497 Mon Sep 17 00:00:00 2001 From: Toni Uhlig Date: Wed, 26 Dec 2018 21:12:37 +0100 Subject: support BSD arc4random() if available Signed-off-by: Toni Uhlig --- configure.ac | 14 +++++++++++--- src/Makefile.am | 4 ++++ src/utils.c | 7 +++++++ 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/configure.ac b/configure.ac index b0534e0..c9ee465 100644 --- a/configure.ac +++ b/configure.ac @@ -146,9 +146,16 @@ if test x"${pcap_enabled}" != x -a \ fi dnl Check for more secure randomization functions -AC_CHECK_FUNCS([timespec_get srandom random], - [random_enabled=yes], - [random_enabled=]) +AC_CHECK_HEADERS([bsd/stdlib.h],, [random_enabled=yes]) +AC_SEARCH_LIBS([arc4random], [bsd],,,) +AC_CHECK_FUNCS([arc4random], [random_enabled=],) +if test x"${random_enabled}" != x; then + AC_CHECK_FUNCS([timespec_get srandom random], + [random_enabled=yes], + [random_enabled=]) +else + arc4random_enabled=yes +fi dnl Check for SELINUX if test x"${selinux_enabled}" != x; then @@ -185,6 +192,7 @@ AM_CONDITIONAL([HAVE_SELINUX], [test x"${selinux_enabled}" = xyes]) AM_CONDITIONAL([IS_WINDOWS], [test x"${use_msw}" = xyes]) AM_CONDITIONAL([HAVE_ICMPFILTER], [test x"${with_icmp_filter}" = xyes]) AM_CONDITIONAL([HAVE_RANDOM], [test x"${random_enabled}" = xyes]) +AM_CONDITIONAL([HAVE_ARC4RANDOM], [test x"${arc4random_enabled}" = xyes]) dnl output config headers AC_CONFIG_HEADERS([src/config.h:src/config.h.in]) diff --git a/src/Makefile.am b/src/Makefile.am index da23fd8..1d161a2 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -18,9 +18,13 @@ if HAVE_ICMPFILTER ptunnel_ng_CFLAGS += -DHAVE_ICMPFILTER=1 endif +if HAVE_ARC4RANDOM +ptunnel_ng_CFLAGS += -DHAVE_ARC4RANDOM=1 +else if HAVE_RANDOM ptunnel_ng_CFLAGS += -DHAVE_RANDOM=1 endif +endif ptunnel_ng_SOURCES = \ md5.c \ diff --git a/src/utils.c b/src/utils.c index 6233753..10e8182 100644 --- a/src/utils.c +++ b/src/utils.c @@ -49,6 +49,9 @@ #include #include #include +#ifdef HAVE_ARC4RANDOM +#include +#endif #ifndef WIN32 #include @@ -148,6 +151,9 @@ void print_hexstr(unsigned char *buf, size_t siz) { #endif int pt_random(void) { +#ifdef HAVE_ARC4RANDOM + return arc4random(); +#else #ifdef HAVE_RANDOM #ifndef TIME_UTC #define TIME_UTC 1 @@ -161,4 +167,5 @@ int pt_random(void) { srand(time(0)); return rand(); #endif +#endif } -- cgit v1.2.3 From 5bd360af054f4cf33c09508d1a209e2440b75d2c Mon Sep 17 00:00:00 2001 From: Toni Uhlig Date: Wed, 26 Dec 2018 21:26:48 +0100 Subject: travis-ci install libbsd-dev to have arc4random() available Signed-off-by: Toni Uhlig --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 7e7d6ad..e9a181d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,7 +2,7 @@ language: c before_install: - sudo apt-get -qq update - sudo apt-get install -y git debhelper fakeroot -- sudo apt-get install -y libpcap-dev libselinux1-dev +- sudo apt-get install -y libpcap-dev libselinux1-dev libbsd-dev - sudo apt-get install -y binutils-mingw-w64-i686 gcc-mingw-w64 mingw-w64-i686-dev mingw-w64-common - sudo apt-get install -y autoconf automake dh-autoreconf -- cgit v1.2.3 From b6afe103c2e1ff213e3510fd690c362644e2c7a1 Mon Sep 17 00:00:00 2001 From: Toni Uhlig Date: Thu, 27 Dec 2018 00:17:40 +0100 Subject: set icmp_filter according forwarder/proxy Signed-off-by: Toni Uhlig --- src/ptunnel.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/ptunnel.c b/src/ptunnel.c index 52661ae..aa50883 100644 --- a/src/ptunnel.c +++ b/src/ptunnel.c @@ -402,17 +402,23 @@ void* pt_proxy(void *args) { } } else { - if (opts.unprivileged) { + if (opts.unprivileged) + { pt_log(kLog_debug, "Attempting to create unprivileged ICMP datagram socket..\n"); fwd_sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_ICMP); - } - else { + } else { pt_log(kLog_debug, "Attempting to create privileged ICMP raw socket..\n"); fwd_sock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); #ifdef HAVE_ICMPFILTER - filt.data = ~((1<= 0 && + setsockopt(fwd_sock, SOL_RAW, ICMP_FILTER, &filt, sizeof filt) == -1) + { pt_log(kLog_error, "setockopt for ICMP_FILTER: %s\n", strerror(errno)); + } #endif } if (fwd_sock < 0) { -- cgit v1.2.3 From d9d7a33d2e2f1627845001b98152cd05b5781ab3 Mon Sep 17 00:00:00 2001 From: Toni Uhlig Date: Tue, 8 Jan 2019 09:43:33 +0100 Subject: copyright update Signed-off-by: Toni Uhlig --- COPYING | 2 +- README | 2 +- README.md | 2 +- debian/copyright | 2 +- src/challenge.c | 2 +- src/challenge.h | 2 +- src/options.c | 2 +- src/options.h | 2 +- src/pconfig.h | 2 +- src/pdesc.c | 2 +- src/pdesc.h | 2 +- src/pkt.c | 2 +- src/pkt.h | 2 +- src/ptunnel.c | 4 ++-- src/utils.c | 2 +- src/utils.h | 2 +- 16 files changed, 17 insertions(+), 17 deletions(-) diff --git a/COPYING b/COPYING index 8b4cb53..6918db2 100644 --- a/COPYING +++ b/COPYING @@ -1,4 +1,4 @@ -Copyright (c) 2017, Toni Uhlig +Copyright (c) 2017-2019, Toni Uhlig All rights reserved. Redistribution and use in source and binary forms, with or without diff --git a/README b/README index 97cd0d0..1a0712e 100644 --- a/README +++ b/README @@ -128,6 +128,6 @@ Daniel Stoedle et al. License ------- -Ping Tunnel NG is Copyright (c) 2017, Toni Uhlig , +Ping Tunnel NG is Copyright (c) 2017-2019, Toni Uhlig , All rights reserved. Ping Tunnel NG is licensed under the BSD License. Please see the COPYING file for details. diff --git a/README.md b/README.md index 34c00c1..5d48190 100644 --- a/README.md +++ b/README.md @@ -144,7 +144,7 @@ Daniel Stoedle et al. ## License ``` -Ping Tunnel NG is Copyright (c) 2017, Toni Uhlig , +Ping Tunnel NG is Copyright (c) 2017-2019, Toni Uhlig , All rights reserved. Ping Tunnel NG is licensed under the BSD License. Please see the COPYING file for details. ``` diff --git a/debian/copyright b/debian/copyright index b0e21c4..855cf53 100644 --- a/debian/copyright +++ b/debian/copyright @@ -3,7 +3,7 @@ Upstream-Name: ptunnel Source: http://www.cs.uit.no/~daniels/PingTunnel/index.html Files: * -Copyright: Copyright 2017 Toni Uhlig +Copyright: Copyright 2017-2019 Toni Uhlig License: BSD-3-Clause Files: md5.* diff --git a/src/challenge.c b/src/challenge.c index 4f69298..f269313 100644 --- a/src/challenge.c +++ b/src/challenge.c @@ -5,7 +5,7 @@ * Copyright (c) 2004-2011, Daniel Stoedle , * Yellow Lemon Software. All rights reserved. * - * Copyright (c) 2017 Toni Uhlig + * Copyright (c) 2017-2019, Toni Uhlig * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: diff --git a/src/challenge.h b/src/challenge.h index 035a97e..18495cf 100644 --- a/src/challenge.h +++ b/src/challenge.h @@ -5,7 +5,7 @@ * Copyright (c) 2004-2011, Daniel Stoedle , * Yellow Lemon Software. All rights reserved. * - * Copyright (c) 2017 Toni Uhlig + * Copyright (c) 2017-2019, Toni Uhlig * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: diff --git a/src/options.c b/src/options.c index beecd39..4ae434f 100644 --- a/src/options.c +++ b/src/options.c @@ -2,7 +2,7 @@ * options.c * ptunnel is licensed under the BSD license: * - * Copyright (c) 2017 Toni Uhlig + * Copyright (c) 2017-2019, Toni Uhlig * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: diff --git a/src/options.h b/src/options.h index 3c42a19..176620a 100644 --- a/src/options.h +++ b/src/options.h @@ -2,7 +2,7 @@ * options.h * ptunnel is licensed under the BSD license: * - * Copyright (c) 2017 Toni Uhlig + * Copyright (c) 2017-2019, Toni Uhlig * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: diff --git a/src/pconfig.h b/src/pconfig.h index c85df14..6be141e 100644 --- a/src/pconfig.h +++ b/src/pconfig.h @@ -5,7 +5,7 @@ * Copyright (c) 2004-2011, Daniel Stoedle , * Yellow Lemon Software. All rights reserved. * - * Copyright (c) 2017 Toni Uhlig + * Copyright (c) 2017-2019, Toni Uhlig * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: diff --git a/src/pdesc.c b/src/pdesc.c index 906f35c..5ba2003 100644 --- a/src/pdesc.c +++ b/src/pdesc.c @@ -5,7 +5,7 @@ * Copyright (c) 2004-2011, Daniel Stoedle , * Yellow Lemon Software. All rights reserved. * - * Copyright (c) 2017 Toni Uhlig + * Copyright (c) 2017-2019, Toni Uhlig * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: diff --git a/src/pdesc.h b/src/pdesc.h index 35147db..d0767aa 100644 --- a/src/pdesc.h +++ b/src/pdesc.h @@ -5,7 +5,7 @@ * Copyright (c) 2004-2011, Daniel Stoedle , * Yellow Lemon Software. All rights reserved. * - * Copyright (c) 2017 Toni Uhlig + * Copyright (c) 2017-2019, Toni Uhlig * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: diff --git a/src/pkt.c b/src/pkt.c index bc85bc7..06dfd91 100644 --- a/src/pkt.c +++ b/src/pkt.c @@ -5,7 +5,7 @@ * Copyright (c) 2004-2011, Daniel Stoedle , * Yellow Lemon Software. All rights reserved. * - * Copyright (c) 2017 Toni Uhlig + * Copyright (c) 2017-2019, Toni Uhlig * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: diff --git a/src/pkt.h b/src/pkt.h index 9668d97..338bc65 100644 --- a/src/pkt.h +++ b/src/pkt.h @@ -5,7 +5,7 @@ * Copyright (c) 2004-2011, Daniel Stoedle , * Yellow Lemon Software. All rights reserved. * - * Copyright (c) 2017 Toni Uhlig + * Copyright (c) 2017-2019, Toni Uhlig * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: diff --git a/src/ptunnel.c b/src/ptunnel.c index aa50883..8fdf7a8 100644 --- a/src/ptunnel.c +++ b/src/ptunnel.c @@ -5,7 +5,7 @@ * Copyright (c) 2004-2011, Daniel Stoedle , * Yellow Lemon Software. All rights reserved. * - * Copyright (c) 2017 Toni Uhlig + * Copyright (c) 2017-2019, Toni Uhlig * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -150,7 +150,7 @@ int main(int argc, char *argv[]) { #endif pt_log(kLog_info, "Starting %s.\n", PACKAGE_STRING); pt_log(kLog_info, "(c) 2004-2011 Daniel Stoedle, \n"); - pt_log(kLog_info, "(c) 2017 Toni Uhlig, \n"); + pt_log(kLog_info, "(c) 2017-2019 Toni Uhlig, \n"); #ifdef WIN32 pt_log(kLog_info, "Windows version by Mike Miller, \n"); #else diff --git a/src/utils.c b/src/utils.c index 10e8182..462d688 100644 --- a/src/utils.c +++ b/src/utils.c @@ -5,7 +5,7 @@ * Copyright (c) 2004-2011, Daniel Stoedle , * Yellow Lemon Software. All rights reserved. * - * Copyright (c) 2017 Toni Uhlig + * Copyright (c) 2017-2019, Toni Uhlig * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: diff --git a/src/utils.h b/src/utils.h index 1ad2416..0796848 100644 --- a/src/utils.h +++ b/src/utils.h @@ -5,7 +5,7 @@ * Copyright (c) 2004-2011, Daniel Stoedle , * Yellow Lemon Software. All rights reserved. * - * Copyright (c) 2017 Toni Uhlig + * Copyright (c) 2017-2019, Toni Uhlig * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: -- cgit v1.2.3 From bf54c7ed64a17693762a9db4fbaa3765d182a501 Mon Sep 17 00:00:00 2001 From: elnerd Date: Wed, 16 Jan 2019 20:40:58 +0100 Subject: fixed some bugs that can lead to remove segfaults --- src/pdesc.c | 2 +- src/pkt.c | 12 +++++++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/pdesc.c b/src/pdesc.c index 5ba2003..51fa3ab 100644 --- a/src/pdesc.c +++ b/src/pdesc.c @@ -56,7 +56,7 @@ * the descriptor chain. If the sock argument is 0, the function will establish * a TCP connection to the ip and port given by dst_ip, dst_port. */ -proxy_desc_t* create_and_insert_proxy_desc(uint16_t id_no, uint16_t icmp_id, +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) { diff --git a/src/pkt.c b/src/pkt.c index 06dfd91..9ba2181 100644 --- a/src/pkt.c +++ b/src/pkt.c @@ -124,6 +124,10 @@ void handle_packet(char *buf, unsigned bytes, int is_pcap, struct sockaddr_in *a pkt_flag = pt_pkt->state & kFlag_mask; pt_pkt->state &= ~kFlag_mask; + if (pt_pkt->state > (kNum_proto_types-1)) { + pt_log(kLog_error, "Dropping packet with invalid state.\n"); + return; + } pt_log(kLog_sendrecv, "Recv: %d [%d] bytes " "[seq = %d] [type = %s] " "[ack = %d] [icmp = %d] " @@ -166,14 +170,20 @@ void handle_packet(char *buf, unsigned bytes, int is_pcap, struct sockaddr_in *a else init_state = kProto_data; - cur = create_and_insert_proxy_desc(pt_pkt->id_no, pkt->identifier, 0, + cur = (proxy_desc_t*) 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); + if (!cur) { + /* if failed, abort. Logging is done in create_insert_proxy_desc */ + pt_log(kLog_info, "failed to create proxy descriptor\n"); + return; + } if (init_state == kProto_authenticate) { pt_log(kLog_debug, "Sending authentication challenge..\n"); /* Send challenge */ cur->challenge = generate_challenge(); + pt_log(kLog_debug, "Challenge generated\n"); memcpy(cur->buf, cur->challenge, sizeof(challenge_t)); queue_packet(icmp_sock, cur->pkt_type, cur->buf, sizeof(challenge_t), cur->id_no, -- cgit v1.2.3 From 5850d4218e7199c80499217a6f9faeb967f69c08 Mon Sep 17 00:00:00 2001 From: dev0 Date: Wed, 16 Jan 2019 23:13:47 +0100 Subject: cosmetics ty very much @elnerd --- src/pkt.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/pkt.c b/src/pkt.c index 9ba2181..d446ffd 100644 --- a/src/pkt.c +++ b/src/pkt.c @@ -170,20 +170,19 @@ void handle_packet(char *buf, unsigned bytes, int is_pcap, struct sockaddr_in *a else init_state = kProto_data; - cur = (proxy_desc_t*) create_and_insert_proxy_desc(pt_pkt->id_no, pkt->identifier, 0, + cur = (proxy_desc_t *) 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); if (!cur) { /* if failed, abort. Logging is done in create_insert_proxy_desc */ - pt_log(kLog_info, "failed to create proxy descriptor\n"); + pt_log(kLog_error, "Failed to create proxy descriptor!\n"); return; } if (init_state == kProto_authenticate) { pt_log(kLog_debug, "Sending authentication challenge..\n"); /* Send challenge */ cur->challenge = generate_challenge(); - pt_log(kLog_debug, "Challenge generated\n"); memcpy(cur->buf, cur->challenge, sizeof(challenge_t)); queue_packet(icmp_sock, cur->pkt_type, cur->buf, sizeof(challenge_t), cur->id_no, -- cgit v1.2.3 From 8c15ce9fd2c753fc21b5f71c8ab81fd145180f7f Mon Sep 17 00:00:00 2001 From: Toni Uhlig Date: Fri, 18 Jan 2019 18:11:04 +0100 Subject: python based fuzzing script to detect security related issues (work-in-progress) Signed-off-by: Toni Uhlig --- test/fuzzer.py | 275 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 275 insertions(+) create mode 100755 test/fuzzer.py diff --git a/test/fuzzer.py b/test/fuzzer.py new file mode 100755 index 0000000..3778952 --- /dev/null +++ b/test/fuzzer.py @@ -0,0 +1,275 @@ +#!/usr/bin/env python2.7 +""" + This is a python ICMP/Ping script, + which can be used to fuzz the proxy/forwarder + to detect security issues. + + This script was originally taken from: + https://gist.githubusercontent.com/pklaus/856268/raw/a4e295d0dbd1140bddc90616e93ab3b19718a87b/ping.py +""" + +import os +import time +import socket +import struct +import select +import random +import asyncore + +UINT_MAX=4294967295 +USHORT_MAX=65535 +ICMP_ECHO_REQUEST = 8 +ICMP_PROTO = socket.getprotobyname('icmp') +ERROR_DESCR = { + 1: ' - Note that ICMP messages can only be ' + 'sent from processes running as root.', + 10013: ' - Note that ICMP messages can only be sent by' + ' users or processes with administrator rights.' +} + +__all__ = ['create_packet', 'do_one', 'verbose_ping', 'PingQuery', + 'multi_ping_query'] + + +def checksum(source_string): + # I'm not too confident that this is right but testing seems to + # suggest that it gives the same answers as in_cksum in ping.c. + sum = 0 + count_to = (len(source_string) / 2) * 2 + count = 0 + while count < count_to: + this_val = ord(source_string[count + 1])*256+ord(source_string[count]) + sum = sum + this_val + sum = sum & 0xffffffff # Necessary? + count = count + 2 + if count_to < len(source_string): + sum = sum + ord(source_string[len(source_string) - 1]) + sum = sum & 0xffffffff # Necessary? + sum = (sum >> 16) + (sum & 0xffff) + sum = sum + (sum >> 16) + answer = ~sum + answer = answer & 0xffff + # Swap bytes. Bugger me if I know why. + answer = answer >> 8 | (answer << 8 & 0xff00) + return answer + + +def create_packet(id, data=None): + """Create a new echo request packet based on the given "id".""" + # Header is type (8), code (8), checksum (16), id (16), sequence (16) + header = struct.pack('bbHHh', ICMP_ECHO_REQUEST, 0, 0, id, 1) + if data is None: + data = 192 * 'Q' + # Calculate the checksum on the data and the dummy header. + my_checksum = checksum(header + data) + # Now that we have the right checksum, we put that in. It's just easier + # to make up a new header than to stuff it into the dummy. + header = struct.pack('bbHHh', ICMP_ECHO_REQUEST, 0, + socket.htons(my_checksum), id, 1) + return header + data + + +def do_one(dest_addr, timeout=1, data=None): + """ + Sends one ping to the given "dest_addr" which can be an ip or hostname. + "timeout" can be any integer or float except negatives and zero. + + Returns either the delay (in seconds) or None on timeout and an invalid + address, respectively. + + """ + try: + my_socket = socket.socket(socket.AF_INET, socket.SOCK_RAW, ICMP_PROTO) + except socket.error as e: + if e.errno in ERROR_DESCR: + # Operation not permitted + raise socket.error(''.join((e.args[1], ERROR_DESCR[e.errno]))) + raise # raise the original error + try: + host = socket.gethostbyname(dest_addr) + except socket.gaierror: + return + # Maximum for an unsigned short int c object counts to 65535 so + # we have to sure that our packet id is not greater than that. + packet_id = int((id(timeout) * random.random()) % 65535) + packet = create_packet(packet_id, data) + while packet: + # The icmp protocol does not use a port, but the function + # below expects it, so we just give it a dummy port. + sent = my_socket.sendto(packet, (dest_addr, 1)) + packet = packet[sent:] + delay = receive_ping(my_socket, packet_id, time.time(), timeout) + my_socket.close() + return delay + + +def receive_ping(my_socket, packet_id, time_sent, timeout): + # Receive the ping from the socket. + time_left = timeout + while True: + started_select = time.time() + ready = select.select([my_socket], [], [], time_left) + how_long_in_select = time.time() - started_select + if ready[0] == []: # Timeout + return + time_received = time.time() + rec_packet, addr = my_socket.recvfrom(1024) + icmp_header = rec_packet[20:28] + type, code, checksum, p_id, sequence = struct.unpack( + 'bbHHh', icmp_header) + if p_id == packet_id: + return time_received - time_sent + time_left -= time_received - time_sent + if time_left <= 0: + return + + +def verbose_ping(dest_addr, data=None, timeout=2, count=4): + """ + Sends one ping to the given "dest_addr" which can be an ip or hostname. + + "timeout" can be any integer or float except negatives and zero. + "count" specifies how many pings will be sent. + + Displays the result on the screen. + + """ + for i in range(count): + print('ping {}...'.format(dest_addr)) + delay = do_one(dest_addr, timeout, data) + if delay == None: + print('failed. (Timeout within {} seconds.)'.format(timeout)) + else: + delay = round(delay * 1000.0, 4) + print('get ping in {} milliseconds.'.format(delay)) + print('') + + +class PingQuery(asyncore.dispatcher): + def __init__(self, host, p_id, timeout=0.5, ignore_errors=False, data=None): + """ + Derived class from "asyncore.dispatcher" for sending and + receiving an icmp echo request/reply. + + Usually this class is used in conjunction with the "loop" + function of asyncore. + + Once the loop is over, you can retrieve the results with + the "get_result" method. Assignment is possible through + the "get_host" method. + + "host" represents the address under which the server can be reached. + "timeout" is the interval which the host gets granted for its reply. + "p_id" must be any unique integer or float except negatives and zeros. + + If "ignore_errors" is True, the default behaviour of asyncore + will be overwritten with a function which does just nothing. + + """ + asyncore.dispatcher.__init__(self) + try: + self.create_socket(socket.AF_INET, socket.SOCK_RAW, ICMP_CODE) + except socket.error as e: + if e.errno in ERROR_DESCR: + # Operation not permitted + raise socket.error(''.join((e.args[1], ERROR_DESCR[e.errno]))) + raise # raise the original error + self.time_received = 0 + self.time_sent = 0 + self.timeout = timeout + # Maximum for an unsigned short int c object counts to 65535 so + # we have to sure that our packet id is not greater than that. + self.packet_id = int((id(timeout) / p_id) % 65535) + self.host = host + self.packet = create_packet(self.packet_id, data) + if ignore_errors: + # If it does not care whether an error occured or not. + self.handle_error = self.do_not_handle_errors + self.handle_expt = self.do_not_handle_errors + + def writable(self): + return self.time_sent == 0 + + def handle_write(self): + self.time_sent = time.time() + while self.packet: + # The icmp protocol does not use a port, but the function + # below expects it, so we just give it a dummy port. + sent = self.sendto(self.packet, (self.host, 1)) + self.packet = self.packet[sent:] + + def readable(self): + # As long as we did not sent anything, the channel has to be left open. + if (not self.writable() + # Once we sent something, we should periodically check if the reply + # timed out. + and self.timeout < (time.time() - self.time_sent)): + self.close() + return False + # If the channel should not be closed, we do not want to read something + # until we did not sent anything. + return not self.writable() + + def handle_read(self): + read_time = time.time() + packet, addr = self.recvfrom(1024) + header = packet[20:28] + type, code, checksum, p_id, sequence = struct.unpack("bbHHh", header) + if p_id == self.packet_id: + # This comparison is necessary because winsocks do not only get + # the replies for their own sent packets. + self.time_received = read_time + self.close() + + def get_result(self): + """Return the ping delay if possible, otherwise None.""" + if self.time_received > 0: + return self.time_received - self.time_sent + + def get_host(self): + """Return the host where to the request has or should been sent.""" + return self.host + + def do_not_handle_errors(self): + # Just a dummy handler to stop traceback printing, if desired. + pass + + def create_socket(self, family, type, proto): + # Overwritten, because the original does not support the "proto" arg. + sock = socket.socket(family, type, proto) + sock.setblocking(0) + self.set_socket(sock) + # Part of the original but is not used. (at least at python 2.7) + # Copied for possible compatiblity reasons. + self.family_and_type = family, type + + # If the following methods would not be there, we would see some very + # "useful" warnings from asyncore, maybe. But we do not want to, or do we? + def handle_connect(self): + pass + + def handle_accept(self): + pass + + def handle_close(self): + self.close() + + + +if __name__ == '__main__': + # Testing + while True: + pt_pkt = struct.pack('!IIIIIIHHs', + 0xdeadc0de, # magic + random.randint(0, UINT_MAX), # ip + random.randint(0, UINT_MAX), # port + random.randint(0, 4), # state + random.randint(0, UINT_MAX), # ack + random.randint(0, UINT_MAX), # length + random.randint(0, USHORT_MAX), # seq + random.randint(0, USHORT_MAX), # rsv + '2222' # data.. + ) + + verbose_ping('127.0.0.1', pt_pkt, 1, 1) + random.seed(time.clock()) -- cgit v1.2.3 From 44b32c31eb575ec20b8bb2f0b1642c78d556cb91 Mon Sep 17 00:00:00 2001 From: Toni Uhlig Date: Mon, 21 Jan 2019 17:00:35 +0100 Subject: fuzzer.py: build pt icmp pkt Signed-off-by: Toni Uhlig --- test/fuzzer.py | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/test/fuzzer.py b/test/fuzzer.py index 3778952..766122c 100755 --- a/test/fuzzer.py +++ b/test/fuzzer.py @@ -254,22 +254,25 @@ class PingQuery(asyncore.dispatcher): def handle_close(self): self.close() +def build_pt_pkt(ip, port, state, ack, seq, rsv, data): + if type(ip) is int: + dst_ip = ip + elif type(ip) is str: + dst_ip = struct.unpack(' Date: Thu, 24 Jan 2019 14:17:04 +0100 Subject: 1.32-release Signed-off-by: Toni Uhlig --- ChangeLog | 7 +++++++ configure.ac | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index fc40604..4c82b5c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,13 @@ PingTunnel-NG Changelog ======================= +1.32 - 24. January 2019 +- improved error logging +- introduced icmp_filter via setsockopt to filter unwanted icmp messages +- more "secure" random number generator +- fixed NULL deref and invalid memory access by elnerd +(https://github.com/elnerd) PoC: https://www.securityfocus.com/bid/54627/info + 1.31 - 03. December 2018 - added Android build support (requires a root'ed device!) - fixed ArchLinux PKGBUILD/AUR diff --git a/configure.ac b/configure.ac index c9ee465..eeb6634 100644 --- a/configure.ac +++ b/configure.ac @@ -1,5 +1,5 @@ AC_PREREQ(2.69) -AC_INIT([ptunnel-ng], [1.31], [], [], []) +AC_INIT([ptunnel-ng], [1.32], [], [], []) AC_CONFIG_SRCDIR([src/config.h.in]) AC_CONFIG_FILES([Makefile src/Makefile]) -- cgit v1.2.3