Home | History | Annotate | Download | only in ssl
      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 
     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 
     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 
     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 
     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 
    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 
    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 
    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 
    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 
    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 
    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 
    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*
    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*
    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 
    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 
    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 
    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 
    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