aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorvda <vda@69ca8d6d-28ef-0310-b511-8ec308f3f277>2007-02-11 19:51:06 +0000
committervda <vda@69ca8d6d-28ef-0310-b511-8ec308f3f277>2007-02-11 19:51:06 +0000
commit6b6a7891b2f9e3970f8e3067579d4352561be034 (patch)
tree199456a861abdbe489168f02cba6fe325edfbc7b
parent65ba6e76598417848b028c45365bc45f1c008f2f (diff)
downloadbusybox-w32-6b6a7891b2f9e3970f8e3067579d4352561be034.tar.gz
busybox-w32-6b6a7891b2f9e3970f8e3067579d4352561be034.tar.bz2
busybox-w32-6b6a7891b2f9e3970f8e3067579d4352561be034.zip
httpd: fix for POSTDATA handling bugs:
erroneous close(0) full_read -> safe_read (with explanation) git-svn-id: svn://busybox.net/trunk/busybox@17857 69ca8d6d-28ef-0310-b511-8ec308f3f277
-rw-r--r--networking/httpd.c48
1 files changed, 24 insertions, 24 deletions
diff --git a/networking/httpd.c b/networking/httpd.c
index fb363c56f..6f4ca05a7 100644
--- a/networking/httpd.c
+++ b/networking/httpd.c
@@ -950,7 +950,6 @@ static int getLine(void)
950 * (int bodyLen) . . . . . . . . Length of the post body. 950 * (int bodyLen) . . . . . . . . Length of the post body.
951 * (const char *cookie) . . . . . For set HTTP_COOKIE. 951 * (const char *cookie) . . . . . For set HTTP_COOKIE.
952 * (const char *content_type) . . For set CONTENT_TYPE. 952 * (const char *content_type) . . For set CONTENT_TYPE.
953
954 * 953 *
955 * $Return: (char *) . . . . A pointer to the decoded string (same as input). 954 * $Return: (char *) . . . . A pointer to the decoded string (same as input).
956 * 955 *
@@ -984,31 +983,32 @@ static int sendCgi(const char *url,
984 if (!pid) { 983 if (!pid) {
985 /* child process */ 984 /* child process */
986 char *script; 985 char *script;
987 char *purl = xstrdup(url); 986 char *purl;
988 char realpath_buff[MAXPATHLEN]; 987 char realpath_buff[MAXPATHLEN];
989 988
990 if (purl == NULL) 989 if (config->accepted_socket > 1)
991 _exit(242); 990 close(config->accepted_socket);
992 991 if (config->server_socket > 1)
993 inFd = toCgi[0]; 992 close(config->server_socket);
994 outFd = fromCgi[1];
995 993
996 dup2(inFd, 0); // replace stdin with the pipe 994 dup2(toCgi[0], 0); // replace stdin with the pipe
997 dup2(outFd, 1); // replace stdout with the pipe 995 dup2(fromCgi[1], 1); // replace stdout with the pipe
996 /* Huh? User seeing stderr can be a security problem...
997 * and if cgi really wants that, it can always dup2(1,2)...
998 if (!DEBUG) 998 if (!DEBUG)
999 dup2(outFd, 2); // replace stderr with the pipe 999 dup2(fromCgi[1], 2); // replace stderr with the pipe
1000 1000 */
1001 /* I think we cannot inadvertently close 0, 1 here... */
1001 close(toCgi[0]); 1002 close(toCgi[0]);
1002 close(toCgi[1]); 1003 close(toCgi[1]);
1003 close(fromCgi[0]); 1004 close(fromCgi[0]);
1004 close(fromCgi[1]); 1005 close(fromCgi[1]);
1005 1006
1006 close(config->accepted_socket);
1007 close(config->server_socket);
1008
1009 /* 1007 /*
1010 * Find PATH_INFO. 1008 * Find PATH_INFO.
1011 */ 1009 */
1010 xfunc_error_retval = 242;
1011 purl = xstrdup(url);
1012 script = purl; 1012 script = purl;
1013 while ((script = strchr(script + 1, '/')) != NULL) { 1013 while ((script = strchr(script + 1, '/')) != NULL) {
1014 /* have script.cgi/PATH_INFO or dirs/script.cgi[/PATH_INFO] */ 1014 /* have script.cgi/PATH_INFO or dirs/script.cgi[/PATH_INFO] */
@@ -1210,33 +1210,33 @@ static int sendCgi(const char *url,
1210#if PIPESIZE >= MAX_MEMORY_BUFF 1210#if PIPESIZE >= MAX_MEMORY_BUFF
1211# error "PIPESIZE >= MAX_MEMORY_BUFF" 1211# error "PIPESIZE >= MAX_MEMORY_BUFF"
1212#endif 1212#endif
1213 /* NB: was safe_read. If it *has to be* safe_read, */ 1213 /* Must use safe_read, not full_read, because
1214 /* please explain why in this comment... */ 1214 * cgi may output a few first lines and then wait
1215 count = full_read(inFd, rbuf, PIPESIZE); 1215 * for POSTDATA without closing stdout.
1216 * With full_read we may wait here forever. */
1217 count = safe_read(inFd, rbuf, PIPESIZE);
1216 if (count == 0) 1218 if (count == 0)
1217 break; /* closed */ 1219 break; /* closed */
1218 if (count < 0) 1220 if (count < 0)
1219 continue; /* huh, error, why continue?? */ 1221 continue; /* huh, error, why continue?? */
1220 1222
1221 if (firstLine) { 1223 if (firstLine) {
1222 /* full_read (above) avoids 1224 static const char HTTP_200[] = "HTTP/1.0 200 OK\r\n\r\n";
1223 * "chopped up into small chunks" syndrome here */
1224 rbuf[count] = '\0'; 1225 rbuf[count] = '\0';
1225 /* check to see if the user script added headers */ 1226 /* check to see if the user script added headers */
1226#define HTTP_200 "HTTP/1.0 200 OK\r\n\r\n" 1227 /* (NB: buggy wrt cgi splitting "HTTP OK") */
1227 if (memcmp(rbuf, HTTP_200, 4) != 0) { 1228 if (memcmp(rbuf, HTTP_200, 4) != 0) {
1228 /* there is no "HTTP", do it ourself */ 1229 /* there is no "HTTP", do it ourself */
1229 full_write(s, HTTP_200, sizeof(HTTP_200)-1); 1230 full_write(s, HTTP_200, sizeof(HTTP_200)-1);
1230 } 1231 }
1231#undef HTTP_200
1232 /* Example of valid GCI without "Content-type:" 1232 /* Example of valid GCI without "Content-type:"
1233 * echo -en "HTTP/1.0 302 Found\r\n" 1233 * echo -en "HTTP/1.0 302 Found\r\n"
1234 * echo -en "Location: http://www.busybox.net\r\n" 1234 * echo -en "Location: http://www.busybox.net\r\n"
1235 * echo -en "\r\n" 1235 * echo -en "\r\n"
1236 if (!strstr(rbuf, "ontent-")) {
1237 full_write(s, "Content-type: text/plain\r\n\r\n", 28);
1238 }
1236 */ 1239 */
1237 //if (!strstr(rbuf, "ontent-")) {
1238 // full_write(s, "Content-type: text/plain\r\n\r\n", 28);
1239 //}
1240 firstLine = 0; 1240 firstLine = 0;
1241 } 1241 }
1242 if (full_write(s, rbuf, count) != count) 1242 if (full_write(s, rbuf, count) != count)