diff --git a/CHANGES b/CHANGES old mode 100755 new mode 100644 index 35753b4..24d5bfb --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,18 @@ +Changes to proxytunnel 1.12.3 -- Fri Mar 7 23:04:25 CET 2025 + +- PR #83 from https://github.com/tofurky to avoid printing unterminated string + in readline(). +- PR #86 from https://github.com/e9hack to fix and improve ntlm authentication. +- PR #89 from https://github.com/njbraun to increase MAX_HEADER_SIZE to 4k. +- From Sven Geuer, https://github.com/68420948 + - Chmode 755 to 644 for file CHANGES. + - Drop obsolete entry about SSL proxy support from file TODO. + +Changes to proxytunnel 1.12.2 -- Mon Mar 25 14:50:38 CET 2024 + +- PRs #79 and #80 from https://github.com/hoilc implementing github action to + build windows binary. + Changes to proxytunnel 1.12.1 -- Tue Feb 6 17:36:38 CET 2024 [ Sven Geuer, https://github.com/68420948 ] diff --git a/INSTALL.md b/INSTALL.md index 9e2e7fa..a7db3fe 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -10,6 +10,55 @@ to build simply run `make` and optionally `make install`. If you manually want to install, copy proxytunnel to /usr/local/bin and optionally the manual-page from the debian-subdirectory to your manpath +# Nix Flakes + +> NOTE: The Nix Flake installation currently only supports the `x86_64-linux` platform, and has not been tested on other architectures. + +A simple Nix Flake is included to allow for use via flake inputs. To create a temporary Nix Shell with access to the `proxytunnel` binary, you can run the command: +```console +nix develop github:proxytunnel/proxytunnel +``` +If you instead want to include it as a flake input, the following `flake.nix` shows how to do so: +```nix +{ + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; + + # Add proxytunnel as an input + proxytunnel.url = "github:proxytunnel/proxytunnel"; + }; + + outputs = { + nixpkgs, + proxytunnel, + ... + }: let + system = "x86_64-linux"; + pkgs = import nixpkgs { + system = "x86_64-linux"; + overlays = [ + # Add proxytunnel's default features to your nixpkgs + proxytunnel = proxytunnel.overlays.default; + + # For a full list of override options, see `nix/proxytunnel.nix` + ]; + }; + in { + devShells.${system}.default = pkgs.mkShell { + packages = [ + # Make the `proxytunnel` binary available in a Nix Shell + # The above overlay adds it to nixpkgs. Without the overlay, use proxytunnel.packages.${system}.default + pkgs.proxytunnel + + # And include any other packages as desired... + pkgs.gcc + # ... + ]; + }; + }; +} +``` + # msys2 To install msys2 with [chocolatey](https://chocolatey.org/install): diff --git a/Makefile b/Makefile index 1da0ce7..a925a89 100644 --- a/Makefile +++ b/Makefile @@ -14,8 +14,15 @@ OPTFLAGS += -DHAVE_GETOPT_LONG # Comment if you don't have/want ssl OPTFLAGS += -DUSE_SSL -# Most systems +# MSYS +# The current version of gcc from MSYS defines __MSYS__ and __CYGWIN__. +# To avoid to change the code, simply define CYGWIN additionally. +ifneq ($(filter $(MSYSTEM),MSYS MINGW32 MINGW64 UCRT64),) +CFLAGS += -DCYGWIN +else +# Most systems, MSYS definitely not OPTFLAGS += -DSETPROCTITLE -DSPT_TYPE=2 +endif # System dependant blocks... if your system is listed below, uncomment # the relevant lines @@ -59,7 +66,6 @@ mandir = $(datadir)/man OBJ = proxytunnel.o \ base64.o \ strzcat.o \ - setproctitle.o \ io.o \ http.o \ basicauth.o \ @@ -70,6 +76,10 @@ OBJ = proxytunnel.o \ ntlm.o \ ptstream.o +ifneq (,$(findstring -DSETPROCTITLE,$(OPTFLAGS))) +OBJ += setproctitle.o +endif + UNAME = $(shell uname) ifneq ($(UNAME),Darwin) OBJ += strlcpy.o \ diff --git a/TODO b/TODO index 45c19e4..8ac9281 100644 --- a/TODO +++ b/TODO @@ -7,11 +7,6 @@ or: proxytunnel -p username:password@local-proxy:port -r username:password@remote-proxy:port -d %h:%p -### SSL proxy support -- Starting with Apache 2.4 using CONNECT over SSL is supported !! - See: http://issues.apache.org/bugzilla/show_bug.cgi?id=29744 - - ### Code cleanup - Find some hardcore C experts to help us improve the code quality diff --git a/buildwin.sh b/buildwin.sh index 52d8b59..5e1165c 100644 --- a/buildwin.sh +++ b/buildwin.sh @@ -4,13 +4,13 @@ echo "Build docs..." make -C docs echo "Build proxytunnel..." -make -f Makefile.ssl11 - -echo "Copy msys/openssl dll to build dir..." -cp /usr/bin/msys-2.0.dll /usr/bin/msys-crypto-1.1.dll /usr/bin/msys-ssl-1.1.dll /usr/bin/msys-z.dll . +make -f Makefile +strip -s proxytunnel.exe echo "Generate proxytunnel.zip with docs, exe and msys/openssl dll..." -zip proxytunnel.zip proxytunnel.exe *.dll docs/proxytunnel.1 docs/proxytunnel.1.html docs/proxytunnel-paper.html +zip proxytunnel.zip proxytunnel.exe docs/proxytunnel.1 docs/proxytunnel.1.html docs/proxytunnel-paper.html +DLLS="$(ldd proxytunnel.exe | grep msys.*\.dll | awk '{print $3}' | xargs) /usr/lib/ossl-modules/legacy.dll" +zip proxytunnel.zip -j $DLLS if [ ! -z "${TRAVIS_TAG}" ]; then echo "Deploy proxytunnel.zip to github release tag:${TRAVIS_TAG}..." diff --git a/cmdline.c b/cmdline.c index 36aafae..7e5db30 100644 --- a/cmdline.c +++ b/cmdline.c @@ -596,7 +596,7 @@ int cmdline_parser( int argc, char * const *argv, struct gengetopt_args_info *ar } } - if (! args_info->proxy_given && ! args_info->dest_given ) { + if (! args_info->proxy_given || ! args_info->dest_given ) { clear_args (); // cmdline_parser_print_help (); message( "No proxy or destination given, exiting\nUse '--help' flag for usage info\n" ); diff --git a/cmdline.h b/cmdline.h index 18b77e9..93cf460 100644 --- a/cmdline.h +++ b/cmdline.h @@ -23,7 +23,7 @@ #ifndef _cmdline_h #define _cmdline_h -#define MAX_HEADER_SIZE 1024 +#define MAX_HEADER_SIZE 4096 struct gengetopt_args_info { char *user_arg; /* Username to send to HTTPS proxy for auth. */ diff --git a/config.h b/config.h index 80914fd..f73e2ed 100644 --- a/config.h +++ b/config.h @@ -17,9 +17,9 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#define VERSION "1.12.1" -#define VERSION_YEAR "2024" -#define VERSION_DATE "2024-02-06" +#define VERSION "1.12.3" +#define VERSION_YEAR "2025" +#define VERSION_DATE "2025-03-07" #define PACKAGE "proxytunnel" #define PURPOSE "Build generic tunnels through HTTPS proxies" #define AUTHORS "Jos Visser (Muppet) , Mark Janssen (Maniac) " diff --git a/docs/proxytunnel.1.adoc b/docs/proxytunnel.1.adoc index e04b4ac..0e8e6b5 100644 --- a/docs/proxytunnel.1.adoc +++ b/docs/proxytunnel.1.adoc @@ -6,7 +6,7 @@ proxytunnel - program to tunnel a connection through a standard HTTPS proxy == SYNOPSIS -*proxytunnel* [_OPTION…_] [_host_++:++_port_] +*proxytunnel* [_OPTION…_] == DESCRIPTION @@ -32,15 +32,16 @@ also be used for other proxy-traversing purposes like proxy bouncing. [2001:db8::123:4567:89ab:cdef%eth0]:22 *-p*, *--proxy*=_host_++:++_port_:: - Use _host_ and _port_ as the local proxy to connect to, if not specified - the *HTTP_PROXY* environment variable, if set, will be used instead. + Use _host_ and _port_ as the local (primary) proxy to connect to, if not + specified the *HTTP_PROXY* environment variable, if set, will be used + instead. This option or the environment variable are mandatory. *-r*, *--remproxy*=_host_++:++_port_:: Use _host_ and _port_ as the remote (secondary) proxy to connect to. *-d*, *--dest*=_host_++:++_port_:: - Use _host_ and _port_ as the destination for the tunnel, you can also - specify them as the argument to the proxytunnel command. + Use _host_ and _port_ as the destination for the tunnel. This is a + mandatory option. *-e*, *--encrypt*:: SSL encrypt data between local proxy and destination. @@ -150,13 +151,6 @@ also be used for other proxy-traversing purposes like proxy bouncing. Print version and exit. -== ARGUMENTS -_host_++:++_port_ is the destination hostname and port number combination. - -NOTE: Specifying the destination as arguments is exactly the same as -specifying them using the *-d* or *--dest* option. - - == USAGE Depending on your situation you might want to do any of the following things: diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..d28337e --- /dev/null +++ b/flake.lock @@ -0,0 +1,61 @@ +{ + "nodes": { + "flake-parts": { + "inputs": { + "nixpkgs-lib": "nixpkgs-lib" + }, + "locked": { + "lastModified": 1743550720, + "narHash": "sha256-hIshGgKZCgWh6AYJpJmRgFdR3WUbkY04o82X05xqQiY=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "c621e8422220273271f52058f618c94e405bb0f5", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "flake-parts", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1743583204, + "narHash": "sha256-F7n4+KOIfWrwoQjXrL2wD9RhFYLs2/GGe/MQY1sSdlE=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "2c8d3f48d33929642c1c12cd243df4cc7d2ce434", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-lib": { + "locked": { + "lastModified": 1743296961, + "narHash": "sha256-b1EdN3cULCqtorQ4QeWgLMrd5ZGOjLSLemfa00heasc=", + "owner": "nix-community", + "repo": "nixpkgs.lib", + "rev": "e4822aea2a6d1cdd36653c134cacfd64c97ff4fa", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "nixpkgs.lib", + "type": "github" + } + }, + "root": { + "inputs": { + "flake-parts": "flake-parts", + "nixpkgs": "nixpkgs" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..eb73249 --- /dev/null +++ b/flake.nix @@ -0,0 +1,33 @@ +{ + description = "Basic flake that provides proxytunnel as a package or as a binary in a nix shell"; + + inputs = { + flake-parts.url = "github:hercules-ci/flake-parts"; + nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; + }; + + outputs = inputs @ {flake-parts, ...}: + flake-parts.lib.mkFlake {inherit inputs;} { + # TODO: Add support for more systems once checked. + systems = ["x86_64-linux"]; + + imports = [inputs.flake-parts.flakeModules.easyOverlay]; + + perSystem = { + config, + pkgs, + ... + }: { + overlayAttrs = { + inherit (config.packages) proxytunnel; + }; + + packages.proxytunnel = pkgs.callPackage ./nix/proxytunnel.nix {}; + packages.default = config.packages.proxytunnel; + + devShells.default = pkgs.mkShell { + packages = [config.packages.default]; + }; + }; + }; +} diff --git a/http.c b/http.c index a4e020c..12e1956 100644 --- a/http.c +++ b/http.c @@ -37,17 +37,16 @@ * header */ void analyze_HTTP(PTSTREAM *pts) { - char *p = strtok( buf, " "); + char *p; /* Strip html error pages for faulty proxies (Stephane Engel ) */ - while (strncmp( p, "HTTP/", 5) != 0 ) { - if ( readline(pts) ) { - p = strtok( buf, " "); - } else { + do { + if (readline(pts) <= 0) { message( "analyze_HTTP: readline failed: Connection closed by remote host\n" ); exit(2); } - } + p = strtok( buf, " \t"); + } while (strncmp( p, "HTTP/", 5) != 0 ); if (strcmp( p, "HTTP/1.0" ) != 0 && strcmp( p, "HTTP/1.1" ) != 0) { message( "Unsupported HTTP version number %s\n", p ); @@ -117,6 +116,7 @@ void proxy_protocol(PTSTREAM *pts) { if (args_info.ntlm_flag) { if (ntlm_challenge == 1) { build_type3_response(); + ntlm_challenge = 2; strzcat( buf, "Proxy-Authorization: NTLM %s\r\n", ntlm_type3_buf ); } else if (ntlm_challenge == 0) { strzcat( buf, "Proxy-Authorization: NTLM %s\r\n", ntlm_type1_buf ); @@ -157,7 +157,7 @@ void proxy_protocol(PTSTREAM *pts) { /* Read the first line of the response and analyze it */ analyze_HTTP(pts); - if (args_info.remproxy_given ) { + if (ntlm_challenge < 3 && args_info.remproxy_given ) { /* Clean buffer for next analysis */ while ( strcmp( buf, "\r\n" ) != 0 ) readline(pts); @@ -209,8 +209,8 @@ void proxy_protocol(PTSTREAM *pts) { * Then, repeat reading lines of the responses until a blank line * (which signifies the end of the response) is encountered. */ - if (ntlm_challenge == 1) { - ntlm_challenge = 2; + if (ntlm_challenge == 2) { + ntlm_challenge = 3; } else { do { readline(pts); diff --git a/io.c b/io.c index e8df31a..56d516e 100644 --- a/io.c +++ b/io.c @@ -57,7 +57,7 @@ int readline(PTSTREAM *pts) { if( args_info.verbose_flag ) { /* Copy line of data into dstr without trailing newline */ - char *dstr = malloc(strlen(buf) + 1); + char *dstr = calloc(1, strlen(buf) + 1); strncpy( dstr, buf, strlen(buf)); if (strcmp(dstr, "")) message( " <- %s\n", dstr ); diff --git a/nix/proxytunnel.nix b/nix/proxytunnel.nix new file mode 100644 index 0000000..ad3a010 --- /dev/null +++ b/nix/proxytunnel.nix @@ -0,0 +1,31 @@ +{ + gnu-system ? true, + set-proc-title ? true, + pkgs, +}: let + optflags = "-DUSE_SSL ${ + if gnu-system + then "-DHAVE_GETOPT_LONG" + else "" + } ${ + if set-proc-title + then "-DSETPROCTITLE -DSPT_TYPE=2" + else "" + }"; +in + pkgs.stdenv.mkDerivation { + pname = "proxytunnel"; + version = "1.12.3"; + src = ./..; + + buildInputs = [pkgs.openssl]; + + buildPhase = '' + make OPTFLAGS="${optflags}" + ''; + + installPhase = '' + mkdir -p $out/bin + cp ./proxytunnel $out/bin + ''; + } diff --git a/ntlm.c b/ntlm.c index 54761f5..5159202 100644 --- a/ntlm.c +++ b/ntlm.c @@ -29,6 +29,9 @@ #include #include #if OPENSSL_VERSION_NUMBER >= 0x30000000L + #ifdef CYGWIN + #include + #endif #include #include #else @@ -71,8 +74,55 @@ unsigned char lm2digest[LM2_DIGEST_LEN]; void init_ntlm() { #if OPENSSL_VERSION_NUMBER >= 0x30000000L - OSSL_PROVIDER_load(NULL, "default"); - OSSL_PROVIDER_load(NULL, "legacy"); + OSSL_PROVIDER *provider; + provider = OSSL_PROVIDER_load(NULL, "default"); + if (!provider) { + my_perror("Loading default provider failed"); + exit(1); + } + provider = OSSL_PROVIDER_load(NULL, "legacy"); +#ifdef CYGWIN + if (!provider) { + // available at msys and git for windows + // the msys version has an additional dependency on libcrypto-3-x64.dll + provider = OSSL_PROVIDER_load(NULL, "/mingw64/lib/ossl-modules/legacy.dll"); + } + if (!provider) { + // available at msys (without dependency on libcrypto-3-x64.dll) + provider = OSSL_PROVIDER_load(NULL, "/usr/lib/ossl-modules/legacy.dll"); + } + if (!provider) { + // default installation path for additional tools + provider = OSSL_PROVIDER_load(NULL, "/usr/local/bin/legacy.dll"); + } + if (!provider) { + // directory of proxytunnel itself + const char *p = strrchr(program_name, '/'); + if (p) { + const int len = p - program_name; + char *tmp = (char*)alloca(len + sizeof("/legacy.dll")); + memcpy(tmp, program_name, len); + strcpy(tmp + len, "/legacy.dll"); + provider = OSSL_PROVIDER_load(NULL, tmp); + } + } + if (!provider) { + // current working directory + char *cwd = getcwd(NULL, 0); + if (cwd) { + const int len = strlen(cwd); + char *tmp = (char*)alloca(len + sizeof("/legacy.dll")); + memcpy(tmp, cwd, len); + free(cwd); + strcpy(tmp + len, "/legacy.dll"); + provider = OSSL_PROVIDER_load(NULL, tmp); + } + } +#endif + if (!provider) { + my_perror("Loading legacy provider failed"); + exit(1); + } md4alg = EVP_md4(); md5alg = EVP_md5(); mdctx = EVP_MD_CTX_new(); diff --git a/proxytunnel.h b/proxytunnel.h index 74547f8..88a5471 100644 --- a/proxytunnel.h +++ b/proxytunnel.h @@ -30,8 +30,10 @@ void analyze_HTTP(PTSTREAM *pts); void proxy_protocol(PTSTREAM *pts); void closeall(); void do_daemon(); +#ifdef SETPROCTITLE void initsetproctitle(int argc, char *argv[]); void setproctitle(const char *fmt, ...); +#endif #if defined(__APPLE__) && defined(__MACH__) /* Don't include strlcat and strlcpy since they are provided as macros on OSX */