• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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