]> git.ipfire.org Git - thirdparty/apache/httpd.git/commitdiff
mod_ssl: add compatibility with OpenSSL 3.0.0
authorYann Ylavic <ylavic@apache.org>
Fri, 24 Apr 2020 16:09:02 +0000 (16:09 +0000)
committerYann Ylavic <ylavic@apache.org>
Fri, 24 Apr 2020 16:09:02 +0000 (16:09 +0000)
Wrappers around deprecated API:
* X509_STORE_load_locations() => modssl_X509_STORE_load_locations(),
* CTX_load_verify_locations() => modssl_CTX_load_verify_locations(),
* ERR_peek_error_line_data()  => modssl_ERR_peek_error_data(),
* DH_bits(dh)                 => BN_num_bits(DH_get0_p(dh)).

Provide a compatible version of ssl_callback_SessionTicket() which does not
use the deprecated HMAC_CTX and HMAC_Init_ex(), replaced by EVP_MAC_CTX and
EVP_MAC_CTX_set_params() respectively. This requires adapting struct
modssl_ticket_key_t to replace hmac_secret[] with OSSL_PARAM mac_params[],
created once at load time still.
The callback is registered by SSL_CTX_set_tlsext_ticket_key_evp_cb() instead
of SSL_CTX_set_tlsext_ticket_key_cb().

Since BIO_eof() may now be called openssl-3 state machine, the never-called
assertion in bio_filter_in_ctrl() does not hold anymore, and we have to
handle BIO_CTRL_EOF. For any other cmd, we continue to AP_DEBUG_ASSERT(0) and
log an error, yet the return value is changed from -1 to 0 which is the usual
unhandled value.

Note that OpenSSL 3.0.0 is still in alpha stage as of now, the API shouldn't
change though, neither breakage to 1.x.x API.

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1876934 13f79535-47bb-0310-9956-ffa450edef68

modules/ssl/ssl_engine_init.c
modules/ssl/ssl_engine_io.c
modules/ssl/ssl_engine_kernel.c
modules/ssl/ssl_engine_log.c
modules/ssl/ssl_private.h

index 29810726c5849ce89d48c1da55943ba48fe2209d..9a64ce5760608fb84619db8346ba76f2eb95e8b1 100644 (file)
@@ -894,6 +894,23 @@ static void ssl_init_ctx_callbacks(server_rec *s,
 #endif
 }
 
