1 /* $OpenBSD: server_http.c,v 1.149 2021/11/11 15:52:33 claudio Exp $ */
2
3 /*
4 * Copyright (c) 2020 Matthias Pressfreund <mpfr@fn.de>
5 * Copyright (c) 2006 - 2018 Reyk Floeter <reyk@openbsd.org>
6 *
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 */
19
20 #include <sys/types.h>
21 #include <sys/queue.h>
22 #include <sys/socket.h>
23 #include <sys/tree.h>
24 #include <sys/stat.h>
25
26 #include <netinet/in.h>
27 #include <arpa/inet.h>
28
29 #include <errno.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <unistd.h>
33 #include <limits.h>
34 #include <fnmatch.h>
35 #define _WITH_GETLINE
36 #include <stdio.h>
37 #include <time.h>
38 #include <resolv.h>
39 #include <event.h>
40 #include <ctype.h>
41 #include <vis.h>
42 #include <fcntl.h>
43
44 #include "httpd.h"
45 #include "http.h"
46 #include "patterns.h"
47
48 #ifndef __OpenBSD__
49 #include "compat.h"
50 #endif
51
52 static int server_httpmethod_cmp(const void *, const void *);
53 static int server_httperror_cmp(const void *, const void *);
54 void server_httpdesc_free(struct http_descriptor *);
55 int server_http_authenticate(struct server_config *,
56 struct client *);
57 static int http_version_num(char *);
58 char *server_expand_http(struct client *, const char *,
59 char *, size_t);
60 char *replace_var(char *, const char *, const char *);
61 char *read_errdoc(const char *, const char *);
62
63 static struct http_method http_methods[] = HTTP_METHODS;
64 static struct http_error http_errors[] = HTTP_ERRORS;
65
66 void
server_http(void)67 server_http(void)
68 {
69 DPRINTF("%s: sorting lookup tables, pid %d", __func__, getpid());
70
71 /* Sort the HTTP lookup arrays */
72 qsort(http_methods, sizeof(http_methods) /
73 sizeof(http_methods[0]) - 1,
74 sizeof(http_methods[0]), server_httpmethod_cmp);
75 qsort(http_errors, sizeof(http_errors) /
76 sizeof(http_errors[0]) - 1,
77 sizeof(http_errors[0]), server_httperror_cmp);
78 }
79
80 void
server_http_init(struct server * srv)81 server_http_init(struct server *srv)
82 {
83 /* nothing */
84 }
85
86 int
server_httpdesc_init(struct client * clt)87 server_httpdesc_init(struct client *clt)
88 {
89 struct http_descriptor *desc;
90
91 if ((desc = calloc(1, sizeof(*desc))) == NULL)
92 return (-1);
93 RB_INIT(&desc->http_headers);
94 clt->clt_descreq = desc;
95
96 if ((desc = calloc(1, sizeof(*desc))) == NULL) {
97 /* req will be cleaned up later */
98 return (-1);
99 }
100 RB_INIT(&desc->http_headers);
101 clt->clt_descresp = desc;
102
103 return (0);
104 }
105
106 void
server_httpdesc_free(struct http_descriptor * desc)107 server_httpdesc_free(struct http_descriptor *desc)
108 {
109 if (desc == NULL)
110 return;
111
112 free(desc->http_path);
113 desc->http_path = NULL;
114 free(desc->http_path_orig);
115 desc->http_path_orig = NULL;
116 free(desc->http_path_alias);
117 desc->http_path_alias = NULL;
118 free(desc->http_query);
119 desc->http_query = NULL;
120 free(desc->http_query_alias);
121 desc->http_query_alias = NULL;
122 free(desc->http_version);
123 desc->http_version = NULL;
124 free(desc->http_host);
125 desc->http_host = NULL;
126
127 kv_purge(&desc->http_headers);
128 desc->http_lastheader = NULL;
129 desc->http_method = 0;
130 desc->http_chunked = 0;
131 }
132
133 int
server_http_authenticate(struct server_config * srv_conf,struct client * clt)134 server_http_authenticate(struct server_config *srv_conf, struct client *clt)
135 {
136 char decoded[1024];
137 FILE *fp = NULL;
138 struct http_descriptor *desc = clt->clt_descreq;
139 const struct auth *auth = srv_conf->auth;
140 struct kv *ba, key;
141 size_t linesize = 0;
142 ssize_t linelen;
143 int ret = -1;
144 char *line = NULL, *user = NULL, *pass = NULL;
145 char *clt_user = NULL, *clt_pass = NULL;
146
147 memset(decoded, 0, sizeof(decoded));
148 key.kv_key = "Authorization";
149
150 if ((ba = kv_find(&desc->http_headers, &key)) == NULL ||
151 ba->kv_value == NULL)
152 goto done;
153
154 if (strncmp(ba->kv_value, "Basic ", strlen("Basic ")) != 0)
155 goto done;
156
157 if (b64_pton(strchr(ba->kv_value, ' ') + 1, (uint8_t *)decoded,
158 sizeof(decoded)) <= 0)
159 goto done;
160
161 if ((clt_pass = strchr(decoded, ':')) == NULL)
162 goto done;
163
164 clt_user = decoded;
165 *clt_pass++ = '\0';
166 if ((clt->clt_remote_user = strdup(clt_user)) == NULL)
167 goto done;
168
169 if ((fp = fopen(auth->auth_htpasswd, "r")) == NULL)
170 goto done;
171
172 while ((linelen = getline(&line, &linesize, fp)) != -1) {
173 if (line[linelen - 1] == '\n')
174 line[linelen - 1] = '\0';
175 user = line;
176 pass = strchr(line, ':');
177
178 if (pass == NULL) {
179 explicit_bzero(line, linelen);
180 continue;
181 }
182
183 *pass++ = '\0';
184
185 if (strcmp(clt_user, user) != 0) {
186 explicit_bzero(line, linelen);
187 continue;
188 }
189
190 if (crypt_checkpass(clt_pass, pass) == 0) {
191 explicit_bzero(line, linelen);
192 ret = 0;
193 break;
194 }
195 }
196 done:
197 free(line);
198 if (fp != NULL)
199 fclose(fp);
200
201 if (ba != NULL && ba->kv_value != NULL) {
202 explicit_bzero(ba->kv_value, strlen(ba->kv_value));
203 explicit_bzero(decoded, sizeof(decoded));
204 }
205
206 return (ret);
207 }
208
209 static int
http_version_num(char * version)210 http_version_num(char *version)
211 {
212 if (strlen(version) != 8 || strncmp(version, "HTTP/", 5) != 0
213 || !isdigit((unsigned char)version[5]) || version[6] != '.'
214 || !isdigit((unsigned char)version[7]))
215 return (-1);
216 if (version[5] == '0' && version[7] == '9')
217 return (9);
218 if (version[5] == '1') {
219 if (version[7] == '0')
220 return (10);
221 else
222 /* any other version 1.x gets downgraded to 1.1 */
223 return (11);
224 }
225 return (0);
226 }
227
228 void
server_read_http(struct bufferevent * bev,void * arg)229 server_read_http(struct bufferevent *bev, void *arg)
230 {
231 struct client *clt = arg;
232 struct http_descriptor *desc = clt->clt_descreq;
233 struct evbuffer *src = EVBUFFER_INPUT(bev);
234 char *line = NULL, *key, *value;
235 const char *errstr;
236 char *http_version, *query;
237 size_t size, linelen;
238 int version;
239 struct kv *hdr = NULL;
240
241 getmonotime(&clt->clt_tv_last);
242
243 size = EVBUFFER_LENGTH(src);
244 DPRINTF("%s: session %d: size %lu, to read %lld",
245 __func__, clt->clt_id, size, clt->clt_toread);
246 if (!size) {
247 clt->clt_toread = TOREAD_HTTP_HEADER;
248 goto done;
249 }
250
251 while (!clt->clt_headersdone) {
252 if (!clt->clt_line) {
253 /* Peek into the buffer to see if it looks like HTTP */
254 key = EVBUFFER_DATA(src);
255 if (!isalpha((unsigned char)*key)) {
256 server_abort_http(clt, 400,
257 "invalid request line");
258 goto abort;
259 }
260 }
261
262 if ((line = evbuffer_readln(src,
263 &linelen, EVBUFFER_EOL_CRLF_STRICT)) == NULL) {
264 /* No newline found after too many bytes */
265 if (size > SERVER_MAXHEADERLENGTH) {
266 server_abort_http(clt, 413,
267 "request line too long");
268 goto abort;
269 }
270 break;
271 }
272
273 /*
274 * An empty line indicates the end of the request.
275 * libevent already stripped the \r\n for us.
276 */
277 if (!linelen) {
278 clt->clt_headersdone = 1;
279 free(line);
280 break;
281 }
282 key = line;
283
284 /* Limit the total header length minus \r\n */
285 clt->clt_headerlen += linelen;
286 if (clt->clt_headerlen > SERVER_MAXHEADERLENGTH) {
287 server_abort_http(clt, 413, "request too large");
288 goto abort;
289 }
290
291 /*
292 * The first line is the GET/POST/PUT/... request,
293 * subsequent lines are HTTP headers.
294 */
295 if (++clt->clt_line == 1)
296 value = strchr(key, ' ');
297 else if (*key == ' ' || *key == '\t')
298 /* Multiline headers wrap with a space or tab */
299 value = NULL;
300 else {
301 /* Not a multiline header, should have a : */
302 value = strchr(key, ':');
303 if (value == NULL) {
304 server_abort_http(clt, 400, "malformed");
305 goto abort;
306 }
307 }
308 if (value == NULL) {
309 if (clt->clt_line == 1) {
310 server_abort_http(clt, 400, "malformed");
311 goto abort;
312 }
313
314 /* Append line to the last header, if present */
315 if (kv_extend(&desc->http_headers,
316 desc->http_lastheader, line) == NULL)
317 goto fail;
318
319 free(line);
320 continue;
321 }
322 if (*value == ':') {
323 *value++ = '\0';
324 value += strspn(value, " \t\r\n");
325 } else {
326 *value++ = '\0';
327 }
328
329 DPRINTF("%s: session %d: header '%s: %s'", __func__,
330 clt->clt_id, key, value);
331
332 /*
333 * Identify and handle specific HTTP request methods
334 */
335 if (clt->clt_line == 1) {
336 if ((desc->http_method = server_httpmethod_byname(key))
337 == HTTP_METHOD_NONE) {
338 server_abort_http(clt, 400, "malformed");
339 goto abort;
340 }
341
342 /*
343 * Decode request path and query
344 */
345 desc->http_path = strdup(value);
346 if (desc->http_path == NULL)
347 goto fail;
348
349 http_version = strchr(desc->http_path, ' ');
350 if (http_version == NULL) {
351 server_abort_http(clt, 400, "malformed");
352 goto abort;
353 }
354
355 *http_version++ = '\0';
356
357 /*
358 * We have to allocate the strings because they could
359 * be changed independently by the filters later.
360 * Allow HTTP version 0.9 to 1.1.
361 * Downgrade http version > 1.1 <= 1.9 to version 1.1.
362 * Return HTTP Version Not Supported for anything else.
363 */
364
365 version = http_version_num(http_version);
366
367 if (version == -1) {
368 server_abort_http(clt, 400, "malformed");
369 goto abort;
370 } else if (version == 0) {
371 server_abort_http(clt, 505, "bad http version");
372 goto abort;
373 } else if (version == 11) {
374 if ((desc->http_version =
375 strdup("HTTP/1.1")) == NULL)
376 goto fail;
377 } else {
378 if ((desc->http_version =
379 strdup(http_version)) == NULL)
380 goto fail;
381 }
382
383 query = strchr(desc->http_path, '?');
384 if (query != NULL) {
385 *query++ = '\0';
386
387 if ((desc->http_query = strdup(query)) == NULL)
388 goto fail;
389 }
390
391 } else if (desc->http_method != HTTP_METHOD_NONE &&
392 strcasecmp("Content-Length", key) == 0) {
393 if (desc->http_method == HTTP_METHOD_TRACE ||
394 desc->http_method == HTTP_METHOD_CONNECT) {
395 /*
396 * These method should not have a body
397 * and thus no Content-Length header.
398 */
399 server_abort_http(clt, 400, "malformed");
400 goto abort;
401 }
402
403 /*
404 * Need to read data from the client after the
405 * HTTP header.
406 * XXX What about non-standard clients not using
407 * the carriage return? And some browsers seem to
408 * include the line length in the content-length.
409 */
410 clt->clt_toread = strtonum(value, 0, LLONG_MAX,
411 &errstr);
412 if (errstr) {
413 server_abort_http(clt, 500, errstr);
414 goto abort;
415 }
416 }
417
418 if (strcasecmp("Transfer-Encoding", key) == 0 &&
419 strcasecmp("chunked", value) == 0)
420 desc->http_chunked = 1;
421
422 if (clt->clt_line != 1) {
423 if ((hdr = kv_add(&desc->http_headers, key,
424 value)) == NULL)
425 goto fail;
426
427 desc->http_lastheader = hdr;
428 }
429
430 free(line);
431 }
432 if (clt->clt_headersdone) {
433 if (desc->http_method == HTTP_METHOD_NONE) {
434 server_abort_http(clt, 406, "no method");
435 return;
436 }
437
438 switch (desc->http_method) {
439 case HTTP_METHOD_CONNECT:
440 /* Data stream */
441 clt->clt_toread = TOREAD_UNLIMITED;
442 bev->readcb = server_read;
443 break;
444 case HTTP_METHOD_GET:
445 case HTTP_METHOD_HEAD:
446 /* WebDAV methods */
447 case HTTP_METHOD_COPY:
448 case HTTP_METHOD_MOVE:
449 clt->clt_toread = 0;
450 break;
451 case HTTP_METHOD_DELETE:
452 case HTTP_METHOD_OPTIONS:
453 case HTTP_METHOD_POST:
454 case HTTP_METHOD_PUT:
455 case HTTP_METHOD_RESPONSE:
456 /* WebDAV methods */
457 case HTTP_METHOD_PROPFIND:
458 case HTTP_METHOD_PROPPATCH:
459 case HTTP_METHOD_MKCOL:
460 case HTTP_METHOD_LOCK:
461 case HTTP_METHOD_UNLOCK:
462 case HTTP_METHOD_VERSION_CONTROL:
463 case HTTP_METHOD_REPORT:
464 case HTTP_METHOD_CHECKOUT:
465 case HTTP_METHOD_CHECKIN:
466 case HTTP_METHOD_UNCHECKOUT:
467 case HTTP_METHOD_MKWORKSPACE:
468 case HTTP_METHOD_UPDATE:
469 case HTTP_METHOD_LABEL:
470 case HTTP_METHOD_MERGE:
471 case HTTP_METHOD_BASELINE_CONTROL:
472 case HTTP_METHOD_MKACTIVITY:
473 case HTTP_METHOD_ORDERPATCH:
474 case HTTP_METHOD_ACL:
475 case HTTP_METHOD_MKREDIRECTREF:
476 case HTTP_METHOD_UPDATEREDIRECTREF:
477 case HTTP_METHOD_SEARCH:
478 case HTTP_METHOD_PATCH:
479 /* HTTP request payload */
480 if (clt->clt_toread > 0)
481 bev->readcb = server_read_httpcontent;
482
483 /* Single-pass HTTP body */
484 if (clt->clt_toread < 0) {
485 clt->clt_toread = TOREAD_UNLIMITED;
486 bev->readcb = server_read;
487 }
488 break;
489 default:
490 server_abort_http(clt, 405, "method not allowed");
491 return;
492 }
493 if (desc->http_chunked) {
494 /* Chunked transfer encoding */
495 clt->clt_toread = TOREAD_HTTP_CHUNK_LENGTH;
496 bev->readcb = server_read_httpchunks;
497 }
498
499 done:
500 if (clt->clt_toread != 0)
501 bufferevent_disable(bev, EV_READ);
502 server_response(httpd_env, clt);
503 return;
504 }
505 if (clt->clt_done) {
506 server_close(clt, "done");
507 return;
508 }
509 if (EVBUFFER_LENGTH(src) && bev->readcb != server_read_http)
510 bev->readcb(bev, arg);
511 bufferevent_enable(bev, EV_READ);
512 return;
513 fail:
514 server_abort_http(clt, 500, strerror(errno));
515 abort:
516 free(line);
517 }
518
519 void
server_read_httpcontent(struct bufferevent * bev,void * arg)520 server_read_httpcontent(struct bufferevent *bev, void *arg)
521 {
522 struct client *clt = arg;
523 struct evbuffer *src = EVBUFFER_INPUT(bev);
524 size_t size;
525
526 getmonotime(&clt->clt_tv_last);
527
528 size = EVBUFFER_LENGTH(src);
529 DPRINTF("%s: session %d: size %lu, to read %lld", __func__,
530 clt->clt_id, size, clt->clt_toread);
531 if (!size)
532 return;
533
534 if (clt->clt_toread > 0) {
535 /* Read content data */
536 if ((off_t)size > clt->clt_toread) {
537 size = clt->clt_toread;
538 if (fcgi_add_stdin(clt, src) == -1)
539 goto fail;
540 clt->clt_toread = 0;
541 } else {
542 if (fcgi_add_stdin(clt, src) == -1)
543 goto fail;
544 clt->clt_toread -= size;
545 }
546 DPRINTF("%s: done, size %lu, to read %lld", __func__,
547 size, clt->clt_toread);
548 }
549 if (clt->clt_toread == 0) {
550 fcgi_add_stdin(clt, NULL);
551 clt->clt_toread = TOREAD_HTTP_HEADER;
552 bufferevent_disable(bev, EV_READ);
553 bev->readcb = server_read_http;
554 return;
555 }
556 if (clt->clt_done)
557 goto done;
558 if (bev->readcb != server_read_httpcontent)
559 bev->readcb(bev, arg);
560
561 return;
562 done:
563 return;
564 fail:
565 server_close(clt, strerror(errno));
566 }
567
568 void
server_read_httpchunks(struct bufferevent * bev,void * arg)569 server_read_httpchunks(struct bufferevent *bev, void *arg)
570 {
571 struct client *clt = arg;
572 struct evbuffer *src = EVBUFFER_INPUT(bev);
573 char *line;
574 long long llval;
575 size_t size;
576
577 getmonotime(&clt->clt_tv_last);
578
579 size = EVBUFFER_LENGTH(src);
580 DPRINTF("%s: session %d: size %lu, to read %lld", __func__,
581 clt->clt_id, size, clt->clt_toread);
582 if (!size)
583 return;
584
585 if (clt->clt_toread > 0) {
586 /* Read chunk data */
587 if ((off_t)size > clt->clt_toread) {
588 size = clt->clt_toread;
589 if (server_bufferevent_write_chunk(clt, src, size)
590 == -1)
591 goto fail;
592 clt->clt_toread = 0;
593 } else {
594 if (server_bufferevent_write_buffer(clt, src) == -1)
595 goto fail;
596 clt->clt_toread -= size;
597 }
598 DPRINTF("%s: done, size %lu, to read %lld", __func__,
599 size, clt->clt_toread);
600 }
601 switch (clt->clt_toread) {
602 case TOREAD_HTTP_CHUNK_LENGTH:
603 line = evbuffer_readln(src, NULL, EVBUFFER_EOL_CRLF_STRICT);
604 if (line == NULL) {
605 /* Ignore empty line, continue */
606 bufferevent_enable(bev, EV_READ);
607 return;
608 }
609 if (strlen(line) == 0) {
610 free(line);
611 goto next;
612 }
613
614 /*
615 * Read prepended chunk size in hex, ignore the trailer.
616 * The returned signed value must not be negative.
617 */
618 if (sscanf(line, "%llx", &llval) != 1 || llval < 0) {
619 free(line);
620 server_close(clt, "invalid chunk size");
621 return;
622 }
623
624 if (server_bufferevent_print(clt, line) == -1 ||
625 server_bufferevent_print(clt, "\r\n") == -1) {
626 free(line);
627 goto fail;
628 }
629 free(line);
630
631 if ((clt->clt_toread = llval) == 0) {
632 DPRINTF("%s: last chunk", __func__);
633 clt->clt_toread = TOREAD_HTTP_CHUNK_TRAILER;
634 }
635 break;
636 case TOREAD_HTTP_CHUNK_TRAILER:
637 /* Last chunk is 0 bytes followed by trailer and empty line */
638 line = evbuffer_readln(src, NULL, EVBUFFER_EOL_CRLF_STRICT);
639 if (line == NULL) {
640 /* Ignore empty line, continue */
641 bufferevent_enable(bev, EV_READ);
642 return;
643 }
644 if (server_bufferevent_print(clt, line) == -1 ||
645 server_bufferevent_print(clt, "\r\n") == -1) {
646 free(line);
647 goto fail;
648 }
649 if (strlen(line) == 0) {
650 /* Switch to HTTP header mode */
651 clt->clt_toread = TOREAD_HTTP_HEADER;
652 bev->readcb = server_read_http;
653 }
654 free(line);
655 break;
656 case 0:
657 /* Chunk is terminated by an empty newline */
658 line = evbuffer_readln(src, NULL, EVBUFFER_EOL_CRLF_STRICT);
659 free(line);
660 if (server_bufferevent_print(clt, "\r\n") == -1)
661 goto fail;
662 clt->clt_toread = TOREAD_HTTP_CHUNK_LENGTH;
663 break;
664 }
665
666 next:
667 if (clt->clt_done)
668 goto done;
669 if (EVBUFFER_LENGTH(src))
670 bev->readcb(bev, arg);
671 bufferevent_enable(bev, EV_READ);
672 return;
673
674 done:
675 server_close(clt, "last http chunk read (done)");
676 return;
677 fail:
678 server_close(clt, strerror(errno));
679 }
680
681 void
server_read_httprange(struct bufferevent * bev,void * arg)682 server_read_httprange(struct bufferevent *bev, void *arg)
683 {
684 struct client *clt = arg;
685 struct evbuffer *src = EVBUFFER_INPUT(bev);
686 size_t size;
687 struct media_type *media;
688 struct range_data *r = &clt->clt_ranges;
689 struct range *range;
690
691 getmonotime(&clt->clt_tv_last);
692
693 if (r->range_toread > 0) {
694 size = EVBUFFER_LENGTH(src);
695 if (!size)
696 return;
697
698 /* Read chunk data */
699 if ((off_t)size > r->range_toread) {
700 size = r->range_toread;
701 if (server_bufferevent_write_chunk(clt, src, size)
702 == -1)
703 goto fail;
704 r->range_toread = 0;
705 } else {
706 if (server_bufferevent_write_buffer(clt, src) == -1)
707 goto fail;
708 r->range_toread -= size;
709 }
710 if (r->range_toread < 1)
711 r->range_toread = TOREAD_HTTP_RANGE;
712 DPRINTF("%s: done, size %lu, to read %lld", __func__,
713 size, r->range_toread);
714 }
715
716 switch (r->range_toread) {
717 case TOREAD_HTTP_RANGE:
718 if (r->range_index >= r->range_count) {
719 if (r->range_count > 1) {
720 /* Add end marker */
721 if (server_bufferevent_printf(clt,
722 "\r\n--%llu--\r\n",
723 clt->clt_boundary) == -1)
724 goto fail;
725 }
726 r->range_toread = TOREAD_HTTP_NONE;
727 break;
728 }
729
730 range = &r->range[r->range_index];
731
732 if (r->range_count > 1) {
733 media = r->range_media;
734 if (server_bufferevent_printf(clt,
735 "\r\n--%llu\r\n"
736 "Content-Type: %s/%s\r\n"
737 "Content-Range: bytes %lld-%lld/%zu\r\n\r\n",
738 clt->clt_boundary,
739 media->media_type, media->media_subtype,
740 range->start, range->end, r->range_total) == -1)
741 goto fail;
742 }
743 r->range_toread = range->end - range->start + 1;
744
745 if (lseek(clt->clt_fd, range->start, SEEK_SET) == -1)
746 goto fail;
747
748 /* Throw away bytes that are already in the input buffer */
749 evbuffer_drain(src, EVBUFFER_LENGTH(src));
750
751 /* Increment for the next part */
752 r->range_index++;
753 break;
754 case TOREAD_HTTP_NONE:
755 goto done;
756 case 0:
757 break;
758 }
759
760 if (clt->clt_done)
761 goto done;
762
763 if (EVBUFFER_LENGTH(EVBUFFER_OUTPUT(clt->clt_bev)) > (size_t)
764 SERVER_MAX_PREFETCH * clt->clt_sndbufsiz) {
765 bufferevent_disable(clt->clt_srvbev, EV_READ);
766 clt->clt_srvbev_throttled = 1;
767 }
768
769 return;
770 done:
771 (*bev->errorcb)(bev, EVBUFFER_READ, bev->cbarg);
772 return;
773 fail:
774 server_close(clt, strerror(errno));
775 }
776
777 void
server_reset_http(struct client * clt)778 server_reset_http(struct client *clt)
779 {
780 struct server *srv = clt->clt_srv;
781
782 server_log(clt, NULL);
783
784 server_httpdesc_free(clt->clt_descreq);
785 server_httpdesc_free(clt->clt_descresp);
786 clt->clt_headerlen = 0;
787 clt->clt_headersdone = 0;
788 clt->clt_done = 0;
789 clt->clt_line = 0;
790 clt->clt_chunk = 0;
791 free(clt->clt_remote_user);
792 clt->clt_remote_user = NULL;
793 clt->clt_bev->readcb = server_read_http;
794 clt->clt_srv_conf = &srv->srv_conf;
795 str_match_free(&clt->clt_srv_match);
796 }
797
798 ssize_t
server_http_time(time_t t,char * tmbuf,size_t len)799 server_http_time(time_t t, char *tmbuf, size_t len)
800 {
801 struct tm tm;
802
803 /* New HTTP/1.1 RFC 7231 prefers IMF-fixdate from RFC 5322 */
804 if (t == -1 || gmtime_r(&t, &tm) == NULL)
805 return (-1);
806 else
807 return (strftime(tmbuf, len, "%a, %d %h %Y %T %Z", &tm));
808 }
809
810 const char *
server_http_host(struct sockaddr_storage * ss,char * buf,size_t len)811 server_http_host(struct sockaddr_storage *ss, char *buf, size_t len)
812 {
813 char hbuf[HOST_NAME_MAX+1];
814 in_port_t port;
815
816 if (print_host(ss, buf, len) == NULL)
817 return (NULL);
818
819 port = ntohs(server_socket_getport(ss));
820 if (port == HTTP_PORT)
821 return (buf);
822
823 switch (ss->ss_family) {
824 case AF_INET:
825 if ((size_t)snprintf(hbuf, sizeof(hbuf),
826 "%s:%u", buf, port) >= sizeof(hbuf))
827 return (NULL);
828 break;
829 case AF_INET6:
830 if ((size_t)snprintf(hbuf, sizeof(hbuf),
831 "[%s]:%u", buf, port) >= sizeof(hbuf))
832 return (NULL);
833 break;
834 }
835
836 if (strlcpy(buf, hbuf, len) >= len)
837 return (NULL);
838
839 return (buf);
840 }
841
842 char *
server_http_parsehost(char * host,char * buf,size_t len,int * portval)843 server_http_parsehost(char *host, char *buf, size_t len, int *portval)
844 {
845 char *start, *end, *port;
846 const char *errstr = NULL;
847
848 if (strlcpy(buf, host, len) >= len) {
849 log_debug("%s: host name too long", __func__);
850 return (NULL);
851 }
852
853 start = buf;
854 end = port = NULL;
855
856 if (*start == '[' && (end = strchr(start, ']')) != NULL) {
857 /* Address enclosed in [] with port, eg. [2001:db8::1]:80 */
858 start++;
859 *end++ = '\0';
860 if ((port = strchr(end, ':')) == NULL || *port == '\0')
861 port = NULL;
862 else
863 port++;
864 memmove(buf, start, strlen(start) + 1);
865 } else if ((end = strchr(start, ':')) != NULL) {
866 /* Name or address with port, eg. www.example.com:80 */
867 *end++ = '\0';
868 port = end;
869 } else {
870 /* Name or address with default port, eg. www.example.com */
871 port = NULL;
872 }
873
874 if (port != NULL) {
875 /* Save the requested port */
876 *portval = strtonum(port, 0, 0xffff, &errstr);
877 if (errstr != NULL) {
878 log_debug("%s: invalid port: %s", __func__,
879 strerror(errno));
880 return (NULL);
881 }
882 *portval = htons(*portval);
883 } else {
884 /* Port not given, indicate the default port */
885 *portval = -1;
886 }
887
888 return (start);
889 }
890
891 void
server_abort_http(struct client * clt,unsigned int code,const char * msg)892 server_abort_http(struct client *clt, unsigned int code, const char *msg)
893 {
894 struct server_config *srv_conf = clt->clt_srv_conf;
895 struct bufferevent *bev = clt->clt_bev;
896 struct http_descriptor *desc = clt->clt_descreq;
897 const char *httperr = NULL, *style;
898 char *httpmsg, *body = NULL, *extraheader = NULL;
899 char tmbuf[32], hbuf[128], *hstsheader = NULL;
900 char *clenheader = NULL;
901 char buf[IBUF_READ_SIZE];
902 char *escapedmsg = NULL;
903 char cstr[5];
904 ssize_t bodylen;
905
906 if (code == 0) {
907 server_close(clt, "dropped");
908 return;
909 }
910
911 if ((httperr = server_httperror_byid(code)) == NULL)
912 httperr = "Unknown Error";
913
914 if (bev == NULL)
915 goto done;
916
917 if (server_log_http(clt, code, 0) == -1)
918 goto done;
919
920 /* Some system information */
921 if (print_host(&srv_conf->ss, hbuf, sizeof(hbuf)) == NULL)
922 goto done;
923
924 if (server_http_time(time(NULL), tmbuf, sizeof(tmbuf)) <= 0)
925 goto done;
926
927 /* Do not send details of the Internal Server Error */
928 switch (code) {
929 case 301:
930 case 302:
931 case 303:
932 case 307:
933 case 308:
934 if (msg == NULL)
935 break;
936 memset(buf, 0, sizeof(buf));
937 if (server_expand_http(clt, msg, buf, sizeof(buf)) == NULL)
938 goto done;
939 if (asprintf(&extraheader, "Location: %s\r\n", buf) == -1) {
940 code = 500;
941 extraheader = NULL;
942 }
943 msg = buf;
944 break;
945 case 401:
946 if (msg == NULL)
947 break;
948 #ifdef __OpenBSD__
949 if (stravis(&escapedmsg, msg, VIS_DQ) == -1) {
950 #else
951 if (stravis(&escapedmsg, msg, VIS_MIMESTYLE) == -1) {
952 #endif
953 code = 500;
954 extraheader = NULL;
955 } else if (asprintf(&extraheader,
956 "WWW-Authenticate: Basic realm=\"%s\"\r\n", escapedmsg)
957 == -1) {
958 code = 500;
959 extraheader = NULL;
960 }
961 break;
962 case 416:
963 if (msg == NULL)
964 break;
965 if (asprintf(&extraheader,
966 "Content-Range: %s\r\n", msg) == -1) {
967 code = 500;
968 extraheader = NULL;
969 }
970 break;
971 default:
972 /*
973 * Do not send details of the error. Traditionally,
974 * web servers responsed with the request path on 40x
975 * errors which could be abused to inject JavaScript etc.
976 * Instead of sanitizing the path here, we just don't
977 * reprint it.
978 */
979 break;
980 }
981
982 free(escapedmsg);
983
984 if ((srv_conf->flags & SRVFLAG_ERRDOCS) == 0)
985 goto builtin; /* errdocs not enabled */
986 if ((size_t)snprintf(cstr, sizeof(cstr), "%03u", code) >= sizeof(cstr))
987 goto builtin;
988
989 if ((body = read_errdoc(srv_conf->errdocroot, cstr)) == NULL &&
990 (body = read_errdoc(srv_conf->errdocroot, HTTPD_ERRDOCTEMPLATE))
991 == NULL)
992 goto builtin;
993
994 body = replace_var(body, "$HTTP_ERROR", httperr);
995 body = replace_var(body, "$RESPONSE_CODE", cstr);
996 body = replace_var(body, "$SERVER_SOFTWARE", HTTPD_SERVERNAME);
997 bodylen = strlen(body);
998 goto send;
999
1000 builtin:
1001 /* A CSS stylesheet allows minimal customization by the user */
1002 style = "body { background-color: white; color: black; font-family: "
1003 "'Comic Sans MS', 'Chalkboard SE', 'Comic Neue', sans-serif; }\n"
1004 "hr { border: 0; border-bottom: 1px dashed; }\n"
1005 "@media (prefers-color-scheme: dark) {\n"
1006 "body { background-color: #1E1F21; color: #EEEFF1; }\n"
1007 "a { color: #BAD7FF; }\n}";
1008
1009 /* Generate simple HTML error document */
1010 if ((bodylen = asprintf(&body,
1011 "<!DOCTYPE html>\n"
1012 "<html>\n"
1013 "<head>\n"
1014 "<meta charset=\"utf-8\">\n"
1015 "<title>%03d %s</title>\n"
1016 "<style type=\"text/css\"><!--\n%s\n--></style>\n"
1017 "</head>\n"
1018 "<body>\n"
1019 "<h1>%03d %s</h1>\n"
1020 "<hr>\n<address>%s</address>\n"
1021 "</body>\n"
1022 "</html>\n",
1023 code, httperr, style, code, httperr, HTTPD_SERVERNAME)) == -1) {
1024 body = NULL;
1025 goto done;
1026 }
1027
1028 send:
1029 if (srv_conf->flags & SRVFLAG_SERVER_HSTS &&
1030 srv_conf->flags & SRVFLAG_TLS) {
1031 if (asprintf(&hstsheader, "Strict-Transport-Security: "
1032 "max-age=%d%s%s\r\n", srv_conf->hsts_max_age,
1033 srv_conf->hsts_flags & HSTSFLAG_SUBDOMAINS ?
1034 "; includeSubDomains" : "",
1035 srv_conf->hsts_flags & HSTSFLAG_PRELOAD ?
1036 "; preload" : "") == -1) {
1037 hstsheader = NULL;
1038 goto done;
1039 }
1040 }
1041
1042 if ((code >= 100 && code < 200) || code == 204)
1043 clenheader = NULL;
1044 else {
1045 if (asprintf(&clenheader,
1046 "Content-Length: %zd\r\n", bodylen) == -1) {
1047 clenheader = NULL;
1048 goto done;
1049 }
1050 }
1051
1052 /* Add basic HTTP headers */
1053 if (asprintf(&httpmsg,
1054 "HTTP/1.0 %03d %s\r\n"
1055 "Date: %s\r\n"
1056 "Server: %s\r\n"
1057 "Connection: close\r\n"
1058 "Content-Type: text/html\r\n"
1059 "%s"
1060 "%s"
1061 "%s"
1062 "\r\n"
1063 "%s",
1064 code, httperr, tmbuf, HTTPD_SERVERNAME,
1065 clenheader == NULL ? "" : clenheader,
1066 extraheader == NULL ? "" : extraheader,
1067 hstsheader == NULL ? "" : hstsheader,
1068 desc->http_method == HTTP_METHOD_HEAD || clenheader == NULL ?
1069 "" : body) == -1)
1070 goto done;
1071
1072 /* Dump the message without checking for success */
1073 server_dump(clt, httpmsg, strlen(httpmsg));
1074 free(httpmsg);
1075
1076 done:
1077 free(body);
1078 free(extraheader);
1079 free(hstsheader);
1080 free(clenheader);
1081 if (msg == NULL)
1082 msg = "\"\"";
1083 if (asprintf(&httpmsg, "%s (%03d %s)", msg, code, httperr) == -1) {
1084 server_close(clt, msg);
1085 } else {
1086 server_close(clt, httpmsg);
1087 free(httpmsg);
1088 }
1089 }
1090
1091 void
1092 server_close_http(struct client *clt)
1093 {
1094 struct http_descriptor *desc;
1095
1096 desc = clt->clt_descreq;
1097 server_httpdesc_free(desc);
1098 free(desc);
1099 clt->clt_descreq = NULL;
1100
1101 desc = clt->clt_descresp;
1102 server_httpdesc_free(desc);
1103 free(desc);
1104 clt->clt_descresp = NULL;
1105 free(clt->clt_remote_user);
1106 clt->clt_remote_user = NULL;
1107
1108 str_match_free(&clt->clt_srv_match);
1109 }
1110
1111 char *
1112 server_expand_http(struct client *clt, const char *val, char *buf,
1113 size_t len)
1114 {
1115 struct http_descriptor *desc = clt->clt_descreq;
1116 struct server_config *srv_conf = clt->clt_srv_conf;
1117 char ibuf[128], *str, *path, *query;
1118 const char *errstr = NULL, *p;
1119 size_t size;
1120 int n, ret;
1121
1122 if (strlcpy(buf, val, len) >= len)
1123 return (NULL);
1124
1125 /* Find previously matched substrings by index */
1126 for (p = val; clt->clt_srv_match.sm_nmatch &&
1127 (p = strstr(p, "%")) != NULL; p++) {
1128 if (!isdigit((unsigned char)*(p + 1)))
1129 continue;
1130
1131 /* Copy number, leading '%' char and add trailing \0 */
1132 size = strspn(p + 1, "0123456789") + 2;
1133 if (size >= sizeof(ibuf))
1134 return (NULL);
1135 (void)strlcpy(ibuf, p, size);
1136 n = strtonum(ibuf + 1, 0,
1137 clt->clt_srv_match.sm_nmatch - 1, &errstr);
1138 if (errstr != NULL)
1139 return (NULL);
1140
1141 /* Expand variable with matched value */
1142 if ((str = url_encode(clt->clt_srv_match.sm_match[n])) == NULL)
1143 return (NULL);
1144 ret = expand_string(buf, len, ibuf, str);
1145 free(str);
1146 if (ret != 0)
1147 return (NULL);
1148 }
1149 if (strstr(val, "$DOCUMENT_URI") != NULL) {
1150 if ((path = url_encode(desc->http_path)) == NULL)
1151 return (NULL);
1152 ret = expand_string(buf, len, "$DOCUMENT_URI", path);
1153 free(path);
1154 if (ret != 0)
1155 return (NULL);
1156 }
1157 if (strstr(val, "$QUERY_STRING_ENC") != NULL) {
1158 if (desc->http_query == NULL) {
1159 ret = expand_string(buf, len, "$QUERY_STRING_ENC", "");
1160 } else {
1161 if ((query = url_encode(desc->http_query)) == NULL)
1162 return (NULL);
1163 ret = expand_string(buf, len, "$QUERY_STRING_ENC", query);
1164 free(query);
1165 }
1166 if (ret != 0)
1167 return (NULL);
1168 }
1169 if (strstr(val, "$QUERY_STRING") != NULL) {
1170 if (desc->http_query == NULL) {
1171 ret = expand_string(buf, len, "$QUERY_STRING", "");
1172 } else {
1173 ret = expand_string(buf, len, "$QUERY_STRING",
1174 desc->http_query);
1175 }
1176 if (ret != 0)
1177 return (NULL);
1178 }
1179 if (strstr(val, "$HTTP_HOST") != NULL) {
1180 if (desc->http_host == NULL)
1181 return (NULL);
1182 if ((str = url_encode(desc->http_host)) == NULL)
1183 return (NULL);
1184 expand_string(buf, len, "$HTTP_HOST", str);
1185 free(str);
1186 }
1187 if (strstr(val, "$REMOTE_") != NULL) {
1188 if (strstr(val, "$REMOTE_ADDR") != NULL) {
1189 if (print_host(&clt->clt_ss,
1190 ibuf, sizeof(ibuf)) == NULL)
1191 return (NULL);
1192 if (expand_string(buf, len,
1193 "$REMOTE_ADDR", ibuf) != 0)
1194 return (NULL);
1195 }
1196 if (strstr(val, "$REMOTE_PORT") != NULL) {
1197 snprintf(ibuf, sizeof(ibuf),
1198 "%u", ntohs(clt->clt_port));
1199 if (expand_string(buf, len,
1200 "$REMOTE_PORT", ibuf) != 0)
1201 return (NULL);
1202 }
1203 if (strstr(val, "$REMOTE_USER") != NULL) {
1204 if ((srv_conf->flags & SRVFLAG_AUTH) &&
1205 clt->clt_remote_user != NULL) {
1206 if ((str = url_encode(clt->clt_remote_user))
1207 == NULL)
1208 return (NULL);
1209 } else
1210 str = strdup("");
1211 ret = expand_string(buf, len, "$REMOTE_USER", str);
1212 free(str);
1213 if (ret != 0)
1214 return (NULL);
1215 }
1216 }
1217 if (strstr(val, "$REQUEST_URI") != NULL) {
1218 if ((path = url_encode(desc->http_path)) == NULL)
1219 return (NULL);
1220 if (desc->http_query == NULL) {
1221 str = path;
1222 } else {
1223 ret = asprintf(&str, "%s?%s", path, desc->http_query);
1224 free(path);
1225 if (ret == -1)
1226 return (NULL);
1227 }
1228
1229 ret = expand_string(buf, len, "$REQUEST_URI", str);
1230 free(str);
1231 if (ret != 0)
1232 return (NULL);
1233 }
1234 if (strstr(val, "$REQUEST_SCHEME") != NULL) {
1235 if (srv_conf->flags & SRVFLAG_TLS) {
1236 ret = expand_string(buf, len, "$REQUEST_SCHEME", "https");
1237 } else {
1238 ret = expand_string(buf, len, "$REQUEST_SCHEME", "http");
1239 }
1240 if (ret != 0)
1241 return (NULL);
1242 }
1243 if (strstr(val, "$SERVER_") != NULL) {
1244 if (strstr(val, "$SERVER_ADDR") != NULL) {
1245 if (print_host(&srv_conf->ss,
1246 ibuf, sizeof(ibuf)) == NULL)
1247 return (NULL);
1248 if (expand_string(buf, len,
1249 "$SERVER_ADDR", ibuf) != 0)
1250 return (NULL);
1251 }
1252 if (strstr(val, "$SERVER_PORT") != NULL) {
1253 snprintf(ibuf, sizeof(ibuf), "%u",
1254 ntohs(srv_conf->port));
1255 if (expand_string(buf, len,
1256 "$SERVER_PORT", ibuf) != 0)
1257 return (NULL);
1258 }
1259 if (strstr(val, "$SERVER_NAME") != NULL) {
1260 if ((str = url_encode(srv_conf->name))
1261 == NULL)
1262 return (NULL);
1263 ret = expand_string(buf, len, "$SERVER_NAME", str);
1264 free(str);
1265 if (ret != 0)
1266 return (NULL);
1267 }
1268 }
1269
1270 return (buf);
1271 }
1272
1273 int
1274 server_response(struct httpd *httpd, struct client *clt)
1275 {
1276 char path[PATH_MAX];
1277 char hostname[HOST_NAME_MAX+1];
1278 struct http_descriptor *desc = clt->clt_descreq;
1279 struct http_descriptor *resp = clt->clt_descresp;
1280 struct server *srv = clt->clt_srv;
1281 struct server_config *srv_conf = &srv->srv_conf;
1282 struct kv *kv, key, *host;
1283 struct str_find sm;
1284 int portval = -1, ret;
1285 char *hostval, *query;
1286 const char *errstr = NULL;
1287
1288 /* Preserve original path */
1289 if (desc->http_path == NULL ||
1290 (desc->http_path_orig = strdup(desc->http_path)) == NULL)
1291 goto fail;
1292
1293 /* Decode the URL */
1294 if (url_decode(desc->http_path) == NULL)
1295 goto fail;
1296
1297 /* Canonicalize the request path */
1298 if (canonicalize_path(desc->http_path, path, sizeof(path)) == NULL)
1299 goto fail;
1300 free(desc->http_path);
1301 if ((desc->http_path = strdup(path)) == NULL)
1302 goto fail;
1303
1304 key.kv_key = "Host";
1305 if ((host = kv_find(&desc->http_headers, &key)) != NULL &&
1306 host->kv_value == NULL)
1307 host = NULL;
1308
1309 if (strcmp(desc->http_version, "HTTP/1.1") == 0) {
1310 /* Host header is mandatory */
1311 if (host == NULL)
1312 goto fail;
1313
1314 /* Is the connection persistent? */
1315 key.kv_key = "Connection";
1316 if ((kv = kv_find(&desc->http_headers, &key)) != NULL &&
1317 strcasecmp("close", kv->kv_value) == 0)
1318 clt->clt_persist = 0;
1319 else
1320 clt->clt_persist++;
1321 } else {
1322 /* Is the connection persistent? */
1323 key.kv_key = "Connection";
1324 if ((kv = kv_find(&desc->http_headers, &key)) != NULL &&
1325 strcasecmp("keep-alive", kv->kv_value) == 0)
1326 clt->clt_persist++;
1327 else
1328 clt->clt_persist = 0;
1329 }
1330
1331 /*
1332 * Do we have a Host header and matching configuration?
1333 * XXX the Host can also appear in the URL path.
1334 */
1335 if (host != NULL) {
1336 if ((hostval = server_http_parsehost(host->kv_value,
1337 hostname, sizeof(hostname), &portval)) == NULL)
1338 goto fail;
1339
1340 TAILQ_FOREACH(srv_conf, &srv->srv_hosts, entry) {
1341 #ifdef DEBUG
1342 if ((srv_conf->flags & SRVFLAG_LOCATION) == 0) {
1343 DPRINTF("%s: virtual host \"%s:%u\""
1344 " host \"%s\" (\"%s\")",
1345 __func__, srv_conf->name,
1346 ntohs(srv_conf->port), host->kv_value,
1347 hostname);
1348 }
1349 #endif
1350 if (srv_conf->flags & SRVFLAG_LOCATION)
1351 continue;
1352 else if (srv_conf->flags & SRVFLAG_SERVER_MATCH) {
1353 str_find(hostname, srv_conf->name,
1354 &sm, 1, &errstr);
1355 ret = errstr == NULL ? 0 : -1;
1356 } else {
1357 ret = fnmatch(srv_conf->name,
1358 hostname, FNM_CASEFOLD);
1359 }
1360 if (ret == 0 &&
1361 (portval == -1 || portval == srv_conf->port)) {
1362 /* Replace host configuration */
1363 clt->clt_srv_conf = srv_conf;
1364 srv_conf = NULL;
1365 break;
1366 }
1367 }
1368 }
1369
1370 if (srv_conf != NULL) {
1371 /* Use the actual server IP address */
1372 if (server_http_host(&clt->clt_srv_ss, hostname,
1373 sizeof(hostname)) == NULL)
1374 goto fail;
1375 } else {
1376 /* Host header was valid and found */
1377 if (strlcpy(hostname, host->kv_value, sizeof(hostname)) >=
1378 sizeof(hostname))
1379 goto fail;
1380 srv_conf = clt->clt_srv_conf;
1381 }
1382
1383 if (clt->clt_persist >= srv_conf->maxrequests)
1384 clt->clt_persist = 0;
1385
1386 /* pipelining should end after the first "idempotent" method */
1387 if (clt->clt_pipelining && clt->clt_toread > 0)
1388 clt->clt_persist = 0;
1389
1390 if ((desc->http_host = strdup(hostname)) == NULL)
1391 goto fail;
1392
1393 /* Now fill in the mandatory parts of the response descriptor */
1394 resp->http_method = desc->http_method;
1395 if ((resp->http_version = strdup(desc->http_version)) == NULL)
1396 goto fail;
1397
1398 /* Now search for the location */
1399 if ((srv_conf = server_getlocation(clt, desc->http_path)) == NULL) {
1400 server_abort_http(clt, 500, desc->http_path);
1401 return (-1);
1402 }
1403
1404 /* Optional rewrite */
1405 if (srv_conf->flags & SRVFLAG_PATH_REWRITE) {
1406 /* Expand macros */
1407 if (server_expand_http(clt, srv_conf->path,
1408 path, sizeof(path)) == NULL)
1409 goto fail;
1410
1411 /*
1412 * Reset and update the query. The updated query must already
1413 * be URL encoded - either specified by the user or by using the
1414 * original $QUERY_STRING.
1415 */
1416 free(desc->http_query_alias);
1417 desc->http_query_alias = NULL;
1418 if ((query = strchr(path, '?')) != NULL) {
1419 *query++ = '\0';
1420 if ((desc->http_query_alias = strdup(query)) == NULL)
1421 goto fail;
1422 }
1423
1424 /* Canonicalize the updated request path */
1425 if (canonicalize_path(path,
1426 path, sizeof(path)) == NULL)
1427 goto fail;
1428
1429 log_debug("%s: rewrote %s?%s -> %s?%s", __func__,
1430 desc->http_path, desc->http_query ? desc->http_query : "",
1431 path, query ? query : "");
1432
1433 free(desc->http_path_alias);
1434 if ((desc->http_path_alias = strdup(path)) == NULL)
1435 goto fail;
1436
1437 /* Now search for the updated location */
1438 if ((srv_conf = server_getlocation(clt,
1439 desc->http_path_alias)) == NULL) {
1440 server_abort_http(clt, 500, desc->http_path_alias);
1441 return (-1);
1442 }
1443 }
1444
1445 if (clt->clt_toread > 0 && (size_t)clt->clt_toread >
1446 srv_conf->maxrequestbody) {
1447 server_abort_http(clt, 413, "request body too large");
1448 return (-1);
1449 }
1450
1451 if (srv_conf->flags & SRVFLAG_BLOCK) {
1452 server_abort_http(clt, srv_conf->return_code,
1453 srv_conf->return_uri);
1454 return (-1);
1455 } else if (srv_conf->flags & SRVFLAG_AUTH &&
1456 server_http_authenticate(srv_conf, clt) == -1) {
1457 server_abort_http(clt, 401, srv_conf->auth_realm);
1458 return (-1);
1459 } else
1460 return (server_file(httpd, clt));
1461 fail:
1462 server_abort_http(clt, 400, "bad request");
1463 return (-1);
1464 }
1465
1466 const char *
1467 server_root_strip(const char *path, int n)
1468 {
1469 const char *p;
1470
1471 /* Strip strip leading directories. Leading '/' is ignored. */
1472 for (; n > 0 && *path != '\0'; n--)
1473 if ((p = strchr(++path, '/')) == NULL)
1474 path = strchr(path, '\0');
1475 else
1476 path = p;
1477
1478 return (path);
1479 }
1480
1481 struct server_config *
1482 server_getlocation(struct client *clt, const char *path)
1483 {
1484 struct server *srv = clt->clt_srv;
1485 struct server_config *srv_conf = clt->clt_srv_conf, *location;
1486 const char *errstr = NULL;
1487 int ret;
1488
1489 /* Now search for the location */
1490 TAILQ_FOREACH(location, &srv->srv_hosts, entry) {
1491 #ifdef DEBUG
1492 if (location->flags & SRVFLAG_LOCATION) {
1493 DPRINTF("%s: location \"%s\" path \"%s\"",
1494 __func__, location->location, path);
1495 }
1496 #endif
1497 if ((location->flags & SRVFLAG_LOCATION) &&
1498 location->parent_id == srv_conf->parent_id) {
1499 errstr = NULL;
1500 if (location->flags & SRVFLAG_LOCATION_MATCH) {
1501 ret = str_match(path, location->location,
1502 &clt->clt_srv_match, &errstr);
1503 } else {
1504 ret = fnmatch(location->location,
1505 path, FNM_CASEFOLD);
1506 }
1507 if (ret == 0 && errstr == NULL) {
1508 if ((ret = server_locationaccesstest(location,
1509 path)) == -1)
1510 return (NULL);
1511
1512 if (ret)
1513 continue;
1514 /* Replace host configuration */
1515 clt->clt_srv_conf = srv_conf = location;
1516 break;
1517 }
1518 }
1519 }
1520
1521 return (srv_conf);
1522 }
1523
1524 int
1525 server_locationaccesstest(struct server_config *srv_conf, const char *path)
1526 {
1527 int rootfd, ret;
1528 struct stat sb;
1529
1530 if (((SRVFLAG_LOCATION_FOUND | SRVFLAG_LOCATION_NOT_FOUND) &
1531 srv_conf->flags) == 0)
1532 return (0);
1533
1534 if ((rootfd = open(srv_conf->root, O_RDONLY)) == -1)
1535 return (-1);
1536
1537 path = server_root_strip(path, srv_conf->strip) + 1;
1538 if ((ret = faccessat(rootfd, path, R_OK, 0)) != -1)
1539 ret = fstatat(rootfd, path, &sb, 0);
1540 close(rootfd);
1541 return ((ret == -1 && SRVFLAG_LOCATION_FOUND & srv_conf->flags) ||
1542 (ret == 0 && SRVFLAG_LOCATION_NOT_FOUND & srv_conf->flags));
1543 }
1544
1545 int
1546 server_response_http(struct client *clt, unsigned int code,
1547 struct media_type *media, off_t size, time_t mtime)
1548 {
1549 struct server_config *srv_conf = clt->clt_srv_conf;
1550 struct http_descriptor *desc = clt->clt_descreq;
1551 struct http_descriptor *resp = clt->clt_descresp;
1552 const char *error;
1553 struct kv *ct, *cl;
1554 char tmbuf[32];
1555
1556 if (desc == NULL || media == NULL ||
1557 (error = server_httperror_byid(code)) == NULL)
1558 return (-1);
1559
1560 if (server_log_http(clt, code, size >= 0 ? size : 0) == -1)
1561 return (-1);
1562
1563 /* Add error codes */
1564 if (kv_setkey(&resp->http_pathquery, "%u", code) == -1 ||
1565 kv_set(&resp->http_pathquery, "%s", error) == -1)
1566 return (-1);
1567
1568 /* Add headers */
1569 if (kv_add(&resp->http_headers, "Server", HTTPD_SERVERNAME) == NULL)
1570 return (-1);
1571
1572 /* Is it a persistent connection? */
1573 if (clt->clt_persist) {
1574 if (kv_add(&resp->http_headers,
1575 "Connection", "keep-alive") == NULL)
1576 return (-1);
1577 } else if (kv_add(&resp->http_headers, "Connection", "close") == NULL)
1578 return (-1);
1579
1580 /* Set media type */
1581 if ((ct = kv_add(&resp->http_headers, "Content-Type", NULL)) == NULL ||
1582 kv_set(ct, "%s/%s", media->media_type, media->media_subtype) == -1)
1583 return (-1);
1584
1585 /* Set content length, if specified */
1586 if (size >= 0 && ((cl =
1587 kv_add(&resp->http_headers, "Content-Length", NULL)) == NULL ||
1588 kv_set(cl, "%lld", (long long)size) == -1))
1589 return (-1);
1590
1591 /* Set last modification time */
1592 if (server_http_time(mtime, tmbuf, sizeof(tmbuf)) <= 0 ||
1593 kv_add(&resp->http_headers, "Last-Modified", tmbuf) == NULL)
1594 return (-1);
1595
1596 /* HSTS header */
1597 if (srv_conf->flags & SRVFLAG_SERVER_HSTS &&
1598 srv_conf->flags & SRVFLAG_TLS) {
1599 if ((cl =
1600 kv_add(&resp->http_headers, "Strict-Transport-Security",
1601 NULL)) == NULL ||
1602 kv_set(cl, "max-age=%d%s%s", srv_conf->hsts_max_age,
1603 srv_conf->hsts_flags & HSTSFLAG_SUBDOMAINS ?
1604 "; includeSubDomains" : "",
1605 srv_conf->hsts_flags & HSTSFLAG_PRELOAD ?
1606 "; preload" : "") == -1)
1607 return (-1);
1608 }
1609
1610 /* Date header is mandatory and should be added as late as possible */
1611 if (server_http_time(time(NULL), tmbuf, sizeof(tmbuf)) <= 0 ||
1612 kv_add(&resp->http_headers, "Date", tmbuf) == NULL)
1613 return (-1);
1614
1615 /* Write completed header */
1616 if (server_writeresponse_http(clt) == -1 ||
1617 server_bufferevent_print(clt, "\r\n") == -1 ||
1618 server_headers(clt, resp, server_writeheader_http, NULL) == -1 ||
1619 server_bufferevent_print(clt, "\r\n") == -1)
1620 return (-1);
1621
1622 if (size <= 0 || resp->http_method == HTTP_METHOD_HEAD) {
1623 bufferevent_enable(clt->clt_bev, EV_READ|EV_WRITE);
1624 if (clt->clt_persist)
1625 clt->clt_toread = TOREAD_HTTP_HEADER;
1626 else
1627 clt->clt_toread = TOREAD_HTTP_NONE;
1628 clt->clt_done = 0;
1629 return (0);
1630 }
1631
1632 return (1);
1633 }
1634
1635 int
1636 server_writeresponse_http(struct client *clt)
1637 {
1638 struct http_descriptor *desc = clt->clt_descresp;
1639
1640 DPRINTF("version: %s rescode: %s resmsg: %s", desc->http_version,
1641 desc->http_rescode, desc->http_resmesg);
1642
1643 if (server_bufferevent_print(clt, desc->http_version) == -1 ||
1644 server_bufferevent_print(clt, " ") == -1 ||
1645 server_bufferevent_print(clt, desc->http_rescode) == -1 ||
1646 server_bufferevent_print(clt, " ") == -1 ||
1647 server_bufferevent_print(clt, desc->http_resmesg) == -1)
1648 return (-1);
1649
1650 return (0);
1651 }
1652
1653 int
1654 server_writeheader_http(struct client *clt, struct kv *hdr, void *arg)
1655 {
1656 char *ptr;
1657 const char *key;
1658
1659 if (hdr->kv_flags & KV_FLAG_INVALID)
1660 return (0);
1661
1662 /* The key might have been updated in the parent */
1663 if (hdr->kv_parent != NULL && hdr->kv_parent->kv_key != NULL)
1664 key = hdr->kv_parent->kv_key;
1665 else
1666 key = hdr->kv_key;
1667
1668 ptr = hdr->kv_value;
1669 if (server_bufferevent_print(clt, key) == -1 ||
1670 (ptr != NULL &&
1671 (server_bufferevent_print(clt, ": ") == -1 ||
1672 server_bufferevent_print(clt, ptr) == -1 ||
1673 server_bufferevent_print(clt, "\r\n") == -1)))
1674 return (-1);
1675 DPRINTF("%s: %s: %s", __func__, key,
1676 hdr->kv_value == NULL ? "" : hdr->kv_value);
1677
1678 return (0);
1679 }
1680
1681 int
1682 server_headers(struct client *clt, void *descp,
1683 int (*hdr_cb)(struct client *, struct kv *, void *), void *arg)
1684 {
1685 struct kv *hdr, *kv;
1686 struct http_descriptor *desc = descp;
1687
1688 RB_FOREACH(hdr, kvtree, &desc->http_headers) {
1689 if ((hdr_cb)(clt, hdr, arg) == -1)
1690 return (-1);
1691 TAILQ_FOREACH(kv, &hdr->kv_children, kv_entry) {
1692 if ((hdr_cb)(clt, kv, arg) == -1)
1693 return (-1);
1694 }
1695 }
1696
1697 return (0);
1698 }
1699
1700 enum httpmethod
1701 server_httpmethod_byname(const char *name)
1702 {
1703 enum httpmethod id = HTTP_METHOD_NONE;
1704 struct http_method method, *res = NULL;
1705
1706 /* Set up key */
1707 method.method_name = name;
1708
1709 if ((res = bsearch(&method, http_methods,
1710 sizeof(http_methods) / sizeof(http_methods[0]) - 1,
1711 sizeof(http_methods[0]), server_httpmethod_cmp)) != NULL)
1712 id = res->method_id;
1713
1714 return (id);
1715 }
1716
1717 const char *
1718 server_httpmethod_byid(unsigned int id)
1719 {
1720 const char *name = "<UNKNOWN>";
1721 int i;
1722
1723 for (i = 0; http_methods[i].method_name != NULL; i++) {
1724 if (http_methods[i].method_id == id) {
1725 name = http_methods[i].method_name;
1726 break;
1727 }
1728 }
1729
1730 return (name);
1731 }
1732
1733 static int
1734 server_httpmethod_cmp(const void *a, const void *b)
1735 {
1736 const struct http_method *ma = a;
1737 const struct http_method *mb = b;
1738
1739 /*
1740 * RFC 2616 section 5.1.1 says that the method is case
1741 * sensitive so we don't do a strcasecmp here.
1742 */
1743 return (strcmp(ma->method_name, mb->method_name));
1744 }
1745
1746 const char *
1747 server_httperror_byid(unsigned int id)
1748 {
1749 struct http_error error, *res;
1750
1751 /* Set up key */
1752 error.error_code = (int)id;
1753
1754 if ((res = bsearch(&error, http_errors,
1755 sizeof(http_errors) / sizeof(http_errors[0]) - 1,
1756 sizeof(http_errors[0]), server_httperror_cmp)) != NULL)
1757 return (res->error_name);
1758
1759 return (NULL);
1760 }
1761
1762 static int
1763 server_httperror_cmp(const void *a, const void *b)
1764 {
1765 const struct http_error *ea = a;
1766 const struct http_error *eb = b;
1767 return (ea->error_code - eb->error_code);
1768 }
1769
1770 /*
1771 * return -1 on failure, strlen() of read file otherwise.
1772 * body is NULL on failure, contents of file with trailing \0 otherwise.
1773 */
1774 char *
1775 read_errdoc(const char *root, const char *file)
1776 {
1777 struct stat sb;
1778 char *path;
1779 int fd;
1780 char *ret = NULL;
1781
1782 if (asprintf(&path, "%s/%s.html", root, file) == -1)
1783 fatal("asprintf");
1784 if ((fd = open(path, O_RDONLY)) == -1) {
1785 free(path);
1786 log_warn("%s: open", __func__);
1787 return (NULL);
1788 }
1789 free(path);
1790 if (fstat(fd, &sb) < 0) {
1791 log_warn("%s: stat", __func__);
1792 return (NULL);
1793 }
1794
1795 if ((ret = calloc(1, sb.st_size + 1)) == NULL)
1796 fatal("calloc");
1797 if (sb.st_size == 0)
1798 return (ret);
1799 if (read(fd, ret, sb.st_size) != sb.st_size) {
1800 log_warn("%s: read", __func__);
1801 close(fd);
1802 free(ret);
1803 ret = NULL;
1804 return (ret);
1805 }
1806 close(fd);
1807
1808 return (ret);
1809 }
1810
1811 char *
1812 replace_var(char *str, const char *var, const char *repl)
1813 {
1814 char *iv, *r;
1815 size_t vlen;
1816
1817 vlen = strlen(var);
1818 while ((iv = strstr(str, var)) != NULL) {
1819 *iv = '\0';
1820 if (asprintf(&r, "%s%s%s", str, repl, &iv[vlen]) == -1)
1821 fatal("asprintf");
1822 free(str);
1823 str = r;
1824 }
1825 return (str);
1826 }
1827
1828 int
1829 server_log_http(struct client *clt, unsigned int code, size_t len)
1830 {
1831 static char tstamp[64];
1832 static char ip[INET6_ADDRSTRLEN];
1833 time_t t;
1834 struct kv key, *agent, *referrer, *xff, *xfp;
1835 struct tm *tm;
1836 struct server_config *srv_conf;
1837 struct http_descriptor *desc;
1838 int ret = -1;
1839 char *user = NULL;
1840 char *path = NULL;
1841 char *version = NULL;
1842 char *referrer_v = NULL;
1843 char *agent_v = NULL;
1844 char *xff_v = NULL;
1845 char *xfp_v = NULL;
1846
1847 if ((srv_conf = clt->clt_srv_conf) == NULL)
1848 return (-1);
1849 if ((srv_conf->flags & SRVFLAG_LOG) == 0)
1850 return (0);
1851 if ((desc = clt->clt_descreq) == NULL)
1852 return (-1);
1853
1854 if ((t = time(NULL)) == -1)
1855 return (-1);
1856 if ((tm = localtime(&t)) == NULL)
1857 return (-1);
1858 if (strftime(tstamp, sizeof(tstamp), "%d/%b/%Y:%H:%M:%S %z", tm) == 0)
1859 return (-1);
1860
1861 if (print_host(&clt->clt_ss, ip, sizeof(ip)) == NULL)
1862 return (-1);
1863
1864 /*
1865 * For details on common log format, see:
1866 * https://httpd.apache.org/docs/current/mod/mod_log_config.html
1867 *
1868 * httpd's format is similar to these Apache LogFormats:
1869 * "%v %h %l %u %t \"%r\" %>s %B"
1870 * "%v %h %l %u %t \"%r\" %>s %B \"%{Referer}i\" \"%{User-agent}i\""
1871 */
1872 switch (srv_conf->logformat) {
1873 case LOG_FORMAT_COMMON:
1874 /* Use vis to encode input values from the header */
1875 if (clt->clt_remote_user &&
1876 stravis(&user, clt->clt_remote_user, HTTPD_LOGVIS) == -1)
1877 goto done;
1878 if (desc->http_version &&
1879 stravis(&version, desc->http_version, HTTPD_LOGVIS) == -1)
1880 goto done;
1881
1882 /* The following should be URL-encoded */
1883 if (desc->http_path &&
1884 (path = url_encode(desc->http_path)) == NULL)
1885 goto done;
1886
1887 ret = evbuffer_add_printf(clt->clt_log,
1888 "%s %s - %s [%s] \"%s %s%s%s%s%s\" %03d %zu\n",
1889 srv_conf->name, ip, clt->clt_remote_user == NULL ? "-" :
1890 user, tstamp,
1891 server_httpmethod_byid(desc->http_method),
1892 desc->http_path == NULL ? "" : path,
1893 desc->http_query == NULL ? "" : "?",
1894 desc->http_query == NULL ? "" : desc->http_query,
1895 desc->http_version == NULL ? "" : " ",
1896 desc->http_version == NULL ? "" : version,
1897 code, len);
1898
1899 break;
1900
1901 case LOG_FORMAT_COMBINED:
1902 case LOG_FORMAT_FORWARDED:
1903 key.kv_key = "Referer"; /* sic */
1904 if ((referrer = kv_find(&desc->http_headers, &key)) != NULL &&
1905 referrer->kv_value == NULL)
1906 referrer = NULL;
1907
1908 key.kv_key = "User-Agent";
1909 if ((agent = kv_find(&desc->http_headers, &key)) != NULL &&
1910 agent->kv_value == NULL)
1911 agent = NULL;
1912
1913 /* Use vis to encode input values from the header */
1914 if (clt->clt_remote_user &&
1915 stravis(&user, clt->clt_remote_user, HTTPD_LOGVIS) == -1)
1916 goto done;
1917 if (clt->clt_remote_user == NULL &&
1918 clt->clt_tls_ctx != NULL &&
1919 (srv_conf->tls_flags & TLSFLAG_CA) &&
1920 tls_peer_cert_subject(clt->clt_tls_ctx) != NULL &&
1921 stravis(&user, tls_peer_cert_subject(clt->clt_tls_ctx),
1922 HTTPD_LOGVIS) == -1)
1923 goto done;
1924 if (desc->http_version &&
1925 stravis(&version, desc->http_version, HTTPD_LOGVIS) == -1)
1926 goto done;
1927 if (agent &&
1928 stravis(&agent_v, agent->kv_value, HTTPD_LOGVIS) == -1)
1929 goto done;
1930
1931 /* The following should be URL-encoded */
1932 if (desc->http_path &&
1933 (path = url_encode(desc->http_path)) == NULL)
1934 goto done;
1935 if (referrer &&
1936 (referrer_v = url_encode(referrer->kv_value)) == NULL)
1937 goto done;
1938
1939 if ((ret = evbuffer_add_printf(clt->clt_log,
1940 "%s %s - %s [%s] \"%s %s%s%s%s%s\""
1941 " %03d %zu \"%s\" \"%s\"",
1942 srv_conf->name, ip, user == NULL ? "-" :
1943 user, tstamp,
1944 server_httpmethod_byid(desc->http_method),
1945 desc->http_path == NULL ? "" : path,
1946 desc->http_query == NULL ? "" : "?",
1947 desc->http_query == NULL ? "" : desc->http_query,
1948 desc->http_version == NULL ? "" : " ",
1949 desc->http_version == NULL ? "" : version,
1950 code, len,
1951 referrer == NULL ? "" : referrer_v,
1952 agent == NULL ? "" : agent_v)) == -1)
1953 break;
1954
1955 if (srv_conf->logformat == LOG_FORMAT_COMBINED)
1956 goto finish;
1957
1958 xff = xfp = NULL;
1959
1960 key.kv_key = "X-Forwarded-For";
1961 if ((xff = kv_find(&desc->http_headers, &key)) != NULL
1962 && xff->kv_value == NULL)
1963 xff = NULL;
1964
1965 if (xff &&
1966 stravis(&xff_v, xff->kv_value, HTTPD_LOGVIS) == -1)
1967 goto finish;
1968
1969 key.kv_key = "X-Forwarded-Port";
1970 if ((xfp = kv_find(&desc->http_headers, &key)) != NULL &&
1971 (xfp->kv_value == NULL))
1972 xfp = NULL;
1973
1974 if (xfp &&
1975 stravis(&xfp_v, xfp->kv_value, HTTPD_LOGVIS) == -1)
1976 goto finish;
1977
1978 if ((ret = evbuffer_add_printf(clt->clt_log, " %s %s",
1979 xff == NULL ? "-" : xff_v,
1980 xfp == NULL ? "-" : xfp_v)) == -1)
1981 break;
1982 finish:
1983 ret = evbuffer_add_printf(clt->clt_log, "\n");
1984
1985 break;
1986
1987 case LOG_FORMAT_CONNECTION:
1988 /* URL-encode the path */
1989 if (desc->http_path &&
1990 (path = url_encode(desc->http_path)) == NULL)
1991 goto done;
1992
1993 ret = evbuffer_add_printf(clt->clt_log, " [%s]",
1994 desc->http_path == NULL ? "" : path);
1995
1996 break;
1997 }
1998
1999 done:
2000 free(user);
2001 free(path);
2002 free(version);
2003 free(referrer_v);
2004 free(agent_v);
2005 free(xff_v);
2006 free(xfp_v);
2007
2008 return (ret);
2009 }
2010