- Applied (reworked) changes from Mark Cave-Ayland to support -E option

encrypting data to the proxy with SSL (untested by me)
- Change version to 1.6.4


git-svn-id: https://proxytunnel.svn.sourceforge.net/svnroot/proxytunnel/trunk/proxytunnel@143 bc163920-b10d-0410-b2c5-a5491ca2ceef
This commit is contained in:
Mark Janssen 2007-02-12 20:48:17 +00:00
parent 42913f3c39
commit bbda7f9734
13 changed files with 479 additions and 303 deletions

View file

@ -1,4 +1,4 @@
Changes to proxytunnel version 1.6.4 -- xxx
Changes to proxytunnel version 1.6.4 -- Mon Feb 12 21:45:06 CEST 2007
- Allow multiple '-H' options (headers), total size of the headers
should not exceed 1k.
@ -10,6 +10,8 @@ Changes to proxytunnel version 1.6.4 -- xxx
- Change error message on 'connection closed' in analyze_HTTP
- Reworked debug-output (dag-)
- Signal handling (dag-)
- Applied (reworked) changes from Mark Cave-Ayland to support -E option
encrypting data to the proxy with SSL (untested by me)
Changes to proxytunnel version 1.6.3 -- Mon Apr 10 12:48:02 CEST 2006

View file

@ -18,7 +18,7 @@ people.
Stephane Engel at macchiati.org - Fix for broken proxy
Mike Frysinger <vapier@gentoo.org> - Makefile fix, 64bit fix
Alex Peuchert proxytunnel@peuchert.de - SSL/Encrypt support
Mark.Cave-Ayland @ ilande.co.uk - SSL to Proxy, Streams
Furthermore we would like to thank the wonderful people at SourceForge
for hosting our development.

View file

@ -50,7 +50,8 @@ OBJ = proxytunnel.o \
readpassphrase.o \
messages.o \
cmdline.o \
ntlm.o
ntlm.o \
ptstream.o
proxytunnel: $(OBJ)
$(CC) -o $(PROGNAME) $(CFLAGS) $(OBJ) $(LDFLAGS)

View file

