Commit b05398fe authored by Chad Barb's avatar Chad Barb

Tiptunnel can now take "ssl-server-cert:" property from the ACL file,
which is a SHA hash of the expected server certificate.

(this is used to verify the server's identity,
thus precluding man-in-the-middle attacks.)

If no "ssl-server-cert:" is in the ACL,
it will revert to using a normal TCP connection.

In this version, authentication is still the same (even over SSL.)
(next step: add SSL to capture server.)
parent 2ad9ac28
...@@ -9,7 +9,7 @@ all: tip tiptunnel ...@@ -9,7 +9,7 @@ all: tip tiptunnel
include $(TESTBED_SRCDIR)/GNUmakerules include $(TESTBED_SRCDIR)/GNUmakerules
CC = gcc -g -O2 -DUSESOCKETS -I$(TESTBED_SRCDIR)/capture CC = gcc -g -O2 -DUSESOCKETS -DWITHSSL -I$(TESTBED_SRCDIR)/capture
OBJS = cmds.o cmdtab.o hunt.o partab.o \ OBJS = cmds.o cmdtab.o hunt.o partab.o \
remote.o tip.o value.o vars.o getcap.o remote.o tip.o value.o vars.o getcap.o
...@@ -21,11 +21,13 @@ TUNNELOBJS = tiptunnel.o ...@@ -21,11 +21,13 @@ TUNNELOBJS = tiptunnel.o
# #
LIBS= LIBS=
SSLLIBS = -lssl -lcrypto
tip: $(OBJS) tip: $(OBJS)
$(CC) -static -o tip $(OBJS) $(LIBS) $(CC) -static -o tip $(OBJS) $(LIBS)
tiptunnel: tiptunnel.o tiptunnel: tiptunnel.o
$(CC) -static -o tiptunnel tiptunnel.o $(LIBS) $(CC) -o tiptunnel tiptunnel.o $(SSLLIBS)
$(OBJS): tipconf.h tip.h $(OBJS): tipconf.h tip.h
......
...@@ -8,10 +8,12 @@ ...@@ -8,10 +8,12 @@
#include <netinet/in.h> #include <netinet/in.h>
#include <netdb.h> #include <netdb.h>
#ifdef WITHSSL
#include <openssl/ssl.h>
#endif /* WITHSSL */
#include "capdecls.h" #include "capdecls.h"
int ssl = 0;
int debug = 0; int debug = 0;
int allowRemote = 0; int allowRemote = 0;
...@@ -26,6 +28,12 @@ char * hostname = NULL; ...@@ -26,6 +28,12 @@ char * hostname = NULL;
secretkey_t key; secretkey_t key;
typedef int WriteFunc( void * data, int size );
typedef int ReadFunc( void * data, int size );
WriteFunc * writeFunc;
ReadFunc * readFunc;
void usage(); void usage();
void loadAcl( const char * filename ); void loadAcl( const char * filename );
void doConnect(); void doConnect();
...@@ -33,6 +41,24 @@ void doAuthenticate(); ...@@ -33,6 +41,24 @@ void doAuthenticate();
void doCreateTunnel(); void doCreateTunnel();
void doTunnelConnection(); void doTunnelConnection();
int writeNormal( void * data, int size );
int readNormal( void * data, int size );
#ifdef WITHSSL
void initSSL();
void sslConnect();
int writeSSL( void * data, int size );
int readSSL( void * data, int size );
SSL * ssl;
SSL_CTX * ctx;
int usingSSL = 0;
char * certString = NULL;
#endif /* WITHSSL */
int main( int argc, char ** argv ) int main( int argc, char ** argv )
{ {
...@@ -40,9 +66,6 @@ int main( int argc, char ** argv ) ...@@ -40,9 +66,6 @@ int main( int argc, char ** argv )
while ((op = getopt( argc, argv, "sp:rd" )) != -1) { while ((op = getopt( argc, argv, "sp:rd" )) != -1) {
switch (op) { switch (op) {
case 's':
ssl++;
break;
case 'p': case 'p':
tunnelPort = atoi( optarg ); tunnelPort = atoi( optarg );
break; break;
...@@ -68,9 +91,25 @@ int main( int argc, char ** argv ) ...@@ -68,9 +91,25 @@ int main( int argc, char ** argv )
loadAcl( argv[0] ); loadAcl( argv[0] );
doConnect(); #ifdef WITHSSL
if (usingSSL) {
writeFunc = writeSSL;
readFunc = readSSL;
initSSL();
doConnect();
sslConnect();
} else
#endif /* WITHSSL */
{
/* either there is no SSL, or they're not using it. */
writeFunc = writeNormal;
readFunc = readNormal;
doConnect();
}
doAuthenticate(); doAuthenticate();
doCreateTunnel(); doCreateTunnel();
if (programToLaunch) { if (programToLaunch) {
char portString[12]; char portString[12];
sprintf( portString, "%i", tunnelPort ); sprintf( portString, "%i", tunnelPort );
...@@ -95,9 +134,7 @@ void usage() ...@@ -95,9 +134,7 @@ void usage()
"\n" "\n"
"[program] path of program to launch with 'localhost'\n" "[program] path of program to launch with 'localhost'\n"
" and tunnel port as arguments.\n" " and tunnel port as arguments.\n"
// "-s\tturns on SSL (not implemented)\n" //"-k keeps accepting connections until killed"
//"-e <program>\tlaunches program to connect to tunnel\n"
//"-k\tkeeps accepting connections until killed"
); );
exit(-1); exit(-1);
} }
...@@ -127,6 +164,12 @@ void loadAcl( const char * filename ) ...@@ -127,6 +164,12 @@ void loadAcl( const char * filename )
key.keylen = atoi( b2 ); key.keylen = atoi( b2 );
} else if ( strcmp(b1, "key:") == 0 ) { } else if ( strcmp(b1, "key:") == 0 ) {
strcpy( key.key, b2 ); strcpy( key.key, b2 );
#ifdef WITHSSL
} else if ( strcmp(b1, "ssl-server-cert:") == 0 ) {
if (debug) { printf("Using SSL to connect to capture.\n"); }
certString = strdup( b2 );
usingSSL++;
#endif /* WITHSSL */
} else { } else {
fprintf(stderr, "Ignored unknown ACL: %s %s\n", b1, b2); fprintf(stderr, "Ignored unknown ACL: %s %s\n", b1, b2);
} }
...@@ -139,6 +182,16 @@ void loadAcl( const char * filename ) ...@@ -139,6 +182,16 @@ void loadAcl( const char * filename )
} }
int writeNormal( void * data, int size )
{
return write( sock, data, size );
}
int readNormal( void * data, int size )
{
return read( sock, data, size );
}
void doConnect() void doConnect()
{ {
struct sockaddr_in name; struct sockaddr_in name;
...@@ -172,14 +225,20 @@ void doAuthenticate() ...@@ -172,14 +225,20 @@ void doAuthenticate()
{ {
capret_t capret; capret_t capret;
if ( write( sock, &key, sizeof(key) ) == sizeof(key) && if ( writeFunc( /*sock,*/ &key, sizeof(key) ) == sizeof(key) &&
read(sock, &capret, sizeof(capret)) > 0 ) { readFunc( /*sock,*/ &capret, sizeof(capret)) > 0 ) {
if (capret == CAPOK) { switch( capret ) {
case CAPOK:
return; return;
} else if (capret == CAPBUSY) { case CAPBUSY:
fprintf(stderr, "Tip line busy.\n"); fprintf(stderr, "Tip line busy.\n");
} else if (capret == CAPNOPERM) { break;
fprintf(stderr, "You do not have permission! No TIP for you!\n"); case CAPNOPERM:
fprintf(stderr, "You do not have permission. No TIP for you!\n");
break;
default:
fprintf(stderr, "Unknown return code 0x%02x.\n", (unsigned int)capret);
return; // XXX Final version should break here.
} }
} else { } else {
// write or read hosed. // write or read hosed.
...@@ -284,14 +343,14 @@ acceptor: ...@@ -284,14 +343,14 @@ acceptor:
return; return;
} }
if (write( sock, buf, got ) < 0) { if (writeFunc( /*sock,*/ buf, got ) < 0) {
perror("write sock"); perror("write sock");
return; return;
} }
} }
if ( FD_ISSET( sock, &fds ) ) { if ( FD_ISSET( sock, &fds ) ) {
int got = read( sock, buf, 4096); int got = readFunc( /*sock,*/ buf, 4096);
if (got <= 0) { if (got <= 0) {
if (got < 0) { perror("read sock"); } if (got < 0) { perror("read sock"); }
if (debug) { printf("sock read %i; exiting.\n", got); } if (debug) { printf("sock read %i; exiting.\n", got); }
...@@ -305,3 +364,80 @@ acceptor: ...@@ -305,3 +364,80 @@ acceptor:
} }
} }
} }
#ifdef WITHSSL
void initSSL()
{
SSL_library_init();
ctx = SSL_CTX_new( SSLv23_method() );
// if (!(SSL_CTX_load_verify_location( ctx, CA_LIST, 0 ))
}
void sslConnect()
{
unsigned char digest[256];
unsigned int len = sizeof( digest );
unsigned char digestHex[512];
X509 * peer;
BIO * sbio;
int i;
ssl = SSL_new( ctx );
SSL_set_fd( ssl, sock );
// sbio = BIO_new_socket( sock, BIO_NOCLOSE );
// SSL_set_bio( ssl, sbio, sbio );
if (SSL_connect( ssl ) <= 0) {
fprintf(stderr, "SSL Connect error.\n");
exit(-1);
}
peer = SSL_get_peer_certificate( ssl );
// X509_print_fp( stdout );
// X509_digest( &peer, EVP_sha() , digest, &len );
//X509_digest( peer, EVP_md5(), digest, &len );
X509_digest( peer, EVP_sha(), digest, &len );
for (i = 0; i < len; i++) {
sprintf( digestHex + (i * 2), "%02x", (unsigned int) digest[i] );
}
if (debug) {
printf("ACL's cert digest: %s\n"
"Server cert digest: %s\n",
certString,
digestHex );
}
if (0 != strcmp( certString, digestHex )) {
fprintf(stderr,
"Server does not have certificate described in ACL:\n"
"ACL's cert digest: %s\n"
"Server cert digest: %s\n"
"Possible man-in-the-middle attack. Aborting.\n\n",
certString,
digestHex );
exit(-1);
}
}
int writeSSL( void * data, int size )
{
return SSL_write( ssl, data, size );
}
int readSSL( void * data, int size )
{
return SSL_read( ssl, data, size );
}
#endif /* WITHSSL */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment