Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

use new API on new windows to get TLS13 #37888

Merged
merged 10 commits into from
Jul 15, 2020
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ internal interface ISSPIInterface
int EnumerateSecurityPackages(out int pkgnum, out SafeFreeContextBuffer pkgArray);
int AcquireCredentialsHandle(string moduleName, Interop.SspiCli.CredentialUse usage, ref SafeSspiAuthDataHandle authdata, out SafeFreeCredentials outCredential);
int AcquireCredentialsHandle(string moduleName, Interop.SspiCli.CredentialUse usage, ref Interop.SspiCli.SCHANNEL_CRED authdata, out SafeFreeCredentials outCredential);
unsafe int AcquireCredentialsHandle(string moduleName, Interop.SspiCli.CredentialUse usage, Interop.SspiCli.SCH_CREDENTIALS* authdata, out SafeFreeCredentials outCredential);
stephentoub marked this conversation as resolved.
Show resolved Hide resolved
int AcquireDefaultCredential(string moduleName, Interop.SspiCli.CredentialUse usage, out SafeFreeCredentials outCredential);
int AcceptSecurityContext(SafeFreeCredentials? credential, ref SafeDeleteSslContext? context, InputSecurityBuffers inputBuffers, Interop.SspiCli.ContextFlags inFlags, Interop.SspiCli.Endianness endianness, ref SecurityBuffer outputBuffer, ref Interop.SspiCli.ContextFlags outFlags);
int InitializeSecurityContext(ref SafeFreeCredentials? credential, ref SafeDeleteSslContext? context, string? targetName, Interop.SspiCli.ContextFlags inFlags, Interop.SspiCli.Endianness endianness, InputSecurityBuffers inputBuffers, ref SecurityBuffer outputBuffer, ref Interop.SspiCli.ContextFlags outFlags);
Expand Down
100 changes: 100 additions & 0 deletions src/libraries/Common/src/Interop/Windows/SspiCli/Interop.SSPI.cs
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,92 @@ public enum Flags
}
}

[StructLayout(LayoutKind.Sequential)]
internal unsafe struct SCH_CREDENTIALS
{
public const int CurrentVersion = 0x5;

public int dwVersion;
public int dwCredformat;
public int cCreds;

// This is pointer to arry of CERT_CONTEXT*
// We do not use it directly in .NET. Instead, we wrap returned OS pointer in safe handle.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this comment needed? I'm not even sure what it means; we do use it.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the meaning was that we do not dereference or use CERT_CONTEXT in .NET. So it is pointer to a structure but that is hidden to PAL.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added that comment after your questions about IntPtr vs something strongly typed.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So the "it" in we dot not use it" is referring to CERT_CONTEXT rather than to paCred? That was my confusion.

But, even so, we are kind of using it, aren't we? X509Certificate.Handle must be a CERT_CONTEXT*; we're storing that into paCred, effectively storing a pointer to an array of one CERT_CONTEXT. So while we're not naming it as such, we are using it.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes. I assumed the "directly" would be a hint but obviously it is not clear. I was also thinking about also adding CERT_CONTEXT so we can see details in debugger but that is somewhat complicated with more pointers inside.
Maybe Windbg could do cast to native but I failed so far with VS.

public void* paCred;

public IntPtr hRootStore; // == always null, OTHERWISE NOT RELIABLE
public int cMappers;
public IntPtr aphMappers; // == always null, OTHERWISE NOT RELIABLE

public int dwSessionLifespan;
public SCH_CREDENTIALS.Flags dwFlags;
public int cTlsParameters;
public TLS_PARAMETERS* pTlsParameters;

[Flags]
public enum Flags
{
Zero = 0,
SCH_CRED_NO_SYSTEM_MAPPER = 0x02,
SCH_CRED_NO_SERVERNAME_CHECK = 0x04,
SCH_CRED_MANUAL_CRED_VALIDATION = 0x08,
SCH_CRED_NO_DEFAULT_CREDS = 0x10,
SCH_CRED_AUTO_CRED_VALIDATION = 0x20,
SCH_CRED_USE_DEFAULT_CREDS = 0x40,
SCH_DISABLE_RECONNECTS = 0x80,
SCH_CRED_REVOCATION_CHECK_END_CERT = 0x100,
SCH_CRED_REVOCATION_CHECK_CHAIN = 0x200,
SCH_CRED_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT = 0x400,
SCH_CRED_IGNORE_NO_REVOCATION_CHECK = 0x800,
SCH_CRED_IGNORE_REVOCATION_OFFLINE = 0x1000,
SCH_CRED_CACHE_ONLY_URL_RETRIEVAL_ON_CREATE = 0x2000,
SCH_SEND_ROOT_CERT = 0x40000,
SCH_SEND_AUX_RECORD = 0x00200000,
SCH_USE_STRONG_CRYPTO = 0x00400000,
SCH_USE_PRESHAREDKEY_ONLY = 0x800000,
SCH_ALLOW_NULL_ENCRYPTION = 0x02000000,
}
}

