From bc5f3af068245b096d6c57ebb5c997662248bb94 Mon Sep 17 00:00:00 2001 From: "dwitte@stanford.edu" Date: Wed, 12 Mar 2008 00:53:50 -0700 Subject: [PATCH] Bug 421494 - reimplement third party cookie blocking. r=mconnor, sr=bz, blocking1.9+ --- extensions/cookie/Makefile.in | 7 ++ extensions/cookie/makefiles.sh | 1 + extensions/cookie/nsCookiePermission.cpp | 98 +++++++++++++++- extensions/cookie/test/Makefile.in | 93 +++++++++++++++ .../cookie/test/browser_test_favicon.js | 44 +++++++ extensions/cookie/test/file_domain_inner.html | 14 +++ .../cookie/test/file_domain_inner_inner.html | 14 +++ extensions/cookie/test/file_image_inner.html | 15 +++ .../cookie/test/file_image_inner_inner.html | 20 ++++ .../cookie/test/file_loadflags_inner.html | 17 +++ .../cookie/test/file_localhost_inner.html | 14 +++ .../cookie/test/file_loopback_inner.html | 14 +++ .../cookie/test/file_subdomain_inner.html | 14 +++ extensions/cookie/test/file_testcommon.js | 67 +++++++++++ extensions/cookie/test/file_testloadflags.js | 111 ++++++++++++++++++ extensions/cookie/test/image1.png | Bin 0 -> 1242 bytes extensions/cookie/test/image1.png^headers^ | 3 + extensions/cookie/test/image2.png | Bin 0 -> 1242 bytes extensions/cookie/test/image2.png^headers^ | 3 + extensions/cookie/test/test1.css | 2 + extensions/cookie/test/test1.css^headers^ | 3 + extensions/cookie/test/test2.css | 2 + extensions/cookie/test/test2.css^headers^ | 3 + .../cookie/test/test_differentdomain.html | 16 +++ extensions/cookie/test/test_image.html | 15 +++ extensions/cookie/test/test_loadflags.html | 16 +++ .../cookie/test/test_same_base_domain.html | 16 +++ .../cookie/test/test_same_base_domain_2.html | 16 +++ .../cookie/test/test_same_base_domain_3.html | 16 +++ .../cookie/test/test_same_base_domain_4.html | 16 +++ .../cookie/test/test_same_base_domain_5.html | 16 +++ .../cookie/test/test_same_base_domain_6.html | 16 +++ .../cookie/test/test_same_base_domain_7.html | 16 +++ extensions/cookie/test/test_samedomain.html | 16 +++ extensions/cookie/test/unit/test_cookies.js | 49 ++++++++ netwerk/cookie/public/nsICookiePermission.idl | 24 +++- netwerk/cookie/src/nsCookieService.cpp | 97 ++++----------- netwerk/cookie/src/nsCookieService.h | 9 +- netwerk/test/TestCookie.cpp | 85 +------------- 39 files changed, 826 insertions(+), 172 deletions(-) create mode 100644 extensions/cookie/test/Makefile.in create mode 100644 extensions/cookie/test/browser_test_favicon.js create mode 100644 extensions/cookie/test/file_domain_inner.html create mode 100644 extensions/cookie/test/file_domain_inner_inner.html create mode 100644 extensions/cookie/test/file_image_inner.html create mode 100644 extensions/cookie/test/file_image_inner_inner.html create mode 100644 extensions/cookie/test/file_loadflags_inner.html create mode 100644 extensions/cookie/test/file_localhost_inner.html create mode 100644 extensions/cookie/test/file_loopback_inner.html create mode 100644 extensions/cookie/test/file_subdomain_inner.html create mode 100644 extensions/cookie/test/file_testcommon.js create mode 100644 extensions/cookie/test/file_testloadflags.js create mode 100644 extensions/cookie/test/image1.png create mode 100644 extensions/cookie/test/image1.png^headers^ create mode 100644 extensions/cookie/test/image2.png create mode 100644 extensions/cookie/test/image2.png^headers^ create mode 100644 extensions/cookie/test/test1.css create mode 100644 extensions/cookie/test/test1.css^headers^ create mode 100644 extensions/cookie/test/test2.css create mode 100644 extensions/cookie/test/test2.css^headers^ create mode 100644 extensions/cookie/test/test_differentdomain.html create mode 100644 extensions/cookie/test/test_image.html create mode 100644 extensions/cookie/test/test_loadflags.html create mode 100644 extensions/cookie/test/test_same_base_domain.html create mode 100644 extensions/cookie/test/test_same_base_domain_2.html create mode 100644 extensions/cookie/test/test_same_base_domain_3.html create mode 100644 extensions/cookie/test/test_same_base_domain_4.html create mode 100644 extensions/cookie/test/test_same_base_domain_5.html create mode 100644 extensions/cookie/test/test_same_base_domain_6.html create mode 100644 extensions/cookie/test/test_same_base_domain_7.html create mode 100644 extensions/cookie/test/test_samedomain.html create mode 100644 extensions/cookie/test/unit/test_cookies.js diff --git a/extensions/cookie/Makefile.in b/extensions/cookie/Makefile.in index e1ea6e6f16b..842166fca07 100644 --- a/extensions/cookie/Makefile.in +++ b/extensions/cookie/Makefile.in @@ -56,10 +56,13 @@ REQUIRES = xpcom \ string \ necko \ dom \ + content \ + widget \ pref \ windowwatcher \ docshell \ appshell \ + caps \ storage \ $(NULL) @@ -85,4 +88,8 @@ ifdef MOZ_MAIL_NEWS DEFINES += -DMOZ_MAIL_NEWS endif +ifdef ENABLE_TESTS +TOOL_DIRS += test +endif + include $(topsrcdir)/config/rules.mk diff --git a/extensions/cookie/makefiles.sh b/extensions/cookie/makefiles.sh index a4a5abea161..d7b6c690431 100755 --- a/extensions/cookie/makefiles.sh +++ b/extensions/cookie/makefiles.sh @@ -38,4 +38,5 @@ add_makefiles " extensions/cookie/Makefile + extensions/cookie/test/Makefile " diff --git a/extensions/cookie/nsCookiePermission.cpp b/extensions/cookie/nsCookiePermission.cpp index 4acad1689fb..0f8a64f02f7 100644 --- a/extensions/cookie/nsCookiePermission.cpp +++ b/extensions/cookie/nsCookiePermission.cpp @@ -21,6 +21,7 @@ * * Contributor(s): * Darin Fisher + * Daniel Witte * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or @@ -49,11 +50,12 @@ #include "nsIPrefBranch2.h" #include "nsIDocShell.h" #include "nsIDocShellTreeItem.h" -#include "nsIInterfaceRequestor.h" -#include "nsIInterfaceRequestorUtils.h" -#include "nsILoadGroup.h" +#include "nsIWebNavigation.h" +#include "nsINode.h" #include "nsIChannel.h" #include "nsIDOMWindow.h" +#include "nsIDOMDocument.h" +#include "nsIPrincipal.h" #include "nsString.h" #include "nsCRT.h" @@ -199,7 +201,6 @@ nsCookiePermission::SetAccess(nsIURI *aURI, NS_IMETHODIMP nsCookiePermission::CanAccess(nsIURI *aURI, - nsIURI *aFirstURI, nsIChannel *aChannel, nsCookieAccess *aResult) { @@ -235,7 +236,6 @@ nsCookiePermission::CanAccess(nsIURI *aURI, } } if ((appType == nsIDocShell::APP_TYPE_MAIL) || - (aFirstURI && IsFromMailNews(aFirstURI)) || IsFromMailNews(aURI)) { *aResult = ACCESS_DENY; return NS_OK; @@ -421,6 +421,94 @@ nsCookiePermission::CanSetCookie(nsIURI *aURI, return NS_OK; } +NS_IMETHODIMP +nsCookiePermission::GetOriginatingURI(nsIChannel *aChannel, + nsIURI **aURI) +{ + /* to find the originating URI, we use the loadgroup of the channel to obtain + * the docshell owning the load, and from there, we find the root content + * docshell and its URI. there are several possible cases: + * + * 1) no channel. this will occur for plugins using the nsICookieStorage + * interface, since they have none to provide. other consumers should + * have a channel. + * + * 2) a channel, but no docshell. this can occur when the consumer kicking + * off the load doesn't provide one to the channel, and should be limited + * to loads of certain types of resources (e.g. favicons). + * + * 3) a non-content docshell. this occurs for loads kicked off from chrome, + * where no content docshell exists (favicons can also fall into this + * category). + * + * 4) a content docshell equal to the root content docshell, with channel + * loadflags LOAD_DOCUMENT_URI. this covers the case of a freshly kicked- + * off load (e.g. the user typing something in the location bar, or + * clicking on a bookmark), where the currentURI hasn't yet been set, + * and will be bogus. we return the channel URI in this case. note that + * we could also allow non-content docshells here, but that goes against + * the philosophy of having an audit trail back to a URI the user typed + * or clicked on. + * + * 5) a root content docshell. this covers most cases for an ordinary page + * load from the location bar, and will catch nested frames within + * a page, image loads, etc. we return the URI of the docshell's principal + * in this case. + * + */ + + *aURI = nsnull; + + // case 1) + if (!aChannel) + return NS_ERROR_NULL_POINTER; + + // find the docshell and its root + nsCOMPtr docshell, root; + NS_QueryNotificationCallbacks(aChannel, docshell); + if (docshell) + docshell->GetSameTypeRootTreeItem(getter_AddRefs(root)); + + PRInt32 type; + if (root) + root->GetItemType(&type); + + // cases 2) and 3) + if (!root || type != nsIDocShellTreeItem::typeContent) + return NS_ERROR_INVALID_ARG; + + // case 4) + if (docshell == root) { + nsLoadFlags flags; + aChannel->GetLoadFlags(&flags); + + if (flags & nsIChannel::LOAD_DOCUMENT_URI) { + // get the channel URI - the docshell's will be bogus + aChannel->GetURI(aURI); + if (!*aURI) + return NS_ERROR_NULL_POINTER; + + return NS_OK; + } + } + + // case 5) - get the originating URI from the docshell's principal + nsCOMPtr webnav = do_QueryInterface(root); + if (webnav) { + nsCOMPtr doc; + webnav->GetDocument(getter_AddRefs(doc)); + nsCOMPtr node = do_QueryInterface(doc); + if (node) + node->NodePrincipal()->GetURI(aURI); + } + + if (!*aURI) + return NS_ERROR_NULL_POINTER; + + // all done! + return NS_OK; +} + NS_IMETHODIMP nsCookiePermission::Observe(nsISupports *aSubject, const char *aTopic, diff --git a/extensions/cookie/test/Makefile.in b/extensions/cookie/test/Makefile.in new file mode 100644 index 00000000000..e36a367cd9e --- /dev/null +++ b/extensions/cookie/test/Makefile.in @@ -0,0 +1,93 @@ +# +# ***** BEGIN LICENSE BLOCK ***** +# Version: MPL 1.1/GPL 2.0/LGPL 2.1 +# +# The contents of this file are subject to the Mozilla Public License Version +# 1.1 (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS IS" basis, +# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License +# for the specific language governing rights and limitations under the +# License. +# +# The Original Code is mozilla.org code. +# +# The Initial Developer of the Original Code is +# Mozilla Foundation. +# Portions created by the Initial Developer are Copyright (C) 2007 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the terms of +# either of the GNU General Public License Version 2 or later (the "GPL"), +# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), +# in which case the provisions of the GPL or the LGPL are applicable instead +# of those above. If you wish to allow use of your version of this file only +# under the terms of either the GPL or the LGPL, and not to allow others to +# use your version of this file under the terms of the MPL, indicate your +# decision by deleting the provisions above and replace them with the notice +# and other provisions required by the GPL or the LGPL. If you do not delete +# the provisions above, a recipient may use your version of this file under +# the terms of any one of the MPL, the GPL or the LGPL. +# +# ***** END LICENSE BLOCK ***** + +DEPTH = ../../.. +topsrcdir = @top_srcdir@ +srcdir = @srcdir@ +VPATH = @srcdir@ +relativesrcdir = extensions/cookie/test + +include $(DEPTH)/config/autoconf.mk + +MODULE = test_cookies + +_TEST_FILES = \ + test_samedomain.html \ + file_testcommon.js \ + file_domain_inner.html \ + file_domain_inner_inner.html \ + test_differentdomain.html \ + test_image.html \ + file_image_inner.html \ + file_image_inner_inner.html \ + image1.png \ + image1.png^headers^ \ + image2.png \ + image2.png^headers^ \ + test1.css \ + test1.css^headers^ \ + test2.css \ + test2.css^headers^ \ + test_loadflags.html \ + file_testloadflags.js \ + file_loadflags_inner.html \ + test_same_base_domain.html \ + file_subdomain_inner.html \ + test_same_base_domain_2.html \ + test_same_base_domain_3.html \ + test_same_base_domain_4.html \ + file_localhost_inner.html \ + test_same_base_domain_5.html \ + test_same_base_domain_6.html \ + file_loopback_inner.html \ + test_same_base_domain_7.html \ + $(NULL) + +_BROWSER_TEST_FILES = \ + browser_test_favicon.js \ + $(NULL) + +libs:: $(_TEST_FILES) + $(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir) + +libs:: $(_BROWSER_TEST_FILES) + $(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir) + +XPCSHELL_TESTS = unit + +include $(topsrcdir)/config/rules.mk + diff --git a/extensions/cookie/test/browser_test_favicon.js b/extensions/cookie/test/browser_test_favicon.js new file mode 100644 index 00000000000..4c1ae877c30 --- /dev/null +++ b/extensions/cookie/test/browser_test_favicon.js @@ -0,0 +1,44 @@ +// tests third party cookie blocking using a favicon load directly from chrome. +// in this case, the docshell of the channel is chrome, not content; thus +// the cookie should be considered third party. + +function test() { + waitForExplicitFinish(); + + var prefs = Components.classes["@mozilla.org/preferences-service;1"] + .getService(Components.interfaces.nsIPrefBranch); + prefs.setIntPref("network.cookie.cookieBehavior", 1); + + var o = new obs(); + + // kick off a favicon load + PageProxySetIcon("http://example.org/tests/extensions/cookie/test/image1.png"); +} + +function obs () { + this.os = Components.classes["@mozilla.org/observer-service;1"] + .getService(Components.interfaces.nsIObserverService); + this.os.addObserver(this, "cookie-rejected", false); +} + +obs.prototype = { + observe: function obs_observe (theSubject, theTopic, theData) + { + var uri = theSubject.QueryInterface(Components.interfaces.nsIURI); + var domain = uri.host; + + if (domain == "example.org") { + ok(true, "foreign favicon cookie was blocked"); + + var prefs = Components.classes["@mozilla.org/preferences-service;1"] + .getService(Components.interfaces.nsIPrefBranch); + prefs.setIntPref("network.cookie.cookieBehavior", 0); + + this.os.removeObserver(this, "cookie-rejected"); + this.os = null; + + finish(); + } + } +} + diff --git a/extensions/cookie/test/file_domain_inner.html b/extensions/cookie/test/file_domain_inner.html new file mode 100644 index 00000000000..b561c441705 --- /dev/null +++ b/extensions/cookie/test/file_domain_inner.html @@ -0,0 +1,14 @@ + + + + + + + + + diff --git a/extensions/cookie/test/file_domain_inner_inner.html b/extensions/cookie/test/file_domain_inner_inner.html new file mode 100644 index 00000000000..baa608e6a72 --- /dev/null +++ b/extensions/cookie/test/file_domain_inner_inner.html @@ -0,0 +1,14 @@ + + + + + + + + + diff --git a/extensions/cookie/test/file_image_inner.html b/extensions/cookie/test/file_image_inner.html new file mode 100644 index 00000000000..a4d98ee0599 --- /dev/null +++ b/extensions/cookie/test/file_image_inner.html @@ -0,0 +1,15 @@ + + + + + + + + + + diff --git a/extensions/cookie/test/file_image_inner_inner.html b/extensions/cookie/test/file_image_inner_inner.html new file mode 100644 index 00000000000..07f060940b8 --- /dev/null +++ b/extensions/cookie/test/file_image_inner_inner.html @@ -0,0 +1,20 @@ + + + + + + + + + + + + + diff --git a/extensions/cookie/test/file_loadflags_inner.html b/extensions/cookie/test/file_loadflags_inner.html new file mode 100644 index 00000000000..1dc7619cae9 --- /dev/null +++ b/extensions/cookie/test/file_loadflags_inner.html @@ -0,0 +1,17 @@ + + + + + + + + + + diff --git a/extensions/cookie/test/file_localhost_inner.html b/extensions/cookie/test/file_localhost_inner.html new file mode 100644 index 00000000000..49c75603877 --- /dev/null +++ b/extensions/cookie/test/file_localhost_inner.html @@ -0,0 +1,14 @@ + + + + + + + + + diff --git a/extensions/cookie/test/file_loopback_inner.html b/extensions/cookie/test/file_loopback_inner.html new file mode 100644 index 00000000000..156532dc338 --- /dev/null +++ b/extensions/cookie/test/file_loopback_inner.html @@ -0,0 +1,14 @@ + + + + + + + + + diff --git a/extensions/cookie/test/file_subdomain_inner.html b/extensions/cookie/test/file_subdomain_inner.html new file mode 100644 index 00000000000..ff1036edb47 --- /dev/null +++ b/extensions/cookie/test/file_subdomain_inner.html @@ -0,0 +1,14 @@ + + + + + + + + + diff --git a/extensions/cookie/test/file_testcommon.js b/extensions/cookie/test/file_testcommon.js new file mode 100644 index 00000000000..5adb7fbeaec --- /dev/null +++ b/extensions/cookie/test/file_testcommon.js @@ -0,0 +1,67 @@ +SimpleTest.waitForExplicitFinish(); + +var gPopup = null; + +var gExpectedCookies = 0; +var gExpectedLoads = 0; +var gLoads = 0; + +function setupTest(uri, cookies, loads) { + netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect"); + + var prefs = Components.classes["@mozilla.org/preferences-service;1"] + .getService(Components.interfaces.nsIPrefBranch); + prefs.setIntPref("network.cookie.cookieBehavior", 1); + + var cs = Components.classes["@mozilla.org/cookiemanager;1"] + .getService(Components.interfaces.nsICookieManager2); + cs.removeAll(); + + gExpectedCookies = cookies; + gExpectedLoads = loads; + + // load a window which contains an iframe; each will attempt to set + // cookies from their respective domains. + gPopup = window.open(uri, 'hai', 'width=100,height=100'); +} + +/** Receives MessageEvents to this window. */ +function messageReceiver(evt) +{ + ok(evt instanceof MessageEvent, "wrong event type"); + + if (evt.data == "message") + gLoads++; + else { + ok(false, "wrong message"); + gPopup.close(); + SimpleTest.finish(); + } + + // only run the test when all our children are done loading & setting cookies + if (gLoads == gExpectedLoads) + runTest(); +} + +function runTest() { + // set a cookie from a domain of "localhost" + document.cookie = "oh=hai"; + + netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect"); + var cs = Components.classes["@mozilla.org/cookiemanager;1"] + .getService(Components.interfaces.nsICookieManager); + var list = cs.enumerator; + var count = 0; + while (list.hasMoreElements()) { + count++; + list.getNext(); + } + is(count, gExpectedCookies, "incorrect number of cookies"); + + gPopup.close(); + cs.removeAll(); + SimpleTest.finish(); +} + +document.addEventListener("message", messageReceiver, false); + diff --git a/extensions/cookie/test/file_testloadflags.js b/extensions/cookie/test/file_testloadflags.js new file mode 100644 index 00000000000..aa432c6dec8 --- /dev/null +++ b/extensions/cookie/test/file_testloadflags.js @@ -0,0 +1,111 @@ +SimpleTest.waitForExplicitFinish(); + +var gPopup = null; + +var gExpectedCookies = 0; +var gExpectedLoads = 0; +var gExpectedHeaders = 0; +var gLoads = 0; +var gHeaders = 0; + +var o = null; + +function setupTest(uri, domain, cookies, loads, headers) { + netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect"); + + var prefs = Components.classes["@mozilla.org/preferences-service;1"] + .getService(Components.interfaces.nsIPrefBranch); + prefs.setIntPref("network.cookie.cookieBehavior", 1); + + var cs = Components.classes["@mozilla.org/cookiemanager;1"] + .getService(Components.interfaces.nsICookieManager2); + cs.removeAll(); + cs.add(domain, "", "oh", "hai", false, false, true, Math.pow(2, 62)); + is(cs.countCookiesFromHost(domain), 1, "cookie wasn't inited"); + + o = new obs(); + + gExpectedCookies = cookies; + gExpectedLoads = loads; + gExpectedHeaders = headers; + + // load a window which contains an iframe; each will attempt to set + // cookies from their respective domains. + gPopup = window.open(uri, 'hai', 'width=100,height=100'); +} + +function obs () { + netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect"); + this.os = Components.classes["@mozilla.org/observer-service;1"] + .getService(Components.interfaces.nsIObserverService); + this.os.addObserver(this, "http-on-modify-request", false); + this.window = window; +} + +obs.prototype = { + observe: function obs_observe (theSubject, theTopic, theData) + { + this.window.netscape.security + .PrivilegeManager.enablePrivilege("UniversalXPConnect"); + var httpchannel = theSubject.QueryInterface(this.window.Components.interfaces + .nsIHttpChannel); + + var cookie = httpchannel.getRequestHeader("Cookie"); + + var got = cookie.indexOf("oh=hai"); + this.window.isnot(got, -1, "cookie wasn't sent"); + gHeaders++; + }, + + remove: function obs_remove() + { + netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect"); + this.os.removeObserver(this, "http-on-modify-request"); + this.os = null; + this.window = null; + } +} + +/** Receives MessageEvents to this window. */ +function messageReceiver(evt) +{ + ok(evt instanceof MessageEvent, "wrong event type"); + + if (evt.data == "message") + gLoads++; + else { + ok(false, "wrong message"); + o.remove(); + gPopup.close(); + SimpleTest.finish(); + } + + // only run the test when all our children are done loading & setting cookies + if (gLoads == gExpectedLoads) + runTest(); +} + +function runTest() { + // set a cookie from a domain of "localhost" + document.cookie = "o=noes"; + + netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect"); + var cs = Components.classes["@mozilla.org/cookiemanager;1"] + .getService(Components.interfaces.nsICookieManager); + var list = cs.enumerator; + var count = 0; + while (list.hasMoreElements()) { + count++; + list.getNext(); + } + is(count, gExpectedCookies, "incorrect number of cookies"); + is(gHeaders, gExpectedHeaders, "incorrect number of request headers"); + + o.remove(); + gPopup.close(); + cs.removeAll(); + SimpleTest.finish(); +} + +document.addEventListener("message", messageReceiver, false); + diff --git a/extensions/cookie/test/image1.png b/extensions/cookie/test/image1.png new file mode 100644 index 0000000000000000000000000000000000000000..4b7c102840cab57d589b4380cb1d0675498fcda9 GIT binary patch literal 1242 zcmV<01SR{4P)4Tx0C=30k{)ols`Zz7ik<`+6&3Ip87oB zo_cEv5f^-H+-Di={FM z6ELfqlYm*#JPnvzN-7X}z;xDa7laF>!j(b}#2%2SYCZxI70s7GqTy5(h$fH@+*$zQ z1<1HwN%IszU0@Ua)i?;lVNAhax!z6Z`Ujx<{>*xR z0Mc+g538N9xC;kQFnR$!SCH?9l_`wO^LOZ50Wg@e{aPiomFHT8xvZ6|`}HuAw&VTl z?SD&o+X^68mpfstx~{BQDSa0GkgN=i*4c{6kO5(000SaNLh0L01FcU z01FcV0GgZ_0008*NklR(axBghhpis%YaSwDm*SW%g1$|O^3ZZj?II&IEfzwiCtw_nPP?EE`C z&pGg%=K%jf;S(z>Y{*>-00s4y4S5f;!hi4Z(WKaB&4}hqq@WS;;O=v!1|mwyG(yGy z8c+eQqK2HqV_XubKnZe*S2&sKR$M>`s`3N5XD2m~1nMJ%o&tdU`xYM~EQS)Q?acUH zu_(_HduHWvq^HfQUbEd;J*MF%-25W7<7C3alP#pjB_(l zsx86kH+5iyff5F;;E}~gz%OYkYjOjC^^Tb-pup~V<#7G#KqwM~2ql^aKjOD<1X*bd z(f^>`ZF}4^3jpMlvN%p6F6-T_+j5C7nWmhMb^3gK{AR~!cmzL#qad+~*ki7O$M47G z#w$=MY3FzbjT>7OQiQfpk!}%0lCs&b9FFhp@P)ki>Gwg9sZco8jJIwZ@#sq>7^Gj|3kLuK z$j1{5GbvF!1qwbML%|S2h(k`&0(A9u!+EV6`SxB|l>(mdTDWKG`c>_&+1_1-qvLOs z5x(~Ar&f%FfDnyCPRc^`4t3#Wy%TD?6FW!*J)kg)VOsO)vwn{{;niBxv4(Mjru}U- zoWQ@n@!}p<8CD`lMj=VS6qyE9ni#kwiZU<2jrw^zBV-$87TuAWMp<+ZzS(|U*A>lJ z*5Yc_PgU!nlxfjwcOc<|2TLTvK64x=0&pZ~_-4~$49EpCp-5wxe`wB4Ng$OHVZ5R* z8OB~O>KrcVI|pv3J}t0*alys+&Uf7K{)(sn(ocYSUzWXcQz>%->~>Nd%PU!SK6);n zOgM(N+E(N6)=crl>P!-NHh3v^T6#SIY%MBM22xYSKMhDxmS%e%O#lD@07*qoM6N<$ Eg369MXaE2J literal 0 HcmV?d00001 diff --git a/extensions/cookie/test/image1.png^headers^ b/extensions/cookie/test/image1.png^headers^ new file mode 100644 index 00000000000..6b75fe95939 --- /dev/null +++ b/extensions/cookie/test/image1.png^headers^ @@ -0,0 +1,3 @@ +Cache-Control: no-cache +Set-Cookie: foo=bar + diff --git a/extensions/cookie/test/image2.png b/extensions/cookie/test/image2.png new file mode 100644 index 0000000000000000000000000000000000000000..4b7c102840cab57d589b4380cb1d0675498fcda9 GIT binary patch literal 1242 zcmV<01SR{4P)4Tx0C=30k{)ols`Zz7ik<`+6&3Ip87oB zo_cEv5f^-H+-Di={FM z6ELfqlYm*#JPnvzN-7X}z;xDa7laF>!j(b}#2%2SYCZxI70s7GqTy5(h$fH@+*$zQ z1<1HwN%IszU0@Ua)i?;lVNAhax!z6Z`Ujx<{>*xR z0Mc+g538N9xC;kQFnR$!SCH?9l_`wO^LOZ50Wg@e{aPiomFHT8xvZ6|`}HuAw&VTl z?SD&o+X^68mpfstx~{BQDSa0GkgN=i*4c{6kO5(000SaNLh0L01FcU z01FcV0GgZ_0008*NklR(axBghhpis%YaSwDm*SW%g1$|O^3ZZj?II&IEfzwiCtw_nPP?EE`C z&pGg%=K%jf;S(z>Y{*>-00s4y4S5f;!hi4Z(WKaB&4}hqq@WS;;O=v!1|mwyG(yGy z8c+eQqK2HqV_XubKnZe*S2&sKR$M>`s`3N5XD2m~1nMJ%o&tdU`xYM~EQS)Q?acUH zu_(_HduHWvq^HfQUbEd;J*MF%-25W7<7C3alP#pjB_(l zsx86kH+5iyff5F;;E}~gz%OYkYjOjC^^Tb-pup~V<#7G#KqwM~2ql^aKjOD<1X*bd z(f^>`ZF}4^3jpMlvN%p6F6-T_+j5C7nWmhMb^3gK{AR~!cmzL#qad+~*ki7O$M47G z#w$=MY3FzbjT>7OQiQfpk!}%0lCs&b9FFhp@P)ki>Gwg9sZco8jJIwZ@#sq>7^Gj|3kLuK z$j1{5GbvF!1qwbML%|S2h(k`&0(A9u!+EV6`SxB|l>(mdTDWKG`c>_&+1_1-qvLOs z5x(~Ar&f%FfDnyCPRc^`4t3#Wy%TD?6FW!*J)kg)VOsO)vwn{{;niBxv4(Mjru}U- zoWQ@n@!}p<8CD`lMj=VS6qyE9ni#kwiZU<2jrw^zBV-$87TuAWMp<+ZzS(|U*A>lJ z*5Yc_PgU!nlxfjwcOc<|2TLTvK64x=0&pZ~_-4~$49EpCp-5wxe`wB4Ng$OHVZ5R* z8OB~O>KrcVI|pv3J}t0*alys+&Uf7K{)(sn(ocYSUzWXcQz>%->~>Nd%PU!SK6);n zOgM(N+E(N6)=crl>P!-NHh3v^T6#SIY%MBM22xYSKMhDxmS%e%O#lD@07*qoM6N<$ Eg369MXaE2J literal 0 HcmV?d00001 diff --git a/extensions/cookie/test/image2.png^headers^ b/extensions/cookie/test/image2.png^headers^ new file mode 100644 index 00000000000..16e3fce28e0 --- /dev/null +++ b/extensions/cookie/test/image2.png^headers^ @@ -0,0 +1,3 @@ +Cache-Control: no-cache +Set-Cookie: foo2=bar2 + diff --git a/extensions/cookie/test/test1.css b/extensions/cookie/test/test1.css new file mode 100644 index 00000000000..139597f9cb0 --- /dev/null +++ b/extensions/cookie/test/test1.css @@ -0,0 +1,2 @@ + + diff --git a/extensions/cookie/test/test1.css^headers^ b/extensions/cookie/test/test1.css^headers^ new file mode 100644 index 00000000000..729babb5a4c --- /dev/null +++ b/extensions/cookie/test/test1.css^headers^ @@ -0,0 +1,3 @@ +Cache-Control: no-cache +Set-Cookie: css=bar + diff --git a/extensions/cookie/test/test2.css b/extensions/cookie/test/test2.css new file mode 100644 index 00000000000..139597f9cb0 --- /dev/null +++ b/extensions/cookie/test/test2.css @@ -0,0 +1,2 @@ + + diff --git a/extensions/cookie/test/test2.css^headers^ b/extensions/cookie/test/test2.css^headers^ new file mode 100644 index 00000000000..b12d32c72bb --- /dev/null +++ b/extensions/cookie/test/test2.css^headers^ @@ -0,0 +1,3 @@ +Cache-Control: no-cache +Set-Cookie: css2=bar2 + diff --git a/extensions/cookie/test/test_differentdomain.html b/extensions/cookie/test/test_differentdomain.html new file mode 100644 index 00000000000..9fbaf6f7b96 --- /dev/null +++ b/extensions/cookie/test/test_differentdomain.html @@ -0,0 +1,16 @@ + + + + Test for Cross domain access to properties + + + + + +

