• 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 "src/core/lib/security/security_connector/tls/tls_security_connector.h"
20 
21 #include <grpc/grpc.h>
22 #include <grpc/grpc_security_constants.h>
23 #include <grpc/support/alloc.h>
24 #include <grpc/support/port_platform.h>
25 #include <grpc/support/string_util.h>
26 #include <string.h>
27 
28 #include <memory>
29 #include <utility>
30 #include <vector>
31 
32 #include "absl/functional/bind_front.h"
33 #include "absl/log/check.h"
34 #include "absl/log/log.h"
35 #include "absl/strings/str_cat.h"
36 #include "absl/strings/string_view.h"
37 #include "src/core/handshaker/security/security_handshaker.h"
38 #include "src/core/lib/channel/channel_args.h"
39 #include "src/core/lib/iomgr/exec_ctx.h"
40 #include "src/core/lib/promise/promise.h"
41 #include "src/core/lib/security/context/security_context.h"
42 #include "src/core/lib/security/credentials/credentials.h"
43 #include "src/core/lib/security/credentials/tls/grpc_tls_certificate_verifier.h"
44 #include "src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h"
45 #include "src/core/lib/security/security_connector/ssl_utils.h"
46 #include "src/core/tsi/ssl_transport_security.h"
47 #include "src/core/util/debug_location.h"
48 #include "src/core/util/host_port.h"
49 #include "src/core/util/status_helper.h"
50 
51 namespace grpc_core {
52 
53 namespace {
54 
CopyCoreString(char * src,size_t length)55 char* CopyCoreString(char* src, size_t length) {
56   char* target = static_cast<char*>(gpr_malloc(length + 1));
57   memcpy(target, src, length);
58   target[length] = '\0';
59   return target;
60 }
61 
PendingVerifierRequestInit(const char * target_name,tsi_peer peer,grpc_tls_custom_verification_check_request * request)62 void PendingVerifierRequestInit(
63     const char* target_name, tsi_peer peer,
64     grpc_tls_custom_verification_check_request* request) {
65   CHECK_NE(request, nullptr);
66   // The verifier holds a ref to the security connector, so it's fine to
67   // directly point this to the name cached in the security connector.
68   request->target_name = target_name;
69   // TODO(ZhenLian): avoid the copy when the underlying core implementation used
70   // the null-terminating string.
71   bool has_common_name = false;
72   bool has_peer_cert = false;
73   bool has_peer_cert_full_chain = false;
74   bool has_verified_root_cert_subject = false;
75   std::vector<char*> uri_names;
76   std::vector<char*> dns_names;
77   std::vector<char*> email_names;
78   std::vector<char*> ip_names;
79   for (size_t i = 0; i < peer.property_count; ++i) {
80     const tsi_peer_property* prop = &peer.properties[i];
81     if (prop->name == nullptr) continue;
82     if (strcmp(prop->name, TSI_X509_SUBJECT_COMMON_NAME_PEER_PROPERTY) == 0) {
83       request->peer_info.common_name =
84           CopyCoreString(prop->value.data, prop->value.length);
85       has_common_name = true;
86     } else if (strcmp(prop->name, TSI_X509_PEM_CERT_PROPERTY) == 0) {
87       request->peer_info.peer_cert =
88           CopyCoreString(prop->value.data, prop->value.length);
89       has_peer_cert = true;
90     } else if (strcmp(prop->name, TSI_X509_PEM_CERT_CHAIN_PROPERTY) == 0) {
91       request->peer_info.peer_cert_full_chain =
92           CopyCoreString(prop->value.data, prop->value.length);
93       has_peer_cert_full_chain = true;
94     } else if (strcmp(prop->name, TSI_X509_URI_PEER_PROPERTY) == 0) {
95       char* uri = CopyCoreString(prop->value.data, prop->value.length);
96       uri_names.emplace_back(uri);
97     } else if (strcmp(prop->name, TSI_X509_DNS_PEER_PROPERTY) == 0) {
98       char* dns = CopyCoreString(prop->value.data, prop->value.length);
99       dns_names.emplace_back(dns);
100     } else if (strcmp(prop->name, TSI_X509_EMAIL_PEER_PROPERTY) == 0) {
101       char* email = CopyCoreString(prop->value.data, prop->value.length);
102       email_names.emplace_back(email);
103     } else if (strcmp(prop->name, TSI_X509_IP_PEER_PROPERTY) == 0) {
104       char* ip = CopyCoreString(prop->value.data, prop->value.length);
105       ip_names.emplace_back(ip);
106     } else if (strcmp(prop->name,
107                       TSI_X509_VERIFIED_ROOT_CERT_SUBECT_PEER_PROPERTY) == 0) {
108       request->peer_info.verified_root_cert_subject =
109           CopyCoreString(prop->value.data, prop->value.length);
110       has_verified_root_cert_subject = true;
111     }
112   }
113   if (!has_common_name) {
114     request->peer_info.common_name = nullptr;
115   }
116   if (!has_peer_cert) {
117     request->peer_info.peer_cert = nullptr;
118   }
119   if (!has_peer_cert_full_chain) {
120     request->peer_info.peer_cert_full_chain = nullptr;
121   }
122   if (!has_verified_root_cert_subject) {
123     request->peer_info.verified_root_cert_subject = nullptr;
124   }
125   request->peer_info.san_names.uri_names_size = uri_names.size();
126   if (!uri_names.empty()) {
127     request->peer_info.san_names.uri_names =
128         new char*[request->peer_info.san_names.uri_names_size];
129     for (size_t i = 0; i < request->peer_info.san_names.uri_names_size; ++i) {
130       // We directly point the char* string stored in vector to the |request|.
131       // That string will be released when the |request| is destroyed.
132       request->peer_info.san_names.uri_names[i] = uri_names[i];
133     }
134   } else {
135     request->peer_info.san_names.uri_names = nullptr;
136   }
137   request->peer_info.san_names.dns_names_size = dns_names.size();
138   if (!dns_names.empty()) {
139     request->peer_info.san_names.dns_names =
140         new char*[request->peer_info.san_names.dns_names_size];
141     for (size_t i = 0; i < request->peer_info.san_names.dns_names_size; ++i) {
142       // We directly point the char* string stored in vector to the |request|.
143       // That string will be released when the |request| is destroyed.
144       request->peer_info.san_names.dns_names[i] = dns_names[i];
145     }
146   } else {
147     request->peer_info.san_names.dns_names = nullptr;
148   }
149   request->peer_info.san_names.email_names_size = email_names.size();
150   if (!email_names.empty()) {
151     request->peer_info.san_names.email_names =
152         new char*[request->peer_info.san_names.email_names_size];
153     for (size_t i = 0; i < request->peer_info.san_names.email_names_size; ++i) {
154       // We directly point the char* string stored in vector to the |request|.
155       // That string will be released when the |request| is destroyed.
156       request->peer_info.san_names.email_names[i] = email_names[i];
157     }
158   } else {
159     request->peer_info.san_names.email_names = nullptr;
160   }
161   request->peer_info.san_names.ip_names_size = ip_names.size();
162   if (!ip_names.empty()) {
163     request->peer_info.san_names.ip_names =
164         new char*[request->peer_info.san_names.ip_names_size];
165     for (size_t i = 0; i < request->peer_info.san_names.ip_names_size; ++i) {
166       // We directly point the char* string stored in vector to the |request|.
167       // That string will be released when the |request| is destroyed.
168       request->peer_info.san_names.ip_names[i] = ip_names[i];
169     }
170   } else {
171     request->peer_info.san_names.ip_names = nullptr;
172   }
173 }
174 
PendingVerifierRequestDestroy(grpc_tls_custom_verification_check_request * request)175 void PendingVerifierRequestDestroy(
176     grpc_tls_custom_verification_check_request* request) {
177   CHECK_NE(request, nullptr);
178   if (request->peer_info.common_name != nullptr) {
179     gpr_free(const_cast<char*>(request->peer_info.common_name));
180   }
181   if (request->peer_info.san_names.uri_names_size > 0) {
182     for (size_t i = 0; i < request->peer_info.san_names.uri_names_size; ++i) {
183       gpr_free(request->peer_info.san_names.uri_names[i]);
184     }
185     delete[] request->peer_info.san_names.uri_names;
186   }
187   if (request->peer_info.san_names.dns_names_size > 0) {
188     for (size_t i = 0; i < request->peer_info.san_names.dns_names_size; ++i) {
189       gpr_free(request->peer_info.san_names.dns_names[i]);
190     }
191     delete[] request->peer_info.san_names.dns_names;
192   }
193   if (request->peer_info.san_names.email_names_size > 0) {
194     for (size_t i = 0; i < request->peer_info.san_names.email_names_size; ++i) {
195       gpr_free(request->peer_info.san_names.email_names[i]);
196     }
197     delete[] request->peer_info.san_names.email_names;
198   }
199   if (request->peer_info.san_names.ip_names_size > 0) {
200     for (size_t i = 0; i < request->peer_info.san_names.ip_names_size; ++i) {
201       gpr_free(request->peer_info.san_names.ip_names[i]);
202     }
203     delete[] request->peer_info.san_names.ip_names;
204   }
205   if (request->peer_info.peer_cert != nullptr) {
206     gpr_free(const_cast<char*>(request->peer_info.peer_cert));
207   }
208   if (request->peer_info.peer_cert_full_chain != nullptr) {
209     gpr_free(const_cast<char*>(request->peer_info.peer_cert_full_chain));
210   }
211   if (request->peer_info.verified_root_cert_subject != nullptr) {
212     gpr_free(const_cast<char*>(request->peer_info.verified_root_cert_subject));
213   }
214 }
215 
ConvertToTsiPemKeyCertPair(const PemKeyCertPairList & cert_pair_list)216 tsi_ssl_pem_key_cert_pair* ConvertToTsiPemKeyCertPair(
217     const PemKeyCertPairList& cert_pair_list) {
218   tsi_ssl_pem_key_cert_pair* tsi_pairs = nullptr;
219   size_t num_key_cert_pairs = cert_pair_list.size();
220   if (num_key_cert_pairs > 0) {
221     CHECK_NE(cert_pair_list.data(), nullptr);
222     tsi_pairs = static_cast<tsi_ssl_pem_key_cert_pair*>(
223         gpr_zalloc(num_key_cert_pairs * sizeof(tsi_ssl_pem_key_cert_pair)));
224   }
225   for (size_t i = 0; i < num_key_cert_pairs; i++) {
226     CHECK(!cert_pair_list[i].private_key().empty());
227     CHECK(!cert_pair_list[i].cert_chain().empty());
228     tsi_pairs[i].cert_chain =
229         gpr_strdup(cert_pair_list[i].cert_chain().c_str());
230     tsi_pairs[i].private_key =
231         gpr_strdup(cert_pair_list[i].private_key().c_str());
232   }
233   return tsi_pairs;
234 }
235 
236 }  // namespace
237 
238 // -------------------channel security connector-------------------
239 RefCountedPtr<grpc_channel_security_connector>
CreateTlsChannelSecurityConnector(RefCountedPtr<grpc_channel_credentials> channel_creds,RefCountedPtr<grpc_tls_credentials_options> options,RefCountedPtr<grpc_call_credentials> request_metadata_creds,const char * target_name,const char * overridden_target_name,tsi_ssl_session_cache * ssl_session_cache)240 TlsChannelSecurityConnector::CreateTlsChannelSecurityConnector(
241     RefCountedPtr<grpc_channel_credentials> channel_creds,
242     RefCountedPtr<grpc_tls_credentials_options> options,
243     RefCountedPtr<grpc_call_credentials> request_metadata_creds,
244     const char* target_name, const char* overridden_target_name,
245     tsi_ssl_session_cache* ssl_session_cache) {
246   if (channel_creds == nullptr) {
247     LOG(ERROR) << "channel_creds is nullptr in "
248                   "TlsChannelSecurityConnectorCreate()";
249     return nullptr;
250   }
251   if (options == nullptr) {
252     LOG(ERROR) << "options is nullptr in "
253                   "TlsChannelSecurityConnectorCreate()";
254     return nullptr;
255   }
256   if (target_name == nullptr) {
257     LOG(ERROR) << "target_name is nullptr in "
258                   "TlsChannelSecurityConnectorCreate()";
259     return nullptr;
260   }
261   return MakeRefCounted<TlsChannelSecurityConnector>(
262       std::move(channel_creds), std::move(options),
263       std::move(request_metadata_creds), target_name, overridden_target_name,
264       ssl_session_cache);
265 }
266 
TlsChannelSecurityConnector(RefCountedPtr<grpc_channel_credentials> channel_creds,RefCountedPtr<grpc_tls_credentials_options> options,RefCountedPtr<grpc_call_credentials> request_metadata_creds,const char * target_name,const char * overridden_target_name,tsi_ssl_session_cache * ssl_session_cache)267 TlsChannelSecurityConnector::TlsChannelSecurityConnector(
268     RefCountedPtr<grpc_channel_credentials> channel_creds,
269     RefCountedPtr<grpc_tls_credentials_options> options,
270     RefCountedPtr<grpc_call_credentials> request_metadata_creds,
271     const char* target_name, const char* overridden_target_name,
272     tsi_ssl_session_cache* ssl_session_cache)
273     : grpc_channel_security_connector(GRPC_SSL_URL_SCHEME,
274                                       std::move(channel_creds),
275                                       std::move(request_metadata_creds)),
276       options_(std::move(options)),
277       overridden_target_name_(
278           overridden_target_name == nullptr ? "" : overridden_target_name),
279       ssl_session_cache_(ssl_session_cache) {
280   const std::string& tls_session_key_log_file_path =
281       options_->tls_session_key_log_file_path();
282   if (!tls_session_key_log_file_path.empty()) {
283     tls_session_key_logger_ =
284         tsi::TlsSessionKeyLoggerCache::Get(tls_session_key_log_file_path);
285   }
286   if (ssl_session_cache_ != nullptr) {
287     tsi_ssl_session_cache_ref(ssl_session_cache_);
288   }
289   absl::string_view host;
290   absl::string_view port;
291   SplitHostPort(target_name, &host, &port);
292   target_name_ = std::string(host);
293   // Create a watcher.
294   auto watcher_ptr = std::make_unique<TlsChannelCertificateWatcher>(this);
295   certificate_watcher_ = watcher_ptr.get();
296   // Register the watcher with the distributor.
297   grpc_tls_certificate_distributor* distributor =
298       options_->certificate_distributor();
299   absl::optional<std::string> watched_root_cert_name;
300   if (options_->watch_root_cert()) {
301     watched_root_cert_name = options_->root_cert_name();
302   }
303   absl::optional<std::string> watched_identity_cert_name;
304   if (options_->watch_identity_pair()) {
305     watched_identity_cert_name = options_->identity_cert_name();
306   }
307   // We will use the root certs stored in system default locations if not
308   // watching root certs on the client side. We will handle this case
309   // differently here, because "watching a default roots without the identity
310   // certs" is a valid case(and hence we will need to call
311   // OnCertificatesChanged), but it requires nothing from the provider, and
312   // hence no need to register the watcher.
313   bool use_default_roots = !options_->watch_root_cert();
314   if (use_default_roots && !options_->watch_identity_pair()) {
315     watcher_ptr->OnCertificatesChanged(absl::nullopt, absl::nullopt);
316   } else {
317     distributor->WatchTlsCertificates(std::move(watcher_ptr),
318                                       watched_root_cert_name,
319                                       watched_identity_cert_name);
320   }
321 }
322 
~TlsChannelSecurityConnector()323 TlsChannelSecurityConnector::~TlsChannelSecurityConnector() {
324   if (ssl_session_cache_ != nullptr) {
325     tsi_ssl_session_cache_unref(ssl_session_cache_);
326   }
327   // Cancel all the watchers.
328   grpc_tls_certificate_distributor* distributor =
329       options_->certificate_distributor();
330   if (distributor != nullptr) {
331     distributor->CancelTlsCertificatesWatch(certificate_watcher_);
332   }
333   if (client_handshaker_factory_ != nullptr) {
334     tsi_ssl_client_handshaker_factory_unref(client_handshaker_factory_);
335   }
336 }
337 
add_handshakers(const ChannelArgs & args,grpc_pollset_set *,HandshakeManager * handshake_mgr)338 void TlsChannelSecurityConnector::add_handshakers(
339     const ChannelArgs& args, grpc_pollset_set* /*interested_parties*/,
340     HandshakeManager* handshake_mgr) {
341   MutexLock lock(&mu_);
342   tsi_handshaker* tsi_hs = nullptr;
343   if (client_handshaker_factory_ != nullptr) {
344     // Instantiate TSI handshaker.
345     tsi_result result = tsi_ssl_client_handshaker_factory_create_handshaker(
346         client_handshaker_factory_,
347         overridden_target_name_.empty() ? target_name_.c_str()
348                                         : overridden_target_name_.c_str(),
349         /*network_bio_buf_size=*/0,
350         /*ssl_bio_buf_size=*/0, &tsi_hs);
351     if (result != TSI_OK) {
352       LOG(ERROR) << "Handshaker creation failed with error "
353                  << tsi_result_to_string(result);
354     }
355   }
356   // If tsi_hs is null, this will add a failing handshaker.
357   handshake_mgr->Add(SecurityHandshakerCreate(tsi_hs, this, args));
358 }
359 
check_peer(tsi_peer peer,grpc_endpoint *,const ChannelArgs &,RefCountedPtr<grpc_auth_context> * auth_context,grpc_closure * on_peer_checked)360 void TlsChannelSecurityConnector::check_peer(
361     tsi_peer peer, grpc_endpoint* /*ep*/, const ChannelArgs& /*args*/,
362     RefCountedPtr<grpc_auth_context>* auth_context,
363     grpc_closure* on_peer_checked) {
364   const char* target_name = overridden_target_name_.empty()
365                                 ? target_name_.c_str()
366                                 : overridden_target_name_.c_str();
367   grpc_error_handle error = grpc_ssl_check_alpn(&peer);
368   if (!error.ok()) {
369     ExecCtx::Run(DEBUG_LOCATION, on_peer_checked, error);
370     tsi_peer_destruct(&peer);
371     return;
372   }
373   *auth_context =
374       grpc_ssl_peer_to_auth_context(&peer, GRPC_TLS_TRANSPORT_SECURITY_TYPE);
375   CHECK_NE(options_->certificate_verifier(), nullptr);
376   auto* pending_request = new ChannelPendingVerifierRequest(
377       RefAsSubclass<TlsChannelSecurityConnector>(), on_peer_checked, peer,
378       target_name);
379   {
380     MutexLock lock(&verifier_request_map_mu_);
381     pending_verifier_requests_.emplace(on_peer_checked, pending_request);
382   }
383   pending_request->Start();
384 }
385 
cancel_check_peer(grpc_closure * on_peer_checked,grpc_error_handle)386 void TlsChannelSecurityConnector::cancel_check_peer(
387     grpc_closure* on_peer_checked, grpc_error_handle /*error*/) {
388   auto* verifier = options_->certificate_verifier();
389   if (verifier != nullptr) {
390     grpc_tls_custom_verification_check_request* pending_verifier_request =
391         nullptr;
392     {
393       MutexLock lock(&verifier_request_map_mu_);
394       auto it = pending_verifier_requests_.find(on_peer_checked);
395       if (it != pending_verifier_requests_.end()) {
396         pending_verifier_request = it->second->request();
397       } else {
398         VLOG(2) << "TlsChannelSecurityConnector::cancel_check_peer: no "
399                    "corresponding pending request found";
400       }
401     }
402     if (pending_verifier_request != nullptr) {
403       verifier->Cancel(pending_verifier_request);
404     }
405   }
406 }
407 
cmp(const grpc_security_connector * other_sc) const408 int TlsChannelSecurityConnector::cmp(
409     const grpc_security_connector* other_sc) const {
410   auto* other = reinterpret_cast<const TlsChannelSecurityConnector*>(other_sc);
411   int c = channel_security_connector_cmp(other);
412   if (c != 0) return c;
413   c = grpc_ssl_cmp_target_name(
414       target_name_.c_str(), other->target_name_.c_str(),
415       overridden_target_name_.c_str(), other->overridden_target_name_.c_str());
416   if (c != 0) return c;
417   return 0;
418 }
419 
CheckCallHost(absl::string_view host,grpc_auth_context * auth_context)420 ArenaPromise<absl::Status> TlsChannelSecurityConnector::CheckCallHost(
421     absl::string_view host, grpc_auth_context* auth_context) {
422   if (options_->check_call_host()) {
423     return Immediate(SslCheckCallHost(host, target_name_.c_str(),
424                                       overridden_target_name_.c_str(),
425                                       auth_context));
426   }
427   return ImmediateOkStatus();
428 }
429 
430 void TlsChannelSecurityConnector::TlsChannelCertificateWatcher::
OnCertificatesChanged(absl::optional<absl::string_view> root_certs,absl::optional<PemKeyCertPairList> key_cert_pairs)431     OnCertificatesChanged(absl::optional<absl::string_view> root_certs,
432                           absl::optional<PemKeyCertPairList> key_cert_pairs) {
433   CHECK_NE(security_connector_, nullptr);
434   MutexLock lock(&security_connector_->mu_);
435   if (root_certs.has_value()) {
436     security_connector_->pem_root_certs_ = root_certs;
437   }
438   if (key_cert_pairs.has_value()) {
439     security_connector_->pem_key_cert_pair_list_ = std::move(key_cert_pairs);
440   }
441   const bool root_ready = !security_connector_->options_->watch_root_cert() ||
442                           security_connector_->pem_root_certs_.has_value();
443   const bool identity_ready =
444       !security_connector_->options_->watch_identity_pair() ||
445       security_connector_->pem_key_cert_pair_list_.has_value();
446   if (root_ready && identity_ready) {
447     if (security_connector_->UpdateHandshakerFactoryLocked() !=
448         GRPC_SECURITY_OK) {
449       LOG(ERROR) << "Update handshaker factory failed.";
450     }
451   }
452 }
453 
454 // TODO(ZhenLian): implement the logic to signal waiting handshakers once
455 // BlockOnInitialCredentialHandshaker is implemented.
OnError(grpc_error_handle root_cert_error,grpc_error_handle identity_cert_error)456 void TlsChannelSecurityConnector::TlsChannelCertificateWatcher::OnError(
457     grpc_error_handle root_cert_error, grpc_error_handle identity_cert_error) {
458   if (!root_cert_error.ok()) {
459     LOG(ERROR) << "TlsChannelCertificateWatcher getting root_cert_error: "
460                << StatusToString(root_cert_error);
461   }
462   if (!identity_cert_error.ok()) {
463     LOG(ERROR) << "TlsChannelCertificateWatcher getting identity_cert_error: "
464                << StatusToString(identity_cert_error);
465   }
466 }
467 
468 TlsChannelSecurityConnector::ChannelPendingVerifierRequest::
ChannelPendingVerifierRequest(RefCountedPtr<TlsChannelSecurityConnector> security_connector,grpc_closure * on_peer_checked,tsi_peer peer,const char * target_name)469     ChannelPendingVerifierRequest(
470         RefCountedPtr<TlsChannelSecurityConnector> security_connector,
471         grpc_closure* on_peer_checked, tsi_peer peer, const char* target_name)
472     : security_connector_(std::move(security_connector)),
473       on_peer_checked_(on_peer_checked) {
474   PendingVerifierRequestInit(target_name, peer, &request_);
475   tsi_peer_destruct(&peer);
476 }
477 
478 TlsChannelSecurityConnector::ChannelPendingVerifierRequest::
~ChannelPendingVerifierRequest()479     ~ChannelPendingVerifierRequest() {
480   PendingVerifierRequestDestroy(&request_);
481 }
482 
Start()483 void TlsChannelSecurityConnector::ChannelPendingVerifierRequest::Start() {
484   absl::Status sync_status;
485   grpc_tls_certificate_verifier* verifier =
486       security_connector_->options_->certificate_verifier();
487   bool is_done = verifier->Verify(
488       &request_,
489       absl::bind_front(&ChannelPendingVerifierRequest::OnVerifyDone, this,
490                        true),
491       &sync_status);
492   if (is_done) {
493     OnVerifyDone(false, sync_status);
494   }
495 }
496 
OnVerifyDone(bool run_callback_inline,absl::Status status)497 void TlsChannelSecurityConnector::ChannelPendingVerifierRequest::OnVerifyDone(
498     bool run_callback_inline, absl::Status status) {
499   {
500     MutexLock lock(&security_connector_->verifier_request_map_mu_);
501     security_connector_->pending_verifier_requests_.erase(on_peer_checked_);
502   }
503   grpc_error_handle error;
504   if (!status.ok()) {
505     error = GRPC_ERROR_CREATE(
506         absl::StrCat("Custom verification check failed with error: ",
507                      status.ToString())
508             .c_str());
509   }
510   if (run_callback_inline) {
511     Closure::Run(DEBUG_LOCATION, on_peer_checked_, error);
512   } else {
513     ExecCtx::Run(DEBUG_LOCATION, on_peer_checked_, error);
514   }
515   delete this;
516 }
517 
518 // TODO(ZhenLian): implement the logic to signal waiting handshakers once
519 // BlockOnInitialCredentialHandshaker is implemented.
520 grpc_security_status
UpdateHandshakerFactoryLocked()521 TlsChannelSecurityConnector::UpdateHandshakerFactoryLocked() {
522   bool skip_server_certificate_verification = !options_->verify_server_cert();
523   // Free the client handshaker factory if exists.
524   if (client_handshaker_factory_ != nullptr) {
525     tsi_ssl_client_handshaker_factory_unref(client_handshaker_factory_);
526   }
527   std::string pem_root_certs;
528   if (pem_root_certs_.has_value()) {
529     // TODO(ZhenLian): update the underlying TSI layer to use C++ types like
530     // std::string and absl::string_view to avoid making another copy here.
531     pem_root_certs = std::string(*pem_root_certs_);
532   }
533   tsi_ssl_pem_key_cert_pair* pem_key_cert_pair = nullptr;
534   if (pem_key_cert_pair_list_.has_value()) {
535     pem_key_cert_pair = ConvertToTsiPemKeyCertPair(*pem_key_cert_pair_list_);
536   }
537   bool use_default_roots = !options_->watch_root_cert();
538   grpc_security_status status = grpc_ssl_tsi_client_handshaker_factory_init(
539       pem_key_cert_pair,
540       pem_root_certs.empty() || use_default_roots ? nullptr
541                                                   : pem_root_certs.c_str(),
542       skip_server_certificate_verification,
543       grpc_get_tsi_tls_version(options_->min_tls_version()),
544       grpc_get_tsi_tls_version(options_->max_tls_version()), ssl_session_cache_,
545       tls_session_key_logger_.get(), options_->crl_directory().c_str(),
546       options_->crl_provider(), &client_handshaker_factory_);
547   // Free memory.
548   if (pem_key_cert_pair != nullptr) {
549     grpc_tsi_ssl_pem_key_cert_pairs_destroy(pem_key_cert_pair, 1);
550   }
551   return status;
552 }
553 
554 // -------------------server security connector-------------------
555 RefCountedPtr<grpc_server_security_connector>
CreateTlsServerSecurityConnector(RefCountedPtr<grpc_server_credentials> server_creds,RefCountedPtr<grpc_tls_credentials_options> options)556 TlsServerSecurityConnector::CreateTlsServerSecurityConnector(
557     RefCountedPtr<grpc_server_credentials> server_creds,
558     RefCountedPtr<grpc_tls_credentials_options> options) {
559   if (server_creds == nullptr) {
560     LOG(ERROR) << "server_creds is nullptr in "
561                   "TlsServerSecurityConnectorCreate()";
562     return nullptr;
563   }
564   if (options == nullptr) {
565     LOG(ERROR) << "options is nullptr in "
566                   "TlsServerSecurityConnectorCreate()";
567     return nullptr;
568   }
569   return MakeRefCounted<TlsServerSecurityConnector>(std::move(server_creds),
570                                                     std::move(options));
571 }
572 
TlsServerSecurityConnector(RefCountedPtr<grpc_server_credentials> server_creds,RefCountedPtr<grpc_tls_credentials_options> options)573 TlsServerSecurityConnector::TlsServerSecurityConnector(
574     RefCountedPtr<grpc_server_credentials> server_creds,
575     RefCountedPtr<grpc_tls_credentials_options> options)
576     : grpc_server_security_connector(GRPC_SSL_URL_SCHEME,
577                                      std::move(server_creds)),
578       options_(std::move(options)) {
579   const std::string& tls_session_key_log_file_path =
580       options_->tls_session_key_log_file_path();
581   if (!tls_session_key_log_file_path.empty()) {
582     tls_session_key_logger_ =
583         tsi::TlsSessionKeyLoggerCache::Get(tls_session_key_log_file_path);
584   }
585   // Create a watcher.
586   auto watcher_ptr = std::make_unique<TlsServerCertificateWatcher>(this);
587   certificate_watcher_ = watcher_ptr.get();
588   // Register the watcher with the distributor.
589   grpc_tls_certificate_distributor* distributor =
590       options_->certificate_distributor();
591   absl::optional<std::string> watched_root_cert_name;
592   if (options_->watch_root_cert()) {
593     watched_root_cert_name = options_->root_cert_name();
594   }
595   absl::optional<std::string> watched_identity_cert_name;
596   if (options_->watch_identity_pair()) {
597     watched_identity_cert_name = options_->identity_cert_name();
598   }
599   // Server side won't use default system roots at any time.
600   distributor->WatchTlsCertificates(std::move(watcher_ptr),
601                                     watched_root_cert_name,
602                                     watched_identity_cert_name);
603 }
604 
~TlsServerSecurityConnector()605 TlsServerSecurityConnector::~TlsServerSecurityConnector() {
606   // Cancel all the watchers.
607   grpc_tls_certificate_distributor* distributor =
608       options_->certificate_distributor();
609   distributor->CancelTlsCertificatesWatch(certificate_watcher_);
610   if (server_handshaker_factory_ != nullptr) {
611     tsi_ssl_server_handshaker_factory_unref(server_handshaker_factory_);
612   }
613 }
614 
add_handshakers(const ChannelArgs & args,grpc_pollset_set *,HandshakeManager * handshake_mgr)615 void TlsServerSecurityConnector::add_handshakers(
616     const ChannelArgs& args, grpc_pollset_set* /*interested_parties*/,
617     HandshakeManager* handshake_mgr) {
618   MutexLock lock(&mu_);
619   tsi_handshaker* tsi_hs = nullptr;
620   if (server_handshaker_factory_ != nullptr) {
621     // Instantiate TSI handshaker.
622     tsi_result result = tsi_ssl_server_handshaker_factory_create_handshaker(
623         server_handshaker_factory_, /*network_bio_buf_size=*/0,
624         /*ssl_bio_buf_size=*/0, &tsi_hs);
625     if (result != TSI_OK) {
626       LOG(ERROR) << "Handshaker creation failed with error "
627                  << tsi_result_to_string(result);
628     }
629   }
630   // If tsi_hs is null, this will add a failing handshaker.
631   handshake_mgr->Add(SecurityHandshakerCreate(tsi_hs, this, args));
632 }
633 
check_peer(tsi_peer peer,grpc_endpoint *,const ChannelArgs &,RefCountedPtr<grpc_auth_context> * auth_context,grpc_closure * on_peer_checked)634 void TlsServerSecurityConnector::check_peer(
635     tsi_peer peer, grpc_endpoint* /*ep*/, const ChannelArgs& /*args*/,
636     RefCountedPtr<grpc_auth_context>* auth_context,
637     grpc_closure* on_peer_checked) {
638   grpc_error_handle error = grpc_ssl_check_alpn(&peer);
639   if (!error.ok()) {
640     ExecCtx::Run(DEBUG_LOCATION, on_peer_checked, error);
641     tsi_peer_destruct(&peer);
642     return;
643   }
644   *auth_context =
645       grpc_ssl_peer_to_auth_context(&peer, GRPC_TLS_TRANSPORT_SECURITY_TYPE);
646   if (options_->certificate_verifier() != nullptr) {
647     auto* pending_request = new ServerPendingVerifierRequest(
648         RefAsSubclass<TlsServerSecurityConnector>(), on_peer_checked, peer);
649     {
650       MutexLock lock(&verifier_request_map_mu_);
651       pending_verifier_requests_.emplace(on_peer_checked, pending_request);
652     }
653     pending_request->Start();
654   } else {
655     tsi_peer_destruct(&peer);
656     ExecCtx::Run(DEBUG_LOCATION, on_peer_checked, error);
657   }
658 }
659 
cancel_check_peer(grpc_closure * on_peer_checked,grpc_error_handle)660 void TlsServerSecurityConnector::cancel_check_peer(
661     grpc_closure* on_peer_checked, grpc_error_handle /*error*/) {
662   auto* verifier = options_->certificate_verifier();
663   if (verifier != nullptr) {
664     grpc_tls_custom_verification_check_request* pending_verifier_request =
665         nullptr;
666     {
667       MutexLock lock(&verifier_request_map_mu_);
668       auto it = pending_verifier_requests_.find(on_peer_checked);
669       if (it != pending_verifier_requests_.end()) {
670         pending_verifier_request = it->second->request();
671       } else {
672         LOG(INFO) << "TlsServerSecurityConnector::cancel_check_peer: no "
673                      "corresponding pending request found";
674       }
675     }
676     if (pending_verifier_request != nullptr) {
677       verifier->Cancel(pending_verifier_request);
678     }
679   }
680 }
681 
cmp(const grpc_security_connector * other_sc) const682 int TlsServerSecurityConnector::cmp(
683     const grpc_security_connector* other_sc) const {
684   auto* other = reinterpret_cast<const TlsServerSecurityConnector*>(other_sc);
685   int c = server_security_connector_cmp(other);
686   if (c != 0) return c;
687   return 0;
688 }
689 
690 void TlsServerSecurityConnector::TlsServerCertificateWatcher::
OnCertificatesChanged(absl::optional<absl::string_view> root_certs,absl::optional<PemKeyCertPairList> key_cert_pairs)691     OnCertificatesChanged(absl::optional<absl::string_view> root_certs,
692                           absl::optional<PemKeyCertPairList> key_cert_pairs) {
693   CHECK_NE(security_connector_, nullptr);
694   MutexLock lock(&security_connector_->mu_);
695   if (root_certs.has_value()) {
696     security_connector_->pem_root_certs_ = root_certs;
697   }
698   if (key_cert_pairs.has_value()) {
699     security_connector_->pem_key_cert_pair_list_ = std::move(key_cert_pairs);
700   }
701   bool root_being_watched = security_connector_->options_->watch_root_cert();
702   bool root_has_value = security_connector_->pem_root_certs_.has_value();
703   bool identity_being_watched =
704       security_connector_->options_->watch_identity_pair();
705   bool identity_has_value =
706       security_connector_->pem_key_cert_pair_list_.has_value();
707   if ((root_being_watched && root_has_value && identity_being_watched &&
708        identity_has_value) ||
709       (root_being_watched && root_has_value && !identity_being_watched) ||
710       (!root_being_watched && identity_being_watched && identity_has_value)) {
711     if (security_connector_->UpdateHandshakerFactoryLocked() !=
712         GRPC_SECURITY_OK) {
713       LOG(ERROR) << "Update handshaker factory failed.";
714     }
715   }
716 }
717 
718 // TODO(ZhenLian): implement the logic to signal waiting handshakers once
719 // BlockOnInitialCredentialHandshaker is implemented.
OnError(grpc_error_handle root_cert_error,grpc_error_handle identity_cert_error)720 void TlsServerSecurityConnector::TlsServerCertificateWatcher::OnError(
721     grpc_error_handle root_cert_error, grpc_error_handle identity_cert_error) {
722   if (!root_cert_error.ok()) {
723     LOG(ERROR) << "TlsServerCertificateWatcher getting root_cert_error: "
724                << StatusToString(root_cert_error);
725   }
726   if (!identity_cert_error.ok()) {
727     LOG(ERROR) << "TlsServerCertificateWatcher getting identity_cert_error: "
728                << StatusToString(identity_cert_error);
729   }
730 }
731 
732 TlsServerSecurityConnector::ServerPendingVerifierRequest::
ServerPendingVerifierRequest(RefCountedPtr<TlsServerSecurityConnector> security_connector,grpc_closure * on_peer_checked,tsi_peer peer)733     ServerPendingVerifierRequest(
734         RefCountedPtr<TlsServerSecurityConnector> security_connector,
735         grpc_closure* on_peer_checked, tsi_peer peer)
736     : security_connector_(std::move(security_connector)),
737       on_peer_checked_(on_peer_checked) {
738   PendingVerifierRequestInit(nullptr, peer, &request_);
739   tsi_peer_destruct(&peer);
740 }
741 
742 TlsServerSecurityConnector::ServerPendingVerifierRequest::
~ServerPendingVerifierRequest()743     ~ServerPendingVerifierRequest() {
744   PendingVerifierRequestDestroy(&request_);
745 }
746 
Start()747 void TlsServerSecurityConnector::ServerPendingVerifierRequest::Start() {
748   absl::Status sync_status;
749   grpc_tls_certificate_verifier* verifier =
750       security_connector_->options_->certificate_verifier();
751   bool is_done = verifier->Verify(
752       &request_,
753       absl::bind_front(&ServerPendingVerifierRequest::OnVerifyDone, this, true),
754       &sync_status);
755   if (is_done) {
756     OnVerifyDone(false, sync_status);
757   }
758 }
759 
OnVerifyDone(bool run_callback_inline,absl::Status status)760 void TlsServerSecurityConnector::ServerPendingVerifierRequest::OnVerifyDone(
761     bool run_callback_inline, absl::Status status) {
762   {
763     MutexLock lock(&security_connector_->verifier_request_map_mu_);
764     security_connector_->pending_verifier_requests_.erase(on_peer_checked_);
765   }
766   grpc_error_handle error;
767   if (!status.ok()) {
768     error = GRPC_ERROR_CREATE(
769         absl::StrCat("Custom verification check failed with error: ",
770                      status.ToString())
771             .c_str());
772   }
773   if (run_callback_inline) {
774     Closure::Run(DEBUG_LOCATION, on_peer_checked_, error);
775   } else {
776     ExecCtx::Run(DEBUG_LOCATION, on_peer_checked_, error);
777   }
778   delete this;
779 }
780 
781 // TODO(ZhenLian): implement the logic to signal waiting handshakers once
782 // BlockOnInitialCredentialHandshaker is implemented.
783 grpc_security_status
UpdateHandshakerFactoryLocked()784 TlsServerSecurityConnector::UpdateHandshakerFactoryLocked() {
785   // Free the server handshaker factory if exists.
786   if (server_handshaker_factory_ != nullptr) {
787     tsi_ssl_server_handshaker_factory_unref(server_handshaker_factory_);
788   }
789   // The identity certs on the server side shouldn't be empty.
790   CHECK(pem_key_cert_pair_list_.has_value());
791   CHECK(!(*pem_key_cert_pair_list_).empty());
792   std::string pem_root_certs;
793   if (pem_root_certs_.has_value()) {
794     // TODO(ZhenLian): update the underlying TSI layer to use C++ types like
795     // std::string and absl::string_view to avoid making another copy here.
796     pem_root_certs = std::string(*pem_root_certs_);
797   }
798   tsi_ssl_pem_key_cert_pair* pem_key_cert_pairs = nullptr;
799   pem_key_cert_pairs = ConvertToTsiPemKeyCertPair(*pem_key_cert_pair_list_);
800   size_t num_key_cert_pairs = (*pem_key_cert_pair_list_).size();
801   grpc_security_status status = grpc_ssl_tsi_server_handshaker_factory_init(
802       pem_key_cert_pairs, num_key_cert_pairs,
803       pem_root_certs.empty() ? nullptr : pem_root_certs.c_str(),
804       options_->cert_request_type(),
805       grpc_get_tsi_tls_version(options_->min_tls_version()),
806       grpc_get_tsi_tls_version(options_->max_tls_version()),
807       tls_session_key_logger_.get(), options_->crl_directory().c_str(),
808       options_->send_client_ca_list(), options_->crl_provider(),
809       &server_handshaker_factory_);
810   // Free memory.
811   grpc_tsi_ssl_pem_key_cert_pairs_destroy(pem_key_cert_pairs,
812                                           num_key_cert_pairs);
813   return status;
814 }
815 
816 }  // namespace grpc_core
817