• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *
3  * Copyright 2018 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/security_connector/tls/tls_security_connector.h"
22 
23 #include <stdbool.h>
24 #include <string.h>
25 
26 #include "absl/strings/str_cat.h"
27 #include "absl/strings/string_view.h"
28 
29 #include <grpc/grpc.h>
30 #include <grpc/support/alloc.h>
31 #include <grpc/support/log.h>
32 #include <grpc/support/string_util.h>
33 
34 #include "src/core/lib/gprpp/host_port.h"
35 #include "src/core/lib/security/credentials/ssl/ssl_credentials.h"
36 #include "src/core/lib/security/credentials/tls/tls_credentials.h"
37 #include "src/core/lib/security/security_connector/ssl_utils.h"
38 #include "src/core/lib/security/transport/security_handshaker.h"
39 #include "src/core/lib/slice/slice_internal.h"
40 #include "src/core/lib/transport/transport.h"
41 #include "src/core/tsi/ssl_transport_security.h"
42 #include "src/core/tsi/transport_security.h"
43 
44 namespace grpc_core {
45 
46 namespace {
47 
ConvertToTsiPemKeyCertPair(const grpc_core::PemKeyCertPairList & cert_pair_list)48 tsi_ssl_pem_key_cert_pair* ConvertToTsiPemKeyCertPair(
49     const grpc_core::PemKeyCertPairList& cert_pair_list) {
50   tsi_ssl_pem_key_cert_pair* tsi_pairs = nullptr;
51   size_t num_key_cert_pairs = cert_pair_list.size();
52   if (num_key_cert_pairs > 0) {
53     GPR_ASSERT(cert_pair_list.data() != nullptr);
54     tsi_pairs = static_cast<tsi_ssl_pem_key_cert_pair*>(
55         gpr_zalloc(num_key_cert_pairs * sizeof(tsi_ssl_pem_key_cert_pair)));
56   }
57   for (size_t i = 0; i < num_key_cert_pairs; i++) {
58     GPR_ASSERT(!cert_pair_list[i].private_key().empty());
59     GPR_ASSERT(!cert_pair_list[i].cert_chain().empty());
60     tsi_pairs[i].cert_chain =
61         gpr_strdup(cert_pair_list[i].cert_chain().c_str());
62     tsi_pairs[i].private_key =
63         gpr_strdup(cert_pair_list[i].private_key().c_str());
64   }
65   return tsi_pairs;
66 }
67 
68 }  // namespace
69 
70 // -------------------channel security connector-------------------
71 grpc_core::RefCountedPtr<grpc_channel_security_connector>
CreateTlsChannelSecurityConnector(grpc_core::RefCountedPtr<grpc_channel_credentials> channel_creds,grpc_core::RefCountedPtr<grpc_tls_credentials_options> options,grpc_core::RefCountedPtr<grpc_call_credentials> request_metadata_creds,const char * target_name,const char * overridden_target_name,tsi_ssl_session_cache * ssl_session_cache)72 TlsChannelSecurityConnector::CreateTlsChannelSecurityConnector(
73     grpc_core::RefCountedPtr<grpc_channel_credentials> channel_creds,
74     grpc_core::RefCountedPtr<grpc_tls_credentials_options> options,
75     grpc_core::RefCountedPtr<grpc_call_credentials> request_metadata_creds,
76     const char* target_name, const char* overridden_target_name,
77     tsi_ssl_session_cache* ssl_session_cache) {
78   if (channel_creds == nullptr) {
79     gpr_log(GPR_ERROR,
80             "channel_creds is nullptr in "
81             "TlsChannelSecurityConnectorCreate()");
82     return nullptr;
83   }
84   if (options == nullptr) {
85     gpr_log(GPR_ERROR,
86             "options is nullptr in "
87             "TlsChannelSecurityConnectorCreate()");
88     return nullptr;
89   }
90   if (target_name == nullptr) {
91     gpr_log(GPR_ERROR,
92             "target_name is nullptr in "
93             "TlsChannelSecurityConnectorCreate()");
94     return nullptr;
95   }
96   grpc_core::RefCountedPtr<TlsChannelSecurityConnector> c =
97       grpc_core::MakeRefCounted<TlsChannelSecurityConnector>(
98           std::move(channel_creds), std::move(options),
99           std::move(request_metadata_creds), target_name,
100           overridden_target_name, ssl_session_cache);
101   return c;
102 }
103 
TlsChannelSecurityConnector(grpc_core::RefCountedPtr<grpc_channel_credentials> channel_creds,grpc_core::RefCountedPtr<grpc_tls_credentials_options> options,grpc_core::RefCountedPtr<grpc_call_credentials> request_metadata_creds,const char * target_name,const char * overridden_target_name,tsi_ssl_session_cache * ssl_session_cache)104 TlsChannelSecurityConnector::TlsChannelSecurityConnector(
105     grpc_core::RefCountedPtr<grpc_channel_credentials> channel_creds,
106     grpc_core::RefCountedPtr<grpc_tls_credentials_options> options,
107     grpc_core::RefCountedPtr<grpc_call_credentials> request_metadata_creds,
108     const char* target_name, const char* overridden_target_name,
109     tsi_ssl_session_cache* ssl_session_cache)
110     : grpc_channel_security_connector(GRPC_SSL_URL_SCHEME,
111                                       std::move(channel_creds),
112                                       std::move(request_metadata_creds)),
113       options_(std::move(options)),
114       overridden_target_name_(
115           overridden_target_name == nullptr ? "" : overridden_target_name),
116       ssl_session_cache_(ssl_session_cache) {
117   if (ssl_session_cache_ != nullptr) {
118     tsi_ssl_session_cache_ref(ssl_session_cache_);
119   }
120   check_arg_ = ServerAuthorizationCheckArgCreate(this);
121   absl::string_view host;
122   absl::string_view port;
123   grpc_core::SplitHostPort(target_name, &host, &port);
124   target_name_ = std::string(host);
125   // Create a watcher.
126   auto watcher_ptr = absl::make_unique<TlsChannelCertificateWatcher>(this);
127   certificate_watcher_ = watcher_ptr.get();
128   // Register the watcher with the distributor.
129   grpc_tls_certificate_distributor* distributor =
130       options_->certificate_distributor();
131   absl::optional<std::string> watched_root_cert_name;
132   if (options_->watch_root_cert()) {
133     watched_root_cert_name = options_->root_cert_name();
134   }
135   absl::optional<std::string> watched_identity_cert_name;
136   if (options_->watch_identity_pair()) {
137     watched_identity_cert_name = options_->identity_cert_name();
138   }
139   distributor->WatchTlsCertificates(std::move(watcher_ptr),
140                                     watched_root_cert_name,
141                                     watched_identity_cert_name);
142 }
143 
~TlsChannelSecurityConnector()144 TlsChannelSecurityConnector::~TlsChannelSecurityConnector() {
145   if (ssl_session_cache_ != nullptr) {
146     tsi_ssl_session_cache_unref(ssl_session_cache_);
147   }
148   // Cancel all the watchers.
149   grpc_tls_certificate_distributor* distributor =
150       options_->certificate_distributor();
151   distributor->CancelTlsCertificatesWatch(certificate_watcher_);
152   if (client_handshaker_factory_ != nullptr) {
153     tsi_ssl_client_handshaker_factory_unref(client_handshaker_factory_);
154   }
155   if (check_arg_ != nullptr) {
156     ServerAuthorizationCheckArgDestroy(check_arg_);
157   }
158 }
159 
add_handshakers(const grpc_channel_args * args,grpc_pollset_set *,grpc_core::HandshakeManager * handshake_mgr)160 void TlsChannelSecurityConnector::add_handshakers(
161     const grpc_channel_args* args, grpc_pollset_set* /*interested_parties*/,
162     grpc_core::HandshakeManager* handshake_mgr) {
163   grpc_core::MutexLock lock(&mu_);
164   if (client_handshaker_factory_ != nullptr) {
165     // Instantiate TSI handshaker.
166     tsi_handshaker* tsi_hs = nullptr;
167     tsi_result result = tsi_ssl_client_handshaker_factory_create_handshaker(
168         client_handshaker_factory_,
169         overridden_target_name_.empty() ? target_name_.c_str()
170                                         : overridden_target_name_.c_str(),
171         &tsi_hs);
172     if (result != TSI_OK) {
173       gpr_log(GPR_ERROR, "Handshaker creation failed with error %s.",
174               tsi_result_to_string(result));
175       return;
176     }
177     // Create handshakers.
178     handshake_mgr->Add(grpc_core::SecurityHandshakerCreate(tsi_hs, this, args));
179     return;
180   }
181   // TODO(ZhenLian): Implement the logic(delegation to
182   // BlockOnInitialCredentialHandshaker) when certificates are not ready.
183   gpr_log(GPR_ERROR, "%s not supported yet.",
184           "Client BlockOnInitialCredentialHandshaker");
185 }
186 
check_peer(tsi_peer peer,grpc_endpoint *,grpc_core::RefCountedPtr<grpc_auth_context> * auth_context,grpc_closure * on_peer_checked)187 void TlsChannelSecurityConnector::check_peer(
188     tsi_peer peer, grpc_endpoint* /*ep*/,
189     grpc_core::RefCountedPtr<grpc_auth_context>* auth_context,
190     grpc_closure* on_peer_checked) {
191   const char* target_name = overridden_target_name_.empty()
192                                 ? target_name_.c_str()
193                                 : overridden_target_name_.c_str();
194   grpc_error* error = grpc_ssl_check_alpn(&peer);
195   if (error != GRPC_ERROR_NONE) {
196     grpc_core::ExecCtx::Run(DEBUG_LOCATION, on_peer_checked, error);
197     tsi_peer_destruct(&peer);
198     return;
199   }
200   *auth_context =
201       grpc_ssl_peer_to_auth_context(&peer, GRPC_TLS_TRANSPORT_SECURITY_TYPE);
202   if (options_->server_verification_option() == GRPC_TLS_SERVER_VERIFICATION) {
203     /* Do the default host name check if specifying the target name. */
204     error = internal::TlsCheckHostName(target_name, &peer);
205     if (error != GRPC_ERROR_NONE) {
206       grpc_core::ExecCtx::Run(DEBUG_LOCATION, on_peer_checked, error);
207       tsi_peer_destruct(&peer);
208       return;
209     }
210   }
211   /* Do the custom server authorization check, if specified by the user. */
212   const grpc_tls_server_authorization_check_config* config =
213       options_->server_authorization_check_config();
214   /* If server authorization config is not null, use it to perform
215    * server authorization check. */
216   if (config != nullptr) {
217     const tsi_peer_property* p =
218         tsi_peer_get_property_by_name(&peer, TSI_X509_PEM_CERT_PROPERTY);
219     if (p == nullptr) {
220       error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(
221           "Cannot check peer: missing pem cert property.");
222     } else {
223       char* peer_pem = static_cast<char*>(gpr_zalloc(p->value.length + 1));
224       memcpy(peer_pem, p->value.data, p->value.length);
225       GPR_ASSERT(check_arg_ != nullptr);
226       check_arg_->peer_cert = check_arg_->peer_cert == nullptr
227                                   ? gpr_strdup(peer_pem)
228                                   : check_arg_->peer_cert;
229       check_arg_->target_name = check_arg_->target_name == nullptr
230                                     ? gpr_strdup(target_name)
231                                     : check_arg_->target_name;
232       on_peer_checked_ = on_peer_checked;
233       gpr_free(peer_pem);
234       const tsi_peer_property* chain = tsi_peer_get_property_by_name(
235           &peer, TSI_X509_PEM_CERT_CHAIN_PROPERTY);
236       if (chain != nullptr) {
237         char* peer_pem_chain =
238             static_cast<char*>(gpr_zalloc(chain->value.length + 1));
239         memcpy(peer_pem_chain, chain->value.data, chain->value.length);
240         check_arg_->peer_cert_full_chain =
241             check_arg_->peer_cert_full_chain == nullptr
242                 ? gpr_strdup(peer_pem_chain)
243                 : check_arg_->peer_cert_full_chain;
244         gpr_free(peer_pem_chain);
245       }
246       // TODO(zhenlian) - This should be cleaned up as part of the custom
247       // verification changes. Fill in the subject alternative names
248       std::vector<char*> subject_alternative_names;
249       for (size_t i = 0; i < peer.property_count; i++) {
250         const tsi_peer_property* prop = &peer.properties[i];
251         if (strcmp(prop->name,
252                    TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY) == 0) {
253           char* san = new char[prop->value.length + 1];
254           memcpy(san, prop->value.data, prop->value.length);
255           san[prop->value.length] = '\0';
256           subject_alternative_names.emplace_back(san);
257         }
258       }
259       if (check_arg_->subject_alternative_names != nullptr) {
260         for (size_t i = 0; i < check_arg_->subject_alternative_names_size;
261              ++i) {
262           delete[] check_arg_->subject_alternative_names[i];
263         }
264         delete[] check_arg_->subject_alternative_names;
265       }
266       check_arg_->subject_alternative_names_size =
267           subject_alternative_names.size();
268       if (subject_alternative_names.empty()) {
269         check_arg_->subject_alternative_names = nullptr;
270       } else {
271         check_arg_->subject_alternative_names =
272             new char*[check_arg_->subject_alternative_names_size];
273         for (size_t i = 0; i < check_arg_->subject_alternative_names_size;
274              ++i) {
275           check_arg_->subject_alternative_names[i] =
276               subject_alternative_names[i];
277         }
278       }
279       int callback_status = config->Schedule(check_arg_);
280       /* Server authorization check is handled asynchronously. */
281       if (callback_status) {
282         tsi_peer_destruct(&peer);
283         return;
284       }
285       /* Server authorization check is handled synchronously. */
286       error = ProcessServerAuthorizationCheckResult(check_arg_);
287     }
288   }
289   grpc_core::ExecCtx::Run(DEBUG_LOCATION, on_peer_checked, error);
290   tsi_peer_destruct(&peer);
291 }
292 
cmp(const grpc_security_connector * other_sc) const293 int TlsChannelSecurityConnector::cmp(
294     const grpc_security_connector* other_sc) const {
295   auto* other = reinterpret_cast<const TlsChannelSecurityConnector*>(other_sc);
296   int c = channel_security_connector_cmp(other);
297   if (c != 0) {
298     return c;
299   }
300   return grpc_ssl_cmp_target_name(
301       target_name_.c_str(), other->target_name_.c_str(),
302       overridden_target_name_.c_str(), other->overridden_target_name_.c_str());
303 }
304 
check_call_host(absl::string_view host,grpc_auth_context * auth_context,grpc_closure *,grpc_error ** error)305 bool TlsChannelSecurityConnector::check_call_host(
306     absl::string_view host, grpc_auth_context* auth_context,
307     grpc_closure* /*on_call_host_checked*/, grpc_error** error) {
308   return grpc_ssl_check_call_host(host, target_name_.c_str(),
309                                   overridden_target_name_.c_str(), auth_context,
310                                   error);
311 }
312 
cancel_check_call_host(grpc_closure *,grpc_error * error)313 void TlsChannelSecurityConnector::cancel_check_call_host(
314     grpc_closure* /*on_call_host_checked*/, grpc_error* error) {
315   GRPC_ERROR_UNREF(error);
316 }
317 
318 void TlsChannelSecurityConnector::TlsChannelCertificateWatcher::
OnCertificatesChanged(absl::optional<absl::string_view> root_certs,absl::optional<grpc_core::PemKeyCertPairList> key_cert_pairs)319     OnCertificatesChanged(
320         absl::optional<absl::string_view> root_certs,
321         absl::optional<grpc_core::PemKeyCertPairList> key_cert_pairs) {
322   GPR_ASSERT(security_connector_ != nullptr);
323   grpc_core::MutexLock lock(&security_connector_->mu_);
324   if (root_certs.has_value()) {
325     security_connector_->pem_root_certs_ = root_certs;
326   }
327   if (key_cert_pairs.has_value()) {
328     security_connector_->pem_key_cert_pair_list_ = std::move(key_cert_pairs);
329   }
330   bool root_being_watched = security_connector_->options_->watch_root_cert();
331   bool root_has_value = security_connector_->pem_root_certs_.has_value();
332   bool identity_being_watched =
333       security_connector_->options_->watch_identity_pair();
334   bool identity_has_value =
335       security_connector_->pem_key_cert_pair_list_.has_value();
336   if ((root_being_watched && root_has_value && identity_being_watched &&
337        identity_has_value) ||
338       (root_being_watched && root_has_value && !identity_being_watched) ||
339       (!root_being_watched && identity_being_watched && identity_has_value)) {
340     if (security_connector_->UpdateHandshakerFactoryLocked() !=
341         GRPC_SECURITY_OK) {
342       gpr_log(GPR_ERROR, "Update handshaker factory failed.");
343     }
344   }
345 }
346 
347 // TODO(ZhenLian): implement the logic to signal waiting handshakers once
348 // BlockOnInitialCredentialHandshaker is implemented.
OnError(grpc_error * root_cert_error,grpc_error * identity_cert_error)349 void TlsChannelSecurityConnector::TlsChannelCertificateWatcher::OnError(
350     grpc_error* root_cert_error, grpc_error* identity_cert_error) {
351   if (root_cert_error != GRPC_ERROR_NONE) {
352     gpr_log(GPR_ERROR,
353             "TlsChannelCertificateWatcher getting root_cert_error: %s",
354             grpc_error_string(root_cert_error));
355   }
356   if (identity_cert_error != GRPC_ERROR_NONE) {
357     gpr_log(GPR_ERROR,
358             "TlsChannelCertificateWatcher getting identity_cert_error: %s",
359             grpc_error_string(identity_cert_error));
360   }
361   GRPC_ERROR_UNREF(root_cert_error);
362   GRPC_ERROR_UNREF(identity_cert_error);
363 }
364 
365 // TODO(ZhenLian): implement the logic to signal waiting handshakers once
366 // BlockOnInitialCredentialHandshaker is implemented.
367 grpc_security_status
UpdateHandshakerFactoryLocked()368 TlsChannelSecurityConnector::UpdateHandshakerFactoryLocked() {
369   bool skip_server_certificate_verification =
370       options_->server_verification_option() ==
371       GRPC_TLS_SKIP_ALL_SERVER_VERIFICATION;
372   /* Free the client handshaker factory if exists. */
373   if (client_handshaker_factory_ != nullptr) {
374     tsi_ssl_client_handshaker_factory_unref(client_handshaker_factory_);
375   }
376   std::string pem_root_certs;
377   if (pem_root_certs_.has_value()) {
378     // TODO(ZhenLian): update the underlying TSI layer to use C++ types like
379     // std::string and absl::string_view to avoid making another copy here.
380     pem_root_certs = std::string(*pem_root_certs_);
381   }
382   tsi_ssl_pem_key_cert_pair* pem_key_cert_pair = nullptr;
383   if (pem_key_cert_pair_list_.has_value()) {
384     pem_key_cert_pair = ConvertToTsiPemKeyCertPair(*pem_key_cert_pair_list_);
385   }
386   grpc_security_status status = grpc_ssl_tsi_client_handshaker_factory_init(
387       pem_key_cert_pair,
388       pem_root_certs.empty() ? nullptr : pem_root_certs.c_str(),
389       skip_server_certificate_verification,
390       grpc_get_tsi_tls_version(options_->min_tls_version()),
391       grpc_get_tsi_tls_version(options_->max_tls_version()), ssl_session_cache_,
392       &client_handshaker_factory_);
393   /* Free memory. */
394   if (pem_key_cert_pair != nullptr) {
395     grpc_tsi_ssl_pem_key_cert_pairs_destroy(pem_key_cert_pair, 1);
396   }
397   return status;
398 }
399 
ServerAuthorizationCheckDone(grpc_tls_server_authorization_check_arg * arg)400 void TlsChannelSecurityConnector::ServerAuthorizationCheckDone(
401     grpc_tls_server_authorization_check_arg* arg) {
402   GPR_ASSERT(arg != nullptr);
403   grpc_core::ExecCtx exec_ctx;
404   grpc_error* error = ProcessServerAuthorizationCheckResult(arg);
405   TlsChannelSecurityConnector* connector =
406       static_cast<TlsChannelSecurityConnector*>(arg->cb_user_data);
407   grpc_core::ExecCtx::Run(DEBUG_LOCATION, connector->on_peer_checked_, error);
408 }
409 
ProcessServerAuthorizationCheckResult(grpc_tls_server_authorization_check_arg * arg)410 grpc_error* TlsChannelSecurityConnector::ProcessServerAuthorizationCheckResult(
411     grpc_tls_server_authorization_check_arg* arg) {
412   grpc_error* error = GRPC_ERROR_NONE;
413   /* Server authorization check is cancelled by caller. */
414   if (arg->status == GRPC_STATUS_CANCELLED) {
415     error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(
416         absl::StrCat("Server authorization check is cancelled by the caller "
417                      "with error: ",
418                      arg->error_details->error_details())
419             .c_str());
420   } else if (arg->status == GRPC_STATUS_OK) {
421     /* Server authorization check completed successfully but returned check
422      * failure. */
423     if (!arg->success) {
424       error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(
425           absl::StrCat("Server authorization check failed with error: ",
426                        arg->error_details->error_details())
427               .c_str());
428     }
429     /* Server authorization check did not complete correctly. */
430   } else {
431     error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(
432         absl::StrCat(
433             "Server authorization check did not finish correctly with error: ",
434             arg->error_details->error_details())
435             .c_str());
436   }
437   return error;
438 }
439 
440 grpc_tls_server_authorization_check_arg*
ServerAuthorizationCheckArgCreate(void * user_data)441 TlsChannelSecurityConnector::ServerAuthorizationCheckArgCreate(
442     void* user_data) {
443   grpc_tls_server_authorization_check_arg* arg =
444       new grpc_tls_server_authorization_check_arg();
445   arg->target_name = nullptr;
446   arg->peer_cert = nullptr;
447   arg->peer_cert_full_chain = nullptr;
448   arg->subject_alternative_names = nullptr;
449   arg->subject_alternative_names_size = 0;
450   arg->error_details = new grpc_tls_error_details();
451   arg->cb = ServerAuthorizationCheckDone;
452   arg->cb_user_data = user_data;
453   arg->status = GRPC_STATUS_OK;
454   return arg;
455 }
456 
ServerAuthorizationCheckArgDestroy(grpc_tls_server_authorization_check_arg * arg)457 void TlsChannelSecurityConnector::ServerAuthorizationCheckArgDestroy(
458     grpc_tls_server_authorization_check_arg* arg) {
459   if (arg == nullptr) {
460     return;
461   }
462   gpr_free(const_cast<char*>(arg->target_name));
463   gpr_free(const_cast<char*>(arg->peer_cert));
464   gpr_free(const_cast<char*>(arg->peer_cert_full_chain));
465   for (size_t i = 0; i < arg->subject_alternative_names_size; ++i) {
466     delete[] arg->subject_alternative_names[i];
467   }
468   delete[] arg->subject_alternative_names;
469   delete arg->error_details;
470   if (arg->destroy_context != nullptr) {
471     arg->destroy_context(arg->context);
472   }
473   delete arg;
474 }
475 
476 // -------------------server security connector-------------------
477 grpc_core::RefCountedPtr<grpc_server_security_connector>
CreateTlsServerSecurityConnector(grpc_core::RefCountedPtr<grpc_server_credentials> server_creds,grpc_core::RefCountedPtr<grpc_tls_credentials_options> options)478 TlsServerSecurityConnector::CreateTlsServerSecurityConnector(
479     grpc_core::RefCountedPtr<grpc_server_credentials> server_creds,
480     grpc_core::RefCountedPtr<grpc_tls_credentials_options> options) {
481   if (server_creds == nullptr) {
482     gpr_log(GPR_ERROR,
483             "server_creds is nullptr in "
484             "TlsServerSecurityConnectorCreate()");
485     return nullptr;
486   }
487   if (options == nullptr) {
488     gpr_log(GPR_ERROR,
489             "options is nullptr in "
490             "TlsServerSecurityConnectorCreate()");
491     return nullptr;
492   }
493   grpc_core::RefCountedPtr<TlsServerSecurityConnector> c =
494       grpc_core::MakeRefCounted<TlsServerSecurityConnector>(
495           std::move(server_creds), std::move(options));
496   return c;
497 }
498 
TlsServerSecurityConnector(grpc_core::RefCountedPtr<grpc_server_credentials> server_creds,grpc_core::RefCountedPtr<grpc_tls_credentials_options> options)499 TlsServerSecurityConnector::TlsServerSecurityConnector(
500     grpc_core::RefCountedPtr<grpc_server_credentials> server_creds,
501     grpc_core::RefCountedPtr<grpc_tls_credentials_options> options)
502     : grpc_server_security_connector(GRPC_SSL_URL_SCHEME,
503                                      std::move(server_creds)),
504       options_(std::move(options)) {
505   // Create a watcher.
506   auto watcher_ptr = absl::make_unique<TlsServerCertificateWatcher>(this);
507   certificate_watcher_ = watcher_ptr.get();
508   // Register the watcher with the distributor.
509   grpc_tls_certificate_distributor* distributor =
510       options_->certificate_distributor();
511   absl::optional<std::string> watched_root_cert_name;
512   if (options_->watch_root_cert()) {
513     watched_root_cert_name = options_->root_cert_name();
514   }
515   absl::optional<std::string> watched_identity_cert_name;
516   if (options_->watch_identity_pair()) {
517     watched_identity_cert_name = options_->identity_cert_name();
518   }
519   distributor->WatchTlsCertificates(std::move(watcher_ptr),
520                                     watched_root_cert_name,
521                                     watched_identity_cert_name);
522 }
523 
~TlsServerSecurityConnector()524 TlsServerSecurityConnector::~TlsServerSecurityConnector() {
525   // Cancel all the watchers.
526   grpc_tls_certificate_distributor* distributor =
527       options_->certificate_distributor();
528   distributor->CancelTlsCertificatesWatch(certificate_watcher_);
529   if (server_handshaker_factory_ != nullptr) {
530     tsi_ssl_server_handshaker_factory_unref(server_handshaker_factory_);
531   }
532 }
533 
add_handshakers(const grpc_channel_args * args,grpc_pollset_set *,grpc_core::HandshakeManager * handshake_mgr)534 void TlsServerSecurityConnector::add_handshakers(
535     const grpc_channel_args* args, grpc_pollset_set* /*interested_parties*/,
536     grpc_core::HandshakeManager* handshake_mgr) {
537   grpc_core::MutexLock lock(&mu_);
538   if (server_handshaker_factory_ != nullptr) {
539     // Instantiate TSI handshaker.
540     tsi_handshaker* tsi_hs = nullptr;
541     tsi_result result = tsi_ssl_server_handshaker_factory_create_handshaker(
542         server_handshaker_factory_, &tsi_hs);
543     if (result != TSI_OK) {
544       gpr_log(GPR_ERROR, "Handshaker creation failed with error %s.",
545               tsi_result_to_string(result));
546       return;
547     }
548     // Create handshakers.
549     handshake_mgr->Add(grpc_core::SecurityHandshakerCreate(tsi_hs, this, args));
550     return;
551   }
552   // TODO(ZhenLian): Implement the logic(delegation to
553   // BlockOnInitialCredentialHandshaker) when certificates are not ready.
554   gpr_log(GPR_ERROR, "%s not supported yet.",
555           "Server BlockOnInitialCredentialHandshaker");
556 }
557 
check_peer(tsi_peer peer,grpc_endpoint *,grpc_core::RefCountedPtr<grpc_auth_context> * auth_context,grpc_closure * on_peer_checked)558 void TlsServerSecurityConnector::check_peer(
559     tsi_peer peer, grpc_endpoint* /*ep*/,
560     grpc_core::RefCountedPtr<grpc_auth_context>* auth_context,
561     grpc_closure* on_peer_checked) {
562   grpc_error* error = grpc_ssl_check_alpn(&peer);
563   *auth_context =
564       grpc_ssl_peer_to_auth_context(&peer, GRPC_TLS_TRANSPORT_SECURITY_TYPE);
565   tsi_peer_destruct(&peer);
566   grpc_core::ExecCtx::Run(DEBUG_LOCATION, on_peer_checked, error);
567 }
568 
cmp(const grpc_security_connector * other) const569 int TlsServerSecurityConnector::cmp(
570     const grpc_security_connector* other) const {
571   return server_security_connector_cmp(
572       static_cast<const grpc_server_security_connector*>(other));
573 }
574 
575 void TlsServerSecurityConnector::TlsServerCertificateWatcher::
OnCertificatesChanged(absl::optional<absl::string_view> root_certs,absl::optional<grpc_core::PemKeyCertPairList> key_cert_pairs)576     OnCertificatesChanged(
577         absl::optional<absl::string_view> root_certs,
578         absl::optional<grpc_core::PemKeyCertPairList> key_cert_pairs) {
579   GPR_ASSERT(security_connector_ != nullptr);
580   grpc_core::MutexLock lock(&security_connector_->mu_);
581   if (root_certs.has_value()) {
582     security_connector_->pem_root_certs_ = root_certs;
583   }
584   if (key_cert_pairs.has_value()) {
585     security_connector_->pem_key_cert_pair_list_ = std::move(key_cert_pairs);
586   }
587   bool root_being_watched = security_connector_->options_->watch_root_cert();
588   bool root_has_value = security_connector_->pem_root_certs_.has_value();
589   bool identity_being_watched =
590       security_connector_->options_->watch_identity_pair();
591   bool identity_has_value =
592       security_connector_->pem_key_cert_pair_list_.has_value();
593   if ((root_being_watched && root_has_value && identity_being_watched &&
594        identity_has_value) ||
595       (root_being_watched && root_has_value && !identity_being_watched) ||
596       (!root_being_watched && identity_being_watched && identity_has_value)) {
597     if (security_connector_->UpdateHandshakerFactoryLocked() !=
598         GRPC_SECURITY_OK) {
599       gpr_log(GPR_ERROR, "Update handshaker factory failed.");
600     }
601   }
602 }
603 
604 // TODO(ZhenLian): implement the logic to signal waiting handshakers once
605 // BlockOnInitialCredentialHandshaker is implemented.
OnError(grpc_error * root_cert_error,grpc_error * identity_cert_error)606 void TlsServerSecurityConnector::TlsServerCertificateWatcher::OnError(
607     grpc_error* root_cert_error, grpc_error* identity_cert_error) {
608   if (root_cert_error != GRPC_ERROR_NONE) {
609     gpr_log(GPR_ERROR,
610             "TlsServerCertificateWatcher getting root_cert_error: %s",
611             grpc_error_string(root_cert_error));
612   }
613   if (identity_cert_error != GRPC_ERROR_NONE) {
614     gpr_log(GPR_ERROR,
615             "TlsServerCertificateWatcher getting identity_cert_error: %s",
616             grpc_error_string(identity_cert_error));
617   }
618   GRPC_ERROR_UNREF(root_cert_error);
619   GRPC_ERROR_UNREF(identity_cert_error);
620 }
621 
622 // TODO(ZhenLian): implement the logic to signal waiting handshakers once
623 // BlockOnInitialCredentialHandshaker is implemented.
624 grpc_security_status
UpdateHandshakerFactoryLocked()625 TlsServerSecurityConnector::UpdateHandshakerFactoryLocked() {
626   /* Free the server handshaker factory if exists. */
627   if (server_handshaker_factory_ != nullptr) {
628     tsi_ssl_server_handshaker_factory_unref(server_handshaker_factory_);
629   }
630   // The identity certs on the server side shouldn't be empty.
631   GPR_ASSERT(pem_key_cert_pair_list_.has_value());
632   GPR_ASSERT(!(*pem_key_cert_pair_list_).empty());
633   std::string pem_root_certs;
634   if (pem_root_certs_.has_value()) {
635     // TODO(ZhenLian): update the underlying TSI layer to use C++ types like
636     // std::string and absl::string_view to avoid making another copy here.
637     pem_root_certs = std::string(*pem_root_certs_);
638   }
639   tsi_ssl_pem_key_cert_pair* pem_key_cert_pairs = nullptr;
640   pem_key_cert_pairs = ConvertToTsiPemKeyCertPair(*pem_key_cert_pair_list_);
641   size_t num_key_cert_pairs = (*pem_key_cert_pair_list_).size();
642   grpc_security_status status = grpc_ssl_tsi_server_handshaker_factory_init(
643       pem_key_cert_pairs, num_key_cert_pairs,
644       pem_root_certs.empty() ? nullptr : pem_root_certs.c_str(),
645       options_->cert_request_type(),
646       grpc_get_tsi_tls_version(options_->min_tls_version()),
647       grpc_get_tsi_tls_version(options_->max_tls_version()),
648       &server_handshaker_factory_);
649   /* Free memory. */
650   grpc_tsi_ssl_pem_key_cert_pairs_destroy(pem_key_cert_pairs,
651                                           num_key_cert_pairs);
652   return status;
653 }
654 
655 namespace internal {
656 
TlsCheckHostName(const char * peer_name,const tsi_peer * peer)657 grpc_error* TlsCheckHostName(const char* peer_name, const tsi_peer* peer) {
658   /* Check the peer name if specified. */
659   if (peer_name != nullptr && !grpc_ssl_host_matches_name(peer, peer_name)) {
660     return GRPC_ERROR_CREATE_FROM_COPIED_STRING(
661         absl::StrCat("Peer name ", peer_name, " is not in peer certificate")
662             .c_str());
663   }
664   return GRPC_ERROR_NONE;
665 }
666 
667 }  // namespace internal
668 
669 }  // namespace grpc_core
670