/// <summary> /// Verifies the end <see cref="Certificate"/> according to the SSL policy rules. /// </summary> /// <param name="server">The server that returned the certificate -or- a null reference if the certificate is a client certificate.</param> /// <param name="type">One of the <see cref="AuthType"/> values.</param> /// <param name="flags">One or more of the <see cref="VerificationFlags"/> values. VerificationFlags values can be combined with the OR operator.</param> /// <returns>One of the <see cref="CertificateStatus"/> values.</returns> /// <exception cref="CertificateException">An error occurs while verifying the certificate.</exception> public virtual CertificateStatus VerifyChain(string server, AuthType type, VerificationFlags flags) { // Convert the server string to a wide string memory pointer IntPtr serverName = IntPtr.Zero; IntPtr dataPtr = IntPtr.Zero; try { if (server == null) { serverName = IntPtr.Zero; } else { serverName = Marshal.StringToHGlobalUni(server); } // create a HTTPSPolicyCallbackData and get a memory pointer to the structure SslPolicyParameters data = new SslPolicyParameters(); data.cbSize = Marshal.SizeOf(typeof(SslPolicyParameters)); data.dwAuthType = (int)type; data.pwszServerName = serverName; data.fdwChecks = (int)flags; dataPtr = Marshal.AllocHGlobal(data.cbSize); Marshal.StructureToPtr(data, dataPtr, false); // create a CERT_CHAIN_POLICY_PARA ChainPolicyParameters para = new ChainPolicyParameters(); para.cbSize = Marshal.SizeOf(typeof(ChainPolicyParameters)); para.dwFlags = (int)flags; para.pvExtraPolicyPara = dataPtr; // create a CERT_CHAIN_POLICY_STATUS ChainPolicyStatus status = new ChainPolicyStatus(); status.cbSize = Marshal.SizeOf(typeof(ChainPolicyStatus)); // verify the certificate if (SspiProvider.CertVerifyCertificateChainPolicy(new IntPtr(SecurityConstants.CERT_CHAIN_POLICY_SSL), m_Handle, ref para, ref status) == 0) { throw new CertificateException("Unable to verify the certificate."); } if (Enum.IsDefined(typeof(CertificateStatus), status.dwError)) { return((CertificateStatus)status.dwError); } else { return(CertificateStatus.OtherError); } } finally { // clean up if (dataPtr != IntPtr.Zero) { Marshal.FreeHGlobal(dataPtr); } if (serverName != IntPtr.Zero) { Marshal.FreeHGlobal(serverName); } } }