Description: fix denial of service and possible code execution via seeding manager reporter with crafted data Origin: upstream, http://www.squid-cache.org/Versions/v3/3.5/changesets/SQUID-2016_5.patch Index: squid3-3.5.12/src/tests/stub_cbdata.cc =================================================================== --- squid3-3.5.12.orig/src/tests/stub_cbdata.cc 2015-12-02 13:10:29.000000000 -0500 +++ squid3-3.5.12/src/tests/stub_cbdata.cc 2016-06-07 08:07:18.242973870 -0400 @@ -13,7 +13,13 @@ #include "tests/STUB.h" void cbdataRegisterWithCacheManager(void) STUB - +void *cbdataInternalAlloc(cbdata_type type, const char *, int sz) { + return xcalloc(1, sz); +} +void *cbdataInternalFree(void *p, const char *, int) { + xfree(p); + return NULL; +} #if USE_CBDATA_DEBUG void *cbdataInternalAllocDbg(cbdata_type type, const char *, int) STUB_RETVAL(NULL) void *cbdataInternalFreeDbg(void *p, const char *, int) STUB_RETVAL(NULL) Index: squid3-3.5.12/src/tests/stub_mem.cc =================================================================== --- squid3-3.5.12.orig/src/tests/stub_mem.cc 2015-12-02 13:10:29.000000000 -0500 +++ squid3-3.5.12/src/tests/stub_mem.cc 2016-06-07 08:07:18.242973870 -0400 @@ -14,7 +14,7 @@ #define STUB_API "stub_mem.cc" #include "Mem.h" -#include "STUB.h" +#include "tests/STUB.h" void memFreeString(size_t size, void *buf) Index: squid3-3.5.12/tools/Makefile.am =================================================================== --- squid3-3.5.12.orig/tools/Makefile.am 2015-12-02 13:10:29.000000000 -0500 +++ squid3-3.5.12/tools/Makefile.am 2016-06-07 08:07:18.242973870 -0400 @@ -34,15 +34,24 @@ stub_debug.cc: $(top_srcdir)/src/tests/stub_debug.cc cp $(top_srcdir)/src/tests/stub_debug.cc . +MemBuf.cc: $(top_srcdir)/src/MemBuf.cc + cp $(top_srcdir)/src/MemBuf.cc $@ + time.cc: $(top_srcdir)/src/time.cc cp $(top_srcdir)/src/time.cc . +stub_cbdata.cc: $(top_srcdir)/src/tests/stub_cbdata.cc + cp $(top_srcdir)/src/tests/stub_cbdata.cc $@ + +stub_mem.cc: $(top_srcdir)/src/tests/stub_mem.cc + cp $(top_srcdir)/src/tests/stub_mem.cc $@ + # stock tools for unit tests - library independent versions of dlink_list # etc. # globals.cc is needed by test_tools.cc. # Neither of these should be disted from here. TESTSOURCES= test_tools.cc -CLEANFILES += test_tools.cc stub_debug.cc time.cc +CLEANFILES += test_tools.cc MemBuf.cc stub_debug.cc time.cc stub_cbdata.cc stub_mem.cc ## ##### helper-mux ##### @@ -60,7 +69,10 @@ libexec_PROGRAMS = cachemgr$(CGIEXT) cachemgr__CGIEXT__SOURCES = cachemgr.cc \ + MemBuf.cc \ + stub_cbdata.cc \ stub_debug.cc \ + stub_mem.cc \ test_tools.cc \ time.cc Index: squid3-3.5.12/tools/cachemgr.cc =================================================================== --- squid3-3.5.12.orig/tools/cachemgr.cc 2015-12-02 13:10:29.000000000 -0500 +++ squid3-3.5.12/tools/cachemgr.cc 2016-06-07 08:07:18.242973870 -0400 @@ -11,6 +11,7 @@ #include "getfullhostname.h" #include "html_quote.h" #include "ip/Address.h" +#include "MemBuf.h" #include "rfc1123.h" #include "rfc1738.h" #include "util.h" @@ -423,8 +424,8 @@ return url; } -static const char * -munge_menu_line(const char *buf, cachemgr_request * req) +static void +munge_menu_line(MemBuf &out, const char *buf, cachemgr_request * req) { char *x; const char *a; @@ -432,15 +433,14 @@ const char *p; char *a_url; char *buf_copy; - static char html[2 * 1024]; - - if (strlen(buf) < 1) - return buf; - if (*buf != ' ') - return buf; + const char bufLen = strlen(buf); + if (bufLen < 1 || *buf != ' ') { + out.append(buf, bufLen); + return; + } - buf_copy = x = xstrdup(buf); + buf_copy = x = xstrndup(buf, bufLen); a = xstrtok(&x, '\t'); @@ -452,59 +452,56 @@ /* no reason to give a url for a disabled action */ if (!strcmp(p, "disabled")) - snprintf(html, sizeof(html), "
  • %s (disabled).\n", d, a_url); + out.Printf("
  • %s (disabled).\n", d, a_url); else /* disable a hidden action (requires a password, but password is not in squid.conf) */ if (!strcmp(p, "hidden")) - snprintf(html, sizeof(html), "
  • %s (hidden).\n", d, a_url); + out.Printf("
  • %s (hidden).\n", d, a_url); else /* disable link if authentication is required and we have no password */ if (!strcmp(p, "protected") && !req->passwd) - snprintf(html, sizeof(html), "
  • %s (requires authentication).\n", - d, menu_url(req, "authenticate"), a_url); + out.Printf("
  • %s (requires authentication).\n", + d, menu_url(req, "authenticate"), a_url); else /* highlight protected but probably available entries */ if (!strcmp(p, "protected")) - snprintf(html, sizeof(html), "
  • %s\n", - a_url, d); + out.Printf("
  • %s\n", + a_url, d); /* public entry or unknown type of protection */ else - snprintf(html, sizeof(html), "
  • %s\n", a_url, d); + out.Printf("
  • %s\n", a_url, d); xfree(a_url); xfree(buf_copy); - - return html; } -static const char * -munge_other_line(const char *buf, cachemgr_request * req) +static void +munge_other_line(MemBuf &out, const char *buf, cachemgr_request *) { static const char *ttags[] = {"td", "th"}; - static char html[4096]; static int table_line_num = 0; static int next_is_header = 0; int is_header = 0; const char *ttag; char *buf_copy; char *x, *p; - int l = 0; /* does it look like a table? */ if (!strchr(buf, '\t') || *buf == '\t') { /* nope, just text */ - snprintf(html, sizeof(html), "%s%s", - table_line_num ? "\n
    " : "", html_quote(buf));
    +        if (table_line_num)
    +            out.append("\n
    ", 14);
    +        out.Printf("%s", html_quote(buf));
             table_line_num = 0;
    -        return html;
    +        return;
         }
     
         /* start html table */
         if (!table_line_num) {
    -        l += snprintf(html + l, sizeof(html) - l, "
    \n"); + out.append("
    \n", 46); next_is_header = 0; } @@ -514,7 +511,7 @@ ttag = ttags[is_header]; /* record starts */ - l += snprintf(html + l, sizeof(html) - l, ""); + out.append("", 4); /* substitute '\t' */ buf_copy = x = xstrdup(buf); @@ -531,18 +528,17 @@ ++x; } - l += snprintf(html + l, sizeof(html) - l, "<%s colspan=\"%d\" align=\"%s\">%s", - ttag, column_span, - is_header ? "center" : is_number(cell) ? "right" : "left", - html_quote(cell), ttag); + out.Printf("<%s colspan=\"%d\" align=\"%s\">%s", + ttag, column_span, + is_header ? "center" : is_number(cell) ? "right" : "left", + html_quote(cell), ttag); } xfree(buf_copy); /* record ends */ - snprintf(html + l, sizeof(html) - l, "\n"); + out.append("\n", 6); next_is_header = is_header && strstr(buf, "\t\t"); ++table_line_num; - return html; } static const char * @@ -699,14 +695,18 @@ /* yes, fall through, we do not want to loose the first line */ case isBody: + { /* interpret [and reformat] cache response */ - + MemBuf out; + out.init(); if (parse_menu) - fputs(munge_menu_line(buf, req), stdout); + munge_menu_line(out, buf, req); else - fputs(munge_other_line(buf, req), stdout); + munge_other_line(out, buf, req); - break; + fputs(out.buf, stdout); + } + break; case isForward: /* forward: no modifications allowed */