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