1 /*
2 MIT License
3 
4 Copyright (c) 2018 - 2021 LiteSpeed Technologies Inc
5 
6 Permission is hereby granted, free of charge, to any person obtaining a copy
7 of this software and associated documentation files (the "Software"), to deal
8 in the Software without restriction, including without limitation the rights
9 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 copies of the Software, and to permit persons to whom the Software is
11 furnished to do so, subject to the following conditions:
12 
13 The above copyright notice and this permission notice shall be included in all
14 copies or substantial portions of the Software.
15 
16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 SOFTWARE.
23 */
24 
25 #ifndef LITESPEED_HPACK_H
26 #define LITESPEED_HPACK_H 1
27 
28 #ifdef __cplusplus
29 extern "C" {
30 #endif
31 
32 #include <limits.h>
33 #include <stdint.h>
34 #include "lsxpack_header.h"
35 
36 #define LSHPACK_MAJOR_VERSION 2
37 #define LSHPACK_MINOR_VERSION 3
38 #define LSHPACK_PATCH_VERSION 0
39 
40 #define lshpack_strlen_t lsxpack_strlen_t
41 #define LSHPACK_MAX_STRLEN LSXPACK_MAX_STRLEN
42 
43 /*(lighttpd customization)*/
44 /* decoder provides "field-name: value\r\n"; define to 0 to omit ": ", "\r\n" */
45 #define LSHPACK_DEC_HTTP1X_OUTPUT 0
46 /* decoder provides hash values for request fields; define to 0 to skip */
47 /* (future: might be useful to lighttpd if lighttpd reverse-proxy (mod_proxy)
48  *  were to support HTTP/2 requests to backends, which is not currently done) */
49 #define LSHPACK_DEC_CALC_HASH 0
50 
51 #ifndef LSHPACK_DEC_HTTP1X_OUTPUT
52 #define LSHPACK_DEC_HTTP1X_OUTPUT 1
53 #endif
54 #ifndef LSHPACK_DEC_CALC_HASH
55 #define LSHPACK_DEC_CALC_HASH 1
56 #endif
57 
58 struct lshpack_enc;
59 struct lshpack_dec;
60 
61 enum lshpack_static_hdr_idx
62 {
63     LSHPACK_HDR_UNKNOWN,
64     LSHPACK_HDR_AUTHORITY,
65     LSHPACK_HDR_METHOD_GET,
66     LSHPACK_HDR_METHOD_POST,
67     LSHPACK_HDR_PATH,
68     LSHPACK_HDR_PATH_INDEX_HTML,
69     LSHPACK_HDR_SCHEME_HTTP,
70     LSHPACK_HDR_SCHEME_HTTPS,
71     LSHPACK_HDR_STATUS_200,
72     LSHPACK_HDR_STATUS_204,
73     LSHPACK_HDR_STATUS_206,
74     LSHPACK_HDR_STATUS_304,
75     LSHPACK_HDR_STATUS_400,
76     LSHPACK_HDR_STATUS_404,
77     LSHPACK_HDR_STATUS_500,
78     LSHPACK_HDR_ACCEPT_CHARSET,
79     LSHPACK_HDR_ACCEPT_ENCODING,
80     LSHPACK_HDR_ACCEPT_LANGUAGE,
81     LSHPACK_HDR_ACCEPT_RANGES,
82     LSHPACK_HDR_ACCEPT,
83     LSHPACK_HDR_ACCESS_CONTROL_ALLOW_ORIGIN,
84     LSHPACK_HDR_AGE,
85     LSHPACK_HDR_ALLOW,
86     LSHPACK_HDR_AUTHORIZATION,
87     LSHPACK_HDR_CACHE_CONTROL,
88     LSHPACK_HDR_CONTENT_DISPOSITION,
89     LSHPACK_HDR_CONTENT_ENCODING,
90     LSHPACK_HDR_CONTENT_LANGUAGE,
91     LSHPACK_HDR_CONTENT_LENGTH,
92     LSHPACK_HDR_CONTENT_LOCATION,
93     LSHPACK_HDR_CONTENT_RANGE,
94     LSHPACK_HDR_CONTENT_TYPE,
95     LSHPACK_HDR_COOKIE,
96     LSHPACK_HDR_DATE,
97     LSHPACK_HDR_ETAG,
98     LSHPACK_HDR_EXPECT,
99     LSHPACK_HDR_EXPIRES,
100     LSHPACK_HDR_FROM,
101     LSHPACK_HDR_HOST,
102     LSHPACK_HDR_IF_MATCH,
103     LSHPACK_HDR_IF_MODIFIED_SINCE,
104     LSHPACK_HDR_IF_NONE_MATCH,
105     LSHPACK_HDR_IF_RANGE,
106     LSHPACK_HDR_IF_UNMODIFIED_SINCE,
107     LSHPACK_HDR_LAST_MODIFIED,
108     LSHPACK_HDR_LINK,
109     LSHPACK_HDR_LOCATION,
110     LSHPACK_HDR_MAX_FORWARDS,
111     LSHPACK_HDR_PROXY_AUTHENTICATE,
112     LSHPACK_HDR_PROXY_AUTHORIZATION,
113     LSHPACK_HDR_RANGE,
114     LSHPACK_HDR_REFERER,
115     LSHPACK_HDR_REFRESH,
116     LSHPACK_HDR_RETRY_AFTER,
117     LSHPACK_HDR_SERVER,
118     LSHPACK_HDR_SET_COOKIE,
119     LSHPACK_HDR_STRICT_TRANSPORT_SECURITY,
120     LSHPACK_HDR_TRANSFER_ENCODING,
121     LSHPACK_HDR_USER_AGENT,
122     LSHPACK_HDR_VARY,
123     LSHPACK_HDR_VIA,
124     LSHPACK_HDR_WWW_AUTHENTICATE,
125     LSHPACK_HDR_TOBE_INDEXED = 255
126 };
127 
128 #define LSHPACK_MAX_INDEX           61
129 
130 #define LSHPACK_ERR_MORE_BUF        (-3)
131 #define LSHPACK_ERR_TOO_LARGE       (-2)
132 #define LSHPACK_ERR_BAD_DATA        (-1)
133 #define LSHPACK_OK                  (0)
134 
135 /**
136  * Initialization routine allocates memory.  -1 is returned if memory
137  * could not be allocated.  0 is returned on success.
138  */
139 int
140 lshpack_enc_init (struct lshpack_enc *);
141 
142 /**
143  * Clean up HPACK encoder, freeing all allocated memory.
144  */
145 void
146 lshpack_enc_cleanup (struct lshpack_enc *);
147 
148 /**
149  * @brief Encode one name/value pair
150  *
151  * @param[in,out] henc - A pointer to a valid HPACK API struct
152  * @param[out] dst - A pointer to destination buffer
153  * @param[out] dst_end - A pointer to end of destination buffer
154  * @param[in] input - Header to encode
155  *
156  * @return The (possibly advanced) dst pointer.  If the destination
157  * pointer was not advanced, an error must have occurred.
158  */
159 unsigned char *
160 lshpack_enc_encode (struct lshpack_enc *henc, unsigned char *dst,
161         unsigned char *dst_end, struct lsxpack_header *input);
162 
163 void
164 lshpack_enc_set_max_capacity (struct lshpack_enc *, unsigned);
165 
166 /**
167  * Turn history on or off.  Turning history on may fail (malloc), in
168  * which case -1 is returned.
169  */
170 int
171 lshpack_enc_use_hist (struct lshpack_enc *, int on);
172 
173 /**
174  * Return true if history is used, false otherwise.  By default,
175  * history is off.
176  */
177 int
178 lshpack_enc_hist_used (const struct lshpack_enc *);
179 
180 /**
181  * Initialize HPACK decoder structure.
182  */
183 void
184 lshpack_dec_init (struct lshpack_dec *);
185 
186 /**
187  * Clean up HPACK decoder structure, freeing all allocated memory.
188  */
189 void
190 lshpack_dec_cleanup (struct lshpack_dec *);
191 
192 /*
193  * Returns 0 on success, a negative value on failure.
194  *
195  * If 0 is returned, `src' is advanced.  Calling with a zero-length input
196  * buffer results in an error.
197  *
198  * To calculate number of bytes written to the output buffer:
199  *  output->name_len + output->val_len + lshpack_dec_extra_bytes(dec)
200  */
201 int
202 lshpack_dec_decode (struct lshpack_dec *dec,
203     const unsigned char **src, const unsigned char *src_end,
204     struct lsxpack_header *output);
205 
206 /* Return number of extra bytes per header */
207 #if LSHPACK_DEC_HTTP1X_OUTPUT
208 #define LSHPACK_DEC_HTTP1X_EXTRA  (2)
209 #define lshpack_dec_extra_bytes(dec_) (4)
210 #else
211 #define LSHPACK_DEC_HTTP1X_EXTRA  (0)
212 #define lshpack_dec_extra_bytes(dec_) (0)
213 #endif
214 
215 void
216 lshpack_dec_set_max_capacity (struct lshpack_dec *, unsigned);
217 
218 /* Some internals follow.  Struct definitions are exposed to save a malloc.
219  * These structures are not very complicated.
220  */
221 
222 #include <sys/queue.h>
223 
224 #ifdef __OpenBSD__
225 #define STAILQ_HEAD             SIMPLEQ_HEAD
226 #define STAILQ_ENTRY            SIMPLEQ_ENTRY
227 #define STAILQ_INIT             SIMPLEQ_INIT
228 #define STAILQ_INSERT_TAIL      SIMPLEQ_INSERT_TAIL
229 #define STAILQ_EMPTY            SIMPLEQ_EMPTY
230 #define STAILQ_FIRST            SIMPLEQ_FIRST
231 #define STAILQ_NEXT             SIMPLEQ_NEXT
232 #define STAILQ_REMOVE_HEAD      SIMPLEQ_REMOVE_HEAD
233 #define STAILQ_FOREACH          SIMPLEQ_FOREACH
234 #endif
235 
236 struct lshpack_enc_table_entry;
237 
238 STAILQ_HEAD(lshpack_enc_head, lshpack_enc_table_entry);
239 struct lshpack_double_enc_head;
240 
241 struct lshpack_enc
242 {
243     unsigned            hpe_cur_capacity;
244     unsigned            hpe_max_capacity;
245 
246     /* Each new dynamic table entry gets the next number.  It is used to
247      * calculate the entry's position in the decoder table without having
248      * to maintain an actual array.
249      */
250     unsigned            hpe_next_id;
251 
252     /* Dynamic table entries (struct enc_table_entry) live in two hash
253      * tables: name/value hash table and name hash table.  These tables
254      * are the same size.
255      */
256     unsigned            hpe_nelem;
257     unsigned            hpe_nbits;
258     struct lshpack_enc_head
259                         hpe_all_entries;
260     struct lshpack_double_enc_head
261                        *hpe_buckets;
262 
263     uint32_t           *hpe_hist_buf;
264     unsigned            hpe_hist_size, hpe_hist_idx;
265     int                 hpe_hist_wrapped;
266     enum {
267         LSHPACK_ENC_USE_HIST    = 1 << 0,
268     }                   hpe_flags;
269 };
270 
271 struct lshpack_arr
272 {
273     unsigned        nalloc,
274                     nelem,
275                     off;
276     uintptr_t      *els;
277 };
278 
279 struct lshpack_dec
280 {
281     struct lshpack_arr hpd_dyn_table;
282     unsigned           hpd_max_capacity;       /* Maximum set by caller */
283     unsigned           hpd_cur_max_capacity;   /* Adjusted at runtime */
284     unsigned           hpd_cur_capacity;
285     unsigned           hpd_state;
286 };
287 
288 /* This function may update hash values and flags */
289 unsigned
290 lshpack_enc_get_stx_tab_id (struct lsxpack_header *);
291 
292 #ifdef __cplusplus
293 }
294 #endif
295 
296 #endif
297