Imported Upstream version 1.33.1
[platform/upstream/grpc.git] / src / core / lib / security / security_connector / tls / tls_security_connector.cc
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
48 tsi_ssl_pem_key_cert_pair* ConvertToTsiPemKeyCertPair(
49     const grpc_tls_key_materials_config::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() != nullptr);
59     GPR_ASSERT(cert_pair_list[i].cert_chain() != nullptr);
60     tsi_pairs[i].cert_chain = gpr_strdup(cert_pair_list[i].cert_chain());
61     tsi_pairs[i].private_key = gpr_strdup(cert_pair_list[i].private_key());
62   }
63   return tsi_pairs;
64 }
65
66 }  // namespace
67
68 grpc_status_code TlsFetchKeyMaterials(
69     const grpc_core::RefCountedPtr<grpc_tls_key_materials_config>&
70         key_materials_config,
71     const grpc_tls_credentials_options& options, bool is_server,
72     grpc_ssl_certificate_config_reload_status* status) {
73   GPR_ASSERT(key_materials_config != nullptr);
74   GPR_ASSERT(status != nullptr);
75   bool is_key_materials_empty =
76       key_materials_config->pem_key_cert_pair_list().empty();
77   grpc_tls_credential_reload_config* credential_reload_config =
78       options.credential_reload_config();
79   /** If there are no key materials and no credential reload config and the
80    *  caller is a server, then return an error. We do not require that a client
81    *  always provision certificates. **/
82   if (credential_reload_config == nullptr && is_key_materials_empty &&
83       is_server) {
84     gpr_log(GPR_ERROR,
85             "Either credential reload config or key materials should be "
86             "provisioned.");
87     return GRPC_STATUS_FAILED_PRECONDITION;
88   }
89   grpc_status_code reload_status = GRPC_STATUS_OK;
90   /** Use |credential_reload_config| to update |key_materials_config|. **/
91   if (credential_reload_config != nullptr) {
92     grpc_tls_credential_reload_arg* arg = new grpc_tls_credential_reload_arg();
93     arg->key_materials_config = key_materials_config.get();
94     arg->error_details = new grpc_tls_error_details();
95     int result = credential_reload_config->Schedule(arg);
96     if (result) {
97       /** Credential reloading is performed async. This is not yet supported.
98        * **/
99       gpr_log(GPR_ERROR, "Async credential reload is unsupported now.");
100       *status = GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_UNCHANGED;
101       reload_status =
102           is_key_materials_empty ? GRPC_STATUS_UNIMPLEMENTED : GRPC_STATUS_OK;
103     } else {
104       /** Credential reloading is performed sync. **/
105       *status = arg->status;
106       if (arg->status == GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_UNCHANGED) {
107         /* Key materials is not empty. */
108         gpr_log(GPR_DEBUG, "Credential does not change after reload.");
109       } else if (arg->status == GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_FAIL) {
110         gpr_log(GPR_ERROR, "Credential reload failed with an error:");
111         if (arg->error_details != nullptr) {
112           gpr_log(GPR_ERROR, "%s", arg->error_details->error_details().c_str());
113         }
114         reload_status =
115             is_key_materials_empty ? GRPC_STATUS_INTERNAL : GRPC_STATUS_OK;
116       }
117     }
118     delete arg->error_details;
119     /** If the credential reload config was constructed via a wrapped language,
120      *  then |arg->context| and |arg->destroy_context| will not be nullptr. In
121      *  this case, we must destroy |arg->context|, which stores the wrapped
122      *  language-version of the credential reload arg. **/
123     if (arg->destroy_context != nullptr) {
124       arg->destroy_context(arg->context);
125     }
126     delete arg;
127   }
128   return reload_status;
129 }
130
131 grpc_error* TlsCheckHostName(const char* peer_name, const tsi_peer* peer) {
132   /* Check the peer name if specified. */
133   if (peer_name != nullptr && !grpc_ssl_host_matches_name(peer, peer_name)) {
134     return GRPC_ERROR_CREATE_FROM_COPIED_STRING(
135         absl::StrCat("Peer name ", peer_name, " is not in peer certificate")
136             .c_str());
137   }
138   return GRPC_ERROR_NONE;
139 }
140
141 TlsChannelSecurityConnector::TlsChannelSecurityConnector(
142     grpc_core::RefCountedPtr<grpc_channel_credentials> channel_creds,
143     grpc_core::RefCountedPtr<grpc_call_credentials> request_metadata_creds,
144     const char* target_name, const char* overridden_target_name)
145     : grpc_channel_security_connector(GRPC_SSL_URL_SCHEME,
146                                       std::move(channel_creds),
147                                       std::move(request_metadata_creds)),
148       overridden_target_name_(
149           overridden_target_name == nullptr ? "" : overridden_target_name) {
150   key_materials_config_ = grpc_tls_key_materials_config_create()->Ref();
151   check_arg_ = ServerAuthorizationCheckArgCreate(this);
152   absl::string_view host;
153   absl::string_view port;
154   grpc_core::SplitHostPort(target_name, &host, &port);
155   target_name_ = std::string(host);
156 }
157
158 TlsChannelSecurityConnector::~TlsChannelSecurityConnector() {
159   if (client_handshaker_factory_ != nullptr) {
160     tsi_ssl_client_handshaker_factory_unref(client_handshaker_factory_);
161   }
162   if (key_materials_config_.get() != nullptr) {
163     key_materials_config_.get()->Unref();
164   }
165   ServerAuthorizationCheckArgDestroy(check_arg_);
166 }
167
168 void TlsChannelSecurityConnector::add_handshakers(
169     const grpc_channel_args* args, grpc_pollset_set* /*interested_parties*/,
170     grpc_core::HandshakeManager* handshake_mgr) {
171   if (RefreshHandshakerFactory() != GRPC_SECURITY_OK) {
172     gpr_log(GPR_ERROR, "Handshaker factory refresh failed.");
173     return;
174   }
175   // Instantiate TSI handshaker.
176   tsi_handshaker* tsi_hs = nullptr;
177   tsi_result result = tsi_ssl_client_handshaker_factory_create_handshaker(
178       client_handshaker_factory_,
179       overridden_target_name_.empty() ? target_name_.c_str()
180                                       : overridden_target_name_.c_str(),
181       &tsi_hs);
182   if (result != TSI_OK) {
183     gpr_log(GPR_ERROR, "Handshaker creation failed with error %s.",
184             tsi_result_to_string(result));
185     return;
186   }
187   // Create handshakers.
188   handshake_mgr->Add(grpc_core::SecurityHandshakerCreate(tsi_hs, this, args));
189 }
190
191 void TlsChannelSecurityConnector::check_peer(
192     tsi_peer peer, grpc_endpoint* /*ep*/,
193     grpc_core::RefCountedPtr<grpc_auth_context>* auth_context,
194     grpc_closure* on_peer_checked) {
195   const char* target_name = overridden_target_name_.empty()
196                                 ? target_name_.c_str()
197                                 : overridden_target_name_.c_str();
198   grpc_error* error = grpc_ssl_check_alpn(&peer);
199   if (error != GRPC_ERROR_NONE) {
200     grpc_core::ExecCtx::Run(DEBUG_LOCATION, on_peer_checked, error);
201     tsi_peer_destruct(&peer);
202     return;
203   }
204   *auth_context =
205       grpc_ssl_peer_to_auth_context(&peer, GRPC_TLS_TRANSPORT_SECURITY_TYPE);
206   const TlsCredentials* creds =
207       static_cast<const TlsCredentials*>(channel_creds());
208   if (creds->options().server_verification_option() ==
209       GRPC_TLS_SERVER_VERIFICATION) {
210     /* Do the default host name check if specifying the target name. */
211     error = TlsCheckHostName(target_name, &peer);
212     if (error != GRPC_ERROR_NONE) {
213       grpc_core::ExecCtx::Run(DEBUG_LOCATION, on_peer_checked, error);
214       tsi_peer_destruct(&peer);
215       return;
216     }
217   }
218   /* Do the custom server authorization check, if specified by the user. */
219   const grpc_tls_server_authorization_check_config* config =
220       creds->options().server_authorization_check_config();
221   /* If server authorization config is not null, use it to perform
222    * server authorization check. */
223   if (config != nullptr) {
224     const tsi_peer_property* p =
225         tsi_peer_get_property_by_name(&peer, TSI_X509_PEM_CERT_PROPERTY);
226     if (p == nullptr) {
227       error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(
228           "Cannot check peer: missing pem cert property.");
229     } else {
230       char* peer_pem = static_cast<char*>(gpr_zalloc(p->value.length + 1));
231       memcpy(peer_pem, p->value.data, p->value.length);
232       GPR_ASSERT(check_arg_ != nullptr);
233       check_arg_->peer_cert = check_arg_->peer_cert == nullptr
234                                   ? gpr_strdup(peer_pem)
235                                   : check_arg_->peer_cert;
236       check_arg_->target_name = check_arg_->target_name == nullptr
237                                     ? gpr_strdup(target_name)
238                                     : check_arg_->target_name;
239       on_peer_checked_ = on_peer_checked;
240       gpr_free(peer_pem);
241       const tsi_peer_property* chain = tsi_peer_get_property_by_name(
242           &peer, TSI_X509_PEM_CERT_CHAIN_PROPERTY);
243       if (chain != nullptr) {
244         char* peer_pem_chain =
245             static_cast<char*>(gpr_zalloc(chain->value.length + 1));
246         memcpy(peer_pem_chain, chain->value.data, chain->value.length);
247         check_arg_->peer_cert_full_chain =
248             check_arg_->peer_cert_full_chain == nullptr
249                 ? gpr_strdup(peer_pem_chain)
250                 : check_arg_->peer_cert_full_chain;
251         gpr_free(peer_pem_chain);
252       }
253       int callback_status = config->Schedule(check_arg_);
254       /* Server authorization check is handled asynchronously. */
255       if (callback_status) {
256         tsi_peer_destruct(&peer);
257         return;
258       }
259       /* Server authorization check is handled synchronously. */
260       error = ProcessServerAuthorizationCheckResult(check_arg_);
261     }
262   }
263   grpc_core::ExecCtx::Run(DEBUG_LOCATION, on_peer_checked, error);
264   tsi_peer_destruct(&peer);
265 }
266
267 int TlsChannelSecurityConnector::cmp(
268     const grpc_security_connector* other_sc) const {
269   auto* other = reinterpret_cast<const TlsChannelSecurityConnector*>(other_sc);
270   int c = channel_security_connector_cmp(other);
271   if (c != 0) {
272     return c;
273   }
274   return grpc_ssl_cmp_target_name(
275       target_name_.c_str(), other->target_name_.c_str(),
276       overridden_target_name_.c_str(), other->overridden_target_name_.c_str());
277 }
278
279 bool TlsChannelSecurityConnector::check_call_host(
280     absl::string_view host, grpc_auth_context* auth_context,
281     grpc_closure* /*on_call_host_checked*/, grpc_error** error) {
282   return grpc_ssl_check_call_host(host, target_name_.c_str(),
283                                   overridden_target_name_.c_str(), auth_context,
284                                   error);
285 }
286
287 void TlsChannelSecurityConnector::cancel_check_call_host(
288     grpc_closure* /*on_call_host_checked*/, grpc_error* error) {
289   GRPC_ERROR_UNREF(error);
290 }
291
292 grpc_core::RefCountedPtr<grpc_channel_security_connector>
293 TlsChannelSecurityConnector::CreateTlsChannelSecurityConnector(
294     grpc_core::RefCountedPtr<grpc_channel_credentials> channel_creds,
295     grpc_core::RefCountedPtr<grpc_call_credentials> request_metadata_creds,
296     const char* target_name, const char* overridden_target_name,
297     tsi_ssl_session_cache* ssl_session_cache) {
298   if (channel_creds == nullptr) {
299     gpr_log(GPR_ERROR,
300             "channel_creds is nullptr in "
301             "TlsChannelSecurityConnectorCreate()");
302     return nullptr;
303   }
304   if (target_name == nullptr) {
305     gpr_log(GPR_ERROR,
306             "target_name is nullptr in "
307             "TlsChannelSecurityConnectorCreate()");
308     return nullptr;
309   }
310   grpc_core::RefCountedPtr<TlsChannelSecurityConnector> c =
311       grpc_core::MakeRefCounted<TlsChannelSecurityConnector>(
312           std::move(channel_creds), std::move(request_metadata_creds),
313           target_name, overridden_target_name);
314   if (c->InitializeHandshakerFactory(ssl_session_cache) != GRPC_SECURITY_OK) {
315     gpr_log(GPR_ERROR, "Could not initialize client handshaker factory.");
316     return nullptr;
317   }
318   return c;
319 }
320
321 grpc_security_status TlsChannelSecurityConnector::ReplaceHandshakerFactory(
322     tsi_ssl_session_cache* ssl_session_cache) {
323   const TlsCredentials* creds =
324       static_cast<const TlsCredentials*>(channel_creds());
325   bool skip_server_certificate_verification =
326       creds->options().server_verification_option() ==
327       GRPC_TLS_SKIP_ALL_SERVER_VERIFICATION;
328   /* Free the client handshaker factory if exists. */
329   if (client_handshaker_factory_) {
330     tsi_ssl_client_handshaker_factory_unref(client_handshaker_factory_);
331   }
332   tsi_ssl_pem_key_cert_pair* pem_key_cert_pair = ConvertToTsiPemKeyCertPair(
333       key_materials_config_->pem_key_cert_pair_list());
334   grpc_security_status status = grpc_ssl_tsi_client_handshaker_factory_init(
335       pem_key_cert_pair, key_materials_config_->pem_root_certs(),
336       skip_server_certificate_verification,
337       grpc_get_tsi_tls_version(creds->options().min_tls_version()),
338       grpc_get_tsi_tls_version(creds->options().max_tls_version()),
339       ssl_session_cache, &client_handshaker_factory_);
340   /* Free memory. */
341   grpc_tsi_ssl_pem_key_cert_pairs_destroy(pem_key_cert_pair, 1);
342   return status;
343 }
344
345 grpc_security_status TlsChannelSecurityConnector::InitializeHandshakerFactory(
346     tsi_ssl_session_cache* ssl_session_cache) {
347   grpc_core::MutexLock lock(&mu_);
348   const TlsCredentials* creds =
349       static_cast<const TlsCredentials*>(channel_creds());
350   grpc_tls_key_materials_config* key_materials_config =
351       creds->options().key_materials_config();
352   // key_materials_config_->set_key_materials will handle the copying of the key
353   // materials users provided
354   if (key_materials_config != nullptr) {
355     key_materials_config_->set_key_materials(
356         key_materials_config->pem_root_certs(),
357         key_materials_config->pem_key_cert_pair_list());
358   }
359   grpc_ssl_certificate_config_reload_status reload_status =
360       GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_UNCHANGED;
361   /** If |creds->options()| has a credential reload config, then the call to
362    *  |TlsFetchKeyMaterials| will use it to update the root cert and
363    *  pem-key-cert-pair list stored in |key_materials_config_|. **/
364   if (TlsFetchKeyMaterials(key_materials_config_, creds->options(), false,
365                            &reload_status) != GRPC_STATUS_OK) {
366     /* Raise an error if key materials are not populated. */
367     return GRPC_SECURITY_ERROR;
368   }
369   return ReplaceHandshakerFactory(ssl_session_cache);
370 }
371
372 grpc_security_status TlsChannelSecurityConnector::RefreshHandshakerFactory() {
373   grpc_core::MutexLock lock(&mu_);
374   const TlsCredentials* creds =
375       static_cast<const TlsCredentials*>(channel_creds());
376   grpc_ssl_certificate_config_reload_status reload_status =
377       GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_UNCHANGED;
378   /** If |creds->options()| has a credential reload config, then the call to
379    *  |TlsFetchKeyMaterials| will use it to update the root cert and
380    *  pem-key-cert-pair list stored in |key_materials_config_|. **/
381   if (TlsFetchKeyMaterials(key_materials_config_, creds->options(), false,
382                            &reload_status) != GRPC_STATUS_OK) {
383     return GRPC_SECURITY_ERROR;
384   }
385   if (reload_status != GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_NEW) {
386     // Re-use existing handshaker factory.
387     return GRPC_SECURITY_OK;
388   } else {
389     return ReplaceHandshakerFactory(nullptr);
390   }
391 }
392
393 void TlsChannelSecurityConnector::ServerAuthorizationCheckDone(
394     grpc_tls_server_authorization_check_arg* arg) {
395   GPR_ASSERT(arg != nullptr);
396   grpc_core::ExecCtx exec_ctx;
397   grpc_error* error = ProcessServerAuthorizationCheckResult(arg);
398   TlsChannelSecurityConnector* connector =
399       static_cast<TlsChannelSecurityConnector*>(arg->cb_user_data);
400   grpc_core::ExecCtx::Run(DEBUG_LOCATION, connector->on_peer_checked_, error);
401 }
402
403 grpc_error* TlsChannelSecurityConnector::ProcessServerAuthorizationCheckResult(
404     grpc_tls_server_authorization_check_arg* arg) {
405   grpc_error* error = GRPC_ERROR_NONE;
406   /* Server authorization check is cancelled by caller. */
407   if (arg->status == GRPC_STATUS_CANCELLED) {
408     error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(
409         absl::StrCat("Server authorization check is cancelled by the caller "
410                      "with error: ",
411                      arg->error_details->error_details())
412             .c_str());
413   } else if (arg->status == GRPC_STATUS_OK) {
414     /* Server authorization check completed successfully but returned check
415      * failure. */
416     if (!arg->success) {
417       error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(
418           absl::StrCat("Server authorization check failed with error: ",
419                        arg->error_details->error_details())
420               .c_str());
421     }
422     /* Server authorization check did not complete correctly. */
423   } else {
424     error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(
425         absl::StrCat(
426             "Server authorization check did not finish correctly with error: ",
427             arg->error_details->error_details())
428             .c_str());
429   }
430   return error;
431 }
432
433 grpc_tls_server_authorization_check_arg*
434 TlsChannelSecurityConnector::ServerAuthorizationCheckArgCreate(
435     void* user_data) {
436   grpc_tls_server_authorization_check_arg* arg =
437       new grpc_tls_server_authorization_check_arg();
438   arg->error_details = new grpc_tls_error_details();
439   arg->cb = ServerAuthorizationCheckDone;
440   arg->cb_user_data = user_data;
441   arg->status = GRPC_STATUS_OK;
442   return arg;
443 }
444
445 void TlsChannelSecurityConnector::ServerAuthorizationCheckArgDestroy(
446     grpc_tls_server_authorization_check_arg* arg) {
447   if (arg == nullptr) {
448     return;
449   }
450   gpr_free((void*)arg->target_name);
451   gpr_free((void*)arg->peer_cert);
452   if (arg->peer_cert_full_chain) gpr_free((void*)arg->peer_cert_full_chain);
453   delete arg->error_details;
454   if (arg->destroy_context != nullptr) {
455     arg->destroy_context(arg->context);
456   }
457   delete arg;
458 }
459
460 TlsServerSecurityConnector::TlsServerSecurityConnector(
461     grpc_core::RefCountedPtr<grpc_server_credentials> server_creds)
462     : grpc_server_security_connector(GRPC_SSL_URL_SCHEME,
463                                      std::move(server_creds)) {
464   key_materials_config_ = grpc_tls_key_materials_config_create()->Ref();
465 }
466
467 TlsServerSecurityConnector::~TlsServerSecurityConnector() {
468   if (server_handshaker_factory_ != nullptr) {
469     tsi_ssl_server_handshaker_factory_unref(server_handshaker_factory_);
470   }
471   if (key_materials_config_.get() != nullptr) {
472     key_materials_config_.get()->Unref();
473   }
474 }
475
476 void TlsServerSecurityConnector::add_handshakers(
477     const grpc_channel_args* args, grpc_pollset_set* /*interested_parties*/,
478     grpc_core::HandshakeManager* handshake_mgr) {
479   /* Refresh handshaker factory if needed. */
480   if (RefreshHandshakerFactory() != GRPC_SECURITY_OK) {
481     gpr_log(GPR_ERROR, "Handshaker factory refresh failed.");
482     return;
483   }
484   /* Create a TLS TSI handshaker for server. */
485   tsi_handshaker* tsi_hs = nullptr;
486   tsi_result result = tsi_ssl_server_handshaker_factory_create_handshaker(
487       server_handshaker_factory_, &tsi_hs);
488   if (result != TSI_OK) {
489     gpr_log(GPR_ERROR, "Handshaker creation failed with error %s.",
490             tsi_result_to_string(result));
491     return;
492   }
493   handshake_mgr->Add(grpc_core::SecurityHandshakerCreate(tsi_hs, this, args));
494 }
495
496 void TlsServerSecurityConnector::check_peer(
497     tsi_peer peer, grpc_endpoint* /*ep*/,
498     grpc_core::RefCountedPtr<grpc_auth_context>* auth_context,
499     grpc_closure* on_peer_checked) {
500   grpc_error* error = grpc_ssl_check_alpn(&peer);
501   *auth_context =
502       grpc_ssl_peer_to_auth_context(&peer, GRPC_TLS_TRANSPORT_SECURITY_TYPE);
503   tsi_peer_destruct(&peer);
504   grpc_core::ExecCtx::Run(DEBUG_LOCATION, on_peer_checked, error);
505 }
506
507 int TlsServerSecurityConnector::cmp(
508     const grpc_security_connector* other) const {
509   return server_security_connector_cmp(
510       static_cast<const grpc_server_security_connector*>(other));
511 }
512
513 grpc_core::RefCountedPtr<grpc_server_security_connector>
514 TlsServerSecurityConnector::CreateTlsServerSecurityConnector(
515     grpc_core::RefCountedPtr<grpc_server_credentials> server_creds) {
516   if (server_creds == nullptr) {
517     gpr_log(GPR_ERROR,
518             "server_creds is nullptr in "
519             "TlsServerSecurityConnectorCreate()");
520     return nullptr;
521   }
522   grpc_core::RefCountedPtr<TlsServerSecurityConnector> c =
523       grpc_core::MakeRefCounted<TlsServerSecurityConnector>(
524           std::move(server_creds));
525   if (c->InitializeHandshakerFactory() != GRPC_SECURITY_OK) {
526     gpr_log(GPR_ERROR, "Could not initialize server handshaker factory.");
527     return nullptr;
528   }
529   return c;
530 }
531
532 grpc_security_status TlsServerSecurityConnector::ReplaceHandshakerFactory() {
533   const TlsServerCredentials* creds =
534       static_cast<const TlsServerCredentials*>(server_creds());
535   /* Free the server handshaker factory if exists. */
536   if (server_handshaker_factory_) {
537     tsi_ssl_server_handshaker_factory_unref(server_handshaker_factory_);
538   }
539   GPR_ASSERT(!key_materials_config_->pem_key_cert_pair_list().empty());
540   tsi_ssl_pem_key_cert_pair* pem_key_cert_pairs = ConvertToTsiPemKeyCertPair(
541       key_materials_config_->pem_key_cert_pair_list());
542   size_t num_key_cert_pairs =
543       key_materials_config_->pem_key_cert_pair_list().size();
544   grpc_security_status status = grpc_ssl_tsi_server_handshaker_factory_init(
545       pem_key_cert_pairs, num_key_cert_pairs,
546       key_materials_config_->pem_root_certs(),
547       creds->options().cert_request_type(),
548       grpc_get_tsi_tls_version(creds->options().min_tls_version()),
549       grpc_get_tsi_tls_version(creds->options().max_tls_version()),
550       &server_handshaker_factory_);
551   /* Free memory. */
552   grpc_tsi_ssl_pem_key_cert_pairs_destroy(pem_key_cert_pairs,
553                                           num_key_cert_pairs);
554   return status;
555 }
556
557 grpc_security_status TlsServerSecurityConnector::InitializeHandshakerFactory() {
558   grpc_core::MutexLock lock(&mu_);
559   const TlsServerCredentials* creds =
560       static_cast<const TlsServerCredentials*>(server_creds());
561   grpc_tls_key_materials_config* key_materials_config =
562       creds->options().key_materials_config();
563   if (key_materials_config != nullptr) {
564     key_materials_config_->set_key_materials(
565         key_materials_config->pem_root_certs(),
566         key_materials_config->pem_key_cert_pair_list());
567   }
568   grpc_ssl_certificate_config_reload_status reload_status =
569       GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_UNCHANGED;
570   /** If |creds->options()| has a credential reload config, then the call to
571    *  |TlsFetchKeyMaterials| will use it to update the root cert and
572    *  pem-key-cert-pair list stored in |key_materials_config_|. Otherwise, it
573    *  will return |GRPC_STATUS_OK| if |key_materials_config_| already has
574    *  credentials, and an error code if not. **/
575   if (TlsFetchKeyMaterials(key_materials_config_, creds->options(), true,
576                            &reload_status) != GRPC_STATUS_OK) {
577     /* Raise an error if key materials are not populated. */
578     return GRPC_SECURITY_ERROR;
579   }
580   return ReplaceHandshakerFactory();
581 }
582
583 grpc_security_status TlsServerSecurityConnector::RefreshHandshakerFactory() {
584   grpc_core::MutexLock lock(&mu_);
585   const TlsServerCredentials* creds =
586       static_cast<const TlsServerCredentials*>(server_creds());
587   grpc_ssl_certificate_config_reload_status reload_status =
588       GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_UNCHANGED;
589   /** If |creds->options()| has a credential reload config, then the call to
590    *  |TlsFetchKeyMaterials| will use it to update the root cert and
591    *  pem-key-cert-pair list stored in |key_materials_config_|. Otherwise, it
592    *  will return |GRPC_STATUS_OK| if |key_materials_config_| already has
593    *  credentials, and an error code if not. **/
594   if (TlsFetchKeyMaterials(key_materials_config_, creds->options(), true,
595                            &reload_status) != GRPC_STATUS_OK) {
596     return GRPC_SECURITY_ERROR;
597   }
598   if (reload_status != GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_NEW) {
599     /* At this point, we should have key materials populated. */
600     return GRPC_SECURITY_OK;
601   } else {
602     return ReplaceHandshakerFactory();
603   }
604 }
605
606 }  // namespace grpc_core