1
1
const tls = require ( 'tls' ) ;
2
2
const crypto = require ( 'crypto' ) ;
3
+ const net = require ( 'net' ) ;
3
4
const EventEmitter = require ( 'events' ) . EventEmitter ;
4
5
const Transform = require ( 'readable-stream' ) . Transform ;
5
6
@@ -50,6 +51,51 @@ class ReadablePacketStream extends Transform {
50
51
}
51
52
}
52
53
54
+ class TLSHandler extends EventEmitter {
55
+ constructor ( secureContext ) {
56
+ super ( ) ;
57
+ const self = this ;
58
+ self . server = net . createServer ( ) ;
59
+
60
+ self . server . listen ( 0 , '127.0.0.1' , ( ) => {
61
+ self . cleartext = tls . connect ( {
62
+ host : '127.0.0.1' ,
63
+ port : self . server . address ( ) . port ,
64
+ secureContext : secureContext ,
65
+ rejectUnauthorized : false
66
+ } ) ;
67
+ self . cleartext . on ( 'secureConnect' , ( ) => {
68
+ self . emit ( 'secure' ) ;
69
+ self . cleartext . write ( '' ) ;
70
+ } ) ;
71
+ } ) ;
72
+
73
+ const encryptedOnQueue = [ ] ;
74
+ self . encrypted = {
75
+ on : ( event , cb ) => {
76
+ encryptedOnQueue . push ( [ event , cb ] ) ;
77
+ }
78
+ } ;
79
+
80
+ self . server . on ( 'connection' , ( socket ) => {
81
+ self . encrypted = socket ;
82
+ encryptedOnQueue . forEach ( ( [ event , cb ] ) => {
83
+ self . encrypted . on ( event , cb ) ;
84
+ } ) ;
85
+ self . server . close ( ) ;
86
+ } ) ;
87
+ }
88
+
89
+ destroy ( ) {
90
+ if ( this . encrypted && this . encrypted . destroy ) {
91
+ this . encrypted . destroy ( ) ;
92
+ }
93
+ if ( this . cleartext && this . cleartext . destroy ) {
94
+ this . cleartext . destroy ( ) ;
95
+ }
96
+ }
97
+ }
98
+
53
99
module . exports = class MessageIO extends EventEmitter {
54
100
constructor ( socket , _packetSize , debug ) {
55
101
super ( ) ;
@@ -70,6 +116,10 @@ module.exports = class MessageIO extends EventEmitter {
70
116
71
117
this . socket . pipe ( this . packetStream ) ;
72
118
this . packetDataSize = this . _packetSize - packetHeaderLength ;
119
+
120
+ this . socket . on ( 'close' , ( ) => {
121
+ this . emit ( 'close' ) ;
122
+ } ) ;
73
123
}
74
124
75
125
packetSize ( packetSize ) {
@@ -84,54 +134,59 @@ module.exports = class MessageIO extends EventEmitter {
84
134
startTls ( credentialsDetails , hostname , trustServerCertificate ) {
85
135
const credentials = tls . createSecureContext ? tls . createSecureContext ( credentialsDetails ) : crypto . createCredentials ( credentialsDetails ) ;
86
136
87
- this . securePair = tls . createSecurePair ( credentials ) ;
137
+ this . tlsHandler = new TLSHandler ( credentials ) ;
138
+
88
139
this . tlsNegotiationComplete = false ;
89
140
90
- this . securePair . on ( 'secure' , ( ) => {
91
- const cipher = this . securePair . cleartext . getCipher ( ) ;
141
+ this . tlsHandler . on ( 'secure' , ( ) => {
142
+ const cipher = this . tlsHandler . cleartext . getCipher ( ) ;
92
143
93
144
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
- }
100
-
101
- if ( verifyError ) {
102
- this . securePair . destroy ( ) ;
103
- this . socket . destroy ( verifyError ) ;
145
+ if ( ! this . tlsHandler . cleartext . authorized ) {
146
+ this . tlsHandler . destroy ( ) ;
147
+ this . socket . destroy ( this . tlsHandler . cleartext . authorizationError ) ;
104
148
return ;
105
149
}
106
150
}
107
151
108
152
this . debug . log ( 'TLS negotiated (' + cipher . name + ', ' + cipher . version + ')' ) ;
109
- this . emit ( 'secure' , this . securePair . cleartext ) ;
153
+ this . emit ( 'secure' , this . tlsHandler . cleartext ) ;
110
154
this . encryptAllFutureTraffic ( ) ;
111
155
} ) ;
112
156
113
- this . securePair . encrypted . on ( 'data' , ( data ) => {
157
+ this . tlsHandler . encrypted . on ( 'data' , ( data ) => {
114
158
this . sendMessage ( TYPE . PRELOGIN , data ) ;
115
159
} ) ;
116
-
117
- // On Node >= 0.12, the encrypted stream automatically starts spewing out
118
- // data once we attach a `data` listener. But on Node <= 0.10.x, this is not
119
- // the case. We need to kick the cleartext stream once to get the
120
- // encrypted end of the secure pair to emit the TLS handshake data.
121
- this . securePair . cleartext . write ( '' ) ;
122
160
}
123
161
124
162
encryptAllFutureTraffic ( ) {
125
163
this . socket . unpipe ( this . packetStream ) ;
126
- this . securePair . encrypted . removeAllListeners ( 'data' ) ;
127
- this . socket . pipe ( this . securePair . encrypted ) ;
128
- this . securePair . encrypted . pipe ( this . socket ) ;
129
- this . securePair . cleartext . pipe ( this . packetStream ) ;
164
+ this . tlsHandler . encrypted . removeAllListeners ( 'data' ) ;
165
+ this . socket . pipe ( this . tlsHandler . encrypted ) ;
166
+ this . socket . removeAllListeners ( 'close' ) ;
167
+ this . socket . on ( 'close' , ( ) => {
168
+ this . tlsHandler . encrypted . end ( ) ;
169
+ } ) ;
170
+ this . socket . on ( 'error' , ( ) => {
171
+ this . tlsHandler . encrypted . end ( ) ;
172
+ } ) ;
173
+ this . tlsHandler . cleartext . on ( 'close' , ( ) => {
174
+ this . emit ( 'close' ) ;
175
+ } ) ;
176
+ this . tlsHandler . encrypted . pipe ( this . socket ) ;
177
+ this . tlsHandler . cleartext . pipe ( this . packetStream ) ;
130
178
this . tlsNegotiationComplete = true ;
179
+ if ( ! this . socket . destroyed ) {
180
+ // the old SecurePair worked synchronously and fired the
181
+ // 'secure' event before the packet was handled by
182
+ // RedablePacketStream. this is not the case anymore so
183
+ // emit 'message' manually to fire SENT_TLSSSLNEGOTIATION.message again
184
+ this . emit ( 'message' ) ;
185
+ }
131
186
}
132
187
133
188
tlsHandshakeData ( data ) {
134
- this . securePair . encrypted . write ( data ) ;
189
+ this . tlsHandler . encrypted . write ( data ) ;
135
190
}
136
191
137
192
// TODO listen for 'drain' event when socket.write returns false.
@@ -168,8 +223,8 @@ module.exports = class MessageIO extends EventEmitter {
168
223
169
224
sendPacket ( packet ) {
170
225
this . logPacket ( 'Sent' , packet ) ;
171
- if ( this . securePair && this . tlsNegotiationComplete ) {
172
- this . securePair . cleartext . write ( packet . buffer ) ;
226
+ if ( this . tlsHandler && this . tlsNegotiationComplete ) {
227
+ this . tlsHandler . cleartext . write ( packet . buffer ) ;
173
228
} else {
174
229
this . socket . write ( packet . buffer ) ;
175
230
}
0 commit comments