+static APR_INLINE
+int modssl_CTX_load_verify_locations(SSL_CTX *ctx,
+                                     const char *file,
+                                     const char *path)
+{
+#if OPENSSL_VERSION_NUMBER < 0x30000000L
+    if (!SSL_CTX_load_verify_locations(ctx, file, path))
+        return 0;
+#else
+    if (file && !SSL_CTX_load_verify_file(ctx, file))
+        return 0;
+    if (path && !SSL_CTX_load_verify_dir(ctx, path))
+        return 0;
+#endif
+    return 1;
+}
+
 static apr_status_t ssl_init_ctx_verify(server_rec *s,
                                         apr_pool_t *p,
                                         apr_pool_t *ptemp,
@@ -934,10 +951,8 @@ static apr_status_t ssl_init_ctx_verify(server_rec *s,
         ap_log_error(APLOG_MARK, APLOG_TRACE1, 0, s,
                      "Configuring client authentication");
 
-        if (!SSL_CTX_load_verify_locations(ctx,
-                                           mctx->auth.ca_cert_file,
-                                           mctx->auth.ca_cert_path))
-        {
+        if (!modssl_CTX_load_verify_locations(ctx, mctx->auth.ca_cert_file,
+                                                   mctx->auth.ca_cert_path)) {
             ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(01895)
                     "Unable to configure verify locations "
                     "for client authentication");
@@ -1022,6 +1037,23 @@ static apr_status_t ssl_init_ctx_cipher_suite(server_rec *s,
     return APR_SUCCESS;
 }
 
+static APR_INLINE
+int modssl_X509_STORE_load_locations(X509_STORE *store,
+                                     const char *file,
+                                     const char *path)
+{
+#if OPENSSL_VERSION_NUMBER < 0x30000000L
+    if (!X509_STORE_load_locations(store, file, path))
+        return 0;
+#else
+    if (file && !X509_STORE_load_file(store, file))
+        return 0;
+    if (path && !X509_STORE_load_path(store, path))
+        return 0;
+#endif
+    return 1;
+}
+
 static apr_status_t ssl_init_ctx_crl(server_rec *s,
                                      apr_pool_t *p,
                                      apr_pool_t *ptemp,
@@ -1060,8 +1092,8 @@ static apr_status_t ssl_init_ctx_crl(server_rec *s,
     ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(01900)
                  "Configuring certificate revocation facility");
 
-    if (!store || !X509_STORE_load_locations(store, mctx->crl_file,
-                                             mctx->crl_path)) {
+    if (!store || modssl_X509_STORE_load_locations(store, mctx->crl_file,
+                                                          mctx->crl_path)) {
         ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(01901)
                      "Host %s: unable to configure X.509 CRL storage "
                      "for certificate revocation", mctx->sc->vhost_id);
@@ -1300,7 +1332,7 @@ static apr_status_t ssl_init_server_certs(server_rec *s,
     const char *vhost_id = mctx->sc->vhost_id, *key_id, *certfile, *keyfile;
     int i;
     X509 *cert;
-    DH *dhparams;
+    DH *dh;
 #ifdef HAVE_ECC
     EC_GROUP *ecparams = NULL;
     int nid;
@@ -1485,12 +1517,12 @@ static apr_status_t ssl_init_server_certs(server_rec *s,
      */
     certfile = APR_ARRAY_IDX(mctx->pks->cert_files, 0, const char *);
     if (certfile && !modssl_is_engine_id(certfile)
-        && (dhparams = ssl_dh_GetParamFromFile(certfile))) {
-        SSL_CTX_set_tmp_dh(mctx->ssl_ctx, dhparams);
+        && (dh = ssl_dh_GetParamFromFile(certfile))) {
+        SSL_CTX_set_tmp_dh(mctx->ssl_ctx, dh);
         ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(02540)
                      "Custom DH parameters (%d bits) for %s loaded from %s",
-                     DH_bits(dhparams), vhost_id, certfile);
-        DH_free(dhparams);
+                     BN_num_bits(DH_get0_p(dh)), vhost_id, certfile);
+        DH_free(dh);
     }
 
 #ifdef HAVE_ECC
@@ -1541,6 +1573,7 @@ static apr_status_t ssl_init_ticket_key(server_rec *s,
     char buf[TLSEXT_TICKET_KEY_LEN];
     char *path;
     modssl_ticket_key_t *ticket_key = mctx->ticket_key;
+    int res;
 
     if (!ticket_key->file_path) {
         return APR_SUCCESS;
@@ -1568,11 +1601,22 @@ static apr_status_t ssl_init_ticket_key(server_rec *s,
     }
 
     memcpy(ticket_key->key_name, buf, 16);
-    memcpy(ticket_key->hmac_secret, buf + 16, 16);
     memcpy(ticket_key->aes_key, buf + 32, 16);
-
-    if (!SSL_CTX_set_tlsext_ticket_key_cb(mctx->ssl_ctx,
-                                          ssl_callback_SessionTicket)) {
+#if OPENSSL_VERSION_NUMBER < 0x30000000L
+    memcpy(ticket_key->hmac_secret, buf + 16, 16);
+    res = SSL_CTX_set_tlsext_ticket_key_cb(mctx->ssl_ctx,
+                                           ssl_callback_SessionTicket);
+#else
+    ticket_key->mac_params[0] =
+        OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_KEY, buf + 16, 16);
+    ticket_key->mac_params[1] =
+        OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_DIGEST, "sha256", 0);
+    ticket_key->mac_params[2] =
+        OSSL_PARAM_construct_end();
+    res = SSL_CTX_set_tlsext_ticket_key_evp_cb(mctx->ssl_ctx,
+                                               ssl_callback_SessionTicket);
+#endif
+    if (!res) {
         ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(01913)
                      "Unable to initialize TLS session ticket key callback "
                      "(incompatible OpenSSL version?)");
@@ -1703,7 +1747,7 @@ static apr_status_t ssl_init_proxy_certs(server_rec *s,
         return ssl_die(s);
     }
 
-    X509_STORE_load_locations(store, pkp->ca_cert_file, NULL);
+    modssl_X509_STORE_load_locations(store, pkp->ca_cert_file, NULL);
 
     for (n = 0; n < ncerts; n++) {
         int i;
index 2249faf2c7059453a94dd6c89663ca531efc89ac..771d29c675645a5f71e959b01698f414dddac41f 100644 (file)
@@ -613,10 +613,19 @@ static int bio_filter_in_gets(BIO *bio, char *buf, int size)
 static long bio_filter_in_ctrl(BIO *bio, int cmd, long num, void *ptr)
 {
     bio_filter_in_ctx_t *inctx = (bio_filter_in_ctx_t *)BIO_get_data(bio);
+    switch (cmd) {
+#ifdef BIO_CTRL_EOF
+    case BIO_CTRL_EOF:
+        return inctx->rc == APR_EOF;
+#endif
+    default:
+        break;
+    }
     ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, inctx->f->c,
-                  "BUG: %s() should not be called", "bio_filter_in_ctrl");
+                  "BUG: bio_filter_in_ctrl() should not be called with cmd=%i",
+                  cmd);
     AP_DEBUG_ASSERT(0);
-    return -1;
+    return 0;
 }
 
 #if MODSSL_USE_OPENSSL_PRE_1_1_API
@@ -641,7 +650,7 @@ static BIO_METHOD bio_filter_in_method = {
     bio_filter_in_read,
     bio_filter_in_puts,         /* puts is never called */
     bio_filter_in_gets,         /* gets is never called */
-    bio_filter_in_ctrl,         /* ctrl is never called */
+    bio_filter_in_ctrl,         /* ctrl is called for EOF check */
     bio_filter_create,
     bio_filter_destroy,
     NULL
index a9adea31007dccd4d8e43dbe53db055903c5d0a1..21df1eeb8f67bd0bd151ecd9cfb1526ccea2eb44 100644 (file)
@@ -2611,7 +2611,11 @@ int ssl_callback_SessionTicket(SSL *ssl,
                                unsigned char *keyname,
                                unsigned char *iv,
                                EVP_CIPHER_CTX *cipher_ctx,
-                               HMAC_CTX *hctx,
+#if OPENSSL_VERSION_NUMBER < 0x30000000L
+                               HMAC_CTX *hmac_ctx,
+#else
+                               EVP_MAC_CTX *mac_ctx,
+#endif
                                int mode)
 {
     conn_rec *c = (conn_rec *)SSL_get_app_data(ssl);
@@ -2638,7 +2642,13 @@ int ssl_callback_SessionTicket(SSL *ssl,
         }
         EVP_EncryptInit_ex(cipher_ctx, EVP_aes_128_cbc(), NULL,
                            ticket_key->aes_key, iv);
-        HMAC_Init_ex(hctx, ticket_key->hmac_secret, 16, tlsext_tick_md(), NULL);
+
+#if OPENSSL_VERSION_NUMBER < 0x30000000L
+        HMAC_Init_ex(hmac_ctx, ticket_key->hmac_secret, 16,
+                     tlsext_tick_md(), NULL);
+#else
+        EVP_MAC_CTX_set_params(mac_ctx, ticket_key->mac_params);
+#endif
 
         ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, APLOGNO(02289)
                       "TLS session ticket key for %s successfully set, "
@@ -2659,7 +2669,13 @@ int ssl_callback_SessionTicket(SSL *ssl,
 
         EVP_DecryptInit_ex(cipher_ctx, EVP_aes_128_cbc(), NULL,
                            ticket_key->aes_key, iv);
-        HMAC_Init_ex(hctx, ticket_key->hmac_secret, 16, tlsext_tick_md(), NULL);
+
+#if OPENSSL_VERSION_NUMBER < 0x30000000L
+        HMAC_Init_ex(hmac_ctx, ticket_key->hmac_secret, 16,
+                     tlsext_tick_md(), NULL);
+#else
+        EVP_MAC_CTX_set_params(mac_ctx, ticket_key->mac_params);
+#endif
 
         ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, APLOGNO(02290)
                       "TLS session ticket key for %s successfully set, "
index 451b83e4975677e9d43fd8db7bef0bbb4c4fb995..6bca827d50f21ecf7a5df1819409c176a2c48dd1 100644 (file)
@@ -78,6 +78,16 @@ apr_status_t ssl_die(server_rec *s)
     return APR_EGENERAL;
 }
 
+static APR_INLINE
+unsigned long modssl_ERR_peek_error_data(const char **data, int *flags)
+{
+#if OPENSSL_VERSION_NUMBER < 0x30000000L
+    return ERR_peek_error_line_data(NULL, NULL, data, flags);
+#else
+    return ERR_peek_error_data(data, flags);
+#endif
+}
+
 /*
  * Prints the SSL library error information.
  */
@@ -87,7 +97,7 @@ void ssl_log_ssl_error(const char *file, int line, int level, server_rec *s)
     const char *data;
     int flags;
 
-    while ((e = ERR_peek_error_line_data(NULL, NULL, &data, &flags))) {
+    while ((e = modssl_ERR_peek_error_data(&data, &flags))) {
         const char *annotation;
         char err[256];
 
index 12d79208b166ad4bad1e2310274a1897fe16db31..d8213eef7eb20f855f3683acfb6aa2b185ed8500 100644 (file)
@@ -88,6 +88,9 @@
 /* must be defined before including ssl.h */
 #define OPENSSL_NO_SSL_INTERN
 #endif
+#if OPENSSL_VERSION_NUMBER >= 0x30000000
+#include <openssl/core_names.h>
+#endif
 #include <openssl/ssl.h>
 #include <openssl/err.h>
 #include <openssl/x509.h>
@@ -667,7 +670,11 @@ typedef struct {
 typedef struct {
     const char *file_path;
     unsigned char key_name[16];
+#if OPENSSL_VERSION_NUMBER < 0x30000000L
     unsigned char hmac_secret[16];
+#else
+    OSSL_PARAM mac_params[3];
+#endif
     unsigned char aes_key[16];
 } modssl_ticket_key_t;
 #endif
@@ -935,8 +942,16 @@ int          ssl_callback_ServerNameIndication(SSL *, int *, modssl_ctx_t *);
 int          ssl_callback_ClientHello(SSL *, int *, void *);
 #endif
 #ifdef HAVE_TLS_SESSION_TICKETS
-int         ssl_callback_SessionTicket(SSL *, unsigned char *, unsigned char *,
-                                       EVP_CIPHER_CTX *, HMAC_CTX *, int);
+int ssl_callback_SessionTicket(SSL *ssl,
+                               unsigned char *keyname,
+                               unsigned char *iv,
+                               EVP_CIPHER_CTX *cipher_ctx,
+#if OPENSSL_VERSION_NUMBER < 0x30000000L
+                               HMAC_CTX *hmac_ctx,
+#else
+                               EVP_MAC_CTX *mac_ctx,
+#endif
+                               int mode);
 #endif
 
 #ifdef HAVE_TLS_ALPN