commit e7f93e1a6a0a761d4d02295daf622f9e446dcd93 Author: Karsten Loesing karsten.loesing@gmx.net Date: Fri May 3 15:32:13 2013 +0200
Restrict valid keyword characters to [A-Za-z0-9-]+.
Fixes #8798. --- .../descriptor/impl/ExtraInfoDescriptorImpl.java | 1 + .../torproject/descriptor/impl/ParseHelper.java | 11 ++++++ .../descriptor/impl/ServerDescriptorImpl.java | 1 + .../impl/ExtraInfoDescriptorImplTest.java | 34 ++++++++++++++++++ .../descriptor/impl/ServerDescriptorImplTest.java | 37 ++++++++++++++++++++ 5 files changed, 84 insertions(+), 0 deletions(-)
diff --git a/src/org/torproject/descriptor/impl/ExtraInfoDescriptorImpl.java b/src/org/torproject/descriptor/impl/ExtraInfoDescriptorImpl.java index 9bd9a9b..f5bf8ed 100644 --- a/src/org/torproject/descriptor/impl/ExtraInfoDescriptorImpl.java +++ b/src/org/torproject/descriptor/impl/ExtraInfoDescriptorImpl.java @@ -183,6 +183,7 @@ public class ExtraInfoDescriptorImpl extends DescriptorImpl } else if (line.startsWith("-----END")) { skipCrypto = false; } else if (!skipCrypto) { + ParseHelper.parseKeyword(line, partsNoOpt[0]); if (this.failUnrecognizedDescriptorLines) { throw new DescriptorParseException("Unrecognized line '" + line + "' in extra-info descriptor."); diff --git a/src/org/torproject/descriptor/impl/ParseHelper.java b/src/org/torproject/descriptor/impl/ParseHelper.java index 1b7eff2..4fd776e 100644 --- a/src/org/torproject/descriptor/impl/ParseHelper.java +++ b/src/org/torproject/descriptor/impl/ParseHelper.java @@ -17,6 +17,17 @@ import org.apache.commons.codec.binary.Hex;
public class ParseHelper {
+ private static Pattern keywordPattern = + Pattern.compile("^[A-Za-z0-9-]+$"); + public static String parseKeyword(String line, String keyword) + throws DescriptorParseException { + if (!keywordPattern.matcher(keyword).matches()) { + throw new DescriptorParseException("Unrecognized character in " + + "keyword '" + keyword + "' in line '" + line + "'."); + } + return keyword; + } + private static Pattern ipv4Pattern = Pattern.compile("^[0-9\.]{7,15}$"); public static String parseIpv4Address(String line, String address) diff --git a/src/org/torproject/descriptor/impl/ServerDescriptorImpl.java b/src/org/torproject/descriptor/impl/ServerDescriptorImpl.java index 1fb39f5..baf4456 100644 --- a/src/org/torproject/descriptor/impl/ServerDescriptorImpl.java +++ b/src/org/torproject/descriptor/impl/ServerDescriptorImpl.java @@ -152,6 +152,7 @@ public class ServerDescriptorImpl extends DescriptorImpl } else if (crypto != null) { crypto.append(line + "\n"); } else { + ParseHelper.parseKeyword(line, partsNoOpt[0]); if (this.failUnrecognizedDescriptorLines) { throw new DescriptorParseException("Unrecognized line '" + line + "' in server descriptor."); diff --git a/test/org/torproject/descriptor/impl/ExtraInfoDescriptorImplTest.java b/test/org/torproject/descriptor/impl/ExtraInfoDescriptorImplTest.java index 569ce06..11b07b2 100644 --- a/test/org/torproject/descriptor/impl/ExtraInfoDescriptorImplTest.java +++ b/test/org/torproject/descriptor/impl/ExtraInfoDescriptorImplTest.java @@ -7,6 +7,8 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue;
+import java.io.ByteArrayOutputStream; +import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -142,6 +144,15 @@ public class ExtraInfoDescriptorImplTest { return new ExtraInfoDescriptorImpl(db.buildDescriptor(), failUnrecognizedDescriptorLines); } + private byte[] nonAsciiLineBytes = null; + private static ExtraInfoDescriptor createWithNonAsciiLineBytes( + byte[] lineBytes, boolean failUnrecognizedDescriptorLines) + throws DescriptorParseException { + DescriptorBuilder db = new DescriptorBuilder(); + db.nonAsciiLineBytes = lineBytes; + return new ExtraInfoDescriptorImpl(db.buildDescriptor(), + failUnrecognizedDescriptorLines); + } private String routerSignatureLines = "router-signature\n" + "-----BEGIN SIGNATURE-----\n" + "o4j+kH8UQfjBwepUnr99v0ebN8RpzHJ/lqYsTojXHy9kMr1RNI9IDeSzA7PSqT" @@ -204,6 +215,20 @@ public class ExtraInfoDescriptorImplTest { if (this.unrecognizedLine != null) { sb.append(this.unrecognizedLine + "\n"); } + if (this.nonAsciiLineBytes != null) { + try { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + baos.write(sb.toString().getBytes()); + baos.write(this.nonAsciiLineBytes); + baos.write("\n".getBytes()); + if (this.routerSignatureLines != null) { + baos.write(this.routerSignatureLines.getBytes()); + } + return baos.toByteArray(); + } catch (IOException e) { + return null; + } + } if (this.routerSignatureLines != null) { sb.append(this.routerSignatureLines + "\n"); } @@ -1304,6 +1329,15 @@ public class ExtraInfoDescriptorImplTest { }
@Test(expected = DescriptorParseException.class) + public void testBridgeIpsNonAsciiKeyword() + throws DescriptorParseException { + DescriptorBuilder.createWithNonAsciiLineBytes(new byte[] { + 0x14, (byte) 0xfe, 0x18, // non-ascii chars + 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x2d, // "bridge-" + 0x69, 0x70, 0x73 }, false); // "ips" (no newline) + } + + @Test(expected = DescriptorParseException.class) public void testBridgeIpVersionsDouble() throws DescriptorParseException { BridgeStatsBuilder.createWithBridgeIpVersionsLine( diff --git a/test/org/torproject/descriptor/impl/ServerDescriptorImplTest.java b/test/org/torproject/descriptor/impl/ServerDescriptorImplTest.java index 5bd73af..9eb38ae 100644 --- a/test/org/torproject/descriptor/impl/ServerDescriptorImplTest.java +++ b/test/org/torproject/descriptor/impl/ServerDescriptorImplTest.java @@ -8,6 +8,8 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue;
+import java.io.ByteArrayOutputStream; +import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -216,6 +218,15 @@ public class ServerDescriptorImplTest { return new ServerDescriptorImpl(db.buildDescriptor(), failUnrecognizedDescriptorLines); } + private byte[] nonAsciiLineBytes = null; + private static ServerDescriptor createWithNonAsciiLineBytes( + byte[] lineBytes, boolean failUnrecognizedDescriptorLines) + throws DescriptorParseException { + DescriptorBuilder db = new DescriptorBuilder(); + db.nonAsciiLineBytes = lineBytes; + return new ServerDescriptorImpl(db.buildDescriptor(), + failUnrecognizedDescriptorLines); + } private byte[] buildDescriptor() { StringBuilder sb = new StringBuilder(); if (this.routerLine != null) { @@ -287,6 +298,20 @@ public class ServerDescriptorImplTest { if (this.unrecognizedLine != null) { sb.append(this.unrecognizedLine + "\n"); } + if (this.nonAsciiLineBytes != null) { + try { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + baos.write(sb.toString().getBytes()); + baos.write(this.nonAsciiLineBytes); + baos.write("\n".getBytes()); + if (this.routerSignatureLines != null) { + baos.write(this.routerSignatureLines.getBytes()); + } + return baos.toByteArray(); + } catch (IOException e) { + return null; + } + } if (this.routerSignatureLines != null) { sb.append(this.routerSignatureLines + "\n"); } @@ -1159,6 +1184,18 @@ public class ServerDescriptorImplTest { "allow-single-hop-exits true"); }
+ @Test(expected = DescriptorParseException.class) + public void testAllowSingleHopExitsNonAsciiKeyword() + throws DescriptorParseException { + DescriptorBuilder.createWithNonAsciiLineBytes(new byte[] { + 0x14, (byte) 0xfe, 0x18, // non-ascii chars + 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x2d, // "allow-" + 0x73, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x2d, // "single-" + 0x68, 0x6f, 0x70, 0x2d, // "hop-" + 0x65, 0x78, 0x69, 0x74, 0x73 }, // "exits" (no newline) + false); + } + @Test() public void testIpv6PolicyLine() throws DescriptorParseException { ServerDescriptor descriptor = DescriptorBuilder.