Diffstat (limited to 'frontend/delta/js/Clipperz/PM/Proxy/Proxy.Offline.LocalStorageDataStore.js') (more/less context) (ignore whitespace changes)
-rw-r--r-- | frontend/delta/js/Clipperz/PM/Proxy/Proxy.Offline.LocalStorageDataStore.js | 420 |
1 files changed, 420 insertions, 0 deletions
diff --git a/frontend/delta/js/Clipperz/PM/Proxy/Proxy.Offline.LocalStorageDataStore.js b/frontend/delta/js/Clipperz/PM/Proxy/Proxy.Offline.LocalStorageDataStore.js new file mode 100644 index 0000000..a3c238c --- a/dev/null +++ b/frontend/delta/js/Clipperz/PM/Proxy/Proxy.Offline.LocalStorageDataStore.js | |||
@@ -0,0 +1,420 @@ | |||
1 | /* | ||
2 | |||
3 | Copyright 2008-2013 Clipperz Srl | ||
4 | |||
5 | This file is part of Clipperz, the online password manager. | ||
6 | For further information about its features and functionalities please | ||
7 | refer to http://www.clipperz.com. | ||
8 | |||
9 | * Clipperz is free software: you can redistribute it and/or modify it | ||
10 | under the terms of the GNU Affero General Public License as published | ||
11 | by the Free Software Foundation, either version 3 of the License, or | ||
12 | (at your option) any later version. | ||
13 | |||
14 | * Clipperz is distributed in the hope that it will be useful, but | ||
15 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||
17 | See the GNU Affero General Public License for more details. | ||
18 | |||
19 | * You should have received a copy of the GNU Affero General Public | ||
20 | License along with Clipperz. If not, see http://www.gnu.org/licenses/. | ||
21 | |||
22 | */ | ||
23 | |||
24 | try { if (typeof(Clipperz.PM.Proxy.Offline.DataStore) == 'undefined') { throw ""; }} catch (e) { | ||
25 | throw "Clipperz.PM.Proxy.Offline.LocalStorageDataStore depends on Clipperz.PM.Proxy.Offline.DataStore!"; | ||
26 | } | ||
27 | |||
28 | //============================================================================= | ||
29 | |||
30 | Clipperz.PM.Proxy.Offline.LocalStorageDataStore = function(args) { | ||
31 | args = args || {}; | ||
32 | |||
33 | this._data = args.data || (typeof(_clipperz_dump_data_) != 'undefined' ? _clipperz_dump_data_ : null); | ||
34 | this._isReadOnly = (typeof(args.readOnly) == 'undefined' ? true : args.readOnly); | ||
35 | this._shouldPayTolls = args.shouldPayTolls || false; | ||
36 | |||
37 | this._tolls = {}; | ||
38 | this._currentStaticConnection = null; | ||
39 | |||
40 | //Clipperz.PM.Proxy.Offline.LocalStorageDataStore.superclass.constructor.apply(this, arguments); | ||
41 | |||
42 | return this; | ||
43 | } | ||
44 | |||
45 | Clipperz.Base.extend(Clipperz.PM.Proxy.Offline.LocalStorageDataStore, Clipperz.PM.Proxy.Offline.DataStore, { | ||
46 | |||
47 | //========================================================================= | ||
48 | |||
49 | '_knock': function(aConnection, someParameters) { | ||
50 | var result; | ||
51 | |||
52 | result = { | ||
53 | toll: this.getTollForRequestType(someParameters['requestType']) | ||
54 | } | ||
55 | |||
56 | return result; | ||
57 | }, | ||
58 | |||
59 | //------------------------------------------------------------------------- | ||
60 | |||
61 | '_registration': function(aConnection, someParameters) { | ||
62 | throw Clipperz.PM.Proxy.Offline.DataStore.exception.ReadOnly; | ||
63 | }, | ||
64 | |||
65 | //------------------------------------------------------------------------- | ||
66 | |||
67 | '_handshake': function(aConnection, someParameters) { | ||
68 | var result; | ||
69 | varnextTollRequestType; | ||
70 | |||
71 | result = {}; | ||
72 | if (someParameters.message == "connect") { | ||
73 | var userData; | ||
74 | var randomBytes; | ||
75 | var v; | ||
76 | |||
77 | userData = this.data()['users'][someParameters.parameters.C]; | ||
78 | |||
79 | if ((typeof(userData) != 'undefined') && (userData['version'] == someParameters.version)) { | ||
80 | aConnection['userData'] = userData; | ||
81 | aConnection['C'] = someParameters.parameters.C; | ||
82 | } else { | ||
83 | aConnection['userData'] = this.data()['users']['catchAllUser']; | ||
84 | } | ||
85 | |||
86 | randomBytes = Clipperz.Crypto.Base.generateRandomSeed(); | ||
87 | aConnection['b'] = new Clipperz.Crypto.BigInt(randomBytes, 16); | ||
88 | v = new Clipperz.Crypto.BigInt(aConnection['userData']['v'], 16); | ||
89 | aConnection['B'] = v.add(Clipperz.Crypto.SRP.g().powerModule(aConnection['b'], Clipperz.Crypto.SRP.n())); | ||
90 | |||
91 | aConnection['A'] = someParameters.parameters.A; | ||
92 | |||
93 | result['s'] = aConnection['userData']['s']; | ||
94 | result['B'] = aConnection['B'].asString(16); | ||
95 | |||
96 | nextTollRequestType = 'CONNECT'; | ||
97 | } else if (someParameters.message == "credentialCheck") { | ||
98 | var v, u, S, A, K, M1; | ||
99 | |||
100 | v = new Clipperz.Crypto.BigInt(aConnection['userData']['v'], 16); | ||
101 | u = new Clipperz.Crypto.BigInt(Clipperz.PM.Crypto.encryptingFunctions.versions[someParameters.version].hash(new Clipperz.ByteArray(aConnection['B'].asString(10))).toHexString(), 16); | ||
102 | A = new Clipperz.Crypto.BigInt(aConnection['A'], 16); | ||
103 | S = (A.multiply(v.powerModule(u, Clipperz.Crypto.SRP.n()))).powerModule(aConnection['b'], Clipperz.Crypto.SRP.n()); | ||
104 | |||
105 | K = Clipperz.PM.Crypto.encryptingFunctions.versions[someParameters.version].hash(new Clipperz.ByteArray(S.asString(10))).toHexString().slice(2); | ||
106 | |||
107 | M1 = Clipperz.PM.Crypto.encryptingFunctions.versions[someParameters.version].hash(new Clipperz.ByteArray(A.asString(10) + aConnection['B'].asString(10) + K)).toHexString().slice(2); | ||
108 | if (someParameters.parameters.M1 == M1) { | ||
109 | var M2; | ||
110 | |||
111 | M2 = Clipperz.PM.Crypto.encryptingFunctions.versions[someParameters.version].hash(new Clipperz.ByteArray(A.asString(10) + someParameters.parameters.M1 + K)).toHexString().slice(2); | ||
112 | result['M2'] = M2; | ||
113 | } else { | ||
114 | throw new Error("Client checksum verification failed! Expected <" + M1 + ">, received <" + someParameters.parameters.M1 + ">.", "Error"); | ||
115 | } | ||
116 | |||
117 | nextTollRequestType = 'MESSAGE'; | ||
118 | } else if (someParameters.message == "oneTimePassword") { | ||
119 | var otpData; | ||
120 | |||
121 | otpData = this.data()['onetimePasswords'][someParameters.parameters.oneTimePasswordKey]; | ||
122 | |||
123 | try { | ||
124 | if (typeof(otpData) != 'undefined') { | ||
125 | if (otpData['status'] == 'ACTIVE') { | ||
126 | if (otpData['key_checksum'] == someParameters.parameters.oneTimePasswordKeyChecksum) { | ||
127 | result = { | ||
128 | 'data': otpData['data'], | ||
129 | 'version':otpData['version'] | ||
130 | } | ||
131 | |||
132 | otpData['status'] = 'REQUESTED'; | ||
133 | } else { | ||
134 | otpData['status'] = 'DISABLED'; | ||
135 | throw "The requested One Time Password has been disabled, due to a wrong keyChecksum"; | ||
136 | } | ||
137 | } else { | ||
138 | throw "The requested One Time Password was not active"; | ||
139 | } | ||
140 | } else { | ||
141 | throw "The requested One Time Password has not been found" | ||
142 | } | ||
143 | } catch (exception) { | ||
144 | result = { | ||
145 | 'data': Clipperz.PM.Crypto.randomKey(), | ||
146 | 'version':Clipperz.PM.Connection.communicationProtocol.currentVersion | ||
147 | } | ||
148 | } | ||
149 | nextTollRequestType = 'CONNECT'; | ||
150 | } else { | ||
151 | Clipperz.logError("Clipperz.PM.Proxy.Test.handshake - unhandled message: " + someParameters.message); | ||
152 | } | ||
153 | |||
154 | result = { | ||
155 | result: result, | ||
156 | toll: this.getTollForRequestType(nextTollRequestType) | ||
157 | } | ||
158 | |||
159 | return result; | ||
160 | }, | ||
161 | |||
162 | //------------------------------------------------------------------------- | ||
163 | |||
164 | '_message': function(aConnection, someParameters) { | ||
165 | var result; | ||
166 | |||
167 | result = {}; | ||
168 | |||
169 | //===================================================================== | ||
170 | // | ||
171 | // R E A D - O N L Y M e t h o d s | ||
172 | // | ||
173 | //===================================================================== | ||
174 | if (someParameters.message == 'getUserDetails') { | ||
175 | var recordsStats; | ||
176 | var recordReference; | ||
177 | |||
178 | recordsStats = {}; | ||
179 | for (recordReference in aConnection['userData']['records']) { | ||
180 | recordsStats[recordReference] = { | ||
181 | 'updateDate': aConnection['userData']['records'][recordReference]['updateDate'] | ||
182 | } | ||
183 | } | ||
184 | |||
185 | result['header'] = this.userDetails(aConnection); | ||
186 | result['statistics'] = this.statistics(aConnection); | ||
187 | result['maxNumberOfRecords'] = aConnection['userData']['maxNumberOfRecords']; | ||
188 | result['version'] = aConnection['userData']['userDetailsVersion']; | ||
189 | result['recordsStats'] = recordsStats; | ||
190 | |||
191 | if (this.isReadOnly() == false) { | ||
192 | varlock; | ||
193 | |||
194 | if (typeof(aConnection['userData']['lock']) == 'undefined') { | ||
195 | aConnection['userData']['lock'] = "<<LOCK>>"; | ||
196 | } | ||
197 | |||
198 | result['lock'] = aConnection['userData']['lock']; | ||
199 | } | ||
200 | |||
201 | //===================================================================== | ||
202 | } else if (someParameters.message == 'getRecordDetail') { | ||
203 | /* | ||
204 | varrecordData; | ||
205 | var currentVersionData; | ||
206 | |||
207 | recordData = this.userData()['records'][someParameters['parameters']['reference']]; | ||
208 | result['reference'] = someParameters['parameters']['reference']; | ||
209 | result['data'] = recordData['data']; | ||
210 | result['version'] = recordData['version']; | ||
211 | result['creationData'] = recordData['creationDate']; | ||
212 | result['updateDate'] = recordData['updateDate']; | ||
213 | result['accessDate'] = recordData['accessDate']; | ||
214 | |||
215 | currentVersionData = recordData['versions'][recordData['currentVersion']]; | ||
216 | |||
217 | result['currentVersion'] = {}; | ||
218 | result['currentVersion']['reference'] = recordData['currentVersion']; | ||
219 | result['currentVersion']['version'] = currentVersionData['version']; | ||
220 | result['currentVersion']['header'] = currentVersionData['header']; | ||
221 | result['currentVersion']['data'] = currentVersionData['data']; | ||
222 | result['currentVersion']['creationData'] = currentVersionData['creationDate']; | ||
223 | result['currentVersion']['updateDate'] = currentVersionData['updateDate']; | ||
224 | result['currentVersion']['accessDate'] = currentVersionData['accessDate']; | ||
225 | if (typeof(currentVersionData['previousVersion']) != 'undefined') { | ||
226 | result['currentVersion']['previousVersionKey'] = currentVersionData['previousVersionKey']; | ||
227 | result['currentVersion']['previousVersion'] = currentVersionData['previousVersion']; | ||
228 | } | ||
229 | */ | ||
230 | MochiKit.Base.update(result, aConnection['userData']['records'][someParameters['parameters']['reference']]); | ||
231 | result['reference'] = someParameters['parameters']['reference']; | ||
232 | |||
233 | //===================================================================== | ||
234 | // | ||
235 | // R E A D - W R I T E M e t h o d s | ||
236 | // | ||
237 | //===================================================================== | ||
238 | } else if (someParameters.message == 'upgradeUserCredentials') { | ||
239 | if (this.isReadOnly() == false) { | ||
240 | var parameters; | ||
241 | var credentials; | ||
242 | |||
243 | parameters = someParameters['parameters']; | ||
244 | credentials = parameters['credentials']; | ||
245 | |||
246 | if ((credentials['C'] == null) | ||
247 | ||(credentials['s'] == null) | ||
248 | ||(credentials['v'] == null) | ||
249 | ||(credentials['version'] != Clipperz.PM.Connection.communicationProtocol.currentVersion) | ||
250 | ) { | ||
251 | result = Clipperz.PM.DataModel.User.exception.CredentialUpgradeFailed; | ||
252 | } else { | ||
253 | varoldCValue; | ||
254 | oldCValue = aConnection['C']; | ||
255 | |||
256 | this.data()['users'][credentials['C']] = aConnection['userData']; | ||
257 | aConnection['C'] = credentials['C']; | ||
258 | |||
259 | aConnection['userData']['s'] = credentials['s']; | ||
260 | aConnection['userData']['v'] = credentials['v']; | ||
261 | aConnection['userData']['version'] = credentials['version']; | ||
262 | |||
263 | aConnection['userData']['userDetails'] = parameters['user']['header']; | ||
264 | aConnection['userData']['userDetailsVersion'] = parameters['user']['version']; | ||
265 | aConnection['userData']['statistics'] = parameters['user']['statistics']; | ||
266 | |||
267 | aConnection['userData']['lock'] = parameters['user']['lock']; | ||
268 | |||
269 | delete this.data()['users'][oldCValue]; | ||
270 | |||
271 | result = {result:"done", parameters:parameters}; | ||
272 | } | ||
273 | } else { | ||
274 | throw Clipperz.PM.Proxy.Offline.DataStore.exception.ReadOnly; | ||
275 | } | ||
276 | |||
277 | //===================================================================== | ||
278 | |||
279 | } else if (someParameters.message == 'saveChanges') { | ||
280 | if (this.isReadOnly() == false) { | ||
281 | var i, c; | ||
282 | |||
283 | if (aConnection['userData']['lock']!= someParameters['parameters']['user']['lock']) { | ||
284 | throw "the lock attribute is not processed correctly" | ||
285 | } | ||
286 | |||
287 | aConnection['userData']['userDetails'] = someParameters['parameters']['user']['header']; | ||
288 | aConnection['userData']['statistics'] = someParameters['parameters']['user']['statistics']; | ||
289 | aConnection['userData']['userDetailsVersion']= someParameters['parameters']['user']['version']; | ||
290 | |||
291 | c = someParameters['parameters']['records']['updated'].length; | ||
292 | for (i=0; i<c; i++) { | ||
293 | var currentRecord; | ||
294 | var currentRecordData; | ||
295 | |||
296 | currentRecordData = someParameters['parameters']['records']['updated'][i]; | ||
297 | currentRecord = aConnection['userData']['records'][currentRecordData['record']['reference']]; | ||
298 | |||
299 | if ( | ||
300 | (typeof(aConnection['userData']['records'][currentRecordData['record']['reference']]) == 'undefined') | ||
301 | && | ||
302 | (typeof(currentRecordData['currentRecordVersion']) == 'undefined') | ||
303 | ) { | ||
304 | throw "Record added without a recordVersion"; | ||
305 | } | ||
306 | |||
307 | if (currentRecord == null) { | ||
308 | currentRecord = {}; | ||
309 | currentRecord['versions'] = {}; | ||
310 | currentRecord['creationDate']= Clipperz.PM.Date.formatDateWithUTCFormat(new Date()); | ||
311 | currentRecord['accessDate'] = Clipperz.PM.Date.formatDateWithUTCFormat(new Date()); | ||
312 | |||
313 | aConnection['userData']['records'][currentRecordData['record']['reference']] = currentRecord; | ||
314 | } | ||
315 | |||
316 | currentRecord['data'] = currentRecordData['record']['data']; | ||
317 | currentRecord['version']= currentRecordData['record']['version']; | ||
318 | currentRecord['updateDate']= Clipperz.PM.Date.formatDateWithUTCFormat(new Date()); | ||
319 | |||
320 | if (typeof(currentRecordData['currentRecordVersion']) != 'undefined') { | ||
321 | currentRecord['currentVersion'] = currentRecordData['currentRecordVersion']['reference']; | ||
322 | currentRecord['versions'][currentRecordData['currentRecordVersion']['reference']] = { | ||
323 | 'data': currentRecordData['currentRecordVersion']['data'], | ||
324 | 'version': currentRecordData['currentRecordVersion']['version'], | ||
325 | 'previousVersion': currentRecordData['currentRecordVersion']['previousVersion'], | ||
326 | 'previousVersionKey':currentRecordData['currentRecordVersion']['previousVersionKey'], | ||
327 | 'creationDate':Clipperz.PM.Date.formatDateWithUTCFormat(new Date()), | ||
328 | 'updateDate':Clipperz.PM.Date.formatDateWithUTCFormat(new Date()), | ||
329 | 'accessDate':Clipperz.PM.Date.formatDateWithUTCFormat(new Date()) | ||
330 | } | ||
331 | } | ||
332 | } | ||
333 | |||
334 | c = someParameters['parameters']['records']['deleted'].length; | ||
335 | for (i=0; i<c; i++) { | ||
336 | var currentRecordReference; | ||
337 | |||
338 | currentRecordReference = someParameters['parameters']['records']['deleted'][i]; | ||
339 | delete aConnection['userData']['records'][currentRecordReference]; | ||
340 | } | ||
341 | |||
342 | aConnection['userData']['lock'] = Clipperz.PM.Crypto.randomKey(); | ||
343 | result['lock'] = aConnection['userData']['lock']; | ||
344 | result['result'] = 'done'; | ||
345 | } else { | ||
346 | throw Clipperz.PM.Proxy.Offline.DataStore.exception.ReadOnly; | ||
347 | } | ||
348 | |||
349 | //===================================================================== | ||
350 | // | ||
351 | // U N H A N D L E D M e t h o d | ||
352 | // | ||
353 | //===================================================================== | ||
354 | } else { | ||
355 | Clipperz.logError("Clipperz.PM.Proxy.Test.message - unhandled message: " + someParameters.message); | ||
356 | } | ||
357 | |||
358 | result = { | ||
359 | result: result, | ||
360 | toll: this.getTollForRequestType('MESSAGE') | ||
361 | } | ||
362 | |||
363 | // return MochiKit.Async.succeed(result); | ||
364 | return result; | ||
365 | }, | ||
366 | |||
367 | //------------------------------------------------------------------------- | ||
368 | |||
369 | '_logout': function(someParameters) { | ||
370 | // return MochiKit.Async.succeed({result: 'done'}); | ||
371 | return {result: 'done'}; | ||
372 | }, | ||
373 | |||
374 | //========================================================================= | ||
375 | //######################################################################### | ||
376 | /* | ||
377 | 'userDetails': function(aConnection) { | ||
378 | var result; | ||
379 | |||
380 | if (this.isTestData(aConnection)) { | ||
381 | var serializedHeader; | ||
382 | var version; | ||
383 | |||
384 | //Clipperz.logDebug("### test data"); | ||
385 | version = aConnection['userData']['userDetailsVersion']; | ||
386 | serializedHeader = Clipperz.Base.serializeJSON(aConnection['userData']['userDetails']); | ||
387 | result = Clipperz.PM.Crypto.encryptingFunctions.versions[version].encrypt(aConnection['userData']['__masterkey_test_value__'], serializedHeader); | ||
388 | } else { | ||
389 | //Clipperz.logDebug("### NOT test data"); | ||
390 | result = aConnection['userData']['userDetails']; | ||
391 | } | ||
392 | |||
393 | return result; | ||
394 | }, | ||
395 | |||
396 | 'statistics': function(aConnection) { | ||
397 | var result; | ||
398 | |||
399 | if (aConnection['userData']['statistics'] != null) { | ||
400 | if (this.isTestData(aConnection)) { | ||
401 | var serializedStatistics; | ||
402 | var version; | ||
403 | |||
404 | version = aConnection['userData']['userDetailsVersion']; | ||
405 | serializedStatistics = Clipperz.Base.serializeJSON(aConnection['userData']['statistics']); | ||
406 | result = Clipperz.PM.Crypto.encryptingFunctions.versions[version].encrypt(aConnection['userData']['__masterkey_test_value__'], serializedStatistics); | ||
407 | } else { | ||
408 | result = aConnection['userData']['statistics']; | ||
409 | } | ||
410 | } else { | ||
411 | result = null; | ||
412 | } | ||
413 | |||
414 | return result; | ||
415 | }, | ||
416 | */ | ||
417 | //========================================================================= | ||
418 | __syntaxFix__: "syntax fix" | ||
419 | }); | ||
420 | |||