Merge pull request #23165 from matthewstevenson88/matt-tls13

Enable TLS 1.3 in the C-core and all wrapped languages.
pull/23376/head
matthewstevenson88 4 years ago committed by GitHub
commit c1e07d8308
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 3
      include/grpc/grpc_security_constants.h
  2. 20
      src/core/lib/security/credentials/ssl/ssl_credentials.cc
  3. 10
      src/core/lib/security/credentials/ssl/ssl_credentials.h
  4. 6
      src/core/lib/security/security_connector/ssl/ssl_security_connector.cc
  5. 5
      src/core/lib/security/security_connector/ssl/ssl_security_connector.h
  6. 15
      src/core/lib/security/security_connector/ssl_utils.cc
  7. 3
      src/core/lib/security/security_connector/ssl_utils.h
  8. 111
      src/core/tsi/ssl_transport_security.cc
  9. 16
      src/core/tsi/ssl_transport_security.h
  10. 5
      src/core/tsi/transport_security_interface.h
  11. 4
      src/csharp/Grpc.IntegrationTesting/SslCredentialsTest.cs
  12. 10
      src/python/grpcio_tests/tests/unit/_server_ssl_cert_config_test.py
  13. 1
      test/core/end2end/end2end_tests.h
  14. 50
      test/core/end2end/fixtures/h2_oauth2.cc
  15. 50
      test/core/end2end/fixtures/h2_ssl.cc
  16. 50
      test/core/end2end/fixtures/h2_ssl_cred_reload.cc
  17. 10
      test/core/end2end/tests/filter_call_init_fails.cc
  18. 34
      test/core/tsi/ssl_transport_security_test.cc

@ -139,6 +139,9 @@ typedef enum {
*/ */
typedef enum { UDS = 0, LOCAL_TCP } grpc_local_connect_type; typedef enum { UDS = 0, LOCAL_TCP } grpc_local_connect_type;
/** The TLS versions that are supported by the SSL stack. **/
typedef enum { TLS1_2, TLS1_3 } grpc_tls_version;
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

@ -117,6 +117,16 @@ void grpc_ssl_credentials::build_config(
} }
} }
void grpc_ssl_credentials::set_min_tls_version(
grpc_tls_version min_tls_version) {
config_.min_tls_version = min_tls_version;
}
void grpc_ssl_credentials::set_max_tls_version(
grpc_tls_version max_tls_version) {
config_.max_tls_version = max_tls_version;
}
/* Deprecated in favor of grpc_ssl_credentials_create_ex. Will be removed /* Deprecated in favor of grpc_ssl_credentials_create_ex. Will be removed
* once all of its call sites are migrated to grpc_ssl_credentials_create_ex. */ * once all of its call sites are migrated to grpc_ssl_credentials_create_ex. */
grpc_channel_credentials* grpc_ssl_credentials_create( grpc_channel_credentials* grpc_ssl_credentials_create(
@ -213,6 +223,16 @@ void grpc_ssl_server_credentials::build_config(
config_.num_key_cert_pairs = num_key_cert_pairs; config_.num_key_cert_pairs = num_key_cert_pairs;
} }
void grpc_ssl_server_credentials::set_min_tls_version(
grpc_tls_version min_tls_version) {
config_.min_tls_version = min_tls_version;
}
void grpc_ssl_server_credentials::set_max_tls_version(
grpc_tls_version max_tls_version) {
config_.max_tls_version = max_tls_version;
}
grpc_ssl_server_certificate_config* grpc_ssl_server_certificate_config_create( grpc_ssl_server_certificate_config* grpc_ssl_server_certificate_config_create(
const char* pem_root_certs, const char* pem_root_certs,
const grpc_ssl_pem_key_cert_pair* pem_key_cert_pairs, const grpc_ssl_pem_key_cert_pair* pem_key_cert_pairs,

@ -38,6 +38,11 @@ class grpc_ssl_credentials : public grpc_channel_credentials {
const char* target, const grpc_channel_args* args, const char* target, const grpc_channel_args* args,
grpc_channel_args** new_args) override; grpc_channel_args** new_args) override;
// TODO(mattstev): Plumb to wrapped languages. Until then, setting the TLS
// version should be done for testing purposes only.
void set_min_tls_version(grpc_tls_version min_tls_version);
void set_max_tls_version(grpc_tls_version max_tls_version);
private: private:
void build_config(const char* pem_root_certs, void build_config(const char* pem_root_certs,
grpc_ssl_pem_key_cert_pair* pem_key_cert_pair, grpc_ssl_pem_key_cert_pair* pem_key_cert_pair,
@ -77,6 +82,11 @@ class grpc_ssl_server_credentials final : public grpc_server_credentials {
config); config);
} }
// TODO(mattstev): Plumb to wrapped languages. Until then, setting the TLS
// version should be done for testing purposes only.
void set_min_tls_version(grpc_tls_version min_tls_version);
void set_max_tls_version(grpc_tls_version max_tls_version);
const grpc_ssl_server_config& config() const { return config_; } const grpc_ssl_server_config& config() const { return config_; }
private: private:

@ -107,6 +107,8 @@ class grpc_ssl_channel_security_connector final
} }
options.cipher_suites = grpc_get_ssl_cipher_suites(); options.cipher_suites = grpc_get_ssl_cipher_suites();
options.session_cache = ssl_session_cache; options.session_cache = ssl_session_cache;
options.min_tls_version = grpc_get_tsi_tls_version(config->min_tls_version);
options.max_tls_version = grpc_get_tsi_tls_version(config->max_tls_version);
const tsi_result result = const tsi_result result =
tsi_create_ssl_client_handshaker_factory_with_options( tsi_create_ssl_client_handshaker_factory_with_options(
&options, &client_handshaker_factory_); &options, &client_handshaker_factory_);
@ -251,6 +253,10 @@ class grpc_ssl_server_security_connector
options.cipher_suites = grpc_get_ssl_cipher_suites(); options.cipher_suites = grpc_get_ssl_cipher_suites();
options.alpn_protocols = alpn_protocol_strings; options.alpn_protocols = alpn_protocol_strings;
options.num_alpn_protocols = static_cast<uint16_t>(num_alpn_protocols); options.num_alpn_protocols = static_cast<uint16_t>(num_alpn_protocols);
options.min_tls_version = grpc_get_tsi_tls_version(
server_credentials->config().min_tls_version);
options.max_tls_version = grpc_get_tsi_tls_version(
server_credentials->config().max_tls_version);
const tsi_result result = const tsi_result result =
tsi_create_ssl_server_handshaker_factory_with_options( tsi_create_ssl_server_handshaker_factory_with_options(
&options, &server_handshaker_factory_); &options, &server_handshaker_factory_);

