Author: [email protected]
Date: Mon Mar 16 11:18:25 2009
New Revision: 5018

Modified:
    trunk/dev/core/src/com/google/gwt/dev/shell/BrowserWidgetHostChecker.java
    trunk/dev/core/test/com/google/gwt/dev/GWTShellTest.java
    trunk/dev/core/test/com/google/gwt/dev/HostedModeTest.java

Log:
Add host name/address to automatically generated whitelist, improve handling
of these regexes.

Patch by: jat
Review by: scottb


Modified:  
trunk/dev/core/src/com/google/gwt/dev/shell/BrowserWidgetHostChecker.java
==============================================================================
---  
trunk/dev/core/src/com/google/gwt/dev/shell/BrowserWidgetHostChecker.java       
 
(original)
+++  
trunk/dev/core/src/com/google/gwt/dev/shell/BrowserWidgetHostChecker.java       
 
Mon Mar 16 11:18:25 2009
@@ -17,6 +17,8 @@

  import com.google.gwt.core.ext.TreeLogger;

+import java.net.InetAddress;
+import java.net.UnknownHostException;
  import java.util.HashSet;
  import java.util.Iterator;
  import java.util.Set;
@@ -31,7 +33,7 @@
    /**
     * The set of always allowed URLs, which are immune to blacklisting.
     */
