Skip to content

Commit

Permalink
Bug 414540 - RDFXMLDataSource should reject cross-domain redirects. O…
Browse files Browse the repository at this point in the history
…riginal patch by Neil Deakin, fixed up with better testing, r+sr=bz
  • Loading branch information
bsmedberg committed Jan 29, 2009
1 parent ac2f869 commit d05ca8b
Show file tree
Hide file tree
Showing 5 changed files with 159 additions and 2 deletions.
2 changes: 2 additions & 0 deletions rdf/base/src/Makefile.in
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ LIBXUL_LIBRARY = 1
REQUIRES = xpcom \
string \
rdfutil \
js \
caps \
necko \
content \
htmlparser \
Expand Down
56 changes: 54 additions & 2 deletions rdf/base/src/nsRDFXMLDataSource.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,9 @@
#include "nsNameSpaceMap.h"
#include "nsCRT.h"
#include "nsCycleCollectionParticipant.h"
#include "nsIScriptSecurityManager.h"
#include "nsIChannelEventSink.h"
#include "nsNetUtil.h"

#include "rdfIDataSource.h"

Expand All @@ -145,7 +148,9 @@ class RDFXMLDataSourceImpl : public nsIRDFDataSource,
public nsIRDFXMLSink,
public nsIRDFXMLSource,
public nsIStreamListener,
public rdfIDataSource
public rdfIDataSource,
public nsIInterfaceRequestor,
public nsIChannelEventSink
{
protected:
enum LoadState {
Expand Down Expand Up @@ -318,6 +323,12 @@ class RDFXMLDataSourceImpl : public nsIRDFDataSource,
// nsIStreamListener
NS_DECL_NSISTREAMLISTENER

// nsIInterfaceRequestor
NS_DECL_NSIINTERFACEREQUESTOR

// nsIChannelEventSink
NS_DECL_NSICHANNELEVENTSINK

// rdfIDataSource
NS_IMETHOD VisitAllSubjects(rdfITripleVisitor *aVisitor) {
nsresult rv;
Expand Down Expand Up @@ -481,9 +492,17 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(RDFXMLDataSourceImpl)
NS_INTERFACE_MAP_ENTRY(nsIRequestObserver)
NS_INTERFACE_MAP_ENTRY(nsIStreamListener)
NS_INTERFACE_MAP_ENTRY(rdfIDataSource)
NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor)
NS_INTERFACE_MAP_ENTRY(nsIChannelEventSink)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIRDFDataSource)
NS_INTERFACE_MAP_END

// nsIInterfaceRequestor
NS_IMETHODIMP
RDFXMLDataSourceImpl::GetInterface(const nsIID& aIID, void** aSink)
{
return QueryInterface(aIID, aSink);
}

nsresult
RDFXMLDataSourceImpl::BlockingParse(nsIURI* aURL, nsIStreamListener* aConsumer)
Expand Down Expand Up @@ -877,6 +896,39 @@ RDFXMLDataSourceImpl::SetReadOnly(PRBool aIsReadOnly)

#include "nsITimelineService.h"

// nsIChannelEventSink

// This code is copied from nsSameOriginChecker::OnChannelRedirect. See
// bug 475940 on providing this code in a shared location.
NS_IMETHODIMP
RDFXMLDataSourceImpl::OnChannelRedirect(nsIChannel *aOldChannel,
nsIChannel *aNewChannel,
PRUint32 aFlags)
{
NS_PRECONDITION(aNewChannel, "Redirecting to null channel?");

nsresult rv;
nsCOMPtr<nsIScriptSecurityManager> secMan =
do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);

nsCOMPtr<nsIPrincipal> oldPrincipal;
secMan->GetChannelPrincipal(aOldChannel, getter_AddRefs(oldPrincipal));

nsCOMPtr<nsIURI> newURI;
aNewChannel->GetURI(getter_AddRefs(newURI));
nsCOMPtr<nsIURI> newOriginalURI;
aNewChannel->GetOriginalURI(getter_AddRefs(newOriginalURI));

NS_ENSURE_STATE(oldPrincipal && newURI && newOriginalURI);

rv = oldPrincipal->CheckMayLoad(newURI, PR_FALSE);
if (NS_SUCCEEDED(rv) && newOriginalURI != newURI) {
rv = oldPrincipal->CheckMayLoad(newOriginalURI, PR_FALSE);
}
return rv;
}

