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