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