Hi,
Here's a small diff (thanks to benno!) which implements a simple fast
ACL lookup for the maximum request size. This allows Squid administrators
to restrict POST/upload sizes based on a variety of available request
information.
I'd like to commit this to Squid-2.HEAD, squid-2.7 and if possible,
Squid-2.6.
Thanks,
Adrian
--
- Xenion - http://www.xenion.com.au/ - VPS Hosting - Commercial Squid Support -
- $25/pm entry-level VPSes w/ capped bandwidth charges available in WA -
Index: src/cf.data.pre
===================================================================
RCS file: /squid/squid/src/cf.data.pre,v
retrieving revision 1.471
diff -u -r1.471 cf.data.pre
--- src/cf.data.pre 27 Apr 2008 20:55:42 -0000 1.471
+++ src/cf.data.pre 9 May 2008 00:51:59 -0000
@@ -3234,17 +3234,24 @@
DOC_END
NAME: request_body_max_size
-COMMENT: (KB)
-TYPE: b_size_t
-DEFAULT: 0 KB
-LOC: Config.maxRequestBodySize
+COMMENT: bytes allow|deny acl acl...
+TYPE: body_size_t
+DEFAULT: none
+DEFAULT_IF_NONE: 0 allow all
+LOC: Config.RequestBodySize
DOC_START
- This specifies the maximum size for an HTTP request body.
- In other words, the maximum size of a PUT/POST request.
- A user who attempts to send a request with a body larger
- than this limit receives an "Invalid Request" error message.
- If you set this parameter to a zero (the default), there will
- be no limit imposed.
+ This option specifies the maximum size of a request body in bytes.
+ It can be used to prevent users from uploading very large files. When
+ the request headers are received, the request_body_max_size lines are
+ processed, and the first line with a result of "allow" is used as the
+ maximum body size for this request. This size is checked against the
+ content-length value in the request headers. If the content length
+ value is larger than the allowed size, the request is denied and the
+ user receives an error message that says "the request or reply is too
+ large."
+
+ If you set this parameter to zero (the default), there will be
+ no limit imposed.
DOC_END
NAME: broken_posts
Index: src/client_side.c
===================================================================
RCS file: /squid/squid/src/client_side.c,v
retrieving revision 1.768
diff -u -r1.768 client_side.c
--- src/client_side.c 2 May 2008 20:09:59 -0000 1.768
+++ src/client_side.c 9 May 2008 00:52:00 -0000
@@ -151,7 +151,7 @@
static DEFER httpAcceptDefer;
static log_type clientProcessRequest2(clientHttpRequest * http);
static int clientReplyBodyTooLarge(clientHttpRequest *, squid_off_t clen);
-static int clientRequestBodyTooLarge(squid_off_t clen);
+static int clientRequestBodyTooLarge(clientHttpRequest *, request_t *);
static void clientProcessBody(ConnStateData * conn);
static void clientEatRequestBody(clientHttpRequest *);
static void clientAccessCheck(void *data);
@@ -2715,15 +2715,47 @@
}
#endif
+/*
+ * Calculates the maximum size allowed for an HTTP request body
+ */
+static void
+clientMaxRequestBodySize(request_t * request, clientHttpRequest * http)
+{
+ body_size *bs;
+ aclCheck_t *checklist;
+ if (http->log_type == LOG_TCP_DENIED)
+ return;
+ bs = (body_size *) Config.RequestBodySize.head;
+ http->maxRequestBodySize = 0;
+ while (bs) {
+ checklist = clientAclChecklistCreate(bs->access_list, http);
+ if (aclCheckFast(bs->access_list, checklist) != 1) {
+ /* deny - skip this entry */
+ bs = (body_size *) bs->node.next;
+ } else {
+ /* Allow - use this entry */
+ http->maxRequestBodySize = bs->maxsize;
+ bs = NULL;
+ debug(58, 3) ("clientMaxRequestBodySize: Setting maxRequestBodySize to %ld\n", (long int) http->maxRequestBodySize);
+ }
+ aclChecklistFree(checklist);
+ }
+}
+
static int
-clientRequestBodyTooLarge(squid_off_t clen)
+clientRequestBodyTooLarge(clientHttpRequest * http, request_t * request)
{
- if (0 == Config.maxRequestBodySize)
- return 0; /* disabled */
- if (clen < 0)
- return 0; /* unknown, bug? */
- if (clen > Config.maxRequestBodySize)
- return 1; /* too large */
+
+ if (http->maxRequestBodySize == -1) {
+ clientMaxRequestBodySize(request, http);
+ }
+
+ if (0 == http->maxRequestBodySize)
+ return 0; /* disabled */
+ if (request->content_length < 0)
+ return 0; /* unknown, bug? */
+ if (request->content_length > http->maxRequestBodySize)
+ return 1; /* too large */
return 0;
}
@@ -3767,6 +3799,7 @@
http->start = current_time;
http->req_sz = prefix_sz;
http->range_iter.boundary = StringNull;
+ http->maxRequestBodySize = -1;
dlinkAdd(http, &http->active, &ClientActiveRequests);
debug(33, 5) ("parseHttpRequest: Request Header is\n%s\n", hmsg->buf + hmsg->req_end);
@@ -4083,7 +4116,7 @@
request->body_reader_data = conn;
cbdataLock(conn);
/* Is it too large? */
- if (clientRequestBodyTooLarge(request->content_length)) {
+ if (clientRequestBodyTooLarge(http, request)) {
err = errorCon(ERR_TOO_BIG, HTTP_REQUEST_ENTITY_TOO_LARGE, request);
http->log_type = LOG_TCP_DENIED;
http->entry = clientCreateStoreEntry(http,
Index: src/structs.h
===================================================================
RCS file: /squid/squid/src/structs.h,v
retrieving revision 1.554
diff -u -r1.554 structs.h
--- src/structs.h 21 Apr 2008 02:28:14 -0000 1.554
+++ src/structs.h 9 May 2008 00:52:01 -0000
@@ -486,8 +486,8 @@
#endif
} Timeout;
squid_off_t maxRequestHeaderSize;
- squid_off_t maxRequestBodySize;
squid_off_t maxReplyHeaderSize;
+ dlink_list RequestBodySize;
dlink_list ReplyBodySize;
dlink_list DelayBodySize;
struct {
@@ -1280,6 +1280,7 @@
char *location;
} redirect;
dlink_node active;
+ squid_off_t maxRequestBodySize;
squid_off_t maxBodySize;
squid_off_t delayMaxBodySize;
ushort delayAssignedPool;