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