diff options
Diffstat (limited to 'src/core/security')
-rw-r--r-- | src/core/security/client_auth_filter.c | 18 | ||||
-rw-r--r-- | src/core/security/credentials.c | 123 | ||||
-rw-r--r-- | src/core/security/credentials.h | 112 | ||||
-rw-r--r-- | src/core/security/google_default_credentials.c | 89 | ||||
-rw-r--r-- | src/core/security/json_token.c | 54 | ||||
-rw-r--r-- | src/core/security/json_token.h | 15 | ||||
-rw-r--r-- | src/core/security/jwt_verifier.c | 40 | ||||
-rw-r--r-- | src/core/security/security_context.c | 14 | ||||
-rw-r--r-- | src/core/security/security_context.h | 8 |
9 files changed, 295 insertions, 178 deletions
diff --git a/src/core/security/client_auth_filter.c b/src/core/security/client_auth_filter.c index 16f2abe04b..9e49a807f1 100644 --- a/src/core/security/client_auth_filter.c +++ b/src/core/security/client_auth_filter.c @@ -61,6 +61,7 @@ typedef struct { grpc_transport_stream_op op; size_t op_md_idx; int sent_initial_metadata; + gpr_uint8 security_context_set; grpc_linked_mdelem md_links[MAX_CREDENTIALS_METADATA_COUNT]; } call_data; @@ -199,8 +200,22 @@ static void auth_start_transport_op(grpc_call_element *elem, channel_data *chand = elem->channel_data; grpc_linked_mdelem *l; size_t i; + grpc_client_security_context* sec_ctx = NULL; - /* TODO(jboeuf): write the call auth context. */ + if (calld->security_context_set == 0) { + calld->security_context_set = 1; + GPR_ASSERT(op->context); + if (op->context[GRPC_CONTEXT_SECURITY].value == NULL) { + op->context[GRPC_CONTEXT_SECURITY].value = + grpc_client_security_context_create(); + op->context[GRPC_CONTEXT_SECURITY].destroy = + grpc_client_security_context_destroy; + } + sec_ctx = op->context[GRPC_CONTEXT_SECURITY].value; + GRPC_AUTH_CONTEXT_UNREF(sec_ctx->auth_context, "client auth filter"); + sec_ctx->auth_context = GRPC_AUTH_CONTEXT_REF( + chand->security_connector->base.auth_context, "client_auth_filter"); + } if (op->bind_pollset) { calld->pollset = op->bind_pollset; @@ -263,6 +278,7 @@ static void init_call_elem(grpc_call_element *elem, calld->method = NULL; calld->pollset = NULL; calld->sent_initial_metadata = 0; + calld->security_context_set = 0; GPR_ASSERT(!initial_op || !initial_op->send_ops); } diff --git a/src/core/security/credentials.c b/src/core/security/credentials.c index 8d694c2f79..230f0dfb85 100644 --- a/src/core/security/credentials.c +++ b/src/core/security/credentials.c @@ -41,7 +41,6 @@ #include "src/core/json/json.h" #include "src/core/httpcli/httpcli.h" #include "src/core/iomgr/iomgr.h" -#include "src/core/security/json_token.h" #include "src/core/support/string.h" #include <grpc/support/alloc.h> @@ -52,12 +51,12 @@ /* -- Common. -- */ -typedef struct { +struct grpc_credentials_metadata_request { grpc_credentials *creds; grpc_credentials_metadata_cb cb; grpc_iomgr_closure *on_simulated_token_fetch_done_closure; void *user_data; -} grpc_credentials_metadata_request; +}; static grpc_credentials_metadata_request * grpc_credentials_metadata_request_create(grpc_credentials *creds, @@ -152,16 +151,6 @@ grpc_security_status grpc_server_credentials_create_security_connector( /* -- Ssl credentials. -- */ -typedef struct { - grpc_credentials base; - grpc_ssl_config config; -} grpc_ssl_credentials; - -typedef struct { - grpc_server_credentials base; - grpc_ssl_server_config config; -} grpc_ssl_server_credentials; - static void ssl_destroy(grpc_credentials *creds) { grpc_ssl_credentials *c = (grpc_ssl_credentials *)creds; if (c->config.pem_root_certs != NULL) gpr_free(c->config.pem_root_certs); @@ -326,22 +315,6 @@ grpc_server_credentials *grpc_ssl_server_credentials_create( /* -- Jwt credentials -- */ -typedef struct { - grpc_credentials base; - - /* Have a simple cache for now with just 1 entry. We could have a map based on - the service_url for a more sophisticated one. */ - gpr_mu cache_mu; - struct { - grpc_credentials_md_store *jwt_md; - char *service_url; - gpr_timespec jwt_expiration; - } cached; - - grpc_auth_json_key key; - gpr_timespec jwt_lifetime; -} grpc_jwt_credentials; - static void jwt_reset_cache(grpc_jwt_credentials *c) { if (c->cached.jwt_md != NULL) { grpc_credentials_md_store_unref(c->cached.jwt_md); @@ -384,7 +357,8 @@ static void jwt_get_request_metadata(grpc_credentials *creds, if (c->cached.service_url != NULL && strcmp(c->cached.service_url, service_url) == 0 && c->cached.jwt_md != NULL && - (gpr_time_cmp(gpr_time_sub(c->cached.jwt_expiration, gpr_now()), + (gpr_time_cmp(gpr_time_sub(c->cached.jwt_expiration, + gpr_now(GPR_CLOCK_REALTIME)), refresh_threshold) > 0)) { jwt_md = grpc_credentials_md_store_ref(c->cached.jwt_md); } @@ -401,7 +375,8 @@ static void jwt_get_request_metadata(grpc_credentials *creds, char *md_value; gpr_asprintf(&md_value, "Bearer %s", jwt); gpr_free(jwt); - c->cached.jwt_expiration = gpr_time_add(gpr_now(), c->jwt_lifetime); + c->cached.jwt_expiration = + gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), c->jwt_lifetime); c->cached.service_url = gpr_strdup(service_url); c->cached.jwt_md = grpc_credentials_md_store_create(1); grpc_credentials_md_store_add_cstrings( @@ -424,10 +399,9 @@ static grpc_credentials_vtable jwt_vtable = { jwt_destroy, jwt_has_request_metadata, jwt_has_request_metadata_only, jwt_get_request_metadata, NULL}; -grpc_credentials *grpc_jwt_credentials_create(const char *json_key, - gpr_timespec token_lifetime) { +grpc_credentials *grpc_jwt_credentials_create_from_auth_json_key( + grpc_auth_json_key key, gpr_timespec token_lifetime) { grpc_jwt_credentials *c; - grpc_auth_json_key key = grpc_auth_json_key_create_from_string(json_key); if (!grpc_auth_json_key_is_valid(&key)) { gpr_log(GPR_ERROR, "Invalid input for jwt credentials creation"); return NULL; @@ -444,25 +418,13 @@ grpc_credentials *grpc_jwt_credentials_create(const char *json_key, return &c->base; } -/* -- Oauth2TokenFetcher credentials -- */ - -/* This object is a base for credentials that need to acquire an oauth2 token - from an http service. */ - -typedef void (*grpc_fetch_oauth2_func)(grpc_credentials_metadata_request *req, - grpc_httpcli_context *http_context, - grpc_pollset *pollset, - grpc_httpcli_response_cb response_cb, - gpr_timespec deadline); +grpc_credentials *grpc_jwt_credentials_create(const char *json_key, + gpr_timespec token_lifetime) { + return grpc_jwt_credentials_create_from_auth_json_key( + grpc_auth_json_key_create_from_string(json_key), token_lifetime); +} -typedef struct { - grpc_credentials base; - gpr_mu mu; - grpc_credentials_md_store *access_token_md; - gpr_timespec token_expiration; - grpc_httpcli_context httpcli_context; - grpc_fetch_oauth2_func fetch_func; -} grpc_oauth2_token_fetcher_credentials; +/* -- Oauth2TokenFetcher credentials -- */ static void oauth2_token_fetcher_destroy(grpc_credentials *creds) { grpc_oauth2_token_fetcher_credentials *c = @@ -585,7 +547,8 @@ static void on_oauth2_token_fetcher_http_response( status = grpc_oauth2_token_fetcher_credentials_parse_server_response( response, &c->access_token_md, &token_lifetime); if (status == GRPC_CREDENTIALS_OK) { - c->token_expiration = gpr_time_add(gpr_now(), token_lifetime); + c->token_expiration = + gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), token_lifetime); r->cb(r->user_data, c->access_token_md->entries, c->access_token_md->num_entries, status); } else { @@ -607,8 +570,9 @@ static void oauth2_token_fetcher_get_request_metadata( { gpr_mu_lock(&c->mu); if (c->access_token_md != NULL && - (gpr_time_cmp(gpr_time_sub(c->token_expiration, gpr_now()), - refresh_threshold) > 0)) { + (gpr_time_cmp( + gpr_time_sub(c->token_expiration, gpr_now(GPR_CLOCK_REALTIME)), + refresh_threshold) > 0)) { cached_access_token_md = grpc_credentials_md_store_ref(c->access_token_md); } @@ -622,7 +586,7 @@ static void oauth2_token_fetcher_get_request_metadata( c->fetch_func( grpc_credentials_metadata_request_create(creds, cb, user_data), &c->httpcli_context, pollset, on_oauth2_token_fetcher_http_response, - gpr_time_add(gpr_now(), refresh_threshold)); + gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), refresh_threshold)); } } @@ -669,13 +633,6 @@ grpc_credentials *grpc_compute_engine_credentials_create(void) { /* -- ServiceAccount credentials. -- */ -typedef struct { - grpc_oauth2_token_fetcher_credentials base; - grpc_auth_json_key key; - char *scope; - gpr_timespec token_lifetime; -} grpc_service_account_credentials; - static void service_account_destroy(grpc_credentials *creds) { grpc_service_account_credentials *c = (grpc_service_account_credentials *)creds; @@ -746,11 +703,6 @@ grpc_credentials *grpc_service_account_credentials_create( /* -- RefreshToken credentials. -- */ -typedef struct { - grpc_oauth2_token_fetcher_credentials base; - grpc_auth_refresh_token refresh_token; -} grpc_refresh_token_credentials; - static void refresh_token_destroy(grpc_credentials *creds) { grpc_refresh_token_credentials *c = (grpc_refresh_token_credentials *)creds; grpc_auth_refresh_token_destruct(&c->refresh_token); @@ -786,12 +738,9 @@ static void refresh_token_fetch_oauth2( gpr_free(body); } -grpc_credentials *grpc_refresh_token_credentials_create( - const char *json_refresh_token) { +grpc_credentials *grpc_refresh_token_credentials_create_from_auth_refresh_token( + grpc_auth_refresh_token refresh_token) { grpc_refresh_token_credentials *c; - grpc_auth_refresh_token refresh_token = - grpc_auth_refresh_token_create_from_string(json_refresh_token); - if (!grpc_auth_refresh_token_is_valid(&refresh_token)) { gpr_log(GPR_ERROR, "Invalid input for refresh token credentials creation"); return NULL; @@ -804,13 +753,13 @@ grpc_credentials *grpc_refresh_token_credentials_create( return &c->base.base; } -/* -- Fake Oauth2 credentials. -- */ +grpc_credentials *grpc_refresh_token_credentials_create( + const char *json_refresh_token) { + return grpc_refresh_token_credentials_create_from_auth_refresh_token( + grpc_auth_refresh_token_create_from_string(json_refresh_token)); +} -typedef struct { - grpc_credentials base; - grpc_credentials_md_store *access_token_md; - int is_async; -} grpc_fake_oauth2_credentials; +/* -- Fake Oauth2 credentials. -- */ static void fake_oauth2_destroy(grpc_credentials *creds) { grpc_fake_oauth2_credentials *c = (grpc_fake_oauth2_credentials *)creds; @@ -877,11 +826,6 @@ grpc_credentials *grpc_fake_oauth2_credentials_create( /* -- Oauth2 Access Token credentials. -- */ -typedef struct { - grpc_credentials base; - grpc_credentials_md_store *access_token_md; -} grpc_access_token_credentials; - static void access_token_destroy(grpc_credentials *creds) { grpc_access_token_credentials *c = (grpc_access_token_credentials *)creds; grpc_credentials_md_store_unref(c->access_token_md); @@ -997,12 +941,6 @@ grpc_server_credentials *grpc_fake_transport_security_server_credentials_create( /* -- Composite credentials. -- */ typedef struct { - grpc_credentials base; - grpc_credentials_array inner; - grpc_credentials *connector_creds; -} grpc_composite_credentials; - -typedef struct { grpc_composite_credentials *composite_creds; size_t creds_index; grpc_credentials_md_store *md_elems; @@ -1232,11 +1170,6 @@ grpc_credentials *grpc_credentials_contains_type( /* -- IAM credentials. -- */ -typedef struct { - grpc_credentials base; - grpc_credentials_md_store *iam_md; -} grpc_iam_credentials; - static void iam_destroy(grpc_credentials *creds) { grpc_iam_credentials *c = (grpc_iam_credentials *)creds; grpc_credentials_md_store_unref(c->iam_md); diff --git a/src/core/security/credentials.h b/src/core/security/credentials.h index 75af73a0c6..d988901cf7 100644 --- a/src/core/security/credentials.h +++ b/src/core/security/credentials.h @@ -39,6 +39,8 @@ #include <grpc/grpc_security.h> #include <grpc/support/sync.h> +#include "src/core/httpcli/httpcli.h" +#include "src/core/security/json_token.h" #include "src/core/security/security_connector.h" struct grpc_httpcli_response; @@ -178,11 +180,22 @@ grpc_credentials_status grpc_oauth2_token_fetcher_credentials_parse_server_response( const struct grpc_httpcli_response *response, grpc_credentials_md_store **token_md, gpr_timespec *token_lifetime); +void grpc_flush_cached_google_default_credentials(void); /* Simulates an oauth2 token fetch with the specified value for testing. */ grpc_credentials *grpc_fake_oauth2_credentials_create( const char *token_md_value, int is_async); +/* Private constructor for jwt credentials from an already parsed json key. + Takes ownership of the key. */ +grpc_credentials *grpc_jwt_credentials_create_from_auth_json_key( + grpc_auth_json_key key, gpr_timespec token_lifetime); + +/* Private constructor for refresh token credentials from an already parsed + refresh token. Takes ownership of the refresh token. */ +grpc_credentials *grpc_refresh_token_credentials_create_from_auth_refresh_token( + grpc_auth_refresh_token token); + /* --- grpc_server_credentials. --- */ typedef struct { @@ -199,4 +212,103 @@ struct grpc_server_credentials { grpc_security_status grpc_server_credentials_create_security_connector( grpc_server_credentials *creds, grpc_security_connector **sc); +/* -- Ssl credentials. -- */ + +typedef struct { + grpc_credentials base; + grpc_ssl_config config; +} grpc_ssl_credentials; + +typedef struct { + grpc_server_credentials base; + grpc_ssl_server_config config; +} grpc_ssl_server_credentials; + +/* -- Jwt credentials -- */ + +typedef struct { + grpc_credentials base; + + /* Have a simple cache for now with just 1 entry. We could have a map based on + the service_url for a more sophisticated one. */ + gpr_mu cache_mu; + struct { + grpc_credentials_md_store *jwt_md; + char *service_url; + gpr_timespec jwt_expiration; + } cached; + + grpc_auth_json_key key; + gpr_timespec jwt_lifetime; +} grpc_jwt_credentials; + +/* -- Oauth2TokenFetcher credentials -- + + This object is a base for credentials that need to acquire an oauth2 token + from an http service. */ + +typedef struct grpc_credentials_metadata_request + grpc_credentials_metadata_request; + +typedef void (*grpc_fetch_oauth2_func)(grpc_credentials_metadata_request *req, + grpc_httpcli_context *http_context, + grpc_pollset *pollset, + grpc_httpcli_response_cb response_cb, + gpr_timespec deadline); + +typedef struct { + grpc_credentials base; + gpr_mu mu; + grpc_credentials_md_store *access_token_md; + gpr_timespec token_expiration; + grpc_httpcli_context httpcli_context; + grpc_fetch_oauth2_func fetch_func; +} grpc_oauth2_token_fetcher_credentials; + +/* -- ServiceAccount credentials. -- */ + +typedef struct { + grpc_oauth2_token_fetcher_credentials base; + grpc_auth_json_key key; + char *scope; + gpr_timespec token_lifetime; +} grpc_service_account_credentials; + +/* -- RefreshToken credentials. -- */ + +typedef struct { + grpc_oauth2_token_fetcher_credentials base; + grpc_auth_refresh_token refresh_token; +} grpc_refresh_token_credentials; + +/* -- Oauth2 Access Token credentials. -- */ + +typedef struct { + grpc_credentials base; + grpc_credentials_md_store *access_token_md; +} grpc_access_token_credentials; + +/* -- Fake Oauth2 credentials. -- */ + +typedef struct { + grpc_credentials base; + grpc_credentials_md_store *access_token_md; + int is_async; +} grpc_fake_oauth2_credentials; + +/* -- IAM credentials. -- */ + +typedef struct { + grpc_credentials base; + grpc_credentials_md_store *iam_md; +} grpc_iam_credentials; + +/* -- Composite credentials. -- */ + +typedef struct { + grpc_credentials base; + grpc_credentials_array inner; + grpc_credentials *connector_creds; +} grpc_composite_credentials; + #endif /* GRPC_INTERNAL_CORE_SECURITY_CREDENTIALS_H */ diff --git a/src/core/security/google_default_credentials.c b/src/core/security/google_default_credentials.c index 5822ce6337..f622deff42 100644 --- a/src/core/security/google_default_credentials.c +++ b/src/core/security/google_default_credentials.c @@ -46,7 +46,6 @@ /* -- Constants. -- */ #define GRPC_COMPUTE_ENGINE_DETECTION_HOST "metadata.google.internal" -#define GRPC_GOOGLE_CREDENTIALS_ENV_VAR "GOOGLE_APPLICATION_CREDENTIALS" /* -- Default credentials. -- */ @@ -104,9 +103,10 @@ static int is_stack_running_on_compute_engine(void) { grpc_httpcli_context_init(&context); - grpc_httpcli_get(&context, &detector.pollset, &request, - gpr_time_add(gpr_now(), max_detection_delay), - on_compute_engine_detection_http_response, &detector); + grpc_httpcli_get( + &context, &detector.pollset, &request, + gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), max_detection_delay), + on_compute_engine_detection_http_response, &detector); /* Block until we get the response. This is not ideal but this should only be called once for the lifetime of the process by the default credentials. */ @@ -123,36 +123,40 @@ static int is_stack_running_on_compute_engine(void) { } /* Takes ownership of creds_path if not NULL. */ -static grpc_credentials *create_jwt_creds_from_path(char *creds_path) { +static grpc_credentials *create_default_creds_from_path(char *creds_path) { + grpc_json *json = NULL; + grpc_auth_json_key key; + grpc_auth_refresh_token token; grpc_credentials *result = NULL; - gpr_slice creds_data; + gpr_slice creds_data = gpr_empty_slice(); int file_ok = 0; - if (creds_path == NULL) return NULL; - creds_data = gpr_load_file(creds_path, 1, &file_ok); - gpr_free(creds_path); - if (file_ok) { - result = grpc_jwt_credentials_create( - (const char *)GPR_SLICE_START_PTR(creds_data), - grpc_max_auth_token_lifetime); - gpr_slice_unref(creds_data); + if (creds_path == NULL) goto end; + creds_data = gpr_load_file(creds_path, 0, &file_ok); + if (!file_ok) goto end; + json = grpc_json_parse_string_with_len( + (char *)GPR_SLICE_START_PTR(creds_data), GPR_SLICE_LENGTH(creds_data)); + if (json == NULL) goto end; + + /* First, try an auth json key. */ + key = grpc_auth_json_key_create_from_json(json); + if (grpc_auth_json_key_is_valid(&key)) { + result = grpc_jwt_credentials_create_from_auth_json_key( + key, grpc_max_auth_token_lifetime); + goto end; } - return result; -} -/* Takes ownership of creds_path if not NULL. */ -static grpc_credentials *create_refresh_token_creds_from_path( - char *creds_path) { - grpc_credentials *result = NULL; - gpr_slice creds_data; - int file_ok = 0; - if (creds_path == NULL) return NULL; - creds_data = gpr_load_file(creds_path, 1, &file_ok); - gpr_free(creds_path); - if (file_ok) { - result = grpc_refresh_token_credentials_create( - (const char *)GPR_SLICE_START_PTR(creds_data)); - gpr_slice_unref(creds_data); + /* Then try a refresh token if the auth json key was invalid. */ + token = grpc_auth_refresh_token_create_from_json(json); + if (grpc_auth_refresh_token_is_valid(&token)) { + result = + grpc_refresh_token_credentials_create_from_auth_refresh_token(token); + goto end; } + +end: + if (creds_path != NULL) gpr_free(creds_path); + gpr_slice_unref(creds_data); + if (json != NULL) grpc_json_destroy(json); return result; } @@ -170,12 +174,12 @@ grpc_credentials *grpc_google_default_credentials_create(void) { } /* First, try the environment variable. */ - result = - create_jwt_creds_from_path(gpr_getenv(GRPC_GOOGLE_CREDENTIALS_ENV_VAR)); + result = create_default_creds_from_path( + gpr_getenv(GRPC_GOOGLE_CREDENTIALS_ENV_VAR)); if (result != NULL) goto end; /* Then the well-known file. */ - result = create_refresh_token_creds_from_path( + result = create_default_creds_from_path( grpc_get_well_known_google_credentials_file_path()); if (result != NULL) goto end; @@ -193,11 +197,24 @@ end: if (!serving_cached_credentials && result != NULL) { /* Blend with default ssl credentials and add a global reference so that it can be cached and re-served. */ - result = grpc_composite_credentials_create( - grpc_ssl_credentials_create(NULL, NULL), result); - GPR_ASSERT(result != NULL); - default_credentials = grpc_credentials_ref(result); + grpc_credentials *ssl_creds = grpc_ssl_credentials_create(NULL, NULL); + default_credentials = grpc_credentials_ref(grpc_composite_credentials_create( + ssl_creds, result)); + GPR_ASSERT(default_credentials != NULL); + grpc_credentials_unref(ssl_creds); + grpc_credentials_unref(result); + result = default_credentials; } gpr_mu_unlock(&g_mu); return result; } + +void grpc_flush_cached_google_default_credentials(void) { + gpr_once_init(&g_once, init_default_credentials); + gpr_mu_lock(&g_mu); + if (default_credentials != NULL) { + grpc_credentials_unref(default_credentials); + default_credentials = NULL; + } + gpr_mu_unlock(&g_mu); +} diff --git a/src/core/security/json_token.c b/src/core/security/json_token.c index 6116f1d767..9b1ea255ae 100644 --- a/src/core/security/json_token.c +++ b/src/core/security/json_token.c @@ -46,17 +46,11 @@ #include <openssl/evp.h> #include <openssl/pem.h> -#include "src/core/json/json.h" - /* --- Constants. --- */ /* 1 hour max. */ const gpr_timespec grpc_max_auth_token_lifetime = {3600, 0}; -#define GRPC_AUTH_JSON_TYPE_INVALID "invalid" -#define GRPC_AUTH_JSON_TYPE_SERVICE_ACCOUNT "service_account" -#define GRPC_AUTH_JSON_TYPE_AUTHORIZED_USER "authorized_user" - #define GRPC_JWT_RSA_SHA256_ALGORITHM "RS256" #define GRPC_JWT_TYPE "JWT" @@ -66,7 +60,7 @@ static grpc_jwt_encode_and_sign_override g_jwt_encode_and_sign_override = NULL; /* --- grpc_auth_json_key. --- */ -static const char *json_get_string_property(grpc_json *json, +static const char *json_get_string_property(const grpc_json *json, const char *prop_name) { grpc_json *child; for (child = json->child; child != NULL; child = child->next) { @@ -79,7 +73,8 @@ static const char *json_get_string_property(grpc_json *json, return child->value; } -static int set_json_key_string_property(grpc_json *json, const char *prop_name, +static int set_json_key_string_property(const grpc_json *json, + const char *prop_name, char **json_key_field) { const char *prop_value = json_get_string_property(json, prop_name); if (prop_value == NULL) return 0; @@ -92,11 +87,8 @@ int grpc_auth_json_key_is_valid(const grpc_auth_json_key *json_key) { strcmp(json_key->type, GRPC_AUTH_JSON_TYPE_INVALID); } -grpc_auth_json_key grpc_auth_json_key_create_from_string( - const char *json_string) { +grpc_auth_json_key grpc_auth_json_key_create_from_json(const grpc_json *json) { grpc_auth_json_key result; - char *scratchpad = gpr_strdup(json_string); - grpc_json *json = grpc_json_parse_string(scratchpad); BIO *bio = NULL; const char *prop_value; int success = 0; @@ -104,7 +96,7 @@ grpc_auth_json_key grpc_auth_json_key_create_from_string( memset(&result, 0, sizeof(grpc_auth_json_key)); result.type = GRPC_AUTH_JSON_TYPE_INVALID; if (json == NULL) { - gpr_log(GPR_ERROR, "Invalid json string %s", json_string); + gpr_log(GPR_ERROR, "Invalid json."); goto end; } @@ -142,8 +134,16 @@ grpc_auth_json_key grpc_auth_json_key_create_from_string( end: if (bio != NULL) BIO_free(bio); - if (json != NULL) grpc_json_destroy(json); if (!success) grpc_auth_json_key_destruct(&result); + return result; +} + +grpc_auth_json_key grpc_auth_json_key_create_from_string( + const char *json_string) { + char *scratchpad = gpr_strdup(json_string); + grpc_json *json = grpc_json_parse_string(scratchpad); + grpc_auth_json_key result = grpc_auth_json_key_create_from_json(json); + if (json != NULL) grpc_json_destroy(json); gpr_free(scratchpad); return result; } @@ -207,7 +207,7 @@ static char *encoded_jwt_claim(const grpc_auth_json_key *json_key, grpc_json *child = NULL; char *json_str = NULL; char *result = NULL; - gpr_timespec now = gpr_now(); + gpr_timespec now = gpr_now(GPR_CLOCK_REALTIME); gpr_timespec expiration = gpr_time_add(now, token_lifetime); char now_str[GPR_LTOA_MIN_BUFSIZE]; char expiration_str[GPR_LTOA_MIN_BUFSIZE]; @@ -218,8 +218,8 @@ static char *encoded_jwt_claim(const grpc_auth_json_key *json_key, gpr_ltoa(now.tv_sec, now_str); gpr_ltoa(expiration.tv_sec, expiration_str); - child = create_child(NULL, json, "iss", json_key->client_email, - GRPC_JSON_STRING); + child = + create_child(NULL, json, "iss", json_key->client_email, GRPC_JSON_STRING); if (scope != NULL) { child = create_child(child, json, "scope", scope, GRPC_JSON_STRING); } else { @@ -342,18 +342,16 @@ int grpc_auth_refresh_token_is_valid( strcmp(refresh_token->type, GRPC_AUTH_JSON_TYPE_INVALID); } -grpc_auth_refresh_token grpc_auth_refresh_token_create_from_string( - const char *json_string) { +grpc_auth_refresh_token grpc_auth_refresh_token_create_from_json( + const grpc_json *json) { grpc_auth_refresh_token result; - char *scratchpad = gpr_strdup(json_string); - grpc_json *json = grpc_json_parse_string(scratchpad); const char *prop_value; int success = 0; memset(&result, 0, sizeof(grpc_auth_refresh_token)); result.type = GRPC_AUTH_JSON_TYPE_INVALID; if (json == NULL) { - gpr_log(GPR_ERROR, "Invalid json string %s", json_string); + gpr_log(GPR_ERROR, "Invalid json."); goto end; } @@ -374,8 +372,17 @@ grpc_auth_refresh_token grpc_auth_refresh_token_create_from_string( success = 1; end: - if (json != NULL) grpc_json_destroy(json); if (!success) grpc_auth_refresh_token_destruct(&result); + return result; +} + +grpc_auth_refresh_token grpc_auth_refresh_token_create_from_string( + const char *json_string) { + char *scratchpad = gpr_strdup(json_string); + grpc_json *json = grpc_json_parse_string(scratchpad); + grpc_auth_refresh_token result = + grpc_auth_refresh_token_create_from_json(json); + if (json != NULL) grpc_json_destroy(json); gpr_free(scratchpad); return result; } @@ -396,4 +403,3 @@ void grpc_auth_refresh_token_destruct(grpc_auth_refresh_token *refresh_token) { refresh_token->refresh_token = NULL; } } - diff --git a/src/core/security/json_token.h b/src/core/security/json_token.h index 197796ab4c..091dfefb6e 100644 --- a/src/core/security/json_token.h +++ b/src/core/security/json_token.h @@ -37,10 +37,16 @@ #include <grpc/support/slice.h> #include <openssl/rsa.h> +#include "src/core/json/json.h" + /* --- Constants. --- */ #define GRPC_JWT_OAUTH2_AUDIENCE "https://www.googleapis.com/oauth2/v3/token" +#define GRPC_AUTH_JSON_TYPE_INVALID "invalid" +#define GRPC_AUTH_JSON_TYPE_SERVICE_ACCOUNT "service_account" +#define GRPC_AUTH_JSON_TYPE_AUTHORIZED_USER "authorized_user" + /* --- auth_json_key parsing. --- */ typedef struct { @@ -59,6 +65,10 @@ int grpc_auth_json_key_is_valid(const grpc_auth_json_key *json_key); grpc_auth_json_key grpc_auth_json_key_create_from_string( const char *json_string); +/* Creates a json_key object from parsed json. Returns an invalid object if a + parsing error has been encountered. */ +grpc_auth_json_key grpc_auth_json_key_create_from_json(const grpc_json *json); + /* Destructs the object. */ void grpc_auth_json_key_destruct(grpc_auth_json_key *json_key); @@ -97,6 +107,11 @@ int grpc_auth_refresh_token_is_valid( grpc_auth_refresh_token grpc_auth_refresh_token_create_from_string( const char *json_string); +/* Creates a refresh token object from parsed json. Returns an invalid object if + a parsing error has been encountered. */ +grpc_auth_refresh_token grpc_auth_refresh_token_create_from_json( + const grpc_json *json); + /* Destructs the object. */ void grpc_auth_refresh_token_destruct(grpc_auth_refresh_token *refresh_token); diff --git a/src/core/security/jwt_verifier.c b/src/core/security/jwt_verifier.c index 01007a1a84..9140eb2ef7 100644 --- a/src/core/security/jwt_verifier.c +++ b/src/core/security/jwt_verifier.c @@ -189,7 +189,6 @@ struct grpc_jwt_claims { gpr_slice buffer; }; - void grpc_jwt_claims_destroy(grpc_jwt_claims *claims) { grpc_json_destroy(claims->json); gpr_slice_unref(claims->buffer); @@ -286,12 +285,14 @@ grpc_jwt_verifier_status grpc_jwt_claims_check(const grpc_jwt_claims *claims, GPR_ASSERT(claims != NULL); - skewed_now = gpr_time_add(gpr_now(), grpc_jwt_verifier_clock_skew); + skewed_now = + gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), grpc_jwt_verifier_clock_skew); if (gpr_time_cmp(skewed_now, claims->nbf) < 0) { gpr_log(GPR_ERROR, "JWT is not valid yet."); return GRPC_JWT_VERIFIER_TIME_CONSTRAINT_FAILURE; } - skewed_now = gpr_time_sub(gpr_now(), grpc_jwt_verifier_clock_skew); + skewed_now = + gpr_time_sub(gpr_now(GPR_CLOCK_REALTIME), grpc_jwt_verifier_clock_skew); if (gpr_time_cmp(skewed_now, claims->exp) > 0) { gpr_log(GPR_ERROR, "JWT is expired."); return GRPC_JWT_VERIFIER_TIME_CONSTRAINT_FAILURE; @@ -327,10 +328,10 @@ typedef struct { /* Takes ownership of the header, claims and signature. */ static verifier_cb_ctx *verifier_cb_ctx_create( - grpc_jwt_verifier *verifier, grpc_pollset *pollset, - jose_header * header, grpc_jwt_claims *claims, const char *audience, - gpr_slice signature, const char *signed_jwt, size_t signed_jwt_len, - void *user_data, grpc_jwt_verification_done_cb cb) { + grpc_jwt_verifier *verifier, grpc_pollset *pollset, jose_header *header, + grpc_jwt_claims *claims, const char *audience, gpr_slice signature, + const char *signed_jwt, size_t signed_jwt_len, void *user_data, + grpc_jwt_verification_done_cb cb) { verifier_cb_ctx *ctx = gpr_malloc(sizeof(verifier_cb_ctx)); memset(ctx, 0, sizeof(verifier_cb_ctx)); ctx->verifier = verifier; @@ -604,7 +605,7 @@ end: static void on_openid_config_retrieved(void *user_data, const grpc_httpcli_response *response) { - const grpc_json* cur; + const grpc_json *cur; grpc_json *json = json_from_http(response); verifier_cb_ctx *ctx = (verifier_cb_ctx *)user_data; grpc_httpcli_request req; @@ -632,9 +633,10 @@ static void on_openid_config_retrieved(void *user_data, } else { *(req.host + (req.path - jwks_uri)) = '\0'; } - grpc_httpcli_get(&ctx->verifier->http_ctx, ctx->pollset, &req, - gpr_time_add(gpr_now(), grpc_jwt_verifier_max_delay), - on_keys_retrieved, ctx); + grpc_httpcli_get( + &ctx->verifier->http_ctx, ctx->pollset, &req, + gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), grpc_jwt_verifier_max_delay), + on_keys_retrieved, ctx); grpc_json_destroy(json); gpr_free(req.host); return; @@ -645,8 +647,8 @@ error: verifier_cb_ctx_destroy(ctx); } -static email_key_mapping *verifier_get_mapping( - grpc_jwt_verifier *v, const char *email_domain) { +static email_key_mapping *verifier_get_mapping(grpc_jwt_verifier *v, + const char *email_domain) { size_t i; if (v->mappings == NULL) return NULL; for (i = 0; i < v->num_mappings; i++) { @@ -733,9 +735,10 @@ static void retrieve_key_and_verify(verifier_cb_ctx *ctx) { http_cb = on_openid_config_retrieved; } - grpc_httpcli_get(&ctx->verifier->http_ctx, ctx->pollset, &req, - gpr_time_add(gpr_now(), grpc_jwt_verifier_max_delay), - http_cb, ctx); + grpc_httpcli_get( + &ctx->verifier->http_ctx, ctx->pollset, &req, + gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), grpc_jwt_verifier_max_delay), + http_cb, ctx); gpr_free(req.host); gpr_free(req.path); return; @@ -764,7 +767,7 @@ void grpc_jwt_verifier_verify(grpc_jwt_verifier *verifier, dot = strchr(cur, '.'); if (dot == NULL) goto error; json = parse_json_part_from_jwt(cur, dot - cur, &header_buffer); - if (json == NULL) goto error; + if (json == NULL) goto error; header = jose_header_from_json(json, header_buffer); if (header == NULL) goto error; @@ -772,7 +775,7 @@ void grpc_jwt_verifier_verify(grpc_jwt_verifier *verifier, dot = strchr(cur, '.'); if (dot == NULL) goto error; json = parse_json_part_from_jwt(cur, dot - cur, &claims_buffer); - if (json == NULL) goto error; + if (json == NULL) goto error; claims = grpc_jwt_claims_from_json(json, claims_buffer); if (claims == NULL) goto error; @@ -827,4 +830,3 @@ void grpc_jwt_verifier_destroy(grpc_jwt_verifier *v) { } gpr_free(v); } - diff --git a/src/core/security/security_context.c b/src/core/security/security_context.c index 4d56549f9b..8ce7876bd8 100644 --- a/src/core/security/security_context.c +++ b/src/core/security/security_context.c @@ -69,12 +69,20 @@ grpc_call_error grpc_call_set_credentials(grpc_call *call, return GRPC_CALL_OK; } -const grpc_auth_context *grpc_call_auth_context(grpc_call *call) { +grpc_auth_context *grpc_call_auth_context(grpc_call *call) { void *sec_ctx = grpc_call_context_get(call, GRPC_CONTEXT_SECURITY); if (sec_ctx == NULL) return NULL; return grpc_call_is_client(call) - ? ((grpc_client_security_context *)sec_ctx)->auth_context - : ((grpc_server_security_context *)sec_ctx)->auth_context; + ? GRPC_AUTH_CONTEXT_REF( + ((grpc_client_security_context *)sec_ctx)->auth_context, + "grpc_call_auth_context client") + : GRPC_AUTH_CONTEXT_REF( + ((grpc_server_security_context *)sec_ctx)->auth_context, + "grpc_call_auth_context server"); +} + +void grpc_auth_context_release(grpc_auth_context *context) { + GRPC_AUTH_CONTEXT_UNREF(context, "grpc_auth_context_unref"); } /* --- grpc_client_security_context --- */ diff --git a/src/core/security/security_context.h b/src/core/security/security_context.h index 20c4390898..76a45910bb 100644 --- a/src/core/security/security_context.h +++ b/src/core/security/security_context.h @@ -36,6 +36,10 @@ #include "src/core/security/credentials.h" +#ifdef __cplusplus +extern "C" { +#endif + /* --- grpc_auth_context --- High level authentication context object. Can optionally be chained. */ @@ -103,5 +107,9 @@ typedef struct { grpc_server_security_context *grpc_server_security_context_create(void); void grpc_server_security_context_destroy(void *ctx); +#ifdef __cplusplus +} +#endif + #endif /* GRPC_INTERNAL_CORE_SECURITY_SECURITY_CONTEXT_H */ |