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
