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