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/ssl/ssl_security_connector.h"
22 
23 #include <stdbool.h>
24 
25 #include "absl/strings/str_cat.h"
26 #include "absl/strings/str_format.h"
27 #include "absl/strings/string_view.h"
28 
29 #include <grpc/support/alloc.h>
30 #include <grpc/support/log.h>
31 
32 #include "src/core/ext/transport/chttp2/alpn/alpn.h"
33 #include "src/core/lib/channel/handshaker.h"
34 #include "src/core/lib/gpr/string.h"
35 #include "src/core/lib/gprpp/host_port.h"
36 #include "src/core/lib/gprpp/ref_counted_ptr.h"
37 #include "src/core/lib/gprpp/sync.h"
38 #include "src/core/lib/security/context/security_context.h"
39 #include "src/core/lib/security/credentials/credentials.h"
40 #include "src/core/lib/security/credentials/ssl/ssl_credentials.h"
41 #include "src/core/lib/security/security_connector/load_system_roots.h"
42 #include "src/core/lib/security/security_connector/ssl_utils.h"
43 #include "src/core/lib/security/transport/security_handshaker.h"
44 #include "src/core/tsi/ssl_transport_security.h"
45 #include "src/core/tsi/transport_security.h"
46 
47 namespace {
ssl_check_peer(const char * peer_name,const tsi_peer * peer,grpc_core::RefCountedPtr<grpc_auth_context> * auth_context)48 grpc_error_handle ssl_check_peer(
49     const char* peer_name, const tsi_peer* peer,
50     grpc_core::RefCountedPtr<grpc_auth_context>* auth_context) {
51   grpc_error_handle error = grpc_ssl_check_alpn(peer);
52   if (error != GRPC_ERROR_NONE) {
53     return error;
54   }
55   /* Check the peer name if specified. */
56   if (peer_name != nullptr && !grpc_ssl_host_matches_name(peer, peer_name)) {
57     return GRPC_ERROR_CREATE_FROM_CPP_STRING(
58         absl::StrCat("Peer name ", peer_name, " is not in peer certificate"));
59   }
60   *auth_context =
61       grpc_ssl_peer_to_auth_context(peer, GRPC_SSL_TRANSPORT_SECURITY_TYPE);
62   return GRPC_ERROR_NONE;
63 }
64 
65 class grpc_ssl_channel_security_connector final
66     : public grpc_channel_security_connector {
67  public:
grpc_ssl_channel_security_connector(grpc_core::RefCountedPtr<grpc_channel_credentials> channel_creds,grpc_core::RefCountedPtr<grpc_call_credentials> request_metadata_creds,const grpc_ssl_config * config,const char * target_name,const char * overridden_target_name)68   grpc_ssl_channel_security_connector(
69       grpc_core::RefCountedPtr<grpc_channel_credentials> channel_creds,
70       grpc_core::RefCountedPtr<grpc_call_credentials> request_metadata_creds,
71       const grpc_ssl_config* config, const char* target_name,
72       const char* overridden_target_name)
73       : grpc_channel_security_connector(GRPC_SSL_URL_SCHEME,
74                                         std::move(channel_creds),
75                                         std::move(request_metadata_creds)),
76         overridden_target_name_(
77             overridden_target_name == nullptr ? "" : overridden_target_name),
78         verify_options_(&config->verify_options) {
79     absl::string_view host;
80     absl::string_view port;
81     grpc_core::SplitHostPort(target_name, &host, &port);
82     target_name_ = std::string(host);
83   }
84 
~grpc_ssl_channel_security_connector()85   ~grpc_ssl_channel_security_connector() override {
86     tsi_ssl_client_handshaker_factory_unref(client_handshaker_factory_);
87   }
88 
InitializeHandshakerFactory(const grpc_ssl_config * config,const char * pem_root_certs,const tsi_ssl_root_certs_store * root_store,tsi_ssl_session_cache * ssl_session_cache)89   grpc_security_status InitializeHandshakerFactory(
90       const grpc_ssl_config* config, const char* pem_root_certs,
91       const tsi_ssl_root_certs_store* root_store,
92       tsi_ssl_session_cache* ssl_session_cache) {
93     bool has_key_cert_pair =
94         config->pem_key_cert_pair != nullptr &&
95         config->pem_key_cert_pair->private_key != nullptr &&
96         config->pem_key_cert_pair->cert_chain != nullptr;
97     tsi_ssl_client_handshaker_options options;
98     GPR_DEBUG_ASSERT(pem_root_certs != nullptr);
99     options.pem_root_certs = pem_root_certs;
100     options.root_store = root_store;
101     options.alpn_protocols =
102         grpc_fill_alpn_protocol_strings(&options.num_alpn_protocols);
103     if (has_key_cert_pair) {
104       options.pem_key_cert_pair = config->pem_key_cert_pair;
105     }
106     options.cipher_suites = grpc_get_ssl_cipher_suites();
107     options.session_cache = ssl_session_cache;
108     options.min_tls_version = grpc_get_tsi_tls_version(config->min_tls_version);
109     options.max_tls_version = grpc_get_tsi_tls_version(config->max_tls_version);
110     const tsi_result result =
111         tsi_create_ssl_client_handshaker_factory_with_options(
112             &options, &client_handshaker_factory_);
113     gpr_free(options.alpn_protocols);
114     if (result != TSI_OK) {
115       gpr_log(GPR_ERROR, "Handshaker factory creation failed with %s.",
116               tsi_result_to_string(result));
117       return GRPC_SECURITY_ERROR;
118     }
119     return GRPC_SECURITY_OK;
120   }
121 
add_handshakers(const grpc_channel_args * args,grpc_pollset_set *,grpc_core::HandshakeManager * handshake_mgr)122   void add_handshakers(const grpc_channel_args* args,
123                        grpc_pollset_set* /*interested_parties*/,
124                        grpc_core::HandshakeManager* handshake_mgr) override {
125     // Instantiate TSI handshaker.
126     tsi_handshaker* tsi_hs = nullptr;
127     tsi_result result = tsi_ssl_client_handshaker_factory_create_handshaker(
128         client_handshaker_factory_,
129         overridden_target_name_.empty() ? target_name_.c_str()
130                                         : overridden_target_name_.c_str(),
131         &tsi_hs);
132     if (result != TSI_OK) {
133       gpr_log(GPR_ERROR, "Handshaker creation failed with error %s.",
134               tsi_result_to_string(result));
135       return;
136     }
137     // Create handshakers.
138     handshake_mgr->Add(grpc_core::SecurityHandshakerCreate(tsi_hs, this, args));
139   }
140 
check_peer(tsi_peer peer,grpc_endpoint *,grpc_core::RefCountedPtr<grpc_auth_context> * auth_context,grpc_closure * on_peer_checked)141   void check_peer(tsi_peer peer, grpc_endpoint* /*ep*/,
142                   grpc_core::RefCountedPtr<grpc_auth_context>* auth_context,
143                   grpc_closure* on_peer_checked) override {
144     const char* target_name = overridden_target_name_.empty()
145                                   ? target_name_.c_str()
146                                   : overridden_target_name_.c_str();
147     grpc_error_handle error = ssl_check_peer(target_name, &peer, auth_context);
148     if (error == GRPC_ERROR_NONE &&
149         verify_options_->verify_peer_callback != nullptr) {
150       const tsi_peer_property* p =
151           tsi_peer_get_property_by_name(&peer, TSI_X509_PEM_CERT_PROPERTY);
152       if (p == nullptr) {
153         error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(
154             "Cannot check peer: missing pem cert property.");
155       } else {
156         char* peer_pem = static_cast<char*>(gpr_malloc(p->value.length + 1));
157         memcpy(peer_pem, p->value.data, p->value.length);
158         peer_pem[p->value.length] = '\0';
159         int callback_status = verify_options_->verify_peer_callback(
160             target_name, peer_pem,
161             verify_options_->verify_peer_callback_userdata);
162         gpr_free(peer_pem);
163         if (callback_status) {
164           error = GRPC_ERROR_CREATE_FROM_CPP_STRING(absl::StrFormat(
165               "Verify peer callback returned a failure (%d)", callback_status));
166         }
167       }
168     }
169     grpc_core::ExecCtx::Run(DEBUG_LOCATION, on_peer_checked, error);
170     tsi_peer_destruct(&peer);
171   }
172 
cancel_check_peer(grpc_closure *,grpc_error_handle error)173   void cancel_check_peer(grpc_closure* /*on_peer_checked*/,
174                          grpc_error_handle error) override {
175     GRPC_ERROR_UNREF(error);
176   }
177 
cmp(const grpc_security_connector * other_sc) const178   int cmp(const grpc_security_connector* other_sc) const override {
179     auto* other =
180         reinterpret_cast<const grpc_ssl_channel_security_connector*>(other_sc);
181     int c = channel_security_connector_cmp(other);
182     if (c != 0) return c;
183     c = target_name_.compare(other->target_name_);
184     if (c != 0) return c;
185     return overridden_target_name_.compare(other->overridden_target_name_);
186   }
187 
check_call_host(absl::string_view host,grpc_auth_context * auth_context,grpc_closure *,grpc_error_handle * error)188   bool check_call_host(absl::string_view host, grpc_auth_context* auth_context,
189                        grpc_closure* /*on_call_host_checked*/,
190                        grpc_error_handle* error) override {
191     return grpc_ssl_check_call_host(host, target_name_.c_str(),
192                                     overridden_target_name_.c_str(),
193                                     auth_context, error);
194   }
195 
cancel_check_call_host(grpc_closure *,grpc_error_handle error)196   void cancel_check_call_host(grpc_closure* /*on_call_host_checked*/,
197                               grpc_error_handle error) override {
198     GRPC_ERROR_UNREF(error);
199   }
200 
201  private:
202   tsi_ssl_client_handshaker_factory* client_handshaker_factory_;
203   std::string target_name_;
204   std::string overridden_target_name_;
205   const verify_peer_options* verify_options_;
206 };
207 
208 class grpc_ssl_server_security_connector
209     : public grpc_server_security_connector {
210  public:
grpc_ssl_server_security_connector(grpc_core::RefCountedPtr<grpc_server_credentials> server_creds)211   explicit grpc_ssl_server_security_connector(
212       grpc_core::RefCountedPtr<grpc_server_credentials> server_creds)
213       : grpc_server_security_connector(GRPC_SSL_URL_SCHEME,
214                                        std::move(server_creds)) {}
215 
~grpc_ssl_server_security_connector()216   ~grpc_ssl_server_security_connector() override {
217     tsi_ssl_server_handshaker_factory_unref(server_handshaker_factory_);
218   }
219 
has_cert_config_fetcher() const220   bool has_cert_config_fetcher() const {
221     return static_cast<const grpc_ssl_server_credentials*>(server_creds())
222         ->has_cert_config_fetcher();
223   }
224 
server_handshaker_factory() const225   const tsi_ssl_server_handshaker_factory* server_handshaker_factory() const {
226     return server_handshaker_factory_;
227   }
228 
InitializeHandshakerFactory()229   grpc_security_status InitializeHandshakerFactory() {
230     if (has_cert_config_fetcher()) {
231       // Load initial credentials from certificate_config_fetcher:
232       if (!try_fetch_ssl_server_credentials()) {
233         gpr_log(GPR_ERROR,
234                 "Failed loading SSL server credentials from fetcher.");
235         return GRPC_SECURITY_ERROR;
236       }
237     } else {
238       auto* server_credentials =
239           static_cast<const grpc_ssl_server_credentials*>(server_creds());
240       size_t num_alpn_protocols = 0;
241       const char** alpn_protocol_strings =
242           grpc_fill_alpn_protocol_strings(&num_alpn_protocols);
243       tsi_ssl_server_handshaker_options options;
244       options.pem_key_cert_pairs =
245           server_credentials->config().pem_key_cert_pairs;
246       options.num_key_cert_pairs =
247           server_credentials->config().num_key_cert_pairs;
248       options.pem_client_root_certs =
249           server_credentials->config().pem_root_certs;
250       options.client_certificate_request =
251           grpc_get_tsi_client_certificate_request_type(
252               server_credentials->config().client_certificate_request);
253       options.cipher_suites = grpc_get_ssl_cipher_suites();
254       options.alpn_protocols = alpn_protocol_strings;
255       options.num_alpn_protocols = static_cast<uint16_t>(num_alpn_protocols);
256       options.min_tls_version = grpc_get_tsi_tls_version(
257           server_credentials->config().min_tls_version);
258       options.max_tls_version = grpc_get_tsi_tls_version(
259           server_credentials->config().max_tls_version);
260       const tsi_result result =
261           tsi_create_ssl_server_handshaker_factory_with_options(
262               &options, &server_handshaker_factory_);
263       gpr_free(alpn_protocol_strings);
264       if (result != TSI_OK) {
265         gpr_log(GPR_ERROR, "Handshaker factory creation failed with %s.",
266                 tsi_result_to_string(result));
267         return GRPC_SECURITY_ERROR;
268       }
269     }
270     return GRPC_SECURITY_OK;
271   }
272 
add_handshakers(const grpc_channel_args * args,grpc_pollset_set *,grpc_core::HandshakeManager * handshake_mgr)273   void add_handshakers(const grpc_channel_args* args,
274                        grpc_pollset_set* /*interested_parties*/,
275                        grpc_core::HandshakeManager* handshake_mgr) override {
276     // Instantiate TSI handshaker.
277     try_fetch_ssl_server_credentials();
278     tsi_handshaker* tsi_hs = nullptr;
279     tsi_result result = tsi_ssl_server_handshaker_factory_create_handshaker(
280         server_handshaker_factory_, &tsi_hs);
281     if (result != TSI_OK) {
282       gpr_log(GPR_ERROR, "Handshaker creation failed with error %s.",
283               tsi_result_to_string(result));
284       return;
285     }
286     // Create handshakers.
287     handshake_mgr->Add(grpc_core::SecurityHandshakerCreate(tsi_hs, this, args));
288   }
289 
check_peer(tsi_peer peer,grpc_endpoint *,grpc_core::RefCountedPtr<grpc_auth_context> * auth_context,grpc_closure * on_peer_checked)290   void check_peer(tsi_peer peer, grpc_endpoint* /*ep*/,
291                   grpc_core::RefCountedPtr<grpc_auth_context>* auth_context,
292                   grpc_closure* on_peer_checked) override {
293     grpc_error_handle error = ssl_check_peer(nullptr, &peer, auth_context);
294     tsi_peer_destruct(&peer);
295     grpc_core::ExecCtx::Run(DEBUG_LOCATION, on_peer_checked, error);
296   }
297 
cancel_check_peer(grpc_closure *,grpc_error_handle error)298   void cancel_check_peer(grpc_closure* /*on_peer_checked*/,
299                          grpc_error_handle error) override {
300     GRPC_ERROR_UNREF(error);
301   }
302 
cmp(const grpc_security_connector * other) const303   int cmp(const grpc_security_connector* other) const override {
304     return server_security_connector_cmp(
305         static_cast<const grpc_server_security_connector*>(other));
306   }
307 
308  private:
309   /* Attempts to fetch the server certificate config if a callback is available.
310    * Current certificate config will continue to be used if the callback returns
311    * an error. Returns true if new credentials were successfully loaded. */
try_fetch_ssl_server_credentials()312   bool try_fetch_ssl_server_credentials() {
313     grpc_ssl_server_certificate_config* certificate_config = nullptr;
314     bool status;
315     if (!has_cert_config_fetcher()) return false;
316 
317     grpc_core::MutexLock lock(&mu_);
318     grpc_ssl_server_credentials* server_creds =
319         static_cast<grpc_ssl_server_credentials*>(this->mutable_server_creds());
320     grpc_ssl_certificate_config_reload_status cb_result =
321         server_creds->FetchCertConfig(&certificate_config);
322     if (cb_result == GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_UNCHANGED) {
323       gpr_log(GPR_DEBUG, "No change in SSL server credentials.");
324       status = false;
325     } else if (cb_result == GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_NEW) {
326       status = try_replace_server_handshaker_factory(certificate_config);
327     } else {
328       // Log error, continue using previously-loaded credentials.
329       gpr_log(GPR_ERROR,
330               "Failed fetching new server credentials, continuing to "
331               "use previously-loaded credentials.");
332       status = false;
333     }
334 
335     if (certificate_config != nullptr) {
336       grpc_ssl_server_certificate_config_destroy(certificate_config);
337     }
338     return status;
339   }
340 
341   /* Attempts to replace the server_handshaker_factory with a new factory using
342    * the provided grpc_ssl_server_certificate_config. Should new factory
343    * creation fail, the existing factory will not be replaced. Returns true on
344    * success (new factory created). */
try_replace_server_handshaker_factory(const grpc_ssl_server_certificate_config * config)345   bool try_replace_server_handshaker_factory(
346       const grpc_ssl_server_certificate_config* config) {
347     if (config == nullptr) {
348       gpr_log(GPR_ERROR,
349               "Server certificate config callback returned invalid (NULL) "
350               "config.");
351       return false;
352     }
353     gpr_log(GPR_DEBUG, "Using new server certificate config (%p).", config);
354 
355     size_t num_alpn_protocols = 0;
356     const char** alpn_protocol_strings =
357         grpc_fill_alpn_protocol_strings(&num_alpn_protocols);
358     tsi_ssl_server_handshaker_factory* new_handshaker_factory = nullptr;
359     const grpc_ssl_server_credentials* server_creds =
360         static_cast<const grpc_ssl_server_credentials*>(this->server_creds());
361     GPR_DEBUG_ASSERT(config->pem_root_certs != nullptr);
362     tsi_ssl_server_handshaker_options options;
363     options.pem_key_cert_pairs = grpc_convert_grpc_to_tsi_cert_pairs(
364         config->pem_key_cert_pairs, config->num_key_cert_pairs);
365     options.num_key_cert_pairs = config->num_key_cert_pairs;
366     options.pem_client_root_certs = config->pem_root_certs;
367     options.client_certificate_request =
368         grpc_get_tsi_client_certificate_request_type(
369             server_creds->config().client_certificate_request);
370     options.cipher_suites = grpc_get_ssl_cipher_suites();
371     options.alpn_protocols = alpn_protocol_strings;
372     options.num_alpn_protocols = static_cast<uint16_t>(num_alpn_protocols);
373     tsi_result result = tsi_create_ssl_server_handshaker_factory_with_options(
374         &options, &new_handshaker_factory);
375     grpc_tsi_ssl_pem_key_cert_pairs_destroy(
376         const_cast<tsi_ssl_pem_key_cert_pair*>(options.pem_key_cert_pairs),
377         options.num_key_cert_pairs);
378     gpr_free(alpn_protocol_strings);
379 
380     if (result != TSI_OK) {
381       gpr_log(GPR_ERROR, "Handshaker factory creation failed with %s.",
382               tsi_result_to_string(result));
383       return false;
384     }
385     set_server_handshaker_factory(new_handshaker_factory);
386     return true;
387   }
388 
set_server_handshaker_factory(tsi_ssl_server_handshaker_factory * new_factory)389   void set_server_handshaker_factory(
390       tsi_ssl_server_handshaker_factory* new_factory) {
391     if (server_handshaker_factory_) {
392       tsi_ssl_server_handshaker_factory_unref(server_handshaker_factory_);
393     }
394     server_handshaker_factory_ = new_factory;
395   }
396 
397   grpc_core::Mutex mu_;
398   tsi_ssl_server_handshaker_factory* server_handshaker_factory_ = nullptr;
399 };
400 }  // namespace
401 
402 grpc_core::RefCountedPtr<grpc_channel_security_connector>
grpc_ssl_channel_security_connector_create(grpc_core::RefCountedPtr<grpc_channel_credentials> channel_creds,grpc_core::RefCountedPtr<grpc_call_credentials> request_metadata_creds,const grpc_ssl_config * config,const char * target_name,const char * overridden_target_name,tsi_ssl_session_cache * ssl_session_cache)403 grpc_ssl_channel_security_connector_create(
404     grpc_core::RefCountedPtr<grpc_channel_credentials> channel_creds,
405     grpc_core::RefCountedPtr<grpc_call_credentials> request_metadata_creds,
406     const grpc_ssl_config* config, const char* target_name,
407     const char* overridden_target_name,
408     tsi_ssl_session_cache* ssl_session_cache) {
409   if (config == nullptr || target_name == nullptr) {
410     gpr_log(GPR_ERROR, "An ssl channel needs a config and a target name.");
411     return nullptr;
412   }
413 
414   const char* pem_root_certs;
415   const tsi_ssl_root_certs_store* root_store;
416   if (config->pem_root_certs == nullptr) {
417     // Use default root certificates.
418     pem_root_certs = grpc_core::DefaultSslRootStore::GetPemRootCerts();
419     if (pem_root_certs == nullptr) {
420       gpr_log(GPR_ERROR, "Could not get default pem root certs.");
421       return nullptr;
422     }
423     root_store = grpc_core::DefaultSslRootStore::GetRootStore();
424   } else {
425     pem_root_certs = config->pem_root_certs;
426     root_store = nullptr;
427   }
428 
429   grpc_core::RefCountedPtr<grpc_ssl_channel_security_connector> c =
430       grpc_core::MakeRefCounted<grpc_ssl_channel_security_connector>(
431           std::move(channel_creds), std::move(request_metadata_creds), config,
432           target_name, overridden_target_name);
433   const grpc_security_status result = c->InitializeHandshakerFactory(
434       config, pem_root_certs, root_store, ssl_session_cache);
435   if (result != GRPC_SECURITY_OK) {
436     return nullptr;
437   }
438   return c;
439 }
440 
441 grpc_core::RefCountedPtr<grpc_server_security_connector>
grpc_ssl_server_security_connector_create(grpc_core::RefCountedPtr<grpc_server_credentials> server_credentials)442 grpc_ssl_server_security_connector_create(
443     grpc_core::RefCountedPtr<grpc_server_credentials> server_credentials) {
444   GPR_ASSERT(server_credentials != nullptr);
445   grpc_core::RefCountedPtr<grpc_ssl_server_security_connector> c =
446       grpc_core::MakeRefCounted<grpc_ssl_server_security_connector>(
447           std::move(server_credentials));
448   const grpc_security_status retval = c->InitializeHandshakerFactory();
449   if (retval != GRPC_SECURITY_OK) {
450     return nullptr;
451   }
452   return c;
453 }
454