server_ssl_common.cc 8.7 KB

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