pax_global_header00006660000000000000000000000064146045272640014524gustar00rootroot0000000000000052 comment=b1baa742c0e667b7d4e4965f74ae6f1740f89837 ptunnel-ng-1.43/000077500000000000000000000000001460452726400135425ustar00rootroot00000000000000ptunnel-ng-1.43/.clang-format000066400000000000000000000054071460452726400161230ustar00rootroot00000000000000Language: Cpp BasedOnStyle : LLVM Standard : Cpp03 # BasedOnStyle: LLVM BraceWrapping: AfterClass: false AfterControlStatement: false AfterEnum: false AfterFunction: false AfterNamespace: false AfterObjCDeclaration: false AfterStruct: false AfterUnion: false BeforeCatch: false BeforeElse: false IndentBraces: true ConstructorInitializerIndentWidth: 4 AlignEscapedNewlinesLeft: false AlignTrailingComments: true AllowShortBlocksOnASingleLine: true AllowShortCaseLabelsOnASingleLine: false AllowShortIfStatementsOnASingleLine: false AllowShortLoopsOnASingleLine: false AlwaysBreakAfterDefinitionReturnType: false AlwaysBreakTemplateDeclarations: true AlwaysBreakBeforeMultilineStrings: true BreakBeforeTernaryOperators: true BreakConstructorInitializersBeforeComma: false ColumnLimit: 120 ConstructorInitializerAllOnOneLineOrOnePerLine: true DerivePointerAlignment: false ExperimentalAutoDetectBinPacking: false IndentCaseLabels: true IndentWrappedFunctionNames: false IndentFunctionDeclarationAfterType: false MaxEmptyLinesToKeep: 1 KeepEmptyLinesAtTheStartOfBlocks: true NamespaceIndentation: None ObjCSpaceAfterProperty: false ObjCSpaceBeforeProtocolList: false PenaltyExcessCharacter : 500 PenaltyReturnTypeOnItsOwnLine : 120 PenaltyBreakBeforeFirstCallParameter : 100 PenaltyBreakString : 20 PenaltyBreakComment : 10 PenaltyBreakFirstLessLess : 0 SpacesBeforeTrailingComments: 1 Cpp11BracedListStyle: true IndentWidth: 4 TabWidth: 4 UseTab: Never BreakBeforeBraces: Linux SpacesInParentheses: false SpacesInSquareBrackets: false SpacesInAngles : false SpaceInEmptyParentheses : false SpacesInCStyleCastParentheses : false SpaceAfterCStyleCast : false SpacesInContainerLiterals : true SpaceBeforeAssignmentOperators : true ContinuationIndentWidth : 4 SpaceBeforeParens : ControlStatements DisableFormat : false AccessModifierOffset : -4 PointerAlignment : Middle AlignAfterOpenBracket : Align AllowAllParametersOfDeclarationOnNextLine : true BinPackArguments : false BinPackParameters : false AlignOperands : true AlignConsecutiveAssignments : false AllowShortFunctionsOnASingleLine : None BreakBeforeBinaryOperators : None AlwaysBreakAfterReturnType : None SortIncludes : false ptunnel-ng-1.43/.dockerignore000066400000000000000000000000351460452726400162140ustar00rootroot00000000000000.dockerignore .git Dockerfileptunnel-ng-1.43/.gitlab-ci.yml000066400000000000000000000145611460452726400162050ustar00rootroot00000000000000image: debian:stable-slim stages: - build - test before_script: - test ! -r /etc/debian_version || apt-get -qq update - test ! -r /etc/debian_version || apt-get install -y git debhelper dpkg-dev build-essential fakeroot flawfinder wget unzip - test ! -r /etc/debian_version || apt-get install -y libpcap-dev libselinux1-dev - test ! -r /etc/debian_version || apt-get install -y binutils-mingw-w64-i686 gcc-mingw-w64 mingw-w64-i686-dev binutils-mingw-w64-x86-64 mingw-w64-x86-64-dev mingw-w64-common clang - test ! -r /etc/debian_version || apt-get install -y valgrind sudo netcat-openbsd - test ! -r /etc/debian_version || apt-get install -y autoconf automake dh-autoreconf - test ! -r /etc/arch-release || pacman -Syu --noconfirm - test ! -r /etc/arch-release || pacman -S --noconfirm binutils gcc base-devel git - test ! -r /etc/arch-release || pacman -S --noconfirm valgrind sudo - mkdir -p ./deploy/gcc ./deploy/i686-w64-mingw32-winpcap ./deploy/i686-w64-mingw32-npcap ./deploy/clang ./deploy/android28-clang build: script: - autoreconf -fi - ./configure --enable-option-checking=fatal --prefix=/ - mv config.log deploy/config-default.log - make install CFLAGS='-Werror' DESTDIR="$(realpath ./deploy/gcc)" V=s - make dist - cp ptunnel-ng-*.tar.gz ./deploy/ stage: build artifacts: paths: - deploy/ when: always build-sanitizer-asserts: script: - autoreconf -fi - ./configure --enable-option-checking=fatal --prefix=/ --enable-sanitizer --enable-asserts - mv config.log deploy/config-sanitizer-assert.log - make install CFLAGS='-Werror' DESTDIR="$(realpath ./deploy/gcc-sanitizer-asserts)" V=s stage: build artifacts: paths: - deploy/ when: always build-debian: script: - dpkg-buildpackage -b -us -uc - mv config.log deploy/config-debian.log - ls -alh .. - mkdir -p deploy/debian - mv -v ../ptunnel-ng-dbgsym_* ../ptunnel-ng_* deploy/debian/ stage: build artifacts: paths: - deploy/ when: always build-archlinux: image: archlinux/base script: - useradd builduser -m - passwd -d builduser - chown -R builduser . - su -m builduser bash -c 'makepkg' - su -m builduser bash -c 'makepkg -p PKGBUILD.dev --skipchecksums' - ls -alh . - mkdir deploy/archlinux - mv -v ptunnel-ng-*.pkg.tar.zst deploy/archlinux/ stage: build artifacts: paths: - deploy/ when: always build-mingw: script: # print mingw-gcc versions and check if the required define is set - i686-w64-mingw32-gcc --version - i686-w64-mingw32-gcc -dM -E - < /dev/null | grep -E '^#define WIN32 1$' - x86_64-w64-mingw32-gcc --version - x86_64-w64-mingw32-gcc -dM -E - < /dev/null | grep -E '^#define WIN32 1$' # the actual build - autoreconf -fi # i686-w64-mingw32 - ./configure --enable-option-checking=fatal --prefix=/ --host=i686-w64-mingw32 - mv config.log deploy/config-mingw-i686.log - make install CFLAGS='-Werror' DESTDIR="$(realpath ./deploy/i686-w64-mingw32-winpcap)" V=s - make clean - ./configure --enable-option-checking=fatal --prefix=/ --host=i686-w64-mingw32 --enable-npcap - mv config.log deploy/config-mingw-i686-npcap.log - make install CFLAGS='-Werror' DESTDIR="$(realpath ./deploy/i686-w64-mingw32-npcap)" V=s - make clean # x86-64-w64-mingw32 - ./configure --enable-option-checking=fatal --prefix=/ --host=x86_64-w64-mingw32 - mv config.log deploy/config-mingw-x86_64.log - make install CFLAGS='-Werror' DESTDIR="$(realpath ./deploy/x86_64-w64-mingw32-winpcap)" V=s - make clean - ./configure --enable-option-checking=fatal --prefix=/ --host=x86_64-w64-mingw32 --enable-npcap - mv config.log deploy/config-mingw-x86_64-npcap.log - make install CFLAGS='-Werror' DESTDIR="$(realpath ./deploy/x86_64-w64-mingw32-npcap)" V=s - make clean stage: build artifacts: paths: - deploy/ when: always build-clang: script: - autoreconf -fi - CC=clang ./configure --enable-option-checking=fatal --prefix=/ - mv config.log deploy/config-clang.log - make install CFLAGS='-Werror' DESTDIR="$(realpath ./deploy/clang)" V=s stage: build artifacts: paths: - deploy/ when: always build-android: cache: key: toolchain-cache paths: - vendor/ script: - mkdir -p vendor && cd vendor - test -r 'android-ndk-r19-linux-x86_64.zip' || wget --progress=dot:mega 'https://dl.google.com/android/repository/android-ndk-r19-linux-x86_64.zip' - test -d 'android-ndk-r19' || unzip -q 'android-ndk-r19-linux-x86_64.zip' - cd .. - autoreconf -fi - CC=aarch64-linux-android28-clang PATH="${PATH}:$(realpath ./vendor/android-ndk-r19/toolchains/llvm/prebuilt/linux-x86_64/bin)" ./configure --enable-option-checking=fatal --host=aarch64-linux-android - mv config.log deploy/config-aarch64-linux-android28-clang.log - PATH="${PATH}:$(realpath ./vendor/android-ndk-r19/toolchains/llvm/prebuilt/linux-x86_64/bin)" make install CFLAGS='-Werror' DESTDIR="$(realpath ./deploy/android28-clang)" V=s stage: build artifacts: paths: - deploy/ when: always test-valgrind: script: - ls -alhR . - deploy/gcc/bin/ptunnel-ng --help - PTUNNEL_BIN="deploy/gcc/bin/ptunnel-ng" test/integration_test.sh - mv /tmp/ptunnel-client.log ptunnel-client-valgrind.log - mv /tmp/ptunnel-server.log ptunnel-server-valgrind.log stage: test artifacts: paths: - deploy/ - ptunnel-client-valgrind.log - ptunnel-server-valgrind.log when: always test-asan: script: - ls -alhR . - deploy/gcc-sanitizer-asserts/bin/ptunnel-ng --help - export DISABLE_VALGRIND=y && export PTUNNEL_BIN="deploy/gcc-sanitizer-asserts/bin/ptunnel-ng" && test/integration_test.sh - mv /tmp/ptunnel-client.log ptunnel-client-sanitizer.log - mv /tmp/ptunnel-server.log ptunnel-server-sanitizer.log - export DISABLE_VALGRIND=y && export PTUNNEL_BIN="deploy/gcc-sanitizer-asserts/bin/ptunnel-ng" && export PTUNNEL_ARGS="--passwd=ci" && test/integration_test.sh - mv /tmp/ptunnel-client.log ptunnel-client-sanitizer-passwd.log - mv /tmp/ptunnel-server.log ptunnel-server-sanitizer-passwd.log stage: test artifacts: paths: - deploy/ - ptunnel-client-sanitizer.log - ptunnel-server-sanitizer.log - ptunnel-client-sanitizer-passwd.log - ptunnel-server-sanitizer-passwd.log when: always ptunnel-ng-1.43/AUTHORS000066400000000000000000000003171460452726400146130ustar00rootroot00000000000000Daniel Stoedle Mike Miller Toni Uhlig Sebastien Raveau Masaq- elnerd ptunnel-ng-1.43/COPYING000066400000000000000000000027701460452726400146030ustar00rootroot00000000000000Copyright (c) 2017-2019, Toni Uhlig All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ptunnel-ng-1.43/ChangeLog000066400000000000000000000143331460452726400153200ustar00rootroot00000000000000PingTunnel-NG Changelog ======================= 1.42 - 27. April 2019 - updated SeLinux policy file - added SeLinux policy compile script - list available pcap devices - fixed build errors related to pcap 1.41 - 03. April 2019 - change the RNG device during ./configure (fixes issues on systems without enough entropy avilable from it's random source) 1.40 - 20. March 2019 - improved empty ping mode (by Masaq-) - fixed NULL pointer derefs and division by zero - more secure chroot - CWE-126 workaround reported by codacy - switched to /dev/random as RNG except for Windows - fixed CLang related build errors - fixed SEGFAULT when network not reachable (by Masaq-) - added extended options for protocol tuning (by Masaq-) - Systemd support (also in debian/rules) - fixed compilation issues for Android targets - fixed 100% CPU consumption when receive window is full but data via select() available (by Masq-) 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 1.30 - 19. October 2018 - travis-ci, coverity integration - xcompile issue for mingw-w64 fixed - fixed wrong usage of format() specifiers 1.20 - 15. July 2018 - Readme improvements - Fixes a possible memory leak when a packet could not send - Better error handling on socket descriptor creation - All Coverity issues fixed 1.00 - 18. December 2017 - First public release - Fixes a exploitable memory leak (proxy/forwarder) if using password protected challenge response authentication. - Fixes an invalid memory write during a pcap capture. - Full source refactoring. The code should be more readable imho. - This project is now Autotools based. Disable optional features: SeLinux, pcap. - Removed an already disabled and highly buggy feature: kPT_add_iphdr - Added a more "GNU" alike option parsing. - Support a user defined PingTunnel-NG magic value which is required for bypassing Cisco IPS (and maybe other IDS/IPS/Firewalls). This feature was well tested against Cisco's "IronPort" which scans for fingerprints in an ICMP packet (PingTunnel magic value). PingTunnel Changelog ==================== 0.72 - 5. September 2011 - Fixes an authentication bug that would manifest as hung connections with protocols that send data from the client-side before receiving data from the server-side. Thanks to StalkR for locating the bug and fixing it. - Fixes a crash when attempting to enable packet-capture for non-existing network devices. Thanks to Steffen Wendzel for the patch. 0.71 - 22. June 2009 - Added security features and SELinux support, courtesy of Sebastien Raveau. 0.70 - 12. January 2009 - Added rudimentary support for tunneling over udp port 53. - Added built-in support for compiling on Windows, thanks to Mike Miller. - Added syslog support, also courtesy of Mike Miller. - Experimental support for spoofing the source IP address. The source address must be explicitly configured in the source code, and it might not work (which is why it's experimental). To enable, define kPT_add_iphdr to 1. 0.62 - [Never released] - Added many comments to the ptunnel header file. - Moved most include directives to the header file. - Fixed crash if proxy or destination hostnames could not be looked up. 0.61 - 26. May 2005 - Noted that ptunnel now works without packet capturing on Mac OS X 10.4 Tiger. - Log files are now opened in append-mode (i.e., not truncated). - Fixed a bug that could cause ptunnel to crash if passwords shorter than 16 characters were used (the overwhelming majority of passwords, most likely!). 0.60 - 15. Apr 2005 - Added authentication support, changing parts of the ptunnel protocol. - Added a manpage. - Added MD5 implementation by L. Peter Deutsch for authentication. - Moved declaration of a variable to allow ptunnel to compile cleanly on gcc 2.95 - thanks Choong! - Added error handling for proxy connections. - Fixed a problem with printing send/recv info. All verbosity levels should work now. - Updated contact info. 0.55 - 18. Feb 2005 - Fixed a locking bug that would manifest itself when the maximum connection count on the proxy was reached. - Fixed ptunnel to compile correctly on 64-bit architectures (thanks to smund Grammeltvedt for pointing out the necessary changes!) - Added a new logging level (level 5). Level 4 no longer outputs send and receive info; for this info level 5 is necessary. - When libpcap is in use, the interface is no longer put in promiscous mode. This has never been necessary, and also makes it impossible to use ptunnel with more than one client on the same network. - Discovered a problem with pcap that would cause ptunnel to hang when pcap was in use. This problem has not been resolved; the workaround is to simply re-execute the client, or disable pcap if possible. - Added support for specifying a log file on the command line, using the -f switch. 0.54 - 1. Feb 2005 - Fixed a byte-order bug (thanks Alfred!) 0.53 - 31. Jan 2005 - Fixed a threading bug, and implemented support for limiting the maximum number of tunnels. Thanks to Alfred Young for reporting and fixing the following bugs: - Fixed a bug with packets captured via libpcap, where the struct sockaddr wasn't properly zeroed. - Fixed a byte order bug in create_and_insert_proxy_desc. - Fixed a memory leak in remove_proxy_desc. 0.52 - 3. Jan 2005 - Fixed a problem introduced by the ICMP ID field changes. The proxy didn't retain the ID of the packets received from clients, resulting in dropped ICMP packets at the router. This in turn lead to the tunnel no longer working, depending on the strictness of the router. This version fixes that problem. - Makefile is better now, thanks to Dries Verachtert. 0.51 - 2. Jan 2005 - Fixed incorrect checksum calculation for resent packets. - Stopped relying on the ICMP packet's "built-in" ID field, and moved the information to the data portion of the packet. - Changed default verbosity level from debug to verbose. 0.50 - 7. Dec 2004 Initial public release. ptunnel-ng-1.43/Dockerfile000066400000000000000000000005451460452726400155400ustar00rootroot00000000000000FROM alpine AS build RUN apk update && apk add \ musl-dev \ autoconf \ automake \ make \ gcc \ tini COPY . /build WORKDIR /build RUN autoreconf -fi && ./configure && make RUN make DESTDIR=/opt install FROM alpine COPY --from=build /opt / COPY --from=build /sbin/tini /sbin/tini ENTRYPOINT ["/sbin/tini", "/usr/local/bin/ptunnel-ng"]ptunnel-ng-1.43/Makefile.am000066400000000000000000000000161460452726400155730ustar00rootroot00000000000000SUBDIRS = src ptunnel-ng-1.43/NEWS000066400000000000000000000000001460452726400142270ustar00rootroot00000000000000ptunnel-ng-1.43/PKGBUILD000066400000000000000000000014551460452726400146730ustar00rootroot00000000000000pkgname="ptunnel-ng" pkgver=1.42 pkgrel=1 pkgdesc="A TCP forwarder and proxy used for ICMP/UDP tunneling without creating tun devices. (Ping Tunnel, ICMP Echo Tunnel, UDP Tunnel)" arch=('i686' 'x86_64') url='https://www.github.com/lnslbrty/ptunnel-ng' license=('BSD-3') makedepends=('git') provides=("ptunnel-ng=${pkgver}") source=("https://github.com/lnslbrty/ptunnel-ng/archive/v${pkgver}.tar.gz") md5sums=('b7741527a7833bc06130ea67502ae21a') build() { cd "${srcdir}/${pkgname}-${pkgver}" ./configure \ --prefix=/usr \ --libdir=/usr/lib \ --disable-pcap \ --disable-selinux make } package() { cd "${srcdir}/${pkgname}-${pkgver}" make DESTDIR="${pkgdir}" install find "${pkgdir}" -type d -name .git -exec rm -r '{}' + install -D -m644 COPYING "${pkgdir}/usr/share/licenses/ptunnel-ng/LICENSE" } ptunnel-ng-1.43/PKGBUILD.dev000066400000000000000000000017761460452726400154560ustar00rootroot00000000000000# use `makepkg -p PKGBUILD.dev --skipchecksums' to build the pkg pkgname="ptunnel-ng" pkgver=master pkgrel=1 pkgdesc="A TCP forwarder and proxy used for ICMP/UDP tunneling without creating tun devices. (Ping Tunnel, ICMP Echo Tunnel, UDP Tunnel)" arch=('i686' 'x86_64') url='https://www.github.com/lnslbrty/ptunnel-ng' license=('BSD-3') makedepends=('git') provides=("ptunnel-ng=${pkgver}") source=("https://github.com/lnslbrty/ptunnel-ng/archive/master.zip") build() { cd "${srcdir}/${pkgname}-${pkgver}" autoreconf -fi ./configure \ --prefix=/usr \ --libdir=/usr/lib \ --disable-pcap \ --disable-selinux make V=s } package() { cd "${srcdir}/${pkgname}-${pkgver}" make DESTDIR="${pkgdir}" install find "${pkgdir}" -type d -name .git -exec rm -r '{}' + install -D -m644 COPYING "${pkgdir}/usr/share/licenses/ptunnel-ng/LICENSE" install -D -m644 contrib/ptunnel-ng.conf "${pkgdir}/etc/conf.d/ptunnel-ng" install -D -m644 contrib/ptunnel-ng.service "${pkgdir}/etc/systemd/system/ptunnel-ng.service" } ptunnel-ng-1.43/README000066400000000000000000000141411460452726400144230ustar00rootroot00000000000000PingTunnel-[N]ew[G]eneration Read Me ==================================== What is ptunnel-ng? ---------------- Ptunnel-NG is a bugfixed and refactored version of Ptunnel with some additional features e.g. change the magic value without recompiling. What is ptunnel? ---------------- Ptunnel is an application that allows you to reliably tunnel TCP connections to a remote host using ICMP echo request and reply packets, commonly known as ping requests and replies. Simple usage ------------ Opens a SSH over ICMP tunnel to a remote. Server: sudo ptunnel-ng Client: sudo ptunnel-ng -p[Server-IP/NAME] -l2222 ssh -p2222 -luser 127.0.0.1 Restricted usage ---------------- Opens a SSH over ICMP tunnel to a remote but restricts destination IP/Port for tunnel clients. 10.0.3.1 is the machine your SSH daemon listens on. This can be a virtual machine, container or (.*). Server: sudo ptunnel-ng -r10.0.3.1 -R22 Client: sudo ptunnel-ng -p[Server-IP/NAME] -l2222 -r10.0.3.1 -R22 ssh -p2222 -luser 127.0.0.1 Reverse shell usage ------------------- Opens a SSH over ICMP tunnel to a remote and creates a reverse tunnel on same but restricts destination IP/Port for tunnel clients. 10.0.3.1 is the machine your SSH daemon listens on. This can be a virtual machine, container or (.*). Server: sudo ptunnel-ng -r10.0.3.1 -R22 Client: sudo ./src/ptunnel-ng -p[Server-IP/NAME] -l2222 -r10.0.3.1 -R22 ssh -R 127.0.0.1:22222 127.0.0.1 -p2222 Server: ssh -p22222 -luser 127.0.0.1 Contact details --------------- The ptunnel-ng fork was done by Toni Uhlig: You can contact the author of ptunnel, Daniel Stoedle, here: The official ptunnel website is located here: Dependencies ------------ Required: pthread Optional: pcap, selinux Compiling --------- Either run "./autogen.sh" for a fully automatic build or run it manually with: "./configure && make" You should end up with a binary called ptunnel-ng. This serves as both the client and proxy. You can optionally install it using "make install". To compile the Windows binary. You will need mingw installed. If you want pcap support you will need the WinPcap library as well. WinPcap is available here: REMEMBER: ptunnel-ng might not work on Windows without WinPcap! Running ------- Ptunnel works best when starting as root, and usually requires starting as root. Common ptunnel-ng options: Proxy(Server): ./ptunnel-ng -r -R -v -P -u -g Forwarder(Client): ./ptunnel-ng -p
-l -r -R -v -P -u -g The -p switch sets the address of the host on which the proxy is running. A quick test to see if the proxy will work is simply to try pinging this host - if you get replies, you should be able to make the tunnel work. If pinging works but you are not able to establish a tunnel, you should play around with the -m switch and change the magic value. A IDS/IPS or Firwall might try to fool you. The -l, -r and -R switches set the local listening port, destination address and destination port. For instance, to tunnel ssh connections from the client machine via a proxy running on proxy.pingtunnel.com to the computer login.domain.com, the following command line would be used: sudo ./ptunnel-ng -p proxy.pingtunnel.com -l 8000 -r login.domain.com -R 22 An ssh connection to login.domain.com can now be established as follows: ssh -p 8000 localhost If ssh complains about potential man-in-the-middle attacks, simply remove the offending key from the known_hosts file. The warning/error is expected if you have previously ssh'd to your local computer (i.e., ssh localhost), or you have used ptunnel-ng to forward ssh connections to different hosts. Of course, for all of this to work, you need to start the proxy on your proxy-computer (we'll call it proxy.pingtunnel.com here). Doing this is very simple: sudo ./ptunnel-ng If you find that the proxy isn't working, you will need to enable packet capturing on the main network device. Currently this device is assumed to be an ethernet-device (i.e., ethernet or wireless). Packet capturing is enabled by giving the -L switch, and supplying the device name to capture packets on (for instance eth0 or en1). The same goes for the client. On versions of Mac OS X prior to 10.4 (Tiger), packet capturing must always be enabled (both for proxy and client), as resent packets won't be received otherwise. To protect yourself from others using your proxy, you can protect access to it with a password using the -P switch. The password is never sent in the clear, but keep in mind that it may be visible from tools like top or ps, which can display the command line used to start an application. Finally, the -u switch will attempt to run the proxy in unprivileged mode (i.e., no need for root access), and the -v switch controls the amount of output from ptunnel-ng. -1 indicates no output, 0 shows errors only, 1 shows info messages, 2 gives more output, 3 provides even more output, level 4 displays debug info and level 5 displays absolutely everything, including the nasty details of sends and receives. The -o switch allows output to be saved to a logfile. Security features: Please see the ptunnel-ng man-page for instructions. Supported operating systems --------------------------- Ptunnel supports most operating systems with libpcap, the usual POSIX functions and a BSD sockets compatible API. In particular, it has been tested on Linux Fedora Core 2 and Mac OS X 10.3.6 and above. As of version 0.7, ptunnel-ng can also be compiled on Windows, courtesy of Mike Miller, assuming mingw and WinPcap is installed. TODOs ----- - refactoring - libsodium integration Credits and contributors ------------------------ Daniel Stoedle et al. License ------- 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. ptunnel-ng-1.43/README.md000066400000000000000000000164261460452726400150320ustar00rootroot00000000000000[![Coverity Status](https://scan.coverity.com/projects/14737/badge.svg?flat=1)](https://scan.coverity.com/projects/14737) [![Total alerts](https://img.shields.io/lgtm/alerts/g/lnslbrty/ptunnel-ng.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/lnslbrty/ptunnel-ng/alerts/) [![Codacy Badge](https://api.codacy.com/project/badge/Grade/021aa1d88dd7486db83df3ff96f9eff8)](https://www.codacy.com/app/lnslbrty/ptunnel-ng?utm_source=github.com&utm_medium=referral&utm_content=lnslbrty/ptunnel-ng&utm_campaign=Badge_Grade) [![GitHub issues](https://img.shields.io/github/issues/lnslbrty/ptunnel-ng.svg)](https://github.com/lnslbrty/ptunnel-ng/issues) [![GitHub license](https://img.shields.io/github/license/lnslbrty/ptunnel-ng.svg)](https://github.com/lnslbrty/ptunnel-ng/blob/master/COPYING) [![Gitter chat](https://badges.gitter.im/ptunnel-ng/Lobby.png)](https://gitter.im/ptunnel-ng/Lobby) [![Packaging status](https://repology.org/badge/tiny-repos/ptunnel-ng.svg)](https://repology.org/project/ptunnel-ng/versions) # PingTunnel-[N]ew[G]eneration Read Me ## What is ptunnel-ng? ``` Ptunnel-NG is a bugfixed and refactored version of Ptunnel with some additional features e.g. change the magic value without recompiling. ``` ## What is ptunnel? ``` Ptunnel is an application that allows you to reliably tunnel TCP connections to a remote host using ICMP echo request and reply packets, commonly known as ping requests and replies. ``` ## Simple usage Opens a SSH over ICMP tunnel to a remote. Server: `sudo ptunnel-ng` Client: `sudo ptunnel-ng -p[Server-IP/NAME] -l2222` `ssh -p2222 -luser 127.0.0.1` ## Restricted usage Opens a SSH over ICMP tunnel to a remote but restricts destination IP/Port for tunnel clients. 10.0.3.1 is the machine your SSH daemon listens on. This can be a virtual machine, container or (.\*). Server: `sudo ptunnel-ng -r10.0.3.1 -R22` Client: `sudo ptunnel-ng -p[Server-IP/NAME] -l2222 -r10.0.3.1 -R22` `ssh -p2222 -luser 127.0.0.1` ## Reverse shell usage Opens a SSH over ICMP tunnel to a remote and creates a reverse tunnel on same but restricts destination IP/Port for tunnel clients. 10.0.3.1 is the machine your SSH daemon listens on. This can be a virtual machine, container or (.\*). Server: `sudo ptunnel-ng -r10.0.3.1 -R22` Client: `sudo ./src/ptunnel-ng -p[Server-IP/NAME] -l2222 -r10.0.3.1 -R22` `ssh -R 127.0.0.1:22222 127.0.0.1 -p2222` Server: `ssh -p22222 -luser 127.0.0.1` ## How does it work? ``` ICMP Packet structure ``` ![Ptunnel Packet Structure](https://github.com/lnslbrty/ptunnel-ng/raw/master/web/packet-format.png) ``` Ptunnel program setup ``` ![Ptunnel Setup](https://github.com/lnslbrty/ptunnel-ng/raw/master/web/setup.png) ## Contact details ``` The ptunnel-ng fork was done by Toni Uhlig: You can contact the author of ptunnel, Daniel Stoedle, here: The official ptunnel website is located here: ``` ## Dependencies ``` Required: pthread Optional: pcap, selinux ``` ## Compiling ``` Either run "./autogen.sh" for a fully automatic build or run it manually with: "./configure && make" You should end up with a binary called ptunnel-ng. This serves as both the client and proxy. You can optionally install it using "make install". To compile the Windows binary. You will need mingw installed. If you want pcap support you will need the WinPcap library as well. WinPcap is available here: REMEMBER: ptunnel-ng might not work on Windows without WinPcap! ``` ## Running ``` Ptunnel works best when starting as root, and usually requires starting as root. Common ptunnel-ng options: Proxy(Server): ./ptunnel-ng -r -R -v -P -u -g Forwarder(Client): ./ptunnel-ng -p
-l -r -R -v -P -u -g The -p switch sets the address of the host on which the proxy is running. A quick test to see if the proxy will work is simply to try pinging this host - if you get replies, you should be able to make the tunnel work. If pinging works but you are not able to establish a tunnel, you should play around with the -m switch and change the magic value. A IDS/IPS or Firwall might try to fool you. The -l, -r and -R switches set the local listening port, destination address and destination port. For instance, to tunnel ssh connections from the client machine via a proxy running on proxy.pingtunnel.com to the computer login.domain.com, the following command line would be used: sudo ./ptunnel-ng -p proxy.pingtunnel.com -l 8000 -r login.domain.com -R 22 An ssh connection to login.domain.com can now be established as follows: ssh -p 8000 localhost If ssh complains about potential man-in-the-middle attacks, simply remove the offending key from the known_hosts file. The warning/error is expected if you have previously ssh'd to your local computer (i.e., ssh localhost), or you have used ptunnel-ng to forward ssh connections to different hosts. Of course, for all of this to work, you need to start the proxy on your proxy-computer (we'll call it proxy.pingtunnel.com here). Doing this is very simple: sudo ./ptunnel-ng If you find that the proxy isn't working, you will need to enable packet capturing on the main network device. Currently this device is assumed to be an ethernet-device (i.e., ethernet or wireless). Packet capturing is enabled by giving the -L switch, and supplying the device name to capture packets on (for instance eth0 or en1). The same goes for the client. On versions of Mac OS X prior to 10.4 (Tiger), packet capturing must always be enabled (both for proxy and client), as resent packets won't be received otherwise. To protect yourself from others using your proxy, you can protect access to it with a password using the -P switch. The password is never sent in the clear, but keep in mind that it may be visible from tools like top or ps, which can display the command line used to start an application. Finally, the -u switch will attempt to run the proxy in unprivileged mode (i.e., no need for root access), and the -v switch controls the amount of output from ptunnel-ng. -1 indicates no output, 0 shows errors only, 1 shows info messages, 2 gives more output, 3 provides even more output, level 4 displays debug info and level 5 displays absolutely everything, including the nasty details of sends and receives. The -o switch allows output to be saved to a logfile. Security features: Please see the ptunnel-ng man-page for instructions. ``` ## Supported operating systems ``` Ptunnel supports most operating systems with libpcap, the usual POSIX functions and a BSD sockets compatible API. In particular, it has been tested on Linux Fedora Core 2 and Mac OS X 10.3.6 and above. As of version 0.7, ptunnel-ng can also be compiled on Windows, courtesy of Mike Miller, assuming mingw and WinPcap is installed. ``` ## TODOs ``` - refactoring - libsodium integration ``` ## Credits and contributors ``` Daniel Stoedle et al. ``` ## License ``` 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. ``` ptunnel-ng-1.43/autogen.sh000077500000000000000000000004251460452726400155440ustar00rootroot00000000000000#!/bin/bash set -x OLD_WD="$(pwd)" NEW_WD="$(dirname ${0})" cd "${NEW_WD}" if ! autoreconf -fi; then aclocal autoheader automake --force-missing --add-missing autoconf fi cd "${OLD_WD}" "${NEW_WD}/configure" $@ && make clean && make -j${BUILDJOBS:-4} all ptunnel-ng-1.43/configure.ac000066400000000000000000000220131460452726400160260ustar00rootroot00000000000000AC_PREREQ(2.69) AC_INIT([ptunnel-ng], [1.42], [], [], []) AC_CONFIG_SRCDIR([src/config.h.in]) AC_CONFIG_FILES([Makefile src/Makefile]) AC_CANONICAL_BUILD AC_CANONICAL_HOST case x"${host}" in x*-*-cygwin* | x*-*-mingw32*) dnl Some Windows includes required by third-party modules. use_msw=yes PROGRAM_EXT=".exe" ;; *-androideabi) use_android=yes ;; esac AM_SILENT_RULES([yes]) AM_INIT_AUTOMAKE AC_PROG_INSTALL AC_PROG_CC AC_PROG_CC_STDC AC_USE_SYSTEM_EXTENSIONS AC_C_CONST AC_C_INLINE AC_TYPE_SIZE_T AC_CHECK_HEADER_STDBOOL AC_FUNC_VPRINTF AC_FUNC_MEMCMP dnl Check for -std=gnu99 if test x"${ac_cv_prog_cc_stdc}" = x"no"; then AC_MSG_ERROR([Your compiler does not support \`-std=gnu99\`. This is fatal.]) fi dnl Check for std includes. AC_CHECK_HEADERS([stdarg.h stdio.h unistd.h stdlib.h string.h stdint.h time.h signal.h assert.h],, [AC_MSG_ERROR([Missing essential std headers.])]) if test x"${use_msw}" != x"yes"; then AC_CHECK_HEADERS([sys/unistd.h],,) AC_CHECK_HEADERS([sys/types.h sys/socket.h netinet/in.h arpa/inet.h netdb.h pthread.h errno.h net/ethernet.h syslog.h pwd.h grp.h],, [AC_MSG_ERROR([Missing essential non-Windows std headers.])]) AC_SEARCH_LIBS([pthread_create], [pthread],, [AC_MSG_ERROR([Missing pthread library.])],) if test x"${use_android}" != x"yes"; then AC_CHECK_FUNCS([signal],,[AC_MSG_ERROR([Missing essential non-Android std functions.])]) fi AC_CHECK_FUNCS([pthread_mutex_init pthread_mutex_lock pthread_mutex_unlock syslog getaddrinfo freeaddrinfo gai_strerror],, [AC_MSG_ERROR([Missing essential Linux std functions.])]) else AC_CHECK_TOOL([DLLTOOL], [dlltool], [:]) if test x"${DLLTOOL}" = x":"; then AC_MSG_ERROR([Missing dlltool which is required to build the import library!]) fi AC_CHECK_HEADERS([winsock2.h windows.h ws2tcpip.h],, [AC_MSG_ERROR([Missing essential Windows std headers.])]) AC_CHECK_LIB([ws2_32],[main]) fi AC_MSG_CHECKING([for GNU getopt_long]) AC_COMPILE_IFELSE( [AC_LANG_PROGRAM([[ #include #include struct option long_options[] = { {"opt1", required_argument, 0, 'a'}, {"opt2", optional_argument, 0, 'b'}, {"opt3", no_argument, 0, 'c'} }; void parse_opts(int argc, char **argv) { getopt_long(argc, argv, "a:b::c", &long_options[0], &optind); } ]], [])] ,[AC_MSG_RESULT([yes])] ,[AC_MSG_ERROR([Your compiler does not support \`_GNU_SOURCE\`.])]) dnl Check timeval struct members. AC_CHECK_MEMBER([struct timeval.tv_sec], [], [AC_MSG_ERROR([Invalid \`struct timeval\` structure.])], [[#include ]]) AC_CHECK_MEMBER([struct timeval.tv_usec], [], [AC_MSG_ERROR([Invalid \`struct timeval\` structure.])], [[#include ]]) dnl Check size AC_CHECK_SIZEOF(char) AC_CHECK_SIZEOF(uint8_t) AC_CHECK_SIZEOF(uint16_t) AC_CHECK_SIZEOF(uint32_t) AC_CHECK_SIZEOF(int) if test $ac_cv_sizeof_char != "1" -o \ $ac_cv_sizeof_uint8_t != "1" -o \ $ac_cv_sizeof_uint16_t != "2" -o \ $ac_cv_sizeof_uint32_t != "4" -o \ $ac_cv_sizeof_int != "4"; then AC_MSG_ERROR([Invalid type size.]) fi AC_MSG_CHECKING([for __attribute__ ((packed))]) AC_COMPILE_IFELSE( [AC_LANG_PROGRAM([[ #include struct foo { int num; char *str; void *ptr; } __attribute__ ((packed)); ]], [])] ,[AC_MSG_RESULT([yes])] ,[AC_MSG_ERROR([Your compiler does not support \`__attribute__ ((packed))\`.])]) dnl Check for std functions. AC_CHECK_FUNCS([malloc calloc free memcpy memset printf sprintf vsnprintf strerror strlen strncmp strstr strtol strtoul fopen fprintf gettimeofday close fclose exit getopt_long],, [AC_MSG_ERROR([Missing essential std functions.])]) if test x"${use_msw}" = x; then AC_CHECK_FUNCS([inet_ntoa],, [AC_MSG_ERROR([Missing essential std functions.])]) fi dnl `--disable-pcap`: Enabled if found. AC_ARG_ENABLE([pcap], [AS_HELP_STRING([--disable-pcap], [Disable pcap support. (default: enabled if found)])],,[pcap_enabled=yes]) pcap_enabled=$(echo ${pcap_enabled}) case ${pcap_enabled} in 1|y|yes) pcap_enabled=yes ;; ''|0|n|no) pcap_enabled= ;; *) AC_MSG_ERROR([Unknown option \`${pcap_enabled}\` for --disable-pcap]) ;; esac dnl `--disable-ssl`: Enabled if found. AC_ARG_ENABLE([ssl], [AS_HELP_STRING([--disable-ssl], [Disable ssl support. (default: enabled if found)])],,[ssl_enabled=yes]) ssl_enabled=$(echo ${ssl_enabled}) case ${ssl_enabled} in 1|y|yes) ssl_enabled=yes ;; ''|0|n|no) ssl_enabled= ;; *) AC_MSG_ERROR([Unknown option \`${ssl_enabled}\' for --disable-ssl]) ;; esac dnl `--enable-npcap`: Enable npcap interface (Windows only!) AC_ARG_ENABLE([npcap], [AS_HELP_STRING([--enable-npcap], [Enable npcap support. (Windows only; default: disabled)])],[npcap_enabled=yes],) npcap_enabled=$(echo ${npcap_enabled}) case ${npcap_enabled} in 1|y|yes) pcap_enabled=yes ;; ''|0|n|no) pcap_enabled= ;; *) AC_MSG_ERROR([Unknown option \`${npcap_enabled}\` for --enable-npcap]) ;; esac dnl `--disable-selinux`: Enabled if found. AC_ARG_ENABLE([selinux], [AS_HELP_STRING([--disable-selinux], [Disable SELINUX support. (default: enabled if found)])],,[selinux_enabled=yes]) selinux_enabled=$(echo ${selinux_enabled}) case ${selinux_enabled} in 1|y|yes) selinux_enabled=yes ;; ''|0|n|no) selinux_enabled= ;; *) AC_MSG_ERROR([Unknown option \`${selinux_enabled}\` for --disable-selinux]) ;; esac dnl `--with-randomdev`: Default value /dev/random use_customrng=no AC_MSG_CHECKING([for random device]) AC_ARG_WITH([rngdev], [AS_HELP_STRING([--with-rngdev], [Set an alternative random device. (default: /dev/random)])], [use_customrng=yes], [with_rngdev="/dev/random"]) case ${with_rngdev} in yes) with_rngdev="/dev/random" ;; /dev/random) ;; /dev/urandom) ;; *) AC_MSG_ERROR([Unknown random device \`${with_rngdev}\` for --with-rngdev: Only \`/dev/random\` xor \`/dev/urandom\` allowed. This option is unused on Windows targets.]) ;; esac AC_MSG_RESULT([${with_rngdev}]) AC_DEFINE_UNQUOTED([RNGDEV], ["${with_rngdev}"], [set the path to the random device you want to use for pt_random]) dnl `--enable-asserts`: Disabled per default AC_ARG_ENABLE([asserts], [AS_HELP_STRING([--enable-asserts], [Enable asserts(). (default: disabled)])],[asserts_enabled=yes],) asserts_enabled=$(echo ${asserts_enabled}) case ${asserts_enabled} in 1|y|yes) asserts_enabled=yes ;; ''|0|n|no) asserts_enabled=no ;; *) AC_MSG_ERROR([Unknown option \`${asserts_enabled}\` for --enable-asserts]) ;; esac dnl `--enable-sanitizer`: Disabled per default AC_ARG_ENABLE([sanitizer], [AS_HELP_STRING([--enable-sanitizer], [Enable ASAN, LSAN and UBSAN. (default: disabled)])],[sanitizer_enabled=yes],) sanitizer_enabled=$(echo ${sanitizer_enabled}) case ${sanitizer_enabled} in 1|y|yes) sanitizer_enabled=yes ;; ''|0|n|no) sanitizer_enabled=no ;; *) AC_MSG_ERROR([Unknown option \`${sanitizer_enabled}\` for --enable-sanitizer]) ;; esac dnl Check libpcap headers/functions. if test x"${pcap_enabled}" != x -a \ x"${use_msw}" != xyes; then AC_CHECK_HEADERS([pcap.h],, [pcap_enabled=]) AC_SEARCH_LIBS([pcap_lookupnet], [pcap],, [pcap_enabled=],) AC_CHECK_FUNCS([pcap_compile pcap_close pcap_setfilter pcap_dispatch pcap_findalldevs pcap_freealldevs],, [pcap_enabled=]) fi dnl Check openssl headers/functions. if test x"${ssl_enabled}" != x; then AC_CHECK_HEADERS([openssl/sha.h],,[ssl_enabled=]) AC_SEARCH_LIBS([CRYPTO_new_ex_data],[crypto],,[ssl_enabled=]) fi dnl Check for more secure randomization functions if test x"${use_customrng}" != xyes; then AC_CHECK_HEADERS([bsd/stdlib.h],,) AC_SEARCH_LIBS([arc4random], [bsd],,,) AC_CHECK_FUNCS([arc4random], [arc4random_enabled=yes],) fi dnl Check for SELINUX if test x"${selinux_enabled}" != x; then AC_CHECK_HEADERS([selinux/selinux.h],, [selinux_enabled=]) 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</dev/null } case $1 in ""|load) modlib_add_user_and_group nobody modreg cgi 'pingtunnel-ng' 'pingtunnel-ng' modreg daemon $DAEMON modlib_start $PINGTUNNELNG_ENABLED ;; unload) modunreg daemon $DAEMON modunreg cgi 'pingtunnel-ng' modlib_stop ;; start) modlib_start ;; stop) modlib_stop ;; restart) modlib_restart ;; status) modlib_status ;; *) echo "Usage: $0 [load|unload|start|stop|restart|status]" 1>&2 exit 1 ;; esac exit 0 ptunnel-ng-1.43/contrib/freetz/make/pingtunnel-ng/files/root/usr/000077500000000000000000000000001460452726400251015ustar00rootroot00000000000000ptunnel-ng-1.43/contrib/freetz/make/pingtunnel-ng/files/root/usr/lib/000077500000000000000000000000001460452726400256475ustar00rootroot00000000000000ptunnel-ng-1.43/contrib/freetz/make/pingtunnel-ng/files/root/usr/lib/cgi-bin/000077500000000000000000000000001460452726400271575ustar00rootroot00000000000000ptunnel-ng-1.43/contrib/freetz/make/pingtunnel-ng/files/root/usr/lib/cgi-bin/pingtunnel-ng.cgi000077500000000000000000000011371460452726400324350ustar00rootroot00000000000000#!/bin/sh . /usr/lib/libmodcgi.sh sec_begin '$(lang de:"Starttyp" en:"Start type")' cgi_print_radiogroup_service_starttype "enabled" "$PINGTUNNELNG_ENABLED" "" "" 0 sec_end sec_begin '$(lang de:"Server" en:"Server")' cgi_print_password_p "password" "$PINGTUNNELNG_PASSWORD" 20/32 \ "$(lang de:"Tunnel-Passwort" en:"Tunnel password"): " cgi_print_textline_p "extra" "$PINGTUNNELNG_EXTRA" 40/255 \ "$(lang de:"Erweiterte Optionen" en:"Extra options"): " cgi_print_textline_p "magic" "$PINGTUNNELNG_MAGIC" 20/32 \ "$(lang de:"ICMP Tunnel magische Nummer" en:"ICMP Tunnel Magic Number"): " sec_end ptunnel-ng-1.43/contrib/freetz/make/pingtunnel-ng/pingtunnel-ng.mk000066400000000000000000000020151460452726400253170ustar00rootroot00000000000000$(call PKG_INIT_BIN, 1.1) $(PKG)_SOURCE:=ptunnel-ng-$($(PKG)_VERSION).tar.gz $(PKG)_SOURCE_SHA256:=3182ecc4f9a7ef3ae8895b460aa596ae050b9718b98fd5eaf224772fba017c22 $(PKG)_SITE:=https://github.com/lnslbrty/ptunnel-ng/releases/download/v$($(PKG)_VERSION) $(PKG)_DIR:=$($(PKG)_SOURCE_DIR)/ptunnel-ng-$($(PKG)_VERSION) $(PKG)_BINARY:=$($(PKG)_DIR)/src/ptunnel-ng $(PKG)_TARGET_BINARY:=$($(PKG)_DEST_DIR)/usr/sbin/ptunnel-ng $(PKG)_BUILD_PREREQ += aclocal automake autoconf $(PKG)_DEPENDS_ON += libpcap $(PKG)_EXTRA_CFLAGS += -std=gnu99 $(PKG)_CONFIGURE_OPTIONS += --disable-selinux $(PKG_SOURCE_DOWNLOAD) $(PKG_UNPACKED) $(PKG_CONFIGURED_CONFIGURE) $($(PKG)_BINARY): $($(PKG)_DIR)/.configured echo "______$(PINGTUNNEL_NG_EXTRA_CFLAGS)_____" $(SUBMAKE) -C $(PINGTUNNEL_NG_DIR) V=1 \ CFLAGS="$(TARGET_CFLAGS) $(PINGTUNNEL_NG_EXTRA_CFLAGS)" $($(PKG)_TARGET_BINARY): $($(PKG)_BINARY) $(INSTALL_BINARY_STRIP) $(pkg): $(pkg)-precompiled: $($(PKG)_TARGET_BINARY) $(pkg)-uninstall: $(RM) $(PINGTUNNEL_NG_TARGET_BINARY) $(PKG_FINISH) ptunnel-ng-1.43/contrib/ptunnel-ng.conf000066400000000000000000000011441460452726400201400ustar00rootroot00000000000000# Do not forget the '=' between options and values # for long options e.g. '--option=value'. # This is not required nor valid for short options e.g. '-o value'. # # required settings # # chroot to this dir PT_CHROOT="/var/lib/ptunnel" # change user/group PT_USER="nobody" PT_GROUP="nobody" # # optional settings # # authentication challenge (won't be visible in /proc/*/cmdline) #PT_PASSWD="--passwd=changeme" # magic value protocol identifier (fool IDS/IDP software) #PT_MAGIC="--magic=0x41414141" # destination ip #PT_DESTIP="--remote-addr=127.0.0.1" # destination port #PT_DESTPORT="--remote-port=22" ptunnel-ng-1.43/contrib/ptunnel-ng.service000066400000000000000000000010601460452726400206500ustar00rootroot00000000000000[Unit] Description=PingTunnel NG Proxy/Server After=syslog.target [Service] Type=fork EnvironmentFile=/etc/conf.d/ptunnel-ng Environment="PT_CHROOT=${PT_CHROOT:/var/lib/ptunnel}" Environment="PT_USER=${PT_USER:nobody}" Environment="PT_GROUP=${PT_GROUP:nobody}" ExecStartPre=mkdir -p ${PT_CHROOT} ExecStartPre=chown ${PT_USER}:${PT_GROUP} ${PT_CHROOT} ExecStart=/usr/bin/ptunnel-ng \ --syslog \ --chroot=${PT_CHROOT} --user=${PT_USER} --group=${PT_GROUP} \ $PT_PASSWD $PT_MAGIC $PT_DESTIP $PT_DESTPORT Restart=on-abort [Install] WantedBy=multi-user.target ptunnel-ng-1.43/debian/000077500000000000000000000000001460452726400147645ustar00rootroot00000000000000ptunnel-ng-1.43/debian/changelog000066400000000000000000000002131460452726400166320ustar00rootroot00000000000000ptunnel-ng (1.0) RELEASED; urgency=medium * Initial release. -- Toni Uhlig Tue, 19 Dec 2017 00:16:33 +0100 ptunnel-ng-1.43/debian/compat000066400000000000000000000000021460452726400161620ustar00rootroot000000000000009 ptunnel-ng-1.43/debian/control000066400000000000000000000016131460452726400163700ustar00rootroot00000000000000Source: ptunnel-ng Section: net Priority: optional Maintainer: Debian QA Group Build-Depends: debhelper (>= 9), libpcap0.8-dev | libpcap-dev, libselinux1-dev [linux-any] Standards-Version: 3.9.7 Homepage: https://github.com/lnslbrty/ptunnel-ng Package: ptunnel-ng Architecture: any Depends: ${misc:Depends}, ${shlibs:Depends} Description: Tunnel TCP connections over ICMP packets ptunnel-ng is an application that allows you to reliably tunnel TCP connections to a remote host using ICMP echo request and reply packets, commonly known as ping requests and replies. It acts as a proxy and can handle sockets and secured identification. . Those features can be very handy when working in a closed networking environment with firewalls and proxies. ptunnel-ng is a improved version of the original ptunnel with additional features and bugfixes. ptunnel-ng-1.43/debian/copyright000066400000000000000000000052641460452726400167260ustar00rootroot00000000000000Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ Upstream-Name: ptunnel Source: http://www.cs.uit.no/~daniels/PingTunnel/index.html Files: * Copyright: Copyright 2017-2019 Toni Uhlig License: BSD-3-Clause Files: md5.* Copyright: Copyright 1999, 2000, 2002 Aladdin Enterprises License: Zlib Files: debian/* Copyright: Copyright 2017 Toni Uhlig License: BSD-3-Clause Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. License: Zlib This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. . Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: . 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. ptunnel-ng-1.43/debian/ptunnel.doc-base000066400000000000000000000004341460452726400200510ustar00rootroot00000000000000Document: ptunnel Title: Debian ptunnel manual Author: Daniel Stoedle Abstract: This manual describes how works ptunnel and how use it. Section: Network/Communication Format: HTML Index: /usr/share/doc/ptunnel/index.html Files: /usr/share/doc/ptunnel/index.html ptunnel-ng-1.43/debian/ptunnel.docs000066400000000000000000000000721460452726400173220ustar00rootroot00000000000000README web/index.html web/packet-format.png web/setup.png ptunnel-ng-1.43/debian/rules000077500000000000000000000011131460452726400160400ustar00rootroot00000000000000#!/usr/bin/make -f export DEB_BUILD_MAINT_OPTIONS = hardening=+all CPPFLAGS:=$(shell dpkg-buildflags --get CPPFLAGS) CFLAGS:=$(shell dpkg-buildflags --get CFLAGS) LDFLAGS:=$(shell dpkg-buildflags --get LDFLAGS) %: dh $@ --with autoreconf override_dh_auto_build: dh_auto_build -- CFLAGS="-Wall -Werror $(CFLAGS)" LDFLAGS="$(LDFLAGS)" CPPFLAGS="$(CPPFLAGS)" override_dh_auto_install: dh_auto_install install -D -m644 contrib/ptunnel-ng.conf debian/ptunnel-ng/etc/conf.d/ptunnel-ng install -D -m644 contrib/ptunnel-ng.service debian/ptunnel-ng/etc/systemd/system/ptunnel-ng.service ptunnel-ng-1.43/debian/source/000077500000000000000000000000001460452726400162645ustar00rootroot00000000000000ptunnel-ng-1.43/debian/source/format000066400000000000000000000000141460452726400174720ustar00rootroot000000000000003.0 (quilt) ptunnel-ng-1.43/debian/watch000066400000000000000000000001171460452726400160140ustar00rootroot00000000000000version=3 http://www.cs.uit.no/~daniels/PingTunnel/PingTunnel-(.*)\.tar\.gz ptunnel-ng-1.43/model_file.c000066400000000000000000000014471460452726400160130ustar00rootroot00000000000000/* Coverity Scan model * * This is a modeling file for Coverity Scan. Modeling helps to avoid false * positives. * * - A model file can't import any header files. * - Therefore only some built-in primitives like int, char and void are * available but not wchar_t, NULL etc. * - Modeling doesn't need full structs and typedefs. Rudimentary structs * and similar types are sufficient. * - An uninitialized local pointer is not an error. It signifies that the * variable could be either NULL or have some data. * * Coverity Scan doesn't pick up modifications automatically. The model file * must be uploaded by an admin in the analysis settings of */ /* ignore optarg NULL deref false positive for parse_options(...) */ int parse_options(int argc, char **argv) { __coverity_panic__(); } ptunnel-ng-1.43/selinux/000077500000000000000000000000001460452726400152315ustar00rootroot00000000000000ptunnel-ng-1.43/selinux/compile.sh000066400000000000000000000003071460452726400172150ustar00rootroot00000000000000#!/bin/sh set -x set -e OUTDIR="$(dirname $0)" checkmodule -M -m -o ${OUTDIR}/ptunnel-ng.mod ${OUTDIR}/ptunnel-ng.te semodule_package -o ${OUTDIR}/ptunnel-ng.pp -m ${OUTDIR}/ptunnel-ng.mod exit 0 ptunnel-ng-1.43/selinux/ptunnel-ng.te000066400000000000000000000037431460452726400176610ustar00rootroot00000000000000 module ptunnel-ng 1.0; require { type local_login_t; type file_context_t; type unconfined_t; type lvm_t; type bin_t; type gpmctl_t; type tracefs_t; type dpkg_script_t; type xconsole_device_t; type modules_object_t; type initrc_var_run_t; type var_run_t; type debugfs_t; type udev_var_run_t; type bootloader_t; type tmp_t; type fsadm_run_t; class file { create execmod execute execute_no_trans getattr link open read rename setattr unlink write }; class capability sys_module; class dir { add_name getattr remove_name search write }; class fifo_file getattr; class sock_file getattr; class system module_load; } #============= bootloader_t ============== allow bootloader_t debugfs_t:dir search; allow bootloader_t file_context_t:dir search; allow bootloader_t file_context_t:file { getattr open read }; allow bootloader_t fsadm_run_t:dir { add_name getattr remove_name write }; allow bootloader_t fsadm_run_t:file { create getattr link open read rename setattr unlink write }; allow bootloader_t gpmctl_t:sock_file getattr; allow bootloader_t modules_object_t:system module_load; allow bootloader_t self:capability sys_module; allow bootloader_t tmp_t:file { execute execute_no_trans getattr open read }; allow bootloader_t tracefs_t:dir search; allow bootloader_t udev_var_run_t:file { getattr open read }; allow bootloader_t xconsole_device_t:fifo_file getattr; #============= dpkg_script_t ============== #!!!! This avc can be allowed using the boolean 'allow_execmod' allow dpkg_script_t bin_t:file execmod; #============= local_login_t ============== allow local_login_t initrc_var_run_t:file unlink; allow local_login_t var_run_t:dir { add_name remove_name write }; allow local_login_t var_run_t:file { getattr open read rename unlink }; #============= lvm_t ============== allow lvm_t initrc_var_run_t:dir { add_name getattr write }; #============= unconfined_t ============== #!!!! This avc can be allowed using the boolean 'allow_execmod' allow unconfined_t bin_t:file execmod; ptunnel-ng-1.43/src/000077500000000000000000000000001460452726400143315ustar00rootroot00000000000000ptunnel-ng-1.43/src/Makefile.am000066400000000000000000000022401460452726400163630ustar00rootroot00000000000000bin_PROGRAMS = ptunnel-ng man8_MANS = ptunnel-ng.8 ptunnel_ng_CFLAGS = -Wall -Wextra ptunnel_ng_LDADD = CLEANFILES = EXTTRA_DIST = if HAVE_PCAP ptunnel_ng_CFLAGS += -DHAVE_PCAP=1 endif if ENABLE_SHA512 ptunnel_ng_CFLAGS += -DENABLE_SHA512=1 endif if HAVE_SELINUX ptunnel_ng_CFLAGS += -DHAVE_SELINUX=1 endif if HAVE_ICMPFILTER ptunnel_ng_CFLAGS += -DHAVE_ICMPFILTER=1 endif if HAVE_ARC4RANDOM ptunnel_ng_CFLAGS += -DHAVE_ARC4RANDOM=1 endif if USE_CUSTOMRNG ptunnel_ng_CFLAGS += -DUSE_CUSTOMRNG=1 endif if DISABLE_ASSERTS ptunnel_ng_CFLAGS += -DNDEBUG=1 endif if ENABLE_SANITIZER ptunnel_ng_CFLAGS += -fsanitize=address -fsanitize=leak -fsanitize=undefined endif ptunnel_ng_SOURCES = \ md5.c \ challenge.c \ options.c \ utils.c \ pkt.c \ pdesc.c \ ptunnel.c if IS_WINDOWS wpcap_DEF = $(srcdir)/win32/WPCAP.DEF wpcap_IMP = $(srcdir)/win32/libwpcap_implib.a ptunnel_ng_CFLAGS += -I$(srcdir)/win32/includes -DHAVE_PCAP=1 if HAVE_NPCAP ptunnel_ng_CFLAGS += -DHAVE_NPCAP=1 endif ptunnel_ng_LDADD += $(wpcap_IMP) ptunnel_ng_SOURCES += $(wpcap_DEF) $(wpcap_IMP): @DLLTOOL@ -k -y $(wpcap_IMP) --def $(wpcap_DEF) CLEANFILES += $(wpcap_IMP) EXTTRA_DIST += $(wpcap_DEF) endif ptunnel-ng-1.43/src/challenge.c000066400000000000000000000116001460452726400164150ustar00rootroot00000000000000/* * challenge.c * ptunnel is licensed under the BSD license: * * Copyright (c) 2004-2011, Daniel Stoedle , * Yellow Lemon Software. All rights reserved. * * 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: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * - Neither the name of the Yellow Lemon Software nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * Contacting the author: * You can get in touch with me, Daniel Stødle (that's the Norwegian letter oe, * in case your text editor didn't realize), here: * * The official ptunnel website is here: * * * Note that the source code is best viewed with tabs set to 4 spaces. */ #include #include #include #include #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. */ challenge_t *generate_challenge(void) { struct timeval tt; challenge_t *c; int i; c = (challenge_t *) calloc(1, sizeof(challenge_t)); assert(c != NULL); gettimeofday(&tt, 0); c->plain.sec = tt.tv_sec; c->plain.usec_rnd = tt.tv_usec + pt_random(); for (i=0;i<6;i++) c->plain.random[i] = pt_random(); return c; } /* generate_response_md5: Generates a response to the given challenge. The response * is generated by combining the concatenating the challenge data with the * md5 digest of the password, and then calculating the MD5 digest of the * entire buffer. The result is stored in the passed-in challenge, overwriting * the challenge data. */ void generate_response_md5(challenge_plain_t *plain, challenge_digest_t *digest) { md5_byte_t buf[sizeof(*plain) + kMD5_digest_size]; md5_state_t state; digest->hash_type = HT_MD5; memcpy(buf, plain, sizeof(*plain)); memcpy(&buf[sizeof(*plain)], opts.md5_password_digest, kMD5_digest_size); memset(plain, 0, sizeof(*plain)); md5_init(&state); md5_append(&state, buf, sizeof(*plain) + kMD5_digest_size); md5_finish(&state, (md5_byte_t *) &digest->md5[0]); } /* validate_challenge_md5: Checks whether a given response matches the expected * response, returning 1 if validation succeeded, and 0 otherwise. Note that * overwriting the local challenge with the challenge result is not a problem, * as the data will not be used again anyway (authentication either succeeds, * or the connection is closed down). */ int validate_challenge_md5(challenge_t *local, challenge_digest_t *remote) { generate_response_md5(&local->plain, &local->digest); if (remote->hash_type == HT_MD5 && memcmp(&local->digest.md5[0], &remote->md5[0], sizeof(local->digest.md5)) == 0) { return 1; } return 0; } #ifdef ENABLE_SHA512 void generate_response_sha512(challenge_plain_t *plain, challenge_digest_t *digest) { unsigned char buf[sizeof(*plain) + kSHA512_digest_size]; digest->hash_type = HT_SHA512; memcpy(buf, plain, sizeof(*plain)); memcpy(&buf[sizeof(*plain)], opts.sha512_password_digest, kSHA512_digest_size); memset(plain, 0, sizeof(*plain)); SHA512(buf, sizeof(*plain) + kSHA512_digest_size, &digest->sha512[0]); } int validate_challenge_sha512(challenge_t *local, challenge_digest_t *remote) { generate_response_sha512(&local->plain, &local->digest); if (remote->hash_type == HT_SHA512 && memcmp(&local->digest.sha512[0], &remote->sha512[0], sizeof(local->digest.sha512)) == 0) { return 1; } return 0; } #endif /* ENABLE_SHA512 */ ptunnel-ng-1.43/src/challenge.h000066400000000000000000000065571460452726400164410ustar00rootroot00000000000000/* * challenge.h * ptunnel is licensed under the BSD license: * * Copyright (c) 2004-2011, Daniel Stoedle , * Yellow Lemon Software. All rights reserved. * * 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: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * - Neither the name of the Yellow Lemon Software nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * Contacting the author: * You can get in touch with me, Daniel Stødle (that's the Norwegian letter oe, * in case your text editor didn't realize), here: * * The official ptunnel website is here: * * * Note that the source code is best viewed with tabs set to 4 spaces. */ #ifndef CHALLENGE_H #define CHALLENGE_H 1 #include "pconfig.h" #include #ifdef ENABLE_SHA512 #include #endif #define HT_MD5 0x1 #define HT_SHA512 0x2 typedef struct challenge_plain_t { /** tv_sec as returned by gettimeofday */ uint32_t sec; /** tv_usec as returned by gettimeofday + random value */ uint32_t usec_rnd; /** random values */ uint32_t random[6]; } __attribute__ ((packed)) challenge_plain_t; typedef struct challenge_digest_t { uint8_t hash_type; union { unsigned char md5[kMD5_digest_size]; unsigned char sha512[kSHA512_digest_size]; }; } __attribute__ ((packed)) challenge_digest_t; /** challenge_t: This structure contains the pseudo-random challenge used for * authentication. If OpenSSL is available SHA512 will be used per default. */ typedef struct challenge_t { challenge_plain_t plain; challenge_digest_t digest; } __attribute__ ((packed)) challenge_t; challenge_t *generate_challenge(void); void generate_response_md5(challenge_plain_t *plain, challenge_digest_t *digest); int validate_challenge_md5(challenge_t *local, challenge_digest_t *remote); #ifdef ENABLE_SHA512 void generate_response_sha512(challenge_plain_t *plain, challenge_digest_t *digest); int validate_challenge_sha512(challenge_t *local, challenge_digest_t *remote); #endif #endif ptunnel-ng-1.43/src/md5.c000066400000000000000000000302261460452726400151650ustar00rootroot00000000000000/* Copyright (C) 1999, 2000, 2002 Aladdin Enterprises. All rights reserved. This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. L. Peter Deutsch ghost@aladdin.com */ /* $Id: md5.c,v 1.1 2005/04/15 07:37:22 daniels Exp $ */ /* Independent implementation of MD5 (RFC 1321). This code implements the MD5 Algorithm defined in RFC 1321, whose text is available at http://www.ietf.org/rfc/rfc1321.txt The code is derived from the text of the RFC, including the test suite (section A.5) but excluding the rest of Appendix A. It does not include any code or documentation that is identified in the RFC as being copyrighted. The original and principal author of md5.c is L. Peter Deutsch . Other authors are noted in the change history that follows (in reverse chronological order): 2002-04-13 lpd Clarified derivation from RFC 1321; now handles byte order either statically or dynamically; added missing #include in library. 2002-03-11 lpd Corrected argument list for main(), and added int return type, in test program and T value program. 2002-02-21 lpd Added missing #include in test program. 2000-07-03 lpd Patched to eliminate warnings about "constant is unsigned in ANSI C, signed in traditional"; made test program self-checking. 1999-11-04 lpd Edited comments slightly for automatic TOC extraction. 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5). 1999-05-03 lpd Original version. */ #include "md5.h" #include #undef BYTE_ORDER /* 1 = big-endian, -1 = little-endian, 0 = unknown */ #ifdef ARCH_IS_BIG_ENDIAN # define BYTE_ORDER (ARCH_IS_BIG_ENDIAN ? 1 : -1) #else # define BYTE_ORDER 0 #endif #define T_MASK ((md5_word_t)~0) #define T1 /* 0xd76aa478 */ (T_MASK ^ 0x28955b87) #define T2 /* 0xe8c7b756 */ (T_MASK ^ 0x173848a9) #define T3 0x242070db #define T4 /* 0xc1bdceee */ (T_MASK ^ 0x3e423111) #define T5 /* 0xf57c0faf */ (T_MASK ^ 0x0a83f050) #define T6 0x4787c62a #define T7 /* 0xa8304613 */ (T_MASK ^ 0x57cfb9ec) #define T8 /* 0xfd469501 */ (T_MASK ^ 0x02b96afe) #define T9 0x698098d8 #define T10 /* 0x8b44f7af */ (T_MASK ^ 0x74bb0850) #define T11 /* 0xffff5bb1 */ (T_MASK ^ 0x0000a44e) #define T12 /* 0x895cd7be */ (T_MASK ^ 0x76a32841) #define T13 0x6b901122 #define T14 /* 0xfd987193 */ (T_MASK ^ 0x02678e6c) #define T15 /* 0xa679438e */ (T_MASK ^ 0x5986bc71) #define T16 0x49b40821 #define T17 /* 0xf61e2562 */ (T_MASK ^ 0x09e1da9d) #define T18 /* 0xc040b340 */ (T_MASK ^ 0x3fbf4cbf) #define T19 0x265e5a51 #define T20 /* 0xe9b6c7aa */ (T_MASK ^ 0x16493855) #define T21 /* 0xd62f105d */ (T_MASK ^ 0x29d0efa2) #define T22 0x02441453 #define T23 /* 0xd8a1e681 */ (T_MASK ^ 0x275e197e) #define T24 /* 0xe7d3fbc8 */ (T_MASK ^ 0x182c0437) #define T25 0x21e1cde6 #define T26 /* 0xc33707d6 */ (T_MASK ^ 0x3cc8f829) #define T27 /* 0xf4d50d87 */ (T_MASK ^ 0x0b2af278) #define T28 0x455a14ed #define T29 /* 0xa9e3e905 */ (T_MASK ^ 0x561c16fa) #define T30 /* 0xfcefa3f8 */ (T_MASK ^ 0x03105c07) #define T31 0x676f02d9 #define T32 /* 0x8d2a4c8a */ (T_MASK ^ 0x72d5b375) #define T33 /* 0xfffa3942 */ (T_MASK ^ 0x0005c6bd) #define T34 /* 0x8771f681 */ (T_MASK ^ 0x788e097e) #define T35 0x6d9d6122 #define T36 /* 0xfde5380c */ (T_MASK ^ 0x021ac7f3) #define T37 /* 0xa4beea44 */ (T_MASK ^ 0x5b4115bb) #define T38 0x4bdecfa9 #define T39 /* 0xf6bb4b60 */ (T_MASK ^ 0x0944b49f) #define T40 /* 0xbebfbc70 */ (T_MASK ^ 0x4140438f) #define T41 0x289b7ec6 #define T42 /* 0xeaa127fa */ (T_MASK ^ 0x155ed805) #define T43 /* 0xd4ef3085 */ (T_MASK ^ 0x2b10cf7a) #define T44 0x04881d05 #define T45 /* 0xd9d4d039 */ (T_MASK ^ 0x262b2fc6) #define T46 /* 0xe6db99e5 */ (T_MASK ^ 0x1924661a) #define T47 0x1fa27cf8 #define T48 /* 0xc4ac5665 */ (T_MASK ^ 0x3b53a99a) #define T49 /* 0xf4292244 */ (T_MASK ^ 0x0bd6ddbb) #define T50 0x432aff97 #define T51 /* 0xab9423a7 */ (T_MASK ^ 0x546bdc58) #define T52 /* 0xfc93a039 */ (T_MASK ^ 0x036c5fc6) #define T53 0x655b59c3 #define T54 /* 0x8f0ccc92 */ (T_MASK ^ 0x70f3336d) #define T55 /* 0xffeff47d */ (T_MASK ^ 0x00100b82) #define T56 /* 0x85845dd1 */ (T_MASK ^ 0x7a7ba22e) #define T57 0x6fa87e4f #define T58 /* 0xfe2ce6e0 */ (T_MASK ^ 0x01d3191f) #define T59 /* 0xa3014314 */ (T_MASK ^ 0x5cfebceb) #define T60 0x4e0811a1 #define T61 /* 0xf7537e82 */ (T_MASK ^ 0x08ac817d) #define T62 /* 0xbd3af235 */ (T_MASK ^ 0x42c50dca) #define T63 0x2ad7d2bb #define T64 /* 0xeb86d391 */ (T_MASK ^ 0x14792c6e) static void md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/) { md5_word_t a = pms->abcd[0], b = pms->abcd[1], c = pms->abcd[2], d = pms->abcd[3]; md5_word_t t; #if BYTE_ORDER > 0 /* Define storage only for big-endian CPUs. */ md5_word_t X[16]; #else /* Define storage for little-endian or both types of CPUs. */ md5_word_t xbuf[16]; const md5_word_t *X; #endif { #if BYTE_ORDER == 0 /* * Determine dynamically whether this is a big-endian or * little-endian machine, since we can use a more efficient * algorithm on the latter. */ static const int w = 1; if (*((const md5_byte_t *)&w)) /* dynamic little-endian */ #endif #if BYTE_ORDER <= 0 /* little-endian */ { /* * On little-endian machines, we can process properly aligned * data without copying it. */ if (!((data - (const md5_byte_t *)0) & 3)) { /* data are properly aligned */ X = (const md5_word_t *)data; } else { /* not aligned */ memcpy(xbuf, data, 64); X = xbuf; } } #endif #if BYTE_ORDER == 0 else /* dynamic big-endian */ #endif #if BYTE_ORDER >= 0 /* big-endian */ { /* * On big-endian machines, we must arrange the bytes in the * right order. */ const md5_byte_t *xp = data; int i; # if BYTE_ORDER == 0 X = xbuf; /* (dynamic only) */ # else # define xbuf X /* (static only) */ # endif for (i = 0; i < 16; ++i, xp += 4) xbuf[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24); } #endif } #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) /* Round 1. */ /* Let [abcd k s i] denote the operation a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */ #define F(x, y, z) (((x) & (y)) | (~(x) & (z))) #define SET(a, b, c, d, k, s, Ti)\ t = a + F(b,c,d) + X[k] + Ti;\ a = ROTATE_LEFT(t, s) + b /* Do the following 16 operations. */ SET(a, b, c, d, 0, 7, T1); SET(d, a, b, c, 1, 12, T2); SET(c, d, a, b, 2, 17, T3); SET(b, c, d, a, 3, 22, T4); SET(a, b, c, d, 4, 7, T5); SET(d, a, b, c, 5, 12, T6); SET(c, d, a, b, 6, 17, T7); SET(b, c, d, a, 7, 22, T8); SET(a, b, c, d, 8, 7, T9); SET(d, a, b, c, 9, 12, T10); SET(c, d, a, b, 10, 17, T11); SET(b, c, d, a, 11, 22, T12); SET(a, b, c, d, 12, 7, T13); SET(d, a, b, c, 13, 12, T14); SET(c, d, a, b, 14, 17, T15); SET(b, c, d, a, 15, 22, T16); #undef SET /* Round 2. */ /* Let [abcd k s i] denote the operation a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */ #define G(x, y, z) (((x) & (z)) | ((y) & ~(z))) #define SET(a, b, c, d, k, s, Ti)\ t = a + G(b,c,d) + X[k] + Ti;\ a = ROTATE_LEFT(t, s) + b /* Do the following 16 operations. */ SET(a, b, c, d, 1, 5, T17); SET(d, a, b, c, 6, 9, T18); SET(c, d, a, b, 11, 14, T19); SET(b, c, d, a, 0, 20, T20); SET(a, b, c, d, 5, 5, T21); SET(d, a, b, c, 10, 9, T22); SET(c, d, a, b, 15, 14, T23); SET(b, c, d, a, 4, 20, T24); SET(a, b, c, d, 9, 5, T25); SET(d, a, b, c, 14, 9, T26); SET(c, d, a, b, 3, 14, T27); SET(b, c, d, a, 8, 20, T28); SET(a, b, c, d, 13, 5, T29); SET(d, a, b, c, 2, 9, T30); SET(c, d, a, b, 7, 14, T31); SET(b, c, d, a, 12, 20, T32); #undef SET /* Round 3. */ /* Let [abcd k s t] denote the operation a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */ #define H(x, y, z) ((x) ^ (y) ^ (z)) #define SET(a, b, c, d, k, s, Ti)\ t = a + H(b,c,d) + X[k] + Ti;\ a = ROTATE_LEFT(t, s) + b /* Do the following 16 operations. */ SET(a, b, c, d, 5, 4, T33); SET(d, a, b, c, 8, 11, T34); SET(c, d, a, b, 11, 16, T35); SET(b, c, d, a, 14, 23, T36); SET(a, b, c, d, 1, 4, T37); SET(d, a, b, c, 4, 11, T38); SET(c, d, a, b, 7, 16, T39); SET(b, c, d, a, 10, 23, T40); SET(a, b, c, d, 13, 4, T41); SET(d, a, b, c, 0, 11, T42); SET(c, d, a, b, 3, 16, T43); SET(b, c, d, a, 6, 23, T44); SET(a, b, c, d, 9, 4, T45); SET(d, a, b, c, 12, 11, T46); SET(c, d, a, b, 15, 16, T47); SET(b, c, d, a, 2, 23, T48); #undef SET /* Round 4. */ /* Let [abcd k s t] denote the operation a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */ #define I(x, y, z) ((y) ^ ((x) | ~(z))) #define SET(a, b, c, d, k, s, Ti)\ t = a + I(b,c,d) + X[k] + Ti;\ a = ROTATE_LEFT(t, s) + b /* Do the following 16 operations. */ SET(a, b, c, d, 0, 6, T49); SET(d, a, b, c, 7, 10, T50); SET(c, d, a, b, 14, 15, T51); SET(b, c, d, a, 5, 21, T52); SET(a, b, c, d, 12, 6, T53); SET(d, a, b, c, 3, 10, T54); SET(c, d, a, b, 10, 15, T55); SET(b, c, d, a, 1, 21, T56); SET(a, b, c, d, 8, 6, T57); SET(d, a, b, c, 15, 10, T58); SET(c, d, a, b, 6, 15, T59); SET(b, c, d, a, 13, 21, T60); SET(a, b, c, d, 4, 6, T61); SET(d, a, b, c, 11, 10, T62); SET(c, d, a, b, 2, 15, T63); SET(b, c, d, a, 9, 21, T64); #undef SET /* Then perform the following additions. (That is increment each of the four registers by the value it had before this block was started.) */ pms->abcd[0] += a; pms->abcd[1] += b; pms->abcd[2] += c; pms->abcd[3] += d; } void md5_init(md5_state_t *pms) { pms->count[0] = pms->count[1] = 0; pms->abcd[0] = 0x67452301; pms->abcd[1] = /*0xefcdab89*/ T_MASK ^ 0x10325476; pms->abcd[2] = /*0x98badcfe*/ T_MASK ^ 0x67452301; pms->abcd[3] = 0x10325476; } void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes) { const md5_byte_t *p = data; int left = nbytes; int offset = (pms->count[0] >> 3) & 63; md5_word_t nbits = (md5_word_t)(nbytes << 3); if (nbytes <= 0) return; /* Update the message length. */ pms->count[1] += nbytes >> 29; pms->count[0] += nbits; if (pms->count[0] < nbits) pms->count[1]++; /* Process an initial partial block. */ if (offset) { int copy = (offset + nbytes > 64 ? 64 - offset : nbytes); memcpy(pms->buf + offset, p, copy); if (offset + copy < 64) return; p += copy; left -= copy; md5_process(pms, pms->buf); } /* Process full blocks. */ for (; left >= 64; p += 64, left -= 64) md5_process(pms, p); /* Process a final partial block. */ if (left) memcpy(pms->buf, p, left); } void md5_finish(md5_state_t *pms, md5_byte_t digest[16]) { static const md5_byte_t pad[64] = { 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; md5_byte_t data[8]; int i; /* Save the length before padding. */ for (i = 0; i < 8; ++i) data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3)); /* Pad to 56 bytes mod 64. */ md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1); /* Append the length. */ md5_append(pms, data, 8); for (i = 0; i < 16; ++i) digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3)); } ptunnel-ng-1.43/src/md5.h000066400000000000000000000065341460452726400151770ustar00rootroot00000000000000/* Copyright (C) 1999, 2002 Aladdin Enterprises. All rights reserved. This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. L. Peter Deutsch ghost@aladdin.com */ /* $Id: md5.h,v 1.1 2005/04/15 07:37:22 daniels Exp $ */ /* Independent implementation of MD5 (RFC 1321). This code implements the MD5 Algorithm defined in RFC 1321, whose text is available at http://www.ietf.org/rfc/rfc1321.txt The code is derived from the text of the RFC, including the test suite (section A.5) but excluding the rest of Appendix A. It does not include any code or documentation that is identified in the RFC as being copyrighted. The original and principal author of md5.h is L. Peter Deutsch . Other authors are noted in the change history that follows (in reverse chronological order): 2002-04-13 lpd Removed support for non-ANSI compilers; removed references to Ghostscript; clarified derivation from RFC 1321; now handles byte order either statically or dynamically. 1999-11-04 lpd Edited comments slightly for automatic TOC extraction. 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5); added conditionalization for C++ compilation from Martin Purschke . 1999-05-03 lpd Original version. */ #ifndef md5_INCLUDED # define md5_INCLUDED /* * This package supports both compile-time and run-time determination of CPU * byte order. If ARCH_IS_BIG_ENDIAN is defined as 0, the code will be * compiled to run only on little-endian CPUs; if ARCH_IS_BIG_ENDIAN is * defined as non-zero, the code will be compiled to run only on big-endian * CPUs; if ARCH_IS_BIG_ENDIAN is not defined, the code will be compiled to * run on either big- or little-endian CPUs, but will run slightly less * efficiently on either one than if ARCH_IS_BIG_ENDIAN is defined. */ typedef unsigned char md5_byte_t; /* 8-bit byte */ typedef unsigned int md5_word_t; /* 32-bit word */ #define MD5_LEN 16 /* Define the state of the MD5 Algorithm. */ typedef struct md5_state_s { md5_word_t count[2]; /* message length in bits, lsw first */ md5_word_t abcd[4]; /* digest buffer */ md5_byte_t buf[64]; /* accumulate block */ } md5_state_t; #ifdef __cplusplus extern "C" { #endif /* Initialize the algorithm. */ void md5_init(md5_state_t *pms); /* Append a string to the message. */ void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes); /* Finish the message and return the digest. */ void md5_finish(md5_state_t *pms, md5_byte_t digest[MD5_LEN]); #ifdef __cplusplus } /* end extern "C" */ #endif #endif /* md5_INCLUDED */ ptunnel-ng-1.43/src/options.c000066400000000000000000000441671460452726400162040ustar00rootroot00000000000000/* * options.c * ptunnel is licensed under the BSD license: * * 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: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * - Neither the name of the Yellow Lemon Software nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #ifdef WIN32 #include #endif #ifdef ENABLE_SHA512 #include #endif #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "options.h" #include "utils.h" #include "ptunnel.h" #include "md5.h" struct options opts; enum option_type { OPT_BOOL, OPT_DEC32, OPT_HEX32, OPT_STR }; struct option_usage { const char *short_help; int required; enum option_type otype; union { int32_t num; uint32_t unum; const char *str; }; const char *long_help; }; static const struct option_usage usage[] = { /** --magic */ {"magic", 0, OPT_HEX32, {.unum = 0xdeadc0de}, "Set ptunnel magic hexadecimal number. (32-bit unsigned)\n" "It is an identifier for all ICMP/UDP packets\n" "and can be used to bypass Cisco IPS fingerprint scan.\n" "This value has to be the same on the server and client!\n" }, /** --proxy */ {"address", 1, OPT_STR, {.str = NULL}, "Set address of peer running packet forwarder. This causes\n" "ptunnel to operate in forwarding mode (Client) - the absence of this\n" "option causes ptunnel to operate in proxy mode (Server).\n" }, /** --listen */ {"port", 0, OPT_DEC32, {.unum = 2222}, "Set TCP listening port (only used when operating in forward mode)\n" }, /** --remote-addr */ {"address", 1, OPT_STR, {.str = "127.0.0.1"}, "Set remote proxy destination address if client\n" "Restrict to only this destination address if server\n" }, /** --remote-port */ {"port", 1, OPT_DEC32, {.unum = 22}, "Set remote proxy destination port if client\n" "Restrict to only this destination port if server\n" }, /** --connections */ {"connections", 0, OPT_DEC32, {.unum = kMax_tunnels}, "Set maximum number of concurrent tunnels\n" }, /** --verbosity */ {"level", 0, OPT_DEC32, {.num = kLog_event}, "Verbosity level (-1 to 4, where -1 is no output, and 4 is all output)\n" "The special level 5 (or higher) includes xfer logging (lots of output)\n" }, /** --libpcap */ {"interface", 0, OPT_STR, {.str = NULL}, #ifndef HAVE_PCAP "(Not available on this platform.)\n" #endif "Enable libpcap on the given device.\n" }, /** --list-libpcap-devices */ {NULL, 0, OPT_BOOL, {.num = 0}, #ifndef HAVE_PCAP "(Not available on this platform.)\n" #endif "List all available pcap devices.\n" }, /** --logfile */ {"file", 0, OPT_STR, {.str = "/var/log/ptunnel.log"}, "Specify a file to log to, rather than printing to standard out.\n" }, /** --statistics */ {NULL, 0, OPT_BOOL, {.num = 0}, "Client only. Enables continuous output of statistics (packet loss, etc.)\n" }, /** --passwd */ {"password", 0, OPT_STR, {.str = NULL}, "Set a password (must be same on client and proxy)\n" "DEPRECATED: Will be removed/replaced soon!\n" }, /** --udp */ {NULL, 0, OPT_BOOL, {.num = 0}, "Toggle use of UDP instead of ICMP. Proxy will listen on port 53 (must be root).\n" }, /** --unprivileged */ {NULL, 0, OPT_BOOL, {.num = 0}, "Run proxy in unprivileged mode. This causes the proxy to forward\n" "packets using standard echo requests, instead of crafting custom echo replies.\n" "Unprivileged mode will only work on some systems, and is in general less reliable\n" "than running in privileged mode.\n" }, /** --force-sha512 */ {"force-sha512", 0, OPT_BOOL, {.num = 0}, "Force SHA512 as challenge response checksum generator.\n" #ifdef ENABLE_SHA512 "This is the default for this configuration.\n" #else "SHA512 is not available for this configuration.\n" #endif }, /** --daemon */ #ifdef __FreeBSD__ {"pidfile", 0, OPT_STR, {.str = "/var/run/ptunnel.pid"}, #else {"pidfile", 0, OPT_STR, {.str = "/run/ptunnel.pid"}, #endif #ifdef WIN32 "(Not available on this platform.)\n" #endif "Run in background, the PID will be written in the file supplied as argument\n" }, /** --syslog */ {NULL, 0, OPT_BOOL, {.num = 0}, #ifdef WIN32 "(Not available on this platform.)\n" #endif "Output debug to syslog instead of standard out.\n" }, /** --user */ {"user", 0, OPT_STR, {.str = "nobody"}, #ifdef WIN32 "(Not available on this platform.)\n" #endif "When started in privileged mode, drop down to user's rights as soon as possible\n" }, /** --group */ {"group", 0, OPT_STR, {.str = "nogroup"}, #ifdef WIN32 "(Not available on this platform.)\n" #endif "When started in privileged mode, drop down to group's rights as soon as possible\n" }, /** --chroot */ {"directory", 0, OPT_STR, {.str = "/var/lib/ptunnel"}, #ifdef WIN32 "(Not available on this platform.)\n" #endif "When started in privileged mode, restrict file access to the specified directory\n" }, /** --setcon */ {"context", 0, OPT_STR, {.str = "ptunnel"}, #ifndef HAVE_SELINUX "(Not available on this platform.)\n" #endif "Set SELinux context when all there is left to do are network I/O operations\n" "To combine with --chroot you will have to `mount --bind /proc /chrootdir/proc`\n" }, /** --help */ {NULL, 0, OPT_STR, {.str = NULL}, "this\n"}, {NULL,0,OPT_BOOL,{.unum=0},NULL} }; static struct option long_options[] = { {"magic", required_argument, 0, 'm'}, {"proxy", required_argument, 0, 'p'}, {"listen", required_argument, 0, 'l'}, {"remote-addr", optional_argument, 0, 'r'}, {"remote-port", optional_argument, 0, 'R'}, {"connections", required_argument, 0, 'c'}, {"verbosity", required_argument, 0, 'v'}, {"libpcap", required_argument, 0, 'L'}, {"list-libpcap-devices", no_argument, &opts.list_pcap_devices, 1}, {"logfile", optional_argument, 0, 'o'}, {"statistics", no_argument, 0, 's'}, {"passwd", required_argument, 0, 'P'}, {"udp", no_argument, &opts.udp, 1}, {"unprivileged", no_argument, &opts.unprivileged, 1}, {"force-sha512", no_argument, &opts.force_sha512, 1}, {"daemon", optional_argument, 0, 'd'}, {"syslog", no_argument, 0, 'S'}, {"user", optional_argument, 0, 'u'}, {"group", optional_argument, 0, 'g'}, {"chroot", optional_argument, 0, 'C'}, {"setcon", optional_argument, 0, 'e'}, {"help", no_argument, 0, 'h'}, {NULL,0,0,0} }; static const void *get_default_optval(enum option_type opttype, const char *optname) { (void) opttype; for (unsigned i = 0; i < ARRAY_SIZE(long_options); ++i) { if (strncmp(long_options[i].name, optname, BUFSIZ /* not optimal */) == 0 && strlen(long_options[i].name) == strlen(optname)) { assert(usage[i].otype == opttype && (usage[i].otype != OPT_STR || usage[i].str)); return &usage[i].str; } } assert(NULL); return NULL; } static void set_options_defaults(void) { #ifndef WIN32 char *tmp; struct passwd *pwnam; struct group *grnam; #endif memset(&opts, 0, sizeof(opts)); opts.magic = *(uint32_t *) get_default_optval(OPT_HEX32, "magic"); opts.mode = kMode_proxy; opts.tcp_listen_port = *(uint32_t *) get_default_optval(OPT_DEC32, "listen"); opts.given_dst_hostname = strdup(*(char **) get_default_optval(OPT_STR, "remote-addr")); opts.given_dst_port = *(uint32_t *) get_default_optval(OPT_DEC32, "remote-port"); opts.max_tunnels = *(uint32_t *) get_default_optval(OPT_DEC32, "connections"); opts.log_level = *(int *) get_default_optval(OPT_DEC32, "verbosity"); opts.log_path = strdup(*(char **)get_default_optval(OPT_STR, "logfile")); opts.log_file = stdout; opts.print_stats = *(int *) get_default_optval(OPT_BOOL, "statistics"); #ifndef WIN32 opts.pid_path = strdup(*(char **)get_default_optval(OPT_STR, "daemon")); errno = 0; tmp = *(char **) get_default_optval(OPT_STR, "user"); if (NULL == (pwnam = getpwnam(tmp))) pt_log(kLog_error, "%s: %s\n", tmp, errno ? strerror(errno) : "unknown user"); else { opts.uid = pwnam->pw_uid; if (!opts.gid) opts.gid = pwnam->pw_gid; } errno = 0; tmp = *(char **) get_default_optval(OPT_STR, "group"); if (NULL != (grnam = getgrnam(tmp))) opts.gid = grnam->gr_gid; opts.root_dir = strdup(*(char **)get_default_optval(OPT_STR, "chroot")); #endif #ifdef HAVE_SELINUX opts.selinux_context = strdup(*(char **)get_default_optval(OPT_STR, "setcon")); #endif } static void print_multiline(const char *prefix, const char *multiline) { const char sep[] = "\n"; const char *start, *end; start = multiline; end = NULL; do { if (start) { end = strstr(start, sep); if (end && *end != '\0') { printf("%s%.*s\n", prefix, (int)(end-start), start); start = end + strnlen(sep, BUFSIZ /* not optimal */); } } } while (start && end); } static void print_long_help(unsigned index, int required_state) { const char spaces[] = " "; if (usage[index].required != required_state) return; if (!long_options[index].name) return; if (isalpha(long_options[index].val)) { printf("%.*s-%c --%s\n", 4, spaces, long_options[index].val, long_options[index].name); } else { printf("%.*s--%s\n", 4, spaces, long_options[index].name); } if (usage[index].long_help) { print_multiline(&spaces[4], usage[index].long_help); } switch (usage[index].otype) { case OPT_BOOL: break; case OPT_DEC32: printf("%s(default: %d)\n", spaces, usage[index].num); break; case OPT_HEX32: printf("%s(default: 0x%X)\n", spaces, usage[index].unum); break; case OPT_STR: if (usage[index].str) printf("%s(default: %s)\n", spaces, usage[index].str); break; } } static void print_short_help(unsigned index, int required_state) { const char *ob = (required_state == 0 ? "[" : ""); const char *cb = (required_state == 0 ? "]" : ""); const char *ov = (long_options[index].has_arg != optional_argument ? " " : ""); if (usage[index].required != required_state) return; if (!long_options[index].name) return; if (!usage[index].short_help && isalpha(long_options[index].val)) { printf(" %s-%c%s", ob, long_options[index].val, cb); } else if (!usage[index].short_help) { printf(" %s--%s%s", ob, long_options[index].name, cb); } else if (isalpha(long_options[index].val)) { printf(" %s-%c%s<%s>%s", ob, long_options[index].val, ov, usage[index].short_help, cb); } else { printf(" %s--%s <%s>%s", ob, long_options[index].name, usage[index].short_help, cb); } } void print_usage(const char *arg0) { unsigned i; printf("%s\n\nUsage: %s", PACKAGE_STRING, arg0); /* print (short)help argument line */ for (i = 0; i < ARRAY_SIZE(usage); ++i) { print_short_help(i, 1); } for (i = 0; i < ARRAY_SIZE(usage); ++i) { print_short_help(i, 0); } printf("%s", "\n\n"); /* print (long)help lines */ for (i = 0; i < ARRAY_SIZE(usage); ++i) { print_long_help(i, 1); } for (i = 0; i < ARRAY_SIZE(usage); ++i) { print_long_help(i, 0); } } int parse_options(int argc, char **argv) { int c = 0, oidx = -1, has_logfile = 0, ret; md5_state_t state; #ifndef WIN32 struct passwd *pwnam; struct group *grnam; #endif FILE *tmp_log; assert( ARRAY_SIZE(long_options) == ARRAY_SIZE(usage) ); /* set defaults */ set_options_defaults(); /* parse command line arguments */ while (1) { /* FIXME: We are using '::' (optional argument values). This is not optimal * since you have to pass long options as '--option=value'. Commonly used * '--option value' is *NOT* allowed for some libc implementations. */ c = getopt_long(argc, argv, "m:p:l:r::R::c:v:L:o::sP:d::Su::g::C::e::h", &long_options[0], &oidx); if (c == -1) break; switch (c) { case 'm': if (!optarg) break; opts.magic = strtoul(optarg, NULL, 16); break; case 'p': if (!optarg) break; opts.mode = kMode_forward; if (opts.given_proxy_hostname) free(opts.given_proxy_hostname); opts.given_proxy_hostname = strdup(optarg); break; case 'l': if (!optarg) break; opts.tcp_listen_port = strtoul(optarg, NULL, 10); break; case 'r': opts.restrict_dst_ip = 1; if (!optarg) break; if (opts.given_dst_hostname) free(opts.given_dst_hostname); opts.given_dst_hostname = strdup(optarg); break; case 'R': opts.restrict_dst_port = 1; if (optarg) opts.given_dst_port = strtoul(optarg, NULL, 10); break; case 'c': if (!optarg) break; opts.max_tunnels = strtoul(optarg, NULL,10); if (opts.max_tunnels > kMax_tunnels) opts.max_tunnels = kMax_tunnels; break; case 'v': if (!optarg) break; opts.log_level = strtol(optarg, NULL, 10); break; case 'L': #ifdef HAVE_PCAP opts.pcap = 1; if (!optarg) break; if (opts.pcap_device) free(opts.pcap_device); opts.pcap_device = strdup(optarg); break; #else pt_log(kLog_error, "pcap: %s\n", "feature not supported"); exit(1); #endif case 'o': has_logfile = 1; if (!optarg) break; if (opts.log_path) free(opts.log_path); opts.log_path = strdup(optarg); break; case 's': opts.print_stats = !opts.print_stats; break; case 'P': if (!optarg) break; if (opts.password) free(opts.password); opts.password = strdup(optarg); pt_log(kLog_debug, "%s\n", "Password set - unauthenicated connections will be refused."); /* Compute the md5 password digest */ md5_init(&state); md5_append(&state, (md5_byte_t *)optarg, strnlen(opts.password, BUFSIZ /* not optimal */)); md5_finish(&state, &opts.md5_password_digest[0]); #ifdef ENABLE_SHA512 pt_log(kLog_debug, "%s\n", "Password set - sha512 authentication enabled."); SHA512((const unsigned char *)optarg, strnlen(opts.password, BUFSIZ /* not optimal */), &opts.sha512_password_digest[0]); #endif // Hide the password in process listing memset(optarg, '*', strnlen(optarg, BUFSIZ /* not optimal */)); break; #ifndef WIN32 case 'd': opts.daemonize = true; if (!optarg) break; if (opts.pid_path) free(opts.pid_path); opts.pid_path = strdup(optarg); break; case 'S': opts.use_syslog = 1; break; case 'u': if (!optarg) break; errno = 0; if (NULL == (pwnam = getpwnam(optarg))) { pt_log(kLog_error, "%s: %s\n", optarg, errno ? strerror(errno) : "unknown user"); exit(1); } opts.uid = pwnam->pw_uid; if (!opts.gid) opts.gid = pwnam->pw_gid; break; case 'g': if (!optarg) break; errno = 0; if (NULL == (grnam = getgrnam(optarg))) { pt_log(kLog_error, "%s: %s\n", optarg, errno ? strerror(errno) : "unknown group"); exit(1); } opts.gid = grnam->gr_gid; break; case 'C': opts.chroot = 1; if (!optarg) break; if (opts.root_dir) free(opts.root_dir); opts.root_dir = strdup(optarg); break; #else case 'd': case 'S': case 'u': case 'g': case 'C': pt_log(kLog_error, "-%c: %s\n", c, "feature not supported"); exit(1); #endif case 'e': #ifdef HAVE_SELINUX opts.selinux = 1; if (!optarg) break; if (opts.selinux_context) free(opts.selinux_context); opts.selinux_context = strdup(optarg); break; #else pt_log(kLog_error, "SeLinux: %s\n", "feature not supported"); exit(1); #endif case 'h': print_usage(argv[0]); exit(EXIT_SUCCESS); case 0: /* long opt only */ default: break; } } if (optind != argc) { pt_log(kLog_error, "Unknown argument: '%s'\n", argv[optind]); exit(1); } #ifndef ENABLE_SHA512 if (opts.force_sha512) { pt_log(kLog_error, "%s\n", "You are forcing sha512 but it isn't available."); return 1; } #endif if (opts.given_proxy_hostname) { if ((ret = host_to_addr(opts.given_proxy_hostname, &opts.given_proxy_ip)) != 0) { pt_log(kLog_error, "Failed to look up %s as destination address: %s\n", opts.given_proxy_hostname, gai_strerror(ret)); return 1; } } if ((ret = host_to_addr(opts.given_dst_hostname, &opts.given_dst_ip)) != 0) { pt_log(kLog_error, "Failed to look up %s as destination address: %s\n", opts.given_dst_hostname, gai_strerror(ret)); return 1; } #ifndef WIN32 if (NULL == (opts.pid_file = fopen(opts.pid_path, "w"))) pt_log(kLog_error, "Failed to open pidfile: \"%s\", Cause: %s\n", opts.pid_path, strerror(errno)); #endif if (has_logfile && opts.log_path) { pt_log(kLog_info, "Open Logfile: \"%s\"\n", opts.log_path); tmp_log = fopen(opts.log_path, "a"); if (!tmp_log) { pt_log(kLog_error, "Failed to open log file: \"%s\", Cause: %s\n", opts.log_path, strerror(errno)); pt_log(kLog_error, "Reverting log to standard out.\n"); } else opts.log_file = tmp_log; } return 0; } ptunnel-ng-1.43/src/options.h000066400000000000000000000076311460452726400162040ustar00rootroot00000000000000/* * options.h * ptunnel is licensed under the BSD license: * * 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: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * - Neither the name of the Yellow Lemon Software nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #ifndef OPTIONS_H #define OPTIONS_H 1 #include #include #include #ifndef WIN32 #include #include #endif #ifdef HAVE_SELINUX #include #endif #include "md5.h" #include "pconfig.h" struct options { /** user defined magic value (prevent Cisco WSA/IronPort fingerprint scan) */ uint32_t magic; /** proxy or forwarder? */ int mode; /** Proxy's internet address */ char *given_proxy_hostname; uint32_t given_proxy_ip; /** Port the client listens on */ uint32_t tcp_listen_port; /** restrict Forward/Proxy destination internet address */ int restrict_dst_ip; char *given_dst_hostname; uint32_t given_dst_ip; /** restrict Forward/Proxy destination port */ int restrict_dst_port; uint32_t given_dst_port; /** Default maximum number of tunnels to support at once */ uint32_t max_tunnels; /** Default log level */ int log_level; #ifdef HAVE_PCAP /** Non zero value if user wants packet capturing */ int pcap; /** Device to capture packets from */ char *pcap_device; #endif /** Force SHA512 based challenge response. */ int force_sha512; /** List all available pcap devices and exit */ int list_pcap_devices; /** Usually stdout, but can be altered by the user */ char *log_path; FILE *log_file; /** Print more detailed traffic statistics if non zero value */ int print_stats; /** Password (must be the same on proxy and client for authentica tion to succeed) */ char *password; /** MD5 digest of password */ md5_byte_t md5_password_digest[kMD5_digest_size]; /** SHA512 digest of password */ unsigned char sha512_password_digest[kSHA512_digest_size]; /** use UDP instead of ICMP */ int udp; /** unpriviledged mode */ int unprivileged; #ifndef WIN32 /** run as daemon if non zero value */ int daemonize; /** PIDFILE if running as daemon */ char *pid_path; FILE *pid_file; /** log to syslog if non zero value */ int use_syslog; /** UID of the running process */ uid_t uid; /** GID of the running process */ gid_t gid; /** CHROOT dir */ int chroot; char *root_dir; #endif #ifdef HAVE_SELINUX /** Non zero value if uer wants SeLinux */ int selinux; /** SeLinux context name */ char *selinux_context; #endif }; extern struct options opts; void print_usage(const char *arg0); int parse_options(int argc, char **argv); #endif ptunnel-ng-1.43/src/pconfig.h000066400000000000000000000132011460452726400161240ustar00rootroot00000000000000/* * pconfig.h * ptunnel is licensed under the BSD license: * * Copyright (c) 2004-2011, Daniel Stoedle , * Yellow Lemon Software. All rights reserved. * * 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: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * - Neither the name of the Yellow Lemon Software nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * Contacting the author: * You can get in touch with me, Daniel Stødle (that's the Norwegian letter oe, * in case your text editor didn't realize), here: * * The official ptunnel website is here: * * * Note that the source code is best viewed with tabs set to 4 spaces. */ #ifndef PCONFIG_H #define PCONFIG_H 1 enum { /** Set this constant to the number of * concurrent connections you wish to handle by default. */ kMax_tunnels = 10, /** numbers */ kIP_packet_max_size = 576, /** In bytes, mind you */ kIP_header_size = 20, kIP_actual_size = (kIP_packet_max_size - kIP_header_size) - ((kIP_packet_max_size - kIP_header_size) % 8), /** Also in bytes */ kICMP_header_size = 8, /** This constant control the maximum size of * the payload-portion of the ICMP packets * we send. Note that this does not include * the IP or ICMP headers! */ kDefault_buf_size = 1024, /** Type code for echo request and replies */ kICMP_echo_request = 8, kICMP_echo_reply = 0, /** number of packets we can have in our send/receive ring */ kPing_window_size = 64, /** Tunnels are automatically closed after one minute of inactivity. Since * we continously send acknowledgements between the two peers, this mechanism * won't disconnect "valid" connections. */ kAutomatic_close_timeout = 60, // Seconds! /** size of md5 digest in bytes */ kMD5_digest_size = 16, /** size of sha512 digest in bytes */ kSHA512_digest_size = 64, kDNS_port = 53 }; enum oper_mode { /** Ping tunnel's operating mode (client) */ kMode_forward = 0, /** Ping tunnel's operating mode (server) */ kMode_proxy }; enum pkt_flag { /** set when packet comes from a user */ kUser_flag = 1 << 30, /** set when packet comes from the proxy */ kProxy_flag = 1 << 31, kFlag_mask = kUser_flag | kProxy_flag }; enum log_level { /** Different verbosity levels. */ kNo_log = -1, kLog_error = 0, kLog_info, kLog_event, kLog_verbose, kLog_debug, kLog_sendrecv }; enum proxy_state { /** These constants are used to indicate the protocol state. The protocol * works as follows: * - The identifier is used by both the proxy and the forwarder * to identify the session (and thus the relevant sockets). * - The seq-no of the ping packet is used in a sliding-window-esque * way, and to identify the order of data. * * The protocol can be in any of the following states: * kProxy_start Causes the proxy to open a connection to the given * host and port, associating the ID with the socket, * before the data on the socket are transmitted. * kProxy_data Indicates that the packet contains data from the proxy. * Data ordering is indicated by the seq-no, which will start * at 0. (The proxy and forwarder maintain different seq-nos.) * kUser_data This packet contains user data. * kConnection_close Indicates that the connection is being closed. * kProxy_ack and Acknowledges the packet (and all packets before it) with seq_no = ack. * kUser_ack This is used if there are no implicit acknowledgements due to data * being sent. * * Acknowledgements work by the remote peer acknowledging the last * continuous seq no it has received. * * Note: A proxy receiving a kProxy_data packet, or a user receiving a * kUser_data packet, should ignore it, as it is the host operating system * actually returning the ping. This is mostly relevant for users, and for * proxies running in unprivileged mode. */ kProxy_start = 0, kProto_ack, kProto_data, kProto_close, kProto_authenticate, kNum_proto_types }; #endif ptunnel-ng-1.43/src/pdesc.c000066400000000000000000000253211460452726400155760ustar00rootroot00000000000000/* * pdesc.c * ptunnel is licensed under the BSD license: * * Copyright (c) 2004-2011, Daniel Stoedle , * Yellow Lemon Software. All rights reserved. * * 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: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * - Neither the name of the Yellow Lemon Software nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * Contacting the author: * You can get in touch with me, Daniel Stødle (that's the Norwegian letter oe, * in case your text editor didn't realize), here: * * The official ptunnel website is here: * * * Note that the source code is best viewed with tabs set to 4 spaces. */ #include #include #include #include "pdesc.h" #include "options.h" #include "utils.h" #include "ptunnel.h" /* create_and_insert_proxy_desc: Creates a new proxy descriptor, linking it into * 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, int sock, struct sockaddr_in *addr, uint32_t dst_ip, uint32_t dst_port, uint32_t init_state, enum pkt_flag type) { proxy_desc_t *cur; pthread_mutex_lock(&chain_lock); if (num_tunnels >= opts.max_tunnels) { pt_log(kLog_info, "Discarding incoming connection - too many tunnels! Maximum count is %u (adjust with the -m switch).\n", opts.max_tunnels); if (sock) close(sock); pthread_mutex_unlock(&chain_lock); return 0; } num_tunnels++; pthread_mutex_unlock(&chain_lock); 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")); cur = (proxy_desc_t *) calloc(1, sizeof(proxy_desc_t)); cur->id_no = id_no; cur->dest_addr = *addr; cur->dst_ip = dst_ip; cur->dst_port = dst_port; cur->icmp_id = icmp_id; if (!sock) { cur->sock = socket(AF_INET, SOCK_STREAM, 0); memset(addr, 0, sizeof(struct sockaddr_in)); addr->sin_port = htons((uint16_t)dst_port); addr->sin_addr.s_addr = dst_ip; addr->sin_family = AF_INET; /* Let's just assume success, shall we? */ if (cur->sock >= 0 && connect(cur->sock, (struct sockaddr*)addr, sizeof(struct sockaddr_in)) < 0) { 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)); } } else { cur->sock = sock; } cur->state = init_state; cur->type_flag = type; if (cur->type_flag == kUser_flag) { cur->pkt_type = kICMP_echo_request; } else { cur->pkt_type = (opts.unprivileged ? kICMP_echo_request : kICMP_echo_reply); } cur->buf = (char *) malloc(icmp_receive_buf_len); cur->last_activity = time_as_double(); cur->authenticated = 0; pthread_mutex_lock(&chain_lock); cur->next = chain; chain = cur; pthread_mutex_unlock(&chain_lock); cur->xfer.bytes_in = 0.0; cur->xfer.bytes_out = 0.0; cur->window_size = kPing_window_size; cur->ack_interval = 1.0; cur->resend_interval = 1.5; cur->send_ring = (icmp_desc_t *) calloc(cur->window_size, sizeof(icmp_desc_t)); cur->recv_ring = (forward_desc_t **) calloc(cur->window_size, sizeof(forward_desc_t *)); return cur; } /* remove_proxy_desc: Removes the given proxy desc, freeing its resources. * Assumes that we hold the chain_lock. */ void remove_proxy_desc(proxy_desc_t *cur, proxy_desc_t *prev) { struct timeval tt; pt_log(kLog_debug, "Removing proxy descriptor.\n"); /* Get a timestamp, for making an entry in the seq_expiry_tbl */ gettimeofday(&tt, 0); seq_expiry_tbl[cur->id_no] = tt.tv_sec+(2*kAutomatic_close_timeout); /* Free resources associated with connection */ if (cur->buf) free(cur->buf); cur->buf = 0; remove_proxy_desc_rings(cur); close(cur->sock); cur->sock = 0; /* Keep list up-to-date */ if (prev) prev->next = cur->next; else chain = cur->next; if (cur->challenge) free(cur->challenge); free(cur); num_tunnels--; } void remove_proxy_desc_rings(proxy_desc_t *cur) { int i; for (i=0;iwindow_size;i++) { if (cur->send_ring[i].pkt) free(cur->send_ring[i].pkt); cur->send_ring[i].pkt = 0; if (cur->recv_ring[i]) free(cur->recv_ring[i]); cur->recv_ring[i] = 0; } free(cur->send_ring); free(cur->recv_ring); cur->recv_idx = 0; cur->recv_xfer_idx = 0; cur->send_idx = 0; cur->send_first_ack = 0; cur->recv_wait_send = 0; cur->send_wait_ack = 0; cur->next_resend_start = 0; } forward_desc_t* create_fwd_desc(uint16_t seq_no, uint32_t data_len, char *data) { forward_desc_t *fwd_desc; fwd_desc = (forward_desc_t *) malloc(sizeof(forward_desc_t)+data_len); fwd_desc->seq_no = seq_no; fwd_desc->length = data_len; fwd_desc->remaining = data_len; if (data_len > 0) memcpy(fwd_desc->data, data, data_len); return fwd_desc; } /* queue_packet: * Creates an ICMP packet descriptor, and sends it. The packet descriptor is added * to the given send ring, for potential resends later on. */ int queue_packet(int sock_fd, proxy_desc_t *cur, char *buf, size_t bufsiz, uint32_t dest_ip, uint32_t dest_port, uint32_t state) { int pkt_len = sizeof(icmp_echo_packet_t) + sizeof(ping_tunnel_pkt_t) + bufsiz; int err = 0; icmp_echo_packet_t *pkt = 0; ping_tunnel_pkt_t *pt_pkt = 0; uint16_t ack_val; uint8_t * icmp_chksm_ptr; assert(sock_fd >= 0); assert(cur); if (sock_fd < 0 || !cur) return -1; ack_val = cur->next_remote_seq - 1; if (pkt_len % 2) pkt_len++; pkt = (icmp_echo_packet_t *) calloc(1, pkt_len); /* ICMP Echo request or reply */ pkt->type = cur->pkt_type; /* Must be zero (non-zero requires root) */ pkt->code = 0; pkt->identifier = htons(cur->icmp_id); pkt->seq = htons(cur->ping_seq); pkt->checksum = 0; cur->ping_seq++; /* Add our information */ pt_pkt = (ping_tunnel_pkt_t*)pkt->data; pt_pkt->magic = htonl(opts.magic); pt_pkt->dst_ip = dest_ip; pt_pkt->dst_port = htonl(dest_port); pt_pkt->ack = htonl(ack_val); pt_pkt->data_len = htonl(bufsiz); pt_pkt->state = htonl(state); pt_pkt->seq_no = htons(cur->my_seq); pt_pkt->id_no = htons(cur->id_no); /* Copy user data */ if (buf && bufsiz > 0) memcpy(pt_pkt->data, buf, bufsiz); icmp_chksm_ptr = (uint8_t*)pkt; pkt->checksum = htons(calc_icmp_checksum((uint16_t*)icmp_chksm_ptr, pkt_len)); /* Send it! */ pt_log(kLog_sendrecv, "Send: %4d [%4d] bytes " "[id = 0x%04X] [seq = %d] " "[seq_no = %d] [type = %s] " "[ack = %d] [icmp = %d] " "[user = %s]\n", pkt_len, bufsiz, cur->icmp_id, cur->ping_seq, cur->my_seq, state_name[state & (~kFlag_mask)], ack_val, cur->pkt_type, ((state & kUser_flag) == kUser_flag ? "yes" : "no")); log_sendrecv_hexstr("SEND ICMP", pkt, sizeof(*pkt)); log_sendrecv_hexstr("SEND PTNG", pt_pkt, sizeof(*pt_pkt)); if (pkt_len - (pt_pkt->data - (char *)pkt) > 0) { log_sendrecv_hexstr("SEND PAYL", pt_pkt->data, pkt_len - (pt_pkt->data - (char *)pkt)); } err = sendto(sock_fd, (const void*)pkt, pkt_len, 0, (struct sockaddr*)&cur->dest_addr, sizeof(struct sockaddr)); if (err < 0) { pt_log(kLog_error, "Failed to send ICMP packet: %s\n", strerror(errno)); free(pkt); return -1; } else if (err != pkt_len) pt_log(kLog_error, "WARNING WARNING, didn't send entire packet\n"); /* Update sequence no's and so on */ cur->send_ring[cur->send_idx].pkt = pkt; cur->send_ring[cur->send_idx].pkt_len = pkt_len; cur->send_ring[cur->send_idx].last_resend = time_as_double(); cur->send_ring[cur->send_idx].seq_no = cur->my_seq; cur->send_ring[cur->send_idx].icmp_id = cur->icmp_id; cur->my_seq++; if (!cur->send_ring[cur->send_first_ack].pkt) cur->send_first_ack = cur->send_idx; cur->send_wait_ack++; cur->send_idx++; if (cur->send_idx >= cur->window_size) cur->send_idx = 0; return 0; } /* send_packets: * Examines the passed-in ring, and forwards data in it over TCP. */ uint32_t send_packets(forward_desc_t *ring[], int *xfer_idx, int *await_send, int *sock, uint16_t window_size) { forward_desc_t *fwd_desc; int bytes, total = 0; while (*await_send > 0) { fwd_desc = ring[*xfer_idx]; if (!fwd_desc)/* We haven't got this packet yet.. */ break; if (fwd_desc->length > 0) { bytes = send(*sock, &fwd_desc->data[fwd_desc->length - fwd_desc->remaining], fwd_desc->remaining, 0); if (bytes < 0) { printf("Weirdness.\n"); /* TODO: send close stuff */ close(*sock); *sock = 0; break; } fwd_desc->remaining -= bytes; total += bytes; } if (!fwd_desc->remaining) { ring[*xfer_idx] = 0; free(fwd_desc); (*xfer_idx)++; (*await_send)--; if (*xfer_idx >= window_size) *xfer_idx = 0; } else break; } return total; } ptunnel-ng-1.43/src/pdesc.h000066400000000000000000000153151460452726400156050ustar00rootroot00000000000000/* * pdesc.h * ptunnel is licensed under the BSD license: * * Copyright (c) 2004-2011, Daniel Stoedle , * Yellow Lemon Software. All rights reserved. * * 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: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * - Neither the name of the Yellow Lemon Software nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * Contacting the author: * You can get in touch with me, Daniel Stødle (that's the Norwegian letter oe, * in case your text editor didn't realize), here: * * The official ptunnel website is here: * * * Note that the source code is best viewed with tabs set to 4 spaces. */ #ifndef PDESC_H #define PDESC_H 1 #include #ifndef WIN32 #include #include #include #endif #include "pkt.h" #include "challenge.h" #include "pconfig.h" /** forward_desc_t: Describes a piece of that needs to be forwarded. This * structure is used for receiving data from the network, and for subsequent * forwarding over TCP: * * 1. Client sends data to proxy over ICMP * 2. Proxy receives the data, and puts it into a forward_desc_t * 3. The proxy starts send()-ing the data over the TCP socket to the destination, * decreasing forward_desc_t->remaining with the number of bytes transferred. * 4. Once remaining reaches 0, the forward_desc_t is removed from the receive * ring. * * The same procedure is followed in proxy-to-client communication. Just replace * proxy with client and vice versa in the list above. */ typedef struct forward_desc_t { /** ping_tunnel_pkt_t seq_no */ uint16_t seq_no; /** length of data */ uint16_t length; /** amount of data not yet transferred */ size_t remaining; char data[0]; } forward_desc_t; /** icmp_desc_t: This structure is used to track the ICMP packets sent by either * the client or proxy. The last_resend variable is used to prevent resending * the packet too often. Once the packet is acknowledged by the remote end, * it will be removed from the send-ring, freeing up space for more outgoing * ICMP packets. */ typedef struct icmp_desc_t { /** total length of ICMP packet, including ICMP header and ptunnel data. */ uint16_t pkt_len; double last_resend; uint16_t seq_no; uint16_t icmp_id; icmp_echo_packet_t * pkt; } icmp_desc_t; /** xfer_stats_t: Various transfer statistics, such as bytes sent and received, * number of ping packets sent/received, etc. */ typedef struct xfer_stats_t { double bytes_in; double bytes_out; uint32_t icmp_in; uint32_t icmp_out; uint32_t icmp_resent; uint32_t icmp_ack_out; } xfer_stats_t; /** proxy_desc_t: This massive structure describes a tunnel instance. */ typedef struct proxy_desc_t { /** ICMP or UDP socket */ int sock; /** number of bytes in receive buffer */ int bytes; /** set to true once this instance should be removed */ int should_remove; /** data buffer, used to receive ping and pong packets */ char * buf; uint16_t id_no; uint16_t my_seq; uint16_t ping_seq; uint16_t next_remote_seq; uint16_t pkt_type; uint16_t remote_ack_val; uint16_t icmp_id; /** first available slot in recv ring */ int recv_idx; /** current slot in recv ring being transferred */ int recv_xfer_idx; /** first available slot in send ring */ int send_idx; /** first packet in send ring not yet acked */ int send_first_ack; /** number of items in recv ring awaiting send */ int recv_wait_send; /** number of items in send ring awaiting ack */ int send_wait_ack; int next_resend_start; int authenticated; /** Contains the challenge, if used. */ challenge_t * challenge; /** Protocol state */ uint32_t state; /** Either kProxy_flag or kUser_flag */ enum pkt_flag type_flag; /** IP and port to which data should be forwarded. */ uint32_t dst_ip; uint32_t dst_port; /** Same as above */ struct sockaddr_in dest_addr; /** Time when last ack packet was sent. */ double last_ack; /** Time when a packet was last received. */ double last_activity; double last_data_activity; uint16_t window_size; double ack_interval; double resend_interval; icmp_desc_t * send_ring; forward_desc_t ** recv_ring; xfer_stats_t xfer; struct proxy_desc_t * next; } proxy_desc_t; 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, enum pkt_flag type); void remove_proxy_desc(proxy_desc_t * cur, proxy_desc_t * prev); void remove_proxy_desc_rings(proxy_desc_t * cur); forward_desc_t * create_fwd_desc(uint16_t seq_no, uint32_t data_len, char * data); int queue_packet( int sock_fd, proxy_desc_t * cur, char * buf, size_t bufsiz, uint32_t dest_ip, uint32_t dest_port, uint32_t state); uint32_t send_packets(forward_desc_t * ring[], int * xfer_idx, int * await_send, int * sock, uint16_t window_size); #endif ptunnel-ng-1.43/src/pkt.c000066400000000000000000000471611460452726400153040ustar00rootroot00000000000000/* * pkt.c * ptunnel is licensed under the BSD license: * * Copyright (c) 2004-2011, Daniel Stoedle , * Yellow Lemon Software. All rights reserved. * * 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: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * - Neither the name of the Yellow Lemon Software nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * Contacting the author: * You can get in touch with me, Daniel Stødle (that's the Norwegian letter oe, * in case your text editor didn't realize), here: * * The official ptunnel website is here: * * * Note that the source code is best viewed with tabs set to 4 spaces. */ #ifndef WIN32 #include #include #include #endif #include #include "ptunnel.h" #include "pkt.h" #include "pdesc.h" #include "options.h" #include "utils.h" static proxy_desc_t * handle_incoming_tunnel_request(unsigned bytes, struct sockaddr_in * addr, int icmp_sock, icmp_echo_packet_t * const pkt, ping_tunnel_pkt_t * const pt_pkt) { struct timeval tt; struct in_addr in_addr; uint32_t init_state; proxy_desc_t * cur; pt_log(kLog_info, "Incoming tunnel request from %s.\n", inet_ntoa(*(struct in_addr *)&addr->sin_addr)); gettimeofday(&tt, 0); if (tt.tv_sec < seq_expiry_tbl[pt_pkt->id_no]) { pt_log(kLog_verbose, "Dropping request: ID was recently in use.\n"); return NULL; } in_addr.s_addr = pt_pkt->dst_ip; pt_log(kLog_info, "Starting new session to %s:%d with ID %d\n", inet_ntoa(in_addr), ntohl(pt_pkt->dst_port), pt_pkt->id_no); if ((opts.restrict_dst_ip && opts.given_dst_ip && opts.given_dst_ip != pt_pkt->dst_ip) || (opts.restrict_dst_port && (uint32_t)-1 != opts.given_dst_port && opts.given_dst_port != ntohl(pt_pkt->dst_port))) { pt_log(kLog_info, "Destination administratively prohibited!\n"); return NULL; } if (opts.password) { init_state = kProto_authenticate; } else { init_state = kProto_data; } 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_error, "Failed to create proxy descriptor!\n"); return NULL; } if (pt_pkt->data_len > 0) { handle_data(pkt, bytes, cur); } if (init_state == kProto_authenticate) { pt_log(kLog_debug, "Sending authentication challenge..\n"); /* Send challenge */ cur->challenge = generate_challenge(); memcpy(cur->buf, cur->challenge, sizeof(challenge_t)); queue_packet(icmp_sock, cur, cur->buf, sizeof(challenge_t), 0, 0, kProto_authenticate | cur->type_flag); } return cur; } static void handle_auth_request(unsigned bytes, int icmp_sock, icmp_echo_packet_t * const pkt, proxy_desc_t * const cur, challenge_t * const challenge) { if (!opts.password) { pt_log(kLog_error, "This proxy requires a password! " "Please supply one usin g the -x switch.\n"); send_termination_msg(cur, icmp_sock); cur->should_remove = 1; return; } #ifdef ENABLE_SHA512 if (opts.force_sha512) { pt_log(kLog_debug, "Got authentication challenge - sending SHA512 response\n"); generate_response_sha512(&challenge->plain, &challenge->digest); } else #endif { pt_log(kLog_debug, "Got authentication challenge - sending MD5 response\n"); generate_response_md5(&challenge->plain, &challenge->digest); } memcpy(cur->buf, challenge, sizeof(challenge_t)); queue_packet(icmp_sock, cur, cur->buf, sizeof(challenge_t), 0, 0, kProto_authenticate | cur->type_flag); /* We have authenticated locally. * It's up to the proxy now if it accepts our response or not.. */ cur->authenticated = 1; handle_data(pkt, bytes, cur); } static void handle_auth_response(unsigned bytes, int icmp_sock, icmp_echo_packet_t * const pkt, proxy_desc_t * const cur, challenge_t * const challenge) { pt_log(kLog_debug, "Received remote %s challenge response.\n", (challenge->digest.hash_type == HT_SHA512 ? "SHA512" : "MD5")); if ((!opts.force_sha512 && challenge->digest.hash_type == HT_MD5 && validate_challenge_md5(cur->challenge, &challenge->digest)) || #ifdef ENABLE_SHA512 (challenge->digest.hash_type == HT_SHA512 && validate_challenge_sha512(cur->challenge, &challenge->digest)) || #endif cur->authenticated) { pt_log(kLog_verbose, "Remote end authenticated successfully.\n"); /* Authentication has succeeded, so now we can proceed * to handle incoming TCP data. */ cur->authenticated = 1; cur->state = kProto_data; /* Insert the packet into the receive ring, to avoid * confusing the reliab ility mechanism. */ handle_data(pkt, bytes, cur); } else { pt_log(kLog_info, "Remote end failed authentication.\n"); send_termination_msg(cur, icmp_sock); cur->should_remove = 1; } } static void header_byteorder_ntoh(icmp_echo_packet_t * const icmp_pkt, ping_tunnel_pkt_t * const pt_pkt) { pt_pkt->state = ntohl(pt_pkt->state); icmp_pkt->identifier = ntohs(icmp_pkt->identifier); icmp_pkt->seq = ntohs(icmp_pkt->seq); pt_pkt->id_no = ntohs(pt_pkt->id_no); pt_pkt->seq_no = ntohs(pt_pkt->seq_no); } static proxy_desc_t * get_proxy_descriptor(uint16_t id_no) { proxy_desc_t * cur; /* Find the relevant connection, if it exists */ pthread_mutex_lock(&chain_lock); for (cur = chain; cur; cur = cur->next) { if (cur->id_no == id_no) { break; } } pthread_mutex_unlock(&chain_lock); return cur; } /* handle_proxy_packet: * Processes incoming ICMP packets for the proxy. The packet can come either from the * packet capture lib, or from the actual socket or both. * Input: A buffer pointing at the start of an IP header, the buffer length and the proxy * descriptor chain. */ void handle_packet(char * buf, unsigned bytes, int is_pcap, struct sockaddr_in * addr, int icmp_sock) { ip_packet_t * ip_pkt = NULL; icmp_echo_packet_t * pkt; ping_tunnel_pkt_t * pt_pkt; proxy_desc_t * cur; int pkt_flag; enum pkt_flag type_flag, proxy_flag; challenge_t * challenge; proxy_flag = kProxy_flag; if (bytes < sizeof(icmp_echo_packet_t) + sizeof(ping_tunnel_pkt_t)) { pt_log(kLog_verbose, "Skipping this packet - too short. " "Expect: %lu+%lu = %lu ; Got: %u\n", sizeof(icmp_echo_packet_t), sizeof(ping_tunnel_pkt_t), sizeof(icmp_echo_packet_t) + sizeof(ping_tunnel_pkt_t), bytes); return; } if (opts.udp || opts.unprivileged) { pkt = (icmp_echo_packet_t *)buf; pt_pkt = (ping_tunnel_pkt_t *)pkt->data; } else { ip_pkt = (ip_packet_t *)buf; pkt = (icmp_echo_packet_t *)ip_pkt->data; pt_pkt = (ping_tunnel_pkt_t *)pkt->data; } if (ntohl(pt_pkt->magic) != opts.magic) { pt_log(kLog_verbose, "Ignored incoming packet. Magic value 0x%X mismatch.\n", ntohl(pt_pkt->magic)); return; } header_byteorder_ntoh(pkt, pt_pkt); cur = get_proxy_descriptor(pt_pkt->id_no); /* Handle the packet if it comes from "the other end." This is a bit tricky * to get right, since we receive both our own and the other end's packets. * Basically, a proxy will accept any packet from a user, regardless if it * has a valid connection or not. A user will only accept the packet if there * exists a connection to handle it. */ if (cur) { type_flag = cur->type_flag; if (type_flag == kProxy_flag) { cur->icmp_id = pkt->identifier; cur->ping_seq = pkt->seq; } if (!is_pcap) cur->xfer.icmp_in++; } else { type_flag = kProxy_flag; } pkt_flag = (int)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: %4d [%4d] bytes " "[id = 0x%04X] [seq = %d] " "[seq_no = %d] [type = %s] " "[ack = %d] [icmp = %d] " "[user = %s] [pcap = %d]\n", bytes, ntohl(pt_pkt->data_len), pkt->identifier, ntohs(pkt->seq), pt_pkt->seq_no, state_name[pt_pkt->state & (~kFlag_mask)], ntohl(pt_pkt->ack), pkt->type, (pkt_flag == kUser_flag ? "yes" : "no"), is_pcap); log_sendrecv_hexstr("RECV ICMP", pkt, sizeof(*pkt)); log_sendrecv_hexstr("RECV PTNG", pt_pkt, sizeof(*pt_pkt)); if (bytes - (pt_pkt->data - buf) > 0) { log_sendrecv_hexstr("RECV PAYL", pt_pkt->data, bytes - (pt_pkt->data - buf)); } /* This test essentially verifies that the packet comes from someone who isn't us. */ if ((pkt_flag == kUser_flag && type_flag == proxy_flag) || (pkt_flag == proxy_flag && type_flag == kUser_flag)) { pt_pkt->data_len = ntohl(pt_pkt->data_len); pt_pkt->ack = ntohl(pt_pkt->ack); if (pt_pkt->state == kProxy_start) { if (!cur && type_flag == proxy_flag) { cur = handle_incoming_tunnel_request(bytes, addr, icmp_sock, pkt, pt_pkt); if (!cur) { return; } } else if (type_flag == kUser_flag) { pt_log(kLog_error, "Dropping proxy session request - we are not a proxy!\n"); return; } else { 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 */ if (pt_pkt->data_len != sizeof(challenge_t)) { pt_log(kLog_error, "Received challenge packet, but data length " "is not as expected.\n"); pt_log(kLog_debug, "Data length: %u Expected: %lu\n", pt_pkt->data_len, sizeof(challenge_t)); cur->should_remove = 1; return; } /* Prevent packet data from being forwarded over TCP! */ pt_pkt->data_len = 0; challenge = (challenge_t *)pt_pkt->data; /* If client: Compute response to challenge */ if (type_flag == kUser_flag) { /* Required for integration tests w/ passwd set. */ pt_log(kLog_debug, "AUTH-REQUEST: Received ack-series starting at seq %d\n", pt_pkt->seq_no); handle_auth_request(bytes, icmp_sock, pkt, cur, challenge); return; } /* If proxy: Handle client's response to challenge */ else if (type_flag == proxy_flag) { cur->next_remote_seq++; handle_auth_response(bytes, icmp_sock, pkt, cur, challenge); return; } } /* Handle close-messages for connections we know about */ if (cur && pt_pkt->state == kProto_close) { pt_log(kLog_info, "Received session close from remote peer.\n"); cur->should_remove = 1; return; } /* The proxy will ignore any other packets from the client * until it has been authenticated. The packet resend mechanism * insures that this isn't problematic. */ if (type_flag == proxy_flag && opts.password && cur && !cur->authenticated) { pt_log(kLog_debug, "Ignoring packet with seq-no %d " "- not authenticated yet.\n", pt_pkt->seq_no); return; } if (cur && cur->sock) { double now = time_as_double(); if (pt_pkt->state != kProto_ack) { cur->last_data_activity = now; } if (pt_pkt->state == kProto_data || pt_pkt->state == kProxy_start || pt_pkt->state == kProto_ack) { if (pt_pkt->state == kProxy_start) { pt_pkt->data_len = 0; } handle_data(pkt, bytes, cur); } handle_ack(pt_pkt->ack, cur); cur->last_activity = now; } } } static void queue_payload_data(ping_tunnel_pkt_t * const pt_pkt, proxy_desc_t * const cur) { /* Check if we should add payload data to the queue. */ if (!cur->recv_ring[cur->recv_idx] && pt_pkt->state == kProto_data) { pt_log(kLog_debug, "Queing data packet: %d\n", pt_pkt->seq_no); cur->recv_ring[cur->recv_idx] = create_fwd_desc(pt_pkt->seq_no, pt_pkt->data_len, pt_pkt->data); cur->recv_wait_send++; cur->recv_idx++; } else { pt_log(kLog_debug, "Dup packet for %d ?\n", pt_pkt->seq_no); } cur->next_remote_seq++; if (cur->recv_idx >= cur->window_size) { cur->recv_idx = 0; } /* Check if we have already received some of the next packets. */ while (cur->recv_ring[cur->recv_idx]) { if (cur->recv_ring[cur->recv_idx]->seq_no == cur->next_remote_seq) { cur->next_remote_seq++; cur->recv_idx++; if (cur->recv_idx >= cur->window_size) { cur->recv_idx = 0; } } else { break; } } } static void queue_payload_data_out_of_order(ping_tunnel_pkt_t * const pt_pkt, proxy_desc_t * const cur) { int r, s, d, pos; pos = -1; /* If pos ends up staying -1, packet is discarded. */ r = cur->next_remote_seq; s = pt_pkt->seq_no; d = s - r; if (d < 0) { /* This packet _may_ be old, or seq_no may have wrapped around */ d = (s + 0xFFFF) - r; if (cur->window_size && d < cur->window_size) { /* Counter has wrapped, so we should add this packet to the recv ring */ pos = (cur->recv_idx + d) % cur->window_size; } } else if (cur->window_size && d < cur->window_size) { pos = (cur->recv_idx + d) % cur->window_size; } if (pos != -1) { if (!cur->recv_ring[pos]) { pt_log(kLog_verbose, "Out of order. Expected: %d Got: %d Inserted: %d " "(cur = %d)\n", cur->next_remote_seq, pt_pkt->seq_no, pos, cur->recv_idx); cur->recv_ring[pos] = create_fwd_desc(pt_pkt->seq_no, pt_pkt->data_len, pt_pkt->data); cur->recv_wait_send++; } } else { pt_log(kLog_info, "Packet discarded - outside receive window.\n"); } } /* handle_data: * Utility function for handling kProto_data packets, and place the data it contains * onto the passed-in receive ring. */ void handle_data(icmp_echo_packet_t * pkt, int total_len, proxy_desc_t * cur) { ping_tunnel_pkt_t * pt_pkt = (ping_tunnel_pkt_t *)pkt->data; int expected_len = sizeof(ip_packet_t) + sizeof(icmp_echo_packet_t) + sizeof(ping_tunnel_pkt_t); /* 20+8+28 */ /* Place packet in the receive ring, in its proper place. * This works as follows: * -1. Packet == ack packet? Perform ack, and continue. * 0. seq_no < next_remote_seq, and absolute difference is bigger than w size => discard * 1. If seq_no == next_remote_seq, we have no problems; just put it in the ring. * 2. If seq_no > next_remote_seq + remaining window size, discard packet. * Send resend request for missing packets. * 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 * 4. If packed was not discarded, process ack info in packet. */ expected_len += pt_pkt->data_len; expected_len += expected_len % 2; if (opts.udp || opts.unprivileged) { expected_len -= sizeof(ip_packet_t); } if (total_len < expected_len) { pt_log(kLog_error, "Packet not completely received: %d Should be: %d.\n", total_len, expected_len); pt_log(kLog_debug, "Data length: %d Total length: %d\n", pt_pkt->data_len, total_len); /* just ignore that packet */ return; } if (pt_pkt->seq_no == cur->next_remote_seq) { queue_payload_data(pt_pkt, cur); } else { queue_payload_data_out_of_order(pt_pkt, cur); } } void handle_ack(uint32_t seq_no, proxy_desc_t * cur) { if (cur->send_wait_ack > 0) { int i, can_ack = 0, count = 0; i = cur->send_idx - 1; if (i < 0) { i = cur->window_size - 1; } pt_log(kLog_debug, "Received ack-series starting at seq %d\n", seq_no); while (count < cur->window_size) { if (!cur->send_ring[i].pkt) { break; } if (cur->send_ring[i].seq_no == seq_no) { can_ack = 1; } else if (!can_ack) { cur->send_first_ack = i; } if (can_ack) { free(cur->send_ring[i].pkt); cur->send_ring[i].pkt = 0; cur->send_ring[i].pkt_len = 0; cur->send_wait_ack--; } i--; if (i < 0) { i = cur->window_size - 1; } count++; } } else { pt_log(kLog_verbose, "Dropping superfluous acknowledgement for seq %d " "(no outstanding packets needing ack.)\n", seq_no); } } ptunnel-ng-1.43/src/pkt.h000066400000000000000000000117761460452726400153140ustar00rootroot00000000000000/* * pkt.h * ptunnel is licensed under the BSD license: * * Copyright (c) 2004-2011, Daniel Stoedle , * Yellow Lemon Software. All rights reserved. * * 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: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * - Neither the name of the Yellow Lemon Software nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * Contacting the author: * You can get in touch with me, Daniel Stødle (that's the Norwegian letter oe, * in case your text editor didn't realize), here: * * The official ptunnel website is here: * * * Note that the source code is best viewed with tabs set to 4 spaces. */ #ifndef PKT_H #define PKT_H 1 #include #ifndef __MINGW32__ #define __PTATTR__ __attribute__((packed)) #else #define __PTATTR__ __attribute__((packed, gcc_struct)) #endif #ifdef WIN32 #include typedef int socklen_t; typedef uint32_t in_addr_t; #define ETH_ALEN 6 /* Octets in one ethernet addr */ struct ether_header { uint8_t ether_dhost[ETH_ALEN]; /* destination eth addr */ uint8_t ether_shost[ETH_ALEN]; /* source ether addr */ uint16_t ether_type; /* packet type ID field */ } __PTATTR__; #endif /* WIN32 */ /** Resend packets after this interval (in seconds) */ #define kResend_interval 1.5 /** ping_tunnel_pkt_t: This data structure represents the header of a ptunnel * packet, consisting of a magic number, the tunnel's destination IP and port, * as well as some other fields. Note that the dest IP and port is only valid * in packets from the client to the proxy. */ typedef struct { /** magic number, used to identify ptunnel packets. */ uint32_t magic; /** destination IP and port (used by proxy to figure */ uint32_t dst_ip; /** out where to tunnel to) */ uint32_t dst_port; /** current connection state; see constants above. */ uint32_t state; /** sequence number of last packet received from other end */ uint32_t ack; /** length of data buffer */ uint32_t data_len; /** sequence number of this packet */ uint16_t seq_no; /** id number, used to separate different tunnels from each other */ uint16_t id_no; /** optional data buffer */ char data[0]; } __PTATTR__ ping_tunnel_pkt_t; /** ip_packet_t: This is basically my own definition of the IP packet, which * of course complies with the official definition ;) See any good book on IP * (or even the RFC) for info on the contents of this packet. */ typedef struct { uint8_t vers_ihl; uint8_t tos; uint16_t pkt_len; uint16_t id; uint16_t flags_frag_offset; uint8_t ttl; uint8_t proto; // 1 for ICMP uint16_t checksum; uint32_t src_ip; uint32_t dst_ip; char data[0]; } __PTATTR__ ip_packet_t; /** icmp_echo_packet_t: This is the definition of a standard ICMP header. The * ptunnel packets are constructed as follows: * [ ip header (20 bytes) ] * [ icmp header (8 bytes) ] * [ ptunnel header (28 bytes) ] * * We actually only create the ICMP and ptunnel headers, the IP header is * taken care of by the OS. */ typedef struct { uint8_t type; uint8_t code; uint16_t checksum; uint16_t identifier; uint16_t seq; char data[0]; } __PTATTR__ icmp_echo_packet_t; typedef struct forward_desc_t forward_desc_t; typedef struct icmp_desc_t icmp_desc_t; typedef struct proxy_desc_t proxy_desc_t; void handle_packet(char * buf, unsigned bytes, int is_pcap, struct sockaddr_in * addr, int icmp_sock); void handle_data(icmp_echo_packet_t * pkt, int total_len, proxy_desc_t * cur); void handle_ack(uint32_t seq_no, proxy_desc_t * cur); #endif ptunnel-ng-1.43/src/ptunnel-ng.8000066400000000000000000000201511460452726400165100ustar00rootroot00000000000000.TH ptunnel-ng 8 "December 19, 2017" "Version 1.00" .SH NAME ptunnel-ng \- tunnel TCP connections over ICMP echo request/reply packets. .SH SYNOPSIS .na .B ptunnel-ng \-p
\-l \-r
\-R [\-m ] [\-c ] [\-v ] [\-L ] [\-o] [\-s] [\-P ] [\-\-udp] [\-\-unprivileged] [\-d] [\-S] [\-u] [\-g] [\-C] [\-e] [\-h] .SH DESCRIPTION PingTunnel-NG is a fork from the famous PingTunnel with the aim of an improved and refactored code base and some additional features. .PP ptunnel is an application that allows you to reliably tunnel TCP connections to a remote host using ICMP echo request and reply packets, commonly known as ping requests and replies. At first glance, this might seem like a rather useless thing to do, but it can actually come in handy in some cases. The following example illustrates the main motivation in creating ptunnel: .PP Setting: You're on the go, and stumble across an open wireless network. The network gives you an IP address, but won't let you send TCP or UDP packets out to the rest of the internet, for instance to check your mail. What to do? By chance, you discover that the network will allow you to ping any computer on the rest of the internet. With ptunnel, you can utilize this feature to check your mail, or do other things that require TCP. .SH OPTIONS .TP .SH Client options only: .TP .B \-p .PD 0 .TP .BI \-\-proxy= proxy_address .PD Specify the host on which the proxy is running. .TP .B \-l .PD 0 .TP .BI \-\-listen= listen_port .PD Specifies the port on which the client will listen for incoming TCP connections. .TP .B \-s .PD 0 .TP .BI \-\-statistics .PD Enables continuous output of statistics (packet loss, etc.) .TP .SH Server and Client options: .TP .B \-m .PD 0 .TP .BI \-\-magic= magic_value .PD Sets a different magic value which can be used to bypass Cisco's IPS. It may also work for other IDS/IPS/Firewalls. .br .B Remember: This value has to be the same on the server and client! .TP .B \-r .PD 0 .TP .BI \-\-remote\-adr= destination_addr .PD Specifies the address to which you want your packets tunneled after reaching the proxy when in client mode, or restricts the destination packets can be forwarded to when in server mode. .TP .B \-R .PD 0 .TP .BI \-\-remote\-port= destination_port .PD Specifies/restrict the port that the proxy should tunnel the TCP connection to. .TP .B \-c .PD 0 .TP .BI \-\-connections= max_value .PD Set the maximum of concurrent tunnels. .TP .B \-v .PD 0 .TP .BI \-\-verbosity= level .PD Controls the verbosity level. \-1 is no output, 0 shows errors only, 1 shows info messages, 2 gives more output, 3 provides even more output, level 4 displays debug info and level 5 displays absolutely everything, including the nasty details of sends and receives. .TP .B \-L .PD 0 .TP .BI \-\-libpcap= network_device .PD Specify the network interface to capture packets from. Note that packet capturing isn't always necessary, but you should try this if you experience problems with ptunnel. .TP .B \-o .PD 0 .TP .BI \-\-logfile= logfile .PD Specify a file to log to, rather than printing to standard out. .TP .B \-P .PD 0 .TP .BI \-\-passwd= secret_password .PD Set a password (must be same on client and proxy) which will be used for the challenge response authentication. The program will try to hide the password from `/proc/PID/cmdline` but it may not work for ld wrapper or debugging/profiling tools like valgrind. .TP .BI \-\-udp .br .PD Enables tunneling over UDP port 53 (DNS) instead of using ICMP. This will only work if your proxy can accept incoming traffic on port 53, and the client is able to send data to the proxy on port 53. Note that this option does not wrap ptunnel's data in DNS\-compliant packets. This option must be given on both the proxy and client side for things to work correctly. .TP .BI \-\-unprivileged .PD Run proxy in unprivileged mode. This causes the proxy to forward packets using standard echo requests, instead of crafting custom echo replies. Unprivileged mode will only work on some systems, and is in general less reliable than running in privileged mode. .TP .B \-d .PD 0 .TP .BI \-\-daemon= pidfile .PD .B (Not available on Windows.) .br Run in background, writing PID to a pidfile. .TP .B \-S .PD 0 .TP .BI \-\-syslog .PD .B (Not available on Windows.) .br Changes logging to use the built\-in syslog fascility. .TP .B \-u .PD 0 .TP .BI \-\-user= username .PD .B (Not available on Windows.) .br When started in privileged mode (as root), drop down to user's rights as soon as possible. .TP .B \-g .PD 0 .TP .BI \-\-group= groupname .PD .B (Not available on Windows.) .br When started in privileged mode (as root), drop down to group's rights as soon as possible. If you set .B \-\-user it is not required to set this option too. The program will use the group associated with that user. .TP .B \-C .PD 0 .TP .BI \-\-chroot= directory .PD .B (Not available on Windows.) .br When started in privileged mode (as root), restrict file access to the specified directory. .TP .B \-e .PD 0 .TP .BI \-\-setcon= context .PD .B (Only available on Linux.) .br Set SELinux context when all there is left to do are network I/O operations. In order to be able to combine with \-\-chroot you will have to `mount \-\-bind /proc /chrootdir/proc`. .TP .B \-h .PD 0 .TP .BI \-\-help .br Displays brief usage information. .SH EXAMPLES The following assumes that ptunnel is run as root, both on the proxy and client. To tunnel ssh connections from the client machine via a proxy running on proxy.pingtunnel.com to the computer login.domain.com, the following command line would be used: .TP .B ptunnel \-p proxy.pingtunnel.com \-lp 8000 \-da login.domain.com \-dp 22 .PP An ssh connection to login.domain.com can now be established as follows: .TP .B ssh \-p 8000 localhost .PP If ssh complains about potential man\-in\-the\-middle attacks, simply remove the offending key from the known_hosts file. The warning/error is expected if you have previously ssh'd to your local computer (i.e., ssh localhost), or you have used ptunnel to forward ssh connections to different hosts. Of course, for all of this to work, you need to start the proxy on your proxy\-computer (proxy.pingtunnel.com). Doing this is very simple: .B ptunnel If you find that the proxy isn't working, you will need to enable packet capturing on the main network device. Currently this device is assumed to be an ethernet-device (i.e., ethernet or wireless). Packet capturing is enabled by giving the -c switch, and supplying the device name to capture packets on (for instance eth0 or en1). The same goes for the client. On Mac OS X, packet capturing must always be enabled (both for proxy and client), as resent packets won't be received otherwise. To protect yourself from others using your proxy, you can protect access to it with a password using the \-x switch. The password is never sent in the clear, but keep in mind that it may be visible from tools like top or ps, which can display the command line used to start an application. .SH EXIT STATUS .B ptunnel-ng does only exit if an invalid command line option is found or a fatal error during the initialisation process occurred. If this happens the exit value should always be non zero. The program does not exit until forced to do so by an external SIGNAL or if it crashes. .SH BUGS .B ptunnel-ng currently does not handle packet capturing on network interfaces other than ethernet or wireless correctly. .SH AUTHORS AND CONTRIBUTORS PingTunnel-NG: Toni Uhlig (matzeton@googlemail.com) PingTunnel: Daniel Stoedle (daniels@cs.uit.no) Windows port: Mike Miller (mike@mikeage.net) SELinux support: Sebastien Raveau (sebastien.raveau@epita.fr) Patches: Joe McKenzie, Steffen Wendzel and StalkR. .SH LICENSE .B ptunnel-ng is licensed under the BSD License. .SH AVAILABILITY .TP The ptunnel-ng homepage is currently located here: https://github.com/lnslbrty/ptunnel-ng .TP The ptunnel homepage is currently located here: http://www.cs.uit.no/~daniels/PingTunnel/ .TP The freshmeat project page is located here: http://freshmeat.net/projects/ptunnel/ .PP Please take the time to rate ptunnel or ptunnel-ng if you find it useful. Thanks! ptunnel-ng-1.43/src/ptunnel.c000066400000000000000000000707561460452726400162010ustar00rootroot00000000000000/* * ptunnel.c * ptunnel is licensed under the BSD license: * * Copyright (c) 2004-2011, Daniel Stoedle , * Yellow Lemon Software. All rights reserved. * * 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: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * - Neither the name of the Yellow Lemon Software nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * Contacting the author: * You can get in touch with me, Daniel Stoedle (that's the Norwegian letter oe, * in case your text editor didn't realize), here: * * The official ptunnel website is here: * * * Note that the source code is best viewed with tabs set to 4 spaces. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "ptunnel.h" #include "options.h" #include "utils.h" #include "md5.h" #ifdef HAVE_SELINUX #include #endif #ifndef PACKAGE_STRING #define PACKAGE_STRING "ptunnel-ng" #endif #ifdef WIN32 #include #include /* Map errno (which Winsock doesn't use) to GetLastError; include the code in the strerror */ #ifdef errno #undef errno #endif /* errno */ #define errno GetLastError() /** Local error string storage */ static char errorstr[255]; static char * print_last_windows_error() { char last_errorstr[255]; DWORD last_error = GetLastError(); memset(last_errorstr, 0, sizeof(last_errorstr)); FormatMessage(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM, NULL, last_error, 0, last_errorstr, sizeof(last_errorstr), NULL); snprintf(errorstr, sizeof(errorstr), "%s (%lu)", last_errorstr, last_error); return errorstr; } #define strerror(x) print_last_windows_error() #endif /* WIN32 */ #ifdef HAVE_NPCAP static BOOL LoadNpcapDlls() { TCHAR npcap_dir[512]; UINT len; len = GetSystemDirectory(npcap_dir, 480); if (!len) { pt_log(kLog_error, "Error in GetSystemDirectory: %x", GetLastError()); return FALSE; } _tcscat_s(npcap_dir, 512, _T("\\Npcap")); if (SetDllDirectory(npcap_dir) == 0) { pt_log(kLog_error, "Error in SetDllDirectory: %x", GetLastError()); return FALSE; } return TRUE; } #endif /* globals */ /** Lock protecting the chain of connections */ pthread_mutex_t chain_lock; /** Lock protecting the num_threads variable */ pthread_mutex_t num_threads_lock; /** Current thread count */ int num_threads = 0; /** Current tunnel count */ uint32_t num_tunnels = 0; /** Table indicating when a connection ID is allowable (used by proxy) */ time_t *seq_expiry_tbl = NULL; /* Some buffer constants */ const int tcp_receive_buf_len = kDefault_buf_size; const int icmp_receive_buf_len = kDefault_buf_size + kIP_header_size + kICMP_header_size + sizeof(ping_tunnel_pkt_t); const int pcap_buf_size = (kDefault_buf_size + kIP_header_size + kICMP_header_size + sizeof(ping_tunnel_pkt_t)+64)*64; /** (icmp[icmptype] = icmp-echo || icmp[icmptype] = icmp-echoreply) */ char pcap_filter_program[] = "icmp"; /** The chain of client/proxy connections */ proxy_desc_t *chain = 0; const char *state_name[kNum_proto_types] = { "start", "ack ", "data ", "close", "authenticate" }; #ifdef HAVE_PCAP static void print_pcap_devices(void) { pcap_if_t *devs, *cur_dev; pcap_addr_t *cur_addr; char errbuf[PCAP_ERRBUF_SIZE+1]; if (pcap_findalldevs(&devs, errbuf)) { pt_log(kLog_error, "List all available pcap devices failed: %s.\n", errbuf); } printf("Available pcap devices:\n"); for (cur_dev = devs; cur_dev; cur_dev = cur_dev->next) { if (cur_dev->description) printf("\n\t%s%c '%s'\n", cur_dev->name, (cur_dev->addresses ? ':' : ' '), cur_dev->description); else printf("\n\t%s%c\n", cur_dev->name, (cur_dev->addresses ? ':' : ' ')); for (cur_addr = cur_dev->addresses; cur_addr; cur_addr = cur_addr->next) { if (cur_addr->addr->sa_family == AF_INET) printf("\t\t%s\n", inet_ntoa(((struct sockaddr_in*)cur_addr->addr)->sin_addr)); } } pcap_freealldevs(devs); } #endif /* Let the fun begin! */ int main(int argc, char *argv[]) { #ifndef WIN32 pid_t pid; #endif #ifdef WIN32 WORD wVersionRequested; WSADATA wsaData; int err; wVersionRequested = MAKEWORD(2, 2); err = WSAStartup( wVersionRequested, &wsaData ); if ( err != 0 ) { return -1; } if (LOBYTE( wsaData.wVersion ) != 2 || HIBYTE( wsaData.wVersion ) != 2) { WSACleanup(); return -1; } #endif /* WIN32 */ #ifdef HAVE_NPCAP if (!LoadNpcapDlls()) return -1; #endif memset(opts.md5_password_digest, 0, kMD5_digest_size); memset(opts.sha512_password_digest, 0, kSHA512_digest_size); /* The seq_expiry_tbl is used to prevent the remote ends from prematurely * re-using a sequence number. */ seq_expiry_tbl = (time_t *) calloc(65536, sizeof(time_t)); /* Parse options */ if (parse_options(argc, argv)) return -1; /* Init ptunnel RNG */ pt_random(); if (opts.list_pcap_devices) { #ifdef HAVE_PCAP print_pcap_devices(); return 0; #else pt_log(kLog_error, "Pcap not available!\n"); return 1; #endif } #ifdef HAVE_PCAP if (opts.pcap && opts.udp) { pt_log(kLog_error, "Packet capture is not supported (or needed) when using UDP for transport.\n"); opts.pcap = 0; } #ifdef WIN32 if (!opts.pcap && !opts.udp) { pt_log(kLog_info, "Running ptunnel-ng on Windows in ICMP mode without WinPcap/Npcap enabled is not supported and may not work!\n"); pt_log(kLog_info, "If you encounter problems, install WinPCAP/Npcap from:\n"); pt_log(kLog_info, "https://www.winpcap.org/install/default.htm or Npcap for WIN10: https://nmap.org/npcap/windows-10.html\n"); pt_log(kLog_info, "After WinPCAP is installed, you can list pcap devices with: --list-libpcap-devices\n"); } #endif #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-2019 Toni Uhlig, \n"); #ifdef WIN32 pt_log(kLog_info, "Windows version by Mike Miller, \n"); #else pt_log(kLog_info, "Security features by Sebastien Raveau, \n"); #endif pt_log(kLog_info, "%s.\n", (opts.mode == kMode_forward ? "Relaying packets from incoming TCP streams" : "Forwarding incoming ping packets over TCP")); if (opts.udp) pt_log(kLog_info, "UDP transport enabled.\n"); pt_log(kLog_debug, "Destination at %s:%u\n", opts.given_dst_hostname, opts.given_dst_port); /* TODO: Maybe give the user the opportunity to bind to certain addresses e.g. 127.0.0.1 ? */ if (opts.mode == kMode_forward) pt_log(kLog_debug, "Listen for incoming connections at 0.0.0.0:%u\n", opts.tcp_listen_port); #ifndef WIN32 signal(SIGPIPE, SIG_IGN); if (opts.use_syslog) { if (opts.log_file != stdout) { pt_log(kLog_error, "Logging using syslog overrides the use of a specified logfile (using -f).\n"); fclose(opts.log_file); opts.log_file = stdout; } openlog("ptunnel", LOG_PID, LOG_USER); } if (opts.chroot) { pt_log(kLog_info, "Restricting file access to %s\n", opts.root_dir); if (-1 == chdir(opts.root_dir) || -1 == chroot(".") || -1 == chdir("/")) { pt_log(kLog_error, "chdir/chroot `%s': %s\n", opts.root_dir, strerror(errno)); exit(1); } } if (opts.daemonize) { pt_log(kLog_info, "Going to the background.\n"); if (0 < (pid = fork())) exit(0); if (0 > pid) pt_log(kLog_error, "fork: %s\n", strerror(errno)); else if (-1 == setsid()) pt_log(kLog_error, "setsid: %s\n", strerror(errno)); else { if (0 < (pid = fork())) exit(0); if (0 > pid) pt_log(kLog_error, "fork: %s\n", strerror(errno)); else { if (NULL != opts.pid_file) { fprintf(opts.pid_file, "%d\n", getpid()); fclose(opts.pid_file); } if (! freopen("/dev/null", "r", stdin) || ! freopen("/dev/null", "w", stdout) || ! freopen("/dev/null", "w", stderr)) pt_log(kLog_error, "freopen `%s': %s\n", "/dev/null", strerror(errno)); } } } #endif /* !WIN32 */ pthread_mutex_init(&chain_lock, 0); pthread_mutex_init(&num_threads_lock, 0); // Check mode, validate arguments and start either client or proxy. if (opts.mode == kMode_forward) { if (!opts.given_proxy_ip || !opts.given_dst_ip || !opts.given_dst_port || !opts.tcp_listen_port) { printf("One of the options are missing or invalid.\n"); print_usage(argv[0]); return -1; } pt_forwarder(); } else pt_proxy(0); #ifdef WIN32 WSACleanup(); #else if (opts.root_dir) free(opts.root_dir); #ifdef HAVE_SELINUX if (NULL != opts.selinux_context) free(opts.selinux_context); #endif #endif /* WIN32 */ pt_log(kLog_info, "ptunnel is exiting.\n"); return 0; } /** pt_forwarder: * Sets up a listening TCP socket, and forwards incoming connections * over ping packets. */ void pt_forwarder(void) { int server_sock, new_sock, sock, yes = 1; fd_set set; struct timeval time; struct sockaddr_in addr, dest_addr; socklen_t addr_len; pthread_t pid; uint16_t rand_id; struct in_addr in_addr; pt_log(kLog_debug, "Starting forwarder..\n"); /** Open our listening socket */ sock = socket(AF_INET, SOCK_STREAM, 0); if (sock < 0) { pt_log(kLog_error, "Failed to create socket: %s\n", strerror(errno)); return; } if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const void *) &yes, sizeof(int)) == -1) { pt_log(kLog_error, "Failed to set SO_REUSEADDR option on listening socket: %s\n", strerror(errno)); close(sock); return; } addr.sin_family = AF_INET; addr.sin_port = htons(opts.tcp_listen_port); addr.sin_addr.s_addr = INADDR_ANY; memset(&(addr.sin_zero), 0, 8); if (bind(sock, (struct sockaddr*)&addr, sizeof(struct sockaddr)) == -1) { pt_log(kLog_error, "Failed to bind listening socket to port %u: %s\n", opts.tcp_listen_port, strerror(errno)); close(sock); return; } server_sock = sock; /* Fill out address structure */ memset(&dest_addr, 0, sizeof(struct sockaddr_in)); dest_addr.sin_family = AF_INET; if (opts.udp) dest_addr.sin_port = htons(kDNS_port /* dns port.. */); else dest_addr.sin_port = 0; in_addr.s_addr = opts.given_proxy_ip; dest_addr.sin_addr.s_addr = opts.given_proxy_ip; pt_log(kLog_verbose, "Proxy IP address: %s\n", inet_ntoa(in_addr)); listen(server_sock, 10); while (1) { FD_ZERO(&set); FD_SET(server_sock, &set); time.tv_sec = 1; time.tv_usec = 0; if (select(server_sock+1, &set, 0, 0, &time) > 0) { pt_log(kLog_info, "Incoming connection.\n"); addr_len = sizeof(struct sockaddr_in); new_sock = accept(server_sock, (struct sockaddr*)&addr, &addr_len); if (new_sock < 0) { pt_log(kLog_error, "Accepting incoming connection failed.\n"); continue; } pthread_mutex_lock(&num_threads_lock); if (num_threads <= 0) { pt_log(kLog_event, "No running proxy thread - starting it.\n"); #ifndef WIN32 if (pthread_create(&pid, 0, pt_proxy, 0) != 0) #else if (0 == (pid = _beginthreadex(0, 0, pt_proxy, 0, 0, 0))) #endif { pt_log(kLog_error, "Couldn't create thread! Dropping incoming connection.\n"); close(new_sock); pthread_mutex_unlock(&num_threads_lock); continue; } } addr = dest_addr; rand_id = 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); } } } int pt_create_udp_socket(int port) { struct sockaddr_in addr; int sock, yes = 1; sock = socket(AF_INET, SOCK_DGRAM, 0); if (sock < 0) { pt_log(kLog_error, "Failed to set create UDP socket..\n"); return 0; } if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const void*)&yes, sizeof(int)) < 0) { pt_log(kLog_error, "Failed to set UDP REUSEADDR socket option. (Not fatal, hopefully.)\n"); close(sock); return 0; } #ifdef SO_REUSEPORT yes = 1; if (setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, (const void*)&yes, sizeof(int)) < 0) pt_log(kLog_error, "Failed to set UDP REUSEPORT socket option. (Not fatal, hopefully.)\n"); #endif /* SO_REUSEPORT */ memset(&addr, 0, sizeof(struct sockaddr_in)); addr.sin_family = AF_INET; addr.sin_addr.s_addr = htonl(INADDR_ANY); addr.sin_port = htons(port); if (bind(sock, (struct sockaddr*) &addr, sizeof(struct sockaddr_in)) < 0) { pt_log(kLog_error, "Failed to bind UDP socket to port %d (try running as root).\n", port); close(sock); return 0; } return sock; } /* pt_proxy: This function does all the client and proxy stuff. */ #ifndef WIN32 void * pt_proxy(void *args) #else unsigned int __stdcall pt_proxy(void *args) #endif { (void) args; fd_set set; struct timeval timeout; int bytes; struct sockaddr_in addr; socklen_t addr_len; int fwd_sock = 0, max_sock = 0, idx; char *buf; double now, last_status_update = 0.0; proxy_desc_t *cur, *prev, *tmp; #ifdef HAVE_PCAP pcap_info_t pc; pcap_if_t *alldevs = 0, *pdev; #endif xfer_stats_t xfer; #ifdef HAVE_PCAP ip_packet_t *pkt; uint32_t ip; in_addr_t *adr; #endif struct in_addr in_addr; #ifdef HAVE_ICMPFILTER struct icmp_filter filt; #endif /* Start the thread, initialize protocol and ring states. */ pt_log(kLog_debug, "Starting ping proxy..\n"); if (opts.udp) { pt_log(kLog_debug, "Creating UDP socket..\n"); if (opts.mode == kMode_proxy) fwd_sock = pt_create_udp_socket(kDNS_port); else fwd_sock = pt_create_udp_socket(0); if (!fwd_sock) { pt_log(kLog_error, "Failed to create UDP socket.\n"); return 0; } } else { 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 { pt_log(kLog_debug, "Attempting to create privileged ICMP raw socket..\n"); fwd_sock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); #ifdef HAVE_ICMPFILTER if (opts.mode == kMode_forward) 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) { pt_log(kLog_error, "Couldn't create %s socket: %s\n", (opts.unprivileged ? "unprivileged datagram" : "privileged raw"), strerror(errno)); return 0; } } max_sock = fwd_sock+1; #ifdef HAVE_PCAP if (opts.pcap) { if (opts.udp) { pt_log(kLog_error, "Packet capture is not useful with UDP [should not get here!]!\n"); close(fwd_sock); return 0; } if (!opts.unprivileged) { memset(&pc, 0, sizeof(pc)); pt_log(kLog_info, "Initializing pcap.\n"); pc.pcap_err_buf = (char *) malloc(PCAP_ERRBUF_SIZE); pc.pcap_data_buf = (char *) malloc(pcap_buf_size); pc.pcap_desc = pcap_open_live(opts.pcap_device, pcap_buf_size, 0 /* promiscous */, 50 /* ms */, pc.pcap_err_buf); if (pc.pcap_desc) { if (pcap_lookupnet(opts.pcap_device, &pc.netp, &pc.netmask, pc.pcap_err_buf) == -1) { pt_log(kLog_error, "pcap error: %s\n", pc.pcap_err_buf); opts.pcap = 0; } in_addr.s_addr = pc.netp; pt_log(kLog_verbose, "Network: %s\n", inet_ntoa(in_addr)); in_addr.s_addr = pc.netmask; pt_log(kLog_verbose, "Netmask: %s\n", inet_ntoa(in_addr)); if (pcap_compile(pc.pcap_desc, &pc.fp, pcap_filter_program, 0, pc.netp) == -1) { pt_log(kLog_error, "Failed to compile pcap filter program.\n"); pcap_close(pc.pcap_desc); opts.pcap = 0; } else if (pcap_setfilter(pc.pcap_desc, &pc.fp) == -1) { pt_log(kLog_error, "Failed to set pcap filter program.\n"); pcap_close(pc.pcap_desc); opts.pcap = 0; } } else { pt_log(kLog_error, "pcap error: %s\n", pc.pcap_err_buf); opts.pcap = 0; if (pcap_findalldevs(&alldevs, pc.pcap_err_buf) == 0) { idx = 0; pt_log(kLog_error, "Available pcap devices:\n"); for (pdev = alldevs; pdev != NULL; pdev = pdev->next) { pt_log(kLog_error, "[%d] \"%s\": \"%s\"\n", ++idx, pdev->name, (pdev->description ? pdev->description : "UNKNOWN")); } pcap_freealldevs(alldevs); } } pc.pkt_q.head = 0; pc.pkt_q.tail = 0; pc.pkt_q.elems = 0; /* Check if we have succeeded, and free stuff if not */ if (!opts.pcap) { pt_log(kLog_error, "There were errors enabling pcap - pcap has been disabled.\n"); free(pc.pcap_err_buf); free(pc.pcap_data_buf); return 0; } } else pt_log(kLog_info, "pcap disabled since we're running in unprivileged mode.\n"); } #endif pthread_mutex_lock(&num_threads_lock); num_threads++; pthread_mutex_unlock(&num_threads_lock); /* Allocate icmp receive buffer */ buf = (char *) malloc(icmp_receive_buf_len); /* Start forwarding :) */ pt_log(kLog_info, "Ping proxy is listening in %s mode.\n", (opts.unprivileged ? "unprivileged" : "privileged")); #ifndef WIN32 #ifdef HAVE_SELINUX if (opts.uid || opts.gid || opts.selinux_context) #else if (opts.uid || opts.gid) #endif pt_log(kLog_info, "Dropping privileges now.\n"); if (opts.gid && -1 == setgid(opts.gid)) pt_log(kLog_error, "setgid(%d): %s\n", opts.gid, strerror(errno)); if (opts.uid && -1 == setuid(opts.uid)) pt_log(kLog_error, "setuid(%d): %s\n", opts.uid, strerror(errno)); #ifdef HAVE_SELINUX if (opts.selinux) { if (NULL != opts.selinux_context && -1 == setcon(opts.selinux_context)) pt_log(kLog_error, "setcon(%s) failed: %s\n", opts.selinux_context, strerror(errno)); } #endif #endif while (1) { FD_ZERO(&set); FD_SET(fwd_sock, &set); max_sock = fwd_sock+1; pthread_mutex_lock(&chain_lock); for (cur = chain; cur; cur = cur->next) { /* Only handle traffic if there is traffic on the socket, we have * room in our send window AND we either don't use a password, or * have been authenticated. */ if (cur->sock && cur->send_wait_ack < cur->window_size && (!opts.password || cur->authenticated)) { FD_SET(cur->sock, &set); if (cur->sock >= max_sock) max_sock = cur->sock+1; } } pthread_mutex_unlock(&chain_lock); timeout.tv_sec = 0; timeout.tv_usec = 10000; /* Don't care about return val, since we need to check for new states anyway.. */ select(max_sock, &set, 0, 0, &timeout); pthread_mutex_lock(&chain_lock); for (prev = 0, cur = chain; cur && cur->sock; cur = tmp) { /* Client: If we're starting up, send a message to the remote end saying so, * causing him to connect to our desired endpoint. */ if (cur->state == kProxy_start) { pt_log(kLog_verbose, "Sending proxy request.\n"); cur->last_ack = time_as_double(); queue_packet(fwd_sock, cur, NULL, 0, cur->dst_ip, cur->dst_port, cur->state | cur->type_flag); cur->xfer.icmp_out++; cur->state = kProto_data; } if (cur->should_remove) { pt_log(kLog_info, "\nSession statistics:\n"); print_statistics(&cur->xfer, 0); pt_log(kLog_info, "\n"); tmp = cur->next; remove_proxy_desc(cur, prev); continue; } /* Handle TCP traffic */ if (FD_ISSET(cur->sock, &set)) { bytes = recv(cur->sock, cur->buf, tcp_receive_buf_len, 0); if (bytes <= 0) { pt_log(kLog_info, "Connection closed or lost.\n"); tmp = cur->next; send_termination_msg(cur, fwd_sock); pt_log(kLog_info, "Session statistics:\n"); print_statistics(&cur->xfer, 0); remove_proxy_desc(cur, prev); /* No need to update prev */ continue; } cur->xfer.bytes_out += bytes; cur->xfer.icmp_out++; queue_packet(fwd_sock, cur, cur->buf, bytes, 0, 0, cur->state | cur->type_flag); } prev = cur; tmp = cur->next; } pthread_mutex_unlock(&chain_lock); if (FD_ISSET(fwd_sock, &set)) { /* Handle ping traffic */ addr_len = sizeof(struct sockaddr); bytes = recvfrom(fwd_sock, buf, icmp_receive_buf_len, 0, (struct sockaddr*)&addr, &addr_len); if (bytes < 0) { pt_log(kLog_error, "Error receiving packet on ICMP socket: %s\n", strerror(errno)); break; } handle_packet(buf, bytes, 0, &addr, fwd_sock); } /* Check for packets needing resend, and figure out if any connections * should be closed down due to inactivity. */ pthread_mutex_lock(&chain_lock); now = time_as_double(); for (cur = chain; cur; cur = cur->next) { in_addr.s_addr = cur->dst_ip; if (cur->last_activity + kAutomatic_close_timeout < now) { pt_log(kLog_info, "Dropping tunnel %u to %s:%u due to inactivity.\n", cur->id_no, inet_ntoa(in_addr), cur->dst_port); cur->should_remove = 1; continue; } if (cur->recv_wait_send && cur->sock) cur->xfer.bytes_in += send_packets(cur->recv_ring, &cur->recv_xfer_idx, &cur->recv_wait_send, &cur->sock, cur->window_size); /* Check for any icmp packets requiring resend, and resend _only_ the first packet. */ idx = cur->send_first_ack; if (cur->send_ring[idx].pkt && cur->send_ring[idx].last_resend+cur->resend_interval < now) { pt_log(kLog_debug, "Resending packet with seq-no %d.\n", cur->send_ring[idx].seq_no); cur->send_ring[idx].last_resend = now; cur->send_ring[idx].pkt->identifier = htons(cur->icmp_id); cur->send_ring[idx].pkt->seq = htons(cur->ping_seq); cur->ping_seq++; cur->send_ring[idx].pkt->checksum = 0; cur->send_ring[idx].pkt->checksum = htons(calc_icmp_checksum((uint16_t*)cur->send_ring[idx].pkt, cur->send_ring[idx].pkt_len)); /* printf("ID: %d\n", htons(cur->send_ring[idx].pkt->identifier)); */ 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)); cur->xfer.icmp_resent++; } /* Figure out if it's time to send an explicit acknowledgement */ if (cur->last_ack+cur->ack_interval < now && cur->send_wait_ack < cur->window_size && cur->remote_ack_val+1 != cur->next_remote_seq) { queue_packet(fwd_sock, cur, NULL, 0, cur->dst_ip, cur->dst_port, kProto_ack | cur->type_flag); cur->last_ack = now; cur->xfer.icmp_ack_out++; } } pthread_mutex_unlock(&chain_lock); #ifdef HAVE_PCAP if (opts.pcap) { if (pcap_dispatch(pc.pcap_desc, 32, pcap_packet_handler, (u_char*)&pc.pkt_q) > 0) { pqueue_elem_t *cur; pt_log(kLog_verbose, "pcap captured %d packets - handling them..\n", pc.pkt_q.elems); while (pc.pkt_q.head) { cur = pc.pkt_q.head; memset(&addr, 0, sizeof(struct sockaddr)); addr.sin_family = AF_INET; pkt = (ip_packet_t*)&cur->data[0]; ip = pkt->src_ip; adr = (in_addr_t*)&ip; addr.sin_addr.s_addr = *adr; handle_packet(cur->data, cur->bytes, 1, &addr, fwd_sock); pc.pkt_q.head = cur->next; free(cur); pc.pkt_q.elems--; } pc.pkt_q.tail = 0; pc.pkt_q.head = 0; } } #endif /* Update running statistics, if requested (only once every second) */ if (opts.print_stats && opts.mode == kMode_forward && now > last_status_update+1) { pthread_mutex_lock(&chain_lock); memset(&xfer, 0, sizeof(xfer_stats_t)); for (cur = chain; cur; cur = cur->next) { xfer.bytes_in += cur->xfer.bytes_in; xfer.bytes_out += cur->xfer.bytes_out; xfer.icmp_in += cur->xfer.icmp_in; xfer.icmp_out += cur->xfer.icmp_out; xfer.icmp_resent += cur->xfer.icmp_resent; } pthread_mutex_unlock(&chain_lock); print_statistics(&xfer, (opts.log_level >= kLog_verbose ? 0 : 1)); last_status_update = now; } } pt_log(kLog_debug, "Proxy exiting..\n"); if (fwd_sock) close(fwd_sock); /* TODO: Clean up the other descs. Not really a priority since there's no * real way to quit ptunnel in the first place.. */ free(buf); pt_log(kLog_debug, "Ping proxy done\n"); return 0; } /* print_statistics: Prints transfer statistics for the given xfer block. The * is_continuous variable controls the output mode, either printing a new line * or overwriting the old line. */ void print_statistics(xfer_stats_t *xfer, int is_continuous) { const double mb = 1024.0*1024.0; double loss = 0.0; if (xfer->icmp_out > 0) loss = (double)xfer->icmp_resent/(double)xfer->icmp_out; if (is_continuous) printf("\r"); printf("[inf]: I/O: %6.2f/%6.2f mb ICMP I/O/R: %8u/%8u/%8u Loss: %4.1f%%", xfer->bytes_in/mb, xfer->bytes_out/mb, xfer->icmp_in, xfer->icmp_out, xfer->icmp_resent, loss); if (!is_continuous) printf("\n"); else fflush(stdout); } #ifdef HAVE_PCAP /* pcap_packet_handler: * This is our callback function handling captured packets. We already know that the packets * are ICMP echo or echo-reply messages, so all we need to do is strip off the ethernet header * and append it to the queue descriptor (the refcon argument). * * Ok, the above isn't entirely correct (we can get other ICMP types as well). This function * also has problems when it captures packets on the loopback interface. The moral of the * story: Don't do ping forwarding over the loopback interface. * * Also, we currently don't support anything else than ethernet when in pcap mode. The reason * is that I haven't read up on yet on how to remove the frame header from the packet.. */ void pcap_packet_handler(u_char *refcon, const struct pcap_pkthdr *hdr, const u_char* pkt) { pqueue_t *q; pqueue_elem_t *elem; ip_packet_t *ip; /* pt_log(kLog_verbose, "Packet handler: %d =? %d\n", hdr->caplen, hdr->len); */ q = (pqueue_t*)refcon; elem = (pqueue_elem_t *) malloc(sizeof(pqueue_elem_t)+hdr->caplen-sizeof(struct ether_header)); memcpy(elem->data, pkt+sizeof(struct ether_header), hdr->caplen-sizeof(struct ether_header)); ip = (ip_packet_t*)elem->data; /* TODO: Add fragment support */ elem->bytes = ntohs(ip->pkt_len); if (elem->bytes > hdr->caplen-sizeof(struct ether_header)) { pt_log(kLog_error, "Received fragmented packet - unable to reconstruct!\n"); pt_log(kLog_error, "This error usually occurs because pcap is used on " "devices that are not wlan or ethernet.\n"); free(elem); return; } /* elem->bytes = hdr->caplen-sizeof(struct ether_header); */ elem->next = 0; if (q->tail) { q->tail->next = elem; q->tail = elem; } else { q->head = elem; q->tail = elem; } q->elems++; } #endif uint16_t calc_icmp_checksum(uint16_t *data, int bytes) { uint32_t sum; int i; sum = 0; for (i = 0; i < bytes / 2; i++) { /* WARNING; this might be a bug, but might explain why I occasionally * see buggy checksums.. (added htons, that might be the correct behaviour) */ sum += data[i]; } sum = (sum & 0xFFFF) + (sum >> 16); sum = htons(0xFFFF - sum); return sum; } /* send_termination_msg: Sends two packets to the remote end, informing it that * the tunnel is being closed down. */ void send_termination_msg(proxy_desc_t *cur, int icmp_sock) { size_t i; const size_t max_termination_msgs = 3; /* Send packet twice, hoping at least one of them makes it through.. */ for (i = 0; i < max_termination_msgs; ++i) { queue_packet(icmp_sock, cur, NULL, 0, cur->dst_ip, cur->dst_port, kProto_close | cur->type_flag); } cur->xfer.icmp_out += max_termination_msgs; } ptunnel-ng-1.43/src/ptunnel.h000066400000000000000000000114001460452726400161630ustar00rootroot00000000000000/* * ptunnel.h * ptunnel is licensed under the BSD license: * * Copyright (c) 2004-2011, Daniel Stoedle , * Yellow Lemon Software. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * - Neither the name of the Yellow Lemon Software nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * Contacting the author: * You can get in touch with me, Daniel Stoedle (that's the Norwegian letter oe, * in case your text editor didn't realize), here: * * The official ptunnel website is here: * * * Note that the source code is best viewed with tabs set to 4 spaces. */ #ifndef PING_TUNNEL_H #define PING_TUNNEL_H 1 #ifndef WIN32 #ifdef HAVE_ICMPFILTER #include #endif #ifdef HAVE_SYS_UNISTD_H #include #endif #include #include #include #include #include #include #include #include #include #include #include #endif /* !WIN32 */ #include #include #include #include #include #include #include #include #include #ifdef HAVE_PCAP #include #endif #include "pkt.h" #include "pdesc.h" #include "challenge.h" #ifdef WIN32 /* pthread porting to windows */ typedef CRITICAL_SECTION pthread_mutex_t; typedef unsigned long pthread_t; #define pthread_mutex_init InitializeCriticalSectionAndSpinCount #define pthread_mutex_lock EnterCriticalSection #define pthread_mutex_unlock LeaveCriticalSection #endif extern pthread_mutex_t chain_lock; extern uint32_t num_tunnels; extern const int icmp_receive_buf_len; extern proxy_desc_t *chain; extern time_t *seq_expiry_tbl; extern const char *state_name[kNum_proto_types]; /* pt_thread_info_t: A simple (very simple, in fact) structure that allows us * to pass an arbitrary number of params to the threads we create. Currently, * that's just one single parameter: The socket which the thread should listen * to. */ typedef struct { int sock; } pt_thread_info_t; #ifdef HAVE_PCAP /* pqueue_elem_t: An queue element in the pqueue structure (below). */ typedef struct pqueue_elem_t { /** size of data buffer */ unsigned long bytes; /** next queue element (if any) */ struct pqueue_elem_t *next; /** optional data */ char data[0]; } pqueue_elem_t; /* pqueue_t: A simple queue strucutre. */ typedef struct { pqueue_elem_t *head; pqueue_elem_t *tail; int elems; } pqueue_t; /* pcap_info_t: Structure to hold information related to packet capturing. */ typedef struct { pcap_t *pcap_desc; /** compiled filter program */ struct bpf_program fp; uint32_t netp; uint32_t netmask; /** buffers for error info */ char *pcap_err_buf; /** buffers for packet info */ char *pcap_data_buf; /** queue of packets to process */ pqueue_t pkt_q; } pcap_info_t; #endif /* function Prototypes */ #ifndef WIN32 void * pt_proxy(void *args); #else unsigned int __stdcall pt_proxy(void *args); #endif #ifdef HAVE_PCAP void pcap_packet_handler(u_char *refcon, const struct pcap_pkthdr *hdr, const u_char* pkt); #endif void pt_forwarder(void); void print_statistics(xfer_stats_t *xfer, int is_continuous); uint16_t calc_icmp_checksum(uint16_t *data, int bytes); void send_termination_msg(proxy_desc_t *cur, int icmp_sock); #endif ptunnel-ng-1.43/src/utils.c000066400000000000000000000134351460452726400156430ustar00rootroot00000000000000/* * utils.c * ptunnel is licensed under the BSD license: * * Copyright (c) 2004-2011, Daniel Stoedle , * Yellow Lemon Software. All rights reserved. * * 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: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * - Neither the name of the Yellow Lemon Software nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * Contacting the author: * You can get in touch with me, Daniel Stødle (that's the Norwegian letter oe, * in case your text editor didn't realize), here: * * The official ptunnel website is here: * * * Note that the source code is best viewed with tabs set to 4 spaces. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include #include #ifdef HAVE_BSD_STDLIB_H #include #endif #ifndef WIN32 #include #include #include #include #include #include #include #else #include #endif #include #include "utils.h" #include "options.h" void pt_log(enum log_level level, const char * fmt, ...) { va_list args; const char * header[] = {"[err]: ", "[inf]: ", "[evt]: ", "[vbs]: ", "[dbg]: ", "[xfr]: "}; #ifndef WIN32 int syslog_levels[] = {LOG_ERR, LOG_NOTICE, LOG_NOTICE, LOG_INFO, LOG_DEBUG, LOG_DEBUG}; #endif /* !WIN32 */ if (level <= opts.log_level) { va_start(args, fmt); #ifndef WIN32 if (opts.use_syslog) { char log[255]; int header_len; header_len = snprintf(log, sizeof(log), "%s", header[level]); vsnprintf(log + header_len, sizeof(log) - header_len, fmt, args); syslog(syslog_levels[level], "%s", log); } else #endif /* !WIN32 */ fprintf(opts.log_file, "%s", header[level]), vfprintf(opts.log_file, fmt, args); va_end(args); #ifndef WIN32 if (opts.log_file != stdout && !opts.use_syslog) #else if (opts.log_file != stdout) #endif fflush(opts.log_file); } } double time_as_double(void) { double result; struct timeval tt; gettimeofday(&tt, 0); result = (double)tt.tv_sec + ((double)tt.tv_usec / (double)10e5); return result; } int host_to_addr(const char * hostname, uint32_t * result) { int ret; struct addrinfo * addrs = NULL; struct addrinfo hints; struct sockaddr_in * addr; memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_INET; if ((ret = getaddrinfo(hostname, NULL, &hints, &addrs)) != 0) return ret; addr = (struct sockaddr_in *)addrs->ai_addr; *result = *(uint32_t *)&addr->sin_addr; freeaddrinfo(addrs); return 0; } static const char hextab[] = "0123456789ABCDEF"; void log_sendrecv_hexstr(const char *prefix, void *buf, size_t siz) { if (opts.log_level != kLog_sendrecv) { return; } const size_t outsiz = siz * 3; if (outsiz + 1 > BUFSIZ) { pt_log(kLog_error, "Can not print hex string with size %zu: too big\n", siz); return; } char out[outsiz + 1]; unsigned char high, low; size_t i, j; for (i = 0, j = 0; j < siz && i < outsiz; i += 3, ++j) { high = (((unsigned char *)buf)[j] & 0xF0) >> 4; low = ((unsigned char *)buf)[j] & 0x0F; out[i ] = hextab[high]; out[i+1] = hextab[low]; out[i+2] = ' '; } out[i] = '\0'; pt_log(kLog_sendrecv, "%s[HEX]: %s\n", prefix, out); } int pt_random(void) { #if defined(HAVE_ARC4RANDOM) || defined(__COVERITY__) return arc4random(); #else #if defined(RNGDEV) && !defined(_WIN32) static int rng_fd = -1; ssize_t bytes_read; int rnd_val; if (rng_fd < 0) { rng_fd = open(RNGDEV, O_RDONLY); if (rng_fd < 0) { pt_log(kLog_error, "FATAL: Could not open random device '%s': %s\n", RNGDEV, strerror(errno)); exit(EXIT_FAILURE); } } bytes_read = read(rng_fd, &rnd_val, sizeof rnd_val); if (bytes_read != sizeof rnd_val) { if (bytes_read < 0) pt_log(kLog_error, "FATAL: Read from random device failed: %s\n", strerror(errno)); else pt_log(kLog_error, "FATAL: Read only %zd bytes (wanted %zd bytes)\n", bytes_read, sizeof rnd_val); exit(EXIT_FAILURE); } return rnd_val; #else srand(time(0)); return rand(); #endif #endif } ptunnel-ng-1.43/src/utils.h000066400000000000000000000047101460452726400156440ustar00rootroot00000000000000/* * utils.h * ptunnel is licensed under the BSD license: * * Copyright (c) 2004-2011, Daniel Stoedle , * Yellow Lemon Software. All rights reserved. * * 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: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * - Neither the name of the Yellow Lemon Software nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * Contacting the author: * You can get in touch with me, Daniel Stødle (that's the Norwegian letter oe, * in case your text editor didn't realize), here: * * The official ptunnel website is here: * * * Note that the source code is best viewed with tabs set to 4 spaces. */ #ifndef UTILS_H #define UTILS_H 1 #include #include #include "pconfig.h" #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0])) void pt_log(enum log_level level, const char * fmt, ...); double time_as_double(void); int host_to_addr(const char * hostname, uint32_t * result); void log_sendrecv_hexstr(const char * prefix, void *buf, size_t siz); int pt_random(void); #endif ptunnel-ng-1.43/src/win32/000077500000000000000000000000001460452726400152735ustar00rootroot00000000000000ptunnel-ng-1.43/src/win32/WPCAP.DEF000066400000000000000000000032041460452726400164640ustar00rootroot00000000000000LIBRARY wpcap.dll EXPORTS pcap_lookupdev pcap_lookupnet pcap_open_live pcap_open_offline pcap_close pcap_getnonblock pcap_setnonblock pcap_loop pcap_dispatch pcap_read pcap_setuserbuffer pcap_offline_read pcap_next pcap_stats pcap_stats_ex pcap_setfilter pcap_perror pcap_strerror pcap_geterr pcap_compile pcap_compile_nopcap pcap_freecode pcap_datalink pcap_snapshot pcap_is_swapped pcap_major_version pcap_minor_version pcap_file pcap_fileno pcap_dump_open pcap_dump_close pcap_dump_flush pcap_dump pcap_dump_file pcap_setbuff pcap_setmode pcap_sendpacket pcap_sendqueue_alloc pcap_sendqueue_destroy pcap_sendqueue_queue pcap_sendqueue_transmit pcap_next_etherent pcap_getevent pcap_setmintocopy pcap_open_dead pcap_findalldevs pcap_freealldevs pcap_live_dump pcap_live_dump_ended bpf_filter bpf_validate bpf_image bpf_dump wsockinit endservent getservent eproto_db pcap_stats_ex pcap_open pcap_createsrcstr pcap_parsesrcstr pcap_findalldevs_ex pcap_remoteact_accept pcap_remoteact_list pcap_remoteact_close pcap_remoteact_cleanup install_bpf_program pcap_next_ex pcap_offline_filter pcap_setsampling pcap_breakloop pcap_list_datalinks pcap_list_datalinks pcap_set_datalink pcap_datalink_name_to_val pcap_datalink_val_to_name pcap_datalink_val_to_description pcap_lib_version pcap_dump_file pcap_dump_ftell pcap_get_airpcap_handle pcap_create pcap_activate pcap_set_promisc pcap_set_snaplen pcap_set_timeout pcap_set_buffer_size pcap_hopen_offline pcap_setdirection pcap_free_datalinksptunnel-ng-1.43/src/win32/includes/000077500000000000000000000000001460452726400171015ustar00rootroot00000000000000ptunnel-ng-1.43/src/win32/includes/bittypes.h000066400000000000000000000075301460452726400211220ustar00rootroot00000000000000/* * Copyright (C) 1999 WIDE Project. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the project nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #ifndef _BITTYPES_H #define _BITTYPES_H #ifndef HAVE_U_INT8_T #if SIZEOF_CHAR == 1 typedef unsigned char u_int8_t; typedef signed char int8_t; #elif SIZEOF_INT == 1 typedef unsigned int u_int8_t; typedef signed int int8_t; #else /* XXX */ #error "there's no appropriate type for u_int8_t" #endif #define HAVE_U_INT8_T 1 #define HAVE_INT8_T 1 #endif /* HAVE_U_INT8_T */ #ifndef HAVE_U_INT16_T #if SIZEOF_SHORT == 2 typedef unsigned short u_int16_t; typedef signed short int16_t; #elif SIZEOF_INT == 2 typedef unsigned int u_int16_t; typedef signed int int16_t; #elif SIZEOF_CHAR == 2 typedef unsigned char u_int16_t; typedef signed char int16_t; #else /* XXX */ #error "there's no appropriate type for u_int16_t" #endif #define HAVE_U_INT16_T 1 #define HAVE_INT16_T 1 #endif /* HAVE_U_INT16_T */ #ifndef HAVE_U_INT32_T #if SIZEOF_INT == 4 typedef unsigned int u_int32_t; typedef signed int int32_t; #elif SIZEOF_LONG == 4 typedef unsigned long u_int32_t; typedef signed long int32_t; #elif SIZEOF_SHORT == 4 typedef unsigned short u_int32_t; typedef signed short int32_t; #else /* XXX */ #error "there's no appropriate type for u_int32_t" #endif #define HAVE_U_INT32_T 1 #define HAVE_INT32_T 1 #endif /* HAVE_U_INT32_T */ #ifndef HAVE_U_INT64_T #if SIZEOF_LONG_LONG == 8 typedef unsigned long long u_int64_t; typedef long long int64_t; #elif defined(_MSC_EXTENSIONS) typedef unsigned _int64 u_int64_t; typedef _int64 int64_t; #elif SIZEOF_INT == 8 typedef unsigned int u_int64_t; #elif SIZEOF_LONG == 8 typedef unsigned long u_int64_t; #elif SIZEOF_SHORT == 8 typedef unsigned short u_int64_t; #else /* XXX */ #error "there's no appropriate type for u_int64_t" #endif #endif /* HAVE_U_INT64_T */ #ifndef PRId64 #ifdef _MSC_EXTENSIONS #define PRId64 "I64d" #else /* _MSC_EXTENSIONS */ #define PRId64 "lld" #endif /* _MSC_EXTENSIONS */ #endif /* PRId64 */ #ifndef PRIo64 #ifdef _MSC_EXTENSIONS #define PRIo64 "I64o" #else /* _MSC_EXTENSIONS */ #define PRIo64 "llo" #endif /* _MSC_EXTENSIONS */ #endif /* PRIo64 */ #ifndef PRIx64 #ifdef _MSC_EXTENSIONS #define PRIx64 "I64x" #else /* _MSC_EXTENSIONS */ #define PRIx64 "llx" #endif /* _MSC_EXTENSIONS */ #endif /* PRIx64 */ #ifndef PRIu64 #ifdef _MSC_EXTENSIONS #define PRIu64 "I64u" #else /* _MSC_EXTENSIONS */ #define PRIu64 "llu" #endif /* _MSC_EXTENSIONS */ #endif /* PRIu64 */ #endif /* _BITTYPES_H */ ptunnel-ng-1.43/src/win32/includes/pcap-stdinc.h000066400000000000000000000054711460452726400214660ustar00rootroot00000000000000/* * Copyright (c) 2002 - 2005 NetGroup, Politecnico di Torino (Italy) * Copyright (c) 2005 - 2009 CACE Technologies, Inc. Davis (California) * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the Politecnico di Torino nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * @(#) $Header: /tcpdump/master/libpcap/pcap-stdinc.h,v 1.10.2.1 2008-10-06 15:38:39 gianluca Exp $ (LBL) */ #define SIZEOF_CHAR 1 #define SIZEOF_SHORT 2 #define SIZEOF_INT 4 #ifndef _MSC_EXTENSIONS #define SIZEOF_LONG_LONG 8 #endif /* * Avoids a compiler warning in case this was already defined * (someone defined _WINSOCKAPI_ when including 'windows.h', in order * to prevent it from including 'winsock.h') */ #ifdef _WINSOCKAPI_ #undef _WINSOCKAPI_ #endif #include #include #include "bittypes.h" #include #include #ifndef __MINGW32__ #include "IP6_misc.h" #endif #define caddr_t char* #if _MSC_VER < 1500 #define snprintf _snprintf #define vsnprintf _vsnprintf #define strdup _strdup #endif #define inline __inline #ifdef __MINGW32__ #include #else /*__MINGW32__*/ /* MSVC compiler */ #ifndef _UINTPTR_T_DEFINED #ifdef _WIN64 typedef unsigned __int64 uintptr_t; #else typedef _W64 unsigned int uintptr_t; #endif #define _UINTPTR_T_DEFINED #endif #ifndef _INTPTR_T_DEFINED #ifdef _WIN64 typedef __int64 intptr_t; #else typedef _W64 int intptr_t; #endif #define _INTPTR_T_DEFINED #endif #endif /*__MINGW32__*/ ptunnel-ng-1.43/src/win32/includes/pcap.h000066400000000000000000000044201460452726400201750ustar00rootroot00000000000000/* * Copyright (c) 1993, 1994, 1995, 1996, 1997 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the Computer Systems * Engineering Group at Lawrence Berkeley Laboratory. * 4. Neither the name of the University nor of the Laboratory may be used * to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#) $Header: /tcpdump/master/libpcap/pcap.h,v 1.59 2006/10/04 18:09:22 guy Exp $ (LBL) */ /* * For backwards compatibility. * * Note to OS vendors: do NOT get rid of this file! Many applications * expect to be able to include , and at least some of them * go through contortions in their configure scripts to try to detect * OSes that have "helpfully" moved pcap.h to without * leaving behind a file. */ #include ptunnel-ng-1.43/src/win32/includes/pcap/000077500000000000000000000000001460452726400200245ustar00rootroot00000000000000ptunnel-ng-1.43/src/win32/includes/pcap/bpf.h000066400000000000000000000706671460452726400207640ustar00rootroot00000000000000/*- * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997 * The Regents of the University of California. All rights reserved. * * This code is derived from the Stanford/CMU enet packet filter, * (net/enet.c) distributed as part of 4.3BSD, and code contributed * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence * Berkeley Laboratory. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)bpf.h 7.1 (Berkeley) 5/7/91 * * @(#) $Header: /tcpdump/master/libpcap/pcap/bpf.h,v 1.19.2.8 2008-09-22 20:16:01 guy Exp $ (LBL) */ /* * This is libpcap's cut-down version of bpf.h; it includes only * the stuff needed for the code generator and the userland BPF * interpreter, and the libpcap APIs for setting filters, etc.. * * "pcap-bpf.c" will include the native OS version, as it deals with * the OS's BPF implementation. * * XXX - should this all just be moved to "pcap.h"? */ #ifndef BPF_MAJOR_VERSION #ifdef __cplusplus extern "C" { #endif /* BSD style release date */ #define BPF_RELEASE 199606 #ifdef MSDOS /* must be 32-bit */ typedef long bpf_int32; typedef unsigned long bpf_u_int32; #else typedef int bpf_int32; typedef u_int bpf_u_int32; #endif /* * Alignment macros. BPF_WORDALIGN rounds up to the next * even multiple of BPF_ALIGNMENT. */ #ifndef __NetBSD__ #define BPF_ALIGNMENT sizeof(bpf_int32) #else #define BPF_ALIGNMENT sizeof(long) #endif #define BPF_WORDALIGN(x) (((x)+(BPF_ALIGNMENT-1))&~(BPF_ALIGNMENT-1)) #define BPF_MAXBUFSIZE 0x8000 #define BPF_MINBUFSIZE 32 /* * Structure for "pcap_compile()", "pcap_setfilter()", etc.. */ struct bpf_program { u_int bf_len; struct bpf_insn *bf_insns; }; /* * Struct return by BIOCVERSION. This represents the version number of * the filter language described by the instruction encodings below. * bpf understands a program iff kernel_major == filter_major && * kernel_minor >= filter_minor, that is, if the value returned by the * running kernel has the same major number and a minor number equal * equal to or less than the filter being downloaded. Otherwise, the * results are undefined, meaning an error may be returned or packets * may be accepted haphazardly. * It has nothing to do with the source code version. */ struct bpf_version { u_short bv_major; u_short bv_minor; }; /* Current version number of filter architecture. */ #define BPF_MAJOR_VERSION 1 #define BPF_MINOR_VERSION 1 /* * Data-link level type codes. * * Do *NOT* add new values to this list without asking * "tcpdump-workers@lists.tcpdump.org" for a value. Otherwise, you run * the risk of using a value that's already being used for some other * purpose, and of having tools that read libpcap-format captures not * being able to handle captures with your new DLT_ value, with no hope * that they will ever be changed to do so (as that would destroy their * ability to read captures using that value for that other purpose). */ /* * These are the types that are the same on all platforms, and that * have been defined by for ages. */ #define DLT_NULL 0 /* BSD loopback encapsulation */ #define DLT_EN10MB 1 /* Ethernet (10Mb) */ #define DLT_EN3MB 2 /* Experimental Ethernet (3Mb) */ #define DLT_AX25 3 /* Amateur Radio AX.25 */ #define DLT_PRONET 4 /* Proteon ProNET Token Ring */ #define DLT_CHAOS 5 /* Chaos */ #define DLT_IEEE802 6 /* 802.5 Token Ring */ #define DLT_ARCNET 7 /* ARCNET, with BSD-style header */ #define DLT_SLIP 8 /* Serial Line IP */ #define DLT_PPP 9 /* Point-to-point Protocol */ #define DLT_FDDI 10 /* FDDI */ /* * These are types that are different on some platforms, and that * have been defined by for ages. We use #ifdefs to * detect the BSDs that define them differently from the traditional * libpcap * * XXX - DLT_ATM_RFC1483 is 13 in BSD/OS, and DLT_RAW is 14 in BSD/OS, * but I don't know what the right #define is for BSD/OS. */ #define DLT_ATM_RFC1483 11 /* LLC-encapsulated ATM */ #ifdef __OpenBSD__ #define DLT_RAW 14 /* raw IP */ #else #define DLT_RAW 12 /* raw IP */ #endif /* * Given that the only OS that currently generates BSD/OS SLIP or PPP * is, well, BSD/OS, arguably everybody should have chosen its values * for DLT_SLIP_BSDOS and DLT_PPP_BSDOS, which are 15 and 16, but they * didn't. So it goes. */ #if defined(__NetBSD__) || defined(__FreeBSD__) #ifndef DLT_SLIP_BSDOS #define DLT_SLIP_BSDOS 13 /* BSD/OS Serial Line IP */ #define DLT_PPP_BSDOS 14 /* BSD/OS Point-to-point Protocol */ #endif #else #define DLT_SLIP_BSDOS 15 /* BSD/OS Serial Line IP */ #define DLT_PPP_BSDOS 16 /* BSD/OS Point-to-point Protocol */ #endif /* * 17 is used for DLT_OLD_PFLOG in OpenBSD; * OBSOLETE: DLT_PFLOG is 117 in OpenBSD now as well. See below. * 18 is used for DLT_PFSYNC in OpenBSD; don't use it for anything else. */ #define DLT_ATM_CLIP 19 /* Linux Classical-IP over ATM */ /* * Apparently Redback uses this for its SmartEdge 400/800. I hope * nobody else decided to use it, too. */ #define DLT_REDBACK_SMARTEDGE 32 /* * These values are defined by NetBSD; other platforms should refrain from * using them for other purposes, so that NetBSD savefiles with link * types of 50 or 51 can be read as this type on all platforms. */ #define DLT_PPP_SERIAL 50 /* PPP over serial with HDLC encapsulation */ #define DLT_PPP_ETHER 51 /* PPP over Ethernet */ /* * The Axent Raptor firewall - now the Symantec Enterprise Firewall - uses * a link-layer type of 99 for the tcpdump it supplies. The link-layer * header has 6 bytes of unknown data, something that appears to be an * Ethernet type, and 36 bytes that appear to be 0 in at least one capture * I've seen. */ #define DLT_SYMANTEC_FIREWALL 99 /* * Values between 100 and 103 are used in capture file headers as * link-layer types corresponding to DLT_ types that differ * between platforms; don't use those values for new DLT_ new types. */ /* * This value was defined by libpcap 0.5; platforms that have defined * it with a different value should define it here with that value - * a link type of 104 in a save file will be mapped to DLT_C_HDLC, * whatever value that happens to be, so programs will correctly * handle files with that link type regardless of the value of * DLT_C_HDLC. * * The name DLT_C_HDLC was used by BSD/OS; we use that name for source * compatibility with programs written for BSD/OS. * * libpcap 0.5 defined it as DLT_CHDLC; we define DLT_CHDLC as well, * for source compatibility with programs written for libpcap 0.5. */ #define DLT_C_HDLC 104 /* Cisco HDLC */ #define DLT_CHDLC DLT_C_HDLC #define DLT_IEEE802_11 105 /* IEEE 802.11 wireless */ /* * 106 is reserved for Linux Classical IP over ATM; it's like DLT_RAW, * except when it isn't. (I.e., sometimes it's just raw IP, and * sometimes it isn't.) We currently handle it as DLT_LINUX_SLL, * so that we don't have to worry about the link-layer header.) */ /* * Frame Relay; BSD/OS has a DLT_FR with a value of 11, but that collides * with other values. * DLT_FR and DLT_FRELAY packets start with the Q.922 Frame Relay header * (DLCI, etc.). */ #define DLT_FRELAY 107 /* * OpenBSD DLT_LOOP, for loopback devices; it's like DLT_NULL, except * that the AF_ type in the link-layer header is in network byte order. * * DLT_LOOP is 12 in OpenBSD, but that's DLT_RAW in other OSes, so * we don't use 12 for it in OSes other than OpenBSD. */ #ifdef __OpenBSD__ #define DLT_LOOP 12 #else #define DLT_LOOP 108 #endif /* * Encapsulated packets for IPsec; DLT_ENC is 13 in OpenBSD, but that's * DLT_SLIP_BSDOS in NetBSD, so we don't use 13 for it in OSes other * than OpenBSD. */ #ifdef __OpenBSD__ #define DLT_ENC 13 #else #define DLT_ENC 109 #endif /* * Values between 110 and 112 are reserved for use in capture file headers * as link-layer types corresponding to DLT_ types that might differ * between platforms; don't use those values for new DLT_ types * other than the corresponding DLT_ types. */ /* * This is for Linux cooked sockets. */ #define DLT_LINUX_SLL 113 /* * Apple LocalTalk hardware. */ #define DLT_LTALK 114 /* * Acorn Econet. */ #define DLT_ECONET 115 /* * Reserved for use with OpenBSD ipfilter. */ #define DLT_IPFILTER 116 /* * OpenBSD DLT_PFLOG; DLT_PFLOG is 17 in OpenBSD, but that's DLT_LANE8023 * in SuSE 6.3, so we can't use 17 for it in capture-file headers. * * XXX: is there a conflict with DLT_PFSYNC 18 as well? */ #ifdef __OpenBSD__ #define DLT_OLD_PFLOG 17 #define DLT_PFSYNC 18 #endif #define DLT_PFLOG 117 /* * Registered for Cisco-internal use. */ #define DLT_CISCO_IOS 118 /* * For 802.11 cards using the Prism II chips, with a link-layer * header including Prism monitor mode information plus an 802.11 * header. */ #define DLT_PRISM_HEADER 119 /* * Reserved for Aironet 802.11 cards, with an Aironet link-layer header * (see Doug Ambrisko's FreeBSD patches). */ #define DLT_AIRONET_HEADER 120 /* * Reserved for Siemens HiPath HDLC. */ #define DLT_HHDLC 121 /* * This is for RFC 2625 IP-over-Fibre Channel. * * This is not for use with raw Fibre Channel, where the link-layer * header starts with a Fibre Channel frame header; it's for IP-over-FC, * where the link-layer header starts with an RFC 2625 Network_Header * field. */ #define DLT_IP_OVER_FC 122 /* * This is for Full Frontal ATM on Solaris with SunATM, with a * pseudo-header followed by an AALn PDU. * * There may be other forms of Full Frontal ATM on other OSes, * with different pseudo-headers. * * If ATM software returns a pseudo-header with VPI/VCI information * (and, ideally, packet type information, e.g. signalling, ILMI, * LANE, LLC-multiplexed traffic, etc.), it should not use * DLT_ATM_RFC1483, but should get a new DLT_ value, so tcpdump * and the like don't have to infer the presence or absence of a * pseudo-header and the form of the pseudo-header. */ #define DLT_SUNATM 123 /* Solaris+SunATM */ /* * Reserved as per request from Kent Dahlgren * for private use. */ #define DLT_RIO 124 /* RapidIO */ #define DLT_PCI_EXP 125 /* PCI Express */ #define DLT_AURORA 126 /* Xilinx Aurora link layer */ /* * Header for 802.11 plus a number of bits of link-layer information * including radio information, used by some recent BSD drivers as * well as the madwifi Atheros driver for Linux. */ #define DLT_IEEE802_11_RADIO 127 /* 802.11 plus radiotap radio header */ /* * Reserved for the TZSP encapsulation, as per request from * Chris Waters * TZSP is a generic encapsulation for any other link type, * which includes a means to include meta-information * with the packet, e.g. signal strength and channel * for 802.11 packets. */ #define DLT_TZSP 128 /* Tazmen Sniffer Protocol */ /* * BSD's ARCNET headers have the source host, destination host, * and type at the beginning of the packet; that's what's handed * up to userland via BPF. * * Linux's ARCNET headers, however, have a 2-byte offset field * between the host IDs and the type; that's what's handed up * to userland via PF_PACKET sockets. * * We therefore have to have separate DLT_ values for them. */ #define DLT_ARCNET_LINUX 129 /* ARCNET */ /* * Juniper-private data link types, as per request from * Hannes Gredler . The DLT_s are used * for passing on chassis-internal metainformation such as * QOS profiles, etc.. */ #define DLT_JUNIPER_MLPPP 130 #define DLT_JUNIPER_MLFR 131 #define DLT_JUNIPER_ES 132 #define DLT_JUNIPER_GGSN 133 #define DLT_JUNIPER_MFR 134 #define DLT_JUNIPER_ATM2 135 #define DLT_JUNIPER_SERVICES 136 #define DLT_JUNIPER_ATM1 137 /* * Apple IP-over-IEEE 1394, as per a request from Dieter Siegmund * . The header that's presented is an Ethernet-like * header: * * #define FIREWIRE_EUI64_LEN 8 * struct firewire_header { * u_char firewire_dhost[FIREWIRE_EUI64_LEN]; * u_char firewire_shost[FIREWIRE_EUI64_LEN]; * u_short firewire_type; * }; * * with "firewire_type" being an Ethernet type value, rather than, * for example, raw GASP frames being handed up. */ #define DLT_APPLE_IP_OVER_IEEE1394 138 /* * Various SS7 encapsulations, as per a request from Jeff Morriss * and subsequent discussions. */ #define DLT_MTP2_WITH_PHDR 139 /* pseudo-header with various info, followed by MTP2 */ #define DLT_MTP2 140 /* MTP2, without pseudo-header */ #define DLT_MTP3 141 /* MTP3, without pseudo-header or MTP2 */ #define DLT_SCCP 142 /* SCCP, without pseudo-header or MTP2 or MTP3 */ /* * DOCSIS MAC frames. */ #define DLT_DOCSIS 143 /* * Linux-IrDA packets. Protocol defined at http://www.irda.org. * Those packets include IrLAP headers and above (IrLMP...), but * don't include Phy framing (SOF/EOF/CRC & byte stuffing), because Phy * framing can be handled by the hardware and depend on the bitrate. * This is exactly the format you would get capturing on a Linux-IrDA * interface (irdaX), but not on a raw serial port. * Note the capture is done in "Linux-cooked" mode, so each packet include * a fake packet header (struct sll_header). This is because IrDA packet * decoding is dependant on the direction of the packet (incomming or * outgoing). * When/if other platform implement IrDA capture, we may revisit the * issue and define a real DLT_IRDA... * Jean II */ #define DLT_LINUX_IRDA 144 /* * Reserved for IBM SP switch and IBM Next Federation switch. */ #define DLT_IBM_SP 145 #define DLT_IBM_SN 146 /* * Reserved for private use. If you have some link-layer header type * that you want to use within your organization, with the capture files * using that link-layer header type not ever be sent outside your * organization, you can use these values. * * No libpcap release will use these for any purpose, nor will any * tcpdump release use them, either. * * Do *NOT* use these in capture files that you expect anybody not using * your private versions of capture-file-reading tools to read; in * particular, do *NOT* use them in products, otherwise you may find that * people won't be able to use tcpdump, or snort, or Ethereal, or... to * read capture files from your firewall/intrusion detection/traffic * monitoring/etc. appliance, or whatever product uses that DLT_ value, * and you may also find that the developers of those applications will * not accept patches to let them read those files. * * Also, do not use them if somebody might send you a capture using them * for *their* private type and tools using them for *your* private type * would have to read them. * * Instead, ask "tcpdump-workers@lists.tcpdump.org" for a new DLT_ value, * as per the comment above, and use the type you're given. */ #define DLT_USER0 147 #define DLT_USER1 148 #define DLT_USER2 149 #define DLT_USER3 150 #define DLT_USER4 151 #define DLT_USER5 152 #define DLT_USER6 153 #define DLT_USER7 154 #define DLT_USER8 155 #define DLT_USER9 156 #define DLT_USER10 157 #define DLT_USER11 158 #define DLT_USER12 159 #define DLT_USER13 160 #define DLT_USER14 161 #define DLT_USER15 162 /* * For future use with 802.11 captures - defined by AbsoluteValue * Systems to store a number of bits of link-layer information * including radio information: * * http://www.shaftnet.org/~pizza/software/capturefrm.txt * * but it might be used by some non-AVS drivers now or in the * future. */ #define DLT_IEEE802_11_RADIO_AVS 163 /* 802.11 plus AVS radio header */ /* * Juniper-private data link type, as per request from * Hannes Gredler . The DLT_s are used * for passing on chassis-internal metainformation such as * QOS profiles, etc.. */ #define DLT_JUNIPER_MONITOR 164 /* * Reserved for BACnet MS/TP. */ #define DLT_BACNET_MS_TP 165 /* * Another PPP variant as per request from Karsten Keil . * * This is used in some OSes to allow a kernel socket filter to distinguish * between incoming and outgoing packets, on a socket intended to * supply pppd with outgoing packets so it can do dial-on-demand and * hangup-on-lack-of-demand; incoming packets are filtered out so they * don't cause pppd to hold the connection up (you don't want random * input packets such as port scans, packets from old lost connections, * etc. to force the connection to stay up). * * The first byte of the PPP header (0xff03) is modified to accomodate * the direction - 0x00 = IN, 0x01 = OUT. */ #define DLT_PPP_PPPD 166 /* * Names for backwards compatibility with older versions of some PPP * software; new software should use DLT_PPP_PPPD. */ #define DLT_PPP_WITH_DIRECTION DLT_PPP_PPPD #define DLT_LINUX_PPP_WITHDIRECTION DLT_PPP_PPPD /* * Juniper-private data link type, as per request from * Hannes Gredler . The DLT_s are used * for passing on chassis-internal metainformation such as * QOS profiles, cookies, etc.. */ #define DLT_JUNIPER_PPPOE 167 #define DLT_JUNIPER_PPPOE_ATM 168 #define DLT_GPRS_LLC 169 /* GPRS LLC */ #define DLT_GPF_T 170 /* GPF-T (ITU-T G.7041/Y.1303) */ #define DLT_GPF_F 171 /* GPF-F (ITU-T G.7041/Y.1303) */ /* * Requested by Oolan Zimmer for use in Gcom's T1/E1 line * monitoring equipment. */ #define DLT_GCOM_T1E1 172 #define DLT_GCOM_SERIAL 173 /* * Juniper-private data link type, as per request from * Hannes Gredler . The DLT_ is used * for internal communication to Physical Interface Cards (PIC) */ #define DLT_JUNIPER_PIC_PEER 174 /* * Link types requested by Gregor Maier of Endace * Measurement Systems. They add an ERF header (see * http://www.endace.com/support/EndaceRecordFormat.pdf) in front of * the link-layer header. */ #define DLT_ERF_ETH 175 /* Ethernet */ #define DLT_ERF_POS 176 /* Packet-over-SONET */ /* * Requested by Daniele Orlandi for raw LAPD * for vISDN (http://www.orlandi.com/visdn/). Its link-layer header * includes additional information before the LAPD header, so it's * not necessarily a generic LAPD header. */ #define DLT_LINUX_LAPD 177 /* * Juniper-private data link type, as per request from * Hannes Gredler . * The DLT_ are used for prepending meta-information * like interface index, interface name * before standard Ethernet, PPP, Frelay & C-HDLC Frames */ #define DLT_JUNIPER_ETHER 178 #define DLT_JUNIPER_PPP 179 #define DLT_JUNIPER_FRELAY 180 #define DLT_JUNIPER_CHDLC 181 /* * Multi Link Frame Relay (FRF.16) */ #define DLT_MFR 182 /* * Juniper-private data link type, as per request from * Hannes Gredler . * The DLT_ is used for internal communication with a * voice Adapter Card (PIC) */ #define DLT_JUNIPER_VP 183 /* * Arinc 429 frames. * DLT_ requested by Gianluca Varenni . * Every frame contains a 32bit A429 label. * More documentation on Arinc 429 can be found at * http://www.condoreng.com/support/downloads/tutorials/ARINCTutorial.pdf */ #define DLT_A429 184 /* * Arinc 653 Interpartition Communication messages. * DLT_ requested by Gianluca Varenni . * Please refer to the A653-1 standard for more information. */ #define DLT_A653_ICM 185 /* * USB packets, beginning with a USB setup header; requested by * Paolo Abeni . */ #define DLT_USB 186 /* * Bluetooth HCI UART transport layer (part H:4); requested by * Paolo Abeni. */ #define DLT_BLUETOOTH_HCI_H4 187 /* * IEEE 802.16 MAC Common Part Sublayer; requested by Maria Cruz * . */ #define DLT_IEEE802_16_MAC_CPS 188 /* * USB packets, beginning with a Linux USB header; requested by * Paolo Abeni . */ #define DLT_USB_LINUX 189 /* * Controller Area Network (CAN) v. 2.0B packets. * DLT_ requested by Gianluca Varenni . * Used to dump CAN packets coming from a CAN Vector board. * More documentation on the CAN v2.0B frames can be found at * http://www.can-cia.org/downloads/?269 */ #define DLT_CAN20B 190 /* * IEEE 802.15.4, with address fields padded, as is done by Linux * drivers; requested by Juergen Schimmer. */ #define DLT_IEEE802_15_4_LINUX 191 /* * Per Packet Information encapsulated packets. * DLT_ requested by Gianluca Varenni . */ #define DLT_PPI 192 /* * Header for 802.16 MAC Common Part Sublayer plus a radiotap radio header; * requested by Charles Clancy. */ #define DLT_IEEE802_16_MAC_CPS_RADIO 193 /* * Juniper-private data link type, as per request from * Hannes Gredler . * The DLT_ is used for internal communication with a * integrated service module (ISM). */ #define DLT_JUNIPER_ISM 194 /* * IEEE 802.15.4, exactly as it appears in the spec (no padding, no * nothing); requested by Mikko Saarnivala . */ #define DLT_IEEE802_15_4 195 /* * Various link-layer types, with a pseudo-header, for SITA * (http://www.sita.aero/); requested by Fulko Hew (fulko.hew@gmail.com). */ #define DLT_SITA 196 /* * Various link-layer types, with a pseudo-header, for Endace DAG cards; * encapsulates Endace ERF records. Requested by Stephen Donnelly * . */ #define DLT_ERF 197 /* * Special header prepended to Ethernet packets when capturing from a * u10 Networks board. Requested by Phil Mulholland * . */ #define DLT_RAIF1 198 /* * IPMB packet for IPMI, beginning with the I2C slave address, followed * by the netFn and LUN, etc.. Requested by Chanthy Toeung * . */ #define DLT_IPMB 199 /* * Juniper-private data link type, as per request from * Hannes Gredler . * The DLT_ is used for capturing data on a secure tunnel interface. */ #define DLT_JUNIPER_ST 200 /* * Bluetooth HCI UART transport layer (part H:4), with pseudo-header * that includes direction information; requested by Paolo Abeni. */ #define DLT_BLUETOOTH_HCI_H4_WITH_PHDR 201 /* * AX.25 packet with a 1-byte KISS header; see * * http://www.ax25.net/kiss.htm * * as per Richard Stearn . */ #define DLT_AX25_KISS 202 /* * LAPD packets from an ISDN channel, starting with the address field, * with no pseudo-header. * Requested by Varuna De Silva . */ #define DLT_LAPD 203 /* * Variants of various link-layer headers, with a one-byte direction * pseudo-header prepended - zero means "received by this host", * non-zero (any non-zero value) means "sent by this host" - as per * Will Barker . */ #define DLT_PPP_WITH_DIR 204 /* PPP - don't confuse with DLT_PPP_WITH_DIRECTION */ #define DLT_C_HDLC_WITH_DIR 205 /* Cisco HDLC */ #define DLT_FRELAY_WITH_DIR 206 /* Frame Relay */ #define DLT_LAPB_WITH_DIR 207 /* LAPB */ /* * 208 is reserved for an as-yet-unspecified proprietary link-layer * type, as requested by Will Barker. */ /* * IPMB with a Linux-specific pseudo-header; as requested by Alexey Neyman * . */ #define DLT_IPMB_LINUX 209 /* * FlexRay automotive bus - http://www.flexray.com/ - as requested * by Hannes Kaelber . */ #define DLT_FLEXRAY 210 /* * Media Oriented Systems Transport (MOST) bus for multimedia * transport - http://www.mostcooperation.com/ - as requested * by Hannes Kaelber . */ #define DLT_MOST 211 /* * Local Interconnect Network (LIN) bus for vehicle networks - * http://www.lin-subbus.org/ - as requested by Hannes Kaelber * . */ #define DLT_LIN 212 /* * X2E-private data link type used for serial line capture, * as requested by Hannes Kaelber . */ #define DLT_X2E_SERIAL 213 /* * X2E-private data link type used for the Xoraya data logger * family, as requested by Hannes Kaelber . */ #define DLT_X2E_XORAYA 214 /* * IEEE 802.15.4, exactly as it appears in the spec (no padding, no * nothing), but with the PHY-level data for non-ASK PHYs (4 octets * of 0 as preamble, one octet of SFD, one octet of frame length+ * reserved bit, and then the MAC-layer data, starting with the * frame control field). * * Requested by Max Filippov . */ #define DLT_IEEE802_15_4_NONASK_PHY 215 /* * DLT and savefile link type values are split into a class and * a member of that class. A class value of 0 indicates a regular * DLT_/LINKTYPE_ value. */ #define DLT_CLASS(x) ((x) & 0x03ff0000) /* * NetBSD-specific generic "raw" link type. The class value indicates * that this is the generic raw type, and the lower 16 bits are the * address family we're dealing with. Those values are NetBSD-specific; * do not assume that they correspond to AF_ values for your operating * system. */ #define DLT_CLASS_NETBSD_RAWAF 0x02240000 #define DLT_NETBSD_RAWAF(af) (DLT_CLASS_NETBSD_RAWAF | (af)) #define DLT_NETBSD_RAWAF_AF(x) ((x) & 0x0000ffff) #define DLT_IS_NETBSD_RAWAF(x) (DLT_CLASS(x) == DLT_CLASS_NETBSD_RAWAF) /* * The instruction encodings. */ /* instruction classes */ #define BPF_CLASS(code) ((code) & 0x07) #define BPF_LD 0x00 #define BPF_LDX 0x01 #define BPF_ST 0x02 #define BPF_STX 0x03 #define BPF_ALU 0x04 #define BPF_JMP 0x05 #define BPF_RET 0x06 #define BPF_MISC 0x07 /* ld/ldx fields */ #define BPF_SIZE(code) ((code) & 0x18) #define BPF_W 0x00 #define BPF_H 0x08 #define BPF_B 0x10 #define BPF_MODE(code) ((code) & 0xe0) #define BPF_IMM 0x00 #define BPF_ABS 0x20 #define BPF_IND 0x40 #define BPF_MEM 0x60 #define BPF_LEN 0x80 #define BPF_MSH 0xa0 /* alu/jmp fields */ #define BPF_OP(code) ((code) & 0xf0) #define BPF_ADD 0x00 #define BPF_SUB 0x10 #define BPF_MUL 0x20 #define BPF_DIV 0x30 #define BPF_OR 0x40 #define BPF_AND 0x50 #define BPF_LSH 0x60 #define BPF_RSH 0x70 #define BPF_NEG 0x80 #define BPF_JA 0x00 #define BPF_JEQ 0x10 #define BPF_JGT 0x20 #define BPF_JGE 0x30 #define BPF_JSET 0x40 #define BPF_SRC(code) ((code) & 0x08) #define BPF_K 0x00 #define BPF_X 0x08 /* ret - BPF_K and BPF_X also apply */ #define BPF_RVAL(code) ((code) & 0x18) #define BPF_A 0x10 /* misc */ #define BPF_MISCOP(code) ((code) & 0xf8) #define BPF_TAX 0x00 #define BPF_TXA 0x80 /* * The instruction data structure. */ struct bpf_insn { u_short code; u_char jt; u_char jf; bpf_u_int32 k; }; /* * Macros for insn array initializers. */ #define BPF_STMT(code, k) { (u_short)(code), 0, 0, k } #define BPF_JUMP(code, k, jt, jf) { (u_short)(code), jt, jf, k } #if __STDC__ || defined(__cplusplus) extern int bpf_validate(const struct bpf_insn *, int); extern u_int bpf_filter(const struct bpf_insn *, const u_char *, u_int, u_int); #else extern int bpf_validate(); extern u_int bpf_filter(); #endif /* * Number of scratch memory words (for BPF_LD|BPF_MEM and BPF_ST). */ #define BPF_MEMWORDS 16 #ifdef __cplusplus } #endif #endif ptunnel-ng-1.43/src/win32/includes/pcap/pcap.h000066400000000000000000000333521460452726400211260ustar00rootroot00000000000000/* -*- Mode: c; tab-width: 8; indent-tabs-mode: 1; c-basic-offset: 8; -*- */ /* * Copyright (c) 1993, 1994, 1995, 1996, 1997 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the Computer Systems * Engineering Group at Lawrence Berkeley Laboratory. * 4. Neither the name of the University nor of the Laboratory may be used * to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#) $Header: /tcpdump/master/libpcap/pcap/pcap.h,v 1.4.2.11 2008-10-06 15:38:39 gianluca Exp $ (LBL) */ #ifndef lib_pcap_pcap_h #define lib_pcap_pcap_h #if defined(WIN32) #include #elif defined(MSDOS) #include #include /* u_int, u_char etc. */ #else /* UN*X */ #include #include #endif /* WIN32/MSDOS/UN*X */ #ifndef PCAP_DONT_INCLUDE_PCAP_BPF_H #include #endif #include #ifdef HAVE_REMOTE // We have to define the SOCKET here, although it has been defined in sockutils.h // This is to avoid the distribution of the 'sockutils.h' file around // (for example in the WinPcap developer's pack) #ifndef SOCKET #ifdef WIN32 #define SOCKET unsigned int #else #define SOCKET int #endif #endif #endif #ifdef __cplusplus extern "C" { #endif #define PCAP_VERSION_MAJOR 2 #define PCAP_VERSION_MINOR 4 #define PCAP_ERRBUF_SIZE 256 /* * Compatibility for systems that have a bpf.h that * predates the bpf typedefs for 64-bit support. */ #if BPF_RELEASE - 0 < 199406 typedef int bpf_int32; typedef u_int bpf_u_int32; #endif typedef struct pcap pcap_t; typedef struct pcap_dumper pcap_dumper_t; typedef struct pcap_if pcap_if_t; typedef struct pcap_addr pcap_addr_t; /* * The first record in the file contains saved values for some * of the flags used in the printout phases of tcpdump. * Many fields here are 32 bit ints so compilers won't insert unwanted * padding; these files need to be interchangeable across architectures. * * Do not change the layout of this structure, in any way (this includes * changes that only affect the length of fields in this structure). * * Also, do not change the interpretation of any of the members of this * structure, in any way (this includes using values other than * LINKTYPE_ values, as defined in "savefile.c", in the "linktype" * field). * * Instead: * * introduce a new structure for the new format, if the layout * of the structure changed; * * send mail to "tcpdump-workers@lists.tcpdump.org", requesting * a new magic number for your new capture file format, and, when * you get the new magic number, put it in "savefile.c"; * * use that magic number for save files with the changed file * header; * * make the code in "savefile.c" capable of reading files with * the old file header as well as files with the new file header * (using the magic number to determine the header format). * * Then supply the changes as a patch at * * http://sourceforge.net/projects/libpcap/ * * so that future versions of libpcap and programs that use it (such as * tcpdump) will be able to read your new capture file format. */ struct pcap_file_header { bpf_u_int32 magic; u_short version_major; u_short version_minor; bpf_int32 thiszone; /* gmt to local correction */ bpf_u_int32 sigfigs; /* accuracy of timestamps */ bpf_u_int32 snaplen; /* max length saved portion of each pkt */ bpf_u_int32 linktype; /* data link type (LINKTYPE_*) */ }; /* * Macros for the value returned by pcap_datalink_ext(). * * If LT_FCS_LENGTH_PRESENT(x) is true, the LT_FCS_LENGTH(x) macro * gives the FCS length of packets in the capture. */ #define LT_FCS_LENGTH_PRESENT(x) ((x) & 0x04000000) #define LT_FCS_LENGTH(x) (((x) & 0xF0000000) >> 28) #define LT_FCS_DATALINK_EXT(x) ((((x) & 0xF) << 28) | 0x04000000) typedef enum { PCAP_D_INOUT = 0, PCAP_D_IN, PCAP_D_OUT } pcap_direction_t; /* * Generic per-packet information, as supplied by libpcap. * * The time stamp can and should be a "struct timeval", regardless of * whether your system supports 32-bit tv_sec in "struct timeval", * 64-bit tv_sec in "struct timeval", or both if it supports both 32-bit * and 64-bit applications. The on-disk format of savefiles uses 32-bit * tv_sec (and tv_usec); this structure is irrelevant to that. 32-bit * and 64-bit versions of libpcap, even if they're on the same platform, * should supply the appropriate version of "struct timeval", even if * that's not what the underlying packet capture mechanism supplies. */ struct pcap_pkthdr { struct timeval ts; /* time stamp */ bpf_u_int32 caplen; /* length of portion present */ bpf_u_int32 len; /* length this packet (off wire) */ }; /* * As returned by the pcap_stats() */ struct pcap_stat { u_int ps_recv; /* number of packets received */ u_int ps_drop; /* number of packets dropped */ u_int ps_ifdrop; /* drops by interface XXX not yet supported */ #ifdef HAVE_REMOTE u_int ps_capt; /* number of packets that are received by the application; please get rid off the Win32 ifdef */ u_int ps_sent; /* number of packets sent by the server on the network */ u_int ps_netdrop; /* number of packets lost on the network */ #endif /* HAVE_REMOTE */ }; #ifdef MSDOS /* * As returned by the pcap_stats_ex() */ struct pcap_stat_ex { u_long rx_packets; /* total packets received */ u_long tx_packets; /* total packets transmitted */ u_long rx_bytes; /* total bytes received */ u_long tx_bytes; /* total bytes transmitted */ u_long rx_errors; /* bad packets received */ u_long tx_errors; /* packet transmit problems */ u_long rx_dropped; /* no space in Rx buffers */ u_long tx_dropped; /* no space available for Tx */ u_long multicast; /* multicast packets received */ u_long collisions; /* detailed rx_errors: */ u_long rx_length_errors; u_long rx_over_errors; /* receiver ring buff overflow */ u_long rx_crc_errors; /* recv'd pkt with crc error */ u_long rx_frame_errors; /* recv'd frame alignment error */ u_long rx_fifo_errors; /* recv'r fifo overrun */ u_long rx_missed_errors; /* recv'r missed packet */ /* detailed tx_errors */ u_long tx_aborted_errors; u_long tx_carrier_errors; u_long tx_fifo_errors; u_long tx_heartbeat_errors; u_long tx_window_errors; }; #endif /* * Item in a list of interfaces. */ struct pcap_if { struct pcap_if *next; char *name; /* name to hand to "pcap_open_live()" */ char *description; /* textual description of interface, or NULL */ struct pcap_addr *addresses; bpf_u_int32 flags; /* PCAP_IF_ interface flags */ }; #define PCAP_IF_LOOPBACK 0x00000001 /* interface is loopback */ /* * Representation of an interface address. */ struct pcap_addr { struct pcap_addr *next; struct sockaddr *addr; /* address */ struct sockaddr *netmask; /* netmask for that address */ struct sockaddr *broadaddr; /* broadcast address for that address */ struct sockaddr *dstaddr; /* P2P destination address for that address */ }; typedef void (*pcap_handler)(u_char *, const struct pcap_pkthdr *, const u_char *); /* * Error codes for the pcap API. * These will all be negative, so you can check for the success or * failure of a call that returns these codes by checking for a * negative value. */ #define PCAP_ERROR -1 /* generic error code */ #define PCAP_ERROR_BREAK -2 /* loop terminated by pcap_breakloop */ #define PCAP_ERROR_NOT_ACTIVATED -3 /* the capture needs to be activated */ #define PCAP_ERROR_ACTIVATED -4 /* the operation can't be performed on already activated captures */ #define PCAP_ERROR_NO_SUCH_DEVICE -5 /* no such device exists */ #define PCAP_ERROR_RFMON_NOTSUP -6 /* this device doesn't support rfmon (monitor) mode */ #define PCAP_ERROR_NOT_RFMON -7 /* operation supported only in monitor mode */ #define PCAP_ERROR_PERM_DENIED -8 /* no permission to open the device */ #define PCAP_ERROR_IFACE_NOT_UP -9 /* interface isn't up */ /* * Warning codes for the pcap API. * These will all be positive and non-zero, so they won't look like * errors. */ #define PCAP_WARNING 1 /* generic warning code */ #define PCAP_WARNING_PROMISC_NOTSUP 2 /* this device doesn't support promiscuous mode */ char *pcap_lookupdev(char *); int pcap_lookupnet(const char *, bpf_u_int32 *, bpf_u_int32 *, char *); pcap_t *pcap_create(const char *, char *); int pcap_set_snaplen(pcap_t *, int); int pcap_set_promisc(pcap_t *, int); int pcap_can_set_rfmon(pcap_t *); int pcap_set_rfmon(pcap_t *, int); int pcap_set_timeout(pcap_t *, int); int pcap_set_buffer_size(pcap_t *, int); int pcap_activate(pcap_t *); pcap_t *pcap_open_live(const char *, int, int, int, char *); pcap_t *pcap_open_dead(int, int); pcap_t *pcap_open_offline(const char *, char *); #if defined(WIN32) pcap_t *pcap_hopen_offline(intptr_t, char *); #if !defined(LIBPCAP_EXPORTS) #define pcap_fopen_offline(f,b) \ pcap_hopen_offline(_get_osfhandle(_fileno(f)), b) #else /*LIBPCAP_EXPORTS*/ static pcap_t *pcap_fopen_offline(FILE *, char *); #endif #else /*WIN32*/ pcap_t *pcap_fopen_offline(FILE *, char *); #endif /*WIN32*/ void pcap_close(pcap_t *); int pcap_loop(pcap_t *, int, pcap_handler, u_char *); int pcap_dispatch(pcap_t *, int, pcap_handler, u_char *); const u_char* pcap_next(pcap_t *, struct pcap_pkthdr *); int pcap_next_ex(pcap_t *, struct pcap_pkthdr **, const u_char **); void pcap_breakloop(pcap_t *); int pcap_stats(pcap_t *, struct pcap_stat *); int pcap_setfilter(pcap_t *, struct bpf_program *); int pcap_setdirection(pcap_t *, pcap_direction_t); int pcap_getnonblock(pcap_t *, char *); int pcap_setnonblock(pcap_t *, int, char *); int pcap_inject(pcap_t *, const void *, size_t); int pcap_sendpacket(pcap_t *, const u_char *, int); const char *pcap_statustostr(int); const char *pcap_strerror(int); char *pcap_geterr(pcap_t *); void pcap_perror(pcap_t *, char *); int pcap_compile(pcap_t *, struct bpf_program *, const char *, int, bpf_u_int32); int pcap_compile_nopcap(int, int, struct bpf_program *, const char *, int, bpf_u_int32); void pcap_freecode(struct bpf_program *); int pcap_offline_filter(struct bpf_program *, const struct pcap_pkthdr *, const u_char *); int pcap_datalink(pcap_t *); int pcap_datalink_ext(pcap_t *); int pcap_list_datalinks(pcap_t *, int **); int pcap_set_datalink(pcap_t *, int); void pcap_free_datalinks(int *); int pcap_datalink_name_to_val(const char *); const char *pcap_datalink_val_to_name(int); const char *pcap_datalink_val_to_description(int); int pcap_snapshot(pcap_t *); int pcap_is_swapped(pcap_t *); int pcap_major_version(pcap_t *); int pcap_minor_version(pcap_t *); /* XXX */ FILE *pcap_file(pcap_t *); int pcap_fileno(pcap_t *); pcap_dumper_t *pcap_dump_open(pcap_t *, const char *); pcap_dumper_t *pcap_dump_fopen(pcap_t *, FILE *fp); FILE *pcap_dump_file(pcap_dumper_t *); long pcap_dump_ftell(pcap_dumper_t *); int pcap_dump_flush(pcap_dumper_t *); void pcap_dump_close(pcap_dumper_t *); void pcap_dump(u_char *, const struct pcap_pkthdr *, const u_char *); int pcap_findalldevs(pcap_if_t **, char *); void pcap_freealldevs(pcap_if_t *); const char *pcap_lib_version(void); /* XXX this guy lives in the bpf tree */ u_int bpf_filter(const struct bpf_insn *, const u_char *, u_int, u_int); int bpf_validate(const struct bpf_insn *f, int len); char *bpf_image(const struct bpf_insn *, int); void bpf_dump(const struct bpf_program *, int); #if defined(WIN32) /* * Win32 definitions */ int pcap_setbuff(pcap_t *p, int dim); int pcap_setmode(pcap_t *p, int mode); int pcap_setmintocopy(pcap_t *p, int size); #ifdef WPCAP /* Include file with the wpcap-specific extensions */ #include #endif /* WPCAP */ #define MODE_CAPT 0 #define MODE_STAT 1 #define MODE_MON 2 #elif defined(MSDOS) /* * MS-DOS definitions */ int pcap_stats_ex (pcap_t *, struct pcap_stat_ex *); void pcap_set_wait (pcap_t *p, void (*yield)(void), int wait); u_long pcap_mac_packets (void); #else /* UN*X */ /* * UN*X definitions */ int pcap_get_selectable_fd(pcap_t *); #endif /* WIN32/MSDOS/UN*X */ #ifdef HAVE_REMOTE /* Includes most of the public stuff that is needed for the remote capture */ #include #endif /* HAVE_REMOTE */ #ifdef __cplusplus } #endif #endif ptunnel-ng-1.43/test/000077500000000000000000000000001460452726400145215ustar00rootroot00000000000000ptunnel-ng-1.43/test/integration_test.sh000077500000000000000000000061641460452726400204510ustar00rootroot00000000000000#!/usr/bin/env bash set -e set -x set -o pipefail BIN_ROOT="${BIN_ROOT:-$(realpath $(dirname $0)/..)}" PTUNNEL_BIN=${PTUNNEL_BIN:-${BIN_ROOT}/src/ptunnel-ng} PTUNNEL_ARGS="${PTUNNEL_ARGS:-}" VALGRIND_BIN=${VALGRIND_BIN:-valgrind} VALGRIND_ARGS="--error-exitcode=1 --exit-on-first-error=yes" if [ "x${DISABLE_VALGRIND}" = xy ]; then VALGRIND_BIN="" VALGRIND_ARGS="" fi test -x "${PTUNNEL_BIN}" #################### # Test PERFORMANCE # #################### TUNNEL_TIMEOUT=25 DATA_TIMEOUT=22 echo -n >/tmp/ptunnel-server.log echo -n >/tmp/ptunnel-client.log timeout --foreground -k1 ${TUNNEL_TIMEOUT} \ ${VALGRIND_BIN} ${VALGRIND_ARGS} \ "${PTUNNEL_BIN}" -v4 -r127.0.0.1 -R3000 -l4000 ${PTUNNEL_ARGS} -o/tmp/ptunnel-server.log & PTUNNEL_SERVER_PID=$! timeout --foreground -k1 ${TUNNEL_TIMEOUT} \ ${VALGRIND_BIN} ${VALGRIND_ARGS} \ "${PTUNNEL_BIN}" -v4 -p127.0.0.1 -r127.0.0.1 -R3000 -l4000 ${PTUNNEL_ARGS} -o/tmp/ptunnel-client.log & PTUNNEL_CLIENT_PID=$! timeout --foreground -k1 ${DATA_TIMEOUT} \ nc -l -p 3000 >/dev/null || true & DATA_SERVER_PID=$! sleep 3 timeout --foreground -k1 ${DATA_TIMEOUT} \ sh -c "dd if=/dev/urandom bs=8192 | nc 127.0.0.1 4000" || true wait ${PTUNNEL_CLIENT_PID} || true wait ${PTUNNEL_SERVER_PID} || true wait ${DATA_SERVER_PID} || true cat /tmp/ptunnel-client.log cat /tmp/ptunnel-server.log cat /tmp/ptunnel-client.log |& grep 'Incoming connection.' cat /tmp/ptunnel-server.log |& grep 'Starting new session to 127.0.0.1:3000' # verify results CLIENT_ACK_SERIES=$(cat /tmp/ptunnel-client.log |& grep 'Received ack-series starting at seq' | wc -l) SERVER_ACK_SERIES=$(cat /tmp/ptunnel-server.log |& grep 'Received ack-series starting at seq' | \ grep -v 'Received ack-series starting at seq 65535' | wc -l) test ${CLIENT_ACK_SERIES} -eq ${SERVER_ACK_SERIES} ####################### # Test DATA INTEGRITY # ####################### TUNNEL_TIMEOUT=10 DATA_TIMEOUT=7 echo -n >/tmp/ptunnel-server.log echo -n >/tmp/ptunnel-client.log timeout --foreground -k1 ${TUNNEL_TIMEOUT} \ ${VALGRIND_BIN} ${VALGRIND_ARGS} \ "${PTUNNEL_BIN}" -v4 -r127.0.0.1 -R3000 -l4000 ${PTUNNEL_ARGS} -o/tmp/ptunnel-server.log & PTUNNEL_SERVER_PID=$! timeout --foreground -k1 ${TUNNEL_TIMEOUT} \ ${VALGRIND_BIN} ${VALGRIND_ARGS} \ "${PTUNNEL_BIN}" -v4 -p127.0.0.1 -r127.0.0.1 -R3000 -l4000 ${PTUNNEL_ARGS} -o/tmp/ptunnel-client.log & PTUNNEL_CLIENT_PID=$! timeout --foreground -k1 ${DATA_TIMEOUT} \ nc -l -p 3000 >/tmp/ptunnel-data-recv || true & DATA_SERVER_PID=$! sleep 3 timeout --foreground -k1 ${DATA_TIMEOUT} \ sh -c "dd if=/dev/urandom bs=8192 count=1 >/tmp/ptunnel-data-send && cat /tmp/ptunnel-data-send | sha256sum | cut -d' ' -f1 >/tmp/ptunnel-data-send.sha256 && cat /tmp/ptunnel-data-send | nc 127.0.0.1 4000" || true wait ${PTUNNEL_CLIENT_PID} || true wait ${PTUNNEL_SERVER_PID} || true wait ${DATA_SERVER_PID} || true # verify results test ${CLIENT_ACK_SERIES} -eq ${SERVER_ACK_SERIES} CLIENT_SHA=$(cat /tmp/ptunnel-data-send.sha256) SERVER_SHA=$(cat /tmp/ptunnel-data-recv | sha256sum | cut -d' ' -f1) test ${CLIENT_SHA} = ${SERVER_SHA} set +x printf '[+] SUCCESS !!\n' ptunnel-ng-1.43/web/000077500000000000000000000000001460452726400143175ustar00rootroot00000000000000ptunnel-ng-1.43/web/index.html000077500000000000000000000544521460452726400163310ustar00rootroot00000000000000 Ping Tunnel [N]ew[G]eneration - Send TCP traffic over ICMP

