blob: b6f3504dc24605e3079b5ff28c4e5c029ef81e2f [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
Craig Tiller9533d042016-03-25 17:11:06 -070043#include "src/core/lib/channel/channel_args.h"
44#include "src/core/lib/channel/client_channel.h"
45#include "src/core/lib/client_config/resolver_registry.h"
46#include "src/core/lib/iomgr/tcp_client.h"
47#include "src/core/lib/security/auth_filters.h"
48#include "src/core/lib/security/credentials.h"
49#include "src/core/lib/security/security_context.h"
50#include "src/core/lib/surface/api_trace.h"
51#include "src/core/lib/surface/channel.h"
52#include "src/core/lib/transport/chttp2_transport.h"
53#include "src/core/lib/tsi/transport_security_interface.h"
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080054
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;
Julien Boeuf4f4d37c2016-02-24 22:07:36 -0800126 grpc_channel_security_connector_do_handshake(exec_ctx, c->security_connector,
127 c->connecting_endpoint,
128 on_secure_handshake_done, c);
yang-ga6124122015-11-05 22:36:20 -0800129}
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 {
Julien Boeuf4f4d37c2016-02-24 22:07:36 -0800149 grpc_channel_security_connector_do_handshake(
150 exec_ctx, c->security_connector, tcp, on_secure_handshake_done, c);
yang-ga6124122015-11-05 22:36:20 -0800151 }
Craig Tillera82950e2015-09-22 12:33:20 -0700152 } else {
153 memset(c->result, 0, sizeof(*c->result));
154 notify = c->notify;
155 c->notify = NULL;
156 notify->cb(exec_ctx, notify->cb_arg, 1);
157 }
Craig Tilleracf0f072015-06-29 08:24:16 -0700158}
159
Craig Tillera82950e2015-09-22 12:33:20 -0700160static void connector_shutdown(grpc_exec_ctx *exec_ctx, grpc_connector *con) {
161 connector *c = (connector *)con;
Craig Tiller131f6ed2015-09-15 08:20:20 -0700162 grpc_endpoint *ep;
Craig Tillera82950e2015-09-22 12:33:20 -0700163 gpr_mu_lock(&c->mu);
Craig Tiller131f6ed2015-09-15 08:20:20 -0700164 ep = c->connecting_endpoint;
165 c->connecting_endpoint = NULL;
Craig Tillera82950e2015-09-22 12:33:20 -0700166 gpr_mu_unlock(&c->mu);
167 if (ep) {
168 grpc_endpoint_shutdown(exec_ctx, ep);
169 }
Craig Tiller131f6ed2015-09-15 08:20:20 -0700170}
171
Craig Tillera82950e2015-09-22 12:33:20 -0700172static void connector_connect(grpc_exec_ctx *exec_ctx, grpc_connector *con,
173 const grpc_connect_in_args *args,
174 grpc_connect_out_args *result,
175 grpc_closure *notify) {
176 connector *c = (connector *)con;
177 GPR_ASSERT(c->notify == NULL);
178 GPR_ASSERT(notify->cb);
Craig Tilleracf0f072015-06-29 08:24:16 -0700179 c->notify = notify;
180 c->args = *args;
181 c->result = result;
Craig Tillera82950e2015-09-22 12:33:20 -0700182 gpr_mu_lock(&c->mu);
183 GPR_ASSERT(c->connecting_endpoint == NULL);
184 gpr_mu_unlock(&c->mu);
185 grpc_closure_init(&c->connected_closure, connected, c);
186 grpc_tcp_client_connect(
187 exec_ctx, &c->connected_closure, &c->newly_connecting_endpoint,
188 args->interested_parties, args->addr, args->addr_len, args->deadline);
Craig Tilleracf0f072015-06-29 08:24:16 -0700189}
190
Craig Tiller079a11b2015-06-30 10:07:15 -0700191static const grpc_connector_vtable connector_vtable = {
Craig Tillera82950e2015-09-22 12:33:20 -0700192 connector_ref, connector_unref, connector_shutdown, connector_connect};
Craig Tilleracf0f072015-06-29 08:24:16 -0700193
Craig Tillera82950e2015-09-22 12:33:20 -0700194typedef struct {
Craig Tilleracf0f072015-06-29 08:24:16 -0700195 grpc_subchannel_factory base;
196 gpr_refcount refs;
Craig Tillerd9a50882015-06-29 15:57:36 -0700197 grpc_channel_args *merge_args;
Craig Tilleracf0f072015-06-29 08:24:16 -0700198 grpc_channel_security_connector *security_connector;
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700199 grpc_channel *master;
Craig Tilleracf0f072015-06-29 08:24:16 -0700200} subchannel_factory;
201
Craig Tillera82950e2015-09-22 12:33:20 -0700202static void subchannel_factory_ref(grpc_subchannel_factory *scf) {
203 subchannel_factory *f = (subchannel_factory *)scf;
204 gpr_ref(&f->refs);
Craig Tilleracf0f072015-06-29 08:24:16 -0700205}
206
Craig Tillera82950e2015-09-22 12:33:20 -0700207static void subchannel_factory_unref(grpc_exec_ctx *exec_ctx,
208 grpc_subchannel_factory *scf) {
209 subchannel_factory *f = (subchannel_factory *)scf;
210 if (gpr_unref(&f->refs)) {
211 GRPC_SECURITY_CONNECTOR_UNREF(&f->security_connector->base,
212 "subchannel_factory");
213 GRPC_CHANNEL_INTERNAL_UNREF(exec_ctx, f->master, "subchannel_factory");
214 grpc_channel_args_destroy(f->merge_args);
Craig Tillera82950e2015-09-22 12:33:20 -0700215 gpr_free(f);
216 }
Craig Tilleracf0f072015-06-29 08:24:16 -0700217}
218
Craig Tillera82950e2015-09-22 12:33:20 -0700219static grpc_subchannel *subchannel_factory_create_subchannel(
220 grpc_exec_ctx *exec_ctx, grpc_subchannel_factory *scf,
221 grpc_subchannel_args *args) {
222 subchannel_factory *f = (subchannel_factory *)scf;
223 connector *c = gpr_malloc(sizeof(*c));
224 grpc_channel_args *final_args =
225 grpc_channel_args_merge(args->args, f->merge_args);
Craig Tilleracf0f072015-06-29 08:24:16 -0700226 grpc_subchannel *s;
Craig Tillera82950e2015-09-22 12:33:20 -0700227 memset(c, 0, sizeof(*c));
Craig Tilleracf0f072015-06-29 08:24:16 -0700228 c->base.vtable = &connector_vtable;
229 c->security_connector = f->security_connector;
Craig Tiller58473e82015-09-22 14:37:11 -0700230 gpr_mu_init(&c->mu);
Craig Tillera82950e2015-09-22 12:33:20 -0700231 gpr_ref_init(&c->refs, 1);
Craig Tillerd9a50882015-06-29 15:57:36 -0700232 args->args = final_args;
Craig Tiller7391f132016-01-22 06:39:54 -0800233 s = grpc_subchannel_create(exec_ctx, &c->base, args);
Craig Tillera82950e2015-09-22 12:33:20 -0700234 grpc_connector_unref(exec_ctx, &c->base);
235 grpc_channel_args_destroy(final_args);
Craig Tilleracf0f072015-06-29 08:24:16 -0700236 return s;
237}
238
Craig Tiller079a11b2015-06-30 10:07:15 -0700239static const grpc_subchannel_factory_vtable subchannel_factory_vtable = {
Craig Tillera82950e2015-09-22 12:33:20 -0700240 subchannel_factory_ref, subchannel_factory_unref,
241 subchannel_factory_create_subchannel};
Craig Tilleracf0f072015-06-29 08:24:16 -0700242
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800243/* Create a secure client channel:
244 Asynchronously: - resolve target
245 - connect to it (trying alternatives as presented)
246 - perform handshakes */
Julien Boeuf441176d2015-10-09 21:14:07 -0700247grpc_channel *grpc_secure_channel_create(grpc_channel_credentials *creds,
Craig Tillera82950e2015-09-22 12:33:20 -0700248 const char *target,
249 const grpc_channel_args *args,
250 void *reserved) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800251 grpc_channel *channel;
Julien Boeuf7d1d9ca2015-04-17 14:38:48 -0700252 grpc_arg connector_arg;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800253 grpc_channel_args *args_copy;
Julien Boeuf7d1d9ca2015-04-17 14:38:48 -0700254 grpc_channel_args *new_args_from_connector;
Craig Tillerb9d35962015-09-11 13:31:16 -0700255 grpc_channel_security_connector *security_connector;
Craig Tilleracf0f072015-06-29 08:24:16 -0700256 grpc_resolver *resolver;
257 subchannel_factory *f;
Craig Tillerf5768a62015-09-22 10:54:34 -0700258 grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
Julien Boeuf7d1d9ca2015-04-17 14:38:48 -0700259
Craig Tiller4de3e4f2015-10-05 08:55:50 -0700260 GRPC_API_TRACE(
261 "grpc_secure_channel_create(creds=%p, target=%s, args=%p, "
262 "reserved=%p)",
263 4, (creds, target, args, reserved));
Craig Tillera82950e2015-09-22 12:33:20 -0700264 GPR_ASSERT(reserved == NULL);
Masood Malekghassemi76c3d742015-08-19 18:22:53 -0700265
Craig Tillera82950e2015-09-22 12:33:20 -0700266 if (grpc_find_security_connector_in_args(args) != NULL) {
267 gpr_log(GPR_ERROR, "Cannot set security context in channel args.");
Craig Tiller63010382015-09-24 15:00:58 -0700268 grpc_exec_ctx_finish(&exec_ctx);
Craig Tillera82950e2015-09-22 12:33:20 -0700269 return grpc_lame_client_channel_create(
Craig Tillerc82048f2016-03-23 14:41:51 -0700270 target, GRPC_STATUS_INTERNAL,
Craig Tillera82950e2015-09-22 12:33:20 -0700271 "Security connector exists in channel args.");
272 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800273
Julien Boeuf441176d2015-10-09 21:14:07 -0700274 if (grpc_channel_credentials_create_security_connector(
275 creds, target, args, &security_connector, &new_args_from_connector) !=
276 GRPC_SECURITY_OK) {
Craig Tiller63010382015-09-24 15:00:58 -0700277 grpc_exec_ctx_finish(&exec_ctx);
Craig Tillera82950e2015-09-22 12:33:20 -0700278 return grpc_lame_client_channel_create(
Craig Tillerc82048f2016-03-23 14:41:51 -0700279 target, GRPC_STATUS_INTERNAL, "Failed to create security connector.");
Craig Tillera82950e2015-09-22 12:33:20 -0700280 }
Julien Boeuf7d1d9ca2015-04-17 14:38:48 -0700281
Craig Tillerb9d35962015-09-11 13:31:16 -0700282 connector_arg = grpc_security_connector_to_arg(&security_connector->base);
Craig Tillera82950e2015-09-22 12:33:20 -0700283 args_copy = grpc_channel_args_copy_and_add(
284 new_args_from_connector != NULL ? new_args_from_connector : args,
285 &connector_arg, 1);
Craig Tilleracf0f072015-06-29 08:24:16 -0700286
Craig Tiller178edfa2016-02-17 20:54:46 -0800287 channel = grpc_channel_create(&exec_ctx, target, args_copy,
288 GRPC_CLIENT_CHANNEL, NULL);
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700289
Craig Tillera82950e2015-09-22 12:33:20 -0700290 f = gpr_malloc(sizeof(*f));
Craig Tilleracf0f072015-06-29 08:24:16 -0700291 f->base.vtable = &subchannel_factory_vtable;
Craig Tillera82950e2015-09-22 12:33:20 -0700292 gpr_ref_init(&f->refs, 1);
Craig Tillerb9d35962015-09-11 13:31:16 -0700293 GRPC_SECURITY_CONNECTOR_REF(&security_connector->base, "subchannel_factory");
294 f->security_connector = security_connector;
Craig Tillera82950e2015-09-22 12:33:20 -0700295 f->merge_args = grpc_channel_args_copy(args_copy);
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700296 f->master = channel;
Craig Tillera82950e2015-09-22 12:33:20 -0700297 GRPC_CHANNEL_INTERNAL_REF(channel, "subchannel_factory");
298 resolver = grpc_resolver_create(target, &f->base);
yang-gd47a44d2015-12-10 15:44:25 -0800299 if (resolver) {
300 grpc_client_channel_set_resolver(
301 &exec_ctx, grpc_channel_get_channel_stack(channel), resolver);
302 GRPC_RESOLVER_UNREF(&exec_ctx, resolver, "create");
Craig Tillera82950e2015-09-22 12:33:20 -0700303 }
Craig Tillera82950e2015-09-22 12:33:20 -0700304 grpc_subchannel_factory_unref(&exec_ctx, &f->base);
Craig Tillerb9d35962015-09-11 13:31:16 -0700305 GRPC_SECURITY_CONNECTOR_UNREF(&security_connector->base, "channel_create");
Craig Tillera82950e2015-09-22 12:33:20 -0700306 grpc_channel_args_destroy(args_copy);
307 if (new_args_from_connector != NULL) {
308 grpc_channel_args_destroy(new_args_from_connector);
309 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800310
yang-gd47a44d2015-12-10 15:44:25 -0800311 if (!resolver) {
312 GRPC_CHANNEL_INTERNAL_UNREF(&exec_ctx, channel, "subchannel_factory");
313 channel = NULL;
314 }
Craig Tillera82950e2015-09-22 12:33:20 -0700315 grpc_exec_ctx_finish(&exec_ctx);
Craig Tillerd1bec032015-09-18 17:29:00 -0700316
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800317 return channel;
Craig Tiller190d3602015-02-18 09:23:38 -0800318}