[tor-commits] [onionoo/master] Don't require searches by IPv6 address to start with [.

karsten at torproject.org karsten at torproject.org
Tue Feb 28 08:21:39 UTC 2017


commit 723e71a09ea6bfb8ebc4d4b40b51c2ff0aebd510
Author: Karsten Loesing <karsten.loesing at 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() {



More information about the tor-commits mailing list