blob: 7065d261ba2112c3eb931df9223750273fde1235 [file] [log] [blame]
Julien Boeuf87047d72015-08-21 14:30:33 -07001/*
2 *
Craig Tiller6169d5f2016-03-31 07:46:18 -07003 * Copyright 2015, Google Inc.
Julien Boeuf87047d72015-08-21 14:30:33 -07004 * 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
Mark D. Roth071cacf2016-11-17 13:17:56 -080034#include "src/core/lib/security/transport/security_handshaker.h"
Julien Boeuf87047d72015-08-21 14:30:33 -070035
Julien Boeuf4f4d37c2016-02-24 22:07:36 -080036#include <stdbool.h>
Julien Boeuf87047d72015-08-21 14:30:33 -070037#include <string.h>
38
Craig Tiller28b72422016-10-26 21:15:29 -070039#include <grpc/slice_buffer.h>
Julien Boeuf87047d72015-08-21 14:30:33 -070040#include <grpc/support/alloc.h>
41#include <grpc/support/log.h>
Mark D. Roth963be372016-11-16 14:17:06 -080042
43#include "src/core/lib/channel/channel_args.h"
44#include "src/core/lib/channel/handshaker.h"
Mark D. Roth1f0f23c2017-01-06 13:07:19 -080045#include "src/core/lib/channel/handshaker_registry.h"
Julien Boeuf8ca294e2016-05-02 14:56:30 -070046#include "src/core/lib/security/context/security_context.h"
47#include "src/core/lib/security/transport/secure_endpoint.h"
Craig Tiller804ff712016-05-05 16:25:40 -070048#include "src/core/lib/security/transport/tsi_error.h"
Craig Tiller6822a7a2016-12-06 19:28:52 -080049#include "src/core/lib/slice/slice_internal.h"
Julien Boeuf87047d72015-08-21 14:30:33 -070050
51#define GRPC_INITIAL_HANDSHAKE_BUFFER_SIZE 256
52
Craig Tillera82950e2015-09-22 12:33:20 -070053typedef struct {
Mark D. Roth963be372016-11-16 14:17:06 -080054 grpc_handshaker base;
Mark D. Roth75d0c422016-11-30 11:40:57 -080055
56 // State set at creation time.
Julien Boeufdb5282b2015-08-21 15:23:52 -070057 tsi_handshaker *handshaker;
Mark D. Roth75d0c422016-11-30 11:40:57 -080058 grpc_security_connector *connector;
59
Mark D. Roth3beb6c52016-11-29 11:25:12 -080060 gpr_mu mu;
61 gpr_refcount refs;
Mark D. Roth75d0c422016-11-30 11:40:57 -080062
63 bool shutdown;
64 // Endpoint and read buffer to destroy after a shutdown.
65 grpc_endpoint *endpoint_to_destroy;
66 grpc_slice_buffer *read_buffer_to_destroy;
67
68 // State saved while performing the handshake.
Mark D. Rotha5617852016-12-01 08:48:22 -080069 grpc_handshaker_args *args;
70 grpc_closure *on_handshake_done;
Mark D. Roth75d0c422016-11-30 11:40:57 -080071
Julien Boeuf87047d72015-08-21 14:30:33 -070072 unsigned char *handshake_buffer;
73 size_t handshake_buffer_size;
Craig Tillerd41a4a72016-10-26 16:16:06 -070074 grpc_slice_buffer left_overs;
Craig Tillerd41a4a72016-10-26 16:16:06 -070075 grpc_slice_buffer outgoing;
Craig Tiller10ee2742015-09-22 09:25:57 -070076 grpc_closure on_handshake_data_sent_to_peer;
77 grpc_closure on_handshake_data_received_from_peer;
Mark D. Roth3beb6c52016-11-29 11:25:12 -080078 grpc_closure on_peer_checked;
Julien Boeuf366f42c2015-12-16 22:05:46 -080079 grpc_auth_context *auth_context;
Mark D. Roth963be372016-11-16 14:17:06 -080080} security_handshaker;
Julien Boeuf87047d72015-08-21 14:30:33 -070081
Mark D. Roth75d0c422016-11-30 11:40:57 -080082static void security_handshaker_unref(grpc_exec_ctx *exec_ctx,
83 security_handshaker *h) {
Craig Tillerfc25b5f2016-06-14 09:50:15 -070084 if (gpr_unref(&h->refs)) {
Mark D. Roth3beb6c52016-11-29 11:25:12 -080085 gpr_mu_destroy(&h->mu);
Mark D. Rothbd913a82016-12-02 16:47:35 +000086 tsi_handshaker_destroy(h->handshaker);
Mark D. Roth75d0c422016-11-30 11:40:57 -080087 if (h->endpoint_to_destroy != NULL) {
88 grpc_endpoint_destroy(exec_ctx, h->endpoint_to_destroy);
89 }
90 if (h->read_buffer_to_destroy != NULL) {
Craig Tiller6822a7a2016-12-06 19:28:52 -080091 grpc_slice_buffer_destroy_internal(exec_ctx, h->read_buffer_to_destroy);
Mark D. Roth75d0c422016-11-30 11:40:57 -080092 gpr_free(h->read_buffer_to_destroy);
93 }
Mark D. Rothbd913a82016-12-02 16:47:35 +000094 gpr_free(h->handshake_buffer);
Craig Tiller6822a7a2016-12-06 19:28:52 -080095 grpc_slice_buffer_destroy_internal(exec_ctx, &h->left_overs);
96 grpc_slice_buffer_destroy_internal(exec_ctx, &h->outgoing);
Craig Tillerfc25b5f2016-06-14 09:50:15 -070097 GRPC_AUTH_CONTEXT_UNREF(h->auth_context, "handshake");
Craig Tiller397bff32016-12-06 15:05:59 -080098 GRPC_SECURITY_CONNECTOR_UNREF(exec_ctx, h->connector, "handshake");
Craig Tillerfc25b5f2016-06-14 09:50:15 -070099 gpr_free(h);
100 }
101}
102
Mark D. Roth75d0c422016-11-30 11:40:57 -0800103// Set args fields to NULL, saving the endpoint and read buffer for
104// later destruction.
Craig Tillerb6821f62016-12-06 15:10:42 -0800105static void cleanup_args_for_failure_locked(grpc_exec_ctx *exec_ctx,
106 security_handshaker *h) {
Mark D. Roth75d0c422016-11-30 11:40:57 -0800107 h->endpoint_to_destroy = h->args->endpoint;
108 h->args->endpoint = NULL;
109 h->read_buffer_to_destroy = h->args->read_buffer;
110 h->args->read_buffer = NULL;
Craig Tiller397bff32016-12-06 15:05:59 -0800111 grpc_channel_args_destroy(exec_ctx, h->args->args);
Mark D. Roth75d0c422016-11-30 11:40:57 -0800112 h->args->args = NULL;
113}
114
115// If the handshake failed or we're shutting down, clean up and invoke the
116// callback with the error.
117static void security_handshake_failed_locked(grpc_exec_ctx *exec_ctx,
118 security_handshaker *h,
119 grpc_error *error) {
Craig Tiller804ff712016-05-05 16:25:40 -0700120 if (error == GRPC_ERROR_NONE) {
Mark D. Roth75d0c422016-11-30 11:40:57 -0800121 // If we were shut down after the handshake succeeded but before an
122 // endpoint callback was invoked, we need to generate our own error.
123 error = GRPC_ERROR_CREATE("Handshaker shutdown");
Craig Tillera82950e2015-09-22 12:33:20 -0700124 }
Mark D. Roth75d0c422016-11-30 11:40:57 -0800125 const char *msg = grpc_error_string(error);
126 gpr_log(GPR_DEBUG, "Security handshake failed: %s", msg);
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800127
Mark D. Roth75d0c422016-11-30 11:40:57 -0800128 if (!h->shutdown) {
129 // TODO(ctiller): It is currently necessary to shutdown endpoints
130 // before destroying them, even if we know that there are no
131 // pending read/write callbacks. This should be fixed, at which
132 // point this can be removed.
Craig Tillercda759d2017-01-27 11:37:37 -0800133 grpc_endpoint_shutdown(exec_ctx, h->args->endpoint, GRPC_ERROR_REF(error));
Mark D. Roth75d0c422016-11-30 11:40:57 -0800134 // Not shutting down, so the write failed. Clean up before
135 // invoking the callback.
Craig Tiller397bff32016-12-06 15:05:59 -0800136 cleanup_args_for_failure_locked(exec_ctx, h);
Mark D. Rothc8984172016-12-08 09:40:33 -0800137 // Set shutdown to true so that subsequent calls to
138 // security_handshaker_shutdown() do nothing.
139 h->shutdown = true;
Mark D. Roth75d0c422016-11-30 11:40:57 -0800140 }
141 // Invoke callback.
Craig Tiller91031da2016-12-28 15:44:25 -0800142 grpc_closure_sched(exec_ctx, h->on_handshake_done, error);
Julien Boeuf87047d72015-08-21 14:30:33 -0700143}
144
Mark D. Roth3beb6c52016-11-29 11:25:12 -0800145static void on_peer_checked(grpc_exec_ctx *exec_ctx, void *arg,
146 grpc_error *error) {
147 security_handshaker *h = arg;
148 gpr_mu_lock(&h->mu);
Mark D. Roth75d0c422016-11-30 11:40:57 -0800149 if (error != GRPC_ERROR_NONE || h->shutdown) {
150 security_handshake_failed_locked(exec_ctx, h, GRPC_ERROR_REF(error));
Mark D. Roth3beb6c52016-11-29 11:25:12 -0800151 goto done;
Craig Tillera82950e2015-09-22 12:33:20 -0700152 }
Mark D. Roth3beb6c52016-11-29 11:25:12 -0800153 // Get frame protector.
154 tsi_frame_protector *protector;
155 tsi_result result =
Craig Tillera82950e2015-09-22 12:33:20 -0700156 tsi_handshaker_create_frame_protector(h->handshaker, NULL, &protector);
157 if (result != TSI_OK) {
Mark D. Roth3beb6c52016-11-29 11:25:12 -0800158 error = grpc_set_tsi_error_result(
159 GRPC_ERROR_CREATE("Frame protector creation failed"), result);
Mark D. Roth75d0c422016-11-30 11:40:57 -0800160 security_handshake_failed_locked(exec_ctx, h, error);
Mark D. Roth3beb6c52016-11-29 11:25:12 -0800161 goto done;
Craig Tillera82950e2015-09-22 12:33:20 -0700162 }
Mark D. Roth75d0c422016-11-30 11:40:57 -0800163 // Success.
164 // Create secure endpoint.
Mark D. Rotha5617852016-12-01 08:48:22 -0800165 h->args->endpoint = grpc_secure_endpoint_create(
166 protector, h->args->endpoint, h->left_overs.slices, h->left_overs.count);
Julien Boeufe9961d22015-09-15 22:51:02 -0700167 h->left_overs.count = 0;
168 h->left_overs.length = 0;
Mark D. Roth75d0c422016-11-30 11:40:57 -0800169 // Clear out the read buffer before it gets passed to the transport,
170 // since any excess bytes were already copied to h->left_overs.
Craig Tiller6822a7a2016-12-06 19:28:52 -0800171 grpc_slice_buffer_reset_and_unref_internal(exec_ctx, h->args->read_buffer);
Mark D. Roth75d0c422016-11-30 11:40:57 -0800172 // Add auth context to channel args.
173 grpc_arg auth_context_arg = grpc_auth_context_to_arg(h->auth_context);
Mark D. Rotha5617852016-12-01 08:48:22 -0800174 grpc_channel_args *tmp_args = h->args->args;
Mark D. Roth75d0c422016-11-30 11:40:57 -0800175 h->args->args =
176 grpc_channel_args_copy_and_add(tmp_args, &auth_context_arg, 1);
Craig Tiller397bff32016-12-06 15:05:59 -0800177 grpc_channel_args_destroy(exec_ctx, tmp_args);
Mark D. Roth75d0c422016-11-30 11:40:57 -0800178 // Invoke callback.
Craig Tiller91031da2016-12-28 15:44:25 -0800179 grpc_closure_sched(exec_ctx, h->on_handshake_done, GRPC_ERROR_NONE);
Mark D. Roth412e6ac2016-12-01 08:24:45 -0800180 // Set shutdown to true so that subsequent calls to
181 // security_handshaker_shutdown() do nothing.
182 h->shutdown = true;
Mark D. Roth3beb6c52016-11-29 11:25:12 -0800183done:
Mark D. Roth3beb6c52016-11-29 11:25:12 -0800184 gpr_mu_unlock(&h->mu);
Mark D. Roth75d0c422016-11-30 11:40:57 -0800185 security_handshaker_unref(exec_ctx, h);
Julien Boeuf87047d72015-08-21 14:30:33 -0700186}
187
Mark D. Rotha5617852016-12-01 08:48:22 -0800188static grpc_error *check_peer_locked(grpc_exec_ctx *exec_ctx,
Mark D. Roth3beb6c52016-11-29 11:25:12 -0800189 security_handshaker *h) {
Julien Boeuf87047d72015-08-21 14:30:33 -0700190 tsi_peer peer;
Craig Tillera82950e2015-09-22 12:33:20 -0700191 tsi_result result = tsi_handshaker_extract_peer(h->handshaker, &peer);
Craig Tillera82950e2015-09-22 12:33:20 -0700192 if (result != TSI_OK) {
Mark D. Roth3beb6c52016-11-29 11:25:12 -0800193 return grpc_set_tsi_error_result(
194 GRPC_ERROR_CREATE("Peer extraction failed"), result);
Craig Tillera82950e2015-09-22 12:33:20 -0700195 }
Julien Boeuf366f42c2015-12-16 22:05:46 -0800196 grpc_security_connector_check_peer(exec_ctx, h->connector, peer,
Mark D. Roth3beb6c52016-11-29 11:25:12 -0800197 &h->auth_context, &h->on_peer_checked);
198 return GRPC_ERROR_NONE;
Julien Boeuf87047d72015-08-21 14:30:33 -0700199}
200
Mark D. Rotha5617852016-12-01 08:48:22 -0800201static grpc_error *send_handshake_bytes_to_peer_locked(grpc_exec_ctx *exec_ctx,
Mark D. Roth3beb6c52016-11-29 11:25:12 -0800202 security_handshaker *h) {
203 // Get data to send.
Julien Boeuf87047d72015-08-21 14:30:33 -0700204 tsi_result result = TSI_OK;
Mark D. Roth3beb6c52016-11-29 11:25:12 -0800205 size_t offset = 0;
Craig Tillera82950e2015-09-22 12:33:20 -0700206 do {
207 size_t to_send_size = h->handshake_buffer_size - offset;
208 result = tsi_handshaker_get_bytes_to_send_to_peer(
209 h->handshaker, h->handshake_buffer + offset, &to_send_size);
210 offset += to_send_size;
211 if (result == TSI_INCOMPLETE_DATA) {
212 h->handshake_buffer_size *= 2;
213 h->handshake_buffer =
214 gpr_realloc(h->handshake_buffer, h->handshake_buffer_size);
Julien Boeuf87047d72015-08-21 14:30:33 -0700215 }
Craig Tillera82950e2015-09-22 12:33:20 -0700216 } while (result == TSI_INCOMPLETE_DATA);
Craig Tillera82950e2015-09-22 12:33:20 -0700217 if (result != TSI_OK) {
Mark D. Roth3beb6c52016-11-29 11:25:12 -0800218 return grpc_set_tsi_error_result(GRPC_ERROR_CREATE("Handshake failed"),
219 result);
Craig Tillera82950e2015-09-22 12:33:20 -0700220 }
Mark D. Roth3beb6c52016-11-29 11:25:12 -0800221 // Send data.
222 grpc_slice to_send =
Craig Tillerd41a4a72016-10-26 16:16:06 -0700223 grpc_slice_from_copied_buffer((const char *)h->handshake_buffer, offset);
Craig Tiller6822a7a2016-12-06 19:28:52 -0800224 grpc_slice_buffer_reset_and_unref_internal(exec_ctx, &h->outgoing);
Craig Tillerd41a4a72016-10-26 16:16:06 -0700225 grpc_slice_buffer_add(&h->outgoing, to_send);
Mark D. Roth95fcb582016-11-29 11:29:19 -0800226 grpc_endpoint_write(exec_ctx, h->args->endpoint, &h->outgoing,
Craig Tillera82950e2015-09-22 12:33:20 -0700227 &h->on_handshake_data_sent_to_peer);
Mark D. Roth3beb6c52016-11-29 11:25:12 -0800228 return GRPC_ERROR_NONE;
Julien Boeuf87047d72015-08-21 14:30:33 -0700229}
230
Craig Tillera82950e2015-09-22 12:33:20 -0700231static void on_handshake_data_received_from_peer(grpc_exec_ctx *exec_ctx,
Mark D. Roth75d0c422016-11-30 11:40:57 -0800232 void *arg, grpc_error *error) {
233 security_handshaker *h = arg;
Mark D. Roth3beb6c52016-11-29 11:25:12 -0800234 gpr_mu_lock(&h->mu);
Mark D. Roth75d0c422016-11-30 11:40:57 -0800235 if (error != GRPC_ERROR_NONE || h->shutdown) {
236 security_handshake_failed_locked(
Craig Tiller804ff712016-05-05 16:25:40 -0700237 exec_ctx, h,
238 GRPC_ERROR_CREATE_REFERENCING("Handshake read failed", &error, 1));
Mark D. Roth3beb6c52016-11-29 11:25:12 -0800239 gpr_mu_unlock(&h->mu);
Mark D. Roth75d0c422016-11-30 11:40:57 -0800240 security_handshaker_unref(exec_ctx, h);
Craig Tillera82950e2015-09-22 12:33:20 -0700241 return;
242 }
Mark D. Roth3beb6c52016-11-29 11:25:12 -0800243 // Process received data.
244 tsi_result result = TSI_OK;
245 size_t consumed_slice_size = 0;
246 size_t i;
Mark D. Roth963be372016-11-16 14:17:06 -0800247 for (i = 0; i < h->args->read_buffer->count; i++) {
248 consumed_slice_size = GRPC_SLICE_LENGTH(h->args->read_buffer->slices[i]);
Craig Tillera82950e2015-09-22 12:33:20 -0700249 result = tsi_handshaker_process_bytes_from_peer(
Mark D. Roth963be372016-11-16 14:17:06 -0800250 h->handshaker, GRPC_SLICE_START_PTR(h->args->read_buffer->slices[i]),
Craig Tillera82950e2015-09-22 12:33:20 -0700251 &consumed_slice_size);
252 if (!tsi_handshaker_is_in_progress(h->handshaker)) break;
253 }
Craig Tillera82950e2015-09-22 12:33:20 -0700254 if (tsi_handshaker_is_in_progress(h->handshaker)) {
255 /* We may need more data. */
256 if (result == TSI_INCOMPLETE_DATA) {
Mark D. Roth95fcb582016-11-29 11:29:19 -0800257 grpc_endpoint_read(exec_ctx, h->args->endpoint, h->args->read_buffer,
Craig Tillera82950e2015-09-22 12:33:20 -0700258 &h->on_handshake_data_received_from_peer);
Mark D. Roth3beb6c52016-11-29 11:25:12 -0800259 goto done;
Craig Tillera82950e2015-09-22 12:33:20 -0700260 } else {
Mark D. Roth3beb6c52016-11-29 11:25:12 -0800261 error = send_handshake_bytes_to_peer_locked(exec_ctx, h);
262 if (error != GRPC_ERROR_NONE) {
Mark D. Roth75d0c422016-11-30 11:40:57 -0800263 security_handshake_failed_locked(exec_ctx, h, error);
Mark D. Roth3beb6c52016-11-29 11:25:12 -0800264 gpr_mu_unlock(&h->mu);
Mark D. Roth75d0c422016-11-30 11:40:57 -0800265 security_handshaker_unref(exec_ctx, h);
Mark D. Roth3beb6c52016-11-29 11:25:12 -0800266 return;
267 }
268 goto done;
Julien Boeuf87047d72015-08-21 14:30:33 -0700269 }
Craig Tillera82950e2015-09-22 12:33:20 -0700270 }
Craig Tillera82950e2015-09-22 12:33:20 -0700271 if (result != TSI_OK) {
Mark D. Roth75d0c422016-11-30 11:40:57 -0800272 security_handshake_failed_locked(
Mark D. Rotha5617852016-12-01 08:48:22 -0800273 exec_ctx, h, grpc_set_tsi_error_result(
274 GRPC_ERROR_CREATE("Handshake failed"), result));
Mark D. Roth3beb6c52016-11-29 11:25:12 -0800275 gpr_mu_unlock(&h->mu);
Mark D. Roth75d0c422016-11-30 11:40:57 -0800276 security_handshaker_unref(exec_ctx, h);
Craig Tillera82950e2015-09-22 12:33:20 -0700277 return;
278 }
Julien Boeuf87047d72015-08-21 14:30:33 -0700279 /* Handshake is done and successful this point. */
Mark D. Roth3beb6c52016-11-29 11:25:12 -0800280 bool has_left_overs_in_current_slice =
Mark D. Roth963be372016-11-16 14:17:06 -0800281 (consumed_slice_size <
282 GRPC_SLICE_LENGTH(h->args->read_buffer->slices[i]));
Mark D. Rotha5617852016-12-01 08:48:22 -0800283 size_t num_left_overs = (has_left_overs_in_current_slice ? 1 : 0) +
284 h->args->read_buffer->count - i - 1;
Mark D. Roth963be372016-11-16 14:17:06 -0800285 if (num_left_overs > 0) {
286 /* Put the leftovers in our buffer (ownership transfered). */
287 if (has_left_overs_in_current_slice) {
288 grpc_slice_buffer_add(
289 &h->left_overs,
290 grpc_slice_split_tail(&h->args->read_buffer->slices[i],
Mark D. Rotha5617852016-12-01 08:48:22 -0800291 consumed_slice_size));
Mark D. Roth963be372016-11-16 14:17:06 -0800292 /* split_tail above increments refcount. */
Craig Tiller6822a7a2016-12-06 19:28:52 -0800293 grpc_slice_unref_internal(exec_ctx, h->args->read_buffer->slices[i]);
Mark D. Roth963be372016-11-16 14:17:06 -0800294 }
295 grpc_slice_buffer_addn(
296 &h->left_overs, &h->args->read_buffer->slices[i + 1],
297 num_left_overs - (size_t)has_left_overs_in_current_slice);
Craig Tillera82950e2015-09-22 12:33:20 -0700298 }
Mark D. Roth3beb6c52016-11-29 11:25:12 -0800299 // Check peer.
300 error = check_peer_locked(exec_ctx, h);
301 if (error != GRPC_ERROR_NONE) {
Mark D. Roth75d0c422016-11-30 11:40:57 -0800302 security_handshake_failed_locked(exec_ctx, h, error);
Mark D. Roth3beb6c52016-11-29 11:25:12 -0800303 gpr_mu_unlock(&h->mu);
Mark D. Roth75d0c422016-11-30 11:40:57 -0800304 security_handshaker_unref(exec_ctx, h);
Mark D. Roth3beb6c52016-11-29 11:25:12 -0800305 return;
306 }
307done:
308 gpr_mu_unlock(&h->mu);
Julien Boeuf87047d72015-08-21 14:30:33 -0700309}
310
Mark D. Rotha5617852016-12-01 08:48:22 -0800311static void on_handshake_data_sent_to_peer(grpc_exec_ctx *exec_ctx, void *arg,
312 grpc_error *error) {
Mark D. Roth75d0c422016-11-30 11:40:57 -0800313 security_handshaker *h = arg;
314 gpr_mu_lock(&h->mu);
315 if (error != GRPC_ERROR_NONE || h->shutdown) {
316 security_handshake_failed_locked(
317 exec_ctx, h,
318 GRPC_ERROR_CREATE_REFERENCING("Handshake write failed", &error, 1));
319 gpr_mu_unlock(&h->mu);
320 security_handshaker_unref(exec_ctx, h);
Craig Tillera82950e2015-09-22 12:33:20 -0700321 return;
322 }
Julien Boeuf87047d72015-08-21 14:30:33 -0700323 /* We may be done. */
Craig Tillera82950e2015-09-22 12:33:20 -0700324 if (tsi_handshaker_is_in_progress(h->handshaker)) {
Mark D. Roth95fcb582016-11-29 11:29:19 -0800325 grpc_endpoint_read(exec_ctx, h->args->endpoint, h->args->read_buffer,
Craig Tillera82950e2015-09-22 12:33:20 -0700326 &h->on_handshake_data_received_from_peer);
327 } else {
Mark D. Roth3beb6c52016-11-29 11:25:12 -0800328 error = check_peer_locked(exec_ctx, h);
329 if (error != GRPC_ERROR_NONE) {
Mark D. Roth75d0c422016-11-30 11:40:57 -0800330 security_handshake_failed_locked(exec_ctx, h, error);
Mark D. Roth3beb6c52016-11-29 11:25:12 -0800331 gpr_mu_unlock(&h->mu);
Mark D. Roth75d0c422016-11-30 11:40:57 -0800332 security_handshaker_unref(exec_ctx, h);
Mark D. Roth3beb6c52016-11-29 11:25:12 -0800333 return;
334 }
Craig Tillera82950e2015-09-22 12:33:20 -0700335 }
Mark D. Roth3beb6c52016-11-29 11:25:12 -0800336 gpr_mu_unlock(&h->mu);
Julien Boeuf87047d72015-08-21 14:30:33 -0700337}
338
Mark D. Roth963be372016-11-16 14:17:06 -0800339//
340// public handshaker API
341//
342
Mark D. Rotha5617852016-12-01 08:48:22 -0800343static void security_handshaker_destroy(grpc_exec_ctx *exec_ctx,
344 grpc_handshaker *handshaker) {
345 security_handshaker *h = (security_handshaker *)handshaker;
Mark D. Roth75d0c422016-11-30 11:40:57 -0800346 security_handshaker_unref(exec_ctx, h);
Craig Tillerae134942016-06-14 08:31:48 -0700347}
348
Mark D. Rotha5617852016-12-01 08:48:22 -0800349static void security_handshaker_shutdown(grpc_exec_ctx *exec_ctx,
Craig Tillercda759d2017-01-27 11:37:37 -0800350 grpc_handshaker *handshaker,
351 grpc_error *why) {
Mark D. Rotha5617852016-12-01 08:48:22 -0800352 security_handshaker *h = (security_handshaker *)handshaker;
Mark D. Roth3beb6c52016-11-29 11:25:12 -0800353 gpr_mu_lock(&h->mu);
Mark D. Roth75d0c422016-11-30 11:40:57 -0800354 if (!h->shutdown) {
355 h->shutdown = true;
Craig Tillercda759d2017-01-27 11:37:37 -0800356 grpc_endpoint_shutdown(exec_ctx, h->args->endpoint, GRPC_ERROR_REF(why));
Craig Tiller397bff32016-12-06 15:05:59 -0800357 cleanup_args_for_failure_locked(exec_ctx, h);
Mark D. Roth183a59f2016-11-17 11:10:00 -0800358 }
Mark D. Roth3beb6c52016-11-29 11:25:12 -0800359 gpr_mu_unlock(&h->mu);
Craig Tillercda759d2017-01-27 11:37:37 -0800360 GRPC_ERROR_UNREF(why);
Mark D. Roth963be372016-11-16 14:17:06 -0800361}
362
Mark D. Rotha5617852016-12-01 08:48:22 -0800363static void security_handshaker_do_handshake(grpc_exec_ctx *exec_ctx,
364 grpc_handshaker *handshaker,
365 grpc_tcp_server_acceptor *acceptor,
366 grpc_closure *on_handshake_done,
367 grpc_handshaker_args *args) {
368 security_handshaker *h = (security_handshaker *)handshaker;
Mark D. Roth3beb6c52016-11-29 11:25:12 -0800369 gpr_mu_lock(&h->mu);
Mark D. Roth963be372016-11-16 14:17:06 -0800370 h->args = args;
371 h->on_handshake_done = on_handshake_done;
Mark D. Roth963be372016-11-16 14:17:06 -0800372 gpr_ref(&h->refs);
Mark D. Rotha5617852016-12-01 08:48:22 -0800373 grpc_error *error = send_handshake_bytes_to_peer_locked(exec_ctx, h);
Mark D. Roth3beb6c52016-11-29 11:25:12 -0800374 if (error != GRPC_ERROR_NONE) {
Mark D. Roth75d0c422016-11-30 11:40:57 -0800375 security_handshake_failed_locked(exec_ctx, h, error);
Mark D. Roth3beb6c52016-11-29 11:25:12 -0800376 gpr_mu_unlock(&h->mu);
Mark D. Roth75d0c422016-11-30 11:40:57 -0800377 security_handshaker_unref(exec_ctx, h);
Mark D. Roth3beb6c52016-11-29 11:25:12 -0800378 return;
379 }
380 gpr_mu_unlock(&h->mu);
Mark D. Roth963be372016-11-16 14:17:06 -0800381}
382
383static const grpc_handshaker_vtable security_handshaker_vtable = {
Mark D. Rotha5617852016-12-01 08:48:22 -0800384 security_handshaker_destroy, security_handshaker_shutdown,
385 security_handshaker_do_handshake};
Mark D. Roth963be372016-11-16 14:17:06 -0800386
Mark D. Rotha5617852016-12-01 08:48:22 -0800387static grpc_handshaker *security_handshaker_create(
Craig Tiller449c64b2016-06-13 16:26:50 -0700388 grpc_exec_ctx *exec_ctx, tsi_handshaker *handshaker,
Mark D. Roth963be372016-11-16 14:17:06 -0800389 grpc_security_connector *connector) {
Craig Tiller6f417882017-02-16 14:09:39 -0800390 security_handshaker *h = gpr_zalloc(sizeof(security_handshaker));
Mark D. Roth963be372016-11-16 14:17:06 -0800391 grpc_handshaker_init(&security_handshaker_vtable, &h->base);
Julien Boeufdb5282b2015-08-21 15:23:52 -0700392 h->handshaker = handshaker;
Craig Tillera82950e2015-09-22 12:33:20 -0700393 h->connector = GRPC_SECURITY_CONNECTOR_REF(connector, "handshake");
Mark D. Roth3beb6c52016-11-29 11:25:12 -0800394 gpr_mu_init(&h->mu);
395 gpr_ref_init(&h->refs, 1);
Julien Boeuf87047d72015-08-21 14:30:33 -0700396 h->handshake_buffer_size = GRPC_INITIAL_HANDSHAKE_BUFFER_SIZE;
Craig Tillera82950e2015-09-22 12:33:20 -0700397 h->handshake_buffer = gpr_malloc(h->handshake_buffer_size);
Craig Tillera82950e2015-09-22 12:33:20 -0700398 grpc_closure_init(&h->on_handshake_data_sent_to_peer,
Craig Tiller91031da2016-12-28 15:44:25 -0800399 on_handshake_data_sent_to_peer, h,
400 grpc_schedule_on_exec_ctx);
Craig Tillera82950e2015-09-22 12:33:20 -0700401 grpc_closure_init(&h->on_handshake_data_received_from_peer,
Craig Tiller91031da2016-12-28 15:44:25 -0800402 on_handshake_data_received_from_peer, h,
403 grpc_schedule_on_exec_ctx);
404 grpc_closure_init(&h->on_peer_checked, on_peer_checked, h,
405 grpc_schedule_on_exec_ctx);
Craig Tillerd41a4a72016-10-26 16:16:06 -0700406 grpc_slice_buffer_init(&h->left_overs);
407 grpc_slice_buffer_init(&h->outgoing);
Mark D. Roth963be372016-11-16 14:17:06 -0800408 return &h->base;
Julien Boeuf87047d72015-08-21 14:30:33 -0700409}
yang-g5e72a352015-11-20 09:49:36 -0800410
Mark D. Roth963be372016-11-16 14:17:06 -0800411//
412// fail_handshaker
413//
414
Mark D. Rotha5617852016-12-01 08:48:22 -0800415static void fail_handshaker_destroy(grpc_exec_ctx *exec_ctx,
416 grpc_handshaker *handshaker) {
Mark D. Roth963be372016-11-16 14:17:06 -0800417 gpr_free(handshaker);
418}
419
Mark D. Rotha5617852016-12-01 08:48:22 -0800420static void fail_handshaker_shutdown(grpc_exec_ctx *exec_ctx,
Craig Tillercda759d2017-01-27 11:37:37 -0800421 grpc_handshaker *handshaker,
422 grpc_error *why) {
423 GRPC_ERROR_UNREF(why);
424}
Mark D. Roth963be372016-11-16 14:17:06 -0800425
Mark D. Rotha5617852016-12-01 08:48:22 -0800426static void fail_handshaker_do_handshake(grpc_exec_ctx *exec_ctx,
427 grpc_handshaker *handshaker,
428 grpc_tcp_server_acceptor *acceptor,
429 grpc_closure *on_handshake_done,
430 grpc_handshaker_args *args) {
Craig Tiller91031da2016-12-28 15:44:25 -0800431 grpc_closure_sched(exec_ctx, on_handshake_done,
432 GRPC_ERROR_CREATE("Failed to create security handshaker"));
Mark D. Roth963be372016-11-16 14:17:06 -0800433}
434
435static const grpc_handshaker_vtable fail_handshaker_vtable = {
Mark D. Rotha5617852016-12-01 08:48:22 -0800436 fail_handshaker_destroy, fail_handshaker_shutdown,
437 fail_handshaker_do_handshake};
Mark D. Roth963be372016-11-16 14:17:06 -0800438
Mark D. Rotha5617852016-12-01 08:48:22 -0800439static grpc_handshaker *fail_handshaker_create() {
440 grpc_handshaker *h = gpr_malloc(sizeof(*h));
Mark D. Roth963be372016-11-16 14:17:06 -0800441 grpc_handshaker_init(&fail_handshaker_vtable, h);
442 return h;
443}
444
445//
Mark D. Roth1f0f23c2017-01-06 13:07:19 -0800446// handshaker factories
447//
448
449static void client_handshaker_factory_add_handshakers(
450 grpc_exec_ctx *exec_ctx, grpc_handshaker_factory *handshaker_factory,
451 const grpc_channel_args *args, grpc_handshake_manager *handshake_mgr) {
452 grpc_channel_security_connector *security_connector =
David Garcia Quintas01291502017-02-07 13:26:41 -0800453 (grpc_channel_security_connector *)grpc_security_connector_find_in_args(
Mark D. Roth1f0f23c2017-01-06 13:07:19 -0800454 args);
455 grpc_channel_security_connector_add_handshakers(exec_ctx, security_connector,
456 handshake_mgr);
457}
458
459static void server_handshaker_factory_add_handshakers(
460 grpc_exec_ctx *exec_ctx, grpc_handshaker_factory *hf,
461 const grpc_channel_args *args, grpc_handshake_manager *handshake_mgr) {
462 grpc_server_security_connector *security_connector =
David Garcia Quintas01291502017-02-07 13:26:41 -0800463 (grpc_server_security_connector *)grpc_security_connector_find_in_args(
Mark D. Roth1f0f23c2017-01-06 13:07:19 -0800464 args);
465 grpc_server_security_connector_add_handshakers(exec_ctx, security_connector,
466 handshake_mgr);
467}
468
469static void handshaker_factory_destroy(
470 grpc_exec_ctx *exec_ctx, grpc_handshaker_factory *handshaker_factory) {}
471
472static const grpc_handshaker_factory_vtable client_handshaker_factory_vtable = {
473 client_handshaker_factory_add_handshakers, handshaker_factory_destroy};
474
475static grpc_handshaker_factory client_handshaker_factory = {
476 &client_handshaker_factory_vtable};
477
478static const grpc_handshaker_factory_vtable server_handshaker_factory_vtable = {
479 server_handshaker_factory_add_handshakers, handshaker_factory_destroy};
480
481static grpc_handshaker_factory server_handshaker_factory = {
482 &server_handshaker_factory_vtable};
483
484//
Mark D. Roth963be372016-11-16 14:17:06 -0800485// exported functions
486//
487
Mark D. Rothd0953402016-12-07 07:56:48 -0800488grpc_handshaker *grpc_security_handshaker_create(
489 grpc_exec_ctx *exec_ctx, tsi_handshaker *handshaker,
490 grpc_security_connector *connector) {
491 // If no TSI handshaker was created, return a handshaker that always fails.
492 // Otherwise, return a real security handshaker.
Mark D. Roth963be372016-11-16 14:17:06 -0800493 if (handshaker == NULL) {
Mark D. Rothd0953402016-12-07 07:56:48 -0800494 return fail_handshaker_create();
Mark D. Roth963be372016-11-16 14:17:06 -0800495 } else {
Mark D. Rothd0953402016-12-07 07:56:48 -0800496 return security_handshaker_create(exec_ctx, handshaker, connector);
Mark D. Roth963be372016-11-16 14:17:06 -0800497 }
yang-g5e72a352015-11-20 09:49:36 -0800498}
Mark D. Roth1f0f23c2017-01-06 13:07:19 -0800499
500void grpc_security_register_handshaker_factories() {
501 grpc_handshaker_factory_register(false /* at_start */, HANDSHAKER_CLIENT,
502 &client_handshaker_factory);
503 grpc_handshaker_factory_register(false /* at_start */, HANDSHAKER_SERVER,
504 &server_handshaker_factory);
505}