Author: markt Date: Mon May 14 10:50:22 2018 New Revision: 1831556 URL: http://svn.apache.org/viewvc?rev=1831556&view=rev Log: Relax Host validation by removing the requirement that the final component of a FQDN must be alphabetic.
Modified: tomcat/trunk/java/org/apache/tomcat/util/http/parser/HttpParser.java tomcat/trunk/java/org/apache/tomcat/util/http/parser/LocalStrings.properties tomcat/trunk/test/org/apache/tomcat/util/http/parser/TestHttpParserHost.java tomcat/trunk/webapps/docs/changelog.xml 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=1831556&r1=1831555&r2=1831556&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 Mon May 14 10:50:22 2018 @@ -667,17 +667,13 @@ public class HttpParser { pos++; } while (true); - if (octetCount != 4) { + if (octetCount != 4 || octet < 0 || octet > 255) { // Might not be an IPv4 address. Could be a host name or a FQDN with // fully numeric components. Go back to the start and parse as a // host / FQDN. reader.reset(); return readHostDomainName(reader); } - if (octet < 0 || octet > 255) { - throw new IllegalArgumentException( - sm.getString("http.invalidOctet", Integer.toString(octet))); - } return pos; } @@ -788,13 +784,9 @@ public class HttpParser { static int readHostDomainName(Reader reader) throws IOException { DomainParseState state = DomainParseState.NEW; int pos = 0; - int segmentIndex = 0; while (state.mayContinue()) { - state = state.next(reader.read(), segmentIndex); - if (DomainParseState.PERIOD == state) { - segmentIndex++; - } + state = state.next(reader.read()); pos++; } @@ -836,31 +828,23 @@ public class HttpParser { } - private enum AllowsEnd { - NEVER, - FIRST, - ALWAYS - } - - private enum DomainParseState { - NEW( true, false, false, AllowsEnd.NEVER, " at the start of"), - ALL_ALPHA( true, true, true, AllowsEnd.ALWAYS, " after a letter in"), - ALPHA( true, true, true, AllowsEnd.FIRST, " after a letter in"), - NUMERIC( true, true, true, AllowsEnd.FIRST, " after a number in"), - PERIOD( true, false, false, AllowsEnd.NEVER, " after a period in"), - HYPHEN( true, true, false, AllowsEnd.NEVER, " after a hypen in"), - COLON( false, false, false, AllowsEnd.NEVER, " after a colon in"), - END( false, false, false, AllowsEnd.NEVER, " at the end of"); + NEW( true, false, false, false, " at the start of"), + ALPHA( true, true, true, true, " after a letter in"), + NUMERIC( true, true, true, true, " after a number in"), + PERIOD( true, false, false, false, " after a period in"), + HYPHEN( true, true, false, false, " after a hypen in"), + COLON( false, false, false, false, " after a colon in"), + END( false, false, false, false, " at the end of"); private final boolean mayContinue; private final boolean allowsHyphen; private final boolean allowsPeriod; - private final AllowsEnd allowsEnd; + private final boolean allowsEnd; private final String errorLocation; private DomainParseState(boolean mayContinue, boolean allowsHyphen, boolean allowsPeriod, - AllowsEnd allowsEnd, String errorLocation) { + boolean allowsEnd, String errorLocation) { this.mayContinue = mayContinue; this.allowsHyphen = allowsHyphen; this.allowsPeriod = allowsPeriod; @@ -872,13 +856,9 @@ public class HttpParser { return mayContinue; } - public DomainParseState next(int c, int segmentIndex) { + public DomainParseState next(int c) { if (HttpParser.isAlpha(c)) { - if (ALL_ALPHA == this || NEW == this || PERIOD == this) { - return ALL_ALPHA; - } else { - return ALPHA; - } + return ALPHA; } else if (HttpParser.isNumeric(c)) { return NUMERIC; } else if (c == '.') { @@ -889,26 +869,18 @@ public class HttpParser { Character.toString((char) c), errorLocation)); } } else if (c == ':') { - if (allowsEnd == AllowsEnd.ALWAYS || - allowsEnd == AllowsEnd.FIRST && segmentIndex == 0) { + if (allowsEnd) { return COLON; } else { throw new IllegalArgumentException(sm.getString("http.invalidCharacterDomain", Character.toString((char) c), errorLocation)); } } else if (c == -1) { - if (allowsEnd == AllowsEnd.ALWAYS || - allowsEnd == AllowsEnd.FIRST && segmentIndex == 0) { + if (allowsEnd) { return END; } else { - String msg; - if (allowsEnd == AllowsEnd.NEVER) { - msg = sm.getString("http.invalidSegmentEndState", this.name()); - } else { - // allowsEnd == AllowsEnd.FIRST && segmentIndex > 0 - msg = sm.getString("http.invalidEndState", this.name()); - } - throw new IllegalArgumentException(msg); + throw new IllegalArgumentException( + sm.getString("http.invalidSegmentEndState", this.name())); } } else if (c == '-') { if (allowsHyphen) { Modified: tomcat/trunk/java/org/apache/tomcat/util/http/parser/LocalStrings.properties URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/http/parser/LocalStrings.properties?rev=1831556&r1=1831555&r2=1831556&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/util/http/parser/LocalStrings.properties (original) +++ tomcat/trunk/java/org/apache/tomcat/util/http/parser/LocalStrings.properties Mon May 14 10:50:22 2018 @@ -26,7 +26,6 @@ http.illegalCharacterDomain=The characte http.illegalCharacterIpv4=The character [{0}] is never valid in an IPv4 address. http.illegalCharacterIpv6=The character [{0}] is never valid in an IPv6 address. http.invalidCharacterDomain=The character [{0}] is not valid{1} a domain name. -http.invalidEndState=The state [{0}] is not valid for the end of a domain name. http.invalidHextet=Invalid hextet. A hextet must consist of 4 or less hex characters. http.invalidIpv4Location=The IPv6 address contains an embedded IPv4 address at an invalid location. http.invalidOctet=Invalid octet [{0}]. The valid range for IPv4 octets is 0 to 255. Modified: tomcat/trunk/test/org/apache/tomcat/util/http/parser/TestHttpParserHost.java URL: http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/tomcat/util/http/parser/TestHttpParserHost.java?rev=1831556&r1=1831555&r2=1831556&view=diff ============================================================================== --- tomcat/trunk/test/org/apache/tomcat/util/http/parser/TestHttpParserHost.java (original) +++ tomcat/trunk/test/org/apache/tomcat/util/http/parser/TestHttpParserHost.java Mon May 14 10:50:22 2018 @@ -56,18 +56,25 @@ public class TestHttpParserHost { result.add(new Object[] { TestType.IPv4, "0.0.0.0:8080", Integer.valueOf(7), null} ); result.add(new Object[] { TestType.IPv4, "0", Integer.valueOf(-1), null} ); // IPv4 - invalid - result.add(new Object[] { TestType.IPv4, "0.0", Integer.valueOf(-1), IAE} ); - result.add(new Object[] { TestType.IPv4, "0.0.0", Integer.valueOf(-1), IAE} ); result.add(new Object[] { TestType.IPv4, ".0.0.0", Integer.valueOf(-1), IAE} ); result.add(new Object[] { TestType.IPv4, "0.0.0.", Integer.valueOf(-1), IAE} ); - result.add(new Object[] { TestType.IPv4, "256.0.0.0", Integer.valueOf(-1), IAE} ); - result.add(new Object[] { TestType.IPv4, "0.256.0.0", Integer.valueOf(-1), IAE} ); - result.add(new Object[] { TestType.IPv4, "0.0.256.0", Integer.valueOf(-1), IAE} ); - result.add(new Object[] { TestType.IPv4, "0.0.0.256", Integer.valueOf(-1), IAE} ); - result.add(new Object[] { TestType.IPv4, "0.a.0.0", Integer.valueOf(-1), IAE} ); result.add(new Object[] { TestType.IPv4, "0..0.0", Integer.valueOf(-1), IAE} ); result.add(new Object[] { TestType.IPv4, "0]", Integer.valueOf(-1), IAE} ); // Domain Name - valid + result.add(new Object[] { TestType.IPv4, "0.0", Integer.valueOf(-1), null} ); + result.add(new Object[] { TestType.IPv4, "0.0:8080", Integer.valueOf(3), null} ); + result.add(new Object[] { TestType.IPv4, "0.0.0", Integer.valueOf(-1), null} ); + result.add(new Object[] { TestType.IPv4, "0.0.0:8080", Integer.valueOf(5), null} ); + result.add(new Object[] { TestType.IPv4, "256.0.0.0", Integer.valueOf(-1), null} ); + result.add(new Object[] { TestType.IPv4, "256.0.0.0:8080", Integer.valueOf(9), null} ); + result.add(new Object[] { TestType.IPv4, "0.256.0.0", Integer.valueOf(-1), null} ); + result.add(new Object[] { TestType.IPv4, "0.256.0.0:8080", Integer.valueOf(9), null} ); + result.add(new Object[] { TestType.IPv4, "0.0.256.0", Integer.valueOf(-1), null} ); + result.add(new Object[] { TestType.IPv4, "0.0.256.0:8080", Integer.valueOf(9), null} ); + result.add(new Object[] { TestType.IPv4, "0.0.0.256", Integer.valueOf(-1), null} ); + result.add(new Object[] { TestType.IPv4, "0.0.0.256:8080", Integer.valueOf(9), null} ); + result.add(new Object[] { TestType.IPv4, "0.a.0.0", Integer.valueOf(-1), null} ); + result.add(new Object[] { TestType.IPv4, "0.a.0.0:8080", Integer.valueOf(7), null} ); result.add(new Object[] { TestType.IPv4, "localhost", Integer.valueOf(-1), null} ); result.add(new Object[] { TestType.IPv4, "localhost:8080", Integer.valueOf(9), null} ); result.add(new Object[] { TestType.IPv4, "tomcat.apache.org", Integer.valueOf(-1), null} ); @@ -80,18 +87,42 @@ public class TestHttpParserHost { result.add(new Object[] { TestType.IPv4, "foo.0.0.com:8080", Integer.valueOf(11), null} ); result.add(new Object[] { TestType.IPv4, "1foo.0.0.com", Integer.valueOf(-1), null} ); result.add(new Object[] { TestType.IPv4, "1foo.0.0.com:8080", Integer.valueOf(12), null} ); + result.add(new Object[] { TestType.IPv4, "foo1.0.0.com", Integer.valueOf(-1), null} ); + result.add(new Object[] { TestType.IPv4, "foo1.0.0.com:8080", Integer.valueOf(12), null} ); + result.add(new Object[] { TestType.IPv4, "1foo1.0.0.com", Integer.valueOf(-1), null} ); + result.add(new Object[] { TestType.IPv4, "1foo1.0.0.com:8080", Integer.valueOf(13), null} ); result.add(new Object[] { TestType.IPv4, "1-foo.0.0.com", Integer.valueOf(-1), null} ); result.add(new Object[] { TestType.IPv4, "1-foo.0.0.com:8080", Integer.valueOf(13), null} ); result.add(new Object[] { TestType.IPv4, "1--foo.0.0.com", Integer.valueOf(-1), null} ); result.add(new Object[] { TestType.IPv4, "1--foo.0.0.com:8080", Integer.valueOf(14), null} ); + result.add(new Object[] { TestType.IPv4, "foo.0.0.1com", Integer.valueOf(-1), null} ); + result.add(new Object[] { TestType.IPv4, "foo.0.0.1com:8080", Integer.valueOf(12), null} ); + result.add(new Object[] { TestType.IPv4, "foo.0.0.com1", Integer.valueOf(-1), null} ); + result.add(new Object[] { TestType.IPv4, "foo.0.0.com1:8080", Integer.valueOf(12), null} ); + result.add(new Object[] { TestType.IPv4, "foo.0.0.1com1", Integer.valueOf(-1), null} ); + result.add(new Object[] { TestType.IPv4, "foo.0.0.1com1:8080", Integer.valueOf(13), null} ); + result.add(new Object[] { TestType.IPv4, "foo.0.0.1-com", Integer.valueOf(-1), null} ); + result.add(new Object[] { TestType.IPv4, "foo.0.0.1-com:8080", Integer.valueOf(13), null} ); + result.add(new Object[] { TestType.IPv4, "foo.0.0.1--com", Integer.valueOf(-1), null} ); + result.add(new Object[] { TestType.IPv4, "foo.0.0.1--com:8080", Integer.valueOf(14), null} ); result.add(new Object[] { TestType.IPv4, "com", Integer.valueOf(-1), null} ); result.add(new Object[] { TestType.IPv4, "com:8080", Integer.valueOf(3), null} ); result.add(new Object[] { TestType.IPv4, "0com", Integer.valueOf(-1), null} ); result.add(new Object[] { TestType.IPv4, "0com:8080", Integer.valueOf(4), null} ); + result.add(new Object[] { TestType.IPv4, "0.0.0com", Integer.valueOf(-1), null} ); + result.add(new Object[] { TestType.IPv4, "0.0.0com:8080", Integer.valueOf(8), null} ); + result.add(new Object[] { TestType.IPv4, "0.0.0.0com", Integer.valueOf(-1), null} ); + result.add(new Object[] { TestType.IPv4, "0.0.0.0com:8080", Integer.valueOf(10), null} ); result.add(new Object[] { TestType.IPv4, "123", Integer.valueOf(-1), null} ); result.add(new Object[] { TestType.IPv4, "123:8080", Integer.valueOf(3), null} ); + result.add(new Object[] { TestType.IPv4, "foo.bar.0com", Integer.valueOf(-1), null} ); + result.add(new Object[] { TestType.IPv4, "foo.bar.0com:8080", Integer.valueOf(12), null} ); result.add(new Object[] { TestType.IPv4, "myapp-t.mydomain.com", Integer.valueOf(-1), null} ); + result.add(new Object[] { TestType.IPv4, "myapp-t.mydomain.com:8080", Integer.valueOf(20), null} ); result.add(new Object[] { TestType.IPv4, "myapp-t.my-domain.com", Integer.valueOf(-1), null} ); + result.add(new Object[] { TestType.IPv4, "myapp-t.my-domain.com:8080", Integer.valueOf(21), null} ); + result.add(new Object[] { TestType.IPv4, "myapp-t.my-domain.c-om", Integer.valueOf(-1), null} ); + result.add(new Object[] { TestType.IPv4, "myapp-t.my-domain.c-om:8080", Integer.valueOf(22), null} ); // Domain Name - invalid result.add(new Object[] { TestType.IPv4, ".", Integer.valueOf(-1), IAE} ); result.add(new Object[] { TestType.IPv4, ".:8080", Integer.valueOf(-1), IAE} ); @@ -108,11 +139,6 @@ public class TestHttpParserHost { result.add(new Object[] { TestType.IPv4, "foo.-bar", Integer.valueOf(-1), IAE} ); result.add(new Object[] { TestType.IPv4, "foo.^bar", Integer.valueOf(-1), IAE} ); result.add(new Object[] { TestType.IPv4, "foo.b*ar", Integer.valueOf(-1), IAE} ); - result.add(new Object[] { TestType.IPv4, "0.0.0com", Integer.valueOf(-1), IAE} ); - result.add(new Object[] { TestType.IPv4, "0.0.0.0com", Integer.valueOf(-1), IAE} ); - result.add(new Object[] { TestType.IPv4, "foo.bar.0com", Integer.valueOf(-1), IAE} ); - result.add(new Object[] { TestType.IPv4, "foo.bar.0com:8080", Integer.valueOf(-1), IAE} ); - result.add(new Object[] { TestType.IPv4, "myapp-t.my-domain.c-om", Integer.valueOf(-1), IAE} ); // IPv6 - valid result.add(new Object[] { TestType.IPv6, "[::1]", Integer.valueOf(-1), null} ); result.add(new Object[] { TestType.IPv6, "[::1]:8080", Integer.valueOf(5), null} ); Modified: tomcat/trunk/webapps/docs/changelog.xml URL: http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/changelog.xml?rev=1831556&r1=1831555&r2=1831556&view=diff ============================================================================== --- tomcat/trunk/webapps/docs/changelog.xml (original) +++ tomcat/trunk/webapps/docs/changelog.xml Mon May 14 10:50:22 2018 @@ -105,6 +105,10 @@ is sending AJP messages that are too large for the configured <code>packetSize</code>. (markt) </fix> + <fix> + Relax Host validation by removing the requirement that the final + component of a FQDN must be alphabetic. (markt) + </fix> </changelog> </subsection> <subsection name="Jasper"> --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org