diff options
author | Craig Tiller <ctiller@google.com> | 2017-07-17 14:10:44 -0700 |
---|---|---|
committer | Craig Tiller <ctiller@google.com> | 2017-07-17 14:10:44 -0700 |
commit | fa5c6215bec5be0830e429c3321cb2db355a49c0 (patch) | |
tree | 8a164517c994103a0c76a891e167f2ba72328444 /src/core/lib/security/transport/server_auth_filter.c | |
parent | dc3998e7103a0f5e325787da3ab0a32ec402468e (diff) | |
parent | 4708a21c8144f9fed3c90ea8fa153aa20302a1d7 (diff) |
Merge github.com:grpc/grpc into grpc_millis
Diffstat (limited to 'src/core/lib/security/transport/server_auth_filter.c')
-rw-r--r-- | src/core/lib/security/transport/server_auth_filter.c | 178 |
1 files changed, 62 insertions, 116 deletions
diff --git a/src/core/lib/security/transport/server_auth_filter.c b/src/core/lib/security/transport/server_auth_filter.c index 1aca76f9e8..9bf3f0ca0f 100644 --- a/src/core/lib/security/transport/server_auth_filter.c +++ b/src/core/lib/security/transport/server_auth_filter.c @@ -1,33 +1,18 @@ /* * - * Copyright 2015, Google Inc. - * All rights reserved. + * Copyright 2015 gRPC authors. * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. + * http://www.apache.org/licenses/LICENSE-2.0 * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. * */ @@ -42,14 +27,9 @@ #include "src/core/lib/slice/slice_internal.h" typedef struct call_data { - grpc_metadata_batch *recv_initial_metadata; - /* Closure to call when finished with the auth_on_recv hook. */ - grpc_closure *on_done_recv; - /* Receive closures are chained: we inject this closure as the on_done_recv - up-call on transport_op, and remember to call our on_done_recv member after - handling it. */ - grpc_closure auth_on_recv; - grpc_transport_stream_op_batch *transport_op; + grpc_transport_stream_op_batch *recv_initial_metadata_batch; + grpc_closure *original_recv_initial_metadata_ready; + grpc_closure recv_initial_metadata_ready; grpc_metadata_array md; const grpc_metadata *consumed_md; size_t num_consumed_md; @@ -105,125 +85,96 @@ static void on_md_processing_done( grpc_status_code status, const char *error_details) { grpc_call_element *elem = user_data; call_data *calld = elem->call_data; + grpc_transport_stream_op_batch *batch = calld->recv_initial_metadata_batch; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - /* TODO(jboeuf): Implement support for response_md. */ if (response_md != NULL && num_response_md > 0) { gpr_log(GPR_INFO, "response_md in auth metadata processing not supported for now. " "Ignoring..."); } - + grpc_error *error = GRPC_ERROR_NONE; if (status == GRPC_STATUS_OK) { calld->consumed_md = consumed_md; calld->num_consumed_md = num_consumed_md; - /* TODO(ctiller): propagate error */ - GRPC_LOG_IF_ERROR( - "grpc_metadata_batch_filter", - grpc_metadata_batch_filter(&exec_ctx, calld->recv_initial_metadata, - remove_consumed_md, elem, - "Response metadata filtering error")); - for (size_t i = 0; i < calld->md.count; i++) { - grpc_slice_unref_internal(&exec_ctx, calld->md.metadata[i].key); - grpc_slice_unref_internal(&exec_ctx, calld->md.metadata[i].value); - } - grpc_metadata_array_destroy(&calld->md); - grpc_closure_sched(&exec_ctx, calld->on_done_recv, GRPC_ERROR_NONE); + error = grpc_metadata_batch_filter( + &exec_ctx, batch->payload->recv_initial_metadata.recv_initial_metadata, + remove_consumed_md, elem, "Response metadata filtering error"); } else { - for (size_t i = 0; i < calld->md.count; i++) { - grpc_slice_unref_internal(&exec_ctx, calld->md.metadata[i].key); - grpc_slice_unref_internal(&exec_ctx, calld->md.metadata[i].value); - } - grpc_metadata_array_destroy(&calld->md); - error_details = error_details != NULL - ? error_details - : "Authentication metadata processing failed."; - if (calld->transport_op->send_message) { - grpc_byte_stream_destroy( - &exec_ctx, calld->transport_op->payload->send_message.send_message); - calld->transport_op->payload->send_message.send_message = NULL; + if (error_details == NULL) { + error_details = "Authentication metadata processing failed."; } - grpc_closure_sched( - &exec_ctx, calld->on_done_recv, + error = grpc_error_set_int(GRPC_ERROR_CREATE_FROM_COPIED_STRING(error_details), - GRPC_ERROR_INT_GRPC_STATUS, status)); + GRPC_ERROR_INT_GRPC_STATUS, status); } - + for (size_t i = 0; i < calld->md.count; i++) { + grpc_slice_unref_internal(&exec_ctx, calld->md.metadata[i].key); + grpc_slice_unref_internal(&exec_ctx, calld->md.metadata[i].value); + } + grpc_metadata_array_destroy(&calld->md); + GRPC_CLOSURE_SCHED(&exec_ctx, calld->original_recv_initial_metadata_ready, + error); grpc_exec_ctx_finish(&exec_ctx); } -static void auth_on_recv(grpc_exec_ctx *exec_ctx, void *user_data, - grpc_error *error) { - grpc_call_element *elem = user_data; - call_data *calld = elem->call_data; +static void recv_initial_metadata_ready(grpc_exec_ctx *exec_ctx, void *arg, + grpc_error *error) { + grpc_call_element *elem = arg; channel_data *chand = elem->channel_data; + call_data *calld = elem->call_data; + grpc_transport_stream_op_batch *batch = calld->recv_initial_metadata_batch; if (error == GRPC_ERROR_NONE) { if (chand->creds != NULL && chand->creds->processor.process != NULL) { - calld->md = metadata_batch_to_md_array(calld->recv_initial_metadata); + calld->md = metadata_batch_to_md_array( + batch->payload->recv_initial_metadata.recv_initial_metadata); chand->creds->processor.process( chand->creds->processor.state, calld->auth_context, calld->md.metadata, calld->md.count, on_md_processing_done, elem); return; } } - grpc_closure_sched(exec_ctx, calld->on_done_recv, GRPC_ERROR_REF(error)); + GRPC_CLOSURE_RUN(exec_ctx, calld->original_recv_initial_metadata_ready, + GRPC_ERROR_REF(error)); } -static void set_recv_ops_md_callbacks(grpc_call_element *elem, - grpc_transport_stream_op_batch *op) { +static void auth_start_transport_stream_op_batch( + grpc_exec_ctx *exec_ctx, grpc_call_element *elem, + grpc_transport_stream_op_batch *batch) { call_data *calld = elem->call_data; - - if (op->recv_initial_metadata) { - /* substitute our callback for the higher callback */ - calld->recv_initial_metadata = - op->payload->recv_initial_metadata.recv_initial_metadata; - calld->on_done_recv = - op->payload->recv_initial_metadata.recv_initial_metadata_ready; - op->payload->recv_initial_metadata.recv_initial_metadata_ready = - &calld->auth_on_recv; - calld->transport_op = op; + if (batch->recv_initial_metadata) { + // Inject our callback. + calld->recv_initial_metadata_batch = batch; + calld->original_recv_initial_metadata_ready = + batch->payload->recv_initial_metadata.recv_initial_metadata_ready; + batch->payload->recv_initial_metadata.recv_initial_metadata_ready = + &calld->recv_initial_metadata_ready; } -} - -/* Called either: - - in response to an API call (or similar) from above, to send something - - a network event (or similar) from below, to receive something - op contains type and call direction information, in addition to the data - that is being sent or received. */ -static void auth_start_transport_op(grpc_exec_ctx *exec_ctx, - grpc_call_element *elem, - grpc_transport_stream_op_batch *op) { - set_recv_ops_md_callbacks(elem, op); - grpc_call_next_op(exec_ctx, elem, op); + grpc_call_next_op(exec_ctx, elem, batch); } /* Constructor for call_data */ static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, const grpc_call_element_args *args) { - /* grab pointers to our data from the call element */ call_data *calld = elem->call_data; channel_data *chand = elem->channel_data; - grpc_server_security_context *server_ctx = NULL; - - /* initialize members */ - memset(calld, 0, sizeof(*calld)); - grpc_closure_init(&calld->auth_on_recv, auth_on_recv, elem, + GRPC_CLOSURE_INIT(&calld->recv_initial_metadata_ready, + recv_initial_metadata_ready, elem, grpc_schedule_on_exec_ctx); - + // Create server security context. Set its auth context from channel + // data and save it in the call context. + grpc_server_security_context *server_ctx = + grpc_server_security_context_create(); + server_ctx->auth_context = grpc_auth_context_create(chand->auth_context); + calld->auth_context = server_ctx->auth_context; if (args->context[GRPC_CONTEXT_SECURITY].value != NULL) { args->context[GRPC_CONTEXT_SECURITY].destroy( args->context[GRPC_CONTEXT_SECURITY].value); } - - server_ctx = grpc_server_security_context_create(); - server_ctx->auth_context = grpc_auth_context_create(chand->auth_context); - calld->auth_context = server_ctx->auth_context; - args->context[GRPC_CONTEXT_SECURITY].value = server_ctx; args->context[GRPC_CONTEXT_SECURITY].destroy = grpc_server_security_context_destroy; - return GRPC_ERROR_NONE; } @@ -236,19 +187,15 @@ static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, static grpc_error *init_channel_elem(grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, grpc_channel_element_args *args) { + GPR_ASSERT(!args->is_last); + channel_data *chand = elem->channel_data; grpc_auth_context *auth_context = grpc_find_auth_context_in_args(args->channel_args); - grpc_server_credentials *creds = - grpc_find_server_credentials_in_args(args->channel_args); - /* grab pointers to our data from the channel element */ - channel_data *chand = elem->channel_data; - - GPR_ASSERT(!args->is_last); GPR_ASSERT(auth_context != NULL); - - /* initialize members */ chand->auth_context = GRPC_AUTH_CONTEXT_REF(auth_context, "server_auth_filter"); + grpc_server_credentials *creds = + grpc_find_server_credentials_in_args(args->channel_args); chand->creds = grpc_server_credentials_ref(creds); return GRPC_ERROR_NONE; } @@ -256,14 +203,13 @@ static grpc_error *init_channel_elem(grpc_exec_ctx *exec_ctx, /* Destructor for channel data */ static void destroy_channel_elem(grpc_exec_ctx *exec_ctx, grpc_channel_element *elem) { - /* grab pointers to our data from the channel element */ channel_data *chand = elem->channel_data; GRPC_AUTH_CONTEXT_UNREF(chand->auth_context, "server_auth_filter"); grpc_server_credentials_unref(exec_ctx, chand->creds); } const grpc_channel_filter grpc_server_auth_filter = { - auth_start_transport_op, + auth_start_transport_stream_op_batch, grpc_channel_next_op, sizeof(call_data), init_call_elem, |