.Le 25/07/2017 à 19:37, Kevin McArthur a écrit :
Hi Willy,

I cant replicate your results here....

I cloned from git and built the package with the debian/ubuntu build scripts from https://launchpad.net/~vbernat/+archive/ubuntu/haproxy-1.7 ... updating the changelog to add a 1.8-dev2 version and calling ./debian/rules binary to build the package.

The git log shows:

    commit 2ab88675ecbf960a6f33ffe9c6a27f264150b201
    Author: Willy Tarreau <w...@1wt.eu>
    Date:   Wed Jul 5 18:23:03 2017 +0200

         MINOR: ssl: compare server certificate names to the SNI on
    outgoing connections



Hi,

There is a bug in this commit. I checked with openssl 1.0.2l and 1.1.0f and I observed the same behavior than Kevin's one. SSL_SESSION_get0_hostname seems to always return NULL when the server returns a default certificate.

It tried to explain why in my commit log.

Kevin, could you check the patch in attachment to confirm it works ?

--
Christopher Faulet
>From afe2d426c6aeb82aa11af842e8f75f54a2d9130d Mon Sep 17 00:00:00 2001
From: Christopher Faulet <cfau...@haproxy.com>
Date: Wed, 26 Jul 2017 11:50:01 +0200
Subject: [PATCH] BUG/MINOR: ssl: Fix check against SNI during server
 certificate verification

This patch fixes the commit 2ab8867 ("MINOR: ssl: compare server certificate
names to the SNI on outgoing connections")

When we check the certificate sent by a server, in the verify callback, we get
the SNI from the session (SSL_SESSION object). In OpenSSL, tlsext_hostname value
for this session is copied from the ssl connection (SSL object). But the copy is
done only if the "server_name" extension is found in the server hello
message. This means the server has found a certificate matching the client's
SNI.

When the server returns a default certificate not matching the client's SNI, it
doesn't set any "server_name" extension in the server hello message. So no SNI
is set on the SSL session and SSL_SESSION_get0_hostname always returns NULL.

To fix the problemn, we get the SNI directly from the SSL connection. It is
always defined with the value set by the client.

If the commit 2ab8867 is backported in 1.7 and/or 1.8, this one must be
backported too.
---
 include/proto/openssl-compat.h | 5 -----
 src/ssl_sock.c                 | 6 +-----
 2 files changed, 1 insertion(+), 10 deletions(-)

diff --git a/include/proto/openssl-compat.h b/include/proto/openssl-compat.h
index a1e75b47..ea92072e 100644
--- a/include/proto/openssl-compat.h
+++ b/include/proto/openssl-compat.h
@@ -94,11 +94,6 @@ static inline int SSL_SESSION_set1_id_context(SSL_SESSION *s, const unsigned cha
  * Functions introduced in OpenSSL 1.1.0 and not yet present in LibreSSL
  */
 
-static inline const char *SSL_SESSION_get0_hostname(const SSL_SESSION *sess)
-{
-       return sess->tlsext_hostname;
-}
-
 static inline const unsigned char *SSL_SESSION_get0_id_context(const SSL_SESSION *sess, unsigned int *sid_ctx_length)
 {
 	*sid_ctx_length = sess->sid_ctx_length;
diff --git a/src/ssl_sock.c b/src/ssl_sock.c
index fa815715..42d27de9 100644
--- a/src/ssl_sock.c
+++ b/src/ssl_sock.c
@@ -3951,11 +3951,7 @@ static int ssl_sock_srv_verifycbk(int ok, X509_STORE_CTX *ctx)
 	 */
 	servername = objt_server(conn->target)->ssl_ctx.verify_host;
 	if (!servername) {
-		SSL_SESSION *ssl_sess = SSL_get_session(conn->xprt_ctx);
-		if (!ssl_sess)
-			return ok;
-
-		servername = SSL_SESSION_get0_hostname(ssl_sess);
+		servername = SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name);
 		if (!servername)
 			return ok;
 	}
-- 
2.13.3

Reply via email to