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 SymbolFor, 31} = primordials; 32 33const { 34 assertCrypto, 35 deprecate 36} = require('internal/util'); 37 38assertCrypto(); 39 40const { setImmediate } = require('timers'); 41const assert = require('internal/assert'); 42const crypto = require('crypto'); 43const EE = require('events'); 44const net = require('net'); 45const tls = require('tls'); 46const common = require('_tls_common'); 47const JSStreamSocket = require('internal/js_stream_socket'); 48const { Buffer } = require('buffer'); 49let debug = require('internal/util/debuglog').debuglog('tls', (fn) => { 50 debug = fn; 51}); 52const { TCP, constants: TCPConstants } = internalBinding('tcp_wrap'); 53const tls_wrap = internalBinding('tls_wrap'); 54const { Pipe, constants: PipeConstants } = internalBinding('pipe_wrap'); 55const { owner_symbol } = require('internal/async_hooks').symbols; 56const { isArrayBufferView } = require('internal/util/types'); 57const { SecureContext: NativeSecureContext } = internalBinding('crypto'); 58const { connResetException, codes } = require('internal/errors'); 59const { 60 ERR_INVALID_ARG_TYPE, 61 ERR_INVALID_ARG_VALUE, 62 ERR_INVALID_CALLBACK, 63 ERR_MULTIPLE_CALLBACK, 64 ERR_SOCKET_CLOSED, 65 ERR_TLS_DH_PARAM_SIZE, 66 ERR_TLS_HANDSHAKE_TIMEOUT, 67 ERR_TLS_INVALID_CONTEXT, 68 ERR_TLS_RENEGOTIATION_DISABLED, 69 ERR_TLS_REQUIRED_SERVER_NAME, 70 ERR_TLS_SESSION_ATTACK, 71 ERR_TLS_SNI_FROM_SERVER, 72 ERR_TLS_INVALID_STATE 73} = codes; 74const { onpskexchange: kOnPskExchange } = internalBinding('symbols'); 75const { 76 getOptionValue, 77 getAllowUnauthorized, 78} = require('internal/options'); 79const { 80 validateString, 81 validateBuffer, 82 validateUint32 83} = require('internal/validators'); 84const traceTls = getOptionValue('--trace-tls'); 85const tlsKeylog = getOptionValue('--tls-keylog'); 86const { appendFile } = require('fs'); 87const kConnectOptions = Symbol('connect-options'); 88const kDisableRenegotiation = Symbol('disable-renegotiation'); 89const kErrorEmitted = Symbol('error-emitted'); 90const kHandshakeTimeout = Symbol('handshake-timeout'); 91const kRes = Symbol('res'); 92const kSNICallback = Symbol('snicallback'); 93const kEnableTrace = Symbol('enableTrace'); 94const kPskCallback = Symbol('pskcallback'); 95const kPskIdentityHint = Symbol('pskidentityhint'); 96const kPendingSession = Symbol('pendingSession'); 97const kIsVerified = Symbol('verified'); 98 99const noop = () => {}; 100 101let ipServernameWarned = false; 102let tlsTracingWarned = false; 103 104// Server side times how long a handshake is taking to protect against slow 105// handshakes being used for DoS. 106function onhandshakestart(now) { 107 debug('server onhandshakestart'); 108 109 const { lastHandshakeTime } = this; 110 assert(now >= lastHandshakeTime, 111 `now (${now}) < lastHandshakeTime (${lastHandshakeTime})`); 112 113 this.lastHandshakeTime = now; 114 115 // If this is the first handshake we can skip the rest of the checks. 116 if (lastHandshakeTime === 0) 117 return; 118 119 if ((now - lastHandshakeTime) >= tls.CLIENT_RENEG_WINDOW * 1000) 120 this.handshakes = 1; 121 else 122 this.handshakes++; 123 124 const owner = this[owner_symbol]; 125 126 assert(owner._tlsOptions.isServer); 127 128 if (this.handshakes > tls.CLIENT_RENEG_LIMIT) { 129 owner._emitTLSError(new ERR_TLS_SESSION_ATTACK()); 130 return; 131 } 132 133 if (owner[kDisableRenegotiation]) 134 owner._emitTLSError(new ERR_TLS_RENEGOTIATION_DISABLED()); 135} 136 137function onhandshakedone() { 138 debug('server onhandshakedone'); 139 140 const owner = this[owner_symbol]; 141 assert(owner._tlsOptions.isServer); 142 143 // `newSession` callback wasn't called yet 144 if (owner._newSessionPending) { 145 owner._securePending = true; 146 return; 147 } 148 149 owner._finishInit(); 150} 151 152 153function loadSession(hello) { 154 debug('server onclienthello', 155 'sessionid.len', hello.sessionId.length, 156 'ticket?', hello.tlsTicket 157 ); 158 const owner = this[owner_symbol]; 159 160 let once = false; 161 function onSession(err, session) { 162 debug('server resumeSession callback(err %j, sess? %s)', err, !!session); 163 if (once) 164 return owner.destroy(new ERR_MULTIPLE_CALLBACK()); 165 once = true; 166 167 if (err) 168 return owner.destroy(err); 169 170 if (owner._handle === null) 171 return owner.destroy(new ERR_SOCKET_CLOSED()); 172 173 owner._handle.loadSession(session); 174 // Session is loaded. End the parser to allow handshaking to continue. 175 owner._handle.endParser(); 176 } 177 178 if (hello.sessionId.length <= 0 || 179 hello.tlsTicket || 180 (owner.server && 181 !owner.server.emit('resumeSession', hello.sessionId, onSession))) { 182 // Sessions without identifiers can't be resumed. 183 // Sessions with tickets can be resumed directly from the ticket, no server 184 // session storage is necessary. 185 // Without a call to a resumeSession listener, a session will never be 186 // loaded, so end the parser to allow handshaking to continue. 187 owner._handle.endParser(); 188 } 189} 190 191 192function loadSNI(info) { 193 const owner = this[owner_symbol]; 194 const servername = info.servername; 195 if (!servername || !owner._SNICallback) 196 return requestOCSP(owner, info); 197 198 let once = false; 199 owner._SNICallback(servername, (err, context) => { 200 if (once) 201 return owner.destroy(new ERR_MULTIPLE_CALLBACK()); 202 once = true; 203 204 if (err) 205 return owner.destroy(err); 206 207 if (owner._handle === null) 208 return owner.destroy(new ERR_SOCKET_CLOSED()); 209 210 // TODO(indutny): eventually disallow raw `SecureContext` 211 if (context) 212 owner._handle.sni_context = context.context || context; 213 214 requestOCSP(owner, info); 215 }); 216} 217 218 219function requestOCSP(socket, info) { 220 if (!info.OCSPRequest || !socket.server) 221 return requestOCSPDone(socket); 222 223 let ctx = socket._handle.sni_context; 224 225 if (!ctx) { 226 ctx = socket.server._sharedCreds; 227 228 // TLS socket is using a `net.Server` instead of a tls.TLSServer. 229 // Some TLS properties like `server._sharedCreds` will not be present 230 if (!ctx) 231 return requestOCSPDone(socket); 232 } 233 234 // TODO(indutny): eventually disallow raw `SecureContext` 235 if (ctx.context) 236 ctx = ctx.context; 237 238 if (socket.server.listenerCount('OCSPRequest') === 0) { 239 return requestOCSPDone(socket); 240 } 241 242 let once = false; 243 const onOCSP = (err, response) => { 244 debug('server OCSPRequest done', 'handle?', !!socket._handle, 'once?', once, 245 'response?', !!response, 'err?', err); 246 if (once) 247 return socket.destroy(new ERR_MULTIPLE_CALLBACK()); 248 once = true; 249 250 if (err) 251 return socket.destroy(err); 252 253 if (socket._handle === null) 254 return socket.destroy(new ERR_SOCKET_CLOSED()); 255 256 if (response) 257 socket._handle.setOCSPResponse(response); 258 requestOCSPDone(socket); 259 }; 260 261 debug('server oncertcb emit OCSPRequest'); 262 socket.server.emit('OCSPRequest', 263 ctx.getCertificate(), 264 ctx.getIssuer(), 265 onOCSP); 266} 267 268function requestOCSPDone(socket) { 269 debug('server certcb done'); 270 try { 271 socket._handle.certCbDone(); 272 } catch (e) { 273 debug('server certcb done errored', e); 274 socket.destroy(e); 275 } 276} 277 278function onnewsessionclient(sessionId, session) { 279 debug('client emit session'); 280 const owner = this[owner_symbol]; 281 if (owner[kIsVerified]) { 282 owner.emit('session', session); 283 } else { 284 owner[kPendingSession] = session; 285 } 286} 287 288function onnewsession(sessionId, session) { 289 debug('onnewsession'); 290 const owner = this[owner_symbol]; 291 292 // TODO(@sam-github) no server to emit the event on, but handshake won't 293 // continue unless newSessionDone() is called, should it be, or is that 294 // situation unreachable, or only occurring during shutdown? 295 if (!owner.server) 296 return; 297 298 let once = false; 299 const done = () => { 300 debug('onnewsession done'); 301 if (once) 302 return; 303 once = true; 304 305 if (owner._handle === null) 306 return owner.destroy(new ERR_SOCKET_CLOSED()); 307 308 this.newSessionDone(); 309 310 owner._newSessionPending = false; 311 if (owner._securePending) 312 owner._finishInit(); 313 owner._securePending = false; 314 }; 315 316 owner._newSessionPending = true; 317 if (!owner.server.emit('newSession', sessionId, session, done)) 318 done(); 319} 320 321function onPskServerCallback(identity, maxPskLen) { 322 const owner = this[owner_symbol]; 323 const ret = owner[kPskCallback](owner, identity); 324 if (ret == null) 325 return undefined; 326 327 let psk; 328 if (isArrayBufferView(ret)) { 329 psk = ret; 330 } else { 331 if (typeof ret !== 'object') { 332 throw new ERR_INVALID_ARG_TYPE( 333 'ret', 334 ['Object', 'Buffer', 'TypedArray', 'DataView'], 335 ret 336 ); 337 } 338 psk = ret.psk; 339 validateBuffer(psk, 'psk'); 340 } 341 342 if (psk.length > maxPskLen) { 343 throw new ERR_INVALID_ARG_VALUE( 344 'psk', 345 psk, 346 `Pre-shared key exceeds ${maxPskLen} bytes` 347 ); 348 } 349 350 return psk; 351} 352 353function onPskClientCallback(hint, maxPskLen, maxIdentityLen) { 354 const owner = this[owner_symbol]; 355 const ret = owner[kPskCallback](hint); 356 if (ret == null) 357 return undefined; 358 359 if (typeof ret !== 'object') 360 throw new ERR_INVALID_ARG_TYPE('ret', 'Object', ret); 361 362 validateBuffer(ret.psk, 'psk'); 363 if (ret.psk.length > maxPskLen) { 364 throw new ERR_INVALID_ARG_VALUE( 365 'psk', 366 ret.psk, 367 `Pre-shared key exceeds ${maxPskLen} bytes` 368 ); 369 } 370 371 validateString(ret.identity, 'identity'); 372 if (Buffer.byteLength(ret.identity) > maxIdentityLen) { 373 throw new ERR_INVALID_ARG_VALUE( 374 'identity', 375 ret.identity, 376 `PSK identity exceeds ${maxIdentityLen} bytes` 377 ); 378 } 379 380 return { psk: ret.psk, identity: ret.identity }; 381} 382 383function onkeylog(line) { 384 debug('onkeylog'); 385 this[owner_symbol].emit('keylog', line); 386} 387 388function onocspresponse(resp) { 389 debug('client onocspresponse'); 390 this[owner_symbol].emit('OCSPResponse', resp); 391} 392 393function onerror(err) { 394 const owner = this[owner_symbol]; 395 debug('%s onerror %s had? %j', 396 owner._tlsOptions.isServer ? 'server' : 'client', err, 397 owner._hadError); 398 399 if (owner._hadError) 400 return; 401 402 owner._hadError = true; 403 404 // Destroy socket if error happened before handshake's finish 405 if (!owner._secureEstablished) { 406 // When handshake fails control is not yet released, 407 // so self._tlsError will return null instead of actual error 408 owner.destroy(err); 409 } else if (owner._tlsOptions.isServer && 410 owner._rejectUnauthorized && 411 /peer did not return a certificate/.test(err.message)) { 412 // Ignore server's authorization errors 413 owner.destroy(); 414 } else { 415 // Emit error 416 owner._emitTLSError(err); 417 } 418} 419 420// Used by both client and server TLSSockets to start data flowing from _handle, 421// read(0) causes a StreamBase::ReadStart, via Socket._read. 422function initRead(tlsSocket, socket) { 423 debug('%s initRead', 424 tlsSocket._tlsOptions.isServer ? 'server' : 'client', 425 'handle?', !!tlsSocket._handle, 426 'buffered?', !!socket && socket.readableLength 427 ); 428 // If we were destroyed already don't bother reading 429 if (!tlsSocket._handle) 430 return; 431 432 // Socket already has some buffered data - emulate receiving it 433 if (socket && socket.readableLength) { 434 let buf; 435 while ((buf = socket.read()) !== null) 436 tlsSocket._handle.receive(buf); 437 } 438 439 tlsSocket.read(0); 440} 441 442/** 443 * Provides a wrap of socket stream to do encrypted communication. 444 */ 445 446function TLSSocket(socket, opts) { 447 const tlsOptions = { ...opts }; 448 let enableTrace = tlsOptions.enableTrace; 449 450 if (enableTrace == null) { 451 enableTrace = traceTls; 452 453 if (enableTrace && !tlsTracingWarned) { 454 tlsTracingWarned = true; 455 process.emitWarning('Enabling --trace-tls can expose sensitive data in ' + 456 'the resulting log.'); 457 } 458 } else if (typeof enableTrace !== 'boolean') { 459 throw new ERR_INVALID_ARG_TYPE( 460 'options.enableTrace', 'boolean', enableTrace); 461 } 462 463 if (tlsOptions.ALPNProtocols) 464 tls.convertALPNProtocols(tlsOptions.ALPNProtocols, tlsOptions); 465 466 this._tlsOptions = tlsOptions; 467 this._secureEstablished = false; 468 this._securePending = false; 469 this._newSessionPending = false; 470 this._controlReleased = false; 471 this.secureConnecting = true; 472 this._SNICallback = null; 473 this.servername = null; 474 this.alpnProtocol = null; 475 this.authorized = false; 476 this.authorizationError = null; 477 this[kRes] = null; 478 this[kIsVerified] = false; 479 this[kPendingSession] = null; 480 481 let wrap; 482 if ((socket instanceof net.Socket && socket._handle) || !socket) { 483 // 1. connected socket 484 // 2. no socket, one will be created with net.Socket().connect 485 wrap = socket; 486 } else { 487 // 3. socket has no handle so it is js not c++ 488 // 4. unconnected sockets are wrapped 489 // TLS expects to interact from C++ with a net.Socket that has a C++ stream 490 // handle, but a JS stream doesn't have one. Wrap it up to make it look like 491 // a socket. 492 wrap = new JSStreamSocket(socket); 493 } 494 495 // Just a documented property to make secure sockets 496 // distinguishable from regular ones. 497 this.encrypted = true; 498 499 net.Socket.call(this, { 500 handle: this._wrapHandle(wrap), 501 allowHalfOpen: socket ? socket.allowHalfOpen : tlsOptions.allowHalfOpen, 502 pauseOnCreate: tlsOptions.pauseOnConnect, 503 manualStart: true, 504 highWaterMark: tlsOptions.highWaterMark, 505 onread: !socket ? tlsOptions.onread : null, 506 }); 507 508 // Proxy for API compatibility 509 this.ssl = this._handle; // C++ TLSWrap object 510 511 this.on('error', this._tlsError); 512 513 this._init(socket, wrap); 514 515 if (enableTrace && this._handle) 516 this._handle.enableTrace(); 517 518 // Read on next tick so the caller has a chance to setup listeners 519 process.nextTick(initRead, this, socket); 520} 521ObjectSetPrototypeOf(TLSSocket.prototype, net.Socket.prototype); 522ObjectSetPrototypeOf(TLSSocket, net.Socket); 523exports.TLSSocket = TLSSocket; 524 525const proxiedMethods = [ 526 'ref', 'unref', 'open', 'bind', 'listen', 'connect', 'bind6', 527 'connect6', 'getsockname', 'getpeername', 'setNoDelay', 'setKeepAlive', 528 'setSimultaneousAccepts', 'setBlocking', 529 530 // PipeWrap 531 'setPendingInstances', 532]; 533 534// Proxy HandleWrap, PipeWrap and TCPWrap methods 535function makeMethodProxy(name) { 536 return function methodProxy(...args) { 537 if (this._parent[name]) 538 return this._parent[name].apply(this._parent, args); 539 }; 540} 541for (const proxiedMethod of proxiedMethods) { 542 tls_wrap.TLSWrap.prototype[proxiedMethod] = 543 makeMethodProxy(proxiedMethod); 544} 545 546tls_wrap.TLSWrap.prototype.close = function close(cb) { 547 let ssl; 548 if (this[owner_symbol]) { 549 ssl = this[owner_symbol].ssl; 550 this[owner_symbol].ssl = null; 551 } 552 553 // Invoke `destroySSL` on close to clean up possibly pending write requests 554 // that may self-reference TLSWrap, leading to leak 555 const done = () => { 556 if (ssl) { 557 ssl.destroySSL(); 558 if (ssl._secureContext.singleUse) { 559 ssl._secureContext.context.close(); 560 ssl._secureContext.context = null; 561 } 562 } 563 if (cb) 564 cb(); 565 }; 566 567 if (this._parentWrap && this._parentWrap._handle === this._parent) { 568 this._parentWrap.once('close', done); 569 return this._parentWrap.destroy(); 570 } 571 return this._parent.close(done); 572}; 573 574TLSSocket.prototype.disableRenegotiation = function disableRenegotiation() { 575 this[kDisableRenegotiation] = true; 576}; 577 578TLSSocket.prototype._wrapHandle = function(wrap) { 579 let handle; 580 581 if (wrap) 582 handle = wrap._handle; 583 584 const options = this._tlsOptions; 585 if (!handle) { 586 handle = options.pipe ? 587 new Pipe(PipeConstants.SOCKET) : 588 new TCP(TCPConstants.SOCKET); 589 handle[owner_symbol] = this; 590 } 591 592 // Wrap socket's handle 593 const context = options.secureContext || 594 options.credentials || 595 tls.createSecureContext(options); 596 assert(handle.isStreamBase, 'handle must be a StreamBase'); 597 if (!(context.context instanceof NativeSecureContext)) { 598 throw new ERR_TLS_INVALID_CONTEXT('context'); 599 } 600 const res = tls_wrap.wrap(handle, context.context, !!options.isServer); 601 res._parent = handle; // C++ "wrap" object: TCPWrap, JSStream, ... 602 res._parentWrap = wrap; // JS object: net.Socket, JSStreamSocket, ... 603 res._secureContext = context; 604 res.reading = handle.reading; 605 this[kRes] = res; 606 defineHandleReading(this, handle); 607 608 this.on('close', onSocketCloseDestroySSL); 609 610 return res; 611}; 612 613// This eliminates a cyclic reference to TLSWrap 614// Ref: https://github.com/nodejs/node/commit/f7620fb96d339f704932f9bb9a0dceb9952df2d4 615function defineHandleReading(socket, handle) { 616 ObjectDefineProperty(handle, 'reading', { 617 get: () => { 618 return socket[kRes].reading; 619 }, 620 set: (value) => { 621 socket[kRes].reading = value; 622 } 623 }); 624} 625 626function onSocketCloseDestroySSL() { 627 // Make sure we are not doing it on OpenSSL's stack 628 setImmediate(destroySSL, this); 629 this[kRes] = null; 630} 631 632function destroySSL(self) { 633 self._destroySSL(); 634} 635 636TLSSocket.prototype._destroySSL = function _destroySSL() { 637 if (!this.ssl) return; 638 this.ssl.destroySSL(); 639 if (this.ssl._secureContext.singleUse) { 640 this.ssl._secureContext.context.close(); 641 this.ssl._secureContext.context = null; 642 } 643 this.ssl = null; 644 this[kPendingSession] = null; 645 this[kIsVerified] = false; 646}; 647 648// Constructor guts, arbitrarily factored out. 649let warnOnTlsKeylog = true; 650let warnOnTlsKeylogError = true; 651TLSSocket.prototype._init = function(socket, wrap) { 652 const options = this._tlsOptions; 653 const ssl = this._handle; 654 this.server = options.server; 655 656 debug('%s _init', 657 options.isServer ? 'server' : 'client', 658 'handle?', !!ssl 659 ); 660 661 // Clients (!isServer) always request a cert, servers request a client cert 662 // only on explicit configuration. 663 const requestCert = !!options.requestCert || !options.isServer; 664 const rejectUnauthorized = !!options.rejectUnauthorized; 665 666 this._requestCert = requestCert; 667 this._rejectUnauthorized = rejectUnauthorized; 668 if (requestCert || rejectUnauthorized) 669 ssl.setVerifyMode(requestCert, rejectUnauthorized); 670 671 // Only call .onkeylog if there is a keylog listener. 672 ssl.onkeylog = onkeylog; 673 this.on('newListener', keylogNewListener); 674 675 function keylogNewListener(event) { 676 if (event !== 'keylog') 677 return; 678 679 // Guard against enableKeylogCallback after destroy 680 if (!this._handle) return; 681 this._handle.enableKeylogCallback(); 682 683 // Remove this listener since it's no longer needed. 684 this.removeListener('newListener', keylogNewListener); 685 } 686 687 if (options.isServer) { 688 ssl.onhandshakestart = onhandshakestart; 689 ssl.onhandshakedone = onhandshakedone; 690 ssl.onclienthello = loadSession; 691 ssl.oncertcb = loadSNI; 692 ssl.onnewsession = onnewsession; 693 ssl.lastHandshakeTime = 0; 694 ssl.handshakes = 0; 695 696 if (this.server) { 697 if (this.server.listenerCount('resumeSession') > 0 || 698 this.server.listenerCount('newSession') > 0) { 699 // Also starts the client hello parser as a side effect. 700 ssl.enableSessionCallbacks(); 701 } 702 if (this.server.listenerCount('OCSPRequest') > 0) 703 ssl.enableCertCb(); 704 } 705 } else { 706 ssl.onhandshakestart = noop; 707 ssl.onhandshakedone = () => { 708 debug('client onhandshakedone'); 709 this._finishInit(); 710 }; 711 ssl.onocspresponse = onocspresponse; 712 713 if (options.session) 714 ssl.setSession(options.session); 715 716 ssl.onnewsession = onnewsessionclient; 717 718 // Only call .onnewsession if there is a session listener. 719 this.on('newListener', newListener); 720 721 function newListener(event) { 722 if (event !== 'session') 723 return; 724 725 // Guard against enableSessionCallbacks after destroy 726 if (!this._handle) return; 727 this._handle.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.privateKeyIdentifier = options.privateKeyIdentifier; 1329 this.privateKeyEngine = options.privateKeyEngine; 1330 1331 this._sharedCreds = tls.createSecureContext({ 1332 pfx: this.pfx, 1333 key: this.key, 1334 passphrase: this.passphrase, 1335 cert: this.cert, 1336 clientCertEngine: this.clientCertEngine, 1337 ca: this.ca, 1338 ciphers: this.ciphers, 1339 sigalgs: this.sigalgs, 1340 ecdhCurve: this.ecdhCurve, 1341 dhparam: this.dhparam, 1342 minVersion: this.minVersion, 1343 maxVersion: this.maxVersion, 1344 secureProtocol: this.secureProtocol, 1345 secureOptions: this.secureOptions, 1346 honorCipherOrder: this.honorCipherOrder, 1347 crl: this.crl, 1348 sessionIdContext: this.sessionIdContext, 1349 ticketKeys: this.ticketKeys, 1350 sessionTimeout: this.sessionTimeout, 1351 privateKeyIdentifier: this.privateKeyIdentifier, 1352 privateKeyEngine: this.privateKeyEngine, 1353 }); 1354}; 1355 1356 1357Server.prototype._getServerData = function() { 1358 return { 1359 ticketKeys: this.getTicketKeys().toString('hex') 1360 }; 1361}; 1362 1363 1364Server.prototype._setServerData = function(data) { 1365 this.setTicketKeys(Buffer.from(data.ticketKeys, 'hex')); 1366}; 1367 1368 1369Server.prototype.getTicketKeys = function getTicketKeys() { 1370 return this._sharedCreds.context.getTicketKeys(); 1371}; 1372 1373 1374Server.prototype.setTicketKeys = function setTicketKeys(keys) { 1375 validateBuffer(keys); 1376 assert(keys.byteLength === 48, 1377 'Session ticket keys must be a 48-byte buffer'); 1378 this._sharedCreds.context.setTicketKeys(keys); 1379}; 1380 1381 1382Server.prototype.setOptions = deprecate(function(options) { 1383 this.requestCert = options.requestCert === true; 1384 this.rejectUnauthorized = options.rejectUnauthorized !== false; 1385 1386 if (options.pfx) this.pfx = options.pfx; 1387 if (options.key) this.key = options.key; 1388 if (options.passphrase) this.passphrase = options.passphrase; 1389 if (options.cert) this.cert = options.cert; 1390 if (options.clientCertEngine) 1391 this.clientCertEngine = options.clientCertEngine; 1392 if (options.ca) this.ca = options.ca; 1393 if (options.minVersion) this.minVersion = options.minVersion; 1394 if (options.maxVersion) this.maxVersion = options.maxVersion; 1395 if (options.secureProtocol) this.secureProtocol = options.secureProtocol; 1396 if (options.crl) this.crl = options.crl; 1397 if (options.ciphers) this.ciphers = options.ciphers; 1398 if (options.ecdhCurve !== undefined) 1399 this.ecdhCurve = options.ecdhCurve; 1400 if (options.dhparam) this.dhparam = options.dhparam; 1401 if (options.sessionTimeout) this.sessionTimeout = options.sessionTimeout; 1402 if (options.ticketKeys) this.ticketKeys = options.ticketKeys; 1403 const secureOptions = options.secureOptions || 0; 1404 if (options.honorCipherOrder !== undefined) 1405 this.honorCipherOrder = !!options.honorCipherOrder; 1406 else 1407 this.honorCipherOrder = true; 1408 if (secureOptions) this.secureOptions = secureOptions; 1409 if (options.ALPNProtocols) 1410 tls.convertALPNProtocols(options.ALPNProtocols, this); 1411 if (options.sessionIdContext) { 1412 this.sessionIdContext = options.sessionIdContext; 1413 } else { 1414 this.sessionIdContext = crypto.createHash('sha1') 1415 .update(process.argv.join(' ')) 1416 .digest('hex') 1417 .slice(0, 32); 1418 } 1419 if (options.pskCallback) this[kPskCallback] = options.pskCallback; 1420 if (options.pskIdentityHint) this[kPskIdentityHint] = options.pskIdentityHint; 1421 if (options.sigalgs) this.sigalgs = options.sigalgs; 1422 if (options.privateKeyIdentifier !== undefined) 1423 this.privateKeyIdentifier = options.privateKeyIdentifier; 1424 if (options.privateKeyEngine !== undefined) 1425 this.privateKeyEngine = options.privateKeyEngine; 1426}, 'Server.prototype.setOptions() is deprecated', 'DEP0122'); 1427 1428// SNI Contexts High-Level API 1429Server.prototype.addContext = function(servername, context) { 1430 if (!servername) { 1431 throw new ERR_TLS_REQUIRED_SERVER_NAME(); 1432 } 1433 1434 const re = new RegExp('^' + 1435 servername.replace(/([.^$+?\-\\[\]{}])/g, '\\$1') 1436 .replace(/\*/g, '[^.]*') + 1437 '$'); 1438 this._contexts.push([re, tls.createSecureContext(context).context]); 1439}; 1440 1441Server.prototype[EE.captureRejectionSymbol] = function( 1442 err, event, sock) { 1443 1444 switch (event) { 1445 case 'secureConnection': 1446 sock.destroy(err); 1447 break; 1448 default: 1449 net.Server.prototype[SymbolFor('nodejs.rejection')] 1450 .call(this, err, event, sock); 1451 } 1452}; 1453 1454function SNICallback(servername, callback) { 1455 const contexts = this.server._contexts; 1456 1457 for (const elem of contexts) { 1458 if (elem[0].test(servername)) { 1459 callback(null, elem[1]); 1460 return; 1461 } 1462 } 1463 1464 callback(null, undefined); 1465} 1466 1467 1468// Target API: 1469// 1470// let s = tls.connect({port: 8000, host: "google.com"}, function() { 1471// if (!s.authorized) { 1472// s.destroy(); 1473// return; 1474// } 1475// 1476// // s.socket; 1477// 1478// s.end("hello world\n"); 1479// }); 1480// 1481// 1482function normalizeConnectArgs(listArgs) { 1483 const args = net._normalizeArgs(listArgs); 1484 const options = args[0]; 1485 const cb = args[1]; 1486 1487 // If args[0] was options, then normalize dealt with it. 1488 // If args[0] is port, or args[0], args[1] is host, port, we need to 1489 // find the options and merge them in, normalize's options has only 1490 // the host/port/path args that it knows about, not the tls options. 1491 // This means that options.host overrides a host arg. 1492 if (listArgs[1] !== null && typeof listArgs[1] === 'object') { 1493 ObjectAssign(options, listArgs[1]); 1494 } else if (listArgs[2] !== null && typeof listArgs[2] === 'object') { 1495 ObjectAssign(options, listArgs[2]); 1496 } 1497 1498 return cb ? [options, cb] : [options]; 1499} 1500 1501function onConnectSecure() { 1502 const options = this[kConnectOptions]; 1503 1504 // Check the size of DHE parameter above minimum requirement 1505 // specified in options. 1506 const ekeyinfo = this.getEphemeralKeyInfo(); 1507 if (ekeyinfo.type === 'DH' && ekeyinfo.size < options.minDHSize) { 1508 const err = new ERR_TLS_DH_PARAM_SIZE(ekeyinfo.size); 1509 debug('client emit:', err); 1510 this.emit('error', err); 1511 this.destroy(); 1512 return; 1513 } 1514 1515 let verifyError = this._handle.verifyError(); 1516 1517 // Verify that server's identity matches it's certificate's names 1518 // Unless server has resumed our existing session 1519 if (!verifyError && !this.isSessionReused()) { 1520 const hostname = options.servername || 1521 options.host || 1522 (options.socket && options.socket._host) || 1523 'localhost'; 1524 const cert = this.getPeerCertificate(true); 1525 verifyError = options.checkServerIdentity(hostname, cert); 1526 } 1527 1528 if (verifyError) { 1529 this.authorized = false; 1530 this.authorizationError = verifyError.code || verifyError.message; 1531 1532 // rejectUnauthorized property can be explicitly defined as `undefined` 1533 // causing the assignment to default value (`true`) fail. Before assigning 1534 // it to the tlssock connection options, explicitly check if it is false 1535 // and update rejectUnauthorized property. The property gets used by 1536 // TLSSocket connection handler to allow or reject connection if 1537 // unauthorized. 1538 // This check is potentially redundant, however it is better to keep it 1539 // in case the option object gets modified somewhere. 1540 if (options.rejectUnauthorized !== false) { 1541 this.destroy(verifyError); 1542 return; 1543 } 1544 debug('client emit secureConnect. rejectUnauthorized: %s, ' + 1545 'authorizationError: %s', options.rejectUnauthorized, 1546 this.authorizationError); 1547 this.secureConnecting = false; 1548 this.emit('secureConnect'); 1549 } else { 1550 this.authorized = true; 1551 debug('client emit secureConnect. authorized:', this.authorized); 1552 this.secureConnecting = false; 1553 this.emit('secureConnect'); 1554 } 1555 1556 this[kIsVerified] = true; 1557 const session = this[kPendingSession]; 1558 this[kPendingSession] = null; 1559 if (session) 1560 this.emit('session', session); 1561 1562 this.removeListener('end', onConnectEnd); 1563} 1564 1565function onConnectEnd() { 1566 // NOTE: This logic is shared with _http_client.js 1567 if (!this._hadError) { 1568 const options = this[kConnectOptions]; 1569 this._hadError = true; 1570 const error = connResetException('Client network socket disconnected ' + 1571 'before secure TLS connection was ' + 1572 'established'); 1573 error.path = options.path; 1574 error.host = options.host; 1575 error.port = options.port; 1576 error.localAddress = options.localAddress; 1577 this.destroy(error); 1578 } 1579} 1580 1581// Arguments: [port,] [host,] [options,] [cb] 1582exports.connect = function connect(...args) { 1583 args = normalizeConnectArgs(args); 1584 let options = args[0]; 1585 const cb = args[1]; 1586 const allowUnauthorized = getAllowUnauthorized(); 1587 1588 options = { 1589 rejectUnauthorized: !allowUnauthorized, 1590 ciphers: tls.DEFAULT_CIPHERS, 1591 checkServerIdentity: tls.checkServerIdentity, 1592 minDHSize: 1024, 1593 ...options 1594 }; 1595 1596 if (!options.keepAlive) 1597 options.singleUse = true; 1598 1599 assert(typeof options.checkServerIdentity === 'function'); 1600 assert(typeof options.minDHSize === 'number', 1601 'options.minDHSize is not a number: ' + options.minDHSize); 1602 assert(options.minDHSize > 0, 1603 'options.minDHSize is not a positive number: ' + 1604 options.minDHSize); 1605 1606 const context = options.secureContext || tls.createSecureContext(options); 1607 1608 const tlssock = new TLSSocket(options.socket, { 1609 allowHalfOpen: options.allowHalfOpen, 1610 pipe: !!options.path, 1611 secureContext: context, 1612 isServer: false, 1613 requestCert: true, 1614 rejectUnauthorized: options.rejectUnauthorized !== false, 1615 session: options.session, 1616 ALPNProtocols: options.ALPNProtocols, 1617 requestOCSP: options.requestOCSP, 1618 enableTrace: options.enableTrace, 1619 pskCallback: options.pskCallback, 1620 highWaterMark: options.highWaterMark, 1621 onread: options.onread, 1622 }); 1623 1624 // rejectUnauthorized property can be explicitly defined as `undefined` 1625 // causing the assignment to default value (`true`) fail. Before assigning 1626 // it to the tlssock connection options, explicitly check if it is false 1627 // and update rejectUnauthorized property. The property gets used by TLSSocket 1628 // connection handler to allow or reject connection if unauthorized 1629 options.rejectUnauthorized = options.rejectUnauthorized !== false; 1630 1631 tlssock[kConnectOptions] = options; 1632 1633 if (cb) 1634 tlssock.once('secureConnect', cb); 1635 1636 if (!options.socket) { 1637 // If user provided the socket, it's their responsibility to manage its 1638 // connectivity. If we created one internally, we connect it. 1639 if (options.timeout) { 1640 tlssock.setTimeout(options.timeout); 1641 } 1642 1643 tlssock.connect(options, tlssock._start); 1644 } 1645 1646 tlssock._releaseControl(); 1647 1648 if (options.session) 1649 tlssock.setSession(options.session); 1650 1651 if (options.servername) { 1652 if (!ipServernameWarned && net.isIP(options.servername)) { 1653 process.emitWarning( 1654 'Setting the TLS ServerName to an IP address is not permitted by ' + 1655 'RFC 6066. This will be ignored in a future version.', 1656 'DeprecationWarning', 1657 'DEP0123' 1658 ); 1659 ipServernameWarned = true; 1660 } 1661 tlssock.setServername(options.servername); 1662 } 1663 1664 if (options.socket) 1665 tlssock._start(); 1666 1667 tlssock.on('secure', onConnectSecure); 1668 tlssock.prependListener('end', onConnectEnd); 1669 1670 return tlssock; 1671}; 1672