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:
Brian Smith 2012-12-13 20:35:58 -08:00
parent c90d9b85f2
commit 84a41131c1

View File

@ -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();
}
});
});
});
};