Index: doc/tls.html ================================================================== --- doc/tls.html +++ doc/tls.html @@ -171,10 +171,12 @@
Callback to invoke when OpenSSL needs to obtain a password, typically to unlock the private key of a certificate. The callback should return a string which represents the password to be used. See CALLBACK OPTIONS for further discussion.
+
-post_handshake bool
+
Allow post-handshake ticket updates.
-request bool
Request a certificate from peer during SSL handshake. (default is true)
-require bool
Require a valid certificate from peer during SSL handshake. Index: generic/tls.c ================================================================== --- generic/tls.c +++ generic/tls.c @@ -1071,11 +1071,11 @@ const unsigned char *session_id = NULL; Tcl_Obj *alpn = NULL; int ssl2 = 0, ssl3 = 0; int tls1 = 1, tls1_1 = 1, tls1_2 = 1, tls1_3 = 1; int proto = 0, level = -1; - int verify = 0, require = 0, request = 1; + int verify = 0, require = 0, request = 1, post_handshake = 0; dprintf("Called"); #if OPENSSL_VERSION_NUMBER < 0x10100000L && !defined(OPENSSL_NO_SSL2) && !defined(NO_SSL2) && defined(NO_SSL3) && defined(NO_TLS1) && defined(NO_TLS1_1) && defined(NO_TLS1_2) && defined(NO_TLS1_3) ssl2 = 1; @@ -1124,10 +1124,11 @@ OPTOBJ("-command", script); OPTSTR("-dhparams", DHparams); OPTSTR("-keyfile", keyfile); OPTSTR("-model", model); OPTOBJ("-password", password); + OPTBOOL("-post_handshake", post_handshake); OPTBOOL("-require", require); OPTBOOL("-request", request); OPTINT("-securitylevel", level); OPTBOOL("-server", server); OPTSTR("-servername", servername); @@ -1146,10 +1147,11 @@ return TCL_ERROR; } if (request) verify |= SSL_VERIFY_CLIENT_ONCE | SSL_VERIFY_PEER; if (request && require) verify |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT; + if (request && post_handshake) verify |= SSL_VERIFY_POST_HANDSHAKE; if (verify == 0) verify = SSL_VERIFY_NONE; proto |= (ssl2 ? TLS_PROTO_SSL2 : 0); proto |= (ssl3 ? TLS_PROTO_SSL3 : 0); proto |= (tls1 ? TLS_PROTO_TLS1 : 0); @@ -1361,17 +1363,27 @@ /* Server callbacks */ SSL_CTX_set_alpn_select_cb(statePtr->ctx, ALPNCallback, (void *)statePtr); SSL_CTX_set_tlsext_servername_arg(statePtr->ctx, (void *)statePtr); SSL_CTX_set_tlsext_servername_callback(statePtr->ctx, SNICallback); SSL_CTX_set_client_hello_cb(statePtr->ctx, HelloCallback, (void *)statePtr); + + /* Enable server to send cert request after handshake (TLS 1.3 only) */ + if (request && post_handshake) { + SSL_verify_client_post_handshake(statePtr->ssl); + } statePtr->flags |= TLS_TCL_SERVER; SSL_set_accept_state(statePtr->ssl); } else { /* Session caching */ SSL_CTX_set_session_cache_mode(statePtr->ctx, SSL_SESS_CACHE_CLIENT | SSL_SESS_CACHE_NO_INTERNAL_STORE); SSL_CTX_sess_set_new_cb(statePtr->ctx, SessionCallback); + + /* Enable post handshake Authentication extension. TLS 1.3 only, not http/2. */ + if (request && post_handshake) { + SSL_set_post_handshake_auth(statePtr->ssl, 1); + } SSL_set_connect_state(statePtr->ssl); } SSL_set_bio(statePtr->ssl, statePtr->p_bio, statePtr->p_bio); BIO_set_ssl(statePtr->bio, statePtr->ssl, BIO_NOCLOSE);