mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-01-26 23:23:33 +00:00
Bug 772365, Part 4: Check JAR signature during packaged app installation, r=anygregor
--HG-- extra : rebase_source : 022a85cdb5b14ff03e65b2e16f2b723da8981e40 extra : amend_source : 2140858e32614316cde30e473a6957c09aad3058
This commit is contained in:
parent
9dcf1b156f
commit
96b28b415d
@ -1622,6 +1622,7 @@ this.DOMApplicationRegistry = {
|
||||
// Here are the steps when installing a package:
|
||||
// - create a temp directory where to store the app.
|
||||
// - download the zip in this directory.
|
||||
// - check the signature on the zip.
|
||||
// - extract the manifest from the zip and check it.
|
||||
// - ask confirmation to the user.
|
||||
// - add the new app to the registry.
|
||||
@ -1661,28 +1662,6 @@ this.DOMApplicationRegistry = {
|
||||
app: app });
|
||||
}
|
||||
|
||||
function getInferedStatus() {
|
||||
// XXX Update once we have digital signatures (bug 772365)
|
||||
return Ci.nsIPrincipal.APP_STATUS_INSTALLED;
|
||||
}
|
||||
|
||||
function getAppStatus(aManifest) {
|
||||
let manifestStatus = AppsUtils.getAppManifestStatus(aManifest);
|
||||
let inferedStatus = getInferedStatus();
|
||||
|
||||
return (Services.prefs.getBoolPref("dom.mozApps.dev_mode") ? manifestStatus
|
||||
: inferedStatus);
|
||||
}
|
||||
// Returns true if the privilege level from the manifest
|
||||
// is lower or equal to the one we infered for the app.
|
||||
function checkAppStatus(aManifest) {
|
||||
if (Services.prefs.getBoolPref("dom.mozApps.dev_mode")) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return (AppsUtils.getAppManifestStatus(aManifest) <= getInferedStatus());
|
||||
}
|
||||
|
||||
function download() {
|
||||
debug("About to download " + aManifest.fullPackagePath());
|
||||
|
||||
@ -1742,7 +1721,7 @@ this.DOMApplicationRegistry = {
|
||||
cleanup("NETWORK_ERROR");
|
||||
return;
|
||||
}
|
||||
// Copy the zip on disk.
|
||||
// Copy the zip on disk. XXX: this can consume all disk space.
|
||||
let zipFile = FileUtils.getFile("TmpD",
|
||||
["webapps", id, "application.zip"], true);
|
||||
let ostream = FileUtils.openSafeFileOutputStream(zipFile);
|
||||
@ -1753,50 +1732,76 @@ this.DOMApplicationRegistry = {
|
||||
return;
|
||||
}
|
||||
|
||||
let zipReader = Cc["@mozilla.org/libjar/zip-reader;1"]
|
||||
.createInstance(Ci.nsIZipReader);
|
||||
try {
|
||||
zipReader.open(zipFile);
|
||||
if (!zipReader.hasEntry("manifest.webapp")) {
|
||||
throw "MISSING_MANIFEST";
|
||||
let certdb;
|
||||
try {
|
||||
certdb = Cc["@mozilla.org/security/x509certdb;1"]
|
||||
.getService(Ci.nsIX509CertDB);
|
||||
} catch (e) {
|
||||
cleanup("CERTDB_ERROR");
|
||||
return;
|
||||
}
|
||||
certdb.openSignedJARFileAsync(zipFile, function(aRv, aZipReader) {
|
||||
try {
|
||||
let zipReader;
|
||||
let isSigned;
|
||||
if (Components.isSuccessCode(aRv)) {
|
||||
isSigned = true;
|
||||
zipReader = aZipReader;
|
||||
} else if (aRv != Cr.NS_ERROR_SIGNED_JAR_NOT_SIGNED) {
|
||||
throw "INVALID_SIGNATURE";
|
||||
} else {
|
||||
isSigned = false;
|
||||
zipReader = Cc["@mozilla.org/libjar/zip-reader;1"]
|
||||
.createInstance(Ci.nsIZipReader);
|
||||
zipReader.open(zipFile);
|
||||
}
|
||||
|
||||
if (!zipReader.hasEntry("manifest.webapp")) {
|
||||
throw "MISSING_MANIFEST";
|
||||
}
|
||||
|
||||
let istream = zipReader.getInputStream("manifest.webapp");
|
||||
|
||||
// Obtain a converter to read from a UTF-8 encoded input stream.
|
||||
let converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"]
|
||||
.createInstance(Ci.nsIScriptableUnicodeConverter);
|
||||
converter.charset = "UTF-8";
|
||||
|
||||
let manifest = JSON.parse(converter.ConvertToUnicode(NetUtil.readInputStreamToString(istream,
|
||||
istream.available()) || ""));
|
||||
|
||||
if (!AppsUtils.checkManifest(manifest)) {
|
||||
throw "INVALID_MANIFEST";
|
||||
}
|
||||
|
||||
if (!AppsUtils.checkInstallAllowed(manifest, aApp.installOrigin)) {
|
||||
throw "INSTALL_FROM_DENIED";
|
||||
}
|
||||
|
||||
let isDevMode = Services.prefs.getBoolPref("dom.mozApps.dev_mode");
|
||||
let maxStatus = isDevMode ? Ci.nsIPrincipal.APP_STATUS_CERTIFIED
|
||||
: isSigned ? Ci.nsIPrincipal.APP_STATUS_PRIVILEGED
|
||||
: Ci.nsIPrincipal.APP_STATUS_INSTALLED;
|
||||
|
||||
if (AppsUtils.getAppManifestStatus(aManifest) > maxStatus) {
|
||||
throw "INVALID_SECURITY_LEVEL";
|
||||
}
|
||||
|
||||
if (aOnSuccess) {
|
||||
aOnSuccess(id, manifest);
|
||||
}
|
||||
delete self.downloads[aApp.manifestURL];
|
||||
} catch (e) {
|
||||
// Something bad happened when reading the package.
|
||||
if (typeof e == 'object') {
|
||||
cleanup("INVALID_PACKAGE");
|
||||
} else {
|
||||
cleanup(e);
|
||||
}
|
||||
} finally {
|
||||
zipReader.close();
|
||||
}
|
||||
|
||||
let istream = zipReader.getInputStream("manifest.webapp");
|
||||
|
||||
// Obtain a converter to read from a UTF-8 encoded input stream.
|
||||
let converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"]
|
||||
.createInstance(Ci.nsIScriptableUnicodeConverter);
|
||||
converter.charset = "UTF-8";
|
||||
|
||||
let manifest = JSON.parse(converter.ConvertToUnicode(NetUtil.readInputStreamToString(istream,
|
||||
istream.available()) || ""));
|
||||
|
||||
if (!AppsUtils.checkManifest(manifest)) {
|
||||
throw "INVALID_MANIFEST";
|
||||
}
|
||||
|
||||
if (!AppsUtils.checkInstallAllowed(manifest, aApp.installOrigin)) {
|
||||
throw "INSTALL_FROM_DENIED";
|
||||
}
|
||||
|
||||
if (!checkAppStatus(manifest)) {
|
||||
throw "INVALID_SECURITY_LEVEL";
|
||||
}
|
||||
|
||||
if (aOnSuccess) {
|
||||
aOnSuccess(id, manifest);
|
||||
}
|
||||
delete self.downloads[aApp.manifestURL];
|
||||
} catch (e) {
|
||||
// Something bad happened when reading the package.
|
||||
if (typeof e == 'object') {
|
||||
cleanup("INVALID_PACKAGE");
|
||||
} else {
|
||||
cleanup(e);
|
||||
}
|
||||
} finally {
|
||||
zipReader.close();
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user