From 8bc4871c576e5587d8a31cc3c2c6fa2fa7a1649d Mon Sep 17 00:00:00 2001 From: Rainer Jung Date: Sun, 7 Feb 2016 01:20:37 +0000 Subject: [PATCH] Support for OpenSSL 1.1.0: - mod_ssl Look out for "XXX: OpenSSL 1.1.0:" for a few open problems. Not tested with test suite yet. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1728909 13f79535-47bb-0310-9956-ffa450edef68 --- modules/ssl/mod_ssl.c | 4 ++++ modules/ssl/mod_ssl_ct.c | 18 ++++++++++++++- modules/ssl/ssl_ct_sct.c | 6 ++--- modules/ssl/ssl_engine_init.c | 4 ++++ modules/ssl/ssl_engine_kernel.c | 40 +++++++++++++++++++++++++++++++-- modules/ssl/ssl_engine_ocsp.c | 4 ++++ modules/ssl/ssl_engine_vars.c | 34 +++++++++++++++++++++++++++- modules/ssl/ssl_util_stapling.c | 14 ++++++++++++ 8 files changed, 117 insertions(+), 7 deletions(-) diff --git a/modules/ssl/mod_ssl.c b/modules/ssl/mod_ssl.c index e426507234..edc27c4588 100644 --- a/modules/ssl/mod_ssl.c +++ b/modules/ssl/mod_ssl.c @@ -356,7 +356,11 @@ static int ssl_hook_pre_config(apr_pool_t *pconf, /* We must register the library in full, to ensure our configuration * code can successfully test the SSL environment. */ +#if OPENSSL_VERSION_NUMBER < 0x10100000L CRYPTO_malloc_init(); +#else + OPENSSL_malloc_init(); +#endif ERR_load_crypto_strings(); SSL_load_error_strings(); SSL_library_init(); diff --git a/modules/ssl/mod_ssl_ct.c b/modules/ssl/mod_ssl_ct.c index d08e77ae66..0b3de1852b 100644 --- a/modules/ssl/mod_ssl_ct.c +++ b/modules/ssl/mod_ssl_ct.c @@ -1937,9 +1937,11 @@ static int ocsp_resp_cb(SSL *ssl, void *arg) int i, len; OCSP_RESPONSE *rsp; OCSP_BASICRESP *br; +#if OPENSSL_VERSION_NUMBER < 0x10100000L OCSP_RESPDATA *rd; - OCSP_SINGLERESP *single; STACK_OF(X509_EXTENSION) *exts; +#endif + OCSP_SINGLERESP *single; len = SSL_get_tlsext_status_ocsp_resp(ssl, &p); /* UNDOC */ if (!p) { @@ -1963,15 +1965,25 @@ static int ocsp_resp_cb(SSL *ssl, void *arg) return 0; } +#if OPENSSL_VERSION_NUMBER < 0x10100000L rd = br->tbsResponseData; +#endif +#if OPENSSL_VERSION_NUMBER < 0x10100000L for (i = 0; i < sk_OCSP_SINGLERESP_num(rd->responses); i++) { /* UNDOC */ +#else + for (i = 0; i < OCSP_resp_count(br); i++) { +#endif const unsigned char *p; X509_EXTENSION *ext; int idx; ASN1_OCTET_STRING *oct1, *oct2; +#if OPENSSL_VERSION_NUMBER < 0x10100000L single = sk_OCSP_SINGLERESP_value(rd->responses, i); /* UNDOC */ +#else + single = OCSP_resp_get0(br, i); +#endif if (!single) { continue; } @@ -1986,9 +1998,13 @@ static int ocsp_resp_cb(SSL *ssl, void *arg) ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, c, "index of NID_ct_cert_scts: %d", idx); +#if OPENSSL_VERSION_NUMBER < 0x10100000L exts = single->singleExtensions; ext = sk_X509_EXTENSION_value(exts, idx); /* UNDOC */ +#else + ext = OCSP_SINGLERESP_get_ext(single, idx); +#endif oct1 = X509_EXTENSION_get_data(ext); /* UNDOC */ p = oct1->data; diff --git a/modules/ssl/ssl_ct_sct.c b/modules/ssl/ssl_ct_sct.c index 7f11a9ba1c..6d3652ac2b 100644 --- a/modules/ssl/ssl_ct_sct.c +++ b/modules/ssl/ssl_ct_sct.c @@ -25,19 +25,19 @@ APLOG_USE_MODULE(ssl_ct); static apr_status_t verify_signature(sct_fields_t *sctf, EVP_PKEY *pkey) { - EVP_MD_CTX ctx; + EVP_MD_CTX *ctx; int rc; if (sctf->signed_data == NULL) { return APR_EINVAL; } - EVP_MD_CTX_init(&ctx); + ctx = EVP_MD_CTX_new(); ap_assert(1 == EVP_VerifyInit(&ctx, EVP_sha256())); ap_assert(1 == EVP_VerifyUpdate(&ctx, sctf->signed_data, sctf->signed_data_len)); rc = EVP_VerifyFinal(&ctx, sctf->sig, sctf->siglen, pkey); - EVP_MD_CTX_cleanup(&ctx); + EVP_MD_CTX_free(ctx); return rc == 1 ? APR_SUCCESS : APR_EINVAL; } diff --git a/modules/ssl/ssl_engine_init.c b/modules/ssl/ssl_engine_init.c index 226c706a6b..e4c21c912d 100644 --- a/modules/ssl/ssl_engine_init.c +++ b/modules/ssl/ssl_engine_init.c @@ -872,7 +872,11 @@ static int use_certificate_chain( unsigned long err; int n; +#if OPENSSL_VERSION_NUMBER < 0x10100000L if ((bio = BIO_new(BIO_s_file_internal())) == NULL) +#else + if ((bio = BIO_new(BIO_s_file())) == NULL) +#endif return -1; if (BIO_read_filename(bio, file) <= 0) { BIO_free(bio); diff --git a/modules/ssl/ssl_engine_kernel.c b/modules/ssl/ssl_engine_kernel.c index fab3ab90d1..3f6b81e0ee 100644 --- a/modules/ssl/ssl_engine_kernel.c +++ b/modules/ssl/ssl_engine_kernel.c @@ -80,7 +80,11 @@ static apr_status_t upgrade_connection(request_rec *r) SSL_set_accept_state(ssl); SSL_do_handshake(ssl); +#if OPENSSL_VERSION_NUMBER < 0x10100000L if (SSL_get_state(ssl) != SSL_ST_OK) { +#else + if (SSL_get_state(ssl) != TLS_ST_OK) { +#endif ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02030) "TLS upgrade handshake failed"); ssl_log_ssl_error(SSLLOG_MARK, APLOG_ERR, r->server); @@ -456,7 +460,11 @@ int ssl_hook_Access(request_rec *r) * forbidden in the latter case, let ap_die() handle * this recursive (same) error. */ +#if OPENSSL_VERSION_NUMBER < 0x10100000L if (SSL_get_state(ssl) != SSL_ST_OK) { +#else + if (SSL_get_state(ssl) != TLS_ST_OK) { +#endif return HTTP_FORBIDDEN; } ctx = SSL_get_SSL_CTX(ssl); @@ -622,7 +630,7 @@ int ssl_hook_Access(request_rec *r) !renegotiate && (n < sk_SSL_CIPHER_num(cipher_list)); n++) { - SSL_CIPHER *value = sk_SSL_CIPHER_value(cipher_list, n); + const SSL_CIPHER *value = sk_SSL_CIPHER_value(cipher_list, n); if (sk_SSL_CIPHER_find(cipher_list_old, value) < 0) { renegotiate = TRUE; @@ -633,7 +641,7 @@ int ssl_hook_Access(request_rec *r) !renegotiate && (n < sk_SSL_CIPHER_num(cipher_list_old)); n++) { - SSL_CIPHER *value = sk_SSL_CIPHER_value(cipher_list_old, n); + const SSL_CIPHER *value = sk_SSL_CIPHER_value(cipher_list_old, n); if (sk_SSL_CIPHER_find(cipher_list, value) < 0) { renegotiate = TRUE; @@ -982,7 +990,11 @@ int ssl_hook_Access(request_rec *r) SSL_renegotiate(ssl); SSL_do_handshake(ssl); +#if OPENSSL_VERSION_NUMBER < 0x10100000L if (SSL_get_state(ssl) != SSL_ST_OK) { +#else + if (SSL_get_state(ssl) != TLS_ST_OK) { +#endif ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02225) "Re-negotiation request failed"); ssl_log_ssl_error(SSLLOG_MARK, APLOG_ERR, r->server); @@ -998,16 +1010,24 @@ int ssl_hook_Access(request_rec *r) * However, this causes failures in perl-framework currently, * perhaps pre-test if we have already negotiated? */ + /* XXX: OpenSSL 1.1.0: SSL_set_state() no longer available. + * Would SSL_renegotiate(ssl) work? */ +#if OPENSSL_VERSION_NUMBER < 0x10100000L #ifdef OPENSSL_NO_SSL_INTERN SSL_set_state(ssl, SSL_ST_ACCEPT); #else ssl->state = SSL_ST_ACCEPT; +#endif #endif SSL_do_handshake(ssl); sslconn->reneg_state = RENEG_REJECT; +#if OPENSSL_VERSION_NUMBER < 0x10100000L if (SSL_get_state(ssl) != SSL_ST_OK) { +#else + if (SSL_get_state(ssl) != TLS_ST_OK) { +#endif ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02261) "Re-negotiation handshake failed"); ssl_log_ssl_error(SSLLOG_MARK, APLOG_ERR, r->server); @@ -1723,11 +1743,19 @@ static void modssl_proxy_info_log(conn_rec *c, * so we need to increment here to prevent them from * being freed. */ +#if OPENSSL_VERSION_NUMBER < 0x10100000L #define modssl_set_cert_info(info, cert, pkey) \ *cert = info->x509; \ CRYPTO_add(&(*cert)->references, +1, CRYPTO_LOCK_X509); \ *pkey = info->x_pkey->dec_pkey; \ CRYPTO_add(&(*pkey)->references, +1, CRYPTO_LOCK_X509_PKEY) +#else +#define modssl_set_cert_info(info, cert, pkey) \ + *cert = info->x509; \ + X509_up_ref(*cert); \ + *pkey = info->x_pkey->dec_pkey; \ + EVP_PKEY_up_ref(*pkey); +#endif int ssl_callback_proxy_cert(SSL *ssl, X509 **x509, EVP_PKEY **pkey) { @@ -2066,6 +2094,9 @@ void ssl_callback_Info(const SSL *ssl, int where, int rc) * state machine and move to ABORT if a Client Hello is being * read. */ if ((where & SSL_CB_ACCEPT_LOOP) && scr->reneg_state == RENEG_REJECT) { + /* XXX: OpenSSL 1.1.0: Which state machine states to use instead of + * SSL3_ST_SR_CLNT_HELLO_A and SSL23_ST_SR_CLNT_HELLO_A ? */ +#if OPENSSL_VERSION_NUMBER < 0x10100000L int state = SSL_get_state((SSL *)ssl); if (state == SSL3_ST_SR_CLNT_HELLO_A @@ -2074,6 +2105,7 @@ void ssl_callback_Info(const SSL *ssl, int where, int rc) ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c, APLOGNO(02042) "rejecting client initiated renegotiation"); } +#endif } /* If the first handshake is complete, change state to reject any * subsequent client-initiated renegotiation. */ @@ -2277,7 +2309,11 @@ int ssl_callback_SessionTicket(SSL *ssl, } memcpy(keyname, ticket_key->key_name, 16); +#if OPENSSL_VERSION_NUMBER < 0x10100000L RAND_pseudo_bytes(iv, EVP_MAX_IV_LENGTH); +#else + RAND_bytes(iv, EVP_MAX_IV_LENGTH); +#endif 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); diff --git a/modules/ssl/ssl_engine_ocsp.c b/modules/ssl/ssl_engine_ocsp.c index 553004f5d0..28016afddd 100644 --- a/modules/ssl/ssl_engine_ocsp.c +++ b/modules/ssl/ssl_engine_ocsp.c @@ -262,6 +262,9 @@ int modssl_verify_ocsp(X509_STORE_CTX *ctx, SSLSrvConfigRec *sc, "No cert available to check with OCSP"); return 1; } + /* XXX: OpenSSL 1.1.0: cert->valid not available in OpenSSL 1.1.0 + * and I have found no accessor method. What to do? */ +#if OPENSSL_VERSION_NUMBER < 0x10100000L else if (cert->valid && X509_check_issued(cert,cert) == X509_V_OK) { /* don't do OCSP checking for valid self-issued certs */ ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, c, @@ -269,6 +272,7 @@ int modssl_verify_ocsp(X509_STORE_CTX *ctx, SSLSrvConfigRec *sc, X509_STORE_CTX_set_error(ctx, X509_V_OK); return 1; } +#endif /* Create a temporary pool to constrain memory use (the passed-in * pool may be e.g. a connection pool). */ diff --git a/modules/ssl/ssl_engine_vars.c b/modules/ssl/ssl_engine_vars.c index 5a0038632f..cfe979e33e 100644 --- a/modules/ssl/ssl_engine_vars.c +++ b/modules/ssl/ssl_engine_vars.c @@ -114,7 +114,11 @@ static apr_status_t ssl_get_tls_cb(apr_pool_t *p, conn_rec *c, const char *type, else if (x != NULL) { const EVP_MD *md; +#if OPENSSL_VERSION_NUMBER < 0x10100000L md = EVP_get_digestbynid(OBJ_obj2nid(x->sig_alg->algorithm)); +#else + md = EVP_get_digestbynid(X509_get_signature_nid(x)); +#endif /* Override digest as specified by RFC 5929 section 4.1. */ if (md == NULL || md == EVP_md5() || md == EVP_sha1()) { md = EVP_sha256(); @@ -600,13 +604,25 @@ static char *ssl_var_lookup_ssl_cert(apr_pool_t *p, request_rec *r, X509 *xs, resdup = FALSE; } else if (strcEQ(var, "A_SIG")) { +#if OPENSSL_VERSION_NUMBER < 0x10100000L nid = OBJ_obj2nid((ASN1_OBJECT *)(xs->cert_info->signature->algorithm)); +#else + ASN1_OBJECT *paobj; + X509_ALGOR_get0(&paobj, NULL, NULL, X509_get0_tbs_sigalg(xs)); + nid = OBJ_obj2nid(paobj); +#endif result = apr_pstrdup(p, (nid == NID_undef) ? "UNKNOWN" : OBJ_nid2ln(nid)); resdup = FALSE; } else if (strcEQ(var, "A_KEY")) { +#if OPENSSL_VERSION_NUMBER < 0x10100000L nid = OBJ_obj2nid((ASN1_OBJECT *)(xs->cert_info->key->algor->algorithm)); +#else + ASN1_OBJECT *paobj; + X509_PUBKEY_get0_param(&paobj, NULL, 0, NULL, X509_get_X509_PUBKEY(xs)); + nid = OBJ_obj2nid(paobj); +#endif result = apr_pstrdup(p, (nid == NID_undef) ? "UNKNOWN" : OBJ_nid2ln(nid)); resdup = FALSE; @@ -668,11 +684,15 @@ static char *ssl_var_lookup_ssl_cert_dn(apr_pool_t *p, X509_NAME *xsname, char * for (i = 0; ssl_var_lookup_ssl_cert_dn_rec[i].name != NULL; i++) { if (strEQn(var, ssl_var_lookup_ssl_cert_dn_rec[i].name, varlen) && strlen(ssl_var_lookup_ssl_cert_dn_rec[i].name) == varlen) { +#if OPENSSL_VERSION_NUMBER < 0x10100000L for (j = 0; j < sk_X509_NAME_ENTRY_num((STACK_OF(X509_NAME_ENTRY) *) xsname->entries); j++) { xsne = sk_X509_NAME_ENTRY_value((STACK_OF(X509_NAME_ENTRY) *) - xsname->entries, j); +#else + for (j = 0; j < X509_NAME_entry_count(xsname); j++) { + xsne = X509_NAME_get_entry(xsname, j); +#endif n =OBJ_obj2nid((ASN1_OBJECT *)X509_NAME_ENTRY_get_object(xsne)); @@ -974,7 +994,9 @@ static char *ssl_var_lookup_ssl_version(apr_pool_t *p, char *var) static void extract_dn(apr_table_t *t, apr_hash_t *nids, const char *pfx, X509_NAME *xn, apr_pool_t *p) { +#if OPENSSL_VERSION_NUMBER < 0x10100000L STACK_OF(X509_NAME_ENTRY) *ents = xn->entries; +#endif X509_NAME_ENTRY *xsne; apr_hash_t *count; int i, nid; @@ -984,10 +1006,16 @@ static void extract_dn(apr_table_t *t, apr_hash_t *nids, const char *pfx, count = apr_hash_make(p); /* For each RDN... */ +#if OPENSSL_VERSION_NUMBER < 0x10100000L for (i = 0; i < sk_X509_NAME_ENTRY_num(ents); i++) { const char *tag; xsne = sk_X509_NAME_ENTRY_value(ents, i); +#else + for (i = 0; i < X509_NAME_entry_count(xn); i++) { + const char *tag; + xsne = X509_NAME_get_entry(xn, i); +#endif /* Retrieve the nid, and check whether this is one of the nids * which are to be extracted. */ @@ -1161,7 +1189,11 @@ apr_array_header_t *ssl_ext_list(apr_pool_t *p, conn_rec *c, int peer, for (j = 0; j < count; j++) { X509_EXTENSION *ext = X509_get_ext(xs, j); +#if OPENSSL_VERSION_NUMBER < 0x10100000L if (OBJ_cmp(ext->object, oid) == 0) { +#else + if (OBJ_cmp(X509_EXTENSION_get_object(ext), oid) == 0) { +#endif BIO *bio = BIO_new(BIO_s_mem()); /* We want to obtain a string representation of the extensions diff --git a/modules/ssl/ssl_util_stapling.c b/modules/ssl/ssl_util_stapling.c index 413e40f8b4..1226d9bfde 100644 --- a/modules/ssl/ssl_util_stapling.c +++ b/modules/ssl/ssl_util_stapling.c @@ -91,7 +91,11 @@ static X509 *stapling_get_issuer(modssl_ctx_t *mctx, X509 *x) for (i = 0; i < sk_X509_num(extra_certs); i++) { issuer = sk_X509_value(extra_certs, i); if (X509_check_issued(issuer, x) == X509_V_OK) { +#if OPENSSL_VERSION_NUMBER < 0x10100000L CRYPTO_add(&issuer->references, 1, CRYPTO_LOCK_X509); +#else + X509_up_ref(issuer); +#endif return issuer; } } @@ -168,6 +172,10 @@ int ssl_stapling_init_cert(server_rec *s, apr_pool_t *p, apr_pool_t *ptemp, apr_pool_cleanup_null); if (aia) { /* allocate uri from the pconf pool */ + /* XXX: OpenSSL 1.1.0: Compiler warning: passing argument 1 of 'sk_value' + * from incompatible pointer type expected 'const struct _STACK *' + * but argument is of type 'struct stack_st_OPENSSL_STRING *' + */ cinf->uri = apr_pstrdup(p, sk_OPENSSL_STRING_value(aia, 0)); X509_email_free(aia); } @@ -398,7 +406,13 @@ static int stapling_check_response(server_rec *s, modssl_ctx_t *mctx, if (bio) { int n; +#if OPENSSL_VERSION_NUMBER < 0x10100000L if ((i2a_ASN1_INTEGER(bio, cinf->cid->serialNumber) != -1) && +#else + ASN1_INTEGER *pserial; + OCSP_id_get0_info(NULL, NULL, NULL, &pserial, cinf->cid); + if ((i2a_ASN1_INTEGER(bio, pserial) != -1) && +#endif ((n = BIO_read(bio, snum, sizeof snum - 1)) > 0)) snum[n] = '\0'; BIO_free(bio); -- 2.50.0