about summary refs log tree commit diff stats
path: root/WWW/Library/Implementation
diff options
context:
space:
mode:
authorThomas E. Dickey <dickey@invisible-island.net>2001-01-02 01:53:43 -0500
committerThomas E. Dickey <dickey@invisible-island.net>2001-01-02 01:53:43 -0500
commitd31fb3c41be5d6e079d415087eda3c03cc34bcdb (patch)
tree76faa032cec14cb8e3500f25c1074eacc56c1c7e /WWW/Library/Implementation
parent244b955fa0312faea2e138d55330bd9a81fd92de (diff)
downloadlynx-snapshots-d31fb3c41be5d6e079d415087eda3c03cc34bcdb.tar.gz
snapshot of project "lynx", label v2-8-4dev_16
Diffstat (limited to 'WWW/Library/Implementation')
-rw-r--r--WWW/Library/Implementation/HTAAUtil.c11
-rw-r--r--WWW/Library/Implementation/HTFormat.c40
-rw-r--r--WWW/Library/Implementation/HTMLDTD.c3
-rw-r--r--WWW/Library/Implementation/HTNews.c167
-rw-r--r--WWW/Library/Implementation/HTNews.h14
-rw-r--r--WWW/Library/Implementation/HTTP.c273
-rw-r--r--WWW/Library/Implementation/HTUtils.h52
7 files changed, 552 insertions, 8 deletions
diff --git a/WWW/Library/Implementation/HTAAUtil.c b/WWW/Library/Implementation/HTAAUtil.c
index ecfb04e1..25d24aa6 100644
--- a/WWW/Library/Implementation/HTAAUtil.c
+++ b/WWW/Library/Implementation/HTAAUtil.c
@@ -50,6 +50,10 @@
 #include <HTTCP.h>
 #include <HTTP.h>
 
+#ifdef USE_SSL
+PRIVATE SSL * Handle = NULL;	/* The SSL Handle	*/
+#endif /* USE_SSL */
+
 #include <LYStrings.h>
 #include <LYLeaks.h>
 
