2010-03-12 Jochen Eisinger <jochen@chromium.org>
authoreric@webkit.org <eric@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 12 Mar 2010 14:06:31 +0000 (14:06 +0000)
committereric@webkit.org <eric@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 12 Mar 2010 14:06:31 +0000 (14:06 +0000)
        Reviewed by Jeremy Orlow.

        Test for referrer information being stripped when the header is removed in willSendRequest
        https://bugs.webkit.org/show_bug.cgi?id=35920

        * http/tests/security/no-referrer-expected.txt: Added.
        * http/tests/security/no-referrer.html: Added.
        * http/tests/security/resources/no-referrer-frame.php: Added.
        * http/tests/security/resources/no-referrer.php: Added.
        * platform/gtk/Skipped:
        * platform/qt/Skipped:
2010-03-12  Jochen Eisinger  <jochen@chromium.org>

        Reviewed by Jeremy Orlow.

        Introduce setWillSendRequestClearHeader to LayoutTestController to selectively remove headers in willSendRequest. Used in http/tests/security/no-referrer.html
        https://bugs.webkit.org/show_bug.cgi?id=35920

        * DumpRenderTree/LayoutTestController.cpp:
        (setWillSendRequestClearHeaderCallback):
        (LayoutTestController::staticFunctions):
        * DumpRenderTree/LayoutTestController.h:
        (LayoutTestController::willSendRequestClearHeaders):
        (LayoutTestController::setWillSendRequestClearHeader):
        * DumpRenderTree/mac/ResourceLoadDelegate.mm:
        (-[ResourceLoadDelegate webView:resource:willSendRequest:redirectResponse:fromDataSource:]):
        * DumpRenderTree/win/ResourceLoadDelegate.cpp:
        (ResourceLoadDelegate::willSendRequest):

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

12 files changed:
LayoutTests/ChangeLog
LayoutTests/http/tests/security/no-referrer-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/security/no-referrer.html [new file with mode: 0644]
LayoutTests/http/tests/security/resources/no-referrer-frame.php [new file with mode: 0644]
LayoutTests/http/tests/security/resources/no-referrer.php [new file with mode: 0644]
LayoutTests/platform/gtk/Skipped
LayoutTests/platform/qt/Skipped
WebKitTools/ChangeLog
WebKitTools/DumpRenderTree/LayoutTestController.cpp
WebKitTools/DumpRenderTree/LayoutTestController.h
WebKitTools/DumpRenderTree/mac/ResourceLoadDelegate.mm
WebKitTools/DumpRenderTree/win/ResourceLoadDelegate.cpp

index a888bb8..8554197 100644 (file)
@@ -1,3 +1,17 @@
+2010-03-12  Jochen Eisinger  <jochen@chromium.org>
+
+        Reviewed by Jeremy Orlow.
+
+        Test for referrer information being stripped when the header is removed in willSendRequest
+        https://bugs.webkit.org/show_bug.cgi?id=35920
+
+        * http/tests/security/no-referrer-expected.txt: Added.
+        * http/tests/security/no-referrer.html: Added.
+        * http/tests/security/resources/no-referrer-frame.php: Added.
+        * http/tests/security/resources/no-referrer.php: Added.
+        * platform/gtk/Skipped:
+        * platform/qt/Skipped:
+
 2010-03-12  Nikolas Zimmermann  <nzimmermann@rim.com>
 
         Rubber-stamped by Dirk Schulze.
