diff options
Diffstat (limited to 'src/core/security/credentials.c')
-rw-r--r-- | src/core/security/credentials.c | 315 |
1 files changed, 241 insertions, 74 deletions
diff --git a/src/core/security/credentials.c b/src/core/security/credentials.c index a764413300..5e155d83b9 100644 --- a/src/core/security/credentials.c +++ b/src/core/security/credentials.c @@ -41,12 +41,14 @@ #include "src/core/json/json.h" #include "src/core/httpcli/httpcli.h" #include "src/core/iomgr/iomgr.h" +#include "src/core/surface/api_trace.h" #include "src/core/support/string.h" #include <grpc/support/alloc.h> #include <grpc/support/log.h> #include <grpc/support/string_util.h> #include <grpc/support/sync.h> +#include <grpc/support/thd.h> #include <grpc/support/time.h> /* -- Common. -- */ @@ -54,7 +56,6 @@ 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; }; @@ -66,8 +67,6 @@ grpc_credentials_metadata_request_create(grpc_credentials *creds, gpr_malloc(sizeof(grpc_credentials_metadata_request)); r->creds = grpc_credentials_ref(creds); r->cb = cb; - r->on_simulated_token_fetch_done_closure = - gpr_malloc(sizeof(grpc_iomgr_closure)); r->user_data = user_data; return r; } @@ -75,7 +74,6 @@ grpc_credentials_metadata_request_create(grpc_credentials *creds, static void grpc_credentials_metadata_request_destroy( grpc_credentials_metadata_request *r) { grpc_credentials_unref(r->creds); - gpr_free(r->on_simulated_token_fetch_done_closure); gpr_free(r); } @@ -94,6 +92,7 @@ void grpc_credentials_unref(grpc_credentials *creds) { } void grpc_credentials_release(grpc_credentials *creds) { + GRPC_API_TRACE("grpc_credentials_release(creds=%p)", 1, (creds)); grpc_credentials_unref(creds); } @@ -107,19 +106,17 @@ int grpc_credentials_has_request_metadata_only(grpc_credentials *creds) { return creds->vtable->has_request_metadata_only(creds); } -void grpc_credentials_get_request_metadata(grpc_credentials *creds, - grpc_pollset *pollset, - const char *service_url, - grpc_credentials_metadata_cb cb, - void *user_data) { +void grpc_credentials_get_request_metadata( + grpc_exec_ctx *exec_ctx, grpc_credentials *creds, grpc_pollset *pollset, + const char *service_url, grpc_credentials_metadata_cb cb, void *user_data) { if (creds == NULL || !grpc_credentials_has_request_metadata(creds) || creds->vtable->get_request_metadata == NULL) { if (cb != NULL) { - cb(user_data, NULL, 0, GRPC_CREDENTIALS_OK); + cb(exec_ctx, user_data, NULL, 0, GRPC_CREDENTIALS_OK); } return; } - creds->vtable->get_request_metadata(creds, pollset, service_url, cb, + creds->vtable->get_request_metadata(exec_ctx, creds, pollset, service_url, cb, user_data); } @@ -157,6 +154,7 @@ void grpc_server_credentials_unref(grpc_server_credentials *creds) { } void grpc_server_credentials_release(grpc_server_credentials *creds) { + GRPC_API_TRACE("grpc_server_credentials_release(creds=%p)", 1, (creds)); grpc_server_credentials_unref(creds); } @@ -171,6 +169,11 @@ grpc_security_status grpc_server_credentials_create_security_connector( void grpc_server_credentials_set_auth_metadata_processor( grpc_server_credentials *creds, grpc_auth_metadata_processor processor) { + GRPC_API_TRACE( + "grpc_server_credentials_set_auth_metadata_processor(" + "creds=%p, " + "processor=grpc_auth_metadata_processor { process: %lx, state: %p })", + 3, (creds, (unsigned long)processor.process, processor.state)); if (creds == NULL) return; if (creds->processor.destroy != NULL && creds->processor.state != NULL) { creds->processor.destroy(creds->processor.state); @@ -178,6 +181,48 @@ void grpc_server_credentials_set_auth_metadata_processor( creds->processor = processor; } +static void server_credentials_pointer_arg_destroy(void *p) { + grpc_server_credentials_unref(p); +} + +static void *server_credentials_pointer_arg_copy(void *p) { + return grpc_server_credentials_ref(p); +} + +grpc_arg grpc_server_credentials_to_arg(grpc_server_credentials *p) { + grpc_arg arg; + memset(&arg, 0, sizeof(grpc_arg)); + arg.type = GRPC_ARG_POINTER; + arg.key = GRPC_SERVER_CREDENTIALS_ARG; + arg.value.pointer.p = p; + arg.value.pointer.copy = server_credentials_pointer_arg_copy; + arg.value.pointer.destroy = server_credentials_pointer_arg_destroy; + return arg; +} + +grpc_server_credentials *grpc_server_credentials_from_arg( + const grpc_arg *arg) { + if (strcmp(arg->key, GRPC_SERVER_CREDENTIALS_ARG) != 0) return NULL; + if (arg->type != GRPC_ARG_POINTER) { + gpr_log(GPR_ERROR, "Invalid type %d for arg %s", arg->type, + GRPC_SERVER_CREDENTIALS_ARG); + return NULL; + } + return arg->value.pointer.p; +} + +grpc_server_credentials *grpc_find_server_credentials_in_args( + const grpc_channel_args *args) { + size_t i; + if (args == NULL) return NULL; + for (i = 0; i < args->num_args; i++) { + grpc_server_credentials *p = + grpc_server_credentials_from_arg(&args->args[i]); + if (p != NULL) return p; + } + return NULL; +} + /* -- Ssl credentials. -- */ static void ssl_destruct(grpc_credentials *creds) { @@ -223,7 +268,7 @@ static grpc_security_status ssl_create_security_connector( grpc_security_status status = GRPC_SECURITY_OK; size_t i = 0; const char *overridden_target_name = NULL; - grpc_arg arg; + grpc_arg new_arg; for (i = 0; args && i < args->num_args; i++) { grpc_arg *arg = &args->args[i]; @@ -238,10 +283,10 @@ static grpc_security_status ssl_create_security_connector( if (status != GRPC_SECURITY_OK) { return status; } - arg.type = GRPC_ARG_STRING; - arg.key = GRPC_ARG_HTTP2_SCHEME; - arg.value.string = "https"; - *new_args = grpc_channel_args_copy_and_add(args, &arg, 1); + new_arg.type = GRPC_ARG_STRING; + new_arg.key = GRPC_ARG_HTTP2_SCHEME; + new_arg.value.string = "https"; + *new_args = grpc_channel_args_copy_and_add(args, &new_arg, 1); return status; } @@ -322,6 +367,11 @@ grpc_credentials *grpc_ssl_credentials_create( const char *pem_root_certs, grpc_ssl_pem_key_cert_pair *pem_key_cert_pair, void *reserved) { grpc_ssl_credentials *c = gpr_malloc(sizeof(grpc_ssl_credentials)); + GRPC_API_TRACE( + "grpc_ssl_credentials_create(pem_root_certs=%s, " + "pem_key_cert_pair=%p, " + "reserved=%p)", + 3, (pem_root_certs, pem_key_cert_pair, reserved)); GPR_ASSERT(reserved == NULL); memset(c, 0, sizeof(grpc_ssl_credentials)); c->base.type = GRPC_CREDENTIALS_TYPE_SSL; @@ -336,6 +386,12 @@ grpc_server_credentials *grpc_ssl_server_credentials_create( size_t num_key_cert_pairs, int force_client_auth, void *reserved) { grpc_ssl_server_credentials *c = gpr_malloc(sizeof(grpc_ssl_server_credentials)); + GRPC_API_TRACE( + "grpc_ssl_server_credentials_create(" + "pem_root_certs=%s, pem_key_cert_pairs=%p, num_key_cert_pairs=%lu, " + "force_client_auth=%d, reserved=%p)", + 5, (pem_root_certs, pem_key_cert_pairs, (unsigned long)num_key_cert_pairs, + force_client_auth, reserved)); GPR_ASSERT(reserved == NULL); memset(c, 0, sizeof(grpc_ssl_server_credentials)); c->base.type = GRPC_CREDENTIALS_TYPE_SSL; @@ -374,11 +430,9 @@ static int jwt_has_request_metadata_only(const grpc_credentials *creds) { return 1; } -static void jwt_get_request_metadata(grpc_credentials *creds, - grpc_pollset *pollset, - const char *service_url, - grpc_credentials_metadata_cb cb, - void *user_data) { +static void jwt_get_request_metadata( + grpc_exec_ctx *exec_ctx, grpc_credentials *creds, grpc_pollset *pollset, + const char *service_url, grpc_credentials_metadata_cb cb, void *user_data) { grpc_service_account_jwt_access_credentials *c = (grpc_service_account_jwt_access_credentials *)creds; gpr_timespec refresh_threshold = gpr_time_from_seconds( @@ -422,10 +476,11 @@ static void jwt_get_request_metadata(grpc_credentials *creds, } if (jwt_md != NULL) { - cb(user_data, jwt_md->entries, jwt_md->num_entries, GRPC_CREDENTIALS_OK); + cb(exec_ctx, user_data, jwt_md->entries, jwt_md->num_entries, + GRPC_CREDENTIALS_OK); grpc_credentials_md_store_unref(jwt_md); } else { - cb(user_data, NULL, 0, GRPC_CREDENTIALS_ERROR); + cb(exec_ctx, user_data, NULL, 0, GRPC_CREDENTIALS_ERROR); } } @@ -455,6 +510,14 @@ grpc_service_account_jwt_access_credentials_create_from_auth_json_key( grpc_credentials *grpc_service_account_jwt_access_credentials_create( const char *json_key, gpr_timespec token_lifetime, void *reserved) { + GRPC_API_TRACE( + "grpc_service_account_jwt_access_credentials_create(" + "json_key=%s, " + "token_lifetime=" + "gpr_timespec { tv_sec: %ld, tv_nsec: %d, clock_type: %d }, " + "reserved=%p)", + 5, (json_key, (long)token_lifetime.tv_sec, token_lifetime.tv_nsec, + (int)token_lifetime.clock_type, reserved)); GPR_ASSERT(reserved == NULL); return grpc_service_account_jwt_access_credentials_create_from_auth_json_key( grpc_auth_json_key_create_from_string(json_key), token_lifetime); @@ -571,7 +634,8 @@ end: } static void on_oauth2_token_fetcher_http_response( - void *user_data, const grpc_httpcli_response *response) { + grpc_exec_ctx *exec_ctx, void *user_data, + const grpc_httpcli_response *response) { grpc_credentials_metadata_request *r = (grpc_credentials_metadata_request *)user_data; grpc_oauth2_token_fetcher_credentials *c = @@ -585,19 +649,19 @@ static void on_oauth2_token_fetcher_http_response( if (status == GRPC_CREDENTIALS_OK) { c->token_expiration = gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), token_lifetime); - r->cb(r->user_data, c->access_token_md->entries, + r->cb(exec_ctx, r->user_data, c->access_token_md->entries, c->access_token_md->num_entries, status); } else { c->token_expiration = gpr_inf_past(GPR_CLOCK_REALTIME); - r->cb(r->user_data, NULL, 0, status); + r->cb(exec_ctx, r->user_data, NULL, 0, status); } gpr_mu_unlock(&c->mu); grpc_credentials_metadata_request_destroy(r); } static void oauth2_token_fetcher_get_request_metadata( - grpc_credentials *creds, grpc_pollset *pollset, const char *service_url, - grpc_credentials_metadata_cb cb, void *user_data) { + grpc_exec_ctx *exec_ctx, grpc_credentials *creds, grpc_pollset *pollset, + const char *service_url, grpc_credentials_metadata_cb cb, void *user_data) { grpc_oauth2_token_fetcher_credentials *c = (grpc_oauth2_token_fetcher_credentials *)creds; gpr_timespec refresh_threshold = gpr_time_from_seconds( @@ -615,11 +679,12 @@ static void oauth2_token_fetcher_get_request_metadata( gpr_mu_unlock(&c->mu); } if (cached_access_token_md != NULL) { - cb(user_data, cached_access_token_md->entries, + cb(exec_ctx, user_data, cached_access_token_md->entries, cached_access_token_md->num_entries, GRPC_CREDENTIALS_OK); grpc_credentials_md_store_unref(cached_access_token_md); } else { c->fetch_func( + exec_ctx, grpc_credentials_metadata_request_create(creds, cb, user_data), &c->httpcli_context, pollset, on_oauth2_token_fetcher_http_response, gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), refresh_threshold)); @@ -645,7 +710,7 @@ static grpc_credentials_vtable compute_engine_vtable = { oauth2_token_fetcher_get_request_metadata, NULL}; static void compute_engine_fetch_oauth2( - grpc_credentials_metadata_request *metadata_req, + grpc_exec_ctx *exec_ctx, grpc_credentials_metadata_request *metadata_req, grpc_httpcli_context *httpcli_context, grpc_pollset *pollset, grpc_httpcli_response_cb response_cb, gpr_timespec deadline) { grpc_httpcli_header header = {"Metadata-Flavor", "Google"}; @@ -655,14 +720,16 @@ static void compute_engine_fetch_oauth2( request.path = GRPC_COMPUTE_ENGINE_METADATA_TOKEN_PATH; request.hdr_count = 1; request.hdrs = &header; - grpc_httpcli_get(httpcli_context, pollset, &request, deadline, response_cb, - metadata_req); + grpc_httpcli_get(exec_ctx, httpcli_context, pollset, &request, deadline, + response_cb, metadata_req); } grpc_credentials *grpc_google_compute_engine_credentials_create( void *reserved) { grpc_oauth2_token_fetcher_credentials *c = gpr_malloc(sizeof(grpc_oauth2_token_fetcher_credentials)); + GRPC_API_TRACE("grpc_compute_engine_credentials_create(reserved=%p)", 1, + (reserved)); GPR_ASSERT(reserved == NULL); init_oauth2_token_fetcher(c, compute_engine_fetch_oauth2); c->base.vtable = &compute_engine_vtable; @@ -684,7 +751,7 @@ static grpc_credentials_vtable refresh_token_vtable = { oauth2_token_fetcher_get_request_metadata, NULL}; static void refresh_token_fetch_oauth2( - grpc_credentials_metadata_request *metadata_req, + grpc_exec_ctx *exec_ctx, grpc_credentials_metadata_request *metadata_req, grpc_httpcli_context *httpcli_context, grpc_pollset *pollset, grpc_httpcli_response_cb response_cb, gpr_timespec deadline) { grpc_google_refresh_token_credentials *c = @@ -702,13 +769,12 @@ static void refresh_token_fetch_oauth2( request.hdr_count = 1; request.hdrs = &header; request.handshaker = &grpc_httpcli_ssl; - grpc_httpcli_post(httpcli_context, pollset, &request, body, strlen(body), - deadline, response_cb, metadata_req); + grpc_httpcli_post(exec_ctx, httpcli_context, pollset, &request, body, + strlen(body), deadline, response_cb, metadata_req); gpr_free(body); } -grpc_credentials * -grpc_refresh_token_credentials_create_from_auth_refresh_token( +grpc_credentials *grpc_refresh_token_credentials_create_from_auth_refresh_token( grpc_auth_refresh_token refresh_token) { grpc_google_refresh_token_credentials *c; if (!grpc_auth_refresh_token_is_valid(&refresh_token)) { @@ -725,6 +791,10 @@ grpc_refresh_token_credentials_create_from_auth_refresh_token( grpc_credentials *grpc_google_refresh_token_credentials_create( const char *json_refresh_token, void *reserved) { + GRPC_API_TRACE( + "grpc_refresh_token_credentials_create(json_refresh_token=%s, " + "reserved=%p)", + 2, (json_refresh_token, reserved)); GPR_ASSERT(reserved == NULL); return grpc_refresh_token_credentials_create_from_auth_refresh_token( grpc_auth_refresh_token_create_from_string(json_refresh_token)); @@ -746,31 +816,29 @@ static int md_only_test_has_request_metadata_only( return 1; } -void on_simulated_token_fetch_done(void *user_data, int success) { +static void on_simulated_token_fetch_done(void *user_data) { grpc_credentials_metadata_request *r = (grpc_credentials_metadata_request *)user_data; grpc_md_only_test_credentials *c = (grpc_md_only_test_credentials *)r->creds; - GPR_ASSERT(success); - r->cb(r->user_data, c->md_store->entries, c->md_store->num_entries, + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + r->cb(&exec_ctx, r->user_data, c->md_store->entries, c->md_store->num_entries, GRPC_CREDENTIALS_OK); grpc_credentials_metadata_request_destroy(r); + grpc_exec_ctx_finish(&exec_ctx); } -static void md_only_test_get_request_metadata(grpc_credentials *creds, - grpc_pollset *pollset, - const char *service_url, - grpc_credentials_metadata_cb cb, - void *user_data) { +static void md_only_test_get_request_metadata( + grpc_exec_ctx *exec_ctx, grpc_credentials *creds, grpc_pollset *pollset, + const char *service_url, grpc_credentials_metadata_cb cb, void *user_data) { grpc_md_only_test_credentials *c = (grpc_md_only_test_credentials *)creds; if (c->is_async) { + gpr_thd_id thd_id; grpc_credentials_metadata_request *cb_arg = grpc_credentials_metadata_request_create(creds, cb, user_data); - grpc_iomgr_closure_init(cb_arg->on_simulated_token_fetch_done_closure, - on_simulated_token_fetch_done, cb_arg); - grpc_iomgr_add_callback(cb_arg->on_simulated_token_fetch_done_closure); + gpr_thd_new(&thd_id, on_simulated_token_fetch_done, cb_arg, NULL); } else { - cb(user_data, c->md_store->entries, 1, GRPC_CREDENTIALS_OK); + cb(exec_ctx, user_data, c->md_store->entries, 1, GRPC_CREDENTIALS_OK); } } @@ -810,13 +878,11 @@ static int access_token_has_request_metadata_only( return 1; } -static void access_token_get_request_metadata(grpc_credentials *creds, - grpc_pollset *pollset, - const char *service_url, - grpc_credentials_metadata_cb cb, - void *user_data) { +static void access_token_get_request_metadata( + grpc_exec_ctx *exec_ctx, grpc_credentials *creds, grpc_pollset *pollset, + const char *service_url, grpc_credentials_metadata_cb cb, void *user_data) { grpc_access_token_credentials *c = (grpc_access_token_credentials *)creds; - cb(user_data, c->access_token_md->entries, 1, GRPC_CREDENTIALS_OK); + cb(exec_ctx, user_data, c->access_token_md->entries, 1, GRPC_CREDENTIALS_OK); } static grpc_credentials_vtable access_token_vtable = { @@ -829,6 +895,10 @@ grpc_credentials *grpc_access_token_credentials_create(const char *access_token, grpc_access_token_credentials *c = gpr_malloc(sizeof(grpc_access_token_credentials)); char *token_md_value; + GRPC_API_TRACE( + "grpc_access_token_credentials_create(access_token=%s, " + "reserved=%p)", + 2, (access_token, reserved)); GPR_ASSERT(reserved == NULL); memset(c, 0, sizeof(grpc_access_token_credentials)); c->base.type = GRPC_CREDENTIALS_TYPE_OAUTH2; @@ -961,13 +1031,13 @@ static void composite_md_context_destroy( gpr_free(ctx); } -static void composite_metadata_cb(void *user_data, +static void composite_metadata_cb(grpc_exec_ctx *exec_ctx, void *user_data, grpc_credentials_md *md_elems, size_t num_md, grpc_credentials_status status) { grpc_composite_credentials_metadata_context *ctx = (grpc_composite_credentials_metadata_context *)user_data; if (status != GRPC_CREDENTIALS_OK) { - ctx->cb(ctx->user_data, NULL, 0, status); + ctx->cb(exec_ctx, ctx->user_data, NULL, 0, status); return; } @@ -985,7 +1055,7 @@ static void composite_metadata_cb(void *user_data, grpc_credentials *inner_creds = ctx->composite_creds->inner.creds_array[ctx->creds_index++]; if (grpc_credentials_has_request_metadata(inner_creds)) { - grpc_credentials_get_request_metadata(inner_creds, ctx->pollset, + grpc_credentials_get_request_metadata(exec_ctx, inner_creds, ctx->pollset, ctx->service_url, composite_metadata_cb, ctx); return; @@ -993,20 +1063,18 @@ static void composite_metadata_cb(void *user_data, } /* We're done!. */ - ctx->cb(ctx->user_data, ctx->md_elems->entries, ctx->md_elems->num_entries, - GRPC_CREDENTIALS_OK); + ctx->cb(exec_ctx, ctx->user_data, ctx->md_elems->entries, + ctx->md_elems->num_entries, GRPC_CREDENTIALS_OK); composite_md_context_destroy(ctx); } -static void composite_get_request_metadata(grpc_credentials *creds, - grpc_pollset *pollset, - const char *service_url, - grpc_credentials_metadata_cb cb, - void *user_data) { +static void composite_get_request_metadata( + grpc_exec_ctx *exec_ctx, grpc_credentials *creds, grpc_pollset *pollset, + const char *service_url, grpc_credentials_metadata_cb cb, void *user_data) { grpc_composite_credentials *c = (grpc_composite_credentials *)creds; grpc_composite_credentials_metadata_context *ctx; if (!grpc_credentials_has_request_metadata(creds)) { - cb(user_data, NULL, 0, GRPC_CREDENTIALS_OK); + cb(exec_ctx, user_data, NULL, 0, GRPC_CREDENTIALS_OK); return; } ctx = gpr_malloc(sizeof(grpc_composite_credentials_metadata_context)); @@ -1020,8 +1088,9 @@ static void composite_get_request_metadata(grpc_credentials *creds, while (ctx->creds_index < c->inner.num_creds) { grpc_credentials *inner_creds = c->inner.creds_array[ctx->creds_index++]; if (grpc_credentials_has_request_metadata(inner_creds)) { - grpc_credentials_get_request_metadata(inner_creds, pollset, service_url, - composite_metadata_cb, ctx); + grpc_credentials_get_request_metadata(exec_ctx, inner_creds, pollset, + service_url, composite_metadata_cb, + ctx); return; } } @@ -1066,6 +1135,10 @@ grpc_credentials *grpc_composite_credentials_create(grpc_credentials *creds1, grpc_credentials_array creds1_array; grpc_credentials_array creds2_array; grpc_composite_credentials *c; + GRPC_API_TRACE( + "grpc_composite_credentials_create(creds1=%p, creds2=%p, " + "reserved=%p)", + 3, (creds1, creds2, reserved)); GPR_ASSERT(reserved == NULL); GPR_ASSERT(creds1 != NULL); GPR_ASSERT(creds2 != NULL); @@ -1153,13 +1226,11 @@ static int iam_has_request_metadata_only(const grpc_credentials *creds) { return 1; } -static void iam_get_request_metadata(grpc_credentials *creds, - grpc_pollset *pollset, - const char *service_url, - grpc_credentials_metadata_cb cb, - void *user_data) { +static void iam_get_request_metadata( + grpc_exec_ctx *exec_ctx, grpc_credentials *creds, grpc_pollset *pollset, + const char *service_url, grpc_credentials_metadata_cb cb, void *user_data) { grpc_google_iam_credentials *c = (grpc_google_iam_credentials *)creds; - cb(user_data, c->iam_md->entries, c->iam_md->num_entries, + cb(exec_ctx, user_data, c->iam_md->entries, c->iam_md->num_entries, GRPC_CREDENTIALS_OK); } @@ -1170,6 +1241,10 @@ static grpc_credentials_vtable iam_vtable = { grpc_credentials *grpc_google_iam_credentials_create( const char *token, const char *authority_selector, void *reserved) { grpc_google_iam_credentials *c; + GRPC_API_TRACE( + "grpc_iam_credentials_create(token=%s, authority_selector=%s, " + "reserved=%p)", + 3, (token, authority_selector, reserved)); GPR_ASSERT(reserved == NULL); GPR_ASSERT(token != NULL); GPR_ASSERT(authority_selector != NULL); @@ -1185,3 +1260,95 @@ grpc_credentials *grpc_google_iam_credentials_create( c->iam_md, GRPC_IAM_AUTHORITY_SELECTOR_METADATA_KEY, authority_selector); return &c->base; } + +/* -- Plugin credentials. -- */ + +typedef struct { + void *user_data; + grpc_credentials_metadata_cb cb; +} grpc_metadata_plugin_request; + +static void plugin_destruct(grpc_credentials *creds) { + grpc_plugin_credentials *c = (grpc_plugin_credentials *)creds; + if (c->plugin.state != NULL && c->plugin.destroy != NULL) { + c->plugin.destroy(c->plugin.state); + } +} + +static int plugin_has_request_metadata(const grpc_credentials *creds) { + return 1; +} + +static int plugin_has_request_metadata_only(const grpc_credentials *creds) { + return 1; +} + +static void plugin_md_request_metadata_ready(void *request, + const grpc_metadata *md, + size_t num_md, + grpc_status_code status, + const char *error_details) { + /* called from application code */ + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_metadata_plugin_request *r = (grpc_metadata_plugin_request *)request; + if (status != GRPC_STATUS_OK) { + if (error_details != NULL) { + gpr_log(GPR_ERROR, "Getting metadata from plugin failed with error: %s", + error_details); + } + r->cb(&exec_ctx, r->user_data, NULL, 0, GRPC_CREDENTIALS_ERROR); + } else { + size_t i; + grpc_credentials_md *md_array = NULL; + if (num_md > 0) { + md_array = gpr_malloc(num_md * sizeof(grpc_credentials_md)); + for (i = 0; i < num_md; i++) { + md_array[i].key = gpr_slice_from_copied_string(md[i].key); + md_array[i].value = + gpr_slice_from_copied_buffer(md[i].value, md[i].value_length); + } + } + r->cb(&exec_ctx, r->user_data, md_array, num_md, GRPC_CREDENTIALS_OK); + if (md_array != NULL) { + for (i = 0; i < num_md; i++) { + gpr_slice_unref(md_array[i].key); + gpr_slice_unref(md_array[i].value); + } + gpr_free(md_array); + } + } + gpr_free(r); + grpc_exec_ctx_finish(&exec_ctx); +} + +static void plugin_get_request_metadata( + grpc_exec_ctx *exec_ctx, grpc_credentials *creds, grpc_pollset *pollset, + const char *service_url, grpc_credentials_metadata_cb cb, void *user_data) { + grpc_plugin_credentials *c = (grpc_plugin_credentials *)creds; + if (c->plugin.get_metadata != NULL) { + grpc_metadata_plugin_request *request = gpr_malloc(sizeof(*request)); + memset(request, 0, sizeof(*request)); + request->user_data = user_data; + request->cb = cb; + c->plugin.get_metadata(c->plugin.state, service_url, + plugin_md_request_metadata_ready, request); + } else { + cb(exec_ctx, user_data, NULL, 0, GRPC_CREDENTIALS_OK); + } +} + +static grpc_credentials_vtable plugin_vtable = { + plugin_destruct, plugin_has_request_metadata, + plugin_has_request_metadata_only, plugin_get_request_metadata, NULL}; + +grpc_credentials *grpc_metadata_credentials_create_from_plugin( + grpc_metadata_credentials_plugin plugin, void *reserved) { + grpc_plugin_credentials *c = gpr_malloc(sizeof(*c)); + GPR_ASSERT(reserved == NULL); + memset(c, 0, sizeof(*c)); + c->base.type = GRPC_CREDENTIALS_TYPE_METADATA_PLUGIN; + c->base.vtable = &plugin_vtable; + gpr_ref_init(&c->base.refcount, 1); + c->plugin = plugin; + return &c->base; +} |