aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNatanael Copa <ncopa@alpinelinux.org>2014-05-14 09:31:30 +0000
committerNatanael Copa <ncopa@alpinelinux.org>2014-05-14 09:47:02 +0000
commiteb920fcf6ac920ce23fae59a2efa559e3f25d227 (patch)
tree6b74562590a852c40d66953b745f0ae8d1a7001d
parent29880316e4d89974619a59348463b0c4a9bfd613 (diff)
downloadaports-eb920fcf6ac920ce23fae59a2efa559e3f25d227.tar.bz2
aports-eb920fcf6ac920ce23fae59a2efa559e3f25d227.tar.xz
main/squid: upgrade to 3.2.13 and security fix for CVE-2014-0128
fixes #2875
-rw-r--r--main/squid/APKBUILD6
-rw-r--r--main/squid/CVE-2014-0128.patch288
2 files changed, 292 insertions, 2 deletions
diff --git a/main/squid/APKBUILD b/main/squid/APKBUILD
index 12bfe36d7c..cbdb1337da 100644
--- a/main/squid/APKBUILD
+++ b/main/squid/APKBUILD
@@ -1,7 +1,7 @@
# Contributor: Carlo Landmeter <clandmeter@gmail.com>
# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
pkgname=squid
-pkgver=3.2.9
+pkgver=3.2.13
pkgrel=0
pkgdesc="A full-featured Web proxy cache server."
url="http://www.squid-cache.org"
@@ -21,6 +21,7 @@ langdir="/usr/share/squid/errors"
source="http://www.squid-cache.org/Versions/v3/3.2/squid-$pkgver.tar.bz2
squid-3.2.0.16-loggable-urlgroup.patch
cf_gen-pthread.patch
+ CVE-2014-0128.patch
squid.initd
squid.confd
$pkgname.logrotate
@@ -104,9 +105,10 @@ squid_kerb_auth() {
mv "$pkgdir"/usr/lib/squid/squid_kerb_auth "$subpkgdir"/usr/lib/squid/
}
-md5sums="de02be3c1f72e0d818374438044261a6 squid-3.2.9.tar.bz2
+md5sums="367e59c9c25da7ebbfbf7cbc36d2444e squid-3.2.13.tar.bz2
16e3b38996d4c5858e1478f8eb650876 squid-3.2.0.16-loggable-urlgroup.patch
c60237de253c02937f272d3b189d7679 cf_gen-pthread.patch
+7a631b0300d090d89567df8090f5368e CVE-2014-0128.patch
905e57c6d41414f54a75a5c0f9f7fac7 squid.initd
2897c725c201be53d3c9a7db0101bdf0 squid.confd
58823e0b86bc2dc71d270208b7b284b4 squid.logrotate"
diff --git a/main/squid/CVE-2014-0128.patch b/main/squid/CVE-2014-0128.patch
new file mode 100644
index 0000000000..7861df1335
--- /dev/null
+++ b/main/squid/CVE-2014-0128.patch
@@ -0,0 +1,288 @@
+diff -rNU 20 ../squid-3.2.11-o/src/client_side.cc ./src/client_side.cc
+--- ../squid-3.2.11-o/src/client_side.cc 2013-04-30 06:47:06.000000000 +0200
++++ ./src/client_side.cc 2014-04-09 15:14:50.000000000 +0200
+@@ -1249,43 +1249,41 @@
+
+ /* hits only - upstream peer determines correct behaviour on misses, and client_side_reply determines
+ * hits candidates
+ */
+ else if (logTypeIsATcpHit(http->logType) && http->request->header.has(HDR_IF_RANGE) && !clientIfRangeMatch(http, rep))
+ range_err = "If-Range match failed";
+ else if (!http->request->range->canonize(rep))
+ range_err = "canonization failed";
+ else if (http->request->range->isComplex())
+ range_err = "too complex range header";
+ else if (!logTypeIsATcpHit(http->logType) && http->request->range->offsetLimitExceeded(roffLimit))
+ range_err = "range outside range_offset_limit";
+
+ /* get rid of our range specs on error */
+ if (range_err) {
+ /* XXX We do this here because we need canonisation etc. However, this current
+ * code will lead to incorrect store offset requests - the store will have the
+ * offset data, but we won't be requesting it.
+ * So, we can either re-request, or generate an error
+ */
+- debugs(33, 3, "clientBuildRangeHeader: will not do ranges: " << range_err << ".");
+- delete http->request->range;
+- http->request->range = NULL;
++ http->request->ignoreRange(range_err);
+ } else {
+ /* XXX: TODO: Review, this unconditional set may be wrong. - TODO: review. */
+ httpStatusLineSet(&rep->sline, rep->sline.version,
+ HTTP_PARTIAL_CONTENT, NULL);
+ // web server responded with a valid, but unexpected range.
+ // will (try-to) forward as-is.
+ //TODO: we should cope with multirange request/responses
+ bool replyMatchRequest = rep->content_range != NULL ?
+ request->range->contains(rep->content_range->spec) :
+ true;
+ const int spec_count = http->request->range->specs.count;
+ int64_t actual_clen = -1;
+
+ debugs(33, 3, "clientBuildRangeHeader: range spec count: " <<
+ spec_count << " virgin clen: " << rep->content_length);
+ assert(spec_count > 0);
+ /* append appropriate header(s) */
+
+ if (spec_count == 1) {
+ if (!replyMatchRequest) {
+diff -rNU 20 ../squid-3.2.11-o/src/client_side_reply.cc ./src/client_side_reply.cc
+--- ../squid-3.2.11-o/src/client_side_reply.cc 2013-04-30 06:47:06.000000000 +0200
++++ ./src/client_side_reply.cc 2014-04-09 15:21:57.000000000 +0200
+@@ -102,40 +102,43 @@
+ err_type err, http_status status, const HttpRequestMethod& method, char const *uri,
+ Ip::Address &addr, HttpRequest * failedrequest, const char *unparsedrequest,
+ #if USE_AUTH
+ Auth::UserRequest::Pointer auth_user_request
+ #else
+ void*
+ #endif
+ )
+ {
+ ErrorState *errstate = clientBuildError(err, status, uri, addr, failedrequest);
+
+ if (unparsedrequest)
+ errstate->request_hdrs = xstrdup(unparsedrequest);
+
+ if (status == HTTP_NOT_IMPLEMENTED && http->request)
+ /* prevent confusion over whether we default to persistent or not */
+ http->request->flags.proxy_keepalive = 0;
+
+ http->al->http.code = errstate->httpStatus;
+
++ if (http->request)
++ http->request->ignoreRange("responding with a Squid-generated error");
++
+ createStoreEntry(method, request_flags());
+ #if USE_AUTH
+ errstate->auth_user_request = auth_user_request;
+ #endif
+ assert(errstate->callback_data == NULL);
+ errorAppendEntry(http->storeEntry(), errstate);
+ /* Now the caller reads to get this */
+ }
+
+ void
+ clientReplyContext::removeStoreReference(store_client ** scp,
+ StoreEntry ** ep)
+ {
+ StoreEntry *e;
+ store_client *sc_tmp = *scp;
+
+ if ((e = *ep) != NULL) {
+ *ep = NULL;
+ storeUnregister(sc_tmp, e, this);
+ *scp = NULL;
+diff -rNU 20 ../squid-3.2.11-o/src/client_side_request.cc ./src/client_side_request.cc
+--- ../squid-3.2.11-o/src/client_side_request.cc 2014-04-09 14:58:52.000000000 +0200
++++ ./src/client_side_request.cc 2014-04-09 15:22:41.000000000 +0200
+@@ -1097,42 +1097,41 @@
+ clientStreamNode *node = (clientStreamNode *)http->client_stream.tail->data;
+ /* XXX: This is suboptimal. We should give the stream the range set,
+ * and thereby let the top of the stream set the offset when the
+ * size becomes known. As it is, we will end up requesting from 0
+ * for evey -X range specification.
+ * RBC - this may be somewhat wrong. We should probably set the range
+ * iter up at this point.
+ */
+ node->readBuffer.offset = request->range->lowestOffset(0);
+ http->range_iter.pos = request->range->begin();
+ http->range_iter.valid = true;
+ }
+ }
+
+ /* Only HEAD and GET requests permit a Range or Request-Range header.
+ * If these headers appear on any other type of request, delete them now.
+ */
+ else {
+ req_hdr->delById(HDR_RANGE);
+ req_hdr->delById(HDR_REQUEST_RANGE);
+- delete request->range;
+- request->range = NULL;
++ request->ignoreRange("neither HEAD nor GET");
+ }
+
+ if (req_hdr->has(HDR_AUTHORIZATION))
+ request->flags.auth = 1;
+
+ clientCheckPinning(http);
+
+ if (request->login[0] != '\0')
+ request->flags.auth = 1;
+
+ if (req_hdr->has(HDR_VIA)) {
+ String s = req_hdr->getList(HDR_VIA);
+ /*
+ * ThisCache cannot be a member of Via header, "1.1 ThisCache" can.
+ * Note ThisCache2 has a space prepended to the hostname so we don't
+ * accidentally match super-domains.
+ */
+
+ if (strListIsSubstr(&s, ThisCache2, ',')) {
+ debugObj(33, 1, "WARNING: Forwarding loop detected for:\n",
+diff -rNU 20 ../squid-3.2.11-o/src/http.cc ./src/http.cc
+--- ../squid-3.2.11-o/src/http.cc 2013-04-30 06:47:06.000000000 +0200
++++ ./src/http.cc 2014-04-09 15:23:31.000000000 +0200
+@@ -1710,42 +1710,41 @@
+ assert (hdr_out->owner == hoRequest);
+
+ /* append our IMS header */
+ if (request->lastmod > -1)
+ hdr_out->putTime(HDR_IF_MODIFIED_SINCE, request->lastmod);
+
+ bool we_do_ranges = decideIfWeDoRanges (request);
+
+ String strConnection (hdr_in->getList(HDR_CONNECTION));
+
+ while ((e = hdr_in->getEntry(&pos)))
+ copyOneHeaderFromClientsideRequestToUpstreamRequest(e, strConnection, request, hdr_out, we_do_ranges, flags);
+
+ /* Abstraction break: We should interpret multipart/byterange responses
+ * into offset-length data, and this works around our inability to do so.
+ */
+ if (!we_do_ranges && request->multipartRangeRequest()) {
+ /* don't cache the result */
+ request->flags.cachable = 0;
+ /* pretend it's not a range request */
+- delete request->range;
+- request->range = NULL;
++ request->ignoreRange("want to request the whole object");
+ request->flags.range = 0;
+ }
+
+ /* append Via */
+ if (Config.onoff.via) {
+ String strVia;
+ strVia = hdr_in->getList(HDR_VIA);
+ snprintf(bbuf, BBUF_SZ, "%d.%d %s",
+ request->http_ver.major,
+ request->http_ver.minor, ThisCache);
+ strListAdd(&strVia, bbuf, ',');
+ hdr_out->putStr(HDR_VIA, strVia.termedBuf());
+ strVia.clean();
+ }
+
+ if (request->flags.accelerated) {
+ /* Append Surrogate-Capabilities */
+ String strSurrogate(hdr_in->getList(HDR_SURROGATE_CAPABILITY));
+ #if USE_SQUID_ESI
+ snprintf(bbuf, BBUF_SZ, "%s=\"Surrogate/1.0 ESI/1.0\"", Config.Accel.surrogate_id);
+diff -rNU 20 ../squid-3.2.11-o/src/HttpRequest.cc ./src/HttpRequest.cc
+--- ../squid-3.2.11-o/src/HttpRequest.cc 2013-04-30 06:47:06.000000000 +0200
++++ ./src/HttpRequest.cc 2014-04-09 15:04:05.000000000 +0200
+@@ -674,31 +674,46 @@
+ return rangeOffsetLimit;
+
+ rangeOffsetLimit = 0; // default value for rangeOffsetLimit
+
+ ACLFilledChecklist ch(NULL, this, NULL);
+ ch.src_addr = client_addr;
+ ch.my_addr = my_addr;
+
+ for (acl_size_t *l = Config.rangeOffsetLimit; l; l = l -> next) {
+ /* if there is no ACL list or if the ACLs listed match use this limit value */
+ if (!l->aclList || ch.fastCheck(l->aclList) == ACCESS_ALLOWED) {
+ debugs(58, 4, HERE << "rangeOffsetLimit=" << rangeOffsetLimit);
+ rangeOffsetLimit = l->size; // may be -1
+ break;
+ }
+ }
+
+ return rangeOffsetLimit;
+ }
+
++void
++HttpRequest::ignoreRange(const char *reason)
++{
++ if (range) {
++ debugs(73, 3, static_cast<void*>(range) << " for " << reason);
++ delete range;
++ range = NULL;
++ }
++ // Some callers also reset isRanged but it may not be safe for all callers:
++ // isRanged is used to determine whether a weak ETag comparison is allowed,
++ // and that check should not ignore the Range header if it was present.
++ // TODO: Some callers also delete HDR_RANGE, HDR_REQUEST_RANGE. Should we?
++}
++
++
+ bool
+ HttpRequest::canHandle1xx() const
+ {
+ // old clients do not support 1xx unless they sent Expect: 100-continue
+ // (we reject all other HDR_EXPECT values so just check for HDR_EXPECT)
+ if (http_ver <= HttpVersion(1,0) && !header.has(HDR_EXPECT))
+ return false;
+
+ // others must support 1xx control messages
+ return true;
+ }
+diff -rNU 20 ../squid-3.2.11-o/src/HttpRequest.h ./src/HttpRequest.h
+--- ../squid-3.2.11-o/src/HttpRequest.h 2013-04-30 06:47:06.000000000 +0200
++++ ./src/HttpRequest.h 2014-04-09 15:04:42.000000000 +0200
+@@ -223,40 +223,43 @@
+ void pack(Packer * p);
+
+ static void httpRequestPack(void *obj, Packer *p);
+
+ static HttpRequest * CreateFromUrlAndMethod(char * url, const HttpRequestMethod& method);
+
+ static HttpRequest * CreateFromUrl(char * url);
+
+ ConnStateData *pinnedConnection() {
+ if (clientConnectionManager.valid() && clientConnectionManager->pinning.pinned)
+ return clientConnectionManager.get();
+ return NULL;
+ }
+
+ /**
+ * The client connection manager, if known;
+ * Used for any response actions needed directly to the client.
+ * ie 1xx forwarding or connection pinning state changes
+ */
+ CbcPointer<ConnStateData> clientConnectionManager;
++ /// forgets about the cached Range header (for a reason)
++ void ignoreRange(const char *reason);
++
+
+ int64_t getRangeOffsetLimit(); /* the result of this function gets cached in rangeOffsetLimit */
+
+ private:
+ const char *packableURI(bool full_uri) const;
+
+ mutable int64_t rangeOffsetLimit; /* caches the result of getRangeOffsetLimit */
+
+ protected:
+ virtual void packFirstLineInto(Packer * p, bool full_uri) const;
+
+ virtual bool sanityCheckStartLine(MemBuf *buf, const size_t hdr_len, http_status *error);
+
+ virtual void hdrCacheInit();
+
+ virtual bool inheritProperties(const HttpMsg *aMsg);
+ };
+
+ MEMPROXY_CLASS_INLINE(HttpRequest);
+
+
+