• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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