Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions grpc.def
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ EXPORTS
grpc_local_server_credentials_create
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_key_materials_config
grpc_tls_credentials_options_set_credential_reload_config
grpc_tls_credentials_options_set_server_authorization_check_config
Expand Down
14 changes: 14 additions & 0 deletions include/grpc/grpc_security.h
Original file line number Diff line number Diff line change
Expand Up @@ -731,6 +731,19 @@ GRPCAPI int grpc_tls_credentials_options_set_cert_request_type(
grpc_tls_credentials_options* options,
grpc_ssl_client_certificate_request_type type);

/** Set grpc_tls_server_verification_option field in credentials options
with the provided server_verification_option. options should not be NULL.
This should be called only on the client side.
If grpc_tls_server_verification_option is not
GRPC_TLS_SERVER_VERIFICATION, use of a customer server
authorization check (grpc_tls_server_authorization_check_config)
will be mandatory.
It returns 1 on success and 0 on failure. It is used for
experimental purpose for now and subject to change. */
GRPCAPI int grpc_tls_credentials_options_set_server_verification_option(
grpc_tls_credentials_options* options,
grpc_tls_server_verification_option server_verification_option);

/** Set grpc_tls_key_materials_config field in credentials options
with the provided config struct whose ownership is transferred.
Both parameters should not be NULL.
Expand Down Expand Up @@ -902,6 +915,7 @@ struct grpc_tls_server_authorization_check_arg {
int success;
const char* target_name;
const char* peer_cert;
const char* peer_cert_full_chain;
grpc_status_code status;
const char* error_details;
grpc_tls_server_authorization_check_config* config;
Expand Down
15 changes: 15 additions & 0 deletions include/grpc/grpc_security_constants.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ extern "C" {
#define GRPC_X509_CN_PROPERTY_NAME "x509_common_name"
#define GRPC_X509_SAN_PROPERTY_NAME "x509_subject_alternative_name"
#define GRPC_X509_PEM_CERT_PROPERTY_NAME "x509_pem_cert"
#define GRPC_X509_PEM_CERT_CHAIN_PROPERTY_NAME "x509_pem_cert_chain"
#define GRPC_SSL_SESSION_REUSED_PROPERTY "ssl_session_reused"

/** Environment variable that points to the default SSL roots file. This file
Expand Down Expand Up @@ -114,6 +115,20 @@ 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.
Expand Down
9 changes: 9 additions & 0 deletions include/grpcpp/security/tls_credentials_options.h
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,7 @@ class TlsServerAuthorizationCheckArg {
int success() const;
grpc::string target_name() const;
grpc::string peer_cert() const;
grpc::string peer_cert_full_chain() const;
grpc_status_code status() const;
grpc::string error_details() const;

Expand All @@ -206,6 +207,7 @@ class TlsServerAuthorizationCheckArg {
void set_success(int success);
void set_target_name(const grpc::string& target_name);
void set_peer_cert(const grpc::string& peer_cert);
void set_peer_cert_full_chain(const grpc::string& peer_cert_full_chain);
void set_status(grpc_status_code status);
void set_error_details(const grpc::string& error_details);

Expand Down Expand Up @@ -287,6 +289,7 @@ class TlsCredentialsOptions {
public:
TlsCredentialsOptions(
grpc_ssl_client_certificate_request_type cert_request_type,
grpc_tls_server_verification_option server_verification_option,
std::shared_ptr<TlsKeyMaterialsConfig> key_materials_config,
std::shared_ptr<TlsCredentialReloadConfig> credential_reload_config,
std::shared_ptr<TlsServerAuthorizationCheckConfig>
Expand All @@ -297,6 +300,9 @@ class TlsCredentialsOptions {
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_;
}
std::shared_ptr<TlsKeyMaterialsConfig> key_materials_config() const {
return key_materials_config_;
}
Expand All @@ -317,6 +323,9 @@ class TlsCredentialsOptions {
* goes unused when creating channel credentials, and the user can set it to
* GRPC_SSL_DONT_REQUEST_CLIENT_CERTIFICATE. **/
grpc_ssl_client_certificate_request_type cert_request_type_;
/** The server_verification_option_ flag is only relevant when the
* TlsCredentialsOptions are used to instantiate client credentials; **/
grpc_tls_server_verification_option server_verification_option_;
std::shared_ptr<TlsKeyMaterialsConfig> key_materials_config_;
std::shared_ptr<TlsCredentialReloadConfig> credential_reload_config_;
std::shared_ptr<TlsServerAuthorizationCheckConfig>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,26 @@ int grpc_tls_credentials_options_set_cert_request_type(
return 1;
}

