1 // Copyright 2023 gRPC authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include <grpc/grpc.h>
16 #include <grpc/slice.h>
17
18 #include "absl/log/check.h"
19 #include "src/core/server/server.h"
20 #include "test/core/bad_client/bad_client.h"
21 #include "test/core/end2end/cq_verifier.h"
22 #include "test/core/test_util/test_config.h"
23
24 #define PFX_STR \
25 "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n" \
26 "\x00\x00\x00\x04\x00\x00\x00\x00\x00" /* settings frame */ \
27 "\x00\x00\xc9\x01\x04\x00\x00\x00\x01" /* headers: generated from \
28 simple_request.headers in this \
29 directory */ \
30 "\x10\x05:path\x08/foo/bar" \
31 "\x10\x07:scheme\x04http" \
32 "\x10\x07:method\x04POST" \
33 "\x10\x0a:authority\x09localhost" \
34 "\x10\x0c" \
35 "content-type\x10" \
36 "application/grpc" \
37 "\x10\x14grpc-accept-encoding\x15" \
38 "deflate,identity,gzip" \
39 "\x10\x02te\x08trailers" \
40 "\x10\x0auser-agent\"bad-client grpc-c/0.12.0.0 (linux)"
41
42 #define ONE_SETTING_HDR \
43 "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n" \
44 "\x00\x00\x06\x04\x00\x00\x00\x00\x00" /* settings frame */
45
46 #define USUAL_HDR \
47 "\x00\x00\xc9\x01\x04\x00\x00\x00\x01" /* headers: generated from \
48 simple_request.headers in this \
49 directory */ \
50 "\x10\x05:path\x08/foo/bar" \
51 "\x10\x07:scheme\x04http" \
52 "\x10\x07:method\x04POST" \
53 "\x10\x0a:authority\x09localhost" \
54 "\x10\x0c" \
55 "content-type\x10" \
56 "application/grpc" \
57 "\x10\x14grpc-accept-encoding\x15" \
58 "deflate,identity,gzip" \
59 "\x10\x02te\x08trailers" \
60 "\x10\x0auser-agent\"bad-client grpc-c/0.12.0.0 (linux)"
61
62 #define PFX_STR_UNUSUAL \
63 "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n" \
64 "\x00\x00\x00\x04\x00\x00\x00\x00\x00" /* settings frame */ \
65 "\x00\x00\xf4\x01\x04\x00\x00\x00\x01" /* headers: generated from \
66 simple_request_unusual.headers \
67 in this directory */ \
68 "\x10\x05:path\x08/foo/bar" \
69 "\x10\x07:scheme\x04http" \
70 "\x10\x07:method\x04POST" \
71 "\x10\x04host\x09localhost" \
72 "\x10\x0c" \
73 "content-type\x1e" \
74 "application/grpc+this-is-valid" \
75 "\x10\x14grpc-accept-encoding\x15identity,deflate,gzip" \
76 "\x10\x02te\x08trailers" \
77 "\x10\x0auser-agent\"bad-client grpc-c/0.12.0.0 (linux)" \
78 "\x10\x0cgrpc-timeout\x03" \
79 "10S" \
80 "\x10\x0cgrpc-timeout\x02" \
81 "5S"
82
83 #define PFX_STR_UNUSUAL2 \
84 "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n" \
85 "\x00\x00\x00\x04\x00\x00\x00\x00\x00" /* settings frame */ \
86 "\x00\x00\xf4\x01\x04\x00\x00\x00\x01" /* headers: generated from \
87 simple_request_unusual2.headers \
88 in this directory */ \
89 "\x10\x05:path\x08/foo/bar" \
90 "\x10\x07:scheme\x04http" \
91 "\x10\x07:method\x04POST" \
92 "\x10\x04host\x09localhost" \
93 "\x10\x0c" \
94 "content-type\x1e" \
95 "application/grpc;this-is-valid" \
96 "\x10\x14grpc-accept-encoding\x15identity,deflate,gzip" \
97 "\x10\x02te\x08trailers" \
98 "\x10\x0auser-agent\"bad-client grpc-c/0.12.0.0 (linux)" \
99 "\x10\x0cgrpc-timeout\x03" \
100 "10S" \
101 "\x10\x0cgrpc-timeout\x02" \
102 "5S"
103
104 #define PFX_STR_TEXT_HTML_CONTENT_TYPE_HEADER \
105 "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n" \
106 "\x00\x00\x00\x04\x00\x00\x00\x00\x00" /* settings frame */ \
107 "\x00\x00\xdf\x01\x04\x00\x00\x00\x01" /* headers: generated from \
108 simple_request_text_html_content_type.headers \
109 in this directory */ \
110 "\x10\x05:path\x08/foo/bar" \
111 "\x10\x07:scheme\x04http" \
112 "\x10\x07:method\x04POST" \
113 "\x10\x04host\x09localhost" \
114 "\x10\x0c" \
115 "content-type\x09text/html" \
116 "\x10\x14grpc-accept-encoding\x15" \
117 "deflate,identity,gzip" \
118 "\x10\x02te\x08trailers" \
119 "\x10\x0auser-agent\"bad-client grpc-c/0.12.0.0 (linux)" \
120 "\x10\x0cgrpc-timeout\x03" \
121 "10S" \
122 "\x10\x0cgrpc-timeout\x02" \
123 "5S"
124
verifier(grpc_server * server,grpc_completion_queue * cq,void *)125 static void verifier(grpc_server* server, grpc_completion_queue* cq,
126 void* /*registered_method*/) {
127 grpc_call_error error;
128 grpc_call* s;
129 grpc_call_details call_details;
130 grpc_core::CqVerifier cqv(cq);
131 grpc_metadata_array request_metadata_recv;
132
133 grpc_call_details_init(&call_details);
134 grpc_metadata_array_init(&request_metadata_recv);
135
136 error = grpc_server_request_call(server, &s, &call_details,
137 &request_metadata_recv, cq, cq,
138 grpc_core::CqVerifier::tag(101));
139 CHECK_EQ(error, GRPC_CALL_OK);
140 cqv.Expect(grpc_core::CqVerifier::tag(101), true);
141 cqv.Verify();
142
143 CHECK_EQ(grpc_slice_str_cmp(call_details.host, "localhost"), 0);
144 CHECK_EQ(grpc_slice_str_cmp(call_details.method, "/foo/bar"), 0);
145
146 grpc_metadata_array_destroy(&request_metadata_recv);
147 grpc_call_details_destroy(&call_details);
148 grpc_call_unref(s);
149 }
150
VerifyRpcDoesNotGetCanceled(grpc_server * server,grpc_completion_queue * cq,void *)151 static void VerifyRpcDoesNotGetCanceled(grpc_server* server,
152 grpc_completion_queue* cq,
153 void* /*registered_method*/) {
154 grpc_call_error error;
155 grpc_call* s;
156 grpc_call_details call_details;
157 grpc_core::CqVerifier cqv(cq);
158 grpc_metadata_array request_metadata_recv;
159 int was_cancelled = 2;
160
161 grpc_call_details_init(&call_details);
162 grpc_metadata_array_init(&request_metadata_recv);
163
164 error = grpc_server_request_call(server, &s, &call_details,
165 &request_metadata_recv, cq, cq,
166 grpc_core::CqVerifier::tag(101));
167 CHECK_EQ(error, GRPC_CALL_OK);
168 cqv.Expect(grpc_core::CqVerifier::tag(101), true);
169 cqv.Verify();
170
171 CHECK_EQ(grpc_slice_str_cmp(call_details.host, "localhost"), 0);
172 CHECK_EQ(grpc_slice_str_cmp(call_details.method, "/foo/bar"), 0);
173
174 grpc_op* op;
175 grpc_op ops[6];
176 // Send the initial metadata and the status from the server.
177 memset(ops, 0, sizeof(ops));
178 op = ops;
179 op->op = GRPC_OP_SEND_INITIAL_METADATA;
180 op->data.send_initial_metadata.count = 0;
181 op->flags = 0;
182 op->reserved = nullptr;
183 op++;
184 op->op = GRPC_OP_RECV_CLOSE_ON_SERVER;
185 op->data.recv_close_on_server.cancelled = &was_cancelled;
186 op->flags = 0;
187 op->reserved = nullptr;
188 op++;
189 op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
190 op->data.send_status_from_server.trailing_metadata_count = 0;
191 op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED;
192 grpc_slice status_details = grpc_slice_from_static_string("xyz");
193 op->data.send_status_from_server.status_details = &status_details;
194 op->flags = 0;
195 op->reserved = nullptr;
196 op++;
197 error = grpc_call_start_batch(s, ops, static_cast<size_t>(op - ops),
198 grpc_core::CqVerifier::tag(103), nullptr);
199 CHECK_EQ(error, GRPC_CALL_OK);
200
201 cqv.Expect(grpc_core::CqVerifier::tag(103), true);
202 cqv.Verify();
203
204 // If the call had an error, `was_cancelled` would be 1.
205 // CHECK_EQ(was_cancelled, 1);
206
207 grpc_metadata_array_destroy(&request_metadata_recv);
208 grpc_call_details_destroy(&call_details);
209 grpc_call_unref(s);
210 }
211
failure_verifier(grpc_server * server,grpc_completion_queue * cq,void *)212 static void failure_verifier(grpc_server* server, grpc_completion_queue* cq,
213 void* /*registered_method*/) {
214 while (grpc_core::Server::FromC(server)->HasOpenConnections()) {
215 CHECK(grpc_completion_queue_next(
216 cq, grpc_timeout_milliseconds_to_deadline(20), nullptr)
217 .type == GRPC_QUEUE_TIMEOUT);
218 }
219 }
220
main(int argc,char ** argv)221 int main(int argc, char** argv) {
222 grpc::testing::TestEnvironment env(&argc, argv);
223 grpc_init();
224
225 // basic request: check that things are working
226 GRPC_RUN_BAD_CLIENT_TEST(verifier, nullptr, PFX_STR, 0);
227 GRPC_RUN_BAD_CLIENT_TEST(verifier, nullptr, PFX_STR_UNUSUAL, 0);
228 GRPC_RUN_BAD_CLIENT_TEST(verifier, nullptr, PFX_STR_UNUSUAL2, 0);
229
230 // A basic request with a "content-type: text/html" header. The spec is
231 // not clear on what the behavior should be here, so to avoid breaking anyone,
232 // we should continue to accept this header.
233 GRPC_RUN_BAD_CLIENT_TEST(VerifyRpcDoesNotGetCanceled, nullptr,
234 PFX_STR_TEXT_HTML_CONTENT_TYPE_HEADER, 0);
235
236 // push an illegal data frame
237 GRPC_RUN_BAD_CLIENT_TEST(verifier, nullptr,
238 PFX_STR
239 "\x00\x00\x05\x00\x00\x00\x00\x00\x01"
240 "\x34\x00\x00\x00\x00",
241 0);
242 // push a data frame with bad flags
243 GRPC_RUN_BAD_CLIENT_TEST(verifier, nullptr,
244 PFX_STR "\x00\x00\x00\x00\x02\x00\x00\x00\x01", 0);
245 // push a window update with a bad length
246 GRPC_RUN_BAD_CLIENT_TEST(failure_verifier, nullptr,
247 PFX_STR "\x00\x00\x01\x08\x00\x00\x00\x00\x01", 0);
248 // push a window update with bad flags
249 GRPC_RUN_BAD_CLIENT_TEST(failure_verifier, nullptr,
250 PFX_STR "\x00\x00\x00\x08\x10\x00\x00\x00\x01", 0);
251 // push a window update with bad data (0 is not legal window size increment)
252 GRPC_RUN_BAD_CLIENT_TEST(failure_verifier, nullptr,
253 PFX_STR
254 "\x00\x00\x04\x08\x00\x00\x00\x00\x01"
255 "\x00\x00\x00\x00",
256 0);
257 // push a valid secure frame with payload "hello" and setting
258 // `allow_security_frame` enabled, frame should be parsed
259 GRPC_RUN_BAD_CLIENT_TEST(
260 verifier, nullptr,
261 ONE_SETTING_HDR
262 "\xFE\x05\x00\x00\x00\x01" USUAL_HDR
263 "\x00\x00\x05\xC8\x00\x00\x00\x00\x00\x68\x65\x6C\x6C\x6F",
264 0);
265 // push a valid secure frame with payload "hello" and setting
266 // `allow_security_frame` disabled, frame should be ignored
267 GRPC_RUN_BAD_CLIENT_TEST(
268 VerifyRpcDoesNotGetCanceled, nullptr,
269 ONE_SETTING_HDR
270 "\xFE\x05\x00\x00\x00\x00" USUAL_HDR
271 "\x00\x00\x05\xC8\x00\x00\x00\x00\x00\x68\x65\x6C\x6C\x6F",
272 0);
273 // push a short goaway
274 GRPC_RUN_BAD_CLIENT_TEST(failure_verifier, nullptr,
275 PFX_STR "\x00\x00\x04\x07\x00\x00\x00\x00\x00", 0);
276 // disconnect before sending goaway
277 GRPC_RUN_BAD_CLIENT_TEST(failure_verifier, nullptr,
278 PFX_STR "\x00\x01\x12\x07\x00\x00\x00\x00\x00",
279 GRPC_BAD_CLIENT_DISCONNECT);
280 // push a rst_stream with a bad length
281 GRPC_RUN_BAD_CLIENT_TEST(failure_verifier, nullptr,
282 PFX_STR "\x00\x00\x01\x03\x00\x00\x00\x00\x01", 0);
283 // push a rst_stream with bad flags
284 GRPC_RUN_BAD_CLIENT_TEST(failure_verifier, nullptr,
285 PFX_STR "\x00\x00\x00\x03\x10\x00\x00\x00\x01", 0);
286
287 grpc_shutdown();
288 return 0;
289 }
290