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 | } |