--- a/Makefile
+++ b/Makefile
@@ -37,13 +37,8 @@
 
 # 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)
-endif
-ifeq ($(SSL_LIBS),)
-SSL_LIBS := -lssl -lcrypto
-endif
+SSL_LIBS := $(shell pkg-config --libs gnutls 2>/dev/null)
+SSL_LIBS += -lmhash
 LDFLAGS += $(SSL_LIBS)
 
 PREFIX =/usr/local
--- a/ntlm.c
+++ b/ntlm.c
@@ -28,8 +28,7 @@
 #include "proxytunnel.h"
 #include <ctype.h>
 #include <sys/time.h>
-#include <openssl/md4.h>
-#include <openssl/md5.h>
+#include <mhash.h>
 
 #define TYPE1_DATA_SEG 8
 #define TYPE2_BUF_SIZE 2048
@@ -247,62 +246,22 @@
 int key_len; /* length of authentication key */
 unsigned char digest[16]; /* caller digest to be filled in */
 {
-	MD5_CTX context;
-	unsigned char k_ipad[65];    /* inner padding - key XORd with ipad */
-	unsigned char k_opad[65];    /* outer padding - key XORd with opad */
-	unsigned char tk[16];
-	int i;
+	MHASH td;
 
-	/* if key is longer than 64 bytes reset it to key=MD5(key) */
-	if (key_len > 64) {
-		MD5_CTX tctx;
-		MD5_Init( &tctx );
-		MD5_Update( &tctx, key, key_len );
-		MD5_Final( tk, &tctx );
-		key = tk;
-		key_len = 16;
-	}
-
-	/*
-	 * the HMAC_MD5 transform looks like:
-	 *
-	 * MD5(K XOR opad, MD5(K XOR ipad, text))
-	 *
-	 * where K is an n byte key
-	 * ipad is the byte 0x36 repeated 64 times
-	 * opad is the byte 0x5c repeated 64 times
-	 * and text is the data being protected
-	 */
-
-	/* start out by storing key in pads */
-	bzero( k_ipad, sizeof k_ipad);
-	bzero( k_opad, sizeof k_opad);
-	bcopy( key, k_ipad, key_len);
-	bcopy( key, k_opad, key_len);
-
-	/* XOR key with ipad and opad values */
-	for (i=0; i<64; i++) {
-		k_ipad[i] ^= 0x36;
-		k_opad[i] ^= 0x5c;
-	}
-
-	/* perform inner MD5 */
-	MD5_Init(&context);                   /* init context for 1st pass */
-	MD5_Update(&context, k_ipad, 64);     /* start with inner pad */
-	MD5_Update(&context, text, text_len); /* then text of datagram */
-	MD5_Final(digest, &context);          /* finish up 1st pass */
-
-	/* perform outer MD5 */
-	MD5_Init(&context);                   /* init context for 2nd pass */
-	MD5_Update(&context, k_opad, 64);     /* start with outer pad */
-	MD5_Update(&context, digest, 16);     /* then results of 1st hash */
-	MD5_Final(digest, &context);          /* finish up 2nd pass */
+	td = mhash_hmac_init(MHASH_MD5, key, key_len,
+			     mhash_get_hash_pblock(MHASH_MD5));
+	if (td == MHASH_FAILED) {
+		message("Failed to set up HMAC hashing - giving up!\n");
+		exit(-1);
+	}
+	mhash(td, text, text_len);
+	mhash_hmac_deinit(td, digest);
 }
 
 void build_ntlm2_response() {
 	int i, j;
 	int passlen = 0;
-	MD4_CTX passcontext;
+	MHASH td;
 	unsigned char passdigest[16];
 	unsigned char *userdom;
 	int userdomlen;
@@ -327,9 +286,13 @@
 		}
 	}
 
