1 /*
2  * Copyright (c) 2013 Joris Vink <joris@coders.se>
3  *
4  * Permission to use, copy, modify, and distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16 
17 #if !defined(KORE_NO_HTTP)
18 
19 #ifndef __H_HTTP_H
20 #define __H_HTTP_H
21 
22 #include <sys/types.h>
23 #include <sys/queue.h>
24 
25 #include <openssl/sha.h>
26 
27 #if defined(__cplusplus)
28 extern "C" {
29 #endif
30 
31 /* Keep the http_populate_get symbol around. */
32 #define http_populate_get	http_populate_qs
33 
34 #define HTTP_KEEPALIVE_TIME	20
35 #define HTTP_HSTS_ENABLE	31536000
36 #define HTTP_HEADER_MAX_LEN	4096
37 #define HTTP_BODY_MAX_LEN	1024000
38 #define HTTP_URI_LEN		2000
39 #define HTTP_USERAGENT_LEN	256
40 #define HTTP_REFERER_LEN	256
41 #define HTTP_REQ_HEADER_MAX	25
42 #define HTTP_MAX_QUERY_ARGS	20
43 #define HTTP_MAX_COOKIES	10
44 #define HTTP_MAX_COOKIENAME	255
45 #define HTTP_HEADER_BUFSIZE	1024
46 #define HTTP_COOKIE_BUFSIZE	1024
47 #define HTTP_DATE_MAXSIZE	255
48 #define HTTP_REQUEST_LIMIT	1000
49 #define HTTP_REQUEST_MS		10
50 #define HTTP_BODY_DISK_PATH	"tmp_files"
51 #define HTTP_BODY_DISK_OFFLOAD	0
52 #define HTTP_BODY_PATH_MAX	256
53 #define HTTP_BOUNDARY_MAX	80
54 #define HTTP_HEADER_TIMEOUT	10
55 #define HTTP_BODY_TIMEOUT	60
56 
57 #define HTTP_ARG_TYPE_RAW	0
58 #define HTTP_ARG_TYPE_BYTE	1
59 #define HTTP_ARG_TYPE_INT16	2
60 #define HTTP_ARG_TYPE_UINT16	3
61 #define HTTP_ARG_TYPE_INT32	4
62 #define HTTP_ARG_TYPE_UINT32	5
63 #define HTTP_ARG_TYPE_STRING	6
64 #define HTTP_ARG_TYPE_INT64	7
65 #define HTTP_ARG_TYPE_UINT64	8
66 #define HTTP_ARG_TYPE_FLOAT	9
67 #define HTTP_ARG_TYPE_DOUBLE	10
68 
69 #define HTTP_STATE_ERROR	0
70 #define HTTP_STATE_CONTINUE	1
71 #define HTTP_STATE_COMPLETE	2
72 #define HTTP_STATE_RETRY	3
73 
74 struct http_runlock_queue {
75 	struct http_request		*req;
76 	LIST_ENTRY(http_runlock_queue)	list;
77 };
78 
79 struct http_runlock {
80 	struct http_request		*owner;
81 	LIST_HEAD(, http_runlock_queue)	queue;
82 };
83 
84 struct http_header {
85 	char			*header;
86 	char			*value;
87 
88 	TAILQ_ENTRY(http_header)	list;
89 };
90 
91 #define HTTP_COOKIE_HTTPONLY	0x0001
92 #define HTTP_COOKIE_SECURE	0x0002
93 
94 struct http_cookie {
95 	char				*name;
96 	char				*value;
97 	char				*path;
98 	char				*domain;
99 	u_int32_t			maxage;
100 	time_t				expires;
101 	u_int16_t			flags;
102 
103 	TAILQ_ENTRY(http_cookie)	list;
104 };
105 
106 struct http_arg {
107 	char			*name;
108 	char			*s_value;
109 
110 	TAILQ_ENTRY(http_arg)	list;
111 };
112 
113 #define COPY_ARG_TYPE(v, t)				\
114 	do {						\
115 		*(t *)nout = v;				\
116 	} while (0)
117 
118 #define COPY_ARG_INT64(type, sign)					\
119 	do {								\
120 		int err;						\
121 		type nval;						\
122 		nval = (type)kore_strtonum64(q->s_value, sign, &err);	\
123 		if (err != KORE_RESULT_OK)				\
124 			return (KORE_RESULT_ERROR);			\
125 		COPY_ARG_TYPE(nval, type);				\
126 	} while (0)
127 
128 #define COPY_ARG_DOUBLE(min, max, type)					\
129 	do {								\
130 		int err;						\
131 		type nval;						\
132 		nval = kore_strtodouble(q->s_value, min, max, &err);	\
133 		if (err != KORE_RESULT_OK)				\
134 			return (KORE_RESULT_ERROR);			\
135 		COPY_ARG_TYPE(nval, type);				\
136 	} while (0)
137 
138 #define COPY_ARG_INT(min, max, type)					\
139 	do {								\
140 		int err;						\
141 		int64_t nval;						\
142 		nval = kore_strtonum(q->s_value, 10, min, max, &err);	\
143 		if (err != KORE_RESULT_OK)				\
144 			return (KORE_RESULT_ERROR);			\
145 		COPY_ARG_TYPE(nval, type);				\
146 	} while (0)
147 
148 #define COPY_AS_INTTYPE_64(type, sign)					\
149 	do {								\
150 		if (nout == NULL)					\
151 			return (KORE_RESULT_ERROR);			\
152 		COPY_ARG_INT64(type, sign);				\
153 	} while (0)
154 
155 #define COPY_AS_INTTYPE(min, max, type)					\
156 	do {								\
157 		if (nout == NULL)					\
158 			return (KORE_RESULT_ERROR);			\
159 		COPY_ARG_INT(min, max, type);				\
160 	} while (0)
161 
162 #define http_argument_type(r, n, so, no, t)				\
163 	http_argument_get(r, n, so, no, t)
164 
165 #define http_argument_get_string(r, n, o)				\
166 	http_argument_type(r, n, (void **)o, NULL, HTTP_ARG_TYPE_STRING)
167 
168 #define http_argument_get_byte(r, n, o)				\
169 	http_argument_type(r, n, NULL, o, HTTP_ARG_TYPE_BYTE)
170 
171 #define http_argument_get_uint16(r, n, o)				\
172 	http_argument_type(r, n, NULL, o, HTTP_ARG_TYPE_UINT16)
173 
174 #define http_argument_get_int16(r, n, o)				\
175 	http_argument_type(r, n, NULL, o, HTTP_ARG_TYPE_INT16)
176 
177 #define http_argument_get_uint32(r, n, o)				\
178 	http_argument_type(r, n, NULL, o, HTTP_ARG_TYPE_UINT32)
179 
180 #define http_argument_get_int32(r, n, o)				\
181 	http_argument_type(r, n, NULL, o, HTTP_ARG_TYPE_INT32)
182 
183 #define http_argument_get_uint64(r, n, o)				\
184 	http_argument_type(r, n, NULL, o, HTTP_ARG_TYPE_UINT64)
185 
186 #define http_argument_get_int64(r, n, o)				\
187 	http_argument_type(r, n, NULL, o, HTTP_ARG_TYPE_INT64)
188 
189 #define http_argument_get_float(r, n, o)				\
190 	http_argument_type(r, n, NULL, o, HTTP_ARG_TYPE_FLOAT)
191 
192 #define http_argument_get_double(r, n, o)				\
193 	http_argument_type(r, n, NULL, o, HTTP_ARG_TYPE_DOUBLE)
194 
195 struct http_file {
196 	char			*name;
197 	char			*filename;
198 	size_t			position;
199 	size_t			offset;
200 	size_t			length;
201 	struct http_request	*req;
202 	TAILQ_ENTRY(http_file)	list;
203 };
204 
205 #define HTTP_METHOD_GET		0x0001
206 #define HTTP_METHOD_POST	0x0002
207 #define HTTP_METHOD_PUT		0x0004
208 #define HTTP_METHOD_DELETE	0x0010
209 #define HTTP_METHOD_HEAD	0x0020
210 #define HTTP_METHOD_OPTIONS	0x0040
211 #define HTTP_METHOD_PATCH	0x0080
212 
213 #define HTTP_METHOD_ALL		(HTTP_METHOD_GET | HTTP_METHOD_POST | \
214     HTTP_METHOD_PUT | HTTP_METHOD_DELETE | HTTP_METHOD_HEAD | \
215     HTTP_METHOD_OPTIONS | HTTP_METHOD_PATCH)
216 
217 #define HTTP_REQUEST_COMPLETE		0x0001
218 #define HTTP_REQUEST_DELETE		0x0002
219 #define HTTP_REQUEST_SLEEPING		0x0004
220 #define HTTP_REQUEST_EXPECT_BODY	0x0020
221 #define HTTP_REQUEST_RETAIN_EXTRA	0x0040
222 #define HTTP_REQUEST_NO_CONTENT_LENGTH	0x0080
223 #define HTTP_REQUEST_AUTHED		0x0100
224 
225 #define HTTP_VERSION_1_1		0x1000
226 #define HTTP_VERSION_1_0		0x2000
227 
228 #define HTTP_VALIDATOR_IS_REQUEST	0x8000
229 
230 #define HTTP_BODY_DIGEST_LEN		32
231 #define HTTP_BODY_DIGEST_STRLEN		((HTTP_BODY_DIGEST_LEN * 2) + 1)
232 
233 #define HTTP_CAPTURE_GROUPS		17
234 
235 struct reqcall;
236 struct kore_task;
237 struct http_client;
238 
239 struct http_redirect {
240 	regex_t				rctx;
241 	int				status;
242 	char				*target;
243 	TAILQ_ENTRY(http_redirect)	list;
244 };
245 
246 struct http_request {
247 	u_int8_t			method;
248 	u_int8_t			fsm_state;
249 	u_int16_t			flags;
250 	u_int16_t			status;
251 	u_int64_t			ms;
252 	u_int64_t			start;
253 	u_int64_t			end;
254 	u_int64_t			total;
255 	const char			*path;
256 	const char			*host;
257 	const char			*agent;
258 	const char			*referer;
259 	struct connection		*owner;
260 	SHA256_CTX			hashctx;
261 	u_int8_t			*headers;
262 	struct kore_buf			*http_body;
263 	int				http_body_fd;
264 	char				*http_body_path;
265 	size_t				http_body_length;
266 	size_t				http_body_offset;
267 	size_t				content_length;
268 	void				*hdlr_extra;
269 	size_t				state_len;
270 	char				*query_string;
271 	struct kore_module_handle	*hdlr;
272 	struct http_runlock_queue	*runlock;
273 	void				(*onfree)(struct http_request *);
274 
275 #if defined(KORE_USE_PYTHON)
276 	void				*py_req;
277 	void				*py_coro;
278 	void				*py_validator;
279 	struct reqcall			*py_rqnext;
280 #endif
281 
282 	regmatch_t	cgroups[HTTP_CAPTURE_GROUPS];
283 	u_int8_t	http_body_digest[HTTP_BODY_DIGEST_LEN];
284 
285 #if defined(KORE_USE_CURL)
286 	LIST_HEAD(, kore_curl)		chandles;
287 #endif
288 
289 #if defined(KORE_USE_TASKS)
290 	LIST_HEAD(, kore_task)		tasks;
291 #endif
292 
293 #if defined(KORE_USE_PGSQL)
294 	LIST_HEAD(, kore_pgsql)		pgsqls;
295 #endif
296 
297 	TAILQ_HEAD(, http_cookie)	req_cookies;
298 	TAILQ_HEAD(, http_cookie)	resp_cookies;
299 	TAILQ_HEAD(, http_header)	req_headers;
300 	TAILQ_HEAD(, http_header)	resp_headers;
301 	TAILQ_HEAD(, http_arg)		arguments;
302 	TAILQ_HEAD(, http_file)		files;
303 	TAILQ_ENTRY(http_request)	list;
304 	TAILQ_ENTRY(http_request)	olist;
305 };
306 
307 #define KORE_HTTP_STATE(f)		{ #f, f }
308 
309 struct http_state {
310 	const char		*name;
311 	int			(*cb)(struct http_request *);
312 };
313 
314 struct http_media_type {
315 	char				*ext;
316 	char				*type;
317 	LIST_ENTRY(http_media_type)	list;
318 };
319 
320 extern size_t		http_body_max;
321 extern u_int16_t	http_body_timeout;
322 extern u_int16_t	http_header_max;
323 extern u_int16_t	http_header_timeout;
324 extern u_int32_t	http_request_ms;
325 extern u_int64_t	http_hsts_enable;
326 extern u_int16_t	http_keepalive_time;
327 extern u_int32_t	http_request_limit;
328 extern u_int32_t	http_request_count;
329 extern u_int64_t	http_body_disk_offload;
330 extern int		http_pretty_error;
331 extern char		*http_body_disk_path;
332 extern struct kore_pool	http_header_pool;
333 
334 void		kore_accesslog(struct http_request *);
335 
336 void		http_init(void);
337 void		http_parent_init(void);
338 void		http_cleanup(void);
339 void 		http_server_version(const char *);
340 void		http_process(void);
341 const char	*http_status_text(int);
342 const char	*http_method_text(int);
343 time_t		http_date_to_time(char *);
344 char		*http_validate_header(char *);
345 int		http_method_value(const char *);
346 void		http_start_recv(struct connection *);
347 void		http_request_free(struct http_request *);
348 void		http_request_sleep(struct http_request *);
349 void		http_request_wakeup(struct http_request *);
350 void		http_process_request(struct http_request *);
351 int		http_body_rewind(struct http_request *);
352 int		http_media_register(const char *, const char *);
353 int		http_check_timeout(struct connection *, u_int64_t);
354 ssize_t		http_body_read(struct http_request *, void *, size_t);
355 int		http_body_digest(struct http_request *, char *, size_t);
356 
357 int		http_redirect_add(struct kore_domain *,
358 		    const char *, int, const char *);
359 void		http_response(struct http_request *, int, const void *, size_t);
360 void		http_response_fileref(struct http_request *, int,
361 		    struct kore_fileref *);
362 void		http_serveable(struct http_request *, const void *,
363 		    size_t, const char *, const char *);
364 void		http_response_stream(struct http_request *, int, void *,
365 		    size_t, int (*cb)(struct netbuf *), void *);
366 int		http_request_header(struct http_request *,
367 		    const char *, const char **);
368 void		http_response_header(struct http_request *,
369 		    const char *, const char *);
370 int		http_state_run(struct http_state *, u_int8_t,
371 		    struct http_request *);
372 int	 	http_request_cookie(struct http_request *,
373 		    const char *, char **);
374 void		http_response_cookie(struct http_request *, const char *,
375 		    const char *, const char *, time_t, u_int32_t,
376 		    struct http_cookie **);
377 
378 void		http_runlock_init(struct http_runlock *);
379 void		http_runlock_release(struct http_runlock *,
380 		    struct http_request *);
381 int		http_runlock_acquire(struct http_runlock *,
382 		    struct http_request *);
383 
384 const char	*http_media_type(const char *);
385 void		*http_state_get(struct http_request *);
386 int		http_state_exists(struct http_request *);
387 void		http_state_cleanup(struct http_request *);
388 void		*http_state_create(struct http_request *, size_t,
389 		    void (*onfree)(struct http_request *));
390 
391 int		http_argument_urldecode(char *);
392 int		http_header_recv(struct netbuf *);
393 void		http_populate_qs(struct http_request *);
394 void		http_populate_post(struct http_request *);
395 void		http_populate_multipart_form(struct http_request *);
396 void		http_populate_cookies(struct http_request *);
397 int		http_argument_get(struct http_request *,
398 		    const char *, void **, void *, int);
399 
400 void			http_file_rewind(struct http_file *);
401 ssize_t			http_file_read(struct http_file *, void *, size_t);
402 struct http_file	*http_file_lookup(struct http_request *, const char *);
403 
404 enum http_status_code {
405 	HTTP_STATUS_CONTINUE			= 100,
406 	HTTP_STATUS_SWITCHING_PROTOCOLS		= 101,
407 	HTTP_STATUS_OK				= 200,
408 	HTTP_STATUS_CREATED			= 201,
409 	HTTP_STATUS_ACCEPTED			= 202,
410 	HTTP_STATUS_NON_AUTHORITATIVE		= 203,
411 	HTTP_STATUS_NO_CONTENT			= 204,
412 	HTTP_STATUS_RESET_CONTENT		= 205,
413 	HTTP_STATUS_PARTIAL_CONTENT		= 206,
414 	HTTP_STATUS_MULTIPLE_CHOICES		= 300,
415 	HTTP_STATUS_MOVED_PERMANENTLY		= 301,
416 	HTTP_STATUS_FOUND			= 302,
417 	HTTP_STATUS_SEE_OTHER			= 303,
418 	HTTP_STATUS_NOT_MODIFIED		= 304,
419 	HTTP_STATUS_USE_PROXY			= 305,
420 	HTTP_STATUS_TEMPORARY_REDIRECT		= 307,
421 	HTTP_STATUS_BAD_REQUEST			= 400,
422 	HTTP_STATUS_UNAUTHORIZED		= 401,
423 	HTTP_STATUS_PAYMENT_REQUIRED		= 402,
424 	HTTP_STATUS_FORBIDDEN			= 403,
425 	HTTP_STATUS_NOT_FOUND			= 404,
426 	HTTP_STATUS_METHOD_NOT_ALLOWED		= 405,
427 	HTTP_STATUS_NOT_ACCEPTABLE		= 406,
428 	HTTP_STATUS_PROXY_AUTH_REQUIRED		= 407,
429 	HTTP_STATUS_REQUEST_TIMEOUT		= 408,
430 	HTTP_STATUS_CONFLICT			= 409,
431 	HTTP_STATUS_GONE			= 410,
432 	HTTP_STATUS_LENGTH_REQUIRED		= 411,
433 	HTTP_STATUS_PRECONDITION_FAILED		= 412,
434 	HTTP_STATUS_REQUEST_ENTITY_TOO_LARGE	= 413,
435 	HTTP_STATUS_REQUEST_URI_TOO_LARGE	= 414,
436 	HTTP_STATUS_UNSUPPORTED_MEDIA_TYPE	= 415,
437 	HTTP_STATUS_REQUEST_RANGE_INVALID	= 416,
438 	HTTP_STATUS_EXPECTATION_FAILED		= 417,
439 	HTTP_STATUS_MISDIRECTED_REQUEST		= 421,
440 	HTTP_STATUS_INTERNAL_ERROR		= 500,
441 	HTTP_STATUS_NOT_IMPLEMENTED		= 501,
442 	HTTP_STATUS_BAD_GATEWAY			= 502,
443 	HTTP_STATUS_SERVICE_UNAVAILABLE		= 503,
444 	HTTP_STATUS_GATEWAY_TIMEOUT		= 504,
445 	HTTP_STATUS_BAD_VERSION			= 505
446 };
447 #if defined(__cplusplus)
448 }
449 #endif
450 #endif /* !__H_HTTP_H */
451 
452 #endif /* ! KORE_NO_HTTP */
453