diff --git a/LayoutTests/http/tests/security/no-referrer-expected.txt b/LayoutTests/http/tests/security/no-referrer-expected.txt
new file mode 100644 (file)
index 0000000..6ab01dc
--- /dev/null
@@ -0,0 +1,8 @@
+JavaScript: PASS
+HTTP Referer: PASS
+External script (HTTP Referer): PASS
+External script (JavaScript): PASS
+Sync XHR: PASS
+ASync XHR: PASS
+DONE
+
diff --git a/LayoutTests/http/tests/security/no-referrer.html b/LayoutTests/http/tests/security/no-referrer.html
new file mode 100644 (file)
index 0000000..c5f63fb
--- /dev/null
@@ -0,0 +1,9 @@
+<script>
+if (window.layoutTestController) {
+    layoutTestController.waitUntilDone();
+    layoutTestController.dumpAsText();
+    layoutTestController.setWillSendRequestClearHeader("Referer");
+}
+</script>
+<div id=log></div>
+<iframe src="http://127.0.0.1:8000/security/resources/no-referrer-frame.php"></iframe>
diff --git a/LayoutTests/http/tests/security/resources/no-referrer-frame.php b/LayoutTests/http/tests/security/resources/no-referrer-frame.php
new file mode 100644 (file)
index 0000000..115c234
--- /dev/null
@@ -0,0 +1,39 @@
+<script>
+function log(message)
+{
+    parent.document.getElementById("log").innerHTML += message + "<br>";
+}
+
+if (document.referrer.toString() != "") {
+  log("JavaScript: FAIL");
+} else {
+  log("JavaScript: PASS");
+}
+
+<?php
+$refer = $_SERVER['HTTP_REFERER'];
+if ($refer && $refer != "")
+    print("log('HTTP Referer: FAIL')");
+else
+    print("log('HTTP Referer: PASS')");
+?>
+
+window.onload = function() {
+    var xhr = new XMLHttpRequest;
+    xhr.open("GET", "no-referrer.php", false);
+    xhr.send(null);
+    log("Sync XHR: " + (xhr.responseText.match(/HTTP.*FAIL/) ? "FAIL" : "PASS"));
+    xhr.open("GET", "no-referrer.php", true);
+    xhr.send(null);
+    xhr.onload = onXHRLoad;
+}
+
+function onXHRLoad(evt)
+{
+    log("ASync XHR: " + (evt.target.responseText.match(/HTTP.*FAIL/) ? "FAIL" : "PASS"));
+    log("DONE");
+    if (window.layoutTestController)
+        layoutTestController.notifyDone();
+}
+</script>
+<script src="no-referrer.php"></script>
diff --git a/LayoutTests/http/tests/security/resources/no-referrer.php b/LayoutTests/http/tests/security/resources/no-referrer.php
new file mode 100644 (file)
index 0000000..b0fd8ca
--- /dev/null
@@ -0,0 +1,13 @@
+<?php
+header("Cache: no-cache, no-store");
+
+$refer = $_SERVER['HTTP_REFERER'];
+if ($refer && $refer != "")
+    print("log('External script (HTTP Referer): FAIL');\n");
+else
+    print("log('External script (HTTP Referer): PASS');\n");
+?>
+if (document.referrer.toString() != "")
+    log('External script (JavaScript): FAIL');
+else
+    log('External script (JavaScript): PASS');
index 6e49f01..39790b2 100644 (file)
@@ -5676,6 +5676,9 @@ fast/css/non-standard-checkbox-size.html
 # https://bugs.webkit.org/show_bug.cgi?id=33671
 media/video-loop.html
 
+# GTK+ does not have layoutTestController.setWillSendRequestClearHeader.
+http/tests/security/no-referrer.html
+
 # GTK+ does not have layoutTestController.setWillSendRequestReturnsNull.
 fast/loader/onload-willSendRequest-null-for-script.html
 
index 481c27e..6217152 100644 (file)
@@ -199,6 +199,9 @@ http/tests/misc/policy-delegate-called-twice.html
 http/tests/misc/redirect-to-external-url.html
 http/tests/security/feed-urls-from-remote.html
 
+# Missing layoutTestController.setWillSendRequestClearHeader()
+http/tests/security/no-referrer.html
+
 # Missing layoutTestController.setWillSendRequestReturnsNull()
 fast/loader/onload-willSendRequest-null-for-frame.html
 fast/loader/onload-willSendRequest-null-for-script.html
