Skip to content
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .evergreen/generated_configs/legacy-config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10232,6 +10232,13 @@ buildvariants:
- test-aws-openssl-regular-latest
- .authentication-tests .openssl !.sasl
- .authentication-tests .winssl
- name: windows-2022
display_name: Windows (VS 2022)
expansions:
CC: Visual Studio 17 2022 Win64
run_on: windows-vsCurrent-large
tasks:
- .authentication-tests .winssl
- name: mingw-windows2016
display_name: MinGW-W64 (Windows Server 2016)
expansions:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,15 @@ def days(n: int) -> int:
],
{'CC': 'Visual Studio 15 2017 Win64'},
),
Variant(
'windows-2022',
'Windows (VS 2022)',
'windows-vsCurrent-large',
[
'.authentication-tests .winssl',
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I expect the cause of the task failure in the new authentication-tests-winssl task is a missing dependent compile task. The test task tries to download the binaries built in the compile task. Try adding debug-compile-sspi-winssl.

],
{'CC': 'Visual Studio 17 2022 Win64'},
),
Variant(
'mingw-windows2016',
'MinGW-W64 (Windows Server 2016)',
Expand Down
3 changes: 2 additions & 1 deletion src/libmongoc/src/mongoc/mongoc-client.c
Original file line number Diff line number Diff line change
Expand Up @@ -825,7 +825,8 @@ mongoc_client_connect(bool use_ssl,
base_stream, host->host, ssl_opts, true, (SSL_CTX *)openssl_ctx_void);
#elif defined(MONGOC_ENABLE_SSL_SECURE_CHANNEL)
// Use shared Secure Channel credentials.
base_stream = mongoc_stream_tls_new_with_secure_channel_cred(base_stream, ssl_opts, secure_channel_cred_ptr);
base_stream =
mongoc_stream_tls_new_with_secure_channel_cred(base_stream, host->host, ssl_opts, secure_channel_cred_ptr);
#else
base_stream = mongoc_stream_tls_new_with_hostname(base_stream, host->host, ssl_opts, true);
#endif
Expand Down
1 change: 1 addition & 0 deletions src/libmongoc/src/mongoc/mongoc-stream-tls-private.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ mongoc_stream_tls_new_with_hostname_and_openssl_context(mongoc_stream_t *base_st
#elif defined(MONGOC_ENABLE_SSL_SECURE_CHANNEL)
mongoc_stream_t *
mongoc_stream_tls_new_with_secure_channel_cred(mongoc_stream_t *base_stream,
const char *host,
mongoc_ssl_opt_t *opt,
mongoc_shared_ptr secure_channel_cred_ptr) BSON_GNUC_WARN_UNUSED_RESULT;
#endif // MONGOC_ENABLE_SSL_SECURE_CHANNEL
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
#ifdef MONGOC_ENABLE_SSL_SECURE_CHANNEL
#include <mongoc/mongoc-shared-private.h>

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

#include <bson/bson.h>

#include <subauth.h> // For SCH_CREDENTIALS
Expand Down Expand Up @@ -77,6 +79,8 @@ typedef struct {
*/
typedef struct {
ssl_connect_state connecting_state;
mongoc_stream_tls_t *tls; /* back pointer to parent */
char *hostname; /* the host name the stream was created with */
mongoc_shared_ptr cred_ptr; // Manages a mongoc_secure_channel_cred.
mongoc_secure_channel_cred_handle *cred_handle;
mongoc_secure_channel_ctxt *ctxt;
Expand All @@ -87,6 +91,7 @@ typedef struct {
unsigned long req_flags, ret_flags;
int recv_unrecoverable_err; /* _mongoc_stream_tls_secure_channel_read had an
unrecoverable err */
bool recv_renegotiate; /* true if server requests renegotiation on TLS 1.3 */
bool recv_sspi_close_notify; /* true if connection closed by close_notify */
bool recv_connection_closed; /* true if connection closed, regardless how */
} mongoc_stream_tls_secure_channel_t;
Expand All @@ -103,6 +108,7 @@ mongoc_secure_channel_cred_deleter(void *cred_void);

struct _mongoc_stream_t *
mongoc_stream_tls_secure_channel_new_with_creds(struct _mongoc_stream_t *base_stream,
const char *host,
const struct _mongoc_ssl_opt_t *opt,
mongoc_shared_ptr cred_ptr /* optional */);

Expand Down
40 changes: 38 additions & 2 deletions src/libmongoc/src/mongoc/mongoc-stream-tls-secure-channel.c
Original file line number Diff line number Diff line change
Expand Up @@ -464,6 +464,7 @@ _mongoc_stream_tls_secure_channel_decrypt(mongoc_stream_tls_secure_channel_t *se
{
size_t size = 0;
size_t remaining;
bool secbuf_extra_received = false;
SecBuffer inbuf[4];
SecBufferDesc inbuf_desc;
SECURITY_STATUS sspi_status = SEC_E_OK;
Expand All @@ -474,6 +475,8 @@ _mongoc_stream_tls_secure_channel_decrypt(mongoc_stream_tls_secure_channel_t *se

/* decrypt loop */
while (secure_channel->encdata_offset > 0 && sspi_status == SEC_E_OK) {
secbuf_extra_received = false;

/* prepare data buffer for DecryptMessage call */
_mongoc_secure_channel_init_sec_buffer(&inbuf[0],
SECBUFFER_DATA,
Expand Down Expand Up @@ -534,6 +537,8 @@ _mongoc_stream_tls_secure_channel_decrypt(mongoc_stream_tls_secure_channel_t *se
secure_channel->encdata_offset = inbuf[3].cbBuffer;
}

secbuf_extra_received = true;

TRACE("encrypted data cached: offset %d length %d",
(int)secure_channel->encdata_offset,
(int)secure_channel->encdata_length);
Expand All @@ -546,6 +551,27 @@ _mongoc_stream_tls_secure_channel_decrypt(mongoc_stream_tls_secure_channel_t *se
/* check if server wants to renegotiate the connection context */
if (sspi_status == SEC_I_RENEGOTIATE) {
TRACE("%s", "remote party requests renegotiation");

if (secbuf_extra_received) {
bool ret;
bson_error_t error;

secure_channel->recv_renegotiate = true;

/* the tls handshake will pass the contents of SECBUFFER_EXTRA to the server */
secure_channel->connecting_state = ssl_connect_2_writing;
ret = mongoc_secure_channel_handshake_step_2(secure_channel->tls, secure_channel->hostname, &error);
if (!ret) {
TRACE("TLS 1.3 renegotiation failed: %s", error.message);
secure_channel->recv_unrecoverable_err = true;
return;
}

/* now continue decrypting data */
secure_channel->connecting_state = ssl_connect_done;
sspi_status = SEC_E_OK;
continue;
}
}
/* check if the server closed the connection */
else if (sspi_status == SEC_I_CONTEXT_EXPIRED) {
Expand Down Expand Up @@ -678,6 +704,12 @@ _mongoc_stream_tls_secure_channel_readv(
ssize_t read_ret = _mongoc_stream_tls_secure_channel_read(
stream, (char *)iov[i].iov_base + iov_pos, (int)(iov[i].iov_len - iov_pos));

/* used up all read bytes for tls renegotiation, try reading again to get next message */
if (read_ret == 0 && secure_channel->recv_renegotiate) {
secure_channel->recv_renegotiate = false;
continue;
}

if (read_ret < 0) {
RETURN(-1);
}
Expand Down Expand Up @@ -990,13 +1022,13 @@ mongoc_secure_channel_cred_deleter(void *cred_void)
mongoc_stream_t *
mongoc_stream_tls_secure_channel_new(mongoc_stream_t *base_stream, const char *host, mongoc_ssl_opt_t *opt, int client)
{
BSON_UNUSED(host);
BSON_UNUSED(client);
return mongoc_stream_tls_secure_channel_new_with_creds(base_stream, opt, MONGOC_SHARED_PTR_NULL);
return mongoc_stream_tls_secure_channel_new_with_creds(base_stream, host, opt, MONGOC_SHARED_PTR_NULL);
}

mongoc_stream_t *
mongoc_stream_tls_secure_channel_new_with_creds(mongoc_stream_t *base_stream,
const char *host,
const mongoc_ssl_opt_t *opt,
mongoc_shared_ptr cred_ptr)
{
Expand All @@ -1011,6 +1043,8 @@ mongoc_stream_tls_secure_channel_new_with_creds(mongoc_stream_t *base_stream,

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

secure_channel->hostname = bson_strdup(host);

secure_channel->decdata_buffer = bson_malloc(MONGOC_SCHANNEL_BUFFER_INIT_SIZE);
secure_channel->decdata_length = MONGOC_SCHANNEL_BUFFER_INIT_SIZE;
secure_channel->encdata_buffer = bson_malloc(MONGOC_SCHANNEL_BUFFER_INIT_SIZE);
Expand All @@ -1035,6 +1069,8 @@ mongoc_stream_tls_secure_channel_new_with_creds(mongoc_stream_t *base_stream,
tls->timeout_msec = -1;
tls->base_stream = base_stream;

secure_channel->tls = tls;

TRACE("%s", "SSL/TLS connection with endpoint AcquireCredentialsHandle");

/* setup Schannel API options */
Expand Down
3 changes: 2 additions & 1 deletion src/libmongoc/src/mongoc/mongoc-stream-tls.c
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,7 @@ mongoc_stream_tls_new_with_hostname_and_openssl_context(
// Returns a new stream on success. Returns `NULL` on failure.
mongoc_stream_t *
mongoc_stream_tls_new_with_secure_channel_cred(mongoc_stream_t *base_stream,
const char *host,
mongoc_ssl_opt_t *opt,
mongoc_shared_ptr secure_channel_cred_ptr)
{
Expand All @@ -232,7 +233,7 @@ mongoc_stream_tls_new_with_secure_channel_cred(mongoc_stream_t *base_stream,
// For compatibility with `mongoc_stream_tls_new_with_hostname`, modify `opt` directly:
opt->allow_invalid_hostname = true;
}
return mongoc_stream_tls_secure_channel_new_with_creds(base_stream, opt, secure_channel_cred_ptr);
return mongoc_stream_tls_secure_channel_new_with_creds(base_stream, host, opt, secure_channel_cred_ptr);
}
#endif // MONGOC_ENABLE_SSL_SECURE_CHANNEL

Expand Down
4 changes: 2 additions & 2 deletions src/libmongoc/src/mongoc/mongoc-topology-scanner.c
Original file line number Diff line number Diff line change
Expand Up @@ -856,8 +856,8 @@ _mongoc_topology_scanner_node_setup_stream_for_tls(mongoc_topology_scanner_node_
tls_stream = mongoc_stream_tls_new_with_hostname_and_openssl_context(
stream, node->host.host, node->ts->ssl_opts, 1, node->ts->openssl_ctx);
#elif defined(MONGOC_ENABLE_SSL_SECURE_CHANNEL)
tls_stream =
mongoc_stream_tls_new_with_secure_channel_cred(stream, node->ts->ssl_opts, node->ts->secure_channel_cred_ptr);
tls_stream = mongoc_stream_tls_new_with_secure_channel_cred(
stream, node->host.host, node->ts->ssl_opts, node->ts->secure_channel_cred_ptr);
#else
tls_stream = mongoc_stream_tls_new_with_hostname(stream, node->host.host, node->ts->ssl_opts, 1);
#endif
Expand Down
3 changes: 2 additions & 1 deletion src/libmongoc/tests/test-mongoc-secure-channel.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ connect_with_secure_channel_cred(const mongoc_ssl_opt_t *ssl_opt, mongoc_shared_
return false;
}

mongoc_stream_t *tls_stream = mongoc_stream_tls_secure_channel_new_with_creds(tcp_stream, ssl_opt, cred_ptr);
mongoc_stream_t *tls_stream =
mongoc_stream_tls_secure_channel_new_with_creds(tcp_stream, host.host, ssl_opt, cred_ptr);
if (!tls_stream) {
mongoc_stream_destroy(tcp_stream);
return false;
Expand Down