Bug 909022 - Mark all executables as coming from the Internet zone on Windows. r=enn

This commit is contained in:
Paolo Amadini 2013-09-09 15:45:29 +02:00
parent 4ff4e8810b
commit cadfff357d
2 changed files with 61 additions and 12 deletions

View File

@ -147,6 +147,13 @@ pref("browser.helperApps.alwaysAsk.force", false);
pref("browser.helperApps.neverAsk.saveToDisk", "");
pref("browser.helperApps.neverAsk.openFile", "");
#ifdef XP_WIN
// By default, security zone information is stored in the Alternate Data Stream
// of downloaded executable files on Windows. This preference allows disabling
// this feature, and thus the associated system-level execution prompts.
pref("browser.download.saveZoneInformation", true);
#endif
// xxxbsmedberg: where should prefs for the toolkit go?
pref("browser.chrome.toolbar_tips", true);
// 0 = Pictures Only, 1 = Text Only, 2 = Pictures and Text

View File

@ -66,6 +66,14 @@ XPCOMUtils.defineLazyGetter(this, "gParentalControlsService", function() {
return null;
});
/**
* ArrayBufferView representing the bytes to be written to the "Zone.Identifier"
* Alternate Data Stream to mark a file as coming from the Internet zone.
*/
XPCOMUtils.defineLazyGetter(this, "gInternetZoneIdentifier", function() {
return new TextEncoder().encode("[ZoneTransfer]\r\nZoneId=3\r\n");
});
const Timer = Components.Constructor("@mozilla.org/timer;1", "nsITimer",
"initWithCallback");
@ -389,15 +397,46 @@ this.DownloadIntegration = {
* @rejects JavaScript exception if any of the operations failed.
*/
downloadDone: function(aDownload) {
try {
return Task.spawn(function () {
#ifdef XP_WIN
// On Windows, we mark any executable file saved to the NTFS file system
// as coming from the Internet security zone. We do this by writing to
// the "Zone.Identifier" Alternate Data Stream directly, because the Save
// method of the IAttachmentExecute interface would trigger operations
// that may cause the application to hang, or other performance issues.
// The stream created in this way is forward-compatible with all the
// current and future versions of Windows.
if (Services.prefs.getBoolPref("browser.download.saveZoneInformation")) {
let file = new FileUtils.File(aDownload.target.path);
if (file.isExecutable()) {
try {
let streamPath = aDownload.target.path + ":Zone.Identifier";
let stream = yield OS.File.open(streamPath, { create: true });
try {
yield stream.write(gInternetZoneIdentifier);
} finally {
yield stream.close();
}
} catch (ex) {
// If writing to the stream fails, we ignore the error and continue.
// The Windows API error 123 (ERROR_INVALID_NAME) is expected to
// occur when working on a file system that does not support
// Alternate Data Streams, like FAT32, thus we don't report this
// specific error.
if (!(ex instanceof OS.File.Error) || ex.winLastError != 123) {
Cu.reportError(ex);
}
}
}
}
#endif
gDownloadPlatform.downloadDone(NetUtil.newURI(aDownload.source.url),
new FileUtils.File(aDownload.target.path),
aDownload.contentType, aDownload.source.isPrivate);
aDownload.contentType,
aDownload.source.isPrivate);
this.downloadDoneCalled = true;
return Promise.resolve();
} catch(ex) {
return Promise.reject(ex);
}
}.bind(this));
},
/**
@ -432,12 +471,14 @@ this.DownloadIntegration = {
let deferred = Task.spawn(function DI_launchDownload_task() {
let file = new FileUtils.File(aDownload.target.path);
// Ask for confirmation if the file is executable. We do this here,
// instead of letting the caller handle the prompt separately in the user
// interface layer, for two reasons. The first is because of its security
// nature, so that add-ons cannot forget to do this check. The second is
// that the system-level security prompt, if enabled, would be displayed
// at launch time in any case.
#ifndef XP_WIN
// Ask for confirmation if the file is executable, except on Windows where
// the operating system will show the prompt based on the security zone.
// We do this here, instead of letting the caller handle the prompt
// separately in the user interface layer, for two reasons. The first is
// because of its security nature, so that add-ons cannot forget to do
// this check. The second is that the system-level security prompt would
// be displayed at launch time in any case.
if (file.isExecutable() && !this.dontOpenFileAndFolder) {
// We don't anchor the prompt to a specific window intentionally, not
// only because this is the same behavior as the system-level prompt,
@ -449,6 +490,7 @@ this.DownloadIntegration = {
return;
}
}
#endif
// In case of a double extension, like ".tar.gz", we only
// consider the last one, because the MIME service cannot