ASF Bugzilla – Attachment 36385 Details for
Bug 63097
TLS 1.3: Support "SSLOptions OptRenegotiate"
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Implement OptRenegotiate for TLS 1.3
quick_renegotiation.patch (text/plain), 11.02 KB, created by
Michael Kaufmann
on 2019-01-21 17:18:32 UTC
(
hide
)
Description:
Implement OptRenegotiate for TLS 1.3
Filename:
MIME Type:
Creator:
Michael Kaufmann
Created:
2019-01-21 17:18:32 UTC
Size:
11.02 KB
patch
obsolete
>diff --git a/modules/ssl/ssl_engine_kernel.c b/modules/ssl/ssl_engine_kernel.c >index 1570d8da64..06c7d6e234 100644 >--- a/modules/ssl/ssl_engine_kernel.c >+++ b/modules/ssl/ssl_engine_kernel.c >@@ -476,6 +476,84 @@ static int ssl_check_post_client_verify(request_rec *r, SSLSrvConfigRec *sc, > return OK; > } > >+static int ssl_renegotiate_quick(request_rec *r, SSL *ssl) >+{ >+ SSL_CTX *ctx = ssl ? SSL_get_SSL_CTX(ssl) : NULL; >+ X509_STORE *cert_store = NULL; >+ X509_STORE_CTX *cert_store_ctx; >+ STACK_OF(X509) *cert_stack; >+ X509 *cert; >+ int depth; >+ >+ /* perform just a manual re-verification of the peer */ >+ ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(02258) >+ "Performing quick renegotiation: " >+ "just re-verifying the peer"); >+ >+ cert_stack = (STACK_OF(X509) *)SSL_get_peer_cert_chain(ssl); >+ >+ cert = SSL_get_peer_certificate(ssl); >+ >+ if (!cert_stack || (sk_X509_num(cert_stack) == 0)) { >+ if (!cert) { >+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02222) >+ "Cannot find peer certificate chain"); >+ >+ return HTTP_FORBIDDEN; >+ } >+ >+ /* client cert is in the session cache, but there is >+ * no chain, since ssl3_get_client_certificate() >+ * sk_X509_shift-ed the peer cert out of the chain. >+ * we put it back here for the purpose of quick_renegotiation. >+ */ >+ cert_stack = sk_X509_new_null(); >+ sk_X509_push(cert_stack, cert); >+ } >+ >+ if (!(cert_store || >+ (cert_store = SSL_CTX_get_cert_store(ctx)))) >+ { >+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02223) >+ "Cannot find certificate storage"); >+ >+ return HTTP_FORBIDDEN; >+ } >+ >+ if (!cert) { >+ cert = sk_X509_value(cert_stack, 0); >+ } >+ >+ cert_store_ctx = X509_STORE_CTX_new(); >+ X509_STORE_CTX_init(cert_store_ctx, cert_store, cert, cert_stack); >+ depth = SSL_get_verify_depth(ssl); >+ >+ if (depth >= 0) { >+ X509_STORE_CTX_set_depth(cert_store_ctx, depth); >+ } >+ >+ X509_STORE_CTX_set_ex_data(cert_store_ctx, >+ SSL_get_ex_data_X509_STORE_CTX_idx(), >+ (char *)ssl); >+ >+ if (!X509_verify_cert(cert_store_ctx)) { >+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02224) >+ "Re-negotiation verification step failed"); >+ ssl_log_ssl_error(SSLLOG_MARK, APLOG_ERR, r->server); >+ } >+ >+ SSL_set_verify_result(ssl, X509_STORE_CTX_get_error(cert_store_ctx)); >+ X509_STORE_CTX_cleanup(cert_store_ctx); >+ X509_STORE_CTX_free(cert_store_ctx); >+ >+ if (cert_stack != SSL_get_peer_cert_chain(ssl)) { >+ /* we created this ourselves, so free it */ >+ sk_X509_pop_free(cert_stack, X509_free); >+ } >+ >+ return OK; >+} >+ > /* > * Access Handler, classic flavour, for SSL/TLS up to v1.2 > * where everything can be renegotiated and no one is happy. >@@ -485,14 +563,11 @@ static int ssl_hook_Access_classic(request_rec *r, SSLSrvConfigRec *sc, SSLDirCo > { > server_rec *handshakeserver = sslconn ? sslconn->server : NULL; > SSLSrvConfigRec *hssc = handshakeserver? mySrvConfig(handshakeserver) : NULL; >- SSL_CTX *ctx = ssl ? SSL_get_SSL_CTX(ssl) : NULL; > BOOL renegotiate = FALSE, renegotiate_quick = FALSE; > X509 *peercert; >- X509_STORE *cert_store = NULL; >- X509_STORE_CTX *cert_store_ctx; > STACK_OF(SSL_CIPHER) *cipher_list_old = NULL, *cipher_list = NULL; > const SSL_CIPHER *cipher = NULL; >- int depth, verify_old, verify, n, rc; >+ int verify_old, verify, n, rc; > const char *ncipher_suite; > > #ifdef HAVE_SRP >@@ -871,73 +946,8 @@ static int ssl_hook_Access_classic(request_rec *r, SSLSrvConfigRec *sc, SSLDirCo > "Requesting connection re-negotiation"); > > if (renegotiate_quick) { >- STACK_OF(X509) *cert_stack; >- X509 *cert; >- >- /* perform just a manual re-verification of the peer */ >- ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(02258) >- "Performing quick renegotiation: " >- "just re-verifying the peer"); >- >- cert_stack = (STACK_OF(X509) *)SSL_get_peer_cert_chain(ssl); >- >- cert = SSL_get_peer_certificate(ssl); >- >- if (!cert_stack || (sk_X509_num(cert_stack) == 0)) { >- if (!cert) { >- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02222) >- "Cannot find peer certificate chain"); >- >- return HTTP_FORBIDDEN; >- } >- >- /* client cert is in the session cache, but there is >- * no chain, since ssl3_get_client_certificate() >- * sk_X509_shift-ed the peer cert out of the chain. >- * we put it back here for the purpose of quick_renegotiation. >- */ >- cert_stack = sk_X509_new_null(); >- sk_X509_push(cert_stack, cert); >- } >- >- if (!(cert_store || >- (cert_store = SSL_CTX_get_cert_store(ctx)))) >- { >- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02223) >- "Cannot find certificate storage"); >- >- return HTTP_FORBIDDEN; >- } >- >- if (!cert) { >- cert = sk_X509_value(cert_stack, 0); >- } >- >- cert_store_ctx = X509_STORE_CTX_new(); >- X509_STORE_CTX_init(cert_store_ctx, cert_store, cert, cert_stack); >- depth = SSL_get_verify_depth(ssl); >- >- if (depth >= 0) { >- X509_STORE_CTX_set_depth(cert_store_ctx, depth); >- } >- >- X509_STORE_CTX_set_ex_data(cert_store_ctx, >- SSL_get_ex_data_X509_STORE_CTX_idx(), >- (char *)ssl); >- >- if (!X509_verify_cert(cert_store_ctx)) { >- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02224) >- "Re-negotiation verification step failed"); >- ssl_log_ssl_error(SSLLOG_MARK, APLOG_ERR, r->server); >- } >- >- SSL_set_verify_result(ssl, X509_STORE_CTX_get_error(cert_store_ctx)); >- X509_STORE_CTX_cleanup(cert_store_ctx); >- X509_STORE_CTX_free(cert_store_ctx); >- >- if (cert_stack != SSL_get_peer_cert_chain(ssl)) { >- /* we created this ourselves, so free it */ >- sk_X509_pop_free(cert_stack, X509_free); >+ if (OK != (rc = ssl_renegotiate_quick(r, ssl))) { >+ return rc; > } > } > else { >@@ -1066,6 +1076,7 @@ static int ssl_hook_Access_modern(request_rec *r, SSLSrvConfigRec *sc, SSLDirCon > (sc->server->auth.verify_mode != SSL_CVERIFY_UNSET)) { > int vmode_inplace, vmode_needed; > int change_vmode = FALSE; >+ BOOL renegotiate_quick = FALSE; > int old_state, n, rc; > > vmode_inplace = SSL_get_verify_mode(ssl); >@@ -1097,8 +1108,21 @@ static int ssl_hook_Access_modern(request_rec *r, SSLSrvConfigRec *sc, SSLDirCon > && (vmode_needed & SSL_VERIFY_PEER)) > || (!(vmode_inplace & SSL_VERIFY_FAIL_IF_NO_PEER_CERT) > && (vmode_needed & SSL_VERIFY_FAIL_IF_NO_PEER_CERT))) { >+ >+ X509 *peercert; >+ > /* need to change the effective verify mode */ > change_vmode = TRUE; >+ >+ /* optimization */ >+ >+ if ((dc->nOptions & SSL_OPT_OPTRENEGOTIATE) && >+ (vmode_inplace == SSL_VERIFY_NONE) && >+ ((peercert = SSL_get_peer_certificate(ssl)) != NULL)) >+ { >+ renegotiate_quick = TRUE; >+ X509_free(peercert); >+ } > } > else { > /* FIXME: does this work with TLSv1.3? Is this more than re-inspecting >@@ -1133,8 +1157,6 @@ static int ssl_hook_Access_modern(request_rec *r, SSLSrvConfigRec *sc, SSLDirCon > } > > if (change_vmode) { >- char peekbuf[1]; >- > if (r->connection->master) { > /* FIXME: modifying the SSL on a slave connection is no good. > * We would need to push this back to the master connection >@@ -1146,30 +1168,39 @@ static int ssl_hook_Access_modern(request_rec *r, SSLSrvConfigRec *sc, SSLDirCon > > ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(10129) "verify client post handshake"); > >- SSL_set_verify(ssl, vmode_needed, ssl_callback_SSLVerify); >- >- if (SSL_verify_client_post_handshake(ssl) != 1) { >- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(10158) >- "cannot perform post-handshake authentication"); >- ssl_log_ssl_error(SSLLOG_MARK, APLOG_ERR, r->server); >- apr_table_setn(r->notes, "error-notes", >- "Reason: Cannot perform Post-Handshake Authentication.<br />"); >- return HTTP_FORBIDDEN; >+ if (renegotiate_quick) { >+ if (OK != (rc = ssl_renegotiate_quick(r, ssl))) { >+ return rc; >+ } > } >- >- old_state = sslconn->reneg_state; >- sslconn->reneg_state = RENEG_ALLOW; >- modssl_set_app_data2(ssl, r); >+ else { >+ char peekbuf[1]; > >- SSL_do_handshake(ssl); >- /* Need to trigger renegotiation handshake by reading. >- * Peeking 0 bytes actually works. >- * See: http://marc.info/?t=145493359200002&r=1&w=2 >- */ >- SSL_peek(ssl, peekbuf, 0); >+ SSL_set_verify(ssl, vmode_needed, ssl_callback_SSLVerify); >+ >+ if (SSL_verify_client_post_handshake(ssl) != 1) { >+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(10158) >+ "cannot perform post-handshake authentication"); >+ ssl_log_ssl_error(SSLLOG_MARK, APLOG_ERR, r->server); >+ apr_table_setn(r->notes, "error-notes", >+ "Reason: Cannot perform Post-Handshake Authentication.<br />"); >+ return HTTP_FORBIDDEN; >+ } >+ >+ old_state = sslconn->reneg_state; >+ sslconn->reneg_state = RENEG_ALLOW; >+ modssl_set_app_data2(ssl, r); > >- sslconn->reneg_state = old_state; >- modssl_set_app_data2(ssl, NULL); >+ SSL_do_handshake(ssl); >+ /* Need to trigger renegotiation handshake by reading. >+ * Peeking 0 bytes actually works. >+ * See: http://marc.info/?t=145493359200002&r=1&w=2 >+ */ >+ SSL_peek(ssl, peekbuf, 0); >+ >+ sslconn->reneg_state = old_state; >+ modssl_set_app_data2(ssl, NULL); >+ } > > /* > * Finally check for acceptable renegotiation results
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 63097
: 36385