Skip to content

Commit

Permalink
Fixes #104
Browse files Browse the repository at this point in the history
Add known good list of ciphers for Riak SSL and Erlang R16
  • Loading branch information
Luke Bakken committed Jan 16, 2016
1 parent d70bf50 commit fc8b4b2
Show file tree
Hide file tree
Showing 7 changed files with 72 additions and 55 deletions.
4 changes: 2 additions & 2 deletions benchmarks/kv.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ function kv(deferred, useCork) {

var f_callback = function(err, resp) {
if (err) {
logger.error("[benchmarks/kv] %s", err);
logger.error('[benchmarks/kv]', err);
throw new Error(err);
} else {
var robj = resp.values.shift();
Expand All @@ -67,7 +67,7 @@ function kv(deferred, useCork) {

var s_callback = function(err, resp) {
if (err) {
logger.error("[benchmarks/kv] %s", err);
logger.error('[benchmarks/kv]', err);
throw new Error(err);
} else {
var fetch = new Riak.Commands.KV.FetchValue.Builder()
Expand Down
4 changes: 3 additions & 1 deletion lib/core/authreq.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@ var logger = require('winston');
* @extends CommandBase
*/
function AuthReq(options, callback) {
CommandBase.call(this, 'RpbAuthReq', 'RpbAuthResp', callback);
CommandBase.call(this, 'RpbAuthReq', 'RpbAuthResp', function () {
logger.debug('[AuthReq] callback');
});
this.validateOptions(options, schema);
this.user = this.options.user;
this.password = this.options.password;
Expand Down
54 changes: 30 additions & 24 deletions lib/core/riakconnection.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@ var DEFAULT_MAX_BUFFER = 2048 * 1024;
var DEFAULT_INIT_BUFFER = 2 * 1024;
var DEFAULT_CONNECTION_TIMEOUT = 30000;

// NB: fixes GH 104
// https://github.com/basho/riak-nodejs-client/issues/104
// TODO FUTURE: remove this when Riak uses Erlang R17 or higher.
var RIAK_R16_CIPHERS = 'DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:AES128-SHA256:AES128-SHA:AES256-SHA256:AES256-SHA:RC4-SHA';

/**
* @module Core
*/
Expand All @@ -39,6 +44,7 @@ function RiakConnection(options) {

if (options.auth) {
this.auth = options.auth;
this.auth.ciphers = RIAK_R16_CIPHERS;
}

if (options.healthCheck) {
Expand Down Expand Up @@ -74,10 +80,10 @@ function RiakConnection(options) {
// this._connection.setMaxListeners(1);

if (this.cork && !this._connection.cork) {
logger.warn("[RiakConnection] wanted to use cork/uncork but not supported!");
logger.warn('[RiakConnection] wanted to use cork/uncork but not supported!');
this.cork = false;
} else {
logger.debug("[RiakConnection] using cork() / uncork()");
logger.debug('[RiakConnection] using cork() / uncork()');
}
}

Expand All @@ -92,8 +98,8 @@ RiakConnection.prototype.connect = function() {
};

RiakConnection.prototype._connected = function() {
logger.debug("[RiakConnection] connected - host: " + this.remoteAddress +
" port: " + this.remotePort);
logger.debug('[RiakConnection] (%s:%d) connected',
this.remoteAddress, this.remotePort);

this._connection.removeListener('error', this._boundConnectionError);
this._connection.on('error', this._socketError.bind(this));
Expand All @@ -113,40 +119,42 @@ RiakConnection.prototype._connected = function() {
this.execute(this.healthCheck);
} else {
this._connection.on('data', this._receiveData.bind(this));
this._connection.setTimeout(0);
this._connection.setTimeout(0); // NB: set to zero to disable idle timeout
logger.debug('[RiakConnection] emit connected, no-auth');
this.emit('connected', this);
}
};

RiakConnection.prototype._connectionError = function(err) {
// Connection error, emit to listener
logger.error("[RiakConnection] Failed to connect: " +
this.remoteAddress +
" port: " + this.remotePort +
" error: " + err);
if (err) {
logger.error('[RiakConnection] (%s:%d)', this.remoteAddress, this.remotePort, err);
}
this._connection.destroy();
this.emit('connectFailed', this, err);
};

RiakConnection.prototype._connectionTimeout = function() {
this._connectionError('RiakConnection Timed out trying to connect');
RiakConnection.prototype._connectionTimeout = function(err) {
if (!err) {
err = 'timed out or other error trying to connect';
}
this._connectionError(err);
};

RiakConnection.prototype._socketError = function(err) {
// This is only called if we have an error after a successful connection
// log only because close will be called right after
logger.error("[RiakConnection] Socket error; " + err);
if (err) {
logger.error('[RiakConnection] (%s:%d)', this.remoteAddress, this.remotePort, err);
}
};

RiakConnection.prototype._receiveHealthCheck = function(data) {
logger.debug('[RiakConnection]: receive healthcheck response');

if (this._ensureExpectedResponse(data, this.healthCheck.PbResponseName)) {
// On data, use the _receiveData function
this._connection.removeListener('data', this._boundReceiveHealthCheck);
this._connection.on('data', this._receiveData.bind(this));
this._connection.setTimeout(0);
this._connection.setTimeout(0); // NB: set to zero to disable idle timeout

this.inFlight = false;

Expand All @@ -156,10 +164,9 @@ RiakConnection.prototype._receiveHealthCheck = function(data) {
};

RiakConnection.prototype._receiveStartTls = function(data) {
logger.debug("[RiakConnection]: receive StartTls response");
logger.debug('[RiakConnection]: receive StartTls response');

if (this._ensureExpectedResponse(data, 'RpbStartTls')) {

var tls_secure_context = tls.createSecureContext(this.auth);
var tls_socket_options = {
isServer: false, // NB: required
Expand All @@ -180,19 +187,19 @@ RiakConnection.prototype._receiveStartTls = function(data) {

// Execute AuthReq command
this.inFlight = false;
var command = new AuthReq(auth_options, function(){});
var command = new AuthReq(auth_options);
this.execute(command);
}
};

RiakConnection.prototype._receiveAuthResp = function(data) {
if (this._ensureExpectedResponse(data, 'RpbAuthResp')) {
logger.debug('[RiakConnection]: receive RpbAuthResp');

if (this._ensureExpectedResponse(data, 'RpbAuthResp')) {
// On data, use the _receiveData function
this._connection.removeListener('data', this._boundReceiveAuthResp);
this._connection.on('data', this._receiveData.bind(this));
this._connection.setTimeout(0);

this._connection.setTimeout(0); // NB: set to zero to disable idle timeout
this.inFlight = false;

logger.debug('[RiakConnection] emit connected, with-auth');
Expand All @@ -215,7 +222,6 @@ RiakConnection.prototype._ensureExpectedResponse = function(data, msgName) {
if (protobufArray.length === 0) {
err = 'Expected ' + msgName + ' response message';
} else {

var resp = protobufArray[0];
var code = RiakProtoBuf.getCodeFor(msgName);

Expand Down Expand Up @@ -322,11 +328,11 @@ RiakConnection.prototype.execute = function(command) {
this.command = command;

if (this.inFlight === true) {
logger.error("[RiakConnection] attempted to run command on in-use connection");
logger.error('[RiakConnection] attempted to run command on in-use connection');
return false;
}

logger.debug("[RiakConnection] execute command: " + command.PbRequestName);
logger.debug('[RiakConnection] execute command:', command.PbRequestName);
this.inFlight = true;
this.lastUsed = Date.now();
// write PB to socket
Expand Down
3 changes: 1 addition & 2 deletions lib/core/riaknode.js
Original file line number Diff line number Diff line change
Expand Up @@ -113,9 +113,8 @@ RiakNode.prototype.start = function(callback) {
var self = this;
async.parallel(funcs, function (err, rslts) {
if (err) {
var msg = util.format('[RiakNode] node (%s:%d:%d) error during start: %s',
logger.error('[RiakNode] node (%s:%d:%d) error during start:',
self.remoteAddress, self.remotePort, self.executeCount, err);
logger.error(msg);
}

self._expireTimer = setInterval(function() {
Expand Down
13 changes: 6 additions & 7 deletions lib/core/starttls.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
var CommandBase = require('../commands/commandbase');
var inherits = require('util').inherits;
var Joi = require('joi');
var logger = require('winston');

/**
* @module Core
Expand All @@ -15,9 +16,10 @@ var Joi = require('joi');
* @param {Function} callback the function to call when the command completes or errors
* @extends CommandBase
*/
function StartTls(callback) {
CommandBase.call(this, 'RpbStartTls', 'RpbStartTls', callback);

function StartTls() {
CommandBase.call(this, 'RpbStartTls', 'RpbStartTls', function () {
logger.debug('[StartTls] callback');
});
}

inherits(StartTls, CommandBase);
Expand All @@ -30,13 +32,10 @@ StartTls.prototype.constructPbRequest = function() {
};

StartTls.prototype.onSuccess = function(rpbStartTlsResp) {

if (rpbStartTlsResp === null) {
// TODO ERROR
logger.error('[StartTls] unexpected: no response message!');
}

return true;
};

module.exports = StartTls;

45 changes: 28 additions & 17 deletions test/security/security.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,16 @@ var Test = require('../integration/testparams');
var RiakConnection = require('../../lib/core/riakconnection');
var assert = require('assert');
var fs = require('fs');
var logger = require('winston');

describe('RiakConnection - Integration', function() {

describe('#connect-tls-clientcert', function() {
this.timeout(10000);
this.timeout(10000);
describe('connect-tls-clientcert', function() {
it('should emit on connection success', function(done) {

var conn = new RiakConnection({
remoteAddress : Test.riakHost,
remotePort : Test.riakPort,
connectionTimeout : 30000,
connectionTimeout : 500,
auth: {
// Use the following when the private key and public cert
// are in two file
Expand All @@ -31,28 +30,34 @@ describe('RiakConnection - Integration', function() {
var errTimeout = setTimeout(function () {
assert(false, 'Event never fired');
done();
}, 5000);
}, 1000);

conn.on('connected', function() {
assert(true);
function cleanup() {
clearTimeout(errTimeout);
conn.removeAllListeners();
conn.close();
done();
}

conn.on('connectFailed', function (c, err) {
assert(!err, err);
cleanup();
});

conn.on('connected', function (c) {
cleanup();
});

conn.connect();
});
});

describe('#connect-tls-password', function() {
this.timeout(10000);
describe('connect-tls-password', function() {
it('should emit on connection success', function(done) {

var conn = new RiakConnection({
remoteAddress : Test.riakHost,
remotePort : Test.riakPort,
connectionTimeout : 5000,
connectionTimeout : 500,
auth: {
user: 'riakpass',
password: 'Test1234',
Expand All @@ -64,19 +69,25 @@ describe('RiakConnection - Integration', function() {
var errTimeout = setTimeout(function () {
assert(false, 'Event never fired');
done();
}, 9500);
}, 1000);

conn.on('connected', function() {
assert(true);
function cleanup() {
clearTimeout(errTimeout);
conn.removeAllListeners();
conn.close();
done();
}

conn.on('connectFailed', function (c, err) {
assert(!err, err);
cleanup();
});

conn.on('connected', function() {
cleanup();
});

conn.connect();
});
});

});

4 changes: 2 additions & 2 deletions test/unit/commandbase.js
Original file line number Diff line number Diff line change
Expand Up @@ -384,7 +384,7 @@ describe('CommandBase', function() {
var cmd = eval(eval_str); // jshint ignore:line
} catch (e) {
if (e.message !== '"callback" is not allowed') {
logger.error("%s ctor threw: %s", cmd_name, e.message);
logger.error('%s ctor threw:', cmd_name, e);
throw e;
}
}
Expand All @@ -409,7 +409,7 @@ describe('CommandBase', function() {
try {
cmd = builder.build();
} catch (e) {
logger.error("%s builder.build() threw: %s", cmd_name, e.message);
logger.error('%s builder.build() threw:', cmd_name, e);
throw e;
}
assert(cmd.callback == cb);
Expand Down

0 comments on commit fc8b4b2

Please sign in to comment.