Skip to content

Commit fb56c4c

Browse files
github-actions[bot]wfurtscalablecory
authored
[release/6.0] disable sending NT Authority in TLS handshake if specific trust was specified (#61713)
* diable sending NT Authority if specific trust was specified * feedback from review * add missing file * Apply suggestions from code review Co-authored-by: Cory Nelson <[email protected]> * one more style update Co-authored-by: wfurt <[email protected]> Co-authored-by: Cory Nelson <[email protected]>
1 parent 923ec4d commit fb56c4c

3 files changed

Lines changed: 37 additions & 11 deletions

File tree

src/libraries/System.Net.Security/src/System/Net/Security/SecureChannel.cs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -695,11 +695,13 @@ private bool AcquireServerCredentials(ref byte[]? thumbPrint)
695695
_sslAuthenticationOptions.CertificateContext = SslStreamCertificateContext.Create(selectedCert);
696696
}
697697

698+
Debug.Assert(_sslAuthenticationOptions.CertificateContext != null);
698699
//
699700
// Note selectedCert is a safe ref possibly cloned from the user passed Cert object
700701
//
701702
byte[] guessedThumbPrint = selectedCert.GetCertHash();
702-
SafeFreeCredentials? cachedCredentialHandle = SslSessionsCache.TryCachedCredential(guessedThumbPrint, _sslAuthenticationOptions.EnabledSslProtocols, _sslAuthenticationOptions.IsServer, _sslAuthenticationOptions.EncryptionPolicy);
703+
bool sendTrustedList = _sslAuthenticationOptions.CertificateContext!.Trust?._sendTrustInHandshake ?? false;
704+
SafeFreeCredentials? cachedCredentialHandle = SslSessionsCache.TryCachedCredential(guessedThumbPrint, _sslAuthenticationOptions.EnabledSslProtocols, _sslAuthenticationOptions.IsServer, _sslAuthenticationOptions.EncryptionPolicy, sendTrustedList);
703705

704706
if (cachedCredentialHandle != null)
705707
{
@@ -763,6 +765,7 @@ private SecurityStatusPal GenerateToken(ReadOnlySpan<byte> inputBuffer, ref byte
763765
byte[]? result = Array.Empty<byte>();
764766
SecurityStatusPal status = default;
765767
bool cachedCreds = false;
768+
bool sendTrustList = false;
766769
byte[]? thumbPrint = null;
767770

768771
//
@@ -779,6 +782,11 @@ private SecurityStatusPal GenerateToken(ReadOnlySpan<byte> inputBuffer, ref byte
779782
cachedCreds = _sslAuthenticationOptions.IsServer
780783
? AcquireServerCredentials(ref thumbPrint)
781784
: AcquireClientCredentials(ref thumbPrint);
785+
786+
if (cachedCreds && _sslAuthenticationOptions.IsServer)
787+
{
788+
sendTrustList = _sslAuthenticationOptions.CertificateContext?.Trust?._sendTrustInHandshake ?? false;
789+
}
782790
}
783791

784792
if (_sslAuthenticationOptions.IsServer)
@@ -820,7 +828,7 @@ private SecurityStatusPal GenerateToken(ReadOnlySpan<byte> inputBuffer, ref byte
820828
//
821829
if (!cachedCreds && _securityContext != null && !_securityContext.IsInvalid && _credentialsHandle != null && !_credentialsHandle.IsInvalid)
822830
{
823-
SslSessionsCache.CacheCredential(_credentialsHandle, thumbPrint, _sslAuthenticationOptions.EnabledSslProtocols, _sslAuthenticationOptions.IsServer, _sslAuthenticationOptions.EncryptionPolicy);
831+
SslSessionsCache.CacheCredential(_credentialsHandle, thumbPrint, _sslAuthenticationOptions.EnabledSslProtocols, _sslAuthenticationOptions.IsServer, _sslAuthenticationOptions.EncryptionPolicy, sendTrustList);
824832
}
825833
}
826834
}

src/libraries/System.Net.Security/src/System/Net/Security/SslSessionsCache.cs

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,18 +25,20 @@ internal static class SslSessionsCache
2525
private readonly int _allowedProtocols;
2626
private readonly EncryptionPolicy _encryptionPolicy;
2727
private readonly bool _isServerMode;
28+
private readonly bool _sendTrustList;
2829

2930
//
3031
// SECURITY: X509Certificate.GetCertHash() is virtual hence before going here,
3132
// the caller of this ctor has to ensure that a user cert object was inspected and
3233
// optionally cloned.
3334
//
34-
internal SslCredKey(byte[]? thumbPrint, int allowedProtocols, bool isServerMode, EncryptionPolicy encryptionPolicy)
35+
internal SslCredKey(byte[]? thumbPrint, int allowedProtocols, bool isServerMode, EncryptionPolicy encryptionPolicy, bool sendTrustList)
3536
{
3637
_thumbPrint = thumbPrint ?? Array.Empty<byte>();
3738
_allowedProtocols = allowedProtocols;
3839
_encryptionPolicy = encryptionPolicy;
3940
_isServerMode = isServerMode;
41+
_sendTrustList = sendTrustList;
4042
}
4143

4244
public override int GetHashCode()
@@ -65,6 +67,7 @@ public override int GetHashCode()
6567
hashCode ^= _allowedProtocols;
6668
hashCode ^= (int)_encryptionPolicy;
6769
hashCode ^= _isServerMode ? 0x10000 : 0x20000;
70+
hashCode ^= _sendTrustList ? 0x40000 : 0x80000;
6871

6972
return hashCode;
7073
}
@@ -96,6 +99,11 @@ public bool Equals(SslCredKey other)
9699
return false;
97100
}
98101

