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