Skip to content

Commit d4097fc

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 d4097fc

File tree

1 file changed

+21
-44
lines changed

1 file changed

+21
-44
lines changed

src/message-io.js

+21-44
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,33 @@ 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-
}
106-
}
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+
securePair.encrypted.destroy();
103+
this.socket.destroy(err);
104+
});
107105

106+
securePair.cleartext.on('secureConnect', () => {
107+
const cipher = securePair.cleartext.getCipher();
108108
this.debug.log('TLS negotiated (' + cipher.name + ', ' + cipher.version + ')');
109-
this.emit('secure', this.securePair.cleartext);
109+
this.emit('secure', securePair.cleartext);
110110
this.encryptAllFutureTraffic();
111111
});
112112

113-
this.securePair.encrypted.on('data', (data) => {
113+
securePair.encrypted.on('data', (data) => {
114114
this.sendMessage(TYPE.PRELOGIN, data);
115115
});
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('');
128116
}
129117

130118
encryptAllFutureTraffic() {
@@ -195,15 +183,4 @@ module.exports = class MessageIO extends EventEmitter {
195183
resume() {
196184
this.packetStream.resume();
197185
}
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-
}
209186
};

0 commit comments

Comments
 (0)