blob: be1588dd8b9cf82d560d9b505a1a468760fb73e5 [file] [log] [blame]
Julien Boeuf8ca294e2016-05-02 14:56:30 -07001/*
2 *
David Garcia Quintas8bec6f62016-05-31 13:59:37 -07003 * Copyright 2015-2016, Google Inc.
Julien Boeuf8ca294e2016-05-02 14:56:30 -07004 * 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
34#include "src/core/lib/security/credentials/composite/composite_credentials.h"
35
36#include <string.h>
37
David Garcia Quintas2a50dfe2016-05-31 15:09:12 -070038#include "src/core/lib/iomgr/polling_entity.h"
Julien Boeuf8ca294e2016-05-02 14:56:30 -070039#include "src/core/lib/surface/api_trace.h"
40
41#include <grpc/support/alloc.h>
42#include <grpc/support/log.h>
43#include <grpc/support/string_util.h>
44
45/* -- Composite call credentials. -- */
46
47typedef struct {
48 grpc_composite_call_credentials *composite_creds;
49 size_t creds_index;
50 grpc_credentials_md_store *md_elems;
51 grpc_auth_metadata_context auth_md_context;
52 void *user_data;
David Garcia Quintas2a50dfe2016-05-31 15:09:12 -070053 grpc_polling_entity *pollent;
Julien Boeuf8ca294e2016-05-02 14:56:30 -070054 grpc_credentials_metadata_cb cb;
55} grpc_composite_call_credentials_metadata_context;
56
Craig Tillerbd1795c2016-10-31 15:30:00 -070057static void composite_call_destruct(grpc_exec_ctx *exec_ctx,
58 grpc_call_credentials *creds) {
Julien Boeuf8ca294e2016-05-02 14:56:30 -070059 grpc_composite_call_credentials *c = (grpc_composite_call_credentials *)creds;
60 size_t i;
61 for (i = 0; i < c->inner.num_creds; i++) {
Craig Tillerbd1795c2016-10-31 15:30:00 -070062 grpc_call_credentials_unref(exec_ctx, c->inner.creds_array[i]);
Julien Boeuf8ca294e2016-05-02 14:56:30 -070063 }
64 gpr_free(c->inner.creds_array);
65}
66
67static void composite_call_md_context_destroy(
Craig Tillerbd1795c2016-10-31 15:30:00 -070068 grpc_exec_ctx *exec_ctx,
Julien Boeuf8ca294e2016-05-02 14:56:30 -070069 grpc_composite_call_credentials_metadata_context *ctx) {
Craig Tillerbd1795c2016-10-31 15:30:00 -070070 grpc_credentials_md_store_unref(exec_ctx, ctx->md_elems);
Julien Boeuf8ca294e2016-05-02 14:56:30 -070071 gpr_free(ctx);
72}
73
74static void composite_call_metadata_cb(grpc_exec_ctx *exec_ctx, void *user_data,
75 grpc_credentials_md *md_elems,
76 size_t num_md,
Julien Boeufbfc7ed62016-06-04 18:03:42 -070077 grpc_credentials_status status,
78 const char *error_details) {
Julien Boeuf8ca294e2016-05-02 14:56:30 -070079 grpc_composite_call_credentials_metadata_context *ctx =
80 (grpc_composite_call_credentials_metadata_context *)user_data;
81 if (status != GRPC_CREDENTIALS_OK) {
Julien Boeufbfc7ed62016-06-04 18:03:42 -070082 ctx->cb(exec_ctx, ctx->user_data, NULL, 0, status, error_details);
Julien Boeuf8ca294e2016-05-02 14:56:30 -070083 return;
84 }
85
86 /* Copy the metadata in the context. */
87 if (num_md > 0) {
88 size_t i;
89 for (i = 0; i < num_md; i++) {
90 grpc_credentials_md_store_add(ctx->md_elems, md_elems[i].key,
91 md_elems[i].value);
92 }
93 }
94
95 /* See if we need to get some more metadata. */
96 if (ctx->creds_index < ctx->composite_creds->inner.num_creds) {
97 grpc_call_credentials *inner_creds =
98 ctx->composite_creds->inner.creds_array[ctx->creds_index++];
David Garcia Quintas2a50dfe2016-05-31 15:09:12 -070099 grpc_call_credentials_get_request_metadata(
100 exec_ctx, inner_creds, ctx->pollent, ctx->auth_md_context,
101 composite_call_metadata_cb, ctx);
Julien Boeuf8ca294e2016-05-02 14:56:30 -0700102 return;
103 }
104
105 /* We're done!. */
106 ctx->cb(exec_ctx, ctx->user_data, ctx->md_elems->entries,
Julien Boeufbfc7ed62016-06-04 18:03:42 -0700107 ctx->md_elems->num_entries, GRPC_CREDENTIALS_OK, NULL);
Craig Tillerbd1795c2016-10-31 15:30:00 -0700108 composite_call_md_context_destroy(exec_ctx, ctx);
Julien Boeuf8ca294e2016-05-02 14:56:30 -0700109}
110
111static void composite_call_get_request_metadata(
David Garcia Quintas2a50dfe2016-05-31 15:09:12 -0700112 grpc_exec_ctx *exec_ctx, grpc_call_credentials *creds,
113 grpc_polling_entity *pollent, grpc_auth_metadata_context auth_md_context,
114 grpc_credentials_metadata_cb cb, void *user_data) {
Julien Boeuf8ca294e2016-05-02 14:56:30 -0700115 grpc_composite_call_credentials *c = (grpc_composite_call_credentials *)creds;
116 grpc_composite_call_credentials_metadata_context *ctx;
117
118 ctx = gpr_malloc(sizeof(grpc_composite_call_credentials_metadata_context));
119 memset(ctx, 0, sizeof(grpc_composite_call_credentials_metadata_context));
120 ctx->auth_md_context = auth_md_context;
121 ctx->user_data = user_data;
122 ctx->cb = cb;
123 ctx->composite_creds = c;
David Garcia Quintas2a50dfe2016-05-31 15:09:12 -0700124 ctx->pollent = pollent;
Julien Boeuf8ca294e2016-05-02 14:56:30 -0700125 ctx->md_elems = grpc_credentials_md_store_create(c->inner.num_creds);
126 grpc_call_credentials_get_request_metadata(
David Garcia Quintas2a50dfe2016-05-31 15:09:12 -0700127 exec_ctx, c->inner.creds_array[ctx->creds_index++], ctx->pollent,
Julien Boeuf8ca294e2016-05-02 14:56:30 -0700128 auth_md_context, composite_call_metadata_cb, ctx);
129}
130
131static grpc_call_credentials_vtable composite_call_credentials_vtable = {
132 composite_call_destruct, composite_call_get_request_metadata};
133
134static grpc_call_credentials_array get_creds_array(
135 grpc_call_credentials **creds_addr) {
136 grpc_call_credentials_array result;
137 grpc_call_credentials *creds = *creds_addr;
138 result.creds_array = creds_addr;
139 result.num_creds = 1;
140 if (strcmp(creds->type, GRPC_CALL_CREDENTIALS_TYPE_COMPOSITE) == 0) {
141 result = *grpc_composite_call_credentials_get_credentials(creds);
142 }
143 return result;
144}
145
146grpc_call_credentials *grpc_composite_call_credentials_create(
147 grpc_call_credentials *creds1, grpc_call_credentials *creds2,
148 void *reserved) {
149 size_t i;
150 size_t creds_array_byte_size;
151 grpc_call_credentials_array creds1_array;
152 grpc_call_credentials_array creds2_array;
153 grpc_composite_call_credentials *c;
154 GRPC_API_TRACE(
155 "grpc_composite_call_credentials_create(creds1=%p, creds2=%p, "
156 "reserved=%p)",
157 3, (creds1, creds2, reserved));
158 GPR_ASSERT(reserved == NULL);
159 GPR_ASSERT(creds1 != NULL);
160 GPR_ASSERT(creds2 != NULL);
161 c = gpr_malloc(sizeof(grpc_composite_call_credentials));
162 memset(c, 0, sizeof(grpc_composite_call_credentials));
163 c->base.type = GRPC_CALL_CREDENTIALS_TYPE_COMPOSITE;
164 c->base.vtable = &composite_call_credentials_vtable;
165 gpr_ref_init(&c->base.refcount, 1);
166 creds1_array = get_creds_array(&creds1);
167 creds2_array = get_creds_array(&creds2);
168 c->inner.num_creds = creds1_array.num_creds + creds2_array.num_creds;
169 creds_array_byte_size = c->inner.num_creds * sizeof(grpc_call_credentials *);
170 c->inner.creds_array = gpr_malloc(creds_array_byte_size);
171 memset(c->inner.creds_array, 0, creds_array_byte_size);
172 for (i = 0; i < creds1_array.num_creds; i++) {
173 grpc_call_credentials *cur_creds = creds1_array.creds_array[i];
174 c->inner.creds_array[i] = grpc_call_credentials_ref(cur_creds);
175 }
176 for (i = 0; i < creds2_array.num_creds; i++) {
177 grpc_call_credentials *cur_creds = creds2_array.creds_array[i];
178 c->inner.creds_array[i + creds1_array.num_creds] =
179 grpc_call_credentials_ref(cur_creds);
180 }
181 return &c->base;
182}
183
184const grpc_call_credentials_array *
185grpc_composite_call_credentials_get_credentials(grpc_call_credentials *creds) {
186 const grpc_composite_call_credentials *c =
187 (const grpc_composite_call_credentials *)creds;
188 GPR_ASSERT(strcmp(creds->type, GRPC_CALL_CREDENTIALS_TYPE_COMPOSITE) == 0);
189 return &c->inner;
190}
191
192grpc_call_credentials *grpc_credentials_contains_type(
193 grpc_call_credentials *creds, const char *type,
194 grpc_call_credentials **composite_creds) {
195 size_t i;
196 if (strcmp(creds->type, type) == 0) {
197 if (composite_creds != NULL) *composite_creds = NULL;
198 return creds;
199 } else if (strcmp(creds->type, GRPC_CALL_CREDENTIALS_TYPE_COMPOSITE) == 0) {
200 const grpc_call_credentials_array *inner_creds_array =
201 grpc_composite_call_credentials_get_credentials(creds);
202 for (i = 0; i < inner_creds_array->num_creds; i++) {
203 if (strcmp(type, inner_creds_array->creds_array[i]->type) == 0) {
204 if (composite_creds != NULL) *composite_creds = creds;
205 return inner_creds_array->creds_array[i];
206 }
207 }
208 }
209 return NULL;
210}
211
212/* -- Composite channel credentials. -- */
213
Craig Tillerbd1795c2016-10-31 15:30:00 -0700214static void composite_channel_destruct(grpc_exec_ctx *exec_ctx,
215 grpc_channel_credentials *creds) {
Julien Boeuf8ca294e2016-05-02 14:56:30 -0700216 grpc_composite_channel_credentials *c =
217 (grpc_composite_channel_credentials *)creds;
Craig Tillerbd1795c2016-10-31 15:30:00 -0700218 grpc_channel_credentials_unref(exec_ctx, c->inner_creds);
219 grpc_call_credentials_unref(exec_ctx, c->call_creds);
Julien Boeuf8ca294e2016-05-02 14:56:30 -0700220}
221
222static grpc_security_status composite_channel_create_security_connector(
Craig Tillerbd1795c2016-10-31 15:30:00 -0700223 grpc_exec_ctx *exec_ctx, grpc_channel_credentials *creds,
224 grpc_call_credentials *call_creds, const char *target,
225 const grpc_channel_args *args, grpc_channel_security_connector **sc,
226 grpc_channel_args **new_args) {
Julien Boeuf8ca294e2016-05-02 14:56:30 -0700227 grpc_composite_channel_credentials *c =
228 (grpc_composite_channel_credentials *)creds;
229 grpc_security_status status = GRPC_SECURITY_ERROR;
230
231 GPR_ASSERT(c->inner_creds != NULL && c->call_creds != NULL &&
232 c->inner_creds->vtable != NULL &&
233 c->inner_creds->vtable->create_security_connector != NULL);
234 /* If we are passed a call_creds, create a call composite to pass it
235 downstream. */
236 if (call_creds != NULL) {
237 grpc_call_credentials *composite_call_creds =
238 grpc_composite_call_credentials_create(c->call_creds, call_creds, NULL);
239 status = c->inner_creds->vtable->create_security_connector(
Craig Tillerbd1795c2016-10-31 15:30:00 -0700240 exec_ctx, c->inner_creds, composite_call_creds, target, args, sc,
241 new_args);
242 grpc_call_credentials_unref(exec_ctx, composite_call_creds);
Julien Boeuf8ca294e2016-05-02 14:56:30 -0700243 } else {
244 status = c->inner_creds->vtable->create_security_connector(
Craig Tillerbd1795c2016-10-31 15:30:00 -0700245 exec_ctx, c->inner_creds, c->call_creds, target, args, sc, new_args);
Julien Boeuf8ca294e2016-05-02 14:56:30 -0700246 }
247 return status;
248}
249
Julien Boeufe26ab6c2016-09-22 15:13:07 -0700250static grpc_channel_credentials *
251composite_channel_duplicate_without_call_credentials(
252 grpc_channel_credentials *creds) {
253 grpc_composite_channel_credentials *c =
254 (grpc_composite_channel_credentials *)creds;
255 return grpc_channel_credentials_ref(c->inner_creds);
256}
257
Julien Boeuf8ca294e2016-05-02 14:56:30 -0700258static grpc_channel_credentials_vtable composite_channel_credentials_vtable = {
Julien Boeufe26ab6c2016-09-22 15:13:07 -0700259 composite_channel_destruct, composite_channel_create_security_connector,
260 composite_channel_duplicate_without_call_credentials};
Julien Boeuf8ca294e2016-05-02 14:56:30 -0700261
262grpc_channel_credentials *grpc_composite_channel_credentials_create(
263 grpc_channel_credentials *channel_creds, grpc_call_credentials *call_creds,
264 void *reserved) {
265 grpc_composite_channel_credentials *c = gpr_malloc(sizeof(*c));
266 memset(c, 0, sizeof(*c));
267 GPR_ASSERT(channel_creds != NULL && call_creds != NULL && reserved == NULL);
268 GRPC_API_TRACE(
269 "grpc_composite_channel_credentials_create(channel_creds=%p, "
270 "call_creds=%p, reserved=%p)",
271 3, (channel_creds, call_creds, reserved));
272 c->base.type = channel_creds->type;
273 c->base.vtable = &composite_channel_credentials_vtable;
274 gpr_ref_init(&c->base.refcount, 1);
275 c->inner_creds = grpc_channel_credentials_ref(channel_creds);
276 c->call_creds = grpc_call_credentials_ref(call_creds);
277 return &c->base;
278}