@ -59,6 +59,7 @@ cmdline_parser_print_help (void)
#endif
#ifdef USE_SSL
" -e --encrypt encrypt the communication using SSL\n"
" -E --encrypt-proxy encrypt the communitation between the client and the proxy using SSL\n"
#endif
#ifdef SETPROCTITLE
" -x STRING --proctitle=STRING Set the process-title to STRING\n"
@ -132,6 +133,7 @@ int cmdline_parser( int argc, char * const *argv, struct gengetopt_args_info *ar
args_info->header_given = 0;
args_info->domain_given = 0;
args_info->encrypt_given = 0;
args_info->encryptproxy_given = 0;
args_info->proctitle_given = 0;
/* No... we can't make this a function... -- Maniac */
@ -151,6 +153,7 @@ int cmdline_parser( int argc, char * const *argv, struct gengetopt_args_info *ar
args_info->quiet_flag = 0; \
args_info->standalone_arg = 0; \
args_info->encrypt_flag = 0; \
args_info->encryptproxy_flag = 0; \
args_info->proctitle_arg = NULL; \
}
@ -171,32 +174,33 @@ int cmdline_parser( int argc, char * const *argv, struct gengetopt_args_info *ar
/* Struct option: Name, Has_arg, Flag, Value */
static struct option long_options[] = {
{ "help", 0, NULL, 'h' },
{ "version", 0, NULL, 'V' },
{ "user", 1, NULL, 'u' },
{ "pass", 1, NULL, 's' },
{ "domain", 1, NULL, 't' },
{ "uservar", 1, NULL, 'U' },
{ "passvar", 1, NULL, 'S' },
{ "proxy", 1, NULL, 'p' },
{ "proxyhost", 1, NULL, 'g' },
{ "proxyport", 1, NULL, 'G' },
{ "dest", 1, NULL, 'd' },
{ "remproxy", 1, NULL, 'r' },
{ "proctitle", 1, NULL, 'x' },
{ "header", 1, NULL, 'H' },
{ "verbose", 0, NULL, 'v' },
{ "ntlm", 0, NULL, 'N' },
{ "inetd", 0, NULL, 'i' },
{ "standalone", 1, NULL, 'a' },
{ "quiet", 0, NULL, 'q' },
{ "encrypt", 0, NULL, 'e' },
{ "help", 0, NULL, 'h' },
{ "version", 0, NULL, 'V' },
{ "user", 1, NULL, 'u' },
{ "pass", 1, NULL, 's' },
{ "domain", 1, NULL, 't' },
{ "uservar", 1, NULL, 'U' },
{ "passvar", 1, NULL, 'S' },
{ "proxy", 1, NULL, 'p' },
{ "proxyhost", 1, NULL, 'g' },
{ "proxyport", 1, NULL, 'G' },
{ "dest", 1, NULL, 'd' },
{ "remproxy", 1, NULL, 'r' },
{ "proctitle", 1, NULL, 'x' },
{ "header", 1, NULL, 'H' },
{ "verbose", 0, NULL, 'v' },
{ "ntlm", 0, NULL, 'N' },
{ "inetd", 0, NULL, 'i' },
{ "standalone", 1, NULL, 'a' },
{ "quiet", 0, NULL, 'q' },
{ "encrypt", 0, NULL, 'e' },
{ "encrypt-proxy", 0, NULL, 'E' },
{ NULL, 0, NULL, 0 }
};
c = getopt_long (argc, argv, "hVia:u:s:t:U:S:p:r:d:H:x:nvNeq", long_options, &option_index);
c = getopt_long (argc, argv, "hVia:u:s:t:U:S:p:r:d:H:x:nvNeEq", long_options, &option_index);
#else
c = getopt( argc, argv, "hVia:u:s:t:U:S:p:r:d:H:x:nvNeq" );
c = getopt( argc, argv, "hVia:u:s:t:U:S:p:r:d:H:x:nvNeEq" );
#endif
if (c == -1) break; /* Exit from `while (1)' loop. */
@ -214,6 +218,12 @@ int cmdline_parser( int argc, char * const *argv, struct gengetopt_args_info *ar
if( args_info->verbose_flag )
message("SSL enabled\n");
break;
case 'E': /* Turn on client to proxy SSL encryption */
args_info->encryptproxy_flag = !(args_info->encryptproxy_flag);
if( args_info->verbose_flag )
message("SSL client to proxy enabled\n");
break;
#endif
case 'i': /* Run from inetd. */

View file

@ -41,25 +41,28 @@ struct gengetopt_args_info {
int quiet_flag; /* Turn on quiet mode (default=off). */
int standalone_arg; /* Turn on stdalone (-a) on port */
int encrypt_flag; /* Turn on SSL encryption (default=off). */
int encryptproxy_flag;/* Turn on client to proxy SSL encryption (def=off).*/
char * proctitle_arg; /* Override process title (default=off). */
int help_given; /* Whether help was given. */
int version_given; /* Whether version was given. */
int user_given; /* Whether user was given. */
int pass_given; /* Whether pass was given. */
int domain_given; /* Whether domain was given. */
int proxy_given; /* Whether proxyhost was given. */
int proxyhost_given; /* Whether proxyhost was given. */
int proxyport_given; /* Whether proxyport was given. */
int dest_given; /* Whether dest was given. */
int remproxy_given; /* Whether remproxy was given. */
int verbose_given; /* Whether verbose was given. */
int ntlm_given; /* Whether ntlm was given. */
int inetd_given; /* Whether inetd was given. */
int quiet_given; /* Whether quiet mode was given. */
int header_given; /* Whenther extra headers are given */
int encrypt_given; /* Whether encrypt was given */
int proctitle_given; /* Whether to override process title */
int help_given; /* Whether help was given. */
int version_given; /* Whether version was given. */
int user_given; /* Whether user was given. */
int pass_given; /* Whether pass was given. */
int domain_given; /* Whether domain was given. */
int proxy_given; /* Whether proxyhost was given. */
int proxyhost_given; /* Whether proxyhost was given. */
int proxyport_given; /* Whether proxyport was given. */
int dest_given; /* Whether dest was given. */
int remproxy_given; /* Whether remproxy was given. */
int verbose_given; /* Whether verbose was given. */
int ntlm_given; /* Whether ntlm was given. */
int inetd_given; /* Whether inetd was given. */
int quiet_given; /* Whether quiet mode was given. */
int header_given; /* Whether extra headers are given */
int encrypt_given; /* Whether encrypt was given */
int encryptproxy_given; /* Whether encrypt was given */
int proctitle_given; /* Whether to override process title */
} ;
int cmdline_parser( int argc, char * const *argv, struct gengetopt_args_info *args_info );

View file

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#define VERSION "1.6.3"
#define VERSION "1.6.4"
#define PACKAGE "Proxytunnel"
#define PURPOSE "Build generic tunnels through HTTPS proxies"
#define AUTHORS "Jos Visser (Muppet) <josv@osp.nl>, Mark Janssen (Maniac) <maniac@maniac.nl>"

24
http.c
View file

@ -26,8 +26,8 @@
#include <sys/types.h>
#include <sys/socket.h>
#include "io.h"
#include "proxytunnel.h"
#include "io.h"
#include "basicauth.h"
#include "ntlm.h"
@ -35,7 +35,7 @@
* Analyze the proxy's HTTP response. This must be a HTTP/1.? 200 OK type
* header
*/
void analyze_HTTP()
void analyze_HTTP(PTSTREAM *pts)
{
char *p = strtok( buf, " ");
@ -45,7 +45,7 @@ void analyze_HTTP()
*/
while (strncmp( p, "HTTP/", 5) != 0 )
{
if ( readline() )
if ( readline(pts) )
p = strtok( buf, " ");
else
{
@ -76,7 +76,7 @@ void analyze_HTTP()
{
do
{
readline();
readline(pts);
if (strncmp( buf, "Proxy-Authenticate: NTLM ", 25) == 0)
{
if (parse_type2((unsigned char *)&buf[25]) < 0)
@ -86,7 +86,7 @@ void analyze_HTTP()
}
if (ntlm_challenge == 1)
{
proxy_protocol();
proxy_protocol(pts);
return;
}
exit( 1 );
@ -111,7 +111,7 @@ void print_line_prefix(char *buf, char *prefix)
* Execute the basic proxy protocol of CONNECT and response, until the
* last line of the response has been read. The tunnel is then open.
*/
void proxy_protocol()
void proxy_protocol(PTSTREAM *pts)
{
/*
* Create the proxy CONNECT command into buf
@ -170,7 +170,7 @@ void proxy_protocol()
/*
* Send the CONNECT instruction to the proxy
*/
if( send( sd, buf, strlen( buf ), 0 ) < 0 )
if( stream_write( pts, buf, strlen( buf )) < 0 )
{
my_perror( "Socket write error" );
exit( 1 );
@ -181,14 +181,14 @@ void proxy_protocol()
if( args_info.verbose_flag )
message( "Data received from local proxy:\n");
analyze_HTTP();
analyze_HTTP(pts);
if (args_info.remproxy_given )
{
/*
* Clean buffer for next analysis
*/
while ( strcmp( buf, "\r\n" ) != 0 ) readline();
while ( strcmp( buf, "\r\n" ) != 0 ) readline(pts);
if( args_info.verbose_flag )
message( "Tunneling to %s (destination)\n", args_info.dest_arg );
@ -212,7 +212,7 @@ void proxy_protocol()
/*
* Send the CONNECT instruction to the proxy
*/
if( send( sd, buf, strlen( buf ), 0 ) < 0 )
if( stream_write( pts, buf, strlen( buf )) < 0 )
{
my_perror( "Socket write error" );
exit( 1 );
@ -224,7 +224,7 @@ void proxy_protocol()
if( args_info.verbose_flag )
message( "Received from remote proxy:\n");
analyze_HTTP();
analyze_HTTP(pts);
}
/*
@ -235,7 +235,7 @@ void proxy_protocol()
ntlm_challenge = 2;
} else {
do {
readline();
readline(pts);
} while ( strcmp( buf, "\r\n" ) != 0 );
}
}

193
io.c
View file

@ -29,19 +29,12 @@
#include "proxytunnel.h"
#include "io.h"
#ifdef USE_SSL /* Override copy functions */
#define COPY_TO(fd) copy_to_SSL(fd, ssl)
#define COPY_FROM(fd) copy_from_SSL(ssl, fd)
#else
#define COPY_TO(fd) copy(fd, sd)
#define COPY_FROM(fd) copy(sd, fd)
#endif
/*
* Read one line of data from the tunnel. Line is terminated by a
* newline character. Result is stored in buf.
*/
int readline()
int readline(PTSTREAM *pts)
{
char *p = buf;
char c = 0;
@ -53,7 +46,7 @@ int readline()
*/
while ( c != 10 && ( i < SIZE - 1 ) )
{
if( recv( sd, &c ,1 ,0 ) < 0)
if( stream_read( pts, &c ,1) < 0)
{
my_perror( "Socket read error" );
exit( 1 );
@ -76,144 +69,26 @@ int readline()
return strlen( buf );
}
/*
* Copy a block of data from one socket descriptor to another. A true
* return code signifies EOF on the from socket descriptor.
*/
int copy(int from, int to)
{
int n;
/*
* Read a buffer from the source socket
*/
if ( ( n = read( from, buf, SIZE ) ) < 0 )
{
my_perror( "Socket read error" );
exit( 1 );
}
/*
* If we have read 0 bytes, there is an EOF on src
*/
if( n==0 )
return 1;
/*
* Write the buffer to the destination socket
*/
if ( write( to, buf, n ) != n )
{
my_perror( "Socket write error" );
exit( 1 );
}
/*
* We're not yet at EOF
*/
return 0;
}
#ifdef USE_SSL
int copy_to_SSL(int from, SSL* to)
{
int n;
/*
* Read a buffer from the source socket
*/
if ( ( n = read( from, buf, SIZE ) ) < 0 )
{
my_perror( "Socket read error" );
exit( 1 );
}
/*
* If we have read 0 bytes, there is an EOF on src
*/
if( n==0 )
return 1;
/*
* Write the buffer to the destination socket
*/
if ( SSL_write( to, buf, n ) != n )
{
my_perror( "Socket write error" );
exit( 1 );
}
/*
* We're not yet at EOF
*/
return 0;
}
int copy_from_SSL(SSL* from, int to)
{
int n;
/*
* Read a buffer from the source socket
*/
if ( ( n = SSL_read( from, buf, SIZE ) ) < 0 )
{
my_perror( "Socket read error" );
exit( 1 );
}
/*
* If we have read 0 bytes, there is an EOF on src
*/
if( n==0 )
return 1;
/*
* Write the buffer to the destination socket
*/
if ( write( to, buf, n ) != n )
{
my_perror( "Socket write error" );
exit( 1 );
}
/*
* We're not yet at EOF
*/
return 0;
}
#endif /* USE_SSL */
/*
* Move into a loop of copying data to and from the tunnel.
* stdin (fd 0) and stdout (fd 1) are the file descriptors
* for the connected application, sd is the file descriptor
* of the tunnel.
* Bond stream1 and stream2 together; any data received in stream1 is relayed
* to stream2, and vice-versa.
*/
void cpio()
void cpio(PTSTREAM *stream1, PTSTREAM *stream2)
{
fd_set readfds;
fd_set writefds;
fd_set exceptfds;
int max_fd;
int out_fd;
int in_max_fd, out_max_fd, max_fd;
#ifdef USE_SSL
if( args_info.encrypt_flag )
out_fd = SSL_get_fd(ssl);
else
out_fd = sd;
#else
out_fd = sd;
#endif
/*
* Find the biggest file descriptor for select()
*/
max_fd = MAX( read_fd,write_fd );
max_fd = MAX( max_fd, out_fd );
in_max_fd = MAX(stream_get_incoming_fd(stream1), stream_get_incoming_fd(stream2));
out_max_fd = MAX(stream_get_outgoing_fd(stream1), stream_get_outgoing_fd(stream2));
max_fd = MAX(in_max_fd, out_max_fd);
/*
* We're never interested in sockets being available for write.
@ -235,18 +110,18 @@ void cpio()
FD_ZERO( &exceptfds );
/*
* We want to know whether stdin or sd is ready for reading
* We want to know whether stream1 or stream2 is ready for reading
*/
FD_SET( read_fd, &readfds );
FD_SET( out_fd, &readfds );
FD_SET( stream_get_incoming_fd(stream1), &readfds );
FD_SET( stream_get_incoming_fd(stream2), &readfds );
/*
* And we want to know about exceptional conditions on either
* stdin, stdout or the tunnel
* And we want to know about exceptional conditions on either stream
*/
FD_SET( read_fd, &exceptfds );
FD_SET( write_fd, &exceptfds );
FD_SET( out_fd, &exceptfds );
FD_SET( stream_get_incoming_fd(stream1), &exceptfds );
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 one of the registered
@ -260,37 +135,21 @@ void cpio()
}
/*
* Is stdin ready for read? If so, copy a block of data
* from stdin to the tunnel. Or else if the tunnel socket
* 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
* tunnel to stdout. Otherwise an exceptional condition
* stream2 to stream1. Otherwise an exceptional condition
* is flagged and the program is terminated.
*/
if ( FD_ISSET( read_fd, &readfds ) )
if ( FD_ISSET( stream_get_incoming_fd(stream1), &readfds ) )
{
if( args_info.encrypt_flag )
{
if ( COPY_TO(read_fd ) )
break;
}
else
{
if ( copy(read_fd, sd ) )
break;
}
if ( stream_copy(stream1, stream2 ) )
break;
}
else if( FD_ISSET( sd, &readfds ) )
else if( FD_ISSET( stream_get_incoming_fd(stream2), &readfds ) )
{
if( args_info.encrypt_flag )
{
if( COPY_FROM(write_fd ) )
break;
}
else
{
if( copy(sd,write_fd ) )
break;
}
if( stream_copy(stream2, stream1 ) )
break;
}
else
{

6
io.h
View file

@ -18,7 +18,5 @@
*/
/* io.h */
int readline();
int copy(int from, int to);
void cpio();
int readline(PTSTREAM *pts);
void cpio(PTSTREAM *stream1, PTSTREAM *stream2);

View file

@ -33,11 +33,11 @@
#include <stdarg.h>
#include <stdlib.h>
#include "proxytunnel.h"
#include "io.h"
#include "config.h"
#include "cmdline.h"
#include "basicauth.h"
#include "proxytunnel.h"
#include "ntlm.h"
/* Define DARWIN if compiling on MacOS-X (Darwin), to work around some
@ -50,12 +50,6 @@
int read_fd=0; /* The file descriptor to read from */
int write_fd=1; /* The file destriptor to write to */
#ifdef USE_SSL
SSL_CTX* ctx;
SSL* ssl;
SSL_METHOD *meth;
#endif
/*
* Kill the program (signal handler)
*/
@ -67,12 +61,13 @@ void signal_handler( int signal )
}
/*
* Create and connect the socket that connects to the proxy. After
* this routine the sd socket is connected to the proxy.
* Create and connect the socket that connects to the proxy. Returns
* the socket that is connected to the proxy
*/
void tunnel_connect() {
int tunnel_connect() {
struct sockaddr_in sa;
struct hostent *he;
int sd;
/*
* Create the socket
@ -131,26 +126,11 @@ void tunnel_connect() {
/* Make sure we get warned when someone hangs up on us */
signal(SIGHUP,signal_handler);
/* Return the socket */
return sd;
}
#ifdef USE_SSL
/*
* Do the SSL handshake.
*/
void do_ssl()
{
SSLeay_add_ssl_algorithms();
meth = SSLv2_client_method();
SSL_load_error_strings();
ctx = SSL_CTX_new (meth);
ssl = SSL_new (ctx);
SSL_set_fd (ssl, sd);
SSL_connect (ssl);
}
#endif
/*
* Leave a goodbye message
@ -171,30 +151,12 @@ void closeall() {
#endif
/*
* Close all files we deal with
* Close all streams
*/
close(0);
close(1);
if ( sd != 0 )
close( sd );
#ifdef USE_SSL
if( args_info.encrypt_flag )
{
SSL_free (ssl);
SSL_CTX_free (ctx);
}
#else
close( sd );
#endif
if( read_fd != write_fd ) /* When not running from inetd */
{
close( write_fd );
}
close( read_fd );
if (stunnel)
stream_close(stunnel);
if (std)
stream_close(std);
}
/*
@ -211,6 +173,10 @@ void do_daemon()
char buf[80];
unsigned char addr[4];
/* Socket descriptor */
int sd;
if ( ( listen_sd = socket( AF_INET, SOCK_STREAM, 0 ) ) < 0 )
{
my_perror( "Server socket creation failed" );
@ -297,12 +263,26 @@ void do_daemon()
{
read_fd = write_fd = sd_client;
/* Main processing */
tunnel_connect();
proxy_protocol();
/* Create a stdin/out stream */
std = stream_open(read_fd, write_fd);
/* Create a tunnel stream */
sd = tunnel_connect();
stunnel = stream_open(sd, sd);
/* If --encrypt-proxy is specified, connect to the proxy using SSL */
#ifdef USE_SSL
if ( args_info.encryptproxy_flag )
stream_enable_ssl(stunnel);
#endif
/* Open the tunnel */
proxy_protocol(stunnel);
/* If --encrypt is specified, wrap all traffic after the proxy handoff in SSL */
#ifdef USE_SSL
if( args_info.encrypt_flag )
do_ssl();
stream_enable_ssl(stunnel);
#endif
#ifdef SETPROCTITLE
if( ! args_info.proctitle_given )
@ -313,8 +293,9 @@ void do_daemon()
if( args_info.proctitle_given )
message( "Setting process-title is not supported in this build\n");
#endif
cpio();
/* Run the tunnel - we should stay here indefinitely */
cpio(std, stunnel);
/////
exit( 0 );
}
@ -339,6 +320,13 @@ void do_daemon()
*/
int main( int argc, char *argv[] )
{
/* Socket descriptor */
int sd;
/* Clear all stream variables (so we know whether we need to clear up) */
stunnel = NULL;
std = NULL;
program_name = argv[0];
/*
@ -356,7 +344,7 @@ int main( int argc, char *argv[] )
* different mainline is needed...
* - Set a signal for the hangup (HUP) signal
* - Optionally create the proxy basic authentication cookie
* - Connect the sd socket to the proxy
* - Connect to the proxy
* - Execute the proxy protocol to connect it to the origin server
* - Enter copy in-out mode to channel data hence and forth
*/
@ -386,6 +374,16 @@ int main( int argc, char *argv[] )
make_basicauth();
}
/*
* Only one of -E (SSL encrypt client to proxy connection) or -e (SSL encrypt tunnel data)
* can be specified.
*/
if (args_info.encryptproxy_flag && args_info.encrypt_flag)
{
message("Error: only one of --encrypt-proxy and --encrypt can be specified for a tunnel\n");
exit( 1 );
}
/* Do we need to run as a standalone daemon? */
if ( args_info.standalone_arg > 0 )
{
@ -400,12 +398,26 @@ int main( int argc, char *argv[] )
write_fd=0;
}
/* Main processing */
tunnel_connect();
proxy_protocol();
/* Create a stdin/out stream */
std = stream_open(read_fd, write_fd);
/* Create a tunnel stream */
sd = tunnel_connect();
stunnel = stream_open(sd, sd);
/* If --encrypt-proxy is specified, connect to the proxy using SSL */
#ifdef USE_SSL
if ( args_info.encryptproxy_flag )
stream_enable_ssl(stunnel);
#endif
/* Open the tunnel */
proxy_protocol(stunnel);
/* If --encrypt is specified, wrap all traffic after the proxy handoff in SSL */
#ifdef USE_SSL
if( args_info.encrypt_flag )
do_ssl();
stream_enable_ssl(stunnel);
#endif
#ifdef SETPROCTITLE
if( ! args_info.proctitle_given )
@ -417,8 +429,12 @@ int main( int argc, char *argv[] )
message( "Setting process-title is not supported in this build\n");
#endif
cpio();
/* Run the tunnel - we should stay here indefinitely */
cpio(std, stunnel);
}
/* If we do happen to get here, clean up */
closeall();
exit( 0 );
}

View file

@ -19,22 +19,15 @@
/* proxytunnel.h */
#ifdef USE_SSL
#include <openssl/crypto.h>
#include <openssl/x509.h>
#include <openssl/pem.h>
#include <openssl/ssl.h>
#endif
#include "cmdline.h"
#include "ptstream.h"
void message( char *s, ... );
void my_perror( char *msg );
void signal_handler( int signal );
void tunnel_connect();
int tunnel_connect();
void analyze_HTTP();
void proxy_protocol();
void do_ssl();
void closeall();
void do_daemon();
void initsetproctitle(int argc, char *argv[]);
@ -46,16 +39,13 @@ char * readpassphrase(const char *, char *, size_t, int);
char * getpass_x(const char *prompt);
/* Globals */
int sd; /* The tunnel's socket descriptor */
int read_fd; /* The file descriptor to read from */
int write_fd; /* The file destriptor to write to */
char *program_name; /* Guess what? */
int i_am_daemon; /* Also... */
#ifdef USE_SSL
SSL_CTX* ctx;
SSL* ssl;
#endif
PTSTREAM *stunnel; /* The stream representing the socket from us to the proxy */
PTSTREAM *std; /* The stream representing stdin/stdout */
/*
* All the command line options

247
ptstream.c Normal file
View file

@ -0,0 +1,247 @@
/* Proxytunnel - (C) 2001-2006 Jos Visser / Mark Janssen */
/* Contact: josv@osp.nl / maniac@maniac.nl */
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/* ptstream.c */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include "proxytunnel.h"
/*
* Open a stream for incoming and outgoing data with the specified fds
*/
PTSTREAM *stream_open(int incoming_fd, int outgoing_fd)
{
PTSTREAM *pts;
/* Initialise the structure and store the file descriptor */
pts = malloc(sizeof(PTSTREAM));
pts->incoming_fd = incoming_fd;
pts->outgoing_fd = outgoing_fd;
pts->ssl = NULL;
pts->ctx = NULL;
/* Return a pointer to the structure */
return pts;
}
/*
* Close a stream
*/
int stream_close(PTSTREAM *pts)
{
/* Close the incoming fd */
if (pts->incoming_fd != 0)
close(pts->incoming_fd);
/* Close the outgoing fd */
if (pts->outgoing_fd != 0)
close(pts->outgoing_fd);
/* Destroy the SSL context */
if (pts->ssl)
{
#ifdef USE_SSL
SSL_free (pts->ssl);
SSL_CTX_free (pts->ctx);
#endif
}
/* Free the structure */
free(pts);
return 1;
}
/*
* Read from a stream
*/
int stream_read(PTSTREAM *pts, void *buf, size_t len)
{
/* Read up to the specified number of bytes into the buffer */
int bytes_read;
if (!pts->ssl)
{
/* For a non-SSL stream... */
bytes_read = read(pts->incoming_fd, buf, len);
}
else
{
#ifdef USE_SSL
/* For an SSL stream... */
bytes_read = SSL_read(pts->ssl, buf, len);
#else
/* No SSL support, so must use a non-SSL stream */
bytes_read = read(pts->incoming_fd, buf, len);
#endif
}
return bytes_read;
}
/*
* Write to a stream
*/
int stream_write(PTSTREAM *pts, void *buf, size_t len)
{
/* Write the specified number of bytes from the buffer */
int bytes_written;
if (!pts->ssl)
{
/* For a non-SSL stream... */
bytes_written = write(pts->outgoing_fd, buf, len);
}
else
{
#ifdef USE_SSL
/* For an SSL stream... */
bytes_written = SSL_write(pts->ssl, buf, len);
#else
/* No SSL support, so must use a non-SSL stream */
bytes_written = write(pts->outgoing_fd, buf, len);
#endif
}
return bytes_written;
}
/*
* Copy a block of data from one stream to another. A true
* return code signifies EOF on the from socket descriptor.
*/
int stream_copy(PTSTREAM *pts_from, PTSTREAM *pts_to)
{
char buf[SIZE];
int n;
/*
* Read a buffer from the source socket
*/
if ( ( n = stream_read( pts_from, buf, SIZE ) ) < 0 )
{
my_perror( "Socket read error" );
exit( 1 );
}
/*
* If we have read 0 bytes, there is an EOF on src
*/
if( n==0 )
return 1;
/*
* Write the buffer to the destination socket
*/
if ( stream_write( pts_to, buf, n ) != n )
{
my_perror( "Socket write error" );
exit( 1 );
}
/*
* We're not yet at EOF
*/
return 0;
}
/*
* Initiate an SSL handshake on this stream and encrypt all subsequent data
*/
int stream_enable_ssl(PTSTREAM *pts)
{
#ifdef USE_SSL
SSL_METHOD *meth;
SSL *ssl;
SSL_CTX *ctx;
/* Initialise the connection */
SSLeay_add_ssl_algorithms();
meth = SSLv2_client_method();
SSL_load_error_strings();
ctx = SSL_CTX_new (meth);
ssl = SSL_new (ctx);
SSL_set_rfd (ssl, stream_get_incoming_fd(pts));
SSL_set_wfd (ssl, stream_get_outgoing_fd(pts));
SSL_connect (ssl);
/* Store ssl and ctx parameters */
pts->ssl = ssl;
pts->ctx = ctx;
#else
message("Warning: stream_open(): SSL stream requested but no SSL support available; using unencrypted connection");
#endif
return 1;
}
/*
* Return the incoming_fd for a given stream
*/
int stream_get_incoming_fd(PTSTREAM *pts)
{
if (!pts->ssl)
return pts->incoming_fd;
else
#ifdef USE_SSL
return SSL_get_fd(pts->ssl);
#else
return pts->incoming_fd;
#endif
}
/*
* Return the outgoing_fd for a given stream
*/
int stream_get_outgoing_fd(PTSTREAM *pts)
{
if (!pts->ssl)
return pts->outgoing_fd;
else
#ifdef USE_SSL
return SSL_get_fd(pts->ssl);
#else
return pts->outgoing_fd;
#endif
}

50
ptstream.h Normal file
View file

@ -0,0 +1,50 @@
/* Proxytunnel - (C) 2001-2006 Jos Visser / Mark Janssen */
/* Contact: josv@osp.nl / maniac@maniac.nl */
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/* ptstream.h */
#ifdef USE_SSL
#include <openssl/crypto.h>
#include <openssl/x509.h>
#include <openssl/pem.h>
#include <openssl/ssl.h>
#endif
typedef struct ptstream
{
int incoming_fd;
int outgoing_fd;
#ifdef USE_SSL
SSL *ssl;
SSL_CTX *ctx;
#else
void *ssl;
void *ctx;
#endif
} PTSTREAM;
PTSTREAM *stream_open(int incoming_fd, int outgoing_fd);
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_get_incoming_fd(PTSTREAM *pts);
int stream_get_outgoing_fd(PTSTREAM *pts);