index 8378248..214b17b 100644 (file)
@@ -1,3 +1,21 @@
+2010-03-12  Jochen Eisinger  <jochen@chromium.org>
+
+        Reviewed by Jeremy Orlow.
+
+        Introduce setWillSendRequestClearHeader to LayoutTestController to selectively remove headers in willSendRequest. Used in http/tests/security/no-referrer.html
+        https://bugs.webkit.org/show_bug.cgi?id=35920
+
+        * DumpRenderTree/LayoutTestController.cpp:
+        (setWillSendRequestClearHeaderCallback):
+        (LayoutTestController::staticFunctions):
+        * DumpRenderTree/LayoutTestController.h:
+        (LayoutTestController::willSendRequestClearHeaders):
+        (LayoutTestController::setWillSendRequestClearHeader):
+        * DumpRenderTree/mac/ResourceLoadDelegate.mm:
+        (-[ResourceLoadDelegate webView:resource:willSendRequest:redirectResponse:fromDataSource:]):
+        * DumpRenderTree/win/ResourceLoadDelegate.cpp:
+        (ResourceLoadDelegate::willSendRequest):
+
 2010-03-11  Fumitoshi Ukai  <ukai@chromium.org>
 
         Unreviewed.
index 43a7a73..a9ebe81 100644 (file)
@@ -1023,6 +1023,25 @@ static JSValueRef setUserStyleSheetLocationCallback(JSContextRef context, JSObje
     return JSValueMakeUndefined(context);
 }
 
