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