@@ -123,14 +123,14 @@ const TrustStrategy = {
123
123
return ;
124
124
}
125
125
126
- let tlsOpts = {
126
+ const tlsOpts = {
127
127
ca : config . trustedCertificates . map ( ( f ) => fs . readFileSync ( f ) ) ,
128
128
// Because we manually check for this in the connect callback, to give
129
129
// a more helpful error to the user
130
130
rejectUnauthorized : false
131
131
} ;
132
132
133
- let socket = tls . connect ( config . port , config . host , tlsOpts , function ( ) {
133
+ const connectListener = socket => {
134
134
if ( ! socket . authorized ) {
135
135
onFailure ( newError ( "Server certificate is not trusted. If you trust the database you are connecting to, add" +
136
136
" the signing certificate, or the server certificate, to the list of certificates trusted by this driver" +
@@ -141,18 +141,19 @@ const TrustStrategy = {
141
141
} else {
142
142
onSuccess ( ) ;
143
143
}
144
- } ) ;
145
- socket . on ( 'error' , onFailure ) ;
146
- return socket ;
144
+ } ;
145
+
146
+ return connectTlsSocket ( config , tlsOpts , connectListener , onFailure ) ;
147
147
} ,
148
148
TRUST_SYSTEM_CA_SIGNED_CERTIFICATES : function ( config , onSuccess , onFailure ) {
149
149
150
- let tlsOpts = {
150
+ const tlsOpts = {
151
151
// Because we manually check for this in the connect callback, to give
152
152
// a more helpful error to the user
153
153
rejectUnauthorized : false
154
154
} ;
155
- let socket = tls . connect ( config . port , config . host , tlsOpts , function ( ) {
155
+
156
+ const connectListener = socket => {
156
157
if ( ! socket . authorized ) {
157
158
onFailure ( newError ( "Server certificate is not trusted. If you trust the database you are connecting to, use " +
158
159
"TRUST_CUSTOM_CA_SIGNED_CERTIFICATES and add" +
@@ -164,9 +165,9 @@ const TrustStrategy = {
164
165
} else {
165
166
onSuccess ( ) ;
166
167
}
167
- } ) ;
168
- socket . on ( 'error' , onFailure ) ;
169
- return socket ;
168
+ } ;
169
+
170
+ return connectTlsSocket ( config , tlsOpts , connectListener , onFailure ) ;
170
171
} ,
171
172
/**
172
173
* @deprecated in 1.1 in favour of {@link #TRUST_ALL_CERTIFICATES}. Will be deleted in a future version.
@@ -175,15 +176,15 @@ const TrustStrategy = {
175
176
console . log ( "`TRUST_ON_FIRST_USE` has been deprecated as option and will be removed in a future version of " +
176
177
"the driver. Please use `TRUST_ALL_CERTIFICATES` instead." ) ;
177
178
178
- let tlsOpts = {
179
+ const tlsOpts = {
179
180
// Because we manually verify the certificate against known_hosts
180
181
rejectUnauthorized : false
181
182
} ;
182
183
183
- let socket = tls . connect ( config . port , config . host , tlsOpts , function ( ) {
184
- var serverCert = socket . getPeerCertificate ( /*raw=*/ true ) ;
184
+ const connectListener = socket => {
185
+ const serverCert = socket . getPeerCertificate ( /*raw=*/ true ) ;
185
186
186
- if ( ! serverCert . raw ) {
187
+ if ( ! serverCert . raw ) {
187
188
// If `raw` is not available, we're on an old version of NodeJS, and
188
189
// the raw cert cannot be accessed (or, at least I couldn't find a way to)
189
190
// therefore, we can't generate a SHA512 fingerprint, meaning we can't
@@ -200,10 +201,10 @@ const TrustStrategy = {
200
201
const serverId = config . host + ":" + config . port ;
201
202
202
203
loadFingerprint ( serverId , knownHostsPath , ( knownFingerprint ) => {
203
- if ( knownFingerprint === serverFingerprint ) {
204
+ if ( knownFingerprint === serverFingerprint ) {
204
205
onSuccess ( ) ;
205
- } else if ( knownFingerprint == null ) {
206
- storeFingerprint ( serverId , knownHostsPath , serverFingerprint , ( err ) => {
206
+ } else if ( knownFingerprint == null ) {
207
+ storeFingerprint ( serverId , knownHostsPath , serverFingerprint , ( err ) => {
207
208
if ( err ) {
208
209
return onFailure ( err ) ;
209
210
}
@@ -220,32 +221,33 @@ const TrustStrategy = {
220
221
"update the file with the new certificate. You can configure which file the driver " +
221
222
"should use to store this information by setting `knownHosts` to another path in " +
222
223
"your driver configuration - and you can disable encryption there as well using " +
223
- "`encrypted:\"" + ENCRYPTION_OFF + "\"`." ) )
224
+ "`encrypted:\"" + ENCRYPTION_OFF + "\"`." ) ) ;
224
225
}
225
226
} ) ;
226
- } ) ;
227
- socket . on ( 'error' , onFailure ) ;
228
- return socket ;
227
+ } ;
228
+
229
+ return connectTlsSocket ( config , tlsOpts , connectListener , onFailure ) ;
229
230
} ,
230
231
231
232
TRUST_ALL_CERTIFICATES : function ( config , onSuccess , onFailure ) {
232
233
const tlsOpts = {
233
234
rejectUnauthorized : false
234
235
} ;
235
- const socket = tls . connect ( config . port , config . host , tlsOpts , function ( ) {
236
+
237
+ const connectListener = socket => {
236
238
const certificate = socket . getPeerCertificate ( ) ;
237
239
if ( isEmptyObjectOrNull ( certificate ) ) {
238
240
onFailure ( newError ( "Secure connection was successful but server did not return any valid " +
239
- "certificates. Such connection can not be trusted. If you are just trying " +
240
- " Neo4j out and are not concerned about encryption, simply disable it using " +
241
- "`encrypted=\"" + ENCRYPTION_OFF + "\"` in the driver options. " +
242
- "Socket responded with: " + socket . authorizationError ) ) ;
241
+ "certificates. Such connection can not be trusted. If you are just trying " +
242
+ " Neo4j out and are not concerned about encryption, simply disable it using " +
243
+ "`encrypted=\"" + ENCRYPTION_OFF + "\"` in the driver options. " +
244
+ "Socket responded with: " + socket . authorizationError ) ) ;
243
245
} else {
244
246
onSuccess ( ) ;
245
247
}
246
- } ) ;
247
- socket . on ( 'error' , onFailure ) ;
248
- return socket ;
248
+ } ;
249
+
250
+ return connectTlsSocket ( config , tlsOpts , connectListener , onFailure ) ;
249
251
}
250
252
} ;
251
253
@@ -259,9 +261,7 @@ const TrustStrategy = {
259
261
function connect ( config , onSuccess , onFailure = ( ( ) => null ) ) {
260
262
//still allow boolean for backwards compatibility
261
263
if ( config . encrypted === false || config . encrypted === ENCRYPTION_OFF ) {
262
- var conn = net . connect ( config . port , config . host , onSuccess ) ;
263
- conn . on ( 'error' , onFailure ) ;
264
- return conn ;
264
+ return connectSocket ( config , onSuccess , onFailure ) ;
265
265
} else if ( TrustStrategy [ config . trust ] ) {
266
266
return TrustStrategy [ config . trust ] ( config , onSuccess , onFailure ) ;
267
267
} else {
@@ -275,6 +275,60 @@ function connect( config, onSuccess, onFailure=(()=>null) ) {
275
275
}
276
276
}
277
277
278
+ /**
279
+ * Establish insecure connection using `net.Socket`.
280
+ * @param {ChannelConfig } config - configuration of this channel.
281
+ * @param {function } connectListener - success callback.
282
+ * @param {function } failureListener - failure callback.
283
+ * @return {* } an instance of `net.Socket`.
284
+ */
285
+ function connectSocket ( config , connectListener , failureListener ) {
286
+ const socket = net . connect ( config . port , config . host , ( ) => {
287
+ // connected! cancel the connection timeout and notify provided callback
288
+ socket . setTimeout ( 0 ) ; // remove the timeout
289
+ connectListener ( socket ) ;
290
+ } ) ;
291
+ socket . on ( 'error' , failureListener ) ;
292
+ setupConnectionTimeoutIfConfigured ( socket , config ) ;
293
+ return socket ;
294
+ }
295
+
296
+ /**
297
+ * Establish secure connection using `tls.TLSSocket`.
298
+ * @param {ChannelConfig } config - configuration of this channel.
299
+ * @param {object } tlsOpts - options for TLS socket.
300
+ * @param {function } connectListener - success callback.
301
+ * @param {function } failureListener - failure callback.
302
+ * @return {* } an instance of `tls.TLSSocket`.
303
+ */
304
+ function connectTlsSocket ( config , tlsOpts , connectListener , failureListener ) {
305
+ const socket = tls . connect ( config . port , config . host , tlsOpts , ( ) => {
306
+ // connected! cancel the connection timeout and notify provided callback
307
+ socket . setTimeout ( 0 ) ;
308
+ connectListener ( socket ) ;
309
+ } ) ;
310
+ socket . on ( 'error' , failureListener ) ;
311
+ setupConnectionTimeoutIfConfigured ( socket , config ) ;
312
+ return socket ;
313
+ }
314
+
315
+ /**
316
+ * Set connection timeout on the given socket, if configured.
317
+ * @param {object } socket - NodeJS net.Socket or tls.TLSSocket.
318
+ * @param {ChannelConfig } config - configuration of this channel.
319
+ */
320
+ function setupConnectionTimeoutIfConfigured ( socket , config ) {
321
+ const timeout = config . connectionTimeout ;
322
+ if ( timeout ) {
323
+ socket . on ( 'timeout' , ( ) => {
324
+ // timeout fired - not connected within configured time. cancel timeout and destroy socket
325
+ socket . setTimeout ( 0 ) ;
326
+ socket . destroy ( newError ( `Failed to establish connection in ${ timeout } ms` , config . connectionErrorCode ) ) ;
327
+ } ) ;
328
+ socket . setTimeout ( timeout ) ;
329
+ }
330
+ }
331
+
278
332
/**
279
333
* In a Node.js environment the 'net' module is used
280
334
* as transport.
0 commit comments