/* Copyright 2008-2015 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/. */ "use strict"; if (typeof(Clipperz) == 'undefined') { Clipperz = {}; } if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; } //----------------------------------------------------------------------------- // // Abstract C O N N E C T I O N class // //----------------------------------------------------------------------------- Clipperz.PM.Connection = function (args) { args = args || {}; this._proxy = args.proxy || Clipperz.PM.Proxy.defaultProxy; this._getCredentialsFunction = args.getCredentialsFunction; this._clipperz_pm_crypto_version = null; this._connectionId = null; this._sharedSecret = null; this._serverLockValue = null; return this; } Clipperz.PM.Connection.prototype = MochiKit.Base.update(null, { 'toString': function() { return "Connection [" + this.version() + "]"; }, //========================================================================= 'version': function() { throw Clipperz.Base.exception.AbstractMethod; }, 'clipperz_pm_crypto_version': function() { if (this._clipperz_pm_crypto_version == null) { var connectionVersions; var versions; var version; var i, c; version = null; connectionVersions = Clipperz.PM.Connection.communicationProtocol.versions; versions = MochiKit.Base.keys(connectionVersions); c = versions.length; for (i=0; i>> Connection.messageExceptionHandler: " + anError.message, anError); if (anError instanceof MochiKit.Async.CancelledError) { result = anError; } else { var errorPayload; errorPayload = Clipperz.Base.evalJSON(anError.req.responseText); if ((errorPayload.message == 'Trying to communicate without an active connection') || (errorPayload.message == 'No tollManager available for current session') || (errorPayload.message == 'HashCash verification failed. The provided toll is not valid.') ) { result = this.reestablishConnection(anOriginalMessageArguments); } else if (errorPayload.message == 'Session with stale data') { MochiKit.Signal.signal(this, 'EXCEPTION'); } else { result = errorPayload; } } Clipperz.log("<<< Connection.messageExceptionHandler") return result;; }, //========================================================================= 'uploadAttachment': function(someArguments, aProgressCallback) { return Clipperz.Async.callbacks("Connction.uploadAttachment", [ MochiKit.Base.method(this, 'message', 'echo', {'echo':"echo"}), MochiKit.Base.bind(function(){ return this.sharedSecret()}, this), MochiKit.Base.method(this.proxy(), 'uploadAttachment', someArguments, aProgressCallback/*, this.sharedSecret()*/), ], {trace:false}); }, 'downloadAttachment': function(someArguments, aProgressCallback) { return Clipperz.Async.callbacks("Connction.uploadAttachment", [ MochiKit.Base.method(this, 'message', 'echo', {'echo':"echo"}), MochiKit.Base.bind(function(){ return this.sharedSecret()}, this), MochiKit.Base.method(this.proxy(), 'downloadAttachment', someArguments, aProgressCallback/*, this.sharedSecret()*/), ], {trace:false}); }, //========================================================================= 'reestablishConnection': function(anOriginalMessageArguments) { var deferredResult; deferredResult = new Clipperz.Async.Deferred("Connection.reestablishConnection"); deferredResult.addMethod(this, 'reset'); deferredResult.addMethod(this, 'login', true); deferredResult.addCallback(MochiKit.Base.bind(function(aMessage) { aMessage['srpSharedSecret'] = this.sharedSecret(); return aMessage; }, this), anOriginalMessageArguments); deferredResult.addMethod(this, 'sendMessage'); deferredResult.addErrback(MochiKit.Signal.signal, this, 'EXCEPTION', null); deferredResult.callback(); return deferredResult; }, //========================================================================= 'serverSideUserCredentials': function(aUsername, aPassword) { var result; var newSrpConnection; var normalizedAttributes; normalizedAttributes = this.normalizedCredentials({username:aUsername, password:aPassword}); newSrpConnection = new Clipperz.Crypto.SRP.Connection({ C:normalizedAttributes['username'], P:normalizedAttributes['password'], hash:this.hash() }); result = newSrpConnection.serverSideCredentials(); result['version'] = this.clipperz_pm_crypto_version(); return result; }, //========================================================================= 'normalizedCredentials': function(someValues) { var result; result = {} result['username'] = this.hash()(new Clipperz.ByteArray(someValues['username'])).toHexString().substring(2); result['password'] = this.hash()(new Clipperz.ByteArray(someValues['password'] + someValues['username'])).toHexString().substring(2); return result; }, //----------------------------------------------------------------------------- 'hash': function() { return Clipperz.PM.Crypto.encryptingFunctions.versions['0.1'].hash; }, //----------------------------------------------------------------------------- __syntaxFix__: "syntax fix" }); //----------------------------------------------------------------------------- // // S R P [ 1 . 1 ] C O N N E C T I O N class // //----------------------------------------------------------------------------- Clipperz.PM.Connection.SRP['1.1'] = function (args) { Clipperz.PM.Connection.SRP['1.0'].call(this, args); return this; } Clipperz.PM.Connection.SRP['1.1'].prototype = MochiKit.Base.update(new Clipperz.PM.Connection.SRP['1.0'](), { 'version': function() { return '1.1'; }, //----------------------------------------------------------------------------- 'normalizedCredentials': function(someValues) { var result; result = {} result['username'] = this.hash()(new Clipperz.ByteArray(someValues['username'] + someValues['password'])).toHexString().substring(2); result['password'] = this.hash()(new Clipperz.ByteArray(someValues['password'] + someValues['username'])).toHexString().substring(2); return result; }, //----------------------------------------------------------------------------- 'hash': function() { return Clipperz.PM.Crypto.encryptingFunctions.versions['0.2'].hash; }, //----------------------------------------------------------------------------- __syntaxFix__: "syntax fix" }); Clipperz.PM.Connection.exception = { WrongChecksum: new MochiKit.Base.NamedError("Clipperz.ByteArray.exception.InvalidValue"), StaleData: new MochiKit.Base.NamedError("Stale data"), UnexpectedRequest: new MochiKit.Base.NamedError("Clipperz.ByteArray.exception.UnexpectedRequest") }; Clipperz.PM.Connection.communicationProtocol = { 'currentVersion': '0.2', 'versions': { '0.1': Clipperz.PM.Connection.SRP['1.0'], //Clipperz.Crypto.SRP.versions['1.0'].Connection, '0.2': Clipperz.PM.Connection.SRP['1.1'] //Clipperz.Crypto.SRP.versions['1.1'].Connection }, 'fallbackVersions': { // 'current': '0.1', '0.2': '0.1', '0.1': null } }; MochiKit.Base.update(Clipperz.PM.Connection.communicationProtocol.versions, { 'current': Clipperz.PM.Connection.communicationProtocol.versions[Clipperz.PM.Connection.communicationProtocol.currentVersion] }); MochiKit.Base.update(Clipperz.PM.Connection.communicationProtocol.fallbackVersions, { 'current': Clipperz.PM.Connection.communicationProtocol.fallbackVersions[Clipperz.PM.Connection.communicationProtocol.currentVersion] });