Skip to content

Commit

Permalink
tls: emit errors happening before handshake finish
Browse files Browse the repository at this point in the history
This fixes a race condition introduced in 80342f6.
`socket.destroy(err)` only emits the passed error when
`socket._writableState.errorEmitted === false`, `ssl.onerror`
sets `errorEmitted = true` just before calling
`socket.destroy()`.

See: nodejs/node#1119
See: nodejs/node#1711
PR-URL: nodejs/node#1769
Reviewed-By: Fedor Indutny <fedor@indutny.com>
  • Loading branch information
skenqbx authored and andrewdeandrade committed Jun 3, 2015
1 parent 92b288a commit 43a77d4
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 1 deletion.
3 changes: 2 additions & 1 deletion lib/_tls_wrap.js
Original file line number Diff line number Diff line change
Expand Up @@ -359,7 +359,6 @@ TLSSocket.prototype._init = function(socket, wrap) {
ssl.onerror = function(err) {
if (self._writableState.errorEmitted)
return;
self._writableState.errorEmitted = true;

// Destroy socket if error happened before handshake's finish
if (!self._secureEstablished) {
Expand All @@ -373,6 +372,8 @@ TLSSocket.prototype._init = function(socket, wrap) {
// Throw error
self._emitTLSError(err);
}

self._writableState.errorEmitted = true;
};

// If custom SNICallback was given, or if
Expand Down
46 changes: 46 additions & 0 deletions test/parallel/test-tls-handshake-error.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
'use strict';

var assert = require('assert');
var common = require('../common');

if (!common.hasCrypto) {
console.log('1..0 # Skipped: missing crypto');
process.exit();
}
var tls = require('tls');

var fs = require('fs');
var net = require('net');

var errorCount = 0;
var closeCount = 0;

var server = tls.createServer({
key: fs.readFileSync(common.fixturesDir + '/keys/agent1-key.pem'),
cert: fs.readFileSync(common.fixturesDir + '/keys/agent1-cert.pem'),
rejectUnauthorized: true
}, function(c) {
}).listen(common.PORT, function() {
var c = tls.connect({
port: common.PORT,
ciphers: 'RC4'
}, function() {
assert(false, 'should not be called');
});

c.on('error', function(err) {
errorCount++;
assert.notEqual(err.code, 'ECONNRESET');
});

c.on('close', function(err) {
if (err)
closeCount++;
server.close();
});
});

process.on('exit', function() {
assert.equal(errorCount, 1);
assert.equal(closeCount, 1);
});

0 comments on commit 43a77d4

Please sign in to comment.