]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
Author: Alexandre SIMON <alexandre.simon@ciril.fr>
authorAmos Jeffries <squid3@treenet.co.nz>
Tue, 1 Feb 2011 11:37:01 +0000 (00:37 +1300)
committerAmos Jeffries <squid3@treenet.co.nz>
Tue, 1 Feb 2011 11:37:01 +0000 (00:37 +1300)
Bug 3144: redirector program blocks while reading STDIN

The string passed to redirect helper program may exceed the available
buffer space and be truncated. Thus having no \n terminator for the helper.

Test for this failure condition and produce an error page.

errors/Makefile.am
errors/templates/ERR_GATEWAY_FAILURE [new file with mode: 0644]
src/redirect.cc

index f45bab175a8ce2560ba126e1d42d97754e87b5db..5bafab0a9db318789eb2dc500bfcb2e0d8b2fb4e 100644 (file)
@@ -29,6 +29,7 @@ ERROR_TEMPLATES =  \
        templates/ERR_FTP_PUT_ERROR \
        templates/ERR_FTP_PUT_MODIFIED \
        templates/ERR_FTP_UNAVAILABLE \
+       templates/ERR_GATEWAY_FAILURE \
        templates/ERR_ICAP_FAILURE \
        templates/ERR_INVALID_REQ \
        templates/ERR_INVALID_RESP \
diff --git a/errors/templates/ERR_GATEWAY_FAILURE b/errors/templates/ERR_GATEWAY_FAILURE
new file mode 100644 (file)
index 0000000..0a0cfeb
--- /dev/null
@@ -0,0 +1,39 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html><head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>ERROR: The requested URL could not be retrieved</title>
+<style type="text/css"><!-- 
+ %l
+
+body
+:lang(fa) { direction: rtl; font-size: 100%; font-family: Tahoma, Roya, sans-serif; float: right; }
+:lang(he) { direction: rtl; float: right; }
+ --></style>
+</head><body>
+<div id="titles">
+<h1>ERROR</h1>
+<h2>The requested URL could not be retrieved</h2>
+</div>
+<hr>
+
+<div id="content">
+<p>The following error was encountered while trying to retrieve the URL: <a href="%U">%U</a></p>
+
+<blockquote id="error">
+<p><b>Gateway Proxy Failure</b></p>
+</blockquote>
+
+<p>A non-recoverable internal failure or configuration problem prevents this request from being completed.</p>
+
+<p>This may be due to limits established by the Internet Service Provider who operates this cache. Please contact them directly for more information.</p>
+
+<p>Your cache administrator is <a href="mailto:%w%W">%w</a>.</p>
+<br>
+</div>
+
+<hr>
+<div id="footer">
+<p>Generated %T by %h (%s)</p>
+<!-- %c -->
+</div>
+</body></html>
index 2474bd798104985dc05ee64c8dcbe47559d14b3e..d84e841df9a7ce22b1d1378932ef024ed592aa29 100644 (file)
 #include "acl/Checklist.h"
 #include "HttpRequest.h"
 #include "client_side.h"
+#include "client_side_reply.h"
 #include "helper.h"
 #include "rfc1738.h"
 #if USE_SSL
 #include "ssl/support.h"
 #endif
 
+/// url maximum lengh + extra informations passed to redirector
+#define MAX_REDIRECTOR_REQUEST_STRLEN (MAX_URL + 1024)
+
 typedef struct {
     void *data;
     char *orig_url;
@@ -117,7 +121,9 @@ redirectStart(ClientHttpRequest * http, RH * handler, void *data)
     ConnStateData * conn = http->getConn();
     redirectStateData *r = NULL;
     const char *fqdn;
-    char buf[8192];
+    char buf[MAX_REDIRECTOR_REQUEST_STRLEN];
+    int sz;
+    http_status status;
     char claddr[MAX_IPSTRLEN];
     char myaddr[MAX_IPSTRLEN];
     assert(http);
@@ -167,14 +173,41 @@ redirectStart(ClientHttpRequest * http, RH * handler, void *data)
     if ((fqdn = fqdncache_gethostbyaddr(r->client_addr, 0)) == NULL)
         fqdn = dash_str;
 
-    snprintf(buf, 8192, "%s %s/%s %s %s myip=%s myport=%d\n",
-             r->orig_url,
-             r->client_addr.NtoA(claddr,MAX_IPSTRLEN),
-             fqdn,
-             r->client_ident[0] ? rfc1738_escape(r->client_ident) : dash_str,
-             r->method_s,
-             http->request->my_addr.NtoA(myaddr,MAX_IPSTRLEN),
-             http->request->my_addr.GetPort());
+    sz = snprintf(buf, MAX_REDIRECTOR_REQUEST_STRLEN, "%s %s/%s %s %s myip=%s myport=%d\n",
+                 r->orig_url,
+                 r->client_addr.NtoA(claddr,MAX_IPSTRLEN),
+                 fqdn,
+                 r->client_ident[0] ? rfc1738_escape(r->client_ident) : dash_str,
+                 r->method_s,
+                 http->request->my_addr.NtoA(myaddr,MAX_IPSTRLEN),
+                 http->request->my_addr.GetPort());
+
+    if ((sz<=0) || (sz>=MAX_REDIRECTOR_REQUEST_STRLEN)) {
+      if (sz<=0) {
+       status = HTTP_INTERNAL_SERVER_ERROR;
+       debugs(61, DBG_CRITICAL, "ERROR: Gateway Failure. Can not build request to be passed to redirector. Request ABORTED.");
+      } else {
+       status = HTTP_REQUEST_URI_TOO_LARGE;
+       debugs(61, DBG_CRITICAL, "ERROR: Gateway Failure. Request passed to redirector exceeds MAX_REDIRECTOR_REQUEST_STRLEN (" << MAX_REDIRECTOR_REQUEST_STRLEN << "). Request ABORTED.");
+      }
+
+      clientStreamNode *node = (clientStreamNode *)http->client_stream.tail->prev->data;
+      clientReplyContext *repContext = dynamic_cast<clientReplyContext *>(node->data.getRaw());
+      assert (repContext);
+      IpAddress tmpnoaddr;
+      tmpnoaddr.SetNoAddr();
+      repContext->setReplyToError(ERR_GATEWAY_FAILURE, status,
+                                 http->request->method, NULL,
+                                 http->getConn() != NULL ? http->getConn()->peer : tmpnoaddr,
+                                 http->request,
+                                 NULL,
+                                 http->getConn() != NULL && http->getConn()->auth_user_request ?
+                                 http->getConn()->auth_user_request : http->request->auth_user_request);
+
+      node = (clientStreamNode *)http->client_stream.tail->data;
+      clientStreamRead(node, http, node->readBuffer);
+      return;
+    }
 
     helperSubmit(redirectors, buf, redirectHandleReply, r);
 }