-	MD4_Init (&passcontext);
-	MD4_Update (&passcontext, unipasswd, passlen);
-	MD4_Final (passdigest, &passcontext);
+	td = mhash_init(MHASH_MD4);
+	if (td == MHASH_FAILED) {
+		message("Failed to set up MD4 hashing - giving up!\n");
+		exit(-1);
+	}
+	mhash(td, unipasswd, passlen);
+	mhash_deinit(td, passdigest);
 
 	if( args_info.verbose_flag ) {
 		message("NTLM: MD4 of password is: ");
--- a/proxytunnel.1
+++ b/proxytunnel.1
@@ -2,7 +2,7 @@
 .\" First parameter, NAME, should be all caps
 .\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
 .\" other parameters are allowed: see man(7), man(1)
-.TH PROXYTUNNEL 1 "august  1, 2007"
+.TH PROXYTUNNEL 1 "August 30, 2009"
 .\" Please adjust this date whenever revising the manpage.
 .\"
 .\" Some roff macros, for reference:
@@ -37,11 +37,34 @@
 Print help and exit.
 .TP
 .B \-V, \-\-version
-kPrint the version of the program and exit.
+Print the version of the program and exit.
 .TP
 .B \-i, \-\-inetd
 Run from inetd. Default is off.
 .TP
+.B \-a PORT, \-\-standalone=PORT
+Run as standalone daemon on specified port.
+.TP
+.B \-p host:port, \-\-proxy=host:port
+The local HTTPS proxy host:port combo to connect to.
+.TP
+.B \-r host:port, \-\-remproxy=host:port
+The second-level (remote) proxy host:port to connect to when using two
+proxies.
+.TP
+.B \-d host:port, \-\-dest=host:port
+The destination host:port to built the tunnel to.
+.TP
+.B \-e, \-\-encrypt
+Encrypt the data between the local proxy and the destination using SSL.
+.TP
+.B \-E, \-\-encrypt-proxy
+Encrypt the data between the client and the local proxy using SSL.
+.TP
+.B \-X, \-\-encrypt-remproxy
+Encrypt the data between the local proxy and the second-level proxy
+using SSL.
+.TP
 .B \-F STRING, \-\-passfile=STRING
 The file containing Username & Password to send to HTTPS proxy for
 authentification.  This file uses the same format as .wgetrc, and so
@@ -49,22 +72,23 @@
 to at least hide the password from anyone clever enough to use the
 `ps' command.
 .TP
-.B \-p STRING, \-\-proxy=STRING
-The HTTPS Proxy host:port combo to connect to.
+.B \-P user:pass, \-\-proxyauth=user:pass
+The credentials to use for local HTTP(S) proxy authentication.
 .TP
-.B \-P STRING, \-\-proxyauth=STRING
-The credentials (user:pass) to use for local HTTP(S) proxy
-authentication.
+.B \-R user:pass, \-\-remproxyauth=user:pass
+The credentials to use for remote HTTP(S) proxy authentication.
 .TP
-.B \-d STRING, \-\-dest=STRING
-The destination host:port to built the tunnel to.
+.B \-N, \-\-ntlm
+Use NTLM-based authentication.
+.TP
+.B \-t DOMAIN, \-\-domain=DOMAIN
+The NTLM domain to use, default is to autodetect.
 .TP
-.B \-r STRING, \-\-remproxy=STRING
-The second-level proxy host:port to connect to.
+.B \-H STRING, \-\-header=STRING
+Additional HTTP headers to send to the proxy.
 .TP
-.B \-R STRING, \-\-remproxyauth=STRING
-The credentials (user:pass) to use for remote HTTP(S) proxy
-authentication.
+.B \-x STRING, \-\-proctitle=STRING
+Use a different process title.
 .TP
 .B \-v, \-\-verbose
 Turn on verbosity. Default is off.
@@ -80,8 +104,8 @@
 .br
 	ProtocolKeepAlives 30
 .br
-	ProxyCommand /usr/bin/proxytunnel -p proxy.customer.com:8080 -u user
--s password -d mybox.athome.nl:443
+	ProxyCommand /usr/bin/proxytunnel -p proxy.customer.com:8080
+        -P user:password -d mybox.athome.nl:443
 
 If your proxy doesn't require the username and password for using it,
 you can skip these options.
@@ -102,5 +126,7 @@
 .\".IR "The Rise and Fall of a Fooish Bar" ,
 .\"available via the Info system.
 .SH AUTHOR
-This manual page was written by Loc Le Guyader <loic.leguyader@laposte.net>,
-for the Debian GNU/Linux system (but may be used by others).
+This manual page was written by Loïc Le Guyader
+<loic.leguyader@laposte.net> and updated by Julian Gilbey
+<jdg@debian.org> for the Debian GNU/Linux system (but may be used by
+others).
--- a/proxytunnel.c
+++ b/proxytunnel.c
@@ -51,6 +51,15 @@
 /* Globals */
 int read_fd=0;				  /* The file descriptor to read from */
 int write_fd=1;				 /* The file destriptor to write to */
+#ifdef USE_SSL
+gnutls_anon_client_credentials_t anoncred;
+gnutls_certificate_credentials_t xcred;
+
+/* GNUTLS error logging function */
+void pt_gnutls_log_func( int level, const char* msg ) {
+	message("Log level %d: %s\n", level, msg);
+}
+#endif /* USE_SSL */
 
 /*
  * Kill the program (signal handler)
@@ -317,6 +326,20 @@
 	initsetproctitle( argc, argv );
 #endif
 
+#ifdef USE_SSL
+	/* Set up GNUTLS in case we later need it */
+	gnutls_global_init();
+	/* Anonymous credentials; may not work; see ptstream.c where the
+	   choice is made whether to use anonymous or credentials */
+	gnutls_anon_allocate_client_credentials( &anoncred );
+	/* X.509 stuff */
+	gnutls_certificate_allocate_credentials( &xcred );
+	gnutls_certificate_set_x509_trust_file( xcred, CAFILE, GNUTLS_X509_FMT_PEM);
+	
+	gnutls_global_set_log_function((gnutls_log_func) pt_gnutls_log_func);
+	gnutls_global_set_log_level(0);
+#endif
+
 	/*
 	 * This is what we do:
 	 * - Check if we need to run as a daemon. If so, a completely
@@ -414,6 +437,12 @@
 		cpio(std, stunnel);
 	}
 
+#ifdef USE_SSL
+	/* If we get here, we should clean up the GNUTLS setup */
+	gnutls_anon_free_client_credentials( anoncred );
+	gnutls_global_deinit();
+#endif
+
 	exit( 0 );
 }
 
--- a/ptstream.c
+++ b/ptstream.c
@@ -25,6 +25,7 @@
 #include <unistd.h>
 #include <sys/types.h>
 #include <sys/socket.h>
+#include <errno.h>
 
 #include "proxytunnel.h"
 
@@ -37,8 +38,7 @@
 	pts = malloc(sizeof(PTSTREAM));
 	pts->incoming_fd = incoming_fd;
 	pts->outgoing_fd = outgoing_fd;
-	pts->ssl = NULL;
-	pts->ctx = NULL;
+	pts->ssl = 0;
 
 	/* Return a pointer to the structure */
 	return pts;
@@ -49,11 +49,8 @@
 int stream_close(PTSTREAM *pts) {
 #ifdef USE_SSL
 	/* Destroy the SSL context */
-	if (pts->ssl) {
-		SSL_shutdown (pts->ssl);
-		SSL_free (pts->ssl);
-		SSL_CTX_free (pts->ctx);
-	}
+	if (pts->ssl)
+		gnutls_bye(pts->session, GNUTLS_SHUT_RDWR);
 #endif /* USE_SSL */
 
 	/* Close the incoming fd */
@@ -62,6 +59,12 @@
 	/* Close the outgoing fd */
 	close(pts->outgoing_fd);
 
+#ifdef USE_SSL
+	/* Destroy the SSL context */
+	if (pts->ssl)
+		gnutls_deinit(pts->session);
+#endif /* USE_SSL */
+
 	/* Free the structure */
 	free(pts);
 
@@ -80,7 +83,7 @@
 	} else {
 #ifdef USE_SSL
 		/* For an SSL stream... */
-		bytes_read = SSL_read(pts->ssl, buf, len);
+		bytes_read = gnutls_record_recv(pts->session, buf, len);
 #else
 		/* No SSL support, so must use a non-SSL stream */
 		bytes_read = read(pts->incoming_fd, buf, len);
@@ -102,7 +105,7 @@
 	} else {
 #ifdef USE_SSL
 		/* For an SSL stream... */
-		bytes_written = SSL_write(pts->ssl, buf, len);
+		bytes_written = gnutls_record_send(pts->session, buf, len);
 #else
 		/* No SSL support, so must use a non-SSL stream */
 		bytes_written = write(pts->outgoing_fd, buf, len);
@@ -145,24 +148,27 @@
 /* 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 = SSLv3_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;
+	int ret;
+
+	/* Initialise the context, copied from example in GNUTLS manual */
+	gnutls_init(&pts->session, GNUTLS_CLIENT);
+	gnutls_priority_set_direct(pts->session, "PERFORMANCE", NULL);
+	/* gnutls_credentials_set(pts->session, GNUTLS_CRD_ANON, anoncred); */
+	/* Use X.509 rather than anonymous */
+	gnutls_credentials_set(pts->session, GNUTLS_CRD_CERTIFICATE, xcred);
+
+	gnutls_transport_set_ptr2(pts->session,
+		  (gnutls_transport_ptr_t) stream_get_incoming_fd(pts),
+		  (gnutls_transport_ptr_t) stream_get_outgoing_fd(pts));
+
+	ret = gnutls_handshake (pts->session);
+	if (ret < 0) {
+		message( "TLS handshake error, giving up: gnutls_handshake returned error message:\n  %s\n", gnutls_strerror(ret) );
+		exit( 1 );
+	}
+		
+	/* Mark session as encrypted */
+	pts->ssl = 1;
 #else
 	message("Warning: stream_open(): SSL stream requested but no SSL support available; using unencrypted connection");
 #endif /* USE_SSL */
@@ -173,27 +179,38 @@
 
 /* Return the incoming_fd for a given stream */
 int stream_get_incoming_fd(PTSTREAM *pts) {
-
+#ifdef USE_SSL
+	gnutls_transport_ptr_t rcv, snd;
+#endif
+	
 	if (!pts->ssl)
 		return pts->incoming_fd;
-	else
+	else {
 #ifdef USE_SSL
-		return SSL_get_rfd(pts->ssl);
+		gnutls_transport_get_ptr2 (pts->session, &rcv, &snd);
+		return (int) rcv;
 #else
 		return pts->incoming_fd;
 #endif /* USE_SSL */
+	}
 }
 
 /* Return the outgoing_fd for a given stream */
 int stream_get_outgoing_fd(PTSTREAM *pts) {
+#ifdef USE_SSL
+	gnutls_transport_ptr_t rcv, snd;
+#endif
+
 	if (!pts->ssl)
 		return pts->outgoing_fd;
-	else
+	else {
 #ifdef USE_SSL
-		return SSL_get_wfd(pts->ssl);
+		gnutls_transport_get_ptr2 (pts->session, &rcv, &snd);
+		return (int) snd;
 #else
 		return pts->outgoing_fd;
 #endif /* USE_SSL */
+	}
 }
 
 // vim:noexpandtab:ts=4
--- a/ptstream.h
+++ b/ptstream.h
@@ -20,21 +20,19 @@
 /* ptstream.h */
 
 #ifdef USE_SSL
-#include <openssl/crypto.h>
-#include <openssl/x509.h>
-#include <openssl/pem.h>
-#include <openssl/ssl.h>
+#include <gnutls/gnutls.h>
+
+extern gnutls_anon_client_credentials_t anoncred;
+extern gnutls_certificate_credentials_t xcred;
+#define CAFILE "ca.pem"
 #endif
 
 typedef struct ptstream {
 	int incoming_fd;
 	int outgoing_fd;
+	int ssl;
 #ifdef USE_SSL
-	SSL *ssl;
-	SSL_CTX *ctx;
-#else
-	void *ssl;
-	void *ctx;
+	gnutls_session_t session;
 #endif
 } PTSTREAM;
 
