diff options
| author | Denis Vlasenko <vda.linux@googlemail.com> | 2007-06-09 23:49:05 +0000 |
|---|---|---|
| committer | Denis Vlasenko <vda.linux@googlemail.com> | 2007-06-09 23:49:05 +0000 |
| commit | 77e44d60e698c2164f610072e9f7e2bacefdd589 (patch) | |
| tree | aead8cb0cf31e55735bd7681544f0c61290cbbae | |
| parent | 66db264a5fd67ce4573c905c897a1e80ff26a461 (diff) | |
| download | busybox-w32-77e44d60e698c2164f610072e9f7e2bacefdd589.tar.gz busybox-w32-77e44d60e698c2164f610072e9f7e2bacefdd589.tar.bz2 busybox-w32-77e44d60e698c2164f610072e9f7e2bacefdd589.zip | |
httpd: move data off bss.
httpd: do not realpath() for SCRIPT_FILENAME - it resolves symlinks
but it should not:
- /* SCRIPT_FILENAME required by PHP in CGI mode */
- if (!realpath(purl + 1, realpath_buff))
- goto error_execing_cgi;
- setenv1("SCRIPT_FILENAME", realpath_buff);
+
+ /* SCRIPT_FILENAME required by PHP in CGI mode */
+ fullpath = concat_path_file(home_httpd, purl);
+ setenv1("SCRIPT_FILENAME", fullpath);
| -rw-r--r-- | networking/httpd.c | 407 |
1 files changed, 218 insertions, 189 deletions
diff --git a/networking/httpd.c b/networking/httpd.c index f47e2c11f..529f66bc4 100644 --- a/networking/httpd.c +++ b/networking/httpd.c | |||
| @@ -98,10 +98,8 @@ | |||
| 98 | # define PIPE_BUF 4096 | 98 | # define PIPE_BUF 4096 |
| 99 | #endif | 99 | #endif |
| 100 | 100 | ||
| 101 | static const char httpdVersion[] = "busybox httpd/1.35 6-Oct-2004"; | ||
| 102 | static const char default_path_httpd_conf[] = "/etc"; | 101 | static const char default_path_httpd_conf[] = "/etc"; |
| 103 | static const char httpd_conf[] = "httpd.conf"; | 102 | static const char httpd_conf[] = "httpd.conf"; |
| 104 | static const char home[] = "./"; | ||
| 105 | 103 | ||
| 106 | #define TIMEOUT 60 | 104 | #define TIMEOUT 60 |
| 107 | 105 | ||
| @@ -122,55 +120,85 @@ typedef struct HT_ACCESS { | |||
| 122 | } Htaccess; | 120 | } Htaccess; |
| 123 | 121 | ||
| 124 | typedef struct HT_ACCESS_IP { | 122 | typedef struct HT_ACCESS_IP { |
| 125 | unsigned int ip; | 123 | unsigned ip; |
| 126 | unsigned int mask; | 124 | unsigned mask; |
| 127 | int allow_deny; | 125 | int allow_deny; |
| 128 | struct HT_ACCESS_IP *next; | 126 | struct HT_ACCESS_IP *next; |
| 129 | } Htaccess_IP; | 127 | } Htaccess_IP; |
| 130 | 128 | ||
| 131 | typedef struct { | 129 | struct globals { |
| 132 | char buf[MAX_MEMORY_BUFF]; | 130 | int server_socket; |
| 133 | 131 | int accepted_socket; | |
| 134 | USE_FEATURE_HTTPD_BASIC_AUTH(const char *realm;) | 132 | volatile smallint alarm_signaled; |
| 135 | USE_FEATURE_HTTPD_BASIC_AUTH(char *remoteuser;) | 133 | smallint flg_deny_all; |
| 136 | 134 | const char *g_query; | |
| 137 | const char *query; | ||
| 138 | |||
| 139 | USE_FEATURE_HTTPD_CGI(char *referer;) | ||
| 140 | |||
| 141 | const char *configFile; | 135 | const char *configFile; |
| 136 | const char *home_httpd; | ||
| 137 | unsigned rmt_ip; | ||
| 142 | 138 | ||
| 143 | unsigned int rmt_ip; | ||
| 144 | #if ENABLE_FEATURE_HTTPD_CGI || DEBUG | ||
| 145 | char *rmt_ip_str; /* for set env REMOTE_ADDR */ | ||
| 146 | #endif | ||
| 147 | unsigned port; /* server initial port and for | ||
| 148 | set env REMOTE_PORT */ | ||
| 149 | const char *found_mime_type; | 139 | const char *found_mime_type; |
| 150 | const char *found_moved_temporarily; | 140 | const char *found_moved_temporarily; |
| 151 | |||
| 152 | off_t ContentLength; /* -1 - unknown */ | 141 | off_t ContentLength; /* -1 - unknown */ |
| 153 | time_t last_mod; | 142 | time_t last_mod; |
| 154 | |||
| 155 | Htaccess_IP *ip_a_d; /* config allow/deny lines */ | 143 | Htaccess_IP *ip_a_d; /* config allow/deny lines */ |
| 156 | int flg_deny_all; | 144 | |
| 145 | USE_FEATURE_HTTPD_BASIC_AUTH(const char *g_realm;) | ||
| 146 | USE_FEATURE_HTTPD_BASIC_AUTH(char *remoteuser;) | ||
| 147 | USE_FEATURE_HTTPD_CGI(char *referer;) | ||
| 148 | |||
| 149 | #if ENABLE_FEATURE_HTTPD_CGI || DEBUG | ||
| 150 | char *rmt_ip_str; /* for set env REMOTE_ADDR */ | ||
| 151 | #endif | ||
| 152 | unsigned tcp_port; /* server initial port and for | ||
| 153 | set env REMOTE_PORT */ | ||
| 157 | #if ENABLE_FEATURE_HTTPD_BASIC_AUTH | 154 | #if ENABLE_FEATURE_HTTPD_BASIC_AUTH |
| 158 | Htaccess *auth; /* config user:password lines */ | 155 | Htaccess *g_auth; /* config user:password lines */ |
| 159 | #endif | 156 | #endif |
| 160 | #if ENABLE_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES | 157 | #if ENABLE_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES |
| 161 | Htaccess *mime_a; /* config mime types */ | 158 | Htaccess *mime_a; /* config mime types */ |
| 162 | #endif | 159 | #endif |
| 163 | |||
| 164 | int server_socket; | ||
| 165 | int accepted_socket; | ||
| 166 | volatile int alarm_signaled; | ||
| 167 | |||
| 168 | #if ENABLE_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR | 160 | #if ENABLE_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR |
| 169 | Htaccess *script_i; /* config script interpreters */ | 161 | Htaccess *script_i; /* config script interpreters */ |
| 170 | #endif | 162 | #endif |
| 171 | } HttpdConfig; | 163 | char iobuf[MAX_MEMORY_BUFF]; |
| 172 | 164 | }; | |
| 173 | static HttpdConfig *config; | 165 | #define G (*ptr_to_globals) |
| 166 | #define server_socket (G.server_socket ) | ||
| 167 | #define accepted_socket (G.accepted_socket) | ||
| 168 | #define alarm_signaled (G.alarm_signaled ) | ||
| 169 | #define flg_deny_all (G.flg_deny_all ) | ||
| 170 | #define g_query (G.g_query ) | ||
| 171 | #define configFile (G.configFile ) | ||
| 172 | #define home_httpd (G.home_httpd ) | ||
| 173 | #define rmt_ip (G.rmt_ip ) | ||
| 174 | #define found_mime_type (G.found_mime_type) | ||
| 175 | #define found_moved_temporarily (G.found_moved_temporarily) | ||
| 176 | #define ContentLength (G.ContentLength ) | ||
| 177 | #define last_mod (G.last_mod ) | ||
| 178 | #define ip_a_d (G.ip_a_d ) | ||
| 179 | #define g_realm (G.g_realm ) | ||
| 180 | #define remoteuser (G.remoteuser ) | ||
| 181 | #define referer (G.referer ) | ||
| 182 | #if ENABLE_FEATURE_HTTPD_CGI || DEBUG | ||
| 183 | #define rmt_ip_str (G.rmt_ip_str ) | ||
| 184 | #endif | ||
| 185 | #define tcp_port (G.tcp_port ) | ||
| 186 | #if ENABLE_FEATURE_HTTPD_BASIC_AUTH | ||
| 187 | #define g_auth (G.g_auth ) | ||
| 188 | #endif | ||
| 189 | #if ENABLE_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES | ||
| 190 | #define mime_a (G.mime_a ) | ||
| 191 | #endif | ||
| 192 | #if ENABLE_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR | ||
| 193 | #define script_i (G.script_i ) | ||
| 194 | #endif | ||
| 195 | #define iobuf (G.iobuf ) | ||
| 196 | #define INIT_G() do { \ | ||
| 197 | PTR_TO_GLOBALS = xzalloc(sizeof(G)); \ | ||
| 198 | USE_FEATURE_HTTPD_BASIC_AUTH(g_realm = "Web Server Authentication";) \ | ||
| 199 | tcp_port = 80; \ | ||
| 200 | ContentLength = -1; \ | ||
| 201 | } while (0) | ||
| 174 | 202 | ||
| 175 | static const char request_GET[] = "GET"; /* size algorithmic optimize */ | 203 | static const char request_GET[] = "GET"; /* size algorithmic optimize */ |
| 176 | 204 | ||
| @@ -264,7 +292,7 @@ static const char RFC1123FMT[] = "%a, %d %b %Y %H:%M:%S GMT"; | |||
| 264 | #define STRNCASECMP(a, str) strncasecmp((a), (str), sizeof(str)-1) | 292 | #define STRNCASECMP(a, str) strncasecmp((a), (str), sizeof(str)-1) |
| 265 | 293 | ||
| 266 | 294 | ||
| 267 | static int scan_ip(const char **ep, unsigned int *ip, unsigned char endc) | 295 | static int scan_ip(const char **ep, unsigned *ip, unsigned char endc) |
| 268 | { | 296 | { |
| 269 | const char *p = *ep; | 297 | const char *p = *ep; |
| 270 | int auto_mask = 8; | 298 | int auto_mask = 8; |
| @@ -272,7 +300,7 @@ static int scan_ip(const char **ep, unsigned int *ip, unsigned char endc) | |||
| 272 | 300 | ||
| 273 | *ip = 0; | 301 | *ip = 0; |
| 274 | for (j = 0; j < 4; j++) { | 302 | for (j = 0; j < 4; j++) { |
| 275 | unsigned int octet; | 303 | unsigned octet; |
| 276 | 304 | ||
| 277 | if ((*p < '0' || *p > '9') && (*p != '/' || j == 0) && *p != 0) | 305 | if ((*p < '0' || *p > '9') && (*p != '/' || j == 0) && *p != 0) |
| 278 | return -auto_mask; | 306 | return -auto_mask; |
| @@ -301,10 +329,10 @@ static int scan_ip(const char **ep, unsigned int *ip, unsigned char endc) | |||
| 301 | return auto_mask; | 329 | return auto_mask; |
| 302 | } | 330 | } |
| 303 | 331 | ||
| 304 | static int scan_ip_mask(const char *ipm, unsigned int *ip, unsigned int *mask) | 332 | static int scan_ip_mask(const char *ipm, unsigned *ip, unsigned *mask) |
| 305 | { | 333 | { |
| 306 | int i; | 334 | int i; |
| 307 | unsigned int msk; | 335 | unsigned msk; |
| 308 | 336 | ||
| 309 | i = scan_ip(&ipm, ip, '/'); | 337 | i = scan_ip(&ipm, ip, '/'); |
| 310 | if (i < 0) | 338 | if (i < 0) |
| @@ -397,13 +425,13 @@ static void parse_conf(const char *path, int flag) | |||
| 397 | Htaccess *cur; | 425 | Htaccess *cur; |
| 398 | #endif | 426 | #endif |
| 399 | 427 | ||
| 400 | const char *cf = config->configFile; | 428 | const char *cf = configFile; |
| 401 | char buf[160]; | 429 | char buf[160]; |
| 402 | char *p0 = NULL; | 430 | char *p0 = NULL; |
| 403 | char *c, *p; | 431 | char *c, *p; |
| 404 | 432 | ||
| 405 | /* free previous ip setup if present */ | 433 | /* free previous ip setup if present */ |
| 406 | Htaccess_IP *pip = config->ip_a_d; | 434 | Htaccess_IP *pip = ip_a_d; |
| 407 | 435 | ||
| 408 | while (pip) { | 436 | while (pip) { |
| 409 | Htaccess_IP *cur_ipl = pip; | 437 | Htaccess_IP *cur_ipl = pip; |
| @@ -411,9 +439,9 @@ static void parse_conf(const char *path, int flag) | |||
| 411 | pip = cur_ipl->next; | 439 | pip = cur_ipl->next; |
| 412 | free(cur_ipl); | 440 | free(cur_ipl); |
| 413 | } | 441 | } |
| 414 | config->ip_a_d = NULL; | 442 | ip_a_d = NULL; |
| 415 | 443 | ||
| 416 | config->flg_deny_all = 0; | 444 | flg_deny_all = 0; |
| 417 | 445 | ||
| 418 | #if ENABLE_FEATURE_HTTPD_BASIC_AUTH \ | 446 | #if ENABLE_FEATURE_HTTPD_BASIC_AUTH \ |
| 419 | || ENABLE_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES \ | 447 | || ENABLE_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES \ |
| @@ -421,13 +449,13 @@ static void parse_conf(const char *path, int flag) | |||
| 421 | /* retain previous auth and mime config only for subdir parse */ | 449 | /* retain previous auth and mime config only for subdir parse */ |
| 422 | if (flag != SUBDIR_PARSE) { | 450 | if (flag != SUBDIR_PARSE) { |
| 423 | #if ENABLE_FEATURE_HTTPD_BASIC_AUTH | 451 | #if ENABLE_FEATURE_HTTPD_BASIC_AUTH |
| 424 | free_config_lines(&config->auth); | 452 | free_config_lines(&g_auth); |
| 425 | #endif | 453 | #endif |
| 426 | #if ENABLE_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES | 454 | #if ENABLE_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES |
| 427 | free_config_lines(&config->mime_a); | 455 | free_config_lines(&mime_a); |
| 428 | #endif | 456 | #endif |
| 429 | #if ENABLE_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR | 457 | #if ENABLE_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR |
| 430 | free_config_lines(&config->script_i); | 458 | free_config_lines(&script_i); |
| 431 | #endif | 459 | #endif |
| 432 | } | 460 | } |
| 433 | #endif | 461 | #endif |
| @@ -447,16 +475,16 @@ static void parse_conf(const char *path, int flag) | |||
| 447 | /* config file not found, no changes to config */ | 475 | /* config file not found, no changes to config */ |
| 448 | return; | 476 | return; |
| 449 | } | 477 | } |
| 450 | if (config->configFile && flag == FIRST_PARSE) /* if -c option given */ | 478 | if (configFile && flag == FIRST_PARSE) /* if -c option given */ |
| 451 | bb_perror_msg_and_die("%s", cf); | 479 | bb_perror_msg_and_die("%s", cf); |
| 452 | flag = FIND_FROM_HTTPD_ROOT; | 480 | flag = FIND_FROM_HTTPD_ROOT; |
| 453 | cf = httpd_conf; | 481 | cf = httpd_conf; |
| 454 | } | 482 | } |
| 455 | 483 | ||
| 456 | #if ENABLE_FEATURE_HTTPD_BASIC_AUTH | 484 | #if ENABLE_FEATURE_HTTPD_BASIC_AUTH |
| 457 | prev = config->auth; | 485 | prev = g_auth; |
| 458 | #endif | 486 | #endif |
| 459 | /* This could stand some work */ | 487 | /* This could stand some work */ |
| 460 | while ((p0 = fgets(buf, sizeof(buf), f)) != NULL) { | 488 | while ((p0 = fgets(buf, sizeof(buf), f)) != NULL) { |
| 461 | c = NULL; | 489 | c = NULL; |
| 462 | for (p = p0; *p0 != 0 && *p0 != '#'; p0++) { | 490 | for (p = p0; *p0 != 0 && *p0 != '#'; p0++) { |
| @@ -477,7 +505,7 @@ static void parse_conf(const char *path, int flag) | |||
| 477 | if (*c == '*') { | 505 | if (*c == '*') { |
| 478 | if (*p0 == 'D') { | 506 | if (*p0 == 'D') { |
| 479 | /* memorize deny all */ | 507 | /* memorize deny all */ |
| 480 | config->flg_deny_all++; | 508 | flg_deny_all = 1; |
| 481 | } | 509 | } |
| 482 | /* skip default other "word:*" config lines */ | 510 | /* skip default other "word:*" config lines */ |
| 483 | continue; | 511 | continue; |
| @@ -509,14 +537,14 @@ static void parse_conf(const char *path, int flag) | |||
| 509 | pip->allow_deny = *p0; | 537 | pip->allow_deny = *p0; |
| 510 | if (*p0 == 'D') { | 538 | if (*p0 == 'D') { |
| 511 | /* Deny:form_IP move top */ | 539 | /* Deny:form_IP move top */ |
| 512 | pip->next = config->ip_a_d; | 540 | pip->next = ip_a_d; |
| 513 | config->ip_a_d = pip; | 541 | ip_a_d = pip; |
| 514 | } else { | 542 | } else { |
| 515 | /* add to bottom A:form_IP config line */ | 543 | /* add to bottom A:form_IP config line */ |
| 516 | Htaccess_IP *prev_IP = config->ip_a_d; | 544 | Htaccess_IP *prev_IP = ip_a_d; |
| 517 | 545 | ||
| 518 | if (prev_IP == NULL) { | 546 | if (prev_IP == NULL) { |
| 519 | config->ip_a_d = pip; | 547 | ip_a_d = pip; |
| 520 | } else { | 548 | } else { |
| 521 | while (prev_IP->next) | 549 | while (prev_IP->next) |
| 522 | prev_IP = prev_IP->next; | 550 | prev_IP = prev_IP->next; |
| @@ -579,16 +607,16 @@ static void parse_conf(const char *path, int flag) | |||
| 579 | #if ENABLE_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES | 607 | #if ENABLE_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES |
| 580 | if (*cf == '.') { | 608 | if (*cf == '.') { |
| 581 | /* config .mime line move top for overwrite previous */ | 609 | /* config .mime line move top for overwrite previous */ |
| 582 | cur->next = config->mime_a; | 610 | cur->next = mime_a; |
| 583 | config->mime_a = cur; | 611 | mime_a = cur; |
| 584 | continue; | 612 | continue; |
| 585 | } | 613 | } |
| 586 | #endif | 614 | #endif |
| 587 | #if ENABLE_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR | 615 | #if ENABLE_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR |
| 588 | if (*cf == '*' && cf[1] == '.') { | 616 | if (*cf == '*' && cf[1] == '.') { |
| 589 | /* config script interpreter line move top for overwrite previous */ | 617 | /* config script interpreter line move top for overwrite previous */ |
| 590 | cur->next = config->script_i; | 618 | cur->next = script_i; |
| 591 | config->script_i = cur; | 619 | script_i = cur; |
| 592 | continue; | 620 | continue; |
| 593 | } | 621 | } |
| 594 | #endif | 622 | #endif |
| @@ -596,10 +624,10 @@ static void parse_conf(const char *path, int flag) | |||
| 596 | free(p0); | 624 | free(p0); |
| 597 | if (prev == NULL) { | 625 | if (prev == NULL) { |
| 598 | /* first line */ | 626 | /* first line */ |
| 599 | config->auth = prev = cur; | 627 | g_auth = prev = cur; |
| 600 | } else { | 628 | } else { |
| 601 | /* sort path, if current lenght eq or bigger then move up */ | 629 | /* sort path, if current lenght eq or bigger then move up */ |
| 602 | Htaccess *prev_hti = config->auth; | 630 | Htaccess *prev_hti = g_auth; |
| 603 | size_t l = strlen(cf); | 631 | size_t l = strlen(cf); |
| 604 | Htaccess *hti; | 632 | Htaccess *hti; |
| 605 | 633 | ||
| @@ -611,7 +639,7 @@ static void parse_conf(const char *path, int flag) | |||
| 611 | prev_hti->next = cur; | 639 | prev_hti->next = cur; |
| 612 | } else { | 640 | } else { |
| 613 | /* insert as top */ | 641 | /* insert as top */ |
| 614 | config->auth = cur; | 642 | g_auth = cur; |
| 615 | } | 643 | } |
| 616 | break; | 644 | break; |
| 617 | } | 645 | } |
| @@ -818,7 +846,7 @@ static int openServer(void) | |||
| 818 | int fd; | 846 | int fd; |
| 819 | 847 | ||
| 820 | /* create the socket right now */ | 848 | /* create the socket right now */ |
| 821 | fd = create_and_bind_stream_or_die(NULL, config->port); | 849 | fd = create_and_bind_stream_or_die(NULL, tcp_port); |
| 822 | xlisten(fd, 9); | 850 | xlisten(fd, 9); |
| 823 | return fd; | 851 | return fd; |
| 824 | } | 852 | } |
| @@ -840,7 +868,7 @@ static int openServer(void) | |||
| 840 | ****************************************************************************/ | 868 | ****************************************************************************/ |
| 841 | static int sendHeaders(HttpResponseNum responseNum) | 869 | static int sendHeaders(HttpResponseNum responseNum) |
| 842 | { | 870 | { |
| 843 | char *buf = config->buf; | 871 | char *buf = iobuf; |
| 844 | const char *responseString = ""; | 872 | const char *responseString = ""; |
| 845 | const char *infoString = 0; | 873 | const char *infoString = 0; |
| 846 | const char *mime_type; | 874 | const char *mime_type; |
| @@ -861,7 +889,7 @@ static int sendHeaders(HttpResponseNum responseNum) | |||
| 861 | } | 889 | } |
| 862 | /* error message is HTML */ | 890 | /* error message is HTML */ |
| 863 | mime_type = responseNum == HTTP_OK ? | 891 | mime_type = responseNum == HTTP_OK ? |
| 864 | config->found_mime_type : "text/html"; | 892 | found_mime_type : "text/html"; |
| 865 | 893 | ||
| 866 | /* emit the current date */ | 894 | /* emit the current date */ |
| 867 | strftime(timeStr, sizeof(timeStr), RFC1123FMT, gmtime(&timer)); | 895 | strftime(timeStr, sizeof(timeStr), RFC1123FMT, gmtime(&timer)); |
| @@ -874,20 +902,20 @@ static int sendHeaders(HttpResponseNum responseNum) | |||
| 874 | if (responseNum == HTTP_UNAUTHORIZED) { | 902 | if (responseNum == HTTP_UNAUTHORIZED) { |
| 875 | len += sprintf(buf+len, | 903 | len += sprintf(buf+len, |
| 876 | "WWW-Authenticate: Basic realm=\"%s\"\r\n", | 904 | "WWW-Authenticate: Basic realm=\"%s\"\r\n", |
| 877 | config->realm); | 905 | g_realm); |
| 878 | } | 906 | } |
| 879 | #endif | 907 | #endif |
| 880 | if (responseNum == HTTP_MOVED_TEMPORARILY) { | 908 | if (responseNum == HTTP_MOVED_TEMPORARILY) { |
| 881 | len += sprintf(buf+len, "Location: %s/%s%s\r\n", | 909 | len += sprintf(buf+len, "Location: %s/%s%s\r\n", |
| 882 | config->found_moved_temporarily, | 910 | found_moved_temporarily, |
| 883 | (config->query ? "?" : ""), | 911 | (g_query ? "?" : ""), |
| 884 | (config->query ? config->query : "")); | 912 | (g_query ? g_query : "")); |
| 885 | } | 913 | } |
| 886 | 914 | ||
| 887 | if (config->ContentLength != -1) { /* file */ | 915 | if (ContentLength != -1) { /* file */ |
| 888 | strftime(timeStr, sizeof(timeStr), RFC1123FMT, gmtime(&config->last_mod)); | 916 | strftime(timeStr, sizeof(timeStr), RFC1123FMT, gmtime(&last_mod)); |
| 889 | len += sprintf(buf+len, "Last-Modified: %s\r\n%s %"OFF_FMT"d\r\n", | 917 | len += sprintf(buf+len, "Last-Modified: %s\r\n%s %"OFF_FMT"d\r\n", |
| 890 | timeStr, "Content-length:", config->ContentLength); | 918 | timeStr, "Content-length:", ContentLength); |
| 891 | } | 919 | } |
| 892 | strcat(buf, "\r\n"); | 920 | strcat(buf, "\r\n"); |
| 893 | len += 2; | 921 | len += 2; |
| @@ -900,7 +928,7 @@ static int sendHeaders(HttpResponseNum responseNum) | |||
| 900 | } | 928 | } |
| 901 | if (DEBUG) | 929 | if (DEBUG) |
| 902 | fprintf(stderr, "headers: '%s'\n", buf); | 930 | fprintf(stderr, "headers: '%s'\n", buf); |
| 903 | i = config->accepted_socket; | 931 | i = accepted_socket; |
| 904 | if (i == 0) i++; /* write to fd# 1 in inetd mode */ | 932 | if (i == 0) i++; /* write to fd# 1 in inetd mode */ |
| 905 | return full_write(i, buf, len); | 933 | return full_write(i, buf, len); |
| 906 | } | 934 | } |
| @@ -919,9 +947,9 @@ static int sendHeaders(HttpResponseNum responseNum) | |||
| 919 | static int getLine(void) | 947 | static int getLine(void) |
| 920 | { | 948 | { |
| 921 | int count = 0; | 949 | int count = 0; |
| 922 | char *buf = config->buf; | 950 | char *buf = iobuf; |
| 923 | 951 | ||
| 924 | while (read(config->accepted_socket, buf + count, 1) == 1) { | 952 | while (read(accepted_socket, buf + count, 1) == 1) { |
| 925 | if (buf[count] == '\r') continue; | 953 | if (buf[count] == '\r') continue; |
| 926 | if (buf[count] == '\n') { | 954 | if (buf[count] == '\n') { |
| 927 | buf[count] = 0; | 955 | buf[count] = 0; |
| @@ -962,8 +990,8 @@ static int sendCgi(const char *url, | |||
| 962 | { | 990 | { |
| 963 | int fromCgi[2]; /* pipe for reading data from CGI */ | 991 | int fromCgi[2]; /* pipe for reading data from CGI */ |
| 964 | int toCgi[2]; /* pipe for sending data to CGI */ | 992 | int toCgi[2]; /* pipe for sending data to CGI */ |
| 965 | 993 | char *fullpath; | |
| 966 | static char * argp[] = { 0, 0 }; | 994 | char *argp[] = { NULL, NULL }; |
| 967 | int pid = 0; | 995 | int pid = 0; |
| 968 | int inFd; | 996 | int inFd; |
| 969 | int outFd; | 997 | int outFd; |
| @@ -985,7 +1013,14 @@ static int sendCgi(const char *url, | |||
| 985 | * since httpd is run from inetd (and it can't run standalone | 1013 | * since httpd is run from inetd (and it can't run standalone |
| 986 | * in uClinux). | 1014 | * in uClinux). |
| 987 | */ | 1015 | */ |
| 1016 | |||
| 1017 | // FIXME: setenv leaks memory! (old values of env vars are leaked) | ||
| 1018 | // Thus we have a bug on NOMMU. | ||
| 1019 | // Need to use this instead: | ||
| 1020 | // [malloc +] putenv + (in child: exec) + (in parent: unsetenv [+ free]) | ||
| 1021 | |||
| 988 | #if !BB_MMU | 1022 | #if !BB_MMU |
| 1023 | fullpath = NULL; | ||
| 989 | pid = vfork(); | 1024 | pid = vfork(); |
| 990 | #else | 1025 | #else |
| 991 | pid = fork(); | 1026 | pid = fork(); |
| @@ -997,25 +1032,19 @@ static int sendCgi(const char *url, | |||
| 997 | /* child process */ | 1032 | /* child process */ |
| 998 | char *script; | 1033 | char *script; |
| 999 | char *purl; | 1034 | char *purl; |
| 1000 | char realpath_buff[MAXPATHLEN]; | ||
| 1001 | 1035 | ||
| 1002 | if (config->accepted_socket > 1) | 1036 | if (accepted_socket > 1) |
| 1003 | close(config->accepted_socket); | 1037 | close(accepted_socket); |
| 1004 | if (config->server_socket > 1) | 1038 | if (server_socket > 1) |
| 1005 | close(config->server_socket); | 1039 | close(server_socket); |
| 1006 | 1040 | ||
| 1007 | dup2(toCgi[0], 0); // replace stdin with the pipe | 1041 | xmove_fd(toCgi[0], 0); /* replace stdin with the pipe */ |
| 1008 | dup2(fromCgi[1], 1); // replace stdout with the pipe | 1042 | xmove_fd(fromCgi[1], 1); /* replace stdout with the pipe */ |
| 1009 | /* Huh? User seeing stderr can be a security problem... | ||
| 1010 | * and if CGI really wants that, it can always dup2(1,2)... | ||
| 1011 | if (!DEBUG) | ||
| 1012 | dup2(fromCgi[1], 2); // replace stderr with the pipe | ||
| 1013 | */ | ||
| 1014 | /* I think we cannot inadvertently close 0, 1 here... */ | ||
| 1015 | close(toCgi[0]); | ||
| 1016 | close(toCgi[1]); | ||
| 1017 | close(fromCgi[0]); | 1043 | close(fromCgi[0]); |
| 1018 | close(fromCgi[1]); | 1044 | close(fromCgi[1]); |
| 1045 | /* Huh? User seeing stderr can be a security problem... | ||
| 1046 | * and if CGI really wants that, it can always dup2(1,2)... | ||
| 1047 | * dup2(fromCgi[1], 2); */ | ||
| 1019 | 1048 | ||
| 1020 | /* | 1049 | /* |
| 1021 | * Find PATH_INFO. | 1050 | * Find PATH_INFO. |
| @@ -1036,22 +1065,21 @@ static int sendCgi(const char *url, | |||
| 1036 | *script = '/'; /* is directory, find next '/' */ | 1065 | *script = '/'; /* is directory, find next '/' */ |
| 1037 | } | 1066 | } |
| 1038 | setenv1("PATH_INFO", script); /* set /PATH_INFO or "" */ | 1067 | setenv1("PATH_INFO", script); /* set /PATH_INFO or "" */ |
| 1039 | /* setenv1("PATH", getenv("PATH")); redundant */ | ||
| 1040 | setenv1("REQUEST_METHOD", request); | 1068 | setenv1("REQUEST_METHOD", request); |
| 1041 | if (config->query) { | 1069 | if (g_query) { |
| 1042 | char *uri = alloca(strlen(purl) + 2 + strlen(config->query)); | 1070 | char *uri = alloca(strlen(purl) + 2 + strlen(g_query)); |
| 1043 | if (uri) | 1071 | if (uri) |
| 1044 | sprintf(uri, "%s?%s", purl, config->query); | 1072 | sprintf(uri, "%s?%s", purl, g_query); |
| 1045 | setenv1("REQUEST_URI", uri); | 1073 | setenv1("REQUEST_URI", uri); |
| 1046 | } else { | 1074 | } else { |
| 1047 | setenv1("REQUEST_URI", purl); | 1075 | setenv1("REQUEST_URI", purl); |
| 1048 | } | 1076 | } |
| 1049 | if (script != NULL) | 1077 | if (script != NULL) |
| 1050 | *script = '\0'; /* cut off /PATH_INFO */ | 1078 | *script = '\0'; /* cut off /PATH_INFO */ |
| 1051 | /* SCRIPT_FILENAME required by PHP in CGI mode */ | 1079 | |
| 1052 | if (!realpath(purl + 1, realpath_buff)) | 1080 | /* SCRIPT_FILENAME required by PHP in CGI mode */ |
| 1053 | goto error_execing_cgi; | 1081 | fullpath = concat_path_file(home_httpd, purl); |
| 1054 | setenv1("SCRIPT_FILENAME", realpath_buff); | 1082 | setenv1("SCRIPT_FILENAME", fullpath); |
| 1055 | /* set SCRIPT_NAME as full path: /cgi-bin/dirs/script.cgi */ | 1083 | /* set SCRIPT_NAME as full path: /cgi-bin/dirs/script.cgi */ |
| 1056 | setenv1("SCRIPT_NAME", purl); | 1084 | setenv1("SCRIPT_NAME", purl); |
| 1057 | /* http://hoohoo.ncsa.uiuc.edu/cgi/env.html: | 1085 | /* http://hoohoo.ncsa.uiuc.edu/cgi/env.html: |
| @@ -1061,8 +1089,8 @@ static int sendCgi(const char *url, | |||
| 1061 | * should always be set when there is query information, | 1089 | * should always be set when there is query information, |
| 1062 | * regardless of command line decoding. */ | 1090 | * regardless of command line decoding. */ |
| 1063 | /* (Older versions of bbox seem to do some decoding) */ | 1091 | /* (Older versions of bbox seem to do some decoding) */ |
| 1064 | setenv1("QUERY_STRING", config->query); | 1092 | setenv1("QUERY_STRING", g_query); |
| 1065 | setenv1("SERVER_SOFTWARE", httpdVersion); | 1093 | putenv((char*)"SERVER_SOFTWARE=busybox httpd/"BB_VER); |
| 1066 | putenv((char*)"SERVER_PROTOCOL=HTTP/1.0"); | 1094 | putenv((char*)"SERVER_PROTOCOL=HTTP/1.0"); |
| 1067 | putenv((char*)"GATEWAY_INTERFACE=CGI/1.1"); | 1095 | putenv((char*)"GATEWAY_INTERFACE=CGI/1.1"); |
| 1068 | /* Having _separate_ variables for IP and port defeats | 1096 | /* Having _separate_ variables for IP and port defeats |
| @@ -1071,15 +1099,16 @@ static int sendCgi(const char *url, | |||
| 1071 | * IOW - REMOTE_PEER="1.2.3.4:56" makes much more sense. | 1099 | * IOW - REMOTE_PEER="1.2.3.4:56" makes much more sense. |
| 1072 | * Oh well... */ | 1100 | * Oh well... */ |
| 1073 | { | 1101 | { |
| 1074 | char *p = config->rmt_ip_str ? : (char*)""; | 1102 | char *p = rmt_ip_str ? : (char*)""; |
| 1075 | char *cp = strrchr(p, ':'); | 1103 | char *cp = strrchr(p, ':'); |
| 1076 | if (ENABLE_FEATURE_IPV6 && cp && strchr(cp, ']')) | 1104 | if (ENABLE_FEATURE_IPV6 && cp && strchr(cp, ']')) |
| 1077 | cp = NULL; | 1105 | cp = NULL; |
| 1078 | if (cp) *cp = '\0'; /* delete :PORT */ | 1106 | if (cp) *cp = '\0'; /* delete :PORT */ |
| 1079 | setenv1("REMOTE_ADDR", p); | 1107 | setenv1("REMOTE_ADDR", p); |
| 1108 | if (cp) *cp = ':'; | ||
| 1080 | } | 1109 | } |
| 1081 | #if ENABLE_FEATURE_HTTPD_SET_REMOTE_PORT_TO_ENV | 1110 | #if ENABLE_FEATURE_HTTPD_SET_REMOTE_PORT_TO_ENV |
| 1082 | setenv_long("REMOTE_PORT", config->port); | 1111 | setenv_long("REMOTE_PORT", tcp_port); |
| 1083 | #endif | 1112 | #endif |
| 1084 | if (bodyLen) | 1113 | if (bodyLen) |
| 1085 | setenv_long("CONTENT_LENGTH", bodyLen); | 1114 | setenv_long("CONTENT_LENGTH", bodyLen); |
| @@ -1088,22 +1117,22 @@ static int sendCgi(const char *url, | |||
| 1088 | if (content_type) | 1117 | if (content_type) |
| 1089 | setenv1("CONTENT_TYPE", content_type); | 1118 | setenv1("CONTENT_TYPE", content_type); |
| 1090 | #if ENABLE_FEATURE_HTTPD_BASIC_AUTH | 1119 | #if ENABLE_FEATURE_HTTPD_BASIC_AUTH |
| 1091 | if (config->remoteuser) { | 1120 | if (remoteuser) { |
| 1092 | setenv1("REMOTE_USER", config->remoteuser); | 1121 | setenv1("REMOTE_USER", remoteuser); |
| 1093 | putenv((char*)"AUTH_TYPE=Basic"); | 1122 | putenv((char*)"AUTH_TYPE=Basic"); |
| 1094 | } | 1123 | } |
| 1095 | #endif | 1124 | #endif |
| 1096 | if (config->referer) | 1125 | if (referer) |
| 1097 | setenv1("HTTP_REFERER", config->referer); | 1126 | setenv1("HTTP_REFERER", referer); |
| 1098 | 1127 | ||
| 1099 | /* set execve argp[0] without path */ | 1128 | /* set execve argp[0] without path */ |
| 1100 | argp[0] = strrchr(purl, '/') + 1; | 1129 | argp[0] = strrchr(purl, '/') + 1; |
| 1101 | /* but script argp[0] must have absolute path and chdiring to this */ | 1130 | /* but script argp[0] must have absolute path and chdiring to this */ |
| 1102 | script = strrchr(realpath_buff, '/'); | 1131 | script = strrchr(fullpath, '/'); |
| 1103 | if (!script) | 1132 | if (!script) |
| 1104 | goto error_execing_cgi; | 1133 | goto error_execing_cgi; |
| 1105 | *script = '\0'; | 1134 | *script = '\0'; |
| 1106 | if (chdir(realpath_buff) == 0) { | 1135 | if (chdir(fullpath) == 0) { |
| 1107 | // Now run the program. If it fails, | 1136 | // Now run the program. If it fails, |
| 1108 | // use _exit() so no destructors | 1137 | // use _exit() so no destructors |
| 1109 | // get called and make a mess. | 1138 | // get called and make a mess. |
| @@ -1113,7 +1142,7 @@ static int sendCgi(const char *url, | |||
| 1113 | 1142 | ||
| 1114 | if (suffix) { | 1143 | if (suffix) { |
| 1115 | Htaccess *cur; | 1144 | Htaccess *cur; |
| 1116 | for (cur = config->script_i; cur; cur = cur->next) { | 1145 | for (cur = script_i; cur; cur = cur->next) { |
| 1117 | if (strcmp(cur->before_colon + 1, suffix) == 0) { | 1146 | if (strcmp(cur->before_colon + 1, suffix) == 0) { |
| 1118 | interpr = cur->after_colon; | 1147 | interpr = cur->after_colon; |
| 1119 | break; | 1148 | break; |
| @@ -1127,16 +1156,19 @@ static int sendCgi(const char *url, | |||
| 1127 | execv(interpr, argp); | 1156 | execv(interpr, argp); |
| 1128 | else | 1157 | else |
| 1129 | #endif | 1158 | #endif |
| 1130 | execv(realpath_buff, argp); | 1159 | execv(fullpath, argp); |
| 1131 | } | 1160 | } |
| 1132 | error_execing_cgi: | 1161 | error_execing_cgi: |
| 1133 | /* send to stdout (even if we are not from inetd) */ | 1162 | /* send to stdout (even if we are not from inetd) */ |
| 1134 | config->accepted_socket = 1; | 1163 | accepted_socket = 1; |
| 1135 | sendHeaders(HTTP_NOT_FOUND); | 1164 | sendHeaders(HTTP_NOT_FOUND); |
| 1136 | _exit(242); | 1165 | _exit(242); |
| 1137 | } /* end child */ | 1166 | } /* end child */ |
| 1138 | 1167 | ||
| 1139 | /* parent process */ | 1168 | /* parent process */ |
| 1169 | #if !BB_MMU | ||
| 1170 | free(fullpath); | ||
| 1171 | #endif | ||
| 1140 | 1172 | ||
| 1141 | buf_count = 0; | 1173 | buf_count = 0; |
| 1142 | post_read_size = 0; | 1174 | post_read_size = 0; |
| @@ -1161,9 +1193,9 @@ static int sendCgi(const char *url, | |||
| 1161 | FD_SET(outFd, &writeSet); | 1193 | FD_SET(outFd, &writeSet); |
| 1162 | nfound = outFd > inFd ? outFd : inFd; | 1194 | nfound = outFd > inFd ? outFd : inFd; |
| 1163 | if (post_read_size == 0) { | 1195 | if (post_read_size == 0) { |
| 1164 | FD_SET(config->accepted_socket, &readSet); | 1196 | FD_SET(accepted_socket, &readSet); |
| 1165 | if (nfound < config->accepted_socket) | 1197 | if (nfound < accepted_socket) |
| 1166 | nfound = config->accepted_socket; | 1198 | nfound = accepted_socket; |
| 1167 | } | 1199 | } |
| 1168 | /* Now wait on the set of sockets! */ | 1200 | /* Now wait on the set of sockets! */ |
| 1169 | nfound = select(nfound + 1, &readSet, &writeSet, NULL, NULL); | 1201 | nfound = select(nfound + 1, &readSet, &writeSet, NULL, NULL); |
| @@ -1201,13 +1233,13 @@ static int sendCgi(const char *url, | |||
| 1201 | post_read_size = bodyLen = 0; /* broken pipe to CGI */ | 1233 | post_read_size = bodyLen = 0; /* broken pipe to CGI */ |
| 1202 | } | 1234 | } |
| 1203 | } else if (bodyLen > 0 && post_read_size == 0 | 1235 | } else if (bodyLen > 0 && post_read_size == 0 |
| 1204 | && FD_ISSET(config->accepted_socket, &readSet) | 1236 | && FD_ISSET(accepted_socket, &readSet) |
| 1205 | ) { | 1237 | ) { |
| 1206 | /* We expect data, prev data portion is eaten by CGI | 1238 | /* We expect data, prev data portion is eaten by CGI |
| 1207 | * and there *is* data to read from the peer | 1239 | * and there *is* data to read from the peer |
| 1208 | * (POSTDATA?) */ | 1240 | * (POSTDATA?) */ |
| 1209 | count = bodyLen > (int)sizeof(wbuf) ? (int)sizeof(wbuf) : bodyLen; | 1241 | count = bodyLen > (int)sizeof(wbuf) ? (int)sizeof(wbuf) : bodyLen; |
| 1210 | count = safe_read(config->accepted_socket, wbuf, count); | 1242 | count = safe_read(accepted_socket, wbuf, count); |
| 1211 | if (count > 0) { | 1243 | if (count > 0) { |
| 1212 | post_read_size = count; | 1244 | post_read_size = count; |
| 1213 | post_read_idx = 0; | 1245 | post_read_idx = 0; |
| @@ -1223,8 +1255,8 @@ static int sendCgi(const char *url, | |||
| 1223 | #endif | 1255 | #endif |
| 1224 | if (FD_ISSET(inFd, &readSet)) { | 1256 | if (FD_ISSET(inFd, &readSet)) { |
| 1225 | /* There is something to read from CGI */ | 1257 | /* There is something to read from CGI */ |
| 1226 | int s = config->accepted_socket; | 1258 | int s = accepted_socket; |
| 1227 | char *rbuf = config->buf; | 1259 | char *rbuf = iobuf; |
| 1228 | 1260 | ||
| 1229 | /* Are we still buffering CGI output? */ | 1261 | /* Are we still buffering CGI output? */ |
| 1230 | if (buf_count >= 0) { | 1262 | if (buf_count >= 0) { |
| @@ -1306,14 +1338,14 @@ static int sendFile(const char *url) | |||
| 1306 | break; | 1338 | break; |
| 1307 | } | 1339 | } |
| 1308 | /* also, if not found, set default as "application/octet-stream"; */ | 1340 | /* also, if not found, set default as "application/octet-stream"; */ |
| 1309 | config->found_mime_type = table[1]; | 1341 | found_mime_type = table[1]; |
| 1310 | #if ENABLE_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES | 1342 | #if ENABLE_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES |
| 1311 | if (suffix) { | 1343 | if (suffix) { |
| 1312 | Htaccess * cur; | 1344 | Htaccess * cur; |
| 1313 | 1345 | ||
| 1314 | for (cur = config->mime_a; cur; cur = cur->next) { | 1346 | for (cur = mime_a; cur; cur = cur->next) { |
| 1315 | if (strcmp(cur->before_colon, suffix) == 0) { | 1347 | if (strcmp(cur->before_colon, suffix) == 0) { |
| 1316 | config->found_mime_type = cur->after_colon; | 1348 | found_mime_type = cur->after_colon; |
| 1317 | break; | 1349 | break; |
| 1318 | } | 1350 | } |
| 1319 | } | 1351 | } |
| @@ -1322,17 +1354,17 @@ static int sendFile(const char *url) | |||
| 1322 | 1354 | ||
| 1323 | if (DEBUG) | 1355 | if (DEBUG) |
| 1324 | fprintf(stderr, "sending file '%s' content-type: %s\n", | 1356 | fprintf(stderr, "sending file '%s' content-type: %s\n", |
| 1325 | url, config->found_mime_type); | 1357 | url, found_mime_type); |
| 1326 | 1358 | ||
| 1327 | f = open(url, O_RDONLY); | 1359 | f = open(url, O_RDONLY); |
| 1328 | if (f >= 0) { | 1360 | if (f >= 0) { |
| 1329 | int count; | 1361 | int count; |
| 1330 | char *buf = config->buf; | 1362 | char *buf = iobuf; |
| 1331 | 1363 | ||
| 1332 | sendHeaders(HTTP_OK); | 1364 | sendHeaders(HTTP_OK); |
| 1333 | /* TODO: sendfile() */ | 1365 | /* TODO: sendfile() */ |
| 1334 | while ((count = full_read(f, buf, MAX_MEMORY_BUFF)) > 0) { | 1366 | while ((count = full_read(f, buf, MAX_MEMORY_BUFF)) > 0) { |
| 1335 | int fd = config->accepted_socket; | 1367 | int fd = accepted_socket; |
| 1336 | if (fd == 0) fd++; /* write to fd# 1 in inetd mode */ | 1368 | if (fd == 0) fd++; /* write to fd# 1 in inetd mode */ |
| 1337 | if (full_write(fd, buf, count) != count) | 1369 | if (full_write(fd, buf, count) != count) |
| 1338 | break; | 1370 | break; |
| @@ -1352,9 +1384,9 @@ static int checkPermIP(void) | |||
| 1352 | Htaccess_IP * cur; | 1384 | Htaccess_IP * cur; |
| 1353 | 1385 | ||
| 1354 | /* This could stand some work */ | 1386 | /* This could stand some work */ |
| 1355 | for (cur = config->ip_a_d; cur; cur = cur->next) { | 1387 | for (cur = ip_a_d; cur; cur = cur->next) { |
| 1356 | #if ENABLE_FEATURE_HTTPD_CGI && DEBUG | 1388 | #if ENABLE_FEATURE_HTTPD_CGI && DEBUG |
| 1357 | fprintf(stderr, "checkPermIP: '%s' ? ", config->rmt_ip_str); | 1389 | fprintf(stderr, "checkPermIP: '%s' ? ", rmt_ip_str); |
| 1358 | #endif | 1390 | #endif |
| 1359 | #if DEBUG | 1391 | #if DEBUG |
| 1360 | fprintf(stderr, "'%u.%u.%u.%u/%u.%u.%u.%u'\n", | 1392 | fprintf(stderr, "'%u.%u.%u.%u/%u.%u.%u.%u'\n", |
| @@ -1368,12 +1400,12 @@ static int checkPermIP(void) | |||
| 1368 | (unsigned char)(cur->mask) | 1400 | (unsigned char)(cur->mask) |
| 1369 | ); | 1401 | ); |
| 1370 | #endif | 1402 | #endif |
| 1371 | if ((config->rmt_ip & cur->mask) == cur->ip) | 1403 | if ((rmt_ip & cur->mask) == cur->ip) |
| 1372 | return cur->allow_deny == 'A'; /* Allow/Deny */ | 1404 | return cur->allow_deny == 'A'; /* Allow/Deny */ |
| 1373 | } | 1405 | } |
| 1374 | 1406 | ||
| 1375 | /* if unconfigured, return 1 - access from all */ | 1407 | /* if unconfigured, return 1 - access from all */ |
| 1376 | return !config->flg_deny_all; | 1408 | return !flg_deny_all; |
| 1377 | } | 1409 | } |
| 1378 | 1410 | ||
| 1379 | /**************************************************************************** | 1411 | /**************************************************************************** |
| @@ -1403,7 +1435,7 @@ static int checkPerm(const char *path, const char *request) | |||
| 1403 | const char *prev = NULL; | 1435 | const char *prev = NULL; |
| 1404 | 1436 | ||
| 1405 | /* This could stand some work */ | 1437 | /* This could stand some work */ |
| 1406 | for (cur = config->auth; cur; cur = cur->next) { | 1438 | for (cur = g_auth; cur; cur = cur->next) { |
| 1407 | size_t l; | 1439 | size_t l; |
| 1408 | 1440 | ||
| 1409 | p0 = cur->before_colon; | 1441 | p0 = cur->before_colon; |
| @@ -1449,9 +1481,9 @@ static int checkPerm(const char *path, const char *request) | |||
| 1449 | 1481 | ||
| 1450 | if (strcmp(p, request) == 0) { | 1482 | if (strcmp(p, request) == 0) { |
| 1451 | set_remoteuser_var: | 1483 | set_remoteuser_var: |
| 1452 | config->remoteuser = strdup(request); | 1484 | remoteuser = strdup(request); |
| 1453 | if (config->remoteuser) | 1485 | if (remoteuser) |
| 1454 | config->remoteuser[(u - request)] = 0; | 1486 | remoteuser[(u - request)] = 0; |
| 1455 | return 1; /* Ok */ | 1487 | return 1; /* Ok */ |
| 1456 | } | 1488 | } |
| 1457 | /* unauthorized */ | 1489 | /* unauthorized */ |
| @@ -1474,7 +1506,7 @@ set_remoteuser_var: | |||
| 1474 | static void handle_sigalrm(int sig) | 1506 | static void handle_sigalrm(int sig) |
| 1475 | { | 1507 | { |
| 1476 | sendHeaders(HTTP_REQUEST_TIMEOUT); | 1508 | sendHeaders(HTTP_REQUEST_TIMEOUT); |
| 1477 | config->alarm_signaled = sig; | 1509 | alarm_signaled = 1; |
| 1478 | } | 1510 | } |
| 1479 | 1511 | ||
| 1480 | /**************************************************************************** | 1512 | /**************************************************************************** |
| @@ -1486,7 +1518,7 @@ static void handle_sigalrm(int sig) | |||
| 1486 | ****************************************************************************/ | 1518 | ****************************************************************************/ |
| 1487 | static void handleIncoming(void) | 1519 | static void handleIncoming(void) |
| 1488 | { | 1520 | { |
| 1489 | char *buf = config->buf; | 1521 | char *buf = iobuf; |
| 1490 | char *url; | 1522 | char *url; |
| 1491 | char *purl; | 1523 | char *purl; |
| 1492 | int blank = -1; | 1524 | int blank = -1; |
| @@ -1556,10 +1588,10 @@ static void handleIncoming(void) | |||
| 1556 | strcpy(url, buf); | 1588 | strcpy(url, buf); |
| 1557 | /* extract url args if present */ | 1589 | /* extract url args if present */ |
| 1558 | test = strchr(url, '?'); | 1590 | test = strchr(url, '?'); |
| 1559 | config->query = NULL; | 1591 | g_query = NULL; |
| 1560 | if (test) { | 1592 | if (test) { |
| 1561 | *test++ = '\0'; | 1593 | *test++ = '\0'; |
| 1562 | config->query = test; | 1594 | g_query = test; |
| 1563 | } | 1595 | } |
| 1564 | 1596 | ||
| 1565 | test = decodeString(url, 0); | 1597 | test = decodeString(url, 0); |
| @@ -1605,11 +1637,11 @@ static void handleIncoming(void) | |||
| 1605 | /* If URL is directory, adding '/' */ | 1637 | /* If URL is directory, adding '/' */ |
| 1606 | if (test[-1] != '/') { | 1638 | if (test[-1] != '/') { |
| 1607 | if (is_directory(url + 1, 1, &sb)) { | 1639 | if (is_directory(url + 1, 1, &sb)) { |
| 1608 | config->found_moved_temporarily = url; | 1640 | found_moved_temporarily = url; |
| 1609 | } | 1641 | } |
| 1610 | } | 1642 | } |
| 1611 | if (DEBUG) | 1643 | if (DEBUG) |
| 1612 | fprintf(stderr, "url='%s', args=%s\n", url, config->query); | 1644 | fprintf(stderr, "url='%s', args=%s\n", url, g_query); |
| 1613 | 1645 | ||
| 1614 | test = url; | 1646 | test = url; |
| 1615 | ip_allowed = checkPermIP(); | 1647 | ip_allowed = checkPermIP(); |
| @@ -1656,7 +1688,7 @@ static void handleIncoming(void) | |||
| 1656 | } else if ((STRNCASECMP(buf, "Content-Type:") == 0)) { | 1688 | } else if ((STRNCASECMP(buf, "Content-Type:") == 0)) { |
| 1657 | content_type = strdup(skip_whitespace(buf + sizeof("Content-Type:")-1)); | 1689 | content_type = strdup(skip_whitespace(buf + sizeof("Content-Type:")-1)); |
| 1658 | } else if ((STRNCASECMP(buf, "Referer:") == 0)) { | 1690 | } else if ((STRNCASECMP(buf, "Referer:") == 0)) { |
| 1659 | config->referer = strdup(skip_whitespace(buf + sizeof("Referer:")-1)); | 1691 | referer = strdup(skip_whitespace(buf + sizeof("Referer:")-1)); |
| 1660 | } | 1692 | } |
| 1661 | #endif | 1693 | #endif |
| 1662 | 1694 | ||
| @@ -1679,7 +1711,7 @@ static void handleIncoming(void) | |||
| 1679 | } /* while extra header reading */ | 1711 | } /* while extra header reading */ |
| 1680 | } | 1712 | } |
| 1681 | alarm(0); | 1713 | alarm(0); |
| 1682 | if (config->alarm_signaled) | 1714 | if (alarm_signaled) |
| 1683 | break; | 1715 | break; |
| 1684 | 1716 | ||
| 1685 | if (strcmp(strrchr(url, '/') + 1, httpd_conf) == 0 || ip_allowed == 0) { | 1717 | if (strcmp(strrchr(url, '/') + 1, httpd_conf) == 0 || ip_allowed == 0) { |
| @@ -1698,10 +1730,10 @@ static void handleIncoming(void) | |||
| 1698 | } | 1730 | } |
| 1699 | #endif | 1731 | #endif |
| 1700 | 1732 | ||
| 1701 | if (config->found_moved_temporarily) { | 1733 | if (found_moved_temporarily) { |
| 1702 | sendHeaders(HTTP_MOVED_TEMPORARILY); | 1734 | sendHeaders(HTTP_MOVED_TEMPORARILY); |
| 1703 | /* clear unforked memory flag */ | 1735 | /* clear unforked memory flag */ |
| 1704 | config->found_moved_temporarily = NULL; | 1736 | found_moved_temporarily = NULL; |
| 1705 | break; | 1737 | break; |
| 1706 | } | 1738 | } |
| 1707 | 1739 | ||
| @@ -1719,7 +1751,7 @@ static void handleIncoming(void) | |||
| 1719 | char *suffix = strrchr(test, '.'); | 1751 | char *suffix = strrchr(test, '.'); |
| 1720 | if (suffix) { | 1752 | if (suffix) { |
| 1721 | Htaccess *cur; | 1753 | Htaccess *cur; |
| 1722 | for (cur = config->script_i; cur; cur = cur->next) { | 1754 | for (cur = script_i; cur; cur = cur->next) { |
| 1723 | if (strcmp(cur->before_colon + 1, suffix) == 0) { | 1755 | if (strcmp(cur->before_colon + 1, suffix) == 0) { |
| 1724 | sendCgi(url, prequest, length, cookie, content_type); | 1756 | sendCgi(url, prequest, length, cookie, content_type); |
| 1725 | goto bail_out; | 1757 | goto bail_out; |
| @@ -1737,8 +1769,8 @@ static void handleIncoming(void) | |||
| 1737 | strcpy(purl, "index.html"); | 1769 | strcpy(purl, "index.html"); |
| 1738 | if (stat(test, &sb) == 0) { | 1770 | if (stat(test, &sb) == 0) { |
| 1739 | /* It's a dir URL and there is index.html */ | 1771 | /* It's a dir URL and there is index.html */ |
| 1740 | config->ContentLength = sb.st_size; | 1772 | ContentLength = sb.st_size; |
| 1741 | config->last_mod = sb.st_mtime; | 1773 | last_mod = sb.st_mtime; |
| 1742 | } | 1774 | } |
| 1743 | #if ENABLE_FEATURE_HTTPD_CGI | 1775 | #if ENABLE_FEATURE_HTTPD_CGI |
| 1744 | else if (purl[-1] == '/') { | 1776 | else if (purl[-1] == '/') { |
| @@ -1746,14 +1778,14 @@ static void handleIncoming(void) | |||
| 1746 | * Try cgi-bin/index.cgi */ | 1778 | * Try cgi-bin/index.cgi */ |
| 1747 | if (access("/cgi-bin/index.cgi"+1, X_OK) == 0) { | 1779 | if (access("/cgi-bin/index.cgi"+1, X_OK) == 0) { |
| 1748 | purl[0] = '\0'; | 1780 | purl[0] = '\0'; |
| 1749 | config->query = url; | 1781 | g_query = url; |
| 1750 | sendCgi("/cgi-bin/index.cgi", prequest, length, cookie, content_type); | 1782 | sendCgi("/cgi-bin/index.cgi", prequest, length, cookie, content_type); |
| 1751 | break; | 1783 | break; |
| 1752 | } | 1784 | } |
| 1753 | } | 1785 | } |
| 1754 | #endif /* FEATURE_HTTPD_CGI */ | 1786 | #endif /* FEATURE_HTTPD_CGI */ |
| 1755 | sendFile(test); | 1787 | sendFile(test); |
| 1756 | config->ContentLength = -1; | 1788 | ContentLength = -1; |
| 1757 | } while (0); | 1789 | } while (0); |
| 1758 | 1790 | ||
| 1759 | #if ENABLE_FEATURE_HTTPD_CGI | 1791 | #if ENABLE_FEATURE_HTTPD_CGI |
| @@ -1765,28 +1797,28 @@ static void handleIncoming(void) | |||
| 1765 | #if ENABLE_FEATURE_HTTPD_CGI | 1797 | #if ENABLE_FEATURE_HTTPD_CGI |
| 1766 | free(cookie); | 1798 | free(cookie); |
| 1767 | free(content_type); | 1799 | free(content_type); |
| 1768 | free(config->referer); | 1800 | free(referer); |
| 1769 | config->referer = NULL; | 1801 | referer = NULL; |
| 1770 | # if ENABLE_FEATURE_HTTPD_BASIC_AUTH | 1802 | # if ENABLE_FEATURE_HTTPD_BASIC_AUTH |
| 1771 | free(config->remoteuser); | 1803 | free(remoteuser); |
| 1772 | config->remoteuser = NULL; | 1804 | remoteuser = NULL; |
| 1773 | # endif | 1805 | # endif |
| 1774 | #endif | 1806 | #endif |
| 1775 | shutdown(config->accepted_socket, SHUT_WR); | 1807 | shutdown(accepted_socket, SHUT_WR); |
| 1776 | 1808 | ||
| 1777 | /* Properly wait for remote to closed */ | 1809 | /* Properly wait for remote to closed */ |
| 1778 | FD_ZERO(&s_fd); | 1810 | FD_ZERO(&s_fd); |
| 1779 | FD_SET(config->accepted_socket, &s_fd); | 1811 | FD_SET(accepted_socket, &s_fd); |
| 1780 | 1812 | ||
| 1781 | do { | 1813 | do { |
| 1782 | tv.tv_sec = 2; | 1814 | tv.tv_sec = 2; |
| 1783 | tv.tv_usec = 0; | 1815 | tv.tv_usec = 0; |
| 1784 | retval = select(config->accepted_socket + 1, &s_fd, NULL, NULL, &tv); | 1816 | retval = select(accepted_socket + 1, &s_fd, NULL, NULL, &tv); |
| 1785 | } while (retval > 0 && read(config->accepted_socket, buf, sizeof(config->buf) > 0)); | 1817 | } while (retval > 0 && read(accepted_socket, buf, sizeof(iobuf) > 0)); |
| 1786 | 1818 | ||
| 1787 | shutdown(config->accepted_socket, SHUT_RD); | 1819 | shutdown(accepted_socket, SHUT_RD); |
| 1788 | /* In inetd case, we close fd 1 (stdout) here. We will exit soon anyway */ | 1820 | /* In inetd case, we close fd 1 (stdout) here. We will exit soon anyway */ |
| 1789 | close(config->accepted_socket); | 1821 | close(accepted_socket); |
| 1790 | } | 1822 | } |
| 1791 | 1823 | ||
| 1792 | /**************************************************************************** | 1824 | /**************************************************************************** |
| @@ -1830,24 +1862,24 @@ static int miniHttpd(int server) | |||
| 1830 | s = accept(server, &fromAddr.sa, &fromAddrLen); | 1862 | s = accept(server, &fromAddr.sa, &fromAddrLen); |
| 1831 | if (s < 0) | 1863 | if (s < 0) |
| 1832 | continue; | 1864 | continue; |
| 1833 | config->accepted_socket = s; | 1865 | accepted_socket = s; |
| 1834 | config->rmt_ip = 0; | 1866 | rmt_ip = 0; |
| 1835 | config->port = 0; | 1867 | tcp_port = 0; |
| 1836 | #if ENABLE_FEATURE_HTTPD_CGI || DEBUG | 1868 | #if ENABLE_FEATURE_HTTPD_CGI || DEBUG |
| 1837 | free(config->rmt_ip_str); | 1869 | free(rmt_ip_str); |
| 1838 | config->rmt_ip_str = xmalloc_sockaddr2dotted(&fromAddr.sa, fromAddrLen); | 1870 | rmt_ip_str = xmalloc_sockaddr2dotted(&fromAddr.sa, fromAddrLen); |
| 1839 | #if DEBUG | 1871 | #if DEBUG |
| 1840 | bb_error_msg("connection from '%s'", config->rmt_ip_str); | 1872 | bb_error_msg("connection from '%s'", rmt_ip_str); |
| 1841 | #endif | 1873 | #endif |
| 1842 | #endif /* FEATURE_HTTPD_CGI */ | 1874 | #endif /* FEATURE_HTTPD_CGI */ |
| 1843 | if (fromAddr.sa.sa_family == AF_INET) { | 1875 | if (fromAddr.sa.sa_family == AF_INET) { |
| 1844 | config->rmt_ip = ntohl(fromAddr.sin.sin_addr.s_addr); | 1876 | rmt_ip = ntohl(fromAddr.sin.sin_addr.s_addr); |
| 1845 | config->port = ntohs(fromAddr.sin.sin_port); | 1877 | tcp_port = ntohs(fromAddr.sin.sin_port); |
| 1846 | } | 1878 | } |
| 1847 | #if ENABLE_FEATURE_IPV6 | 1879 | #if ENABLE_FEATURE_IPV6 |
| 1848 | if (fromAddr.sa.sa_family == AF_INET6) { | 1880 | if (fromAddr.sa.sa_family == AF_INET6) { |
| 1849 | //config->rmt_ip = ntohl(fromAddr.sin.sin_addr.s_addr); | 1881 | //rmt_ip = ntohl(fromAddr.sin.sin_addr.s_addr); |
| 1850 | config->port = ntohs(fromAddr.sin6.sin6_port); | 1882 | tcp_port = ntohs(fromAddr.sin6.sin6_port); |
| 1851 | } | 1883 | } |
| 1852 | #endif | 1884 | #endif |
| 1853 | 1885 | ||
| @@ -1880,20 +1912,20 @@ static int miniHttpd_inetd(void) | |||
| 1880 | socklen_t fromAddrLen = sizeof(fromAddr); | 1912 | socklen_t fromAddrLen = sizeof(fromAddr); |
| 1881 | 1913 | ||
| 1882 | getpeername(0, &fromAddr.sa, &fromAddrLen); | 1914 | getpeername(0, &fromAddr.sa, &fromAddrLen); |
| 1883 | config->rmt_ip = 0; | 1915 | rmt_ip = 0; |
| 1884 | config->port = 0; | 1916 | tcp_port = 0; |
| 1885 | #if ENABLE_FEATURE_HTTPD_CGI || DEBUG | 1917 | #if ENABLE_FEATURE_HTTPD_CGI || DEBUG |
| 1886 | free(config->rmt_ip_str); | 1918 | free(rmt_ip_str); |
| 1887 | config->rmt_ip_str = xmalloc_sockaddr2dotted(&fromAddr.sa, fromAddrLen); | 1919 | rmt_ip_str = xmalloc_sockaddr2dotted(&fromAddr.sa, fromAddrLen); |
| 1888 | #endif | 1920 | #endif |
| 1889 | if (fromAddr.sa.sa_family == AF_INET) { | 1921 | if (fromAddr.sa.sa_family == AF_INET) { |
| 1890 | config->rmt_ip = ntohl(fromAddr.sin.sin_addr.s_addr); | 1922 | rmt_ip = ntohl(fromAddr.sin.sin_addr.s_addr); |
| 1891 | config->port = ntohs(fromAddr.sin.sin_port); | 1923 | tcp_port = ntohs(fromAddr.sin.sin_port); |
| 1892 | } | 1924 | } |
| 1893 | #if ENABLE_FEATURE_IPV6 | 1925 | #if ENABLE_FEATURE_IPV6 |
| 1894 | if (fromAddr.sa.sa_family == AF_INET6) { | 1926 | if (fromAddr.sa.sa_family == AF_INET6) { |
| 1895 | //config->rmt_ip = ntohl(fromAddr.sin.sin_addr.s_addr); | 1927 | //rmt_ip = ntohl(fromAddr.sin.sin_addr.s_addr); |
| 1896 | config->port = ntohs(fromAddr.sin6.sin6_port); | 1928 | tcp_port = ntohs(fromAddr.sin6.sin6_port); |
| 1897 | } | 1929 | } |
| 1898 | #endif | 1930 | #endif |
| 1899 | handleIncoming(); | 1931 | handleIncoming(); |
| @@ -1942,7 +1974,6 @@ int httpd_main(int argc, char **argv); | |||
| 1942 | int httpd_main(int argc, char **argv) | 1974 | int httpd_main(int argc, char **argv) |
| 1943 | { | 1975 | { |
| 1944 | unsigned opt; | 1976 | unsigned opt; |
| 1945 | const char *home_httpd = home; | ||
| 1946 | char *url_for_decode; | 1977 | char *url_for_decode; |
| 1947 | USE_FEATURE_HTTPD_ENCODE_URL_STR(const char *url_for_encode;) | 1978 | USE_FEATURE_HTTPD_ENCODE_URL_STR(const char *url_for_encode;) |
| 1948 | const char *s_port; | 1979 | const char *s_port; |
| @@ -1955,22 +1986,20 @@ int httpd_main(int argc, char **argv) | |||
| 1955 | setlocale(LC_TIME, "C"); | 1986 | setlocale(LC_TIME, "C"); |
| 1956 | #endif | 1987 | #endif |
| 1957 | 1988 | ||
| 1958 | config = xzalloc(sizeof(*config)); | 1989 | INIT_G(); |
| 1959 | #if ENABLE_FEATURE_HTTPD_BASIC_AUTH | 1990 | home_httpd = xrealloc_getcwd_or_warn(NULL); |
| 1960 | config->realm = "Web Server Authentication"; | 1991 | /* We do not "absolutize" path given by -h (home) opt. |
| 1961 | #endif | 1992 | * If user gives relative path in -h, $SCRIPT_FILENAME can end up |
| 1962 | config->port = 80; | 1993 | * relative too. */ |
| 1963 | config->ContentLength = -1; | ||
| 1964 | |||
| 1965 | opt = getopt32(argc, argv, "c:d:h:" | 1994 | opt = getopt32(argc, argv, "c:d:h:" |
| 1966 | USE_FEATURE_HTTPD_ENCODE_URL_STR("e:") | 1995 | USE_FEATURE_HTTPD_ENCODE_URL_STR("e:") |
| 1967 | USE_FEATURE_HTTPD_BASIC_AUTH("r:") | 1996 | USE_FEATURE_HTTPD_BASIC_AUTH("r:") |
| 1968 | USE_FEATURE_HTTPD_AUTH_MD5("m:") | 1997 | USE_FEATURE_HTTPD_AUTH_MD5("m:") |
| 1969 | USE_FEATURE_HTTPD_SETUID("u:") | 1998 | USE_FEATURE_HTTPD_SETUID("u:") |
| 1970 | "p:if", | 1999 | "p:if", |
| 1971 | &(config->configFile), &url_for_decode, &home_httpd | 2000 | &(configFile), &url_for_decode, &home_httpd |
| 1972 | USE_FEATURE_HTTPD_ENCODE_URL_STR(, &url_for_encode) | 2001 | USE_FEATURE_HTTPD_ENCODE_URL_STR(, &url_for_encode) |
| 1973 | USE_FEATURE_HTTPD_BASIC_AUTH(, &(config->realm)) | 2002 | USE_FEATURE_HTTPD_BASIC_AUTH(, &g_realm) |
| 1974 | USE_FEATURE_HTTPD_AUTH_MD5(, &pass) | 2003 | USE_FEATURE_HTTPD_AUTH_MD5(, &pass) |
| 1975 | USE_FEATURE_HTTPD_SETUID(, &s_ugid) | 2004 | USE_FEATURE_HTTPD_SETUID(, &s_ugid) |
| 1976 | , &s_port | 2005 | , &s_port |
| @@ -1992,7 +2021,7 @@ int httpd_main(int argc, char **argv) | |||
| 1992 | } | 2021 | } |
| 1993 | #endif | 2022 | #endif |
| 1994 | if (opt & OPT_PORT) | 2023 | if (opt & OPT_PORT) |
| 1995 | config->port = xatou16(s_port); | 2024 | tcp_port = xatou16(s_port); |
| 1996 | 2025 | ||
| 1997 | #if ENABLE_FEATURE_HTTPD_SETUID | 2026 | #if ENABLE_FEATURE_HTTPD_SETUID |
| 1998 | if (opt & OPT_SETUID) { | 2027 | if (opt & OPT_SETUID) { |
| @@ -2005,7 +2034,7 @@ int httpd_main(int argc, char **argv) | |||
| 2005 | xchdir(home_httpd); | 2034 | xchdir(home_httpd); |
| 2006 | if (!(opt & OPT_INETD)) { | 2035 | if (!(opt & OPT_INETD)) { |
| 2007 | signal(SIGCHLD, SIG_IGN); | 2036 | signal(SIGCHLD, SIG_IGN); |
| 2008 | config->server_socket = openServer(); | 2037 | server_socket = openServer(); |
| 2009 | #if ENABLE_FEATURE_HTTPD_SETUID | 2038 | #if ENABLE_FEATURE_HTTPD_SETUID |
| 2010 | /* drop privileges */ | 2039 | /* drop privileges */ |
| 2011 | if (opt & OPT_SETUID) { | 2040 | if (opt & OPT_SETUID) { |
| @@ -2022,12 +2051,12 @@ int httpd_main(int argc, char **argv) | |||
| 2022 | #if ENABLE_FEATURE_HTTPD_CGI | 2051 | #if ENABLE_FEATURE_HTTPD_CGI |
| 2023 | { | 2052 | { |
| 2024 | char *p = getenv("PATH"); | 2053 | char *p = getenv("PATH"); |
| 2025 | p = xstrdup(p); /* if gets NULL, returns NULL */ | 2054 | /* env strings themself are not freed, no need to strdup(p): */ |
| 2026 | clearenv(); | 2055 | clearenv(); |
| 2027 | if (p) | 2056 | if (p) |
| 2028 | setenv1("PATH", p); | 2057 | putenv(p - 5); |
| 2029 | if (!(opt & OPT_INETD)) | 2058 | if (!(opt & OPT_INETD)) |
| 2030 | setenv_long("SERVER_PORT", config->port); | 2059 | setenv_long("SERVER_PORT", tcp_port); |
| 2031 | } | 2060 | } |
| 2032 | #endif | 2061 | #endif |
| 2033 | 2062 | ||
| @@ -2042,5 +2071,5 @@ int httpd_main(int argc, char **argv) | |||
| 2042 | 2071 | ||
| 2043 | if (!(opt & OPT_FOREGROUND)) | 2072 | if (!(opt & OPT_FOREGROUND)) |
| 2044 | bb_daemonize(0); /* don't change current directory */ | 2073 | bb_daemonize(0); /* don't change current directory */ |
| 2045 | return miniHttpd(config->server_socket); | 2074 | return miniHttpd(server_socket); |
| 2046 | } | 2075 | } |
