Skip to content

Commit d3bb538

Browse files
committed
Handle tls 1.3 renegotiation
1 parent f7a39ca commit d3bb538

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> // For SCH_CREDENTIALS
@@ -77,6 +79,8 @@ typedef struct {
7779
*/
7880
typedef struct {
7981
ssl_connect_state connecting_state;
82+
mongoc_stream_tls_t *tls; /* back pointer to parent */
83+
char *hostname; /* the host name the stream was created with */
8084
mongoc_shared_ptr cred_ptr; // Manages a mongoc_secure_channel_cred.
8185
mongoc_secure_channel_cred_handle *cred_handle;
8286
mongoc_secure_channel_ctxt *ctxt;
@@ -87,6 +91,7 @@ typedef struct {
8791
unsigned long req_flags, ret_flags;
8892
int recv_unrecoverable_err; /* _mongoc_stream_tls_secure_channel_read had an
8993
unrecoverable err */
94+
bool recv_renegotiate; /* true if server requests renegotiation on TLS 1.3 */
9095
bool recv_sspi_close_notify; /* true if connection closed by close_notify */
9196
bool recv_connection_closed; /* true if connection closed, regardless how */
9297
} mongoc_stream_tls_secure_channel_t;
@@ -103,6 +108,7 @@ mongoc_secure_channel_cred_deleter(void *cred_void);
103108

104109
struct _mongoc_stream_t *
105110
mongoc_stream_tls_secure_channel_new_with_creds(struct _mongoc_stream_t *base_stream,
111+
const char *host,
106112
const struct _mongoc_ssl_opt_t *opt,
107113
mongoc_shared_ptr cred_ptr /* optional */);
108114

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

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -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)
9901022
mongoc_stream_t *
9911023
mongoc_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

9981029
mongoc_stream_t *
9991030
mongoc_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 */

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)