diff options
Diffstat (limited to 'src/core/lib/security/credentials/jwt/jwt_verifier.c')
-rw-r--r-- | src/core/lib/security/credentials/jwt/jwt_verifier.c | 114 |
1 files changed, 64 insertions, 50 deletions
diff --git a/src/core/lib/security/credentials/jwt/jwt_verifier.c b/src/core/lib/security/credentials/jwt/jwt_verifier.c index 03097a57c0..2270be8f44 100644 --- a/src/core/lib/security/credentials/jwt/jwt_verifier.c +++ b/src/core/lib/security/credentials/jwt/jwt_verifier.c @@ -36,12 +36,6 @@ #include <limits.h> #include <string.h> -#include "src/core/lib/http/httpcli.h" -#include "src/core/lib/iomgr/polling_entity.h" -#include "src/core/lib/security/util/b64.h" -#include "src/core/lib/support/string.h" -#include "src/core/lib/tsi/ssl_types.h" - #include <grpc/support/alloc.h> #include <grpc/support/log.h> #include <grpc/support/string_util.h> @@ -49,6 +43,13 @@ #include <grpc/support/useful.h> #include <openssl/pem.h> +#include "src/core/lib/http/httpcli.h" +#include "src/core/lib/iomgr/polling_entity.h" +#include "src/core/lib/security/util/b64.h" +#include "src/core/lib/slice/slice_internal.h" +#include "src/core/lib/support/string.h" +#include "src/core/lib/tsi/ssl_types.h" + /* --- Utils. --- */ const char *grpc_jwt_verifier_status_to_string( @@ -85,11 +86,12 @@ static const EVP_MD *evp_md_from_alg(const char *alg) { } } -static grpc_json *parse_json_part_from_jwt(const char *str, size_t len, +static grpc_json *parse_json_part_from_jwt(grpc_exec_ctx *exec_ctx, + const char *str, size_t len, grpc_slice *buffer) { grpc_json *json; - *buffer = grpc_base64_decode_with_len(str, len, 1); + *buffer = grpc_base64_decode_with_len(exec_ctx, str, len, 1); if (GRPC_SLICE_IS_EMPTY(*buffer)) { gpr_log(GPR_ERROR, "Invalid base64."); return NULL; @@ -97,7 +99,7 @@ static grpc_json *parse_json_part_from_jwt(const char *str, size_t len, json = grpc_json_parse_string_with_len((char *)GRPC_SLICE_START_PTR(*buffer), GRPC_SLICE_LENGTH(*buffer)); if (json == NULL) { - grpc_slice_unref(*buffer); + grpc_slice_unref_internal(exec_ctx, *buffer); gpr_log(GPR_ERROR, "JSON parsing error."); } return json; @@ -133,13 +135,14 @@ typedef struct { grpc_slice buffer; } jose_header; -static void jose_header_destroy(jose_header *h) { - grpc_slice_unref(h->buffer); +static void jose_header_destroy(grpc_exec_ctx *exec_ctx, jose_header *h) { + grpc_slice_unref_internal(exec_ctx, h->buffer); gpr_free(h); } /* Takes ownership of json and buffer. */ -static jose_header *jose_header_from_json(grpc_json *json, grpc_slice buffer) { +static jose_header *jose_header_from_json(grpc_exec_ctx *exec_ctx, + grpc_json *json, grpc_slice buffer) { grpc_json *cur; jose_header *h = gpr_malloc(sizeof(jose_header)); memset(h, 0, sizeof(jose_header)); @@ -174,7 +177,7 @@ static jose_header *jose_header_from_json(grpc_json *json, grpc_slice buffer) { error: grpc_json_destroy(json); - jose_header_destroy(h); + jose_header_destroy(exec_ctx, h); return NULL; } @@ -194,9 +197,9 @@ struct grpc_jwt_claims { grpc_slice buffer; }; -void grpc_jwt_claims_destroy(grpc_jwt_claims *claims) { +void grpc_jwt_claims_destroy(grpc_exec_ctx *exec_ctx, grpc_jwt_claims *claims) { grpc_json_destroy(claims->json); - grpc_slice_unref(claims->buffer); + grpc_slice_unref_internal(exec_ctx, claims->buffer); gpr_free(claims); } @@ -241,7 +244,8 @@ gpr_timespec grpc_jwt_claims_not_before(const grpc_jwt_claims *claims) { } /* Takes ownership of json and buffer even in case of failure. */ -grpc_jwt_claims *grpc_jwt_claims_from_json(grpc_json *json, grpc_slice buffer) { +grpc_jwt_claims *grpc_jwt_claims_from_json(grpc_exec_ctx *exec_ctx, + grpc_json *json, grpc_slice buffer) { grpc_json *cur; grpc_jwt_claims *claims = gpr_malloc(sizeof(grpc_jwt_claims)); memset(claims, 0, sizeof(grpc_jwt_claims)); @@ -282,7 +286,7 @@ grpc_jwt_claims *grpc_jwt_claims_from_json(grpc_json *json, grpc_slice buffer) { return claims; error: - grpc_jwt_claims_destroy(claims); + grpc_jwt_claims_destroy(exec_ctx, claims); return NULL; } @@ -374,12 +378,12 @@ static verifier_cb_ctx *verifier_cb_ctx_create( return ctx; } -void verifier_cb_ctx_destroy(verifier_cb_ctx *ctx) { +void verifier_cb_ctx_destroy(grpc_exec_ctx *exec_ctx, verifier_cb_ctx *ctx) { if (ctx->audience != NULL) gpr_free(ctx->audience); - if (ctx->claims != NULL) grpc_jwt_claims_destroy(ctx->claims); - grpc_slice_unref(ctx->signature); - grpc_slice_unref(ctx->signed_data); - jose_header_destroy(ctx->header); + if (ctx->claims != NULL) grpc_jwt_claims_destroy(exec_ctx, ctx->claims); + grpc_slice_unref_internal(exec_ctx, ctx->signature); + grpc_slice_unref_internal(exec_ctx, ctx->signed_data); + jose_header_destroy(exec_ctx, ctx->header); for (size_t i = 0; i < HTTP_RESPONSE_COUNT; i++) { grpc_http_response_destroy(&ctx->responses[i]); } @@ -459,23 +463,24 @@ end: return result; } -static BIGNUM *bignum_from_base64(const char *b64) { +static BIGNUM *bignum_from_base64(grpc_exec_ctx *exec_ctx, const char *b64) { BIGNUM *result = NULL; grpc_slice bin; if (b64 == NULL) return NULL; - bin = grpc_base64_decode(b64, 1); + bin = grpc_base64_decode(exec_ctx, b64, 1); if (GRPC_SLICE_IS_EMPTY(bin)) { gpr_log(GPR_ERROR, "Invalid base64 for big num."); return NULL; } result = BN_bin2bn(GRPC_SLICE_START_PTR(bin), TSI_SIZE_AS_SIZE(GRPC_SLICE_LENGTH(bin)), NULL); - grpc_slice_unref(bin); + grpc_slice_unref_internal(exec_ctx, bin); return result; } -static EVP_PKEY *pkey_from_jwk(const grpc_json *json, const char *kty) { +static EVP_PKEY *pkey_from_jwk(grpc_exec_ctx *exec_ctx, const grpc_json *json, + const char *kty) { const grpc_json *key_prop; RSA *rsa = NULL; EVP_PKEY *result = NULL; @@ -492,10 +497,12 @@ static EVP_PKEY *pkey_from_jwk(const grpc_json *json, const char *kty) { } for (key_prop = json->child; key_prop != NULL; key_prop = key_prop->next) { if (strcmp(key_prop->key, "n") == 0) { - rsa->n = bignum_from_base64(validate_string_field(key_prop, "n")); + rsa->n = + bignum_from_base64(exec_ctx, validate_string_field(key_prop, "n")); if (rsa->n == NULL) goto end; } else if (strcmp(key_prop->key, "e") == 0) { - rsa->e = bignum_from_base64(validate_string_field(key_prop, "e")); + rsa->e = + bignum_from_base64(exec_ctx, validate_string_field(key_prop, "e")); if (rsa->e == NULL) goto end; } } @@ -511,7 +518,8 @@ end: return result; } -static EVP_PKEY *find_verification_key(const grpc_json *json, +static EVP_PKEY *find_verification_key(grpc_exec_ctx *exec_ctx, + const grpc_json *json, const char *header_alg, const char *header_kid) { const grpc_json *jkey; @@ -555,7 +563,7 @@ static EVP_PKEY *find_verification_key(const grpc_json *json, } if (alg != NULL && kid != NULL && kty != NULL && strcmp(kid, header_kid) == 0 && strcmp(alg, header_alg) == 0) { - return pkey_from_jwk(jkey, kty); + return pkey_from_jwk(exec_ctx, jkey, kty); } } gpr_log(GPR_ERROR, @@ -609,7 +617,7 @@ static void on_keys_retrieved(grpc_exec_ctx *exec_ctx, void *user_data, goto end; } verification_key = - find_verification_key(json, ctx->header->alg, ctx->header->kid); + find_verification_key(exec_ctx, json, ctx->header->alg, ctx->header->kid); if (verification_key == NULL) { gpr_log(GPR_ERROR, "Could not find verification key with kid %s.", ctx->header->kid); @@ -633,8 +641,8 @@ static void on_keys_retrieved(grpc_exec_ctx *exec_ctx, void *user_data, end: if (json != NULL) grpc_json_destroy(json); if (verification_key != NULL) EVP_PKEY_free(verification_key); - ctx->user_cb(ctx->user_data, status, claims); - verifier_cb_ctx_destroy(ctx); + ctx->user_cb(exec_ctx, ctx->user_data, status, claims); + verifier_cb_ctx_destroy(exec_ctx, ctx); } static void on_openid_config_retrieved(grpc_exec_ctx *exec_ctx, void *user_data, @@ -677,17 +685,18 @@ static void on_openid_config_retrieved(grpc_exec_ctx *exec_ctx, void *user_data, grpc_httpcli_get( exec_ctx, &ctx->verifier->http_ctx, &ctx->pollent, resource_quota, &req, gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), grpc_jwt_verifier_max_delay), - grpc_closure_create(on_keys_retrieved, ctx), + grpc_closure_create(on_keys_retrieved, ctx, grpc_schedule_on_exec_ctx), &ctx->responses[HTTP_RESPONSE_KEYS]); - grpc_resource_quota_internal_unref(exec_ctx, resource_quota); + grpc_resource_quota_unref_internal(exec_ctx, resource_quota); grpc_json_destroy(json); gpr_free(req.host); return; error: if (json != NULL) grpc_json_destroy(json); - ctx->user_cb(ctx->user_data, GRPC_JWT_VERIFIER_KEY_RETRIEVAL_ERROR, NULL); - verifier_cb_ctx_destroy(ctx); + ctx->user_cb(exec_ctx, ctx->user_data, GRPC_JWT_VERIFIER_KEY_RETRIEVAL_ERROR, + NULL); + verifier_cb_ctx_destroy(exec_ctx, ctx); } static email_key_mapping *verifier_get_mapping(grpc_jwt_verifier *v, @@ -778,7 +787,8 @@ static void retrieve_key_and_verify(grpc_exec_ctx *exec_ctx, *(path_prefix++) = '\0'; gpr_asprintf(&req.http.path, "/%s/%s", path_prefix, iss); } - http_cb = grpc_closure_create(on_keys_retrieved, ctx); + http_cb = + grpc_closure_create(on_keys_retrieved, ctx, grpc_schedule_on_exec_ctx); rsp_idx = HTTP_RESPONSE_KEYS; } else { req.host = gpr_strdup(strstr(iss, "https://") == iss ? iss + 8 : iss); @@ -790,7 +800,8 @@ static void retrieve_key_and_verify(grpc_exec_ctx *exec_ctx, gpr_asprintf(&req.http.path, "/%s%s", path_prefix, GRPC_OPENID_CONFIG_URL_SUFFIX); } - http_cb = grpc_closure_create(on_openid_config_retrieved, ctx); + http_cb = grpc_closure_create(on_openid_config_retrieved, ctx, + grpc_schedule_on_exec_ctx); rsp_idx = HTTP_RESPONSE_OPENID; } @@ -803,14 +814,15 @@ static void retrieve_key_and_verify(grpc_exec_ctx *exec_ctx, exec_ctx, &ctx->verifier->http_ctx, &ctx->pollent, resource_quota, &req, gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), grpc_jwt_verifier_max_delay), http_cb, &ctx->responses[rsp_idx]); - grpc_resource_quota_internal_unref(exec_ctx, resource_quota); + grpc_resource_quota_unref_internal(exec_ctx, resource_quota); gpr_free(req.host); gpr_free(req.http.path); return; error: - ctx->user_cb(ctx->user_data, GRPC_JWT_VERIFIER_KEY_RETRIEVAL_ERROR, NULL); - verifier_cb_ctx_destroy(ctx); + ctx->user_cb(exec_ctx, ctx->user_data, GRPC_JWT_VERIFIER_KEY_RETRIEVAL_ERROR, + NULL); + verifier_cb_ctx_destroy(exec_ctx, ctx); } void grpc_jwt_verifier_verify(grpc_exec_ctx *exec_ctx, @@ -832,22 +844,24 @@ void grpc_jwt_verifier_verify(grpc_exec_ctx *exec_ctx, GPR_ASSERT(verifier != NULL && jwt != NULL && audience != NULL && cb != NULL); dot = strchr(cur, '.'); if (dot == NULL) goto error; - json = parse_json_part_from_jwt(cur, (size_t)(dot - cur), &header_buffer); + json = parse_json_part_from_jwt(exec_ctx, cur, (size_t)(dot - cur), + &header_buffer); if (json == NULL) goto error; - header = jose_header_from_json(json, header_buffer); + header = jose_header_from_json(exec_ctx, json, header_buffer); if (header == NULL) goto error; cur = dot + 1; dot = strchr(cur, '.'); if (dot == NULL) goto error; - json = parse_json_part_from_jwt(cur, (size_t)(dot - cur), &claims_buffer); + json = parse_json_part_from_jwt(exec_ctx, cur, (size_t)(dot - cur), + &claims_buffer); if (json == NULL) goto error; - claims = grpc_jwt_claims_from_json(json, claims_buffer); + claims = grpc_jwt_claims_from_json(exec_ctx, json, claims_buffer); if (claims == NULL) goto error; signed_jwt_len = (size_t)(dot - jwt); cur = dot + 1; - signature = grpc_base64_decode(cur, 1); + signature = grpc_base64_decode(exec_ctx, cur, 1); if (GRPC_SLICE_IS_EMPTY(signature)) goto error; retrieve_key_and_verify( exec_ctx, @@ -856,9 +870,9 @@ void grpc_jwt_verifier_verify(grpc_exec_ctx *exec_ctx, return; error: - if (header != NULL) jose_header_destroy(header); - if (claims != NULL) grpc_jwt_claims_destroy(claims); - cb(user_data, GRPC_JWT_VERIFIER_BAD_FORMAT, NULL); + if (header != NULL) jose_header_destroy(exec_ctx, header); + if (claims != NULL) grpc_jwt_claims_destroy(exec_ctx, claims); + cb(exec_ctx, user_data, GRPC_JWT_VERIFIER_BAD_FORMAT, NULL); } grpc_jwt_verifier *grpc_jwt_verifier_create( |