ServerSecureChannelLayer.prototype._process_certificates = function(message,callback) { var self = this; self.receiverPublicKey = null; self.receiverPublicKeyLength = 0; self.receiverCertificate = message.securityHeader ? message.securityHeader.senderCertificate : null; // ignore receiverCertificate that have a zero length /* istanbul ignore next */ if (self.receiverCertificate && self.receiverCertificate.length === 0) { self.receiverCertificate = null; } if (self.receiverCertificate) { // extract public key crypto_utils.extractPublicKeyFromCertificate(self.receiverCertificate,function (err, key) { if (!err) { self.receiverPublicKey = key; self.receiverPublicKeyLength = crypto_utils.rsa_length(key); } callback(err); }); } else { self.receiverPublicKey = null; callback(); } };
it("should extract a public key from a certificate", function (done) { var certificate = fs.readFileSync('certificates/client_cert_1024.pem').toString('ascii'); //xx console.log(" certificate"); var certificate2 = crypto_utils.readCertificate('certificates/client_cert_1024.pem'); //xx console.log(hexDump(certificate2)); var publickey2 = crypto_utils.readKey('certificates/client_public_key_1024.pub'); //xx console.log(hexDump(publickey2)); crypto_utils.extractPublicKeyFromCertificate(certificate2, function (err, publicKey) { var raw_public_key = crypto_utils.readPEM(publicKey); //xx console.log(hexDump(raw_public_key)); raw_public_key.toString("base64").should.eql(publickey2.toString("base64")); done(err); }); });
ClientSecureChannelLayer.prototype.create = function (endpoint_url, callback) { assert(_.isFunction(callback)); var self = this; if (self.securityMode !== MessageSecurityMode.NONE) { if (!crypto_utils.isFullySupported()) { return callback(new Error("Crypto is not fully supported")); } if (!self.serverCertificate) { return callback(new Error("invalid server certificate")); } // take the opportunity of this async method to perform some async pre-processing if (_.isUndefined(self.receiverPublicKey)) { crypto_utils.extractPublicKeyFromCertificate(self.serverCertificate, function (err, publicKey) { /* istanbul ignore next */ if (err) { return callback(err); } self.receiverPublicKey = publicKey; self.create(endpoint_url, callback); }); return undefined; } assert(typeof self.receiverPublicKey === "string"); } this.endpoint_url = endpoint_url; var transport = new ClientTCP_transport(); transport.protocolVersion = self.protocolVersion; transport.connect(endpoint_url, _on_connection.bind(this, transport, callback)); };
ClientSecureChannelLayer.prototype.create = function (endpoint_url, callback) { assert(_.isFunction(callback)); var self = this; if (self.securityMode !== MessageSecurityMode.NONE) { if (!crypto_utils.isFullySupported()) { return callback(new Error("ClientSecureChannelLayer#create : this version of node doesn't fully support crypto")); } if (!self.serverCertificate) { return callback(new Error("ClientSecureChannelLayer#create : expecting a server certificate when securityMode is not NONE")); } // take the opportunity of this async method to perform some async pre-processing if (_.isUndefined(self.receiverPublicKey)) { crypto_utils.extractPublicKeyFromCertificate(self.serverCertificate, function (err, publicKey) { /* istanbul ignore next */ if (err) { return callback(err); } self.receiverPublicKey = publicKey; assert(!_.isUndefined(self.receiverPublicKey)); // make sure we wont go into infinite recursion calling create again. self.create(endpoint_url, callback); }); return undefined; } assert(typeof self.receiverPublicKey === "string"); } self.endpoint_url = endpoint_url; var transport = new ClientTCP_transport(); transport.timeout = self.transportTimeout; transport.protocolVersion = self.protocolVersion; // ------------------------------------------------------------------------- // Handle reconnection // -------------------------------------------------------------------------- var _establish_connection = function (transport,endpoint_url,callback) { var backoff = require('backoff'); var last_err= null; function _connect(_i_callback) { if (self.__call && self.__call._cancelBackoff) { return; } transport.connect(endpoint_url, function (err) { // force Backoff to fail if err is not ECONNRESET or ECONNREFUSE // this mean that the connection to the server has succeeded but for some reason // the server has denied the connection // the cause could be: // - invalid protocol version specified by client // - server going to shutdown // - server too busy - // - server shielding itself from a DOS attack if (err) { last_err = err; if (true) { // connection cannot be establish ? if not, abort the backoff process if (err.message.match(/ECONNRESET/)) { debugLog(" Aborting backoff process prematuraly - err = ", err.message); self.__call.abort(); //xx call emit fail ( this line should be removed when new version of backoff will be posted) //xx self.__call.backoff_.emit("fail",err); //xx self.__call.failAfter(1); } else { debugLog(" backoff - keep trying - err = ", err.message); } } } _i_callback(err); }); } function _backoff_completion(err) { if (self.__call) { // console log = transport.numberOfRetry = transport.numberOfRetry || 0; transport.numberOfRetry += self.__call.getNumRetries(); self.__call.removeAllListeners(); self.__call = null; //console.log('xxx Num retries: ' + transport.numberOfRetry ); if (err) { //xx console.log('xxx Error: ' + err.message,last_err.message); callback(last_err); } else { callback(); } } } self.__call = backoff.call(_connect,_backoff_completion); self.__call._cancelBackoff = false; self.__call.failAfter(self.connectionStrategy.maxRetry); self.__call.on('backoff', function(number, delay) { debugLog(" Backoff #".bgWhite.cyan,number,"delay = ",delay); // Do something when backoff starts, e.g. show to the // user the delay before next reconnection attempt. /** * @event backoff */ self.emit("backoff",number,delay); }); self.__call.on('abort', function(err) { debugLog(" abort #".bgWhite.cyan," after ",self.__call.getNumRetries(), " retries"); // Do something when backoff starts, e.g. show to the // user the delay before next reconnection attempt. /** * @event backoff */ self.emit("abort"); setImmediate(function() { _backoff_completion(null,new Error("Connection abandoned")); }); }); self.__call.setStrategy(new backoff.ExponentialStrategy(self.connectionStrategy)); self.__call.start(); }; _establish_connection(transport,endpoint_url, _on_connection.bind(this, transport, callback)); };