Support Custom Post-handshake Verification in TlsCredentials (#25631)

* custom verification refactoring - post-handshake verification
This commit is contained in:
ZhenLian 2021-11-10 13:45:52 -08:00 committed by GitHub
parent 9be868488f
commit 2e14f6fa70
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
56 changed files with 5156 additions and 1488 deletions

9
BUILD
View File

@ -325,6 +325,7 @@ GRPCXX_PUBLIC_HDRS = [
"include/grpcpp/security/server_credentials.h",
"include/grpcpp/security/tls_certificate_provider.h",
"include/grpcpp/security/authorization_policy_provider.h",
"include/grpcpp/security/tls_certificate_verifier.h",
"include/grpcpp/security/tls_credentials_options.h",
"include/grpcpp/server.h",
"include/grpcpp/server_builder.h",
@ -465,7 +466,6 @@ grpc_cc_library(
hdrs = [
"src/cpp/client/secure_credentials.h",
"src/cpp/common/secure_auth_context.h",
"src/cpp/common/tls_credentials_options_util.h",
"src/cpp/server/secure_server_credentials.h",
],
language = "c++",
@ -505,18 +505,18 @@ grpc_cc_library(
"src/cpp/common/secure_channel_arguments.cc",
"src/cpp/common/secure_create_auth_context.cc",
"src/cpp/common/tls_certificate_provider.cc",
"src/cpp/common/tls_certificate_verifier.cc",
"src/cpp/common/tls_credentials_options.cc",
"src/cpp/common/tls_credentials_options_util.cc",
"src/cpp/server/insecure_server_credentials.cc",
"src/cpp/server/secure_server_credentials.cc",
],
hdrs = [
"src/cpp/client/secure_credentials.h",
"src/cpp/common/secure_auth_context.h",
"src/cpp/common/tls_credentials_options_util.h",
"src/cpp/server/secure_server_credentials.h",
],
external_deps = [
"absl/status",
"absl/synchronization",
"absl/container:inlined_vector",
"absl/strings",
@ -3199,6 +3199,7 @@ grpc_cc_library(
"src/core/lib/security/credentials/ssl/ssl_credentials.cc",
"src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.cc",
"src/core/lib/security/credentials/tls/grpc_tls_certificate_provider.cc",
"src/core/lib/security/credentials/tls/grpc_tls_certificate_verifier.cc",
"src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc",
"src/core/lib/security/credentials/tls/tls_credentials.cc",
"src/core/lib/security/credentials/tls/tls_utils.cc",
@ -3249,6 +3250,7 @@ grpc_cc_library(
"src/core/lib/security/credentials/ssl/ssl_credentials.h",
"src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.h",
"src/core/lib/security/credentials/tls/grpc_tls_certificate_provider.h",
"src/core/lib/security/credentials/tls/grpc_tls_certificate_verifier.h",
"src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h",
"src/core/lib/security/credentials/tls/tls_credentials.h",
"src/core/lib/security/credentials/tls/tls_utils.h",
@ -3271,6 +3273,7 @@ grpc_cc_library(
],
external_deps = [
"absl/container:inlined_vector",
"absl/functional:bind_front",
"absl/strings",
"absl/strings:str_format",
"absl/time",

1656
BUILD.gn generated Normal file

File diff suppressed because it is too large Load Diff

82
CMakeLists.txt generated
View File

@ -822,6 +822,7 @@ if(gRPC_BUILD_TESTS)
add_dependencies(buildtests_cxx grpc_cli)
add_dependencies(buildtests_cxx grpc_tls_certificate_distributor_test)
add_dependencies(buildtests_cxx grpc_tls_certificate_provider_test)
add_dependencies(buildtests_cxx grpc_tls_certificate_verifier_test)
add_dependencies(buildtests_cxx grpc_tls_credentials_options_test)
if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
add_dependencies(buildtests_cxx grpc_tool_test)
@ -952,6 +953,7 @@ if(gRPC_BUILD_TESTS)
endif()
add_dependencies(buildtests_cxx time_util_test)
add_dependencies(buildtests_cxx timer_test)
add_dependencies(buildtests_cxx tls_certificate_verifier_test)
add_dependencies(buildtests_cxx tls_security_connector_test)
add_dependencies(buildtests_cxx tls_test)
add_dependencies(buildtests_cxx too_many_pings_test)
@ -1969,6 +1971,7 @@ add_library(grpc
src/core/lib/security/credentials/ssl/ssl_credentials.cc
src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.cc
src/core/lib/security/credentials/tls/grpc_tls_certificate_provider.cc
src/core/lib/security/credentials/tls/grpc_tls_certificate_verifier.cc
src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc
src/core/lib/security/credentials/tls/tls_credentials.cc
src/core/lib/security/credentials/tls/tls_utils.cc
@ -2818,8 +2821,8 @@ add_library(grpc++
src/cpp/common/secure_channel_arguments.cc
src/cpp/common/secure_create_auth_context.cc
src/cpp/common/tls_certificate_provider.cc
src/cpp/common/tls_certificate_verifier.cc
src/cpp/common/tls_credentials_options.cc
src/cpp/common/tls_credentials_options_util.cc
src/cpp/common/validate_service_config.cc
src/cpp/common/version_cc.cc
src/cpp/server/async_generic_service.cc
@ -3045,6 +3048,7 @@ foreach(_hdr
include/grpcpp/security/credentials.h
include/grpcpp/security/server_credentials.h
include/grpcpp/security/tls_certificate_provider.h
include/grpcpp/security/tls_certificate_verifier.h
include/grpcpp/security/tls_credentials_options.h
include/grpcpp/server.h
include/grpcpp/server_builder.h
@ -3694,6 +3698,7 @@ foreach(_hdr
include/grpcpp/security/credentials.h
include/grpcpp/security/server_credentials.h
include/grpcpp/security/tls_certificate_provider.h
include/grpcpp/security/tls_certificate_verifier.h
include/grpcpp/security/tls_credentials_options.h
include/grpcpp/server.h
include/grpcpp/server_builder.h
@ -11515,6 +11520,41 @@ target_link_libraries(grpc_tls_certificate_provider_test
)
endif()
if(gRPC_BUILD_TESTS)
add_executable(grpc_tls_certificate_verifier_test
test/core/security/grpc_tls_certificate_verifier_test.cc
third_party/googletest/googletest/src/gtest-all.cc
third_party/googletest/googlemock/src/gmock-all.cc
)
target_include_directories(grpc_tls_certificate_verifier_test
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/include
${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
${_gRPC_RE2_INCLUDE_DIR}
${_gRPC_SSL_INCLUDE_DIR}
${_gRPC_UPB_GENERATED_DIR}
${_gRPC_UPB_GRPC_GENERATED_DIR}
${_gRPC_UPB_INCLUDE_DIR}
${_gRPC_XXHASH_INCLUDE_DIR}
${_gRPC_ZLIB_INCLUDE_DIR}
third_party/googletest/googletest/include
third_party/googletest/googletest
third_party/googletest/googlemock/include
third_party/googletest/googlemock
${_gRPC_PROTO_GENS_DIR}
)
target_link_libraries(grpc_tls_certificate_verifier_test
${_gRPC_PROTOBUF_LIBRARIES}
${_gRPC_ALLTARGETS_LIBRARIES}
grpc_test_util
)
endif()
if(gRPC_BUILD_TESTS)
@ -15668,6 +15708,7 @@ if(gRPC_BUILD_TESTS)
add_executable(test_cpp_client_credentials_test
test/cpp/client/credentials_test.cc
test/cpp/util/tls_test_utils.cc
third_party/googletest/googletest/src/gtest-all.cc
third_party/googletest/googlemock/src/gmock-all.cc
)
@ -15704,6 +15745,7 @@ if(gRPC_BUILD_TESTS)
add_executable(test_cpp_server_credentials_test
test/cpp/server/credentials_test.cc
test/cpp/util/tls_test_utils.cc
third_party/googletest/googletest/src/gtest-all.cc
third_party/googletest/googlemock/src/gmock-all.cc
)
@ -16040,6 +16082,43 @@ target_link_libraries(timer_test
)
endif()
if(gRPC_BUILD_TESTS)
add_executable(tls_certificate_verifier_test
test/cpp/security/tls_certificate_verifier_test.cc
test/cpp/util/tls_test_utils.cc
third_party/googletest/googletest/src/gtest-all.cc
third_party/googletest/googlemock/src/gmock-all.cc
)
target_include_directories(tls_certificate_verifier_test
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/include
${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
${_gRPC_RE2_INCLUDE_DIR}
${_gRPC_SSL_INCLUDE_DIR}
${_gRPC_UPB_GENERATED_DIR}
${_gRPC_UPB_GRPC_GENERATED_DIR}
${_gRPC_UPB_INCLUDE_DIR}
${_gRPC_XXHASH_INCLUDE_DIR}
${_gRPC_ZLIB_INCLUDE_DIR}
third_party/googletest/googletest/include
third_party/googletest/googletest
third_party/googletest/googlemock/include
third_party/googletest/googlemock
${_gRPC_PROTO_GENS_DIR}
)
target_link_libraries(tls_certificate_verifier_test
${_gRPC_PROTOBUF_LIBRARIES}
${_gRPC_ALLTARGETS_LIBRARIES}
grpc++
grpc_test_util
)
endif()
if(gRPC_BUILD_TESTS)
@ -17045,6 +17124,7 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
test/cpp/end2end/test_service_impl.cc
test/cpp/end2end/xds/xds_end2end_test.cc
test/cpp/end2end/xds/xds_server.cc
test/cpp/util/tls_test_utils.cc
third_party/googletest/googletest/src/gtest-all.cc
third_party/googletest/googlemock/src/gmock-all.cc
)

2
Makefile generated
View File

@ -1521,6 +1521,7 @@ LIBGRPC_SRC = \
src/core/lib/security/credentials/ssl/ssl_credentials.cc \
src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.cc \
src/core/lib/security/credentials/tls/grpc_tls_certificate_provider.cc \
src/core/lib/security/credentials/tls/grpc_tls_certificate_verifier.cc \
src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc \
src/core/lib/security/credentials/tls/tls_credentials.cc \
src/core/lib/security/credentials/tls/tls_utils.cc \
@ -2947,6 +2948,7 @@ src/core/lib/security/credentials/plugin/plugin_credentials.cc: $(OPENSSL_DEP)
src/core/lib/security/credentials/ssl/ssl_credentials.cc: $(OPENSSL_DEP)
src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.cc: $(OPENSSL_DEP)
src/core/lib/security/credentials/tls/grpc_tls_certificate_provider.cc: $(OPENSSL_DEP)
src/core/lib/security/credentials/tls/grpc_tls_certificate_verifier.cc: $(OPENSSL_DEP)
src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc: $(OPENSSL_DEP)
src/core/lib/security/credentials/tls/tls_credentials.cc: $(OPENSSL_DEP)
src/core/lib/security/credentials/tls/tls_utils.cc: $(OPENSSL_DEP)

View File

@ -872,6 +872,7 @@ libs:
- src/core/lib/security/credentials/ssl/ssl_credentials.h
- src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.h
- src/core/lib/security/credentials/tls/grpc_tls_certificate_provider.h
- src/core/lib/security/credentials/tls/grpc_tls_certificate_verifier.h
- src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h
- src/core/lib/security/credentials/tls/tls_credentials.h
- src/core/lib/security/credentials/tls/tls_utils.h
@ -1436,6 +1437,7 @@ libs:
- src/core/lib/security/credentials/ssl/ssl_credentials.cc
- src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.cc
- src/core/lib/security/credentials/tls/grpc_tls_certificate_provider.cc
- src/core/lib/security/credentials/tls/grpc_tls_certificate_verifier.cc
- src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc
- src/core/lib/security/credentials/tls/tls_credentials.cc
- src/core/lib/security/credentials/tls/tls_utils.cc
@ -2418,6 +2420,7 @@ libs:
- include/grpcpp/security/credentials.h
- include/grpcpp/security/server_credentials.h
- include/grpcpp/security/tls_certificate_provider.h
- include/grpcpp/security/tls_certificate_verifier.h
- include/grpcpp/security/tls_credentials_options.h
- include/grpcpp/server.h
- include/grpcpp/server_builder.h
@ -2471,7 +2474,6 @@ libs:
- src/cpp/client/secure_credentials.h
- src/cpp/common/channel_filter.h
- src/cpp/common/secure_auth_context.h
- src/cpp/common/tls_credentials_options_util.h
- src/cpp/server/dynamic_thread_pool.h
- src/cpp/server/external_connection_acceptor_impl.h
- src/cpp/server/health/default_health_check_service.h
@ -2521,8 +2523,8 @@ libs:
- src/cpp/common/secure_channel_arguments.cc
- src/cpp/common/secure_create_auth_context.cc
- src/cpp/common/tls_certificate_provider.cc
- src/cpp/common/tls_certificate_verifier.cc
- src/cpp/common/tls_credentials_options.cc
- src/cpp/common/tls_credentials_options_util.cc
- src/cpp/common/validate_service_config.cc
- src/cpp/common/version_cc.cc
- src/cpp/server/async_generic_service.cc
@ -2802,6 +2804,7 @@ libs:
- include/grpcpp/security/credentials.h
- include/grpcpp/security/server_credentials.h
- include/grpcpp/security/tls_certificate_provider.h
- include/grpcpp/security/tls_certificate_verifier.h
- include/grpcpp/security/tls_credentials_options.h
- include/grpcpp/server.h
- include/grpcpp/server_builder.h
@ -6164,6 +6167,15 @@ targets:
- test/core/security/grpc_tls_certificate_provider_test.cc
deps:
- grpc_test_util
- name: grpc_tls_certificate_verifier_test
gtest: true
build: test
language: c++
headers: []
src:
- test/core/security/grpc_tls_certificate_verifier_test.cc
deps:
- grpc_test_util
- name: grpc_tls_credentials_options_test
gtest: true
build: test
@ -7925,9 +7937,11 @@ targets:
gtest: true
build: test
language: c++
headers: []
headers:
- test/cpp/util/tls_test_utils.h
src:
- test/cpp/client/credentials_test.cc
- test/cpp/util/tls_test_utils.cc
deps:
- grpc++
- grpc_test_util
@ -7935,9 +7949,11 @@ targets:
gtest: true
build: test
language: c++
headers: []
headers:
- test/cpp/util/tls_test_utils.h
src:
- test/cpp/server/credentials_test.cc
- test/cpp/util/tls_test_utils.cc
deps:
- grpc++
- grpc_test_util
@ -8040,6 +8056,18 @@ targets:
deps:
- grpc++
- grpc_test_util
- name: tls_certificate_verifier_test
gtest: true
build: test
language: c++
headers:
- test/cpp/util/tls_test_utils.h
src:
- test/cpp/security/tls_certificate_verifier_test.cc
- test/cpp/util/tls_test_utils.cc
deps:
- grpc++
- grpc_test_util
- name: tls_security_connector_test
gtest: true
build: test
@ -8564,6 +8592,7 @@ targets:
- test/cpp/end2end/counted_service.h
- test/cpp/end2end/test_service_impl.h
- test/cpp/end2end/xds/xds_server.h
- test/cpp/util/tls_test_utils.h
src:
- src/proto/grpc/testing/duplicate/echo_duplicate.proto
- src/proto/grpc/testing/echo.proto
@ -8603,6 +8632,7 @@ targets:
- test/cpp/end2end/test_service_impl.cc
- test/cpp/end2end/xds/xds_end2end_test.cc
- test/cpp/end2end/xds/xds_server.cc
- test/cpp/util/tls_test_utils.cc
deps:
- grpc++_test_config
- grpc++_test_util

1
config.m4 generated
View File

@ -574,6 +574,7 @@ if test "$PHP_GRPC" != "no"; then
src/core/lib/security/credentials/ssl/ssl_credentials.cc \
src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.cc \
src/core/lib/security/credentials/tls/grpc_tls_certificate_provider.cc \
src/core/lib/security/credentials/tls/grpc_tls_certificate_verifier.cc \
src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc \
src/core/lib/security/credentials/tls/tls_credentials.cc \
src/core/lib/security/credentials/tls/tls_utils.cc \

1
config.w32 generated
View File

@ -540,6 +540,7 @@ if (PHP_GRPC != "no") {
"src\\core\\lib\\security\\credentials\\ssl\\ssl_credentials.cc " +
"src\\core\\lib\\security\\credentials\\tls\\grpc_tls_certificate_distributor.cc " +
"src\\core\\lib\\security\\credentials\\tls\\grpc_tls_certificate_provider.cc " +
"src\\core\\lib\\security\\credentials\\tls\\grpc_tls_certificate_verifier.cc " +
"src\\core\\lib\\security\\credentials\\tls\\grpc_tls_credentials_options.cc " +
"src\\core\\lib\\security\\credentials\\tls\\tls_credentials.cc " +
"src\\core\\lib\\security\\credentials\\tls\\tls_utils.cc " +

7
gRPC-C++.podspec generated
View File

@ -159,6 +159,7 @@ Pod::Spec.new do |s|
'include/grpcpp/security/credentials.h',
'include/grpcpp/security/server_credentials.h',
'include/grpcpp/security/tls_certificate_provider.h',
'include/grpcpp/security/tls_certificate_verifier.h',
'include/grpcpp/security/tls_credentials_options.h',
'include/grpcpp/server.h',
'include/grpcpp/server_builder.h',
@ -731,6 +732,7 @@ Pod::Spec.new do |s|
'src/core/lib/security/credentials/ssl/ssl_credentials.h',
'src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.h',
'src/core/lib/security/credentials/tls/grpc_tls_certificate_provider.h',
'src/core/lib/security/credentials/tls/grpc_tls_certificate_verifier.h',
'src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h',
'src/core/lib/security/credentials/tls/tls_credentials.h',
'src/core/lib/security/credentials/tls/tls_utils.h',
@ -845,9 +847,8 @@ Pod::Spec.new do |s|
'src/cpp/common/secure_channel_arguments.cc',
'src/cpp/common/secure_create_auth_context.cc',
'src/cpp/common/tls_certificate_provider.cc',
'src/cpp/common/tls_certificate_verifier.cc',
'src/cpp/common/tls_credentials_options.cc',
'src/cpp/common/tls_credentials_options_util.cc',
'src/cpp/common/tls_credentials_options_util.h',
'src/cpp/common/validate_service_config.cc',
'src/cpp/common/version_cc.cc',
'src/cpp/server/async_generic_service.cc',
@ -1424,6 +1425,7 @@ Pod::Spec.new do |s|
'src/core/lib/security/credentials/ssl/ssl_credentials.h',
'src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.h',
'src/core/lib/security/credentials/tls/grpc_tls_certificate_provider.h',
'src/core/lib/security/credentials/tls/grpc_tls_certificate_verifier.h',
'src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h',
'src/core/lib/security/credentials/tls/tls_credentials.h',
'src/core/lib/security/credentials/tls/tls_utils.h',
@ -1514,7 +1516,6 @@ Pod::Spec.new do |s|
'src/cpp/client/secure_credentials.h',
'src/cpp/common/channel_filter.h',
'src/cpp/common/secure_auth_context.h',
'src/cpp/common/tls_credentials_options_util.h',
'src/cpp/server/dynamic_thread_pool.h',
'src/cpp/server/external_connection_acceptor_impl.h',
'src/cpp/server/health/default_health_check_service.h',

3
gRPC-Core.podspec generated
View File

@ -1204,6 +1204,8 @@ Pod::Spec.new do |s|
'src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.h',
'src/core/lib/security/credentials/tls/grpc_tls_certificate_provider.cc',
'src/core/lib/security/credentials/tls/grpc_tls_certificate_provider.h',
'src/core/lib/security/credentials/tls/grpc_tls_certificate_verifier.cc',
'src/core/lib/security/credentials/tls/grpc_tls_certificate_verifier.h',
'src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc',
'src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h',
'src/core/lib/security/credentials/tls/tls_credentials.cc',
@ -1941,6 +1943,7 @@ Pod::Spec.new do |s|
'src/core/lib/security/credentials/ssl/ssl_credentials.h',
'src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.h',
'src/core/lib/security/credentials/tls/grpc_tls_certificate_provider.h',
'src/core/lib/security/credentials/tls/grpc_tls_certificate_verifier.h',
'src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h',
'src/core/lib/security/credentials/tls/tls_credentials.h',
'src/core/lib/security/credentials/tls/tls_utils.h',

8
grpc.def generated
View File

@ -149,16 +149,14 @@ EXPORTS
grpc_tls_certificate_provider_file_watcher_create
grpc_tls_certificate_provider_release
grpc_tls_credentials_options_create
grpc_tls_credentials_options_set_cert_request_type
grpc_tls_credentials_options_set_server_verification_option
grpc_tls_credentials_options_set_certificate_provider
grpc_tls_credentials_options_watch_root_certs
grpc_tls_credentials_options_set_root_cert_name
grpc_tls_credentials_options_watch_identity_key_cert_pairs
grpc_tls_credentials_options_set_identity_cert_name
grpc_tls_credentials_options_set_server_authorization_check_config
grpc_tls_server_authorization_check_config_create
grpc_tls_server_authorization_check_config_release
grpc_tls_credentials_options_set_cert_request_type
grpc_tls_credentials_options_set_verify_server_cert
grpc_tls_credentials_options_set_check_call_host
grpc_xds_credentials_create
grpc_xds_server_credentials_create
grpc_authorization_policy_provider_static_data_create

2
grpc.gemspec generated
View File

@ -1124,6 +1124,8 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.h )
s.files += %w( src/core/lib/security/credentials/tls/grpc_tls_certificate_provider.cc )
s.files += %w( src/core/lib/security/credentials/tls/grpc_tls_certificate_provider.h )
s.files += %w( src/core/lib/security/credentials/tls/grpc_tls_certificate_verifier.cc )
s.files += %w( src/core/lib/security/credentials/tls/grpc_tls_certificate_verifier.h )
s.files += %w( src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc )
s.files += %w( src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h )
s.files += %w( src/core/lib/security/credentials/tls/tls_credentials.cc )

3
grpc.gyp generated
View File

@ -962,6 +962,7 @@
'src/core/lib/security/credentials/ssl/ssl_credentials.cc',
'src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.cc',
'src/core/lib/security/credentials/tls/grpc_tls_certificate_provider.cc',
'src/core/lib/security/credentials/tls/grpc_tls_certificate_verifier.cc',
'src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc',
'src/core/lib/security/credentials/tls/tls_credentials.cc',
'src/core/lib/security/credentials/tls/tls_utils.cc',
@ -1501,8 +1502,8 @@
'src/cpp/common/secure_channel_arguments.cc',
'src/cpp/common/secure_create_auth_context.cc',
'src/cpp/common/tls_certificate_provider.cc',
'src/cpp/common/tls_certificate_verifier.cc',
'src/cpp/common/tls_credentials_options.cc',
'src/cpp/common/tls_credentials_options_util.cc',
'src/cpp/common/validate_service_config.cc',
'src/cpp/common/version_cc.cc',
'src/cpp/server/async_generic_service.cc',

View File

@ -747,61 +747,62 @@ GRPCAPI grpc_server_credentials* grpc_local_server_credentials_create(
/** --- TLS channel/server credentials ---
* It is used for experimental purpose for now and subject to change. */
/** Struct for indicating errors. It is used for
* experimental purpose for now and subject to change. */
typedef struct grpc_tls_error_details grpc_tls_error_details;
/** Config for TLS server authorization check. It is used for
* experimental purpose for now and subject to change. */
typedef struct grpc_tls_server_authorization_check_config
grpc_tls_server_authorization_check_config;
/**
* EXPERIMENTAL API - Subject to change
*
* A struct that can be specified by callers to configure underlying TLS
* behaviors. It is used for experimental purpose for now and subject to change.
* behaviors.
*/
typedef struct grpc_tls_credentials_options grpc_tls_credentials_options;
/**
* EXPERIMENTAL API - Subject to change
*
* A struct provides ways to gain credential data that will be used in the TLS
* handshake. It is used for experimental purpose for now and subject to change.
* handshake.
*/
typedef struct grpc_tls_certificate_provider grpc_tls_certificate_provider;
/**
* EXPERIMENTAL API - Subject to change
*
* A struct that stores the credential data presented to the peer in handshake
* to show local identity. It is used for experimental purpose for now and
* subject to change.
* to show local identity.
*/
typedef struct grpc_tls_identity_pairs grpc_tls_identity_pairs;
/**
* EXPERIMENTAL API - Subject to change
*
* Creates a grpc_tls_identity_pairs that stores a list of identity credential
* data, including identity private key and identity certificate chain. It is
* used for experimental purpose for now and subject to change.
* data, including identity private key and identity certificate chain.
*/
GRPCAPI grpc_tls_identity_pairs* grpc_tls_identity_pairs_create();
/**
* EXPERIMENTAL API - Subject to change
*
* Adds a identity private key and a identity certificate chain to
* grpc_tls_identity_pairs. This function will make an internal copy of
* |private_key| and |cert_chain|. It is used for experimental purpose for now
* and subject to change.
* |private_key| and |cert_chain|.
*/
GRPCAPI void grpc_tls_identity_pairs_add_pair(grpc_tls_identity_pairs* pairs,
const char* private_key,
const char* cert_chain);
/**
* EXPERIMENTAL API - Subject to change
*
* Destroys a grpc_tls_identity_pairs object. If this object is passed to a
* provider initiation function, the ownership is transferred so this function
* doesn't need to be called. Otherwise the creator of the
* grpc_tls_identity_pairs object is responsible for its destruction. It is
* used for experimental purpose for now and subject to change.
* grpc_tls_identity_pairs object is responsible for its destruction.
*/
GRPCAPI void grpc_tls_identity_pairs_destroy(grpc_tls_identity_pairs* pairs);
/**
* EXPERIMENTAL API - Subject to change
*
* Creates a grpc_tls_certificate_provider that will load credential data from
* static string during initialization. This provider will always return the
* same cert data for all cert names.
@ -809,13 +810,14 @@ GRPCAPI void grpc_tls_identity_pairs_destroy(grpc_tls_identity_pairs* pairs);
* corresponding credential data is not needed.
* This function will make a copy of |root_certificate|.
* The ownership of |pem_key_cert_pairs| is transferred.
* It is used for experimental purpose for now and subject to change.
*/
GRPCAPI grpc_tls_certificate_provider*
grpc_tls_certificate_provider_static_data_create(
const char* root_certificate, grpc_tls_identity_pairs* pem_key_cert_pairs);
/**
* EXPERIMENTAL API - Subject to change
*
* Creates a grpc_tls_certificate_provider that will watch the credential
* changes on the file system. This provider will always return the up-to-date
* cert data for all the cert names callers set through
@ -833,7 +835,6 @@ grpc_tls_certificate_provider_static_data_create(
* - refresh_interval_sec is the refreshing interval that we will check the
* files for updates.
* It does not take ownership of parameters.
* It is used for experimental purpose for now and subject to change.
*/
GRPCAPI grpc_tls_certificate_provider*
grpc_tls_certificate_provider_file_watcher_create(
@ -841,49 +842,34 @@ grpc_tls_certificate_provider_file_watcher_create(
const char* root_cert_path, unsigned int refresh_interval_sec);
/**
* EXPERIMENTAL API - Subject to change
*
* Releases a grpc_tls_certificate_provider object. The creator of the
* grpc_tls_certificate_provider object is responsible for its release. It is
* used for experimental purpose for now and subject to change.
* grpc_tls_certificate_provider object is responsible for its release.
*/
GRPCAPI void grpc_tls_certificate_provider_release(
grpc_tls_certificate_provider* provider);
/**
* EXPERIMENTAL API - Subject to change
*
* Creates an grpc_tls_credentials_options.
* It is used for experimental purpose for now and subject to change.
*/
GRPCAPI grpc_tls_credentials_options* grpc_tls_credentials_options_create(void);
/**
* Sets the options of whether to request and verify client certs. This should
* be called only on the server side. It is used for experimental purpose for
* now and subject to change.
*/
GRPCAPI void grpc_tls_credentials_options_set_cert_request_type(
grpc_tls_credentials_options* options,
grpc_ssl_client_certificate_request_type type);
/**
* Sets the options of whether to choose certain checks, e.g. certificate check,
* hostname check, etc. This should be called only on the client side. If
* |server_verification_option| is not GRPC_TLS_SERVER_VERIFICATION, use of a
* custom authorization check (grpc_tls_server_authorization_check_config) is
* mandatory. It is used for experimental purpose for now and subject to change.
*/
GRPCAPI void grpc_tls_credentials_options_set_server_verification_option(
grpc_tls_credentials_options* options,
grpc_tls_server_verification_option server_verification_option);
/**
* EXPERIMENTAL API - Subject to change
*
* Sets the credential provider in the options.
* The |options| will implicitly take a new ref to the |provider|.
* It is used for experimental purpose for now and subject to change.
*/
GRPCAPI void grpc_tls_credentials_options_set_certificate_provider(
grpc_tls_credentials_options* options,
grpc_tls_certificate_provider* provider);
/**
* EXPERIMENTAL API - Subject to change
*
* If set, gRPC stack will keep watching the root certificates with
* name |root_cert_name|.
* If this is not set on the client side, we will use the root certificates
@ -892,151 +878,296 @@ GRPCAPI void grpc_tls_credentials_options_set_certificate_provider(
* If this is not set on the server side, we will not watch any root certificate
* updates, and assume no root certificates needed for the server(single-side
* TLS). Default root certs on the server side is not supported.
* It is used for experimental purpose for now and subject to change.
*/
GRPCAPI void grpc_tls_credentials_options_watch_root_certs(
grpc_tls_credentials_options* options);
/**
* EXPERIMENTAL API - Subject to change
*
* Sets the name of the root certificates being watched.
* If not set, We will use a default empty string as the root certificate name.
* It is used for experimental purpose for now and subject to change.
*/
GRPCAPI void grpc_tls_credentials_options_set_root_cert_name(
grpc_tls_credentials_options* options, const char* root_cert_name);
/**
* EXPERIMENTAL API - Subject to change
*
* If set, gRPC stack will keep watching the identity key-cert pairs
* with name |identity_cert_name|.
* This is required on the server side, and optional on the client side.
* It is used for experimental purpose for now and subject to change.
*/
GRPCAPI void grpc_tls_credentials_options_watch_identity_key_cert_pairs(
grpc_tls_credentials_options* options);
/**
* EXPERIMENTAL API - Subject to change
*
* Sets the name of the identity certificates being watched.
* If not set, We will use a default empty string as the identity certificate
* name. It is used for experimental purpose for now and subject to change.
* name.
*/
GRPCAPI void grpc_tls_credentials_options_set_identity_cert_name(
grpc_tls_credentials_options* options, const char* identity_cert_name);
/**
* Sets the configuration for a custom authorization check performed at the end
* of the handshake. The |options| will implicitly take a new ref to the
* |config|.
* It is used for experimental purpose for now and subject to change.
* EXPERIMENTAL API - Subject to change
*
* Sets the options of whether to request and/or verify client certs. This shall
* only be called on the server side.
*/
GRPCAPI void grpc_tls_credentials_options_set_server_authorization_check_config(
GRPCAPI void grpc_tls_credentials_options_set_cert_request_type(
grpc_tls_credentials_options* options,
grpc_tls_server_authorization_check_config* config);
/** --- TLS server authorization check config. ---
* It is used for experimental purpose for now and subject to change. */
typedef struct grpc_tls_server_authorization_check_arg
grpc_tls_server_authorization_check_arg;
/** callback function provided by gRPC used to handle the result of server
authorization check. It is used when schedule API is implemented
asynchronously, and serves to bring the control back to gRPC C core. It is
used for experimental purpose for now and subject to change. */
typedef void (*grpc_tls_on_server_authorization_check_done_cb)(
grpc_tls_server_authorization_check_arg* arg);
/** A struct containing all information necessary to schedule/cancel a server
authorization check request.
- cb and cb_user_data represent a gRPC-provided callback and an argument
passed to it.
- success will store the result of server authorization check. That is,
if success returns a non-zero value, it means the authorization check
passes and if returning zero, it means the check fails.
- target_name is the name of an endpoint the channel is connecting to.
- peer_cert represents a complete certificate chain including both
signing and leaf certificates.
- \a subject_alternative_names is an array of size
\a subject_alternative_names_size consisting of pointers to strings.
- status and error_details contain information
about errors occurred when a server authorization check request is
scheduled/cancelled.
- config is a pointer to the unique
grpc_tls_server_authorization_check_config instance that this argument
corresponds to.
- context is a pointer to a wrapped language implementation of this
grpc_tls_server_authorization_check_arg instance.
- destroy_context is a pointer to a caller-provided method that cleans
up any data associated with the context pointer.
It is used for experimental purpose for now and subject to change.
*/
struct grpc_tls_server_authorization_check_arg {
grpc_tls_on_server_authorization_check_done_cb cb;
void* cb_user_data;
int success;
const char* target_name;
const char* peer_cert;
const char* peer_cert_full_chain;
char** subject_alternative_names;
size_t subject_alternative_names_size;
grpc_status_code status;
grpc_tls_error_details* error_details;
grpc_tls_server_authorization_check_config* config;
void* context;
void (*destroy_context)(void* ctx);
};
/** Create a grpc_tls_server_authorization_check_config instance.
- config_user_data is config-specific, read-only user data
that works for all channels created with a credential using the config.
- schedule is a pointer to an application-provided callback used to invoke
server authorization check API. The implementation of this method has to
be non-blocking, but can be performed synchronously or asynchronously.
1)If processing occurs synchronously, it populates arg->result,
arg->status, and arg->error_details and returns zero.
2) If processing occurs asynchronously, it returns a non-zero value. The
application then invokes arg->cb when processing is completed. Note that
arg->cb cannot be invoked before schedule API returns.
- cancel is a pointer to an application-provided callback used to cancel a
server authorization check request scheduled via an asynchronous schedule
API. arg is used to pinpoint an exact check request to be cancelled. The
operation may not have any effect if the request has already been
processed.
- destruct is a pointer to an application-provided callback used to clean up
any data associated with the config.
It is used for experimental purpose for now and subject to change.
*/
GRPCAPI grpc_tls_server_authorization_check_config*
grpc_tls_server_authorization_check_config_create(
const void* config_user_data,
int (*schedule)(void* config_user_data,
grpc_tls_server_authorization_check_arg* arg),
void (*cancel)(void* config_user_data,
grpc_tls_server_authorization_check_arg* arg),
void (*destruct)(void* config_user_data));
grpc_ssl_client_certificate_request_type type);
/**
* Releases a grpc_tls_server_authorization_check_config object. The creator of
* the grpc_tls_server_authorization_check_config object is responsible for its
* release. It is used for experimental purpose for now and subject to change.
* EXPERIMENTAL API - Subject to change
*
* Sets the options of whether to verify server certs on the client side.
* Passing in a non-zero value indicates verifying the certs.
*/
GRPCAPI void grpc_tls_server_authorization_check_config_release(
grpc_tls_server_authorization_check_config* config);
GRPCAPI void grpc_tls_credentials_options_set_verify_server_cert(
grpc_tls_credentials_options* options, int verify_server_cert);
/**
* EXPERIMENTAL API - Subject to change
*
* The read-only request information exposed in a verification call.
* Callers should not directly manage the ownership of it. We will make sure it
* is always available inside verify() or cancel() call, and will destroy the
* object at the end of custom verification.
*/
typedef struct grpc_tls_custom_verification_check_request {
/* The target name of the server when the client initiates the connection. */
/* This field will be nullptr if on the server side. */
const char* target_name;
/* The information contained in the certificate chain sent from the peer. */
struct peer_info {
/* The Common Name field on the peer leaf certificate. */
const char* common_name;
/* The list of Subject Alternative Names on the peer leaf certificate. */
struct san_names {
char** uri_names;
size_t uri_names_size;
char** dns_names;
size_t dns_names_size;
char** email_names;
size_t email_names_size;
char** ip_names;
size_t ip_names_size;
} san_names;
/* The raw peer leaf certificate. */
const char* peer_cert;
/* The raw peer certificate chain. Note that it is not always guaranteed to
* get the peer full chain. For more, please refer to
* GRPC_X509_PEM_CERT_CHAIN_PROPERTY_NAME defined in file
* grpc_security_constants.h.
* TODO(ZhenLian): Consider fixing this in the future. */
const char* peer_cert_full_chain;
} peer_info;
} grpc_tls_custom_verification_check_request;
/**
* EXPERIMENTAL API - Subject to change
*
* A callback function provided by gRPC as a parameter of the |verify| function
* in grpc_tls_certificate_verifier_external. If |verify| is expected to be run
* asynchronously, the implementer of |verify| will need to invoke this callback
* with |callback_arg| and proper verification status at the end to bring the
* control back to gRPC C core.
*/
typedef void (*grpc_tls_on_custom_verification_check_done_cb)(
grpc_tls_custom_verification_check_request* request, void* callback_arg,
grpc_status_code status, const char* error_details);
/**
* EXPERIMENTAL API - Subject to change
*
* The internal verifier type that will be used inside core.
*/
typedef struct grpc_tls_certificate_verifier grpc_tls_certificate_verifier;
/**
* EXPERIMENTAL API - Subject to change
*
* A struct containing all the necessary functions a custom external verifier
* needs to implement to be able to be converted to an internal verifier.
*/
typedef struct grpc_tls_certificate_verifier_external {
void* user_data;
/**
* A function pointer containing the verification logic that will be
* performed after the TLS handshake is done. It could be processed
* synchronously or asynchronously.
* - If expected to be processed synchronously, the implementer should
* populate the verification result through |sync_status| and
* |sync_error_details|, and then return true.
* - If expected to be processed asynchronously, the implementer should return
* false immediately, and then in the asynchronous thread invoke |callback|
* with the verification result. The implementer MUST NOT invoke the async
* |callback| in the same thread before |verify| returns, otherwise it can
* lead to deadlocks.
*
* user_data: any argument that is passed in the user_data of
* grpc_tls_certificate_verifier_external during construction time
* can be retrieved later here.
* request: request information exposed to the function implementer.
* callback: the callback that the function implementer needs to invoke, if
* return a non-zero value. It is usually invoked when the
* asynchronous verification is done, and serves to bring the
* control back to gRPC.
* callback_arg: A pointer to the internal ExternalVerifier instance. This is
* mainly used as an argument in |callback|, if want to invoke
* |callback| in async mode.
* sync_status: indicates if a connection should be allowed. This should only
* be used if the verification check is done synchronously.
* sync_error_details: the error generated while verifying a connection. This
* should only be used if the verification check is done
* synchronously. the implementation must allocate the
* error string via gpr_malloc() or gpr_strdup().
* return: return 0 if |verify| is expected to be executed asynchronously,
* otherwise return a non-zero value.
*/
int (*verify)(void* user_data,
grpc_tls_custom_verification_check_request* request,
grpc_tls_on_custom_verification_check_done_cb callback,
void* callback_arg, grpc_status_code* sync_status,
char** sync_error_details);
/**
* A function pointer that cleans up the caller-specified resources when the
* verifier is still running but the whole connection got cancelled. This
* could happen when the verifier is doing some async operations, and the
* whole handshaker object got destroyed because of connection time limit is
* reached, or any other reasons. In such cases, function implementers might
* want to be notified, and properly clean up some resources.
*
* user_data: any argument that is passed in the user_data of
* grpc_tls_certificate_verifier_external during construction time
* can be retrieved later here.
* request: request information exposed to the function implementer. It will
* be the same request object that was passed to verify(), and it
* tells the cancel() which request to cancel.
*/
void (*cancel)(void* user_data,
grpc_tls_custom_verification_check_request* request);
/**
* A function pointer that does some additional destruction work when the
* verifier is destroyed. This is used when the caller wants to associate some
* objects to the lifetime of external_verifier, and destroy them when
* external_verifier got destructed. For example, in C++, the class containing
* user-specified callback functions should not be destroyed before
* external_verifier, since external_verifier will invoke them while being
* used.
* Note that the caller MUST delete the grpc_tls_certificate_verifier_external
* object itself in this function, otherwise it will cause memory leaks. That
* also means the user_data has to carries at least a self pointer, for the
* callers to later delete it in destruct().
*
* user_data: any argument that is passed in the user_data of
* grpc_tls_certificate_verifier_external during construction time
* can be retrieved later here.
*/
void (*destruct)(void* user_data);
} grpc_tls_certificate_verifier_external;
/**
* EXPERIMENTAL API - Subject to change
*
* Converts an external verifier to an internal verifier.
* Note that we will not take the ownership of the external_verifier. Callers
* will need to delete external_verifier in its own destruct function.
*/
grpc_tls_certificate_verifier* grpc_tls_certificate_verifier_external_create(
grpc_tls_certificate_verifier_external* external_verifier);
/**
* EXPERIMENTAL API - Subject to change
*
* Factory function for an internal verifier that will do the default hostname
* check.
*/
grpc_tls_certificate_verifier* grpc_tls_certificate_verifier_host_name_create();
/**
* EXPERIMENTAL API - Subject to change
*
* Releases a grpc_tls_certificate_verifier object. The creator of the
* grpc_tls_certificate_verifier object is responsible for its release.
*/
void grpc_tls_certificate_verifier_release(
grpc_tls_certificate_verifier* verifier);
/**
* EXPERIMENTAL API - Subject to change
*
* Sets the verifier in options. The |options| will implicitly take a new ref to
* the |verifier|. If not set on the client side, we will verify server's
* certificates, and check the default hostname. If not set on the server side,
* we will verify client's certificates.
*/
void grpc_tls_credentials_options_set_certificate_verifier(
grpc_tls_credentials_options* options,
grpc_tls_certificate_verifier* verifier);
/**
* EXPERIMENTAL API - Subject to change
*
* Sets the options of whether to check the hostname of the peer on a per-call
* basis. This is usually used in a combination with virtual hosting at the
* client side, where each individual call on a channel can have a different
* host associated with it.
* This check is intended to verify that the host specified for the individual
* call is covered by the cert that the peer presented.
* The default is a non-zero value, which indicates performing such checks.
*/
GRPCAPI void grpc_tls_credentials_options_set_check_call_host(
grpc_tls_credentials_options* options, int check_call_host);
/**
* EXPERIMENTAL API - Subject to change
*
* Performs the verification logic of an internal verifier.
* This is typically used when composing the internal verifiers as part of the
* custom verification.
* If |grpc_tls_certificate_verifier_verify| returns true, inspect the
* verification result through request->status and request->error_details.
* Otherwise, inspect through the parameter of |callback|.
*/
int grpc_tls_certificate_verifier_verify(
grpc_tls_certificate_verifier* verifier,
grpc_tls_custom_verification_check_request* request,
grpc_tls_on_custom_verification_check_done_cb callback, void* callback_arg,
grpc_status_code* sync_status, char** sync_error_details);
/**
* EXPERIMENTAL API - Subject to change
*
* Performs the cancellation logic of an internal verifier.
* This is typically used when composing the internal verifiers as part of the
* custom verification.
*/
void grpc_tls_certificate_verifier_cancel(
grpc_tls_certificate_verifier* verifier,
grpc_tls_custom_verification_check_request* request);
/**
* EXPERIMENTAL API - Subject to change
*
* Creates a TLS channel credential object based on the
* grpc_tls_credentials_options specified by callers. The
* grpc_channel_credentials will take the ownership of the |options|. The
* security level of the resulting connection is GRPC_PRIVACY_AND_INTEGRITY. It
* is used for experimental purpose for now and subject to change.
* security level of the resulting connection is GRPC_PRIVACY_AND_INTEGRITY.
*/
grpc_channel_credentials* grpc_tls_credentials_create(
grpc_tls_credentials_options* options);
/**
* EXPERIMENTAL API - Subject to change
*
* Creates a TLS server credential object based on the
* grpc_tls_credentials_options specified by callers. The
* grpc_server_credentials will take the ownership of the |options|. It
* is used for experimental purpose for now and subject to change.
* grpc_server_credentials will take the ownership of the |options|.
*/
grpc_server_credentials* grpc_tls_server_credentials_create(
grpc_tls_credentials_options* options);

View File

@ -135,20 +135,6 @@ typedef enum {
GRPC_SECURITY_MAX = GRPC_PRIVACY_AND_INTEGRITY,
} grpc_security_level;
typedef enum {
/** Default option: performs server certificate verification and hostname
verification. */
GRPC_TLS_SERVER_VERIFICATION,
/** Performs server certificate verification, but skips hostname verification
Client is responsible for verifying server's identity via
server authorization check callback. */
GRPC_TLS_SKIP_HOSTNAME_VERIFICATION,
/** Skips both server certificate and hostname verification.
Client is responsible for verifying server's identity and
server's certificate via server authorization check callback. */
GRPC_TLS_SKIP_ALL_SERVER_VERIFICATION
} grpc_tls_server_verification_option;
/**
* Type of local connections for which local channel/server credentials will be
* applied. It supports UDS and local TCP connections.

View File

@ -0,0 +1,225 @@
//
// Copyright 2021 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.
//
#ifndef GRPCPP_SECURITY_TLS_CERTIFICATE_VERIFIER_H
#define GRPCPP_SECURITY_TLS_CERTIFICATE_VERIFIER_H
#include <functional>
#include <map>
#include <memory>
#include <utility>
#include <vector>
#include <grpc/grpc_security_constants.h>
#include <grpc/status.h>
#include <grpc/support/log.h>
#include <grpcpp/impl/codegen/grpc_library.h>
#include <grpcpp/impl/codegen/sync.h>
#include <grpcpp/impl/grpc_library.h>
#include <grpcpp/support/config.h>
#include <grpcpp/support/string_ref.h>
// TODO(yihuazhang): remove the forward declaration here and include
// <grpc/grpc_security.h> directly once the insecure builds are cleaned up.
typedef struct grpc_tls_custom_verification_check_request
grpc_tls_custom_verification_check_request;
typedef struct grpc_tls_certificate_verifier grpc_tls_certificate_verifier;
typedef struct grpc_tls_certificate_verifier_external
grpc_tls_certificate_verifier_external;
typedef void (*grpc_tls_on_custom_verification_check_done_cb)(
grpc_tls_custom_verification_check_request* request, void* callback_arg,
grpc_status_code status, const char* error_details);
extern "C" grpc_tls_certificate_verifier*
grpc_tls_certificate_verifier_external_create(
grpc_tls_certificate_verifier_external* external_verifier);
namespace grpc {
namespace experimental {
// Contains the verification-related information associated with a connection
// request. Users should not directly create or destroy this request object, but
// shall interact with it through CertificateVerifier's Verify() and Cancel().
class TlsCustomVerificationCheckRequest {
public:
explicit TlsCustomVerificationCheckRequest(
grpc_tls_custom_verification_check_request* request);
~TlsCustomVerificationCheckRequest() {}
grpc::string_ref target_name() const;
grpc::string_ref peer_cert() const;
grpc::string_ref peer_cert_full_chain() const;
grpc::string_ref common_name() const;
std::vector<grpc::string_ref> uri_names() const;
std::vector<grpc::string_ref> dns_names() const;
std::vector<grpc::string_ref> email_names() const;
std::vector<grpc::string_ref> ip_names() const;
grpc_tls_custom_verification_check_request* c_request() { return c_request_; }
private:
grpc_tls_custom_verification_check_request* c_request_ = nullptr;
};
// The base class of all internal verifier implementations, and the ultimate
// class that all external verifiers will eventually be transformed into.
// To implement a custom verifier, do not extend this class; instead,
// implement a subclass of ExternalCertificateVerifier. Note that custom
// verifier implementations can compose their functionality with existing
// implementations of this interface, such as HostnameVerifier, by delegating
// to an instance of that class.
class CertificateVerifier {
public:
explicit CertificateVerifier(grpc_tls_certificate_verifier* v);
~CertificateVerifier();
// Verifies a connection request, based on the logic specified in an internal
// verifier. The check on each internal verifier could be either synchronous
// or asynchronous, and we will need to use return value to know.
//
// request: the verification information associated with this request
// callback: This will only take effect if the verifier is asynchronous.
// The function that gRPC will invoke when the verifier has already
// completed its asynchronous check. Callers can use this function
// to perform any additional checks. The input parameter of the
// std::function indicates the status of the verifier check.
// sync_status: This will only be useful if the verifier is synchronous.
// The status of the verifier as it has already done it's
// synchronous check.
// return: return true if executed synchronously, otherwise return false
bool Verify(TlsCustomVerificationCheckRequest* request,
std::function<void(grpc::Status)> callback,
grpc::Status* sync_status);
// Cancels a verification request previously started via Verify().
// Used when the connection attempt times out or is cancelled while an async
// verification request is pending.
//
// request: the verification information associated with this request
void Cancel(TlsCustomVerificationCheckRequest* request);
// Gets the core verifier used internally.
grpc_tls_certificate_verifier* c_verifier() { return verifier_; };
private:
static void AsyncCheckDone(
grpc_tls_custom_verification_check_request* request, void* callback_arg,
grpc_status_code status, const char* error_details);
grpc_tls_certificate_verifier* verifier_ = nullptr;
grpc::internal::Mutex mu_;
std::map<grpc_tls_custom_verification_check_request*,
std::function<void(grpc::Status)>>
request_map_ ABSL_GUARDED_BY(mu_);
};
// The base class of all external, user-specified verifiers. Users should
// inherit this class to implement a custom verifier.
// Note that while implementing the custom verifier that extends this class, it
// is possible to compose an existing ExternalCertificateVerifier or
// CertificateVerifier, inside the Verify() and Cancel() function of the new
// custom verifier.
class ExternalCertificateVerifier {
public:
// A factory method for creating a |CertificateVerifier| from this class. All
// the user-implemented verifiers should use this function to be converted to
// verifiers compatible with |TlsCredentialsOptions|.
// The resulting CertificateVerifier takes ownership of the newly instantiated
// Subclass.
template <typename Subclass, typename... Args>
static std::shared_ptr<CertificateVerifier> Create(Args&&... args) {
grpc::internal::GrpcLibraryInitializer g_gli_initializer;
g_gli_initializer.summon();
auto* external_verifier = new Subclass(std::forward<Args>(args)...);
return std::make_shared<CertificateVerifier>(
grpc_tls_certificate_verifier_external_create(
external_verifier->base_));
}
// The verification logic that will be performed after the TLS handshake
// completes. Implementers can choose to do their checks synchronously or
// asynchronously.
//
// request: the verification information associated with this request
// callback: This should only be used if your check is done asynchronously.
// When the asynchronous work is done, invoke this callback function
// with the proper status, indicating the success or the failure of
// the check. The implementer MUST NOT invoke this |callback| in the
// same thread before Verify() returns, otherwise it can lead to
// deadlocks.
// sync_status: This should only be used if your check is done synchronously.
// Modifies this value to indicate the success or the failure of
// the check.
// return: return true if your check is done synchronously, otherwise return
// false
virtual bool Verify(TlsCustomVerificationCheckRequest* request,
std::function<void(grpc::Status)> callback,
grpc::Status* sync_status) = 0;
// Cancels a verification request previously started via Verify().
// Used when the connection attempt times out or is cancelled while an async
// verification request is pending. The implementation should abort whatever
// async operation it is waiting for and quickly invoke the callback that was
// passed to Verify() with a status indicating the cancellation.
//
// request: the verification information associated with this request
virtual void Cancel(TlsCustomVerificationCheckRequest* request) = 0;
protected:
ExternalCertificateVerifier();
virtual ~ExternalCertificateVerifier();
private:
struct AsyncRequestState {
AsyncRequestState(grpc_tls_on_custom_verification_check_done_cb cb,
void* arg,
grpc_tls_custom_verification_check_request* request)
: callback(cb), callback_arg(arg), cpp_request(request) {}
grpc_tls_on_custom_verification_check_done_cb callback;
void* callback_arg;
TlsCustomVerificationCheckRequest cpp_request;
};
static int VerifyInCoreExternalVerifier(
void* user_data, grpc_tls_custom_verification_check_request* request,
grpc_tls_on_custom_verification_check_done_cb callback,
void* callback_arg, grpc_status_code* sync_status,
char** sync_error_details);
static void CancelInCoreExternalVerifier(
void* user_data, grpc_tls_custom_verification_check_request* request);
static void DestructInCoreExternalVerifier(void* user_data);
// TODO(yihuazhang): after the insecure build is removed, make this an object
// member instead of a pointer.
grpc_tls_certificate_verifier_external* base_ = nullptr;
grpc::internal::Mutex mu_;
std::map<grpc_tls_custom_verification_check_request*, AsyncRequestState>
request_map_ ABSL_GUARDED_BY(mu_);
};
class HostNameCertificateVerifier : public CertificateVerifier {
public:
HostNameCertificateVerifier();
};
} // namespace experimental
} // namespace grpc
#endif // GRPCPP_SECURITY_TLS_CERTIFICATE_VERIFIER_H

View File

@ -26,6 +26,7 @@
#include <grpc/status.h>
#include <grpc/support/log.h>
#include <grpcpp/security/tls_certificate_provider.h>
#include <grpcpp/security/tls_certificate_verifier.h>
#include <grpcpp/support/config.h>
// TODO(yihuazhang): remove the forward declaration here and include
@ -36,116 +37,11 @@ typedef struct grpc_tls_server_authorization_check_config
grpc_tls_server_authorization_check_config;
typedef struct grpc_tls_credentials_options grpc_tls_credentials_options;
typedef struct grpc_tls_certificate_provider grpc_tls_certificate_provider;
typedef struct grpc_tls_certificate_verifier grpc_tls_certificate_verifier;
namespace grpc {
namespace experimental {
/** TLS server authorization check arguments, wraps
* grpc_tls_server_authorization_check_arg. It is used for experimental
* purposes for now and it is subject to change.
*
* The server authorization check arg contains all the info necessary to
* schedule/cancel a server authorization check request. The callback function
* must be called after finishing the schedule operation. See the description
* of the grpc_tls_server_authorization_check_arg struct in grpc_security.h for
* more details. **/
class TlsServerAuthorizationCheckArg {
public:
/** TlsServerAuthorizationCheckArg does not take ownership of the C arg passed
* to the constructor. One must remember to free any memory allocated to the
* C arg after using the setter functions below. **/
explicit TlsServerAuthorizationCheckArg(
grpc_tls_server_authorization_check_arg* arg);
~TlsServerAuthorizationCheckArg();
/** Getters for member fields. **/
void* cb_user_data() const;
int success() const;
std::string target_name() const;
std::string peer_cert() const;
std::string peer_cert_full_chain() const;
grpc_status_code status() const;
std::string error_details() const;
/** Setters for member fields. **/
void set_cb_user_data(void* cb_user_data);
void set_success(int success);
void set_target_name(const std::string& target_name);
void set_peer_cert(const std::string& peer_cert);
void set_peer_cert_full_chain(const std::string& peer_cert_full_chain);
void set_status(grpc_status_code status);
void set_error_details(const std::string& error_details);
/** Calls the C arg's callback function. **/
void OnServerAuthorizationCheckDoneCallback();
private:
grpc_tls_server_authorization_check_arg* c_arg_;
};
/** An interface that the application derives and uses to instantiate a
* TlsServerAuthorizationCheckConfig instance. Refer to the definition of the
* grpc_tls_server_authorization_check_config in grpc_tls_credentials_options.h
* for more details on the expectations of the member functions of the
* interface.
* **/
struct TlsServerAuthorizationCheckInterface {
virtual ~TlsServerAuthorizationCheckInterface() = default;
/** A callback that invokes the server authorization check. **/
virtual int Schedule(TlsServerAuthorizationCheckArg* arg) = 0;
/** A callback that cancels a server authorization check request. **/
virtual void Cancel(TlsServerAuthorizationCheckArg* /* arg */) {}
};
/** TLS server authorization check config, wraps
* grps_tls_server_authorization_check_config. It is used for experimental
* purposes for now and it is subject to change. **/
class TlsServerAuthorizationCheckConfig {
public:
explicit TlsServerAuthorizationCheckConfig(
std::shared_ptr<TlsServerAuthorizationCheckInterface>
server_authorization_check_interface);
~TlsServerAuthorizationCheckConfig();
int Schedule(TlsServerAuthorizationCheckArg* arg) const {
if (server_authorization_check_interface_ == nullptr) {
gpr_log(GPR_ERROR, "server authorization check interface is nullptr");
if (arg != nullptr) {
arg->set_status(GRPC_STATUS_NOT_FOUND);
arg->set_error_details(
"the interface of the server authorization check config is "
"nullptr");
}
return 1;
}
return server_authorization_check_interface_->Schedule(arg);
}
void Cancel(TlsServerAuthorizationCheckArg* arg) const {
if (server_authorization_check_interface_ == nullptr) {
gpr_log(GPR_ERROR, "server authorization check interface is nullptr");
if (arg != nullptr) {
arg->set_status(GRPC_STATUS_NOT_FOUND);
arg->set_error_details(
"the interface of the server authorization check config is "
"nullptr");
}
return;
}
server_authorization_check_interface_->Cancel(arg);
}
/** Returns C struct for the server authorization check config. **/
grpc_tls_server_authorization_check_config* c_config() const {
return c_config_;
}
private:
grpc_tls_server_authorization_check_config* c_config_;
std::shared_ptr<TlsServerAuthorizationCheckInterface>
server_authorization_check_interface_;
};
// Base class of configurable options specified by users to configure their
// certain security features supported in TLS. It is used for experimental
// purposes for now and it is subject to change.
@ -187,6 +83,19 @@ class TlsCredentialsOptions {
//
// @param identity_cert_name the name of identity key-cert pairs being set.
void set_identity_cert_name(const std::string& identity_cert_name);
// Sets the certificate verifier used to perform post-handshake peer identity
// checks.
void set_certificate_verifier(
std::shared_ptr<CertificateVerifier> certificate_verifier);
// Sets the options of whether to check the hostname of the peer on a per-call
// basis. This is usually used in a combination with virtual hosting at the
// client side, where each individual call on a channel can have a different
// host associated with it.
// This check is intended to verify that the host specified for the individual
// call is covered by the cert that the peer presented.
// We will perform such checks by default. This should be disabled if
// verifiers other than the host name verifier is used.
void set_check_call_host(bool check_call_host);
// ----- Getters for member fields ----
// Get the internal c options. This function shall be used only internally.
@ -196,6 +105,7 @@ class TlsCredentialsOptions {
private:
std::shared_ptr<CertificateProviderInterface> certificate_provider_;
std::shared_ptr<CertificateVerifier> certificate_verifier_;
grpc_tls_credentials_options* c_credentials_options_ = nullptr;
};
@ -207,14 +117,9 @@ class TlsCredentialsOptions {
// It is used for experimental purposes for now and it is subject to change.
class TlsChannelCredentialsOptions final : public TlsCredentialsOptions {
public:
// Sets the option to verify the server.
// The default is GRPC_TLS_SERVER_VERIFICATION.
void set_server_verification_option(
grpc_tls_server_verification_option server_verification_option);
// Sets the custom authorization config.
void set_server_authorization_check_config(
std::shared_ptr<TlsServerAuthorizationCheckConfig>
authorization_check_config);
// Sets the decision of whether to do a crypto check on the server certs.
// The default is true.
void set_verify_server_certs(bool verify_server_certs);
private:
};

2
package.xml generated
View File

@ -1104,6 +1104,8 @@
<file baseinstalldir="/" name="src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/security/credentials/tls/grpc_tls_certificate_provider.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/security/credentials/tls/grpc_tls_certificate_provider.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/security/credentials/tls/grpc_tls_certificate_verifier.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/security/credentials/tls/grpc_tls_certificate_verifier.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/security/credentials/tls/tls_credentials.cc" role="src" />

View File

@ -0,0 +1,201 @@
//
// Copyright 2021 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 <grpc/support/port_platform.h>
#include "src/core/lib/security/credentials/tls/grpc_tls_certificate_verifier.h"
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
#include "src/core/lib/gprpp/host_port.h"
#include "src/core/lib/gprpp/stat.h"
#include "src/core/lib/security/credentials/tls/tls_utils.h"
#include "src/core/lib/slice/slice_internal.h"
#include "src/core/lib/surface/api_trace.h"
namespace grpc_core {
bool ExternalCertificateVerifier::Verify(
grpc_tls_custom_verification_check_request* request,
std::function<void(absl::Status)> callback, absl::Status* sync_status) {
{
MutexLock lock(&mu_);
request_map_.emplace(request, std::move(callback));
}
// Invoke the caller-specified verification logic embedded in
// external_verifier_.
grpc_status_code status_code = GRPC_STATUS_OK;
char* error_details = nullptr;
bool is_done = external_verifier_->verify(external_verifier_->user_data,
request, &OnVerifyDone, this,
&status_code, &error_details);
if (is_done) {
if (status_code != GRPC_STATUS_OK) {
*sync_status = absl::Status(static_cast<absl::StatusCode>(status_code),
error_details);
}
MutexLock lock(&mu_);
request_map_.erase(request);
}
gpr_free(error_details);
return is_done;
}
void ExternalCertificateVerifier::OnVerifyDone(
grpc_tls_custom_verification_check_request* request, void* callback_arg,
grpc_status_code status, const char* error_details) {
ExecCtx exec_ctx;
auto* self = static_cast<ExternalCertificateVerifier*>(callback_arg);
std::function<void(absl::Status)> callback;
{
MutexLock lock(&self->mu_);
auto it = self->request_map_.find(request);
if (it != self->request_map_.end()) {
callback = std::move(it->second);
self->request_map_.erase(it);
}
}
if (callback != nullptr) {
absl::Status return_status = absl::OkStatus();
if (status != GRPC_STATUS_OK) {
return_status =
absl::Status(static_cast<absl::StatusCode>(status), error_details);
}
callback(return_status);
}
}
bool HostNameCertificateVerifier::Verify(
grpc_tls_custom_verification_check_request* request,
std::function<void(absl::Status)>, absl::Status* sync_status) {
GPR_ASSERT(request != nullptr);
// Extract the target name, and remove its port.
const char* target_name = request->target_name;
if (target_name == nullptr) {
*sync_status = absl::Status(absl::StatusCode::kUnauthenticated,
"Target name is not specified.");
return true; // synchronous check
}
absl::string_view target_host;
absl::string_view ignored_port;
SplitHostPort(target_name, &target_host, &ignored_port);
if (target_host.empty()) {
*sync_status = absl::Status(absl::StatusCode::kUnauthenticated,
"Failed to split hostname and port.");
return true; // synchronous check
}
// IPv6 zone-id should not be included in comparisons.
const size_t zone_id = target_host.find('%');
if (zone_id != absl::string_view::npos) {
target_host.remove_suffix(target_host.size() - zone_id);
}
// Perform the hostname check.
// First check the DNS field. We allow prefix or suffix wildcard matching.
char** dns_names = request->peer_info.san_names.dns_names;
size_t dns_names_size = request->peer_info.san_names.dns_names_size;
if (dns_names != nullptr && dns_names_size > 0) {
for (size_t i = 0; i < dns_names_size; ++i) {
const char* dns_name = dns_names[i];
// We are using the target name sent from the client as a matcher to match
// against identity name on the peer cert.
if (VerifySubjectAlternativeName(dns_name, std::string(target_host))) {
return true; // synchronous check
}
}
}
// Then check the IP address. We only allow exact matching.
char** ip_names = request->peer_info.san_names.ip_names;
size_t ip_names_size = request->peer_info.san_names.ip_names_size;
if (ip_names != nullptr && ip_names_size > 0) {
for (size_t i = 0; i < ip_names_size; ++i) {
const char* ip_name = ip_names[i];
if (target_host == ip_name) {
return true; // synchronous check
}
}
}
// If there's no SAN, try the CN.
if (dns_names_size == 0) {
const char* common_name = request->peer_info.common_name;
// We are using the target name sent from the client as a matcher to match
// against identity name on the peer cert.
if (VerifySubjectAlternativeName(common_name, std::string(target_host))) {
return true; // synchronous check
}
}
*sync_status = absl::Status(absl::StatusCode::kUnauthenticated,
"Hostname Verification Check failed.");
return true; // synchronous check
}
} // namespace grpc_core
//
// Wrapper APIs declared in grpc_security.h
//
int grpc_tls_certificate_verifier_verify(
grpc_tls_certificate_verifier* verifier,
grpc_tls_custom_verification_check_request* request,
grpc_tls_on_custom_verification_check_done_cb callback, void* callback_arg,
grpc_status_code* sync_status, char** sync_error_details) {
grpc_core::ExecCtx exec_ctx;
std::function<void(absl::Status)> async_cb =
[callback, request, callback_arg](absl::Status async_status) {
callback(request, callback_arg,
static_cast<grpc_status_code>(async_status.code()),
std::string(async_status.message()).c_str());
};
absl::Status sync_status_cpp;
bool is_done = verifier->Verify(request, async_cb, &sync_status_cpp);
if (is_done) {
if (!sync_status_cpp.ok()) {
*sync_status = static_cast<grpc_status_code>(sync_status_cpp.code());
*sync_error_details =
gpr_strdup(std::string(sync_status_cpp.message()).c_str());
}
}
return is_done;
}
void grpc_tls_certificate_verifier_cancel(
grpc_tls_certificate_verifier* verifier,
grpc_tls_custom_verification_check_request* request) {
grpc_core::ExecCtx exec_ctx;
verifier->Cancel(request);
}
grpc_tls_certificate_verifier* grpc_tls_certificate_verifier_external_create(
grpc_tls_certificate_verifier_external* external_verifier) {
grpc_core::ExecCtx exec_ctx;
return new grpc_core::ExternalCertificateVerifier(external_verifier);
}
grpc_tls_certificate_verifier*
grpc_tls_certificate_verifier_host_name_create() {
grpc_core::ExecCtx exec_ctx;
return new grpc_core::HostNameCertificateVerifier();
}
void grpc_tls_certificate_verifier_release(
grpc_tls_certificate_verifier* verifier) {
GRPC_API_TRACE("grpc_tls_certificate_verifier_release(verifier=%p)", 1,
(verifier));
grpc_core::ExecCtx exec_ctx;
if (verifier != nullptr) verifier->Unref();
}

View File

@ -0,0 +1,106 @@
//
// Copyright 2021 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.
//
#ifndef GRPC_CORE_LIB_SECURITY_CREDENTIALS_TLS_GRPC_TLS_CERTIFICATE_VERIFIER_H
#define GRPC_CORE_LIB_SECURITY_CREDENTIALS_TLS_GRPC_TLS_CERTIFICATE_VERIFIER_H
#include <grpc/support/port_platform.h>
#include <string.h>
#include "absl/status/status.h"
#include <grpc/grpc_security.h>
#include "src/core/lib/gprpp/ref_counted.h"
#include "src/core/lib/gprpp/ref_counted_ptr.h"
#include "src/core/lib/gprpp/thd.h"
#include "src/core/lib/iomgr/load_file.h"
#include "src/core/lib/iomgr/pollset_set.h"
#include "src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.h"
#include "src/core/lib/security/security_connector/ssl_utils.h"
// An abstraction of the verifier that all verifier subclasses should extend.
struct grpc_tls_certificate_verifier
: public grpc_core::RefCounted<grpc_tls_certificate_verifier> {
public:
grpc_tls_certificate_verifier() = default;
~grpc_tls_certificate_verifier() override = default;
// Verifies the specific request. It can be processed in sync or async mode.
// If the caller want it to be processed asynchronously, return false
// immediately, and at the end of the async operation, invoke the callback
// with the verification results stored in absl::Status. Otherwise, populate
// the verification results in |sync_status| and return true. The caller is
// expected to populate verification results by setting request.
virtual bool Verify(grpc_tls_custom_verification_check_request* request,
std::function<void(absl::Status)> callback,
absl::Status* sync_status) = 0;
// Operations that will be performed when a request is cancelled.
// This is only needed when in async mode.
virtual void Cancel(grpc_tls_custom_verification_check_request* request) = 0;
};
namespace grpc_core {
// A verifier that will transform grpc_tls_certificate_verifier_external to a
// verifier that extends grpc_tls_certificate_verifier.
class ExternalCertificateVerifier : public grpc_tls_certificate_verifier {
public:
explicit ExternalCertificateVerifier(
grpc_tls_certificate_verifier_external* external_verifier)
: external_verifier_(external_verifier) {}
~ExternalCertificateVerifier() override {
if (external_verifier_->destruct != nullptr) {
external_verifier_->destruct(external_verifier_->user_data);
}
}
bool Verify(grpc_tls_custom_verification_check_request* request,
std::function<void(absl::Status)> callback,
absl::Status* sync_status) override;
void Cancel(grpc_tls_custom_verification_check_request* request) override {
external_verifier_->cancel(external_verifier_->user_data, request);
}
private:
grpc_tls_certificate_verifier_external* external_verifier_;
static void OnVerifyDone(grpc_tls_custom_verification_check_request* request,
void* callback_arg, grpc_status_code status,
const char* error_details);
// Guards members below.
Mutex mu_;
// stores each check request and its corresponding callback function.
std::map<grpc_tls_custom_verification_check_request*,
std::function<void(absl::Status)>>
request_map_ ABSL_GUARDED_BY(mu_);
};
// An internal verifier that will perform hostname verification check.
class HostNameCertificateVerifier : public grpc_tls_certificate_verifier {
public:
bool Verify(grpc_tls_custom_verification_check_request* request,
std::function<void(absl::Status)> callback,
absl::Status* sync_status) override;
void Cancel(grpc_tls_custom_verification_check_request*) override {}
};
} // namespace grpc_core
#endif // GRPC_CORE_LIB_SECURITY_CREDENTIALS_TLS_GRPC_TLS_CERTIFICATE_VERIFIER_H

View File

@ -29,61 +29,6 @@
#include "src/core/lib/surface/api_trace.h"
/** -- gRPC TLS server authorization check API implementation. -- **/
grpc_tls_server_authorization_check_config::
grpc_tls_server_authorization_check_config(
const void* config_user_data,
int (*schedule)(void* config_user_data,
grpc_tls_server_authorization_check_arg* arg),
void (*cancel)(void* config_user_data,
grpc_tls_server_authorization_check_arg* arg),
void (*destruct)(void* config_user_data))
: config_user_data_(const_cast<void*>(config_user_data)),
schedule_(schedule),
cancel_(cancel),
destruct_(destruct) {}
grpc_tls_server_authorization_check_config::
~grpc_tls_server_authorization_check_config() {
if (destruct_ != nullptr) {
destruct_(config_user_data_);
}
}
int grpc_tls_server_authorization_check_config::Schedule(
grpc_tls_server_authorization_check_arg* arg) const {
if (schedule_ == nullptr) {
gpr_log(GPR_ERROR, "schedule API is nullptr");
if (arg != nullptr) {
arg->status = GRPC_STATUS_NOT_FOUND;
arg->error_details->set_error_details(
"schedule API in server authorization check config is nullptr");
}
return 1;
}
if (arg != nullptr && context_ != nullptr) {
arg->config = const_cast<grpc_tls_server_authorization_check_config*>(this);
}
return schedule_(config_user_data_, arg);
}
void grpc_tls_server_authorization_check_config::Cancel(
grpc_tls_server_authorization_check_arg* arg) const {
if (cancel_ == nullptr) {
gpr_log(GPR_ERROR, "cancel API is nullptr.");
if (arg != nullptr) {
arg->status = GRPC_STATUS_NOT_FOUND;
arg->error_details->set_error_details(
"schedule API in server authorization check config is nullptr");
}
return;
}
if (arg != nullptr) {
arg->config = const_cast<grpc_tls_server_authorization_check_config*>(this);
}
cancel_(config_user_data_, arg);
}
/** -- Wrapper APIs declared in grpc_security.h -- **/
grpc_tls_credentials_options* grpc_tls_credentials_options_create() {
@ -98,11 +43,10 @@ void grpc_tls_credentials_options_set_cert_request_type(
options->set_cert_request_type(type);
}
void grpc_tls_credentials_options_set_server_verification_option(
grpc_tls_credentials_options* options,
grpc_tls_server_verification_option server_verification_option) {
void grpc_tls_credentials_options_set_verify_server_cert(
grpc_tls_credentials_options* options, int verify_server_cert) {
GPR_ASSERT(options != nullptr);
options->set_server_verification_option(server_verification_option);
options->set_verify_server_cert(verify_server_cert);
}
void grpc_tls_credentials_options_set_certificate_provider(
@ -139,39 +83,16 @@ void grpc_tls_credentials_options_set_identity_cert_name(
options->set_identity_cert_name(identity_cert_name);
}
void grpc_tls_credentials_options_set_server_authorization_check_config(
void grpc_tls_credentials_options_set_certificate_verifier(
grpc_tls_credentials_options* options,
grpc_tls_server_authorization_check_config* config) {
grpc_tls_certificate_verifier* verifier) {
GPR_ASSERT(options != nullptr);
GPR_ASSERT(config != nullptr);
grpc_core::ExecCtx exec_ctx;
options->set_server_authorization_check_config(config->Ref());
GPR_ASSERT(verifier != nullptr);
options->set_certificate_verifier(verifier->Ref());
}
grpc_tls_server_authorization_check_config*
grpc_tls_server_authorization_check_config_create(
const void* config_user_data,
int (*schedule)(void* config_user_data,
grpc_tls_server_authorization_check_arg* arg),
void (*cancel)(void* config_user_data,
grpc_tls_server_authorization_check_arg* arg),
void (*destruct)(void* config_user_data)) {
if (schedule == nullptr) {
gpr_log(GPR_ERROR,
"Schedule API is nullptr in creating TLS server authorization "
"check config.");
return nullptr;
}
grpc_core::ExecCtx exec_ctx;
return new grpc_tls_server_authorization_check_config(
config_user_data, schedule, cancel, destruct);
}
void grpc_tls_server_authorization_check_config_release(
grpc_tls_server_authorization_check_config* config) {
GRPC_API_TRACE(
"grpc_tls_server_authorization_check_config_release(config=%p)", 1,
(config));
grpc_core::ExecCtx exec_ctx;
if (config != nullptr) config->Unref();
void grpc_tls_credentials_options_set_check_call_host(
grpc_tls_credentials_options* options, int check_call_host) {
GPR_ASSERT(options != nullptr);
options->set_check_call_host(check_call_host);
}

View File

@ -28,73 +28,9 @@
#include "src/core/lib/gprpp/ref_counted.h"
#include "src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.h"
#include "src/core/lib/security/credentials/tls/grpc_tls_certificate_provider.h"
#include "src/core/lib/security/credentials/tls/grpc_tls_certificate_verifier.h"
#include "src/core/lib/security/security_connector/ssl_utils.h"
struct grpc_tls_error_details
: public grpc_core::RefCounted<grpc_tls_error_details> {
public:
grpc_tls_error_details() : error_details_("") {}
void set_error_details(const char* err_details) {
error_details_ = err_details;
}
const std::string& error_details() { return error_details_; }
private:
std::string error_details_;
};
/** TLS server authorization check config. **/
struct grpc_tls_server_authorization_check_config
: public grpc_core::RefCounted<grpc_tls_server_authorization_check_config> {
public:
grpc_tls_server_authorization_check_config(
const void* config_user_data,
int (*schedule)(void* config_user_data,
grpc_tls_server_authorization_check_arg* arg),
void (*cancel)(void* config_user_data,
grpc_tls_server_authorization_check_arg* arg),
void (*destruct)(void* config_user_data));
~grpc_tls_server_authorization_check_config() override;
void* context() const { return context_; }
void set_context(void* context) { context_ = context; }
int Schedule(grpc_tls_server_authorization_check_arg* arg) const;
void Cancel(grpc_tls_server_authorization_check_arg* arg) const;
private:
/** This is a pointer to the wrapped language implementation of
* grpc_tls_server_authorization_check_config. It is necessary to implement
* the C schedule and cancel functions, given the schedule or cancel function
* in a wrapped language. **/
void* context_ = nullptr;
/** config-specific, read-only user data that works for all channels created
with a Credential using the config. */
void* config_user_data_;
/** callback function for invoking server authorization check. The
implementation of this method has to be non-blocking, but can be performed
synchronously or asynchronously.
If processing occurs synchronously, it populates \a arg->result, \a
arg->status, and \a arg->error_details, and returns zero.
If processing occurs asynchronously, it returns a non-zero value.
Application then invokes \a arg->cb when processing is completed. Note that
\a arg->cb cannot be invoked before \a schedule() returns.
*/
int (*schedule_)(void* config_user_data,
grpc_tls_server_authorization_check_arg* arg);
/** callback function for canceling a server authorization check request. */
void (*cancel_)(void* config_user_data,
grpc_tls_server_authorization_check_arg* arg);
/** callback function for cleaning up any data associated with server
authorization check config. */
void (*destruct_)(void* config_user_data);
};
// Contains configurable options specified by callers to configure their certain
// security features supported in TLS.
// TODO(ZhenLian): consider making this not ref-counted.
@ -107,15 +43,14 @@ struct grpc_tls_credentials_options
grpc_ssl_client_certificate_request_type cert_request_type() const {
return cert_request_type_;
}
grpc_tls_server_verification_option server_verification_option() const {
return server_verification_option_;
}
bool verify_server_cert() const { return verify_server_cert_; }
grpc_tls_version min_tls_version() const { return min_tls_version_; }
grpc_tls_version max_tls_version() const { return max_tls_version_; }
grpc_tls_server_authorization_check_config*
server_authorization_check_config() const {
return server_authorization_check_config_.get();
// Returns the verifier set in the options.
grpc_tls_certificate_verifier* certificate_verifier() {
return verifier_.get();
}
bool check_call_host() const { return check_call_host_; }
// Returns the distributor from provider_ if it is set, nullptr otherwise.
grpc_tls_certificate_distributor* certificate_distributor() {
if (provider_ != nullptr) return provider_->distributor().get();
@ -131,9 +66,8 @@ struct grpc_tls_credentials_options
const grpc_ssl_client_certificate_request_type type) {
cert_request_type_ = type;
}
void set_server_verification_option(
const grpc_tls_server_verification_option server_verification_option) {
server_verification_option_ = server_verification_option;
void set_verify_server_cert(bool verify_server_cert) {
verify_server_cert_ = verify_server_cert;
}
void set_min_tls_version(grpc_tls_version min_tls_version) {
min_tls_version_ = min_tls_version;
@ -141,10 +75,14 @@ struct grpc_tls_credentials_options
void set_max_tls_version(grpc_tls_version max_tls_version) {
max_tls_version_ = max_tls_version;
}
void set_server_authorization_check_config(
grpc_core::RefCountedPtr<grpc_tls_server_authorization_check_config>
config) {
server_authorization_check_config_ = std::move(config);
// Sets the verifier in the options.
void set_certificate_verifier(
grpc_core::RefCountedPtr<grpc_tls_certificate_verifier> verifier) {
verifier_ = std::move(verifier);
}
// Sets the verifier in the options.
void set_check_call_host(bool check_call_host) {
check_call_host_ = check_call_host;
}
// Sets the provider in the options.
void set_certificate_provider(
@ -177,12 +115,11 @@ struct grpc_tls_credentials_options
private:
grpc_ssl_client_certificate_request_type cert_request_type_ =
GRPC_SSL_DONT_REQUEST_CLIENT_CERTIFICATE;
grpc_tls_server_verification_option server_verification_option_ =
GRPC_TLS_SERVER_VERIFICATION;
bool verify_server_cert_ = true;
grpc_tls_version min_tls_version_ = grpc_tls_version::TLS1_2;
grpc_tls_version max_tls_version_ = grpc_tls_version::TLS1_3;
grpc_core::RefCountedPtr<grpc_tls_server_authorization_check_config>
server_authorization_check_config_;
grpc_core::RefCountedPtr<grpc_tls_certificate_verifier> verifier_;
bool check_call_host_ = true;
grpc_core::RefCountedPtr<grpc_tls_certificate_provider> provider_;
bool watch_root_cert_ = false;
std::string root_cert_name_;

View File

@ -28,29 +28,40 @@
#include <grpc/support/string_util.h>
#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/security/credentials/tls/grpc_tls_certificate_verifier.h"
#include "src/core/lib/security/security_connector/tls/tls_security_connector.h"
#define GRPC_CREDENTIALS_TYPE_TLS "Tls"
namespace {
bool CredentialOptionSanityCheck(const grpc_tls_credentials_options* options,
bool CredentialOptionSanityCheck(grpc_tls_credentials_options* options,
bool is_client) {
if (options == nullptr) {
gpr_log(GPR_ERROR, "TLS credentials options is nullptr.");
return false;
}
// TODO(ZhenLian): remove this when it is also supported on server side.
if (!is_client && options->server_authorization_check_config() != nullptr) {
gpr_log(GPR_INFO,
"Server's credentials options should not contain server "
"authorization check config.");
}
if (options->server_verification_option() != GRPC_TLS_SERVER_VERIFICATION &&
options->server_authorization_check_config() == nullptr) {
// In the following conditions, there won't be any issues, but it might
// indicate callers are doing something wrong with the API.
if (is_client && options->cert_request_type() !=
GRPC_SSL_DONT_REQUEST_CLIENT_CERTIFICATE) {
gpr_log(GPR_ERROR,
"Should provider custom verifications if bypassing default ones.");
return false;
"Client's credentials options should not set cert_request_type.");
}
if (!is_client && !options->verify_server_cert()) {
gpr_log(GPR_ERROR,
"Server's credentials options should not set verify_server_cert.");
}
// In the following conditions, there could be severe security issues.
if (is_client && options->certificate_verifier() == nullptr) {
// If no verifier is specified on the client side, use the hostname verifier
// as default. Users who want to bypass all the verifier check should
// implement an external verifier instead.
gpr_log(GPR_INFO,
"No verifier specified on the client side. Using default hostname "
"verifier");
options->set_certificate_verifier(
grpc_core::MakeRefCounted<grpc_core::HostNameCertificateVerifier>());
}
return true;
}

View File

@ -61,41 +61,39 @@ bool XdsVerifySubjectAlternativeNames(
return false;
}
class ServerAuthCheck {
class XdsCertificateVerifier : public grpc_tls_certificate_verifier {
public:
ServerAuthCheck(
XdsCertificateVerifier(
RefCountedPtr<XdsCertificateProvider> xds_certificate_provider,
std::string cluster_name)
: xds_certificate_provider_(std::move(xds_certificate_provider)),
cluster_name_(std::move(cluster_name)) {}
static int Schedule(void* config_user_data,
grpc_tls_server_authorization_check_arg* arg) {
return static_cast<ServerAuthCheck*>(config_user_data)->ScheduleImpl(arg);
}
static void Destroy(void* config_user_data) {
delete static_cast<ServerAuthCheck*>(config_user_data);
bool Verify(grpc_tls_custom_verification_check_request* request,
std::function<void(absl::Status)>,
absl::Status* sync_status) override {
GPR_ASSERT(request != nullptr);
if (!XdsVerifySubjectAlternativeNames(
request->peer_info.san_names.uri_names,
request->peer_info.san_names.uri_names_size,
xds_certificate_provider_->GetSanMatchers(cluster_name_)) &&
!XdsVerifySubjectAlternativeNames(
request->peer_info.san_names.ip_names,
request->peer_info.san_names.ip_names_size,
xds_certificate_provider_->GetSanMatchers(cluster_name_)) &&
!XdsVerifySubjectAlternativeNames(
request->peer_info.san_names.dns_names,
request->peer_info.san_names.dns_names_size,
xds_certificate_provider_->GetSanMatchers(cluster_name_))) {
*sync_status = absl::Status(
absl::StatusCode::kUnauthenticated,
"SANs from certificate did not match SANs from xDS control plane");
}
return true; /* synchronous check */
}
void Cancel(grpc_tls_custom_verification_check_request*) override {}
private:
int ScheduleImpl(grpc_tls_server_authorization_check_arg* arg) {
if (XdsVerifySubjectAlternativeNames(
arg->subject_alternative_names, arg->subject_alternative_names_size,
xds_certificate_provider_->GetSanMatchers(cluster_name_))) {
arg->success = 1;
arg->status = GRPC_STATUS_OK;
} else {
arg->success = 0;
arg->status = GRPC_STATUS_UNAUTHENTICATED;
if (arg->error_details) {
arg->error_details->set_error_details(
"SANs from certificate did not match SANs from xDS control plane");
}
}
return 0; /* synchronous check */
}
RefCountedPtr<XdsCertificateProvider> xds_certificate_provider_;
std::string cluster_name_;
};
@ -161,14 +159,11 @@ XdsCredentials::create_security_connector(
tls_credentials_options->set_watch_identity_pair(true);
tls_credentials_options->set_identity_cert_name(cluster_name);
}
tls_credentials_options->set_server_verification_option(
GRPC_TLS_SKIP_HOSTNAME_VERIFICATION);
auto* server_auth_check = new ServerAuthCheck(xds_certificate_provider,
std::move(cluster_name));
tls_credentials_options->set_server_authorization_check_config(
MakeRefCounted<grpc_tls_server_authorization_check_config>(
server_auth_check, ServerAuthCheck::Schedule, nullptr,
ServerAuthCheck::Destroy));
tls_credentials_options->set_verify_server_cert(true);
tls_credentials_options->set_certificate_verifier(
MakeRefCounted<XdsCertificateVerifier>(xds_certificate_provider,
std::move(cluster_name)));
tls_credentials_options->set_check_call_host(false);
// TODO(yashkt): Creating a new TlsCreds object each time we create a
// security connector means that the security connector's cmp() method
// returns unequal for each instance, which means that every time an LB

View File

@ -196,6 +196,7 @@ bool grpc_ssl_check_call_host(absl::string_view host,
if (status != GRPC_SECURITY_OK) {
*error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"call host does not match SSL server name");
gpr_log(GPR_ERROR, "call host does not match SSL server name");
}
grpc_shallow_peer_destruct(&peer);
return true;

View File

@ -23,6 +23,7 @@
#include <stdbool.h>
#include <string.h>
#include "absl/functional/bind_front.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
@ -46,6 +47,155 @@ namespace grpc_core {
namespace {
char* CopyCoreString(char* src, size_t length) {
char* target = static_cast<char*>(gpr_malloc(length + 1));
memcpy(target, src, length);
target[length] = '\0';
return target;
}
void PendingVerifierRequestInit(
const char* target_name, tsi_peer peer,
grpc_tls_custom_verification_check_request* request) {
GPR_ASSERT(request != nullptr);
// The verifier holds a ref to the security connector, so it's fine to
// directly point this to the name cached in the security connector.
request->target_name = target_name;
// TODO(ZhenLian): avoid the copy when the underlying core implementation used
// the null-terminating string.
bool has_common_name = false;
bool has_peer_cert = false;
bool has_peer_cert_full_chain = false;
std::vector<char*> uri_names;
std::vector<char*> dns_names;
std::vector<char*> email_names;
std::vector<char*> ip_names;
for (size_t i = 0; i < peer.property_count; ++i) {
const tsi_peer_property* prop = &peer.properties[i];
if (prop->name == nullptr) continue;
if (strcmp(prop->name, TSI_X509_SUBJECT_COMMON_NAME_PEER_PROPERTY) == 0) {
request->peer_info.common_name =
CopyCoreString(prop->value.data, prop->value.length);
has_common_name = true;
} else if (strcmp(prop->name, TSI_X509_PEM_CERT_PROPERTY) == 0) {
request->peer_info.peer_cert =
CopyCoreString(prop->value.data, prop->value.length);
has_peer_cert = true;
} else if (strcmp(prop->name, TSI_X509_PEM_CERT_CHAIN_PROPERTY) == 0) {
request->peer_info.peer_cert_full_chain =
CopyCoreString(prop->value.data, prop->value.length);
has_peer_cert_full_chain = true;
} else if (strcmp(prop->name, TSI_X509_URI_PEER_PROPERTY) == 0) {
char* uri = CopyCoreString(prop->value.data, prop->value.length);
uri_names.emplace_back(uri);
} else if (strcmp(prop->name, TSI_X509_DNS_PEER_PROPERTY) == 0) {
char* dns = CopyCoreString(prop->value.data, prop->value.length);
dns_names.emplace_back(dns);
} else if (strcmp(prop->name, TSI_X509_EMAIL_PEER_PROPERTY) == 0) {
char* email = CopyCoreString(prop->value.data, prop->value.length);
email_names.emplace_back(email);
} else if (strcmp(prop->name, TSI_X509_IP_PEER_PROPERTY) == 0) {
char* ip = CopyCoreString(prop->value.data, prop->value.length);
ip_names.emplace_back(ip);
}
}
if (!has_common_name) {
request->peer_info.common_name = nullptr;
}
if (!has_peer_cert) {
request->peer_info.peer_cert = nullptr;
}
if (!has_peer_cert_full_chain) {
request->peer_info.peer_cert_full_chain = nullptr;
}
request->peer_info.san_names.uri_names_size = uri_names.size();
if (!uri_names.empty()) {
request->peer_info.san_names.uri_names =
new char*[request->peer_info.san_names.uri_names_size];
for (size_t i = 0; i < request->peer_info.san_names.uri_names_size; ++i) {
// We directly point the char* string stored in vector to the |request|.
// That string will be released when the |request| is destroyed.
request->peer_info.san_names.uri_names[i] = uri_names[i];
}
} else {
request->peer_info.san_names.uri_names = nullptr;
}
request->peer_info.san_names.dns_names_size = dns_names.size();
if (!dns_names.empty()) {
request->peer_info.san_names.dns_names =
new char*[request->peer_info.san_names.dns_names_size];
for (size_t i = 0; i < request->peer_info.san_names.dns_names_size; ++i) {
// We directly point the char* string stored in vector to the |request|.
// That string will be released when the |request| is destroyed.
request->peer_info.san_names.dns_names[i] = dns_names[i];
}
} else {
request->peer_info.san_names.dns_names = nullptr;
}
request->peer_info.san_names.email_names_size = email_names.size();
if (!email_names.empty()) {
request->peer_info.san_names.email_names =
new char*[request->peer_info.san_names.email_names_size];
for (size_t i = 0; i < request->peer_info.san_names.email_names_size; ++i) {
// We directly point the char* string stored in vector to the |request|.
// That string will be released when the |request| is destroyed.
request->peer_info.san_names.email_names[i] = email_names[i];
}
} else {
request->peer_info.san_names.email_names = nullptr;
}
request->peer_info.san_names.ip_names_size = ip_names.size();
if (!ip_names.empty()) {
request->peer_info.san_names.ip_names =
new char*[request->peer_info.san_names.ip_names_size];
for (size_t i = 0; i < request->peer_info.san_names.ip_names_size; ++i) {
// We directly point the char* string stored in vector to the |request|.
// That string will be released when the |request| is destroyed.
request->peer_info.san_names.ip_names[i] = ip_names[i];
}
} else {
request->peer_info.san_names.ip_names = nullptr;
}
}
void PendingVerifierRequestDestroy(
grpc_tls_custom_verification_check_request* request) {
GPR_ASSERT(request != nullptr);
if (request->peer_info.common_name != nullptr) {
gpr_free(const_cast<char*>(request->peer_info.common_name));
}
if (request->peer_info.san_names.uri_names_size > 0) {
for (size_t i = 0; i < request->peer_info.san_names.uri_names_size; ++i) {
gpr_free(request->peer_info.san_names.uri_names[i]);
}
delete[] request->peer_info.san_names.uri_names;
}
if (request->peer_info.san_names.dns_names_size > 0) {
for (size_t i = 0; i < request->peer_info.san_names.dns_names_size; ++i) {
gpr_free(request->peer_info.san_names.dns_names[i]);
}
delete[] request->peer_info.san_names.dns_names;
}
if (request->peer_info.san_names.email_names_size > 0) {
for (size_t i = 0; i < request->peer_info.san_names.email_names_size; ++i) {
gpr_free(request->peer_info.san_names.email_names[i]);
}
delete[] request->peer_info.san_names.email_names;
}
if (request->peer_info.san_names.ip_names_size > 0) {
for (size_t i = 0; i < request->peer_info.san_names.ip_names_size; ++i) {
gpr_free(request->peer_info.san_names.ip_names[i]);
}
delete[] request->peer_info.san_names.ip_names;
}
if (request->peer_info.peer_cert != nullptr) {
gpr_free(const_cast<char*>(request->peer_info.peer_cert));
}
if (request->peer_info.peer_cert_full_chain != nullptr) {
gpr_free(const_cast<char*>(request->peer_info.peer_cert_full_chain));
}
}
tsi_ssl_pem_key_cert_pair* ConvertToTsiPemKeyCertPair(
const PemKeyCertPairList& cert_pair_list) {
tsi_ssl_pem_key_cert_pair* tsi_pairs = nullptr;
@ -116,7 +266,6 @@ TlsChannelSecurityConnector::TlsChannelSecurityConnector(
if (ssl_session_cache_ != nullptr) {
tsi_ssl_session_cache_ref(ssl_session_cache_);
}
check_arg_ = ServerAuthorizationCheckArgCreate(this);
absl::string_view host;
absl::string_view port;
SplitHostPort(target_name, &host, &port);
@ -164,9 +313,6 @@ TlsChannelSecurityConnector::~TlsChannelSecurityConnector() {
if (client_handshaker_factory_ != nullptr) {
tsi_ssl_client_handshaker_factory_unref(client_handshaker_factory_);
}
if (check_arg_ != nullptr) {
ServerAuthorizationCheckArgDestroy(check_arg_);
}
}
void TlsChannelSecurityConnector::add_handshakers(
@ -205,121 +351,67 @@ void TlsChannelSecurityConnector::check_peer(
}
*auth_context =
grpc_ssl_peer_to_auth_context(&peer, GRPC_TLS_TRANSPORT_SECURITY_TYPE);
if (options_->server_verification_option() == GRPC_TLS_SERVER_VERIFICATION) {
/* Do the default host name check if specifying the target name. */
error = internal::TlsCheckHostName(target_name, &peer);
if (error != GRPC_ERROR_NONE) {
ExecCtx::Run(DEBUG_LOCATION, on_peer_checked, error);
tsi_peer_destruct(&peer);
return;
}
GPR_ASSERT(options_->certificate_verifier() != nullptr);
auto* pending_request = new ChannelPendingVerifierRequest(
Ref(), on_peer_checked, peer, target_name);
{
MutexLock lock(&verifier_request_map_mu_);
pending_verifier_requests_.emplace(on_peer_checked, pending_request);
}
/* Do the custom server authorization check, if specified by the user. */
const grpc_tls_server_authorization_check_config* config =
options_->server_authorization_check_config();
/* If server authorization config is not null, use it to perform
* server authorization check. */
if (config != 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_zalloc(p->value.length + 1));
memcpy(peer_pem, p->value.data, p->value.length);
GPR_ASSERT(check_arg_ != nullptr);
check_arg_->peer_cert = check_arg_->peer_cert == nullptr
? gpr_strdup(peer_pem)
: check_arg_->peer_cert;
check_arg_->target_name = check_arg_->target_name == nullptr
? gpr_strdup(target_name)
: check_arg_->target_name;
on_peer_checked_ = on_peer_checked;
gpr_free(peer_pem);
const tsi_peer_property* chain = tsi_peer_get_property_by_name(
&peer, TSI_X509_PEM_CERT_CHAIN_PROPERTY);
if (chain != nullptr) {
char* peer_pem_chain =
static_cast<char*>(gpr_zalloc(chain->value.length + 1));
memcpy(peer_pem_chain, chain->value.data, chain->value.length);
check_arg_->peer_cert_full_chain =
check_arg_->peer_cert_full_chain == nullptr
? gpr_strdup(peer_pem_chain)
: check_arg_->peer_cert_full_chain;
gpr_free(peer_pem_chain);
}
// TODO(zhenlian) - This should be cleaned up as part of the custom
// verification changes. Fill in the subject alternative names
std::vector<char*> subject_alternative_names;
for (size_t i = 0; i < peer.property_count; i++) {
const tsi_peer_property* prop = &peer.properties[i];
if (strcmp(prop->name,
TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY) == 0) {
char* san = new char[prop->value.length + 1];
memcpy(san, prop->value.data, prop->value.length);
san[prop->value.length] = '\0';
subject_alternative_names.emplace_back(san);
}
}
if (check_arg_->subject_alternative_names != nullptr) {
for (size_t i = 0; i < check_arg_->subject_alternative_names_size;
++i) {
delete[] check_arg_->subject_alternative_names[i];
}
delete[] check_arg_->subject_alternative_names;
}
check_arg_->subject_alternative_names_size =
subject_alternative_names.size();
if (subject_alternative_names.empty()) {
check_arg_->subject_alternative_names = nullptr;
pending_request->Start();
}
void TlsChannelSecurityConnector::cancel_check_peer(
grpc_closure* on_peer_checked, grpc_error_handle error) {
if (error != GRPC_ERROR_NONE) {
gpr_log(GPR_ERROR,
"TlsChannelSecurityConnector::cancel_check_peer error: %s",
grpc_error_std_string(error).c_str());
GRPC_ERROR_UNREF(error);
return;
}
auto* verifier = options_->certificate_verifier();
if (verifier != nullptr) {
grpc_tls_custom_verification_check_request* pending_verifier_request =
nullptr;
{
MutexLock lock(&verifier_request_map_mu_);
auto it = pending_verifier_requests_.find(on_peer_checked);
if (it != pending_verifier_requests_.end()) {
pending_verifier_request = it->second->request();
} else {
check_arg_->subject_alternative_names =
new char*[check_arg_->subject_alternative_names_size];
for (size_t i = 0; i < check_arg_->subject_alternative_names_size;
++i) {
check_arg_->subject_alternative_names[i] =
subject_alternative_names[i];
}
gpr_log(GPR_INFO,
"TlsChannelSecurityConnector::cancel_check_peer: no "
"corresponding pending request found");
}
int callback_status = config->Schedule(check_arg_);
/* Server authorization check is handled asynchronously. */
if (callback_status) {
tsi_peer_destruct(&peer);
return;
}
/* Server authorization check is handled synchronously. */
error = ProcessServerAuthorizationCheckResult(check_arg_);
}
if (pending_verifier_request != nullptr) {
verifier->Cancel(pending_verifier_request);
}
}
ExecCtx::Run(DEBUG_LOCATION, on_peer_checked, error);
tsi_peer_destruct(&peer);
}
int TlsChannelSecurityConnector::cmp(
const grpc_security_connector* other_sc) const {
auto* other = reinterpret_cast<const TlsChannelSecurityConnector*>(other_sc);
int c = channel_security_connector_cmp(other);
if (c != 0) {
return c;
}
return grpc_ssl_cmp_target_name(
if (c != 0) return c;
c = grpc_ssl_cmp_target_name(
target_name_.c_str(), other->target_name_.c_str(),
overridden_target_name_.c_str(), other->overridden_target_name_.c_str());
if (c != 0) return c;
return 0;
}
bool TlsChannelSecurityConnector::check_call_host(
absl::string_view host, grpc_auth_context* auth_context,
grpc_closure* /*on_call_host_checked*/, grpc_error_handle* error) {
if (options_->server_verification_option() ==
GRPC_TLS_SKIP_HOSTNAME_VERIFICATION ||
options_->server_verification_option() ==
GRPC_TLS_SKIP_ALL_SERVER_VERIFICATION) {
return true;
if (options_->check_call_host()) {
return grpc_ssl_check_call_host(host, target_name_.c_str(),
overridden_target_name_.c_str(),
auth_context, error);
}
return grpc_ssl_check_call_host(host, target_name_.c_str(),
overridden_target_name_.c_str(), auth_context,
error);
return true;
}
void TlsChannelSecurityConnector::cancel_check_call_host(
@ -369,13 +461,61 @@ void TlsChannelSecurityConnector::TlsChannelCertificateWatcher::OnError(
GRPC_ERROR_UNREF(identity_cert_error);
}
TlsChannelSecurityConnector::ChannelPendingVerifierRequest::
ChannelPendingVerifierRequest(
RefCountedPtr<TlsChannelSecurityConnector> security_connector,
grpc_closure* on_peer_checked, tsi_peer peer, const char* target_name)
: security_connector_(std::move(security_connector)),
on_peer_checked_(on_peer_checked) {
PendingVerifierRequestInit(target_name, peer, &request_);
tsi_peer_destruct(&peer);
}
TlsChannelSecurityConnector::ChannelPendingVerifierRequest::
~ChannelPendingVerifierRequest() {
PendingVerifierRequestDestroy(&request_);
}
void TlsChannelSecurityConnector::ChannelPendingVerifierRequest::Start() {
absl::Status sync_status;
grpc_tls_certificate_verifier* verifier =
security_connector_->options_->certificate_verifier();
bool is_done = verifier->Verify(
&request_,
absl::bind_front(&ChannelPendingVerifierRequest::OnVerifyDone, this,
true),
&sync_status);
if (is_done) {
OnVerifyDone(false, sync_status);
}
}
void TlsChannelSecurityConnector::ChannelPendingVerifierRequest::OnVerifyDone(
bool run_callback_inline, absl::Status status) {
{
MutexLock lock(&security_connector_->verifier_request_map_mu_);
security_connector_->pending_verifier_requests_.erase(on_peer_checked_);
}
grpc_error_handle error = GRPC_ERROR_NONE;
if (!status.ok()) {
error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(
absl::StrCat("Custom verification check failed with error: ",
status.ToString())
.c_str());
}
if (run_callback_inline) {
Closure::Run(DEBUG_LOCATION, on_peer_checked_, error);
} else {
ExecCtx::Run(DEBUG_LOCATION, on_peer_checked_, error);
}
delete this;
}
// TODO(ZhenLian): implement the logic to signal waiting handshakers once
// BlockOnInitialCredentialHandshaker is implemented.
grpc_security_status
TlsChannelSecurityConnector::UpdateHandshakerFactoryLocked() {
bool skip_server_certificate_verification =
options_->server_verification_option() ==
GRPC_TLS_SKIP_ALL_SERVER_VERIFICATION;
bool skip_server_certificate_verification = !options_->verify_server_cert();
/* Free the client handshaker factory if exists. */
if (client_handshaker_factory_ != nullptr) {
tsi_ssl_client_handshaker_factory_unref(client_handshaker_factory_);
@ -406,79 +546,6 @@ TlsChannelSecurityConnector::UpdateHandshakerFactoryLocked() {
return status;
}
void TlsChannelSecurityConnector::ServerAuthorizationCheckDone(
grpc_tls_server_authorization_check_arg* arg) {
GPR_ASSERT(arg != nullptr);
ExecCtx exec_ctx;
grpc_error_handle error = ProcessServerAuthorizationCheckResult(arg);
TlsChannelSecurityConnector* connector =
static_cast<TlsChannelSecurityConnector*>(arg->cb_user_data);
ExecCtx::Run(DEBUG_LOCATION, connector->on_peer_checked_, error);
}
grpc_error_handle
TlsChannelSecurityConnector::ProcessServerAuthorizationCheckResult(
grpc_tls_server_authorization_check_arg* arg) {
grpc_error_handle error = GRPC_ERROR_NONE;
/* Server authorization check is cancelled by caller. */
if (arg->status == GRPC_STATUS_CANCELLED) {
error = GRPC_ERROR_CREATE_FROM_CPP_STRING(
absl::StrCat("Server authorization check is cancelled by the caller "
"with error: ",
arg->error_details->error_details()));
} else if (arg->status == GRPC_STATUS_OK) {
/* Server authorization check completed successfully but returned check
* failure. */
if (!arg->success) {
error = GRPC_ERROR_CREATE_FROM_CPP_STRING(
absl::StrCat("Server authorization check failed with error: ",
arg->error_details->error_details()));
}
/* Server authorization check did not complete correctly. */
} else {
error = GRPC_ERROR_CREATE_FROM_CPP_STRING(absl::StrCat(
"Server authorization check did not finish correctly with error: ",
arg->error_details->error_details()));
}
return error;
}
grpc_tls_server_authorization_check_arg*
TlsChannelSecurityConnector::ServerAuthorizationCheckArgCreate(
void* user_data) {
grpc_tls_server_authorization_check_arg* arg =
new grpc_tls_server_authorization_check_arg();
arg->target_name = nullptr;
arg->peer_cert = nullptr;
arg->peer_cert_full_chain = nullptr;
arg->subject_alternative_names = nullptr;
arg->subject_alternative_names_size = 0;
arg->error_details = new grpc_tls_error_details();
arg->cb = ServerAuthorizationCheckDone;
arg->cb_user_data = user_data;
arg->status = GRPC_STATUS_OK;
return arg;
}
void TlsChannelSecurityConnector::ServerAuthorizationCheckArgDestroy(
grpc_tls_server_authorization_check_arg* arg) {
if (arg == nullptr) {
return;
}
gpr_free(const_cast<char*>(arg->target_name));
gpr_free(const_cast<char*>(arg->peer_cert));
gpr_free(const_cast<char*>(arg->peer_cert_full_chain));
for (size_t i = 0; i < arg->subject_alternative_names_size; ++i) {
delete[] arg->subject_alternative_names[i];
}
delete[] arg->subject_alternative_names;
delete arg->error_details;
if (arg->destroy_context != nullptr) {
arg->destroy_context(arg->context);
}
delete arg;
}
// -------------------server security connector-------------------
RefCountedPtr<grpc_server_security_connector>
TlsServerSecurityConnector::CreateTlsServerSecurityConnector(
@ -559,16 +626,63 @@ void TlsServerSecurityConnector::check_peer(
RefCountedPtr<grpc_auth_context>* auth_context,
grpc_closure* on_peer_checked) {
grpc_error_handle error = grpc_ssl_check_alpn(&peer);
if (error != GRPC_ERROR_NONE) {
ExecCtx::Run(DEBUG_LOCATION, on_peer_checked, error);
tsi_peer_destruct(&peer);
return;
}
*auth_context =
grpc_ssl_peer_to_auth_context(&peer, GRPC_TLS_TRANSPORT_SECURITY_TYPE);
tsi_peer_destruct(&peer);
ExecCtx::Run(DEBUG_LOCATION, on_peer_checked, error);
if (options_->certificate_verifier() != nullptr) {
auto* pending_request =
new ServerPendingVerifierRequest(Ref(), on_peer_checked, peer);
{
MutexLock lock(&verifier_request_map_mu_);
pending_verifier_requests_.emplace(on_peer_checked, pending_request);
}
pending_request->Start();
} else {
tsi_peer_destruct(&peer);
ExecCtx::Run(DEBUG_LOCATION, on_peer_checked, error);
}
}
void TlsServerSecurityConnector::cancel_check_peer(
grpc_closure* on_peer_checked, grpc_error_handle error) {
if (error != GRPC_ERROR_NONE) {
gpr_log(GPR_ERROR,
"TlsServerSecurityConnector::cancel_check_peer error: %s",
grpc_error_std_string(error).c_str());
GRPC_ERROR_UNREF(error);
return;
}
auto* verifier = options_->certificate_verifier();
if (verifier != nullptr) {
grpc_tls_custom_verification_check_request* pending_verifier_request =
nullptr;
{
MutexLock lock(&verifier_request_map_mu_);
auto it = pending_verifier_requests_.find(on_peer_checked);
if (it != pending_verifier_requests_.end()) {
pending_verifier_request = it->second->request();
} else {
gpr_log(GPR_INFO,
"TlsServerSecurityConnector::cancel_check_peer: no "
"corresponding pending request found");
}
}
if (pending_verifier_request != nullptr) {
verifier->Cancel(pending_verifier_request);
}
}
}
int TlsServerSecurityConnector::cmp(
const grpc_security_connector* other) const {
return server_security_connector_cmp(
static_cast<const grpc_server_security_connector*>(other));
const grpc_security_connector* other_sc) const {
auto* other = reinterpret_cast<const TlsServerSecurityConnector*>(other_sc);
int c = server_security_connector_cmp(other);
if (c != 0) return c;
return 0;
}
void TlsServerSecurityConnector::TlsServerCertificateWatcher::
@ -617,6 +731,55 @@ void TlsServerSecurityConnector::TlsServerCertificateWatcher::OnError(
GRPC_ERROR_UNREF(identity_cert_error);
}
TlsServerSecurityConnector::ServerPendingVerifierRequest::
ServerPendingVerifierRequest(
RefCountedPtr<TlsServerSecurityConnector> security_connector,
grpc_closure* on_peer_checked, tsi_peer peer)
: security_connector_(std::move(security_connector)),
on_peer_checked_(on_peer_checked) {
PendingVerifierRequestInit(nullptr, peer, &request_);
tsi_peer_destruct(&peer);
}
TlsServerSecurityConnector::ServerPendingVerifierRequest::
~ServerPendingVerifierRequest() {
PendingVerifierRequestDestroy(&request_);
}
void TlsServerSecurityConnector::ServerPendingVerifierRequest::Start() {
absl::Status sync_status;
grpc_tls_certificate_verifier* verifier =
security_connector_->options_->certificate_verifier();
bool is_done = verifier->Verify(
&request_,
absl::bind_front(&ServerPendingVerifierRequest::OnVerifyDone, this, true),
&sync_status);
if (is_done) {
OnVerifyDone(false, sync_status);
}
}
void TlsServerSecurityConnector::ServerPendingVerifierRequest::OnVerifyDone(
bool run_callback_inline, absl::Status status) {
{
MutexLock lock(&security_connector_->verifier_request_map_mu_);
security_connector_->pending_verifier_requests_.erase(on_peer_checked_);
}
grpc_error_handle error = GRPC_ERROR_NONE;
if (!status.ok()) {
error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(
absl::StrCat("Custom verification check failed with error: ",
status.ToString())
.c_str());
}
if (run_callback_inline) {
Closure::Run(DEBUG_LOCATION, on_peer_checked_, error);
} else {
ExecCtx::Run(DEBUG_LOCATION, on_peer_checked_, error);
}
delete this;
}
// TODO(ZhenLian): implement the logic to signal waiting handshakers once
// BlockOnInitialCredentialHandshaker is implemented.
grpc_security_status
@ -650,18 +813,4 @@ TlsServerSecurityConnector::UpdateHandshakerFactoryLocked() {
return status;
}
namespace internal {
grpc_error_handle TlsCheckHostName(const char* peer_name,
const tsi_peer* peer) {
/* Check the peer name if specified. */
if (peer_name != nullptr && !grpc_ssl_host_matches_name(peer, peer_name)) {
return GRPC_ERROR_CREATE_FROM_CPP_STRING(
absl::StrCat("Peer name ", peer_name, " is not in peer certificate"));
}
return GRPC_ERROR_NONE;
}
} // namespace internal
} // namespace grpc_core

View File

@ -21,6 +21,8 @@
#include <grpc/support/port_platform.h>
#include "absl/status/status.h"
#include "src/core/lib/gprpp/sync.h"
#include "src/core/lib/security/context/security_context.h"
#include "src/core/lib/security/credentials/tls/grpc_tls_certificate_provider.h"
@ -58,11 +60,8 @@ class TlsChannelSecurityConnector final
RefCountedPtr<grpc_auth_context>* auth_context,
grpc_closure* on_peer_checked) override;
void cancel_check_peer(grpc_closure* /*on_peer_checked*/,
grpc_error_handle error) override {
// TODO(ZhenLian): call verifier->cancel() once the verifier is ready.
GRPC_ERROR_UNREF(error);
}
void cancel_check_peer(grpc_closure* on_peer_checked,
grpc_error_handle error) override;
int cmp(const grpc_security_connector* other_sc) const override;
@ -108,43 +107,51 @@ class TlsChannelSecurityConnector final
TlsChannelSecurityConnector* security_connector_ = nullptr;
};
// Use "new" to create a new instance, and no need to delete it later, since
// it will be self-destroyed in |OnVerifyDone|.
class ChannelPendingVerifierRequest {
public:
ChannelPendingVerifierRequest(
RefCountedPtr<TlsChannelSecurityConnector> security_connector,
grpc_closure* on_peer_checked, tsi_peer peer, const char* target_name);
~ChannelPendingVerifierRequest();
void Start();
grpc_tls_custom_verification_check_request* request() { return &request_; }
private:
void OnVerifyDone(bool run_callback_inline, absl::Status status);
// The request will keep a reference of the security connector to make sure
// it won't be destroyed while the request is still ongoing.
RefCountedPtr<TlsChannelSecurityConnector> security_connector_;
grpc_tls_custom_verification_check_request request_;
grpc_closure* on_peer_checked_;
};
// Updates |client_handshaker_factory_| when the certificates that
// |certificate_watcher_| is watching get updated.
grpc_security_status UpdateHandshakerFactoryLocked()
ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_);
// gRPC-provided callback executed by application, which servers to bring the
// control back to gRPC core.
static void ServerAuthorizationCheckDone(
grpc_tls_server_authorization_check_arg* arg);
// A util function to process server authorization check result.
static grpc_error_handle ProcessServerAuthorizationCheckResult(
grpc_tls_server_authorization_check_arg* arg);
// A util function to create a server authorization check arg instance.
static grpc_tls_server_authorization_check_arg*
ServerAuthorizationCheckArgCreate(void* user_data);
// A util function to destroy a server authorization check arg instance.
static void ServerAuthorizationCheckArgDestroy(
grpc_tls_server_authorization_check_arg* arg);
Mutex mu_;
// We need a separate mutex for |pending_verifier_requests_|, otherwise there
// would be deadlock errors.
Mutex verifier_request_map_mu_;
RefCountedPtr<grpc_tls_credentials_options> options_;
grpc_tls_certificate_distributor::TlsCertificatesWatcherInterface*
certificate_watcher_ = nullptr;
grpc_closure* on_peer_checked_ = nullptr;
std::string target_name_;
std::string overridden_target_name_;
grpc_tls_server_authorization_check_arg* check_arg_ = nullptr;
Mutex mu_;
tsi_ssl_client_handshaker_factory* client_handshaker_factory_
ABSL_GUARDED_BY(mu_) = nullptr;
tsi_ssl_session_cache* ssl_session_cache_ ABSL_GUARDED_BY(mu_) = nullptr;
absl::optional<absl::string_view> pem_root_certs_ ABSL_GUARDED_BY(mu_);
absl::optional<PemKeyCertPairList> pem_key_cert_pair_list_
ABSL_GUARDED_BY(mu_);
std::map<grpc_closure* /*on_peer_checked*/, ChannelPendingVerifierRequest*>
pending_verifier_requests_ ABSL_GUARDED_BY(verifier_request_map_mu_);
};
// Server security connector using TLS as transport security protocol.
@ -170,10 +177,7 @@ class TlsServerSecurityConnector final : public grpc_server_security_connector {
grpc_closure* on_peer_checked) override;
void cancel_check_peer(grpc_closure* /*on_peer_checked*/,
grpc_error_handle error) override {
// TODO(ZhenLian): call verifier->cancel() once the verifier is ready.
GRPC_ERROR_UNREF(error);
}
grpc_error_handle error) override;
int cmp(const grpc_security_connector* other) const override;
@ -205,6 +209,7 @@ class TlsServerSecurityConnector final : public grpc_server_security_connector {
void OnCertificatesChanged(
absl::optional<absl::string_view> root_certs,
absl::optional<PemKeyCertPairList> key_cert_pairs) override;
void OnError(grpc_error_handle root_cert_error,
grpc_error_handle identity_cert_error) override;
@ -212,32 +217,50 @@ class TlsServerSecurityConnector final : public grpc_server_security_connector {
TlsServerSecurityConnector* security_connector_ = nullptr;
};
// Use "new" to create a new instance, and no need to delete it later, since
// it will be self-destroyed in |OnVerifyDone|.
class ServerPendingVerifierRequest {
public:
ServerPendingVerifierRequest(
RefCountedPtr<TlsServerSecurityConnector> security_connector,
grpc_closure* on_peer_checked, tsi_peer peer);
~ServerPendingVerifierRequest();
void Start();
grpc_tls_custom_verification_check_request* request() { return &request_; }
private:
void OnVerifyDone(bool run_callback_inline, absl::Status status);
// The request will keep a reference of the security connector to make sure
// it won't be destroyed while the request is still ongoing.
RefCountedPtr<TlsServerSecurityConnector> security_connector_;
grpc_tls_custom_verification_check_request request_;
grpc_closure* on_peer_checked_;
};
// Updates |server_handshaker_factory_| when the certificates that
// |certificate_watcher_| is watching get updated.
grpc_security_status UpdateHandshakerFactoryLocked()
ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_);
Mutex mu_;
// We need a separate mutex for |pending_verifier_requests_|, otherwise there
// would be deadlock errors.
Mutex verifier_request_map_mu_;
RefCountedPtr<grpc_tls_credentials_options> options_;
grpc_tls_certificate_distributor::TlsCertificatesWatcherInterface*
certificate_watcher_ = nullptr;
Mutex mu_;
tsi_ssl_server_handshaker_factory* server_handshaker_factory_
ABSL_GUARDED_BY(mu_) = nullptr;
absl::optional<absl::string_view> pem_root_certs_ ABSL_GUARDED_BY(mu_);
absl::optional<PemKeyCertPairList> pem_key_cert_pair_list_
ABSL_GUARDED_BY(mu_);
std::map<grpc_closure* /*on_peer_checked*/, ServerPendingVerifierRequest*>
pending_verifier_requests_ ABSL_GUARDED_BY(verifier_request_map_mu_);
};
// ---- Functions below are exposed for testing only -----------------------
namespace internal {
// TlsCheckHostName checks if |peer_name| matches the identity information
// contained in |peer|. This is AKA hostname check.
grpc_error_handle TlsCheckHostName(const char* peer_name, const tsi_peer* peer);
} // namespace internal
} // namespace grpc_core
#endif // GRPC_CORE_LIB_SECURITY_SECURITY_CONNECTOR_TLS_TLS_SECURITY_CONNECTOR_H

View File

@ -0,0 +1,244 @@
//
// Copyright 2021 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 "absl/container/inlined_vector.h"
#include "absl/status/status.h"
#include <grpc/grpc_security.h>
#include <grpc/support/alloc.h>
#include <grpc/support/string_util.h>
#include <grpcpp/security/tls_certificate_verifier.h>
namespace grpc {
namespace experimental {
static internal::GrpcLibraryInitializer g_gli_initializer;
TlsCustomVerificationCheckRequest::TlsCustomVerificationCheckRequest(
grpc_tls_custom_verification_check_request* request)
: c_request_(request) {
GPR_ASSERT(c_request_ != nullptr);
}
grpc::string_ref TlsCustomVerificationCheckRequest::target_name() const {
return c_request_->target_name != nullptr ? c_request_->target_name : "";
}
grpc::string_ref TlsCustomVerificationCheckRequest::peer_cert() const {
return c_request_->peer_info.peer_cert != nullptr
? c_request_->peer_info.peer_cert
: "";
}
grpc::string_ref TlsCustomVerificationCheckRequest::peer_cert_full_chain()
const {
return c_request_->peer_info.peer_cert_full_chain != nullptr
? c_request_->peer_info.peer_cert_full_chain
: "";
}
grpc::string_ref TlsCustomVerificationCheckRequest::common_name() const {
return c_request_->peer_info.common_name != nullptr
? c_request_->peer_info.common_name
: "";
}
std::vector<grpc::string_ref> TlsCustomVerificationCheckRequest::uri_names()
const {
std::vector<grpc::string_ref> uri_names;
for (size_t i = 0; i < c_request_->peer_info.san_names.uri_names_size; ++i) {
uri_names.emplace_back(c_request_->peer_info.san_names.uri_names[i]);
}
return uri_names;
}
std::vector<grpc::string_ref> TlsCustomVerificationCheckRequest::dns_names()
const {
std::vector<grpc::string_ref> dns_names;
for (size_t i = 0; i < c_request_->peer_info.san_names.dns_names_size; ++i) {
dns_names.emplace_back(c_request_->peer_info.san_names.dns_names[i]);
}
return dns_names;
}
std::vector<grpc::string_ref> TlsCustomVerificationCheckRequest::email_names()
const {
std::vector<grpc::string_ref> email_names;
for (size_t i = 0; i < c_request_->peer_info.san_names.email_names_size;
++i) {
email_names.emplace_back(c_request_->peer_info.san_names.email_names[i]);
}
return email_names;
}
std::vector<grpc::string_ref> TlsCustomVerificationCheckRequest::ip_names()
const {
std::vector<grpc::string_ref> ip_names;
for (size_t i = 0; i < c_request_->peer_info.san_names.ip_names_size; ++i) {
ip_names.emplace_back(c_request_->peer_info.san_names.ip_names[i]);
}
return ip_names;
}
CertificateVerifier::CertificateVerifier(grpc_tls_certificate_verifier* v)
: verifier_(v) {
g_gli_initializer.summon();
}
CertificateVerifier::~CertificateVerifier() {
grpc_tls_certificate_verifier_release(verifier_);
}
bool CertificateVerifier::Verify(TlsCustomVerificationCheckRequest* request,
std::function<void(grpc::Status)> callback,
grpc::Status* sync_status) {
GPR_ASSERT(request != nullptr);
GPR_ASSERT(request->c_request() != nullptr);
{
internal::MutexLock lock(&mu_);
request_map_.emplace(request->c_request(), std::move(callback));
}
grpc_status_code status_code = GRPC_STATUS_OK;
char* error_details = nullptr;
bool is_done = grpc_tls_certificate_verifier_verify(
verifier_, request->c_request(), &AsyncCheckDone, this, &status_code,
&error_details);
if (is_done) {
if (status_code != GRPC_STATUS_OK) {
*sync_status = grpc::Status(static_cast<grpc::StatusCode>(status_code),
error_details);
}
internal::MutexLock lock(&mu_);
request_map_.erase(request->c_request());
}
gpr_free(error_details);
return is_done;
}
void CertificateVerifier::Cancel(TlsCustomVerificationCheckRequest* request) {
GPR_ASSERT(request != nullptr);
GPR_ASSERT(request->c_request() != nullptr);
grpc_tls_certificate_verifier_cancel(verifier_, request->c_request());
}
void CertificateVerifier::AsyncCheckDone(
grpc_tls_custom_verification_check_request* request, void* callback_arg,
grpc_status_code status, const char* error_details) {
auto* self = static_cast<CertificateVerifier*>(callback_arg);
std::function<void(grpc::Status)> callback;
{
internal::MutexLock lock(&self->mu_);
auto it = self->request_map_.find(request);
if (it != self->request_map_.end()) {
callback = std::move(it->second);
self->request_map_.erase(it);
}
}
if (callback != nullptr) {
grpc::Status return_status;
if (status != GRPC_STATUS_OK) {
return_status =
grpc::Status(static_cast<grpc::StatusCode>(status), error_details);
}
callback(return_status);
}
}
ExternalCertificateVerifier::ExternalCertificateVerifier() {
base_ = new grpc_tls_certificate_verifier_external();
base_->user_data = this;
base_->verify = VerifyInCoreExternalVerifier;
base_->cancel = CancelInCoreExternalVerifier;
base_->destruct = DestructInCoreExternalVerifier;
}
ExternalCertificateVerifier::~ExternalCertificateVerifier() { delete base_; }
int ExternalCertificateVerifier::VerifyInCoreExternalVerifier(
void* user_data, grpc_tls_custom_verification_check_request* request,
grpc_tls_on_custom_verification_check_done_cb callback, void* callback_arg,
grpc_status_code* sync_status, char** sync_error_details) {
auto* self = static_cast<ExternalCertificateVerifier*>(user_data);
TlsCustomVerificationCheckRequest* cpp_request = nullptr;
{
internal::MutexLock lock(&self->mu_);
auto pair = self->request_map_.emplace(
request, AsyncRequestState(callback, callback_arg, request));
GPR_ASSERT(pair.second);
cpp_request = &pair.first->second.cpp_request;
}
grpc::Status sync_current_verifier_status;
bool is_done = self->Verify(
cpp_request,
[self, request](grpc::Status status) {
grpc_tls_on_custom_verification_check_done_cb callback = nullptr;
void* callback_arg = nullptr;
{
internal::MutexLock lock(&self->mu_);
auto it = self->request_map_.find(request);
if (it != self->request_map_.end()) {
callback = it->second.callback;
callback_arg = it->second.callback_arg;
self->request_map_.erase(it);
}
}
if (callback != nullptr) {
callback(request, callback_arg,
static_cast<grpc_status_code>(status.error_code()),
status.error_message().c_str());
}
},
&sync_current_verifier_status);
if (is_done) {
if (!sync_current_verifier_status.ok()) {
*sync_status = static_cast<grpc_status_code>(
sync_current_verifier_status.error_code());
*sync_error_details =
gpr_strdup(sync_current_verifier_status.error_message().c_str());
}
internal::MutexLock lock(&self->mu_);
self->request_map_.erase(request);
}
return is_done;
}
void ExternalCertificateVerifier::CancelInCoreExternalVerifier(
void* user_data, grpc_tls_custom_verification_check_request* request) {
auto* self = static_cast<ExternalCertificateVerifier*>(user_data);
TlsCustomVerificationCheckRequest* cpp_request = nullptr;
{
internal::MutexLock lock(&self->mu_);
auto it = self->request_map_.find(request);
if (it != self->request_map_.end()) {
cpp_request = &it->second.cpp_request;
}
}
if (cpp_request != nullptr) {
self->Cancel(cpp_request);
}
}
void ExternalCertificateVerifier::DestructInCoreExternalVerifier(
void* user_data) {
auto* self = static_cast<ExternalCertificateVerifier*>(user_data);
delete self;
}
HostNameCertificateVerifier::HostNameCertificateVerifier()
: CertificateVerifier(grpc_tls_certificate_verifier_host_name_create()) {}
} // namespace experimental
} // namespace grpc

View File

@ -22,109 +22,9 @@
#include <grpc/support/alloc.h>
#include <grpcpp/security/tls_credentials_options.h>
#include "src/cpp/common/tls_credentials_options_util.h"
namespace grpc {
namespace experimental {
/** gRPC TLS server authorization check arg API implementation **/
TlsServerAuthorizationCheckArg::TlsServerAuthorizationCheckArg(
grpc_tls_server_authorization_check_arg* arg)
: c_arg_(arg) {
GPR_ASSERT(c_arg_ != nullptr);
if (c_arg_->context != nullptr) {
gpr_log(GPR_ERROR, "c_arg context has already been set");
}
c_arg_->context = static_cast<void*>(this);
c_arg_->destroy_context = &TlsServerAuthorizationCheckArgDestroyContext;
}
TlsServerAuthorizationCheckArg::~TlsServerAuthorizationCheckArg() {}
void* TlsServerAuthorizationCheckArg::cb_user_data() const {
return c_arg_->cb_user_data;
}
int TlsServerAuthorizationCheckArg::success() const { return c_arg_->success; }
std::string TlsServerAuthorizationCheckArg::target_name() const {
std::string cpp_target_name(c_arg_->target_name);
return cpp_target_name;
}
std::string TlsServerAuthorizationCheckArg::peer_cert() const {
std::string cpp_peer_cert(c_arg_->peer_cert);
return cpp_peer_cert;
}
std::string TlsServerAuthorizationCheckArg::peer_cert_full_chain() const {
std::string cpp_peer_cert_full_chain(c_arg_->peer_cert_full_chain);
return cpp_peer_cert_full_chain;
}
grpc_status_code TlsServerAuthorizationCheckArg::status() const {
return c_arg_->status;
}
std::string TlsServerAuthorizationCheckArg::error_details() const {
return c_arg_->error_details->error_details();
}
void TlsServerAuthorizationCheckArg::set_cb_user_data(void* cb_user_data) {
c_arg_->cb_user_data = cb_user_data;
}
void TlsServerAuthorizationCheckArg::set_success(int success) {
c_arg_->success = success;
}
void TlsServerAuthorizationCheckArg::set_target_name(
const std::string& target_name) {
c_arg_->target_name = gpr_strdup(target_name.c_str());
}
void TlsServerAuthorizationCheckArg::set_peer_cert(
const std::string& peer_cert) {
c_arg_->peer_cert = gpr_strdup(peer_cert.c_str());
}
void TlsServerAuthorizationCheckArg::set_peer_cert_full_chain(
const std::string& peer_cert_full_chain) {
c_arg_->peer_cert_full_chain = gpr_strdup(peer_cert_full_chain.c_str());
}
void TlsServerAuthorizationCheckArg::set_status(grpc_status_code status) {
c_arg_->status = status;
}
void TlsServerAuthorizationCheckArg::set_error_details(
const std::string& error_details) {
c_arg_->error_details->set_error_details(error_details.c_str());
}
void TlsServerAuthorizationCheckArg::OnServerAuthorizationCheckDoneCallback() {
if (c_arg_->cb == nullptr) {
gpr_log(GPR_ERROR, "server authorizaton check arg callback API is nullptr");
return;
}
c_arg_->cb(c_arg_);
}
TlsServerAuthorizationCheckConfig::TlsServerAuthorizationCheckConfig(
std::shared_ptr<TlsServerAuthorizationCheckInterface>
server_authorization_check_interface)
: server_authorization_check_interface_(
std::move(server_authorization_check_interface)) {
c_config_ = grpc_tls_server_authorization_check_config_create(
nullptr, &TlsServerAuthorizationCheckConfigCSchedule,
&TlsServerAuthorizationCheckConfigCCancel, nullptr);
c_config_->set_context(static_cast<void*>(this));
}
TlsServerAuthorizationCheckConfig::~TlsServerAuthorizationCheckConfig() {
grpc_tls_server_authorization_check_config_release(c_config_);
}
TlsCredentialsOptions::TlsCredentialsOptions() {
c_credentials_options_ = grpc_tls_credentials_options_create();
}
@ -159,22 +59,27 @@ void TlsCredentialsOptions::set_identity_cert_name(
c_credentials_options_, identity_cert_name.c_str());
}
void TlsChannelCredentialsOptions::set_server_verification_option(
grpc_tls_server_verification_option server_verification_option) {
grpc_tls_credentials_options* options = c_credentials_options();
GPR_ASSERT(options != nullptr);
grpc_tls_credentials_options_set_server_verification_option(
options, server_verification_option);
void TlsCredentialsOptions::set_certificate_verifier(
std::shared_ptr<CertificateVerifier> certificate_verifier) {
certificate_verifier_ = std::move(certificate_verifier);
if (certificate_verifier_ != nullptr) {
grpc_tls_credentials_options_set_certificate_verifier(
c_credentials_options_, certificate_verifier_->c_verifier());
}
}
void TlsChannelCredentialsOptions::set_server_authorization_check_config(
std::shared_ptr<TlsServerAuthorizationCheckConfig> config) {
void TlsCredentialsOptions::set_check_call_host(bool check_call_host) {
grpc_tls_credentials_options* options = c_credentials_options();
GPR_ASSERT(options != nullptr);
if (config != nullptr) {
grpc_tls_credentials_options_set_server_authorization_check_config(
options, config->c_config());
}
grpc_tls_credentials_options_set_check_call_host(options, check_call_host);
}
void TlsChannelCredentialsOptions::set_verify_server_certs(
bool verify_server_certs) {
grpc_tls_credentials_options* options = c_credentials_options();
GPR_ASSERT(options != nullptr);
grpc_tls_credentials_options_set_verify_server_cert(options,
verify_server_certs);
}
void TlsServerCredentialsOptions::set_cert_request_type(

View File

@ -1,76 +0,0 @@
/*
*
* Copyright 2019 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/cpp/common/tls_credentials_options_util.h"
#include "absl/container/inlined_vector.h"
#include <grpcpp/security/tls_credentials_options.h>
namespace grpc {
namespace experimental {
/** The C schedule and cancel functions for the server authorization check
* config. They populate a C server authorization check arg with the result
* of a C++ server authorization check schedule/cancel API. **/
int TlsServerAuthorizationCheckConfigCSchedule(
void* /*config_user_data*/, grpc_tls_server_authorization_check_arg* arg) {
if (arg == nullptr || arg->config == nullptr ||
arg->config->context() == nullptr) {
gpr_log(GPR_ERROR,
"server authorization check arg was not properly initialized");
return 1;
}
TlsServerAuthorizationCheckConfig* cpp_config =
static_cast<TlsServerAuthorizationCheckConfig*>(arg->config->context());
TlsServerAuthorizationCheckArg* cpp_arg =
new TlsServerAuthorizationCheckArg(arg);
int schedule_result = cpp_config->Schedule(cpp_arg);
return schedule_result;
}
void TlsServerAuthorizationCheckConfigCCancel(
void* /*config_user_data*/, grpc_tls_server_authorization_check_arg* arg) {
if (arg == nullptr || arg->config == nullptr ||
arg->config->context() == nullptr) {
gpr_log(GPR_ERROR,
"server authorization check arg was not properly initialized");
return;
}
if (arg->context == nullptr) {
gpr_log(GPR_ERROR,
"server authorization check arg schedule has already completed");
return;
}
TlsServerAuthorizationCheckConfig* cpp_config =
static_cast<TlsServerAuthorizationCheckConfig*>(arg->config->context());
TlsServerAuthorizationCheckArg* cpp_arg =
static_cast<TlsServerAuthorizationCheckArg*>(arg->context);
cpp_config->Cancel(cpp_arg);
}
void TlsServerAuthorizationCheckArgDestroyContext(void* context) {
if (context != nullptr) {
TlsServerAuthorizationCheckArg* cpp_arg =
static_cast<TlsServerAuthorizationCheckArg*>(context);
delete cpp_arg;
}
}
} // namespace experimental
} // namespace grpc

View File

@ -1,44 +0,0 @@
/*
*
* Copyright 2019 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.
*
*/
#ifndef GRPC_INTERNAL_CPP_COMMON_TLS_CREDENTIALS_OPTIONS_UTIL_H
#define GRPC_INTERNAL_CPP_COMMON_TLS_CREDENTIALS_OPTIONS_UTIL_H
#include <grpc/grpc_security.h>
#include <grpcpp/security/tls_credentials_options.h>
#include "src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h"
namespace grpc {
namespace experimental {
/** The following 2 functions convert the user-provided schedule or cancel
* functions into C style schedule or cancel functions. These are internal
* functions, not meant to be accessed by the user. **/
int TlsServerAuthorizationCheckConfigCSchedule(
void* config_user_data, grpc_tls_server_authorization_check_arg* arg);
void TlsServerAuthorizationCheckConfigCCancel(
void* config_user_data, grpc_tls_server_authorization_check_arg* arg);
void TlsServerAuthorizationCheckArgDestroyContext(void* context);
} // namespace experimental
} // namespace grpc
#endif // GRPC_INTERNAL_CPP_COMMON_TLS_CREDENTIALS_OPTIONS_UTIL_H

View File

@ -549,6 +549,7 @@ CORE_SOURCE_FILES = [
'src/core/lib/security/credentials/ssl/ssl_credentials.cc',
'src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.cc',
'src/core/lib/security/credentials/tls/grpc_tls_certificate_provider.cc',
'src/core/lib/security/credentials/tls/grpc_tls_certificate_verifier.cc',
'src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc',
'src/core/lib/security/credentials/tls/tls_credentials.cc',
'src/core/lib/security/credentials/tls/tls_utils.cc',

View File

@ -172,16 +172,14 @@ grpc_tls_certificate_provider_static_data_create_type grpc_tls_certificate_provi
grpc_tls_certificate_provider_file_watcher_create_type grpc_tls_certificate_provider_file_watcher_create_import;
grpc_tls_certificate_provider_release_type grpc_tls_certificate_provider_release_import;
grpc_tls_credentials_options_create_type grpc_tls_credentials_options_create_import;
grpc_tls_credentials_options_set_cert_request_type_type grpc_tls_credentials_options_set_cert_request_type_import;
grpc_tls_credentials_options_set_server_verification_option_type grpc_tls_credentials_options_set_server_verification_option_import;
grpc_tls_credentials_options_set_certificate_provider_type grpc_tls_credentials_options_set_certificate_provider_import;
grpc_tls_credentials_options_watch_root_certs_type grpc_tls_credentials_options_watch_root_certs_import;
grpc_tls_credentials_options_set_root_cert_name_type grpc_tls_credentials_options_set_root_cert_name_import;
grpc_tls_credentials_options_watch_identity_key_cert_pairs_type grpc_tls_credentials_options_watch_identity_key_cert_pairs_import;
grpc_tls_credentials_options_set_identity_cert_name_type grpc_tls_credentials_options_set_identity_cert_name_import;
grpc_tls_credentials_options_set_server_authorization_check_config_type grpc_tls_credentials_options_set_server_authorization_check_config_import;
grpc_tls_server_authorization_check_config_create_type grpc_tls_server_authorization_check_config_create_import;
grpc_tls_server_authorization_check_config_release_type grpc_tls_server_authorization_check_config_release_import;
grpc_tls_credentials_options_set_cert_request_type_type grpc_tls_credentials_options_set_cert_request_type_import;
grpc_tls_credentials_options_set_verify_server_cert_type grpc_tls_credentials_options_set_verify_server_cert_import;
grpc_tls_credentials_options_set_check_call_host_type grpc_tls_credentials_options_set_check_call_host_import;
grpc_xds_credentials_create_type grpc_xds_credentials_create_import;
grpc_xds_server_credentials_create_type grpc_xds_server_credentials_create_import;
grpc_authorization_policy_provider_static_data_create_type grpc_authorization_policy_provider_static_data_create_import;
@ -462,16 +460,14 @@ void grpc_rb_load_imports(HMODULE library) {
grpc_tls_certificate_provider_file_watcher_create_import = (grpc_tls_certificate_provider_file_watcher_create_type) GetProcAddress(library, "grpc_tls_certificate_provider_file_watcher_create");
grpc_tls_certificate_provider_release_import = (grpc_tls_certificate_provider_release_type) GetProcAddress(library, "grpc_tls_certificate_provider_release");
grpc_tls_credentials_options_create_import = (grpc_tls_credentials_options_create_type) GetProcAddress(library, "grpc_tls_credentials_options_create");
grpc_tls_credentials_options_set_cert_request_type_import = (grpc_tls_credentials_options_set_cert_request_type_type) GetProcAddress(library, "grpc_tls_credentials_options_set_cert_request_type");
grpc_tls_credentials_options_set_server_verification_option_import = (grpc_tls_credentials_options_set_server_verification_option_type) GetProcAddress(library, "grpc_tls_credentials_options_set_server_verification_option");
grpc_tls_credentials_options_set_certificate_provider_import = (grpc_tls_credentials_options_set_certificate_provider_type) GetProcAddress(library, "grpc_tls_credentials_options_set_certificate_provider");
grpc_tls_credentials_options_watch_root_certs_import = (grpc_tls_credentials_options_watch_root_certs_type) GetProcAddress(library, "grpc_tls_credentials_options_watch_root_certs");
grpc_tls_credentials_options_set_root_cert_name_import = (grpc_tls_credentials_options_set_root_cert_name_type) GetProcAddress(library, "grpc_tls_credentials_options_set_root_cert_name");
grpc_tls_credentials_options_watch_identity_key_cert_pairs_import = (grpc_tls_credentials_options_watch_identity_key_cert_pairs_type) GetProcAddress(library, "grpc_tls_credentials_options_watch_identity_key_cert_pairs");
grpc_tls_credentials_options_set_identity_cert_name_import = (grpc_tls_credentials_options_set_identity_cert_name_type) GetProcAddress(library, "grpc_tls_credentials_options_set_identity_cert_name");
grpc_tls_credentials_options_set_server_authorization_check_config_import = (grpc_tls_credentials_options_set_server_authorization_check_config_type) GetProcAddress(library, "grpc_tls_credentials_options_set_server_authorization_check_config");
grpc_tls_server_authorization_check_config_create_import = (grpc_tls_server_authorization_check_config_create_type) GetProcAddress(library, "grpc_tls_server_authorization_check_config_create");
grpc_tls_server_authorization_check_config_release_import = (grpc_tls_server_authorization_check_config_release_type) GetProcAddress(library, "grpc_tls_server_authorization_check_config_release");
grpc_tls_credentials_options_set_cert_request_type_import = (grpc_tls_credentials_options_set_cert_request_type_type) GetProcAddress(library, "grpc_tls_credentials_options_set_cert_request_type");
grpc_tls_credentials_options_set_verify_server_cert_import = (grpc_tls_credentials_options_set_verify_server_cert_type) GetProcAddress(library, "grpc_tls_credentials_options_set_verify_server_cert");
grpc_tls_credentials_options_set_check_call_host_import = (grpc_tls_credentials_options_set_check_call_host_type) GetProcAddress(library, "grpc_tls_credentials_options_set_check_call_host");
grpc_xds_credentials_create_import = (grpc_xds_credentials_create_type) GetProcAddress(library, "grpc_xds_credentials_create");
grpc_xds_server_credentials_create_import = (grpc_xds_server_credentials_create_type) GetProcAddress(library, "grpc_xds_server_credentials_create");
grpc_authorization_policy_provider_static_data_create_import = (grpc_authorization_policy_provider_static_data_create_type) GetProcAddress(library, "grpc_authorization_policy_provider_static_data_create");

View File

@ -491,12 +491,6 @@ extern grpc_tls_certificate_provider_release_type grpc_tls_certificate_provider_
typedef grpc_tls_credentials_options*(*grpc_tls_credentials_options_create_type)(void);
extern grpc_tls_credentials_options_create_type grpc_tls_credentials_options_create_import;
#define grpc_tls_credentials_options_create grpc_tls_credentials_options_create_import
typedef void(*grpc_tls_credentials_options_set_cert_request_type_type)(grpc_tls_credentials_options* options, grpc_ssl_client_certificate_request_type type);
extern grpc_tls_credentials_options_set_cert_request_type_type grpc_tls_credentials_options_set_cert_request_type_import;
#define grpc_tls_credentials_options_set_cert_request_type grpc_tls_credentials_options_set_cert_request_type_import
typedef void(*grpc_tls_credentials_options_set_server_verification_option_type)(grpc_tls_credentials_options* options, grpc_tls_server_verification_option server_verification_option);
extern grpc_tls_credentials_options_set_server_verification_option_type grpc_tls_credentials_options_set_server_verification_option_import;
#define grpc_tls_credentials_options_set_server_verification_option grpc_tls_credentials_options_set_server_verification_option_import
typedef void(*grpc_tls_credentials_options_set_certificate_provider_type)(grpc_tls_credentials_options* options, grpc_tls_certificate_provider* provider);
extern grpc_tls_credentials_options_set_certificate_provider_type grpc_tls_credentials_options_set_certificate_provider_import;
#define grpc_tls_credentials_options_set_certificate_provider grpc_tls_credentials_options_set_certificate_provider_import
@ -512,15 +506,15 @@ extern grpc_tls_credentials_options_watch_identity_key_cert_pairs_type grpc_tls_
typedef void(*grpc_tls_credentials_options_set_identity_cert_name_type)(grpc_tls_credentials_options* options, const char* identity_cert_name);
extern grpc_tls_credentials_options_set_identity_cert_name_type grpc_tls_credentials_options_set_identity_cert_name_import;
#define grpc_tls_credentials_options_set_identity_cert_name grpc_tls_credentials_options_set_identity_cert_name_import
typedef void(*grpc_tls_credentials_options_set_server_authorization_check_config_type)(grpc_tls_credentials_options* options, grpc_tls_server_authorization_check_config* config);
extern grpc_tls_credentials_options_set_server_authorization_check_config_type grpc_tls_credentials_options_set_server_authorization_check_config_import;
#define grpc_tls_credentials_options_set_server_authorization_check_config grpc_tls_credentials_options_set_server_authorization_check_config_import
typedef grpc_tls_server_authorization_check_config*(*grpc_tls_server_authorization_check_config_create_type)(const void* config_user_data, int (*schedule)(void* config_user_data, grpc_tls_server_authorization_check_arg* arg), void (*cancel)(void* config_user_data, grpc_tls_server_authorization_check_arg* arg), void (*destruct)(void* config_user_data));
extern grpc_tls_server_authorization_check_config_create_type grpc_tls_server_authorization_check_config_create_import;
#define grpc_tls_server_authorization_check_config_create grpc_tls_server_authorization_check_config_create_import
typedef void(*grpc_tls_server_authorization_check_config_release_type)(grpc_tls_server_authorization_check_config* config);
extern grpc_tls_server_authorization_check_config_release_type grpc_tls_server_authorization_check_config_release_import;
#define grpc_tls_server_authorization_check_config_release grpc_tls_server_authorization_check_config_release_import
typedef void(*grpc_tls_credentials_options_set_cert_request_type_type)(grpc_tls_credentials_options* options, grpc_ssl_client_certificate_request_type type);
extern grpc_tls_credentials_options_set_cert_request_type_type grpc_tls_credentials_options_set_cert_request_type_import;
#define grpc_tls_credentials_options_set_cert_request_type grpc_tls_credentials_options_set_cert_request_type_import
typedef void(*grpc_tls_credentials_options_set_verify_server_cert_type)(grpc_tls_credentials_options* options, int verify_server_cert);
extern grpc_tls_credentials_options_set_verify_server_cert_type grpc_tls_credentials_options_set_verify_server_cert_import;
#define grpc_tls_credentials_options_set_verify_server_cert grpc_tls_credentials_options_set_verify_server_cert_import
typedef void(*grpc_tls_credentials_options_set_check_call_host_type)(grpc_tls_credentials_options* options, int check_call_host);
extern grpc_tls_credentials_options_set_check_call_host_type grpc_tls_credentials_options_set_check_call_host_import;
#define grpc_tls_credentials_options_set_check_call_host grpc_tls_credentials_options_set_check_call_host_import
typedef grpc_channel_credentials*(*grpc_xds_credentials_create_type)(grpc_channel_credentials* fallback_credentials);
extern grpc_xds_credentials_create_type grpc_xds_credentials_create_import;
#define grpc_xds_credentials_create grpc_xds_credentials_create_import

View File

@ -39,6 +39,7 @@
#include "test/core/end2end/end2end_tests.h"
#include "test/core/util/port.h"
#include "test/core/util/test_config.h"
#include "test/core/util/tls_utils.h"
// For normal TLS connections.
#define CA_CERT_PATH "src/core/tsi/test_creds/ca.pem"
@ -47,103 +48,200 @@
typedef absl::InlinedVector<grpc_core::Thread, 1> ThreadList;
struct SecurityPrimitives {
enum ProviderType { STATIC_PROVIDER = 0, FILE_PROVIDER = 1 } provider_type;
enum VerifierType {
EXTERNAL_SYNC_VERIFIER = 0,
EXTERNAL_ASYNC_VERIFIER = 1,
HOSTNAME_VERIFIER = 2
} verifier_type;
enum TlsVersion { V_12 = 0, V_13 = 1 } tls_version;
};
struct fullstack_secure_fixture_data {
~fullstack_secure_fixture_data() {
for (size_t ind = 0; ind < thd_list.size(); ind++) {
thd_list[ind].Join();
}
grpc_tls_certificate_provider_release(client_provider);
grpc_tls_certificate_provider_release(server_provider);
grpc_tls_certificate_verifier_release(client_verifier);
grpc_tls_certificate_verifier_release(server_verifier);
}
std::string localaddr;
grpc_tls_version tls_version;
ThreadList thd_list;
grpc_tls_certificate_provider* client_provider = nullptr;
grpc_tls_certificate_provider* server_provider = nullptr;
grpc_tls_certificate_verifier* client_verifier = nullptr;
grpc_tls_certificate_verifier* server_verifier = nullptr;
bool check_call_host = true;
};
static grpc_end2end_test_fixture chttp2_create_fixture_static_data(
grpc_channel_args* /*client_args*/, grpc_channel_args* /*server_args*/,
grpc_tls_version tls_version) {
grpc_end2end_test_fixture f;
int port = grpc_pick_unused_port_or_die();
fullstack_secure_fixture_data* ffd = new fullstack_secure_fixture_data();
memset(&f, 0, sizeof(f));
ffd->localaddr = grpc_core::JoinHostPort("localhost", port);
ffd->tls_version = tls_version;
grpc_slice root_slice, cert_slice, key_slice;
GPR_ASSERT(GRPC_LOG_IF_ERROR("load_file",
grpc_load_file(CA_CERT_PATH, 1, &root_slice)));
std::string root_cert =
std::string(grpc_core::StringViewFromSlice(root_slice));
GPR_ASSERT(GRPC_LOG_IF_ERROR(
"load_file", grpc_load_file(SERVER_CERT_PATH, 1, &cert_slice)));
std::string identity_cert =
std::string(grpc_core::StringViewFromSlice(cert_slice));
GPR_ASSERT(GRPC_LOG_IF_ERROR("load_file",
grpc_load_file(SERVER_KEY_PATH, 1, &key_slice)));
std::string private_key =
std::string(grpc_core::StringViewFromSlice(key_slice));
grpc_tls_identity_pairs* client_pairs = grpc_tls_identity_pairs_create();
grpc_tls_identity_pairs_add_pair(client_pairs, private_key.c_str(),
identity_cert.c_str());
ffd->client_provider = grpc_tls_certificate_provider_static_data_create(
root_cert.c_str(), client_pairs);
grpc_tls_identity_pairs* server_pairs = grpc_tls_identity_pairs_create();
grpc_tls_identity_pairs_add_pair(server_pairs, private_key.c_str(),
identity_cert.c_str());
ffd->server_provider = grpc_tls_certificate_provider_static_data_create(
root_cert.c_str(), server_pairs);
f.fixture_data = ffd;
f.cq = grpc_completion_queue_create_for_next(nullptr);
f.shutdown_cq = grpc_completion_queue_create_for_pluck(nullptr);
grpc_slice_unref(root_slice);
grpc_slice_unref(cert_slice);
grpc_slice_unref(key_slice);
return f;
static void SetTlsVersion(fullstack_secure_fixture_data* ffd,
SecurityPrimitives::TlsVersion tls_version) {
switch (tls_version) {
case SecurityPrimitives::TlsVersion::V_12: {
ffd->tls_version = grpc_tls_version::TLS1_2;
break;
}
case SecurityPrimitives::TlsVersion::V_13: {
ffd->tls_version = grpc_tls_version::TLS1_3;
break;
}
}
}
static grpc_end2end_test_fixture chttp2_create_fixture_cert_watcher(
grpc_channel_args* /*client_args*/, grpc_channel_args* /*server_args*/,
grpc_tls_version tls_version) {
static void SetCertificateProvider(
fullstack_secure_fixture_data* ffd,
SecurityPrimitives::ProviderType provider_type) {
switch (provider_type) {
case SecurityPrimitives::ProviderType::STATIC_PROVIDER: {
grpc_slice root_slice, cert_slice, key_slice;
GPR_ASSERT(GRPC_LOG_IF_ERROR(
"load_file", grpc_load_file(CA_CERT_PATH, 1, &root_slice)));
std::string root_cert =
std::string(grpc_core::StringViewFromSlice(root_slice));
GPR_ASSERT(GRPC_LOG_IF_ERROR(
"load_file", grpc_load_file(SERVER_CERT_PATH, 1, &cert_slice)));
std::string identity_cert =
std::string(grpc_core::StringViewFromSlice(cert_slice));
GPR_ASSERT(GRPC_LOG_IF_ERROR(
"load_file", grpc_load_file(SERVER_KEY_PATH, 1, &key_slice)));
std::string private_key =
std::string(grpc_core::StringViewFromSlice(key_slice));
grpc_tls_identity_pairs* client_pairs = grpc_tls_identity_pairs_create();
grpc_tls_identity_pairs_add_pair(client_pairs, private_key.c_str(),
identity_cert.c_str());
ffd->client_provider = grpc_tls_certificate_provider_static_data_create(
root_cert.c_str(), client_pairs);
grpc_tls_identity_pairs* server_pairs = grpc_tls_identity_pairs_create();
grpc_tls_identity_pairs_add_pair(server_pairs, private_key.c_str(),
identity_cert.c_str());
ffd->server_provider = grpc_tls_certificate_provider_static_data_create(
root_cert.c_str(), server_pairs);
grpc_slice_unref(root_slice);
grpc_slice_unref(cert_slice);
grpc_slice_unref(key_slice);
break;
}
case SecurityPrimitives::ProviderType::FILE_PROVIDER: {
ffd->client_provider = grpc_tls_certificate_provider_file_watcher_create(
SERVER_KEY_PATH, SERVER_CERT_PATH, CA_CERT_PATH, 1);
ffd->server_provider = grpc_tls_certificate_provider_file_watcher_create(
SERVER_KEY_PATH, SERVER_CERT_PATH, CA_CERT_PATH, 1);
break;
}
}
}
static void SetCertificateVerifier(
fullstack_secure_fixture_data* ffd,
SecurityPrimitives::VerifierType verifier_type) {
switch (verifier_type) {
case SecurityPrimitives::VerifierType::EXTERNAL_SYNC_VERIFIER: {
auto* client_sync_verifier =
new grpc_core::testing::SyncExternalVerifier(true);
ffd->client_verifier = grpc_tls_certificate_verifier_external_create(
client_sync_verifier->base());
auto* server_sync_verifier =
new grpc_core::testing::SyncExternalVerifier(true);
ffd->server_verifier = grpc_tls_certificate_verifier_external_create(
server_sync_verifier->base());
ffd->check_call_host = false;
break;
}
case SecurityPrimitives::VerifierType::EXTERNAL_ASYNC_VERIFIER: {
auto* client_async_verifier =
new grpc_core::testing::AsyncExternalVerifier(true);
ffd->client_verifier = grpc_tls_certificate_verifier_external_create(
client_async_verifier->base());
auto* server_async_verifier =
new grpc_core::testing::AsyncExternalVerifier(true);
ffd->server_verifier = grpc_tls_certificate_verifier_external_create(
server_async_verifier->base());
ffd->check_call_host = false;
break;
}
case SecurityPrimitives::VerifierType::HOSTNAME_VERIFIER: {
ffd->client_verifier = grpc_tls_certificate_verifier_host_name_create();
// Hostname verifier couldn't be applied to the server side, so we will
// use sync external verifier here.
auto* server_async_verifier =
new grpc_core::testing::AsyncExternalVerifier(true);
ffd->server_verifier = grpc_tls_certificate_verifier_external_create(
server_async_verifier->base());
break;
}
}
}
static grpc_end2end_test_fixture chttp2_create_fixture_simple_fullstack(
grpc_channel_args*, grpc_channel_args*) {
grpc_end2end_test_fixture f;
int port = grpc_pick_unused_port_or_die();
fullstack_secure_fixture_data* ffd = new fullstack_secure_fixture_data();
memset(&f, 0, sizeof(f));
ffd->localaddr = grpc_core::JoinHostPort("localhost", port);
ffd->tls_version = tls_version;
ffd->client_provider = grpc_tls_certificate_provider_file_watcher_create(
SERVER_KEY_PATH, SERVER_CERT_PATH, CA_CERT_PATH, 1);
ffd->server_provider = grpc_tls_certificate_provider_file_watcher_create(
SERVER_KEY_PATH, SERVER_CERT_PATH, CA_CERT_PATH, 1);
SetTlsVersion(ffd, SecurityPrimitives::TlsVersion::V_12);
SetCertificateProvider(ffd,
SecurityPrimitives::ProviderType::STATIC_PROVIDER);
SetCertificateVerifier(
ffd, SecurityPrimitives::VerifierType::EXTERNAL_SYNC_VERIFIER);
f.fixture_data = ffd;
f.cq = grpc_completion_queue_create_for_next(nullptr);
f.shutdown_cq = grpc_completion_queue_create_for_pluck(nullptr);
return f;
}
static grpc_end2end_test_fixture chttp2_create_fixture_static_data_tls1_2(
grpc_channel_args* client_args, grpc_channel_args* server_args) {
return chttp2_create_fixture_static_data(client_args, server_args,
grpc_tls_version::TLS1_2);
static grpc_end2end_test_fixture chttp2_create_fixture_async_verifier(
grpc_channel_args*, grpc_channel_args*) {
grpc_end2end_test_fixture f;
int port = grpc_pick_unused_port_or_die();
fullstack_secure_fixture_data* ffd = new fullstack_secure_fixture_data();
memset(&f, 0, sizeof(f));
ffd->localaddr = grpc_core::JoinHostPort("localhost", port);
SetTlsVersion(ffd, SecurityPrimitives::TlsVersion::V_13);
SetCertificateProvider(ffd,
SecurityPrimitives::ProviderType::STATIC_PROVIDER);
SetCertificateVerifier(
ffd, SecurityPrimitives::VerifierType::EXTERNAL_ASYNC_VERIFIER);
f.fixture_data = ffd;
f.cq = grpc_completion_queue_create_for_next(nullptr);
f.shutdown_cq = grpc_completion_queue_create_for_pluck(nullptr);
return f;
}
static grpc_end2end_test_fixture chttp2_create_fixture_static_data_tls1_3(
grpc_channel_args* client_args, grpc_channel_args* server_args) {
return chttp2_create_fixture_static_data(client_args, server_args,
grpc_tls_version::TLS1_3);
static grpc_end2end_test_fixture
chttp2_create_fixture_hostname_verifier_cert_watcher(grpc_channel_args*,
grpc_channel_args*) {
grpc_end2end_test_fixture f;
int port = grpc_pick_unused_port_or_die();
fullstack_secure_fixture_data* ffd = new fullstack_secure_fixture_data();
memset(&f, 0, sizeof(f));
ffd->localaddr = grpc_core::JoinHostPort("localhost", port);
SetTlsVersion(ffd, SecurityPrimitives::TlsVersion::V_12);
SetCertificateProvider(ffd, SecurityPrimitives::ProviderType::FILE_PROVIDER);
SetCertificateVerifier(ffd,
SecurityPrimitives::VerifierType::HOSTNAME_VERIFIER);
f.fixture_data = ffd;
f.cq = grpc_completion_queue_create_for_next(nullptr);
f.shutdown_cq = grpc_completion_queue_create_for_pluck(nullptr);
return f;
}
static grpc_end2end_test_fixture chttp2_create_fixture_cert_watcher_tls1_2(
grpc_channel_args* client_args, grpc_channel_args* server_args) {
return chttp2_create_fixture_cert_watcher(client_args, server_args,
grpc_tls_version::TLS1_2);
}
static grpc_end2end_test_fixture chttp2_create_fixture_cert_watcher_tls1_3(
grpc_channel_args* client_args, grpc_channel_args* server_args) {
return chttp2_create_fixture_cert_watcher(client_args, server_args,
grpc_tls_version::TLS1_3);
static grpc_end2end_test_fixture
chttp2_create_fixture_async_verifier_cert_watcher(grpc_channel_args*,
grpc_channel_args*) {
grpc_end2end_test_fixture f;
int port = grpc_pick_unused_port_or_die();
fullstack_secure_fixture_data* ffd = new fullstack_secure_fixture_data();
memset(&f, 0, sizeof(f));
ffd->localaddr = grpc_core::JoinHostPort("localhost", port);
SetTlsVersion(ffd, SecurityPrimitives::TlsVersion::V_12);
SetCertificateProvider(ffd, SecurityPrimitives::ProviderType::FILE_PROVIDER);
SetCertificateVerifier(
ffd, SecurityPrimitives::VerifierType::EXTERNAL_ASYNC_VERIFIER);
f.fixture_data = ffd;
f.cq = grpc_completion_queue_create_for_next(nullptr);
f.shutdown_cq = grpc_completion_queue_create_for_pluck(nullptr);
return f;
}
static void process_auth_failure(void* state, grpc_auth_context* /*ctx*/,
@ -188,37 +286,12 @@ void chttp2_tear_down_secure_fullstack(grpc_end2end_test_fixture* f) {
delete ffd;
}
// Application-provided callback for server authorization check.
static void server_authz_check_cb(void* user_data) {
grpc_tls_server_authorization_check_arg* check_arg =
static_cast<grpc_tls_server_authorization_check_arg*>(user_data);
GPR_ASSERT(check_arg != nullptr);
// result = 1 indicates the server authorization check passes.
// Normally, the application code should resort to mapping information
// between server identity and target name to derive the result.
// For this test, we directly return 1 for simplicity.
check_arg->success = 1;
check_arg->status = GRPC_STATUS_OK;
check_arg->cb(check_arg);
}
// Asynchronous implementation of schedule field in
// grpc_server_authorization_check_config.
static int server_authz_check_async(
void* config_user_data, grpc_tls_server_authorization_check_arg* arg) {
fullstack_secure_fixture_data* ffd =
static_cast<fullstack_secure_fixture_data*>(config_user_data);
ffd->thd_list.push_back(
grpc_core::Thread("h2_tls_test", &server_authz_check_cb, arg));
ffd->thd_list[ffd->thd_list.size() - 1].Start();
return 1;
}
// Create a TLS channel credential.
static grpc_channel_credentials* create_tls_channel_credentials(
fullstack_secure_fixture_data* ffd) {
grpc_tls_credentials_options* options = grpc_tls_credentials_options_create();
options->set_server_verification_option(GRPC_TLS_SERVER_VERIFICATION);
grpc_tls_credentials_options_set_verify_server_cert(
options, 1 /* = verify server certs */);
options->set_min_tls_version(ffd->tls_version);
options->set_max_tls_version(ffd->tls_version);
// Set credential provider.
@ -226,15 +299,13 @@ static grpc_channel_credentials* create_tls_channel_credentials(
ffd->client_provider);
grpc_tls_credentials_options_watch_root_certs(options);
grpc_tls_credentials_options_watch_identity_key_cert_pairs(options);
/* Set server authorization check config. */
grpc_tls_server_authorization_check_config* check_config =
grpc_tls_server_authorization_check_config_create(
ffd, server_authz_check_async, nullptr, nullptr);
grpc_tls_credentials_options_set_server_authorization_check_config(
options, check_config);
// Set credential verifier.
grpc_tls_credentials_options_set_certificate_verifier(options,
ffd->client_verifier);
grpc_tls_credentials_options_set_check_call_host(options,
ffd->check_call_host);
/* Create TLS channel credentials. */
grpc_channel_credentials* creds = grpc_tls_credentials_create(options);
grpc_tls_server_authorization_check_config_release(check_config);
return creds;
}
@ -249,9 +320,12 @@ static grpc_server_credentials* create_tls_server_credentials(
ffd->server_provider);
grpc_tls_credentials_options_watch_root_certs(options);
grpc_tls_credentials_options_watch_identity_key_cert_pairs(options);
/* Set client certificate request type. */
// Set client certificate request type.
grpc_tls_credentials_options_set_cert_request_type(
options, GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY);
// Set credential verifier.
grpc_tls_credentials_options_set_certificate_verifier(options,
ffd->server_verifier);
grpc_server_credentials* creds = grpc_tls_server_credentials_create(options);
return creds;
}
@ -294,48 +368,37 @@ static void chttp2_init_server(grpc_end2end_test_fixture* f,
chttp2_init_server_secure_fullstack(f, server_args, ssl_creds);
}
static grpc_end2end_test_config configs[] = {
// client: static data provider + async custom verification
// server: static data provider
// extra: TLS 1.2
{"chttp2/simple_ssl_fullstack_tls1_2",
FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION |
FEATURE_MASK_SUPPORTS_PER_CALL_CREDENTIALS |
FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL |
FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER,
"foo.test.google.fr", chttp2_create_fixture_static_data_tls1_2,
chttp2_init_client, chttp2_init_server, chttp2_tear_down_secure_fullstack},
// client: static data provider + async custom verification
// server: static data provider
// extra: TLS 1.3
{"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,
"foo.test.google.fr", chttp2_create_fixture_static_data_tls1_3,
chttp2_init_client, chttp2_init_server, chttp2_tear_down_secure_fullstack},
// client: certificate watcher provider + async custom verification
// server: certificate watcher provider
// extra: TLS 1.2
{"chttp2/reloading_from_files_ssl_fullstack_tls1_2",
FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION |
FEATURE_MASK_SUPPORTS_PER_CALL_CREDENTIALS |
FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL |
FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER,
"foo.test.google.fr", chttp2_create_fixture_cert_watcher_tls1_2,
chttp2_init_client, chttp2_init_server, chttp2_tear_down_secure_fullstack},
// client: certificate watcher provider + async custom verification
// server: certificate watcher provider
// extra: TLS 1.3
{"chttp2/reloading_from_files_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,
"foo.test.google.fr", chttp2_create_fixture_cert_watcher_tls1_3,
chttp2_init_client, chttp2_init_server, chttp2_tear_down_secure_fullstack},
static const uint32_t kH2TLSFeatureMask =
FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION |
FEATURE_MASK_SUPPORTS_PER_CALL_CREDENTIALS |
FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL |
FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER;
static grpc_end2end_test_config configs[] = {
// client: static data provider + sync external verifier
// server: static data provider + sync external verifier
// extra: TLS 1.2
{"chttp2/simple_ssl_fullstack", kH2TLSFeatureMask, "foo.test.google.fr",
chttp2_create_fixture_simple_fullstack, chttp2_init_client,
chttp2_init_server, chttp2_tear_down_secure_fullstack},
// client: static data provider + async external verifier
// server: static data provider + async external verifier
// extra: TLS 1.3
{"chttp2/static_provider_async_verifier_tls1_3", kH2TLSFeatureMask,
"foo.test.google.fr", chttp2_create_fixture_async_verifier,
chttp2_init_client, chttp2_init_server, chttp2_tear_down_secure_fullstack},
// client: certificate watcher provider + hostname verifier
// server: certificate watcher provider + sync external verifier
// extra: TLS 1.2
{"chttp2/cert_watcher_provider_sync_verifier_tls1_2", kH2TLSFeatureMask,
"foo.test.google.fr", chttp2_create_fixture_hostname_verifier_cert_watcher,
chttp2_init_client, chttp2_init_server, chttp2_tear_down_secure_fullstack},
// client: certificate watcher provider + async external verifier
// server: certificate watcher provider + async external verifier
// extra: TLS 1.3
{"chttp2/cert_watcher_provider_async_verifier_tls1_3", kH2TLSFeatureMask,
"foo.test.google.fr", chttp2_create_fixture_async_verifier_cert_watcher,
chttp2_init_client, chttp2_init_server, chttp2_tear_down_secure_fullstack},
};
int main(int argc, char** argv) {

View File

@ -370,6 +370,19 @@ grpc_cc_test(
],
)
grpc_cc_test(
name = "grpc_tls_certificate_verifier_test",
srcs = ["grpc_tls_certificate_verifier_test.cc"],
external_deps = ["gtest"],
language = "C++",
deps = [
"//:gpr",
"//:grpc",
"//:grpc_secure",
"//test/core/util:grpc_test_util",
],
)
grpc_cc_test(
name = "insecure_security_connector_test",
srcs = ["insecure_security_connector_test.cc"],

View File

@ -0,0 +1,265 @@
//
// Copyright 2021 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/security/credentials/tls/grpc_tls_certificate_verifier.h"
#include <deque>
#include <list>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
#include "src/core/lib/gpr/tmpfile.h"
#include "src/core/lib/iomgr/load_file.h"
#include "src/core/lib/security/security_connector/tls/tls_security_connector.h"
#include "src/core/lib/slice/slice_internal.h"
#include "test/core/util/test_config.h"
#include "test/core/util/tls_utils.h"
namespace grpc_core {
namespace testing {
// Unit tests for grpc_tls_certificate_verifier and all its successors.
// In these tests, |request_| is not outliving the test itself, so it's fine to
// point fields in |request_| directly to the address of local variables. In
// actual implementation, these fields are dynamically allocated.
class GrpcTlsCertificateVerifierTest : public ::testing::Test {
protected:
void SetUp() override { memset(&request_, 0, sizeof(request_)); }
void TearDown() override {}
grpc_tls_custom_verification_check_request request_;
HostNameCertificateVerifier hostname_certificate_verifier_;
};
TEST_F(GrpcTlsCertificateVerifierTest, SyncExternalVerifierSucceeds) {
auto* sync_verifier = new SyncExternalVerifier(true);
ExternalCertificateVerifier core_external_verifier(sync_verifier->base());
absl::Status sync_status;
EXPECT_TRUE(core_external_verifier.Verify(
&request_, [](absl::Status) {}, &sync_status));
EXPECT_TRUE(sync_status.ok())
<< sync_status.code() << " " << sync_status.message();
}
TEST_F(GrpcTlsCertificateVerifierTest, SyncExternalVerifierFails) {
auto* sync_verifier = new SyncExternalVerifier(false);
ExternalCertificateVerifier core_external_verifier(sync_verifier->base());
absl::Status sync_status;
EXPECT_TRUE(core_external_verifier.Verify(
&request_, [](absl::Status) {}, &sync_status));
EXPECT_EQ(sync_status.code(), absl::StatusCode::kUnauthenticated);
EXPECT_EQ(sync_status.ToString(),
"UNAUTHENTICATED: SyncExternalVerifier failed");
}
TEST_F(GrpcTlsCertificateVerifierTest, AsyncExternalVerifierSucceeds) {
absl::Status sync_status;
// This is to make sure the callback has already been completed before we
// destroy ExternalCertificateVerifier object.
gpr_event callback_completed_event;
gpr_event_init(&callback_completed_event);
auto* async_verifier = new AsyncExternalVerifier(true);
ExternalCertificateVerifier core_external_verifier(async_verifier->base());
EXPECT_FALSE(core_external_verifier.Verify(
&request_,
[&callback_completed_event](absl::Status async_status) {
EXPECT_TRUE(async_status.ok())
<< async_status.code() << " " << async_status.message();
gpr_event_set(&callback_completed_event, reinterpret_cast<void*>(1));
},
&sync_status));
void* callback_completed =
gpr_event_wait(&callback_completed_event,
gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC),
gpr_time_from_seconds(10, GPR_TIMESPAN)));
EXPECT_NE(callback_completed, nullptr);
}
TEST_F(GrpcTlsCertificateVerifierTest, AsyncExternalVerifierFails) {
absl::Status sync_status;
// This is to make sure the callback has already been completed before we
// destroy ExternalCertificateVerifier object.
gpr_event callback_completed_event;
gpr_event_init(&callback_completed_event);
auto* async_verifier = new AsyncExternalVerifier(false);
ExternalCertificateVerifier core_external_verifier(async_verifier->base());
EXPECT_FALSE(core_external_verifier.Verify(
&request_,
[&callback_completed_event](absl::Status async_status) {
gpr_log(GPR_INFO, "Callback is invoked.");
EXPECT_EQ(async_status.code(), absl::StatusCode::kUnauthenticated);
EXPECT_EQ(async_status.ToString(),
"UNAUTHENTICATED: AsyncExternalVerifier failed");
gpr_event_set(&callback_completed_event, reinterpret_cast<void*>(1));
},
&sync_status));
void* callback_completed =
gpr_event_wait(&callback_completed_event,
gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC),
gpr_time_from_seconds(10, GPR_TIMESPAN)));
EXPECT_NE(callback_completed, nullptr);
}
TEST_F(GrpcTlsCertificateVerifierTest, HostnameVerifierNullTargetName) {
absl::Status sync_status;
EXPECT_TRUE(hostname_certificate_verifier_.Verify(
&request_, [](absl::Status) {}, &sync_status));
EXPECT_EQ(sync_status.code(), absl::StatusCode::kUnauthenticated);
EXPECT_EQ(sync_status.ToString(),
"UNAUTHENTICATED: Target name is not specified.");
}
TEST_F(GrpcTlsCertificateVerifierTest, HostnameVerifierInvalidTargetName) {
absl::Status sync_status;
request_.target_name = "[foo.com@443";
EXPECT_TRUE(hostname_certificate_verifier_.Verify(
&request_, [](absl::Status) {}, &sync_status));
EXPECT_EQ(sync_status.code(), absl::StatusCode::kUnauthenticated);
EXPECT_EQ(sync_status.ToString(),
"UNAUTHENTICATED: Failed to split hostname and port.");
}
TEST_F(GrpcTlsCertificateVerifierTest, HostnameVerifierDNSExactCheckSucceeds) {
absl::Status sync_status;
request_.target_name = "foo.com:443";
char* dns_names[] = {const_cast<char*>("foo.com")};
request_.peer_info.san_names.dns_names = dns_names;
request_.peer_info.san_names.dns_names_size = 1;
EXPECT_TRUE(hostname_certificate_verifier_.Verify(
&request_, [](absl::Status) {}, &sync_status));
EXPECT_TRUE(sync_status.ok())
<< sync_status.code() << " " << sync_status.message();
}
TEST_F(GrpcTlsCertificateVerifierTest,
HostnameVerifierDNSWildcardCheckSucceeds) {
absl::Status sync_status;
request_.target_name = "foo.bar.com:443";
char* dns_names[] = {const_cast<char*>("*.bar.com")};
request_.peer_info.san_names.dns_names = dns_names;
request_.peer_info.san_names.dns_names_size = 1;
EXPECT_TRUE(hostname_certificate_verifier_.Verify(
&request_, [](absl::Status) {}, &sync_status));
EXPECT_TRUE(sync_status.ok())
<< sync_status.code() << " " << sync_status.message();
}
TEST_F(GrpcTlsCertificateVerifierTest,
HostnameVerifierDNSWildcardCaseInsensitiveCheckSucceeds) {
absl::Status sync_status;
request_.target_name = "fOo.bar.cOm:443";
char* dns_names[] = {const_cast<char*>("*.BaR.Com")};
request_.peer_info.san_names.dns_names = dns_names;
request_.peer_info.san_names.dns_names_size = 1;
EXPECT_TRUE(hostname_certificate_verifier_.Verify(
&request_, [](absl::Status) {}, &sync_status));
EXPECT_TRUE(sync_status.ok())
<< sync_status.code() << " " << sync_status.message();
}
TEST_F(GrpcTlsCertificateVerifierTest,
HostnameVerifierDNSTopWildcardCheckFails) {
absl::Status sync_status;
request_.target_name = "foo.com:443";
char* dns_names[] = {const_cast<char*>("*.")};
request_.peer_info.san_names.dns_names = dns_names;
request_.peer_info.san_names.dns_names_size = 1;
EXPECT_TRUE(hostname_certificate_verifier_.Verify(
&request_, [](absl::Status) {}, &sync_status));
EXPECT_EQ(sync_status.code(), absl::StatusCode::kUnauthenticated);
EXPECT_EQ(sync_status.ToString(),
"UNAUTHENTICATED: Hostname Verification Check failed.");
}
TEST_F(GrpcTlsCertificateVerifierTest, HostnameVerifierDNSExactCheckFails) {
absl::Status sync_status;
request_.target_name = "foo.com:443";
char* dns_names[] = {const_cast<char*>("bar.com")};
request_.peer_info.san_names.dns_names = dns_names;
request_.peer_info.san_names.dns_names_size = 1;
EXPECT_TRUE(hostname_certificate_verifier_.Verify(
&request_, [](absl::Status) {}, &sync_status));
EXPECT_EQ(sync_status.code(), absl::StatusCode::kUnauthenticated);
EXPECT_EQ(sync_status.ToString(),
"UNAUTHENTICATED: Hostname Verification Check failed.");
}
TEST_F(GrpcTlsCertificateVerifierTest, HostnameVerifierIpCheckSucceeds) {
absl::Status sync_status;
request_.target_name = "192.168.0.1:443";
char* ip_names[] = {const_cast<char*>("192.168.0.1")};
request_.peer_info.san_names.ip_names = ip_names;
request_.peer_info.san_names.ip_names_size = 1;
EXPECT_TRUE(hostname_certificate_verifier_.Verify(
&request_, [](absl::Status) {}, &sync_status));
EXPECT_TRUE(sync_status.ok())
<< sync_status.code() << " " << sync_status.message();
}
TEST_F(GrpcTlsCertificateVerifierTest, HostnameVerifierIpCheckFails) {
absl::Status sync_status;
request_.target_name = "192.168.0.1:443";
char* ip_names[] = {const_cast<char*>("192.168.1.1")};
request_.peer_info.san_names.ip_names = ip_names;
request_.peer_info.san_names.ip_names_size = 1;
EXPECT_TRUE(hostname_certificate_verifier_.Verify(
&request_, [](absl::Status) {}, &sync_status));
EXPECT_EQ(sync_status.code(), absl::StatusCode::kUnauthenticated);
EXPECT_EQ(sync_status.ToString(),
"UNAUTHENTICATED: Hostname Verification Check failed.");
}
TEST_F(GrpcTlsCertificateVerifierTest,
HostnameVerifierCommonNameCheckSucceeds) {
absl::Status sync_status;
request_.target_name = "foo.com:443";
request_.peer_info.common_name = "foo.com";
EXPECT_TRUE(hostname_certificate_verifier_.Verify(
&request_, [](absl::Status) {}, &sync_status));
EXPECT_TRUE(sync_status.ok())
<< sync_status.code() << " " << sync_status.message();
}
TEST_F(GrpcTlsCertificateVerifierTest, HostnameVerifierCommonNameCheckFails) {
absl::Status sync_status;
request_.target_name = "foo.com:443";
request_.peer_info.common_name = "bar.com";
EXPECT_TRUE(hostname_certificate_verifier_.Verify(
&request_, [](absl::Status) {}, &sync_status));
EXPECT_EQ(sync_status.code(), absl::StatusCode::kUnauthenticated);
EXPECT_EQ(sync_status.ToString(),
"UNAUTHENTICATED: Hostname Verification Check failed.");
}
} // namespace testing
} // namespace grpc_core
int main(int argc, char** argv) {
grpc::testing::TestEnvironment env(argc, argv);
::testing::InitGoogleTest(&argc, argv);
grpc_init();
int ret = RUN_ALL_TESTS();
grpc_shutdown();
return ret;
}

View File

@ -61,18 +61,15 @@ class GrpcTlsCredentialsOptionsTest : public ::testing::Test {
std::string root_cert_2_;
std::string private_key_2_;
std::string cert_chain_2_;
HostNameCertificateVerifier hostname_certificate_verifier_;
};
TEST_F(GrpcTlsCredentialsOptionsTest, ErrorDetails) {
grpc_tls_error_details error_details;
EXPECT_STREQ(error_details.error_details().c_str(), "");
error_details.set_error_details("test error details");
EXPECT_STREQ(error_details.error_details().c_str(), "test error details");
}
//
// Tests for Default Root Certs.
//
TEST_F(GrpcTlsCredentialsOptionsTest, ClientOptionsOnDefaultRootCerts) {
auto options = MakeRefCounted<grpc_tls_credentials_options>();
options->set_server_verification_option(GRPC_TLS_SERVER_VERIFICATION);
auto credentials = MakeRefCounted<TlsCredentials>(options);
ASSERT_NE(credentials, nullptr);
grpc_channel_args* new_args = nullptr;
@ -85,7 +82,10 @@ TEST_F(GrpcTlsCredentialsOptionsTest, ClientOptionsOnDefaultRootCerts) {
EXPECT_NE(tls_connector->ClientHandshakerFactoryForTesting(), nullptr);
}
//
// Tests for StaticDataCertificateProvider.
//
TEST_F(GrpcTlsCredentialsOptionsTest,
ClientOptionsWithStaticDataProviderOnBothCerts) {
auto options = MakeRefCounted<grpc_tls_credentials_options>();
@ -94,7 +94,6 @@ TEST_F(GrpcTlsCredentialsOptionsTest,
options->set_certificate_provider(std::move(provider));
options->set_watch_root_cert(true);
options->set_watch_identity_pair(true);
options->set_server_verification_option(GRPC_TLS_SERVER_VERIFICATION);
auto credentials = MakeRefCounted<TlsCredentials>(options);
ASSERT_NE(credentials, nullptr);
grpc_channel_args* new_args = nullptr;
@ -116,7 +115,6 @@ TEST_F(GrpcTlsCredentialsOptionsTest,
root_cert_, PemKeyCertPairList());
options->set_certificate_provider(std::move(provider));
options->set_watch_root_cert(true);
options->set_server_verification_option(GRPC_TLS_SERVER_VERIFICATION);
auto credentials = MakeRefCounted<TlsCredentials>(options);
ASSERT_NE(credentials, nullptr);
grpc_channel_args* new_args = nullptr;
@ -138,7 +136,6 @@ TEST_F(GrpcTlsCredentialsOptionsTest,
"", MakeCertKeyPairs(private_key_.c_str(), cert_chain_.c_str()));
options->set_certificate_provider(std::move(provider));
options->set_watch_root_cert(true);
options->set_server_verification_option(GRPC_TLS_SERVER_VERIFICATION);
auto credentials = MakeRefCounted<TlsCredentials>(options);
ASSERT_NE(credentials, nullptr);
grpc_channel_args* new_args = nullptr;
@ -158,7 +155,6 @@ TEST_F(GrpcTlsCredentialsOptionsTest,
"", MakeCertKeyPairs(private_key_.c_str(), cert_chain_.c_str()));
options->set_certificate_provider(std::move(provider));
options->set_watch_identity_pair(true);
options->set_server_verification_option(GRPC_TLS_SERVER_VERIFICATION);
auto credentials = MakeRefCounted<TlsCredentials>(options);
ASSERT_NE(credentials, nullptr);
grpc_channel_args* new_args = nullptr;
@ -228,7 +224,10 @@ TEST_F(GrpcTlsCredentialsOptionsTest,
EXPECT_EQ(tls_connector->ServerHandshakerFactoryForTesting(), nullptr);
}
//
// Tests for FileWatcherCertificateProvider.
//
TEST_F(GrpcTlsCredentialsOptionsTest,
ClientOptionsWithCertWatcherProviderOnBothCerts) {
auto options = MakeRefCounted<grpc_tls_credentials_options>();
@ -237,7 +236,6 @@ TEST_F(GrpcTlsCredentialsOptionsTest,
options->set_certificate_provider(std::move(provider));
options->set_watch_root_cert(true);
options->set_watch_identity_pair(true);
options->set_server_verification_option(GRPC_TLS_SERVER_VERIFICATION);
auto credentials = MakeRefCounted<TlsCredentials>(options);
ASSERT_NE(credentials, nullptr);
grpc_channel_args* new_args = nullptr;
@ -259,7 +257,6 @@ TEST_F(GrpcTlsCredentialsOptionsTest,
MakeRefCounted<FileWatcherCertificateProvider>("", "", CA_CERT_PATH, 1);
options->set_certificate_provider(std::move(provider));
options->set_watch_root_cert(true);
options->set_server_verification_option(GRPC_TLS_SERVER_VERIFICATION);
auto credentials = MakeRefCounted<TlsCredentials>(options);
ASSERT_NE(credentials, nullptr);
grpc_channel_args* new_args = nullptr;
@ -281,7 +278,6 @@ TEST_F(GrpcTlsCredentialsOptionsTest,
SERVER_KEY_PATH, SERVER_CERT_PATH, "", 1);
options->set_certificate_provider(std::move(provider));
options->set_watch_root_cert(true);
options->set_server_verification_option(GRPC_TLS_SERVER_VERIFICATION);
auto credentials = MakeRefCounted<TlsCredentials>(options);
ASSERT_NE(credentials, nullptr);
grpc_channel_args* new_args = nullptr;
@ -301,7 +297,6 @@ TEST_F(GrpcTlsCredentialsOptionsTest,
MakeRefCounted<FileWatcherCertificateProvider>("", "", INVALID_PATH, 1);
options->set_certificate_provider(std::move(provider));
options->set_watch_root_cert(true);
options->set_server_verification_option(GRPC_TLS_SERVER_VERIFICATION);
auto credentials = MakeRefCounted<TlsCredentials>(options);
ASSERT_NE(credentials, nullptr);
grpc_channel_args* new_args = nullptr;
@ -388,8 +383,11 @@ TEST_F(GrpcTlsCredentialsOptionsTest,
EXPECT_EQ(tls_connector->ServerHandshakerFactoryForTesting(), nullptr);
}
// The following tests write credential data to temporary files to test the
//
// Tests writing credential data to temporary files to test the
// transition behavior of the provider.
//
TEST_F(GrpcTlsCredentialsOptionsTest,
ClientOptionsWithCertWatcherProviderOnCertificateRefreshed) {
// Create temporary files and copy cert data into them.
@ -404,7 +402,6 @@ TEST_F(GrpcTlsCredentialsOptionsTest,
options->set_certificate_provider(std::move(provider));
options->set_watch_root_cert(true);
options->set_watch_identity_pair(true);
options->set_server_verification_option(GRPC_TLS_SERVER_VERIFICATION);
auto credentials = MakeRefCounted<TlsCredentials>(options);
ASSERT_NE(credentials, nullptr);
grpc_channel_args* new_args = nullptr;
@ -453,7 +450,6 @@ TEST_F(GrpcTlsCredentialsOptionsTest,
options->set_certificate_provider(std::move(provider));
options->set_watch_root_cert(true);
options->set_watch_identity_pair(true);
options->set_server_verification_option(GRPC_TLS_SERVER_VERIFICATION);
auto credentials = MakeRefCounted<TlsCredentials>(options);
ASSERT_NE(credentials, nullptr);
grpc_channel_args* new_args = nullptr;
@ -490,6 +486,91 @@ TEST_F(GrpcTlsCredentialsOptionsTest,
MakeCertKeyPairs(private_key_.c_str(), cert_chain_.c_str()));
}
//
// Tests for ExternalCertificateVerifier.
// It will only test the creation of security connector, so the actual verify
// logic is not invoked.
//
TEST_F(GrpcTlsCredentialsOptionsTest, ClientOptionsWithExternalVerifier) {
auto* sync_verifier_ = new SyncExternalVerifier(true);
ExternalCertificateVerifier core_external_verifier(sync_verifier_->base());
auto options = MakeRefCounted<grpc_tls_credentials_options>();
options->set_verify_server_cert(true);
options->set_certificate_verifier(core_external_verifier.Ref());
options->set_check_call_host(false);
auto credentials = MakeRefCounted<TlsCredentials>(options);
ASSERT_NE(credentials, nullptr);
grpc_channel_args* new_args = nullptr;
auto connector = credentials->create_security_connector(
nullptr, "random targets", nullptr, &new_args);
grpc_channel_args_destroy(new_args);
ASSERT_NE(connector, nullptr);
TlsChannelSecurityConnector* tls_connector =
static_cast<TlsChannelSecurityConnector*>(connector.get());
EXPECT_NE(tls_connector, nullptr);
}
TEST_F(GrpcTlsCredentialsOptionsTest, ServerOptionsWithExternalVerifier) {
auto* sync_verifier_ = new SyncExternalVerifier(true);
ExternalCertificateVerifier core_external_verifier(sync_verifier_->base());
auto options = MakeRefCounted<grpc_tls_credentials_options>();
options->set_cert_request_type(GRPC_SSL_DONT_REQUEST_CLIENT_CERTIFICATE);
options->set_certificate_verifier(core_external_verifier.Ref());
// On server side we have to set the provider providing identity certs.
auto provider = MakeRefCounted<StaticDataCertificateProvider>(
root_cert_, PemKeyCertPairList());
options->set_certificate_provider(std::move(provider));
options->set_watch_identity_pair(true);
auto credentials = MakeRefCounted<TlsServerCredentials>(options);
ASSERT_NE(credentials, nullptr);
auto connector = credentials->create_security_connector(nullptr);
ASSERT_NE(connector, nullptr);
TlsServerSecurityConnector* tls_connector =
static_cast<TlsServerSecurityConnector*>(connector.get());
EXPECT_NE(tls_connector, nullptr);
}
//
// Tests for HostnameCertificateVerifier.
//
TEST_F(GrpcTlsCredentialsOptionsTest,
ClientOptionsWithHostnameCertificateVerifier) {
auto options = MakeRefCounted<grpc_tls_credentials_options>();
options->set_verify_server_cert(true);
options->set_certificate_verifier(hostname_certificate_verifier_.Ref());
auto credentials = MakeRefCounted<TlsCredentials>(options);
ASSERT_NE(credentials, nullptr);
grpc_channel_args* new_args = nullptr;
auto connector = credentials->create_security_connector(
nullptr, "random targets", nullptr, &new_args);
grpc_channel_args_destroy(new_args);
ASSERT_NE(connector, nullptr);
TlsChannelSecurityConnector* tls_connector =
static_cast<TlsChannelSecurityConnector*>(connector.get());
EXPECT_NE(tls_connector->ClientHandshakerFactoryForTesting(), nullptr);
}
TEST_F(GrpcTlsCredentialsOptionsTest,
ServerOptionsWithHostnameCertificateVerifier) {
auto options = MakeRefCounted<grpc_tls_credentials_options>();
options->set_cert_request_type(GRPC_SSL_DONT_REQUEST_CLIENT_CERTIFICATE);
options->set_certificate_verifier(hostname_certificate_verifier_.Ref());
// On server side we have to set the provider providing identity certs.
auto provider = MakeRefCounted<StaticDataCertificateProvider>(
root_cert_, PemKeyCertPairList());
options->set_certificate_provider(std::move(provider));
options->set_watch_identity_pair(true);
auto credentials = MakeRefCounted<TlsServerCredentials>(options);
ASSERT_NE(credentials, nullptr);
auto connector = credentials->create_security_connector(nullptr);
ASSERT_NE(connector, nullptr);
TlsServerSecurityConnector* tls_connector =
static_cast<TlsServerSecurityConnector*>(connector.get());
EXPECT_EQ(tls_connector->ServerHandshakerFactoryForTesting(), nullptr);
}
} // namespace testing
} // namespace grpc_core

View File

@ -33,6 +33,7 @@
#include "src/core/lib/security/credentials/tls/tls_credentials.h"
#include "src/core/tsi/transport_security.h"
#include "test/core/util/test_config.h"
#include "test/core/util/tls_utils.h"
#define CA_CERT_PATH "src/core/tsi/test_creds/ca.pem"
#define CLIENT_CERT_PATH "src/core/tsi/test_creds/multi-domain.pem"
@ -41,17 +42,18 @@
#define SERVER_CERT_PATH_1 "src/core/tsi/test_creds/server1.pem"
#define SERVER_KEY_PATH_1 "src/core/tsi/test_creds/server1.key"
namespace grpc {
namespace grpc_core {
namespace testing {
constexpr const char* kRootCertName = "root_cert_name";
constexpr const char* kIdentityCertName = "identity_cert_name";
constexpr const char* kErrorMessage = "error_message";
constexpr const char* kTargetName = "some_target";
constexpr const char* kTargetName = "foo.bar.com:443";
class TlsSecurityConnectorTest : public ::testing::Test {
protected:
TlsSecurityConnectorTest() {}
void SetUp() override {
grpc_slice ca_slice_1, ca_slice_0, cert_slice_1, key_slice_1, cert_slice_0,
key_slice_0;
@ -87,12 +89,27 @@ class TlsSecurityConnectorTest : public ::testing::Test {
grpc_slice_unref(key_slice_0);
}
void TearDown() override {}
static void VerifyExpectedErrorCallback(void* arg, grpc_error_handle error) {
const char* expected_error_msg = static_cast<const char*>(arg);
if (expected_error_msg == nullptr) {
EXPECT_EQ(error, GRPC_ERROR_NONE);
} else {
EXPECT_EQ(GetErrorMsg(error), expected_error_msg);
}
}
static std::string GetErrorMsg(grpc_error_handle error) {
std::string error_str;
GPR_ASSERT(
grpc_error_get_str(error, GRPC_ERROR_STR_DESCRIPTION, &error_str));
return error_str;
}
std::string root_cert_1_;
std::string root_cert_0_;
grpc_core::PemKeyCertPairList identity_pairs_1_;
grpc_core::PemKeyCertPairList identity_pairs_0_;
grpc_core::HostNameCertificateVerifier hostname_certificate_verifier_;
};
class TlsTestCertificateProvider : public ::grpc_tls_certificate_provider {
@ -110,7 +127,10 @@ class TlsTestCertificateProvider : public ::grpc_tls_certificate_provider {
grpc_core::RefCountedPtr<grpc_tls_certificate_distributor> distributor_;
};
// Tests for ChannelSecurityConnector.
//
// Tests for Certificate Providers in ChannelSecurityConnector.
//
TEST_F(TlsSecurityConnectorTest,
RootAndIdentityCertsObtainedWhenCreateChannelSecurityConnector) {
grpc_core::RefCountedPtr<grpc_tls_certificate_distributor> distributor =
@ -347,33 +367,84 @@ TEST_F(TlsSecurityConnectorTest, CreateChannelSecurityConnectorFailNoOptions) {
EXPECT_EQ(connector, nullptr);
}
TEST_F(TlsSecurityConnectorTest, TlsCheckHostNameSuccess) {
const char* target_name = "foo.test.google.fr";
//
// Tests for Certificate Verifier in ChannelSecurityConnector.
//
TEST_F(TlsSecurityConnectorTest,
ChannelSecurityConnectorWithSyncExternalVerifierSucceeds) {
auto* sync_verifier_ = new SyncExternalVerifier(true);
ExternalCertificateVerifier core_external_verifier(sync_verifier_->base());
grpc_core::RefCountedPtr<grpc_tls_credentials_options> options =
grpc_core::MakeRefCounted<grpc_tls_credentials_options>();
options->set_verify_server_cert(true);
options->set_certificate_verifier(core_external_verifier.Ref());
options->set_check_call_host(false);
grpc_core::RefCountedPtr<TlsCredentials> credential =
grpc_core::MakeRefCounted<TlsCredentials>(options);
grpc_channel_args* new_args = nullptr;
grpc_core::RefCountedPtr<grpc_channel_security_connector> connector =
credential->create_security_connector(nullptr, kTargetName, nullptr,
&new_args);
EXPECT_NE(connector, nullptr);
grpc_core::TlsChannelSecurityConnector* tls_connector =
static_cast<grpc_core::TlsChannelSecurityConnector*>(connector.get());
EXPECT_NE(tls_connector->ClientHandshakerFactoryForTesting(), nullptr);
// Construct a basic TSI Peer.
tsi_peer peer;
GPR_ASSERT(tsi_construct_peer(1, &peer) == TSI_OK);
GPR_ASSERT(tsi_construct_peer(2, &peer) == TSI_OK);
GPR_ASSERT(tsi_construct_string_peer_property(TSI_SSL_ALPN_SELECTED_PROTOCOL,
"grpc", strlen("grpc"),
&peer.properties[0]) == TSI_OK);
GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY, target_name,
&peer.properties[0]) == TSI_OK);
grpc_error_handle error =
grpc_core::internal::TlsCheckHostName(target_name, &peer);
tsi_peer_destruct(&peer);
EXPECT_EQ(error, GRPC_ERROR_NONE);
GRPC_ERROR_UNREF(error);
TSI_X509_SUBJECT_COMMON_NAME_PEER_PROPERTY, "foo.bar.com",
&peer.properties[1]) == TSI_OK);
grpc_core::RefCountedPtr<grpc_auth_context> auth_context;
grpc_core::ExecCtx exec_ctx;
grpc_closure* on_peer_checked = GRPC_CLOSURE_CREATE(
VerifyExpectedErrorCallback, nullptr, grpc_schedule_on_exec_ctx);
tls_connector->check_peer(peer, nullptr, &auth_context, on_peer_checked);
grpc_channel_args_destroy(new_args);
}
TEST_F(TlsSecurityConnectorTest, TlsCheckHostNameFail) {
const char* target_name = "foo.test.google.fr";
const char* another_name = "bar.test.google.fr";
TEST_F(TlsSecurityConnectorTest,
ChannelSecurityConnectorWithSyncExternalVerifierFails) {
auto* sync_verifier_ = new SyncExternalVerifier(false);
ExternalCertificateVerifier core_external_verifier(sync_verifier_->base());
grpc_core::RefCountedPtr<grpc_tls_credentials_options> options =
grpc_core::MakeRefCounted<grpc_tls_credentials_options>();
options->set_verify_server_cert(true);
options->set_certificate_verifier(core_external_verifier.Ref());
options->set_check_call_host(false);
grpc_core::RefCountedPtr<TlsCredentials> credential =
grpc_core::MakeRefCounted<TlsCredentials>(options);
grpc_channel_args* new_args = nullptr;
grpc_core::RefCountedPtr<grpc_channel_security_connector> connector =
credential->create_security_connector(nullptr, kTargetName, nullptr,
&new_args);
EXPECT_NE(connector, nullptr);
grpc_core::TlsChannelSecurityConnector* tls_connector =
static_cast<grpc_core::TlsChannelSecurityConnector*>(connector.get());
EXPECT_NE(tls_connector->ClientHandshakerFactoryForTesting(), nullptr);
// Construct a basic TSI Peer.
tsi_peer peer;
GPR_ASSERT(tsi_construct_peer(1, &peer) == TSI_OK);
GPR_ASSERT(tsi_construct_peer(2, &peer) == TSI_OK);
GPR_ASSERT(tsi_construct_string_peer_property(TSI_SSL_ALPN_SELECTED_PROTOCOL,
"grpc", strlen("grpc"),
&peer.properties[0]) == TSI_OK);
GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY, another_name,
&peer.properties[0]) == TSI_OK);
grpc_error_handle error =
grpc_core::internal::TlsCheckHostName(target_name, &peer);
tsi_peer_destruct(&peer);
EXPECT_NE(error, GRPC_ERROR_NONE);
GRPC_ERROR_UNREF(error);
TSI_X509_SUBJECT_COMMON_NAME_PEER_PROPERTY, "foo.bar.com",
&peer.properties[1]) == TSI_OK);
grpc_core::RefCountedPtr<grpc_auth_context> auth_context;
const char* expected_error_msg =
"Custom verification check failed with error: UNAUTHENTICATED: "
"SyncExternalVerifier failed";
grpc_core::ExecCtx exec_ctx;
grpc_closure* on_peer_checked = GRPC_CLOSURE_CREATE(
VerifyExpectedErrorCallback, const_cast<char*>(expected_error_msg),
grpc_schedule_on_exec_ctx);
tls_connector->check_peer(peer, nullptr, &auth_context, on_peer_checked);
grpc_channel_args_destroy(new_args);
}
TEST_F(TlsSecurityConnectorTest,
@ -477,6 +548,192 @@ TEST_F(TlsSecurityConnectorTest,
}
// Tests for ServerSecurityConnector.
TEST_F(TlsSecurityConnectorTest,
ChannelSecurityConnectorWithAsyncExternalVerifierSucceeds) {
auto* async_verifier = new AsyncExternalVerifier(true);
auto* core_external_verifier =
new ExternalCertificateVerifier(async_verifier->base());
auto options = grpc_core::MakeRefCounted<grpc_tls_credentials_options>();
options->set_verify_server_cert(true);
options->set_certificate_verifier(core_external_verifier->Ref());
options->set_check_call_host(false);
grpc_core::RefCountedPtr<TlsCredentials> credential =
grpc_core::MakeRefCounted<TlsCredentials>(options);
grpc_channel_args* new_args = nullptr;
grpc_core::RefCountedPtr<grpc_channel_security_connector> connector =
credential->create_security_connector(nullptr, kTargetName, nullptr,
&new_args);
EXPECT_NE(connector, nullptr);
grpc_core::TlsChannelSecurityConnector* tls_connector =
static_cast<grpc_core::TlsChannelSecurityConnector*>(connector.get());
EXPECT_NE(tls_connector->ClientHandshakerFactoryForTesting(), nullptr);
// Construct a basic TSI Peer.
tsi_peer peer;
GPR_ASSERT(tsi_construct_peer(2, &peer) == TSI_OK);
GPR_ASSERT(tsi_construct_string_peer_property(TSI_SSL_ALPN_SELECTED_PROTOCOL,
"grpc", strlen("grpc"),
&peer.properties[0]) == TSI_OK);
GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
TSI_X509_SUBJECT_COMMON_NAME_PEER_PROPERTY, "foo.bar.com",
&peer.properties[1]) == TSI_OK);
grpc_core::RefCountedPtr<grpc_auth_context> auth_context;
grpc_core::ExecCtx exec_ctx;
grpc_closure* on_peer_checked = GRPC_CLOSURE_CREATE(
VerifyExpectedErrorCallback, nullptr, grpc_schedule_on_exec_ctx);
tls_connector->check_peer(peer, nullptr, &auth_context, on_peer_checked);
grpc_channel_args_destroy(new_args);
core_external_verifier->Unref();
}
TEST_F(TlsSecurityConnectorTest,
ChannelSecurityConnectorWithAsyncExternalVerifierFails) {
auto* async_verifier = new AsyncExternalVerifier(false);
auto* core_external_verifier =
new ExternalCertificateVerifier(async_verifier->base());
auto options = grpc_core::MakeRefCounted<grpc_tls_credentials_options>();
options->set_verify_server_cert(true);
options->set_certificate_verifier(core_external_verifier->Ref());
options->set_check_call_host(false);
grpc_core::RefCountedPtr<TlsCredentials> credential =
grpc_core::MakeRefCounted<TlsCredentials>(options);
grpc_channel_args* new_args = nullptr;
grpc_core::RefCountedPtr<grpc_channel_security_connector> connector =
credential->create_security_connector(nullptr, kTargetName, nullptr,
&new_args);
EXPECT_NE(connector, nullptr);
grpc_core::TlsChannelSecurityConnector* tls_connector =
static_cast<grpc_core::TlsChannelSecurityConnector*>(connector.get());
EXPECT_NE(tls_connector->ClientHandshakerFactoryForTesting(), nullptr);
// Construct a basic TSI Peer.
tsi_peer peer;
GPR_ASSERT(tsi_construct_peer(2, &peer) == TSI_OK);
GPR_ASSERT(tsi_construct_string_peer_property(TSI_SSL_ALPN_SELECTED_PROTOCOL,
"grpc", strlen("grpc"),
&peer.properties[0]) == TSI_OK);
GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
TSI_X509_SUBJECT_COMMON_NAME_PEER_PROPERTY, "foo.bar.com",
&peer.properties[1]) == TSI_OK);
grpc_core::RefCountedPtr<grpc_auth_context> auth_context;
const char* expected_error_msg =
"Custom verification check failed with error: UNAUTHENTICATED: "
"AsyncExternalVerifier failed";
grpc_core::ExecCtx exec_ctx;
grpc_closure* on_peer_checked = GRPC_CLOSURE_CREATE(
VerifyExpectedErrorCallback, const_cast<char*>(expected_error_msg),
grpc_schedule_on_exec_ctx);
tls_connector->check_peer(peer, nullptr, &auth_context, on_peer_checked);
grpc_channel_args_destroy(new_args);
core_external_verifier->Unref();
}
TEST_F(TlsSecurityConnectorTest,
ChannelSecurityConnectorHostnameVerifierSucceeds) {
grpc_core::RefCountedPtr<grpc_tls_credentials_options> options =
grpc_core::MakeRefCounted<grpc_tls_credentials_options>();
options->set_verify_server_cert(true);
options->set_certificate_verifier(hostname_certificate_verifier_.Ref());
options->set_check_call_host(false);
grpc_core::RefCountedPtr<TlsCredentials> credential =
grpc_core::MakeRefCounted<TlsCredentials>(options);
grpc_channel_args* new_args = nullptr;
grpc_core::RefCountedPtr<grpc_channel_security_connector> connector =
credential->create_security_connector(nullptr, kTargetName, nullptr,
&new_args);
EXPECT_NE(connector, nullptr);
grpc_core::TlsChannelSecurityConnector* tls_connector =
static_cast<grpc_core::TlsChannelSecurityConnector*>(connector.get());
EXPECT_NE(tls_connector->ClientHandshakerFactoryForTesting(), nullptr);
// Construct a full TSI Peer.
tsi_peer peer;
GPR_ASSERT(tsi_construct_peer(7, &peer) == TSI_OK);
GPR_ASSERT(tsi_construct_string_peer_property(TSI_SSL_ALPN_SELECTED_PROTOCOL,
"grpc", strlen("grpc"),
&peer.properties[0]) == TSI_OK);
GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
TSI_X509_SUBJECT_COMMON_NAME_PEER_PROPERTY, "foo.bar.com",
&peer.properties[1]) == TSI_OK);
GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
TSI_X509_PEM_CERT_PROPERTY, "pem_cert", &peer.properties[2]) ==
TSI_OK);
GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
TSI_SECURITY_LEVEL_PEER_PROPERTY,
tsi_security_level_to_string(TSI_PRIVACY_AND_INTEGRITY),
&peer.properties[3]) == TSI_OK);
GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
TSI_X509_PEM_CERT_CHAIN_PROPERTY, "pem_cert_chain",
&peer.properties[4]) == TSI_OK);
GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY, "foo.bar.com",
&peer.properties[5]) == TSI_OK);
GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY, "foo.baz.com",
&peer.properties[6]) == TSI_OK);
grpc_core::RefCountedPtr<grpc_auth_context> auth_context;
grpc_core::ExecCtx exec_ctx;
grpc_closure* on_peer_checked = GRPC_CLOSURE_CREATE(
VerifyExpectedErrorCallback, nullptr, grpc_schedule_on_exec_ctx);
tls_connector->check_peer(peer, nullptr, &auth_context, on_peer_checked);
grpc_channel_args_destroy(new_args);
}
TEST_F(TlsSecurityConnectorTest,
ChannelSecurityConnectorHostnameVerifierFails) {
grpc_core::RefCountedPtr<grpc_tls_credentials_options> options =
grpc_core::MakeRefCounted<grpc_tls_credentials_options>();
options->set_verify_server_cert(true);
options->set_certificate_verifier(hostname_certificate_verifier_.Ref());
grpc_core::RefCountedPtr<TlsCredentials> credential =
grpc_core::MakeRefCounted<TlsCredentials>(options);
grpc_channel_args* new_args = nullptr;
grpc_core::RefCountedPtr<grpc_channel_security_connector> connector =
credential->create_security_connector(nullptr, kTargetName, nullptr,
&new_args);
EXPECT_NE(connector, nullptr);
grpc_core::TlsChannelSecurityConnector* tls_connector =
static_cast<grpc_core::TlsChannelSecurityConnector*>(connector.get());
EXPECT_NE(tls_connector->ClientHandshakerFactoryForTesting(), nullptr);
// Construct a full TSI Peer.
tsi_peer peer;
GPR_ASSERT(tsi_construct_peer(7, &peer) == TSI_OK);
GPR_ASSERT(tsi_construct_string_peer_property(TSI_SSL_ALPN_SELECTED_PROTOCOL,
"grpc", strlen("grpc"),
&peer.properties[0]) == TSI_OK);
GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
TSI_X509_SUBJECT_COMMON_NAME_PEER_PROPERTY, "foo.com",
&peer.properties[1]) == TSI_OK);
GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
TSI_X509_PEM_CERT_PROPERTY, "pem_cert", &peer.properties[2]) ==
TSI_OK);
GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
TSI_SECURITY_LEVEL_PEER_PROPERTY,
tsi_security_level_to_string(TSI_PRIVACY_AND_INTEGRITY),
&peer.properties[3]) == TSI_OK);
GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
TSI_X509_PEM_CERT_CHAIN_PROPERTY, "pem_cert_chain",
&peer.properties[4]) == TSI_OK);
GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY, "*.com",
&peer.properties[5]) == TSI_OK);
GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY, "foo.baz.com",
&peer.properties[6]) == TSI_OK);
grpc_core::RefCountedPtr<grpc_auth_context> auth_context;
const char* expected_error_msg =
"Custom verification check failed with error: UNAUTHENTICATED: Hostname "
"Verification "
"Check failed.";
grpc_core::ExecCtx exec_ctx;
grpc_closure* on_peer_checked = GRPC_CLOSURE_CREATE(
VerifyExpectedErrorCallback, const_cast<char*>(expected_error_msg),
grpc_schedule_on_exec_ctx);
tls_connector->check_peer(peer, nullptr, &auth_context, on_peer_checked);
grpc_channel_args_destroy(new_args);
}
//
// Tests for Certificate Providers in ServerSecurityConnector.
//
TEST_F(TlsSecurityConnectorTest,
RootAndIdentityCertsObtainedWhenCreateServerSecurityConnector) {
grpc_core::RefCountedPtr<grpc_tls_certificate_distributor> distributor =
@ -691,8 +948,147 @@ TEST_F(TlsSecurityConnectorTest,
EXPECT_NE(connector->cmp(other_connector.get()), 0);
}
//
// Tests for Certificate Verifier in ServerSecurityConnector.
//
TEST_F(TlsSecurityConnectorTest,
ServerSecurityConnectorWithSyncExternalVerifierSucceeds) {
auto* sync_verifier = new SyncExternalVerifier(true);
ExternalCertificateVerifier core_external_verifier(sync_verifier->base());
grpc_core::RefCountedPtr<grpc_tls_credentials_options> options =
grpc_core::MakeRefCounted<grpc_tls_credentials_options>();
options->set_cert_request_type(GRPC_SSL_DONT_REQUEST_CLIENT_CERTIFICATE);
options->set_certificate_verifier(core_external_verifier.Ref());
auto provider =
grpc_core::MakeRefCounted<grpc_core::StaticDataCertificateProvider>(
"", grpc_core::PemKeyCertPairList());
options->set_certificate_provider(std::move(provider));
options->set_watch_identity_pair(true);
auto credentials = grpc_core::MakeRefCounted<TlsServerCredentials>(options);
auto connector = credentials->create_security_connector(nullptr);
// Construct a basic TSI Peer.
tsi_peer peer;
GPR_ASSERT(tsi_construct_peer(2, &peer) == TSI_OK);
GPR_ASSERT(tsi_construct_string_peer_property(TSI_SSL_ALPN_SELECTED_PROTOCOL,
"grpc", strlen("grpc"),
&peer.properties[0]) == TSI_OK);
GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
TSI_X509_SUBJECT_COMMON_NAME_PEER_PROPERTY, "foo.bar.com",
&peer.properties[1]) == TSI_OK);
grpc_core::RefCountedPtr<grpc_auth_context> auth_context;
grpc_core::ExecCtx exec_ctx;
grpc_closure* on_peer_checked = GRPC_CLOSURE_CREATE(
VerifyExpectedErrorCallback, nullptr, grpc_schedule_on_exec_ctx);
connector->check_peer(peer, nullptr, &auth_context, on_peer_checked);
}
TEST_F(TlsSecurityConnectorTest,
ServerSecurityConnectorWithSyncExternalVerifierFails) {
auto* sync_verifier = new SyncExternalVerifier(false);
ExternalCertificateVerifier core_external_verifier(sync_verifier->base());
grpc_core::RefCountedPtr<grpc_tls_credentials_options> options =
grpc_core::MakeRefCounted<grpc_tls_credentials_options>();
options->set_cert_request_type(GRPC_SSL_DONT_REQUEST_CLIENT_CERTIFICATE);
options->set_certificate_verifier(core_external_verifier.Ref());
auto provider =
grpc_core::MakeRefCounted<grpc_core::StaticDataCertificateProvider>(
"", grpc_core::PemKeyCertPairList());
options->set_certificate_provider(std::move(provider));
options->set_watch_identity_pair(true);
auto credentials = grpc_core::MakeRefCounted<TlsServerCredentials>(options);
auto connector = credentials->create_security_connector(nullptr);
// Construct a basic TSI Peer.
tsi_peer peer;
GPR_ASSERT(tsi_construct_peer(2, &peer) == TSI_OK);
GPR_ASSERT(tsi_construct_string_peer_property(TSI_SSL_ALPN_SELECTED_PROTOCOL,
"grpc", strlen("grpc"),
&peer.properties[0]) == TSI_OK);
GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
TSI_X509_SUBJECT_COMMON_NAME_PEER_PROPERTY, "foo.bar.com",
&peer.properties[1]) == TSI_OK);
grpc_core::RefCountedPtr<grpc_auth_context> auth_context;
const char* expected_error_msg =
"Custom verification check failed with error: UNAUTHENTICATED: "
"SyncExternalVerifier failed";
grpc_core::ExecCtx exec_ctx;
grpc_closure* on_peer_checked = GRPC_CLOSURE_CREATE(
VerifyExpectedErrorCallback, const_cast<char*>(expected_error_msg),
grpc_schedule_on_exec_ctx);
connector->check_peer(peer, nullptr, &auth_context, on_peer_checked);
}
TEST_F(TlsSecurityConnectorTest,
ServerSecurityConnectorWithAsyncExternalVerifierSucceeds) {
auto* async_verifier = new AsyncExternalVerifier(true);
auto* core_external_verifier =
new ExternalCertificateVerifier(async_verifier->base());
auto options = grpc_core::MakeRefCounted<grpc_tls_credentials_options>();
options->set_cert_request_type(GRPC_SSL_DONT_REQUEST_CLIENT_CERTIFICATE);
options->set_certificate_verifier(core_external_verifier->Ref());
auto provider =
grpc_core::MakeRefCounted<grpc_core::StaticDataCertificateProvider>(
"", grpc_core::PemKeyCertPairList());
options->set_certificate_provider(std::move(provider));
options->set_watch_identity_pair(true);
auto credentials = grpc_core::MakeRefCounted<TlsServerCredentials>(options);
auto connector = credentials->create_security_connector(nullptr);
// Construct a basic TSI Peer.
tsi_peer peer;
GPR_ASSERT(tsi_construct_peer(2, &peer) == TSI_OK);
GPR_ASSERT(tsi_construct_string_peer_property(TSI_SSL_ALPN_SELECTED_PROTOCOL,
"grpc", strlen("grpc"),
&peer.properties[0]) == TSI_OK);
GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
TSI_X509_SUBJECT_COMMON_NAME_PEER_PROPERTY, "foo.bar.com",
&peer.properties[1]) == TSI_OK);
grpc_core::RefCountedPtr<grpc_auth_context> auth_context;
grpc_core::ExecCtx exec_ctx;
grpc_closure* on_peer_checked = GRPC_CLOSURE_CREATE(
VerifyExpectedErrorCallback, nullptr, grpc_schedule_on_exec_ctx);
connector->check_peer(peer, nullptr, &auth_context, on_peer_checked);
core_external_verifier->Unref();
}
TEST_F(TlsSecurityConnectorTest,
ServerSecurityConnectorWithAsyncExternalVerifierFails) {
auto* async_verifier = new AsyncExternalVerifier(false);
auto* core_external_verifier =
new ExternalCertificateVerifier(async_verifier->base());
grpc_core::RefCountedPtr<grpc_tls_credentials_options> options =
grpc_core::MakeRefCounted<grpc_tls_credentials_options>();
options->set_cert_request_type(GRPC_SSL_DONT_REQUEST_CLIENT_CERTIFICATE);
options->set_certificate_verifier(core_external_verifier->Ref());
auto provider =
grpc_core::MakeRefCounted<grpc_core::StaticDataCertificateProvider>(
"", grpc_core::PemKeyCertPairList());
options->set_certificate_provider(std::move(provider));
options->set_watch_identity_pair(true);
auto credentials = grpc_core::MakeRefCounted<TlsServerCredentials>(options);
auto connector = credentials->create_security_connector(nullptr);
// Construct a basic TSI Peer.
tsi_peer peer;
GPR_ASSERT(tsi_construct_peer(2, &peer) == TSI_OK);
GPR_ASSERT(tsi_construct_string_peer_property(TSI_SSL_ALPN_SELECTED_PROTOCOL,
"grpc", strlen("grpc"),
&peer.properties[0]) == TSI_OK);
GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
TSI_X509_SUBJECT_COMMON_NAME_PEER_PROPERTY, "foo.bar.com",
&peer.properties[1]) == TSI_OK);
grpc_core::RefCountedPtr<grpc_auth_context> auth_context;
const char* expected_error_msg =
"Custom verification check failed with error: UNAUTHENTICATED: "
"AsyncExternalVerifier failed";
grpc_core::ExecCtx exec_ctx;
grpc_closure* on_peer_checked = GRPC_CLOSURE_CREATE(
VerifyExpectedErrorCallback, const_cast<char*>(expected_error_msg),
grpc_schedule_on_exec_ctx);
connector->check_peer(peer, nullptr, &auth_context, on_peer_checked);
core_external_verifier->Unref();
}
} // namespace testing
} // namespace grpc
} // namespace grpc_core
int main(int argc, char** argv) {
grpc::testing::TestEnvironment env(argc, argv);

View File

@ -216,16 +216,14 @@ int main(int argc, char **argv) {
printf("%lx", (unsigned long) grpc_tls_certificate_provider_file_watcher_create);
printf("%lx", (unsigned long) grpc_tls_certificate_provider_release);
printf("%lx", (unsigned long) grpc_tls_credentials_options_create);
printf("%lx", (unsigned long) grpc_tls_credentials_options_set_cert_request_type);
printf("%lx", (unsigned long) grpc_tls_credentials_options_set_server_verification_option);
printf("%lx", (unsigned long) grpc_tls_credentials_options_set_certificate_provider);
printf("%lx", (unsigned long) grpc_tls_credentials_options_watch_root_certs);
printf("%lx", (unsigned long) grpc_tls_credentials_options_set_root_cert_name);
printf("%lx", (unsigned long) grpc_tls_credentials_options_watch_identity_key_cert_pairs);
printf("%lx", (unsigned long) grpc_tls_credentials_options_set_identity_cert_name);
printf("%lx", (unsigned long) grpc_tls_credentials_options_set_server_authorization_check_config);
printf("%lx", (unsigned long) grpc_tls_server_authorization_check_config_create);
printf("%lx", (unsigned long) grpc_tls_server_authorization_check_config_release);
printf("%lx", (unsigned long) grpc_tls_credentials_options_set_cert_request_type);
printf("%lx", (unsigned long) grpc_tls_credentials_options_set_verify_server_cert);
printf("%lx", (unsigned long) grpc_tls_credentials_options_set_check_call_host);
printf("%lx", (unsigned long) grpc_xds_credentials_create);
printf("%lx", (unsigned long) grpc_xds_server_credentials_create);
printf("%lx", (unsigned long) grpc_authorization_policy_provider_static_data_create);

View File

@ -16,6 +16,8 @@
#include "test/core/util/tls_utils.h"
#include <grpc/support/log.h>
#include "src/core/lib/gpr/tmpfile.h"
#include "src/core/lib/iomgr/load_file.h"
#include "src/core/lib/slice/slice_internal.h"
@ -71,6 +73,102 @@ std::string GetFileContents(const char* path) {
return credential;
}
int SyncExternalVerifier::Verify(void* user_data,
grpc_tls_custom_verification_check_request*,
grpc_tls_on_custom_verification_check_done_cb,
void*, grpc_status_code* sync_status,
char** sync_error_details) {
auto* self = static_cast<SyncExternalVerifier*>(user_data);
if (self->success_) {
*sync_status = GRPC_STATUS_OK;
return true; // Synchronous call
}
*sync_status = GRPC_STATUS_UNAUTHENTICATED;
*sync_error_details = gpr_strdup("SyncExternalVerifier failed");
return true; // Synchronous call
}
void SyncExternalVerifier::Destruct(void* user_data) {
auto* self = static_cast<SyncExternalVerifier*>(user_data);
delete self;
}
AsyncExternalVerifier::~AsyncExternalVerifier() {
// Tell the thread to shut down.
{
MutexLock lock(&mu_);
queue_.push_back(Request{nullptr, nullptr, nullptr, true});
}
// Wait for thread to exit.
thread_.Join();
grpc_shutdown();
}
int AsyncExternalVerifier::Verify(
void* user_data, grpc_tls_custom_verification_check_request* request,
grpc_tls_on_custom_verification_check_done_cb callback, void* callback_arg,
grpc_status_code*, char**) {
auto* self = static_cast<AsyncExternalVerifier*>(user_data);
// Add request to queue to be picked up by worker thread.
MutexLock lock(&self->mu_);
self->queue_.push_back(Request{request, callback, callback_arg, false});
return false; // Asynchronous call
}
namespace {
void DestroyExternalVerifier(void* arg) {
auto* verifier = static_cast<AsyncExternalVerifier*>(arg);
delete verifier;
}
} // namespace
void AsyncExternalVerifier::Destruct(void* user_data) {
auto* self = static_cast<AsyncExternalVerifier*>(user_data);
// Spawn a detached thread to destroy the verifier, to make sure that we don't
// try to join the worker thread from within the worker thread.
grpc_core::Thread destroy_thread(
"DestroyExternalVerifier", DestroyExternalVerifier, self, nullptr,
grpc_core::Thread::Options().set_joinable(false));
destroy_thread.Start();
}
void AsyncExternalVerifier::WorkerThread(void* arg) {
auto* self = static_cast<AsyncExternalVerifier*>(arg);
while (true) {
// Check queue for work.
bool got_request = false;
Request request;
{
MutexLock lock(&self->mu_);
if (!self->queue_.empty()) {
got_request = true;
request = self->queue_.front();
self->queue_.pop_front();
}
}
// If nothing found in the queue, sleep for a bit and try again.
if (!got_request) {
gpr_sleep_until(grpc_timeout_milliseconds_to_deadline(100));
continue;
}
// If we're being told to shut down, return.
if (request.shutdown) {
return;
}
// Process the request.
if (self->success_) {
request.callback(request.request, request.callback_arg, GRPC_STATUS_OK,
"");
} else {
request.callback(request.request, request.callback_arg,
GRPC_STATUS_UNAUTHENTICATED,
"AsyncExternalVerifier failed");
}
}
}
} // namespace testing
} // namespace grpc_core

View File

@ -14,7 +14,11 @@
// limitations under the License.
//
#include <deque>
#include "src/core/lib/gprpp/thd.h"
#include "src/core/lib/security/security_connector/ssl_utils.h"
#include "test/core/util/test_config.h"
namespace grpc_core {
@ -43,6 +47,90 @@ PemKeyCertPairList MakeCertKeyPairs(absl::string_view private_key,
std::string GetFileContents(const char* path);
// A synchronous external verifier implementation that simply returns
// verification results based on users' inputs. Note that it will delete itself
// in Destruct(), so create it like
// ```
// auto* sync_verifier_ = new SyncExternalVerifier(false);
// ```
// and no need to delete it later. This is basically to keep consistent with the
// semantics in AsyncExternalVerifier.
class SyncExternalVerifier {
public:
explicit SyncExternalVerifier(bool success)
: success_(success), base_{this, Verify, Cancel, Destruct} {}
grpc_tls_certificate_verifier_external* base() { return &base_; }
private:
static int Verify(void* user_data,
grpc_tls_custom_verification_check_request* request,
grpc_tls_on_custom_verification_check_done_cb callback,
void* callback_arg, grpc_status_code* sync_status,
char** sync_error_details);
static void Cancel(void*, grpc_tls_custom_verification_check_request*) {}
static void Destruct(void* user_data);
bool success_ = false;
grpc_tls_certificate_verifier_external base_;
};
// An asynchronous external verifier implementation that runs a thread and
// process each request received from the verifier sequentially. Note that it
// will delete itself in Destruct(), so create it like
// ```
// auto* async_verifier = new AsyncExternalVerifier(true, &event);
// auto* core_external_verifier =
// new ExternalCertificateVerifier(async_verifier->base());
// ```
// and no need to delete it later.
// We delete AsyncExternalVerifier in Destruct() instead of its dtor because we
// wanted AsyncExternalVerifier to outlive the underlying core
// ExternalCertificateVerifier implementation.
class AsyncExternalVerifier {
public:
explicit AsyncExternalVerifier(bool success)
: success_(success),
thread_("AsyncExternalVerifierWorkerThread", WorkerThread, this),
base_{this, Verify, Cancel, Destruct} {
grpc_init();
thread_.Start();
}
~AsyncExternalVerifier();
grpc_tls_certificate_verifier_external* base() { return &base_; }
private:
// A request to pass to the worker thread.
struct Request {
grpc_tls_custom_verification_check_request* request;
grpc_tls_on_custom_verification_check_done_cb callback;
void* callback_arg;
bool shutdown; // If true, thread will exit.
};
static int Verify(void* user_data,
grpc_tls_custom_verification_check_request* request,
grpc_tls_on_custom_verification_check_done_cb callback,
void* callback_arg, grpc_status_code* sync_status,
char** sync_error_details);
static void Cancel(void*, grpc_tls_custom_verification_check_request*) {}
static void Destruct(void* user_data);
static void WorkerThread(void* arg);
bool success_ = false;
grpc_core::Thread thread_;
grpc_tls_certificate_verifier_external base_;
Mutex mu_;
std::deque<Request> queue_ ABSL_GUARDED_BY(mu_);
};
} // namespace testing
} // namespace grpc_core

View File

@ -34,6 +34,7 @@ grpc_cc_test(
"//:grpc",
"//:grpc++",
"//test/core/util:grpc_test_util",
"//test/cpp/util:tls_test_utils",
],
)

View File

@ -31,7 +31,7 @@
#include "src/core/lib/gpr/env.h"
#include "src/core/lib/gpr/tmpfile.h"
#include "src/cpp/client/secure_credentials.h"
#include "src/cpp/common/tls_credentials_options_util.h"
#include "test/cpp/util/tls_test_utils.h"
#define CA_CERT_PATH "src/core/tsi/test_creds/ca.pem"
#define SERVER_CERT_PATH "src/core/tsi/test_creds/server1.pem"
@ -45,44 +45,11 @@ constexpr const char* kIdentityCertName = "identity_cert_name";
constexpr const char* kIdentityCertPrivateKey = "identity_private_key";
constexpr const char* kIdentityCertContents = "identity_cert_contents";
using ::grpc::experimental::ExternalCertificateVerifier;
using ::grpc::experimental::FileWatcherCertificateProvider;
using ::grpc::experimental::HostNameCertificateVerifier;
using ::grpc::experimental::StaticDataCertificateProvider;
using ::grpc::experimental::TlsServerAuthorizationCheckArg;
using ::grpc::experimental::TlsServerAuthorizationCheckConfig;
using ::grpc::experimental::TlsServerAuthorizationCheckInterface;
static void tls_server_authorization_check_callback(
grpc_tls_server_authorization_check_arg* arg) {
GPR_ASSERT(arg != nullptr);
std::string cb_user_data = "cb_user_data";
arg->cb_user_data = static_cast<void*>(gpr_strdup(cb_user_data.c_str()));
arg->success = 1;
arg->target_name = gpr_strdup("callback_target_name");
arg->peer_cert = gpr_strdup("callback_peer_cert");
arg->status = GRPC_STATUS_OK;
arg->error_details->set_error_details("callback_error_details");
}
class TestTlsServerAuthorizationCheck
: public TlsServerAuthorizationCheckInterface {
int Schedule(TlsServerAuthorizationCheckArg* arg) override {
GPR_ASSERT(arg != nullptr);
std::string cb_user_data = "cb_user_data";
arg->set_cb_user_data(static_cast<void*>(gpr_strdup(cb_user_data.c_str())));
arg->set_success(1);
arg->set_target_name("sync_target_name");
arg->set_peer_cert("sync_peer_cert");
arg->set_status(GRPC_STATUS_OK);
arg->set_error_details("sync_error_details");
return 1;
}
void Cancel(TlsServerAuthorizationCheckArg* arg) override {
GPR_ASSERT(arg != nullptr);
arg->set_status(GRPC_STATUS_PERMISSION_DENIED);
arg->set_error_details("cancelled");
}
};
} // namespace
namespace grpc {
@ -297,126 +264,9 @@ TEST(CredentialsTest, StsCredentialsOptionsFromEnv) {
gpr_unsetenv("STS_CREDENTIALS");
}
TEST(CredentialsTest, TlsServerAuthorizationCheckArgCallback) {
grpc_tls_server_authorization_check_arg* c_arg =
new grpc_tls_server_authorization_check_arg;
c_arg->cb = tls_server_authorization_check_callback;
c_arg->context = nullptr;
c_arg->error_details = new grpc_tls_error_details();
TlsServerAuthorizationCheckArg* arg =
new TlsServerAuthorizationCheckArg(c_arg);
arg->set_cb_user_data(nullptr);
arg->set_success(0);
arg->set_target_name("target_name");
arg->set_peer_cert("peer_cert");
arg->set_status(GRPC_STATUS_UNAUTHENTICATED);
arg->set_error_details("error_details");
const char* target_name_before_callback = c_arg->target_name;
const char* peer_cert_before_callback = c_arg->peer_cert;
arg->OnServerAuthorizationCheckDoneCallback();
EXPECT_STREQ(static_cast<char*>(arg->cb_user_data()), "cb_user_data");
gpr_free(arg->cb_user_data());
EXPECT_EQ(arg->success(), 1);
EXPECT_STREQ(arg->target_name().c_str(), "callback_target_name");
EXPECT_STREQ(arg->peer_cert().c_str(), "callback_peer_cert");
EXPECT_EQ(arg->status(), GRPC_STATUS_OK);
EXPECT_STREQ(arg->error_details().c_str(), "callback_error_details");
// Cleanup.
gpr_free(const_cast<char*>(target_name_before_callback));
gpr_free(const_cast<char*>(peer_cert_before_callback));
gpr_free(const_cast<char*>(c_arg->target_name));
gpr_free(const_cast<char*>(c_arg->peer_cert));
delete c_arg->error_details;
delete arg;
delete c_arg;
}
TEST(CredentialsTest, TlsServerAuthorizationCheckConfigSchedule) {
std::shared_ptr<TestTlsServerAuthorizationCheck>
test_server_authorization_check(new TestTlsServerAuthorizationCheck());
TlsServerAuthorizationCheckConfig config(test_server_authorization_check);
grpc_tls_server_authorization_check_arg* c_arg =
new grpc_tls_server_authorization_check_arg();
c_arg->error_details = new grpc_tls_error_details();
c_arg->context = nullptr;
TlsServerAuthorizationCheckArg* arg =
new TlsServerAuthorizationCheckArg(c_arg);
arg->set_cb_user_data(nullptr);
arg->set_success(0);
arg->set_target_name("target_name");
arg->set_peer_cert("peer_cert");
arg->set_status(GRPC_STATUS_PERMISSION_DENIED);
arg->set_error_details("error_details");
const char* target_name_before_schedule = c_arg->target_name;
const char* peer_cert_before_schedule = c_arg->peer_cert;
int schedule_output = config.Schedule(arg);
EXPECT_EQ(schedule_output, 1);
EXPECT_STREQ(static_cast<char*>(arg->cb_user_data()), "cb_user_data");
EXPECT_EQ(arg->success(), 1);
EXPECT_STREQ(arg->target_name().c_str(), "sync_target_name");
EXPECT_STREQ(arg->peer_cert().c_str(), "sync_peer_cert");
EXPECT_EQ(arg->status(), GRPC_STATUS_OK);
EXPECT_STREQ(arg->error_details().c_str(), "sync_error_details");
// Cleanup.
gpr_free(arg->cb_user_data());
gpr_free(const_cast<char*>(target_name_before_schedule));
gpr_free(const_cast<char*>(peer_cert_before_schedule));
gpr_free(const_cast<char*>(c_arg->target_name));
gpr_free(const_cast<char*>(c_arg->peer_cert));
delete c_arg->error_details;
if (c_arg->destroy_context != nullptr) {
c_arg->destroy_context(c_arg->context);
}
delete c_arg;
}
TEST(CredentialsTest, TlsServerAuthorizationCheckConfigCppToC) {
std::shared_ptr<TestTlsServerAuthorizationCheck>
test_server_authorization_check(new TestTlsServerAuthorizationCheck());
TlsServerAuthorizationCheckConfig config(test_server_authorization_check);
grpc_tls_server_authorization_check_arg c_arg;
c_arg.cb = tls_server_authorization_check_callback;
c_arg.cb_user_data = nullptr;
c_arg.success = 0;
c_arg.target_name = "target_name";
c_arg.peer_cert = "peer_cert";
c_arg.status = GRPC_STATUS_UNAUTHENTICATED;
c_arg.error_details = new grpc_tls_error_details();
c_arg.error_details->set_error_details("error_details");
c_arg.config = config.c_config();
c_arg.context = nullptr;
int c_schedule_output = (c_arg.config)->Schedule(&c_arg);
EXPECT_EQ(c_schedule_output, 1);
EXPECT_STREQ(static_cast<char*>(c_arg.cb_user_data), "cb_user_data");
EXPECT_EQ(c_arg.success, 1);
EXPECT_STREQ(c_arg.target_name, "sync_target_name");
EXPECT_STREQ(c_arg.peer_cert, "sync_peer_cert");
EXPECT_EQ(c_arg.status, GRPC_STATUS_OK);
EXPECT_STREQ(c_arg.error_details->error_details().c_str(),
"sync_error_details");
// Cleanup.
gpr_free(c_arg.cb_user_data);
c_arg.destroy_context(c_arg.context);
delete c_arg.error_details;
gpr_free(const_cast<char*>(c_arg.target_name));
gpr_free(const_cast<char*>(c_arg.peer_cert));
}
TEST(CredentialsTest, TlsChannelCredentialsWithDefaultRoots) {
TEST(CredentialsTest, TlsChannelCredentialsWithDefaultRootsAndDefaultVerifier) {
grpc::experimental::TlsChannelCredentialsOptions options;
options.set_server_verification_option(GRPC_TLS_SERVER_VERIFICATION);
auto test_server_authorization_check =
std::make_shared<TestTlsServerAuthorizationCheck>();
auto server_authorization_check_config =
std::make_shared<TlsServerAuthorizationCheckConfig>(
test_server_authorization_check);
options.set_server_authorization_check_config(
server_authorization_check_config);
options.set_verify_server_certs(true);
auto channel_credentials = grpc::experimental::TlsCredentials(options);
GPR_ASSERT(channel_credentials.get() != nullptr);
}
@ -431,20 +281,12 @@ TEST(
identity_key_cert_pairs.emplace_back(key_cert_pair);
auto certificate_provider = std::make_shared<StaticDataCertificateProvider>(
kRootCertContents, identity_key_cert_pairs);
auto test_server_authorization_check =
std::make_shared<TestTlsServerAuthorizationCheck>();
auto server_authorization_check_config =
std::make_shared<TlsServerAuthorizationCheckConfig>(
test_server_authorization_check);
grpc::experimental::TlsChannelCredentialsOptions options;
options.set_certificate_provider(certificate_provider);
options.watch_root_certs();
options.set_root_cert_name(kRootCertName);
options.watch_identity_key_cert_pairs();
options.set_identity_cert_name(kIdentityCertName);
options.set_server_verification_option(GRPC_TLS_SERVER_VERIFICATION);
options.set_server_authorization_check_config(
server_authorization_check_config);
auto channel_credentials = grpc::experimental::TlsCredentials(options);
GPR_ASSERT(channel_credentials.get() != nullptr);
}
@ -453,20 +295,12 @@ TEST(CredentialsTest,
TlsChannelCredentialsWithStaticDataCertificateProviderLoadingRootOnly) {
auto certificate_provider =
std::make_shared<StaticDataCertificateProvider>(kRootCertContents);
auto test_server_authorization_check =
std::make_shared<TestTlsServerAuthorizationCheck>();
auto server_authorization_check_config =
std::make_shared<TlsServerAuthorizationCheckConfig>(
test_server_authorization_check);
GPR_ASSERT(certificate_provider != nullptr);
GPR_ASSERT(certificate_provider->c_provider() != nullptr);
grpc::experimental::TlsChannelCredentialsOptions options;
options.set_certificate_provider(certificate_provider);
options.watch_root_certs();
options.set_root_cert_name(kRootCertName);
options.set_server_verification_option(GRPC_TLS_SERVER_VERIFICATION);
options.set_server_authorization_check_config(
server_authorization_check_config);
auto channel_credentials = grpc::experimental::TlsCredentials(options);
GPR_ASSERT(channel_credentials.get() != nullptr);
}
@ -481,18 +315,10 @@ TEST(
identity_key_cert_pairs.emplace_back(key_cert_pair);
auto certificate_provider =
std::make_shared<StaticDataCertificateProvider>(identity_key_cert_pairs);
auto test_server_authorization_check =
std::make_shared<TestTlsServerAuthorizationCheck>();
auto server_authorization_check_config =
std::make_shared<TlsServerAuthorizationCheckConfig>(
test_server_authorization_check);
grpc::experimental::TlsChannelCredentialsOptions options;
options.set_certificate_provider(certificate_provider);
options.watch_identity_key_cert_pairs();
options.set_identity_cert_name(kIdentityCertName);
options.set_server_verification_option(GRPC_TLS_SERVER_VERIFICATION);
options.set_server_authorization_check_config(
server_authorization_check_config);
auto channel_credentials = grpc::experimental::TlsCredentials(options);
GPR_ASSERT(channel_credentials.get() != nullptr);
}
@ -508,14 +334,6 @@ TEST(
options.set_root_cert_name(kRootCertName);
options.watch_identity_key_cert_pairs();
options.set_identity_cert_name(kIdentityCertName);
options.set_server_verification_option(GRPC_TLS_SERVER_VERIFICATION);
auto test_server_authorization_check =
std::make_shared<TestTlsServerAuthorizationCheck>();
auto server_authorization_check_config =
std::make_shared<TlsServerAuthorizationCheckConfig>(
test_server_authorization_check);
options.set_server_authorization_check_config(
server_authorization_check_config);
auto channel_credentials = grpc::experimental::TlsCredentials(options);
GPR_ASSERT(channel_credentials.get() != nullptr);
}
@ -528,48 +346,39 @@ TEST(CredentialsTest,
options.set_certificate_provider(certificate_provider);
options.watch_root_certs();
options.set_root_cert_name(kRootCertName);
options.set_server_verification_option(GRPC_TLS_SERVER_VERIFICATION);
auto test_server_authorization_check =
std::make_shared<TestTlsServerAuthorizationCheck>();
auto server_authorization_check_config =
std::make_shared<TlsServerAuthorizationCheckConfig>(
test_server_authorization_check);
options.set_server_authorization_check_config(
server_authorization_check_config);
auto channel_credentials = grpc::experimental::TlsCredentials(options);
GPR_ASSERT(channel_credentials.get() != nullptr);
}
TEST(CredentialsTest, TlsServerAuthorizationCheckConfigErrorMessages) {
std::shared_ptr<TlsServerAuthorizationCheckConfig> config(
new TlsServerAuthorizationCheckConfig(nullptr));
grpc_tls_server_authorization_check_arg* c_arg =
new grpc_tls_server_authorization_check_arg;
c_arg->error_details = new grpc_tls_error_details();
c_arg->context = nullptr;
TlsServerAuthorizationCheckArg* arg =
new TlsServerAuthorizationCheckArg(c_arg);
int schedule_output = config->Schedule(arg);
TEST(CredentialsTest, TlsChannelCredentialsWithHostNameVerifier) {
auto verifier = std::make_shared<HostNameCertificateVerifier>();
grpc::experimental::TlsChannelCredentialsOptions options;
options.set_verify_server_certs(true);
options.set_certificate_verifier(verifier);
auto channel_credentials = grpc::experimental::TlsCredentials(options);
GPR_ASSERT(channel_credentials.get() != nullptr);
}
EXPECT_EQ(schedule_output, 1);
EXPECT_EQ(arg->status(), GRPC_STATUS_NOT_FOUND);
EXPECT_STREQ(
arg->error_details().c_str(),
"the interface of the server authorization check config is nullptr");
TEST(CredentialsTest, TlsChannelCredentialsWithSyncExternalVerifier) {
auto verifier =
ExternalCertificateVerifier::Create<SyncCertificateVerifier>(true);
grpc::experimental::TlsChannelCredentialsOptions options;
options.set_verify_server_certs(true);
options.set_certificate_verifier(verifier);
options.set_check_call_host(false);
auto channel_credentials = grpc::experimental::TlsCredentials(options);
GPR_ASSERT(channel_credentials.get() != nullptr);
}
arg->set_status(GRPC_STATUS_OK);
config->Cancel(arg);
EXPECT_EQ(arg->status(), GRPC_STATUS_NOT_FOUND);
EXPECT_STREQ(
arg->error_details().c_str(),
"the interface of the server authorization check config is nullptr");
// Cleanup.
delete c_arg->error_details;
if (c_arg->destroy_context != nullptr) {
c_arg->destroy_context(c_arg->context);
}
delete c_arg;
TEST(CredentialsTest, TlsChannelCredentialsWithAsyncExternalVerifier) {
auto verifier =
ExternalCertificateVerifier::Create<AsyncCertificateVerifier>(true);
grpc::experimental::TlsChannelCredentialsOptions options;
options.set_verify_server_certs(true);
options.set_certificate_verifier(verifier);
options.set_check_call_host(false);
auto channel_credentials = grpc::experimental::TlsCredentials(options);
GPR_ASSERT(channel_credentials.get() != nullptr);
}
} // namespace

View File

@ -97,6 +97,7 @@ grpc_cc_test(
"//test/cpp/end2end:test_service_impl",
"//test/cpp/util:test_config",
"//test/cpp/util:test_util",
"//test/cpp/util:tls_test_utils",
],
)

View File

@ -103,6 +103,7 @@
#include "test/cpp/end2end/test_service_impl.h"
#include "test/cpp/end2end/xds/xds_server.h"
#include "test/cpp/util/test_config.h"
#include "test/cpp/util/tls_test_utils.h"
#ifndef DISABLED_XDS_PROTO_IN_CC
#include "src/cpp/server/csds/csds.h"
@ -139,6 +140,9 @@ using ::envoy::type::matcher::v3::StringMatcher;
using ::envoy::type::v3::FractionalPercent;
using ClientStats = LrsServiceImpl::ClientStats;
using ::grpc::experimental::ExternalCertificateVerifier;
using ::grpc::experimental::IdentityKeyCertPair;
using ::grpc::experimental::StaticDataCertificateProvider;
constexpr char kDefaultLocalityRegion[] = "xds_default_locality_region";
constexpr char kDefaultLocalityZone[] = "xds_default_locality_zone";
@ -538,34 +542,25 @@ class FakeCertificateProviderFactory
FakeCertificateProvider::CertDataMap* g_fake1_cert_data_map = nullptr;
FakeCertificateProvider::CertDataMap* g_fake2_cert_data_map = nullptr;
int ServerAuthCheckSchedule(void* /* config_user_data */,
grpc_tls_server_authorization_check_arg* arg) {
arg->success = 1;
arg->status = GRPC_STATUS_OK;
return 0; /* synchronous check */
}
std::shared_ptr<ChannelCredentials> CreateTlsFallbackCredentials() {
// TODO(yashykt): Switch to using C++ API once b/173823806 is fixed.
grpc_tls_credentials_options* options = grpc_tls_credentials_options_create();
grpc_tls_credentials_options_set_server_verification_option(
options, GRPC_TLS_SKIP_HOSTNAME_VERIFICATION);
grpc_tls_credentials_options_set_certificate_provider(
options,
grpc_core::MakeRefCounted<grpc_core::StaticDataCertificateProvider>(
ReadFile(kCaCertPath),
ReadTlsIdentityPair(kServerKeyPath, kServerCertPath))
.get());
grpc_tls_credentials_options_watch_root_certs(options);
grpc_tls_credentials_options_watch_identity_key_cert_pairs(options);
grpc_tls_server_authorization_check_config* check_config =
grpc_tls_server_authorization_check_config_create(
nullptr, ServerAuthCheckSchedule, nullptr, nullptr);
grpc_tls_credentials_options_set_server_authorization_check_config(
options, check_config);
auto channel_creds = std::make_shared<SecureChannelCredentials>(
grpc_tls_credentials_create(options));
grpc_tls_server_authorization_check_config_release(check_config);
IdentityKeyCertPair key_cert_pair;
key_cert_pair.private_key = ReadFile(kServerKeyPath);
key_cert_pair.certificate_chain = ReadFile(kServerCertPath);
std::vector<IdentityKeyCertPair> identity_key_cert_pairs;
identity_key_cert_pairs.emplace_back(key_cert_pair);
auto certificate_provider = std::make_shared<StaticDataCertificateProvider>(
ReadFile(kCaCertPath), identity_key_cert_pairs);
grpc::experimental::TlsChannelCredentialsOptions options;
options.set_certificate_provider(std::move(certificate_provider));
options.watch_root_certs();
options.watch_identity_key_cert_pairs();
auto verifier =
ExternalCertificateVerifier::Create<SyncCertificateVerifier>(true);
options.set_certificate_verifier(std::move(verifier));
options.set_verify_server_certs(true);
options.set_check_call_host(false);
auto channel_creds = grpc::experimental::TlsCredentials(options);
GPR_ASSERT(channel_creds.get() != nullptr);
return channel_creds;
}
@ -8502,27 +8497,23 @@ class XdsServerSecurityTest : public XdsEnd2endTest {
args.SetInt(GRPC_ARG_USE_LOCAL_SUBCHANNEL_POOL, 1);
std::string uri = absl::StrCat(
ipv6_only_ ? "ipv6:[::1]:" : "ipv4:127.0.0.1:", backends_[0]->port());
// TODO(yashykt): Switch to using C++ API once b/173823806 is fixed.
grpc_tls_credentials_options* options =
grpc_tls_credentials_options_create();
grpc_tls_credentials_options_set_server_verification_option(
options, GRPC_TLS_SKIP_HOSTNAME_VERIFICATION);
grpc_tls_credentials_options_set_certificate_provider(
options,
grpc_core::MakeRefCounted<grpc_core::StaticDataCertificateProvider>(
ReadFile(kCaCertPath),
ReadTlsIdentityPair(kServerKeyPath, kServerCertPath))
.get());
grpc_tls_credentials_options_watch_root_certs(options);
grpc_tls_credentials_options_watch_identity_key_cert_pairs(options);
grpc_tls_server_authorization_check_config* check_config =
grpc_tls_server_authorization_check_config_create(
nullptr, ServerAuthCheckSchedule, nullptr, nullptr);
grpc_tls_credentials_options_set_server_authorization_check_config(
options, check_config);
auto channel_creds = std::make_shared<SecureChannelCredentials>(
grpc_tls_credentials_create(options));
grpc_tls_server_authorization_check_config_release(check_config);
IdentityKeyCertPair key_cert_pair;
key_cert_pair.private_key = ReadFile(kServerKeyPath);
key_cert_pair.certificate_chain = ReadFile(kServerCertPath);
std::vector<IdentityKeyCertPair> identity_key_cert_pairs;
identity_key_cert_pairs.emplace_back(key_cert_pair);
auto certificate_provider = std::make_shared<StaticDataCertificateProvider>(
ReadFile(kCaCertPath), identity_key_cert_pairs);
grpc::experimental::TlsChannelCredentialsOptions options;
options.set_certificate_provider(std::move(certificate_provider));
options.watch_root_certs();
options.watch_identity_key_cert_pairs();
auto verifier =
ExternalCertificateVerifier::Create<SyncCertificateVerifier>(true);
options.set_verify_server_certs(true);
options.set_certificate_verifier(std::move(verifier));
auto channel_creds = grpc::experimental::TlsCredentials(options);
GPR_ASSERT(channel_creds.get() != nullptr);
return CreateCustomChannel(uri, channel_creds, args);
}
@ -8534,26 +8525,17 @@ class XdsServerSecurityTest : public XdsEnd2endTest {
args.SetInt(GRPC_ARG_USE_LOCAL_SUBCHANNEL_POOL, 1);
std::string uri = absl::StrCat(
ipv6_only_ ? "ipv6:[::1]:" : "ipv4:127.0.0.1:", backends_[0]->port());
// TODO(yashykt): Switch to using C++ API once b/173823806 is fixed.
grpc_tls_credentials_options* options =
grpc_tls_credentials_options_create();
grpc_tls_credentials_options_set_server_verification_option(
options, GRPC_TLS_SKIP_HOSTNAME_VERIFICATION);
grpc_tls_credentials_options_set_certificate_provider(
options,
grpc_core::MakeRefCounted<grpc_core::StaticDataCertificateProvider>(
ReadFile(kCaCertPath),
ReadTlsIdentityPair(kServerKeyPath, kServerCertPath))
.get());
grpc_tls_credentials_options_watch_root_certs(options);
grpc_tls_server_authorization_check_config* check_config =
grpc_tls_server_authorization_check_config_create(
nullptr, ServerAuthCheckSchedule, nullptr, nullptr);
grpc_tls_credentials_options_set_server_authorization_check_config(
options, check_config);
auto channel_creds = std::make_shared<SecureChannelCredentials>(
grpc_tls_credentials_create(options));
grpc_tls_server_authorization_check_config_release(check_config);
auto certificate_provider =
std::make_shared<StaticDataCertificateProvider>(ReadFile(kCaCertPath));
grpc::experimental::TlsChannelCredentialsOptions options;
options.set_certificate_provider(std::move(certificate_provider));
options.watch_root_certs();
auto verifier =
ExternalCertificateVerifier::Create<SyncCertificateVerifier>(true);
options.set_verify_server_certs(true);
options.set_certificate_verifier(std::move(verifier));
auto channel_creds = grpc::experimental::TlsCredentials(options);
GPR_ASSERT(channel_creds.get() != nullptr);
return CreateCustomChannel(uri, channel_creds, args);
}

34
test/cpp/security/BUILD Normal file
View File

@ -0,0 +1,34 @@
# Copyright 2021 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.
load("//bazel:grpc_build_system.bzl", "grpc_cc_test", "grpc_package")
licenses(["notice"])
grpc_package(name = "test/cpp/security")
grpc_cc_test(
name = "tls_certificate_verifier_test",
srcs = ["tls_certificate_verifier_test.cc"],
external_deps = [
"gtest",
],
deps = [
"//:gpr",
"//:grpc",
"//:grpc++",
"//test/core/util:grpc_test_util",
"//test/cpp/util:tls_test_utils",
],
)

View File

@ -0,0 +1,161 @@
//
// Copyright 2021 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 <memory>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <grpc/grpc.h>
#include <grpc/grpc_security.h>
#include <grpcpp/security/server_credentials.h>
#include <grpcpp/security/tls_credentials_options.h>
#include "src/cpp/client/secure_credentials.h"
#include "test/core/util/port.h"
#include "test/core/util/test_config.h"
#include "test/cpp/util/tls_test_utils.h"
namespace {
using ::grpc::experimental::ExternalCertificateVerifier;
using ::grpc::experimental::HostNameCertificateVerifier;
using ::grpc::experimental::TlsCustomVerificationCheckRequest;
} // namespace
namespace grpc {
namespace testing {
namespace {
TEST(TlsCertificateVerifierTest, SyncCertificateVerifierSucceeds) {
grpc_tls_custom_verification_check_request request;
auto verifier =
ExternalCertificateVerifier::Create<SyncCertificateVerifier>(true);
TlsCustomVerificationCheckRequest cpp_request(&request);
grpc::Status sync_status;
verifier->Verify(&cpp_request, nullptr, &sync_status);
EXPECT_TRUE(sync_status.ok())
<< sync_status.error_code() << " " << sync_status.error_message();
}
TEST(TlsCertificateVerifierTest, SyncCertificateVerifierFails) {
grpc_tls_custom_verification_check_request request;
auto verifier =
ExternalCertificateVerifier::Create<SyncCertificateVerifier>(false);
TlsCustomVerificationCheckRequest cpp_request(&request);
grpc::Status sync_status;
verifier->Verify(&cpp_request, nullptr, &sync_status);
EXPECT_EQ(sync_status.error_code(), grpc::StatusCode::UNAUTHENTICATED);
EXPECT_EQ(sync_status.error_message(), "SyncCertificateVerifier failed");
}
TEST(TlsCertificateVerifierTest, AsyncCertificateVerifierSucceeds) {
grpc_tls_custom_verification_check_request request;
auto verifier =
ExternalCertificateVerifier::Create<AsyncCertificateVerifier>(true);
TlsCustomVerificationCheckRequest cpp_request(&request);
std::function<void(grpc::Status)> callback = [](grpc::Status async_status) {
EXPECT_TRUE(async_status.ok())
<< async_status.error_code() << " " << async_status.error_message();
};
grpc::Status sync_status;
EXPECT_FALSE(verifier->Verify(&cpp_request, callback, &sync_status));
}
TEST(TlsCertificateVerifierTest, AsyncCertificateVerifierFails) {
grpc_tls_custom_verification_check_request request;
auto verifier =
ExternalCertificateVerifier::Create<AsyncCertificateVerifier>(false);
TlsCustomVerificationCheckRequest cpp_request(&request);
std::function<void(grpc::Status)> callback = [](grpc::Status async_status) {
EXPECT_EQ(async_status.error_code(), grpc::StatusCode::UNAUTHENTICATED);
EXPECT_EQ(async_status.error_message(), "AsyncCertificateVerifier failed");
};
grpc::Status sync_status;
EXPECT_FALSE(verifier->Verify(&cpp_request, callback, &sync_status));
}
TEST(TlsCertificateVerifierTest, HostNameCertificateVerifierSucceeds) {
grpc_tls_custom_verification_check_request request;
memset(&request, 0, sizeof(request));
request.target_name = "foo.bar.com";
request.peer_info.common_name = "foo.bar.com";
auto verifier = std::make_shared<HostNameCertificateVerifier>();
TlsCustomVerificationCheckRequest cpp_request(&request);
grpc::Status sync_status;
verifier->Verify(&cpp_request, nullptr, &sync_status);
EXPECT_TRUE(sync_status.ok())
<< sync_status.error_code() << " " << sync_status.error_message();
}
TEST(TlsCertificateVerifierTest, HostNameCertificateVerifierFails) {
grpc_tls_custom_verification_check_request request;
memset(&request, 0, sizeof(request));
request.target_name = "foo.bar.com";
request.peer_info.common_name = "foo.baz.com";
auto verifier = std::make_shared<HostNameCertificateVerifier>();
TlsCustomVerificationCheckRequest cpp_request(&request);
grpc::Status sync_status;
verifier->Verify(&cpp_request, nullptr, &sync_status);
EXPECT_EQ(sync_status.error_code(), grpc::StatusCode::UNAUTHENTICATED);
EXPECT_EQ(sync_status.error_message(), "Hostname Verification Check failed.");
}
TEST(TlsCertificateVerifierTest,
HostNameCertificateVerifierSucceedsMultipleFields) {
grpc_tls_custom_verification_check_request request;
memset(&request, 0, sizeof(request));
request.target_name = "foo.bar.com";
request.peer_info.common_name = "foo.baz.com";
char* dns_names[] = {const_cast<char*>("*.bar.com")};
request.peer_info.san_names.dns_names = dns_names;
request.peer_info.san_names.dns_names_size = 1;
auto verifier = std::make_shared<HostNameCertificateVerifier>();
TlsCustomVerificationCheckRequest cpp_request(&request);
grpc::Status sync_status;
verifier->Verify(&cpp_request, nullptr, &sync_status);
EXPECT_TRUE(sync_status.ok())
<< sync_status.error_code() << " " << sync_status.error_message();
}
TEST(TlsCertificateVerifierTest,
HostNameCertificateVerifierFailsMultipleFields) {
grpc_tls_custom_verification_check_request request;
memset(&request, 0, sizeof(request));
request.target_name = "foo.bar.com";
request.peer_info.common_name = "foo.baz.com";
char* dns_names[] = {const_cast<char*>("*.")};
request.peer_info.san_names.dns_names = dns_names;
request.peer_info.san_names.dns_names_size = 1;
auto verifier = std::make_shared<HostNameCertificateVerifier>();
TlsCustomVerificationCheckRequest cpp_request(&request);
grpc::Status sync_status;
verifier->Verify(&cpp_request, nullptr, &sync_status);
EXPECT_EQ(sync_status.error_code(), grpc::StatusCode::UNAUTHENTICATED);
EXPECT_EQ(sync_status.error_message(), "Hostname Verification Check failed.");
}
} // namespace
} // namespace testing
} // namespace grpc
int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
grpc::testing::TestEnvironment env(argc, argv);
int ret = RUN_ALL_TESTS();
return ret;
}

View File

@ -76,6 +76,7 @@ grpc_cc_test(
"//:grpc",
"//:grpc++",
"//test/core/util:grpc_test_util",
"//test/cpp/util:tls_test_utils",
],
)

View File

@ -27,6 +27,7 @@
#include "src/cpp/client/secure_credentials.h"
#include "test/core/util/port.h"
#include "test/core/util/test_config.h"
#include "test/cpp/util/tls_test_utils.h"
#define CA_CERT_PATH "src/core/tsi/test_creds/ca.pem"
#define SERVER_CERT_PATH "src/core/tsi/test_creds/server1.pem"
@ -40,6 +41,7 @@ constexpr const char* kIdentityCertName = "identity_cert_name";
constexpr const char* kIdentityCertPrivateKey = "identity_private_key";
constexpr const char* kIdentityCertContents = "identity_cert_contents";
using ::grpc::experimental::ExternalCertificateVerifier;
using ::grpc::experimental::FileWatcherCertificateProvider;
using ::grpc::experimental::StaticDataCertificateProvider;
@ -124,6 +126,40 @@ TEST(
GPR_ASSERT(server_credentials.get() != nullptr);
}
TEST(CredentialsTest, TlsServerCredentialsWithSyncExternalVerifier) {
auto verifier =
ExternalCertificateVerifier::Create<SyncCertificateVerifier>(true);
auto certificate_provider = std::make_shared<FileWatcherCertificateProvider>(
SERVER_KEY_PATH, SERVER_CERT_PATH, CA_CERT_PATH, 1);
grpc::experimental::TlsServerCredentialsOptions options(certificate_provider);
options.watch_root_certs();
options.set_root_cert_name(kRootCertName);
options.watch_identity_key_cert_pairs();
options.set_identity_cert_name(kIdentityCertName);
options.set_cert_request_type(
GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY);
options.set_certificate_verifier(verifier);
auto server_credentials = grpc::experimental::TlsServerCredentials(options);
GPR_ASSERT(server_credentials.get() != nullptr);
}
TEST(CredentialsTest, TlsServerCredentialsWithAsyncExternalVerifier) {
auto verifier =
ExternalCertificateVerifier::Create<AsyncCertificateVerifier>(true);
auto certificate_provider = std::make_shared<FileWatcherCertificateProvider>(
SERVER_KEY_PATH, SERVER_CERT_PATH, CA_CERT_PATH, 1);
grpc::experimental::TlsServerCredentialsOptions options(certificate_provider);
options.watch_root_certs();
options.set_root_cert_name(kRootCertName);
options.watch_identity_key_cert_pairs();
options.set_identity_cert_name(kIdentityCertName);
options.set_cert_request_type(
GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY);
options.set_certificate_verifier(verifier);
auto server_credentials = grpc::experimental::TlsServerCredentials(options);
GPR_ASSERT(server_credentials.get() != nullptr);
}
} // namespace
} // namespace testing
} // namespace grpc

View File

@ -364,3 +364,19 @@ grpc_cc_test(
"//test/cpp/util:test_util",
],
)
grpc_cc_library(
name = "tls_test_utils",
srcs = [
"tls_test_utils.cc",
],
hdrs = [
"tls_test_utils.h",
],
deps = [
"//:gpr",
"//:grpc",
"//:grpc++",
"//test/core/util:grpc_test_util",
],
)

View File

@ -0,0 +1,99 @@
//
// Copyright 2021 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 "test/cpp/util/tls_test_utils.h"
#include <memory>
#include "src/core/lib/gprpp/thd.h"
#include "test/core/util/port.h"
#include "test/core/util/test_config.h"
using ::grpc::experimental::ExternalCertificateVerifier;
using ::grpc::experimental::TlsCustomVerificationCheckRequest;
namespace grpc {
namespace testing {
bool SyncCertificateVerifier::Verify(TlsCustomVerificationCheckRequest*,
std::function<void(grpc::Status)>,
grpc::Status* sync_status) {
if (!success_) {
*sync_status = grpc::Status(grpc::StatusCode::UNAUTHENTICATED,
"SyncCertificateVerifier failed");
} else {
*sync_status = grpc::Status(grpc::StatusCode::OK, "");
}
return true;
}
AsyncCertificateVerifier::AsyncCertificateVerifier(bool success)
: success_(success),
thread_("AsyncCertificateVerifierWorkerThread", WorkerThread, this) {
thread_.Start();
}
AsyncCertificateVerifier::~AsyncCertificateVerifier() {
// Tell the thread to shut down.
{
internal::MutexLock lock(&mu_);
queue_.push_back(Request{nullptr, nullptr, true});
}
// Wait for thread to exit.
thread_.Join();
}
bool AsyncCertificateVerifier::Verify(
TlsCustomVerificationCheckRequest* request,
std::function<void(grpc::Status)> callback, grpc::Status*) {
internal::MutexLock lock(&mu_);
queue_.push_back(Request{request, std::move(callback), false});
return false; // Asynchronous call
}
void AsyncCertificateVerifier::WorkerThread(void* arg) {
auto* self = static_cast<AsyncCertificateVerifier*>(arg);
while (true) {
// Check queue for work.
bool got_request = false;
Request request;
{
internal::MutexLock lock(&self->mu_);
if (!self->queue_.empty()) {
got_request = true;
request = self->queue_.front();
self->queue_.pop_front();
}
}
// If nothing found in the queue, sleep for a bit and try again.
if (!got_request) {
gpr_sleep_until(grpc_timeout_milliseconds_to_deadline(100));
continue;
}
// If we're being told to shut down, return.
if (request.shutdown) return;
auto return_status = grpc::Status(grpc::StatusCode::OK, "");
// Process the request.
if (!self->success_) {
return_status = grpc::Status(grpc::StatusCode::UNAUTHENTICATED,
"AsyncCertificateVerifier failed");
}
request.callback(return_status);
}
}
} // namespace testing
} // namespace grpc

View File

@ -0,0 +1,82 @@
//
// Copyright 2021 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.
//
#ifndef GRPC_TEST_CPP_UTIL_TLS_TEST_UTILS_H
#define GRPC_TEST_CPP_UTIL_TLS_TEST_UTILS_H
#include <deque>
#include <grpc/grpc.h>
#include <grpc/grpc_security.h>
#include <grpcpp/security/server_credentials.h>
#include "src/core/lib/gprpp/thd.h"
namespace grpc {
namespace testing {
class SyncCertificateVerifier
: public ::grpc::experimental::ExternalCertificateVerifier {
public:
explicit SyncCertificateVerifier(bool success) : success_(success) {}
~SyncCertificateVerifier() override {}
bool Verify(::grpc::experimental::TlsCustomVerificationCheckRequest* request,
std::function<void(grpc::Status)> callback,
grpc::Status* sync_status) override;
void Cancel(
::grpc::experimental::TlsCustomVerificationCheckRequest*) override {}
private:
bool success_ = false;
};
class AsyncCertificateVerifier
: public ::grpc::experimental::ExternalCertificateVerifier {
public:
explicit AsyncCertificateVerifier(bool success);
~AsyncCertificateVerifier() override;
bool Verify(::grpc::experimental::TlsCustomVerificationCheckRequest* request,
std::function<void(grpc::Status)> callback,
grpc::Status* sync_status) override;
void Cancel(
::grpc::experimental::TlsCustomVerificationCheckRequest*) override {}
private:
// A request to pass to the worker thread.
struct Request {
::grpc::experimental::TlsCustomVerificationCheckRequest* request;
std::function<void(grpc::Status)> callback;
bool shutdown; // If true, thread will exit.
};
static void WorkerThread(void* arg);
bool success_ = false;
grpc_core::Thread thread_;
grpc::internal::Mutex mu_;
std::deque<Request> queue_ ABSL_GUARDED_BY(mu_);
};
} // namespace testing
} // namespace grpc
#endif // GRPC_TEST_CPP_UTIL_TLS_TEST_UTILS_H

View File

@ -1021,6 +1021,7 @@ include/grpcpp/security/binder_security_policy.h \
include/grpcpp/security/credentials.h \
include/grpcpp/security/server_credentials.h \
include/grpcpp/security/tls_certificate_provider.h \
include/grpcpp/security/tls_certificate_verifier.h \
include/grpcpp/security/tls_credentials_options.h \
include/grpcpp/server.h \
include/grpcpp/server_builder.h \

View File

@ -1021,6 +1021,7 @@ include/grpcpp/security/binder_security_policy.h \
include/grpcpp/security/credentials.h \
include/grpcpp/security/server_credentials.h \
include/grpcpp/security/tls_certificate_provider.h \
include/grpcpp/security/tls_certificate_verifier.h \
include/grpcpp/security/tls_credentials_options.h \
include/grpcpp/server.h \
include/grpcpp/server_builder.h \
@ -2098,6 +2099,8 @@ src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.cc \
src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.h \
src/core/lib/security/credentials/tls/grpc_tls_certificate_provider.cc \
src/core/lib/security/credentials/tls/grpc_tls_certificate_provider.h \
src/core/lib/security/credentials/tls/grpc_tls_certificate_verifier.cc \
src/core/lib/security/credentials/tls/grpc_tls_certificate_verifier.h \
src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc \
src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h \
src/core/lib/security/credentials/tls/tls_credentials.cc \
@ -2307,9 +2310,8 @@ src/cpp/common/secure_auth_context.h \
src/cpp/common/secure_channel_arguments.cc \
src/cpp/common/secure_create_auth_context.cc \
src/cpp/common/tls_certificate_provider.cc \
src/cpp/common/tls_certificate_verifier.cc \
src/cpp/common/tls_credentials_options.cc \
src/cpp/common/tls_credentials_options_util.cc \
src/cpp/common/tls_credentials_options_util.h \
src/cpp/common/validate_service_config.cc \
src/cpp/common/version_cc.cc \
src/cpp/server/async_generic_service.cc \

View File

@ -1898,6 +1898,8 @@ src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.cc \
src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.h \
src/core/lib/security/credentials/tls/grpc_tls_certificate_provider.cc \
src/core/lib/security/credentials/tls/grpc_tls_certificate_provider.h \
src/core/lib/security/credentials/tls/grpc_tls_certificate_verifier.cc \
src/core/lib/security/credentials/tls/grpc_tls_certificate_verifier.h \
src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc \
src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h \
src/core/lib/security/credentials/tls/tls_credentials.cc \

View File

@ -4743,6 +4743,30 @@
],
"uses_polling": true
},
{
"args": [],
"benchmark": false,
"ci_platforms": [
"linux",
"mac",
"posix",
"windows"
],
"cpu_cost": 1.0,
"exclude_configs": [],
"exclude_iomgrs": [],
"flaky": false,
"gtest": true,
"language": "c++",
"name": "grpc_tls_certificate_verifier_test",
"platforms": [
"linux",
"mac",
"posix",
"windows"
],
"uses_polling": true
},
{
"args": [],
"benchmark": false,
@ -7075,6 +7099,30 @@
],
"uses_polling": true
},
{
"args": [],
"benchmark": false,
"ci_platforms": [
"linux",
"mac",
"posix",
"windows"
],
"cpu_cost": 1.0,
"exclude_configs": [],
"exclude_iomgrs": [],
"flaky": false,
"gtest": true,
"language": "c++",
"name": "tls_certificate_verifier_test",
"platforms": [
"linux",
"mac",
"posix",
"windows"
],
"uses_polling": true
},
{
"args": [],
"benchmark": false,