diff options
Diffstat (limited to 'src/core/lib/security/transport/client_auth_filter.c')
-rw-r--r-- | src/core/lib/security/transport/client_auth_filter.c | 115 |
1 files changed, 45 insertions, 70 deletions
diff --git a/src/core/lib/security/transport/client_auth_filter.c b/src/core/lib/security/transport/client_auth_filter.c index cf056e8008..b7f6fd23e3 100644 --- a/src/core/lib/security/transport/client_auth_filter.c +++ b/src/core/lib/security/transport/client_auth_filter.c @@ -45,7 +45,6 @@ #include "src/core/lib/security/credentials/credentials.h" #include "src/core/lib/security/transport/security_connector.h" #include "src/core/lib/slice/slice_internal.h" -#include "src/core/lib/slice/slice_string_helpers.h" #include "src/core/lib/support/string.h" #include "src/core/lib/surface/call.h" #include "src/core/lib/transport/static_metadata.h" @@ -55,10 +54,8 @@ /* We can have a per-call credentials. */ typedef struct { grpc_call_credentials *creds; - bool have_host; - bool have_method; - grpc_slice host; - grpc_slice method; + grpc_mdstr *host; + grpc_mdstr *method; /* pollset{_set} bound to this call; if we need to make external network requests, they should be done under a pollset added to this pollset_set so that work can progress when this call wants work to progress @@ -92,12 +89,14 @@ static void reset_auth_metadata_context( auth_md_context->channel_auth_context = NULL; } -static void add_error(grpc_error **combined, grpc_error *error) { - if (error == GRPC_ERROR_NONE) return; - if (*combined == GRPC_ERROR_NONE) { - *combined = GRPC_ERROR_CREATE("Client auth metadata plugin error"); - } - *combined = grpc_error_add_child(*combined, error); +static void bubble_up_error(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, + grpc_status_code status, const char *error_msg) { + call_data *calld = elem->call_data; + gpr_log(GPR_ERROR, "Client side authentication failure: %s", error_msg); + grpc_slice error_slice = grpc_slice_from_copied_string(error_msg); + grpc_transport_stream_op_add_close(exec_ctx, &calld->op, status, + &error_slice); + grpc_call_next_op(exec_ctx, elem, &calld->op); } static void on_credentials_metadata(grpc_exec_ctx *exec_ctx, void *user_data, @@ -111,37 +110,30 @@ static void on_credentials_metadata(grpc_exec_ctx *exec_ctx, void *user_data, grpc_metadata_batch *mdb; size_t i; reset_auth_metadata_context(&calld->auth_md_context); - grpc_error *error = GRPC_ERROR_NONE; if (status != GRPC_CREDENTIALS_OK) { - error = grpc_error_set_int( - GRPC_ERROR_CREATE(error_details != NULL && strlen(error_details) > 0 - ? error_details - : "Credentials failed to get metadata."), - GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAUTHENTICATED); - } else { - GPR_ASSERT(num_md <= MAX_CREDENTIALS_METADATA_COUNT); - GPR_ASSERT(op->send_initial_metadata != NULL); - mdb = op->send_initial_metadata; - for (i = 0; i < num_md; i++) { - add_error(&error, - grpc_metadata_batch_add_tail( - exec_ctx, mdb, &calld->md_links[i], - grpc_mdelem_from_slices( - exec_ctx, grpc_slice_ref_internal(md_elems[i].key), - grpc_slice_ref_internal(md_elems[i].value)))); - } + bubble_up_error(exec_ctx, elem, GRPC_STATUS_UNAUTHENTICATED, + (error_details != NULL && strlen(error_details) > 0) + ? error_details + : "Credentials failed to get metadata."); + return; } - if (error == GRPC_ERROR_NONE) { - grpc_call_next_op(exec_ctx, elem, op); - } else { - grpc_transport_stream_op_finish_with_failure(exec_ctx, op, error); + GPR_ASSERT(num_md <= MAX_CREDENTIALS_METADATA_COUNT); + GPR_ASSERT(op->send_initial_metadata != NULL); + mdb = op->send_initial_metadata; + for (i = 0; i < num_md; i++) { + grpc_metadata_batch_add_tail( + mdb, &calld->md_links[i], + grpc_mdelem_from_slices(exec_ctx, + grpc_slice_ref_internal(md_elems[i].key), + grpc_slice_ref_internal(md_elems[i].value))); } + grpc_call_next_op(exec_ctx, elem, op); } void build_auth_metadata_context(grpc_security_connector *sc, grpc_auth_context *auth_context, call_data *calld) { - char *service = grpc_slice_to_c_string(calld->method); + char *service = gpr_strdup(grpc_mdstr_as_c_string(calld->method)); char *last_slash = strrchr(service, '/'); char *method_name = NULL; char *service_url = NULL; @@ -157,15 +149,14 @@ void build_auth_metadata_context(grpc_security_connector *sc, method_name = gpr_strdup(last_slash + 1); } if (method_name == NULL) method_name = gpr_strdup(""); - char *host = grpc_slice_to_c_string(calld->host); gpr_asprintf(&service_url, "%s://%s%s", - sc->url_scheme == NULL ? "" : sc->url_scheme, host, service); + sc->url_scheme == NULL ? "" : sc->url_scheme, + grpc_mdstr_as_c_string(calld->host), service); calld->auth_md_context.service_url = service_url; calld->auth_md_context.method_name = method_name; calld->auth_md_context.channel_auth_context = GRPC_AUTH_CONTEXT_REF(auth_context, "grpc_auth_metadata_context"); gpr_free(service); - gpr_free(host); } static void send_security_metadata(grpc_exec_ctx *exec_ctx, @@ -189,12 +180,8 @@ static void send_security_metadata(grpc_exec_ctx *exec_ctx, calld->creds = grpc_composite_call_credentials_create(channel_call_creds, ctx->creds, NULL); if (calld->creds == NULL) { - grpc_transport_stream_op_finish_with_failure( - exec_ctx, op, - grpc_error_set_int( - GRPC_ERROR_CREATE( - "Incompatible credentials set on channel and call."), - GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAUTHENTICATED)); + bubble_up_error(exec_ctx, elem, GRPC_STATUS_UNAUTHENTICATED, + "Incompatible credentials set on channel and call."); return; } } else { @@ -220,14 +207,9 @@ static void on_host_checked(grpc_exec_ctx *exec_ctx, void *user_data, send_security_metadata(exec_ctx, elem, &calld->op); } else { char *error_msg; - char *host = grpc_slice_to_c_string(calld->host); gpr_asprintf(&error_msg, "Invalid host %s set in :authority metadata.", - host); - gpr_free(host); - grpc_call_element_signal_error( - exec_ctx, elem, grpc_error_set_int(GRPC_ERROR_CREATE(error_msg), - GRPC_ERROR_INT_GRPC_STATUS, - GRPC_STATUS_UNAUTHENTICATED)); + grpc_mdstr_as_c_string(calld->host)); + bubble_up_error(exec_ctx, elem, GRPC_STATUS_UNAUTHENTICATED, error_msg); gpr_free(error_msg); } } @@ -265,30 +247,23 @@ static void auth_start_transport_op(grpc_exec_ctx *exec_ctx, if (op->send_initial_metadata != NULL) { for (l = op->send_initial_metadata->list.head; l != NULL; l = l->next) { - grpc_mdelem md = l->md; + grpc_mdelem *md = l->md; /* Pointer comparison is OK for md_elems created from the same context. */ - if (grpc_slice_eq(GRPC_MDKEY(md), GRPC_MDSTR_AUTHORITY)) { - if (calld->have_host) { - grpc_slice_unref_internal(exec_ctx, calld->host); - } - calld->host = grpc_slice_ref_internal(GRPC_MDVALUE(md)); - calld->have_host = true; - } else if (grpc_slice_eq(GRPC_MDKEY(md), GRPC_MDSTR_PATH)) { - if (calld->have_method) { - grpc_slice_unref_internal(exec_ctx, calld->method); - } - calld->method = grpc_slice_ref_internal(GRPC_MDVALUE(md)); - calld->have_method = true; + if (md->key == GRPC_MDSTR_AUTHORITY) { + if (calld->host != NULL) GRPC_MDSTR_UNREF(exec_ctx, calld->host); + calld->host = GRPC_MDSTR_REF(md->value); + } else if (md->key == GRPC_MDSTR_PATH) { + if (calld->method != NULL) GRPC_MDSTR_UNREF(exec_ctx, calld->method); + calld->method = GRPC_MDSTR_REF(md->value); } } - if (calld->have_host) { - char *call_host = grpc_slice_to_c_string(calld->host); + if (calld->host != NULL) { + const char *call_host = grpc_mdstr_as_c_string(calld->host); calld->op = *op; /* Copy op (originates from the caller's stack). */ grpc_channel_security_connector_check_call_host( exec_ctx, chand->security_connector, call_host, chand->auth_context, on_host_checked, elem); - gpr_free(call_host); GPR_TIMER_END("auth_start_transport_op", 0); return; /* early exit */ } @@ -321,11 +296,11 @@ static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, void *ignored) { call_data *calld = elem->call_data; grpc_call_credentials_unref(exec_ctx, calld->creds); - if (calld->have_host) { - grpc_slice_unref_internal(exec_ctx, calld->host); + if (calld->host != NULL) { + GRPC_MDSTR_UNREF(exec_ctx, calld->host); } - if (calld->have_method) { - grpc_slice_unref_internal(exec_ctx, calld->method); + if (calld->method != NULL) { + GRPC_MDSTR_UNREF(exec_ctx, calld->method); } reset_auth_metadata_context(&calld->auth_md_context); } |