server_ssl_common.cc
Go to the documentation of this file.
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 
20 
21 #include <arpa/inet.h>
22 #include <string.h>
23 #include <sys/socket.h>
24 #include <unistd.h>
25 
26 #include <string>
27 
28 #include <openssl/err.h>
29 #include <openssl/ssl.h>
30 
31 #include "absl/strings/str_cat.h"
32 
33 #include <grpc/grpc.h>
34 #include <grpc/grpc_security.h>
35 #include <grpc/support/alloc.h>
36 #include <grpc/support/log.h>
37 #include <grpc/support/sync.h>
38 
40 #include "src/core/lib/gprpp/thd.h"
42 #include "test/core/util/port.h"
44 
45 #define SSL_CERT_PATH "src/core/tsi/test_creds/server1.pem"
46 #define SSL_KEY_PATH "src/core/tsi/test_creds/server1.key"
47 #define SSL_CA_PATH "src/core/tsi/test_creds/ca.pem"
48 
49 namespace {
50 
51 // Handshake completed signal to server thread.
52 gpr_event client_handshake_complete;
53 
54 int create_socket(int port) {
55  int s;
56  struct sockaddr_in addr;
57 
58  addr.sin_family = AF_INET;
59  addr.sin_port = htons(static_cast<uint16_t>(port));
60  addr.sin_addr.s_addr = htonl(INADDR_ANY);
61 
62  s = socket(AF_INET, SOCK_STREAM, 0);
63  if (s < 0) {
64  perror("Unable to create socket");
65  return -1;
66  }
67 
68  if (connect(s, reinterpret_cast<struct sockaddr*>(&addr), sizeof(addr)) < 0) {
69  perror("Unable to connect");
70  return -1;
71  }
72 
73  return s;
74 }
75 
76 class ServerInfo {
77  public:
78  explicit ServerInfo(int p) : port_(p) {}
79 
80  int port() const { return port_; }
81 
82  void Activate() {
84  ready_ = true;
85  cv_.Signal();
86  }
87 
88  void Await() {
90  while (!ready_) {
91  cv_.Wait(&mu_);
92  }
93  }
94 
95  private:
96  const int port_;
99  bool ready_ ABSL_GUARDED_BY(mu_) = false;
100 };
101 
102 // Simple gRPC server. This listens until client_handshake_complete occurs.
103 void server_thread(void* arg) {
104  ServerInfo* s = static_cast<ServerInfo*>(arg);
105  const int port = s->port();
106 
107  // Load key pair and establish server SSL credentials.
108  grpc_ssl_pem_key_cert_pair pem_key_cert_pair;
109  grpc_slice ca_slice, cert_slice, key_slice;
110  GPR_ASSERT(GRPC_LOG_IF_ERROR("load_file",
111  grpc_load_file(SSL_CA_PATH, 1, &ca_slice)));
112  GPR_ASSERT(GRPC_LOG_IF_ERROR("load_file",
113  grpc_load_file(SSL_CERT_PATH, 1, &cert_slice)));
114  GPR_ASSERT(GRPC_LOG_IF_ERROR("load_file",
115  grpc_load_file(SSL_KEY_PATH, 1, &key_slice)));
116  const char* ca_cert =
117  reinterpret_cast<const char*> GRPC_SLICE_START_PTR(ca_slice);
118  pem_key_cert_pair.private_key =
119  reinterpret_cast<const char*> GRPC_SLICE_START_PTR(key_slice);
120  pem_key_cert_pair.cert_chain =
121  reinterpret_cast<const char*> GRPC_SLICE_START_PTR(cert_slice);
123  ca_cert, &pem_key_cert_pair, 1, 0, nullptr);
124 
125  // Start server listening on local port.
126  std::string addr = absl::StrCat("127.0.0.1:", port);
127  grpc_server* server = grpc_server_create(nullptr, nullptr);
128  GPR_ASSERT(grpc_server_add_http2_port(server, addr.c_str(), ssl_creds));
129 
131 
134 
135  // Notify the other side that it is now ok to start working since SSL is
136  // definitely already started.
137  s->Activate();
138 
139  // Wait a bounded number of time until client_handshake_complete is set,
140  // sleeping between polls.
141  int retries = 10;
142  while (!gpr_event_get(&client_handshake_complete) && retries-- > 0) {
143  const gpr_timespec cq_deadline = grpc_timeout_seconds_to_deadline(1);
144  grpc_event ev = grpc_completion_queue_next(cq, cq_deadline, nullptr);
146  }
147 
148  gpr_log(GPR_INFO, "Shutting down server");
151 
152  const gpr_timespec cq_deadline = grpc_timeout_seconds_to_deadline(5);
153  grpc_event ev = grpc_completion_queue_next(cq, cq_deadline, nullptr);
155 
159  grpc_slice_unref(cert_slice);
160  grpc_slice_unref(key_slice);
161  grpc_slice_unref(ca_slice);
162 }
163 
164 } // namespace
165 
166 // This test launches a gRPC server on a separate thread and then establishes a
167 // TLS handshake via a minimal TLS client. The TLS client has configurable (via
168 // alpn_list) ALPN settings and can probe at the supported ALPN preferences
169 // using this (via alpn_expected).
170 bool server_ssl_test(const char* alpn_list[], unsigned int alpn_list_len,
171  const char* alpn_expected) {
172  bool success = true;
173 
174  grpc_init();
175  ServerInfo s(grpc_pick_unused_port_or_die());
176  gpr_event_init(&client_handshake_complete);
177 
178  // Launch the gRPC server thread.
179  bool ok;
180  grpc_core::Thread thd("grpc_ssl_test", server_thread, &s, &ok);
181  GPR_ASSERT(ok);
182  thd.Start();
183 
184  // The work in server_thread will cause the SSL initialization to take place
185  // so long as we wait for it to reach beyond the point of adding a secure
186  // server port.
187  s.Await();
188 
191  if (!ctx) {
192  perror("Unable to create SSL context");
194  abort();
195  }
196 
197  // Load key pair.
200  abort();
201  }
204  abort();
205  }
206 
207  // Set the cipher list to match the one expressed in
208  // src/core/tsi/ssl_transport_security.c.
209  const char* cipher_list =
210  "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-"
211  "SHA384:ECDHE-RSA-AES256-GCM-SHA384";
212  if (!SSL_CTX_set_cipher_list(ctx, cipher_list)) {
214  gpr_log(GPR_ERROR, "Couldn't set server cipher list.");
215  abort();
216  }
217 
218  // Configure ALPN list the client will send to the server. This must match the
219  // wire format, see documentation for SSL_CTX_set_alpn_protos.
220  unsigned int alpn_protos_len = alpn_list_len;
221  for (unsigned int i = 0; i < alpn_list_len; ++i) {
222  alpn_protos_len += static_cast<unsigned int>(strlen(alpn_list[i]));
223  }
224  unsigned char* alpn_protos =
225  static_cast<unsigned char*>(gpr_malloc(alpn_protos_len));
226  unsigned char* p = alpn_protos;
227  for (unsigned int i = 0; i < alpn_list_len; ++i) {
228  const uint8_t len = static_cast<uint8_t>(strlen(alpn_list[i]));
229  *p++ = len;
230  memcpy(p, alpn_list[i], len);
231  p += len;
232  }
233  GPR_ASSERT(SSL_CTX_set_alpn_protos(ctx, alpn_protos, alpn_protos_len) == 0);
234 
235  // Try and connect to server. We allow a bounded number of retries as we might
236  // be racing with the server setup on its separate thread.
237  int retries = 10;
238  int sock = -1;
239  while (sock == -1 && retries-- > 0) {
240  sock = create_socket(s.port());
241  if (sock < 0) {
242  sleep(1);
243  }
244  }
245  GPR_ASSERT(sock > 0);
246  gpr_log(GPR_INFO, "Connected to server on port %d", s.port());
247 
248  // Establish a SSL* and connect at SSL layer.
249  SSL* ssl = SSL_new(ctx);
250  GPR_ASSERT(ssl);
251  SSL_set_fd(ssl, sock);
252  if (SSL_connect(ssl) <= 0) {
254  gpr_log(GPR_ERROR, "Handshake failed.");
255  success = false;
256  } else {
257  gpr_log(GPR_INFO, "Handshake successful.");
258  // Validate ALPN preferred by server matches alpn_expected.
259  const unsigned char* alpn_selected;
260  unsigned int alpn_selected_len;
261  SSL_get0_alpn_selected(ssl, &alpn_selected, &alpn_selected_len);
262  if (strlen(alpn_expected) != alpn_selected_len ||
263  strncmp(reinterpret_cast<const char*>(alpn_selected), alpn_expected,
264  alpn_selected_len) != 0) {
265  gpr_log(GPR_ERROR, "Unexpected ALPN protocol preference");
266  success = false;
267  }
268  }
269  gpr_event_set(&client_handshake_complete, &client_handshake_complete);
270 
271  SSL_free(ssl);
272  gpr_free(alpn_protos);
273  SSL_CTX_free(ctx);
274  close(sock);
275 
276  thd.Join();
277 
278  grpc_shutdown();
279 
280  return success;
281 }
282 
grpc_slice_unref
GPRAPI void grpc_slice_unref(grpc_slice s)
Definition: slice_api.cc:32
GPR_INFO
#define GPR_INFO
Definition: include/grpc/impl/codegen/log.h:56
grpc_core::CondVar
Definition: src/core/lib/gprpp/sync.h:126
grpc_timeout_seconds_to_deadline
gpr_timespec grpc_timeout_seconds_to_deadline(int64_t time_s)
Definition: test/core/util/test_config.cc:81
log.h
port.h
SSL_connect
#define SSL_connect
Definition: boringssl_prefix_symbols.h:294
ctx
Definition: benchmark-async.c:30
grpc_load_file
grpc_error_handle grpc_load_file(const char *filename, int add_null_terminator, grpc_slice *output)
Definition: load_file.cc:33
gpr_event_get
GPRAPI void * gpr_event_get(gpr_event *ev)
Definition: sync.cc:69
absl::StrCat
std::string StrCat(const AlphaNum &a, const AlphaNum &b)
Definition: abseil-cpp/absl/strings/str_cat.cc:98
load_file.h
grpc_ssl_pem_key_cert_pair::private_key
const char * private_key
Definition: grpc_security.h:176
cv_
std::condition_variable cv_
Definition: client_callback_end2end_test.cc:733
SSL_get0_alpn_selected
#define SSL_get0_alpn_selected
Definition: boringssl_prefix_symbols.h:310
uint16_t
unsigned short uint16_t
Definition: stdint-msvc2008.h:79
grpc_core::MutexLock
Definition: src/core/lib/gprpp/sync.h:88
server_thread
void server_thread(void *vargs)
Definition: concurrent_connectivity_test.cc:107
SSL_KEY_PATH
#define SSL_KEY_PATH
Definition: server_ssl_common.cc:46
string.h
gpr_event_set
GPRAPI void gpr_event_set(gpr_event *ev, void *value)
Definition: sync.cc:59
gpr_free
GPRAPI void gpr_free(void *ptr)
Definition: alloc.cc:51
testing::internal::string
::std::string string
Definition: bloaty/third_party/protobuf/third_party/googletest/googletest/include/gtest/internal/gtest-port.h:881
ERR_print_errors_fp
#define ERR_print_errors_fp
Definition: boringssl_prefix_symbols.h:1437
GRPC_OP_COMPLETE
@ GRPC_OP_COMPLETE
Definition: grpc_types.h:558
grpc_server_create
GRPCAPI grpc_server * grpc_server_create(const grpc_channel_args *args, void *reserved)
Definition: src/core/lib/surface/server.cc:1456
gpr_malloc
GPRAPI void * gpr_malloc(size_t size)
Definition: alloc.cc:29
ABSL_GUARDED_BY
#define ABSL_GUARDED_BY(x)
Definition: abseil-cpp/absl/base/thread_annotations.h:62
grpc_server_register_completion_queue
GRPCAPI void grpc_server_register_completion_queue(grpc_server *server, grpc_completion_queue *cq, void *reserved)
Definition: src/core/lib/surface/server.cc:1466
GRPC_LOG_IF_ERROR
#define GRPC_LOG_IF_ERROR(what, error)
Definition: error.h:398
xds_manager.p
p
Definition: xds_manager.py:60
grpc_security.h
uint8_t
unsigned char uint8_t
Definition: stdint-msvc2008.h:78
TLSv1_2_client_method
#define TLSv1_2_client_method
Definition: boringssl_prefix_symbols.h:544
grpc_ssl_pem_key_cert_pair::cert_chain
const char * cert_chain
Definition: grpc_security.h:180
ssl_ctx_st
Definition: third_party/boringssl-with-bazel/src/ssl/internal.h:3404
gen_build_yaml.struct
def struct(**kwargs)
Definition: test/core/end2end/gen_build_yaml.py:30
mu_
Mutex mu_
Definition: oob_backend_metric.cc:115
python_utils.port_server.stderr
stderr
Definition: port_server.py:51
SSL_CTX_free
#define SSL_CTX_free
Definition: boringssl_prefix_symbols.h:84
memcpy
memcpy(mem, inblock.get(), min(CONTAINING_RECORD(inblock.get(), MEMBLOCK, data) ->size, size))
SSL_CTX_new
#define SSL_CTX_new
Definition: boringssl_prefix_symbols.h:115
GPR_ASSERT
#define GPR_ASSERT(x)
Definition: include/grpc/impl/codegen/log.h:94
grpc_ssl_server_credentials_create
GRPCAPI grpc_server_credentials * 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)
Definition: ssl_credentials.cc:319
grpc_server_credentials_release
GRPCAPI void grpc_server_credentials_release(grpc_server_credentials *creds)
Definition: credentials.cc:95
ssl_st
Definition: third_party/boringssl-with-bazel/src/ssl/internal.h:3698
grpc_server_add_http2_port
GRPCAPI int grpc_server_add_http2_port(grpc_server *server, const char *addr, grpc_server_credentials *creds)
Definition: chttp2_server.cc:1029
gpr_log
GPRAPI void gpr_log(const char *file, int line, gpr_log_severity severity, const char *format,...) GPR_PRINT_FORMAT_CHECK(4
grpc_event
Definition: grpc_types.h:564
grpc_completion_queue
Definition: completion_queue.cc:347
grpc.h
GRPC_SLICE_START_PTR
#define GRPC_SLICE_START_PTR(slice)
Definition: include/grpc/impl/codegen/slice.h:101
err.h
arg
Definition: cmdline.cc:40
create_socket
int create_socket(const char *socket_type, fd_pair *client_fds, fd_pair *server_fds)
Definition: low_level_ping_pong.cc:560
grpc_slice
Definition: include/grpc/impl/codegen/slice.h:65
close
#define close
Definition: test-fs.c:48
grpc_server
struct grpc_server grpc_server
Definition: grpc_types.h:65
gpr_event_init
GPRAPI void gpr_event_init(gpr_event *ev)
Definition: sync.cc:54
grpc_server_destroy
GRPCAPI void grpc_server_destroy(grpc_server *server)
Definition: src/core/lib/surface/server.cc:1519
GPR_ERROR
#define GPR_ERROR
Definition: include/grpc/impl/codegen/log.h:57
grpc_pick_unused_port_or_die
int grpc_pick_unused_port_or_die(void)
ssl.h
tests.unit._exit_scenarios.port
port
Definition: _exit_scenarios.py:179
test_config.h
SSL_CTX_use_certificate_file
#define SSL_CTX_use_certificate_file
Definition: boringssl_prefix_symbols.h:231
SSL_CA_PATH
#define SSL_CA_PATH
Definition: server_ssl_common.cc:47
SSL_CTX_set_cipher_list
#define SSL_CTX_set_cipher_list
Definition: boringssl_prefix_symbols.h:157
SSL_free
#define SSL_free
Definition: boringssl_prefix_symbols.h:308
grpc_server_credentials
Definition: src/core/lib/security/credentials/credentials.h:259
grpc_core::Mutex
Definition: src/core/lib/gprpp/sync.h:61
gpr_event
Definition: impl/codegen/sync_generic.h:31
SSL_CERT_PATH
#define SSL_CERT_PATH
Definition: server_ssl_common.cc:45
server
Definition: examples/python/async_streaming/server.py:1
grpc_completion_queue_destroy
GRPCAPI void grpc_completion_queue_destroy(grpc_completion_queue *cq)
Definition: completion_queue.cc:1424
alloc.h
thd.h
grpc_server_shutdown_and_notify
GRPCAPI void grpc_server_shutdown_and_notify(grpc_server *server, grpc_completion_queue *cq, void *tag)
Definition: src/core/lib/surface/server.cc:1503
EVP_cleanup
#define EVP_cleanup
Definition: boringssl_prefix_symbols.h:1715
ssl_method_st
Definition: third_party/boringssl-with-bazel/src/ssl/internal.h:3392
server_ssl_common.h
grpc_completion_queue_next
GRPCAPI grpc_event grpc_completion_queue_next(grpc_completion_queue *cq, gpr_timespec deadline, void *reserved)
Definition: completion_queue.cc:1133
grpc_completion_queue_shutdown
GRPCAPI void grpc_completion_queue_shutdown(grpc_completion_queue *cq)
Definition: completion_queue.cc:1416
ok
bool ok
Definition: async_end2end_test.cc:197
arg
struct arg arg
grpc_core::Thread
Definition: thd.h:43
SSL_CTX_use_PrivateKey_file
#define SSL_CTX_use_PrivateKey_file
Definition: boringssl_prefix_symbols.h:224
SSL_CTX_set_alpn_protos
#define SSL_CTX_set_alpn_protos
Definition: boringssl_prefix_symbols.h:151
SSL_new
#define SSL_new
Definition: boringssl_prefix_symbols.h:414
server_ssl_test
bool server_ssl_test(const char *alpn_list[], unsigned int alpn_list_len, const char *alpn_expected)
Definition: server_ssl_common.cc:170
test_server.socket
socket
Definition: test_server.py:65
grpc_completion_queue_create_for_next
GRPCAPI grpc_completion_queue * grpc_completion_queue_create_for_next(void *reserved)
Definition: completion_queue_factory.cc:62
profile_analyzer.thd
thd
Definition: profile_analyzer.py:168
len
int len
Definition: abseil-cpp/absl/base/internal/low_level_alloc_test.cc:46
gpr_timespec
Definition: gpr_types.h:50
grpc_event::type
grpc_completion_type type
Definition: grpc_types.h:566
grpc_init
GRPCAPI void grpc_init(void)
Definition: init.cc:146
grpc_server_start
GRPCAPI void grpc_server_start(grpc_server *server)
Definition: src/core/lib/surface/server.cc:1497
method
NSString * method
Definition: ProtoMethod.h:28
port_
int port_
Definition: streams_not_seen_test.cc:377
SSL_set_fd
#define SSL_set_fd
Definition: boringssl_prefix_symbols.h:463
sync.h
GRPC_QUEUE_TIMEOUT
@ GRPC_QUEUE_TIMEOUT
Definition: grpc_types.h:556
grpc_shutdown
GRPCAPI void grpc_shutdown(void)
Definition: init.cc:209
CleanupSslLibrary
void CleanupSslLibrary()
Definition: server_ssl_common.cc:283
grpc_ssl_pem_key_cert_pair
Definition: grpc_security.h:173
addr
struct sockaddr_in addr
Definition: libuv/docs/code/tcp-echo-server/main.c:10
cq
static grpc_completion_queue * cq
Definition: test/core/fling/client.cc:37
sync.h
i
uint64_t i
Definition: abseil-cpp/absl/container/btree_benchmark.cc:230
SSL_FILETYPE_PEM
#define SSL_FILETYPE_PEM
Definition: ssl.h:1185


grpc
Author(s):
autogenerated on Thu Mar 13 2025 03:01:17