diff -ruN squid-2.5.STABLE7-RC2/ChangeLog squid-2.5.STABLE7-RC3/ChangeLog --- squid-2.5.STABLE7-RC2/ChangeLog Mon Sep 27 12:44:40 2004 +++ squid-2.5.STABLE7-RC3/ChangeLog Tue Oct 5 16:43:26 2004 @@ -47,7 +47,6 @@ - [Medium] New acl types to match arbitrary HTTP headers. In addition the http_header_access & replace directivess now support arbitrary headers and not only the well known ones. (Bug #961) - [2.5.STABLE7-RC1] - [Cosmetic] ncsa_auth now accepts Window formatted password files (Bug #1078) - [Cosmetic] Support the --program-prefix/suffix options or other @@ -56,7 +55,11 @@ CONNECT requests in a more graceful manner. (Bug #859) - [Minor] New balance_on_multiple_ip directive to work around certain broken load balancers and optimized ipcache on reload requests - + (Bug #1058) + - [Medium] Odd things happens on large http reply headers + (Bug #874) + - [Minor] Suspected instability on aborted PUT/POST requests + (Bug #1089) Changes to squid-2.5.STABLE6 (9 Jul 2004) diff -ruN squid-2.5.STABLE7-RC2/RELEASENOTES.html squid-2.5.STABLE7-RC3/RELEASENOTES.html --- squid-2.5.STABLE7-RC2/RELEASENOTES.html Mon Sep 27 13:16:11 2004 +++ squid-2.5.STABLE7-RC3/RELEASENOTES.html Tue Oct 5 16:58:15 2004 @@ -1,13 +1,13 @@ - + Squid 2.5 release notes

Squid 2.5 release notes

-

Squid Developers

$Id: release-2.5.html,v 1.1.2.36 2004/09/27 18:44:40 hno Exp $ +

Squid Developers

$Id: release-2.5.html,v 1.1.2.38 2004/10/05 22:43:26 hno Exp $
This document contains the release notes for version 2.5 of Squid. Squid is a WWW Cache application developed by the National Laboratory @@ -133,6 +133,7 @@
short_icon_urls

New directive to enable an alternative way of referring to icons in FTP directory listings etc.

acl urllogin

New acl type to match the login component of Internet style URLs (protocol://user:password@host/path/to/file)

balance_on_multiple_ip

New directive to make it possible to disable the automatic round-robin load balancing on multiple IP addresses normally done by Squid.

+
reply_header_max_size

New directive limiting the size of HTTP reply headers, similar to request_header_max_size but in the reply direction (from servers to clients). Default is 20KB.

@@ -144,11 +145,12 @@
Bug #761

assertion failed: cbdata.c:249: "c->locks > 0" when using diskd

Bug -#910

ntlm auth_user_hash_pointer memory leak if challenge reuses are enabled

- -
Bug #779

users going above their allowed IP count no longer logged in cache.log

Bug +#1059

mime.conf and referenced icons must be within chroot

+
Bug +#1033

CARP ignores cache_peer_access and cache_peer_domain

+
Bug #692

tcp_outgoing_address using an ident ACL does not work

Bug #581

acl max_user_ip and multiple authentication schemes

@@ -308,6 +310,7 @@
  • request_header_max_size directive corrected. You may need to increase this value after upgrading if set very low. The default have been increased from 10 KB to 20 KB which should be sufficient for most uses.
  • +
  • reply_header_max_size directive added
  • http_header_access & replace now support arbitrary headers, not only the well known headers known by Squid
  • new acl types req_hdr and resp_hdr to match arbitrary HTTP headers, diff -ruN squid-2.5.STABLE7-RC2/configure squid-2.5.STABLE7-RC3/configure --- squid-2.5.STABLE7-RC2/configure Mon Sep 27 13:15:58 2004 +++ squid-2.5.STABLE7-RC3/configure Tue Oct 5 16:58:02 2004 @@ -1000,7 +1000,7 @@ # Define the identity of the package. PACKAGE=squid -VERSION=2.5.STABLE7-RC2 +VERSION=2.5.STABLE7-RC3 cat >> confdefs.h <&6 echo "configure:1057: checking whether to enable maintainer-specific portions of Makefiles" >&5 # Check whether --enable-maintainer-mode or --disable-maintainer-mode was given. diff -ruN squid-2.5.STABLE7-RC2/configure.in squid-2.5.STABLE7-RC3/configure.in --- squid-2.5.STABLE7-RC2/configure.in Mon Sep 27 13:15:58 2004 +++ squid-2.5.STABLE7-RC3/configure.in Tue Oct 5 16:58:02 2004 @@ -3,15 +3,15 @@ dnl dnl Duane Wessels, wessels@nlanr.net, February 1996 (autoconf v2.9) dnl -dnl $Id: configure.in,v 1.251.2.66 2004/09/27 19:14:57 hno Exp $ +dnl $Id: configure.in,v 1.251.2.68 2004/10/05 22:45:56 hno Exp $ dnl dnl dnl AC_INIT(src/main.c) AC_CONFIG_AUX_DIR(cfgaux) -AM_INIT_AUTOMAKE(squid, 2.5.STABLE7-RC2) +AM_INIT_AUTOMAKE(squid, 2.5.STABLE7-RC3) AM_CONFIG_HEADER(include/autoconf.h) -AC_REVISION($Revision: 1.251.2.66 $)dnl +AC_REVISION($Revision: 1.251.2.68 $)dnl AC_PREFIX_DEFAULT(/usr/local/squid) AM_MAINTAINER_MODE diff -ruN squid-2.5.STABLE7-RC2/include/version.h squid-2.5.STABLE7-RC3/include/version.h --- squid-2.5.STABLE7-RC2/include/version.h Mon Sep 27 13:15:58 2004 +++ squid-2.5.STABLE7-RC3/include/version.h Tue Oct 5 16:58:02 2004 @@ -9,5 +9,5 @@ */ #ifndef SQUID_RELEASE_TIME -#define SQUID_RELEASE_TIME 1096312556 +#define SQUID_RELEASE_TIME 1097017079 #endif diff -ruN squid-2.5.STABLE7-RC2/src/HttpReply.c squid-2.5.STABLE7-RC3/src/HttpReply.c --- squid-2.5.STABLE7-RC2/src/HttpReply.c Tue May 6 14:13:02 2003 +++ squid-2.5.STABLE7-RC3/src/HttpReply.c Tue Oct 5 15:31:25 2004 @@ -1,6 +1,6 @@ /* - * $Id: HttpReply.c,v 1.49.2.1 2003/05/06 20:13:02 hno Exp $ + * $Id: HttpReply.c,v 1.49.2.2 2004/10/05 21:31:25 hno Exp $ * * DEBUG: section 58 HTTP Reply (Response) * AUTHOR: Alex Rousskov @@ -143,16 +143,17 @@ * becuase somebody may feed a non NULL-terminated buffer to * us. */ - char *headers = memAllocate(MEM_4K_BUF); + MemBuf mb = MemBufNull; int success; - size_t s = XMIN(end + 1, 4096); /* reset current state, because we are not used in incremental fashion */ httpReplyReset(rep); /* put a string terminator. s is how many bytes to touch in * 'buf' including the terminating NULL. */ - xstrncpy(headers, buf, s); - success = httpReplyParseStep(rep, headers, 0); - memFree(headers, MEM_4K_BUF); + memBufDefInit(&mb); + memBufAppend(&mb, buf, end); + memBufAppend(&mb, "\0", 1); + success = httpReplyParseStep(rep, mb.buf, 0); + memBufClean(&mb); return success == 1; } diff -ruN squid-2.5.STABLE7-RC2/src/HttpRequest.c squid-2.5.STABLE7-RC3/src/HttpRequest.c --- squid-2.5.STABLE7-RC2/src/HttpRequest.c Fri Apr 13 18:25:17 2001 +++ squid-2.5.STABLE7-RC3/src/HttpRequest.c Tue Oct 5 16:34:42 2004 @@ -1,6 +1,6 @@ /* - * $Id: HttpRequest.c,v 1.30 2001/04/14 00:25:17 hno Exp $ + * $Id: HttpRequest.c,v 1.30.2.1 2004/10/05 22:34:42 hno Exp $ * * DEBUG: section 73 HTTP Request * AUTHOR: Duane Wessels @@ -55,8 +55,8 @@ requestDestroy(request_t * req) { assert(req); - if (req->body_connection) - clientAbortBody(req); + if (req->body_reader) + requestAbortBody(req); if (req->auth_user_request) authenticateAuthUserRequestUnlock(req->auth_user_request); safe_free(req->canonical); @@ -157,4 +157,35 @@ if (strConn && strListIsMember(strConn, strBuf(e->name), ',')) return 0; return 1; +} + +/* + * Read request body contents + */ +void +requestReadBody(request_t * request, char *buf, size_t size, CBCB * callback, void *cbdata) +{ + if (request->body_reader) { + if (cbdataValid(request->body_reader_data)) { + request->body_reader(request, buf, size, callback, cbdata); + } else { + debug(0, 0) ("requestReadBody: Aborted\n"); + request->body_reader = NULL; + cbdataUnlock(request->body_reader_data); + request->body_reader_data = NULL; + callback(buf, 0, cbdata); /* Signal end of body */ + } + } else { + callback(buf, 0, cbdata); /* Signal end of body */ + } +} + +void +requestAbortBody(request_t * request) +{ + if (!request) + return; + if (request->body_reader) { + requestReadBody(request, NULL, -1, NULL, NULL); + } } diff -ruN squid-2.5.STABLE7-RC2/src/MemBuf.c squid-2.5.STABLE7-RC3/src/MemBuf.c --- squid-2.5.STABLE7-RC2/src/MemBuf.c Sun Jun 6 09:07:16 2004 +++ squid-2.5.STABLE7-RC3/src/MemBuf.c Tue Oct 5 15:31:25 2004 @@ -1,6 +1,6 @@ /* - * $Id: MemBuf.c,v 1.28.2.2 2004/06/06 15:07:16 hno Exp $ + * $Id: MemBuf.c,v 1.28.2.3 2004/10/05 21:31:25 hno Exp $ * * DEBUG: section 59 auto-growing Memory Buffer with printf * AUTHOR: Alex Rousskov @@ -158,7 +158,7 @@ (*mb->freefunc) (mb->buf); /* free */ mb->freefunc = NULL; /* freeze */ mb->buf = NULL; - mb->size = mb->capacity = 0; + mb->size = mb->capacity = mb->max_capacity = 0; } /* cleans the buffer without changing its capacity diff -ruN squid-2.5.STABLE7-RC2/src/access_log.c squid-2.5.STABLE7-RC3/src/access_log.c --- squid-2.5.STABLE7-RC2/src/access_log.c Mon Jun 7 15:20:34 2004 +++ squid-2.5.STABLE7-RC3/src/access_log.c Mon Sep 27 16:34:19 2004 @@ -1,6 +1,6 @@ /* - * $Id: access_log.c,v 1.72.2.5 2004/06/07 21:20:34 hno Exp $ + * $Id: access_log.c,v 1.72.2.6 2004/09/27 22:34:19 wessels Exp $ * * DEBUG: section 46 Access Log * AUTHOR: Duane Wessels @@ -389,7 +389,7 @@ logfile = logfileOpen(Config.Log.access, MAX_URL << 1, 1); LogfileStatus = LOG_ENABLE; #if HEADERS_LOG - headerslog = logfileOpen("/usr/local/squid/logs/headers.log", 512); + headerslog = logfileOpen("/usr/local/squid/logs/headers.log", MAX_URL << 1, 0); assert(NULL != headerslog); #endif #if FORW_VIA_DB diff -ruN squid-2.5.STABLE7-RC2/src/carp.c squid-2.5.STABLE7-RC3/src/carp.c --- squid-2.5.STABLE7-RC2/src/carp.c Thu Jun 19 15:06:19 2003 +++ squid-2.5.STABLE7-RC3/src/carp.c Thu Sep 30 03:23:30 2004 @@ -1,6 +1,6 @@ /* - * $Id: carp.c,v 1.15.2.1 2003/06/19 21:06:19 wessels Exp $ + * $Id: carp.c,v 1.15.2.2 2004/09/30 09:23:30 hno Exp $ * * DEBUG: section 39 Cache Array Routing Protocol * AUTHOR: Eric Stern @@ -119,7 +119,7 @@ for (tp = Config.peers; tp; tp = tp->next) { if (0.0 == tp->carp.load_factor) continue; - if (tp->tcp_up != PEER_TCP_MAGIC_COUNT) + if (!peerHTTPOkay(tp, request)) continue; assert(tp->type == PEER_PARENT); combined_hash = (url_hash ^ tp->carp.hash); diff -ruN squid-2.5.STABLE7-RC2/src/cf.data.pre squid-2.5.STABLE7-RC3/src/cf.data.pre --- squid-2.5.STABLE7-RC2/src/cf.data.pre Mon Sep 27 12:17:38 2004 +++ squid-2.5.STABLE7-RC3/src/cf.data.pre Tue Oct 5 15:31:25 2004 @@ -1,6 +1,6 @@ # -# $Id: cf.data.pre,v 1.245.2.75 2004/09/27 18:17:38 hno Exp $ +# $Id: cf.data.pre,v 1.245.2.76 2004/10/05 21:31:25 hno Exp $ # # # SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -2364,6 +2364,19 @@ Processing proceeds in the order specified, and stops at first fully matching line. +DOC_END + +NAME: reply_header_max_size +COMMENT: (KB) +TYPE: b_size_t +DEFAULT: 20 KB +LOC: Config.maxReplyHeaderSize +DOC_START + This specifies the maximum size for HTTP headers in a reply. + Reply headers are usually relatively small (about 512 bytes). + Placing a limit on the reply header size will catch certain + bugs (for example with persistent connections) and possibly + buffer-overflow or denial-of-service attacks. DOC_END NAME: reply_body_max_size diff -ruN squid-2.5.STABLE7-RC2/src/client_db.c squid-2.5.STABLE7-RC3/src/client_db.c --- squid-2.5.STABLE7-RC2/src/client_db.c Sat Jul 17 16:37:30 2004 +++ squid-2.5.STABLE7-RC3/src/client_db.c Mon Oct 4 15:13:18 2004 @@ -1,6 +1,6 @@ /* - * $Id: client_db.c,v 1.53.2.1 2004/07/17 22:37:30 hno Exp $ + * $Id: client_db.c,v 1.53.2.2 2004/10/04 21:13:18 hno Exp $ * * DEBUG: section 0 Client Database * AUTHOR: Duane Wessels @@ -282,7 +282,7 @@ cleanup_scheduled = 1; eventAdd("client_db garbage collector", clientdbScheduledGC, NULL, 6 * 3600, 0); } - debug(49, 1) ("clientdbGC: Removed %d entries\n", cleanup_removed); + debug(49, 2) ("clientdbGC: Removed %d entries\n", cleanup_removed); } } diff -ruN squid-2.5.STABLE7-RC2/src/client_side.c squid-2.5.STABLE7-RC3/src/client_side.c --- squid-2.5.STABLE7-RC2/src/client_side.c Mon Sep 27 12:17:38 2004 +++ squid-2.5.STABLE7-RC3/src/client_side.c Tue Oct 5 16:34:42 2004 @@ -1,6 +1,6 @@ /* - * $Id: client_side.c,v 1.561.2.59 2004/09/27 18:17:38 hno Exp $ + * $Id: client_side.c,v 1.561.2.60 2004/10/05 22:34:42 hno Exp $ * * DEBUG: section 33 Client-side Routines * AUTHOR: Duane Wessels @@ -129,6 +129,8 @@ static int clientRequestBodyTooLarge(int clen); static void clientProcessBody(ConnStateData * conn); static void clientEatRequestBody(clientHttpRequest *); +static BODY_HANDLER clientReadBody; +static void clientAbortBody(request_t * req); static int checkAccelOnly(clientHttpRequest * http) @@ -360,9 +362,11 @@ new_request->auth_user_request = old_request->auth_user_request; authenticateAuthUserRequestLock(new_request->auth_user_request); } - if (old_request->body_connection) { - new_request->body_connection = old_request->body_connection; - old_request->body_connection = NULL; + if (old_request->body_reader) { + new_request->body_reader = old_request->body_reader; + new_request->body_reader_data = old_request->body_reader_data; + old_request->body_reader = NULL; + old_request->body_reader_data = NULL; } new_request->content_length = old_request->content_length; new_request->flags.proxy_keepalive = old_request->flags.proxy_keepalive; @@ -813,10 +817,7 @@ MemObject *mem = NULL; debug(33, 3) ("httpRequestFree: %s\n", storeUrl(http->entry)); if (!clientCheckTransferDone(http)) { - if (request && request->body_connection) { - clientAbortBody(request); /* abort request body transter */ - request->body_connection = NULL; - } + requestAbortBody(request); /* abort request body transter */ /* HN: This looks a bit odd.. why should client_side care about * the ICP selection status? */ @@ -2220,7 +2221,7 @@ } else if (clientGotNotEnough(http)) { debug(33, 5) ("clientWriteComplete: client didn't get all it expected\n"); comm_close(fd); - } else if (http->request->body_connection) { + } else if (http->request->body_reader == clientReadBody) { debug(33, 5) ("clientWriteComplete: closing, but first we need to read the rest of the request\n"); /* XXX We assumes the reply does fit in the TCP transmit window. * If not the connection may stall while sending the reply @@ -3112,7 +3113,9 @@ /* Do we expect a request-body? */ if (request->content_length > 0) { conn->body.size_left = request->content_length; - request->body_connection = conn; + request->body_reader = clientReadBody; + request->body_reader_data = conn; + cbdataLock(conn); /* Is it too large? */ if (clientRequestBodyTooLarge(request->content_length)) { err = errorCon(ERR_TOO_BIG, HTTP_REQUEST_ENTITY_TOO_LARGE); @@ -3168,15 +3171,20 @@ } /* file_read like function, for reading body content */ -void +static void clientReadBody(request_t * request, char *buf, size_t size, CBCB * callback, void *cbdata) { - ConnStateData *conn = request->body_connection; + ConnStateData *conn = request->body_reader_data; + if (!callback) { + clientAbortBody(request); + return; + } if (!conn) { debug(33, 5) ("clientReadBody: no body to read, request=%p\n", request); callback(buf, 0, cbdata); /* Signal end of body */ return; } + assert(cbdataValid(conn)); debug(33, 2) ("clientReadBody: start fd=%d body_size=%lu in.offset=%ld cb=%p req=%p\n", conn->fd, (unsigned long int) conn->body.size_left, (long int) conn->in.offset, callback, request); conn->body.callback = callback; conn->body.cbdata = cbdata; @@ -3218,7 +3226,7 @@ ConnStateData *conn = http->conn; cbdataLock(conn); if (conn->body.request) - clientAbortBody(conn->body.request); + requestAbortBody(conn->body.request); if (cbdataValid(conn)) clientEatRequestBodyHandler(NULL, -1, http); cbdataUnlock(conn); @@ -3261,8 +3269,12 @@ xmemmove(conn->in.buf, conn->in.buf + size, conn->in.offset); /* Remove request link if this is the last part of the body, as * clientReadRequest automatically continues to process next request */ - if (conn->body.size_left <= 0 && request != NULL) - request->body_connection = NULL; + if (conn->body.size_left <= 0 && request != NULL) { + request->body_reader = NULL; + if (request->body_reader_data) + cbdataUnlock(request->body_reader_data); + request->body_reader_data = NULL; + } /* Remove clientReadBody arguments (the call is completed) */ conn->body.request = NULL; conn->body.callback = NULL; @@ -3283,14 +3295,16 @@ } /* Abort a body request */ -void +static void clientAbortBody(request_t * request) { - ConnStateData *conn = request->body_connection; + ConnStateData *conn = request->body_reader_data; char *buf; CBCB *callback; void *cbdata; int valid; + if (!cbdataValid(conn)) + return; if (!conn->body.callback || conn->body.request != request) return; buf = conn->body.buf; diff -ruN squid-2.5.STABLE7-RC2/src/enums.h squid-2.5.STABLE7-RC3/src/enums.h --- squid-2.5.STABLE7-RC2/src/enums.h Sat Sep 25 05:56:16 2004 +++ squid-2.5.STABLE7-RC3/src/enums.h Tue Oct 5 15:31:26 2004 @@ -1,6 +1,6 @@ /* - * $Id: enums.h,v 1.203.2.12 2004/09/25 11:56:16 hno Exp $ + * $Id: enums.h,v 1.203.2.13 2004/10/05 21:31:26 hno Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -483,7 +483,8 @@ HTTP_GATEWAY_TIMEOUT = 504, HTTP_HTTP_VERSION_NOT_SUPPORTED = 505, HTTP_INSUFFICIENT_STORAGE = 507, /* RFC2518 section 10.6 */ - HTTP_INVALID_HEADER = 600 /* Squid header parsing error */ + HTTP_INVALID_HEADER = 600, /* Squid header parsing error */ + HTTP_HEADER_TOO_LARGE = 601 /* Header too large to process */ } http_status; /* diff -ruN squid-2.5.STABLE7-RC2/src/forward.c squid-2.5.STABLE7-RC3/src/forward.c --- squid-2.5.STABLE7-RC2/src/forward.c Wed Feb 18 06:44:55 2004 +++ squid-2.5.STABLE7-RC3/src/forward.c Tue Oct 5 16:34:42 2004 @@ -1,6 +1,6 @@ /* - * $Id: forward.c,v 1.82.2.12 2004/02/18 13:44:55 hno Exp $ + * $Id: forward.c,v 1.82.2.13 2004/10/05 22:34:42 hno Exp $ * * DEBUG: section 17 Request Forwarding * AUTHOR: Duane Wessels @@ -152,7 +152,7 @@ /* If there is a request body then Squid can only try once * even if the method is indempotent */ - if (fwdState->request->body_connection) + if (fwdState->request->body_reader) return 0; /* RFC2616 9.1 Safe and Idempotent Methods */ diff -ruN squid-2.5.STABLE7-RC2/src/ftp.c squid-2.5.STABLE7-RC3/src/ftp.c --- squid-2.5.STABLE7-RC2/src/ftp.c Mon May 31 17:14:37 2004 +++ squid-2.5.STABLE7-RC3/src/ftp.c Tue Oct 5 16:34:42 2004 @@ -1,6 +1,6 @@ /* - * $Id: ftp.c,v 1.316.2.14 2004/05/31 23:14:37 hno Exp $ + * $Id: ftp.c,v 1.316.2.15 2004/10/05 22:34:42 hno Exp $ * * DEBUG: section 9 File Transfer Protocol (FTP) * AUTHOR: Harvest Derived @@ -2309,7 +2309,7 @@ return; if (!err) { /* Shedule the rest of the request */ - clientReadBody(ftpState->request, ftpState->data.buf, ftpState->data.size, ftpRequestBody, ftpState); + requestReadBody(ftpState->request, ftpState->data.buf, ftpState->data.size, ftpRequestBody, ftpState); } else { debug(9, 1) ("ftpDataWriteCallback: write error: %s\n", xstrerror()); ftpFailed(ftpState, ERR_WRITE_ERROR); @@ -2322,7 +2322,7 @@ FtpStateData *ftpState = (FtpStateData *) data; debug(9, 3) ("ftpDataWrite\n"); /* This starts the body transfer */ - clientReadBody(ftpState->request, ftpState->data.buf, ftpState->data.size, ftpRequestBody, ftpState); + requestReadBody(ftpState->request, ftpState->data.buf, ftpState->data.size, ftpRequestBody, ftpState); } static void diff -ruN squid-2.5.STABLE7-RC2/src/http.c squid-2.5.STABLE7-RC3/src/http.c --- squid-2.5.STABLE7-RC2/src/http.c Tue Jun 8 04:54:07 2004 +++ squid-2.5.STABLE7-RC3/src/http.c Tue Oct 5 16:34:42 2004 @@ -1,6 +1,6 @@ /* - * $Id: http.c,v 1.384.2.16 2004/06/08 10:54:07 hno Exp $ + * $Id: http.c,v 1.384.2.18 2004/10/05 22:34:42 hno Exp $ * * DEBUG: section 11 Hypertext Transfer Protocol (HTTP) * AUTHOR: Harvest Derived @@ -65,18 +65,15 @@ if (httpState == NULL) return; if (httpState->body_buf) { - if (httpState->orig_request->body_connection) { - clientAbortBody(httpState->orig_request); - } + requestAbortBody(httpState->orig_request); if (httpState->body_buf) { memFree(httpState->body_buf, MEM_8K_BUF); httpState->body_buf = NULL; } } storeUnlockObject(httpState->entry); - if (httpState->reply_hdr) { - memFree(httpState->reply_hdr, MEM_8K_BUF); - httpState->reply_hdr = NULL; + if (!memBufIsNull(&httpState->reply_hdr)) { + memBufClean(&httpState->reply_hdr); } requestUnlink(httpState->request); requestUnlink(httpState->orig_request); @@ -320,6 +317,7 @@ case HTTP_UNAUTHORIZED: case HTTP_PROXY_AUTHENTICATION_REQUIRED: case HTTP_INVALID_HEADER: /* Squid header parsing error */ + case HTTP_HEADER_TOO_LARGE: default: /* Unknown status code */ return 0; /* NOTREACHED */ @@ -395,50 +393,61 @@ } /* rewrite this later using new interfaces @?@ */ -void +static void httpProcessReplyHeader(HttpStateData * httpState, const char *buf, int size) { - char *t = NULL; StoreEntry *entry = httpState->entry; - int room; size_t hdr_len; + size_t hdr_size = headersEnd(buf, size); HttpReply *reply = entry->mem_obj->reply; Ctx ctx; debug(11, 3) ("httpProcessReplyHeader: key '%s'\n", storeKeyText(entry->hash.key)); - if (httpState->reply_hdr == NULL) - httpState->reply_hdr = memAllocate(MEM_8K_BUF); + if (memBufIsNull(&httpState->reply_hdr)) + memBufDefInit(&httpState->reply_hdr); assert(httpState->reply_hdr_state == 0); - hdr_len = httpState->reply_hdr_size; - room = 8191 - hdr_len; - xmemcpy(httpState->reply_hdr + hdr_len, buf, room < size ? room : size); - hdr_len += room < size ? room : size; - httpState->reply_hdr[hdr_len] = '\0'; - httpState->reply_hdr_size = hdr_len; - if (hdr_len > 4 && strncmp(httpState->reply_hdr, "HTTP/", 5)) { - debug(11, 3) ("httpProcessReplyHeader: Non-HTTP-compliant header: '%s'\n", httpState->reply_hdr); + if (hdr_size) + memBufAppend(&httpState->reply_hdr, buf, hdr_size); + else + memBufAppend(&httpState->reply_hdr, buf, size); + hdr_len = httpState->reply_hdr.size; + if (hdr_len > 4 && strncmp(httpState->reply_hdr.buf, "HTTP/", 5)) { + debug(11, 3) ("httpProcessReplyHeader: Non-HTTP-compliant header: '%s'\n", httpState->reply_hdr.buf); httpState->reply_hdr_state += 2; + memBufClean(&httpState->reply_hdr); reply->sline.status = HTTP_INVALID_HEADER; return; } - t = httpState->reply_hdr + hdr_len; + if (hdr_size != hdr_len) + hdr_size = headersEnd(httpState->reply_hdr.buf, hdr_len); + if (hdr_size) + hdr_len = hdr_size; + if (hdr_len > Config.maxReplyHeaderSize) { + debug(11, 1) ("httpProcessReplyHeader: Too large reply header\n"); + if (!memBufIsNull(&httpState->reply_hdr)) + memBufClean(&httpState->reply_hdr); + reply->sline.status = HTTP_HEADER_TOO_LARGE; + return; + } /* headers can be incomplete only if object still arriving */ - if (!httpState->eof) { - size_t k = headersEnd(httpState->reply_hdr, 8192); - if (0 == k) + if (!hdr_size) { + if (httpState->eof) + hdr_size = hdr_len; + else return; /* headers not complete */ - t = httpState->reply_hdr + k; } - *t = '\0'; + /* Cut away any excess body data (only needed for debug?) */ + memBufAppend(&httpState->reply_hdr, "\0", 1); + httpState->reply_hdr.buf[hdr_size] = '\0'; httpState->reply_hdr_state++; assert(httpState->reply_hdr_state == 1); ctx = ctx_enter(entry->mem_obj->url); httpState->reply_hdr_state++; debug(11, 9) ("GOT HTTP REPLY HDR:\n---------\n%s\n----------\n", - httpState->reply_hdr); + httpState->reply_hdr.buf); /* Parse headers into reply structure */ /* what happens if we fail to parse here? */ - httpReplyParse(reply, httpState->reply_hdr, hdr_len); + httpReplyParse(reply, httpState->reply_hdr.buf, hdr_size); storeTimestampsSet(entry); /* Check if object is cacheable or not based on reply code */ debug(11, 3) ("httpProcessReplyHeader: HTTP CODE: %d\n", reply->sline.status); @@ -489,7 +498,7 @@ if (Config.onoff.detect_broken_server_pconns && httpReplyBodySize(httpState->request->method, reply) == -1) { debug(11, 1) ("httpProcessReplyHeader: Impossible keep-alive header from '%s'\n", storeUrl(entry)); debug(11, 2) ("GOT HTTP REPLY HDR:\n---------\n%s\n----------\n", - httpState->reply_hdr); + httpState->reply_hdr.buf); httpState->flags.keepalive_broken = 1; } } @@ -600,7 +609,7 @@ clen >>= 1; IOStats.Http.read_hist[bin]++; } - if (!httpState->reply_hdr && len > 0 && fd_table[fd].uses > 1) { + if (!httpState->reply_hdr.size && len > 0 && fd_table[fd].uses > 1) { /* Skip whitespace */ while (len > 0 && xisspace(*buf)) xmemmove(buf, buf + 1, len--); @@ -618,7 +627,7 @@ commSetSelect(fd, COMM_SELECT_READ, httpReadReply, httpState, 0); } else if (entry->mem_obj->inmem_hi == 0) { ErrorState *err; - err = errorCon(ERR_READ_ERROR, HTTP_INTERNAL_SERVER_ERROR); + err = errorCon(ERR_READ_ERROR, HTTP_BAD_GATEWAY); err->request = requestLink((request_t *) request); err->xerrno = errno; fwdFail(httpState->fwd, err); @@ -628,7 +637,7 @@ } } else if (len == 0 && entry->mem_obj->inmem_hi == 0) { ErrorState *err; - err = errorCon(ERR_ZERO_SIZE_OBJECT, HTTP_SERVICE_UNAVAILABLE); + err = errorCon(ERR_ZERO_SIZE_OBJECT, HTTP_BAD_GATEWAY); err->xerrno = errno; err->request = requestLink((request_t *) request); fwdFail(httpState->fwd, err); @@ -645,11 +654,31 @@ * we want to process the reply headers. */ httpProcessReplyHeader(httpState, buf, len); - fwdComplete(httpState->fwd); + if (entry->mem_obj->reply->sline.status == HTTP_HEADER_TOO_LARGE) { + ErrorState *err; + storeEntryReset(entry); + err = errorCon(ERR_TOO_BIG, HTTP_BAD_GATEWAY); + err->request = requestLink((request_t *) request); + fwdFail(httpState->fwd, err); + httpState->fwd->flags.dont_retry = 1; + } else { + fwdComplete(httpState->fwd); + } comm_close(fd); + return; } else { if (httpState->reply_hdr_state < 2) { httpProcessReplyHeader(httpState, buf, len); + if (entry->mem_obj->reply->sline.status == HTTP_HEADER_TOO_LARGE) { + ErrorState *err; + storeEntryReset(entry); + err = errorCon(ERR_TOO_BIG, HTTP_BAD_GATEWAY); + err->request = requestLink((request_t *) request); + fwdFail(httpState->fwd, err); + httpState->fwd->flags.dont_retry = 1; + comm_close(fd); + return; + } if (httpState->reply_hdr_state == 2) { http_status s = entry->mem_obj->reply->sline.status; #if WIP_FWD_LOG @@ -719,7 +748,7 @@ return; if (errflag) { if (entry->mem_obj->inmem_hi == 0) { - err = errorCon(ERR_WRITE_ERROR, HTTP_INTERNAL_SERVER_ERROR); + err = errorCon(ERR_WRITE_ERROR, HTTP_BAD_GATEWAY); err->xerrno = errno; err->request = requestLink(httpState->orig_request); errorAppendEntry(entry, err); @@ -1002,7 +1031,7 @@ commSetTimeout(fd, Config.Timeout.lifetime, httpTimeout, httpState); commSetSelect(fd, COMM_SELECT_READ, httpReadReply, httpState, 0); - if (httpState->orig_request->body_connection) + if (httpState->orig_request->body_reader) sendHeaderDone = httpSendRequestEntry; else sendHeaderDone = httpSendComplete; @@ -1175,7 +1204,7 @@ return; if (errflag) { if (entry->mem_obj->inmem_hi == 0) { - err = errorCon(ERR_WRITE_ERROR, HTTP_INTERNAL_SERVER_ERROR); + err = errorCon(ERR_WRITE_ERROR, HTTP_BAD_GATEWAY); err->xerrno = errno; err->request = requestLink(httpState->orig_request); errorAppendEntry(entry, err); @@ -1188,7 +1217,7 @@ return; } httpState->body_buf = memAllocate(MEM_8K_BUF); - clientReadBody(httpState->orig_request, httpState->body_buf, 8192, httpRequestBodyHandler, httpState); + requestReadBody(httpState->orig_request, httpState->body_buf, 8192, httpRequestBodyHandler, httpState); } void diff -ruN squid-2.5.STABLE7-RC2/src/protos.h squid-2.5.STABLE7-RC3/src/protos.h --- squid-2.5.STABLE7-RC2/src/protos.h Mon Sep 27 12:17:39 2004 +++ squid-2.5.STABLE7-RC3/src/protos.h Tue Oct 5 16:34:42 2004 @@ -1,6 +1,6 @@ /* - * $Id: protos.h,v 1.420.2.23 2004/09/27 18:17:39 hno Exp $ + * $Id: protos.h,v 1.420.2.25 2004/10/05 22:34:42 hno Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -141,8 +141,6 @@ extern void clientHttpConnectionsClose(void); extern StoreEntry *clientCreateStoreEntry(clientHttpRequest *, method_t, request_flags); extern int isTcpHit(log_type); -extern void clientReadBody(request_t * req, char *buf, size_t size, CBCB * callback, void *data); -extern void clientAbortBody(request_t * req); extern int commSetNonBlocking(int fd); extern int commUnsetNonBlocking(int fd); @@ -304,8 +302,6 @@ /* http.c */ extern int httpCachable(method_t); extern void httpStart(FwdState *); -extern void httpParseReplyHeaders(const char *, http_reply *); -extern void httpProcessReplyHeader(HttpStateData *, const char *, int); extern mb_size_t httpBuildRequestPrefix(request_t * request, request_t * orig_request, StoreEntry * entry, @@ -521,6 +517,8 @@ extern int httpRequestPrefixLen(const request_t * req); extern int httpRequestHdrAllowed(const HttpHeaderEntry * e, String * strConnection); extern int httpRequestHdrAllowedByName(http_hdr_type id); +extern void requestReadBody(request_t * request, char *buf, size_t size, CBCB * callback, void *cbdata); +extern void requestAbortBody(request_t * request); extern void icmpOpen(void); extern void icmpClose(void); diff -ruN squid-2.5.STABLE7-RC2/src/structs.h squid-2.5.STABLE7-RC3/src/structs.h --- squid-2.5.STABLE7-RC2/src/structs.h Mon Sep 27 12:17:39 2004 +++ squid-2.5.STABLE7-RC3/src/structs.h Tue Oct 5 16:56:36 2004 @@ -1,6 +1,6 @@ /* - * $Id: structs.h,v 1.408.2.27 2004/09/27 18:17:39 hno Exp $ + * $Id: structs.h,v 1.408.2.30 2004/10/05 22:56:36 hno Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -431,6 +431,7 @@ } Timeout; size_t maxRequestHeaderSize; size_t maxRequestBodySize; + size_t maxReplyHeaderSize; dlink_list ReplyBodySize; struct { u_short icp; @@ -987,8 +988,7 @@ struct _HttpStateData { StoreEntry *entry; request_t *request; - char *reply_hdr; - size_t reply_hdr_size; + MemBuf reply_hdr; int reply_hdr_state; peer *peer; /* peer request made to */ int eof; /* reached end-of-object? */ @@ -1672,13 +1672,14 @@ struct in_addr my_addr; unsigned short my_port; HttpHeader header; - ConnStateData *body_connection; /* used by clientReadBody() */ int content_length; HierarchyLogEntry hier; err_type err_type; char *peer_login; /* Configured peer login:password */ time_t lastmod; /* Used on refreshes */ const char *vary_headers; /* Used when varying entities are detected. Changes how the store key is calculated */ + BODY_HANDLER *body_reader; + void *body_reader_data; }; struct _cachemgr_passwd { diff -ruN squid-2.5.STABLE7-RC2/src/typedefs.h squid-2.5.STABLE7-RC3/src/typedefs.h --- squid-2.5.STABLE7-RC2/src/typedefs.h Sat Sep 25 05:56:16 2004 +++ squid-2.5.STABLE7-RC3/src/typedefs.h Tue Oct 5 16:34:42 2004 @@ -1,6 +1,6 @@ /* - * $Id: typedefs.h,v 1.132.2.5 2004/09/25 11:56:16 hno Exp $ + * $Id: typedefs.h,v 1.132.2.6 2004/10/05 22:34:42 hno Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -236,6 +236,7 @@ typedef int READ_HANDLER(int, char *, int); typedef int WRITE_HANDLER(int, const char *, int); typedef void CBCB(char *buf, ssize_t size, void *data); +typedef void BODY_HANDLER(request_t * req, char *, size_t, CBCB *, void *); typedef void STIOCB(void *their_data, int errflag, storeIOState *); typedef void STFNCB(void *their_data, int errflag, storeIOState *);