author | Giulio Cesare Solaroli <giulio.cesare@clipperz.com> | 2013-04-26 09:18:23 (UTC) |
---|---|---|
committer | Giulio Cesare Solaroli <giulio.cesare@clipperz.com> | 2013-04-26 09:18:23 (UTC) |
commit | 108dd23db8fdc9512446be708d2694f3050b1d8f (patch) (side-by-side diff) | |
tree | feff31a273898aa20d13673947457a87024e457e | |
parent | 65f064cb6c99dde320d49e6c4157607c25e2d092 (diff) | |
download | clipperz-108dd23db8fdc9512446be708d2694f3050b1d8f.zip clipperz-108dd23db8fdc9512446be708d2694f3050b1d8f.tar.gz clipperz-108dd23db8fdc9512446be708d2694f3050b1d8f.tar.bz2 |
Fixed a bug that would "corrupt" header data when upgrading the crypto version used to process an account data
The problem being that only part of the header section would be re-encrypted, thus ending up with different sections encrypted using different crypto function versions.
And this would break when loading data back on next login.
-rw-r--r-- | frontend/beta/js/Clipperz/PM/DataModel/Header.js | 4 |
1 files changed, 3 insertions, 1 deletions
diff --git a/frontend/beta/js/Clipperz/PM/DataModel/Header.js b/frontend/beta/js/Clipperz/PM/DataModel/Header.js index 908d9f4..d577830 100644 --- a/frontend/beta/js/Clipperz/PM/DataModel/Header.js +++ b/frontend/beta/js/Clipperz/PM/DataModel/Header.js @@ -1,180 +1,181 @@ /* Copyright 2008-2013 Clipperz Srl This file is part of Clipperz, the online password manager. For further information about its features and functionalities please refer to http://www.clipperz.com. * Clipperz is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. * Clipperz is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. * You should have received a copy of the GNU Affero General Public License along with Clipperz. If not, see http://www.gnu.org/licenses/. */ if (typeof(Clipperz) == 'undefined') { Clipperz = {}; } if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; } if (typeof(Clipperz.PM.DataModel) == 'undefined') { Clipperz.PM.DataModel = {}; } //############################################################################# Clipperz.PM.DataModel.Header = function(args) { args = args || {}; this._user = args.user; this._serverData = null; this._serverDataVersion = null; this._jsonEvaledServerData = null; this._decryptedLegacyServerData = null; this._isDecryptingLegacyServerData = false; this._decryptingLegacyServerDataPendingQueue = []; this.resetUpdatedSections(); this._shouldLoadSections = {}; Clipperz.NotificationCenter.register(this.user(), 'updatedSection', this, 'updatedSectionHandler'); return this; } Clipperz.PM.DataModel.Header.prototype = MochiKit.Base.update(null, { //------------------------------------------------------------------------- 'user': function() { return this._user; }, //------------------------------------------------------------------------- //------------------------------------------------------------------------- //------------------------------------------------------------------------- //------------------------------------------------------------------------- //------------------------------------------------------------------------- //------------------------------------------------------------------------- //------------------------------------------------------------------------- //------------------------------------------------------------------------- //------------------------------------------------------------------------- 'updatedSections': function() { return this._updatedSections; }, 'markSectionAsUpdated': function(aSectionName) { this.updatedSections().push(aSectionName); }, 'resetUpdatedSections': function() { this._updatedSections = [] }, 'hasSectionBeenUpdated': function(aSectionName) { - return (this.updatedSections().join().indexOf(aSectionName) != -1); + return (this.updatedSections().join().indexOf(aSectionName) != -1) + || (this.serverDataVersion() != Clipperz.PM.Crypto.encryptingFunctions.currentVersion); }, 'cachedServerDataSection': function(aSectionName) { return (this.hasSectionBeenUpdated(aSectionName)) ? {} : this.jsonEvaledServerData()[aSectionName]; }, 'updateAllSections': function() { this.resetUpdatedSections(); this.markSectionAsUpdated('records'); this.markSectionAsUpdated('directLogins'); this.markSectionAsUpdated('preferences'); this.markSectionAsUpdated('oneTimePasswords'); return MochiKit.Async.succeed(this); }, 'updatedSectionHandler': function(anEvent) { this.markSectionAsUpdated(anEvent.parameters()); }, //------------------------------------------------------------------------- 'getObjectKeyIndex': function(anObject) { var result; var itemReference; var index; result = {}; index = 0; for (itemReference in anObject) { result[itemReference] = index.toString(); index ++; } return result; }, //------------------------------------------------------------------------- 'serializedDataWithRecordAndDirectLoginIndexes': function(aRecordIndexes, aDirectLoginIndexs) { var result; var records; var recordReference; //MochiKit.Logging.logDebug(">>> Header.serializedData"); result = { 'records': {}, 'directLogins': {} }; records = this.user().records(); for (recordReference in records) { result['records'][aRecordIndexes[recordReference]] = this.user().records()[recordReference].headerData(); } for (directLoginReference in this.user().directLoginReferences()) { var currentDirectLogin; var directLoginData; currentDirectLogin = this.user().directLoginReferences()[directLoginReference]; if (aRecordIndexes[currentDirectLogin.recordReference()] != null) { directLoginData = { // reference: currentDirectLogin.reference(), record: aRecordIndexes[currentDirectLogin.recordReference()].toString(), label: currentDirectLogin.label(), favicon: currentDirectLogin.favicon() || "" } result['directLogins'][aDirectLoginIndexs[directLoginReference]] = directLoginData; } } //MochiKit.Logging.logDebug("<<< Header.serializedData - result: " + Clipperz.Base.serializeJSON(result)); //MochiKit.Logging.logDebug("<<< Header.serializedData"); return result; }, //------------------------------------------------------------------------- 'encryptedData': function() { var deferredResult; var recordIndex; var directLoginIndex; var serializedData; var result; //MochiKit.Logging.logDebug(">>> [" + (new Date()).valueOf() + "] Header.encryptedData"); //MochiKit.Logging.logDebug("### Header.encryptedData - " + Clipperz.Base.serializeJSON(this.updatedSections())); result = { 'records': this.cachedServerDataSection('records'), 'directLogins': this.cachedServerDataSection('directLogins'), 'preferences': this.cachedServerDataSection('preferences'), 'oneTimePasswords': this.cachedServerDataSection('oneTimePasswords'), 'version': '0.1' @@ -319,192 +320,193 @@ Clipperz.PM.DataModel.Header.prototype = MochiKit.Base.update(null, { //MochiKit.Logging.logDebug(">>> Header.decryptedLegacyServerData"); deferredResult = new MochiKit.Async.Deferred(); //deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Header.decryptedLegacyServerData 1: "/* + res*/); return res;}); //deferredResult.addErrback(function(res) {MochiKit.Logging.logDebug("ERROR: " + res); return res;}); deferredResult.addCallback(MochiKit.Base.method(this, 'updateAllSections')); //deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Header.decryptedLegacyServerData 2: "/* + res*/); return res;}); //deferredResult.addErrback(function(res) {MochiKit.Logging.logDebug("ERROR: " + res); return res;}); if (this._decryptedLegacyServerData == null) { //deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Header.decryptedLegacyServerData 3: "/* + res*/); return res;}); //deferredResult.addErrback(function(res) {MochiKit.Logging.logDebug("ERROR: " + res); return res;}); deferredResult.addCallback(Clipperz.NotificationCenter.deferredNotification, this, 'updatedProgressState', 'connection_decryptingUserData'); //deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Header.decryptedLegacyServerData 4: "/* + res*/); return res;}); //deferredResult.addErrback(function(res) {MochiKit.Logging.logDebug("ERROR: " + res); return res;}); deferredResult.addCallback(Clipperz.PM.Crypto.deferredDecrypt, this.user().passphrase(), this.serverData(), this.serverDataVersion()); //deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Header.decryptedLegacyServerData 5: "/* + res*/); return res;}); //deferredResult.addErrback(function(res) {MochiKit.Logging.logDebug("ERROR: " + res); return res;}); deferredResult.addCallback(function(anHeader, aValue) { anHeader._decryptedLegacyServerData = aValue; }, this); //deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Header.decryptedLegacyServerData 6: "/* + res*/); return res;}); //deferredResult.addErrback(function(res) {MochiKit.Logging.logDebug("ERROR: " + res); return res;}); }; //deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Header.decryptedLegacyServerData 7: "/* + res*/); return res;}); //deferredResult.addErrback(function(res) {MochiKit.Logging.logDebug("ERROR: " + res); return res;}); deferredResult.addCallback(function(anHeader) { return anHeader._decryptedLegacyServerData; }, this); //deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Header.decryptedLegacyServerData 8: "/* + res*/); return res;}); //deferredResult.addErrback(function(res) {MochiKit.Logging.logDebug("ERROR: " + res); return res;}); deferredResult.callback(); //MochiKit.Logging.logDebug("<<< Header.decryptedLegacyServerData"); return deferredResult; }, //------------------------------------------------------------------------- 'serverDataFormat': function() { var result; //MochiKit.Logging.logDebug(">>> Header.serverDataFormat"); if (this.serverData().charAt(0) == '{') { var serverData; serverData = Clipperz.Base.evalJSON(this.serverData()); result = serverData['version']; } else { result = 'LEGACY'; } //MochiKit.Logging.logDebug("<<< Header.serverDataFormat"); return result; }, //------------------------------------------------------------------------- 'extractHeaderDataFromUserDetails': function(someUserDetails) { if (this.serverData() == null) { this.setServerData(someUserDetails['header']); this.setServerDataVersion(someUserDetails['version']) } }, //------------------------------------------------------------------------- 'extractDataWithKey': function(aKey) { var deferredResult; //MochiKit.Logging.logDebug(">>> Header.extractDataWithKey"); deferredResult = new MochiKit.Async.Deferred(); switch (this.serverDataFormat()) { case 'LEGACY': //deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Header.extractDataWithKey 1: "/* + res*/); return res;}); //deferredResult.addErrback(function(res) {MochiKit.Logging.logDebug("ERROR: " + res); return res;}); deferredResult.addCallback(MochiKit.Base.method(this, 'decryptedLegacyServerData')); //deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Header.extractDataWithKey 2: "/* + res*/); return res;}); //deferredResult.addErrback(function(res) {MochiKit.Logging.logDebug("ERROR: " + res); return res;}); deferredResult.addCallback(function(someDecryptedValues) { return someDecryptedValues[aKey] || {}; }) //deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Header.extractDataWithKey 3: "/* + res*/); return res;}); //deferredResult.addErrback(function(res) {MochiKit.Logging.logDebug("ERROR: " + res); return res;}); break; case '0.1': var data; //# data = Clipperz.Base.evalJSON(this.serverData()); data = this.jsonEvaledServerData(); if (typeof(data[aKey]) != 'undefined') { //deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Header.extractDataWithKey 4: "/* + res*/); return res;}); //deferredResult.addErrback(function(res) {MochiKit.Logging.logDebug("ERROR: " + res); return res;}); deferredResult.addCallback(Clipperz.NotificationCenter.deferredNotification, this, 'updatedProgressState', 'connection_decryptingUserData'); //deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Header.extractDataWithKey 5: "/* + res*/); return res;}); +//deferredResult.addBoth(function(res) {console.log("aKey: " + aKey); return res;}); //deferredResult.addErrback(function(res) {MochiKit.Logging.logDebug("ERROR: " + res); return res;}); deferredResult.addCallback(Clipperz.PM.Crypto.deferredDecrypt, this.user().passphrase(), data[aKey]['data'], this.serverDataVersion()); //deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Header.extractDataWithKey 6: "/* + res*/); return res;}); //deferredResult.addErrback(function(res) {MochiKit.Logging.logDebug("ERROR: " + res); return res;}); deferredResult.addCallback(function(/*anHeader,*/ aKey, aData, aRecordIndex, aValue) { var result; //MochiKit.Logging.logDebug(">>> [start] ==============================================="); //MochiKit.Logging.logDebug("--- extractDataWithKey - 0 [" + aKey + "]: " + Clipperz.Base.serializeJSON(aValue)); //MochiKit.Logging.logDebug("<<< [end] ================================================="); if (aKey == 'records') { var recordKey; result = {}; for (recordKey in aData['index']) { result[recordKey] = aValue[aData['index'][recordKey]]; } } else if (aKey == 'directLogins') { var recordKeyReversedIndex; var recordKey; var directLoginKey; result = {}; recordKeyReversedIndex = {}; for (recordKey in aRecordIndex) { recordKeyReversedIndex[aRecordIndex[recordKey]] = recordKey; } //MochiKit.Logging.logDebug("--- extractDataWithKey - 1 - aData['index']: " + Clipperz.Base.serializeJSON(aData['index'])); for (directLoginKey in aData['index']) { try { if ((aData['index'][directLoginKey] != null) && (aValue[aData['index'][directLoginKey]] != null)) { result[directLoginKey] = aValue[aData['index'][directLoginKey]]; result[directLoginKey]['record'] = recordKeyReversedIndex[result[directLoginKey]['record']]; } } catch(exception) { // result[directLoginKey] has no properties MochiKit.Logging.logDebug("[Header 391] EXCEPTION: " + exception); throw exception; } } //MochiKit.Logging.logDebug("--- extractDataWithKey - 2"); } else { result = aValue; } return result; }, /*this,*/ aKey, data[aKey], data['records']['index']); //deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Header.extractDataWithKey 6: "/* + res*/); return res;}); //deferredResult.addErrback(function(res) {MochiKit.Logging.logDebug("ERROR: " + res); return res;}); } else { //deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Header.extractDataWithKey 7: "/* + res*/); return res;}); //deferredResult.addErrback(function(res) {MochiKit.Logging.logDebug("ERROR: " + res); return res;}); deferredResult.addCallback(MochiKit.Async.succeed, {}); //deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Header.extractDataWithKey 8: "/* + res*/); return res;}); //deferredResult.addErrback(function(res) {MochiKit.Logging.logDebug("ERROR: " + res); return res;}); } break; } //deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Header.extractDataWithKey 9: "/* + res*/); return res;}); //deferredResult.addErrback(function(res) {MochiKit.Logging.logDebug("ERROR: " + res); return res;}); deferredResult.callback(); //MochiKit.Logging.logDebug("<<< Header.extractDataWithKey"); return deferredResult; }, //------------------------------------------------------------------------- 'processRecordData': function(someRecordData) { var records; var recordReference; //console.log("HeaderRecordData parameters", someRecordData); //MochiKit.Logging.logDebug(">>> Header.processRecordData"); records = someRecordData; //MochiKit.Logging.logDebug("--- Header.processRecordData - 1"); if (records != null) { //MochiKit.Logging.logDebug("--- Header.processRecordData - records: " + Clipperz.Base.serializeJSON(records)); for (recordReference in records) { var newRecord; var parameters; //MochiKit.Logging.logDebug("--- Header.processRecordData - 2 - recordReference: " + recordReference); if (recordReference != "stacktrace") { parameters = records[recordReference]; //.slice(); //MochiKit.Logging.logDebug("--- Header.processRecordData - 3"); if (typeof(parameters['notes']) != 'undefined') { //MochiKit.Logging.logDebug("--- Header.processRecordData - 4"); if (parameters['notes'] != "") { //MochiKit.Logging.logDebug("--- Header.processRecordData - 5"); parameters['headerNotes'] = parameters['notes']; //MochiKit.Logging.logDebug("--- Header.processRecordData - 6"); } //MochiKit.Logging.logDebug("--- Header.processRecordData - 7"); |