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