1 //
2 //
3 // Copyright 2016 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/credentials/ssl/ssl_credentials.h"
22 
23 #include <string.h>
24 
25 #include <string>
26 #include <utility>
27 
28 #include "absl/strings/string_view.h"
29 #include "absl/types/optional.h"
30 
31 #include <grpc/support/alloc.h>
32 #include <grpc/support/log.h>
33 #include <grpc/support/string_util.h>
34 
35 #include "src/core/lib/channel/channel_args.h"
36 #include "src/core/lib/debug/trace.h"
37 #include "src/core/lib/security/security_connector/ssl_utils.h"
38 #include "src/core/lib/surface/api_trace.h"
39 #include "src/core/tsi/ssl/session_cache/ssl_session_cache.h"
40 #include "src/core/tsi/ssl_transport_security.h"
41 
42 //
43 // SSL Channel Credentials.
44 //
45 
grpc_ssl_credentials(const char * pem_root_certs,grpc_ssl_pem_key_cert_pair * pem_key_cert_pair,const grpc_ssl_verify_peer_options * verify_options)46 grpc_ssl_credentials::grpc_ssl_credentials(
47     const char* pem_root_certs, grpc_ssl_pem_key_cert_pair* pem_key_cert_pair,
48     const grpc_ssl_verify_peer_options* verify_options) {
49   build_config(pem_root_certs, pem_key_cert_pair, verify_options);
50 }
51 
~grpc_ssl_credentials()52 grpc_ssl_credentials::~grpc_ssl_credentials() {
53   gpr_free(config_.pem_root_certs);
54   grpc_tsi_ssl_pem_key_cert_pairs_destroy(config_.pem_key_cert_pair, 1);
55   if (config_.verify_options.verify_peer_destruct != nullptr) {
56     config_.verify_options.verify_peer_destruct(
57         config_.verify_options.verify_peer_callback_userdata);
58   }
59 }
60 
61 grpc_core::RefCountedPtr<grpc_channel_security_connector>
create_security_connector(grpc_core::RefCountedPtr<grpc_call_credentials> call_creds,const char * target,grpc_core::ChannelArgs * args)62 grpc_ssl_credentials::create_security_connector(
63     grpc_core::RefCountedPtr<grpc_call_credentials> call_creds,
64     const char* target, grpc_core::ChannelArgs* args) {
65   absl::optional<std::string> overridden_target_name =
66       args->GetOwnedString(GRPC_SSL_TARGET_NAME_OVERRIDE_ARG);
67   auto* ssl_session_cache = args->GetObject<tsi::SslSessionLRUCache>();
68   grpc_core::RefCountedPtr<grpc_channel_security_connector> sc =
69       grpc_ssl_channel_security_connector_create(
70           this->Ref(), std::move(call_creds), &config_, target,
71           overridden_target_name.has_value() ? overridden_target_name->c_str()
72                                              : nullptr,
73           ssl_session_cache == nullptr ? nullptr : ssl_session_cache->c_ptr());
74   if (sc == nullptr) {
75     return sc;
76   }
77   *args = args->Set(GRPC_ARG_HTTP2_SCHEME, "https");
78   return sc;
79 }
80 
Type()81 grpc_core::UniqueTypeName grpc_ssl_credentials::Type() {
82   static grpc_core::UniqueTypeName::Factory kFactory("Ssl");
83   return kFactory.Create();
84 }
85 
build_config(const char * pem_root_certs,grpc_ssl_pem_key_cert_pair * pem_key_cert_pair,const grpc_ssl_verify_peer_options * verify_options)86 void grpc_ssl_credentials::build_config(
87     const char* pem_root_certs, grpc_ssl_pem_key_cert_pair* pem_key_cert_pair,
88     const grpc_ssl_verify_peer_options* verify_options) {
89   config_.pem_root_certs = gpr_strdup(pem_root_certs);
90   if (pem_key_cert_pair != nullptr) {
91     GPR_ASSERT(pem_key_cert_pair->private_key != nullptr);
92     GPR_ASSERT(pem_key_cert_pair->cert_chain != nullptr);
93     config_.pem_key_cert_pair = static_cast<tsi_ssl_pem_key_cert_pair*>(
94         gpr_zalloc(sizeof(tsi_ssl_pem_key_cert_pair)));
95     config_.pem_key_cert_pair->cert_chain =
96         gpr_strdup(pem_key_cert_pair->cert_chain);
97     config_.pem_key_cert_pair->private_key =
98         gpr_strdup(pem_key_cert_pair->private_key);
99   } else {
100     config_.pem_key_cert_pair = nullptr;
101   }
102   if (verify_options != nullptr) {
103     memcpy(&config_.verify_options, verify_options,
104            sizeof(verify_peer_options));
105   } else {
106     // Otherwise set all options to default values
107     memset(&config_.verify_options, 0, sizeof(verify_peer_options));
108   }
109 }
110 
set_min_tls_version(grpc_tls_version min_tls_version)111 void grpc_ssl_credentials::set_min_tls_version(
112     grpc_tls_version min_tls_version) {
113   config_.min_tls_version = min_tls_version;
114 }
115 
set_max_tls_version(grpc_tls_version max_tls_version)116 void grpc_ssl_credentials::set_max_tls_version(
117     grpc_tls_version max_tls_version) {
118   config_.max_tls_version = max_tls_version;
119 }
120 
121 // Deprecated in favor of grpc_ssl_credentials_create_ex. Will be removed
122 // once all of its call sites are migrated to grpc_ssl_credentials_create_ex.
grpc_ssl_credentials_create(const char * pem_root_certs,grpc_ssl_pem_key_cert_pair * pem_key_cert_pair,const verify_peer_options * verify_options,void * reserved)123 grpc_channel_credentials* grpc_ssl_credentials_create(
124     const char* pem_root_certs, grpc_ssl_pem_key_cert_pair* pem_key_cert_pair,
125     const verify_peer_options* verify_options, void* reserved) {
126   GRPC_API_TRACE(
127       "grpc_ssl_credentials_create(pem_root_certs=%s, "
128       "pem_key_cert_pair=%p, "
129       "verify_options=%p, "
130       "reserved=%p)",
131       4, (pem_root_certs, pem_key_cert_pair, verify_options, reserved));
132   GPR_ASSERT(reserved == nullptr);
133 
134   return new grpc_ssl_credentials(
135       pem_root_certs, pem_key_cert_pair,
136       reinterpret_cast<const grpc_ssl_verify_peer_options*>(verify_options));
137 }
138 
grpc_ssl_credentials_create_ex(const char * pem_root_certs,grpc_ssl_pem_key_cert_pair * pem_key_cert_pair,const grpc_ssl_verify_peer_options * verify_options,void * reserved)139 grpc_channel_credentials* grpc_ssl_credentials_create_ex(
140     const char* pem_root_certs, grpc_ssl_pem_key_cert_pair* pem_key_cert_pair,
141     const grpc_ssl_verify_peer_options* verify_options, void* reserved) {
142   GRPC_API_TRACE(
143       "grpc_ssl_credentials_create(pem_root_certs=%s, "
144       "pem_key_cert_pair=%p, "
145       "verify_options=%p, "
146       "reserved=%p)",
147       4, (pem_root_certs, pem_key_cert_pair, verify_options, reserved));
148   GPR_ASSERT(reserved == nullptr);
149 
150   return new grpc_ssl_credentials(pem_root_certs, pem_key_cert_pair,
151                                   verify_options);
152 }
153 
154 //
155 // SSL Server Credentials.
156 //
157 
158 struct grpc_ssl_server_credentials_options {
159   grpc_ssl_client_certificate_request_type client_certificate_request;
160   grpc_ssl_server_certificate_config* certificate_config;
161   grpc_ssl_server_certificate_config_fetcher* certificate_config_fetcher;
162 };
163 
grpc_ssl_server_credentials(const grpc_ssl_server_credentials_options & options)164 grpc_ssl_server_credentials::grpc_ssl_server_credentials(
165     const grpc_ssl_server_credentials_options& options) {
166   if (options.certificate_config_fetcher != nullptr) {
167     config_.client_certificate_request = options.client_certificate_request;
168     certificate_config_fetcher_ = *options.certificate_config_fetcher;
169   } else {
170     build_config(options.certificate_config->pem_root_certs,
171                  options.certificate_config->pem_key_cert_pairs,
172                  options.certificate_config->num_key_cert_pairs,
173                  options.client_certificate_request);
174   }
175 }
176 
~grpc_ssl_server_credentials()177 grpc_ssl_server_credentials::~grpc_ssl_server_credentials() {
178   grpc_tsi_ssl_pem_key_cert_pairs_destroy(config_.pem_key_cert_pairs,
179                                           config_.num_key_cert_pairs);
180   gpr_free(config_.pem_root_certs);
181 }
182 grpc_core::RefCountedPtr<grpc_server_security_connector>
create_security_connector(const grpc_core::ChannelArgs &)183 grpc_ssl_server_credentials::create_security_connector(
184     const grpc_core::ChannelArgs& /* args */) {
185   return grpc_ssl_server_security_connector_create(this->Ref());
186 }
187 
Type()188 grpc_core::UniqueTypeName grpc_ssl_server_credentials::Type() {
189   static grpc_core::UniqueTypeName::Factory kFactory("Ssl");
190   return kFactory.Create();
191 }
192 
grpc_convert_grpc_to_tsi_cert_pairs(const grpc_ssl_pem_key_cert_pair * pem_key_cert_pairs,size_t num_key_cert_pairs)193 tsi_ssl_pem_key_cert_pair* grpc_convert_grpc_to_tsi_cert_pairs(
194     const grpc_ssl_pem_key_cert_pair* pem_key_cert_pairs,
195     size_t num_key_cert_pairs) {
196   tsi_ssl_pem_key_cert_pair* tsi_pairs = nullptr;
197   if (num_key_cert_pairs > 0) {
198     GPR_ASSERT(pem_key_cert_pairs != nullptr);
199     tsi_pairs = static_cast<tsi_ssl_pem_key_cert_pair*>(
200         gpr_zalloc(num_key_cert_pairs * sizeof(tsi_ssl_pem_key_cert_pair)));
201   }
202   for (size_t i = 0; i < num_key_cert_pairs; i++) {
203     GPR_ASSERT(pem_key_cert_pairs[i].private_key != nullptr);
204     GPR_ASSERT(pem_key_cert_pairs[i].cert_chain != nullptr);
205     tsi_pairs[i].cert_chain = gpr_strdup(pem_key_cert_pairs[i].cert_chain);
206     tsi_pairs[i].private_key = gpr_strdup(pem_key_cert_pairs[i].private_key);
207   }
208   return tsi_pairs;
209 }
210 
build_config(const char * pem_root_certs,grpc_ssl_pem_key_cert_pair * pem_key_cert_pairs,size_t num_key_cert_pairs,grpc_ssl_client_certificate_request_type client_certificate_request)211 void grpc_ssl_server_credentials::build_config(
212     const char* pem_root_certs, grpc_ssl_pem_key_cert_pair* pem_key_cert_pairs,
213     size_t num_key_cert_pairs,
214     grpc_ssl_client_certificate_request_type client_certificate_request) {
215   config_.client_certificate_request = client_certificate_request;
216   config_.pem_root_certs = gpr_strdup(pem_root_certs);
217   config_.pem_key_cert_pairs = grpc_convert_grpc_to_tsi_cert_pairs(
218       pem_key_cert_pairs, num_key_cert_pairs);
219   config_.num_key_cert_pairs = num_key_cert_pairs;
220 }
221 
set_min_tls_version(grpc_tls_version min_tls_version)222 void grpc_ssl_server_credentials::set_min_tls_version(
223     grpc_tls_version min_tls_version) {
224   config_.min_tls_version = min_tls_version;
225 }
226 
set_max_tls_version(grpc_tls_version max_tls_version)227 void grpc_ssl_server_credentials::set_max_tls_version(
228     grpc_tls_version max_tls_version) {
229   config_.max_tls_version = max_tls_version;
230 }
231 
grpc_ssl_server_certificate_config_create(const char * pem_root_certs,const grpc_ssl_pem_key_cert_pair * pem_key_cert_pairs,size_t num_key_cert_pairs)232 grpc_ssl_server_certificate_config* grpc_ssl_server_certificate_config_create(
233     const char* pem_root_certs,
234     const grpc_ssl_pem_key_cert_pair* pem_key_cert_pairs,
235     size_t num_key_cert_pairs) {
236   grpc_ssl_server_certificate_config* config =
237       static_cast<grpc_ssl_server_certificate_config*>(
238           gpr_zalloc(sizeof(grpc_ssl_server_certificate_config)));
239   config->pem_root_certs = gpr_strdup(pem_root_certs);
240   if (num_key_cert_pairs > 0) {
241     GPR_ASSERT(pem_key_cert_pairs != nullptr);
242     config->pem_key_cert_pairs = static_cast<grpc_ssl_pem_key_cert_pair*>(
243         gpr_zalloc(num_key_cert_pairs * sizeof(grpc_ssl_pem_key_cert_pair)));
244   }
245   config->num_key_cert_pairs = num_key_cert_pairs;
246   for (size_t i = 0; i < num_key_cert_pairs; i++) {
247     GPR_ASSERT(pem_key_cert_pairs[i].private_key != nullptr);
248     GPR_ASSERT(pem_key_cert_pairs[i].cert_chain != nullptr);
249     config->pem_key_cert_pairs[i].cert_chain =
250         gpr_strdup(pem_key_cert_pairs[i].cert_chain);
251     config->pem_key_cert_pairs[i].private_key =
252         gpr_strdup(pem_key_cert_pairs[i].private_key);
253   }
254   return config;
255 }
256 
grpc_ssl_server_certificate_config_destroy(grpc_ssl_server_certificate_config * config)257 void grpc_ssl_server_certificate_config_destroy(
258     grpc_ssl_server_certificate_config* config) {
259   if (config == nullptr) return;
260   for (size_t i = 0; i < config->num_key_cert_pairs; i++) {
261     gpr_free(const_cast<char*>(config->pem_key_cert_pairs[i].private_key));
262     gpr_free(const_cast<char*>(config->pem_key_cert_pairs[i].cert_chain));
263   }
264   gpr_free(config->pem_key_cert_pairs);
265   gpr_free(config->pem_root_certs);
266   gpr_free(config);
267 }
268 
269 grpc_ssl_server_credentials_options*
grpc_ssl_server_credentials_create_options_using_config(grpc_ssl_client_certificate_request_type client_certificate_request,grpc_ssl_server_certificate_config * config)270 grpc_ssl_server_credentials_create_options_using_config(
271     grpc_ssl_client_certificate_request_type client_certificate_request,
272     grpc_ssl_server_certificate_config* config) {
273   grpc_ssl_server_credentials_options* options = nullptr;
274   if (config == nullptr) {
275     gpr_log(GPR_ERROR, "Certificate config must not be NULL.");
276     goto done;
277   }
278   options = static_cast<grpc_ssl_server_credentials_options*>(
279       gpr_zalloc(sizeof(grpc_ssl_server_credentials_options)));
280   options->client_certificate_request = client_certificate_request;
281   options->certificate_config = config;
282 done:
283   return options;
284 }
285 
286 grpc_ssl_server_credentials_options*
grpc_ssl_server_credentials_create_options_using_config_fetcher(grpc_ssl_client_certificate_request_type client_certificate_request,grpc_ssl_server_certificate_config_callback cb,void * user_data)287 grpc_ssl_server_credentials_create_options_using_config_fetcher(
288     grpc_ssl_client_certificate_request_type client_certificate_request,
289     grpc_ssl_server_certificate_config_callback cb, void* user_data) {
290   if (cb == nullptr) {
291     gpr_log(GPR_ERROR, "Invalid certificate config callback parameter.");
292     return nullptr;
293   }
294 
295   grpc_ssl_server_certificate_config_fetcher* fetcher =
296       static_cast<grpc_ssl_server_certificate_config_fetcher*>(
297           gpr_zalloc(sizeof(grpc_ssl_server_certificate_config_fetcher)));
298   fetcher->cb = cb;
299   fetcher->user_data = user_data;
300 
301   grpc_ssl_server_credentials_options* options =
302       static_cast<grpc_ssl_server_credentials_options*>(
303           gpr_zalloc(sizeof(grpc_ssl_server_credentials_options)));
304   options->client_certificate_request = client_certificate_request;
305   options->certificate_config_fetcher = fetcher;
306 
307   return options;
308 }
309 
grpc_ssl_server_credentials_create(const char * pem_root_certs,grpc_ssl_pem_key_cert_pair * pem_key_cert_pairs,size_t num_key_cert_pairs,int force_client_auth,void * reserved)310 grpc_server_credentials* grpc_ssl_server_credentials_create(
311     const char* pem_root_certs, grpc_ssl_pem_key_cert_pair* pem_key_cert_pairs,
312     size_t num_key_cert_pairs, int force_client_auth, void* reserved) {
313   return grpc_ssl_server_credentials_create_ex(
314       pem_root_certs, pem_key_cert_pairs, num_key_cert_pairs,
315       force_client_auth
316           ? GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY
317           : GRPC_SSL_DONT_REQUEST_CLIENT_CERTIFICATE,
318       reserved);
319 }
320 
grpc_ssl_server_credentials_create_ex(const char * pem_root_certs,grpc_ssl_pem_key_cert_pair * pem_key_cert_pairs,size_t num_key_cert_pairs,grpc_ssl_client_certificate_request_type client_certificate_request,void * reserved)321 grpc_server_credentials* grpc_ssl_server_credentials_create_ex(
322     const char* pem_root_certs, grpc_ssl_pem_key_cert_pair* pem_key_cert_pairs,
323     size_t num_key_cert_pairs,
324     grpc_ssl_client_certificate_request_type client_certificate_request,
325     void* reserved) {
326   GRPC_API_TRACE(
327       "grpc_ssl_server_credentials_create_ex("
328       "pem_root_certs=%s, pem_key_cert_pairs=%p, num_key_cert_pairs=%lu, "
329       "client_certificate_request=%d, reserved=%p)",
330       5,
331       (pem_root_certs, pem_key_cert_pairs, (unsigned long)num_key_cert_pairs,
332        client_certificate_request, reserved));
333   GPR_ASSERT(reserved == nullptr);
334 
335   grpc_ssl_server_certificate_config* cert_config =
336       grpc_ssl_server_certificate_config_create(
337           pem_root_certs, pem_key_cert_pairs, num_key_cert_pairs);
338   grpc_ssl_server_credentials_options* options =
339       grpc_ssl_server_credentials_create_options_using_config(
340           client_certificate_request, cert_config);
341 
342   return grpc_ssl_server_credentials_create_with_options(options);
343 }
344 
grpc_ssl_server_credentials_create_with_options(grpc_ssl_server_credentials_options * options)345 grpc_server_credentials* grpc_ssl_server_credentials_create_with_options(
346     grpc_ssl_server_credentials_options* options) {
347   grpc_server_credentials* retval = nullptr;
348 
349   if (options == nullptr) {
350     gpr_log(GPR_ERROR,
351             "Invalid options trying to create SSL server credentials.");
352     goto done;
353   }
354 
355   if (options->certificate_config == nullptr &&
356       options->certificate_config_fetcher == nullptr) {
357     gpr_log(GPR_ERROR,
358             "SSL server credentials options must specify either "
359             "certificate config or fetcher.");
360     goto done;
361   } else if (options->certificate_config_fetcher != nullptr &&
362              options->certificate_config_fetcher->cb == nullptr) {
363     gpr_log(GPR_ERROR, "Certificate config fetcher callback must not be NULL.");
364     goto done;
365   }
366 
367   retval = new grpc_ssl_server_credentials(*options);
368 
369 done:
370   grpc_ssl_server_credentials_options_destroy(options);
371   return retval;
372 }
373 
grpc_ssl_server_credentials_options_destroy(grpc_ssl_server_credentials_options * o)374 void grpc_ssl_server_credentials_options_destroy(
375     grpc_ssl_server_credentials_options* o) {
376   if (o == nullptr) return;
377   gpr_free(o->certificate_config_fetcher);
378   grpc_ssl_server_certificate_config_destroy(o->certificate_config);
379   gpr_free(o);
380 }
381