blob: a764413300fef3763c965cfc4b4a0ec38c07d104 [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>
50#include <grpc/support/time.h>
51
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080052/* -- Common. -- */
53
Julien Boeufb037bb62015-07-08 14:58:14 -070054struct grpc_credentials_metadata_request {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080055 grpc_credentials *creds;
56 grpc_credentials_metadata_cb cb;
David Garcia Quintas69ba8712015-06-01 11:29:42 -070057 grpc_iomgr_closure *on_simulated_token_fetch_done_closure;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080058 void *user_data;
Julien Boeufb037bb62015-07-08 14:58:14 -070059};
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080060
61static grpc_credentials_metadata_request *
62grpc_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);
68 r->cb = cb;
David Garcia Quintas69ba8712015-06-01 11:29:42 -070069 r->on_simulated_token_fetch_done_closure =
70 gpr_malloc(sizeof(grpc_iomgr_closure));
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080071 r->user_data = user_data;
72 return r;
73}
74
75static void grpc_credentials_metadata_request_destroy(
76 grpc_credentials_metadata_request *r) {
77 grpc_credentials_unref(r->creds);
David Garcia Quintas69ba8712015-06-01 11:29:42 -070078 gpr_free(r->on_simulated_token_fetch_done_closure);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080079 gpr_free(r);
80}
81
82grpc_credentials *grpc_credentials_ref(grpc_credentials *creds) {
83 if (creds == NULL) return NULL;
84 gpr_ref(&creds->refcount);
85 return creds;
86}
87
88void grpc_credentials_unref(grpc_credentials *creds) {
89 if (creds == NULL) return;
Julien Boeuffe1478f2015-08-30 21:57:38 -070090 if (gpr_unref(&creds->refcount)) {
91 creds->vtable->destruct(creds);
92 gpr_free(creds);
93 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080094}
95
96void grpc_credentials_release(grpc_credentials *creds) {
97 grpc_credentials_unref(creds);
98}
99
100int grpc_credentials_has_request_metadata(grpc_credentials *creds) {
101 if (creds == NULL) return 0;
102 return creds->vtable->has_request_metadata(creds);
103}
104
105int grpc_credentials_has_request_metadata_only(grpc_credentials *creds) {
106 if (creds == NULL) return 0;
107 return creds->vtable->has_request_metadata_only(creds);
108}
109
110void grpc_credentials_get_request_metadata(grpc_credentials *creds,
Craig Tiller06bac342015-06-01 12:55:57 -0700111 grpc_pollset *pollset,
Julien Boeuff47a5cb2015-02-18 12:24:08 -0800112 const char *service_url,
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800113 grpc_credentials_metadata_cb cb,
114 void *user_data) {
nnoble0c475f02014-12-05 15:37:39 -0800115 if (creds == NULL || !grpc_credentials_has_request_metadata(creds) ||
116 creds->vtable->get_request_metadata == NULL) {
117 if (cb != NULL) {
118 cb(user_data, NULL, 0, GRPC_CREDENTIALS_OK);
119 }
120 return;
121 }
Craig Tiller06bac342015-06-01 12:55:57 -0700122 creds->vtable->get_request_metadata(creds, pollset, service_url, cb,
123 user_data);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800124}
125
Julien Boeuf7d1d9ca2015-04-17 14:38:48 -0700126grpc_security_status grpc_credentials_create_security_connector(
127 grpc_credentials *creds, const char *target, const grpc_channel_args *args,
128 grpc_credentials *request_metadata_creds,
129 grpc_channel_security_connector **sc, grpc_channel_args **new_args) {
130 *new_args = NULL;
131 if (creds == NULL || creds->vtable->create_security_connector == NULL ||
132 grpc_credentials_has_request_metadata_only(creds)) {
133 gpr_log(GPR_ERROR,
134 "Invalid credentials for creating a security connector.");
135 return GRPC_SECURITY_ERROR;
136 }
137 return creds->vtable->create_security_connector(
138 creds, target, args, request_metadata_creds, sc, new_args);
Craig Tillerc4885ed2015-04-14 09:51:28 -0700139}
140
Julien Boeuffe1478f2015-08-30 21:57:38 -0700141grpc_server_credentials *grpc_server_credentials_ref(
142 grpc_server_credentials *creds) {
143 if (creds == NULL) return NULL;
144 gpr_ref(&creds->refcount);
145 return creds;
146}
147
148void grpc_server_credentials_unref(grpc_server_credentials *creds) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800149 if (creds == NULL) return;
Julien Boeuffe1478f2015-08-30 21:57:38 -0700150 if (gpr_unref(&creds->refcount)) {
151 creds->vtable->destruct(creds);
152 if (creds->processor.destroy != NULL && creds->processor.state != NULL) {
153 creds->processor.destroy(creds->processor.state);
154 }
155 gpr_free(creds);
156 }
157}
158
159void grpc_server_credentials_release(grpc_server_credentials *creds) {
160 grpc_server_credentials_unref(creds);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800161}
162
Julien Boeuf7d1d9ca2015-04-17 14:38:48 -0700163grpc_security_status grpc_server_credentials_create_security_connector(
164 grpc_server_credentials *creds, grpc_security_connector **sc) {
165 if (creds == NULL || creds->vtable->create_security_connector == NULL) {
166 gpr_log(GPR_ERROR, "Server credentials cannot create security context.");
167 return GRPC_SECURITY_ERROR;
168 }
169 return creds->vtable->create_security_connector(creds, sc);
170}
171
Julien Boeuf6bdc9b42015-07-19 21:56:02 -0700172void grpc_server_credentials_set_auth_metadata_processor(
173 grpc_server_credentials *creds, grpc_auth_metadata_processor processor) {
174 if (creds == NULL) return;
Julien Boeuf0c711ad2015-08-28 14:10:58 -0700175 if (creds->processor.destroy != NULL && creds->processor.state != NULL) {
176 creds->processor.destroy(creds->processor.state);
177 }
Julien Boeuf6bdc9b42015-07-19 21:56:02 -0700178 creds->processor = processor;
179}
180
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800181/* -- Ssl credentials. -- */
182
Julien Boeuffe1478f2015-08-30 21:57:38 -0700183static void ssl_destruct(grpc_credentials *creds) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800184 grpc_ssl_credentials *c = (grpc_ssl_credentials *)creds;
185 if (c->config.pem_root_certs != NULL) gpr_free(c->config.pem_root_certs);
186 if (c->config.pem_private_key != NULL) gpr_free(c->config.pem_private_key);
187 if (c->config.pem_cert_chain != NULL) gpr_free(c->config.pem_cert_chain);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800188}
189
Julien Boeuffe1478f2015-08-30 21:57:38 -0700190static void ssl_server_destruct(grpc_server_credentials *creds) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800191 grpc_ssl_server_credentials *c = (grpc_ssl_server_credentials *)creds;
Julien Boeuf8fbcc432015-01-15 16:44:13 -0800192 size_t i;
193 for (i = 0; i < c->config.num_key_cert_pairs; i++) {
194 if (c->config.pem_private_keys[i] != NULL) {
195 gpr_free(c->config.pem_private_keys[i]);
196 }
Nicolas Noble614c2bf2015-01-21 15:48:36 -0800197 if (c->config.pem_cert_chains[i] != NULL) {
Julien Boeuf8fbcc432015-01-15 16:44:13 -0800198 gpr_free(c->config.pem_cert_chains[i]);
199 }
200 }
201 if (c->config.pem_private_keys != NULL) gpr_free(c->config.pem_private_keys);
202 if (c->config.pem_private_keys_sizes != NULL) {
203 gpr_free(c->config.pem_private_keys_sizes);
204 }
205 if (c->config.pem_cert_chains != NULL) gpr_free(c->config.pem_cert_chains);
206 if (c->config.pem_cert_chains_sizes != NULL) {
207 gpr_free(c->config.pem_cert_chains_sizes);
208 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800209 if (c->config.pem_root_certs != NULL) gpr_free(c->config.pem_root_certs);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800210}
211
Craig Tiller83b826a2015-05-13 13:43:01 -0700212static int ssl_has_request_metadata(const grpc_credentials *creds) { return 0; }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800213
214static int ssl_has_request_metadata_only(const grpc_credentials *creds) {
215 return 0;
216}
217
Julien Boeuf7d1d9ca2015-04-17 14:38:48 -0700218static grpc_security_status ssl_create_security_connector(
219 grpc_credentials *creds, const char *target, const grpc_channel_args *args,
220 grpc_credentials *request_metadata_creds,
221 grpc_channel_security_connector **sc, grpc_channel_args **new_args) {
222 grpc_ssl_credentials *c = (grpc_ssl_credentials *)creds;
223 grpc_security_status status = GRPC_SECURITY_OK;
224 size_t i = 0;
225 const char *overridden_target_name = NULL;
226 grpc_arg arg;
227
228 for (i = 0; args && i < args->num_args; i++) {
229 grpc_arg *arg = &args->args[i];
230 if (strcmp(arg->key, GRPC_SSL_TARGET_NAME_OVERRIDE_ARG) == 0 &&
231 arg->type == GRPC_ARG_STRING) {
232 overridden_target_name = arg->value.string;
233 break;
234 }
235 }
236 status = grpc_ssl_channel_security_connector_create(
237 request_metadata_creds, &c->config, target, overridden_target_name, sc);
238 if (status != GRPC_SECURITY_OK) {
239 return status;
240 }
241 arg.type = GRPC_ARG_STRING;
242 arg.key = GRPC_ARG_HTTP2_SCHEME;
243 arg.value.string = "https";
Craig Tillerd9a50882015-06-29 15:57:36 -0700244 *new_args = grpc_channel_args_copy_and_add(args, &arg, 1);
Julien Boeuf7d1d9ca2015-04-17 14:38:48 -0700245 return status;
246}
247
248static grpc_security_status ssl_server_create_security_connector(
249 grpc_server_credentials *creds, grpc_security_connector **sc) {
250 grpc_ssl_server_credentials *c = (grpc_ssl_server_credentials *)creds;
251 return grpc_ssl_server_security_connector_create(&c->config, sc);
252}
253
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800254static grpc_credentials_vtable ssl_vtable = {
Julien Boeuffe1478f2015-08-30 21:57:38 -0700255 ssl_destruct, ssl_has_request_metadata, ssl_has_request_metadata_only, NULL,
Julien Boeuf75c9b6f2015-05-29 13:12:12 -0700256 ssl_create_security_connector};
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800257
Julien Boeuf7d1d9ca2015-04-17 14:38:48 -0700258static grpc_server_credentials_vtable ssl_server_vtable = {
Julien Boeuffe1478f2015-08-30 21:57:38 -0700259 ssl_server_destruct, ssl_server_create_security_connector};
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800260
Julien Boeuf8fbcc432015-01-15 16:44:13 -0800261static void ssl_copy_key_material(const char *input, unsigned char **output,
262 size_t *output_size) {
263 *output_size = strlen(input);
264 *output = gpr_malloc(*output_size);
265 memcpy(*output, input, *output_size);
266}
267
268static void ssl_build_config(const char *pem_root_certs,
269 grpc_ssl_pem_key_cert_pair *pem_key_cert_pair,
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800270 grpc_ssl_config *config) {
Julien Boeuf026a4172015-02-02 18:36:37 -0800271 if (pem_root_certs != NULL) {
Julien Boeuf8fbcc432015-01-15 16:44:13 -0800272 ssl_copy_key_material(pem_root_certs, &config->pem_root_certs,
273 &config->pem_root_certs_size);
274 }
Julien Boeuf8fbcc432015-01-15 16:44:13 -0800275 if (pem_key_cert_pair != NULL) {
276 GPR_ASSERT(pem_key_cert_pair->private_key != NULL);
277 GPR_ASSERT(pem_key_cert_pair->cert_chain != NULL);
278 ssl_copy_key_material(pem_key_cert_pair->private_key,
279 &config->pem_private_key,
280 &config->pem_private_key_size);
281 ssl_copy_key_material(pem_key_cert_pair->cert_chain,
282 &config->pem_cert_chain,
283 &config->pem_cert_chain_size);
284 }
285}
286
287static void ssl_build_server_config(
288 const char *pem_root_certs, grpc_ssl_pem_key_cert_pair *pem_key_cert_pairs,
Julien Boeuf5029b302015-07-21 23:02:16 -0700289 size_t num_key_cert_pairs, int force_client_auth,
290 grpc_ssl_server_config *config) {
Julien Boeuf8fbcc432015-01-15 16:44:13 -0800291 size_t i;
Julien Boeuf5029b302015-07-21 23:02:16 -0700292 config->force_client_auth = force_client_auth;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800293 if (pem_root_certs != NULL) {
Julien Boeuf8fbcc432015-01-15 16:44:13 -0800294 ssl_copy_key_material(pem_root_certs, &config->pem_root_certs,
295 &config->pem_root_certs_size);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800296 }
Julien Boeuf8fbcc432015-01-15 16:44:13 -0800297 if (num_key_cert_pairs > 0) {
298 GPR_ASSERT(pem_key_cert_pairs != NULL);
299 config->pem_private_keys =
300 gpr_malloc(num_key_cert_pairs * sizeof(unsigned char *));
301 config->pem_cert_chains =
302 gpr_malloc(num_key_cert_pairs * sizeof(unsigned char *));
303 config->pem_private_keys_sizes =
304 gpr_malloc(num_key_cert_pairs * sizeof(size_t));
305 config->pem_cert_chains_sizes =
306 gpr_malloc(num_key_cert_pairs * sizeof(size_t));
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800307 }
Julien Boeuf8fbcc432015-01-15 16:44:13 -0800308 config->num_key_cert_pairs = num_key_cert_pairs;
309 for (i = 0; i < num_key_cert_pairs; i++) {
310 GPR_ASSERT(pem_key_cert_pairs[i].private_key != NULL);
311 GPR_ASSERT(pem_key_cert_pairs[i].cert_chain != NULL);
312 ssl_copy_key_material(pem_key_cert_pairs[i].private_key,
313 &config->pem_private_keys[i],
314 &config->pem_private_keys_sizes[i]);
315 ssl_copy_key_material(pem_key_cert_pairs[i].cert_chain,
316 &config->pem_cert_chains[i],
317 &config->pem_cert_chains_sizes[i]);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800318 }
319}
320
321grpc_credentials *grpc_ssl_credentials_create(
Julien Boeufc5b570f2015-08-25 17:47:55 -0700322 const char *pem_root_certs, grpc_ssl_pem_key_cert_pair *pem_key_cert_pair,
323 void *reserved) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800324 grpc_ssl_credentials *c = gpr_malloc(sizeof(grpc_ssl_credentials));
Julien Boeufc5b570f2015-08-25 17:47:55 -0700325 GPR_ASSERT(reserved == NULL);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800326 memset(c, 0, sizeof(grpc_ssl_credentials));
327 c->base.type = GRPC_CREDENTIALS_TYPE_SSL;
328 c->base.vtable = &ssl_vtable;
329 gpr_ref_init(&c->base.refcount, 1);
Julien Boeuf8fbcc432015-01-15 16:44:13 -0800330 ssl_build_config(pem_root_certs, pem_key_cert_pair, &c->config);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800331 return &c->base;
332}
333
334grpc_server_credentials *grpc_ssl_server_credentials_create(
Julien Boeuf8fbcc432015-01-15 16:44:13 -0800335 const char *pem_root_certs, grpc_ssl_pem_key_cert_pair *pem_key_cert_pairs,
Julien Boeufc5b570f2015-08-25 17:47:55 -0700336 size_t num_key_cert_pairs, int force_client_auth, void *reserved) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800337 grpc_ssl_server_credentials *c =
338 gpr_malloc(sizeof(grpc_ssl_server_credentials));
Julien Boeufc5b570f2015-08-25 17:47:55 -0700339 GPR_ASSERT(reserved == NULL);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800340 memset(c, 0, sizeof(grpc_ssl_server_credentials));
341 c->base.type = GRPC_CREDENTIALS_TYPE_SSL;
Julien Boeuffe1478f2015-08-30 21:57:38 -0700342 gpr_ref_init(&c->base.refcount, 1);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800343 c->base.vtable = &ssl_server_vtable;
Julien Boeuf8fbcc432015-01-15 16:44:13 -0800344 ssl_build_server_config(pem_root_certs, pem_key_cert_pairs,
Julien Boeuf5029b302015-07-21 23:02:16 -0700345 num_key_cert_pairs, force_client_auth, &c->config);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800346 return &c->base;
347}
348
Julien Boeuff47a5cb2015-02-18 12:24:08 -0800349/* -- Jwt credentials -- */
350
Julien Boeuffe4c3f42015-07-22 16:20:13 -0700351static void jwt_reset_cache(grpc_service_account_jwt_access_credentials *c) {
Julien Boeuff47a5cb2015-02-18 12:24:08 -0800352 if (c->cached.jwt_md != NULL) {
Julien Boeuf75c9b6f2015-05-29 13:12:12 -0700353 grpc_credentials_md_store_unref(c->cached.jwt_md);
Julien Boeuff47a5cb2015-02-18 12:24:08 -0800354 c->cached.jwt_md = NULL;
355 }
356 if (c->cached.service_url != NULL) {
357 gpr_free(c->cached.service_url);
358 c->cached.service_url = NULL;
359 }
Craig Tiller143e7bf2015-07-13 08:41:49 -0700360 c->cached.jwt_expiration = gpr_inf_past(GPR_CLOCK_REALTIME);
Julien Boeuff47a5cb2015-02-18 12:24:08 -0800361}
362
Julien Boeuffe1478f2015-08-30 21:57:38 -0700363static void jwt_destruct(grpc_credentials *creds) {
Julien Boeuffe4c3f42015-07-22 16:20:13 -0700364 grpc_service_account_jwt_access_credentials *c =
365 (grpc_service_account_jwt_access_credentials *)creds;
Julien Boeuff47a5cb2015-02-18 12:24:08 -0800366 grpc_auth_json_key_destruct(&c->key);
367 jwt_reset_cache(c);
368 gpr_mu_destroy(&c->cache_mu);
Julien Boeuff47a5cb2015-02-18 12:24:08 -0800369}
370
371static int jwt_has_request_metadata(const grpc_credentials *creds) { return 1; }
372
373static int jwt_has_request_metadata_only(const grpc_credentials *creds) {
374 return 1;
375}
376
Julien Boeuff47a5cb2015-02-18 12:24:08 -0800377static void jwt_get_request_metadata(grpc_credentials *creds,
Craig Tiller06bac342015-06-01 12:55:57 -0700378 grpc_pollset *pollset,
Julien Boeuff47a5cb2015-02-18 12:24:08 -0800379 const char *service_url,
380 grpc_credentials_metadata_cb cb,
381 void *user_data) {
Julien Boeuffe4c3f42015-07-22 16:20:13 -0700382 grpc_service_account_jwt_access_credentials *c =
383 (grpc_service_account_jwt_access_credentials *)creds;
Craig Tiller58bbc862015-07-13 09:51:17 -0700384 gpr_timespec refresh_threshold = gpr_time_from_seconds(
385 GRPC_SECURE_TOKEN_REFRESH_THRESHOLD_SECS, GPR_TIMESPAN);
Julien Boeuff47a5cb2015-02-18 12:24:08 -0800386
387 /* See if we can return a cached jwt. */
Julien Boeuf75c9b6f2015-05-29 13:12:12 -0700388 grpc_credentials_md_store *jwt_md = NULL;
Julien Boeuff47a5cb2015-02-18 12:24:08 -0800389 {
390 gpr_mu_lock(&c->cache_mu);
391 if (c->cached.service_url != NULL &&
Ronnie Sahlberg2ad8d212015-03-07 08:39:22 -0800392 strcmp(c->cached.service_url, service_url) == 0 &&
Julien Boeuff47a5cb2015-02-18 12:24:08 -0800393 c->cached.jwt_md != NULL &&
Craig Tillerf1bff012015-07-06 11:20:50 -0700394 (gpr_time_cmp(gpr_time_sub(c->cached.jwt_expiration,
395 gpr_now(GPR_CLOCK_REALTIME)),
Julien Boeuff47a5cb2015-02-18 12:24:08 -0800396 refresh_threshold) > 0)) {
Julien Boeuf75c9b6f2015-05-29 13:12:12 -0700397 jwt_md = grpc_credentials_md_store_ref(c->cached.jwt_md);
Julien Boeuff47a5cb2015-02-18 12:24:08 -0800398 }
399 gpr_mu_unlock(&c->cache_mu);
400 }
401
402 if (jwt_md == NULL) {
403 char *jwt = NULL;
404 /* Generate a new jwt. */
405 gpr_mu_lock(&c->cache_mu);
406 jwt_reset_cache(c);
407 jwt = grpc_jwt_encode_and_sign(&c->key, service_url, c->jwt_lifetime, NULL);
408 if (jwt != NULL) {
409 char *md_value;
410 gpr_asprintf(&md_value, "Bearer %s", jwt);
411 gpr_free(jwt);
Craig Tillerf1bff012015-07-06 11:20:50 -0700412 c->cached.jwt_expiration =
413 gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), c->jwt_lifetime);
Julien Boeuff47a5cb2015-02-18 12:24:08 -0800414 c->cached.service_url = gpr_strdup(service_url);
Julien Boeuf75c9b6f2015-05-29 13:12:12 -0700415 c->cached.jwt_md = grpc_credentials_md_store_create(1);
416 grpc_credentials_md_store_add_cstrings(
417 c->cached.jwt_md, GRPC_AUTHORIZATION_METADATA_KEY, md_value);
Julien Boeuff47a5cb2015-02-18 12:24:08 -0800418 gpr_free(md_value);
Julien Boeuf75c9b6f2015-05-29 13:12:12 -0700419 jwt_md = grpc_credentials_md_store_ref(c->cached.jwt_md);
Julien Boeuff47a5cb2015-02-18 12:24:08 -0800420 }
421 gpr_mu_unlock(&c->cache_mu);
422 }
423
424 if (jwt_md != NULL) {
Julien Boeuf75c9b6f2015-05-29 13:12:12 -0700425 cb(user_data, jwt_md->entries, jwt_md->num_entries, GRPC_CREDENTIALS_OK);
426 grpc_credentials_md_store_unref(jwt_md);
Julien Boeuff47a5cb2015-02-18 12:24:08 -0800427 } else {
428 cb(user_data, NULL, 0, GRPC_CREDENTIALS_ERROR);
429 }
430}
431
432static grpc_credentials_vtable jwt_vtable = {
Julien Boeuffe1478f2015-08-30 21:57:38 -0700433 jwt_destruct, jwt_has_request_metadata, jwt_has_request_metadata_only,
Julien Boeuf75c9b6f2015-05-29 13:12:12 -0700434 jwt_get_request_metadata, NULL};
Julien Boeuff47a5cb2015-02-18 12:24:08 -0800435
Julien Boeuffe4c3f42015-07-22 16:20:13 -0700436grpc_credentials *
437grpc_service_account_jwt_access_credentials_create_from_auth_json_key(
Julien Boeuf54006062015-07-07 19:13:04 -0700438 grpc_auth_json_key key, gpr_timespec token_lifetime) {
Julien Boeuffe4c3f42015-07-22 16:20:13 -0700439 grpc_service_account_jwt_access_credentials *c;
Julien Boeuff47a5cb2015-02-18 12:24:08 -0800440 if (!grpc_auth_json_key_is_valid(&key)) {
441 gpr_log(GPR_ERROR, "Invalid input for jwt credentials creation");
442 return NULL;
443 }
Julien Boeuffe4c3f42015-07-22 16:20:13 -0700444 c = gpr_malloc(sizeof(grpc_service_account_jwt_access_credentials));
445 memset(c, 0, sizeof(grpc_service_account_jwt_access_credentials));
Julien Boeuff47a5cb2015-02-18 12:24:08 -0800446 c->base.type = GRPC_CREDENTIALS_TYPE_JWT;
447 gpr_ref_init(&c->base.refcount, 1);
448 c->base.vtable = &jwt_vtable;
Julien Boeuff47a5cb2015-02-18 12:24:08 -0800449 c->key = key;
450 c->jwt_lifetime = token_lifetime;
451 gpr_mu_init(&c->cache_mu);
452 jwt_reset_cache(c);
453 return &c->base;
454}
455
Julien Boeuffe4c3f42015-07-22 16:20:13 -0700456grpc_credentials *grpc_service_account_jwt_access_credentials_create(
Julien Boeufc5b570f2015-08-25 17:47:55 -0700457 const char *json_key, gpr_timespec token_lifetime, void *reserved) {
458 GPR_ASSERT(reserved == NULL);
Julien Boeuffe4c3f42015-07-22 16:20:13 -0700459 return grpc_service_account_jwt_access_credentials_create_from_auth_json_key(
Julien Boeuf54006062015-07-07 19:13:04 -0700460 grpc_auth_json_key_create_from_string(json_key), token_lifetime);
461}
462
jboeuf1a809c02014-12-19 15:44:30 -0800463/* -- Oauth2TokenFetcher credentials -- */
464
Julien Boeuffe1478f2015-08-30 21:57:38 -0700465static void oauth2_token_fetcher_destruct(grpc_credentials *creds) {
jboeuf1a809c02014-12-19 15:44:30 -0800466 grpc_oauth2_token_fetcher_credentials *c =
467 (grpc_oauth2_token_fetcher_credentials *)creds;
Julien Boeuf75c9b6f2015-05-29 13:12:12 -0700468 grpc_credentials_md_store_unref(c->access_token_md);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800469 gpr_mu_destroy(&c->mu);
Craig Tillera0abe372015-06-01 11:31:08 -0700470 grpc_httpcli_context_destroy(&c->httpcli_context);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800471}
472
jboeuf1a809c02014-12-19 15:44:30 -0800473static int oauth2_token_fetcher_has_request_metadata(
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800474 const grpc_credentials *creds) {
475 return 1;
476}
477
jboeuf1a809c02014-12-19 15:44:30 -0800478static int oauth2_token_fetcher_has_request_metadata_only(
479 const grpc_credentials *creds) {
480 return 1;
481}
482
483grpc_credentials_status
484grpc_oauth2_token_fetcher_credentials_parse_server_response(
Craig Tiller8674cb12015-06-05 07:09:25 -0700485 const grpc_httpcli_response *response, grpc_credentials_md_store **token_md,
486 gpr_timespec *token_lifetime) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800487 char *null_terminated_body = NULL;
488 char *new_access_token = NULL;
489 grpc_credentials_status status = GRPC_CREDENTIALS_OK;
Nicolas Noble614c2bf2015-01-21 15:48:36 -0800490 grpc_json *json = NULL;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800491
Julien Boeuf90bd7c42015-02-18 18:51:16 -0800492 if (response == NULL) {
493 gpr_log(GPR_ERROR, "Received NULL response.");
494 status = GRPC_CREDENTIALS_ERROR;
495 goto end;
496 }
497
jboeuf1a809c02014-12-19 15:44:30 -0800498 if (response->body_length > 0) {
499 null_terminated_body = gpr_malloc(response->body_length + 1);
500 null_terminated_body[response->body_length] = '\0';
501 memcpy(null_terminated_body, response->body, response->body_length);
502 }
503
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800504 if (response->status != 200) {
jboeuf1a809c02014-12-19 15:44:30 -0800505 gpr_log(GPR_ERROR, "Call to http server ended with error %d [%s].",
506 response->status,
507 null_terminated_body != NULL ? null_terminated_body : "");
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800508 status = GRPC_CREDENTIALS_ERROR;
509 goto end;
510 } else {
Nicolas Noble614c2bf2015-01-21 15:48:36 -0800511 grpc_json *access_token = NULL;
512 grpc_json *token_type = NULL;
513 grpc_json *expires_in = NULL;
514 grpc_json *ptr;
Nicolas Noble614c2bf2015-01-21 15:48:36 -0800515 json = grpc_json_parse_string(null_terminated_body);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800516 if (json == NULL) {
517 gpr_log(GPR_ERROR, "Could not parse JSON from %s", null_terminated_body);
518 status = GRPC_CREDENTIALS_ERROR;
519 goto end;
520 }
Nicolas Noble614c2bf2015-01-21 15:48:36 -0800521 if (json->type != GRPC_JSON_OBJECT) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800522 gpr_log(GPR_ERROR, "Response should be a JSON object");
523 status = GRPC_CREDENTIALS_ERROR;
524 goto end;
525 }
Nicolas Noble614c2bf2015-01-21 15:48:36 -0800526 for (ptr = json->child; ptr; ptr = ptr->next) {
527 if (strcmp(ptr->key, "access_token") == 0) {
528 access_token = ptr;
529 } else if (strcmp(ptr->key, "token_type") == 0) {
530 token_type = ptr;
531 } else if (strcmp(ptr->key, "expires_in") == 0) {
532 expires_in = ptr;
533 }
534 }
535 if (access_token == NULL || access_token->type != GRPC_JSON_STRING) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800536 gpr_log(GPR_ERROR, "Missing or invalid access_token in JSON.");
537 status = GRPC_CREDENTIALS_ERROR;
538 goto end;
539 }
Nicolas Noble614c2bf2015-01-21 15:48:36 -0800540 if (token_type == NULL || token_type->type != GRPC_JSON_STRING) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800541 gpr_log(GPR_ERROR, "Missing or invalid token_type in JSON.");
542 status = GRPC_CREDENTIALS_ERROR;
543 goto end;
544 }
Nicolas Noble614c2bf2015-01-21 15:48:36 -0800545 if (expires_in == NULL || expires_in->type != GRPC_JSON_NUMBER) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800546 gpr_log(GPR_ERROR, "Missing or invalid expires_in in JSON.");
547 status = GRPC_CREDENTIALS_ERROR;
548 goto end;
549 }
Nicolas Noblefee065c2015-01-26 11:41:12 -0800550 gpr_asprintf(&new_access_token, "%s %s", token_type->value,
551 access_token->value);
Nicolas Noblee04455a2015-01-26 17:01:29 -0800552 token_lifetime->tv_sec = strtol(expires_in->value, NULL, 10);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800553 token_lifetime->tv_nsec = 0;
Craig Tiller143e7bf2015-07-13 08:41:49 -0700554 token_lifetime->clock_type = GPR_TIMESPAN;
Julien Boeuf75c9b6f2015-05-29 13:12:12 -0700555 if (*token_md != NULL) grpc_credentials_md_store_unref(*token_md);
556 *token_md = grpc_credentials_md_store_create(1);
557 grpc_credentials_md_store_add_cstrings(
558 *token_md, GRPC_AUTHORIZATION_METADATA_KEY, new_access_token);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800559 status = GRPC_CREDENTIALS_OK;
560 }
561
562end:
Julien Boeuf75c9b6f2015-05-29 13:12:12 -0700563 if (status != GRPC_CREDENTIALS_OK && (*token_md != NULL)) {
564 grpc_credentials_md_store_unref(*token_md);
565 *token_md = NULL;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800566 }
567 if (null_terminated_body != NULL) gpr_free(null_terminated_body);
568 if (new_access_token != NULL) gpr_free(new_access_token);
Nicolas Noble8c2be9b2015-01-27 14:21:18 -0800569 if (json != NULL) grpc_json_destroy(json);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800570 return status;
571}
572
jboeuf1a809c02014-12-19 15:44:30 -0800573static void on_oauth2_token_fetcher_http_response(
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800574 void *user_data, const grpc_httpcli_response *response) {
575 grpc_credentials_metadata_request *r =
576 (grpc_credentials_metadata_request *)user_data;
jboeuf1a809c02014-12-19 15:44:30 -0800577 grpc_oauth2_token_fetcher_credentials *c =
578 (grpc_oauth2_token_fetcher_credentials *)r->creds;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800579 gpr_timespec token_lifetime;
580 grpc_credentials_status status;
581
582 gpr_mu_lock(&c->mu);
jboeuf1a809c02014-12-19 15:44:30 -0800583 status = grpc_oauth2_token_fetcher_credentials_parse_server_response(
Julien Boeuf75c9b6f2015-05-29 13:12:12 -0700584 response, &c->access_token_md, &token_lifetime);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800585 if (status == GRPC_CREDENTIALS_OK) {
Craig Tillerf1bff012015-07-06 11:20:50 -0700586 c->token_expiration =
587 gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), token_lifetime);
Julien Boeuf75c9b6f2015-05-29 13:12:12 -0700588 r->cb(r->user_data, c->access_token_md->entries,
589 c->access_token_md->num_entries, status);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800590 } else {
Craig Tiller143e7bf2015-07-13 08:41:49 -0700591 c->token_expiration = gpr_inf_past(GPR_CLOCK_REALTIME);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800592 r->cb(r->user_data, NULL, 0, status);
593 }
594 gpr_mu_unlock(&c->mu);
595 grpc_credentials_metadata_request_destroy(r);
596}
597
jboeuf1a809c02014-12-19 15:44:30 -0800598static void oauth2_token_fetcher_get_request_metadata(
Craig Tiller06bac342015-06-01 12:55:57 -0700599 grpc_credentials *creds, grpc_pollset *pollset, const char *service_url,
Julien Boeuff47a5cb2015-02-18 12:24:08 -0800600 grpc_credentials_metadata_cb cb, void *user_data) {
jboeuf1a809c02014-12-19 15:44:30 -0800601 grpc_oauth2_token_fetcher_credentials *c =
602 (grpc_oauth2_token_fetcher_credentials *)creds;
Craig Tiller58bbc862015-07-13 09:51:17 -0700603 gpr_timespec refresh_threshold = gpr_time_from_seconds(
604 GRPC_SECURE_TOKEN_REFRESH_THRESHOLD_SECS, GPR_TIMESPAN);
Julien Boeuf75c9b6f2015-05-29 13:12:12 -0700605 grpc_credentials_md_store *cached_access_token_md = NULL;
jboeuf1a809c02014-12-19 15:44:30 -0800606 {
607 gpr_mu_lock(&c->mu);
608 if (c->access_token_md != NULL &&
Craig Tillerf1bff012015-07-06 11:20:50 -0700609 (gpr_time_cmp(
610 gpr_time_sub(c->token_expiration, gpr_now(GPR_CLOCK_REALTIME)),
611 refresh_threshold) > 0)) {
Craig Tiller8674cb12015-06-05 07:09:25 -0700612 cached_access_token_md =
613 grpc_credentials_md_store_ref(c->access_token_md);
jboeuf1a809c02014-12-19 15:44:30 -0800614 }
615 gpr_mu_unlock(&c->mu);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800616 }
jboeuf1a809c02014-12-19 15:44:30 -0800617 if (cached_access_token_md != NULL) {
Julien Boeuf75c9b6f2015-05-29 13:12:12 -0700618 cb(user_data, cached_access_token_md->entries,
619 cached_access_token_md->num_entries, GRPC_CREDENTIALS_OK);
620 grpc_credentials_md_store_unref(cached_access_token_md);
jboeuf1a809c02014-12-19 15:44:30 -0800621 } else {
622 c->fetch_func(
623 grpc_credentials_metadata_request_create(creds, cb, user_data),
Craig Tiller06bac342015-06-01 12:55:57 -0700624 &c->httpcli_context, pollset, on_oauth2_token_fetcher_http_response,
Craig Tillerf3756c12015-07-01 17:21:01 -0700625 gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), refresh_threshold));
jboeuf1a809c02014-12-19 15:44:30 -0800626 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800627}
628
jboeuf1a809c02014-12-19 15:44:30 -0800629static void init_oauth2_token_fetcher(grpc_oauth2_token_fetcher_credentials *c,
630 grpc_fetch_oauth2_func fetch_func) {
631 memset(c, 0, sizeof(grpc_oauth2_token_fetcher_credentials));
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800632 c->base.type = GRPC_CREDENTIALS_TYPE_OAUTH2;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800633 gpr_ref_init(&c->base.refcount, 1);
634 gpr_mu_init(&c->mu);
Craig Tiller143e7bf2015-07-13 08:41:49 -0700635 c->token_expiration = gpr_inf_past(GPR_CLOCK_REALTIME);
jboeuf1a809c02014-12-19 15:44:30 -0800636 c->fetch_func = fetch_func;
Julien Boeuffeca1bf2015-06-22 16:46:20 +0200637 grpc_httpcli_context_init(&c->httpcli_context);
jboeuf1a809c02014-12-19 15:44:30 -0800638}
639
Julien Boeuf510a9202015-08-25 21:51:07 -0700640/* -- GoogleComputeEngine credentials. -- */
jboeuf1a809c02014-12-19 15:44:30 -0800641
642static grpc_credentials_vtable compute_engine_vtable = {
Julien Boeuffe1478f2015-08-30 21:57:38 -0700643 oauth2_token_fetcher_destruct, oauth2_token_fetcher_has_request_metadata,
jboeuf1a809c02014-12-19 15:44:30 -0800644 oauth2_token_fetcher_has_request_metadata_only,
Julien Boeuf7d1d9ca2015-04-17 14:38:48 -0700645 oauth2_token_fetcher_get_request_metadata, NULL};
jboeuf1a809c02014-12-19 15:44:30 -0800646
647static void compute_engine_fetch_oauth2(
648 grpc_credentials_metadata_request *metadata_req,
Craig Tiller06bac342015-06-01 12:55:57 -0700649 grpc_httpcli_context *httpcli_context, grpc_pollset *pollset,
650 grpc_httpcli_response_cb response_cb, gpr_timespec deadline) {
jboeuf1a809c02014-12-19 15:44:30 -0800651 grpc_httpcli_header header = {"Metadata-Flavor", "Google"};
652 grpc_httpcli_request request;
653 memset(&request, 0, sizeof(grpc_httpcli_request));
654 request.host = GRPC_COMPUTE_ENGINE_METADATA_HOST;
655 request.path = GRPC_COMPUTE_ENGINE_METADATA_TOKEN_PATH;
656 request.hdr_count = 1;
657 request.hdrs = &header;
Craig Tiller06bac342015-06-01 12:55:57 -0700658 grpc_httpcli_get(httpcli_context, pollset, &request, deadline, response_cb,
Craig Tiller83b826a2015-05-13 13:43:01 -0700659 metadata_req);
jboeuf1a809c02014-12-19 15:44:30 -0800660}
661
Julien Boeuf510a9202015-08-25 21:51:07 -0700662grpc_credentials *grpc_google_compute_engine_credentials_create(
663 void *reserved) {
jboeuf1a809c02014-12-19 15:44:30 -0800664 grpc_oauth2_token_fetcher_credentials *c =
665 gpr_malloc(sizeof(grpc_oauth2_token_fetcher_credentials));
Julien Boeufc5b570f2015-08-25 17:47:55 -0700666 GPR_ASSERT(reserved == NULL);
jboeuf1a809c02014-12-19 15:44:30 -0800667 init_oauth2_token_fetcher(c, compute_engine_fetch_oauth2);
668 c->base.vtable = &compute_engine_vtable;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800669 return &c->base;
670}
671
Julien Boeuf510a9202015-08-25 21:51:07 -0700672/* -- GoogleRefreshToken credentials. -- */
Julien Boeuf9835cf02015-03-09 16:56:44 -0700673
Julien Boeuffe1478f2015-08-30 21:57:38 -0700674static void refresh_token_destruct(grpc_credentials *creds) {
Julien Boeuf510a9202015-08-25 21:51:07 -0700675 grpc_google_refresh_token_credentials *c =
676 (grpc_google_refresh_token_credentials *)creds;
Julien Boeuf9835cf02015-03-09 16:56:44 -0700677 grpc_auth_refresh_token_destruct(&c->refresh_token);
Julien Boeuffe1478f2015-08-30 21:57:38 -0700678 oauth2_token_fetcher_destruct(&c->base.base);
Julien Boeuf9835cf02015-03-09 16:56:44 -0700679}
680
681static grpc_credentials_vtable refresh_token_vtable = {
Julien Boeuffe1478f2015-08-30 21:57:38 -0700682 refresh_token_destruct, oauth2_token_fetcher_has_request_metadata,
Julien Boeuf9835cf02015-03-09 16:56:44 -0700683 oauth2_token_fetcher_has_request_metadata_only,
Julien Boeuf7d1d9ca2015-04-17 14:38:48 -0700684 oauth2_token_fetcher_get_request_metadata, NULL};
Julien Boeuf9835cf02015-03-09 16:56:44 -0700685
686static void refresh_token_fetch_oauth2(
687 grpc_credentials_metadata_request *metadata_req,
Craig Tiller06bac342015-06-01 12:55:57 -0700688 grpc_httpcli_context *httpcli_context, grpc_pollset *pollset,
689 grpc_httpcli_response_cb response_cb, gpr_timespec deadline) {
Julien Boeuf510a9202015-08-25 21:51:07 -0700690 grpc_google_refresh_token_credentials *c =
691 (grpc_google_refresh_token_credentials *)metadata_req->creds;
Julien Boeuf9835cf02015-03-09 16:56:44 -0700692 grpc_httpcli_header header = {"Content-Type",
693 "application/x-www-form-urlencoded"};
694 grpc_httpcli_request request;
695 char *body = NULL;
696 gpr_asprintf(&body, GRPC_REFRESH_TOKEN_POST_BODY_FORMAT_STRING,
697 c->refresh_token.client_id, c->refresh_token.client_secret,
698 c->refresh_token.refresh_token);
699 memset(&request, 0, sizeof(grpc_httpcli_request));
700 request.host = GRPC_GOOGLE_OAUTH2_SERVICE_HOST;
701 request.path = GRPC_GOOGLE_OAUTH2_SERVICE_TOKEN_PATH;
702 request.hdr_count = 1;
703 request.hdrs = &header;
Craig Tillerf53d9c82015-08-04 14:19:43 -0700704 request.handshaker = &grpc_httpcli_ssl;
Craig Tiller06bac342015-06-01 12:55:57 -0700705 grpc_httpcli_post(httpcli_context, pollset, &request, body, strlen(body),
706 deadline, response_cb, metadata_req);
Julien Boeuf9835cf02015-03-09 16:56:44 -0700707 gpr_free(body);
708}
709
Julien Boeuf510a9202015-08-25 21:51:07 -0700710grpc_credentials *
711grpc_refresh_token_credentials_create_from_auth_refresh_token(
Julien Boeuf54006062015-07-07 19:13:04 -0700712 grpc_auth_refresh_token refresh_token) {
Julien Boeuf510a9202015-08-25 21:51:07 -0700713 grpc_google_refresh_token_credentials *c;
Julien Boeuf9835cf02015-03-09 16:56:44 -0700714 if (!grpc_auth_refresh_token_is_valid(&refresh_token)) {
Craig Tiller83b826a2015-05-13 13:43:01 -0700715 gpr_log(GPR_ERROR, "Invalid input for refresh token credentials creation");
Julien Boeuf9835cf02015-03-09 16:56:44 -0700716 return NULL;
717 }
Julien Boeuf510a9202015-08-25 21:51:07 -0700718 c = gpr_malloc(sizeof(grpc_google_refresh_token_credentials));
719 memset(c, 0, sizeof(grpc_google_refresh_token_credentials));
Julien Boeuf9835cf02015-03-09 16:56:44 -0700720 init_oauth2_token_fetcher(&c->base, refresh_token_fetch_oauth2);
721 c->base.base.vtable = &refresh_token_vtable;
722 c->refresh_token = refresh_token;
723 return &c->base.base;
724}
725
Julien Boeuf510a9202015-08-25 21:51:07 -0700726grpc_credentials *grpc_google_refresh_token_credentials_create(
Julien Boeufc5b570f2015-08-25 17:47:55 -0700727 const char *json_refresh_token, void *reserved) {
728 GPR_ASSERT(reserved == NULL);
Julien Boeuf54006062015-07-07 19:13:04 -0700729 return grpc_refresh_token_credentials_create_from_auth_refresh_token(
730 grpc_auth_refresh_token_create_from_string(json_refresh_token));
731}
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800732
Julien Boeufea456fc2015-07-07 15:23:30 -0700733/* -- Metadata-only credentials. -- */
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800734
Julien Boeuffe1478f2015-08-30 21:57:38 -0700735static void md_only_test_destruct(grpc_credentials *creds) {
Julien Boeufea456fc2015-07-07 15:23:30 -0700736 grpc_md_only_test_credentials *c = (grpc_md_only_test_credentials *)creds;
737 grpc_credentials_md_store_unref(c->md_store);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800738}
739
Julien Boeufea456fc2015-07-07 15:23:30 -0700740static int md_only_test_has_request_metadata(const grpc_credentials *creds) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800741 return 1;
742}
743
Julien Boeufea456fc2015-07-07 15:23:30 -0700744static int md_only_test_has_request_metadata_only(
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800745 const grpc_credentials *creds) {
746 return 1;
747}
748
ctiller58393c22015-01-07 14:03:30 -0800749void on_simulated_token_fetch_done(void *user_data, int success) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800750 grpc_credentials_metadata_request *r =
751 (grpc_credentials_metadata_request *)user_data;
Julien Boeufea456fc2015-07-07 15:23:30 -0700752 grpc_md_only_test_credentials *c = (grpc_md_only_test_credentials *)r->creds;
ctiller58393c22015-01-07 14:03:30 -0800753 GPR_ASSERT(success);
Craig Tillerd6c98df2015-08-18 09:33:44 -0700754 r->cb(r->user_data, c->md_store->entries, c->md_store->num_entries,
755 GRPC_CREDENTIALS_OK);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800756 grpc_credentials_metadata_request_destroy(r);
757}
758
Julien Boeufea456fc2015-07-07 15:23:30 -0700759static void md_only_test_get_request_metadata(grpc_credentials *creds,
Craig Tillerd6c98df2015-08-18 09:33:44 -0700760 grpc_pollset *pollset,
761 const char *service_url,
762 grpc_credentials_metadata_cb cb,
763 void *user_data) {
Julien Boeufea456fc2015-07-07 15:23:30 -0700764 grpc_md_only_test_credentials *c = (grpc_md_only_test_credentials *)creds;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800765
766 if (c->is_async) {
David Garcia Quintas69ba8712015-06-01 11:29:42 -0700767 grpc_credentials_metadata_request *cb_arg =
David Garcia Quintas8b8cce02015-05-31 12:39:40 -0700768 grpc_credentials_metadata_request_create(creds, cb, user_data);
David Garcia Quintas69ba8712015-06-01 11:29:42 -0700769 grpc_iomgr_closure_init(cb_arg->on_simulated_token_fetch_done_closure,
770 on_simulated_token_fetch_done, cb_arg);
771 grpc_iomgr_add_callback(cb_arg->on_simulated_token_fetch_done_closure);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800772 } else {
Julien Boeufea456fc2015-07-07 15:23:30 -0700773 cb(user_data, c->md_store->entries, 1, GRPC_CREDENTIALS_OK);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800774 }
775}
776
Julien Boeufea456fc2015-07-07 15:23:30 -0700777static grpc_credentials_vtable md_only_test_vtable = {
Julien Boeuffe1478f2015-08-30 21:57:38 -0700778 md_only_test_destruct, md_only_test_has_request_metadata,
Julien Boeufea456fc2015-07-07 15:23:30 -0700779 md_only_test_has_request_metadata_only, md_only_test_get_request_metadata,
Craig Tiller83b826a2015-05-13 13:43:01 -0700780 NULL};
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800781
Julien Boeufea456fc2015-07-07 15:23:30 -0700782grpc_credentials *grpc_md_only_test_credentials_create(const char *md_key,
783 const char *md_value,
784 int is_async) {
785 grpc_md_only_test_credentials *c =
786 gpr_malloc(sizeof(grpc_md_only_test_credentials));
787 memset(c, 0, sizeof(grpc_md_only_test_credentials));
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800788 c->base.type = GRPC_CREDENTIALS_TYPE_OAUTH2;
Julien Boeufea456fc2015-07-07 15:23:30 -0700789 c->base.vtable = &md_only_test_vtable;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800790 gpr_ref_init(&c->base.refcount, 1);
Julien Boeufea456fc2015-07-07 15:23:30 -0700791 c->md_store = grpc_credentials_md_store_create(1);
792 grpc_credentials_md_store_add_cstrings(c->md_store, md_key, md_value);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800793 c->is_async = is_async;
794 return &c->base;
795}
796
Julien Boeuf2805be12015-07-01 02:47:18 -0700797/* -- Oauth2 Access Token credentials. -- */
798
Julien Boeuffe1478f2015-08-30 21:57:38 -0700799static void access_token_destruct(grpc_credentials *creds) {
Julien Boeuf2805be12015-07-01 02:47:18 -0700800 grpc_access_token_credentials *c = (grpc_access_token_credentials *)creds;
801 grpc_credentials_md_store_unref(c->access_token_md);
Julien Boeuf2805be12015-07-01 02:47:18 -0700802}
803
804static int access_token_has_request_metadata(const grpc_credentials *creds) {
805 return 1;
806}
807
808static int access_token_has_request_metadata_only(
809 const grpc_credentials *creds) {
810 return 1;
811}
812
813static void access_token_get_request_metadata(grpc_credentials *creds,
Craig Tillerd6c98df2015-08-18 09:33:44 -0700814 grpc_pollset *pollset,
815 const char *service_url,
816 grpc_credentials_metadata_cb cb,
817 void *user_data) {
Julien Boeuf2805be12015-07-01 02:47:18 -0700818 grpc_access_token_credentials *c = (grpc_access_token_credentials *)creds;
819 cb(user_data, c->access_token_md->entries, 1, GRPC_CREDENTIALS_OK);
820}
821
822static grpc_credentials_vtable access_token_vtable = {
Julien Boeuffe1478f2015-08-30 21:57:38 -0700823 access_token_destruct, access_token_has_request_metadata,
Julien Boeuf2805be12015-07-01 02:47:18 -0700824 access_token_has_request_metadata_only, access_token_get_request_metadata,
825 NULL};
826
Julien Boeufc5b570f2015-08-25 17:47:55 -0700827grpc_credentials *grpc_access_token_credentials_create(const char *access_token,
828 void *reserved) {
Julien Boeuf2805be12015-07-01 02:47:18 -0700829 grpc_access_token_credentials *c =
830 gpr_malloc(sizeof(grpc_access_token_credentials));
831 char *token_md_value;
Julien Boeufc5b570f2015-08-25 17:47:55 -0700832 GPR_ASSERT(reserved == NULL);
Julien Boeuf2805be12015-07-01 02:47:18 -0700833 memset(c, 0, sizeof(grpc_access_token_credentials));
834 c->base.type = GRPC_CREDENTIALS_TYPE_OAUTH2;
835 c->base.vtable = &access_token_vtable;
836 gpr_ref_init(&c->base.refcount, 1);
837 c->access_token_md = grpc_credentials_md_store_create(1);
838 gpr_asprintf(&token_md_value, "Bearer %s", access_token);
839 grpc_credentials_md_store_add_cstrings(
840 c->access_token_md, GRPC_AUTHORIZATION_METADATA_KEY, token_md_value);
841 gpr_free(token_md_value);
842 return &c->base;
843}
844
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800845/* -- Fake transport security credentials. -- */
846
Julien Boeuffe1478f2015-08-30 21:57:38 -0700847static void fake_transport_security_credentials_destruct(
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800848 grpc_credentials *creds) {
Julien Boeuffe1478f2015-08-30 21:57:38 -0700849 /* Nothing to do here. */
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800850}
851
Julien Boeuffe1478f2015-08-30 21:57:38 -0700852static void fake_transport_security_server_credentials_destruct(
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800853 grpc_server_credentials *creds) {
Julien Boeuffe1478f2015-08-30 21:57:38 -0700854 /* Nothing to do here. */
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800855}
856
857static int fake_transport_security_has_request_metadata(
858 const grpc_credentials *creds) {
859 return 0;
860}
861
862static int fake_transport_security_has_request_metadata_only(
863 const grpc_credentials *creds) {
864 return 0;
865}
866
Craig Tiller8674cb12015-06-05 07:09:25 -0700867static grpc_security_status fake_transport_security_create_security_connector(
Julien Boeuf7d1d9ca2015-04-17 14:38:48 -0700868 grpc_credentials *c, const char *target, const grpc_channel_args *args,
869 grpc_credentials *request_metadata_creds,
870 grpc_channel_security_connector **sc, grpc_channel_args **new_args) {
871 *sc = grpc_fake_channel_security_connector_create(request_metadata_creds, 1);
872 return GRPC_SECURITY_OK;
873}
874
875static grpc_security_status
876fake_transport_security_server_create_security_connector(
877 grpc_server_credentials *c, grpc_security_connector **sc) {
878 *sc = grpc_fake_server_security_connector_create();
879 return GRPC_SECURITY_OK;
880}
881
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800882static grpc_credentials_vtable fake_transport_security_credentials_vtable = {
Julien Boeuffe1478f2015-08-30 21:57:38 -0700883 fake_transport_security_credentials_destruct,
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800884 fake_transport_security_has_request_metadata,
Julien Boeuf75c9b6f2015-05-29 13:12:12 -0700885 fake_transport_security_has_request_metadata_only, NULL,
Julien Boeuf7d1d9ca2015-04-17 14:38:48 -0700886 fake_transport_security_create_security_connector};
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800887
888static grpc_server_credentials_vtable
889 fake_transport_security_server_credentials_vtable = {
Julien Boeuffe1478f2015-08-30 21:57:38 -0700890 fake_transport_security_server_credentials_destruct,
Julien Boeuf7d1d9ca2015-04-17 14:38:48 -0700891 fake_transport_security_server_create_security_connector};
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800892
893grpc_credentials *grpc_fake_transport_security_credentials_create(void) {
894 grpc_credentials *c = gpr_malloc(sizeof(grpc_credentials));
895 memset(c, 0, sizeof(grpc_credentials));
896 c->type = GRPC_CREDENTIALS_TYPE_FAKE_TRANSPORT_SECURITY;
897 c->vtable = &fake_transport_security_credentials_vtable;
898 gpr_ref_init(&c->refcount, 1);
899 return c;
900}
901
Craig Tiller3eef2c42015-01-15 11:37:54 -0800902grpc_server_credentials *grpc_fake_transport_security_server_credentials_create(
903 void) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800904 grpc_server_credentials *c = gpr_malloc(sizeof(grpc_server_credentials));
905 memset(c, 0, sizeof(grpc_server_credentials));
906 c->type = GRPC_CREDENTIALS_TYPE_FAKE_TRANSPORT_SECURITY;
Julien Boeuffe1478f2015-08-30 21:57:38 -0700907 gpr_ref_init(&c->refcount, 1);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800908 c->vtable = &fake_transport_security_server_credentials_vtable;
909 return c;
910}
911
nnoble0c475f02014-12-05 15:37:39 -0800912/* -- Composite credentials. -- */
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800913
nnoble0c475f02014-12-05 15:37:39 -0800914typedef struct {
nnoble0c475f02014-12-05 15:37:39 -0800915 grpc_composite_credentials *composite_creds;
916 size_t creds_index;
Julien Boeuf75c9b6f2015-05-29 13:12:12 -0700917 grpc_credentials_md_store *md_elems;
Julien Boeuff47a5cb2015-02-18 12:24:08 -0800918 char *service_url;
nnoble0c475f02014-12-05 15:37:39 -0800919 void *user_data;
Craig Tiller06bac342015-06-01 12:55:57 -0700920 grpc_pollset *pollset;
nnoble0c475f02014-12-05 15:37:39 -0800921 grpc_credentials_metadata_cb cb;
922} grpc_composite_credentials_metadata_context;
923
Julien Boeuffe1478f2015-08-30 21:57:38 -0700924static void composite_destruct(grpc_credentials *creds) {
nnoble0c475f02014-12-05 15:37:39 -0800925 grpc_composite_credentials *c = (grpc_composite_credentials *)creds;
926 size_t i;
927 for (i = 0; i < c->inner.num_creds; i++) {
928 grpc_credentials_unref(c->inner.creds_array[i]);
929 }
930 gpr_free(c->inner.creds_array);
nnoble0c475f02014-12-05 15:37:39 -0800931}
932
933static int composite_has_request_metadata(const grpc_credentials *creds) {
934 const grpc_composite_credentials *c =
935 (const grpc_composite_credentials *)creds;
936 size_t i;
937 for (i = 0; i < c->inner.num_creds; i++) {
938 if (grpc_credentials_has_request_metadata(c->inner.creds_array[i])) {
939 return 1;
940 }
941 }
942 return 0;
943}
944
945static int composite_has_request_metadata_only(const grpc_credentials *creds) {
946 const grpc_composite_credentials *c =
947 (const grpc_composite_credentials *)creds;
948 size_t i;
949 for (i = 0; i < c->inner.num_creds; i++) {
950 if (!grpc_credentials_has_request_metadata_only(c->inner.creds_array[i])) {
951 return 0;
952 }
953 }
954 return 1;
955}
956
957static void composite_md_context_destroy(
958 grpc_composite_credentials_metadata_context *ctx) {
Julien Boeuf75c9b6f2015-05-29 13:12:12 -0700959 grpc_credentials_md_store_unref(ctx->md_elems);
Julien Boeuff47a5cb2015-02-18 12:24:08 -0800960 if (ctx->service_url != NULL) gpr_free(ctx->service_url);
nnoble0c475f02014-12-05 15:37:39 -0800961 gpr_free(ctx);
962}
963
Julien Boeuf75c9b6f2015-05-29 13:12:12 -0700964static void composite_metadata_cb(void *user_data,
965 grpc_credentials_md *md_elems, size_t num_md,
nnoble0c475f02014-12-05 15:37:39 -0800966 grpc_credentials_status status) {
967 grpc_composite_credentials_metadata_context *ctx =
968 (grpc_composite_credentials_metadata_context *)user_data;
nnoble0c475f02014-12-05 15:37:39 -0800969 if (status != GRPC_CREDENTIALS_OK) {
970 ctx->cb(ctx->user_data, NULL, 0, status);
971 return;
972 }
973
974 /* Copy the metadata in the context. */
975 if (num_md > 0) {
Julien Boeuf75c9b6f2015-05-29 13:12:12 -0700976 size_t i;
nnoble0c475f02014-12-05 15:37:39 -0800977 for (i = 0; i < num_md; i++) {
Julien Boeuf75c9b6f2015-05-29 13:12:12 -0700978 grpc_credentials_md_store_add(ctx->md_elems, md_elems[i].key,
979 md_elems[i].value);
nnoble0c475f02014-12-05 15:37:39 -0800980 }
nnoble0c475f02014-12-05 15:37:39 -0800981 }
982
983 /* See if we need to get some more metadata. */
984 while (ctx->creds_index < ctx->composite_creds->inner.num_creds) {
985 grpc_credentials *inner_creds =
986 ctx->composite_creds->inner.creds_array[ctx->creds_index++];
987 if (grpc_credentials_has_request_metadata(inner_creds)) {
Craig Tiller06bac342015-06-01 12:55:57 -0700988 grpc_credentials_get_request_metadata(inner_creds, ctx->pollset,
989 ctx->service_url,
Julien Boeuff47a5cb2015-02-18 12:24:08 -0800990 composite_metadata_cb, ctx);
nnoble0c475f02014-12-05 15:37:39 -0800991 return;
992 }
993 }
994
995 /* We're done!. */
Julien Boeuf75c9b6f2015-05-29 13:12:12 -0700996 ctx->cb(ctx->user_data, ctx->md_elems->entries, ctx->md_elems->num_entries,
997 GRPC_CREDENTIALS_OK);
nnoble0c475f02014-12-05 15:37:39 -0800998 composite_md_context_destroy(ctx);
999}
1000
1001static void composite_get_request_metadata(grpc_credentials *creds,
Craig Tiller06bac342015-06-01 12:55:57 -07001002 grpc_pollset *pollset,
Julien Boeuff47a5cb2015-02-18 12:24:08 -08001003 const char *service_url,
nnoble0c475f02014-12-05 15:37:39 -08001004 grpc_credentials_metadata_cb cb,
1005 void *user_data) {
1006 grpc_composite_credentials *c = (grpc_composite_credentials *)creds;
1007 grpc_composite_credentials_metadata_context *ctx;
1008 if (!grpc_credentials_has_request_metadata(creds)) {
1009 cb(user_data, NULL, 0, GRPC_CREDENTIALS_OK);
1010 return;
1011 }
1012 ctx = gpr_malloc(sizeof(grpc_composite_credentials_metadata_context));
1013 memset(ctx, 0, sizeof(grpc_composite_credentials_metadata_context));
Julien Boeuff47a5cb2015-02-18 12:24:08 -08001014 ctx->service_url = gpr_strdup(service_url);
nnoble0c475f02014-12-05 15:37:39 -08001015 ctx->user_data = user_data;
1016 ctx->cb = cb;
1017 ctx->composite_creds = c;
Craig Tiller06bac342015-06-01 12:55:57 -07001018 ctx->pollset = pollset;
Julien Boeuf75c9b6f2015-05-29 13:12:12 -07001019 ctx->md_elems = grpc_credentials_md_store_create(c->inner.num_creds);
nnoble0c475f02014-12-05 15:37:39 -08001020 while (ctx->creds_index < c->inner.num_creds) {
1021 grpc_credentials *inner_creds = c->inner.creds_array[ctx->creds_index++];
1022 if (grpc_credentials_has_request_metadata(inner_creds)) {
Craig Tiller06bac342015-06-01 12:55:57 -07001023 grpc_credentials_get_request_metadata(inner_creds, pollset, service_url,
Julien Boeuff47a5cb2015-02-18 12:24:08 -08001024 composite_metadata_cb, ctx);
nnoble0c475f02014-12-05 15:37:39 -08001025 return;
1026 }
1027 }
1028 GPR_ASSERT(0); /* Should have exited before. */
1029}
1030
Julien Boeuf7d1d9ca2015-04-17 14:38:48 -07001031static grpc_security_status composite_create_security_connector(
1032 grpc_credentials *creds, const char *target, const grpc_channel_args *args,
1033 grpc_credentials *request_metadata_creds,
1034 grpc_channel_security_connector **sc, grpc_channel_args **new_args) {
1035 grpc_composite_credentials *c = (grpc_composite_credentials *)creds;
1036 if (c->connector_creds == NULL) {
1037 gpr_log(GPR_ERROR,
1038 "Cannot create security connector, missing connector credentials.");
1039 return GRPC_SECURITY_ERROR;
1040 }
1041 return grpc_credentials_create_security_connector(c->connector_creds, target,
1042 args, creds, sc, new_args);
1043}
1044
nnoble0c475f02014-12-05 15:37:39 -08001045static grpc_credentials_vtable composite_credentials_vtable = {
Julien Boeuffe1478f2015-08-30 21:57:38 -07001046 composite_destruct, composite_has_request_metadata,
Julien Boeuf75c9b6f2015-05-29 13:12:12 -07001047 composite_has_request_metadata_only, composite_get_request_metadata,
Craig Tiller83b826a2015-05-13 13:43:01 -07001048 composite_create_security_connector};
nnoble0c475f02014-12-05 15:37:39 -08001049
1050static grpc_credentials_array get_creds_array(grpc_credentials **creds_addr) {
1051 grpc_credentials_array result;
1052 grpc_credentials *creds = *creds_addr;
1053 result.creds_array = creds_addr;
1054 result.num_creds = 1;
Ronnie Sahlberg2ad8d212015-03-07 08:39:22 -08001055 if (strcmp(creds->type, GRPC_CREDENTIALS_TYPE_COMPOSITE) == 0) {
nnoble0c475f02014-12-05 15:37:39 -08001056 result = *grpc_composite_credentials_get_credentials(creds);
1057 }
1058 return result;
1059}
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001060
1061grpc_credentials *grpc_composite_credentials_create(grpc_credentials *creds1,
Julien Boeufc5b570f2015-08-25 17:47:55 -07001062 grpc_credentials *creds2,
1063 void *reserved) {
nnoble0c475f02014-12-05 15:37:39 -08001064 size_t i;
Julien Boeuf7d1d9ca2015-04-17 14:38:48 -07001065 size_t creds_array_byte_size;
nnoble0c475f02014-12-05 15:37:39 -08001066 grpc_credentials_array creds1_array;
1067 grpc_credentials_array creds2_array;
1068 grpc_composite_credentials *c;
Julien Boeufc5b570f2015-08-25 17:47:55 -07001069 GPR_ASSERT(reserved == NULL);
nnoble0c475f02014-12-05 15:37:39 -08001070 GPR_ASSERT(creds1 != NULL);
1071 GPR_ASSERT(creds2 != NULL);
1072 c = gpr_malloc(sizeof(grpc_composite_credentials));
1073 memset(c, 0, sizeof(grpc_composite_credentials));
1074 c->base.type = GRPC_CREDENTIALS_TYPE_COMPOSITE;
1075 c->base.vtable = &composite_credentials_vtable;
1076 gpr_ref_init(&c->base.refcount, 1);
1077 creds1_array = get_creds_array(&creds1);
1078 creds2_array = get_creds_array(&creds2);
1079 c->inner.num_creds = creds1_array.num_creds + creds2_array.num_creds;
Julien Boeuf7d1d9ca2015-04-17 14:38:48 -07001080 creds_array_byte_size = c->inner.num_creds * sizeof(grpc_credentials *);
1081 c->inner.creds_array = gpr_malloc(creds_array_byte_size);
1082 memset(c->inner.creds_array, 0, creds_array_byte_size);
nnoble0c475f02014-12-05 15:37:39 -08001083 for (i = 0; i < creds1_array.num_creds; i++) {
Julien Boeuf7d1d9ca2015-04-17 14:38:48 -07001084 grpc_credentials *cur_creds = creds1_array.creds_array[i];
1085 if (!grpc_credentials_has_request_metadata_only(cur_creds)) {
1086 if (c->connector_creds == NULL) {
1087 c->connector_creds = cur_creds;
1088 } else {
1089 gpr_log(GPR_ERROR, "Cannot compose multiple connector credentials.");
1090 goto fail;
1091 }
1092 }
1093 c->inner.creds_array[i] = grpc_credentials_ref(cur_creds);
nnoble0c475f02014-12-05 15:37:39 -08001094 }
1095 for (i = 0; i < creds2_array.num_creds; i++) {
Julien Boeuf7d1d9ca2015-04-17 14:38:48 -07001096 grpc_credentials *cur_creds = creds2_array.creds_array[i];
1097 if (!grpc_credentials_has_request_metadata_only(cur_creds)) {
1098 if (c->connector_creds == NULL) {
1099 c->connector_creds = cur_creds;
1100 } else {
1101 gpr_log(GPR_ERROR, "Cannot compose multiple connector credentials.");
1102 goto fail;
1103 }
1104 }
nnoble0c475f02014-12-05 15:37:39 -08001105 c->inner.creds_array[i + creds1_array.num_creds] =
Julien Boeuf7d1d9ca2015-04-17 14:38:48 -07001106 grpc_credentials_ref(cur_creds);
nnoble0c475f02014-12-05 15:37:39 -08001107 }
1108 return &c->base;
Julien Boeuf7d1d9ca2015-04-17 14:38:48 -07001109
1110fail:
1111 grpc_credentials_unref(&c->base);
1112 return NULL;
nnoble0c475f02014-12-05 15:37:39 -08001113}
1114
1115const grpc_credentials_array *grpc_composite_credentials_get_credentials(
1116 grpc_credentials *creds) {
1117 const grpc_composite_credentials *c =
1118 (const grpc_composite_credentials *)creds;
Ronnie Sahlberg2ad8d212015-03-07 08:39:22 -08001119 GPR_ASSERT(strcmp(creds->type, GRPC_CREDENTIALS_TYPE_COMPOSITE) == 0);
nnoble0c475f02014-12-05 15:37:39 -08001120 return &c->inner;
1121}
1122
jboeuf6ad120e2015-01-12 17:08:15 -08001123grpc_credentials *grpc_credentials_contains_type(
1124 grpc_credentials *creds, const char *type,
1125 grpc_credentials **composite_creds) {
1126 size_t i;
Ronnie Sahlberg2ad8d212015-03-07 08:39:22 -08001127 if (strcmp(creds->type, type) == 0) {
jboeuf6ad120e2015-01-12 17:08:15 -08001128 if (composite_creds != NULL) *composite_creds = NULL;
1129 return creds;
Ronnie Sahlberg2ad8d212015-03-07 08:39:22 -08001130 } else if (strcmp(creds->type, GRPC_CREDENTIALS_TYPE_COMPOSITE) == 0) {
jboeuf6ad120e2015-01-12 17:08:15 -08001131 const grpc_credentials_array *inner_creds_array =
1132 grpc_composite_credentials_get_credentials(creds);
1133 for (i = 0; i < inner_creds_array->num_creds; i++) {
Ronnie Sahlberg2ad8d212015-03-07 08:39:22 -08001134 if (strcmp(type, inner_creds_array->creds_array[i]->type) == 0) {
jboeuf6ad120e2015-01-12 17:08:15 -08001135 if (composite_creds != NULL) *composite_creds = creds;
1136 return inner_creds_array->creds_array[i];
1137 }
1138 }
1139 }
1140 return NULL;
1141}
1142
nnoble0c475f02014-12-05 15:37:39 -08001143/* -- IAM credentials. -- */
1144
Julien Boeuffe1478f2015-08-30 21:57:38 -07001145static void iam_destruct(grpc_credentials *creds) {
Julien Boeuf510a9202015-08-25 21:51:07 -07001146 grpc_google_iam_credentials *c = (grpc_google_iam_credentials *)creds;
Julien Boeuf75c9b6f2015-05-29 13:12:12 -07001147 grpc_credentials_md_store_unref(c->iam_md);
nnoble0c475f02014-12-05 15:37:39 -08001148}
1149
Craig Tiller83b826a2015-05-13 13:43:01 -07001150static int iam_has_request_metadata(const grpc_credentials *creds) { return 1; }
nnoble0c475f02014-12-05 15:37:39 -08001151
1152static int iam_has_request_metadata_only(const grpc_credentials *creds) {
1153 return 1;
1154}
1155
1156static void iam_get_request_metadata(grpc_credentials *creds,
Craig Tiller06bac342015-06-01 12:55:57 -07001157 grpc_pollset *pollset,
Julien Boeuff47a5cb2015-02-18 12:24:08 -08001158 const char *service_url,
nnoble0c475f02014-12-05 15:37:39 -08001159 grpc_credentials_metadata_cb cb,
1160 void *user_data) {
Julien Boeuf510a9202015-08-25 21:51:07 -07001161 grpc_google_iam_credentials *c = (grpc_google_iam_credentials *)creds;
Julien Boeuf75c9b6f2015-05-29 13:12:12 -07001162 cb(user_data, c->iam_md->entries, c->iam_md->num_entries,
1163 GRPC_CREDENTIALS_OK);
nnoble0c475f02014-12-05 15:37:39 -08001164}
1165
1166static grpc_credentials_vtable iam_vtable = {
Julien Boeuffe1478f2015-08-30 21:57:38 -07001167 iam_destruct, iam_has_request_metadata, iam_has_request_metadata_only,
Julien Boeuf75c9b6f2015-05-29 13:12:12 -07001168 iam_get_request_metadata, NULL};
nnoble0c475f02014-12-05 15:37:39 -08001169
Julien Boeuf510a9202015-08-25 21:51:07 -07001170grpc_credentials *grpc_google_iam_credentials_create(
1171 const char *token, const char *authority_selector, void *reserved) {
1172 grpc_google_iam_credentials *c;
Julien Boeufc5b570f2015-08-25 17:47:55 -07001173 GPR_ASSERT(reserved == NULL);
nnoble0c475f02014-12-05 15:37:39 -08001174 GPR_ASSERT(token != NULL);
1175 GPR_ASSERT(authority_selector != NULL);
Julien Boeuf510a9202015-08-25 21:51:07 -07001176 c = gpr_malloc(sizeof(grpc_google_iam_credentials));
1177 memset(c, 0, sizeof(grpc_google_iam_credentials));
nnoble0c475f02014-12-05 15:37:39 -08001178 c->base.type = GRPC_CREDENTIALS_TYPE_IAM;
1179 c->base.vtable = &iam_vtable;
1180 gpr_ref_init(&c->base.refcount, 1);
Julien Boeuf75c9b6f2015-05-29 13:12:12 -07001181 c->iam_md = grpc_credentials_md_store_create(2);
1182 grpc_credentials_md_store_add_cstrings(
1183 c->iam_md, GRPC_IAM_AUTHORIZATION_TOKEN_METADATA_KEY, token);
1184 grpc_credentials_md_store_add_cstrings(
1185 c->iam_md, GRPC_IAM_AUTHORITY_SELECTOR_METADATA_KEY, authority_selector);
nnoble0c475f02014-12-05 15:37:39 -08001186 return &c->base;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001187}