@ -33,7 +33,10 @@ struct grpc_ssl_config {
tsi_ssl_pem_key_cert_pair* pem_key_cert_pair; tsi_ssl_pem_key_cert_pair* pem_key_cert_pair;
char* pem_root_certs; char* pem_root_certs;
verify_peer_options verify_options; verify_peer_options verify_options;
grpc_tls_version min_tls_version = grpc_tls_version::TLS1_2;
grpc_tls_version max_tls_version = grpc_tls_version::TLS1_3;
}; };
/* Creates an SSL channel_security_connector. /* Creates an SSL channel_security_connector.
- request_metadata_creds is the credentials object which metadata - request_metadata_creds is the credentials object which metadata
will be sent with each request. This parameter can be NULL. will be sent with each request. This parameter can be NULL.
@ -62,6 +65,8 @@ struct grpc_ssl_server_config {
char* pem_root_certs = nullptr; char* pem_root_certs = nullptr;
grpc_ssl_client_certificate_request_type client_certificate_request = grpc_ssl_client_certificate_request_type client_certificate_request =
GRPC_SSL_DONT_REQUEST_CLIENT_CERTIFICATE; GRPC_SSL_DONT_REQUEST_CLIENT_CERTIFICATE;
grpc_tls_version min_tls_version = grpc_tls_version::TLS1_2;
grpc_tls_version max_tls_version = grpc_tls_version::TLS1_3;
}; };
/* Creates an SSL server_security_connector. /* Creates an SSL server_security_connector.
- config is the SSL config to be used for the SSL channel establishment. - config is the SSL config to be used for the SSL channel establishment.

@ -67,6 +67,9 @@ static const char* cipher_suites = nullptr;
// All cipher suites for default are compliant with HTTP2. // All cipher suites for default are compliant with HTTP2.
GPR_GLOBAL_CONFIG_DEFINE_STRING( GPR_GLOBAL_CONFIG_DEFINE_STRING(
grpc_ssl_cipher_suites, grpc_ssl_cipher_suites,
"TLS_AES_128_GCM_SHA256:"
"TLS_AES_256_GCM_SHA384:"
"TLS_CHACHA20_POLY1305_SHA256:"
"ECDHE-ECDSA-AES128-GCM-SHA256:" "ECDHE-ECDSA-AES128-GCM-SHA256:"
"ECDHE-ECDSA-AES256-GCM-SHA384:" "ECDHE-ECDSA-AES256-GCM-SHA384:"
"ECDHE-RSA-AES128-GCM-SHA256:" "ECDHE-RSA-AES128-GCM-SHA256:"
@ -134,6 +137,18 @@ grpc_get_tsi_client_certificate_request_type(
} }
} }
tsi_tls_version grpc_get_tsi_tls_version(grpc_tls_version tls_version) {
switch (tls_version) {
case grpc_tls_version::TLS1_2:
return tsi_tls_version::TSI_TLS1_2;
case grpc_tls_version::TLS1_3:
return tsi_tls_version::TSI_TLS1_3;
default:
gpr_log(GPR_INFO, "Falling back to TLS 1.2.");
return tsi_tls_version::TSI_TLS1_2;
}
}
grpc_error* grpc_ssl_check_alpn(const tsi_peer* peer) { grpc_error* grpc_ssl_check_alpn(const tsi_peer* peer) {
#if TSI_OPENSSL_ALPN_SUPPORT #if TSI_OPENSSL_ALPN_SUPPORT
/* Check the ALPN if ALPN is supported. */ /* Check the ALPN if ALPN is supported. */

