Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(327)

Side by Side Diff: third_party/grpc/src/core/security/credentials.c

Issue 1932353002: Initial checkin of gRPC to third_party/ Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 /*
2 *
3 * Copyright 2015-2016, Google Inc.
4 * 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/security/credentials.h"
35
36 #include <stdio.h>
37 #include <string.h>
38
39 #include "src/core/channel/channel_args.h"
40 #include "src/core/channel/http_client_filter.h"
41 #include "src/core/httpcli/httpcli.h"
42 #include "src/core/iomgr/executor.h"
43 #include "src/core/json/json.h"
44 #include "src/core/support/string.h"
45 #include "src/core/surface/api_trace.h"
46
47 #include <grpc/support/alloc.h>
48 #include <grpc/support/log.h>
49 #include <grpc/support/string_util.h>
50 #include <grpc/support/sync.h>
51 #include <grpc/support/time.h>
52
53 /* -- Common. -- */
54
55 struct grpc_credentials_metadata_request {
56 grpc_call_credentials *creds;
57 grpc_credentials_metadata_cb cb;
58 void *user_data;
59 };
60
61 static grpc_credentials_metadata_request *
62 grpc_credentials_metadata_request_create(grpc_call_credentials *creds,
63 grpc_credentials_metadata_cb cb,
64 void *user_data) {
65 grpc_credentials_metadata_request *r =
66 gpr_malloc(sizeof(grpc_credentials_metadata_request));
67 r->creds = grpc_call_credentials_ref(creds);
68 r->cb = cb;
69 r->user_data = user_data;
70 return r;
71 }
72
73 static void grpc_credentials_metadata_request_destroy(
74 grpc_credentials_metadata_request *r) {
75 grpc_call_credentials_unref(r->creds);
76 gpr_free(r);
77 }
78
79 grpc_channel_credentials *grpc_channel_credentials_ref(
80 grpc_channel_credentials *creds) {
81 if (creds == NULL) return NULL;
82 gpr_ref(&creds->refcount);
83 return creds;
84 }
85
86 void grpc_channel_credentials_unref(grpc_channel_credentials *creds) {
87 if (creds == NULL) return;
88 if (gpr_unref(&creds->refcount)) {
89 if (creds->vtable->destruct != NULL) creds->vtable->destruct(creds);
90 gpr_free(creds);
91 }
92 }
93
94 void grpc_channel_credentials_release(grpc_channel_credentials *creds) {
95 GRPC_API_TRACE("grpc_channel_credentials_release(creds=%p)", 1, (creds));
96 grpc_channel_credentials_unref(creds);
97 }
98
99 grpc_call_credentials *grpc_call_credentials_ref(grpc_call_credentials *creds) {
100 if (creds == NULL) return NULL;
101 gpr_ref(&creds->refcount);
102 return creds;
103 }
104
105 void grpc_call_credentials_unref(grpc_call_credentials *creds) {
106 if (creds == NULL) return;
107 if (gpr_unref(&creds->refcount)) {
108 if (creds->vtable->destruct != NULL) creds->vtable->destruct(creds);
109 gpr_free(creds);
110 }
111 }
112
113 void grpc_call_credentials_release(grpc_call_credentials *creds) {
114 GRPC_API_TRACE("grpc_call_credentials_release(creds=%p)", 1, (creds));
115 grpc_call_credentials_unref(creds);
116 }
117
118 void grpc_call_credentials_get_request_metadata(
119 grpc_exec_ctx *exec_ctx, grpc_call_credentials *creds,
120 grpc_pollset *pollset, grpc_auth_metadata_context context,
121 grpc_credentials_metadata_cb cb, void *user_data) {
122 if (creds == NULL || creds->vtable->get_request_metadata == NULL) {
123 if (cb != NULL) {
124 cb(exec_ctx, user_data, NULL, 0, GRPC_CREDENTIALS_OK);
125 }
126 return;
127 }
128 creds->vtable->get_request_metadata(exec_ctx, creds, pollset, context, cb,
129 user_data);
130 }
131
132 grpc_security_status grpc_channel_credentials_create_security_connector(
133 grpc_channel_credentials *channel_creds, const char *target,
134 const grpc_channel_args *args, grpc_channel_security_connector **sc,
135 grpc_channel_args **new_args) {
136 *new_args = NULL;
137 if (channel_creds == NULL) {
138 return GRPC_SECURITY_ERROR;
139 }
140 GPR_ASSERT(channel_creds->vtable->create_security_connector != NULL);
141 return channel_creds->vtable->create_security_connector(
142 channel_creds, NULL, target, args, sc, new_args);
143 }
144
145 grpc_server_credentials *grpc_server_credentials_ref(
146 grpc_server_credentials *creds) {
147 if (creds == NULL) return NULL;
148 gpr_ref(&creds->refcount);
149 return creds;
150 }
151
152 void grpc_server_credentials_unref(grpc_server_credentials *creds) {
153 if (creds == NULL) return;
154 if (gpr_unref(&creds->refcount)) {
155 if (creds->vtable->destruct != NULL) creds->vtable->destruct(creds);
156 if (creds->processor.destroy != NULL && creds->processor.state != NULL) {
157 creds->processor.destroy(creds->processor.state);
158 }
159 gpr_free(creds);
160 }
161 }
162
163 void grpc_server_credentials_release(grpc_server_credentials *creds) {
164 GRPC_API_TRACE("grpc_server_credentials_release(creds=%p)", 1, (creds));
165 grpc_server_credentials_unref(creds);
166 }
167
168 grpc_security_status grpc_server_credentials_create_security_connector(
169 grpc_server_credentials *creds, grpc_server_security_connector **sc) {
170 if (creds == NULL || creds->vtable->create_security_connector == NULL) {
171 gpr_log(GPR_ERROR, "Server credentials cannot create security context.");
172 return GRPC_SECURITY_ERROR;
173 }
174 return creds->vtable->create_security_connector(creds, sc);
175 }
176
177 void grpc_server_credentials_set_auth_metadata_processor(
178 grpc_server_credentials *creds, grpc_auth_metadata_processor processor) {
179 GRPC_API_TRACE(
180 "grpc_server_credentials_set_auth_metadata_processor("
181 "creds=%p, "
182 "processor=grpc_auth_metadata_processor { process: %p, state: %p })",
183 3, (creds, (void *)(intptr_t)processor.process, processor.state));
184 if (creds == NULL) return;
185 if (creds->processor.destroy != NULL && creds->processor.state != NULL) {
186 creds->processor.destroy(creds->processor.state);
187 }
188 creds->processor = processor;
189 }
190
191 static void server_credentials_pointer_arg_destroy(void *p) {
192 grpc_server_credentials_unref(p);
193 }
194
195 static void *server_credentials_pointer_arg_copy(void *p) {
196 return grpc_server_credentials_ref(p);
197 }
198
199 static int server_credentials_pointer_cmp(void *a, void *b) {
200 return GPR_ICMP(a, b);
201 }
202
203 static const grpc_arg_pointer_vtable cred_ptr_vtable = {
204 server_credentials_pointer_arg_copy, server_credentials_pointer_arg_destroy,
205 server_credentials_pointer_cmp};
206
207 grpc_arg grpc_server_credentials_to_arg(grpc_server_credentials *p) {
208 grpc_arg arg;
209 memset(&arg, 0, sizeof(grpc_arg));
210 arg.type = GRPC_ARG_POINTER;
211 arg.key = GRPC_SERVER_CREDENTIALS_ARG;
212 arg.value.pointer.p = p;
213 arg.value.pointer.vtable = &cred_ptr_vtable;
214 return arg;
215 }
216
217 grpc_server_credentials *grpc_server_credentials_from_arg(const grpc_arg *arg) {
218 if (strcmp(arg->key, GRPC_SERVER_CREDENTIALS_ARG) != 0) return NULL;
219 if (arg->type != GRPC_ARG_POINTER) {
220 gpr_log(GPR_ERROR, "Invalid type %d for arg %s", arg->type,
221 GRPC_SERVER_CREDENTIALS_ARG);
222 return NULL;
223 }
224 return arg->value.pointer.p;
225 }
226
227 grpc_server_credentials *grpc_find_server_credentials_in_args(
228 const grpc_channel_args *args) {
229 size_t i;
230 if (args == NULL) return NULL;
231 for (i = 0; i < args->num_args; i++) {
232 grpc_server_credentials *p =
233 grpc_server_credentials_from_arg(&args->args[i]);
234 if (p != NULL) return p;
235 }
236 return NULL;
237 }
238
239 /* -- Ssl credentials. -- */
240
241 static void ssl_destruct(grpc_channel_credentials *creds) {
242 grpc_ssl_credentials *c = (grpc_ssl_credentials *)creds;
243 if (c->config.pem_root_certs != NULL) gpr_free(c->config.pem_root_certs);
244 if (c->config.pem_private_key != NULL) gpr_free(c->config.pem_private_key);
245 if (c->config.pem_cert_chain != NULL) gpr_free(c->config.pem_cert_chain);
246 }
247
248 static void ssl_server_destruct(grpc_server_credentials *creds) {
249 grpc_ssl_server_credentials *c = (grpc_ssl_server_credentials *)creds;
250 size_t i;
251 for (i = 0; i < c->config.num_key_cert_pairs; i++) {
252 if (c->config.pem_private_keys[i] != NULL) {
253 gpr_free(c->config.pem_private_keys[i]);
254 }
255 if (c->config.pem_cert_chains[i] != NULL) {
256 gpr_free(c->config.pem_cert_chains[i]);
257 }
258 }
259 if (c->config.pem_private_keys != NULL) gpr_free(c->config.pem_private_keys);
260 if (c->config.pem_private_keys_sizes != NULL) {
261 gpr_free(c->config.pem_private_keys_sizes);
262 }
263 if (c->config.pem_cert_chains != NULL) gpr_free(c->config.pem_cert_chains);
264 if (c->config.pem_cert_chains_sizes != NULL) {
265 gpr_free(c->config.pem_cert_chains_sizes);
266 }
267 if (c->config.pem_root_certs != NULL) gpr_free(c->config.pem_root_certs);
268 }
269
270 static grpc_security_status ssl_create_security_connector(
271 grpc_channel_credentials *creds, grpc_call_credentials *call_creds,
272 const char *target, const grpc_channel_args *args,
273 grpc_channel_security_connector **sc, grpc_channel_args **new_args) {
274 grpc_ssl_credentials *c = (grpc_ssl_credentials *)creds;
275 grpc_security_status status = GRPC_SECURITY_OK;
276 size_t i = 0;
277 const char *overridden_target_name = NULL;
278 grpc_arg new_arg;
279
280 for (i = 0; args && i < args->num_args; i++) {
281 grpc_arg *arg = &args->args[i];
282 if (strcmp(arg->key, GRPC_SSL_TARGET_NAME_OVERRIDE_ARG) == 0 &&
283 arg->type == GRPC_ARG_STRING) {
284 overridden_target_name = arg->value.string;
285 break;
286 }
287 }
288 status = grpc_ssl_channel_security_connector_create(
289 call_creds, &c->config, target, overridden_target_name, sc);
290 if (status != GRPC_SECURITY_OK) {
291 return status;
292 }
293 new_arg.type = GRPC_ARG_STRING;
294 new_arg.key = GRPC_ARG_HTTP2_SCHEME;
295 new_arg.value.string = "https";
296 *new_args = grpc_channel_args_copy_and_add(args, &new_arg, 1);
297 return status;
298 }
299
300 static grpc_security_status ssl_server_create_security_connector(
301 grpc_server_credentials *creds, grpc_server_security_connector **sc) {
302 grpc_ssl_server_credentials *c = (grpc_ssl_server_credentials *)creds;
303 return grpc_ssl_server_security_connector_create(&c->config, sc);
304 }
305
306 static grpc_channel_credentials_vtable ssl_vtable = {
307 ssl_destruct, ssl_create_security_connector};
308
309 static grpc_server_credentials_vtable ssl_server_vtable = {
310 ssl_server_destruct, ssl_server_create_security_connector};
311
312 static void ssl_copy_key_material(const char *input, unsigned char **output,
313 size_t *output_size) {
314 *output_size = strlen(input);
315 *output = gpr_malloc(*output_size);
316 memcpy(*output, input, *output_size);
317 }
318
319 static void ssl_build_config(const char *pem_root_certs,
320 grpc_ssl_pem_key_cert_pair *pem_key_cert_pair,
321 grpc_ssl_config *config) {
322 if (pem_root_certs != NULL) {
323 ssl_copy_key_material(pem_root_certs, &config->pem_root_certs,
324 &config->pem_root_certs_size);
325 }
326 if (pem_key_cert_pair != NULL) {
327 GPR_ASSERT(pem_key_cert_pair->private_key != NULL);
328 GPR_ASSERT(pem_key_cert_pair->cert_chain != NULL);
329 ssl_copy_key_material(pem_key_cert_pair->private_key,
330 &config->pem_private_key,
331 &config->pem_private_key_size);
332 ssl_copy_key_material(pem_key_cert_pair->cert_chain,
333 &config->pem_cert_chain,
334 &config->pem_cert_chain_size);
335 }
336 }
337
338 static void ssl_build_server_config(
339 const char *pem_root_certs, grpc_ssl_pem_key_cert_pair *pem_key_cert_pairs,
340 size_t num_key_cert_pairs, int force_client_auth,
341 grpc_ssl_server_config *config) {
342 size_t i;
343 config->force_client_auth = force_client_auth;
344 if (pem_root_certs != NULL) {
345 ssl_copy_key_material(pem_root_certs, &config->pem_root_certs,
346 &config->pem_root_certs_size);
347 }
348 if (num_key_cert_pairs > 0) {
349 GPR_ASSERT(pem_key_cert_pairs != NULL);
350 config->pem_private_keys =
351 gpr_malloc(num_key_cert_pairs * sizeof(unsigned char *));
352 config->pem_cert_chains =
353 gpr_malloc(num_key_cert_pairs * sizeof(unsigned char *));
354 config->pem_private_keys_sizes =
355 gpr_malloc(num_key_cert_pairs * sizeof(size_t));
356 config->pem_cert_chains_sizes =
357 gpr_malloc(num_key_cert_pairs * sizeof(size_t));
358 }
359 config->num_key_cert_pairs = num_key_cert_pairs;
360 for (i = 0; i < num_key_cert_pairs; i++) {
361 GPR_ASSERT(pem_key_cert_pairs[i].private_key != NULL);
362 GPR_ASSERT(pem_key_cert_pairs[i].cert_chain != NULL);
363 ssl_copy_key_material(pem_key_cert_pairs[i].private_key,
364 &config->pem_private_keys[i],
365 &config->pem_private_keys_sizes[i]);
366 ssl_copy_key_material(pem_key_cert_pairs[i].cert_chain,
367 &config->pem_cert_chains[i],
368 &config->pem_cert_chains_sizes[i]);
369 }
370 }
371
372 grpc_channel_credentials *grpc_ssl_credentials_create(
373 const char *pem_root_certs, grpc_ssl_pem_key_cert_pair *pem_key_cert_pair,
374 void *reserved) {
375 grpc_ssl_credentials *c = gpr_malloc(sizeof(grpc_ssl_credentials));
376 GRPC_API_TRACE(
377 "grpc_ssl_credentials_create(pem_root_certs=%s, "
378 "pem_key_cert_pair=%p, "
379 "reserved=%p)",
380 3, (pem_root_certs, pem_key_cert_pair, reserved));
381 GPR_ASSERT(reserved == NULL);
382 memset(c, 0, sizeof(grpc_ssl_credentials));
383 c->base.type = GRPC_CHANNEL_CREDENTIALS_TYPE_SSL;
384 c->base.vtable = &ssl_vtable;
385 gpr_ref_init(&c->base.refcount, 1);
386 ssl_build_config(pem_root_certs, pem_key_cert_pair, &c->config);
387 return &c->base;
388 }
389
390 grpc_server_credentials *grpc_ssl_server_credentials_create(
391 const char *pem_root_certs, grpc_ssl_pem_key_cert_pair *pem_key_cert_pairs,
392 size_t num_key_cert_pairs, int force_client_auth, void *reserved) {
393 grpc_ssl_server_credentials *c =
394 gpr_malloc(sizeof(grpc_ssl_server_credentials));
395 GRPC_API_TRACE(
396 "grpc_ssl_server_credentials_create("
397 "pem_root_certs=%s, pem_key_cert_pairs=%p, num_key_cert_pairs=%lu, "
398 "force_client_auth=%d, reserved=%p)",
399 5, (pem_root_certs, pem_key_cert_pairs, (unsigned long)num_key_cert_pairs,
400 force_client_auth, reserved));
401 GPR_ASSERT(reserved == NULL);
402 memset(c, 0, sizeof(grpc_ssl_server_credentials));
403 c->base.type = GRPC_CHANNEL_CREDENTIALS_TYPE_SSL;
404 gpr_ref_init(&c->base.refcount, 1);
405 c->base.vtable = &ssl_server_vtable;
406 ssl_build_server_config(pem_root_certs, pem_key_cert_pairs,
407 num_key_cert_pairs, force_client_auth, &c->config);
408 return &c->base;
409 }
410
411 /* -- Jwt credentials -- */
412
413 static void jwt_reset_cache(grpc_service_account_jwt_access_credentials *c) {
414 if (c->cached.jwt_md != NULL) {
415 grpc_credentials_md_store_unref(c->cached.jwt_md);
416 c->cached.jwt_md = NULL;
417 }
418 if (c->cached.service_url != NULL) {
419 gpr_free(c->cached.service_url);
420 c->cached.service_url = NULL;
421 }
422 c->cached.jwt_expiration = gpr_inf_past(GPR_CLOCK_REALTIME);
423 }
424
425 static void jwt_destruct(grpc_call_credentials *creds) {
426 grpc_service_account_jwt_access_credentials *c =
427 (grpc_service_account_jwt_access_credentials *)creds;
428 grpc_auth_json_key_destruct(&c->key);
429 jwt_reset_cache(c);
430 gpr_mu_destroy(&c->cache_mu);
431 }
432
433 static void jwt_get_request_metadata(grpc_exec_ctx *exec_ctx,
434 grpc_call_credentials *creds,
435 grpc_pollset *pollset,
436 grpc_auth_metadata_context context,
437 grpc_credentials_metadata_cb cb,
438 void *user_data) {
439 grpc_service_account_jwt_access_credentials *c =
440 (grpc_service_account_jwt_access_credentials *)creds;
441 gpr_timespec refresh_threshold = gpr_time_from_seconds(
442 GRPC_SECURE_TOKEN_REFRESH_THRESHOLD_SECS, GPR_TIMESPAN);
443
444 /* See if we can return a cached jwt. */
445 grpc_credentials_md_store *jwt_md = NULL;
446 {
447 gpr_mu_lock(&c->cache_mu);
448 if (c->cached.service_url != NULL &&
449 strcmp(c->cached.service_url, context.service_url) == 0 &&
450 c->cached.jwt_md != NULL &&
451 (gpr_time_cmp(gpr_time_sub(c->cached.jwt_expiration,
452 gpr_now(GPR_CLOCK_REALTIME)),
453 refresh_threshold) > 0)) {
454 jwt_md = grpc_credentials_md_store_ref(c->cached.jwt_md);
455 }
456 gpr_mu_unlock(&c->cache_mu);
457 }
458
459 if (jwt_md == NULL) {
460 char *jwt = NULL;
461 /* Generate a new jwt. */
462 gpr_mu_lock(&c->cache_mu);
463 jwt_reset_cache(c);
464 jwt = grpc_jwt_encode_and_sign(&c->key, context.service_url,
465 c->jwt_lifetime, NULL);
466 if (jwt != NULL) {
467 char *md_value;
468 gpr_asprintf(&md_value, "Bearer %s", jwt);
469 gpr_free(jwt);
470 c->cached.jwt_expiration =
471 gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), c->jwt_lifetime);
472 c->cached.service_url = gpr_strdup(context.service_url);
473 c->cached.jwt_md = grpc_credentials_md_store_create(1);
474 grpc_credentials_md_store_add_cstrings(
475 c->cached.jwt_md, GRPC_AUTHORIZATION_METADATA_KEY, md_value);
476 gpr_free(md_value);
477 jwt_md = grpc_credentials_md_store_ref(c->cached.jwt_md);
478 }
479 gpr_mu_unlock(&c->cache_mu);
480 }
481
482 if (jwt_md != NULL) {
483 cb(exec_ctx, user_data, jwt_md->entries, jwt_md->num_entries,
484 GRPC_CREDENTIALS_OK);
485 grpc_credentials_md_store_unref(jwt_md);
486 } else {
487 cb(exec_ctx, user_data, NULL, 0, GRPC_CREDENTIALS_ERROR);
488 }
489 }
490
491 static grpc_call_credentials_vtable jwt_vtable = {jwt_destruct,
492 jwt_get_request_metadata};
493
494 grpc_call_credentials *
495 grpc_service_account_jwt_access_credentials_create_from_auth_json_key(
496 grpc_auth_json_key key, gpr_timespec token_lifetime) {
497 grpc_service_account_jwt_access_credentials *c;
498 if (!grpc_auth_json_key_is_valid(&key)) {
499 gpr_log(GPR_ERROR, "Invalid input for jwt credentials creation");
500 return NULL;
501 }
502 c = gpr_malloc(sizeof(grpc_service_account_jwt_access_credentials));
503 memset(c, 0, sizeof(grpc_service_account_jwt_access_credentials));
504 c->base.type = GRPC_CALL_CREDENTIALS_TYPE_JWT;
505 gpr_ref_init(&c->base.refcount, 1);
506 c->base.vtable = &jwt_vtable;
507 c->key = key;
508 c->jwt_lifetime = token_lifetime;
509 gpr_mu_init(&c->cache_mu);
510 jwt_reset_cache(c);
511 return &c->base;
512 }
513
514 grpc_call_credentials *grpc_service_account_jwt_access_credentials_create(
515 const char *json_key, gpr_timespec token_lifetime, void *reserved) {
516 GRPC_API_TRACE(
517 "grpc_service_account_jwt_access_credentials_create("
518 "json_key=%s, "
519 "token_lifetime="
520 "gpr_timespec { tv_sec: %lld, tv_nsec: %d, clock_type: %d }, "
521 "reserved=%p)",
522 5,
523 (json_key, (long long)token_lifetime.tv_sec, (int)token_lifetime.tv_nsec,
524 (int)token_lifetime.clock_type, reserved));
525 GPR_ASSERT(reserved == NULL);
526 return grpc_service_account_jwt_access_credentials_create_from_auth_json_key(
527 grpc_auth_json_key_create_from_string(json_key), token_lifetime);
528 }
529
530 /* -- Oauth2TokenFetcher credentials -- */
531
532 static void oauth2_token_fetcher_destruct(grpc_call_credentials *creds) {
533 grpc_oauth2_token_fetcher_credentials *c =
534 (grpc_oauth2_token_fetcher_credentials *)creds;
535 grpc_credentials_md_store_unref(c->access_token_md);
536 gpr_mu_destroy(&c->mu);
537 grpc_httpcli_context_destroy(&c->httpcli_context);
538 }
539
540 grpc_credentials_status
541 grpc_oauth2_token_fetcher_credentials_parse_server_response(
542 const grpc_httpcli_response *response, grpc_credentials_md_store **token_md,
543 gpr_timespec *token_lifetime) {
544 char *null_terminated_body = NULL;
545 char *new_access_token = NULL;
546 grpc_credentials_status status = GRPC_CREDENTIALS_OK;
547 grpc_json *json = NULL;
548
549 if (response == NULL) {
550 gpr_log(GPR_ERROR, "Received NULL response.");
551 status = GRPC_CREDENTIALS_ERROR;
552 goto end;
553 }
554
555 if (response->body_length > 0) {
556 null_terminated_body = gpr_malloc(response->body_length + 1);
557 null_terminated_body[response->body_length] = '\0';
558 memcpy(null_terminated_body, response->body, response->body_length);
559 }
560
561 if (response->status != 200) {
562 gpr_log(GPR_ERROR, "Call to http server ended with error %d [%s].",
563 response->status,
564 null_terminated_body != NULL ? null_terminated_body : "");
565 status = GRPC_CREDENTIALS_ERROR;
566 goto end;
567 } else {
568 grpc_json *access_token = NULL;
569 grpc_json *token_type = NULL;
570 grpc_json *expires_in = NULL;
571 grpc_json *ptr;
572 json = grpc_json_parse_string(null_terminated_body);
573 if (json == NULL) {
574 gpr_log(GPR_ERROR, "Could not parse JSON from %s", null_terminated_body);
575 status = GRPC_CREDENTIALS_ERROR;
576 goto end;
577 }
578 if (json->type != GRPC_JSON_OBJECT) {
579 gpr_log(GPR_ERROR, "Response should be a JSON object");
580 status = GRPC_CREDENTIALS_ERROR;
581 goto end;
582 }
583 for (ptr = json->child; ptr; ptr = ptr->next) {
584 if (strcmp(ptr->key, "access_token") == 0) {
585 access_token = ptr;
586 } else if (strcmp(ptr->key, "token_type") == 0) {
587 token_type = ptr;
588 } else if (strcmp(ptr->key, "expires_in") == 0) {
589 expires_in = ptr;
590 }
591 }
592 if (access_token == NULL || access_token->type != GRPC_JSON_STRING) {
593 gpr_log(GPR_ERROR, "Missing or invalid access_token in JSON.");
594 status = GRPC_CREDENTIALS_ERROR;
595 goto end;
596 }
597 if (token_type == NULL || token_type->type != GRPC_JSON_STRING) {
598 gpr_log(GPR_ERROR, "Missing or invalid token_type in JSON.");
599 status = GRPC_CREDENTIALS_ERROR;
600 goto end;
601 }
602 if (expires_in == NULL || expires_in->type != GRPC_JSON_NUMBER) {
603 gpr_log(GPR_ERROR, "Missing or invalid expires_in in JSON.");
604 status = GRPC_CREDENTIALS_ERROR;
605 goto end;
606 }
607 gpr_asprintf(&new_access_token, "%s %s", token_type->value,
608 access_token->value);
609 token_lifetime->tv_sec = strtol(expires_in->value, NULL, 10);
610 token_lifetime->tv_nsec = 0;
611 token_lifetime->clock_type = GPR_TIMESPAN;
612 if (*token_md != NULL) grpc_credentials_md_store_unref(*token_md);
613 *token_md = grpc_credentials_md_store_create(1);
614 grpc_credentials_md_store_add_cstrings(
615 *token_md, GRPC_AUTHORIZATION_METADATA_KEY, new_access_token);
616 status = GRPC_CREDENTIALS_OK;
617 }
618
619 end:
620 if (status != GRPC_CREDENTIALS_OK && (*token_md != NULL)) {
621 grpc_credentials_md_store_unref(*token_md);
622 *token_md = NULL;
623 }
624 if (null_terminated_body != NULL) gpr_free(null_terminated_body);
625 if (new_access_token != NULL) gpr_free(new_access_token);
626 if (json != NULL) grpc_json_destroy(json);
627 return status;
628 }
629
630 static void on_oauth2_token_fetcher_http_response(
631 grpc_exec_ctx *exec_ctx, void *user_data,
632 const grpc_httpcli_response *response) {
633 grpc_credentials_metadata_request *r =
634 (grpc_credentials_metadata_request *)user_data;
635 grpc_oauth2_token_fetcher_credentials *c =
636 (grpc_oauth2_token_fetcher_credentials *)r->creds;
637 gpr_timespec token_lifetime;
638 grpc_credentials_status status;
639
640 gpr_mu_lock(&c->mu);
641 status = grpc_oauth2_token_fetcher_credentials_parse_server_response(
642 response, &c->access_token_md, &token_lifetime);
643 if (status == GRPC_CREDENTIALS_OK) {
644 c->token_expiration =
645 gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), token_lifetime);
646 r->cb(exec_ctx, r->user_data, c->access_token_md->entries,
647 c->access_token_md->num_entries, status);
648 } else {
649 c->token_expiration = gpr_inf_past(GPR_CLOCK_REALTIME);
650 r->cb(exec_ctx, r->user_data, NULL, 0, status);
651 }
652 gpr_mu_unlock(&c->mu);
653 grpc_credentials_metadata_request_destroy(r);
654 }
655
656 static void oauth2_token_fetcher_get_request_metadata(
657 grpc_exec_ctx *exec_ctx, grpc_call_credentials *creds,
658 grpc_pollset *pollset, grpc_auth_metadata_context context,
659 grpc_credentials_metadata_cb cb, void *user_data) {
660 grpc_oauth2_token_fetcher_credentials *c =
661 (grpc_oauth2_token_fetcher_credentials *)creds;
662 gpr_timespec refresh_threshold = gpr_time_from_seconds(
663 GRPC_SECURE_TOKEN_REFRESH_THRESHOLD_SECS, GPR_TIMESPAN);
664 grpc_credentials_md_store *cached_access_token_md = NULL;
665 {
666 gpr_mu_lock(&c->mu);
667 if (c->access_token_md != NULL &&
668 (gpr_time_cmp(
669 gpr_time_sub(c->token_expiration, gpr_now(GPR_CLOCK_REALTIME)),
670 refresh_threshold) > 0)) {
671 cached_access_token_md =
672 grpc_credentials_md_store_ref(c->access_token_md);
673 }
674 gpr_mu_unlock(&c->mu);
675 }
676 if (cached_access_token_md != NULL) {
677 cb(exec_ctx, user_data, cached_access_token_md->entries,
678 cached_access_token_md->num_entries, GRPC_CREDENTIALS_OK);
679 grpc_credentials_md_store_unref(cached_access_token_md);
680 } else {
681 c->fetch_func(
682 exec_ctx,
683 grpc_credentials_metadata_request_create(creds, cb, user_data),
684 &c->httpcli_context, pollset, on_oauth2_token_fetcher_http_response,
685 gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), refresh_threshold));
686 }
687 }
688
689 static void init_oauth2_token_fetcher(grpc_oauth2_token_fetcher_credentials *c,
690 grpc_fetch_oauth2_func fetch_func) {
691 memset(c, 0, sizeof(grpc_oauth2_token_fetcher_credentials));
692 c->base.type = GRPC_CALL_CREDENTIALS_TYPE_OAUTH2;
693 gpr_ref_init(&c->base.refcount, 1);
694 gpr_mu_init(&c->mu);
695 c->token_expiration = gpr_inf_past(GPR_CLOCK_REALTIME);
696 c->fetch_func = fetch_func;
697 grpc_httpcli_context_init(&c->httpcli_context);
698 }
699
700 /* -- GoogleComputeEngine credentials. -- */
701
702 static grpc_call_credentials_vtable compute_engine_vtable = {
703 oauth2_token_fetcher_destruct, oauth2_token_fetcher_get_request_metadata};
704
705 static void compute_engine_fetch_oauth2(
706 grpc_exec_ctx *exec_ctx, grpc_credentials_metadata_request *metadata_req,
707 grpc_httpcli_context *httpcli_context, grpc_pollset *pollset,
708 grpc_httpcli_response_cb response_cb, gpr_timespec deadline) {
709 grpc_httpcli_header header = {"Metadata-Flavor", "Google"};
710 grpc_httpcli_request request;
711 memset(&request, 0, sizeof(grpc_httpcli_request));
712 request.host = GRPC_COMPUTE_ENGINE_METADATA_HOST;
713 request.path = GRPC_COMPUTE_ENGINE_METADATA_TOKEN_PATH;
714 request.hdr_count = 1;
715 request.hdrs = &header;
716 grpc_httpcli_get(exec_ctx, httpcli_context, pollset, &request, deadline,
717 response_cb, metadata_req);
718 }
719
720 grpc_call_credentials *grpc_google_compute_engine_credentials_create(
721 void *reserved) {
722 grpc_oauth2_token_fetcher_credentials *c =
723 gpr_malloc(sizeof(grpc_oauth2_token_fetcher_credentials));
724 GRPC_API_TRACE("grpc_compute_engine_credentials_create(reserved=%p)", 1,
725 (reserved));
726 GPR_ASSERT(reserved == NULL);
727 init_oauth2_token_fetcher(c, compute_engine_fetch_oauth2);
728 c->base.vtable = &compute_engine_vtable;
729 return &c->base;
730 }
731
732 /* -- GoogleRefreshToken credentials. -- */
733
734 static void refresh_token_destruct(grpc_call_credentials *creds) {
735 grpc_google_refresh_token_credentials *c =
736 (grpc_google_refresh_token_credentials *)creds;
737 grpc_auth_refresh_token_destruct(&c->refresh_token);
738 oauth2_token_fetcher_destruct(&c->base.base);
739 }
740
741 static grpc_call_credentials_vtable refresh_token_vtable = {
742 refresh_token_destruct, oauth2_token_fetcher_get_request_metadata};
743
744 static void refresh_token_fetch_oauth2(
745 grpc_exec_ctx *exec_ctx, grpc_credentials_metadata_request *metadata_req,
746 grpc_httpcli_context *httpcli_context, grpc_pollset *pollset,
747 grpc_httpcli_response_cb response_cb, gpr_timespec deadline) {
748 grpc_google_refresh_token_credentials *c =
749 (grpc_google_refresh_token_credentials *)metadata_req->creds;
750 grpc_httpcli_header header = {"Content-Type",
751 "application/x-www-form-urlencoded"};
752 grpc_httpcli_request request;
753 char *body = NULL;
754 gpr_asprintf(&body, GRPC_REFRESH_TOKEN_POST_BODY_FORMAT_STRING,
755 c->refresh_token.client_id, c->refresh_token.client_secret,
756 c->refresh_token.refresh_token);
757 memset(&request, 0, sizeof(grpc_httpcli_request));
758 request.host = GRPC_GOOGLE_OAUTH2_SERVICE_HOST;
759 request.path = GRPC_GOOGLE_OAUTH2_SERVICE_TOKEN_PATH;
760 request.hdr_count = 1;
761 request.hdrs = &header;
762 request.handshaker = &grpc_httpcli_ssl;
763 grpc_httpcli_post(exec_ctx, httpcli_context, pollset, &request, body,
764 strlen(body), deadline, response_cb, metadata_req);
765 gpr_free(body);
766 }
767
768 grpc_call_credentials *
769 grpc_refresh_token_credentials_create_from_auth_refresh_token(
770 grpc_auth_refresh_token refresh_token) {
771 grpc_google_refresh_token_credentials *c;
772 if (!grpc_auth_refresh_token_is_valid(&refresh_token)) {
773 gpr_log(GPR_ERROR, "Invalid input for refresh token credentials creation");
774 return NULL;
775 }
776 c = gpr_malloc(sizeof(grpc_google_refresh_token_credentials));
777 memset(c, 0, sizeof(grpc_google_refresh_token_credentials));
778 init_oauth2_token_fetcher(&c->base, refresh_token_fetch_oauth2);
779 c->base.base.vtable = &refresh_token_vtable;
780 c->refresh_token = refresh_token;
781 return &c->base.base;
782 }
783
784 grpc_call_credentials *grpc_google_refresh_token_credentials_create(
785 const char *json_refresh_token, void *reserved) {
786 GRPC_API_TRACE(
787 "grpc_refresh_token_credentials_create(json_refresh_token=%s, "
788 "reserved=%p)",
789 2, (json_refresh_token, reserved));
790 GPR_ASSERT(reserved == NULL);
791 return grpc_refresh_token_credentials_create_from_auth_refresh_token(
792 grpc_auth_refresh_token_create_from_string(json_refresh_token));
793 }
794
795 /* -- Metadata-only credentials. -- */
796
797 static void md_only_test_destruct(grpc_call_credentials *creds) {
798 grpc_md_only_test_credentials *c = (grpc_md_only_test_credentials *)creds;
799 grpc_credentials_md_store_unref(c->md_store);
800 }
801
802 static void on_simulated_token_fetch_done(grpc_exec_ctx *exec_ctx,
803 void *user_data, bool success) {
804 grpc_credentials_metadata_request *r =
805 (grpc_credentials_metadata_request *)user_data;
806 grpc_md_only_test_credentials *c = (grpc_md_only_test_credentials *)r->creds;
807 r->cb(exec_ctx, r->user_data, c->md_store->entries, c->md_store->num_entries,
808 GRPC_CREDENTIALS_OK);
809 grpc_credentials_metadata_request_destroy(r);
810 }
811
812 static void md_only_test_get_request_metadata(
813 grpc_exec_ctx *exec_ctx, grpc_call_credentials *creds,
814 grpc_pollset *pollset, grpc_auth_metadata_context context,
815 grpc_credentials_metadata_cb cb, void *user_data) {
816 grpc_md_only_test_credentials *c = (grpc_md_only_test_credentials *)creds;
817
818 if (c->is_async) {
819 grpc_credentials_metadata_request *cb_arg =
820 grpc_credentials_metadata_request_create(creds, cb, user_data);
821 grpc_executor_enqueue(
822 grpc_closure_create(on_simulated_token_fetch_done, cb_arg), true);
823 } else {
824 cb(exec_ctx, user_data, c->md_store->entries, 1, GRPC_CREDENTIALS_OK);
825 }
826 }
827
828 static grpc_call_credentials_vtable md_only_test_vtable = {
829 md_only_test_destruct, md_only_test_get_request_metadata};
830
831 grpc_call_credentials *grpc_md_only_test_credentials_create(
832 const char *md_key, const char *md_value, int is_async) {
833 grpc_md_only_test_credentials *c =
834 gpr_malloc(sizeof(grpc_md_only_test_credentials));
835 memset(c, 0, sizeof(grpc_md_only_test_credentials));
836 c->base.type = GRPC_CALL_CREDENTIALS_TYPE_OAUTH2;
837 c->base.vtable = &md_only_test_vtable;
838 gpr_ref_init(&c->base.refcount, 1);
839 c->md_store = grpc_credentials_md_store_create(1);
840 grpc_credentials_md_store_add_cstrings(c->md_store, md_key, md_value);
841 c->is_async = is_async;
842 return &c->base;
843 }
844
845 /* -- Oauth2 Access Token credentials. -- */
846
847 static void access_token_destruct(grpc_call_credentials *creds) {
848 grpc_access_token_credentials *c = (grpc_access_token_credentials *)creds;
849 grpc_credentials_md_store_unref(c->access_token_md);
850 }
851
852 static void access_token_get_request_metadata(
853 grpc_exec_ctx *exec_ctx, grpc_call_credentials *creds,
854 grpc_pollset *pollset, grpc_auth_metadata_context context,
855 grpc_credentials_metadata_cb cb, void *user_data) {
856 grpc_access_token_credentials *c = (grpc_access_token_credentials *)creds;
857 cb(exec_ctx, user_data, c->access_token_md->entries, 1, GRPC_CREDENTIALS_OK);
858 }
859
860 static grpc_call_credentials_vtable access_token_vtable = {
861 access_token_destruct, access_token_get_request_metadata};
862
863 grpc_call_credentials *grpc_access_token_credentials_create(
864 const char *access_token, void *reserved) {
865 grpc_access_token_credentials *c =
866 gpr_malloc(sizeof(grpc_access_token_credentials));
867 char *token_md_value;
868 GRPC_API_TRACE(
869 "grpc_access_token_credentials_create(access_token=%s, "
870 "reserved=%p)",
871 2, (access_token, reserved));
872 GPR_ASSERT(reserved == NULL);
873 memset(c, 0, sizeof(grpc_access_token_credentials));
874 c->base.type = GRPC_CALL_CREDENTIALS_TYPE_OAUTH2;
875 c->base.vtable = &access_token_vtable;
876 gpr_ref_init(&c->base.refcount, 1);
877 c->access_token_md = grpc_credentials_md_store_create(1);
878 gpr_asprintf(&token_md_value, "Bearer %s", access_token);
879 grpc_credentials_md_store_add_cstrings(
880 c->access_token_md, GRPC_AUTHORIZATION_METADATA_KEY, token_md_value);
881 gpr_free(token_md_value);
882 return &c->base;
883 }
884
885 /* -- Fake transport security credentials. -- */
886
887 static grpc_security_status fake_transport_security_create_security_connector(
888 grpc_channel_credentials *c, grpc_call_credentials *call_creds,
889 const char *target, const grpc_channel_args *args,
890 grpc_channel_security_connector **sc, grpc_channel_args **new_args) {
891 *sc = grpc_fake_channel_security_connector_create(call_creds);
892 return GRPC_SECURITY_OK;
893 }
894
895 static grpc_security_status
896 fake_transport_security_server_create_security_connector(
897 grpc_server_credentials *c, grpc_server_security_connector **sc) {
898 *sc = grpc_fake_server_security_connector_create();
899 return GRPC_SECURITY_OK;
900 }
901
902 static grpc_channel_credentials_vtable
903 fake_transport_security_credentials_vtable = {
904 NULL, fake_transport_security_create_security_connector};
905
906 static grpc_server_credentials_vtable
907 fake_transport_security_server_credentials_vtable = {
908 NULL, fake_transport_security_server_create_security_connector};
909
910 grpc_channel_credentials *grpc_fake_transport_security_credentials_create(
911 void) {
912 grpc_channel_credentials *c = gpr_malloc(sizeof(grpc_channel_credentials));
913 memset(c, 0, sizeof(grpc_channel_credentials));
914 c->type = GRPC_CHANNEL_CREDENTIALS_TYPE_FAKE_TRANSPORT_SECURITY;
915 c->vtable = &fake_transport_security_credentials_vtable;
916 gpr_ref_init(&c->refcount, 1);
917 return c;
918 }
919
920 grpc_server_credentials *grpc_fake_transport_security_server_credentials_create(
921 void) {
922 grpc_server_credentials *c = gpr_malloc(sizeof(grpc_server_credentials));
923 memset(c, 0, sizeof(grpc_server_credentials));
924 c->type = GRPC_CHANNEL_CREDENTIALS_TYPE_FAKE_TRANSPORT_SECURITY;
925 gpr_ref_init(&c->refcount, 1);
926 c->vtable = &fake_transport_security_server_credentials_vtable;
927 return c;
928 }
929
930 /* -- Composite call credentials. -- */
931
932 typedef struct {
933 grpc_composite_call_credentials *composite_creds;
934 size_t creds_index;
935 grpc_credentials_md_store *md_elems;
936 grpc_auth_metadata_context auth_md_context;
937 void *user_data;
938 grpc_pollset *pollset;
939 grpc_credentials_metadata_cb cb;
940 } grpc_composite_call_credentials_metadata_context;
941
942 static void composite_call_destruct(grpc_call_credentials *creds) {
943 grpc_composite_call_credentials *c = (grpc_composite_call_credentials *)creds;
944 size_t i;
945 for (i = 0; i < c->inner.num_creds; i++) {
946 grpc_call_credentials_unref(c->inner.creds_array[i]);
947 }
948 gpr_free(c->inner.creds_array);
949 }
950
951 static void composite_call_md_context_destroy(
952 grpc_composite_call_credentials_metadata_context *ctx) {
953 grpc_credentials_md_store_unref(ctx->md_elems);
954 gpr_free(ctx);
955 }
956
957 static void composite_call_metadata_cb(grpc_exec_ctx *exec_ctx, void *user_data,
958 grpc_credentials_md *md_elems,
959 size_t num_md,
960 grpc_credentials_status status) {
961 grpc_composite_call_credentials_metadata_context *ctx =
962 (grpc_composite_call_credentials_metadata_context *)user_data;
963 if (status != GRPC_CREDENTIALS_OK) {
964 ctx->cb(exec_ctx, ctx->user_data, NULL, 0, status);
965 return;
966 }
967
968 /* Copy the metadata in the context. */
969 if (num_md > 0) {
970 size_t i;
971 for (i = 0; i < num_md; i++) {
972 grpc_credentials_md_store_add(ctx->md_elems, md_elems[i].key,
973 md_elems[i].value);
974 }
975 }
976
977 /* See if we need to get some more metadata. */
978 if (ctx->creds_index < ctx->composite_creds->inner.num_creds) {
979 grpc_call_credentials *inner_creds =
980 ctx->composite_creds->inner.creds_array[ctx->creds_index++];
981 grpc_call_credentials_get_request_metadata(
982 exec_ctx, inner_creds, ctx->pollset, ctx->auth_md_context,
983 composite_call_metadata_cb, ctx);
984 return;
985 }
986
987 /* We're done!. */
988 ctx->cb(exec_ctx, ctx->user_data, ctx->md_elems->entries,
989 ctx->md_elems->num_entries, GRPC_CREDENTIALS_OK);
990 composite_call_md_context_destroy(ctx);
991 }
992
993 static void composite_call_get_request_metadata(
994 grpc_exec_ctx *exec_ctx, grpc_call_credentials *creds,
995 grpc_pollset *pollset, grpc_auth_metadata_context auth_md_context,
996 grpc_credentials_metadata_cb cb, void *user_data) {
997 grpc_composite_call_credentials *c = (grpc_composite_call_credentials *)creds;
998 grpc_composite_call_credentials_metadata_context *ctx;
999
1000 ctx = gpr_malloc(sizeof(grpc_composite_call_credentials_metadata_context));
1001 memset(ctx, 0, sizeof(grpc_composite_call_credentials_metadata_context));
1002 ctx->auth_md_context = auth_md_context;
1003 ctx->user_data = user_data;
1004 ctx->cb = cb;
1005 ctx->composite_creds = c;
1006 ctx->pollset = pollset;
1007 ctx->md_elems = grpc_credentials_md_store_create(c->inner.num_creds);
1008 grpc_call_credentials_get_request_metadata(
1009 exec_ctx, c->inner.creds_array[ctx->creds_index++], pollset,
1010 auth_md_context, composite_call_metadata_cb, ctx);
1011 }
1012
1013 static grpc_call_credentials_vtable composite_call_credentials_vtable = {
1014 composite_call_destruct, composite_call_get_request_metadata};
1015
1016 static grpc_call_credentials_array get_creds_array(
1017 grpc_call_credentials **creds_addr) {
1018 grpc_call_credentials_array result;
1019 grpc_call_credentials *creds = *creds_addr;
1020 result.creds_array = creds_addr;
1021 result.num_creds = 1;
1022 if (strcmp(creds->type, GRPC_CALL_CREDENTIALS_TYPE_COMPOSITE) == 0) {
1023 result = *grpc_composite_call_credentials_get_credentials(creds);
1024 }
1025 return result;
1026 }
1027
1028 grpc_call_credentials *grpc_composite_call_credentials_create(
1029 grpc_call_credentials *creds1, grpc_call_credentials *creds2,
1030 void *reserved) {
1031 size_t i;
1032 size_t creds_array_byte_size;
1033 grpc_call_credentials_array creds1_array;
1034 grpc_call_credentials_array creds2_array;
1035 grpc_composite_call_credentials *c;
1036 GRPC_API_TRACE(
1037 "grpc_composite_call_credentials_create(creds1=%p, creds2=%p, "
1038 "reserved=%p)",
1039 3, (creds1, creds2, reserved));
1040 GPR_ASSERT(reserved == NULL);
1041 GPR_ASSERT(creds1 != NULL);
1042 GPR_ASSERT(creds2 != NULL);
1043 c = gpr_malloc(sizeof(grpc_composite_call_credentials));
1044 memset(c, 0, sizeof(grpc_composite_call_credentials));
1045 c->base.type = GRPC_CALL_CREDENTIALS_TYPE_COMPOSITE;
1046 c->base.vtable = &composite_call_credentials_vtable;
1047 gpr_ref_init(&c->base.refcount, 1);
1048 creds1_array = get_creds_array(&creds1);
1049 creds2_array = get_creds_array(&creds2);
1050 c->inner.num_creds = creds1_array.num_creds + creds2_array.num_creds;
1051 creds_array_byte_size = c->inner.num_creds * sizeof(grpc_call_credentials *);
1052 c->inner.creds_array = gpr_malloc(creds_array_byte_size);
1053 memset(c->inner.creds_array, 0, creds_array_byte_size);
1054 for (i = 0; i < creds1_array.num_creds; i++) {
1055 grpc_call_credentials *cur_creds = creds1_array.creds_array[i];
1056 c->inner.creds_array[i] = grpc_call_credentials_ref(cur_creds);
1057 }
1058 for (i = 0; i < creds2_array.num_creds; i++) {
1059 grpc_call_credentials *cur_creds = creds2_array.creds_array[i];
1060 c->inner.creds_array[i + creds1_array.num_creds] =
1061 grpc_call_credentials_ref(cur_creds);
1062 }
1063 return &c->base;
1064 }
1065
1066 const grpc_call_credentials_array *
1067 grpc_composite_call_credentials_get_credentials(grpc_call_credentials *creds) {
1068 const grpc_composite_call_credentials *c =
1069 (const grpc_composite_call_credentials *)creds;
1070 GPR_ASSERT(strcmp(creds->type, GRPC_CALL_CREDENTIALS_TYPE_COMPOSITE) == 0);
1071 return &c->inner;
1072 }
1073
1074 grpc_call_credentials *grpc_credentials_contains_type(
1075 grpc_call_credentials *creds, const char *type,
1076 grpc_call_credentials **composite_creds) {
1077 size_t i;
1078 if (strcmp(creds->type, type) == 0) {
1079 if (composite_creds != NULL) *composite_creds = NULL;
1080 return creds;
1081 } else if (strcmp(creds->type, GRPC_CALL_CREDENTIALS_TYPE_COMPOSITE) == 0) {
1082 const grpc_call_credentials_array *inner_creds_array =
1083 grpc_composite_call_credentials_get_credentials(creds);
1084 for (i = 0; i < inner_creds_array->num_creds; i++) {
1085 if (strcmp(type, inner_creds_array->creds_array[i]->type) == 0) {
1086 if (composite_creds != NULL) *composite_creds = creds;
1087 return inner_creds_array->creds_array[i];
1088 }
1089 }
1090 }
1091 return NULL;
1092 }
1093
1094 /* -- IAM credentials. -- */
1095
1096 static void iam_destruct(grpc_call_credentials *creds) {
1097 grpc_google_iam_credentials *c = (grpc_google_iam_credentials *)creds;
1098 grpc_credentials_md_store_unref(c->iam_md);
1099 }
1100
1101 static void iam_get_request_metadata(grpc_exec_ctx *exec_ctx,
1102 grpc_call_credentials *creds,
1103 grpc_pollset *pollset,
1104 grpc_auth_metadata_context context,
1105 grpc_credentials_metadata_cb cb,
1106 void *user_data) {
1107 grpc_google_iam_credentials *c = (grpc_google_iam_credentials *)creds;
1108 cb(exec_ctx, user_data, c->iam_md->entries, c->iam_md->num_entries,
1109 GRPC_CREDENTIALS_OK);
1110 }
1111
1112 static grpc_call_credentials_vtable iam_vtable = {iam_destruct,
1113 iam_get_request_metadata};
1114
1115 grpc_call_credentials *grpc_google_iam_credentials_create(
1116 const char *token, const char *authority_selector, void *reserved) {
1117 grpc_google_iam_credentials *c;
1118 GRPC_API_TRACE(
1119 "grpc_iam_credentials_create(token=%s, authority_selector=%s, "
1120 "reserved=%p)",
1121 3, (token, authority_selector, reserved));
1122 GPR_ASSERT(reserved == NULL);
1123 GPR_ASSERT(token != NULL);
1124 GPR_ASSERT(authority_selector != NULL);
1125 c = gpr_malloc(sizeof(grpc_google_iam_credentials));
1126 memset(c, 0, sizeof(grpc_google_iam_credentials));
1127 c->base.type = GRPC_CALL_CREDENTIALS_TYPE_IAM;
1128 c->base.vtable = &iam_vtable;
1129 gpr_ref_init(&c->base.refcount, 1);
1130 c->iam_md = grpc_credentials_md_store_create(2);
1131 grpc_credentials_md_store_add_cstrings(
1132 c->iam_md, GRPC_IAM_AUTHORIZATION_TOKEN_METADATA_KEY, token);
1133 grpc_credentials_md_store_add_cstrings(
1134 c->iam_md, GRPC_IAM_AUTHORITY_SELECTOR_METADATA_KEY, authority_selector);
1135 return &c->base;
1136 }
1137
1138 /* -- Plugin credentials. -- */
1139
1140 typedef struct {
1141 void *user_data;
1142 grpc_credentials_metadata_cb cb;
1143 } grpc_metadata_plugin_request;
1144
1145 static void plugin_destruct(grpc_call_credentials *creds) {
1146 grpc_plugin_credentials *c = (grpc_plugin_credentials *)creds;
1147 if (c->plugin.state != NULL && c->plugin.destroy != NULL) {
1148 c->plugin.destroy(c->plugin.state);
1149 }
1150 }
1151
1152 static void plugin_md_request_metadata_ready(void *request,
1153 const grpc_metadata *md,
1154 size_t num_md,
1155 grpc_status_code status,
1156 const char *error_details) {
1157 /* called from application code */
1158 grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
1159 grpc_metadata_plugin_request *r = (grpc_metadata_plugin_request *)request;
1160 if (status != GRPC_STATUS_OK) {
1161 if (error_details != NULL) {
1162 gpr_log(GPR_ERROR, "Getting metadata from plugin failed with error: %s",
1163 error_details);
1164 }
1165 r->cb(&exec_ctx, r->user_data, NULL, 0, GRPC_CREDENTIALS_ERROR);
1166 } else {
1167 size_t i;
1168 grpc_credentials_md *md_array = NULL;
1169 if (num_md > 0) {
1170 md_array = gpr_malloc(num_md * sizeof(grpc_credentials_md));
1171 for (i = 0; i < num_md; i++) {
1172 md_array[i].key = gpr_slice_from_copied_string(md[i].key);
1173 md_array[i].value =
1174 gpr_slice_from_copied_buffer(md[i].value, md[i].value_length);
1175 }
1176 }
1177 r->cb(&exec_ctx, r->user_data, md_array, num_md, GRPC_CREDENTIALS_OK);
1178 if (md_array != NULL) {
1179 for (i = 0; i < num_md; i++) {
1180 gpr_slice_unref(md_array[i].key);
1181 gpr_slice_unref(md_array[i].value);
1182 }
1183 gpr_free(md_array);
1184 }
1185 }
1186 gpr_free(r);
1187 grpc_exec_ctx_finish(&exec_ctx);
1188 }
1189
1190 static void plugin_get_request_metadata(grpc_exec_ctx *exec_ctx,
1191 grpc_call_credentials *creds,
1192 grpc_pollset *pollset,
1193 grpc_auth_metadata_context context,
1194 grpc_credentials_metadata_cb cb,
1195 void *user_data) {
1196 grpc_plugin_credentials *c = (grpc_plugin_credentials *)creds;
1197 if (c->plugin.get_metadata != NULL) {
1198 grpc_metadata_plugin_request *request = gpr_malloc(sizeof(*request));
1199 memset(request, 0, sizeof(*request));
1200 request->user_data = user_data;
1201 request->cb = cb;
1202 c->plugin.get_metadata(c->plugin.state, context,
1203 plugin_md_request_metadata_ready, request);
1204 } else {
1205 cb(exec_ctx, user_data, NULL, 0, GRPC_CREDENTIALS_OK);
1206 }
1207 }
1208
1209 static grpc_call_credentials_vtable plugin_vtable = {
1210 plugin_destruct, plugin_get_request_metadata};
1211
1212 grpc_call_credentials *grpc_metadata_credentials_create_from_plugin(
1213 grpc_metadata_credentials_plugin plugin, void *reserved) {
1214 grpc_plugin_credentials *c = gpr_malloc(sizeof(*c));
1215 GRPC_API_TRACE("grpc_metadata_credentials_create_from_plugin(reserved=%p)", 1,
1216 (reserved));
1217 GPR_ASSERT(reserved == NULL);
1218 memset(c, 0, sizeof(*c));
1219 c->base.type = plugin.type;
1220 c->base.vtable = &plugin_vtable;
1221 gpr_ref_init(&c->base.refcount, 1);
1222 c->plugin = plugin;
1223 return &c->base;
1224 }
1225
1226 /* -- Composite channel credentials. -- */
1227
1228 static void composite_channel_destruct(grpc_channel_credentials *creds) {
1229 grpc_composite_channel_credentials *c =
1230 (grpc_composite_channel_credentials *)creds;
1231 grpc_channel_credentials_unref(c->inner_creds);
1232 grpc_call_credentials_unref(c->call_creds);
1233 }
1234
1235 static grpc_security_status composite_channel_create_security_connector(
1236 grpc_channel_credentials *creds, grpc_call_credentials *call_creds,
1237 const char *target, const grpc_channel_args *args,
1238 grpc_channel_security_connector **sc, grpc_channel_args **new_args) {
1239 grpc_composite_channel_credentials *c =
1240 (grpc_composite_channel_credentials *)creds;
1241 grpc_security_status status = GRPC_SECURITY_ERROR;
1242
1243 GPR_ASSERT(c->inner_creds != NULL && c->call_creds != NULL &&
1244 c->inner_creds->vtable != NULL &&
1245 c->inner_creds->vtable->create_security_connector != NULL);
1246 /* If we are passed a call_creds, create a call composite to pass it
1247 downstream. */
1248 if (call_creds != NULL) {
1249 grpc_call_credentials *composite_call_creds =
1250 grpc_composite_call_credentials_create(c->call_creds, call_creds, NULL);
1251 status = c->inner_creds->vtable->create_security_connector(
1252 c->inner_creds, composite_call_creds, target, args, sc, new_args);
1253 grpc_call_credentials_unref(composite_call_creds);
1254 } else {
1255 status = c->inner_creds->vtable->create_security_connector(
1256 c->inner_creds, c->call_creds, target, args, sc, new_args);
1257 }
1258 return status;
1259 }
1260
1261 static grpc_channel_credentials_vtable composite_channel_credentials_vtable = {
1262 composite_channel_destruct, composite_channel_create_security_connector};
1263
1264 grpc_channel_credentials *grpc_composite_channel_credentials_create(
1265 grpc_channel_credentials *channel_creds, grpc_call_credentials *call_creds,
1266 void *reserved) {
1267 grpc_composite_channel_credentials *c = gpr_malloc(sizeof(*c));
1268 memset(c, 0, sizeof(*c));
1269 GPR_ASSERT(channel_creds != NULL && call_creds != NULL && reserved == NULL);
1270 GRPC_API_TRACE(
1271 "grpc_composite_channel_credentials_create(channel_creds=%p, "
1272 "call_creds=%p, reserved=%p)",
1273 3, (channel_creds, call_creds, reserved));
1274 c->base.type = channel_creds->type;
1275 c->base.vtable = &composite_channel_credentials_vtable;
1276 gpr_ref_init(&c->base.refcount, 1);
1277 c->inner_creds = grpc_channel_credentials_ref(channel_creds);
1278 c->call_creds = grpc_call_credentials_ref(call_creds);
1279 return &c->base;
1280 }
OLDNEW
« no previous file with comments | « third_party/grpc/src/core/security/credentials.h ('k') | third_party/grpc/src/core/security/credentials_metadata.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698