internal static SslPolicyErrors VerifyCertificateProperties(
X509Chain chain,
X509Certificate2 remoteCertificate,
bool checkCertName,
bool isServer,
string hostName)
{
SslPolicyErrors sslPolicyErrors = SslPolicyErrors.None;
if (!chain.Build(remoteCertificate) // Build failed on handle or on policy.
&& chain.SafeHandle.DangerousGetHandle() == IntPtr.Zero) // Build failed to generate a valid handle.
{
throw new CryptographicException(Marshal.GetLastWin32Error());
}
if (checkCertName)
{
unsafe
{
uint status = 0;
var eppStruct = new Interop.Crypt32.SSL_EXTRA_CERT_CHAIN_POLICY_PARA()
{
cbSize = (uint)Marshal.SizeOf<Interop.Crypt32.SSL_EXTRA_CERT_CHAIN_POLICY_PARA>(),
dwAuthType = isServer ? Interop.Crypt32.AuthType.AUTHTYPE_SERVER : Interop.Crypt32.AuthType.AUTHTYPE_CLIENT,
fdwChecks = 0,
pwszServerName = null
};
var cppStruct = new Interop.Crypt32.CERT_CHAIN_POLICY_PARA()
{
cbSize = (uint)Marshal.SizeOf<Interop.Crypt32.CERT_CHAIN_POLICY_PARA>(),
dwFlags = 0,
pvExtraPolicyPara = &eppStruct
};
fixed (char* namePtr = hostName)
{
eppStruct.pwszServerName = namePtr;
cppStruct.dwFlags |=
(Interop.Crypt32.CertChainPolicyIgnoreFlags.CERT_CHAIN_POLICY_IGNORE_ALL &
~Interop.Crypt32.CertChainPolicyIgnoreFlags.CERT_CHAIN_POLICY_IGNORE_INVALID_NAME_FLAG);
SafeX509ChainHandle chainContext = chain.SafeHandle;
status = Verify(chainContext, ref cppStruct);
if (status == Interop.Crypt32.CertChainPolicyErrors.CERT_E_CN_NO_MATCH)
{
sslPolicyErrors |= SslPolicyErrors.RemoteCertificateNameMismatch;
}
}
}
}
X509ChainStatus[] chainStatusArray = chain.ChainStatus;
if (chainStatusArray != null && chainStatusArray.Length != 0)
{
sslPolicyErrors |= SslPolicyErrors.RemoteCertificateChainErrors;
}
return sslPolicyErrors;
}