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