102+
if (_sendTrustList != other._sendTrustList)
103+
{
104+
return false;
105+
}
106+
99107
for (int i = 0; i < thumbPrint.Length; ++i)
100108
{
101109
if (thumbPrint[i] != otherThumbPrint[i])
@@ -114,15 +122,15 @@ public bool Equals(SslCredKey other)
114122
// ATTN: The returned handle can be invalid, the callers of InitializeSecurityContext and AcceptSecurityContext
115123
// must be prepared to execute a back-out code if the call fails.
116124
//
117-
internal static SafeFreeCredentials? TryCachedCredential(byte[]? thumbPrint, SslProtocols sslProtocols, bool isServer, EncryptionPolicy encryptionPolicy)
125+
internal static SafeFreeCredentials? TryCachedCredential(byte[]? thumbPrint, SslProtocols sslProtocols, bool isServer, EncryptionPolicy encryptionPolicy, bool sendTrustList = false)
118126
{
119127
if (s_cachedCreds.IsEmpty)
120128
{
121129
if (NetEventSource.Log.IsEnabled()) NetEventSource.Info(null, $"Not found, Current Cache Count = {s_cachedCreds.Count}");
122130
return null;
123131
}
124132

125-
var key = new SslCredKey(thumbPrint, (int)sslProtocols, isServer, encryptionPolicy);
133+
var key = new SslCredKey(thumbPrint, (int)sslProtocols, isServer, encryptionPolicy, sendTrustList);
126134

127135
//SafeCredentialReference? cached;
128136
SafeFreeCredentials? credentials = GetCachedCredential(key);
@@ -147,7 +155,7 @@ public bool Equals(SslCredKey other)
147155
//
148156
// ATTN: The thumbPrint must be from inspected and possibly cloned user Cert object or we get a security hole in SslCredKey ctor.
149157
//
150-
internal static void CacheCredential(SafeFreeCredentials creds, byte[]? thumbPrint, SslProtocols sslProtocols, bool isServer, EncryptionPolicy encryptionPolicy)
158+
internal static void CacheCredential(SafeFreeCredentials creds, byte[]? thumbPrint, SslProtocols sslProtocols, bool isServer, EncryptionPolicy encryptionPolicy, bool sendTrustList = false)
151159
{
152160
Debug.Assert(creds != null, "creds == null");
153161

@@ -157,7 +165,7 @@ internal static void CacheCredential(SafeFreeCredentials creds, byte[]? thumbPri
157165
return;
158166
}
159167

160-
SslCredKey key = new SslCredKey(thumbPrint, (int)sslProtocols, isServer, encryptionPolicy);
168+
SslCredKey key = new SslCredKey(thumbPrint, (int)sslProtocols, isServer, encryptionPolicy, sendTrustList);
161169

162170
SafeFreeCredentials? credentials = GetCachedCredential(key);
163171

src/libraries/System.Net.Security/src/System/Net/Security/SslStreamPal.Windows.cs

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -124,8 +124,8 @@ public static SafeFreeCredentials AcquireCredentialsHandle(SslStreamCertificateC
124124
{
125125
// New crypto API supports TLS1.3 but it does not allow to force NULL encryption.
126126
SafeFreeCredentials cred = !UseNewCryptoApi || policy == EncryptionPolicy.NoEncryption ?
127-
AcquireCredentialsHandleSchannelCred(certificateContext?.Certificate, protocols, policy, isServer) :
128-
AcquireCredentialsHandleSchCredentials(certificateContext?.Certificate, protocols, policy, isServer);
127+
AcquireCredentialsHandleSchannelCred(certificateContext, protocols, policy, isServer) :
128+
AcquireCredentialsHandleSchCredentials(certificateContext, protocols, policy, isServer);
129129
if (certificateContext != null && certificateContext.Trust != null && certificateContext.Trust._sendTrustInHandshake)
130130
{
131131
AttachCertificateStore(cred, certificateContext.Trust._store!);
@@ -157,8 +157,9 @@ private static unsafe void AttachCertificateStore(SafeFreeCredentials cred, X509
157157

158158
// This is legacy crypto API used on .NET Framework and older Windows versions.
159159
// It only supports TLS up to 1.2
160-
public static unsafe SafeFreeCredentials AcquireCredentialsHandleSchannelCred(X509Certificate2? certificate, SslProtocols protocols, EncryptionPolicy policy, bool isServer)
160+
public static unsafe SafeFreeCredentials AcquireCredentialsHandleSchannelCred(SslStreamCertificateContext? certificateContext, SslProtocols protocols, EncryptionPolicy policy, bool isServer)
161161
{
162+
X509Certificate2? certificate = certificateContext?.Certificate;
162163
int protocolFlags = GetProtocolFlagsFromSslProtocols(protocols, isServer);
163164
Interop.SspiCli.SCHANNEL_CRED.Flags flags;
164165
Interop.SspiCli.CredentialUse direction;
@@ -183,6 +184,10 @@ public static unsafe SafeFreeCredentials AcquireCredentialsHandleSchannelCred(X5
183184
{
184185
direction = Interop.SspiCli.CredentialUse.SECPKG_CRED_INBOUND;
185186
flags = Interop.SspiCli.SCHANNEL_CRED.Flags.SCH_SEND_AUX_RECORD;
187+
if (certificateContext?.Trust?._sendTrustInHandshake == true)
188+
{
189+
flags |= Interop.SspiCli.SCHANNEL_CRED.Flags.SCH_CRED_NO_SYSTEM_MAPPER;
190+
}
186191
}
187192

188193
if (NetEventSource.Log.IsEnabled()) NetEventSource.Info($"flags=({flags}), ProtocolFlags=({protocolFlags}), EncryptionPolicy={policy}");
@@ -203,15 +208,20 @@ public static unsafe SafeFreeCredentials AcquireCredentialsHandleSchannelCred(X5
203208
}
204209

205210
// This function uses new crypto API to support TLS 1.3 and beyond.
206-
public static unsafe SafeFreeCredentials AcquireCredentialsHandleSchCredentials(X509Certificate2? certificate, SslProtocols protocols, EncryptionPolicy policy, bool isServer)
211+
public static unsafe SafeFreeCredentials AcquireCredentialsHandleSchCredentials(SslStreamCertificateContext? certificateContext, SslProtocols protocols, EncryptionPolicy policy, bool isServer)
207212
{
213+
X509Certificate2? certificate = certificateContext?.Certificate;
208214
int protocolFlags = GetProtocolFlagsFromSslProtocols(protocols, isServer);
209215
Interop.SspiCli.SCH_CREDENTIALS.Flags flags;
210216
Interop.SspiCli.CredentialUse direction;
211217
if (isServer)
212218
{
213219
direction = Interop.SspiCli.CredentialUse.SECPKG_CRED_INBOUND;
214220
flags = Interop.SspiCli.SCH_CREDENTIALS.Flags.SCH_SEND_AUX_RECORD;
221+
if (certificateContext?.Trust?._sendTrustInHandshake == true)
222+
{
223+
flags |= Interop.SspiCli.SCH_CREDENTIALS.Flags.SCH_CRED_NO_SYSTEM_MAPPER;
224+
}
215225
}
216226
else
217227
{

0 commit comments

Comments
 (0)