blob: bf570d91b3ed7d3a29055634451bf7b286be252c [file] [log] [blame]
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001/*
2 *
Craig Tiller06059952015-02-18 08:34:56 -08003 * Copyright 2015, Google Inc.
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08004 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above
13 * copyright notice, this list of conditions and the following disclaimer
14 * in the documentation and/or other materials provided with the
15 * distribution.
16 * * Neither the name of Google Inc. nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 */
33
34#include "src/core/security/credentials.h"
35
Julien Boeuff47a5cb2015-02-18 12:24:08 -080036#include <string.h>
37#include <stdio.h>
38
Julien Boeuf7d1d9ca2015-04-17 14:38:48 -070039#include "src/core/channel/channel_args.h"
40#include "src/core/channel/http_client_filter.h"
Julien Boeuff47a5cb2015-02-18 12:24:08 -080041#include "src/core/json/json.h"
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080042#include "src/core/httpcli/httpcli.h"
ctiller18b49ab2014-12-09 14:39:16 -080043#include "src/core/iomgr/iomgr.h"
Craig Tiller485d7762015-01-23 12:54:05 -080044#include "src/core/support/string.h"
Julien Boeuf7d1d9ca2015-04-17 14:38:48 -070045
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080046#include <grpc/support/alloc.h>
47#include <grpc/support/log.h>
Masood Malekghassemi701af602015-06-03 15:01:17 -070048#include <grpc/support/string_util.h>
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080049#include <grpc/support/sync.h>
Craig Tiller8664ca62015-09-09 12:30:59 -070050#include <grpc/support/thd.h>
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080051#include <grpc/support/time.h>
52
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080053/* -- Common. -- */
54
Craig Tillera82950e2015-09-22 12:33:20 -070055struct grpc_credentials_metadata_request {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080056 grpc_credentials *creds;
57 grpc_credentials_metadata_cb cb;
58 void *user_data;
Julien Boeufb037bb62015-07-08 14:58:14 -070059};
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080060
61static grpc_credentials_metadata_request *
Craig Tillera82950e2015-09-22 12:33:20 -070062grpc_credentials_metadata_request_create(grpc_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_credentials_ref(creds);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080068 r->cb = cb;
69 r->user_data = user_data;
70 return r;
71}
72
Craig Tillera82950e2015-09-22 12:33:20 -070073static void grpc_credentials_metadata_request_destroy(
74 grpc_credentials_metadata_request *r) {
75 grpc_credentials_unref(r->creds);
76 gpr_free(r);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080077}
78
Craig Tillera82950e2015-09-22 12:33:20 -070079grpc_credentials *grpc_credentials_ref(grpc_credentials *creds) {
80 if (creds == NULL) return NULL;
81 gpr_ref(&creds->refcount);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080082 return creds;
83}
84
Craig Tillera82950e2015-09-22 12:33:20 -070085void grpc_credentials_unref(grpc_credentials *creds) {
86 if (creds == NULL) return;
87 if (gpr_unref(&creds->refcount)) {
88 creds->vtable->destruct(creds);
89 gpr_free(creds);
90 }
91}
92
93void grpc_credentials_release(grpc_credentials *creds) {
94 grpc_credentials_unref(creds);
95}
96
97int grpc_credentials_has_request_metadata(grpc_credentials *creds) {
98 if (creds == NULL) return 0;
99 return creds->vtable->has_request_metadata(creds);
100}
101
102int grpc_credentials_has_request_metadata_only(grpc_credentials *creds) {
103 if (creds == NULL) return 0;
104 return creds->vtable->has_request_metadata_only(creds);
105}
106
107void grpc_credentials_get_request_metadata(
108 grpc_exec_ctx *exec_ctx, grpc_credentials *creds, grpc_pollset *pollset,
109 const char *service_url, grpc_credentials_metadata_cb cb, void *user_data) {
110 if (creds == NULL || !grpc_credentials_has_request_metadata(creds) ||
111 creds->vtable->get_request_metadata == NULL) {
112 if (cb != NULL) {
113 cb(exec_ctx, user_data, NULL, 0, GRPC_CREDENTIALS_OK);
114 }
nnoble0c475f02014-12-05 15:37:39 -0800115 return;
Craig Tillera82950e2015-09-22 12:33:20 -0700116 }
117 creds->vtable->get_request_metadata(exec_ctx, creds, pollset, service_url, cb,
118 user_data);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800119}
120
Craig Tillera82950e2015-09-22 12:33:20 -0700121grpc_security_status grpc_credentials_create_security_connector(
122 grpc_credentials *creds, const char *target, const grpc_channel_args *args,
123 grpc_credentials *request_metadata_creds,
124 grpc_channel_security_connector **sc, grpc_channel_args **new_args) {
Julien Boeuf7d1d9ca2015-04-17 14:38:48 -0700125 *new_args = NULL;
Craig Tillera82950e2015-09-22 12:33:20 -0700126 if (creds == NULL || creds->vtable->create_security_connector == NULL ||
127 grpc_credentials_has_request_metadata_only(creds)) {
128 gpr_log(GPR_ERROR,
129 "Invalid credentials for creating a security connector.");
130 return GRPC_SECURITY_ERROR;
131 }
132 return creds->vtable->create_security_connector(
133 creds, target, args, request_metadata_creds, sc, new_args);
Craig Tillerc4885ed2015-04-14 09:51:28 -0700134}
135
Craig Tillera82950e2015-09-22 12:33:20 -0700136grpc_server_credentials *grpc_server_credentials_ref(
137 grpc_server_credentials *creds) {
138 if (creds == NULL) return NULL;
139 gpr_ref(&creds->refcount);
Julien Boeuffe1478f2015-08-30 21:57:38 -0700140 return creds;
141}
142
Craig Tillera82950e2015-09-22 12:33:20 -0700143void grpc_server_credentials_unref(grpc_server_credentials *creds) {
144 if (creds == NULL) return;
145 if (gpr_unref(&creds->refcount)) {
146 creds->vtable->destruct(creds);
147 if (creds->processor.destroy != NULL && creds->processor.state != NULL) {
148 creds->processor.destroy(creds->processor.state);
Julien Boeuffe1478f2015-08-30 21:57:38 -0700149 }
Craig Tillera82950e2015-09-22 12:33:20 -0700150 gpr_free(creds);
151 }
Julien Boeuffe1478f2015-08-30 21:57:38 -0700152}
153
Craig Tillera82950e2015-09-22 12:33:20 -0700154void grpc_server_credentials_release(grpc_server_credentials *creds) {
155 grpc_server_credentials_unref(creds);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800156}
157
Craig Tillera82950e2015-09-22 12:33:20 -0700158grpc_security_status grpc_server_credentials_create_security_connector(
159 grpc_server_credentials *creds, grpc_security_connector **sc) {
160 if (creds == NULL || creds->vtable->create_security_connector == NULL) {
161 gpr_log(GPR_ERROR, "Server credentials cannot create security context.");
162 return GRPC_SECURITY_ERROR;
163 }
164 return creds->vtable->create_security_connector(creds, sc);
Julien Boeuf7d1d9ca2015-04-17 14:38:48 -0700165}
166
Craig Tillera82950e2015-09-22 12:33:20 -0700167void grpc_server_credentials_set_auth_metadata_processor(
168 grpc_server_credentials *creds, grpc_auth_metadata_processor processor) {
169 if (creds == NULL) return;
170 if (creds->processor.destroy != NULL && creds->processor.state != NULL) {
171 creds->processor.destroy(creds->processor.state);
172 }
Julien Boeuf6bdc9b42015-07-19 21:56:02 -0700173 creds->processor = processor;
174}
175
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800176/* -- Ssl credentials. -- */
177
Craig Tillera82950e2015-09-22 12:33:20 -0700178static void ssl_destruct(grpc_credentials *creds) {
179 grpc_ssl_credentials *c = (grpc_ssl_credentials *)creds;
180 if (c->config.pem_root_certs != NULL) gpr_free(c->config.pem_root_certs);
181 if (c->config.pem_private_key != NULL) gpr_free(c->config.pem_private_key);
182 if (c->config.pem_cert_chain != NULL) gpr_free(c->config.pem_cert_chain);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800183}
184
Craig Tillera82950e2015-09-22 12:33:20 -0700185static void ssl_server_destruct(grpc_server_credentials *creds) {
186 grpc_ssl_server_credentials *c = (grpc_ssl_server_credentials *)creds;
Julien Boeuf8fbcc432015-01-15 16:44:13 -0800187 size_t i;
Craig Tillera82950e2015-09-22 12:33:20 -0700188 for (i = 0; i < c->config.num_key_cert_pairs; i++) {
189 if (c->config.pem_private_keys[i] != NULL) {
190 gpr_free(c->config.pem_private_keys[i]);
Julien Boeuf8fbcc432015-01-15 16:44:13 -0800191 }
Craig Tillera82950e2015-09-22 12:33:20 -0700192 if (c->config.pem_cert_chains[i] != NULL) {
193 gpr_free(c->config.pem_cert_chains[i]);
Julien Boeuf8fbcc432015-01-15 16:44:13 -0800194 }
Craig Tillera82950e2015-09-22 12:33:20 -0700195 }
196 if (c->config.pem_private_keys != NULL) gpr_free(c->config.pem_private_keys);
197 if (c->config.pem_private_keys_sizes != NULL) {
198 gpr_free(c->config.pem_private_keys_sizes);
199 }
200 if (c->config.pem_cert_chains != NULL) gpr_free(c->config.pem_cert_chains);
201 if (c->config.pem_cert_chains_sizes != NULL) {
202 gpr_free(c->config.pem_cert_chains_sizes);
203 }
204 if (c->config.pem_root_certs != NULL) gpr_free(c->config.pem_root_certs);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800205}
206
Craig Tillera82950e2015-09-22 12:33:20 -0700207static int ssl_has_request_metadata(const grpc_credentials *creds) { return 0; }
208
209static int ssl_has_request_metadata_only(const grpc_credentials *creds) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800210 return 0;
211}
212
Craig Tillera82950e2015-09-22 12:33:20 -0700213static grpc_security_status ssl_create_security_connector(
214 grpc_credentials *creds, const char *target, const grpc_channel_args *args,
215 grpc_credentials *request_metadata_creds,
216 grpc_channel_security_connector **sc, grpc_channel_args **new_args) {
217 grpc_ssl_credentials *c = (grpc_ssl_credentials *)creds;
Julien Boeuf7d1d9ca2015-04-17 14:38:48 -0700218 grpc_security_status status = GRPC_SECURITY_OK;
219 size_t i = 0;
220 const char *overridden_target_name = NULL;
221 grpc_arg arg;
222
Craig Tillera82950e2015-09-22 12:33:20 -0700223 for (i = 0; args && i < args->num_args; i++) {
224 grpc_arg *arg = &args->args[i];
225 if (strcmp(arg->key, GRPC_SSL_TARGET_NAME_OVERRIDE_ARG) == 0 &&
226 arg->type == GRPC_ARG_STRING) {
227 overridden_target_name = arg->value.string;
228 break;
Julien Boeuf7d1d9ca2015-04-17 14:38:48 -0700229 }
Craig Tillera82950e2015-09-22 12:33:20 -0700230 }
231 status = grpc_ssl_channel_security_connector_create(
232 request_metadata_creds, &c->config, target, overridden_target_name, sc);
233 if (status != GRPC_SECURITY_OK) {
234 return status;
235 }
Julien Boeuf7d1d9ca2015-04-17 14:38:48 -0700236 arg.type = GRPC_ARG_STRING;
237 arg.key = GRPC_ARG_HTTP2_SCHEME;
238 arg.value.string = "https";
Craig Tillera82950e2015-09-22 12:33:20 -0700239 *new_args = grpc_channel_args_copy_and_add(args, &arg, 1);
Julien Boeuf7d1d9ca2015-04-17 14:38:48 -0700240 return status;
241}
242
Craig Tillera82950e2015-09-22 12:33:20 -0700243static grpc_security_status ssl_server_create_security_connector(
244 grpc_server_credentials *creds, grpc_security_connector **sc) {
245 grpc_ssl_server_credentials *c = (grpc_ssl_server_credentials *)creds;
246 return grpc_ssl_server_security_connector_create(&c->config, sc);
Julien Boeuf7d1d9ca2015-04-17 14:38:48 -0700247}
248
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800249static grpc_credentials_vtable ssl_vtable = {
Craig Tillera82950e2015-09-22 12:33:20 -0700250 ssl_destruct, ssl_has_request_metadata, ssl_has_request_metadata_only, NULL,
251 ssl_create_security_connector};
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800252
Julien Boeuf7d1d9ca2015-04-17 14:38:48 -0700253static grpc_server_credentials_vtable ssl_server_vtable = {
Craig Tillera82950e2015-09-22 12:33:20 -0700254 ssl_server_destruct, ssl_server_create_security_connector};
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800255
Craig Tillera82950e2015-09-22 12:33:20 -0700256static void ssl_copy_key_material(const char *input, unsigned char **output,
257 size_t *output_size) {
258 *output_size = strlen(input);
259 *output = gpr_malloc(*output_size);
260 memcpy(*output, input, *output_size);
Julien Boeuf8fbcc432015-01-15 16:44:13 -0800261}
262
Craig Tillera82950e2015-09-22 12:33:20 -0700263static void ssl_build_config(const char *pem_root_certs,
264 grpc_ssl_pem_key_cert_pair *pem_key_cert_pair,
265 grpc_ssl_config *config) {
266 if (pem_root_certs != NULL) {
267 ssl_copy_key_material(pem_root_certs, &config->pem_root_certs,
268 &config->pem_root_certs_size);
269 }
270 if (pem_key_cert_pair != NULL) {
271 GPR_ASSERT(pem_key_cert_pair->private_key != NULL);
272 GPR_ASSERT(pem_key_cert_pair->cert_chain != NULL);
273 ssl_copy_key_material(pem_key_cert_pair->private_key,
274 &config->pem_private_key,
275 &config->pem_private_key_size);
276 ssl_copy_key_material(pem_key_cert_pair->cert_chain,
277 &config->pem_cert_chain,
278 &config->pem_cert_chain_size);
279 }
Julien Boeuf8fbcc432015-01-15 16:44:13 -0800280}
281
Craig Tillera82950e2015-09-22 12:33:20 -0700282static void ssl_build_server_config(
283 const char *pem_root_certs, grpc_ssl_pem_key_cert_pair *pem_key_cert_pairs,
284 size_t num_key_cert_pairs, int force_client_auth,
285 grpc_ssl_server_config *config) {
Julien Boeuf8fbcc432015-01-15 16:44:13 -0800286 size_t i;
Julien Boeuf5029b302015-07-21 23:02:16 -0700287 config->force_client_auth = force_client_auth;
Craig Tillera82950e2015-09-22 12:33:20 -0700288 if (pem_root_certs != NULL) {
289 ssl_copy_key_material(pem_root_certs, &config->pem_root_certs,
290 &config->pem_root_certs_size);
291 }
292 if (num_key_cert_pairs > 0) {
293 GPR_ASSERT(pem_key_cert_pairs != NULL);
294 config->pem_private_keys =
295 gpr_malloc(num_key_cert_pairs * sizeof(unsigned char *));
296 config->pem_cert_chains =
297 gpr_malloc(num_key_cert_pairs * sizeof(unsigned char *));
298 config->pem_private_keys_sizes =
299 gpr_malloc(num_key_cert_pairs * sizeof(size_t));
300 config->pem_cert_chains_sizes =
301 gpr_malloc(num_key_cert_pairs * sizeof(size_t));
302 }
Julien Boeuf8fbcc432015-01-15 16:44:13 -0800303 config->num_key_cert_pairs = num_key_cert_pairs;
Craig Tillera82950e2015-09-22 12:33:20 -0700304 for (i = 0; i < num_key_cert_pairs; i++) {
305 GPR_ASSERT(pem_key_cert_pairs[i].private_key != NULL);
306 GPR_ASSERT(pem_key_cert_pairs[i].cert_chain != NULL);
307 ssl_copy_key_material(pem_key_cert_pairs[i].private_key,
308 &config->pem_private_keys[i],
309 &config->pem_private_keys_sizes[i]);
310 ssl_copy_key_material(pem_key_cert_pairs[i].cert_chain,
311 &config->pem_cert_chains[i],
312 &config->pem_cert_chains_sizes[i]);
313 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800314}
315
Craig Tillera82950e2015-09-22 12:33:20 -0700316grpc_credentials *grpc_ssl_credentials_create(
317 const char *pem_root_certs, grpc_ssl_pem_key_cert_pair *pem_key_cert_pair,
318 void *reserved) {
319 grpc_ssl_credentials *c = gpr_malloc(sizeof(grpc_ssl_credentials));
320 GPR_ASSERT(reserved == NULL);
321 memset(c, 0, sizeof(grpc_ssl_credentials));
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800322 c->base.type = GRPC_CREDENTIALS_TYPE_SSL;
323 c->base.vtable = &ssl_vtable;
Craig Tillera82950e2015-09-22 12:33:20 -0700324 gpr_ref_init(&c->base.refcount, 1);
325 ssl_build_config(pem_root_certs, pem_key_cert_pair, &c->config);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800326 return &c->base;
327}
328
Craig Tillera82950e2015-09-22 12:33:20 -0700329grpc_server_credentials *grpc_ssl_server_credentials_create(
330 const char *pem_root_certs, grpc_ssl_pem_key_cert_pair *pem_key_cert_pairs,
331 size_t num_key_cert_pairs, int force_client_auth, void *reserved) {
332 grpc_ssl_server_credentials *c =
333 gpr_malloc(sizeof(grpc_ssl_server_credentials));
334 GPR_ASSERT(reserved == NULL);
335 memset(c, 0, sizeof(grpc_ssl_server_credentials));
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800336 c->base.type = GRPC_CREDENTIALS_TYPE_SSL;
Craig Tillera82950e2015-09-22 12:33:20 -0700337 gpr_ref_init(&c->base.refcount, 1);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800338 c->base.vtable = &ssl_server_vtable;
Craig Tillera82950e2015-09-22 12:33:20 -0700339 ssl_build_server_config(pem_root_certs, pem_key_cert_pairs,
340 num_key_cert_pairs, force_client_auth, &c->config);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800341 return &c->base;
342}
343
Julien Boeuff47a5cb2015-02-18 12:24:08 -0800344/* -- Jwt credentials -- */
345
Craig Tillera82950e2015-09-22 12:33:20 -0700346static void jwt_reset_cache(grpc_service_account_jwt_access_credentials *c) {
347 if (c->cached.jwt_md != NULL) {
348 grpc_credentials_md_store_unref(c->cached.jwt_md);
349 c->cached.jwt_md = NULL;
350 }
351 if (c->cached.service_url != NULL) {
352 gpr_free(c->cached.service_url);
353 c->cached.service_url = NULL;
354 }
355 c->cached.jwt_expiration = gpr_inf_past(GPR_CLOCK_REALTIME);
Julien Boeuff47a5cb2015-02-18 12:24:08 -0800356}
357
Craig Tillera82950e2015-09-22 12:33:20 -0700358static void jwt_destruct(grpc_credentials *creds) {
359 grpc_service_account_jwt_access_credentials *c =
360 (grpc_service_account_jwt_access_credentials *)creds;
361 grpc_auth_json_key_destruct(&c->key);
362 jwt_reset_cache(c);
363 gpr_mu_destroy(&c->cache_mu);
Julien Boeuff47a5cb2015-02-18 12:24:08 -0800364}
365
Craig Tillera82950e2015-09-22 12:33:20 -0700366static int jwt_has_request_metadata(const grpc_credentials *creds) { return 1; }
367
368static int jwt_has_request_metadata_only(const grpc_credentials *creds) {
Julien Boeuff47a5cb2015-02-18 12:24:08 -0800369 return 1;
370}
371
Craig Tillera82950e2015-09-22 12:33:20 -0700372static void jwt_get_request_metadata(
373 grpc_exec_ctx *exec_ctx, grpc_credentials *creds, grpc_pollset *pollset,
374 const char *service_url, grpc_credentials_metadata_cb cb, void *user_data) {
375 grpc_service_account_jwt_access_credentials *c =
376 (grpc_service_account_jwt_access_credentials *)creds;
377 gpr_timespec refresh_threshold = gpr_time_from_seconds(
378 GRPC_SECURE_TOKEN_REFRESH_THRESHOLD_SECS, GPR_TIMESPAN);
Julien Boeuff47a5cb2015-02-18 12:24:08 -0800379
380 /* See if we can return a cached jwt. */
Julien Boeuf75c9b6f2015-05-29 13:12:12 -0700381 grpc_credentials_md_store *jwt_md = NULL;
Julien Boeuff47a5cb2015-02-18 12:24:08 -0800382 {
Craig Tillera82950e2015-09-22 12:33:20 -0700383 gpr_mu_lock(&c->cache_mu);
384 if (c->cached.service_url != NULL &&
385 strcmp(c->cached.service_url, service_url) == 0 &&
386 c->cached.jwt_md != NULL &&
387 (gpr_time_cmp(gpr_time_sub(c->cached.jwt_expiration,
388 gpr_now(GPR_CLOCK_REALTIME)),
389 refresh_threshold) > 0)) {
390 jwt_md = grpc_credentials_md_store_ref(c->cached.jwt_md);
391 }
392 gpr_mu_unlock(&c->cache_mu);
Julien Boeuff47a5cb2015-02-18 12:24:08 -0800393 }
394
Craig Tillera82950e2015-09-22 12:33:20 -0700395 if (jwt_md == NULL) {
396 char *jwt = NULL;
397 /* Generate a new jwt. */
398 gpr_mu_lock(&c->cache_mu);
399 jwt_reset_cache(c);
400 jwt = grpc_jwt_encode_and_sign(&c->key, service_url, c->jwt_lifetime, NULL);
401 if (jwt != NULL) {
402 char *md_value;
403 gpr_asprintf(&md_value, "Bearer %s", jwt);
404 gpr_free(jwt);
405 c->cached.jwt_expiration =
406 gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), c->jwt_lifetime);
407 c->cached.service_url = gpr_strdup(service_url);
408 c->cached.jwt_md = grpc_credentials_md_store_create(1);
409 grpc_credentials_md_store_add_cstrings(
410 c->cached.jwt_md, GRPC_AUTHORIZATION_METADATA_KEY, md_value);
411 gpr_free(md_value);
412 jwt_md = grpc_credentials_md_store_ref(c->cached.jwt_md);
Julien Boeuff47a5cb2015-02-18 12:24:08 -0800413 }
Craig Tillera82950e2015-09-22 12:33:20 -0700414 gpr_mu_unlock(&c->cache_mu);
415 }
Julien Boeuff47a5cb2015-02-18 12:24:08 -0800416
Craig Tillera82950e2015-09-22 12:33:20 -0700417 if (jwt_md != NULL) {
418 cb(exec_ctx, user_data, jwt_md->entries, jwt_md->num_entries,
419 GRPC_CREDENTIALS_OK);
420 grpc_credentials_md_store_unref(jwt_md);
421 } else {
422 cb(exec_ctx, user_data, NULL, 0, GRPC_CREDENTIALS_ERROR);
423 }
Julien Boeuff47a5cb2015-02-18 12:24:08 -0800424}
425
426static grpc_credentials_vtable jwt_vtable = {
Craig Tillera82950e2015-09-22 12:33:20 -0700427 jwt_destruct, jwt_has_request_metadata, jwt_has_request_metadata_only,
428 jwt_get_request_metadata, NULL};
Julien Boeuff47a5cb2015-02-18 12:24:08 -0800429
Julien Boeuffe4c3f42015-07-22 16:20:13 -0700430grpc_credentials *
Craig Tillera82950e2015-09-22 12:33:20 -0700431grpc_service_account_jwt_access_credentials_create_from_auth_json_key(
432 grpc_auth_json_key key, gpr_timespec token_lifetime) {
Julien Boeuffe4c3f42015-07-22 16:20:13 -0700433 grpc_service_account_jwt_access_credentials *c;
Craig Tillera82950e2015-09-22 12:33:20 -0700434 if (!grpc_auth_json_key_is_valid(&key)) {
435 gpr_log(GPR_ERROR, "Invalid input for jwt credentials creation");
436 return NULL;
437 }
438 c = gpr_malloc(sizeof(grpc_service_account_jwt_access_credentials));
439 memset(c, 0, sizeof(grpc_service_account_jwt_access_credentials));
Julien Boeuff47a5cb2015-02-18 12:24:08 -0800440 c->base.type = GRPC_CREDENTIALS_TYPE_JWT;
Craig Tillera82950e2015-09-22 12:33:20 -0700441 gpr_ref_init(&c->base.refcount, 1);
Julien Boeuff47a5cb2015-02-18 12:24:08 -0800442 c->base.vtable = &jwt_vtable;
Julien Boeuff47a5cb2015-02-18 12:24:08 -0800443 c->key = key;
444 c->jwt_lifetime = token_lifetime;
Craig Tillera82950e2015-09-22 12:33:20 -0700445 gpr_mu_init(&c->cache_mu);
446 jwt_reset_cache(c);
Julien Boeuff47a5cb2015-02-18 12:24:08 -0800447 return &c->base;
448}
449
Craig Tillera82950e2015-09-22 12:33:20 -0700450grpc_credentials *grpc_service_account_jwt_access_credentials_create(
451 const char *json_key, gpr_timespec token_lifetime, void *reserved) {
452 GPR_ASSERT(reserved == NULL);
453 return grpc_service_account_jwt_access_credentials_create_from_auth_json_key(
454 grpc_auth_json_key_create_from_string(json_key), token_lifetime);
Julien Boeuf54006062015-07-07 19:13:04 -0700455}
456
jboeuf1a809c02014-12-19 15:44:30 -0800457/* -- Oauth2TokenFetcher credentials -- */
458
Craig Tillera82950e2015-09-22 12:33:20 -0700459static void oauth2_token_fetcher_destruct(grpc_credentials *creds) {
460 grpc_oauth2_token_fetcher_credentials *c =
461 (grpc_oauth2_token_fetcher_credentials *)creds;
462 grpc_credentials_md_store_unref(c->access_token_md);
463 gpr_mu_destroy(&c->mu);
464 grpc_httpcli_context_destroy(&c->httpcli_context);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800465}
466
Craig Tillera82950e2015-09-22 12:33:20 -0700467static int oauth2_token_fetcher_has_request_metadata(
468 const grpc_credentials *creds) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800469 return 1;
470}
471
Craig Tillera82950e2015-09-22 12:33:20 -0700472static int oauth2_token_fetcher_has_request_metadata_only(
473 const grpc_credentials *creds) {
jboeuf1a809c02014-12-19 15:44:30 -0800474 return 1;
475}
476
477grpc_credentials_status
Craig Tillera82950e2015-09-22 12:33:20 -0700478grpc_oauth2_token_fetcher_credentials_parse_server_response(
479 const grpc_httpcli_response *response, grpc_credentials_md_store **token_md,
480 gpr_timespec *token_lifetime) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800481 char *null_terminated_body = NULL;
482 char *new_access_token = NULL;
483 grpc_credentials_status status = GRPC_CREDENTIALS_OK;
Nicolas Noble614c2bf2015-01-21 15:48:36 -0800484 grpc_json *json = NULL;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800485
Craig Tillera82950e2015-09-22 12:33:20 -0700486 if (response == NULL) {
487 gpr_log(GPR_ERROR, "Received NULL response.");
488 status = GRPC_CREDENTIALS_ERROR;
489 goto end;
490 }
491
492 if (response->body_length > 0) {
493 null_terminated_body = gpr_malloc(response->body_length + 1);
494 null_terminated_body[response->body_length] = '\0';
495 memcpy(null_terminated_body, response->body, response->body_length);
496 }
497
498 if (response->status != 200) {
499 gpr_log(GPR_ERROR, "Call to http server ended with error %d [%s].",
500 response->status,
501 null_terminated_body != NULL ? null_terminated_body : "");
502 status = GRPC_CREDENTIALS_ERROR;
503 goto end;
504 } else {
505 grpc_json *access_token = NULL;
506 grpc_json *token_type = NULL;
507 grpc_json *expires_in = NULL;
508 grpc_json *ptr;
509 json = grpc_json_parse_string(null_terminated_body);
510 if (json == NULL) {
511 gpr_log(GPR_ERROR, "Could not parse JSON from %s", null_terminated_body);
Craig Tiller45724b32015-09-22 10:42:19 -0700512 status = GRPC_CREDENTIALS_ERROR;
513 goto end;
514 }
Craig Tillera82950e2015-09-22 12:33:20 -0700515 if (json->type != GRPC_JSON_OBJECT) {
516 gpr_log(GPR_ERROR, "Response should be a JSON object");
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800517 status = GRPC_CREDENTIALS_ERROR;
518 goto end;
519 }
Craig Tillera82950e2015-09-22 12:33:20 -0700520 for (ptr = json->child; ptr; ptr = ptr->next) {
521 if (strcmp(ptr->key, "access_token") == 0) {
522 access_token = ptr;
523 } else if (strcmp(ptr->key, "token_type") == 0) {
524 token_type = ptr;
525 } else if (strcmp(ptr->key, "expires_in") == 0) {
526 expires_in = ptr;
527 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800528 }
Craig Tillera82950e2015-09-22 12:33:20 -0700529 if (access_token == NULL || access_token->type != GRPC_JSON_STRING) {
530 gpr_log(GPR_ERROR, "Missing or invalid access_token in JSON.");
531 status = GRPC_CREDENTIALS_ERROR;
532 goto end;
533 }
534 if (token_type == NULL || token_type->type != GRPC_JSON_STRING) {
535 gpr_log(GPR_ERROR, "Missing or invalid token_type in JSON.");
536 status = GRPC_CREDENTIALS_ERROR;
537 goto end;
538 }
539 if (expires_in == NULL || expires_in->type != GRPC_JSON_NUMBER) {
540 gpr_log(GPR_ERROR, "Missing or invalid expires_in in JSON.");
541 status = GRPC_CREDENTIALS_ERROR;
542 goto end;
543 }
544 gpr_asprintf(&new_access_token, "%s %s", token_type->value,
545 access_token->value);
546 token_lifetime->tv_sec = strtol(expires_in->value, NULL, 10);
547 token_lifetime->tv_nsec = 0;
548 token_lifetime->clock_type = GPR_TIMESPAN;
549 if (*token_md != NULL) grpc_credentials_md_store_unref(*token_md);
550 *token_md = grpc_credentials_md_store_create(1);
551 grpc_credentials_md_store_add_cstrings(
552 *token_md, GRPC_AUTHORIZATION_METADATA_KEY, new_access_token);
553 status = GRPC_CREDENTIALS_OK;
554 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800555
556end:
Craig Tillera82950e2015-09-22 12:33:20 -0700557 if (status != GRPC_CREDENTIALS_OK && (*token_md != NULL)) {
558 grpc_credentials_md_store_unref(*token_md);
559 *token_md = NULL;
560 }
561 if (null_terminated_body != NULL) gpr_free(null_terminated_body);
562 if (new_access_token != NULL) gpr_free(new_access_token);
563 if (json != NULL) grpc_json_destroy(json);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800564 return status;
565}
566
Craig Tillera82950e2015-09-22 12:33:20 -0700567static void on_oauth2_token_fetcher_http_response(
568 grpc_exec_ctx *exec_ctx, void *user_data,
569 const grpc_httpcli_response *response) {
570 grpc_credentials_metadata_request *r =
571 (grpc_credentials_metadata_request *)user_data;
572 grpc_oauth2_token_fetcher_credentials *c =
573 (grpc_oauth2_token_fetcher_credentials *)r->creds;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800574 gpr_timespec token_lifetime;
575 grpc_credentials_status status;
576
Craig Tillera82950e2015-09-22 12:33:20 -0700577 gpr_mu_lock(&c->mu);
578 status = grpc_oauth2_token_fetcher_credentials_parse_server_response(
579 response, &c->access_token_md, &token_lifetime);
580 if (status == GRPC_CREDENTIALS_OK) {
581 c->token_expiration =
582 gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), token_lifetime);
583 r->cb(exec_ctx, r->user_data, c->access_token_md->entries,
584 c->access_token_md->num_entries, status);
585 } else {
586 c->token_expiration = gpr_inf_past(GPR_CLOCK_REALTIME);
587 r->cb(exec_ctx, r->user_data, NULL, 0, status);
588 }
589 gpr_mu_unlock(&c->mu);
590 grpc_credentials_metadata_request_destroy(r);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800591}
592
Craig Tillera82950e2015-09-22 12:33:20 -0700593static void oauth2_token_fetcher_get_request_metadata(
594 grpc_exec_ctx *exec_ctx, grpc_credentials *creds, grpc_pollset *pollset,
595 const char *service_url, grpc_credentials_metadata_cb cb, void *user_data) {
596 grpc_oauth2_token_fetcher_credentials *c =
597 (grpc_oauth2_token_fetcher_credentials *)creds;
598 gpr_timespec refresh_threshold = gpr_time_from_seconds(
599 GRPC_SECURE_TOKEN_REFRESH_THRESHOLD_SECS, GPR_TIMESPAN);
Julien Boeuf75c9b6f2015-05-29 13:12:12 -0700600 grpc_credentials_md_store *cached_access_token_md = NULL;
jboeuf1a809c02014-12-19 15:44:30 -0800601 {
Craig Tillera82950e2015-09-22 12:33:20 -0700602 gpr_mu_lock(&c->mu);
603 if (c->access_token_md != NULL &&
604 (gpr_time_cmp(
605 gpr_time_sub(c->token_expiration, gpr_now(GPR_CLOCK_REALTIME)),
606 refresh_threshold) > 0)) {
607 cached_access_token_md =
608 grpc_credentials_md_store_ref(c->access_token_md);
609 }
610 gpr_mu_unlock(&c->mu);
Craig Tiller45724b32015-09-22 10:42:19 -0700611 }
Craig Tillera82950e2015-09-22 12:33:20 -0700612 if (cached_access_token_md != NULL) {
613 cb(exec_ctx, user_data, cached_access_token_md->entries,
614 cached_access_token_md->num_entries, GRPC_CREDENTIALS_OK);
615 grpc_credentials_md_store_unref(cached_access_token_md);
616 } else {
617 c->fetch_func(
618 exec_ctx,
619 grpc_credentials_metadata_request_create(creds, cb, user_data),
620 &c->httpcli_context, pollset, on_oauth2_token_fetcher_http_response,
621 gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), refresh_threshold));
622 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800623}
624
Craig Tillera82950e2015-09-22 12:33:20 -0700625static void init_oauth2_token_fetcher(grpc_oauth2_token_fetcher_credentials *c,
626 grpc_fetch_oauth2_func fetch_func) {
627 memset(c, 0, sizeof(grpc_oauth2_token_fetcher_credentials));
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800628 c->base.type = GRPC_CREDENTIALS_TYPE_OAUTH2;
Craig Tillera82950e2015-09-22 12:33:20 -0700629 gpr_ref_init(&c->base.refcount, 1);
630 gpr_mu_init(&c->mu);
631 c->token_expiration = gpr_inf_past(GPR_CLOCK_REALTIME);
jboeuf1a809c02014-12-19 15:44:30 -0800632 c->fetch_func = fetch_func;
Craig Tillera82950e2015-09-22 12:33:20 -0700633 grpc_httpcli_context_init(&c->httpcli_context);
jboeuf1a809c02014-12-19 15:44:30 -0800634}
635
Julien Boeuf510a9202015-08-25 21:51:07 -0700636/* -- GoogleComputeEngine credentials. -- */
jboeuf1a809c02014-12-19 15:44:30 -0800637
638static grpc_credentials_vtable compute_engine_vtable = {
Craig Tillera82950e2015-09-22 12:33:20 -0700639 oauth2_token_fetcher_destruct, oauth2_token_fetcher_has_request_metadata,
640 oauth2_token_fetcher_has_request_metadata_only,
641 oauth2_token_fetcher_get_request_metadata, NULL};
jboeuf1a809c02014-12-19 15:44:30 -0800642
Craig Tillera82950e2015-09-22 12:33:20 -0700643static void compute_engine_fetch_oauth2(
644 grpc_exec_ctx *exec_ctx, grpc_credentials_metadata_request *metadata_req,
645 grpc_httpcli_context *httpcli_context, grpc_pollset *pollset,
646 grpc_httpcli_response_cb response_cb, gpr_timespec deadline) {
647 grpc_httpcli_header header = {"Metadata-Flavor", "Google"};
jboeuf1a809c02014-12-19 15:44:30 -0800648 grpc_httpcli_request request;
Craig Tillera82950e2015-09-22 12:33:20 -0700649 memset(&request, 0, sizeof(grpc_httpcli_request));
jboeuf1a809c02014-12-19 15:44:30 -0800650 request.host = GRPC_COMPUTE_ENGINE_METADATA_HOST;
651 request.path = GRPC_COMPUTE_ENGINE_METADATA_TOKEN_PATH;
652 request.hdr_count = 1;
653 request.hdrs = &header;
Craig Tillera82950e2015-09-22 12:33:20 -0700654 grpc_httpcli_get(exec_ctx, httpcli_context, pollset, &request, deadline,
655 response_cb, metadata_req);
jboeuf1a809c02014-12-19 15:44:30 -0800656}
657
Craig Tillera82950e2015-09-22 12:33:20 -0700658grpc_credentials *grpc_google_compute_engine_credentials_create(
659 void *reserved) {
660 grpc_oauth2_token_fetcher_credentials *c =
661 gpr_malloc(sizeof(grpc_oauth2_token_fetcher_credentials));
662 GPR_ASSERT(reserved == NULL);
663 init_oauth2_token_fetcher(c, compute_engine_fetch_oauth2);
jboeuf1a809c02014-12-19 15:44:30 -0800664 c->base.vtable = &compute_engine_vtable;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800665 return &c->base;
666}
667
Julien Boeuf510a9202015-08-25 21:51:07 -0700668/* -- GoogleRefreshToken credentials. -- */
Julien Boeuf9835cf02015-03-09 16:56:44 -0700669
Craig Tillera82950e2015-09-22 12:33:20 -0700670static void refresh_token_destruct(grpc_credentials *creds) {
671 grpc_google_refresh_token_credentials *c =
672 (grpc_google_refresh_token_credentials *)creds;
673 grpc_auth_refresh_token_destruct(&c->refresh_token);
674 oauth2_token_fetcher_destruct(&c->base.base);
Julien Boeuf9835cf02015-03-09 16:56:44 -0700675}
676
677static grpc_credentials_vtable refresh_token_vtable = {
Craig Tillera82950e2015-09-22 12:33:20 -0700678 refresh_token_destruct, oauth2_token_fetcher_has_request_metadata,
679 oauth2_token_fetcher_has_request_metadata_only,
680 oauth2_token_fetcher_get_request_metadata, NULL};
Julien Boeuf9835cf02015-03-09 16:56:44 -0700681
Craig Tillera82950e2015-09-22 12:33:20 -0700682static void refresh_token_fetch_oauth2(
683 grpc_exec_ctx *exec_ctx, grpc_credentials_metadata_request *metadata_req,
684 grpc_httpcli_context *httpcli_context, grpc_pollset *pollset,
685 grpc_httpcli_response_cb response_cb, gpr_timespec deadline) {
686 grpc_google_refresh_token_credentials *c =
687 (grpc_google_refresh_token_credentials *)metadata_req->creds;
688 grpc_httpcli_header header = {"Content-Type",
689 "application/x-www-form-urlencoded"};
Julien Boeuf9835cf02015-03-09 16:56:44 -0700690 grpc_httpcli_request request;
691 char *body = NULL;
Craig Tillera82950e2015-09-22 12:33:20 -0700692 gpr_asprintf(&body, GRPC_REFRESH_TOKEN_POST_BODY_FORMAT_STRING,
693 c->refresh_token.client_id, c->refresh_token.client_secret,
694 c->refresh_token.refresh_token);
695 memset(&request, 0, sizeof(grpc_httpcli_request));
Julien Boeuf9835cf02015-03-09 16:56:44 -0700696 request.host = GRPC_GOOGLE_OAUTH2_SERVICE_HOST;
697 request.path = GRPC_GOOGLE_OAUTH2_SERVICE_TOKEN_PATH;
698 request.hdr_count = 1;
699 request.hdrs = &header;
Craig Tillerf53d9c82015-08-04 14:19:43 -0700700 request.handshaker = &grpc_httpcli_ssl;
Craig Tillera82950e2015-09-22 12:33:20 -0700701 grpc_httpcli_post(exec_ctx, httpcli_context, pollset, &request, body,
702 strlen(body), deadline, response_cb, metadata_req);
703 gpr_free(body);
Julien Boeuf9835cf02015-03-09 16:56:44 -0700704}
705
Craig Tillera82950e2015-09-22 12:33:20 -0700706grpc_credentials *grpc_refresh_token_credentials_create_from_auth_refresh_token(
707 grpc_auth_refresh_token refresh_token) {
Julien Boeuf510a9202015-08-25 21:51:07 -0700708 grpc_google_refresh_token_credentials *c;
Craig Tillera82950e2015-09-22 12:33:20 -0700709 if (!grpc_auth_refresh_token_is_valid(&refresh_token)) {
710 gpr_log(GPR_ERROR, "Invalid input for refresh token credentials creation");
711 return NULL;
712 }
713 c = gpr_malloc(sizeof(grpc_google_refresh_token_credentials));
714 memset(c, 0, sizeof(grpc_google_refresh_token_credentials));
715 init_oauth2_token_fetcher(&c->base, refresh_token_fetch_oauth2);
Julien Boeuf9835cf02015-03-09 16:56:44 -0700716 c->base.base.vtable = &refresh_token_vtable;
717 c->refresh_token = refresh_token;
718 return &c->base.base;
719}
720
Craig Tillera82950e2015-09-22 12:33:20 -0700721grpc_credentials *grpc_google_refresh_token_credentials_create(
722 const char *json_refresh_token, void *reserved) {
723 GPR_ASSERT(reserved == NULL);
724 return grpc_refresh_token_credentials_create_from_auth_refresh_token(
725 grpc_auth_refresh_token_create_from_string(json_refresh_token));
Julien Boeuf54006062015-07-07 19:13:04 -0700726}
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800727
Julien Boeufea456fc2015-07-07 15:23:30 -0700728/* -- Metadata-only credentials. -- */
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800729
Craig Tillera82950e2015-09-22 12:33:20 -0700730static void md_only_test_destruct(grpc_credentials *creds) {
731 grpc_md_only_test_credentials *c = (grpc_md_only_test_credentials *)creds;
732 grpc_credentials_md_store_unref(c->md_store);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800733}
734
Craig Tillera82950e2015-09-22 12:33:20 -0700735static int md_only_test_has_request_metadata(const grpc_credentials *creds) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800736 return 1;
737}
738
Craig Tillera82950e2015-09-22 12:33:20 -0700739static int md_only_test_has_request_metadata_only(
740 const grpc_credentials *creds) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800741 return 1;
742}
743
Craig Tillera82950e2015-09-22 12:33:20 -0700744static void on_simulated_token_fetch_done(void *user_data) {
745 grpc_credentials_metadata_request *r =
746 (grpc_credentials_metadata_request *)user_data;
747 grpc_md_only_test_credentials *c = (grpc_md_only_test_credentials *)r->creds;
Craig Tillerf5768a62015-09-22 10:54:34 -0700748 grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
Craig Tillera82950e2015-09-22 12:33:20 -0700749 r->cb(&exec_ctx, r->user_data, c->md_store->entries, c->md_store->num_entries,
750 GRPC_CREDENTIALS_OK);
751 grpc_credentials_metadata_request_destroy(r);
752 grpc_exec_ctx_finish(&exec_ctx);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800753}
754
Craig Tillera82950e2015-09-22 12:33:20 -0700755static void md_only_test_get_request_metadata(
756 grpc_exec_ctx *exec_ctx, grpc_credentials *creds, grpc_pollset *pollset,
757 const char *service_url, grpc_credentials_metadata_cb cb, void *user_data) {
758 grpc_md_only_test_credentials *c = (grpc_md_only_test_credentials *)creds;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800759
Craig Tillera82950e2015-09-22 12:33:20 -0700760 if (c->is_async) {
761 gpr_thd_id thd_id;
762 grpc_credentials_metadata_request *cb_arg =
763 grpc_credentials_metadata_request_create(creds, cb, user_data);
764 gpr_thd_new(&thd_id, on_simulated_token_fetch_done, cb_arg, NULL);
765 } else {
766 cb(exec_ctx, user_data, c->md_store->entries, 1, GRPC_CREDENTIALS_OK);
767 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800768}
769
Julien Boeufea456fc2015-07-07 15:23:30 -0700770static grpc_credentials_vtable md_only_test_vtable = {
Craig Tillera82950e2015-09-22 12:33:20 -0700771 md_only_test_destruct, md_only_test_has_request_metadata,
772 md_only_test_has_request_metadata_only, md_only_test_get_request_metadata,
773 NULL};
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800774
Craig Tillera82950e2015-09-22 12:33:20 -0700775grpc_credentials *grpc_md_only_test_credentials_create(const char *md_key,
776 const char *md_value,
777 int is_async) {
778 grpc_md_only_test_credentials *c =
779 gpr_malloc(sizeof(grpc_md_only_test_credentials));
780 memset(c, 0, sizeof(grpc_md_only_test_credentials));
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800781 c->base.type = GRPC_CREDENTIALS_TYPE_OAUTH2;
Julien Boeufea456fc2015-07-07 15:23:30 -0700782 c->base.vtable = &md_only_test_vtable;
Craig Tillera82950e2015-09-22 12:33:20 -0700783 gpr_ref_init(&c->base.refcount, 1);
784 c->md_store = grpc_credentials_md_store_create(1);
785 grpc_credentials_md_store_add_cstrings(c->md_store, md_key, md_value);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800786 c->is_async = is_async;
787 return &c->base;
788}
789
Julien Boeuf2805be12015-07-01 02:47:18 -0700790/* -- Oauth2 Access Token credentials. -- */
791
Craig Tillera82950e2015-09-22 12:33:20 -0700792static void access_token_destruct(grpc_credentials *creds) {
793 grpc_access_token_credentials *c = (grpc_access_token_credentials *)creds;
794 grpc_credentials_md_store_unref(c->access_token_md);
Julien Boeuf2805be12015-07-01 02:47:18 -0700795}
796
Craig Tillera82950e2015-09-22 12:33:20 -0700797static int access_token_has_request_metadata(const grpc_credentials *creds) {
Julien Boeuf2805be12015-07-01 02:47:18 -0700798 return 1;
799}
800
Craig Tillera82950e2015-09-22 12:33:20 -0700801static int access_token_has_request_metadata_only(
802 const grpc_credentials *creds) {
Julien Boeuf2805be12015-07-01 02:47:18 -0700803 return 1;
804}
805
Craig Tillera82950e2015-09-22 12:33:20 -0700806static void access_token_get_request_metadata(
807 grpc_exec_ctx *exec_ctx, grpc_credentials *creds, grpc_pollset *pollset,
808 const char *service_url, grpc_credentials_metadata_cb cb, void *user_data) {
809 grpc_access_token_credentials *c = (grpc_access_token_credentials *)creds;
810 cb(exec_ctx, user_data, c->access_token_md->entries, 1, GRPC_CREDENTIALS_OK);
Julien Boeuf2805be12015-07-01 02:47:18 -0700811}
812
813static grpc_credentials_vtable access_token_vtable = {
Craig Tillera82950e2015-09-22 12:33:20 -0700814 access_token_destruct, access_token_has_request_metadata,
815 access_token_has_request_metadata_only, access_token_get_request_metadata,
816 NULL};
Julien Boeuf2805be12015-07-01 02:47:18 -0700817
Craig Tillera82950e2015-09-22 12:33:20 -0700818grpc_credentials *grpc_access_token_credentials_create(const char *access_token,
819 void *reserved) {
820 grpc_access_token_credentials *c =
821 gpr_malloc(sizeof(grpc_access_token_credentials));
Julien Boeuf2805be12015-07-01 02:47:18 -0700822 char *token_md_value;
Craig Tillera82950e2015-09-22 12:33:20 -0700823 GPR_ASSERT(reserved == NULL);
824 memset(c, 0, sizeof(grpc_access_token_credentials));
Julien Boeuf2805be12015-07-01 02:47:18 -0700825 c->base.type = GRPC_CREDENTIALS_TYPE_OAUTH2;
826 c->base.vtable = &access_token_vtable;
Craig Tillera82950e2015-09-22 12:33:20 -0700827 gpr_ref_init(&c->base.refcount, 1);
828 c->access_token_md = grpc_credentials_md_store_create(1);
829 gpr_asprintf(&token_md_value, "Bearer %s", access_token);
830 grpc_credentials_md_store_add_cstrings(
831 c->access_token_md, GRPC_AUTHORIZATION_METADATA_KEY, token_md_value);
832 gpr_free(token_md_value);
Julien Boeuf2805be12015-07-01 02:47:18 -0700833 return &c->base;
834}
835
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800836/* -- Fake transport security credentials. -- */
837
Craig Tillera82950e2015-09-22 12:33:20 -0700838static void fake_transport_security_credentials_destruct(
839 grpc_credentials *creds) {
Julien Boeuffe1478f2015-08-30 21:57:38 -0700840 /* Nothing to do here. */
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800841}
842
Craig Tillera82950e2015-09-22 12:33:20 -0700843static void fake_transport_security_server_credentials_destruct(
844 grpc_server_credentials *creds) {
Julien Boeuffe1478f2015-08-30 21:57:38 -0700845 /* Nothing to do here. */
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800846}
847
Craig Tillera82950e2015-09-22 12:33:20 -0700848static int fake_transport_security_has_request_metadata(
849 const grpc_credentials *creds) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800850 return 0;
851}
852
Craig Tillera82950e2015-09-22 12:33:20 -0700853static int fake_transport_security_has_request_metadata_only(
854 const grpc_credentials *creds) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800855 return 0;
856}
857
Craig Tillera82950e2015-09-22 12:33:20 -0700858static grpc_security_status fake_transport_security_create_security_connector(
859 grpc_credentials *c, const char *target, const grpc_channel_args *args,
860 grpc_credentials *request_metadata_creds,
861 grpc_channel_security_connector **sc, grpc_channel_args **new_args) {
862 *sc = grpc_fake_channel_security_connector_create(request_metadata_creds, 1);
Julien Boeuf7d1d9ca2015-04-17 14:38:48 -0700863 return GRPC_SECURITY_OK;
864}
865
866static grpc_security_status
Craig Tillera82950e2015-09-22 12:33:20 -0700867fake_transport_security_server_create_security_connector(
868 grpc_server_credentials *c, grpc_security_connector **sc) {
869 *sc = grpc_fake_server_security_connector_create();
Julien Boeuf7d1d9ca2015-04-17 14:38:48 -0700870 return GRPC_SECURITY_OK;
871}
872
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800873static grpc_credentials_vtable fake_transport_security_credentials_vtable = {
Craig Tillera82950e2015-09-22 12:33:20 -0700874 fake_transport_security_credentials_destruct,
875 fake_transport_security_has_request_metadata,
876 fake_transport_security_has_request_metadata_only, NULL,
877 fake_transport_security_create_security_connector};
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800878
Craig Tillera82950e2015-09-22 12:33:20 -0700879static grpc_server_credentials_vtable
880 fake_transport_security_server_credentials_vtable = {
881 fake_transport_security_server_credentials_destruct,
882 fake_transport_security_server_create_security_connector};
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800883
Craig Tillera82950e2015-09-22 12:33:20 -0700884grpc_credentials *grpc_fake_transport_security_credentials_create(void) {
885 grpc_credentials *c = gpr_malloc(sizeof(grpc_credentials));
886 memset(c, 0, sizeof(grpc_credentials));
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800887 c->type = GRPC_CREDENTIALS_TYPE_FAKE_TRANSPORT_SECURITY;
888 c->vtable = &fake_transport_security_credentials_vtable;
Craig Tillera82950e2015-09-22 12:33:20 -0700889 gpr_ref_init(&c->refcount, 1);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800890 return c;
891}
892
Craig Tillera82950e2015-09-22 12:33:20 -0700893grpc_server_credentials *grpc_fake_transport_security_server_credentials_create(
894 void) {
895 grpc_server_credentials *c = gpr_malloc(sizeof(grpc_server_credentials));
896 memset(c, 0, sizeof(grpc_server_credentials));
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800897 c->type = GRPC_CREDENTIALS_TYPE_FAKE_TRANSPORT_SECURITY;
Craig Tillera82950e2015-09-22 12:33:20 -0700898 gpr_ref_init(&c->refcount, 1);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800899 c->vtable = &fake_transport_security_server_credentials_vtable;
900 return c;
901}
902
nnoble0c475f02014-12-05 15:37:39 -0800903/* -- Composite credentials. -- */
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800904
Craig Tillera82950e2015-09-22 12:33:20 -0700905typedef struct {
nnoble0c475f02014-12-05 15:37:39 -0800906 grpc_composite_credentials *composite_creds;
907 size_t creds_index;
Julien Boeuf75c9b6f2015-05-29 13:12:12 -0700908 grpc_credentials_md_store *md_elems;
Julien Boeuff47a5cb2015-02-18 12:24:08 -0800909 char *service_url;
nnoble0c475f02014-12-05 15:37:39 -0800910 void *user_data;
Craig Tiller06bac342015-06-01 12:55:57 -0700911 grpc_pollset *pollset;
nnoble0c475f02014-12-05 15:37:39 -0800912 grpc_credentials_metadata_cb cb;
913} grpc_composite_credentials_metadata_context;
914
Craig Tillera82950e2015-09-22 12:33:20 -0700915static void composite_destruct(grpc_credentials *creds) {
916 grpc_composite_credentials *c = (grpc_composite_credentials *)creds;
nnoble0c475f02014-12-05 15:37:39 -0800917 size_t i;
Craig Tillera82950e2015-09-22 12:33:20 -0700918 for (i = 0; i < c->inner.num_creds; i++) {
919 grpc_credentials_unref(c->inner.creds_array[i]);
920 }
921 gpr_free(c->inner.creds_array);
nnoble0c475f02014-12-05 15:37:39 -0800922}
923
Craig Tillera82950e2015-09-22 12:33:20 -0700924static int composite_has_request_metadata(const grpc_credentials *creds) {
925 const grpc_composite_credentials *c =
926 (const grpc_composite_credentials *)creds;
nnoble0c475f02014-12-05 15:37:39 -0800927 size_t i;
Craig Tillera82950e2015-09-22 12:33:20 -0700928 for (i = 0; i < c->inner.num_creds; i++) {
929 if (grpc_credentials_has_request_metadata(c->inner.creds_array[i])) {
930 return 1;
nnoble0c475f02014-12-05 15:37:39 -0800931 }
Craig Tillera82950e2015-09-22 12:33:20 -0700932 }
nnoble0c475f02014-12-05 15:37:39 -0800933 return 0;
934}
935
Craig Tillera82950e2015-09-22 12:33:20 -0700936static int composite_has_request_metadata_only(const grpc_credentials *creds) {
937 const grpc_composite_credentials *c =
938 (const grpc_composite_credentials *)creds;
nnoble0c475f02014-12-05 15:37:39 -0800939 size_t i;
Craig Tillera82950e2015-09-22 12:33:20 -0700940 for (i = 0; i < c->inner.num_creds; i++) {
941 if (!grpc_credentials_has_request_metadata_only(c->inner.creds_array[i])) {
942 return 0;
nnoble0c475f02014-12-05 15:37:39 -0800943 }
Craig Tillera82950e2015-09-22 12:33:20 -0700944 }
nnoble0c475f02014-12-05 15:37:39 -0800945 return 1;
946}
947
Craig Tillera82950e2015-09-22 12:33:20 -0700948static void composite_md_context_destroy(
949 grpc_composite_credentials_metadata_context *ctx) {
950 grpc_credentials_md_store_unref(ctx->md_elems);
951 if (ctx->service_url != NULL) gpr_free(ctx->service_url);
952 gpr_free(ctx);
nnoble0c475f02014-12-05 15:37:39 -0800953}
954
Craig Tillera82950e2015-09-22 12:33:20 -0700955static void composite_metadata_cb(grpc_exec_ctx *exec_ctx, void *user_data,
956 grpc_credentials_md *md_elems, size_t num_md,
957 grpc_credentials_status status) {
958 grpc_composite_credentials_metadata_context *ctx =
959 (grpc_composite_credentials_metadata_context *)user_data;
960 if (status != GRPC_CREDENTIALS_OK) {
961 ctx->cb(exec_ctx, ctx->user_data, NULL, 0, status);
962 return;
963 }
Craig Tiller45724b32015-09-22 10:42:19 -0700964
965 /* Copy the metadata in the context. */
Craig Tillera82950e2015-09-22 12:33:20 -0700966 if (num_md > 0) {
967 size_t i;
968 for (i = 0; i < num_md; i++) {
969 grpc_credentials_md_store_add(ctx->md_elems, md_elems[i].key,
970 md_elems[i].value);
Craig Tiller45724b32015-09-22 10:42:19 -0700971 }
Craig Tillera82950e2015-09-22 12:33:20 -0700972 }
Craig Tiller45724b32015-09-22 10:42:19 -0700973
974 /* See if we need to get some more metadata. */
Craig Tillera82950e2015-09-22 12:33:20 -0700975 while (ctx->creds_index < ctx->composite_creds->inner.num_creds) {
976 grpc_credentials *inner_creds =
977 ctx->composite_creds->inner.creds_array[ctx->creds_index++];
978 if (grpc_credentials_has_request_metadata(inner_creds)) {
979 grpc_credentials_get_request_metadata(exec_ctx, inner_creds, ctx->pollset,
980 ctx->service_url,
981 composite_metadata_cb, ctx);
Craig Tiller45724b32015-09-22 10:42:19 -0700982 return;
983 }
Craig Tillera82950e2015-09-22 12:33:20 -0700984 }
985
986 /* We're done!. */
987 ctx->cb(exec_ctx, ctx->user_data, ctx->md_elems->entries,
988 ctx->md_elems->num_entries, GRPC_CREDENTIALS_OK);
989 composite_md_context_destroy(ctx);
990}
991
992static void composite_get_request_metadata(
993 grpc_exec_ctx *exec_ctx, grpc_credentials *creds, grpc_pollset *pollset,
994 const char *service_url, grpc_credentials_metadata_cb cb, void *user_data) {
995 grpc_composite_credentials *c = (grpc_composite_credentials *)creds;
996 grpc_composite_credentials_metadata_context *ctx;
997 if (!grpc_credentials_has_request_metadata(creds)) {
998 cb(exec_ctx, user_data, NULL, 0, GRPC_CREDENTIALS_OK);
999 return;
1000 }
1001 ctx = gpr_malloc(sizeof(grpc_composite_credentials_metadata_context));
1002 memset(ctx, 0, sizeof(grpc_composite_credentials_metadata_context));
1003 ctx->service_url = gpr_strdup(service_url);
nnoble0c475f02014-12-05 15:37:39 -08001004 ctx->user_data = user_data;
1005 ctx->cb = cb;
1006 ctx->composite_creds = c;
Craig Tiller06bac342015-06-01 12:55:57 -07001007 ctx->pollset = pollset;
Craig Tillera82950e2015-09-22 12:33:20 -07001008 ctx->md_elems = grpc_credentials_md_store_create(c->inner.num_creds);
1009 while (ctx->creds_index < c->inner.num_creds) {
1010 grpc_credentials *inner_creds = c->inner.creds_array[ctx->creds_index++];
1011 if (grpc_credentials_has_request_metadata(inner_creds)) {
1012 grpc_credentials_get_request_metadata(exec_ctx, inner_creds, pollset,
1013 service_url, composite_metadata_cb,
1014 ctx);
1015 return;
nnoble0c475f02014-12-05 15:37:39 -08001016 }
Craig Tillera82950e2015-09-22 12:33:20 -07001017 }
1018 GPR_ASSERT(0); /* Should have exited before. */
nnoble0c475f02014-12-05 15:37:39 -08001019}
1020
Craig Tillera82950e2015-09-22 12:33:20 -07001021static grpc_security_status composite_create_security_connector(
1022 grpc_credentials *creds, const char *target, const grpc_channel_args *args,
1023 grpc_credentials *request_metadata_creds,
1024 grpc_channel_security_connector **sc, grpc_channel_args **new_args) {
1025 grpc_composite_credentials *c = (grpc_composite_credentials *)creds;
1026 if (c->connector_creds == NULL) {
1027 gpr_log(GPR_ERROR,
1028 "Cannot create security connector, missing connector credentials.");
1029 return GRPC_SECURITY_ERROR;
1030 }
1031 return grpc_credentials_create_security_connector(c->connector_creds, target,
1032 args, creds, sc, new_args);
Julien Boeuf7d1d9ca2015-04-17 14:38:48 -07001033}
1034
nnoble0c475f02014-12-05 15:37:39 -08001035static grpc_credentials_vtable composite_credentials_vtable = {
Craig Tillera82950e2015-09-22 12:33:20 -07001036 composite_destruct, composite_has_request_metadata,
1037 composite_has_request_metadata_only, composite_get_request_metadata,
1038 composite_create_security_connector};
nnoble0c475f02014-12-05 15:37:39 -08001039
Craig Tillera82950e2015-09-22 12:33:20 -07001040static grpc_credentials_array get_creds_array(grpc_credentials **creds_addr) {
nnoble0c475f02014-12-05 15:37:39 -08001041 grpc_credentials_array result;
1042 grpc_credentials *creds = *creds_addr;
1043 result.creds_array = creds_addr;
1044 result.num_creds = 1;
Craig Tillera82950e2015-09-22 12:33:20 -07001045 if (strcmp(creds->type, GRPC_CREDENTIALS_TYPE_COMPOSITE) == 0) {
1046 result = *grpc_composite_credentials_get_credentials(creds);
1047 }
nnoble0c475f02014-12-05 15:37:39 -08001048 return result;
1049}
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001050
Craig Tillera82950e2015-09-22 12:33:20 -07001051grpc_credentials *grpc_composite_credentials_create(grpc_credentials *creds1,
1052 grpc_credentials *creds2,
1053 void *reserved) {
nnoble0c475f02014-12-05 15:37:39 -08001054 size_t i;
Julien Boeuf7d1d9ca2015-04-17 14:38:48 -07001055 size_t creds_array_byte_size;
nnoble0c475f02014-12-05 15:37:39 -08001056 grpc_credentials_array creds1_array;
1057 grpc_credentials_array creds2_array;
1058 grpc_composite_credentials *c;
Craig Tillera82950e2015-09-22 12:33:20 -07001059 GPR_ASSERT(reserved == NULL);
1060 GPR_ASSERT(creds1 != NULL);
1061 GPR_ASSERT(creds2 != NULL);
1062 c = gpr_malloc(sizeof(grpc_composite_credentials));
1063 memset(c, 0, sizeof(grpc_composite_credentials));
nnoble0c475f02014-12-05 15:37:39 -08001064 c->base.type = GRPC_CREDENTIALS_TYPE_COMPOSITE;
1065 c->base.vtable = &composite_credentials_vtable;
Craig Tillera82950e2015-09-22 12:33:20 -07001066 gpr_ref_init(&c->base.refcount, 1);
1067 creds1_array = get_creds_array(&creds1);
1068 creds2_array = get_creds_array(&creds2);
nnoble0c475f02014-12-05 15:37:39 -08001069 c->inner.num_creds = creds1_array.num_creds + creds2_array.num_creds;
Craig Tillera82950e2015-09-22 12:33:20 -07001070 creds_array_byte_size = c->inner.num_creds * sizeof(grpc_credentials *);
1071 c->inner.creds_array = gpr_malloc(creds_array_byte_size);
1072 memset(c->inner.creds_array, 0, creds_array_byte_size);
1073 for (i = 0; i < creds1_array.num_creds; i++) {
1074 grpc_credentials *cur_creds = creds1_array.creds_array[i];
1075 if (!grpc_credentials_has_request_metadata_only(cur_creds)) {
1076 if (c->connector_creds == NULL) {
1077 c->connector_creds = cur_creds;
1078 } else {
1079 gpr_log(GPR_ERROR, "Cannot compose multiple connector credentials.");
1080 goto fail;
1081 }
Julien Boeuf7d1d9ca2015-04-17 14:38:48 -07001082 }
Craig Tillera82950e2015-09-22 12:33:20 -07001083 c->inner.creds_array[i] = grpc_credentials_ref(cur_creds);
1084 }
1085 for (i = 0; i < creds2_array.num_creds; i++) {
1086 grpc_credentials *cur_creds = creds2_array.creds_array[i];
1087 if (!grpc_credentials_has_request_metadata_only(cur_creds)) {
1088 if (c->connector_creds == NULL) {
1089 c->connector_creds = cur_creds;
1090 } else {
1091 gpr_log(GPR_ERROR, "Cannot compose multiple connector credentials.");
1092 goto fail;
1093 }
Julien Boeuf7d1d9ca2015-04-17 14:38:48 -07001094 }
Craig Tillera82950e2015-09-22 12:33:20 -07001095 c->inner.creds_array[i + creds1_array.num_creds] =
1096 grpc_credentials_ref(cur_creds);
1097 }
nnoble0c475f02014-12-05 15:37:39 -08001098 return &c->base;
Julien Boeuf7d1d9ca2015-04-17 14:38:48 -07001099
1100fail:
Craig Tillera82950e2015-09-22 12:33:20 -07001101 grpc_credentials_unref(&c->base);
Julien Boeuf7d1d9ca2015-04-17 14:38:48 -07001102 return NULL;
nnoble0c475f02014-12-05 15:37:39 -08001103}
1104
Craig Tillera82950e2015-09-22 12:33:20 -07001105const grpc_credentials_array *grpc_composite_credentials_get_credentials(
1106 grpc_credentials *creds) {
1107 const grpc_composite_credentials *c =
1108 (const grpc_composite_credentials *)creds;
1109 GPR_ASSERT(strcmp(creds->type, GRPC_CREDENTIALS_TYPE_COMPOSITE) == 0);
nnoble0c475f02014-12-05 15:37:39 -08001110 return &c->inner;
1111}
1112
Craig Tillera82950e2015-09-22 12:33:20 -07001113grpc_credentials *grpc_credentials_contains_type(
1114 grpc_credentials *creds, const char *type,
1115 grpc_credentials **composite_creds) {
jboeuf6ad120e2015-01-12 17:08:15 -08001116 size_t i;
Craig Tillera82950e2015-09-22 12:33:20 -07001117 if (strcmp(creds->type, type) == 0) {
1118 if (composite_creds != NULL) *composite_creds = NULL;
1119 return creds;
1120 } else if (strcmp(creds->type, GRPC_CREDENTIALS_TYPE_COMPOSITE) == 0) {
1121 const grpc_credentials_array *inner_creds_array =
1122 grpc_composite_credentials_get_credentials(creds);
1123 for (i = 0; i < inner_creds_array->num_creds; i++) {
1124 if (strcmp(type, inner_creds_array->creds_array[i]->type) == 0) {
1125 if (composite_creds != NULL) *composite_creds = creds;
1126 return inner_creds_array->creds_array[i];
1127 }
jboeuf6ad120e2015-01-12 17:08:15 -08001128 }
Craig Tillera82950e2015-09-22 12:33:20 -07001129 }
jboeuf6ad120e2015-01-12 17:08:15 -08001130 return NULL;
1131}
1132
nnoble0c475f02014-12-05 15:37:39 -08001133/* -- IAM credentials. -- */
1134
Craig Tillera82950e2015-09-22 12:33:20 -07001135static void iam_destruct(grpc_credentials *creds) {
1136 grpc_google_iam_credentials *c = (grpc_google_iam_credentials *)creds;
1137 grpc_credentials_md_store_unref(c->iam_md);
nnoble0c475f02014-12-05 15:37:39 -08001138}
1139
Craig Tillera82950e2015-09-22 12:33:20 -07001140static int iam_has_request_metadata(const grpc_credentials *creds) { return 1; }
1141
1142static int iam_has_request_metadata_only(const grpc_credentials *creds) {
nnoble0c475f02014-12-05 15:37:39 -08001143 return 1;
1144}
1145
Craig Tillera82950e2015-09-22 12:33:20 -07001146static void iam_get_request_metadata(
1147 grpc_exec_ctx *exec_ctx, grpc_credentials *creds, grpc_pollset *pollset,
1148 const char *service_url, grpc_credentials_metadata_cb cb, void *user_data) {
1149 grpc_google_iam_credentials *c = (grpc_google_iam_credentials *)creds;
1150 cb(exec_ctx, user_data, c->iam_md->entries, c->iam_md->num_entries,
1151 GRPC_CREDENTIALS_OK);
nnoble0c475f02014-12-05 15:37:39 -08001152}
1153
1154static grpc_credentials_vtable iam_vtable = {
Craig Tillera82950e2015-09-22 12:33:20 -07001155 iam_destruct, iam_has_request_metadata, iam_has_request_metadata_only,
1156 iam_get_request_metadata, NULL};
nnoble0c475f02014-12-05 15:37:39 -08001157
Craig Tillera82950e2015-09-22 12:33:20 -07001158grpc_credentials *grpc_google_iam_credentials_create(
1159 const char *token, const char *authority_selector, void *reserved) {
Julien Boeuf510a9202015-08-25 21:51:07 -07001160 grpc_google_iam_credentials *c;
Craig Tillera82950e2015-09-22 12:33:20 -07001161 GPR_ASSERT(reserved == NULL);
1162 GPR_ASSERT(token != NULL);
1163 GPR_ASSERT(authority_selector != NULL);
1164 c = gpr_malloc(sizeof(grpc_google_iam_credentials));
1165 memset(c, 0, sizeof(grpc_google_iam_credentials));
nnoble0c475f02014-12-05 15:37:39 -08001166 c->base.type = GRPC_CREDENTIALS_TYPE_IAM;
1167 c->base.vtable = &iam_vtable;
Craig Tillera82950e2015-09-22 12:33:20 -07001168 gpr_ref_init(&c->base.refcount, 1);
1169 c->iam_md = grpc_credentials_md_store_create(2);
1170 grpc_credentials_md_store_add_cstrings(
1171 c->iam_md, GRPC_IAM_AUTHORIZATION_TOKEN_METADATA_KEY, token);
1172 grpc_credentials_md_store_add_cstrings(
1173 c->iam_md, GRPC_IAM_AUTHORITY_SELECTOR_METADATA_KEY, authority_selector);
nnoble0c475f02014-12-05 15:37:39 -08001174 return &c->base;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001175}
Julien Boeuf2d041182015-08-31 20:30:09 -07001176
1177/* -- Plugin credentials. -- */
1178
Craig Tillera82950e2015-09-22 12:33:20 -07001179typedef struct {
Julien Boeuf2d041182015-08-31 20:30:09 -07001180 void *user_data;
1181 grpc_credentials_metadata_cb cb;
1182} grpc_metadata_plugin_request;
1183
Craig Tillera82950e2015-09-22 12:33:20 -07001184static void plugin_destruct(grpc_credentials *creds) {
1185 grpc_plugin_credentials *c = (grpc_plugin_credentials *)creds;
1186 if (c->plugin.state != NULL && c->plugin.destroy != NULL) {
1187 c->plugin.destroy(c->plugin.state);
1188 }
Julien Boeuf2d041182015-08-31 20:30:09 -07001189}
1190
Craig Tillera82950e2015-09-22 12:33:20 -07001191static int plugin_has_request_metadata(const grpc_credentials *creds) {
Julien Boeuf2d041182015-08-31 20:30:09 -07001192 return 1;
1193}
1194
Craig Tillera82950e2015-09-22 12:33:20 -07001195static int plugin_has_request_metadata_only(const grpc_credentials *creds) {
Julien Boeuf2d041182015-08-31 20:30:09 -07001196 return 1;
1197}
1198
Craig Tillera82950e2015-09-22 12:33:20 -07001199static void plugin_md_request_metadata_ready(void *request,
1200 const grpc_metadata *md,
1201 size_t num_md,
1202 grpc_status_code status,
1203 const char *error_details) {
Craig Tiller10ee2742015-09-22 09:25:57 -07001204 /* called from application code */
Craig Tillerf5768a62015-09-22 10:54:34 -07001205 grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
Craig Tillera82950e2015-09-22 12:33:20 -07001206 grpc_metadata_plugin_request *r = (grpc_metadata_plugin_request *)request;
1207 if (status != GRPC_STATUS_OK) {
1208 if (error_details != NULL) {
1209 gpr_log(GPR_ERROR, "Getting metadata from plugin failed with error: %s",
1210 error_details);
Julien Boeuf2d041182015-08-31 20:30:09 -07001211 }
Craig Tillera82950e2015-09-22 12:33:20 -07001212 r->cb(&exec_ctx, r->user_data, NULL, 0, GRPC_CREDENTIALS_ERROR);
1213 } else {
1214 size_t i;
1215 grpc_credentials_md *md_array = NULL;
1216 if (num_md > 0) {
1217 md_array = gpr_malloc(num_md * sizeof(grpc_credentials_md));
1218 for (i = 0; i < num_md; i++) {
1219 md_array[i].key = gpr_slice_from_copied_string(md[i].key);
1220 md_array[i].value =
1221 gpr_slice_from_copied_buffer(md[i].value, md[i].value_length);
1222 }
Julien Boeuf2d041182015-08-31 20:30:09 -07001223 }
Craig Tillera82950e2015-09-22 12:33:20 -07001224 r->cb(&exec_ctx, r->user_data, md_array, num_md, GRPC_CREDENTIALS_OK);
1225 if (md_array != NULL) {
1226 for (i = 0; i < num_md; i++) {
1227 gpr_slice_unref(md_array[i].key);
1228 gpr_slice_unref(md_array[i].value);
1229 }
1230 gpr_free(md_array);
1231 }
1232 }
1233 gpr_free(r);
Craig Tiller80183f32015-09-23 12:33:59 -07001234 grpc_exec_ctx_finish(&exec_ctx);
Julien Boeuf2d041182015-08-31 20:30:09 -07001235}
1236
Craig Tillera82950e2015-09-22 12:33:20 -07001237static void plugin_get_request_metadata(
1238 grpc_exec_ctx *exec_ctx, grpc_credentials *creds, grpc_pollset *pollset,
1239 const char *service_url, grpc_credentials_metadata_cb cb, void *user_data) {
1240 grpc_plugin_credentials *c = (grpc_plugin_credentials *)creds;
1241 if (c->plugin.get_metadata != NULL) {
1242 grpc_metadata_plugin_request *request = gpr_malloc(sizeof(*request));
1243 memset(request, 0, sizeof(*request));
1244 request->user_data = user_data;
1245 request->cb = cb;
1246 c->plugin.get_metadata(c->plugin.state, service_url,
1247 plugin_md_request_metadata_ready, request);
1248 } else {
1249 cb(exec_ctx, user_data, NULL, 0, GRPC_CREDENTIALS_OK);
1250 }
Julien Boeuf2d041182015-08-31 20:30:09 -07001251}
1252
1253static grpc_credentials_vtable plugin_vtable = {
Craig Tillera82950e2015-09-22 12:33:20 -07001254 plugin_destruct, plugin_has_request_metadata,
1255 plugin_has_request_metadata_only, plugin_get_request_metadata, NULL};
Julien Boeuf2d041182015-08-31 20:30:09 -07001256
Craig Tillera82950e2015-09-22 12:33:20 -07001257grpc_credentials *grpc_metadata_credentials_create_from_plugin(
1258 grpc_metadata_credentials_plugin plugin, void *reserved) {
1259 grpc_plugin_credentials *c = gpr_malloc(sizeof(*c));
1260 GPR_ASSERT(reserved == NULL);
1261 memset(c, 0, sizeof(*c));
Julien Boeuf2d041182015-08-31 20:30:09 -07001262 c->base.type = GRPC_CREDENTIALS_TYPE_METADATA_PLUGIN;
1263 c->base.vtable = &plugin_vtable;
Craig Tillera82950e2015-09-22 12:33:20 -07001264 gpr_ref_init(&c->base.refcount, 1);
Julien Boeuf2d041182015-08-31 20:30:09 -07001265 c->plugin = plugin;
1266 return &c->base;
1267}