blob: 2a1bf4d4e3484e271978974ab28168b06f29a68d [file] [log] [blame]
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001/*
2 *
Craig Tiller6169d5f2016-03-31 07:46:18 -07003 * Copyright 2015, Google Inc.
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08004 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above
13 * copyright notice, this list of conditions and the following disclaimer
14 * in the documentation and/or other materials provided with the
15 * distribution.
16 * * Neither the name of Google Inc. nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 */
33
Julien Boeuf8ca294e2016-05-02 14:56:30 -070034#include "src/core/lib/security/transport/auth_filters.h"
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080035
36#include <string.h>
37
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080038#include <grpc/support/alloc.h>
39#include <grpc/support/log.h>
Masood Malekghassemi701af602015-06-03 15:01:17 -070040#include <grpc/support/string_util.h>
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080041
Craig Tiller9533d042016-03-25 17:11:06 -070042#include "src/core/lib/channel/channel_stack.h"
Julien Boeuf8ca294e2016-05-02 14:56:30 -070043#include "src/core/lib/security/context/security_context.h"
44#include "src/core/lib/security/credentials/credentials.h"
45#include "src/core/lib/security/transport/security_connector.h"
Craig Tiller9533d042016-03-25 17:11:06 -070046#include "src/core/lib/support/string.h"
47#include "src/core/lib/surface/call.h"
48#include "src/core/lib/transport/static_metadata.h"
Julien Boeuf54b21922015-02-04 16:39:35 -080049
Craig Tiller9c9d4e02015-04-20 09:03:29 -070050#define MAX_CREDENTIALS_METADATA_COUNT 4
Craig Tiller6902ad22015-04-16 08:01:49 -070051
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080052/* We can have a per-call credentials. */
Craig Tillera82950e2015-09-22 12:33:20 -070053typedef struct {
Julien Boeuf441176d2015-10-09 21:14:07 -070054 grpc_call_credentials *creds;
Julien Boeuf54b21922015-02-04 16:39:35 -080055 grpc_mdstr *host;
Julien Boeuff47a5cb2015-02-18 12:24:08 -080056 grpc_mdstr *method;
David Garcia Quintasf72eb972016-05-03 18:28:09 -070057 /* pollset{_set} bound to this call; if we need to make external
David Garcia Quintas4afce7e2016-04-18 16:25:17 -070058 network requests, they should be done under a pollset added to this
59 pollset_set so that work can progress when this call wants work to progress
60 */
David Garcia Quintas2a50dfe2016-05-31 15:09:12 -070061 grpc_polling_entity *pollent;
Craig Tillerb7959a02015-06-25 08:50:54 -070062 grpc_transport_stream_op op;
Craig Tiller7536af02015-12-22 13:49:30 -080063 uint8_t security_context_set;
Craig Tiller9c9d4e02015-04-20 09:03:29 -070064 grpc_linked_mdelem md_links[MAX_CREDENTIALS_METADATA_COUNT];
Julien Boeuf3c957e62015-11-18 21:33:58 -080065 grpc_auth_metadata_context auth_md_context;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080066} call_data;
67
68/* We can have a per-channel credentials. */
Craig Tillera82950e2015-09-22 12:33:20 -070069typedef struct {
Julien Boeuf7d1d9ca2015-04-17 14:38:48 -070070 grpc_channel_security_connector *security_connector;
Julien Boeuf366f42c2015-12-16 22:05:46 -080071 grpc_auth_context *auth_context;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080072} channel_data;
73
Julien Boeuf3c957e62015-11-18 21:33:58 -080074static void reset_auth_metadata_context(
75 grpc_auth_metadata_context *auth_md_context) {
76 if (auth_md_context->service_url != NULL) {
77 gpr_free((char *)auth_md_context->service_url);
78 auth_md_context->service_url = NULL;
Craig Tillera82950e2015-09-22 12:33:20 -070079 }
Julien Boeuf3c957e62015-11-18 21:33:58 -080080 if (auth_md_context->method_name != NULL) {
81 gpr_free((char *)auth_md_context->method_name);
82 auth_md_context->method_name = NULL;
83 }
84 GRPC_AUTH_CONTEXT_UNREF(
85 (grpc_auth_context *)auth_md_context->channel_auth_context,
86 "grpc_auth_metadata_context");
87 auth_md_context->channel_auth_context = NULL;
Julien Boeuf1928d492015-09-15 15:20:11 -070088}
89
Craig Tillera82950e2015-09-22 12:33:20 -070090static void bubble_up_error(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
91 grpc_status_code status, const char *error_msg) {
Julien Boeuf9f218dd2015-04-23 10:24:02 -070092 call_data *calld = elem->call_data;
Craig Tillera82950e2015-09-22 12:33:20 -070093 gpr_log(GPR_ERROR, "Client side authentication failure: %s", error_msg);
Julien Boeufc49464d2016-05-18 23:11:50 -070094 gpr_slice error_slice = gpr_slice_from_copied_string(error_msg);
95 grpc_transport_stream_op_add_close(&calld->op, status, &error_slice);
Craig Tillera82950e2015-09-22 12:33:20 -070096 grpc_call_next_op(exec_ctx, elem, &calld->op);
Julien Boeuf9f218dd2015-04-23 10:24:02 -070097}
98
Craig Tillera82950e2015-09-22 12:33:20 -070099static void on_credentials_metadata(grpc_exec_ctx *exec_ctx, void *user_data,
100 grpc_credentials_md *md_elems,
101 size_t num_md,
Julien Boeuf2e3c9ad2016-01-19 17:14:38 -0800102 grpc_credentials_status status,
103 const char *error_details) {
Craig Tillera82950e2015-09-22 12:33:20 -0700104 grpc_call_element *elem = (grpc_call_element *)user_data;
Craig Tiller6902ad22015-04-16 08:01:49 -0700105 call_data *calld = elem->call_data;
Craig Tillerb7959a02015-06-25 08:50:54 -0700106 grpc_transport_stream_op *op = &calld->op;
Craig Tiller6e84aba2015-04-23 15:08:17 -0700107 grpc_metadata_batch *mdb;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800108 size_t i;
Julien Boeuf3c957e62015-11-18 21:33:58 -0800109 reset_auth_metadata_context(&calld->auth_md_context);
Craig Tillera82950e2015-09-22 12:33:20 -0700110 if (status != GRPC_CREDENTIALS_OK) {
111 bubble_up_error(exec_ctx, elem, GRPC_STATUS_UNAUTHENTICATED,
Julien Boeufc49464d2016-05-18 23:11:50 -0700112 (error_details != NULL && strlen(error_details) > 0)
113 ? error_details
114 : "Credentials failed to get metadata.");
Craig Tillera82950e2015-09-22 12:33:20 -0700115 return;
116 }
117 GPR_ASSERT(num_md <= MAX_CREDENTIALS_METADATA_COUNT);
Craig Tiller0581d122015-11-02 14:09:40 -0800118 GPR_ASSERT(op->send_initial_metadata != NULL);
119 mdb = op->send_initial_metadata;
Craig Tillera82950e2015-09-22 12:33:20 -0700120 for (i = 0; i < num_md; i++) {
121 grpc_metadata_batch_add_tail(
122 mdb, &calld->md_links[i],
Craig Tillerb2b42612015-11-20 12:02:17 -0800123 grpc_mdelem_from_slices(gpr_slice_ref(md_elems[i].key),
Craig Tillera82950e2015-09-22 12:33:20 -0700124 gpr_slice_ref(md_elems[i].value)));
125 }
126 grpc_call_next_op(exec_ctx, elem, op);
Julien Boeuf54b21922015-02-04 16:39:35 -0800127}
128
Julien Boeuf3c957e62015-11-18 21:33:58 -0800129void build_auth_metadata_context(grpc_security_connector *sc,
Julien Boeuf366f42c2015-12-16 22:05:46 -0800130 grpc_auth_context *auth_context,
Julien Boeuf3c957e62015-11-18 21:33:58 -0800131 call_data *calld) {
Craig Tillera82950e2015-09-22 12:33:20 -0700132 char *service = gpr_strdup(grpc_mdstr_as_c_string(calld->method));
133 char *last_slash = strrchr(service, '/');
Julien Boeuf3c957e62015-11-18 21:33:58 -0800134 char *method_name = NULL;
135 char *service_url = NULL;
136 reset_auth_metadata_context(&calld->auth_md_context);
Craig Tillera82950e2015-09-22 12:33:20 -0700137 if (last_slash == NULL) {
138 gpr_log(GPR_ERROR, "No '/' found in fully qualified method name");
139 service[0] = '\0';
140 } else if (last_slash == service) {
141 /* No service part in fully qualified method name: will just be "/". */
142 service[1] = '\0';
143 } else {
144 *last_slash = '\0';
Julien Boeuf3c957e62015-11-18 21:33:58 -0800145 method_name = gpr_strdup(last_slash + 1);
Craig Tillera82950e2015-09-22 12:33:20 -0700146 }
Julien Boeufeb029c92015-11-25 13:47:56 -0800147 if (method_name == NULL) method_name = gpr_strdup("");
Julien Boeuf3c957e62015-11-18 21:33:58 -0800148 gpr_asprintf(&service_url, "%s://%s%s",
149 sc->url_scheme == NULL ? "" : sc->url_scheme,
Craig Tillera82950e2015-09-22 12:33:20 -0700150 grpc_mdstr_as_c_string(calld->host), service);
Julien Boeuf3c957e62015-11-18 21:33:58 -0800151 calld->auth_md_context.service_url = service_url;
152 calld->auth_md_context.method_name = method_name;
Nicolas "Pixel" Noblef9c58f32015-12-01 22:40:44 +0100153 calld->auth_md_context.channel_auth_context =
Julien Boeuf366f42c2015-12-16 22:05:46 -0800154 GRPC_AUTH_CONTEXT_REF(auth_context, "grpc_auth_metadata_context");
Craig Tillera82950e2015-09-22 12:33:20 -0700155 gpr_free(service);
Craig Tiller45724b32015-09-22 10:42:19 -0700156}
157
Craig Tillera82950e2015-09-22 12:33:20 -0700158static void send_security_metadata(grpc_exec_ctx *exec_ctx,
159 grpc_call_element *elem,
160 grpc_transport_stream_op *op) {
Craig Tiller45724b32015-09-22 10:42:19 -0700161 call_data *calld = elem->call_data;
162 channel_data *chand = elem->channel_data;
Craig Tillera82950e2015-09-22 12:33:20 -0700163 grpc_client_security_context *ctx =
164 (grpc_client_security_context *)op->context[GRPC_CONTEXT_SECURITY].value;
Julien Boeuf441176d2015-10-09 21:14:07 -0700165 grpc_call_credentials *channel_call_creds =
Craig Tillera82950e2015-09-22 12:33:20 -0700166 chand->security_connector->request_metadata_creds;
Julien Boeuf441176d2015-10-09 21:14:07 -0700167 int call_creds_has_md = (ctx != NULL) && (ctx->creds != NULL);
Craig Tiller45724b32015-09-22 10:42:19 -0700168
Julien Boeuf441176d2015-10-09 21:14:07 -0700169 if (channel_call_creds == NULL && !call_creds_has_md) {
Craig Tillera82950e2015-09-22 12:33:20 -0700170 /* Skip sending metadata altogether. */
171 grpc_call_next_op(exec_ctx, elem, op);
172 return;
173 }
174
Julien Boeuf441176d2015-10-09 21:14:07 -0700175 if (channel_call_creds != NULL && call_creds_has_md) {
176 calld->creds = grpc_composite_call_credentials_create(channel_call_creds,
177 ctx->creds, NULL);
Craig Tillera82950e2015-09-22 12:33:20 -0700178 if (calld->creds == NULL) {
Julien Boeuff0ae3e32016-07-06 11:23:51 -0700179 bubble_up_error(exec_ctx, elem, GRPC_STATUS_UNAUTHENTICATED,
Craig Tillera82950e2015-09-22 12:33:20 -0700180 "Incompatible credentials set on channel and call.");
Craig Tiller45724b32015-09-22 10:42:19 -0700181 return;
182 }
Craig Tillera82950e2015-09-22 12:33:20 -0700183 } else {
Julien Boeuf441176d2015-10-09 21:14:07 -0700184 calld->creds = grpc_call_credentials_ref(
185 call_creds_has_md ? ctx->creds : channel_call_creds);
Craig Tillera82950e2015-09-22 12:33:20 -0700186 }
Craig Tiller45724b32015-09-22 10:42:19 -0700187
Julien Boeuf366f42c2015-12-16 22:05:46 -0800188 build_auth_metadata_context(&chand->security_connector->base,
189 chand->auth_context, calld);
Craig Tillera82950e2015-09-22 12:33:20 -0700190 calld->op = *op; /* Copy op (originates from the caller's stack). */
David Garcia Quintas2a50dfe2016-05-31 15:09:12 -0700191 GPR_ASSERT(calld->pollent != NULL);
Julien Boeuf3c957e62015-11-18 21:33:58 -0800192 grpc_call_credentials_get_request_metadata(
David Garcia Quintas2a50dfe2016-05-31 15:09:12 -0700193 exec_ctx, calld->creds, calld->pollent, calld->auth_md_context,
Julien Boeuf3c957e62015-11-18 21:33:58 -0800194 on_credentials_metadata, elem);
Craig Tiller45724b32015-09-22 10:42:19 -0700195}
196
Craig Tillera82950e2015-09-22 12:33:20 -0700197static void on_host_checked(grpc_exec_ctx *exec_ctx, void *user_data,
198 grpc_security_status status) {
199 grpc_call_element *elem = (grpc_call_element *)user_data;
Julien Boeuf54b21922015-02-04 16:39:35 -0800200 call_data *calld = elem->call_data;
201
Craig Tillera82950e2015-09-22 12:33:20 -0700202 if (status == GRPC_SECURITY_OK) {
203 send_security_metadata(exec_ctx, elem, &calld->op);
204 } else {
205 char *error_msg;
206 gpr_asprintf(&error_msg, "Invalid host %s set in :authority metadata.",
207 grpc_mdstr_as_c_string(calld->host));
Julien Boeuff0ae3e32016-07-06 11:23:51 -0700208 bubble_up_error(exec_ctx, elem, GRPC_STATUS_UNAUTHENTICATED, error_msg);
Craig Tillera82950e2015-09-22 12:33:20 -0700209 gpr_free(error_msg);
210 }
Julien Boeuf54b21922015-02-04 16:39:35 -0800211}
212
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800213/* Called either:
214 - in response to an API call (or similar) from above, to send something
215 - a network event (or similar) from below, to receive something
216 op contains type and call direction information, in addition to the data
217 that is being sent or received. */
Craig Tillera82950e2015-09-22 12:33:20 -0700218static void auth_start_transport_op(grpc_exec_ctx *exec_ctx,
219 grpc_call_element *elem,
220 grpc_transport_stream_op *op) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800221 /* grab pointers to our data from the call element */
222 call_data *calld = elem->call_data;
Julien Boeuf9f218dd2015-04-23 10:24:02 -0700223 channel_data *chand = elem->channel_data;
Craig Tiller6902ad22015-04-16 08:01:49 -0700224 grpc_linked_mdelem *l;
Craig Tillerd6c98df2015-08-18 09:33:44 -0700225 grpc_client_security_context *sec_ctx = NULL;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800226
Craig Tillerf0f70a82016-06-23 13:55:06 -0700227 if (calld->security_context_set == 0 && op->cancel_error == GRPC_ERROR_NONE) {
Craig Tillera82950e2015-09-22 12:33:20 -0700228 calld->security_context_set = 1;
229 GPR_ASSERT(op->context);
230 if (op->context[GRPC_CONTEXT_SECURITY].value == NULL) {
231 op->context[GRPC_CONTEXT_SECURITY].value =
232 grpc_client_security_context_create();
233 op->context[GRPC_CONTEXT_SECURITY].destroy =
234 grpc_client_security_context_destroy;
yang-gd8c466e2015-06-30 09:50:53 -0700235 }
Craig Tillera82950e2015-09-22 12:33:20 -0700236 sec_ctx = op->context[GRPC_CONTEXT_SECURITY].value;
237 GRPC_AUTH_CONTEXT_UNREF(sec_ctx->auth_context, "client auth filter");
Craig Tillerbe52c6e2016-01-04 15:35:26 -0800238 sec_ctx->auth_context =
239 GRPC_AUTH_CONTEXT_REF(chand->auth_context, "client_auth_filter");
Craig Tillera82950e2015-09-22 12:33:20 -0700240 }
Julien Boeuf84d964a2015-04-29 11:31:06 -0700241
Craig Tiller0581d122015-11-02 14:09:40 -0800242 if (op->send_initial_metadata != NULL) {
243 for (l = op->send_initial_metadata->list.head; l != NULL; l = l->next) {
244 grpc_mdelem *md = l->md;
245 /* Pointer comparison is OK for md_elems created from the same context.
246 */
Craig Tillered43f512015-11-19 08:53:23 -0800247 if (md->key == GRPC_MDSTR_AUTHORITY) {
Craig Tiller0581d122015-11-02 14:09:40 -0800248 if (calld->host != NULL) GRPC_MDSTR_UNREF(calld->host);
249 calld->host = GRPC_MDSTR_REF(md->value);
Craig Tillered43f512015-11-19 08:53:23 -0800250 } else if (md->key == GRPC_MDSTR_PATH) {
Craig Tiller0581d122015-11-02 14:09:40 -0800251 if (calld->method != NULL) GRPC_MDSTR_UNREF(calld->method);
252 calld->method = GRPC_MDSTR_REF(md->value);
Craig Tillera82950e2015-09-22 12:33:20 -0700253 }
Craig Tiller45724b32015-09-22 10:42:19 -0700254 }
Craig Tiller0581d122015-11-02 14:09:40 -0800255 if (calld->host != NULL) {
Craig Tiller0581d122015-11-02 14:09:40 -0800256 const char *call_host = grpc_mdstr_as_c_string(calld->host);
257 calld->op = *op; /* Copy op (originates from the caller's stack). */
Julien Boeuf1d9ac662015-12-17 21:35:47 -0800258 grpc_channel_security_connector_check_call_host(
259 exec_ctx, chand->security_connector, call_host, chand->auth_context,
260 on_host_checked, elem);
261 return; /* early exit */
Craig Tiller0581d122015-11-02 14:09:40 -0800262 }
Craig Tillera82950e2015-09-22 12:33:20 -0700263 }
Craig Tiller6e84aba2015-04-23 15:08:17 -0700264
Craig Tillerd1bec032015-09-18 17:29:00 -0700265 /* pass control down the stack */
Craig Tillera82950e2015-09-22 12:33:20 -0700266 grpc_call_next_op(exec_ctx, elem, op);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800267}
268
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800269/* Constructor for call_data */
Mark D. Roth76d24422016-06-23 13:22:10 -0700270static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx,
Mark D. Roth0badbe82016-06-23 10:15:12 -0700271 grpc_call_element *elem,
272 grpc_call_element_args *args) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800273 call_data *calld = elem->call_data;
Craig Tillera82950e2015-09-22 12:33:20 -0700274 memset(calld, 0, sizeof(*calld));
Mark D. Roth0badbe82016-06-23 10:15:12 -0700275 return GRPC_ERROR_NONE;
Craig Tiller0581d122015-11-02 14:09:40 -0800276}
277
David Garcia Quintasf72eb972016-05-03 18:28:09 -0700278static void set_pollset_or_pollset_set(grpc_exec_ctx *exec_ctx,
279 grpc_call_element *elem,
David Garcia Quintas2a50dfe2016-05-31 15:09:12 -0700280 grpc_polling_entity *pollent) {
Craig Tiller0581d122015-11-02 14:09:40 -0800281 call_data *calld = elem->call_data;
David Garcia Quintas2a50dfe2016-05-31 15:09:12 -0700282 calld->pollent = pollent;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800283}
284
285/* Destructor for call_data */
Craig Tiller2c8063c2016-03-22 22:12:15 -0700286static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
David Garcia Quintas5dde14c2016-07-28 17:29:27 -0700287 const grpc_call_final_info *final_info,
288 void *ignored) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800289 call_data *calld = elem->call_data;
Julien Boeuf441176d2015-10-09 21:14:07 -0700290 grpc_call_credentials_unref(calld->creds);
Craig Tillera82950e2015-09-22 12:33:20 -0700291 if (calld->host != NULL) {
292 GRPC_MDSTR_UNREF(calld->host);
293 }
294 if (calld->method != NULL) {
295 GRPC_MDSTR_UNREF(calld->method);
296 }
Julien Boeuf3c957e62015-11-18 21:33:58 -0800297 reset_auth_metadata_context(&calld->auth_md_context);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800298}
299
300/* Constructor for channel_data */
Craig Tillera82950e2015-09-22 12:33:20 -0700301static void init_channel_elem(grpc_exec_ctx *exec_ctx,
Craig Tiller0581d122015-11-02 14:09:40 -0800302 grpc_channel_element *elem,
303 grpc_channel_element_args *args) {
304 grpc_security_connector *sc =
305 grpc_find_security_connector_in_args(args->channel_args);
Julien Boeuf366f42c2015-12-16 22:05:46 -0800306 grpc_auth_context *auth_context =
307 grpc_find_auth_context_in_args(args->channel_args);
308
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800309 /* grab pointers to our data from the channel element */
Julien Boeuf9f218dd2015-04-23 10:24:02 -0700310 channel_data *chand = elem->channel_data;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800311
312 /* The first and the last filters tend to be implemented differently to
313 handle the case that there's no 'next' filter to call on the up or down
314 path */
Craig Tiller0581d122015-11-02 14:09:40 -0800315 GPR_ASSERT(!args->is_last);
Craig Tillera82950e2015-09-22 12:33:20 -0700316 GPR_ASSERT(sc != NULL);
Julien Boeuf366f42c2015-12-16 22:05:46 -0800317 GPR_ASSERT(auth_context != NULL);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800318
319 /* initialize members */
Craig Tillera82950e2015-09-22 12:33:20 -0700320 chand->security_connector =
321 (grpc_channel_security_connector *)GRPC_SECURITY_CONNECTOR_REF(
322 sc, "client_auth_filter");
Julien Boeuf366f42c2015-12-16 22:05:46 -0800323 chand->auth_context =
324 GRPC_AUTH_CONTEXT_REF(auth_context, "client_auth_filter");
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800325}
326
327/* Destructor for channel data */
Craig Tillera82950e2015-09-22 12:33:20 -0700328static void destroy_channel_elem(grpc_exec_ctx *exec_ctx,
329 grpc_channel_element *elem) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800330 /* grab pointers to our data from the channel element */
Julien Boeuf9f218dd2015-04-23 10:24:02 -0700331 channel_data *chand = elem->channel_data;
Julien Boeuf366f42c2015-12-16 22:05:46 -0800332 grpc_channel_security_connector *sc = chand->security_connector;
333 if (sc != NULL) {
334 GRPC_SECURITY_CONNECTOR_UNREF(&sc->base, "client_auth_filter");
Craig Tillera82950e2015-09-22 12:33:20 -0700335 }
Julien Boeuf366f42c2015-12-16 22:05:46 -0800336 GRPC_AUTH_CONTEXT_UNREF(chand->auth_context, "client_auth_filter");
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800337}
338
David Garcia Quintas4afce7e2016-04-18 16:25:17 -0700339const grpc_channel_filter grpc_client_auth_filter = {auth_start_transport_op,
340 grpc_channel_next_op,
341 sizeof(call_data),
342 init_call_elem,
343 set_pollset_or_pollset_set,
344 destroy_call_elem,
345 sizeof(channel_data),
346 init_channel_elem,
347 destroy_channel_elem,
348 grpc_call_next_get_peer,
349 "client-auth"};