]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MINOR: ssl: Fix check against SNI during server certificate verification
authorChristopher Faulet <cfaulet@haproxy.com>
Wed, 26 Jul 2017 09:50:01 +0000 (11:50 +0200)
committerWilly Tarreau <w@1wt.eu>
Wed, 26 Jul 2017 17:43:33 +0000 (19:43 +0200)
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.6, this one must be
backported too.

Note: it's worth mentionning that by making the SNI check work, we
      introduce another problem by which failed SNI checks can cause
      long connection retries on the server, and in certain cases the
      SNI value used comes from the client. So this patch series must
      not be backported until this issue is resolved.

include/proto/openssl-compat.h
src/ssl_sock.c

index a1e75b47bca18268bd43f2a3ace4673a6ad5793a..ea92072e559e0fbd61c82d1724d905c2a5350efe 100644 (file)
@@ -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;
index fa815715541783348d8bccf0afc41e62ffa8414d..42d27de9fadf74b7d674d4a8f5bc7d7815a53371 100644 (file)
@@ -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;
        }