author | Brian Smith <bsmith@mozilla.com> |
Thu, 13 Dec 2012 20:35:58 -0800 | |
changeset 115911 | b11065872128ed68e5023b1861004d4af6324166 |
parent 115910 | 6a0ed6484811bc7233c39eec1687bb8ce09cb98e |
child 115928 | 8a30e07815ff4aa3d1ff2fd2d21daf93e251fa7d |
push id | 24032 |
push user | bsmith@mozilla.com |
push date | Fri, 14 Dec 2012 04:46:12 +0000 |
treeherder | mozilla-central@b11065872128 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | anygregor |
bugs | 772365 |
milestone | 20.0a1 |
first release with | nightly linux32
b11065872128
/
20.0a1
/
20121214030827
/
files
nightly linux64
b11065872128
/
20.0a1
/
20121214030827
/
files
nightly mac
b11065872128
/
20.0a1
/
20121214030827
/
files
nightly win32
b11065872128
/
20.0a1
/
20121214030827
/
files
nightly win64
b11065872128
/
20.0a1
/
20121214030827
/
files
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
releases | nightly linux32
20.0a1
/
20121214030827
/
pushlog to previous
nightly linux64
20.0a1
/
20121214030827
/
pushlog to previous
nightly mac
20.0a1
/
20121214030827
/
pushlog to previous
nightly win32
20.0a1
/
20121214030827
/
pushlog to previous
nightly win64
20.0a1
/
20121214030827
/
pushlog to previous
|
--- a/dom/apps/src/Webapps.jsm +++ b/dom/apps/src/Webapps.jsm @@ -1617,16 +1617,17 @@ this.DOMApplicationRegistry = { this._readManifests(aData, aFinalCallback, index + 1); }).bind(this)); }, downloadPackage: function(aManifest, aApp, aIsUpdate, aOnSuccess) { // 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. // If we fail at any step, we backout the previous ones and return an error. debug("downloadPackage " + JSON.stringify(aApp)); let id = this._appIdForManifestURL(aApp.manifestURL); @@ -1656,38 +1657,16 @@ this.DOMApplicationRegistry = { app.installState = download ? download.previousState : "pending"; self.broadcastMessage("Webapps:PackageEvent", { type: "error", manifestURL: aApp.manifestURL, error: aError, 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()); let requestChannel = NetUtil.newChannel(aManifest.fullPackagePath()) .QueryInterface(Ci.nsIHttpChannel); self.downloads[aApp.manifestURL] = { channel:requestChannel, appId: id, @@ -1737,71 +1716,97 @@ this.DOMApplicationRegistry = { app.installState = aIsUpdate ? "updating" : "pending"; NetUtil.asyncFetch(requestChannel, function(aInput, aResult, aRequest) { if (!Components.isSuccessCode(aResult)) { // We failed to fetch the zip. 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); NetUtil.asyncCopy(aInput, ostream, function (aResult) { if (!Components.isSuccessCode(aResult)) { // We failed to save the zip. cleanup("DOWNLOAD_ERROR"); 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 istream = zipReader.getInputStream("manifest.webapp"); + 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); + } - // 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"; + if (!zipReader.hasEntry("manifest.webapp")) { + throw "MISSING_MANIFEST"; + } - let manifest = JSON.parse(converter.ConvertToUnicode(NetUtil.readInputStreamToString(istream, - istream.available()) || "")); + let istream = zipReader.getInputStream("manifest.webapp"); - if (!AppsUtils.checkManifest(manifest)) { - throw "INVALID_MANIFEST"; - } + // 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"; - if (!AppsUtils.checkInstallAllowed(manifest, aApp.installOrigin)) { - throw "INSTALL_FROM_DENIED"; - } + 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 (!checkAppStatus(manifest)) { - throw "INVALID_SECURITY_LEVEL"; - } + if (AppsUtils.getAppManifestStatus(aManifest) > maxStatus) { + throw "INVALID_SECURITY_LEVEL"; + } - if (aOnSuccess) { - aOnSuccess(id, manifest); + 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(); } - 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 deviceStorage = Services.wm.getMostRecentWindow("navigator:browser") .navigator.getDeviceStorage("apps"); let req = deviceStorage.stat(); req.onsuccess = req.onerror = function statResult(e) {