Author: markt Date: Thu Oct 2 11:15:04 2014 New Revision: 1628936 URL: http://svn.apache.org/r1628936 Log: Add support for the remaining attributes to the RFC 6265 cookie generation
Modified: tomcat/trunk/java/org/apache/tomcat/util/http/LocalStrings.properties tomcat/trunk/java/org/apache/tomcat/util/http/Rfc6265CookieProcessor.java tomcat/trunk/test/org/apache/tomcat/util/http/TestCookieProcessorGeneration.java Modified: tomcat/trunk/java/org/apache/tomcat/util/http/LocalStrings.properties URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/http/LocalStrings.properties?rev=1628936&r1=1628935&r2=1628936&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/util/http/LocalStrings.properties (original) +++ tomcat/trunk/java/org/apache/tomcat/util/http/LocalStrings.properties Thu Oct 2 11:15:04 2014 @@ -30,3 +30,7 @@ cookies.invalidSpecial=Cookies: Unknown cookies.fallToDebug=\n Note: further occurrences of Cookie errors will be logged at DEBUG level. headers.maxCountFail=More than the maximum allowed number of headers ([{0}]) were detected. + +rfc6265CookieProcessor.invalidCharInValue=An invalid character [{0}] was present in the Cookie value +rfc6265CookieProcessor.invalidDomain=An invalid domain [{0}] was specified for this cookie +rfc6265CookieProcessor.invalidPath=An invalid path [{0}] was specified for this cookie \ No newline at end of file Modified: tomcat/trunk/java/org/apache/tomcat/util/http/Rfc6265CookieProcessor.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/http/Rfc6265CookieProcessor.java?rev=1628936&r1=1628935&r2=1628936&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/util/http/Rfc6265CookieProcessor.java (original) +++ tomcat/trunk/java/org/apache/tomcat/util/http/Rfc6265CookieProcessor.java Thu Oct 2 11:15:04 2014 @@ -18,17 +18,39 @@ package org.apache.tomcat.util.http; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; +import java.util.BitSet; import org.apache.juli.logging.Log; import org.apache.juli.logging.LogFactory; import org.apache.tomcat.util.buf.ByteChunk; import org.apache.tomcat.util.buf.MessageBytes; import org.apache.tomcat.util.http.parser.Cookie; +import org.apache.tomcat.util.res.StringManager; public class Rfc6265CookieProcessor implements CookieProcessor { private static final Log log = LogFactory.getLog(Rfc6265CookieProcessor.class); + private static final StringManager sm = + StringManager.getManager(Rfc6265CookieProcessor.class.getPackage().getName()); + + private static final BitSet domainValid = new BitSet(128); + + static { + for (char c = '0'; c < '9'; c++) { + domainValid.set(c); + } + for (char c = 'a'; c < 'z'; c++) { + domainValid.set(c); + } + for (char c = 'A'; c < 'Z'; c++) { + domainValid.set(c); + } + domainValid.set('.'); + domainValid.set('-'); + } + + @Override public Charset getCharset() { return StandardCharsets.UTF_8; @@ -82,7 +104,7 @@ public class Rfc6265CookieProcessor impl header.append(cookie.getName()); header.append('='); String value = cookie.getValue(); - if (value != null) { + if (value != null && value.length() > 0) { validateCookieValue(value); header.append(value); } @@ -95,16 +117,33 @@ public class Rfc6265CookieProcessor impl header.append(maxAge); } - // TODO add support for the remaining attributes. + String domain = cookie.getDomain(); + if (domain != null && domain.length() > 0) { + validateDomain(domain); + header.append(";domain="); + header.append(domain); + } + + String path = cookie.getPath(); + if (path != null && path.length() > 0) { + validatePath(path); + header.append(";path="); + header.append(path); + } + + if (cookie.getSecure()) { + header.append(";Secure"); + } + + if (cookie.isHttpOnly()) { + header.append(";HttpOnly"); + } + return header.toString(); } private void validateCookieValue(String value) { - if (value == null || value.length() == 0) { - return; - } - int start = 0; int end = value.length(); @@ -117,8 +156,53 @@ public class Rfc6265CookieProcessor impl for (int i = start; i < end; i++) { char c = chars[i]; if (c < 0x21 || c == 0x22 || c == 0x2c || c == 0x3b || c == 0x5c || c == 0x7f) { - // TODO i18n - throw new IllegalArgumentException(); + throw new IllegalArgumentException(sm.getString( + "rfc6265CookieProcessor.invalidCharInValue", Integer.toString(c))); + } + } + } + + + private void validateDomain(String domain) { + int i = 0; + int prev = -1; + int cur = -1; + char[] chars = domain.toCharArray(); + while (i < chars.length) { + prev = cur; + cur = chars[i]; + if (!domainValid.get(cur)) { + throw new IllegalArgumentException(sm.getString( + "rfc6265CookieProcessor.invalidDomain", domain)); + } + // labels must start with a letter or number + if ((prev == '.' || prev == -1) && (cur == '.' || cur == '-')) { + throw new IllegalArgumentException(sm.getString( + "rfc6265CookieProcessor.invalidDomain", domain)); + } + // labels must end with a letter or number + if (prev == '-' && cur == '.') { + throw new IllegalArgumentException(sm.getString( + "rfc6265CookieProcessor.invalidDomain", domain)); + } + i++; + } + // domain must end with a label + if (cur == '.' || cur == '-') { + throw new IllegalArgumentException(sm.getString( + "rfc6265CookieProcessor.invalidDomain", domain)); + } + } + + + private void validatePath(String path) { + char[] chars = path.toCharArray(); + + for (int i = 0; i < chars.length; i++) { + char ch = chars[i]; + if (ch < 0x20 || ch > 0x7E || ch == ';') { + throw new IllegalArgumentException(sm.getString( + "rfc6265CookieProcessor.invalidPath", path)); } } } Modified: tomcat/trunk/test/org/apache/tomcat/util/http/TestCookieProcessorGeneration.java URL: http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/tomcat/util/http/TestCookieProcessorGeneration.java?rev=1628936&r1=1628935&r2=1628936&view=diff ============================================================================== --- tomcat/trunk/test/org/apache/tomcat/util/http/TestCookieProcessorGeneration.java (original) +++ tomcat/trunk/test/org/apache/tomcat/util/http/TestCookieProcessorGeneration.java Thu Oct 2 11:15:04 2014 @@ -190,6 +190,64 @@ public class TestCookieProcessorGenerati doV1TestMaxAge(-100, "foo=bar; Version=1", "foo=bar"); } + @Test + public void v1TestDomainValid01() { + doV1TestDomain("example.com", "foo=bar; Version=1; Domain=example.com", + "foo=bar;domain=example.com"); + } + + @Test + public void v1TestDomainValid02() { + doV1TestDomain("exa-mple.com", "foo=bar; Version=1; Domain=exa-mple.com", + "foo=bar;domain=exa-mple.com"); + } + + @Test + public void v1TestDomainInvalid01() { + doV1TestDomain("example.com.", "foo=bar; Version=1; Domain=example.com.", null); + } + + @Test + public void v1TestDomainInvalid02() { + doV1TestDomain("example.com-", "foo=bar; Version=1; Domain=example.com-", null); + } + + @Test + public void v1TestDomainInvalid03() { + doV1TestDomain(".example.com.", "foo=bar; Version=1; Domain=.example.com.", null); + } + + @Test + public void v1TestDomainInvalid04() { + doV1TestDomain("-example.com.", "foo=bar; Version=1; Domain=-example.com.", null); + } + + @Test + public void v1TestDomainInvalid05() { + doV1TestDomain("example..com.", "foo=bar; Version=1; Domain=example..com.", null); + } + + @Test + public void v1TestDomainInvalid06() { + doV1TestDomain("example-.com.", "foo=bar; Version=1; Domain=example-.com.", null); + } + + @Test + public void v1TestDomainInvalid07() { + doV1TestDomain("exam$ple.com.", "foo=bar; Version=1; Domain=exam$ple.com.", null); + } + + @Test + public void v1TestPathValid() { + doV1TestPath("/example", "foo=bar; Version=1; Path=/example", + "foo=bar;path=/example"); + } + + @Test + public void v1TestPathInvalid01() { + doV1TestPath("exa\tmple", "foo=bar; Version=1; Path=\"exa\tmple\"", null); + } + private void doTest(Cookie cookie, String expected) { doTest(cookie, expected, expected); @@ -247,4 +305,24 @@ public class TestCookieProcessorGenerati cookie.setMaxAge(age); doTest(cookie, legacy, expectedLegacy, new Rfc6265CookieProcessor(), expectedRfc6265); } + + + private void doV1TestDomain(String domain, String expectedLegacy, String expectedRfc6265) { + LegacyCookieProcessor legacy = new LegacyCookieProcessor(); + legacy.setAlwaysAddExpires(false); + Cookie cookie = new Cookie("foo", "bar"); + cookie.setVersion(1); + cookie.setDomain(domain); + doTest(cookie, legacy, expectedLegacy, new Rfc6265CookieProcessor(), expectedRfc6265); + } + + + private void doV1TestPath(String path, String expectedLegacy, String expectedRfc6265) { + LegacyCookieProcessor legacy = new LegacyCookieProcessor(); + legacy.setAlwaysAddExpires(false); + Cookie cookie = new Cookie("foo", "bar"); + cookie.setVersion(1); + cookie.setPath(path); + doTest(cookie, legacy, expectedLegacy, new Rfc6265CookieProcessor(), expectedRfc6265); + } } --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org