http.c (59993B)
1 /*
2 * Copyright (c) 2013-2022 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 #include <sys/param.h>
18 #include <sys/types.h>
19
20 #include <sys/socket.h>
21 #include <netinet/in.h>
22
23 #include <ctype.h>
24 #include <fcntl.h>
25 #include <inttypes.h>
26 #include <float.h>
27 #include <time.h>
28 #include <stdio.h>
29
30 #include "kore.h"
31 #include "http.h"
32
33 #if defined(KORE_USE_PYTHON)
34 #include "python_api.h"
35 #endif
36
37 #if defined(KORE_USE_PGSQL)
38 #include "pgsql.h"
39 #endif
40
41 #if defined(KORE_USE_TASKS)
42 #include "tasks.h"
43 #endif
44
45 #if defined(KORE_USE_CURL)
46 #include "curl.h"
47 #endif
48
49 static struct {
50 const char *ext;
51 const char *type;
52 } builtin_media[] = {
53 { "gif", "image/gif" },
54 { "png", "image/png" },
55 { "jpeg", "image/jpeg" },
56 { "jpg", "image/jpeg" },
57 { "zip", "application/zip" },
58 { "pdf", "application/pdf" },
59 { "json", "application/json" },
60 { "js", "application/javascript" },
61 { "htm", "text/html" },
62 { "txt", "text/plain" },
63 { "css", "text/css" },
64 { "html", "text/html" },
65 { NULL, NULL },
66 };
67
68 #define HTTP_MAP_LIMIT 127
69
70 /*
71 * token = 1*<any CHAR except CTLs or separators>
72 * separators = "(" | ")" | "<" | ">" | "@"
73 * | "," | ";" | ":" | "\" | <">
74 * | "/" | "[" | "]" | "?" | "="
75 * | "{" | "}" | SP | HT
76 */
77 static const char http_token[] = {
78 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
79 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
80 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
81 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
82 0x00, '!' , 0x00, '#' , '$' , '%' , '&' , '\'',
83 0x00, 0x00, '*' , '+' , 0x00, '-' , '.' , 0x00,
84 '0' , '1' , '2' , '3' , '4' , '5' , '6' , '7' ,
85 '8' , '9' , 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
86 0x00, 'A' , 'B' , 'C' , 'D' , 'E' , 'F' , 'G' ,
87 'H' , 'I' , 'J' , 'K' , 'L' , 'M' , 'N' , 'O' ,
88 'P' , 'Q' , 'R' , 'S' , 'T' , 'U' , 'V' , 'W' ,
89 'X' , 'Y' , 'Z' , 0x00, 0x00, 0x00, '^' , '_' ,
90 '`' , 'a' , 'b' , 'c' , 'd' , 'e' , 'f' , 'g' ,
91 'h' , 'i' , 'j' , 'k' , 'l' , 'm' , 'n' , 'o' ,
92 'p' , 'q' , 'r' , 's' , 't' , 'u' , 'v' , 'w' ,
93 'x' , 'y' , 'z' , 0x00, '|' , 0x00, '~' , 0x00
94 };
95
96 /*
97 * field-content = <the OCTETs making up the field-value
98 * and consisting of either *TEXT or combinations
99 * of token, separators, and quoted-string>
100 */
101 static const char http_field_content[] = {
102 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
103 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
104 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
105 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
106 ' ' , '!' , '"' , '#' , '$' , '%' , '&' , '\'',
107 '(' , ')' , '*' , '+' , ',' , '-' , '.' , '/' ,
108 '0' , '1' , '2' , '3' , '4' , '5' , '6' , '7' ,
109 '8' , '9' , ':' , ';' , '<' , '=' , '>' , '?' ,
110 '@' , 'A' , 'B' , 'C' , 'D' , 'E' , 'F' , 'G' ,
111 'H' , 'I' , 'J' , 'K' , 'L' , 'M' , 'N' , 'O' ,
112 'P' , 'Q' , 'R' , 'S' , 'T' , 'U' , 'V' , 'W' ,
113 'X' , 'Y' , 'Z' , '[' , '\\', ']' , '^' , '_' ,
114 '`' , 'a' , 'b' , 'c' , 'd' , 'e' , 'f' , 'g' ,
115 'h' , 'i' , 'j' , 'k' , 'l' , 'm' , 'n' , 'o' ,
116 'p' , 'q' , 'r' , 's' , 't' , 'u' , 'v' , 'w' ,
117 'x' , 'y' , 'z' , '{' , '|' , '}' , '~' , 0x00
118 };
119
120 /*
121 * Fixed "pretty" HTTP error HTML page.
122 */
123 static const char *pretty_error_fmt =
124 "<html>\n<head>\n\t<title>%d %s</title>"
125 "</head>\n<body>\n\t"
126 "<h1>%d %s</h1>\n"
127 "</body>\n</html>\n";
128
129 static int http_body_recv(struct netbuf *);
130 static int http_release_buffer(struct netbuf *);
131 static void http_error_response(struct connection *, int);
132 static int http_data_convert(void *, void **, void *, int);
133 static void http_write_response_cookie(struct http_cookie *);
134 static int http_body_update(struct http_request *, const void *, size_t);
135 static void http_argument_add(struct http_request *, char *, char *,
136 int, int);
137 static int http_check_redirect(struct http_request *,
138 struct kore_domain *);
139 static void http_response_normal(struct http_request *,
140 struct connection *, int, const void *, size_t);
141 static void multipart_add_field(struct http_request *, struct kore_buf *,
142 char *, const char *, const int);
143 static void multipart_file_add(struct http_request *, struct kore_buf *,
144 const char *, const char *, const char *, const int);
145 static int multipart_find_data(struct kore_buf *, struct kore_buf *,
146 size_t *, struct http_request *, const void *, size_t);
147 static int multipart_parse_headers(struct http_request *,
148 struct kore_buf *, struct kore_buf *,
149 const char *, const int);
150
151 static struct http_request *http_request_new(struct connection *,
152 const char *, const char *, char *,
153 const char *);
154
155 static struct kore_buf *header_buf;
156 static struct kore_buf *ckhdr_buf;
157 static char http_version[64];
158 static u_int16_t http_version_len;
159 static TAILQ_HEAD(, http_request) http_requests;
160 static TAILQ_HEAD(, http_request) http_requests_sleeping;
161 static LIST_HEAD(, http_media_type) http_media_types;
162 static struct kore_pool http_request_pool;
163 static struct kore_pool http_cookie_pool;
164 static struct kore_pool http_body_path;
165 static struct kore_pool http_rlq_pool;
166
167 struct kore_pool http_header_pool;
168
169 int http_pretty_error = 0;
170 u_int32_t http_request_count = 0;
171 u_int32_t http_request_ms = HTTP_REQUEST_MS;
172 u_int16_t http_body_timeout = HTTP_BODY_TIMEOUT;
173 u_int32_t http_request_limit = HTTP_REQUEST_LIMIT;
174 u_int64_t http_hsts_enable = HTTP_HSTS_ENABLE;
175 u_int16_t http_header_max = HTTP_HEADER_MAX_LEN;
176 u_int16_t http_keepalive_time = HTTP_KEEPALIVE_TIME;
177 u_int16_t http_header_timeout = HTTP_HEADER_TIMEOUT;
178
179 size_t http_body_max = HTTP_BODY_MAX_LEN;
180 char *http_body_disk_path = HTTP_BODY_DISK_PATH;
181 u_int64_t http_body_disk_offload = HTTP_BODY_DISK_OFFLOAD;
182
183 void
184 http_parent_init(void)
185 {
186 LIST_INIT(&http_media_types);
187 }
188
189 void
190 http_init(void)
191 {
192 int prealloc, l, i;
193
194 TAILQ_INIT(&http_requests);
195 TAILQ_INIT(&http_requests_sleeping);
196
197 header_buf = kore_buf_alloc(HTTP_HEADER_BUFSIZE);
198 ckhdr_buf = kore_buf_alloc(HTTP_COOKIE_BUFSIZE);
199
200 if (!http_version_len) {
201 l = snprintf(http_version, sizeof(http_version),
202 "server: kore (%s)\r\n", kore_version);
203 if (l == -1 || (size_t)l >= sizeof(http_version))
204 fatal("http_init(): http_version buffer too small");
205
206 http_version_len = l;
207 }
208
209 prealloc = MIN((worker_max_connections / 10), 1000);
210 kore_pool_init(&http_request_pool, "http_request_pool",
211 sizeof(struct http_request), http_request_limit);
212 kore_pool_init(&http_header_pool, "http_header_pool",
213 sizeof(struct http_header), prealloc * HTTP_REQ_HEADER_MAX);
214 kore_pool_init(&http_cookie_pool, "http_cookie_pool",
215 sizeof(struct http_cookie), prealloc * HTTP_MAX_COOKIES);
216 kore_pool_init(&http_rlq_pool, "http_rlq_pool",
217 sizeof(struct http_runlock_queue), http_request_limit);
218
219 kore_pool_init(&http_body_path,
220 "http_body_path", HTTP_BODY_PATH_MAX, prealloc);
221
222 for (i = 0; builtin_media[i].ext != NULL; i++) {
223 if (!http_media_register(builtin_media[i].ext,
224 builtin_media[i].type)) {
225 fatal("duplicate media type for %s",
226 builtin_media[i].ext);
227 }
228 }
229 }
230
231 void
232 http_cleanup(void)
233 {
234 if (header_buf != NULL) {
235 kore_buf_free(header_buf);
236 header_buf = NULL;
237 }
238
239 if (ckhdr_buf != NULL) {
240 kore_buf_free(ckhdr_buf);
241 ckhdr_buf = NULL;
242 }
243
244 kore_pool_cleanup(&http_request_pool);
245 kore_pool_cleanup(&http_header_pool);
246 kore_pool_cleanup(&http_body_path);
247 }
248
249 void
250 http_server_version(const char *version)
251 {
252 int l;
253
254 l = snprintf(http_version, sizeof(http_version),
255 "server: %s\r\n", version);
256 if (l == -1 || (size_t)l >= sizeof(http_version))
257 fatal("http_server_version(): http_version buffer too small");
258
259 http_version_len = l;
260 }
261
262 int
263 http_check_timeout(struct connection *c, u_int64_t now)
264 {
265 u_int64_t d;
266
267 if (c->http_timeout == 0)
268 return (KORE_RESULT_OK);
269
270 if (now > c->http_start)
271 d = now - c->http_start;
272 else
273 d = 0;
274
275 if (d >= c->http_timeout) {
276 http_error_response(c, HTTP_STATUS_REQUEST_TIMEOUT);
277 kore_connection_disconnect(c);
278 return (KORE_RESULT_ERROR);
279 }
280
281 return (KORE_RESULT_OK);
282 }
283
284 void
285 http_request_sleep(struct http_request *req)
286 {
287 if (!(req->flags & HTTP_REQUEST_SLEEPING)) {
288 req->flags |= HTTP_REQUEST_SLEEPING;
289 TAILQ_REMOVE(&http_requests, req, list);
290 TAILQ_INSERT_TAIL(&http_requests_sleeping, req, list);
291 }
292 }
293
294 void
295 http_request_wakeup(struct http_request *req)
296 {
297 if (req->flags & HTTP_REQUEST_SLEEPING) {
298 req->flags &= ~HTTP_REQUEST_SLEEPING;
299 TAILQ_REMOVE(&http_requests_sleeping, req, list);
300 TAILQ_INSERT_TAIL(&http_requests, req, list);
301 }
302 }
303
304 void
305 http_process(void)
306 {
307 u_int64_t total;
308 struct http_request *req, *next;
309
310 total = 0;
311
312 for (req = TAILQ_FIRST(&http_requests); req != NULL; req = next) {
313 if (total >= http_request_ms)
314 break;
315
316 next = TAILQ_NEXT(req, list);
317 if (req->flags & HTTP_REQUEST_DELETE) {
318 http_request_free(req);
319 continue;
320 }
321
322 /* Sleeping requests should be in http_requests_sleeping. */
323 if (req->flags & HTTP_REQUEST_SLEEPING)
324 fatal("http_process: sleeping request on list");
325
326 if (!(req->flags & HTTP_REQUEST_COMPLETE))
327 continue;
328
329 http_process_request(req);
330 total += req->ms;
331
332 if (req->flags & HTTP_REQUEST_DELETE)
333 http_request_free(req);
334 }
335 }
336
337 void
338 http_process_request(struct http_request *req)
339 {
340 int r;
341
342 if (req->flags & HTTP_REQUEST_DELETE || req->rt == NULL)
343 return;
344
345 req->start = kore_time_ms();
346 if (req->rt->auth != NULL && !(req->flags & HTTP_REQUEST_AUTHED))
347 r = kore_auth_run(req, req->rt->auth);
348 else
349 r = KORE_RESULT_OK;
350
351 switch (r) {
352 case KORE_RESULT_OK:
353 r = kore_runtime_http_request(req->rt->rcall, req);
354 break;
355 case KORE_RESULT_RETRY:
356 break;
357 case KORE_RESULT_ERROR:
358 /*
359 * Set r to KORE_RESULT_OK so we can properly
360 * flush the result from kore_auth_run().
361 */
362 r = KORE_RESULT_OK;
363 break;
364 default:
365 fatal("kore_auth() returned unknown %d", r);
366 }
367 req->end = kore_time_ms();
368 req->ms = req->end - req->start;
369 req->total += req->ms;
370
371 switch (r) {
372 case KORE_RESULT_OK:
373 r = net_send_flush(req->owner);
374 if (r == KORE_RESULT_ERROR)
375 kore_connection_disconnect(req->owner);
376 break;
377 case KORE_RESULT_ERROR:
378 kore_connection_disconnect(req->owner);
379 break;
380 case KORE_RESULT_RETRY:
381 return;
382 default:
383 fatal("A page handler returned an unknown result: %d", r);
384 }
385
386 if (req->rt->dom->accesslog)
387 kore_accesslog(req);
388
389 req->flags |= HTTP_REQUEST_DELETE;
390 }
391
392 void
393 http_response_header(struct http_request *req,
394 const char *header, const char *value)
395 {
396 struct http_header *hdr;
397
398 hdr = NULL;
399
400 TAILQ_FOREACH(hdr, &req->resp_headers, list) {
401 if (!strcasecmp(hdr->header, header)) {
402 TAILQ_REMOVE(&req->resp_headers, hdr, list);
403 kore_free(hdr->header);
404 kore_free(hdr->value);
405 break;
406 }
407 }
408
409 if (hdr == NULL)
410 hdr = kore_pool_get(&http_header_pool);
411
412 hdr->header = kore_strdup(header);
413 hdr->value = kore_strdup(value);
414
415 TAILQ_INSERT_TAIL(&(req->resp_headers), hdr, list);
416 }
417
418 void
419 http_request_free(struct http_request *req)
420 {
421 #if defined(KORE_USE_TASKS)
422 struct kore_task *t, *nt;
423 int pending_tasks;
424 #endif
425 #if defined(KORE_USE_PGSQL)
426 struct kore_pgsql *pgsql;
427 #endif
428 #if defined(KORE_USE_CURL)
429 struct kore_curl *client;
430 #endif
431 struct http_file *f, *fnext;
432 struct http_arg *q, *qnext;
433 struct http_header *hdr, *next;
434 struct http_cookie *ck, *cknext;
435
436 if (req->rt != NULL && req->rt->on_free != NULL)
437 kore_runtime_http_request_free(req->rt->on_free, req);
438
439 if (req->runlock != NULL) {
440 LIST_REMOVE(req->runlock, list);
441 req->runlock = NULL;
442 }
443
444 #if defined(KORE_USE_TASKS)
445 pending_tasks = 0;
446 for (t = LIST_FIRST(&(req->tasks)); t != NULL; t = nt) {
447 nt = LIST_NEXT(t, rlist);
448 if (!kore_task_finished(t)) {
449 pending_tasks++;
450 } else {
451 kore_task_destroy(t);
452 }
453 }
454
455 if (pending_tasks)
456 return;
457 #endif
458
459 #if defined(KORE_USE_PYTHON)
460 if (req->py_coro != NULL) {
461 kore_python_coro_delete(req->py_coro);
462 req->py_coro = NULL;
463 }
464 if (req->py_validator != NULL) {
465 kore_python_coro_delete(req->py_validator);
466 req->py_validator = NULL;
467 }
468 Py_XDECREF(req->py_req);
469 #endif
470 #if defined(KORE_USE_PGSQL)
471 while (!LIST_EMPTY(&(req->pgsqls))) {
472 pgsql = LIST_FIRST(&(req->pgsqls));
473 kore_pgsql_cleanup(pgsql);
474 }
475 #endif
476 #if defined(KORE_USE_CURL)
477 while (!LIST_EMPTY(&req->chandles)) {
478 client = LIST_FIRST(&req->chandles);
479 kore_curl_cleanup(client);
480 }
481 #endif
482 kore_free(req->headers);
483
484 req->host = NULL;
485 req->path = NULL;
486 req->headers = NULL;
487
488 TAILQ_REMOVE(&http_requests, req, list);
489 if (req->owner != NULL)
490 TAILQ_REMOVE(&(req->owner->http_requests), req, olist);
491
492 for (hdr = TAILQ_FIRST(&(req->resp_headers)); hdr != NULL; hdr = next) {
493 next = TAILQ_NEXT(hdr, list);
494 TAILQ_REMOVE(&(req->resp_headers), hdr, list);
495 kore_free(hdr->header);
496 kore_free(hdr->value);
497 kore_pool_put(&http_header_pool, hdr);
498 }
499
500 for (hdr = TAILQ_FIRST(&(req->req_headers)); hdr != NULL; hdr = next) {
501 next = TAILQ_NEXT(hdr, list);
502 TAILQ_REMOVE(&(req->req_headers), hdr, list);
503 kore_pool_put(&http_header_pool, hdr);
504 }
505
506 for (ck = TAILQ_FIRST(&(req->resp_cookies)); ck != NULL; ck = cknext) {
507 cknext = TAILQ_NEXT(ck, list);
508 TAILQ_REMOVE(&(req->resp_cookies), ck, list);
509 kore_free(ck->name);
510 kore_free(ck->value);
511 kore_free(ck->path);
512 kore_free(ck->domain);
513 kore_pool_put(&http_cookie_pool, ck);
514 }
515
516 for (ck = TAILQ_FIRST(&(req->req_cookies)); ck != NULL; ck = cknext) {
517 cknext = TAILQ_NEXT(ck, list);
518 TAILQ_REMOVE(&(req->req_cookies), ck, list);
519 kore_free(ck->name);
520 kore_free(ck->value);
521 kore_pool_put(&http_cookie_pool, ck);
522 }
523
524 for (q = TAILQ_FIRST(&(req->arguments)); q != NULL; q = qnext) {
525 qnext = TAILQ_NEXT(q, list);
526 TAILQ_REMOVE(&(req->arguments), q, list);
527 kore_free(q->name);
528 kore_free(q->s_value);
529 kore_free(q);
530 }
531
532 for (f = TAILQ_FIRST(&(req->files)); f != NULL; f = fnext) {
533 fnext = TAILQ_NEXT(f, list);
534 TAILQ_REMOVE(&(req->files), f, list);
535 kore_free(f->filename);
536 kore_free(f->name);
537 kore_free(f);
538 }
539
540 if (req->http_body != NULL)
541 kore_buf_free(req->http_body);
542
543 if (req->http_body_fd != -1)
544 (void)close(req->http_body_fd);
545
546 if (req->http_body_path != NULL) {
547 if (unlink(req->http_body_path) == -1 && errno != ENOENT) {
548 kore_log(LOG_NOTICE, "failed to unlink %s: %s",
549 req->http_body_path, errno_s);
550 }
551 kore_pool_put(&http_body_path, req->http_body_path);
552 }
553
554 if (req->hdlr_extra != NULL &&
555 !(req->flags & HTTP_REQUEST_RETAIN_EXTRA))
556 kore_free(req->hdlr_extra);
557
558 kore_pool_put(&http_request_pool, req);
559 http_request_count--;
560 }
561
562 void
563 http_serveable(struct http_request *req, const void *data, size_t len,
564 const char *etag, const char *type)
565 {
566 const char *match;
567
568 if (req->method != HTTP_METHOD_GET) {
569 http_response_header(req, "allow", "get");
570 http_response(req, HTTP_STATUS_BAD_REQUEST, NULL, 0);
571 return;
572 }
573
574 if (http_request_header(req, "if-none-match", &match)) {
575 if (!strcmp(match, etag)) {
576 http_response(req, HTTP_STATUS_NOT_MODIFIED, NULL, 0);
577 return;
578 }
579 }
580
581 http_response_header(req, "etag", etag);
582 http_response_header(req, "content-type", type);
583 http_response(req, HTTP_STATUS_OK, data, len);
584 }
585
586 void
587 http_response(struct http_request *req, int code, const void *d, size_t l)
588 {
589 if (req->owner == NULL)
590 return;
591
592 req->status = code;
593
594 switch (req->owner->proto) {
595 case CONN_PROTO_HTTP:
596 case CONN_PROTO_WEBSOCKET:
597 http_response_normal(req, req->owner, code, d, l);
598 break;
599 default:
600 fatal("%s: bad proto %d", __func__, req->owner->proto);
601 /* NOTREACHED. */
602 }
603 }
604
605 void
606 http_response_close(struct http_request *req, int code, const void *d, size_t l)
607 {
608 if (req->owner == NULL)
609 return;
610
611 req->status = code;
612 req->owner->flags |= CONN_CLOSE_EMPTY;
613
614 switch (req->owner->proto) {
615 case CONN_PROTO_HTTP:
616 case CONN_PROTO_WEBSOCKET:
617 http_response_normal(req, req->owner, code, d, l);
618 break;
619 default:
620 fatal("%s: bad proto %d", __func__, req->owner->proto);
621 /* NOTREACHED. */
622 }
623 }
624
625 void
626 http_response_json(struct http_request *req, int status,
627 struct kore_json_item *json)
628 {
629 struct kore_buf *buf;
630
631 if (req->owner == NULL)
632 return;
633
634 buf = kore_buf_alloc(1024);
635 kore_json_item_tobuf(json, buf);
636 kore_json_item_free(json);
637
638 req->status = status;
639 http_response_header(req, "content-type", "application/json");
640
641 switch (req->owner->proto) {
642 case CONN_PROTO_HTTP:
643 http_response_stream(req, status, buf->data, buf->offset,
644 http_release_buffer, buf);
645 break;
646 default:
647 fatal("%s: bad proto %d", __func__, req->owner->proto);
648 /* NOTREACHED. */
649 }
650 }
651
652 void
653 http_response_stream(struct http_request *req, int status, void *base,
654 size_t len, int (*cb)(struct netbuf *), void *arg)
655 {
656 struct netbuf *nb;
657
658 if (req->owner == NULL)
659 return;
660
661 req->status = status;
662
663 switch (req->owner->proto) {
664 case CONN_PROTO_HTTP:
665 http_response_normal(req, req->owner, status, NULL, len);
666 break;
667 default:
668 fatal("%s: bad proto %d", __func__, req->owner->proto);
669 /* NOTREACHED. */
670 }
671
672 net_send_stream(req->owner, base, len, cb, &nb);
673 nb->extra = arg;
674
675 if (req->method == HTTP_METHOD_HEAD) {
676 nb->s_off = nb->b_len;
677 net_remove_netbuf(req->owner, nb);
678 }
679 }
680
681 void
682 http_response_fileref(struct http_request *req, int status,
683 struct kore_fileref *ref)
684 {
685 struct tm *tm;
686 time_t mtime;
687 char tbuf[128];
688 const char *media_type, *modified;
689
690 if (req->owner == NULL)
691 return;
692
693 media_type = http_media_type(ref->path);
694 if (media_type != NULL)
695 http_response_header(req, "content-type", media_type);
696
697 if (http_request_header(req, "if-modified-since", &modified)) {
698 mtime = kore_date_to_time(modified);
699 if (mtime == ref->mtime_sec) {
700 kore_fileref_release(ref);
701 http_response(req, HTTP_STATUS_NOT_MODIFIED, NULL, 0);
702 return;
703 }
704 }
705
706 if ((tm = gmtime(&ref->mtime_sec)) != NULL) {
707 if (strftime(tbuf, sizeof(tbuf),
708 "%a, %d %b %Y %H:%M:%S GMT", tm) > 0) {
709 http_response_header(req, "last-modified", tbuf);
710 }
711 }
712
713 req->status = status;
714 switch (req->owner->proto) {
715 case CONN_PROTO_HTTP:
716 http_response_normal(req, req->owner, status, NULL, ref->size);
717 break;
718 default:
719 fatal("http_response_fd() bad proto %d", req->owner->proto);
720 /* NOTREACHED. */
721 }
722
723 if (req->method != HTTP_METHOD_HEAD)
724 net_send_fileref(req->owner, ref);
725 else
726 kore_fileref_release(ref);
727 }
728
729 int
730 http_request_header(struct http_request *req, const char *header,
731 const char **out)
732 {
733 struct http_header *hdr;
734
735 TAILQ_FOREACH(hdr, &(req->req_headers), list) {
736 if (!strcasecmp(hdr->header, header)) {
737 *out = hdr->value;
738 return (KORE_RESULT_OK);
739 }
740 }
741
742 if (!strcasecmp(header, "host")) {
743 *out = req->host;
744 return (KORE_RESULT_OK);
745 }
746
747 return (KORE_RESULT_ERROR);
748 }
749
750 int
751 http_request_header_get(struct http_request *req, const char *header,
752 void **out, void *nout, int type)
753 {
754 struct http_header *hdr;
755
756 if (type == HTTP_ARG_TYPE_STRING)
757 fatal("%s: cannot be called with type string", __func__);
758
759 TAILQ_FOREACH(hdr, &req->req_headers, list) {
760 if (strcasecmp(hdr->header, header))
761 continue;
762
763 if (http_data_convert(hdr->value, out, nout, type))
764 return (KORE_RESULT_OK);
765
766 return (KORE_RESULT_ERROR);
767 }
768
769 return (KORE_RESULT_ERROR);
770 }
771
772 int
773 http_request_cookie(struct http_request *req, const char *cookie, char **out)
774 {
775 struct http_cookie *ck;
776
777 TAILQ_FOREACH(ck, &(req->req_cookies), list) {
778 if (!strcasecmp(ck->name, cookie)) {
779 *out = ck->value;
780 return (KORE_RESULT_OK);
781 }
782 }
783
784 return (KORE_RESULT_ERROR);
785 }
786
787 int
788 http_header_recv(struct netbuf *nb)
789 {
790 struct connection *c;
791 size_t len;
792 struct http_header *hdr;
793 struct http_request *req;
794 u_int8_t *end_headers;
795 int h, i, v, skip, l;
796 char *headers[HTTP_REQ_HEADER_MAX];
797 char *value, *host, *request[4], *hbuf;
798
799 c = nb->owner;
800
801 if (nb->s_off < 4)
802 return (KORE_RESULT_OK);
803
804 if (!isalpha(nb->buf[0])) {
805 http_error_response(c, HTTP_STATUS_BAD_REQUEST);
806 return (KORE_RESULT_ERROR);
807 }
808
809 skip = 4;
810 end_headers = kore_mem_find(nb->buf, nb->s_off, "\r\n\r\n", 4);
811 if (end_headers == NULL) {
812 end_headers = kore_mem_find(nb->buf, nb->s_off, "\n\n", 2);
813 if (end_headers == NULL) {
814 if (nb->s_off == http_header_max) {
815 http_error_response(c,
816 HTTP_STATUS_REQUEST_ENTITY_TOO_LARGE);
817 return (KORE_RESULT_ERROR);
818 }
819 return (KORE_RESULT_OK);
820 }
821 skip = 2;
822 }
823
824 *end_headers = '\0';
825 end_headers += skip;
826 len = end_headers - nb->buf;
827 hbuf = (char *)nb->buf;
828
829 h = kore_split_string(hbuf, "\r\n", headers, HTTP_REQ_HEADER_MAX);
830 if (h < 2) {
831 http_error_response(c, HTTP_STATUS_BAD_REQUEST);
832 return (KORE_RESULT_OK);
833 }
834
835 v = kore_split_string(headers[0], " ", request, 4);
836 if (v != 3) {
837 http_error_response(c, HTTP_STATUS_BAD_REQUEST);
838 return (KORE_RESULT_OK);
839 }
840
841 skip = 0;
842 host = NULL;
843 for (i = 0; i < h; i++) {
844 if (strncasecmp(headers[i], "host", 4))
845 continue;
846
847 if ((host = http_validate_header(headers[i])) == NULL) {
848 http_error_response(c, HTTP_STATUS_BAD_REQUEST);
849 return (KORE_RESULT_OK);
850 }
851
852 if (*host == '\0') {
853 http_error_response(c, HTTP_STATUS_BAD_REQUEST);
854 return (KORE_RESULT_OK);
855 }
856
857 skip = i;
858 break;
859 }
860
861 if (host == NULL) {
862 http_error_response(c, HTTP_STATUS_BAD_REQUEST);
863 return (KORE_RESULT_OK);
864 }
865
866 req = http_request_new(c, host, request[0], request[1], request[2]);
867 if (req == NULL)
868 return (KORE_RESULT_OK);
869
870 /* take full ownership of the buffer. */
871 req->headers = nb->buf;
872 nb->buf = NULL;
873 nb->m_len = 0;
874
875 for (i = 1; i < h; i++) {
876 if (i == skip)
877 continue;
878
879 if ((value = http_validate_header(headers[i])) == NULL) {
880 req->flags |= HTTP_REQUEST_DELETE;
881 http_error_response(c, HTTP_STATUS_BAD_REQUEST);
882 return (KORE_RESULT_OK);
883 }
884
885 if (*value == '\0') {
886 req->flags |= HTTP_REQUEST_DELETE;
887 http_error_response(c, HTTP_STATUS_BAD_REQUEST);
888 return (KORE_RESULT_OK);
889 }
890
891 hdr = kore_pool_get(&http_header_pool);
892 hdr->header = headers[i];
893 hdr->value = value;
894 TAILQ_INSERT_TAIL(&(req->req_headers), hdr, list);
895
896 if (req->agent == NULL &&
897 !strcasecmp(hdr->header, "user-agent"))
898 req->agent = hdr->value;
899
900 if (req->referer == NULL &&
901 !strcasecmp(hdr->header, "referer"))
902 req->referer = hdr->value;
903 }
904
905 if (req->flags & HTTP_REQUEST_EXPECT_BODY) {
906 if (http_body_max == 0) {
907 req->flags |= HTTP_REQUEST_DELETE;
908 http_error_response(req->owner,
909 HTTP_STATUS_METHOD_NOT_ALLOWED);
910 return (KORE_RESULT_OK);
911 }
912
913 if (!http_request_header_uint64(req, "content-length",
914 &req->content_length)) {
915 if (req->method == HTTP_METHOD_DELETE) {
916 req->flags |= HTTP_REQUEST_COMPLETE;
917 return (KORE_RESULT_OK);
918 }
919
920 req->flags |= HTTP_REQUEST_DELETE;
921 http_error_response(req->owner,
922 HTTP_STATUS_LENGTH_REQUIRED);
923 return (KORE_RESULT_OK);
924 }
925
926 if (req->content_length == 0) {
927 c->http_timeout = 0;
928 req->flags |= HTTP_REQUEST_COMPLETE;
929 req->flags &= ~HTTP_REQUEST_EXPECT_BODY;
930 return (KORE_RESULT_OK);
931 }
932
933 if (((nb->s_off - len) > req->content_length) ||
934 (req->content_length > http_body_max)) {
935 req->flags |= HTTP_REQUEST_DELETE;
936 http_error_response(req->owner,
937 HTTP_STATUS_REQUEST_ENTITY_TOO_LARGE);
938 return (KORE_RESULT_OK);
939 }
940
941 req->http_body_length = req->content_length;
942
943 if (req->rt->on_body_chunk == NULL &&
944 http_body_disk_offload > 0 &&
945 req->content_length > http_body_disk_offload) {
946 req->http_body_path = kore_pool_get(&http_body_path);
947 l = snprintf(req->http_body_path, HTTP_BODY_PATH_MAX,
948 "%s/http_body.XXXXXX", http_body_disk_path);
949 if (l == -1 || (size_t)l >= HTTP_BODY_PATH_MAX) {
950 req->flags |= HTTP_REQUEST_DELETE;
951 http_error_response(req->owner,
952 HTTP_STATUS_INTERNAL_ERROR);
953 return (KORE_RESULT_ERROR);
954 }
955
956 req->http_body = NULL;
957 req->http_body_fd = mkstemp(req->http_body_path);
958 if (req->http_body_fd == -1) {
959 req->flags |= HTTP_REQUEST_DELETE;
960 http_error_response(req->owner,
961 HTTP_STATUS_INTERNAL_ERROR);
962 return (KORE_RESULT_OK);
963 }
964 } else if (req->rt->on_body_chunk == NULL) {
965 req->http_body_fd = -1;
966 req->http_body = kore_buf_alloc(req->content_length);
967 }
968
969 SHA256Init(&req->hashctx);
970 c->http_timeout = http_body_timeout * 1000;
971
972 if (!http_body_update(req, end_headers, nb->s_off - len)) {
973 req->flags |= HTTP_REQUEST_DELETE;
974 http_error_response(req->owner,
975 HTTP_STATUS_INTERNAL_ERROR);
976 return (KORE_RESULT_OK);
977 }
978 } else {
979 c->http_timeout = 0;
980 }
981
982 if (req->rt->on_headers != NULL) {
983 if (!kore_runtime_http_request(req->rt->on_headers, req)) {
984 req->flags |= HTTP_REQUEST_DELETE;
985 return (KORE_RESULT_OK);
986 }
987 }
988
989 return (KORE_RESULT_OK);
990 }
991
992 int
993 http_argument_get(struct http_request *req, const char *name,
994 void **out, void *nout, int type)
995 {
996 struct http_arg *q;
997
998 TAILQ_FOREACH(q, &(req->arguments), list) {
999 if (strcmp(q->name, name))
1000 continue;
1001
1002 if (http_data_convert(q->s_value, out, nout, type))
1003 return (KORE_RESULT_OK);
1004
1005 break;
1006 }
1007
1008 return (KORE_RESULT_ERROR);
1009 }
1010
1011 int
1012 http_argument_urldecode(char *arg, int url)
1013 {
1014 u_int8_t v;
1015 int err;
1016 size_t len;
1017 char *p, *in, h[5];
1018
1019 p = arg;
1020 in = arg;
1021 len = strlen(arg);
1022
1023 while (*p != '\0' && p < (arg + len)) {
1024 if (*p == '+')
1025 *p = ' ';
1026 if (*p != '%') {
1027 *in++ = *p++;
1028 continue;
1029 }
1030
1031 if ((p + 2) >= (arg + len))
1032 return (KORE_RESULT_ERROR);
1033
1034 if (!isxdigit((unsigned char)*(p + 1)) ||
1035 !isxdigit((unsigned char)*(p + 2))) {
1036 *in++ = *p++;
1037 continue;
1038 }
1039
1040 h[0] = '0';
1041 h[1] = 'x';
1042 h[2] = *(p + 1);
1043 h[3] = *(p + 2);
1044 h[4] = '\0';
1045
1046 v = kore_strtonum(h, 16, 0x0, 0xff, &err);
1047 if (err != KORE_RESULT_OK)
1048 return (err);
1049
1050 if (url) {
1051 if (v <= 0x1f || v == 0x7f)
1052 return (KORE_RESULT_ERROR);
1053 } else {
1054 if ((v <= 0x1f || v == 0x7f) &&
1055 (v != '\n' && v != '\r' && v != '\t'))
1056 return (KORE_RESULT_ERROR);
1057 }
1058
1059 *in++ = (char)v;
1060 p += 3;
1061 }
1062
1063 *in = '\0';
1064 return (KORE_RESULT_OK);
1065 }
1066
1067 struct http_file *
1068 http_file_lookup(struct http_request *req, const char *name)
1069 {
1070 struct http_file *f;
1071
1072 TAILQ_FOREACH(f, &(req->files), list) {
1073 if (!strcmp(f->name, name))
1074 return (f);
1075 }
1076
1077 return (NULL);
1078 }
1079
1080 ssize_t
1081 http_file_read(struct http_file *file, void *buf, size_t len)
1082 {
1083 ssize_t ret;
1084 size_t toread, off;
1085
1086 if (file->length < file->offset)
1087 return (-1);
1088 if ((file->offset + len) < file->offset)
1089 return (-1);
1090 if ((file->position + file->offset) < file->position)
1091 return (-1);
1092
1093 off = file->position + file->offset;
1094 toread = MIN(len, (file->length - file->offset));
1095 if (toread == 0)
1096 return (0);
1097
1098 if (file->req->http_body_fd != -1) {
1099 if (lseek(file->req->http_body_fd, off, SEEK_SET) == -1) {
1100 kore_log(LOG_ERR, "http_file_read: lseek(%s): %s",
1101 file->req->http_body_path, errno_s);
1102 return (-1);
1103 }
1104
1105 for (;;) {
1106 ret = read(file->req->http_body_fd, buf, toread);
1107 if (ret == -1) {
1108 if (errno == EINTR)
1109 continue;
1110 kore_log(LOG_ERR, "failed to read %s: %s",
1111 file->req->http_body_path, errno_s);
1112 return (-1);
1113 }
1114 if (ret == 0)
1115 return (0);
1116 break;
1117 }
1118 } else if (file->req->http_body != NULL) {
1119 if (off > file->req->http_body->length)
1120 return (0);
1121 memcpy(buf, file->req->http_body->data + off, toread);
1122 ret = toread;
1123 } else {
1124 kore_log(LOG_ERR, "http_file_read: called without body");
1125 return (-1);
1126 }
1127
1128 file->offset += (size_t)ret;
1129 return (ret);
1130 }
1131
1132 void
1133 http_file_rewind(struct http_file *file)
1134 {
1135 file->offset = 0;
1136 }
1137
1138 void
1139 http_response_cookie(struct http_request *req, const char *name,
1140 const char *val, const char *path, time_t expires, u_int32_t maxage,
1141 struct http_cookie **out)
1142 {
1143 char *p;
1144 struct http_cookie *ck;
1145
1146 if (name == NULL || val == NULL)
1147 fatal("http_response_cookie: invalid parameters");
1148
1149 ck = kore_pool_get(&http_cookie_pool);
1150
1151 ck->maxage = maxage;
1152 ck->expires = expires;
1153 ck->name = kore_strdup(name);
1154 ck->value = kore_strdup(val);
1155 ck->domain = kore_strdup(req->host);
1156 ck->flags = HTTP_COOKIE_HTTPONLY | HTTP_COOKIE_SECURE;
1157
1158 if ((p = strrchr(ck->domain, ':')) != NULL)
1159 *p = '\0';
1160
1161 if (path != NULL)
1162 ck->path = kore_strdup(path);
1163 else
1164 ck->path = NULL;
1165
1166 TAILQ_INSERT_TAIL(&(req->resp_cookies), ck, list);
1167
1168 if (out != NULL)
1169 *out = ck;
1170 }
1171
1172 void
1173 http_populate_cookies(struct http_request *req)
1174 {
1175 struct http_cookie *ck;
1176 const char *hdr;
1177 int i, v, n;
1178 char *c, *header, *pair[3];
1179 char *cookies[HTTP_MAX_COOKIES];
1180
1181 if (!http_request_header(req, "cookie", &hdr))
1182 return;
1183
1184 header = kore_strdup(hdr);
1185 v = kore_split_string(header, ";", cookies, HTTP_MAX_COOKIES);
1186 for (i = 0; i < v; i++) {
1187 for (c = cookies[i]; isspace(*(unsigned char *)c); c++)
1188 ;
1189
1190 n = kore_split_string(c, "=", pair, 3);
1191 if (n != 2)
1192 continue;
1193
1194 ck = kore_pool_get(&http_cookie_pool);
1195 ck->name = kore_strdup(pair[0]);
1196 ck->value = kore_strdup(pair[1]);
1197 TAILQ_INSERT_TAIL(&(req->req_cookies), ck, list);
1198 }
1199
1200 kore_free(header);
1201 }
1202
1203 void
1204 http_populate_post(struct http_request *req)
1205 {
1206 ssize_t ret;
1207 int i, v;
1208 struct kore_buf *body;
1209 char data[BUFSIZ];
1210 char *args[HTTP_MAX_QUERY_ARGS], *val[3], *string;
1211
1212 if (req->method != HTTP_METHOD_POST)
1213 return;
1214
1215 if (req->http_body != NULL) {
1216 body = NULL;
1217 req->http_body->offset = req->content_length;
1218 string = kore_buf_stringify(req->http_body, NULL);
1219 req->http_body_length = 0;
1220 req->http_body_offset = 0;
1221 } else {
1222 body = kore_buf_alloc(128);
1223 for (;;) {
1224 ret = http_body_read(req, data, sizeof(data));
1225 if (ret == -1)
1226 goto out;
1227 if (ret == 0)
1228 break;
1229 kore_buf_append(body, data, ret);
1230 }
1231 string = kore_buf_stringify(body, NULL);
1232 }
1233
1234 v = kore_split_string(string, "&", args, HTTP_MAX_QUERY_ARGS);
1235 for (i = 0; i < v; i++) {
1236 kore_split_string(args[i], "=", val, 3);
1237 if (val[0] != NULL && val[1] != NULL)
1238 http_argument_add(req, val[0], val[1], 0, 1);
1239 }
1240
1241 out:
1242 if (body != NULL)
1243 kore_buf_free(body);
1244 }
1245
1246 void
1247 http_populate_qs(struct http_request *req)
1248 {
1249 int i, v;
1250 char *query, *args[HTTP_MAX_QUERY_ARGS], *val[3];
1251
1252 if (req->query_string == NULL)
1253 return;
1254
1255 query = kore_strdup(req->query_string);
1256 v = kore_split_string(query, "&", args, HTTP_MAX_QUERY_ARGS);
1257 for (i = 0; i < v; i++) {
1258 kore_split_string(args[i], "=", val, 3);
1259 if (val[0] != NULL && val[1] != NULL)
1260 http_argument_add(req, val[0], val[1], 1, 1);
1261 }
1262
1263 kore_free(query);
1264 }
1265
1266 void
1267 http_populate_multipart_form(struct http_request *req)
1268 {
1269 const char *hdr;
1270 int h, blen;
1271 struct kore_buf in, out;
1272 char *type, *val, *args[3];
1273 char boundary[HTTP_BOUNDARY_MAX];
1274
1275 if (req->method != HTTP_METHOD_POST)
1276 return;
1277
1278 if (!http_request_header(req, "content-type", &hdr))
1279 return;
1280
1281 kore_buf_init(&in, 128);
1282 kore_buf_init(&out, 128);
1283
1284 type = kore_strdup(hdr);
1285 h = kore_split_string(type, ";", args, 3);
1286 if (h != 2)
1287 goto cleanup;
1288
1289 if (strcasecmp(args[0], "multipart/form-data"))
1290 goto cleanup;
1291
1292 if ((val = strchr(args[1], '=')) == NULL)
1293 goto cleanup;
1294
1295 val++;
1296 blen = snprintf(boundary, sizeof(boundary), "--%s", val);
1297 if (blen == -1 || (size_t)blen >= sizeof(boundary))
1298 goto cleanup;
1299
1300 if (!multipart_find_data(&in, NULL, NULL, req, boundary, blen))
1301 goto cleanup;
1302
1303 for (;;) {
1304 if (!multipart_find_data(&in, NULL, NULL, req, "\r\n", 2))
1305 break;
1306 if (in.offset < 4 && req->http_body_length == 0)
1307 break;
1308 if (!multipart_find_data(&in, &out, NULL, req, "\r\n\r\n", 4))
1309 break;
1310 if (!multipart_parse_headers(req, &in, &out, boundary, blen))
1311 break;
1312
1313 kore_buf_reset(&out);
1314 }
1315
1316 cleanup:
1317 kore_free(type);
1318 kore_buf_cleanup(&in);
1319 kore_buf_cleanup(&out);
1320 }
1321
1322 int
1323 http_body_rewind(struct http_request *req)
1324 {
1325 if (req->http_body_fd != -1) {
1326 if (lseek(req->http_body_fd, 0, SEEK_SET) == -1) {
1327 kore_log(LOG_ERR, "lseek(%s) failed: %s",
1328 req->http_body_path, errno_s);
1329 return (KORE_RESULT_ERROR);
1330 }
1331 } else if (req->http_body != NULL) {
1332 kore_buf_reset(req->http_body);
1333 }
1334
1335 req->http_body_offset = 0;
1336 req->http_body_length = req->content_length;
1337
1338 return (KORE_RESULT_OK);
1339 }
1340
1341 int
1342 http_body_digest(struct http_request *req, char *out, size_t len)
1343 {
1344 size_t idx;
1345 int slen;
1346
1347 if (len != HTTP_BODY_DIGEST_STRLEN) {
1348 fatal("http_body_digest: bad len:%zu wanted:%u",
1349 len, HTTP_BODY_DIGEST_STRLEN);
1350 }
1351
1352 if (!(req->flags & HTTP_REQUEST_COMPLETE))
1353 return (KORE_RESULT_ERROR);
1354
1355 for (idx = 0; idx < sizeof(req->http_body_digest); idx++) {
1356 slen = snprintf(out + (idx * 2), len - (idx * 2), "%02x",
1357 req->http_body_digest[idx]);
1358 if (slen == -1 || (size_t)slen >= len)
1359 fatal("failed to create hex string");
1360 }
1361
1362 return (KORE_RESULT_OK);
1363 }
1364
1365 ssize_t
1366 http_body_read(struct http_request *req, void *out, size_t len)
1367 {
1368 ssize_t ret;
1369 size_t toread;
1370
1371 toread = MIN(req->http_body_length, len);
1372 if (toread == 0)
1373 return (0);
1374
1375 if (req->http_body_fd != -1) {
1376 for (;;) {
1377 ret = read(req->http_body_fd, out, toread);
1378 if (ret == -1) {
1379 if (errno == EINTR)
1380 continue;
1381 kore_log(LOG_ERR, "failed to read %s: %s",
1382 req->http_body_path, errno_s);
1383 return (-1);
1384 }
1385 if (ret == 0)
1386 return (0);
1387 break;
1388 }
1389 } else if (req->http_body != NULL) {
1390 memcpy(out,
1391 (req->http_body->data + req->http_body->offset), toread);
1392 req->http_body->offset += toread;
1393 ret = toread;
1394 } else {
1395 kore_log(LOG_ERR, "http_body_read: called without body");
1396 return (-1);
1397 }
1398
1399 req->http_body_length -= (size_t)ret;
1400 req->http_body_offset += (size_t)ret;
1401
1402 return (ret);
1403 }
1404
1405 int
1406 http_state_run(struct http_state *states, u_int8_t elm,
1407 struct http_request *req)
1408 {
1409 int r, done;
1410
1411 done = 0;
1412
1413 while (!done) {
1414 if (req->fsm_state >= elm) {
1415 fatal("http_state_run: fsm_state > elm (%d/%d)",
1416 req->fsm_state, elm);
1417 }
1418
1419 r = states[req->fsm_state].cb(req);
1420 switch (r) {
1421 case HTTP_STATE_ERROR:
1422 return (KORE_RESULT_OK);
1423 case HTTP_STATE_RETRY:
1424 return (KORE_RESULT_RETRY);
1425 case HTTP_STATE_CONTINUE:
1426 break;
1427 case HTTP_STATE_COMPLETE:
1428 done = 1;
1429 break;
1430 default:
1431 fatal("http_state_run: unknown return value %d", r);
1432 }
1433 }
1434
1435 req->fsm_state = 0;
1436
1437 return (KORE_RESULT_OK);
1438 }
1439
1440 int
1441 http_state_exists(struct http_request *req)
1442 {
1443 return (req->hdlr_extra != NULL);
1444 }
1445
1446 void *
1447 http_state_create(struct http_request *req, size_t len)
1448 {
1449 if (req->hdlr_extra != NULL)
1450 fatal("http_state_create: state already exists");
1451
1452 req->state_len = len;
1453 req->hdlr_extra = kore_calloc(1, len);
1454
1455 return (req->hdlr_extra);
1456 }
1457
1458 void *
1459 http_state_get(struct http_request *req)
1460 {
1461 return (req->hdlr_extra);
1462 }
1463
1464 void
1465 http_state_cleanup(struct http_request *req)
1466 {
1467 kore_free(req->hdlr_extra);
1468 req->hdlr_extra = NULL;
1469 }
1470
1471 void
1472 http_start_recv(struct connection *c)
1473 {
1474 c->http_start = kore_time_ms();
1475 c->http_timeout = http_header_timeout * 1000;
1476 net_recv_reset(c, http_header_max, http_header_recv);
1477 }
1478
1479 void
1480 http_runlock_init(struct http_runlock *lock)
1481 {
1482 lock->owner = NULL;
1483 LIST_INIT(&lock->queue);
1484 }
1485
1486 int
1487 http_runlock_acquire(struct http_runlock *lock, struct http_request *req)
1488 {
1489 if (lock->owner != NULL) {
1490 if (req->runlock != NULL)
1491 fatal("%s: request already waiting on lock", __func__);
1492
1493 req->runlock = kore_pool_get(&http_rlq_pool);
1494 req->runlock->req = req;
1495 LIST_INSERT_HEAD(&lock->queue, req->runlock, list);
1496
1497 http_request_sleep(req);
1498 return (KORE_RESULT_ERROR);
1499 }
1500
1501 lock->owner = req;
1502
1503 return (KORE_RESULT_OK);
1504 }
1505
1506 void
1507 http_runlock_release(struct http_runlock *lock, struct http_request *req)
1508 {
1509 struct http_runlock_queue *next;
1510 struct http_request *nextreq;
1511
1512 if (lock->owner != req)
1513 fatal("%s: calling request != owner of runlock", __func__);
1514
1515 lock->owner = NULL;
1516
1517 if ((next = LIST_FIRST(&lock->queue)) != NULL) {
1518 LIST_REMOVE(next, list);
1519
1520 nextreq = next->req;
1521 nextreq->runlock = NULL;
1522
1523 http_request_wakeup(nextreq);
1524 kore_pool_put(&http_rlq_pool, next);
1525 }
1526 }
1527
1528 int
1529 http_redirect_add(struct kore_domain *dom, const char *path, int status,
1530 const char *target)
1531 {
1532 struct http_redirect *rdr;
1533
1534 rdr = kore_calloc(1, sizeof(*rdr));
1535
1536 if (regcomp(&(rdr->rctx), path, REG_EXTENDED)) {
1537 kore_free(rdr);
1538 return (KORE_RESULT_ERROR);
1539 }
1540
1541 rdr->status = status;
1542
1543 if (target != NULL)
1544 rdr->target = kore_strdup(target);
1545 else
1546 rdr->target = NULL;
1547
1548 TAILQ_INSERT_TAIL(&dom->redirects, rdr, list);
1549
1550 return (KORE_RESULT_OK);
1551 }
1552
1553 const char *
1554 http_status_text(int status)
1555 {
1556 const char *r;
1557
1558 switch (status) {
1559 case HTTP_STATUS_CONTINUE:
1560 r = "Continue";
1561 break;
1562 case HTTP_STATUS_SWITCHING_PROTOCOLS:
1563 r = "Switching Protocols";
1564 break;
1565 case HTTP_STATUS_OK:
1566 r = "OK";
1567 break;
1568 case HTTP_STATUS_CREATED:
1569 r = "Created";
1570 break;
1571 case HTTP_STATUS_ACCEPTED:
1572 r = "Accepted";
1573 break;
1574 case HTTP_STATUS_NON_AUTHORITATIVE:
1575 r = "Non-Authoritative Information";
1576 break;
1577 case HTTP_STATUS_NO_CONTENT:
1578 r = "No Content";
1579 break;
1580 case HTTP_STATUS_RESET_CONTENT:
1581 r = "Reset Content";
1582 break;
1583 case HTTP_STATUS_PARTIAL_CONTENT:
1584 r = "Partial Content";
1585 break;
1586 case HTTP_STATUS_MULTIPLE_CHOICES:
1587 r = "Multiple Choices";
1588 break;
1589 case HTTP_STATUS_MOVED_PERMANENTLY:
1590 r = "Moved Permanently";
1591 break;
1592 case HTTP_STATUS_FOUND:
1593 r = "Found";
1594 break;
1595 case HTTP_STATUS_SEE_OTHER:
1596 r = "See Other";
1597 break;
1598 case HTTP_STATUS_NOT_MODIFIED:
1599 r = "Not Modified";
1600 break;
1601 case HTTP_STATUS_USE_PROXY:
1602 r = "Use Proxy";
1603 break;
1604 case HTTP_STATUS_TEMPORARY_REDIRECT:
1605 r = "Temporary Redirect";
1606 break;
1607 case HTTP_STATUS_BAD_REQUEST:
1608 r = "Bad Request";
1609 break;
1610 case HTTP_STATUS_UNAUTHORIZED:
1611 r = "Unauthorized";
1612 break;
1613 case HTTP_STATUS_PAYMENT_REQUIRED:
1614 r = "Payment Required";
1615 break;
1616 case HTTP_STATUS_FORBIDDEN:
1617 r = "Forbidden";
1618 break;
1619 case HTTP_STATUS_NOT_FOUND:
1620 r = "Not Found";
1621 break;
1622 case HTTP_STATUS_METHOD_NOT_ALLOWED:
1623 r = "Method Not Allowed";
1624 break;
1625 case HTTP_STATUS_NOT_ACCEPTABLE:
1626 r = "Not Acceptable";
1627 break;
1628 case HTTP_STATUS_PROXY_AUTH_REQUIRED:
1629 r = "Proxy Authentication Required";
1630 break;
1631 case HTTP_STATUS_REQUEST_TIMEOUT:
1632 r = "Request Time-out";
1633 break;
1634 case HTTP_STATUS_CONFLICT:
1635 r = "Conflict";
1636 break;
1637 case HTTP_STATUS_GONE:
1638 r = "Gone";
1639 break;
1640 case HTTP_STATUS_LENGTH_REQUIRED:
1641 r = "Length Required";
1642 break;
1643 case HTTP_STATUS_PRECONDITION_FAILED:
1644 r = "Precondition Failed";
1645 break;
1646 case HTTP_STATUS_REQUEST_ENTITY_TOO_LARGE:
1647 r = "Request Entity Too Large";
1648 break;
1649 case HTTP_STATUS_REQUEST_URI_TOO_LARGE:
1650 r = "Request-URI Too Large";
1651 break;
1652 case HTTP_STATUS_UNSUPPORTED_MEDIA_TYPE:
1653 r = "Unsupported Media Type";
1654 break;
1655 case HTTP_STATUS_REQUEST_RANGE_INVALID:
1656 r = "Requested range not satisfiable";
1657 break;
1658 case HTTP_STATUS_EXPECTATION_FAILED:
1659 r = "Expectation Failed";
1660 break;
1661 case HTTP_STATUS_MISDIRECTED_REQUEST:
1662 r = "Misdirected Request";
1663 break;
1664 case HTTP_STATUS_INTERNAL_ERROR:
1665 r = "Internal Server Error";
1666 break;
1667 case HTTP_STATUS_NOT_IMPLEMENTED:
1668 r = "Not Implemented";
1669 break;
1670 case HTTP_STATUS_BAD_GATEWAY:
1671 r = "Bad Gateway";
1672 break;
1673 case HTTP_STATUS_SERVICE_UNAVAILABLE:
1674 r = "Service Unavailable";
1675 break;
1676 case HTTP_STATUS_GATEWAY_TIMEOUT:
1677 r = "Gateway Time-out";
1678 break;
1679 case HTTP_STATUS_BAD_VERSION:
1680 r = "HTTP Version not supported";
1681 break;
1682 default:
1683 r = "";
1684 break;
1685 }
1686
1687 return (r);
1688 }
1689
1690 const char *
1691 http_method_text(int method)
1692 {
1693 char *r;
1694
1695 switch(method) {
1696 case HTTP_METHOD_GET:
1697 r = "GET";
1698 break;
1699 case HTTP_METHOD_POST:
1700 r = "POST";
1701 break;
1702 case HTTP_METHOD_PUT:
1703 r = "PUT";
1704 break;
1705 case HTTP_METHOD_DELETE:
1706 r = "DELETE";
1707 break;
1708 case HTTP_METHOD_HEAD:
1709 r = "HEAD";
1710 break;
1711 case HTTP_METHOD_OPTIONS:
1712 r = "OPTIONS";
1713 break;
1714 case HTTP_METHOD_PATCH:
1715 r = "PATCH";
1716 break;
1717 default:
1718 r = "";
1719 break;
1720 }
1721
1722 return (r);
1723 }
1724
1725 int
1726 http_method_value(const char *method)
1727 {
1728 if (!strcasecmp(method, "GET"))
1729 return (HTTP_METHOD_GET);
1730
1731 if (!strcasecmp(method, "POST"))
1732 return (HTTP_METHOD_POST);
1733
1734 if (!strcasecmp(method, "PUT"))
1735 return (HTTP_METHOD_PUT);
1736
1737 if (!strcasecmp(method, "DELETE"))
1738 return (HTTP_METHOD_DELETE);
1739
1740 if (!strcasecmp(method, "HEAD"))
1741 return (HTTP_METHOD_HEAD);
1742
1743 if (!strcasecmp(method, "OPTIONS"))
1744 return (HTTP_METHOD_OPTIONS);
1745
1746 if (!strcasecmp(method, "PATCH"))
1747 return (HTTP_METHOD_PATCH);
1748
1749 return (0);
1750 }
1751
1752 int
1753 http_media_register(const char *ext, const char *type)
1754 {
1755 struct http_media_type *media;
1756
1757 LIST_FOREACH(media, &http_media_types, list) {
1758 if (!strcasecmp(media->ext, ext))
1759 return (KORE_RESULT_ERROR);
1760 }
1761
1762 media = kore_calloc(1, sizeof(*media));
1763 media->ext = kore_strdup(ext);
1764 media->type = kore_strdup(type);
1765
1766 LIST_INSERT_HEAD(&http_media_types, media, list);
1767
1768 return (KORE_RESULT_OK);
1769 }
1770
1771 const char *
1772 http_media_type(const char *path)
1773 {
1774 const char *p;
1775 struct http_media_type *media;
1776
1777 if ((p = strrchr(path, '.')) == NULL)
1778 return (NULL);
1779
1780 p++;
1781 if (*p == '\0')
1782 return (NULL);
1783
1784 LIST_FOREACH(media, &http_media_types, list) {
1785 if (!strcasecmp(media->ext, p))
1786 return (media->type);
1787 }
1788
1789 return (NULL);
1790 }
1791
1792 char *
1793 http_validate_header(char *header)
1794 {
1795 u_int8_t idx;
1796 char *p, *value;
1797
1798 for (p = header; *p != '\0'; p++) {
1799 idx = *p;
1800 if (idx > HTTP_MAP_LIMIT)
1801 return (NULL);
1802
1803 if (*p == ':') {
1804 *(p)++ = '\0';
1805 break;
1806 }
1807
1808 if (*p >= 'A' && *p <= 'Z')
1809 *p += 32;
1810
1811 if (http_token[idx] == 0x00)
1812 return (NULL);
1813 }
1814
1815 while (isspace(*(unsigned char *)p))
1816 p++;
1817
1818 if (*p == '\0')
1819 return (NULL);
1820
1821 value = p;
1822 while (*p != '\0') {
1823 idx = *p;
1824 if (idx > HTTP_MAP_LIMIT)
1825 return (NULL);
1826 if (http_field_content[idx] == 0x00)
1827 return (NULL);
1828 p++;
1829 }
1830
1831 return (value);
1832 }
1833
1834 static int
1835 http_release_buffer(struct netbuf *nb)
1836 {
1837 kore_buf_free(nb->extra);
1838
1839 return (KORE_RESULT_OK);
1840 }
1841
1842 static int
1843 http_check_redirect(struct http_request *req, struct kore_domain *dom)
1844 {
1845 int idx;
1846 struct http_redirect *rdr;
1847 const char *uri;
1848 char key[4];
1849 struct kore_buf location;
1850
1851 TAILQ_FOREACH(rdr, &dom->redirects, list) {
1852 if (!regexec(&(rdr->rctx), req->path,
1853 HTTP_CAPTURE_GROUPS, req->cgroups, 0))
1854 break;
1855 }
1856
1857 if (rdr == NULL)
1858 return (KORE_RESULT_ERROR);
1859
1860 uri = NULL;
1861 kore_buf_init(&location, 128);
1862
1863 if (rdr->target) {
1864 kore_buf_appendf(&location, "%s", rdr->target);
1865
1866 if (req->query_string != NULL) {
1867 kore_buf_replace_string(&location, "$qs",
1868 req->query_string, strlen(req->query_string));
1869 }
1870
1871 /* Starts at 1 to skip the full path. */
1872 for (idx = 1; idx < HTTP_CAPTURE_GROUPS - 1; idx++) {
1873 if (req->cgroups[idx].rm_so == -1 ||
1874 req->cgroups[idx].rm_eo == -1)
1875 break;
1876
1877 (void)snprintf(key, sizeof(key), "$%d", idx);
1878
1879 kore_buf_replace_string(&location, key,
1880 req->path + req->cgroups[idx].rm_so,
1881 req->cgroups[idx].rm_eo - req->cgroups[idx].rm_so);
1882 }
1883
1884 uri = kore_buf_stringify(&location, NULL);
1885 }
1886
1887 if (uri)
1888 http_response_header(req, "location", uri);
1889
1890 http_response(req, rdr->status, NULL, 0);
1891 kore_buf_cleanup(&location);
1892
1893 if (dom->accesslog)
1894 kore_accesslog(req);
1895
1896 return (KORE_RESULT_OK);
1897 }
1898
1899 static struct http_request *
1900 http_request_new(struct connection *c, const char *host,
1901 const char *method, char *path, const char *version)
1902 {
1903 struct kore_domain *dom;
1904 struct http_request *req;
1905 size_t qsoff;
1906 char *p, *hp;
1907 int m, flags, exists;
1908
1909 if (http_request_count >= http_request_limit) {
1910 http_error_response(c, HTTP_STATUS_SERVICE_UNAVAILABLE);
1911 return (NULL);
1912 }
1913
1914 if (strlen(host) >= KORE_DOMAINNAME_LEN - 1) {
1915 http_error_response(c, HTTP_STATUS_BAD_REQUEST);
1916 return (NULL);
1917 }
1918
1919 if (strlen(path) >= HTTP_URI_LEN - 1) {
1920 http_error_response(c, HTTP_STATUS_REQUEST_URI_TOO_LARGE);
1921 return (NULL);
1922 }
1923
1924 if (strcasecmp(version, "http/1.1")) {
1925 if (strcasecmp(version, "http/1.0")) {
1926 http_error_response(c, HTTP_STATUS_BAD_VERSION);
1927 return (NULL);
1928 }
1929
1930 flags = HTTP_VERSION_1_0;
1931 } else {
1932 flags = HTTP_VERSION_1_1;
1933 }
1934
1935 if ((p = strchr(path, '?')) != NULL) {
1936 qsoff = p - path;
1937 } else {
1938 qsoff = 0;
1939 }
1940
1941 hp = NULL;
1942
1943 switch (c->family) {
1944 case AF_INET6:
1945 if (*host == '[') {
1946 if ((hp = strrchr(host, ']')) == NULL) {
1947 http_error_response(c, HTTP_STATUS_BAD_REQUEST);
1948 return (NULL);
1949 }
1950 hp++;
1951 if (*hp == ':')
1952 *hp = '\0';
1953 else
1954 hp = NULL;
1955 }
1956 break;
1957 default:
1958 if ((hp = strrchr(host, ':')) != NULL)
1959 *hp = '\0';
1960 break;
1961 }
1962
1963 if (c->owner->server->tls && c->tls_sni != NULL) {
1964 if (strcasecmp(c->tls_sni, host)) {
1965 http_error_response(c, HTTP_STATUS_MISDIRECTED_REQUEST);
1966 return (NULL);
1967 }
1968 }
1969
1970 if ((dom = kore_domain_lookup(c->owner->server, host)) == NULL) {
1971 http_error_response(c, HTTP_STATUS_NOT_FOUND);
1972 return (NULL);
1973 }
1974
1975 if (dom->cafile != NULL && c->tls_cert == NULL) {
1976 http_error_response(c, HTTP_STATUS_FORBIDDEN);
1977 return (NULL);
1978 }
1979
1980 if (hp != NULL)
1981 *hp = ':';
1982
1983 if (!strcasecmp(method, "get")) {
1984 m = HTTP_METHOD_GET;
1985 flags |= HTTP_REQUEST_COMPLETE;
1986 } else if (!strcasecmp(method, "delete")) {
1987 m = HTTP_METHOD_DELETE;
1988 flags |= HTTP_REQUEST_EXPECT_BODY;
1989 } else if (!strcasecmp(method, "post")) {
1990 m = HTTP_METHOD_POST;
1991 flags |= HTTP_REQUEST_EXPECT_BODY;
1992 } else if (!strcasecmp(method, "put")) {
1993 m = HTTP_METHOD_PUT;
1994 flags |= HTTP_REQUEST_EXPECT_BODY;
1995 } else if (!strcasecmp(method, "head")) {
1996 m = HTTP_METHOD_HEAD;
1997 flags |= HTTP_REQUEST_COMPLETE;
1998 } else if (!strcasecmp(method, "options")) {
1999 m = HTTP_METHOD_OPTIONS;
2000 flags |= HTTP_REQUEST_COMPLETE;
2001 } else if (!strcasecmp(method, "patch")) {
2002 m = HTTP_METHOD_PATCH;
2003 flags |= HTTP_REQUEST_EXPECT_BODY;
2004 } else {
2005 http_error_response(c, HTTP_STATUS_BAD_REQUEST);
2006 return (NULL);
2007 }
2008
2009 if (flags & HTTP_VERSION_1_0) {
2010 if (m != HTTP_METHOD_GET && m != HTTP_METHOD_POST &&
2011 m != HTTP_METHOD_HEAD) {
2012 http_error_response(c, HTTP_STATUS_METHOD_NOT_ALLOWED);
2013 return (NULL);
2014 }
2015 }
2016
2017 req = kore_pool_get(&http_request_pool);
2018
2019 req->end = 0;
2020 req->total = 0;
2021 req->start = 0;
2022 req->owner = c;
2023 req->status = 0;
2024 req->method = m;
2025 req->agent = NULL;
2026 req->referer = NULL;
2027 req->runlock = NULL;
2028 req->flags = flags;
2029 req->fsm_state = 0;
2030 req->http_body = NULL;
2031 req->http_body_fd = -1;
2032 req->hdlr_extra = NULL;
2033 req->content_length = 0;
2034 req->query_string = NULL;
2035 req->http_body_length = 0;
2036 req->http_body_offset = 0;
2037 req->http_body_path = NULL;
2038
2039 req->host = host;
2040 req->path = path;
2041
2042 #if defined(KORE_USE_PYTHON)
2043 req->py_req = NULL;
2044 req->py_coro = NULL;
2045 req->py_rqnext = NULL;
2046 req->py_validator = NULL;
2047 #endif
2048
2049 if (qsoff > 0) {
2050 req->query_string = path + qsoff;
2051 *(req->query_string)++ = '\0';
2052 } else {
2053 req->query_string = NULL;
2054 }
2055
2056 /* Checked further down below if we need to 404. */
2057 exists = kore_route_lookup(req, dom, m, &req->rt);
2058
2059 TAILQ_INIT(&(req->resp_headers));
2060 TAILQ_INIT(&(req->req_headers));
2061 TAILQ_INIT(&(req->resp_cookies));
2062 TAILQ_INIT(&(req->req_cookies));
2063 TAILQ_INIT(&(req->arguments));
2064 TAILQ_INIT(&(req->files));
2065
2066 #if defined(KORE_USE_TASKS)
2067 LIST_INIT(&(req->tasks));
2068 #endif
2069
2070 #if defined(KORE_USE_PGSQL)
2071 LIST_INIT(&(req->pgsqls));
2072 #endif
2073
2074 http_request_count++;
2075 TAILQ_INSERT_HEAD(&http_requests, req, list);
2076 TAILQ_INSERT_TAIL(&(c->http_requests), req, olist);
2077
2078 if (http_check_redirect(req, dom)) {
2079 http_request_free(req);
2080 return (NULL);
2081 }
2082
2083 if (exists == 0) {
2084 http_request_free(req);
2085 http_error_response(c, HTTP_STATUS_NOT_FOUND);
2086 return (NULL);
2087 }
2088
2089 if (req->rt == NULL) {
2090 http_request_free(req);
2091 http_error_response(c, HTTP_STATUS_METHOD_NOT_ALLOWED);
2092 return (NULL);
2093 }
2094
2095 return (req);
2096 }
2097
2098 static int
2099 multipart_find_data(struct kore_buf *in, struct kore_buf *out,
2100 size_t *olen, struct http_request *req, const void *needle, size_t len)
2101 {
2102 ssize_t ret;
2103 size_t left;
2104 u_int8_t *p, first, data[4096];
2105
2106 if (olen != NULL)
2107 *olen = 0;
2108
2109 first = *(const u_int8_t *)needle;
2110 for (;;) {
2111 if (in->offset < len) {
2112 ret = http_body_read(req, data, sizeof(data));
2113 if (ret == -1)
2114 return (KORE_RESULT_ERROR);
2115 if (ret == 0)
2116 return (KORE_RESULT_ERROR);
2117
2118 kore_buf_append(in, data, ret);
2119 continue;
2120 }
2121
2122 p = kore_mem_find(in->data, in->offset, &first, 1);
2123 if (p == NULL) {
2124 if (out != NULL)
2125 kore_buf_append(out, in->data, in->offset);
2126 if (olen != NULL)
2127 *olen += in->offset;
2128 kore_buf_reset(in);
2129 continue;
2130 }
2131
2132 left = in->offset - (p - in->data);
2133 if (left < len) {
2134 if (out != NULL)
2135 kore_buf_append(out, in->data, (p - in->data));
2136 if (olen != NULL)
2137 *olen += (p - in->data);
2138 memmove(in->data, p, left);
2139 in->offset = left;
2140 continue;
2141 }
2142
2143 if (!memcmp(p, needle, len)) {
2144 if (out != NULL)
2145 kore_buf_append(out, in->data, p - in->data);
2146 if (olen != NULL)
2147 *olen += (p - in->data);
2148
2149 in->offset = left - len;
2150 if (in->offset > 0)
2151 memmove(in->data, p + len, in->offset);
2152 return (KORE_RESULT_OK);
2153 }
2154
2155 if (out != NULL)
2156 kore_buf_append(out, in->data, (p - in->data) + 1);
2157 if (olen != NULL)
2158 *olen += (p - in->data) + 1;
2159
2160 in->offset = left - 1;
2161 if (in->offset > 0)
2162 memmove(in->data, p + 1, in->offset);
2163 }
2164
2165 return (KORE_RESULT_ERROR);
2166 }
2167
2168 static int
2169 multipart_parse_headers(struct http_request *req, struct kore_buf *in,
2170 struct kore_buf *hbuf, const char *boundary, const int blen)
2171 {
2172 int h, c, i;
2173 char *headers[5], *args[5], *opt[5];
2174 char *d, *val, *name, *fname, *string;
2175
2176 string = kore_buf_stringify(hbuf, NULL);
2177 h = kore_split_string(string, "\r\n", headers, 5);
2178 for (i = 0; i < h; i++) {
2179 c = kore_split_string(headers[i], ":", args, 5);
2180 if (c != 2)
2181 continue;
2182
2183 /* Ignore other headers for now. */
2184 if (strcasecmp(args[0], "content-disposition"))
2185 continue;
2186
2187 for (d = args[1]; isspace(*(unsigned char *)d); d++)
2188 ;
2189
2190 c = kore_split_string(d, ";", opt, 5);
2191 if (c < 2)
2192 continue;
2193
2194 if (strcasecmp(opt[0], "form-data"))
2195 continue;
2196
2197 if ((val = strchr(opt[1], '=')) == NULL)
2198 continue;
2199 if (strlen(val) < 3)
2200 continue;
2201
2202 val++;
2203 kore_strip_chars(val, '"', &name);
2204
2205 if (opt[2] == NULL) {
2206 multipart_add_field(req, in, name, boundary, blen);
2207 kore_free(name);
2208 continue;
2209 }
2210
2211 for (d = opt[2]; isspace(*(unsigned char *)d); d++)
2212 ;
2213
2214 if (!strncasecmp(d, "filename=", 9)) {
2215 if ((val = strchr(d, '=')) == NULL) {
2216 kore_free(name);
2217 continue;
2218 }
2219
2220 val++;
2221 kore_strip_chars(val, '"', &fname);
2222 if (strlen(fname) > 0) {
2223 multipart_file_add(req,
2224 in, name, fname, boundary, blen);
2225 }
2226 kore_free(fname);
2227 }
2228
2229 kore_free(name);
2230 }
2231
2232 return (KORE_RESULT_OK);
2233 }
2234
2235 static void
2236 multipart_add_field(struct http_request *req, struct kore_buf *in,
2237 char *name, const char *boundary, const int blen)
2238 {
2239 struct kore_buf *data;
2240 char *string;
2241
2242 data = kore_buf_alloc(128);
2243
2244 if (!multipart_find_data(in, data, NULL, req, boundary, blen)) {
2245 kore_buf_free(data);
2246 return;
2247 }
2248
2249 if (data->offset < 3) {
2250 kore_buf_free(data);
2251 return;
2252 }
2253
2254 data->offset -= 2;
2255 string = kore_buf_stringify(data, NULL);
2256 http_argument_add(req, name, string, 0, 0);
2257 kore_buf_free(data);
2258 }
2259
2260 static void
2261 multipart_file_add(struct http_request *req, struct kore_buf *in,
2262 const char *name, const char *fname, const char *boundary, const int blen)
2263 {
2264 struct http_file *f;
2265 size_t position, len;
2266
2267 position = req->http_body_offset - in->offset;
2268 if (!multipart_find_data(in, NULL, &len, req, boundary, blen))
2269 return;
2270
2271 if (len < 3)
2272 return;
2273 len -= 2;
2274
2275 f = kore_malloc(sizeof(struct http_file));
2276 f->req = req;
2277 f->offset = 0;
2278 f->length = len;
2279 f->position = position;
2280 f->name = kore_strdup(name);
2281 f->filename = kore_strdup(fname);
2282
2283 TAILQ_INSERT_TAIL(&(req->files), f, list);
2284 }
2285
2286 static void
2287 http_argument_add(struct http_request *req, char *name, char *value, int qs,
2288 int decode)
2289 {
2290 struct http_arg *q;
2291 struct kore_route_params *p;
2292
2293 if (decode) {
2294 if (!http_argument_urldecode(name, qs))
2295 return;
2296 }
2297
2298 TAILQ_FOREACH(p, &req->rt->params, list) {
2299 if (qs == 1 && !(p->flags & KORE_PARAMS_QUERY_STRING))
2300 continue;
2301 if (qs == 0 && (p->flags & KORE_PARAMS_QUERY_STRING))
2302 continue;
2303
2304 if (p->method != req->method)
2305 continue;
2306
2307 if (strcmp(p->name, name))
2308 continue;
2309
2310 if (decode) {
2311 if (!http_argument_urldecode(value, qs))
2312 return;
2313 }
2314
2315 if (!kore_validator_check(req, p->validator, value))
2316 break;
2317
2318 q = kore_malloc(sizeof(struct http_arg));
2319 q->name = kore_strdup(name);
2320 q->s_value = kore_strdup(value);
2321 TAILQ_INSERT_TAIL(&(req->arguments), q, list);
2322 break;
2323 }
2324 }
2325
2326 static int
2327 http_body_recv(struct netbuf *nb)
2328 {
2329 struct http_request *req = (struct http_request *)nb->extra;
2330
2331 return (http_body_update(req, nb->buf, nb->s_off));
2332 }
2333
2334 static int
2335 http_body_update(struct http_request *req, const void *data, size_t len)
2336 {
2337 ssize_t ret;
2338 u_int64_t bytes_left;
2339
2340 SHA256Update(&req->hashctx, data, len);
2341
2342 if (req->rt->on_body_chunk != NULL) {
2343 if (kore_runtime_http_body_chunk(req->rt->on_body_chunk,
2344 req, data, len) != KORE_RESULT_OK) {
2345 req->flags |= HTTP_REQUEST_DELETE;
2346 http_error_response(req->owner,
2347 HTTP_STATUS_INTERNAL_ERROR);
2348 return (KORE_RESULT_ERROR);
2349 }
2350 } else if (req->http_body_fd != -1) {
2351 ret = write(req->http_body_fd, data, len);
2352 if (ret == -1 || (size_t)ret != len) {
2353 req->flags |= HTTP_REQUEST_DELETE;
2354 http_error_response(req->owner,
2355 HTTP_STATUS_INTERNAL_ERROR);
2356 return (KORE_RESULT_ERROR);
2357 }
2358 } else if (req->http_body != NULL) {
2359 kore_buf_append(req->http_body, data, len);
2360 } else {
2361 req->flags |= HTTP_REQUEST_DELETE;
2362 http_error_response(req->owner,
2363 HTTP_STATUS_INTERNAL_ERROR);
2364 return (KORE_RESULT_ERROR);
2365 }
2366
2367 req->content_length -= len;
2368
2369 if (req->content_length == 0) {
2370 req->owner->http_timeout = 0;
2371 req->owner->rnb->extra = NULL;
2372 http_request_wakeup(req);
2373 req->flags |= HTTP_REQUEST_COMPLETE;
2374 req->flags &= ~HTTP_REQUEST_EXPECT_BODY;
2375 req->content_length = req->http_body_length;
2376 if (!http_body_rewind(req)) {
2377 req->flags |= HTTP_REQUEST_DELETE;
2378 http_error_response(req->owner,
2379 HTTP_STATUS_INTERNAL_ERROR);
2380 return (KORE_RESULT_ERROR);
2381 }
2382 SHA256Final(req->http_body_digest, &req->hashctx);
2383 } else {
2384 bytes_left = req->content_length;
2385 net_recv_reset(req->owner,
2386 MIN(bytes_left, NETBUF_SEND_PAYLOAD_MAX),
2387 http_body_recv);
2388 req->owner->rnb->extra = req;
2389 }
2390
2391 return (KORE_RESULT_OK);
2392 }
2393
2394 static void
2395 http_error_response(struct connection *c, int status)
2396 {
2397 c->flags |= CONN_CLOSE_EMPTY;
2398
2399 switch (c->proto) {
2400 case CONN_PROTO_HTTP:
2401 http_response_normal(NULL, c, status, NULL, 0);
2402 break;
2403 default:
2404 fatal("http_error_response() bad proto %d", c->proto);
2405 /* NOTREACHED. */
2406 }
2407
2408 if (!net_send_flush(c))
2409 kore_connection_disconnect(c);
2410 }
2411
2412 static void
2413 http_response_normal(struct http_request *req, struct connection *c,
2414 int status, const void *d, size_t len)
2415 {
2416 struct kore_buf buf;
2417 struct http_cookie *ck;
2418 struct http_header *hdr;
2419 char version;
2420 const char *conn, *text;
2421 int connection_close, send_body;
2422
2423 send_body = 1;
2424 text = http_status_text(status);
2425
2426 kore_buf_reset(header_buf);
2427
2428 if (req != NULL) {
2429 if (req->flags & HTTP_VERSION_1_0)
2430 version = '0';
2431 else
2432 version = '1';
2433 } else {
2434 version = '1';
2435 }
2436
2437 kore_buf_appendf(header_buf, "HTTP/1.%c %d %s\r\n",
2438 version, status, text);
2439
2440 if (status == 100) {
2441 kore_buf_append(header_buf, "\r\n", 2);
2442 net_send_queue(c, header_buf->data, header_buf->offset);
2443 return;
2444 }
2445
2446 kore_buf_append(header_buf, http_version, http_version_len);
2447
2448 if ((c->flags & CONN_CLOSE_EMPTY) ||
2449 (req != NULL && (req->flags & HTTP_VERSION_1_0))) {
2450 connection_close = 1;
2451 } else {
2452 connection_close = 0;
2453 }
2454
2455 if (connection_close == 0 && req != NULL) {
2456 if (http_request_header(req, "connection", &conn)) {
2457 if ((*conn == 'c' || *conn == 'C') &&
2458 !strcasecmp(conn, "close")) {
2459 connection_close = 1;
2460 }
2461 }
2462 }
2463
2464 kore_buf_init(&buf, 1024);
2465
2466 /* Note that req CAN be NULL. */
2467 if (req == NULL || req->owner->proto != CONN_PROTO_WEBSOCKET) {
2468 if (http_keepalive_time && connection_close == 0) {
2469 kore_buf_appendf(header_buf,
2470 "connection: keep-alive\r\n");
2471 kore_buf_appendf(header_buf,
2472 "keep-alive: timeout=%d\r\n", http_keepalive_time);
2473 } else {
2474 c->flags |= CONN_CLOSE_EMPTY;
2475 kore_buf_appendf(header_buf, "connection: close\r\n");
2476 }
2477 }
2478
2479 if (c->tls && http_hsts_enable) {
2480 kore_buf_appendf(header_buf, "strict-transport-security: ");
2481 kore_buf_appendf(header_buf,
2482 "max-age=%" PRIu64 "; includeSubDomains\r\n",
2483 http_hsts_enable);
2484 }
2485
2486 if (http_pretty_error && d == NULL && status >= 400) {
2487 kore_buf_appendf(&buf, pretty_error_fmt,
2488 status, text, status, text);
2489
2490 d = buf.data;
2491 len = buf.offset;
2492 }
2493
2494 if (req != NULL) {
2495 TAILQ_FOREACH(ck, &(req->resp_cookies), list)
2496 http_write_response_cookie(ck);
2497
2498 TAILQ_FOREACH(hdr, &(req->resp_headers), list) {
2499 kore_buf_appendf(header_buf, "%s: %s\r\n",
2500 hdr->header, hdr->value);
2501 }
2502
2503 TAILQ_FOREACH(hdr, &(req->rt->dom->headers), list) {
2504 kore_buf_appendf(header_buf, "%s: %s\r\n",
2505 hdr->header, hdr->value);
2506 }
2507
2508 if (status != 204 && status >= 200 &&
2509 !(req->flags & HTTP_REQUEST_NO_CONTENT_LENGTH)) {
2510 kore_buf_appendf(header_buf,
2511 "content-length: %zu\r\n", len);
2512 }
2513 } else {
2514 if (status != 204 && status >= 200) {
2515 kore_buf_appendf(header_buf,
2516 "content-length: %zu\r\n", len);
2517 }
2518 }
2519
2520 kore_buf_append(header_buf, "\r\n", 2);
2521 net_send_queue(c, header_buf->data, header_buf->offset);
2522
2523 if (req != NULL && req->method == HTTP_METHOD_HEAD)
2524 send_body = 0;
2525
2526 if (d != NULL && send_body)
2527 net_send_queue(c, d, len);
2528
2529 if (!(c->flags & CONN_CLOSE_EMPTY) && !(c->flags & CONN_IS_BUSY))
2530 http_start_recv(c);
2531
2532 if (req != NULL)
2533 req->content_length = len;
2534
2535 kore_buf_cleanup(&buf);
2536 }
2537
2538 static void
2539 http_write_response_cookie(struct http_cookie *ck)
2540 {
2541 struct tm tm;
2542 char expires[HTTP_DATE_MAXSIZE];
2543
2544 kore_buf_reset(ckhdr_buf);
2545 kore_buf_appendf(ckhdr_buf, "%s=%s", ck->name, ck->value);
2546
2547 if (ck->path != NULL)
2548 kore_buf_appendf(ckhdr_buf, "; Path=%s", ck->path);
2549 if (ck->domain != NULL)
2550 kore_buf_appendf(ckhdr_buf, "; Domain=%s", ck->domain);
2551
2552 if (ck->expires > 0) {
2553 if (gmtime_r(&ck->expires, &tm) == NULL) {
2554 kore_log(LOG_ERR, "gmtime_r(): %s", errno_s);
2555 return;
2556 }
2557
2558 if (strftime(expires, sizeof(expires),
2559 "%a, %d %b %y %H:%M:%S GMT", &tm) == 0) {
2560 kore_log(LOG_ERR, "strftime(): %s", errno_s);
2561 return;
2562 }
2563
2564 kore_buf_appendf(ckhdr_buf, "; Expires=%s", expires);
2565 }
2566
2567 if (ck->maxage > 0)
2568 kore_buf_appendf(ckhdr_buf, "; Max-Age=%u", ck->maxage);
2569
2570 if (ck->flags & HTTP_COOKIE_HTTPONLY)
2571 kore_buf_appendf(ckhdr_buf, "; HttpOnly");
2572 if (ck->flags & HTTP_COOKIE_SECURE)
2573 kore_buf_appendf(ckhdr_buf, "; Secure");
2574
2575 kore_buf_appendf(header_buf, "set-cookie: %s\r\n",
2576 kore_buf_stringify(ckhdr_buf, NULL));
2577 }
2578
2579 static int
2580 http_data_convert(void *data, void **out, void *nout, int type)
2581 {
2582 switch (type) {
2583 case HTTP_ARG_TYPE_RAW:
2584 case HTTP_ARG_TYPE_STRING:
2585 *out = data;
2586 return (KORE_RESULT_OK);
2587 case HTTP_ARG_TYPE_BYTE:
2588 COPY_ARG_TYPE(*(u_int8_t *)data, u_int8_t);
2589 return (KORE_RESULT_OK);
2590 case HTTP_ARG_TYPE_INT16:
2591 COPY_AS_INTTYPE(SHRT_MIN, SHRT_MAX, int16_t);
2592 return (KORE_RESULT_OK);
2593 case HTTP_ARG_TYPE_UINT16:
2594 COPY_AS_INTTYPE(0, USHRT_MAX, u_int16_t);
2595 return (KORE_RESULT_OK);
2596 case HTTP_ARG_TYPE_INT32:
2597 COPY_AS_INTTYPE(INT_MIN, INT_MAX, int32_t);
2598 return (KORE_RESULT_OK);
2599 case HTTP_ARG_TYPE_UINT32:
2600 COPY_AS_INTTYPE(0, UINT_MAX, u_int32_t);
2601 return (KORE_RESULT_OK);
2602 case HTTP_ARG_TYPE_INT64:
2603 COPY_AS_INTTYPE_64(int64_t, 1);
2604 return (KORE_RESULT_OK);
2605 case HTTP_ARG_TYPE_UINT64:
2606 COPY_AS_INTTYPE_64(u_int64_t, 0);
2607 return (KORE_RESULT_OK);
2608 case HTTP_ARG_TYPE_FLOAT:
2609 COPY_ARG_DOUBLE(-FLT_MAX, FLT_MAX, float);
2610 return (KORE_RESULT_OK);
2611 case HTTP_ARG_TYPE_DOUBLE:
2612 COPY_ARG_DOUBLE(-DBL_MAX, DBL_MAX, double);
2613 return (KORE_RESULT_OK);
2614 default:
2615 break;
2616 }
2617
2618 return (KORE_RESULT_ERROR);
2619 }