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