summaryrefslogtreecommitdiff
path: root/frontend/beta/js/Clipperz/PM/Proxy/Proxy.Offline.DataStore.js
Unidiff
Diffstat (limited to 'frontend/beta/js/Clipperz/PM/Proxy/Proxy.Offline.DataStore.js') (more/less context) (show whitespace changes)
-rw-r--r--frontend/beta/js/Clipperz/PM/Proxy/Proxy.Offline.DataStore.js39
1 files changed, 33 insertions, 6 deletions
diff --git a/frontend/beta/js/Clipperz/PM/Proxy/Proxy.Offline.DataStore.js b/frontend/beta/js/Clipperz/PM/Proxy/Proxy.Offline.DataStore.js
index 1a5caff..b0b9b63 100644
--- a/frontend/beta/js/Clipperz/PM/Proxy/Proxy.Offline.DataStore.js
+++ b/frontend/beta/js/Clipperz/PM/Proxy/Proxy.Offline.DataStore.js
@@ -1,87 +1,88 @@
1/* 1/*
2 2
3Copyright 2008-2013 Clipperz Srl 3Copyright 2008-2013 Clipperz Srl
4 4
5This file is part of Clipperz, the online password manager. 5This file is part of Clipperz, the online password manager.
6For further information about its features and functionalities please 6For further information about its features and functionalities please
7refer to http://www.clipperz.com. 7refer to http://www.clipperz.com.
8 8
9* Clipperz is free software: you can redistribute it and/or modify it 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 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 11 by the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version. 12 (at your option) any later version.
13 13
14* Clipperz is distributed in the hope that it will be useful, but 14* Clipperz is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of 15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 See the GNU Affero General Public License for more details. 17 See the GNU Affero General Public License for more details.
18 18
19* You should have received a copy of the GNU Affero General Public 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/. 20 License along with Clipperz. If not, see http://www.gnu.org/licenses/.
21 21
22*/ 22*/
23 23
24try { if (typeof(Clipperz.PM.Proxy.Offline) == 'undefined') { throw ""; }} catch (e) { 24try { if (typeof(Clipperz.PM.Proxy.Offline) == 'undefined') { throw ""; }} catch (e) {
25 throw "Clipperz.PM.Proxy.Offline.DataStore depends on Clipperz.PM.Proxy.Offline!"; 25 throw "Clipperz.PM.Proxy.Offline.DataStore depends on Clipperz.PM.Proxy.Offline!";
26} 26}
27 27
28//============================================================================= 28//=============================================================================
29 29
30Clipperz.PM.Proxy.Offline.DataStore = function(args) { 30Clipperz.PM.Proxy.Offline.DataStore = function(args) {
31 args = args || {}; 31 args = args || {};
32 32
33 this._data = args.data || (typeof(_clipperz_dump_data_) != 'undefined' ? _clipperz_dump_data_ : null); 33 this._data = args.data || (typeof(_clipperz_dump_data_) != 'undefined' ? _clipperz_dump_data_ : null);
34 this._isReadOnly = (typeof(args.readOnly) == 'undefined' ? true : args.readOnly); 34 this._isReadOnly = (typeof(args.readOnly) == 'undefined' ? true : args.readOnly);
35 this._shouldPayTolls = args.shouldPayTolls || false; 35 this._shouldPayTolls = args.shouldPayTolls || false;
36 36
37 this._tolls = {}; 37 this._tolls = {};
38 this._connections = {}; 38 this._connections = {};
39 39
40 this._C = null;
40 this._b = null; 41 this._b = null;
41 this._B = null; 42 this._B = null;
42 this._A = null; 43 this._A = null;
43 this._userData = null; 44 this._userData = null;
44 45
45 return this; 46 return this;
46} 47}
47 48
48//Clipperz.Base.extend(Clipperz.PM.Proxy.Offline.DataStore, Object, { 49//Clipperz.Base.extend(Clipperz.PM.Proxy.Offline.DataStore, Object, {
49Clipperz.PM.Proxy.Offline.DataStore.prototype = MochiKit.Base.update(null, { 50Clipperz.PM.Proxy.Offline.DataStore.prototype = MochiKit.Base.update(null, {
50 51
51 //------------------------------------------------------------------------- 52 //-------------------------------------------------------------------------
52 53
53 'isReadOnly': function () { 54 'isReadOnly': function () {
54 return this._isReadOnly; 55 return this._isReadOnly;
55 }, 56 },
56 57
57 //------------------------------------------------------------------------- 58 //-------------------------------------------------------------------------
58 59
59 'shouldPayTolls': function() { 60 'shouldPayTolls': function() {
60 return this._shouldPayTolls; 61 return this._shouldPayTolls;
61 }, 62 },
62 63
63 //------------------------------------------------------------------------- 64 //-------------------------------------------------------------------------
64 65
65 'data': function () { 66 'data': function () {
66 return this._data; 67 return this._data;
67 }, 68 },
68 69
69 //------------------------------------------------------------------------- 70 //-------------------------------------------------------------------------
70 71
71 'tolls': function () { 72 'tolls': function () {
72 return this._tolls; 73 return this._tolls;
73 }, 74 },
74 75
75 //------------------------------------------------------------------------- 76 //-------------------------------------------------------------------------
76 77
77 'connections': function () { 78 'connections': function () {
78 return this._connections; 79 return this._connections;
79 }, 80 },
80 81
81 //========================================================================= 82 //=========================================================================
82 83
83 'resetData': function() { 84 'resetData': function() {
84 this._data = { 85 this._data = {
85 'users': { 86 'users': {
86 'catchAllUser': { 87 'catchAllUser': {
87 __masterkey_test_value__: 'masterkey', 88 __masterkey_test_value__: 'masterkey',
@@ -99,96 +100,106 @@ Clipperz.PM.Proxy.Offline.DataStore.prototype = MochiKit.Base.update(null, {
99 }, 100 },
100 101
101 //------------------------------------------------------------------------- 102 //-------------------------------------------------------------------------
102 103
103 'setupWithData': function(someData) { 104 'setupWithData': function(someData) {
104 var deferredResult; 105 var deferredResult;
105 var resultData; 106 var resultData;
106 var i, c; 107 var i, c;
107 108
108//Clipperz.log(">>> Proxy.Test.setupWithData"); 109//Clipperz.log(">>> Proxy.Test.setupWithData");
109 resultData = this._data; 110 resultData = this._data;
110 111
111 deferredResult = new MochiKit.Async.Deferred(); 112 deferredResult = new MochiKit.Async.Deferred();
112 c = someData['users'].length; 113 c = someData['users'].length;
113 114
114 for (i=0; i<c; i++) { 115 for (i=0; i<c; i++) {
115 varnewConnection; 116 varnewConnection;
116 varrecordConfiguration; 117 varrecordConfiguration;
117 118
118 deferredResult.addCallback(MochiKit.Base.method(this, 'userSerializedEncryptedData', someData['users'][i])); 119 deferredResult.addCallback(MochiKit.Base.method(this, 'userSerializedEncryptedData', someData['users'][i]));
119 deferredResult.addCallback(MochiKit.Base.bind(function(aUserSerializationContext) { 120 deferredResult.addCallback(MochiKit.Base.bind(function(aUserSerializationContext) {
120//console.log("SERIALIZED USER", aUserSerializationContext); 121//console.log("SERIALIZED USER", aUserSerializationContext);
121 resultData['users'][aUserSerializationContext['credentials']['C']] = { 122 resultData['users'][aUserSerializationContext['credentials']['C']] = {
122 's': aUserSerializationContext['credentials']['s'], 123 's': aUserSerializationContext['credentials']['s'],
123 'v': aUserSerializationContext['credentials']['v'], 124 'v': aUserSerializationContext['credentials']['v'],
124 'version': aUserSerializationContext['data']['connectionVersion'], 125 'version': aUserSerializationContext['data']['connectionVersion'],
125 'userDetails': aUserSerializationContext['encryptedData']['user']['header'], 126 'userDetails': aUserSerializationContext['encryptedData']['user']['header'],
126 'userDetailsVersion':aUserSerializationContext['encryptedData']['user']['version'], 127 'userDetailsVersion':aUserSerializationContext['encryptedData']['user']['version'],
127 'statistics': aUserSerializationContext['encryptedData']['user']['statistics'], 128 'statistics': aUserSerializationContext['encryptedData']['user']['statistics'],
128 'lock': aUserSerializationContext['encryptedData']['user']['lock'], 129 'lock': aUserSerializationContext['encryptedData']['user']['lock'],
129 'records': this.rearrangeRecordsData(aUserSerializationContext['encryptedData']['records']) 130 'records': this.rearrangeRecordsData(aUserSerializationContext['encryptedData']['records'])
130 } 131 }
131 }, this)); 132 }, this));
132 } 133 }
133 134
134 deferredResult.addCallback(MochiKit.Base.bind(function() { 135 deferredResult.addCallback(MochiKit.Base.bind(function() {
135//console.log("this._data", resultData); 136//console.log("this._data", resultData);
136 this._data = resultData; 137 this._data = resultData;
137 }, this)); 138 }, this));
138 139
139 deferredResult.callback(); 140 deferredResult.callback();
140//Clipperz.log("<<< Proxy.Test.setupWithData"); 141//Clipperz.log("<<< Proxy.Test.setupWithData");
141 142
142 return deferredResult; 143 return deferredResult;
143 }, 144 },
144 145
145 //========================================================================= 146 //=========================================================================
146 147
148 'C': function() {
149 return this._C;
150 },
151
152 'set_C': function(aValue) {
153 this._C = aValue;
154 },
155
156 //-------------------------------------------------------------------------
157
147 'b': function() { 158 'b': function() {
148 return this._b; 159 return this._b;
149 }, 160 },
150 161
151 'set_b': function(aValue) { 162 'set_b': function(aValue) {
152 this._b = aValue; 163 this._b = aValue;
153 }, 164 },
154 165
155 //------------------------------------------------------------------------- 166 //-------------------------------------------------------------------------
156 167
157 'B': function() { 168 'B': function() {
158 return this._B; 169 return this._B;
159 }, 170 },
160 171
161 'set_B': function(aValue) { 172 'set_B': function(aValue) {
162 this._B = aValue; 173 this._B = aValue;
163 }, 174 },
164 175
165 //------------------------------------------------------------------------- 176 //-------------------------------------------------------------------------
166 177
167 'A': function() { 178 'A': function() {
168 return this._A; 179 return this._A;
169 }, 180 },
170 181
171 'set_A': function(aValue) { 182 'set_A': function(aValue) {
172 this._A = aValue; 183 this._A = aValue;
173 }, 184 },
174 185
175 //------------------------------------------------------------------------- 186 //-------------------------------------------------------------------------
176 187
177 'userData': function() { 188 'userData': function() {
178 return this._userData; 189 return this._userData;
179 }, 190 },
180 191
181 'setUserData': function(aValue) { 192 'setUserData': function(aValue) {
182 this._userData = aValue; 193 this._userData = aValue;
183 }, 194 },
184 195
185 //========================================================================= 196 //=========================================================================
186 197
187 'getTollForRequestType': function (aRequestType) { 198 'getTollForRequestType': function (aRequestType) {
188 varresult; 199 varresult;
189 vartargetValue; 200 vartargetValue;
190 var cost; 201 var cost;
191 202
192 targetValue = Clipperz.Crypto.PRNG.defaultRandomGenerator().getRandomBytes(32).toHexString().substring(2); 203 targetValue = Clipperz.Crypto.PRNG.defaultRandomGenerator().getRandomBytes(32).toHexString().substring(2);
193 switch (aRequestType) { 204 switch (aRequestType) {
194 case 'REGISTER': 205 case 'REGISTER':
@@ -295,122 +306,138 @@ Clipperz.PM.Proxy.Offline.DataStore.prototype = MochiKit.Base.update(null, {
295 'lock': Clipperz.Crypto.Base.generateRandomSeed(), 306 'lock': Clipperz.Crypto.Base.generateRandomSeed(),
296 // 'maxNumberOfRecords':'100', 307 // 'maxNumberOfRecords':'100',
297 'userDetails': someParameters['user']['header'], 308 'userDetails': someParameters['user']['header'],
298 'statistics': someParameters['user']['statistics'], 309 'statistics': someParameters['user']['statistics'],
299 'userDetailsVersion':someParameters['user']['version'], 310 'userDetailsVersion':someParameters['user']['version'],
300 'records':{} 311 'records':{}
301 } 312 }
302 } else { 313 } else {
303 throw "user already exists"; 314 throw "user already exists";
304 } 315 }
305 } else { 316 } else {
306 throw Clipperz.PM.Proxy.Offline.DataStore.exception.ReadOnly; 317 throw Clipperz.PM.Proxy.Offline.DataStore.exception.ReadOnly;
307 } 318 }
308 319
309 result = { 320 result = {
310 result: { 321 result: {
311 'lock': this.data()['users'][someParameters['credentials']['C']]['lock'], 322 'lock': this.data()['users'][someParameters['credentials']['C']]['lock'],
312 'result':'done' 323 'result':'done'
313 }, 324 },
314 toll: this.getTollForRequestType('CONNECT') 325 toll: this.getTollForRequestType('CONNECT')
315 } 326 }
316 327
317 return MochiKit.Async.succeed(result); 328 return MochiKit.Async.succeed(result);
318 }, 329 },
319 330
320 //------------------------------------------------------------------------- 331 //-------------------------------------------------------------------------
321 332
322 '_handshake': function(someParameters) { 333 '_handshake': function(someParameters) {
323 var result; 334 var result;
324 varnextTollRequestType; 335 varnextTollRequestType;
325 336
326//Clipperz.log(">>> Proxy.Offline.DataStore._handshake"); 337//Clipperz.log(">>> Proxy.Offline.DataStore._handshake");
327 result = {}; 338 result = {};
328 if (someParameters.message == "connect") { 339 if (someParameters.message == "connect") {
329 var userData; 340 var userData;
330 var randomBytes; 341 var randomBytes;
331 var b, B, v; 342 var b, B, v;
332 343
333//console.log(">>> Proxy.Offline.DataStore._handshake.connect", someParameters); 344//console.log(">>> Proxy.Offline.DataStore._handshake.connect", someParameters);
334 userData = this.data()['users'][someParameters.parameters.C]; 345 userData = this.data()['users'][someParameters.parameters.C];
335 346
336 if ((typeof(userData) != 'undefined') && (userData['version'] == someParameters.version)) { 347 if ((typeof(userData) != 'undefined') && (userData['version'] == someParameters.version)) {
337 this.setUserData(userData); 348 this.setUserData(userData);
338 } else { 349 } else {
339 this.setUserData(this.data()['users']['catchAllUser']); 350 this.setUserData(this.data()['users']['catchAllUser']);
340 } 351 }
341 352
342 randomBytes = Clipperz.Crypto.Base.generateRandomSeed(); 353 randomBytes = Clipperz.Crypto.Base.generateRandomSeed();
354 this.set_C(someParameters.parameters.C);
343 this.set_b(new Clipperz.Crypto.BigInt(randomBytes, 16)); 355 this.set_b(new Clipperz.Crypto.BigInt(randomBytes, 16));
344 v = new Clipperz.Crypto.BigInt(this.userData()['v'], 16); 356 v = new Clipperz.Crypto.BigInt(this.userData()['v'], 16);
345 this.set_B(v.add(Clipperz.Crypto.SRP.g().powerModule(this.b(), Clipperz.Crypto.SRP.n()))); 357 this.set_B((Clipperz.Crypto.SRP.k().multiply(v)).add(Clipperz.Crypto.SRP.g().powerModule(this.b(), Clipperz.Crypto.SRP.n())));
346 358
347 this.set_A(someParameters.parameters.A); 359 this.set_A(someParameters.parameters.A);
348 360
349 result['s'] = this.userData()['s']; 361 result['s'] = this.userData()['s'];
350 result['B'] = this.B().asString(16); 362 result['B'] = this.B().asString(16);
351 363
352 nextTollRequestType = 'CONNECT'; 364 nextTollRequestType = 'CONNECT';
353 } else if (someParameters.message == "credentialCheck") { 365 } else if (someParameters.message == "credentialCheck") {
354 var v, u, S, A, K, M1; 366 var v, u, s, S, A, K, M1;
367 var stringHash = function (aValue) {
368 return Clipperz.PM.Crypto.encryptingFunctions.versions[someParameters.version].hash(new Clipperz.ByteArray(aValue)).toHexString().substring(2);
369 };
355 370
356//console.log(">>> Proxy.Offline.DataStore._handshake.credentialCheck", someParameters); 371//console.log(">>> Proxy.Offline.DataStore._handshake.credentialCheck", someParameters);
357 v = new Clipperz.Crypto.BigInt(this.userData()['v'], 16); 372 v = new Clipperz.Crypto.BigInt(this.userData()['v'], 16);
358 u = new Clipperz.Crypto.BigInt(Clipperz.PM.Crypto.encryptingFunctions.versions[someParameters.version].hash(new Clipperz.ByteArray(this.B().asString(10))).toHexString(), 16);
359 A = new Clipperz.Crypto.BigInt(this.A(), 16); 373 A = new Clipperz.Crypto.BigInt(this.A(), 16);
374 u = new Clipperz.Crypto.BigInt(Clipperz.PM.Crypto.encryptingFunctions.versions[someParameters.version].hash(new Clipperz.ByteArray(A.asString(10) + this.B().asString(10))).toHexString(), 16);
375 s = new Clipperz.Crypto.BigInt(this.userData()['s'], 16);
360 S = (A.multiply(v.powerModule(u, Clipperz.Crypto.SRP.n()))).powerModule(this.b(), Clipperz.Crypto.SRP.n()); 376 S = (A.multiply(v.powerModule(u, Clipperz.Crypto.SRP.n()))).powerModule(this.b(), Clipperz.Crypto.SRP.n());
361 377
362 K = Clipperz.PM.Crypto.encryptingFunctions.versions[someParameters.version].hash(new Clipperz.ByteArray(S.asString(10))).toHexString().slice(2); 378 K = stringHash(S.asString(10));
363 379
364 M1 = Clipperz.PM.Crypto.encryptingFunctions.versions[someParameters.version].hash(new Clipperz.ByteArray(A.asString(10) + this.B().asString(10) + K)).toHexString().slice(2); 380 M1 = stringHash(
381 "597626870978286801440197562148588907434001483655788865609375806439877501869636875571920406529" +
382 stringHash(this.C()) +
383 s.asString(10) +
384 A.asString(10) +
385 this.B().asString(10) +
386 K
387 );
365 if (someParameters.parameters.M1 == M1) { 388 if (someParameters.parameters.M1 == M1) {
366 var M2; 389 var M2;
367 390
368 M2 = Clipperz.PM.Crypto.encryptingFunctions.versions[someParameters.version].hash(new Clipperz.ByteArray(A.asString(10) + someParameters.parameters.M1 + K)).toHexString().slice(2); 391 M2 = stringHash(
392 A.asString(10) +
393 someParameters.parameters.M1 +
394 K
395 );
369 result['M2'] = M2; 396 result['M2'] = M2;
370 } else { 397 } else {
371 throw new Error("Client checksum verification failed! Expected <" + M1 + ">, received <" + someParameters.parameters.M1 + ">.", "Error"); 398 throw new Error("Client checksum verification failed! Expected <" + M1 + ">, received <" + someParameters.parameters.M1 + ">.", "Error");
372 } 399 }
373 400
374 nextTollRequestType = 'MESSAGE'; 401 nextTollRequestType = 'MESSAGE';
375 } else if (someParameters.message == "oneTimePassword") { 402 } else if (someParameters.message == "oneTimePassword") {
376 var otpData; 403 var otpData;
377 404
378//console.log("HANDSHAKE WITH OTP", someParameters.parameters.oneTimePasswordKey); 405//console.log("HANDSHAKE WITH OTP", someParameters.parameters.oneTimePasswordKey);
379//console.log("someParameters", someParameters); 406//console.log("someParameters", someParameters);
380//console.log("data.OTP", Clipperz.Base.serializeJSON(this.data()['onetimePasswords'])); 407//console.log("data.OTP", Clipperz.Base.serializeJSON(this.data()['onetimePasswords']));
381 otpData = this.data()['onetimePasswords'][someParameters.parameters.oneTimePasswordKey]; 408 otpData = this.data()['onetimePasswords'][someParameters.parameters.oneTimePasswordKey];
382 409
383 try { 410 try {
384 if (typeof(otpData) != 'undefined') { 411 if (typeof(otpData) != 'undefined') {
385 if (otpData['status'] == 'ACTIVE') { 412 if (otpData['status'] == 'ACTIVE') {
386 if (otpData['key_checksum'] == someParameters.parameters.oneTimePasswordKeyChecksum) { 413 if (otpData['key_checksum'] == someParameters.parameters.oneTimePasswordKeyChecksum) {
387 result = { 414 result = {
388 'data': otpData['data'], 415 'data': otpData['data'],
389 'version':otpData['version'] 416 'version':otpData['version']
390 } 417 }
391 418
392 otpData['status'] = 'REQUESTED'; 419 otpData['status'] = 'REQUESTED';
393 } else { 420 } else {
394 otpData['status'] = 'DISABLED'; 421 otpData['status'] = 'DISABLED';
395 throw "The requested One Time Password has been disabled, due to a wrong keyChecksum"; 422 throw "The requested One Time Password has been disabled, due to a wrong keyChecksum";
396 } 423 }
397 } else { 424 } else {
398 throw "The requested One Time Password was not active"; 425 throw "The requested One Time Password was not active";
399 } 426 }
400 } else { 427 } else {
401 throw "The requested One Time Password has not been found" 428 throw "The requested One Time Password has not been found"
402 } 429 }
403 } catch (exception) { 430 } catch (exception) {
404 result = { 431 result = {
405 'data': Clipperz.PM.Crypto.randomKey(), 432 'data': Clipperz.PM.Crypto.randomKey(),
406 'version':Clipperz.PM.Connection.communicationProtocol.currentVersion 433 'version':Clipperz.PM.Connection.communicationProtocol.currentVersion
407 } 434 }
408 } 435 }
409 nextTollRequestType = 'CONNECT'; 436 nextTollRequestType = 'CONNECT';
410 } else { 437 } else {
411 MochiKit.Logging.logError("Clipperz.PM.Proxy.Test.handshake - unhandled message: " + someParameters.message); 438 MochiKit.Logging.logError("Clipperz.PM.Proxy.Test.handshake - unhandled message: " + someParameters.message);
412 } 439 }
413//console.log("<<< Proxy.Offline._handshake", result); 440//console.log("<<< Proxy.Offline._handshake", result);
414 441
415 result = { 442 result = {
416 result: result, 443 result: result,