security_context.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676
  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/security_context.h"
  34. #include <string.h>
  35. #include "src/core/channel/channel_args.h"
  36. #include "src/core/channel/http_client_filter.h"
  37. #include "src/core/security/credentials.h"
  38. #include "src/core/security/secure_endpoint.h"
  39. #include "src/core/support/env.h"
  40. #include "src/core/support/file.h"
  41. #include "src/core/support/string.h"
  42. #include "src/core/transport/chttp2/alpn.h"
  43. #include <grpc/support/alloc.h>
  44. #include <grpc/support/host_port.h>
  45. #include <grpc/support/log.h>
  46. #include <grpc/support/slice_buffer.h>
  47. #include "src/core/tsi/fake_transport_security.h"
  48. #include "src/core/tsi/ssl_transport_security.h"
  49. /* -- Constants. -- */
  50. #ifndef INSTALL_PREFIX
  51. static const char *installed_roots_path = "/usr/share/grpc/roots.pem";
  52. #else
  53. static const char *installed_roots_path = INSTALL_PREFIX "/share/grpc/roots.pem";
  54. #endif
  55. /* -- Cipher suites. -- */
  56. /* Defines the cipher suites that we accept by default. All these cipher suites
  57. are compliant with HTTP2. */
  58. #define GRPC_SSL_CIPHER_SUITES \
  59. "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-" \
  60. "SHA384:ECDHE-RSA-AES256-GCM-SHA384"
  61. static gpr_once cipher_suites_once = GPR_ONCE_INIT;
  62. static const char *cipher_suites = NULL;
  63. static void init_cipher_suites(void) {
  64. char *overridden = gpr_getenv("GRPC_SSL_CIPHER_SUITES");
  65. cipher_suites = overridden != NULL ? overridden : GRPC_SSL_CIPHER_SUITES;
  66. }
  67. static const char *ssl_cipher_suites(void) {
  68. gpr_once_init(&cipher_suites_once, init_cipher_suites);
  69. return cipher_suites;
  70. }
  71. /* -- Common methods. -- */
  72. grpc_security_status grpc_security_context_create_handshaker(
  73. grpc_security_context *ctx, tsi_handshaker **handshaker) {
  74. if (ctx == NULL || handshaker == NULL) return GRPC_SECURITY_ERROR;
  75. return ctx->vtable->create_handshaker(ctx, handshaker);
  76. }
  77. grpc_security_status grpc_security_context_check_peer(
  78. grpc_security_context *ctx, tsi_peer peer, grpc_security_check_cb cb,
  79. void *user_data) {
  80. if (ctx == NULL) {
  81. tsi_peer_destruct(&peer);
  82. return GRPC_SECURITY_ERROR;
  83. }
  84. return ctx->vtable->check_peer(ctx, peer, cb, user_data);
  85. }
  86. grpc_security_status grpc_channel_security_context_check_call_host(
  87. grpc_channel_security_context *ctx, const char *host,
  88. grpc_security_check_cb cb, void *user_data) {
  89. if (ctx == NULL || ctx->check_call_host == NULL) return GRPC_SECURITY_ERROR;
  90. return ctx->check_call_host(ctx, host, cb, user_data);
  91. }
  92. void grpc_security_context_unref(grpc_security_context *ctx) {
  93. if (ctx == NULL) return;
  94. if (gpr_unref(&ctx->refcount)) ctx->vtable->destroy(ctx);
  95. }
  96. grpc_security_context *grpc_security_context_ref(grpc_security_context *ctx) {
  97. if (ctx == NULL) return NULL;
  98. gpr_ref(&ctx->refcount);
  99. return ctx;
  100. }
  101. static void context_pointer_arg_destroy(void *p) {
  102. grpc_security_context_unref(p);
  103. }
  104. static void *context_pointer_arg_copy(void *p) {
  105. return grpc_security_context_ref(p);
  106. }
  107. grpc_arg grpc_security_context_to_arg(grpc_security_context *ctx) {
  108. grpc_arg result;
  109. result.type = GRPC_ARG_POINTER;
  110. result.key = GRPC_SECURITY_CONTEXT_ARG;
  111. result.value.pointer.destroy = context_pointer_arg_destroy;
  112. result.value.pointer.copy = context_pointer_arg_copy;
  113. result.value.pointer.p = ctx;
  114. return result;
  115. }
  116. grpc_security_context *grpc_security_context_from_arg(const grpc_arg *arg) {
  117. if (strcmp(arg->key, GRPC_SECURITY_CONTEXT_ARG)) return NULL;
  118. if (arg->type != GRPC_ARG_POINTER) {
  119. gpr_log(GPR_ERROR, "Invalid type %d for arg %s", arg->type,
  120. GRPC_SECURITY_CONTEXT_ARG);
  121. return NULL;
  122. }
  123. return arg->value.pointer.p;
  124. }
  125. grpc_security_context *grpc_find_security_context_in_args(
  126. const grpc_channel_args *args) {
  127. size_t i;
  128. if (args == NULL) return NULL;
  129. for (i = 0; i < args->num_args; i++) {
  130. grpc_security_context *ctx = grpc_security_context_from_arg(&args->args[i]);
  131. if (ctx != NULL) return ctx;
  132. }
  133. return NULL;
  134. }
  135. static int check_request_metadata_creds(grpc_credentials *creds) {
  136. if (creds != NULL && !grpc_credentials_has_request_metadata(creds)) {
  137. gpr_log(GPR_ERROR,
  138. "Incompatible credentials for channel security context: needs to "
  139. "set request metadata.");
  140. return 0;
  141. }
  142. return 1;
  143. }
  144. /* -- Fake implementation. -- */
  145. typedef struct {
  146. grpc_channel_security_context base;
  147. int call_host_check_is_async;
  148. } grpc_fake_channel_security_context;
  149. static void fake_channel_destroy(grpc_security_context *ctx) {
  150. grpc_channel_security_context *c = (grpc_channel_security_context *)ctx;
  151. grpc_credentials_unref(c->request_metadata_creds);
  152. gpr_free(ctx);
  153. }
  154. static void fake_server_destroy(grpc_security_context *ctx) { gpr_free(ctx); }
  155. static grpc_security_status fake_channel_create_handshaker(
  156. grpc_security_context *ctx, tsi_handshaker **handshaker) {
  157. *handshaker = tsi_create_fake_handshaker(1);
  158. return GRPC_SECURITY_OK;
  159. }
  160. static grpc_security_status fake_server_create_handshaker(
  161. grpc_security_context *ctx, tsi_handshaker **handshaker) {
  162. *handshaker = tsi_create_fake_handshaker(0);
  163. return GRPC_SECURITY_OK;
  164. }
  165. static grpc_security_status fake_check_peer(grpc_security_context *ctx,
  166. tsi_peer peer,
  167. grpc_security_check_cb cb,
  168. void *user_data) {
  169. const char *prop_name;
  170. grpc_security_status status = GRPC_SECURITY_OK;
  171. if (peer.property_count != 1) {
  172. gpr_log(GPR_ERROR, "Fake peers should only have 1 property.");
  173. status = GRPC_SECURITY_ERROR;
  174. goto end;
  175. }
  176. prop_name = peer.properties[0].name;
  177. if (prop_name == NULL ||
  178. strcmp(prop_name, TSI_CERTIFICATE_TYPE_PEER_PROPERTY)) {
  179. gpr_log(GPR_ERROR, "Unexpected property in fake peer: %s.",
  180. prop_name == NULL ? "<EMPTY>" : prop_name);
  181. status = GRPC_SECURITY_ERROR;
  182. goto end;
  183. }
  184. if (peer.properties[0].type != TSI_PEER_PROPERTY_TYPE_STRING) {
  185. gpr_log(GPR_ERROR, "Invalid type of cert type property.");
  186. status = GRPC_SECURITY_ERROR;
  187. goto end;
  188. }
  189. if (strncmp(peer.properties[0].value.string.data, TSI_FAKE_CERTIFICATE_TYPE,
  190. peer.properties[0].value.string.length)) {
  191. gpr_log(GPR_ERROR, "Invalid value for cert type property.");
  192. status = GRPC_SECURITY_ERROR;
  193. goto end;
  194. }
  195. end:
  196. tsi_peer_destruct(&peer);
  197. return status;
  198. }
  199. static grpc_security_status fake_channel_check_call_host(
  200. grpc_channel_security_context *ctx, const char *host,
  201. grpc_security_check_cb cb, void *user_data) {
  202. grpc_fake_channel_security_context *c =
  203. (grpc_fake_channel_security_context *)ctx;
  204. if (c->call_host_check_is_async) {
  205. cb(user_data, GRPC_SECURITY_OK);
  206. return GRPC_SECURITY_PENDING;
  207. } else {
  208. return GRPC_SECURITY_OK;
  209. }
  210. }
  211. static grpc_security_context_vtable fake_channel_vtable = {
  212. fake_channel_destroy, fake_channel_create_handshaker, fake_check_peer};
  213. static grpc_security_context_vtable fake_server_vtable = {
  214. fake_server_destroy, fake_server_create_handshaker, fake_check_peer};
  215. grpc_channel_security_context *grpc_fake_channel_security_context_create(
  216. grpc_credentials *request_metadata_creds, int call_host_check_is_async) {
  217. grpc_fake_channel_security_context *c =
  218. gpr_malloc(sizeof(grpc_fake_channel_security_context));
  219. gpr_ref_init(&c->base.base.refcount, 1);
  220. c->base.base.is_client_side = 1;
  221. c->base.base.url_scheme = GRPC_FAKE_SECURITY_URL_SCHEME;
  222. c->base.base.vtable = &fake_channel_vtable;
  223. GPR_ASSERT(check_request_metadata_creds(request_metadata_creds));
  224. c->base.request_metadata_creds = grpc_credentials_ref(request_metadata_creds);
  225. c->base.check_call_host = fake_channel_check_call_host;
  226. c->call_host_check_is_async = call_host_check_is_async;
  227. return &c->base;
  228. }
  229. grpc_security_context *grpc_fake_server_security_context_create(void) {
  230. grpc_security_context *c = gpr_malloc(sizeof(grpc_security_context));
  231. gpr_ref_init(&c->refcount, 1);
  232. c->vtable = &fake_server_vtable;
  233. c->url_scheme = GRPC_FAKE_SECURITY_URL_SCHEME;
  234. return c;
  235. }
  236. /* --- Ssl implementation. --- */
  237. typedef struct {
  238. grpc_channel_security_context base;
  239. tsi_ssl_handshaker_factory *handshaker_factory;
  240. char *target_name;
  241. char *overridden_target_name;
  242. tsi_peer peer;
  243. } grpc_ssl_channel_security_context;
  244. typedef struct {
  245. grpc_security_context base;
  246. tsi_ssl_handshaker_factory *handshaker_factory;
  247. } grpc_ssl_server_security_context;
  248. static void ssl_channel_destroy(grpc_security_context *ctx) {
  249. grpc_ssl_channel_security_context *c =
  250. (grpc_ssl_channel_security_context *)ctx;
  251. grpc_credentials_unref(c->base.request_metadata_creds);
  252. if (c->handshaker_factory != NULL) {
  253. tsi_ssl_handshaker_factory_destroy(c->handshaker_factory);
  254. }
  255. if (c->target_name != NULL) gpr_free(c->target_name);
  256. if (c->overridden_target_name != NULL) gpr_free(c->overridden_target_name);
  257. tsi_peer_destruct(&c->peer);
  258. gpr_free(ctx);
  259. }
  260. static void ssl_server_destroy(grpc_security_context *ctx) {
  261. grpc_ssl_server_security_context *c = (grpc_ssl_server_security_context *)ctx;
  262. if (c->handshaker_factory != NULL) {
  263. tsi_ssl_handshaker_factory_destroy(c->handshaker_factory);
  264. }
  265. gpr_free(ctx);
  266. }
  267. static grpc_security_status ssl_create_handshaker(
  268. tsi_ssl_handshaker_factory *handshaker_factory, int is_client,
  269. const char *peer_name, tsi_handshaker **handshaker) {
  270. tsi_result result = TSI_OK;
  271. if (handshaker_factory == NULL) return GRPC_SECURITY_ERROR;
  272. result = tsi_ssl_handshaker_factory_create_handshaker(
  273. handshaker_factory, is_client ? peer_name : NULL, handshaker);
  274. if (result != TSI_OK) {
  275. gpr_log(GPR_ERROR, "Handshaker creation failed with error %s.",
  276. tsi_result_to_string(result));
  277. return GRPC_SECURITY_ERROR;
  278. }
  279. return GRPC_SECURITY_OK;
  280. }
  281. static grpc_security_status ssl_channel_create_handshaker(
  282. grpc_security_context *ctx, tsi_handshaker **handshaker) {
  283. grpc_ssl_channel_security_context *c =
  284. (grpc_ssl_channel_security_context *)ctx;
  285. return ssl_create_handshaker(c->handshaker_factory, 1,
  286. c->overridden_target_name != NULL
  287. ? c->overridden_target_name
  288. : c->target_name,
  289. handshaker);
  290. }
  291. static grpc_security_status ssl_server_create_handshaker(
  292. grpc_security_context *ctx, tsi_handshaker **handshaker) {
  293. grpc_ssl_server_security_context *c = (grpc_ssl_server_security_context *)ctx;
  294. return ssl_create_handshaker(c->handshaker_factory, 0, NULL, handshaker);
  295. }
  296. static int ssl_host_matches_name(const tsi_peer *peer,
  297. const char *peer_name) {
  298. char *allocated_name = NULL;
  299. int r;
  300. if (strchr(peer_name, ':') != NULL) {
  301. char *ignored_port;
  302. gpr_split_host_port(peer_name, &allocated_name, &ignored_port);
  303. gpr_free(ignored_port);
  304. peer_name = allocated_name;
  305. if (!peer_name) return 0;
  306. }
  307. r = tsi_ssl_peer_matches_name(peer, peer_name);
  308. gpr_free(allocated_name);
  309. return r;
  310. }
  311. static grpc_security_status ssl_check_peer(const char *peer_name,
  312. const tsi_peer *peer) {
  313. /* Check the ALPN. */
  314. const tsi_peer_property *p =
  315. tsi_peer_get_property_by_name(peer, TSI_SSL_ALPN_SELECTED_PROTOCOL);
  316. if (p == NULL) {
  317. gpr_log(GPR_ERROR, "Missing selected ALPN property.");
  318. return GRPC_SECURITY_ERROR;
  319. }
  320. if (p->type != TSI_PEER_PROPERTY_TYPE_STRING) {
  321. gpr_log(GPR_ERROR, "Invalid selected ALPN property.");
  322. return GRPC_SECURITY_ERROR;
  323. }
  324. if (!grpc_chttp2_is_alpn_version_supported(p->value.string.data,
  325. p->value.string.length)) {
  326. gpr_log(GPR_ERROR, "Invalid ALPN value.");
  327. return GRPC_SECURITY_ERROR;
  328. }
  329. /* Check the peer name if specified. */
  330. if (peer_name != NULL &&
  331. !ssl_host_matches_name(peer, peer_name)) {
  332. gpr_log(GPR_ERROR, "Peer name %s is not in peer certificate", peer_name);
  333. return GRPC_SECURITY_ERROR;
  334. }
  335. return GRPC_SECURITY_OK;
  336. }
  337. static grpc_security_status ssl_channel_check_peer(grpc_security_context *ctx,
  338. tsi_peer peer,
  339. grpc_security_check_cb cb,
  340. void *user_data) {
  341. grpc_ssl_channel_security_context *c =
  342. (grpc_ssl_channel_security_context *)ctx;
  343. grpc_security_status status;
  344. tsi_peer_destruct(&c->peer);
  345. c->peer = peer;
  346. status = ssl_check_peer(c->overridden_target_name != NULL
  347. ? c->overridden_target_name
  348. : c->target_name,
  349. &peer);
  350. return status;
  351. }
  352. static grpc_security_status ssl_server_check_peer(grpc_security_context *ctx,
  353. tsi_peer peer,
  354. grpc_security_check_cb cb,
  355. void *user_data) {
  356. /* TODO(jboeuf): Find a way to expose the peer to the authorization layer. */
  357. grpc_security_status status = ssl_check_peer(NULL, &peer);
  358. tsi_peer_destruct(&peer);
  359. return status;
  360. }
  361. static grpc_security_status ssl_channel_check_call_host(
  362. grpc_channel_security_context *ctx, const char *host,
  363. grpc_security_check_cb cb, void *user_data) {
  364. grpc_ssl_channel_security_context *c =
  365. (grpc_ssl_channel_security_context *)ctx;
  366. if (ssl_host_matches_name(&c->peer, host)) return GRPC_SECURITY_OK;
  367. /* If the target name was overridden, then the original target_name was
  368. 'checked' transitively during the previous peer check at the end of the
  369. handshake. */
  370. if (c->overridden_target_name != NULL && strcmp(host, c->target_name) == 0) {
  371. return GRPC_SECURITY_OK;
  372. } else {
  373. return GRPC_SECURITY_ERROR;
  374. }
  375. }
  376. static grpc_security_context_vtable ssl_channel_vtable = {
  377. ssl_channel_destroy, ssl_channel_create_handshaker, ssl_channel_check_peer};
  378. static grpc_security_context_vtable ssl_server_vtable = {
  379. ssl_server_destroy, ssl_server_create_handshaker, ssl_server_check_peer};
  380. static gpr_slice default_pem_root_certs;
  381. static void init_default_pem_root_certs(void) {
  382. /* First try to load the roots from the environment. */
  383. char *default_root_certs_path =
  384. gpr_getenv(GRPC_DEFAULT_SSL_ROOTS_FILE_PATH_ENV_VAR);
  385. if (default_root_certs_path == NULL) {
  386. default_pem_root_certs = gpr_empty_slice();
  387. } else {
  388. default_pem_root_certs = gpr_load_file(default_root_certs_path, NULL);
  389. gpr_free(default_root_certs_path);
  390. }
  391. /* Fall back to installed certs if needed. */
  392. if (GPR_SLICE_IS_EMPTY(default_pem_root_certs)) {
  393. default_pem_root_certs = gpr_load_file(installed_roots_path, NULL);
  394. }
  395. }
  396. size_t grpc_get_default_ssl_roots(const unsigned char **pem_root_certs) {
  397. /* TODO(jboeuf@google.com): Maybe revisit the approach which consists in
  398. loading all the roots once for the lifetime of the process. */
  399. static gpr_once once = GPR_ONCE_INIT;
  400. gpr_once_init(&once, init_default_pem_root_certs);
  401. *pem_root_certs = GPR_SLICE_START_PTR(default_pem_root_certs);
  402. return GPR_SLICE_LENGTH(default_pem_root_certs);
  403. }
  404. grpc_security_status grpc_ssl_channel_security_context_create(
  405. grpc_credentials *request_metadata_creds, const grpc_ssl_config *config,
  406. const char *target_name, const char *overridden_target_name,
  407. grpc_channel_security_context **ctx) {
  408. size_t num_alpn_protocols = grpc_chttp2_num_alpn_versions();
  409. const unsigned char **alpn_protocol_strings =
  410. gpr_malloc(sizeof(const char *) * num_alpn_protocols);
  411. unsigned char *alpn_protocol_string_lengths =
  412. gpr_malloc(sizeof(unsigned char) * num_alpn_protocols);
  413. tsi_result result = TSI_OK;
  414. grpc_ssl_channel_security_context *c;
  415. size_t i;
  416. const unsigned char *pem_root_certs;
  417. size_t pem_root_certs_size;
  418. char *port;
  419. for (i = 0; i < num_alpn_protocols; i++) {
  420. alpn_protocol_strings[i] =
  421. (const unsigned char *)grpc_chttp2_get_alpn_version_index(i);
  422. alpn_protocol_string_lengths[i] =
  423. strlen(grpc_chttp2_get_alpn_version_index(i));
  424. }
  425. if (config == NULL || target_name == NULL) {
  426. gpr_log(GPR_ERROR, "An ssl channel needs a config and a target name.");
  427. goto error;
  428. }
  429. if (!check_request_metadata_creds(request_metadata_creds)) {
  430. goto error;
  431. }
  432. c = gpr_malloc(sizeof(grpc_ssl_channel_security_context));
  433. memset(c, 0, sizeof(grpc_ssl_channel_security_context));
  434. gpr_ref_init(&c->base.base.refcount, 1);
  435. c->base.base.vtable = &ssl_channel_vtable;
  436. c->base.base.is_client_side = 1;
  437. c->base.base.url_scheme = GRPC_SSL_URL_SCHEME;
  438. c->base.request_metadata_creds = grpc_credentials_ref(request_metadata_creds);
  439. c->base.check_call_host = ssl_channel_check_call_host;
  440. gpr_split_host_port(target_name, &c->target_name, &port);
  441. gpr_free(port);
  442. if (overridden_target_name != NULL) {
  443. c->overridden_target_name = gpr_strdup(overridden_target_name);
  444. }
  445. if (config->pem_root_certs == NULL) {
  446. pem_root_certs_size = grpc_get_default_ssl_roots(&pem_root_certs);
  447. if (pem_root_certs == NULL || pem_root_certs_size == 0) {
  448. gpr_log(GPR_ERROR, "Could not get default pem root certs.");
  449. goto error;
  450. }
  451. } else {
  452. pem_root_certs = config->pem_root_certs;
  453. pem_root_certs_size = config->pem_root_certs_size;
  454. }
  455. result = tsi_create_ssl_client_handshaker_factory(
  456. config->pem_private_key, config->pem_private_key_size,
  457. config->pem_cert_chain, config->pem_cert_chain_size, pem_root_certs,
  458. pem_root_certs_size, ssl_cipher_suites(), alpn_protocol_strings,
  459. alpn_protocol_string_lengths, num_alpn_protocols, &c->handshaker_factory);
  460. if (result != TSI_OK) {
  461. gpr_log(GPR_ERROR, "Handshaker factory creation failed with %s.",
  462. tsi_result_to_string(result));
  463. ssl_channel_destroy(&c->base.base);
  464. *ctx = NULL;
  465. goto error;
  466. }
  467. *ctx = &c->base;
  468. gpr_free(alpn_protocol_strings);
  469. gpr_free(alpn_protocol_string_lengths);
  470. return GRPC_SECURITY_OK;
  471. error:
  472. gpr_free(alpn_protocol_strings);
  473. gpr_free(alpn_protocol_string_lengths);
  474. return GRPC_SECURITY_ERROR;
  475. }
  476. grpc_security_status grpc_ssl_server_security_context_create(
  477. const grpc_ssl_server_config *config, grpc_security_context **ctx) {
  478. size_t num_alpn_protocols = grpc_chttp2_num_alpn_versions();
  479. const unsigned char **alpn_protocol_strings =
  480. gpr_malloc(sizeof(const char *) * num_alpn_protocols);
  481. unsigned char *alpn_protocol_string_lengths =
  482. gpr_malloc(sizeof(unsigned char) * num_alpn_protocols);
  483. tsi_result result = TSI_OK;
  484. grpc_ssl_server_security_context *c;
  485. size_t i;
  486. for (i = 0; i < num_alpn_protocols; i++) {
  487. alpn_protocol_strings[i] =
  488. (const unsigned char *)grpc_chttp2_get_alpn_version_index(i);
  489. alpn_protocol_string_lengths[i] =
  490. strlen(grpc_chttp2_get_alpn_version_index(i));
  491. }
  492. if (config == NULL || config->num_key_cert_pairs == 0) {
  493. gpr_log(GPR_ERROR, "An SSL server needs a key and a cert.");
  494. goto error;
  495. }
  496. c = gpr_malloc(sizeof(grpc_ssl_server_security_context));
  497. memset(c, 0, sizeof(grpc_ssl_server_security_context));
  498. gpr_ref_init(&c->base.refcount, 1);
  499. c->base.url_scheme = GRPC_SSL_URL_SCHEME;
  500. c->base.vtable = &ssl_server_vtable;
  501. result = tsi_create_ssl_server_handshaker_factory(
  502. (const unsigned char **)config->pem_private_keys,
  503. config->pem_private_keys_sizes,
  504. (const unsigned char **)config->pem_cert_chains,
  505. config->pem_cert_chains_sizes, config->num_key_cert_pairs,
  506. config->pem_root_certs, config->pem_root_certs_size,
  507. ssl_cipher_suites(), alpn_protocol_strings,
  508. alpn_protocol_string_lengths, num_alpn_protocols, &c->handshaker_factory);
  509. if (result != TSI_OK) {
  510. gpr_log(GPR_ERROR, "Handshaker factory creation failed with %s.",
  511. tsi_result_to_string(result));
  512. ssl_server_destroy(&c->base);
  513. *ctx = NULL;
  514. goto error;
  515. }
  516. *ctx = &c->base;
  517. gpr_free(alpn_protocol_strings);
  518. gpr_free(alpn_protocol_string_lengths);
  519. return GRPC_SECURITY_OK;
  520. error:
  521. gpr_free(alpn_protocol_strings);
  522. gpr_free(alpn_protocol_string_lengths);
  523. return GRPC_SECURITY_ERROR;
  524. }
  525. /* -- High level objects. -- */
  526. grpc_channel *grpc_ssl_channel_create(grpc_credentials *ssl_creds,
  527. grpc_credentials *request_metadata_creds,
  528. const char *target,
  529. const grpc_channel_args *args) {
  530. grpc_channel_security_context *ctx = NULL;
  531. grpc_channel *channel = NULL;
  532. grpc_security_status status = GRPC_SECURITY_OK;
  533. size_t i = 0;
  534. const char *overridden_target_name = NULL;
  535. grpc_arg arg;
  536. grpc_channel_args *new_args;
  537. for (i = 0; args && i < args->num_args; i++) {
  538. grpc_arg *arg = &args->args[i];
  539. if (strcmp(arg->key, GRPC_SSL_TARGET_NAME_OVERRIDE_ARG) == 0 &&
  540. arg->type == GRPC_ARG_STRING) {
  541. overridden_target_name = arg->value.string;
  542. break;
  543. }
  544. }
  545. status = grpc_ssl_channel_security_context_create(
  546. request_metadata_creds, grpc_ssl_credentials_get_config(ssl_creds),
  547. target, overridden_target_name, &ctx);
  548. if (status != GRPC_SECURITY_OK) {
  549. return grpc_lame_client_channel_create();
  550. }
  551. arg.type = GRPC_ARG_STRING;
  552. arg.key = GRPC_ARG_HTTP2_SCHEME;
  553. arg.value.string = "https";
  554. new_args = grpc_channel_args_copy_and_add(args, &arg);
  555. channel = grpc_secure_channel_create_internal(target, new_args, ctx);
  556. grpc_security_context_unref(&ctx->base);
  557. grpc_channel_args_destroy(new_args);
  558. return channel;
  559. }
  560. grpc_channel *grpc_fake_transport_security_channel_create(
  561. grpc_credentials *fake_creds, grpc_credentials *request_metadata_creds,
  562. const char *target, const grpc_channel_args *args) {
  563. grpc_channel_security_context *ctx =
  564. grpc_fake_channel_security_context_create(request_metadata_creds, 1);
  565. grpc_channel *channel =
  566. grpc_secure_channel_create_internal(target, args, ctx);
  567. grpc_security_context_unref(&ctx->base);
  568. return channel;
  569. }
  570. grpc_channel *grpc_secure_channel_create_with_factories(
  571. const grpc_secure_channel_factory *factories, size_t num_factories,
  572. grpc_credentials *creds, const char *target,
  573. const grpc_channel_args *args) {
  574. size_t i;
  575. if (creds == NULL) {
  576. gpr_log(GPR_ERROR, "No credentials to create a secure channel.");
  577. return grpc_lame_client_channel_create();
  578. }
  579. if (grpc_credentials_has_request_metadata_only(creds)) {
  580. gpr_log(GPR_ERROR,
  581. "Credentials is insufficient to create a secure channel.");
  582. return grpc_lame_client_channel_create();
  583. }
  584. for (i = 0; i < num_factories; i++) {
  585. grpc_credentials *composite_creds = NULL;
  586. grpc_credentials *transport_security_creds = NULL;
  587. transport_security_creds = grpc_credentials_contains_type(
  588. creds, factories[i].creds_type, &composite_creds);
  589. if (transport_security_creds != NULL) {
  590. return factories[i].factory(transport_security_creds, composite_creds,
  591. target, args);
  592. }
  593. }
  594. gpr_log(GPR_ERROR,
  595. "Unknown credentials type %s for creating a secure channel.",
  596. creds->type);
  597. return grpc_lame_client_channel_create();
  598. }