Home | History | Annotate | Download | only in handshake
      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 "test/core/handshake/server_ssl_common.h"
     20 
     21 #include <arpa/inet.h>
     22 #include <openssl/err.h>
     23 #include <openssl/ssl.h>
     24 #include <string.h>
     25 #include <sys/socket.h>
     26 #include <unistd.h>
     27 
     28 #include <grpc/grpc.h>
     29 #include <grpc/grpc_security.h>
     30 #include <grpc/support/alloc.h>
     31 #include <grpc/support/log.h>
     32 #include <grpc/support/string_util.h>
     33 #include <grpc/support/sync.h>
     34 
     35 #include "src/core/lib/gprpp/thd.h"
     36 #include "src/core/lib/iomgr/load_file.h"
     37 #include "test/core/util/port.h"
     38 #include "test/core/util/test_config.h"
     39 
     40 #define SSL_CERT_PATH "src/core/tsi/test_creds/server1.pem"
     41 #define SSL_KEY_PATH "src/core/tsi/test_creds/server1.key"
     42 #define SSL_CA_PATH "src/core/tsi/test_creds/ca.pem"
     43 
     44 // Handshake completed signal to server thread.
     45 static gpr_event client_handshake_complete;
     46 
     47 static int create_socket(int port) {
     48   int s;
     49   struct sockaddr_in addr;
     50 
     51   addr.sin_family = AF_INET;
     52   addr.sin_port = htons(static_cast<uint16_t>(port));
     53   addr.sin_addr.s_addr = htonl(INADDR_ANY);
     54 
     55   s = socket(AF_INET, SOCK_STREAM, 0);
     56   if (s < 0) {
     57     perror("Unable to create socket");
     58     return -1;
     59   }
     60 
     61   if (connect(s, reinterpret_cast<struct sockaddr*>(&addr), sizeof(addr)) < 0) {
     62     perror("Unable to connect");
     63     return -1;
     64   }
     65 
     66   return s;
     67 }
     68 
     69 // Simple gRPC server. This listens until client_handshake_complete occurs.
     70 static void server_thread(void* arg) {
     71   const int port = *static_cast<int*>(arg);
     72 
     73   // Load key pair and establish server SSL credentials.
     74   grpc_ssl_pem_key_cert_pair pem_key_cert_pair;
     75   grpc_slice ca_slice, cert_slice, key_slice;
     76   GPR_ASSERT(GRPC_LOG_IF_ERROR("load_file",
     77                                grpc_load_file(SSL_CA_PATH, 1, &ca_slice)));
     78   GPR_ASSERT(GRPC_LOG_IF_ERROR("load_file",
     79                                grpc_load_file(SSL_CERT_PATH, 1, &cert_slice)));
     80   GPR_ASSERT(GRPC_LOG_IF_ERROR("load_file",
     81                                grpc_load_file(SSL_KEY_PATH, 1, &key_slice)));
     82   const char* ca_cert =
     83       reinterpret_cast<const char*> GRPC_SLICE_START_PTR(ca_slice);
     84   pem_key_cert_pair.private_key =
     85       reinterpret_cast<const char*> GRPC_SLICE_START_PTR(key_slice);
     86   pem_key_cert_pair.cert_chain =
     87       reinterpret_cast<const char*> GRPC_SLICE_START_PTR(cert_slice);
     88   grpc_server_credentials* ssl_creds = grpc_ssl_server_credentials_create(
     89       ca_cert, &pem_key_cert_pair, 1, 0, nullptr);
     90 
     91   // Start server listening on local port.
     92   char* addr;
     93   gpr_asprintf(&addr, "127.0.0.1:%d", port);
     94   grpc_server* server = grpc_server_create(nullptr, nullptr);
     95   GPR_ASSERT(grpc_server_add_secure_http2_port(server, addr, ssl_creds));
     96   free(addr);
     97 
     98   grpc_completion_queue* cq = grpc_completion_queue_create_for_next(nullptr);
     99 
    100   grpc_server_register_completion_queue(server, cq, nullptr);
    101   grpc_server_start(server);
    102 
    103   // Wait a bounded number of time until client_handshake_complete is set,
    104   // sleeping between polls.
    105   int retries = 10;
    106   while (!gpr_event_get(&client_handshake_complete) && retries-- > 0) {
    107     const gpr_timespec cq_deadline = grpc_timeout_seconds_to_deadline(1);
    108     grpc_event ev = grpc_completion_queue_next(cq, cq_deadline, nullptr);
    109     GPR_ASSERT(ev.type == GRPC_QUEUE_TIMEOUT);
    110   }
    111 
    112   gpr_log(GPR_INFO, "Shutting down server");
    113   grpc_server_shutdown_and_notify(server, cq, nullptr);
    114   grpc_completion_queue_shutdown(cq);
    115 
    116   const gpr_timespec cq_deadline = grpc_timeout_seconds_to_deadline(5);
    117   grpc_event ev = grpc_completion_queue_next(cq, cq_deadline, nullptr);
    118   GPR_ASSERT(ev.type == GRPC_OP_COMPLETE);
    119 
    120   grpc_server_destroy(server);
    121   grpc_completion_queue_destroy(cq);
    122   grpc_server_credentials_release(ssl_creds);
    123   grpc_slice_unref(cert_slice);
    124   grpc_slice_unref(key_slice);
    125   grpc_slice_unref(ca_slice);
    126 }
    127 
    128 // This test launches a gRPC server on a separate thread and then establishes a
    129 // TLS handshake via a minimal TLS client. The TLS client has configurable (via
    130 // alpn_list) ALPN settings and can probe at the supported ALPN preferences
    131 // using this (via alpn_expected).
    132 bool server_ssl_test(const char* alpn_list[], unsigned int alpn_list_len,
    133                      const char* alpn_expected) {
    134   bool success = true;
    135 
    136   grpc_init();
    137   int port = grpc_pick_unused_port_or_die();
    138   gpr_event_init(&client_handshake_complete);
    139 
    140   // Launch the gRPC server thread.
    141   bool ok;
    142   grpc_core::Thread thd("grpc_ssl_test", server_thread, &port, &ok);
    143   GPR_ASSERT(ok);
    144   thd.Start();
    145 
    146   SSL_load_error_strings();
    147   OpenSSL_add_ssl_algorithms();
    148 
    149   const SSL_METHOD* method = TLSv1_2_client_method();
    150   SSL_CTX* ctx = SSL_CTX_new(method);
    151   if (!ctx) {
    152     perror("Unable to create SSL context");
    153     ERR_print_errors_fp(stderr);
    154     abort();
    155   }
    156 
    157   // Load key pair.
    158   if (SSL_CTX_use_certificate_file(ctx, SSL_CERT_PATH, SSL_FILETYPE_PEM) < 0) {
    159     ERR_print_errors_fp(stderr);
    160     abort();
    161   }
    162   if (SSL_CTX_use_PrivateKey_file(ctx, SSL_KEY_PATH, SSL_FILETYPE_PEM) < 0) {
    163     ERR_print_errors_fp(stderr);
    164     abort();
    165   }
    166 
    167   // Set the cipher list to match the one expressed in
    168   // src/core/tsi/ssl_transport_security.c.
    169   const char* cipher_list =
    170       "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-"
    171       "SHA384:ECDHE-RSA-AES256-GCM-SHA384";
    172   if (!SSL_CTX_set_cipher_list(ctx, cipher_list)) {
    173     ERR_print_errors_fp(stderr);
    174     gpr_log(GPR_ERROR, "Couldn't set server cipher list.");
    175     abort();
    176   }
    177 
    178   // Configure ALPN list the client will send to the server. This must match the
    179   // wire format, see documentation for SSL_CTX_set_alpn_protos.
    180   unsigned int alpn_protos_len = alpn_list_len;
    181   for (unsigned int i = 0; i < alpn_list_len; ++i) {
    182     alpn_protos_len += static_cast<unsigned int>(strlen(alpn_list[i]));
    183   }
    184   unsigned char* alpn_protos =
    185       static_cast<unsigned char*>(gpr_malloc(alpn_protos_len));
    186   unsigned char* p = alpn_protos;
    187   for (unsigned int i = 0; i < alpn_list_len; ++i) {
    188     const uint8_t len = static_cast<uint8_t>(strlen(alpn_list[i]));
    189     *p++ = len;
    190     memcpy(p, alpn_list[i], len);
    191     p += len;
    192   }
    193   GPR_ASSERT(SSL_CTX_set_alpn_protos(ctx, alpn_protos, alpn_protos_len) == 0);
    194 
    195   // Try and connect to server. We allow a bounded number of retries as we might
    196   // be racing with the server setup on its separate thread.
    197   int retries = 10;
    198   int sock = -1;
    199   while (sock == -1 && retries-- > 0) {
    200     sock = create_socket(port);
    201     if (sock < 0) {
    202       sleep(1);
    203     }
    204   }
    205   GPR_ASSERT(sock > 0);
    206   gpr_log(GPR_INFO, "Connected to server on port %d", port);
    207 
    208   // Establish a SSL* and connect at SSL layer.
    209   SSL* ssl = SSL_new(ctx);
    210   GPR_ASSERT(ssl);
    211   SSL_set_fd(ssl, sock);
    212   if (SSL_connect(ssl) <= 0) {
    213     ERR_print_errors_fp(stderr);
    214     gpr_log(GPR_ERROR, "Handshake failed.");
    215     success = false;
    216   } else {
    217     gpr_log(GPR_INFO, "Handshake successful.");
    218     // Validate ALPN preferred by server matches alpn_expected.
    219     const unsigned char* alpn_selected;
    220     unsigned int alpn_selected_len;
    221     SSL_get0_alpn_selected(ssl, &alpn_selected, &alpn_selected_len);
    222     if (strlen(alpn_expected) != alpn_selected_len ||
    223         strncmp(reinterpret_cast<const char*>(alpn_selected), alpn_expected,
    224                 alpn_selected_len) != 0) {
    225       gpr_log(GPR_ERROR, "Unexpected ALPN protocol preference");
    226       success = false;
    227     }
    228   }
    229   gpr_event_set(&client_handshake_complete, &client_handshake_complete);
    230 
    231   SSL_free(ssl);
    232   gpr_free(alpn_protos);
    233   SSL_CTX_free(ctx);
    234   EVP_cleanup();
    235   close(sock);
    236 
    237   thd.Join();
    238 
    239   grpc_shutdown();
    240 
    241   return success;
    242 }
    243