blob: e8575d4e6e9a8efd12351326f97822a81d7c9148 [file] [log] [blame]
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001/*
2 *
Craig Tiller6169d5f2016-03-31 07:46:18 -07003 * Copyright 2015, Google Inc.
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08004 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above
13 * copyright notice, this list of conditions and the following disclaimer
14 * in the documentation and/or other materials provided with the
15 * distribution.
16 * * Neither the name of Google Inc. nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 */
33
Craig Tiller9533d042016-03-25 17:11:06 -070034#include "src/core/lib/http/httpcli.h"
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080035
36#include <string.h>
37
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080038#include <grpc/support/alloc.h>
39#include <grpc/support/log.h>
Masood Malekghassemi701af602015-06-03 15:01:17 -070040#include <grpc/support/string_util.h>
Julien Boeuf8ca294e2016-05-02 14:56:30 -070041#include "src/core/lib/security/transport/handshake.h"
Craig Tiller9533d042016-03-25 17:11:06 -070042#include "src/core/lib/support/string.h"
43#include "src/core/lib/tsi/ssl_transport_security.h"
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080044
Craig Tillera82950e2015-09-22 12:33:20 -070045typedef struct {
Julien Boeuf7d1d9ca2015-04-17 14:38:48 -070046 grpc_channel_security_connector base;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080047 tsi_ssl_handshaker_factory *handshaker_factory;
48 char *secure_peer_name;
Julien Boeuf7d1d9ca2015-04-17 14:38:48 -070049} grpc_httpcli_ssl_channel_security_connector;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080050
Craig Tillerbd1795c2016-10-31 15:30:00 -070051static void httpcli_ssl_destroy(grpc_exec_ctx *exec_ctx,
52 grpc_security_connector *sc) {
Craig Tillera82950e2015-09-22 12:33:20 -070053 grpc_httpcli_ssl_channel_security_connector *c =
54 (grpc_httpcli_ssl_channel_security_connector *)sc;
55 if (c->handshaker_factory != NULL) {
56 tsi_ssl_handshaker_factory_destroy(c->handshaker_factory);
57 }
58 if (c->secure_peer_name != NULL) gpr_free(c->secure_peer_name);
59 gpr_free(sc);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080060}
61
Craig Tillera82950e2015-09-22 12:33:20 -070062static void httpcli_ssl_do_handshake(grpc_exec_ctx *exec_ctx,
Julien Boeuf4f4d37c2016-02-24 22:07:36 -080063 grpc_channel_security_connector *sc,
Craig Tillera82950e2015-09-22 12:33:20 -070064 grpc_endpoint *nonsecure_endpoint,
Craig Tillerd41a4a72016-10-26 16:16:06 -070065 grpc_slice_buffer *read_buffer,
Craig Tiller449c64b2016-06-13 16:26:50 -070066 gpr_timespec deadline,
Craig Tillera82950e2015-09-22 12:33:20 -070067 grpc_security_handshake_done_cb cb,
68 void *user_data) {
69 grpc_httpcli_ssl_channel_security_connector *c =
70 (grpc_httpcli_ssl_channel_security_connector *)sc;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080071 tsi_result result = TSI_OK;
Julien Boeufdb5282b2015-08-21 15:23:52 -070072 tsi_handshaker *handshaker;
Craig Tillera82950e2015-09-22 12:33:20 -070073 if (c->handshaker_factory == NULL) {
Mark D. Roth7d9f2762016-08-04 11:06:49 -070074 gpr_free(read_buffer);
Julien Boeuf366f42c2015-12-16 22:05:46 -080075 cb(exec_ctx, user_data, GRPC_SECURITY_ERROR, NULL, NULL);
Craig Tillera82950e2015-09-22 12:33:20 -070076 return;
77 }
78 result = tsi_ssl_handshaker_factory_create_handshaker(
79 c->handshaker_factory, c->secure_peer_name, &handshaker);
80 if (result != TSI_OK) {
81 gpr_log(GPR_ERROR, "Handshaker creation failed with error %s.",
82 tsi_result_to_string(result));
Mark D. Roth7d9f2762016-08-04 11:06:49 -070083 gpr_free(read_buffer);
Julien Boeuf366f42c2015-12-16 22:05:46 -080084 cb(exec_ctx, user_data, GRPC_SECURITY_ERROR, NULL, NULL);
Craig Tillera82950e2015-09-22 12:33:20 -070085 } else {
Julien Boeuf4f4d37c2016-02-24 22:07:36 -080086 grpc_do_security_handshake(exec_ctx, handshaker, &sc->base, true,
Mark D. Roth7d9f2762016-08-04 11:06:49 -070087 nonsecure_endpoint, read_buffer, deadline, cb,
88 user_data);
Craig Tillera82950e2015-09-22 12:33:20 -070089 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080090}
91
Julien Boeuf366f42c2015-12-16 22:05:46 -080092static void httpcli_ssl_check_peer(grpc_exec_ctx *exec_ctx,
Craig Tillerbe52c6e2016-01-04 15:35:26 -080093 grpc_security_connector *sc, tsi_peer peer,
Julien Boeuf366f42c2015-12-16 22:05:46 -080094 grpc_security_peer_check_cb cb,
95 void *user_data) {
Craig Tillera82950e2015-09-22 12:33:20 -070096 grpc_httpcli_ssl_channel_security_connector *c =
97 (grpc_httpcli_ssl_channel_security_connector *)sc;
Julien Boeuf54b21922015-02-04 16:39:35 -080098 grpc_security_status status = GRPC_SECURITY_OK;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080099
100 /* Check the peer name. */
Craig Tillera82950e2015-09-22 12:33:20 -0700101 if (c->secure_peer_name != NULL &&
102 !tsi_ssl_peer_matches_name(&peer, c->secure_peer_name)) {
103 gpr_log(GPR_ERROR, "Peer name %s is not in peer certificate",
104 c->secure_peer_name);
105 status = GRPC_SECURITY_ERROR;
106 }
Julien Boeuf366f42c2015-12-16 22:05:46 -0800107 cb(exec_ctx, user_data, status, NULL);
Julien Boeuf1d9ac662015-12-17 21:35:47 -0800108 tsi_peer_destruct(&peer);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800109}
110
Julien Boeuf7d1d9ca2015-04-17 14:38:48 -0700111static grpc_security_connector_vtable httpcli_ssl_vtable = {
Julien Boeuf4f4d37c2016-02-24 22:07:36 -0800112 httpcli_ssl_destroy, httpcli_ssl_check_peer};
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800113
Craig Tillera82950e2015-09-22 12:33:20 -0700114static grpc_security_status httpcli_ssl_channel_security_connector_create(
Craig Tillerbd1795c2016-10-31 15:30:00 -0700115 grpc_exec_ctx *exec_ctx, const unsigned char *pem_root_certs,
116 size_t pem_root_certs_size, const char *secure_peer_name,
117 grpc_channel_security_connector **sc) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800118 tsi_result result = TSI_OK;
Julien Boeuf7d1d9ca2015-04-17 14:38:48 -0700119 grpc_httpcli_ssl_channel_security_connector *c;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800120
Craig Tillera82950e2015-09-22 12:33:20 -0700121 if (secure_peer_name != NULL && pem_root_certs == NULL) {
122 gpr_log(GPR_ERROR,
123 "Cannot assert a secure peer name without a trust root.");
124 return GRPC_SECURITY_ERROR;
125 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800126
Craig Tillera82950e2015-09-22 12:33:20 -0700127 c = gpr_malloc(sizeof(grpc_httpcli_ssl_channel_security_connector));
128 memset(c, 0, sizeof(grpc_httpcli_ssl_channel_security_connector));
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800129
Craig Tillera82950e2015-09-22 12:33:20 -0700130 gpr_ref_init(&c->base.base.refcount, 1);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800131 c->base.base.vtable = &httpcli_ssl_vtable;
Craig Tillera82950e2015-09-22 12:33:20 -0700132 if (secure_peer_name != NULL) {
133 c->secure_peer_name = gpr_strdup(secure_peer_name);
134 }
135 result = tsi_create_ssl_client_handshaker_factory(
136 NULL, 0, NULL, 0, pem_root_certs, pem_root_certs_size, NULL, NULL, NULL,
137 0, &c->handshaker_factory);
138 if (result != TSI_OK) {
139 gpr_log(GPR_ERROR, "Handshaker factory creation failed with %s.",
140 tsi_result_to_string(result));
Craig Tillerbd1795c2016-10-31 15:30:00 -0700141 httpcli_ssl_destroy(exec_ctx, &c->base.base);
Craig Tillera82950e2015-09-22 12:33:20 -0700142 *sc = NULL;
143 return GRPC_SECURITY_ERROR;
144 }
Julien Boeuf4f4d37c2016-02-24 22:07:36 -0800145 c->base.do_handshake = httpcli_ssl_do_handshake;
Julien Boeuf7d1d9ca2015-04-17 14:38:48 -0700146 *sc = &c->base;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800147 return GRPC_SECURITY_OK;
Craig Tiller190d3602015-02-18 09:23:38 -0800148}
Craig Tillerf53d9c82015-08-04 14:19:43 -0700149
150/* handshaker */
151
Craig Tillera82950e2015-09-22 12:33:20 -0700152typedef struct {
153 void (*func)(grpc_exec_ctx *exec_ctx, void *arg, grpc_endpoint *endpoint);
Craig Tillerf53d9c82015-08-04 14:19:43 -0700154 void *arg;
155} on_done_closure;
156
Craig Tillera82950e2015-09-22 12:33:20 -0700157static void on_secure_transport_setup_done(grpc_exec_ctx *exec_ctx, void *rp,
158 grpc_security_status status,
Julien Boeuf366f42c2015-12-16 22:05:46 -0800159 grpc_endpoint *secure_endpoint,
160 grpc_auth_context *auth_context) {
Craig Tillerf53d9c82015-08-04 14:19:43 -0700161 on_done_closure *c = rp;
Craig Tillera82950e2015-09-22 12:33:20 -0700162 if (status != GRPC_SECURITY_OK) {
163 gpr_log(GPR_ERROR, "Secure transport setup failed with error %d.", status);
164 c->func(exec_ctx, c->arg, NULL);
165 } else {
166 c->func(exec_ctx, c->arg, secure_endpoint);
167 }
168 gpr_free(c);
Craig Tillerf53d9c82015-08-04 14:19:43 -0700169}
170
Craig Tillera82950e2015-09-22 12:33:20 -0700171static void ssl_handshake(grpc_exec_ctx *exec_ctx, void *arg,
172 grpc_endpoint *tcp, const char *host,
Craig Tiller449c64b2016-06-13 16:26:50 -0700173 gpr_timespec deadline,
Craig Tillera82950e2015-09-22 12:33:20 -0700174 void (*on_done)(grpc_exec_ctx *exec_ctx, void *arg,
175 grpc_endpoint *endpoint)) {
Craig Tillerf53d9c82015-08-04 14:19:43 -0700176 grpc_channel_security_connector *sc = NULL;
177 const unsigned char *pem_root_certs = NULL;
Craig Tillera82950e2015-09-22 12:33:20 -0700178 on_done_closure *c = gpr_malloc(sizeof(*c));
179 size_t pem_root_certs_size = grpc_get_default_ssl_roots(&pem_root_certs);
180 if (pem_root_certs == NULL || pem_root_certs_size == 0) {
181 gpr_log(GPR_ERROR, "Could not get default pem root certs.");
182 on_done(exec_ctx, arg, NULL);
183 gpr_free(c);
184 return;
185 }
Craig Tillerf53d9c82015-08-04 14:19:43 -0700186 c->func = on_done;
187 c->arg = arg;
Craig Tillera82950e2015-09-22 12:33:20 -0700188 GPR_ASSERT(httpcli_ssl_channel_security_connector_create(
Craig Tillerbd1795c2016-10-31 15:30:00 -0700189 exec_ctx, pem_root_certs, pem_root_certs_size, host, &sc) ==
Craig Tillera82950e2015-09-22 12:33:20 -0700190 GRPC_SECURITY_OK);
Julien Boeuf4f4d37c2016-02-24 22:07:36 -0800191 grpc_channel_security_connector_do_handshake(
Mark D. Roth7d9f2762016-08-04 11:06:49 -0700192 exec_ctx, sc, tcp, NULL, deadline, on_secure_transport_setup_done, c);
Craig Tillerbd1795c2016-10-31 15:30:00 -0700193 GRPC_SECURITY_CONNECTOR_UNREF(exec_ctx, &sc->base, "httpcli");
Craig Tillerf53d9c82015-08-04 14:19:43 -0700194}
195
Craig Tillera82950e2015-09-22 12:33:20 -0700196const grpc_httpcli_handshaker grpc_httpcli_ssl = {"https", ssl_handshake};