[pkg-squid-devel] squid3_3.4.8-6+deb8u1 - Fix for CVE-2015-5400

Luigi Gangitano luigi at debian.org
Wed Jul 22 17:31:34 UTC 2015


Hi security-team,

I’ve prepared an update for squid3 in jessie, fixing CVE-2015-5400 and closing bug #793128. Debdiff against current version in jessie is below.

I can write a DSA if needed, or upload the package if you instruct so.

Let me know which is the preferred process from now on.

Best regards,

L

--
Luigi Gangitano -- <luigi at debian.org <mailto:luigi at debian.org>> -- <gangitano at lugroma3.org <mailto:gangitano at lugroma3.org>>
GPG: 1024D/924C0C26: 12F8 9C03 89D3 DB4A 9972  C24A F19B A618 924C 0C26
GPG: 4096R/2BA97CED: 8D48 5A35 FF1E 6EB7 90E5  0F6D 0284 F20C 2BA9 7CED

dpkg-source: warning: extracting unsigned source package (/home/luigi/debian/squid3/build-area/squid3_3.4.8-6+deb8u1.dsc)
diff -Nru squid3-3.4.8/debian/changelog squid3-3.4.8/debian/changelog
--- squid3-3.4.8/debian/changelog	2015-01-28 12:59:07.000000000 +0100
+++ squid3-3.4.8/debian/changelog	2015-07-22 19:35:30.000000000 +0200
@@ -1,3 +1,12 @@
+squid3 (3.4.8-6+deb8u1) jessie-security; urgency=high
+
+  [ Luigi Gangitano <luigi at debian.org> ]
+  * debian/patches/36-squid-3.4-13225.patch
+    - Added upstream patch fixing Improper Protection of Alternate Path
+      (Ref: SQUID-2015:2, CVE-2015-5400) (Closes: #793128)
+
+ -- Luigi Gangitano <luigi at debian.org>  Wed, 22 Jul 2015 18:36:08 +0200
+
 squid3 (3.4.8-6) unstable; urgency=medium
 
   [ Luigi Gangitano <luigi at debian.org> ]
diff -Nru squid3-3.4.8/debian/patches/36-squid-3.4-13225.patch squid3-3.4.8/debian/patches/36-squid-3.4-13225.patch
--- squid3-3.4.8/debian/patches/36-squid-3.4-13225.patch	1970-01-01 01:00:00.000000000 +0100
+++ squid3-3.4.8/debian/patches/36-squid-3.4-13225.patch	2015-07-22 19:35:30.000000000 +0200
@@ -0,0 +1,237 @@
+--- a/src/tunnel.cc
++++ b/src/tunnel.cc
+@@ -122,6 +122,10 @@
+                  (request->flags.interceptTproxy || request->flags.intercepted));
+     }
+ 
++    /// Sends "502 Bad Gateway" error response to the client,
++    /// if it is waiting for Squid CONNECT response, closing connections.
++    void informUserOfPeerError(const char *errMsg);
++
+     class Connection
+     {
+ 
+@@ -139,13 +143,14 @@
+ 
+         void error(int const xerrno);
+         int debugLevelForError(int const xerrno) const;
+-        /// handles a non-I/O error associated with this Connection
+-        void logicError(const char *errMsg);
+         void closeIfOpen();
+         void dataSent (size_t amount);
++        /// writes 'b' buffer, setting the 'writer' member to 'callback'.
++        void write(const char *b, int size, AsyncCall::Pointer &callback, FREE * free_func);
+         int len;
+         char *buf;
+         int64_t *size_ptr;		/* pointer to size in an ConnStateData for logging */
++        AsyncCall::Pointer writer; ///< pending Comm::Write callback
+ 
+         Comm::ConnectionPointer conn;    ///< The currently connected connection.
+ 
+@@ -195,13 +200,14 @@
+     TunnelStateData *tunnelState = (TunnelStateData *)params.data;
+     debugs(26, 3, HERE << tunnelState->server.conn);
+     tunnelState->server.conn = NULL;
++    tunnelState->server.writer = NULL;
+ 
+     if (tunnelState->noConnections()) {
+         delete tunnelState;
+         return;
+     }
+ 
+-    if (!tunnelState->server.len) {
++    if (!tunnelState->client.writer) {
+         tunnelState->client.conn->close();
+         return;
+     }
+@@ -213,13 +219,14 @@
+     TunnelStateData *tunnelState = (TunnelStateData *)params.data;
+     debugs(26, 3, HERE << tunnelState->client.conn);
+     tunnelState->client.conn = NULL;
++    tunnelState->client.writer = NULL;
+ 
+     if (tunnelState->noConnections()) {
+         delete tunnelState;
+         return;
+     }
+ 
+-    if (!tunnelState->client.len) {
++    if (!tunnelState->server.writer) {
+         tunnelState->server.conn->close();
+         return;
+     }
+@@ -343,6 +350,23 @@
+         handleConnectResponse(len);
+ }
+ 
++void
++TunnelStateData::informUserOfPeerError(const char *errMsg)
++{
++    server.len = 0;
++    if (!clientExpectsConnectResponse()) {
++        // closing the connection is the best we can do here
++        debugs(50, 3, server.conn << " closing on error: " << errMsg);
++        server.conn->close();
++        return;
++    }
++    ErrorState *err  = new ErrorState(ERR_CONNECT_FAIL, Http::scBadGateway, request.getRaw());
++    err->callback = tunnelErrorComplete;
++    err->callback_data = this;
++    *status_ptr = Http::scBadGateway;
++    errorSend(http->getConn()->clientConnection, err);
++}
++
+ /* Read from client side and queue it for writing to the server */
+ void
+ TunnelStateData::ReadConnectResponseDone(const Comm::ConnectionPointer &, char *buf, size_t len, comm_err_t errcode, int xerrno, void *data)
+@@ -374,7 +398,7 @@
+     const bool parsed = rep.parse(connectRespBuf, eof, &parseErr);
+     if (!parsed) {
+         if (parseErr > 0) { // unrecoverable parsing error
+-            server.logicError("malformed CONNECT response from peer");
++            informUserOfPeerError("malformed CONNECT response from peer");
+             return;
+         }
+ 
+@@ -383,7 +407,7 @@
+         assert(!parseErr);
+ 
+         if (!connectRespBuf->hasSpace()) {
+-            server.logicError("huge CONNECT response from peer");
++            informUserOfPeerError("huge CONNECT response from peer");
+             return;
+         }
+ 
+@@ -397,7 +421,8 @@
+ 
+     // bail if we did not get an HTTP 200 (Connection Established) response
+     if (rep.sline.status() != Http::scOkay) {
+-        server.logicError("unsupported CONNECT response status code");
++        // if we ever decide to reuse the peer connection, we must extract the error response first
++        informUserOfPeerError("unsupported CONNECT response status code");
+         return;
+     }
+ 
+@@ -416,13 +441,6 @@
+ }
+ 
+ void
+-TunnelStateData::Connection::logicError(const char *errMsg)
+-{
+-    debugs(50, 3, conn << " closing on error: " << errMsg);
+-    conn->close();
+-}
+-
+-void
+ TunnelStateData::Connection::error(int const xerrno)
+ {
+     /* XXX fixme xstrerror and xerrno... */
+@@ -517,7 +535,7 @@
+     debugs(26, 3, HERE << "Schedule Write");
+     AsyncCall::Pointer call = commCbCall(5,5, "TunnelBlindCopyWriteHandler",
+                                          CommIoCbPtrFun(completion, this));
+-    Comm::Write(to.conn, from.buf, len, call, NULL);
++    to.write(from.buf, len, call, NULL);
+ }
+ 
+ /* Writes data from the client buffer to the server side */
+@@ -526,6 +544,7 @@
+ {
+     TunnelStateData *tunnelState = (TunnelStateData *)data;
+     assert (cbdataReferenceValid (tunnelState));
++    tunnelState->server.writer = NULL;
+ 
+     tunnelState->writeServerDone(buf, len, flag, xerrno);
+ }
+@@ -575,6 +594,7 @@
+ {
+     TunnelStateData *tunnelState = (TunnelStateData *)data;
+     assert (cbdataReferenceValid (tunnelState));
++    tunnelState->client.writer = NULL;
+ 
+     tunnelState->writeClientDone(buf, len, flag, xerrno);
+ }
+@@ -592,7 +612,14 @@
+ }
+ 
+ void
+-TunnelStateData::writeClientDone(char *buf, size_t len, comm_err_t flag, int xerrno)
++TunnelStateData::Connection::write(const char *b, int size, AsyncCall::Pointer &callback, FREE * free_func)
++{
++    writer = callback;
++    Comm::Write(conn, b, size, callback, free_func);
++}
++
++void
++TunnelStateData::writeClientDone(char *, size_t len, comm_err_t flag, int xerrno)
+ {
+     debugs(26, 3, HERE << client.conn << ", " << len << " bytes written, flag=" << flag);
+ 
+@@ -712,6 +739,7 @@
+ {
+     TunnelStateData *tunnelState = (TunnelStateData *)data;
+     debugs(26, 3, HERE << conn << ", flag=" << flag);
++    tunnelState->client.writer = NULL;
+ 
+     if (flag != COMM_OK) {
+         *tunnelState->status_ptr = Http::scInternalServerError;
+@@ -728,6 +756,7 @@
+ {
+     TunnelStateData *tunnelState = (TunnelStateData *)data;
+     debugs(26, 3, conn << ", flag=" << flag);
++    tunnelState->server.writer = NULL;
+     assert(tunnelState->waitingForConnectRequest());
+ 
+     if (flag != COMM_OK) {
+@@ -768,7 +797,7 @@
+     else {
+         AsyncCall::Pointer call = commCbCall(5,5, "tunnelConnectedWriteDone",
+                                              CommIoCbPtrFun(tunnelConnectedWriteDone, tunnelState));
+-        Comm::Write(tunnelState->client.conn, conn_established, strlen(conn_established), call, NULL);
++        tunnelState->client.write(conn_established, strlen(conn_established), call, NULL);
+     }
+ }
+ 
+@@ -955,29 +984,20 @@
+     debugs(11, 2, "Tunnel Server REQUEST: " << tunnelState->server.conn << ":\n----------\n" <<
+            Raw("tunnelRelayConnectRequest", mb.content(), mb.contentSize()) << "\n----------");
+ 
+-    if (tunnelState->clientExpectsConnectResponse()) {
+-        // hack: blindly tunnel peer response (to our CONNECT request) to the client as ours.
+-        AsyncCall::Pointer writeCall = commCbCall(5,5, "tunnelConnectedWriteDone",
+-                                       CommIoCbPtrFun(tunnelConnectedWriteDone, tunnelState));
+-        Comm::Write(srv, &mb, writeCall);
+-    } else {
+-        // we have to eat the connect response from the peer (so that the client
+-        // does not see it) and only then start shoveling data to the client
+-        AsyncCall::Pointer writeCall = commCbCall(5,5, "tunnelConnectReqWriteDone",
+-                                       CommIoCbPtrFun(tunnelConnectReqWriteDone,
+-                                                      tunnelState));
+-        Comm::Write(srv, &mb, writeCall);
+-        tunnelState->connectReqWriting = true;
+-
+-        tunnelState->connectRespBuf = new MemBuf;
+-        // SQUID_TCP_SO_RCVBUF: we should not accumulate more than regular I/O buffer
+-        // can hold since any CONNECT response leftovers have to fit into server.buf.
+-        // 2*SQUID_TCP_SO_RCVBUF: HttpMsg::parse() zero-terminates, which uses space.
+-        tunnelState->connectRespBuf->init(SQUID_TCP_SO_RCVBUF, 2*SQUID_TCP_SO_RCVBUF);
+-        tunnelState->readConnectResponse();
++    AsyncCall::Pointer writeCall = commCbCall(5,5, "tunnelConnectReqWriteDone",
++                                   CommIoCbPtrFun(tunnelConnectReqWriteDone, tunnelState));
+ 
+-        assert(tunnelState->waitingForConnectExchange());
+-    }
++    tunnelState->server.write(mb.buf, mb.size, writeCall, mb.freeFunc());
++    tunnelState->connectReqWriting = true;
++
++    tunnelState->connectRespBuf = new MemBuf;
++    // SQUID_TCP_SO_RCVBUF: we should not accumulate more than regular I/O buffer
++    // can hold since any CONNECT response leftovers have to fit into server.buf.
++    // 2*SQUID_TCP_SO_RCVBUF: HttpMsg::parse() zero-terminates, which uses space.
++    tunnelState->connectRespBuf->init(SQUID_TCP_SO_RCVBUF, 2*SQUID_TCP_SO_RCVBUF);
++    tunnelState->readConnectResponse();
++
++    assert(tunnelState->waitingForConnectExchange());
+ 
+     AsyncCall::Pointer timeoutCall = commCbCall(5, 4, "tunnelTimeout",
+                                      CommTimeoutCbPtrFun(tunnelTimeout, tunnelState));
diff -Nru squid3-3.4.8/debian/patches/series squid3-3.4.8/debian/patches/series
--- squid3-3.4.8/debian/patches/series	2015-01-28 12:59:07.000000000 +0100
+++ squid3-3.4.8/debian/patches/series	2015-07-22 19:35:30.000000000 +0200
@@ -9,3 +9,4 @@
 33-squid-3.4-13211.patch
 34-squid-3.4-13213.patch
 35-squid-3.4-13203.patch 
+36-squid-3.4-13225.patch

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.alioth.debian.org/pipermail/pkg-squid-devel/attachments/20150722/1f2990c5/attachment-0001.html>


More information about the pkg-squid-devel mailing list