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;