src/server/safs/cgi.c

changeset 162
b169992137a8
parent 161
aadda87bad1b
child 164
6f47eb624665
--- 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

mercurial