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 <ctype.h> 22 #include <errno.h> 23 #include <limits.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 uh_chunk_eof(cl); 128 uh_dispatch_done(cl); 129 blob_buf_init(&cl->hdr_response, 0); 130 memset(&cl->dispatch, 0, sizeof(cl->dispatch)); 131 132 if (!conf.http_keepalive || cl->request.connection_close) 133 return uh_connection_close(cl); 134 135 cl->state = CLIENT_STATE_INIT; 136 cl->requests++; 137 uh_poll_connection(cl); 138 } 139 140 void __printf(4, 5) 141 uh_client_error(struct client *cl, int code, const char *summary, const char *fmt, ...) 142 { 143 struct http_request *r = &cl->request; 144 va_list arg; 145 146 uh_http_header(cl, code, summary); 147 ustream_printf(cl->us, "Content-Type: text/html\r\n\r\n"); 148 149 uh_chunk_printf(cl, "<h1>%s</h1>", summary); 150 151 if (fmt) { 152 va_start(arg, fmt); 153 uh_chunk_vprintf(cl, fmt, arg); 154 va_end(arg); 155 } 156 157 /* Close the connection even when keep alive is set, when it 158 * contains a request body, as it was not read and we are 159 * currently out of sync. Without handling this the body will be 160 * interpreted as part of the next request. The alternative 161 * would be to read and discard the request body here. 162 */ 163 if (r->transfer_chunked || r->content_length > 0) 164 cl->request.connection_close = true; 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 static int client_parse_request(struct client *cl, char *data) 187 { 188 struct http_request *req = &cl->request; 189 char *type, *path, *version; 190 int h_method, h_version; 191 192 type = strtok(data, " "); 193 path = strtok(NULL, " "); 194 version = strtok(NULL, " "); 195 if (!type || !path || !version) 196 return CLIENT_STATE_DONE; 197 198 blobmsg_add_string(&cl->hdr, "URL", path); 199 200 memset(&cl->request, 0, sizeof(cl->request)); 201 h_method = find_idx(http_methods, ARRAY_SIZE(http_methods), type); 202 h_version = find_idx(http_versions, ARRAY_SIZE(http_versions), version); 203 if (h_method < 0 || h_version < 0) { 204 req->version = UH_HTTP_VER_1_0; 205 return CLIENT_STATE_DONE; 206 } 207 208 req->method = h_method; 209 req->version = h_version; 210 if (req->version < UH_HTTP_VER_1_1 || !conf.http_keepalive) 211 req->connection_close = true; 212 213 return CLIENT_STATE_HEADER; 214 } 215 216 static bool client_init_cb(struct client *cl, char *buf, int len) 217 { 218 char *newline; 219 220 newline = strstr(buf, "\r\n"); 221 if (!newline) 222 return false; 223 224 if (newline == buf) { 225 ustream_consume(cl->us, 2); 226 return true; 227 } 228 229 *newline = 0; 230 blob_buf_init(&cl->hdr, 0); 231 cl->state = client_parse_request(cl, buf); 232 ustream_consume(cl->us, newline + 2 - buf); 233 if (cl->state == CLIENT_STATE_DONE) 234 uh_header_error(cl, 400, "Bad Request"); 235 236 return true; 237 } 238 239 static bool request_header_check(struct client *cl) 240 { 241 size_t num_transfer_encoding = 0; 242 size_t num_content_length = 0; 243 struct blob_attr *cur; 244 int rem; 245 246 blob_for_each_attr(cur, cl->hdr.head, rem) { 247 if (!strcasecmp(blobmsg_name(cur), "Transfer-Encoding")) 248 num_transfer_encoding++; 249 else if (!strcasecmp(blobmsg_name(cur), "Content-Length")) 250 num_content_length++; 251 } 252 253 /* Section 3.3.2 of RFC 7230: messages with multiple Content-Length headers 254 containing different values MUST be rejected as invalid. Messages with 255 multiple Content-Length headers containing identical values MAY be 256 rejected as invalid */ 257 if (num_content_length > 1) { 258 uh_header_error(cl, 400, "Bad Request"); 259 return false; 260 } 261 262 /* Section 3.3.3 of RFC 7230: messages with both Content-Length and 263 Transfer-Encoding ought to be handled as an error */ 264 if (num_content_length > 0 && num_transfer_encoding > 0) { 265 uh_header_error(cl, 400, "Bad Request"); 266 return false; 267 } 268 269 return true; 270 } 271 272 static bool rfc1918_filter_check(struct client *cl) 273 { 274 if (!conf.rfc1918_filter) 275 return true; 276 277 if (!uh_addr_rfc1918(&cl->peer_addr) || uh_addr_rfc1918(&cl->srv_addr)) 278 return true; 279 280 uh_client_error(cl, 403, "Forbidden", 281 "Rejected request from RFC1918 IP " 282 "to public server address"); 283 return false; 284 } 285 286 static bool tls_redirect_check(struct client *cl) 287 { 288 int rem, port; 289 struct blob_attr *cur; 290 char *ptr, *url = NULL, *host = NULL; 291 292 if (cl->tls || !conf.tls_redirect) 293 return true; 294 295 if ((port = uh_first_tls_port(cl->srv_addr.family)) == -1) 296 return true; 297 298 blob_for_each_attr(cur, cl->hdr.head, rem) { 299 if (!strcmp(blobmsg_name(cur), "host")) 300 host = blobmsg_get_string(cur); 301 302 if (!strcmp(blobmsg_name(cur), "URL")) 303 url = blobmsg_get_string(cur); 304 305 if (url && host) 306 break; 307 } 308 309 if (!url || !host) 310 return true; 311 312 if ((ptr = strchr(host, ']')) != NULL) 313 *(ptr+1) = 0; 314 else if ((ptr = strchr(host, ':')) != NULL) 315 *ptr = 0; 316 317 cl->request.disable_chunked = true; 318 cl->request.connection_close = true; 319 320 uh_http_header(cl, 307, "Temporary Redirect"); 321 322 if (port != 443) 323 ustream_printf(cl->us, "Location: https://%s:%d%s\r\n\r\n", host, port, url); 324 else 325 ustream_printf(cl->us, "Location: https://%s%s\r\n\r\n", host, url); 326 327 uh_request_done(cl); 328 329 return false; 330 } 331 332 static void client_header_complete(struct client *cl) 333 { 334 struct http_request *r = &cl->request; 335 336 if (!request_header_check(cl)) 337 return; 338 339 if (!rfc1918_filter_check(cl)) 340 return; 341 342 if (!tls_redirect_check(cl)) 343 return; 344 345 if (r->expect_cont) 346 ustream_printf(cl->us, "HTTP/1.1 100 Continue\r\n\r\n"); 347 348 switch(r->ua) { 349 case UH_UA_MSIE_OLD: 350 if (r->method != UH_HTTP_MSG_POST) 351 break; 352 353 /* fall through */ 354 case UH_UA_SAFARI: 355 r->connection_close = true; 356 break; 357 default: 358 break; 359 } 360 361 uh_handle_request(cl); 362 } 363 364 static void client_parse_header(struct client *cl, char *data) 365 { 366 struct http_request *r = &cl->request; 367 char *err; 368 char *name; 369 char *val; 370 371 if (!*data) { 372 uloop_timeout_cancel(&cl->timeout); 373 cl->state = CLIENT_STATE_DATA; 374 client_header_complete(cl); 375 return; 376 } 377 378 val = uh_split_header(data); 379 if (!val) { 380 cl->state = CLIENT_STATE_DONE; 381 return; 382 } 383 384 for (name = data; *name; name++) 385 if (isupper((unsigned char)*name)) 386 *name = tolower((unsigned char)*name); 387 388 if (!strcmp(data, "expect")) { 389 if (!strcasecmp(val, "100-continue")) 390 r->expect_cont = true; 391 else { 392 uh_header_error(cl, 412, "Precondition Failed"); 393 return; 394 } 395 } else if (!strcmp(data, "content-length")) { 396 long length; 397 398 errno = 0; 399 length = strtol(val, &err, 10); 400 if ((err && *err) || errno || length < 0 || length > INT_MAX) { 401 uh_header_error(cl, 400, "Bad Request"); 402 return; 403 } 404 r->content_length = (int)length; 405 } else if (!strcmp(data, "transfer-encoding")) { 406 if (!strcmp(val, "chunked")) 407 r->transfer_chunked = true; 408 } else if (!strcmp(data, "connection")) { 409 if (!strcasecmp(val, "close")) 410 r->connection_close = true; 411 } else if (!strcmp(data, "user-agent")) { 412 char *str; 413 414 if (strstr(val, "Opera")) 415 r->ua = UH_UA_OPERA; 416 else if ((str = strstr(val, "MSIE ")) != NULL) { 417 r->ua = UH_UA_MSIE_NEW; 418 if (str[5] && str[6] == '.') { 419 switch (str[5]) { 420 case '6': 421 if (strstr(str, "SV1")) 422 break; 423 /* fall through */ 424 case '5': 425 case '4': 426 r->ua = UH_UA_MSIE_OLD; 427 break; 428 } 429 } 430 } 431 else if (strstr(val, "Chrome/")) 432 r->ua = UH_UA_CHROME; 433 else if (strstr(val, "Safari/") && strstr(val, "Mac OS X")) 434 r->ua = UH_UA_SAFARI; 435 else if (strstr(val, "Gecko/")) 436 r->ua = UH_UA_GECKO; 437 else if (strstr(val, "Konqueror")) 438 r->ua = UH_UA_KONQUEROR; 439 } 440 441 442 blobmsg_add_string(&cl->hdr, data, val); 443 444 cl->state = CLIENT_STATE_HEADER; 445 } 446 447 void client_poll_post_data(struct client *cl) 448 { 449 struct dispatch *d = &cl->dispatch; 450 struct http_request *r = &cl->request; 451 enum client_state st; 452 char *buf; 453 int len; 454 455 if (cl->state == CLIENT_STATE_DONE) 456 return; 457 458 while (1) { 459 char *sep; 460 long chunk_len; 461 int offset = 0; 462 int cur_len; 463 464 buf = ustream_get_read_buf(cl->us, &len); 465 if (!buf || !len) 466 break; 467 468 if (!d->data_send) 469 return; 470 471 cur_len = min(r->content_length, len); 472 if (cur_len) { 473 if (d->data_blocked) 474 break; 475 476 if (d->data_send) 477 cur_len = d->data_send(cl, buf, cur_len); 478 479 r->content_length -= cur_len; 480 ustream_consume(cl->us, cur_len); 481 continue; 482 } 483 484 if (!r->transfer_chunked) 485 break; 486 487 if (r->transfer_chunked > 1) 488 offset = 2; 489 490 sep = strstr(buf + offset, "\r\n"); 491 if (!sep) 492 break; 493 494 *sep = 0; 495 496 errno = 0; 497 chunk_len = strtol(buf + offset, &sep, 16); 498 499 /* invalid chunk length */ 500 if ((sep && *sep) || errno || chunk_len < 0 || chunk_len > INT_MAX) { 501 ustream_consume(cl->us, sep + 2 - buf); 502 r->content_length = 0; 503 r->transfer_chunked = 0; 504 break; 505 } 506 507 if (r->transfer_chunked < 2) 508 r->transfer_chunked++; 509 ustream_consume(cl->us, sep + 2 - buf); 510 r->content_length = (int)chunk_len; 511 512 /* empty chunk == eof */ 513 if (!r->content_length) { 514 r->transfer_chunked = false; 515 break; 516 } 517 } 518 519 buf = ustream_get_read_buf(cl->us, &len); 520 if (!r->content_length && !r->transfer_chunked && 521 cl->state != CLIENT_STATE_DONE) { 522 st = cl->state; 523 524 if (cl->dispatch.data_done) 525 cl->dispatch.data_done(cl); 526 527 if (cl->state == st) 528 cl->state = CLIENT_STATE_DONE; 529 } 530 } 531 532 static bool client_data_cb(struct client *cl, char *buf, int len) 533 { 534 client_poll_post_data(cl); 535 return false; 536 } 537 538 static bool client_header_cb(struct client *cl, char *buf, int len) 539 { 540 char *newline; 541 int line_len; 542 543 newline = strstr(buf, "\r\n"); 544 if (!newline) 545 return false; 546 547 *newline = 0; 548 client_parse_header(cl, buf); 549 line_len = newline + 2 - buf; 550 ustream_consume(cl->us, line_len); 551 if (cl->state == CLIENT_STATE_DATA) 552 return client_data_cb(cl, newline + 2, len - line_len); 553 554 return true; 555 } 556 557 typedef bool (*read_cb_t)(struct client *cl, char *buf, int len); 558 static read_cb_t read_cbs[] = { 559 [CLIENT_STATE_INIT] = client_init_cb, 560 [CLIENT_STATE_HEADER] = client_header_cb, 561 [CLIENT_STATE_DATA] = client_data_cb, 562 }; 563 564 void uh_client_read_cb(struct client *cl) 565 { 566 struct ustream *us = cl->us; 567 char *str; 568 int len; 569 570 client_done = false; 571 do { 572 str = ustream_get_read_buf(us, &len); 573 if (!str || !len) 574 break; 575 576 if (cl->state >= array_size(read_cbs) || !read_cbs[cl->state]) 577 break; 578 579 if (!read_cbs[cl->state](cl, str, len)) { 580 if (len == us->r.buffer_len && 581 cl->state != CLIENT_STATE_DATA && 582 cl->state != CLIENT_STATE_DONE) 583 uh_header_error(cl, 413, "Request Entity Too Large"); 584 break; 585 } 586 } while (!client_done); 587 } 588 589 static void client_close(struct client *cl) 590 { 591 if (cl->refcount) { 592 cl->state = CLIENT_STATE_CLEANUP; 593 return; 594 } 595 596 client_done = true; 597 n_clients--; 598 uh_dispatch_done(cl); 599 uloop_timeout_cancel(&cl->timeout); 600 if (cl->tls) 601 uh_tls_client_detach(cl); 602 ustream_free(&cl->sfd.stream); 603 close(cl->sfd.fd.fd); 604 list_del(&cl->list); 605 blob_buf_free(&cl->hdr); 606 blob_buf_free(&cl->hdr_response); 607 free(cl); 608 609 uh_unblock_listeners(); 610 } 611 612 void uh_client_notify_state(struct client *cl) 613 { 614 struct ustream *s = cl->us; 615 616 if (!s->write_error && cl->state != CLIENT_STATE_CLEANUP) { 617 if (cl->state == CLIENT_STATE_DATA) 618 return; 619 620 if (!s->eof || s->w.data_bytes) 621 return; 622 623 #ifdef HAVE_TLS 624 if (cl->tls && cl->ssl.conn && cl->ssl.conn->w.data_bytes) { 625 cl->ssl.conn->eof = s->eof; 626 if (!ustream_write_pending(cl->ssl.conn)) 627 return; 628 } 629 #endif 630 } 631 632 return client_close(cl); 633 } 634 635 static void client_ustream_read_cb(struct ustream *s, int bytes) 636 { 637 struct client *cl = container_of(s, struct client, sfd.stream); 638 639 uh_client_read_cb(cl); 640 } 641 642 static void client_ustream_write_cb(struct ustream *s, int bytes) 643 { 644 struct client *cl = container_of(s, struct client, sfd.stream); 645 646 if (cl->dispatch.write_cb) 647 cl->dispatch.write_cb(cl); 648 } 649 650 static void client_notify_state(struct ustream *s) 651 { 652 struct client *cl = container_of(s, struct client, sfd.stream); 653 654 uh_client_notify_state(cl); 655 } 656 657 static void set_addr(struct uh_addr *addr, void *src) 658 { 659 struct sockaddr_in *sin = src; 660 struct sockaddr_in6 *sin6 = src; 661 662 addr->family = sin->sin_family; 663 if (addr->family == AF_INET) { 664 addr->port = ntohs(sin->sin_port); 665 memcpy(&addr->in, &sin->sin_addr, sizeof(addr->in)); 666 } else { 667 addr->port = ntohs(sin6->sin6_port); 668 memcpy(&addr->in6, &sin6->sin6_addr, sizeof(addr->in6)); 669 } 670 } 671 672 bool uh_accept_client(int fd, bool tls) 673 { 674 static struct client *next_client; 675 struct client *cl; 676 unsigned int sl; 677 int sfd; 678 static int client_id = 0; 679 struct sockaddr_in6 addr; 680 681 if (!next_client) 682 next_client = calloc(1, sizeof(*next_client)); 683 684 cl = next_client; 685 686 sl = sizeof(addr); 687 sfd = accept(fd, (struct sockaddr *) &addr, &sl); 688 if (sfd < 0) 689 return false; 690 691 set_addr(&cl->peer_addr, &addr); 692 sl = sizeof(addr); 693 getsockname(sfd, (struct sockaddr *) &addr, &sl); 694 set_addr(&cl->srv_addr, &addr); 695 696 cl->us = &cl->sfd.stream; 697 if (tls) { 698 uh_tls_client_attach(cl); 699 } else { 700 cl->us->notify_read = client_ustream_read_cb; 701 cl->us->notify_write = client_ustream_write_cb; 702 cl->us->notify_state = client_notify_state; 703 } 704 705 cl->us->string_data = true; 706 ustream_fd_init(&cl->sfd, sfd); 707 708 uh_poll_connection(cl); 709 list_add_tail(&cl->list, &clients); 710 711 next_client = NULL; 712 n_clients++; 713 cl->id = client_id++; 714 cl->tls = tls; 715 716 return true; 717 } 718 719 void uh_close_fds(void) 720 { 721 struct client *cl; 722 723 uloop_done(); 724 uh_close_listen_fds(); 725 list_for_each_entry(cl, &clients, list) { 726 close(cl->sfd.fd.fd); 727 if (cl->dispatch.close_fds) 728 cl->dispatch.close_fds(cl); 729 } 730 } 731
This page was automatically generated by LXR 0.3.1. • OpenWrt