diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2007-08-14 16:55:01 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2007-08-14 16:55:01 +0000 |
commit | 384b1d12f957a3a4c80fb32bc29cb79c282ac361 (patch) | |
tree | 8011c52fb98f2613626edfcd879508bc5c45d66a | |
parent | 0372f0f1999ace825a2265ad03b80be627b039fb (diff) | |
download | busybox-w32-384b1d12f957a3a4c80fb32bc29cb79c282ac361.tar.gz busybox-w32-384b1d12f957a3a4c80fb32bc29cb79c282ac361.tar.bz2 busybox-w32-384b1d12f957a3a4c80fb32bc29cb79c282ac361.zip |
httpd: add -v[v]: prints client addresses, HTTP codes returned [and URLs]
get_line - 70 +70
packed_usage 22811 22863 +52
handle_incoming_and_exit 2246 2277 +31
httpd_main 1141 1155 +14
sendHeaders 489 482 -7
getLine 77 - -77
------------------------------------------------------------------------------
(add/remove: 1/1 grow/shrink: 3/1 up/down: 167/-84) Total: 83 bytes
text data bss dec hex filename
774335 1058 11092 786485 c0035 busybox_old
774447 1058 11092 786597 c00a5 busybox_unstripped
-rw-r--r-- | include/usage.h | 9 | ||||
-rw-r--r-- | libbb/xfuncs.c | 12 | ||||
-rw-r--r-- | networking/httpd.c | 242 |
3 files changed, 128 insertions, 135 deletions
diff --git a/include/usage.h b/include/usage.h index 41459e8c3..d9e2857e8 100644 --- a/include/usage.h +++ b/include/usage.h | |||
@@ -1344,8 +1344,8 @@ | |||
1344 | 1344 | ||
1345 | #define httpd_trivial_usage \ | 1345 | #define httpd_trivial_usage \ |
1346 | "[-c conffile]" \ | 1346 | "[-c conffile]" \ |
1347 | " [-p port]" \ | 1347 | " [-p [ip:]port]" \ |
1348 | " [-i] [-f]" \ | 1348 | " [-i] [-f] [-v[v]]" \ |
1349 | USE_FEATURE_HTTPD_SETUID(" [-u user[:grp]]") \ | 1349 | USE_FEATURE_HTTPD_SETUID(" [-u user[:grp]]") \ |
1350 | USE_FEATURE_HTTPD_BASIC_AUTH(" [-r realm]") \ | 1350 | USE_FEATURE_HTTPD_BASIC_AUTH(" [-r realm]") \ |
1351 | USE_FEATURE_HTTPD_AUTH_MD5(" [-m pass]") \ | 1351 | USE_FEATURE_HTTPD_AUTH_MD5(" [-m pass]") \ |
@@ -1355,9 +1355,10 @@ | |||
1355 | "Listen for incoming HTTP requests" \ | 1355 | "Listen for incoming HTTP requests" \ |
1356 | "\n\nOptions:" \ | 1356 | "\n\nOptions:" \ |
1357 | "\n -c FILE Configuration file (default httpd.conf)" \ | 1357 | "\n -c FILE Configuration file (default httpd.conf)" \ |
1358 | "\n -p PORT Server port (default 80)" \ | 1358 | "\n -p [IP:]PORT Bind to ip:port (default *:80)" \ |
1359 | "\n -i Inetd mode" \ | 1359 | "\n -i Inetd mode" \ |
1360 | "\n -f Do not daemonize" \ | 1360 | "\n -f Do not daemonize" \ |
1361 | "\n -v[v] Verbose" \ | ||
1361 | USE_FEATURE_HTTPD_SETUID( \ | 1362 | USE_FEATURE_HTTPD_SETUID( \ |
1362 | "\n -u USER[:GRP] Set uid/gid after binding to port") \ | 1363 | "\n -u USER[:GRP] Set uid/gid after binding to port") \ |
1363 | USE_FEATURE_HTTPD_BASIC_AUTH( \ | 1364 | USE_FEATURE_HTTPD_BASIC_AUTH( \ |
@@ -1366,7 +1367,7 @@ | |||
1366 | "\n -m PASS Crypt PASS with md5 algorithm") \ | 1367 | "\n -m PASS Crypt PASS with md5 algorithm") \ |
1367 | "\n -h HOME Home directory (default .)" \ | 1368 | "\n -h HOME Home directory (default .)" \ |
1368 | "\n -e STRING HTML encode STRING" \ | 1369 | "\n -e STRING HTML encode STRING" \ |
1369 | "\n -d STRING URL decode STRING" | 1370 | "\n -d STRING URL decode STRING" \ |
1370 | 1371 | ||
1371 | #define hwclock_trivial_usage \ | 1372 | #define hwclock_trivial_usage \ |
1372 | "[-r|--show] [-s|--hctosys] [-w|--systohc]" \ | 1373 | "[-r|--show] [-s|--hctosys] [-w|--systohc]" \ |
diff --git a/libbb/xfuncs.c b/libbb/xfuncs.c index 67c986640..4e17c28bd 100644 --- a/libbb/xfuncs.c +++ b/libbb/xfuncs.c | |||
@@ -484,12 +484,14 @@ int fdprintf(int fd, const char *format, ...) | |||
484 | #else | 484 | #else |
485 | // Bloat for systems that haven't got the GNU extension. | 485 | // Bloat for systems that haven't got the GNU extension. |
486 | va_start(p, format); | 486 | va_start(p, format); |
487 | r = vsnprintf(NULL, 0, format, p); | 487 | r = vsnprintf(NULL, 0, format, p) + 1; |
488 | va_end(p); | ||
489 | string_ptr = xmalloc(r+1); | ||
490 | va_start(p, format); | ||
491 | r = vsnprintf(string_ptr, r+1, format, p); | ||
492 | va_end(p); | 488 | va_end(p); |
489 | string_ptr = malloc(r); | ||
490 | if (string_ptr) { | ||
491 | va_start(p, format); | ||
492 | r = vsnprintf(string_ptr, r, format, p); | ||
493 | va_end(p); | ||
494 | } | ||
493 | #endif | 495 | #endif |
494 | 496 | ||
495 | if (r >= 0) { | 497 | if (r >= 0) { |
diff --git a/networking/httpd.c b/networking/httpd.c index 875b9d641..9a9489ed5 100644 --- a/networking/httpd.c +++ b/networking/httpd.c | |||
@@ -132,17 +132,22 @@ typedef struct Htaccess_IP { | |||
132 | struct globals { | 132 | struct globals { |
133 | int server_socket; | 133 | int server_socket; |
134 | int accepted_socket; | 134 | int accepted_socket; |
135 | int verbose; | ||
135 | volatile smallint alarm_signaled; | 136 | volatile smallint alarm_signaled; |
136 | smallint flg_deny_all; | 137 | smallint flg_deny_all; |
138 | |||
139 | unsigned rmt_ip; | ||
140 | unsigned tcp_port; /* for set env REMOTE_PORT */ | ||
141 | const char *bind_addr_or_port; | ||
142 | |||
137 | const char *g_query; | 143 | const char *g_query; |
138 | const char *configFile; | 144 | const char *configFile; |
139 | const char *home_httpd; | 145 | const char *home_httpd; |
140 | unsigned rmt_ip; | ||
141 | 146 | ||
142 | const char *found_mime_type; | 147 | const char *found_mime_type; |
143 | const char *found_moved_temporarily; | 148 | const char *found_moved_temporarily; |
144 | off_t ContentLength; /* -1 - unknown */ | ||
145 | time_t last_mod; | 149 | time_t last_mod; |
150 | off_t ContentLength; /* -1 - unknown */ | ||
146 | Htaccess_IP *ip_a_d; /* config allow/deny lines */ | 151 | Htaccess_IP *ip_a_d; /* config allow/deny lines */ |
147 | 152 | ||
148 | USE_FEATURE_HTTPD_BASIC_AUTH(const char *g_realm;) | 153 | USE_FEATURE_HTTPD_BASIC_AUTH(const char *g_realm;) |
@@ -150,11 +155,7 @@ struct globals { | |||
150 | USE_FEATURE_HTTPD_CGI(char *referer;) | 155 | USE_FEATURE_HTTPD_CGI(char *referer;) |
151 | USE_FEATURE_HTTPD_CGI(char *user_agent;) | 156 | USE_FEATURE_HTTPD_CGI(char *user_agent;) |
152 | 157 | ||
153 | #if ENABLE_FEATURE_HTTPD_CGI || DEBUG | ||
154 | char *rmt_ip_str; /* for set env REMOTE_ADDR */ | 158 | char *rmt_ip_str; /* for set env REMOTE_ADDR */ |
155 | #endif | ||
156 | const char *bind_addr_or_port; | ||
157 | unsigned tcp_port; /* for set env REMOTE_PORT */ | ||
158 | 159 | ||
159 | #if ENABLE_FEATURE_HTTPD_BASIC_AUTH | 160 | #if ENABLE_FEATURE_HTTPD_BASIC_AUTH |
160 | Htaccess *g_auth; /* config user:password lines */ | 161 | Htaccess *g_auth; /* config user:password lines */ |
@@ -168,38 +169,31 @@ struct globals { | |||
168 | char iobuf[MAX_MEMORY_BUF]; | 169 | char iobuf[MAX_MEMORY_BUF]; |
169 | }; | 170 | }; |
170 | #define G (*ptr_to_globals) | 171 | #define G (*ptr_to_globals) |
171 | #define server_socket (G.server_socket ) | 172 | #define server_socket (G.server_socket ) |
172 | #define accepted_socket (G.accepted_socket) | 173 | #define accepted_socket (G.accepted_socket ) |
173 | #define alarm_signaled (G.alarm_signaled ) | 174 | #define verbose (G.verbose ) |
174 | #define flg_deny_all (G.flg_deny_all ) | 175 | #define alarm_signaled (G.alarm_signaled ) |
175 | #define g_query (G.g_query ) | 176 | #define flg_deny_all (G.flg_deny_all ) |
176 | #define configFile (G.configFile ) | 177 | #define rmt_ip (G.rmt_ip ) |
177 | #define home_httpd (G.home_httpd ) | 178 | #define tcp_port (G.tcp_port ) |
178 | #define rmt_ip (G.rmt_ip ) | ||
179 | #define found_mime_type (G.found_mime_type) | ||
180 | #define found_moved_temporarily (G.found_moved_temporarily) | ||
181 | #define ContentLength (G.ContentLength ) | ||
182 | #define last_mod (G.last_mod ) | ||
183 | #define ip_a_d (G.ip_a_d ) | ||
184 | #define g_realm (G.g_realm ) | ||
185 | #define remoteuser (G.remoteuser ) | ||
186 | #define referer (G.referer ) | ||
187 | #define user_agent (G.user_agent ) | ||
188 | #if ENABLE_FEATURE_HTTPD_CGI || DEBUG | ||
189 | #define rmt_ip_str (G.rmt_ip_str ) | ||
190 | #endif | ||
191 | #define bind_addr_or_port (G.bind_addr_or_port) | 179 | #define bind_addr_or_port (G.bind_addr_or_port) |
192 | #define tcp_port (G.tcp_port ) | 180 | #define g_query (G.g_query ) |
193 | #if ENABLE_FEATURE_HTTPD_BASIC_AUTH | 181 | #define configFile (G.configFile ) |
194 | #define g_auth (G.g_auth ) | 182 | #define home_httpd (G.home_httpd ) |
195 | #endif | 183 | #define found_mime_type (G.found_mime_type ) |
196 | #if ENABLE_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES | 184 | #define found_moved_temporarily (G.found_moved_temporarily) |
197 | #define mime_a (G.mime_a ) | 185 | #define ContentLength (G.ContentLength ) |
198 | #endif | 186 | #define last_mod (G.last_mod ) |
199 | #if ENABLE_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR | 187 | #define ip_a_d (G.ip_a_d ) |
200 | #define script_i (G.script_i ) | 188 | #define g_realm (G.g_realm ) |
201 | #endif | 189 | #define remoteuser (G.remoteuser ) |
202 | #define iobuf (G.iobuf ) | 190 | #define referer (G.referer ) |
191 | #define user_agent (G.user_agent ) | ||
192 | #define rmt_ip_str (G.rmt_ip_str ) | ||
193 | #define g_auth (G.g_auth ) | ||
194 | #define mime_a (G.mime_a ) | ||
195 | #define script_i (G.script_i ) | ||
196 | #define iobuf (G.iobuf ) | ||
203 | #define INIT_G() do { \ | 197 | #define INIT_G() do { \ |
204 | PTR_TO_GLOBALS = xzalloc(sizeof(G)); \ | 198 | PTR_TO_GLOBALS = xzalloc(sizeof(G)); \ |
205 | USE_FEATURE_HTTPD_BASIC_AUTH(g_realm = "Web Server Authentication";) \ | 199 | USE_FEATURE_HTTPD_BASIC_AUTH(g_realm = "Web Server Authentication";) \ |
@@ -210,7 +204,7 @@ struct globals { | |||
210 | static const char request_GET[] ALIGN1 = "GET"; /* size algorithmic optimize */ | 204 | static const char request_GET[] ALIGN1 = "GET"; /* size algorithmic optimize */ |
211 | 205 | ||
212 | static const char *const suffixTable[] = { | 206 | static const char *const suffixTable[] = { |
213 | /* Warning: shorted equivalent suffix in one line must be first */ | 207 | /* Warning: shorter equivalent suffix in one line must be first */ |
214 | ".htm.html", "text/html", | 208 | ".htm.html", "text/html", |
215 | ".jpg.jpeg", "image/jpeg", | 209 | ".jpg.jpeg", "image/jpeg", |
216 | ".gif", "image/gif", | 210 | ".gif", "image/gif", |
@@ -780,24 +774,14 @@ static void setenv_long(const char *name, long value) | |||
780 | #endif | 774 | #endif |
781 | 775 | ||
782 | #if ENABLE_FEATURE_HTTPD_BASIC_AUTH | 776 | #if ENABLE_FEATURE_HTTPD_BASIC_AUTH |
783 | /**************************************************************************** | 777 | /* |
784 | * | 778 | * Decode a base 64 data stream as per rfc1521. |
785 | > $Function: decodeBase64() | 779 | * Note that the rfc states that non base64 chars are to be ignored. |
786 | * | 780 | * Since the decode always results in a shorter size than the input, it is |
787 | > $Description: Decode a base 64 data stream as per rfc1521. | 781 | * OK to pass the input arg as an output arg. |
788 | * Note that the rfc states that none base64 chars are to be ignored. | 782 | * Parameter: a pointer to a base64 encoded string. |
789 | * Since the decode always results in a shorter size than the input, it is | 783 | * Decoded data is stored in-place. |
790 | * OK to pass the input arg as an output arg. | 784 | */ |
791 | * | ||
792 | * $Parameter: | ||
793 | * (char *) Data . . . . A pointer to a base64 encoded string. | ||
794 | * Where to place the decoded data. | ||
795 | * | ||
796 | * $Return: void | ||
797 | * | ||
798 | * $Errors: None | ||
799 | * | ||
800 | ****************************************************************************/ | ||
801 | static void decodeBase64(char *Data) | 785 | static void decodeBase64(char *Data) |
802 | { | 786 | { |
803 | const unsigned char *in = (const unsigned char *)Data; | 787 | const unsigned char *in = (const unsigned char *)Data; |
@@ -871,13 +855,12 @@ static int openServer(void) | |||
871 | */ | 855 | */ |
872 | static int sendHeaders(HttpResponseNum responseNum) | 856 | static int sendHeaders(HttpResponseNum responseNum) |
873 | { | 857 | { |
874 | char *const buf = iobuf; // dont really need it? | ||
875 | const char *responseString = ""; | 858 | const char *responseString = ""; |
876 | const char *infoString = 0; | 859 | const char *infoString = NULL; |
877 | const char *mime_type; | 860 | const char *mime_type; |
878 | unsigned i; | 861 | unsigned i; |
879 | time_t timer = time(0); | 862 | time_t timer = time(0); |
880 | char timeStr[80]; | 863 | char tmp_str[80]; |
881 | int len; | 864 | int len; |
882 | 865 | ||
883 | for (i = 0; i < ARRAY_SIZE(httpResponseNames); i++) { | 866 | for (i = 0; i < ARRAY_SIZE(httpResponseNames); i++) { |
@@ -891,54 +874,60 @@ static int sendHeaders(HttpResponseNum responseNum) | |||
891 | mime_type = responseNum == HTTP_OK ? | 874 | mime_type = responseNum == HTTP_OK ? |
892 | found_mime_type : "text/html"; | 875 | found_mime_type : "text/html"; |
893 | 876 | ||
877 | if (verbose) | ||
878 | write(2, iobuf, sprintf(iobuf, "%s response:%u\n", rmt_ip_str, responseNum)); | ||
879 | |||
894 | /* emit the current date */ | 880 | /* emit the current date */ |
895 | strftime(timeStr, sizeof(timeStr), RFC1123FMT, gmtime(&timer)); | 881 | strftime(tmp_str, sizeof(tmp_str), RFC1123FMT, gmtime(&timer)); |
896 | len = sprintf(buf, | 882 | len = sprintf(iobuf, |
897 | "HTTP/1.0 %d %s\r\nContent-type: %s\r\n" | 883 | "HTTP/1.0 %d %s\r\nContent-type: %s\r\n" |
898 | "Date: %s\r\nConnection: close\r\n", | 884 | "Date: %s\r\nConnection: close\r\n", |
899 | responseNum, responseString, mime_type, timeStr); | 885 | responseNum, responseString, mime_type, tmp_str); |
900 | 886 | ||
901 | #if ENABLE_FEATURE_HTTPD_BASIC_AUTH | 887 | #if ENABLE_FEATURE_HTTPD_BASIC_AUTH |
902 | if (responseNum == HTTP_UNAUTHORIZED) { | 888 | if (responseNum == HTTP_UNAUTHORIZED) { |
903 | len += sprintf(buf+len, | 889 | len += sprintf(iobuf + len, |
904 | "WWW-Authenticate: Basic realm=\"%s\"\r\n", | 890 | "WWW-Authenticate: Basic realm=\"%s\"\r\n", |
905 | g_realm); | 891 | g_realm); |
906 | } | 892 | } |
907 | #endif | 893 | #endif |
908 | if (responseNum == HTTP_MOVED_TEMPORARILY) { | 894 | if (responseNum == HTTP_MOVED_TEMPORARILY) { |
909 | len += sprintf(buf+len, "Location: %s/%s%s\r\n", | 895 | len += sprintf(iobuf + len, "Location: %s/%s%s\r\n", |
910 | found_moved_temporarily, | 896 | found_moved_temporarily, |
911 | (g_query ? "?" : ""), | 897 | (g_query ? "?" : ""), |
912 | (g_query ? g_query : "")); | 898 | (g_query ? g_query : "")); |
913 | } | 899 | } |
914 | 900 | ||
915 | if (ContentLength != -1) { /* file */ | 901 | if (ContentLength != -1) { /* file */ |
916 | strftime(timeStr, sizeof(timeStr), RFC1123FMT, gmtime(&last_mod)); | 902 | strftime(tmp_str, sizeof(tmp_str), RFC1123FMT, gmtime(&last_mod)); |
917 | len += sprintf(buf+len, "Last-Modified: %s\r\n%s %"OFF_FMT"d\r\n", | 903 | len += sprintf(iobuf + len, "Last-Modified: %s\r\n%s %"OFF_FMT"d\r\n", |
918 | timeStr, "Content-length:", ContentLength); | 904 | tmp_str, "Content-length:", ContentLength); |
919 | } | 905 | } |
920 | strcat(buf, "\r\n"); | 906 | strcat(iobuf, "\r\n"); |
921 | len += 2; | 907 | len += 2; |
922 | if (infoString) { | 908 | if (infoString) { |
923 | len += sprintf(buf+len, | 909 | len += sprintf(iobuf + len, |
924 | "<HTML><HEAD><TITLE>%d %s</TITLE></HEAD>\n" | 910 | "<HTML><HEAD><TITLE>%d %s</TITLE></HEAD>\n" |
925 | "<BODY><H1>%d %s</H1>\n%s\n</BODY></HTML>\n", | 911 | "<BODY><H1>%d %s</H1>\n%s\n</BODY></HTML>\n", |
926 | responseNum, responseString, | 912 | responseNum, responseString, |
927 | responseNum, responseString, infoString); | 913 | responseNum, responseString, infoString); |
928 | } | 914 | } |
929 | if (DEBUG) | 915 | if (DEBUG) |
930 | fprintf(stderr, "headers: '%s'\n", buf); | 916 | fprintf(stderr, "headers: '%s'\n", iobuf); |
931 | i = accepted_socket; | 917 | i = accepted_socket; |
932 | if (i == 0) i++; /* write to fd #1 in inetd mode */ | 918 | if (i == 0) |
933 | return full_write(i, buf, len); | 919 | i++; /* write to fd #1 in inetd mode */ |
920 | return full_write(i, iobuf, len); | ||
934 | } | 921 | } |
935 | 922 | ||
936 | /* | 923 | /* |
937 | * Read from the socket until '\n' or EOF. '\r' chars are removed. | 924 | * Read from the socket until '\n' or EOF. '\r' chars are removed. |
938 | * Return number of characters read or -1 if nothing is read. | 925 | * '\n' is replaced with NUL. |
926 | * Return number of characters read or 0 if nothing is read | ||
927 | * ('\r' and '\n' are not counted). | ||
939 | * Data is returned in iobuf. | 928 | * Data is returned in iobuf. |
940 | */ | 929 | */ |
941 | static int getLine(void) | 930 | static int get_line(void) |
942 | { | 931 | { |
943 | int count = 0; | 932 | int count = 0; |
944 | 933 | ||
@@ -953,9 +942,7 @@ static int getLine(void) | |||
953 | if (count < (MAX_MEMORY_BUF - 1)) /* check overflow */ | 942 | if (count < (MAX_MEMORY_BUF - 1)) /* check overflow */ |
954 | count++; | 943 | count++; |
955 | } | 944 | } |
956 | if (count) | 945 | return count; |
957 | return count; | ||
958 | return -1; | ||
959 | } | 946 | } |
960 | 947 | ||
961 | #if ENABLE_FEATURE_HTTPD_CGI | 948 | #if ENABLE_FEATURE_HTTPD_CGI |
@@ -1414,11 +1401,10 @@ static int checkPermIP(void) | |||
1414 | 1401 | ||
1415 | /* This could stand some work */ | 1402 | /* This could stand some work */ |
1416 | for (cur = ip_a_d; cur; cur = cur->next) { | 1403 | for (cur = ip_a_d; cur; cur = cur->next) { |
1417 | #if ENABLE_FEATURE_HTTPD_CGI && DEBUG | ||
1418 | fprintf(stderr, "checkPermIP: '%s' ? ", rmt_ip_str); | ||
1419 | #endif | ||
1420 | #if DEBUG | 1404 | #if DEBUG |
1421 | fprintf(stderr, "'%u.%u.%u.%u/%u.%u.%u.%u'\n", | 1405 | fprintf(stderr, |
1406 | "checkPermIP: '%s' ? '%u.%u.%u.%u/%u.%u.%u.%u'\n", | ||
1407 | rmt_ip_str, | ||
1422 | (unsigned char)(cur->ip >> 24), | 1408 | (unsigned char)(cur->ip >> 24), |
1423 | (unsigned char)(cur->ip >> 16), | 1409 | (unsigned char)(cur->ip >> 16), |
1424 | (unsigned char)(cur->ip >> 8), | 1410 | (unsigned char)(cur->ip >> 8), |
@@ -1539,7 +1525,6 @@ static void handle_sigalrm(int sig) | |||
1539 | static void handle_incoming_and_exit(void) ATTRIBUTE_NORETURN; | 1525 | static void handle_incoming_and_exit(void) ATTRIBUTE_NORETURN; |
1540 | static void handle_incoming_and_exit(void) | 1526 | static void handle_incoming_and_exit(void) |
1541 | { | 1527 | { |
1542 | char *buf = iobuf; | ||
1543 | char *url; | 1528 | char *url; |
1544 | char *purl; | 1529 | char *purl; |
1545 | int blank = -1; | 1530 | int blank = -1; |
@@ -1569,10 +1554,10 @@ static void handle_incoming_and_exit(void) | |||
1569 | int count; | 1554 | int count; |
1570 | 1555 | ||
1571 | alarm(TIMEOUT); | 1556 | alarm(TIMEOUT); |
1572 | if (getLine() <= 0) | 1557 | if (!get_line()) |
1573 | break; /* closed */ | 1558 | break; /* EOF or error or empty line */ |
1574 | 1559 | ||
1575 | purl = strpbrk(buf, " \t"); | 1560 | purl = strpbrk(iobuf, " \t"); |
1576 | if (purl == NULL) { | 1561 | if (purl == NULL) { |
1577 | BAD_REQUEST: | 1562 | BAD_REQUEST: |
1578 | sendHeaders(HTTP_BAD_REQUEST); | 1563 | sendHeaders(HTTP_BAD_REQUEST); |
@@ -1580,32 +1565,32 @@ static void handle_incoming_and_exit(void) | |||
1580 | } | 1565 | } |
1581 | *purl = '\0'; | 1566 | *purl = '\0'; |
1582 | #if ENABLE_FEATURE_HTTPD_CGI | 1567 | #if ENABLE_FEATURE_HTTPD_CGI |
1583 | if (strcasecmp(buf, prequest) != 0) { | 1568 | if (strcasecmp(iobuf, prequest) != 0) { |
1584 | prequest = "POST"; | 1569 | prequest = "POST"; |
1585 | if (strcasecmp(buf, prequest) != 0) { | 1570 | if (strcasecmp(iobuf, prequest) != 0) { |
1586 | sendHeaders(HTTP_NOT_IMPLEMENTED); | 1571 | sendHeaders(HTTP_NOT_IMPLEMENTED); |
1587 | break; | 1572 | break; |
1588 | } | 1573 | } |
1589 | } | 1574 | } |
1590 | #else | 1575 | #else |
1591 | if (strcasecmp(buf, request_GET) != 0) { | 1576 | if (strcasecmp(iobuf, request_GET) != 0) { |
1592 | sendHeaders(HTTP_NOT_IMPLEMENTED); | 1577 | sendHeaders(HTTP_NOT_IMPLEMENTED); |
1593 | break; | 1578 | break; |
1594 | } | 1579 | } |
1595 | #endif | 1580 | #endif |
1596 | *purl = ' '; | 1581 | *purl = ' '; |
1597 | count = sscanf(purl, " %[^ ] HTTP/%d.%*d", buf, &blank); | 1582 | count = sscanf(purl, " %[^ ] HTTP/%d.%*d", iobuf, &blank); |
1598 | 1583 | ||
1599 | if (count < 1 || buf[0] != '/') { | 1584 | if (count < 1 || iobuf[0] != '/') { |
1600 | /* Garbled request/URL */ | 1585 | /* Garbled request/URL */ |
1601 | goto BAD_REQUEST; | 1586 | goto BAD_REQUEST; |
1602 | } | 1587 | } |
1603 | url = alloca(strlen(buf) + sizeof("/index.html")); | 1588 | url = alloca(strlen(iobuf) + sizeof("/index.html")); |
1604 | if (url == NULL) { | 1589 | if (url == NULL) { |
1605 | sendHeaders(HTTP_INTERNAL_SERVER_ERROR); | 1590 | sendHeaders(HTTP_INTERNAL_SERVER_ERROR); |
1606 | break; | 1591 | break; |
1607 | } | 1592 | } |
1608 | strcpy(url, buf); | 1593 | strcpy(url, iobuf); |
1609 | /* extract url args if present */ | 1594 | /* extract url args if present */ |
1610 | test = strchr(url, '?'); | 1595 | test = strchr(url, '?'); |
1611 | g_query = NULL; | 1596 | g_query = NULL; |
@@ -1641,7 +1626,7 @@ static void handle_incoming_and_exit(void) | |||
1641 | if (test[1] == '.' && (test[2] == '/' || !test[2])) { | 1626 | if (test[1] == '.' && (test[2] == '/' || !test[2])) { |
1642 | ++test; | 1627 | ++test; |
1643 | if (purl == url) { | 1628 | if (purl == url) { |
1644 | /* protect out root */ | 1629 | /* protect root */ |
1645 | goto BAD_REQUEST; | 1630 | goto BAD_REQUEST; |
1646 | } | 1631 | } |
1647 | while (*--purl != '/') /* omit previous dir */; | 1632 | while (*--purl != '/') /* omit previous dir */; |
@@ -1660,8 +1645,11 @@ static void handle_incoming_and_exit(void) | |||
1660 | found_moved_temporarily = url; | 1645 | found_moved_temporarily = url; |
1661 | } | 1646 | } |
1662 | } | 1647 | } |
1663 | if (DEBUG) | 1648 | if (verbose > 1) { |
1664 | fprintf(stderr, "url='%s', args=%s\n", url, g_query); | 1649 | /* Hopefully does it with single write[v] */ |
1650 | /* (uclibc does, glibc: ?) */ | ||
1651 | fdprintf(2, "%s url:%s\n", rmt_ip_str, url); | ||
1652 | } | ||
1665 | 1653 | ||
1666 | test = url; | 1654 | test = url; |
1667 | ip_allowed = checkPermIP(); | 1655 | ip_allowed = checkPermIP(); |
@@ -1679,18 +1667,18 @@ static void handle_incoming_and_exit(void) | |||
1679 | /* read until blank line for HTTP version specified, else parse immediate */ | 1667 | /* read until blank line for HTTP version specified, else parse immediate */ |
1680 | while (1) { | 1668 | while (1) { |
1681 | alarm(TIMEOUT); | 1669 | alarm(TIMEOUT); |
1682 | if (getLine() <= 0) | 1670 | if (!get_line()) |
1683 | break; | 1671 | break; /* EOF or error or empty line */ |
1684 | 1672 | ||
1685 | if (DEBUG) | 1673 | if (DEBUG) |
1686 | fprintf(stderr, "header: '%s'\n", buf); | 1674 | fprintf(stderr, "header: '%s'\n", iobuf); |
1687 | 1675 | ||
1688 | #if ENABLE_FEATURE_HTTPD_CGI | 1676 | #if ENABLE_FEATURE_HTTPD_CGI |
1689 | /* try and do our best to parse more lines */ | 1677 | /* try and do our best to parse more lines */ |
1690 | if ((STRNCASECMP(buf, "Content-length:") == 0)) { | 1678 | if ((STRNCASECMP(iobuf, "Content-length:") == 0)) { |
1691 | /* extra read only for POST */ | 1679 | /* extra read only for POST */ |
1692 | if (prequest != request_GET) { | 1680 | if (prequest != request_GET) { |
1693 | test = buf + sizeof("Content-length:") - 1; | 1681 | test = iobuf + sizeof("Content-length:") - 1; |
1694 | if (!test[0]) | 1682 | if (!test[0]) |
1695 | goto bail_out; | 1683 | goto bail_out; |
1696 | errno = 0; | 1684 | errno = 0; |
@@ -1702,24 +1690,24 @@ static void handle_incoming_and_exit(void) | |||
1702 | if (test[0] || errno || length > INT_MAX) | 1690 | if (test[0] || errno || length > INT_MAX) |
1703 | goto bail_out; | 1691 | goto bail_out; |
1704 | } | 1692 | } |
1705 | } else if (STRNCASECMP(buf, "Cookie:") == 0) { | 1693 | } else if (STRNCASECMP(iobuf, "Cookie:") == 0) { |
1706 | cookie = strdup(skip_whitespace(buf + sizeof("Cookie:")-1)); | 1694 | cookie = strdup(skip_whitespace(iobuf + sizeof("Cookie:")-1)); |
1707 | } else if (STRNCASECMP(buf, "Content-Type:") == 0) { | 1695 | } else if (STRNCASECMP(iobuf, "Content-Type:") == 0) { |
1708 | content_type = strdup(skip_whitespace(buf + sizeof("Content-Type:")-1)); | 1696 | content_type = strdup(skip_whitespace(iobuf + sizeof("Content-Type:")-1)); |
1709 | } else if (STRNCASECMP(buf, "Referer:") == 0) { | 1697 | } else if (STRNCASECMP(iobuf, "Referer:") == 0) { |
1710 | referer = strdup(skip_whitespace(buf + sizeof("Referer:")-1)); | 1698 | referer = strdup(skip_whitespace(iobuf + sizeof("Referer:")-1)); |
1711 | } else if (STRNCASECMP(buf, "User-Agent:") == 0) { | 1699 | } else if (STRNCASECMP(iobuf, "User-Agent:") == 0) { |
1712 | user_agent = strdup(skip_whitespace(buf + sizeof("User-Agent:")-1)); | 1700 | user_agent = strdup(skip_whitespace(iobuf + sizeof("User-Agent:")-1)); |
1713 | } | 1701 | } |
1714 | #endif | 1702 | #endif |
1715 | 1703 | ||
1716 | #if ENABLE_FEATURE_HTTPD_BASIC_AUTH | 1704 | #if ENABLE_FEATURE_HTTPD_BASIC_AUTH |
1717 | if (STRNCASECMP(buf, "Authorization:") == 0) { | 1705 | if (STRNCASECMP(iobuf, "Authorization:") == 0) { |
1718 | /* We only allow Basic credentials. | 1706 | /* We only allow Basic credentials. |
1719 | * It shows up as "Authorization: Basic <userid:password>" where | 1707 | * It shows up as "Authorization: Basic <userid:password>" where |
1720 | * the userid:password is base64 encoded. | 1708 | * the userid:password is base64 encoded. |
1721 | */ | 1709 | */ |
1722 | test = skip_whitespace(buf + sizeof("Authorization:")-1); | 1710 | test = skip_whitespace(iobuf + sizeof("Authorization:")-1); |
1723 | if (STRNCASECMP(test, "Basic") != 0) | 1711 | if (STRNCASECMP(test, "Basic") != 0) |
1724 | continue; | 1712 | continue; |
1725 | test += sizeof("Basic")-1; | 1713 | test += sizeof("Basic")-1; |
@@ -1762,7 +1750,7 @@ static void handle_incoming_and_exit(void) | |||
1762 | 1750 | ||
1763 | #if ENABLE_FEATURE_HTTPD_CGI | 1751 | #if ENABLE_FEATURE_HTTPD_CGI |
1764 | if (strncmp(test, "cgi-bin", 7) == 0) { | 1752 | if (strncmp(test, "cgi-bin", 7) == 0) { |
1765 | if (test[7] == '/' && test[8] == 0) | 1753 | if (test[7] == '/' && test[8] == '\0') |
1766 | goto FORBIDDEN; /* protect listing cgi-bin/ */ | 1754 | goto FORBIDDEN; /* protect listing cgi-bin/ */ |
1767 | sendCgi(url, prequest, length, cookie, content_type); | 1755 | sendCgi(url, prequest, length, cookie, content_type); |
1768 | break; | 1756 | break; |
@@ -1839,7 +1827,7 @@ static void handle_incoming_and_exit(void) | |||
1839 | tv.tv_sec = 2; | 1827 | tv.tv_sec = 2; |
1840 | tv.tv_usec = 0; | 1828 | tv.tv_usec = 0; |
1841 | retval = select(accepted_socket + 1, &s_fd, NULL, NULL, &tv); | 1829 | retval = select(accepted_socket + 1, &s_fd, NULL, NULL, &tv); |
1842 | } while (retval > 0 && read(accepted_socket, buf, sizeof(iobuf) > 0)); | 1830 | } while (retval > 0 && read(accepted_socket, iobuf, sizeof(iobuf) > 0)); |
1843 | shutdown(accepted_socket, SHUT_RD); | 1831 | shutdown(accepted_socket, SHUT_RD); |
1844 | close(accepted_socket); | 1832 | close(accepted_socket); |
1845 | exit(0); | 1833 | exit(0); |
@@ -1883,13 +1871,12 @@ static void mini_httpd(int server) | |||
1883 | accepted_socket = s; | 1871 | accepted_socket = s; |
1884 | rmt_ip = 0; | 1872 | rmt_ip = 0; |
1885 | tcp_port = 0; | 1873 | tcp_port = 0; |
1886 | #if ENABLE_FEATURE_HTTPD_CGI || DEBUG | 1874 | if (verbose || ENABLE_FEATURE_HTTPD_CGI || DEBUG) { |
1887 | free(rmt_ip_str); | 1875 | free(rmt_ip_str); |
1888 | rmt_ip_str = xmalloc_sockaddr2dotted(&fromAddr.sa, fromAddrLen); | 1876 | rmt_ip_str = xmalloc_sockaddr2dotted(&fromAddr.sa, fromAddrLen); |
1889 | #if DEBUG | 1877 | if (DEBUG) |
1890 | bb_error_msg("connection from '%s'", rmt_ip_str); | 1878 | bb_error_msg("connection from '%s'", rmt_ip_str); |
1891 | #endif | 1879 | } |
1892 | #endif /* FEATURE_HTTPD_CGI */ | ||
1893 | if (fromAddr.sa.sa_family == AF_INET) { | 1880 | if (fromAddr.sa.sa_family == AF_INET) { |
1894 | rmt_ip = ntohl(fromAddr.sin.sin_addr.s_addr); | 1881 | rmt_ip = ntohl(fromAddr.sin.sin_addr.s_addr); |
1895 | tcp_port = ntohs(fromAddr.sin.sin_port); | 1882 | tcp_port = ntohs(fromAddr.sin.sin_port); |
@@ -1932,10 +1919,10 @@ static void mini_httpd_inetd(void) | |||
1932 | getpeername(0, &fromAddr.sa, &fromAddrLen); | 1919 | getpeername(0, &fromAddr.sa, &fromAddrLen); |
1933 | rmt_ip = 0; | 1920 | rmt_ip = 0; |
1934 | tcp_port = 0; | 1921 | tcp_port = 0; |
1935 | #if ENABLE_FEATURE_HTTPD_CGI || DEBUG | 1922 | if (verbose || ENABLE_FEATURE_HTTPD_CGI || DEBUG) { |
1936 | free(rmt_ip_str); | 1923 | free(rmt_ip_str); |
1937 | rmt_ip_str = xmalloc_sockaddr2dotted(&fromAddr.sa, fromAddrLen); | 1924 | rmt_ip_str = xmalloc_sockaddr2dotted(&fromAddr.sa, fromAddrLen); |
1938 | #endif | 1925 | } |
1939 | if (fromAddr.sa.sa_family == AF_INET) { | 1926 | if (fromAddr.sa.sa_family == AF_INET) { |
1940 | rmt_ip = ntohl(fromAddr.sin.sin_addr.s_addr); | 1927 | rmt_ip = ntohl(fromAddr.sin.sin_addr.s_addr); |
1941 | tcp_port = ntohs(fromAddr.sin.sin_port); | 1928 | tcp_port = ntohs(fromAddr.sin.sin_port); |
@@ -1974,6 +1961,7 @@ enum { | |||
1974 | p_opt_port , | 1961 | p_opt_port , |
1975 | p_opt_inetd , | 1962 | p_opt_inetd , |
1976 | p_opt_foreground, | 1963 | p_opt_foreground, |
1964 | p_opt_verbose , | ||
1977 | OPT_CONFIG_FILE = 1 << c_opt_config_file, | 1965 | OPT_CONFIG_FILE = 1 << c_opt_config_file, |
1978 | OPT_DECODE_URL = 1 << d_opt_decode_url, | 1966 | OPT_DECODE_URL = 1 << d_opt_decode_url, |
1979 | OPT_HOME_HTTPD = 1 << h_opt_home_httpd, | 1967 | OPT_HOME_HTTPD = 1 << h_opt_home_httpd, |
@@ -1984,6 +1972,7 @@ enum { | |||
1984 | OPT_PORT = 1 << p_opt_port, | 1972 | OPT_PORT = 1 << p_opt_port, |
1985 | OPT_INETD = 1 << p_opt_inetd, | 1973 | OPT_INETD = 1 << p_opt_inetd, |
1986 | OPT_FOREGROUND = 1 << p_opt_foreground, | 1974 | OPT_FOREGROUND = 1 << p_opt_foreground, |
1975 | OPT_VERBOSE = 1 << p_opt_verbose, | ||
1987 | }; | 1976 | }; |
1988 | 1977 | ||
1989 | 1978 | ||
@@ -2004,6 +1993,7 @@ int httpd_main(int argc, char **argv) | |||
2004 | 1993 | ||
2005 | INIT_G(); | 1994 | INIT_G(); |
2006 | home_httpd = xrealloc_getcwd_or_warn(NULL); | 1995 | home_httpd = xrealloc_getcwd_or_warn(NULL); |
1996 | opt_complementary = "vv"; /* counter */ | ||
2007 | /* We do not "absolutize" path given by -h (home) opt. | 1997 | /* We do not "absolutize" path given by -h (home) opt. |
2008 | * If user gives relative path in -h, $SCRIPT_FILENAME can end up | 1998 | * If user gives relative path in -h, $SCRIPT_FILENAME can end up |
2009 | * relative too. */ | 1999 | * relative too. */ |
@@ -2012,13 +2002,14 @@ int httpd_main(int argc, char **argv) | |||
2012 | USE_FEATURE_HTTPD_BASIC_AUTH("r:") | 2002 | USE_FEATURE_HTTPD_BASIC_AUTH("r:") |
2013 | USE_FEATURE_HTTPD_AUTH_MD5("m:") | 2003 | USE_FEATURE_HTTPD_AUTH_MD5("m:") |
2014 | USE_FEATURE_HTTPD_SETUID("u:") | 2004 | USE_FEATURE_HTTPD_SETUID("u:") |
2015 | "p:if", | 2005 | "p:ifv", |
2016 | &(configFile), &url_for_decode, &home_httpd | 2006 | &configFile, &url_for_decode, &home_httpd |
2017 | USE_FEATURE_HTTPD_ENCODE_URL_STR(, &url_for_encode) | 2007 | USE_FEATURE_HTTPD_ENCODE_URL_STR(, &url_for_encode) |
2018 | USE_FEATURE_HTTPD_BASIC_AUTH(, &g_realm) | 2008 | USE_FEATURE_HTTPD_BASIC_AUTH(, &g_realm) |
2019 | USE_FEATURE_HTTPD_AUTH_MD5(, &pass) | 2009 | USE_FEATURE_HTTPD_AUTH_MD5(, &pass) |
2020 | USE_FEATURE_HTTPD_SETUID(, &s_ugid) | 2010 | USE_FEATURE_HTTPD_SETUID(, &s_ugid) |
2021 | , &bind_addr_or_port | 2011 | , &bind_addr_or_port |
2012 | , &verbose | ||
2022 | ); | 2013 | ); |
2023 | if (opt & OPT_DECODE_URL) { | 2014 | if (opt & OPT_DECODE_URL) { |
2024 | printf("%s", decodeString(url_for_decode, 1)); | 2015 | printf("%s", decodeString(url_for_decode, 1)); |
@@ -2036,7 +2027,6 @@ int httpd_main(int argc, char **argv) | |||
2036 | return 0; | 2027 | return 0; |
2037 | } | 2028 | } |
2038 | #endif | 2029 | #endif |
2039 | |||
2040 | #if ENABLE_FEATURE_HTTPD_SETUID | 2030 | #if ENABLE_FEATURE_HTTPD_SETUID |
2041 | if (opt & OPT_SETUID) { | 2031 | if (opt & OPT_SETUID) { |
2042 | if (!get_uidgid(&ugid, s_ugid, 1)) | 2032 | if (!get_uidgid(&ugid, s_ugid, 1)) |