[tomcat6/f14] Resolves CVE-2011-1184 rhbz 741406

Dave Knox dknox at fedoraproject.org
Wed Nov 16 16:54:42 UTC 2011


commit e714cf209acc4cc44646b11a44e6177ed0251236
Author: David Knox <dknox at dknox-laptop.(none)>
Date:   Wed Nov 16 09:55:15 2011 -0700

    Resolves CVE-2011-1184 rhbz 741406

 tomcat6-6.0.26-CVE-2011-1184-rhbz-741406.patch |  744 ++++++++++++++++++++++++
 tomcat6.spec                                   |    9 +-
 2 files changed, 751 insertions(+), 2 deletions(-)
---
diff --git a/tomcat6-6.0.26-CVE-2011-1184-rhbz-741406.patch b/tomcat6-6.0.26-CVE-2011-1184-rhbz-741406.patch
new file mode 100644
index 0000000..c4c7ab6
--- /dev/null
+++ b/tomcat6-6.0.26-CVE-2011-1184-rhbz-741406.patch
@@ -0,0 +1,744 @@
+--- java/org/apache/catalina/authenticator/DigestAuthenticator.java.orig	2011-11-09 11:15:23.675098163 -0700
++++ java/org/apache/catalina/authenticator/DigestAuthenticator.java	2011-11-15 15:58:31.135585307 -0700
+@@ -23,11 +23,13 @@
+ 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 +49,8 @@
+  * @version $Revision: 467222 $ $Date: 2006-10-24 05:17:11 +0200 (Tue, 24 Oct 2006) $
+  */
+ 
+-public class DigestAuthenticator
+-    extends AuthenticatorBase {
++public class DigestAuthenticator extends AuthenticatorBase {
++
+     private static Log log = LogFactory.getLog(DigestAuthenticator.class);
+ 
+ 
+@@ -66,6 +68,11 @@
+     protected static final String info =
+         "org.apache.catalina.authenticator.DigestAuthenticator/1.0";
+ 
++    /**
++	  * Tomcat's DIGEST implementaion only supports auth quality of protection
++	  */
++	 protected static final String QOP = "auth";		  
++
+ 
+     // ----------------------------------------------------------- Constructors
+ 
+@@ -90,25 +97,91 @@
+      */
+     protected static MessageDigest md5Helper;
+ 
++	 /**
++	  * 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;
+ 
++	 /**
++	  * 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 validatd as required by RFC2617? Can be disabled in
++	 * reverse proxies wher the proxy has modified the URI
++	 */
++	protected boolean validateUri = true;
+ 
+     // ------------------------------------------------------------- Properties
+ 
+-
+     /**
+      * Return descriptive information about this Valve implementation.
+      */
++	 @Override
+     public String getInfo() {
+ 
+         return (info);
+ 
+     }
+ 
++	 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
+ 
+@@ -126,6 +199,7 @@
+      *
+      * @exception IOException if an input/output error occurs
+      */
++	 @Override
+     public boolean authenticate(Request request,
+                                 Response response,
+                                 LoginConfig config)
+@@ -172,8 +246,14 @@
+ 
+         // 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 +265,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);
+@@ -199,93 +280,6 @@
+ 
+     // ------------------------------------------------------ Protected Methods
+ 
+-
+-    /**
+-     * 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 +288,6 @@
+      */
+     protected String parseUsername(String authorization) {
+ 
+-        //System.out.println("Authorization token : " + authorization);
+         // Validate the authorization credentials format
+         if (authorization == null)
+             return (null);
+@@ -354,20 +347,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 +372,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,30 +389,306 @@
+      * @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 = request.getServerName() + ":"
+-                + request.getServerPort();
++            realmName =  "Authentication required";
++             
+ 
+-        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());
++		}
++		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;
++		 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(equalSign).trim();
++				String currentTokenValue = 
++					currentToken.substring(equalSign + 1).trim();
++				if ("username".equals(currentTokenName)) {
++					userName = removeQuotes(currentTokenValue);
++				}
++				if ("realm".equals(currentTokenName) ) {
++					realmName = removeQuotes(currentTokenValue);
++				}
++				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 = "Authorization required";
++			 }
++			 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 nfx) {
++				 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 nfx) {
++					return false;
++				}
++				NonceInfo info;
++				synchronized (cnonces) {
++					info = (NonceInfo) 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;
++		}
++	}
+ }
++
+--- STATUS.txt.orig	2011-11-09 11:14:55.287098433 -0700
++++ STATUS.txt	2011-11-09 11:23:39.299093436 -0700
+@@ -163,3 +163,10 @@
+   -1:
+ 
+ * Fix various sendfile issues CVE-2011-2526
++
++* Add StuckThreadDectionValve
++    https://github.com/sylvainlaurent/tomcat60/commit/252334f958877221ecb2dc64ee0fd12bb77e360b
++	 CVE-2011-1184
++	 +1 slaurent
++
++
+--- java/org/apache/catalina/authenticator/LocalStrings.properties.orig	2011-11-09 11:15:48.906097922 -0700
++++ java/org/apache/catalina/authenticator/LocalStrings.properties	2011-11-15 12:54:44.851690535 -0700
+@@ -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 the client nonce cache to make room for new entries. A replay attack is now possible. To prevent the possiblity of replay attacks, reduce nonceValidity or increase conceCacheSize. 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
+--- java/org/apache/catalina/authenticator/mbeans-descriptors.xml.orig	2011-11-09 11:16:06.973097749 -0700
++++ java/org/apache/catalina/authenticator/mbeans-descriptors.xml	2011-11-15 13:47:45.280660144 -0700
+@@ -60,10 +60,31 @@
+                description="Fully qualified class name of the managed object"
+                type="java.lang.String"
+                writeable="false"/>
++
++	<attribute name="cnonceCacheSize"
++					description="The size of the cnonce cahce 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="validUri"
++				description="Should the uri be validated as required by RFC2617?"
++				type="boolean"/>
++
+   </mbean>
+   
+   <mbean name="FormAuthenticator"
+--- java/org/apache/catalina/realm/RealmBase.java.orig	2011-11-09 11:16:25.518097573 -0700
++++ java/org/apache/catalina/realm/RealmBase.java	2011-11-15 13:57:21.483654649 -0700
+@@ -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 + ":"
++		  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);
+--- webapps/docs/changelog.xml.orig	2011-11-09 11:16:40.641097443 -0700
++++ webapps/docs/changelog.xml	2011-11-15 14:03:22.497651205 -0700
+@@ -322,6 +322,10 @@
+          (such as Apache httpd 2.2) as the proxy should reject the 
+          invalid transfer encoding header.
+       </fix>
++		<add>
++			Add additional configuration options to the DIGEST authenticator
++			CVE-2011-1138 (markt)
++		</add>
+     </changelog>
+   </subsection>
+   <subsection name="Other">
diff --git a/tomcat6.spec b/tomcat6.spec
index 89ef970..bba40aa 100644
--- a/tomcat6.spec
+++ b/tomcat6.spec
@@ -55,7 +55,7 @@
 Name: tomcat6
 Epoch: 0
 Version: %{major_version}.%{minor_version}.%{micro_version}
