summaryrefslogtreecommitdiff
authorGiulio 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)
commit108dd23db8fdc9512446be708d2694f3050b1d8f (patch) (side-by-side diff)
treefeff31a273898aa20d13673947457a87024e457e
parent65f064cb6c99dde320d49e6c4157607c25e2d092 (diff)
downloadclipperz-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.
Diffstat (more/less context) (show whitespace changes)
-rw-r--r--frontend/beta/js/Clipperz/PM/DataModel/Header.js4
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");