NS_IMETHODIMP
RDFXMLDataSourceImpl::Refresh(PRBool aBlocking)
{
Expand Down Expand Up @@ -925,7 +977,7 @@ RDFXMLDataSourceImpl::Refresh(PRBool aBlocking)
}
else {
// Null LoadGroup ?
rv = NS_OpenURI(this, nsnull, mURL, nsnull);
rv = NS_OpenURI(this, nsnull, mURL, nsnull, nsnull, this);
if (NS_FAILED(rv)) return rv;

// So we don't try to issue two asynchronous loads at once.
Expand Down
4 changes: 4 additions & 0 deletions rdf/tests/Makefile.in
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,13 @@ topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@

MODULE = test_rdf

include $(DEPTH)/config/autoconf.mk

DIRS = rdfcat rdfpoll triplescat

XPCSHELL_TESTS = unit

include $(topsrcdir)/config/rules.mk

9 changes: 9 additions & 0 deletions rdf/tests/unit/sample.rdf
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?xml version="1.0"?>

<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/">

<rdf:Description about="urn:mozilla:sample-data"
dc:title="Sample" />

</rdf:RDF>
90 changes: 90 additions & 0 deletions rdf/tests/unit/test_rdfredirect.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
do_import_script("netwerk/test/httpserver/httpd.js");

function getRDFService()
{
return Components.classes["@mozilla.org/rdf/rdf-service;1"].
getService(Components.interfaces.nsIRDFService);
}

var server1, server2;

function run_test()
{
var samplefile = do_get_file('rdf/tests/unit/sample.rdf');

server1 = new nsHttpServer();
server1.registerPathHandler("/sample-xs.rdf", xsRedirect);
server1.registerPathHandler("/sample-local.rdf", localRedirect);
server1.registerFile('/sample.rdf', samplefile);
server1.start(4444);

server2 = new nsHttpServer();
server2.registerFile('/sample.rdf', samplefile);
server2.start(4445);

do_test_pending();

new rdfLoadObserver('http://localhost:4444/sample.rdf', true);
new rdfLoadObserver('http://localhost:4445/sample.rdf', true);
new rdfLoadObserver('http://localhost:4444/sample-xs.rdf', false);
new rdfLoadObserver('http://localhost:4444/sample-local.rdf', true);
}

var gPending = 0;

function rdfLoadObserver(uri, shouldPass)
{
this.shouldPass = shouldPass;
this.uri = uri;

++gPending;

var rdfService = getRDFService();
this.ds = rdfService.GetDataSource(uri).
QueryInterface(Components.interfaces.nsIRDFXMLSink);
this.ds.addXMLSinkObserver(this);
}

rdfLoadObserver.prototype =
{
onBeginLoad : function() { },
onInterrupt : function() { },
onResume : function() { },
onEndLoad : function() {
print("Testing results of loading " + this.uri);

var rdfs = getRDFService();
var res = rdfs.GetResource("urn:mozilla:sample-data");
var arc = rdfs.GetResource("http://purl.org/dc/elements/1.1/title");
var answer = this.ds.GetTarget(res, arc, true);
if (answer !== null) {
do_check_true(this.shouldPass);
do_check_true(answer instanceof Components.interfaces.nsIRDFLiteral);
do_check_eq(answer.Value, "Sample");
}
else {
do_check_false(this.shouldPass);
}

gPending -= 1;

if (gPending == 0) {
server1.stop();
server2.stop();
do_test_finished();
}
},
onError : function() { }
}

function xsRedirect(metadata, response)
{
response.setStatusLine(metadata.httpVersion, 301, "Moved Permanently");
response.setHeader("Location", "http://localhost:4445/sample.rdf", false);
}

function localRedirect(metadata, response)
{
response.setStatusLine(metadata.httpVersion, 301, "Moved Permanently");
response.setHeader("Location", "http://localhost:4444/sample.rdf", false);
}

0 comments on commit d05ca8b

Please sign in to comment.