Ping Tunnel [N]ew[G]eneration

For those times when everything else is blocked.

By Daniel Stødle, daniels@cs.uit.no
Last updated: 5. September 2011

Contents


What is it?

Ptunnel is an application that allows you to reliably tunnel TCP connections to a remote host using ICMP echo request and reply packets, commonly known as ping requests and replies. At first glance, this might seem like a rather useless thing to do, but it can actually come in handy in some cases. The following example illustrates the main motivation in creating ptunnel:

Setting: You're on the go, and stumble across an open wireless network. The network gives you an IP address, but won't let you send TCP or UDP packets out to the rest of the internet, for instance to check your mail. What to do? By chance, you discover that the network will allow you to ping any computer on the rest of the internet. With ptunnel, you can utilize this feature to check your mail, or do other things that require TCP.

Features and requirements

Ptunnel is not a feature-rich tool by any means, but it does what it advertises. So here is what it can do:

  • Tunnel TCP using ICMP echo request and reply packets
  • Connections are reliable (lost packets are resent as necessary)
  • Handles multiple connections
  • Acceptable bandwidth (150 kb/s downstream and about 50 kb/s upstream are the currently measured maximas for one tunnel, but with tweaking this can be improved further)
  • Authentication, to prevent just anyone from using your proxy
So what do you need for all this to work?

  • One computer accessible on the internet that is not firewalled (or at least allows incoming ICMP packets)
  • A computer to act as the client (this will usually be your laptop, on the go..)
  • Root access, preferably on both computers
  • A posix-compliant OS, with libpcap (for packet capturing) and its associated headers installed (typically available in a dev-package on Ubuntu)
  • Or: Windows with mingw and WinPcap installed
