You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by ma...@apache.org on 2013/01/04 21:55:34 UTC

svn commit: r1429123 - in /tomcat/trunk: java/org/apache/tomcat/util/http/parser/HttpParser.java test/org/apache/tomcat/util/http/parser/TestAuthorizationDigest.java

Author: markt
Date: Fri Jan  4 20:55:34 2013
New Revision: 1429123

URL: http://svn.apache.org/viewvc?rev=1429123&view=rev
Log:
Make HTTP DIGEST authentication header parsing tolerant of known buggy clients.

Modified:
    tomcat/trunk/java/org/apache/tomcat/util/http/parser/HttpParser.java
    tomcat/trunk/test/org/apache/tomcat/util/http/parser/TestAuthorizationDigest.java

Modified: tomcat/trunk/java/org/apache/tomcat/util/http/parser/HttpParser.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/http/parser/HttpParser.java?rev=1429123&r1=1429122&r2=1429123&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/util/http/parser/HttpParser.java (original)
+++ tomcat/trunk/java/org/apache/tomcat/util/http/parser/HttpParser.java Fri Jan  4 20:55:34 2013
@@ -48,6 +48,7 @@ public class HttpParser {
     private static final Integer FIELD_TYPE_TOKEN_OR_QUOTED_STRING = Integer.valueOf(2);
     private static final Integer FIELD_TYPE_LHEX = Integer.valueOf(3);
     private static final Integer FIELD_TYPE_QUOTED_LHEX = Integer.valueOf(4);
+    private static final Integer FIELD_TYPE_QUOTED_TOKEN = Integer.valueOf(5);
 
     private static final Map<String,Integer> fieldTypes = new HashMap<>();
 
@@ -64,7 +65,7 @@ public class HttpParser {
         fieldTypes.put("algorithm", FIELD_TYPE_TOKEN);
         fieldTypes.put("cnonce", FIELD_TYPE_QUOTED_STRING);
         fieldTypes.put("opaque", FIELD_TYPE_QUOTED_STRING);
-        fieldTypes.put("qop", FIELD_TYPE_TOKEN);
+        fieldTypes.put("qop", FIELD_TYPE_QUOTED_TOKEN);
         fieldTypes.put("nc", FIELD_TYPE_LHEX);
 
         // Setup the flag arrays
@@ -148,6 +149,10 @@ public class HttpParser {
                     // FIELD_TYPE_QUOTED_LHEX
                     value = readQuotedLhex(input);
                     break;
+                case 5:
+                    // FIELD_TYPE_QUOTED_TOKEN
+                    value = readQuotedToken(input);
+                    break;
                 default:
                     // Error
                     throw new IllegalArgumentException(
@@ -346,6 +351,58 @@ public class HttpParser {
     }
 
     /**
+     * This is not defined in any RFC. It is a special case to handle data from
+     * buggy clients (known buggy clients include Microsoft IE 8 & 9, Apple
+     * Safari for OSX and iOS) that add quotes to values that should be tokens.
+     *
+     * @return the token if one was found, null if data other than a token or
+     *         quoted token was found or null if the end of data was reached
+     *         before a quoted token was terminated
+     */
+    private static String readQuotedToken(StringReader input)
+            throws IOException {
+
+        StringBuilder result = new StringBuilder();
+        boolean quoted = false;
+
+        int c = input.read();
+
+        // Skip lws
+        while (c == 32 || c == 9) {
+            c = input.read();
+        }
+
+        if (c == '"') {
+            quoted = true;
+        } else if (c == -1) {
+            return null;
+        } else {
+            result.append((char) c);
+        }
+        c = input.read();
+
+        while (c != -1 && isToken[c]) {
+            result.append((char) c);
+            c = input.read();
+        }
+
+        if (quoted) {
+            if (c != '"') {
+                return null;
+            }
+        } else {
+            // Skip back so non-token character is available for next read
+            input.skip(-1);
+        }
+
+        if (c != -1 && result.length() == 0) {
+            return null;
+        } else {
+            return result.toString();
+        }
+    }
+
+    /**
      * Parses lower case hex but permits upper case hex to be used (converting
      * it to lower case before returning).
      *

Modified: tomcat/trunk/test/org/apache/tomcat/util/http/parser/TestAuthorizationDigest.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/tomcat/util/http/parser/TestAuthorizationDigest.java?rev=1429123&r1=1429122&r2=1429123&view=diff
==============================================================================
--- tomcat/trunk/test/org/apache/tomcat/util/http/parser/TestAuthorizationDigest.java (original)
+++ tomcat/trunk/test/org/apache/tomcat/util/http/parser/TestAuthorizationDigest.java Fri Jan  4 20:55:34 2013
@@ -155,4 +155,53 @@ public class TestAuthorizationDigest {
         Assert.assertNull(result);
     }
 
+    @Test
+    public void testTokenQop() throws Exception {
+        String header = "Digest qop=auth";
+
+        StringReader input = new StringReader(header);
+
+        Map<String,String> result = HttpParser.parseAuthorizationDigest(input);
+        Assert.assertEquals("auth", result.get("qop"));
+    }
+
+    @Test
+    public void testQuotedTokenQop() throws Exception {
+        String header = "Digest qop=\"auth\"";
+
+        StringReader input = new StringReader(header);
+
+        Map<String,String> result = HttpParser.parseAuthorizationDigest(input);
+        Assert.assertEquals("auth", result.get("qop"));
+    }
+
+    @Test
+    public void testNonTokenQop() throws Exception {
+        String header = "Digest qop=au{th";
+
+        StringReader input = new StringReader(header);
+
+        Map<String,String> result = HttpParser.parseAuthorizationDigest(input);
+        Assert.assertNull(result);
+    }
+
+    @Test
+    public void testQuotedNonTokenQop() throws Exception {
+        String header = "Digest qop=\"au{th\"";
+
+        StringReader input = new StringReader(header);
+
+        Map<String,String> result = HttpParser.parseAuthorizationDigest(input);
+        Assert.assertNull(result);
+    }
+
+    @Test
+    public void testUnclosedQuotedTokenQop() throws Exception {
+        String header = "Digest qop=\"auth";
+
+        StringReader input = new StringReader(header);
+
+        Map<String,String> result = HttpParser.parseAuthorizationDigest(input);
+        Assert.assertNull(result);
+    }
 }



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org