@@ -464,6 +464,7 @@ _mongoc_stream_tls_secure_channel_decrypt(mongoc_stream_tls_secure_channel_t *se
464464{
465465 size_t size = 0 ;
466466 size_t remaining ;
467+ bool secbuf_extra_received = false;
467468 SecBuffer inbuf [4 ];
468469 SecBufferDesc inbuf_desc ;
469470 SECURITY_STATUS sspi_status = SEC_E_OK ;
@@ -474,6 +475,8 @@ _mongoc_stream_tls_secure_channel_decrypt(mongoc_stream_tls_secure_channel_t *se
474475
475476 /* decrypt loop */
476477 while (secure_channel -> encdata_offset > 0 && sspi_status == SEC_E_OK ) {
478+ secbuf_extra_received = false;
479+
477480 /* prepare data buffer for DecryptMessage call */
478481 _mongoc_secure_channel_init_sec_buffer (& inbuf [0 ],
479482 SECBUFFER_DATA ,
@@ -534,6 +537,8 @@ _mongoc_stream_tls_secure_channel_decrypt(mongoc_stream_tls_secure_channel_t *se
534537 secure_channel -> encdata_offset = inbuf [3 ].cbBuffer ;
535538 }
536539
540+ secbuf_extra_received = true;
541+
537542 TRACE ("encrypted data cached: offset %d length %d" ,
538543 (int )secure_channel -> encdata_offset ,
539544 (int )secure_channel -> encdata_length );
@@ -546,6 +551,27 @@ _mongoc_stream_tls_secure_channel_decrypt(mongoc_stream_tls_secure_channel_t *se
546551 /* check if server wants to renegotiate the connection context */
547552 if (sspi_status == SEC_I_RENEGOTIATE ) {
548553 TRACE ("%s" , "remote party requests renegotiation" );
554+
555+ if (secbuf_extra_received ) {
556+ bool ret ;
557+ bson_error_t error ;
558+
559+ secure_channel -> recv_renegotiate = true;
560+
561+ /* the tls handshake will pass the contents of SECBUFFER_EXTRA to the server */
562+ secure_channel -> connecting_state = ssl_connect_2_writing ;
563+ ret = mongoc_secure_channel_handshake_step_2 (secure_channel -> tls , secure_channel -> hostname , & error );
564+ if (!ret ) {
565+ TRACE ("TLS 1.3 renegotiation failed: %s" , error .message );
566+ secure_channel -> recv_unrecoverable_err = true;
567+ return ;
568+ }
569+
570+ /* now continue decrypting data */
571+ secure_channel -> connecting_state = ssl_connect_done ;
572+ sspi_status = SEC_E_OK ;
573+ continue ;
574+ }
549575 }
550576 /* check if the server closed the connection */
551577 else if (sspi_status == SEC_I_CONTEXT_EXPIRED ) {
@@ -678,6 +704,12 @@ _mongoc_stream_tls_secure_channel_readv(
678704 ssize_t read_ret = _mongoc_stream_tls_secure_channel_read (
679705 stream , (char * )iov [i ].iov_base + iov_pos , (int )(iov [i ].iov_len - iov_pos ));
680706
707+ /* used up all read bytes for tls renegotiation, try reading again to get next message */
708+ if (read_ret == 0 && secure_channel -> recv_renegotiate ) {
709+ secure_channel -> recv_renegotiate = false;
710+ continue ;
711+ }
712+
681713 if (read_ret < 0 ) {
682714 RETURN (-1 );
683715 }
@@ -990,13 +1022,13 @@ mongoc_secure_channel_cred_deleter(void *cred_void)
9901022mongoc_stream_t *
9911023mongoc_stream_tls_secure_channel_new (mongoc_stream_t * base_stream , const char * host , mongoc_ssl_opt_t * opt , int client )
9921024{
993- BSON_UNUSED (host );
9941025 BSON_UNUSED (client );
995- return mongoc_stream_tls_secure_channel_new_with_creds (base_stream , opt , MONGOC_SHARED_PTR_NULL );
1026+ return mongoc_stream_tls_secure_channel_new_with_creds (base_stream , host , opt , MONGOC_SHARED_PTR_NULL );
9961027}
9971028
9981029mongoc_stream_t *
9991030mongoc_stream_tls_secure_channel_new_with_creds (mongoc_stream_t * base_stream ,
1031+ const char * host ,
10001032 const mongoc_ssl_opt_t * opt ,
10011033 mongoc_shared_ptr cred_ptr )
10021034{
@@ -1011,6 +1043,8 @@ mongoc_stream_tls_secure_channel_new_with_creds(mongoc_stream_t *base_stream,
10111043
10121044 secure_channel = (mongoc_stream_tls_secure_channel_t * )bson_malloc0 (sizeof * secure_channel );
10131045
1046+ secure_channel -> hostname = bson_strdup (host );
1047+
10141048 secure_channel -> decdata_buffer = bson_malloc (MONGOC_SCHANNEL_BUFFER_INIT_SIZE );
10151049 secure_channel -> decdata_length = MONGOC_SCHANNEL_BUFFER_INIT_SIZE ;
10161050 secure_channel -> encdata_buffer = bson_malloc (MONGOC_SCHANNEL_BUFFER_INIT_SIZE );
@@ -1035,6 +1069,8 @@ mongoc_stream_tls_secure_channel_new_with_creds(mongoc_stream_t *base_stream,
10351069 tls -> timeout_msec = -1 ;
10361070 tls -> base_stream = base_stream ;
10371071
1072+ secure_channel -> tls = tls ;
1073+
10381074 TRACE ("%s" , "SSL/TLS connection with endpoint AcquireCredentialsHandle" );
10391075
10401076 /* setup Schannel API options */
0 commit comments