[elinks-dev] [PATCH] ssl: use the OpenSSL-provided host name check

Kamil Dudka kdudka at redhat.com
Tue Jun 30 03:31:14 PDT 2015


... if built against a new enough version of OpenSSL

Suggested-by: Christian Heimes
---
 configure.in             |  3 +++
 src/network/ssl/socket.c | 50 +++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 52 insertions(+), 1 deletion(-)

diff --git a/configure.in b/configure.in
index 58548fe..324fb2a 100644
--- a/configure.in
+++ b/configure.in
@@ -1134,6 +1134,9 @@ else
 fi
 
 AC_MSG_RESULT($cf_result)
+if test "$cf_result" = yes; then
+	AC_CHECK_FUNCS(X509_VERIFY_PARAM_set1_host)
+fi
 
 # ---- GNU TLS
 
diff --git a/src/network/ssl/socket.c b/src/network/ssl/socket.c
index 6af5e0d..9a2109b 100644
--- a/src/network/ssl/socket.c
+++ b/src/network/ssl/socket.c
@@ -7,6 +7,9 @@
 #ifdef CONFIG_OPENSSL
 #include <openssl/ssl.h>
 #include <openssl/x509v3.h>
+#ifdef HAVE_X509_VERIFY_PARAM_SET1_HOST
+#include <openssl/x509_vfy.h>
+#endif
 #define USE_OPENSSL
 #elif defined(CONFIG_NSS_COMPAT_OSSL)
 #include <nss_compat_ossl/nss_compat_ossl.h>
@@ -168,6 +171,30 @@ verify_certificates(struct socket *socket)
 
 #ifdef USE_OPENSSL
 
+#ifdef HAVE_X509_VERIFY_PARAM_SET1_HOST
+/* activate the OpenSSL-provided host name check */
+static int
+ossl_set_hostname(void *ssl, unsigned char *server_name)
+{
+	int ret = -1;
+
+	X509_VERIFY_PARAM *vpm = X509_VERIFY_PARAM_new();
+	if (vpm) {
+		if (X509_VERIFY_PARAM_set1_host(vpm, (char *) server_name, 0)
+				&& SSL_set1_param(ssl, vpm))
+		{
+			/* successfully activated the OpenSSL host name check */
+			ret = 0;
+		}
+
+		X509_VERIFY_PARAM_free(vpm);
+	}
+
+	return ret;
+}
+
+#else /* HAVE_X509_VERIFY_PARAM_SET1_HOST */
+
 /** Checks whether the host component of a URI matches a host name in
  * the server certificate.
  *
@@ -360,6 +387,7 @@ verify_callback(int preverify_ok, X509_STORE_CTX *ctx)
 	mem_free(host_in_uri);
 	return matched;
 }
+#endif	/* HAVE_X509_VERIFY_PARAM_SET1_HOST */
 
 #endif	/* USE_OPENSSL */
 
@@ -400,6 +428,9 @@ ssl_connect(struct socket *socket)
 	int ret;
 	unsigned char *server_name;
 	struct connection *conn = socket->conn;
+#ifdef USE_OPENSSL
+	int (*verify_callback_ptr)(int, X509_STORE_CTX *);
+#endif	/* USE_OPENSSL */
 
 	/* TODO: Recode server_name to UTF-8.  */
 	server_name = get_uri_string(conn->proxied_uri, URI_HOST);
@@ -418,6 +449,23 @@ ssl_connect(struct socket *socket)
 		return -1;
 	}
 
+#ifdef USE_OPENSSL
+#ifdef HAVE_X509_VERIFY_PARAM_SET1_HOST
+	/* activate the OpenSSL-provided host name check */
+	if (ossl_set_hostname(socket->ssl, server_name)) {
+		mem_free_if(server_name);
+		socket->ops->done(socket, connection_state(S_SSL_ERROR));
+		return -1;
+	}
+
+	/* verify_callback() is not needed with X509_VERIFY_PARAM_set1_host() */
+	verify_callback_ptr = NULL;
+#else
+	/* use our own callback implementing the host name check */
+	verify_callback_ptr = verify_callback;
+#endif
+#endif	/* USE_OPENSSL */
+
 	mem_free_if(server_name);
 
 	if (socket->no_tls)
@@ -429,7 +477,7 @@ ssl_connect(struct socket *socket)
 	if (get_opt_bool("connection.ssl.cert_verify", NULL))
 		SSL_set_verify(socket->ssl, SSL_VERIFY_PEER
 					  | SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
-			       verify_callback);
+			       verify_callback_ptr);
 
 	if (get_opt_bool("connection.ssl.client_cert.enable", NULL)) {
 		unsigned char *client_cert;
-- 
2.4.3



More information about the elinks-dev mailing list