From fd582e454378db9a1e218acf79f24fbe042bed98 Mon Sep 17 00:00:00 2001
From: Phil Pennock <mutt-dev@spodhuis.org>
Date: Fri, 13 Apr 2012 23:58:46 +0200
Subject: [PATCH] Add support for TLS SNI

diff --git a/src/gnutls.c b/src/gnutls.c
index 291da89..cbd5e1d 100644
--- a/src/gnutls.c
+++ b/src/gnutls.c
@@ -54,6 +54,8 @@ as that of the covered work.  */
 # include "w32sock.h"
 #endif
 
+#include "host.h"
+
 static int
 key_type_to_gnutls_type (enum keyfile_type type)
 {
@@ -369,12 +371,20 @@ static struct transport_implementation wgnutls_transport =
 };
 
 bool
-ssl_connect_wget (int fd)
+ssl_connect_wget (int fd, const char *hostname)
 {
   struct wgnutls_transport_context *ctx;
   gnutls_session session;
   int err;
   gnutls_init (&session, GNUTLS_CLIENT);
+
+  /* We set the server name but only if it's not an IP address. */
+  if (! is_valid_ip_address (hostname))
+    {
+      gnutls_server_name_set (session, GNUTLS_NAME_DNS, hostname,
+			      strlen (hostname));
+    }
+
   gnutls_set_default_priority (session);
   gnutls_credentials_set (session, GNUTLS_CRD_CERTIFICATE, credentials);
 #ifndef FD_TO_SOCKET
diff --git a/src/host.c b/src/host.c
index 86f107a..86bf83b 100644
--- a/src/host.c
+++ b/src/host.c
@@ -1,6 +1,6 @@
 /* Host name resolution and matching.
    Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
-   2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation,
+   2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Free Software Foundation,
    Inc.
 
 This file is part of GNU Wget.
@@ -914,3 +914,18 @@ host_cleanup (void)
       host_name_addresses_map = NULL;
     }
 }
+
+bool
+is_valid_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_ipv6_address (name, endp))
+    return true;
+#endif
+  return false;
+}
diff --git a/src/host.h b/src/host.h
index 3f4a02a..3f27ea0 100644
--- a/src/host.h
+++ b/src/host.h
@@ -1,6 +1,6 @@
 /* Declarations for host.c
    Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
-   2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation,
+   2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Free Software Foundation,
    Inc.
 
 This file is part of GNU Wget.
@@ -98,6 +98,8 @@ const char *print_address (const ip_address *);
 bool is_valid_ipv6_address (const char *, const char *);
 #endif
 
+bool is_valid_ip_address (const char *name);
+
 bool accept_domain (struct url *);
 bool sufmatch (const char **, const char *);
 
diff --git a/src/http.c b/src/http.c
index 61001f3..87d3748 100644
--- a/src/http.c
+++ b/src/http.c
@@ -1,6 +1,6 @@
 /* HTTP support.
    Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
-   2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation,
+   2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Free Software Foundation,
    Inc.
 
 This file is part of GNU Wget.
@@ -2082,7 +2082,7 @@ gethttp (struct url *u, struct http_stat *hs, int *dt, struct url *proxy,
 
       if (conn->scheme == SCHEME_HTTPS)
         {
-          if (!ssl_connect_wget (sock))
+          if (!ssl_connect_wget (sock, u->host))
             {
               fd_close (sock);
               return CONSSLERR;
diff --git a/src/openssl.c b/src/openssl.c
index bc37491..f976455 100644
--- a/src/openssl.c
+++ b/src/openssl.c
@@ -1,6 +1,6 @@
 /* SSL support via OpenSSL library.
    Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
-   2009, 2010, 2011 Free Software Foundation, Inc.
+   2009, 2010, 2011, 2012 Free Software Foundation, Inc.
    Originally contributed by Christian Fraenkel.
 
 This file is part of GNU Wget.
@@ -395,7 +395,7 @@ static struct transport_implementation openssl_transport = {
    Returns true on success, false on failure.  */
 
 bool
-ssl_connect_wget (int fd)
+ssl_connect_wget (int fd, const char *hostname)
 {
   SSL *conn;
   struct openssl_transport_context *ctx;
@@ -406,6 +406,19 @@ ssl_connect_wget (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_valid_ip_address (hostname))
+    {
+      if (! SSL_set_tlsext_host_name (conn, hostname))
+	{
+	DEBUGP (("Failed to set TLS server-name indication."));
+	goto error;
+	}
+    }
+#endif
+
 #ifndef FD_TO_SOCKET
 # define FD_TO_SOCKET(X) (X)
 #endif
diff --git a/src/ssl.h b/src/ssl.h
index 0532c40..e365c4f 100644
--- a/src/ssl.h
+++ b/src/ssl.h
@@ -1,6 +1,6 @@
 /* SSL support.
    Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
-   2009, 2010, 2011 Free Software Foundation, Inc.
+   2009, 2010, 2011, 2012 Free Software Foundation, Inc.
    Originally contributed by Christian Fraenkel.
 
 This file is part of GNU Wget.
@@ -33,7 +33,7 @@ as that of the covered work.  */
 #define GEN_SSLFUNC_H
 
 bool ssl_init (void);
-bool ssl_connect_wget (int);
+bool ssl_connect_wget (int, const char *);
 bool ssl_check_certificate (int, const char *);
 
 #endif /* GEN_SSLFUNC_H */
-- 
1.8.5.3