+
+
+
+ + diff --git a/extensions/cookie/test/test_image.html b/extensions/cookie/test/test_image.html new file mode 100644 index 00000000000..681a0075ea2 --- /dev/null +++ b/extensions/cookie/test/test_image.html @@ -0,0 +1,15 @@ + + + + Test for Cross domain access to properties + + + + + +

+
+
+
+ + diff --git a/extensions/cookie/test/test_loadflags.html b/extensions/cookie/test/test_loadflags.html new file mode 100644 index 00000000000..1e50680d926 --- /dev/null +++ b/extensions/cookie/test/test_loadflags.html @@ -0,0 +1,16 @@ + + + + Test for Cross domain access to properties + + + + + +

+
+
+
+ + diff --git a/extensions/cookie/test/test_same_base_domain.html b/extensions/cookie/test/test_same_base_domain.html new file mode 100644 index 00000000000..ef2a5d4f429 --- /dev/null +++ b/extensions/cookie/test/test_same_base_domain.html @@ -0,0 +1,16 @@ + + + + Test for Cross domain access to properties + + + + + +

+
+
+
+ + diff --git a/extensions/cookie/test/test_same_base_domain_2.html b/extensions/cookie/test/test_same_base_domain_2.html new file mode 100644 index 00000000000..18cf5c15f56 --- /dev/null +++ b/extensions/cookie/test/test_same_base_domain_2.html @@ -0,0 +1,16 @@ + + + + Test for Cross domain access to properties + + + + + +

