private unsafe uint[] GetChainErrors(string hostName, X509Chain chain, ref bool fatalError) { fatalError = false; SafeFreeCertChain chainContext = new SafeFreeCertChain(chain.ChainContext); ArrayList list = new ArrayList(); uint errorCode = 0; ChainPolicyParameter cpp = new ChainPolicyParameter { cbSize = ChainPolicyParameter.StructSize, dwFlags = 0 }; SSL_EXTRA_CERT_CHAIN_POLICY_PARA ssl_extra_cert_chain_policy_para = new SSL_EXTRA_CERT_CHAIN_POLICY_PARA(false); cpp.pvExtraPolicyPara = &ssl_extra_cert_chain_policy_para; fixed (char* str = ((char*) hostName)) { char* chPtr = str; if (ServicePointManager.CheckCertificateName) { ssl_extra_cert_chain_policy_para.pwszServerName = chPtr; } Label_006B: errorCode = VerifyChainPolicy(chainContext, ref cpp); uint num2 = (uint) MapErrorCode(errorCode); list.Add(errorCode); if (errorCode != 0) { if (num2 == 0) { fatalError = true; } else { cpp.dwFlags |= num2; if ((errorCode == 0x800b010f) && ServicePointManager.CheckCertificateName) { ssl_extra_cert_chain_policy_para.fdwChecks = 0x1000; } goto Label_006B; } } } return (uint[]) list.ToArray(typeof(uint)); }
private uint[] GetChainErrors(string hostName, X509Chain chain, ref bool fatalError) { fatalError = false; SafeFreeCertChain chainContext= new SafeFreeCertChain(chain.ChainContext); ArrayList certificateProblems = new ArrayList(); unsafe { uint status = 0; ChainPolicyParameter cppStruct = new ChainPolicyParameter(); cppStruct.cbSize = ChainPolicyParameter.StructSize; cppStruct.dwFlags = 0; SSL_EXTRA_CERT_CHAIN_POLICY_PARA eppStruct = new SSL_EXTRA_CERT_CHAIN_POLICY_PARA(false); cppStruct.pvExtraPolicyPara = &eppStruct; fixed (char* namePtr = hostName) { if (ServicePointManager.CheckCertificateName){ eppStruct.pwszServerName = namePtr; } while (true) { status = VerifyChainPolicy(chainContext, ref cppStruct); uint ignoreErrorMask = (uint)MapErrorCode(status); certificateProblems.Add(status); if (status == 0) { // No more problems with the certificate? break; // Then break out of the callback loop } if (ignoreErrorMask == 0) { // Unrecognized error encountered fatalError = true; break; } else { cppStruct.dwFlags |= ignoreErrorMask; if ((CertificateProblem)status == CertificateProblem.CertCN_NO_MATCH && ServicePointManager.CheckCertificateName) { eppStruct.fdwChecks = IgnoreUnmatchedCN; } } } } } return (uint[]) certificateProblems.ToArray(typeof(uint)); }
internal static uint VerifyChainPolicy(SafeFreeCertChain chainContext, ref ChainPolicyParameter cpp) { GlobalLog.Enter("PolicyWrapper::VerifyChainPolicy", "chainContext="+ chainContext + ", options="+String.Format("0x{0:x}", cpp.dwFlags)); ChainPolicyStatus status = new ChainPolicyStatus(); status.cbSize = ChainPolicyStatus.StructSize; int errorCode = UnsafeNclNativeMethods.NativePKI.CertVerifyCertificateChainPolicy( (IntPtr) ChainPolicyType.SSL, chainContext, ref cpp, ref status); GlobalLog.Print("PolicyWrapper::VerifyChainPolicy() CertVerifyCertificateChainPolicy returned: " + errorCode); #if TRAVE GlobalLog.Print("PolicyWrapper::VerifyChainPolicy() error code: " + status.dwError+String.Format(" [0x{0:x8}", status.dwError) + " " + SecureChannel.MapSecurityStatus(status.dwError) + "]"); #endif GlobalLog.Leave("PolicyWrapper::VerifyChainPolicy", status.dwError.ToString()); return status.dwError; }
internal bool VerifyRemoteCertificate(RemoteCertValidationCallback remoteCertValidationCallback) { GlobalLog.Enter("SecureChannel#" + ValidationHelper.HashString(this) + "::VerifyRemoteCertificate"); SslPolicyErrors sslPolicyErrors = SslPolicyErrors.None; // we don't catch exceptions in this method, so it's safe for "accepted" be initialized with true bool success = false; X509Chain chain = null; X509Certificate2 remoteCertificateEx = null; try { X509Certificate2Collection remoteCertificateStore; remoteCertificateEx = GetRemoteCertificate(out remoteCertificateStore); m_IsRemoteCertificateAvailable = remoteCertificateEx != null; if (remoteCertificateEx == null) { GlobalLog.Leave("SecureChannel#" + ValidationHelper.HashString(this) + "::VerifyRemoteCertificate (no remote cert)", (!m_RemoteCertRequired).ToString()); sslPolicyErrors |= SslPolicyErrors.RemoteCertificateNotAvailable; } #if !MONO else { chain = new X509Chain(); chain.ChainPolicy.RevocationMode = m_CheckCertRevocation? X509RevocationMode.Online : X509RevocationMode.NoCheck; chain.ChainPolicy.RevocationFlag = X509RevocationFlag.ExcludeRoot; if (remoteCertificateStore != null) chain.ChainPolicy.ExtraStore.AddRange(remoteCertificateStore); if (!chain.Build(remoteCertificateEx) // Build failed on handle or on policy && chain.ChainContext == IntPtr.Zero) // Build failed to generate a valid handle { throw new CryptographicException(Marshal.GetLastWin32Error()); } if (m_CheckCertName) { unsafe { uint status = 0; ChainPolicyParameter cppStruct = new ChainPolicyParameter(); cppStruct.cbSize = ChainPolicyParameter.StructSize; cppStruct.dwFlags = 0; SSL_EXTRA_CERT_CHAIN_POLICY_PARA eppStruct = new SSL_EXTRA_CERT_CHAIN_POLICY_PARA(IsServer); cppStruct.pvExtraPolicyPara = &eppStruct; fixed (char* namePtr = m_HostName) { eppStruct.pwszServerName = namePtr; cppStruct.dwFlags |= (int) (IgnoreCertProblem.none & ~IgnoreCertProblem.invalid_name); SafeFreeCertChain chainContext= new SafeFreeCertChain(chain.ChainContext); status = PolicyWrapper.VerifyChainPolicy(chainContext, ref cppStruct); if ((CertificateProblem) status == CertificateProblem.CertCN_NO_MATCH) sslPolicyErrors |= SslPolicyErrors.RemoteCertificateNameMismatch; } } } X509ChainStatus[] chainStatusArray = chain.ChainStatus; if (chainStatusArray != null && chainStatusArray.Length != 0) sslPolicyErrors |= SslPolicyErrors.RemoteCertificateChainErrors; } if (remoteCertValidationCallback != null) { success = remoteCertValidationCallback(m_HostName, remoteCertificateEx, chain, sslPolicyErrors); } else { if (sslPolicyErrors == SslPolicyErrors.RemoteCertificateNotAvailable && !m_RemoteCertRequired) success = true; else success = (sslPolicyErrors == SslPolicyErrors.None); } #else success = SSPIWrapper.CheckRemoteCertificate(m_SecurityContext); #endif if (Logging.On) { if (sslPolicyErrors != SslPolicyErrors.None) { Logging.PrintInfo(Logging.Web, this, SR.GetString(SR.net_log_remote_cert_has_errors)); if ((sslPolicyErrors & SslPolicyErrors.RemoteCertificateNotAvailable) != 0) Logging.PrintInfo(Logging.Web, this, "\t" + SR.GetString(SR.net_log_remote_cert_not_available)); if ((sslPolicyErrors & SslPolicyErrors.RemoteCertificateNameMismatch) != 0) Logging.PrintInfo(Logging.Web, this, "\t" + SR.GetString(SR.net_log_remote_cert_name_mismatch)); if ((sslPolicyErrors & SslPolicyErrors.RemoteCertificateChainErrors) != 0) foreach (X509ChainStatus chainStatus in chain.ChainStatus) Logging.PrintInfo(Logging.Web, this, "\t" + chainStatus.StatusInformation); } if (success) { if (remoteCertValidationCallback != null) Logging.PrintInfo(Logging.Web, this, SR.GetString(SR.net_log_remote_cert_user_declared_valid)); else Logging.PrintInfo(Logging.Web, this, SR.GetString(SR.net_log_remote_cert_has_no_errors)); } else { if (remoteCertValidationCallback != null) Logging.PrintInfo(Logging.Web, this, SR.GetString(SR.net_log_remote_cert_user_declared_invalid)); } } GlobalLog.Print("Cert Validation, remote cert = " + (remoteCertificateEx == null? "<null>": remoteCertificateEx.ToString(true))); } finally { // At least on Win2k server the chain is found to have dependancies on the original cert context. // So it should be closed first. if (chain != null) { chain.Reset(); } if (remoteCertificateEx != null) remoteCertificateEx.Reset(); } GlobalLog.Leave("SecureChannel#" + ValidationHelper.HashString(this) + "::VerifyRemoteCertificate", success.ToString()); return success; }
internal static X509CertificateCollection FindClientCertificates() { if (!ComNetOS.IsWin7orLater) { throw new PlatformNotSupportedException(); } X509CertificateCollection certificates = new X509CertificateCollection(); X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser); store.Open(OpenFlags.MaxAllowed); int chainCount = 0; SafeFreeCertChainList chainList = null; SafeCertSelectCritera criteria = new SafeCertSelectCritera(); try { bool success = CertSelectCertificateChains( IntPtr.Zero, CertificateSelect.HasPrivateKey, IntPtr.Zero, criteria.Count, // DWORD criteria, // PCCERT_SELECT_CRITERIA store.StoreHandle, out chainCount, out chainList); if (!success) { throw new Win32Exception(); // Calls GetLastError. } Debug.Assert(chainCount == 0 || !chainList.IsInvalid); for (int i = 0; i < chainCount; i++) { // Resolve IntPtr in array. using (SafeFreeCertChain chainRef = new SafeFreeCertChain( Marshal.ReadIntPtr(chainList.DangerousGetHandle() + i * Marshal.SizeOf(typeof(IntPtr))), true)) { Debug.Assert(!chainRef.IsInvalid); // X509Chain will duplicate the chain by increasing its ref-count. X509Chain chain = new X509Chain(chainRef.DangerousGetHandle()); // Copy base cert from chain. if (chain.ChainElements.Count > 0) { X509Certificate2 cert = chain.ChainElements[0].Certificate; certificates.Add(cert); } // Remove the X509Chain's reference prior to releasing the Chain List. chain.Reset(); } } } finally { // Close store. store.Close(); chainList.Dispose(); criteria.Dispose(); } return certificates; }
internal static uint VerifyChainPolicy(SafeFreeCertChain chainContext, ref ChainPolicyParameter cpp) { ChainPolicyStatus ps = new ChainPolicyStatus { cbSize = ChainPolicyStatus.StructSize }; UnsafeNclNativeMethods.NativePKI.CertVerifyCertificateChainPolicy((IntPtr) 4L, chainContext, ref cpp, ref ps); return ps.dwError; }
internal unsafe bool VerifyRemoteCertificate(RemoteCertValidationCallback remoteCertValidationCallback) { SslPolicyErrors none = SslPolicyErrors.None; bool flag = false; X509Chain chain = null; X509Certificate2 remoteCertificate = null; try { X509Certificate2Collection certificates; remoteCertificate = this.GetRemoteCertificate(out certificates); this.m_IsRemoteCertificateAvailable = remoteCertificate != null; if (remoteCertificate == null) { none |= SslPolicyErrors.RemoteCertificateNotAvailable; } else { chain = new X509Chain { ChainPolicy = { RevocationMode = this.m_CheckCertRevocation ? X509RevocationMode.Online : X509RevocationMode.NoCheck, RevocationFlag = X509RevocationFlag.ExcludeRoot } }; if (certificates != null) { chain.ChainPolicy.ExtraStore.AddRange(certificates); } if (!chain.Build(remoteCertificate) && (chain.ChainContext == IntPtr.Zero)) { throw new CryptographicException(Marshal.GetLastWin32Error()); } if (this.m_CheckCertName) { ChainPolicyParameter cpp = new ChainPolicyParameter { cbSize = ChainPolicyParameter.StructSize, dwFlags = 0 }; SSL_EXTRA_CERT_CHAIN_POLICY_PARA ssl_extra_cert_chain_policy_para = new SSL_EXTRA_CERT_CHAIN_POLICY_PARA(this.IsServer); cpp.pvExtraPolicyPara = &ssl_extra_cert_chain_policy_para; fixed (char* str = ((char*) this.m_HostName)) { char* chPtr = str; ssl_extra_cert_chain_policy_para.pwszServerName = chPtr; cpp.dwFlags |= 0xfbf; SafeFreeCertChain chainContext = new SafeFreeCertChain(chain.ChainContext); if (PolicyWrapper.VerifyChainPolicy(chainContext, ref cpp) == 0x800b010f) { none |= SslPolicyErrors.RemoteCertificateNameMismatch; } } } X509ChainStatus[] chainStatus = chain.ChainStatus; if ((chainStatus != null) && (chainStatus.Length != 0)) { none |= SslPolicyErrors.RemoteCertificateChainErrors; } } if (remoteCertValidationCallback != null) { flag = remoteCertValidationCallback(this.m_HostName, remoteCertificate, chain, none); } else if ((none == SslPolicyErrors.RemoteCertificateNotAvailable) && !this.m_RemoteCertRequired) { flag = true; } else { flag = none == SslPolicyErrors.None; } if (!Logging.On) { return flag; } if (none != SslPolicyErrors.None) { Logging.PrintInfo(Logging.Web, this, SR.GetString("net_log_remote_cert_has_errors")); if ((none & SslPolicyErrors.RemoteCertificateNotAvailable) != SslPolicyErrors.None) { Logging.PrintInfo(Logging.Web, this, "\t" + SR.GetString("net_log_remote_cert_not_available")); } if ((none & SslPolicyErrors.RemoteCertificateNameMismatch) != SslPolicyErrors.None) { Logging.PrintInfo(Logging.Web, this, "\t" + SR.GetString("net_log_remote_cert_name_mismatch")); } if ((none & SslPolicyErrors.RemoteCertificateChainErrors) != SslPolicyErrors.None) { foreach (X509ChainStatus status in chain.ChainStatus) { Logging.PrintInfo(Logging.Web, this, "\t" + status.StatusInformation); } } } if (flag) { if (remoteCertValidationCallback != null) { Logging.PrintInfo(Logging.Web, this, SR.GetString("net_log_remote_cert_user_declared_valid")); return flag; } Logging.PrintInfo(Logging.Web, this, SR.GetString("net_log_remote_cert_has_no_errors")); return flag; } if (remoteCertValidationCallback != null) { Logging.PrintInfo(Logging.Web, this, SR.GetString("net_log_remote_cert_user_declared_invalid")); } } finally { if (chain != null) { chain.Reset(); } if (remoteCertificate != null) { remoteCertificate.Reset(); } } return flag; }