Compiling the sources simply consists of running make. No ./configure, make, make install, just make. On Windows, you'll need to run make ptunnel.exe, but that's it. The resulting binary is called ptunnel. See the usage section below for info on running it.

How it works

This is a technical description of how ptunnel works. If you're not interested in low-level networking details, you can skip this section. It might help to read it either way, as it provides some insights into the situations where ptunnel doesn't work. Ptunnel works by tunneling TCP connections over ICMP packets. In the following, we will talk about the proxy, the client and the destination. The proxy is the "endpoint" for our ping packets, i.e. the computer that we send the ping packets to. The client is the computer we're trying to surf the net from, and the destination is the computer we would normally be trying to access over TCP (such as a web site or an ssh server somewhere).

So, in order to accomplish this, we need the ability to send and receive ping packets. Many operating systems enable us to do this using so-called raw sockets. Raw sockets is the preferred mechanism for sending ICMP packets, and is used by both the proxy and the client. Unfortunately, raw sockets require root, so there is a provision for using standard datagram sockets if they are supported by the operating system (Mac OS X 10.2 or later supports this, but Linux systems will require root either way). Ptunnel supports this, however it is not recommended for actual use. We'll get back to the reason later.

The client will perform all its communications using ICMP echo request (ping) packets (type 8), whereas the proxy will use echo reply packets (type 0). In theory, it is possible to have the proxy also use echo request packets (and thus make it operate without root), but these packets are not necessarily forwarded to the client beyond the host network, so they are not used.

