commit 723e71a09ea6bfb8ebc4d4b40b51c2ff0aebd510 Author: Karsten Loesing karsten.loesing@gmx.net Date: Sat Jan 7 10:50:52 2017 +0100
Don't require searches by IPv6 address to start with [.
Implements #16552. --- CHANGELOG.md | 7 +++++ .../torproject/onionoo/server/RequestHandler.java | 3 +- .../torproject/onionoo/server/ResourceServlet.java | 18 ++++++++--- .../torproject/onionoo/server/ResponseBuilder.java | 4 +-- src/main/resources/web/index.html | 10 +++---- .../onionoo/server/ResourceServletTest.java | 35 ++++++++++++++++++++++ 6 files changed, 65 insertions(+), 12 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md index bd30ca0..465e145 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +# Changes in version 4.0-x.x.x - 2017-xx-xx + + * Medium changes + - Accept searches by IPv6 addresses even without leading or + enclosing square brackets. + + # Changes in version 3.2-1.1.0 - 2017-01-27
* Major changes diff --git a/src/main/java/org/torproject/onionoo/server/RequestHandler.java b/src/main/java/org/torproject/onionoo/server/RequestHandler.java index 49e0259..98ece58 100644 --- a/src/main/java/org/torproject/onionoo/server/RequestHandler.java +++ b/src/main/java/org/torproject/onionoo/server/RequestHandler.java @@ -261,7 +261,8 @@ public class RequestHandler { } else { List<String> addresses = entry.getAddresses(); for (String address : addresses) { - if (address.startsWith(searchTerm.toLowerCase())) { + if (address.startsWith(searchTerm.toLowerCase()) + || address.startsWith("[" + searchTerm.toLowerCase())) { /* Address matches. */ lineMatches = true; break; diff --git a/src/main/java/org/torproject/onionoo/server/ResourceServlet.java b/src/main/java/org/torproject/onionoo/server/ResourceServlet.java index 9a4c679..c5fd949 100644 --- a/src/main/java/org/torproject/onionoo/server/ResourceServlet.java +++ b/src/main/java/org/torproject/onionoo/server/ResourceServlet.java @@ -75,6 +75,12 @@ public class ResourceServlet extends HttpServlet { new HashSet<>(Arrays.asList(("search,fingerprint,order,limit," + "offset,fields").split(",")));
+ private static String ipv6AddressPatternString = + "^\[?[0-9a-fA-F:\.]{1,39}\]?$"; + + private static Pattern ipv6AddressPattern = + Pattern.compile(ipv6AddressPatternString); + /** Handles the HTTP GET request in the wrapped <code>request</code> by * writing an HTTP GET response to the likewise <code>response</code>, * both of which are wrapped to facilitate testing. */ @@ -150,13 +156,17 @@ public class ResourceServlet extends HttpServlet { } List<String> unqualifiedSearchTerms = new ArrayList<>(); for (String searchTerm : searchTerms) { - if (searchTerm.contains(":") && !searchTerm.startsWith("[")) { + if (searchTerm.contains(":")) { String[] parts = searchTerm.split(":", 2); String parameterKey = parts[0]; if (!knownParameters.contains(parameterKey) || illegalSearchQualifiers.contains(parameterKey)) { - response.sendError(HttpServletResponse.SC_BAD_REQUEST); - return; + if (ipv6AddressPattern.matcher(parameterKey).matches()) { + unqualifiedSearchTerms.add(searchTerm); + } else { + response.sendError(HttpServletResponse.SC_BAD_REQUEST); + return; + } } if (!parameterMap.containsKey(parameterKey)) { String parameterValue = parts[1]; @@ -369,7 +379,7 @@ public class ResourceServlet extends HttpServlet { Pattern.compile("^\$?[0-9a-fA-F]{1,40}$|" /* Hex fingerprint. */ + "^[0-9a-zA-Z+/]{1,27}$|" /* Base64 fingerprint. */ + "^[0-9a-zA-Z\.]{1,19}$|" /* Nickname or IPv4 address. */ - + "^\[[0-9a-fA-F:\.]{1,39}\]?$|" /* IPv6 address. */ + + ipv6AddressPatternString + "|" /* IPv6 address. */ + "^[a-zA-Z_]+:\p{Graph}+$" /* Qualified search term. */);
protected static String[] parseSearchParameters(String queryString) { diff --git a/src/main/java/org/torproject/onionoo/server/ResponseBuilder.java b/src/main/java/org/torproject/onionoo/server/ResponseBuilder.java index e07868a..c9cec32 100644 --- a/src/main/java/org/torproject/onionoo/server/ResponseBuilder.java +++ b/src/main/java/org/torproject/onionoo/server/ResponseBuilder.java @@ -102,9 +102,9 @@ public class ResponseBuilder { return this.charsWritten; }
- private static final String PROTOCOL_VERSION = "3.2"; + private static final String PROTOCOL_VERSION = "4.0";
- private static final String NEXT_MAJOR_VERSION_SCHEDULED = "2017-02-27"; + private static final String NEXT_MAJOR_VERSION_SCHEDULED = null;
private void writeRelays(List<SummaryDocument> relays, PrintWriter pw) { this.write(pw, "{"version":"%s",\n", PROTOCOL_VERSION); diff --git a/src/main/resources/web/index.html b/src/main/resources/web/index.html index 6e863e5..d8fe74a 100644 --- a/src/main/resources/web/index.html +++ b/src/main/resources/web/index.html @@ -346,10 +346,9 @@ characters of a space-separated fingerprint on November 15, 2015.</li> <li><strong>3.2</strong>: Extended order parameter to "first_seen" and added response meta data fields "relays_skipped", "relays_truncated", "bridges_skipped", and "bridges_truncated" on January 27, 2017.</li> -<li><strong>4.0</strong>: (scheduled, but not deployed yet!): Extend -search parameter to not require leading or enclosing square brackets -around IPv6 addresses anymore, to be deployed by February 27, -2017.</li> +<li><strong>4.0</strong>: Extended search parameter to not require +leading or enclosing square brackets around IPv6 addresses anymore on +February 28, 2017.</li> </ul>
@@ -456,7 +455,8 @@ Return only (1) relays with the parameter value matching (part of a) nickname, (possibly $-prefixed) beginning of a hex-encoded fingerprint, any 4 hex characters of a space-separated fingerprint, beginning of a base64-encoded fingerprint without trailing equal signs, or beginning of -an IP address, (2) bridges with (part of a) nickname or (possibly +an IP address (possibly enclosed in square brackets in case of IPv6), +(2) bridges with (part of a) nickname or (possibly $-prefixed) beginning of a hashed hex-encoded fingerprint, and (3) relays and/or bridges matching a given qualified search term. Searches by relay IP address include all known addresses used for onion diff --git a/src/test/java/org/torproject/onionoo/server/ResourceServletTest.java b/src/test/java/org/torproject/onionoo/server/ResourceServletTest.java index e4a9e3d..a28c66b 100644 --- a/src/test/java/org/torproject/onionoo/server/ResourceServletTest.java +++ b/src/test/java/org/torproject/onionoo/server/ResourceServletTest.java @@ -707,6 +707,34 @@ public class ResourceServletTest { }
@Test() + public void testSearchIpv6Slash64NoBrackets() { + this.assertSummaryDocument( + "/summary?search=2001:4f8:3:2e::", 1, + new String[] { "Ferrari458" }, 0, null); + } + + @Test() + public void testSearchIpv6Slash8Colon() { + this.assertSummaryDocument( + "/summary?search=[2001:", 1, + new String[] { "Ferrari458" }, 0, null); + } + + @Test() + public void testSearchIpv6Slash8NoColon() { + this.assertSummaryDocument( + "/summary?search=[2001", 1, + new String[] { "Ferrari458" }, 0, null); + } + + @Test() + public void testSearchIpv6Slash8NoColonNoBrackets() { + this.assertSummaryDocument( + "/summary?search=2001", 1, + new String[] { "Ferrari458" }, 0, null); + } + + @Test() public void testSearchIpv6Uncompressed() { this.assertSummaryDocument( "/summary?search=[2001:04f8:0003:002e:0000:0000:0000:0051]", 0, @@ -887,6 +915,13 @@ public class ResourceServletTest { this.assertErrorStatusCode("/summary?search=limit:1", 400); }
+ @Test() + public void testSearchDeadBeef() { + /* This does not return 400 Bad Request, even though "dead" is not a valid + * search term qualifier, because this could be the start of an IPv6 address + * without leading bracket. */ + this.assertSummaryDocument("/summary?search=dead:beef", 0, null, 0, null); + }
@Test() public void testSearchEmailAddress() {
tor-commits@lists.torproject.org