mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-30 00:01:50 +00:00
Bug 851586, r=bz
--HG-- extra : rebase_source : 4144764238b0f38f1457358b1c9f61bc4d347424
This commit is contained in:
parent
9bde498c5b
commit
decd2dd5c1
@ -17,9 +17,7 @@ NS_IMPL_ISUPPORTS1(AboutRedirector, nsIAboutModule)
|
||||
struct RedirEntry {
|
||||
const char* id;
|
||||
const char* url;
|
||||
uint32_t flags; // See nsIAboutModule. The URI_SAFE_FOR_UNTRUSTED_CONTENT
|
||||
// flag does double duty here -- if it's not set, we don't
|
||||
// drop chrome privileges.
|
||||
uint32_t flags;
|
||||
};
|
||||
|
||||
/*
|
||||
@ -128,28 +126,6 @@ AboutRedirector::NewChannel(nsIURI *aURI, nsIChannel **result)
|
||||
|
||||
tempChannel->SetOriginalURI(aURI);
|
||||
|
||||
// Keep the page from getting unnecessary privileges unless it needs them
|
||||
if (kRedirMap[i].flags & nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT) {
|
||||
if (path.EqualsLiteral("feeds")) {
|
||||
nsCOMPtr<nsIScriptSecurityManager> securityManager =
|
||||
do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIPrincipal> principal;
|
||||
rv = securityManager->GetNoAppCodebasePrincipal(aURI, getter_AddRefs(principal));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = tempChannel->SetOwner(principal);
|
||||
}
|
||||
else {
|
||||
// Setting the owner to null means that we'll go through the normal
|
||||
// path in GetChannelPrincipal and create a codebase principal based
|
||||
// on the channel's originalURI
|
||||
rv = tempChannel->SetOwner(nullptr);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
}
|
||||
|
||||
NS_ADDREF(*result = tempChannel);
|
||||
return rv;
|
||||
}
|
||||
|
@ -5,6 +5,7 @@
|
||||
|
||||
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Components.utils.import("resource://gre/modules/debug.js");
|
||||
Components.utils.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
@ -23,8 +24,6 @@ const TYPE_MAYBE_VIDEO_FEED = "application/vnd.mozilla.maybe.video.feed";
|
||||
const TYPE_MAYBE_AUDIO_FEED = "application/vnd.mozilla.maybe.audio.feed";
|
||||
const TYPE_ANY = "*/*";
|
||||
|
||||
const FEEDHANDLER_URI = "about:feeds";
|
||||
|
||||
const PREF_SELECTED_APP = "browser.feeds.handlers.application";
|
||||
const PREF_SELECTED_WEB = "browser.feeds.handlers.webservice";
|
||||
const PREF_SELECTED_ACTION = "browser.feeds.handler";
|
||||
@ -246,12 +245,14 @@ FeedConverter.prototype = {
|
||||
feedService.addFeedResult(result);
|
||||
|
||||
// Now load the actual XUL document.
|
||||
var chromeURI = ios.newURI(FEEDHANDLER_URI, null, null);
|
||||
chromeChannel = ios.newChannelFromURI(chromeURI, null);
|
||||
var aboutFeedsURI = ios.newURI("about:feeds", null, null);
|
||||
chromeChannel = ios.newChannelFromURI(aboutFeedsURI, null);
|
||||
chromeChannel.originalURI = result.uri;
|
||||
}
|
||||
else
|
||||
chromeChannel.owner =
|
||||
Services.scriptSecurityManager.getNoAppCodebasePrincipal(aboutFeedsURI);
|
||||
} else {
|
||||
chromeChannel = ios.newChannelFromURI(result.uri, null);
|
||||
}
|
||||
|
||||
chromeChannel.loadGroup = this._request.loadGroup;
|
||||
chromeChannel.asyncOpen(this._listener, null);
|
||||
|
@ -51,7 +51,6 @@ const TYPE_MAYBE_FEED = "application/vnd.mozilla.maybe.feed";
|
||||
const TYPE_MAYBE_AUDIO_FEED = "application/vnd.mozilla.maybe.audio.feed";
|
||||
const TYPE_MAYBE_VIDEO_FEED = "application/vnd.mozilla.maybe.video.feed";
|
||||
const URI_BUNDLE = "chrome://browser/locale/feeds/subscribe.properties";
|
||||
const FEEDHANDLER_URI = "about:feeds";
|
||||
|
||||
const PREF_SELECTED_APP = "browser.feeds.handlers.application";
|
||||
const PREF_SELECTED_WEB = "browser.feeds.handlers.webservice";
|
||||
@ -1102,7 +1101,7 @@ FeedWriter.prototype = {
|
||||
|
||||
var resolvedURI = Cc["@mozilla.org/network/io-service;1"].
|
||||
getService(Ci.nsIIOService).
|
||||
newChannel(FEEDHANDLER_URI, null, null).URI;
|
||||
newChannel("about:feeds", null, null).URI;
|
||||
|
||||
if (resolvedURI.equals(chan.URI))
|
||||
return chan.originalURI;
|
||||
|
@ -15,9 +15,7 @@ NS_IMPL_ISUPPORTS1(nsAboutRedirector, nsIAboutModule)
|
||||
struct RedirEntry {
|
||||
const char* id;
|
||||
const char* url;
|
||||
uint32_t flags; // See nsIAboutModule. The URI_SAFE_FOR_UNTRUSTED_CONTENT
|
||||
// flag does double duty here -- if it's not set, we don't
|
||||
// drop chrome privileges.
|
||||
uint32_t flags;
|
||||
};
|
||||
|
||||
/*
|
||||
@ -99,18 +97,6 @@ nsAboutRedirector::NewChannel(nsIURI *aURI, nsIChannel **result)
|
||||
|
||||
tempChannel->SetOriginalURI(aURI);
|
||||
|
||||
// Keep the page from getting unnecessary privileges unless it needs them
|
||||
if (kRedirMap[i].flags &
|
||||
nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT)
|
||||
{
|
||||
// Setting the owner to null means that we'll go through the normal
|
||||
// path in GetChannelPrincipal and create a codebase principal based
|
||||
// on the channel's originalURI
|
||||
rv = tempChannel->SetOwner(nullptr);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_ADDREF(*result = tempChannel);
|
||||
return rv;
|
||||
}
|
||||
|
@ -26,6 +26,13 @@
|
||||
static NS_DEFINE_CID(kSimpleURICID, NS_SIMPLEURI_CID);
|
||||
static NS_DEFINE_CID(kNestedAboutURICID, NS_NESTEDABOUTURI_CID);
|
||||
|
||||
static bool IsSafeForUntrustedContent(nsIAboutModule *aModule, nsIURI *aURI) {
|
||||
uint32_t flags;
|
||||
nsresult rv = aModule->GetURIFlags(aURI, &flags);
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
|
||||
return (flags & nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT) != 0;
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
NS_IMPL_ISUPPORTS1(nsAboutProtocolHandler, nsIProtocolHandler)
|
||||
@ -80,13 +87,7 @@ nsAboutProtocolHandler::NewURI(const nsACString &aSpec,
|
||||
nsCOMPtr<nsIAboutModule> aboutMod;
|
||||
rv = NS_GetAboutModule(url, getter_AddRefs(aboutMod));
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
// The standard return case
|
||||
uint32_t flags;
|
||||
rv = aboutMod->GetURIFlags(url, &flags);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
isSafe =
|
||||
((flags & nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT) != 0);
|
||||
isSafe = IsSafeForUntrustedContent(aboutMod, url);
|
||||
}
|
||||
|
||||
if (isSafe) {
|
||||
@ -133,6 +134,15 @@ nsAboutProtocolHandler::NewChannel(nsIURI* uri, nsIChannel* *result)
|
||||
// The standard return case:
|
||||
rv = aboutMod->NewChannel(uri, result);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
// If this URI is safe for untrusted content, enforce that its
|
||||
// principal be based on the channel's originalURI by setting the
|
||||
// owner to null.
|
||||
// Note: this relies on aboutMod's newChannel implementation
|
||||
// having set the proper originalURI, which probably isn't ideal.
|
||||
if (IsSafeForUntrustedContent(aboutMod, uri)) {
|
||||
(*result)->SetOwner(nullptr);
|
||||
}
|
||||
|
||||
nsRefPtr<nsNestedAboutURI> aboutURI;
|
||||
nsresult rv2 = uri->QueryInterface(kNestedAboutURICID,
|
||||
getter_AddRefs(aboutURI));
|
||||
|
@ -21,8 +21,11 @@ interface nsIAboutModule : nsISupports
|
||||
/**
|
||||
* A flag that indicates whether a URI is safe for untrusted
|
||||
* content. If it is, web pages and so forth will be allowed to
|
||||
* link to this about: URI. Otherwise, only chrome will be able
|
||||
* to link to it.
|
||||
* link to this about: URI, and the about: protocol handler will
|
||||
* enforce that the principal of channels created for it be based
|
||||
* on their originalURI or URI (depending on the channel flags),
|
||||
* by setting their "owner" to null.
|
||||
* Otherwise, only chrome will be able to link to it.
|
||||
*/
|
||||
const unsigned long URI_SAFE_FOR_UNTRUSTED_CONTENT = (1 << 0);
|
||||
|
||||
|
45
netwerk/test/unit/test_about_protocol.js
Normal file
45
netwerk/test/unit/test_about_protocol.js
Normal file
@ -0,0 +1,45 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
let Ci = Components.interfaces;
|
||||
let Cc = Components.classes;
|
||||
|
||||
Components.utils.import("resource://gre/modules/Services.jsm");
|
||||
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
let unsafeAboutModule = {
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIAboutModule]),
|
||||
newChannel: function (aURI) {
|
||||
let chan = Services.io.newChannel("about:blank", null, null);
|
||||
chan.owner = Services.scriptSecurityManager.getSystemPrincipal();
|
||||
return chan;
|
||||
},
|
||||
getURIFlags: function (aURI) {
|
||||
return Ci.nsIAboutModule.URI_SAFE_FOR_UNTRUSTED_CONTENT;
|
||||
}
|
||||
};
|
||||
|
||||
let factory = {
|
||||
createInstance: function(aOuter, aIID) {
|
||||
if (aOuter)
|
||||
throw Components.results.NS_ERROR_NO_AGGREGATION;
|
||||
return unsafeAboutModule.QueryInterface(aIID);
|
||||
},
|
||||
lockFactory: function(aLock) {
|
||||
throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
|
||||
},
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIFactory])
|
||||
};
|
||||
|
||||
function run_test() {
|
||||
let registrar = Components.manager.QueryInterface(Ci.nsIComponentRegistrar);
|
||||
let classID = Cc["@mozilla.org/uuid-generator;1"].getService(Ci.nsIUUIDGenerator).generateUUID();
|
||||
registrar.registerFactory(classID, "", "@mozilla.org/network/protocol/about;1?what=unsafe", factory);
|
||||
|
||||
let aboutUnsafeURI = Services.io.newURI("about:unsafe", null, null);
|
||||
let aboutUnsafeChan = Services.io.newChannelFromURI(aboutUnsafeURI);
|
||||
do_check_null(aboutUnsafeChan.owner, "URI_SAFE_FOR_UNTRUSTED_CONTENT channel has no owner");
|
||||
|
||||
registrar.unregisterFactory(classID, factory);
|
||||
}
|
@ -212,3 +212,4 @@ run-if = hasNode
|
||||
[test_bug826063.js]
|
||||
[test_bug812167.js]
|
||||
[test_tldservice_nextsubdomain.js]
|
||||
[test_about_protocol.js]
|
||||
|
Loading…
Reference in New Issue
Block a user