1 /*
2 *
3 * Copyright 2015 gRPC authors.
4 *
5 * 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
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * 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.
16 *
17 */
18
19 #include <grpc/support/port_platform.h>
20
21 #include "src/core/lib/security/transport/security_handshaker.h"
22
23 #include <stdbool.h>
24 #include <string.h>
25 #include <limits>
26
27 #include <grpc/slice_buffer.h>
28 #include <grpc/support/alloc.h>
29 #include <grpc/support/log.h>
30
31 #include "src/core/lib/channel/channel_args.h"
32 #include "src/core/lib/channel/handshaker.h"
33 #include "src/core/lib/channel/handshaker_registry.h"
34 #include "src/core/lib/gprpp/ref_counted_ptr.h"
35 #include "src/core/lib/security/context/security_context.h"
36 #include "src/core/lib/security/transport/secure_endpoint.h"
37 #include "src/core/lib/security/transport/tsi_error.h"
38 #include "src/core/lib/slice/slice_internal.h"
39 #include "src/core/tsi/transport_security_grpc.h"
40
41 #define GRPC_INITIAL_HANDSHAKE_BUFFER_SIZE 256
42
43 namespace grpc_core {
44
45 namespace {
46
47 class SecurityHandshaker : public Handshaker {
48 public:
49 SecurityHandshaker(tsi_handshaker* handshaker,
50 grpc_security_connector* connector,
51 const grpc_channel_args* args);
52 ~SecurityHandshaker() override;
53 void Shutdown(grpc_error* why) override;
54 void DoHandshake(grpc_tcp_server_acceptor* acceptor,
55 grpc_closure* on_handshake_done,
56 HandshakerArgs* args) override;
name() const57 const char* name() const override { return "security"; }
58
59 private:
60 grpc_error* DoHandshakerNextLocked(const unsigned char* bytes_received,
61 size_t bytes_received_size);
62
63 grpc_error* OnHandshakeNextDoneLocked(
64 tsi_result result, const unsigned char* bytes_to_send,
65 size_t bytes_to_send_size, tsi_handshaker_result* handshaker_result);
66 void HandshakeFailedLocked(grpc_error* error);
67 void CleanupArgsForFailureLocked();
68
69 static void OnHandshakeDataReceivedFromPeerFn(void* arg, grpc_error* error);
70 static void OnHandshakeDataSentToPeerFn(void* arg, grpc_error* error);
71 static void OnHandshakeDataReceivedFromPeerFnScheduler(void* arg,
72 grpc_error* error);
73 static void OnHandshakeDataSentToPeerFnScheduler(void* arg,
74 grpc_error* error);
75 static void OnHandshakeNextDoneGrpcWrapper(
76 tsi_result result, void* user_data, const unsigned char* bytes_to_send,
77 size_t bytes_to_send_size, tsi_handshaker_result* handshaker_result);
78 static void OnPeerCheckedFn(void* arg, grpc_error* error);
79 void OnPeerCheckedInner(grpc_error* error);
80 size_t MoveReadBufferIntoHandshakeBuffer();
81 grpc_error* CheckPeerLocked();
82
83 // State set at creation time.
84 tsi_handshaker* handshaker_;
85 RefCountedPtr<grpc_security_connector> connector_;
86
87 Mutex mu_;
88
89 bool is_shutdown_ = false;
90 // Endpoint and read buffer to destroy after a shutdown.
91 grpc_endpoint* endpoint_to_destroy_ = nullptr;
92 grpc_slice_buffer* read_buffer_to_destroy_ = nullptr;
93
94 // State saved while performing the handshake.
95 HandshakerArgs* args_ = nullptr;
96 grpc_closure* on_handshake_done_ = nullptr;
97
98 size_t handshake_buffer_size_;
99 unsigned char* handshake_buffer_;
100 grpc_slice_buffer outgoing_;
101 grpc_closure on_handshake_data_sent_to_peer_;
102 grpc_closure on_handshake_data_received_from_peer_;
103 grpc_closure on_peer_checked_;
104 RefCountedPtr<grpc_auth_context> auth_context_;
105 tsi_handshaker_result* handshaker_result_ = nullptr;
106 size_t max_frame_size_ = 0;
107 };
108
SecurityHandshaker(tsi_handshaker * handshaker,grpc_security_connector * connector,const grpc_channel_args * args)109 SecurityHandshaker::SecurityHandshaker(tsi_handshaker* handshaker,
110 grpc_security_connector* connector,
111 const grpc_channel_args* args)
112 : handshaker_(handshaker),
113 connector_(connector->Ref(DEBUG_LOCATION, "handshake")),
114 handshake_buffer_size_(GRPC_INITIAL_HANDSHAKE_BUFFER_SIZE),
115 handshake_buffer_(
116 static_cast<uint8_t*>(gpr_malloc(handshake_buffer_size_))) {
117 const grpc_arg* arg =
118 grpc_channel_args_find(args, GRPC_ARG_TSI_MAX_FRAME_SIZE);
119 if (arg != nullptr && arg->type == GRPC_ARG_INTEGER) {
120 max_frame_size_ = grpc_channel_arg_get_integer(
121 arg, {0, 0, std::numeric_limits<int>::max()});
122 }
123 grpc_slice_buffer_init(&outgoing_);
124 GRPC_CLOSURE_INIT(&on_peer_checked_, &SecurityHandshaker::OnPeerCheckedFn,
125 this, grpc_schedule_on_exec_ctx);
126 }
127
~SecurityHandshaker()128 SecurityHandshaker::~SecurityHandshaker() {
129 tsi_handshaker_destroy(handshaker_);
130 tsi_handshaker_result_destroy(handshaker_result_);
131 if (endpoint_to_destroy_ != nullptr) {
132 grpc_endpoint_destroy(endpoint_to_destroy_);
133 }
134 if (read_buffer_to_destroy_ != nullptr) {
135 grpc_slice_buffer_destroy_internal(read_buffer_to_destroy_);
136 gpr_free(read_buffer_to_destroy_);
137 }
138 gpr_free(handshake_buffer_);
139 grpc_slice_buffer_destroy_internal(&outgoing_);
140 auth_context_.reset(DEBUG_LOCATION, "handshake");
141 connector_.reset(DEBUG_LOCATION, "handshake");
142 }
143
MoveReadBufferIntoHandshakeBuffer()144 size_t SecurityHandshaker::MoveReadBufferIntoHandshakeBuffer() {
145 size_t bytes_in_read_buffer = args_->read_buffer->length;
146 if (handshake_buffer_size_ < bytes_in_read_buffer) {
147 handshake_buffer_ = static_cast<uint8_t*>(
148 gpr_realloc(handshake_buffer_, bytes_in_read_buffer));
149 handshake_buffer_size_ = bytes_in_read_buffer;
150 }
151 size_t offset = 0;
152 while (args_->read_buffer->count > 0) {
153 grpc_slice* next_slice = grpc_slice_buffer_peek_first(args_->read_buffer);
154 memcpy(handshake_buffer_ + offset, GRPC_SLICE_START_PTR(*next_slice),
155 GRPC_SLICE_LENGTH(*next_slice));
156 offset += GRPC_SLICE_LENGTH(*next_slice);
157 grpc_slice_buffer_remove_first(args_->read_buffer);
158 }
159 return bytes_in_read_buffer;
160 }
161
162 // Set args_ fields to NULL, saving the endpoint and read buffer for
163 // later destruction.
CleanupArgsForFailureLocked()164 void SecurityHandshaker::CleanupArgsForFailureLocked() {
165 endpoint_to_destroy_ = args_->endpoint;
166 args_->endpoint = nullptr;
167 read_buffer_to_destroy_ = args_->read_buffer;
168 args_->read_buffer = nullptr;
169 grpc_channel_args_destroy(args_->args);
170 args_->args = nullptr;
171 }
172
173 // If the handshake failed or we're shutting down, clean up and invoke the
174 // callback with the error.
HandshakeFailedLocked(grpc_error * error)175 void SecurityHandshaker::HandshakeFailedLocked(grpc_error* error) {
176 if (error == GRPC_ERROR_NONE) {
177 // If we were shut down after the handshake succeeded but before an
178 // endpoint callback was invoked, we need to generate our own error.
179 error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Handshaker shutdown");
180 }
181 const char* msg = grpc_error_string(error);
182 gpr_log(GPR_DEBUG, "Security handshake failed: %s", msg);
183
184 if (!is_shutdown_) {
185 tsi_handshaker_shutdown(handshaker_);
186 // TODO(ctiller): It is currently necessary to shutdown endpoints
187 // before destroying them, even if we know that there are no
188 // pending read/write callbacks. This should be fixed, at which
189 // point this can be removed.
190 grpc_endpoint_shutdown(args_->endpoint, GRPC_ERROR_REF(error));
191 // Not shutting down, so the write failed. Clean up before
192 // invoking the callback.
193 CleanupArgsForFailureLocked();
194 // Set shutdown to true so that subsequent calls to
195 // security_handshaker_shutdown() do nothing.
196 is_shutdown_ = true;
197 }
198 // Invoke callback.
199 ExecCtx::Run(DEBUG_LOCATION, on_handshake_done_, error);
200 }
201
OnPeerCheckedInner(grpc_error * error)202 void SecurityHandshaker::OnPeerCheckedInner(grpc_error* error) {
203 MutexLock lock(&mu_);
204 if (error != GRPC_ERROR_NONE || is_shutdown_) {
205 HandshakeFailedLocked(error);
206 return;
207 }
208 // Create zero-copy frame protector, if implemented.
209 tsi_zero_copy_grpc_protector* zero_copy_protector = nullptr;
210 tsi_result result = tsi_handshaker_result_create_zero_copy_grpc_protector(
211 handshaker_result_, max_frame_size_ == 0 ? nullptr : &max_frame_size_,
212 &zero_copy_protector);
213 if (result != TSI_OK && result != TSI_UNIMPLEMENTED) {
214 error = grpc_set_tsi_error_result(
215 GRPC_ERROR_CREATE_FROM_STATIC_STRING(
216 "Zero-copy frame protector creation failed"),
217 result);
218 HandshakeFailedLocked(error);
219 return;
220 }
221 // Create frame protector if zero-copy frame protector is NULL.
222 tsi_frame_protector* protector = nullptr;
223 if (zero_copy_protector == nullptr) {
224 result = tsi_handshaker_result_create_frame_protector(
225 handshaker_result_, max_frame_size_ == 0 ? nullptr : &max_frame_size_,
226 &protector);
227 if (result != TSI_OK) {
228 error = grpc_set_tsi_error_result(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
229 "Frame protector creation failed"),
230 result);
231 HandshakeFailedLocked(error);
232 return;
233 }
234 }
235 // Get unused bytes.
236 const unsigned char* unused_bytes = nullptr;
237 size_t unused_bytes_size = 0;
238 result = tsi_handshaker_result_get_unused_bytes(
239 handshaker_result_, &unused_bytes, &unused_bytes_size);
240 // Create secure endpoint.
241 if (unused_bytes_size > 0) {
242 grpc_slice slice = grpc_slice_from_copied_buffer(
243 reinterpret_cast<const char*>(unused_bytes), unused_bytes_size);
244 args_->endpoint = grpc_secure_endpoint_create(
245 protector, zero_copy_protector, args_->endpoint, &slice, 1);
246 grpc_slice_unref_internal(slice);
247 } else {
248 args_->endpoint = grpc_secure_endpoint_create(
249 protector, zero_copy_protector, args_->endpoint, nullptr, 0);
250 }
251 tsi_handshaker_result_destroy(handshaker_result_);
252 handshaker_result_ = nullptr;
253 // Add auth context to channel args.
254 grpc_arg auth_context_arg = grpc_auth_context_to_arg(auth_context_.get());
255 grpc_channel_args* tmp_args = args_->args;
256 args_->args = grpc_channel_args_copy_and_add(tmp_args, &auth_context_arg, 1);
257 grpc_channel_args_destroy(tmp_args);
258 // Invoke callback.
259 ExecCtx::Run(DEBUG_LOCATION, on_handshake_done_, GRPC_ERROR_NONE);
260 // Set shutdown to true so that subsequent calls to
261 // security_handshaker_shutdown() do nothing.
262 is_shutdown_ = true;
263 }
264
OnPeerCheckedFn(void * arg,grpc_error * error)265 void SecurityHandshaker::OnPeerCheckedFn(void* arg, grpc_error* error) {
266 RefCountedPtr<SecurityHandshaker>(static_cast<SecurityHandshaker*>(arg))
267 ->OnPeerCheckedInner(GRPC_ERROR_REF(error));
268 }
269
CheckPeerLocked()270 grpc_error* SecurityHandshaker::CheckPeerLocked() {
271 tsi_peer peer;
272 tsi_result result =
273 tsi_handshaker_result_extract_peer(handshaker_result_, &peer);
274 if (result != TSI_OK) {
275 return grpc_set_tsi_error_result(
276 GRPC_ERROR_CREATE_FROM_STATIC_STRING("Peer extraction failed"), result);
277 }
278 connector_->check_peer(peer, args_->endpoint, &auth_context_,
279 &on_peer_checked_);
280 return GRPC_ERROR_NONE;
281 }
282
OnHandshakeNextDoneLocked(tsi_result result,const unsigned char * bytes_to_send,size_t bytes_to_send_size,tsi_handshaker_result * handshaker_result)283 grpc_error* SecurityHandshaker::OnHandshakeNextDoneLocked(
284 tsi_result result, const unsigned char* bytes_to_send,
285 size_t bytes_to_send_size, tsi_handshaker_result* handshaker_result) {
286 grpc_error* error = GRPC_ERROR_NONE;
287 // Handshaker was shutdown.
288 if (is_shutdown_) {
289 return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Handshaker shutdown");
290 }
291 // Read more if we need to.
292 if (result == TSI_INCOMPLETE_DATA) {
293 GPR_ASSERT(bytes_to_send_size == 0);
294 grpc_endpoint_read(
295 args_->endpoint, args_->read_buffer,
296 GRPC_CLOSURE_INIT(
297 &on_handshake_data_received_from_peer_,
298 &SecurityHandshaker::OnHandshakeDataReceivedFromPeerFnScheduler,
299 this, grpc_schedule_on_exec_ctx),
300 /*urgent=*/true);
301 return error;
302 }
303 if (result != TSI_OK) {
304 return grpc_set_tsi_error_result(
305 GRPC_ERROR_CREATE_FROM_STATIC_STRING("Handshake failed"), result);
306 }
307 // Update handshaker result.
308 if (handshaker_result != nullptr) {
309 GPR_ASSERT(handshaker_result_ == nullptr);
310 handshaker_result_ = handshaker_result;
311 }
312 if (bytes_to_send_size > 0) {
313 // Send data to peer, if needed.
314 grpc_slice to_send = grpc_slice_from_copied_buffer(
315 reinterpret_cast<const char*>(bytes_to_send), bytes_to_send_size);
316 grpc_slice_buffer_reset_and_unref_internal(&outgoing_);
317 grpc_slice_buffer_add(&outgoing_, to_send);
318 grpc_endpoint_write(
319 args_->endpoint, &outgoing_,
320 GRPC_CLOSURE_INIT(
321 &on_handshake_data_sent_to_peer_,
322 &SecurityHandshaker::OnHandshakeDataSentToPeerFnScheduler, this,
323 grpc_schedule_on_exec_ctx),
324 nullptr);
325 } else if (handshaker_result == nullptr) {
326 // There is nothing to send, but need to read from peer.
327 grpc_endpoint_read(
328 args_->endpoint, args_->read_buffer,
329 GRPC_CLOSURE_INIT(
330 &on_handshake_data_received_from_peer_,
331 &SecurityHandshaker::OnHandshakeDataReceivedFromPeerFnScheduler,
332 this, grpc_schedule_on_exec_ctx),
333 /*urgent=*/true);
334 } else {
335 // Handshake has finished, check peer and so on.
336 error = CheckPeerLocked();
337 }
338 return error;
339 }
340
OnHandshakeNextDoneGrpcWrapper(tsi_result result,void * user_data,const unsigned char * bytes_to_send,size_t bytes_to_send_size,tsi_handshaker_result * handshaker_result)341 void SecurityHandshaker::OnHandshakeNextDoneGrpcWrapper(
342 tsi_result result, void* user_data, const unsigned char* bytes_to_send,
343 size_t bytes_to_send_size, tsi_handshaker_result* handshaker_result) {
344 RefCountedPtr<SecurityHandshaker> h(
345 static_cast<SecurityHandshaker*>(user_data));
346 MutexLock lock(&h->mu_);
347 grpc_error* error = h->OnHandshakeNextDoneLocked(
348 result, bytes_to_send, bytes_to_send_size, handshaker_result);
349 if (error != GRPC_ERROR_NONE) {
350 h->HandshakeFailedLocked(error);
351 } else {
352 h.release(); // Avoid unref
353 }
354 }
355
DoHandshakerNextLocked(const unsigned char * bytes_received,size_t bytes_received_size)356 grpc_error* SecurityHandshaker::DoHandshakerNextLocked(
357 const unsigned char* bytes_received, size_t bytes_received_size) {
358 // Invoke TSI handshaker.
359 const unsigned char* bytes_to_send = nullptr;
360 size_t bytes_to_send_size = 0;
361 tsi_handshaker_result* hs_result = nullptr;
362 tsi_result result = tsi_handshaker_next(
363 handshaker_, bytes_received, bytes_received_size, &bytes_to_send,
364 &bytes_to_send_size, &hs_result, &OnHandshakeNextDoneGrpcWrapper, this);
365 if (result == TSI_ASYNC) {
366 // Handshaker operating asynchronously. Nothing else to do here;
367 // callback will be invoked in a TSI thread.
368 return GRPC_ERROR_NONE;
369 }
370 // Handshaker returned synchronously. Invoke callback directly in
371 // this thread with our existing exec_ctx.
372 return OnHandshakeNextDoneLocked(result, bytes_to_send, bytes_to_send_size,
373 hs_result);
374 }
375
376 // This callback might be run inline while we are still holding on to the mutex,
377 // so schedule OnHandshakeDataReceivedFromPeerFn on ExecCtx to avoid a deadlock.
OnHandshakeDataReceivedFromPeerFnScheduler(void * arg,grpc_error * error)378 void SecurityHandshaker::OnHandshakeDataReceivedFromPeerFnScheduler(
379 void* arg, grpc_error* error) {
380 SecurityHandshaker* h = static_cast<SecurityHandshaker*>(arg);
381 grpc_core::ExecCtx::Run(
382 DEBUG_LOCATION,
383 GRPC_CLOSURE_INIT(&h->on_handshake_data_received_from_peer_,
384 &SecurityHandshaker::OnHandshakeDataReceivedFromPeerFn,
385 h, grpc_schedule_on_exec_ctx),
386 GRPC_ERROR_REF(error));
387 }
388
OnHandshakeDataReceivedFromPeerFn(void * arg,grpc_error * error)389 void SecurityHandshaker::OnHandshakeDataReceivedFromPeerFn(void* arg,
390 grpc_error* error) {
391 RefCountedPtr<SecurityHandshaker> h(static_cast<SecurityHandshaker*>(arg));
392 MutexLock lock(&h->mu_);
393 if (error != GRPC_ERROR_NONE || h->is_shutdown_) {
394 h->HandshakeFailedLocked(GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
395 "Handshake read failed", &error, 1));
396 return;
397 }
398 // Copy all slices received.
399 size_t bytes_received_size = h->MoveReadBufferIntoHandshakeBuffer();
400 // Call TSI handshaker.
401 error = h->DoHandshakerNextLocked(h->handshake_buffer_, bytes_received_size);
402
403 if (error != GRPC_ERROR_NONE) {
404 h->HandshakeFailedLocked(error);
405 } else {
406 h.release(); // Avoid unref
407 }
408 }
409
410 // This callback might be run inline while we are still holding on to the mutex,
411 // so schedule OnHandshakeDataSentToPeerFn on ExecCtx to avoid a deadlock.
OnHandshakeDataSentToPeerFnScheduler(void * arg,grpc_error * error)412 void SecurityHandshaker::OnHandshakeDataSentToPeerFnScheduler(
413 void* arg, grpc_error* error) {
414 SecurityHandshaker* h = static_cast<SecurityHandshaker*>(arg);
415 grpc_core::ExecCtx::Run(
416 DEBUG_LOCATION,
417 GRPC_CLOSURE_INIT(&h->on_handshake_data_sent_to_peer_,
418 &SecurityHandshaker::OnHandshakeDataSentToPeerFn, h,
419 grpc_schedule_on_exec_ctx),
420 GRPC_ERROR_REF(error));
421 }
422
OnHandshakeDataSentToPeerFn(void * arg,grpc_error * error)423 void SecurityHandshaker::OnHandshakeDataSentToPeerFn(void* arg,
424 grpc_error* error) {
425 RefCountedPtr<SecurityHandshaker> h(static_cast<SecurityHandshaker*>(arg));
426 MutexLock lock(&h->mu_);
427 if (error != GRPC_ERROR_NONE || h->is_shutdown_) {
428 h->HandshakeFailedLocked(GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
429 "Handshake write failed", &error, 1));
430 return;
431 }
432 // We may be done.
433 if (h->handshaker_result_ == nullptr) {
434 grpc_endpoint_read(
435 h->args_->endpoint, h->args_->read_buffer,
436 GRPC_CLOSURE_INIT(
437 &h->on_handshake_data_received_from_peer_,
438 &SecurityHandshaker::OnHandshakeDataReceivedFromPeerFnScheduler,
439 h.get(), grpc_schedule_on_exec_ctx),
440 /*urgent=*/true);
441 } else {
442 error = h->CheckPeerLocked();
443 if (error != GRPC_ERROR_NONE) {
444 h->HandshakeFailedLocked(error);
445 return;
446 }
447 }
448 h.release(); // Avoid unref
449 }
450
451 //
452 // public handshaker API
453 //
454
Shutdown(grpc_error * why)455 void SecurityHandshaker::Shutdown(grpc_error* why) {
456 MutexLock lock(&mu_);
457 if (!is_shutdown_) {
458 is_shutdown_ = true;
459 tsi_handshaker_shutdown(handshaker_);
460 grpc_endpoint_shutdown(args_->endpoint, GRPC_ERROR_REF(why));
461 CleanupArgsForFailureLocked();
462 }
463 GRPC_ERROR_UNREF(why);
464 }
465
DoHandshake(grpc_tcp_server_acceptor *,grpc_closure * on_handshake_done,HandshakerArgs * args)466 void SecurityHandshaker::DoHandshake(grpc_tcp_server_acceptor* /*acceptor*/,
467 grpc_closure* on_handshake_done,
468 HandshakerArgs* args) {
469 auto ref = Ref();
470 MutexLock lock(&mu_);
471 args_ = args;
472 on_handshake_done_ = on_handshake_done;
473 size_t bytes_received_size = MoveReadBufferIntoHandshakeBuffer();
474 grpc_error* error =
475 DoHandshakerNextLocked(handshake_buffer_, bytes_received_size);
476 if (error != GRPC_ERROR_NONE) {
477 HandshakeFailedLocked(error);
478 } else {
479 ref.release(); // Avoid unref
480 }
481 }
482
483 //
484 // FailHandshaker
485 //
486
487 class FailHandshaker : public Handshaker {
488 public:
name() const489 const char* name() const override { return "security_fail"; }
Shutdown(grpc_error * why)490 void Shutdown(grpc_error* why) override { GRPC_ERROR_UNREF(why); }
DoHandshake(grpc_tcp_server_acceptor *,grpc_closure * on_handshake_done,HandshakerArgs *)491 void DoHandshake(grpc_tcp_server_acceptor* /*acceptor*/,
492 grpc_closure* on_handshake_done,
493 HandshakerArgs* /*args*/) override {
494 ExecCtx::Run(DEBUG_LOCATION, on_handshake_done,
495 GRPC_ERROR_CREATE_FROM_STATIC_STRING(
496 "Failed to create security handshaker"));
497 }
498
499 private:
500 ~FailHandshaker() override = default;
501 };
502
503 //
504 // handshaker factories
505 //
506
507 class ClientSecurityHandshakerFactory : public HandshakerFactory {
508 public:
AddHandshakers(const grpc_channel_args * args,grpc_pollset_set * interested_parties,HandshakeManager * handshake_mgr)509 void AddHandshakers(const grpc_channel_args* args,
510 grpc_pollset_set* interested_parties,
511 HandshakeManager* handshake_mgr) override {
512 auto* security_connector =
513 reinterpret_cast<grpc_channel_security_connector*>(
514 grpc_security_connector_find_in_args(args));
515 if (security_connector) {
516 security_connector->add_handshakers(args, interested_parties,
517 handshake_mgr);
518 }
519 }
520 ~ClientSecurityHandshakerFactory() override = default;
521 };
522
523 class ServerSecurityHandshakerFactory : public HandshakerFactory {
524 public:
AddHandshakers(const grpc_channel_args * args,grpc_pollset_set * interested_parties,HandshakeManager * handshake_mgr)525 void AddHandshakers(const grpc_channel_args* args,
526 grpc_pollset_set* interested_parties,
527 HandshakeManager* handshake_mgr) override {
528 auto* security_connector =
529 reinterpret_cast<grpc_server_security_connector*>(
530 grpc_security_connector_find_in_args(args));
531 if (security_connector) {
532 security_connector->add_handshakers(args, interested_parties,
533 handshake_mgr);
534 }
535 }
536 ~ServerSecurityHandshakerFactory() override = default;
537 };
538
539 } // namespace
540
541 //
542 // exported functions
543 //
544
SecurityHandshakerCreate(tsi_handshaker * handshaker,grpc_security_connector * connector,const grpc_channel_args * args)545 RefCountedPtr<Handshaker> SecurityHandshakerCreate(
546 tsi_handshaker* handshaker, grpc_security_connector* connector,
547 const grpc_channel_args* args) {
548 // If no TSI handshaker was created, return a handshaker that always fails.
549 // Otherwise, return a real security handshaker.
550 if (handshaker == nullptr) {
551 return MakeRefCounted<FailHandshaker>();
552 } else {
553 return MakeRefCounted<SecurityHandshaker>(handshaker, connector, args);
554 }
555 }
556
SecurityRegisterHandshakerFactories()557 void SecurityRegisterHandshakerFactories() {
558 HandshakerRegistry::RegisterHandshakerFactory(
559 false /* at_start */, HANDSHAKER_CLIENT,
560 absl::make_unique<ClientSecurityHandshakerFactory>());
561 HandshakerRegistry::RegisterHandshakerFactory(
562 false /* at_start */, HANDSHAKER_SERVER,
563 absl::make_unique<ServerSecurityHandshakerFactory>());
564 }
565
566 } // namespace grpc_core
567
grpc_security_handshaker_create(tsi_handshaker * handshaker,grpc_security_connector * connector,const grpc_channel_args * args)568 grpc_handshaker* grpc_security_handshaker_create(
569 tsi_handshaker* handshaker, grpc_security_connector* connector,
570 const grpc_channel_args* args) {
571 return SecurityHandshakerCreate(handshaker, connector, args).release();
572 }
573