2222'use strict' ;
2323
2424const {
25+ ArrayBufferIsView,
2526 ArrayIsArray,
2627 ArrayPrototypeIndexOf,
2728 ArrayPrototypePush,
@@ -35,6 +36,8 @@ const {
3536 ObjectSetPrototypeOf,
3637 ReflectApply,
3738 ReflectConstruct,
39+ SafeWeakMap,
40+ String,
3841 Symbol,
3942 SymbolAsyncDispose,
4043} = primordials ;
@@ -54,6 +57,8 @@ const {
5457} = require ( 'internal/tls/secure-context' ) ;
5558const kPerRequestCheckServerIdentity = Symbol ( 'per-request checkServerIdentity' ) ;
5659let perRequestCheckServerIdentityIndex = 0 ;
60+ const tlsPolicyObjectIds = new SafeWeakMap ( ) ;
61+ let tlsPolicyObjectId = 0 ;
5762const {
5863 kProxyConfig,
5964 checkShouldUseProxy,
@@ -514,16 +519,65 @@ Agent.prototype.keepSocketAlive = function keepSocketAlive(socket) {
514519 return FunctionPrototypeCall ( HttpAgent . prototype . keepSocketAlive , this , socket ) ;
515520} ;
516521
517- function getPfxAgentKey ( pfx , passphrase ) {
518- if ( ! ArrayIsArray ( pfx ) )
519- return pfx ;
522+ // Encode values with their type and length so distinct TLS policies cannot
523+ // collapse to the same Agent key. Use stable identities for opaque objects.
524+ function getTlsOptionKey ( value ) {
525+ if ( value === undefined )
526+ return '' ;
527+ if ( value === null )
528+ return 'n' ;
529+
530+ if ( ArrayIsArray ( value ) ) {
531+ let key = `a${ value . length } ` ;
532+ for ( let i = 0 ; i < value . length ; i ++ ) {
533+ const itemKey = getTlsOptionKey ( value [ i ] ) ;
534+ key += `:${ itemKey . length } :${ itemKey } ` ;
535+ }
536+ return key ;
537+ }
538+
539+ if ( ArrayBufferIsView ( value ) ) {
540+ const bytes = Buffer . from ( value . buffer , value . byteOffset , value . byteLength ) ;
541+ return `v${ bytes . byteLength } :${ bytes . toString ( 'base64' ) } ` ;
542+ }
543+
544+ const type = typeof value ;
545+ if ( type === 'object' || type === 'function' ) {
546+ let id = tlsPolicyObjectIds . get ( value ) ;
547+ if ( id === undefined ) {
548+ id = ++ tlsPolicyObjectId ;
549+ tlsPolicyObjectIds . set ( value , id ) ;
550+ }
551+ return `o${ id } ` ;
552+ }
553+
554+ const string = String ( value ) ;
555+ return `${ type [ 0 ] } ${ string . length } :${ string } ` ;
556+ }
557+
558+ function getKeyMaterialAgentKey ( value , passphrase , property ,
559+ useTruthyProperties ) {
560+ if ( ! ArrayIsArray ( value ) ) {
561+ return `${ getTlsOptionKey ( value ) } :${ getTlsOptionKey ( passphrase ) } ` ;
562+ }
520563
521- let key = '' ;
522- for ( let i = 0 ; i < pfx . length ; i ++ ) {
523- const value = pfx [ i ] ;
524- const raw = value ?. buf || value ;
525- const pass = value ?. passphrase || passphrase ;
526- key += `:${ raw } :${ pass } ` ;
564+ let key = `a${ value . length } ` ;
565+ for ( let i = 0 ; i < value . length ; i ++ ) {
566+ const item = value [ i ] ;
567+ let raw = item ;
568+ let pass = passphrase ;
569+ if ( item !== null && typeof item === 'object' &&
570+ ! ArrayBufferIsView ( item ) ) {
571+ if ( useTruthyProperties ) {
572+ raw = item [ property ] || item ;
573+ pass = item . passphrase || passphrase ;
574+ } else {
575+ raw = item [ property ] !== undefined ? item [ property ] : item ;
576+ pass = item . passphrase !== undefined ? item . passphrase : passphrase ;
577+ }
578+ }
579+ const itemKey = `${ getTlsOptionKey ( raw ) } :${ getTlsOptionKey ( pass ) } ` ;
580+ key += `:${ itemKey . length } :${ itemKey } ` ;
527581 }
528582 return key ;
529583}
@@ -544,23 +598,27 @@ Agent.prototype.getName = function getName(options = kEmptyObject) {
544598
545599 name += ':' ;
546600 if ( options . ca )
547- name += options . ca ;
601+ name += getTlsOptionKey ( options . ca ) ;
548602
549603 name += ':' ;
550604 if ( options . cert )
551- name += options . cert ;
605+ name += getTlsOptionKey ( options . cert ) ;
552606
553607 name += ':' ;
554608 if ( options . ciphers )
555609 name += options . ciphers ;
556610
557611 name += ':' ;
558- if ( options . key )
559- name += options . key ;
612+ if ( options . key ) {
613+ name += getKeyMaterialAgentKey (
614+ options . key , options . passphrase , 'pem' , false ) ;
615+ }
560616
561617 name += ':' ;
562- if ( options . pfx )
563- name += getPfxAgentKey ( options . pfx , options . passphrase ) ;
618+ if ( options . pfx ) {
619+ name += getKeyMaterialAgentKey (
620+ options . pfx , options . passphrase , 'buf' , true ) ;
621+ }
564622
565623 name += ':' ;
566624 if ( options . rejectUnauthorized !== undefined )
@@ -584,7 +642,7 @@ Agent.prototype.getName = function getName(options = kEmptyObject) {
584642
585643 name += ':' ;
586644 if ( options . crl )
587- name += options . crl ;
645+ name += getTlsOptionKey ( options . crl ) ;
588646
589647 name += ':' ;
590648 if ( options . honorCipherOrder !== undefined )
@@ -610,6 +668,38 @@ Agent.prototype.getName = function getName(options = kEmptyObject) {
610668 if ( options . sigalgs )
611669 name += JSONStringify ( options . sigalgs ) ;
612670
671+ name += ':' ;
672+ if ( options . secureContext )
673+ name += getTlsOptionKey ( options . secureContext ) ;
674+
675+ name += ':' ;
676+ if ( options . allowPartialTrustChain !== undefined )
677+ name += getTlsOptionKey ( options . allowPartialTrustChain ) ;
678+
679+ name += ':' ;
680+ if ( options . ALPNProtocols )
681+ name += getTlsOptionKey ( options . ALPNProtocols ) ;
682+
683+ name += ':' ;
684+ if ( options . certificateCompression )
685+ name += getTlsOptionKey ( options . certificateCompression ) ;
686+
687+ name += ':' ;
688+ if ( options . minDHSize !== undefined )
689+ name += getTlsOptionKey ( options . minDHSize ) ;
690+
691+ name += ':' ;
692+ if ( options . pskCallback )
693+ name += getTlsOptionKey ( options . pskCallback ) ;
694+
695+ name += ':' ;
696+ if ( options . requestOCSP !== undefined )
697+ name += getTlsOptionKey ( options . requestOCSP ) ;
698+
699+ name += ':' ;
700+ if ( options . session )
701+ name += getTlsOptionKey ( options . session ) ;
702+
613703 if ( options [ kPerRequestCheckServerIdentity ] )
614704 name += `:${ options [ kPerRequestCheckServerIdentity ] } ` ;
615705
0 commit comments