bug-wget
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Bug-wget] [PATCH] TLS SNI support


From: Phil Pennock
Subject: [Bug-wget] [PATCH] TLS SNI support
Date: Tue, 31 Mar 2009 17:52:59 -0700

Please find attached a fairly short patch to let wget use the TLS
extension for Server Name Indication, to be compatible with vhosting of
SSL sites.  Most modern graphical browsers now support SNI.

Patch is against wget 1.11.4.

The length of this patch is short enough that I do not believe any
copyright assignment is necessary.  If the maintainers feel otherwise,
then I'll discuss it with my employer who have some kind of process set
up for this with FSF -- but I'd really prefer to avoid the overhead.
I'm mostly just throwing this out there.

I've tested the OpenSSL build of this patch, but not the GnuTLS build.
I couldn't see any versioning information as to when
gnutls_server_name_set was added to gnutls, so I've just used it without
guards.  For OpenSSL, the version must be at least 0x0090806fL (0.9.8f)
and OPENSSL_NO_TLSEXT must not be defined.  Thus if OpenSSL was built
with "enable-tlsext" in EXTRACONFIGURE then wget will automatically gain
support.

With this patch, wget basically adds some extra information to the TLS
handshake to indicate the hostname to which it's connecting (RFC 4366,
and RFC 3546 before that).  I've tested that this works with Apache
httpd 2.2.x built with the SNI patch from https://sni.velox.ch/ -- this
appears to have been accepted into the Apache httpd trunk.

Total work:
 * pass hostname to ssl_connect
 * let ssl_connect check that the hostname is not an IP address by
   exposing functionality from host.c
 * call the appropriate library function to pass this on.

I'm very interested in feedback on whether or not the gnutls variant
works.

OpenSSL variant tested on FreeBSD 7.0/amd64 with OpenSSL 0.9.8k.

Thanks,
-Phil
--- src/gnutls.c.pre-pdp        2009-04-01 00:02:50.000000000 +0000
+++ src/gnutls.c        2009-04-01 00:28:00.000000000 +0000
@@ -45,6 +45,7 @@ as that of the covered work.  */
 #include "connect.h"
 #include "url.h"
 #include "ssl.h"
+#include "host.h"
 
 /* Note: some of the functions private to this file have names that
    begin with "wgnutls_" (e.g. wgnutls_read) so that they wouldn't be
@@ -181,7 +182,7 @@ static struct transport_implementation w
 };
 
 bool
-ssl_connect (int fd) 
+ssl_connect (int fd, const char *hostname) 
 {
   static const int cert_type_priority[] = {
     GNUTLS_CRT_X509, GNUTLS_CRT_OPENPGP, 0
@@ -189,8 +190,17 @@ ssl_connect (int fd) 
   struct wgnutls_transport_context *ctx;
   gnutls_session session;
   int err;
+
   gnutls_init (&session, GNUTLS_CLIENT);
   gnutls_set_default_priority (session);
+
+  /* We set the server name but only if it's not an IP address. */
+  if (!is_ip_address(hostname))
+    {
+      gnutls_server_name_set (session, GNUTLS_NAME_DNS,
+         hostname, strlen(hostname));
+    }
+
   gnutls_certificate_type_set_priority (session, cert_type_priority);
   gnutls_credentials_set (session, GNUTLS_CRD_CERTIFICATE, credentials);
   gnutls_transport_set_ptr (session, (gnutls_transport_ptr) fd);
--- src/host.c.pre-pdp  2009-04-01 00:20:23.000000000 +0000
+++ src/host.c  2009-04-01 00:29:39.000000000 +0000
@@ -878,3 +878,19 @@ host_cleanup (void)
       host_name_addresses_map = NULL;
     }
 }
+
+/* Determine whether or not a hostname is an IP address that we recognise. */
+bool
+is_ip_address (const char *name)
+{
+  const char *endp;
+
+  endp = name + strlen(name);
+  if (is_valid_ipv4_address(name, endp))
+    return true;
+#ifdef ENABLE_IPV6
+  if (is_valid_ipv4_address(name, endp))
+    return true;
+#endif
+  return false;
+}
--- src/host.h.pre-pdp  2009-04-01 00:20:19.000000000 +0000
+++ src/host.h  2009-04-01 00:20:53.000000000 +0000
@@ -98,4 +98,6 @@ bool sufmatch (const char **, const char
 
 void host_cleanup (void);
 
+bool is_ip_address(const char *);
+
 #endif /* HOST_H */
--- src/http.c.pre-pdp  2009-04-01 00:02:38.000000000 +0000
+++ src/http.c  2009-04-01 00:03:20.000000000 +0000
@@ -1732,7 +1732,7 @@ gethttp (struct url *u, struct http_stat
 
       if (conn->scheme == SCHEME_HTTPS)
         {
-          if (!ssl_connect (sock) || !ssl_check_certificate (sock, u->host))
+          if (!ssl_connect (sock, u->host) || !ssl_check_certificate (sock, 
u->host))
             {
               fd_close (sock);
               return CONSSLERR;
--- src/openssl.c.pre-pdp       2009-03-31 23:57:34.000000000 +0000
+++ src/openssl.c       2009-04-01 00:28:35.000000000 +0000
@@ -48,6 +48,7 @@ as that of the covered work.  */
 #include "connect.h"
 #include "url.h"
 #include "ssl.h"
+#include "host.h"
 
 /* Application-wide SSL context.  This is common to all SSL
    connections.  */
@@ -384,7 +385,7 @@ static struct transport_implementation o
    Returns true on success, false on failure.  */
 
 bool
-ssl_connect (int fd) 
+ssl_connect (int fd, const char *hostname) 
 {
   SSL *conn;
   struct openssl_transport_context *ctx;
@@ -395,6 +396,19 @@ ssl_connect (int fd) 
   conn = SSL_new (ssl_ctx);
   if (!conn)
     goto error;
+
+#if OPENSSL_VERSION_NUMBER >= 0x0090806fL && !defined(OPENSSL_NO_TLSEXT)
+  /* If the SSL library was build with support for ServerNameIndication
+     then use it whenever we have a hostname.  If not, don't, ever. */
+  if (!is_ip_address(hostname))
+    {
+      if (!SSL_set_tlsext_host_name(conn, hostname)) {
+       DEBUGP (("Failed to set TLS server-name indication."));
+       goto error;
+      }
+    }
+#endif
+
   if (!SSL_set_fd (conn, fd))
     goto error;
   SSL_set_connect_state (conn);
--- src/ssl.h.pre-pdp   2009-04-01 00:02:43.000000000 +0000
+++ src/ssl.h   2009-04-01 00:03:35.000000000 +0000
@@ -33,7 +33,7 @@ as that of the covered work.  */
 #define GEN_SSLFUNC_H
 
 bool ssl_init (void);
-bool ssl_connect (int);
+bool ssl_connect (int, const char *);
 bool ssl_check_certificate (int, const char *);
 
 #endif /* GEN_SSLFUNC_H */

Attachment: pgpcNigx9HUMq.pgp
Description: PGP signature


reply via email to

[Prev in Thread] Current Thread [Next in Thread]