From: Amos Jeffries Date: Tue, 1 Feb 2011 11:37:01 +0000 (+1300) Subject: Author: Alexandre SIMON X-Git-Tag: take03^2~42 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=7561850e172544d52ab3914f82fc54e8a06ab060;p=thirdparty%2Fsquid.git Author: Alexandre SIMON 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. --- diff --git a/errors/Makefile.am b/errors/Makefile.am index f45bab175a..5bafab0a9d 100644 --- a/errors/Makefile.am +++ b/errors/Makefile.am @@ -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 index 0000000000..0a0cfeb771 --- /dev/null +++ b/errors/templates/ERR_GATEWAY_FAILURE @@ -0,0 +1,39 @@ + + + +ERROR: The requested URL could not be retrieved + + +
+

ERROR

+

The requested URL could not be retrieved

+
+
+ +
+

The following error was encountered while trying to retrieve the URL: %U

+ +
+

Gateway Proxy Failure

+
+ +

A non-recoverable internal failure or configuration problem prevents this request from being completed.

+ +

This may be due to limits established by the Internet Service Provider who operates this cache. Please contact them directly for more information.

+ +

Your cache administrator is %w.

+
+
+ +
+ + diff --git a/src/redirect.cc b/src/redirect.cc index 2474bd7981..d84e841df9 100644 --- a/src/redirect.cc +++ b/src/redirect.cc @@ -42,12 +42,16 @@ #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(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); }