+
+
+
+ + diff --git a/extensions/cookie/test/test_same_base_domain_3.html b/extensions/cookie/test/test_same_base_domain_3.html new file mode 100644 index 00000000000..e768d8b84af --- /dev/null +++ b/extensions/cookie/test/test_same_base_domain_3.html @@ -0,0 +1,16 @@ + + + + Test for Cross domain access to properties + + + + + +

+
+
+
+ + diff --git a/extensions/cookie/test/test_same_base_domain_4.html b/extensions/cookie/test/test_same_base_domain_4.html new file mode 100644 index 00000000000..60706b5f31d --- /dev/null +++ b/extensions/cookie/test/test_same_base_domain_4.html @@ -0,0 +1,16 @@ + + + + Test for Cross domain access to properties + + + + + +

+
+
+
+ + diff --git a/extensions/cookie/test/test_same_base_domain_5.html b/extensions/cookie/test/test_same_base_domain_5.html new file mode 100644 index 00000000000..cf959e66190 --- /dev/null +++ b/extensions/cookie/test/test_same_base_domain_5.html @@ -0,0 +1,16 @@ + + + + Test for Cross domain access to properties + + + + + +

+
+
+
+ + diff --git a/extensions/cookie/test/test_same_base_domain_6.html b/extensions/cookie/test/test_same_base_domain_6.html new file mode 100644 index 00000000000..fbc5945fbd9 --- /dev/null +++ b/extensions/cookie/test/test_same_base_domain_6.html @@ -0,0 +1,16 @@ + + + + Test for Cross domain access to properties + + + + + +

