diff options
author | jiangtaoli2016 <jiangtao@google.com> | 2018-03-23 11:28:48 -0700 |
---|---|---|
committer | jiangtaoli2016 <jiangtao@google.com> | 2018-03-23 11:28:48 -0700 |
commit | 144f5559dabd2bd646acba1426647123d31c2323 (patch) | |
tree | 1418b4a63820a9d40d82a51a6522fc770c1a27ce /src/core/lib/security/security_connector | |
parent | 90af9346de2e4e6f0d45b130ce0de3d08d075c3f (diff) |
cache default SSL root cert store
Diffstat (limited to 'src/core/lib/security/security_connector')
-rw-r--r-- | src/core/lib/security/security_connector/security_connector.cc | 138 | ||||
-rw-r--r-- | src/core/lib/security/security_connector/security_connector.h | 51 |
2 files changed, 124 insertions, 65 deletions
diff --git a/src/core/lib/security/security_connector/security_connector.cc b/src/core/lib/security/security_connector/security_connector.cc index cbe77d5a69..3967112bb8 100644 --- a/src/core/lib/security/security_connector/security_connector.cc +++ b/src/core/lib/security/security_connector/security_connector.cc @@ -965,63 +965,6 @@ static grpc_security_connector_vtable ssl_channel_vtable = { static grpc_security_connector_vtable ssl_server_vtable = { ssl_server_destroy, ssl_server_check_peer, ssl_server_cmp}; -/* returns a NULL terminated slice. */ -static grpc_slice compute_default_pem_root_certs_once(void) { - grpc_slice result = grpc_empty_slice(); - - /* First try to load the roots from the environment. */ - char* default_root_certs_path = - gpr_getenv(GRPC_DEFAULT_SSL_ROOTS_FILE_PATH_ENV_VAR); - if (default_root_certs_path != nullptr) { - GRPC_LOG_IF_ERROR("load_file", - grpc_load_file(default_root_certs_path, 1, &result)); - gpr_free(default_root_certs_path); - } - - /* Try overridden roots if needed. */ - grpc_ssl_roots_override_result ovrd_res = GRPC_SSL_ROOTS_OVERRIDE_FAIL; - if (GRPC_SLICE_IS_EMPTY(result) && ssl_roots_override_cb != nullptr) { - char* pem_root_certs = nullptr; - ovrd_res = ssl_roots_override_cb(&pem_root_certs); - if (ovrd_res == GRPC_SSL_ROOTS_OVERRIDE_OK) { - GPR_ASSERT(pem_root_certs != nullptr); - result = grpc_slice_from_copied_buffer( - pem_root_certs, - strlen(pem_root_certs) + 1); // NULL terminator. - } - gpr_free(pem_root_certs); - } - - /* Fall back to installed certs if needed. */ - if (GRPC_SLICE_IS_EMPTY(result) && - ovrd_res != GRPC_SSL_ROOTS_OVERRIDE_FAIL_PERMANENTLY) { - GRPC_LOG_IF_ERROR("load_file", - grpc_load_file(installed_roots_path, 1, &result)); - } - return result; -} - -static grpc_slice default_pem_root_certs; - -static void init_default_pem_root_certs(void) { - default_pem_root_certs = compute_default_pem_root_certs_once(); -} - -grpc_slice grpc_get_default_ssl_roots_for_testing(void) { - return compute_default_pem_root_certs_once(); -} - -const char* grpc_get_default_ssl_roots(void) { - /* TODO(jboeuf@google.com): Maybe revisit the approach which consists in - loading all the roots once for the lifetime of the process. */ - static gpr_once once = GPR_ONCE_INIT; - gpr_once_init(&once, init_default_pem_root_certs); - return GRPC_SLICE_IS_EMPTY(default_pem_root_certs) - ? nullptr - : reinterpret_cast<const char*> - GRPC_SLICE_START_PTR(default_pem_root_certs); -} - grpc_security_status grpc_ssl_channel_security_connector_create( grpc_channel_credentials* channel_creds, grpc_call_credentials* request_metadata_creds, @@ -1043,7 +986,9 @@ grpc_security_status grpc_ssl_channel_security_connector_create( goto error; } if (config->pem_root_certs == nullptr) { - options.pem_root_certs = grpc_get_default_ssl_roots(); + // Use default root certificates. + options.pem_root_certs = grpc_core::DefaultSslRootStore::GetPemRootCerts(); + options.root_store = grpc_core::DefaultSslRootStore::GetRootStore(); if (options.pem_root_certs == nullptr) { gpr_log(GPR_ERROR, "Could not get default pem root certs."); goto error; @@ -1051,7 +996,6 @@ grpc_security_status grpc_ssl_channel_security_connector_create( } else { options.pem_root_certs = config->pem_root_certs; } - c = static_cast<grpc_ssl_channel_security_connector*>( gpr_zalloc(sizeof(grpc_ssl_channel_security_connector))); @@ -1157,3 +1101,79 @@ grpc_security_status grpc_ssl_server_security_connector_create( } return retval; } + +namespace grpc_core { + +tsi_ssl_root_certs_store* DefaultSslRootStore::default_root_store_; +grpc_slice DefaultSslRootStore::default_pem_root_certs_; + +const tsi_ssl_root_certs_store* DefaultSslRootStore::GetRootStore() { + InitRootStore(); + return default_root_store_; +} + +const char* DefaultSslRootStore::GetPemRootCerts() { + InitRootStore(); + return GRPC_SLICE_IS_EMPTY(default_pem_root_certs_) + ? nullptr + : reinterpret_cast<const char*> + GRPC_SLICE_START_PTR(default_pem_root_certs_); +} + +void DefaultSslRootStore::Initialize() { + default_root_store_ = nullptr; + default_pem_root_certs_ = grpc_empty_slice(); +} + +void DefaultSslRootStore::Destroy() { + tsi_ssl_root_certs_store_destroy(default_root_store_); + grpc_slice_unref_internal(default_pem_root_certs_); +} + +grpc_slice DefaultSslRootStore::ComputePemRootCerts() { + grpc_slice result = grpc_empty_slice(); + // First try to load the roots from the environment. + char* default_root_certs_path = + gpr_getenv(GRPC_DEFAULT_SSL_ROOTS_FILE_PATH_ENV_VAR); + if (default_root_certs_path != nullptr) { + GRPC_LOG_IF_ERROR("load_file", + grpc_load_file(default_root_certs_path, 1, &result)); + gpr_free(default_root_certs_path); + } + // Try overridden roots if needed. + grpc_ssl_roots_override_result ovrd_res = GRPC_SSL_ROOTS_OVERRIDE_FAIL; + if (GRPC_SLICE_IS_EMPTY(result) && ssl_roots_override_cb != nullptr) { + char* pem_root_certs = nullptr; + ovrd_res = ssl_roots_override_cb(&pem_root_certs); + if (ovrd_res == GRPC_SSL_ROOTS_OVERRIDE_OK) { + GPR_ASSERT(pem_root_certs != nullptr); + result = grpc_slice_from_copied_buffer( + pem_root_certs, + strlen(pem_root_certs) + 1); // nullptr terminator. + } + gpr_free(pem_root_certs); + } + // Fall back to installed certs if needed. + if (GRPC_SLICE_IS_EMPTY(result) && + ovrd_res != GRPC_SSL_ROOTS_OVERRIDE_FAIL_PERMANENTLY) { + GRPC_LOG_IF_ERROR("load_file", + grpc_load_file(installed_roots_path, 1, &result)); + } + return result; +} + +void DefaultSslRootStore::InitRootStore() { + static gpr_once once = GPR_ONCE_INIT; + gpr_once_init(&once, DefaultSslRootStore::InitRootStoreOnce); +} + +void DefaultSslRootStore::InitRootStoreOnce() { + default_pem_root_certs_ = ComputePemRootCerts(); + if (!GRPC_SLICE_IS_EMPTY(default_pem_root_certs_)) { + default_root_store_ = + tsi_ssl_root_certs_store_create(reinterpret_cast<const char*>( + GRPC_SLICE_START_PTR(default_pem_root_certs_))); + } +} + +} // namespace grpc_core diff --git a/src/core/lib/security/security_connector/security_connector.h b/src/core/lib/security/security_connector/security_connector.h index dc847d94f9..5d3d1e0f44 100644 --- a/src/core/lib/security/security_connector/security_connector.h +++ b/src/core/lib/security/security_connector/security_connector.h @@ -216,12 +216,6 @@ grpc_security_status grpc_ssl_channel_security_connector_create( tsi_ssl_session_cache* ssl_session_cache, grpc_channel_security_connector** sc); -/* Gets the default ssl roots. Returns NULL if not found. */ -const char* grpc_get_default_ssl_roots(void); - -/* Exposed for TESTING ONLY!. */ -grpc_slice grpc_get_default_ssl_roots_for_testing(void); - /* Config for ssl servers. */ typedef struct { tsi_ssl_pem_key_cert_pair* pem_key_cert_pairs; @@ -250,4 +244,49 @@ tsi_peer tsi_shallow_peer_from_ssl_auth_context( const grpc_auth_context* auth_context); void tsi_shallow_peer_destruct(tsi_peer* peer); +/* --- Default SSL Root Store. --- */ +namespace grpc_core { + +// The class implements default SSL root store. +class DefaultSslRootStore { + public: + // Gets the default SSL root store. Returns nullptr if not found. + static const tsi_ssl_root_certs_store* GetRootStore(); + + // Gets the default PEM root certificate. + static const char* GetPemRootCerts(); + + // Initializes the SSL root store's underlying data structure. It does not + // load default SSL root certificates. Should only be called by + // grpc_security_init(). + static void Initialize(); + + // Destroys the default SSL root store. Should only be called by + // grpc_security_shutdown(). + static void Destroy(); + + protected: + // Returns default PEM root certificates in nullptr terminated grpc_slice. + // This function is protected instead of private, so that it can be tested. + static grpc_slice ComputePemRootCerts(); + + private: + // Construct me not! + DefaultSslRootStore(); + + // Initialization of default SSL root store. + static void InitRootStore(); + + // One-time initialization of default SSL root store. + static void InitRootStoreOnce(); + + // SSL root store in tsi_ssl_root_certs_store object. + static tsi_ssl_root_certs_store* default_root_store_; + + // Default PEM root certificates. + static grpc_slice default_pem_root_certs_; +}; + +} // namespace grpc_core + #endif /* GRPC_CORE_LIB_SECURITY_SECURITY_CONNECTOR_SECURITY_CONNECTOR_H */ |