-  private static final Set<String> alwaysValidHttpHosts = new  
HashSet<String>();
+  private static final Pattern alwaysValidHttpHosts;

    /**
     * The set of blacklisted URLs.
@@ -48,19 +50,49 @@
    private static final Set<String> validHttpHosts = new HashSet<String>();

    static {
-    alwaysValidHttpHosts.add("^https?://localhost");
-    alwaysValidHttpHosts.add("^file:");
-    alwaysValidHttpHosts.add("^about:");
-    alwaysValidHttpHosts.add("^res:");
-    alwaysValidHttpHosts.add("^javascript:");
-    alwaysValidHttpHosts.add("^([a-zA-Z][:])[/\\\\]");
+    Set<String> regexes = new HashSet<String>();
+    // Regular URLs may or may not have a port, and must either end with
+    // the host+port, or be followed by a slash (to avoid attacks like
+    // localhost.evildomain.org).
+    String portSuffix = "(:\\d+)?(/.*)?";
+    regexes.add("https?://localhost" + portSuffix);
+    regexes.add("https?://localhost[.]localdomain" + portSuffix);
+    regexes.add("https?://127[.]0[.]0[.]1" + portSuffix);
+    String hostName;
+    try {
+      hostName = InetAddress.getLocalHost().getHostName();
+      if (hostName != null) {
+        hostName = hostName.replace(".", "[.]");
+        regexes.add("https?://" + hostName + portSuffix);
+      }
+    } catch (UnknownHostException e) {
+      // Ignore
+    }
+    String addr;
+    try {
+      addr = InetAddress.getLocalHost().getHostAddress();
+      if (addr != null) {
+        addr = addr.replace(".", "[.]");
+        regexes.add("https?://" + addr + portSuffix);
+      }
+    } catch (UnknownHostException e) {
+      // Ignore
+    }
+    regexes.add("file:.*");
+    regexes.add("about:.*");
+    regexes.add("res:.*");
+    regexes.add("javascript:.*");
+    regexes.add("([a-z][:])[/\\\\].*");
      // matches c:\ and c:/
-    alwaysValidHttpHosts.add("^https?://localhost/");
-    alwaysValidHttpHosts.add("^https?://localhost[.]localdomain/");
-    alwaysValidHttpHosts.add("^https?://127[.]0[.]0[.]1/");
-    alwaysValidHttpHosts.add("^https?://localhost$");
-    alwaysValidHttpHosts.add("^https?://localhost[.]localdomain$");
-    alwaysValidHttpHosts.add("^https?://127[.]0[.]0[.]1$");
+    StringBuilder buf = new StringBuilder();
+    String prefix = "(";
+    for (String regex : regexes) {
+      buf.append(prefix).append('(').append(regex).append(')');
+      prefix = "|";
+    }
+    buf.append(")");
+    alwaysValidHttpHosts = Pattern.compile(buf.toString(),
+        Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE);
    }

    /**
@@ -90,9 +122,10 @@
     * @return true if the host matches
     */
    public static String checkHost(String hostUnderConsideration,  
Set<String> hosts) {
+    // TODO(jat): build a single regex instead of looping
      hostUnderConsideration = hostUnderConsideration.toLowerCase();
-    for (Iterator<String> i = hosts.iterator(); i.hasNext();) {
-      String rule = i.next().toString().toLowerCase();
+    for (String rule : hosts) {
+      rule = rule.toLowerCase();
        // match on lowercased regex
        if (hostUnderConsideration.matches(".*" + rule + ".*")) {
          return rule;
@@ -149,20 +182,18 @@
    }

    /**
-   * This method returns true if the host is always admissable, regardless  
of
+   * This method returns true if the host is always admissible, regardless  
of
     * the blacklist.
     *
     * @param url the URL to be verified
-   * @return returns true if the host is always admissable
+   * @return returns true if the host is always admissible
     */
    public static boolean isAlwaysWhitelisted(String url) {
-    String whitelistRuleFound;
-    whitelistRuleFound = checkHost(url, alwaysValidHttpHosts);
-    return whitelistRuleFound != null;
+    return alwaysValidHttpHosts.matcher(url).matches();
    }

    /**
-   * This method returns true if the host is forbidden.
+   * This method returns non-null if the host is forbidden.
     *
     * @param url the URL to be verified
     * @return returns the regex that specified the host matches the  
blacklist
@@ -173,7 +204,7 @@
    }

    /**
-   * This method returns true if the host is admissable, provided it is  
not on
+   * This method returns null if the host is admissible, provided it is  
not on
     * the blacklist.
     *
     * @param url the URL to be verified

Modified: trunk/dev/core/test/com/google/gwt/dev/GWTShellTest.java
==============================================================================
--- trunk/dev/core/test/com/google/gwt/dev/GWTShellTest.java    (original)
+++ trunk/dev/core/test/com/google/gwt/dev/GWTShellTest.java    Mon Mar 16  
11:18:25 2009
@@ -44,6 +44,21 @@

      assertNotNull(BrowserWidgetHostChecker.matchWhitelisted("white"));
      assertNotNull(BrowserWidgetHostChecker.matchBlacklisted("black"));
+     
assertFalse(BrowserWidgetHostChecker.isAlwaysWhitelisted("http://127.0.0.1.40";));
+     
assertFalse(BrowserWidgetHostChecker.isAlwaysWhitelisted("http://127.0.0.1.40:88";));
+     
assertFalse(BrowserWidgetHostChecker.isAlwaysWhitelisted("http://127.0.0.1.40:88/";));
+     
assertFalse(BrowserWidgetHostChecker.isAlwaysWhitelisted("http://127.0.0.1.40:88/foo";));
+     
assertFalse(BrowserWidgetHostChecker.isAlwaysWhitelisted("http://localhost.evildomain.org";));
+     
assertFalse(BrowserWidgetHostChecker.isAlwaysWhitelisted("http://localhost.evildomain.org:88";));
+     
assertFalse(BrowserWidgetHostChecker.isAlwaysWhitelisted("http://localhost.evildomain.org:88/";));
+     
assertFalse(BrowserWidgetHostChecker.isAlwaysWhitelisted("http://localhost.evildomain.org:88/foo";));
+     
assertFalse(BrowserWidgetHostChecker.isAlwaysWhitelisted("http://localhost.evildomain.org/";));
+     
assertFalse(BrowserWidgetHostChecker.isAlwaysWhitelisted("http://localhost.evildomain.org/foo";));
+     
assertFalse(BrowserWidgetHostChecker.isAlwaysWhitelisted("http://www.evildomain.org/foo?http://localhost";));
+     
assertTrue(BrowserWidgetHostChecker.isAlwaysWhitelisted("http://127.0.0.1";));
+     
assertTrue(BrowserWidgetHostChecker.isAlwaysWhitelisted("http://127.0.0.1:88";));
+     
assertTrue(BrowserWidgetHostChecker.isAlwaysWhitelisted("http://127.0.0.1:88/";));
+     
assertTrue(BrowserWidgetHostChecker.isAlwaysWhitelisted("http://127.0.0.1:88/foo";));

      assertEquals(new File("myGen").getAbsoluteFile(),
          options.getGenDir().getAbsoluteFile());

Modified: trunk/dev/core/test/com/google/gwt/dev/HostedModeTest.java
==============================================================================
--- trunk/dev/core/test/com/google/gwt/dev/HostedModeTest.java  (original)
+++ trunk/dev/core/test/com/google/gwt/dev/HostedModeTest.java  Mon Mar 16  
11:18:25 2009
@@ -31,7 +31,9 @@
  public class HostedModeTest extends ArgProcessorTestBase {

    public static class MySCL extends ServletContainerLauncher {
-    public ServletContainer start(TreeLogger logger, int port, File  
appRootDir)
+    @Override
+    public ServletContainer start(TreeLogger logger, String bindAddr, int  
port,
+        File appRootDir)
          throws BindException, Exception {
        throw new UnsupportedOperationException();
      }
@@ -55,6 +57,21 @@

      assertNotNull(BrowserWidgetHostChecker.matchWhitelisted("white"));
      assertNotNull(BrowserWidgetHostChecker.matchBlacklisted("black"));
+     
assertFalse(BrowserWidgetHostChecker.isAlwaysWhitelisted("http://127.0.0.1.40";));
+     
assertFalse(BrowserWidgetHostChecker.isAlwaysWhitelisted("http://127.0.0.1.40:88";));
+     
assertFalse(BrowserWidgetHostChecker.isAlwaysWhitelisted("http://127.0.0.1.40:88/";));
+     
assertFalse(BrowserWidgetHostChecker.isAlwaysWhitelisted("http://127.0.0.1.40:88/foo";));
+     
assertFalse(BrowserWidgetHostChecker.isAlwaysWhitelisted("http://localhost.evildomain.org";));
+     
assertFalse(BrowserWidgetHostChecker.isAlwaysWhitelisted("http://localhost.evildomain.org:88";));
+     
assertFalse(BrowserWidgetHostChecker.isAlwaysWhitelisted("http://localhost.evildomain.org:88/";));
+     
assertFalse(BrowserWidgetHostChecker.isAlwaysWhitelisted("http://localhost.evildomain.org:88/foo";));
+     
assertFalse(BrowserWidgetHostChecker.isAlwaysWhitelisted("http://localhost.evildomain.org/";));
+     
assertFalse(BrowserWidgetHostChecker.isAlwaysWhitelisted("http://localhost.evildomain.org/foo";));
+     
assertFalse(BrowserWidgetHostChecker.isAlwaysWhitelisted("http://www.evildomain.org/foo?http://localhost";));
+     
assertTrue(BrowserWidgetHostChecker.isAlwaysWhitelisted("http://127.0.0.1";));
+     
assertTrue(BrowserWidgetHostChecker.isAlwaysWhitelisted("http://127.0.0.1:88";));
+     
assertTrue(BrowserWidgetHostChecker.isAlwaysWhitelisted("http://127.0.0.1:88/";));
+     
assertTrue(BrowserWidgetHostChecker.isAlwaysWhitelisted("http://127.0.0.1:88/foo";));

      assertEquals(new File("myGen").getAbsoluteFile(),
          options.getGenDir().getAbsoluteFile());

--~--~---------~--~----~------------~-------~--~----~
http://groups.google.com/group/Google-Web-Toolkit-Contributors
-~----------~----~----~----~------~----~------~--~---

Reply via email to