// callback to destroy the connection right now, it would crash and burn.
setImmediate(function() {
var err = new Error('TLS session renegotiation attack detected.');
- self._tlsError(err);
+ self._emitTLSError(err);
});
}
}
// Proxy for API compatibility
this.ssl = this._handle;
- this.on('error', this._tlsError);
+ this.on('error', this._emitTLSError);
this._init(socket, wrap);
// Destroy socket if error happened before handshake's finish
if (!self._secureEstablished) {
- self._tlsError(err);
- self.destroy();
+ self.destroy(self._tlsError(err));
} else if (options.isServer &&
rejectUnauthorized &&
/peer did not return a certificate/.test(err.message)) {
self.destroy();
} else {
// Throw error
- self._tlsError(err);
+ self._emitTLSError(err);
}
};
// Assume `tls.connect()`
if (wrap) {
wrap.on('error', function(err) {
- self._tlsError(err);
+ self._emitTLSError(err);
});
} else {
assert(!socket);
};
TLSSocket.prototype._handleTimeout = function() {
- this._tlsError(new Error('TLS handshake timeout'));
+ this._emitTLSError(new Error('TLS handshake timeout'));
+};
+
+TLSSocket.prototype._emitTLSError = function(err) {
+ var e = this._tlsError(err);
+ if (e)
+ this.emit('error', e);
};
TLSSocket.prototype._tlsError = function(err) {
this.emit('_tlsError', err);
if (this._controlReleased)
- this.emit('error', err);
+ return err;
+ return null;
};
TLSSocket.prototype._releaseControl = function() {
if (this._controlReleased)
return false;
this._controlReleased = true;
- this.removeListener('error', this._tlsError);
+ this.removeListener('error', this._emitTLSError);
return true;
};
});
var errorEmitted = false;
- socket.on('close', function() {
+ socket.on('close', function(err) {
+ // Closed because of error - no need to emit it twice
+ if (err)
+ return;
+
// Emit ECONNRESET
if (!socket._controlReleased && !errorEmitted) {
errorEmitted = true;
socket.authorizationError = verifyError.code || verifyError.message;
if (options.rejectUnauthorized) {
- socket.emit('error', verifyError);
- socket.destroy();
+ socket.destroy(verifyError);
return;
} else {
socket.emit('secureConnect');
socket._hadError = true;
var error = new Error('socket hang up');
error.code = 'ECONNRESET';
- socket.destroy();
- socket.emit('error', error);
+ socket.destroy(error);
}
}
socket.once('end', onHangUp);
--- /dev/null
+'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')
+}, function(c) {
+}).listen(common.PORT, function() {
+ var c = tls.connect(common.PORT, function() {
+ assert(false, 'should not be called');
+ });
+
+ c.on('error', function(err) {
+ errorCount++;
+ });
+
+ c.on('close', function(err) {
+ if (err)
+ closeCount++;
+
+ server.close();
+ });
+});
+
+process.on('exit', function() {
+ assert.equal(errorCount, 1);
+ assert.equal(closeCount, 1);
+});