blob: 0b53d63e773f284883fa741ab2e66a3d2a21c511 [file] [log] [blame]
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001/*
2 *
Jan Tattermusch7897ae92017-06-07 22:57:36 +02003 * Copyright 2015 gRPC authors.
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08004 *
Jan Tattermusch7897ae92017-06-07 22:57:36 +02005 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08008 *
Jan Tattermusch7897ae92017-06-07 22:57:36 +02009 * http://www.apache.org/licenses/LICENSE-2.0
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080010 *
Jan Tattermusch7897ae92017-06-07 22:57:36 +020011 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080016 *
17 */
18
Alexander Polcyndb3e8982018-02-21 16:59:24 -080019#include <grpc/support/port_platform.h>
20
Craig Tiller9533d042016-03-25 17:11:06 -070021#include "src/core/lib/http/httpcli.h"
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080022
23#include <string.h>
24
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080025#include <grpc/support/alloc.h>
26#include <grpc/support/log.h>
Masood Malekghassemi701af602015-06-03 15:01:17 -070027#include <grpc/support/string_util.h>
Mark D. Roth963be372016-11-16 14:17:06 -080028
29#include "src/core/lib/channel/channel_args.h"
Mark D. Rothbe928be2017-06-29 10:43:00 -070030#include "src/core/lib/channel/handshaker_registry.h"
Mark D. Rothdbdf4952018-01-18 11:21:12 -080031#include "src/core/lib/gpr/string.h"
Mark D. Roth071cacf2016-11-17 13:17:56 -080032#include "src/core/lib/security/transport/security_handshaker.h"
Craig Tiller6822a7a2016-12-06 19:28:52 -080033#include "src/core/lib/slice/slice_internal.h"
Craig Tillerb29f1fe2017-03-28 15:49:23 -070034#include "src/core/tsi/ssl_transport_security.h"
jiangtaoli201622cc52a2017-04-28 17:35:35 -070035#include "src/core/tsi/transport_security_adapter.h"
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080036
Craig Tillera82950e2015-09-22 12:33:20 -070037typedef struct {
Julien Boeuf7d1d9ca2015-04-17 14:38:48 -070038 grpc_channel_security_connector base;
Craig Tillerbaa14a92017-11-03 09:09:36 -070039 tsi_ssl_client_handshaker_factory* handshaker_factory;
40 char* secure_peer_name;
Julien Boeuf7d1d9ca2015-04-17 14:38:48 -070041} grpc_httpcli_ssl_channel_security_connector;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080042
Yash Tibrewal8cf14702017-12-06 09:47:54 -080043static void httpcli_ssl_destroy(grpc_security_connector* sc) {
Craig Tillerbaa14a92017-11-03 09:09:36 -070044 grpc_httpcli_ssl_channel_security_connector* c =
Noah Eisenbe82e642018-02-09 09:16:55 -080045 reinterpret_cast<grpc_httpcli_ssl_channel_security_connector*>(sc);
Craig Tiller4782d922017-11-10 09:53:21 -080046 if (c->handshaker_factory != nullptr) {
Justin Burke49841352017-08-31 17:42:54 -070047 tsi_ssl_client_handshaker_factory_unref(c->handshaker_factory);
Craig Tiller4782d922017-11-10 09:53:21 -080048 c->handshaker_factory = nullptr;
Craig Tillera82950e2015-09-22 12:33:20 -070049 }
Craig Tiller4782d922017-11-10 09:53:21 -080050 if (c->secure_peer_name != nullptr) gpr_free(c->secure_peer_name);
Craig Tillera82950e2015-09-22 12:33:20 -070051 gpr_free(sc);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080052}
53
Yash Tibrewal8cf14702017-12-06 09:47:54 -080054static void httpcli_ssl_add_handshakers(grpc_channel_security_connector* sc,
Craig Tillerbaa14a92017-11-03 09:09:36 -070055 grpc_handshake_manager* handshake_mgr) {
56 grpc_httpcli_ssl_channel_security_connector* c =
Noah Eisenbe82e642018-02-09 09:16:55 -080057 reinterpret_cast<grpc_httpcli_ssl_channel_security_connector*>(sc);
Craig Tiller4782d922017-11-10 09:53:21 -080058 tsi_handshaker* handshaker = nullptr;
59 if (c->handshaker_factory != nullptr) {
Julien Boeuf935d02e2017-04-09 00:07:09 -070060 tsi_result result = tsi_ssl_client_handshaker_factory_create_handshaker(
Mark D. Roth963be372016-11-16 14:17:06 -080061 c->handshaker_factory, c->secure_peer_name, &handshaker);
62 if (result != TSI_OK) {
63 gpr_log(GPR_ERROR, "Handshaker creation failed with error %s.",
64 tsi_result_to_string(result));
65 }
Craig Tillera82950e2015-09-22 12:33:20 -070066 }
Mark D. Rothd0953402016-12-07 07:56:48 -080067 grpc_handshake_manager_add(
Yash Tibrewal8cf14702017-12-06 09:47:54 -080068 handshake_mgr, grpc_security_handshaker_create(
69 tsi_create_adapter_handshaker(handshaker), &sc->base));
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080070}
71
Yash Tibrewal8cf14702017-12-06 09:47:54 -080072static void httpcli_ssl_check_peer(grpc_security_connector* sc, tsi_peer peer,
Craig Tillerbaa14a92017-11-03 09:09:36 -070073 grpc_auth_context** auth_context,
74 grpc_closure* on_peer_checked) {
75 grpc_httpcli_ssl_channel_security_connector* c =
Noah Eisenbe82e642018-02-09 09:16:55 -080076 reinterpret_cast<grpc_httpcli_ssl_channel_security_connector*>(sc);
Craig Tillerbaa14a92017-11-03 09:09:36 -070077 grpc_error* error = GRPC_ERROR_NONE;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080078
79 /* Check the peer name. */
Craig Tiller4782d922017-11-10 09:53:21 -080080 if (c->secure_peer_name != nullptr &&
Craig Tillera82950e2015-09-22 12:33:20 -070081 !tsi_ssl_peer_matches_name(&peer, c->secure_peer_name)) {
Craig Tillerbaa14a92017-11-03 09:09:36 -070082 char* msg;
Mark D. Roth3beb6c52016-11-29 11:25:12 -080083 gpr_asprintf(&msg, "Peer name %s is not in peer certificate",
84 c->secure_peer_name);
ncteisen4b36a3d2017-03-13 19:08:06 -070085 error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg);
Mark D. Roth3beb6c52016-11-29 11:25:12 -080086 gpr_free(msg);
Craig Tillera82950e2015-09-22 12:33:20 -070087 }
Yash Tibrewal8cf14702017-12-06 09:47:54 -080088 GRPC_CLOSURE_SCHED(on_peer_checked, error);
Julien Boeuf1d9ac662015-12-17 21:35:47 -080089 tsi_peer_destruct(&peer);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080090}
91
Craig Tillerbaa14a92017-11-03 09:09:36 -070092static int httpcli_ssl_cmp(grpc_security_connector* sc1,
93 grpc_security_connector* sc2) {
94 grpc_httpcli_ssl_channel_security_connector* c1 =
Noah Eisenbe82e642018-02-09 09:16:55 -080095 reinterpret_cast<grpc_httpcli_ssl_channel_security_connector*>(sc1);
Craig Tillerbaa14a92017-11-03 09:09:36 -070096 grpc_httpcli_ssl_channel_security_connector* c2 =
Noah Eisenbe82e642018-02-09 09:16:55 -080097 reinterpret_cast<grpc_httpcli_ssl_channel_security_connector*>(sc2);
Mark D. Rothccfdfb32017-10-16 13:26:13 -070098 return strcmp(c1->secure_peer_name, c2->secure_peer_name);
99}
100
Julien Boeuf7d1d9ca2015-04-17 14:38:48 -0700101static grpc_security_connector_vtable httpcli_ssl_vtable = {
Mark D. Rothccfdfb32017-10-16 13:26:13 -0700102 httpcli_ssl_destroy, httpcli_ssl_check_peer, httpcli_ssl_cmp};
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800103
Craig Tillera82950e2015-09-22 12:33:20 -0700104static grpc_security_status httpcli_ssl_channel_security_connector_create(
jiangtaoli2016144f5552018-03-23 11:28:48 -0700105 const char* pem_root_certs, const tsi_ssl_root_certs_store* root_store,
106 const char* secure_peer_name, grpc_channel_security_connector** sc) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800107 tsi_result result = TSI_OK;
Craig Tillerbaa14a92017-11-03 09:09:36 -0700108 grpc_httpcli_ssl_channel_security_connector* c;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800109
Craig Tiller4782d922017-11-10 09:53:21 -0800110 if (secure_peer_name != nullptr && pem_root_certs == nullptr) {
Craig Tillera82950e2015-09-22 12:33:20 -0700111 gpr_log(GPR_ERROR,
112 "Cannot assert a secure peer name without a trust root.");
113 return GRPC_SECURITY_ERROR;
114 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800115
Noah Eisen4d20a662018-02-09 09:34:04 -0800116 c = static_cast<grpc_httpcli_ssl_channel_security_connector*>(
117 gpr_zalloc(sizeof(grpc_httpcli_ssl_channel_security_connector)));
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800118
Craig Tillera82950e2015-09-22 12:33:20 -0700119 gpr_ref_init(&c->base.base.refcount, 1);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800120 c->base.base.vtable = &httpcli_ssl_vtable;
Craig Tiller4782d922017-11-10 09:53:21 -0800121 if (secure_peer_name != nullptr) {
Craig Tillera82950e2015-09-22 12:33:20 -0700122 c->secure_peer_name = gpr_strdup(secure_peer_name);
123 }
Ruslan Nigmatullin7ae37332018-02-21 16:44:35 -0800124 tsi_ssl_client_handshaker_options options;
125 memset(&options, 0, sizeof(options));
126 options.pem_root_certs = pem_root_certs;
jiangtaoli2016144f5552018-03-23 11:28:48 -0700127 options.root_store = root_store;
Ruslan Nigmatullin7ae37332018-02-21 16:44:35 -0800128 result = tsi_create_ssl_client_handshaker_factory_with_options(
129 &options, &c->handshaker_factory);
Craig Tillera82950e2015-09-22 12:33:20 -0700130 if (result != TSI_OK) {
131 gpr_log(GPR_ERROR, "Handshaker factory creation failed with %s.",
132 tsi_result_to_string(result));
Yash Tibrewal8cf14702017-12-06 09:47:54 -0800133 httpcli_ssl_destroy(&c->base.base);
Craig Tiller4782d922017-11-10 09:53:21 -0800134 *sc = nullptr;
Craig Tillera82950e2015-09-22 12:33:20 -0700135 return GRPC_SECURITY_ERROR;
136 }
Mark D. Rothccfdfb32017-10-16 13:26:13 -0700137 // We don't actually need a channel credentials object in this case,
Yash Tibrewal8cf14702017-12-06 09:47:54 -0800138 // but we set it to a non-nullptr address so that we don't trigger
Mark D. Rothccfdfb32017-10-16 13:26:13 -0700139 // assertions in grpc_channel_security_connector_cmp().
Craig Tillerbaa14a92017-11-03 09:09:36 -0700140 c->base.channel_creds = (grpc_channel_credentials*)1;
Mark D. Roth65b79c82016-12-06 07:20:20 -0800141 c->base.add_handshakers = httpcli_ssl_add_handshakers;
Julien Boeuf7d1d9ca2015-04-17 14:38:48 -0700142 *sc = &c->base;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800143 return GRPC_SECURITY_OK;
Craig Tiller190d3602015-02-18 09:23:38 -0800144}
Craig Tillerf53d9c82015-08-04 14:19:43 -0700145
146/* handshaker */
147
Craig Tillera82950e2015-09-22 12:33:20 -0700148typedef struct {
Yash Tibrewal8cf14702017-12-06 09:47:54 -0800149 void (*func)(void* arg, grpc_endpoint* endpoint);
Craig Tillerbaa14a92017-11-03 09:09:36 -0700150 void* arg;
151 grpc_handshake_manager* handshake_mgr;
Craig Tillerf53d9c82015-08-04 14:19:43 -0700152} on_done_closure;
153
Yash Tibrewal8cf14702017-12-06 09:47:54 -0800154static void on_handshake_done(void* arg, grpc_error* error) {
Noah Eisenbe82e642018-02-09 09:16:55 -0800155 grpc_handshaker_args* args = static_cast<grpc_handshaker_args*>(arg);
156 on_done_closure* c = static_cast<on_done_closure*>(args->user_data);
Mark D. Roth963be372016-11-16 14:17:06 -0800157 if (error != GRPC_ERROR_NONE) {
Craig Tillerbaa14a92017-11-03 09:09:36 -0700158 const char* msg = grpc_error_string(error);
Mark D. Roth963be372016-11-16 14:17:06 -0800159 gpr_log(GPR_ERROR, "Secure transport setup failed: %s", msg);
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800160
Yash Tibrewal8cf14702017-12-06 09:47:54 -0800161 c->func(c->arg, nullptr);
Craig Tillera82950e2015-09-22 12:33:20 -0700162 } else {
Yash Tibrewal8cf14702017-12-06 09:47:54 -0800163 grpc_channel_args_destroy(args->args);
164 grpc_slice_buffer_destroy_internal(args->read_buffer);
Mark D. Rothbd913a82016-12-02 16:47:35 +0000165 gpr_free(args->read_buffer);
Yash Tibrewal8cf14702017-12-06 09:47:54 -0800166 c->func(c->arg, args->endpoint);
Craig Tillera82950e2015-09-22 12:33:20 -0700167 }
Yash Tibrewal8cf14702017-12-06 09:47:54 -0800168 grpc_handshake_manager_destroy(c->handshake_mgr);
Craig Tillera82950e2015-09-22 12:33:20 -0700169 gpr_free(c);
Craig Tillerf53d9c82015-08-04 14:19:43 -0700170}
171
Yash Tibrewal8cf14702017-12-06 09:47:54 -0800172static void ssl_handshake(void* arg, grpc_endpoint* tcp, const char* host,
Craig Tillerdc3998e2017-05-12 09:55:30 -0700173 grpc_millis deadline,
Yash Tibrewal8cf14702017-12-06 09:47:54 -0800174 void (*on_done)(void* arg, grpc_endpoint* endpoint)) {
Noah Eisenbe82e642018-02-09 09:16:55 -0800175 on_done_closure* c = static_cast<on_done_closure*>(gpr_malloc(sizeof(*c)));
jiangtaoli2016144f5552018-03-23 11:28:48 -0700176 const char* pem_root_certs =
177 grpc_core::DefaultSslRootStore::GetPemRootCerts();
178 const tsi_ssl_root_certs_store* root_store =
179 grpc_core::DefaultSslRootStore::GetRootStore();
180 if (root_store == nullptr) {
Craig Tillera82950e2015-09-22 12:33:20 -0700181 gpr_log(GPR_ERROR, "Could not get default pem root certs.");
Yash Tibrewal8cf14702017-12-06 09:47:54 -0800182 on_done(arg, nullptr);
Craig Tillera82950e2015-09-22 12:33:20 -0700183 gpr_free(c);
184 return;
185 }
Craig Tillerf53d9c82015-08-04 14:19:43 -0700186 c->func = on_done;
187 c->arg = arg;
Craig Tiller4782d922017-11-10 09:53:21 -0800188 grpc_channel_security_connector* sc = nullptr;
Craig Tillera82950e2015-09-22 12:33:20 -0700189 GPR_ASSERT(httpcli_ssl_channel_security_connector_create(
jiangtaoli2016144f5552018-03-23 11:28:48 -0700190 pem_root_certs, root_store, host, &sc) == GRPC_SECURITY_OK);
Mark D. Rothbe928be2017-06-29 10:43:00 -0700191 grpc_arg channel_arg = grpc_security_connector_to_arg(&sc->base);
192 grpc_channel_args args = {1, &channel_arg};
193 c->handshake_mgr = grpc_handshake_manager_create();
Yash Tibrewal8cf14702017-12-06 09:47:54 -0800194 grpc_handshakers_add(HANDSHAKER_CLIENT, &args, c->handshake_mgr);
Mark D. Roth963be372016-11-16 14:17:06 -0800195 grpc_handshake_manager_do_handshake(
Yash Tibrewal8cf14702017-12-06 09:47:54 -0800196 c->handshake_mgr, nullptr /* interested_parties */, tcp,
Dan Born53d55032017-11-16 11:37:57 -0800197 nullptr /* channel_args */, deadline, nullptr /* acceptor */,
198 on_handshake_done, c /* user_data */);
Yash Tibrewal8cf14702017-12-06 09:47:54 -0800199 GRPC_SECURITY_CONNECTOR_UNREF(&sc->base, "httpcli");
Craig Tillerf53d9c82015-08-04 14:19:43 -0700200}
201
Craig Tillera82950e2015-09-22 12:33:20 -0700202const grpc_httpcli_handshaker grpc_httpcli_ssl = {"https", ssl_handshake};