• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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