Skip to content

Commit 6c60125

Browse files
committed
Merge branch 'cdriver-6045-renegotiation' of https://github.com/Julia-Garland/mongo-c-driver into cdriver-6045-renegotiation
2 parents d937319 + fc5f6c8 commit 6c60125

File tree

3 files changed

+55
-0
lines changed

3 files changed

+55
-0
lines changed

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

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424

2525
#include <mongoc/mongoc-stream-tls.h>
2626

27+
#include <mongoc/mongoc-stream-tls.h>
28+
2729
#include <bson/bson.h>
2830

2931
#include <subauth.h> // For SCH_CREDENTIALS
@@ -54,6 +56,9 @@ typedef enum {
5456
/* enum for underlying type cred field in mongoc_secure_channel_cred */
5557
typedef enum { schannel_cred, sch_credentials } schannel_credential_type;
5658

59+
/* enum for underlying type cred field in mongoc_secure_channel_cred */
60+
typedef enum { schannel_cred, sch_credentials } schannel_credential_type;
61+
5762
/* Structs to store Schannel handles */
5863
typedef struct {
5964
CredHandle cred_handle;
@@ -65,6 +70,9 @@ typedef struct _mongoc_secure_channel_cred {
6570
PCCERT_CONTEXT cert; /* Owning. Optional client cert. */
6671
schannel_credential_type cred_type;
6772
void *cred; /* Underlying type is specified by schannel_credential_type. */
73+
PCCERT_CONTEXT cert; /* Owning. Optional client cert. */
74+
schannel_credential_type cred_type;
75+
void *cred; /* Underlying type is specified by schannel_credential_type. */
6876
} mongoc_secure_channel_cred;
6977

7078
typedef struct {
@@ -81,6 +89,8 @@ typedef struct {
8189
ssl_connect_state connecting_state;
8290
mongoc_stream_tls_t *tls; /* back pointer to parent */
8391
char *hostname; /* the host name the stream was created with */
92+
mongoc_stream_tls_t *tls; /* back pointer to parent */
93+
char *hostname; /* the host name the stream was created with */
8494
mongoc_shared_ptr cred_ptr; // Manages a mongoc_secure_channel_cred.
8595
mongoc_secure_channel_cred_handle *cred_handle;
8696
mongoc_secure_channel_ctxt *ctxt;
@@ -92,6 +102,7 @@ typedef struct {
92102
int recv_unrecoverable_err; /* _mongoc_stream_tls_secure_channel_read had an
93103
unrecoverable err */
94104
bool recv_renegotiate; /* true if server requests renegotiation on TLS 1.3 */
105+
bool recv_renegotiate; /* true if server requests renegotiation on TLS 1.3 */
95106
bool recv_sspi_close_notify; /* true if connection closed by close_notify */
96107
bool recv_connection_closed; /* true if connection closed, regardless how */
97108
} mongoc_stream_tls_secure_channel_t;

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

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,10 +78,12 @@
7878

7979
#define SECURITY_WIN32
8080
#define SCHANNEL_USE_BLACKLISTS 1
81+
#define SCHANNEL_USE_BLACKLISTS 1
8182
#include <schannel.h>
8283
#include <schnlsp.h>
8384
#include <security.h>
8485
#include <versionhelpers.h>
86+
#include <versionhelpers.h>
8587

8688

8789
/* mingw doesn't define these */
@@ -467,6 +469,7 @@ _mongoc_stream_tls_secure_channel_decrypt(mongoc_stream_tls_secure_channel_t *se
467469
size_t size = 0;
468470
size_t remaining;
469471
bool secbuf_extra_received = false;
472+
bool secbuf_extra_received = false;
470473
SecBuffer inbuf[4];
471474
SecBufferDesc inbuf_desc;
472475
SECURITY_STATUS sspi_status = SEC_E_OK;
@@ -479,6 +482,8 @@ _mongoc_stream_tls_secure_channel_decrypt(mongoc_stream_tls_secure_channel_t *se
479482
while (secure_channel->encdata_offset > 0 && sspi_status == SEC_E_OK) {
480483
secbuf_extra_received = false;
481484

485+
secbuf_extra_received = false;
486+
482487
/* prepare data buffer for DecryptMessage call */
483488
_mongoc_secure_channel_init_sec_buffer(&inbuf[0],
484489
SECBUFFER_DATA,
@@ -541,6 +546,8 @@ _mongoc_stream_tls_secure_channel_decrypt(mongoc_stream_tls_secure_channel_t *se
541546

542547
secbuf_extra_received = true;
543548

549+
secbuf_extra_received = true;
550+
544551
TRACE("encrypted data cached: offset %d length %d",
545552
(int)secure_channel->encdata_offset,
546553
(int)secure_channel->encdata_length);
@@ -574,6 +581,27 @@ _mongoc_stream_tls_secure_channel_decrypt(mongoc_stream_tls_secure_channel_t *se
574581
sspi_status = SEC_E_OK;
575582
continue;
576583
}
584+
585+
if (secbuf_extra_received) {
586+
bool ret;
587+
bson_error_t error;
588+
589+
secure_channel->recv_renegotiate = true;
590+
591+
/* the tls handshake will pass the contents of SECBUFFER_EXTRA to the server */
592+
secure_channel->connecting_state = ssl_connect_2_writing;
593+
ret = mongoc_secure_channel_handshake_step_2(secure_channel->tls, secure_channel->hostname, &error);
594+
if (!ret) {
595+
TRACE("TLS 1.3 renegotiation failed: %s", error.message);
596+
secure_channel->recv_unrecoverable_err = true;
597+
return;
598+
}
599+
600+
/* now continue decrypting data */
601+
secure_channel->connecting_state = ssl_connect_done;
602+
sspi_status = SEC_E_OK;
603+
continue;
604+
}
577605
}
578606
/* check if the server closed the connection */
579607
else if (sspi_status == SEC_I_CONTEXT_EXPIRED) {
@@ -712,6 +740,12 @@ _mongoc_stream_tls_secure_channel_readv(
712740
continue;
713741
}
714742

743+
/* used up all read bytes for tls renegotiation, try reading again to get next message */
744+
if (read_ret == 0 && secure_channel->recv_renegotiate) {
745+
secure_channel->recv_renegotiate = false;
746+
continue;
747+
}
748+
715749
if (read_ret < 0) {
716750
RETURN(-1);
717751
}
@@ -998,6 +1032,8 @@ mongoc_secure_channel_cred_new(const mongoc_ssl_opt_t *opt)
9981032
#else
9991033
cred->cred = _mongoc_secure_channel_schannel_cred_new(opt, &cred->cert, enabled_protocols);
10001034
cred->cred_type = schannel_cred;
1035+
cred->cred = _mongoc_secure_channel_schannel_cred_new(opt, &cred->cert, enabled_protocols);
1036+
cred->cred_type = schannel_cred;
10011037
#endif
10021038

10031039
return cred;
@@ -1026,10 +1062,12 @@ mongoc_stream_tls_secure_channel_new(mongoc_stream_t *base_stream, const char *h
10261062
{
10271063
BSON_UNUSED(client);
10281064
return mongoc_stream_tls_secure_channel_new_with_creds(base_stream, host, opt, MONGOC_SHARED_PTR_NULL);
1065+
return mongoc_stream_tls_secure_channel_new_with_creds(base_stream, host, opt, MONGOC_SHARED_PTR_NULL);
10291066
}
10301067

10311068
mongoc_stream_t *
10321069
mongoc_stream_tls_secure_channel_new_with_creds(mongoc_stream_t *base_stream,
1070+
const char *host,
10331071
const char *host,
10341072
const mongoc_ssl_opt_t *opt,
10351073
mongoc_shared_ptr cred_ptr)
@@ -1047,6 +1085,8 @@ mongoc_stream_tls_secure_channel_new_with_creds(mongoc_stream_t *base_stream,
10471085

10481086
secure_channel->hostname = bson_strdup(host);
10491087

1088+
secure_channel->hostname = bson_strdup(host);
1089+
10501090
secure_channel->decdata_buffer = bson_malloc(MONGOC_SCHANNEL_BUFFER_INIT_SIZE);
10511091
secure_channel->decdata_length = MONGOC_SCHANNEL_BUFFER_INIT_SIZE;
10521092
secure_channel->encdata_buffer = bson_malloc(MONGOC_SCHANNEL_BUFFER_INIT_SIZE);
@@ -1073,6 +1113,8 @@ mongoc_stream_tls_secure_channel_new_with_creds(mongoc_stream_t *base_stream,
10731113

10741114
secure_channel->tls = tls;
10751115

1116+
secure_channel->tls = tls;
1117+
10761118
TRACE("%s", "SSL/TLS connection with endpoint AcquireCredentialsHandle");
10771119

10781120
/* setup Schannel API options */
@@ -1099,6 +1141,7 @@ mongoc_stream_tls_secure_channel_new_with_creds(mongoc_stream_t *base_stream,
10991141
SECPKG_CRED_OUTBOUND, /* we are preparing outbound connection */
11001142
NULL, /* Optional logon */
11011143
cred->cred, /* TLS "configuration", "auth data" */
1144+
cred->cred, /* TLS "configuration", "auth data" */
11021145
NULL, /* unused */
11031146
NULL, /* unused */
11041147
&secure_channel->cred_handle->cred_handle, /* credential OUT param */

src/libmongoc/tests/test-mongoc-secure-channel.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ test_secure_channel_shared_creds_stream(void *unused)
9696
mongoc_shared_ptr_reset_null(&cred_ptr);
9797
}
9898

99+
// Test with bad SCHANNEL CREDENTIALS to exercise error path:
99100
// Test with bad SCHANNEL CREDENTIALS to exercise error path:
100101
{
101102
mongoc_secure_channel_cred *cred = mongoc_secure_channel_cred_new(&ssl_opt);

0 commit comments

Comments
 (0)