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 // We will use the root certs stored in system default locations if not
140 // watching root certs on the client side. We will handle this case
141 // differently here, because "watching a default roots without the identity
142 // certs" is a valid case(and hence we will need to call
143 // OnCertificatesChanged), but it requires nothing from the provider, and
144 // hence no need to register the watcher.
145 bool use_default_roots = !options_->watch_root_cert();
146 if (use_default_roots && !options_->watch_identity_pair()) {
147 watcher_ptr->OnCertificatesChanged(absl::nullopt, absl::nullopt);
148 } else {
149 distributor->WatchTlsCertificates(std::move(watcher_ptr),
150 watched_root_cert_name,
151 watched_identity_cert_name);
152 }
153 }
154
~TlsChannelSecurityConnector()155 TlsChannelSecurityConnector::~TlsChannelSecurityConnector() {
156 if (ssl_session_cache_ != nullptr) {
157 tsi_ssl_session_cache_unref(ssl_session_cache_);
158 }
159 // Cancel all the watchers.
160 grpc_tls_certificate_distributor* distributor =
161 options_->certificate_distributor();
162 if (distributor != nullptr) {
163 distributor->CancelTlsCertificatesWatch(certificate_watcher_);
164 }
165 if (client_handshaker_factory_ != nullptr) {
166 tsi_ssl_client_handshaker_factory_unref(client_handshaker_factory_);
167 }
168 if (check_arg_ != nullptr) {
169 ServerAuthorizationCheckArgDestroy(check_arg_);
170 }
171 }
172
add_handshakers(const grpc_channel_args * args,grpc_pollset_set *,grpc_core::HandshakeManager * handshake_mgr)173 void TlsChannelSecurityConnector::add_handshakers(
174 const grpc_channel_args* args, grpc_pollset_set* /*interested_parties*/,
175 grpc_core::HandshakeManager* handshake_mgr) {
176 grpc_core::MutexLock lock(&mu_);
177 if (client_handshaker_factory_ != nullptr) {
178 // Instantiate TSI handshaker.
179 tsi_handshaker* tsi_hs = nullptr;
180 tsi_result result = tsi_ssl_client_handshaker_factory_create_handshaker(
181 client_handshaker_factory_,
182 overridden_target_name_.empty() ? target_name_.c_str()
183 : overridden_target_name_.c_str(),
184 &tsi_hs);
185 if (result != TSI_OK) {
186 gpr_log(GPR_ERROR, "Handshaker creation failed with error %s.",
187 tsi_result_to_string(result));
188 return;
189 }
190 // Create handshakers.
191 handshake_mgr->Add(grpc_core::SecurityHandshakerCreate(tsi_hs, this, args));
192 return;
193 }
194 // TODO(ZhenLian): Implement the logic(delegation to
195 // BlockOnInitialCredentialHandshaker) when certificates are not ready.
196 gpr_log(GPR_ERROR, "%s not supported yet.",
197 "Client BlockOnInitialCredentialHandshaker");
198 }
199
check_peer(tsi_peer peer,grpc_endpoint *,grpc_core::RefCountedPtr<grpc_auth_context> * auth_context,grpc_closure * on_peer_checked)200 void TlsChannelSecurityConnector::check_peer(
201 tsi_peer peer, grpc_endpoint* /*ep*/,
202 grpc_core::RefCountedPtr<grpc_auth_context>* auth_context,
203 grpc_closure* on_peer_checked) {
204 const char* target_name = overridden_target_name_.empty()
205 ? target_name_.c_str()
206 : overridden_target_name_.c_str();
207 grpc_error* error = grpc_ssl_check_alpn(&peer);
208 if (error != GRPC_ERROR_NONE) {
209 grpc_core::ExecCtx::Run(DEBUG_LOCATION, on_peer_checked, error);
210 tsi_peer_destruct(&peer);
211 return;
212 }
213 *auth_context =
214 grpc_ssl_peer_to_auth_context(&peer, GRPC_TLS_TRANSPORT_SECURITY_TYPE);
215 if (options_->server_verification_option() == GRPC_TLS_SERVER_VERIFICATION) {
216 /* Do the default host name check if specifying the target name. */
217 error = internal::TlsCheckHostName(target_name, &peer);
218 if (error != GRPC_ERROR_NONE) {
219 grpc_core::ExecCtx::Run(DEBUG_LOCATION, on_peer_checked, error);
220 tsi_peer_destruct(&peer);
221 return;
222 }
223 }
224 /* Do the custom server authorization check, if specified by the user. */
225 const grpc_tls_server_authorization_check_config* config =
226 options_->server_authorization_check_config();
227 /* If server authorization config is not null, use it to perform
228 * server authorization check. */
229 if (config != nullptr) {
230 const tsi_peer_property* p =
231 tsi_peer_get_property_by_name(&peer, TSI_X509_PEM_CERT_PROPERTY);
232 if (p == nullptr) {
233 error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(
234 "Cannot check peer: missing pem cert property.");
235 } else {
236 char* peer_pem = static_cast<char*>(gpr_zalloc(p->value.length + 1));
237 memcpy(peer_pem, p->value.data, p->value.length);
238 GPR_ASSERT(check_arg_ != nullptr);
239 check_arg_->peer_cert = check_arg_->peer_cert == nullptr
240 ? gpr_strdup(peer_pem)
241 : check_arg_->peer_cert;
242 check_arg_->target_name = check_arg_->target_name == nullptr
243 ? gpr_strdup(target_name)
244 : check_arg_->target_name;
245 on_peer_checked_ = on_peer_checked;
246 gpr_free(peer_pem);
247 const tsi_peer_property* chain = tsi_peer_get_property_by_name(
248 &peer, TSI_X509_PEM_CERT_CHAIN_PROPERTY);
249 if (chain != nullptr) {
250 char* peer_pem_chain =
251 static_cast<char*>(gpr_zalloc(chain->value.length + 1));
252 memcpy(peer_pem_chain, chain->value.data, chain->value.length);
253 check_arg_->peer_cert_full_chain =
254 check_arg_->peer_cert_full_chain == nullptr
255 ? gpr_strdup(peer_pem_chain)
256 : check_arg_->peer_cert_full_chain;
257 gpr_free(peer_pem_chain);
258 }
259 // TODO(zhenlian) - This should be cleaned up as part of the custom
260 // verification changes. Fill in the subject alternative names
261 std::vector<char*> subject_alternative_names;
262 for (size_t i = 0; i < peer.property_count; i++) {
263 const tsi_peer_property* prop = &peer.properties[i];
264 if (strcmp(prop->name,
265 TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY) == 0) {
266 char* san = new char[prop->value.length + 1];
267 memcpy(san, prop->value.data, prop->value.length);
268 san[prop->value.length] = '\0';
269 subject_alternative_names.emplace_back(san);
270 }
271 }
272 if (check_arg_->subject_alternative_names != nullptr) {
273 for (size_t i = 0; i < check_arg_->subject_alternative_names_size;
274 ++i) {
275 delete[] check_arg_->subject_alternative_names[i];
276 }
277 delete[] check_arg_->subject_alternative_names;
278 }
279 check_arg_->subject_alternative_names_size =
280 subject_alternative_names.size();
281 if (subject_alternative_names.empty()) {
282 check_arg_->subject_alternative_names = nullptr;
283 } else {
284 check_arg_->subject_alternative_names =
285 new char*[check_arg_->subject_alternative_names_size];
286 for (size_t i = 0; i < check_arg_->subject_alternative_names_size;
287 ++i) {
288 check_arg_->subject_alternative_names[i] =
289 subject_alternative_names[i];
290 }
291 }
292 int callback_status = config->Schedule(check_arg_);
293 /* Server authorization check is handled asynchronously. */
294 if (callback_status) {
295 tsi_peer_destruct(&peer);
296 return;
297 }
298 /* Server authorization check is handled synchronously. */
299 error = ProcessServerAuthorizationCheckResult(check_arg_);
300 }
301 }
302 grpc_core::ExecCtx::Run(DEBUG_LOCATION, on_peer_checked, error);
303 tsi_peer_destruct(&peer);
304 }
305
cmp(const grpc_security_connector * other_sc) const306 int TlsChannelSecurityConnector::cmp(
307 const grpc_security_connector* other_sc) const {
308 auto* other = reinterpret_cast<const TlsChannelSecurityConnector*>(other_sc);
309 int c = channel_security_connector_cmp(other);
310 if (c != 0) {
311 return c;
312 }
313 return grpc_ssl_cmp_target_name(
314 target_name_.c_str(), other->target_name_.c_str(),
315 overridden_target_name_.c_str(), other->overridden_target_name_.c_str());
316 }
317
check_call_host(absl::string_view host,grpc_auth_context * auth_context,grpc_closure *,grpc_error ** error)318 bool TlsChannelSecurityConnector::check_call_host(
319 absl::string_view host, grpc_auth_context* auth_context,
320 grpc_closure* /*on_call_host_checked*/, grpc_error** error) {
321 return grpc_ssl_check_call_host(host, target_name_.c_str(),
322 overridden_target_name_.c_str(), auth_context,
323 error);
324 }
325
cancel_check_call_host(grpc_closure *,grpc_error * error)326 void TlsChannelSecurityConnector::cancel_check_call_host(
327 grpc_closure* /*on_call_host_checked*/, grpc_error* error) {
328 GRPC_ERROR_UNREF(error);
329 }
330
331 void TlsChannelSecurityConnector::TlsChannelCertificateWatcher::
OnCertificatesChanged(absl::optional<absl::string_view> root_certs,absl::optional<grpc_core::PemKeyCertPairList> key_cert_pairs)332 OnCertificatesChanged(
333 absl::optional<absl::string_view> root_certs,
334 absl::optional<grpc_core::PemKeyCertPairList> key_cert_pairs) {
335 GPR_ASSERT(security_connector_ != nullptr);
336 grpc_core::MutexLock lock(&security_connector_->mu_);
337 if (root_certs.has_value()) {
338 security_connector_->pem_root_certs_ = root_certs;
339 }
340 if (key_cert_pairs.has_value()) {
341 security_connector_->pem_key_cert_pair_list_ = std::move(key_cert_pairs);
342 }
343 const bool root_ready = !security_connector_->options_->watch_root_cert() ||
344 security_connector_->pem_root_certs_.has_value();
345 const bool identity_ready =
346 !security_connector_->options_->watch_identity_pair() ||
347 security_connector_->pem_key_cert_pair_list_.has_value();
348 if (root_ready && identity_ready) {
349 if (security_connector_->UpdateHandshakerFactoryLocked() !=
350 GRPC_SECURITY_OK) {
351 gpr_log(GPR_ERROR, "Update handshaker factory failed.");
352 }
353 }
354 }
355
356 // TODO(ZhenLian): implement the logic to signal waiting handshakers once
357 // BlockOnInitialCredentialHandshaker is implemented.
OnError(grpc_error * root_cert_error,grpc_error * identity_cert_error)358 void TlsChannelSecurityConnector::TlsChannelCertificateWatcher::OnError(
359 grpc_error* root_cert_error, grpc_error* identity_cert_error) {
360 if (root_cert_error != GRPC_ERROR_NONE) {
361 gpr_log(GPR_ERROR,
362 "TlsChannelCertificateWatcher getting root_cert_error: %s",
363 grpc_error_string(root_cert_error));
364 }
365 if (identity_cert_error != GRPC_ERROR_NONE) {
366 gpr_log(GPR_ERROR,
367 "TlsChannelCertificateWatcher getting identity_cert_error: %s",
368 grpc_error_string(identity_cert_error));
369 }
370 GRPC_ERROR_UNREF(root_cert_error);
371 GRPC_ERROR_UNREF(identity_cert_error);
372 }
373
374 // TODO(ZhenLian): implement the logic to signal waiting handshakers once
375 // BlockOnInitialCredentialHandshaker is implemented.
376 grpc_security_status
UpdateHandshakerFactoryLocked()377 TlsChannelSecurityConnector::UpdateHandshakerFactoryLocked() {
378 bool skip_server_certificate_verification =
379 options_->server_verification_option() ==
380 GRPC_TLS_SKIP_ALL_SERVER_VERIFICATION;
381 /* Free the client handshaker factory if exists. */
382 if (client_handshaker_factory_ != nullptr) {
383 tsi_ssl_client_handshaker_factory_unref(client_handshaker_factory_);
384 }
385 std::string pem_root_certs;
386 if (pem_root_certs_.has_value()) {
387 // TODO(ZhenLian): update the underlying TSI layer to use C++ types like
388 // std::string and absl::string_view to avoid making another copy here.
389 pem_root_certs = std::string(*pem_root_certs_);
390 }
391 tsi_ssl_pem_key_cert_pair* pem_key_cert_pair = nullptr;
392 if (pem_key_cert_pair_list_.has_value()) {
393 pem_key_cert_pair = ConvertToTsiPemKeyCertPair(*pem_key_cert_pair_list_);
394 }
395 bool use_default_roots = !options_->watch_root_cert();
396 grpc_security_status status = grpc_ssl_tsi_client_handshaker_factory_init(
397 pem_key_cert_pair,
398 pem_root_certs.empty() || use_default_roots ? nullptr
399 : pem_root_certs.c_str(),
400 skip_server_certificate_verification,
401 grpc_get_tsi_tls_version(options_->min_tls_version()),
402 grpc_get_tsi_tls_version(options_->max_tls_version()), ssl_session_cache_,
403 &client_handshaker_factory_);
404 /* Free memory. */
405 if (pem_key_cert_pair != nullptr) {
406 grpc_tsi_ssl_pem_key_cert_pairs_destroy(pem_key_cert_pair, 1);
407 }
408 return status;
409 }
410
ServerAuthorizationCheckDone(grpc_tls_server_authorization_check_arg * arg)411 void TlsChannelSecurityConnector::ServerAuthorizationCheckDone(
412 grpc_tls_server_authorization_check_arg* arg) {
413 GPR_ASSERT(arg != nullptr);
414 grpc_core::ExecCtx exec_ctx;
415 grpc_error* error = ProcessServerAuthorizationCheckResult(arg);
416 TlsChannelSecurityConnector* connector =
417 static_cast<TlsChannelSecurityConnector*>(arg->cb_user_data);
418 grpc_core::ExecCtx::Run(DEBUG_LOCATION, connector->on_peer_checked_, error);
419 }
420
ProcessServerAuthorizationCheckResult(grpc_tls_server_authorization_check_arg * arg)421 grpc_error* TlsChannelSecurityConnector::ProcessServerAuthorizationCheckResult(
422 grpc_tls_server_authorization_check_arg* arg) {
423 grpc_error* error = GRPC_ERROR_NONE;
424 /* Server authorization check is cancelled by caller. */
425 if (arg->status == GRPC_STATUS_CANCELLED) {
426 error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(
427 absl::StrCat("Server authorization check is cancelled by the caller "
428 "with error: ",
429 arg->error_details->error_details())
430 .c_str());
431 } else if (arg->status == GRPC_STATUS_OK) {
432 /* Server authorization check completed successfully but returned check
433 * failure. */
434 if (!arg->success) {
435 error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(
436 absl::StrCat("Server authorization check failed with error: ",
437 arg->error_details->error_details())
438 .c_str());
439 }
440 /* Server authorization check did not complete correctly. */
441 } else {
442 error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(
443 absl::StrCat(
444 "Server authorization check did not finish correctly with error: ",
445 arg->error_details->error_details())
446 .c_str());
447 }
448 return error;
449 }
450
451 grpc_tls_server_authorization_check_arg*
ServerAuthorizationCheckArgCreate(void * user_data)452 TlsChannelSecurityConnector::ServerAuthorizationCheckArgCreate(
453 void* user_data) {
454 grpc_tls_server_authorization_check_arg* arg =
455 new grpc_tls_server_authorization_check_arg();
456 arg->target_name = nullptr;
457 arg->peer_cert = nullptr;
458 arg->peer_cert_full_chain = nullptr;
459 arg->subject_alternative_names = nullptr;
460 arg->subject_alternative_names_size = 0;
461 arg->error_details = new grpc_tls_error_details();
462 arg->cb = ServerAuthorizationCheckDone;
463 arg->cb_user_data = user_data;
464 arg->status = GRPC_STATUS_OK;
465 return arg;
466 }
467
ServerAuthorizationCheckArgDestroy(grpc_tls_server_authorization_check_arg * arg)468 void TlsChannelSecurityConnector::ServerAuthorizationCheckArgDestroy(
469 grpc_tls_server_authorization_check_arg* arg) {
470 if (arg == nullptr) {
471 return;
472 }
473 gpr_free(const_cast<char*>(arg->target_name));
474 gpr_free(const_cast<char*>(arg->peer_cert));
475 gpr_free(const_cast<char*>(arg->peer_cert_full_chain));
476 for (size_t i = 0; i < arg->subject_alternative_names_size; ++i) {
477 delete[] arg->subject_alternative_names[i];
478 }
479 delete[] arg->subject_alternative_names;
480 delete arg->error_details;
481 if (arg->destroy_context != nullptr) {
482 arg->destroy_context(arg->context);
483 }
484 delete arg;
485 }
486
487 // -------------------server security connector-------------------
488 grpc_core::RefCountedPtr<grpc_server_security_connector>
CreateTlsServerSecurityConnector(grpc_core::RefCountedPtr<grpc_server_credentials> server_creds,grpc_core::RefCountedPtr<grpc_tls_credentials_options> options)489 TlsServerSecurityConnector::CreateTlsServerSecurityConnector(
490 grpc_core::RefCountedPtr<grpc_server_credentials> server_creds,
491 grpc_core::RefCountedPtr<grpc_tls_credentials_options> options) {
492 if (server_creds == nullptr) {
493 gpr_log(GPR_ERROR,
494 "server_creds is nullptr in "
495 "TlsServerSecurityConnectorCreate()");
496 return nullptr;
497 }
498 if (options == nullptr) {
499 gpr_log(GPR_ERROR,
500 "options is nullptr in "
501 "TlsServerSecurityConnectorCreate()");
502 return nullptr;
503 }
504 grpc_core::RefCountedPtr<TlsServerSecurityConnector> c =
505 grpc_core::MakeRefCounted<TlsServerSecurityConnector>(
506 std::move(server_creds), std::move(options));
507 return c;
508 }
509
TlsServerSecurityConnector(grpc_core::RefCountedPtr<grpc_server_credentials> server_creds,grpc_core::RefCountedPtr<grpc_tls_credentials_options> options)510 TlsServerSecurityConnector::TlsServerSecurityConnector(
511 grpc_core::RefCountedPtr<grpc_server_credentials> server_creds,
512 grpc_core::RefCountedPtr<grpc_tls_credentials_options> options)
513 : grpc_server_security_connector(GRPC_SSL_URL_SCHEME,
514 std::move(server_creds)),
515 options_(std::move(options)) {
516 // Create a watcher.
517 auto watcher_ptr = absl::make_unique<TlsServerCertificateWatcher>(this);
518 certificate_watcher_ = watcher_ptr.get();
519 // Register the watcher with the distributor.
520 grpc_tls_certificate_distributor* distributor =
521 options_->certificate_distributor();
522 absl::optional<std::string> watched_root_cert_name;
523 if (options_->watch_root_cert()) {
524 watched_root_cert_name = options_->root_cert_name();
525 }
526 absl::optional<std::string> watched_identity_cert_name;
527 if (options_->watch_identity_pair()) {
528 watched_identity_cert_name = options_->identity_cert_name();
529 }
530 // Server side won't use default system roots at any time.
531 distributor->WatchTlsCertificates(std::move(watcher_ptr),
532 watched_root_cert_name,
533 watched_identity_cert_name);
534 }
535
~TlsServerSecurityConnector()536 TlsServerSecurityConnector::~TlsServerSecurityConnector() {
537 // Cancel all the watchers.
538 grpc_tls_certificate_distributor* distributor =
539 options_->certificate_distributor();
540 distributor->CancelTlsCertificatesWatch(certificate_watcher_);
541 if (server_handshaker_factory_ != nullptr) {
542 tsi_ssl_server_handshaker_factory_unref(server_handshaker_factory_);
543 }
544 }
545
add_handshakers(const grpc_channel_args * args,grpc_pollset_set *,grpc_core::HandshakeManager * handshake_mgr)546 void TlsServerSecurityConnector::add_handshakers(
547 const grpc_channel_args* args, grpc_pollset_set* /*interested_parties*/,
548 grpc_core::HandshakeManager* handshake_mgr) {
549 grpc_core::MutexLock lock(&mu_);
550 if (server_handshaker_factory_ != nullptr) {
551 // Instantiate TSI handshaker.
552 tsi_handshaker* tsi_hs = nullptr;
553 tsi_result result = tsi_ssl_server_handshaker_factory_create_handshaker(
554 server_handshaker_factory_, &tsi_hs);
555 if (result != TSI_OK) {
556 gpr_log(GPR_ERROR, "Handshaker creation failed with error %s.",
557 tsi_result_to_string(result));
558 return;
559 }
560 // Create handshakers.
561 handshake_mgr->Add(grpc_core::SecurityHandshakerCreate(tsi_hs, this, args));
562 return;
563 }
564 // TODO(ZhenLian): Implement the logic(delegation to
565 // BlockOnInitialCredentialHandshaker) when certificates are not ready.
566 gpr_log(GPR_ERROR, "%s not supported yet.",
567 "Server BlockOnInitialCredentialHandshaker");
568 }
569
check_peer(tsi_peer peer,grpc_endpoint *,grpc_core::RefCountedPtr<grpc_auth_context> * auth_context,grpc_closure * on_peer_checked)570 void TlsServerSecurityConnector::check_peer(
571 tsi_peer peer, grpc_endpoint* /*ep*/,
572 grpc_core::RefCountedPtr<grpc_auth_context>* auth_context,
573 grpc_closure* on_peer_checked) {
574 grpc_error* error = grpc_ssl_check_alpn(&peer);
575 *auth_context =
576 grpc_ssl_peer_to_auth_context(&peer, GRPC_TLS_TRANSPORT_SECURITY_TYPE);
577 tsi_peer_destruct(&peer);
578 grpc_core::ExecCtx::Run(DEBUG_LOCATION, on_peer_checked, error);
579 }
580
cmp(const grpc_security_connector * other) const581 int TlsServerSecurityConnector::cmp(
582 const grpc_security_connector* other) const {
583 return server_security_connector_cmp(
584 static_cast<const grpc_server_security_connector*>(other));
585 }
586
587 void TlsServerSecurityConnector::TlsServerCertificateWatcher::
OnCertificatesChanged(absl::optional<absl::string_view> root_certs,absl::optional<grpc_core::PemKeyCertPairList> key_cert_pairs)588 OnCertificatesChanged(
589 absl::optional<absl::string_view> root_certs,
590 absl::optional<grpc_core::PemKeyCertPairList> key_cert_pairs) {
591 GPR_ASSERT(security_connector_ != nullptr);
592 grpc_core::MutexLock lock(&security_connector_->mu_);
593 if (root_certs.has_value()) {
594 security_connector_->pem_root_certs_ = root_certs;
595 }
596 if (key_cert_pairs.has_value()) {
597 security_connector_->pem_key_cert_pair_list_ = std::move(key_cert_pairs);
598 }
599 bool root_being_watched = security_connector_->options_->watch_root_cert();
600 bool root_has_value = security_connector_->pem_root_certs_.has_value();
601 bool identity_being_watched =
602 security_connector_->options_->watch_identity_pair();
603 bool identity_has_value =
604 security_connector_->pem_key_cert_pair_list_.has_value();
605 if ((root_being_watched && root_has_value && identity_being_watched &&
606 identity_has_value) ||
607 (root_being_watched && root_has_value && !identity_being_watched) ||
608 (!root_being_watched && identity_being_watched && identity_has_value)) {
609 if (security_connector_->UpdateHandshakerFactoryLocked() !=
610 GRPC_SECURITY_OK) {
611 gpr_log(GPR_ERROR, "Update handshaker factory failed.");
612 }
613 }
614 }
615
616 // TODO(ZhenLian): implement the logic to signal waiting handshakers once
617 // BlockOnInitialCredentialHandshaker is implemented.
OnError(grpc_error * root_cert_error,grpc_error * identity_cert_error)618 void TlsServerSecurityConnector::TlsServerCertificateWatcher::OnError(
619 grpc_error* root_cert_error, grpc_error* identity_cert_error) {
620 if (root_cert_error != GRPC_ERROR_NONE) {
621 gpr_log(GPR_ERROR,
622 "TlsServerCertificateWatcher getting root_cert_error: %s",
623 grpc_error_string(root_cert_error));
624 }
625 if (identity_cert_error != GRPC_ERROR_NONE) {
626 gpr_log(GPR_ERROR,
627 "TlsServerCertificateWatcher getting identity_cert_error: %s",
628 grpc_error_string(identity_cert_error));
629 }
630 GRPC_ERROR_UNREF(root_cert_error);
631 GRPC_ERROR_UNREF(identity_cert_error);
632 }
633
634 // TODO(ZhenLian): implement the logic to signal waiting handshakers once
635 // BlockOnInitialCredentialHandshaker is implemented.
636 grpc_security_status
UpdateHandshakerFactoryLocked()637 TlsServerSecurityConnector::UpdateHandshakerFactoryLocked() {
638 /* Free the server handshaker factory if exists. */
639 if (server_handshaker_factory_ != nullptr) {
640 tsi_ssl_server_handshaker_factory_unref(server_handshaker_factory_);
641 }
642 // The identity certs on the server side shouldn't be empty.
643 GPR_ASSERT(pem_key_cert_pair_list_.has_value());
644 GPR_ASSERT(!(*pem_key_cert_pair_list_).empty());
645 std::string pem_root_certs;
646 if (pem_root_certs_.has_value()) {
647 // TODO(ZhenLian): update the underlying TSI layer to use C++ types like
648 // std::string and absl::string_view to avoid making another copy here.
649 pem_root_certs = std::string(*pem_root_certs_);
650 }
651 tsi_ssl_pem_key_cert_pair* pem_key_cert_pairs = nullptr;
652 pem_key_cert_pairs = ConvertToTsiPemKeyCertPair(*pem_key_cert_pair_list_);
653 size_t num_key_cert_pairs = (*pem_key_cert_pair_list_).size();
654 grpc_security_status status = grpc_ssl_tsi_server_handshaker_factory_init(
655 pem_key_cert_pairs, num_key_cert_pairs,
656 pem_root_certs.empty() ? nullptr : pem_root_certs.c_str(),
657 options_->cert_request_type(),
658 grpc_get_tsi_tls_version(options_->min_tls_version()),
659 grpc_get_tsi_tls_version(options_->max_tls_version()),
660 &server_handshaker_factory_);
661 /* Free memory. */
662 grpc_tsi_ssl_pem_key_cert_pairs_destroy(pem_key_cert_pairs,
663 num_key_cert_pairs);
664 return status;
665 }
666
667 namespace internal {
668
TlsCheckHostName(const char * peer_name,const tsi_peer * peer)669 grpc_error* TlsCheckHostName(const char* peer_name, const tsi_peer* peer) {
670 /* Check the peer name if specified. */
671 if (peer_name != nullptr && !grpc_ssl_host_matches_name(peer, peer_name)) {
672 return GRPC_ERROR_CREATE_FROM_COPIED_STRING(
673 absl::StrCat("Peer name ", peer_name, " is not in peer certificate")
674 .c_str());
675 }
676 return GRPC_ERROR_NONE;
677 }
678
679 } // namespace internal
680
681 } // namespace grpc_core
682