credentials.c 49 KB

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