1 /*
2 * libwebsockets - small server side websockets and web server implementation
3 *
4 * Copyright (C) 2010 - 2019 Andy Green <andy@warmcat.com>
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
8 * deal in the Software without restriction, including without limitation the
9 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10 * sell 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
14 * all 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
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22 * IN THE SOFTWARE.
23 *
24 * This is included from private-lib-core.h if either H1 or H2 roles are
25 * enabled
26 */
27
28 #if defined(LWS_WITH_HUBBUB)
29 #include <hubbub/hubbub.h>
30 #include <hubbub/parser.h>
31 #endif
32
33 #if defined(LWS_WITH_HTTP_STREAM_COMPRESSION)
34 #include "private-lib-roles-http-compression.h"
35 #endif
36
37 #define lwsi_role_http(wsi) (lwsi_role_h1(wsi) || lwsi_role_h2(wsi))
38
39 enum http_version {
40 HTTP_VERSION_1_0,
41 HTTP_VERSION_1_1,
42 HTTP_VERSION_2
43 };
44
45 enum http_conn_type {
46 HTTP_CONNECTION_CLOSE,
47 HTTP_CONNECTION_KEEP_ALIVE
48 };
49
50 /*
51 * This is totally opaque to code using the library. It's exported as a
52 * forward-reference pointer-only declaration; the user can use the pointer with
53 * other APIs to get information out of it.
54 */
55
56 #if defined(LWS_PLAT_FREERTOS)
57 typedef uint16_t ah_data_idx_t;
58 #else
59 typedef uint32_t ah_data_idx_t;
60 #endif
61
62 struct lws_fragments {
63 ah_data_idx_t offset;
64 uint16_t len;
65 uint8_t nfrag; /* which ah->frag[] continues this content, or 0 */
66 uint8_t flags; /* only http2 cares */
67 };
68
69 #if defined(LWS_WITH_RANGES)
70 enum range_states {
71 LWSRS_NO_ACTIVE_RANGE,
72 LWSRS_BYTES_EQ,
73 LWSRS_FIRST,
74 LWSRS_STARTING,
75 LWSRS_ENDING,
76 LWSRS_COMPLETED,
77 LWSRS_SYNTAX,
78 };
79
80 struct lws_range_parsing {
81 unsigned long long start, end, extent, agg, budget;
82 const char buf[128];
83 int pos;
84 enum range_states state;
85 char start_valid, end_valid, ctr, count_ranges, did_try, inside, send_ctr;
86 };
87
88 int
89 lws_ranges_init(struct lws *wsi, struct lws_range_parsing *rp,
90 unsigned long long extent);
91 int
92 lws_ranges_next(struct lws_range_parsing *rp);
93 void
94 lws_ranges_reset(struct lws_range_parsing *rp);
95 #endif
96
97 /*
98 * these are assigned from a pool held in the context.
99 * Both client and server mode uses them for http header analysis
100 */
101
102 struct allocated_headers {
103 struct allocated_headers *next; /* linked list */
104 struct lws *wsi; /* owner */
105 char *data; /* prepared by context init to point to dedicated storage */
106 ah_data_idx_t data_length;
107 /*
108 * the randomly ordered fragments, indexed by frag_index and
109 * lws_fragments->nfrag for continuation.
110 */
111 struct lws_fragments frags[WSI_TOKEN_COUNT];
112 time_t assigned;
113 /*
114 * for each recognized token, frag_index says which frag[] his data
115 * starts in (0 means the token did not appear)
116 * the actual header data gets dumped as it comes in, into data[]
117 */
118 uint8_t frag_index[WSI_TOKEN_COUNT];
119
120 #if defined(LWS_WITH_CLIENT)
121 char initial_handshake_hash_base64[30];
122 #endif
123 int hdr_token_idx;
124
125 ah_data_idx_t pos;
126 ah_data_idx_t http_response;
127 ah_data_idx_t current_token_limit;
128
129 #if defined(LWS_WITH_CUSTOM_HEADERS)
130 ah_data_idx_t unk_pos; /* to undo speculative unknown header */
131 ah_data_idx_t unk_value_pos;
132
133 ah_data_idx_t unk_ll_head;
134 ah_data_idx_t unk_ll_tail;
135 #endif
136
137 int16_t lextable_pos;
138
139 uint8_t in_use;
140 uint8_t nfrag;
141 char /*enum uri_path_states */ ups;
142 char /*enum uri_esc_states */ ues;
143
144 char esc_stash;
145 char post_literal_equal;
146 uint8_t /* enum lws_token_indexes */ parser_state;
147 };
148
149
150
151 #if defined(LWS_WITH_HUBBUB)
152 struct lws_rewrite {
153 hubbub_parser *parser;
154 hubbub_parser_optparams params;
155 const char *from, *to;
156 int from_len, to_len;
157 unsigned char *p, *end;
158 struct lws *wsi;
159 };
hstrcmp(hubbub_string * s,const char * p,int len)160 static LWS_INLINE int hstrcmp(hubbub_string *s, const char *p, int len)
161 {
162 if ((int)s->len != len)
163 return 1;
164
165 return strncmp((const char *)s->ptr, p, len);
166 }
167 typedef hubbub_error (*hubbub_callback_t)(const hubbub_token *token, void *pw);
168 LWS_EXTERN struct lws_rewrite *
169 lws_rewrite_create(struct lws *wsi, hubbub_callback_t cb, const char *from, const char *to);
170 LWS_EXTERN void
171 lws_rewrite_destroy(struct lws_rewrite *r);
172 LWS_EXTERN int
173 lws_rewrite_parse(struct lws_rewrite *r, const unsigned char *in, int in_len);
174 #endif
175
176 struct lws_pt_role_http {
177 struct allocated_headers *ah_list;
178 struct lws *ah_wait_list;
179 #ifdef LWS_WITH_CGI
180 struct lws_cgi *cgi_list;
181 #endif
182 int ah_wait_list_length;
183 uint32_t ah_pool_length;
184
185 int ah_count_in_use;
186 };
187
188 struct lws_peer_role_http {
189 uint32_t count_ah;
190 uint32_t total_ah;
191 };
192
193 struct lws_vhost_role_http {
194 #if defined(LWS_CLIENT_HTTP_PROXYING)
195 char http_proxy_address[128];
196 #endif
197 const struct lws_http_mount *mount_list;
198 const char *error_document_404;
199 #if defined(LWS_CLIENT_HTTP_PROXYING)
200 unsigned int http_proxy_port;
201 #endif
202 };
203
204 #ifdef LWS_WITH_ACCESS_LOG
205 struct lws_access_log {
206 char *header_log;
207 char *user_agent;
208 char *referrer;
209 unsigned long sent;
210 int response;
211 };
212 #endif
213
214 #define LWS_HTTP_CHUNK_HDR_MAX_SIZE (6 + 2) /* 6 hex digits and then CRLF */
215 #define LWS_HTTP_CHUNK_TRL_MAX_SIZE (2 + 5) /* CRLF, then maybe 0 CRLF CRLF */
216
217 struct _lws_http_mode_related {
218 struct lws *new_wsi_list;
219
220 unsigned char *pending_return_headers;
221 size_t pending_return_headers_len;
222 size_t prh_content_length;
223
224 #if defined(LWS_WITH_HTTP_PROXY)
225 struct lws_rewrite *rw;
226 struct lws_buflist *buflist_post_body;
227 #endif
228 struct allocated_headers *ah;
229 struct lws *ah_wait_list;
230
231 unsigned long writeable_len;
232
233 #if defined(LWS_WITH_FILE_OPS)
234 lws_filepos_t filepos;
235 lws_filepos_t filelen;
236 lws_fop_fd_t fop_fd;
237 #endif
238 #if defined(LWS_WITH_CLIENT)
239 char multipart_boundary[16];
240 #endif
241 #if defined(LWS_WITH_RANGES)
242 struct lws_range_parsing range;
243 char multipart_content_type[64];
244 #endif
245
246 #ifdef LWS_WITH_ACCESS_LOG
247 struct lws_access_log access_log;
248 #endif
249 #ifdef LWS_WITH_CGI
250 struct lws_cgi *cgi; /* wsi being cgi master have one of these */
251 #endif
252 #if defined(LWS_WITH_HTTP_STREAM_COMPRESSION)
253 struct lws_compression_support *lcs;
254 lws_comp_ctx_t comp_ctx;
255 unsigned char comp_accept_mask;
256 #endif
257
258 enum http_version request_version;
259 enum http_conn_type conn_type;
260 lws_filepos_t tx_content_length;
261 lws_filepos_t tx_content_remain;
262 lws_filepos_t rx_content_length;
263 lws_filepos_t rx_content_remain;
264
265 #if defined(LWS_WITH_HTTP_PROXY)
266 unsigned int perform_rewrite:1;
267 unsigned int proxy_clientside:1;
268 unsigned int proxy_parent_chunked:1;
269 #endif
270 unsigned int deferred_transaction_completed:1;
271 unsigned int content_length_explicitly_zero:1;
272 unsigned int content_length_given:1;
273 unsigned int did_stream_close:1;
274 unsigned int multipart:1;
275 unsigned int cgi_transaction_complete:1;
276 unsigned int multipart_issue_boundary:1;
277 };
278
279
280 #if defined(LWS_WITH_CLIENT)
281 enum lws_chunk_parser {
282 ELCP_HEX,
283 ELCP_CR,
284 ELCP_CONTENT,
285 ELCP_POST_CR,
286 ELCP_POST_LF,
287 ELCP_TRAILER_CR,
288 ELCP_TRAILER_LF
289 };
290 #endif
291
292 enum lws_parse_urldecode_results {
293 LPUR_CONTINUE,
294 LPUR_SWALLOW,
295 LPUR_FORBID,
296 LPUR_EXCESSIVE,
297 };
298
299 enum lws_check_basic_auth_results {
300 LCBA_CONTINUE,
301 LCBA_FAILED_AUTH,
302 LCBA_END_TRANSACTION,
303 };
304
305 enum lws_check_basic_auth_results
306 lws_check_basic_auth(struct lws *wsi, const char *basic_auth_login_file, unsigned int auth_mode);
307
308 int
309 lws_unauthorised_basic_auth(struct lws *wsi);
310
311 int
312 lws_read_h1(struct lws *wsi, unsigned char *buf, lws_filepos_t len);
313
314 void
315 _lws_header_table_reset(struct allocated_headers *ah);
316
317 LWS_EXTERN int
318 _lws_destroy_ah(struct lws_context_per_thread *pt, struct allocated_headers *ah);
319
320 int
321 lws_http_proxy_start(struct lws *wsi, const struct lws_http_mount *hit,
322 char *uri_ptr, char ws);
323
324 void
325 lws_sul_http_ah_lifecheck(lws_sorted_usec_list_t *sul);
326
327 uint8_t *
328 lws_http_multipart_headers(struct lws *wsi, uint8_t *p);
329
330 int
331 lws_client_create_tls(struct lws *wsi, const char **pcce, int do_c1);
332