Skip to content

Commit 23e5bcd

Browse files
refactor: use tls.connect instead of using tls.TLSSocket directly
This ensures we actually always perform a proper tls connection setup - and that errors are handled correctly.
1 parent f49208c commit 23e5bcd

File tree

1 file changed

+23
-43
lines changed

1 file changed

+23
-43
lines changed

src/message-io.js

+23-43
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,8 @@ module.exports = class MessageIO extends EventEmitter {
5959
this._packetSize = _packetSize;
6060
this.debug = debug;
6161

62+
this.tlsNegotiationComplete = false;
63+
6264
this.packetStream = new ReadablePacketStream();
6365
this.packetStream.on('data', (packet) => {
6466
this.logPacket('Received', packet);
@@ -84,47 +86,36 @@ module.exports = class MessageIO extends EventEmitter {
8486
startTls(credentialsDetails, hostname, trustServerCertificate) {
8587
const credentials = tls.createSecureContext ? tls.createSecureContext(credentialsDetails) : crypto.createCredentials(credentialsDetails);
8688

87-
this.securePair = this.createSecurePair(credentials);
88-
this.tlsNegotiationComplete = false;
89-
90-
this.securePair.cleartext.on('secure', () => {
91-
const cipher = this.securePair.cleartext.getCipher();
92-
93-
if (!trustServerCertificate) {
94-
let verifyError = this.securePair.ssl.verifyError();
95-
96-
// Verify that server's identity matches it's certificate's names
97-
if (!verifyError) {
98-
verifyError = tls.checkServerIdentity(hostname, this.securePair.cleartext.getPeerCertificate());
99-
}
89+
const duplexpair = new DuplexPair();
90+
const securePair = this.securePair = {
91+
cleartext: tls.connect({
92+
socket: duplexpair.socket1,
93+
secureContext: credentials,
94+
rejectUnauthorized: !trustServerCertificate
95+
}),
96+
encrypted: duplexpair.socket2
97+
};
10098

101-
if (verifyError) {
102-
this.securePair.destroy();
103-
this.socket.destroy(verifyError);
104-
return;
105-
}
99+
// If an error happens in the TLS layer, there is nothing we can do about it.
100+
// Forward the error to the socket so the connection gets properly cleaned up.
101+
securePair.cleartext.on('error', (err) => {
102+
// Streams in node.js versions before 8.0.0 don't support `.destroy`
103+
if (typeof securePair.encrypted.destroy === 'function') {
104+
securePair.encrypted.destroy();
106105
}
106+
this.socket.destroy(err);
107+
});
107108

109+
securePair.cleartext.on('secureConnect', () => {
110+
const cipher = securePair.cleartext.getCipher();
108111
this.debug.log('TLS negotiated (' + cipher.name + ', ' + cipher.version + ')');
109-
this.emit('secure', this.securePair.cleartext);
112+
this.emit('secure', securePair.cleartext);
110113
this.encryptAllFutureTraffic();
111114
});
112115

113-
this.securePair.encrypted.on('data', (data) => {
116+
securePair.encrypted.on('data', (data) => {
114117
this.sendMessage(TYPE.PRELOGIN, data);
115118
});
116-
117-
// If an error happens in the TLS layer, there is nothing we can do about it.
118-
// Forward the error to the socket so the connection gets properly cleaned up.
119-
this.securePair.cleartext.on('error', (err) => {
120-
this.socket.destroy(err);
121-
});
122-
123-
// On Node >= 0.12, the encrypted stream automatically starts spewing out
124-
// data once we attach a `data` listener. But on Node <= 0.10.x, this is not
125-
// the case. We need to kick the cleartext stream once to get the
126-
// encrypted end of the secure pair to emit the TLS handshake data.
127-
this.securePair.cleartext.write('');
128119
}
129120

130121
encryptAllFutureTraffic() {
@@ -195,15 +186,4 @@ module.exports = class MessageIO extends EventEmitter {
195186
resume() {
196187
this.packetStream.resume();
197188
}
198-
199-
createSecurePair(credentials) {
200-
const duplexpair = new DuplexPair();
201-
return {
202-
cleartext: new tls.TLSSocket(duplexpair.socket1, {
203-
secureContext: credentials,
204-
rejectUnauthorized: false
205-
}),
206-
encrypted: duplexpair.socket2
207-
};
208-
}
209189
};

0 commit comments

Comments
 (0)