+
+
+
+ + diff --git a/extensions/cookie/test/test_same_base_domain_7.html b/extensions/cookie/test/test_same_base_domain_7.html new file mode 100644 index 00000000000..06c7307d79d --- /dev/null +++ b/extensions/cookie/test/test_same_base_domain_7.html @@ -0,0 +1,16 @@ + + + + Test for Cross domain access to properties + + + + + +

+
+
+
+ + diff --git a/extensions/cookie/test/test_samedomain.html b/extensions/cookie/test/test_samedomain.html new file mode 100644 index 00000000000..51ed99b201b --- /dev/null +++ b/extensions/cookie/test/test_samedomain.html @@ -0,0 +1,16 @@ + + + + Test for Cross domain access to properties + + + + + +

+
+
+
+ + diff --git a/extensions/cookie/test/unit/test_cookies.js b/extensions/cookie/test/unit/test_cookies.js new file mode 100644 index 00000000000..ccda2a72bee --- /dev/null +++ b/extensions/cookie/test/unit/test_cookies.js @@ -0,0 +1,49 @@ +// test third party cookie blocking, for the cases: +// 1) with null channel +// 2) with channel, but with no docshell parent + +const Cc = Components.classes; +const Ci = Components.interfaces; + +function run_test() { + var cs = Cc["@mozilla.org/cookieService;1"].getService(Ci.nsICookieService); + var cm = Cc["@mozilla.org/cookiemanager;1"].getService(Ci.nsICookieManager2); + var ios = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService); + var prefs = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch); + + var spec = "http://foo.com/dribble.html"; + var uri = ios.newURI(spec, null, null); + var channel = ios.newChannelFromURI(uri); + + // test with cookies enabled + prefs.setIntPref("network.cookie.cookieBehavior", 0); + // without channel + cs.setCookieString(uri, null, "oh=hai", null); + do_check_eq(cs.countCookiesFromHost("foo.com"), 1); + // with channel + cs.setCookieString(uri, null, "can=has", channel); + do_check_eq(cs.countCookiesFromHost("foo.com"), 2); + // without channel, from http + cs.setCookieStringFromHttp(uri, null, null, "cheez=burger", null, null); + do_check_eq(cs.countCookiesFromHost("foo.com"), 3); + // with channel, from http + cs.setCookieStringFromHttp(uri, null, null, "hot=dog", null, channel); + do_check_eq(cs.countCookiesFromHost("foo.com"), 4); + cs.removeAll(); + + // test with third party cookies blocked + prefs.setIntPref("network.cookie.cookieBehavior", 1); + // without channel + cs.setCookieString(uri, null, "oh=hai", null); + do_check_eq(cs.countCookiesFromHost("foo.com"), 0); + // with channel + cs.setCookieString(uri, null, "can=has", channel); + do_check_eq(cs.countCookiesFromHost("foo.com"), 0); + // without channel, from http + cs.setCookieStringFromHttp(uri, null, null, "cheez=burger", null, null); + do_check_eq(cs.countCookiesFromHost("foo.com"), 0); + // with channel, from http + cs.setCookieStringFromHttp(uri, null, null, "hot=dog", null, channel); + do_check_eq(cs.countCookiesFromHost("foo.com"), 0); +} + diff --git a/netwerk/cookie/public/nsICookiePermission.idl b/netwerk/cookie/public/nsICookiePermission.idl index 86aaf5200ea..511af410ffe 100644 --- a/netwerk/cookie/public/nsICookiePermission.idl +++ b/netwerk/cookie/public/nsICookiePermission.idl @@ -19,6 +19,7 @@ * the Initial Developer. All Rights Reserved. * * Contributor(s): + * Daniel Witte * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or @@ -45,7 +46,7 @@ typedef long nsCookieAccess; /** * An interface to test for cookie permissions */ -[scriptable, uuid(91f1c3ec-73a0-4bf0-bdc5-348a1f181b0e)] +[scriptable, uuid(4b1a775d-f6d3-4389-be2e-9dfbaf2ab47b)] interface nsICookiePermission : nsISupports { /** @@ -86,8 +87,6 @@ interface nsICookiePermission : nsISupports * * @param aURI * the URI trying to access cookies - * @param aFirstURI - * the URI initiated by the user that resulted in aURI being loaded * @param aChannel * the channel corresponding to aURI * @@ -95,7 +94,6 @@ interface nsICookiePermission : nsISupports * ACCESS_DEFAULT, ACCESS_ALLOW, or ACCESS_DENY */ nsCookieAccess canAccess(in nsIURI aURI, - in nsIURI aFirstURI, in nsIChannel aChannel); /** @@ -111,7 +109,7 @@ interface nsICookiePermission : nsISupports * @param aURI * the URI trying to set the cookie * @param aChannel - * the corresponding to aURI + * the channel corresponding to aURI * @param aCookie * the cookie being added to the cookie database * @param aIsSession @@ -130,6 +128,22 @@ interface nsICookiePermission : nsISupports in nsICookie2 aCookie, inout boolean aIsSession, inout PRInt64 aExpiry); + + /** + * getOriginatingURI + * + * determines the originating URI for a load given a channel, for third-party + * cookie blocking. this is done by leveraging the loadgroup of the channel to + * find the root content docshell, and the URI associated with its principal. + * if the root content docshell or its principal's URI cannot be obtained, + * this method will throw. + * + * @param aChannel + * the channel for the load trying to get or set cookies + * + * @return the originating URI. + */ + nsIURI getOriginatingURI(in nsIChannel aChannel); }; %{ C++ diff --git a/netwerk/cookie/src/nsCookieService.cpp b/netwerk/cookie/src/nsCookieService.cpp index 9933cfb165a..edb41cd4b72 100644 --- a/netwerk/cookie/src/nsCookieService.cpp +++ b/netwerk/cookie/src/nsCookieService.cpp @@ -48,9 +48,6 @@ #include "nsIURI.h" #include "nsIURL.h" #include "nsIChannel.h" -#include "nsIHttpChannel.h" -#include "nsIHttpChannelInternal.h" // evil hack! -#include "nsIPrompt.h" #include "nsIFile.h" #include "nsIObserverService.h" #include "nsILineInputStream.h" @@ -448,6 +445,8 @@ nsCookieService::Init() } mPermissionService = do_GetService(NS_COOKIEPERMISSION_CONTRACTID); + if (!mPermissionService) + NS_WARNING("nsICookiePermission implementation not available - some features won't work!"); return NS_OK; } @@ -647,15 +646,7 @@ nsCookieService::GetCookieString(nsIURI *aHostURI, nsIChannel *aChannel, char **aCookie) { - // try to determine first party URI - nsCOMPtr firstURI; - if (aChannel) { - nsCOMPtr httpInternal = do_QueryInterface(aChannel); - if (httpInternal) - httpInternal->GetDocumentURI(getter_AddRefs(firstURI)); - } - - GetCookieInternal(aHostURI, firstURI, aChannel, PR_FALSE, aCookie); + GetCookieInternal(aHostURI, aChannel, PR_FALSE, aCookie); return NS_OK; } @@ -666,7 +657,7 @@ nsCookieService::GetCookieStringFromHttp(nsIURI *aHostURI, nsIChannel *aChannel, char **aCookie) { - GetCookieInternal(aHostURI, aFirstURI, aChannel, PR_TRUE, aCookie); + GetCookieInternal(aHostURI, aChannel, PR_TRUE, aCookie); return NS_OK; } @@ -677,16 +668,7 @@ nsCookieService::SetCookieString(nsIURI *aHostURI, const char *aCookieHeader, nsIChannel *aChannel) { - // try to determine first party URI - nsCOMPtr firstURI; - - if (aChannel) { - nsCOMPtr httpInternal = do_QueryInterface(aChannel); - if (httpInternal) - httpInternal->GetDocumentURI(getter_AddRefs(firstURI)); - } - - return SetCookieStringInternal(aHostURI, firstURI, aPrompt, aCookieHeader, nsnull, aChannel, PR_FALSE); + return SetCookieStringInternal(aHostURI, aPrompt, aCookieHeader, nsnull, aChannel, PR_FALSE); } NS_IMETHODIMP @@ -697,12 +679,11 @@ nsCookieService::SetCookieStringFromHttp(nsIURI *aHostURI, const char *aServerTime, nsIChannel *aChannel) { - return SetCookieStringInternal(aHostURI, aFirstURI, aPrompt, aCookieHeader, aServerTime, aChannel, PR_TRUE); + return SetCookieStringInternal(aHostURI, aPrompt, aCookieHeader, aServerTime, aChannel, PR_TRUE); } nsresult nsCookieService::SetCookieStringInternal(nsIURI *aHostURI, - nsIURI *aFirstURI, nsIPrompt *aPrompt, const char *aCookieHeader, const char *aServerTime, @@ -715,7 +696,7 @@ nsCookieService::SetCookieStringInternal(nsIURI *aHostURI, } // check default prefs - PRUint32 cookieStatus = CheckPrefs(aHostURI, aFirstURI, aChannel, aCookieHeader); + PRUint32 cookieStatus = CheckPrefs(aHostURI, aChannel, aCookieHeader); // fire a notification if cookie was rejected (but not if there was an error) switch (cookieStatus) { case STATUS_REJECTED: @@ -1119,7 +1100,6 @@ static inline PRBool ispathdelimiter(char c) { return c == '/' || c == '?' || c void nsCookieService::GetCookieInternal(nsIURI *aHostURI, - nsIURI *aFirstURI, nsIChannel *aChannel, PRBool aHttpBound, char **aCookie) @@ -1132,7 +1112,7 @@ nsCookieService::GetCookieInternal(nsIURI *aHostURI, } // check default prefs - PRUint32 cookieStatus = CheckPrefs(aHostURI, aFirstURI, aChannel, nsnull); + PRUint32 cookieStatus = CheckPrefs(aHostURI, aChannel, nsnull); // for GetCookie(), we don't fire rejection notifications. switch (cookieStatus) { case STATUS_REJECTED: @@ -1729,15 +1709,11 @@ PRBool nsCookieService::IsForeign(nsIURI *aHostURI, nsIURI *aFirstURI) { - // if aFirstURI is null, default to not foreign - if (!aFirstURI) { - return PR_FALSE; - } - // Get hosts nsCAutoString currentHost, firstHost; if (NS_FAILED(aHostURI->GetAsciiHost(currentHost)) || NS_FAILED(aFirstURI->GetAsciiHost(firstHost))) { + // assume foreign return PR_TRUE; } // trim trailing dots @@ -1758,19 +1734,10 @@ nsCookieService::IsForeign(nsIURI *aHostURI, if (firstHost.Equals(currentHost)) return PR_FALSE; - // chrome URLs are never foreign (otherwise sidebar cookies won't work). - // eventually we want to have a protocol whitelist here, - // _or_ do something smart with nsIProtocolHandler::protocolFlags. - PRBool isChrome = PR_FALSE; - nsresult rv = aFirstURI->SchemeIs("chrome", &isChrome); - if (NS_SUCCEEDED(rv) && isChrome) { - return PR_FALSE; - } - // get the base domain for the originating URI. // e.g. for "images.bbc.co.uk", this would be "bbc.co.uk". nsCAutoString baseDomain; - rv = mTLDService->GetBaseDomain(aFirstURI, 0, baseDomain); + nsresult rv = mTLDService->GetBaseDomain(aFirstURI, 0, baseDomain); if (NS_FAILED(rv)) { // URI is an IP, eTLD, or something else went wrong - assume foreign return PR_TRUE; @@ -1787,35 +1754,14 @@ nsCookieService::IsForeign(nsIURI *aHostURI, PRUint32 nsCookieService::CheckPrefs(nsIURI *aHostURI, - nsIURI *aFirstURI, nsIChannel *aChannel, const char *aCookieHeader) { - // pref tree: - // 0) get the scheme strings from the two URI's - // 1) disallow ftp - // 2) disallow mailnews, if pref set - // 3) perform a permissionlist lookup to see if an entry exists for this host - // (a match here will override defaults in 4) - // 4) go through enumerated permissions to see which one we have: - // -> cookies disabled: return - // -> dontacceptforeign: check if cookie is foreign - - // first, get the URI scheme for further use - // if GetScheme fails on aHostURI, reject; aFirstURI is optional, so failing is ok - nsCAutoString currentURIScheme, firstURIScheme; - nsresult rv, rv2 = NS_OK; - rv = aHostURI->GetScheme(currentURIScheme); - if (aFirstURI) { - rv2 = aFirstURI->GetScheme(firstURIScheme); - } - if (NS_FAILED(rv) || NS_FAILED(rv2)) { - COOKIE_LOGFAILURE(aCookieHeader ? SET_COOKIE : GET_COOKIE, aHostURI, aCookieHeader, "couldn't get scheme of host URI"); - return STATUS_REJECTED_WITH_ERROR; - } + nsresult rv; // don't let ftp sites get/set cookies (could be a security issue) - if (currentURIScheme.EqualsLiteral("ftp")) { + PRBool ftp; + if (NS_SUCCEEDED(aHostURI->SchemeIs("ftp", &ftp)) && ftp) { COOKIE_LOGFAILURE(aCookieHeader ? SET_COOKIE : GET_COOKIE, aHostURI, aCookieHeader, "ftp sites cannot read cookies"); return STATUS_REJECTED_WITH_ERROR; } @@ -1824,7 +1770,7 @@ nsCookieService::CheckPrefs(nsIURI *aHostURI, // default prefs. see bug 184059. if (mPermissionService) { nsCookieAccess access; - rv = mPermissionService->CanAccess(aHostURI, aFirstURI, aChannel, &access); + rv = mPermissionService->CanAccess(aHostURI, aChannel, &access); // if we found an entry, use it if (NS_SUCCEEDED(rv)) { @@ -1839,19 +1785,20 @@ nsCookieService::CheckPrefs(nsIURI *aHostURI, } } - // check default prefs - go thru enumerated permissions + // check default prefs if (mCookiesPermissions == BEHAVIOR_REJECT) { COOKIE_LOGFAILURE(aCookieHeader ? SET_COOKIE : GET_COOKIE, aHostURI, aCookieHeader, "cookies are disabled"); return STATUS_REJECTED; } else if (mCookiesPermissions == BEHAVIOR_REJECTFOREIGN) { - // check if cookie is foreign. - // if aFirstURI is null, allow by default + // check if cookie is foreign + if (!mPermissionService) + return STATUS_REJECTED; - // note: this can be circumvented if we have http redirects within html, - // since the documentURI attribute isn't always correctly - // passed to the redirected channels. (or isn't correctly set in the first place) - if (IsForeign(aHostURI, aFirstURI)) { + nsCOMPtr firstURI; + rv = mPermissionService->GetOriginatingURI(aChannel, getter_AddRefs(firstURI)); + + if (NS_FAILED(rv) || IsForeign(aHostURI, firstURI)) { COOKIE_LOGFAILURE(aCookieHeader ? SET_COOKIE : GET_COOKIE, aHostURI, aCookieHeader, "originating server test failed"); return STATUS_REJECTED; } diff --git a/netwerk/cookie/src/nsCookieService.h b/netwerk/cookie/src/nsCookieService.h index 513b9145758..8a3f5473566 100644 --- a/netwerk/cookie/src/nsCookieService.h +++ b/netwerk/cookie/src/nsCookieService.h @@ -54,9 +54,6 @@ struct nsCookieAttributes; struct nsListIter; struct nsEnumerationData; -class nsAutoVoidArray; - -class nsIPrefBranch; class nsICookiePermission; class nsIEffectiveTLDService; class nsIPrefBranch; @@ -168,8 +165,8 @@ class nsCookieService : public nsICookieService nsresult InitDB(); nsresult CreateTable(); nsresult Read(); - void GetCookieInternal(nsIURI *aHostURI, nsIURI *aFirstURI, nsIChannel *aChannel, PRBool aHttpBound, char **aCookie); - nsresult SetCookieStringInternal(nsIURI *aHostURI, nsIURI *aFirstURI, nsIPrompt *aPrompt, const char *aCookieHeader, const char *aServerTime, nsIChannel *aChannel, PRBool aFromHttp); + void GetCookieInternal(nsIURI *aHostURI, nsIChannel *aChannel, PRBool aHttpBound, char **aCookie); + nsresult SetCookieStringInternal(nsIURI *aHostURI, nsIPrompt *aPrompt, const char *aCookieHeader, const char *aServerTime, nsIChannel *aChannel, PRBool aFromHttp); PRBool SetCookieInternal(nsIURI *aHostURI, nsIChannel *aChannel, nsDependentCString &aCookieHeader, PRInt64 aServerTime, PRBool aFromHttp); void AddInternal(nsCookie *aCookie, PRInt64 aCurrentTime, nsIURI *aHostURI, const char *aCookieHeader, PRBool aFromHttp); void RemoveCookieFromList(nsListIter &aIter); @@ -178,7 +175,7 @@ class nsCookieService : public nsICookieService static PRBool GetTokenValue(nsASingleFragmentCString::const_char_iterator &aIter, nsASingleFragmentCString::const_char_iterator &aEndIter, nsDependentCSubstring &aTokenString, nsDependentCSubstring &aTokenValue, PRBool &aEqualsFound); static PRBool ParseAttributes(nsDependentCString &aCookieHeader, nsCookieAttributes &aCookie); PRBool IsForeign(nsIURI *aHostURI, nsIURI *aFirstURI); - PRUint32 CheckPrefs(nsIURI *aHostURI, nsIURI *aFirstURI, nsIChannel *aChannel, const char *aCookieHeader); + PRUint32 CheckPrefs(nsIURI *aHostURI, nsIChannel *aChannel, const char *aCookieHeader); PRBool CheckDomain(nsCookieAttributes &aCookie, nsIURI *aHostURI); static PRBool CheckPath(nsCookieAttributes &aCookie, nsIURI *aHostURI); static PRBool GetExpiry(nsCookieAttributes &aCookie, PRInt64 aServerTime, PRInt64 aCurrentTime); diff --git a/netwerk/test/TestCookie.cpp b/netwerk/test/TestCookie.cpp index 8e64621928d..e8981e984e6 100644 --- a/netwerk/test/TestCookie.cpp +++ b/netwerk/test/TestCookie.cpp @@ -203,8 +203,9 @@ void InitPrefs(nsIPrefBranch *aPrefBranch) { // init some relevant prefs, so the tests don't go awry. - // we use the most restrictive set of prefs we can. - aPrefBranch->SetIntPref(kCookiesPermissions, 1); // 'reject foreign' + // we use the most restrictive set of prefs we can; + // however, we don't test third party blocking here. + aPrefBranch->SetIntPref(kCookiesPermissions, 0); // accept all aPrefBranch->SetBoolPref(kCookiesDisabledForMailNews, PR_TRUE); aPrefBranch->SetBoolPref(kCookiesLifetimeEnabled, PR_TRUE); aPrefBranch->SetIntPref(kCookiesLifetimeCurrentSession, 0); @@ -512,76 +513,6 @@ main(PRInt32 argc, char *argv[]) allTestsPassed = PrintResult(rv, 9) && allTestsPassed; - // *** foreign cookie tests - printf("*** Beginning foreign cookie tests...\n"); - - // test the blocking of foreign cookies, under various circumstances. - // order of URI arguments is hostURI, firstURI - SetACookie(cookieService, "http://yahoo.com/", "http://yahoo.com/", "test=foreign; domain=.yahoo.com", nsnull); - GetACookie(cookieService, "http://yahoo.com/", "http://yahoo.com/", getter_Copies(cookie)); - rv[0] = CheckResult(cookie.get(), MUST_EQUAL, "test=foreign"); - SetACookie(cookieService, "http://weather.yahoo.com/", "http://yahoo.com/", "test=foreign; domain=.yahoo.com", nsnull); - GetACookie(cookieService, "http://notweather.yahoo.com/", "http://sport.yahoo.com/", getter_Copies(cookie)); - rv[1] = CheckResult(cookie.get(), MUST_EQUAL, "test=foreign"); - SetACookie(cookieService, "http://moose.yahoo.com/", "http://canada.yahoo.com/", "test=foreign; domain=.yahoo.com", nsnull); - GetACookie(cookieService, "http://yahoo.com/", "http://sport.yahoo.com/", getter_Copies(cookie)); - rv[2] = CheckResult(cookie.get(), MUST_EQUAL, "test=foreign"); - GetACookie(cookieService, "http://sport.yahoo.com/", "http://yahoo.com/", getter_Copies(cookie)); - rv[3] = CheckResult(cookie.get(), MUST_EQUAL, "test=foreign"); - SetACookie(cookieService, "http://jack.yahoo.com/", "http://jill.yahoo.com/", "test=foreign; domain=.yahoo.com; max-age=0", nsnull); - GetACookie(cookieService, "http://jane.yahoo.com/", "http://yahoo.com/", getter_Copies(cookie)); - rv[4] = CheckResult(cookie.get(), MUST_BE_NULL); - - SetACookie(cookieService, "http://moose.yahoo.com/", "http://foo.moose.yahoo.com/", "test=foreign; domain=.yahoo.com", nsnull); - GetACookie(cookieService, "http://yahoo.com/", "http://yahoo.com/", getter_Copies(cookie)); - rv[5] = CheckResult(cookie.get(), MUST_EQUAL, "test=foreign"); - SetACookie(cookieService, "http://foo.bar.yahoo.com/", "http://yahoo.com/", "test=foreign; domain=.yahoo.com", nsnull); - GetACookie(cookieService, "http://yahoo.com/", "http://yahoo.com/", getter_Copies(cookie)); - rv[6] = CheckResult(cookie.get(), MUST_EQUAL, "test=foreign"); - SetACookie(cookieService, "http://foo.bar.yahoo.com/", "http://yahoo.com/", "test=foreign; domain=.yahoo.com; max-age=0", nsnull); - GetACookie(cookieService, "http://yahoo.com/", "http://yahoo.com/", getter_Copies(cookie)); - rv[7] = CheckResult(cookie.get(), MUST_BE_NULL); - - // test handling of IP addresses by the foreign blocking algo - SetACookie(cookieService, "http://192.168.54.33/", "http://192.168.54.33/", "test=foreign; domain=192.168.54.33", nsnull); - GetACookie(cookieService, "http://192.168.54.33/", "http://192.168.54.33/", getter_Copies(cookie)); - rv[8] = CheckResult(cookie.get(), MUST_EQUAL, "test=foreign"); - GetACookie(cookieService, "http://192.168.54.33./", "http://.192.168.54.33../", getter_Copies(cookie)); - rv[9] = CheckResult(cookie.get(), MUST_EQUAL, "test=foreign"); - GetACookie(cookieService, "http://192.168.54.33/", nsnull, getter_Copies(cookie)); - rv[10] = CheckResult(cookie.get(), MUST_EQUAL, "test=foreign"); - GetACookie(cookieService, "http://192.168.54.33/", "http://148.168.54.33", getter_Copies(cookie)); - rv[11] = CheckResult(cookie.get(), MUST_BE_NULL); - SetACookie(cookieService, "http://192.168.54.33/", "http://192.168.54.33/", "test=foreign; domain=192.168.54.33; max-age=0", nsnull); - GetACookie(cookieService, "http://192.168.54.33/", "http://192.168.54.33/", getter_Copies(cookie)); - rv[12] = CheckResult(cookie.get(), MUST_BE_NULL); - SetACookie(cookieService, "http://192.168.54.33/", "http://148.168.54.33/", "test=foreign; domain=192.168.54.33", nsnull); - GetACookie(cookieService, "http://192.168.54.33/", "http://192.168.54.33/", getter_Copies(cookie)); - rv[13] = CheckResult(cookie.get(), MUST_BE_NULL); - - // test the case where the host is an eTLD, e.g. http://co.tv/ (a legitimate site) - SetACookie(cookieService, "http://co.uk/", "http://co.uk/", "test=foreign; domain=.co.uk", nsnull); - GetACookie(cookieService, "http://co.uk/", "http://co.uk/", getter_Copies(cookie)); - // should be rejected, can't set a domain cookie for .co.uk - rv[14] = CheckResult(cookie.get(), MUST_BE_NULL); - SetACookie(cookieService, "http://co.uk/", "http://co.uk/", "test=foreign", nsnull); - GetACookie(cookieService, "http://co.uk/", "http://co.uk/", getter_Copies(cookie)); - // should be allowed, hostURI == firstURI and it's not a domain cookie - rv[15] = CheckResult(cookie.get(), MUST_EQUAL, "test=foreign"); - GetACookie(cookieService, "http://oblivious.co.uk/", nsnull, getter_Copies(cookie)); - rv[16] = CheckResult(cookie.get(), MUST_BE_NULL); - // remove cookie - SetACookie(cookieService, "http://co.uk/", "http://co.uk/", "test=foreign; max-age=0", nsnull); - GetACookie(cookieService, "http://co.uk/", "http://co.uk/", getter_Copies(cookie)); - rv[17] = CheckResult(cookie.get(), MUST_BE_NULL); - SetACookie(cookieService, "http://co.uk/", "http://evil.co.uk/", "test=foreign", nsnull); - GetACookie(cookieService, "http://co.uk/", "http://co.uk/", getter_Copies(cookie)); - // should be rejected, hostURI != firstURI and hostURI is an eTLD - rv[18] = CheckResult(cookie.get(), MUST_BE_NULL); - - allTestsPassed = PrintResult(rv, 19) && allTestsPassed; - - // *** parser tests printf("*** Beginning parser tests...\n"); @@ -639,15 +570,7 @@ main(PRInt32 argc, char *argv[]) GetACookie(cookieService, "http://mail.co.uk/", nsnull, getter_Copies(cookie)); rv[4] = CheckResult(cookie.get(), MUST_BE_NULL); - // test non-null firstURI's, i) from mailnews ii) not from mailnews - SetACookie(cookieService, "mailbox://mail.co.uk/", "http://mail.co.uk/", "test=mailnews", nsnull); - GetACookie(cookieService, "http://mail.co.uk/", nsnull, getter_Copies(cookie)); - rv[5] = CheckResult(cookie.get(), MUST_BE_NULL); - SetACookie(cookieService, "http://mail.co.uk/", "mailbox://mail.co.uk/", "test=mailnews", nsnull); - GetACookie(cookieService, "http://mail.co.uk/", nsnull, getter_Copies(cookie)); - rv[6] = CheckResult(cookie.get(), MUST_BE_NULL); - - allTestsPassed = PrintResult(rv, 7) && allTestsPassed; + allTestsPassed = PrintResult(rv, 5) && allTestsPassed; // *** path ordering tests