aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt34
-rw-r--r--Makefile36
-rw-r--r--build.yaml15
-rw-r--r--include/grpc/grpc_security.h31
-rw-r--r--src/core/lib/security/credentials/google_default/google_default_credentials.cc3
-rw-r--r--src/core/lib/security/credentials/ssl/ssl_credentials.cc20
-rw-r--r--src/core/lib/security/security_connector/security_connector.cc35
-rw-r--r--src/core/lib/security/security_connector/security_connector.h1
-rw-r--r--src/cpp/client/secure_credentials.cc3
-rw-r--r--src/csharp/ext/grpc_csharp_ext.c5
-rw-r--r--src/objective-c/GRPCClient/private/GRPCHost.m4
-rw-r--r--src/php/ext/grpc/channel_credentials.c2
-rw-r--r--src/python/grpcio/grpc/_cython/_cygrpc/credentials.pyx.pxi4
-rw-r--r--src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi7
-rw-r--r--src/ruby/ext/grpc/rb_channel_credentials.c6
-rw-r--r--src/ruby/ext/grpc/rb_grpc_imports.generated.h2
-rw-r--r--test/core/bad_ssl/bad_ssl_test.cc2
-rw-r--r--test/core/end2end/fixtures/h2_oauth2.cc2
-rw-r--r--test/core/end2end/fixtures/h2_ssl.cc2
-rw-r--r--test/core/end2end/fixtures/h2_ssl_proxy.cc4
-rw-r--r--test/core/end2end/fuzzers/api_fuzzer.cc2
-rw-r--r--test/core/end2end/h2_ssl_cert_test.cc4
-rw-r--r--test/core/end2end/h2_ssl_session_reuse_test.cc2
-rw-r--r--test/core/handshake/BUILD18
-rw-r--r--test/core/handshake/client_ssl.cc4
-rw-r--r--test/core/handshake/verify_peer_options.cc275
-rw-r--r--test/core/surface/num_external_connectivity_watchers_test.cc2
-rw-r--r--test/core/surface/sequential_connectivity_test.cc2
-rw-r--r--tools/run_tests/generated/sources_and_headers.json17
-rw-r--r--tools/run_tests/generated/tests.json20
30 files changed, 526 insertions, 38 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index d92d7c0558..6371521f6a 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -309,6 +309,9 @@ endif()
if(_gRPC_PLATFORM_LINUX)
add_dependencies(buildtests_c handshake_server_with_readahead_handshaker)
endif()
+if(_gRPC_PLATFORM_LINUX)
+add_dependencies(buildtests_c handshake_verify_peer_options)
+endif()
add_dependencies(buildtests_c histogram_test)
add_dependencies(buildtests_c hpack_parser_test)
add_dependencies(buildtests_c hpack_table_test)
@@ -7491,6 +7494,37 @@ target_link_libraries(handshake_server_with_readahead_handshaker
endif()
endif (gRPC_BUILD_TESTS)
if (gRPC_BUILD_TESTS)
+if(_gRPC_PLATFORM_LINUX)
+
+add_executable(handshake_verify_peer_options
+ test/core/handshake/verify_peer_options.cc
+)
+
+
+target_include_directories(handshake_verify_peer_options
+ PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
+ PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
+ PRIVATE ${_gRPC_SSL_INCLUDE_DIR}
+ PRIVATE ${_gRPC_PROTOBUF_INCLUDE_DIR}
+ PRIVATE ${_gRPC_ZLIB_INCLUDE_DIR}
+ PRIVATE ${_gRPC_BENCHMARK_INCLUDE_DIR}
+ PRIVATE ${_gRPC_CARES_INCLUDE_DIR}
+ PRIVATE ${_gRPC_GFLAGS_INCLUDE_DIR}
+ PRIVATE ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
+)
+
+target_link_libraries(handshake_verify_peer_options
+ ${_gRPC_SSL_LIBRARIES}
+ ${_gRPC_ALLTARGETS_LIBRARIES}
+ grpc_test_util
+ grpc
+ gpr_test_util
+ gpr
+)
+
+endif()
+endif (gRPC_BUILD_TESTS)
+if (gRPC_BUILD_TESTS)
add_executable(histogram_test
test/core/util/histogram_test.cc
diff --git a/Makefile b/Makefile
index f4d8e3139b..5bb4fbab43 100644
--- a/Makefile
+++ b/Makefile
@@ -1012,6 +1012,7 @@ grpc_verify_jwt: $(BINDIR)/$(CONFIG)/grpc_verify_jwt
handshake_client: $(BINDIR)/$(CONFIG)/handshake_client
handshake_server: $(BINDIR)/$(CONFIG)/handshake_server
handshake_server_with_readahead_handshaker: $(BINDIR)/$(CONFIG)/handshake_server_with_readahead_handshaker
+handshake_verify_peer_options: $(BINDIR)/$(CONFIG)/handshake_verify_peer_options
histogram_test: $(BINDIR)/$(CONFIG)/histogram_test
hpack_parser_fuzzer_test: $(BINDIR)/$(CONFIG)/hpack_parser_fuzzer_test
hpack_parser_test: $(BINDIR)/$(CONFIG)/hpack_parser_test
@@ -1454,6 +1455,7 @@ buildtests_c: privatelibs_c \
$(BINDIR)/$(CONFIG)/handshake_client \
$(BINDIR)/$(CONFIG)/handshake_server \
$(BINDIR)/$(CONFIG)/handshake_server_with_readahead_handshaker \
+ $(BINDIR)/$(CONFIG)/handshake_verify_peer_options \
$(BINDIR)/$(CONFIG)/histogram_test \
$(BINDIR)/$(CONFIG)/hpack_parser_test \
$(BINDIR)/$(CONFIG)/hpack_table_test \
@@ -2009,6 +2011,8 @@ test_c: buildtests_c
$(Q) $(BINDIR)/$(CONFIG)/handshake_server || ( echo test handshake_server failed ; exit 1 )
$(E) "[RUN] Testing handshake_server_with_readahead_handshaker"
$(Q) $(BINDIR)/$(CONFIG)/handshake_server_with_readahead_handshaker || ( echo test handshake_server_with_readahead_handshaker failed ; exit 1 )
+ $(E) "[RUN] Testing handshake_verify_peer_options"
+ $(Q) $(BINDIR)/$(CONFIG)/handshake_verify_peer_options || ( echo test handshake_verify_peer_options failed ; exit 1 )
$(E) "[RUN] Testing histogram_test"
$(Q) $(BINDIR)/$(CONFIG)/histogram_test || ( echo test histogram_test failed ; exit 1 )
$(E) "[RUN] Testing hpack_parser_test"
@@ -12469,6 +12473,38 @@ endif
endif
+HANDSHAKE_VERIFY_PEER_OPTIONS_SRC = \
+ test/core/handshake/verify_peer_options.cc \
+
+HANDSHAKE_VERIFY_PEER_OPTIONS_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(HANDSHAKE_VERIFY_PEER_OPTIONS_SRC))))
+ifeq ($(NO_SECURE),true)
+
+# You can't build secure targets if you don't have OpenSSL.
+
+$(BINDIR)/$(CONFIG)/handshake_verify_peer_options: openssl_dep_error
+
+else
+
+
+
+$(BINDIR)/$(CONFIG)/handshake_verify_peer_options: $(HANDSHAKE_VERIFY_PEER_OPTIONS_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+ $(E) "[LD] Linking $@"
+ $(Q) mkdir -p `dirname $@`
+ $(Q) $(LD) $(LDFLAGS) $(HANDSHAKE_VERIFY_PEER_OPTIONS_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/handshake_verify_peer_options
+
+endif
+
+$(OBJDIR)/$(CONFIG)/test/core/handshake/verify_peer_options.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+
+deps_handshake_verify_peer_options: $(HANDSHAKE_VERIFY_PEER_OPTIONS_OBJS:.o=.dep)
+
+ifneq ($(NO_SECURE),true)
+ifneq ($(NO_DEPS),true)
+-include $(HANDSHAKE_VERIFY_PEER_OPTIONS_OBJS:.o=.dep)
+endif
+endif
+
+
HISTOGRAM_TEST_SRC = \
test/core/util/histogram_test.cc \
diff --git a/build.yaml b/build.yaml
index 593c845e3c..f963f0c913 100644
--- a/build.yaml
+++ b/build.yaml
@@ -2792,6 +2792,21 @@ targets:
platforms:
- linux
secure: true
+- name: handshake_verify_peer_options
+ build: test
+ language: c
+ src:
+ - test/core/handshake/verify_peer_options.cc
+ deps:
+ - grpc_test_util
+ - grpc
+ - gpr_test_util
+ - gpr
+ exclude_iomgrs:
+ - uv
+ platforms:
+ - linux
+ secure: true
- name: histogram_test
build: test
language: c
diff --git a/include/grpc/grpc_security.h b/include/grpc/grpc_security.h
index e1975a8e09..b34fb70898 100644
--- a/include/grpc/grpc_security.h
+++ b/include/grpc/grpc_security.h
@@ -163,6 +163,26 @@ typedef struct {
const char* cert_chain;
} grpc_ssl_pem_key_cert_pair;
+/** Object that holds additional peer-verification options on a secure
+ channel. */
+typedef struct {
+ /** If non-NULL this callback will be invoked with the expected
+ target_name, the peer's certificate (in PEM format), and whatever
+ userdata pointer is set below. If a non-zero value is returned by this
+ callback then it is treated as a verification failure. Invocation of
+ the callback is blocking, so any implementation should be light-weight.
+ */
+ int (*verify_peer_callback)(const char* target_name, const char* peer_pem,
+ void* userdata);
+ /** Arbitrary userdata that will be passed as the last argument to
+ verify_peer_callback. */
+ void* verify_peer_callback_userdata;
+ /** A destruct callback that will be invoked when the channel is being
+ cleaned up. The userdata argument will be passed to it. The intent is
+ to perform any cleanup associated with that userdata. */
+ void (*verify_peer_destruct)(void* userdata);
+} verify_peer_options;
+
/** Creates an SSL credentials object.
- pem_root_certs is the NULL-terminated string containing the PEM encoding
of the server root certificates. If this parameter is NULL, the
@@ -173,10 +193,17 @@ typedef struct {
disk (in the grpc install directory).
- pem_key_cert_pair is a pointer on the object containing client's private
key and certificate chain. This parameter can be NULL if the client does
- not have such a key/cert pair. */
+ not have such a key/cert pair.
+ - verify_options is an optional verify_peer_options object which holds
+ additional options controlling how peer certificates are verified. For
+ example, you can supply a callback which receives the peer's certificate
+ with which you can do additional verification. Can be NULL, in which
+ case verification will retain default behavior. Any settings in
+ verify_options are copied during this call, so the verify_options
+ object can be released afterwards. */
GRPCAPI grpc_channel_credentials* grpc_ssl_credentials_create(
const char* pem_root_certs, grpc_ssl_pem_key_cert_pair* pem_key_cert_pair,
- void* reserved);
+ const verify_peer_options* verify_options, void* reserved);
/** --- grpc_call_credentials object.
diff --git a/src/core/lib/security/credentials/google_default/google_default_credentials.cc b/src/core/lib/security/credentials/google_default/google_default_credentials.cc
index 38c9175717..c456ffaf5d 100644
--- a/src/core/lib/security/credentials/google_default/google_default_credentials.cc
+++ b/src/core/lib/security/credentials/google_default/google_default_credentials.cc
@@ -231,7 +231,8 @@ end:
creds->base.vtable = &google_default_credentials_vtable;
creds->base.type = GRPC_CHANNEL_CREDENTIALS_TYPE_GOOGLE_DEFAULT;
gpr_ref_init(&creds->base.refcount, 1);
- creds->ssl_creds = grpc_ssl_credentials_create(nullptr, nullptr, nullptr);
+ creds->ssl_creds =
+ grpc_ssl_credentials_create(nullptr, nullptr, nullptr, nullptr);
GPR_ASSERT(creds->ssl_creds != nullptr);
grpc_alts_credentials_options* options =
grpc_alts_credentials_client_options_create();
diff --git a/src/core/lib/security/credentials/ssl/ssl_credentials.cc b/src/core/lib/security/credentials/ssl/ssl_credentials.cc
index 2b6377d3ec..3d6f2f200a 100644
--- a/src/core/lib/security/credentials/ssl/ssl_credentials.cc
+++ b/src/core/lib/security/credentials/ssl/ssl_credentials.cc
@@ -48,6 +48,10 @@ static void ssl_destruct(grpc_channel_credentials* creds) {
grpc_ssl_credentials* c = reinterpret_cast<grpc_ssl_credentials*>(creds);
gpr_free(c->config.pem_root_certs);
grpc_tsi_ssl_pem_key_cert_pairs_destroy(c->config.pem_key_cert_pair, 1);
+ if (c->config.verify_options.verify_peer_destruct != nullptr) {
+ c->config.verify_options.verify_peer_destruct(
+ c->config.verify_options.verify_peer_callback_userdata);
+ }
}
static grpc_security_status ssl_create_security_connector(
@@ -87,6 +91,7 @@ static grpc_channel_credentials_vtable ssl_vtable = {
static void ssl_build_config(const char* pem_root_certs,
grpc_ssl_pem_key_cert_pair* pem_key_cert_pair,
+ const verify_peer_options* verify_options,
grpc_ssl_config* config) {
if (pem_root_certs != nullptr) {
config->pem_root_certs = gpr_strdup(pem_root_certs);
@@ -101,23 +106,32 @@ static void ssl_build_config(const char* pem_root_certs,
config->pem_key_cert_pair->private_key =
gpr_strdup(pem_key_cert_pair->private_key);
}
+ if (verify_options != nullptr) {
+ memcpy(&config->verify_options, verify_options,
+ sizeof(verify_peer_options));
+ } else {
+ // Otherwise set all options to default values
+ memset(&config->verify_options, 0, sizeof(verify_peer_options));
+ }
}
grpc_channel_credentials* grpc_ssl_credentials_create(
const char* pem_root_certs, grpc_ssl_pem_key_cert_pair* pem_key_cert_pair,
- void* reserved) {
+ const verify_peer_options* verify_options, void* reserved) {
grpc_ssl_credentials* c = static_cast<grpc_ssl_credentials*>(
gpr_zalloc(sizeof(grpc_ssl_credentials)));
GRPC_API_TRACE(
"grpc_ssl_credentials_create(pem_root_certs=%s, "
"pem_key_cert_pair=%p, "
+ "verify_options=%p, "
"reserved=%p)",
- 3, (pem_root_certs, pem_key_cert_pair, reserved));
+ 4, (pem_root_certs, pem_key_cert_pair, verify_options, reserved));
GPR_ASSERT(reserved == nullptr);
c->base.type = GRPC_CHANNEL_CREDENTIALS_TYPE_SSL;
c->base.vtable = &ssl_vtable;
gpr_ref_init(&c->base.refcount, 1);
- ssl_build_config(pem_root_certs, pem_key_cert_pair, &c->config);
+ ssl_build_config(pem_root_certs, pem_key_cert_pair, verify_options,
+ &c->config);
return &c->base;
}
diff --git a/src/core/lib/security/security_connector/security_connector.cc b/src/core/lib/security/security_connector/security_connector.cc
index b54a7643e4..cc72bb6164 100644
--- a/src/core/lib/security/security_connector/security_connector.cc
+++ b/src/core/lib/security/security_connector/security_connector.cc
@@ -620,6 +620,7 @@ typedef struct {
tsi_ssl_client_handshaker_factory* client_handshaker_factory;
char* target_name;
char* overridden_target_name;
+ const verify_peer_options* verify_options;
} grpc_ssl_channel_security_connector;
typedef struct {
@@ -878,11 +879,34 @@ static void ssl_channel_check_peer(grpc_security_connector* sc, tsi_peer peer,
grpc_closure* on_peer_checked) {
grpc_ssl_channel_security_connector* c =
reinterpret_cast<grpc_ssl_channel_security_connector*>(sc);
- grpc_error* error = ssl_check_peer(sc,
- c->overridden_target_name != nullptr
- ? c->overridden_target_name
- : c->target_name,
- &peer, auth_context);
+ const char* target_name = c->overridden_target_name != nullptr
+ ? c->overridden_target_name
+ : c->target_name;
+ grpc_error* error = ssl_check_peer(sc, target_name, &peer, auth_context);
+ if (error == GRPC_ERROR_NONE &&
+ c->verify_options->verify_peer_callback != nullptr) {
+ const tsi_peer_property* p =
+ tsi_peer_get_property_by_name(&peer, TSI_X509_PEM_CERT_PROPERTY);
+ if (p == nullptr) {
+ error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(
+ "Cannot check peer: missing pem cert property.");
+ } else {
+ char* peer_pem = static_cast<char*>(gpr_malloc(p->value.length + 1));
+ memcpy(peer_pem, p->value.data, p->value.length);
+ peer_pem[p->value.length] = '\0';
+ int callback_status = c->verify_options->verify_peer_callback(
+ target_name, peer_pem,
+ c->verify_options->verify_peer_callback_userdata);
+ gpr_free(peer_pem);
+ if (callback_status) {
+ char* msg;
+ gpr_asprintf(&msg, "Verify peer callback returned a failure (%d)",
+ callback_status);
+ error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg);
+ gpr_free(msg);
+ }
+ }
+ }
GRPC_CLOSURE_SCHED(on_peer_checked, error);
tsi_peer_destruct(&peer);
}
@@ -1047,6 +1071,7 @@ grpc_security_status grpc_ssl_channel_security_connector_create(
if (overridden_target_name != nullptr) {
c->overridden_target_name = gpr_strdup(overridden_target_name);
}
+ c->verify_options = &config->verify_options;
has_key_cert_pair = config->pem_key_cert_pair != nullptr &&
config->pem_key_cert_pair->private_key != nullptr &&
diff --git a/src/core/lib/security/security_connector/security_connector.h b/src/core/lib/security/security_connector/security_connector.h
index f9723166d0..67a506b576 100644
--- a/src/core/lib/security/security_connector/security_connector.h
+++ b/src/core/lib/security/security_connector/security_connector.h
@@ -193,6 +193,7 @@ grpc_server_security_connector* grpc_fake_server_security_connector_create(
typedef struct {
tsi_ssl_pem_key_cert_pair* pem_key_cert_pair;
char* pem_root_certs;
+ verify_peer_options verify_options;
} grpc_ssl_config;
/* Creates an SSL channel_security_connector.
diff --git a/src/cpp/client/secure_credentials.cc b/src/cpp/client/secure_credentials.cc
index 00245b397d..bdb6359632 100644
--- a/src/cpp/client/secure_credentials.cc
+++ b/src/cpp/client/secure_credentials.cc
@@ -83,7 +83,8 @@ std::shared_ptr<ChannelCredentials> SslCredentials(
grpc_channel_credentials* c_creds = grpc_ssl_credentials_create(
options.pem_root_certs.empty() ? nullptr : options.pem_root_certs.c_str(),
- options.pem_private_key.empty() ? nullptr : &pem_key_cert_pair, nullptr);
+ options.pem_private_key.empty() ? nullptr : &pem_key_cert_pair, nullptr,
+ nullptr);
return WrapChannelCredentials(c_creds);
}
diff --git a/src/csharp/ext/grpc_csharp_ext.c b/src/csharp/ext/grpc_csharp_ext.c
index 3e6ec474b7..87a2516f8d 100644
--- a/src/csharp/ext/grpc_csharp_ext.c
+++ b/src/csharp/ext/grpc_csharp_ext.c
@@ -935,11 +935,12 @@ grpcsharp_ssl_credentials_create(const char* pem_root_certs,
if (key_cert_pair_cert_chain || key_cert_pair_private_key) {
key_cert_pair.cert_chain = key_cert_pair_cert_chain;
key_cert_pair.private_key = key_cert_pair_private_key;
- return grpc_ssl_credentials_create(pem_root_certs, &key_cert_pair, NULL);
+ return grpc_ssl_credentials_create(pem_root_certs, &key_cert_pair, NULL,
+ NULL);
} else {
GPR_ASSERT(!key_cert_pair_cert_chain);
GPR_ASSERT(!key_cert_pair_private_key);
- return grpc_ssl_credentials_create(pem_root_certs, NULL, NULL);
+ return grpc_ssl_credentials_create(pem_root_certs, NULL, NULL, NULL);
}
}
diff --git a/src/objective-c/GRPCClient/private/GRPCHost.m b/src/objective-c/GRPCClient/private/GRPCHost.m
index f4b933751f..348989904a 100644
--- a/src/objective-c/GRPCClient/private/GRPCHost.m
+++ b/src/objective-c/GRPCClient/private/GRPCHost.m
@@ -183,14 +183,14 @@ static NSMutableDictionary *kHostCache;
grpc_channel_credentials *creds;
if (pemPrivateKey == nil && pemCertChain == nil) {
- creds = grpc_ssl_credentials_create(rootsASCII.bytes, NULL, NULL);
+ creds = grpc_ssl_credentials_create(rootsASCII.bytes, NULL, NULL, NULL);
} else {
grpc_ssl_pem_key_cert_pair key_cert_pair;
NSData *privateKeyASCII = [self nullTerminatedDataWithString:pemPrivateKey];
NSData *certChainASCII = [self nullTerminatedDataWithString:pemCertChain];
key_cert_pair.private_key = privateKeyASCII.bytes;
key_cert_pair.cert_chain = certChainASCII.bytes;
- creds = grpc_ssl_credentials_create(rootsASCII.bytes, &key_cert_pair, NULL);
+ creds = grpc_ssl_credentials_create(rootsASCII.bytes, &key_cert_pair, NULL, NULL);
}
@synchronized(self) {
diff --git a/src/php/ext/grpc/channel_credentials.c b/src/php/ext/grpc/channel_credentials.c
index 10d7380ca1..af1372878d 100644
--- a/src/php/ext/grpc/channel_credentials.c
+++ b/src/php/ext/grpc/channel_credentials.c
@@ -158,7 +158,7 @@ PHP_METHOD(ChannelCredentials, createSsl) {
grpc_channel_credentials *creds = grpc_ssl_credentials_create(
pem_root_certs,
- pem_key_cert_pair.private_key == NULL ? NULL : &pem_key_cert_pair, NULL);
+ pem_key_cert_pair.private_key == NULL ? NULL : &pem_key_cert_pair, NULL, NULL);
zval *creds_object = grpc_php_wrap_channel_credentials(creds, hashstr, false
TSRMLS_CC);
efree(hashkey);
diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/credentials.pyx.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/credentials.pyx.pxi
index f4ccfbc016..d2c0389ca6 100644
--- a/src/python/grpcio/grpc/_cython/_cygrpc/credentials.pyx.pxi
+++ b/src/python/grpcio/grpc/_cython/_cygrpc/credentials.pyx.pxi
@@ -142,12 +142,12 @@ cdef class SSLChannelCredentials(ChannelCredentials):
c_pem_root_certificates = self._pem_root_certificates
if self._private_key is None and self._certificate_chain is None:
return grpc_ssl_credentials_create(
- c_pem_root_certificates, NULL, NULL)
+ c_pem_root_certificates, NULL, NULL, NULL)
else:
c_pem_key_certificate_pair.private_key = self._private_key
c_pem_key_certificate_pair.certificate_chain = self._certificate_chain
return grpc_ssl_credentials_create(
- c_pem_root_certificates, &c_pem_key_certificate_pair, NULL)
+ c_pem_root_certificates, &c_pem_key_certificate_pair, NULL, NULL)
cdef class CompositeChannelCredentials(ChannelCredentials):
diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi
index cfefeaf938..bcbfec0c9f 100644
--- a/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi
+++ b/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi
@@ -453,11 +453,14 @@ cdef extern from "grpc/grpc_security.h":
# We don't care about the internals (and in fact don't know them)
pass
-
ctypedef struct grpc_ssl_session_cache:
# We don't care about the internals (and in fact don't know them)
pass
+ ctypedef struct verify_peer_options:
+ # We don't care about the internals (and in fact don't know them)
+ pass
+
ctypedef void (*grpc_ssl_roots_override_callback)(char **pem_root_certs)
grpc_ssl_session_cache *grpc_ssl_session_cache_create_lru(size_t capacity)
@@ -469,7 +472,7 @@ cdef extern from "grpc/grpc_security.h":
grpc_channel_credentials *grpc_google_default_credentials_create() nogil
grpc_channel_credentials *grpc_ssl_credentials_create(
const char *pem_root_certs, grpc_ssl_pem_key_cert_pair *pem_key_cert_pair,
- void *reserved) nogil
+ verify_peer_options *verify_options, void *reserved) nogil
grpc_channel_credentials *grpc_composite_channel_credentials_create(
grpc_channel_credentials *creds1, grpc_call_credentials *creds2,
void *reserved) nogil
diff --git a/src/ruby/ext/grpc/rb_channel_credentials.c b/src/ruby/ext/grpc/rb_channel_credentials.c
index b23a32caf1..178224c6e0 100644
--- a/src/ruby/ext/grpc/rb_channel_credentials.c
+++ b/src/ruby/ext/grpc/rb_channel_credentials.c
@@ -159,12 +159,12 @@ static VALUE grpc_rb_channel_credentials_init(int argc, VALUE* argv,
pem_root_certs_cstr = RSTRING_PTR(pem_root_certs);
}
if (pem_private_key == Qnil && pem_cert_chain == Qnil) {
- creds = grpc_ssl_credentials_create(pem_root_certs_cstr, NULL, NULL);
+ creds = grpc_ssl_credentials_create(pem_root_certs_cstr, NULL, NULL, NULL);
} else {
key_cert_pair.private_key = RSTRING_PTR(pem_private_key);
key_cert_pair.cert_chain = RSTRING_PTR(pem_cert_chain);
- creds =
- grpc_ssl_credentials_create(pem_root_certs_cstr, &key_cert_pair, NULL);
+ creds = grpc_ssl_credentials_create(pem_root_certs_cstr, &key_cert_pair,
+ NULL, NULL);
}
if (creds == NULL) {
rb_raise(rb_eRuntimeError, "could not create a credentials, not sure why");
diff --git a/src/ruby/ext/grpc/rb_grpc_imports.generated.h b/src/ruby/ext/grpc/rb_grpc_imports.generated.h
index b2186a69aa..46d3bf5a33 100644
--- a/src/ruby/ext/grpc/rb_grpc_imports.generated.h
+++ b/src/ruby/ext/grpc/rb_grpc_imports.generated.h
@@ -317,7 +317,7 @@ extern grpc_google_default_credentials_create_type grpc_google_default_credentia
typedef void(*grpc_set_ssl_roots_override_callback_type)(grpc_ssl_roots_override_callback cb);
extern grpc_set_ssl_roots_override_callback_type grpc_set_ssl_roots_override_callback_import;
#define grpc_set_ssl_roots_override_callback grpc_set_ssl_roots_override_callback_import
-typedef grpc_channel_credentials*(*grpc_ssl_credentials_create_type)(const char* pem_root_certs, grpc_ssl_pem_key_cert_pair* pem_key_cert_pair, void* reserved);
+typedef grpc_channel_credentials*(*grpc_ssl_credentials_create_type)(const char* pem_root_certs, grpc_ssl_pem_key_cert_pair* pem_key_cert_pair, const verify_peer_options* verify_options, void* reserved);
extern grpc_ssl_credentials_create_type grpc_ssl_credentials_create_import;
#define grpc_ssl_credentials_create grpc_ssl_credentials_create_import
typedef void(*grpc_call_credentials_release_type)(grpc_call_credentials* creds);
diff --git a/test/core/bad_ssl/bad_ssl_test.cc b/test/core/bad_ssl/bad_ssl_test.cc
index e2ea7540ef..73d251eff4 100644
--- a/test/core/bad_ssl/bad_ssl_test.cc
+++ b/test/core/bad_ssl/bad_ssl_test.cc
@@ -37,7 +37,7 @@ static void* tag(intptr_t t) { return (void*)t; }
static void run_test(const char* target, size_t nops) {
grpc_channel_credentials* ssl_creds =
- grpc_ssl_credentials_create(nullptr, nullptr, nullptr);
+ grpc_ssl_credentials_create(nullptr, nullptr, nullptr, nullptr);
grpc_channel* channel;
grpc_call* c;
diff --git a/test/core/end2end/fixtures/h2_oauth2.cc b/test/core/end2end/fixtures/h2_oauth2.cc
index d44aafd50a..37397d6450 100644
--- a/test/core/end2end/fixtures/h2_oauth2.cc
+++ b/test/core/end2end/fixtures/h2_oauth2.cc
@@ -146,7 +146,7 @@ static void chttp2_init_client_simple_ssl_with_oauth2_secure_fullstack(
grpc_end2end_test_fixture* f, grpc_channel_args* client_args) {
grpc_core::ExecCtx exec_ctx;
grpc_channel_credentials* ssl_creds =
- grpc_ssl_credentials_create(test_root_cert, nullptr, nullptr);
+ grpc_ssl_credentials_create(test_root_cert, nullptr, nullptr, nullptr);
grpc_call_credentials* oauth2_creds = grpc_md_only_test_credentials_create(
"authorization", oauth2_md, true /* is_async */);
grpc_channel_credentials* ssl_oauth2_creds =
diff --git a/test/core/end2end/fixtures/h2_ssl.cc b/test/core/end2end/fixtures/h2_ssl.cc
index 999cd4cdfb..4d6c815716 100644
--- a/test/core/end2end/fixtures/h2_ssl.cc
+++ b/test/core/end2end/fixtures/h2_ssl.cc
@@ -101,7 +101,7 @@ void chttp2_tear_down_secure_fullstack(grpc_end2end_test_fixture* f) {
static void chttp2_init_client_simple_ssl_secure_fullstack(
grpc_end2end_test_fixture* f, grpc_channel_args* client_args) {
grpc_channel_credentials* ssl_creds =
- grpc_ssl_credentials_create(nullptr, nullptr, nullptr);
+ grpc_ssl_credentials_create(nullptr, nullptr, nullptr, nullptr);
grpc_arg ssl_name_override = {
GRPC_ARG_STRING,
const_cast<char*>(GRPC_SSL_TARGET_NAME_OVERRIDE_ARG),
diff --git a/test/core/end2end/fixtures/h2_ssl_proxy.cc b/test/core/end2end/fixtures/h2_ssl_proxy.cc
index 9ab50c6217..09cbf974b6 100644
--- a/test/core/end2end/fixtures/h2_ssl_proxy.cc
+++ b/test/core/end2end/fixtures/h2_ssl_proxy.cc
@@ -55,7 +55,7 @@ static grpc_channel* create_proxy_client(const char* target,
grpc_channel_args* client_args) {
grpc_channel* channel;
grpc_channel_credentials* ssl_creds =
- grpc_ssl_credentials_create(nullptr, nullptr, nullptr);
+ grpc_ssl_credentials_create(nullptr, nullptr, nullptr, nullptr);
grpc_arg ssl_name_override = {
GRPC_ARG_STRING,
const_cast<char*>(GRPC_SSL_TARGET_NAME_OVERRIDE_ARG),
@@ -138,7 +138,7 @@ void chttp2_tear_down_secure_fullstack(grpc_end2end_test_fixture* f) {
static void chttp2_init_client_simple_ssl_secure_fullstack(
grpc_end2end_test_fixture* f, grpc_channel_args* client_args) {
grpc_channel_credentials* ssl_creds =
- grpc_ssl_credentials_create(nullptr, nullptr, nullptr);
+ grpc_ssl_credentials_create(nullptr, nullptr, nullptr, nullptr);
grpc_arg ssl_name_override = {
GRPC_ARG_STRING,
const_cast<char*>(GRPC_SSL_TARGET_NAME_OVERRIDE_ARG),
diff --git a/test/core/end2end/fuzzers/api_fuzzer.cc b/test/core/end2end/fuzzers/api_fuzzer.cc
index ccb194cdf5..6c226818b9 100644
--- a/test/core/end2end/fuzzers/api_fuzzer.cc
+++ b/test/core/end2end/fuzzers/api_fuzzer.cc
@@ -222,7 +222,7 @@ static grpc_channel_credentials* read_ssl_channel_creds(input_stream* inp) {
grpc_channel_credentials* creds = grpc_ssl_credentials_create(
root_certs,
private_key != nullptr && certs != nullptr ? &key_cert_pair : nullptr,
- nullptr);
+ nullptr, nullptr);
cred_artifact_ctx_finish(&ctx);
return creds;
}
diff --git a/test/core/end2end/h2_ssl_cert_test.cc b/test/core/end2end/h2_ssl_cert_test.cc
index 9ed6f23798..2c5ee3b156 100644
--- a/test/core/end2end/h2_ssl_cert_test.cc
+++ b/test/core/end2end/h2_ssl_cert_test.cc
@@ -169,8 +169,8 @@ typedef enum { NONE, SELF_SIGNED, SIGNED, BAD_CERT_PAIR } certtype;
default: \
break; \
} \
- ssl_creds = \
- grpc_ssl_credentials_create(test_root_cert, key_cert_pair, NULL); \
+ ssl_creds = grpc_ssl_credentials_create(test_root_cert, key_cert_pair, \
+ NULL, NULL); \
grpc_arg ssl_name_override = { \
GRPC_ARG_STRING, \
const_cast<char*>(GRPC_SSL_TARGET_NAME_OVERRIDE_ARG), \
diff --git a/test/core/end2end/h2_ssl_session_reuse_test.cc b/test/core/end2end/h2_ssl_session_reuse_test.cc
index d5984be93f..b2f398625a 100644
--- a/test/core/end2end/h2_ssl_session_reuse_test.cc
+++ b/test/core/end2end/h2_ssl_session_reuse_test.cc
@@ -66,7 +66,7 @@ grpc_channel* client_create(char* server_addr, grpc_ssl_session_cache* cache) {
grpc_ssl_pem_key_cert_pair signed_client_key_cert_pair = {
test_signed_client_key, test_signed_client_cert};
grpc_channel_credentials* client_creds = grpc_ssl_credentials_create(
- test_root_cert, &signed_client_key_cert_pair, nullptr);
+ test_root_cert, &signed_client_key_cert_pair, nullptr, nullptr);
grpc_arg args[] = {
grpc_channel_arg_string_create(
diff --git a/test/core/handshake/BUILD b/test/core/handshake/BUILD
index a3276b9343..712cd59197 100644
--- a/test/core/handshake/BUILD
+++ b/test/core/handshake/BUILD
@@ -82,3 +82,21 @@ grpc_cc_test(
"//test/core/util:grpc_test_util",
],
)
+
+grpc_cc_test(
+ name = "handshake_verify_peer_options",
+ srcs = ["verify_peer_options.cc"],
+ language = "C++",
+ data = [
+ "//src/core/tsi/test_creds:ca.pem",
+ "//src/core/tsi/test_creds:server1.key",
+ "//src/core/tsi/test_creds:server1.pem",
+ ],
+ deps = [
+ "//:gpr",
+ "//:grpc",
+ "//test/core/util:gpr_test_util",
+ "//test/core/util:grpc_test_util",
+ ],
+)
+
diff --git a/test/core/handshake/client_ssl.cc b/test/core/handshake/client_ssl.cc
index 8ac763ac4b..467df6e229 100644
--- a/test/core/handshake/client_ssl.cc
+++ b/test/core/handshake/client_ssl.cc
@@ -251,8 +251,8 @@ static bool client_ssl_test(char* server_alpn_preferred) {
reinterpret_cast<const char*> GRPC_SLICE_START_PTR(key_slice);
pem_key_cert_pair.cert_chain =
reinterpret_cast<const char*> GRPC_SLICE_START_PTR(cert_slice);
- grpc_channel_credentials* ssl_creds =
- grpc_ssl_credentials_create(ca_cert, &pem_key_cert_pair, nullptr);
+ grpc_channel_credentials* ssl_creds = grpc_ssl_credentials_create(
+ ca_cert, &pem_key_cert_pair, nullptr, nullptr);
// Establish a channel pointing at the TLS server. Since the gRPC runtime is
// lazy, this won't necessarily establish a connection yet.
diff --git a/test/core/handshake/verify_peer_options.cc b/test/core/handshake/verify_peer_options.cc
new file mode 100644
index 0000000000..86c524b4a5
--- /dev/null
+++ b/test/core/handshake/verify_peer_options.cc
@@ -0,0 +1,275 @@
+/*
+ *
+ * Copyright 2018 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include "src/core/lib/iomgr/port.h"
+
+// This test won't work except with posix sockets enabled
+#ifdef GRPC_POSIX_SOCKET
+
+#include <arpa/inet.h>
+#include <openssl/err.h>
+#include <openssl/ssl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <unistd.h>
+
+#include <grpc/grpc.h>
+#include <grpc/grpc_security.h>
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/string_util.h>
+
+#include "src/core/lib/gprpp/thd.h"
+#include "src/core/lib/iomgr/load_file.h"
+#include "test/core/util/port.h"
+#include "test/core/util/test_config.h"
+
+#define SSL_CERT_PATH "src/core/tsi/test_creds/server1.pem"
+#define SSL_KEY_PATH "src/core/tsi/test_creds/server1.key"
+#define SSL_CA_PATH "src/core/tsi/test_creds/ca.pem"
+
+// Simple gRPC server. This listens until client_handshake_complete occurs.
+static gpr_event client_handshake_complete;
+
+static void server_thread(void* arg) {
+ const int port = *static_cast<int*>(arg);
+
+ // Load key pair and establish server SSL credentials.
+ grpc_ssl_pem_key_cert_pair pem_key_cert_pair;
+ grpc_slice ca_slice, cert_slice, key_slice;
+ GPR_ASSERT(GRPC_LOG_IF_ERROR("load_file",
+ grpc_load_file(SSL_CA_PATH, 1, &ca_slice)));
+ GPR_ASSERT(GRPC_LOG_IF_ERROR("load_file",
+ grpc_load_file(SSL_CERT_PATH, 1, &cert_slice)));
+ GPR_ASSERT(GRPC_LOG_IF_ERROR("load_file",
+ grpc_load_file(SSL_KEY_PATH, 1, &key_slice)));
+ const char* ca_cert =
+ reinterpret_cast<const char*> GRPC_SLICE_START_PTR(ca_slice);
+ pem_key_cert_pair.private_key =
+ reinterpret_cast<const char*> GRPC_SLICE_START_PTR(key_slice);
+ pem_key_cert_pair.cert_chain =
+ reinterpret_cast<const char*> GRPC_SLICE_START_PTR(cert_slice);
+ grpc_server_credentials* ssl_creds = grpc_ssl_server_credentials_create(
+ ca_cert, &pem_key_cert_pair, 1, 0, nullptr);
+
+ // Start server listening on local port.
+ char* addr;
+ gpr_asprintf(&addr, "127.0.0.1:%d", port);
+ grpc_server* server = grpc_server_create(nullptr, nullptr);
+ GPR_ASSERT(grpc_server_add_secure_http2_port(server, addr, ssl_creds));
+ free(addr);
+
+ grpc_completion_queue* cq = grpc_completion_queue_create_for_next(nullptr);
+
+ grpc_server_register_completion_queue(server, cq, nullptr);
+ grpc_server_start(server);
+
+ // Wait a bounded number of time until client_handshake_complete is set,
+ // sleeping between polls. The total time spent (deadline * retries)
+ // should be strictly greater than the client retry limit so that the
+ // client will always timeout first.
+ int retries = 60;
+ while (!gpr_event_get(&client_handshake_complete) && retries-- > 0) {
+ const gpr_timespec cq_deadline = grpc_timeout_seconds_to_deadline(1);
+ grpc_event ev = grpc_completion_queue_next(cq, cq_deadline, nullptr);
+ GPR_ASSERT(ev.type == GRPC_QUEUE_TIMEOUT);
+ }
+
+ gpr_log(GPR_INFO, "Shutting down server");
+ grpc_server_shutdown_and_notify(server, cq, nullptr);
+ grpc_server_cancel_all_calls(server);
+ grpc_completion_queue_shutdown(cq);
+
+ const gpr_timespec cq_deadline = grpc_timeout_seconds_to_deadline(60);
+ grpc_event ev = grpc_completion_queue_next(cq, cq_deadline, nullptr);
+ GPR_ASSERT(ev.type == GRPC_OP_COMPLETE);
+
+ grpc_server_destroy(server);
+ grpc_completion_queue_destroy(cq);
+ grpc_server_credentials_release(ssl_creds);
+ grpc_slice_unref(cert_slice);
+ grpc_slice_unref(key_slice);
+ grpc_slice_unref(ca_slice);
+}
+
+// This test launches a minimal TLS grpc server on a separate thread and then
+// establishes a TLS handshake via the core library to the server. The client
+// uses the supplied verify options.
+static bool verify_peer_options_test(verify_peer_options* verify_options) {
+ bool success = true;
+
+ grpc_init();
+ int port = grpc_pick_unused_port_or_die();
+ gpr_event_init(&client_handshake_complete);
+
+ // Launch the gRPC server thread.
+ bool ok;
+ grpc_core::Thread thd("grpc_client_ssl_test", server_thread, &port, &ok);
+ GPR_ASSERT(ok);
+ thd.Start();
+
+ // Load key pair and establish client SSL credentials.
+ grpc_ssl_pem_key_cert_pair pem_key_cert_pair;
+ grpc_slice ca_slice, cert_slice, key_slice;
+ GPR_ASSERT(GRPC_LOG_IF_ERROR("load_file",
+ grpc_load_file(SSL_CA_PATH, 1, &ca_slice)));
+ GPR_ASSERT(GRPC_LOG_IF_ERROR("load_file",
+ grpc_load_file(SSL_CERT_PATH, 1, &cert_slice)));
+ GPR_ASSERT(GRPC_LOG_IF_ERROR("load_file",
+ grpc_load_file(SSL_KEY_PATH, 1, &key_slice)));
+ const char* ca_cert =
+ reinterpret_cast<const char*> GRPC_SLICE_START_PTR(ca_slice);
+ pem_key_cert_pair.private_key =
+ reinterpret_cast<const char*> GRPC_SLICE_START_PTR(key_slice);
+ pem_key_cert_pair.cert_chain =
+ reinterpret_cast<const char*> GRPC_SLICE_START_PTR(cert_slice);
+ grpc_channel_credentials* ssl_creds = grpc_ssl_credentials_create(
+ ca_cert, &pem_key_cert_pair, verify_options, nullptr);
+
+ // Establish a channel pointing at the TLS server. Since the gRPC runtime is
+ // lazy, this won't necessarily establish a connection yet.
+ char* target;
+ gpr_asprintf(&target, "127.0.0.1:%d", port);
+ grpc_arg ssl_name_override = {
+ GRPC_ARG_STRING,
+ const_cast<char*>(GRPC_SSL_TARGET_NAME_OVERRIDE_ARG),
+ {const_cast<char*>("foo.test.google.fr")}};
+ grpc_channel_args grpc_args;
+ grpc_args.num_args = 1;
+ grpc_args.args = &ssl_name_override;
+ grpc_channel* channel =
+ grpc_secure_channel_create(ssl_creds, target, &grpc_args, nullptr);
+ GPR_ASSERT(channel);
+ gpr_free(target);
+
+ // Initially the channel will be idle, the
+ // grpc_channel_check_connectivity_state triggers an attempt to connect.
+ GPR_ASSERT(grpc_channel_check_connectivity_state(
+ channel, 1 /* try_to_connect */) == GRPC_CHANNEL_IDLE);
+
+ // Wait a bounded number of times for the channel to be ready. When the
+ // channel is ready, the initial TLS handshake will have successfully
+ // completed. The total time spent on the client side (retries * deadline)
+ // should be greater than the server side time limit.
+ int retries = 10;
+ grpc_connectivity_state state = GRPC_CHANNEL_IDLE;
+ grpc_completion_queue* cq = grpc_completion_queue_create_for_next(nullptr);
+
+ while (state != GRPC_CHANNEL_READY && retries-- > 0) {
+ grpc_channel_watch_connectivity_state(
+ channel, state, grpc_timeout_seconds_to_deadline(3), cq, nullptr);
+ gpr_timespec cq_deadline = grpc_timeout_seconds_to_deadline(5);
+ grpc_event ev = grpc_completion_queue_next(cq, cq_deadline, nullptr);
+ GPR_ASSERT(ev.type == GRPC_OP_COMPLETE);
+ state =
+ grpc_channel_check_connectivity_state(channel, 0 /* try_to_connect */);
+ }
+ grpc_completion_queue_destroy(cq);
+ if (retries < 0) {
+ success = false;
+ }
+
+ grpc_channel_destroy(channel);
+ grpc_channel_credentials_release(ssl_creds);
+ grpc_slice_unref(cert_slice);
+ grpc_slice_unref(key_slice);
+ grpc_slice_unref(ca_slice);
+
+ // Now that the client is completely cleaned up, trigger the server to
+ // shutdown
+ gpr_event_set(&client_handshake_complete, &client_handshake_complete);
+ // Wait for the server to completely shutdown
+ thd.Join();
+
+ grpc_shutdown();
+
+ return success;
+}
+
+static int callback_return_value = 0;
+static char callback_target_host[4096];
+static char callback_target_pem[4096];
+static void* callback_userdata = nullptr;
+static void* destruct_userdata = nullptr;
+
+static int verify_callback(const char* target_host, const char* target_pem,
+ void* userdata) {
+ if (target_host != nullptr) {
+ snprintf(callback_target_host, sizeof(callback_target_host), "%s",
+ target_host);
+ } else {
+ callback_target_host[0] = '\0';
+ }
+ if (target_pem != nullptr) {
+ snprintf(callback_target_pem, sizeof(callback_target_pem), "%s",
+ target_pem);
+ } else {
+ callback_target_pem[0] = '\0';
+ }
+ callback_userdata = userdata;
+ return callback_return_value;
+}
+
+static void verify_destruct(void* userdata) { destruct_userdata = userdata; }
+
+int main(int argc, char* argv[]) {
+ int userdata = 42;
+ verify_peer_options verify_options;
+
+ // Load the server's cert so that we can assert it gets passed to the callback
+ grpc_slice cert_slice;
+ GPR_ASSERT(GRPC_LOG_IF_ERROR("load_file",
+ grpc_load_file(SSL_CERT_PATH, 1, &cert_slice)));
+ const char* server_cert =
+ reinterpret_cast<const char*> GRPC_SLICE_START_PTR(cert_slice);
+
+ // Running with all-null values should have no effect
+ verify_options.verify_peer_callback = nullptr;
+ verify_options.verify_peer_callback_userdata = nullptr;
+ verify_options.verify_peer_destruct = nullptr;
+ GPR_ASSERT(verify_peer_options_test(&verify_options));
+ GPR_ASSERT(strlen(callback_target_host) == 0);
+ GPR_ASSERT(strlen(callback_target_pem) == 0);
+ GPR_ASSERT(callback_userdata == nullptr);
+ GPR_ASSERT(destruct_userdata == nullptr);
+
+ // Running with the callbacks and verify we get the expected values
+ verify_options.verify_peer_callback = verify_callback;
+ verify_options.verify_peer_callback_userdata = static_cast<void*>(&userdata);
+ verify_options.verify_peer_destruct = verify_destruct;
+ GPR_ASSERT(verify_peer_options_test(&verify_options));
+ GPR_ASSERT(strcmp(callback_target_host, "foo.test.google.fr") == 0);
+ GPR_ASSERT(strcmp(callback_target_pem, server_cert) == 0);
+ GPR_ASSERT(callback_userdata == static_cast<void*>(&userdata));
+ GPR_ASSERT(destruct_userdata == static_cast<void*>(&userdata));
+
+ // If the callback returns non-zero, initializing the channel should fail.
+ callback_return_value = 1;
+ GPR_ASSERT(!verify_peer_options_test(&verify_options));
+
+ grpc_slice_unref(cert_slice);
+
+ return 0;
+}
+
+#else /* GRPC_POSIX_SOCKET */
+
+int main(int argc, char** argv) { return 1; }
+
+#endif /* GRPC_POSIX_SOCKET */
diff --git a/test/core/surface/num_external_connectivity_watchers_test.cc b/test/core/surface/num_external_connectivity_watchers_test.cc
index 467deeeaec..7b7a0b6dfc 100644
--- a/test/core/surface/num_external_connectivity_watchers_test.cc
+++ b/test/core/surface/num_external_connectivity_watchers_test.cc
@@ -168,7 +168,7 @@ static const test_fixture insecure_test = {
static grpc_channel* secure_test_create_channel(const char* addr) {
grpc_channel_credentials* ssl_creds =
- grpc_ssl_credentials_create(test_root_cert, nullptr, nullptr);
+ grpc_ssl_credentials_create(test_root_cert, nullptr, nullptr, nullptr);
grpc_arg ssl_name_override = {
GRPC_ARG_STRING,
const_cast<char*>(GRPC_SSL_TARGET_NAME_OVERRIDE_ARG),
diff --git a/test/core/surface/sequential_connectivity_test.cc b/test/core/surface/sequential_connectivity_test.cc
index 9aba4c499e..10562b3be9 100644
--- a/test/core/surface/sequential_connectivity_test.cc
+++ b/test/core/surface/sequential_connectivity_test.cc
@@ -144,7 +144,7 @@ static void secure_test_add_port(grpc_server* server, const char* addr) {
static grpc_channel* secure_test_create_channel(const char* addr) {
grpc_channel_credentials* ssl_creds =
- grpc_ssl_credentials_create(test_root_cert, nullptr, nullptr);
+ grpc_ssl_credentials_create(test_root_cert, nullptr, nullptr, nullptr);
grpc_arg ssl_name_override = {
GRPC_ARG_STRING,
const_cast<char*>(GRPC_SSL_TARGET_NAME_OVERRIDE_ARG),
diff --git a/tools/run_tests/generated/sources_and_headers.json b/tools/run_tests/generated/sources_and_headers.json
index f17c1c75b6..66191656ff 100644
--- a/tools/run_tests/generated/sources_and_headers.json
+++ b/tools/run_tests/generated/sources_and_headers.json
@@ -1177,6 +1177,23 @@
{
"deps": [
"gpr",
+ "gpr_test_util",
+ "grpc",
+ "grpc_test_util"
+ ],
+ "headers": [],
+ "is_filegroup": false,
+ "language": "c",
+ "name": "handshake_verify_peer_options",
+ "src": [
+ "test/core/handshake/verify_peer_options.cc"
+ ],
+ "third_party": false,
+ "type": "target"
+ },
+ {
+ "deps": [
+ "gpr",
"grpc_test_util"
],
"headers": [],
diff --git a/tools/run_tests/generated/tests.json b/tools/run_tests/generated/tests.json
index ba63352036..498edbb35d 100644
--- a/tools/run_tests/generated/tests.json
+++ b/tools/run_tests/generated/tests.json
@@ -1451,6 +1451,26 @@
"args": [],
"benchmark": false,
"ci_platforms": [
+ "linux"
+ ],
+ "cpu_cost": 1.0,
+ "exclude_configs": [],
+ "exclude_iomgrs": [
+ "uv"
+ ],
+ "flaky": false,
+ "gtest": false,
+ "language": "c",
+ "name": "handshake_verify_peer_options",
+ "platforms": [
+ "linux"
+ ],
+ "uses_polling": true
+ },
+ {
+ "args": [],
+ "benchmark": false,
+ "ci_platforms": [
"linux",
"mac",
"posix",