Hi

Third time's the charm.

A magic fairy told me someone could do an evil cgi app that sends one line 
break after headers and the other-style line break at the start of the content.

This fixes it. Thank you, magic fairy.

This applies on top of all the previous ones.

- Lauri
>From 0b19b5ba1557b2e56a8dc41de2c848c9e909bf25 Mon Sep 17 00:00:00 2001
From: Lauri Kasanen <[email protected]>
Date: Mon, 17 Dec 2012 16:26:55 +0200
Subject: [PATCH] cgi: Check both line break styles and use the earlier one.


Signed-off-by: Lauri Kasanen <[email protected]>
---
 plugins/cgi/event.c |   45 ++++++++++++++++++++++++++++++++++++---------
 1 files changed, 36 insertions(+), 9 deletions(-)

diff --git a/plugins/cgi/event.c b/plugins/cgi/event.c
index 1b8a19b..ccddc9d 100644
--- a/plugins/cgi/event.c
+++ b/plugins/cgi/event.c
@@ -20,6 +20,41 @@
 
 #include "cgi.h"
 
+/* Get the earliest break between headers and content.
+
+   The reason for this function is that some CGI apps
+   use LFLF and some use CRLFCRLF.
+
+   If that app then sends content that has the other break
+   in the beginning, monkey can accidentally send part of the
+   content as headers.
+*/
+static char *getearliestbreak(const char buf[], const unsigned bufsize,
+                               unsigned char * const advance) {
+
+    char * const crend = memmem(buf, bufsize, MK_IOV_CRLFCRLF,
+                               sizeof(MK_IOV_CRLFCRLF) - 1);
+    char * const lfend = memmem(buf, bufsize, MK_IOV_LFLF,
+                               sizeof(MK_IOV_LFLF) - 1);
+
+    // If only one found, return that one
+    if (!crend && !lfend)
+        return NULL;
+    if (!crend) {
+        *advance = 2;
+        return lfend;
+    }
+    if (!lfend)
+        return crend;
+
+    // Both found, return the earlier one - the latter one is part of content
+    if (lfend < crend) {
+        *advance = 2;
+        return lfend;
+    }
+    return crend;
+}
+
 static void done(const int socket) {
 
     struct cgi_request *r = cgi_req_get_by_fd(socket);
@@ -121,15 +156,7 @@ int _mkp_event_write(int socket)
             unsigned char advance = 4;
 
             // Write the rest of the headers without chunking
-            char *end = strstr(outptr, MK_IOV_CRLFCRLF);
-            if (!end) {
-                end = strstr(outptr, MK_IOV_LFLF);
-                advance = 2;
-            }
-            if (!end) {
-                end = strstr(outptr, MK_IOV_LFLFLFLF);
-                advance = 4;
-            }
+            char *end = getearliestbreak(outptr, r->in_len, &advance);
             if (!end)
             {
                 swrite(socket, outptr, r->in_len);
-- 
1.7.2.1

_______________________________________________
Monkey mailing list
[email protected]
http://lists.monkey-project.com/listinfo/monkey

Reply via email to