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