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 
19 #include <stdio.h>
20 #include <string.h>
21 
22 #include <gtest/gtest.h>
23 
24 #include <grpc/support/alloc.h>
25 #include <grpc/support/log.h>
26 
27 #include "src/core/lib/channel/channel_args.h"
28 #include "src/core/lib/gpr/string.h"
29 #include "src/core/lib/gpr/tmpfile.h"
30 #include "src/core/lib/gprpp/host_port.h"
31 #include "src/core/lib/iomgr/load_file.h"
32 #include "src/core/lib/security/credentials/credentials.h"
33 #include "src/core/lib/security/security_connector/ssl_utils_config.h"
34 #include "test/core/end2end/cq_verifier.h"
35 #include "test/core/end2end/end2end_tests.h"
36 #include "test/core/util/port.h"
37 #include "test/core/util/test_config.h"
38 
39 #define CA_CERT_PATH "src/core/tsi/test_creds/ca.pem"
40 #define CLIENT_CERT_PATH "src/core/tsi/test_creds/client.pem"
41 #define CLIENT_KEY_PATH "src/core/tsi/test_creds/client.key"
42 #define SERVER_CERT_PATH "src/core/tsi/test_creds/server1.pem"
43 #define SERVER_KEY_PATH "src/core/tsi/test_creds/server1.key"
44 
45 namespace grpc {
46 namespace testing {
47 namespace {
48 
tag(intptr_t t)49 void* tag(intptr_t t) { return reinterpret_cast<void*>(t); }
50 
five_seconds_time()51 gpr_timespec five_seconds_time() { return grpc_timeout_seconds_to_deadline(5); }
52 
server_create(grpc_completion_queue * cq,const char * server_addr)53 grpc_server* server_create(grpc_completion_queue* cq, const char* server_addr) {
54   grpc_slice ca_slice, cert_slice, key_slice;
55   GPR_ASSERT(GRPC_LOG_IF_ERROR("load_file",
56                                grpc_load_file(CA_CERT_PATH, 1, &ca_slice)));
57   GPR_ASSERT(GRPC_LOG_IF_ERROR(
58       "load_file", grpc_load_file(SERVER_CERT_PATH, 1, &cert_slice)));
59   GPR_ASSERT(GRPC_LOG_IF_ERROR("load_file",
60                                grpc_load_file(SERVER_KEY_PATH, 1, &key_slice)));
61   const char* ca_cert =
62       reinterpret_cast<const char*> GRPC_SLICE_START_PTR(ca_slice);
63   const char* server_cert =
64       reinterpret_cast<const char*> GRPC_SLICE_START_PTR(cert_slice);
65   const char* server_key =
66       reinterpret_cast<const char*> GRPC_SLICE_START_PTR(key_slice);
67   grpc_ssl_pem_key_cert_pair pem_cert_key_pair = {server_key, server_cert};
68   grpc_server_credentials* server_creds = grpc_ssl_server_credentials_create_ex(
69       ca_cert, &pem_cert_key_pair, 1,
70       GRPC_SSL_REQUEST_CLIENT_CERTIFICATE_AND_VERIFY, nullptr);
71 
72   grpc_server* server = grpc_server_create(nullptr, nullptr);
73   grpc_server_register_completion_queue(server, cq, nullptr);
74   GPR_ASSERT(
75       grpc_server_add_secure_http2_port(server, server_addr, server_creds));
76   grpc_server_credentials_release(server_creds);
77   grpc_server_start(server);
78 
79   grpc_slice_unref(cert_slice);
80   grpc_slice_unref(key_slice);
81   grpc_slice_unref(ca_slice);
82   return server;
83 }
84 
client_create(const char * server_addr,grpc_ssl_session_cache * cache)85 grpc_channel* client_create(const char* server_addr,
86                             grpc_ssl_session_cache* cache) {
87   grpc_slice ca_slice, cert_slice, key_slice;
88   GPR_ASSERT(GRPC_LOG_IF_ERROR("load_file",
89                                grpc_load_file(CA_CERT_PATH, 1, &ca_slice)));
90   GPR_ASSERT(GRPC_LOG_IF_ERROR(
91       "load_file", grpc_load_file(CLIENT_CERT_PATH, 1, &cert_slice)));
92   GPR_ASSERT(GRPC_LOG_IF_ERROR("load_file",
93                                grpc_load_file(CLIENT_KEY_PATH, 1, &key_slice)));
94   const char* ca_cert =
95       reinterpret_cast<const char*> GRPC_SLICE_START_PTR(ca_slice);
96   const char* client_cert =
97       reinterpret_cast<const char*> GRPC_SLICE_START_PTR(cert_slice);
98   const char* client_key =
99       reinterpret_cast<const char*> GRPC_SLICE_START_PTR(key_slice);
100   grpc_ssl_pem_key_cert_pair signed_client_key_cert_pair = {client_key,
101                                                             client_cert};
102   grpc_channel_credentials* client_creds = grpc_ssl_credentials_create(
103       ca_cert, &signed_client_key_cert_pair, nullptr, nullptr);
104 
105   grpc_arg args[] = {
106       grpc_channel_arg_string_create(
107           const_cast<char*>(GRPC_SSL_TARGET_NAME_OVERRIDE_ARG),
108           const_cast<char*>("waterzooi.test.google.be")),
109       grpc_ssl_session_cache_create_channel_arg(cache),
110   };
111 
112   grpc_channel_args* client_args =
113       grpc_channel_args_copy_and_add(nullptr, args, GPR_ARRAY_SIZE(args));
114 
115   grpc_channel* client = grpc_secure_channel_create(client_creds, server_addr,
116                                                     client_args, nullptr);
117   GPR_ASSERT(client != nullptr);
118   grpc_channel_credentials_release(client_creds);
119 
120   {
121     grpc_core::ExecCtx exec_ctx;
122     grpc_channel_args_destroy(client_args);
123   }
124 
125   grpc_slice_unref(cert_slice);
126   grpc_slice_unref(key_slice);
127   grpc_slice_unref(ca_slice);
128   return client;
129 }
130 
do_round_trip(grpc_completion_queue * cq,grpc_server * server,const char * server_addr,grpc_ssl_session_cache * cache,bool expect_session_reuse)131 void do_round_trip(grpc_completion_queue* cq, grpc_server* server,
132                    const char* server_addr, grpc_ssl_session_cache* cache,
133                    bool expect_session_reuse) {
134   grpc_channel* client = client_create(server_addr, cache);
135 
136   cq_verifier* cqv = cq_verifier_create(cq);
137   grpc_op ops[6];
138   grpc_op* op;
139   grpc_metadata_array initial_metadata_recv;
140   grpc_metadata_array trailing_metadata_recv;
141   grpc_metadata_array request_metadata_recv;
142   grpc_call_details call_details;
143   grpc_status_code status;
144   grpc_call_error error;
145   grpc_slice details;
146   int was_cancelled = 2;
147 
148   gpr_timespec deadline = grpc_timeout_seconds_to_deadline(60);
149   grpc_call* c = grpc_channel_create_call(
150       client, nullptr, GRPC_PROPAGATE_DEFAULTS, cq,
151       grpc_slice_from_static_string("/foo"), nullptr, deadline, nullptr);
152   GPR_ASSERT(c);
153 
154   grpc_metadata_array_init(&initial_metadata_recv);
155   grpc_metadata_array_init(&trailing_metadata_recv);
156   grpc_metadata_array_init(&request_metadata_recv);
157   grpc_call_details_init(&call_details);
158 
159   memset(ops, 0, sizeof(ops));
160   op = ops;
161   op->op = GRPC_OP_SEND_INITIAL_METADATA;
162   op->data.send_initial_metadata.count = 0;
163   op->flags = 0;
164   op->reserved = nullptr;
165   op++;
166   op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT;
167   op->flags = 0;
168   op->reserved = nullptr;
169   op++;
170   op->op = GRPC_OP_RECV_INITIAL_METADATA;
171   op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv;
172   op->flags = 0;
173   op->reserved = nullptr;
174   op++;
175   op->op = GRPC_OP_RECV_STATUS_ON_CLIENT;
176   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
177   op->data.recv_status_on_client.status = &status;
178   op->data.recv_status_on_client.status_details = &details;
179   op->flags = 0;
180   op->reserved = nullptr;
181   op++;
182   error = grpc_call_start_batch(c, ops, static_cast<size_t>(op - ops), tag(1),
183                                 nullptr);
184   GPR_ASSERT(GRPC_CALL_OK == error);
185 
186   grpc_call* s;
187   error = grpc_server_request_call(server, &s, &call_details,
188                                    &request_metadata_recv, cq, cq, tag(101));
189   GPR_ASSERT(GRPC_CALL_OK == error);
190   CQ_EXPECT_COMPLETION(cqv, tag(101), 1);
191   cq_verify(cqv);
192 
193   grpc_auth_context* auth = grpc_call_auth_context(s);
194   grpc_auth_property_iterator it = grpc_auth_context_find_properties_by_name(
195       auth, GRPC_SSL_SESSION_REUSED_PROPERTY);
196   const grpc_auth_property* property = grpc_auth_property_iterator_next(&it);
197   GPR_ASSERT(property != nullptr);
198   if (expect_session_reuse) {
199     GPR_ASSERT(strcmp(property->value, "true") == 0);
200   } else {
201     GPR_ASSERT(strcmp(property->value, "false") == 0);
202   }
203   grpc_auth_context_release(auth);
204 
205   memset(ops, 0, sizeof(ops));
206   op = ops;
207   op->op = GRPC_OP_SEND_INITIAL_METADATA;
208   op->data.send_initial_metadata.count = 0;
209   op->flags = 0;
210   op->reserved = nullptr;
211   op++;
212   op->op = GRPC_OP_RECV_CLOSE_ON_SERVER;
213   op->data.recv_close_on_server.cancelled = &was_cancelled;
214   op->flags = 0;
215   op->reserved = nullptr;
216   op++;
217   op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
218   op->data.send_status_from_server.trailing_metadata_count = 0;
219   op->data.send_status_from_server.status = GRPC_STATUS_OK;
220   op->flags = 0;
221   op->reserved = nullptr;
222   op++;
223   error = grpc_call_start_batch(s, ops, static_cast<size_t>(op - ops), tag(103),
224                                 nullptr);
225   GPR_ASSERT(GRPC_CALL_OK == error);
226 
227   CQ_EXPECT_COMPLETION(cqv, tag(103), 1);
228   CQ_EXPECT_COMPLETION(cqv, tag(1), 1);
229   cq_verify(cqv);
230 
231   grpc_metadata_array_destroy(&initial_metadata_recv);
232   grpc_metadata_array_destroy(&trailing_metadata_recv);
233   grpc_metadata_array_destroy(&request_metadata_recv);
234   grpc_call_details_destroy(&call_details);
235 
236   grpc_call_unref(c);
237   grpc_call_unref(s);
238 
239   cq_verifier_destroy(cqv);
240 
241   grpc_channel_destroy(client);
242 }
243 
drain_cq(grpc_completion_queue * cq)244 void drain_cq(grpc_completion_queue* cq) {
245   grpc_event ev;
246   do {
247     ev = grpc_completion_queue_next(cq, five_seconds_time(), nullptr);
248   } while (ev.type != GRPC_QUEUE_SHUTDOWN);
249 }
250 
TEST(H2SessionReuseTest,SingleReuse)251 TEST(H2SessionReuseTest, SingleReuse) {
252   int port = grpc_pick_unused_port_or_die();
253 
254   std::string server_addr = grpc_core::JoinHostPort("localhost", port);
255 
256   grpc_completion_queue* cq = grpc_completion_queue_create_for_next(nullptr);
257   grpc_ssl_session_cache* cache = grpc_ssl_session_cache_create_lru(16);
258 
259   grpc_server* server = server_create(cq, server_addr.c_str());
260 
261   do_round_trip(cq, server, server_addr.c_str(), cache, false);
262   do_round_trip(cq, server, server_addr.c_str(), cache, true);
263   do_round_trip(cq, server, server_addr.c_str(), cache, true);
264 
265   grpc_ssl_session_cache_destroy(cache);
266 
267   GPR_ASSERT(grpc_completion_queue_next(
268                  cq, grpc_timeout_milliseconds_to_deadline(100), nullptr)
269                  .type == GRPC_QUEUE_TIMEOUT);
270 
271   grpc_completion_queue* shutdown_cq =
272       grpc_completion_queue_create_for_pluck(nullptr);
273   grpc_server_shutdown_and_notify(server, shutdown_cq, tag(1000));
274   GPR_ASSERT(grpc_completion_queue_pluck(shutdown_cq, tag(1000),
275                                          grpc_timeout_seconds_to_deadline(5),
276                                          nullptr)
277                  .type == GRPC_OP_COMPLETE);
278   grpc_server_destroy(server);
279   grpc_completion_queue_destroy(shutdown_cq);
280 
281   grpc_completion_queue_shutdown(cq);
282   drain_cq(cq);
283   grpc_completion_queue_destroy(cq);
284 }
285 
286 }  // namespace
287 }  // namespace testing
288 }  // namespace grpc
289 
main(int argc,char ** argv)290 int main(int argc, char** argv) {
291   grpc::testing::TestEnvironment env(argc, argv);
292   GPR_GLOBAL_CONFIG_SET(grpc_default_ssl_roots_file_path, CA_CERT_PATH);
293 
294   grpc_init();
295   ::testing::InitGoogleTest(&argc, argv);
296   int ret = RUN_ALL_TESTS();
297   grpc_shutdown();
298 
299   return ret;
300 }
301