blob: f7a2e7378588a9575ff7851ecc4ad7a85d1183ab [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"
Masood Malekghassemi76c3d742015-08-19 18:22:53 -070044#include "src/core/surface/api_trace.h"
Craig Tiller485d7762015-01-23 12:54:05 -080045#include "src/core/support/string.h"
Julien Boeuf7d1d9ca2015-04-17 14:38:48 -070046
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080047#include <grpc/support/alloc.h>
48#include <grpc/support/log.h>
Masood Malekghassemi701af602015-06-03 15:01:17 -070049#include <grpc/support/string_util.h>
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080050#include <grpc/support/sync.h>
Craig Tiller8664ca62015-09-09 12:30:59 -070051#include <grpc/support/thd.h>
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080052#include <grpc/support/time.h>
53
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080054/* -- Common. -- */
55
Craig Tillera82950e2015-09-22 12:33:20 -070056struct grpc_credentials_metadata_request {
Julien Boeuf441176d2015-10-09 21:14:07 -070057 grpc_call_credentials *creds;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080058 grpc_credentials_metadata_cb cb;
59 void *user_data;
Julien Boeufb037bb62015-07-08 14:58:14 -070060};
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080061
62static grpc_credentials_metadata_request *
Julien Boeuf441176d2015-10-09 21:14:07 -070063grpc_credentials_metadata_request_create(grpc_call_credentials *creds,
Craig Tillera82950e2015-09-22 12:33:20 -070064 grpc_credentials_metadata_cb cb,
65 void *user_data) {
66 grpc_credentials_metadata_request *r =
67 gpr_malloc(sizeof(grpc_credentials_metadata_request));
Julien Boeuf441176d2015-10-09 21:14:07 -070068 r->creds = grpc_call_credentials_ref(creds);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080069 r->cb = cb;
70 r->user_data = user_data;
71 return r;
72}
73
Craig Tillera82950e2015-09-22 12:33:20 -070074static void grpc_credentials_metadata_request_destroy(
75 grpc_credentials_metadata_request *r) {
Julien Boeuf441176d2015-10-09 21:14:07 -070076 grpc_call_credentials_unref(r->creds);
Craig Tillera82950e2015-09-22 12:33:20 -070077 gpr_free(r);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080078}
79
Julien Boeuf441176d2015-10-09 21:14:07 -070080grpc_channel_credentials *grpc_channel_credentials_ref(
81 grpc_channel_credentials *creds) {
Craig Tillera82950e2015-09-22 12:33:20 -070082 if (creds == NULL) return NULL;
83 gpr_ref(&creds->refcount);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080084 return creds;
85}
86
Julien Boeuf441176d2015-10-09 21:14:07 -070087void grpc_channel_credentials_unref(grpc_channel_credentials *creds) {
Craig Tillera82950e2015-09-22 12:33:20 -070088 if (creds == NULL) return;
89 if (gpr_unref(&creds->refcount)) {
Julien Boeufb73cbc22015-10-20 21:52:54 -070090 if (creds->vtable->destruct != NULL) creds->vtable->destruct(creds);
Craig Tillera82950e2015-09-22 12:33:20 -070091 gpr_free(creds);
92 }
93}
94
Julien Boeuf441176d2015-10-09 21:14:07 -070095void grpc_channel_credentials_release(grpc_channel_credentials *creds) {
96 GRPC_API_TRACE("grpc_channel_credentials_release(creds=%p)", 1, (creds));
97 grpc_channel_credentials_unref(creds);
Craig Tillera82950e2015-09-22 12:33:20 -070098}
99
Julien Boeuf441176d2015-10-09 21:14:07 -0700100grpc_call_credentials *grpc_call_credentials_ref(grpc_call_credentials *creds) {
101 if (creds == NULL) return NULL;
102 gpr_ref(&creds->refcount);
103 return creds;
Craig Tillera82950e2015-09-22 12:33:20 -0700104}
105
Julien Boeuf441176d2015-10-09 21:14:07 -0700106void grpc_call_credentials_unref(grpc_call_credentials *creds) {
107 if (creds == NULL) return;
108 if (gpr_unref(&creds->refcount)) {
Julien Boeufb73cbc22015-10-20 21:52:54 -0700109 if (creds->vtable->destruct != NULL) creds->vtable->destruct(creds);
Julien Boeuf441176d2015-10-09 21:14:07 -0700110 gpr_free(creds);
111 }
112}
113
114void grpc_call_credentials_release(grpc_call_credentials *creds) {
115 GRPC_API_TRACE("grpc_call_credentials_release(creds=%p)", 1, (creds));
116 grpc_call_credentials_unref(creds);
Craig Tillera82950e2015-09-22 12:33:20 -0700117}
118
Craig Tillerb1136492015-11-18 11:30:17 -0800119void grpc_call_credentials_get_request_metadata(grpc_exec_ctx *exec_ctx,
120 grpc_call_credentials *creds,
121 grpc_pollset *pollset,
122 const char *service_url,
123 grpc_credentials_metadata_cb cb,
124 void *user_data) {
Julien Boeuf441176d2015-10-09 21:14:07 -0700125 if (creds == NULL || creds->vtable->get_request_metadata == NULL) {
Craig Tillera82950e2015-09-22 12:33:20 -0700126 if (cb != NULL) {
127 cb(exec_ctx, user_data, NULL, 0, GRPC_CREDENTIALS_OK);
128 }
nnoble0c475f02014-12-05 15:37:39 -0800129 return;
Craig Tillera82950e2015-09-22 12:33:20 -0700130 }
131 creds->vtable->get_request_metadata(exec_ctx, creds, pollset, service_url, cb,
132 user_data);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800133}
134
Julien Boeuf441176d2015-10-09 21:14:07 -0700135grpc_security_status grpc_channel_credentials_create_security_connector(
136 grpc_channel_credentials *channel_creds, const char *target,
137 const grpc_channel_args *args, grpc_channel_security_connector **sc,
138 grpc_channel_args **new_args) {
Julien Boeuf7d1d9ca2015-04-17 14:38:48 -0700139 *new_args = NULL;
Julien Boeufb73cbc22015-10-20 21:52:54 -0700140 if (channel_creds == NULL) {
Craig Tillera82950e2015-09-22 12:33:20 -0700141 return GRPC_SECURITY_ERROR;
142 }
Julien Boeufb73cbc22015-10-20 21:52:54 -0700143 GPR_ASSERT(channel_creds->vtable->create_security_connector != NULL);
144 return channel_creds->vtable->create_security_connector(
145 channel_creds, NULL, target, args, sc, new_args);
Craig Tillerc4885ed2015-04-14 09:51:28 -0700146}
147
Craig Tillera82950e2015-09-22 12:33:20 -0700148grpc_server_credentials *grpc_server_credentials_ref(
149 grpc_server_credentials *creds) {
150 if (creds == NULL) return NULL;
151 gpr_ref(&creds->refcount);
Julien Boeuffe1478f2015-08-30 21:57:38 -0700152 return creds;
153}
154
Craig Tillera82950e2015-09-22 12:33:20 -0700155void grpc_server_credentials_unref(grpc_server_credentials *creds) {
156 if (creds == NULL) return;
157 if (gpr_unref(&creds->refcount)) {
Julien Boeufb73cbc22015-10-20 21:52:54 -0700158 if (creds->vtable->destruct != NULL) creds->vtable->destruct(creds);
Craig Tillera82950e2015-09-22 12:33:20 -0700159 if (creds->processor.destroy != NULL && creds->processor.state != NULL) {
160 creds->processor.destroy(creds->processor.state);
Julien Boeuffe1478f2015-08-30 21:57:38 -0700161 }
Craig Tillera82950e2015-09-22 12:33:20 -0700162 gpr_free(creds);
163 }
Julien Boeuffe1478f2015-08-30 21:57:38 -0700164}
165
Craig Tillera82950e2015-09-22 12:33:20 -0700166void grpc_server_credentials_release(grpc_server_credentials *creds) {
Masood Malekghassemi76c3d742015-08-19 18:22:53 -0700167 GRPC_API_TRACE("grpc_server_credentials_release(creds=%p)", 1, (creds));
Craig Tillera82950e2015-09-22 12:33:20 -0700168 grpc_server_credentials_unref(creds);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800169}
170
Craig Tillera82950e2015-09-22 12:33:20 -0700171grpc_security_status grpc_server_credentials_create_security_connector(
172 grpc_server_credentials *creds, grpc_security_connector **sc) {
173 if (creds == NULL || creds->vtable->create_security_connector == NULL) {
174 gpr_log(GPR_ERROR, "Server credentials cannot create security context.");
175 return GRPC_SECURITY_ERROR;
176 }
177 return creds->vtable->create_security_connector(creds, sc);
Julien Boeuf7d1d9ca2015-04-17 14:38:48 -0700178}
179
Craig Tillera82950e2015-09-22 12:33:20 -0700180void grpc_server_credentials_set_auth_metadata_processor(
181 grpc_server_credentials *creds, grpc_auth_metadata_processor processor) {
Masood Malekghassemi76c3d742015-08-19 18:22:53 -0700182 GRPC_API_TRACE(
183 "grpc_server_credentials_set_auth_metadata_processor("
Craig Tiller4de3e4f2015-10-05 08:55:50 -0700184 "creds=%p, "
185 "processor=grpc_auth_metadata_processor { process: %lx, state: %p })",
Masood Malekghassemi76c3d742015-08-19 18:22:53 -0700186 3, (creds, (unsigned long)processor.process, processor.state));
Craig Tillera82950e2015-09-22 12:33:20 -0700187 if (creds == NULL) return;
188 if (creds->processor.destroy != NULL && creds->processor.state != NULL) {
189 creds->processor.destroy(creds->processor.state);
190 }
Julien Boeuf6bdc9b42015-07-19 21:56:02 -0700191 creds->processor = processor;
192}
193
Julien Boeuf9a529082015-10-08 13:12:14 -0700194static void server_credentials_pointer_arg_destroy(void *p) {
195 grpc_server_credentials_unref(p);
196}
197
198static void *server_credentials_pointer_arg_copy(void *p) {
199 return grpc_server_credentials_ref(p);
200}
201
202grpc_arg grpc_server_credentials_to_arg(grpc_server_credentials *p) {
203 grpc_arg arg;
204 memset(&arg, 0, sizeof(grpc_arg));
205 arg.type = GRPC_ARG_POINTER;
206 arg.key = GRPC_SERVER_CREDENTIALS_ARG;
207 arg.value.pointer.p = p;
208 arg.value.pointer.copy = server_credentials_pointer_arg_copy;
209 arg.value.pointer.destroy = server_credentials_pointer_arg_destroy;
210 return arg;
211}
212
Craig Tiller0581d122015-11-02 14:09:40 -0800213grpc_server_credentials *grpc_server_credentials_from_arg(const grpc_arg *arg) {
Julien Boeuf9a529082015-10-08 13:12:14 -0700214 if (strcmp(arg->key, GRPC_SERVER_CREDENTIALS_ARG) != 0) return NULL;
215 if (arg->type != GRPC_ARG_POINTER) {
216 gpr_log(GPR_ERROR, "Invalid type %d for arg %s", arg->type,
217 GRPC_SERVER_CREDENTIALS_ARG);
218 return NULL;
219 }
220 return arg->value.pointer.p;
221}
222
223grpc_server_credentials *grpc_find_server_credentials_in_args(
224 const grpc_channel_args *args) {
225 size_t i;
226 if (args == NULL) return NULL;
227 for (i = 0; i < args->num_args; i++) {
228 grpc_server_credentials *p =
229 grpc_server_credentials_from_arg(&args->args[i]);
230 if (p != NULL) return p;
231 }
232 return NULL;
233}
234
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800235/* -- Ssl credentials. -- */
236
Julien Boeuf441176d2015-10-09 21:14:07 -0700237static void ssl_destruct(grpc_channel_credentials *creds) {
Craig Tillera82950e2015-09-22 12:33:20 -0700238 grpc_ssl_credentials *c = (grpc_ssl_credentials *)creds;
239 if (c->config.pem_root_certs != NULL) gpr_free(c->config.pem_root_certs);
240 if (c->config.pem_private_key != NULL) gpr_free(c->config.pem_private_key);
241 if (c->config.pem_cert_chain != NULL) gpr_free(c->config.pem_cert_chain);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800242}
243
Craig Tillera82950e2015-09-22 12:33:20 -0700244static void ssl_server_destruct(grpc_server_credentials *creds) {
245 grpc_ssl_server_credentials *c = (grpc_ssl_server_credentials *)creds;
Julien Boeuf8fbcc432015-01-15 16:44:13 -0800246 size_t i;
Craig Tillera82950e2015-09-22 12:33:20 -0700247 for (i = 0; i < c->config.num_key_cert_pairs; i++) {
248 if (c->config.pem_private_keys[i] != NULL) {
249 gpr_free(c->config.pem_private_keys[i]);
Julien Boeuf8fbcc432015-01-15 16:44:13 -0800250 }
Craig Tillera82950e2015-09-22 12:33:20 -0700251 if (c->config.pem_cert_chains[i] != NULL) {
252 gpr_free(c->config.pem_cert_chains[i]);
Julien Boeuf8fbcc432015-01-15 16:44:13 -0800253 }
Craig Tillera82950e2015-09-22 12:33:20 -0700254 }
255 if (c->config.pem_private_keys != NULL) gpr_free(c->config.pem_private_keys);
256 if (c->config.pem_private_keys_sizes != NULL) {
257 gpr_free(c->config.pem_private_keys_sizes);
258 }
259 if (c->config.pem_cert_chains != NULL) gpr_free(c->config.pem_cert_chains);
260 if (c->config.pem_cert_chains_sizes != NULL) {
261 gpr_free(c->config.pem_cert_chains_sizes);
262 }
263 if (c->config.pem_root_certs != NULL) gpr_free(c->config.pem_root_certs);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800264}
265
Craig Tillera82950e2015-09-22 12:33:20 -0700266static grpc_security_status ssl_create_security_connector(
Julien Boeufb73cbc22015-10-20 21:52:54 -0700267 grpc_channel_credentials *creds, grpc_call_credentials *call_creds,
268 const char *target, const grpc_channel_args *args,
Craig Tillera82950e2015-09-22 12:33:20 -0700269 grpc_channel_security_connector **sc, grpc_channel_args **new_args) {
270 grpc_ssl_credentials *c = (grpc_ssl_credentials *)creds;
Julien Boeuf7d1d9ca2015-04-17 14:38:48 -0700271 grpc_security_status status = GRPC_SECURITY_OK;
272 size_t i = 0;
273 const char *overridden_target_name = NULL;
Craig Tillerb9d35962015-09-11 13:31:16 -0700274 grpc_arg new_arg;
Julien Boeuf7d1d9ca2015-04-17 14:38:48 -0700275
Craig Tillera82950e2015-09-22 12:33:20 -0700276 for (i = 0; args && i < args->num_args; i++) {
277 grpc_arg *arg = &args->args[i];
278 if (strcmp(arg->key, GRPC_SSL_TARGET_NAME_OVERRIDE_ARG) == 0 &&
279 arg->type == GRPC_ARG_STRING) {
280 overridden_target_name = arg->value.string;
281 break;
Julien Boeuf7d1d9ca2015-04-17 14:38:48 -0700282 }
Craig Tillera82950e2015-09-22 12:33:20 -0700283 }
284 status = grpc_ssl_channel_security_connector_create(
Julien Boeufb73cbc22015-10-20 21:52:54 -0700285 call_creds, &c->config, target, overridden_target_name, sc);
Craig Tillera82950e2015-09-22 12:33:20 -0700286 if (status != GRPC_SECURITY_OK) {
287 return status;
288 }
Craig Tillerb9d35962015-09-11 13:31:16 -0700289 new_arg.type = GRPC_ARG_STRING;
290 new_arg.key = GRPC_ARG_HTTP2_SCHEME;
291 new_arg.value.string = "https";
292 *new_args = grpc_channel_args_copy_and_add(args, &new_arg, 1);
Julien Boeuf7d1d9ca2015-04-17 14:38:48 -0700293 return status;
294}
295
Craig Tillera82950e2015-09-22 12:33:20 -0700296static grpc_security_status ssl_server_create_security_connector(
297 grpc_server_credentials *creds, grpc_security_connector **sc) {
298 grpc_ssl_server_credentials *c = (grpc_ssl_server_credentials *)creds;
299 return grpc_ssl_server_security_connector_create(&c->config, sc);
Julien Boeuf7d1d9ca2015-04-17 14:38:48 -0700300}
301
Julien Boeuf441176d2015-10-09 21:14:07 -0700302static grpc_channel_credentials_vtable ssl_vtable = {
303 ssl_destruct, ssl_create_security_connector};
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800304
Julien Boeuf7d1d9ca2015-04-17 14:38:48 -0700305static grpc_server_credentials_vtable ssl_server_vtable = {
Craig Tillera82950e2015-09-22 12:33:20 -0700306 ssl_server_destruct, ssl_server_create_security_connector};
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800307
Craig Tillera82950e2015-09-22 12:33:20 -0700308static void ssl_copy_key_material(const char *input, unsigned char **output,
309 size_t *output_size) {
310 *output_size = strlen(input);
311 *output = gpr_malloc(*output_size);
312 memcpy(*output, input, *output_size);
Julien Boeuf8fbcc432015-01-15 16:44:13 -0800313}
314
Craig Tillera82950e2015-09-22 12:33:20 -0700315static void ssl_build_config(const char *pem_root_certs,
316 grpc_ssl_pem_key_cert_pair *pem_key_cert_pair,
317 grpc_ssl_config *config) {
318 if (pem_root_certs != NULL) {
319 ssl_copy_key_material(pem_root_certs, &config->pem_root_certs,
320 &config->pem_root_certs_size);
321 }
322 if (pem_key_cert_pair != NULL) {
323 GPR_ASSERT(pem_key_cert_pair->private_key != NULL);
324 GPR_ASSERT(pem_key_cert_pair->cert_chain != NULL);
325 ssl_copy_key_material(pem_key_cert_pair->private_key,
326 &config->pem_private_key,
327 &config->pem_private_key_size);
328 ssl_copy_key_material(pem_key_cert_pair->cert_chain,
329 &config->pem_cert_chain,
330 &config->pem_cert_chain_size);
331 }
Julien Boeuf8fbcc432015-01-15 16:44:13 -0800332}
333
Craig Tillera82950e2015-09-22 12:33:20 -0700334static void ssl_build_server_config(
335 const char *pem_root_certs, grpc_ssl_pem_key_cert_pair *pem_key_cert_pairs,
336 size_t num_key_cert_pairs, int force_client_auth,
337 grpc_ssl_server_config *config) {
Julien Boeuf8fbcc432015-01-15 16:44:13 -0800338 size_t i;
Julien Boeuf5029b302015-07-21 23:02:16 -0700339 config->force_client_auth = force_client_auth;
Craig Tillera82950e2015-09-22 12:33:20 -0700340 if (pem_root_certs != NULL) {
341 ssl_copy_key_material(pem_root_certs, &config->pem_root_certs,
342 &config->pem_root_certs_size);
343 }
344 if (num_key_cert_pairs > 0) {
345 GPR_ASSERT(pem_key_cert_pairs != NULL);
346 config->pem_private_keys =
347 gpr_malloc(num_key_cert_pairs * sizeof(unsigned char *));
348 config->pem_cert_chains =
349 gpr_malloc(num_key_cert_pairs * sizeof(unsigned char *));
350 config->pem_private_keys_sizes =
351 gpr_malloc(num_key_cert_pairs * sizeof(size_t));
352 config->pem_cert_chains_sizes =
353 gpr_malloc(num_key_cert_pairs * sizeof(size_t));
354 }
Julien Boeuf8fbcc432015-01-15 16:44:13 -0800355 config->num_key_cert_pairs = num_key_cert_pairs;
Craig Tillera82950e2015-09-22 12:33:20 -0700356 for (i = 0; i < num_key_cert_pairs; i++) {
357 GPR_ASSERT(pem_key_cert_pairs[i].private_key != NULL);
358 GPR_ASSERT(pem_key_cert_pairs[i].cert_chain != NULL);
359 ssl_copy_key_material(pem_key_cert_pairs[i].private_key,
360 &config->pem_private_keys[i],
361 &config->pem_private_keys_sizes[i]);
362 ssl_copy_key_material(pem_key_cert_pairs[i].cert_chain,
363 &config->pem_cert_chains[i],
364 &config->pem_cert_chains_sizes[i]);
365 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800366}
367
Julien Boeuf441176d2015-10-09 21:14:07 -0700368grpc_channel_credentials *grpc_ssl_credentials_create(
Craig Tillera82950e2015-09-22 12:33:20 -0700369 const char *pem_root_certs, grpc_ssl_pem_key_cert_pair *pem_key_cert_pair,
370 void *reserved) {
371 grpc_ssl_credentials *c = gpr_malloc(sizeof(grpc_ssl_credentials));
Craig Tiller4de3e4f2015-10-05 08:55:50 -0700372 GRPC_API_TRACE(
373 "grpc_ssl_credentials_create(pem_root_certs=%s, "
374 "pem_key_cert_pair=%p, "
375 "reserved=%p)",
376 3, (pem_root_certs, pem_key_cert_pair, reserved));
Craig Tillera82950e2015-09-22 12:33:20 -0700377 GPR_ASSERT(reserved == NULL);
378 memset(c, 0, sizeof(grpc_ssl_credentials));
Julien Boeuf441176d2015-10-09 21:14:07 -0700379 c->base.type = GRPC_CHANNEL_CREDENTIALS_TYPE_SSL;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800380 c->base.vtable = &ssl_vtable;
Craig Tillera82950e2015-09-22 12:33:20 -0700381 gpr_ref_init(&c->base.refcount, 1);
382 ssl_build_config(pem_root_certs, pem_key_cert_pair, &c->config);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800383 return &c->base;
384}
385
Craig Tillera82950e2015-09-22 12:33:20 -0700386grpc_server_credentials *grpc_ssl_server_credentials_create(
387 const char *pem_root_certs, grpc_ssl_pem_key_cert_pair *pem_key_cert_pairs,
388 size_t num_key_cert_pairs, int force_client_auth, void *reserved) {
389 grpc_ssl_server_credentials *c =
390 gpr_malloc(sizeof(grpc_ssl_server_credentials));
Masood Malekghassemi76c3d742015-08-19 18:22:53 -0700391 GRPC_API_TRACE(
392 "grpc_ssl_server_credentials_create("
Craig Tiller4de3e4f2015-10-05 08:55:50 -0700393 "pem_root_certs=%s, pem_key_cert_pairs=%p, num_key_cert_pairs=%lu, "
394 "force_client_auth=%d, reserved=%p)",
395 5, (pem_root_certs, pem_key_cert_pairs, (unsigned long)num_key_cert_pairs,
396 force_client_auth, reserved));
Craig Tillera82950e2015-09-22 12:33:20 -0700397 GPR_ASSERT(reserved == NULL);
398 memset(c, 0, sizeof(grpc_ssl_server_credentials));
Julien Boeuf441176d2015-10-09 21:14:07 -0700399 c->base.type = GRPC_CHANNEL_CREDENTIALS_TYPE_SSL;
Craig Tillera82950e2015-09-22 12:33:20 -0700400 gpr_ref_init(&c->base.refcount, 1);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800401 c->base.vtable = &ssl_server_vtable;
Craig Tillera82950e2015-09-22 12:33:20 -0700402 ssl_build_server_config(pem_root_certs, pem_key_cert_pairs,
403 num_key_cert_pairs, force_client_auth, &c->config);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800404 return &c->base;
405}
406
Julien Boeuff47a5cb2015-02-18 12:24:08 -0800407/* -- Jwt credentials -- */
408
Craig Tillera82950e2015-09-22 12:33:20 -0700409static void jwt_reset_cache(grpc_service_account_jwt_access_credentials *c) {
410 if (c->cached.jwt_md != NULL) {
411 grpc_credentials_md_store_unref(c->cached.jwt_md);
412 c->cached.jwt_md = NULL;
413 }
414 if (c->cached.service_url != NULL) {
415 gpr_free(c->cached.service_url);
416 c->cached.service_url = NULL;
417 }
418 c->cached.jwt_expiration = gpr_inf_past(GPR_CLOCK_REALTIME);
Julien Boeuff47a5cb2015-02-18 12:24:08 -0800419}
420
Julien Boeuf441176d2015-10-09 21:14:07 -0700421static void jwt_destruct(grpc_call_credentials *creds) {
Craig Tillera82950e2015-09-22 12:33:20 -0700422 grpc_service_account_jwt_access_credentials *c =
423 (grpc_service_account_jwt_access_credentials *)creds;
424 grpc_auth_json_key_destruct(&c->key);
425 jwt_reset_cache(c);
426 gpr_mu_destroy(&c->cache_mu);
Julien Boeuff47a5cb2015-02-18 12:24:08 -0800427}
428
Craig Tillerb1136492015-11-18 11:30:17 -0800429static void jwt_get_request_metadata(grpc_exec_ctx *exec_ctx,
430 grpc_call_credentials *creds,
431 grpc_pollset *pollset,
432 const char *service_url,
433 grpc_credentials_metadata_cb cb,
434 void *user_data) {
Craig Tillera82950e2015-09-22 12:33:20 -0700435 grpc_service_account_jwt_access_credentials *c =
436 (grpc_service_account_jwt_access_credentials *)creds;
437 gpr_timespec refresh_threshold = gpr_time_from_seconds(
438 GRPC_SECURE_TOKEN_REFRESH_THRESHOLD_SECS, GPR_TIMESPAN);
Julien Boeuff47a5cb2015-02-18 12:24:08 -0800439
440 /* See if we can return a cached jwt. */
Julien Boeuf75c9b6f2015-05-29 13:12:12 -0700441 grpc_credentials_md_store *jwt_md = NULL;
Julien Boeuff47a5cb2015-02-18 12:24:08 -0800442 {
Craig Tillera82950e2015-09-22 12:33:20 -0700443 gpr_mu_lock(&c->cache_mu);
444 if (c->cached.service_url != NULL &&
445 strcmp(c->cached.service_url, service_url) == 0 &&
446 c->cached.jwt_md != NULL &&
447 (gpr_time_cmp(gpr_time_sub(c->cached.jwt_expiration,
448 gpr_now(GPR_CLOCK_REALTIME)),
449 refresh_threshold) > 0)) {
450 jwt_md = grpc_credentials_md_store_ref(c->cached.jwt_md);
451 }
452 gpr_mu_unlock(&c->cache_mu);
Julien Boeuff47a5cb2015-02-18 12:24:08 -0800453 }
454
Craig Tillera82950e2015-09-22 12:33:20 -0700455 if (jwt_md == NULL) {
456 char *jwt = NULL;
457 /* Generate a new jwt. */
458 gpr_mu_lock(&c->cache_mu);
459 jwt_reset_cache(c);
460 jwt = grpc_jwt_encode_and_sign(&c->key, service_url, c->jwt_lifetime, NULL);
461 if (jwt != NULL) {
462 char *md_value;
463 gpr_asprintf(&md_value, "Bearer %s", jwt);
464 gpr_free(jwt);
465 c->cached.jwt_expiration =
466 gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), c->jwt_lifetime);
467 c->cached.service_url = gpr_strdup(service_url);
468 c->cached.jwt_md = grpc_credentials_md_store_create(1);
469 grpc_credentials_md_store_add_cstrings(
470 c->cached.jwt_md, GRPC_AUTHORIZATION_METADATA_KEY, md_value);
471 gpr_free(md_value);
472 jwt_md = grpc_credentials_md_store_ref(c->cached.jwt_md);
Julien Boeuff47a5cb2015-02-18 12:24:08 -0800473 }
Craig Tillera82950e2015-09-22 12:33:20 -0700474 gpr_mu_unlock(&c->cache_mu);
475 }
Julien Boeuff47a5cb2015-02-18 12:24:08 -0800476
Craig Tillera82950e2015-09-22 12:33:20 -0700477 if (jwt_md != NULL) {
478 cb(exec_ctx, user_data, jwt_md->entries, jwt_md->num_entries,
479 GRPC_CREDENTIALS_OK);
480 grpc_credentials_md_store_unref(jwt_md);
481 } else {
482 cb(exec_ctx, user_data, NULL, 0, GRPC_CREDENTIALS_ERROR);
483 }
Julien Boeuff47a5cb2015-02-18 12:24:08 -0800484}
485
Julien Boeuf441176d2015-10-09 21:14:07 -0700486static grpc_call_credentials_vtable jwt_vtable = {jwt_destruct,
487 jwt_get_request_metadata};
Julien Boeuff47a5cb2015-02-18 12:24:08 -0800488
Julien Boeuf441176d2015-10-09 21:14:07 -0700489grpc_call_credentials *
Craig Tillera82950e2015-09-22 12:33:20 -0700490grpc_service_account_jwt_access_credentials_create_from_auth_json_key(
491 grpc_auth_json_key key, gpr_timespec token_lifetime) {
Julien Boeuffe4c3f42015-07-22 16:20:13 -0700492 grpc_service_account_jwt_access_credentials *c;
Craig Tillera82950e2015-09-22 12:33:20 -0700493 if (!grpc_auth_json_key_is_valid(&key)) {
494 gpr_log(GPR_ERROR, "Invalid input for jwt credentials creation");
495 return NULL;
496 }
497 c = gpr_malloc(sizeof(grpc_service_account_jwt_access_credentials));
498 memset(c, 0, sizeof(grpc_service_account_jwt_access_credentials));
Julien Boeuf441176d2015-10-09 21:14:07 -0700499 c->base.type = GRPC_CALL_CREDENTIALS_TYPE_JWT;
Craig Tillera82950e2015-09-22 12:33:20 -0700500 gpr_ref_init(&c->base.refcount, 1);
Julien Boeuff47a5cb2015-02-18 12:24:08 -0800501 c->base.vtable = &jwt_vtable;
Julien Boeuff47a5cb2015-02-18 12:24:08 -0800502 c->key = key;
503 c->jwt_lifetime = token_lifetime;
Craig Tillera82950e2015-09-22 12:33:20 -0700504 gpr_mu_init(&c->cache_mu);
505 jwt_reset_cache(c);
Julien Boeuff47a5cb2015-02-18 12:24:08 -0800506 return &c->base;
507}
508
Julien Boeuf441176d2015-10-09 21:14:07 -0700509grpc_call_credentials *grpc_service_account_jwt_access_credentials_create(
Craig Tillera82950e2015-09-22 12:33:20 -0700510 const char *json_key, gpr_timespec token_lifetime, void *reserved) {
Masood Malekghassemi76c3d742015-08-19 18:22:53 -0700511 GRPC_API_TRACE(
512 "grpc_service_account_jwt_access_credentials_create("
Craig Tiller4de3e4f2015-10-05 08:55:50 -0700513 "json_key=%s, "
514 "token_lifetime="
515 "gpr_timespec { tv_sec: %ld, tv_nsec: %d, clock_type: %d }, "
516 "reserved=%p)",
517 5, (json_key, (long)token_lifetime.tv_sec, token_lifetime.tv_nsec,
518 (int)token_lifetime.clock_type, reserved));
Craig Tillera82950e2015-09-22 12:33:20 -0700519 GPR_ASSERT(reserved == NULL);
520 return grpc_service_account_jwt_access_credentials_create_from_auth_json_key(
521 grpc_auth_json_key_create_from_string(json_key), token_lifetime);
Julien Boeuf54006062015-07-07 19:13:04 -0700522}
523
jboeuf1a809c02014-12-19 15:44:30 -0800524/* -- Oauth2TokenFetcher credentials -- */
525
Julien Boeuf441176d2015-10-09 21:14:07 -0700526static void oauth2_token_fetcher_destruct(grpc_call_credentials *creds) {
Craig Tillera82950e2015-09-22 12:33:20 -0700527 grpc_oauth2_token_fetcher_credentials *c =
528 (grpc_oauth2_token_fetcher_credentials *)creds;
529 grpc_credentials_md_store_unref(c->access_token_md);
530 gpr_mu_destroy(&c->mu);
531 grpc_httpcli_context_destroy(&c->httpcli_context);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800532}
533
jboeuf1a809c02014-12-19 15:44:30 -0800534grpc_credentials_status
Craig Tillera82950e2015-09-22 12:33:20 -0700535grpc_oauth2_token_fetcher_credentials_parse_server_response(
536 const grpc_httpcli_response *response, grpc_credentials_md_store **token_md,
537 gpr_timespec *token_lifetime) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800538 char *null_terminated_body = NULL;
539 char *new_access_token = NULL;
540 grpc_credentials_status status = GRPC_CREDENTIALS_OK;
Nicolas Noble614c2bf2015-01-21 15:48:36 -0800541 grpc_json *json = NULL;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800542
Craig Tillera82950e2015-09-22 12:33:20 -0700543 if (response == NULL) {
544 gpr_log(GPR_ERROR, "Received NULL response.");
545 status = GRPC_CREDENTIALS_ERROR;
546 goto end;
547 }
548
549 if (response->body_length > 0) {
550 null_terminated_body = gpr_malloc(response->body_length + 1);
551 null_terminated_body[response->body_length] = '\0';
552 memcpy(null_terminated_body, response->body, response->body_length);
553 }
554
555 if (response->status != 200) {
556 gpr_log(GPR_ERROR, "Call to http server ended with error %d [%s].",
557 response->status,
558 null_terminated_body != NULL ? null_terminated_body : "");
559 status = GRPC_CREDENTIALS_ERROR;
560 goto end;
561 } else {
562 grpc_json *access_token = NULL;
563 grpc_json *token_type = NULL;
564 grpc_json *expires_in = NULL;
565 grpc_json *ptr;
566 json = grpc_json_parse_string(null_terminated_body);
567 if (json == NULL) {
568 gpr_log(GPR_ERROR, "Could not parse JSON from %s", null_terminated_body);
Craig Tiller45724b32015-09-22 10:42:19 -0700569 status = GRPC_CREDENTIALS_ERROR;
570 goto end;
571 }
Craig Tillera82950e2015-09-22 12:33:20 -0700572 if (json->type != GRPC_JSON_OBJECT) {
573 gpr_log(GPR_ERROR, "Response should be a JSON object");
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800574 status = GRPC_CREDENTIALS_ERROR;
575 goto end;
576 }
Craig Tillera82950e2015-09-22 12:33:20 -0700577 for (ptr = json->child; ptr; ptr = ptr->next) {
578 if (strcmp(ptr->key, "access_token") == 0) {
579 access_token = ptr;
580 } else if (strcmp(ptr->key, "token_type") == 0) {
581 token_type = ptr;
582 } else if (strcmp(ptr->key, "expires_in") == 0) {
583 expires_in = ptr;
584 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800585 }
Craig Tillera82950e2015-09-22 12:33:20 -0700586 if (access_token == NULL || access_token->type != GRPC_JSON_STRING) {
587 gpr_log(GPR_ERROR, "Missing or invalid access_token in JSON.");
588 status = GRPC_CREDENTIALS_ERROR;
589 goto end;
590 }
591 if (token_type == NULL || token_type->type != GRPC_JSON_STRING) {
592 gpr_log(GPR_ERROR, "Missing or invalid token_type in JSON.");
593 status = GRPC_CREDENTIALS_ERROR;
594 goto end;
595 }
596 if (expires_in == NULL || expires_in->type != GRPC_JSON_NUMBER) {
597 gpr_log(GPR_ERROR, "Missing or invalid expires_in in JSON.");
598 status = GRPC_CREDENTIALS_ERROR;
599 goto end;
600 }
601 gpr_asprintf(&new_access_token, "%s %s", token_type->value,
602 access_token->value);
603 token_lifetime->tv_sec = strtol(expires_in->value, NULL, 10);
604 token_lifetime->tv_nsec = 0;
605 token_lifetime->clock_type = GPR_TIMESPAN;
606 if (*token_md != NULL) grpc_credentials_md_store_unref(*token_md);
607 *token_md = grpc_credentials_md_store_create(1);
608 grpc_credentials_md_store_add_cstrings(
609 *token_md, GRPC_AUTHORIZATION_METADATA_KEY, new_access_token);
610 status = GRPC_CREDENTIALS_OK;
611 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800612
613end:
Craig Tillera82950e2015-09-22 12:33:20 -0700614 if (status != GRPC_CREDENTIALS_OK && (*token_md != NULL)) {
615 grpc_credentials_md_store_unref(*token_md);
616 *token_md = NULL;
617 }
618 if (null_terminated_body != NULL) gpr_free(null_terminated_body);
619 if (new_access_token != NULL) gpr_free(new_access_token);
620 if (json != NULL) grpc_json_destroy(json);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800621 return status;
622}
623
Craig Tillera82950e2015-09-22 12:33:20 -0700624static void on_oauth2_token_fetcher_http_response(
625 grpc_exec_ctx *exec_ctx, void *user_data,
626 const grpc_httpcli_response *response) {
627 grpc_credentials_metadata_request *r =
628 (grpc_credentials_metadata_request *)user_data;
629 grpc_oauth2_token_fetcher_credentials *c =
630 (grpc_oauth2_token_fetcher_credentials *)r->creds;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800631 gpr_timespec token_lifetime;
632 grpc_credentials_status status;
633
Craig Tillera82950e2015-09-22 12:33:20 -0700634 gpr_mu_lock(&c->mu);
635 status = grpc_oauth2_token_fetcher_credentials_parse_server_response(
636 response, &c->access_token_md, &token_lifetime);
637 if (status == GRPC_CREDENTIALS_OK) {
638 c->token_expiration =
639 gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), token_lifetime);
640 r->cb(exec_ctx, r->user_data, c->access_token_md->entries,
641 c->access_token_md->num_entries, status);
642 } else {
643 c->token_expiration = gpr_inf_past(GPR_CLOCK_REALTIME);
644 r->cb(exec_ctx, r->user_data, NULL, 0, status);
645 }
646 gpr_mu_unlock(&c->mu);
647 grpc_credentials_metadata_request_destroy(r);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800648}
649
Craig Tillera82950e2015-09-22 12:33:20 -0700650static void oauth2_token_fetcher_get_request_metadata(
Julien Boeuf441176d2015-10-09 21:14:07 -0700651 grpc_exec_ctx *exec_ctx, grpc_call_credentials *creds,
652 grpc_pollset *pollset, const char *service_url,
653 grpc_credentials_metadata_cb cb, void *user_data) {
Craig Tillera82950e2015-09-22 12:33:20 -0700654 grpc_oauth2_token_fetcher_credentials *c =
655 (grpc_oauth2_token_fetcher_credentials *)creds;
656 gpr_timespec refresh_threshold = gpr_time_from_seconds(
657 GRPC_SECURE_TOKEN_REFRESH_THRESHOLD_SECS, GPR_TIMESPAN);
Julien Boeuf75c9b6f2015-05-29 13:12:12 -0700658 grpc_credentials_md_store *cached_access_token_md = NULL;
jboeuf1a809c02014-12-19 15:44:30 -0800659 {
Craig Tillera82950e2015-09-22 12:33:20 -0700660 gpr_mu_lock(&c->mu);
661 if (c->access_token_md != NULL &&
662 (gpr_time_cmp(
663 gpr_time_sub(c->token_expiration, gpr_now(GPR_CLOCK_REALTIME)),
664 refresh_threshold) > 0)) {
665 cached_access_token_md =
666 grpc_credentials_md_store_ref(c->access_token_md);
667 }
668 gpr_mu_unlock(&c->mu);
Craig Tiller45724b32015-09-22 10:42:19 -0700669 }
Craig Tillera82950e2015-09-22 12:33:20 -0700670 if (cached_access_token_md != NULL) {
671 cb(exec_ctx, user_data, cached_access_token_md->entries,
672 cached_access_token_md->num_entries, GRPC_CREDENTIALS_OK);
673 grpc_credentials_md_store_unref(cached_access_token_md);
674 } else {
675 c->fetch_func(
676 exec_ctx,
677 grpc_credentials_metadata_request_create(creds, cb, user_data),
678 &c->httpcli_context, pollset, on_oauth2_token_fetcher_http_response,
679 gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), refresh_threshold));
680 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800681}
682
Craig Tillera82950e2015-09-22 12:33:20 -0700683static void init_oauth2_token_fetcher(grpc_oauth2_token_fetcher_credentials *c,
684 grpc_fetch_oauth2_func fetch_func) {
685 memset(c, 0, sizeof(grpc_oauth2_token_fetcher_credentials));
Julien Boeuf441176d2015-10-09 21:14:07 -0700686 c->base.type = GRPC_CALL_CREDENTIALS_TYPE_OAUTH2;
Craig Tillera82950e2015-09-22 12:33:20 -0700687 gpr_ref_init(&c->base.refcount, 1);
688 gpr_mu_init(&c->mu);
689 c->token_expiration = gpr_inf_past(GPR_CLOCK_REALTIME);
jboeuf1a809c02014-12-19 15:44:30 -0800690 c->fetch_func = fetch_func;
Craig Tillera82950e2015-09-22 12:33:20 -0700691 grpc_httpcli_context_init(&c->httpcli_context);
jboeuf1a809c02014-12-19 15:44:30 -0800692}
693
Julien Boeuf510a9202015-08-25 21:51:07 -0700694/* -- GoogleComputeEngine credentials. -- */
jboeuf1a809c02014-12-19 15:44:30 -0800695
Julien Boeuf441176d2015-10-09 21:14:07 -0700696static grpc_call_credentials_vtable compute_engine_vtable = {
697 oauth2_token_fetcher_destruct, oauth2_token_fetcher_get_request_metadata};
jboeuf1a809c02014-12-19 15:44:30 -0800698
Craig Tillera82950e2015-09-22 12:33:20 -0700699static void compute_engine_fetch_oauth2(
700 grpc_exec_ctx *exec_ctx, grpc_credentials_metadata_request *metadata_req,
701 grpc_httpcli_context *httpcli_context, grpc_pollset *pollset,
702 grpc_httpcli_response_cb response_cb, gpr_timespec deadline) {
703 grpc_httpcli_header header = {"Metadata-Flavor", "Google"};
jboeuf1a809c02014-12-19 15:44:30 -0800704 grpc_httpcli_request request;
Craig Tillera82950e2015-09-22 12:33:20 -0700705 memset(&request, 0, sizeof(grpc_httpcli_request));
jboeuf1a809c02014-12-19 15:44:30 -0800706 request.host = GRPC_COMPUTE_ENGINE_METADATA_HOST;
707 request.path = GRPC_COMPUTE_ENGINE_METADATA_TOKEN_PATH;
708 request.hdr_count = 1;
709 request.hdrs = &header;
Craig Tillera82950e2015-09-22 12:33:20 -0700710 grpc_httpcli_get(exec_ctx, httpcli_context, pollset, &request, deadline,
711 response_cb, metadata_req);
jboeuf1a809c02014-12-19 15:44:30 -0800712}
713
Julien Boeuf441176d2015-10-09 21:14:07 -0700714grpc_call_credentials *grpc_google_compute_engine_credentials_create(
Craig Tillera82950e2015-09-22 12:33:20 -0700715 void *reserved) {
716 grpc_oauth2_token_fetcher_credentials *c =
717 gpr_malloc(sizeof(grpc_oauth2_token_fetcher_credentials));
Masood Malekghassemi76c3d742015-08-19 18:22:53 -0700718 GRPC_API_TRACE("grpc_compute_engine_credentials_create(reserved=%p)", 1,
719 (reserved));
Craig Tillera82950e2015-09-22 12:33:20 -0700720 GPR_ASSERT(reserved == NULL);
721 init_oauth2_token_fetcher(c, compute_engine_fetch_oauth2);
jboeuf1a809c02014-12-19 15:44:30 -0800722 c->base.vtable = &compute_engine_vtable;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800723 return &c->base;
724}
725
Julien Boeuf510a9202015-08-25 21:51:07 -0700726/* -- GoogleRefreshToken credentials. -- */
Julien Boeuf9835cf02015-03-09 16:56:44 -0700727
Julien Boeuf441176d2015-10-09 21:14:07 -0700728static void refresh_token_destruct(grpc_call_credentials *creds) {
Craig Tillera82950e2015-09-22 12:33:20 -0700729 grpc_google_refresh_token_credentials *c =
730 (grpc_google_refresh_token_credentials *)creds;
731 grpc_auth_refresh_token_destruct(&c->refresh_token);
732 oauth2_token_fetcher_destruct(&c->base.base);
Julien Boeuf9835cf02015-03-09 16:56:44 -0700733}
734
Julien Boeuf441176d2015-10-09 21:14:07 -0700735static grpc_call_credentials_vtable refresh_token_vtable = {
736 refresh_token_destruct, oauth2_token_fetcher_get_request_metadata};
Julien Boeuf9835cf02015-03-09 16:56:44 -0700737
Craig Tillera82950e2015-09-22 12:33:20 -0700738static void refresh_token_fetch_oauth2(
739 grpc_exec_ctx *exec_ctx, grpc_credentials_metadata_request *metadata_req,
740 grpc_httpcli_context *httpcli_context, grpc_pollset *pollset,
741 grpc_httpcli_response_cb response_cb, gpr_timespec deadline) {
742 grpc_google_refresh_token_credentials *c =
743 (grpc_google_refresh_token_credentials *)metadata_req->creds;
744 grpc_httpcli_header header = {"Content-Type",
745 "application/x-www-form-urlencoded"};
Julien Boeuf9835cf02015-03-09 16:56:44 -0700746 grpc_httpcli_request request;
747 char *body = NULL;
Craig Tillera82950e2015-09-22 12:33:20 -0700748 gpr_asprintf(&body, GRPC_REFRESH_TOKEN_POST_BODY_FORMAT_STRING,
749 c->refresh_token.client_id, c->refresh_token.client_secret,
750 c->refresh_token.refresh_token);
751 memset(&request, 0, sizeof(grpc_httpcli_request));
Julien Boeuf9835cf02015-03-09 16:56:44 -0700752 request.host = GRPC_GOOGLE_OAUTH2_SERVICE_HOST;
753 request.path = GRPC_GOOGLE_OAUTH2_SERVICE_TOKEN_PATH;
754 request.hdr_count = 1;
755 request.hdrs = &header;
Craig Tillerf53d9c82015-08-04 14:19:43 -0700756 request.handshaker = &grpc_httpcli_ssl;
Craig Tillera82950e2015-09-22 12:33:20 -0700757 grpc_httpcli_post(exec_ctx, httpcli_context, pollset, &request, body,
758 strlen(body), deadline, response_cb, metadata_req);
759 gpr_free(body);
Julien Boeuf9835cf02015-03-09 16:56:44 -0700760}
761
Julien Boeuf441176d2015-10-09 21:14:07 -0700762grpc_call_credentials *
763grpc_refresh_token_credentials_create_from_auth_refresh_token(
Craig Tillera82950e2015-09-22 12:33:20 -0700764 grpc_auth_refresh_token refresh_token) {
Julien Boeuf510a9202015-08-25 21:51:07 -0700765 grpc_google_refresh_token_credentials *c;
Craig Tillera82950e2015-09-22 12:33:20 -0700766 if (!grpc_auth_refresh_token_is_valid(&refresh_token)) {
767 gpr_log(GPR_ERROR, "Invalid input for refresh token credentials creation");
768 return NULL;
769 }
770 c = gpr_malloc(sizeof(grpc_google_refresh_token_credentials));
771 memset(c, 0, sizeof(grpc_google_refresh_token_credentials));
772 init_oauth2_token_fetcher(&c->base, refresh_token_fetch_oauth2);
Julien Boeuf9835cf02015-03-09 16:56:44 -0700773 c->base.base.vtable = &refresh_token_vtable;
774 c->refresh_token = refresh_token;
775 return &c->base.base;
776}
777
Julien Boeuf441176d2015-10-09 21:14:07 -0700778grpc_call_credentials *grpc_google_refresh_token_credentials_create(
Craig Tillera82950e2015-09-22 12:33:20 -0700779 const char *json_refresh_token, void *reserved) {
Craig Tiller4de3e4f2015-10-05 08:55:50 -0700780 GRPC_API_TRACE(
781 "grpc_refresh_token_credentials_create(json_refresh_token=%s, "
782 "reserved=%p)",
783 2, (json_refresh_token, reserved));
Craig Tillera82950e2015-09-22 12:33:20 -0700784 GPR_ASSERT(reserved == NULL);
785 return grpc_refresh_token_credentials_create_from_auth_refresh_token(
786 grpc_auth_refresh_token_create_from_string(json_refresh_token));
Julien Boeuf54006062015-07-07 19:13:04 -0700787}
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800788
Julien Boeufea456fc2015-07-07 15:23:30 -0700789/* -- Metadata-only credentials. -- */
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800790
Julien Boeuf441176d2015-10-09 21:14:07 -0700791static void md_only_test_destruct(grpc_call_credentials *creds) {
Craig Tillera82950e2015-09-22 12:33:20 -0700792 grpc_md_only_test_credentials *c = (grpc_md_only_test_credentials *)creds;
793 grpc_credentials_md_store_unref(c->md_store);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800794}
795
Craig Tillera82950e2015-09-22 12:33:20 -0700796static void on_simulated_token_fetch_done(void *user_data) {
797 grpc_credentials_metadata_request *r =
798 (grpc_credentials_metadata_request *)user_data;
799 grpc_md_only_test_credentials *c = (grpc_md_only_test_credentials *)r->creds;
Craig Tillerf5768a62015-09-22 10:54:34 -0700800 grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
Craig Tillera82950e2015-09-22 12:33:20 -0700801 r->cb(&exec_ctx, r->user_data, c->md_store->entries, c->md_store->num_entries,
802 GRPC_CREDENTIALS_OK);
803 grpc_credentials_metadata_request_destroy(r);
804 grpc_exec_ctx_finish(&exec_ctx);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800805}
806
Craig Tillerb1136492015-11-18 11:30:17 -0800807static void md_only_test_get_request_metadata(grpc_exec_ctx *exec_ctx,
808 grpc_call_credentials *creds,
809 grpc_pollset *pollset,
810 const char *service_url,
811 grpc_credentials_metadata_cb cb,
812 void *user_data) {
Craig Tillera82950e2015-09-22 12:33:20 -0700813 grpc_md_only_test_credentials *c = (grpc_md_only_test_credentials *)creds;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800814
Craig Tillera82950e2015-09-22 12:33:20 -0700815 if (c->is_async) {
816 gpr_thd_id thd_id;
817 grpc_credentials_metadata_request *cb_arg =
818 grpc_credentials_metadata_request_create(creds, cb, user_data);
819 gpr_thd_new(&thd_id, on_simulated_token_fetch_done, cb_arg, NULL);
820 } else {
821 cb(exec_ctx, user_data, c->md_store->entries, 1, GRPC_CREDENTIALS_OK);
822 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800823}
824
Julien Boeuf441176d2015-10-09 21:14:07 -0700825static grpc_call_credentials_vtable md_only_test_vtable = {
826 md_only_test_destruct, md_only_test_get_request_metadata};
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800827
Julien Boeuf441176d2015-10-09 21:14:07 -0700828grpc_call_credentials *grpc_md_only_test_credentials_create(
829 const char *md_key, const char *md_value, int is_async) {
Craig Tillera82950e2015-09-22 12:33:20 -0700830 grpc_md_only_test_credentials *c =
831 gpr_malloc(sizeof(grpc_md_only_test_credentials));
832 memset(c, 0, sizeof(grpc_md_only_test_credentials));
Julien Boeuf441176d2015-10-09 21:14:07 -0700833 c->base.type = GRPC_CALL_CREDENTIALS_TYPE_OAUTH2;
Julien Boeufea456fc2015-07-07 15:23:30 -0700834 c->base.vtable = &md_only_test_vtable;
Craig Tillera82950e2015-09-22 12:33:20 -0700835 gpr_ref_init(&c->base.refcount, 1);
836 c->md_store = grpc_credentials_md_store_create(1);
837 grpc_credentials_md_store_add_cstrings(c->md_store, md_key, md_value);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800838 c->is_async = is_async;
839 return &c->base;
840}
841
Julien Boeuf2805be12015-07-01 02:47:18 -0700842/* -- Oauth2 Access Token credentials. -- */
843
Julien Boeuf441176d2015-10-09 21:14:07 -0700844static void access_token_destruct(grpc_call_credentials *creds) {
Craig Tillera82950e2015-09-22 12:33:20 -0700845 grpc_access_token_credentials *c = (grpc_access_token_credentials *)creds;
846 grpc_credentials_md_store_unref(c->access_token_md);
Julien Boeuf2805be12015-07-01 02:47:18 -0700847}
848
Craig Tillerb1136492015-11-18 11:30:17 -0800849static void access_token_get_request_metadata(grpc_exec_ctx *exec_ctx,
850 grpc_call_credentials *creds,
851 grpc_pollset *pollset,
852 const char *service_url,
853 grpc_credentials_metadata_cb cb,
854 void *user_data) {
Craig Tillera82950e2015-09-22 12:33:20 -0700855 grpc_access_token_credentials *c = (grpc_access_token_credentials *)creds;
856 cb(exec_ctx, user_data, c->access_token_md->entries, 1, GRPC_CREDENTIALS_OK);
Julien Boeuf2805be12015-07-01 02:47:18 -0700857}
858
Julien Boeuf441176d2015-10-09 21:14:07 -0700859static grpc_call_credentials_vtable access_token_vtable = {
860 access_token_destruct, access_token_get_request_metadata};
Julien Boeuf2805be12015-07-01 02:47:18 -0700861
Julien Boeuf441176d2015-10-09 21:14:07 -0700862grpc_call_credentials *grpc_access_token_credentials_create(
863 const char *access_token, void *reserved) {
Craig Tillera82950e2015-09-22 12:33:20 -0700864 grpc_access_token_credentials *c =
865 gpr_malloc(sizeof(grpc_access_token_credentials));
Julien Boeuf2805be12015-07-01 02:47:18 -0700866 char *token_md_value;
Craig Tiller4de3e4f2015-10-05 08:55:50 -0700867 GRPC_API_TRACE(
868 "grpc_access_token_credentials_create(access_token=%s, "
869 "reserved=%p)",
870 2, (access_token, reserved));
Craig Tillera82950e2015-09-22 12:33:20 -0700871 GPR_ASSERT(reserved == NULL);
872 memset(c, 0, sizeof(grpc_access_token_credentials));
Julien Boeuf441176d2015-10-09 21:14:07 -0700873 c->base.type = GRPC_CALL_CREDENTIALS_TYPE_OAUTH2;
Julien Boeuf2805be12015-07-01 02:47:18 -0700874 c->base.vtable = &access_token_vtable;
Craig Tillera82950e2015-09-22 12:33:20 -0700875 gpr_ref_init(&c->base.refcount, 1);
876 c->access_token_md = grpc_credentials_md_store_create(1);
877 gpr_asprintf(&token_md_value, "Bearer %s", access_token);
878 grpc_credentials_md_store_add_cstrings(
879 c->access_token_md, GRPC_AUTHORIZATION_METADATA_KEY, token_md_value);
880 gpr_free(token_md_value);
Julien Boeuf2805be12015-07-01 02:47:18 -0700881 return &c->base;
882}
883
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800884/* -- Fake transport security credentials. -- */
885
Craig Tillera82950e2015-09-22 12:33:20 -0700886static grpc_security_status fake_transport_security_create_security_connector(
Julien Boeufb73cbc22015-10-20 21:52:54 -0700887 grpc_channel_credentials *c, grpc_call_credentials *call_creds,
888 const char *target, const grpc_channel_args *args,
889 grpc_channel_security_connector **sc, grpc_channel_args **new_args) {
890 *sc = grpc_fake_channel_security_connector_create(call_creds, 1);
Julien Boeuf7d1d9ca2015-04-17 14:38:48 -0700891 return GRPC_SECURITY_OK;
892}
893
894static grpc_security_status
Craig Tillera82950e2015-09-22 12:33:20 -0700895fake_transport_security_server_create_security_connector(
896 grpc_server_credentials *c, grpc_security_connector **sc) {
897 *sc = grpc_fake_server_security_connector_create();
Julien Boeuf7d1d9ca2015-04-17 14:38:48 -0700898 return GRPC_SECURITY_OK;
899}
900
Julien Boeuf441176d2015-10-09 21:14:07 -0700901static grpc_channel_credentials_vtable
902 fake_transport_security_credentials_vtable = {
Julien Boeufb73cbc22015-10-20 21:52:54 -0700903 NULL, fake_transport_security_create_security_connector};
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800904
Craig Tillera82950e2015-09-22 12:33:20 -0700905static grpc_server_credentials_vtable
906 fake_transport_security_server_credentials_vtable = {
Julien Boeufb73cbc22015-10-20 21:52:54 -0700907 NULL, fake_transport_security_server_create_security_connector};
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800908
Julien Boeuf441176d2015-10-09 21:14:07 -0700909grpc_channel_credentials *grpc_fake_transport_security_credentials_create(
910 void) {
911 grpc_channel_credentials *c = gpr_malloc(sizeof(grpc_channel_credentials));
912 memset(c, 0, sizeof(grpc_channel_credentials));
913 c->type = GRPC_CHANNEL_CREDENTIALS_TYPE_FAKE_TRANSPORT_SECURITY;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800914 c->vtable = &fake_transport_security_credentials_vtable;
Craig Tillera82950e2015-09-22 12:33:20 -0700915 gpr_ref_init(&c->refcount, 1);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800916 return c;
917}
918
Craig Tillera82950e2015-09-22 12:33:20 -0700919grpc_server_credentials *grpc_fake_transport_security_server_credentials_create(
920 void) {
921 grpc_server_credentials *c = gpr_malloc(sizeof(grpc_server_credentials));
922 memset(c, 0, sizeof(grpc_server_credentials));
Julien Boeuf441176d2015-10-09 21:14:07 -0700923 c->type = GRPC_CHANNEL_CREDENTIALS_TYPE_FAKE_TRANSPORT_SECURITY;
Craig Tillera82950e2015-09-22 12:33:20 -0700924 gpr_ref_init(&c->refcount, 1);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800925 c->vtable = &fake_transport_security_server_credentials_vtable;
926 return c;
927}
928
Julien Boeufb73cbc22015-10-20 21:52:54 -0700929/* -- Composite call credentials. -- */
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800930
Craig Tillera82950e2015-09-22 12:33:20 -0700931typedef struct {
Julien Boeufb73cbc22015-10-20 21:52:54 -0700932 grpc_composite_call_credentials *composite_creds;
nnoble0c475f02014-12-05 15:37:39 -0800933 size_t creds_index;
Julien Boeuf75c9b6f2015-05-29 13:12:12 -0700934 grpc_credentials_md_store *md_elems;
Julien Boeuff47a5cb2015-02-18 12:24:08 -0800935 char *service_url;
nnoble0c475f02014-12-05 15:37:39 -0800936 void *user_data;
Craig Tiller06bac342015-06-01 12:55:57 -0700937 grpc_pollset *pollset;
nnoble0c475f02014-12-05 15:37:39 -0800938 grpc_credentials_metadata_cb cb;
Julien Boeufb73cbc22015-10-20 21:52:54 -0700939} grpc_composite_call_credentials_metadata_context;
nnoble0c475f02014-12-05 15:37:39 -0800940
Julien Boeufb73cbc22015-10-20 21:52:54 -0700941static void composite_call_destruct(grpc_call_credentials *creds) {
942 grpc_composite_call_credentials *c = (grpc_composite_call_credentials *)creds;
nnoble0c475f02014-12-05 15:37:39 -0800943 size_t i;
Craig Tillera82950e2015-09-22 12:33:20 -0700944 for (i = 0; i < c->inner.num_creds; i++) {
Julien Boeuf441176d2015-10-09 21:14:07 -0700945 grpc_call_credentials_unref(c->inner.creds_array[i]);
Craig Tillera82950e2015-09-22 12:33:20 -0700946 }
947 gpr_free(c->inner.creds_array);
nnoble0c475f02014-12-05 15:37:39 -0800948}
949
Julien Boeufb73cbc22015-10-20 21:52:54 -0700950static void composite_call_md_context_destroy(
951 grpc_composite_call_credentials_metadata_context *ctx) {
Craig Tillera82950e2015-09-22 12:33:20 -0700952 grpc_credentials_md_store_unref(ctx->md_elems);
953 if (ctx->service_url != NULL) gpr_free(ctx->service_url);
954 gpr_free(ctx);
nnoble0c475f02014-12-05 15:37:39 -0800955}
956
Julien Boeufb73cbc22015-10-20 21:52:54 -0700957static void composite_call_metadata_cb(grpc_exec_ctx *exec_ctx, void *user_data,
958 grpc_credentials_md *md_elems,
959 size_t num_md,
960 grpc_credentials_status status) {
961 grpc_composite_call_credentials_metadata_context *ctx =
962 (grpc_composite_call_credentials_metadata_context *)user_data;
Craig Tillera82950e2015-09-22 12:33:20 -0700963 if (status != GRPC_CREDENTIALS_OK) {
964 ctx->cb(exec_ctx, ctx->user_data, NULL, 0, status);
965 return;
966 }
Craig Tiller45724b32015-09-22 10:42:19 -0700967
968 /* Copy the metadata in the context. */
Craig Tillera82950e2015-09-22 12:33:20 -0700969 if (num_md > 0) {
970 size_t i;
971 for (i = 0; i < num_md; i++) {
972 grpc_credentials_md_store_add(ctx->md_elems, md_elems[i].key,
973 md_elems[i].value);
Craig Tiller45724b32015-09-22 10:42:19 -0700974 }
Craig Tillera82950e2015-09-22 12:33:20 -0700975 }
Craig Tiller45724b32015-09-22 10:42:19 -0700976
977 /* See if we need to get some more metadata. */
Julien Boeuf441176d2015-10-09 21:14:07 -0700978 if (ctx->creds_index < ctx->composite_creds->inner.num_creds) {
979 grpc_call_credentials *inner_creds =
Craig Tillera82950e2015-09-22 12:33:20 -0700980 ctx->composite_creds->inner.creds_array[ctx->creds_index++];
Julien Boeuf4e02e842015-10-09 22:49:42 -0700981 grpc_call_credentials_get_request_metadata(exec_ctx, inner_creds,
982 ctx->pollset, ctx->service_url,
Julien Boeufb73cbc22015-10-20 21:52:54 -0700983 composite_call_metadata_cb, ctx);
Julien Boeuf441176d2015-10-09 21:14:07 -0700984 return;
Craig Tillera82950e2015-09-22 12:33:20 -0700985 }
986
987 /* We're done!. */
988 ctx->cb(exec_ctx, ctx->user_data, ctx->md_elems->entries,
989 ctx->md_elems->num_entries, GRPC_CREDENTIALS_OK);
Julien Boeufb73cbc22015-10-20 21:52:54 -0700990 composite_call_md_context_destroy(ctx);
Craig Tillera82950e2015-09-22 12:33:20 -0700991}
992
Craig Tillerb1136492015-11-18 11:30:17 -0800993static void composite_call_get_request_metadata(grpc_exec_ctx *exec_ctx,
994 grpc_call_credentials *creds,
995 grpc_pollset *pollset,
996 const char *service_url,
997 grpc_credentials_metadata_cb cb,
998 void *user_data) {
Julien Boeufb73cbc22015-10-20 21:52:54 -0700999 grpc_composite_call_credentials *c = (grpc_composite_call_credentials *)creds;
1000 grpc_composite_call_credentials_metadata_context *ctx;
Julien Boeuf441176d2015-10-09 21:14:07 -07001001
Julien Boeufb73cbc22015-10-20 21:52:54 -07001002 ctx = gpr_malloc(sizeof(grpc_composite_call_credentials_metadata_context));
1003 memset(ctx, 0, sizeof(grpc_composite_call_credentials_metadata_context));
Craig Tillera82950e2015-09-22 12:33:20 -07001004 ctx->service_url = gpr_strdup(service_url);
nnoble0c475f02014-12-05 15:37:39 -08001005 ctx->user_data = user_data;
1006 ctx->cb = cb;
1007 ctx->composite_creds = c;
Craig Tiller06bac342015-06-01 12:55:57 -07001008 ctx->pollset = pollset;
Craig Tillera82950e2015-09-22 12:33:20 -07001009 ctx->md_elems = grpc_credentials_md_store_create(c->inner.num_creds);
Julien Boeuf4e02e842015-10-09 22:49:42 -07001010 grpc_call_credentials_get_request_metadata(
Julien Boeuf441176d2015-10-09 21:14:07 -07001011 exec_ctx, c->inner.creds_array[ctx->creds_index++], pollset, service_url,
Julien Boeufb73cbc22015-10-20 21:52:54 -07001012 composite_call_metadata_cb, ctx);
nnoble0c475f02014-12-05 15:37:39 -08001013}
1014
Julien Boeufb73cbc22015-10-20 21:52:54 -07001015static grpc_call_credentials_vtable composite_call_credentials_vtable = {
1016 composite_call_destruct, composite_call_get_request_metadata};
Julien Boeuf7d1d9ca2015-04-17 14:38:48 -07001017
Julien Boeuf441176d2015-10-09 21:14:07 -07001018static grpc_call_credentials_array get_creds_array(
1019 grpc_call_credentials **creds_addr) {
1020 grpc_call_credentials_array result;
1021 grpc_call_credentials *creds = *creds_addr;
nnoble0c475f02014-12-05 15:37:39 -08001022 result.creds_array = creds_addr;
1023 result.num_creds = 1;
Julien Boeuf441176d2015-10-09 21:14:07 -07001024 if (strcmp(creds->type, GRPC_CALL_CREDENTIALS_TYPE_COMPOSITE) == 0) {
Julien Boeufb73cbc22015-10-20 21:52:54 -07001025 result = *grpc_composite_call_credentials_get_credentials(creds);
Craig Tillera82950e2015-09-22 12:33:20 -07001026 }
nnoble0c475f02014-12-05 15:37:39 -08001027 return result;
1028}
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001029
Julien Boeuf441176d2015-10-09 21:14:07 -07001030grpc_call_credentials *grpc_composite_call_credentials_create(
1031 grpc_call_credentials *creds1, grpc_call_credentials *creds2,
1032 void *reserved) {
nnoble0c475f02014-12-05 15:37:39 -08001033 size_t i;
Julien Boeuf7d1d9ca2015-04-17 14:38:48 -07001034 size_t creds_array_byte_size;
Julien Boeuf441176d2015-10-09 21:14:07 -07001035 grpc_call_credentials_array creds1_array;
1036 grpc_call_credentials_array creds2_array;
Julien Boeufb73cbc22015-10-20 21:52:54 -07001037 grpc_composite_call_credentials *c;
Craig Tiller4de3e4f2015-10-05 08:55:50 -07001038 GRPC_API_TRACE(
Julien Boeufb73cbc22015-10-20 21:52:54 -07001039 "grpc_composite_call_credentials_create(creds1=%p, creds2=%p, "
Craig Tiller4de3e4f2015-10-05 08:55:50 -07001040 "reserved=%p)",
1041 3, (creds1, creds2, reserved));
Craig Tillera82950e2015-09-22 12:33:20 -07001042 GPR_ASSERT(reserved == NULL);
1043 GPR_ASSERT(creds1 != NULL);
1044 GPR_ASSERT(creds2 != NULL);
Julien Boeufb73cbc22015-10-20 21:52:54 -07001045 c = gpr_malloc(sizeof(grpc_composite_call_credentials));
1046 memset(c, 0, sizeof(grpc_composite_call_credentials));
Julien Boeuf441176d2015-10-09 21:14:07 -07001047 c->base.type = GRPC_CALL_CREDENTIALS_TYPE_COMPOSITE;
Julien Boeufb73cbc22015-10-20 21:52:54 -07001048 c->base.vtable = &composite_call_credentials_vtable;
Craig Tillera82950e2015-09-22 12:33:20 -07001049 gpr_ref_init(&c->base.refcount, 1);
1050 creds1_array = get_creds_array(&creds1);
1051 creds2_array = get_creds_array(&creds2);
nnoble0c475f02014-12-05 15:37:39 -08001052 c->inner.num_creds = creds1_array.num_creds + creds2_array.num_creds;
Julien Boeuf441176d2015-10-09 21:14:07 -07001053 creds_array_byte_size = c->inner.num_creds * sizeof(grpc_call_credentials *);
Craig Tillera82950e2015-09-22 12:33:20 -07001054 c->inner.creds_array = gpr_malloc(creds_array_byte_size);
1055 memset(c->inner.creds_array, 0, creds_array_byte_size);
1056 for (i = 0; i < creds1_array.num_creds; i++) {
Julien Boeuf441176d2015-10-09 21:14:07 -07001057 grpc_call_credentials *cur_creds = creds1_array.creds_array[i];
1058 c->inner.creds_array[i] = grpc_call_credentials_ref(cur_creds);
Craig Tillera82950e2015-09-22 12:33:20 -07001059 }
1060 for (i = 0; i < creds2_array.num_creds; i++) {
Julien Boeuf441176d2015-10-09 21:14:07 -07001061 grpc_call_credentials *cur_creds = creds2_array.creds_array[i];
Craig Tillera82950e2015-09-22 12:33:20 -07001062 c->inner.creds_array[i + creds1_array.num_creds] =
Julien Boeuf441176d2015-10-09 21:14:07 -07001063 grpc_call_credentials_ref(cur_creds);
Craig Tillera82950e2015-09-22 12:33:20 -07001064 }
nnoble0c475f02014-12-05 15:37:39 -08001065 return &c->base;
1066}
1067
Julien Boeufb73cbc22015-10-20 21:52:54 -07001068const grpc_call_credentials_array *
1069grpc_composite_call_credentials_get_credentials(grpc_call_credentials *creds) {
1070 const grpc_composite_call_credentials *c =
1071 (const grpc_composite_call_credentials *)creds;
Julien Boeuf441176d2015-10-09 21:14:07 -07001072 GPR_ASSERT(strcmp(creds->type, GRPC_CALL_CREDENTIALS_TYPE_COMPOSITE) == 0);
nnoble0c475f02014-12-05 15:37:39 -08001073 return &c->inner;
1074}
1075
Julien Boeuf441176d2015-10-09 21:14:07 -07001076grpc_call_credentials *grpc_credentials_contains_type(
1077 grpc_call_credentials *creds, const char *type,
1078 grpc_call_credentials **composite_creds) {
jboeuf6ad120e2015-01-12 17:08:15 -08001079 size_t i;
Craig Tillera82950e2015-09-22 12:33:20 -07001080 if (strcmp(creds->type, type) == 0) {
1081 if (composite_creds != NULL) *composite_creds = NULL;
1082 return creds;
Julien Boeuf441176d2015-10-09 21:14:07 -07001083 } else if (strcmp(creds->type, GRPC_CALL_CREDENTIALS_TYPE_COMPOSITE) == 0) {
1084 const grpc_call_credentials_array *inner_creds_array =
Julien Boeufb73cbc22015-10-20 21:52:54 -07001085 grpc_composite_call_credentials_get_credentials(creds);
Craig Tillera82950e2015-09-22 12:33:20 -07001086 for (i = 0; i < inner_creds_array->num_creds; i++) {
1087 if (strcmp(type, inner_creds_array->creds_array[i]->type) == 0) {
1088 if (composite_creds != NULL) *composite_creds = creds;
1089 return inner_creds_array->creds_array[i];
1090 }
jboeuf6ad120e2015-01-12 17:08:15 -08001091 }
Craig Tillera82950e2015-09-22 12:33:20 -07001092 }
jboeuf6ad120e2015-01-12 17:08:15 -08001093 return NULL;
1094}
1095
nnoble0c475f02014-12-05 15:37:39 -08001096/* -- IAM credentials. -- */
1097
Julien Boeuf441176d2015-10-09 21:14:07 -07001098static void iam_destruct(grpc_call_credentials *creds) {
Craig Tillera82950e2015-09-22 12:33:20 -07001099 grpc_google_iam_credentials *c = (grpc_google_iam_credentials *)creds;
1100 grpc_credentials_md_store_unref(c->iam_md);
nnoble0c475f02014-12-05 15:37:39 -08001101}
1102
Julien Boeuf441176d2015-10-09 21:14:07 -07001103static void iam_get_request_metadata(grpc_exec_ctx *exec_ctx,
1104 grpc_call_credentials *creds,
1105 grpc_pollset *pollset,
1106 const char *service_url,
1107 grpc_credentials_metadata_cb cb,
1108 void *user_data) {
Craig Tillera82950e2015-09-22 12:33:20 -07001109 grpc_google_iam_credentials *c = (grpc_google_iam_credentials *)creds;
1110 cb(exec_ctx, user_data, c->iam_md->entries, c->iam_md->num_entries,
1111 GRPC_CREDENTIALS_OK);
nnoble0c475f02014-12-05 15:37:39 -08001112}
1113
Julien Boeuf441176d2015-10-09 21:14:07 -07001114static grpc_call_credentials_vtable iam_vtable = {iam_destruct,
Craig Tillerb1136492015-11-18 11:30:17 -08001115 iam_get_request_metadata};
nnoble0c475f02014-12-05 15:37:39 -08001116
Julien Boeuf441176d2015-10-09 21:14:07 -07001117grpc_call_credentials *grpc_google_iam_credentials_create(
Craig Tillera82950e2015-09-22 12:33:20 -07001118 const char *token, const char *authority_selector, void *reserved) {
Julien Boeuf510a9202015-08-25 21:51:07 -07001119 grpc_google_iam_credentials *c;
Craig Tiller4de3e4f2015-10-05 08:55:50 -07001120 GRPC_API_TRACE(
1121 "grpc_iam_credentials_create(token=%s, authority_selector=%s, "
1122 "reserved=%p)",
1123 3, (token, authority_selector, reserved));
Craig Tillera82950e2015-09-22 12:33:20 -07001124 GPR_ASSERT(reserved == NULL);
1125 GPR_ASSERT(token != NULL);
1126 GPR_ASSERT(authority_selector != NULL);
1127 c = gpr_malloc(sizeof(grpc_google_iam_credentials));
1128 memset(c, 0, sizeof(grpc_google_iam_credentials));
Julien Boeuf441176d2015-10-09 21:14:07 -07001129 c->base.type = GRPC_CALL_CREDENTIALS_TYPE_IAM;
nnoble0c475f02014-12-05 15:37:39 -08001130 c->base.vtable = &iam_vtable;
Craig Tillera82950e2015-09-22 12:33:20 -07001131 gpr_ref_init(&c->base.refcount, 1);
1132 c->iam_md = grpc_credentials_md_store_create(2);
1133 grpc_credentials_md_store_add_cstrings(
1134 c->iam_md, GRPC_IAM_AUTHORIZATION_TOKEN_METADATA_KEY, token);
1135 grpc_credentials_md_store_add_cstrings(
1136 c->iam_md, GRPC_IAM_AUTHORITY_SELECTOR_METADATA_KEY, authority_selector);
nnoble0c475f02014-12-05 15:37:39 -08001137 return &c->base;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001138}
Julien Boeuf2d041182015-08-31 20:30:09 -07001139
1140/* -- Plugin credentials. -- */
1141
Craig Tillera82950e2015-09-22 12:33:20 -07001142typedef struct {
Julien Boeuf2d041182015-08-31 20:30:09 -07001143 void *user_data;
1144 grpc_credentials_metadata_cb cb;
1145} grpc_metadata_plugin_request;
1146
Julien Boeuf441176d2015-10-09 21:14:07 -07001147static void plugin_destruct(grpc_call_credentials *creds) {
Craig Tillera82950e2015-09-22 12:33:20 -07001148 grpc_plugin_credentials *c = (grpc_plugin_credentials *)creds;
1149 if (c->plugin.state != NULL && c->plugin.destroy != NULL) {
1150 c->plugin.destroy(c->plugin.state);
1151 }
Julien Boeuf2d041182015-08-31 20:30:09 -07001152}
1153
Craig Tillera82950e2015-09-22 12:33:20 -07001154static void plugin_md_request_metadata_ready(void *request,
1155 const grpc_metadata *md,
1156 size_t num_md,
1157 grpc_status_code status,
1158 const char *error_details) {
Craig Tiller10ee2742015-09-22 09:25:57 -07001159 /* called from application code */
Craig Tillerf5768a62015-09-22 10:54:34 -07001160 grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
Craig Tillera82950e2015-09-22 12:33:20 -07001161 grpc_metadata_plugin_request *r = (grpc_metadata_plugin_request *)request;
1162 if (status != GRPC_STATUS_OK) {
1163 if (error_details != NULL) {
1164 gpr_log(GPR_ERROR, "Getting metadata from plugin failed with error: %s",
1165 error_details);
Julien Boeuf2d041182015-08-31 20:30:09 -07001166 }
Craig Tillera82950e2015-09-22 12:33:20 -07001167 r->cb(&exec_ctx, r->user_data, NULL, 0, GRPC_CREDENTIALS_ERROR);
1168 } else {
1169 size_t i;
1170 grpc_credentials_md *md_array = NULL;
1171 if (num_md > 0) {
1172 md_array = gpr_malloc(num_md * sizeof(grpc_credentials_md));
1173 for (i = 0; i < num_md; i++) {
1174 md_array[i].key = gpr_slice_from_copied_string(md[i].key);
1175 md_array[i].value =
1176 gpr_slice_from_copied_buffer(md[i].value, md[i].value_length);
1177 }
Julien Boeuf2d041182015-08-31 20:30:09 -07001178 }
Craig Tillera82950e2015-09-22 12:33:20 -07001179 r->cb(&exec_ctx, r->user_data, md_array, num_md, GRPC_CREDENTIALS_OK);
1180 if (md_array != NULL) {
1181 for (i = 0; i < num_md; i++) {
1182 gpr_slice_unref(md_array[i].key);
1183 gpr_slice_unref(md_array[i].value);
1184 }
1185 gpr_free(md_array);
1186 }
1187 }
1188 gpr_free(r);
Craig Tiller80183f32015-09-23 12:33:59 -07001189 grpc_exec_ctx_finish(&exec_ctx);
Julien Boeuf2d041182015-08-31 20:30:09 -07001190}
1191
Julien Boeuf441176d2015-10-09 21:14:07 -07001192static void plugin_get_request_metadata(grpc_exec_ctx *exec_ctx,
1193 grpc_call_credentials *creds,
1194 grpc_pollset *pollset,
1195 const char *service_url,
1196 grpc_credentials_metadata_cb cb,
1197 void *user_data) {
Craig Tillera82950e2015-09-22 12:33:20 -07001198 grpc_plugin_credentials *c = (grpc_plugin_credentials *)creds;
1199 if (c->plugin.get_metadata != NULL) {
1200 grpc_metadata_plugin_request *request = gpr_malloc(sizeof(*request));
1201 memset(request, 0, sizeof(*request));
1202 request->user_data = user_data;
1203 request->cb = cb;
1204 c->plugin.get_metadata(c->plugin.state, service_url,
1205 plugin_md_request_metadata_ready, request);
1206 } else {
1207 cb(exec_ctx, user_data, NULL, 0, GRPC_CREDENTIALS_OK);
1208 }
Julien Boeuf2d041182015-08-31 20:30:09 -07001209}
1210
Julien Boeuf441176d2015-10-09 21:14:07 -07001211static grpc_call_credentials_vtable plugin_vtable = {
1212 plugin_destruct, plugin_get_request_metadata};
Julien Boeuf2d041182015-08-31 20:30:09 -07001213
Julien Boeuf441176d2015-10-09 21:14:07 -07001214grpc_call_credentials *grpc_metadata_credentials_create_from_plugin(
Craig Tillera82950e2015-09-22 12:33:20 -07001215 grpc_metadata_credentials_plugin plugin, void *reserved) {
1216 grpc_plugin_credentials *c = gpr_malloc(sizeof(*c));
Julien Boeufb73cbc22015-10-20 21:52:54 -07001217 GRPC_API_TRACE("grpc_metadata_credentials_create_from_plugin(reserved=%p)", 1,
1218 (reserved));
Craig Tillera82950e2015-09-22 12:33:20 -07001219 GPR_ASSERT(reserved == NULL);
1220 memset(c, 0, sizeof(*c));
Julien Boeuf441176d2015-10-09 21:14:07 -07001221 c->base.type = GRPC_CALL_CREDENTIALS_TYPE_METADATA_PLUGIN;
Julien Boeuf2d041182015-08-31 20:30:09 -07001222 c->base.vtable = &plugin_vtable;
Craig Tillera82950e2015-09-22 12:33:20 -07001223 gpr_ref_init(&c->base.refcount, 1);
Julien Boeuf2d041182015-08-31 20:30:09 -07001224 c->plugin = plugin;
1225 return &c->base;
1226}
Julien Boeufb73cbc22015-10-20 21:52:54 -07001227
1228/* -- Composite channel credentials. -- */
1229
1230static void composite_channel_destruct(grpc_channel_credentials *creds) {
1231 grpc_composite_channel_credentials *c =
1232 (grpc_composite_channel_credentials *)creds;
1233 grpc_channel_credentials_unref(c->inner_creds);
1234 grpc_call_credentials_unref(c->call_creds);
1235}
1236
1237static grpc_security_status composite_channel_create_security_connector(
1238 grpc_channel_credentials *creds, grpc_call_credentials *call_creds,
1239 const char *target, const grpc_channel_args *args,
1240 grpc_channel_security_connector **sc, grpc_channel_args **new_args) {
1241 grpc_composite_channel_credentials *c =
1242 (grpc_composite_channel_credentials *)creds;
1243 grpc_security_status status = GRPC_SECURITY_ERROR;
1244
1245 GPR_ASSERT(c->inner_creds != NULL && c->call_creds != NULL &&
1246 c->inner_creds->vtable != NULL &&
1247 c->inner_creds->vtable->create_security_connector != NULL);
1248 /* If we are passed a call_creds, create a call composite to pass it
1249 downstream. */
1250 if (call_creds != NULL) {
1251 grpc_call_credentials *composite_call_creds =
1252 grpc_composite_call_credentials_create(c->call_creds, call_creds, NULL);
1253 status = c->inner_creds->vtable->create_security_connector(
1254 c->inner_creds, composite_call_creds, target, args, sc, new_args);
1255 grpc_call_credentials_unref(composite_call_creds);
1256 } else {
1257 status = c->inner_creds->vtable->create_security_connector(
1258 c->inner_creds, c->call_creds, target, args, sc, new_args);
1259 }
1260 return status;
1261}
1262
1263static grpc_channel_credentials_vtable composite_channel_credentials_vtable = {
1264 composite_channel_destruct, composite_channel_create_security_connector};
1265
1266grpc_channel_credentials *grpc_composite_channel_credentials_create(
1267 grpc_channel_credentials *channel_creds, grpc_call_credentials *call_creds,
1268 void *reserved) {
1269 grpc_composite_channel_credentials *c = gpr_malloc(sizeof(*c));
1270 memset(c, 0, sizeof(*c));
1271 GPR_ASSERT(channel_creds != NULL && call_creds != NULL && reserved == NULL);
1272 GRPC_API_TRACE(
1273 "grpc_composite_channel_credentials_create(channel_creds=%p, "
1274 "call_creds=%p, reserved=%p)",
1275 3, (channel_creds, call_creds, reserved));
1276 c->base.type = channel_creds->type;
1277 c->base.vtable = &composite_channel_credentials_vtable;
1278 gpr_ref_init(&c->base.refcount, 1);
1279 c->inner_creds = grpc_channel_credentials_ref(channel_creds);
1280 c->call_creds = grpc_call_credentials_ref(call_creds);
1281 return &c->base;
1282}