• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright Joyent, Inc. and other Node contributors.
2//
3// Permission is hereby granted, free of charge, to any person obtaining a
4// copy of this software and associated documentation files (the
5// "Software"), to deal in the Software without restriction, including
6// without limitation the rights to use, copy, modify, merge, publish,
7// distribute, sublicense, and/or sell copies of the Software, and to permit
8// persons to whom the Software is furnished to do so, subject to the
9// following conditions:
10//
11// The above copyright notice and this permission notice shall be included
12// in all copies or substantial portions of the Software.
13//
14// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
17// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
18// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20// USE OR OTHER DEALINGS IN THE SOFTWARE.
21
22'use strict';
23
24const {
25  ObjectAssign,
26  ObjectDefineProperty,
27  ObjectSetPrototypeOf,
28  RegExp,
29  Symbol,
30  SymbolFor,
31} = primordials;
32
33const {
34  assertCrypto,
35  deprecate
36} = require('internal/util');
37
38assertCrypto();
39
40const { setImmediate } = require('timers');
41const assert = require('internal/assert');
42const crypto = require('crypto');
43const EE = require('events');
44const net = require('net');
45const tls = require('tls');
46const common = require('_tls_common');
47const JSStreamSocket = require('internal/js_stream_socket');
48const { Buffer } = require('buffer');
49let debug = require('internal/util/debuglog').debuglog('tls', (fn) => {
50  debug = fn;
51});
52const { TCP, constants: TCPConstants } = internalBinding('tcp_wrap');
53const tls_wrap = internalBinding('tls_wrap');
54const { Pipe, constants: PipeConstants } = internalBinding('pipe_wrap');
55const { owner_symbol } = require('internal/async_hooks').symbols;
56const { isArrayBufferView } = require('internal/util/types');
57const { SecureContext: NativeSecureContext } = internalBinding('crypto');
58const { connResetException, codes } = require('internal/errors');
59const {
60  ERR_INVALID_ARG_TYPE,
61  ERR_INVALID_ARG_VALUE,
62  ERR_INVALID_CALLBACK,
63  ERR_MULTIPLE_CALLBACK,
64  ERR_SOCKET_CLOSED,
65  ERR_TLS_DH_PARAM_SIZE,
66  ERR_TLS_HANDSHAKE_TIMEOUT,
67  ERR_TLS_INVALID_CONTEXT,
68  ERR_TLS_RENEGOTIATION_DISABLED,
69  ERR_TLS_REQUIRED_SERVER_NAME,
70  ERR_TLS_SESSION_ATTACK,
71  ERR_TLS_SNI_FROM_SERVER,
72  ERR_TLS_INVALID_STATE
73} = codes;
74const { onpskexchange: kOnPskExchange } = internalBinding('symbols');
75const {
76  getOptionValue,
77  getAllowUnauthorized,
78} = require('internal/options');
79const {
80  validateString,
81  validateBuffer,
82  validateUint32
83} = require('internal/validators');
84const traceTls = getOptionValue('--trace-tls');
85const tlsKeylog = getOptionValue('--tls-keylog');
86const { appendFile } = require('fs');
87const kConnectOptions = Symbol('connect-options');
88const kDisableRenegotiation = Symbol('disable-renegotiation');
89const kErrorEmitted = Symbol('error-emitted');
90const kHandshakeTimeout = Symbol('handshake-timeout');
91const kRes = Symbol('res');
92const kSNICallback = Symbol('snicallback');
93const kEnableTrace = Symbol('enableTrace');
94const kPskCallback = Symbol('pskcallback');
95const kPskIdentityHint = Symbol('pskidentityhint');
96const kPendingSession = Symbol('pendingSession');
97const kIsVerified = Symbol('verified');
98
99const noop = () => {};
100
101let ipServernameWarned = false;
102let tlsTracingWarned = false;
103
104// Server side times how long a handshake is taking to protect against slow
105// handshakes being used for DoS.
106function onhandshakestart(now) {
107  debug('server onhandshakestart');
108
109  const { lastHandshakeTime } = this;
110  assert(now >= lastHandshakeTime,
111         `now (${now}) < lastHandshakeTime (${lastHandshakeTime})`);
112
113  this.lastHandshakeTime = now;
114
115  // If this is the first handshake we can skip the rest of the checks.
116  if (lastHandshakeTime === 0)
117    return;
118
119  if ((now - lastHandshakeTime) >= tls.CLIENT_RENEG_WINDOW * 1000)
120    this.handshakes = 1;
121  else
122    this.handshakes++;
123
124  const owner = this[owner_symbol];
125
126  assert(owner._tlsOptions.isServer);
127
128  if (this.handshakes > tls.CLIENT_RENEG_LIMIT) {
129    owner._emitTLSError(new ERR_TLS_SESSION_ATTACK());
130    return;
131  }
132
133  if (owner[kDisableRenegotiation])
134    owner._emitTLSError(new ERR_TLS_RENEGOTIATION_DISABLED());
135}
136
137function onhandshakedone() {
138  debug('server onhandshakedone');
139
140  const owner = this[owner_symbol];
141  assert(owner._tlsOptions.isServer);
142
143  // `newSession` callback wasn't called yet
144  if (owner._newSessionPending) {
145    owner._securePending = true;
146    return;
147  }
148
149  owner._finishInit();
150}
151
152
153function loadSession(hello) {
154  debug('server onclienthello',
155        'sessionid.len', hello.sessionId.length,
156        'ticket?', hello.tlsTicket
157  );
158  const owner = this[owner_symbol];
159
160  let once = false;
161  function onSession(err, session) {
162    debug('server resumeSession callback(err %j, sess? %s)', err, !!session);
163    if (once)
164      return owner.destroy(new ERR_MULTIPLE_CALLBACK());
165    once = true;
166
167    if (err)
168      return owner.destroy(err);
169
170    if (owner._handle === null)
171      return owner.destroy(new ERR_SOCKET_CLOSED());
172
173    owner._handle.loadSession(session);
174    // Session is loaded. End the parser to allow handshaking to continue.
175    owner._handle.endParser();
176  }
177
178  if (hello.sessionId.length <= 0 ||
179      hello.tlsTicket ||
180      (owner.server &&
181      !owner.server.emit('resumeSession', hello.sessionId, onSession))) {
182    // Sessions without identifiers can't be resumed.
183    // Sessions with tickets can be resumed directly from the ticket, no server
184    // session storage is necessary.
185    // Without a call to a resumeSession listener, a session will never be
186    // loaded, so end the parser to allow handshaking to continue.
187    owner._handle.endParser();
188  }
189}
190
191
192function loadSNI(info) {
193  const owner = this[owner_symbol];
194  const servername = info.servername;
195  if (!servername || !owner._SNICallback)
196    return requestOCSP(owner, info);
197
198  let once = false;
199  owner._SNICallback(servername, (err, context) => {
200    if (once)
201      return owner.destroy(new ERR_MULTIPLE_CALLBACK());
202    once = true;
203
204    if (err)
205      return owner.destroy(err);
206
207    if (owner._handle === null)
208      return owner.destroy(new ERR_SOCKET_CLOSED());
209
210    // TODO(indutny): eventually disallow raw `SecureContext`
211    if (context)
212      owner._handle.sni_context = context.context || context;
213
214    requestOCSP(owner, info);
215  });
216}
217
218
219function requestOCSP(socket, info) {
220  if (!info.OCSPRequest || !socket.server)
221    return requestOCSPDone(socket);
222
223  let ctx = socket._handle.sni_context;
224
225  if (!ctx) {
226    ctx = socket.server._sharedCreds;
227
228    // TLS socket is using a `net.Server` instead of a tls.TLSServer.
229    // Some TLS properties like `server._sharedCreds` will not be present
230    if (!ctx)
231      return requestOCSPDone(socket);
232  }
233
234  // TODO(indutny): eventually disallow raw `SecureContext`
235  if (ctx.context)
236    ctx = ctx.context;
237
238  if (socket.server.listenerCount('OCSPRequest') === 0) {
239    return requestOCSPDone(socket);
240  }
241
242  let once = false;
243  const onOCSP = (err, response) => {
244    debug('server OCSPRequest done', 'handle?', !!socket._handle, 'once?', once,
245          'response?', !!response, 'err?', err);
246    if (once)
247      return socket.destroy(new ERR_MULTIPLE_CALLBACK());
248    once = true;
249
250    if (err)
251      return socket.destroy(err);
252
253    if (socket._handle === null)
254      return socket.destroy(new ERR_SOCKET_CLOSED());
255
256    if (response)
257      socket._handle.setOCSPResponse(response);
258    requestOCSPDone(socket);
259  };
260
261  debug('server oncertcb emit OCSPRequest');
262  socket.server.emit('OCSPRequest',
263                     ctx.getCertificate(),
264                     ctx.getIssuer(),
265                     onOCSP);
266}
267
268function requestOCSPDone(socket) {
269  debug('server certcb done');
270  try {
271    socket._handle.certCbDone();
272  } catch (e) {
273    debug('server certcb done errored', e);
274    socket.destroy(e);
275  }
276}
277
278function onnewsessionclient(sessionId, session) {
279  debug('client emit session');
280  const owner = this[owner_symbol];
281  if (owner[kIsVerified]) {
282    owner.emit('session', session);
283  } else {
284    owner[kPendingSession] = session;
285  }
286}
287
288function onnewsession(sessionId, session) {
289  debug('onnewsession');
290  const owner = this[owner_symbol];
291
292  // TODO(@sam-github) no server to emit the event on, but handshake won't
293  // continue unless newSessionDone() is called, should it be, or is that
294  // situation unreachable, or only occurring during shutdown?
295  if (!owner.server)
296    return;
297
298  let once = false;
299  const done = () => {
300    debug('onnewsession done');
301    if (once)
302      return;
303    once = true;
304
305    if (owner._handle === null)
306      return owner.destroy(new ERR_SOCKET_CLOSED());
307
308    this.newSessionDone();
309
310    owner._newSessionPending = false;
311    if (owner._securePending)
312      owner._finishInit();
313    owner._securePending = false;
314  };
315
316  owner._newSessionPending = true;
317  if (!owner.server.emit('newSession', sessionId, session, done))
318    done();
319}
320
321function onPskServerCallback(identity, maxPskLen) {
322  const owner = this[owner_symbol];
323  const ret = owner[kPskCallback](owner, identity);
324  if (ret == null)
325    return undefined;
326
327  let psk;
328  if (isArrayBufferView(ret)) {
329    psk = ret;
330  } else {
331    if (typeof ret !== 'object') {
332      throw new ERR_INVALID_ARG_TYPE(
333        'ret',
334        ['Object', 'Buffer', 'TypedArray', 'DataView'],
335        ret
336      );
337    }
338    psk = ret.psk;
339    validateBuffer(psk, 'psk');
340  }
341
342  if (psk.length > maxPskLen) {
343    throw new ERR_INVALID_ARG_VALUE(
344      'psk',
345      psk,
346      `Pre-shared key exceeds ${maxPskLen} bytes`
347    );
348  }
349
350  return psk;
351}
352
353function onPskClientCallback(hint, maxPskLen, maxIdentityLen) {
354  const owner = this[owner_symbol];
355  const ret = owner[kPskCallback](hint);
356  if (ret == null)
357    return undefined;
358
359  if (typeof ret !== 'object')
360    throw new ERR_INVALID_ARG_TYPE('ret', 'Object', ret);
361
362  validateBuffer(ret.psk, 'psk');
363  if (ret.psk.length > maxPskLen) {
364    throw new ERR_INVALID_ARG_VALUE(
365      'psk',
366      ret.psk,
367      `Pre-shared key exceeds ${maxPskLen} bytes`
368    );
369  }
370
371  validateString(ret.identity, 'identity');
372  if (Buffer.byteLength(ret.identity) > maxIdentityLen) {
373    throw new ERR_INVALID_ARG_VALUE(
374      'identity',
375      ret.identity,
376      `PSK identity exceeds ${maxIdentityLen} bytes`
377    );
378  }
379
380  return { psk: ret.psk, identity: ret.identity };
381}
382
383function onkeylog(line) {
384  debug('onkeylog');
385  this[owner_symbol].emit('keylog', line);
386}
387
388function onocspresponse(resp) {
389  debug('client onocspresponse');
390  this[owner_symbol].emit('OCSPResponse', resp);
391}
392
393function onerror(err) {
394  const owner = this[owner_symbol];
395  debug('%s onerror %s had? %j',
396        owner._tlsOptions.isServer ? 'server' : 'client', err,
397        owner._hadError);
398
399  if (owner._hadError)
400    return;
401
402  owner._hadError = true;
403
404  // Destroy socket if error happened before handshake's finish
405  if (!owner._secureEstablished) {
406    // When handshake fails control is not yet released,
407    // so self._tlsError will return null instead of actual error
408    owner.destroy(err);
409  } else if (owner._tlsOptions.isServer &&
410             owner._rejectUnauthorized &&
411             /peer did not return a certificate/.test(err.message)) {
412    // Ignore server's authorization errors
413    owner.destroy();
414  } else {
415    // Emit error
416    owner._emitTLSError(err);
417  }
418}
419
420// Used by both client and server TLSSockets to start data flowing from _handle,
421// read(0) causes a StreamBase::ReadStart, via Socket._read.
422function initRead(tlsSocket, socket) {
423  debug('%s initRead',
424        tlsSocket._tlsOptions.isServer ? 'server' : 'client',
425        'handle?', !!tlsSocket._handle,
426        'buffered?', !!socket && socket.readableLength
427  );
428  // If we were destroyed already don't bother reading
429  if (!tlsSocket._handle)
430    return;
431
432  // Socket already has some buffered data - emulate receiving it
433  if (socket && socket.readableLength) {
434    let buf;
435    while ((buf = socket.read()) !== null)
436      tlsSocket._handle.receive(buf);
437  }
438
439  tlsSocket.read(0);
440}
441
442/**
443 * Provides a wrap of socket stream to do encrypted communication.
444 */
445
446function TLSSocket(socket, opts) {
447  const tlsOptions = { ...opts };
448  let enableTrace = tlsOptions.enableTrace;
449
450  if (enableTrace == null) {
451    enableTrace = traceTls;
452
453    if (enableTrace && !tlsTracingWarned) {
454      tlsTracingWarned = true;
455      process.emitWarning('Enabling --trace-tls can expose sensitive data in ' +
456                          'the resulting log.');
457    }
458  } else if (typeof enableTrace !== 'boolean') {
459    throw new ERR_INVALID_ARG_TYPE(
460      'options.enableTrace', 'boolean', enableTrace);
461  }
462
463  if (tlsOptions.ALPNProtocols)
464    tls.convertALPNProtocols(tlsOptions.ALPNProtocols, tlsOptions);
465
466  this._tlsOptions = tlsOptions;
467  this._secureEstablished = false;
468  this._securePending = false;
469  this._newSessionPending = false;
470  this._controlReleased = false;
471  this.secureConnecting = true;
472  this._SNICallback = null;
473  this.servername = null;
474  this.alpnProtocol = null;
475  this.authorized = false;
476  this.authorizationError = null;
477  this[kRes] = null;
478  this[kIsVerified] = false;
479  this[kPendingSession] = null;
480
481  let wrap;
482  if ((socket instanceof net.Socket && socket._handle) || !socket) {
483    // 1. connected socket
484    // 2. no socket, one will be created with net.Socket().connect
485    wrap = socket;
486  } else {
487    // 3. socket has no handle so it is js not c++
488    // 4. unconnected sockets are wrapped
489    // TLS expects to interact from C++ with a net.Socket that has a C++ stream
490    // handle, but a JS stream doesn't have one. Wrap it up to make it look like
491    // a socket.
492    wrap = new JSStreamSocket(socket);
493  }
494
495  // Just a documented property to make secure sockets
496  // distinguishable from regular ones.
497  this.encrypted = true;
498
499  net.Socket.call(this, {
500    handle: this._wrapHandle(wrap),
501    allowHalfOpen: socket ? socket.allowHalfOpen : tlsOptions.allowHalfOpen,
502    pauseOnCreate: tlsOptions.pauseOnConnect,
503    manualStart: true,
504    highWaterMark: tlsOptions.highWaterMark,
505    onread: !socket ? tlsOptions.onread : null,
506  });
507
508  // Proxy for API compatibility
509  this.ssl = this._handle;  // C++ TLSWrap object
510
511  this.on('error', this._tlsError);
512
513  this._init(socket, wrap);
514
515  if (enableTrace && this._handle)
516    this._handle.enableTrace();
517
518  // Read on next tick so the caller has a chance to setup listeners
519  process.nextTick(initRead, this, socket);
520}
521ObjectSetPrototypeOf(TLSSocket.prototype, net.Socket.prototype);
522ObjectSetPrototypeOf(TLSSocket, net.Socket);
523exports.TLSSocket = TLSSocket;
524
525const proxiedMethods = [
526  'ref', 'unref', 'open', 'bind', 'listen', 'connect', 'bind6',
527  'connect6', 'getsockname', 'getpeername', 'setNoDelay', 'setKeepAlive',
528  'setSimultaneousAccepts', 'setBlocking',
529
530  // PipeWrap
531  'setPendingInstances',
532];
533
534// Proxy HandleWrap, PipeWrap and TCPWrap methods
535function makeMethodProxy(name) {
536  return function methodProxy(...args) {
537    if (this._parent[name])
538      return this._parent[name].apply(this._parent, args);
539  };
540}
541for (const proxiedMethod of proxiedMethods) {
542  tls_wrap.TLSWrap.prototype[proxiedMethod] =
543    makeMethodProxy(proxiedMethod);
544}
545
546tls_wrap.TLSWrap.prototype.close = function close(cb) {
547  let ssl;
548  if (this[owner_symbol]) {
549    ssl = this[owner_symbol].ssl;
550    this[owner_symbol].ssl = null;
551  }
552
553  // Invoke `destroySSL` on close to clean up possibly pending write requests
554  // that may self-reference TLSWrap, leading to leak
555  const done = () => {
556    if (ssl) {
557      ssl.destroySSL();
558      if (ssl._secureContext.singleUse) {
559        ssl._secureContext.context.close();
560        ssl._secureContext.context = null;
561      }
562    }
563    if (cb)
564      cb();
565  };
566
567  if (this._parentWrap && this._parentWrap._handle === this._parent) {
568    this._parentWrap.once('close', done);
569    return this._parentWrap.destroy();
570  }
571  return this._parent.close(done);
572};
573
574TLSSocket.prototype.disableRenegotiation = function disableRenegotiation() {
575  this[kDisableRenegotiation] = true;
576};
577
578TLSSocket.prototype._wrapHandle = function(wrap) {
579  let handle;
580
581  if (wrap)
582    handle = wrap._handle;
583
584  const options = this._tlsOptions;
585  if (!handle) {
586    handle = options.pipe ?
587      new Pipe(PipeConstants.SOCKET) :
588      new TCP(TCPConstants.SOCKET);
589    handle[owner_symbol] = this;
590  }
591
592  // Wrap socket's handle
593  const context = options.secureContext ||
594                  options.credentials ||
595                  tls.createSecureContext(options);
596  assert(handle.isStreamBase, 'handle must be a StreamBase');
597  if (!(context.context instanceof NativeSecureContext)) {
598    throw new ERR_TLS_INVALID_CONTEXT('context');
599  }
600  const res = tls_wrap.wrap(handle, context.context, !!options.isServer);
601  res._parent = handle;  // C++ "wrap" object: TCPWrap, JSStream, ...
602  res._parentWrap = wrap;  // JS object: net.Socket, JSStreamSocket, ...
603  res._secureContext = context;
604  res.reading = handle.reading;
605  this[kRes] = res;
606  defineHandleReading(this, handle);
607
608  this.on('close', onSocketCloseDestroySSL);
609
610  return res;
611};
612
613// This eliminates a cyclic reference to TLSWrap
614// Ref: https://github.com/nodejs/node/commit/f7620fb96d339f704932f9bb9a0dceb9952df2d4
615function defineHandleReading(socket, handle) {
616  ObjectDefineProperty(handle, 'reading', {
617    get: () => {
618      return socket[kRes].reading;
619    },
620    set: (value) => {
621      socket[kRes].reading = value;
622    }
623  });
624}
625
626function onSocketCloseDestroySSL() {
627  // Make sure we are not doing it on OpenSSL's stack
628  setImmediate(destroySSL, this);
629  this[kRes] = null;
630}
631
632function destroySSL(self) {
633  self._destroySSL();
634}
635
636TLSSocket.prototype._destroySSL = function _destroySSL() {
637  if (!this.ssl) return;
638  this.ssl.destroySSL();
639  if (this.ssl._secureContext.singleUse) {
640    this.ssl._secureContext.context.close();
641    this.ssl._secureContext.context = null;
642  }
643  this.ssl = null;
644  this[kPendingSession] = null;
645  this[kIsVerified] = false;
646};
647
648// Constructor guts, arbitrarily factored out.
649let warnOnTlsKeylog = true;
650let warnOnTlsKeylogError = true;
651TLSSocket.prototype._init = function(socket, wrap) {
652  const options = this._tlsOptions;
653  const ssl = this._handle;
654  this.server = options.server;
655
656  debug('%s _init',
657        options.isServer ? 'server' : 'client',
658        'handle?', !!ssl
659  );
660
661  // Clients (!isServer) always request a cert, servers request a client cert
662  // only on explicit configuration.
663  const requestCert = !!options.requestCert || !options.isServer;
664  const rejectUnauthorized = !!options.rejectUnauthorized;
665
666  this._requestCert = requestCert;
667  this._rejectUnauthorized = rejectUnauthorized;
668  if (requestCert || rejectUnauthorized)
669    ssl.setVerifyMode(requestCert, rejectUnauthorized);
670
671  // Only call .onkeylog if there is a keylog listener.
672  ssl.onkeylog = onkeylog;
673  this.on('newListener', keylogNewListener);
674
675  function keylogNewListener(event) {
676    if (event !== 'keylog')
677      return;
678
679    // Guard against enableKeylogCallback after destroy
680    if (!this._handle) return;
681    this._handle.enableKeylogCallback();
682
683    // Remove this listener since it's no longer needed.
684    this.removeListener('newListener', keylogNewListener);
685  }
686
687  if (options.isServer) {
688    ssl.onhandshakestart = onhandshakestart;
689    ssl.onhandshakedone = onhandshakedone;
690    ssl.onclienthello = loadSession;
691    ssl.oncertcb = loadSNI;
692    ssl.onnewsession = onnewsession;
693    ssl.lastHandshakeTime = 0;
694    ssl.handshakes = 0;
695
696    if (this.server) {
697      if (this.server.listenerCount('resumeSession') > 0 ||
698          this.server.listenerCount('newSession') > 0) {
699        // Also starts the client hello parser as a side effect.
700        ssl.enableSessionCallbacks();
701      }
702      if (this.server.listenerCount('OCSPRequest') > 0)
703        ssl.enableCertCb();
704    }
705  } else {
706    ssl.onhandshakestart = noop;
707    ssl.onhandshakedone = () => {
708      debug('client onhandshakedone');
709      this._finishInit();
710    };
711    ssl.onocspresponse = onocspresponse;
712
713    if (options.session)
714      ssl.setSession(options.session);
715
716    ssl.onnewsession = onnewsessionclient;
717
718    // Only call .onnewsession if there is a session listener.
719    this.on('newListener', newListener);
720
721    function newListener(event) {
722      if (event !== 'session')
723        return;
724
725      // Guard against enableSessionCallbacks after destroy
726      if (!this._handle) return;
727      this._handle.enableSessionCallbacks();
728
729      // Remove this listener since it's no longer needed.
730      this.removeListener('newListener', newListener);
731    }
732  }
733
734  if (tlsKeylog) {
735    if (warnOnTlsKeylog) {
736      warnOnTlsKeylog = false;
737      process.emitWarning('Using --tls-keylog makes TLS connections insecure ' +
738        'by writing secret key material to file ' + tlsKeylog);
739    }
740    this.on('keylog', (line) => {
741      appendFile(tlsKeylog, line, { mode: 0o600 }, (err) => {
742        if (err && warnOnTlsKeylogError) {
743          warnOnTlsKeylogError = false;
744          process.emitWarning('Failed to write TLS keylog (this warning ' +
745            'will not be repeated): ' + err);
746        }
747      });
748    });
749  }
750
751  ssl.onerror = onerror;
752
753  // If custom SNICallback was given, or if
754  // there're SNI contexts to perform match against -
755  // set `.onsniselect` callback.
756  if (options.isServer &&
757      options.SNICallback &&
758      (options.SNICallback !== SNICallback ||
759       (options.server && options.server._contexts.length))) {
760    assert(typeof options.SNICallback === 'function');
761    this._SNICallback = options.SNICallback;
762    ssl.enableCertCb();
763  }
764
765  if (options.ALPNProtocols) {
766    // Keep reference in secureContext not to be GC-ed
767    ssl._secureContext.alpnBuffer = options.ALPNProtocols;
768    ssl.setALPNProtocols(ssl._secureContext.alpnBuffer);
769  }
770
771  if (options.pskCallback && ssl.enablePskCallback) {
772    if (typeof options.pskCallback !== 'function') {
773      throw new ERR_INVALID_ARG_TYPE('pskCallback',
774                                     'function',
775                                     options.pskCallback);
776    }
777
778    ssl[kOnPskExchange] = options.isServer ?
779      onPskServerCallback : onPskClientCallback;
780
781    this[kPskCallback] = options.pskCallback;
782    ssl.enablePskCallback();
783
784    if (options.pskIdentityHint) {
785      if (typeof options.pskIdentityHint !== 'string') {
786        throw new ERR_INVALID_ARG_TYPE(
787          'options.pskIdentityHint',
788          'string',
789          options.pskIdentityHint
790        );
791      }
792      ssl.setPskIdentityHint(options.pskIdentityHint);
793    }
794  }
795
796
797  if (options.handshakeTimeout > 0)
798    this.setTimeout(options.handshakeTimeout, this._handleTimeout);
799
800  if (socket instanceof net.Socket) {
801    this._parent = socket;
802
803    // To prevent assertion in afterConnect() and properly kick off readStart
804    this.connecting = socket.connecting || !socket._handle;
805    socket.once('connect', () => {
806      this.connecting = false;
807      this.emit('connect');
808    });
809  }
810
811  // Assume `tls.connect()`
812  if (wrap) {
813    wrap.on('error', (err) => this._emitTLSError(err));
814  } else {
815    assert(!socket);
816    this.connecting = true;
817  }
818};
819
820TLSSocket.prototype.renegotiate = function(options, callback) {
821  if (options === null || typeof options !== 'object')
822    throw new ERR_INVALID_ARG_TYPE('options', 'Object', options);
823  if (callback !== undefined && typeof callback !== 'function')
824    throw new ERR_INVALID_CALLBACK(callback);
825
826  debug('%s renegotiate()',
827        this._tlsOptions.isServer ? 'server' : 'client',
828        'destroyed?', this.destroyed
829  );
830
831  if (this.destroyed)
832    return;
833
834  let requestCert = !!this._requestCert;
835  let rejectUnauthorized = !!this._rejectUnauthorized;
836
837  if (options.requestCert !== undefined)
838    requestCert = !!options.requestCert;
839  if (options.rejectUnauthorized !== undefined)
840    rejectUnauthorized = !!options.rejectUnauthorized;
841
842  if (requestCert !== this._requestCert ||
843      rejectUnauthorized !== this._rejectUnauthorized) {
844    this._handle.setVerifyMode(requestCert, rejectUnauthorized);
845    this._requestCert = requestCert;
846    this._rejectUnauthorized = rejectUnauthorized;
847  }
848  // Ensure that we'll cycle through internal openssl's state
849  this.write('');
850
851  try {
852    this._handle.renegotiate();
853  } catch (err) {
854    if (callback) {
855      process.nextTick(callback, err);
856    }
857    return false;
858  }
859
860  // Ensure that we'll cycle through internal openssl's state
861  this.write('');
862
863  if (callback) {
864    this.once('secure', () => callback(null));
865  }
866
867  return true;
868};
869
870TLSSocket.prototype.exportKeyingMaterial = function(length, label, context) {
871  validateUint32(length, 'length', true);
872  validateString(label, 'label');
873  if (context !== undefined)
874    validateBuffer(context, 'context');
875
876  if (!this._secureEstablished)
877    throw new ERR_TLS_INVALID_STATE();
878
879  return this._handle.exportKeyingMaterial(length, label, context);
880};
881
882TLSSocket.prototype.setMaxSendFragment = function setMaxSendFragment(size) {
883  return this._handle.setMaxSendFragment(size) === 1;
884};
885
886TLSSocket.prototype._handleTimeout = function() {
887  this._emitTLSError(new ERR_TLS_HANDSHAKE_TIMEOUT());
888};
889
890TLSSocket.prototype._emitTLSError = function(err) {
891  const e = this._tlsError(err);
892  if (e)
893    this.emit('error', e);
894};
895
896TLSSocket.prototype._tlsError = function(err) {
897  this.emit('_tlsError', err);
898  if (this._controlReleased)
899    return err;
900  return null;
901};
902
903TLSSocket.prototype._releaseControl = function() {
904  if (this._controlReleased)
905    return false;
906  this._controlReleased = true;
907  this.removeListener('error', this._tlsError);
908  return true;
909};
910
911TLSSocket.prototype._finishInit = function() {
912  // Guard against getting onhandshakedone() after .destroy().
913  // * 1.2: If destroy() during onocspresponse(), then write of next handshake
914  // record fails, the handshake done info callbacks does not occur, and the
915  // socket closes.
916  // * 1.3: The OCSP response comes in the same record that finishes handshake,
917  // so even after .destroy(), the handshake done info callback occurs
918  // immediately after onocspresponse(). Ignore it.
919  if (!this._handle)
920    return;
921
922  this.alpnProtocol = this._handle.getALPNNegotiatedProtocol();
923  // The servername could be set by TLSWrap::SelectSNIContextCallback().
924  if (this.servername === null) {
925    this.servername = this._handle.getServername();
926  }
927
928  debug('%s _finishInit',
929        this._tlsOptions.isServer ? 'server' : 'client',
930        'handle?', !!this._handle,
931        'alpn', this.alpnProtocol,
932        'servername', this.servername);
933
934  this._secureEstablished = true;
935  if (this._tlsOptions.handshakeTimeout > 0)
936    this.setTimeout(0, this._handleTimeout);
937  this.emit('secure');
938};
939
940TLSSocket.prototype._start = function() {
941  debug('%s _start',
942        this._tlsOptions.isServer ? 'server' : 'client',
943        'handle?', !!this._handle,
944        'connecting?', this.connecting,
945        'requestOCSP?', !!this._tlsOptions.requestOCSP,
946  );
947  if (this.connecting) {
948    this.once('connect', this._start);
949    return;
950  }
951
952  // Socket was destroyed before the connection was established
953  if (!this._handle)
954    return;
955
956  if (this._tlsOptions.requestOCSP)
957    this._handle.requestOCSP();
958  this._handle.start();
959};
960
961TLSSocket.prototype.setServername = function(name) {
962  validateString(name, 'name');
963
964  if (this._tlsOptions.isServer) {
965    throw new ERR_TLS_SNI_FROM_SERVER();
966  }
967
968  this._handle.setServername(name);
969};
970
971TLSSocket.prototype.setSession = function(session) {
972  if (typeof session === 'string')
973    session = Buffer.from(session, 'latin1');
974  this._handle.setSession(session);
975};
976
977TLSSocket.prototype.getPeerCertificate = function(detailed) {
978  if (this._handle) {
979    return common.translatePeerCertificate(
980      this._handle.getPeerCertificate(detailed)) || {};
981  }
982
983  return null;
984};
985
986TLSSocket.prototype.getCertificate = function() {
987  if (this._handle) {
988    // It's not a peer cert, but the formatting is identical.
989    return common.translatePeerCertificate(
990      this._handle.getCertificate()) || {};
991  }
992
993  return null;
994};
995
996// Proxy TLSSocket handle methods
997function makeSocketMethodProxy(name) {
998  return function socketMethodProxy(...args) {
999    if (this._handle)
1000      return this._handle[name].apply(this._handle, args);
1001    return null;
1002  };
1003}
1004
1005[
1006  'getCipher',
1007  'getSharedSigalgs',
1008  'getEphemeralKeyInfo',
1009  'getFinished',
1010  'getPeerFinished',
1011  'getProtocol',
1012  'getSession',
1013  'getTLSTicket',
1014  'isSessionReused',
1015  'enableTrace',
1016].forEach((method) => {
1017  TLSSocket.prototype[method] = makeSocketMethodProxy(method);
1018});
1019
1020// TODO: support anonymous (nocert)
1021
1022
1023function onServerSocketSecure() {
1024  if (this._requestCert) {
1025    const verifyError = this._handle.verifyError();
1026    if (verifyError) {
1027      this.authorizationError = verifyError.code;
1028
1029      if (this._rejectUnauthorized)
1030        this.destroy();
1031    } else {
1032      this.authorized = true;
1033    }
1034  }
1035
1036  if (!this.destroyed && this._releaseControl()) {
1037    debug('server emit secureConnection');
1038    this.secureConnecting = false;
1039    this._tlsOptions.server.emit('secureConnection', this);
1040  }
1041}
1042
1043function onSocketTLSError(err) {
1044  if (!this._controlReleased && !this[kErrorEmitted]) {
1045    this[kErrorEmitted] = true;
1046    debug('server emit tlsClientError:', err);
1047    this._tlsOptions.server.emit('tlsClientError', err, this);
1048  }
1049}
1050
1051function onSocketKeylog(line) {
1052  this._tlsOptions.server.emit('keylog', line, this);
1053}
1054
1055function onSocketClose(err) {
1056  // Closed because of error - no need to emit it twice
1057  if (err)
1058    return;
1059
1060  // Emit ECONNRESET
1061  if (!this._controlReleased && !this[kErrorEmitted]) {
1062    this[kErrorEmitted] = true;
1063    const connReset = connResetException('socket hang up');
1064    this._tlsOptions.server.emit('tlsClientError', connReset, this);
1065  }
1066}
1067
1068function tlsConnectionListener(rawSocket) {
1069  debug('net.Server.on(connection): new TLSSocket');
1070  const socket = new TLSSocket(rawSocket, {
1071    secureContext: this._sharedCreds,
1072    isServer: true,
1073    server: this,
1074    requestCert: this.requestCert,
1075    rejectUnauthorized: this.rejectUnauthorized,
1076    handshakeTimeout: this[kHandshakeTimeout],
1077    ALPNProtocols: this.ALPNProtocols,
1078    SNICallback: this[kSNICallback] || SNICallback,
1079    enableTrace: this[kEnableTrace],
1080    pauseOnConnect: this.pauseOnConnect,
1081    pskCallback: this[kPskCallback],
1082    pskIdentityHint: this[kPskIdentityHint],
1083  });
1084
1085  socket.on('secure', onServerSocketSecure);
1086
1087  if (this.listenerCount('keylog') > 0)
1088    socket.on('keylog', onSocketKeylog);
1089
1090  socket[kErrorEmitted] = false;
1091  socket.on('close', onSocketClose);
1092  socket.on('_tlsError', onSocketTLSError);
1093}
1094
1095// AUTHENTICATION MODES
1096//
1097// There are several levels of authentication that TLS/SSL supports.
1098// Read more about this in "man SSL_set_verify".
1099//
1100// 1. The server sends a certificate to the client but does not request a
1101// cert from the client. This is common for most HTTPS servers. The browser
1102// can verify the identity of the server, but the server does not know who
1103// the client is. Authenticating the client is usually done over HTTP using
1104// login boxes and cookies and stuff.
1105//
1106// 2. The server sends a cert to the client and requests that the client
1107// also send it a cert. The client knows who the server is and the server is
1108// requesting the client also identify themselves. There are several
1109// outcomes:
1110//
1111//   A) verifyError returns null meaning the client's certificate is signed
1112//   by one of the server's CAs. The server now knows the client's identity
1113//   and the client is authorized.
1114//
1115//   B) For some reason the client's certificate is not acceptable -
1116//   verifyError returns a string indicating the problem. The server can
1117//   either (i) reject the client or (ii) allow the client to connect as an
1118//   unauthorized connection.
1119//
1120// The mode is controlled by two boolean variables.
1121//
1122// requestCert
1123//   If true the server requests a certificate from client connections. For
1124//   the common HTTPS case, users will want this to be false, which is what
1125//   it defaults to.
1126//
1127// rejectUnauthorized
1128//   If true clients whose certificates are invalid for any reason will not
1129//   be allowed to make connections. If false, they will simply be marked as
1130//   unauthorized but secure communication will continue. By default this is
1131//   true.
1132//
1133//
1134//
1135// Options:
1136// - requestCert. Send verify request. Default to false.
1137// - rejectUnauthorized. Boolean, default to true.
1138// - key. string.
1139// - cert: string.
1140// - clientCertEngine: string.
1141// - ca: string or array of strings.
1142// - sessionTimeout: integer.
1143//
1144// emit 'secureConnection'
1145//   function (tlsSocket) { }
1146//
1147//   "UNABLE_TO_GET_ISSUER_CERT", "UNABLE_TO_GET_CRL",
1148//   "UNABLE_TO_DECRYPT_CERT_SIGNATURE", "UNABLE_TO_DECRYPT_CRL_SIGNATURE",
1149//   "UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY", "CERT_SIGNATURE_FAILURE",
1150//   "CRL_SIGNATURE_FAILURE", "CERT_NOT_YET_VALID" "CERT_HAS_EXPIRED",
1151//   "CRL_NOT_YET_VALID", "CRL_HAS_EXPIRED" "ERROR_IN_CERT_NOT_BEFORE_FIELD",
1152//   "ERROR_IN_CERT_NOT_AFTER_FIELD", "ERROR_IN_CRL_LAST_UPDATE_FIELD",
1153//   "ERROR_IN_CRL_NEXT_UPDATE_FIELD", "OUT_OF_MEM",
1154//   "DEPTH_ZERO_SELF_SIGNED_CERT", "SELF_SIGNED_CERT_IN_CHAIN",
1155//   "UNABLE_TO_GET_ISSUER_CERT_LOCALLY", "UNABLE_TO_VERIFY_LEAF_SIGNATURE",
1156//   "CERT_CHAIN_TOO_LONG", "CERT_REVOKED" "INVALID_CA",
1157//   "PATH_LENGTH_EXCEEDED", "INVALID_PURPOSE" "CERT_UNTRUSTED",
1158//   "CERT_REJECTED"
1159//
1160function Server(options, listener) {
1161  if (!(this instanceof Server))
1162    return new Server(options, listener);
1163
1164  if (typeof options === 'function') {
1165    listener = options;
1166    options = {};
1167  } else if (options == null || typeof options === 'object') {
1168    options = options || {};
1169  } else {
1170    throw new ERR_INVALID_ARG_TYPE('options', 'Object', options);
1171  }
1172
1173  this._contexts = [];
1174  this.requestCert = options.requestCert === true;
1175  this.rejectUnauthorized = options.rejectUnauthorized !== false;
1176
1177  if (options.sessionTimeout)
1178    this.sessionTimeout = options.sessionTimeout;
1179
1180  if (options.ticketKeys)
1181    this.ticketKeys = options.ticketKeys;
1182
1183  if (options.ALPNProtocols)
1184    tls.convertALPNProtocols(options.ALPNProtocols, this);
1185
1186  this.setSecureContext(options);
1187
1188  this[kHandshakeTimeout] = options.handshakeTimeout || (120 * 1000);
1189  this[kSNICallback] = options.SNICallback;
1190  this[kPskCallback] = options.pskCallback;
1191  this[kPskIdentityHint] = options.pskIdentityHint;
1192
1193  if (typeof this[kHandshakeTimeout] !== 'number') {
1194    throw new ERR_INVALID_ARG_TYPE(
1195      'options.handshakeTimeout', 'number', options.handshakeTimeout);
1196  }
1197
1198  if (this[kSNICallback] && typeof this[kSNICallback] !== 'function') {
1199    throw new ERR_INVALID_ARG_TYPE(
1200      'options.SNICallback', 'function', options.SNICallback);
1201  }
1202
1203  if (this[kPskCallback] && typeof this[kPskCallback] !== 'function') {
1204    throw new ERR_INVALID_ARG_TYPE(
1205      'options.pskCallback', 'function', options.pskCallback);
1206  }
1207  if (this[kPskIdentityHint] && typeof this[kPskIdentityHint] !== 'string') {
1208    throw new ERR_INVALID_ARG_TYPE(
1209      'options.pskIdentityHint',
1210      'string',
1211      options.pskIdentityHint
1212    );
1213  }
1214
1215  // constructor call
1216  net.Server.call(this, options, tlsConnectionListener);
1217
1218  if (listener) {
1219    this.on('secureConnection', listener);
1220  }
1221
1222  this[kEnableTrace] = options.enableTrace;
1223}
1224
1225ObjectSetPrototypeOf(Server.prototype, net.Server.prototype);
1226ObjectSetPrototypeOf(Server, net.Server);
1227exports.Server = Server;
1228exports.createServer = function createServer(options, listener) {
1229  return new Server(options, listener);
1230};
1231
1232
1233Server.prototype.setSecureContext = function(options) {
1234  if (options === null || typeof options !== 'object')
1235    throw new ERR_INVALID_ARG_TYPE('options', 'Object', options);
1236
1237  if (options.pfx)
1238    this.pfx = options.pfx;
1239  else
1240    this.pfx = undefined;
1241
1242  if (options.key)
1243    this.key = options.key;
1244  else
1245    this.key = undefined;
1246
1247  if (options.passphrase)
1248    this.passphrase = options.passphrase;
1249  else
1250    this.passphrase = undefined;
1251
1252  if (options.cert)
1253    this.cert = options.cert;
1254  else
1255    this.cert = undefined;
1256
1257  if (options.clientCertEngine)
1258    this.clientCertEngine = options.clientCertEngine;
1259  else
1260    this.clientCertEngine = undefined;
1261
1262  if (options.ca)
1263    this.ca = options.ca;
1264  else
1265    this.ca = undefined;
1266
1267  if (options.minVersion)
1268    this.minVersion = options.minVersion;
1269  else
1270    this.minVersion = undefined;
1271
1272  if (options.maxVersion)
1273    this.maxVersion = options.maxVersion;
1274  else
1275    this.maxVersion = undefined;
1276
1277  if (options.secureProtocol)
1278    this.secureProtocol = options.secureProtocol;
1279  else
1280    this.secureProtocol = undefined;
1281
1282  if (options.crl)
1283    this.crl = options.crl;
1284  else
1285    this.crl = undefined;
1286
1287  this.sigalgs = options.sigalgs;
1288
1289  if (options.ciphers)
1290    this.ciphers = options.ciphers;
1291  else
1292    this.ciphers = undefined;
1293
1294  this.ecdhCurve = options.ecdhCurve;
1295
1296  if (options.dhparam)
1297    this.dhparam = options.dhparam;
1298  else
1299    this.dhparam = undefined;
1300
1301  if (options.honorCipherOrder !== undefined)
1302    this.honorCipherOrder = !!options.honorCipherOrder;
1303  else
1304    this.honorCipherOrder = true;
1305
1306  const secureOptions = options.secureOptions || 0;
1307
1308  if (secureOptions)
1309    this.secureOptions = secureOptions;
1310  else
1311    this.secureOptions = undefined;
1312
1313  if (options.sessionIdContext) {
1314    this.sessionIdContext = options.sessionIdContext;
1315  } else {
1316    this.sessionIdContext = crypto.createHash('sha1')
1317                                  .update(process.argv.join(' '))
1318                                  .digest('hex')
1319                                  .slice(0, 32);
1320  }
1321
1322  if (options.sessionTimeout)
1323    this.sessionTimeout = options.sessionTimeout;
1324
1325  if (options.ticketKeys)
1326    this.ticketKeys = options.ticketKeys;
1327
1328  this.privateKeyIdentifier = options.privateKeyIdentifier;
1329  this.privateKeyEngine = options.privateKeyEngine;
1330
1331  this._sharedCreds = tls.createSecureContext({
1332    pfx: this.pfx,
1333    key: this.key,
1334    passphrase: this.passphrase,
1335    cert: this.cert,
1336    clientCertEngine: this.clientCertEngine,
1337    ca: this.ca,
1338    ciphers: this.ciphers,
1339    sigalgs: this.sigalgs,
1340    ecdhCurve: this.ecdhCurve,
1341    dhparam: this.dhparam,
1342    minVersion: this.minVersion,
1343    maxVersion: this.maxVersion,
1344    secureProtocol: this.secureProtocol,
1345    secureOptions: this.secureOptions,
1346    honorCipherOrder: this.honorCipherOrder,
1347    crl: this.crl,
1348    sessionIdContext: this.sessionIdContext,
1349    ticketKeys: this.ticketKeys,
1350    sessionTimeout: this.sessionTimeout,
1351    privateKeyIdentifier: this.privateKeyIdentifier,
1352    privateKeyEngine: this.privateKeyEngine,
1353  });
1354};
1355
1356
1357Server.prototype._getServerData = function() {
1358  return {
1359    ticketKeys: this.getTicketKeys().toString('hex')
1360  };
1361};
1362
1363
1364Server.prototype._setServerData = function(data) {
1365  this.setTicketKeys(Buffer.from(data.ticketKeys, 'hex'));
1366};
1367
1368
1369Server.prototype.getTicketKeys = function getTicketKeys() {
1370  return this._sharedCreds.context.getTicketKeys();
1371};
1372
1373
1374Server.prototype.setTicketKeys = function setTicketKeys(keys) {
1375  validateBuffer(keys);
1376  assert(keys.byteLength === 48,
1377         'Session ticket keys must be a 48-byte buffer');
1378  this._sharedCreds.context.setTicketKeys(keys);
1379};
1380
1381
1382Server.prototype.setOptions = deprecate(function(options) {
1383  this.requestCert = options.requestCert === true;
1384  this.rejectUnauthorized = options.rejectUnauthorized !== false;
1385
1386  if (options.pfx) this.pfx = options.pfx;
1387  if (options.key) this.key = options.key;
1388  if (options.passphrase) this.passphrase = options.passphrase;
1389  if (options.cert) this.cert = options.cert;
1390  if (options.clientCertEngine)
1391    this.clientCertEngine = options.clientCertEngine;
1392  if (options.ca) this.ca = options.ca;
1393  if (options.minVersion) this.minVersion = options.minVersion;
1394  if (options.maxVersion) this.maxVersion = options.maxVersion;
1395  if (options.secureProtocol) this.secureProtocol = options.secureProtocol;
1396  if (options.crl) this.crl = options.crl;
1397  if (options.ciphers) this.ciphers = options.ciphers;
1398  if (options.ecdhCurve !== undefined)
1399    this.ecdhCurve = options.ecdhCurve;
1400  if (options.dhparam) this.dhparam = options.dhparam;
1401  if (options.sessionTimeout) this.sessionTimeout = options.sessionTimeout;
1402  if (options.ticketKeys) this.ticketKeys = options.ticketKeys;
1403  const secureOptions = options.secureOptions || 0;
1404  if (options.honorCipherOrder !== undefined)
1405    this.honorCipherOrder = !!options.honorCipherOrder;
1406  else
1407    this.honorCipherOrder = true;
1408  if (secureOptions) this.secureOptions = secureOptions;
1409  if (options.ALPNProtocols)
1410    tls.convertALPNProtocols(options.ALPNProtocols, this);
1411  if (options.sessionIdContext) {
1412    this.sessionIdContext = options.sessionIdContext;
1413  } else {
1414    this.sessionIdContext = crypto.createHash('sha1')
1415                                  .update(process.argv.join(' '))
1416                                  .digest('hex')
1417                                  .slice(0, 32);
1418  }
1419  if (options.pskCallback) this[kPskCallback] = options.pskCallback;
1420  if (options.pskIdentityHint) this[kPskIdentityHint] = options.pskIdentityHint;
1421  if (options.sigalgs) this.sigalgs = options.sigalgs;
1422  if (options.privateKeyIdentifier !== undefined)
1423    this.privateKeyIdentifier = options.privateKeyIdentifier;
1424  if (options.privateKeyEngine !== undefined)
1425    this.privateKeyEngine = options.privateKeyEngine;
1426}, 'Server.prototype.setOptions() is deprecated', 'DEP0122');
1427
1428// SNI Contexts High-Level API
1429Server.prototype.addContext = function(servername, context) {
1430  if (!servername) {
1431    throw new ERR_TLS_REQUIRED_SERVER_NAME();
1432  }
1433
1434  const re = new RegExp('^' +
1435                      servername.replace(/([.^$+?\-\\[\]{}])/g, '\\$1')
1436                                .replace(/\*/g, '[^.]*') +
1437                      '$');
1438  this._contexts.push([re, tls.createSecureContext(context).context]);
1439};
1440
1441Server.prototype[EE.captureRejectionSymbol] = function(
1442  err, event, sock) {
1443
1444  switch (event) {
1445    case 'secureConnection':
1446      sock.destroy(err);
1447      break;
1448    default:
1449      net.Server.prototype[SymbolFor('nodejs.rejection')]
1450        .call(this, err, event, sock);
1451  }
1452};
1453
1454function SNICallback(servername, callback) {
1455  const contexts = this.server._contexts;
1456
1457  for (const elem of contexts) {
1458    if (elem[0].test(servername)) {
1459      callback(null, elem[1]);
1460      return;
1461    }
1462  }
1463
1464  callback(null, undefined);
1465}
1466
1467
1468// Target API:
1469//
1470//  let s = tls.connect({port: 8000, host: "google.com"}, function() {
1471//    if (!s.authorized) {
1472//      s.destroy();
1473//      return;
1474//    }
1475//
1476//    // s.socket;
1477//
1478//    s.end("hello world\n");
1479//  });
1480//
1481//
1482function normalizeConnectArgs(listArgs) {
1483  const args = net._normalizeArgs(listArgs);
1484  const options = args[0];
1485  const cb = args[1];
1486
1487  // If args[0] was options, then normalize dealt with it.
1488  // If args[0] is port, or args[0], args[1] is host, port, we need to
1489  // find the options and merge them in, normalize's options has only
1490  // the host/port/path args that it knows about, not the tls options.
1491  // This means that options.host overrides a host arg.
1492  if (listArgs[1] !== null && typeof listArgs[1] === 'object') {
1493    ObjectAssign(options, listArgs[1]);
1494  } else if (listArgs[2] !== null && typeof listArgs[2] === 'object') {
1495    ObjectAssign(options, listArgs[2]);
1496  }
1497
1498  return cb ? [options, cb] : [options];
1499}
1500
1501function onConnectSecure() {
1502  const options = this[kConnectOptions];
1503
1504  // Check the size of DHE parameter above minimum requirement
1505  // specified in options.
1506  const ekeyinfo = this.getEphemeralKeyInfo();
1507  if (ekeyinfo.type === 'DH' && ekeyinfo.size < options.minDHSize) {
1508    const err = new ERR_TLS_DH_PARAM_SIZE(ekeyinfo.size);
1509    debug('client emit:', err);
1510    this.emit('error', err);
1511    this.destroy();
1512    return;
1513  }
1514
1515  let verifyError = this._handle.verifyError();
1516
1517  // Verify that server's identity matches it's certificate's names
1518  // Unless server has resumed our existing session
1519  if (!verifyError && !this.isSessionReused()) {
1520    const hostname = options.servername ||
1521                   options.host ||
1522                   (options.socket && options.socket._host) ||
1523                   'localhost';
1524    const cert = this.getPeerCertificate(true);
1525    verifyError = options.checkServerIdentity(hostname, cert);
1526  }
1527
1528  if (verifyError) {
1529    this.authorized = false;
1530    this.authorizationError = verifyError.code || verifyError.message;
1531
1532    // rejectUnauthorized property can be explicitly defined as `undefined`
1533    // causing the assignment to default value (`true`) fail. Before assigning
1534    // it to the tlssock connection options, explicitly check if it is false
1535    // and update rejectUnauthorized property. The property gets used by
1536    // TLSSocket connection handler to allow or reject connection if
1537    // unauthorized.
1538    // This check is potentially redundant, however it is better to keep it
1539    // in case the option object gets modified somewhere.
1540    if (options.rejectUnauthorized !== false) {
1541      this.destroy(verifyError);
1542      return;
1543    }
1544    debug('client emit secureConnect. rejectUnauthorized: %s, ' +
1545          'authorizationError: %s', options.rejectUnauthorized,
1546          this.authorizationError);
1547    this.secureConnecting = false;
1548    this.emit('secureConnect');
1549  } else {
1550    this.authorized = true;
1551    debug('client emit secureConnect. authorized:', this.authorized);
1552    this.secureConnecting = false;
1553    this.emit('secureConnect');
1554  }
1555
1556  this[kIsVerified] = true;
1557  const session = this[kPendingSession];
1558  this[kPendingSession] = null;
1559  if (session)
1560    this.emit('session', session);
1561
1562  this.removeListener('end', onConnectEnd);
1563}
1564
1565function onConnectEnd() {
1566  // NOTE: This logic is shared with _http_client.js
1567  if (!this._hadError) {
1568    const options = this[kConnectOptions];
1569    this._hadError = true;
1570    const error = connResetException('Client network socket disconnected ' +
1571                                     'before secure TLS connection was ' +
1572                                     'established');
1573    error.path = options.path;
1574    error.host = options.host;
1575    error.port = options.port;
1576    error.localAddress = options.localAddress;
1577    this.destroy(error);
1578  }
1579}
1580
1581// Arguments: [port,] [host,] [options,] [cb]
1582exports.connect = function connect(...args) {
1583  args = normalizeConnectArgs(args);
1584  let options = args[0];
1585  const cb = args[1];
1586  const allowUnauthorized = getAllowUnauthorized();
1587
1588  options = {
1589    rejectUnauthorized: !allowUnauthorized,
1590    ciphers: tls.DEFAULT_CIPHERS,
1591    checkServerIdentity: tls.checkServerIdentity,
1592    minDHSize: 1024,
1593    ...options
1594  };
1595
1596  if (!options.keepAlive)
1597    options.singleUse = true;
1598
1599  assert(typeof options.checkServerIdentity === 'function');
1600  assert(typeof options.minDHSize === 'number',
1601         'options.minDHSize is not a number: ' + options.minDHSize);
1602  assert(options.minDHSize > 0,
1603         'options.minDHSize is not a positive number: ' +
1604         options.minDHSize);
1605
1606  const context = options.secureContext || tls.createSecureContext(options);
1607
1608  const tlssock = new TLSSocket(options.socket, {
1609    allowHalfOpen: options.allowHalfOpen,
1610    pipe: !!options.path,
1611    secureContext: context,
1612    isServer: false,
1613    requestCert: true,
1614    rejectUnauthorized: options.rejectUnauthorized !== false,
1615    session: options.session,
1616    ALPNProtocols: options.ALPNProtocols,
1617    requestOCSP: options.requestOCSP,
1618    enableTrace: options.enableTrace,
1619    pskCallback: options.pskCallback,
1620    highWaterMark: options.highWaterMark,
1621    onread: options.onread,
1622  });
1623
1624  // rejectUnauthorized property can be explicitly defined as `undefined`
1625  // causing the assignment to default value (`true`) fail. Before assigning
1626  // it to the tlssock connection options, explicitly check if it is false
1627  // and update rejectUnauthorized property. The property gets used by TLSSocket
1628  // connection handler to allow or reject connection if unauthorized
1629  options.rejectUnauthorized = options.rejectUnauthorized !== false;
1630
1631  tlssock[kConnectOptions] = options;
1632
1633  if (cb)
1634    tlssock.once('secureConnect', cb);
1635
1636  if (!options.socket) {
1637    // If user provided the socket, it's their responsibility to manage its
1638    // connectivity. If we created one internally, we connect it.
1639    if (options.timeout) {
1640      tlssock.setTimeout(options.timeout);
1641    }
1642
1643    tlssock.connect(options, tlssock._start);
1644  }
1645
1646  tlssock._releaseControl();
1647
1648  if (options.session)
1649    tlssock.setSession(options.session);
1650
1651  if (options.servername) {
1652    if (!ipServernameWarned && net.isIP(options.servername)) {
1653      process.emitWarning(
1654        'Setting the TLS ServerName to an IP address is not permitted by ' +
1655        'RFC 6066. This will be ignored in a future version.',
1656        'DeprecationWarning',
1657        'DEP0123'
1658      );
1659      ipServernameWarned = true;
1660    }
1661    tlssock.setServername(options.servername);
1662  }
1663
1664  if (options.socket)
1665    tlssock._start();
1666
1667  tlssock.on('secure', onConnectSecure);
1668  tlssock.prependListener('end', onConnectEnd);
1669
1670  return tlssock;
1671};
1672