diff options
author | vda <vda@69ca8d6d-28ef-0310-b511-8ec308f3f277> | 2007-02-11 19:51:06 +0000 |
---|---|---|
committer | vda <vda@69ca8d6d-28ef-0310-b511-8ec308f3f277> | 2007-02-11 19:51:06 +0000 |
commit | 6b6a7891b2f9e3970f8e3067579d4352561be034 (patch) | |
tree | 199456a861abdbe489168f02cba6fe325edfbc7b | |
parent | 65ba6e76598417848b028c45365bc45f1c008f2f (diff) | |
download | busybox-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.c | 48 |
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) |