Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
8 changes: 8 additions & 0 deletions .evergreen/generated_configs/legacy-config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10232,6 +10232,14 @@ 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:
- debug-compile-sspi-winssl
- .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,16 @@ def days(n: int) -> int:
],
{'CC': 'Visual Studio 15 2017 Win64'},
),
Variant(
'windows-2022',
'Windows (VS 2022)',
'windows-vsCurrent-large',
[
'debug-compile-sspi-winssl',
'.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