Browse Source

Some TLS clean ups

v0.7.4-release
Ryan Dahl 14 years ago
parent
commit
0ec57ea34c
  1. 96
      lib/tls.js
  2. 9
      test/simple/test-tls-server-verify.js

96
lib/tls.js

@ -24,7 +24,10 @@ var SecureStream = null;
function SecurePair(credentials, isServer, requestCert, rejectUnauthorized) { function SecurePair(credentials, isServer, requestCert, rejectUnauthorized) {
if (!(this instanceof SecurePair)) { if (!(this instanceof SecurePair)) {
return new SecurePair(credentials, isServer, requestCert, rejectUnauthorized); return new SecurePair(credentials,
isServer,
requestCert,
rejectUnauthorized);
} }
var self = this; var self = this;
@ -183,6 +186,39 @@ exports.createSecurePair = function(credentials,
}; };
SecurePair.prototype._mover = function(reader, writer, checker) {
var bytesRead;
var pool;
var chunkBytes;
var chunk;
do {
bytesRead = 0;
chunkBytes = 0;
pool = new Buffer(4096); // alloc every time?
pool.used = 0;
do {
try {
chunkBytes = reader(pool,
pool.used + bytesRead,
pool.length - pool.used - bytesRead);
} catch (e) {
return this._error(e);
}
if (chunkBytes >= 0) {
bytesRead += chunkBytes;
}
} while ((chunkBytes > 0) && (pool.used + bytesRead < pool.length));
if (bytesRead > 0) {
chunk = pool.slice(0, bytesRead);
writer(chunk);
}
} while (bytesRead > 0 && checker());
};
/** /**
* Attempt to cycle OpenSSLs buffers in various directions. * Attempt to cycle OpenSSLs buffers in various directions.
* *
@ -221,7 +257,6 @@ SecurePair.prototype._cycle = function() {
var tmp; var tmp;
var bytesRead; var bytesRead;
var bytesWritten; var bytesWritten;
var chunkBytes;
var chunk = null; var chunk = null;
var pool = null; var pool = null;
@ -272,40 +307,10 @@ SecurePair.prototype._cycle = function() {
assert(rv === tmp.length); assert(rv === tmp.length);
} }
function mover(reader, writer, checker) { // Move decrypted, clear data out into the application.
var bytesRead;
var pool;
var chunkBytes;
do {
bytesRead = 0;
chunkBytes = 0;
pool = new Buffer(4096);
pool.used = 0;
do {
try {
chunkBytes = reader(pool,
pool.used + bytesRead,
pool.length - pool.used - bytesRead);
} catch (e) {
return self._error(e);
}
if (chunkBytes >= 0) {
bytesRead += chunkBytes;
}
} while ((chunkBytes > 0) && (pool.used + bytesRead < pool.length));
if (bytesRead > 0) {
chunk = pool.slice(0, bytesRead);
writer(chunk);
}
} while (checker(bytesRead));
}
// Move decryptoed, clear data out into the application.
// From the user's perspective this occurs as a 'data' event // From the user's perspective this occurs as a 'data' event
// on the pair.cleartext. // on the pair.cleartext.
mover( this._mover(
function(pool, offset, length) { function(pool, offset, length) {
debug('reading from clearOut'); debug('reading from clearOut');
return self._ssl.clearOut(pool, offset, length); return self._ssl.clearOut(pool, offset, length);
@ -313,8 +318,8 @@ SecurePair.prototype._cycle = function() {
function(chunk) { function(chunk) {
self.cleartext.emit('data', chunk); self.cleartext.emit('data', chunk);
}, },
function(bytesRead) { function() {
return bytesRead > 0 && self._cleartextWriteState === true; return self._cleartextWriteState === true;
}); });
// Move encrypted data to the stream. From the user's perspective this // Move encrypted data to the stream. From the user's perspective this
@ -325,7 +330,7 @@ SecurePair.prototype._cycle = function() {
// socket.write(d); // socket.write(d);
// }); // });
// //
mover( this._mover(
function(pool, offset, length) { function(pool, offset, length) {
debug('reading from encOut'); debug('reading from encOut');
if (!self._ssl) return -1; if (!self._ssl) return -1;
@ -334,13 +339,12 @@ SecurePair.prototype._cycle = function() {
function(chunk) { function(chunk) {
self.encrypted.emit('data', chunk); self.encrypted.emit('data', chunk);
}, },
function(bytesRead) { function() {
if (!self._ssl) return false; if (!self._ssl) return false;
return bytesRead > 0 && self._encryptedWriteState === true; return self._encryptedWriteState === true;
}); });
if (this._ssl && !this._secureEstablished && this._ssl.isInitFinished()) { if (this._ssl && !this._secureEstablished && this._ssl.isInitFinished()) {
this._secureEstablished = true; this._secureEstablished = true;
debug('secure established'); debug('secure established');
@ -359,6 +363,7 @@ SecurePair.prototype._destroy = function(err) {
this.cleartext.emit('close'); this.cleartext.emit('close');
this.emit('end', err); this.emit('end', err);
} }
this._cycle();
}; };
@ -498,7 +503,12 @@ function Server(/* [options], listener */) {
} else { } else {
var verifyError = pair._ssl.verifyError(); var verifyError = pair._ssl.verifyError();
if (verifyError) { if (verifyError) {
self.emit('unauthorized', pair.cleartext, verifyError); if (self.rejectUnauthorized) {
socket.destroy();
pair._destroy();
} else {
self.emit('unauthorized', pair.cleartext, verifyError);
}
} else { } else {
self.emit('authorized', pair.cleartext); self.emit('authorized', pair.cleartext);
} }
@ -506,12 +516,12 @@ function Server(/* [options], listener */) {
}); });
pair.on('error', function(e) { pair.on('error', function(e) {
console.log('pair got error: ' + e); console.error('pair got error: ' + e);
self.emit('error', e); self.emit('error', e);
}); });
pair.cleartext.on('error', function(err) { pair.cleartext.on('error', function(err) {
console.log('cleartext got error: ' + err); console.error('cleartext got error: ' + err);
}); });
pair.encrypted.on('error', function(err) { pair.encrypted.on('error', function(err) {

9
test/simple/test-tls-server-verify.js

@ -112,7 +112,7 @@ function runClient (options, cb) {
// To test use: openssl s_client -connect localhost:8000 // To test use: openssl s_client -connect localhost:8000
var client = spawn('openssl', args); var client = spawn('openssl', args);
//console.error(args); console.error(args);
var out = ''; var out = '';
@ -141,10 +141,13 @@ function runClient (options, cb) {
//client.stdout.pipe(process.stdout); //client.stdout.pipe(process.stdout);
client.on('exit', function(code) { client.on('exit', function(code) {
assert.equal(0, code);
if (options.shouldReject) { if (options.shouldReject) {
assert.equal(true, rejected); assert.equal(true, rejected, options.name +
" NOT rejected, but should have been");
} else { } else {
assert.equal(false, rejected); assert.equal(false, rejected, options.name +
" rejected, but should NOT have been");
assert.equal(options.shouldAuth, authed); assert.equal(options.shouldAuth, authed);
} }

Loading…
Cancel
Save