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