From: wessels <> Date: Tue, 11 May 1999 01:33:20 +0000 (+0000) Subject: Added configuration parameters for maximum sizes of request headers, X-Git-Tag: SQUID_3_0_PRE1~2210 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0483b99141b2c53c207fa8a52a3a4508811d70a6;p=thirdparty%2Fsquid.git Added configuration parameters for maximum sizes of request headers, request bodies, and reply bodies. Added new error page (ERR_TOO_BIG). Large request bodies can be detected immediately because the request header must have a valid content length. Large reply bodies can be detected either by the content-length reply header, or if not present, by the number of bytes written to the client. --- diff --git a/src/cf.data.pre b/src/cf.data.pre index 5508bba7c9..5a1e6f1499 100644 --- a/src/cf.data.pre +++ b/src/cf.data.pre @@ -1,6 +1,6 @@ # -# $Id: cf.data.pre,v 1.152 1999/05/04 21:58:18 wessels Exp $ +# $Id: cf.data.pre,v 1.153 1999/05/10 19:33:20 wessels Exp $ # # # SQUID Internet Object Cache http://squid.nlanr.net/Squid/ @@ -1027,17 +1027,50 @@ wais_relay_port 8000 DOC_END -NAME: request_size +NAME: request_header_max_size +COMMENT: (KB) +TYPE: b_size_t +DEFAULT: 10 KB +LOC: Config.maxRequestHeaderSize +DOC_START + This specifies the maximum size for HTTP headers in a request. + Request headers are usually relatively small (about 512 bytes). + Placing a limit on the request header size will catch certain + bugs (for example with persistent connections) and possibly + buffer-overflow or denial-of-service attacks. +request_header_max_size 10 KB +DOC_END + +NAME: request_body_max_size COMMENT: (KB) TYPE: b_size_t DEFAULT: 100 KB -LOC: Config.maxRequestSize +LOC: Config.maxRequestBodySize DOC_START - Maximum allowed request size in kilobytes. If people are using - POST to upload files, then set this to the largest acceptable - filesize plus a few extra kbytes. + 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, there will be no limit + imposed. +request_body_max_size 100 KB +DOC_END -request_size 100 KB +NAME: reply_body_max_size +COMMENT: (KB) +TYPE: b_size_t +DEFAULT: 0 +LOC: Config.maxReplyBodySize +DOC_START + This specifies the maximum size for an HTTP reply body. + This can be used to restrict users from downloading very + large files. If the reply headers include a content-length + value, then we can recognize large reply bodies early and + avoid downloading any of it. If not, we will download as + much data up to this limit and then ungraciously terminate + the transfer. If you set this parameter to zero, there + will be no limit imposed. +reply_body_max_size 0 DOC_END diff --git a/src/client_side.cc b/src/client_side.cc index 24c93aebd0..c226f0d8cb 100644 --- a/src/client_side.cc +++ b/src/client_side.cc @@ -1,6 +1,6 @@ /* - * $Id: client_side.cc,v 1.451 1999/05/04 21:08:40 wessels Exp $ + * $Id: client_side.cc,v 1.452 1999/05/10 19:33:22 wessels Exp $ * * DEBUG: section 33 Client-side Routines * AUTHOR: Duane Wessels @@ -92,6 +92,7 @@ static int clientHierarchical(clientHttpRequest * http); static int clientCheckContentLength(request_t * r); static int httpAcceptDefer(void); static log_type clientProcessRequest2(clientHttpRequest * http); +static int clientReplyBodyTooLarge(int clen); static int checkAccelOnly(clientHttpRequest * http) @@ -1513,6 +1514,18 @@ clientPackMoreRanges(clientHttpRequest * http, const char *buf, ssize_t size, Me return i->debt_size > 0; } +static int +clientReplyBodyTooLarge(int clen) +{ + if (0 == Config.maxReplyBodySize) + return 0; /* disabled */ + if (clen < 0) + return 0; /* unknown */ + if (clen > Config.maxReplyBodySize) + return 1; /* too large */ + return 0; +} + /* * accepts chunk of a http message in buf, parses prefix, filters headers and * such, writes processed message to the client's socket @@ -1567,7 +1580,16 @@ clientSendMoreData(void *data, char *buf, ssize_t size) } } rep = clientBuildReply(http, buf, size); - if (rep) { + if (clientReplyBodyTooLarge(rep->content_length)) { + ErrorState *err = errorCon(ERR_TOO_BIG, HTTP_FORBIDDEN); + err->request = requestLink(http->request); + storeUnregister(http->entry, http); + storeUnlockObject(http->entry); + http->entry = clientCreateStoreEntry(http, http->request->method, + null_request_flags); + errorAppendEntry(http->entry, err); + return; + } else if (rep) { body_size = size - rep->hdr_sz; assert(body_size >= 0); body_buf = buf + rep->hdr_sz; @@ -1722,6 +1744,8 @@ clientWriteComplete(int fd, char *bufnotused, size_t size, int errflag, void *da } else { comm_close(fd); } + } else if (clientReplyBodyTooLarge((int) http->out.offset)) { + comm_close(fd); } else { /* More data will be coming from primary server; register with * storage manager. */ @@ -2368,7 +2392,7 @@ clientReadRequest(int fd, void *data) break; } if (0 == clientCheckContentLength(request)) { - err = errorCon(ERR_INVALID_REQ, HTTP_LENGTH_REQUIRED); + err = errorCon(ERR_TOO_BIG, HTTP_LENGTH_REQUIRED); err->src_addr = conn->peer.sin_addr; err->request = requestLink(request); http->al.http.code = err->http_status; @@ -2407,6 +2431,15 @@ clientReadRequest(int fd, void *data) */ if (request->body_sz < cont_len) commSetSelect(fd, COMM_SELECT_READ, NULL, NULL, 0); + if (cont_len > Config.maxRequestBodySize) { + err = errorCon(ERR_INVALID_REQ, + HTTP_REQUEST_ENTITY_TOO_LARGE); + err->request = requestLink(request); + http->entry = clientCreateStoreEntry(http, + METHOD_NONE, null_request_flags); + errorAppendEntry(http->entry, err); + break; + } } clientAccessCheck(http); continue; /* while offset > 0 */ @@ -2417,11 +2450,11 @@ clientReadRequest(int fd, void *data) */ k = conn->in.size - 1 - conn->in.offset; if (k == 0) { - if (conn->in.offset >= Config.maxRequestSize) { + if (conn->in.offset >= Config.maxRequestHeaderSize) { /* The request is too large to handle */ debug(33, 0) ("Request won't fit in buffer.\n"); - debug(33, 0) ("Config 'request_size'= %d bytes.\n", - Config.maxRequestSize); + debug(33, 0) ("Config 'request_header_max_size'= %d bytes.\n", + Config.maxRequestHeaderSize); debug(33, 0) ("This request = %d bytes.\n", (int) conn->in.offset); err = errorCon(ERR_INVALID_REQ, HTTP_REQUEST_ENTITY_TOO_LARGE); diff --git a/src/enums.h b/src/enums.h index 8029cb4d73..36d6297cdf 100644 --- a/src/enums.h +++ b/src/enums.h @@ -1,6 +1,6 @@ /* - * $Id: enums.h,v 1.150 1999/05/03 21:55:01 wessels Exp $ + * $Id: enums.h,v 1.151 1999/05/10 19:33:23 wessels Exp $ * * * SQUID Internet Object Cache http://squid.nlanr.net/Squid/ @@ -85,6 +85,7 @@ typedef enum { ERR_FTP_FORBIDDEN, ERR_FTP_UNAVAILABLE, ERR_ONLY_IF_CACHED_MISS, /* failure to satisfy only-if-cached request */ + ERR_TOO_BIG, ERR_MAX } err_type; diff --git a/src/structs.h b/src/structs.h index 762694f781..7e032d9534 100644 --- a/src/structs.h +++ b/src/structs.h @@ -1,6 +1,6 @@ /* - * $Id: structs.h,v 1.288 1999/05/04 20:49:39 wessels Exp $ + * $Id: structs.h,v 1.289 1999/05/10 19:33:25 wessels Exp $ * * * SQUID Internet Object Cache http://squid.nlanr.net/Squid/ @@ -251,7 +251,9 @@ struct _SquidConfig { time_t ident; #endif } Timeout; - size_t maxRequestSize; + size_t maxRequestHeaderSize; + size_t maxRequestBodySize; + size_t maxReplyBodySize; struct { ushortlist *http; u_short icp;