blob: dab55f853dcb33ce12c8c231cb9b410be0938739 [file] [log] [blame]
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001/*
2 *
Craig Tiller19482442016-01-25 09:59:20 -08003 * Copyright 2015-2016, 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
34#include <grpc/grpc.h>
35
36#include <stdlib.h>
37#include <string.h>
38
Craig Tilleracf0f072015-06-29 08:24:16 -070039#include <grpc/support/alloc.h>
yang-ga6124122015-11-05 22:36:20 -080040#include <grpc/support/slice.h>
41#include <grpc/support/slice_buffer.h>
Craig Tilleracf0f072015-06-29 08:24:16 -070042
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080043#include "src/core/channel/channel_args.h"
44#include "src/core/channel/client_channel.h"
Craig Tilleracf0f072015-06-29 08:24:16 -070045#include "src/core/client_config/resolver_registry.h"
ctiller18b49ab2014-12-09 14:39:16 -080046#include "src/core/iomgr/tcp_client.h"
Julien Boeufc6f8d0a2015-05-11 22:40:02 -070047#include "src/core/security/auth_filters.h"
Julien Boeuf7d1d9ca2015-04-17 14:38:48 -070048#include "src/core/security/credentials.h"
Julien Boeuf366f42c2015-12-16 22:05:46 -080049#include "src/core/security/security_context.h"
Masood Malekghassemi76c3d742015-08-19 18:22:53 -070050#include "src/core/surface/api_trace.h"
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080051#include "src/core/surface/channel.h"
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080052#include "src/core/transport/chttp2_transport.h"
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080053#include "src/core/tsi/transport_security_interface.h"
54
Craig Tillera82950e2015-09-22 12:33:20 -070055typedef struct {
Craig Tilleracf0f072015-06-29 08:24:16 -070056 grpc_connector base;
57 gpr_refcount refs;
58
59 grpc_channel_security_connector *security_connector;
60
Craig Tiller33825112015-09-18 07:44:19 -070061 grpc_closure *notify;
Craig Tilleracf0f072015-06-29 08:24:16 -070062 grpc_connect_in_args args;
63 grpc_connect_out_args *result;
yang-ga6124122015-11-05 22:36:20 -080064 grpc_closure initial_string_sent;
65 gpr_slice_buffer initial_string_buffer;
Craig Tiller131f6ed2015-09-15 08:20:20 -070066
67 gpr_mu mu;
68 grpc_endpoint *connecting_endpoint;
Craig Tillerd1bec032015-09-18 17:29:00 -070069 grpc_endpoint *newly_connecting_endpoint;
70
71 grpc_closure connected_closure;
Craig Tilleracf0f072015-06-29 08:24:16 -070072} connector;
73
Craig Tillera82950e2015-09-22 12:33:20 -070074static void connector_ref(grpc_connector *con) {
75 connector *c = (connector *)con;
76 gpr_ref(&c->refs);
Craig Tilleracf0f072015-06-29 08:24:16 -070077}
78
Craig Tillera82950e2015-09-22 12:33:20 -070079static void connector_unref(grpc_exec_ctx *exec_ctx, grpc_connector *con) {
80 connector *c = (connector *)con;
81 if (gpr_unref(&c->refs)) {
yang-ga6124122015-11-05 22:36:20 -080082 /* c->initial_string_buffer does not need to be destroyed */
Craig Tillera82950e2015-09-22 12:33:20 -070083 gpr_free(c);
84 }
Craig Tilleracf0f072015-06-29 08:24:16 -070085}
86
Craig Tillera82950e2015-09-22 12:33:20 -070087static void on_secure_handshake_done(grpc_exec_ctx *exec_ctx, void *arg,
88 grpc_security_status status,
Julien Boeuf366f42c2015-12-16 22:05:46 -080089 grpc_endpoint *secure_endpoint,
90 grpc_auth_context *auth_context) {
Craig Tilleracf0f072015-06-29 08:24:16 -070091 connector *c = arg;
Craig Tiller33825112015-09-18 07:44:19 -070092 grpc_closure *notify;
Julien Boeuf5b194032015-12-17 16:00:51 -080093 grpc_channel_args *args_copy = NULL;
Craig Tillera82950e2015-09-22 12:33:20 -070094 gpr_mu_lock(&c->mu);
95 if (c->connecting_endpoint == NULL) {
96 memset(c->result, 0, sizeof(*c->result));
97 gpr_mu_unlock(&c->mu);
98 } else if (status != GRPC_SECURITY_OK) {
Craig Tillera82950e2015-09-22 12:33:20 -070099 gpr_log(GPR_ERROR, "Secure handshake failed with error %d.", status);
100 memset(c->result, 0, sizeof(*c->result));
101 c->connecting_endpoint = NULL;
102 gpr_mu_unlock(&c->mu);
103 } else {
Julien Boeuf5b194032015-12-17 16:00:51 -0800104 grpc_arg auth_context_arg;
Craig Tillera82950e2015-09-22 12:33:20 -0700105 c->connecting_endpoint = NULL;
106 gpr_mu_unlock(&c->mu);
Julien Boeuf5b194032015-12-17 16:00:51 -0800107 c->result->transport = grpc_create_chttp2_transport(
108 exec_ctx, c->args.channel_args, secure_endpoint, 1);
Craig Tillera82950e2015-09-22 12:33:20 -0700109 grpc_chttp2_transport_start_reading(exec_ctx, c->result->transport, NULL,
110 0);
Julien Boeuf5b194032015-12-17 16:00:51 -0800111 auth_context_arg = grpc_auth_context_to_arg(auth_context);
112 args_copy = grpc_channel_args_copy_and_add(c->args.channel_args,
113 &auth_context_arg, 1);
114 c->result->channel_args = args_copy;
Craig Tillera82950e2015-09-22 12:33:20 -0700115 }
Craig Tillerd9a50882015-06-29 15:57:36 -0700116 notify = c->notify;
117 c->notify = NULL;
Julien Boeuf5b194032015-12-17 16:00:51 -0800118 /* look at c->args which are connector args. */
Craig Tillera82950e2015-09-22 12:33:20 -0700119 notify->cb(exec_ctx, notify->cb_arg, 1);
Julien Boeuf5b194032015-12-17 16:00:51 -0800120 if (args_copy != NULL) grpc_channel_args_destroy(args_copy);
Craig Tilleracf0f072015-06-29 08:24:16 -0700121}
122
yang-ga6124122015-11-05 22:36:20 -0800123static void on_initial_connect_string_sent(grpc_exec_ctx *exec_ctx, void *arg,
Craig Tiller6c396862016-01-28 13:53:40 -0800124 bool success) {
yang-ga6124122015-11-05 22:36:20 -0800125 connector *c = arg;
126 grpc_security_connector_do_handshake(exec_ctx, &c->security_connector->base,
127 c->connecting_endpoint,
128 on_secure_handshake_done, c);
129}
130
Craig Tiller6c396862016-01-28 13:53:40 -0800131static void connected(grpc_exec_ctx *exec_ctx, void *arg, bool success) {
Craig Tilleracf0f072015-06-29 08:24:16 -0700132 connector *c = arg;
Craig Tiller33825112015-09-18 07:44:19 -0700133 grpc_closure *notify;
Craig Tillerd1bec032015-09-18 17:29:00 -0700134 grpc_endpoint *tcp = c->newly_connecting_endpoint;
Craig Tillera82950e2015-09-22 12:33:20 -0700135 if (tcp != NULL) {
136 gpr_mu_lock(&c->mu);
137 GPR_ASSERT(c->connecting_endpoint == NULL);
138 c->connecting_endpoint = tcp;
139 gpr_mu_unlock(&c->mu);
yang-ga6124122015-11-05 22:36:20 -0800140 if (!GPR_SLICE_IS_EMPTY(c->args.initial_connect_string)) {
141 grpc_closure_init(&c->initial_string_sent, on_initial_connect_string_sent,
142 c);
143 gpr_slice_buffer_init(&c->initial_string_buffer);
144 gpr_slice_buffer_add(&c->initial_string_buffer,
145 c->args.initial_connect_string);
146 grpc_endpoint_write(exec_ctx, tcp, &c->initial_string_buffer,
147 &c->initial_string_sent);
148 } else {
149 grpc_security_connector_do_handshake(exec_ctx,
150 &c->security_connector->base, tcp,
151 on_secure_handshake_done, c);
152 }
Craig Tillera82950e2015-09-22 12:33:20 -0700153 } else {
154 memset(c->result, 0, sizeof(*c->result));
155 notify = c->notify;
156 c->notify = NULL;
157 notify->cb(exec_ctx, notify->cb_arg, 1);
158 }
Craig Tilleracf0f072015-06-29 08:24:16 -0700159}
160
Craig Tillera82950e2015-09-22 12:33:20 -0700161static void connector_shutdown(grpc_exec_ctx *exec_ctx, grpc_connector *con) {
162 connector *c = (connector *)con;
Craig Tiller131f6ed2015-09-15 08:20:20 -0700163 grpc_endpoint *ep;
Craig Tillera82950e2015-09-22 12:33:20 -0700164 gpr_mu_lock(&c->mu);
Craig Tiller131f6ed2015-09-15 08:20:20 -0700165 ep = c->connecting_endpoint;
166 c->connecting_endpoint = NULL;
Craig Tillera82950e2015-09-22 12:33:20 -0700167 gpr_mu_unlock(&c->mu);
168 if (ep) {
169 grpc_endpoint_shutdown(exec_ctx, ep);
170 }
Craig Tiller131f6ed2015-09-15 08:20:20 -0700171}
172
Craig Tillera82950e2015-09-22 12:33:20 -0700173static void connector_connect(grpc_exec_ctx *exec_ctx, grpc_connector *con,
174 const grpc_connect_in_args *args,
175 grpc_connect_out_args *result,
176 grpc_closure *notify) {
177 connector *c = (connector *)con;
178 GPR_ASSERT(c->notify == NULL);
179 GPR_ASSERT(notify->cb);
Craig Tilleracf0f072015-06-29 08:24:16 -0700180 c->notify = notify;
181 c->args = *args;
182 c->result = result;
Craig Tillera82950e2015-09-22 12:33:20 -0700183 gpr_mu_lock(&c->mu);
184 GPR_ASSERT(c->connecting_endpoint == NULL);
185 gpr_mu_unlock(&c->mu);
186 grpc_closure_init(&c->connected_closure, connected, c);
187 grpc_tcp_client_connect(
188 exec_ctx, &c->connected_closure, &c->newly_connecting_endpoint,
189 args->interested_parties, args->addr, args->addr_len, args->deadline);
Craig Tilleracf0f072015-06-29 08:24:16 -0700190}
191
Craig Tiller079a11b2015-06-30 10:07:15 -0700192static const grpc_connector_vtable connector_vtable = {
Craig Tillera82950e2015-09-22 12:33:20 -0700193 connector_ref, connector_unref, connector_shutdown, connector_connect};
Craig Tilleracf0f072015-06-29 08:24:16 -0700194
Craig Tillera82950e2015-09-22 12:33:20 -0700195typedef struct {
Craig Tilleracf0f072015-06-29 08:24:16 -0700196 grpc_subchannel_factory base;
197 gpr_refcount refs;
Craig Tillerd9a50882015-06-29 15:57:36 -0700198 grpc_channel_args *merge_args;
Craig Tilleracf0f072015-06-29 08:24:16 -0700199 grpc_channel_security_connector *security_connector;
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700200 grpc_channel *master;
Craig Tilleracf0f072015-06-29 08:24:16 -0700201} subchannel_factory;
202
Craig Tillera82950e2015-09-22 12:33:20 -0700203static void subchannel_factory_ref(grpc_subchannel_factory *scf) {
204 subchannel_factory *f = (subchannel_factory *)scf;
205 gpr_ref(&f->refs);
Craig Tilleracf0f072015-06-29 08:24:16 -0700206}
207
Craig Tillera82950e2015-09-22 12:33:20 -0700208static void subchannel_factory_unref(grpc_exec_ctx *exec_ctx,
209 grpc_subchannel_factory *scf) {
210 subchannel_factory *f = (subchannel_factory *)scf;
211 if (gpr_unref(&f->refs)) {
212 GRPC_SECURITY_CONNECTOR_UNREF(&f->security_connector->base,
213 "subchannel_factory");
214 GRPC_CHANNEL_INTERNAL_UNREF(exec_ctx, f->master, "subchannel_factory");
215 grpc_channel_args_destroy(f->merge_args);
Craig Tillera82950e2015-09-22 12:33:20 -0700216 gpr_free(f);
217 }
Craig Tilleracf0f072015-06-29 08:24:16 -0700218}
219
Craig Tillera82950e2015-09-22 12:33:20 -0700220static grpc_subchannel *subchannel_factory_create_subchannel(
221 grpc_exec_ctx *exec_ctx, grpc_subchannel_factory *scf,
222 grpc_subchannel_args *args) {
223 subchannel_factory *f = (subchannel_factory *)scf;
224 connector *c = gpr_malloc(sizeof(*c));
225 grpc_channel_args *final_args =
226 grpc_channel_args_merge(args->args, f->merge_args);
Craig Tilleracf0f072015-06-29 08:24:16 -0700227 grpc_subchannel *s;
Craig Tillera82950e2015-09-22 12:33:20 -0700228 memset(c, 0, sizeof(*c));
Craig Tilleracf0f072015-06-29 08:24:16 -0700229 c->base.vtable = &connector_vtable;
230 c->security_connector = f->security_connector;
Craig Tiller58473e82015-09-22 14:37:11 -0700231 gpr_mu_init(&c->mu);
Craig Tillera82950e2015-09-22 12:33:20 -0700232 gpr_ref_init(&c->refs, 1);
Craig Tillerd9a50882015-06-29 15:57:36 -0700233 args->args = final_args;
Craig Tiller7391f132016-01-22 06:39:54 -0800234 s = grpc_subchannel_create(exec_ctx, &c->base, args);
Craig Tillera82950e2015-09-22 12:33:20 -0700235 grpc_connector_unref(exec_ctx, &c->base);
236 grpc_channel_args_destroy(final_args);
Craig Tilleracf0f072015-06-29 08:24:16 -0700237 return s;
238}
239
Craig Tiller079a11b2015-06-30 10:07:15 -0700240static const grpc_subchannel_factory_vtable subchannel_factory_vtable = {
Craig Tillera82950e2015-09-22 12:33:20 -0700241 subchannel_factory_ref, subchannel_factory_unref,
242 subchannel_factory_create_subchannel};
Craig Tilleracf0f072015-06-29 08:24:16 -0700243
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800244/* Create a secure client channel:
245 Asynchronously: - resolve target
246 - connect to it (trying alternatives as presented)
247 - perform handshakes */
Julien Boeuf441176d2015-10-09 21:14:07 -0700248grpc_channel *grpc_secure_channel_create(grpc_channel_credentials *creds,
Craig Tillera82950e2015-09-22 12:33:20 -0700249 const char *target,
250 const grpc_channel_args *args,
251 void *reserved) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800252 grpc_channel *channel;
Julien Boeuf7d1d9ca2015-04-17 14:38:48 -0700253 grpc_arg connector_arg;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800254 grpc_channel_args *args_copy;
Julien Boeuf7d1d9ca2015-04-17 14:38:48 -0700255 grpc_channel_args *new_args_from_connector;
Craig Tillerb9d35962015-09-11 13:31:16 -0700256 grpc_channel_security_connector *security_connector;
Craig Tilleracf0f072015-06-29 08:24:16 -0700257 grpc_resolver *resolver;
258 subchannel_factory *f;
Craig Tillerf5768a62015-09-22 10:54:34 -0700259 grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
Julien Boeuf7d1d9ca2015-04-17 14:38:48 -0700260
Craig Tiller4de3e4f2015-10-05 08:55:50 -0700261 GRPC_API_TRACE(
262 "grpc_secure_channel_create(creds=%p, target=%s, args=%p, "
263 "reserved=%p)",
264 4, (creds, target, args, reserved));
Craig Tillera82950e2015-09-22 12:33:20 -0700265 GPR_ASSERT(reserved == NULL);
Masood Malekghassemi76c3d742015-08-19 18:22:53 -0700266
Craig Tillera82950e2015-09-22 12:33:20 -0700267 if (grpc_find_security_connector_in_args(args) != NULL) {
268 gpr_log(GPR_ERROR, "Cannot set security context in channel args.");
Craig Tiller63010382015-09-24 15:00:58 -0700269 grpc_exec_ctx_finish(&exec_ctx);
Craig Tillera82950e2015-09-22 12:33:20 -0700270 return grpc_lame_client_channel_create(
271 target, GRPC_STATUS_INVALID_ARGUMENT,
272 "Security connector exists in channel args.");
273 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800274
Julien Boeuf441176d2015-10-09 21:14:07 -0700275 if (grpc_channel_credentials_create_security_connector(
276 creds, target, args, &security_connector, &new_args_from_connector) !=
277 GRPC_SECURITY_OK) {
Craig Tiller63010382015-09-24 15:00:58 -0700278 grpc_exec_ctx_finish(&exec_ctx);
Craig Tillera82950e2015-09-22 12:33:20 -0700279 return grpc_lame_client_channel_create(
280 target, GRPC_STATUS_INVALID_ARGUMENT,
281 "Failed to create security connector.");
282 }
Julien Boeuf7d1d9ca2015-04-17 14:38:48 -0700283
Craig Tillerb9d35962015-09-11 13:31:16 -0700284 connector_arg = grpc_security_connector_to_arg(&security_connector->base);
Craig Tillera82950e2015-09-22 12:33:20 -0700285 args_copy = grpc_channel_args_copy_and_add(
286 new_args_from_connector != NULL ? new_args_from_connector : args,
287 &connector_arg, 1);
Craig Tilleracf0f072015-06-29 08:24:16 -0700288
Craig Tiller178edfa2016-02-17 20:54:46 -0800289 channel = grpc_channel_create(&exec_ctx, target, args_copy,
290 GRPC_CLIENT_CHANNEL, NULL);
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700291
Craig Tillera82950e2015-09-22 12:33:20 -0700292 f = gpr_malloc(sizeof(*f));
Craig Tilleracf0f072015-06-29 08:24:16 -0700293 f->base.vtable = &subchannel_factory_vtable;
Craig Tillera82950e2015-09-22 12:33:20 -0700294 gpr_ref_init(&f->refs, 1);
Craig Tillerb9d35962015-09-11 13:31:16 -0700295 GRPC_SECURITY_CONNECTOR_REF(&security_connector->base, "subchannel_factory");
296 f->security_connector = security_connector;
Craig Tillera82950e2015-09-22 12:33:20 -0700297 f->merge_args = grpc_channel_args_copy(args_copy);
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700298 f->master = channel;
Craig Tillera82950e2015-09-22 12:33:20 -0700299 GRPC_CHANNEL_INTERNAL_REF(channel, "subchannel_factory");
300 resolver = grpc_resolver_create(target, &f->base);
yang-gd47a44d2015-12-10 15:44:25 -0800301 if (resolver) {
302 grpc_client_channel_set_resolver(
303 &exec_ctx, grpc_channel_get_channel_stack(channel), resolver);
304 GRPC_RESOLVER_UNREF(&exec_ctx, resolver, "create");
Craig Tillera82950e2015-09-22 12:33:20 -0700305 }
Craig Tillera82950e2015-09-22 12:33:20 -0700306 grpc_subchannel_factory_unref(&exec_ctx, &f->base);
Craig Tillerb9d35962015-09-11 13:31:16 -0700307 GRPC_SECURITY_CONNECTOR_UNREF(&security_connector->base, "channel_create");
Craig Tillera82950e2015-09-22 12:33:20 -0700308 grpc_channel_args_destroy(args_copy);
309 if (new_args_from_connector != NULL) {
310 grpc_channel_args_destroy(new_args_from_connector);
311 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800312
yang-gd47a44d2015-12-10 15:44:25 -0800313 if (!resolver) {
314 GRPC_CHANNEL_INTERNAL_UNREF(&exec_ctx, channel, "subchannel_factory");
315 channel = NULL;
316 }
Craig Tillera82950e2015-09-22 12:33:20 -0700317 grpc_exec_ctx_finish(&exec_ctx);
Craig Tillerd1bec032015-09-18 17:29:00 -0700318
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800319 return channel;
Craig Tiller190d3602015-02-18 09:23:38 -0800320}