1 /*
2 * h2 - HTTP/2 protocol layer
3 *
4 * Copyright(c) 2020 Glenn Strauss gstrauss()gluelogic.com All rights reserved
5 * License: BSD 3-clause (same as lighttpd)
6 */
7 #include "first.h"
8 #include "h2.h"
9
10 #include <arpa/inet.h> /* htonl() */
11 #include <stdint.h> /* INT32_MAX INT32_MIN */
12 #include <stdlib.h>
13 #include <string.h>
14
15 #include "base.h"
16 #include "buffer.h"
17 #include "chunk.h"
18 #include "fdevent.h" /* FDEVENT_STREAM_REQUEST_BUFMIN */
19 #include "http_date.h"
20 #include "http_header.h"
21 #include "log.h"
22 #include "request.h"
23 #include "response.h" /* http_response_omit_header() */
24
25
26 /* lowercased field-names
27 * (32-byte record (power-2) and single block of memory for memory locality) */
28 static const char http_header_lc[][32] = {
29 [HTTP_HEADER_OTHER] = ""
30 ,[HTTP_HEADER_ACCEPT] = "accept"
31 ,[HTTP_HEADER_ACCEPT_ENCODING] = "accept-encoding"
32 ,[HTTP_HEADER_ACCEPT_LANGUAGE] = "accept-language"
33 ,[HTTP_HEADER_ACCEPT_RANGES] = "accept-ranges"
34 ,[HTTP_HEADER_ACCESS_CONTROL_ALLOW_ORIGIN]="access-control-allow-origin"
35 ,[HTTP_HEADER_AGE] = "age"
36 ,[HTTP_HEADER_ALLOW] = "allow"
37 ,[HTTP_HEADER_ALT_SVC] = "alt-svc"
38 ,[HTTP_HEADER_ALT_USED] = "alt-used"
39 ,[HTTP_HEADER_AUTHORIZATION] = "authorization"
40 ,[HTTP_HEADER_CACHE_CONTROL] = "cache-control"
41 ,[HTTP_HEADER_CONNECTION] = "connection"
42 ,[HTTP_HEADER_CONTENT_ENCODING] = "content-encoding"
43 ,[HTTP_HEADER_CONTENT_LENGTH] = "content-length"
44 ,[HTTP_HEADER_CONTENT_LOCATION] = "content-location"
45 ,[HTTP_HEADER_CONTENT_RANGE] = "content-range"
46 ,[HTTP_HEADER_CONTENT_SECURITY_POLICY] = "content-security-policy"
47 ,[HTTP_HEADER_CONTENT_TYPE] = "content-type"
48 ,[HTTP_HEADER_COOKIE] = "cookie"
49 ,[HTTP_HEADER_DATE] = "date"
50 ,[HTTP_HEADER_DNT] = "dnt"
51 ,[HTTP_HEADER_ETAG] = "etag"
52 ,[HTTP_HEADER_EXPECT] = "expect"
53 ,[HTTP_HEADER_EXPECT_CT] = "expect-ct"
54 ,[HTTP_HEADER_EXPIRES] = "expires"
55 ,[HTTP_HEADER_FORWARDED] = "forwarded"
56 ,[HTTP_HEADER_HOST] = "host"
57 ,[HTTP_HEADER_HTTP2_SETTINGS] = "http2-settings"
58 ,[HTTP_HEADER_IF_MATCH] = "if-match"
59 ,[HTTP_HEADER_IF_MODIFIED_SINCE] = "if-modified-since"
60 ,[HTTP_HEADER_IF_NONE_MATCH] = "if-none-match"
61 ,[HTTP_HEADER_IF_RANGE] = "if-range"
62 ,[HTTP_HEADER_IF_UNMODIFIED_SINCE] = "if-unmodified-since"
63 ,[HTTP_HEADER_LAST_MODIFIED] = "last-modified"
64 ,[HTTP_HEADER_LINK] = "link"
65 ,[HTTP_HEADER_LOCATION] = "location"
66 ,[HTTP_HEADER_ONION_LOCATION] = "onion-location"
67 ,[HTTP_HEADER_P3P] = "p3p"
68 ,[HTTP_HEADER_PRAGMA] = "pragma"
69 ,[HTTP_HEADER_RANGE] = "range"
70 ,[HTTP_HEADER_REFERER] = "referer"
71 ,[HTTP_HEADER_REFERRER_POLICY] = "referrer-policy"
72 ,[HTTP_HEADER_SERVER] = "server"
73 ,[HTTP_HEADER_SET_COOKIE] = "set-cookie"
74 ,[HTTP_HEADER_STATUS] = "status"
75 ,[HTTP_HEADER_STRICT_TRANSPORT_SECURITY] = "strict-transport-security"
76 ,[HTTP_HEADER_TE] = "te"
77 ,[HTTP_HEADER_TRANSFER_ENCODING] = "transfer-encoding"
78 ,[HTTP_HEADER_UPGRADE] = "upgrade"
79 ,[HTTP_HEADER_UPGRADE_INSECURE_REQUESTS] = "upgrade-insecure-requests"
80 ,[HTTP_HEADER_USER_AGENT] = "user-agent"
81 ,[HTTP_HEADER_VARY] = "vary"
82 ,[HTTP_HEADER_WWW_AUTHENTICATE] = "www-authenticate"
83 ,[HTTP_HEADER_X_CONTENT_TYPE_OPTIONS] = "x-content-type-options"
84 ,[HTTP_HEADER_X_FORWARDED_FOR] = "x-forwarded-for"
85 ,[HTTP_HEADER_X_FORWARDED_PROTO] = "x-forwarded-proto"
86 ,[HTTP_HEADER_X_FRAME_OPTIONS] = "x-frame-options"
87 ,[HTTP_HEADER_X_XSS_PROTECTION] = "x-xss-protection"
88 };
89
90
91 /* future optimization: could conceivably store static XXH32() hash values for
92 * field-name (e.g. for benefit of entries marked LSHPACK_HDR_UNKNOWN) to
93 * incrementally reduce cost of calculating hash values for field-name on each
94 * request where those headers are used. Might also store single element
95 * static caches for "date:" value (updated each time static buffer is updated)
96 * and for "server:" value (often global to server), keyed on r->conf.server_tag
97 * pointer addr. HTTP_HEADER_STATUS could be overloaded for ":status", since
98 * lighttpd should not send "Status:" response header (should not happen) */
99
100 static const uint8_t http_header_lshpack_idx[] = {
101 [HTTP_HEADER_OTHER] = LSHPACK_HDR_UNKNOWN
102 ,[HTTP_HEADER_ACCEPT_ENCODING] = LSHPACK_HDR_ACCEPT_ENCODING
103 ,[HTTP_HEADER_AUTHORIZATION] = LSHPACK_HDR_AUTHORIZATION
104 ,[HTTP_HEADER_CACHE_CONTROL] = LSHPACK_HDR_CACHE_CONTROL
105 ,[HTTP_HEADER_CONNECTION] = LSHPACK_HDR_UNKNOWN
106 ,[HTTP_HEADER_CONTENT_ENCODING] = LSHPACK_HDR_CONTENT_ENCODING
107 ,[HTTP_HEADER_CONTENT_LENGTH] = LSHPACK_HDR_CONTENT_LENGTH
108 ,[HTTP_HEADER_CONTENT_LOCATION] = LSHPACK_HDR_CONTENT_LOCATION
109 ,[HTTP_HEADER_CONTENT_TYPE] = LSHPACK_HDR_CONTENT_TYPE
110 ,[HTTP_HEADER_COOKIE] = LSHPACK_HDR_COOKIE
111 ,[HTTP_HEADER_DATE] = LSHPACK_HDR_DATE
112 ,[HTTP_HEADER_ETAG] = LSHPACK_HDR_ETAG
113 ,[HTTP_HEADER_EXPECT] = LSHPACK_HDR_EXPECT
114 ,[HTTP_HEADER_FORWARDED] = LSHPACK_HDR_UNKNOWN
115 ,[HTTP_HEADER_HOST] = LSHPACK_HDR_HOST
116 ,[HTTP_HEADER_IF_MODIFIED_SINCE] = LSHPACK_HDR_IF_MODIFIED_SINCE
117 ,[HTTP_HEADER_IF_NONE_MATCH] = LSHPACK_HDR_IF_NONE_MATCH
118 ,[HTTP_HEADER_LAST_MODIFIED] = LSHPACK_HDR_LAST_MODIFIED
119 ,[HTTP_HEADER_LOCATION] = LSHPACK_HDR_LOCATION
120 ,[HTTP_HEADER_RANGE] = LSHPACK_HDR_RANGE
121 ,[HTTP_HEADER_SERVER] = LSHPACK_HDR_SERVER
122 ,[HTTP_HEADER_SET_COOKIE] = LSHPACK_HDR_SET_COOKIE
123 ,[HTTP_HEADER_STATUS] = LSHPACK_HDR_UNKNOWN
124 ,[HTTP_HEADER_TRANSFER_ENCODING] = LSHPACK_HDR_TRANSFER_ENCODING
125 ,[HTTP_HEADER_UPGRADE] = LSHPACK_HDR_UNKNOWN
126 ,[HTTP_HEADER_USER_AGENT] = LSHPACK_HDR_USER_AGENT
127 ,[HTTP_HEADER_VARY] = LSHPACK_HDR_VARY
128 ,[HTTP_HEADER_X_FORWARDED_FOR] = LSHPACK_HDR_UNKNOWN
129 ,[HTTP_HEADER_X_FORWARDED_PROTO] = LSHPACK_HDR_UNKNOWN
130 ,[HTTP_HEADER_HTTP2_SETTINGS] = LSHPACK_HDR_UNKNOWN
131 ,[HTTP_HEADER_ACCEPT] = LSHPACK_HDR_ACCEPT
132 ,[HTTP_HEADER_ACCEPT_LANGUAGE] = LSHPACK_HDR_ACCEPT_LANGUAGE
133 ,[HTTP_HEADER_ACCEPT_RANGES] = LSHPACK_HDR_ACCEPT_RANGES
134 ,[HTTP_HEADER_ACCESS_CONTROL_ALLOW_ORIGIN]=LSHPACK_HDR_ACCESS_CONTROL_ALLOW_ORIGIN
135 ,[HTTP_HEADER_AGE] = LSHPACK_HDR_AGE
136 ,[HTTP_HEADER_ALLOW] = LSHPACK_HDR_ALLOW
137 ,[HTTP_HEADER_ALT_SVC] = LSHPACK_HDR_UNKNOWN
138 ,[HTTP_HEADER_ALT_USED] = LSHPACK_HDR_UNKNOWN
139 ,[HTTP_HEADER_CONTENT_RANGE] = LSHPACK_HDR_CONTENT_RANGE
140 ,[HTTP_HEADER_CONTENT_SECURITY_POLICY] = LSHPACK_HDR_UNKNOWN
141 ,[HTTP_HEADER_DNT] = LSHPACK_HDR_UNKNOWN
142 ,[HTTP_HEADER_EXPECT_CT] = LSHPACK_HDR_UNKNOWN
143 ,[HTTP_HEADER_EXPIRES] = LSHPACK_HDR_EXPIRES
144 ,[HTTP_HEADER_IF_MATCH] = LSHPACK_HDR_IF_MATCH
145 ,[HTTP_HEADER_IF_RANGE] = LSHPACK_HDR_IF_RANGE
146 ,[HTTP_HEADER_IF_UNMODIFIED_SINCE] = LSHPACK_HDR_IF_UNMODIFIED_SINCE
147 ,[HTTP_HEADER_LINK] = LSHPACK_HDR_LINK
148 ,[HTTP_HEADER_ONION_LOCATION] = LSHPACK_HDR_UNKNOWN
149 ,[HTTP_HEADER_P3P] = LSHPACK_HDR_UNKNOWN
150 ,[HTTP_HEADER_PRAGMA] = LSHPACK_HDR_UNKNOWN
151 ,[HTTP_HEADER_REFERER] = LSHPACK_HDR_REFERER
152 ,[HTTP_HEADER_REFERRER_POLICY] = LSHPACK_HDR_UNKNOWN
153 ,[HTTP_HEADER_STRICT_TRANSPORT_SECURITY] = LSHPACK_HDR_STRICT_TRANSPORT_SECURITY
154 ,[HTTP_HEADER_TE] = LSHPACK_HDR_UNKNOWN
155 ,[HTTP_HEADER_UPGRADE_INSECURE_REQUESTS] = LSHPACK_HDR_UNKNOWN
156 ,[HTTP_HEADER_WWW_AUTHENTICATE] = LSHPACK_HDR_WWW_AUTHENTICATE
157 ,[HTTP_HEADER_X_CONTENT_TYPE_OPTIONS] = LSHPACK_HDR_UNKNOWN
158 ,[HTTP_HEADER_X_FRAME_OPTIONS] = LSHPACK_HDR_UNKNOWN
159 ,[HTTP_HEADER_X_XSS_PROTECTION] = LSHPACK_HDR_UNKNOWN
160 };
161
162
163 /* Note: must be kept in sync with ls-hpack/lshpack.h:lshpack_static_hdr_idx[]*/
164 static const int8_t lshpack_idx_http_header[] = {
165 [LSHPACK_HDR_UNKNOWN] = HTTP_HEADER_H2_UNKNOWN
166 ,[LSHPACK_HDR_AUTHORITY] = HTTP_HEADER_H2_AUTHORITY
167 ,[LSHPACK_HDR_METHOD_GET] = HTTP_HEADER_H2_METHOD_GET
168 ,[LSHPACK_HDR_METHOD_POST] = HTTP_HEADER_H2_METHOD_POST
169 ,[LSHPACK_HDR_PATH] = HTTP_HEADER_H2_PATH
170 ,[LSHPACK_HDR_PATH_INDEX_HTML] = HTTP_HEADER_H2_PATH_INDEX_HTML
171 ,[LSHPACK_HDR_SCHEME_HTTP] = HTTP_HEADER_H2_SCHEME_HTTP
172 ,[LSHPACK_HDR_SCHEME_HTTPS] = HTTP_HEADER_H2_SCHEME_HTTPS
173 ,[LSHPACK_HDR_STATUS_200] = HTTP_HEADER_H2_UNKNOWN
174 ,[LSHPACK_HDR_STATUS_204] = HTTP_HEADER_H2_UNKNOWN
175 ,[LSHPACK_HDR_STATUS_206] = HTTP_HEADER_H2_UNKNOWN
176 ,[LSHPACK_HDR_STATUS_304] = HTTP_HEADER_H2_UNKNOWN
177 ,[LSHPACK_HDR_STATUS_400] = HTTP_HEADER_H2_UNKNOWN
178 ,[LSHPACK_HDR_STATUS_404] = HTTP_HEADER_H2_UNKNOWN
179 ,[LSHPACK_HDR_STATUS_500] = HTTP_HEADER_H2_UNKNOWN
180 ,[LSHPACK_HDR_ACCEPT_CHARSET] = HTTP_HEADER_OTHER
181 ,[LSHPACK_HDR_ACCEPT_ENCODING] = HTTP_HEADER_ACCEPT_ENCODING
182 ,[LSHPACK_HDR_ACCEPT_LANGUAGE] = HTTP_HEADER_ACCEPT_LANGUAGE
183 ,[LSHPACK_HDR_ACCEPT_RANGES] = HTTP_HEADER_ACCEPT_RANGES
184 ,[LSHPACK_HDR_ACCEPT] = HTTP_HEADER_ACCEPT
185 ,[LSHPACK_HDR_ACCESS_CONTROL_ALLOW_ORIGIN]=HTTP_HEADER_ACCESS_CONTROL_ALLOW_ORIGIN
186 ,[LSHPACK_HDR_AGE] = HTTP_HEADER_AGE
187 ,[LSHPACK_HDR_ALLOW] = HTTP_HEADER_ALLOW
188 ,[LSHPACK_HDR_AUTHORIZATION] = HTTP_HEADER_AUTHORIZATION
189 ,[LSHPACK_HDR_CACHE_CONTROL] = HTTP_HEADER_CACHE_CONTROL
190 ,[LSHPACK_HDR_CONTENT_DISPOSITION] = HTTP_HEADER_OTHER
191 ,[LSHPACK_HDR_CONTENT_ENCODING] = HTTP_HEADER_CONTENT_ENCODING
192 ,[LSHPACK_HDR_CONTENT_LANGUAGE] = HTTP_HEADER_OTHER
193 ,[LSHPACK_HDR_CONTENT_LENGTH] = HTTP_HEADER_CONTENT_LENGTH
194 ,[LSHPACK_HDR_CONTENT_LOCATION] = HTTP_HEADER_CONTENT_LOCATION
195 ,[LSHPACK_HDR_CONTENT_RANGE] = HTTP_HEADER_CONTENT_RANGE
196 ,[LSHPACK_HDR_CONTENT_TYPE] = HTTP_HEADER_CONTENT_TYPE
197 ,[LSHPACK_HDR_COOKIE] = HTTP_HEADER_COOKIE
198 ,[LSHPACK_HDR_DATE] = HTTP_HEADER_DATE
199 ,[LSHPACK_HDR_ETAG] = HTTP_HEADER_ETAG
200 ,[LSHPACK_HDR_EXPECT] = HTTP_HEADER_EXPECT
201 ,[LSHPACK_HDR_EXPIRES] = HTTP_HEADER_EXPIRES
202 ,[LSHPACK_HDR_FROM] = HTTP_HEADER_OTHER
203 ,[LSHPACK_HDR_HOST] = HTTP_HEADER_HOST
204 ,[LSHPACK_HDR_IF_MATCH] = HTTP_HEADER_IF_MATCH
205 ,[LSHPACK_HDR_IF_MODIFIED_SINCE] = HTTP_HEADER_IF_MODIFIED_SINCE
206 ,[LSHPACK_HDR_IF_NONE_MATCH] = HTTP_HEADER_IF_NONE_MATCH
207 ,[LSHPACK_HDR_IF_RANGE] = HTTP_HEADER_IF_RANGE
208 ,[LSHPACK_HDR_IF_UNMODIFIED_SINCE] = HTTP_HEADER_IF_UNMODIFIED_SINCE
209 ,[LSHPACK_HDR_LAST_MODIFIED] = HTTP_HEADER_LAST_MODIFIED
210 ,[LSHPACK_HDR_LINK] = HTTP_HEADER_LINK
211 ,[LSHPACK_HDR_LOCATION] = HTTP_HEADER_LOCATION
212 ,[LSHPACK_HDR_MAX_FORWARDS] = HTTP_HEADER_OTHER
213 ,[LSHPACK_HDR_PROXY_AUTHENTICATE] = HTTP_HEADER_OTHER
214 ,[LSHPACK_HDR_PROXY_AUTHORIZATION] = HTTP_HEADER_OTHER
215 ,[LSHPACK_HDR_RANGE] = HTTP_HEADER_RANGE
216 ,[LSHPACK_HDR_REFERER] = HTTP_HEADER_REFERER
217 ,[LSHPACK_HDR_REFRESH] = HTTP_HEADER_OTHER
218 ,[LSHPACK_HDR_RETRY_AFTER] = HTTP_HEADER_OTHER
219 ,[LSHPACK_HDR_SERVER] = HTTP_HEADER_SERVER
220 ,[LSHPACK_HDR_SET_COOKIE] = HTTP_HEADER_SET_COOKIE
221 ,[LSHPACK_HDR_STRICT_TRANSPORT_SECURITY] = HTTP_HEADER_STRICT_TRANSPORT_SECURITY
222 ,[LSHPACK_HDR_TRANSFER_ENCODING] = HTTP_HEADER_TRANSFER_ENCODING
223 ,[LSHPACK_HDR_USER_AGENT] = HTTP_HEADER_USER_AGENT
224 ,[LSHPACK_HDR_VARY] = HTTP_HEADER_VARY
225 ,[LSHPACK_HDR_VIA] = HTTP_HEADER_OTHER
226 ,[LSHPACK_HDR_WWW_AUTHENTICATE] = HTTP_HEADER_WWW_AUTHENTICATE
227 };
228
229
230 static request_st * h2_init_stream (request_st * const h2r, connection * const con);
231
232
233 __attribute_pure__
234 static inline uint32_t
h2_u32(const uint8_t * const s)235 h2_u32 (const uint8_t * const s)
236 {
237 return ((uint32_t)s[0] << 24)
238 | ((uint32_t)s[1] << 16)
239 | ((uint32_t)s[2] << 8)
240 | (uint32_t)s[3];
241 }
242
243
244 __attribute_pure__
245 static inline uint32_t
h2_u31(const uint8_t * const s)246 h2_u31 (const uint8_t * const s)
247 {
248 return h2_u32(s) & ~0x80000000u;
249 }
250
251
252 __attribute_pure__
253 static inline uint32_t
h2_u24(const uint8_t * const s)254 h2_u24 (const uint8_t * const s)
255 {
256 #if 1
257 /* XXX: optimization is valid only for how this is used in h2.c
258 * where we have checked that frame header received is at least
259 * 9 chars, and where s containing frame length (3-bytes) is
260 * followed by at least 1 additional char. */
261 return h2_u32(s) >> 8;
262 #else
263 return ((uint32_t)s[0] << 16)
264 | ((uint32_t)s[1] << 8)
265 | (uint32_t)s[2];
266 #endif
267 }
268
269
270 __attribute_pure__
271 static inline uint16_t
h2_u16(const uint8_t * const s)272 h2_u16 (const uint8_t * const s)
273 {
274 return ((uint16_t)s[0] << 8)
275 | (uint16_t)s[1];
276 }
277
278
279 static void
h2_send_settings_ack(connection * const con)280 h2_send_settings_ack (connection * const con)
281 {
282 static const uint8_t settings_ack[] = {
283 /* SETTINGS w/ ACK */
284 0x00, 0x00, 0x00 /* frame length */
285 ,H2_FTYPE_SETTINGS /* frame type */
286 ,H2_FLAG_ACK /* frame flags */
287 ,0x00, 0x00, 0x00, 0x00 /* stream identifier */
288 };
289
290 chunkqueue_append_mem(con->write_queue,
291 (const char *)settings_ack, sizeof(settings_ack));
292 }
293
294
295 __attribute_cold__
296 static void
h2_send_rst_stream_id(uint32_t h2id,connection * const con,const request_h2error_t e)297 h2_send_rst_stream_id (uint32_t h2id, connection * const con, const request_h2error_t e)
298 {
299 union {
300 uint8_t c[16];
301 uint32_t u[4]; /*(alignment)*/
302 } rst_stream = { { /*(big-endian numbers)*/
303 0x00, 0x00, 0x00 /* padding for alignment; do not send */
304 /* RST_STREAM */
305 ,0x00, 0x00, 0x04 /* frame length */
306 ,H2_FTYPE_RST_STREAM /* frame type */
307 ,0x00 /* frame flags */
308 ,0x00, 0x00, 0x00, 0x00 /* stream identifier (fill in below) */
309 ,0x00, 0x00, 0x00, 0x00 /* error code; (fill in below) */
310 } };
311
312 rst_stream.u[2] = htonl(h2id);
313 rst_stream.u[3] = htonl(e);
314 chunkqueue_append_mem(con->write_queue, /*(+3 to skip over align padding)*/
315 (const char *)rst_stream.c+3, sizeof(rst_stream)-3);
316 }
317
318
319 __attribute_cold__
320 static void
h2_send_rst_stream_state(request_st * const r,h2con * const h2c)321 h2_send_rst_stream_state (request_st * const r, h2con * const h2c)
322 {
323 if (r->h2state != H2_STATE_HALF_CLOSED_REMOTE
324 && r->h2state != H2_STATE_CLOSED) {
325 /* set timestamp for comparison; not tracking individual stream ids */
326 h2c->half_closed_ts = log_monotonic_secs;
327 }
328 r->state = CON_STATE_ERROR;
329 r->h2state = H2_STATE_CLOSED;
330 }
331
332
333 __attribute_cold__
334 static void
h2_send_rst_stream(request_st * const r,connection * const con,const request_h2error_t e)335 h2_send_rst_stream (request_st * const r, connection * const con, const request_h2error_t e)
336 {
337 h2_send_rst_stream_state(r, con->h2);/*(sets r->h2state = H2_STATE_CLOSED)*/
338 h2_send_rst_stream_id(r->h2id, con, e);
339 }
340
341
342 __attribute_cold__
343 static void
h2_send_goaway_rst_stream(connection * const con)344 h2_send_goaway_rst_stream (connection * const con)
345 {
346 h2con * const h2c = con->h2;
347 const int sent_goaway = h2c->sent_goaway;
348 for (uint32_t i = 0, rused = h2c->rused; i < rused; ++i) {
349 request_st * const r = h2c->r[i];
350 if (r->h2state == H2_STATE_CLOSED) continue;
351 h2_send_rst_stream_state(r, h2c);/*(sets r->h2state = H2_STATE_CLOSED)*/
352 /*(XXX: might consider always sending RST_STREAM)*/
353 if (sent_goaway)
354 h2_send_rst_stream_id(r->h2id, con, H2_E_PROTOCOL_ERROR);
355 }
356 }
357
358
359 void
h2_send_goaway(connection * const con,const request_h2error_t e)360 h2_send_goaway (connection * const con, const request_h2error_t e)
361 {
362 /* future: RFC 7540 Section 6.8 notes that server initiating graceful
363 * connection shutdown SHOULD send GOAWAY with stream id 2^31-1 and a
364 * NO_ERROR code, and later send another GOAWAY with an updated last
365 * stream identifier. (This is not done here, but doing so would be
366 * friendlier to clients that send streaming requests which the client
367 * is unable to retry.) */
368
369 if (e != H2_E_NO_ERROR)
370 h2_send_goaway_rst_stream(con);
371 /*XXX: else should send RST_STREAM w/ CANCEL for any active PUSH_PROMISE */
372
373 h2con * const h2c = con->h2;
374 if (h2c->sent_goaway && (h2c->sent_goaway > 0 || e == H2_E_NO_ERROR))
375 return;
376 h2c->sent_goaway = (e == H2_E_NO_ERROR) ? -1 : (int32_t)e;
377
378 union {
379 uint8_t c[20];
380 uint32_t u[5]; /*(alignment)*/
381 } goaway = { { /*(big-endian numbers)*/
382 0x00, 0x00, 0x00 /* padding for alignment; do not send */
383 /* GOAWAY */
384 ,0x00, 0x00, 0x08 /* frame length */
385 ,H2_FTYPE_GOAWAY /* frame type */
386 ,0x00 /* frame flags */
387 ,0x00, 0x00, 0x00, 0x00 /* stream identifier */
388 ,0x00, 0x00, 0x00, 0x00 /* last-stream-id (fill in below) */
389 ,0x00, 0x00, 0x00, 0x00 /* error code (fill in below) */
390 /* additional debug data (*); (optional)
391 * adjust frame length if any additional
392 * debug data is sent */
393 } };
394
395 goaway.u[3] = htonl(h2c->h2_cid); /* last-stream-id */
396 goaway.u[4] = htonl(e);
397 chunkqueue_append_mem(con->write_queue, /*(+3 to skip over align padding)*/
398 (const char *)goaway.c+3, sizeof(goaway)-3);
399 }
400
401
402 __attribute_cold__
403 static void
h2_send_goaway_e(connection * const con,const request_h2error_t e)404 h2_send_goaway_e (connection * const con, const request_h2error_t e)
405 {
406 h2_send_goaway(con, e);
407 }
408
409
410 __attribute_cold__
411 static int
h2_send_refused_stream(uint32_t h2id,connection * const con)412 h2_send_refused_stream (uint32_t h2id, connection * const con)
413 {
414 h2con * const h2c = con->h2;
415
416 if (h2c->sent_settings) { /*(see h2_recv_settings() comments)*/
417 /* client connected and immediately sent flurry of request streams
418 * (h2c->sent_settings is non-zero if sent SETTINGS frame to
419 * client and have not yet received SETTINGS ACK from client)
420 * lighttpd sends SETTINGS_MAX_CONCURRENT_STREAMS <limit> with
421 * server Connection Preface, so a well-behaved client will
422 * adjust after it sends its initial requests.
423 * (e.g. h2load -n 100 -m 100 sends 100 requests upon connect)
424 *
425 * Check if active streams have pending request body. If all active
426 * streams have pending request body, then must refuse new stream as
427 * progress might be blocked if active streams all wait for DATA. */
428 for (uint32_t i = 0, rused = h2c->rused; i < rused; ++i) {
429 const request_st * const r = h2c->r[i];
430 if (r->reqbody_length == r->reqbody_queue.bytes_in) {
431 /* no pending request body; at least this request may proceed,
432 * though others waiting for request body may block until new
433 * request streams become active if new request streams precede
434 * DATA frames for active streams
435 *
436 * alternative to sending refused stream:
437 * stop processing frames and defer processing this HEADERS
438 * frame until num active streams drops below limit. */
439 return -1;
440 }
441 }
442 }
443
444 /* too many active streams; refuse new stream */
445 h2c->h2_cid = h2id;
446 h2_send_rst_stream_id(h2id, con, H2_E_REFUSED_STREAM);
447 return 1;
448 }
449
450
451 static int
h2_recv_goaway(connection * const con,const uint8_t * const s,uint32_t len)452 h2_recv_goaway (connection * const con, const uint8_t * const s, uint32_t len)
453 {
454 /*(s must be entire GOAWAY frame and len the frame length field)*/
455 /*assert(s[3] == H2_FTYPE_GOAWAY);*/
456 UNUSED(len);
457 if (0 != h2_u31(s+5)) { /*(GOAWAY stream id must be 0)*/
458 h2_send_goaway_e(con, H2_E_PROTOCOL_ERROR);
459 return 0;
460 }
461 const uint32_t e = h2_u32(s+13);
462 #if 0
463 /* XXX: debug: could log error code sent by peer */
464 #endif
465 #if 0
466 /* XXX: debug: could log additional debug info (if any) sent by peer */
467 if (len > 8) {
468 }
469 #endif
470 #if 0
471 /* XXX: could validate/use Last-Stream-ID sent by peer */
472 const uint32_t last_id = h2_u31(s+9);
473 #endif
474
475 /* send PROTOCOL_ERROR back to peer if peer sent an error code
476 * (i.e. not NO_ERROR) in order to terminate connection more quickly */
477 h2_send_goaway(con, e==H2_E_NO_ERROR ? H2_E_NO_ERROR : H2_E_PROTOCOL_ERROR);
478 h2con * const h2c = con->h2;
479 if (0 == h2c->rused) return 0;
480 return 1;
481 }
482
483
484 static void
h2_recv_rst_stream(connection * const con,const uint8_t * const s,const uint32_t len)485 h2_recv_rst_stream (connection * const con, const uint8_t * const s, const uint32_t len)
486 {
487 /*(s must be entire RST_STREAM frame and len the frame length field)*/
488 /*assert(s[3] == H2_FTYPE_RST_STREAM);*/
489 if (4 != len) { /*(RST_STREAM frame length must be 4)*/
490 h2_send_goaway_e(con, H2_E_FRAME_SIZE_ERROR);
491 return;
492 }
493 const uint32_t id = h2_u31(s+5);
494 if (0 == id) { /*(RST_STREAM id must not be 0)*/
495 h2_send_goaway_e(con, H2_E_PROTOCOL_ERROR);
496 return;
497 }
498 h2con * const h2c = con->h2;
499 for (uint32_t i = 0, rused = h2c->rused; i < rused; ++i) {
500 request_st * const r = h2c->r[i];
501 if (r->h2id != id) continue;
502 if (r->h2state == H2_STATE_IDLE) {
503 /*(RST_STREAM must not be for stream in "idle" state)*/
504 h2_send_goaway_e(con, H2_E_PROTOCOL_ERROR);
505 return;
506 }
507 /* XXX: ? add debug trace including error code from RST_STREAM ? */
508 r->state = CON_STATE_ERROR;
509 r->h2state = H2_STATE_CLOSED;
510 return;
511 }
512 /* unknown/inactive stream id
513 * XXX: how should we handle RST_STREAM for unknown/inactive stream id?
514 * (stream id may have been closed recently and server forgot about it,
515 * but client (peer) sent RST_STREAM prior to receiving stream end from
516 * server)*/
517 #if 0
518 if (h2c->sent_goaway && h2c->h2_cid < id) return;
519 h2_send_goaway_e(con, H2_E_PROTOCOL_ERROR);
520 #else
521 if (h2c->h2_cid < id) {
522 h2_send_goaway_e(con, H2_E_PROTOCOL_ERROR);
523 return;
524 }
525 #endif
526 }
527
528
529 static void
h2_recv_ping(connection * const con,uint8_t * const s,const uint32_t len)530 h2_recv_ping (connection * const con, uint8_t * const s, const uint32_t len)
531 {
532 #if 0
533 union {
534 uint8_t c[20];
535 uint32_t u[5]; /*(alignment)*/
536 } ping = { { /*(big-endian numbers)*/
537 0x00, 0x00, 0x00 /* padding for alignment; do not send */
538 /* PING */
539 ,0x00, 0x00, 0x08 /* frame length */
540 ,H2_FTYPE_PING /* frame type */
541 ,H2_FLAG_ACK /* frame flags */
542 ,0x00, 0x00, 0x00, 0x00 /* stream identifier */
543 ,0x00, 0x00, 0x00, 0x00 /* opaque (fill in below) */
544 ,0x00, 0x00, 0x00, 0x00
545 } };
546 #endif
547
548 /*(s must be entire PING frame and len the frame length field)*/
549 /*assert(s[3] == H2_FTYPE_PING);*/
550 if (8 != len) { /*(PING frame length must be 8)*/
551 h2_send_goaway_e(con, H2_E_FRAME_SIZE_ERROR);
552 return;
553 }
554 s[5] &= ~0x80; /* reserved bit must be ignored */
555 if (0 != h2_u31(s+5)) { /*(PING stream id must be 0)*/
556 h2_send_goaway_e(con, H2_E_PROTOCOL_ERROR);
557 return;
558 }
559 if (s[4] & H2_FLAG_ACK) /*(ignore; unexpected if we did not send PING)*/
560 return;
561 /* reflect PING back to peer with frame flag ACK */
562 /* (9 byte frame header plus 8 byte PING payload = 17 bytes)*/
563 s[4] = H2_FLAG_ACK;
564 chunkqueue_append_mem(con->write_queue, (const char *)s, 17);
565 }
566
567
568 static void
h2_recv_priority(connection * const con,const uint8_t * const s,const uint32_t len)569 h2_recv_priority (connection * const con, const uint8_t * const s, const uint32_t len)
570 {
571 /*(s must be entire PRIORITY frame and len the frame length field)*/
572 /*assert(s[3] == H2_FTYPE_PRIORITY);*/
573 if (5 != len) { /*(PRIORITY frame length must be 5)*/
574 h2_send_goaway_e(con, H2_E_FRAME_SIZE_ERROR);
575 return;
576 }
577 const uint32_t id = h2_u31(s+5);
578 if (0 == id) { /*(PRIORITY id must not be 0)*/
579 h2_send_goaway_e(con, H2_E_PROTOCOL_ERROR);
580 return;
581 }
582 const uint32_t prio = h2_u31(s+9);
583 #if 0
584 uint32_t exclusive_dependency = (s[9] & 0x80) ? 1 : 0;
585 uint32_t weight = s[13];
586 #endif
587 h2con * const h2c = con->h2;
588 for (uint32_t i = 0, rused = h2c->rused; i < rused; ++i) {
589 request_st * const r = h2c->r[i];
590 if (r->h2id != id) continue;
591 /* XXX: TODO: update priority info */
592 if (prio == id) {
593 h2_send_rst_stream(r, con, H2_E_PROTOCOL_ERROR);
594 return;
595 }
596 return;
597 }
598 /* XXX: TODO: update priority info for unknown/inactive stream */
599 /*if (h2c->sent_goaway && h2c->h2_cid < id) return;*/
600 if (prio == id) {
601 h2_send_rst_stream_id(id, con, H2_E_PROTOCOL_ERROR);
602 return;
603 }
604 }
605
606
607 static void
h2_recv_window_update(connection * const con,const uint8_t * const s,const uint32_t len)608 h2_recv_window_update (connection * const con, const uint8_t * const s, const uint32_t len)
609 {
610 /*(s must be entire WINDOW_UPDATE frame and len the frame length field)*/
611 /*assert(s[3] == H2_FTYPE_WINDOW_UPDATE);*/
612 if (4 != len) { /*(WINDOW_UPDATE frame length must be 4)*/
613 h2_send_goaway_e(con, H2_E_FRAME_SIZE_ERROR);
614 return;
615 }
616 const uint32_t id = h2_u31(s+5);
617 const int32_t v = (int32_t)h2_u31(s+9);
618 request_st *r = NULL;
619 if (0 == id)
620 r = &con->request;
621 else {
622 h2con * const h2c = con->h2;
623 for (uint32_t i = 0, rused = h2c->rused; i < rused; ++i) {
624 request_st * const rr = h2c->r[i];
625 if (rr->h2id != id) continue;
626 r = rr;
627 break;
628 }
629 /* peer should not send WINDOW_UPDATE for an inactive stream,
630 * but RFC 7540 does not explicitly call this out. On the other hand,
631 * since there may be a temporary mismatch in stream state between
632 * peers, ignore window update if stream id is unknown/inactive.
633 * Also, it is not an error if GOAWAY sent and h2c->h2_cid < id */
634 if (NULL == r) {
635 if (h2c->h2_cid < id && 0 == h2c->sent_goaway)
636 h2_send_goaway_e(con, H2_E_PROTOCOL_ERROR);
637 #if 0
638 /*(needed for h2spec if testing with response < 16k+1 over TLS
639 * or response <= socket send buffer size over cleartext, due to
640 * completing response too quickly for the test frame sequence) */
641 if (v == 0) /* h2spec: 6.9-2 (after we retired id 1) */
642 h2_send_rst_stream_id(id, con, H2_E_PROTOCOL_ERROR);
643 if (v == INT32_MAX)/* h2spec: 6.9.1-3 (after we retired id 1) */
644 h2_send_rst_stream_id(id, con, H2_E_FLOW_CONTROL_ERROR);
645 #endif
646 return;
647 }
648 /* MUST NOT be treated as error if stream is in closed state; ignore */
649 if (r->h2state == H2_STATE_CLOSED
650 || r->h2state == H2_STATE_HALF_CLOSED_LOCAL) return;
651 }
652 if (0 == v || r->h2_swin > INT32_MAX - v) {
653 request_h2error_t e = (0 == v)
654 ? H2_E_PROTOCOL_ERROR
655 : H2_E_FLOW_CONTROL_ERROR;
656 if (0 == id)
657 h2_send_goaway_e(con, e);
658 else
659 h2_send_rst_stream(r, con, e);
660 return;
661 }
662 r->h2_swin += v;
663 }
664
665
666 __attribute_noinline__
667 static void
h2_send_window_update(connection * const con,uint32_t h2id,const uint32_t len)668 h2_send_window_update (connection * const con, uint32_t h2id, const uint32_t len)
669 {
670 if (0 == len) return;
671 union {
672 uint8_t c[16];
673 uint32_t u[4]; /*(alignment)*/
674 } window_upd = { { /*(big-endian numbers)*/
675 0x00, 0x00, 0x00 /* padding for alignment; do not send */
676 /* WINDOW_UPDATE */
677 ,0x00, 0x00, 0x04 /* frame length */
678 ,H2_FTYPE_WINDOW_UPDATE /* frame type */
679 ,0x00 /* frame flags */
680 ,0x00, 0x00, 0x00, 0x00 /* stream identifier (fill in below) */
681 ,0x00, 0x00, 0x00, 0x00 /* window update increase (fill in below) */
682 } };
683
684 window_upd.u[2] = htonl(h2id);
685 window_upd.u[3] = htonl(len);
686 chunkqueue_append_mem(con->write_queue, /*(+3 to skip over align padding)*/
687 (const char *)window_upd.c+3, sizeof(window_upd)-3);
688 }
689
690
691 static void
h2_parse_frame_settings(connection * const con,const uint8_t * s,uint32_t len)692 h2_parse_frame_settings (connection * const con, const uint8_t *s, uint32_t len)
693 {
694 /*(s and len must be SETTINGS frame payload)*/
695 /*(caller must validate frame len, frame type == 0x04, frame id == 0)*/
696 h2con * const h2c = con->h2;
697 for (; len >= 6; len -= 6, s += 6) {
698 uint32_t v = h2_u32(s+2);
699 switch (h2_u16(s)) {
700 case H2_SETTINGS_HEADER_TABLE_SIZE:
701 /* encoder may use any table size <= value sent by peer */
702 /* For simple compliance with RFC and constrained memory use,
703 * choose to not increase table size beyond the default 4096,
704 * but allow smaller sizes to be set and then reset up to 4096,
705 * e.g. set to 0 to evict all dynamic table entries,
706 * and then set to 4096 to restore dynamic table use */
707 if (v > 4096) v = 4096;
708 if (v == h2c->s_header_table_size) break;
709 h2c->s_header_table_size = v;
710 lshpack_enc_set_max_capacity(&h2c->encoder, v);
711 break;
712 case H2_SETTINGS_ENABLE_PUSH:
713 if ((v|1) != 1) { /*(v == 0 || v == 1)*/
714 h2_send_goaway_e(con, H2_E_PROTOCOL_ERROR);
715 return;
716 }
717 h2c->s_enable_push = v;
718 break;
719 case H2_SETTINGS_MAX_CONCURRENT_STREAMS:
720 h2c->s_max_concurrent_streams = v;
721 break;
722 case H2_SETTINGS_INITIAL_WINDOW_SIZE:
723 if (v > INT32_MAX) { /*(2^31 - 1)*/
724 h2_send_goaway_e(con, H2_E_FLOW_CONTROL_ERROR);
725 return;
726 }
727 else if (h2c->rused) { /*(update existing streams)*/
728 /*(underflow is ok; unsigned integer math)*/
729 /*(h2c->s_initial_window_size is >= 0)*/
730 int32_t diff =
731 (int32_t)((uint32_t)v - (uint32_t)h2c->s_initial_window_size);
732 for (uint32_t i = 0, rused = h2c->rused; i < rused; ++i) {
733 request_st * const r = h2c->r[i];
734 const int32_t swin = r->h2_swin;
735 if (r->h2state == H2_STATE_HALF_CLOSED_LOCAL
736 || r->h2state == H2_STATE_CLOSED) continue;
737 if (diff >= 0
738 ? swin > INT32_MAX - diff
739 : swin < INT32_MIN - diff) {
740 h2_send_rst_stream(r, con, H2_E_FLOW_CONTROL_ERROR);
741 continue;
742 }
743 r->h2_swin += diff;
744 }
745 }
746 h2c->s_initial_window_size = (int32_t)v;
747 break;
748 case H2_SETTINGS_MAX_FRAME_SIZE:
749 if (v < 16384 || v > 16777215) { /*[(2^14),(2^24-1)]*/
750 h2_send_goaway_e(con, H2_E_PROTOCOL_ERROR);
751 return;
752 }
753 h2c->s_max_frame_size = v;
754 break;
755 case H2_SETTINGS_MAX_HEADER_LIST_SIZE:
756 h2c->s_max_header_list_size = v;
757 break;
758 default:
759 break;
760 }
761 }
762
763 if (len) {
764 h2_send_goaway_e(con, H2_E_FRAME_SIZE_ERROR);
765 return;
766 }
767
768 /* caller must send SETTINGS frame with ACK flag,
769 * if appropriate, and if h2c->sent_goaway is not set
770 * (Do not send ACK for Upgrade: h2c and HTTP2-Settings header) */
771 }
772
773
774 static void
h2_recv_settings(connection * const con,const uint8_t * const s,const uint32_t len)775 h2_recv_settings (connection * const con, const uint8_t * const s, const uint32_t len)
776 {
777 /*(s must be entire SETTINGS frame, len must be the frame length field)*/
778 /*assert(s[3] == H2_FTYPE_SETTINGS);*/
779 if (0 != h2_u31(s+5)) {/*(SETTINGS stream id must be 0)*/
780 h2_send_goaway_e(con, H2_E_PROTOCOL_ERROR);
781 return;
782 }
783
784 h2con * const h2c = con->h2;
785 if (!(s[4] & H2_FLAG_ACK)) {
786 h2_parse_frame_settings(con, s+9, len);
787 if (h2c->sent_goaway <= 0)
788 h2_send_settings_ack(con);
789 }
790 else {
791 /* lighttpd currently sends SETTINGS in server preface, and not again,
792 * so this does not have to handle another SETTINGS frame being sent
793 * before receiving an ACK from prior SETTINGS frame. (If it does,
794 * then we will need some sort of counter.) */
795 if (0 != len)
796 h2_send_goaway_e(con, H2_E_FRAME_SIZE_ERROR);
797 else if (h2c->sent_settings)
798 h2c->sent_settings = 0;
799 else /* SETTINGS with ACK for SETTINGS frame we did not send */
800 h2_send_goaway_e(con, H2_E_PROTOCOL_ERROR);
801 }
802 }
803
804
805 static int
h2_recv_end_data(request_st * const r,connection * const con,const uint32_t alen)806 h2_recv_end_data (request_st * const r, connection * const con, const uint32_t alen)
807 {
808 chunkqueue * const reqbody_queue = &r->reqbody_queue;
809 r->h2state = (r->h2state == H2_STATE_OPEN)
810 ? H2_STATE_HALF_CLOSED_REMOTE
811 : H2_STATE_CLOSED;
812 if (r->reqbody_length == -1)
813 r->reqbody_length = reqbody_queue->bytes_in + (off_t)alen;
814 else if (r->reqbody_length != reqbody_queue->bytes_in + (off_t)alen) {
815 if (0 == reqbody_queue->bytes_out) {
816 h2_send_rst_stream(r, con, H2_E_PROTOCOL_ERROR);
817 return 0;
818 } /* else let reqbody streaming consumer handle truncated reqbody */
819 }
820
821 return 1;
822 }
823
824
825 static int
h2_recv_data(connection * const con,const uint8_t * const s,const uint32_t len)826 h2_recv_data (connection * const con, const uint8_t * const s, const uint32_t len)
827 {
828 /*(s must be entire DATA frame, len must be the frame length field)*/
829 /*assert(s[3] == H2_FTYPE_DATA);*/
830
831 /* future: consider string refs rather than copying DATA from chunkqueue
832 * or try to consume entire chunk, or to split chunks with less copying */
833
834 h2con * const h2c = con->h2;
835 const uint32_t id = h2_u31(s+5);
836 if (0 == id || h2c->h2_cid < id) { /*(RST_STREAM id must not be 0)*/
837 h2_send_goaway_e(con, H2_E_PROTOCOL_ERROR);
838 return 0;
839 }
840
841 uint32_t alen = len; /* actual data len, minus padding */
842 uint32_t pad = 0;
843 if (s[4] & H2_FLAG_PADDED) {
844 pad = s[9];
845 if (pad >= len) {
846 h2_send_goaway_e(con, H2_E_PROTOCOL_ERROR);
847 return 0;
848 }
849 alen -= (1 + pad);
850 }
851
852 request_st * const h2r = &con->request;
853 if (h2r->h2_rwin <= 0 && 0 != alen) { /*(always proceed if 0 == alen)*/
854 /*(connection_state_machine_h2() must ensure con is rescheduled,
855 * when backends consume data if con->read_queue is not empty,
856 * whether or not con->fd has data to read from the network)*/
857 /*(leave frame in cq to be re-read later)*/
858 return 0;
859 }
860 /*(allow h2r->h2_rwin to dip below 0 so that entire frame is processed)*/
861 /*(not worried about underflow while
862 * SETTINGS_MAX_FRAME_SIZE is small (e.g. 16k or 32k) and
863 * SETTINGS_MAX_CONCURRENT_STREAMS is small (h2c->r[8]))*/
864 /*h2r->h2_rwin -= (int32_t)len;*//* update connection recv window (below) */
865
866 request_st *r = NULL;
867 for (uint32_t i = 0, rused = h2c->rused; i < rused; ++i) {
868 request_st * const rr = h2c->r[i];
869 if (rr->h2id != id) continue;
870 r = rr;
871 break;
872 }
873 chunkqueue * const cq = con->read_queue;
874 if (NULL == r) {
875 /* simplistic heuristic to discard additional DATA from recently-closed
876 * streams (or half-closed (local)), where recently-closed here is
877 * within 2-3 seconds of any (other) stream being half-closed (local)
878 * or reset before that (other) stream received END_STREAM from peer.
879 * (e.g. clients might fire off POST request followed by DATA,
880 * and a response might be sent before processing DATA frames)
881 * (id <= h2c->h2_cid) already checked above, else H2_E_PROTOCOL_ERROR
882 * If the above conditions do not hold, then send GOAWAY to attempt to
883 * reduce the chance of becoming an infinite data sink for misbehaving
884 * clients, though remaining streams are still handled before the
885 * connection is closed. */
886 chunkqueue_mark_written(cq, 9+len);
887 if (h2c->half_closed_ts + 2 >= log_monotonic_secs) {
888 h2_send_window_update(con, 0, len); /*(h2r->h2_rwin)*/
889 return 1;
890 }
891 else {
892 if (!h2c->sent_goaway && 0 != alen)
893 h2_send_goaway_e(con, H2_E_NO_ERROR);
894 return 0;
895 }
896 }
897
898 if (r->h2state == H2_STATE_CLOSED
899 || r->h2state == H2_STATE_HALF_CLOSED_REMOTE) {
900 h2_send_rst_stream_id(id, con, H2_E_STREAM_CLOSED);
901 chunkqueue_mark_written(cq, 9+len);
902 h2_send_window_update(con, 0, len); /*(h2r->h2_rwin)*/
903 return 1;
904 }
905
906 if (r->h2_rwin <= 0 && 0 != alen) {/*(always proceed if 0==alen)*/
907 /* note: r->h2_rwin is not adjusted (below) if max_request_size exceeded
908 * in order to read and discard h2_rwin amount of data (below) */
909 if (r->conf.stream_request_body & FDEVENT_STREAM_REQUEST_BUFMIN) {
910 /*(connection_state_machine_h2() must ensure con is rescheduled,
911 * when backends consume data if con->read_queue is not empty,
912 * whether or not con->fd has data to read from the network)*/
913 /*(leave frame in cq to be re-read later)*/
914 return 0;
915 }
916 }
917 /*(allow r->h2_rwin to dip below 0 so that entire frame is processed)*/
918 /*(underflow will not occur (with reasonable SETTINGS_MAX_FRAME_SIZE used)
919 * since windows updated elsewhere and data is streamed to temp files if
920 * not FDEVENT_STREAM_REQUEST_BUFMIN)*/
921 /*r->h2_rwin -= (int32_t)len;*/
922 /*h2_send_window_update(con, r->h2id, len);*//*(r->h2_rwin)*//*(see below)*/
923 h2_send_window_update(con, 0, len); /*(h2r->h2_rwin)*/
924
925 chunkqueue * const dst = &r->reqbody_queue;
926
927 if (r->reqbody_length >= 0 && r->reqbody_length < dst->bytes_in + alen) {
928 /* data exceeds Content-Length specified (client mistake) */
929 #if 0 /* truncate */
930 alen = r->reqbody_length - dst->bytes_in;
931 /*(END_STREAM may follow in 0-length DATA frame or HEADERS (trailers))*/
932 #else /* reject */
933 h2_send_rst_stream(r, con, H2_E_PROTOCOL_ERROR);
934 chunkqueue_mark_written(cq, 9+len);
935 return 1;
936 #endif
937 }
938
939 /*(accounting for mod_accesslog and mod_rrdtool)*/
940 chunkqueue * const rq = &r->read_queue;
941 rq->bytes_in += (off_t)alen;
942 rq->bytes_out += (off_t)alen;
943
944 uint32_t wupd = 0;
945 if (s[4] & H2_FLAG_END_STREAM) {
946 if (!h2_recv_end_data(r, con, alen)) {
947 chunkqueue_mark_written(cq, 9+len);
948 return 1;
949 }
950 /*(accept data if H2_FLAG_END_STREAM was just received,
951 * regardless of r->conf.max_request_size setting)*/
952 }
953 else if (0 == r->conf.max_request_size)
954 wupd = len;
955 else {
956 /* r->conf.max_request_size is in kBytes */
957 const off_t max_request_size = (off_t)r->conf.max_request_size << 10;
958 off_t n = max_request_size - dst->bytes_in - (off_t)alen;
959 int32_t rwin = r->h2_rwin - (int32_t)len;
960 if (rwin < 0) rwin = 0;
961 if (__builtin_expect( (n >= 0), 1)) /*(allow small overage with n+8)*/
962 wupd = n>=rwin ? (n-=rwin) > (int32_t)len ? len : (uint32_t)n+8 : 0;
963 else if (-n > 65536 || 0 == r->http_status) {
964 if (0 == r->http_status) {
965 r->http_status = 413; /* Payload Too Large */
966 r->handler_module = NULL;
967 log_error(r->conf.errh, __FILE__, __LINE__,
968 "request-size too long: %lld -> 413",
969 (long long) (dst->bytes_in + (off_t)alen));
970 }
971 else { /* if (-n > 65536) */
972 /* tolerate up to 64k additional data before resetting stream
973 * (in excess to window updates sent to client)
974 * (attempt to sink data in kernel buffers so 413 can be sent)*/
975 h2_send_rst_stream_id(id, con, H2_E_STREAM_CLOSED);
976 }
977 chunkqueue_mark_written(cq, 9+len);
978 return 1;
979 }
980 }
981 /* r->h2_rwin is intentionally unmodified here so that some data in excess
982 * of max_request_size received and discarded. If r->h2_rwin use is changed
983 * in future and might reach 0, then also need to make sure that we do not
984 * spin re-processing con while waiting for backend to consume request body.
985 * stream rwin is always updated, potentially more than max_request_size so
986 * that too much data is detected, instead of waiting for read timeout. */
987 /*r->h2_rwin -= (int32_t)len;*/
988 /*r->h2_rwin += (int32_t)wupd;*/
989 h2_send_window_update(con, r->h2id, wupd);/*(r->h2_rwin)*//*noop if wupd=0*/
990
991 chunkqueue_mark_written(cq, 9 + ((s[4] & H2_FLAG_PADDED) ? 1 : 0));
992
993 #if 0
994 if (pad) {
995 /* XXX: future optimization: if data is at end of chunk, then adjust
996 * size of chunk by reducing c->mem->used to avoid copying chunk
997 * when it is split (below) since the split would be due to padding
998 * (also adjust cq->bytes_out)*/
999 /*(might quickly check 9+len == cqlen if cqlen passed in as param)*/
1000 /*(then check if cq->last contains all of padding, or leave alone)*/
1001 /*(if handled here, then set pad = 0 here)*/
1002 }
1003 #endif
1004
1005 /*(similar decision logic to that in http_chunk_uses_tempfile())*/
1006 const chunk * const c = dst->last;
1007 if ((c && c->type == FILE_CHUNK && c->file.is_temp)
1008 || chunkqueue_length(dst) + alen > 65536) {
1009 log_error_st * const errh = r->conf.errh;
1010 if (0 != chunkqueue_steal_with_tempfiles(dst, cq, (off_t)alen, errh)) {
1011 h2_send_rst_stream(r, con, H2_E_INTERNAL_ERROR);
1012 return 0;
1013 }
1014 }
1015 else
1016 chunkqueue_steal(dst, cq, (off_t)alen);
1017
1018 if (pad)
1019 chunkqueue_mark_written(cq, pad);
1020 return 1;
1021 }
1022
1023
1024 __attribute_cold__
1025 static uint32_t
h2_frame_cq_compact(chunkqueue * const cq,uint32_t len)1026 h2_frame_cq_compact (chunkqueue * const cq, uint32_t len)
1027 {
1028 /*(marked cold since most frames not expect to cross chunk boundary)*/
1029
1030 /* caller must guarantee that chunks in chunkqueue are all MEM_CHUNK */
1031 /* caller should check (chunkqueue_length(cq) >= len) before calling,
1032 * or should check that returned value >= len */
1033
1034 chunkqueue_compact_mem(cq, len);
1035 return buffer_clen(cq->first->mem) - (uint32_t)cq->first->offset;
1036 }
1037
1038
1039 __attribute_cold__
1040 static uint32_t
h2_recv_continuation(uint32_t n,uint32_t clen,const off_t cqlen,chunkqueue * const cq,connection * const con)1041 h2_recv_continuation (uint32_t n, uint32_t clen, const off_t cqlen, chunkqueue * const cq, connection * const con)
1042 {
1043 chunk *c = cq->first;
1044 uint8_t *s = (uint8_t *)(c->mem->ptr + c->offset);
1045 uint32_t m = n;
1046 uint32_t flags;
1047 h2con * const h2c = con->h2;
1048 const uint32_t fsize = h2c->s_max_frame_size;
1049 const uint32_t id = h2_u31(s+5);
1050 do {
1051 if (cqlen < n+9) return n+9; /* incomplete frame; go on */
1052 if (clen < n+9) {
1053 clen = h2_frame_cq_compact(cq, n+9);
1054 c = cq->first; /*(reload after h2_frame_cq_compact())*/
1055 s = (uint8_t *)(c->mem->ptr + c->offset);
1056 }
1057 if (s[n+3] != H2_FTYPE_CONTINUATION) {
1058 h2_send_goaway_e(con, H2_E_PROTOCOL_ERROR);
1059 return 0;
1060 }
1061 flags = s[n+4];
1062 const uint32_t flen = h2_u24(s+n);
1063 if (id != h2_u32(s+n+5)) {
1064 h2_send_goaway_e(con, H2_E_PROTOCOL_ERROR);
1065 return 0;
1066 }
1067 if (flen > fsize) {
1068 h2_send_goaway_e(con, H2_E_FRAME_SIZE_ERROR);
1069 return 0;
1070 }
1071 n += 9+flen;
1072 if (n >= 65536) { /*(very oversized for hpack)*/
1073 h2_send_goaway_e(con, H2_E_FRAME_SIZE_ERROR);
1074 return 0;
1075 }
1076 if (clen < n) {
1077 clen = h2_frame_cq_compact(cq, n);
1078 if (clen < n) return n; /* incomplete frame; go on */
1079 c = cq->first; /*(reload after h2_frame_cq_compact())*/
1080 s = (uint8_t *)(c->mem->ptr + c->offset);
1081 }
1082 } while (!(flags & H2_FLAG_END_HEADERS));
1083
1084 /* If some CONTINUATION frames were concatenated to earlier frames while
1085 * processing above, but END_HEADERS were not received, then the next time
1086 * data was read, initial frame size might exceed SETTINGS_MAX_FRAME_SIZE.
1087 * (This describes the current lighttpd implementation in h2_parse_frames())
1088 * While a flag could be set and checked to avoid this, such situations of
1089 * large HEADERS (and CONTINUATION) across multiple network reads is
1090 * expected to be rare. Reparse and concatenate below.
1091 *
1092 * Aside: why would the authors of RFC 7540 go through the trouble of
1093 * creating a CONTINUATION frame that must be special-cased when use of
1094 * CONTINUATION is so restricted e.g. no other intervening frames and
1095 * that HEADERS and PUSH_PROMISE HPACK must be parsed as a single block?
1096 * IMHO, it would have been simpler to avoid CONTINUATION entirely, and have
1097 * a special-case for HEADERS and PUSH_PROMISE to be allowed to exceed
1098 * SETTINGS_MAX_FRAME_SIZE with implementations providing a different limit.
1099 * While intermediates would not know such a limit of origin servers,
1100 * there could have been a reasonable default set with a different SETTINGS
1101 * parameter aimed just at HEADERS and PUSH_PROMISE. The parameter
1102 * SETTINGS_MAX_HEADER_LIST_SIZE could even have been (re)used, had it been
1103 * given a reasonable initial value instead of "unlimited", since HPACK
1104 * encoded headers are smaller than the HPACK decoded headers to which the
1105 * limit SETTINGS_MAX_HEADER_LIST_SIZE applies. */
1106
1107 n = m; /* reset n to beginning of first CONTINUATION frame */
1108
1109 /* Eliminate padding from first frame (HEADERS or PUSH_PROMISE) if PADDED */
1110 if (s[4] & H2_FLAG_PADDED) {
1111 const uint32_t plen = s[9];
1112 /* validate padding */
1113 const uint32_t flen = h2_u24(s);
1114 if (flen < 1 + plen + ((s[n+4] & H2_FLAG_PRIORITY) ? 5 : 0)) {
1115 /* Padding that exceeds the size remaining for the header block
1116 * fragment MUST be treated as a PROTOCOL_ERROR. */
1117 h2_send_goaway_e(con, H2_E_PROTOCOL_ERROR);
1118 return 0;
1119 }
1120 /* set padding to 0 since we will overwrite padding in merge below */
1121 /* (alternatively, could memmove() 9 bytes of frame header over the
1122 * pad length octet, remove PADDED flag, add 1 to c->offset,
1123 * add 1 to s, subtract 1 from clen and substract 1 from cqlen,
1124 * substract 1 from n, add 1 to cq->bytes_out) */
1125 s[9] = 0;
1126 /* set offset to beginning of padding at end of first frame */
1127 m -= plen;
1128 /* XXX: layer violation; adjusts chunk.c internal accounting */
1129 cq->bytes_out += plen;
1130 }
1131
1132 #ifdef __COVERITY__
1133 /* Coverity does not notice that values used in s are checked.
1134 * Although silencing here, would prefer not to do so since doing so
1135 * disables Coverity from reporting questionable modifications which
1136 * might be made to the code in the future. */
1137 __coverity_tainted_data_sink__(s);
1138 #endif
1139
1140 do {
1141 const uint32_t flen = h2_u24(s+n);
1142 #ifdef __COVERITY__ /*flen values were checked in do {} while loop above*/
1143 if (clen < n+9+flen) {
1144 h2_send_goaway_e(con, H2_E_FRAME_SIZE_ERROR);
1145 return 0;
1146 }
1147 #endif
1148 flags = s[n+4];
1149 memmove(s+m, s+n+9, flen);
1150 m += flen;
1151 n += 9+flen;
1152 /* XXX: layer violation; adjusts chunk.c internal accounting */
1153 cq->bytes_out += 9;
1154 } while (!(flags & H2_FLAG_END_HEADERS));
1155 /* overwrite frame size */
1156 m -= 9; /*(temporarily remove frame header from len)*/
1157 s[0] = (m >> 16) & 0xFF;
1158 s[1] = (m >> 8) & 0xFF;
1159 s[2] = (m ) & 0xFF;
1160 m += 9;
1161 /* adjust chunk c->mem */
1162 if (n < clen) { /*(additional frames after CONTINUATION)*/
1163 memmove(s+m, s+n, clen-n);
1164 n = m + (clen-n);
1165 }
1166 else
1167 n = m;
1168 buffer_truncate(c->mem, n + (uint32_t)c->offset);
1169
1170 return m;
1171 }
1172
1173
1174 __attribute_cold__
1175 static request_st *
h2_recv_trailers_r(connection * const con,h2con * const h2c,const uint32_t id,const uint32_t flags)1176 h2_recv_trailers_r (connection * const con, h2con * const h2c, const uint32_t id, const uint32_t flags)
1177 {
1178 /* rant: RFC 7230 HTTP/1.1 trailer-part would have been much simpler
1179 * to support in RFC 7540 HTTP/2 as a distinct frame type rather than
1180 * HEADERS. As trailers are not known at the time the request is made,
1181 * reuse of such trailers is limited and so a theoretical TRAILERS frame
1182 * could have been implemented without HPACK encoding, and would have
1183 * been more straightforward to implement than overloading and having to
1184 * handle multiple cases for HEADERS. TRAILERS support could then also
1185 * be optional, like in HTTP/1.1 */
1186 request_st *r = NULL;
1187 for (uint32_t i = 0, rused = h2c->rused; i < rused; ++i) {
1188 request_st * const rr = h2c->r[i];
1189 if (rr->h2id != id) continue;
1190 r = rr;
1191 break;
1192 }
1193 if (NULL == r) {
1194 h2_send_goaway_e(con, H2_E_PROTOCOL_ERROR);
1195 return NULL;
1196 }
1197 if (r->h2state != H2_STATE_OPEN
1198 && r->h2state != H2_STATE_HALF_CLOSED_LOCAL) {
1199 h2_send_rst_stream(r, con, H2_E_STREAM_CLOSED);
1200 return NULL;
1201 }
1202 /* RFC 7540 is not explicit in restricting HEADERS (trailers) following
1203 * (optional) DATA frames, but in following HTTP/1.1, we limit to single
1204 * (optional) HEADERS (+ CONTINUATIONs) after (optional) DATA frame(s)
1205 * and require that the HEADERS frame set END_STREAM flag. */
1206 if (!(flags & H2_FLAG_END_STREAM)) {
1207 h2_send_rst_stream(r, con, H2_E_PROTOCOL_ERROR);
1208 return NULL;
1209 }
1210
1211 return h2_recv_end_data(r, con, 0) ? r : NULL;
1212 }
1213
1214
1215 static void
h2_parse_headers_frame(request_st * const restrict r,const unsigned char * psrc,const uint32_t plen,const int trailers)1216 h2_parse_headers_frame (request_st * const restrict r, const unsigned char *psrc, const uint32_t plen, const int trailers)
1217 {
1218 h2con * const h2c = r->con->h2;
1219 struct lshpack_dec * const restrict decoder = &h2c->decoder;
1220 const unsigned char * const endp = psrc + plen;
1221 http_header_parse_ctx hpctx;
1222 hpctx.hlen = 0;
1223 hpctx.pseudo = 1; /*(XXX: should be !trailers if handling trailers)*/
1224 hpctx.scheme = 0;
1225 hpctx.trailers = trailers;
1226 hpctx.max_request_field_size = r->conf.max_request_field_size;
1227 hpctx.http_parseopts = r->conf.http_parseopts;
1228 const int log_request_header = r->conf.log_request_header;
1229 int rc = LSHPACK_OK;
1230 /*buffer_clear(&r->target);*//*(initial state)*/
1231
1232 /*(h2_init_con() resized h2r->tmp_buf to 64k; shared with r->tmp_buf)*/
1233 buffer * const tb = r->tmp_buf;
1234 force_assert(tb->size >= 65536);/*(sanity check; remove in future)*/
1235 char * const tbptr = tb->ptr;
1236 const lsxpack_strlen_t tbsz = (tb->size <= LSXPACK_MAX_STRLEN)
1237 ? tb->size
1238 : LSXPACK_MAX_STRLEN;
1239
1240 /* note: #define LSHPACK_DEC_HTTP1X_OUTPUT 1 (default) configures
1241 * decoder to produce output in format: "field-name: value\r\n"
1242 * future: modify build system to define value to 0 in lshpack.h
1243 * against which lighttpd builds (or define value in build systems)
1244 * Then adjust code below to not use the HTTP/1.x compatibility,
1245 * as it is less efficient to copy into HTTP/1.1 request and reparse
1246 * than it is to directly parse each decoded header line. */
1247 lsxpack_header_t lsx;
1248 while (psrc < endp) {
1249 memset(&lsx, 0, sizeof(lsxpack_header_t));
1250 lsx.buf = tbptr;
1251 lsx.val_len = tbsz;
1252 rc = lshpack_dec_decode(decoder, &psrc, endp, &lsx);
1253 if (0 == lsx.name_len)
1254 rc = LSHPACK_ERR_BAD_DATA;
1255 if (__builtin_expect( (rc == LSHPACK_OK), 1)) {
1256 hpctx.k = lsx.buf+lsx.name_offset;
1257 hpctx.v = lsx.buf+lsx.val_offset;
1258 hpctx.klen = lsx.name_len;
1259 hpctx.vlen = lsx.val_len;
1260 /*assert(lsx.hpack_index < sizeof(lshpack_idx_http_header));*/
1261 hpctx.id = lshpack_idx_http_header[lsx.hpack_index];
1262
1263 if (log_request_header)
1264 log_error(r->conf.errh, __FILE__, __LINE__,
1265 "fd:%d id:%u rqst: %.*s: %.*s", r->con->fd, r->h2id,
1266 (int)hpctx.klen, hpctx.k, (int)hpctx.vlen, hpctx.v);
1267
1268 const int http_status = http_request_parse_header(r, &hpctx);
1269 if (__builtin_expect( (0 != http_status), 0)) {
1270 if (r->http_status == 0) /*might be set if processing trailers*/
1271 r->http_status = http_status;
1272 break;
1273 }
1274 }
1275 #if 0 /*(see catch-all below)*/
1276 /* Send GOAWAY (further below) (decoder state not maintained on error)
1277 * (see comments above why decoder state must be maintained) */
1278 /* XXX: future: could try to send :status 431 here
1279 * and reset other active streams in H2_STATE_OPEN */
1280 else if (rc == LSHPACK_ERR_MORE_BUF) {
1281 /* XXX: TODO if (r->conf.log_request_header_on_error) */
1282 r->http_status = 431; /* Request Header Fields Too Large */
1283 /*(try to avoid reading/buffering more data for this request)*/
1284 r->h2_rwin = 0; /*(out-of-sync with peer, but is error case)*/
1285 /*r->h2state = H2_STATE_HALF_CLOSED_REMOTE*/
1286 /* psrc was not advanced if LSHPACK_ERR_MORE_BUF;
1287 * processing must stop (since not retrying w/ larger buf)*/
1288 break;
1289 }
1290 #endif
1291 else { /* LSHPACK_ERR_BAD_DATA */
1292 /* GOAWAY with H2_E_PROTOCOL_ERROR is not specific enough
1293 * to tell peer to not retry request, so send RST_STREAM
1294 * (slightly more specific, but not by much) before GOAWAY*/
1295 /* LSHPACK_ERR_MORE_BUF is treated as an attack, send GOAWAY
1296 * (h2r->tmp_buf was resized to 64k in h2_init_con()) */
1297 request_h2error_t err = H2_E_COMPRESSION_ERROR;
1298 if (rc != LSHPACK_ERR_BAD_DATA) {
1299 /* LSHPACK_ERR_TOO_LARGE, LSHPACK_ERR_MORE_BUF */
1300 err = H2_E_PROTOCOL_ERROR;
1301 h2_send_rst_stream(r, r->con, err);
1302 }
1303 if (!h2c->sent_goaway && !trailers)
1304 h2c->h2_cid = r->h2id;
1305 h2_send_goaway_e(r->con, err);
1306 if (!trailers) {
1307 h2_retire_stream(r, r->con);
1308 return;
1309 }
1310 else {
1311 r->state = CON_STATE_ERROR;
1312 r->h2state = H2_STATE_CLOSED;
1313 }
1314 break;
1315 }
1316 }
1317
1318 hpctx.hlen += 2;
1319 r->rqst_header_len += hpctx.hlen;
1320 /*(accounting for mod_accesslog and mod_rrdtool)*/
1321 chunkqueue * const rq = &r->read_queue;
1322 rq->bytes_in += (off_t)hpctx.hlen;
1323 rq->bytes_out += (off_t)hpctx.hlen;
1324
1325 if (0 == r->http_status && LSHPACK_OK == rc && !trailers) {
1326 if (hpctx.pseudo)
1327 r->http_status =
1328 http_request_validate_pseudohdrs(r, hpctx.scheme,
1329 hpctx.http_parseopts);
1330 if (0 == r->http_status)
1331 http_request_headers_process_h2(r, r->con->proto_default_port);
1332 }
1333 }
1334
1335
1336 static int
h2_recv_headers(connection * const con,uint8_t * const s,uint32_t flen)1337 h2_recv_headers (connection * const con, uint8_t * const s, uint32_t flen)
1338 {
1339 #ifdef __COVERITY__
1340 /* Coverity does not notice that values used in s are checked.
1341 * Although silencing here, would prefer not to do so since doing so
1342 * disables Coverity from reporting questionable modifications which
1343 * might be made to the code in the future. */
1344 __coverity_tainted_data_sink__(s);
1345 #endif
1346 request_st *r = NULL;
1347 h2con * const h2c = con->h2;
1348 const uint32_t id = h2_u31(s+5);
1349 #if 0 /*(included in (!(id & 1)) below)*/
1350 if (0 == id) { /* HEADERS, PUSH_PROMISE stream id must != 0 */
1351 h2_send_goaway_e(con, H2_E_PROTOCOL_ERROR);
1352 return 0;
1353 }
1354 #endif
1355 if (!(id & 1)) { /* stream id from client must be odd */
1356 h2_send_goaway_e(con, H2_E_PROTOCOL_ERROR);
1357 return 0;
1358 }
1359
1360 request_st * const h2r = &con->request;
1361 int trailers = 0;
1362
1363 if (id > h2c->h2_cid) {
1364 if (h2c->rused == sizeof(h2c->r)/sizeof(*h2c->r))
1365 return h2_send_refused_stream(id, con);
1366 /* Note: MUST process HPACK decode even if already sent GOAWAY.
1367 * This is necessary since there may be active streams not in
1368 * H2_STATE_HALF_CLOSED_REMOTE, e.g. H2_STATE_OPEN, still possibly
1369 * receiving DATA and, more relevantly, still might receive HEADERS
1370 * frame with trailers, for which the decoder state is required.
1371 * XXX: future might try to reduce other processing done if sent
1372 * GOAWAY, e.g. might avoid allocating (request_st *r) */
1373 r = h2_init_stream(h2r, con);
1374 r->h2id = id;
1375 r->h2state = (s[4] & H2_FLAG_END_STREAM)
1376 ? H2_STATE_HALF_CLOSED_REMOTE
1377 : H2_STATE_OPEN;
1378 r->state = CON_STATE_REQUEST_END;
1379 /* Note: timestamps here are updated only after receipt of entire header
1380 * (HEADERS frame might have been sent in multiple packets
1381 * and CONTINUATION frames may have been sent in multiple packets)
1382 * (affects high precision timestamp, if enabled)
1383 * (large sets of headers are not typical, and even when they do
1384 * occur, they will typically be sent within the same second)
1385 * (future: might keep high precision timestamp in h2con when first
1386 * packet of HEADERS or PUSH_PROMISE is received, and clear that
1387 * timestamp when frame + CONTINUATION(s) are complete (so that
1388 * re-read of initial frame does not overwrite the timestamp))
1389 */
1390 r->start_hp.tv_sec = log_epoch_secs;
1391 if (r->conf.high_precision_timestamps)
1392 log_clock_gettime_realtime(&r->start_hp);
1393 }
1394 else {
1395 r = h2_recv_trailers_r(con, h2c, id, s[4]); /* (cold code path) */
1396 if (NULL == r)
1397 return (h2c->sent_goaway > 0) ? 0 : 1;
1398 trailers = 1;
1399 }
1400
1401 const unsigned char *psrc = s + 9;
1402 uint32_t alen = flen;
1403 if (s[4] & H2_FLAG_PADDED) {
1404 ++psrc;
1405 const uint32_t pad = s[9];
1406 if (flen < 1 + pad + ((s[4] & H2_FLAG_PRIORITY) ? 5 : 0)) {
1407 /* Padding that exceeds the size remaining for the header block
1408 * fragment MUST be treated as a PROTOCOL_ERROR. */
1409 h2_send_goaway_e(con, H2_E_PROTOCOL_ERROR);
1410 if (!trailers)
1411 h2_retire_stream(r, con);
1412 else {
1413 r->state = CON_STATE_ERROR;
1414 r->h2state = H2_STATE_CLOSED;
1415 }
1416 return 0;
1417 }
1418 alen -= (1 + pad); /*(alen is adjusted for PRIORITY below)*/
1419 }
1420 if (s[4] & H2_FLAG_PRIORITY) {
1421 /* XXX: TODO: handle PRIORITY (prio fields start at *psrc) */
1422 const uint32_t prio = h2_u31(psrc);
1423 if (prio == id) {
1424 h2_send_rst_stream(r, con, H2_E_PROTOCOL_ERROR);
1425 if (!trailers)
1426 h2_retire_stream(r, con);
1427 return 1;
1428 }
1429 #if 0
1430 uint32_t exclusive_dependency = (psrc[0] & 0x80) ? 1 : 0;
1431 uint32_t weight = psrc[4];
1432 #endif
1433 psrc += 5;
1434 alen -= 5;
1435 }
1436
1437 h2_parse_headers_frame(r, psrc, alen, trailers);
1438
1439 #if 0 /*(handled in h2_parse_frames() as a connection error)*/
1440 /* not handled here:
1441 * r is invalid if h2_parse_headers_frame() HPACK decode error */
1442 if (s[3] == H2_FTYPE_PUSH_PROMISE && !trailers) {
1443 /* Had to process HPACK to keep HPACK tables sync'd with peer but now
1444 * discard the request if PUSH_PROMISE, since not expected, as this code
1445 * is running as a server, not as a client.
1446 * XXX: future might try to reduce other processing done if
1447 * discarding, e.g. might avoid allocating (request_st *r) */
1448 /* rant: PUSH_PROMISE could have been a flag on HEADERS frame
1449 * instead of an independent frame type */
1450 r->http_status = 0;
1451 h2_retire_stream(r, con);
1452 }
1453 #endif
1454
1455 if (!h2c->sent_goaway) {
1456 h2c->h2_cid = id;
1457 if (!light_btst(r->rqst_htags, HTTP_HEADER_CONTENT_LENGTH))
1458 r->reqbody_length = (s[4] & H2_FLAG_END_STREAM) ? 0 : -1;
1459 #if 0
1460 else if (r->reqbody_length > 0 && (s[4] & H2_FLAG_END_STREAM)) {
1461 /*(handled in connection_handle_read_post_state())*/
1462 /* XXX: TODO if (r->conf.log_request_header_on_error) */
1463 r->http_status = 400; /* Bad Request */
1464 }
1465 #endif
1466
1467 /* RFC 7540 Section 8. HTTP Message Exchanges
1468 * 8.1.2.6. Malformed Requests and Responses
1469 * For malformed requests, a server MAY send an HTTP
1470 * response prior to closing or resetting the stream.
1471 * However, h2spec expects stream PROTOCOL_ERROR.
1472 * (This is unfortunate, since we would rather send
1473 * 400 Bad Request which tells client *do not* retry
1474 * the bad request without modification)
1475 * https://github.com/summerwind/h2spec/issues/120
1476 * https://github.com/summerwind/h2spec/issues/121
1477 * https://github.com/summerwind/h2spec/issues/122
1478 */
1479 #if 0
1480 if (400 == r->http_status && !trailers) {
1481 h2_send_rst_stream(r, con, H2_E_PROTOCOL_ERROR);
1482 h2_retire_stream(r, con);
1483 }
1484 #endif
1485 }
1486 else if (h2c->h2_cid < id) {
1487 /* Had to process HPACK to keep HPACK tables sync'd with peer
1488 * but now discard the request if id is after id sent in GOAWAY.
1489 * XXX: future might try to reduce other processing done if
1490 * discarding, e.g. might avoid allocating (request_st *r) */
1491 r->http_status = 0;
1492 h2_retire_stream(r, con);
1493 }
1494
1495 return 1;
1496 }
1497
1498
1499 int
h2_parse_frames(connection * const con)1500 h2_parse_frames (connection * const con)
1501 {
1502 /* read and process HTTP/2 frames from socket */
1503 h2con * const h2c = con->h2;
1504 chunkqueue * const cq = con->read_queue;
1505 /* initial max frame size is the minimum: 16k
1506 * (lighttpd does not currently increase max frame size)
1507 * (lighttpd does not currently decrease max frame size)
1508 * (XXX: If SETTINGS_MAX_FRAME_SIZE were increased and then decreased,
1509 * should accept the larger frame size until SETTINGS is ACK'd) */
1510 const uint32_t fsize = h2c->s_max_frame_size;
1511 for (off_t cqlen = chunkqueue_length(cq); cqlen >= 9; ) {
1512 chunk *c = cq->first;
1513 /*assert(c->type == MEM_CHUNK);*/
1514 /* copy data if frame header crosses chunk boundary
1515 * future: be more efficient than blind full chunk copy */
1516 uint32_t clen = buffer_clen(c->mem) - c->offset;
1517 if (clen < 9) {
1518 clen = h2_frame_cq_compact(cq, 9);
1519 c = cq->first; /*(reload after h2_frame_cq_compact())*/
1520 }
1521 uint8_t *s = (uint8_t *)(c->mem->ptr + c->offset);
1522 uint32_t flen = h2_u24(s);
1523 if (flen > fsize) {
1524 h2_send_goaway_e(con, H2_E_FRAME_SIZE_ERROR);
1525 return 0;
1526 }
1527
1528 /*(handle PUSH_PROMISE as connection error further below)*/
1529 /*if (s[3] == H2_FTYPE_HEADERS || s[3] == H2_FTYPE_PUSH_PROMISE)*/
1530
1531 if (s[3] == H2_FTYPE_HEADERS) {
1532 if (cqlen < 9+flen) return 1; /* incomplete frame; go on */
1533 if (clen < 9+flen) {
1534 clen = h2_frame_cq_compact(cq, 9+flen);
1535 c = cq->first; /*(reload after h2_frame_cq_compact())*/
1536 s = (uint8_t *)(c->mem->ptr + c->offset);
1537 }
1538
1539 if (!(s[4] & H2_FLAG_END_HEADERS)) {
1540 /* collect CONTINUATION frames (cold code path) */
1541 /* note: h2_recv_continuation() return value is overloaded
1542 * and the resulting clen is 9+flen of *concatenated* frames */
1543 clen = h2_recv_continuation(9+flen, clen, cqlen, cq, con);
1544 if (0 == clen) return 0;
1545 if (cqlen < clen) return 1; /* incomplete frames; go on */
1546 c = cq->first; /*(reload after h2_recv_continuation())*/
1547 s = (uint8_t *)(c->mem->ptr + c->offset);
1548 /* frame size was also updated and might (legitimately)
1549 * exceed SETTINGS_MAX_FRAME_SIZE, so do not test fsize again */
1550 flen = h2_u24(s);
1551 /* recalculate after CONTINUATION removed */
1552 cqlen = chunkqueue_length(cq);
1553 }
1554
1555 #ifdef __COVERITY__
1556 /* Coverity does not notice that values used in s are checked.
1557 * Although silencing here, would prefer not to do so since doing so
1558 * disables Coverity from reporting questionable modifications which
1559 * might be made to the code in the future. */
1560 __coverity_tainted_data_sink__(s);
1561 #endif
1562
1563 int rc = h2_recv_headers(con, s, flen);
1564 cqlen -= (9+flen);
1565 if (rc >= 0)
1566 chunkqueue_mark_written(cq, 9+flen);
1567 if (rc <= 0)
1568 return 0;
1569 con->read_idle_ts = log_monotonic_secs;
1570 }
1571 else if (s[3] == H2_FTYPE_DATA) {
1572 /* future: might try to stream data for incomplete frames,
1573 * but that would require keeping additional state for partially
1574 * read frames, including cleaning up if errors occur.
1575 * Since well-behaved clients do not intentionally send partial
1576 * frames, and try to resend if socket buffers are full, this is
1577 * probably not a big concern in practice. */
1578 if (cqlen < 9+flen) return 1; /* incomplete frame; go on */
1579 con->read_idle_ts = log_monotonic_secs;
1580 /*(h2_recv_data() must consume frame from cq or else return 0)*/
1581 if (!h2_recv_data(con, s, flen))
1582 return 0;
1583 cqlen -= (9+flen);
1584 }
1585 else {
1586 /* frame types below are expected to be small
1587 * most frame types below have fixed (small) size
1588 * 4 bytes - WINDOW_UPDATE
1589 * 5 bytes - PRIORITY
1590 * 8 bytes - PING
1591 * 4 bytes - RST_STREAM
1592 * some are variable size
1593 * SETTINGS (6 * #settings; 6 defined in RFC 7540 Section 6.5)
1594 * GOAWAY (8 + optional additional debug data (variable))
1595 * XXX: might add sanity check for a max flen here,
1596 * before waiting to read partial frame
1597 * (fsize limit is still enforced above for all frames)
1598 */
1599 if (cqlen < 9+flen) return 1; /* incomplete frame; go on */
1600 if (clen < 9+flen) {
1601 clen = h2_frame_cq_compact(cq, 9+flen); UNUSED(clen);
1602 c = cq->first; /*(reload after h2_frame_cq_compact())*/
1603 s = (uint8_t *)(c->mem->ptr + c->offset);
1604 }
1605 switch (s[3]) { /* frame type */
1606 case H2_FTYPE_WINDOW_UPDATE:
1607 h2_recv_window_update(con, s, flen);
1608 break;
1609 case H2_FTYPE_PRIORITY:
1610 h2_recv_priority(con, s, flen);
1611 break;
1612 case H2_FTYPE_SETTINGS:
1613 h2_recv_settings(con, s, flen);
1614 break;
1615 case H2_FTYPE_PING:
1616 h2_recv_ping(con, s, flen);
1617 break;
1618 case H2_FTYPE_RST_STREAM:
1619 h2_recv_rst_stream(con, s, flen);
1620 break;
1621 case H2_FTYPE_GOAWAY:
1622 if (!h2_recv_goaway(con, s, flen)) return 0;
1623 break;
1624 case H2_FTYPE_PUSH_PROMISE: /*not expected from client*/
1625 case H2_FTYPE_CONTINUATION: /*handled with HEADERS*/
1626 h2_send_goaway_e(con, H2_E_PROTOCOL_ERROR);
1627 return 0;
1628 default: /* ignore unknown frame types */
1629 break;
1630 }
1631 cqlen -= (9+flen);
1632 chunkqueue_mark_written(cq, 9+flen);
1633 }
1634
1635 if (h2c->sent_goaway > 0) return 0;
1636 }
1637
1638 return 1;
1639 }
1640
1641
1642 int
h2_want_read(connection * const con)1643 h2_want_read (connection * const con)
1644 {
1645 chunkqueue * const cq = con->read_queue;
1646 if (chunkqueue_is_empty(cq)) return 1;
1647
1648 /* check for partial frame */
1649 const off_t cqlen = chunkqueue_length(cq);
1650 if (cqlen < 9) return 1;
1651 chunk *c = cq->first;
1652 uint32_t clen = buffer_clen(c->mem) - c->offset;
1653 if (clen < 9) {
1654 clen = h2_frame_cq_compact(cq, 9);
1655 c = cq->first; /*(reload after h2_frame_cq_compact())*/
1656 }
1657 uint8_t *s = (uint8_t *)(c->mem->ptr + c->offset);
1658 uint32_t flen = h2_u24(s);
1659 if (clen < 9+flen) return 1;
1660
1661 /* check if not HEADERS, or if HEADERS has END_HEADERS flag */
1662 if (s[3] != H2_FTYPE_HEADERS || (s[4] & H2_FLAG_END_HEADERS))
1663 return 0;
1664
1665 /* check for partial CONTINUATION frames */
1666 for (uint32_t n = 9+flen; cqlen >= n+9; n += 9+flen) {
1667 if (clen < n+9) {
1668 clen = h2_frame_cq_compact(cq, n+9);
1669 c = cq->first; /*(reload after h2_frame_cq_compact())*/
1670 s = (uint8_t *)(c->mem->ptr + c->offset);
1671 }
1672 flen = h2_u24(s+n);
1673 if (cqlen < n+9+flen) return 1; /* incomplete frame; go on */
1674 if (s[4] & H2_FLAG_END_HEADERS) return 0;
1675 }
1676
1677 return 1;
1678 }
1679
1680
1681 static int
h2_recv_client_connection_preface(connection * const con)1682 h2_recv_client_connection_preface (connection * const con)
1683 {
1684 /* check if the client Connection Preface (24 bytes) has been received
1685 * (initial SETTINGS frame should immediately follow, but is not checked) */
1686 chunkqueue * const cq = con->read_queue;
1687 if (chunkqueue_length(cq) < 24) {
1688 chunk * const c = cq->first;
1689 if (c && buffer_clen(c->mem) - c->offset >= 4) {
1690 const char * const s = c->mem->ptr + c->offset;
1691 if (s[0]!='P'||s[1]!='R'||s[2]!='I'||s[3]!=' ') {
1692 h2_send_goaway_e(con, H2_E_PROTOCOL_ERROR);
1693 return 1; /* error; done receiving connection preface */
1694 }
1695 }
1696 return 0; /*(not ready yet)*/
1697 }
1698
1699 static const char h2preface[] = "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n";
1700 chunk *c = cq->first;
1701 const uint32_t clen = buffer_clen(c->mem) - c->offset;
1702 if (clen < 24) h2_frame_cq_compact(cq, 24);
1703 c = cq->first; /*(reload after h2_frame_cq_compact())*/
1704 const uint8_t * const s = (uint8_t *)(c->mem->ptr + c->offset);
1705 if (0 == memcmp(s, h2preface, 24)) /* sizeof(h2preface)-1) */
1706 chunkqueue_mark_written(cq, 24);
1707 else
1708 h2_send_goaway_e(con, H2_E_PROTOCOL_ERROR);
1709 return 1; /* done receiving connection preface (even if error occurred) */
1710 }
1711
1712
1713 __attribute_cold__
1714 static int
h2_read_client_connection_preface(struct connection * const con,chunkqueue * const cq,off_t max_bytes)1715 h2_read_client_connection_preface (struct connection * const con, chunkqueue * const cq, off_t max_bytes)
1716 {
1717 /* temporary con->network_read() filter until connection preface received */
1718
1719 /*(alternatively, func ptr could be saved in an element in (h2con *))*/
1720 void ** const hctx = con->plugin_ctx+0; /*(0 idx used for h2)*/
1721 int(* const network_read)(struct connection *, chunkqueue *, off_t) =
1722 (int(*)(struct connection *, chunkqueue *, off_t))(uintptr_t)(*hctx);
1723 if (max_bytes < 24) max_bytes = 24; /*(should not happen)*/
1724 int rc = (network_read)(con, cq, max_bytes);
1725 if (NULL == con->h2) return rc; /*(unexpected; already cleaned up)*/
1726 if (-1 != rc && h2_recv_client_connection_preface(con)) {
1727 con->network_read = network_read;
1728 *hctx = NULL;
1729 /*(intentionally update timestamp only after reading preface complete)*/
1730 con->read_idle_ts = log_monotonic_secs;
1731 }
1732 return rc;
1733 }
1734
1735
1736 void
h2_init_con(request_st * const restrict h2r,connection * const restrict con,const buffer * const restrict http2_settings)1737 h2_init_con (request_st * const restrict h2r, connection * const restrict con, const buffer * const restrict http2_settings)
1738 {
1739 h2con * const h2c = calloc(1, sizeof(h2con));
1740 force_assert(h2c);
1741 con->h2 = h2c;
1742 con->read_idle_ts = log_monotonic_secs;
1743 con->keep_alive_idle = h2r->conf.max_keep_alive_idle;
1744
1745 /*(h2r->h2_rwin must match value assigned in h2_init_stream())*/
1746 h2r->h2_rwin = 65535; /* h2 connection recv window */
1747 h2r->h2_swin = 65535; /* h2 connection send window */
1748 /* settings sent from peer */ /* initial values */
1749 h2c->s_header_table_size = 4096; /* SETTINGS_HEADER_TABLE_SIZE */
1750 h2c->s_enable_push = 1; /* SETTINGS_ENABLE_PUSH */
1751 h2c->s_max_concurrent_streams= ~0u; /* SETTINGS_MAX_CONCURRENT_STREAMS */
1752 h2c->s_initial_window_size = 65535; /* SETTINGS_INITIAL_WINDOW_SIZE */
1753 h2c->s_max_frame_size = 16384; /* SETTINGS_MAX_FRAME_SIZE */
1754 h2c->s_max_header_list_size = ~0u; /* SETTINGS_MAX_HEADER_LIST_SIZE */
1755 h2c->sent_settings = log_monotonic_secs;/*(send SETTINGS below)*/
1756
1757 lshpack_dec_init(&h2c->decoder);
1758 lshpack_enc_init(&h2c->encoder);
1759 lshpack_enc_use_hist(&h2c->encoder, 1);
1760
1761 if (http2_settings) /*(if Upgrade: h2c)*/
1762 h2_parse_frame_settings(con, (uint8_t *)BUF_PTR_LEN(http2_settings));
1763
1764 static const uint8_t h2settings[] = { /*(big-endian numbers)*/
1765 /* SETTINGS */
1766 0x00, 0x00, 0x0c /* frame length */ /* 6 * 2 for two settings */
1767 ,H2_FTYPE_SETTINGS /* frame type */
1768 ,0x00 /* frame flags */
1769 ,0x00, 0x00, 0x00, 0x00 /* stream identifier */
1770 ,0x00, H2_SETTINGS_MAX_CONCURRENT_STREAMS
1771 ,0x00, 0x00, 0x00, 0x08 /* 8 */
1772 #if 0 /* ? explicitly disable dynamic table ? (and adjust frame length) */
1773 /* If this is sent, must wait until peer sends SETTINGS with ACK
1774 * before disabling dynamic table in HPACK decoder */
1775 /*(before calling lshpack_dec_set_max_capacity(&h2c->decoder, 0))*/
1776 ,0x00, H2_SETTINGS_HEADER_TABLE_SIZE
1777 ,0x00, 0x00, 0x00, 0x00 /* 0 */
1778 #endif
1779 #if 0 /* ? explicitly disable push ? (and adjust frame length) */
1780 ,0x00, H2_SETTINGS_ENABLE_PUSH
1781 ,0x00, 0x00, 0x00, 0x00 /* 0 */
1782 #endif
1783 #if 0 /* ? increase from default (65535) ? (and adjust frame length) */
1784 ,0x00, H2_SETTINGS_INITIAL_WINDOW_SIZE
1785 ,0x00, 0x02, 0x00, 0x00 /* 131072 */
1786 #endif
1787 #if 0 /* ? increase from default (16384) ? (and adjust frame length) */
1788 ,0x00, H2_SETTINGS_MAX_FRAME_SIZE
1789 ,0x00, 0x00, 0x80, 0x00 /* 32768 */
1790 #endif
1791 ,0x00, H2_SETTINGS_MAX_HEADER_LIST_SIZE
1792 ,0x00, 0x00, 0xFF, 0xFF /* 65535 */
1793
1794 #if 0
1795 /* WINDOW_UPDATE */
1796 ,0x00, 0x00, 0x04 /* frame length */
1797 ,H2_FTYPE_WINDOW_UPDATE /* frame type */
1798 ,0x00 /* frame flags */
1799 ,0x00, 0x00, 0x00, 0x00 /* stream identifier */
1800 ,0x00, 0x01, 0x00, 0x01 /* 65537 */ /* increase connection rwin to 128k */
1801 #endif
1802 };
1803
1804 /*h2r->h2_rwin += 65537;*//*(enable if WINDOWS_UPDATE is sent above)*/
1805 chunkqueue_append_mem(con->write_queue,
1806 (const char *)h2settings, sizeof(h2settings));
1807
1808 if (!h2_recv_client_connection_preface(con)) {
1809 /*(alternatively, func ptr could be saved in an element in (h2con *))*/
1810 con->plugin_ctx[0] = (void *)(uintptr_t)con->network_read;
1811 con->network_read = h2_read_client_connection_preface;
1812 /* note: no steps taken to reset con->network_read() on error
1813 * as con->network_read() is always set in connection_accepted() */
1814 }
1815
1816 buffer_string_prepare_copy(h2r->tmp_buf, 65535);
1817 }
1818
1819
1820 static void
h2_send_hpack(request_st * const r,connection * const con,const char * data,uint32_t dlen,const uint32_t flags)1821 h2_send_hpack (request_st * const r, connection * const con, const char *data, uint32_t dlen, const uint32_t flags)
1822 {
1823 union {
1824 uint8_t c[12];
1825 uint32_t u[3]; /*(alignment)*/
1826 } headers = { { /*(big-endian numbers)*/
1827 0x00, 0x00, 0x00 /* padding for alignment; do not send */
1828 /* HEADERS */
1829 ,0x00, 0x00, 0x00 /* frame length (fill in below) */
1830 ,H2_FTYPE_HEADERS /* frame type */
1831 ,(uint8_t)flags /* frame flags (e.g. END_STREAM for trailers) */
1832 ,0x00, 0x00, 0x00, 0x00 /* stream identifier (fill in below) */
1833 } };
1834
1835 headers.u[2] = htonl(r->h2id);
1836
1837 /* similar to h2_send_data(), but unlike DATA frames there is a HEADERS
1838 * frame potentially followed by CONTINUATION frame(s) here, and the final
1839 * HEADERS or CONTINUATION frame here has END_HEADERS flag set.
1840 * For trailers, END_STREAM flag is set on HEADERS frame. */
1841
1842 /*(approximate space needed for frames (header + payload)
1843 * with slight over-estimate of 16 bytes per frame header (> 9)
1844 * and minimum SETTING_MAX_FRAME_SIZE of 16k (could be larger)
1845 * (dlen >> 14)+1 is num 16k frames needed, multipled by 16 bytes
1846 * per frame can be appoximated with (dlen>>10) + 9)*/
1847 buffer * const b =
1848 chunkqueue_append_buffer_open_sz(con->write_queue, dlen + (dlen>>10) + 9);
1849 char * restrict ptr = b->ptr;
1850 h2con * const h2c = con->h2;
1851 const uint32_t fsize = h2c->s_max_frame_size;
1852 do {
1853 const uint32_t len = dlen < fsize ? dlen : fsize;
1854 headers.c[3] = (len >> 16) & 0xFF; /*(off +3 to skip over align pad)*/
1855 headers.c[4] = (len >> 8) & 0xFF;
1856 headers.c[5] = (len ) & 0xFF;
1857 if (len == dlen)
1858 headers.c[7] |= H2_FLAG_END_HEADERS;
1859 #if 0
1860 chunkqueue_append_mem(con->write_queue, /*(+3 to skip over align pad)*/
1861 (const char *)headers.c+3, sizeof(headers)-3);
1862 chunkqueue_append_mem(con->write_queue, data, len);
1863 #else
1864 memcpy(ptr, headers.c+3, sizeof(headers)-3);
1865 memcpy(ptr+sizeof(headers)-3, data, len);
1866 ptr += len + sizeof(headers)-3;
1867 #endif
1868 data += len;
1869 dlen -= len;
1870 /*(include H2_FLAG_END_STREAM in HEADERS frame, not CONTINUATION)*/
1871 headers.c[6] = H2_FTYPE_CONTINUATION; /*(if additional frames needed)*/
1872 headers.c[7] = 0x00; /*(off +3 to skip over align pad)*/
1873 } while (dlen);
1874 buffer_truncate(b, (uint32_t)(ptr - b->ptr));
1875 chunkqueue_append_buffer_commit(con->write_queue);
1876 }
1877
1878
1879 __attribute_cold__
1880 static void
h2_log_response_header_lsx(request_st * const r,const lsxpack_header_t * const lsx)1881 h2_log_response_header_lsx(request_st * const r, const lsxpack_header_t * const lsx)
1882 {
1883 log_error(r->conf.errh, __FILE__, __LINE__,
1884 "fd:%d id:%u resp: %.*s: %.*s", r->con->fd, r->h2id,
1885 (int)lsx->name_len, lsx->buf + lsx->name_offset,
1886 (int)lsx->val_len, lsx->buf + lsx->val_offset);
1887 }
1888
1889
1890 __attribute_cold__
1891 static void
h2_log_response_header(request_st * const r,const int len,const char * const hdr)1892 h2_log_response_header(request_st * const r, const int len, const char * const hdr)
1893 {
1894 log_error(r->conf.errh, __FILE__, __LINE__,
1895 "fd:%d id:%u resp: %.*s", r->con->fd, r->h2id, len, hdr);
1896 }
1897
1898
1899 void
h2_send_headers(request_st * const r,connection * const con)1900 h2_send_headers (request_st * const r, connection * const con)
1901 {
1902 /*(set keep_alive_idle; out-of-place and non-event for most configs,
1903 * but small attempt to (maybe) preserve behavior for specific configs)*/
1904 con->keep_alive_idle = r->conf.max_keep_alive_idle;
1905
1906 /* specialized version of http_response_write_header(); send headers
1907 * directly to HPACK encoder, rather than double-buffering in chunkqueue */
1908
1909 if (304 == r->http_status
1910 && light_btst(r->resp_htags, HTTP_HEADER_CONTENT_ENCODING))
1911 http_header_response_unset(r, HTTP_HEADER_CONTENT_ENCODING,
1912 CONST_STR_LEN("Content-Encoding"));
1913
1914 /*(h2_init_con() resized h2r->tmp_buf to 64k; shared with r->tmp_buf)*/
1915 buffer * const tb = r->tmp_buf;
1916 force_assert(tb->size >= 65536);/*(sanity check; remove in future)*/
1917 unsigned char *dst = (unsigned char *)tb->ptr;
1918 unsigned char * const dst_end = (unsigned char *)tb->ptr + tb->size;
1919
1920 h2con * const h2c = con->h2;
1921 struct lshpack_enc * const encoder = &h2c->encoder;
1922 lsxpack_header_t lsx;
1923 uint32_t alen = 7+3+4; /* ":status: xxx\r\n" */
1924 const int log_response_header = r->conf.log_response_header;
1925 const int resp_header_repeated = r->resp_header_repeated;
1926
1927 char status[12] = ":status: 200";
1928
1929 memset(&lsx, 0, sizeof(lsxpack_header_t));
1930 lsx.buf = status;
1931 lsx.name_offset = 0;
1932 lsx.name_len = 7;
1933 lsx.val_offset = 9;
1934 lsx.val_len = 3;
1935 if (__builtin_expect( (200 == r->http_status), 1)) {
1936 lsx.hpack_index = LSHPACK_HDR_STATUS_200;
1937 }
1938 else {
1939 int x = r->http_status; /*(expect status < 1000; should be [100-599])*/
1940 switch (x) {
1941 /*case 200: lsx.hpack_index = LSHPACK_HDR_STATUS_200; break;*/
1942 case 204: lsx.hpack_index = LSHPACK_HDR_STATUS_204; break;
1943 case 206: lsx.hpack_index = LSHPACK_HDR_STATUS_206; break;
1944 case 304: lsx.hpack_index = LSHPACK_HDR_STATUS_304; break;
1945 case 400: lsx.hpack_index = LSHPACK_HDR_STATUS_400; break;
1946 case 404: lsx.hpack_index = LSHPACK_HDR_STATUS_404; break;
1947 case 500: lsx.hpack_index = LSHPACK_HDR_STATUS_500; break;
1948 default:
1949 break;
1950 }
1951 int nx;
1952 status[11] += (x - (nx = x/10) * 10); /* (x % 10) */
1953 x = nx;
1954 status[10] += (x - (nx = x/10) * 10); /* (x / 10 % 10) */
1955 status[9] = '0' + nx; /* (x / 100) */
1956 }
1957
1958 dst = lshpack_enc_encode(encoder, dst, dst_end, &lsx);
1959 if (dst == (unsigned char *)tb->ptr) {
1960 h2_send_rst_stream(r, con, H2_E_INTERNAL_ERROR);
1961 return;
1962 }
1963
1964 if (log_response_header)
1965 h2_log_response_header(r, 12, status);
1966
1967 /* add all headers */
1968 data_string * const * const restrict hdata =
1969 (data_string * const *)r->resp_headers.data;
1970 for (uint32_t i = 0, used = r->resp_headers.used; i < used; ++i) {
1971 data_string * const ds = hdata[i];
1972 const uint32_t klen = buffer_clen(&ds->key);
1973 const uint32_t vlen = buffer_clen(&ds->value);
1974 if (__builtin_expect( (0 == klen), 0)) continue;
1975 if (__builtin_expect( (0 == vlen), 0)) continue;
1976 alen += klen + vlen + 4;
1977
1978 if (alen > LSXPACK_MAX_STRLEN) {
1979 /* ls-hpack default limit (UINT16_MAX) is per-line, due to field
1980 * sizes of lsx.name_offset,lsx.name_len,lsx.val_offset,lsx.val_len
1981 * However, similar to elsewhere, limit total size of expanded
1982 * headers to (very generous) 64k - 1. Peers might allow less. */
1983 h2_send_rst_stream(r, con, H2_E_INTERNAL_ERROR);
1984 return;
1985 }
1986
1987 /* HTTP/2 requires lowercase keys
1988 * ls-hpack requires key and value be in same buffer
1989 * Since keys are typically short, append (and lowercase) key onto
1990 * end of value buffer, following '\0' after end of value, and
1991 * without modifying ds->value.used or overwriting '\0' */
1992 char * const v =
1993 __builtin_expect( (buffer_string_space(&ds->value) >= klen), 1)
1994 ? ds->value.ptr+vlen+1 /*perf: inline check before call*/
1995 : buffer_string_prepare_append(&ds->value, klen)+1;
1996 if (__builtin_expect( (ds->ext != HTTP_HEADER_OTHER), 1)) {
1997 memcpy(v, http_header_lc[ds->ext], klen);
1998 }
1999 else {
2000 const char * const restrict k = ds->key.ptr;
2001 if ((k[0] & 0xdf) == 'X' && http_response_omit_header(r, ds)) {
2002 alen -= klen + vlen + 4;
2003 continue;
2004 }
2005 for (uint32_t j = 0; j < klen; ++j)
2006 v[j] = !light_isupper(k[j]) ? k[j] : (k[j] | 0x20);
2007 }
2008
2009 uint32_t voff = 0;
2010 const char *n;
2011 lsx.buf = ds->value.ptr;
2012 do {
2013 n = !resp_header_repeated
2014 ? NULL
2015 : memchr(lsx.buf+voff, '\n', vlen - voff);
2016
2017 memset(&lsx, 0, sizeof(lsxpack_header_t));
2018 lsx.hpack_index = http_header_lshpack_idx[ds->ext];
2019 lsx.buf = ds->value.ptr;
2020 lsx.name_offset = vlen+1;
2021 lsx.name_len = klen;
2022 lsx.val_offset = voff;
2023 if (NULL == n)
2024 lsx.val_len = vlen - voff;
2025 else {
2026 /* multiple headers (same field-name) separated by "\r\n"
2027 * and then "field-name: " (see http_header_response_insert())*/
2028 voff = (uint32_t)(n + 1 - lsx.buf);
2029 lsx.val_len = voff - 2 - lsx.val_offset; /*(-2 for "\r\n")*/
2030 voff += klen + 2;
2031 }
2032
2033 if (log_response_header)
2034 h2_log_response_header_lsx(r, &lsx);
2035
2036 unsigned char * const dst_in = dst;
2037 dst = lshpack_enc_encode(encoder, dst, dst_end, &lsx);
2038 if (dst == dst_in) {
2039 h2_send_rst_stream(r, con, H2_E_INTERNAL_ERROR);
2040 return;
2041 }
2042 } while (n);
2043 }
2044
2045 if (!light_btst(r->resp_htags, HTTP_HEADER_DATE)) {
2046 /* HTTP/1.1 and later requires a Date: header */
2047 /* "date: " 6-chars + 30-chars for "%a, %d %b %Y %T GMT" + '\0' */
2048 static unix_time64_t tlast = 0;
2049 static char tstr[36] = "date: ";
2050
2051 memset(&lsx, 0, sizeof(lsxpack_header_t));
2052 lsx.buf = tstr;
2053 lsx.name_offset = 0;
2054 lsx.name_len = 4;
2055 lsx.val_offset = 6;
2056 lsx.val_len = 29;
2057 lsx.hpack_index = LSHPACK_HDR_DATE;
2058
2059 /* cache the generated timestamp */
2060 const unix_time64_t cur_ts = log_epoch_secs;
2061 if (__builtin_expect ( (tlast != cur_ts), 0))
2062 http_date_time_to_str(tstr+6, sizeof(tstr)-6, (tlast = cur_ts));
2063
2064 alen += 35+2;
2065
2066 if (log_response_header)
2067 h2_log_response_header(r, 35, tstr);
2068
2069 unsigned char * const dst_in = dst;
2070 dst = lshpack_enc_encode(encoder, dst, dst_end, &lsx);
2071 if (dst == dst_in) {
2072 h2_send_rst_stream(r, con, H2_E_INTERNAL_ERROR);
2073 return;
2074 }
2075 }
2076
2077 if (!light_btst(r->resp_htags, HTTP_HEADER_SERVER) && r->conf.server_tag) {
2078 buffer * const b = chunk_buffer_acquire();
2079 const uint32_t vlen = buffer_clen(r->conf.server_tag);
2080 buffer_append_str2(b, CONST_STR_LEN("server: "),
2081 r->conf.server_tag->ptr, vlen);
2082
2083 alen += 6+vlen+4;
2084
2085 if (log_response_header)
2086 h2_log_response_header(r, (int)6+vlen+2, b->ptr);
2087
2088 memset(&lsx, 0, sizeof(lsxpack_header_t));
2089 lsx.buf = b->ptr;
2090 lsx.name_offset = 0;
2091 lsx.name_len = 6;
2092 lsx.val_offset = 8;
2093 lsx.val_len = vlen;
2094 lsx.hpack_index = LSHPACK_HDR_SERVER;
2095 unsigned char * const dst_in = dst;
2096 dst = lshpack_enc_encode(encoder, dst, dst_end, &lsx);
2097 chunk_buffer_release(b);
2098 if (dst == dst_in) {
2099 h2_send_rst_stream(r, con, H2_E_INTERNAL_ERROR);
2100 return;
2101 }
2102 }
2103
2104 alen += 2; /* "virtual" blank line ("\r\n") ending headers */
2105 r->resp_header_len = alen;
2106 /*(accounting for mod_accesslog and mod_rrdtool)*/
2107 chunkqueue * const wq = &r->write_queue;
2108 wq->bytes_in += (off_t)alen;
2109 wq->bytes_out += (off_t)alen;
2110
2111 const uint32_t dlen = (uint32_t)((char *)dst - tb->ptr);
2112 const uint32_t flags =
2113 (r->resp_body_finished && chunkqueue_is_empty(&r->write_queue))
2114 ? H2_FLAG_END_STREAM
2115 : 0;
2116 h2_send_hpack(r, con, tb->ptr, dlen, flags);
2117 }
2118
2119
2120 __attribute_cold__
2121 __attribute_noinline__
2122 static void
h2_send_headers_block(request_st * const r,connection * const con,const char * const hdrs,const uint32_t hlen,uint32_t flags)2123 h2_send_headers_block (request_st * const r, connection * const con, const char * const hdrs, const uint32_t hlen, uint32_t flags)
2124 {
2125 unsigned short hoff[8192]; /* max num header lines + 3; 16k on stack */
2126 hoff[0] = 1; /* number of lines */
2127 hoff[1] = 0; /* base offset for all lines */
2128 /*hoff[2] = ...;*/ /* offset from base for 2nd line */
2129 uint32_t rc = http_header_parse_hoff(hdrs, hlen, hoff);
2130 if (0 == rc || rc > USHRT_MAX || hoff[0] >= sizeof(hoff)/sizeof(hoff[0])-1
2131 || 1 == hoff[0]) { /*(initial blank line (should not happen))*/
2132 /* error if headers incomplete or too many header fields */
2133 log_error(r->conf.errh, __FILE__, __LINE__,
2134 "oversized response-header");
2135 hoff[0] = 1;
2136 hoff[1] = 0;
2137 if (http_header_parse_hoff(CONST_STR_LEN(":status: 500\r\n\r\n"),hoff)){
2138 /*(ignore for coverity; static string is successfully parsed)*/
2139 }
2140 }
2141
2142 /*(h2_init_con() resized h2r->tmp_buf to 64k; shared with r->tmp_buf)*/
2143 buffer * const tb = r->tmp_buf;
2144 force_assert(tb->size >= 65536);/*(sanity check; remove in future)*/
2145 unsigned char *dst = (unsigned char *)tb->ptr;
2146 unsigned char * const dst_end = (unsigned char *)tb->ptr + tb->size;
2147
2148 h2con * const h2c = con->h2;
2149 struct lshpack_enc * const encoder = &h2c->encoder;
2150 lsxpack_header_t lsx;
2151
2152 int i = 1;
2153 if (hdrs[0] == ':') {
2154 i = 2;
2155 /* expect first line to contain ":status: ..." if pseudo-header,
2156 * and expecting single pseudo-header for headers, zero for trailers */
2157 /*assert(0 == memcmp(hdrs, ":status: ", sizeof(":status: ")-1));*/
2158 memset(&lsx, 0, sizeof(lsxpack_header_t));
2159 *(const char **)&lsx.buf = hdrs;
2160 lsx.name_offset = 0;
2161 lsx.name_len = sizeof(":status")-1;
2162 lsx.val_offset = lsx.name_len + 2;
2163 lsx.val_len = 3;
2164 dst = lshpack_enc_encode(encoder, dst, dst_end, &lsx);
2165 if (dst == (unsigned char *)tb->ptr) {
2166 h2_send_rst_stream(r, con, H2_E_INTERNAL_ERROR);
2167 return;
2168 }
2169 }
2170
2171 /*(note: not expecting any other pseudo-headers)*/
2172
2173 /* note: expects field-names are lowercased (http_response_write_header())*/
2174
2175 for (; i < hoff[0]; ++i) {
2176 const char *k = hdrs + ((i > 1) ? hoff[i] : 0);
2177 const char *end = hdrs + hoff[i+1];
2178 const char *v = memchr(k, ':', end-k);
2179 /* XXX: DOES NOT handle line wrapping (which is deprecated by RFCs)
2180 * (not expecting line wrapping; not produced internally by lighttpd,
2181 * though possible from backends or with custom lua code)*/
2182 if (NULL == v || k == v) continue;
2183 uint32_t klen = v - k;
2184 if (0 == klen) continue;
2185 do { ++v; } while (*v == ' ' || *v == '\t'); /*(expect single ' ')*/
2186 #ifdef __COVERITY__
2187 /*(k has at least .:\n by now, so end[-2] valid)*/
2188 force_assert(end >= k + 2);
2189 #endif
2190 if (end[-2] != '\r') /*(header line must end "\r\n")*/
2191 continue;
2192 end -= 2;
2193 uint32_t vlen = end - v;
2194 if (0 == vlen) continue;
2195 memset(&lsx, 0, sizeof(lsxpack_header_t));
2196 *(const char **)&lsx.buf = hdrs;
2197 lsx.name_offset = k - hdrs;
2198 lsx.name_len = klen;
2199 lsx.val_offset = v - hdrs;
2200 lsx.val_len = vlen;
2201 unsigned char * const dst_in = dst;
2202 dst = lshpack_enc_encode(encoder, dst, dst_end, &lsx);
2203 if (dst == dst_in) {
2204 h2_send_rst_stream(r, con, H2_E_INTERNAL_ERROR);
2205 return;
2206 }
2207 }
2208 uint32_t dlen = (uint32_t)((char *)dst - tb->ptr);
2209 h2_send_hpack(r, con, tb->ptr, dlen, flags);
2210 }
2211
2212
2213 static void
h2_send_1xx_block(request_st * const r,connection * const con,const char * const hdrs,const uint32_t hlen)2214 h2_send_1xx_block (request_st * const r, connection * const con, const char * const hdrs, const uint32_t hlen)
2215 {
2216 h2_send_headers_block(r, con, hdrs, hlen, 0);
2217 }
2218
2219
2220 int
h2_send_1xx(request_st * const r,connection * const con)2221 h2_send_1xx (request_st * const r, connection * const con)
2222 {
2223 buffer * const b = chunk_buffer_acquire();
2224
2225 buffer_copy_string_len(b, CONST_STR_LEN(":status: "));
2226 buffer_append_int(b, r->http_status);
2227 for (uint32_t i = 0; i < r->resp_headers.used; ++i) {
2228 const data_string * const ds = (data_string *)r->resp_headers.data[i];
2229 const uint32_t klen = buffer_clen(&ds->key);
2230 const uint32_t vlen = buffer_clen(&ds->value);
2231 if (0 == klen || 0 == vlen) continue;
2232 buffer_append_str2(b, CONST_STR_LEN("\r\n"), ds->key.ptr, klen);
2233 buffer_append_str2(b, CONST_STR_LEN(": "), ds->value.ptr, vlen);
2234 }
2235 buffer_append_string_len(b, CONST_STR_LEN("\r\n\r\n"));
2236
2237 h2_send_1xx_block(r, con, BUF_PTR_LEN(b));
2238
2239 chunk_buffer_release(b);
2240 return 1; /* for http_response_send_1xx_cb */
2241 }
2242
2243
2244 void
h2_send_100_continue(request_st * const r,connection * const con)2245 h2_send_100_continue (request_st * const r, connection * const con)
2246 {
2247 /* 100 Continue is small and will always fit in SETTING_MAX_FRAME_SIZE;
2248 * i.e. there will not be any CONTINUATION frames here */
2249
2250 /* XXX: need to update hpack dynamic table,
2251 * or else could hard-code header block fragment
2252 * { 0x48, 0x03, 0x31, 0x30, 0x30 }
2253 */
2254
2255 /* short header block, so reuse shared code used for trailers
2256 * rather than adding something specific for ls-hpack here */
2257
2258 h2_send_1xx_block(r, con, CONST_STR_LEN(":status: 100\r\n\r\n"));
2259 }
2260
2261
2262 static void
2263 h2_send_end_stream_data (request_st * const r, connection * const con);
2264
2265 __attribute_cold__
2266 __attribute_noinline__
2267 static void
h2_send_end_stream_trailers(request_st * const r,connection * const con,const buffer * const trailers)2268 h2_send_end_stream_trailers (request_st * const r, connection * const con, const buffer * const trailers)
2269 {
2270 /*(trailers are merged into response headers if trailers are received before
2271 * sending response headers to client. However, if streaming response, then
2272 * trailers might need handling here)*/
2273
2274 /* parse and lowercase field-names in trailers */
2275 unsigned short hoff[8192]; /* max num header lines + 3; 16k on stack */
2276 hoff[0] = 1; /* number of lines */
2277 hoff[1] = 0; /* base offset for all lines */
2278 /*hoff[2] = ...;*/ /* offset from base for 2nd line */
2279 uint32_t rc = http_header_parse_hoff(BUF_PTR_LEN(trailers), hoff);
2280 if (0 == rc || rc > USHRT_MAX || hoff[0] >= sizeof(hoff)/sizeof(hoff[0])-1
2281 || 1 == hoff[0]) { /*(initial blank line)*/
2282 /* skip trailers if incomplete, too many fields, or too long (> 64k-1)*/
2283 h2_send_end_stream_data(r, con);
2284 return;
2285 }
2286
2287 char * const ptr = trailers->ptr;
2288 for (int i = 1; i < hoff[0]; ++i) {
2289 char *k = ptr + ((i > 1) ? hoff[i] : 0);
2290 if (*k == ':') {
2291 /*(pseudo-header should not appear in trailers)*/
2292 h2_send_end_stream_data(r, con);
2293 return;
2294 }
2295 const char * const colon = memchr(k, ':', ptr+hoff[i+1]-k);
2296 if (NULL == colon) continue;
2297 do {
2298 if (light_isupper(*k)) *k |= 0x20;
2299 } while (++k != colon);
2300 }
2301
2302 h2_send_headers_block(r, con, BUF_PTR_LEN(trailers), H2_FLAG_END_STREAM);
2303 }
2304
2305
2306 #if 0 /*(replaced by h2_send_headers())*/
2307 void
2308 h2_send_cqheaders (request_st * const r, connection * const con)
2309 {
2310 /*(assumes HTTP/1.1 response headers have been prepended as first chunk)
2311 *(future: if r->write_queue is bypassed for headers, adjust
2312 * r->write_queue bytes counts (bytes_in, bytes_out) with header len)*/
2313 /* note: expects field-names are lowercased (http_response_write_header())*/
2314 chunk * const c = r->write_queue.first;
2315 const uint32_t len = buffer_clen(c->mem) - (uint32_t)c->offset;
2316 uint32_t flags = (r->resp_body_finished && NULL == c->next)
2317 ? H2_FLAG_END_STREAM
2318 : 0;
2319 h2_send_headers_block(r, con, c->mem->ptr + c->offset, len, flags);
2320 chunkqueue_mark_written(&r->write_queue, len);
2321 }
2322 #endif
2323
2324
2325 #if 0
2326
2327 uint32_t
2328 h2_send_data (request_st * const r, connection * const con, const char *data, uint32_t dlen)
2329 {
2330 /* Note: dlen should be <= MAX_WRITE_LIMIT in order to share resources */
2331
2332 union {
2333 uint8_t c[12];
2334 uint32_t u[3]; /*(alignment)*/
2335 } dataframe = { { /*(big-endian numbers)*/
2336 0x00, 0x00, 0x00 /* padding for alignment; do not send */
2337 /* DATA */
2338 ,0x00, 0x00, 0x00 /* frame length (fill in below) */
2339 ,H2_FTYPE_DATA /* frame type */
2340 ,0x00 /* frame flags */
2341 ,0x00, 0x00, 0x00, 0x00 /* stream identifier (fill in below) */
2342 } };
2343
2344 dataframe.u[2] = htonl(r->h2id);
2345
2346 /* XXX: does not provide an optimization to send final set of data with
2347 * END_STREAM flag; see h2_send_end_stream_data() to end stream */
2348
2349 /* adjust stream and connection windows */
2350 /*assert(dlen <= INT32_MAX);*//* dlen should be <= MAX_WRITE_LIMIT */
2351 request_st * const h2r = &con->request;
2352 if (r->h2_swin < 0) return 0;
2353 if (h2r->h2_swin < 0) return 0;
2354 if ((int32_t)dlen > r->h2_swin) dlen = (uint32_t)r->h2_swin;
2355 if ((int32_t)dlen > h2r->h2_swin) dlen = (uint32_t)h2r->h2_swin;
2356 if (0 == dlen) return 0;
2357 r->h2_swin -= (int32_t)dlen;
2358 h2r->h2_swin -= (int32_t)dlen;
2359
2360 /* XXX: future: should have an interface which processes chunkqueue
2361 * and takes string refs to mmap FILE_CHUNK to avoid extra copying
2362 * since the result is likely to be consumed by TLS modules */
2363
2364 /*(approximate space needed for frames (header + payload)
2365 * with slight over-estimate of 16 bytes per frame header (> 9)
2366 * and minimum SETTING_MAX_FRAME_SIZE of 16k (could be larger)
2367 * (dlen >> 14)+1 is num 16k frames needed, multipled by 16 bytes
2368 * per frame can be appoximated with (dlen>>10) + 9)*/
2369 buffer * const b =
2370 chunkqueue_append_buffer_open_sz(con->write_queue, dlen + (dlen>>10) + 9);
2371 char * restrict ptr = b->ptr;
2372 h2con * const h2c = con->h2;
2373 const uint32_t fsize = h2c->s_max_frame_size;
2374 uint32_t sent = 0;
2375 do {
2376 const uint32_t len = dlen < fsize ? dlen : fsize;
2377 dataframe.c[3] = (len >> 16) & 0xFF; /*(off +3 to skip over align pad)*/
2378 dataframe.c[4] = (len >> 8) & 0xFF;
2379 dataframe.c[5] = (len ) & 0xFF;
2380 #if 0
2381 chunkqueue_append_mem(con->write_queue, /*(+3 to skip over align pad)*/
2382 (const char *)dataframe.c+3, sizeof(dataframe)-3);
2383 chunkqueue_append_mem(con->write_queue, data, len);
2384 #else
2385 memcpy(ptr, dataframe.c+3, sizeof(dataframe)-3);
2386 memcpy(ptr+sizeof(dataframe)-3, data, len);
2387 ptr += len + sizeof(dataframe)-3;
2388 #endif
2389 data += len;
2390 sent += len;
2391 dlen -= len;
2392 } while (dlen);
2393 buffer_truncate(b, (uint32_t)(ptr - b->ptr));
2394 chunkqueue_append_buffer_commit(con->write_queue);
2395 return sent;
2396 }
2397
2398 #endif
2399
2400
2401 uint32_t
h2_send_cqdata(request_st * const r,connection * const con,chunkqueue * const cq,uint32_t dlen)2402 h2_send_cqdata (request_st * const r, connection * const con, chunkqueue * const cq, uint32_t dlen)
2403 {
2404 /* Note: dlen should be <= MAX_WRITE_LIMIT in order to share resources */
2405
2406 union {
2407 uint8_t c[12];
2408 uint32_t u[3]; /*(alignment)*/
2409 } dataframe = { { /*(big-endian numbers)*/
2410 0x00, 0x00, 0x00 /* padding for alignment; do not send */
2411 /* DATA */
2412 ,0x00, 0x00, 0x00 /* frame length (fill in below) */
2413 ,H2_FTYPE_DATA /* frame type */
2414 ,0x00 /* frame flags */
2415 ,0x00, 0x00, 0x00, 0x00 /* stream identifier (fill in below) */
2416 } };
2417
2418 dataframe.u[2] = htonl(r->h2id);
2419
2420 /* XXX: does not provide an optimization to send final set of data with
2421 * END_STREAM flag; see h2_send_end_stream_data() to end stream */
2422
2423 /* adjust stream and connection windows */
2424 /*assert(dlen <= INT32_MAX);*//* dlen should be <= MAX_WRITE_LIMIT */
2425 request_st * const h2r = &con->request;
2426 if (r->h2_swin < 0) return 0;
2427 if (h2r->h2_swin < 0) return 0;
2428 if ((int32_t)dlen > r->h2_swin) dlen = (uint32_t)r->h2_swin;
2429 if ((int32_t)dlen > h2r->h2_swin) dlen = (uint32_t)h2r->h2_swin;
2430 const uint32_t cqlen = (uint32_t)chunkqueue_length(cq);
2431 if (dlen > cqlen) dlen = cqlen;
2432 if (0 == dlen) return 0;
2433
2434 /* XXX: future: should have an interface which processes chunkqueue
2435 * and takes string refs to mmap FILE_CHUNK to avoid extra copying
2436 * since the result is likely to be consumed by TLS modules */
2437
2438 h2con * const h2c = con->h2;
2439 const uint32_t fsize = h2c->s_max_frame_size;
2440 uint32_t sent = 0;
2441 do {
2442 if (cq->first->type == FILE_CHUNK) {
2443 /* combine frame header and data into single mem chunk buffer
2444 * and adjust to fit efficiently into power-2 sized buffer
2445 * (default and minimum HTTP/2 SETTINGS_MAX_FRAME_SIZE is 16k)
2446 * (default send buffer size in lighttpd TLS modules is 16k)
2447 * (read into memory since likely needed for HTTP/2 over TLS,
2448 * and to avoid many small calls to dup(), sendfile(), close())
2449 * (reading here into single chunk buffer is likely more efficient
2450 * than reference counting file chunks split and duplicated by
2451 * chunkqueue_steal() into 16k chunks, and alternating with 8k
2452 * chunk buffers containing 9 byte HTTP/2 header frame) */
2453 const uint32_t len = dlen < fsize ? dlen : fsize-9;
2454 uint32_t blen = len;
2455 buffer * const b = /*(sizeof(dataframe)-3 == 9)*/
2456 chunkqueue_append_buffer_open_sz(con->write_queue, 9+len);
2457 char *data = b->ptr+9; /*(note: not including +1 to _open_sz)*/
2458 if (0 == chunkqueue_peek_data(cq, &data, &blen, r->conf.errh)
2459 && blen == len) {
2460 dlen -= len;
2461 sent += len;
2462 dataframe.c[3] = (len >> 16) & 0xFF; /*(+3 to skip align pad)*/
2463 dataframe.c[4] = (len >> 8) & 0xFF;
2464 dataframe.c[5] = (len ) & 0xFF;
2465 memcpy(b->ptr,(const char *)dataframe.c+3, sizeof(dataframe)-3);
2466 if (b->ptr+9 != data)
2467 memcpy(b->ptr+9, data, len);
2468 buffer_commit(b, 9+len);
2469 chunkqueue_append_buffer_commit(con->write_queue);
2470 chunkqueue_mark_written(cq, len);
2471 continue;
2472 }
2473
2474 /*(else remove empty last chunk and fall through to below)*/
2475 chunkqueue_remove_empty_chunks(cq);
2476 }
2477
2478 const uint32_t len = dlen < fsize ? dlen : fsize;
2479 dlen -= len;
2480 sent += len;
2481 dataframe.c[3] = (len >> 16) & 0xFF; /*(off +3 to skip over align pad)*/
2482 dataframe.c[4] = (len >> 8) & 0xFF;
2483 dataframe.c[5] = (len ) & 0xFF;
2484 chunkqueue_append_mem(con->write_queue, /*(+3 to skip over align pad)*/
2485 (const char *)dataframe.c+3, sizeof(dataframe)-3);
2486 chunkqueue_steal(con->write_queue, cq, (off_t)len);
2487 } while (dlen);
2488 r->h2_swin -= (int32_t)sent;
2489 h2r->h2_swin -= (int32_t)sent;
2490 return sent;
2491 }
2492
2493
2494 static void
h2_send_end_stream_data(request_st * const r,connection * const con)2495 h2_send_end_stream_data (request_st * const r, connection * const con)
2496 {
2497 union {
2498 uint8_t c[12];
2499 uint32_t u[3]; /*(alignment)*/
2500 } dataframe = { { /*(big-endian numbers)*/
2501 0x00, 0x00, 0x00 /* padding for alignment; do not send */
2502 /* DATA */
2503 ,0x00, 0x00, 0x00 /* frame length */
2504 ,H2_FTYPE_DATA /* frame type */
2505 ,H2_FLAG_END_STREAM /* frame flags */
2506 ,0x00, 0x00, 0x00, 0x00 /* stream identifier (fill in below) */
2507 } };
2508
2509 dataframe.u[2] = htonl(r->h2id);
2510 /*(ignore window updates when sending 0-length DATA frame with END_STREAM)*/
2511 chunkqueue_append_mem(con->write_queue, /*(+3 to skip over align pad)*/
2512 (const char *)dataframe.c+3, sizeof(dataframe)-3);
2513
2514 if (r->h2state != H2_STATE_HALF_CLOSED_REMOTE) {
2515 /* set timestamp for comparison; not tracking individual stream ids */
2516 h2con * const h2c = con->h2;
2517 h2c->half_closed_ts = log_monotonic_secs;
2518 /* indicate to peer that no more DATA should be sent from peer */
2519 h2_send_rst_stream_id(r->h2id, con, H2_E_NO_ERROR);
2520 }
2521 r->h2state = H2_STATE_CLOSED;
2522 }
2523
2524
2525 void
h2_send_end_stream(request_st * const r,connection * const con)2526 h2_send_end_stream (request_st * const r, connection * const con)
2527 {
2528 if (r->h2state == H2_STATE_CLOSED) return;
2529 if (r->state != CON_STATE_ERROR && r->resp_body_finished) {
2530 /* CON_STATE_RESPONSE_END */
2531 if (r->gw_dechunk && r->gw_dechunk->done
2532 && !buffer_is_unset(&r->gw_dechunk->b))
2533 h2_send_end_stream_trailers(r, con, &r->gw_dechunk->b);
2534 else
2535 h2_send_end_stream_data(r, con);
2536 }
2537 else { /* CON_STATE_ERROR */
2538 h2_send_rst_stream(r, con, H2_E_INTERNAL_ERROR);
2539 }
2540 }
2541
2542
2543 /*
2544 * (XXX: might move below to separate file)
2545 */
2546 #include "base64.h"
2547 #include "chunk.h"
2548 #include "plugin.h"
2549 #include "plugin_config.h"
2550 #include "reqpool.h"
2551
2552
2553 static request_st *
h2_init_stream(request_st * const h2r,connection * const con)2554 h2_init_stream (request_st * const h2r, connection * const con)
2555 {
2556 h2con * const h2c = con->h2;
2557 ++con->request_count;
2558 force_assert(h2c->rused < sizeof(h2c->r)/sizeof(*h2c->r));
2559 /* initialize stream as subrequest (request_st *) */
2560 request_st * const r = request_acquire(con);
2561 /* XXX: TODO: assign default priority, etc.
2562 * Perhaps store stream id and priority in separate table */
2563 h2c->r[h2c->rused++] = r;
2564 r->h2_rwin = 65535; /* must keep in sync with h2_init_con() */
2565 r->h2_swin = h2c->s_initial_window_size;
2566 r->http_version = HTTP_VERSION_2;
2567
2568 /* copy config state from h2r */
2569 server * const srv = con->srv;
2570 const uint32_t used = srv->config_context->used;
2571 r->conditional_is_valid = h2r->conditional_is_valid;
2572 memcpy(r->cond_cache, h2r->cond_cache, used * sizeof(cond_cache_t));
2573 #ifdef HAVE_PCRE
2574 if (srv->config_captures)
2575 memcpy(r->cond_match, h2r->cond_match,
2576 srv->config_captures * sizeof(cond_match_t *));
2577 #endif
2578 /*(see request_config_reset() and request_reset_ex())*/
2579 r->server_name = h2r->server_name;
2580 memcpy(&r->conf, &h2r->conf, sizeof(request_config));
2581
2582 /* stream id must be assigned by caller */
2583 return r;
2584 }
2585
2586
2587 static void
h2_release_stream(request_st * const r,connection * const con)2588 h2_release_stream (request_st * const r, connection * const con)
2589 {
2590 if (r->http_status) {
2591 /* (see comment in connection_handle_response_end_state()) */
2592 plugins_call_handle_request_done(r);
2593
2594 #if 0
2595 /* (fuzzy accounting for mod_accesslog, mod_rrdtool to avoid
2596 * double counting, but HTTP/2 framing and HPACK-encoded headers in
2597 * con->read_queue and con->write_queue are not equivalent to the
2598 * HPACK-decoded headers and request and response bodies in stream
2599 * r->read_queue and r->write_queue) */
2600 /* DISABLED since mismatches invalidate the relationship between
2601 * con->bytes_in and con->bytes_out */
2602 con->read_queue->bytes_in -= r->read_queue.bytes_in;
2603 con->write_queue->bytes_out -= r->write_queue.bytes_out;
2604 #else
2605 UNUSED(con);
2606 #endif
2607 }
2608
2609 request_release(r);
2610 }
2611
2612
2613 void
h2_retire_stream(request_st * r,connection * const con)2614 h2_retire_stream (request_st *r, connection * const con)
2615 {
2616 if (r == NULL) return; /*(should not happen)*/
2617 h2con * const h2c = con->h2;
2618 request_st ** const ar = h2c->r;
2619 uint32_t i = 0, rused = h2c->rused;
2620 while (i < rused && ar[i] != r) ++i;
2621 if (i != rused) {
2622 /* swap with last element; might need to revisit if ordered by priority */
2623 /*if (i != --rused) ar[i] = ar[rused];*/
2624 /* shift elements; currently choosing to preserve order requested */
2625 if (i != --rused) memmove(ar+i, ar+i+1, (rused-i)*sizeof(*ar));
2626 h2c->r[(h2c->rused = rused)] = NULL;
2627 h2_release_stream(r, con);
2628 }
2629 /*else ... should not happen*/
2630 }
2631
2632
2633 void
h2_retire_con(request_st * const h2r,connection * const con)2634 h2_retire_con (request_st * const h2r, connection * const con)
2635 {
2636 h2con * const h2c = con->h2;
2637 if (NULL == h2c) return;
2638
2639 if (h2r->state != CON_STATE_ERROR) { /*(CON_STATE_RESPONSE_END)*/
2640 h2_send_goaway(con, H2_E_NO_ERROR);
2641 for (uint32_t i = 0, rused = h2c->rused; i < rused; ++i) {
2642 /*(unexpected if CON_STATE_RESPONSE_END)*/
2643 request_st * const r = h2c->r[i];
2644 h2_send_rst_stream(r, con, H2_E_INTERNAL_ERROR);
2645 h2_release_stream(r, con);
2646 }
2647 if (!chunkqueue_is_empty(con->write_queue)) {
2648 /* similar to connection_handle_write() but without error checks,
2649 * without MAX_WRITE_LIMIT, and without connection throttling */
2650 /*h2r->conf.bytes_per_second = 0;*/ /* disable rate limit */
2651 /*h2r->conf.global_bytes_per_second = 0;*/ /* disable rate limit */
2652 /*con->traffic_limit_reached = 0;*/
2653 chunkqueue * const cq = con->write_queue;
2654 const off_t len = chunkqueue_length(cq);
2655 off_t written = cq->bytes_out;
2656 con->network_write(con, cq, len);
2657 /*(optional accounting)*/
2658 written = cq->bytes_out - written;
2659 con->bytes_written += written;
2660 con->bytes_written_cur_second += written;
2661 if (h2r->conf.global_bytes_per_second_cnt_ptr)
2662 *(h2r->conf.global_bytes_per_second_cnt_ptr) += written;
2663 }
2664 }
2665 else { /* CON_STATE_ERROR */
2666 for (uint32_t i = 0, rused = h2c->rused; i < rused; ++i) {
2667 request_st * const r = h2c->r[i];
2668 h2_release_stream(r, con);
2669 }
2670 /* XXX: perhaps attempt to send GOAWAY? Not when CON_STATE_ERROR */
2671 }
2672
2673 con->h2 = NULL;
2674
2675 /* future: might keep a pool of reusable (h2con *) */
2676 lshpack_enc_cleanup(&h2c->encoder);
2677 lshpack_dec_cleanup(&h2c->decoder);
2678 free(h2c);
2679 }
2680
2681
2682 static void
h2_con_upgrade_h2c(request_st * const h2r,const buffer * const http2_settings)2683 h2_con_upgrade_h2c (request_st * const h2r, const buffer * const http2_settings)
2684 {
2685 /* status: (h2r->state == CON_STATE_REQUEST_END) for Upgrade: h2c */
2686
2687 /* HTTP/1.1 101 Switching Protocols
2688 * Connection: Upgrade
2689 * Upgrade: h2c
2690 */
2691 #if 1
2692 static const char switch_proto[] = "HTTP/1.1 101 Switching Protocols\r\n"
2693 "Connection: Upgrade\r\n"
2694 "Upgrade: h2c\r\n\r\n";
2695 chunkqueue_append_mem(&h2r->write_queue,
2696 CONST_STR_LEN(switch_proto));
2697 h2r->resp_header_len = sizeof(switch_proto)-1;
2698 #else
2699 h2r->http_status = 101;
2700 http_header_response_set(h2r, HTTP_HEADER_UPGRADE, CONST_STR_LEN("Upgrade"),
2701 CONST_STR_LEN("h2c"));
2702 http_response_write_header(h2r);
2703 http_response_reset(h2r);
2704 h2r->http_status = 0;
2705 #endif
2706
2707 connection * const con = h2r->con;
2708 h2_init_con(h2r, con, http2_settings);
2709 if (con->h2->sent_goaway) return;
2710
2711 con->h2->h2_cid = 1; /* stream id 1 is assigned to h2c upgrade */
2712
2713 /* copy request state from &con->request to subrequest r
2714 * XXX: would be nice if there were a cleaner way to do this
2715 * (This is fragile and must be kept in-sync with request_st in request.h)*/
2716
2717 request_st * const r = h2_init_stream(h2r, con);
2718 /*(undo double-count; already incremented in CON_STATE_REQUEST_START)*/
2719 --con->request_count;
2720 r->state = h2r->state; /* CON_STATE_REQUEST_END */
2721 r->http_status = 0;
2722 r->http_method = h2r->http_method;
2723 r->h2state = H2_STATE_HALF_CLOSED_REMOTE;
2724 r->h2id = 1;
2725 r->rqst_htags = h2r->rqst_htags;
2726 h2r->rqst_htags = 0;
2727 r->rqst_header_len = h2r->rqst_header_len;
2728 h2r->rqst_header_len = 0;
2729 r->rqst_headers = h2r->rqst_headers; /* copy struct */
2730 memset(&h2r->rqst_headers, 0, sizeof(array));
2731 r->uri = h2r->uri; /* copy struct */
2732 #if 0
2733 r->physical = h2r->physical; /* copy struct */
2734 r->env = h2r->env; /* copy struct */
2735 #endif
2736 memset(&h2r->rqst_headers, 0, sizeof(array));
2737 memset(&h2r->uri, 0, sizeof(request_uri));
2738 #if 0
2739 memset(&h2r->physical, 0, sizeof(physical));
2740 memset(&h2r->env, 0, sizeof(array));
2741 #endif
2742 #if 0 /* expect empty request body */
2743 r->reqbody_length = h2r->reqbody_length; /* currently always 0 */
2744 r->te_chunked = h2r->te_chunked; /* must be 0 */
2745 r->resp_body_scratchpad = h2r->resp_body_scratchpad; /*(not started yet)*/
2746 swap(&r->reqbody_queue,&h2r->reqbody_queue);/*currently always empty queue*/
2747 #endif
2748 r->http_host = h2r->http_host;
2749 h2r->http_host = NULL;
2750 #if 0
2751 r->server_name = h2r->server_name;
2752 h2r->server_name = &h2r->uri.authority; /*(is not null)*/
2753 #endif
2754 r->target = h2r->target; /* copy struct */
2755 r->target_orig = h2r->target_orig; /* copy struct */
2756 #if 0
2757 r->pathinfo = h2r->pathinfo; /* copy struct */
2758 r->server_name_buf = h2r->server_name_buf; /* copy struct */
2759 #endif
2760 memset(&h2r->target, 0, sizeof(buffer));
2761 memset(&h2r->target_orig, 0, sizeof(buffer));
2762 #if 0
2763 memset(&h2r->pathinfo, 0, sizeof(buffer));
2764 memset(&h2r->server_name_buf, 0, sizeof(buffer));
2765 #endif
2766 #if 0
2767 /* skip copying response structures, other state not yet modified in h2r */
2768 /* r write_queue and read_queue are intentionally separate from h2r */
2769 /* r->gw_dechunk must be NULL for HTTP/2 */
2770 /* bytes_written_ckpt and bytes_read_ckpt are for HTTP/1.1 */
2771 /* error handlers have not yet been set */
2772 #endif
2773 #if 0
2774 r->loops_per_request = h2r->loops_per_request;
2775 r->async_callback = h2r->async_callback;
2776 #endif
2777 r->keep_alive = h2r->keep_alive;
2778 r->tmp_buf = h2r->tmp_buf; /* shared; same as srv->tmp_buf */
2779 r->start_hp = h2r->start_hp; /* copy struct */
2780
2781 /* Note: HTTP/1.1 101 Switching Protocols is not immediately written to
2782 * the network here. As this is called from cleartext Upgrade: h2c,
2783 * we choose to delay sending the status until the beginning of the response
2784 * to the HTTP/1.1 request which included Upgrade: h2c */
2785 }
2786
2787
2788 int
h2_check_con_upgrade_h2c(request_st * const r)2789 h2_check_con_upgrade_h2c (request_st * const r)
2790 {
2791 /* RFC7540 3.2 Starting HTTP/2 for "http" URIs */
2792
2793 buffer *http_connection, *http2_settings;
2794 buffer *upgrade = http_header_request_get(r, HTTP_HEADER_UPGRADE,
2795 CONST_STR_LEN("Upgrade"));
2796 if (NULL == upgrade) return 0;
2797 http_connection = http_header_request_get(r, HTTP_HEADER_CONNECTION,
2798 CONST_STR_LEN("Connection"));
2799 if (NULL == http_connection) {
2800 http_header_request_unset(r, HTTP_HEADER_UPGRADE,
2801 CONST_STR_LEN("Upgrade"));
2802 return 0;
2803 }
2804 if (r->http_version != HTTP_VERSION_1_1) {
2805 http_header_request_unset(r, HTTP_HEADER_UPGRADE,
2806 CONST_STR_LEN("Upgrade"));
2807 http_header_remove_token(http_connection, CONST_STR_LEN("Upgrade"));
2808 return 0;
2809 }
2810
2811 if (!http_header_str_contains_token(BUF_PTR_LEN(upgrade),
2812 CONST_STR_LEN("h2c")))
2813 return 0;
2814
2815 http2_settings = http_header_request_get(r, HTTP_HEADER_HTTP2_SETTINGS,
2816 CONST_STR_LEN("HTTP2-Settings"));
2817 if (NULL != http2_settings) {
2818 if (0 == r->reqbody_length) {
2819 buffer * const b = r->tmp_buf;
2820 buffer_clear(b);
2821 if (r->conf.h2proto > 1/*(must be enabled with server.h2c feature)*/
2822 && !r->con->is_ssl_sock /*(disallow h2c over TLS socket)*/
2823 &&
2824 http_header_str_contains_token(BUF_PTR_LEN(http_connection),
2825 CONST_STR_LEN("HTTP2-Settings"))
2826 && buffer_append_base64_decode(b, BUF_PTR_LEN(http2_settings),
2827 BASE64_URL)) {
2828 h2_con_upgrade_h2c(r, b);
2829 r->http_version = HTTP_VERSION_2;
2830 } /* else ignore if invalid base64 */
2831 }
2832 else {
2833 /* ignore Upgrade: h2c if request body present since we do not
2834 * (currently) handle request body before transition to h2c */
2835 /* RFC7540 3.2 Requests that contain a payload body MUST be sent
2836 * in their entirety before the client can send HTTP/2 frames. */
2837 }
2838 http_header_request_unset(r, HTTP_HEADER_HTTP2_SETTINGS,
2839 CONST_STR_LEN("HTTP2-Settings"));
2840 http_header_remove_token(http_connection, CONST_STR_LEN("HTTP2-Settings"));
2841 } /* else ignore Upgrade: h2c; HTTP2-Settings required for Upgrade: h2c */
2842 http_header_request_unset(r, HTTP_HEADER_UPGRADE,
2843 CONST_STR_LEN("Upgrade"));
2844 http_header_remove_token(http_connection, CONST_STR_LEN("Upgrade"));
2845 return (r->http_version == HTTP_VERSION_2);
2846 }
2847