Author: tmancill
Date: 2011-11-08 18:54:07 +0000 (Tue, 08 Nov 2011)
New Revision: 15367

Added:
   trunk/tomcat6/debian/patches/0014-CVE-2011-1184.patch
   trunk/tomcat6/debian/patches/0015-CVE-2011-2526.patch
Modified:
   trunk/tomcat6/debian/changelog
   trunk/tomcat6/debian/patches/series
Log:
apply patch for #648038; prepare for upload to unstable

Modified: trunk/tomcat6/debian/changelog
===================================================================
--- trunk/tomcat6/debian/changelog      2011-11-08 14:21:37 UTC (rev 15366)
+++ trunk/tomcat6/debian/changelog      2011-11-08 18:54:07 UTC (rev 15367)
@@ -1,15 +1,17 @@
-tomcat6 (6.0.32-7) UNRELEASED; urgency=low
+tomcat6 (6.0.32-7) unstable; urgency=medium
 
   [ tony mancill ]
   * Team upload.
   * Add "unset LC_ALL" to /etc/defaults/tomcat6 to prevent user 
     environment settings from leaking into the servlet container.
     - Thank you to Nicolas Pichon.  (Closes: #645221)
+  * Apply patch for CVE-2011-1184 and CVE-2011-2526.
+    - Thank you to Marc Deslauriers.  (Closes: #648038)
 
   [ Niels Thykier ]
   * Added build-arch and build-indep targets in d/rules.
 
- -- tony mancill <tmanc...@debian.org>  Wed, 26 Oct 2011 21:13:17 -0700
+ -- tony mancill <tmanc...@debian.org>  Tue, 08 Nov 2011 10:42:32 -0800
 
 tomcat6 (6.0.32-6) unstable; urgency=medium
 

Added: trunk/tomcat6/debian/patches/0014-CVE-2011-1184.patch
===================================================================
--- trunk/tomcat6/debian/patches/0014-CVE-2011-1184.patch                       
        (rev 0)
+++ trunk/tomcat6/debian/patches/0014-CVE-2011-1184.patch       2011-11-08 
18:54:07 UTC (rev 15367)
@@ -0,0 +1,798 @@
+Description: fix HTTP DIGEST authentication weaknesses
+Origin: upstream, http://svn.apache.org/viewvc?view=revision&revision=1158180
+
+Index: 
tomcat6-6.0.32/java/org/apache/catalina/authenticator/DigestAuthenticator.java
+===================================================================
+--- 
tomcat6-6.0.32.orig/java/org/apache/catalina/authenticator/DigestAuthenticator.java
        2010-04-29 11:00:41.000000000 -0400
++++ 
tomcat6-6.0.32/java/org/apache/catalina/authenticator/DigestAuthenticator.java  
   2011-10-13 16:38:43.989355250 -0400
+@@ -23,11 +23,14 @@
+ import java.security.MessageDigest;
+ import java.security.NoSuchAlgorithmException;
+ import java.security.Principal;
++import java.util.LinkedHashMap;
++import java.util.Map;
+ import java.util.StringTokenizer;
+ 
+ import javax.servlet.http.HttpServletResponse;
+ 
+ 
++import org.apache.catalina.LifecycleException;
+ import org.apache.catalina.Realm;
+ import org.apache.catalina.connector.Request;
+ import org.apache.catalina.connector.Response;
+@@ -47,8 +50,8 @@
+  * @version $Id: DigestAuthenticator.java 939336 2010-04-29 15:00:41Z 
kkolinko $
+  */
+ 
+-public class DigestAuthenticator
+-    extends AuthenticatorBase {
++public class DigestAuthenticator extends AuthenticatorBase {
++
+     private static Log log = LogFactory.getLog(DigestAuthenticator.class);
+ 
+ 
+@@ -67,6 +70,11 @@
+         "org.apache.catalina.authenticator.DigestAuthenticator/1.0";
+ 
+ 
++    /**
++     * Tomcat's DIGEST implementation only supports auth quality of 
protection.
++     */
++    protected static final String QOP = "auth";
++
+     // ----------------------------------------------------------- 
Constructors
+ 
+ 
+@@ -92,17 +100,49 @@
+ 
+ 
+     /**
++     * List of client nonce values currently being tracked
++     */
++    protected Map<String,NonceInfo> cnonces;
++
++
++    /**
++     * Maximum number of client nonces to keep in the cache. If not specified,
++     * the default value of 1000 is used.
++     */
++    protected int cnonceCacheSize = 1000;
++
++
++    /**
+      * Private key.
+      */
+-    protected String key = "Catalina";
++    protected String key = null;
+ 
+ 
+-    // ------------------------------------------------------------- 
Properties
++    /**
++     * How long server nonces are valid for in milliseconds. Defaults to 5
++     * minutes.
++     */
++    protected long nonceValidity = 5 * 60 * 1000;
++
++
++    /**
++     * Opaque string.
++     */
++    protected String opaque;
+ 
+ 
+     /**
++     * Should the URI be validated as required by RFC2617? Can be disabled in
++     * reverse proxies where the proxy has modified the URI.
++     */
++    protected boolean validateUri = true;
++
++    // ------------------------------------------------------------- 
Properties
++
++    /**
+      * Return descriptive information about this Valve implementation.
+      */
++    @Override
+     public String getInfo() {
+ 
+         return (info);
+@@ -110,9 +150,58 @@
+     }
+ 
+ 
+-    // --------------------------------------------------------- Public 
Methods
++    public int getCnonceCacheSize() {
++        return cnonceCacheSize;
++    }
++
++
++    public void setCnonceCacheSize(int cnonceCacheSize) {
++        this.cnonceCacheSize = cnonceCacheSize;
++    }
++
++
++    public String getKey() {
++        return key;
++    }
++
++
++    public void setKey(String key) {
++        this.key = key;
++    }
++
++
++    public long getNonceValidity() {
++        return nonceValidity;
++    }
++
++
++    public void setNonceValidity(long nonceValidity) {
++        this.nonceValidity = nonceValidity;
++    }
++
++
++    public String getOpaque() {
++        return opaque;
++    }
++
++
++    public void setOpaque(String opaque) {
++        this.opaque = opaque;
++    }
++
++
++    public boolean isValidateUri() {
++        return validateUri;
++    }
++
++
++    public void setValidateUri(boolean validateUri) {
++        this.validateUri = validateUri;
++    }
+ 
+ 
++    // --------------------------------------------------------- Public 
Methods
++
+     /**
+      * Authenticate the user making this request, based on the specified
+      * login configuration.  Return <code>true</code> if any specified
+@@ -126,6 +215,7 @@
+      *
+      * @exception IOException if an input/output error occurs
+      */
++    @Override
+     public boolean authenticate(Request request,
+                                 Response response,
+                                 LoginConfig config)
+@@ -172,8 +262,13 @@
+ 
+         // Validate any credentials already included with this request
+         String authorization = request.getHeader("authorization");
++        DigestInfo digestInfo = new DigestInfo(getOpaque(), 
getNonceValidity(),
++                getKey(), cnonces, isValidateUri());
+         if (authorization != null) {
+-            principal = findPrincipal(request, authorization, 
context.getRealm());
++            if (digestInfo.validate(request, authorization, config)) {
++                principal = digestInfo.authenticate(context.getRealm());
++            }
++            
+             if (principal != null) {
+                 String username = parseUsername(authorization);
+                 register(request, response, principal,
+@@ -185,11 +280,12 @@
+ 
+         // Send an "unauthorized" response and an appropriate challenge
+ 
+-        // Next, generate a nOnce token (that is a token which is supposed
++        // Next, generate a nonce token (that is a token which is supposed
+         // to be unique).
+-        String nOnce = generateNOnce(request);
++        String nonce = generateNonce(request);
+ 
+-        setAuthenticateHeader(request, response, config, nOnce);
++        setAuthenticateHeader(request, response, config, nonce,
++                digestInfo.isNonceStale());
+         response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
+         //      hres.flushBuffer();
+         return (false);
+@@ -201,92 +297,6 @@
+ 
+ 
+     /**
+-     * Parse the specified authorization credentials, and return the
+-     * associated Principal that these credentials authenticate (if any)
+-     * from the specified Realm.  If there is no such Principal, return
+-     * <code>null</code>.
+-     *
+-     * @param request HTTP servlet request
+-     * @param authorization Authorization credentials from this request
+-     * @param realm Realm used to authenticate Principals
+-     */
+-    protected static Principal findPrincipal(Request request,
+-                                             String authorization,
+-                                             Realm realm) {
+-
+-        //System.out.println("Authorization token : " + authorization);
+-        // Validate the authorization credentials format
+-        if (authorization == null)
+-            return (null);
+-        if (!authorization.startsWith("Digest "))
+-            return (null);
+-        authorization = authorization.substring(7).trim();
+-
+-        // Bugzilla 37132: 
http://issues.apache.org/bugzilla/show_bug.cgi?id=37132
+-        String[] tokens = authorization.split(",(?=(?:[^\"]*\"[^\"]*\")+$)");
+-
+-        String userName = null;
+-        String realmName = null;
+-        String nOnce = null;
+-        String nc = null;
+-        String cnonce = null;
+-        String qop = null;
+-        String uri = null;
+-        String response = null;
+-        String method = request.getMethod();
+-
+-        for (int i = 0; i < tokens.length; i++) {
+-            String currentToken = tokens[i];
+-            if (currentToken.length() == 0)
+-                continue;
+-
+-            int equalSign = currentToken.indexOf('=');
+-            if (equalSign < 0)
+-                return null;
+-            String currentTokenName =
+-                currentToken.substring(0, equalSign).trim();
+-            String currentTokenValue =
+-                currentToken.substring(equalSign + 1).trim();
+-            if ("username".equals(currentTokenName))
+-                userName = removeQuotes(currentTokenValue);
+-            if ("realm".equals(currentTokenName))
+-                realmName = removeQuotes(currentTokenValue, true);
+-            if ("nonce".equals(currentTokenName))
+-                nOnce = removeQuotes(currentTokenValue);
+-            if ("nc".equals(currentTokenName))
+-                nc = removeQuotes(currentTokenValue);
+-            if ("cnonce".equals(currentTokenName))
+-                cnonce = removeQuotes(currentTokenValue);
+-            if ("qop".equals(currentTokenName))
+-                qop = removeQuotes(currentTokenValue);
+-            if ("uri".equals(currentTokenName))
+-                uri = removeQuotes(currentTokenValue);
+-            if ("response".equals(currentTokenName))
+-                response = removeQuotes(currentTokenValue);
+-        }
+-
+-        if ( (userName == null) || (realmName == null) || (nOnce == null)
+-             || (uri == null) || (response == null) )
+-            return null;
+-
+-        // Second MD5 digest used to calculate the digest :
+-        // MD5(Method + ":" + uri)
+-        String a2 = method + ":" + uri;
+-        //System.out.println("A2:" + a2);
+-
+-        byte[] buffer = null;
+-        synchronized (md5Helper) {
+-            buffer = md5Helper.digest(a2.getBytes());
+-        }
+-        String md5a2 = md5Encoder.encode(buffer);
+-
+-        return (realm.authenticate(userName, response, nOnce, nc, cnonce, qop,
+-                                   realmName, md5a2));
+-
+-    }
+-
+-
+-    /**
+      * Parse the username from the specified authorization string.  If none
+      * can be identified, return <code>null</code>
+      *
+@@ -294,7 +304,6 @@
+      */
+     protected String parseUsername(String authorization) {
+ 
+-        //System.out.println("Authorization token : " + authorization);
+         // Validate the authorization credentials format
+         if (authorization == null)
+             return (null);
+@@ -354,20 +363,20 @@
+      *
+      * @param request HTTP Servlet request
+      */
+-    protected String generateNOnce(Request request) {
++    protected String generateNonce(Request request) {
+ 
+         long currentTime = System.currentTimeMillis();
+ 
+-        String nOnceValue = request.getRemoteAddr() + ":" +
+-            currentTime + ":" + key;
++        
++        String ipTimeKey =
++            request.getRemoteAddr() + ":" + currentTime + ":" + getKey();
+ 
+-        byte[] buffer = null;
++        byte[] buffer;
+         synchronized (md5Helper) {
+-            buffer = md5Helper.digest(nOnceValue.getBytes());
++            buffer = md5Helper.digest(ipTimeKey.getBytes());
+         }
+-        nOnceValue = md5Encoder.encode(buffer);
+ 
+-        return nOnceValue;
++        return currentTime + ":" + md5Encoder.encode(buffer);
+     }
+ 
+ 
+@@ -379,7 +388,7 @@
+      *      WWW-Authenticate    = "WWW-Authenticate" ":" "Digest"
+      *                            digest-challenge
+      *
+-     *      digest-challenge    = 1#( realm | [ domain ] | nOnce |
++     *      digest-challenge    = 1#( realm | [ domain ] | nonce |
+      *                  [ digest-opaque ] |[ stale ] | [ algorithm ] )
+      *
+      *      realm               = "realm" "=" realm-value
+@@ -396,29 +405,303 @@
+      * @param response HTTP Servlet response
+      * @param config    Login configuration describing how authentication
+      *              should be performed
+-     * @param nOnce nonce token
++     * @param nonce nonce token
+      */
+     protected void setAuthenticateHeader(Request request,
+                                          Response response,
+                                          LoginConfig config,
+-                                         String nOnce) {
++                                         String nonce,
++                                         boolean isNonceStale) {
+ 
+         // Get the realm name
+         String realmName = config.getRealmName();
+         if (realmName == null)
+             realmName = REALM_NAME;
+ 
+-        byte[] buffer = null;
+-        synchronized (md5Helper) {
+-            buffer = md5Helper.digest(nOnce.getBytes());
++        String authenticateHeader;
++        if (isNonceStale) {
++            authenticateHeader = "Digest realm=\"" + realmName + "\", " +
++            "qop=\"" + QOP + "\", nonce=\"" + nonce + "\", " + "opaque=\"" +
++            getOpaque() + "\", stale=true";
++        } else {
++            authenticateHeader = "Digest realm=\"" + realmName + "\", " +
++            "qop=\"" + QOP + "\", nonce=\"" + nonce + "\", " + "opaque=\"" +
++            getOpaque() + "\"";
+         }
+ 
+-        String authenticateHeader = "Digest realm=\"" + realmName + "\", "
+-            +  "qop=\"auth\", nonce=\"" + nOnce + "\", " + "opaque=\""
+-            + md5Encoder.encode(buffer) + "\"";
+         response.setHeader("WWW-Authenticate", authenticateHeader);
+ 
+     }
+ 
+ 
++    // ------------------------------------------------------- Lifecycle 
Methods
++    
++    @Override
++    public void start() throws LifecycleException {
++        super.start();
++        
++        // Generate a random secret key
++        if (getKey() == null) {
++            setKey(generateSessionId());
++        }
++        
++        // Generate the opaque string the same way
++        if (getOpaque() == null) {
++            setOpaque(generateSessionId());
++        }
++        
++        cnonces = new LinkedHashMap<String, DigestAuthenticator.NonceInfo>() {
++
++            private static final long serialVersionUID = 1L;
++            private static final long LOG_SUPPRESS_TIME = 5 * 60 * 1000;
++
++            private long lastLog = 0;
++
++            @Override
++            protected boolean removeEldestEntry(
++                    Map.Entry<String,NonceInfo> eldest) {
++                // This is called from a sync so keep it simple
++                long currentTime = System.currentTimeMillis();
++                if (size() > getCnonceCacheSize()) {
++                    if (lastLog < currentTime &&
++                            currentTime - eldest.getValue().getTimestamp() <
++                            getNonceValidity()) {
++                        // Replay attack is possible
++                        log.warn(sm.getString(
++                                "digestAuthenticator.cacheRemove"));
++                        lastLog = currentTime + LOG_SUPPRESS_TIME;
++                    }
++                    return true;
++                }
++                return false;
++            }
++        };
++    }
++ 
++    private static class DigestInfo {
++
++        private String opaque;
++        private long nonceValidity;
++        private String key;
++        private Map<String,NonceInfo> cnonces;
++        private boolean validateUri = true;
++
++        private String userName = null;
++        private String method = null;
++        private String uri = null;
++        private String response = null;
++        private String nonce = null;
++        private String nc = null;
++        private String cnonce = null;
++        private String realmName = null;
++        private String qop = null;
++
++        private boolean nonceStale = false;
++
++
++        public DigestInfo(String opaque, long nonceValidity, String key,
++                Map<String,NonceInfo> cnonces, boolean validateUri) {
++            this.opaque = opaque;
++            this.nonceValidity = nonceValidity;
++            this.key = key;
++            this.cnonces = cnonces;
++            this.validateUri = validateUri;
++        }
++
++        public boolean validate(Request request, String authorization,
++                LoginConfig config) {
++            // Validate the authorization credentials format
++            if (authorization == null) {
++                return false;
++            }
++            if (!authorization.startsWith("Digest ")) {
++                return false;
++            }
++            authorization = authorization.substring(7).trim();
++
++            // Bugzilla 37132: 
http://issues.apache.org/bugzilla/show_bug.cgi?id=37132
++            String[] tokens = 
authorization.split(",(?=(?:[^\"]*\"[^\"]*\")+$)");
++
++            method = request.getMethod();
++            String opaque = null;
++
++            for (int i = 0; i < tokens.length; i++) {
++                String currentToken = tokens[i];
++                if (currentToken.length() == 0)
++                    continue;
++
++                int equalSign = currentToken.indexOf('=');
++                if (equalSign < 0) {
++                    return false;
++                }
++                String currentTokenName =
++                    currentToken.substring(0, equalSign).trim();
++                String currentTokenValue =
++                    currentToken.substring(equalSign + 1).trim();
++                if ("username".equals(currentTokenName))
++                    userName = removeQuotes(currentTokenValue);
++                if ("realm".equals(currentTokenName))
++                    realmName = removeQuotes(currentTokenValue, true);
++                if ("nonce".equals(currentTokenName))
++                    nonce = removeQuotes(currentTokenValue);
++                if ("nc".equals(currentTokenName))
++                    nc = removeQuotes(currentTokenValue);
++                if ("cnonce".equals(currentTokenName))
++                    cnonce = removeQuotes(currentTokenValue);
++                if ("qop".equals(currentTokenName))
++                    qop = removeQuotes(currentTokenValue);
++                if ("uri".equals(currentTokenName))
++                    uri = removeQuotes(currentTokenValue);
++                if ("response".equals(currentTokenName))
++                    response = removeQuotes(currentTokenValue);
++                if ("opaque".equals(currentTokenName))
++                    opaque = removeQuotes(currentTokenValue);
++            }
++
++            if ( (userName == null) || (realmName == null) || (nonce == null)
++                 || (uri == null) || (response == null) ) {
++                return false;
++            }
++
++            // Validate the URI - should match the request line sent by client
++            if (validateUri) {
++                String uriQuery;
++                String query = request.getQueryString();
++                if (query == null) {
++                    uriQuery = request.getRequestURI();
++                } else {
++                    uriQuery = request.getRequestURI() + "?" + query;
++                }
++                if (!uri.equals(uriQuery)) {
++                    return false;
++                }
++            }
++
++            // Validate the Realm name
++            String lcRealm = config.getRealmName();
++            if (lcRealm == null) {
++                lcRealm = REALM_NAME;
++            }
++            if (!lcRealm.equals(realmName)) {
++                return false;
++            }
++            
++            // Validate the opaque string
++            if (!this.opaque.equals(opaque)) {
++                return false;
++            }
++
++            // Validate nonce
++            int i = nonce.indexOf(":");
++            if (i < 0 || (i + 1) == nonce.length()) {
++                return false;
++            }
++            long nonceTime;
++            try {
++                nonceTime = Long.parseLong(nonce.substring(0, i));
++            } catch (NumberFormatException nfe) {
++                return false;
++            }
++            String md5clientIpTimeKey = nonce.substring(i + 1);
++            long currentTime = System.currentTimeMillis();
++            if ((currentTime - nonceTime) > nonceValidity) {
++                nonceStale = true;
++                return false;
++            }
++            String serverIpTimeKey =
++                request.getRemoteAddr() + ":" + nonceTime + ":" + key;
++            byte[] buffer = null;
++            synchronized (md5Helper) {
++                buffer = md5Helper.digest(serverIpTimeKey.getBytes());
++            }
++            String md5ServerIpTimeKey = md5Encoder.encode(buffer);
++            if (!md5ServerIpTimeKey.equals(md5clientIpTimeKey)) {
++                return false;
++            }
++
++            // Validate qop
++            if (qop != null && !QOP.equals(qop)) {
++                return false;
++            }
++
++            // Validate cnonce and nc
++            // Check if presence of nc and nonce is consistent with presence 
of qop
++            if (qop == null) {
++                if (cnonce != null || nc != null) {
++                    return false;
++                }
++            } else {
++                if (cnonce == null || nc == null) {
++                    return false;
++                }
++                if (nc.length() != 8) {
++                    return false;
++                }
++                long count;
++                try {
++                    count = Long.parseLong(nc, 16);
++                } catch (NumberFormatException nfe) {
++                    return false;
++                }
++                NonceInfo info;
++                synchronized (cnonces) {
++                    info = cnonces.get(cnonce);
++                }
++                if (info == null) {
++                    info = new NonceInfo();
++                } else {
++                    if (count <= info.getCount()) {
++                        return false;
++                    }
++                }
++                info.setCount(count);
++                info.setTimestamp(currentTime);
++                synchronized (cnonces) {
++                    cnonces.put(cnonce, info);
++                }
++            }
++            return true;
++        }
++
++        public boolean isNonceStale() {
++            return nonceStale;
++        }
++
++        public Principal authenticate(Realm realm) {
++            // Second MD5 digest used to calculate the digest :
++            // MD5(Method + ":" + uri)
++            String a2 = method + ":" + uri;
++
++            byte[] buffer;
++            synchronized (md5Helper) {
++                buffer = md5Helper.digest(a2.getBytes());
++            }
++            String md5a2 = md5Encoder.encode(buffer);
++
++            return realm.authenticate(userName, response, nonce, nc, cnonce,
++                    qop, realmName, md5a2);
++        }
++
++    }
++
++    private static class NonceInfo {
++        private volatile long count;
++        private volatile long timestamp;
++        
++        public void setCount(long l) {
++            count = l;
++        }
++        
++        public long getCount() {
++            return count;
++        }
++        
++        public void setTimestamp(long l) {
++            timestamp = l;
++        }
++        
++        public long getTimestamp() {
++            return timestamp;
++        }
++    }
+ }
+Index: 
tomcat6-6.0.32/java/org/apache/catalina/authenticator/LocalStrings.properties
+===================================================================
+--- 
tomcat6-6.0.32.orig/java/org/apache/catalina/authenticator/LocalStrings.properties
 2009-12-21 07:56:09.000000000 -0500
++++ 
tomcat6-6.0.32/java/org/apache/catalina/authenticator/LocalStrings.properties   
   2011-10-13 16:38:43.989355250 -0400
+@@ -28,5 +28,7 @@
+ authenticator.unauthorized=Cannot authenticate with the provided credentials
+ authenticator.userDataConstraint=This request violates a User Data constraint 
for this application
+ 
++digestAuthenticator.cacheRemove=A valid entry has been removed from client 
nonce cache to make room for new entries. A replay attack is now possible. To 
prevent the possibility of replay attacks, reduce nonceValidity or increase 
cnonceCacheSize. Further warnings of this type will be suppressed for 5 minutes.
++ 
+ formAuthenticator.forwardErrorFail=Unexpected error forwarding to error page
+ formAuthenticator.forwardLoginFail=Unexpected error forwarding to login page
+Index: 
tomcat6-6.0.32/java/org/apache/catalina/authenticator/mbeans-descriptors.xml
+===================================================================
+--- 
tomcat6-6.0.32.orig/java/org/apache/catalina/authenticator/mbeans-descriptors.xml
  2007-08-04 19:30:01.000000000 -0400
++++ 
tomcat6-6.0.32/java/org/apache/catalina/authenticator/mbeans-descriptors.xml    
   2011-10-13 16:38:43.989355250 -0400
+@@ -60,10 +60,30 @@
+                description="Fully qualified class name of the managed object"
+                type="java.lang.String"
+                writeable="false"/>
+-      
++
++    <attribute name="cnonceCacheSize"
++               description="The size of the cnonce cache used to prevent 
replay attacks"
++               type="int"/>
++
+     <attribute   name="entropy"
+                description="A String initialization parameter used to 
increase the  entropy of the initialization of our random number generator"
+                type="java.lang.String"/>
++
++    <attribute name="key"
++               description="The secret key used by digest authentication"
++               type="java.lang.String"/>
++      
++    <attribute name="nonceValidity"
++               description="The time, in milliseconds, for which a server 
issued nonce will be valid"
++               type="long"/>
++
++    <attribute name="opaque"
++               description="The opaque server string used by digest 
authentication"
++               type="java.lang.String"/>
++
++    <attribute name="validateUri"
++               description="Should the uri be validated as required by 
RFC2617?"
++               type="boolean"/>
+   </mbean>
+   
+   <mbean name="FormAuthenticator"
+Index: tomcat6-6.0.32/java/org/apache/catalina/realm/RealmBase.java
+===================================================================
+--- tomcat6-6.0.32.orig/java/org/apache/catalina/realm/RealmBase.java  
2010-04-29 20:08:58.000000000 -0400
++++ tomcat6-6.0.32/java/org/apache/catalina/realm/RealmBase.java       
2011-10-13 16:38:43.989355250 -0400
+@@ -353,22 +353,27 @@
+      *
+      * @param username Username of the Principal to look up
+      * @param clientDigest Digest which has been submitted by the client
+-     * @param nOnce Unique (or supposedly unique) token which has been used
++     * @param nonce Unique (or supposedly unique) token which has been used
+      * for this request
+      * @param realm Realm name
+      * @param md5a2 Second MD5 digest used to calculate the digest :
+      * MD5(Method + ":" + uri)
+      */
+     public Principal authenticate(String username, String clientDigest,
+-                                  String nOnce, String nc, String cnonce,
++                                  String nonce, String nc, String cnonce,
+                                   String qop, String realm,
+                                   String md5a2) {
+ 
+         String md5a1 = getDigest(username, realm);
+         if (md5a1 == null)
+             return null;
+-        String serverDigestValue = md5a1 + ":" + nOnce + ":" + nc + ":"
+-            + cnonce + ":" + qop + ":" + md5a2;
++        String serverDigestValue;
++        if (qop == null) {
++            serverDigestValue = md5a1 + ":" + nonce + ":" + md5a2;
++        } else {
++            serverDigestValue = md5a1 + ":" + nonce + ":" + nc + ":" +
++                    cnonce + ":" + qop + ":" + md5a2;
++        }
+ 
+         byte[] valueBytes = null;
+         if(getDigestEncoding() == null) {
+@@ -390,7 +395,7 @@
+ 
+         if (log.isDebugEnabled()) {
+             log.debug("Digest : " + clientDigest + " Username:" + username 
+-                    + " ClientSigest:" + clientDigest + " nOnce:" + nOnce 
++                    + " ClientSigest:" + clientDigest + " nonce:" + nonce 
+                     + " nc:" + nc + " cnonce:" + cnonce + " qop:" + qop 
+                     + " realm:" + realm + "md5a2:" + md5a2 
+                     + " Server digest:" + serverDigest);
+Index: tomcat6-6.0.32/webapps/docs/config/valve.xml
+===================================================================
+--- tomcat6-6.0.32.orig/webapps/docs/config/valve.xml  2010-11-02 
15:26:07.000000000 -0400
++++ tomcat6-6.0.32/webapps/docs/config/valve.xml       2011-10-13 
16:38:43.989355250 -0400
+@@ -460,6 +460,12 @@
+         used.</p>
+       </attribute>
+ 
++      <attribute name="cnonceCacheSize" required="false">
++        <p>To protect against replay attacks, the DIGEST authenticator tracks
++        client nonce and nonce count values. This attribute controls the size
++        of that cache. If not specified, the default value of 1000 is 
used.</p>
++      </attribute>
++
+       <attribute name="disableProxyCaching" required="false">
+         <p>Controls the caching of pages that are protected by security
+         constraints. Setting this to <code>false</code> may help work around
+@@ -470,6 +476,26 @@
+         <code>true</code> will be used.</p>
+       </attribute>
+ 
++      <attribute name="key" required="false">
++        <p>The secret key used by digest authentication. If not set, a secure
++        random value is generated. This should normally only be set when it is
++        necessary to keep key values constant either across server restarts
++        and/or across a cluster.</p>
++      </attribute>
++
++      <attribute name="nonceValidity" required="false">
++        <p>The time, in milliseconds, that a server generated nonce will be
++        considered valid for use in authentication. If not specified, the
++        default value of 300000 (5 minutes) will be used.</p>
++      </attribute>
++
++      <attribute name="opaque" required="false">
++        <p>The opaque server string used by digest authentication. If not 
set, a
++        random value is generated. This should normally only be set when it is
++        necessary to keep opaque values constant either across server restarts
++        and/or across a cluster.</p>
++      </attribute>
++
+       <attribute name="securePagesWithPragma" required="false">
+         <p>Controls the caching of pages that are protected by security
+         constraints. Setting this to <code>false</code> may help work around
+@@ -479,6 +505,14 @@
+         If not set, the default value of <code>true</code> will be used.</p>
+       </attribute>
+ 
++      <attribute name="validateUri" required="false">
++        <p>Should the URI be validated as required by RFC2617? If not 
specified,
++        the default value of <code>true</code> will be used. This should
++        normally only be set when Tomcat is located behind a reverse proxy and
++        the proxy is modifying the URI passed to Tomcat such that DIGEST
++        authentication always fails.</p>
++      </attribute>
++
+     </attributes>
+ 
+   </subsection>

Added: trunk/tomcat6/debian/patches/0015-CVE-2011-2526.patch
===================================================================
--- trunk/tomcat6/debian/patches/0015-CVE-2011-2526.patch                       
        (rev 0)
+++ trunk/tomcat6/debian/patches/0015-CVE-2011-2526.patch       2011-11-08 
18:54:07 UTC (rev 15367)
@@ -0,0 +1,144 @@
+Description: fix file restriction bypass or denial of service via untrusted 
web application
+Origin: upstream, http://svn.apache.org/viewvc?view=revision&revision=1146703
+Bug-Debian: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=634992
+
+Index: 
tomcat6-6.0.32/java/org/apache/catalina/connector/LocalStrings.properties
+===================================================================
+--- 
tomcat6-6.0.32.orig/java/org/apache/catalina/connector/LocalStrings.properties  
   2011-01-20 16:36:06.000000000 -0500
++++ tomcat6-6.0.32/java/org/apache/catalina/connector/LocalStrings.properties  
2011-10-13 16:40:14.477357566 -0400
+@@ -61,6 +61,7 @@
+ coyoteRequest.parseParameters=Exception thrown whilst processing POSTed 
parameters
+ coyoteRequest.postTooLarge=Parameters were not parsed because the size of the 
posted data was too big. Use the maxPostSize attribute of the connector to 
resolve this if the application should accept large POSTs.
+ coyoteRequest.chunkedPostTooLarge=Parameters were not parsed because the size 
of the posted data was too big. Because this request was a chunked request, it 
could not be processed further. Use the maxPostSize attribute of the connector 
to resolve this if the application should accept large POSTs.
++coyoteRequest.sendfileNotCanonical=Unable to determine canonical name of file 
[{0}] specified for use with sendfile
+ coyoteRequest.sessionEndAccessFail=Exception triggered ending access to 
session while recycling request
+ 
+ requestFacade.nullRequest=The request object has been recycled and is no 
longer associated with this facade
+Index: tomcat6-6.0.32/java/org/apache/catalina/connector/Request.java
+===================================================================
+--- tomcat6-6.0.32.orig/java/org/apache/catalina/connector/Request.java        
2011-02-01 22:09:54.000000000 -0500
++++ tomcat6-6.0.32/java/org/apache/catalina/connector/Request.java     
2011-10-13 16:39:36.549356595 -0400
+@@ -19,6 +19,7 @@
+ package org.apache.catalina.connector;
+ 
+ 
++import java.io.File;
+ import java.io.InputStream;
+ import java.io.IOException;
+ import java.io.BufferedReader;
+@@ -1455,6 +1456,26 @@
+             return;
+         }
+ 
++        // Do the security check before any updates are made
++        if (Globals.IS_SECURITY_ENABLED &&
++                name.equals("org.apache.tomcat.sendfile.filename")) {
++            // Use the canonical file name to avoid any possible symlink and
++            // relative path issues
++            String canonicalPath;
++            try {
++                canonicalPath = new File(value.toString()).getCanonicalPath();
++            } catch (IOException e) {
++                throw new SecurityException(sm.getString(
++                        "coyoteRequest.sendfileNotCanonical", value), e);
++            }
++            // Sendfile is performed in Tomcat's security context so need to
++            // check if the web app is permitted to access the file while 
still
++            // in the web app's security context
++            System.getSecurityManager().checkRead(canonicalPath);
++            // Update the value so the canonical path is used
++            value = canonicalPath;
++        }
++
+         oldValue = attributes.put(name, value);
+         if (oldValue != null) {
+             replaced = true;
+Index: tomcat6-6.0.32/java/org/apache/catalina/servlets/DefaultServlet.java
+===================================================================
+--- tomcat6-6.0.32.orig/java/org/apache/catalina/servlets/DefaultServlet.java  
2011-01-20 12:08:54.000000000 -0500
++++ tomcat6-6.0.32/java/org/apache/catalina/servlets/DefaultServlet.java       
2011-10-13 16:39:36.549356595 -0400
+@@ -1619,7 +1619,6 @@
+                 request.setAttribute("org.apache.tomcat.sendfile.start", new 
Long(range.start));
+                 request.setAttribute("org.apache.tomcat.sendfile.end", new 
Long(range.end + 1));
+             }
+-            request.setAttribute("org.apache.tomcat.sendfile.token", this);
+             return true;
+         } else {
+             return false;
+Index: tomcat6-6.0.32/java/org/apache/coyote/http11/Http11AprProcessor.java
+===================================================================
+--- tomcat6-6.0.32.orig/java/org/apache/coyote/http11/Http11AprProcessor.java  
2011-01-07 12:49:20.000000000 -0500
++++ tomcat6-6.0.32/java/org/apache/coyote/http11/Http11AprProcessor.java       
2011-10-13 16:39:36.549356595 -0400
+@@ -910,7 +910,18 @@
+                 sendfileData.socket = socket;
+                 sendfileData.keepAlive = keepAlive;
+                 if (!endpoint.getSendfile().add(sendfileData)) {
+-                    openSocket = true;
++                    if (sendfileData.socket == 0) {
++                        // Didn't send all the data but the socket is no 
longer
++                        // set. Something went wrong. Close the connection.
++                        // Too late to set status code.
++                        if (log.isDebugEnabled()) {
++                            log.debug(sm.getString(
++                                    "http11processor.sendfile.error"));
++                        }
++                        error = true;
++                    } else {
++                        openSocket = true;
++                    }
+                     break;
+                 }
+             }
+Index: tomcat6-6.0.32/java/org/apache/coyote/http11/LocalStrings.properties
+===================================================================
+--- tomcat6-6.0.32.orig/java/org/apache/coyote/http11/LocalStrings.properties  
2009-05-02 21:29:42.000000000 -0400
++++ tomcat6-6.0.32/java/org/apache/coyote/http11/LocalStrings.properties       
2011-10-13 16:39:36.549356595 -0400
+@@ -56,6 +56,7 @@
+ http11processor.socket.info=Exception getting socket information
+ http11processor.socket.ssl=Exception getting SSL attributes
+ http11processor.socket.timeout=Error setting socket timeout
++http11processor.sendfile.error=Error sending data using sendfile. May be 
caused by invalid request attributes for start/end points
+ 
+ #
+ # InternalInputBuffer
+Index: tomcat6-6.0.32/java/org/apache/tomcat/util/net/AprEndpoint.java
+===================================================================
+--- tomcat6-6.0.32.orig/java/org/apache/tomcat/util/net/AprEndpoint.java       
2011-02-01 03:07:46.000000000 -0500
++++ tomcat6-6.0.32/java/org/apache/tomcat/util/net/AprEndpoint.java    
2011-10-13 16:41:23.769359341 -0400
+@@ -1812,7 +1812,9 @@
+                                                data.pos, data.end - data.pos, 
0);
+                     if (nw < 0) {
+                         if (!(-nw == Status.EAGAIN)) {
+-                            destroySocket(data.socket);
++                            Pool.destroy(data.fdpool);
++                            // No need to close socket, this will be done by
++                            // calling code since data.socket == 0
+                             data.socket = 0;
+                             return false;
+                         } else {
+Index: tomcat6-6.0.32/java/org/apache/tomcat/util/net/NioEndpoint.java
+===================================================================
+--- tomcat6-6.0.32.orig/java/org/apache/tomcat/util/net/NioEndpoint.java       
2011-01-07 13:43:39.000000000 -0500
++++ tomcat6-6.0.32/java/org/apache/tomcat/util/net/NioEndpoint.java    
2011-10-13 16:39:36.553356596 -0400
+@@ -1734,6 +1734,13 @@
+                         sd.pos += written;
+                         sd.length -= written;
+                         attachment.access();
++                    } else {
++                        // Unusual not to be able to transfer any bytes
++                        // Check the length was set correctly
++                        if (sd.fchannel.size() <= sd.pos) {
++                            throw new IOException("Sendfile configured to " +
++                                    "send more data than was available");
++                        }
+                     }
+                 }
+                 if ( sd.length <= 0 && sc.getOutboundRemaining()<=0) {
+@@ -1758,6 +1765,7 @@
+                             log.debug("Send file connection is being closed");
+                         }
+                         cancelledKey(sk,SocketStatus.STOP,false);
++                        return false;
+                     }
+                 } else if ( attachment.interestOps() == 0 && reg ) {
+                     if (log.isDebugEnabled()) {

Modified: trunk/tomcat6/debian/patches/series
===================================================================
--- trunk/tomcat6/debian/patches/series 2011-11-08 14:21:37 UTC (rev 15366)
+++ trunk/tomcat6/debian/patches/series 2011-11-08 18:54:07 UTC (rev 15367)
@@ -10,3 +10,5 @@
 0011-623242.patch
 0012-CVE-2011-2204.patch
 0013-CVE-2011-3190.patch
+0014-CVE-2011-1184.patch
+0015-CVE-2011-2526.patch


_______________________________________________
pkg-java-commits mailing list
pkg-java-comm...@lists.alioth.debian.org
http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/pkg-java-commits

Reply via email to