mirror of
https://github.com/proxytunnel/proxytunnel.git
synced 2026-01-23 02:34:59 +00:00
Cleaning up more... moving more stuff to separate .c and .h files
git-svn-id: https://proxytunnel.svn.sourceforge.net/svnroot/proxytunnel/trunk/proxytunnel@20 bc163920-b10d-0410-b2c5-a5491ca2ceef
This commit is contained in:
parent
785411bb8b
commit
6f626da741
11 changed files with 599 additions and 378 deletions
8
Makefile
8
Makefile
|
|
@ -12,8 +12,12 @@ INSTALLPATH = /usr/local/bin
|
|||
# LDFLAGS = -lsocket -lnsl
|
||||
|
||||
PROGNAME = proxytunnel
|
||||
OBJ = proxytunnel.o \
|
||||
base64.o \
|
||||
OBJ = proxytunnel.o \
|
||||
base64.o \
|
||||
io.o \
|
||||
http.o \
|
||||
basicauth.o \
|
||||
messages.o \
|
||||
cmdline.o
|
||||
|
||||
proxytunnel: $(OBJ)
|
||||
|
|
|
|||
23
base64.h
23
base64.h
|
|
@ -1,5 +1,22 @@
|
|||
/* Proxytunnel base64.h */
|
||||
/* Proxytunnel - (C) 2001-2002 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
|
||||
*/
|
||||
|
||||
/* base64.h */
|
||||
|
||||
void base64(unsigned char *out, const unsigned char *in, int len);
|
||||
char basicauth[80]; /* Buffer to hold the proxies basic authentication data */
|
||||
|
||||
|
|
|
|||
57
basicauth.c
Normal file
57
basicauth.c
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
/* Proxytunnel - (C) 2001-2002 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
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "base64.h"
|
||||
#include "config.h"
|
||||
#include "cmdline.h"
|
||||
#include "proxytunnel.h"
|
||||
#include "basicauth.h"
|
||||
|
||||
/*
|
||||
* Create the HTTP basic authentication cookie for use by the proxy. Result
|
||||
* is stored in basicauth.
|
||||
*/
|
||||
void make_basicauth()
|
||||
{
|
||||
int len = strlen( args_info.user_arg ) + \
|
||||
strlen( args_info.pass_arg ) + 2;
|
||||
char *p = (char *) malloc( len );
|
||||
|
||||
/*
|
||||
* Set up the cookie in clear text
|
||||
*/
|
||||
sprintf( p, "%s:%s", args_info.user_arg, args_info.pass_arg );
|
||||
|
||||
/*
|
||||
* Base64 encode the clear text cookie to create the HTTP base64
|
||||
* authentication cookie
|
||||
*/
|
||||
base64( basicauth, p, strlen( p ) );
|
||||
|
||||
if( args_info.verbose_flag )
|
||||
{
|
||||
message( "Proxy basic auth is %s\n", basicauth );
|
||||
}
|
||||
|
||||
free( p );
|
||||
}
|
||||
|
||||
26
basicauth.h
Normal file
26
basicauth.h
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
/* Proxytunnel - (C) 2001-2002 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
|
||||
*/
|
||||
|
||||
/* basicauth.h */
|
||||
char basicauth[80]; /* Buffer to hold the proxies basic authentication data */
|
||||
|
||||
/* Functions */
|
||||
void make_basicauth();
|
||||
|
||||
|
||||
144
http.c
Normal file
144
http.c
Normal file
|
|
@ -0,0 +1,144 @@
|
|||
/* Proxytunnel - (C) 2001-2002 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
|
||||
*/
|
||||
|
||||
/* http.c */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <netdb.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include "io.h"
|
||||
#include "proxytunnel.h"
|
||||
#include "basicauth.h"
|
||||
|
||||
/*
|
||||
* Analyze the proxy's HTTP response. This must be a HTTP/1.? 200 OK type
|
||||
* header
|
||||
*/
|
||||
void analyze_HTTP()
|
||||
{
|
||||
char *p = strtok( buf, " ");
|
||||
|
||||
if (strcmp( p, "HTTP/1.0" ) != 0 && strcmp( p, "HTTP/1.1" ) != 0)
|
||||
{
|
||||
message( "Unsupported HTTP version number %s\n", p );
|
||||
exit( 1 );
|
||||
}
|
||||
|
||||
p = strtok( 0, " ");
|
||||
|
||||
if( strcmp( p, "200" ) != 0 )
|
||||
{
|
||||
message( "HTTP return code: '%s'\n", p );
|
||||
p += strlen( p ) + 1;
|
||||
message( "%s\n", p );
|
||||
exit( 1 );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 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()
|
||||
{
|
||||
/*
|
||||
* Create the proxy CONNECT command into buf
|
||||
*/
|
||||
|
||||
if( args_info.dottedquad_flag )
|
||||
{
|
||||
static char ipbuf[16]; /* IPv4: 'xxx.xxx.xxx.xxx' + \0 = 16 */
|
||||
struct hostent * he = gethostbyname( args_info.desthost_arg );
|
||||
if ( he )
|
||||
{
|
||||
sprintf( ipbuf, "%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 )
|
||||
{
|
||||
message( "DEBUG: ipbuf = '%s'\n", ipbuf );
|
||||
message( "DEBUG: desthost = '%s'\n",
|
||||
args_info.desthost_arg );
|
||||
}
|
||||
|
||||
args_info.desthost_arg = ipbuf;
|
||||
|
||||
if( args_info.verbose_flag )
|
||||
message( "DEBUG: desthost = '%s'\n",
|
||||
args_info.desthost_arg );
|
||||
|
||||
}
|
||||
else if( args_info.verbose_flag )
|
||||
message( "Can't lookup dest host: %s.\n",
|
||||
args_info.desthost_arg );
|
||||
|
||||
}
|
||||
|
||||
if ( args_info.user_given && args_info.pass_given )
|
||||
{
|
||||
/*
|
||||
* Create connect string including the authorization part
|
||||
*/
|
||||
sprintf( buf,
|
||||
"CONNECT %s:%d HTTP/1.0\r\nProxy-authorization: Basic %s \r\nProxy-Connection: Keep-Alive\r\n\r\n",
|
||||
args_info.desthost_arg,
|
||||
args_info.destport_arg,basicauth );
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* Create connect string without authorization part
|
||||
*/
|
||||
sprintf( buf, "CONNECT %s:%d HTTP/1.0\r\nProxy-Connection: Keep-Alive\r\n\r\n",
|
||||
args_info.desthost_arg,
|
||||
args_info.destport_arg );
|
||||
}
|
||||
|
||||
if( args_info.verbose_flag )
|
||||
message( "%s", buf);
|
||||
|
||||
/*
|
||||
* Send the CONNECT instruction to the proxy
|
||||
*/
|
||||
if( send( sd, buf, strlen( buf ), 0 ) < 0 )
|
||||
{
|
||||
my_perror( "Socket write error" );
|
||||
exit( 1 );
|
||||
}
|
||||
|
||||
/*
|
||||
* Read the first line of the response and analyze it
|
||||
*/
|
||||
readline();
|
||||
analyze_HTTP();
|
||||
|
||||
/*
|
||||
* Then, repeat reading lines of the responses until a blank line
|
||||
* (which signifies the end of the response) is encountered.
|
||||
*/
|
||||
do {
|
||||
readline();
|
||||
} while ( strcmp( buf, "\r\n" ) != 0 );
|
||||
}
|
||||
207
io.c
Normal file
207
io.c
Normal file
|
|
@ -0,0 +1,207 @@
|
|||
/* Proxytunnel - (C) 2001-2002 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
|
||||
*/
|
||||
|
||||
/* io.c */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include "proxytunnel.h"
|
||||
#include "io.h"
|
||||
|
||||
/*
|
||||
* Read one line of data from the tunnel. Line is terminated by a
|
||||
* newline character. Result is stored in buf.
|
||||
*/
|
||||
void readline()
|
||||
{
|
||||
char *p = buf;
|
||||
char c = 0;
|
||||
int i = 0;
|
||||
|
||||
/*
|
||||
* Read one character at a time into buf, until a newline is
|
||||
* encountered.
|
||||
*/
|
||||
while ( c != 10 && i < SIZE - 1 )
|
||||
{
|
||||
if( recv( sd, &c ,1 ,0 ) < 0)
|
||||
{
|
||||
my_perror( "Socket read error" );
|
||||
exit( 1 );
|
||||
}
|
||||
|
||||
*p = c;
|
||||
p++;
|
||||
i++;
|
||||
}
|
||||
|
||||
*p = 0;
|
||||
|
||||
if( args_info.verbose_flag )
|
||||
message( "%s", 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;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
void cpio()
|
||||
{
|
||||
fd_set readfds;
|
||||
fd_set writefds;
|
||||
fd_set exceptfds;
|
||||
int max_fd;
|
||||
|
||||
/*
|
||||
* Find the biggest file descriptor for select()
|
||||
*/
|
||||
max_fd = MAX( read_fd,write_fd );
|
||||
max_fd = MAX( max_fd,sd );
|
||||
|
||||
|
||||
/*
|
||||
* We're never interested in sockets being available for write.
|
||||
*/
|
||||
FD_ZERO( &writefds );
|
||||
|
||||
if( ! args_info.quiet_flag )
|
||||
{
|
||||
message( "Starting tunnel\n" );
|
||||
}
|
||||
|
||||
/*
|
||||
* Only diamonds are forever :-)
|
||||
*/
|
||||
while( 1==1 )
|
||||
{
|
||||
/*
|
||||
* Clear the interesting socket sets
|
||||
*/
|
||||
FD_ZERO( &readfds );
|
||||
FD_ZERO( &exceptfds );
|
||||
|
||||
/*
|
||||
* We want to know whether stdin or sd is ready for reading
|
||||
*/
|
||||
FD_SET( read_fd,&readfds );
|
||||
FD_SET( sd,&readfds );
|
||||
|
||||
/*
|
||||
* And we want to know about exceptional conditions on either
|
||||
* stdin, stdout or the tunnel
|
||||
*/
|
||||
FD_SET( read_fd,&exceptfds );
|
||||
FD_SET( write_fd,&exceptfds );
|
||||
FD_SET( sd,&exceptfds );
|
||||
|
||||
/*
|
||||
* Wait until something happens on one of the registered
|
||||
* sockets/files
|
||||
*/
|
||||
if ( select( max_fd + 1, &readfds, &writefds,
|
||||
&exceptfds, 0 ) < 0 )
|
||||
{
|
||||
perror("select error");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Is stdin ready for read? If so, copy a block of data
|
||||
* from stdin to the tunnel. Or else if the tunnel socket
|
||||
* is ready for read, copy a block of data from the
|
||||
* tunnel to stdout. Otherwise an exceptional condition
|
||||
* is flagged and the program is terminated.
|
||||
*/
|
||||
if ( FD_ISSET( read_fd, &readfds ) )
|
||||
{
|
||||
if ( copy( read_fd, sd ) )
|
||||
break;
|
||||
}
|
||||
else if( FD_ISSET( sd, &readfds ) )
|
||||
{
|
||||
if( copy(sd,write_fd ) )
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
my_perror( "Exceptional condition" );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Close all files we deal with
|
||||
*/
|
||||
close( read_fd );
|
||||
close( sd );
|
||||
|
||||
if( read_fd != write_fd ) /* When not running from inetd */
|
||||
{
|
||||
close( write_fd );
|
||||
}
|
||||
|
||||
if( args_info.verbose_flag )
|
||||
{
|
||||
message( "Tunnel closed\n" );
|
||||
}
|
||||
}
|
||||
24
io.h
Normal file
24
io.h
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
/* Proxytunnel - (C) 2001-2002 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
|
||||
*/
|
||||
|
||||
/* io.h */
|
||||
void readline();
|
||||
int copy(int from, int to);
|
||||
void cpio();
|
||||
|
||||
53
messages.c
Normal file
53
messages.c
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
/* Proxytunnel - (C) 2001-2002 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
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <syslog.h>
|
||||
#include "proxytunnel.h"
|
||||
|
||||
/*
|
||||
* Give a message to the user
|
||||
*/
|
||||
void message( char *s, ... )
|
||||
{
|
||||
va_list ap;
|
||||
char buf[1024];
|
||||
|
||||
va_start( ap, s );
|
||||
vsnprintf( buf, sizeof( buf ), s, ap );
|
||||
va_end( ap );
|
||||
|
||||
if ( i_am_daemon )
|
||||
syslog( LOG_NOTICE, buf );
|
||||
else
|
||||
fputs( buf, stderr );
|
||||
}
|
||||
|
||||
/*
|
||||
* My own perror function (uses the internal message)
|
||||
*/
|
||||
void my_perror( char *msg )
|
||||
{
|
||||
char *err = strerror( errno );
|
||||
|
||||
message( "Error! %s: %s\n", msg, err );
|
||||
}
|
||||
BIN
proxytunnel
BIN
proxytunnel
Binary file not shown.
379
proxytunnel.c
379
proxytunnel.c
|
|
@ -32,63 +32,17 @@
|
|||
#include <syslog.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "io.h"
|
||||
#include "config.h"
|
||||
#include "cmdline.h"
|
||||
#include "base64.h"
|
||||
#include "basicauth.h"
|
||||
#include "proxytunnel.h"
|
||||
|
||||
/*
|
||||
* Some variables
|
||||
*/
|
||||
int sd; /* The tunnel's socket descriptor */
|
||||
int read_fd=0; /* The file descriptor to read from */
|
||||
int write_fd=1; /* The file destriptor to write to */
|
||||
char *program_name; /* Guess what? */
|
||||
int i_am_daemon; /* Also... */
|
||||
/* Globals */
|
||||
int read_fd=0; /* The file descriptor to read from */
|
||||
int write_fd=1; /* The file destriptor to write to */
|
||||
|
||||
|
||||
/*
|
||||
* All the command line options
|
||||
*/
|
||||
struct gengetopt_args_info args_info;
|
||||
|
||||
#define SIZE 65536
|
||||
char buf[SIZE]; /* Data transfer buffer */
|
||||
|
||||
/*
|
||||
* Small MAX macro
|
||||
*/
|
||||
#ifndef MAX
|
||||
#define MAX( x, y ) ( ( (x)>(y) ) ? (x) : (y) )
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Give a message to the user
|
||||
*/
|
||||
void message( char *s, ... )
|
||||
{
|
||||
va_list ap;
|
||||
char buf[1024];
|
||||
|
||||
va_start( ap, s );
|
||||
vsnprintf( buf, sizeof( buf ), s, ap );
|
||||
va_end( ap );
|
||||
|
||||
if ( i_am_daemon )
|
||||
syslog( LOG_NOTICE, buf );
|
||||
else
|
||||
fputs( buf, stderr );
|
||||
}
|
||||
|
||||
/*
|
||||
* My own perror function (uses the internal message)
|
||||
*/
|
||||
void my_perror( char *msg )
|
||||
{
|
||||
char *err = strerror( errno );
|
||||
|
||||
message( "Error! %s: %s\n", msg, err );
|
||||
}
|
||||
|
||||
/*
|
||||
* Kill the program (signal handler)
|
||||
*/
|
||||
|
|
@ -168,327 +122,6 @@ void tunnel_connect() {
|
|||
signal(SIGHUP,signal_handler);
|
||||
}
|
||||
|
||||
/*
|
||||
* Create the HTTP basic authentication cookie for use by the proxy. Result
|
||||
* is stored in basicauth.
|
||||
*/
|
||||
void make_basicauth()
|
||||
{
|
||||
int len = strlen( args_info.user_arg ) + \
|
||||
strlen( args_info.pass_arg ) + 2;
|
||||
char *p = (char *) malloc( len );
|
||||
|
||||
/*
|
||||
* Set up the cookie in clear text
|
||||
*/
|
||||
sprintf( p, "%s:%s", args_info.user_arg, args_info.pass_arg );
|
||||
|
||||
/*
|
||||
* Base64 encode the clear text cookie to create the HTTP base64
|
||||
* authentication cookie
|
||||
*/
|
||||
base64( basicauth, p, strlen( p ) );
|
||||
|
||||
if( args_info.verbose_flag )
|
||||
{
|
||||
message( "Proxy basic auth is %s\n", basicauth );
|
||||
}
|
||||
|
||||
free( p );
|
||||
}
|
||||
|
||||
/*
|
||||
* Read one line of data from the tunnel. Line is terminated by a
|
||||
* newline character. Result is stored in buf.
|
||||
*/
|
||||
void readline()
|
||||
{
|
||||
char *p = buf;
|
||||
char c = 0;
|
||||
int i = 0;
|
||||
|
||||
/*
|
||||
* Read one character at a time into buf, until a newline is
|
||||
* encountered.
|
||||
*/
|
||||
while ( c != 10 && i < SIZE - 1 )
|
||||
{
|
||||
if( recv( sd, &c ,1 ,0 ) < 0)
|
||||
{
|
||||
my_perror( "Socket read error" );
|
||||
exit( 1 );
|
||||
}
|
||||
|
||||
*p = c;
|
||||
p++;
|
||||
i++;
|
||||
}
|
||||
|
||||
*p = 0;
|
||||
|
||||
if( args_info.verbose_flag )
|
||||
message( "%s", buf );
|
||||
}
|
||||
|
||||
/*
|
||||
* Analyze the proxy's HTTP response. This must be a HTTP/1.? 200 OK type
|
||||
* header
|
||||
*/
|
||||
void analyze_HTTP()
|
||||
{
|
||||
char *p = strtok( buf, " ");
|
||||
|
||||
if (strcmp( p, "HTTP/1.0" ) != 0 && strcmp( p, "HTTP/1.1" ) != 0)
|
||||
{
|
||||
message( "Unsupported HTTP version number %s\n", p );
|
||||
exit( 1 );
|
||||
}
|
||||
|
||||
p = strtok( 0, " ");
|
||||
|
||||
if( strcmp( p, "200" ) != 0 )
|
||||
{
|
||||
message( "HTTP return code: '%s'\n", p );
|
||||
p += strlen( p ) + 1;
|
||||
message( "%s\n", p );
|
||||
exit( 1 );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 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()
|
||||
{
|
||||
/*
|
||||
* Create the proxy CONNECT command into buf
|
||||
*/
|
||||
|
||||
if( args_info.dottedquad_flag )
|
||||
{
|
||||
static char ipbuf[16]; /* IPv4: 'xxx.xxx.xxx.xxx' + \0 = 16 */
|
||||
struct hostent * he = gethostbyname( args_info.desthost_arg );
|
||||
if ( he )
|
||||
{
|
||||
sprintf( ipbuf, "%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 )
|
||||
{
|
||||
message( "DEBUG: ipbuf = '%s'\n", ipbuf );
|
||||
message( "DEBUG: desthost = '%s'\n",
|
||||
args_info.desthost_arg );
|
||||
}
|
||||
|
||||
args_info.desthost_arg = ipbuf;
|
||||
|
||||
if( args_info.verbose_flag )
|
||||
message( "DEBUG: desthost = '%s'\n",
|
||||
args_info.desthost_arg );
|
||||
|
||||
}
|
||||
else if( args_info.verbose_flag )
|
||||
message( "Can't lookup dest host: %s.\n",
|
||||
args_info.desthost_arg );
|
||||
|
||||
}
|
||||
|
||||
if ( args_info.user_given && args_info.pass_given )
|
||||
{
|
||||
/*
|
||||
* Create connect string including the authorization part
|
||||
*/
|
||||
sprintf( buf,
|
||||
"CONNECT %s:%d HTTP/1.0\r\nProxy-authorization: Basic %s \r\nProxy-Connection: Keep-Alive\r\n\r\n",
|
||||
args_info.desthost_arg,
|
||||
args_info.destport_arg,basicauth );
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* Create connect string without authorization part
|
||||
*/
|
||||
sprintf( buf, "CONNECT %s:%d HTTP/1.0\r\nProxy-Connection: Keep-Alive\r\n\r\n",
|
||||
args_info.desthost_arg,
|
||||
args_info.destport_arg );
|
||||
}
|
||||
|
||||
if( args_info.verbose_flag )
|
||||
message( "%s", buf);
|
||||
|
||||
/*
|
||||
* Send the CONNECT instruction to the proxy
|
||||
*/
|
||||
if( send( sd, buf, strlen( buf ), 0 ) < 0 )
|
||||
{
|
||||
my_perror( "Socket write error" );
|
||||
exit( 1 );
|
||||
}
|
||||
|
||||
/*
|
||||
* Read the first line of the response and analyze it
|
||||
*/
|
||||
readline();
|
||||
analyze_HTTP();
|
||||
|
||||
/*
|
||||
* Then, repeat reading lines of the responses until a blank line
|
||||
* (which signifies the end of the response) is encountered.
|
||||
*/
|
||||
do {
|
||||
readline();
|
||||
} while ( strcmp( buf, "\r\n" ) != 0 );
|
||||
}
|
||||
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
void cpio()
|
||||
{
|
||||
fd_set readfds;
|
||||
fd_set writefds;
|
||||
fd_set exceptfds;
|
||||
int max_fd;
|
||||
|
||||
/*
|
||||
* Find the biggest file descriptor for select()
|
||||
*/
|
||||
max_fd = MAX( read_fd,write_fd );
|
||||
max_fd = MAX( max_fd,sd );
|
||||
|
||||
|
||||
/*
|
||||
* We're never interested in sockets being available for write.
|
||||
*/
|
||||
FD_ZERO( &writefds );
|
||||
|
||||
if( ! args_info.quiet_flag )
|
||||
{
|
||||
message( "Starting tunnel\n" );
|
||||
}
|
||||
|
||||
/*
|
||||
* Only diamonds are forever :-)
|
||||
*/
|
||||
while( 1==1 )
|
||||
{
|
||||
/*
|
||||
* Clear the interesting socket sets
|
||||
*/
|
||||
FD_ZERO( &readfds );
|
||||
FD_ZERO( &exceptfds );
|
||||
|
||||
/*
|
||||
* We want to know whether stdin or sd is ready for reading
|
||||
*/
|
||||
FD_SET( read_fd,&readfds );
|
||||
FD_SET( sd,&readfds );
|
||||
|
||||
/*
|
||||
* And we want to know about exceptional conditions on either
|
||||
* stdin, stdout or the tunnel
|
||||
*/
|
||||
FD_SET( read_fd,&exceptfds );
|
||||
FD_SET( write_fd,&exceptfds );
|
||||
FD_SET( sd,&exceptfds );
|
||||
|
||||
/*
|
||||
* Wait until something happens on one of the registered
|
||||
* sockets/files
|
||||
*/
|
||||
if ( select( max_fd + 1, &readfds, &writefds,
|
||||
&exceptfds, 0 ) < 0 )
|
||||
{
|
||||
perror("select error");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Is stdin ready for read? If so, copy a block of data
|
||||
* from stdin to the tunnel. Or else if the tunnel socket
|
||||
* is ready for read, copy a block of data from the
|
||||
* tunnel to stdout. Otherwise an exceptional condition
|
||||
* is flagged and the program is terminated.
|
||||
*/
|
||||
if ( FD_ISSET( read_fd, &readfds ) )
|
||||
{
|
||||
if ( copy( read_fd, sd ) )
|
||||
break;
|
||||
}
|
||||
else if( FD_ISSET( sd, &readfds ) )
|
||||
{
|
||||
if( copy(sd,write_fd ) )
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
my_perror( "Exceptional condition" );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Close all files we deal with
|
||||
*/
|
||||
close( read_fd );
|
||||
close( sd );
|
||||
|
||||
if( read_fd != write_fd ) /* When not running from inetd */
|
||||
{
|
||||
close( write_fd );
|
||||
}
|
||||
|
||||
if( args_info.verbose_flag )
|
||||
{
|
||||
message( "Tunnel closed\n" );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Leave a goodbye message
|
||||
*/
|
||||
|
|
|
|||
56
proxytunnel.h
Normal file
56
proxytunnel.h
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
/* Proxytunnel - (C) 2001-2002 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
|
||||
*/
|
||||
|
||||
/* proxytunnel.h */
|
||||
|
||||
#include "cmdline.h"
|
||||
|
||||
void message( char *s, ... );
|
||||
void my_perror( char *msg );
|
||||
void signal_handler( int signal );
|
||||
void tunnel_connect();
|
||||
void analyze_HTTP();
|
||||
void proxy_protocol();
|
||||
void einde();
|
||||
void do_daemon();
|
||||
int main( int argc, char *argv[] );
|
||||
|
||||
/* 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... */
|
||||
|
||||
/*
|
||||
* All the command line options
|
||||
*/
|
||||
struct gengetopt_args_info args_info;
|
||||
|
||||
#define SIZE 65536
|
||||
char buf[SIZE]; /* Data transfer buffer */
|
||||
|
||||
/*
|
||||
* Small MAX macro
|
||||
*/
|
||||
|
||||
#ifndef MAX
|
||||
#define MAX( x, y ) ( ( (x)>(y) ) ? (x) : (y) )
|
||||
#endif
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue