Add a way to check if a host is an IP address
authorcarlosgc@webkit.org <carlosgc@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 5 Feb 2018 08:04:30 +0000 (08:04 +0000)
committercarlosgc@webkit.org <carlosgc@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 5 Feb 2018 08:04:30 +0000 (08:04 +0000)
https://bugs.webkit.org/show_bug.cgi?id=182427

Reviewed by Alex Christensen.

Source/WebCore:

There are several places where this is needed. We currently just assume that any host ending in a digit is an IP
address, except in PublicSuffix where platform specific code is used. This patch adds URL::hostIsIPAddress()
platform specific implementations, falling back to current assumption if there isn't an implementation for the
platform.

* page/OriginAccessEntry.cpp:
(WebCore::OriginAccessEntry::OriginAccessEntry): Use URL::hostIsIPAddress().
* platform/URL.cpp:
(WebCore::URL::hostIsIPAddress): Fallback implementation.
* platform/URL.h:
* platform/mac/PublicSuffixMac.mm:
(WebCore::topPrivatelyControlledDomain): Use URL::hostIsIPAddress().
* platform/mac/URLMac.mm:
(WebCore::URL::hostIsIPAddress): Move implementation from PublicSuffixMac.mm.
* platform/network/curl/CookieUtil.cpp:
(WebCore::CookieUtil::isIPAddress): Use URL::hostIsIPAddress().
* platform/soup/URLSoup.cpp:
(WebCore::URL::hostIsIPAddress): Use g_hostname_is_ip_address().

Tools:

Add unit test for URL::hostIsIPAddress().

* TestWebKitAPI/Tests/WebCore/URL.cpp:
(TestWebKitAPI::TEST_F):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@228086 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebCore/ChangeLog
Source/WebCore/page/OriginAccessEntry.cpp
Source/WebCore/platform/URL.cpp
Source/WebCore/platform/URL.h
Source/WebCore/platform/mac/PublicSuffixMac.mm
Source/WebCore/platform/mac/URLMac.mm
Source/WebCore/platform/network/curl/CookieUtil.cpp
Source/WebCore/platform/soup/URLSoup.cpp
Tools/ChangeLog
Tools/TestWebKitAPI/Tests/WebCore/URL.cpp

index e9ecb6b..d04ba35 100644 (file)
@@ -1,3 +1,29 @@
+2018-02-05  Carlos Garcia Campos  <cgarcia@igalia.com>
+
+        Add a way to check if a host is an IP address
+        https://bugs.webkit.org/show_bug.cgi?id=182427
+
+        Reviewed by Alex Christensen.
+
+        There are several places where this is needed. We currently just assume that any host ending in a digit is an IP
+        address, except in PublicSuffix where platform specific code is used. This patch adds URL::hostIsIPAddress()
+        platform specific implementations, falling back to current assumption if there isn't an implementation for the
+        platform.
+
+        * page/OriginAccessEntry.cpp:
+        (WebCore::OriginAccessEntry::OriginAccessEntry): Use URL::hostIsIPAddress().
+        * platform/URL.cpp:
+        (WebCore::URL::hostIsIPAddress): Fallback implementation.
+        * platform/URL.h:
+        * platform/mac/PublicSuffixMac.mm:
+        (WebCore::topPrivatelyControlledDomain): Use URL::hostIsIPAddress().
+        * platform/mac/URLMac.mm:
+        (WebCore::URL::hostIsIPAddress): Move implementation from PublicSuffixMac.mm.
+        * platform/network/curl/CookieUtil.cpp:
+        (WebCore::CookieUtil::isIPAddress): Use URL::hostIsIPAddress().
+        * platform/soup/URLSoup.cpp:
+        (WebCore::URL::hostIsIPAddress): Use g_hostname_is_ip_address().
+
 2018-02-04  Zan Dobersek  <zdobersek@igalia.com>
 
         [Cairo] Correctly calculate stride in GraphicsContext3D::paintToCanvas()
index 8472d38..376104e 100644 (file)
@@ -40,11 +40,9 @@ OriginAccessEntry::OriginAccessEntry(const String& protocol, const String& host,
     , m_host(host.convertToASCIILowercase())
     , m_subdomainSettings(subdomainSetting)
     , m_ipAddressSettings(ipAddressSetting)
+    , m_hostIsIPAddress(URL::hostIsIPAddress(m_host))
 {
     ASSERT(subdomainSetting == AllowSubdomains || subdomainSetting == DisallowSubdomains);
-
-    // Assume that any host that ends with a digit is trying to be an IP address.
-    m_hostIsIPAddress = !m_host.isEmpty() && isASCIIDigit(m_host[m_host.length() - 1]);
 }
 
 bool OriginAccessEntry::matchesOrigin(const SecurityOrigin& origin) const
@@ -69,7 +67,7 @@ bool OriginAccessEntry::matchesOrigin(const SecurityOrigin& origin) const
 
     // IP addresses are not domains: https://url.spec.whatwg.org/#concept-domain
     // Don't try to do subdomain matching on IP addresses.
-    if (m_hostIsIPAddress && m_ipAddressSettings == TreatIPAddressAsIPAddress)
+    if (m_ipAddressSettings == TreatIPAddressAsIPAddress && (m_hostIsIPAddress || URL::hostIsIPAddress(origin.host())))
         return false;
     
     // Match subdomains.
index a5a37ad..597a56c 100644 (file)
@@ -1035,4 +1035,12 @@ TextStream& operator<<(TextStream& ts, const URL& url)
     return ts;
 }
 
+#if !PLATFORM(COCOA) && !USE(SOUP)
+bool URL::hostIsIPAddress(const String& host)
+{
+    // Assume that any host that ends with a digit is trying to be an IP address.
+    return !host.isEmpty() && isASCIIDigit(host[host.length() - 1]);
+}
+#endif
+
 } // namespace WebCore
index ddd97e9..c196745 100644 (file)
@@ -175,6 +175,8 @@ public:
     unsigned hostStart() const;
     unsigned hostEnd() const;
 
+    WEBCORE_EXPORT static bool hostIsIPAddress(const String&);
+
     unsigned pathStart() const;
     unsigned pathEnd() const;
     unsigned pathAfterLastSlash() const;
index 81380cc..44b15f0 100644 (file)
 
 #if ENABLE(PUBLIC_SUFFIX_LIST)
 
-#import "WebCoreNSURLExtras.h"
+#import "URL.h"
 #import <pal/spi/cf/CFNetworkSPI.h>
 
-@interface NSString (WebCoreNSURLExtras)
-- (BOOL)_web_looksLikeIPAddress;
-@end
-
 namespace WebCore {
 
 bool isPublicSuffix(const String& domain)
@@ -45,7 +41,7 @@ bool isPublicSuffix(const String& domain)
 
 String topPrivatelyControlledDomain(const String& domain)
 {
-    if ([domain _web_looksLikeIPAddress])
+    if (URL::hostIsIPAddress(domain))
         return domain;
 
     if (!domain.isAllASCII())
index 7299cb0..fc5c46d 100644 (file)
 
 #import "CFURLExtras.h"
 #import "URLParser.h"
+#import "WebCoreNSURLExtras.h"
 #import <wtf/ObjcRuntimeExtras.h>
 #import <wtf/text/CString.h>
 
+@interface NSString (WebCoreNSURLExtras)
+- (BOOL)_web_looksLikeIPAddress;
+@end
+
 namespace WebCore {
 
 URL::URL(NSURL *url)
@@ -74,4 +79,9 @@ RetainPtr<CFURLRef> URL::createCFURL() const
     return createCFURLFromBuffer(buffer.data(), buffer.size());
 }
 
+bool URL::hostIsIPAddress(const String& host)
+{
+    return [host _web_looksLikeIPAddress];
+}
+
 }
index 955e5d1..d62fdbd 100644 (file)
@@ -53,8 +53,7 @@ namespace CookieUtil {
 
 bool isIPAddress(const String& hostname)
 {
-    // Assuming that hosts ending in a digit are IP Addresses
-    return !hostname.isEmpty() && isASCIIDigit(hostname[hostname.length() - 1]);
+    return URL::hostIsIPAddress(hostname);
 }
 
 bool domainMatch(const String& cookieDomain, const String& host)
index f9f0d4b..fc289ce 100644 (file)
@@ -66,6 +66,11 @@ GUniquePtr<SoupURI> URL::createSoupURI() const
     return GUniquePtr<SoupURI>(soup_uri_new(string().utf8().data()));
 }
 
+bool URL::hostIsIPAddress(const String& host)
+{
+    return !host.isEmpty() && g_hostname_is_ip_address(host.utf8().data());
+}
+
 } // namespace WebCore
 
 #endif
index fe6b418..9778300 100644 (file)
@@ -1,3 +1,15 @@
+2018-02-05  Carlos Garcia Campos  <cgarcia@igalia.com>
+
+        Add a way to check if a host is an IP address
+        https://bugs.webkit.org/show_bug.cgi?id=182427
+
+        Reviewed by Alex Christensen.
+
+        Add unit test for URL::hostIsIPAddress().
+
+        * TestWebKitAPI/Tests/WebCore/URL.cpp:
+        (TestWebKitAPI::TEST_F):
+
 2018-02-03  Charlie Turner  <cturner@igalia.com>
 
         Add libmount to WPE dependencies
index dd09e82..cc66e60 100644 (file)
@@ -231,4 +231,34 @@ TEST_F(URLTest, ProtocolIsInHTTPFamily)
     EXPECT_TRUE(protocolIsInHTTPFamily("https://!@#$%^&*()"));
 }
 
+TEST_F(URLTest, HostIsIPAddress)
+{
+    EXPECT_FALSE(URL::hostIsIPAddress({ }));
+    EXPECT_FALSE(URL::hostIsIPAddress(""));
+    EXPECT_FALSE(URL::hostIsIPAddress("localhost"));
+    EXPECT_FALSE(URL::hostIsIPAddress("127.localhost"));
+    EXPECT_FALSE(URL::hostIsIPAddress("localhost.127"));
+    EXPECT_FALSE(URL::hostIsIPAddress("127.0.0"));
+    EXPECT_FALSE(URL::hostIsIPAddress("127.0 .0.1"));
+    EXPECT_FALSE(URL::hostIsIPAddress(" 127.0.0.1"));
+    EXPECT_FALSE(URL::hostIsIPAddress("127..0.0.1"));
+    EXPECT_FALSE(URL::hostIsIPAddress("127.0.0."));
+    EXPECT_FALSE(URL::hostIsIPAddress("0123:4567:89AB:cdef:3210:7654:ba98"));
+    EXPECT_FALSE(URL::hostIsIPAddress("012x:4567:89AB:cdef:3210:7654:ba98:FeDc"));
+    EXPECT_FALSE(URL::hostIsIPAddress("00123:4567:89AB:cdef:3210:7654:ba98:FeDc"));
+    EXPECT_FALSE(URL::hostIsIPAddress("0123:4567:89AB:cdef:3210:123.45.67.89"));
+    EXPECT_FALSE(URL::hostIsIPAddress(":::"));
+
+    EXPECT_TRUE(URL::hostIsIPAddress("127.0.0.1"));
+    EXPECT_TRUE(URL::hostIsIPAddress("123.45.67.89"));
+    EXPECT_TRUE(URL::hostIsIPAddress("0.0.0.0"));
+    EXPECT_TRUE(URL::hostIsIPAddress("::1"));
+    EXPECT_TRUE(URL::hostIsIPAddress("::"));
+    EXPECT_TRUE(URL::hostIsIPAddress("0123:4567:89AB:cdef:3210:7654:ba98:FeDc"));
+    EXPECT_TRUE(URL::hostIsIPAddress("0123:4567:89AB:cdef:3210:7654:ba98::"));
+    EXPECT_TRUE(URL::hostIsIPAddress("::4567:89AB:cdef:3210:7654:ba98:FeDc"));
+    EXPECT_TRUE(URL::hostIsIPAddress("0123:4567:89AB:cdef:3210:7654:123.45.67.89"));
+    EXPECT_TRUE(URL::hostIsIPAddress("::123.45.67.89"));
+}
+
 } // namespace TestWebKitAPI