summaryrefslogtreecommitdiff
path: root/frontend/gamma/js/Clipperz/PM/Connection.js
Unidiff
Diffstat (limited to 'frontend/gamma/js/Clipperz/PM/Connection.js') (more/less context) (ignore whitespace changes)
-rw-r--r--frontend/gamma/js/Clipperz/PM/Connection.js619
1 files changed, 619 insertions, 0 deletions
diff --git a/frontend/gamma/js/Clipperz/PM/Connection.js b/frontend/gamma/js/Clipperz/PM/Connection.js
new file mode 100644
index 0000000..6e58c60
--- a/dev/null
+++ b/frontend/gamma/js/Clipperz/PM/Connection.js
@@ -0,0 +1,619 @@
1/*
2
3Copyright 2008-2011 Clipperz Srl
4
5This file is part of Clipperz's Javascript Crypto Library.
6Javascript Crypto Library provides web developers with an extensive
7and efficient set of cryptographic functions. The library aims to
8obtain maximum execution speed while preserving modularity and
9reusability.
10For further information about its features and functionalities please
11refer to http://www.clipperz.com
12
13* Javascript Crypto Library is free software: you can redistribute
14 it and/or modify it under the terms of the GNU Affero General Public
15 License as published by the Free Software Foundation, either version
16 3 of the License, or (at your option) any later version.
17
18* Javascript Crypto Library is distributed in the hope that it will
19 be useful, but WITHOUT ANY WARRANTY; without even the implied
20 warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
21 See the GNU Affero General Public License for more details.
22
23* You should have received a copy of the GNU Affero General Public
24 License along with Javascript Crypto Library. If not, see
25 <http://www.gnu.org/licenses/>.
26
27*/
28
29if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
30if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; }
31
32//-----------------------------------------------------------------------------
33//
34 // Abstract C O N N E C T I O N class
35//
36//-----------------------------------------------------------------------------
37
38Clipperz.PM.Connection = function (args) {
39 args = args || {};
40
41 this._proxy = args.proxy || Clipperz.PM.Proxy.defaultProxy;
42 this._getCredentialsFunction = args.getCredentialsFunction;
43
44 this._clipperz_pm_crypto_version = null;
45 this._connectionId = null;
46 this._sharedSecret = null;
47
48 return this;
49}
50
51Clipperz.PM.Connection.prototype = MochiKit.Base.update(null, {
52
53 'toString': function() {
54 return "Connection [" + this.version() + "]";
55 },
56
57 //=========================================================================
58
59 'version': function() {
60 throw Clipperz.Base.exception.AbstractMethod;
61 },
62
63 'clipperz_pm_crypto_version': function() {
64 if (this._clipperz_pm_crypto_version == null) {
65 var connectionVersions;
66 varversions;
67 varversion;
68 var i, c;
69
70 version = null;
71 connectionVersions = Clipperz.PM.Connection.communicationProtocol.versions;
72 versions = MochiKit.Base.keys(connectionVersions);
73 c = versions.length;
74 for (i=0; i<c; i++) {
75 if (! (versions[i] == 'current')) {
76 if (this instanceof connectionVersions[versions[i]]) {
77 version = versions[i];
78 };
79 }
80 }
81
82 this._clipperz_pm_crypto_version = version;
83 }
84
85 return this._clipperz_pm_crypto_version;
86 },
87
88 //-------------------------------------------------------------------------
89
90 'defaultErrorHandler': function(anErrorString, anException) {
91MochiKit.Logging.logError("### Connection.defaultErrorHandler: " + anErrorString + " (" + anException + ")");
92 },
93
94 //-------------------------------------------------------------------------
95
96 'getCredentialsFunction': function () {
97 return this._getCredentialsFunction;
98 },
99
100 'normalizedCredentials': function(someValues) {
101 throw Clipperz.Base.exception.AbstractMethod;
102 },
103
104 //=========================================================================
105
106 'proxy': function () {
107 return this._proxy;
108 },
109
110 //=========================================================================
111
112 'register': function () {
113 throw Clipperz.Base.exception.AbstractMethod;
114 },
115
116 'login': function() {
117 throw Clipperz.Base.exception.AbstractMethod;
118 },
119
120 //-------------------------------------------------------------------------
121
122 'message': function(someArguments, aCallback) {
123 throw Clipperz.Base.exception.AbstractMethod;
124 },
125
126 //-------------------------------------------------------------------------
127
128 'serverSideUserCredentials': function() {
129 throw Clipperz.Base.exception.AbstractMethod;
130 },
131
132 //=========================================================================
133
134 'sharedSecret': function () {
135 return this._sharedSecret;
136 },
137
138 'setSharedSecret': function (aValue) {
139 this._sharedSecret = aValue;
140 },
141
142 //-------------------------------------------------------------------------
143
144 'connectionId': function() {
145 return this._connectionId;
146 },
147
148 'setConnectionId': function(aValue) {
149 this._connectionId = aValue;
150 },
151
152 //=========================================================================
153/*
154 //TODO: ?????
155 'oneTimePassword': function() {
156 return this._oneTimePassword;
157 },
158
159 'setOneTimePassword': function(aValue) {
160 this._oneTimePassword = aValue;
161 },
162*/
163 //=========================================================================
164
165 'reset': function() {
166 this.setSharedSecret(null);
167 this.setConnectionId(null);
168 },
169
170 //=========================================================================
171 __syntaxFix__: "syntax fix"
172
173}
174);
175
176
177if (typeof(Clipperz.PM.Connection.SRP) == 'undefined') { Clipperz.PM.Connection.SRP = {}; }
178//-----------------------------------------------------------------------------
179//
180 // S R P [ 1 . 0 ] C O N N E C T I O N class
181//
182//-----------------------------------------------------------------------------
183
184Clipperz.PM.Connection.SRP['1.0'] = function (args) {
185 Clipperz.PM.Connection.call(this, args);
186
187 return this;
188}
189
190Clipperz.PM.Connection.SRP['1.0'].prototype = MochiKit.Base.update(new Clipperz.PM.Connection(), {
191
192 'version': function() {
193 return '1.0';
194 },
195
196 //=========================================================================
197
198 'register': function (someUserData) {
199 vardeferredResult;
200 var cryptoVersion;
201 var srpConnection;
202
203 cryptoVersion = this.clipperz_pm_crypto_version();
204
205 deferredResult = new Clipperz.Async.Deferred("Connection.registerWithVersion", {trace:false});
206 deferredResult.collectResults({
207 'credentials': [
208 this.getCredentialsFunction(),
209 MochiKit.Base.method(this, 'normalizedCredentials'),
210 MochiKit.Base.bind(function(someCredentials) {
211 var srpConnection;
212 var result;
213
214 srpConnection = new Clipperz.Crypto.SRP.Connection({ C:someCredentials['username'], P:someCredentials['password'], hash:this.hash() });
215 result = srpConnection.serverSideCredentials();
216 result['version'] = Clipperz.PM.Connection.communicationProtocol.currentVersion;
217
218 return result;
219 }, this)
220 ],
221 'user': MochiKit.Base.partial(MochiKit.Async.succeed, someUserData),
222 'version':MochiKit.Base.partial(MochiKit.Async.succeed, Clipperz.PM.Connection.communicationProtocol.currentVersion),
223 'message':MochiKit.Base.partial(MochiKit.Async.succeed, 'completeRegistration')
224 });
225 deferredResult.addCallbackPass(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'advanceProgress');
226 deferredResult.addMethod(this.proxy(), 'registration');
227 deferredResult.addCallbackPass(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'advanceProgress');
228
229 deferredResult.callback();
230
231 return deferredResult;
232 },
233
234 //-------------------------------------------------------------------------
235
236 'updateCredentials': function (aUsername, aPassphrase, someUserData) {
237 vardeferredResult;
238
239 deferredResult = new Clipperz.Async.Deferred("Connection.updateCredentials", {trace:false});
240 deferredResult.collectResults({
241 'credentials': [
242 MochiKit.Base.method(this, 'normalizedCredentials', {username:aUsername, password:aPassphrase}),
243 MochiKit.Base.bind(function(someCredentials) {
244 var srpConnection;
245 var result;
246
247 srpConnection = new Clipperz.Crypto.SRP.Connection({ C:someCredentials['username'], P:someCredentials['password'], hash:this.hash() });
248 result = srpConnection.serverSideCredentials();
249 result['version'] = Clipperz.PM.Connection.communicationProtocol.currentVersion;
250
251 return result;
252 }, this)
253 ],
254 'user': MochiKit.Base.partial(MochiKit.Async.succeed, someUserData)
255 });
256 deferredResult.addCallbackPass(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'advanceProgress');
257 deferredResult.addMethod(this, 'message', 'upgradeUserCredentials');
258 deferredResult.addCallbackPass(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'advanceProgress');
259 deferredResult.callback();
260
261 return deferredResult;
262
263 },
264
265 //=========================================================================
266
267 'redeemOneTimePassword': function (someParameters) {
268//console.log("Connections.redeemOneTimePassword", someParameters['username'], someParameters['password']);
269/*
270 //=========================================================================
271 //LOGIN WITH PASSPHRASE, extracted from the TRUNK version (LoginPanel.js)
272 deferredResult.addCallback(function(anUsername, aOneTimePassword) {
273 var args;
274
275 args = {
276 'message': 'oneTimePassword',
277 'version': Clipperz.PM.Crypto.communicationProtocol.currentVersion,
278 'parameters': {
279 'oneTimePasswordKey': Clipperz.PM.DataModel.OneTimePassword.computeKeyWithUsernameAndPassword(anUsername, aOneTimePassword),
280 'oneTimePasswordKeyChecksum': Clipperz.PM.DataModel.OneTimePassword.computeKeyChecksumWithUsernameAndPassword(anUsername, aOneTimePassword)
281 }
282 }
283
284 return args;
285 }, anUsername, oneTimePassword);
286 deferredResult.addCallback(Clipperz.NotificationCenter.deferredNotification, this, 'updatedProgressState', 'OTP_login_loadingOTP');
287 deferredResult.addCallback(MochiKit.Base.method(Clipperz.PM.Proxy.defaultProxy, 'handshake'));
288 deferredResult.addCallback(Clipperz.NotificationCenter.deferredNotification, this, 'updatedProgressState', 'OTP_login_extractingPassphrase');
289 deferredResult.addCallback(function(aResult) {
290 return Clipperz.PM.Crypto.deferredDecrypt(oneTimePassword, aResult['data'], aResult['version']);
291 });
292 deferredResult.addCallback(function(aResult) {
293 return (new Clipperz.ByteArray().appendBase64String(aResult['passphrase'])).asString();
294 });
295 deferredResult.addMethod(this, 'doLoginWithUsernameAndPassphrase', anUsername),
296*/
297 var args;
298 var normalizedOTP;
299
300 normalizedOTP = Clipperz.PM.DataModel.OneTimePassword.normalizedOneTimePassword(someParameters['password']);
301
302 args = {
303 'message': 'oneTimePassword',
304 'version': Clipperz.PM.Connection.communicationProtocol.currentVersion,
305 'parameters': {
306 'oneTimePasswordKey': Clipperz.PM.DataModel.OneTimePassword.computeKeyWithUsernameAndPassword(someParameters['username'], normalizedOTP),
307 'oneTimePasswordKeyChecksum':Clipperz.PM.DataModel.OneTimePassword.computeKeyChecksumWithUsernameAndPassword(someParameters['username'], normalizedOTP)
308 }
309 }
310
311 return Clipperz.Async.callbacks("Connction.redeemOTP", [
312 MochiKit.Base.method(this.proxy(), 'handshake', args),
313 function(aResult) {
314 return Clipperz.PM.Crypto.deferredDecrypt({
315 value:aResult['data'],
316 key:normalizedOTP,
317 version:aResult['version']
318 });
319 },
320 function(aResult) {
321 return (new Clipperz.ByteArray().appendBase64String(aResult['passphrase'])).asString();
322 }
323 ], {trace:false})
324 },
325
326 'login': function(/*anUsername, aPassphrase*/) {
327 vardeferredResult;
328 var cryptoVersion;
329 var srpConnection;
330
331 cryptoVersion = this.clipperz_pm_crypto_version();
332
333 deferredResult = new Clipperz.Async.Deferred("Connection.login", {trace:false});
334 deferredResult.addCallback(this.getCredentialsFunction());
335 deferredResult.addMethod(this, 'normalizedCredentials');
336 // deferredResult.addCallbackPass(MochiKit.Signal.signal, this, 'updatedProgressState', 'connection_sendingCredentials');
337 deferredResult.addCallbackPass(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'advanceProgress');
338 deferredResult.addCallback(MochiKit.Base.bind(function(someCredentials) {
339 srpConnection = new Clipperz.Crypto.SRP.Connection({ C:someCredentials['username'], P:someCredentials['password'], hash:this.hash() });
340 }, this));
341 deferredResult.addCallback(function() {
342 var result;
343
344 result = {
345 message: 'connect',
346 version: cryptoVersion,
347 parameters: {
348 C: srpConnection.C(),
349 A: srpConnection.A().asString(16)
350 // reconnecting: this.connectionId()
351 }
352 };
353
354 // TODO: ?????
355 // if (isReconnecting == true) {
356 // args.parameters['reconnecting'] = aConnection.connectionId();
357 // }
358
359 return result;
360 });
361 deferredResult.addMethod(this.proxy(), 'handshake');
362 // deferredResult.addCallbackPass(MochiKit.Signal.signal, this, 'updatedProgressState', 'connection_credentialVerification');
363 deferredResult.addCallbackPass(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'advanceProgress');
364 deferredResult.addCallback(function(someParameters) {
365 var result;
366
367 srpConnection.set_s(new Clipperz.Crypto.BigInt(someParameters['s'], 16));
368 srpConnection.set_B(new Clipperz.Crypto.BigInt(someParameters['B'], 16));
369
370 //TODO: ?????
371 // if (typeof(someParameters['oneTimePassword']) != 'undefined') {
372 // this.setOneTimePassword(someParameters['oneTimePassword']);
373 // }
374
375 result = {
376 message: 'credentialCheck',
377 version: cryptoVersion,
378 parameters: {
379 M1: srpConnection.M1()
380 }
381 };
382
383 return result;
384 });
385 deferredResult.addMethod(this.proxy(), 'handshake');
386 deferredResult.addCallback(function(someParameters) {
387 var result;
388
389 if (someParameters['M2'] == srpConnection.M2()) {
390 result = MochiKit.Async.succeed(someParameters);
391 } else {
392 result = MochiKit.Async.fail(Clipperz.PM.Connection.exception.WrongChecksum);
393 }
394
395 return result;
396 });
397 deferredResult.addCallback(MochiKit.Base.bind(function(someParameters) {
398 this.setConnectionId(someParameters['connectionId']);
399 this.setSharedSecret(srpConnection.K());
400
401 // TODO: ?????
402 // if (this.oneTimePassword() != null) {
403 /// ?? result = this.user().oneTimePasswordManager().archiveOneTimePassword(this.oneTimePassword()));
404 // }
405 return someParameters;
406 }, this));
407 // deferredResult.addCallbackPass(MochiKit.Signal.signal, this, 'updatedProgressState', 'connection_loggedIn');
408 deferredResult.addCallbackPass(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'advanceProgress');
409 deferredResult.addCallback(MochiKit.Async.succeed, {result:"done"});
410
411 deferredResult.callback();
412
413 return deferredResult;
414 },
415
416 //=========================================================================
417
418 'logout': function() {
419 return Clipperz.Async.callbacks("Connection.logout", [
420 MochiKit.Base.method(this, 'setSharedSecret'),
421 MochiKit.Base.method(this.proxy(), 'logout', {})
422 ], {trace:false});
423 },
424
425 //=========================================================================
426
427 'ping': function () {
428 //TODO: ping the server in order to have a valid session
429 },
430
431 //=========================================================================
432
433 'message': function(aMessageName, someParameters) {
434 var args;
435
436//console.log(">>> Connection.message", aMessageName, someParameters);
437 args = {
438 message: aMessageName,
439 srpSharedSecret: this.sharedSecret(),
440 parameters: (someParameters || {})
441 }
442
443 return this.sendMessage(args);
444 },
445
446 //-------------------------------------------------------------------------
447
448 'sendMessage': function(someArguments) {
449 vardeferredResult;
450
451 deferredResult = new Clipperz.Async.Deferred("Connection.sendMessage", {trace:false});
452 deferredResult.addMethod(this.proxy(), 'message', someArguments);
453 deferredResult.addCallback(MochiKit.Base.bind(function(res) {
454 if (typeof(res['lock']) != 'undefined') {
455 //TODO: ?????
456 // ?? this.user().setLock(res['lock']);
457 }
458 return res;
459 }, this));
460
461 deferredResult.addErrback(MochiKit.Base.method(this, 'messageExceptionHandler'), someArguments);
462 deferredResult.callback();
463
464 return deferredResult
465 },
466
467 //-------------------------------------------------------------------------
468
469 'messageExceptionHandler': function(anOriginalMessageArguments, anError) {
470 var result;
471
472console.log(">>> Connection.messageExceptionHandler", anError, anError.message);
473 if (anError instanceof MochiKit.Async.CancelledError) {
474 result = anError;
475 } else {
476 if ((anError.message == 'Trying to communicate without an active connection')||
477 (anError.message == 'No tollManager available for current session')
478 ) {
479 result = this.reestablishConnection(anOriginalMessageArguments);
480 } else if (anError.message == 'Session with stale data') {
481 MochiKit.Signal.signal(this, 'EXCEPTION');
482 } else {
483 result = anError;
484 }
485 }
486console.log("<<< Connection.messageExceptionHandler", anError)
487
488 return result;;
489 },
490
491 //=========================================================================
492
493 'reestablishConnection': function(anOriginalMessageArguments) {
494 var deferredResult;
495
496 deferredResult = new Clipperz.Async.Deferred("Connection.reestablishConnection");
497 deferredResult.addMethod(this, 'reset');
498 deferredResult.addMethod(this, 'login', true);
499 deferredResult.addCallback(MochiKit.Base.bind(function(aMessage) {
500 aMessage['srpSharedSecret'] = this.sharedSecret();
501 return aMessage;
502 }, this), anOriginalMessageArguments);
503 deferredResult.addMethod(this, 'sendMessage');
504 deferredResult.addErrback(MochiKit.Signal.signal, this, 'EXCEPTION', null);
505 deferredResult.callback();
506
507 return deferredResult;
508 },
509
510 //=========================================================================
511
512 'serverSideUserCredentials': function(aUsername, aPassword) {
513 varresult;
514 varnewSrpConnection;
515 var normalizedAttributes;
516
517 normalizedAttributes = this.normalizedCredentials({username:aUsername, password:aPassword});
518 newSrpConnection = new Clipperz.Crypto.SRP.Connection({ C:normalizedAttributes['username'], P:normalizedAttributes['password'], hash:this.hash() });
519 result = newSrpConnection.serverSideCredentials();
520 result['version'] = this.clipperz_pm_crypto_version();
521
522 return result;
523 },
524
525 //=========================================================================
526
527 'normalizedCredentials': function(someValues) {
528 var result;
529
530 result = {}
531 result['username'] = this.hash()(new Clipperz.ByteArray(someValues['username'])).toHexString().substring(2);
532 result['password'] = this.hash()(new Clipperz.ByteArray(someValues['password'] + someValues['username'])).toHexString().substring(2);
533
534 return result;
535 },
536
537 //-----------------------------------------------------------------------------
538
539 'hash': function() {
540 return Clipperz.PM.Crypto.encryptingFunctions.versions['0.1'].hash;
541 },
542
543 //-----------------------------------------------------------------------------
544 __syntaxFix__: "syntax fix"
545
546});
547
548
549
550//-----------------------------------------------------------------------------
551//
552 // S R P [ 1 . 1 ] C O N N E C T I O N class
553//
554//-----------------------------------------------------------------------------
555
556Clipperz.PM.Connection.SRP['1.1'] = function (args) {
557 Clipperz.PM.Connection.SRP['1.0'].call(this, args);
558
559 return this;
560}
561
562Clipperz.PM.Connection.SRP['1.1'].prototype = MochiKit.Base.update(new Clipperz.PM.Connection.SRP['1.0'](), {
563
564 'version': function() {
565 return '1.1';
566 },
567
568 //-----------------------------------------------------------------------------
569
570 'normalizedCredentials': function(someValues) {
571 var result;
572
573 result = {}
574 result['username'] = this.hash()(new Clipperz.ByteArray(someValues['username'] + someValues['password'])).toHexString().substring(2);
575 result['password'] = this.hash()(new Clipperz.ByteArray(someValues['password'] + someValues['username'])).toHexString().substring(2);
576
577 return result;
578 },
579
580 //-----------------------------------------------------------------------------
581
582 'hash': function() {
583 return Clipperz.PM.Crypto.encryptingFunctions.versions['0.2'].hash;
584 },
585
586 //-----------------------------------------------------------------------------
587 __syntaxFix__: "syntax fix"
588
589});
590
591Clipperz.PM.Connection.exception = {
592 WrongChecksum: new MochiKit.Base.NamedError("Clipperz.ByteArray.exception.InvalidValue"),
593 UnexpectedRequest:new MochiKit.Base.NamedError("Clipperz.ByteArray.exception.UnexpectedRequest")
594};
595
596
597Clipperz.PM.Connection.communicationProtocol = {
598 'currentVersion': '0.2',
599 'versions': {
600 '0.1': Clipperz.PM.Connection.SRP['1.0'],//Clipperz.Crypto.SRP.versions['1.0'].Connection,
601 '0.2': Clipperz.PM.Connection.SRP['1.1']//Clipperz.Crypto.SRP.versions['1.1'].Connection
602 },
603 'fallbackVersions': {
604 // 'current':'0.1',
605 '0.2': '0.1',
606 '0.1': null
607 }
608};
609
610MochiKit.Base.update(Clipperz.PM.Connection.communicationProtocol.versions, {
611 'current': Clipperz.PM.Connection.communicationProtocol.versions[Clipperz.PM.Connection.communicationProtocol.currentVersion]
612});
613
614MochiKit.Base.update(Clipperz.PM.Connection.communicationProtocol.fallbackVersions, {
615 'current': Clipperz.PM.Connection.communicationProtocol.fallbackVersions[Clipperz.PM.Connection.communicationProtocol.currentVersion]
616});
617
618
619