diff options
author | Glenn L McGrath <bug1@ihug.co.nz> | 2003-10-03 10:50:56 +0000 |
---|---|---|
committer | Glenn L McGrath <bug1@ihug.co.nz> | 2003-10-03 10:50:56 +0000 |
commit | 1dc0ccafddf9b5f540008b7cabbf3ab1f4f53ee3 (patch) | |
tree | 96579ff97eb7334d004e12c8fdd60ec0f6555e37 | |
parent | 8ac86e33a279192cc94be9fc5611e797216f523c (diff) | |
download | busybox-w32-1dc0ccafddf9b5f540008b7cabbf3ab1f4f53ee3.tar.gz busybox-w32-1dc0ccafddf9b5f540008b7cabbf3ab1f4f53ee3.tar.bz2 busybox-w32-1dc0ccafddf9b5f540008b7cabbf3ab1f4f53ee3.zip |
Vodz, last_patch_114
- env vars CONTENT_TYPE, CONTENT_LENGTH, HTTPD_REFERER, REMOTE_USER and
AUTH_TYPE(Basic always).
- POST data pipied now (previous version have loading into memory may be
big size data and reducing with hardcoded limit)
- removed $CGI_foo environment variables, else my have rubbish
enviroment if POST data have big binary file
-rw-r--r-- | networking/httpd.c | 254 |
1 files changed, 115 insertions, 139 deletions
diff --git a/networking/httpd.c b/networking/httpd.c index 6f5100c9e..e5ad7f65e 100644 --- a/networking/httpd.c +++ b/networking/httpd.c | |||
@@ -33,11 +33,7 @@ | |||
33 | * | 33 | * |
34 | * When a url contains "cgi-bin" it is assumed to be a cgi script. The | 34 | * When a url contains "cgi-bin" it is assumed to be a cgi script. The |
35 | * server changes directory to the location of the script and executes it | 35 | * server changes directory to the location of the script and executes it |
36 | * after setting QUERY_STRING and other environment variables. If url args | 36 | * after setting QUERY_STRING and other environment variables. |
37 | * are included in the url or as a post, the args are placed into decoded | ||
38 | * environment variables. e.g. /cgi-bin/setup?foo=Hello%20World will set | ||
39 | * the $CGI_foo environment variable to "Hello World" while | ||
40 | * CONFIG_FEATURE_HTTPD_SET_CGI_VARS_TO_ENV enabled. | ||
41 | * | 37 | * |
42 | * The server can also be invoked as a url arg decoder and html text encoder | 38 | * The server can also be invoked as a url arg decoder and html text encoder |
43 | * as follows: | 39 | * as follows: |
@@ -120,7 +116,7 @@ | |||
120 | #include "busybox.h" | 116 | #include "busybox.h" |
121 | 117 | ||
122 | 118 | ||
123 | static const char httpdVersion[] = "busybox httpd/1.30 7-Sep-2003"; | 119 | static const char httpdVersion[] = "busybox httpd/1.34 2-Oct-2003"; |
124 | static const char default_path_httpd_conf[] = "/etc"; | 120 | static const char default_path_httpd_conf[] = "/etc"; |
125 | static const char httpd_conf[] = "httpd.conf"; | 121 | static const char httpd_conf[] = "httpd.conf"; |
126 | static const char home[] = "./"; | 122 | static const char home[] = "./"; |
@@ -131,7 +127,6 @@ static const char home[] = "./"; | |||
131 | # define cont_l_fmt "%ld" | 127 | # define cont_l_fmt "%ld" |
132 | #endif | 128 | #endif |
133 | 129 | ||
134 | |||
135 | // Note: bussybox xfuncs are not used because we want the server to keep running | 130 | // Note: bussybox xfuncs are not used because we want the server to keep running |
136 | // if something bad happens due to a malformed user request. | 131 | // if something bad happens due to a malformed user request. |
137 | // As a result, all memory allocation after daemonize | 132 | // As a result, all memory allocation after daemonize |
@@ -142,7 +137,6 @@ static const char home[] = "./"; | |||
142 | /* Configure options, disabled by default as custom httpd feature */ | 137 | /* Configure options, disabled by default as custom httpd feature */ |
143 | 138 | ||
144 | /* disabled as optional features */ | 139 | /* disabled as optional features */ |
145 | //#define CONFIG_FEATURE_HTTPD_SET_CGI_VARS_TO_ENV | ||
146 | //#define CONFIG_FEATURE_HTTPD_ENCODE_URL_STR | 140 | //#define CONFIG_FEATURE_HTTPD_ENCODE_URL_STR |
147 | //#define CONFIG_FEATURE_HTTPD_SET_REMOTE_PORT_TO_ENV | 141 | //#define CONFIG_FEATURE_HTTPD_SET_REMOTE_PORT_TO_ENV |
148 | //#define CONFIG_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES | 142 | //#define CONFIG_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES |
@@ -166,7 +160,6 @@ static const char home[] = "./"; | |||
166 | /* unset config option for remove warning as redefined */ | 160 | /* unset config option for remove warning as redefined */ |
167 | #undef CONFIG_FEATURE_HTTPD_BASIC_AUTH | 161 | #undef CONFIG_FEATURE_HTTPD_BASIC_AUTH |
168 | #undef CONFIG_FEATURE_HTTPD_AUTH_MD5 | 162 | #undef CONFIG_FEATURE_HTTPD_AUTH_MD5 |
169 | #undef CONFIG_FEATURE_HTTPD_SET_CGI_VARS_TO_ENV | ||
170 | #undef CONFIG_FEATURE_HTTPD_ENCODE_URL_STR | 163 | #undef CONFIG_FEATURE_HTTPD_ENCODE_URL_STR |
171 | #undef CONFIG_FEATURE_HTTPD_SET_REMOTE_PORT_TO_ENV | 164 | #undef CONFIG_FEATURE_HTTPD_SET_REMOTE_PORT_TO_ENV |
172 | #undef CONFIG_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES | 165 | #undef CONFIG_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES |
@@ -176,7 +169,6 @@ static const char home[] = "./"; | |||
176 | /* enable all features now */ | 169 | /* enable all features now */ |
177 | #define CONFIG_FEATURE_HTTPD_BASIC_AUTH | 170 | #define CONFIG_FEATURE_HTTPD_BASIC_AUTH |
178 | #define CONFIG_FEATURE_HTTPD_AUTH_MD5 | 171 | #define CONFIG_FEATURE_HTTPD_AUTH_MD5 |
179 | #define CONFIG_FEATURE_HTTPD_SET_CGI_VARS_TO_ENV | ||
180 | #define CONFIG_FEATURE_HTTPD_ENCODE_URL_STR | 172 | #define CONFIG_FEATURE_HTTPD_ENCODE_URL_STR |
181 | #define CONFIG_FEATURE_HTTPD_SET_REMOTE_PORT_TO_ENV | 173 | #define CONFIG_FEATURE_HTTPD_SET_REMOTE_PORT_TO_ENV |
182 | #define CONFIG_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES | 174 | #define CONFIG_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES |
@@ -202,8 +194,6 @@ void bb_show_usage(void) | |||
202 | #undef DEBUG | 194 | #undef DEBUG |
203 | #endif | 195 | #endif |
204 | 196 | ||
205 | #define MAX_POST_SIZE (64*1024) /* 64k. Its Small? May be ;) */ | ||
206 | |||
207 | #define MAX_MEMORY_BUFF 8192 /* IO buffer */ | 197 | #define MAX_MEMORY_BUFF 8192 /* IO buffer */ |
208 | 198 | ||
209 | typedef struct HT_ACCESS { | 199 | typedef struct HT_ACCESS { |
@@ -225,7 +215,13 @@ typedef struct | |||
225 | 215 | ||
226 | #ifdef CONFIG_FEATURE_HTTPD_BASIC_AUTH | 216 | #ifdef CONFIG_FEATURE_HTTPD_BASIC_AUTH |
227 | const char *realm; | 217 | const char *realm; |
218 | char *remoteuser; | ||
219 | #endif | ||
220 | |||
221 | #ifdef CONFIG_FEATURE_HTTPD_CGI | ||
222 | char *referer; | ||
228 | #endif | 223 | #endif |
224 | |||
229 | const char *configFile; | 225 | const char *configFile; |
230 | 226 | ||
231 | unsigned int rmt_ip; | 227 | unsigned int rmt_ip; |
@@ -474,11 +470,10 @@ static void free_config_lines(Htaccess **pprev) | |||
474 | static void parse_conf(const char *path, int flag) | 470 | static void parse_conf(const char *path, int flag) |
475 | { | 471 | { |
476 | FILE *f; | 472 | FILE *f; |
477 | #if defined(CONFIG_FEATURE_HTTPD_BASIC_AUTH) || defined(CONFIG_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES) | ||
478 | Htaccess *cur; | ||
479 | #ifdef CONFIG_FEATURE_HTTPD_BASIC_AUTH | 473 | #ifdef CONFIG_FEATURE_HTTPD_BASIC_AUTH |
480 | Htaccess *prev; | 474 | Htaccess *prev, *cur; |
481 | #endif | 475 | #elif CONFIG_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES |
476 | Htaccess *cur; | ||
482 | #endif | 477 | #endif |
483 | 478 | ||
484 | const char *cf = config->configFile; | 479 | const char *cf = config->configFile; |
@@ -822,58 +817,6 @@ static void addEnvPort(const char *port_name) | |||
822 | #endif | 817 | #endif |
823 | #endif /* CONFIG_FEATURE_HTTPD_CGI */ | 818 | #endif /* CONFIG_FEATURE_HTTPD_CGI */ |
824 | 819 | ||
825 | #ifdef CONFIG_FEATURE_HTTPD_SET_CGI_VARS_TO_ENV | ||
826 | /**************************************************************************** | ||
827 | * | ||
828 | > $Function: addEnvCgi | ||
829 | * | ||
830 | * $Description: Create environment variables given a URL encoded arg list. | ||
831 | * For each variable setting the URL encoded arg list, create a corresponding | ||
832 | * environment variable. URL encoded arguments have the form | ||
833 | * name1=value1&name2=value2&name3=&ignores | ||
834 | * from this example, name3 set empty value, tail without '=' skiping | ||
835 | * | ||
836 | * $Parameters: | ||
837 | * (char *) pargs . . . . A pointer to the URL encoded arguments. | ||
838 | * | ||
839 | * $Return: None | ||
840 | * | ||
841 | * $Errors: None | ||
842 | * | ||
843 | ****************************************************************************/ | ||
844 | static void addEnvCgi(const char *pargs) | ||
845 | { | ||
846 | char *args; | ||
847 | char *memargs; | ||
848 | char *namelist; /* space separated list of arg names */ | ||
849 | if (pargs==0) return; | ||
850 | |||
851 | /* args are a list of name=value&name2=value2 sequences */ | ||
852 | namelist = (char *) malloc(strlen(pargs)); | ||
853 | if (namelist) namelist[0]=0; | ||
854 | memargs = args = strdup(pargs); | ||
855 | while (args && *args) { | ||
856 | const char *name = args; | ||
857 | char *value = strchr(args, '='); | ||
858 | |||
859 | if (!value) /* &XXX without '=' */ | ||
860 | break; | ||
861 | *value++ = 0; | ||
862 | args = strchr(value, '&'); | ||
863 | if (args) | ||
864 | *args++ = 0; | ||
865 | addEnv("CGI", name, decodeString(value, 1)); | ||
866 | if (*namelist) strcat(namelist, " "); | ||
867 | strcat(namelist, name); | ||
868 | } | ||
869 | free(memargs); | ||
870 | if (namelist) { | ||
871 | addEnv("CGI", "ARGLIST_", namelist); | ||
872 | free(namelist); | ||
873 | } | ||
874 | } | ||
875 | #endif /* CONFIG_FEATURE_HTTPD_SET_CGI_VARS_TO_ENV */ | ||
876 | |||
877 | 820 | ||
878 | #ifdef CONFIG_FEATURE_HTTPD_BASIC_AUTH | 821 | #ifdef CONFIG_FEATURE_HTTPD_BASIC_AUTH |
879 | /**************************************************************************** | 822 | /**************************************************************************** |
@@ -1058,15 +1001,13 @@ static int sendHeaders(HttpResponseNum responseNum) | |||
1058 | * | 1001 | * |
1059 | * Characters are read one at a time until an eol sequence is found. | 1002 | * Characters are read one at a time until an eol sequence is found. |
1060 | * | 1003 | * |
1061 | * $Parameters: | ||
1062 | * (char *) buf . . Where to place the read result. | ||
1063 | * | ||
1064 | * $Return: (int) . . . . number of characters read. -1 if error. | 1004 | * $Return: (int) . . . . number of characters read. -1 if error. |
1065 | * | 1005 | * |
1066 | ****************************************************************************/ | 1006 | ****************************************************************************/ |
1067 | static int getLine(char *buf) | 1007 | static int getLine(void) |
1068 | { | 1008 | { |
1069 | int count = 0; | 1009 | int count = 0; |
1010 | char *buf = config->buf; | ||
1070 | 1011 | ||
1071 | while (read(a_c_r, buf + count, 1) == 1) { | 1012 | while (read(a_c_r, buf + count, 1) == 1) { |
1072 | if (buf[count] == '\r') continue; | 1013 | if (buf[count] == '\r') continue; |
@@ -1093,11 +1034,11 @@ static int getLine(char *buf) | |||
1093 | * data in addition to setting the QUERY_STRING variable (for GETs or POSTs). | 1034 | * data in addition to setting the QUERY_STRING variable (for GETs or POSTs). |
1094 | * | 1035 | * |
1095 | * $Parameters: | 1036 | * $Parameters: |
1096 | * (const char *) url . . . The requested URL (with leading /). | 1037 | * (const char *) url . . . . . . The requested URL (with leading /). |
1097 | * (const char *urlArgs). . Any URL arguments. | 1038 | * (const char *urlArgs). . . . . Any URL arguments. |
1098 | * (const char *body) . . . POST body contents. | 1039 | * (int bodyLen) . . . . . . . . Length of the post body. |
1099 | * (int bodyLen) . . . . . Length of the post body. | 1040 | * (const char *cookie) . . . . . For set HTTP_COOKIE. |
1100 | * (const char *cookie) . . For set HTTP_COOKIE. | 1041 | * (const char *content_type) . . For set CONTENT_TYPE. |
1101 | 1042 | ||
1102 | * | 1043 | * |
1103 | * $Return: (char *) . . . . A pointer to the decoded string (same as input). | 1044 | * $Return: (char *) . . . . A pointer to the decoded string (same as input). |
@@ -1107,7 +1048,8 @@ static int getLine(char *buf) | |||
1107 | ****************************************************************************/ | 1048 | ****************************************************************************/ |
1108 | static int sendCgi(const char *url, | 1049 | static int sendCgi(const char *url, |
1109 | const char *request, const char *urlArgs, | 1050 | const char *request, const char *urlArgs, |
1110 | const char *body, int bodyLen, const char *cookie) | 1051 | int bodyLen, const char *cookie, |
1052 | const char *content_type) | ||
1111 | { | 1053 | { |
1112 | int fromCgi[2]; /* pipe for reading data from CGI */ | 1054 | int fromCgi[2]; /* pipe for reading data from CGI */ |
1113 | int toCgi[2]; /* pipe for sending data to CGI */ | 1055 | int toCgi[2]; /* pipe for sending data to CGI */ |
@@ -1174,6 +1116,7 @@ static int sendCgi(const char *url, | |||
1174 | *script = '/'; /* is directory, find next '/' */ | 1116 | *script = '/'; /* is directory, find next '/' */ |
1175 | } | 1117 | } |
1176 | addEnv("PATH", "INFO", script); /* set /PATH_INFO or NULL */ | 1118 | addEnv("PATH", "INFO", script); /* set /PATH_INFO or NULL */ |
1119 | addEnv("PATH", "", getenv("PATH")); | ||
1177 | addEnv("REQUEST", "METHOD", request); | 1120 | addEnv("REQUEST", "METHOD", request); |
1178 | if(urlArgs) { | 1121 | if(urlArgs) { |
1179 | char *uri = alloca(strlen(purl) + 2 + strlen(urlArgs)); | 1122 | char *uri = alloca(strlen(purl) + 2 + strlen(urlArgs)); |
@@ -1191,28 +1134,26 @@ static int sendCgi(const char *url, | |||
1191 | addEnv("SERVER", "SOFTWARE", httpdVersion); | 1134 | addEnv("SERVER", "SOFTWARE", httpdVersion); |
1192 | addEnv("SERVER", "PROTOCOL", "HTTP/1.0"); | 1135 | addEnv("SERVER", "PROTOCOL", "HTTP/1.0"); |
1193 | addEnv("GATEWAY_INTERFACE", "", "CGI/1.1"); | 1136 | addEnv("GATEWAY_INTERFACE", "", "CGI/1.1"); |
1194 | #ifdef CONFIG_FEATURE_HTTPD_SET_REMOTE_PORT_TO_ENV | ||
1195 | addEnv("REMOTE", "ADDR", config->rmt_ip_str); | 1137 | addEnv("REMOTE", "ADDR", config->rmt_ip_str); |
1138 | #ifdef CONFIG_FEATURE_HTTPD_SET_REMOTE_PORT_TO_ENV | ||
1196 | addEnvPort("REMOTE"); | 1139 | addEnvPort("REMOTE"); |
1197 | #else | ||
1198 | addEnv("REMOTE_ADDR", "", config->rmt_ip_str); | ||
1199 | #endif | 1140 | #endif |
1200 | if(bodyLen) { | 1141 | if(bodyLen) { |
1201 | char sbl[32]; | 1142 | char sbl[32]; |
1202 | 1143 | ||
1203 | sprintf(sbl, "%d", bodyLen); | 1144 | sprintf(sbl, "%d", bodyLen); |
1204 | addEnv("CONTENT_LENGTH", "", sbl); | 1145 | addEnv("CONTENT", "LENGTH", sbl); |
1205 | } | 1146 | } |
1206 | if(cookie) | 1147 | if(cookie) |
1207 | addEnv("HTTP_COOKIE", "", cookie); | 1148 | addEnv("HTTP", "COOKIE", cookie); |
1208 | 1149 | if(content_type) | |
1209 | #ifdef CONFIG_FEATURE_HTTPD_SET_CGI_VARS_TO_ENV | 1150 | addEnv("CONTENT", "TYPE", content_type); |
1210 | if (request != request_GET) { | 1151 | if(config->remoteuser) { |
1211 | addEnvCgi(body); | 1152 | addEnv("REMOTE", "USER", config->remoteuser); |
1212 | } else { | 1153 | addEnv("AUTH_TYPE", "", "Basic"); |
1213 | addEnvCgi(urlArgs); | ||
1214 | } | 1154 | } |
1215 | #endif | 1155 | if(config->referer) |
1156 | addEnv("HTTP", "REFERER", config->referer); | ||
1216 | 1157 | ||
1217 | /* set execve argp[0] without path */ | 1158 | /* set execve argp[0] without path */ |
1218 | argp[0] = strrchr( purl, '/' ) + 1; | 1159 | argp[0] = strrchr( purl, '/' ) + 1; |
@@ -1242,28 +1183,41 @@ static int sendCgi(const char *url, | |||
1242 | if (pid) { | 1183 | if (pid) { |
1243 | /* parent process */ | 1184 | /* parent process */ |
1244 | int status; | 1185 | int status; |
1186 | size_t post_readed_size = 0, post_readed_idx = 0; | ||
1245 | 1187 | ||
1246 | inFd = fromCgi[0]; | 1188 | inFd = fromCgi[0]; |
1247 | outFd = toCgi[1]; | 1189 | outFd = toCgi[1]; |
1248 | close(fromCgi[1]); | 1190 | close(fromCgi[1]); |
1249 | close(toCgi[0]); | 1191 | close(toCgi[0]); |
1250 | if (body) bb_full_write(outFd, body, bodyLen); | 1192 | signal(SIGPIPE, SIG_IGN); |
1251 | close(outFd); | ||
1252 | 1193 | ||
1253 | while (1) { | 1194 | while (1) { |
1254 | struct timeval timeout; | ||
1255 | fd_set readSet; | 1195 | fd_set readSet; |
1256 | char buf[160]; | 1196 | fd_set writeSet; |
1197 | char wbuf[128]; | ||
1257 | int nfound; | 1198 | int nfound; |
1258 | int count; | 1199 | int count; |
1259 | 1200 | ||
1260 | FD_ZERO(&readSet); | 1201 | FD_ZERO(&readSet); |
1202 | FD_ZERO(&writeSet); | ||
1261 | FD_SET(inFd, &readSet); | 1203 | FD_SET(inFd, &readSet); |
1262 | 1204 | if(bodyLen > 0 || post_readed_size > 0) { | |
1205 | FD_SET(outFd, &writeSet); | ||
1206 | nfound = outFd > inFd ? outFd : inFd; | ||
1207 | if(post_readed_size == 0) { | ||
1208 | FD_SET(a_c_r, &readSet); | ||
1209 | if(nfound < a_c_r) | ||
1210 | nfound = a_c_r; | ||
1211 | } | ||
1263 | /* Now wait on the set of sockets! */ | 1212 | /* Now wait on the set of sockets! */ |
1264 | timeout.tv_sec = 0; | 1213 | nfound = select(nfound + 1, &readSet, &writeSet, 0, NULL); |
1265 | timeout.tv_usec = 10000; | 1214 | } else { |
1266 | nfound = select(inFd + 1, &readSet, 0, 0, &timeout); | 1215 | if(!bodyLen) { |
1216 | close(outFd); | ||
1217 | bodyLen = -1; | ||
1218 | } | ||
1219 | nfound = select(inFd + 1, &readSet, 0, 0, NULL); | ||
1220 | } | ||
1267 | 1221 | ||
1268 | if (nfound <= 0) { | 1222 | if (nfound <= 0) { |
1269 | if (waitpid(pid, &status, WNOHANG) > 0) { | 1223 | if (waitpid(pid, &status, WNOHANG) > 0) { |
@@ -1276,29 +1230,46 @@ static int sendCgi(const char *url, | |||
1276 | bb_error_msg("piped has exited with signal=%d", WTERMSIG(status)); | 1230 | bb_error_msg("piped has exited with signal=%d", WTERMSIG(status)); |
1277 | } | 1231 | } |
1278 | #endif | 1232 | #endif |
1279 | pid = -1; | ||
1280 | break; | 1233 | break; |
1281 | } | 1234 | } |
1235 | } else if(post_readed_size > 0 && FD_ISSET(outFd, &writeSet)) { | ||
1236 | count = bb_full_write(outFd, wbuf + post_readed_idx, post_readed_size); | ||
1237 | if(count > 0) { | ||
1238 | post_readed_size -= count; | ||
1239 | post_readed_idx += count; | ||
1240 | if(post_readed_size == 0) | ||
1241 | post_readed_idx = 0; | ||
1242 | } | ||
1243 | } else if(bodyLen > 0 && post_readed_size == 0 && FD_ISSET(a_c_r, &readSet)) { | ||
1244 | count = bodyLen > sizeof(wbuf) ? sizeof(wbuf) : bodyLen; | ||
1245 | count = bb_full_read(a_c_r, wbuf, count); | ||
1246 | if(count > 0) { | ||
1247 | post_readed_size += count; | ||
1248 | bodyLen -= count; | ||
1282 | } else { | 1249 | } else { |
1250 | bodyLen = 0; /* closed */ | ||
1251 | } | ||
1252 | } else if(FD_ISSET(inFd, &readSet)) { | ||
1283 | int s = a_c_w; | 1253 | int s = a_c_w; |
1254 | char *rbuf = config->buf; | ||
1284 | 1255 | ||
1285 | // There is something to read | 1256 | // There is something to read |
1286 | count = bb_full_read(inFd, buf, sizeof(buf)-1); | 1257 | count = bb_full_read(inFd, rbuf, MAX_MEMORY_BUFF-1); |
1287 | // If a read returns 0 at this point then some type of error has | 1258 | if (count == 0) |
1288 | // occurred. Bail now. | 1259 | break; /* closed */ |
1289 | if (count == 0) break; | ||
1290 | if (count > 0) { | 1260 | if (count > 0) { |
1291 | if (firstLine) { | 1261 | if (firstLine) { |
1262 | rbuf[count] = 0; | ||
1292 | /* check to see if the user script added headers */ | 1263 | /* check to see if the user script added headers */ |
1293 | if (strncmp(buf, "HTTP/1.0 200 OK\n", 4) != 0) { | 1264 | if(strncmp(rbuf, "HTTP/1.0 200 OK\n", 4) != 0) { |
1294 | bb_full_write(s, "HTTP/1.0 200 OK\n", 16); | 1265 | bb_full_write(s, "HTTP/1.0 200 OK\n", 16); |
1295 | } | 1266 | } |
1296 | if (strstr(buf, "ontent-") == 0) { | 1267 | if (strstr(rbuf, "ontent-") == 0) { |
1297 | bb_full_write(s, "Content-type: text/plain\n\n", 26); | 1268 | bb_full_write(s, "Content-type: text/plain\n\n", 26); |
1298 | } | 1269 | } |
1299 | firstLine=0; | 1270 | firstLine = 0; |
1300 | } | 1271 | } |
1301 | bb_full_write(s, buf, count); | 1272 | bb_full_write(s, rbuf, count); |
1302 | #ifdef DEBUG | 1273 | #ifdef DEBUG |
1303 | if (config->debugHttpd) | 1274 | if (config->debugHttpd) |
1304 | fprintf(stderr, "cgi read %d bytes\n", count); | 1275 | fprintf(stderr, "cgi read %d bytes\n", count); |
@@ -1319,12 +1290,11 @@ static int sendCgi(const char *url, | |||
1319 | * | 1290 | * |
1320 | * $Parameter: | 1291 | * $Parameter: |
1321 | * (const char *) url . . The URL requested. | 1292 | * (const char *) url . . The URL requested. |
1322 | * (char *) buf . . . . . The stack buffer. | ||
1323 | * | 1293 | * |
1324 | * $Return: (int) . . . . . . Always 0. | 1294 | * $Return: (int) . . . . . . Always 0. |
1325 | * | 1295 | * |
1326 | ****************************************************************************/ | 1296 | ****************************************************************************/ |
1327 | static int sendFile(const char *url, char *buf) | 1297 | static int sendFile(const char *url) |
1328 | { | 1298 | { |
1329 | char * suffix; | 1299 | char * suffix; |
1330 | int f; | 1300 | int f; |
@@ -1363,6 +1333,7 @@ static int sendFile(const char *url, char *buf) | |||
1363 | f = open(url, O_RDONLY); | 1333 | f = open(url, O_RDONLY); |
1364 | if (f >= 0) { | 1334 | if (f >= 0) { |
1365 | int count; | 1335 | int count; |
1336 | char *buf = config->buf; | ||
1366 | 1337 | ||
1367 | sendHeaders(HTTP_OK); | 1338 | sendHeaders(HTTP_OK); |
1368 | while ((count = bb_full_read(f, buf, MAX_MEMORY_BUFF)) > 0) { | 1339 | while ((count = bb_full_read(f, buf, MAX_MEMORY_BUFF)) > 0) { |
@@ -1449,20 +1420,21 @@ static int checkPerm(const char *path, const char *request) | |||
1449 | 1420 | ||
1450 | if(strncmp(p0, path, l) == 0 && | 1421 | if(strncmp(p0, path, l) == 0 && |
1451 | (l == 1 || path[l] == '/' || path[l] == 0)) { | 1422 | (l == 1 || path[l] == '/' || path[l] == 0)) { |
1423 | char *u; | ||
1452 | /* path match found. Check request */ | 1424 | /* path match found. Check request */ |
1453 | |||
1454 | /* for check next /path:user:password */ | 1425 | /* for check next /path:user:password */ |
1455 | prev = p0; | 1426 | prev = p0; |
1427 | u = strchr(request, ':'); | ||
1428 | if(u == NULL) { | ||
1429 | /* bad request, ':' required */ | ||
1430 | break; | ||
1431 | } | ||
1432 | |||
1456 | #ifdef CONFIG_FEATURE_HTTPD_AUTH_MD5 | 1433 | #ifdef CONFIG_FEATURE_HTTPD_AUTH_MD5 |
1457 | { | 1434 | { |
1458 | char *cipher; | 1435 | char *cipher; |
1459 | char *pp; | 1436 | char *pp; |
1460 | char *u = strchr(request, ':'); | ||
1461 | 1437 | ||
1462 | if(u == NULL) { | ||
1463 | /* bad request, ':' required */ | ||
1464 | continue; | ||
1465 | } | ||
1466 | if(strncmp(p, request, u-request) != 0) { | 1438 | if(strncmp(p, request, u-request) != 0) { |
1467 | /* user uncompared */ | 1439 | /* user uncompared */ |
1468 | continue; | 1440 | continue; |
@@ -1473,14 +1445,19 @@ static int checkPerm(const char *path, const char *request) | |||
1473 | pp++; | 1445 | pp++; |
1474 | cipher = pw_encrypt(u+1, pp); | 1446 | cipher = pw_encrypt(u+1, pp); |
1475 | if (strcmp(cipher, pp) == 0) | 1447 | if (strcmp(cipher, pp) == 0) |
1476 | return 1; /* Ok */ | 1448 | goto set_remoteuser_var; /* Ok */ |
1477 | /* unauthorized */ | 1449 | /* unauthorized */ |
1478 | continue; | 1450 | continue; |
1479 | } | 1451 | } |
1480 | } | 1452 | } |
1481 | #endif | 1453 | #endif |
1482 | if (strcmp(p, request) == 0) | 1454 | if (strcmp(p, request) == 0) { |
1455 | set_remoteuser_var: | ||
1456 | config->remoteuser = strdup(request); | ||
1457 | if(config->remoteuser) | ||
1458 | config->remoteuser[(u - request)] = 0; | ||
1483 | return 1; /* Ok */ | 1459 | return 1; /* Ok */ |
1460 | } | ||
1484 | /* unauthorized */ | 1461 | /* unauthorized */ |
1485 | } | 1462 | } |
1486 | } | 1463 | } |
@@ -1508,9 +1485,9 @@ static void handleIncoming(void) | |||
1508 | char *urlArgs; | 1485 | char *urlArgs; |
1509 | #ifdef CONFIG_FEATURE_HTTPD_CGI | 1486 | #ifdef CONFIG_FEATURE_HTTPD_CGI |
1510 | const char *prequest = request_GET; | 1487 | const char *prequest = request_GET; |
1511 | char *body = 0; | ||
1512 | long length=0; | 1488 | long length=0; |
1513 | char *cookie = 0; | 1489 | char *cookie = 0; |
1490 | char *content_type = 0; | ||
1514 | #endif | 1491 | #endif |
1515 | char *test; | 1492 | char *test; |
1516 | struct stat sb; | 1493 | struct stat sb; |
@@ -1523,7 +1500,7 @@ static void handleIncoming(void) | |||
1523 | do { | 1500 | do { |
1524 | int count; | 1501 | int count; |
1525 | 1502 | ||
1526 | if (getLine(buf) <= 0) | 1503 | if (getLine() <= 0) |
1527 | break; /* closed */ | 1504 | break; /* closed */ |
1528 | 1505 | ||
1529 | purl = strpbrk(buf, " \t"); | 1506 | purl = strpbrk(buf, " \t"); |
@@ -1621,7 +1598,7 @@ BAD_REQUEST: | |||
1621 | } | 1598 | } |
1622 | 1599 | ||
1623 | // read until blank line for HTTP version specified, else parse immediate | 1600 | // read until blank line for HTTP version specified, else parse immediate |
1624 | while (blank >= 0 && (count = getLine(buf)) > 0) { | 1601 | while (blank >= 0 && (count = getLine()) > 0) { |
1625 | 1602 | ||
1626 | #ifdef DEBUG | 1603 | #ifdef DEBUG |
1627 | if (config->debugHttpd) fprintf(stderr, "Header: '%s'\n", buf); | 1604 | if (config->debugHttpd) fprintf(stderr, "Header: '%s'\n", buf); |
@@ -1636,6 +1613,14 @@ BAD_REQUEST: | |||
1636 | for(test = buf + 7; isspace(*test); test++) | 1613 | for(test = buf + 7; isspace(*test); test++) |
1637 | ; | 1614 | ; |
1638 | cookie = strdup(test); | 1615 | cookie = strdup(test); |
1616 | } else if ((strncasecmp(buf, "Content-Type:", 13) == 0)) { | ||
1617 | for(test = buf + 13; isspace(*test); test++) | ||
1618 | ; | ||
1619 | content_type = strdup(test); | ||
1620 | } else if ((strncasecmp(buf, "Referer:", 8) == 0)) { | ||
1621 | for(test = buf + 8; isspace(*test); test++) | ||
1622 | ; | ||
1623 | config->referer = strdup(test); | ||
1639 | } | 1624 | } |
1640 | #endif | 1625 | #endif |
1641 | 1626 | ||
@@ -1679,23 +1664,13 @@ FORBIDDEN: /* protect listing /cgi-bin */ | |||
1679 | 1664 | ||
1680 | #ifdef CONFIG_FEATURE_HTTPD_CGI | 1665 | #ifdef CONFIG_FEATURE_HTTPD_CGI |
1681 | /* if strange Content-Length */ | 1666 | /* if strange Content-Length */ |
1682 | if (length < 0 || length > MAX_POST_SIZE) | 1667 | if (length < 0) |
1683 | break; | 1668 | break; |
1684 | 1669 | ||
1685 | if (length > 0) { | ||
1686 | body = malloc(length + 1); | ||
1687 | if (body) { | ||
1688 | length = bb_full_read(a_c_r, body, length); | ||
1689 | if(length < 0) // closed | ||
1690 | length = 0; | ||
1691 | body[length] = 0; // always null terminate for safety | ||
1692 | } | ||
1693 | } | ||
1694 | |||
1695 | if (strncmp(test, "cgi-bin", 7) == 0) { | 1670 | if (strncmp(test, "cgi-bin", 7) == 0) { |
1696 | if(test[7] == '/' && test[8] == 0) | 1671 | if(test[7] == '/' && test[8] == 0) |
1697 | goto FORBIDDEN; // protect listing cgi-bin/ | 1672 | goto FORBIDDEN; // protect listing cgi-bin/ |
1698 | sendCgi(url, prequest, urlArgs, body, length, cookie); | 1673 | sendCgi(url, prequest, urlArgs, length, cookie, content_type); |
1699 | } else { | 1674 | } else { |
1700 | if (prequest != request_GET) | 1675 | if (prequest != request_GET) |
1701 | sendHeaders(HTTP_NOT_IMPLEMENTED); | 1676 | sendHeaders(HTTP_NOT_IMPLEMENTED); |
@@ -1707,7 +1682,7 @@ FORBIDDEN: /* protect listing /cgi-bin */ | |||
1707 | config->ContentLength = sb.st_size; | 1682 | config->ContentLength = sb.st_size; |
1708 | config->last_mod = sb.st_mtime; | 1683 | config->last_mod = sb.st_mtime; |
1709 | } | 1684 | } |
1710 | sendFile(test, buf); | 1685 | sendFile(test); |
1711 | #ifndef CONFIG_FEATURE_HTTPD_USAGE_FROM_INETD_ONLY | 1686 | #ifndef CONFIG_FEATURE_HTTPD_USAGE_FROM_INETD_ONLY |
1712 | /* unset if non inetd looped */ | 1687 | /* unset if non inetd looped */ |
1713 | config->ContentLength = -1; | 1688 | config->ContentLength = -1; |
@@ -1727,8 +1702,10 @@ FORBIDDEN: /* protect listing /cgi-bin */ | |||
1727 | if (config->debugHttpd) fprintf(stderr, "closing socket\n"); | 1702 | if (config->debugHttpd) fprintf(stderr, "closing socket\n"); |
1728 | # endif | 1703 | # endif |
1729 | # ifdef CONFIG_FEATURE_HTTPD_CGI | 1704 | # ifdef CONFIG_FEATURE_HTTPD_CGI |
1730 | free(body); | ||
1731 | free(cookie); | 1705 | free(cookie); |
1706 | free(content_type); | ||
1707 | free(config->remoteuser); | ||
1708 | free(config->referer); | ||
1732 | # endif | 1709 | # endif |
1733 | shutdown(a_c_w, SHUT_WR); | 1710 | shutdown(a_c_w, SHUT_WR); |
1734 | shutdown(a_c_r, SHUT_RD); | 1711 | shutdown(a_c_r, SHUT_RD); |
@@ -1997,13 +1974,12 @@ int httpd_main(int argc, char *argv[]) | |||
1997 | #ifdef CONFIG_FEATURE_HTTPD_CGI | 1974 | #ifdef CONFIG_FEATURE_HTTPD_CGI |
1998 | { | 1975 | { |
1999 | char *p = getenv("PATH"); | 1976 | char *p = getenv("PATH"); |
2000 | |||
2001 | if(p) | ||
2002 | p = bb_xstrdup(p); | ||
2003 | clearenv(); | ||
2004 | if(p) { | 1977 | if(p) { |
2005 | setenv("PATH", p, 0); | 1978 | p = bb_xstrdup(p); |
2006 | } | 1979 | } |
1980 | clearenv(); | ||
1981 | if(p) | ||
1982 | setenv("PATH", p, 1); | ||
2007 | # ifndef CONFIG_FEATURE_HTTPD_USAGE_FROM_INETD_ONLY | 1983 | # ifndef CONFIG_FEATURE_HTTPD_USAGE_FROM_INETD_ONLY |
2008 | addEnvPort("SERVER"); | 1984 | addEnvPort("SERVER"); |
2009 | # endif | 1985 | # endif |