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