? replysizeprerequest.patch Index: HttpReply.c =================================================================== RCS file: /cvsroot/squid/squid/src/HttpReply.c,v retrieving revision 1.7 diff -u -p -r1.7 HttpReply.c --- HttpReply.c 2001/04/14 00:31:01 1.7 +++ HttpReply.c 2001/07/27 08:04:13 @@ -82,6 +82,7 @@ httpReplyInit(HttpReply * rep) { assert(rep); rep->hdr_sz = 0; + rep->maxBodySize = 0; rep->pstate = psReadyToParseStartLine; httpBodyInit(&rep->body); httpHeaderInit(&rep->header, hoReply); @@ -462,4 +463,29 @@ httpReplyBodySize(method_t method, HttpR else if (reply->sline.status < HTTP_OK) return 0; return reply->content_length; +} + +/* + * Calculates the maximum size allowed for an HTTP response + */ +void +httpReplyBodyBuildSize(request_t *request, HttpReply * reply, dlink_list *bodylist) +{ + body_size *bs; + aclCheck_t *checklist; + bs = (body_size *) bodylist->head; + while (bs) { + checklist = aclChecklistCreate(bs->access_list, request, NULL); + checklist->reply = reply; + if (1 != aclCheckFast(bs->access_list, checklist)) { + /* deny - skip this entry */ + bs = (body_size *) bs->node.next; + } else { + /* Allow - use this entry */ + reply->maxBodySize = bs->maxsize; + bs = NULL; + debug (58, 3) ("httpReplyBodyBuildSize: Setting maxBodySize to %d\n", reply->maxBodySize); + } + aclChecklistFree(checklist); + } } Index: cache_cf.c =================================================================== RCS file: /cvsroot/squid/squid/src/cache_cf.c,v retrieving revision 1.29 diff -u -p -r1.29 cache_cf.c --- cache_cf.c 2001/06/28 08:16:29 1.29 +++ cache_cf.c 2001/07/27 08:04:14 @@ -1870,6 +1870,64 @@ parse_b_size_t(size_t * var) parseBytesLine(var, B_BYTES_STR); } +CBDATA_TYPE (body_size); + +static void +parse_body_size_t(dlink_list *bodylist) +{ + body_size *bs; + CBDATA_INIT_TYPE (body_size); + bs = cbdataAlloc(body_size); + parse_size_t (&bs->maxsize); + aclParseAccessLine(&bs->access_list); + + dlinkAddTail(bs, &bs->node, bodylist); +} + +static void +dump_body_size_t(StoreEntry * entry, const char *name, dlink_list bodylist) +{ + body_size *bs; + bs = (body_size *) bodylist.head; + while (bs) { + acl_list *l; + acl_access *head = bs->access_list; + while (head != NULL) { + storeAppendPrintf(entry, "%s %d %s", name, bs->maxsize, + head->allow ? "Allow" : "Deny"); + for (l = head->acl_list; l != NULL; l = l->next) { + storeAppendPrintf(entry, " %s%s", + l->op ? null_string : "!", + l->acl->name); + } + storeAppendPrintf(entry, "\n"); + head = head->next; + } + bs = (body_size *) bs->node.next; + } +} + +static void +free_body_size_t(dlink_list * bodylist) //acl_access ** head) +{ + body_size *bs, *tempnode; + bs = (body_size *) bodylist->head; + while (bs) { + bs->maxsize = 0; + aclDestroyAccessList(&bs->access_list); + tempnode = (body_size *) bs->node.next; + dlinkDelete (&bs->node, bodylist); + bs = tempnode; + } +} + +static int +check_null_body_size_t(dlink_list bodylist) +{ + return bodylist.head == NULL; +} + + static void parse_kb_size_t(size_t * var) { Index: cf.data.pre =================================================================== RCS file: /cvsroot/squid/squid/src/cf.data.pre,v retrieving revision 1.29 diff -u -p -r1.29 cf.data.pre --- cf.data.pre 2001/07/12 20:49:42 1.29 +++ cf.data.pre 2001/07/27 08:04:20 @@ -1464,33 +1464,6 @@ DOC_START imposed. DOC_END -NAME: reply_body_max_size -COMMENT: (KB) -TYPE: b_size_t -DEFAULT: 0 -LOC: Config.maxReplyBodySize -DOC_START - This option specifies the maximum size of a reply body. It - can be used to prevent users from downloading very large files, - such as MP3's and movies. The reply size is checked twice. - First when we get the reply headers, we check the - content-length value. If the content length value exists and - is larger than this parameter, the request is denied and the - user receives an error message that says "the request or reply - is too large." If there is no content-length, and the reply - size exceeds this limit, the client's connection is just closed - and they will receive a partial reply. - - NOTE: downstream caches probably can not detect a partial reply - if there is no content-length header, so they will cache - partial responses and give them out as hits. You should NOT - use this option if you have downstream caches. - - If you set this parameter to zero (the default), there will be - no limit imposed. -DOC_END - - NAME: refresh_pattern TYPE: refreshpattern LOC: Config.Refresh @@ -2122,6 +2095,40 @@ DOC_START the configure script. DOC_END + +NAME: reply_body_max_size +COMMENT: bytes allow|deny acl acl... +TYPE: body_size_t +DEFAULT: none +DEFAULT_IF_NONE: 0 allow all +LOC: Config.ReplyBodySize +DOC_START + This option specifies the maximum size of a reply body. It + can be used to prevent users from downloading very large files, + such as MP3's and movies. When the reply headers are recieved, + the reply_body_max_size lines are processed, and the first line with + a result of "allow" is used as the maximum body size for this reply. + This size is then checked twice. First when we get the reply headers, + we check the content-length value. If the content length value exists + and 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 there is no content-length, and the reply + size exceeds this limit, the client's connection is just closed + and they will receive a partial reply. + + WARNING: downstream caches probably can not detect a partial reply + if there is no content-length header, so they will cache + partial responses and give them out as hits. You should NOT + use this option if you have downstream caches. + + WARNING: A maximum size larger than the size of squid's error messages + will cause an infinite loop and crash squid. Ensure that the smallest + non-zero value you use is greater that the maximum header size plus + the size of your largest error page. + + If you set this parameter to zero (the default), there will be + no limit imposed. +DOC_END COMMENT_START ADMINISTRATIVE PARAMETERS Index: client_side.c =================================================================== RCS file: /cvsroot/squid/squid/src/client_side.c,v retrieving revision 1.31 diff -u -p -r1.31 client_side.c --- client_side.c 2001/07/17 09:51:56 1.31 +++ client_side.c 2001/07/27 08:04:24 @@ -114,7 +114,7 @@ static int clientHierarchical(clientHttp static int clientCheckContentLength(request_t * r); static DEFER httpAcceptDefer; static log_type clientProcessRequest2(clientHttpRequest * http); -static int clientReplyBodyTooLarge(int clen); +static int clientReplyBodyTooLarge(HttpReply *, int clen); static int clientRequestBodyTooLarge(int clen); static void clientProcessBody(ConnStateData * conn); @@ -1760,13 +1760,13 @@ clientPackMoreRanges(clientHttpRequest * } static int -clientReplyBodyTooLarge(int clen) +clientReplyBodyTooLarge(HttpReply *rep, int clen) { - if (0 == Config.maxReplyBodySize) + if (0 == rep->maxBodySize) return 0; /* disabled */ if (clen < 0) return 0; /* unknown */ - if (clen > Config.maxReplyBodySize) + if (clen > rep->maxBodySize) return 1; /* too large */ return 0; } @@ -1865,20 +1865,22 @@ clientSendMoreData(void *data, char *buf } } rep = clientBuildReply(http, buf, size); - if (rep && clientReplyBodyTooLarge(rep->content_length)) { - ErrorState *err = errorCon(ERR_TOO_BIG, HTTP_FORBIDDEN); - err->request = requestLink(http->request); - storeUnregister(http->sc, http->entry, http); - http->sc = NULL; - storeUnlockObject(http->entry); - http->entry = clientCreateStoreEntry(http, http->request->method, - null_request_flags); - errorAppendEntry(http->entry, err); - httpReplyDestroy(rep); - return; - } else if (rep) { + if (rep) { aclCheck_t *ch; int rv; + httpReplyBodyBuildSize(http->request, rep, &Config.ReplyBodySize); + if (clientReplyBodyTooLarge(rep, rep->content_length)) { + ErrorState *err = errorCon(ERR_TOO_BIG, HTTP_FORBIDDEN); + err->request = requestLink(http->request); + storeUnregister(http->sc, http->entry, http); + http->sc = NULL; + storeUnlockObject(http->entry); + http->entry = clientCreateStoreEntry(http, http->request->method, + null_request_flags); + errorAppendEntry(http->entry, err); + httpReplyDestroy(rep); + return; + } body_size = size - rep->hdr_sz; assert(body_size >= 0); body_buf = buf + rep->hdr_sz; @@ -2095,7 +2097,7 @@ clientWriteComplete(int fd, char *bufnot } else { comm_close(fd); } - } else if (clientReplyBodyTooLarge((int) http->out.offset)) { + } else if (clientReplyBodyTooLarge(entry->mem_obj->reply, (int) http->out.offset)) { comm_close(fd); } else { /* More data will be coming from primary server; register with Index: protos.h =================================================================== RCS file: /cvsroot/squid/squid/src/protos.h,v retrieving revision 1.29 diff -u -p -r1.29 protos.h --- protos.h 2001/05/21 18:51:19 1.29 +++ protos.h 2001/07/27 08:04:26 @@ -495,6 +495,7 @@ extern time_t httpReplyExpires(const Htt extern int httpReplyHasCc(const HttpReply * rep, http_hdr_cc_type type); extern void httpRedirectReply(HttpReply *, http_status, const char *); extern int httpReplyBodySize(method_t, HttpReply *); +extern void httpReplyBodyBuildSize(request_t *, HttpReply *, dlink_list *); /* Http Request */ extern request_t *requestCreate(method_t, protocol_t, const char *urlpath); Index: structs.h =================================================================== RCS file: /cvsroot/squid/squid/src/structs.h,v retrieving revision 1.36 diff -u -p -r1.36 structs.h --- structs.h 2001/07/10 06:52:12 1.36 +++ structs.h 2001/07/27 08:04:29 @@ -197,6 +197,12 @@ struct _header_mangler { char *replacement; }; +struct _body_size { + dlink_node node; + acl_access *access_list; + size_t maxsize; +}; + struct _http_version_t { unsigned int major; unsigned int minor; @@ -378,7 +384,7 @@ struct _SquidConfig { } Timeout; size_t maxRequestHeaderSize; size_t maxRequestBodySize; - size_t maxReplyBodySize; + dlink_list ReplyBodySize; struct { u_short icp; #if USE_HTCP @@ -910,6 +916,7 @@ struct _HttpReply { HttpStatusLine sline; HttpHeader header; HttpBody body; /* for small constant memory-resident text bodies only */ + size_t maxBodySize; }; struct _http_state_flags { Index: typedefs.h =================================================================== RCS file: /cvsroot/squid/squid/src/typedefs.h,v retrieving revision 1.21 diff -u -p -r1.21 typedefs.h --- typedefs.h 2001/05/08 15:27:00 1.21 +++ typedefs.h 2001/07/27 08:04:29 @@ -143,6 +143,7 @@ typedef struct _helper_flags helper_flag typedef struct _helper_stateful_flags helper_stateful_flags; typedef struct _http_state_flags http_state_flags; typedef struct _header_mangler header_mangler; +typedef struct _body_size body_size; typedef struct _request_t request_t; typedef struct _AccessLogEntry AccessLogEntry; typedef struct _cachemgr_passwd cachemgr_passwd;