LCOV - code coverage report
Current view: top level - core/security - credentials.c (source / functions) Hit Total Coverage
Test: tmp.CaZ6RjdVn2 Lines: 640 678 94.4 %
Date: 2015-12-10 22:15:08 Functions: 73 74 98.6 %

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

Generated by: LCOV version 1.11