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((void*)kp[i].private_key);
42 gpr_free((void*)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 (char*)GRPC_ARG_HTTP2_SCHEME, (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()193 grpc_ssl_server_credentials::create_security_connector() {
194 return grpc_ssl_server_security_connector_create(this->Ref());
195 }
196
grpc_convert_grpc_to_tsi_cert_pairs(const grpc_ssl_pem_key_cert_pair * pem_key_cert_pairs,size_t num_key_cert_pairs)197 tsi_ssl_pem_key_cert_pair* grpc_convert_grpc_to_tsi_cert_pairs(
198 const grpc_ssl_pem_key_cert_pair* pem_key_cert_pairs,
199 size_t num_key_cert_pairs) {
200 tsi_ssl_pem_key_cert_pair* tsi_pairs = nullptr;
201 if (num_key_cert_pairs > 0) {
202 GPR_ASSERT(pem_key_cert_pairs != nullptr);
203 tsi_pairs = static_cast<tsi_ssl_pem_key_cert_pair*>(
204 gpr_zalloc(num_key_cert_pairs * sizeof(tsi_ssl_pem_key_cert_pair)));
205 }
206 for (size_t i = 0; i < num_key_cert_pairs; i++) {
207 GPR_ASSERT(pem_key_cert_pairs[i].private_key != nullptr);
208 GPR_ASSERT(pem_key_cert_pairs[i].cert_chain != nullptr);
209 tsi_pairs[i].cert_chain = gpr_strdup(pem_key_cert_pairs[i].cert_chain);
210 tsi_pairs[i].private_key = gpr_strdup(pem_key_cert_pairs[i].private_key);
211 }
212 return tsi_pairs;
213 }
214
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)215 void grpc_ssl_server_credentials::build_config(
216 const char* pem_root_certs, grpc_ssl_pem_key_cert_pair* pem_key_cert_pairs,
217 size_t num_key_cert_pairs,
218 grpc_ssl_client_certificate_request_type client_certificate_request) {
219 config_.client_certificate_request = client_certificate_request;
220 config_.pem_root_certs = gpr_strdup(pem_root_certs);
221 config_.pem_key_cert_pairs = grpc_convert_grpc_to_tsi_cert_pairs(
222 pem_key_cert_pairs, num_key_cert_pairs);
223 config_.num_key_cert_pairs = num_key_cert_pairs;
224 }
225
set_min_tls_version(grpc_tls_version min_tls_version)226 void grpc_ssl_server_credentials::set_min_tls_version(
227 grpc_tls_version min_tls_version) {
228 config_.min_tls_version = min_tls_version;
229 }
230
set_max_tls_version(grpc_tls_version max_tls_version)231 void grpc_ssl_server_credentials::set_max_tls_version(
232 grpc_tls_version max_tls_version) {
233 config_.max_tls_version = max_tls_version;
234 }
235
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)236 grpc_ssl_server_certificate_config* grpc_ssl_server_certificate_config_create(
237 const char* pem_root_certs,
238 const grpc_ssl_pem_key_cert_pair* pem_key_cert_pairs,
239 size_t num_key_cert_pairs) {
240 grpc_ssl_server_certificate_config* config =
241 static_cast<grpc_ssl_server_certificate_config*>(
242 gpr_zalloc(sizeof(grpc_ssl_server_certificate_config)));
243 config->pem_root_certs = gpr_strdup(pem_root_certs);
244 if (num_key_cert_pairs > 0) {
245 GPR_ASSERT(pem_key_cert_pairs != nullptr);
246 config->pem_key_cert_pairs = static_cast<grpc_ssl_pem_key_cert_pair*>(
247 gpr_zalloc(num_key_cert_pairs * sizeof(grpc_ssl_pem_key_cert_pair)));
248 }
249 config->num_key_cert_pairs = num_key_cert_pairs;
250 for (size_t i = 0; i < num_key_cert_pairs; i++) {
251 GPR_ASSERT(pem_key_cert_pairs[i].private_key != nullptr);
252 GPR_ASSERT(pem_key_cert_pairs[i].cert_chain != nullptr);
253 config->pem_key_cert_pairs[i].cert_chain =
254 gpr_strdup(pem_key_cert_pairs[i].cert_chain);
255 config->pem_key_cert_pairs[i].private_key =
256 gpr_strdup(pem_key_cert_pairs[i].private_key);
257 }
258 return config;
259 }
260
grpc_ssl_server_certificate_config_destroy(grpc_ssl_server_certificate_config * config)261 void grpc_ssl_server_certificate_config_destroy(
262 grpc_ssl_server_certificate_config* config) {
263 if (config == nullptr) return;
264 for (size_t i = 0; i < config->num_key_cert_pairs; i++) {
265 gpr_free((void*)config->pem_key_cert_pairs[i].private_key);
266 gpr_free((void*)config->pem_key_cert_pairs[i].cert_chain);
267 }
268 gpr_free(config->pem_key_cert_pairs);
269 gpr_free(config->pem_root_certs);
270 gpr_free(config);
271 }
272
273 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)274 grpc_ssl_server_credentials_create_options_using_config(
275 grpc_ssl_client_certificate_request_type client_certificate_request,
276 grpc_ssl_server_certificate_config* config) {
277 grpc_ssl_server_credentials_options* options = nullptr;
278 if (config == nullptr) {
279 gpr_log(GPR_ERROR, "Certificate config must not be NULL.");
280 goto done;
281 }
282 options = static_cast<grpc_ssl_server_credentials_options*>(
283 gpr_zalloc(sizeof(grpc_ssl_server_credentials_options)));
284 options->client_certificate_request = client_certificate_request;
285 options->certificate_config = config;
286 done:
287 return options;
288 }
289
290 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)291 grpc_ssl_server_credentials_create_options_using_config_fetcher(
292 grpc_ssl_client_certificate_request_type client_certificate_request,
293 grpc_ssl_server_certificate_config_callback cb, void* user_data) {
294 if (cb == nullptr) {
295 gpr_log(GPR_ERROR, "Invalid certificate config callback parameter.");
296 return nullptr;
297 }
298
299 grpc_ssl_server_certificate_config_fetcher* fetcher =
300 static_cast<grpc_ssl_server_certificate_config_fetcher*>(
301 gpr_zalloc(sizeof(grpc_ssl_server_certificate_config_fetcher)));
302 fetcher->cb = cb;
303 fetcher->user_data = user_data;
304
305 grpc_ssl_server_credentials_options* options =
306 static_cast<grpc_ssl_server_credentials_options*>(
307 gpr_zalloc(sizeof(grpc_ssl_server_credentials_options)));
308 options->client_certificate_request = client_certificate_request;
309 options->certificate_config_fetcher = fetcher;
310
311 return options;
312 }
313
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)314 grpc_server_credentials* grpc_ssl_server_credentials_create(
315 const char* pem_root_certs, grpc_ssl_pem_key_cert_pair* pem_key_cert_pairs,
316 size_t num_key_cert_pairs, int force_client_auth, void* reserved) {
317 return grpc_ssl_server_credentials_create_ex(
318 pem_root_certs, pem_key_cert_pairs, num_key_cert_pairs,
319 force_client_auth
320 ? GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY
321 : GRPC_SSL_DONT_REQUEST_CLIENT_CERTIFICATE,
322 reserved);
323 }
324
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)325 grpc_server_credentials* grpc_ssl_server_credentials_create_ex(
326 const char* pem_root_certs, grpc_ssl_pem_key_cert_pair* pem_key_cert_pairs,
327 size_t num_key_cert_pairs,
328 grpc_ssl_client_certificate_request_type client_certificate_request,
329 void* reserved) {
330 GRPC_API_TRACE(
331 "grpc_ssl_server_credentials_create_ex("
332 "pem_root_certs=%s, pem_key_cert_pairs=%p, num_key_cert_pairs=%lu, "
333 "client_certificate_request=%d, reserved=%p)",
334 5,
335 (pem_root_certs, pem_key_cert_pairs, (unsigned long)num_key_cert_pairs,
336 client_certificate_request, reserved));
337 GPR_ASSERT(reserved == nullptr);
338
339 grpc_ssl_server_certificate_config* cert_config =
340 grpc_ssl_server_certificate_config_create(
341 pem_root_certs, pem_key_cert_pairs, num_key_cert_pairs);
342 grpc_ssl_server_credentials_options* options =
343 grpc_ssl_server_credentials_create_options_using_config(
344 client_certificate_request, cert_config);
345
346 return grpc_ssl_server_credentials_create_with_options(options);
347 }
348
grpc_ssl_server_credentials_create_with_options(grpc_ssl_server_credentials_options * options)349 grpc_server_credentials* grpc_ssl_server_credentials_create_with_options(
350 grpc_ssl_server_credentials_options* options) {
351 grpc_server_credentials* retval = nullptr;
352
353 if (options == nullptr) {
354 gpr_log(GPR_ERROR,
355 "Invalid options trying to create SSL server credentials.");
356 goto done;
357 }
358
359 if (options->certificate_config == nullptr &&
360 options->certificate_config_fetcher == nullptr) {
361 gpr_log(GPR_ERROR,
362 "SSL server credentials options must specify either "
363 "certificate config or fetcher.");
364 goto done;
365 } else if (options->certificate_config_fetcher != nullptr &&
366 options->certificate_config_fetcher->cb == nullptr) {
367 gpr_log(GPR_ERROR, "Certificate config fetcher callback must not be NULL.");
368 goto done;
369 }
370
371 retval = new grpc_ssl_server_credentials(*options);
372
373 done:
374 grpc_ssl_server_credentials_options_destroy(options);
375 return retval;
376 }
377
grpc_ssl_server_credentials_options_destroy(grpc_ssl_server_credentials_options * o)378 void grpc_ssl_server_credentials_options_destroy(
379 grpc_ssl_server_credentials_options* o) {
380 if (o == nullptr) return;
381 gpr_free(o->certificate_config_fetcher);
382 grpc_ssl_server_certificate_config_destroy(o->certificate_config);
383 gpr_free(o);
384 }
385