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