From: Adam Gołębiowski Date: Sun, 23 Sep 2018 14:19:07 +0000 (+0200) Subject: - updated to 1.9.1 X-Git-Tag: auto/th/proxytunnel-1.9.1-0.1 X-Git-Url: http://git.pld-linux.org/?p=packages%2Fproxytunnel.git;a=commitdiff_plain;h=2a2b5a0 - updated to 1.9.1 - switch to github - git fixes from upstream - warning fixes when building against openssl-1.1 --- diff --git a/proxytunnel-git-openssl-warnings.patch b/proxytunnel-git-openssl-warnings.patch new file mode 100644 index 0000000..9ac1112 --- /dev/null +++ b/proxytunnel-git-openssl-warnings.patch @@ -0,0 +1,28 @@ +commit b8c15860719a3ca182b1e7689df231edc68899f5 +Author: Adam Gołębiowski +Date: Sun Sep 23 16:11:21 2018 +0200 + + ptstream.c: fix openssl-1.1 warnings + +diff --git a/ptstream.c b/ptstream.c +index d1c5f44..bf3995f 100644 +--- a/ptstream.c ++++ b/ptstream.c +@@ -208,7 +208,7 @@ int check_cert_names(X509 *cert, char *peer_host) { + for (i = 0; i < san_count; i++) { + gn = sk_GENERAL_NAME_value(gen_names, i); + if (gn->type == GEN_DNS && !(peer_host_is_ipv4 || peer_host_is_ipv6)) { +- if (check_cert_valid_host((char*)ASN1_STRING_data(gn->d.ia5), peer_host)) { ++ if (check_cert_valid_host((char*)ASN1_STRING_get0_data(gn->d.ia5), peer_host)) { + return 1; + } + } else if (gn->type == GEN_IPADD) { +@@ -254,7 +254,7 @@ int stream_enable_ssl(PTSTREAM *pts, const char *proxy_arg) { + /* Initialise the connection */ + SSLeay_add_ssl_algorithms(); + if (args_info.enforcetls1_flag) { +- meth = TLSv1_client_method(); ++ meth = TLS_client_method(); + } else { + meth = SSLv23_client_method(); + } diff --git a/proxytunnel-git.patch b/proxytunnel-git.patch new file mode 100644 index 0000000..9ae9de1 --- /dev/null +++ b/proxytunnel-git.patch @@ -0,0 +1,1085 @@ +diff --git a/.gitignore b/.gitignore +new file mode 100644 +index 0000000..c15583a +--- /dev/null ++++ b/.gitignore +@@ -0,0 +1,4 @@ ++*.o ++*.exec ++proxytunnel.exe ++proxytunnel +diff --git a/.travis.yml b/.travis.yml +new file mode 100644 +index 0000000..1348562 +--- /dev/null ++++ b/.travis.yml +@@ -0,0 +1,14 @@ ++language: c ++compiler: ++ - clang ++ - gcc ++addons: ++ apt: ++ packages: ++ - asciidoc ++ - xmlto ++install: ++ - make clean ++script: ++ - make ++ - make docs +\ No newline at end of file +diff --git a/Makefile b/Makefile +index 006b5b1..57328e8 100644 +--- a/Makefile ++++ b/Makefile +@@ -5,17 +5,9 @@ + name = proxytunnel + version = $(shell awk 'BEGIN { FS="\"" } /^\#define VERSION / { print $$2 }' config.h) + +-ifneq ($(wildcard .svn),) +-revision = $(shell svnversion | awk 'BEGIN { RS=":" } { next } END { print $$1 }') +-else +-revision = $(shell echo '$$Revision$$' | sed -e 's/\$$Revision: \([0-9]\+\) \$$$$/\1/') +-endif +- + CC ?= cc + CFLAGS ?= -Wall -O2 -ggdb + +-OPTFLAGS = -DREVISION=\"$(revision)\" +- + # Comment on non-gnu systems + OPTFLAGS += -DHAVE_GETOPT_LONG + +@@ -46,9 +38,9 @@ OPTFLAGS += -DSO_REUSEPORT + + # END system dependant block + +-SSL_LIBS := $(shell pkg-config --libs libssl 2>/dev/null) +-ifeq ($(SSL_LIBS),) + SSL_LIBS := $(shell pkg-config --libs openssl 2>/dev/null) ++ifeq ($(SSL_LIBS),) ++SSL_LIBS := $(shell pkg-config --libs libssl 2>/dev/null) + endif + ifeq ($(SSL_LIBS),) + SSL_LIBS := -lssl -lcrypto +@@ -63,8 +55,6 @@ mandir = $(datadir)/man + # Remove strlcpy/strlcat on (open)bsd/darwin systems + OBJ = proxytunnel.o \ + base64.o \ +- strlcpy.o \ +- strlcat.o \ + strzcat.o \ + setproctitle.o \ + io.o \ +@@ -76,9 +66,15 @@ OBJ = proxytunnel.o \ + ntlm.o \ + ptstream.o + ++UNAME = $(shell uname) ++ifneq ($(UNAME),Darwin) ++OBJ += strlcpy.o \ ++ strlcat.o ++endif ++ + .PHONY: all clean docs install + +-all: proxytunnel docs ++all: proxytunnel + + docs: + $(MAKE) -C docs +@@ -91,7 +87,8 @@ clean: + $(MAKE) -C docs clean + + install: +- install -Dp -m0755 $(name) $(DESTDIR)$(bindir)/$(name) ++ install -d $(DESTDIR)$(bindir) ++ install -p -m555 $(name) $(DESTDIR)$(bindir) + $(MAKE) -C docs install + + .c.o: +diff --git a/README b/README +index 1c30836..bdb7fe3 100644 +--- a/README ++++ b/README +@@ -3,8 +3,6 @@ proxytunnel + ----------- + + Author: Jos Visser , Mark Janssen +-Date: Mon Mar 3 22:49:43 CET 2008 +-Version: 1.9.0 + + Hi all, + +@@ -22,27 +20,32 @@ Proxytunnel is very easy to use, when running proxytunnel with the help + option it specifies it's command-line options. + + $ ./proxytunnel --help +-proxytunnel 1.9.0 (rev 224) Copyright 2001-2008 Proxytunnel Project ++proxytunnel 1.9.9 Copyright 2001-2018 Proxytunnel Project + Usage: proxytunnel [OPTIONS]... +-Build generic tunnels trough HTTPS proxy's, supports HTTP authorization ++Build generic tunnels through HTTPS proxies using HTTP authentication + + Standard options: +- -i, --inetd Run from inetd (default=off) ++ -i, --inetd Run from inetd (default: off) + -a, --standalone=INT Run as standalone daemon on specified port + -p, --proxy=STRING Local proxy host:port combination + -r, --remproxy=STRING Remote proxy host:port combination (using 2 proxies) + -d, --dest=STRING Destination host:port combination + -e, --encrypt SSL encrypt data between local proxy and destination + -E, --encrypt-proxy SSL encrypt data between client and local proxy +- -X, --encrypt-remproxy Encrypt between 1st and 2nd proxy using SSL ++ -X, --encrypt-remproxy SSL encrypt data between local and remote proxy ++ -L (legacy) enforce TLSv1 connection ++ -T, --no-ssl3 Do not connect using SSLv3 + + Additional options for specific features: ++ -z, --no-check-certficate Don't verify server SSL certificate ++ -C, --cacert=STRING Path to trusted CA certificate or directory + -F, --passfile=STRING File with credentials for proxy authentication + -P, --proxyauth=STRING Proxy auth credentials user:pass combination +- -R, --remproxyauth=STRING Remote proxy auth credentials user:pass combination ++ -R, --remproxyauth=STRING Remote proxy auth credentials user:pass combination + -N, --ntlm Use NTLM based authentication + -t, --domain=STRING NTLM domain (default: autodetect) + -H, --header=STRING Add additional HTTP headers to send to proxy ++ -o STRING send custom Host Header + -x, --proctitle=STRING Use a different process title + + Miscellaneous options: +@@ -51,7 +54,6 @@ Miscellaneous options: + -h, --help Print help and exit + -V, --version Print version and exit + +- + To use this program with OpenSSH to connect to a host somewhere, create + a $HOME/.ssh/config file with the following content: + +diff --git a/TODO b/TODO +index 4339a0f..45c19e4 100644 +--- a/TODO ++++ b/TODO +@@ -8,14 +8,11 @@ + + + ### SSL proxy support +-- Lobby for the Apache project to allow CONNECT over SSL (much like GET, +- PUT and HEAD is supported over SSL) +- see: http://issues.apache.org/bugzilla/show_bug.cgi?id=29744 ++- Starting with Apache 2.4 using CONNECT over SSL is supported !! ++ See: http://issues.apache.org/bugzilla/show_bug.cgi?id=29744 + + + ### Code cleanup +-- Fix permissions in subversion tree (some files are wrongly executable) +- + - Find some hardcore C experts to help us improve the code quality + + - Improve the error output, make it consistent throughout the program +diff --git a/cmdline.c b/cmdline.c +index 15ebe98..e1ee9b0 100644 +--- a/cmdline.c ++++ b/cmdline.c +@@ -38,14 +38,14 @@ extern char * optarg; + static char *getCredentialsFromFile( const char* filename, char **user, char **pass, char **rem_user, char **rem_pass); + + void cmdline_parser_print_version (void) { +- printf ("%s %s (rev %s) Copyright 2001-2008 Proxytunnel Project\n", PACKAGE, VERSION, REVISION); ++ printf ("%s %s Copyright 2001-2018 Proxytunnel Project\n", PACKAGE, VERSION); + } + + void cmdline_parser_print_help (void) { + cmdline_parser_print_version (); + printf( + "Usage: %s [OPTIONS]...\n" +-"Build generic tunnels trough HTTPS proxies using HTTP authentication\n" ++"Build generic tunnels through HTTPS proxies using HTTP authentication\n" + "\n" + "Standard options:\n" + // FIXME: " -c, --config=FILE Read config options from file\n" +@@ -59,9 +59,15 @@ void cmdline_parser_print_help (void) { + " -e, --encrypt SSL encrypt data between local proxy and destination\n" + " -E, --encrypt-proxy SSL encrypt data between client and local proxy\n" + " -X, --encrypt-remproxy SSL encrypt data between local and remote proxy\n" ++" -L (legacy) enforce TLSv1 connection\n" ++" -T, --no-ssl3 Do not connect using SSLv3\n" + #endif + "\n" + "Additional options for specific features:\n" ++#ifdef USE_SSL ++" -z, --no-check-certficate Don't verify server SSL certificate\n" ++" -C, --cacert=STRING Path to trusted CA certificate or directory\n" ++#endif + " -F, --passfile=STRING File with credentials for proxy authentication\n" + " -P, --proxyauth=STRING Proxy auth credentials user:pass combination\n" + " -R, --remproxyauth=STRING Remote proxy auth credentials user:pass combination\n" +@@ -72,6 +78,7 @@ void cmdline_parser_print_help (void) { + " -N, --ntlm Use NTLM based authentication\n" + " -t, --domain=STRING NTLM domain (default: autodetect)\n" + " -H, --header=STRING Add additional HTTP headers to send to proxy\n" ++" -o STRING send custom Host Header\n" + #ifdef SETPROCTITLE + " -x, --proctitle=STRING Use a different process title\n" + #endif +@@ -132,6 +139,9 @@ int cmdline_parser( int argc, char * const *argv, struct gengetopt_args_info *ar + args_info->encryptproxy_given = 0; + args_info->encryptremproxy_given = 0; + args_info->proctitle_given = 0; ++ args_info->enforcetls1_given = 0; ++ args_info->host_given = 0; ++ args_info->cacert_given = 0; + + /* No... we can't make this a function... -- Maniac */ + #define clear_args() \ +@@ -156,8 +166,13 @@ int cmdline_parser( int argc, char * const *argv, struct gengetopt_args_info *ar + args_info->encrypt_flag = 0; \ + args_info->encryptproxy_flag = 0; \ + args_info->encryptremproxy_flag = 0; \ ++ args_info->no_ssl3_flag = 0; \ + args_info->proctitle_arg = NULL; \ +-} ++ args_info->enforcetls1_flag = 0; \ ++ args_info->host_arg = NULL; \ ++ args_info->no_check_cert_flag = 0; \ ++ args_info->cacert_arg = NULL; \ ++} + + clear_args(); + +@@ -189,6 +204,8 @@ int cmdline_parser( int argc, char * const *argv, struct gengetopt_args_info *ar + { "remproxy", 1, NULL, 'r' }, + { "remproxyauth", 1, NULL, 'R' }, + { "proctitle", 1, NULL, 'x' }, ++ { "host", 1, NULL, 'o' }, ++ { "tlsenforce", 1, NULL, 'L' }, + { "header", 1, NULL, 'H' }, + { "verbose", 0, NULL, 'v' }, + { "ntlm", 0, NULL, 'N' }, +@@ -198,12 +215,15 @@ int cmdline_parser( int argc, char * const *argv, struct gengetopt_args_info *ar + { "encrypt", 0, NULL, 'e' }, + { "encrypt-proxy", 0, NULL, 'E' }, + { "encrypt-remproxy",0,NULL, 'X' }, ++ { "no-ssl3", 0, NULL, 'T' }, ++ { "no-check-certificate",0,NULL,'z' }, ++ { "cacert", 1, NULL, 'C' }, + { NULL, 0, NULL, 0 } + }; + +- c = getopt_long (argc, argv, "hVia:u:s:t:F:p:P:r:R:d:H:x:nvNeEXq", long_options, &option_index); ++ c = getopt_long (argc, argv, "hVia:u:s:t:F:p:P:r:R:d:H:x:nvNeEXqLo:TzC:", long_options, &option_index); + #else +- c = getopt( argc, argv, "hVia:u:s:t:F:p:P:r:R:d:H:x:nvNeEXq" ); ++ c = getopt( argc, argv, "hVia:u:s:t:F:p:P:r:R:d:H:x:nvNeEXqLo:TzC:" ); + #endif + + if (c == -1) +@@ -262,6 +282,18 @@ int cmdline_parser( int argc, char * const *argv, struct gengetopt_args_info *ar + args_info->proctitle_arg = gengetopt_strdup (optarg); + break; + ++ case 'L': ++ args_info->enforcetls1_given = 1; ++ message("Enforcing TLSv1"); ++ args_info->enforcetls1_flag = 1; ++ break; ++ ++ case 'o': ++ args_info->host_given = 1; ++ message("Host-header override enabled\n"); ++ args_info->host_arg = gengetopt_strdup (optarg); ++ break; ++ + case 'u': /* Username to send to HTTPS proxy for authentication. */ + if (args_info->user_given) { + fprintf (stderr, "%s: `--user' (`-u'), `--proxyauth' (`-P') or `--passfile' (`-F') option given more than once\n", PACKAGE); +@@ -370,6 +402,11 @@ int cmdline_parser( int argc, char * const *argv, struct gengetopt_args_info *ar + message("SSL local to remote proxy enabled\n"); + break; + ++ case 'T': /* Turn off SSLv3 */ ++ args_info->no_ssl3_flag = !(args_info->no_ssl3_flag); ++ if( args_info->verbose_flag ) ++ message("SSLv3 disabled\n"); ++ break; + + case 'd': /* Destination host to built the tunnel to. */ + if (args_info->dest_given) { +@@ -403,6 +440,22 @@ int cmdline_parser( int argc, char * const *argv, struct gengetopt_args_info *ar + args_info->quiet_flag = !(args_info->quiet_flag); + break; + ++ case 'z': /* Don't verify server SSL certificate */ ++ args_info->no_check_cert_flag = 1; ++ if( args_info->verbose_flag ) ++ message("Server SSL certificate verification disabled\n"); ++ break; ++ ++ case 'C': /* Trusted CA certificate (or directory) for server SSL certificate verification */ ++ if (args_info->cacert_given) { ++ fprintf (stderr, "%s: `--cacert' (`-C') option given more than once\n", PACKAGE); ++ clear_args (); ++ exit(1); ++ } ++ args_info->cacert_given = 1; ++ args_info->cacert_arg = gengetopt_strdup (optarg); ++ break; ++ + case 0: /* Long option with no short option */ + + case '?': /* Invalid option. */ +@@ -461,10 +514,11 @@ int cmdline_parser( int argc, char * const *argv, struct gengetopt_args_info *ar + + if ( args_info->proxy_arg == NULL ) { + if ( ((tmp = getenv("http_proxy")) != NULL) || ((tmp = getenv("HTTP_PROXY")) != NULL) ) { +- int r; ++ //int r; + char * temp; + temp = malloc( 56+1 ); +- r = sscanf( tmp, "http://%56[^/]/", temp ); ++ sscanf( tmp, "http://%56[^/]/", temp ); ++ //r = sscanf( tmp, "http://%56[^/]/", temp ); + // message( "r = '%d'\ntemp = '%s'\n", r, temp); + + args_info->proxy_given = 1; +@@ -474,7 +528,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" ); +@@ -482,12 +536,23 @@ int cmdline_parser( int argc, char * const *argv, struct gengetopt_args_info *ar + } + + if (args_info->proxy_given ) { ++ char proxy_arg_fmt[32]; ++ size_t proxy_arg_len; + char * phost; + int pport; + +- phost = malloc( 50+1 ); +- +- r = sscanf( args_info->proxy_arg, "%50[^:]:%5u", phost, &pport ); ++ proxy_arg_len = strlen( args_info->proxy_arg ); ++ if ( (phost = malloc( proxy_arg_len + 1 )) == NULL ) { ++ message( "Out of memory\n" ); ++ exit(1); ++ } ++ snprintf( proxy_arg_fmt, sizeof(proxy_arg_fmt), "%%%zu[^:]:%%5u", proxy_arg_len - 1 ); ++ r = sscanf( args_info->proxy_arg, proxy_arg_fmt, phost, &pport ); ++ if ( r != 2 ) { ++ /* try bracket-enclosed IPv6 literal */ ++ snprintf( proxy_arg_fmt, sizeof(proxy_arg_fmt), "[%%%zu[^]]]:%%5u", proxy_arg_len - 1 ); ++ r = sscanf( args_info->proxy_arg, proxy_arg_fmt, phost, &pport ); ++ } + if ( r == 2 ) { + args_info->proxyhost_arg = phost; + args_info->proxyport_arg = pport; +diff --git a/cmdline.h b/cmdline.h +index 2eccab7..cd85191 100644 +--- a/cmdline.h ++++ b/cmdline.h +@@ -47,7 +47,12 @@ struct gengetopt_args_info { + int encrypt_flag; /* Turn on SSL encryption (default=off). */ + int encryptproxy_flag; /* Turn on client to proxy SSL encryption (def=off).*/ + int encryptremproxy_flag; /* Turn on local to remote proxy SSL encryption (def=off).*/ ++ int no_ssl3_flag; /* Turn off SSLv3 (default=on) */ + char *proctitle_arg; /* Override process title (default=off). */ ++ int enforcetls1_flag; /* Override default and enforce TLSv1 */ ++ char *host_arg; /* Optional Host Header */ ++ int no_check_cert_flag; /* Turn off server SSL certificate verification (default=on) */ ++ char *cacert_arg; /* Trusted CA certificate (or directory) for server SSL certificate verification */ + int help_given; /* Whether help was given. */ + int version_given; /* Whether version was given. */ + int user_given; /* Whether user was given. */ +@@ -71,6 +76,9 @@ struct gengetopt_args_info { + int encryptproxy_given; /* Whether encrypt was given */ + int encryptremproxy_given; /* Whether encrypt was given */ + int proctitle_given; /* Whether to override process title */ ++ int enforcetls1_given; /* Wheter to enforce TLSv1 */ ++ int host_given; /* Wheter we override the Host Header */ ++ int cacert_given; /* Whether cacert was given */ + }; + + int cmdline_parser( int argc, char * const *argv, struct gengetopt_args_info *args_info ); +diff --git a/config.h b/config.h +index 4e73de1..204ded5 100644 +--- a/config.h ++++ b/config.h +@@ -17,7 +17,7 @@ + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +-#define VERSION "1.9.0" ++#define VERSION "1.9.9" + #define PACKAGE "proxytunnel" + #define PURPOSE "Build generic tunnels through HTTPS proxies" + #define AUTHORS "Jos Visser (Muppet) , Mark Janssen (Maniac) " +diff --git a/contrib/proxytunnel.spec b/contrib/proxytunnel.spec +index 0c0493d..69cd62e 100644 +--- a/contrib/proxytunnel.spec ++++ b/contrib/proxytunnel.spec +@@ -47,7 +47,7 @@ proxy authentication. + + %files + %defattr(-, root, root, 0755) +-%doc CHANGES CREDITS INSTALL KNOWN_ISSUES LICENSE.txt README RELNOTES TODO docs/*.txt docs/*.html ++%doc CHANGES CREDITS INSTALL KNOWN_ISSUES LICENSE.txt README RELNOTES TODO docs/*.adoc docs/*.html + %doc %{_mandir}/man1/proxytunnel.1* + %{_bindir}/proxytunnel + +diff --git a/docs/Makefile b/docs/Makefile +index 09babbb..f313c38 100644 +--- a/docs/Makefile ++++ b/docs/Makefile +@@ -2,25 +2,26 @@ prefix = /usr/local + datadir = $(prefix)/share + mandir = $(datadir)/man + +-txttargets = $(shell echo *.txt) +-htmltargets = $(patsubst %.txt, %.html, $(txttargets)) ++adoctargets = $(shell echo *.adoc) ++htmltargets = $(patsubst %.adoc, %.html, $(adoctargets)) + + docs: proxytunnel.1 $(htmltargets) + + install: proxytunnel.1 +- install -Dp -m0644 proxytunnel.1 $(DESTDIR)$(mandir)/man1/proxytunnel.1 ++ install -d $(DESTDIR)$(mandir)/man1 ++ install -p proxytunnel.1 $(DESTDIR)$(mandir)/man1 + + clean: + rm -f proxytunnel.1 *.html *.xml + +-%.1.html: %.1.txt ++%.1.html: %.1.adoc + asciidoc -d manpage $< + + %.1: %.1.xml + xmlto man $< + +-%.html: %.txt ++%.html: %.adoc + asciidoc $< + +-%.1.xml: %.1.txt ++%.1.xml: %.1.adoc + asciidoc -b docbook -d manpage $< +diff --git a/docs/proxytunnel-paper.txt b/docs/proxytunnel-paper.adoc +similarity index 100% +rename from docs/proxytunnel-paper.txt +rename to docs/proxytunnel-paper.adoc +diff --git a/docs/proxytunnel.1.txt b/docs/proxytunnel.1.adoc +similarity index 90% +rename from docs/proxytunnel.1.txt +rename to docs/proxytunnel.1.adoc +index 03fa427..a884207 100644 +--- a/docs/proxytunnel.1.txt ++++ b/docs/proxytunnel.1.adoc +@@ -49,6 +49,20 @@ also be used for other proxy-traversing purposes like proxy bouncing. + + == ADDITIONAL OPTIONS + ++*-T*, *--no-ssl3*:: ++ Prevent the use of SSLv3 in encrypted connections (default: enabled) ++ ++*-z*, *--no-check-certificate*:: ++ Do not verify server SSL certificate when establishing an SSL connection. ++ By default, the server SSL certficate is verified and the target host name ++ is checked against the server certificate's subject alternative names if ++ any are present, or common name if there are no subject alternative names. ++ ++*-C*, *--cacert*=_filename/directory_:: ++ Specify a CA certificate file (or directory containing CA certificate(s)) ++ to trust when verifying a server SSL certificate. If a directory is provided, ++ it must be prepared with OpenSSL's c_rehash tool. (default: /etc/ssl/certs) ++ + *-F*, *--passfile*=_filename_:: + Use _filename_ for reading username and password for HTTPS proxy + authentication, the file uses the same format as .wgetrc and can be shared +diff --git a/http.c b/http.c +index 3b7f6b9..3b85418 100644 +--- a/http.c ++++ b/http.c +@@ -105,11 +105,11 @@ void proxy_protocol(PTSTREAM *pts) { + if (args_info.remproxy_given ) { + if( args_info.verbose_flag ) + message( "\nTunneling to %s (remote proxy)\n", args_info.remproxy_arg ); +- sprintf( buf, "CONNECT %s HTTP/1.1\r\nHost: %s\r\n", args_info.remproxy_arg, args_info.remproxy_arg ); ++ sprintf( buf, "CONNECT %s HTTP/1.1\r\nHost: %s\r\n", args_info.remproxy_arg, args_info.host_arg ? args_info.host_arg : args_info.remproxy_arg ); + } else { + if( args_info.verbose_flag ) + message( "\nTunneling to %s (destination)\n", args_info.dest_arg ); +- sprintf( buf, "CONNECT %s HTTP/1.1\r\nHost: %s\r\n", args_info.dest_arg, args_info.dest_arg ); ++ sprintf( buf, "CONNECT %s HTTP/1.1\r\nHost: %s\r\n", args_info.dest_arg, args_info.host_arg ? args_info.host_arg : args_info.proxyhost_arg ); + } + + if ( args_info.user_given && args_info.pass_given ) { +@@ -157,13 +157,13 @@ void proxy_protocol(PTSTREAM *pts) { + while ( strcmp( buf, "\r\n" ) != 0 ) + readline(pts); + +-/* If --encrypt-remproxy is specified, connect to the remote proxy using SSL */ +- if ( args_info.encryptremproxy_flag ) +- stream_enable_ssl(stunnel); ++ /* If --encrypt-remproxy is specified, connect to the remote proxy using SSL */ ++ if ( args_info.encryptremproxy_flag ) ++ stream_enable_ssl(stunnel, args_info.remproxy_arg); + + if( args_info.verbose_flag ) + message( "\nTunneling to %s (destination)\n", args_info.dest_arg ); +- sprintf( buf, "CONNECT %s HTTP/1.1\r\nHost: %s\r\n", args_info.dest_arg, args_info.dest_arg); ++ sprintf( buf, "CONNECT %s HTTP/1.1\r\nHost: %s\r\n", args_info.dest_arg, args_info.host_arg ? args_info.host_arg : args_info.dest_arg); + + if ( args_info.remuser_given && args_info.rempass_given ) + strzcat( buf, "Proxy-Authorization: Basic %s\r\n", basicauth(args_info.remuser_arg, args_info.rempass_arg )); +diff --git a/io.c b/io.c +index acbcde7..e8df31a 100644 +--- a/io.c ++++ b/io.c +@@ -29,6 +29,8 @@ + #include "proxytunnel.h" + #include "io.h" + ++#define ACTIVE 1 ++#define CLOSED 0 + + /* + * Read one line of data from the tunnel. Line is terminated by a +@@ -41,7 +43,7 @@ int readline(PTSTREAM *pts) { + + /* Read one character at a time into buf, until a newline is encountered. */ + while ( c != 10 && ( i < SIZE - 1 ) ) { +- if( stream_read( pts, &c ,1) < 0) { ++ if( stream_read( pts, &c ,1) <= 0) { + my_perror( "Socket read error" ); + exit( 1 ); + } +@@ -55,8 +57,8 @@ int readline(PTSTREAM *pts) { + + if( args_info.verbose_flag ) { + /* Copy line of data into dstr without trailing newline */ +- char *dstr = malloc(sizeof(buf) + 1); +- strlcpy( dstr, buf, strlen(buf) - 1); ++ char *dstr = malloc(strlen(buf) + 1); ++ strncpy( dstr, buf, strlen(buf)); + if (strcmp(dstr, "")) + message( " <- %s\n", dstr ); + } +@@ -81,11 +83,17 @@ void cpio(PTSTREAM *stream1, PTSTREAM *stream2) { + /* We are never interested in sockets being available for write */ + FD_ZERO( &writefds ); + ++ ++ /* experimental timeout */ ++ struct timeval select_timeout; ++ select_timeout.tv_sec = 30; /* should be fine */ ++ select_timeout.tv_usec = 0; ++ + if( args_info.verbose_flag ) + message( "\nTunnel established.\n" ); + +- /* Only diamonds are forever :-) */ +- while( 1==1 ) { ++ int stream_status = ACTIVE; ++ while( stream_status == ACTIVE ) { + /* Clear the interesting socket sets */ + FD_ZERO( &readfds ); + FD_ZERO( &exceptfds ); +@@ -99,32 +107,37 @@ void cpio(PTSTREAM *stream1, PTSTREAM *stream2) { + FD_SET( stream_get_outgoing_fd(stream1), &exceptfds ); + FD_SET( stream_get_incoming_fd(stream2), &exceptfds ); + FD_SET( stream_get_outgoing_fd(stream2), &exceptfds ); +- +- /* Wait until something happens on the registered sockets/files */ +- if ( select( max_fd + 1, &readfds, &writefds, &exceptfds, 0 ) < 0 ) { ++ ++ /* reset the timeout, since select() does modify this struct! */ ++ select_timeout.tv_sec = 30; ++ select_timeout.tv_usec = 0; ++ ++ /* Wait/timeout something happens on the registered sockets/files */ ++ int number_of_fds_ready; ++ number_of_fds_ready = select( max_fd + 1, &readfds, &writefds, &exceptfds, &select_timeout ); ++ if ( number_of_fds_ready < 0 ) { + perror("select error"); + exit(1); + } + +- /* +- * Is stream1 ready for read? If so, copy a block of data +- * from stream1 to stream2. Or else if stream2 +- * is ready for read, copy a block of data from the +- * stream2 to stream1. Otherwise an exceptional condition +- * is flagged and the program is terminated. +- */ +- if ( FD_ISSET( stream_get_incoming_fd(stream1), &readfds ) ) { +- if ( stream_copy(stream1, stream2 ) ) +- break; +- } else if( FD_ISSET( stream_get_incoming_fd(stream2), &readfds ) ) { +- if( stream_copy(stream2, stream1 ) ) +- break; +- } else { +- my_perror( "Exceptional condition" ); +- break; +- } ++ if (number_of_fds_ready > 0) { ++ /* Is stream1 ready for read? If so, copy a block of data ++ * from stream1 to stream2. Or else if stream2 ++ * is ready for read, copy a block of data from the ++ * stream2 to stream1. Otherwise an exceptional condition ++ * is flagged and the program is terminated. ++ */ ++ if ( FD_ISSET( stream_get_incoming_fd(stream1), &readfds ) ) { ++ if ( stream_copy(stream1, stream2 ) ) ++ stream_status = CLOSED; ++ } else if( FD_ISSET( stream_get_incoming_fd(stream2), &readfds ) ) { ++ if( stream_copy(stream2, stream1 ) ) ++ stream_status = CLOSED; ++ } else { ++ my_perror( "Exceptional condition" ); ++ stream_status = CLOSED; ++ } ++ } + } + closeall(); + } +- +-// vim:noexpandtab:ts=4 +diff --git a/proxytunnel.c b/proxytunnel.c +index 9844e3d..18aa414 100644 +--- a/proxytunnel.c ++++ b/proxytunnel.c +@@ -66,45 +66,44 @@ void signal_handler( int signal ) { + * the socket that is connected to the proxy + */ + int tunnel_connect() { +- struct sockaddr_in sa; +- struct hostent *he; ++ struct addrinfo hints = { ++ .ai_family = AF_UNSPEC, ++ .ai_socktype = SOCK_STREAM, ++ .ai_flags = AI_ADDRCONFIG | AI_NUMERICSERV, ++ .ai_protocol = 0 ++ }; ++ struct addrinfo * result, * rp; ++ int rc; ++ char service[6]; + int sd; + +- /* Create the socket */ +- if( ( sd = socket( AF_INET, SOCK_STREAM, 0 ) ) < 0 ) { +- my_perror("Can not create socket"); ++ rc = snprintf( service, sizeof(service), "%d", args_info.proxyport_arg ); ++ if( ( rc < 0 ) || ( rc >= sizeof(service) ) ) { ++ /* this should never happen */ ++ message( "snprintf() failed" ); + exit(1); + } +- +- /* Lookup the IP address of the proxy */ +- if( ! ( he = gethostbyname( args_info.proxyhost_arg ) ) ) { +-// FIXME: my_perror("Local proxy %s could not be resolved", args_info.proxyhost_arg); +- my_perror("Local proxy could not be resolved." ); ++ rc = getaddrinfo( args_info.proxyhost_arg, service, &hints, &result ); ++ if( rc != 0 ) { ++ message( "getaddrinfo() failed to resolve local proxy: %s\n", ++ gai_strerror( rc ) ); + exit(1); + } +- +- char ip[16]; +- snprintf(ip, 16, "%d.%d.%d.%d", he->h_addr[0] & 255, he->h_addr[1] & 255, he->h_addr[2] & 255, he->h_addr[3] & 255); +- if( args_info.verbose_flag && strcmp(args_info.proxyhost_arg, ip)) { +- message( "Local proxy %s resolves to %d.%d.%d.%d\n", +- args_info.proxyhost_arg, +- he->h_addr[0] & 255, +- he->h_addr[1] & 255, +- he->h_addr[2] & 255, +- he->h_addr[3] & 255 ); ++ for (rp = result; rp != NULL; rp = rp->ai_next) { ++ sd = socket( rp->ai_family, rp->ai_socktype, rp->ai_protocol ); ++ if( sd < 0 ) { ++ continue; ++ } ++ if( connect( sd, rp->ai_addr, rp->ai_addrlen ) == 0 ) { ++ break; ++ } ++ close(sd); + } +- +- /* Set up the structure to connect to the proxy port of the proxy host */ +- memset( &sa, '\0', sizeof( sa ) ); +- sa.sin_family = AF_INET; +- memcpy( &sa.sin_addr.s_addr, he->h_addr, 4); +- sa.sin_port = htons( args_info.proxyport_arg ); +- +- /* Connect the socket */ +- if( connect( sd, (struct sockaddr*) &sa, sizeof( sa ) ) < 0 ) { +- my_perror("connect() failed"); ++ if( rp == NULL ) { ++ my_perror( "failed to connect to local proxy" ); + exit(1); + } ++ freeaddrinfo(result); + + /* Increase interactivity of tunnel, patch by Ingo Molnar */ + int flag = 1; +@@ -266,7 +265,7 @@ void do_daemon() + #ifdef USE_SSL + /* If --encrypt-proxy is specified, connect to the proxy using SSL */ + if ( args_info.encryptproxy_flag ) +- stream_enable_ssl(stunnel); ++ stream_enable_ssl(stunnel, args_info.proxy_arg); + #endif /* USE_SSL */ + + /* Open the tunnel */ +@@ -275,7 +274,7 @@ void do_daemon() + #ifdef USE_SSL + /* If --encrypt is specified, wrap all traffic after the proxy handoff in SSL */ + if( args_info.encrypt_flag ) +- stream_enable_ssl(stunnel); ++ stream_enable_ssl(stunnel, args_info.dest_arg); + #endif /* USE_SSL */ + + #ifdef SETPROCTITLE +@@ -388,7 +387,7 @@ int main( int argc, char *argv[] ) { + /* If --encrypt-proxy is specified, connect to the proxy using SSL */ + #ifdef USE_SSL + if ( args_info.encryptproxy_flag ) +- stream_enable_ssl(stunnel); ++ stream_enable_ssl(stunnel, args_info.proxy_arg); + #endif /* USE_SSL */ + + /* Open the tunnel */ +@@ -397,7 +396,7 @@ int main( int argc, char *argv[] ) { + /* If --encrypt is specified, wrap all traffic after the proxy handoff in SSL */ + #ifdef USE_SSL + if( args_info.encrypt_flag ) +- stream_enable_ssl(stunnel); ++ stream_enable_ssl(stunnel, args_info.dest_arg); + #endif /* USE_SSL */ + + #ifdef SETPROCTITLE +diff --git a/proxytunnel.h b/proxytunnel.h +index b948be0..593cd7e 100644 +--- a/proxytunnel.h ++++ b/proxytunnel.h +@@ -26,14 +26,20 @@ void message( char *s, ... ); + void my_perror( char *msg ); + void signal_handler( int signal ); + int tunnel_connect(); +-void analyze_HTTP(); +-void proxy_protocol(); ++void analyze_HTTP(PTSTREAM *pts); ++void proxy_protocol(PTSTREAM *pts); + void closeall(); + void do_daemon(); + void initsetproctitle(int argc, char *argv[]); + void setproctitle(const char *fmt, ...); ++ ++#if defined(__APPLE__) && defined(__MACH__) ++/* Don't include strlcat and strlcpy since they are provided as macros on OSX */ ++#else + size_t strlcat(char *dst, const char *src, size_t siz); + size_t strlcpy(char *dst, const char *src, size_t siz); ++#endif ++ + size_t strzcat(char *dst, char *format, ...); + int main( int argc, char *argv[] ); + char * readpassphrase(const char *, char *, size_t, int); +diff --git a/ptstream.c b/ptstream.c +index 4c87c80..d1c5f44 100644 +--- a/ptstream.c ++++ b/ptstream.c +@@ -19,12 +19,15 @@ + + /* ptstream.c */ + ++#include ++#include + #include + #include + #include + #include + #include + #include ++#include + + #include "proxytunnel.h" + +@@ -142,24 +145,199 @@ int stream_copy(PTSTREAM *pts_from, PTSTREAM *pts_to) { + } + + ++/* Check the certificate host name against the expected host name */ ++/* Return 1 if peer hostname is valid, any other value indicates failure */ ++int check_cert_valid_host(const char *cert_host, const char *peer_host) { ++ if (cert_host == NULL || peer_host == NULL) { ++ return 0; ++ } ++ if (cert_host[0] == '*') { ++ if (strncmp(cert_host, "*.", 2) != 0) { ++ /* Invalid wildcard hostname */ ++ return 0; ++ } ++ /* Skip "*." */ ++ cert_host += 2; ++ /* Wildcards can only match the first subdomain component */ ++ while (*peer_host++ != '.' && *peer_host != '\0') ++ ;; ++ } ++ if (strlen(cert_host) == 0 || strlen(peer_host) == 0) { ++ return 0; ++ } ++ return strcmp(cert_host, peer_host) == 0; ++} ++ ++ ++int check_cert_valid_ip6(const unsigned char *cert_ip_data, const int cert_ip_len, const struct in6_addr *addr6) { ++ int i; ++ for (i = 0; i < cert_ip_len; i++) { ++ if (cert_ip_data[i] != addr6->s6_addr[i]) { ++ return 0; ++ } ++ } ++ return 1; ++} ++ ++ ++int check_cert_valid_ip(const unsigned char *cert_ip_data, const int cert_ip_len, const struct in_addr *addr) { ++ int i; ++ for (i = 0; i < cert_ip_len; i++) { ++ if (cert_ip_data[i] != ((addr->s_addr >> (i * 8)) & 0xFF)) { ++ return 0; ++ } ++ } ++ return 1; ++} ++ ++ ++int check_cert_names(X509 *cert, char *peer_host) { ++ char peer_cn[256]; ++ const GENERAL_NAME *gn; ++ STACK_OF(GENERAL_NAME) *gen_names; ++ struct in_addr addr; ++ struct in6_addr addr6; ++ int peer_host_is_ipv4 = 0, peer_host_is_ipv6 = 0; ++ int i, san_count; ++ ++ gen_names = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL); ++ san_count = sk_GENERAL_NAME_num(gen_names); ++ if (san_count > 0) { ++ peer_host_is_ipv4 = (inet_pton(AF_INET, peer_host, &addr) == 1); ++ peer_host_is_ipv6 = (peer_host_is_ipv4 ? 0 : inet_pton(AF_INET6, peer_host, &addr6) == 1); ++ for (i = 0; i < san_count; i++) { ++ gn = sk_GENERAL_NAME_value(gen_names, i); ++ if (gn->type == GEN_DNS && !(peer_host_is_ipv4 || peer_host_is_ipv6)) { ++ if (check_cert_valid_host((char*)ASN1_STRING_data(gn->d.ia5), peer_host)) { ++ return 1; ++ } ++ } else if (gn->type == GEN_IPADD) { ++ if (gn->d.ip->length == 4 && peer_host_is_ipv4) { ++ if (check_cert_valid_ip(gn->d.ip->data, gn->d.ip->length, &addr)) { ++ return 1; ++ } ++ } else if (gn->d.ip->length == 16 && peer_host_is_ipv6) { ++ if (check_cert_valid_ip6(gn->d.ip->data, gn->d.ip->length, &addr6)) { ++ return 1; ++ } ++ } ++ } ++ } ++ message("Host name %s does not match certificate subject alternative names\n", peer_host); ++ } else { ++ X509_NAME_get_text_by_NID(X509_get_subject_name(cert), NID_commonName, peer_cn, sizeof(peer_cn)); ++ message("Host name %s does not match certificate common name %s or any subject alternative names\n", peer_host, peer_cn); ++ return check_cert_valid_host(peer_cn, peer_host); ++ } ++ return 0; ++} ++ + /* Initiate an SSL handshake on this stream and encrypt all subsequent data */ +-int stream_enable_ssl(PTSTREAM *pts) { ++int stream_enable_ssl(PTSTREAM *pts, const char *proxy_arg) { + #ifdef USE_SSL +- SSL_METHOD *meth; ++ const SSL_METHOD *meth; + SSL *ssl; + SSL_CTX *ctx; +- ++ long res = 1; ++ long ssl_options = 0; ++ ++ X509* cert = NULL; ++ int status; ++ struct stat st_buf; ++ const char *ca_file = NULL; ++ const char *ca_dir = "/etc/ssl/certs/"; /* Default cert directory if none given */ ++ long vresult; ++ char *peer_host = NULL; ++ char proxy_arg_fmt[32]; ++ size_t proxy_arg_len; ++ + /* Initialise the connection */ + SSLeay_add_ssl_algorithms(); +- meth = SSLv3_client_method(); ++ if (args_info.enforcetls1_flag) { ++ meth = TLSv1_client_method(); ++ } else { ++ meth = SSLv23_client_method(); ++ } + SSL_load_error_strings(); + + ctx = SSL_CTX_new (meth); ++ if (args_info.no_ssl3_flag) { ++ ssl_options |= SSL_OP_NO_SSLv3; ++ } ++ SSL_CTX_set_options (ctx, ssl_options); ++ ++ if ( !args_info.no_check_cert_flag ) { ++ if ( args_info.cacert_given ) { ++ if ((status = stat(args_info.cacert_arg, &st_buf)) != 0) { ++ message("Error reading certificate path %s\n", args_info.cacert_arg); ++ goto fail; ++ } ++ if (S_ISDIR(st_buf.st_mode)) { ++ ca_dir = args_info.cacert_arg; ++ } else { ++ ca_dir = NULL; ++ ca_file = args_info.cacert_arg; ++ } ++ } ++ if (!SSL_CTX_load_verify_locations(ctx, ca_file, ca_dir)) { ++ message("Error loading certificate(s) from %s\n", args_info.cacert_arg); ++ goto fail; ++ } ++ } ++ + ssl = SSL_new (ctx); ++ + SSL_set_rfd (ssl, stream_get_incoming_fd(pts)); + SSL_set_wfd (ssl, stream_get_outgoing_fd(pts)); ++ ++ /* Determine the host name we are connecting to */ ++ proxy_arg_len = strlen(proxy_arg); ++ if ((peer_host = malloc(proxy_arg_len + 1)) == NULL) { ++ message("Out of memory\n"); ++ goto fail; ++ } ++ snprintf( proxy_arg_fmt, sizeof(proxy_arg_fmt), proxy_arg[0] == '[' ? "[%%%zu[^]]]" : "%%%zu[^:]", proxy_arg_len - 1 ); ++ if ( sscanf( proxy_arg, proxy_arg_fmt, peer_host ) != 1 ) { ++ goto fail; ++ } ++ ++ /* SNI support */ ++ if ( args_info.verbose_flag ) { ++ message( "Set SNI hostname to %s\n", peer_host); ++ } ++ res = SSL_set_tlsext_host_name(ssl, peer_host); ++ if (res < 0) { ++ message( "TLS SNI error, giving up: SSL_set_tlsext_host_name returned error message:\n %u\n", res ); ++ exit( 1 ); ++ } ++ + SSL_connect (ssl); + ++ if ( !args_info.no_check_cert_flag ) { ++ /* Make sure peer presented a certificate */ ++ cert = SSL_get_peer_certificate(ssl); ++ if (cert == NULL) { ++ message("No certificate presented\n"); ++ goto fail; ++ } ++ ++ /* Check that the certificate is valid */ ++ vresult = SSL_get_verify_result(ssl); ++ if (vresult != X509_V_OK) { ++ message("Certificate verification failed (%s)\n", ++ X509_verify_cert_error_string(vresult)); ++ goto fail; ++ } ++ ++ /* Verify the certificate name matches the host we are connecting to */ ++ if (!check_cert_names(cert, peer_host)) { ++ goto fail; ++ } ++ ++ free(peer_host); ++ X509_free(cert); ++ } ++ + /* Store ssl and ctx parameters */ + pts->ssl = ssl; + pts->ctx = ctx; +@@ -168,6 +346,17 @@ int stream_enable_ssl(PTSTREAM *pts) { + #endif /* USE_SSL */ + + return 1; ++ ++fail: ++#ifdef USE_SSL ++ if (cert != NULL) { ++ X509_free(cert); ++ } ++ if (peer_host != NULL) { ++ free(peer_host); ++ } ++#endif /* USE_SSL */ ++ exit(1); + } + + +diff --git a/ptstream.h b/ptstream.h +index e7efd43..ee36af2 100644 +--- a/ptstream.h ++++ b/ptstream.h +@@ -44,7 +44,7 @@ int stream_close(PTSTREAM *pts); + int stream_read(PTSTREAM *pts, void *buf, size_t len); + int stream_write(PTSTREAM *pts, void *buf, size_t len); + int stream_copy(PTSTREAM *pts_from, PTSTREAM *pts_to); +-int stream_enable_ssl(PTSTREAM *pts); ++int stream_enable_ssl(PTSTREAM *pts, const char *proxy_arg); + int stream_get_incoming_fd(PTSTREAM *pts); + int stream_get_outgoing_fd(PTSTREAM *pts); + +diff --git a/readpassphrase.c b/readpassphrase.c +index 1870700..b107624 100644 +--- a/readpassphrase.c ++++ b/readpassphrase.c +@@ -135,8 +135,13 @@ restart: + oterm.c_lflag |= ECHO; + } + +- if (!(flags & RPP_STDIN)) +- (void)write(output, prompt, strlen(prompt)); ++ if (!(flags & RPP_STDIN)) { ++ ssize_t bytes_written = write(output, prompt, strlen(prompt)); ++ if (bytes_written != strlen(prompt)) { ++ message("Error on writing bytes to prompt\n"); ++ } ++ } ++ + end = buf + bufsiz - 1; + for (p = buf; (nr = read(input, &ch, 1)) == 1 && ch != '\n' && ch != '\r';) { + if (p < end) { +@@ -153,8 +158,12 @@ restart: + } + *p = '\0'; + save_errno = errno; +- if (!(term.c_lflag & ECHO)) +- (void)write(output, "\n", 1); ++ if (!(term.c_lflag & ECHO)) { ++ ssize_t bytes_written = write(output, "\n", 1); ++ if (bytes_written != 1) { ++ message("Error writing one byte to prompt\n"); ++ } ++ } + + /* Restore old terminal settings and signals. */ + if (memcmp(&term, &oterm, sizeof(term)) != 0) { diff --git a/proxytunnel.spec b/proxytunnel.spec index 84d35b2..86809fa 100644 --- a/proxytunnel.spec +++ b/proxytunnel.spec @@ -1,13 +1,15 @@ Summary: Proxy Tunnel ssh-over-https hack Summary(pl.UTF-8): Tunel proxy ssh-po-https Name: proxytunnel -Version: 1.9.0 -Release: 0.2 +Version: 1.9.1 +Release: 0.1 License: GPL Group: Applications -Source0: http://dl.sourceforge.net/proxytunnel/%{name}-%{version}.tgz -# Source0-md5: d74472b89c3f3b3b0abf6bd809ae34c2 -URL: http://proxytunnel.sourceforge.net/ +Source0: https://github.com/proxytunnel/proxytunnel/archive/%{version}.tar.gz +# Source0-md5: 9a844a735c9833b12c725d2118cd3e37 +Patch0: %{name}-git.patch +Patch1: %{name}-git-openssl-warnings.patch +URL: https://github.com/proxytunnel/proxytunnel BuildRequires: openssl-devel BuildRequires: pkgconfig BuildRoot: %{tmpdir}/%{name}-%{version}-root-%(id -u -n) @@ -41,6 +43,8 @@ aktualnie potrafi: %prep %setup -q +%patch0 -p1 +%patch1 -p1 %build %{__make} \ @@ -52,7 +56,8 @@ aktualnie potrafi: rm -rf $RPM_BUILD_ROOT %{__make} install \ - PREFIX=$RPM_BUILD_ROOT%{_prefix} + prefix=%{_prefix} \ + DESTDIR=$RPM_BUILD_ROOT %clean rm -rf $RPM_BUILD_ROOT