[StructLayout(LayoutKind.Sequential)]
internal unsafe struct TLS_PARAMETERS
{
public int cAlpnIds; // Valid for server applications only. Must be zero otherwise. Number of ALPN IDs in rgstrAlpnIds; set to 0 if applies to all.
public IntPtr rgstrAlpnIds; // Valid for server applications only. Must be NULL otherwise. Array of ALPN IDs that the following settings apply to; set to NULL if applies to all.
public uint grbitDisabledProtocols; // List protocols you DO NOT want negotiated.
public int cDisabledCrypto; // Number of CRYPTO_SETTINGS structures; set to 0 if there are none.
public CRYPTO_SETTINGS* pDisabledCrypto; // Array of CRYPTO_SETTINGS structures; set to NULL if there are none;
public TLS_PARAMETERS.Flags dwFlags; // Optional flags to pass; set to 0 if there are none.

[Flags]
public enum Flags
{
Zero = 0,
TLS_PARAMS_OPTIONAL = 0x01, // Valid for server applications only. Must be zero otherwise.
// TLS_PARAMETERS that will only be honored if they do not cause this server to terminate the handshake.
}
}

[StructLayout(LayoutKind.Sequential)]
internal unsafe struct CRYPTO_SETTINGS
{
public TlsAlgorithmUsage eAlgorithmUsage; // How this algorithm is being used.
public UNICODE_STRING* strCngAlgId; // CNG algorithm identifier.
public int cChainingModes; // Set to 0 if CNG algorithm does not have a chaining mode.
public UNICODE_STRING* rgstrChainingModes; // Set to NULL if CNG algorithm does not have a chaining mode.
public int dwMinBitLength; // Blacklist key sizes less than this. Set to 0 if not defined or CNG algorithm implies bit length.
public int dwMaxBitLength; // Blacklist key sizes greater than this. Set to 0 if not defined or CNG algorithm implies bit length.

public enum TlsAlgorithmUsage
{
TlsParametersCngAlgUsageKeyExchange, // Key exchange algorithm. RSA, ECHDE, DHE, etc.
TlsParametersCngAlgUsageSignature, // Signature algorithm. RSA, DSA, ECDSA, etc.
TlsParametersCngAlgUsageCipher, // Encryption algorithm. AES, DES, RC4, etc.
TlsParametersCngAlgUsageDigest, // Digest of cipher suite. SHA1, SHA256, SHA384, etc.
TlsParametersCngAlgUsageCertSig // Signature and/or hash used to sign certificate. RSA, DSA, ECDSA, SHA1, SHA256, etc.
}
}