@@ -555,7 +559,14 @@ PUBLIC char *HTAA_getUnfoldedLine NOARGS
 	/* Reading from socket */
 
 	if (start_pointer >= end_pointer) {/*Read the next block and continue*/
+#ifdef USE_SSL
+	    if (Handle)
+		count = SSL_read(Handle, buffer, BUFFER_SIZE);
+	    else
+		count = NETREAD(in_soc, buffer, BUFFER_SIZE);
+#else
 	    count = NETREAD(in_soc, buffer, BUFFER_SIZE);
+#endif /* USE_SSL */
 	    if (count <= 0) {
 		in_soc = -1;
 		return line;
diff --git a/WWW/Library/Implementation/HTFormat.c b/WWW/Library/Implementation/HTFormat.c
index c589749d..1148e308 100644
--- a/WWW/Library/Implementation/HTFormat.c
+++ b/WWW/Library/Implementation/HTFormat.c
@@ -259,6 +259,39 @@ PUBLIC int HTGetCharacter NOARGS
     return FROMASCII(UCH(ch));
 }
 
+#ifdef USE_SSL
+PUBLIC char HTGetSSLCharacter ARGS1(void *, handle)
+{
+    char ch;
+    interrupted_in_htgetcharacter = 0;
+    if(!handle)
+	return (char)EOF;
+    do {
+	if (input_pointer >= input_limit) {
+	    int status = SSL_read((SSL *)handle,
+				 input_buffer, INPUT_BUFFER_SIZE);
+	    if (status <= 0) {
+		if (status == 0)
+		    return (char)EOF;
+		if (status == HT_INTERRUPTED) {
+		    CTRACE((tfp, "HTFormat: Interrupted in HTGetSSLCharacter\n"));
+		    interrupted_in_htgetcharacter = 1;
+		    return (char)EOF;
+		}
+		CTRACE((tfp, "HTFormat: SSL_read error %d\n", status));
+		return (char)EOF; /* -1 is returned by UCX
+				     at end of HTTP link */
+	    }
+	    input_pointer = input_buffer;
+	    input_limit = input_buffer + status;
+	}
+	ch = *input_pointer++;
+    } while (ch == (char) 13); /* Ignore ASCII carriage return */
+
+    return FROMASCII(ch);
+}
+#endif /* USE_SSL */
+
 /*  Match maintype to any MIME type starting with maintype,
  *  for example:  image/gif should match image
  */
@@ -641,7 +674,14 @@ PUBLIC int HTCopy ARGS4(
 	    goto finished;
 	}
 
+#ifdef USE_SSL
+	if (handle)
+	    status = SSL_read((SSL *)handle, input_buffer, INPUT_BUFFER_SIZE);
+	else
+	    status = NETREAD(file_number, input_buffer, INPUT_BUFFER_SIZE);
+#else
 	status = NETREAD(file_number, input_buffer, INPUT_BUFFER_SIZE);
+#endif /* USE_SSL */
 
 	if (status <= 0) {
 	    if (status == 0) {
diff --git a/WWW/Library/Implementation/HTMLDTD.c b/WWW/Library/Implementation/HTMLDTD.c
index 3b9d9353..981bc989 100644
--- a/WWW/Library/Implementation/HTMLDTD.c
+++ b/WWW/Library/Implementation/HTMLDTD.c
@@ -1365,6 +1365,9 @@ static attr ulist_attr[] = {		/* UL attributes */
 **
 **    Name*,	Attributes,	No. of attributes,     content,   extra info...
 */
+#undef P
+#undef P
+#undef P_
 #ifdef USE_COLOR_STYLE
 #define P_(x) x , (sizeof x) -1
 #define NULL_HTTag_ NULL, 0
diff --git a/WWW/Library/Implementation/HTNews.c b/WWW/Library/Implementation/HTNews.c
index ded9af8c..b404733b 100644
--- a/WWW/Library/Implementation/HTNews.c
+++ b/WWW/Library/Implementation/HTNews.c
@@ -34,9 +34,21 @@ PUBLIC int HTNewsMaxChunk = 40; /* Largest number of articles in one window */
 #define SERVER_FILE "/usr/local/lib/rn/server"
 #endif /* SERVER_FILE */
 
+#ifdef USE_SSL
+extern SSL_CTX * ssl_ctx;
+PRIVATE SSL * Handle = NULL;
+PRIVATE int channel_s = 1;
+#define NEWS_NETWRITE(sock, buff, size) \
+	(Handle ? SSL_write(Handle, buff, size) : NETWRITE(sock, buff, size))
+#define NEWS_NETCLOSE(sock) \
+	{ (void)NETCLOSE(sock); if (Handle) SSL_free(Handle); Handle = NULL; }
+PRIVATE char HTNewsGetCharacter NOPARAMS;
+#define NEXT_CHAR HTNewsGetCharacter()
+#else
 #define NEWS_NETWRITE  NETWRITE
 #define NEWS_NETCLOSE  NETCLOSE
 #define NEXT_CHAR HTGetCharacter()
+#endif /* USE_SSL */
 
 #include <HTML.h>
 #include <HTParse.h>
@@ -2147,6 +2159,9 @@ PRIVATE int HTLoadNews ARGS4(
     char *ProxyHost = NULL;
     char *ProxyHREF = NULL;
     char *postfile = NULL;
+#ifdef USE_SSL
+    char SSLprogress[256];
+#endif /* USE_SSL */
 
     diagnostic = (format_out == WWW_SOURCE ||	/* set global flag */
 		  format_out == HTAtom_for("www/download") ||
@@ -2195,11 +2210,13 @@ PRIVATE int HTLoadNews ARGS4(
 			  group_wanted) &&
 			strchr(arg, '@') == NULL) && (strchr(arg, '*') != NULL));
 
+#ifndef USE_SSL
 	if (!strncasecomp(arg, "snewspost:", 10) ||
 	    !strncasecomp(arg, "snewsreply:", 11)) {
 	    HTAlert(FAILED_CANNOT_POST_SSL);
 	    return HT_NOT_LOADED;
 	}
+#endif /* !USE_SSL */
 	if (post_wanted || reply_wanted || spost_wanted || sreply_wanted) {
 	    /*
 	    **	Make sure we have a non-zero path for the newsgroup(s). - FM
@@ -2287,8 +2304,43 @@ PRIVATE int HTLoadNews ARGS4(
 	    StrAllocCopy(NewsHREF, command);
 	}
 	else if (!strncasecomp(arg, "snews:", 6)) {
+#ifdef USE_SSL
+	    if (((*(arg + 6) == '\0') ||
+		 (!strcmp((arg + 6), "/") ||
+		  !strcmp((arg + 6), "//") ||
+		  !strcmp((arg + 6), "///"))) ||
+		((!strncmp((arg + 6), "//", 2)) &&
+		 (!(cp = strchr((arg + 8), '/')) || *(cp + 1) == '\0'))) {
+		p1 = "*";
+		group_wanted = FALSE;
+		list_wanted = TRUE;
+	    } else if (*(arg + 6) != '/') {
+		p1 = (arg + 6);
+	    } else if (*(arg + 6) == '/' && *(arg + 7) != '/') {
+		p1 = (arg + 7);
+	    } else {
+		p1 = (cp + 1);
+	    }
+	    if (!(cp = HTParse(arg, "", PARSE_HOST)) || *cp == '\0') {
+		if (s >= 0 && NewsHost && strcasecomp(NewsHost, HTNewsHost)) {
+		    NEWS_NETCLOSE(s);
+		    s = -1;
+		}
+		StrAllocCopy(NewsHost, HTNewsHost);
+	    } else {
+		if (s >= 0 && NewsHost && strcasecomp(NewsHost, cp)) {
+		    NEWS_NETCLOSE(s);
+		    s = -1;
+		}
+	    StrAllocCopy(NewsHost, cp);
+	    }
+	    FREE(cp);
+	    sprintf(command, "snews://%.250s/", NewsHost);
+	    StrAllocCopy(NewsHREF, command);
+#else
 	    HTAlert(gettext("This client does not contain support for SNEWS URLs."));
 	    return HT_NOT_LOADED;
+#endif /* USE_SSL */
 	}
 	else if (!strncasecomp (arg, "news:/", 6)) {
 	    if (((*(arg + 6) == '\0') ||
@@ -2526,7 +2578,18 @@ PRIVATE int HTLoadNews ARGS4(
 
 	    _HTProgress(gettext("Connecting to NewsHost ..."));
 
+#ifdef USE_SSL
+	    if (!using_proxy &&
+		(!strncmp(arg, "snews:", 6) ||
+		 !strncmp(arg, "snewspost:", 10) ||
+		 !strncmp(arg, "snewsreply:", 11)))
+		status = HTDoConnect (url, "NNTPS", SNEWS_PORT, &s);
+	    else
+		status = HTDoConnect (url, "NNTP", NEWS_PORT, &s);
+#else
 	    status = HTDoConnect (url, "NNTP", NEWS_PORT, &s);
+#endif /* USE_SSL */
+
 	    if (status == HT_INTERRUPTED) {
 		/*
 		**  Interrupt cleanly.
@@ -2542,6 +2605,12 @@ PRIVATE int HTLoadNews ARGS4(
 		FREE(ProxyHost);
 		FREE(ProxyHREF);
 		FREE(ListArg);
+#ifdef USE_SSL
+		if (Handle) {
+		    SSL_free(Handle);
+		    Handle = NULL;
+		}
+#endif /* USE_SSL */
 		if (postfile) {
 		    HTSYS_remove(postfile);
 		    FREE(postfile);
@@ -2572,6 +2641,54 @@ PRIVATE int HTLoadNews ARGS4(
 	    } else {
 		CTRACE((tfp, "HTNews: Connected to news host %s.\n",
 			    NewsHost));
+#ifdef USE_SSL
+		/*
+		**  If this is an snews url,
+		**  then do the SSL stuff here
+		*/
+		if (!using_proxy &&
+		    (!strncmp(url, "snews", 5) ||
+		     !strncmp(url, "snewspost:", 10) ||
+		     !strncmp(url, "snewsreply:", 11))) {
+		    Handle = HTGetSSLHandle();
+		    SSL_set_fd(Handle, s);
+		    HTSSLInitPRNG();
+		    status = SSL_connect(Handle);
+
+		    if (status <= 0) {
+			unsigned long SSLerror;
+			CTRACE((tfp,"HTNews: Unable to complete SSL handshake for '%s', SSL_connect=%d, SSL error stack dump follows\n",url, status));
+			SSL_load_error_strings();
+			while((SSLerror = ERR_get_error()) != 0) {
+			    CTRACE((tfp,"HTNews: SSL: %s\n",ERR_error_string(SSLerror,NULL)));
+			}
+			HTAlert(
+			    "Unable to make secure connection to remote host.");
+			NEWS_NETCLOSE(s);
+			s = -1;
+			if (!(post_wanted || reply_wanted ||
+			      spost_wanted || sreply_wanted))
+			    (*targetClass._abort)(target, NULL);
+			FREE(NewsHost);
+			FREE(NewsHREF);
+			FREE(ProxyHost);
+			FREE(ProxyHREF);
+			FREE(ListArg);
+			if (postfile) {
+#ifdef VMS
+			    while (remove(postfile) == 0)
+			    ; /* loop through all versions */
+#else
+			    remove(postfile);
+#endif /* VMS */
+			    FREE(postfile);
+			}
+			return HT_NOT_LOADED;
+		    }
+		    sprintf(SSLprogress,"Secure %d-bit %s (%s) NNTP connection",SSL_get_cipher_bits(Handle,NULL),SSL_get_cipher_version(Handle),SSL_get_cipher(Handle));
+		    _HTProgress(SSLprogress);
+		}
+#endif /* USE_SSL */
 		HTInitInput(s);		/* set up buffering */
 		if (proxycmd[0]) {
 		    status = NEWS_NETWRITE(s, proxycmd, strlen(proxycmd));
@@ -2922,6 +3039,56 @@ PUBLIC void HTClearNNTPAuthInfo NOARGS
     free_NNTP_AuthInfo();
 }
 
+#ifdef USE_SSL
+PRIVATE char HTNewsGetCharacter NOARGS
+{
+    if (!Handle)
+	return HTGetCharacter();
+    else
+	return HTGetSSLCharacter((void *)Handle);
+}
+
+PUBLIC int HTNewsProxyConnect ARGS5 (
+    int,		sock,
+    CONST char *,	url,
+    HTParentAnchor *,	anAnchor,
+    HTFormat,		format_out,
+    HTStream *,		sink)
+{
+    int status;
+    CONST char * arg = url;
+    char SSLprogress[256];
+
+    s = channel_s = sock;
+    Handle = HTGetSSLHandle();
+    SSL_set_fd(Handle, s);
+    HTSSLInitPRNG();
+    status = SSL_connect(Handle);
+
+    if (status <= 0) {
+	unsigned long SSLerror;
+	channel_s = -1;
+	CTRACE((tfp,"HTNews: Unable to complete SSL handshake for '%s', SSL_connect=%d, SSL error stack dump follows\n",url, status));
+	SSL_load_error_strings();
+	while((SSLerror = ERR_get_error()) != 0) {
+	    CTRACE((tfp,"HTNews: SSL: %s\n",ERR_error_string(SSLerror,NULL)));
+	}
+	HTAlert("Unable to make secure connection to remote host.");
+	NEWS_NETCLOSE(s);
+	s = -1;
+	return HT_NOT_LOADED;
+    }
+    sprintf(SSLprogress,"Secure %d-bit %s (%s) NNTP connection",
+	    SSL_get_cipher_bits(Handle,NULL),
+	    SSL_get_cipher_version(Handle),
+	    SSL_get_cipher(Handle));
+    _HTProgress(SSLprogress);
+    status = HTLoadNews(arg, anAnchor, format_out, sink);
+    channel_s = -1;
+    return status;
+}
+#endif /* USE_SSL */
+
 #ifdef GLOBALDEF_IS_MACRO
 #define _HTNEWS_C_1_INIT { "news", HTLoadNews, NULL }
 GLOBALDEF (HTProtocol,HTNews,_HTNEWS_C_1_INIT);
diff --git a/WWW/Library/Implementation/HTNews.h b/WWW/Library/Implementation/HTNews.h
index 7cd930a4..92bf7f33 100644
--- a/WWW/Library/Implementation/HTNews.h
+++ b/WWW/Library/Implementation/HTNews.h
@@ -41,9 +41,13 @@ extern char * HTNewsHost;
 
 extern void HTClearNNTPAuthInfo NOPARAMS;
 
-#endif /* HTNEWS_H */
-
+#ifdef USE_SSL
+extern int HTNewsProxyConnect PARAMS ((
+	int		sock,
+	CONST char *	url,
+	HTParentAnchor *anAnchor,
+	HTFormat	format_out,
+	HTStream *	sink));
+#endif
 
-/*
-
-   tbl */
+#endif /* HTNEWS_H */
diff --git a/WWW/Library/Implementation/HTTP.c b/WWW/Library/Implementation/HTTP.c
index 89aa7045..7c792ef6 100644
--- a/WWW/Library/Implementation/HTTP.c
+++ b/WWW/Library/Implementation/HTTP.c
@@ -13,6 +13,10 @@
 #include <HTTP.h>
 #include <LYUtils.h>
 
+#ifdef USE_SSL
+#include <HTNews.h>
+#endif
+
 #define HTTP_VERSION	"HTTP/1.0"
 
 #define HTTP_PORT   80
@@ -67,9 +71,85 @@ extern char *http_error_file;	 /* Store HTTP status code in this file */
 extern BOOL traversal;		 /* TRUE if we are doing a traversal */
 extern BOOL dump_output_immediately;  /* TRUE if no interactive user */
 
+#ifdef USE_SSL
+PUBLIC SSL_CTX * ssl_ctx = NULL;	/* SSL ctx */
+
+PRIVATE void free_ssl_ctx NOARGS
+{
+    if (ssl_ctx != NULL)
+	SSL_CTX_free(ssl_ctx);
+}
+
+PUBLIC SSL * HTGetSSLHandle NOARGS
+{
+    if (ssl_ctx == NULL) {
+	/*
+	 *  First time only.
+	 */
+#if SSLEAY_VERSION_NUMBER < 0x0800
+	ssl_ctx = SSL_CTX_new();
+	X509_set_default_verify_paths(ssl_ctx->cert);
+#else
+	SSLeay_add_ssl_algorithms();
+	ssl_ctx = SSL_CTX_new(SSLv23_client_method());
+	SSL_CTX_set_options(ssl_ctx, SSL_OP_ALL);
+	SSL_CTX_set_default_verify_paths(ssl_ctx);
+#endif /* SSLEAY_VERSION_NUMBER < 0x0800 */
+	atexit(free_ssl_ctx);
+    }
+    return(SSL_new(ssl_ctx));
+}
+
+PUBLIC void HTSSLInitPRNG NOARGS
+{
+#if SSLEAY_VERSION_NUMBER >= 0x00905100
+    if (RAND_status() == 0) {
+	char rand_file[256];
+	time_t t;
+	pid_t pid;
+	long l,seed;
+
+	t = time(NULL);
+	pid = getpid();
+	RAND_file_name(rand_file, 256);
+	CTRACE((tfp,"HTTP: Seeding PRNG\n"));
+	if(rand_file != NULL) {
+	    /* Seed as much as 1024 bytes from RAND_file_name */
+	    RAND_load_file(rand_file, 1024);
+	}
+	/* Seed in time (mod_ssl does this) */
+	RAND_seed((unsigned char *)&t, sizeof(time_t));
+	/* Seed in pid (mod_ssl does this) */
+	RAND_seed((unsigned char *)&pid, sizeof(pid_t));
+	/* Initialize system's random number generator */
+	RAND_bytes((unsigned char *)&seed, sizeof(long));
+	srand48(seed);
+	while (RAND_status() == 0) {
+	    /* Repeatedly seed the PRNG using the system's random number generator until it has been seeded with enough data */
+	    l = lrand48();
+	    RAND_seed((unsigned char *)&l, sizeof(long));
+	}
+	if (rand_file != NULL) {
+	    /* Write a rand_file */
+	    RAND_write_file(rand_file);
+	}
+    }
+#endif /* SSLEAY_VERSION_NUMBER >= 0x00905100 */
+    return;
+}
+
+#define HTTP_NETREAD(sock, buff, size, handle) \
+	(handle ? SSL_read(handle, buff, size) : NETREAD(sock, buff, size))
+#define HTTP_NETWRITE(sock, buff, size, handle) \
+	(handle ? SSL_write(handle, buff, size) : NETWRITE(sock, buff, size))
+#define HTTP_NETCLOSE(sock, handle)  \
+	{ (void)NETCLOSE(sock); if (handle) SSL_free(handle); handle = NULL; }
+
+#else
 #define HTTP_NETREAD(a, b, c, d)   NETREAD(a, b, c)
 #define HTTP_NETWRITE(a, b, c, d)  NETWRITE(a, b, c)
 #define HTTP_NETCLOSE(a, b)  (void)NETCLOSE(a)
+#endif /* USE_SSL */
 
 #ifdef _WINDOWS		/* 1997/11/06 (Thu) 13:00:08 */
 
@@ -299,7 +379,19 @@ PRIVATE int HTLoadHTTP ARGS4 (
   BOOL doing_redirect, already_retrying = FALSE;
   int len = 0;
 
+#ifdef USE_SSL
+  BOOL do_connect = FALSE;	/* ARE WE going to use a proxy tunnel ? */
+  BOOL did_connect = FALSE;	/* ARE WE actually using a proxy tunnel ? */
+  CONST char *connect_url = NULL; /* The URL being proxied */
+  char *connect_host = NULL;	/* The host being proxied */
+  SSL * handle = NULL;		/* The SSL handle */
+  char SSLprogress[256];	/* progress bar message */
+#if SSLEAY_VERSION_NUMBER >= 0x0900
+  BOOL try_tls = TRUE;
+#endif /* SSLEAY_VERSION_NUMBER >= 0x0900 */
+#else
   void * handle = NULL;
+#endif /* USE_SSL */
 
   if (anAnchor->isHEAD)
       do_head = TRUE;
@@ -317,6 +409,30 @@ PRIVATE int HTLoadHTTP ARGS4 (
       goto done;
   }
 
+#ifdef USE_SSL
+  if (using_proxy && !strncmp(url, "http://", 7)) {
+      if ((connect_url = strstr((url+7), "https://"))) {
+	  do_connect = TRUE;
+	  connect_host = HTParse(connect_url, "https", PARSE_HOST);
+	  if (!strchr(connect_host, ':')) {
+	      sprintf(temp, ":%d", HTTPS_PORT);
+	      StrAllocCat(connect_host, temp);
+	  }
+	  CTRACE((tfp, "HTTP: connect_url = '%s'\n", connect_url));
+	  CTRACE((tfp, "HTTP: connect_host = '%s'\n", connect_host));
+      } else if ((connect_url = strstr((url+7), "snews://"))) {
+	  do_connect = TRUE;
+	  connect_host = HTParse(connect_url, "snews", PARSE_HOST);
+	  if (!strchr(connect_host, ':')) {
+	      sprintf(temp, ":%d", SNEWS_PORT);
+	      StrAllocCat(connect_host, temp);
+	  }
+	  CTRACE((tfp, "HTTP: connect_url = '%s'\n", connect_url));
+	  CTRACE((tfp, "HTTP: connect_host = '%s'\n", connect_host));
+      }
+  }
+#endif /* USE_SSL */
+
   sprintf(crlf, "%c%c", CR, LF);
 
   /*
@@ -340,12 +456,18 @@ try_again:
   line_kept_clean = NULL;
 
   if (!strncmp(url, "https", 5))
+#ifdef USE_SSL
+    status = HTDoConnect (url, "HTTPS", HTTPS_PORT, &s);
+  else
+    status = HTDoConnect (url, "HTTP", HTTP_PORT, &s);
+#else
     {
       HTAlert(gettext("This client does not contain support for HTTPS URLs."));
       status = HT_NOT_LOADED;
       goto done;
     }
   status = HTDoConnect (arg, "HTTP", HTTP_PORT, &s);
+#endif /* USE_SSL */
   if (status == HT_INTERRUPTED) {
       /*
       **  Interrupt cleanly.
@@ -375,12 +497,91 @@ try_again:
  * This is a nice long function as well.  *sigh*  -RJP
  */
 
+#ifdef USE_SSL
+use_tunnel:
+  /*
+  ** If this is an https document
+  ** then do the SSL stuff here
+  */
+  if (did_connect || !strncmp(url, "https", 5)) {
+      handle = HTGetSSLHandle();
+      SSL_set_fd(handle, s);
+#if SSLEAY_VERSION_NUMBER >= 0x0900
+      if (!try_tls)
+	  handle->options|=SSL_OP_NO_TLSv1;
+#endif /* SSLEAY_VERSION_NUMBER >= 0x0900 */
+      HTSSLInitPRNG();
+      status = SSL_connect(handle);
+
+      if (status <= 0) {
+#if SSLEAY_VERSION_NUMBER >= 0x0900
+	  if (try_tls) {
+	      CTRACE((tfp, "HTTP: Retrying connection without TLS\n"));
+	      _HTProgress("Retrying connection.");
+	      try_tls = FALSE;
+	      if (did_connect)
+		  HTTP_NETCLOSE(s, handle);
+      	      goto try_again;
+	  } else {
+	      unsigned long SSLerror;
+	      CTRACE((tfp,
+"HTTP: Unable to complete SSL handshake for '%s', SSL_connect=%d, SSL error stack dump follows\n",
+				url, status));
+	      SSL_load_error_strings();
+	      while((SSLerror=ERR_get_error())!=0) {
+		  CTRACE((tfp,"HTTP: SSL: %s\n",ERR_error_string(SSLerror,NULL)));
+	      }
+      	      HTAlert("Unable to make secure connection to remote host.");
+	      if (did_connect)
+		  HTTP_NETCLOSE(s, handle);
+      	      status = HT_NOT_LOADED;
+      	      goto done;
+	  }
+#else
+	  unsigned long SSLerror;
+	  CTRACE((tfp,
+"HTTP: Unable to complete SSL handshake for '%s', SSL_connect=%d, SSL error stack dump follows\n",
+				url, status));
+	  SSL_load_error_strings();
+	  while((SSLerror=ERR_get_error())!=0) {
+	      CTRACE((tfp,"HTTP: SSL: %s\n",ERR_error_string(SSLerror,NULL)));
+	  }
+      	  HTAlert("Unable to make secure connection to remote host.");
+	  if (did_connect)
+	      HTTP_NETCLOSE(s, handle);
+      	  status = HT_NOT_LOADED;
+      	  goto done;
+#endif /* SSLEAY_VERSION_NUMBER >= 0x0900 */
+      }
+      sprintf(SSLprogress,"Secure %d-bit %s (%s) HTTP connection",SSL_get_cipher_bits(handle,NULL),SSL_get_cipher_version(handle),SSL_get_cipher(handle));
+      _HTProgress(SSLprogress);
+
+#ifdef NOTDEFINED
+      if (strcmp(HTParse(url, "", PARSE_HOST),
+      		 strstr(X509_NAME_oneline(
+		 	X509_get_subject_name(
+				handle->session->peer)),"/CN=")+4)) {
+	  HTAlert("Certificate is for different host name");
+	  HTAlert(strstr(X509_NAME_oneline(
+	  		 X509_get_subject_name(
+			 	handle->session->peer)),"/CN=")+4);
+      }
+#endif /* NOTDEFINED */
+  }
+#endif /* USE_SSL */
+
   /*	Ask that node for the document,
   **	omitting the host name & anchor
   */
   {
     char * p1 = (HTParse(url, "", PARSE_PATH|PARSE_PUNCTUATION));
 
+#ifdef USE_SSL
+    if (do_connect) {
+	METHOD = "CONNECT";
+	StrAllocCopy(command, "CONNECT ");
+    } else
+#endif /* USE_SSL */
     if (do_post) {
 	METHOD = "POST";
 	StrAllocCopy(command, "POST ");
@@ -397,8 +598,17 @@ try_again:
     **	of say: /gopher://a;lkdjfl;ajdf;lkj/;aldk/adflj
     **	so that just gopher://.... is sent.
     */
+#ifdef USE_SSL
+    if (using_proxy && !did_connect) {
+	if (do_connect)
+	    StrAllocCat(command, connect_host);
+	else
+	    StrAllocCat(command, p1+1);
+    }
+#else
     if (using_proxy)
 	StrAllocCat(command, p1+1);
+#endif /* USE_SSL */
     else
 	StrAllocCat(command, p1);
     FREE(p1);
@@ -638,6 +848,10 @@ try_again:
 		} else {
 		    if (traversal || dump_output_immediately)
 			HTAlert(FAILED_NEED_PASSWD);
+#ifdef USE_SSL
+		    if (did_connect)
+			HTTP_NETCLOSE(s, handle);
+#endif /* USE_SSL */
 		    FREE(command);
 		    FREE(hostname);
 		    FREE(docname);
@@ -752,7 +966,11 @@ try_again:
       auth_proxy = NO;
   }
 
-    if (do_post) {
+    if (
+#ifdef USE_SSL
+	!do_connect &&
+#endif /* USE_SSL */
+	do_post) {
 	CTRACE((tfp, "HTTP: Doing post, content-type '%s'\n",
 		     anAnchor->post_content_type ? anAnchor->post_content_type
 						 : "lose"));
@@ -776,11 +994,17 @@ try_again:
 	StrAllocCat(command, anAnchor->post_data);
     }
     else
-        StrAllocCat(command, crlf);	/* Blank line means "end" of headers */
+	StrAllocCat(command, crlf);	/* Blank line means "end" of headers */
 
+#ifdef USE_SSL
+  CTRACE((tfp, "Writing:\n%s%s----------------------------------\n",
+	       command,
+	       (anAnchor->post_data && !do_connect ? crlf : "")));
+#else
   CTRACE((tfp, "Writing:\n%s%s----------------------------------\n",
 	       command,
 	       (anAnchor->post_data ? crlf : "")));
+#endif /* USE_SSL */
 
   _HTProgress (gettext("Sending HTTP request."));
 
@@ -1143,6 +1367,35 @@ try_again:
 		 *  > 206 is unknown.
 		 *  All should return something to display.
 		 */
+#ifdef USE_SSL
+		if (do_connect) {
+		    CTRACE((tfp, "HTTP: Proxy tunnel to '%s' established.\n",
+				connect_host));
+		    do_connect = FALSE;
+		    url = connect_url;
+		    FREE(line_buffer);
+		    FREE(line_kept_clean);
+		    if (!strncmp(connect_url, "snews", 5)) {
+			CTRACE((tfp,
+			"      Will attempt handshake and snews connection.\n"));
+			status = HTNewsProxyConnect(s, url, anAnchor,
+						    format_out, sink);
+			goto done;
+		    }
+		    did_connect = TRUE;
+		    already_retrying = TRUE;
+		    eol = 0;
+		    bytes_already_read = 0;
+		    had_header = NO;
+		    length = 0;
+		    doing_redirect = FALSE;
+		    permanent_redirection = FALSE;
+		    target = NULL;
+		    CTRACE((tfp,
+			"      Will attempt handshake and resubmit headers.\n"));
+		    goto use_tunnel;
+		}
+#endif /* USE_SSL */
 		HTProgress(line_buffer);
 	    } /* case 2 switch */
 	    break;
@@ -1337,6 +1590,13 @@ try_again:
 			gettext("Retrying with access authorization information."));
 		    FREE(line_buffer);
 		    FREE(line_kept_clean);
+#ifdef USE_SSL
+		    if (using_proxy && !strncmp(url, "https://", 8)) {
+			url = arg;
+			do_connect = TRUE;
+			did_connect = FALSE;
+		    }
+#endif /* USE_SSL */
 		    goto try_again;
 		} else if (!(traversal || dump_output_immediately) &&
 			   HTConfirm(gettext("Show the 401 message body?"))) {
@@ -1771,6 +2031,15 @@ done:
   do_head = FALSE;
   do_post = FALSE;
   reloading = FALSE;
+#ifdef USE_SSL
+  do_connect = FALSE;
+  did_connect = FALSE;
+  FREE(connect_host);
+  if (handle) {
+    SSL_free(handle);
+    handle = NULL;
+  }
+#endif /* USE_SSL */
   return status;
 }
 
diff --git a/WWW/Library/Implementation/HTUtils.h b/WWW/Library/Implementation/HTUtils.h
index 036ed2fd..ee787194 100644
--- a/WWW/Library/Implementation/HTUtils.h
+++ b/WWW/Library/Implementation/HTUtils.h
@@ -17,7 +17,7 @@
 #include <sys/types.h>
 #include <stdio.h>
 
-#else
+#else  /* HAVE_CONFIG_H */
 
 #ifdef DJGPP
 #include <sys/config.h>	/* pseudo-autoconf values for DJGPP libc/headers */
@@ -102,6 +102,14 @@
 
 #endif /* HAVE_CONFIG_H */
 
+#if '0' != 48
+#define NOT_ASCII
+#endif
+
+#if '0' == 240
+#define EBCDIC
+#endif
+
 #ifndef LY_MAXPATH
 #define LY_MAXPATH 256
 #endif
@@ -507,10 +515,52 @@ extern FILE *TraceFP NOPARAMS;
 #define Rgetpeername  getpeername
 #endif
 
+/*
+ * Workaround for order-of-evaluation problem with gcc and socks5 headers
+ * which breaks the Rxxxx names by attaching the prefix twice:
+ */
+#ifdef INCLUDE_PROTOTYPES
+#undef  Raccept
+#undef  Rbind
+#undef  Rconnect
+#undef  Rlisten
+#undef  Rselect
+#undef  Rgetpeername
+#undef  Rgetsockname
+#define Raccept       accept
+#define Rbind         bind
+#define Rconnect      connect
+#define Rgetpeername  getpeername
+#define Rgetsockname  getsockname
+#define Rlisten       listen
+#define Rselect       select
+#endif
+
 #endif /* USE_SOCKS5 */
 
 #define SHORTENED_RBIND	/* FIXME: do this in configure-script */
 
+#ifdef USE_SSL
+#define free_func free__func
+#ifdef USE_OPENSSL_INCL
+#include <openssl/ssl.h>
+#include <openssl/crypto.h>
+#include <openssl/rand.h>
+#include <openssl/err.h>
+#else
+#include <ssl.h>
+#include <crypto.h>
+#include <rand.h>
+#include <err.h>
+#endif
+#undef free_func
+
+extern SSL * HTGetSSLHandle NOPARAMS;
+extern void HTSSLInitPRNG NOPARAMS;
+extern char HTGetSSLCharacter PARAMS((void * handle));
+
+#endif /* USE_SSL */
+
 #include <userdefs.h>
 
 #endif /* HTUTILS_H */