int grpc_tls_credentials_options_set_server_verification_option(
grpc_tls_credentials_options* options,
grpc_tls_server_verification_option server_verification_option) {
if (options == nullptr) {
gpr_log(GPR_ERROR,
"Invalid nullptr arguments to "
"grpc_tls_credentials_options_set_server_verification_option()");
return 0;
}
if (server_verification_option != GRPC_TLS_SERVER_VERIFICATION &&
options->server_authorization_check_config() == nullptr) {
gpr_log(GPR_ERROR,
"server_authorization_check_config needs to be specified when"
"server_verification_option is not GRPC_TLS_SERVER_VERIFICATION");
return 0;
}
options->set_server_verification_option(server_verification_option);
return 1;
}

int grpc_tls_credentials_options_set_key_materials_config(
grpc_tls_credentials_options* options,
grpc_tls_key_materials_config* config) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,9 @@ 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_;
}
grpc_tls_key_materials_config* key_materials_config() const {
return key_materials_config_.get();
}
Expand All @@ -250,6 +253,10 @@ 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_key_materials_config(
grpc_core::RefCountedPtr<grpc_tls_key_materials_config> config) {
key_materials_config_ = std::move(config);
Expand All @@ -266,6 +273,7 @@ struct grpc_tls_credentials_options

private:
grpc_ssl_client_certificate_request_type cert_request_type_;
grpc_tls_server_verification_option server_verification_option_;
grpc_core::RefCountedPtr<grpc_tls_key_materials_config> key_materials_config_;
grpc_core::RefCountedPtr<grpc_tls_credential_reload_config>
credential_reload_config_;
Expand Down
11 changes: 11 additions & 0 deletions src/core/lib/security/security_connector/ssl_utils.cc
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,10 @@ grpc_core::RefCountedPtr<grpc_auth_context> grpc_ssl_peer_to_auth_context(
grpc_auth_context_add_property(ctx.get(),
GRPC_X509_PEM_CERT_PROPERTY_NAME,
prop->value.data, prop->value.length);
} else if (strcmp(prop->name, TSI_X509_PEM_CERT_CHAIN_PROPERTY) == 0) {
grpc_auth_context_add_property(ctx.get(),
GRPC_X509_PEM_CERT_CHAIN_PROPERTY_NAME,
prop->value.data, prop->value.length);
} else if (strcmp(prop->name, TSI_SSL_SESSION_REUSED_PEER_PROPERTY) == 0) {
grpc_auth_context_add_property(ctx.get(),
GRPC_SSL_SESSION_REUSED_PROPERTY,
Expand Down Expand Up @@ -272,6 +276,10 @@ tsi_peer grpc_shallow_peer_from_ssl_auth_context(
} else if (strcmp(prop->name, GRPC_X509_PEM_CERT_PROPERTY_NAME) == 0) {
add_shallow_auth_property_to_peer(&peer, prop,
TSI_X509_PEM_CERT_PROPERTY);
} else if (strcmp(prop->name, GRPC_X509_PEM_CERT_CHAIN_PROPERTY_NAME) ==
0) {
add_shallow_auth_property_to_peer(&peer, prop,
TSI_X509_PEM_CERT_CHAIN_PROPERTY);
}
}
}
Expand All @@ -284,6 +292,7 @@ void grpc_shallow_peer_destruct(tsi_peer* peer) {

grpc_security_status grpc_ssl_tsi_client_handshaker_factory_init(
tsi_ssl_pem_key_cert_pair* pem_key_cert_pair, const char* pem_root_certs,
bool skip_server_certificate_verification,
tsi_ssl_session_cache* ssl_session_cache,
tsi_ssl_client_handshaker_factory** handshaker_factory) {
const char* root_certs;
Expand Down Expand Up @@ -314,6 +323,8 @@ grpc_security_status grpc_ssl_tsi_client_handshaker_factory_init(
}
options.cipher_suites = grpc_get_ssl_cipher_suites();
options.session_cache = ssl_session_cache;
options.skip_server_certificate_verification =
skip_server_certificate_verification;
const tsi_result result =
tsi_create_ssl_client_handshaker_factory_with_options(&options,
handshaker_factory);
Expand Down
1 change: 1 addition & 0 deletions src/core/lib/security/security_connector/ssl_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ const char** grpc_fill_alpn_protocol_strings(size_t* num_alpn_protocols);
/* Initialize TSI SSL server/client handshaker factory. */
grpc_security_status grpc_ssl_tsi_client_handshaker_factory_init(
tsi_ssl_pem_key_cert_pair* key_cert_pair, const char* pem_root_certs,
bool skip_server_certificate_verification,
tsi_ssl_session_cache* ssl_session_cache,
tsi_ssl_client_handshaker_factory** handshaker_factory);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,12 +66,13 @@ tsi_ssl_pem_key_cert_pair* ConvertToTsiPemKeyCertPair(
grpc_status_code TlsFetchKeyMaterials(
const grpc_core::RefCountedPtr<grpc_tls_key_materials_config>&
key_materials_config,
const grpc_tls_credentials_options& options,
const grpc_tls_credentials_options& options, bool server_config,
grpc_ssl_certificate_config_reload_status* reload_status) {
GPR_ASSERT(key_materials_config != nullptr);
bool is_key_materials_empty =
key_materials_config->pem_key_cert_pair_list().empty();
if (options.credential_reload_config() == nullptr && is_key_materials_empty) {
if (options.credential_reload_config() == nullptr && is_key_materials_empty &&
server_config) {
gpr_log(GPR_ERROR,
"Either credential reload config or key materials should be "
"provisioned.");
Expand Down Expand Up @@ -190,9 +191,8 @@ void TlsChannelSecurityConnector::check_peer(
error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"Cannot check peer: missing pem cert property.");
} else {
char* peer_pem = static_cast<char*>(gpr_malloc(p->value.length + 1));
char* peer_pem = static_cast<char*>(gpr_zalloc(p->value.length + 1));
memcpy(peer_pem, p->value.data, p->value.length);
peer_pem[p->value.length] = '\0';
GPR_ASSERT(check_arg_ != nullptr);
check_arg_->peer_cert = check_arg_->peer_cert == nullptr
? gpr_strdup(peer_pem)
Expand All @@ -202,6 +202,18 @@ void TlsChannelSecurityConnector::check_peer(
: 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);
}
int callback_status = config->Schedule(check_arg_);
/* Server authorization check is handled asynchronously. */
if (callback_status) {
Expand Down Expand Up @@ -272,16 +284,21 @@ TlsChannelSecurityConnector::CreateTlsChannelSecurityConnector(

grpc_security_status TlsChannelSecurityConnector::ReplaceHandshakerFactory(
tsi_ssl_session_cache* ssl_session_cache) {
const TlsCredentials* creds =
static_cast<const TlsCredentials*>(channel_creds());
bool skip_server_certificate_verification =
creds->options().server_verification_option() ==
GRPC_TLS_SKIP_ALL_SERVER_VERIFICATION;
/* Free the client handshaker factory if exists. */
if (client_handshaker_factory_) {
tsi_ssl_client_handshaker_factory_unref(client_handshaker_factory_);
}
GPR_ASSERT(!key_materials_config_->pem_key_cert_pair_list().empty());
tsi_ssl_pem_key_cert_pair* pem_key_cert_pair = ConvertToTsiPemKeyCertPair(
key_materials_config_->pem_key_cert_pair_list());
grpc_security_status status = grpc_ssl_tsi_client_handshaker_factory_init(
pem_key_cert_pair, key_materials_config_->pem_root_certs(),
ssl_session_cache, &client_handshaker_factory_);
skip_server_certificate_verification, ssl_session_cache,
&client_handshaker_factory_);
/* Free memory. */
grpc_tsi_ssl_pem_key_cert_pairs_destroy(pem_key_cert_pair, 1);
return status;
Expand All @@ -305,7 +322,7 @@ grpc_security_status TlsChannelSecurityConnector::InitializeHandshakerFactory(
}
grpc_ssl_certificate_config_reload_status reload_status =
GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_UNCHANGED;
if (TlsFetchKeyMaterials(key_materials_config_, creds->options(),
if (TlsFetchKeyMaterials(key_materials_config_, creds->options(), false,
&reload_status) != GRPC_STATUS_OK) {
/* Raise an error if key materials are not populated. */
return GRPC_SECURITY_ERROR;
Expand All @@ -319,7 +336,7 @@ grpc_security_status TlsChannelSecurityConnector::RefreshHandshakerFactory() {
static_cast<const TlsCredentials*>(channel_creds());
grpc_ssl_certificate_config_reload_status reload_status =
GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_UNCHANGED;
if (TlsFetchKeyMaterials(key_materials_config_, creds->options(),
if (TlsFetchKeyMaterials(key_materials_config_, creds->options(), false,
&reload_status) != GRPC_STATUS_OK) {
return GRPC_SECURITY_ERROR;
}
Expand Down Expand Up @@ -390,6 +407,7 @@ void TlsChannelSecurityConnector::ServerAuthorizationCheckArgDestroy(
}
gpr_free((void*)arg->target_name);
gpr_free((void*)arg->peer_cert);
if (arg->peer_cert_full_chain) gpr_free((void*)arg->peer_cert_full_chain);
gpr_free((void*)arg->error_details);
if (arg->destroy_context != nullptr) {
arg->destroy_context(arg->context);
Expand Down Expand Up @@ -507,7 +525,7 @@ grpc_security_status TlsServerSecurityConnector::InitializeHandshakerFactory() {
}
grpc_ssl_certificate_config_reload_status reload_status =
GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_UNCHANGED;
if (TlsFetchKeyMaterials(key_materials_config_, creds->options(),
if (TlsFetchKeyMaterials(key_materials_config_, creds->options(), true,
&reload_status) != GRPC_STATUS_OK) {
/* Raise an error if key materials are not populated. */
return GRPC_SECURITY_ERROR;
Expand All @@ -521,7 +539,7 @@ grpc_security_status TlsServerSecurityConnector::RefreshHandshakerFactory() {
static_cast<const TlsServerCredentials*>(server_creds());
grpc_ssl_certificate_config_reload_status reload_status =
GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_UNCHANGED;
if (TlsFetchKeyMaterials(key_materials_config_, creds->options(),
if (TlsFetchKeyMaterials(key_materials_config_, creds->options(), true,
&reload_status) != GRPC_STATUS_OK) {
return GRPC_SECURITY_ERROR;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ class TlsServerSecurityConnector final : public grpc_server_security_connector {
grpc_status_code TlsFetchKeyMaterials(
const grpc_core::RefCountedPtr<grpc_tls_key_materials_config>&
key_materials_config,
const grpc_tls_credentials_options& options,
const grpc_tls_credentials_options& options, bool server_config,
grpc_ssl_certificate_config_reload_status* status);

} // namespace grpc_core
Expand Down
Loading