From 633c20a2e622555365d649911acf5996838244a0 Mon Sep 17 00:00:00 2001
From: Juan RP <xtraeme@gmail.com>
Date: Sat, 28 Jun 2014 12:01:00 +0200
Subject: [PATCH] libfetch: merge TLS SNI support from NetBSD with some other
 random changes.

Close GH #41
---
 NEWS               |  5 +++++
 lib/fetch/common.c | 26 ++++++++++++++++++++++----
 lib/fetch/common.h |  2 +-
 lib/fetch/http.c   |  3 ++-
 4 files changed, 30 insertions(+), 6 deletions(-)

diff --git a/lib/fetch/common.c b/lib/fetch/common.c
index 8d7d3f5..5b03348 100644
--- lib/fetch/common.c
+++ lib/fetch/common.c
@@ -434,10 +434,12 @@ fetch_cache_put(conn_t *conn, int (*closecb)(conn_t *))
  * Enable SSL on a connection.
  */
 int
-fetch_ssl(conn_t *conn, int verbose)
+fetch_ssl(conn_t *conn, const struct url *URL, int verbose)
 {
 
 #ifdef WITH_SSL
+	int ret;
+
 	/* Init the SSL library and context */
 	if (!SSL_library_init()){
 		fprintf(stderr, "SSL library init failed\n");
@@ -455,9 +457,21 @@ fetch_ssl(conn_t *conn, int verbose)
 		fprintf(stderr, "SSL context creation failed\n");
 		return (-1);
 	}
-	SSL_set_fd(conn->ssl, conn->sd);
-	if (SSL_connect(conn->ssl) == -1){
-		ERR_print_errors_fp(stderr);
+	SSL_set_connect_state(conn->ssl);
+	if (!SSL_set_fd(conn->ssl, conn->sd)) {
+		fprintf(stderr, "SSL_set_fd failed\n");
+		return (-1);
+	}
+#ifndef OPENSSL_NO_TLSEXT
+	if (!SSL_set_tlsext_host_name(conn->ssl, URL->host)) {
+		fprintf(stderr,
+		    "TLS server name indication extension failed for host %s\n",
+		    URL->host);
+		return (-1);
+	}
+#endif
+	if ((ret = SSL_connect(conn->ssl)) <= 0){
+		fprintf(stderr, "SSL_connect returned %d\n", SSL_get_error(conn->ssl, ret));
 		return (-1);
 	}
 
@@ -717,6 +731,10 @@ fetch_close(conn_t *conn)
 {
 	int ret;
 
+#ifdef WITH_SSL
+	SSL_shutdown(conn->ssl);
+	SSL_free(conn->ssl);
+#endif
 	ret = close(conn->sd);
 	if (conn->cache_url)
 		fetchFreeURL(conn->cache_url);
diff --git a/lib/fetch/common.h b/lib/fetch/common.h
index 4e4408c..231fb02 100644
--- lib/fetch/common.h
+++ lib/fetch/common.h
@@ -98,7 +98,7 @@ conn_t		*fetch_cache_get(const struct url *, int);
 void		 fetch_cache_put(conn_t *, int (*)(conn_t *));
 conn_t		*fetch_connect(struct url *, int, int);
 conn_t		*fetch_reopen(int);
-int		 fetch_ssl(conn_t *, int);
+int		 fetch_ssl(conn_t *, const struct url *, int);
 ssize_t		 fetch_read(conn_t *, char *, size_t);
 int		 fetch_getln(conn_t *);
 ssize_t		 fetch_write(conn_t *, const void *, size_t);
diff --git a/lib/fetch/http.c b/lib/fetch/http.c
index adc5590..122d9c1 100644
--- lib/fetch/http.c
+++ lib/fetch/http.c
@@ -740,8 +740,9 @@ http_connect(struct url *URL, struct url *purl, const char *flags, int *cached)
 	if ((conn = fetch_connect(URL, af, verbose)) == NULL)
 		/* fetch_connect() has already set an error code */
 		return (NULL);
+
 	if (strcasecmp(URL->scheme, SCHEME_HTTPS) == 0 &&
-	    fetch_ssl(conn, verbose) == -1) {
+	    fetch_ssl(conn, URL, verbose) != 0) {
 		fetch_close(conn);
 		/* grrr */
 #ifdef EAUTH
-- 
2.0.1

