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