Skip to content

Commit fc5f6c8

Browse files
committed
Handle tls 1.3 renegotiation
1 parent 807c5e4 commit fc5f6c8

File tree

6 files changed

+51
-6
lines changed

6 files changed

+51
-6
lines changed

src/libmongoc/src/mongoc/mongoc-client.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -825,7 +825,8 @@ mongoc_client_connect(bool use_ssl,
825825
base_stream, host->host, ssl_opts, true, (SSL_CTX *)openssl_ctx_void);
826826
#elif defined(MONGOC_ENABLE_SSL_SECURE_CHANNEL)
827827
// Use shared Secure Channel credentials.
828-
base_stream = mongoc_stream_tls_new_with_secure_channel_cred(base_stream, ssl_opts, secure_channel_cred_ptr);
828+
base_stream =
829+
mongoc_stream_tls_new_with_secure_channel_cred(base_stream, host->host, ssl_opts, secure_channel_cred_ptr);
829830
#else
830831
base_stream = mongoc_stream_tls_new_with_hostname(base_stream, host->host, ssl_opts, true);
831832
#endif

src/libmongoc/src/mongoc/mongoc-stream-tls-private.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ mongoc_stream_tls_new_with_hostname_and_openssl_context(mongoc_stream_t *base_st
5858
#elif defined(MONGOC_ENABLE_SSL_SECURE_CHANNEL)
5959
mongoc_stream_t *
6060
mongoc_stream_tls_new_with_secure_channel_cred(mongoc_stream_t *base_stream,
61+
const char *host,
6162
mongoc_ssl_opt_t *opt,
6263
mongoc_shared_ptr secure_channel_cred_ptr) BSON_GNUC_WARN_UNUSED_RESULT;
6364
#endif // MONGOC_ENABLE_SSL_SECURE_CHANNEL

src/libmongoc/src/mongoc/mongoc-stream-tls-secure-channel-private.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
#ifdef MONGOC_ENABLE_SSL_SECURE_CHANNEL
2323
#include <mongoc/mongoc-shared-private.h>
2424

25+
#include <mongoc/mongoc-stream-tls.h>
26+
2527
#include <bson/bson.h>
2628

2729
#include <subauth.h>
@@ -73,6 +75,8 @@ typedef struct {
7375
*/
7476
typedef struct {
7577
ssl_connect_state connecting_state;
78+
mongoc_stream_tls_t *tls; /* back pointer to parent */
79+
char *hostname; /* the host name the stream was created with */
7680
mongoc_shared_ptr cred_ptr; // Manages a mongoc_secure_channel_cred.
7781
mongoc_secure_channel_cred_handle *cred_handle;
7882
mongoc_secure_channel_ctxt *ctxt;
@@ -83,6 +87,7 @@ typedef struct {
8387
unsigned long req_flags, ret_flags;
8488
int recv_unrecoverable_err; /* _mongoc_stream_tls_secure_channel_read had an
8589
unrecoverable err */
90+
bool recv_renegotiate; /* true if server requests renegotiation on TLS 1.3 */
8691
bool recv_sspi_close_notify; /* true if connection closed by close_notify */
8792
bool recv_connection_closed; /* true if connection closed, regardless how */
8893
} mongoc_stream_tls_secure_channel_t;
@@ -99,6 +104,7 @@ mongoc_secure_channel_cred_deleter(void *cred_void);
99104

100105
struct _mongoc_stream_t *
101106
mongoc_stream_tls_secure_channel_new_with_creds(struct _mongoc_stream_t *base_stream,
107+
const char *host,
102108
const struct _mongoc_ssl_opt_t *opt,
103109
mongoc_shared_ptr cred_ptr /* optional */);
104110

src/libmongoc/src/mongoc/mongoc-stream-tls-secure-channel.c

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -465,6 +465,7 @@ _mongoc_stream_tls_secure_channel_decrypt(mongoc_stream_tls_secure_channel_t *se
465465
{
466466
size_t size = 0;
467467
size_t remaining;
468+
bool secbuf_extra_received = false;
468469
SecBuffer inbuf[4];
469470
SecBufferDesc inbuf_desc;
470471
SECURITY_STATUS sspi_status = SEC_E_OK;
@@ -475,6 +476,8 @@ _mongoc_stream_tls_secure_channel_decrypt(mongoc_stream_tls_secure_channel_t *se
475476

476477
/* decrypt loop */
477478
while (secure_channel->encdata_offset > 0 && sspi_status == SEC_E_OK) {
479+
secbuf_extra_received = false;
480+
478481
/* prepare data buffer for DecryptMessage call */
479482
_mongoc_secure_channel_init_sec_buffer(&inbuf[0],
480483
SECBUFFER_DATA,
@@ -535,6 +538,8 @@ _mongoc_stream_tls_secure_channel_decrypt(mongoc_stream_tls_secure_channel_t *se
535538
secure_channel->encdata_offset = inbuf[3].cbBuffer;
536539
}
537540

541+
secbuf_extra_received = true;
542+
538543
TRACE("encrypted data cached: offset %d length %d",
539544
(int)secure_channel->encdata_offset,
540545
(int)secure_channel->encdata_length);
@@ -547,6 +552,27 @@ _mongoc_stream_tls_secure_channel_decrypt(mongoc_stream_tls_secure_channel_t *se
547552
/* check if server wants to renegotiate the connection context */
548553
if (sspi_status == SEC_I_RENEGOTIATE) {
549554
TRACE("%s", "remote party requests renegotiation");
555+
556+
if (secbuf_extra_received) {
557+
bool ret;
558+
bson_error_t error;
559+
560+
secure_channel->recv_renegotiate = true;
561+
562+
/* the tls handshake will pass the contents of SECBUFFER_EXTRA to the server */
563+
secure_channel->connecting_state = ssl_connect_2_writing;
564+
ret = mongoc_secure_channel_handshake_step_2(secure_channel->tls, secure_channel->hostname, &error);
565+
if (!ret) {
566+
TRACE("TLS 1.3 renegotiation failed: %s", error.message);
567+
secure_channel->recv_unrecoverable_err = true;
568+
return;
569+
}
570+
571+
/* now continue decrypting data */
572+
secure_channel->connecting_state = ssl_connect_done;
573+
sspi_status = SEC_E_OK;
574+
continue;
575+
}
550576
}
551577
/* check if the server closed the connection */
552578
else if (sspi_status == SEC_I_CONTEXT_EXPIRED) {
@@ -679,6 +705,12 @@ _mongoc_stream_tls_secure_channel_readv(
679705
ssize_t read_ret = _mongoc_stream_tls_secure_channel_read(
680706
stream, (char *)iov[i].iov_base + iov_pos, (int)(iov[i].iov_len - iov_pos));
681707

708+
/* used up all read bytes for tls renegotiation, try reading again to get next message */
709+
if (read_ret == 0 && secure_channel->recv_renegotiate) {
710+
secure_channel->recv_renegotiate = false;
711+
continue;
712+
}
713+
682714
if (read_ret < 0) {
683715
RETURN(-1);
684716
}
@@ -1011,13 +1043,13 @@ mongoc_secure_channel_cred_deleter(void *cred_void)
10111043
mongoc_stream_t *
10121044
mongoc_stream_tls_secure_channel_new(mongoc_stream_t *base_stream, const char *host, mongoc_ssl_opt_t *opt, int client)
10131045
{
1014-
BSON_UNUSED(host);
10151046
BSON_UNUSED(client);
1016-
return mongoc_stream_tls_secure_channel_new_with_creds(base_stream, opt, MONGOC_SHARED_PTR_NULL);
1047+
return mongoc_stream_tls_secure_channel_new_with_creds(base_stream, host, opt, MONGOC_SHARED_PTR_NULL);
10171048
}
10181049

10191050
mongoc_stream_t *
10201051
mongoc_stream_tls_secure_channel_new_with_creds(mongoc_stream_t *base_stream,
1052+
const char *host,
10211053
const mongoc_ssl_opt_t *opt,
10221054
mongoc_shared_ptr cred_ptr)
10231055
{
@@ -1032,6 +1064,8 @@ mongoc_stream_tls_secure_channel_new_with_creds(mongoc_stream_t *base_stream,
10321064

10331065
secure_channel = (mongoc_stream_tls_secure_channel_t *)bson_malloc0(sizeof *secure_channel);
10341066

1067+
secure_channel->hostname = bson_strdup(host);
1068+
10351069
secure_channel->decdata_buffer = bson_malloc(MONGOC_SCHANNEL_BUFFER_INIT_SIZE);
10361070
secure_channel->decdata_length = MONGOC_SCHANNEL_BUFFER_INIT_SIZE;
10371071
secure_channel->encdata_buffer = bson_malloc(MONGOC_SCHANNEL_BUFFER_INIT_SIZE);
@@ -1056,6 +1090,8 @@ mongoc_stream_tls_secure_channel_new_with_creds(mongoc_stream_t *base_stream,
10561090
tls->timeout_msec = -1;
10571091
tls->base_stream = base_stream;
10581092

1093+
secure_channel->tls = tls;
1094+
10591095
TRACE("%s", "SSL/TLS connection with endpoint AcquireCredentialsHandle");
10601096

10611097
/* setup Schannel API options */

src/libmongoc/src/mongoc/mongoc-stream-tls.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,7 @@ mongoc_stream_tls_new_with_hostname_and_openssl_context(
222222
// Returns a new stream on success. Returns `NULL` on failure.
223223
mongoc_stream_t *
224224
mongoc_stream_tls_new_with_secure_channel_cred(mongoc_stream_t *base_stream,
225+
const char *host,
225226
mongoc_ssl_opt_t *opt,
226227
mongoc_shared_ptr secure_channel_cred_ptr)
227228
{
@@ -232,7 +233,7 @@ mongoc_stream_tls_new_with_secure_channel_cred(mongoc_stream_t *base_stream,
232233
// For compatibility with `mongoc_stream_tls_new_with_hostname`, modify `opt` directly:
233234
opt->allow_invalid_hostname = true;
234235
}
235-
return mongoc_stream_tls_secure_channel_new_with_creds(base_stream, opt, secure_channel_cred_ptr);
236+
return mongoc_stream_tls_secure_channel_new_with_creds(base_stream, host, opt, secure_channel_cred_ptr);
236237
}
237238
#endif // MONGOC_ENABLE_SSL_SECURE_CHANNEL
238239

src/libmongoc/src/mongoc/mongoc-topology-scanner.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -856,8 +856,8 @@ _mongoc_topology_scanner_node_setup_stream_for_tls(mongoc_topology_scanner_node_
856856
tls_stream = mongoc_stream_tls_new_with_hostname_and_openssl_context(
857857
stream, node->host.host, node->ts->ssl_opts, 1, node->ts->openssl_ctx);
858858
#elif defined(MONGOC_ENABLE_SSL_SECURE_CHANNEL)
859-
tls_stream =
860-
mongoc_stream_tls_new_with_secure_channel_cred(stream, node->ts->ssl_opts, node->ts->secure_channel_cred_ptr);
859+
tls_stream = mongoc_stream_tls_new_with_secure_channel_cred(
860+
stream, node->host.host, node->ts->ssl_opts, node->ts->secure_channel_cred_ptr);
861861
#else
862862
tls_stream = mongoc_stream_tls_new_with_hostname(stream, node->host.host, node->ts->ssl_opts, 1);
863863
#endif

0 commit comments

Comments
 (0)