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 #include <grpc/support/log.h>
18
19 #include "src/core/lib/surface/server.h"
20 #include "test/core/bad_client/bad_client.h"
21 #include "test/core/end2end/cq_verifier.h"
22 #include "test/core/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 PFX_STR_UNUSUAL \
43 "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n" \
44 "\x00\x00\x00\x04\x00\x00\x00\x00\x00" /* settings frame */ \
45 "\x00\x00\xf4\x01\x04\x00\x00\x00\x01" /* headers: generated from \
46 simple_request_unusual.headers \
47 in this directory */ \
48 "\x10\x05:path\x08/foo/bar" \
49 "\x10\x07:scheme\x04http" \
50 "\x10\x07:method\x04POST" \
51 "\x10\x04host\x09localhost" \
52 "\x10\x0c" \
53 "content-type\x1e" \
54 "application/grpc+this-is-valid" \
55 "\x10\x14grpc-accept-encoding\x15identity,deflate,gzip" \
56 "\x10\x02te\x08trailers" \
57 "\x10\x0auser-agent\"bad-client grpc-c/0.12.0.0 (linux)" \
58 "\x10\x0cgrpc-timeout\x03" \
59 "10S" \
60 "\x10\x0cgrpc-timeout\x02" \
61 "5S"
62
63 #define PFX_STR_UNUSUAL2 \
64 "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n" \
65 "\x00\x00\x00\x04\x00\x00\x00\x00\x00" /* settings frame */ \
66 "\x00\x00\xf4\x01\x04\x00\x00\x00\x01" /* headers: generated from \
67 simple_request_unusual2.headers \
68 in this directory */ \
69 "\x10\x05:path\x08/foo/bar" \
70 "\x10\x07:scheme\x04http" \
71 "\x10\x07:method\x04POST" \
72 "\x10\x04host\x09localhost" \
73 "\x10\x0c" \
74 "content-type\x1e" \
75 "application/grpc;this-is-valid" \
76 "\x10\x14grpc-accept-encoding\x15identity,deflate,gzip" \
77 "\x10\x02te\x08trailers" \
78 "\x10\x0auser-agent\"bad-client grpc-c/0.12.0.0 (linux)" \
79 "\x10\x0cgrpc-timeout\x03" \
80 "10S" \
81 "\x10\x0cgrpc-timeout\x02" \
82 "5S"
83
84 #define PFX_STR_TEXT_HTML_CONTENT_TYPE_HEADER \
85 "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n" \
86 "\x00\x00\x00\x04\x00\x00\x00\x00\x00" /* settings frame */ \
87 "\x00\x00\xdf\x01\x04\x00\x00\x00\x01" /* headers: generated from \
88 simple_request_text_html_content_type.headers \
89 in this directory */ \
90 "\x10\x05:path\x08/foo/bar" \
91 "\x10\x07:scheme\x04http" \
92 "\x10\x07:method\x04POST" \
93 "\x10\x04host\x09localhost" \
94 "\x10\x0c" \
95 "content-type\x09text/html" \
96 "\x10\x14grpc-accept-encoding\x15" \
97 "deflate,identity,gzip" \
98 "\x10\x02te\x08trailers" \
99 "\x10\x0auser-agent\"bad-client grpc-c/0.12.0.0 (linux)" \
100 "\x10\x0cgrpc-timeout\x03" \
101 "10S" \
102 "\x10\x0cgrpc-timeout\x02" \
103 "5S"
104
verifier(grpc_server * server,grpc_completion_queue * cq,void *)105 static void verifier(grpc_server* server, grpc_completion_queue* cq,
106 void* /*registered_method*/) {
107 grpc_call_error error;
108 grpc_call* s;
109 grpc_call_details call_details;
110 grpc_core::CqVerifier cqv(cq);
111 grpc_metadata_array request_metadata_recv;
112
113 grpc_call_details_init(&call_details);
114 grpc_metadata_array_init(&request_metadata_recv);
115
116 error = grpc_server_request_call(server, &s, &call_details,
117 &request_metadata_recv, cq, cq,
118 grpc_core::CqVerifier::tag(101));
119 GPR_ASSERT(GRPC_CALL_OK == error);
120 cqv.Expect(grpc_core::CqVerifier::tag(101), true);
121 cqv.Verify();
122
123 GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.host, "localhost"));
124 GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo/bar"));
125
126 grpc_metadata_array_destroy(&request_metadata_recv);
127 grpc_call_details_destroy(&call_details);
128 grpc_call_unref(s);
129 }
130
VerifyRpcDoesNotGetCanceled(grpc_server * server,grpc_completion_queue * cq,void *)131 static void VerifyRpcDoesNotGetCanceled(grpc_server* server,
132 grpc_completion_queue* cq,
133 void* /*registered_method*/) {
134 grpc_call_error error;
135 grpc_call* s;
136 grpc_call_details call_details;
137 grpc_core::CqVerifier cqv(cq);
138 grpc_metadata_array request_metadata_recv;
139 int was_cancelled = 2;
140
141 grpc_call_details_init(&call_details);
142 grpc_metadata_array_init(&request_metadata_recv);
143
144 error = grpc_server_request_call(server, &s, &call_details,
145 &request_metadata_recv, cq, cq,
146 grpc_core::CqVerifier::tag(101));
147 GPR_ASSERT(GRPC_CALL_OK == error);
148 cqv.Expect(grpc_core::CqVerifier::tag(101), true);
149 cqv.Verify();
150
151 GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.host, "localhost"));
152 GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo/bar"));
153
154 grpc_op* op;
155 grpc_op ops[6];
156 // Send the initial metadata and the status from the server.
157 memset(ops, 0, sizeof(ops));
158 op = ops;
159 op->op = GRPC_OP_SEND_INITIAL_METADATA;
160 op->data.send_initial_metadata.count = 0;
161 op->flags = 0;
162 op->reserved = nullptr;
163 op++;
164 op->op = GRPC_OP_RECV_CLOSE_ON_SERVER;
165 op->data.recv_close_on_server.cancelled = &was_cancelled;
166 op->flags = 0;
167 op->reserved = nullptr;
168 op++;
169 op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
170 op->data.send_status_from_server.trailing_metadata_count = 0;
171 op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED;
172 grpc_slice status_details = grpc_slice_from_static_string("xyz");
173 op->data.send_status_from_server.status_details = &status_details;
174 op->flags = 0;
175 op->reserved = nullptr;
176 op++;
177 error = grpc_call_start_batch(s, ops, static_cast<size_t>(op - ops),
178 grpc_core::CqVerifier::tag(103), nullptr);
179 GPR_ASSERT(GRPC_CALL_OK == error);
180
181 cqv.Expect(grpc_core::CqVerifier::tag(103), true);
182 cqv.Verify();
183
184 // If the call had an error, `was_cancelled` would be 1.
185 // GPR_ASSERT(was_cancelled == 1);
186
187 grpc_metadata_array_destroy(&request_metadata_recv);
188 grpc_call_details_destroy(&call_details);
189 grpc_call_unref(s);
190 }
191
failure_verifier(grpc_server * server,grpc_completion_queue * cq,void *)192 static void failure_verifier(grpc_server* server, grpc_completion_queue* cq,
193 void* /*registered_method*/) {
194 while (grpc_core::Server::FromC(server)->HasOpenConnections()) {
195 GPR_ASSERT(grpc_completion_queue_next(
196 cq, grpc_timeout_milliseconds_to_deadline(20), nullptr)
197 .type == GRPC_QUEUE_TIMEOUT);
198 }
199 }
200
main(int argc,char ** argv)201 int main(int argc, char** argv) {
202 grpc::testing::TestEnvironment env(&argc, argv);
203 grpc_init();
204
205 // basic request: check that things are working
206 GRPC_RUN_BAD_CLIENT_TEST(verifier, nullptr, PFX_STR, 0);
207 GRPC_RUN_BAD_CLIENT_TEST(verifier, nullptr, PFX_STR_UNUSUAL, 0);
208 GRPC_RUN_BAD_CLIENT_TEST(verifier, nullptr, PFX_STR_UNUSUAL2, 0);
209
210 // A basic request with a "content-type: text/html" header. The spec is
211 // not clear on what the behavior should be here, so to avoid breaking anyone,
212 // we should continue to accept this header.
213 GRPC_RUN_BAD_CLIENT_TEST(VerifyRpcDoesNotGetCanceled, nullptr,
214 PFX_STR_TEXT_HTML_CONTENT_TYPE_HEADER, 0);
215
216 // push an illegal data frame
217 GRPC_RUN_BAD_CLIENT_TEST(verifier, nullptr,
218 PFX_STR
219 "\x00\x00\x05\x00\x00\x00\x00\x00\x01"
220 "\x34\x00\x00\x00\x00",
221 0);
222
223 // push a data frame with bad flags
224 GRPC_RUN_BAD_CLIENT_TEST(verifier, nullptr,
225 PFX_STR "\x00\x00\x00\x00\x02\x00\x00\x00\x01", 0);
226 // push a window update with a bad length
227 GRPC_RUN_BAD_CLIENT_TEST(failure_verifier, nullptr,
228 PFX_STR "\x00\x00\x01\x08\x00\x00\x00\x00\x01", 0);
229 // push a window update with bad flags
230 GRPC_RUN_BAD_CLIENT_TEST(failure_verifier, nullptr,
231 PFX_STR "\x00\x00\x00\x08\x10\x00\x00\x00\x01", 0);
232 // push a window update with bad data (0 is not legal window size increment)
233 GRPC_RUN_BAD_CLIENT_TEST(failure_verifier, nullptr,
234 PFX_STR
235 "\x00\x00\x04\x08\x00\x00\x00\x00\x01"
236 "\x00\x00\x00\x00",
237 0);
238 // push a short goaway
239 GRPC_RUN_BAD_CLIENT_TEST(failure_verifier, nullptr,
240 PFX_STR "\x00\x00\x04\x07\x00\x00\x00\x00\x00", 0);
241 // disconnect before sending goaway
242 GRPC_RUN_BAD_CLIENT_TEST(failure_verifier, nullptr,
243 PFX_STR "\x00\x01\x12\x07\x00\x00\x00\x00\x00",
244 GRPC_BAD_CLIENT_DISCONNECT);
245 // push a rst_stream with a bad length
246 GRPC_RUN_BAD_CLIENT_TEST(failure_verifier, nullptr,
247 PFX_STR "\x00\x00\x01\x03\x00\x00\x00\x00\x01", 0);
248 // push a rst_stream with bad flags
249 GRPC_RUN_BAD_CLIENT_TEST(failure_verifier, nullptr,
250 PFX_STR "\x00\x00\x00\x03\x10\x00\x00\x00\x01", 0);
251
252 grpc_shutdown();
253 return 0;
254 }
255