http.c (59797B)
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 (req->content_length > http_body_max) {
934 req->flags |= HTTP_REQUEST_DELETE;
935 http_error_response(req->owner,
936 HTTP_STATUS_REQUEST_ENTITY_TOO_LARGE);
937 return (KORE_RESULT_OK);
938 }
939
940 req->http_body_length = req->content_length;
941
942 if (req->rt->on_body_chunk == NULL &&
943 http_body_disk_offload > 0 &&
944 req->content_length > http_body_disk_offload) {
945 req->http_body_path = kore_pool_get(&http_body_path);
946 l = snprintf(req->http_body_path, HTTP_BODY_PATH_MAX,
947 "%s/http_body.XXXXXX", http_body_disk_path);
948 if (l == -1 || (size_t)l >= HTTP_BODY_PATH_MAX) {
949 req->flags |= HTTP_REQUEST_DELETE;
950 http_error_response(req->owner,
951 HTTP_STATUS_INTERNAL_ERROR);
952 return (KORE_RESULT_ERROR);
953 }
954
955 req->http_body = NULL;
956 req->http_body_fd = mkstemp(req->http_body_path);
957 if (req->http_body_fd == -1) {
958 req->flags |= HTTP_REQUEST_DELETE;
959 http_error_response(req->owner,
960 HTTP_STATUS_INTERNAL_ERROR);
961 return (KORE_RESULT_OK);
962 }
963 } else if (req->rt->on_body_chunk == NULL) {
964 req->http_body_fd = -1;
965 req->http_body = kore_buf_alloc(req->content_length);
966 }
967
968 SHA256Init(&req->hashctx);
969 c->http_timeout = http_body_timeout * 1000;
970
971 if (!http_body_update(req, end_headers, nb->s_off - len)) {
972 req->flags |= HTTP_REQUEST_DELETE;
973 http_error_response(req->owner,
974 HTTP_STATUS_INTERNAL_ERROR);
975 return (KORE_RESULT_OK);
976 }
977 } else {
978 c->http_timeout = 0;
979 }
980
981 if (req->rt->on_headers != NULL) {
982 if (!kore_runtime_http_request(req->rt->on_headers, req)) {
983 req->flags |= HTTP_REQUEST_DELETE;
984 return (KORE_RESULT_OK);
985 }
986 }
987
988 return (KORE_RESULT_OK);
989 }
990
991 int
992 http_argument_get(struct http_request *req, const char *name,
993 void **out, void *nout, int type)
994 {
995 struct http_arg *q;
996
997 TAILQ_FOREACH(q, &(req->arguments), list) {
998 if (strcmp(q->name, name))
999 continue;
1000
1001 if (http_data_convert(q->s_value, out, nout, type))
1002 return (KORE_RESULT_OK);
1003
1004 break;
1005 }
1006
1007 return (KORE_RESULT_ERROR);
1008 }
1009
1010 int
1011 http_argument_urldecode(char *arg, int url)
1012 {
1013 u_int8_t v;
1014 int err;
1015 size_t len;
1016 char *p, *in, h[5];
1017
1018 p = arg;
1019 in = arg;
1020 len = strlen(arg);
1021
1022 while (*p != '\0' && p < (arg + len)) {
1023 if (*p == '+')
1024 *p = ' ';
1025 if (*p != '%') {
1026 *in++ = *p++;
1027 continue;
1028 }
1029
1030 if ((p + 2) >= (arg + len))
1031 return (KORE_RESULT_ERROR);
1032
1033 if (!isxdigit((unsigned char)*(p + 1)) ||
1034 !isxdigit((unsigned char)*(p + 2))) {
1035 *in++ = *p++;
1036 continue;
1037 }
1038
1039 h[0] = '0';
1040 h[1] = 'x';
1041 h[2] = *(p + 1);
1042 h[3] = *(p + 2);
1043 h[4] = '\0';
1044
1045 v = kore_strtonum(h, 16, 0x0, 0xff, &err);
1046 if (err != KORE_RESULT_OK)
1047 return (err);
1048
1049 if (url) {
1050 if (v <= 0x1f || v == 0x7f)
1051 return (KORE_RESULT_ERROR);
1052 } else {
1053 if ((v <= 0x1f || v == 0x7f) &&
1054 (v != '\n' && v != '\r' && v != '\t'))
1055 return (KORE_RESULT_ERROR);
1056 }
1057
1058 *in++ = (char)v;
1059 p += 3;
1060 }
1061
1062 *in = '\0';
1063 return (KORE_RESULT_OK);
1064 }
1065
1066 struct http_file *
1067 http_file_lookup(struct http_request *req, const char *name)
1068 {
1069 struct http_file *f;
1070
1071 TAILQ_FOREACH(f, &(req->files), list) {
1072 if (!strcmp(f->name, name))
1073 return (f);
1074 }
1075
1076 return (NULL);
1077 }
1078
1079 ssize_t
1080 http_file_read(struct http_file *file, void *buf, size_t len)
1081 {
1082 ssize_t ret;
1083 size_t toread, off;
1084
1085 if (file->length < file->offset)
1086 return (-1);
1087 if ((file->offset + len) < file->offset)
1088 return (-1);
1089 if ((file->position + file->offset) < file->position)
1090 return (-1);
1091
1092 off = file->position + file->offset;
1093 toread = MIN(len, (file->length - file->offset));
1094 if (toread == 0)
1095 return (0);
1096
1097 if (file->req->http_body_fd != -1) {
1098 if (lseek(file->req->http_body_fd, off, SEEK_SET) == -1) {
1099 kore_log(LOG_ERR, "http_file_read: lseek(%s): %s",
1100 file->req->http_body_path, errno_s);
1101 return (-1);
1102 }
1103
1104 for (;;) {
1105 ret = read(file->req->http_body_fd, buf, toread);
1106 if (ret == -1) {
1107 if (errno == EINTR)
1108 continue;
1109 kore_log(LOG_ERR, "failed to read %s: %s",
1110 file->req->http_body_path, errno_s);
1111 return (-1);
1112 }
1113 if (ret == 0)
1114 return (0);
1115 break;
1116 }
1117 } else if (file->req->http_body != NULL) {
1118 if (off > file->req->http_body->length)
1119 return (0);
1120 memcpy(buf, file->req->http_body->data + off, toread);
1121 ret = toread;
1122 } else {
1123 kore_log(LOG_ERR, "http_file_read: called without body");
1124 return (-1);
1125 }
1126
1127 file->offset += (size_t)ret;
1128 return (ret);
1129 }
1130
1131 void
1132 http_file_rewind(struct http_file *file)
1133 {
1134 file->offset = 0;
1135 }
1136
1137 void
1138 http_response_cookie(struct http_request *req, const char *name,
1139 const char *val, const char *path, time_t expires, u_int32_t maxage,
1140 struct http_cookie **out)
1141 {
1142 char *p;
1143 struct http_cookie *ck;
1144
1145 if (name == NULL || val == NULL)
1146 fatal("http_response_cookie: invalid parameters");
1147
1148 ck = kore_pool_get(&http_cookie_pool);
1149
1150 ck->maxage = maxage;
1151 ck->expires = expires;
1152 ck->name = kore_strdup(name);
1153 ck->value = kore_strdup(val);
1154 ck->domain = kore_strdup(req->host);
1155 ck->flags = HTTP_COOKIE_HTTPONLY | HTTP_COOKIE_SECURE;
1156
1157 if ((p = strrchr(ck->domain, ':')) != NULL)
1158 *p = '\0';
1159
1160 if (path != NULL)
1161 ck->path = kore_strdup(path);
1162 else
1163 ck->path = NULL;
1164
1165 TAILQ_INSERT_TAIL(&(req->resp_cookies), ck, list);
1166
1167 if (out != NULL)
1168 *out = ck;
1169 }
1170
1171 void
1172 http_populate_cookies(struct http_request *req)
1173 {
1174 struct http_cookie *ck;
1175 const char *hdr;
1176 int i, v, n;
1177 char *c, *header, *pair[3];
1178 char *cookies[HTTP_MAX_COOKIES];
1179
1180 if (!http_request_header(req, "cookie", &hdr))
1181 return;
1182
1183 header = kore_strdup(hdr);
1184 v = kore_split_string(header, ";", cookies, HTTP_MAX_COOKIES);
1185 for (i = 0; i < v; i++) {
1186 for (c = cookies[i]; isspace(*(unsigned char *)c); c++)
1187 ;
1188
1189 n = kore_split_string(c, "=", pair, 3);
1190 if (n != 2)
1191 continue;
1192
1193 ck = kore_pool_get(&http_cookie_pool);
1194 ck->name = kore_strdup(pair[0]);
1195 ck->value = kore_strdup(pair[1]);
1196 TAILQ_INSERT_TAIL(&(req->req_cookies), ck, list);
1197 }
1198
1199 kore_free(header);
1200 }
1201
1202 void
1203 http_populate_post(struct http_request *req)
1204 {
1205 ssize_t ret;
1206 int i, v;
1207 struct kore_buf *body;
1208 char data[BUFSIZ];
1209 char *args[HTTP_MAX_QUERY_ARGS], *val[3], *string;
1210
1211 if (req->method != HTTP_METHOD_POST)
1212 return;
1213
1214 if (req->http_body != NULL) {
1215 body = NULL;
1216 req->http_body->offset = req->content_length;
1217 string = kore_buf_stringify(req->http_body, NULL);
1218 req->http_body_length = 0;
1219 req->http_body_offset = 0;
1220 } else {
1221 body = kore_buf_alloc(128);
1222 for (;;) {
1223 ret = http_body_read(req, data, sizeof(data));
1224 if (ret == -1)
1225 goto out;
1226 if (ret == 0)
1227 break;
1228 kore_buf_append(body, data, ret);
1229 }
1230 string = kore_buf_stringify(body, NULL);
1231 }
1232
1233 v = kore_split_string(string, "&", args, HTTP_MAX_QUERY_ARGS);
1234 for (i = 0; i < v; i++) {
1235 kore_split_string(args[i], "=", val, 3);
1236 if (val[0] != NULL && val[1] != NULL)
1237 http_argument_add(req, val[0], val[1], 0, 1);
1238 }
1239
1240 out:
1241 if (body != NULL)
1242 kore_buf_free(body);
1243 }
1244
1245 void
1246 http_populate_qs(struct http_request *req)
1247 {
1248 int i, v;
1249 char *query, *args[HTTP_MAX_QUERY_ARGS], *val[3];
1250
1251 if (req->query_string == NULL)
1252 return;
1253
1254 query = kore_strdup(req->query_string);
1255 v = kore_split_string(query, "&", args, HTTP_MAX_QUERY_ARGS);
1256 for (i = 0; i < v; i++) {
1257 kore_split_string(args[i], "=", val, 3);
1258 if (val[0] != NULL && val[1] != NULL)
1259 http_argument_add(req, val[0], val[1], 1, 1);
1260 }
1261
1262 kore_free(query);
1263 }
1264
1265 void
1266 http_populate_multipart_form(struct http_request *req)
1267 {
1268 const char *hdr;
1269 int h, blen;
1270 struct kore_buf in, out;
1271 char *type, *val, *args[3];
1272 char boundary[HTTP_BOUNDARY_MAX];
1273
1274 if (req->method != HTTP_METHOD_POST)
1275 return;
1276
1277 if (!http_request_header(req, "content-type", &hdr))
1278 return;
1279
1280 kore_buf_init(&in, 128);
1281 kore_buf_init(&out, 128);
1282
1283 type = kore_strdup(hdr);
1284 h = kore_split_string(type, ";", args, 3);
1285 if (h != 2)
1286 goto cleanup;
1287
1288 if (strcasecmp(args[0], "multipart/form-data"))
1289 goto cleanup;
1290
1291 if ((val = strchr(args[1], '=')) == NULL)
1292 goto cleanup;
1293
1294 val++;
1295 blen = snprintf(boundary, sizeof(boundary), "--%s", val);
1296 if (blen == -1 || (size_t)blen >= sizeof(boundary))
1297 goto cleanup;
1298
1299 if (!multipart_find_data(&in, NULL, NULL, req, boundary, blen))
1300 goto cleanup;
1301
1302 for (;;) {
1303 if (!multipart_find_data(&in, NULL, NULL, req, "\r\n", 2))
1304 break;
1305 if (in.offset < 4 && req->http_body_length == 0)
1306 break;
1307 if (!multipart_find_data(&in, &out, NULL, req, "\r\n\r\n", 4))
1308 break;
1309 if (!multipart_parse_headers(req, &in, &out, boundary, blen))
1310 break;
1311
1312 kore_buf_reset(&out);
1313 }
1314
1315 cleanup:
1316 kore_free(type);
1317 kore_buf_cleanup(&in);
1318 kore_buf_cleanup(&out);
1319 }
1320
1321 int
1322 http_body_rewind(struct http_request *req)
1323 {
1324 if (req->http_body_fd != -1) {
1325 if (lseek(req->http_body_fd, 0, SEEK_SET) == -1) {
1326 kore_log(LOG_ERR, "lseek(%s) failed: %s",
1327 req->http_body_path, errno_s);
1328 return (KORE_RESULT_ERROR);
1329 }
1330 } else if (req->http_body != NULL) {
1331 kore_buf_reset(req->http_body);
1332 }
1333
1334 req->http_body_offset = 0;
1335 req->http_body_length = req->content_length;
1336
1337 return (KORE_RESULT_OK);
1338 }
1339
1340 int
1341 http_body_digest(struct http_request *req, char *out, size_t len)
1342 {
1343 size_t idx;
1344 int slen;
1345
1346 if (len != HTTP_BODY_DIGEST_STRLEN) {
1347 fatal("http_body_digest: bad len:%zu wanted:%u",
1348 len, HTTP_BODY_DIGEST_STRLEN);
1349 }
1350
1351 if (!(req->flags & HTTP_REQUEST_COMPLETE))
1352 return (KORE_RESULT_ERROR);
1353
1354 for (idx = 0; idx < sizeof(req->http_body_digest); idx++) {
1355 slen = snprintf(out + (idx * 2), len - (idx * 2), "%02x",
1356 req->http_body_digest[idx]);
1357 if (slen == -1 || (size_t)slen >= len)
1358 fatal("failed to create hex string");
1359 }
1360
1361 return (KORE_RESULT_OK);
1362 }
1363
1364 ssize_t
1365 http_body_read(struct http_request *req, void *out, size_t len)
1366 {
1367 ssize_t ret;
1368 size_t toread;
1369
1370 toread = MIN(req->http_body_length, len);
1371 if (toread == 0)
1372 return (0);
1373
1374 if (req->http_body_fd != -1) {
1375 for (;;) {
1376 ret = read(req->http_body_fd, out, toread);
1377 if (ret == -1) {
1378 if (errno == EINTR)
1379 continue;
1380 kore_log(LOG_ERR, "failed to read %s: %s",
1381 req->http_body_path, errno_s);
1382 return (-1);
1383 }
1384 if (ret == 0)
1385 return (0);
1386 break;
1387 }
1388 } else if (req->http_body != NULL) {
1389 memcpy(out,
1390 (req->http_body->data + req->http_body->offset), toread);
1391 req->http_body->offset += toread;
1392 ret = toread;
1393 } else {
1394 kore_log(LOG_ERR, "http_body_read: called without body");
1395 return (-1);
1396 }
1397
1398 req->http_body_length -= (size_t)ret;
1399 req->http_body_offset += (size_t)ret;
1400
1401 return (ret);
1402 }
1403
1404 int
1405 http_state_run(struct http_state *states, u_int8_t elm,
1406 struct http_request *req)
1407 {
1408 int r, done;
1409
1410 done = 0;
1411
1412 while (!done) {
1413 if (req->fsm_state >= elm) {
1414 fatal("http_state_run: fsm_state > elm (%d/%d)",
1415 req->fsm_state, elm);
1416 }
1417
1418 r = states[req->fsm_state].cb(req);
1419 switch (r) {
1420 case HTTP_STATE_ERROR:
1421 return (KORE_RESULT_OK);
1422 case HTTP_STATE_RETRY:
1423 return (KORE_RESULT_RETRY);
1424 case HTTP_STATE_CONTINUE:
1425 break;
1426 case HTTP_STATE_COMPLETE:
1427 done = 1;
1428 break;
1429 default:
1430 fatal("http_state_run: unknown return value %d", r);
1431 }
1432 }
1433
1434 req->fsm_state = 0;
1435
1436 return (KORE_RESULT_OK);
1437 }
1438
1439 int
1440 http_state_exists(struct http_request *req)
1441 {
1442 return (req->hdlr_extra != NULL);
1443 }
1444
1445 void *
1446 http_state_create(struct http_request *req, size_t len)
1447 {
1448 if (req->hdlr_extra != NULL)
1449 fatal("http_state_create: state already exists");
1450
1451 req->state_len = len;
1452 req->hdlr_extra = kore_calloc(1, len);
1453
1454 return (req->hdlr_extra);
1455 }
1456
1457 void *
1458 http_state_get(struct http_request *req)
1459 {
1460 return (req->hdlr_extra);
1461 }
1462
1463 void
1464 http_state_cleanup(struct http_request *req)
1465 {
1466 kore_free(req->hdlr_extra);
1467 req->hdlr_extra = NULL;
1468 }
1469
1470 void
1471 http_start_recv(struct connection *c)
1472 {
1473 c->http_start = kore_time_ms();
1474 c->http_timeout = http_header_timeout * 1000;
1475 net_recv_reset(c, http_header_max, http_header_recv);
1476 }
1477
1478 void
1479 http_runlock_init(struct http_runlock *lock)
1480 {
1481 lock->owner = NULL;
1482 LIST_INIT(&lock->queue);
1483 }
1484
1485 int
1486 http_runlock_acquire(struct http_runlock *lock, struct http_request *req)
1487 {
1488 if (lock->owner != NULL) {
1489 if (req->runlock != NULL)
1490 fatal("%s: request already waiting on lock", __func__);
1491
1492 req->runlock = kore_pool_get(&http_rlq_pool);
1493 req->runlock->req = req;
1494 LIST_INSERT_HEAD(&lock->queue, req->runlock, list);
1495
1496 http_request_sleep(req);
1497 return (KORE_RESULT_ERROR);
1498 }
1499
1500 lock->owner = req;
1501
1502 return (KORE_RESULT_OK);
1503 }
1504
1505 void
1506 http_runlock_release(struct http_runlock *lock, struct http_request *req)
1507 {
1508 struct http_runlock_queue *next;
1509 struct http_request *nextreq;
1510
1511 if (lock->owner != req)
1512 fatal("%s: calling request != owner of runlock", __func__);
1513
1514 lock->owner = NULL;
1515
1516 if ((next = LIST_FIRST(&lock->queue)) != NULL) {
1517 LIST_REMOVE(next, list);
1518
1519 nextreq = next->req;
1520 nextreq->runlock = NULL;
1521
1522 http_request_wakeup(nextreq);
1523 kore_pool_put(&http_rlq_pool, next);
1524 }
1525 }
1526
1527 int
1528 http_redirect_add(struct kore_domain *dom, const char *path, int status,
1529 const char *target)
1530 {
1531 struct http_redirect *rdr;
1532
1533 rdr = kore_calloc(1, sizeof(*rdr));
1534
1535 if (regcomp(&(rdr->rctx), path, REG_EXTENDED)) {
1536 kore_free(rdr);
1537 return (KORE_RESULT_ERROR);
1538 }
1539
1540 rdr->status = status;
1541
1542 if (target != NULL)
1543 rdr->target = kore_strdup(target);
1544 else
1545 rdr->target = NULL;
1546
1547 TAILQ_INSERT_TAIL(&dom->redirects, rdr, list);
1548
1549 return (KORE_RESULT_OK);
1550 }
1551
1552 const char *
1553 http_status_text(int status)
1554 {
1555 const char *r;
1556
1557 switch (status) {
1558 case HTTP_STATUS_CONTINUE:
1559 r = "Continue";
1560 break;
1561 case HTTP_STATUS_SWITCHING_PROTOCOLS:
1562 r = "Switching Protocols";
1563 break;
1564 case HTTP_STATUS_OK:
1565 r = "OK";
1566 break;
1567 case HTTP_STATUS_CREATED:
1568 r = "Created";
1569 break;
1570 case HTTP_STATUS_ACCEPTED:
1571 r = "Accepted";
1572 break;
1573 case HTTP_STATUS_NON_AUTHORITATIVE:
1574 r = "Non-Authoritative Information";
1575 break;
1576 case HTTP_STATUS_NO_CONTENT:
1577 r = "No Content";
1578 break;
1579 case HTTP_STATUS_RESET_CONTENT:
1580 r = "Reset Content";
1581 break;
1582 case HTTP_STATUS_PARTIAL_CONTENT:
1583 r = "Partial Content";
1584 break;
1585 case HTTP_STATUS_MULTIPLE_CHOICES:
1586 r = "Multiple Choices";
1587 break;
1588 case HTTP_STATUS_MOVED_PERMANENTLY:
1589 r = "Moved Permanently";
1590 break;
1591 case HTTP_STATUS_FOUND:
1592 r = "Found";
1593 break;
1594 case HTTP_STATUS_SEE_OTHER:
1595 r = "See Other";
1596 break;
1597 case HTTP_STATUS_NOT_MODIFIED:
1598 r = "Not Modified";
1599 break;
1600 case HTTP_STATUS_USE_PROXY:
1601 r = "Use Proxy";
1602 break;
1603 case HTTP_STATUS_TEMPORARY_REDIRECT:
1604 r = "Temporary Redirect";
1605 break;
1606 case HTTP_STATUS_BAD_REQUEST:
1607 r = "Bad Request";
1608 break;
1609 case HTTP_STATUS_UNAUTHORIZED:
1610 r = "Unauthorized";
1611 break;
1612 case HTTP_STATUS_PAYMENT_REQUIRED:
1613 r = "Payment Required";
1614 break;
1615 case HTTP_STATUS_FORBIDDEN:
1616 r = "Forbidden";
1617 break;
1618 case HTTP_STATUS_NOT_FOUND:
1619 r = "Not Found";
1620 break;
1621 case HTTP_STATUS_METHOD_NOT_ALLOWED:
1622 r = "Method Not Allowed";
1623 break;
1624 case HTTP_STATUS_NOT_ACCEPTABLE:
1625 r = "Not Acceptable";
1626 break;
1627 case HTTP_STATUS_PROXY_AUTH_REQUIRED:
1628 r = "Proxy Authentication Required";
1629 break;
1630 case HTTP_STATUS_REQUEST_TIMEOUT:
1631 r = "Request Time-out";
1632 break;
1633 case HTTP_STATUS_CONFLICT:
1634 r = "Conflict";
1635 break;
1636 case HTTP_STATUS_GONE:
1637 r = "Gone";
1638 break;
1639 case HTTP_STATUS_LENGTH_REQUIRED:
1640 r = "Length Required";
1641 break;
1642 case HTTP_STATUS_PRECONDITION_FAILED:
1643 r = "Precondition Failed";
1644 break;
1645 case HTTP_STATUS_REQUEST_ENTITY_TOO_LARGE:
1646 r = "Request Entity Too Large";
1647 break;
1648 case HTTP_STATUS_REQUEST_URI_TOO_LARGE:
1649 r = "Request-URI Too Large";
1650 break;
1651 case HTTP_STATUS_UNSUPPORTED_MEDIA_TYPE:
1652 r = "Unsupported Media Type";
1653 break;
1654 case HTTP_STATUS_REQUEST_RANGE_INVALID:
1655 r = "Requested range not satisfiable";
1656 break;
1657 case HTTP_STATUS_EXPECTATION_FAILED:
1658 r = "Expectation Failed";
1659 break;
1660 case HTTP_STATUS_MISDIRECTED_REQUEST:
1661 r = "Misdirected Request";
1662 break;
1663 case HTTP_STATUS_INTERNAL_ERROR:
1664 r = "Internal Server Error";
1665 break;
1666 case HTTP_STATUS_NOT_IMPLEMENTED:
1667 r = "Not Implemented";
1668 break;
1669 case HTTP_STATUS_BAD_GATEWAY:
1670 r = "Bad Gateway";
1671 break;
1672 case HTTP_STATUS_SERVICE_UNAVAILABLE:
1673 r = "Service Unavailable";
1674 break;
1675 case HTTP_STATUS_GATEWAY_TIMEOUT:
1676 r = "Gateway Time-out";
1677 break;
1678 case HTTP_STATUS_BAD_VERSION:
1679 r = "HTTP Version not supported";
1680 break;
1681 default:
1682 r = "";
1683 break;
1684 }
1685
1686 return (r);
1687 }
1688
1689 const char *
1690 http_method_text(int method)
1691 {
1692 char *r;
1693
1694 switch(method) {
1695 case HTTP_METHOD_GET:
1696 r = "GET";
1697 break;
1698 case HTTP_METHOD_POST:
1699 r = "POST";
1700 break;
1701 case HTTP_METHOD_PUT:
1702 r = "PUT";
1703 break;
1704 case HTTP_METHOD_DELETE:
1705 r = "DELETE";
1706 break;
1707 case HTTP_METHOD_HEAD:
1708 r = "HEAD";
1709 break;
1710 case HTTP_METHOD_OPTIONS:
1711 r = "OPTIONS";
1712 break;
1713 case HTTP_METHOD_PATCH:
1714 r = "PATCH";
1715 break;
1716 default:
1717 r = "";
1718 break;
1719 }
1720
1721 return (r);
1722 }
1723
1724 int
1725 http_method_value(const char *method)
1726 {
1727 if (!strcasecmp(method, "GET"))
1728 return (HTTP_METHOD_GET);
1729
1730 if (!strcasecmp(method, "POST"))
1731 return (HTTP_METHOD_POST);
1732
1733 if (!strcasecmp(method, "PUT"))
1734 return (HTTP_METHOD_PUT);
1735
1736 if (!strcasecmp(method, "DELETE"))
1737 return (HTTP_METHOD_DELETE);
1738
1739 if (!strcasecmp(method, "HEAD"))
1740 return (HTTP_METHOD_HEAD);
1741
1742 if (!strcasecmp(method, "OPTIONS"))
1743 return (HTTP_METHOD_OPTIONS);
1744
1745 if (!strcasecmp(method, "PATCH"))
1746 return (HTTP_METHOD_PATCH);
1747
1748 return (0);
1749 }
1750
1751 int
1752 http_media_register(const char *ext, const char *type)
1753 {
1754 struct http_media_type *media;
1755
1756 LIST_FOREACH(media, &http_media_types, list) {
1757 if (!strcasecmp(media->ext, ext))
1758 return (KORE_RESULT_ERROR);
1759 }
1760
1761 media = kore_calloc(1, sizeof(*media));
1762 media->ext = kore_strdup(ext);
1763 media->type = kore_strdup(type);
1764
1765 LIST_INSERT_HEAD(&http_media_types, media, list);
1766
1767 return (KORE_RESULT_OK);
1768 }
1769
1770 const char *
1771 http_media_type(const char *path)
1772 {
1773 const char *p;
1774 struct http_media_type *media;
1775
1776 if ((p = strrchr(path, '.')) == NULL)
1777 return (NULL);
1778
1779 p++;
1780 if (*p == '\0')
1781 return (NULL);
1782
1783 LIST_FOREACH(media, &http_media_types, list) {
1784 if (!strcasecmp(media->ext, p))
1785 return (media->type);
1786 }
1787
1788 return (NULL);
1789 }
1790
1791 char *
1792 http_validate_header(char *header)
1793 {
1794 u_int8_t idx;
1795 char *p, *value;
1796
1797 for (p = header; *p != '\0'; p++) {
1798 idx = *p;
1799 if (idx > HTTP_MAP_LIMIT)
1800 return (NULL);
1801
1802 if (*p == ':') {
1803 *(p)++ = '\0';
1804 break;
1805 }
1806
1807 if (*p >= 'A' && *p <= 'Z')
1808 *p += 32;
1809
1810 if (http_token[idx] == 0x00)
1811 return (NULL);
1812 }
1813
1814 while (isspace(*(unsigned char *)p))
1815 p++;
1816
1817 if (*p == '\0')
1818 return (NULL);
1819
1820 value = p;
1821 while (*p != '\0') {
1822 idx = *p;
1823 if (idx > HTTP_MAP_LIMIT)
1824 return (NULL);
1825 if (http_field_content[idx] == 0x00)
1826 return (NULL);
1827 p++;
1828 }
1829
1830 return (value);
1831 }
1832
1833 static int
1834 http_release_buffer(struct netbuf *nb)
1835 {
1836 kore_buf_free(nb->extra);
1837
1838 return (KORE_RESULT_OK);
1839 }
1840
1841 static int
1842 http_check_redirect(struct http_request *req, struct kore_domain *dom)
1843 {
1844 int idx;
1845 struct http_redirect *rdr;
1846 const char *uri;
1847 char key[4];
1848 struct kore_buf location;
1849
1850 TAILQ_FOREACH(rdr, &dom->redirects, list) {
1851 if (!regexec(&(rdr->rctx), req->path,
1852 HTTP_CAPTURE_GROUPS, req->cgroups, 0))
1853 break;
1854 }
1855
1856 if (rdr == NULL)
1857 return (KORE_RESULT_ERROR);
1858
1859 uri = NULL;
1860 kore_buf_init(&location, 128);
1861
1862 if (rdr->target) {
1863 kore_buf_appendf(&location, "%s", rdr->target);
1864
1865 if (req->query_string != NULL) {
1866 kore_buf_replace_string(&location, "$qs",
1867 req->query_string, strlen(req->query_string));
1868 }
1869
1870 /* Starts at 1 to skip the full path. */
1871 for (idx = 1; idx < HTTP_CAPTURE_GROUPS - 1; idx++) {
1872 if (req->cgroups[idx].rm_so == -1 ||
1873 req->cgroups[idx].rm_eo == -1)
1874 break;
1875
1876 (void)snprintf(key, sizeof(key), "$%d", idx);
1877
1878 kore_buf_replace_string(&location, key,
1879 req->path + req->cgroups[idx].rm_so,
1880 req->cgroups[idx].rm_eo - req->cgroups[idx].rm_so);
1881 }
1882
1883 uri = kore_buf_stringify(&location, NULL);
1884 }
1885
1886 if (uri)
1887 http_response_header(req, "location", uri);
1888
1889 http_response(req, rdr->status, NULL, 0);
1890 kore_buf_cleanup(&location);
1891
1892 if (dom->accesslog)
1893 kore_accesslog(req);
1894
1895 return (KORE_RESULT_OK);
1896 }
1897
1898 static struct http_request *
1899 http_request_new(struct connection *c, const char *host,
1900 const char *method, char *path, const char *version)
1901 {
1902 struct kore_domain *dom;
1903 struct http_request *req;
1904 size_t qsoff;
1905 char *p, *hp;
1906 int m, flags, exists;
1907
1908 if (http_request_count >= http_request_limit) {
1909 http_error_response(c, HTTP_STATUS_SERVICE_UNAVAILABLE);
1910 return (NULL);
1911 }
1912
1913 if (strlen(host) >= KORE_DOMAINNAME_LEN - 1) {
1914 http_error_response(c, HTTP_STATUS_BAD_REQUEST);
1915 return (NULL);
1916 }
1917
1918 if (strlen(path) >= HTTP_URI_LEN - 1) {
1919 http_error_response(c, HTTP_STATUS_REQUEST_URI_TOO_LARGE);
1920 return (NULL);
1921 }
1922
1923 if (strcasecmp(version, "http/1.1")) {
1924 if (strcasecmp(version, "http/1.0")) {
1925 http_error_response(c, HTTP_STATUS_BAD_VERSION);
1926 return (NULL);
1927 }
1928
1929 flags = HTTP_VERSION_1_0;
1930 } else {
1931 flags = HTTP_VERSION_1_1;
1932 }
1933
1934 if ((p = strchr(path, '?')) != NULL) {
1935 qsoff = p - path;
1936 } else {
1937 qsoff = 0;
1938 }
1939
1940 hp = NULL;
1941
1942 switch (c->family) {
1943 case AF_INET6:
1944 if (*host == '[') {
1945 if ((hp = strrchr(host, ']')) == NULL) {
1946 http_error_response(c, HTTP_STATUS_BAD_REQUEST);
1947 return (NULL);
1948 }
1949 hp++;
1950 if (*hp == ':')
1951 *hp = '\0';
1952 else
1953 hp = NULL;
1954 }
1955 break;
1956 default:
1957 if ((hp = strrchr(host, ':')) != NULL)
1958 *hp = '\0';
1959 break;
1960 }
1961
1962 if (c->owner->server->tls && c->tls_sni != NULL) {
1963 if (strcasecmp(c->tls_sni, host)) {
1964 http_error_response(c, HTTP_STATUS_MISDIRECTED_REQUEST);
1965 return (NULL);
1966 }
1967 }
1968
1969 if ((dom = kore_domain_lookup(c->owner->server, host)) == NULL) {
1970 http_error_response(c, HTTP_STATUS_NOT_FOUND);
1971 return (NULL);
1972 }
1973
1974 if (dom->cafile != NULL && c->tls_cert == NULL) {
1975 http_error_response(c, HTTP_STATUS_FORBIDDEN);
1976 return (NULL);
1977 }
1978
1979 if (hp != NULL)
1980 *hp = ':';
1981
1982 if (!strcasecmp(method, "get")) {
1983 m = HTTP_METHOD_GET;
1984 flags |= HTTP_REQUEST_COMPLETE;
1985 } else if (!strcasecmp(method, "delete")) {
1986 m = HTTP_METHOD_DELETE;
1987 flags |= HTTP_REQUEST_EXPECT_BODY;
1988 } else if (!strcasecmp(method, "post")) {
1989 m = HTTP_METHOD_POST;
1990 flags |= HTTP_REQUEST_EXPECT_BODY;
1991 } else if (!strcasecmp(method, "put")) {
1992 m = HTTP_METHOD_PUT;
1993 flags |= HTTP_REQUEST_EXPECT_BODY;
1994 } else if (!strcasecmp(method, "head")) {
1995 m = HTTP_METHOD_HEAD;
1996 flags |= HTTP_REQUEST_COMPLETE;
1997 } else if (!strcasecmp(method, "options")) {
1998 m = HTTP_METHOD_OPTIONS;
1999 flags |= HTTP_REQUEST_COMPLETE;
2000 } else if (!strcasecmp(method, "patch")) {
2001 m = HTTP_METHOD_PATCH;
2002 flags |= HTTP_REQUEST_EXPECT_BODY;
2003 } else {
2004 http_error_response(c, HTTP_STATUS_BAD_REQUEST);
2005 return (NULL);
2006 }
2007
2008 if (flags & HTTP_VERSION_1_0) {
2009 if (m != HTTP_METHOD_GET && m != HTTP_METHOD_POST &&
2010 m != HTTP_METHOD_HEAD) {
2011 http_error_response(c, HTTP_STATUS_METHOD_NOT_ALLOWED);
2012 return (NULL);
2013 }
2014 }
2015
2016 req = kore_pool_get(&http_request_pool);
2017
2018 req->end = 0;
2019 req->total = 0;
2020 req->start = 0;
2021 req->owner = c;
2022 req->status = 0;
2023 req->method = m;
2024 req->agent = NULL;
2025 req->referer = NULL;
2026 req->runlock = NULL;
2027 req->flags = flags;
2028 req->fsm_state = 0;
2029 req->http_body = NULL;
2030 req->http_body_fd = -1;
2031 req->hdlr_extra = NULL;
2032 req->content_length = 0;
2033 req->query_string = NULL;
2034 req->http_body_length = 0;
2035 req->http_body_offset = 0;
2036 req->http_body_path = NULL;
2037
2038 req->host = host;
2039 req->path = path;
2040
2041 #if defined(KORE_USE_PYTHON)
2042 req->py_req = NULL;
2043 req->py_coro = NULL;
2044 req->py_rqnext = NULL;
2045 req->py_validator = NULL;
2046 #endif
2047
2048 if (qsoff > 0) {
2049 req->query_string = path + qsoff;
2050 *(req->query_string)++ = '\0';
2051 } else {
2052 req->query_string = NULL;
2053 }
2054
2055 /* Checked further down below if we need to 404. */
2056 exists = kore_route_lookup(req, dom, m, &req->rt);
2057
2058 TAILQ_INIT(&(req->resp_headers));
2059 TAILQ_INIT(&(req->req_headers));
2060 TAILQ_INIT(&(req->resp_cookies));
2061 TAILQ_INIT(&(req->req_cookies));
2062 TAILQ_INIT(&(req->arguments));
2063 TAILQ_INIT(&(req->files));
2064
2065 #if defined(KORE_USE_TASKS)
2066 LIST_INIT(&(req->tasks));
2067 #endif
2068
2069 #if defined(KORE_USE_PGSQL)
2070 LIST_INIT(&(req->pgsqls));
2071 #endif
2072
2073 http_request_count++;
2074 TAILQ_INSERT_HEAD(&http_requests, req, list);
2075 TAILQ_INSERT_TAIL(&(c->http_requests), req, olist);
2076
2077 if (http_check_redirect(req, dom)) {
2078 http_request_free(req);
2079 return (NULL);
2080 }
2081
2082 if (exists == 0) {
2083 http_request_free(req);
2084 http_error_response(c, HTTP_STATUS_NOT_FOUND);
2085 return (NULL);
2086 }
2087
2088 if (req->rt == NULL) {
2089 http_request_free(req);
2090 http_error_response(c, HTTP_STATUS_METHOD_NOT_ALLOWED);
2091 return (NULL);
2092 }
2093
2094 return (req);
2095 }
2096
2097 static int
2098 multipart_find_data(struct kore_buf *in, struct kore_buf *out,
2099 size_t *olen, struct http_request *req, const void *needle, size_t len)
2100 {
2101 ssize_t ret;
2102 size_t left;
2103 u_int8_t *p, first, data[4096];
2104
2105 if (olen != NULL)
2106 *olen = 0;
2107
2108 first = *(const u_int8_t *)needle;
2109 for (;;) {
2110 if (in->offset < len) {
2111 ret = http_body_read(req, data, sizeof(data));
2112 if (ret == -1)
2113 return (KORE_RESULT_ERROR);
2114 if (ret == 0)
2115 return (KORE_RESULT_ERROR);
2116
2117 kore_buf_append(in, data, ret);
2118 continue;
2119 }
2120
2121 p = kore_mem_find(in->data, in->offset, &first, 1);
2122 if (p == NULL) {
2123 if (out != NULL)
2124 kore_buf_append(out, in->data, in->offset);
2125 if (olen != NULL)
2126 *olen += in->offset;
2127 kore_buf_reset(in);
2128 continue;
2129 }
2130
2131 left = in->offset - (p - in->data);
2132 if (left < len) {
2133 if (out != NULL)
2134 kore_buf_append(out, in->data, (p - in->data));
2135 if (olen != NULL)
2136 *olen += (p - in->data);
2137 memmove(in->data, p, left);
2138 in->offset = left;
2139 continue;
2140 }
2141
2142 if (!memcmp(p, needle, len)) {
2143 if (out != NULL)
2144 kore_buf_append(out, in->data, p - in->data);
2145 if (olen != NULL)
2146 *olen += (p - in->data);
2147
2148 in->offset = left - len;
2149 if (in->offset > 0)
2150 memmove(in->data, p + len, in->offset);
2151 return (KORE_RESULT_OK);
2152 }
2153
2154 if (out != NULL)
2155 kore_buf_append(out, in->data, (p - in->data) + 1);
2156 if (olen != NULL)
2157 *olen += (p - in->data) + 1;
2158
2159 in->offset = left - 1;
2160 if (in->offset > 0)
2161 memmove(in->data, p + 1, in->offset);
2162 }
2163
2164 return (KORE_RESULT_ERROR);
2165 }
2166
2167 static int
2168 multipart_parse_headers(struct http_request *req, struct kore_buf *in,
2169 struct kore_buf *hbuf, const char *boundary, const int blen)
2170 {
2171 int h, c, i;
2172 char *headers[5], *args[5], *opt[5];
2173 char *d, *val, *name, *fname, *string;
2174
2175 string = kore_buf_stringify(hbuf, NULL);
2176 h = kore_split_string(string, "\r\n", headers, 5);
2177 for (i = 0; i < h; i++) {
2178 c = kore_split_string(headers[i], ":", args, 5);
2179 if (c != 2)
2180 continue;
2181
2182 /* Ignore other headers for now. */
2183 if (strcasecmp(args[0], "content-disposition"))
2184 continue;
2185
2186 for (d = args[1]; isspace(*(unsigned char *)d); d++)
2187 ;
2188
2189 c = kore_split_string(d, ";", opt, 5);
2190 if (c < 2)
2191 continue;
2192
2193 if (strcasecmp(opt[0], "form-data"))
2194 continue;
2195
2196 if ((val = strchr(opt[1], '=')) == NULL)
2197 continue;
2198 if (strlen(val) < 3)
2199 continue;
2200
2201 val++;
2202 kore_strip_chars(val, '"', &name);
2203
2204 if (opt[2] == NULL) {
2205 multipart_add_field(req, in, name, boundary, blen);
2206 kore_free(name);
2207 continue;
2208 }
2209
2210 for (d = opt[2]; isspace(*(unsigned char *)d); d++)
2211 ;
2212
2213 if (!strncasecmp(d, "filename=", 9)) {
2214 if ((val = strchr(d, '=')) == NULL) {
2215 kore_free(name);
2216 continue;
2217 }
2218
2219 val++;
2220 kore_strip_chars(val, '"', &fname);
2221 if (strlen(fname) > 0) {
2222 multipart_file_add(req,
2223 in, name, fname, boundary, blen);
2224 }
2225 kore_free(fname);
2226 }
2227
2228 kore_free(name);
2229 }
2230
2231 return (KORE_RESULT_OK);
2232 }
2233
2234 static void
2235 multipart_add_field(struct http_request *req, struct kore_buf *in,
2236 char *name, const char *boundary, const int blen)
2237 {
2238 struct kore_buf *data;
2239 char *string;
2240
2241 data = kore_buf_alloc(128);
2242
2243 if (!multipart_find_data(in, data, NULL, req, boundary, blen)) {
2244 kore_buf_free(data);
2245 return;
2246 }
2247
2248 if (data->offset < 3) {
2249 kore_buf_free(data);
2250 return;
2251 }
2252
2253 data->offset -= 2;
2254 string = kore_buf_stringify(data, NULL);
2255 http_argument_add(req, name, string, 0, 0);
2256 kore_buf_free(data);
2257 }
2258
2259 static void
2260 multipart_file_add(struct http_request *req, struct kore_buf *in,
2261 const char *name, const char *fname, const char *boundary, const int blen)
2262 {
2263 struct http_file *f;
2264 size_t position, len;
2265
2266 position = req->http_body_offset - in->offset;
2267 if (!multipart_find_data(in, NULL, &len, req, boundary, blen))
2268 return;
2269
2270 if (len < 3)
2271 return;
2272 len -= 2;
2273
2274 f = kore_malloc(sizeof(struct http_file));
2275 f->req = req;
2276 f->offset = 0;
2277 f->length = len;
2278 f->position = position;
2279 f->name = kore_strdup(name);
2280 f->filename = kore_strdup(fname);
2281
2282 TAILQ_INSERT_TAIL(&(req->files), f, list);
2283 }
2284
2285 static void
2286 http_argument_add(struct http_request *req, char *name, char *value, int qs,
2287 int decode)
2288 {
2289 struct http_arg *q;
2290 struct kore_route_params *p;
2291
2292 if (decode) {
2293 if (!http_argument_urldecode(name, qs))
2294 return;
2295 }
2296
2297 TAILQ_FOREACH(p, &req->rt->params, list) {
2298 if (qs == 1 && !(p->flags & KORE_PARAMS_QUERY_STRING))
2299 continue;
2300 if (qs == 0 && (p->flags & KORE_PARAMS_QUERY_STRING))
2301 continue;
2302
2303 if (p->method != req->method)
2304 continue;
2305
2306 if (strcmp(p->name, name))
2307 continue;
2308
2309 if (decode) {
2310 if (!http_argument_urldecode(value, qs))
2311 return;
2312 }
2313
2314 if (!kore_validator_check(req, p->validator, value))
2315 break;
2316
2317 q = kore_malloc(sizeof(struct http_arg));
2318 q->name = kore_strdup(name);
2319 q->s_value = kore_strdup(value);
2320 TAILQ_INSERT_TAIL(&(req->arguments), q, list);
2321 break;
2322 }
2323 }
2324
2325 static int
2326 http_body_recv(struct netbuf *nb)
2327 {
2328 struct http_request *req = (struct http_request *)nb->extra;
2329
2330 return (http_body_update(req, nb->buf, nb->s_off));
2331 }
2332
2333 static int
2334 http_body_update(struct http_request *req, const void *data, size_t len)
2335 {
2336 ssize_t ret;
2337 u_int64_t bytes_left;
2338
2339 SHA256Update(&req->hashctx, data, len);
2340
2341 if (req->rt->on_body_chunk != NULL) {
2342 if (kore_runtime_http_body_chunk(req->rt->on_body_chunk,
2343 req, data, len) != KORE_RESULT_OK) {
2344 req->flags |= HTTP_REQUEST_DELETE;
2345 http_error_response(req->owner,
2346 HTTP_STATUS_INTERNAL_ERROR);
2347 return (KORE_RESULT_ERROR);
2348 }
2349 } else if (req->http_body_fd != -1) {
2350 ret = write(req->http_body_fd, data, len);
2351 if (ret == -1 || (size_t)ret != len) {
2352 req->flags |= HTTP_REQUEST_DELETE;
2353 http_error_response(req->owner,
2354 HTTP_STATUS_INTERNAL_ERROR);
2355 return (KORE_RESULT_ERROR);
2356 }
2357 } else if (req->http_body != NULL) {
2358 kore_buf_append(req->http_body, data, len);
2359 } else {
2360 req->flags |= HTTP_REQUEST_DELETE;
2361 http_error_response(req->owner,
2362 HTTP_STATUS_INTERNAL_ERROR);
2363 return (KORE_RESULT_ERROR);
2364 }
2365
2366 req->content_length -= len;
2367
2368 if (req->content_length == 0) {
2369 req->owner->http_timeout = 0;
2370 req->owner->rnb->extra = NULL;
2371 http_request_wakeup(req);
2372 req->flags |= HTTP_REQUEST_COMPLETE;
2373 req->flags &= ~HTTP_REQUEST_EXPECT_BODY;
2374 req->content_length = req->http_body_length;
2375 if (!http_body_rewind(req)) {
2376 req->flags |= HTTP_REQUEST_DELETE;
2377 http_error_response(req->owner,
2378 HTTP_STATUS_INTERNAL_ERROR);
2379 return (KORE_RESULT_ERROR);
2380 }
2381 SHA256Final(req->http_body_digest, &req->hashctx);
2382 } else {
2383 bytes_left = req->content_length;
2384 net_recv_reset(req->owner,
2385 MIN(bytes_left, NETBUF_SEND_PAYLOAD_MAX),
2386 http_body_recv);
2387 req->owner->rnb->extra = req;
2388 }
2389
2390 return (KORE_RESULT_OK);
2391 }
2392
2393 static void
2394 http_error_response(struct connection *c, int status)
2395 {
2396 c->flags |= CONN_CLOSE_EMPTY;
2397
2398 switch (c->proto) {
2399 case CONN_PROTO_HTTP:
2400 http_response_normal(NULL, c, status, NULL, 0);
2401 break;
2402 default:
2403 fatal("http_error_response() bad proto %d", c->proto);
2404 /* NOTREACHED. */
2405 }
2406
2407 if (!net_send_flush(c))
2408 kore_connection_disconnect(c);
2409 }
2410
2411 static void
2412 http_response_normal(struct http_request *req, struct connection *c,
2413 int status, const void *d, size_t len)
2414 {
2415 struct kore_buf buf;
2416 struct http_cookie *ck;
2417 struct http_header *hdr;
2418 char version;
2419 const char *conn, *text;
2420 int connection_close, send_body;
2421
2422 send_body = 1;
2423 text = http_status_text(status);
2424
2425 kore_buf_reset(header_buf);
2426
2427 if (req != NULL) {
2428 if (req->flags & HTTP_VERSION_1_0)
2429 version = '0';
2430 else
2431 version = '1';
2432 } else {
2433 version = '1';
2434 }
2435
2436 kore_buf_appendf(header_buf, "HTTP/1.%c %d %s\r\n",
2437 version, status, text);
2438
2439 if (status == 100) {
2440 kore_buf_append(header_buf, "\r\n", 2);
2441 net_send_queue(c, header_buf->data, header_buf->offset);
2442 return;
2443 }
2444
2445 kore_buf_append(header_buf, http_version, http_version_len);
2446
2447 if ((c->flags & CONN_CLOSE_EMPTY) ||
2448 (req != NULL && (req->flags & HTTP_VERSION_1_0))) {
2449 connection_close = 1;
2450 } else {
2451 connection_close = 0;
2452 }
2453
2454 if (connection_close == 0 && req != NULL) {
2455 if (http_request_header(req, "connection", &conn)) {
2456 if ((*conn == 'c' || *conn == 'C') &&
2457 !strcasecmp(conn, "close")) {
2458 connection_close = 1;
2459 }
2460 }
2461 }
2462
2463 kore_buf_init(&buf, 1024);
2464
2465 /* Note that req CAN be NULL. */
2466 if (req == NULL || req->owner->proto != CONN_PROTO_WEBSOCKET) {
2467 if (http_keepalive_time && connection_close == 0) {
2468 kore_buf_appendf(header_buf,
2469 "connection: keep-alive\r\n");
2470 kore_buf_appendf(header_buf,
2471 "keep-alive: timeout=%d\r\n", http_keepalive_time);
2472 } else {
2473 c->flags |= CONN_CLOSE_EMPTY;
2474 kore_buf_appendf(header_buf, "connection: close\r\n");
2475 }
2476 }
2477
2478 if (c->tls && http_hsts_enable) {
2479 kore_buf_appendf(header_buf, "strict-transport-security: ");
2480 kore_buf_appendf(header_buf,
2481 "max-age=%" PRIu64 "; includeSubDomains\r\n",
2482 http_hsts_enable);
2483 }
2484
2485 if (http_pretty_error && d == NULL && status >= 400) {
2486 kore_buf_appendf(&buf, pretty_error_fmt,
2487 status, text, status, text);
2488
2489 d = buf.data;
2490 len = buf.offset;
2491 }
2492
2493 if (req != NULL) {
2494 TAILQ_FOREACH(ck, &(req->resp_cookies), list)
2495 http_write_response_cookie(ck);
2496
2497 TAILQ_FOREACH(hdr, &(req->resp_headers), list) {
2498 kore_buf_appendf(header_buf, "%s: %s\r\n",
2499 hdr->header, hdr->value);
2500 }
2501
2502 if (status != 204 && status >= 200 &&
2503 !(req->flags & HTTP_REQUEST_NO_CONTENT_LENGTH)) {
2504 kore_buf_appendf(header_buf,
2505 "content-length: %zu\r\n", len);
2506 }
2507 } else {
2508 if (status != 204 && status >= 200) {
2509 kore_buf_appendf(header_buf,
2510 "content-length: %zu\r\n", len);
2511 }
2512 }
2513
2514 kore_buf_append(header_buf, "\r\n", 2);
2515 net_send_queue(c, header_buf->data, header_buf->offset);
2516
2517 if (req != NULL && req->method == HTTP_METHOD_HEAD)
2518 send_body = 0;
2519
2520 if (d != NULL && send_body)
2521 net_send_queue(c, d, len);
2522
2523 if (!(c->flags & CONN_CLOSE_EMPTY) && !(c->flags & CONN_IS_BUSY))
2524 http_start_recv(c);
2525
2526 if (req != NULL)
2527 req->content_length = len;
2528
2529 kore_buf_cleanup(&buf);
2530 }
2531
2532 static void
2533 http_write_response_cookie(struct http_cookie *ck)
2534 {
2535 struct tm tm;
2536 char expires[HTTP_DATE_MAXSIZE];
2537
2538 kore_buf_reset(ckhdr_buf);
2539 kore_buf_appendf(ckhdr_buf, "%s=%s", ck->name, ck->value);
2540
2541 if (ck->path != NULL)
2542 kore_buf_appendf(ckhdr_buf, "; Path=%s", ck->path);
2543 if (ck->domain != NULL)
2544 kore_buf_appendf(ckhdr_buf, "; Domain=%s", ck->domain);
2545
2546 if (ck->expires > 0) {
2547 if (gmtime_r(&ck->expires, &tm) == NULL) {
2548 kore_log(LOG_ERR, "gmtime_r(): %s", errno_s);
2549 return;
2550 }
2551
2552 if (strftime(expires, sizeof(expires),
2553 "%a, %d %b %y %H:%M:%S GMT", &tm) == 0) {
2554 kore_log(LOG_ERR, "strftime(): %s", errno_s);
2555 return;
2556 }
2557
2558 kore_buf_appendf(ckhdr_buf, "; Expires=%s", expires);
2559 }
2560
2561 if (ck->maxage > 0)
2562 kore_buf_appendf(ckhdr_buf, "; Max-Age=%u", ck->maxage);
2563
2564 if (ck->flags & HTTP_COOKIE_HTTPONLY)
2565 kore_buf_appendf(ckhdr_buf, "; HttpOnly");
2566 if (ck->flags & HTTP_COOKIE_SECURE)
2567 kore_buf_appendf(ckhdr_buf, "; Secure");
2568
2569 kore_buf_appendf(header_buf, "set-cookie: %s\r\n",
2570 kore_buf_stringify(ckhdr_buf, NULL));
2571 }
2572
2573 static int
2574 http_data_convert(void *data, void **out, void *nout, int type)
2575 {
2576 switch (type) {
2577 case HTTP_ARG_TYPE_RAW:
2578 case HTTP_ARG_TYPE_STRING:
2579 *out = data;
2580 return (KORE_RESULT_OK);
2581 case HTTP_ARG_TYPE_BYTE:
2582 COPY_ARG_TYPE(*(u_int8_t *)data, u_int8_t);
2583 return (KORE_RESULT_OK);
2584 case HTTP_ARG_TYPE_INT16:
2585 COPY_AS_INTTYPE(SHRT_MIN, SHRT_MAX, int16_t);
2586 return (KORE_RESULT_OK);
2587 case HTTP_ARG_TYPE_UINT16:
2588 COPY_AS_INTTYPE(0, USHRT_MAX, u_int16_t);
2589 return (KORE_RESULT_OK);
2590 case HTTP_ARG_TYPE_INT32:
2591 COPY_AS_INTTYPE(INT_MIN, INT_MAX, int32_t);
2592 return (KORE_RESULT_OK);
2593 case HTTP_ARG_TYPE_UINT32:
2594 COPY_AS_INTTYPE(0, UINT_MAX, u_int32_t);
2595 return (KORE_RESULT_OK);
2596 case HTTP_ARG_TYPE_INT64:
2597 COPY_AS_INTTYPE_64(int64_t, 1);
2598 return (KORE_RESULT_OK);
2599 case HTTP_ARG_TYPE_UINT64:
2600 COPY_AS_INTTYPE_64(u_int64_t, 0);
2601 return (KORE_RESULT_OK);
2602 case HTTP_ARG_TYPE_FLOAT:
2603 COPY_ARG_DOUBLE(-FLT_MAX, FLT_MAX, float);
2604 return (KORE_RESULT_OK);
2605 case HTTP_ARG_TYPE_DOUBLE:
2606 COPY_ARG_DOUBLE(-DBL_MAX, DBL_MAX, double);
2607 return (KORE_RESULT_OK);
2608 default:
2609 break;
2610 }
2611
2612 return (KORE_RESULT_ERROR);
2613 }