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