diff options
author | Julien Boeuf <jboeuf@google.com> | 2016-01-28 17:04:42 -0800 |
---|---|---|
committer | Julien Boeuf <jboeuf@google.com> | 2016-01-28 17:04:42 -0800 |
commit | aaebf7ae7467a43ba69f27943069613f23808461 (patch) | |
tree | b5f08e32df8dcfa976bcf2f21862cf307993e247 | |
parent | 564b9155031a0d00e3bd2da2360e617cfbf8342e (diff) |
Changing the API to use a callback mechanism.
This is the agreed-upon solution.
-rw-r--r-- | include/grpc/grpc_security.h | 27 | ||||
-rw-r--r-- | src/core/security/security_connector.c | 20 | ||||
-rw-r--r-- | test/core/security/security_connector_test.c | 23 |
3 files changed, 55 insertions, 15 deletions
diff --git a/include/grpc/grpc_security.h b/include/grpc/grpc_security.h index ff16e92c35..e280bf5391 100644 --- a/include/grpc/grpc_security.h +++ b/include/grpc/grpc_security.h @@ -143,14 +143,29 @@ grpc_channel_credentials *grpc_google_default_credentials_create(void); #define GRPC_DEFAULT_SSL_ROOTS_FILE_PATH_ENV_VAR \ "GRPC_DEFAULT_SSL_ROOTS_FILE_PATH" -/* Overrides the default TLS/SSL roots. - The roots must be encoded as PEM and NULL-terminated. +/* Results for the SSL roots override callback. */ +typedef enum { + GRPC_SSL_ROOTS_OVERRIDE_OK, + GRPC_SSL_ROOTS_OVERRIDE_FAIL_PERMANENTLY, /* Do not try fallback options. */ + GRPC_SSL_ROOTS_OVERRIDE_FAIL +} grpc_ssl_roots_override_result; + + +/* Callback for getting the SSL roots override from the application. + In case of success, *pem_roots_certs must be set to a NULL terminated string + containing the list of PEM encoded root certificates. The ownership is passed + to the core and freed (laster by the core) with gpr_free. + If this function fails and GRPC_DEFAULT_SSL_ROOTS_FILE_PATH environment is + set to a valid path, it will override the roots specified this func */ +typedef grpc_ssl_roots_override_result (*grpc_ssl_roots_override_callback)( + char **pem_root_certs); + +/* Setup a callback to override the default TLS/SSL roots. This function is not thread-safe and must be called at initialization time before any ssl credentials are created to have the desired side effect. - It also does not do any checks about the validity of the encoding. - If the GRPC_DEFAULT_SSL_ROOTS_FILE_PATH environment is set to a valid path, - it will override the roots specified in this function. */ -void grpc_override_ssl_default_roots(const char *roots_pem); + If GRPC_DEFAULT_SSL_ROOTS_FILE_PATH environment is set to a valid path, the + callback will not be called. */ +void grpc_set_ssl_roots_override_callback(grpc_ssl_roots_override_callback cb); /* Object that holds a private key / certificate chain pair in PEM format. */ typedef struct { diff --git a/src/core/security/security_connector.c b/src/core/security/security_connector.c index 8a67243a18..654866fd4e 100644 --- a/src/core/security/security_connector.c +++ b/src/core/security/security_connector.c @@ -63,10 +63,10 @@ static const char *installed_roots_path = /* -- Overridden default roots. -- */ -static gpr_slice overridden_default_roots; +static grpc_ssl_roots_override_callback ssl_roots_override_cb = NULL; -void grpc_override_ssl_default_roots(const char *roots_pem) { - overridden_default_roots = gpr_slice_from_copied_string(roots_pem); +void grpc_set_ssl_roots_override_callback(grpc_ssl_roots_override_callback cb) { + ssl_roots_override_cb = cb; } /* -- Cipher suites. -- */ @@ -615,13 +615,19 @@ static gpr_slice compute_default_pem_root_certs_once(void) { } /* Try overridden roots path if needed. */ - if (GPR_SLICE_IS_EMPTY(result) && - !GPR_SLICE_IS_EMPTY(overridden_default_roots)) { - result = gpr_slice_ref(overridden_default_roots); + grpc_ssl_roots_override_result ovrd_res = GRPC_SSL_ROOTS_OVERRIDE_FAIL; + if (GPR_SLICE_IS_EMPTY(result) && ssl_roots_override_cb != NULL) { + char *pem_root_certs = NULL; + ovrd_res = ssl_roots_override_cb(&pem_root_certs); + if (ovrd_res == GRPC_SSL_ROOTS_OVERRIDE_OK) { + GPR_ASSERT(pem_root_certs != NULL); + result = gpr_slice_new(pem_root_certs, strlen(pem_root_certs), gpr_free); + } } /* Fall back to installed certs if needed. */ - if (GPR_SLICE_IS_EMPTY(result)) { + if (GPR_SLICE_IS_EMPTY(result) && + ovrd_res != GRPC_SSL_ROOTS_OVERRIDE_FAIL_PERMANENTLY) { result = gpr_load_file(installed_roots_path, 0, NULL); } return result; diff --git a/test/core/security/security_connector_test.c b/test/core/security/security_connector_test.c index bfebf209df..d9322f0257 100644 --- a/test/core/security/security_connector_test.c +++ b/test/core/security/security_connector_test.c @@ -47,6 +47,7 @@ #include <grpc/support/alloc.h> #include <grpc/support/log.h> +#include <grpc/support/string_util.h> #include <grpc/support/useful.h> static int check_transport_security_type(const grpc_auth_context *ctx) { @@ -300,8 +301,20 @@ static void test_cn_and_multiple_sans_and_others_ssl_peer_to_auth_context( GRPC_AUTH_CONTEXT_UNREF(ctx, "test"); } +static const char *roots_for_override_api = "roots for override api"; + +static grpc_ssl_roots_override_result override_roots_success( + char **pem_root_certs) { + *pem_root_certs = gpr_strdup(roots_for_override_api); + return GRPC_SSL_ROOTS_OVERRIDE_OK; +} + +static grpc_ssl_roots_override_result override_roots_permanent_failure( + char **pem_root_certs) { + return GRPC_SSL_ROOTS_OVERRIDE_FAIL_PERMANENTLY; +} + static void test_default_ssl_roots(void) { - const char *roots_for_override_api = "roots for override api"; const char *roots_for_env_var = "roots for env var"; char *roots_env_var_file_path; @@ -311,7 +324,7 @@ static void test_default_ssl_roots(void) { fclose(roots_env_var_file); /* First let's get the root through the override (no env are set). */ - grpc_override_ssl_default_roots(roots_for_override_api); + grpc_set_ssl_roots_override_callback(override_roots_success); gpr_slice roots = grpc_get_default_ssl_roots_for_testing(); char *roots_contents = gpr_dump_slice(roots, GPR_DUMP_ASCII); gpr_slice_unref(roots); @@ -336,6 +349,12 @@ static void test_default_ssl_roots(void) { GPR_ASSERT(strcmp(roots_contents, roots_for_override_api) == 0); gpr_free(roots_contents); + /* Now setup a permanent failure for the overridden roots and we should get + an empty slice. */ + grpc_set_ssl_roots_override_callback(override_roots_permanent_failure); + roots = grpc_get_default_ssl_roots_for_testing(); + GPR_ASSERT(GPR_SLICE_IS_EMPTY(roots)); + /* Cleanup. */ remove(roots_env_var_file_path); gpr_free(roots_env_var_file_path); |