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 #define LWS_HTTP_NO_KNOWN_HEADER 0xff
98 
99 /*
100  * these are assigned from a pool held in the context.
101  * Both client and server mode uses them for http header analysis
102  */
103 
104 struct allocated_headers {
105 	struct allocated_headers *next; /* linked list */
106 	struct lws *wsi; /* owner */
107 	char *data; /* prepared by context init to point to dedicated storage */
108 	ah_data_idx_t data_length;
109 	/*
110 	 * the randomly ordered fragments, indexed by frag_index and
111 	 * lws_fragments->nfrag for continuation.
112 	 */
113 	struct lws_fragments frags[WSI_TOKEN_COUNT];
114 	time_t assigned;
115 	/*
116 	 * for each recognized token, frag_index says which frag[] his data
117 	 * starts in (0 means the token did not appear)
118 	 * the actual header data gets dumped as it comes in, into data[]
119 	 */
120 	uint8_t frag_index[WSI_TOKEN_COUNT];
121 
122 #if defined(LWS_WITH_CLIENT)
123 	char initial_handshake_hash_base64[30];
124 #endif
125 	int hdr_token_idx;
126 
127 	ah_data_idx_t pos;
128 	ah_data_idx_t http_response;
129 	ah_data_idx_t current_token_limit;
130 	ah_data_idx_t unk_pos; /* to undo speculative unknown header */
131 
132 #if defined(LWS_WITH_CUSTOM_HEADERS)
133 	ah_data_idx_t unk_value_pos;
134 
135 	ah_data_idx_t unk_ll_head;
136 	ah_data_idx_t unk_ll_tail;
137 #endif
138 
139 	int16_t lextable_pos;
140 
141 	uint8_t in_use;
142 	uint8_t nfrag;
143 	char /*enum uri_path_states */ ups;
144 	char /*enum uri_esc_states */ ues;
145 
146 	char esc_stash;
147 	char post_literal_equal;
148 	uint8_t /* enum lws_token_indexes */ parser_state;
149 };
150 
151 
152 
153 #if defined(LWS_WITH_HUBBUB)
154 struct lws_rewrite {
155 	hubbub_parser *parser;
156 	hubbub_parser_optparams params;
157 	const char *from, *to;
158 	int from_len, to_len;
159 	unsigned char *p, *end;
160 	struct lws *wsi;
161 };
hstrcmp(hubbub_string * s,const char * p,int len)162 static LWS_INLINE int hstrcmp(hubbub_string *s, const char *p, int len)
163 {
164 	if ((int)s->len != len)
165 		return 1;
166 
167 	return strncmp((const char *)s->ptr, p, len);
168 }
169 typedef hubbub_error (*hubbub_callback_t)(const hubbub_token *token, void *pw);
170 LWS_EXTERN struct lws_rewrite *
171 lws_rewrite_create(struct lws *wsi, hubbub_callback_t cb, const char *from, const char *to);
172 LWS_EXTERN void
173 lws_rewrite_destroy(struct lws_rewrite *r);
174 LWS_EXTERN int
175 lws_rewrite_parse(struct lws_rewrite *r, const unsigned char *in, int in_len);
176 #endif
177 
178 struct lws_pt_role_http {
179 	struct allocated_headers *ah_list;
180 	struct lws *ah_wait_list;
181 #ifdef LWS_WITH_CGI
182 	struct lws_cgi *cgi_list;
183 #endif
184 	int ah_wait_list_length;
185 	uint32_t ah_pool_length;
186 
187 	int ah_count_in_use;
188 };
189 
190 struct lws_peer_role_http {
191 	uint32_t count_ah;
192 	uint32_t total_ah;
193 };
194 
195 struct lws_vhost_role_http {
196 #if defined(LWS_CLIENT_HTTP_PROXYING)
197 	char http_proxy_address[128];
198 #endif
199 	const struct lws_http_mount *mount_list;
200 	const char *error_document_404;
201 #if defined(LWS_CLIENT_HTTP_PROXYING)
202 	unsigned int http_proxy_port;
203 #endif
204 };
205 
206 #ifdef LWS_WITH_ACCESS_LOG
207 struct lws_access_log {
208 	char *header_log;
209 	char *user_agent;
210 	char *referrer;
211 	unsigned long sent;
212 	int response;
213 };
214 #endif
215 
216 #define LWS_HTTP_CHUNK_HDR_MAX_SIZE (6 + 2) /* 6 hex digits and then CRLF */
217 #define LWS_HTTP_CHUNK_TRL_MAX_SIZE (2 + 5) /* CRLF, then maybe 0 CRLF CRLF */
218 
219 struct _lws_http_mode_related {
220 	struct lws *new_wsi_list;
221 
222 	unsigned char *pending_return_headers;
223 	size_t pending_return_headers_len;
224 	size_t prh_content_length;
225 
226 #if defined(LWS_WITH_HTTP_PROXY)
227 	struct lws_rewrite *rw;
228 	struct lws_buflist *buflist_post_body;
229 #endif
230 	struct allocated_headers *ah;
231 	struct lws *ah_wait_list;
232 
233 	unsigned long		writeable_len;
234 
235 #if defined(LWS_WITH_FILE_OPS)
236 	lws_filepos_t filepos;
237 	lws_filepos_t filelen;
238 	lws_fop_fd_t fop_fd;
239 #endif
240 #if defined(LWS_WITH_CLIENT)
241 	char multipart_boundary[16];
242 #endif
243 #if defined(LWS_WITH_RANGES)
244 	struct lws_range_parsing range;
245 	char multipart_content_type[64];
246 #endif
247 
248 #ifdef LWS_WITH_ACCESS_LOG
249 	struct lws_access_log access_log;
250 #endif
251 #if defined(LWS_WITH_SERVER)
252 	unsigned int response_code;
253 #endif
254 #ifdef LWS_WITH_CGI
255 	struct lws_cgi *cgi; /* wsi being cgi stream have one of these */
256 #endif
257 #if defined(LWS_WITH_HTTP_STREAM_COMPRESSION)
258 	struct lws_compression_support *lcs;
259 	lws_comp_ctx_t comp_ctx;
260 	unsigned char comp_accept_mask;
261 #endif
262 
263 	enum http_version request_version;
264 	enum http_conn_type conn_type;
265 	lws_filepos_t tx_content_length;
266 	lws_filepos_t tx_content_remain;
267 	lws_filepos_t rx_content_length;
268 	lws_filepos_t rx_content_remain;
269 
270 #if defined(LWS_WITH_HTTP_PROXY)
271 	unsigned int perform_rewrite:1;
272 	unsigned int proxy_clientside:1;
273 	unsigned int proxy_parent_chunked:1;
274 #endif
275 	unsigned int deferred_transaction_completed:1;
276 	unsigned int content_length_explicitly_zero:1;
277 	unsigned int content_length_given:1;
278 	unsigned int did_stream_close:1;
279 	unsigned int multipart:1;
280 	unsigned int cgi_transaction_complete:1;
281 	unsigned int multipart_issue_boundary:1;
282 };
283 
284 
285 #if defined(LWS_WITH_CLIENT)
286 enum lws_chunk_parser {
287 	ELCP_HEX,
288 	ELCP_CR,
289 	ELCP_CONTENT,
290 	ELCP_POST_CR,
291 	ELCP_POST_LF,
292 	ELCP_TRAILER_CR,
293 	ELCP_TRAILER_LF
294 };
295 #endif
296 
297 enum lws_parse_urldecode_results {
298 	LPUR_CONTINUE,
299 	LPUR_SWALLOW,
300 	LPUR_FORBID,
301 	LPUR_EXCESSIVE,
302 };
303 
304 enum lws_check_basic_auth_results {
305 	LCBA_CONTINUE,
306 	LCBA_FAILED_AUTH,
307 	LCBA_END_TRANSACTION,
308 };
309 
310 enum lws_check_basic_auth_results
311 lws_check_basic_auth(struct lws *wsi, const char *basic_auth_login_file, unsigned int auth_mode);
312 
313 int
314 lws_unauthorised_basic_auth(struct lws *wsi);
315 
316 int
317 lws_read_h1(struct lws *wsi, unsigned char *buf, lws_filepos_t len);
318 
319 void
320 _lws_header_table_reset(struct allocated_headers *ah);
321 
322 LWS_EXTERN int
323 _lws_destroy_ah(struct lws_context_per_thread *pt, struct allocated_headers *ah);
324 
325 int
326 lws_http_proxy_start(struct lws *wsi, const struct lws_http_mount *hit,
327 		     char *uri_ptr, char ws);
328 
329 void
330 lws_sul_http_ah_lifecheck(lws_sorted_usec_list_t *sul);
331 
332 uint8_t *
333 lws_http_multipart_headers(struct lws *wsi, uint8_t *p);
334 
335 int
336 lws_http_string_to_known_header(const char *s, size_t slen);
337 
338 int
339 lws_http_date_render_from_unix(char *buf, size_t len, const time_t *t);
340 
341 int
342 lws_http_date_parse_unix(const char *b, size_t len, time_t *t);
343 
344 enum {
345 	CCTLS_RETURN_ERROR		= -1,
346 	CCTLS_RETURN_DONE		= 0,
347 	CCTLS_RETURN_RETRY		= 1,
348 };
349 
350 int
351 lws_client_create_tls(struct lws *wsi, const char **pcce, int do_c1);
352