[StructLayout(LayoutKind.Sequential)]
internal unsafe struct SecBuffer
{
Expand Down Expand Up @@ -344,6 +430,20 @@ internal static extern unsafe int AcquireCredentialsHandleW(
[Out] out long timeStamp
);

[DllImport(Interop.Libraries.SspiCli, ExactSpelling = true, CharSet = CharSet.Unicode, SetLastError = true)]
internal static extern unsafe int AcquireCredentialsHandleW(
[In] string? principal,
[In] string moduleName,
[In] int usage,
[In] void* logonID,
[In] SCH_CREDENTIALS* authData,
[In] void* keyCallback,
[In] void* keyArgument,
ref CredHandle handlePtr,
[Out] out long timeStamp
);


[DllImport(Interop.Libraries.SspiCli, ExactSpelling = true, SetLastError = true)]
internal static extern unsafe int InitializeSecurityContextW(
ref CredHandle credentialHandle,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,11 @@ public int AcquireCredentialsHandle(string moduleName, Interop.SspiCli.Credentia
return SafeFreeCredentials.AcquireCredentialsHandle(moduleName, usage, ref authdata, out outCredential);
}

public unsafe int AcquireCredentialsHandle(string moduleName, Interop.SspiCli.CredentialUse usage, Interop.SspiCli.SCH_CREDENTIALS* authdata, out SafeFreeCredentials outCredential)
{
return SafeFreeCredentials.AcquireCredentialsHandle(moduleName, usage, authdata, out outCredential);
}

public int AcceptSecurityContext(SafeFreeCredentials? credential, ref SafeDeleteSslContext? context, InputSecurityBuffers inputBuffers, Interop.SspiCli.ContextFlags inFlags, Interop.SspiCli.Endianness endianness, ref SecurityBuffer outputBuffer, ref Interop.SspiCli.ContextFlags outFlags)
{
return SafeDeleteContext.AcceptSecurityContext(ref credential, ref context, inFlags, endianness, inputBuffers, ref outputBuffer, ref outFlags);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,11 @@ public int AcquireCredentialsHandle(string moduleName, Interop.SspiCli.Credentia
return SafeFreeCredentials.AcquireCredentialsHandle(moduleName, usage, ref authdata, out outCredential);
}

public unsafe int AcquireCredentialsHandle(string moduleName, Interop.SspiCli.CredentialUse usage, Interop.SspiCli.SCH_CREDENTIALS* authdata, out SafeFreeCredentials outCredential)
{
return SafeFreeCredentials.AcquireCredentialsHandle(moduleName, usage, authdata, out outCredential);
}

public int AcceptSecurityContext(SafeFreeCredentials? credential, ref SafeDeleteSslContext? context, InputSecurityBuffers inputBuffers, Interop.SspiCli.ContextFlags inFlags, Interop.SspiCli.Endianness endianness, ref SecurityBuffer outputBuffer, ref Interop.SspiCli.ContextFlags outFlags)
{
return SafeDeleteContext.AcceptSecurityContext(ref credential, ref context, inFlags, endianness, inputBuffers, ref outputBuffer, ref outFlags);
Expand Down
22 changes: 18 additions & 4 deletions src/libraries/Common/src/Interop/Windows/SspiCli/SSPIWrapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -110,14 +110,28 @@ public static SafeFreeCredentials AcquireCredentialsHandle(ISSPIInterface secMod

public static SafeFreeCredentials AcquireCredentialsHandle(ISSPIInterface secModule, string package, Interop.SspiCli.CredentialUse intent, Interop.SspiCli.SCHANNEL_CRED scc)
{
if (NetEventSource.Log.IsEnabled()) NetEventSource.Log.AcquireCredentialsHandle(package, intent, scc);

SafeFreeCredentials? outCredential = null;
int errorCode = secModule.AcquireCredentialsHandle(
package,
intent,
ref scc,
out outCredential);
out SafeFreeCredentials outCredential);

if (errorCode != 0)
{
if (NetEventSource.IsEnabled) NetEventSource.Error(null, SR.Format(SR.net_log_operation_failed_with_error, nameof(AcquireCredentialsHandle), $"0x{errorCode:X}"));
throw new Win32Exception(errorCode);
}

return outCredential;
}

public static unsafe SafeFreeCredentials AcquireCredentialsHandle(ISSPIInterface secModule, string package, Interop.SspiCli.CredentialUse intent, Interop.SspiCli.SCH_CREDENTIALS* scc)
{
int errorCode = secModule.AcquireCredentialsHandle(
package,
intent,
scc,
out SafeFreeCredentials outCredential);

if (errorCode != 0)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,38 @@ public static unsafe int AcquireCredentialsHandle(

return errorCode;
}

public static unsafe int AcquireCredentialsHandle(
string package,
Interop.SspiCli.CredentialUse intent,
Interop.SspiCli.SCH_CREDENTIALS* authdata,
out SafeFreeCredentials outCredential)
{
long timeStamp;

outCredential = new SafeFreeCredential_SECURITY();

int errorCode = Interop.SspiCli.AcquireCredentialsHandleW(
null,
package,
(int)intent,
null,
authdata,
null,
null,
ref outCredential._handle,
out timeStamp);

if (NetEventSource.IsEnabled) NetEventSource.Verbose(null, $"{nameof(Interop.SspiCli.AcquireCredentialsHandleW)} returns 0x{errorCode:x}, handle = {outCredential}");

if (errorCode != 0)
{
outCredential.SetHandleAsInvalid();
}

return errorCode;
}

}

//
Expand Down
2 changes: 2 additions & 0 deletions src/libraries/System.Net.Http/src/System.Net.Http.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -429,6 +429,8 @@
<Compile Include="System\Net\Http\SocketsHttpHandler\CurrentUserIdentityProvider.Windows.cs" />
<Compile Include="$(CommonPath)\Interop\Windows\Interop.Libraries.cs"
Link="Common\Interop\Windows\Interop.Libraries.cs" />
<Compile Include="$(CommonPath)Interop\Windows\Interop.UNICODE_STRING.cs"
Link="Common\Interop\Windows\Interop.UNICODE_STRING.cs" />
<Compile Include="$(CommonPath)\Interop\Windows\Crypt32\Interop.CertEnumCertificatesInStore.cs"
Link="Common\Interop\Windows\Crypt32\Interop.CertEnumCertificatesInStore.cs" />
<Compile Include="$(CommonPath)\Interop\Windows\Crypt32\Interop.certificates_types.cs"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,8 @@
<Compile Include="System\Net\Windows\WebSockets\WebSocketProtocolComponent.cs" />
<Compile Include="$(CommonPath)Interop\Windows\Interop.Libraries.cs"
Link="Common\Interop\Windows\Interop.Libraries.cs" />
<Compile Include="$(CommonPath)Interop\Windows\Interop.UNICODE_STRING.cs"
Link="Common\Interop\Windows\Interop.UNICODE_STRING.cs" />
<Compile Include="$(CommonPath)Interop\Windows\SChannel\Interop.SecPkgContext_ApplicationProtocol.cs"
Link="Common\Interop\Windows\SChannel\Interop.SecPkgContext_ApplicationProtocol.cs" />
<Compile Include="$(CommonPath)Interop\Windows\Interop.BOOL.cs"
Expand Down
2 changes: 2 additions & 0 deletions src/libraries/System.Net.Mail/src/System.Net.Mail.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,8 @@
Link="Common\System\Net\Security\NetEventSource.Security.cs" />
<Compile Include="$(CommonPath)System\HexConverter.cs"
Link="Common\System\HexConverter.cs" />
<Compile Include="$(CommonPath)Interop\Windows\Interop.UNICODE_STRING.cs"
Link="Common\Interop\Windows\Interop.UNICODE_STRING.cs" />
</ItemGroup>
<!-- Unix specific files -->
<ItemGroup Condition="'$(TargetsUnix)' == 'true'">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -261,5 +261,7 @@
Link="Common\Interop\Windows\SspiCli\SecuritySafeHandles.cs" />
<Compile Include="$(CommonPath)Interop\Windows\SspiCli\SSPIWrapper.cs"
Link="Common\Interop\Windows\SspiCli\SSPIWrapper.cs" />
<Compile Include="$(CommonPath)Interop\Windows\Interop.UNICODE_STRING.cs"
Link="Common\Interop\Windows\Interop.UNICODE_STRING.cs" />
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,8 @@
<!-- Interop -->
<Compile Include="$(CommonPath)Interop\Windows\Interop.Libraries.cs"
Link="Common\Interop\Windows\Interop.Libraries.cs" />
<Compile Include="$(CommonPath)Interop\Windows\Interop.UNICODE_STRING.cs"
Link="Common\Interop\Windows\Interop.UNICODE_STRING.cs" />
<Compile Include="$(CommonPath)Interop\Windows\Crypt32\Interop.certificates.cs"
Link="Common\Interop\Windows\Crypt32\Interop.certificates.cs" />
<Compile Include="$(CommonPath)Interop\Windows\Crypt32\Interop.certificates_types.cs"
Expand All @@ -154,6 +156,8 @@
Link="Common\Interop\Windows\Crypt32\Interop.CertEnumCertificatesInStore.cs" />
<Compile Include="$(CommonPath)Interop\Windows\Kernel32\Interop.CloseHandle.cs"
Link="Common\Interop\Windows\Kernel32\Interop.CloseHandle.cs" />
<Compile Include="$(CommonPath)Interop\Windows\NtDll\Interop.RtlGetVersion.cs"
Link="Common\Interop\Windows\NtDll\Interop.RtlGetVersion.cs" />
<Compile Include="$(CommonPath)Interop\Windows\SChannel\Interop.Alerts.cs"
Link="Common\Interop\Windows\SChannel\Interop.Alerts.cs" />
<Compile Include="$(CommonPath)Interop\Windows\SChannel\Interop.SchProtocols.cs"
Expand Down
Loading