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