1 /* 2 * uhttpd - Tiny single-threaded httpd 3 * 4 * Copyright (C) 2010-2013 Jo-Philipp Wich <xm@subsignal.org> 5 * Copyright (C) 2013 Felix Fietkau <nbd@openwrt.org> 6 * 7 * Permission to use, copy, modify, and/or 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 <libubox/blobmsg.h> 21 #include <errno.h> 22 #include <limits.h> 23 #include <netinet/tcp.h> 24 25 #include "uhttpd.h" 26 #include "tls.h" 27 28 static LIST_HEAD(clients); 29 static bool client_done = false; 30 31 int n_clients = 0; 32 struct config conf = {}; 33 34 const char * const http_versions[] = { 35 [UH_HTTP_VER_0_9] = "HTTP/0.9", 36 [UH_HTTP_VER_1_0] = "HTTP/1.0", 37 [UH_HTTP_VER_1_1] = "HTTP/1.1", 38 }; 39 40 const char * const http_methods[] = { 41 [UH_HTTP_MSG_GET] = "GET", 42 [UH_HTTP_MSG_POST] = "POST", 43 [UH_HTTP_MSG_HEAD] = "HEAD", 44 [UH_HTTP_MSG_OPTIONS] = "OPTIONS", 45 [UH_HTTP_MSG_PUT] = "PUT", 46 [UH_HTTP_MSG_PATCH] = "PATCH", 47 [UH_HTTP_MSG_DELETE] = "DELETE", 48 }; 49 50 void uh_http_header(struct client *cl, int code, const char *summary) 51 { 52 struct http_request *r = &cl->request; 53 struct blob_attr *cur; 54 const char *enc = "Transfer-Encoding: chunked\r\n"; 55 const char *conn; 56 int rem; 57 58 cl->http_code = code; 59 60 if (!uh_use_chunked(cl)) 61 enc = ""; 62 63 if (r->connection_close) 64 conn = "Connection: close"; 65 else 66 conn = "Connection: Keep-Alive"; 67 68 ustream_printf(cl->us, "%s %03i %s\r\n%s\r\n%s", 69 http_versions[cl->request.version], 70 code, summary, conn, enc); 71 72 if (!r->connection_close) 73 ustream_printf(cl->us, "Keep-Alive: timeout=%d\r\n", conf.http_keepalive); 74 75 blobmsg_for_each_attr(cur, cl->hdr_response.head, rem) 76 ustream_printf(cl->us, "%s: %s\r\n", blobmsg_name(cur), 77 blobmsg_get_string(cur)); 78 } 79 80 static void uh_connection_close(struct client *cl) 81 { 82 cl->state = CLIENT_STATE_CLOSE; 83 cl->us->eof = true; 84 ustream_state_change(cl->us); 85 } 86 87 static void uh_dispatch_done(struct client *cl) 88 { 89 if (cl->dispatch.free) 90 cl->dispatch.free(cl); 91 if (cl->dispatch.req_free) 92 cl->dispatch.req_free(cl); 93 } 94 95 static void client_timeout(struct uloop_timeout *timeout) 96 { 97 struct client *cl = container_of(timeout, struct client, timeout); 98 99 cl->state = CLIENT_STATE_CLOSE; 100 cl->request.connection_close = true; 101 uh_request_done(cl); 102 } 103 104 static void uh_set_client_timeout(struct client *cl, int timeout) 105 { 106 cl->timeout.cb = client_timeout; 107 uloop_timeout_set(&cl->timeout, timeout * 1000); 108 } 109 110 static void uh_keepalive_poll_cb(struct uloop_timeout *timeout) 111 { 112 struct client *cl = container_of(timeout, struct client, timeout); 113 int sec = cl->requests > 0 ? conf.http_keepalive : conf.network_timeout; 114 115 uh_set_client_timeout(cl, sec); 116 cl->us->notify_read(cl->us, 0); 117 } 118 119 static void uh_poll_connection(struct client *cl) 120 { 121 cl->timeout.cb = uh_keepalive_poll_cb; 122 uloop_timeout_set(&cl->timeout, 1); 123 } 124 125 void uh_request_done(struct client *cl) 126 { 127 struct http_request *r = &cl->request; 128 129 uh_chunk_eof(cl); 130 uh_dispatch_done(cl); 131 blob_buf_init(&cl->hdr_response, 0); 132 memset(&cl->dispatch, 0, sizeof(cl->dispatch)); 133 134 /* Close the connection even when keep alive is set, when it 135 * contains a request body, as it was not read and we are 136 * currently out of sync. Without handling this the body will be 137 * interpreted as part of the next request. 138 */ 139 if (r->transfer_chunked || r->content_length > 0) 140 cl->request.connection_close = true; 141 142 if (!conf.http_keepalive || cl->request.connection_close) 143 return uh_connection_close(cl); 144 145 cl->state = CLIENT_STATE_INIT; 146 cl->requests++; 147 uh_poll_connection(cl); 148 } 149 150 void __printf(4, 5) 151 uh_client_error(struct client *cl, int code, const char *summary, const char *fmt, ...) 152 { 153 va_list arg; 154 155 uh_http_header(cl, code, summary); 156 ustream_printf(cl->us, "Content-Type: text/html\r\n\r\n"); 157 158 uh_chunk_printf(cl, "<h1>%s</h1>", summary); 159 160 if (fmt) { 161 va_start(arg, fmt); 162 uh_chunk_vprintf(cl, fmt, arg); 163 va_end(arg); 164 } 165 166 uh_request_done(cl); 167 } 168 169 static void uh_header_error(struct client *cl, int code, const char *summary) 170 { 171 uh_client_error(cl, code, summary, NULL); 172 uh_connection_close(cl); 173 } 174 175 static int find_idx(const char * const *list, int max, const char *str) 176 { 177 int i; 178 179 for (i = 0; i < max; i++) 180 if (!strcmp(list[i], str)) 181 return i; 182 183 return -1; 184 } 185 186 /* 187 * Locate the first CRLF within the first len bytes of buf, or NULL if there 188 * is none. 189 * 190 * This must not be replaced by strstr(): the ustream read buffer is a fixed 191 * size allocation and whatever an earlier read left behind past its tail is 192 * still in memory. Depending on the expected NUL terminator is not good 193 * enough either - a match beyond the valid data would let the parser write a 194 * NUL byte there and hand a length larger than the buffered data to 195 * ustream_consume(), which aborts() the whole server. 196 */ 197 static char *find_crlf(char *buf, int len) 198 { 199 char *p, *end = buf + len; 200 201 if (len < 2) 202 return NULL; 203 204 for (p = memchr(buf + 1, '\n', len - 1); p; p = memchr(p + 1, '\n', end - p - 1)) 205 if (p[-1] == '\r') 206 return p - 1; 207 208 return NULL; 209 } 210 211 static int client_parse_request(struct client *cl, char *data) 212 { 213 struct http_request *req = &cl->request; 214 char *type, *path, *version; 215 int h_method, h_version; 216 217 type = strtok(data, " "); 218 path = strtok(NULL, " "); 219 version = strtok(NULL, " "); 220 if (!type || !path || !version) 221 return CLIENT_STATE_DONE; 222 223 blobmsg_add_string(&cl->hdr, "URL", path); 224 225 memset(&cl->request, 0, sizeof(cl->request)); 226 h_method = find_idx(http_methods, ARRAY_SIZE(http_methods), type); 227 h_version = find_idx(http_versions, ARRAY_SIZE(http_versions), version); 228 if (h_method < 0 || h_version < 0) { 229 req->version = UH_HTTP_VER_1_0; 230 return CLIENT_STATE_DONE; 231 } 232 233 req->method = h_method; 234 req->version = h_version; 235 if (req->version < UH_HTTP_VER_1_1 || !conf.http_keepalive) 236 req->connection_close = true; 237 238 return CLIENT_STATE_HEADER; 239 } 240 241 static bool client_init_cb(struct client *cl, char *buf, int len) 242 { 243 char *newline; 244 245 newline = find_crlf(buf, len); 246 if (!newline) 247 return false; 248 249 if (newline == buf) { 250 ustream_consume(cl->us, 2); 251 return true; 252 } 253 254 *newline = 0; 255 blob_buf_init(&cl->hdr, 0); 256 cl->state = client_parse_request(cl, buf); 257 ustream_consume(cl->us, newline + 2 - buf); 258 if (cl->state == CLIENT_STATE_DONE) 259 uh_header_error(cl, 400, "Bad Request"); 260 261 return true; 262 } 263 264 static bool request_header_check(struct client *cl) 265 { 266 size_t num_transfer_encoding = 0; 267 size_t num_content_length = 0; 268 struct blob_attr *cur; 269 int rem; 270 271 blob_for_each_attr(cur, cl->hdr.head, rem) { 272 if (!strcasecmp(blobmsg_name(cur), "Transfer-Encoding")) 273 num_transfer_encoding++; 274 else if (!strcasecmp(blobmsg_name(cur), "Content-Length")) 275 num_content_length++; 276 } 277 278 /* Section 3.3.2 of RFC 7230: messages with multiple Content-Length headers 279 containing different values MUST be rejected as invalid. Messages with 280 multiple Content-Length headers containing identical values MAY be 281 rejected as invalid */ 282 if (num_content_length > 1) { 283 uh_header_error(cl, 400, "Bad Request"); 284 return false; 285 } 286 287 /* Section 3.3.3 of RFC 7230: messages with both Content-Length and 288 Transfer-Encoding ought to be handled as an error */ 289 if (num_content_length > 0 && num_transfer_encoding > 0) { 290 uh_header_error(cl, 400, "Bad Request"); 291 return false; 292 } 293 294 return true; 295 } 296 297 static bool rfc1918_filter_check(struct client *cl) 298 { 299 if (!conf.rfc1918_filter) 300 return true; 301 302 if (!uh_addr_rfc1918(&cl->peer_addr) || uh_addr_rfc1918(&cl->srv_addr)) 303 return true; 304 305 uh_client_error(cl, 403, "Forbidden", 306 "Rejected request from RFC1918 IP " 307 "to public server address"); 308 return false; 309 } 310 311 static bool tls_redirect_check(struct client *cl) 312 { 313 int rem, port; 314 struct blob_attr *cur; 315 char *ptr, *url = NULL, *host = NULL; 316 317 if (cl->tls || !conf.tls_redirect) 318 return true; 319 320 if ((port = uh_first_tls_port(cl->srv_addr.family)) == -1) 321 return true; 322 323 blob_for_each_attr(cur, cl->hdr.head, rem) { 324 if (!strcmp(blobmsg_name(cur), "host")) 325 host = blobmsg_get_string(cur); 326 327 if (!strcmp(blobmsg_name(cur), "URL")) 328 url = blobmsg_get_string(cur); 329 330 if (url && host) 331 break; 332 } 333 334 if (!url || !host) 335 return true; 336 337 if ((ptr = strchr(host, ']')) != NULL) 338 *(ptr+1) = 0; 339 else if ((ptr = strchr(host, ':')) != NULL) 340 *ptr = 0; 341 342 cl->request.disable_chunked = true; 343 cl->request.connection_close = true; 344 345 uh_http_header(cl, 307, "Temporary Redirect"); 346 347 if (port != 443) 348 ustream_printf(cl->us, "Location: https://%s:%d%s\r\n\r\n", host, port, url); 349 else 350 ustream_printf(cl->us, "Location: https://%s%s\r\n\r\n", host, url); 351 352 uh_request_done(cl); 353 354 return false; 355 } 356 357 #ifdef HAVE_TLS 358 static bool sni_redirect_check(struct client *cl) 359 { 360 struct sni_redirect *r; 361 362 if (!cl->tls || !cl->ssl.server_name) 363 return true; 364 365 list_for_each_entry(r, &conf.sni_redirect, list) { 366 if (!strcmp(cl->ssl.server_name, r->host)) { 367 cl->request.disable_chunked = true; 368 cl->request.connection_close = true; 369 370 uh_http_header(cl, 301, "Moved Permanently"); 371 ustream_printf(cl->us, "Location: %s\r\n\r\n", r->url); 372 uh_request_done(cl); 373 374 return false; 375 } 376 } 377 378 return true; 379 } 380 #else 381 static bool sni_redirect_check(struct client *cl) 382 { 383 return true; 384 } 385 #endif 386 387 static void client_header_complete(struct client *cl) 388 { 389 struct http_request *r = &cl->request; 390 391 if (!request_header_check(cl)) 392 return; 393 394 if (!rfc1918_filter_check(cl)) 395 return; 396 397 if (!tls_redirect_check(cl)) 398 return; 399 400 if (!sni_redirect_check(cl)) 401 return; 402 403 if (r->expect_cont) 404 ustream_printf(cl->us, "HTTP/1.1 100 Continue\r\n\r\n"); 405 406 switch(r->ua) { 407 case UH_UA_MSIE_OLD: 408 if (r->method != UH_HTTP_MSG_POST) 409 break; 410 411 /* fall through */ 412 case UH_UA_SAFARI: 413 r->connection_close = true; 414 break; 415 default: 416 break; 417 } 418 419 uh_handle_request(cl); 420 } 421 422 static long 423 parse_chunksize(char *buf, char *end) 424 { 425 int size = 0; 426 char *p; 427 428 for (p = buf; p < end; p++) { 429 int n; 430 431 if (uh_is_digit(*p)) 432 n = *p - ''; 433 else if (uh_is_hexdig(*p)) 434 n = 10 + (*p | 32) - 'a'; 435 else 436 break; 437 438 if (size > INT_MAX / 16) 439 return -1; /* overflow */ 440 441 size *= 16; 442 443 if (size > INT_MAX - n) 444 return -1; /* overflow */ 445 446 size += n; 447 } 448 449 if (p == buf) 450 return -1; /* empty size */ 451 452 /* 453 * Skip optional chunk extensions. RFC 9112 7.1.1 defines 454 * 455 * chunk-ext = *( BWS chunk-ext-name [ BWS "=" BWS chunk-ext-val ] ) 456 * chunk-ext-name = token 457 * chunk-ext-val = token / quoted-string 458 * 459 * The extensions mean nothing to us, but they have to be skipped 460 * correctly: treating a size line carrying one as malformed would stop 461 * parsing the body of an ordinary, valid request. 462 */ 463 while (p < end) { 464 while (p < end && uh_is_wsp(*p)) 465 p++; 466 467 if (p >= end) 468 break; 469 470 if (*p != ';') 471 return -1; /* garbage after size and/or extensions */ 472 473 p++; 474 475 if (p >= end || !uh_is_tchar(*p)) 476 return -1; /* empty chunk-ext-name */ 477 478 while (p < end && uh_is_tchar(*p)) 479 p++; 480 481 while (p < end && uh_is_wsp(*p)) 482 p++; 483 484 if (p >= end || *p != '=') 485 continue; 486 487 p++; 488 489 while (p < end && uh_is_wsp(*p)) 490 p++; 491 492 if (p < end && *p == '"') { 493 /* quoted-string = DQUOTE *( qdtext / quoted-pair ) DQUOTE */ 494 bool closed = false; 495 496 for (p++; p < end; p++) { 497 if (*p == '"') { 498 p++; 499 closed = true; 500 break; 501 } 502 503 if (*p == '\\') { 504 p++; 505 506 if (p >= end) 507 break; /* quoted-pair at the end of the line */ 508 509 continue; 510 } 511 512 /* qdtext: HTAB / SP / VCHAR, DQUOTE handled above */ 513 if (!(chartypes[(uint8_t)*p] & (CT_VCHAR | CT_WSP))) 514 return -1; 515 } 516 517 if (!closed) 518 return -1; /* unterminated quoted-string */ 519 } else { 520 if (p >= end || !uh_is_tchar(*p)) 521 return -1; /* empty chunk-ext-val */ 522 523 while (p < end && uh_is_tchar(*p)) 524 p++; 525 } 526 } 527 528 return size; 529 } 530 531 static void client_parse_header(struct client *cl, char *data, size_t line_len) 532 { 533 struct http_request *r = &cl->request; 534 char *err; 535 char *name; 536 char *val; 537 char *p; 538 539 if (!*data) { 540 uloop_timeout_cancel(&cl->timeout); 541 cl->state = CLIENT_STATE_DATA; 542 client_header_complete(cl); 543 return; 544 } 545 546 /* Cap header count and cumulative header bytes so a connection 547 * cannot pin an unbounded amount of memory in cl->hdr; line_len 548 * includes the CRLF stripped from the line by the caller. 549 */ 550 r->header_count++; 551 r->header_bytes += line_len; 552 if (r->header_count > UH_LIMIT_HEADER_COUNT || 553 r->header_bytes > UH_LIMIT_HEADER_BYTES) { 554 uh_header_error(cl, 431, "Request Header Fields Too Large"); 555 return; 556 } 557 558 val = uh_split_header(data, line_len - 2); 559 if (!val) { 560 cl->state = CLIENT_STATE_DONE; 561 return; 562 } 563 564 /* RFC 9110: header field names must be non-empty tokens of 565 * TCHAR characters, which already excludes whitespace (SP/HTAB 566 * carry no VCHAR bit and so fail uh_is_tchar()) and the colon 567 * must immediately follow the name. Reject malformed header 568 * lines to prevent request smuggling via reverse proxies that 569 * may interpret them differently. */ 570 if (!*data) { 571 uh_header_error(cl, 400, "Bad Request"); 572 return; 573 } 574 575 for (name = data; *name; name++) { 576 if (!uh_is_tchar(*name)) { 577 uh_header_error(cl, 400, "Bad Request"); 578 return; 579 } 580 if (*name >= 'A' && *name <= 'Z') 581 *name += 'a' - 'A'; 582 } 583 584 /* RFC 9110 field-content only permits VCHAR/obs-text plus SP and 585 * HTAB; reject embedded control characters (e.g. a bare CR or LF 586 * not part of the line terminator) so a value cannot be used to 587 * smuggle an extra header/request past this parser into one that 588 * treats a lone CR or LF as a line break. */ 589 for (p = val; *p; p++) { 590 if (uh_is_ctl(*p)) { 591 uh_header_error(cl, 400, "Bad Request"); 592 return; 593 } 594 } 595 596 if (!strcmp(data, "expect")) { 597 if (!strcasecmp(val, "100-continue")) 598 r->expect_cont = true; 599 else { 600 uh_header_error(cl, 412, "Precondition Failed"); 601 return; 602 } 603 } else if (!strcmp(data, "content-length")) { 604 long length; 605 606 errno = 0; 607 length = strtol(val, &err, 10); 608 if ((err && *err) || errno || length < 0 || length > INT_MAX) { 609 uh_header_error(cl, 400, "Bad Request"); 610 return; 611 } 612 r->content_length = (int)length; 613 } else if (!strcmp(data, "transfer-encoding")) { 614 /* RFC 9112 6.1: transfer-coding tokens are case-insensitive. 615 * Reject any coding we do not implement instead of silently 616 * ignoring it, otherwise the body framing would be unknown and 617 * the unread body could be parsed as the next request. */ 618 if (!strcasecmp(val, "chunked")) { 619 r->transfer_chunked = CHUNKED_FIRST; 620 } else { 621 uh_header_error(cl, 501, "Not Implemented"); 622 return; 623 } 624 } else if (!strcmp(data, "connection")) { 625 if (!strcasecmp(val, "close")) 626 r->connection_close = true; 627 } else if (!strcmp(data, "user-agent")) { 628 char *str; 629 630 if (strstr(val, "Opera")) 631 r->ua = UH_UA_OPERA; 632 else if ((str = strstr(val, "MSIE ")) != NULL) { 633 r->ua = UH_UA_MSIE_NEW; 634 if (str[5] && str[6] == '.') { 635 switch (str[5]) { 636 case '6': 637 if (strstr(str, "SV1")) 638 break; 639 /* fall through */ 640 case '5': 641 case '4': 642 r->ua = UH_UA_MSIE_OLD; 643 break; 644 } 645 } 646 } 647 else if (strstr(val, "Chrome/")) 648 r->ua = UH_UA_CHROME; 649 else if (strstr(val, "Safari/") && strstr(val, "Mac OS X")) 650 r->ua = UH_UA_SAFARI; 651 else if (strstr(val, "Gecko/")) 652 r->ua = UH_UA_GECKO; 653 else if (strstr(val, "Konqueror")) 654 r->ua = UH_UA_KONQUEROR; 655 } 656 657 658 blobmsg_add_string(&cl->hdr, data, val); 659 660 cl->state = CLIENT_STATE_HEADER; 661 } 662 663 void client_poll_post_data(struct client *cl) 664 { 665 struct dispatch *d = &cl->dispatch; 666 struct http_request *r = &cl->request; 667 enum client_state st; 668 char *buf; 669 int len; 670 671 if (cl->state == CLIENT_STATE_DONE) 672 return; 673 674 while (1) { 675 char *sep; 676 long chunk_len; 677 int offset = 0; 678 int cur_len; 679 680 buf = ustream_get_read_buf(cl->us, &len); 681 if (!buf || !len) 682 break; 683 684 if (!d->data_send) 685 return; 686 687 cur_len = min(r->content_length, len); 688 if (cur_len) { 689 if (d->data_blocked) 690 break; 691 692 if (d->data_send) 693 cur_len = d->data_send(cl, buf, cur_len); 694 695 r->content_length -= cur_len; 696 ustream_consume(cl->us, cur_len); 697 continue; 698 } 699 700 if (!r->transfer_chunked) 701 break; 702 703 if (r->transfer_chunked == CHUNKED_TRAILER) { 704 char *tsep = find_crlf(buf, len); 705 706 if (!tsep) 707 break; 708 709 if (tsep == buf) { 710 /* blank line: end of the (possibly empty) trailer 711 * section, request framing is now complete */ 712 ustream_consume(cl->us, 2); 713 r->transfer_chunked = CHUNKED_OFF; 714 break; 715 } 716 717 r->header_count++; 718 r->header_bytes += tsep + 2 - buf; 719 ustream_consume(cl->us, tsep + 2 - buf); 720 721 if (r->header_count > UH_LIMIT_HEADER_COUNT || 722 r->header_bytes > UH_LIMIT_HEADER_BYTES) { 723 /* Too much trailer data; the framing beyond this 724 * point is unknown, so the connection cannot be 725 * safely reused for a subsequent request. */ 726 r->transfer_chunked = CHUNKED_OFF; 727 r->connection_close = true; 728 break; 729 } 730 731 continue; 732 } 733 734 if (r->transfer_chunked == CHUNKED_NEXT) { 735 /* The CRLF terminating the data of the previous chunk must 736 * actually be buffered: skipping two bytes that are not 737 * there yet makes the search below start beyond the valid 738 * data of the read buffer. */ 739 if (len < 2) 740 break; 741 742 /* the chunk data must be followed by a literal CRLF; 743 * anything else means the framing is ambiguous, so 744 * bail out and close the connection instead of 745 * silently resyncing on unrelated bytes */ 746 if (buf[0] != '\r' || buf[1] != '\n') { 747 r->content_length = 0; 748 r->transfer_chunked = CHUNKED_OFF; 749 r->connection_close = true; 750 break; 751 } 752 753 offset = 2; 754 } 755 756 /* a chunk size line is at least one digit plus its CRLF; wait 757 * for the rest of it instead of searching into buffer bytes 758 * that hold no request data */ 759 if (len < offset + 3) 760 break; 761 762 sep = find_crlf(buf + offset, len - offset); 763 if (!sep) 764 break; 765 766 chunk_len = parse_chunksize(buf + offset, sep); 767 768 /* invalid chunk length, including an empty chunk size line, 769 * leading/trailing garbage or an overflowing value; see 770 * parse_chunksize() */ 771 if (chunk_len < 0) { 772 ustream_consume(cl->us, sep + 2 - buf); 773 r->content_length = 0; 774 r->transfer_chunked = CHUNKED_OFF; 775 /* The remaining buffered body is left unconsumed and its 776 * framing is now unknown. Close the connection so the 777 * leftover bytes are not reparsed as the next request 778 * (request smuggling). */ 779 r->connection_close = true; 780 break; 781 } 782 783 if (r->transfer_chunked == CHUNKED_FIRST) 784 r->transfer_chunked = CHUNKED_NEXT; 785 ustream_consume(cl->us, sep + 2 - buf); 786 r->content_length = (int)chunk_len; 787 788 /* empty chunk == eof, but RFC 9112 7.1.3 still permits an 789 * optional trailer section before the request is fully 790 * framed; drain it instead of leaving it for the next 791 * read_cbs state to misparse as a new request. */ 792 if (!r->content_length) { 793 r->transfer_chunked = CHUNKED_TRAILER; 794 continue; 795 } 796 } 797 798 buf = ustream_get_read_buf(cl->us, &len); 799 if (!r->content_length && !r->transfer_chunked && 800 cl->state != CLIENT_STATE_DONE) { 801 st = cl->state; 802 803 if (cl->dispatch.data_done) 804 cl->dispatch.data_done(cl); 805 806 if (cl->state == st) 807 cl->state = CLIENT_STATE_DONE; 808 } 809 } 810 811 static bool client_data_cb(struct client *cl, char *buf, int len) 812 { 813 client_poll_post_data(cl); 814 return false; 815 } 816 817 static bool client_header_cb(struct client *cl, char *buf, int len) 818 { 819 char *newline; 820 int line_len; 821 822 newline = find_crlf(buf, len); 823 if (!newline) 824 return false; 825 826 line_len = newline + 2 - buf; 827 *newline = 0; 828 client_parse_header(cl, buf, line_len); 829 ustream_consume(cl->us, line_len); 830 if (cl->state == CLIENT_STATE_DATA) 831 return client_data_cb(cl, newline + 2, len - line_len); 832 833 return true; 834 } 835 836 typedef bool (*read_cb_t)(struct client *cl, char *buf, int len); 837 static read_cb_t read_cbs[] = { 838 [CLIENT_STATE_INIT] = client_init_cb, 839 [CLIENT_STATE_HEADER] = client_header_cb, 840 [CLIENT_STATE_DATA] = client_data_cb, 841 }; 842 843 void uh_client_read_cb(struct client *cl) 844 { 845 struct ustream *us = cl->us; 846 char *str; 847 int len; 848 849 client_done = false; 850 do { 851 str = ustream_get_read_buf(us, &len); 852 if (!str || !len) 853 break; 854 855 if (cl->state >= array_size(read_cbs) || !read_cbs[cl->state]) 856 break; 857 858 if (!read_cbs[cl->state](cl, str, len)) { 859 if (len == us->r.buffer_len && 860 cl->state != CLIENT_STATE_DATA && 861 cl->state != CLIENT_STATE_DONE) 862 uh_header_error(cl, 413, "Request Entity Too Large"); 863 break; 864 } 865 } while (!client_done); 866 } 867 868 static void client_close(struct client *cl) 869 { 870 if (cl->refcount) { 871 cl->state = CLIENT_STATE_CLEANUP; 872 return; 873 } 874 875 client_done = true; 876 n_clients--; 877 uh_dispatch_done(cl); 878 uloop_timeout_cancel(&cl->timeout); 879 if (cl->tls) 880 uh_tls_client_detach(cl); 881 ustream_free(&cl->sfd.stream); 882 close(cl->sfd.fd.fd); 883 list_del(&cl->list); 884 blob_buf_free(&cl->hdr); 885 blob_buf_free(&cl->hdr_response); 886 free(cl); 887 888 uh_unblock_listeners(); 889 } 890 891 /* 892 * Returns true when the full request body has been received, i.e. it is 893 * safe to keep the connection alive after the peer has closed its write 894 * direction. This distinguishes a legitimate half-close (the client sent 895 * the entire body and now waits for the response) from a connection that 896 * was abandoned while the body was still outstanding (the remaining bytes 897 * will never arrive). 898 * 899 * request.content_length holds the number of body bytes not yet handed to 900 * the script (it is decremented as each byte is consumed, and set to each 901 * chunk's size for chunked bodies); ustream r.data_bytes holds the total 902 * body bytes buffered but not yet consumed. The body is complete when 903 * everything still expected has already been received - either consumed or 904 * still sitting in the read buffer. 905 * 906 * A chunked body is only parsed as fast as the script consumes it, so a 907 * complete body may still sit unparsed in the read buffer, e.g. while the 908 * request is deferred or the script stopped reading. Walk the buffered 909 * bytes from the current parser position, without consuming anything, and 910 * report completeness once the terminal chunk and the end of the trailer 911 * section are buffered. The read stream is a single, compacted buffer and 912 * the peer's EOF is only seen after everything it sent has been read into 913 * it, so the head fragment covers all of the remaining body. 914 */ 915 static bool uh_chunked_body_complete(struct client *cl) 916 { 917 struct http_request *r = &cl->request; 918 enum chunked_state state = r->transfer_chunked; 919 long remaining = r->content_length; 920 char *buf, *sep; 921 int len; 922 923 buf = ustream_get_read_buf(cl->us, &len); 924 if (!buf) 925 len = 0; 926 927 while (1) { 928 if (state == CHUNKED_TRAILER) { 929 sep = find_crlf(buf, len); 930 if (!sep) 931 return false; 932 933 if (sep == buf) 934 return true; /* blank line ends the trailer section */ 935 936 len -= sep + 2 - buf; 937 buf = sep + 2; 938 continue; 939 } 940 941 /* outstanding data of the current chunk */ 942 if (remaining > len) 943 return false; 944 945 buf += remaining; 946 len -= remaining; 947 948 /* CRLF terminating the data of the previous chunk; malformed 949 * framing fails the request anyway, so do not keep it alive */ 950 if (state == CHUNKED_NEXT) { 951 if (len < 2 || buf[0] != '\r' || buf[1] != '\n') 952 return false; 953 954 buf += 2; 955 len -= 2; 956 } 957 958 sep = find_crlf(buf, len); 959 if (!sep) 960 return false; 961 962 remaining = parse_chunksize(buf, sep); 963 if (remaining < 0) 964 return false; 965 966 len -= sep + 2 - buf; 967 buf = sep + 2; 968 state = remaining ? CHUNKED_NEXT : CHUNKED_TRAILER; 969 } 970 } 971 972 static bool uh_client_body_complete(struct client *cl) 973 { 974 struct http_request *r = &cl->request; 975 struct ustream *s = cl->us; 976 977 if (r->transfer_chunked) 978 return uh_chunked_body_complete(cl); 979 980 return r->content_length <= (int)s->r.data_bytes; 981 } 982 983 void uh_client_notify_state(struct client *cl) 984 { 985 struct ustream *s = cl->us; 986 987 if (!s->write_error && cl->state != CLIENT_STATE_CLEANUP) { 988 /* 989 * A peer that closed while the request body was still 990 * outstanding (e.g. headers announcing a Content-Length with 991 * the body never sent) will never deliver the remaining bytes. 992 * The script slot and the connection would otherwise be pinned 993 * until script_timeout expires, so release them here. Only keep 994 * the connection when the full body has actually been received. 995 */ 996 if (cl->state == CLIENT_STATE_DATA && 997 uh_client_body_complete(cl)) 998 return; 999 1000 if (!s->eof || s->w.data_bytes) 1001 return; 1002 1003 #ifdef HAVE_TLS 1004 if (cl->tls && cl->ssl.conn && cl->ssl.conn->w.data_bytes) { 1005 cl->ssl.conn->eof = s->eof; 1006 if (!ustream_write_pending(cl->ssl.conn)) 1007 return; 1008 } 1009 #endif 1010 } 1011 1012 return client_close(cl); 1013 } 1014 1015 static void client_ustream_read_cb(struct ustream *s, int bytes) 1016 { 1017 struct client *cl = container_of(s, struct client, sfd.stream); 1018 1019 uh_client_read_cb(cl); 1020 } 1021 1022 static void client_ustream_write_cb(struct ustream *s, int bytes) 1023 { 1024 struct client *cl = container_of(s, struct client, sfd.stream); 1025 1026 if (cl->dispatch.write_cb) 1027 cl->dispatch.write_cb(cl); 1028 } 1029 1030 static void client_notify_state(struct ustream *s) 1031 { 1032 struct client *cl = container_of(s, struct client, sfd.stream); 1033 1034 uh_client_notify_state(cl); 1035 } 1036 1037 static void set_addr(struct uh_addr *addr, void *src) 1038 { 1039 struct sockaddr_in *sin = src; 1040 struct sockaddr_in6 *sin6 = src; 1041 1042 addr->family = sin->sin_family; 1043 if (addr->family == AF_INET) { 1044 addr->port = ntohs(sin->sin_port); 1045 memcpy(&addr->in, &sin->sin_addr, sizeof(addr->in)); 1046 } else { 1047 addr->port = ntohs(sin6->sin6_port); 1048 memcpy(&addr->in6, &sin6->sin6_addr, sizeof(addr->in6)); 1049 } 1050 } 1051 1052 bool uh_accept_client(int fd, bool tls) 1053 { 1054 static struct client *next_client; 1055 struct client *cl; 1056 unsigned int sl; 1057 int yes = 1; 1058 int sfd; 1059 static int client_id = 0; 1060 struct sockaddr_in6 addr; 1061 1062 if (!next_client) 1063 next_client = calloc(1, sizeof(*next_client)); 1064 1065 cl = next_client; 1066 1067 sl = sizeof(addr); 1068 sfd = accept(fd, (struct sockaddr *) &addr, &sl); 1069 if (sfd < 0) 1070 return false; 1071 1072 /* A response is emitted as one write() per header line plus one for the 1073 * body, so with Nagle enabled the small final segment of a response on a 1074 * REUSED keep-alive connection is held back until the peer acknowledges 1075 * the previous one - which its delayed ACK timer puts ~40 ms away. Every 1076 * request after the first on a connection pays that. */ 1077 setsockopt(sfd, IPPROTO_TCP, TCP_NODELAY, &yes, sizeof(yes)); 1078 1079 set_addr(&cl->peer_addr, &addr); 1080 sl = sizeof(addr); 1081 getsockname(sfd, (struct sockaddr *) &addr, &sl); 1082 set_addr(&cl->srv_addr, &addr); 1083 1084 cl->us = &cl->sfd.stream; 1085 if (tls) { 1086 uh_tls_client_attach(cl); 1087 } else { 1088 cl->us->notify_read = client_ustream_read_cb; 1089 cl->us->notify_write = client_ustream_write_cb; 1090 cl->us->notify_state = client_notify_state; 1091 } 1092 1093 cl->us->string_data = true; 1094 ustream_fd_init(&cl->sfd, sfd); 1095 1096 uh_poll_connection(cl); 1097 list_add_tail(&cl->list, &clients); 1098 1099 next_client = NULL; 1100 n_clients++; 1101 cl->id = client_id++; 1102 cl->tls = tls; 1103 1104 return true; 1105 } 1106 1107 /* 1108 * Number of script slots currently held by clients sharing the given peer 1109 * address. A single connection holds at most one slot (cl->script), so this 1110 * caps how many concurrent script slots one source can take out of the global 1111 * max_script_requests pool - see uh_invoke_handler(). 1112 */ 1113 int uh_source_script_count(const struct uh_addr *addr) 1114 { 1115 struct client *cl; 1116 int n = 0; 1117 1118 list_for_each_entry(cl, &clients, list) { 1119 if (!cl->script) 1120 continue; 1121 if (cl->peer_addr.family != addr->family) 1122 continue; 1123 if (cl->peer_addr.family == AF_INET && 1124 memcmp(&cl->peer_addr.in, &addr->in, sizeof(addr->in))) 1125 continue; 1126 if (cl->peer_addr.family == AF_INET6 && 1127 memcmp(&cl->peer_addr.in6, &addr->in6, sizeof(addr->in6))) 1128 continue; 1129 n++; 1130 } 1131 1132 return n; 1133 } 1134 1135 void uh_close_fds(void) 1136 { 1137 struct client *cl; 1138 1139 uloop_done(); 1140 uh_close_listen_fds(); 1141 list_for_each_entry(cl, &clients, list) { 1142 close(cl->sfd.fd.fd); 1143 if (cl->dispatch.close_fds) 1144 cl->dispatch.close_fds(cl); 1145 } 1146 } 1147
This page was automatically generated by LXR 0.3.1. • OpenWrt