-Release: 27%{?dist}
+Release: 28%{?dist}
 Summary: Apache Servlet/JSP Engine, RI for Servlet %{servletspec}/JSP %{jspspec} API
 
 Group: Networking/Daemons
@@ -82,6 +82,7 @@ Patch6: %{name}-%{major_version}.%{minor_version}.26-CVE-2011-0013.patch
 Patch7: %{name}-6.0.26-CVE-2011-2204-rhbz-717016.patch
 Patch8: %{name}-6.0.26-CVE-2011-2526-rhbz-721087.patch
 Patch9: %{name}-6.0.26-CVE-2011-3190-rhbz-738502.patch
+Patch10: %{name}-6.0.26-CVE-2011-1184-rhbz-741406.patch
 
 BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root
 BuildArch: noarch
@@ -237,6 +238,7 @@ pushd %{packdname}
 %patch7 -p0
 %patch8 -p0
 %patch9 -p0
+%patch10 -p0
 
 %{__ln_s} $(build-classpath jakarta-taglibs-core) webapps/examples/WEB-INF/lib/jstl.jar
 %{__ln_s} $(build-classpath jakarta-taglibs-standard) webapps/examples/WEB-INF/lib/standard.jar
@@ -648,6 +650,9 @@ fi
 %{appdir}/sample
 
 %changelog
+* Tue Nov 15 2011 David Knox <dknox at redhat.com> 0:6.0.26-28
+- Resolves CVE-2011-1184 rhbz 781086
+
 * Tue Sep 27 2011 David Knox <dknox at redhat.com> 0:6.0.26-27
 - Resolves CVE-2011-3190 rhbz 738502
 
@@ -655,7 +660,7 @@ fi
 - Resolves rhbz 640134 - JAVA_HOME setting
 
 * Fri Sep 23 2011 David Knox <dknox at redhat.com> 0:6.0.26-25
-- Resolves CVE-2011-2526 rhbz 721087 sendfile validation and
+- Resolves CVE-2011-2526 rhbz 721086 sendfile validation and
 - validation
 
 * Thu Aug 10 2011 David Knox <dknox at redhat.com> 0:6.0.26-24


More information about the scm-commits mailing list