@ -73,6 +73,9 @@ grpc_get_tsi_client_certificate_request_type(
grpc_security_level grpc_tsi_security_level_string_to_enum( grpc_security_level grpc_tsi_security_level_string_to_enum(
const char* security_level); const char* security_level);
/* Map grpc_tls_version to tsi_tls_version. */
tsi_tls_version grpc_get_tsi_tls_version(grpc_tls_version tls_version);
/* Map grpc_security_level enum to a string. */ /* Map grpc_security_level enum to a string. */
const char* grpc_security_level_to_string(grpc_security_level security_level); const char* grpc_security_level_to_string(grpc_security_level security_level);

@ -51,6 +51,7 @@ extern "C" {
#include <openssl/engine.h> #include <openssl/engine.h>
#include <openssl/err.h> #include <openssl/err.h>
#include <openssl/ssl.h> #include <openssl/ssl.h>
#include <openssl/tls1.h>
#include <openssl/x509.h> #include <openssl/x509.h>
#include <openssl/x509v3.h> #include <openssl/x509v3.h>
} }
@ -890,6 +891,50 @@ static int NullVerifyCallback(int /*preverify_ok*/, X509_STORE_CTX* /*ctx*/) {
return 1; return 1;
} }
// Sets the min and max TLS version of |ssl_context| to |min_tls_version| and
// |max_tls_version|, respectively. Calling this method is a no-op when using
// OpenSSL versions < 1.1.
static tsi_result tsi_set_min_and_max_tls_versions(
SSL_CTX* ssl_context, tsi_tls_version min_tls_version,
tsi_tls_version max_tls_version) {
if (ssl_context == nullptr) {
gpr_log(GPR_INFO,
"Invalid nullptr argument to |tsi_set_min_and_max_tls_versions|.");
return TSI_INVALID_ARGUMENT;
}
#if OPENSSL_VERSION_NUMBER >= 0x10100000
// Set the min TLS version of the SSL context.
switch (min_tls_version) {
case tsi_tls_version::TSI_TLS1_2:
SSL_CTX_set_min_proto_version(ssl_context, TLS1_2_VERSION);
break;
#if defined(TLS1_3_VERSION)
case tsi_tls_version::TSI_TLS1_3:
SSL_CTX_set_min_proto_version(ssl_context, TLS1_3_VERSION);
break;
#endif
default:
gpr_log(GPR_INFO, "TLS version is not supported.");
return TSI_FAILED_PRECONDITION;
}
// Set the max TLS version of the SSL context.
switch (max_tls_version) {
case tsi_tls_version::TSI_TLS1_2:
SSL_CTX_set_max_proto_version(ssl_context, TLS1_2_VERSION);
break;
#if defined(TLS1_3_VERSION)
case tsi_tls_version::TSI_TLS1_3:
SSL_CTX_set_max_proto_version(ssl_context, TLS1_3_VERSION);
break;
#endif
default:
gpr_log(GPR_INFO, "TLS version is not supported.");
return TSI_FAILED_PRECONDITION;
}
#endif
return TSI_OK;
}
/* --- tsi_ssl_root_certs_store methods implementation. ---*/ /* --- tsi_ssl_root_certs_store methods implementation. ---*/
tsi_ssl_root_certs_store* tsi_ssl_root_certs_store_create( tsi_ssl_root_certs_store* tsi_ssl_root_certs_store_create(
@ -1301,7 +1346,7 @@ static const tsi_handshaker_result_vtable handshaker_result_vtable = {
}; };
static tsi_result ssl_handshaker_result_create( static tsi_result ssl_handshaker_result_create(
tsi_ssl_handshaker* handshaker, const unsigned char* unused_bytes, tsi_ssl_handshaker* handshaker, unsigned char* unused_bytes,
size_t unused_bytes_size, tsi_handshaker_result** handshaker_result) { size_t unused_bytes_size, tsi_handshaker_result** handshaker_result) {
if (handshaker == nullptr || handshaker_result == nullptr || if (handshaker == nullptr || handshaker_result == nullptr ||
(unused_bytes_size > 0 && unused_bytes == nullptr)) { (unused_bytes_size > 0 && unused_bytes == nullptr)) {
@ -1315,11 +1360,8 @@ static tsi_result ssl_handshaker_result_create(
handshaker->ssl = nullptr; handshaker->ssl = nullptr;
result->network_io = handshaker->network_io; result->network_io = handshaker->network_io;
handshaker->network_io = nullptr; handshaker->network_io = nullptr;
if (unused_bytes_size > 0) { /* Transfer ownership of |unused_bytes| to the handshaker result. */
result->unused_bytes = result->unused_bytes = unused_bytes;
static_cast<unsigned char*>(gpr_malloc(unused_bytes_size));
memcpy(result->unused_bytes, unused_bytes, unused_bytes_size);
}
result->unused_bytes_size = unused_bytes_size; result->unused_bytes_size = unused_bytes_size;
*handshaker_result = &result->base; *handshaker_result = &result->base;
return TSI_OK; return TSI_OK;
@ -1412,6 +1454,36 @@ static void ssl_handshaker_destroy(tsi_handshaker* self) {
gpr_free(impl); gpr_free(impl);
} }
// Removes the bytes remaining in |impl->SSL|'s read BIO and writes them to
// |bytes_remaining|.
static tsi_result ssl_bytes_remaining(tsi_ssl_handshaker* impl,
unsigned char** bytes_remaining,
size_t* bytes_remaining_size) {
if (impl == nullptr || bytes_remaining == nullptr ||
bytes_remaining_size == nullptr) {
return TSI_INVALID_ARGUMENT;
}
// Atempt to read all of the bytes in SSL's read BIO. These bytes should
// contain application data records that were appended to a handshake record
// containing the ClientFinished or ServerFinished message.
size_t bytes_in_ssl = BIO_pending(SSL_get_rbio(impl->ssl));
if (bytes_in_ssl == 0) return TSI_OK;
*bytes_remaining = static_cast<uint8_t*>(gpr_malloc(bytes_in_ssl));
int bytes_read = BIO_read(SSL_get_rbio(impl->ssl), *bytes_remaining,
static_cast<int>(bytes_in_ssl));
// If an unexpected number of bytes were read, return an error status and free
// all of the bytes that were read.
if (bytes_read < 0 || static_cast<size_t>(bytes_read) != bytes_in_ssl) {
gpr_log(GPR_ERROR,
"Failed to read the expected number of bytes from SSL object.");
gpr_free(*bytes_remaining);
*bytes_remaining = nullptr;
return TSI_INTERNAL_ERROR;
}
*bytes_remaining_size = static_cast<size_t>(bytes_read);
return TSI_OK;
}
static tsi_result ssl_handshaker_next( static tsi_result ssl_handshaker_next(
tsi_handshaker* self, const unsigned char* received_bytes, tsi_handshaker* self, const unsigned char* received_bytes,
size_t received_bytes_size, const unsigned char** bytes_to_send, size_t received_bytes_size, const unsigned char** bytes_to_send,
@ -1452,9 +1524,19 @@ static tsi_result ssl_handshaker_next(
if (ssl_handshaker_get_result(impl) == TSI_HANDSHAKE_IN_PROGRESS) { if (ssl_handshaker_get_result(impl) == TSI_HANDSHAKE_IN_PROGRESS) {
*handshaker_result = nullptr; *handshaker_result = nullptr;
} else { } else {
size_t unused_bytes_size = received_bytes_size - bytes_consumed; // Any bytes that remain in |impl->ssl|'s read BIO after the handshake is
const unsigned char* unused_bytes = // complete must be extracted and set to the unused bytes of the handshaker
unused_bytes_size == 0 ? nullptr : received_bytes + bytes_consumed; // result. This indicates to the gRPC stack that there are bytes from the
// peer that must be processed.
unsigned char* unused_bytes = nullptr;
size_t unused_bytes_size = 0;
status = ssl_bytes_remaining(impl, &unused_bytes, &unused_bytes_size);
if (status != TSI_OK) return status;
if (unused_bytes_size > received_bytes_size) {
gpr_log(GPR_ERROR, "More unused bytes than received bytes.");
gpr_free(unused_bytes);
return TSI_INTERNAL_ERROR;
}
status = ssl_handshaker_result_create(impl, unused_bytes, unused_bytes_size, status = ssl_handshaker_result_create(impl, unused_bytes, unused_bytes_size,
handshaker_result); handshaker_result);
if (status == TSI_OK) { if (status == TSI_OK) {
@ -1807,11 +1889,14 @@ tsi_result tsi_create_ssl_client_handshaker_factory_with_options(
return TSI_INVALID_ARGUMENT; return TSI_INVALID_ARGUMENT;
} }
#if defined(OPENSSL_NO_TLS1_2_METHOD) || OPENSSL_API_COMPAT >= 0x10100000L #if OPENSSL_VERSION_NUMBER >= 0x10100000
ssl_context = SSL_CTX_new(TLS_method()); ssl_context = SSL_CTX_new(TLS_method());
#else #else
ssl_context = SSL_CTX_new(TLSv1_2_method()); ssl_context = SSL_CTX_new(TLSv1_2_method());
#endif #endif
result = tsi_set_min_and_max_tls_versions(
ssl_context, options->min_tls_version, options->max_tls_version);
if (result != TSI_OK) return result;
if (ssl_context == nullptr) { if (ssl_context == nullptr) {
gpr_log(GPR_ERROR, "Could not create ssl context."); gpr_log(GPR_ERROR, "Could not create ssl context.");
return TSI_INVALID_ARGUMENT; return TSI_INVALID_ARGUMENT;
@ -1971,11 +2056,15 @@ tsi_result tsi_create_ssl_server_handshaker_factory_with_options(
for (i = 0; i < options->num_key_cert_pairs; i++) { for (i = 0; i < options->num_key_cert_pairs; i++) {
do { do {
#if defined(OPENSSL_NO_TLS1_2_METHOD) || OPENSSL_API_COMPAT >= 0x10100000L #if OPENSSL_VERSION_NUMBER >= 0x10100000
impl->ssl_contexts[i] = SSL_CTX_new(TLS_method()); impl->ssl_contexts[i] = SSL_CTX_new(TLS_method());
#else #else
impl->ssl_contexts[i] = SSL_CTX_new(TLSv1_2_method()); impl->ssl_contexts[i] = SSL_CTX_new(TLSv1_2_method());
#endif #endif
result = tsi_set_min_and_max_tls_versions(impl->ssl_contexts[i],
options->min_tls_version,
options->max_tls_version);
if (result != TSI_OK) return result;
if (impl->ssl_contexts[i] == nullptr) { if (impl->ssl_contexts[i] == nullptr) {
gpr_log(GPR_ERROR, "Could not create ssl context."); gpr_log(GPR_ERROR, "Could not create ssl context.");
result = TSI_OUT_OF_RESOURCES; result = TSI_OUT_OF_RESOURCES;

@ -21,6 +21,7 @@
#include <grpc/support/port_platform.h> #include <grpc/support/port_platform.h>
#include <grpc/grpc_security_constants.h>
#include "absl/strings/string_view.h" #include "absl/strings/string_view.h"
#include "src/core/tsi/transport_security_interface.h" #include "src/core/tsi/transport_security_interface.h"
@ -152,6 +153,10 @@ struct tsi_ssl_client_handshaker_options {
/* skip server certificate verification. */ /* skip server certificate verification. */
bool skip_server_certificate_verification; bool skip_server_certificate_verification;
/* The min and max TLS versions that will be negotiated by the handshaker. */
tsi_tls_version min_tls_version;
tsi_tls_version max_tls_version;
tsi_ssl_client_handshaker_options() tsi_ssl_client_handshaker_options()
: pem_key_cert_pair(nullptr), : pem_key_cert_pair(nullptr),
pem_root_certs(nullptr), pem_root_certs(nullptr),
@ -160,7 +165,9 @@ struct tsi_ssl_client_handshaker_options {
alpn_protocols(nullptr), alpn_protocols(nullptr),
num_alpn_protocols(0), num_alpn_protocols(0),
session_cache(nullptr), session_cache(nullptr),
skip_server_certificate_verification(false) {} skip_server_certificate_verification(false),
min_tls_version(tsi_tls_version::TSI_TLS1_2),
max_tls_version(tsi_tls_version::TSI_TLS1_3) {}
}; };
/* Creates a client handshaker factory. /* Creates a client handshaker factory.
@ -276,6 +283,9 @@ struct tsi_ssl_server_handshaker_options {
const char* session_ticket_key; const char* session_ticket_key;
/* session_ticket_key_size is a size of session ticket encryption key. */ /* session_ticket_key_size is a size of session ticket encryption key. */
size_t session_ticket_key_size; size_t session_ticket_key_size;
/* The min and max TLS versions that will be negotiated by the handshaker. */
tsi_tls_version min_tls_version;
tsi_tls_version max_tls_version;
tsi_ssl_server_handshaker_options() tsi_ssl_server_handshaker_options()
: pem_key_cert_pairs(nullptr), : pem_key_cert_pairs(nullptr),
@ -286,7 +296,9 @@ struct tsi_ssl_server_handshaker_options {
alpn_protocols(nullptr), alpn_protocols(nullptr),
num_alpn_protocols(0), num_alpn_protocols(0),
session_ticket_key(nullptr), session_ticket_key(nullptr),
session_ticket_key_size(0) {} session_ticket_key_size(0),
min_tls_version(tsi_tls_version::TSI_TLS1_2),
max_tls_version(tsi_tls_version::TSI_TLS1_3) {}
}; };
/* Creates a server handshaker factory. /* Creates a server handshaker factory.

@ -64,6 +64,11 @@ typedef enum {
TSI_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY, TSI_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY,
} tsi_client_certificate_request_type; } tsi_client_certificate_request_type;
typedef enum {
TSI_TLS1_2,
TSI_TLS1_3,
} tsi_tls_version;
const char* tsi_result_to_string(tsi_result result); const char* tsi_result_to_string(tsi_result result);
const char* tsi_security_level_to_string(tsi_security_level security_level); const char* tsi_security_level_to_string(tsi_security_level security_level);

@ -246,7 +246,9 @@ namespace Grpc.IntegrationTesting
private void CheckRejected() private void CheckRejected()
{ {
var ex = Assert.Throws<RpcException>(() => client.UnaryCall(new SimpleRequest { ResponseSize = 10 })); var ex = Assert.Throws<RpcException>(() => client.UnaryCall(new SimpleRequest { ResponseSize = 10 }));
Assert.AreEqual(StatusCode.Unavailable, ex.Status.StatusCode); if (ex.Status.StatusCode != StatusCode.Unavailable & ex.Status.StatusCode != StatusCode.Unknown) {
Assert.Fail("Expect status to be either Unavailable or Unknown");
}
} }
private async Task CheckAuthContextIsPopulated() private async Task CheckAuthContextIsPopulated()

@ -161,8 +161,14 @@ class _ServerSSLCertReloadTest(
else: else:
with self.assertRaises(grpc.RpcError) as exception_context: with self.assertRaises(grpc.RpcError) as exception_context:
client_stub.UnUn(request) client_stub.UnUn(request)
self.assertEqual(exception_context.exception.code(), # If TLS 1.2 is used, then the client receives an alert message
grpc.StatusCode.UNAVAILABLE) # before the handshake is complete, so the status is UNAVAILABLE. If
# TLS 1.3 is used, then the client receives the alert message after
# the handshake is complete, so the TSI handshaker returns the
# TSI_PROTOCOL_FAILURE result. This result does not have a
# corresponding status code, so this yields an UNKNOWN status.
self.assertTrue(exception_context.exception.code(
) in [grpc.StatusCode.UNAVAILABLE, grpc.StatusCode.UNKNOWN])
def _do_one_shot_client_rpc(self, def _do_one_shot_client_rpc(self,
expect_success, expect_success,

@ -35,6 +35,7 @@ typedef struct grpc_end2end_test_config grpc_end2end_test_config;
#define FEATURE_MASK_DOES_NOT_SUPPORT_NETWORK_STATUS_CHANGE 128 #define FEATURE_MASK_DOES_NOT_SUPPORT_NETWORK_STATUS_CHANGE 128
#define FEATURE_MASK_SUPPORTS_WORKAROUNDS 256 #define FEATURE_MASK_SUPPORTS_WORKAROUNDS 256
#define FEATURE_MASK_DOES_NOT_SUPPORT_SEND_CALL_CREDENTIALS 512 #define FEATURE_MASK_DOES_NOT_SUPPORT_SEND_CALL_CREDENTIALS 512
#define FEATURE_MASK_DOES_NOT_SUPPORT_CLIENT_HANDSHAKE_COMPLETE_FIRST 1024
#define FAIL_AUTH_CHECK_SERVER_ARG_NAME "fail_auth_check" #define FAIL_AUTH_CHECK_SERVER_ARG_NAME "fail_auth_check"

@ -26,6 +26,7 @@
#include "src/core/lib/iomgr/iomgr.h" #include "src/core/lib/iomgr/iomgr.h"
#include "src/core/lib/iomgr/load_file.h" #include "src/core/lib/iomgr/load_file.h"
#include "src/core/lib/security/credentials/credentials.h" #include "src/core/lib/security/credentials/credentials.h"
#include "src/core/lib/security/credentials/ssl/ssl_credentials.h"
#include "test/core/end2end/end2end_tests.h" #include "test/core/end2end/end2end_tests.h"
#include "test/core/util/port.h" #include "test/core/util/port.h"
#include "test/core/util/test_config.h" #include "test/core/util/test_config.h"
@ -40,6 +41,7 @@ static const char* client_identity = "Brainy Smurf";
struct fullstack_secure_fixture_data { struct fullstack_secure_fixture_data {
std::string localaddr; std::string localaddr;
grpc_tls_version tls_version;
}; };
static const grpc_metadata* find_metadata(const grpc_metadata* md, static const grpc_metadata* find_metadata(const grpc_metadata* md,
@ -93,18 +95,32 @@ static void process_oauth2_failure(void* state, grpc_auth_context* /*ctx*/,
} }
static grpc_end2end_test_fixture chttp2_create_fixture_secure_fullstack( static grpc_end2end_test_fixture chttp2_create_fixture_secure_fullstack(
grpc_channel_args* /*client_args*/, grpc_channel_args* /*server_args*/) { grpc_channel_args* /*client_args*/, grpc_channel_args* /*server_args*/,
grpc_tls_version tls_version) {
grpc_end2end_test_fixture f; grpc_end2end_test_fixture f;
int port = grpc_pick_unused_port_or_die(); int port = grpc_pick_unused_port_or_die();
fullstack_secure_fixture_data* ffd = new fullstack_secure_fixture_data(); fullstack_secure_fixture_data* ffd = new fullstack_secure_fixture_data();
memset(&f, 0, sizeof(f)); memset(&f, 0, sizeof(f));
ffd->localaddr = grpc_core::JoinHostPort("localhost", port); ffd->localaddr = grpc_core::JoinHostPort("localhost", port);
ffd->tls_version = tls_version;
f.fixture_data = ffd; f.fixture_data = ffd;
f.cq = grpc_completion_queue_create_for_next(nullptr); f.cq = grpc_completion_queue_create_for_next(nullptr);
f.shutdown_cq = grpc_completion_queue_create_for_pluck(nullptr); f.shutdown_cq = grpc_completion_queue_create_for_pluck(nullptr);
return f; return f;
} }
static grpc_end2end_test_fixture chttp2_create_fixture_secure_fullstack_tls1_2(
grpc_channel_args* client_args, grpc_channel_args* server_args) {
return chttp2_create_fixture_secure_fullstack(client_args, server_args,
grpc_tls_version::TLS1_2);
}
static grpc_end2end_test_fixture chttp2_create_fixture_secure_fullstack_tls1_3(
grpc_channel_args* client_args, grpc_channel_args* server_args) {
return chttp2_create_fixture_secure_fullstack(client_args, server_args,
grpc_tls_version::TLS1_3);
}
static void chttp2_init_client_secure_fullstack( static void chttp2_init_client_secure_fullstack(
grpc_end2end_test_fixture* f, grpc_channel_args* client_args, grpc_end2end_test_fixture* f, grpc_channel_args* client_args,
grpc_channel_credentials* creds) { grpc_channel_credentials* creds) {
@ -148,6 +164,15 @@ static void chttp2_init_client_simple_ssl_with_oauth2_secure_fullstack(
reinterpret_cast<const char*> GRPC_SLICE_START_PTR(ca_slice); reinterpret_cast<const char*> GRPC_SLICE_START_PTR(ca_slice);
grpc_channel_credentials* ssl_creds = grpc_channel_credentials* ssl_creds =
grpc_ssl_credentials_create(test_root_cert, nullptr, nullptr, nullptr); grpc_ssl_credentials_create(test_root_cert, nullptr, nullptr, nullptr);
if (f != nullptr && ssl_creds != nullptr) {
// Set the min and max TLS version.
grpc_ssl_credentials* creds =
reinterpret_cast<grpc_ssl_credentials*>(ssl_creds);
fullstack_secure_fixture_data* ffd =
static_cast<fullstack_secure_fixture_data*>(f->fixture_data);
creds->set_min_tls_version(ffd->tls_version);
creds->set_max_tls_version(ffd->tls_version);
}
grpc_call_credentials* oauth2_creds = grpc_md_only_test_credentials_create( grpc_call_credentials* oauth2_creds = grpc_md_only_test_credentials_create(
"authorization", oauth2_md, true /* is_async */); "authorization", oauth2_md, true /* is_async */);
grpc_channel_credentials* ssl_oauth2_creds = grpc_channel_credentials* ssl_oauth2_creds =
@ -213,6 +238,15 @@ static void chttp2_init_server_simple_ssl_secure_fullstack(
grpc_ssl_pem_key_cert_pair pem_key_cert_pair = {server_key, server_cert}; grpc_ssl_pem_key_cert_pair pem_key_cert_pair = {server_key, server_cert};
grpc_server_credentials* ssl_creds = grpc_ssl_server_credentials_create( grpc_server_credentials* ssl_creds = grpc_ssl_server_credentials_create(
nullptr, &pem_key_cert_pair, 1, 0, nullptr); nullptr, &pem_key_cert_pair, 1, 0, nullptr);
if (f != nullptr && ssl_creds != nullptr) {
// Set the min and max TLS version.
grpc_ssl_server_credentials* creds =
reinterpret_cast<grpc_ssl_server_credentials*>(ssl_creds);
fullstack_secure_fixture_data* ffd =
static_cast<fullstack_secure_fixture_data*>(f->fixture_data);
creds->set_min_tls_version(ffd->tls_version);
creds->set_max_tls_version(ffd->tls_version);
}
grpc_server_credentials_set_auth_metadata_processor( grpc_server_credentials_set_auth_metadata_processor(
ssl_creds, test_processor_create(fail_server_auth_check(server_args))); ssl_creds, test_processor_create(fail_server_auth_check(server_args)));
chttp2_init_server_secure_fullstack(f, server_args, ssl_creds); chttp2_init_server_secure_fullstack(f, server_args, ssl_creds);
@ -223,12 +257,22 @@ static void chttp2_init_server_simple_ssl_secure_fullstack(
/* All test configurations */ /* All test configurations */
static grpc_end2end_test_config configs[] = { static grpc_end2end_test_config configs[] = {
{"chttp2/simple_ssl_with_oauth2_fullstack", {"chttp2/simple_ssl_with_oauth2_fullstack_tls1_2",
FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION | FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION |
FEATURE_MASK_SUPPORTS_PER_CALL_CREDENTIALS | FEATURE_MASK_SUPPORTS_PER_CALL_CREDENTIALS |
FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL | FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL |
FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER, FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER,
"foo.test.google.fr", chttp2_create_fixture_secure_fullstack, "foo.test.google.fr", chttp2_create_fixture_secure_fullstack_tls1_2,
chttp2_init_client_simple_ssl_with_oauth2_secure_fullstack,
chttp2_init_server_simple_ssl_secure_fullstack,
chttp2_tear_down_secure_fullstack},
{"chttp2/simple_ssl_with_oauth2_fullstack_tls1_3",
FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION |
FEATURE_MASK_SUPPORTS_PER_CALL_CREDENTIALS |
FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL |
FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER |
FEATURE_MASK_DOES_NOT_SUPPORT_CLIENT_HANDSHAKE_COMPLETE_FIRST,
"foo.test.google.fr", chttp2_create_fixture_secure_fullstack_tls1_3,
chttp2_init_client_simple_ssl_with_oauth2_secure_fullstack, chttp2_init_client_simple_ssl_with_oauth2_secure_fullstack,
chttp2_init_server_simple_ssl_secure_fullstack, chttp2_init_server_simple_ssl_secure_fullstack,
chttp2_tear_down_secure_fullstack}, chttp2_tear_down_secure_fullstack},

@ -27,6 +27,7 @@
#include "src/core/lib/gprpp/host_port.h" #include "src/core/lib/gprpp/host_port.h"
#include "src/core/lib/iomgr/load_file.h" #include "src/core/lib/iomgr/load_file.h"
#include "src/core/lib/security/credentials/credentials.h" #include "src/core/lib/security/credentials/credentials.h"
#include "src/core/lib/security/credentials/ssl/ssl_credentials.h"
#include "src/core/lib/security/security_connector/ssl_utils_config.h" #include "src/core/lib/security/security_connector/ssl_utils_config.h"
#include "test/core/end2end/end2end_tests.h" #include "test/core/end2end/end2end_tests.h"
#include "test/core/util/port.h" #include "test/core/util/port.h"
@ -38,16 +39,19 @@
struct fullstack_secure_fixture_data { struct fullstack_secure_fixture_data {
std::string localaddr; std::string localaddr;
grpc_tls_version tls_version;
}; };
static grpc_end2end_test_fixture chttp2_create_fixture_secure_fullstack( static grpc_end2end_test_fixture chttp2_create_fixture_secure_fullstack(
grpc_channel_args* /*client_args*/, grpc_channel_args* /*server_args*/) { grpc_channel_args* /*client_args*/, grpc_channel_args* /*server_args*/,
grpc_tls_version tls_version) {
grpc_end2end_test_fixture f; grpc_end2end_test_fixture f;
int port = grpc_pick_unused_port_or_die(); int port = grpc_pick_unused_port_or_die();
fullstack_secure_fixture_data* ffd = new fullstack_secure_fixture_data(); fullstack_secure_fixture_data* ffd = new fullstack_secure_fixture_data();
memset(&f, 0, sizeof(f)); memset(&f, 0, sizeof(f));
ffd->localaddr = grpc_core::JoinHostPort("localhost", port); ffd->localaddr = grpc_core::JoinHostPort("localhost", port);
ffd->tls_version = tls_version;
f.fixture_data = ffd; f.fixture_data = ffd;
f.cq = grpc_completion_queue_create_for_next(nullptr); f.cq = grpc_completion_queue_create_for_next(nullptr);
@ -56,6 +60,18 @@ static grpc_end2end_test_fixture chttp2_create_fixture_secure_fullstack(
return f; return f;
} }
static grpc_end2end_test_fixture chttp2_create_fixture_secure_fullstack_tls1_2(
grpc_channel_args* client_args, grpc_channel_args* server_args) {
return chttp2_create_fixture_secure_fullstack(client_args, server_args,
grpc_tls_version::TLS1_2);
}
static grpc_end2end_test_fixture chttp2_create_fixture_secure_fullstack_tls1_3(
grpc_channel_args* client_args, grpc_channel_args* server_args) {
return chttp2_create_fixture_secure_fullstack(client_args, server_args,
grpc_tls_version::TLS1_3);
}
static void process_auth_failure(void* state, grpc_auth_context* /*ctx*/, static void process_auth_failure(void* state, grpc_auth_context* /*ctx*/,
const grpc_metadata* /*md*/, const grpc_metadata* /*md*/,
size_t /*md_count*/, size_t /*md_count*/,
@ -102,6 +118,15 @@ static void chttp2_init_client_simple_ssl_secure_fullstack(
grpc_end2end_test_fixture* f, grpc_channel_args* client_args) { grpc_end2end_test_fixture* f, grpc_channel_args* client_args) {
grpc_channel_credentials* ssl_creds = grpc_channel_credentials* ssl_creds =
grpc_ssl_credentials_create(nullptr, nullptr, nullptr, nullptr); grpc_ssl_credentials_create(nullptr, nullptr, nullptr, nullptr);
if (f != nullptr && ssl_creds != nullptr) {
// Set the min and max TLS version.
grpc_ssl_credentials* creds =
reinterpret_cast<grpc_ssl_credentials*>(ssl_creds);
fullstack_secure_fixture_data* ffd =
static_cast<fullstack_secure_fixture_data*>(f->fixture_data);
creds->set_min_tls_version(ffd->tls_version);
creds->set_max_tls_version(ffd->tls_version);
}
grpc_arg ssl_name_override = { grpc_arg ssl_name_override = {
GRPC_ARG_STRING, GRPC_ARG_STRING,
const_cast<char*>(GRPC_SSL_TARGET_NAME_OVERRIDE_ARG), const_cast<char*>(GRPC_SSL_TARGET_NAME_OVERRIDE_ARG),
@ -138,6 +163,15 @@ static void chttp2_init_server_simple_ssl_secure_fullstack(
grpc_ssl_pem_key_cert_pair pem_key_cert_pair = {server_key, server_cert}; grpc_ssl_pem_key_cert_pair pem_key_cert_pair = {server_key, server_cert};
grpc_server_credentials* ssl_creds = grpc_ssl_server_credentials_create( grpc_server_credentials* ssl_creds = grpc_ssl_server_credentials_create(
nullptr, &pem_key_cert_pair, 1, 0, nullptr); nullptr, &pem_key_cert_pair, 1, 0, nullptr);
if (f != nullptr && ssl_creds != nullptr) {
// Set the min and max TLS version.
grpc_ssl_server_credentials* creds =
reinterpret_cast<grpc_ssl_server_credentials*>(ssl_creds);
fullstack_secure_fixture_data* ffd =
static_cast<fullstack_secure_fixture_data*>(f->fixture_data);
creds->set_min_tls_version(ffd->tls_version);
creds->set_max_tls_version(ffd->tls_version);
}
grpc_slice_unref(cert_slice); grpc_slice_unref(cert_slice);
grpc_slice_unref(key_slice); grpc_slice_unref(key_slice);
if (fail_server_auth_check(server_args)) { if (fail_server_auth_check(server_args)) {
@ -151,12 +185,22 @@ static void chttp2_init_server_simple_ssl_secure_fullstack(
/* All test configurations */ /* All test configurations */
static grpc_end2end_test_config configs[] = { static grpc_end2end_test_config configs[] = {
{"chttp2/simple_ssl_fullstack", {"chttp2/simple_ssl_fullstack_tls1_2",
FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION | FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION |
FEATURE_MASK_SUPPORTS_PER_CALL_CREDENTIALS | FEATURE_MASK_SUPPORTS_PER_CALL_CREDENTIALS |
FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL | FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL |
FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER, FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER,
"foo.test.google.fr", chttp2_create_fixture_secure_fullstack, "foo.test.google.fr", chttp2_create_fixture_secure_fullstack_tls1_2,
chttp2_init_client_simple_ssl_secure_fullstack,
chttp2_init_server_simple_ssl_secure_fullstack,
chttp2_tear_down_secure_fullstack},
{"chttp2/simple_ssl_fullstack_tls1_3",
FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION |
FEATURE_MASK_SUPPORTS_PER_CALL_CREDENTIALS |
FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL |
FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER |
FEATURE_MASK_DOES_NOT_SUPPORT_CLIENT_HANDSHAKE_COMPLETE_FIRST,
"foo.test.google.fr", chttp2_create_fixture_secure_fullstack_tls1_3,
chttp2_init_client_simple_ssl_secure_fullstack, chttp2_init_client_simple_ssl_secure_fullstack,
chttp2_init_server_simple_ssl_secure_fullstack, chttp2_init_server_simple_ssl_secure_fullstack,
chttp2_tear_down_secure_fullstack}, chttp2_tear_down_secure_fullstack},

@ -27,6 +27,7 @@
#include "src/core/lib/gprpp/host_port.h" #include "src/core/lib/gprpp/host_port.h"
#include "src/core/lib/iomgr/load_file.h" #include "src/core/lib/iomgr/load_file.h"
#include "src/core/lib/security/credentials/credentials.h" #include "src/core/lib/security/credentials/credentials.h"
#include "src/core/lib/security/credentials/ssl/ssl_credentials.h"
#include "src/core/lib/security/security_connector/ssl_utils_config.h" #include "src/core/lib/security/security_connector/ssl_utils_config.h"
#include "test/core/end2end/end2end_tests.h" #include "test/core/end2end/end2end_tests.h"
#include "test/core/util/port.h" #include "test/core/util/port.h"
@ -38,6 +39,7 @@
struct fullstack_secure_fixture_data { struct fullstack_secure_fixture_data {
std::string localaddr; std::string localaddr;
grpc_tls_version tls_version;
bool server_credential_reloaded = false; bool server_credential_reloaded = false;
}; };
@ -77,12 +79,14 @@ ssl_server_certificate_config_callback(
} }
static grpc_end2end_test_fixture chttp2_create_fixture_secure_fullstack( static grpc_end2end_test_fixture chttp2_create_fixture_secure_fullstack(
grpc_channel_args* /*client_args*/, grpc_channel_args* /*server_args*/) { grpc_channel_args* /*client_args*/, grpc_channel_args* /*server_args*/,
grpc_tls_version tls_version) {
grpc_end2end_test_fixture f; grpc_end2end_test_fixture f;
int port = grpc_pick_unused_port_or_die(); int port = grpc_pick_unused_port_or_die();
fullstack_secure_fixture_data* ffd = new fullstack_secure_fixture_data(); fullstack_secure_fixture_data* ffd = new fullstack_secure_fixture_data();
memset(&f, 0, sizeof(f)); memset(&f, 0, sizeof(f));
ffd->localaddr = grpc_core::JoinHostPort("localhost", port); ffd->localaddr = grpc_core::JoinHostPort("localhost", port);
ffd->tls_version = tls_version;
f.fixture_data = ffd; f.fixture_data = ffd;
f.cq = grpc_completion_queue_create_for_next(nullptr); f.cq = grpc_completion_queue_create_for_next(nullptr);
@ -91,6 +95,18 @@ static grpc_end2end_test_fixture chttp2_create_fixture_secure_fullstack(
return f; return f;
} }
static grpc_end2end_test_fixture chttp2_create_fixture_secure_fullstack_tls1_2(
grpc_channel_args* client_args, grpc_channel_args* server_args) {
return chttp2_create_fixture_secure_fullstack(client_args, server_args,
grpc_tls_version::TLS1_2);
}
static grpc_end2end_test_fixture chttp2_create_fixture_secure_fullstack_tls1_3(
grpc_channel_args* client_args, grpc_channel_args* server_args) {
return chttp2_create_fixture_secure_fullstack(client_args, server_args,
grpc_tls_version::TLS1_3);
}
static void process_auth_failure(void* state, grpc_auth_context* /*ctx*/, static void process_auth_failure(void* state, grpc_auth_context* /*ctx*/,
const grpc_metadata* /*md*/, const grpc_metadata* /*md*/,
size_t /*md_count*/, size_t /*md_count*/,
@ -138,6 +154,15 @@ static void chttp2_init_client_simple_ssl_secure_fullstack(
grpc_end2end_test_fixture* f, grpc_channel_args* client_args) { grpc_end2end_test_fixture* f, grpc_channel_args* client_args) {
grpc_channel_credentials* ssl_creds = grpc_channel_credentials* ssl_creds =
grpc_ssl_credentials_create(nullptr, nullptr, nullptr, nullptr); grpc_ssl_credentials_create(nullptr, nullptr, nullptr, nullptr);
if (f != nullptr && ssl_creds != nullptr) {
// Set the min and max TLS version.
grpc_ssl_credentials* creds =
reinterpret_cast<grpc_ssl_credentials*>(ssl_creds);
fullstack_secure_fixture_data* ffd =
static_cast<fullstack_secure_fixture_data*>(f->fixture_data);
creds->set_min_tls_version(ffd->tls_version);
creds->set_max_tls_version(ffd->tls_version);
}
grpc_arg ssl_name_override = { grpc_arg ssl_name_override = {
GRPC_ARG_STRING, GRPC_ARG_STRING,
const_cast<char*>(GRPC_SSL_TARGET_NAME_OVERRIDE_ARG), const_cast<char*>(GRPC_SSL_TARGET_NAME_OVERRIDE_ARG),
@ -168,6 +193,15 @@ static void chttp2_init_server_simple_ssl_secure_fullstack(
ssl_server_certificate_config_callback, f->fixture_data); ssl_server_certificate_config_callback, f->fixture_data);
grpc_server_credentials* ssl_creds = grpc_server_credentials* ssl_creds =
grpc_ssl_server_credentials_create_with_options(options); grpc_ssl_server_credentials_create_with_options(options);
if (f != nullptr && ssl_creds != nullptr) {
// Set the min and max TLS version.
grpc_ssl_server_credentials* creds =
reinterpret_cast<grpc_ssl_server_credentials*>(ssl_creds);
fullstack_secure_fixture_data* ffd =
static_cast<fullstack_secure_fixture_data*>(f->fixture_data);
creds->set_min_tls_version(ffd->tls_version);
creds->set_max_tls_version(ffd->tls_version);
}
if (fail_server_auth_check(server_args)) { if (fail_server_auth_check(server_args)) {
grpc_auth_metadata_processor processor = {process_auth_failure, nullptr, grpc_auth_metadata_processor processor = {process_auth_failure, nullptr,
nullptr}; nullptr};
@ -179,12 +213,22 @@ static void chttp2_init_server_simple_ssl_secure_fullstack(
/* All test configurations */ /* All test configurations */
static grpc_end2end_test_config configs[] = { static grpc_end2end_test_config configs[] = {
{"chttp2/simple_ssl_fullstack", {"chttp2/simple_ssl_fullstack_tls1_2",
FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION | FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION |
FEATURE_MASK_SUPPORTS_PER_CALL_CREDENTIALS | FEATURE_MASK_SUPPORTS_PER_CALL_CREDENTIALS |
FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL | FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL |
FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER, FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER,
"foo.test.google.fr", chttp2_create_fixture_secure_fullstack, "foo.test.google.fr", chttp2_create_fixture_secure_fullstack_tls1_2,
chttp2_init_client_simple_ssl_secure_fullstack,
chttp2_init_server_simple_ssl_secure_fullstack,
chttp2_tear_down_secure_fullstack},
{"chttp2/simple_ssl_fullstack_tls1_3",
FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION |
FEATURE_MASK_SUPPORTS_PER_CALL_CREDENTIALS |
FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL |
FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER |
FEATURE_MASK_DOES_NOT_SUPPORT_CLIENT_HANDSHAKE_COMPLETE_FIRST,
"foo.test.google.fr", chttp2_create_fixture_secure_fullstack_tls1_3,
chttp2_init_client_simple_ssl_secure_fullstack, chttp2_init_client_simple_ssl_secure_fullstack,
chttp2_init_server_simple_ssl_secure_fullstack, chttp2_init_server_simple_ssl_secure_fullstack,
chttp2_tear_down_secure_fullstack}, chttp2_tear_down_secure_fullstack},

@ -508,7 +508,15 @@ void filter_call_init_fails(grpc_end2end_test_config config) {
g_enable_client_channel_filter = true; g_enable_client_channel_filter = true;
test_client_channel_filter(config); test_client_channel_filter(config);
g_enable_client_channel_filter = false; g_enable_client_channel_filter = false;
if (config.feature_mask & FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL) { // If the client handshake completes before the server handshake and the
// client is able to send application data before the server handshake
// completes, then testing the CLIENT_SUBCHANNEL filter will cause the server
// to hang waiting for the final handshake message from the client. This
// handshake message will never arrive because it would have been sent with
// the first application data message, which failed because of the filter.
if ((config.feature_mask & FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL) &&
!(config.feature_mask &
FEATURE_MASK_DOES_NOT_SUPPORT_CLIENT_HANDSHAKE_COMPLETE_FIRST)) {
gpr_log(GPR_INFO, "Testing CLIENT_SUBCHANNEL filter."); gpr_log(GPR_INFO, "Testing CLIENT_SUBCHANNEL filter.");
g_enable_client_subchannel_filter = true; g_enable_client_subchannel_filter = true;
test_client_subchannel_filter(config); test_client_subchannel_filter(config);

@ -55,6 +55,9 @@ const size_t kSessionTicketEncryptionKeySize = 80;
const size_t kSessionTicketEncryptionKeySize = 48; const size_t kSessionTicketEncryptionKeySize = 48;
#endif #endif
// Indicates the TLS version used for the test.
static tsi_tls_version test_tls_version = tsi_tls_version::TSI_TLS1_3;
typedef enum AlpnMode { typedef enum AlpnMode {
NO_ALPN, NO_ALPN,
ALPN_CLIENT_NO_SERVER, ALPN_CLIENT_NO_SERVER,
@ -127,6 +130,8 @@ static void ssl_test_setup_handshakers(tsi_test_fixture* fixture) {
if (ssl_fixture->session_cache != nullptr) { if (ssl_fixture->session_cache != nullptr) {
client_options.session_cache = ssl_fixture->session_cache; client_options.session_cache = ssl_fixture->session_cache;
} }
client_options.min_tls_version = test_tls_version;
client_options.max_tls_version = test_tls_version;
GPR_ASSERT(tsi_create_ssl_client_handshaker_factory_with_options( GPR_ASSERT(tsi_create_ssl_client_handshaker_factory_with_options(
&client_options, &ssl_fixture->client_handshaker_factory) == &client_options, &ssl_fixture->client_handshaker_factory) ==
TSI_OK); TSI_OK);
@ -159,6 +164,8 @@ static void ssl_test_setup_handshakers(tsi_test_fixture* fixture) {
} }
server_options.session_ticket_key = ssl_fixture->session_ticket_key; server_options.session_ticket_key = ssl_fixture->session_ticket_key;
server_options.session_ticket_key_size = ssl_fixture->session_ticket_key_size; server_options.session_ticket_key_size = ssl_fixture->session_ticket_key_size;
server_options.min_tls_version = test_tls_version;
server_options.max_tls_version = test_tls_version;
GPR_ASSERT(tsi_create_ssl_server_handshaker_factory_with_options( GPR_ASSERT(tsi_create_ssl_server_handshaker_factory_with_options(
&server_options, &ssl_fixture->server_handshaker_factory) == &server_options, &ssl_fixture->server_handshaker_factory) ==
TSI_OK); TSI_OK);
@ -317,10 +324,18 @@ static void ssl_test_check_handshaker_peers(tsi_test_fixture* fixture) {
GPR_ASSERT(ssl_fixture->key_cert_lib != nullptr); GPR_ASSERT(ssl_fixture->key_cert_lib != nullptr);
ssl_key_cert_lib* key_cert_lib = ssl_fixture->key_cert_lib; ssl_key_cert_lib* key_cert_lib = ssl_fixture->key_cert_lib;
tsi_peer peer; tsi_peer peer;
bool expect_success = // In TLS 1.3, the client-side handshake succeeds even if the client sends a
// bad certificate. In such a case, the server would fail the TLS handshake
// and send an alert to the client as the first application data message. In
// TLS 1.2, the client-side handshake will fail if the client sends a bad
// certificate.
bool expect_server_success =
!(key_cert_lib->use_bad_server_cert || !(key_cert_lib->use_bad_server_cert ||
(key_cert_lib->use_bad_client_cert && ssl_fixture->force_client_auth)); (key_cert_lib->use_bad_client_cert && ssl_fixture->force_client_auth));
if (expect_success) { bool expect_client_success = test_tls_version == tsi_tls_version::TSI_TLS1_2
? expect_server_success
: !key_cert_lib->use_bad_server_cert;
if (expect_client_success) {
GPR_ASSERT(tsi_handshaker_result_extract_peer( GPR_ASSERT(tsi_handshaker_result_extract_peer(
ssl_fixture->base.client_result, &peer) == TSI_OK); ssl_fixture->base.client_result, &peer) == TSI_OK);
check_session_reusage(ssl_fixture, &peer); check_session_reusage(ssl_fixture, &peer);
@ -338,7 +353,7 @@ static void ssl_test_check_handshaker_peers(tsi_test_fixture* fixture) {
} else { } else {
GPR_ASSERT(ssl_fixture->base.client_result == nullptr); GPR_ASSERT(ssl_fixture->base.client_result == nullptr);
} }
if (expect_success) { if (expect_server_success) {
GPR_ASSERT(tsi_handshaker_result_extract_peer( GPR_ASSERT(tsi_handshaker_result_extract_peer(
ssl_fixture->base.server_result, &peer) == TSI_OK); ssl_fixture->base.server_result, &peer) == TSI_OK);
check_session_reusage(ssl_fixture, &peer); check_session_reusage(ssl_fixture, &peer);
@ -421,7 +436,7 @@ static tsi_test_fixture* ssl_tsi_test_fixture_create() {
ssl_tsi_test_fixture* ssl_fixture = ssl_tsi_test_fixture* ssl_fixture =
static_cast<ssl_tsi_test_fixture*>(gpr_zalloc(sizeof(*ssl_fixture))); static_cast<ssl_tsi_test_fixture*>(gpr_zalloc(sizeof(*ssl_fixture)));
tsi_test_fixture_init(&ssl_fixture->base); tsi_test_fixture_init(&ssl_fixture->base);
ssl_fixture->base.test_unused_bytes = false; ssl_fixture->base.test_unused_bytes = true;
ssl_fixture->base.vtable = &vtable; ssl_fixture->base.vtable = &vtable;
/* Create ssl_key_cert_lib. */ /* Create ssl_key_cert_lib. */
ssl_key_cert_lib* key_cert_lib = ssl_key_cert_lib* key_cert_lib =
@ -494,6 +509,9 @@ void ssl_tsi_test_do_handshake_tiny_handshake_buffer() {
gpr_log(GPR_INFO, "ssl_tsi_test_do_handshake_tiny_handshake_buffer"); gpr_log(GPR_INFO, "ssl_tsi_test_do_handshake_tiny_handshake_buffer");
tsi_test_fixture* fixture = ssl_tsi_test_fixture_create(); tsi_test_fixture* fixture = ssl_tsi_test_fixture_create();
fixture->handshake_buffer_size = TSI_TEST_TINY_HANDSHAKE_BUFFER_SIZE; fixture->handshake_buffer_size = TSI_TEST_TINY_HANDSHAKE_BUFFER_SIZE;
// Handshake buffer is too small to hold both handshake messages and the
// unused bytes.
fixture->test_unused_bytes = false;
tsi_test_do_handshake(fixture); tsi_test_do_handshake(fixture);
tsi_test_fixture_destroy(fixture); tsi_test_fixture_destroy(fixture);
} }
@ -951,6 +969,13 @@ void ssl_tsi_test_extract_cert_chain() {
int main(int argc, char** argv) { int main(int argc, char** argv) {
grpc::testing::TestEnvironment env(argc, argv); grpc::testing::TestEnvironment env(argc, argv);
grpc_init(); grpc_init();
const size_t number_tls_versions = 2;
const tsi_tls_version tls_versions[] = {tsi_tls_version::TSI_TLS1_2,
tsi_tls_version::TSI_TLS1_3};
for (size_t i = 0; i < number_tls_versions; i++) {
// Set the TLS version to be used in the tests.
test_tls_version = tls_versions[i];
// Run all the tests using that TLS version for both the client and server.
ssl_tsi_test_do_handshake_tiny_handshake_buffer(); ssl_tsi_test_do_handshake_tiny_handshake_buffer();
ssl_tsi_test_do_handshake_small_handshake_buffer(); ssl_tsi_test_do_handshake_small_handshake_buffer();
ssl_tsi_test_do_handshake(); ssl_tsi_test_do_handshake();
@ -976,6 +1001,7 @@ int main(int argc, char** argv) {
ssl_tsi_test_duplicate_root_certificates(); ssl_tsi_test_duplicate_root_certificates();
ssl_tsi_test_extract_x509_subject_names(); ssl_tsi_test_extract_x509_subject_names();
ssl_tsi_test_extract_cert_chain(); ssl_tsi_test_extract_cert_chain();
}
grpc_shutdown(); grpc_shutdown();
return 0; return 0;
} }

Loading…
Cancel
Save