blob: 80834f4e885be4fb2926c521fedf4b1e386c0e55 [file] [log] [blame]
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001/*
2 *
Dan Born725ee282016-01-13 13:14:56 -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
Craig Tiller759026c2015-02-22 23:09:45 -080036#include <string.h>
37
Craig Tillerf40df232016-03-25 13:38:14 -070038#include <grpc/support/alloc.h>
39#include <grpc/support/log.h>
40#include <grpc/support/sync.h>
41#include <grpc/support/useful.h>
Craig Tilleradcb92d2016-03-28 10:14:05 -070042#include "src/core/ext/transport/chttp2/transport/chttp2_transport.h"
Craig Tiller9533d042016-03-25 17:11:06 -070043#include "src/core/lib/channel/channel_args.h"
44#include "src/core/lib/channel/http_server_filter.h"
45#include "src/core/lib/iomgr/endpoint.h"
46#include "src/core/lib/iomgr/resolve_address.h"
47#include "src/core/lib/iomgr/tcp_server.h"
48#include "src/core/lib/security/auth_filters.h"
49#include "src/core/lib/security/credentials.h"
50#include "src/core/lib/security/security_connector.h"
51#include "src/core/lib/security/security_context.h"
52#include "src/core/lib/surface/api_trace.h"
53#include "src/core/lib/surface/server.h"
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080054
Craig Tillera82950e2015-09-22 12:33:20 -070055typedef struct grpc_server_secure_state {
David Klempnerfd5d8ff2015-03-05 14:17:38 -080056 grpc_server *server;
57 grpc_tcp_server *tcp;
Julien Boeuf4f4d37c2016-02-24 22:07:36 -080058 grpc_server_security_connector *sc;
Julien Boeuffe1478f2015-08-30 21:57:38 -070059 grpc_server_credentials *creds;
David Klempnerfd5d8ff2015-03-05 14:17:38 -080060 int is_shutdown;
61 gpr_mu mu;
62 gpr_refcount refcount;
Craig Tillerd1bec032015-09-18 17:29:00 -070063 grpc_closure destroy_closure;
Craig Tillerdfff1b82015-09-21 14:39:57 -070064 grpc_closure *destroy_callback;
David Klempnerfd5d8ff2015-03-05 14:17:38 -080065} grpc_server_secure_state;
66
Craig Tillera82950e2015-09-22 12:33:20 -070067static void state_ref(grpc_server_secure_state *state) {
68 gpr_ref(&state->refcount);
David Klempnerfd5d8ff2015-03-05 14:17:38 -080069}
70
Craig Tillera82950e2015-09-22 12:33:20 -070071static void state_unref(grpc_server_secure_state *state) {
72 if (gpr_unref(&state->refcount)) {
73 /* ensure all threads have unlocked */
74 gpr_mu_lock(&state->mu);
75 gpr_mu_unlock(&state->mu);
76 /* clean up */
Julien Boeuf4f4d37c2016-02-24 22:07:36 -080077 GRPC_SECURITY_CONNECTOR_UNREF(&state->sc->base, "server");
Craig Tillera82950e2015-09-22 12:33:20 -070078 grpc_server_credentials_unref(state->creds);
79 gpr_free(state);
80 }
David Klempnerfd5d8ff2015-03-05 14:17:38 -080081}
82
Craig Tillera82950e2015-09-22 12:33:20 -070083static void setup_transport(grpc_exec_ctx *exec_ctx, void *statep,
Julien Boeuf366f42c2015-12-16 22:05:46 -080084 grpc_transport *transport,
85 grpc_auth_context *auth_context) {
Julien Boeufc6f8d0a2015-05-11 22:40:02 -070086 grpc_server_secure_state *state = statep;
Julien Boeuf66a27da2015-07-21 17:17:35 -070087 grpc_channel_args *args_copy;
88 grpc_arg args_to_add[2];
Julien Boeuf9a529082015-10-08 13:12:14 -070089 args_to_add[0] = grpc_server_credentials_to_arg(state->creds);
Julien Boeuf366f42c2015-12-16 22:05:46 -080090 args_to_add[1] = grpc_auth_context_to_arg(auth_context);
Craig Tillera82950e2015-09-22 12:33:20 -070091 args_copy = grpc_channel_args_copy_and_add(
92 grpc_server_get_channel_args(state->server), args_to_add,
93 GPR_ARRAY_SIZE(args_to_add));
Craig Tiller178edfa2016-02-17 20:54:46 -080094 grpc_server_setup_transport(exec_ctx, state->server, transport, args_copy);
Craig Tillera82950e2015-09-22 12:33:20 -070095 grpc_channel_args_destroy(args_copy);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080096}
97
Craig Tillera82950e2015-09-22 12:33:20 -070098static void on_secure_handshake_done(grpc_exec_ctx *exec_ctx, void *statep,
99 grpc_security_status status,
Julien Boeuf366f42c2015-12-16 22:05:46 -0800100 grpc_endpoint *secure_endpoint,
101 grpc_auth_context *auth_context) {
David Klempnerfd5d8ff2015-03-05 14:17:38 -0800102 grpc_server_secure_state *state = statep;
Craig Tilleracf0f072015-06-29 08:24:16 -0700103 grpc_transport *transport;
Craig Tillera82950e2015-09-22 12:33:20 -0700104 if (status == GRPC_SECURITY_OK) {
yang-g5e7f08a2015-11-19 01:27:43 -0800105 if (secure_endpoint) {
106 gpr_mu_lock(&state->mu);
107 if (!state->is_shutdown) {
yang-g5e7f08a2015-11-19 01:27:43 -0800108 transport = grpc_create_chttp2_transport(
109 exec_ctx, grpc_server_get_channel_args(state->server),
yang-gd88e1d82015-12-02 13:23:33 -0800110 secure_endpoint, 0);
Julien Boeuf366f42c2015-12-16 22:05:46 -0800111 setup_transport(exec_ctx, state, transport, auth_context);
yang-g5e7f08a2015-11-19 01:27:43 -0800112 grpc_chttp2_transport_start_reading(exec_ctx, transport, NULL, 0);
113 } else {
114 /* We need to consume this here, because the server may already have
yang-g768999d2015-11-20 10:08:26 -0800115 * gone away. */
yang-g5e7f08a2015-11-19 01:27:43 -0800116 grpc_endpoint_destroy(exec_ctx, secure_endpoint);
117 }
118 gpr_mu_unlock(&state->mu);
David Klempnerfd5d8ff2015-03-05 14:17:38 -0800119 }
Craig Tillera82950e2015-09-22 12:33:20 -0700120 } else {
Craig Tillera82950e2015-09-22 12:33:20 -0700121 gpr_log(GPR_ERROR, "Secure transport failed with error %d", status);
122 }
123 state_unref(state);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800124}
125
Dan Bornfa6b6062016-01-08 21:01:59 -0800126static void on_accept(grpc_exec_ctx *exec_ctx, void *statep, grpc_endpoint *tcp,
Dan Born5d81d152016-01-12 20:29:29 -0800127 grpc_tcp_server_acceptor *acceptor) {
David Klempnerfd5d8ff2015-03-05 14:17:38 -0800128 grpc_server_secure_state *state = statep;
Craig Tillera82950e2015-09-22 12:33:20 -0700129 state_ref(state);
Julien Boeuf4f4d37c2016-02-24 22:07:36 -0800130 grpc_server_security_connector_do_handshake(
131 exec_ctx, state->sc, acceptor, tcp, on_secure_handshake_done, state);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800132}
133
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800134/* Server callback: start listening on our ports */
Craig Tillera82950e2015-09-22 12:33:20 -0700135static void start(grpc_exec_ctx *exec_ctx, grpc_server *server, void *statep,
136 grpc_pollset **pollsets, size_t pollset_count) {
David Klempnerfd5d8ff2015-03-05 14:17:38 -0800137 grpc_server_secure_state *state = statep;
Craig Tillera82950e2015-09-22 12:33:20 -0700138 grpc_tcp_server_start(exec_ctx, state->tcp, pollsets, pollset_count,
139 on_accept, state);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800140}
141
Craig Tiller6c396862016-01-28 13:53:40 -0800142static void destroy_done(grpc_exec_ctx *exec_ctx, void *statep, bool success) {
Craig Tiller12d7e1f2015-06-03 07:54:48 -0700143 grpc_server_secure_state *state = statep;
Dan Bornfa6b6062016-01-08 21:01:59 -0800144 if (state->destroy_callback != NULL) {
145 state->destroy_callback->cb(exec_ctx, state->destroy_callback->cb_arg,
146 success);
147 }
Julien Boeuf4f4d37c2016-02-24 22:07:36 -0800148 grpc_server_security_connector_shutdown(exec_ctx, state->sc);
Craig Tillera82950e2015-09-22 12:33:20 -0700149 state_unref(state);
Craig Tiller12d7e1f2015-06-03 07:54:48 -0700150}
151
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800152/* Server callback: destroy the tcp listener (so we don't generate further
153 callbacks) */
Craig Tillera82950e2015-09-22 12:33:20 -0700154static void destroy(grpc_exec_ctx *exec_ctx, grpc_server *server, void *statep,
155 grpc_closure *callback) {
David Klempnerfd5d8ff2015-03-05 14:17:38 -0800156 grpc_server_secure_state *state = statep;
Nicolas "Pixel" Noble04a841f2015-06-23 01:57:21 +0200157 grpc_tcp_server *tcp;
Craig Tillera82950e2015-09-22 12:33:20 -0700158 gpr_mu_lock(&state->mu);
David Klempnerfd5d8ff2015-03-05 14:17:38 -0800159 state->is_shutdown = 1;
Craig Tillerdfff1b82015-09-21 14:39:57 -0700160 state->destroy_callback = callback;
Nicolas "Pixel" Noble04a841f2015-06-23 01:57:21 +0200161 tcp = state->tcp;
Craig Tillera82950e2015-09-22 12:33:20 -0700162 gpr_mu_unlock(&state->mu);
Dan Bornfa6b6062016-01-08 21:01:59 -0800163 grpc_tcp_server_unref(exec_ctx, tcp);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800164}
165
Craig Tillera82950e2015-09-22 12:33:20 -0700166int grpc_server_add_secure_http2_port(grpc_server *server, const char *addr,
167 grpc_server_credentials *creds) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800168 grpc_resolved_addresses *resolved = NULL;
169 grpc_tcp_server *tcp = NULL;
David Klempnerfd5d8ff2015-03-05 14:17:38 -0800170 grpc_server_secure_state *state = NULL;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800171 size_t i;
Nicolas "Pixel" Noble213ed912015-01-30 02:11:35 +0100172 unsigned count = 0;
murgatroid99c896e192015-01-21 11:36:23 -0800173 int port_num = -1;
174 int port_temp;
Craig Tiller759026c2015-02-22 23:09:45 -0800175 grpc_security_status status = GRPC_SECURITY_ERROR;
Julien Boeuf4f4d37c2016-02-24 22:07:36 -0800176 grpc_server_security_connector *sc = NULL;
Craig Tillerf5768a62015-09-22 10:54:34 -0700177 grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800178
Craig Tiller4de3e4f2015-10-05 08:55:50 -0700179 GRPC_API_TRACE(
180 "grpc_server_add_secure_http2_port("
181 "server=%p, addr=%s, creds=%p)",
182 3, (server, addr, creds));
Masood Malekghassemi76c3d742015-08-19 18:22:53 -0700183
Craig Tiller759026c2015-02-22 23:09:45 -0800184 /* create security context */
Craig Tillera82950e2015-09-22 12:33:20 -0700185 if (creds == NULL) goto error;
186 status = grpc_server_credentials_create_security_connector(creds, &sc);
187 if (status != GRPC_SECURITY_OK) {
188 gpr_log(GPR_ERROR,
189 "Unable to create secure server with credentials of type %s.",
190 creds->type);
Craig Tiller759026c2015-02-22 23:09:45 -0800191 goto error;
Craig Tillera82950e2015-09-22 12:33:20 -0700192 }
yang-gdd7c1ae2015-11-23 14:29:09 -0800193 sc->channel_args = grpc_server_get_channel_args(server);
Craig Tiller759026c2015-02-22 23:09:45 -0800194
195 /* resolve address */
Craig Tillera82950e2015-09-22 12:33:20 -0700196 resolved = grpc_blocking_resolve_address(addr, "https");
197 if (!resolved) {
198 goto error;
199 }
Dan Bornfa6b6062016-01-08 21:01:59 -0800200 state = gpr_malloc(sizeof(*state));
201 memset(state, 0, sizeof(*state));
202 grpc_closure_init(&state->destroy_closure, destroy_done, state);
203 tcp = grpc_tcp_server_create(&state->destroy_closure);
Craig Tillera82950e2015-09-22 12:33:20 -0700204 if (!tcp) {
205 goto error;
206 }
Craig Tiller45724b32015-09-22 10:42:19 -0700207
yang-g9356b472016-02-02 22:33:43 -0800208 state->server = server;
209 state->tcp = tcp;
210 state->sc = sc;
211 state->creds = grpc_server_credentials_ref(creds);
yang-g9356b472016-02-02 22:33:43 -0800212 state->is_shutdown = 0;
213 gpr_mu_init(&state->mu);
214 gpr_ref_init(&state->refcount, 1);
215
Craig Tillera82950e2015-09-22 12:33:20 -0700216 for (i = 0; i < resolved->naddrs; i++) {
Dan Bornfa6b6062016-01-08 21:01:59 -0800217 port_temp = grpc_tcp_server_add_port(
Craig Tillera82950e2015-09-22 12:33:20 -0700218 tcp, (struct sockaddr *)&resolved->addrs[i].addr,
219 resolved->addrs[i].len);
Jan Tattermusch1d7ccec2015-12-14 09:33:30 -0800220 if (port_temp > 0) {
Craig Tillera82950e2015-09-22 12:33:20 -0700221 if (port_num == -1) {
222 port_num = port_temp;
223 } else {
224 GPR_ASSERT(port_num == port_temp);
225 }
226 count++;
Craig Tiller45724b32015-09-22 10:42:19 -0700227 }
Craig Tillera82950e2015-09-22 12:33:20 -0700228 }
229 if (count == 0) {
230 gpr_log(GPR_ERROR, "No address added out of total %d resolved",
231 resolved->naddrs);
232 goto error;
233 }
234 if (count != resolved->naddrs) {
235 gpr_log(GPR_ERROR, "Only %d addresses added out of total %d resolved",
236 count, resolved->naddrs);
237 /* if it's an error, don't we want to goto error; here ? */
238 }
239 grpc_resolved_addresses_destroy(resolved);
Craig Tiller45724b32015-09-22 10:42:19 -0700240
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800241 /* Register with the server only upon success */
Craig Tillera82950e2015-09-22 12:33:20 -0700242 grpc_server_add_listener(&exec_ctx, server, state, start, destroy);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800243
Craig Tillera82950e2015-09-22 12:33:20 -0700244 grpc_exec_ctx_finish(&exec_ctx);
murgatroid99c896e192015-01-21 11:36:23 -0800245 return port_num;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800246
247/* Error path: cleanup and return */
248error:
Craig Tillera82950e2015-09-22 12:33:20 -0700249 if (resolved) {
250 grpc_resolved_addresses_destroy(resolved);
251 }
252 if (tcp) {
Dan Bornfa6b6062016-01-08 21:01:59 -0800253 grpc_tcp_server_unref(&exec_ctx, tcp);
yang-g9356b472016-02-02 22:33:43 -0800254 } else {
255 if (sc) {
Julien Boeuf4f4d37c2016-02-24 22:07:36 -0800256 GRPC_SECURITY_CONNECTOR_UNREF(&sc->base, "server");
yang-g9356b472016-02-02 22:33:43 -0800257 }
258 if (state) {
259 gpr_free(state);
260 }
Craig Tillera82950e2015-09-22 12:33:20 -0700261 }
262 grpc_exec_ctx_finish(&exec_ctx);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800263 return 0;
Craig Tiller190d3602015-02-18 09:23:38 -0800264}