]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: ssl: generated certificate is missing in switchctx early callback
authorEmmanuel Hocdet <manu@gandi.net>
Mon, 14 Aug 2017 09:01:25 +0000 (11:01 +0200)
committerWilly Tarreau <w@1wt.eu>
Fri, 27 Oct 2017 08:54:05 +0000 (10:54 +0200)
Openssl 1.1.1 supports switchctx early callback and generated certificate.
Generated certificate calls must be available in switchctx early callback.

src/ssl_sock.c

index e1cfc66976bba145af89acdd2cd2a6d5f9f81ee3..fceccc9ba7f2a6078e637c6de3fae8d5e4455dbb 100644 (file)
@@ -1771,7 +1771,7 @@ ssl_sock_generated_cert_key(const void *data, size_t len)
 /* Generate a cert and immediately assign it to the SSL session so that the cert's
  * refcount is maintained regardless of the cert's presence in the LRU cache.
  */
-static SSL_CTX *
+static int
 ssl_sock_generate_certificate(const char *servername, struct bind_conf *bind_conf, SSL *ssl)
 {
        X509         *cacert  = bind_conf->ca_sign_cert;
@@ -1789,14 +1789,35 @@ ssl_sock_generate_certificate(const char *servername, struct bind_conf *bind_con
                        lru64_commit(lru, ssl_ctx, cacert, 0, (void (*)(void *))SSL_CTX_free);
                }
                SSL_set_SSL_CTX(ssl, ssl_ctx);
+               return 1;
        }
        else {
                ssl_ctx = ssl_sock_do_create_cert(servername, bind_conf, ssl);
                SSL_set_SSL_CTX(ssl, ssl_ctx);
                /* No LRU cache, this CTX will be released as soon as the session dies */
                SSL_CTX_free(ssl_ctx);
+               return 1;
        }
-       return ssl_ctx;
+       return 0;
+}
+static int
+ssl_sock_generate_certificate_from_conn(struct bind_conf *bind_conf, SSL *ssl)
+{
+       unsigned int key;
+       SSL_CTX     *ssl_ctx = NULL;
+       struct connection *conn = SSL_get_app_data(ssl);
+
+       conn_get_to_addr(conn);
+       if (conn->flags & CO_FL_ADDR_TO_SET) {
+               key = ssl_sock_generated_cert_key(&conn->addr.to, get_addr_len(&conn->addr.to));
+               ssl_ctx = ssl_sock_get_generated_cert(key, bind_conf);
+               if (ssl_ctx) {
+                       /* switch ctx */
+                       SSL_set_SSL_CTX(ssl, ssl_ctx);
+                       return 1;
+               }
+       }
+       return 0;
 }
 #endif /* !defined SSL_NO_GENERATE_CERTIFICATES */
 
@@ -1955,12 +1976,12 @@ static void ssl_sock_switchctx_set(SSL *ssl, SSL_CTX *ctx)
 
 static int ssl_sock_switchctx_err_cbk(SSL *ssl, int *al, void *priv)
 {
+       struct bind_conf *s = priv;
        (void)al; /* shut gcc stupid warning */
-       (void)priv;
 
-       if (!SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name))
-               return SSL_TLSEXT_ERR_NOACK;
-       return SSL_TLSEXT_ERR_OK;
+       if (SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name) || s->generate_certs)
+               return SSL_TLSEXT_ERR_OK;
+       return SSL_TLSEXT_ERR_NOACK;
 }
 
 #ifdef OPENSSL_IS_BORINGSSL
@@ -2022,6 +2043,11 @@ static int ssl_sock_switchctx_cbk(SSL *ssl, int *al, void *arg)
                servername = extension_data;
                servername_len = len;
        } else {
+#if (!defined SSL_NO_GENERATE_CERTIFICATES)
+               if (s->generate_certs && ssl_sock_generate_certificate_from_conn(s, ssl)) {
+                       return 1;
+               }
+#endif
                /* without SNI extension, is the default_ctx (need SSL_TLSEXT_ERR_NOACK) */
                if (!s->strict_sni) {
                        ssl_sock_switchctx_set(ssl, s->default_ctx);
@@ -2165,6 +2191,12 @@ static int ssl_sock_switchctx_cbk(SSL *ssl, int *al, void *arg)
                methodVersions[conf->ssl_methods.max].ssl_set_version(ssl, SET_MAX);
                return 1;
        }
+#if (!defined SSL_NO_GENERATE_CERTIFICATES)
+       if (s->generate_certs && ssl_sock_generate_certificate(trash.str, s, ssl)) {
+               /* switch ctx done in ssl_sock_generate_certificate */
+               return 1;
+       }
+#endif
        if (!s->strict_sni) {
                /* no certificate match, is the default_ctx */
                ssl_sock_switchctx_set(ssl, s->default_ctx);
@@ -2199,22 +2231,8 @@ static int ssl_sock_switchctx_cbk(SSL *ssl, int *al, void *priv)
        servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
        if (!servername) {
 #if (!defined SSL_NO_GENERATE_CERTIFICATES)
-               if (s->generate_certs) {
-                       struct connection *conn = SSL_get_app_data(ssl);
-                       unsigned int key;
-                       SSL_CTX *ctx;
-
-                       conn_get_to_addr(conn);
-                       if (conn->flags & CO_FL_ADDR_TO_SET) {
-                               key = ssl_sock_generated_cert_key(&conn->addr.to, get_addr_len(&conn->addr.to));
-                               ctx = ssl_sock_get_generated_cert(key, s);
-                               if (ctx) {
-                                       /* switch ctx */
-                                       SSL_set_SSL_CTX(ssl, ctx);
-                                       return SSL_TLSEXT_ERR_OK;
-                               }
-                       }
-               }
+               if (s->generate_certs && ssl_sock_generate_certificate_from_conn(s, ssl))
+                       return SSL_TLSEXT_ERR_OK;
 #endif
                if (s->strict_sni)
                        return SSL_TLSEXT_ERR_ALERT_FATAL;
@@ -2247,10 +2265,8 @@ static int ssl_sock_switchctx_cbk(SSL *ssl, int *al, void *priv)
        }
        if (!node || container_of(node, struct sni_ctx, name)->neg) {
 #if (!defined SSL_NO_GENERATE_CERTIFICATES)
-               SSL_CTX *ctx;
-               if (s->generate_certs &&
-                   (ctx = ssl_sock_generate_certificate(servername, s, ssl))) {
-                       /* switch ctx */
+               if (s->generate_certs && ssl_sock_generate_certificate(servername, s, ssl)) {
+                       /* switch ctx done in ssl_sock_generate_certificate */
                        return SSL_TLSEXT_ERR_OK;
                }
 #endif
@@ -3678,8 +3694,8 @@ ssl_sock_initial_ctx(struct bind_conf *bind_conf)
        SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_err_cbk);
 #else
        SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_cbk);
-       SSL_CTX_set_tlsext_servername_arg(ctx, bind_conf);
 #endif
+       SSL_CTX_set_tlsext_servername_arg(ctx, bind_conf);
 #endif
        return cfgerr;
 }