httpd: a little bit more correct handling of CGI "HTTP/xxx" output
This commit is contained in:
parent
e54b472ffc
commit
b5368bf437
@ -7,8 +7,6 @@
|
|||||||
* Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
|
* Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include "libbb.h"
|
#include "libbb.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -967,7 +967,7 @@ static int sendCgi(const char *url,
|
|||||||
int pid = 0;
|
int pid = 0;
|
||||||
int inFd;
|
int inFd;
|
||||||
int outFd;
|
int outFd;
|
||||||
int firstLine = 1;
|
int buf_count;
|
||||||
int status;
|
int status;
|
||||||
size_t post_read_size, post_read_idx;
|
size_t post_read_size, post_read_idx;
|
||||||
|
|
||||||
@ -994,7 +994,7 @@ static int sendCgi(const char *url,
|
|||||||
dup2(toCgi[0], 0); // replace stdin with the pipe
|
dup2(toCgi[0], 0); // replace stdin with the pipe
|
||||||
dup2(fromCgi[1], 1); // replace stdout with the pipe
|
dup2(fromCgi[1], 1); // replace stdout with the pipe
|
||||||
/* Huh? User seeing stderr can be a security problem...
|
/* Huh? User seeing stderr can be a security problem...
|
||||||
* and if cgi really wants that, it can always dup2(1,2)...
|
* and if CGI really wants that, it can always dup2(1,2)...
|
||||||
if (!DEBUG)
|
if (!DEBUG)
|
||||||
dup2(fromCgi[1], 2); // replace stderr with the pipe
|
dup2(fromCgi[1], 2); // replace stderr with the pipe
|
||||||
*/
|
*/
|
||||||
@ -1125,6 +1125,7 @@ static int sendCgi(const char *url,
|
|||||||
|
|
||||||
/* parent process */
|
/* parent process */
|
||||||
|
|
||||||
|
buf_count = 0;
|
||||||
post_read_size = 0;
|
post_read_size = 0;
|
||||||
post_read_idx = 0; /* for gcc */
|
post_read_idx = 0; /* for gcc */
|
||||||
inFd = fromCgi[0];
|
inFd = fromCgi[0];
|
||||||
@ -1162,10 +1163,11 @@ static int sendCgi(const char *url,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (nfound <= 0) {
|
if (nfound <= 0) {
|
||||||
if (waitpid(pid, &status, WNOHANG) <= 0)
|
if (waitpid(pid, &status, WNOHANG) <= 0) {
|
||||||
/* Weird. CGI didn't exit and no fd's
|
/* Weird. CGI didn't exit and no fd's
|
||||||
* are ready, yet select returned?! */
|
* are ready, yet select returned?! */
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
close(inFd);
|
close(inFd);
|
||||||
if (DEBUG && WIFEXITED(status))
|
if (DEBUG && WIFEXITED(status))
|
||||||
bb_error_msg("piped has exited with status=%d", WEXITSTATUS(status));
|
bb_error_msg("piped has exited with status=%d", WEXITSTATUS(status));
|
||||||
@ -1190,7 +1192,7 @@ static int sendCgi(const char *url,
|
|||||||
) {
|
) {
|
||||||
/* We expect data, prev data portion is eaten by CGI
|
/* We expect data, prev data portion is eaten by CGI
|
||||||
* and there *is* data to read from the peer
|
* and there *is* data to read from the peer
|
||||||
* (POST data?) */
|
* (POSTDATA?) */
|
||||||
count = bodyLen > (int)sizeof(wbuf) ? (int)sizeof(wbuf) : bodyLen;
|
count = bodyLen > (int)sizeof(wbuf) ? (int)sizeof(wbuf) : bodyLen;
|
||||||
count = safe_read(config->accepted_socket, wbuf, count);
|
count = safe_read(config->accepted_socket, wbuf, count);
|
||||||
if (count > 0) {
|
if (count > 0) {
|
||||||
@ -1202,42 +1204,56 @@ static int sendCgi(const char *url,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (FD_ISSET(inFd, &readSet)) {
|
|
||||||
/* There is something to read from CGI */
|
|
||||||
int s = config->accepted_socket;
|
|
||||||
char *rbuf = config->buf;
|
|
||||||
#define PIPESIZE PIPE_BUF
|
#define PIPESIZE PIPE_BUF
|
||||||
#if PIPESIZE >= MAX_MEMORY_BUFF
|
#if PIPESIZE >= MAX_MEMORY_BUFF
|
||||||
# error "PIPESIZE >= MAX_MEMORY_BUFF"
|
# error "PIPESIZE >= MAX_MEMORY_BUFF"
|
||||||
#endif
|
#endif
|
||||||
/* Must use safe_read, not full_read, because
|
if (FD_ISSET(inFd, &readSet)) {
|
||||||
* cgi may output a few first lines and then wait
|
/* There is something to read from CGI */
|
||||||
* for POSTDATA without closing stdout.
|
int s = config->accepted_socket;
|
||||||
* With full_read we may wait here forever. */
|
char *rbuf = config->buf;
|
||||||
count = safe_read(inFd, rbuf, PIPESIZE);
|
|
||||||
if (count == 0)
|
|
||||||
break; /* closed */
|
|
||||||
if (count < 0)
|
|
||||||
continue; /* huh, error, why continue?? */
|
|
||||||
|
|
||||||
if (firstLine) {
|
/* Are we still buffering CGI output? */
|
||||||
|
if (buf_count >= 0) {
|
||||||
static const char HTTP_200[] = "HTTP/1.0 200 OK\r\n\r\n";
|
static const char HTTP_200[] = "HTTP/1.0 200 OK\r\n\r\n";
|
||||||
rbuf[count] = '\0';
|
/* Must use safe_read, not full_read, because
|
||||||
/* check to see if the user script added headers */
|
* CGI may output a few first bytes and then wait
|
||||||
/* (NB: buggy wrt cgi splitting "HTTP OK") */
|
* for POSTDATA without closing stdout.
|
||||||
if (memcmp(rbuf, HTTP_200, 4) != 0) {
|
* With full_read we may wait here forever. */
|
||||||
/* there is no "HTTP", do it ourself */
|
count = safe_read(inFd, rbuf + buf_count, PIPESIZE - 4);
|
||||||
full_write(s, HTTP_200, sizeof(HTTP_200)-1);
|
if (count <= 0) {
|
||||||
|
/* eof (or error) and there was no "HTTP",
|
||||||
|
* so add one and write out the received data */
|
||||||
|
if (buf_count) {
|
||||||
|
full_write(s, HTTP_200, sizeof(HTTP_200)-1);
|
||||||
|
full_write(s, rbuf, buf_count);
|
||||||
|
}
|
||||||
|
break; /* closed */
|
||||||
}
|
}
|
||||||
/* Example of valid GCI without "Content-type:"
|
buf_count += count;
|
||||||
* echo -en "HTTP/1.0 302 Found\r\n"
|
count = 0;
|
||||||
* echo -en "Location: http://www.busybox.net\r\n"
|
if (buf_count >= 4) {
|
||||||
* echo -en "\r\n"
|
/* check to see if CGI added "HTTP" */
|
||||||
if (!strstr(rbuf, "ontent-")) {
|
if (memcmp(rbuf, HTTP_200, 4) != 0) {
|
||||||
full_write(s, "Content-type: text/plain\r\n\r\n", 28);
|
/* there is no "HTTP", do it ourself */
|
||||||
|
if (full_write(s, HTTP_200, sizeof(HTTP_200)-1) != sizeof(HTTP_200)-1)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* example of valid CGI without "Content-type:"
|
||||||
|
* echo -en "HTTP/1.0 302 Found\r\n"
|
||||||
|
* echo -en "Location: http://www.busybox.net\r\n"
|
||||||
|
* echo -en "\r\n"
|
||||||
|
if (!strstr(rbuf, "ontent-")) {
|
||||||
|
full_write(s, "Content-type: text/plain\r\n\r\n", 28);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
count = buf_count;
|
||||||
|
buf_count = -1; /* buffering off */
|
||||||
}
|
}
|
||||||
*/
|
} else {
|
||||||
firstLine = 0;
|
count = safe_read(inFd, rbuf, PIPESIZE);
|
||||||
|
if (count <= 0)
|
||||||
|
break; /* eof (or error) */
|
||||||
}
|
}
|
||||||
if (full_write(s, rbuf, count) != count)
|
if (full_write(s, rbuf, count) != count)
|
||||||
break;
|
break;
|
||||||
|
Loading…
Reference in New Issue
Block a user