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
ssl_destruct(grpc_channel_credentials * creds)47 static void ssl_destruct(grpc_channel_credentials* creds) {
48 grpc_ssl_credentials* c = reinterpret_cast<grpc_ssl_credentials*>(creds);
49 gpr_free(c->config.pem_root_certs);
50 grpc_tsi_ssl_pem_key_cert_pairs_destroy(c->config.pem_key_cert_pair, 1);
51 if (c->config.verify_options.verify_peer_destruct != nullptr) {
52 c->config.verify_options.verify_peer_destruct(
53 c->config.verify_options.verify_peer_callback_userdata);
54 }
55 }
56
ssl_create_security_connector(grpc_channel_credentials * creds,grpc_call_credentials * call_creds,const char * target,const grpc_channel_args * args,grpc_channel_security_connector ** sc,grpc_channel_args ** new_args)57 static grpc_security_status ssl_create_security_connector(
58 grpc_channel_credentials* creds, grpc_call_credentials* call_creds,
59 const char* target, const grpc_channel_args* args,
60 grpc_channel_security_connector** sc, grpc_channel_args** new_args) {
61 grpc_ssl_credentials* c = reinterpret_cast<grpc_ssl_credentials*>(creds);
62 grpc_security_status status = GRPC_SECURITY_OK;
63 const char* overridden_target_name = nullptr;
64 tsi_ssl_session_cache* ssl_session_cache = nullptr;
65 for (size_t i = 0; args && i < args->num_args; i++) {
66 grpc_arg* arg = &args->args[i];
67 if (strcmp(arg->key, GRPC_SSL_TARGET_NAME_OVERRIDE_ARG) == 0 &&
68 arg->type == GRPC_ARG_STRING) {
69 overridden_target_name = arg->value.string;
70 }
71 if (strcmp(arg->key, GRPC_SSL_SESSION_CACHE_ARG) == 0 &&
72 arg->type == GRPC_ARG_POINTER) {
73 ssl_session_cache =
74 static_cast<tsi_ssl_session_cache*>(arg->value.pointer.p);
75 }
76 }
77 status = grpc_ssl_channel_security_connector_create(
78 creds, call_creds, &c->config, target, overridden_target_name,
79 ssl_session_cache, sc);
80 if (status != GRPC_SECURITY_OK) {
81 return status;
82 }
83 grpc_arg new_arg = grpc_channel_arg_string_create(
84 (char*)GRPC_ARG_HTTP2_SCHEME, (char*)"https");
85 *new_args = grpc_channel_args_copy_and_add(args, &new_arg, 1);
86 return status;
87 }
88
89 static grpc_channel_credentials_vtable ssl_vtable = {
90 ssl_destruct, ssl_create_security_connector, nullptr};
91
ssl_build_config(const char * pem_root_certs,grpc_ssl_pem_key_cert_pair * pem_key_cert_pair,const verify_peer_options * verify_options,grpc_ssl_config * config)92 static void ssl_build_config(const char* pem_root_certs,
93 grpc_ssl_pem_key_cert_pair* pem_key_cert_pair,
94 const verify_peer_options* verify_options,
95 grpc_ssl_config* config) {
96 if (pem_root_certs != nullptr) {
97 config->pem_root_certs = gpr_strdup(pem_root_certs);
98 }
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 }
109 if (verify_options != nullptr) {
110 memcpy(&config->verify_options, verify_options,
111 sizeof(verify_peer_options));
112 } else {
113 // Otherwise set all options to default values
114 memset(&config->verify_options, 0, sizeof(verify_peer_options));
115 }
116 }
117
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)118 grpc_channel_credentials* grpc_ssl_credentials_create(
119 const char* pem_root_certs, grpc_ssl_pem_key_cert_pair* pem_key_cert_pair,
120 const verify_peer_options* verify_options, void* reserved) {
121 grpc_ssl_credentials* c = static_cast<grpc_ssl_credentials*>(
122 gpr_zalloc(sizeof(grpc_ssl_credentials)));
123 GRPC_API_TRACE(
124 "grpc_ssl_credentials_create(pem_root_certs=%s, "
125 "pem_key_cert_pair=%p, "
126 "verify_options=%p, "
127 "reserved=%p)",
128 4, (pem_root_certs, pem_key_cert_pair, verify_options, reserved));
129 GPR_ASSERT(reserved == nullptr);
130 c->base.type = GRPC_CHANNEL_CREDENTIALS_TYPE_SSL;
131 c->base.vtable = &ssl_vtable;
132 gpr_ref_init(&c->base.refcount, 1);
133 ssl_build_config(pem_root_certs, pem_key_cert_pair, verify_options,
134 &c->config);
135 return &c->base;
136 }
137
138 //
139 // SSL Server Credentials.
140 //
141
142 struct grpc_ssl_server_credentials_options {
143 grpc_ssl_client_certificate_request_type client_certificate_request;
144 grpc_ssl_server_certificate_config* certificate_config;
145 grpc_ssl_server_certificate_config_fetcher* certificate_config_fetcher;
146 };
147
ssl_server_destruct(grpc_server_credentials * creds)148 static void ssl_server_destruct(grpc_server_credentials* creds) {
149 grpc_ssl_server_credentials* c =
150 reinterpret_cast<grpc_ssl_server_credentials*>(creds);
151 grpc_tsi_ssl_pem_key_cert_pairs_destroy(c->config.pem_key_cert_pairs,
152 c->config.num_key_cert_pairs);
153 gpr_free(c->config.pem_root_certs);
154 }
155
ssl_server_create_security_connector(grpc_server_credentials * creds,grpc_server_security_connector ** sc)156 static grpc_security_status ssl_server_create_security_connector(
157 grpc_server_credentials* creds, grpc_server_security_connector** sc) {
158 return grpc_ssl_server_security_connector_create(creds, sc);
159 }
160
161 static grpc_server_credentials_vtable ssl_server_vtable = {
162 ssl_server_destruct, ssl_server_create_security_connector};
163
grpc_convert_grpc_to_tsi_cert_pairs(const grpc_ssl_pem_key_cert_pair * pem_key_cert_pairs,size_t num_key_cert_pairs)164 tsi_ssl_pem_key_cert_pair* grpc_convert_grpc_to_tsi_cert_pairs(
165 const grpc_ssl_pem_key_cert_pair* pem_key_cert_pairs,
166 size_t num_key_cert_pairs) {
167 tsi_ssl_pem_key_cert_pair* tsi_pairs = nullptr;
168 if (num_key_cert_pairs > 0) {
169 GPR_ASSERT(pem_key_cert_pairs != nullptr);
170 tsi_pairs = static_cast<tsi_ssl_pem_key_cert_pair*>(
171 gpr_zalloc(num_key_cert_pairs * sizeof(tsi_ssl_pem_key_cert_pair)));
172 }
173 for (size_t i = 0; i < num_key_cert_pairs; i++) {
174 GPR_ASSERT(pem_key_cert_pairs[i].private_key != nullptr);
175 GPR_ASSERT(pem_key_cert_pairs[i].cert_chain != nullptr);
176 tsi_pairs[i].cert_chain = gpr_strdup(pem_key_cert_pairs[i].cert_chain);
177 tsi_pairs[i].private_key = gpr_strdup(pem_key_cert_pairs[i].private_key);
178 }
179 return tsi_pairs;
180 }
181
ssl_build_server_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,grpc_ssl_server_config * config)182 static void ssl_build_server_config(
183 const char* pem_root_certs, grpc_ssl_pem_key_cert_pair* pem_key_cert_pairs,
184 size_t num_key_cert_pairs,
185 grpc_ssl_client_certificate_request_type client_certificate_request,
186 grpc_ssl_server_config* config) {
187 config->client_certificate_request = client_certificate_request;
188 if (pem_root_certs != nullptr) {
189 config->pem_root_certs = gpr_strdup(pem_root_certs);
190 }
191 config->pem_key_cert_pairs = grpc_convert_grpc_to_tsi_cert_pairs(
192 pem_key_cert_pairs, num_key_cert_pairs);
193 config->num_key_cert_pairs = num_key_cert_pairs;
194 }
195
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)196 grpc_ssl_server_certificate_config* grpc_ssl_server_certificate_config_create(
197 const char* pem_root_certs,
198 const grpc_ssl_pem_key_cert_pair* pem_key_cert_pairs,
199 size_t num_key_cert_pairs) {
200 grpc_ssl_server_certificate_config* config =
201 static_cast<grpc_ssl_server_certificate_config*>(
202 gpr_zalloc(sizeof(grpc_ssl_server_certificate_config)));
203 if (pem_root_certs != nullptr) {
204 config->pem_root_certs = gpr_strdup(pem_root_certs);
205 }
206 if (num_key_cert_pairs > 0) {
207 GPR_ASSERT(pem_key_cert_pairs != nullptr);
208 config->pem_key_cert_pairs = static_cast<grpc_ssl_pem_key_cert_pair*>(
209 gpr_zalloc(num_key_cert_pairs * sizeof(grpc_ssl_pem_key_cert_pair)));
210 }
211 config->num_key_cert_pairs = num_key_cert_pairs;
212 for (size_t i = 0; i < num_key_cert_pairs; i++) {
213 GPR_ASSERT(pem_key_cert_pairs[i].private_key != nullptr);
214 GPR_ASSERT(pem_key_cert_pairs[i].cert_chain != nullptr);
215 config->pem_key_cert_pairs[i].cert_chain =
216 gpr_strdup(pem_key_cert_pairs[i].cert_chain);
217 config->pem_key_cert_pairs[i].private_key =
218 gpr_strdup(pem_key_cert_pairs[i].private_key);
219 }
220 return config;
221 }
222
grpc_ssl_server_certificate_config_destroy(grpc_ssl_server_certificate_config * config)223 void grpc_ssl_server_certificate_config_destroy(
224 grpc_ssl_server_certificate_config* config) {
225 if (config == nullptr) return;
226 for (size_t i = 0; i < config->num_key_cert_pairs; i++) {
227 gpr_free((void*)config->pem_key_cert_pairs[i].private_key);
228 gpr_free((void*)config->pem_key_cert_pairs[i].cert_chain);
229 }
230 gpr_free(config->pem_key_cert_pairs);
231 gpr_free(config->pem_root_certs);
232 gpr_free(config);
233 }
234
235 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)236 grpc_ssl_server_credentials_create_options_using_config(
237 grpc_ssl_client_certificate_request_type client_certificate_request,
238 grpc_ssl_server_certificate_config* config) {
239 grpc_ssl_server_credentials_options* options = nullptr;
240 if (config == nullptr) {
241 gpr_log(GPR_ERROR, "Certificate config must not be NULL.");
242 goto done;
243 }
244 options = static_cast<grpc_ssl_server_credentials_options*>(
245 gpr_zalloc(sizeof(grpc_ssl_server_credentials_options)));
246 options->client_certificate_request = client_certificate_request;
247 options->certificate_config = config;
248 done:
249 return options;
250 }
251
252 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)253 grpc_ssl_server_credentials_create_options_using_config_fetcher(
254 grpc_ssl_client_certificate_request_type client_certificate_request,
255 grpc_ssl_server_certificate_config_callback cb, void* user_data) {
256 if (cb == nullptr) {
257 gpr_log(GPR_ERROR, "Invalid certificate config callback parameter.");
258 return nullptr;
259 }
260
261 grpc_ssl_server_certificate_config_fetcher* fetcher =
262 static_cast<grpc_ssl_server_certificate_config_fetcher*>(
263 gpr_zalloc(sizeof(grpc_ssl_server_certificate_config_fetcher)));
264 fetcher->cb = cb;
265 fetcher->user_data = user_data;
266
267 grpc_ssl_server_credentials_options* options =
268 static_cast<grpc_ssl_server_credentials_options*>(
269 gpr_zalloc(sizeof(grpc_ssl_server_credentials_options)));
270 options->client_certificate_request = client_certificate_request;
271 options->certificate_config_fetcher = fetcher;
272
273 return options;
274 }
275
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)276 grpc_server_credentials* grpc_ssl_server_credentials_create(
277 const char* pem_root_certs, grpc_ssl_pem_key_cert_pair* pem_key_cert_pairs,
278 size_t num_key_cert_pairs, int force_client_auth, void* reserved) {
279 return grpc_ssl_server_credentials_create_ex(
280 pem_root_certs, pem_key_cert_pairs, num_key_cert_pairs,
281 force_client_auth
282 ? GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY
283 : GRPC_SSL_DONT_REQUEST_CLIENT_CERTIFICATE,
284 reserved);
285 }
286
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)287 grpc_server_credentials* grpc_ssl_server_credentials_create_ex(
288 const char* pem_root_certs, grpc_ssl_pem_key_cert_pair* pem_key_cert_pairs,
289 size_t num_key_cert_pairs,
290 grpc_ssl_client_certificate_request_type client_certificate_request,
291 void* reserved) {
292 GRPC_API_TRACE(
293 "grpc_ssl_server_credentials_create_ex("
294 "pem_root_certs=%s, pem_key_cert_pairs=%p, num_key_cert_pairs=%lu, "
295 "client_certificate_request=%d, reserved=%p)",
296 5,
297 (pem_root_certs, pem_key_cert_pairs, (unsigned long)num_key_cert_pairs,
298 client_certificate_request, reserved));
299 GPR_ASSERT(reserved == nullptr);
300
301 grpc_ssl_server_certificate_config* cert_config =
302 grpc_ssl_server_certificate_config_create(
303 pem_root_certs, pem_key_cert_pairs, num_key_cert_pairs);
304 grpc_ssl_server_credentials_options* options =
305 grpc_ssl_server_credentials_create_options_using_config(
306 client_certificate_request, cert_config);
307
308 return grpc_ssl_server_credentials_create_with_options(options);
309 }
310
grpc_ssl_server_credentials_create_with_options(grpc_ssl_server_credentials_options * options)311 grpc_server_credentials* grpc_ssl_server_credentials_create_with_options(
312 grpc_ssl_server_credentials_options* options) {
313 grpc_server_credentials* retval = nullptr;
314 grpc_ssl_server_credentials* c = nullptr;
315
316 if (options == nullptr) {
317 gpr_log(GPR_ERROR,
318 "Invalid options trying to create SSL server credentials.");
319 goto done;
320 }
321
322 if (options->certificate_config == nullptr &&
323 options->certificate_config_fetcher == nullptr) {
324 gpr_log(GPR_ERROR,
325 "SSL server credentials options must specify either "
326 "certificate config or fetcher.");
327 goto done;
328 } else if (options->certificate_config_fetcher != nullptr &&
329 options->certificate_config_fetcher->cb == nullptr) {
330 gpr_log(GPR_ERROR, "Certificate config fetcher callback must not be NULL.");
331 goto done;
332 }
333
334 c = static_cast<grpc_ssl_server_credentials*>(
335 gpr_zalloc(sizeof(grpc_ssl_server_credentials)));
336 c->base.type = GRPC_CHANNEL_CREDENTIALS_TYPE_SSL;
337 gpr_ref_init(&c->base.refcount, 1);
338 c->base.vtable = &ssl_server_vtable;
339
340 if (options->certificate_config_fetcher != nullptr) {
341 c->config.client_certificate_request = options->client_certificate_request;
342 c->certificate_config_fetcher = *options->certificate_config_fetcher;
343 } else {
344 ssl_build_server_config(options->certificate_config->pem_root_certs,
345 options->certificate_config->pem_key_cert_pairs,
346 options->certificate_config->num_key_cert_pairs,
347 options->client_certificate_request, &c->config);
348 }
349
350 retval = &c->base;
351
352 done:
353 grpc_ssl_server_credentials_options_destroy(options);
354 return retval;
355 }
356
grpc_ssl_server_credentials_options_destroy(grpc_ssl_server_credentials_options * o)357 void grpc_ssl_server_credentials_options_destroy(
358 grpc_ssl_server_credentials_options* o) {
359 if (o == nullptr) return;
360 gpr_free(o->certificate_config_fetcher);
361 grpc_ssl_server_certificate_config_destroy(o->certificate_config);
362 gpr_free(o);
363 }
364