--- a/src/server/safs/cgi.c Thu Jan 26 18:53:52 2017 +0100 +++ b/src/server/safs/cgi.c Sat Jan 28 10:38:34 2017 +0100 @@ -32,6 +32,10 @@ #include <stdlib.h> #include <unistd.h> +#include <sys/types.h> +#include <signal.h> +#include <sys/wait.h> + #include "../util/util.h" #include "../util/pblock.h" #include "../../ucx/string.h" @@ -99,11 +103,26 @@ while(n < content_length) { r = netbuf_getbytes(sn->inbuf, buf, 4096); if(r <= 0) { - // TODO: handleerror + // TODO: handle error + log_ereport( + LOG_FAILURE, + "send-cgi: script: %s: cannot read request body", + path); + kill(cgip.pid, SIGTERM); cgi_close(&cgip); - return REQ_ABORTED; + return REQ_ABORTED; } - write(cgip.in[1], buf, r); + ssize_t w = write(cgip.in[1], buf, r); + if(w <= 0) { + // TODO: handle error + log_ereport( + LOG_FAILURE, + "send-cgi: script: %s: cannot send request body to cgi process", + path); + kill(cgip.pid, SIGKILL); + cgi_close(&cgip); + return REQ_ABORTED; + } n += r; } } @@ -114,17 +133,19 @@ CGIResponseParser *parser = cgi_parser_new(sn, rq); WSBool cgiheader = TRUE; ssize_t wr = 0; - int result = REQ_PROCEED; + int result = REQ_PROCEED; + size_t response_length = 0; while((r = read(cgip.out[0], buf, 4096)) > 0) { if(cgiheader) { size_t pos; ret = cgi_parse_response(parser, buf, r, &pos); if(ret == -1) { + log_ereport( + LOG_FAILURE, + "broken cgi script response: path: %s", path); protocol_status(sn, rq, 500, NULL); result = REQ_ABORTED; break; - } else if(ret == 0) { - } else if(ret == 1) { cgiheader = FALSE; if(parser->status > 0) { @@ -132,6 +153,7 @@ } http_start_response(sn, rq); if(pos < r) { + response_length += r-pos; wr = net_write(sn->csd, &buf[pos], r-pos); if(wr <= 0) { result = REQ_ABORTED; @@ -140,6 +162,7 @@ } } } else { + response_length = r; wr = net_write(sn->csd, buf, r); if(wr <= 0) { result = REQ_ABORTED; @@ -148,7 +171,26 @@ } } - cgi_close(&cgip); + char *ctlen_header = pblock_findkeyval(pb_key_content_length, rq->srvhdrs); + if(ctlen_header) { + int64_t ctlenhdr; + if(util_strtoint(ctlen_header, &ctlenhdr)) { + if(ctlenhdr != response_length) { + log_ereport( + LOG_FAILURE, + "cgi-send: script: %s: content length mismatch", + path); + rq->rq_attr.keep_alive = 0; + result = REQ_ABORTED; + } + } + } + + if(result == REQ_ABORTED) { + log_ereport(LOG_FAILURE, "cgi-send: kill script: %s", path); + kill(cgip.pid, SIGKILL); + } + cgi_close(&cgip); // TODO: check return value cgi_parser_free(parser); return result; @@ -209,7 +251,10 @@ return REQ_PROCEED; } -void cgi_close(CGIProcess *p) { +int cgi_close(CGIProcess *p) { + int status = -1; + waitpid(p->pid, &status, 0); + if(p->in[0] != -1) { close(p->in[0]); } @@ -222,6 +267,8 @@ if(p->out[1] != -1) { close(p->out[1]); } + + return 0; } CGIResponseParser* cgi_parser_new(Session *sn, Request *rq) { @@ -386,5 +433,4 @@ return 1; } } -} - +} \ No newline at end of file