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