@ -39,6 +39,7 @@
# include "src/core/lib/surface/api_trace.h"
# include "src/core/tsi/ssl/session_cache/ssl_session_cache.h"
# include "src/core/tsi/ssl_transport_security.h"
# include "src/core/tsi/transport_security_interface.h"
//
// SSL Channel Credentials.
@ -48,6 +49,27 @@ grpc_ssl_credentials::grpc_ssl_credentials(
const char * pem_root_certs , grpc_ssl_pem_key_cert_pair * pem_key_cert_pair ,
const grpc_ssl_verify_peer_options * verify_options ) {
build_config ( pem_root_certs , pem_key_cert_pair , verify_options ) ;
// Use default (e.g. OS) root certificates if the user did not pass any root
// certificates.
if ( config_ . pem_root_certs = = nullptr ) {
const char * pem_root_certs =
grpc_core : : DefaultSslRootStore : : GetPemRootCerts ( ) ;
if ( pem_root_certs = = nullptr ) {
gpr_log ( GPR_ERROR , " Could not get default pem root certs. " ) ;
} else {
size_t root_len = strlen ( pem_root_certs ) ;
char * default_roots = strcpy ( new char [ root_len + 1 ] , pem_root_certs ) ;
config_ . pem_root_certs = default_roots ;
root_store_ = grpc_core : : DefaultSslRootStore : : GetRootStore ( ) ;
}
} else {
config_ . pem_root_certs = config_ . pem_root_certs ;
root_store_ = nullptr ;
}
client_handshaker_initialization_status_ = InitializeClientHandshakerFactory (
& config_ , config_ . pem_root_certs , root_store_ , nullptr ,
& client_handshaker_factory_ ) ;
}
grpc_ssl_credentials : : ~ grpc_ssl_credentials ( ) {
@ -57,26 +79,67 @@ grpc_ssl_credentials::~grpc_ssl_credentials() {
config_ . verify_options . verify_peer_destruct (
config_ . verify_options . verify_peer_callback_userdata ) ;
}
tsi_ssl_client_handshaker_factory_unref ( client_handshaker_factory_ ) ;
}
grpc_core : : RefCountedPtr < grpc_channel_security_connector >
grpc_ssl_credentials : : create_security_connector (
grpc_core : : RefCountedPtr < grpc_call_credentials > call_creds ,
const char * target , grpc_core : : ChannelArgs * args ) {
if ( config_ . pem_root_certs = = nullptr ) {
gpr_log ( GPR_ERROR ,
" No root certs in config. Client-side security connector must have "
" root certs. " ) ;
return nullptr ;
}
absl : : optional < std : : string > overridden_target_name =
args - > GetOwnedString ( GRPC_SSL_TARGET_NAME_OVERRIDE_ARG ) ;
auto * ssl_session_cache = args - > GetObject < tsi : : SslSessionLRUCache > ( ) ;
grpc_core : : RefCountedPtr < grpc_channel_security_connector > sc =
grpc_ssl_channel_security_connector_create (
this - > Ref ( ) , std : : move ( call_creds ) , & config_ , target ,
overridden_target_name . has_value ( ) ? overridden_target_name - > c_str ( )
: nullptr ,
ssl_session_cache = = nullptr ? nullptr : ssl_session_cache - > c_ptr ( ) ) ;
if ( sc = = nullptr ) {
return sc ;
tsi_ssl_session_cache * session_cache =
ssl_session_cache = = nullptr ? nullptr : ssl_session_cache - > c_ptr ( ) ;
grpc_core : : RefCountedPtr < grpc_channel_security_connector > security_connector =
nullptr ;
if ( session_cache ! = nullptr ) {
// We need a separate factory and SSL_CTX if there's a cache in the channel
// args. SSL_CTX should live with the factory and that should live on the
// credentials. However, there is a way to configure a session cache in the
// channel args, so that prevents us from also keeping the session cache at
// the credentials level. In the case of a session cache, we still need to
// keep a separate factory and SSL_CTX at the subchannel/security_connector
// level.
tsi_ssl_client_handshaker_factory * factory_with_cache = nullptr ;
grpc_security_status status = InitializeClientHandshakerFactory (
& config_ , config_ . pem_root_certs , root_store_ , session_cache ,
& factory_with_cache ) ;
if ( status ! = GRPC_SECURITY_OK ) {
gpr_log ( GPR_ERROR ,
" InitializeClientHandshakerFactory returned bad "
" status. " ) ;
return nullptr ;
}
security_connector = grpc_ssl_channel_security_connector_create (
this - > Ref ( ) , std : : move ( call_creds ) , & config_ , target ,
overridden_target_name . has_value ( ) ? overridden_target_name - > c_str ( )
: nullptr ,
factory_with_cache ) ;
tsi_ssl_client_handshaker_factory_unref ( factory_with_cache ) ;
} else {
if ( client_handshaker_initialization_status_ ! = GRPC_SECURITY_OK ) {
return nullptr ;
}
security_connector = grpc_ssl_channel_security_connector_create (
this - > Ref ( ) , std : : move ( call_creds ) , & config_ , target ,
overridden_target_name . has_value ( ) ? overridden_target_name - > c_str ( )
: nullptr ,
client_handshaker_factory_ ) ;
}
if ( security_connector = = nullptr ) {
return security_connector ;
}
* args = args - > Set ( GRPC_ARG_HTTP2_SCHEME , " https " ) ;
return sc ;
return se curity_connector ;
}
grpc_core : : UniqueTypeName grpc_ssl_credentials : : Type ( ) {
@ -119,6 +182,50 @@ void grpc_ssl_credentials::set_max_tls_version(
config_ . max_tls_version = max_tls_version ;
}
grpc_security_status grpc_ssl_credentials : : InitializeClientHandshakerFactory (
const grpc_ssl_config * config , const char * pem_root_certs ,
const tsi_ssl_root_certs_store * root_store ,
tsi_ssl_session_cache * ssl_session_cache ,
tsi_ssl_client_handshaker_factory * * handshaker_factory ) {
// This class level factory can't have a session cache by design. If we want
// to init one with a cache we need to make a new one
if ( client_handshaker_factory_ ! = nullptr & & ssl_session_cache = = nullptr ) {
return GRPC_SECURITY_OK ;
}
bool has_key_cert_pair = config - > pem_key_cert_pair ! = nullptr & &
config - > pem_key_cert_pair - > private_key ! = nullptr & &
config - > pem_key_cert_pair - > cert_chain ! = nullptr ;
tsi_ssl_client_handshaker_options options ;
if ( pem_root_certs = = nullptr ) {
gpr_log (
GPR_ERROR ,
" Handshaker factory creation failed. pem_root_certs cannot be nullptr " ) ;
return GRPC_SECURITY_ERROR ;
}
options . pem_root_certs = pem_root_certs ;
options . root_store = root_store ;
options . alpn_protocols =
grpc_fill_alpn_protocol_strings ( & options . num_alpn_protocols ) ;
if ( has_key_cert_pair ) {
options . pem_key_cert_pair = config - > pem_key_cert_pair ;
}
options . cipher_suites = grpc_get_ssl_cipher_suites ( ) ;
options . session_cache = ssl_session_cache ;
options . min_tls_version = grpc_get_tsi_tls_version ( config - > min_tls_version ) ;
options . max_tls_version = grpc_get_tsi_tls_version ( config - > max_tls_version ) ;
const tsi_result result =
tsi_create_ssl_client_handshaker_factory_with_options ( & options ,
handshaker_factory ) ;
gpr_free ( options . alpn_protocols ) ;
if ( result ! = TSI_OK ) {
gpr_log ( GPR_ERROR , " Handshaker factory creation failed with %s. " ,
tsi_result_to_string ( result ) ) ;
return GRPC_SECURITY_ERROR ;
}
return GRPC_SECURITY_OK ;
}
// Deprecated in favor of grpc_ssl_credentials_create_ex. Will be removed
// once all of its call sites are migrated to grpc_ssl_credentials_create_ex.
grpc_channel_credentials * grpc_ssl_credentials_create (