+static JSValueRef setWillSendRequestClearHeaderCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+    // Has mac & windows implementation
+    if (argumentCount < 1)
+        return JSValueMakeUndefined(context);
+
+    JSRetainPtr<JSStringRef> header(Adopt, JSValueToStringCopy(context, arguments[0], exception));
+    ASSERT(!*exception);
+
+    size_t maxLength = JSStringGetMaximumUTF8CStringSize(header.get());
+    char* headerBuffer = new char[maxLength + 1];
+    JSStringGetUTF8CString(header.get(), headerBuffer, maxLength + 1);
+
+    LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
+    controller->setWillSendRequestClearHeader(headerBuffer);
+
+    return JSValueMakeUndefined(context);
+}
+
 static JSValueRef setWillSendRequestReturnsNullCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
 {
     // Has cross-platform implementation
@@ -1463,6 +1482,7 @@ JSStaticFunction* LayoutTestController::staticFunctions()
         { "setUseDashboardCompatibilityMode", setUseDashboardCompatibilityModeCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
         { "setUserStyleSheetEnabled", setUserStyleSheetEnabledCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
         { "setUserStyleSheetLocation", setUserStyleSheetLocationCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+        { "setWillSendRequestClearHeader", setWillSendRequestClearHeaderCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
         { "setWillSendRequestReturnsNull", setWillSendRequestReturnsNullCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
         { "setWillSendRequestReturnsNullOnRedirect", setWillSendRequestReturnsNullOnRedirectCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
         { "setWindowIsKey", setWindowIsKeyCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
index 19a03a3..72e10d2 100644 (file)
 
 #include <JavaScriptCore/JSObjectRef.h>
 #include <JavaScriptCore/JSRetainPtr.h>
-#include <wtf/RefCounted.h>
+#include <set>
 #include <string>
 #include <vector>
+#include <wtf/RefCounted.h>
 
 class LayoutTestController : public RefCounted<LayoutTestController> {
 public:
@@ -186,6 +187,9 @@ public:
     void setWaitToDump(bool waitToDump);
     void waitToDumpWatchdogTimerFired();
 
+    const std::set<std::string>& willSendRequestClearHeaders() const { return m_willSendRequestClearHeaders; }
+    void setWillSendRequestClearHeader(std::string header) { m_willSendRequestClearHeaders.insert(header); }
+
     bool willSendRequestReturnsNull() const { return m_willSendRequestReturnsNull; }
     void setWillSendRequestReturnsNull(bool returnsNull) { m_willSendRequestReturnsNull = returnsNull; }
 
@@ -284,6 +288,8 @@ private:
     std::string m_authenticationPassword; 
     std::string m_testPathOrURL;
     std::string m_expectedPixelHash;    // empty string if no hash
+
+    std::set<std::string> m_willSendRequestClearHeaders;
     
     // origins which have been granted desktop notification access
     std::vector<JSStringRef> m_desktopNotificationAllowedOrigins;
index 6f82e01..9244110 100644 (file)
@@ -35,6 +35,8 @@
 #import <WebKit/WebTypesInternal.h>
 #import <wtf/Assertions.h>
 
+using namespace std;
+
 @interface NSURL (DRTExtras)
 - (NSString *)_drt_descriptionSuitableForTestResult;
 @end
     return @"<unknown>";
 }
 
--(NSURLRequest *)webView: (WebView *)wv resource:identifier willSendRequest: (NSURLRequest *)newRequest redirectResponse:(NSURLResponse *)redirectResponse fromDataSource:(WebDataSource *)dataSource
+-(NSURLRequest *)webView: (WebView *)wv resource:identifier willSendRequest: (NSURLRequest *)request redirectResponse:(NSURLResponse *)redirectResponse fromDataSource:(WebDataSource *)dataSource
 {
     if (!done && gLayoutTestController->dumpResourceLoadCallbacks()) {
-        NSString *string = [NSString stringWithFormat:@"%@ - willSendRequest %@ redirectResponse %@", identifier, [newRequest _drt_descriptionSuitableForTestResult],
+        NSString *string = [NSString stringWithFormat:@"%@ - willSendRequest %@ redirectResponse %@", identifier, [request _drt_descriptionSuitableForTestResult],
             [redirectResponse _drt_descriptionSuitableForTestResult]];
         printf("%s\n", [string UTF8String]);
     }
         return nil;
     }
 
-    NSURL *url = [newRequest URL];
+    NSURL *url = [request URL];
     NSString *host = [url host];
     if (host
         && (NSOrderedSame == [[url scheme] caseInsensitiveCompare:@"http"] || NSOrderedSame == [[url scheme] caseInsensitiveCompare:@"https"])
     if (disallowedURLs && CFSetContainsValue(disallowedURLs, url))
         return nil;
 
-    return newRequest;
+    NSMutableURLRequest *newRequest = [request mutableCopy];
+    const set<string>& clearHeaders = gLayoutTestController->willSendRequestClearHeaders();
+    for (set<string>::const_iterator header = clearHeaders.begin(); header != clearHeaders.end(); ++header) {
+        NSString *nsHeader = [[NSString alloc] initWithUTF8String:header->c_str()];
+        [newRequest setValue:nil forHTTPHeaderField:nsHeader];
+        [nsHeader release];
+    }
+
+    return [newRequest autorelease];
 }
 
 - (void)webView:(WebView *)wv resource:(id)identifier didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge fromDataSource:(WebDataSource *)dataSource
index 19bf84a..2e031da 100644 (file)
 
 #include "DumpRenderTree.h"
 #include "LayoutTestController.h"
-#include <comutil.h>
 #include <WebKit/WebKitCOMAPI.h>
+#include <comutil.h>
+#include <sstream>
+#include <tchar.h>
 #include <wtf/HashMap.h>
 #include <wtf/Vector.h>
-#include <sstream>
-
 
-using std::wstring;
-using std::wiostream;
+using namespace std;
 
 static inline wstring wstringFromBSTR(BSTR str)
 {
     return wstring(str, ::SysStringLen(str));
 }
 
-wstring wstringFromInt(int i)
+static inline wstring wstringFromInt(int i)
 {
-    std::wostringstream ss;
+    wostringstream ss;
     ss << i;
     return ss.str();
 }
 
+static inline BSTR BSTRFromString(const string& str)
+{
+    int length = ::MultiByteToWideChar(CP_UTF8, 0, str.c_str(), str.length(), 0, 0);
+    BSTR result = ::SysAllocStringLen(0, length);
+    ::MultiByteToWideChar(CP_UTF8, 0, str.c_str(), str.length(), result, length);
+    return result;
+}
+
 typedef HashMap<unsigned long, wstring> IdentifierMap;
 
 IdentifierMap& urlMap()
@@ -254,8 +261,16 @@ HRESULT STDMETHODCALLTYPE ResourceLoadDelegate::willSendRequest(
         return S_OK;
     }
 
-    request->AddRef();
-    *newRequest = request;
+    IWebMutableURLRequest* requestCopy = 0;
+    request->mutableCopy(&requestCopy);
+    const set<string>& clearHeaders = gLayoutTestController->willSendRequestClearHeaders();
+    for (set<string>::const_iterator header = clearHeaders.begin(); header != clearHeaders.end(); ++header) {
+      BSTR bstrHeader = BSTRFromString(*header);
+      requestCopy->setValue(0, bstrHeader);
+      SysFreeString(bstrHeader);
+    }
+
+    *newRequest = requestCopy;
     return S_OK;
 }