1
1
const tls = require ( 'tls' ) ;
2
2
const crypto = require ( 'crypto' ) ;
3
+ const DuplexPair = require ( 'native-duplexpair' ) ;
3
4
const EventEmitter = require ( 'events' ) . EventEmitter ;
4
5
const Transform = require ( 'readable-stream' ) . Transform ;
5
6
@@ -58,6 +59,8 @@ module.exports = class MessageIO extends EventEmitter {
58
59
this . _packetSize = _packetSize ;
59
60
this . debug = debug ;
60
61
62
+ this . tlsNegotiationComplete = false ;
63
+
61
64
this . packetStream = new ReadablePacketStream ( ) ;
62
65
this . packetStream . on ( 'data' , ( packet ) => {
63
66
this . logPacket ( 'Received' , packet ) ;
@@ -83,47 +86,37 @@ module.exports = class MessageIO extends EventEmitter {
83
86
startTls ( credentialsDetails , hostname , trustServerCertificate ) {
84
87
const credentials = tls . createSecureContext ? tls . createSecureContext ( credentialsDetails ) : crypto . createCredentials ( credentialsDetails ) ;
85
88
86
- this . securePair = tls . createSecurePair ( credentials ) ;
87
- this . tlsNegotiationComplete = false ;
88
-
89
- this . securePair . on ( 'secure' , ( ) => {
90
- const cipher = this . securePair . cleartext . getCipher ( ) ;
89
+ const duplexpair = new DuplexPair ( ) ;
90
+ const securePair = this . securePair = {
91
+ cleartext : tls . connect ( {
92
+ socket : duplexpair . socket1 ,
93
+ servername : hostname ,
94
+ secureContext : credentials ,
95
+ rejectUnauthorized : ! trustServerCertificate
96
+ } ) ,
97
+ encrypted : duplexpair . socket2
98
+ } ;
91
99
92
- if ( ! trustServerCertificate ) {
93
- let verifyError = this . securePair . ssl . verifyError ( ) ;
94
-
95
- // Verify that server's identity matches it's certificate's names
96
- if ( ! verifyError ) {
97
- verifyError = tls . checkServerIdentity ( hostname , this . securePair . cleartext . getPeerCertificate ( ) ) ;
98
- }
99
-
100
- if ( verifyError ) {
101
- this . securePair . destroy ( ) ;
102
- this . socket . destroy ( verifyError ) ;
103
- return ;
104
- }
100
+ // If an error happens in the TLS layer, there is nothing we can do about it.
101
+ // Forward the error to the socket so the connection gets properly cleaned up.
102
+ securePair . cleartext . on ( 'error' , ( err ) => {
103
+ // Streams in node.js versions before 8.0.0 don't support `.destroy`
104
+ if ( typeof securePair . encrypted . destroy === 'function' ) {
105
+ securePair . encrypted . destroy ( ) ;
105
106
}
107
+ this . socket . destroy ( err ) ;
108
+ } ) ;
106
109
110
+ securePair . cleartext . on ( 'secureConnect' , ( ) => {
111
+ const cipher = securePair . cleartext . getCipher ( ) ;
107
112
this . debug . log ( 'TLS negotiated (' + cipher . name + ', ' + cipher . version + ')' ) ;
108
- this . emit ( 'secure' , this . securePair . cleartext ) ;
113
+ this . emit ( 'secure' , securePair . cleartext ) ;
109
114
this . encryptAllFutureTraffic ( ) ;
110
115
} ) ;
111
116
112
- this . securePair . encrypted . on ( 'data' , ( data ) => {
117
+ securePair . encrypted . on ( 'data' , ( data ) => {
113
118
this . sendMessage ( TYPE . PRELOGIN , data ) ;
114
119
} ) ;
115
-
116
- // If an error happens in the TLS layer, there is nothing we can do about it.
117
- // Forward the error to the socket so the connection gets properly cleaned up.
118
- this . securePair . cleartext . on ( 'error' , ( err ) => {
119
- this . socket . destroy ( err ) ;
120
- } ) ;
121
-
122
- // On Node >= 0.12, the encrypted stream automatically starts spewing out
123
- // data once we attach a `data` listener. But on Node <= 0.10.x, this is not
124
- // the case. We need to kick the cleartext stream once to get the
125
- // encrypted end of the secure pair to emit the TLS handshake data.
126
- this . securePair . cleartext . write ( '' ) ;
127
120
}
128
121
129
122
encryptAllFutureTraffic ( ) {
0 commit comments