Machine setup
Figure 1. Networking setup.

The protocol

The proxy protocol uses four different message types combined with sequence numbers and an acknowledgement field. A magic number is used to differentiate our ping requests and replies from "usual" pings. The general packet format (not including the IP or ICMP headers) can be seen in the figure below.

Packet format
Figure 2. The packet format used to exchange messages between client and proxy.

The IP and port fields are only used in packets from the client to the proxy. They indicate where the client wants the received packets to be forwarded (they are really only used once - when the proxy receives the first message with state code kProxy_start).

State codes:
kProxy_start = 0;
kProto_data = 1;
kProto_ack = 2;
kProto_close = 3;
kProto_authenticate = 4;

Identifier flags:
kUser_flag = 1 << 30;
kProxy_flag = 1 << 31;

The state code serves a dual purpose. First, it indicates what kind of message is being received - either a message starting a new proxy session (kProxy_start), a message containing data to be forwarded (kProto_data), an explicit acknowledgement of received packets (kProto_ack, a close message (kProto_close) or an authentication challenge/response (kProto_authenticate). Second, it indicates who sent the message: A message sent by the client will have the kUser_flag bit set, whereas a message sent by the proxy has the kProxy_flag bit set. This is necessary since a ping request will cause the operating system on the proxy computer to return its own echo reply, which is identical to the packet we just sent to the proxy. The ack and seq fields are tightly related. Modelled after the use of acknowledgements in TCP, the ptunnel protocol places the sequence number of the last packet received into the ack field of any outgoing message. The seq field is a monotonically increasing 16-bit counter, that is allowed to wrap around (ok, so I guess it's monotonic until it wraps around). Whenever an outgoing packet has been waiting for an acknowledgement too long, the peer will attempt to resend the first packet not yet acknowledged.

The length field simply indicates the length of the data portion of the packet, and is 0 for all other state values than kProto_data. Finally the rsv field contains two bytes that are reserved (for now they serve as padding).

On receiving a kProxy_start request, a proxy will open a TCP connection to the server given by the ip and port fields. As data comes in over the TCP connection, the proxy will convert the data to ICMP echo reply packets, and send them to the remote peer. The client will do the same, except its packets will always be echo request packets.

Authentication

As of version 0.60, Ping Tunnel supports authentication. The authentication used is very simple, and works as follows. The user first specifies a password or passphrase, which is then hashed using the MD5 algorithm (Ping Tunnel uses the implementation by L. Peter Deutsch, available here. Note that the implementation is included with Ping Tunnel, so there is no need to download it separately).

Whenever a proxy receives a request for a new tunnel, it will respond with an authentication challenge. The challenge consists of a timestamp augmented with random data, totalling 32 bytes. The response is calculated as follows (the + denotes string concatenation):

md5(challenge + md5(password))

The proxy verifies the result by computing the same md5 sums, and then comparing the two. If authentication succeeds, the proxy allows TCP traffic to start flowing in either direction; if not, the connection is torn down.

Handling multiple connections

The proxy handles multiple different connections by using the ICMP identifier field. A client will randomly generate an identifier when it starts a session, and the remote peer will use this identifier to associate the packets with a connection. The mechanism is not foolproof, but works acceptably as long as no two instances attempt to use the same identifier (there is currently no mechanism for reporting such errors).

The ICMP sequence number field is not used by ptunnel, mostly due to fears that some routers might drop packets whose sequence number repeats. Instead, a separate sequence number is used as part of the ptunnel packet format (see above).

Send and receive windows

Ptunnel uses the simple concept of send and receive windows for controlling the number of packets that can be in-flight at the same time. The window is currently statically allocated at 64 packets, but the number can be tweaked by modifying the ptunnel header file (yes, a recompile is required). Increasing the window size will improve the maximum potential bandwidth. The send and receive windows are simply implemented as a set of circular arrays, with pointers indicating the next available send/receive slot, and the first non-acked packet.

Handling packet loss

Ptunnel handles packet loss by resending (presumably) lost packets. As it sends packets, it will increment a sequence number. Both the client and proxy maintain their own sequence number, and also a number indicating the last sequence number acknowledged by the remote peer. Whenever too much time (1.5 seconds) passes without a packet being acknowledged, the peer will resend that packet.

Note that the peer will only resend the first missing packet. Once that packet has been acknowledged, it may resend the next packet(s), depending on how many packets were acknowledged. If the next few packets are acknowlegded as well, they are removed from the send queue. It is not uncommon for one packet to get lost, with most of the others making it through. This mechanism avoids unecessary resends as much as possible.

Congestion control

Ptunnel currently does no explicit congestion control. It will send as many ping packets as the window size allows, as slowly or as quickly as it sees fit. This might be improved in the future, if it turns out to be a problem (which is not at all unlikely..).

When things don't work

There are a number of situations where ptunnel will fail. They can briefly be put into the following categories:
  1. Outgoing/incoming ping not allowed, or filtered by a gateway somewhere along the way
  2. Operating system causing trouble
  3. Probably some other failures as well ;)

We can't handle the first failure - if our packets are filtered before we can get at them, there's little we can do. It is possible to deal with the second scenario by using the packet capturing library to get the packets before the OS sees them. This is necessary on Mac OS X, and may be necessary on other platforms as well. The problem lies in that the OS may occasionally not deliver ICMP packets to the raw socket we have opened for sending and receiving. This happens when the ICMP packet is an echo request (which the OS handles by itself) or when the ICMP packet is a resend (for some weird reason). The workaround is to use packet capture, however this tends to diminish bandwidth by quite a bit. For this reason, you should always try to run the proxy without packet capturing, and see if that works first. (This is the default mode.)

Download

The current version of ptunnel is 0.71, and the source code is available for download here. Some other links:

Ptunnel has so far been tested on a variety of configurations, including Linux Fedora Core 2 and Mac OS X 10.3.6 and above.

Debian users can install Ping Tunnel by adding the following to /etc/apt/sources.list

deb http://www.cti.ecp.fr/~beauxir5/debian binary/
deb-src http://www.cti.ecp.fr/~beauxir5/debian source/

And then run apt-get update followed by apt-get install ptunnel. A big thanks to Romain Beauxis for taking the time to create a Debian package for ptunnel!

As of version 0.70, ptunnel has support for Windows built-in, thanks to Mike Miller. You will need mingw and WinPcap (download here) installed to compile on Windows. Please note that I don't use Windows, so I can not provide support for compilation-specific issues regarding the Windows port. Wouter van der Veer has been kind enough to provide a compiled Windows binary on his website, which you can download here.

Using ptunnel

Client: ./ptunnel -p <proxy address> -lp <listen port> -da <destination address> -dp <destination port> [-c <network device>] [-v <verbosity>] [-f <logfile>] [-u] [-x password]
Proxy: ./ptunnel [-c <network device>] [-v <verbosity>] [-f <logfile>] [-u] [-x password]

The -p switch sets the address of the host on which the proxy is running. A quick test to see if the proxy will work is simply to try pinging this host - if you get replies, you should be able to make the tunnel work.

The -lp, -da and -dp switches set the local listening port, destination address and destination port. For instance, to tunnel ssh connections from the client machine via a proxy running on proxy.pingtunnel.com to the computer login.domain.com, the following command line would be used:

sudo ./ptunnel -p proxy.pingtunnel.com -lp 8000 -da login.domain.com -dp 22

An ssh connection to login.domain.com can now be established as follows:

ssh -p 8000 localhost

If ssh complains about potential man-in-the-middle attacks, simply remove the offending key from the known_hosts file. The warning/error is expected if you have previously ssh'd to your local computer (i.e., ssh localhost), or you have used ptunnel to forward ssh connections to different hosts.

Of course, for all of this to work, you need to start the proxy on your proxy-computer (we'll call it proxy.pingtunnel.com here). Doing this is very simple:

sudo ./ptunnel

If you find that the proxy isn't working, you will need to enable packet capturing on the main network device. Currently this device is assumed to be an ethernet-device (i.e., ethernet or wireless). Packet capturing is enabled by giving the -c switch, and supplying the device name to capture packets on (for instance eth0 or en1). The same goes for the client. On versions of Mac OS X prior to 10.4 (Tiger), packet capturing must always be enabled (both for proxy and client), as resent packets won't be received otherwise.

To protect yourself from others using your proxy, you can protect access to it with a password using the -x switch. The password is never sent in the clear, but keep in mind that it may be visible from tools like top or ps, which can display the command line used to start an application.

Finally, the -u switch will attempt to run the proxy in unprivileged mode (i.e., no need for root access), and the -v switch controls the amount of output from ptunnel. -1 indicates no output, 0 shows errors only, 1 shows info messages, 2 gives more output, 3 provides even more output, level 4 displays debug info and level 5 displays absolutely everything, including the nasty details of sends and receives. The -f switch allows output to be saved to a logfile.

Changes

0.72 - 5. September 2011
  • Fixes an authentication bug that would manifest as hung connections with protocols that send data from the client-side before receiving data from the server-side. Thanks to StalkR for locating the bug and fixing it.
  • Fixes a crash when attempting to enable packet-capture for non-existing network devices. Thanks to Steffen Wendzel for the patch.

0.71 - 22. June 2009

  • Added security features and SELinux support, courtesy of Sebastien Raveau.

0.70 - 12. January 2009

  • Added rudimentary support for tunneling over UDP port 53. This may or may not be useful.
  • Added built-in support for compiling on Windows, thanks to Mike Miller.
  • Added syslog support, also courtesy of Mike Miller.
  • Experimental support for spoofing the source IP address. The source address must be explicitly configured in the source code, and it might not work (which is why it's experimental). To enable, define kPT_add_iphdr to 1.

0.62 - Never released

  • Added many comments to the ptunnel header file.
  • Moved most include directives to the header file.
  • Fixed crash if proxy or destination hostnames could not be looked up.

0.61 - 26. May 2005

  • Noted that ptunnel now works without packet capturing on Mac OS X 10.4 Tiger.
  • Log files are now opened in append-mode (i.e., not truncated).
  • Fixed a bug that could cause ptunnel to crash if passwords shorter than 16 characters were used (the overwhelming majority of passwords, most likely!).

0.60 - 15. Apr 2005

  • Added authentication support, changing parts of the ptunnel protocol.
  • Added a manpage.
  • Added MD5 implementation by L. Peter Deutsch for authentication.
  • Moved declaration of a variable to allow ptunnel to compile cleanly on gcc 2.95 - thanks Choong!
  • Added error handling for proxy connections.
  • Fixed a problem with printing send/recv info. All verbosity levels should work now.
  • Updated contact info.

0.55 - 18. Feb 2005

  • Fixed a locking bug that would manifest itself when the maximum connection count on the proxy was reached.
  • Fixed ptunnel to compile correctly on 64-bit architectures (thanks to Åsmund Grammeltvedt for pointing out the necessary changes!)
  • Added a new logging level (level 5). Level 4 no longer outputs send and receive info; for this info level 5 is necessary.
  • When libpcap is in use, the interface is no longer put in promiscous mode. This has never been necessary, and also makes it impossible to use ptunnel with more than one client on the same network.
  • Discovered a problem with pcap that would cause ptunnel to hang when pcap was in use. This problem has not been resolved; the workaround is to simply re-execute the client, or disable pcap if possible.
  • Added support for specifying a log file on the command line, using the -f switch.

0.54 - 1. Feb 2005

  • Fixed a byte-order bug (thanks Alfred!)

0.53 - 31. Jan 2005

  • Fixed a threading bug, and implemented support for limiting the maximum number of tunnels.

Thanks to Alfred Young for reporting and fixing the following bugs:

  • Fixed a bug with packets captured via libpcap, where the struct sockaddr wasn't properly zeroed.
  • Fixed a byte order bug in create_and_insert_proxy_desc.
  • Fixed a memory leak in remove_proxy_desc.

0.52 - 3. Jan 2005

  • Fixed a problem introduced by the ICMP ID field changes. The proxy didn't retain the ID of the packets received from clients, resulting in dropped ICMP packets at the router. This in turn lead to the tunnel no longer working, depending on the strictness of the router. This version fixes that problem.
  • Makefile is better now, thanks to Dries Verachtert.

0.51 - 2. Jan 2005

  • Fixed incorrect checksum calculation for resent packets.
  • Stopped relying on the ICMP packet's "built-in" ID field, and moved the information to the data portion of the packet.
  • Changed default verbosity level from debug to verbose.

0.50 - 7. Dec 2004
Initial public release.

License

Ptunnel is licensed under the BSD license.

Feedback

I'd be grateful for any feedback you may have - send it to me here: daniels@cs.uit.no. I'm interested in hearing about bugs, suggestions and naturally general criticism. If you find it useful, I'd love to know about that too :)

ptunnel-ng-1.43/web/packet-format.png000077500000000000000000000103641460452726400175710ustar00rootroot00000000000000PNG  IHDR|gAMAܲIDATxyTWǿ@! RV .GRrףֵhTpV GmUT,**ҊJZa `$)?sg;w{gS:BLD EE#T " " DoE{yetȢEHhhCT(j߿okEcUr8R=___СCVO@${}bz{3hhh?lkb( [`3T*JKK-˗?b6ym8 !LMM =zdi3Vwʔ).i毿Bqqeh6c oɺuit-Kuu5bbb,YYv؁˗/5Zl۶M'-""¬6Xڦ)))o((>!d@.]|uމڼ߿?l- ooo[0+Ν7nڠc͡~HÇ=_BK.utv`i)^Cga5k4MqFmcL Pa߾} ///9rr˗/Ǐ!JsN###ooϘǏ{nTTT@*HmBsѣG믿1bT*^zYLߙ6m̙ݻwo߾8v$ 6oތ'OE.]'`ȑHKKý{PZZ@"h}xbxxoX,Fvv6T*&LUV!55%%%Ÿt&OCcϞ= BZ z]vpRTn%%%@Q?~w_}PSS 6o߾sPPP}vƬԩSpwwG\\|}}c޽pqqAvv6\]]uVNӧ#-- ؾ}; ޽{쌜x<=={a߾}`jǎE˲ظq#x eVä??? 2pc sN-**Ҿ+8gϞzUm lذУG<}ϟ>`ӦMXdV+Eff&`ȑ9rE%''#&&* [nň#0x`xyyaZbUL899W\\ DHFxyyYD{ii)7|S'=##[ln7ǟD"ڵkQRRWW/ϸ~:!@n޼E555GDDZNa  [󑐐@ <_|quJE"?? Xp6uuubBAaĉHNNƑ#G0gho)77<!>>>:=fP444XDSK ^z!99))):!ka }BP֖ M͛71~x 8˗/Grr21tP&<ڵkq-TTThV\D8p":ˢe* {9-***Z=}չ*J`m>A 88!CtRcŘ4iN!,,L}!̟?2e ^xanmdmM=f 0V2 7nKt˖-Cjj*fϞ"|G1gL>qٴi4B$a֭ Ell,,XEFFŋX`f̘Xl6-Ǹqp5 ذa.\cb̙:3ĦL(|r|}}Yf;ki޼yĉ1vXmݻ7͛iӦioxPRR`DFFɓ1c+iӦ(((@@@<<<{~k׮:tY' eY?E1"##1yd|xIЧOHRt???9sF'oE``.֌tzQ'MDPՑB!AAAÇ#HF8K-7ovim} zɐ!CL&ӻt}444Tj466JWTR/&WSScP/ZS}Q[[L3:HGR)儦im6_"{}\ٮOOuu60D&LFy6̢NFC:___R:ˢ%ĿL&3(WO={FFw]Z&ϟ?78_cD/$$dgwinP,BFEEi0 S_~ӭ[7K3P@`֭[3 ŒqwwכݻkD3Y면-tj3p8pwwo&W_՛驳pP(Z3aKM1&.ѣG4'''Fώ= B!11Ѧ mj1;ϡƦih m1LBիpqi ŋJSZMݹsKuu5JU}hsΙ4y$ (7Gj~cPwwBPphj(REs8ZMjϷ/3 \VS4Msx<#Ka=X8;;hI42ֺ(JF#EGATr3 saiNNN~ϦRB0 Ӆ.EQB;Ԇ.y5SsZ+EQFB(b~yߎ7!DG`a!Q899J{MZi{Ea(k0ǮySSw/P(4}DZ Hh~вgc5Jei899}T*XgQB4xZvq4:Bhll\\\J%rF̙3?jVXvBAxfcL5rK JS޷ɻsJ*՚%zϘ z_1ڥ88l&ǜ @ vLBAQy7gw$'JNwܙY'5 YCi-TUn v,B GF>cc ~=X8Oc}~70߂⛩ _]~7^s_Erkfƅ?G؜9s,mn PCD0* L&]]vYTz=9d v!'5sO=??z RGz~MIj0[3Y"162%??Edjbj0Jid|||V^^^k[3*z0:E;G1!$<..+Bt:}E]຀i2̚5K<! Ұ†!!Dз;' BRCaC$8AzlQw N^+ w UPn> y(La@I%pࡹ|{0q`]1/ Ћ^j`e푉>a6.0f{#:˫ n "`@R,+|dE)0yƩ" B[.>Lq@MqP"c0銻Y# +6%7x ǢhK' s=W=w^xt;l_=<: sf|_5؛ӷ^yg|C|ߒ?wwڳ7‚ ^=7+5b*.[~?FNiXµHH}W߇7 GMFO {~Y_cوM¶/n<) tfxg}?g>2"Q )6l=0[gg(l1^ rی[4FLq ᱸ?å c漿fFkӞ P| 73_k$=C'cm]q+k Ljڟ7Pо SoE3L6M-R2*#61 &Kx脁p֖^k|ޣIx 0"&iQsIB\DD'j3õ?'8 xx.0ZQ@%4A0ъv7V|8k() o}PNi{~> wҖ?:e|xwcˆV}5%[Gk=^WD.}WDL £G@q? .G|mTta߶Mx n-sx n@|;s>tpVRJyI;ڿ$FXĴiS~\>CM1\2ې> C΀*r \6k"cS Ԁay2jp蝦7t?^W?hy:{7l&-]wC-^ FLEeaDǥaYYX7.cѯDepfa&+rʲP~b_PO1^n*>.YJ b ">yⓇ5Q N^K$8Az-AD N^K$8Az-AD N^L NUѣP粓$;o PMS|`iJmi7Q-[vwyL=ޮÀjPu:JSh;z#=-nBmk W?}jF8!'t;z7FZ551vʽxGԿ:wzM?^\ɤa#fy(>YŃЭTsǷ{놥%dy^v{9;;c̣鼌ű3Mܘ{p|SRﺆ $K>AVl)S.g0J5M+'8eYRJş;)~[xhmȨ+)4MAo}?=;c*4Ms2&U9rp8")e!PJmnʆ煓tec:2D)NJ:FUY$Z/85Uҥ@vjɛt~I*(Gc%:JBˀLxY[[{qfne%gaO8ۮl$PƘR+4LI)UFHrBg)01UUU͚1Q,ϡBdJ))**wȑ 4iҷ.Gc!nX$I%tNӥigQBH Ln.$)R*wGjժUOZ,'O^麲K䢔֩ZrF,]:6 @X -g7xSNMv8(((riqKLL,C$ %TzZMjl6sʕSǏ_ПbbIpϪweɊRJ RRJ]1qt:HnB Zk^GpYch\ ]4M!>J]f٭<ٍ͝~H_hw^0[fZ($ioGƘ&˲j]rx<:L`xi.~󒞒2aĈǺ>ФcLs:jdd?;;۷x~ε12ydyz.x5.oʌ.KB7nƍ5Qj΁nO m-ZtgWݻX{q_6*bBhp-? '/kk\iX^PO4%G`'Or.d!ADB@4}V?ũ@ 6@ !`N_INE6icjQaSbBMh8ߐBWpv3 f ^%q x]Ї\ӗ48?h }Ƿ?/'ŸP;S7}!}w"Vczh`x J蓮aɬ-?'rF$g' Mj\pPD gxp | BPD]0|HV9xr ))M n=sjh8!؄sM] $Xo?7sAE$D6'7AFUL,g>lg<_A `1=O Rt)?{?@&tk\ WN8#c4~].8 B] `9C>HFoRAH'6/9 GkdfJG* D἗1an i`{'1A J_Qt(%hjLx1A:21wybS`Jfuym`^@i8#hMLBʣ"؁=5cIo7A8>b05h{sE,F4GoAj o-/pFɭf.VMǻ|= +GL ѵBA6u λCL%zh |k4M+>#3zv B 눞  i(p^7\Cn,Hu9hZn JH ^.B/ pKpHWZ"-? Ѵ_I I;\KpMߔ8{_|]{WK7^g:k1 t n4<9u~f xӓ" ^ekh ԃϜ toh?5Op%n0M n `%x߭ nDp}DݳXTop3: ^α)/qj !\ >F_,gp!,^1kHp 7aB;6YTk<׏t}ìZ0X>3O: ݭ!gq%96$8K$տ:]^wzgzIw7VcWt 𱏁Ph/5LR>v<Sx r*B5odȸ|^y .@\{ :|D߂YAR~p UԂ/l0bu('60 d0bٚ 0 G $xM5^. v!(EM2P&=7$|n@ ]WzK*W;>l:\`+#KrZi"B/7lA|2)L~hxxNH)QUNU$>vt >Slo<_;*>} 5  ph`0`Enjc5j!&& (z(**‰'uV_,暚Ǎ:}QO!O8*@AxNG\:xŋ[neUWW|Mv;\F9M /7` %d2=m2\7x\9r~~ WMJ0;6t}C !I-&npvybk~b'NXogpVR鷭i-Mwn n8<~3wkSl6ۆ,=6d &n/I%""b]DDDd%hV0h4Vu)xBճ>U9vhZ| $oTTԗ6D0$I1L5{m6D-7L .)o"##_ Zf]e˖۷bjs~VZZʶm^|EvUW9&*,,)dw&Bp ְҕk( IFDDX,nɽj*o>zotJKK͛k͛牍uLj6ग़fצM4a5**I#vZyGw>o7T5yw:W"gd/XnLi맟~b=6p@dw~<?H?\.=(l͚5,++c"& xbD&3[U w;k.v.;_Wٶmz J)[|9slb;/u%LA2؜9s[o|P1L^i.M3&^b)?~gj*Y,;|=DgX,?/7_QTTX;ƄwbmΜ9`}Mee%4hbZ__ 4Lx1AC&EDDkjj}I.(fnWb(PRRRZhѹ.2o8 Sz Jik޾}jUNz-c3 wO)G)#g!$Zww}fBDZe8tB!M7nWk'B`ώư z;3}!vІ>QQQ\'IRʾW?; kJ'YtEjĨ`2YQQKOwLiCh7-**1V?]no9!D"b^jȲUW_=AOp^ɓ'["55(vÆ 3L~^?|Fbm9#DIt)SR[WZRR"oB_222JTaÆ)uuuv ]w2Ime!`E O|wM~/A(ͥ թׯ_?v!đr 6n8R.IRo7=zP]]}#٣>3fua߾}7Pt:pB;srroذ!n$IusssXB B!0'N6 Nl?~-Y[l ȵ(?>|-:>Æ r$I^0tmTBHw/)zBd0 BCUUՒz8{fBRRZ|>+ذayZ Ox999/x3f>رck.L6 V˜1cW_}]vaHIIܹsp3gL4 ՝FQL4Z;lذo7mڔp8dY}ffEQd2u6Db3X,|%rk↑y `T'cz7Nl1q4:v>\s5xeX^{-ƌ[n]tV^{ O?4-[W^yDc׮]q#-- ;wc=%KƝw ÁK.W\q6nYq7}Yo{V OG;xY+?u:~ߙ[r/ka*6䀏􃏘hz@ǬYpEꫯƁՊxv꫸1m41wuys,Xwuv;OF; (((+{O<5kvc!wIDATAFF-55~D!.HKK*,K`.]\X~ lD۟UW9mov J߿ˊ!+>99VGĂ///6mBuu5 >c;vǷr I/˕s|>ХK0|:t8 ~@ibڋUWYOv Tխ$]([WǾJ;} 2~x!ܥ^E>C='N ==iii8q .ފ4Ͻx¹1zh\ih1tP#G_y啉(SWj*M~^,ލq a&|9v9UHv nq/:%PWdh ?P10**Gvm̙33N'L&dYc :'N!C`0, "裏0w\\p,\+&XSI] M:k MY9$➮-q쭽86L6_N7AV뮍(,yj") EKvCu)H?羚B采aI_Əׯg.Rpm‘ }2?'}QF, o,p8"tf ԅ>C0c؋!&/;O{e»ԼV0ƾ ܪŋXkp*ɓo.\6**1JjBsJnÇ4i`4 WA=xI4U'&6>Vw_WFڼ2}pBђ8rzG8 l`A6P[Rp}u`0%۰o;QcV^Q˧Uk9&oEE)p]TڵD7c}c-s{ Λ0aQQQ?m޼Mſ5NJ***r -[te݌Wo4H/E?6tO=7O4C WR1<؇ !ƢBx9@qI_FXK%#F2݀/LmH42*l5`Sas T",Ux38AtXMH[N { +[,~Xd6mG%4L{6mڤҕ[od#u-֢ ׳w <7CejҊ}J W @CLl H)3tFX߆:v>=W%v5fEAޔ,+wÖutT'8O{コ9Ms\tE(//7kO~?iӦ!^$f_|>9$xFJVBKAg7%\W| ͭ@2yT }.O^O/aˎFDnST ,֌oZn!k,% jrÐvQ=D4@Ui ,ɸ72d-//,IRLYYYt~~)B8O8u侓nlT; y@8 )d~[Uc܋wnj@/2=1@@{vU k[vJE)SeGRoUص!4,~dXJEG$IѲ,[oĐR"&H ܰEwf>r͋,:x.\$V$ b/MC+C2E2l?=GQH<>Jn0Dwy6^xV|9=-H6 OnE/2wi= ZÃk`1'q䰮MIMF㱢"s\\ܙٳdff[/+WvƷgdo4ۺ<=u&r4 jinEa52)5^#ξDtÜ)|n!ª٤[>4N?\kaIzj39S7.I4w-xbccΝ; 1#c\]]m\hx" U`ZX;_pVlw1NҐ-^fw~+Qf?2 >BeG&]crИ6y鬆6*!fwq%"zYVմw^z:IjfR Fsm)W>aَejk{PNp'N8j6}c:rS-lp|Ά L']1Vy#C QZ gXnEB>|f RJRrb{xkNs|۾fn {I:Win<j#YfBtq 2IBTI$hټTGFkx"kw/7P;qAv nd\\84˅*bZ1NS=X,ݝtH ucͶ% z 쬡g3VN4IÄvZ{t:Re1uU ueN?yãeR  n_'ZOޣV1Vi:X:5l)8}_:1!L7NTSc ~)Ǝ[Bq0ƜzG)U,*{7ehj@秤z½^olNNNӖ.]!t~?MTPJ1 У)e+heB1 LKKsIFR<Z^2;z1VXX"),1Bw{ܽG~1_v:q1!$b3Crᮻ233'%%1vRD)-zF$Q n|!#d6C}^n&.111VPU<:3 -,YU'q"4 T/Z'|UV!C&$$cZZI\b 1($٬S]tkv[9ٜ8McU(&;vpv̞=fgg2 %NZL4ͥ뽑JZJ>h^Qn>Z "iNBTUm WiVRR8CaԨQ,##())i?2Y+c߿Oԓ}2Zߙ?`clAE:ƘWOP~:4 ٘1cRRRvkvRB)-Pzk),_/G.ej%O(DN'>V[ͼ*fu:(Xzz^NjVzƍF۷LsjII B1\.ty9s&߿cRJȲ|\QJUUo[$>|xA||X1c$IbUU+%Ix0Ga:NcNEQz}m||3 V͑#G/t.3еk"55dffAP(J_}=p e8Ӊ)ShŞ1c|G)=? v={L봶4099@ińRX$IHT <a-vORJCN;)~jz;))ozt ׮]+Ƿ71Ey<x'bX~h4/3*=۶m{|Q=Xvk֬y󴈈$ITiZaQQ%%%V+HkjjȱcLj$I_~u '㏃TJ9 TU*匱355/0ȬYG'ICR111,ڑ#GM6'~j.w:}]̜9raaڵXl~zIHH8tDU*)U$41VUTT߱cF'FcKuΝ;h_}*LNN>iZ!!1Vݒ$󍯫3 w $IjBHi*cZMjeYv~f\Rt zQQQS$Iz1f;w.~Gx__YY-[믿f6m۷o'IIIM&S5c@c @!1V۬/`0x˽~h4Nz3f+ns^1,Ym޼)))eu:IX1x[eXINN >3b') 84ML&oyy_AAzL'~VVV(ɆNӉ,D!,, ǏgGEYYH||h4ֆ$&& ZMjITC)mHfՔRci'22?p@ŋՄa-6ͦx@+ij˅իW>s)66qr+Ot('TZz3""[o~am۶4јi1cQI~UUܔR!ħ('33K/EW7Q 111S(c|>ߠ4L1UeY1X,.OZnnBHCcI䤔(.I\~ ~JiӦ=[QQWVV5l06i$iԨQCtt4!MݕTUűcP\\B|oe{!qqqR%x}YxRZI 䪪: !իW{cp 'OeY6 cLSUUaiA>٬/: QKp/;΁F1SDX!$\$+TzT4UEH%x'j$+IK4i^EQ,{5Mn^?S-TEQMVU5p^r$E!B$l6l6&ɧkcccOZJiR%,˵a9)NMB1g5MSdYRJ^W1dRWXqփ >/C !$ 1faE1K$˲$IO01VG)uȲh(Uj$ɥ鼔RiQFyEKc\|񄁯`&!ֈ114MhXX_$,fYEFF_Ζjcdƌ^7j1"$I3l`:BRFQc$I c̥Ge?!ݐԚ*UU'`]  cE~,{~,٪( 5 .5 A4^t:%Y, TUPHcfS|>=R e"cL