Bug 441359: Run scripts/css through the classifier. r+sr=sicking

This commit is contained in:
Dave Camp 2009-01-04 23:40:29 -08:00
Родитель c31f761356
Коммит 32154830af
14 изменённых файлов: 287 добавлений и 13 удалений

Просмотреть файл

@ -147,3 +147,8 @@ https://sectest1.example.org:443 privileged
https://sub.sectest2.example.org:443 privileged https://sub.sectest2.example.org:443 privileged
https://sectest2.example.org:443 https://sectest2.example.org:443
https://sub.sectest1.example.org:443 https://sub.sectest1.example.org:443
#
# Used while testing the url-classifier
#
http://malware.com:80 privileged

Просмотреть файл

@ -1758,7 +1758,7 @@ nsObjectLoadingContent::CheckClassifier(nsIChannel *aChannel)
do_CreateInstance(NS_CHANNELCLASSIFIER_CONTRACTID, &rv); do_CreateInstance(NS_CHANNELCLASSIFIER_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
rv = classifier->Start(aChannel); rv = classifier->Start(aChannel, PR_FALSE);
if (rv == NS_ERROR_FACTORY_NOT_REGISTERED) { if (rv == NS_ERROR_FACTORY_NOT_REGISTERED) {
// no URI classifier, ignore this // no URI classifier, ignore this
return NS_OK; return NS_OK;

Просмотреть файл

@ -68,6 +68,8 @@
#include "nsContentErrors.h" #include "nsContentErrors.h"
#include "nsIParser.h" #include "nsIParser.h"
#include "nsThreadUtils.h" #include "nsThreadUtils.h"
#include "nsIChannelClassifier.h"
#include "nsDocShellCID.h"
////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////
// Per-request data structure // Per-request data structure
@ -264,7 +266,21 @@ nsScriptLoader::StartLoad(nsScriptLoadRequest *aRequest, const nsAString &aType)
rv = NS_NewStreamLoader(getter_AddRefs(loader), this); rv = NS_NewStreamLoader(getter_AddRefs(loader), this);
NS_ENSURE_SUCCESS(rv, rv); 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<nsIChannelClassifier> 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 PRBool

Просмотреть файл

@ -7774,7 +7774,7 @@ nsDocShell::CheckClassifier(nsIChannel *aChannel)
nsRefPtr<nsClassifierCallback> classifier = new nsClassifierCallback(); nsRefPtr<nsClassifierCallback> classifier = new nsClassifierCallback();
if (!classifier) return NS_ERROR_OUT_OF_MEMORY; 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 || if (rv == NS_ERROR_FACTORY_NOT_REGISTERED ||
rv == NS_ERROR_NOT_AVAILABLE) { rv == NS_ERROR_NOT_AVAILABLE) {
// no URI classifier => ignored cases // no URI classifier => ignored cases
@ -9660,10 +9660,12 @@ nsDocShell::IsOKToLoadURI(nsIURI* aURI)
// nsClassifierCallback // nsClassifierCallback
//***************************************************************************** //*****************************************************************************
NS_IMPL_ISUPPORTS3(nsClassifierCallback, NS_IMPL_ISUPPORTS5(nsClassifierCallback,
nsIChannelClassifier, nsIChannelClassifier,
nsIURIClassifierCallback, nsIURIClassifierCallback,
nsIRunnable) nsIRunnable,
nsIChannelEventSink,
nsIInterfaceRequestor)
NS_IMETHODIMP NS_IMETHODIMP
nsClassifierCallback::Run() nsClassifierCallback::Run()
@ -9688,7 +9690,7 @@ nsClassifierCallback::Run()
// Don't bother to run the classifier on a cached load that was // Don't bother to run the classifier on a cached load that was
// previously classified. // previously classified.
if (HasBeenClassified()) { if (HasBeenClassified(channel)) {
return NS_OK; return NS_OK;
} }
@ -9780,10 +9782,10 @@ nsClassifierCallback::MarkEntryClassified(nsresult status)
} }
PRBool PRBool
nsClassifierCallback::HasBeenClassified() nsClassifierCallback::HasBeenClassified(nsIChannel *aChannel)
{ {
nsCOMPtr<nsICachingChannel> cachingChannel = nsCOMPtr<nsICachingChannel> cachingChannel =
do_QueryInterface(mSuspendedChannel); do_QueryInterface(aChannel);
if (!cachingChannel) { if (!cachingChannel) {
return PR_FALSE; return PR_FALSE;
} }
@ -9839,15 +9841,26 @@ nsClassifierCallback::OnClassifyComplete(nsresult aErrorCode)
} }
NS_IMETHODIMP NS_IMETHODIMP
nsClassifierCallback::Start(nsIChannel *aChannel) nsClassifierCallback::Start(nsIChannel *aChannel, PRBool aInstallListener)
{ {
mChannel = aChannel; mChannel = aChannel;
if (aInstallListener) {
nsresult rv = aChannel->GetNotificationCallbacks
(getter_AddRefs(mNotificationCallbacks));
NS_ENSURE_SUCCESS(rv, rv);
rv = aChannel->SetNotificationCallbacks
(static_cast<nsIInterfaceRequestor*>(this));
NS_ENSURE_SUCCESS(rv, rv);
}
return Run(); return Run();
} }
NS_IMETHODIMP NS_IMETHODIMP
nsClassifierCallback::OnRedirect(nsIChannel *aOldChannel, nsClassifierCallback::OnRedirect(nsIChannel *aOldChannel,
nsIChannel *aNewChannel) nsIChannel *aNewChannel)
{ {
mChannel = aNewChannel; mChannel = aNewChannel;
@ -9877,3 +9890,36 @@ nsClassifierCallback::Cancel()
return NS_OK; 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<nsIChannelEventSink> 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<nsIChannelEventSink *>(this);
return NS_OK;
} else if (mNotificationCallbacks) {
return mNotificationCallbacks->GetInterface(aIID, aResult);
} else {
return NS_ERROR_NO_INTERFACE;
}
}

Просмотреть файл

@ -148,6 +148,8 @@ protected:
class nsClassifierCallback : public nsIChannelClassifier class nsClassifierCallback : public nsIChannelClassifier
, public nsIURIClassifierCallback , public nsIURIClassifierCallback
, public nsIRunnable , public nsIRunnable
, public nsIChannelEventSink
, public nsIInterfaceRequestor
{ {
public: public:
nsClassifierCallback() {} nsClassifierCallback() {}
@ -157,13 +159,16 @@ public:
NS_DECL_NSICHANNELCLASSIFIER NS_DECL_NSICHANNELCLASSIFIER
NS_DECL_NSIURICLASSIFIERCALLBACK NS_DECL_NSIURICLASSIFIERCALLBACK
NS_DECL_NSIRUNNABLE NS_DECL_NSIRUNNABLE
NS_DECL_NSICHANNELEVENTSINK
NS_DECL_NSIINTERFACEREQUESTOR
private: private:
nsCOMPtr<nsIChannel> mChannel; nsCOMPtr<nsIChannel> mChannel;
nsCOMPtr<nsIChannel> mSuspendedChannel; nsCOMPtr<nsIChannel> mSuspendedChannel;
nsCOMPtr<nsIInterfaceRequestor> mNotificationCallbacks;
void MarkEntryClassified(nsresult status); void MarkEntryClassified(nsresult status);
PRBool HasBeenClassified(); PRBool HasBeenClassified(nsIChannel *aChannel);
}; };
//***************************************************************************** //*****************************************************************************

Просмотреть файл

@ -46,7 +46,7 @@ interface nsIChannel;
* URI classifier service, and cancels the channel before OnStartRequest * URI classifier service, and cancels the channel before OnStartRequest
* if it is found on a blacklist. * if it is found on a blacklist.
*/ */
[scriptable, uuid(d17f8f74-d403-4dea-b124-3ace5dbe44dc)] [scriptable, uuid(1481c5b5-9f6e-4995-8fe3-2aad5c06440d)]
interface nsIChannelClassifier : nsISupports interface nsIChannelClassifier : nsISupports
{ {
/** /**
@ -59,10 +59,18 @@ interface nsIChannelClassifier : nsISupports
* If there is no URI classifier service, NS_ERROR_FACTORY_NOT_REGISTERED * If there is no URI classifier service, NS_ERROR_FACTORY_NOT_REGISTERED
* will be returned. * will be returned.
* *
* This method must be called immediately after AsyncOpen() has been called
* on the channel.
*
* @param aChannel * @param aChannel
* The channel to suspend. * 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 * Notify the classifier that the channel was redirected. The new channel

Просмотреть файл

@ -79,6 +79,8 @@
#include "nsICSSImportRule.h" #include "nsICSSImportRule.h"
#include "nsThreadUtils.h" #include "nsThreadUtils.h"
#include "nsGkAtoms.h" #include "nsGkAtoms.h"
#include "nsDocShellCID.h"
#include "nsIChannelClassifier.h"
#ifdef MOZ_XUL #ifdef MOZ_XUL
#include "nsXULPrototypeCache.h" #include "nsXULPrototypeCache.h"
@ -1455,6 +1457,19 @@ CSSLoaderImpl::LoadSheet(SheetLoadData* aLoadData, StyleSheetState aSheetState)
mSyncCallback = PR_FALSE; mSyncCallback = PR_FALSE;
#endif #endif
// Check the load against the URI classifier
nsCOMPtr<nsIChannelClassifier> 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)) { if (NS_FAILED(rv)) {
LOG_ERROR((" Failed to create stream loader")); LOG_ERROR((" Failed to create stream loader"));
SheetComplete(aLoadData, rv); SheetComplete(aLoadData, rv);

Просмотреть файл

@ -55,6 +55,10 @@ REQUIRES = \
necko \ necko \
$(NULL) $(NULL)
# mochitest tests
DIRS += mochitest \
$(NULL)
# xpcshell tests # xpcshell tests
XPCSHELL_TESTS=unit XPCSHELL_TESTS=unit

Просмотреть файл

@ -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)

Просмотреть файл

@ -0,0 +1,34 @@
<html> <head>
<title></title>
</head>
<script type="text/javascript">
var scriptItem = "untouched";
function checkLoads() {
// Make sure the javascript did not load.
window.parent.is(scriptItem, "untouched", "Should not load bad javascript");
// Make sure the css did not load.
var elt = document.getElementById("styleCheck");
var style = document.defaultView.getComputedStyle(elt, "");
window.parent.isnot(style.visibility, "hidden", "Should not load bad css");
window.parent.SimpleTest.finish();
}
</script>
<!-- Try loading from a malware javascript URI -->
<script type="text/javascript" src="http://malware.com/tests/toolkit/components/url-classifier/test/mochitest/evil.js"></script>
<!-- Try loading from a malware css URI
<link rel="stylesheet" type="text/css" href="http://malware.com/tests/toolkit/components/url-classifier/test/mochitest/evil.css"></link>
<!-- Try loading a marked-as-malware css through an @import from a clean URI -->
<link rel="stylesheet" type="text/css" href="import.css"></link>
<body onload="checkLoads()">
The following should not be hidden:
<div id="styleCheck">STYLE TEST</div>
</body> </html>

Просмотреть файл

@ -0,0 +1 @@
#styleCheck { visibility: hidden; }

Просмотреть файл

@ -0,0 +1 @@
scriptItem = "loaded malware javascript!";

1
toolkit/components/url-classifier/tests/mochitest/import.css поставляемый Normal file
Просмотреть файл

@ -0,0 +1 @@
@import url("http://malware.com/tests/docshell/test/classifierBad.css");

Просмотреть файл

@ -0,0 +1,81 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test the URI Classifier</title>
<script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script class="testbody" type="text/javascript">
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
var Cc = Components.classes;
var Ci = Components.interfaces;
// Add some URLs to the malware database.
var testData = "malware.com/"
var testUpdate =
"n:1000\ni:test-malware-simple\nad:1\n" +
"a:524:32:" + testData.length + "\n" +
testData;
var dbService = Cc["@mozilla.org/url-classifier/dbservice;1"]
.getService(Ci.nsIUrlClassifierDBService);
var numTries = 10;
function doUpdate(update) {
var listener = {
QueryInterface: function(iid)
{
if (iid.equals(Ci.nsISupports) ||
iid.equals(Ci.nsIUrlClassifierUpdateObserver))
return this;
throw Cr.NS_ERROR_NO_INTERFACE;
},
updateUrlRequested: function(url) { },
streamFinished: function(status) { },
updateError: function(errorCode) {
ok(false, "Couldn't update classifier.");
SimpleTest.finish();
},
updateSuccess: function(requestedTimeout) {
document.getElementById("testFrame").src = "classifierFrame.html";
}
};
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
try {
dbService.beginUpdate(listener,
"test-malware-simple", "");
dbService.beginStream("", "");
dbService.updateStream(update);
dbService.finishStream();
dbService.finishUpdate();
} catch(ex) {
// The DB service might already be updating. Try again after a 5 seconds...
if (--numTries != 0) {
setTimeout(function() { doUpdate(update) }, 5000);
return;
}
throw ex;
}
}
doUpdate(testUpdate);
SimpleTest.waitForExplicitFinish();
</script>
</pre>
<iframe id="testFrame" onload=""></iframe>
</body>
</html>