verify_peer_options.cc
Go to the documentation of this file.
1 /*
2  *
3  * Copyright 2018 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 // This test won't work except with posix sockets enabled
22 #ifdef GRPC_POSIX_SOCKET_TCP
23 
24 #include <arpa/inet.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <sys/socket.h>
28 #include <unistd.h>
29 
30 #include <string>
31 
32 #include <openssl/err.h>
33 #include <openssl/ssl.h>
34 
35 #include "absl/strings/str_cat.h"
36 
37 #include <grpc/grpc.h>
38 #include <grpc/grpc_security.h>
39 #include <grpc/support/alloc.h>
40 #include <grpc/support/log.h>
41 
42 #include "src/core/lib/gprpp/thd.h"
44 #include "test/core/util/port.h"
46 
47 #define SSL_CERT_PATH "src/core/tsi/test_creds/server1.pem"
48 #define SSL_KEY_PATH "src/core/tsi/test_creds/server1.key"
49 #define SSL_CA_PATH "src/core/tsi/test_creds/ca.pem"
50 
51 // Simple gRPC server. This listens until client_handshake_complete occurs.
52 static gpr_event client_handshake_complete;
53 
54 static void server_thread(void* arg) {
55  const int port = *static_cast<int*>(arg);
56 
57  // Load key pair and establish server SSL credentials.
58  grpc_ssl_pem_key_cert_pair pem_key_cert_pair;
59  grpc_slice ca_slice, cert_slice, key_slice;
60  GPR_ASSERT(GRPC_LOG_IF_ERROR("load_file",
61  grpc_load_file(SSL_CA_PATH, 1, &ca_slice)));
62  GPR_ASSERT(GRPC_LOG_IF_ERROR("load_file",
63  grpc_load_file(SSL_CERT_PATH, 1, &cert_slice)));
64  GPR_ASSERT(GRPC_LOG_IF_ERROR("load_file",
65  grpc_load_file(SSL_KEY_PATH, 1, &key_slice)));
66  const char* ca_cert =
67  reinterpret_cast<const char*> GRPC_SLICE_START_PTR(ca_slice);
68  pem_key_cert_pair.private_key =
69  reinterpret_cast<const char*> GRPC_SLICE_START_PTR(key_slice);
70  pem_key_cert_pair.cert_chain =
71  reinterpret_cast<const char*> GRPC_SLICE_START_PTR(cert_slice);
73  ca_cert, &pem_key_cert_pair, 1, 0, nullptr);
74 
75  // Start server listening on local port.
76  std::string addr = absl::StrCat("127.0.0.1:", port);
77  grpc_server* server = grpc_server_create(nullptr, nullptr);
78  GPR_ASSERT(grpc_server_add_http2_port(server, addr.c_str(), ssl_creds));
79 
81 
84 
85  // Wait a bounded number of time until client_handshake_complete is set,
86  // sleeping between polls. The total time spent (deadline * retries)
87  // should be strictly greater than the client retry limit so that the
88  // client will always timeout first.
89  int retries = 60;
90  while (!gpr_event_get(&client_handshake_complete) && retries-- > 0) {
91  const gpr_timespec cq_deadline = grpc_timeout_seconds_to_deadline(1);
92  grpc_event ev = grpc_completion_queue_next(cq, cq_deadline, nullptr);
94  }
95 
96  gpr_log(GPR_INFO, "Shutting down server");
100 
101  const gpr_timespec cq_deadline = grpc_timeout_seconds_to_deadline(60);
102  grpc_event ev = grpc_completion_queue_next(cq, cq_deadline, nullptr);
104 
108  grpc_slice_unref(cert_slice);
109  grpc_slice_unref(key_slice);
110  grpc_slice_unref(ca_slice);
111 }
112 
113 // This test launches a minimal TLS grpc server on a separate thread and then
114 // establishes a TLS handshake via the core library to the server. The client
115 // uses the supplied verify options.
116 static bool verify_peer_options_test(verify_peer_options* verify_options) {
117  bool success = true;
118 
119  grpc_init();
121  gpr_event_init(&client_handshake_complete);
122 
123  // Load key pair and establish client SSL credentials.
124  // NOTE: we intentionally load the credential files before starting
125  // the server thread because grpc_load_file can experience trouble
126  // when two threads attempt to load the same file concurrently
127  // and server thread also reads the same files as soon as it starts.
128  // See https://github.com/grpc/grpc/issues/23503 for details.
129  grpc_ssl_pem_key_cert_pair pem_key_cert_pair;
130  grpc_slice ca_slice, cert_slice, key_slice;
131  GPR_ASSERT(GRPC_LOG_IF_ERROR("load_file",
132  grpc_load_file(SSL_CA_PATH, 1, &ca_slice)));
133  GPR_ASSERT(GRPC_LOG_IF_ERROR("load_file",
134  grpc_load_file(SSL_CERT_PATH, 1, &cert_slice)));
135  GPR_ASSERT(GRPC_LOG_IF_ERROR("load_file",
136  grpc_load_file(SSL_KEY_PATH, 1, &key_slice)));
137  const char* ca_cert =
138  reinterpret_cast<const char*> GRPC_SLICE_START_PTR(ca_slice);
139  pem_key_cert_pair.private_key =
140  reinterpret_cast<const char*> GRPC_SLICE_START_PTR(key_slice);
141  pem_key_cert_pair.cert_chain =
142  reinterpret_cast<const char*> GRPC_SLICE_START_PTR(cert_slice);
144  ca_cert, &pem_key_cert_pair, verify_options, nullptr);
145 
146  // Launch the gRPC server thread.
147  bool ok;
148  grpc_core::Thread thd("grpc_client_ssl_test", server_thread, &port, &ok);
149  GPR_ASSERT(ok);
150  thd.Start();
151 
152  // Establish a channel pointing at the TLS server. Since the gRPC runtime is
153  // lazy, this won't necessarily establish a connection yet.
154  std::string target = absl::StrCat("127.0.0.1:", port);
155  grpc_arg ssl_name_override = {
157  const_cast<char*>(GRPC_SSL_TARGET_NAME_OVERRIDE_ARG),
158  {const_cast<char*>("foo.test.google.fr")}};
159  grpc_channel_args grpc_args;
160  grpc_args.num_args = 1;
161  grpc_args.args = &ssl_name_override;
163  grpc_channel_create(target.c_str(), ssl_creds, &grpc_args);
165 
166  // Initially the channel will be idle, the
167  // grpc_channel_check_connectivity_state triggers an attempt to connect.
169  channel, 1 /* try_to_connect */) == GRPC_CHANNEL_IDLE);
170 
171  // Wait a bounded number of times for the channel to be ready. When the
172  // channel is ready, the initial TLS handshake will have successfully
173  // completed. The total time spent on the client side (retries * deadline)
174  // should be greater than the server side time limit.
175  int retries = 10;
178 
179  while (state != GRPC_CHANNEL_READY && retries-- > 0) {
183  grpc_event ev = grpc_completion_queue_next(cq, cq_deadline, nullptr);
185  state =
186  grpc_channel_check_connectivity_state(channel, 0 /* try_to_connect */);
187  }
189  if (retries < 0) {
190  success = false;
191  }
192 
195  grpc_slice_unref(cert_slice);
196  grpc_slice_unref(key_slice);
197  grpc_slice_unref(ca_slice);
198 
199  // Now that the client is completely cleaned up, trigger the server to
200  // shutdown
201  gpr_event_set(&client_handshake_complete, &client_handshake_complete);
202  // Wait for the server to completely shutdown
203  thd.Join();
204 
205  grpc_shutdown();
206 
207  return success;
208 }
209 
210 static int callback_return_value = 0;
211 static char callback_target_host[4096];
212 static char callback_target_pem[4096];
213 static void* callback_userdata = nullptr;
214 static void* destruct_userdata = nullptr;
215 
216 static int verify_callback(const char* target_host, const char* target_pem,
217  void* userdata) {
218  if (target_host != nullptr) {
219  snprintf(callback_target_host, sizeof(callback_target_host), "%s",
220  target_host);
221  } else {
222  callback_target_host[0] = '\0';
223  }
224  if (target_pem != nullptr) {
225  snprintf(callback_target_pem, sizeof(callback_target_pem), "%s",
226  target_pem);
227  } else {
228  callback_target_pem[0] = '\0';
229  }
230  callback_userdata = userdata;
231  return callback_return_value;
232 }
233 
234 static void verify_destruct(void* userdata) { destruct_userdata = userdata; }
235 
236 int main(int argc, char* argv[]) {
237  grpc::testing::TestEnvironment env(&argc, argv);
238  grpc_init();
239 
240  int userdata = 42;
241  verify_peer_options verify_options;
242 
243  // Load the server's cert so that we can assert it gets passed to the callback
244  grpc_slice cert_slice;
245  GPR_ASSERT(GRPC_LOG_IF_ERROR("load_file",
246  grpc_load_file(SSL_CERT_PATH, 1, &cert_slice)));
247  const char* server_cert =
248  reinterpret_cast<const char*> GRPC_SLICE_START_PTR(cert_slice);
249 
250  // Running with all-null values should have no effect
251  verify_options.verify_peer_callback = nullptr;
252  verify_options.verify_peer_callback_userdata = nullptr;
253  verify_options.verify_peer_destruct = nullptr;
254  GPR_ASSERT(verify_peer_options_test(&verify_options));
255  GPR_ASSERT(strlen(callback_target_host) == 0);
256  GPR_ASSERT(strlen(callback_target_pem) == 0);
257  GPR_ASSERT(callback_userdata == nullptr);
258  GPR_ASSERT(destruct_userdata == nullptr);
259 
260  // Running with the callbacks and verify we get the expected values
261  verify_options.verify_peer_callback = verify_callback;
262  verify_options.verify_peer_callback_userdata = static_cast<void*>(&userdata);
263  verify_options.verify_peer_destruct = verify_destruct;
264  GPR_ASSERT(verify_peer_options_test(&verify_options));
265  GPR_ASSERT(strcmp(callback_target_host, "foo.test.google.fr") == 0);
266  GPR_ASSERT(strcmp(callback_target_pem, server_cert) == 0);
267  GPR_ASSERT(callback_userdata == static_cast<void*>(&userdata));
268  GPR_ASSERT(destruct_userdata == static_cast<void*>(&userdata));
269 
270  // If the callback returns non-zero, initializing the channel should fail.
271  callback_return_value = 1;
272  GPR_ASSERT(!verify_peer_options_test(&verify_options));
273 
274  grpc_slice_unref(cert_slice);
275 
276  grpc_shutdown();
277  return 0;
278 }
279 
280 #else /* GRPC_POSIX_SOCKET_TCP */
281 
282 int main(int argc, char** argv) { return 1; }
283 
284 #endif /* GRPC_POSIX_SOCKET_TCP */
grpc_arg
Definition: grpc_types.h:103
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_CHANNEL_READY
@ GRPC_CHANNEL_READY
Definition: include/grpc/impl/codegen/connectivity_state.h:36
verify_peer_options::verify_peer_callback_userdata
void * verify_peer_callback_userdata
Definition: grpc_security.h:198
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
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
generate.env
env
Definition: generate.py:37
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
GRPC_ARG_STRING
@ GRPC_ARG_STRING
Definition: grpc_types.h:80
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
grpc_channel_check_connectivity_state
GRPCAPI grpc_connectivity_state grpc_channel_check_connectivity_state(grpc_channel *channel, int try_to_connect)
Definition: channel_connectivity.cc:56
gpr_event_set
GPRAPI void gpr_event_set(gpr_event *ev, void *value)
Definition: sync.cc:59
main
int main(int argc, char **argv)
Definition: verify_peer_options.cc:282
testing::internal::string
::std::string string
Definition: bloaty/third_party/protobuf/third_party/googletest/googletest/include/gtest/internal/gtest-port.h:881
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
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
grpc_security.h
grpc_ssl_pem_key_cert_pair::cert_chain
const char * cert_chain
Definition: grpc_security.h:180
grpc_channel_args
Definition: grpc_types.h:132
grpc_connectivity_state
grpc_connectivity_state
Definition: include/grpc/impl/codegen/connectivity_state.h:30
grpc_ssl_credentials_create
GRPCAPI grpc_channel_credentials * 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)
Definition: ssl_credentials.cc:132
channel
wrapped_grpc_channel * channel
Definition: src/php/ext/grpc/call.h:33
GPR_ASSERT
#define GPR_ASSERT(x)
Definition: include/grpc/impl/codegen/log.h:94
GRPC_SSL_TARGET_NAME_OVERRIDE_ARG
#define GRPC_SSL_TARGET_NAME_OVERRIDE_ARG
Definition: grpc_types.h:278
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
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
GRPC_CHANNEL_IDLE
@ GRPC_CHANNEL_IDLE
Definition: include/grpc/impl/codegen/connectivity_state.h:32
grpc_channel_args::num_args
size_t num_args
Definition: grpc_types.h:133
arg
Definition: cmdline.cc:40
grpc_slice
Definition: include/grpc/impl/codegen/slice.h:65
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
grpc_pick_unused_port_or_die
int grpc_pick_unused_port_or_die(void)
grpc_server_cancel_all_calls
GRPCAPI void grpc_server_cancel_all_calls(grpc_server *server)
Definition: src/core/lib/surface/server.cc:1512
ssl.h
verify_peer_options
Definition: grpc_security.h:187
tests.unit._exit_scenarios.port
port
Definition: _exit_scenarios.py:179
test_config.h
grpc_channel_credentials_release
GRPCAPI void grpc_channel_credentials_release(grpc_channel_credentials *creds)
Definition: credentials.cc:36
SSL_CA_PATH
#define SSL_CA_PATH
Definition: server_ssl_common.cc:47
grpc_server_credentials
Definition: src/core/lib/security/credentials/credentials.h:259
gpr_event
Definition: impl/codegen/sync_generic.h:31
grpc_channel_create
GRPCAPI grpc_channel * grpc_channel_create(const char *target, grpc_channel_credentials *creds, const grpc_channel_args *args)
Definition: chttp2_connector.cc:366
SSL_CERT_PATH
#define SSL_CERT_PATH
Definition: server_ssl_common.cc:45
verify_peer_options::verify_peer_callback
int(* verify_peer_callback)(const char *target_name, const char *peer_pem, void *userdata)
Definition: grpc_security.h:194
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
port.h
verify_peer_options::verify_peer_destruct
void(* verify_peer_destruct)(void *userdata)
Definition: grpc_security.h:202
alloc.h
grpc::testing::TestEnvironment
Definition: test/core/util/test_config.h:54
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
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_channel_destroy
GRPCAPI void grpc_channel_destroy(grpc_channel *channel)
Definition: channel.cc:437
state
Definition: bloaty/third_party/zlib/contrib/blast/blast.c:41
grpc_core::Thread
Definition: thd.h:43
grpc_channel
struct grpc_channel grpc_channel
Definition: grpc_types.h:62
grpc_channel_watch_connectivity_state
GRPCAPI void grpc_channel_watch_connectivity_state(grpc_channel *channel, grpc_connectivity_state last_observed_state, gpr_timespec deadline, grpc_completion_queue *cq, void *tag)
Definition: channel_connectivity.cc:227
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
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
grpc_channel_args::args
grpc_arg * args
Definition: grpc_types.h:134
GRPC_QUEUE_TIMEOUT
@ GRPC_QUEUE_TIMEOUT
Definition: grpc_types.h:556
grpc_shutdown
GRPCAPI void grpc_shutdown(void)
Definition: init.cc:209
setup.target
target
Definition: third_party/bloaty/third_party/protobuf/python/setup.py:179
grpc_ssl_pem_key_cert_pair
Definition: grpc_security.h:173
grpc_channel_credentials
Definition: src/core/lib/security/credentials/credentials.h:96
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


grpc
Author(s):
autogenerated on Fri May 16 2025 03:00:52