зеркало из https://github.com/mozilla/pjs.git
Bug 441359: Check script and css loads against the classifier. r+sr=jonas
This commit is contained in:
Родитель
f3c17be4a6
Коммит
3ac023a8d9
|
@ -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
|
||||
|
|
|
@ -1753,7 +1753,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;
|
||||
|
|
|
@ -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<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
|
||||
|
|
|
@ -7797,7 +7797,7 @@ nsDocShell::CheckClassifier(nsIChannel *aChannel)
|
|||
nsRefPtr<nsClassifierCallback> 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
|
||||
|
@ -9683,10 +9683,12 @@ nsDocShell::IsOKToLoadURI(nsIURI* aURI)
|
|||
// nsClassifierCallback
|
||||
//*****************************************************************************
|
||||
|
||||
NS_IMPL_ISUPPORTS3(nsClassifierCallback,
|
||||
NS_IMPL_ISUPPORTS5(nsClassifierCallback,
|
||||
nsIChannelClassifier,
|
||||
nsIURIClassifierCallback,
|
||||
nsIRunnable)
|
||||
nsIRunnable,
|
||||
nsIChannelEventSink,
|
||||
nsIInterfaceRequestor)
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsClassifierCallback::Run()
|
||||
|
@ -9711,7 +9713,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;
|
||||
}
|
||||
|
||||
|
@ -9803,10 +9805,10 @@ nsClassifierCallback::MarkEntryClassified(nsresult status)
|
|||
}
|
||||
|
||||
PRBool
|
||||
nsClassifierCallback::HasBeenClassified()
|
||||
nsClassifierCallback::HasBeenClassified(nsIChannel *aChannel)
|
||||
{
|
||||
nsCOMPtr<nsICachingChannel> cachingChannel =
|
||||
do_QueryInterface(mSuspendedChannel);
|
||||
do_QueryInterface(aChannel);
|
||||
if (!cachingChannel) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
@ -9862,15 +9864,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<nsIInterfaceRequestor*>(this));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
return Run();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsClassifierCallback::OnRedirect(nsIChannel *aOldChannel,
|
||||
nsIChannel *aNewChannel)
|
||||
nsIChannel *aNewChannel)
|
||||
{
|
||||
mChannel = aNewChannel;
|
||||
|
||||
|
@ -9900,3 +9913,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<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
|
||||
, 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<nsIChannel> mChannel;
|
||||
nsCOMPtr<nsIChannel> mSuspendedChannel;
|
||||
nsCOMPtr<nsIInterfaceRequestor> mNotificationCallbacks;
|
||||
|
||||
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
|
||||
* 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
|
||||
|
|
|
@ -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"
|
||||
|
@ -1461,6 +1463,19 @@ CSSLoaderImpl::LoadSheet(SheetLoadData* aLoadData, StyleSheetState aSheetState)
|
|||
return 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)) {
|
||||
LOG_ERROR((" Failed to classify URI"));
|
||||
SheetComplete(aLoadData, rv);
|
||||
channel->Cancel(rv);
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
if (!mLoadingDatas.Put(&key, aLoadData)) {
|
||||
LOG_ERROR((" Failed to put data in loading table"));
|
||||
aLoadData->mIsCancelled = PR_TRUE;
|
||||
|
|
|
@ -55,6 +55,10 @@ REQUIRES = \
|
|||
necko \
|
||||
$(NULL)
|
||||
|
||||
# mochitest tests
|
||||
DIRS += mochitest \
|
||||
$(NULL)
|
||||
|
||||
# xpcshell tests
|
||||
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/tests/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/tests/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!";
|
|
@ -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>
|
Загрузка…
Ссылка в новой задаче