blob: 867b851dc1e8e0ab28573a7ddfc3106b0fad2674 [file] [log] [blame]
Julien Boeuf8ca294e2016-05-02 14:56:30 -07001/*
2 *
Jan Tattermusch7897ae92017-06-07 22:57:36 +02003 * Copyright 2015-2016 gRPC authors.
Julien Boeuf8ca294e2016-05-02 14:56:30 -07004 *
Jan Tattermusch7897ae92017-06-07 22:57:36 +02005 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
Julien Boeuf8ca294e2016-05-02 14:56:30 -07008 *
Jan Tattermusch7897ae92017-06-07 22:57:36 +02009 * http://www.apache.org/licenses/LICENSE-2.0
Julien Boeuf8ca294e2016-05-02 14:56:30 -070010 *
Jan Tattermusch7897ae92017-06-07 22:57:36 +020011 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
Julien Boeuf8ca294e2016-05-02 14:56:30 -070016 *
17 */
18
19#include "src/core/lib/security/credentials/composite/composite_credentials.h"
20
21#include <string.h>
22
David Garcia Quintas2a50dfe2016-05-31 15:09:12 -070023#include "src/core/lib/iomgr/polling_entity.h"
Julien Boeuf8ca294e2016-05-02 14:56:30 -070024#include "src/core/lib/surface/api_trace.h"
25
26#include <grpc/support/alloc.h>
27#include <grpc/support/log.h>
28#include <grpc/support/string_util.h>
29
30/* -- Composite call credentials. -- */
31
32typedef struct {
Craig Tillerbaa14a92017-11-03 09:09:36 -070033 grpc_composite_call_credentials* composite_creds;
Julien Boeuf8ca294e2016-05-02 14:56:30 -070034 size_t creds_index;
Craig Tillerbaa14a92017-11-03 09:09:36 -070035 grpc_polling_entity* pollent;
Mark D. Rothe0778b22017-07-21 15:42:00 -070036 grpc_auth_metadata_context auth_md_context;
Craig Tillerbaa14a92017-11-03 09:09:36 -070037 grpc_credentials_mdelem_array* md_array;
38 grpc_closure* on_request_metadata;
Mark D. Rothe0778b22017-07-21 15:42:00 -070039 grpc_closure internal_on_request_metadata;
Julien Boeuf8ca294e2016-05-02 14:56:30 -070040} grpc_composite_call_credentials_metadata_context;
41
Craig Tillerbaa14a92017-11-03 09:09:36 -070042static void composite_call_destruct(grpc_exec_ctx* exec_ctx,
43 grpc_call_credentials* creds) {
44 grpc_composite_call_credentials* c = (grpc_composite_call_credentials*)creds;
Mark D. Rothe0778b22017-07-21 15:42:00 -070045 for (size_t i = 0; i < c->inner.num_creds; i++) {
Craig Tillerbd1795c2016-10-31 15:30:00 -070046 grpc_call_credentials_unref(exec_ctx, c->inner.creds_array[i]);
Julien Boeuf8ca294e2016-05-02 14:56:30 -070047 }
48 gpr_free(c->inner.creds_array);
49}
50
Craig Tillerbaa14a92017-11-03 09:09:36 -070051static void composite_call_metadata_cb(grpc_exec_ctx* exec_ctx, void* arg,
52 grpc_error* error) {
53 grpc_composite_call_credentials_metadata_context* ctx =
54 (grpc_composite_call_credentials_metadata_context*)arg;
Mark D. Rothe0778b22017-07-21 15:42:00 -070055 if (error == GRPC_ERROR_NONE) {
56 /* See if we need to get some more metadata. */
57 if (ctx->creds_index < ctx->composite_creds->inner.num_creds) {
Craig Tillerbaa14a92017-11-03 09:09:36 -070058 grpc_call_credentials* inner_creds =
Mark D. Rothe0778b22017-07-21 15:42:00 -070059 ctx->composite_creds->inner.creds_array[ctx->creds_index++];
60 if (grpc_call_credentials_get_request_metadata(
61 exec_ctx, inner_creds, ctx->pollent, ctx->auth_md_context,
62 ctx->md_array, &ctx->internal_on_request_metadata, &error)) {
63 // Synchronous response, so call ourselves recursively.
64 composite_call_metadata_cb(exec_ctx, arg, error);
65 GRPC_ERROR_UNREF(error);
66 }
67 return;
68 }
69 // We're done!
70 }
71 GRPC_CLOSURE_SCHED(exec_ctx, ctx->on_request_metadata, GRPC_ERROR_REF(error));
Julien Boeuf8ca294e2016-05-02 14:56:30 -070072 gpr_free(ctx);
73}
74
Mark D. Rothe0778b22017-07-21 15:42:00 -070075static bool composite_call_get_request_metadata(
Craig Tillerbaa14a92017-11-03 09:09:36 -070076 grpc_exec_ctx* exec_ctx, grpc_call_credentials* creds,
77 grpc_polling_entity* pollent, grpc_auth_metadata_context auth_md_context,
78 grpc_credentials_mdelem_array* md_array, grpc_closure* on_request_metadata,
79 grpc_error** error) {
80 grpc_composite_call_credentials* c = (grpc_composite_call_credentials*)creds;
81 grpc_composite_call_credentials_metadata_context* ctx;
82 ctx = (grpc_composite_call_credentials_metadata_context*)gpr_zalloc(
Yash Tibrewalacd46e52017-09-20 11:28:25 -070083 sizeof(grpc_composite_call_credentials_metadata_context));
Julien Boeuf8ca294e2016-05-02 14:56:30 -070084 ctx->composite_creds = c;
David Garcia Quintas2a50dfe2016-05-31 15:09:12 -070085 ctx->pollent = pollent;
Mark D. Rothe0778b22017-07-21 15:42:00 -070086 ctx->auth_md_context = auth_md_context;
87 ctx->md_array = md_array;
88 ctx->on_request_metadata = on_request_metadata;
89 GRPC_CLOSURE_INIT(&ctx->internal_on_request_metadata,
90 composite_call_metadata_cb, ctx, grpc_schedule_on_exec_ctx);
Mark D. Roth55a807a2017-09-28 08:33:51 -070091 bool synchronous = true;
Mark D. Rothe0778b22017-07-21 15:42:00 -070092 while (ctx->creds_index < ctx->composite_creds->inner.num_creds) {
Craig Tillerbaa14a92017-11-03 09:09:36 -070093 grpc_call_credentials* inner_creds =
Mark D. Rothe0778b22017-07-21 15:42:00 -070094 ctx->composite_creds->inner.creds_array[ctx->creds_index++];
95 if (grpc_call_credentials_get_request_metadata(
96 exec_ctx, inner_creds, ctx->pollent, ctx->auth_md_context,
97 ctx->md_array, &ctx->internal_on_request_metadata, error)) {
98 if (*error != GRPC_ERROR_NONE) break;
99 } else {
Mark D. Roth55a807a2017-09-28 08:33:51 -0700100 synchronous = false; // Async return.
Mark D. Rothe0778b22017-07-21 15:42:00 -0700101 break;
102 }
103 }
Mark D. Roth55a807a2017-09-28 08:33:51 -0700104 if (synchronous) gpr_free(ctx);
105 return synchronous;
Mark D. Rothe0778b22017-07-21 15:42:00 -0700106}
107
108static void composite_call_cancel_get_request_metadata(
Craig Tillerbaa14a92017-11-03 09:09:36 -0700109 grpc_exec_ctx* exec_ctx, grpc_call_credentials* creds,
110 grpc_credentials_mdelem_array* md_array, grpc_error* error) {
111 grpc_composite_call_credentials* c = (grpc_composite_call_credentials*)creds;
Mark D. Rothe0778b22017-07-21 15:42:00 -0700112 for (size_t i = 0; i < c->inner.num_creds; ++i) {
113 grpc_call_credentials_cancel_get_request_metadata(
114 exec_ctx, c->inner.creds_array[i], md_array, GRPC_ERROR_REF(error));
115 }
116 GRPC_ERROR_UNREF(error);
Julien Boeuf8ca294e2016-05-02 14:56:30 -0700117}
118
119static grpc_call_credentials_vtable composite_call_credentials_vtable = {
Mark D. Rothe0778b22017-07-21 15:42:00 -0700120 composite_call_destruct, composite_call_get_request_metadata,
121 composite_call_cancel_get_request_metadata};
Julien Boeuf8ca294e2016-05-02 14:56:30 -0700122
123static grpc_call_credentials_array get_creds_array(
Craig Tillerbaa14a92017-11-03 09:09:36 -0700124 grpc_call_credentials** creds_addr) {
Julien Boeuf8ca294e2016-05-02 14:56:30 -0700125 grpc_call_credentials_array result;
Craig Tillerbaa14a92017-11-03 09:09:36 -0700126 grpc_call_credentials* creds = *creds_addr;
Julien Boeuf8ca294e2016-05-02 14:56:30 -0700127 result.creds_array = creds_addr;
128 result.num_creds = 1;
129 if (strcmp(creds->type, GRPC_CALL_CREDENTIALS_TYPE_COMPOSITE) == 0) {
130 result = *grpc_composite_call_credentials_get_credentials(creds);
131 }
132 return result;
133}
134
Craig Tillerbaa14a92017-11-03 09:09:36 -0700135grpc_call_credentials* grpc_composite_call_credentials_create(
136 grpc_call_credentials* creds1, grpc_call_credentials* creds2,
137 void* reserved) {
Julien Boeuf8ca294e2016-05-02 14:56:30 -0700138 size_t i;
139 size_t creds_array_byte_size;
140 grpc_call_credentials_array creds1_array;
141 grpc_call_credentials_array creds2_array;
Craig Tillerbaa14a92017-11-03 09:09:36 -0700142 grpc_composite_call_credentials* c;
Julien Boeuf8ca294e2016-05-02 14:56:30 -0700143 GRPC_API_TRACE(
144 "grpc_composite_call_credentials_create(creds1=%p, creds2=%p, "
145 "reserved=%p)",
146 3, (creds1, creds2, reserved));
Craig Tiller4782d922017-11-10 09:53:21 -0800147 GPR_ASSERT(reserved == nullptr);
148 GPR_ASSERT(creds1 != nullptr);
149 GPR_ASSERT(creds2 != nullptr);
Craig Tillerbaa14a92017-11-03 09:09:36 -0700150 c = (grpc_composite_call_credentials*)gpr_zalloc(
Yash Tibrewalacd46e52017-09-20 11:28:25 -0700151 sizeof(grpc_composite_call_credentials));
Julien Boeuf8ca294e2016-05-02 14:56:30 -0700152 c->base.type = GRPC_CALL_CREDENTIALS_TYPE_COMPOSITE;
153 c->base.vtable = &composite_call_credentials_vtable;
154 gpr_ref_init(&c->base.refcount, 1);
155 creds1_array = get_creds_array(&creds1);
156 creds2_array = get_creds_array(&creds2);
157 c->inner.num_creds = creds1_array.num_creds + creds2_array.num_creds;
Craig Tillerbaa14a92017-11-03 09:09:36 -0700158 creds_array_byte_size = c->inner.num_creds * sizeof(grpc_call_credentials*);
Yash Tibrewalacd46e52017-09-20 11:28:25 -0700159 c->inner.creds_array =
Craig Tillerbaa14a92017-11-03 09:09:36 -0700160 (grpc_call_credentials**)gpr_zalloc(creds_array_byte_size);
Julien Boeuf8ca294e2016-05-02 14:56:30 -0700161 for (i = 0; i < creds1_array.num_creds; i++) {
Craig Tillerbaa14a92017-11-03 09:09:36 -0700162 grpc_call_credentials* cur_creds = creds1_array.creds_array[i];
Julien Boeuf8ca294e2016-05-02 14:56:30 -0700163 c->inner.creds_array[i] = grpc_call_credentials_ref(cur_creds);
164 }
165 for (i = 0; i < creds2_array.num_creds; i++) {
Craig Tillerbaa14a92017-11-03 09:09:36 -0700166 grpc_call_credentials* cur_creds = creds2_array.creds_array[i];
Julien Boeuf8ca294e2016-05-02 14:56:30 -0700167 c->inner.creds_array[i + creds1_array.num_creds] =
168 grpc_call_credentials_ref(cur_creds);
169 }
170 return &c->base;
171}
172
Craig Tillerbaa14a92017-11-03 09:09:36 -0700173const grpc_call_credentials_array*
174grpc_composite_call_credentials_get_credentials(grpc_call_credentials* creds) {
175 const grpc_composite_call_credentials* c =
176 (const grpc_composite_call_credentials*)creds;
Julien Boeuf8ca294e2016-05-02 14:56:30 -0700177 GPR_ASSERT(strcmp(creds->type, GRPC_CALL_CREDENTIALS_TYPE_COMPOSITE) == 0);
178 return &c->inner;
179}
180
Craig Tillerbaa14a92017-11-03 09:09:36 -0700181grpc_call_credentials* grpc_credentials_contains_type(
182 grpc_call_credentials* creds, const char* type,
183 grpc_call_credentials** composite_creds) {
Julien Boeuf8ca294e2016-05-02 14:56:30 -0700184 size_t i;
185 if (strcmp(creds->type, type) == 0) {
Craig Tiller4782d922017-11-10 09:53:21 -0800186 if (composite_creds != nullptr) *composite_creds = nullptr;
Julien Boeuf8ca294e2016-05-02 14:56:30 -0700187 return creds;
188 } else if (strcmp(creds->type, GRPC_CALL_CREDENTIALS_TYPE_COMPOSITE) == 0) {
Craig Tillerbaa14a92017-11-03 09:09:36 -0700189 const grpc_call_credentials_array* inner_creds_array =
Julien Boeuf8ca294e2016-05-02 14:56:30 -0700190 grpc_composite_call_credentials_get_credentials(creds);
191 for (i = 0; i < inner_creds_array->num_creds; i++) {
192 if (strcmp(type, inner_creds_array->creds_array[i]->type) == 0) {
Craig Tiller4782d922017-11-10 09:53:21 -0800193 if (composite_creds != nullptr) *composite_creds = creds;
Julien Boeuf8ca294e2016-05-02 14:56:30 -0700194 return inner_creds_array->creds_array[i];
195 }
196 }
197 }
Craig Tiller4782d922017-11-10 09:53:21 -0800198 return nullptr;
Julien Boeuf8ca294e2016-05-02 14:56:30 -0700199}
200
201/* -- Composite channel credentials. -- */
202
Craig Tillerbaa14a92017-11-03 09:09:36 -0700203static void composite_channel_destruct(grpc_exec_ctx* exec_ctx,
204 grpc_channel_credentials* creds) {
205 grpc_composite_channel_credentials* c =
206 (grpc_composite_channel_credentials*)creds;
Craig Tillerbd1795c2016-10-31 15:30:00 -0700207 grpc_channel_credentials_unref(exec_ctx, c->inner_creds);
208 grpc_call_credentials_unref(exec_ctx, c->call_creds);
Julien Boeuf8ca294e2016-05-02 14:56:30 -0700209}
210
211static grpc_security_status composite_channel_create_security_connector(
Craig Tillerbaa14a92017-11-03 09:09:36 -0700212 grpc_exec_ctx* exec_ctx, grpc_channel_credentials* creds,
213 grpc_call_credentials* call_creds, const char* target,
214 const grpc_channel_args* args, grpc_channel_security_connector** sc,
215 grpc_channel_args** new_args) {
216 grpc_composite_channel_credentials* c =
217 (grpc_composite_channel_credentials*)creds;
Julien Boeuf8ca294e2016-05-02 14:56:30 -0700218 grpc_security_status status = GRPC_SECURITY_ERROR;
219
Craig Tiller4782d922017-11-10 09:53:21 -0800220 GPR_ASSERT(c->inner_creds != nullptr && c->call_creds != nullptr &&
221 c->inner_creds->vtable != nullptr &&
222 c->inner_creds->vtable->create_security_connector != nullptr);
Julien Boeuf8ca294e2016-05-02 14:56:30 -0700223 /* If we are passed a call_creds, create a call composite to pass it
224 downstream. */
Craig Tiller4782d922017-11-10 09:53:21 -0800225 if (call_creds != nullptr) {
Craig Tillerbaa14a92017-11-03 09:09:36 -0700226 grpc_call_credentials* composite_call_creds =
Craig Tiller4782d922017-11-10 09:53:21 -0800227 grpc_composite_call_credentials_create(c->call_creds, call_creds, nullptr);
Julien Boeuf8ca294e2016-05-02 14:56:30 -0700228 status = c->inner_creds->vtable->create_security_connector(
Craig Tillerbd1795c2016-10-31 15:30:00 -0700229 exec_ctx, c->inner_creds, composite_call_creds, target, args, sc,
230 new_args);
231 grpc_call_credentials_unref(exec_ctx, composite_call_creds);
Julien Boeuf8ca294e2016-05-02 14:56:30 -0700232 } else {
233 status = c->inner_creds->vtable->create_security_connector(
Craig Tillerbd1795c2016-10-31 15:30:00 -0700234 exec_ctx, c->inner_creds, c->call_creds, target, args, sc, new_args);
Julien Boeuf8ca294e2016-05-02 14:56:30 -0700235 }
236 return status;
237}
238
Craig Tillerbaa14a92017-11-03 09:09:36 -0700239static grpc_channel_credentials*
Julien Boeufe26ab6c2016-09-22 15:13:07 -0700240composite_channel_duplicate_without_call_credentials(
Craig Tillerbaa14a92017-11-03 09:09:36 -0700241 grpc_channel_credentials* creds) {
242 grpc_composite_channel_credentials* c =
243 (grpc_composite_channel_credentials*)creds;
Julien Boeufe26ab6c2016-09-22 15:13:07 -0700244 return grpc_channel_credentials_ref(c->inner_creds);
245}
246
Julien Boeuf8ca294e2016-05-02 14:56:30 -0700247static grpc_channel_credentials_vtable composite_channel_credentials_vtable = {
Julien Boeufe26ab6c2016-09-22 15:13:07 -0700248 composite_channel_destruct, composite_channel_create_security_connector,
249 composite_channel_duplicate_without_call_credentials};
Julien Boeuf8ca294e2016-05-02 14:56:30 -0700250
Craig Tillerbaa14a92017-11-03 09:09:36 -0700251grpc_channel_credentials* grpc_composite_channel_credentials_create(
252 grpc_channel_credentials* channel_creds, grpc_call_credentials* call_creds,
253 void* reserved) {
254 grpc_composite_channel_credentials* c =
255 (grpc_composite_channel_credentials*)gpr_zalloc(sizeof(*c));
Craig Tiller4782d922017-11-10 09:53:21 -0800256 GPR_ASSERT(channel_creds != nullptr && call_creds != nullptr && reserved == nullptr);
Julien Boeuf8ca294e2016-05-02 14:56:30 -0700257 GRPC_API_TRACE(
258 "grpc_composite_channel_credentials_create(channel_creds=%p, "
259 "call_creds=%p, reserved=%p)",
260 3, (channel_creds, call_creds, reserved));
261 c->base.type = channel_creds->type;
262 c->base.vtable = &composite_channel_credentials_vtable;
263 gpr_ref_init(&c->base.refcount, 1);
264 c->inner_creds = grpc_channel_credentials_ref(channel_creds);
265 c->call_creds = grpc_call_credentials_ref(call_creds);
266 return &c->base;
267}