Bug 1018154 - part 1: replace blocking of security principal inheriting with onpaste handler, r=dao

This commit is contained in:
Gijs Kruitbosch 2014-07-01 15:27:08 +01:00
parent fc1a822b92
commit d8e39296ea
3 changed files with 62 additions and 30 deletions

View File

@ -1910,7 +1910,6 @@ function loadURI(uri, referrer, postData, allowThirdPartyFixup) {
}
function getShortcutOrURIAndPostData(aURL, aCallback) {
let mayInheritPrincipal = false;
let postData = null;
let shortcutURL = null;
let keyword = aURL;
@ -1926,8 +1925,7 @@ function getShortcutOrURIAndPostData(aURL, aCallback) {
if (engine) {
let submission = engine.getSubmission(param);
postData = submission.postData;
aCallback({ postData: submission.postData, url: submission.uri.spec,
mayInheritPrincipal: mayInheritPrincipal });
aCallback({ postData: submission.postData, url: submission.uri.spec });
return;
}
@ -1935,8 +1933,7 @@ function getShortcutOrURIAndPostData(aURL, aCallback) {
PlacesUtils.getURLAndPostDataForKeyword(keyword);
if (!shortcutURL) {
aCallback({ postData: postData, url: aURL,
mayInheritPrincipal: mayInheritPrincipal });
aCallback({ postData: postData, url: aURL });
return;
}
@ -1968,12 +1965,7 @@ function getShortcutOrURIAndPostData(aURL, aCallback) {
postData = getPostDataStream(escapedPostData, param, encodedParam,
"application/x-www-form-urlencoded");
// This URL came from a bookmark, so it's safe to let it inherit the current
// document's principal.
mayInheritPrincipal = true;
aCallback({ postData: postData, url: shortcutURL,
mayInheritPrincipal: mayInheritPrincipal });
aCallback({ postData: postData, url: shortcutURL });
}
if (matches) {
@ -1996,15 +1988,9 @@ function getShortcutOrURIAndPostData(aURL, aCallback) {
// the original URL.
postData = null;
aCallback({ postData: postData, url: aURL,
mayInheritPrincipal: mayInheritPrincipal });
aCallback({ postData: postData, url: aURL });
} else {
// This URL came from a bookmark, so it's safe to let it inherit the current
// document's principal.
mayInheritPrincipal = true;
aCallback({ postData: postData, url: shortcutURL,
mayInheritPrincipal: mayInheritPrincipal });
aCallback({ postData: postData, url: shortcutURL });
}
}
@ -5144,6 +5130,8 @@ function middleMousePaste(event) {
// bar's behavior (stripsurroundingwhitespace)
clipboard = clipboard.replace(/\s*\n\s*/g, "");
clipboard = stripUnsafeProtocolOnPaste(clipboard);
// if it's not the current tab, we don't need to do anything because the
// browser doesn't exist.
let where = whereToOpenLink(event, true, false);
@ -5171,14 +5159,32 @@ function middleMousePaste(event) {
if (where != "current" ||
lastLocationChange == gBrowser.selectedBrowser.lastLocationChange) {
openUILink(data.url, event,
{ ignoreButton: true,
disallowInheritPrincipal: !data.mayInheritPrincipal });
{ ignoreButton: true });
}
});
event.stopPropagation();
}
function stripUnsafeProtocolOnPaste(pasteData) {
// Don't allow pasting in full URIs which inherit the security context.
const URI_INHERITS_SECURITY_CONTEXT = Ci.nsIProtocolHandler.URI_INHERITS_SECURITY_CONTEXT;
let pastedURI;
pasteData = pasteData.trim();
do {
if (pastedURI) {
pasteData = pastedURI.path.trim();
}
try {
pastedURI = makeURI(pasteData);
} catch (ex) {
break;
}
} while (Services.netutil.URIChainHasFlags(pastedURI, URI_INHERITS_SECURITY_CONTEXT));
return pasteData;
}
function handleDroppedLink(event, url, name)
{
let lastLocationChange = gBrowser.selectedBrowser.lastLocationChange;

View File

@ -62,6 +62,7 @@
this._ignoreNextSelect = false;
this.inputField.controllers.insertControllerAt(0, this._copyCutController);
this.inputField.addEventListener("paste", this, false);
this.inputField.addEventListener("mousedown", this, false);
this.inputField.addEventListener("mousemove", this, false);
this.inputField.addEventListener("mouseout", this, false);
@ -111,6 +112,7 @@
this._prefs.removeObserver("", this);
this._prefs = null;
this.inputField.controllers.removeController(this._copyCutController);
this.inputField.removeEventListener("paste", this, false);
this.inputField.removeEventListener("mousedown", this, false);
this.inputField.removeEventListener("mousemove", this, false);
this.inputField.removeEventListener("mouseout", this, false);
@ -263,7 +265,6 @@
return; // Do nothing for right clicks
var url = this.value;
var mayInheritPrincipal = false;
var postData = null;
var action = this._parseActionUrl(url);
@ -286,7 +287,7 @@
}
else {
this._canonizeURL(aTriggeringEvent, response => {
[url, postData, mayInheritPrincipal] = response;
[url, postData] = response;
if (url) {
matchLastLocationChange = (lastLocationChange ==
gBrowser.selectedBrowser.lastLocationChange);
@ -311,12 +312,6 @@
let webnav = Ci.nsIWebNavigation;
let flags = webnav.LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP |
webnav.LOAD_FLAGS_FIXUP_SCHEME_TYPOS;
// Pass LOAD_FLAGS_DISALLOW_INHERIT_OWNER to prevent any loads from
// inheriting the currently loaded document's principal, unless this
// URL is marked as safe to inherit (e.g. came from a bookmark
// keyword).
if (!mayInheritPrincipal)
flags |= Ci.nsIWebNavigation.LOAD_FLAGS_DISALLOW_INHERIT_OWNER;
gBrowser.loadURIWithFlags(url, flags, null, null, postData);
}
@ -427,7 +422,7 @@
}
getShortcutOrURIAndPostData(url, data => {
aCallback([data.url, data.postData, data.mayInheritPrincipal]);
aCallback([data.url, data.postData]);
});
]]></body>
</method>
@ -624,6 +619,36 @@
<parameter name="aEvent"/>
<body><![CDATA[
switch (aEvent.type) {
case "paste":
let originalPasteData = aEvent.clipboardData.getData("text/plain");
if (!originalPasteData) {
return;
}
let oldValue = this.inputField.value;
let oldStart = oldValue.substring(0, this.inputField.selectionStart);
// If there is already non-whitespace content in the URL bar
// preceding the pasted content, it's not necessary to check
// protocols used by the pasted content:
if (oldStart.trim()) {
return;
}
let oldEnd = oldValue.substring(this.inputField.selectionEnd);
let pasteData = stripUnsafeProtocolOnPaste(originalPasteData);
if (originalPasteData != pasteData) {
// Unfortunately we're not allowed to set the bits being pasted
// so cancel this event:
aEvent.preventDefault();
aEvent.stopPropagation();
this.inputField.value = oldStart + pasteData + oldEnd;
// Fix up cursor/selection:
let newCursorPos = oldStart.length + pasteData.length;
this.inputField.selectionStart = newCursorPos;
this.inputField.selectionEnd = newCursorPos;
}
break;
case "mousedown":
if (this.doubleClickSelectsAll &&
aEvent.button == 0 && aEvent.detail == 2) {

View File

@ -61,6 +61,7 @@ let initTable = [
["io", "@mozilla.org/network/io-service;1", "nsIIOService2"],
["locale", "@mozilla.org/intl/nslocaleservice;1", "nsILocaleService"],
["logins", "@mozilla.org/login-manager;1", "nsILoginManager"],
["netutil", "@mozilla.org/network/util;1", "nsINetUtil"],
["obs", "@mozilla.org/observer-service;1", "nsIObserverService"],
["perms", "@mozilla.org/permissionmanager;1", "nsIPermissionManager"],
["prompt", "@mozilla.org/embedcomp/prompt-service;1", "nsIPromptService"],