From 32154830afc6cccd4d6d5550cc71ed2811c0b0ea Mon Sep 17 00:00:00 2001 From: Dave Camp Date: Sun, 4 Jan 2009 23:40:29 -0800 Subject: [PATCH] Bug 441359: Run scripts/css through the classifier. r+sr=sicking --- build/pgo/server-locations.txt | 5 ++ content/base/src/nsObjectLoadingContent.cpp | 2 +- content/base/src/nsScriptLoader.cpp | 18 ++++- docshell/base/nsDocShell.cpp | 62 ++++++++++++-- docshell/base/nsDocShell.h | 7 +- docshell/base/nsIChannelClassifier.idl | 12 ++- layout/style/nsCSSLoader.cpp | 15 ++++ .../url-classifier/tests/Makefile.in | 4 + .../tests/mochitest/Makefile.in | 57 +++++++++++++ .../tests/mochitest/classifierFrame.html | 34 ++++++++ .../url-classifier/tests/mochitest/evil.css | 1 + .../url-classifier/tests/mochitest/evil.js | 1 + .../url-classifier/tests/mochitest/import.css | 1 + .../tests/mochitest/test_classifier.html | 81 +++++++++++++++++++ 14 files changed, 287 insertions(+), 13 deletions(-) create mode 100644 toolkit/components/url-classifier/tests/mochitest/Makefile.in create mode 100644 toolkit/components/url-classifier/tests/mochitest/classifierFrame.html create mode 100644 toolkit/components/url-classifier/tests/mochitest/evil.css create mode 100644 toolkit/components/url-classifier/tests/mochitest/evil.js create mode 100644 toolkit/components/url-classifier/tests/mochitest/import.css create mode 100644 toolkit/components/url-classifier/tests/mochitest/test_classifier.html diff --git a/build/pgo/server-locations.txt b/build/pgo/server-locations.txt index a93a67fda37f..dd59b91069ed 100644 --- a/build/pgo/server-locations.txt +++ b/build/pgo/server-locations.txt @@ -147,3 +147,8 @@ https://sectest1.example.org:443 privileged https://sub.sectest2.example.org:443 privileged https://sectest2.example.org:443 https://sub.sectest1.example.org:443 + +# +# Used while testing the url-classifier +# +http://malware.com:80 privileged diff --git a/content/base/src/nsObjectLoadingContent.cpp b/content/base/src/nsObjectLoadingContent.cpp index a6e758ce8334..b5d6a9ab1d01 100644 --- a/content/base/src/nsObjectLoadingContent.cpp +++ b/content/base/src/nsObjectLoadingContent.cpp @@ -1758,7 +1758,7 @@ nsObjectLoadingContent::CheckClassifier(nsIChannel *aChannel) do_CreateInstance(NS_CHANNELCLASSIFIER_CONTRACTID, &rv); NS_ENSURE_SUCCESS(rv, rv); - rv = classifier->Start(aChannel); + rv = classifier->Start(aChannel, PR_FALSE); if (rv == NS_ERROR_FACTORY_NOT_REGISTERED) { // no URI classifier, ignore this return NS_OK; diff --git a/content/base/src/nsScriptLoader.cpp b/content/base/src/nsScriptLoader.cpp index 6f08b65adb26..79417503848e 100644 --- a/content/base/src/nsScriptLoader.cpp +++ b/content/base/src/nsScriptLoader.cpp @@ -68,6 +68,8 @@ #include "nsContentErrors.h" #include "nsIParser.h" #include "nsThreadUtils.h" +#include "nsIChannelClassifier.h" +#include "nsDocShellCID.h" ////////////////////////////////////////////////////////////// // Per-request data structure @@ -264,7 +266,21 @@ nsScriptLoader::StartLoad(nsScriptLoadRequest *aRequest, const nsAString &aType) rv = NS_NewStreamLoader(getter_AddRefs(loader), this); NS_ENSURE_SUCCESS(rv, rv); - return channel->AsyncOpen(loader, aRequest); + rv = channel->AsyncOpen(loader, aRequest); + NS_ENSURE_SUCCESS(rv, rv); + + // Check the load against the URI classifier + nsCOMPtr classifier = + do_CreateInstance(NS_CHANNELCLASSIFIER_CONTRACTID); + if (classifier) { + rv = classifier->Start(channel, PR_TRUE); + if (NS_FAILED(rv)) { + channel->Cancel(rv); + return rv; + } + } + + return NS_OK; } PRBool diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp index b373e945c810..3888e30eeb07 100644 --- a/docshell/base/nsDocShell.cpp +++ b/docshell/base/nsDocShell.cpp @@ -7774,7 +7774,7 @@ nsDocShell::CheckClassifier(nsIChannel *aChannel) nsRefPtr classifier = new nsClassifierCallback(); if (!classifier) return NS_ERROR_OUT_OF_MEMORY; - nsresult rv = classifier->Start(aChannel); + nsresult rv = classifier->Start(aChannel, PR_FALSE); if (rv == NS_ERROR_FACTORY_NOT_REGISTERED || rv == NS_ERROR_NOT_AVAILABLE) { // no URI classifier => ignored cases @@ -9660,10 +9660,12 @@ nsDocShell::IsOKToLoadURI(nsIURI* aURI) // nsClassifierCallback //***************************************************************************** -NS_IMPL_ISUPPORTS3(nsClassifierCallback, +NS_IMPL_ISUPPORTS5(nsClassifierCallback, nsIChannelClassifier, nsIURIClassifierCallback, - nsIRunnable) + nsIRunnable, + nsIChannelEventSink, + nsIInterfaceRequestor) NS_IMETHODIMP nsClassifierCallback::Run() @@ -9688,7 +9690,7 @@ nsClassifierCallback::Run() // Don't bother to run the classifier on a cached load that was // previously classified. - if (HasBeenClassified()) { + if (HasBeenClassified(channel)) { return NS_OK; } @@ -9780,10 +9782,10 @@ nsClassifierCallback::MarkEntryClassified(nsresult status) } PRBool -nsClassifierCallback::HasBeenClassified() +nsClassifierCallback::HasBeenClassified(nsIChannel *aChannel) { nsCOMPtr cachingChannel = - do_QueryInterface(mSuspendedChannel); + do_QueryInterface(aChannel); if (!cachingChannel) { return PR_FALSE; } @@ -9839,15 +9841,26 @@ nsClassifierCallback::OnClassifyComplete(nsresult aErrorCode) } NS_IMETHODIMP -nsClassifierCallback::Start(nsIChannel *aChannel) +nsClassifierCallback::Start(nsIChannel *aChannel, PRBool aInstallListener) { mChannel = aChannel; + + if (aInstallListener) { + nsresult rv = aChannel->GetNotificationCallbacks + (getter_AddRefs(mNotificationCallbacks)); + NS_ENSURE_SUCCESS(rv, rv); + + rv = aChannel->SetNotificationCallbacks + (static_cast(this)); + NS_ENSURE_SUCCESS(rv, rv); + } + return Run(); } NS_IMETHODIMP nsClassifierCallback::OnRedirect(nsIChannel *aOldChannel, - nsIChannel *aNewChannel) + nsIChannel *aNewChannel) { mChannel = aNewChannel; @@ -9877,3 +9890,36 @@ nsClassifierCallback::Cancel() return NS_OK; } + +NS_IMETHODIMP +nsClassifierCallback::OnChannelRedirect(nsIChannel *aOldChannel, + nsIChannel *aNewChannel, + PRUint32 aFlags) +{ + nsresult rv = OnRedirect(aOldChannel, aNewChannel); + NS_ENSURE_SUCCESS(rv, rv); + + if (mNotificationCallbacks) { + nsCOMPtr sink = + do_GetInterface(mNotificationCallbacks); + if (sink) { + return sink->OnChannelRedirect(aOldChannel, aNewChannel, aFlags); + } + } + + return NS_OK; +} + +NS_IMETHODIMP +nsClassifierCallback::GetInterface(const nsIID &aIID, void **aResult) +{ + if (aIID.Equals(NS_GET_IID(nsIChannelEventSink))) { + NS_ADDREF_THIS(); + *aResult = static_cast(this); + return NS_OK; + } else if (mNotificationCallbacks) { + return mNotificationCallbacks->GetInterface(aIID, aResult); + } else { + return NS_ERROR_NO_INTERFACE; + } +} diff --git a/docshell/base/nsDocShell.h b/docshell/base/nsDocShell.h index 2d2776f08eca..190d5b0189c4 100644 --- a/docshell/base/nsDocShell.h +++ b/docshell/base/nsDocShell.h @@ -148,6 +148,8 @@ protected: class nsClassifierCallback : public nsIChannelClassifier , public nsIURIClassifierCallback , public nsIRunnable + , public nsIChannelEventSink + , public nsIInterfaceRequestor { public: nsClassifierCallback() {} @@ -157,13 +159,16 @@ public: NS_DECL_NSICHANNELCLASSIFIER NS_DECL_NSIURICLASSIFIERCALLBACK NS_DECL_NSIRUNNABLE + NS_DECL_NSICHANNELEVENTSINK + NS_DECL_NSIINTERFACEREQUESTOR private: nsCOMPtr mChannel; nsCOMPtr mSuspendedChannel; + nsCOMPtr mNotificationCallbacks; void MarkEntryClassified(nsresult status); - PRBool HasBeenClassified(); + PRBool HasBeenClassified(nsIChannel *aChannel); }; //***************************************************************************** diff --git a/docshell/base/nsIChannelClassifier.idl b/docshell/base/nsIChannelClassifier.idl index 0c19c3c1dd61..6bd48b7e17de 100644 --- a/docshell/base/nsIChannelClassifier.idl +++ b/docshell/base/nsIChannelClassifier.idl @@ -46,7 +46,7 @@ interface nsIChannel; * URI classifier service, and cancels the channel before OnStartRequest * if it is found on a blacklist. */ -[scriptable, uuid(d17f8f74-d403-4dea-b124-3ace5dbe44dc)] +[scriptable, uuid(1481c5b5-9f6e-4995-8fe3-2aad5c06440d)] interface nsIChannelClassifier : nsISupports { /** @@ -59,10 +59,18 @@ interface nsIChannelClassifier : nsISupports * If there is no URI classifier service, NS_ERROR_FACTORY_NOT_REGISTERED * will be returned. * + * This method must be called immediately after AsyncOpen() has been called + * on the channel. + * * @param aChannel * The channel to suspend. + * @param aInstallListener + * If true, the classifier will install notification + * callbacks to listen for redirects. The classifier will + * pass all notifications on to the channel's existing + * notification callbacks. */ - void start(in nsIChannel aChannel); + void start(in nsIChannel aChannel, in boolean aInstallListener); /** * Notify the classifier that the channel was redirected. The new channel diff --git a/layout/style/nsCSSLoader.cpp b/layout/style/nsCSSLoader.cpp index deffc33ff3d9..a6194e9138a8 100644 --- a/layout/style/nsCSSLoader.cpp +++ b/layout/style/nsCSSLoader.cpp @@ -79,6 +79,8 @@ #include "nsICSSImportRule.h" #include "nsThreadUtils.h" #include "nsGkAtoms.h" +#include "nsDocShellCID.h" +#include "nsIChannelClassifier.h" #ifdef MOZ_XUL #include "nsXULPrototypeCache.h" @@ -1455,6 +1457,19 @@ CSSLoaderImpl::LoadSheet(SheetLoadData* aLoadData, StyleSheetState aSheetState) mSyncCallback = PR_FALSE; #endif + // Check the load against the URI classifier + nsCOMPtr classifier = + do_CreateInstance(NS_CHANNELCLASSIFIER_CONTRACTID); + if (classifier) { + rv = classifier->Start(channel, PR_TRUE); + if (NS_FAILED(rv)) { + LOG_ERROR((" Failed to classify URI")); + SheetComplete(aLoadData, rv); + channel->Cancel(rv); + return rv; + } + } + if (NS_FAILED(rv)) { LOG_ERROR((" Failed to create stream loader")); SheetComplete(aLoadData, rv); diff --git a/toolkit/components/url-classifier/tests/Makefile.in b/toolkit/components/url-classifier/tests/Makefile.in index 1d9e6f6e406b..a0d1ed0c3dc4 100644 --- a/toolkit/components/url-classifier/tests/Makefile.in +++ b/toolkit/components/url-classifier/tests/Makefile.in @@ -55,6 +55,10 @@ REQUIRES = \ necko \ $(NULL) +# mochitest tests +DIRS += mochitest \ + $(NULL) + # xpcshell tests XPCSHELL_TESTS=unit diff --git a/toolkit/components/url-classifier/tests/mochitest/Makefile.in b/toolkit/components/url-classifier/tests/mochitest/Makefile.in new file mode 100644 index 000000000000..e5d1e93c5946 --- /dev/null +++ b/toolkit/components/url-classifier/tests/mochitest/Makefile.in @@ -0,0 +1,57 @@ +# +# ***** 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 Corporation. +# Portions created by the Initial Developer are Copyright (C) 2008 +# 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 = toolkit/components/url-classifier/tests/mochitest + +MODULE = test_url-classifier + +include $(DEPTH)/config/autoconf.mk +include $(topsrcdir)/config/rules.mk + +_TEST_FILES = \ + test_classifier.html \ + classifierFrame.html \ + evil.js \ + evil.css \ + import.css \ + $(NULL) + +libs:: $(_TEST_FILES) + $(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir) diff --git a/toolkit/components/url-classifier/tests/mochitest/classifierFrame.html b/toolkit/components/url-classifier/tests/mochitest/classifierFrame.html new file mode 100644 index 000000000000..221909819705 --- /dev/null +++ b/toolkit/components/url-classifier/tests/mochitest/classifierFrame.html @@ -0,0 +1,34 @@ + + + + + + + + + + + + + +The following should not be hidden: +
STYLE TEST
+ diff --git a/toolkit/components/url-classifier/tests/mochitest/evil.css b/toolkit/components/url-classifier/tests/mochitest/evil.css new file mode 100644 index 000000000000..f6f08d7c5cd1 --- /dev/null +++ b/toolkit/components/url-classifier/tests/mochitest/evil.css @@ -0,0 +1 @@ +#styleCheck { visibility: hidden; } \ No newline at end of file diff --git a/toolkit/components/url-classifier/tests/mochitest/evil.js b/toolkit/components/url-classifier/tests/mochitest/evil.js new file mode 100644 index 000000000000..27f2e8c43d5c --- /dev/null +++ b/toolkit/components/url-classifier/tests/mochitest/evil.js @@ -0,0 +1 @@ +scriptItem = "loaded malware javascript!"; diff --git a/toolkit/components/url-classifier/tests/mochitest/import.css b/toolkit/components/url-classifier/tests/mochitest/import.css new file mode 100644 index 000000000000..91f5fbf14329 --- /dev/null +++ b/toolkit/components/url-classifier/tests/mochitest/import.css @@ -0,0 +1 @@ +@import url("http://malware.com/tests/docshell/test/classifierBad.css"); diff --git a/toolkit/components/url-classifier/tests/mochitest/test_classifier.html b/toolkit/components/url-classifier/tests/mochitest/test_classifier.html new file mode 100644 index 000000000000..3378f2431e19 --- /dev/null +++ b/toolkit/components/url-classifier/tests/mochitest/test_classifier.html @@ -0,0 +1,81 @@ + + + + Test the URI Classifier + + + + + +

+ +
+
+
+
+ + +