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