The Squid Team are pleased to announce the release of Squid-3.0.STABLE19.
+The Squid Team are pleased to announce the release of Squid-3.0.STABLE20.
This new release is available for download from http://www.squid-cache.org/Versions/v3/3.0/ or the mirrors.
diff -u -r -N squid-3.0.STABLE19/src/ACLARP.cc squid-3.0.STABLE20/src/ACLARP.cc --- squid-3.0.STABLE19/src/ACLARP.cc 2009-09-06 23:29:35.000000000 +1200 +++ squid-3.0.STABLE20/src/ACLARP.cc 2009-10-29 23:05:44.000000000 +1300 @@ -438,7 +438,7 @@ return (0 == splayLastResult); } -#elif defined(_SQUID_FREEBSD_) || defined(_SQUID_NETBSD_) || defined(_SQUID_OPENBSD_) || defined(_SQUID_DRAGONFLY_) +#elif defined(_SQUID_FREEBSD_) || defined(_SQUID_NETBSD_) || defined(_SQUID_OPENBSD_) || defined(_SQUID_DRAGONFLY_) || defined(_SQUID_KFREEBSD_) struct arpreq arpReq; diff -u -r -N squid-3.0.STABLE19/src/ACLProxyAuth.cc squid-3.0.STABLE20/src/ACLProxyAuth.cc --- squid-3.0.STABLE19/src/ACLProxyAuth.cc 2009-09-06 23:29:35.000000000 +1200 +++ squid-3.0.STABLE20/src/ACLProxyAuth.cc 2009-10-29 23:05:45.000000000 +1300 @@ -143,7 +143,8 @@ assert(checklist->auth_user_request != NULL); auth_user_request = checklist->auth_user_request; - assert(authenticateValidateUser(auth_user_request)); + int validated = authenticateValidateUser(auth_user_request); + assert(validated); auth_user_request->start(LookupDone, checklist); } diff -u -r -N squid-3.0.STABLE19/src/auth/digest/auth_digest.cc squid-3.0.STABLE20/src/auth/digest/auth_digest.cc --- squid-3.0.STABLE19/src/auth/digest/auth_digest.cc 2009-09-06 23:29:36.000000000 +1200 +++ squid-3.0.STABLE20/src/auth/digest/auth_digest.cc 2009-10-29 23:05:46.000000000 +1300 @@ -1035,7 +1035,7 @@ authDigestNonceLink(nonce); /* ping this nonce to this auth user */ - assert((nonce->user == NULL) || (nonce->user = user)); + assert((nonce->user == NULL) || (nonce->user == user)); /* we don't lock this reference because removing the user removes the * hash too. Of course if that changes we're stuffed so read the code huh? @@ -1105,6 +1105,7 @@ /* quote mark */ p++; + safe_free(username); username = xstrndup(p, strchr(p, '"') + 1 - p); debugs(29, 9, "authDigestDecodeAuth: Found Username '" << username << "'"); @@ -1117,6 +1118,7 @@ /* quote mark */ p++; + safe_free(digest_request->realm); digest_request->realm = xstrndup(p, strchr(p, '"') + 1 - p); debugs(29, 9, "authDigestDecodeAuth: Found realm '" << digest_request->realm << "'"); @@ -1130,6 +1132,7 @@ /* quote mark */ p++; + safe_free(digest_request->qop); digest_request->qop = xstrndup(p, strcspn(p, "\" \t\r\n()<>@,;:\\/[]?={}") + 1); debugs(29, 9, "authDigestDecodeAuth: Found qop '" << digest_request->qop << "'"); @@ -1143,6 +1146,7 @@ /* quote mark */ p++; + safe_free(digest_request->algorithm); digest_request->algorithm = xstrndup(p, strcspn(p, "\" \t\r\n()<>@,;:\\/[]?={}") + 1); debugs(29, 9, "authDigestDecodeAuth: Found algorithm '" << digest_request->algorithm << "'"); @@ -1155,6 +1159,7 @@ /* quote mark */ p++; + safe_free(digest_request->uri); digest_request->uri = xstrndup(p, strchr(p, '"') + 1 - p); debugs(29, 9, "authDigestDecodeAuth: Found uri '" << digest_request->uri << "'"); @@ -1167,6 +1172,7 @@ /* quote mark */ p++; + safe_free(digest_request->nonceb64); digest_request->nonceb64 = xstrndup(p, strchr(p, '"') + 1 - p); debugs(29, 9, "authDigestDecodeAuth: Found nonce '" << digest_request->nonceb64 << "'"); @@ -1188,6 +1194,7 @@ /* quote mark */ p++; + safe_free(digest_request->cnonce); digest_request->cnonce = xstrndup(p, strchr(p, '"') + 1 - p); debugs(29, 9, "authDigestDecodeAuth: Found cnonce '" << digest_request->cnonce << "'"); @@ -1200,6 +1207,7 @@ /* quote mark */ p++; + safe_free(digest_request->response); digest_request->response = xstrndup(p, strchr(p, '"') + 1 - p); debugs(29, 9, "authDigestDecodeAuth: Found response '" << digest_request->response << "'"); diff -u -r -N squid-3.0.STABLE19/src/cf.data.pre squid-3.0.STABLE20/src/cf.data.pre --- squid-3.0.STABLE19/src/cf.data.pre 2009-09-06 23:29:37.000000000 +1200 +++ squid-3.0.STABLE20/src/cf.data.pre 2009-10-29 23:05:47.000000000 +1300 @@ -676,8 +676,8 @@ opposite of the last line in the list. If the last line was deny, the default is allow. Conversely, if the last line is allow, the default will be deny. For these reasons, it is a - good idea to have an "deny all" or "allow all" entry at the end - of your access lists to avoid potential confusion. + good idea to have an "deny all" entry at the end of your access + lists to avoid potential confusion. NOCOMMENT_START #Recommended minimum configuration: @@ -5452,7 +5452,7 @@ LOC: Config.chroot_dir DEFAULT: none DOC_START - Specifies a directiry where Squid should do a chroot() while + Specifies a directory where Squid should do a chroot() while initializing. This also causes Squid to fully drop root privileges after initializing. This means, for example, if you use a HTTP port less than 1024 and try to reconfigure, you may diff -u -r -N squid-3.0.STABLE19/src/client_side.cc squid-3.0.STABLE20/src/client_side.cc --- squid-3.0.STABLE19/src/client_side.cc 2009-09-06 23:29:37.000000000 +1200 +++ squid-3.0.STABLE20/src/client_side.cc 2009-10-29 23:05:47.000000000 +1300 @@ -942,14 +942,14 @@ return; } - int64_t next = getNextRangeOffset(); + int64_t nextOffset = getNextRangeOffset(); - assert (next >= http->out.offset); + assert (nextOffset >= http->out.offset); - int64_t skip = next - http->out.offset; + int64_t skip = nextOffset - http->out.offset; /* adjust for not to be transmitted bytes */ - http->out.offset = next; + http->out.offset = nextOffset; if (available.size() <= skip) return; @@ -1913,6 +1913,15 @@ /* Set method_p */ *method_p = HttpRequestMethod(&hp->buf[hp->m_start], &hp->buf[hp->m_end]); + /* deny CONNECT via accelerated ports */ + if (*method_p == METHOD_CONNECT && conn != NULL && conn->port && conn->port->accel) { + debugs(33, DBG_IMPORTANT, "WARNING: CONNECT method received on " << conn->port->protocol << " Accelerator port " << ntohs(conn->port->s.sin_port) ); + /* XXX need a way to say "this many character length string" */ + debugs(33, DBG_IMPORTANT, "WARNING: for request: " << hp->buf); + /* XXX need some way to set 405 status on the error reply */ + return parseHttpRequestAbort(conn, "error:method-not-allowed"); + } + if (*method_p == METHOD_NONE) { /* AYJ: hp->buf is occasionally full of binary crap. Replace any non-printables with underscores. Also crop the output at 100 chars, we should not need a whole binary streaming video to identify the issue diff -u -r -N squid-3.0.STABLE19/src/client_side_reply.cc squid-3.0.STABLE20/src/client_side_reply.cc --- squid-3.0.STABLE19/src/client_side_reply.cc 2009-09-06 23:29:37.000000000 +1200 +++ squid-3.0.STABLE20/src/client_side_reply.cc 2009-10-29 23:05:47.000000000 +1300 @@ -366,7 +366,7 @@ // if client sent IMS - if (http->request->flags.ims) { + if (http->request->flags.ims && !old_entry->modifiedSince(http->request)) { // forward the 304 from origin debugs(88, 3, "handleIMSReply: origin replied 304, revalidating existing entry and forwarding 304 to client"); sendClientUpstreamResponse(); diff -u -r -N squid-3.0.STABLE19/src/client_side_request.cc squid-3.0.STABLE20/src/client_side_request.cc --- squid-3.0.STABLE19/src/client_side_request.cc 2009-09-06 23:29:37.000000000 +1200 +++ squid-3.0.STABLE20/src/client_side_request.cc 2009-10-29 23:05:47.000000000 +1300 @@ -1125,7 +1125,8 @@ // subscribe to receive reply body if (new_rep->body_pipe != NULL) { icapBodySource = new_rep->body_pipe; - assert(icapBodySource->setConsumerIfNotLate(this)); + int consumer_ok = icapBodySource->setConsumerIfNotLate(this); + assert(consumer_ok); } clientStreamNode *node = (clientStreamNode *)client_stream.tail->prev->data; diff -u -r -N squid-3.0.STABLE19/src/comm.h squid-3.0.STABLE20/src/comm.h --- squid-3.0.STABLE19/src/comm.h 2009-09-06 23:29:37.000000000 +1200 +++ squid-3.0.STABLE20/src/comm.h 2009-10-29 23:05:47.000000000 +1300 @@ -20,7 +20,7 @@ COMM_INPROGRESS = -7, COMM_ERR_CONNECT = -8, COMM_ERR_DNS = -9, - COMM_ERR_CLOSING = -10, + COMM_ERR_CLOSING = -10 } comm_err_t; typedef void IOFCB(int fd, StoreIOBuffer receivedData, comm_err_t flag, int xerrno, void *data); typedef void IOWCB(int fd, char *buffer, size_t len, comm_err_t flag, int xerrno, void *data); diff -u -r -N squid-3.0.STABLE19/src/ESIExpression.cc squid-3.0.STABLE20/src/ESIExpression.cc --- squid-3.0.STABLE19/src/ESIExpression.cc 2009-09-06 23:29:36.000000000 +1200 +++ squid-3.0.STABLE20/src/ESIExpression.cc 2009-10-29 23:05:45.000000000 +1300 @@ -721,6 +721,7 @@ if ((point = strchr (s, '.')) && point - s < (ssize_t)length) { /* floating point */ + errno=0; /* reset errno */ rv.value.floating = strtod (s, &end); if (s == end || errno) { @@ -737,6 +738,7 @@ } } else { /* INT */ + errno=0; /* reset errno */ rv.value.integral = strtol (s, &end, 0); if (s == end || errno) { diff -u -r -N squid-3.0.STABLE19/src/fs/ufs/store_dir_ufs.cc squid-3.0.STABLE20/src/fs/ufs/store_dir_ufs.cc --- squid-3.0.STABLE19/src/fs/ufs/store_dir_ufs.cc 2009-09-06 23:29:38.000000000 +1200 +++ squid-3.0.STABLE20/src/fs/ufs/store_dir_ufs.cc 2009-10-29 23:05:47.000000000 +1300 @@ -143,7 +143,7 @@ IO->io = anIO; /* Change the IO Options */ - if (currentIOOptions->options.size() > 2) + if (currentIOOptions && currentIOOptions->options.size() > 2) delete currentIOOptions->options.pop_back(); /* TODO: factor out these 4 lines */ diff -u -r -N squid-3.0.STABLE19/src/ftp.cc squid-3.0.STABLE20/src/ftp.cc --- squid-3.0.STABLE19/src/ftp.cc 2009-09-06 23:29:38.000000000 +1200 +++ squid-3.0.STABLE20/src/ftp.cc 2009-10-29 23:05:47.000000000 +1300 @@ -1204,7 +1204,7 @@ if (data.read_pending) return; - int read_sz = replyBodySpace(data.readBuf->spaceSize()); + const int read_sz = replyBodySpace(*data.readBuf, 0); debugs(11,9, HERE << "FTP may read up to " << read_sz << " bytes"); diff -u -r -N squid-3.0.STABLE19/src/gopher.cc squid-3.0.STABLE20/src/gopher.cc --- squid-3.0.STABLE19/src/gopher.cc 2009-09-06 23:29:38.000000000 +1200 +++ squid-3.0.STABLE20/src/gopher.cc 2009-10-29 23:05:48.000000000 +1300 @@ -37,6 +37,7 @@ #include "errorpage.h" #include "Store.h" #include "HttpRequest.h" +#include "HttpReply.h" #include "comm.h" #if DELAY_POOLS #include "DelayPools.h" @@ -104,7 +105,6 @@ GopherStateData; static PF gopherStateFree; -static void gopher_mime_content(MemBuf * mb, const char *name, const char *def); static void gopherMimeCreate(GopherStateData *); static void gopher_request_parse(const HttpRequest * req, char *type_id, @@ -140,35 +140,13 @@ cbdataFree(gopherState); } - -/* figure out content type from file extension */ -static void -gopher_mime_content(MemBuf * mb, const char *name, const char *def_ctype) -{ - char *ctype = mimeGetContentType(name); - char *cenc = mimeGetContentEncoding(name); - - if (cenc) - mb->Printf("Content-Encoding: %s\r\n", cenc); - - mb->Printf("Content-Type: %s\r\n", - ctype ? ctype : def_ctype); -} - - - -/* create MIME Header for Gopher Data */ +/* Create MIME Header for Gopher Data */ static void gopherMimeCreate(GopherStateData * gopherState) { - MemBuf mb; - - mb.init(); - - mb.Printf("HTTP/1.0 200 OK Gatewaying\r\n" - "Server: Squid/%s\r\n" - "Date: %s\r\n", - version_string, mkrfc1123(squid_curtime)); + StoreEntry *entry = gopherState->entry; + const char *mime_type = NULL; + const char *mime_enc = NULL; switch (gopherState->type_id) { @@ -181,7 +159,7 @@ case GOPHER_WWW: case GOPHER_CSO: - mb.Printf("Content-Type: text/html\r\n"); + mime_type = "text/html"; break; case GOPHER_GIF: @@ -189,17 +167,17 @@ case GOPHER_IMAGE: case GOPHER_PLUS_IMAGE: - mb.Printf("Content-Type: image/gif\r\n"); + mime_type = "image/gif"; break; case GOPHER_SOUND: case GOPHER_PLUS_SOUND: - mb.Printf("Content-Type: audio/basic\r\n"); + mime_type = "audio/basic"; break; case GOPHER_PLUS_MOVIE: - mb.Printf("Content-Type: video/mpeg\r\n"); + mime_type = "video/mpeg"; break; case GOPHER_MACBINHEX: @@ -210,20 +188,33 @@ case GOPHER_BIN: /* Rightnow We have no idea what it is. */ - gopher_mime_content(&mb, gopherState->request, def_gopher_bin); + mime_enc = mimeGetContentEncoding(gopherState->request); + mime_type = mimeGetContentType(gopherState->request); + if (!mime_type) + mime_type = def_gopher_bin; break; case GOPHER_FILE: default: - gopher_mime_content(&mb, gopherState->request, def_gopher_text); + mime_enc = mimeGetContentEncoding(gopherState->request); + mime_type = mimeGetContentType(gopherState->request); + if (!mime_type) + mime_type = def_gopher_text; break; } - mb.Printf("\r\n"); - EBIT_CLR(gopherState->entry->flags, ENTRY_FWD_HDR_WAIT); - gopherState->entry->append(mb.buf, mb.size); - mb.clean(); + assert(entry->isEmpty()); + EBIT_CLR(entry->flags, ENTRY_FWD_HDR_WAIT); + + HttpReply *reply = new HttpReply; + entry->buffer(); + HttpVersion version(1, 0); + reply->setHeaders(version, HTTP_OK, "Gatewaying", mime_type, -1, -1, -2); + if (mime_enc) + reply->header.putStr(HDR_CONTENT_ENCODING, mime_enc); + + entry->replaceHttpReply(reply); } /* Parse a gopher request into components. By Anawat. */ diff -u -r -N squid-3.0.STABLE19/src/http.cc squid-3.0.STABLE20/src/http.cc --- squid-3.0.STABLE19/src/http.cc 2009-09-06 23:29:38.000000000 +1200 +++ squid-3.0.STABLE20/src/http.cc 2009-10-29 23:05:48.000000000 +1300 @@ -1248,7 +1248,9 @@ void HttpStateData::maybeReadVirginBody() { - int read_sz = replyBodySpace(readBuf->spaceSize()); + // we may need to grow the buffer if headers do not fit + const int minRead = flags.headers_parsed ? 0 :1024; + const int read_sz = replyBodySpace(*readBuf, minRead); debugs(11,9, HERE << (flags.do_next_read ? "may" : "wont") << " read up to " << read_sz << " bytes from FD " << fd); @@ -1261,12 +1263,8 @@ * handler until we get a notification from someone that * its okay to read again. */ - if (read_sz < 2) { - if (flags.headers_parsed) - return; - else - read_sz = 1024; - } + if (read_sz < 2) + return; if (flags.do_next_read) { flags.do_next_read = 0; diff -u -r -N squid-3.0.STABLE19/src/Server.cc squid-3.0.STABLE20/src/Server.cc --- squid-3.0.STABLE19/src/Server.cc 2009-09-06 23:29:36.000000000 +1200 +++ squid-3.0.STABLE20/src/Server.cc 2009-10-29 23:05:46.000000000 +1300 @@ -717,8 +717,15 @@ currentOffset += len; } -size_t ServerStateData::replyBodySpace(size_t space) +size_t ServerStateData::replyBodySpace(const MemBuf &readBuf, + const size_t minSpace) const { + size_t space = readBuf.spaceSize(); // available space w/o heroic measures + if (space < minSpace) { + const size_t maxSpace = readBuf.potentialSpaceSize(); // absolute best + space = min(minSpace, maxSpace); // do not promise more than asked + } + #if ICAP_CLIENT if (responseBodyBuffer) { return 0; // Stop reading if already overflowed waiting for ICAP to catch up diff -u -r -N squid-3.0.STABLE19/src/Server.h squid-3.0.STABLE20/src/Server.h --- squid-3.0.STABLE19/src/Server.h 2009-09-06 23:29:36.000000000 +1200 +++ squid-3.0.STABLE20/src/Server.h 2009-10-29 23:05:46.000000000 +1300 @@ -160,7 +160,7 @@ void adaptOrFinalizeReply(); void addVirginReplyBody(const char *buf, ssize_t len); void storeReplyBody(const char *buf, ssize_t len); - size_t replyBodySpace(size_t space = 4096 * 10); + size_t replyBodySpace(const MemBuf &readBuf, const size_t minSpace) const; // These should be private int64_t currentOffset; // Our current offset in the StoreEntry diff -u -r -N squid-3.0.STABLE19/src/tools.cc squid-3.0.STABLE20/src/tools.cc --- squid-3.0.STABLE19/src/tools.cc 2009-09-06 23:29:39.000000000 +1200 +++ squid-3.0.STABLE20/src/tools.cc 2009-10-29 23:05:48.000000000 +1300 @@ -40,16 +40,16 @@ #include "wordlist.h" #include "SquidTime.h" -#ifdef _SQUID_LINUX_ -#if HAVE_SYS_CAPABILITY_H +#if defined(_SQUID_LINUX_) && HAVE_SYS_CAPABILITY_H +// HACK: LIBCAP_BROKEN Ugly glue to get around linux header madness colliding with glibc +#if LIBCAP_BROKEN #undef _POSIX_SOURCE -/* Ugly glue to get around linux header madness colliding with glibc */ #define _LINUX_TYPES_H #define _LINUX_FS_H typedef uint32_t __u32; -#include