| package/uhttpd/src/uhttpd-file.c |
| 29 | 29 | static const char * uh_file_mime_lookup(const char *path) |
| 30 | 30 | { |
| 31 | 31 | struct mimetype *m = &uh_mime_types[0]; |
| 32 | | char *e; |
| 32 | const char *e; |
| 33 | 33 | |
| 34 | 34 | while( m->extn ) |
| 35 | 35 | { |
| ... | ... | |
| 275 | 275 | strncat(filename, files[i]->d_name, |
| 276 | 276 | sizeof(filename) - strlen(files[i]->d_name)); |
| 277 | 277 | |
| 278 | | if( !stat(filename, &s) && (s.st_mode & S_IFDIR) ) |
| 278 | if( !stat(filename, &s) && |
| 279 | (s.st_mode & S_IFDIR) && (s.st_mode & S_IXOTH) |
| 280 | ) |
| 279 | 281 | uh_http_sendf(cl, req, |
| 280 | 282 | "<li><strong><a href='%s%s'>%s</a>/</strong><br />" |
| 281 | 283 | "<small>modified: %s<br />directory - %.02f kbyte" |
| ... | ... | |
| 293 | 295 | strncat(filename, files[i]->d_name, |
| 294 | 296 | sizeof(filename) - strlen(files[i]->d_name)); |
| 295 | 297 | |
| 296 | | if( !stat(filename, &s) && !(s.st_mode & S_IFDIR) ) |
| 298 | if( !stat(filename, &s) && |
| 299 | !(s.st_mode & S_IFDIR) && (s.st_mode & S_IROTH) |
| 300 | ) |
| 297 | 301 | uh_http_sendf(cl, req, |
| 298 | 302 | "<li><strong><a href='%s%s'>%s</a></strong><br />" |
| 299 | 303 | "<small>modified: %s<br />%s - %.02f kbyte<br />" |
| ... | ... | |
| 369 | 373 | } |
| 370 | 374 | |
| 371 | 375 | /* directory */ |
| 372 | | else if( pi->stat.st_mode & S_IFDIR ) |
| 376 | else if( (pi->stat.st_mode & S_IFDIR) && !cl->server->conf->no_dirlists ) |
| 373 | 377 | { |
| 374 | 378 | /* write status */ |
| 375 | 379 | uh_file_response_200(cl, req, NULL); |
| package/uhttpd/src/uhttpd-utils.c |
| 59 | 59 | return ntohs(((struct sockaddr_in6 *)sa)->sin6_port); |
| 60 | 60 | } |
| 61 | 61 | |
| 62 | int sa_rfc1918(void *sa) |
| 63 | { |
| 64 | struct sockaddr_in *v4 = (struct sockaddr_in *)sa; |
| 65 | unsigned long a = htonl(v4->sin_addr.s_addr); |
| 66 | |
| 67 | if( v4->sin_family == AF_INET ) |
| 68 | { |
| 69 | return ((a >= 0x0A000000) && (a <= 0x0AFFFFFF)) || |
| 70 | ((a >= 0xAC100000) && (a <= 0xAC1FFFFF)) || |
| 71 | ((a >= 0xC0A80000) && (a <= 0xC0A8FFFF)); |
| 72 | } |
| 73 | |
| 74 | return 0; |
| 75 | } |
| 76 | |
| 62 | 77 | /* Simple strstr() like function that takes len arguments for both haystack and needle. */ |
| 63 | 78 | char *strfind(char *haystack, int hslen, const char *needle, int ndlen) |
| 64 | 79 | { |
| ... | ... | |
| 464 | 479 | int i = 0; |
| 465 | 480 | struct stat s; |
| 466 | 481 | |
| 482 | /* back out early if url is undefined */ |
| 483 | if ( url == NULL ) |
| 484 | return NULL; |
| 467 | 485 | |
| 468 | 486 | memset(path_phys, 0, sizeof(path_phys)); |
| 469 | 487 | memset(path_info, 0, sizeof(path_info)); |
| ... | ... | |
| 550 | 568 | memcpy(buffer, path_phys, sizeof(buffer)); |
| 551 | 569 | pathptr = &buffer[strlen(buffer)]; |
| 552 | 570 | |
| 553 | | for( i = 0; i < array_size(uh_index_files); i++ ) |
| 571 | if( cl->server->conf->index_file ) |
| 554 | 572 | { |
| 555 | | strncat(buffer, uh_index_files[i], sizeof(buffer)); |
| 573 | strncat(buffer, cl->server->conf->index_file, sizeof(buffer)); |
| 556 | 574 | |
| 557 | 575 | if( !stat(buffer, &s) && (s.st_mode & S_IFREG) ) |
| 558 | 576 | { |
| 559 | 577 | memcpy(path_phys, buffer, sizeof(path_phys)); |
| 560 | 578 | memcpy(&p.stat, &s, sizeof(p.stat)); |
| 561 | | break; |
| 562 | 579 | } |
| 580 | } |
| 581 | else |
| 582 | { |
| 583 | for( i = 0; i < array_size(uh_index_files); i++ ) |
| 584 | { |
| 585 | strncat(buffer, uh_index_files[i], sizeof(buffer)); |
| 563 | 586 | |
| 564 | | *pathptr = 0; |
| 587 | if( !stat(buffer, &s) && (s.st_mode & S_IFREG) ) |
| 588 | { |
| 589 | memcpy(path_phys, buffer, sizeof(path_phys)); |
| 590 | memcpy(&p.stat, &s, sizeof(p.stat)); |
| 591 | break; |
| 592 | } |
| 593 | |
| 594 | *pathptr = 0; |
| 595 | } |
| 565 | 596 | } |
| 566 | 597 | |
| 567 | 598 | p.root = docroot; |
| package/uhttpd/src/uhttpd.c |
| 47 | 47 | while( waitpid(-1, NULL, WNOHANG) > 0 ) { } |
| 48 | 48 | } |
| 49 | 49 | |
| 50 | | static void uh_config_parse(const char *path) |
| 50 | static void uh_config_parse(struct config *conf) |
| 51 | 51 | { |
| 52 | 52 | FILE *c; |
| 53 | 53 | char line[512]; |
| ... | ... | |
| 55 | 55 | char *pass = NULL; |
| 56 | 56 | char *eol = NULL; |
| 57 | 57 | |
| 58 | | if( (c = fopen(path ? path : "/etc/httpd.conf", "r")) != NULL ) |
| 58 | const char *path = conf->file ? conf->file : "/etc/httpd.conf"; |
| 59 | |
| 60 | |
| 61 | if( (c = fopen(path, "r")) != NULL ) |
| 59 | 62 | { |
| 60 | 63 | memset(line, 0, sizeof(line)); |
| 61 | 64 | |
| ... | ... | |
| 74 | 77 | "Notice: No password set for user %s, ignoring " |
| 75 | 78 | "authentication on %s\n", user, line |
| 76 | 79 | ); |
| 80 | } |
| 81 | } |
| 82 | else if( !strncmp(line, "I:", 2) ) |
| 83 | { |
| 84 | if( !(user = strchr(line, ':')) || (*user++ = 0) || |
| 85 | !(eol = strchr(user, '\n')) || (*eol++ = 0) ) |
| 86 | continue; |
| 77 | 87 | |
| 78 | | break; |
| 79 | | } |
| 88 | conf->index_file = strdup(user); |
| 89 | } |
| 90 | else if( !strncmp(line, "E404:", 5) ) |
| 91 | { |
| 92 | if( !(user = strchr(line, ':')) || (*user++ = 0) || |
| 93 | !(eol = strchr(user, '\n')) || (*eol++ = 0) ) |
| 94 | continue; |
| 95 | |
| 96 | conf->error_handler = strdup(user); |
| 80 | 97 | } |
| 81 | 98 | } |
| 82 | 99 | |
| ... | ... | |
| 302 | 319 | } |
| 303 | 320 | |
| 304 | 321 | /* valid enough */ |
| 322 | req.redirect_status = 200; |
| 305 | 323 | return &req; |
| 306 | 324 | } |
| 307 | 325 | |
| ... | ... | |
| 505 | 523 | } |
| 506 | 524 | #endif |
| 507 | 525 | |
| 508 | | while( (opt = getopt(argc, argv, "fSC:K:p:s:h:c:l:L:d:r:m:x:t:T:")) > 0 ) |
| 509 | | { |
| 526 | while( (opt = getopt(argc, argv, |
| 527 | "fSDRC:K:E:I:p:s:h:c:l:L:d:r:m:x:t:T:")) > 0 |
| 528 | ) { |
| 510 | 529 | switch(opt) |
| 511 | 530 | { |
| 512 | 531 | /* [addr:]port */ |
| ... | ... | |
| 597 | 616 | } |
| 598 | 617 | break; |
| 599 | 618 | |
| 619 | /* error handler */ |
| 620 | case 'E': |
| 621 | if( (strlen(optarg) == 0) || (optarg[0] != '/') ) |
| 622 | { |
| 623 | fprintf(stderr, "Error: Invalid error handler: %s\n", |
| 624 | optarg); |
| 625 | exit(1); |
| 626 | } |
| 627 | conf.error_handler = optarg; |
| 628 | break; |
| 629 | |
| 630 | /* index file */ |
| 631 | case 'I': |
| 632 | if( (strlen(optarg) == 0) || (optarg[0] == '/') ) |
| 633 | { |
| 634 | fprintf(stderr, "Error: Invalid index page: %s\n", |
| 635 | optarg); |
| 636 | exit(1); |
| 637 | } |
| 638 | conf.index_file = optarg; |
| 639 | break; |
| 640 | |
| 600 | 641 | /* don't follow symlinks */ |
| 601 | 642 | case 'S': |
| 602 | 643 | conf.no_symlinks = 1; |
| 603 | 644 | break; |
| 604 | 645 | |
| 646 | /* don't list directories */ |
| 647 | case 'D': |
| 648 | conf.no_dirlists = 1; |
| 649 | break; |
| 650 | |
| 651 | case 'R': |
| 652 | conf.rfc1918_filter = 1; |
| 653 | break; |
| 654 | |
| 605 | 655 | #ifdef HAVE_CGI |
| 606 | 656 | /* cgi prefix */ |
| 607 | 657 | case 'x': |
| ... | ... | |
| 678 | 728 | " -K file ASN.1 server private key file\n" |
| 679 | 729 | #endif |
| 680 | 730 | " -h directory Specify the document root, default is '.'\n" |
| 731 | " -E string Use given virtual URL as 404 error handler\n" |
| 732 | " -I string Use given filename as index page for directories\n" |
| 681 | 733 | " -S Do not follow symbolic links outside of the docroot\n" |
| 734 | " -D Do not allow directory listings, send 403 instead\n" |
| 735 | " -R Enable RFC1918 filter\n" |
| 682 | 736 | #ifdef HAVE_LUA |
| 683 | 737 | " -l string URL prefix for Lua handler, default is '/lua'\n" |
| 684 | 738 | " -L file Lua handler script, omit to disable Lua\n" |
| ... | ... | |
| 727 | 781 | conf.realm = "Protected Area"; |
| 728 | 782 | |
| 729 | 783 | /* config file */ |
| 730 | | uh_config_parse(conf.file); |
| 784 | uh_config_parse(&conf); |
| 731 | 785 | |
| 732 | 786 | /* default network timeout */ |
| 733 | 787 | if( conf.network_timeout <= 0 ) |
| ... | ... | |
| 883 | 937 | /* parse message header */ |
| 884 | 938 | if( (req = uh_http_header_recv(cl)) != NULL ) |
| 885 | 939 | { |
| 940 | /* RFC1918 filtering required? */ |
| 941 | if( conf.rfc1918_filter && sa_rfc1918(&cl->peeraddr) && |
| 942 | !sa_rfc1918(&cl->servaddr) ) |
| 943 | { |
| 944 | uh_http_sendhf(cl, 403, "Forbidden", |
| 945 | "Rejected request from RFC1918 IP to public server address"); |
| 946 | } |
| 947 | else |
| 886 | 948 | #ifdef HAVE_LUA |
| 887 | 949 | /* Lua request? */ |
| 888 | 950 | if( L && uh_path_match(conf.lua_prefix, req->url) ) |
| ... | ... | |
| 913 | 975 | /* 404 */ |
| 914 | 976 | else |
| 915 | 977 | { |
| 916 | | uh_http_sendhf(cl, 404, "Not Found", |
| 917 | | "No such file or directory"); |
| 978 | /* Try to invoke an error handler */ |
| 979 | pin = uh_path_lookup(cl, conf.error_handler); |
| 980 | |
| 981 | if( pin && uh_auth_check(cl, req, pin) ) |
| 982 | { |
| 983 | req->redirect_status = 404; |
| 984 | |
| 985 | #ifdef HAVE_CGI |
| 986 | if( uh_path_match(conf.cgi_prefix, pin->name) ) |
| 987 | { |
| 988 | uh_cgi_request(cl, req, pin); |
| 989 | } |
| 990 | else |
| 991 | #endif |
| 992 | { |
| 993 | uh_file_request(cl, req, pin); |
| 994 | } |
| 995 | } |
| 996 | else |
| 997 | { |
| 998 | uh_http_sendhf(cl, 404, "Not Found", |
| 999 | "No such file or directory"); |
| 1000 | } |
| 918 | 1001 | } |
| 919 | 1002 | } |
| 920 | 1003 | |