/// <summary> /// Does not throw on error. Returns null ChainPal instead. /// </summary> public static ChainPal BuildChain( bool useMachineContext, ICertificatePal cert, X509Certificate2Collection extraStore, OidCollection applicationPolicy, OidCollection certificatePolicy, X509RevocationMode revocationMode, X509RevocationFlag revocationFlag, DateTime verificationTime, TimeSpan timeout) { CertificatePal certificatePal = (CertificatePal)cert; unsafe { using (SafeCertStoreHandle extraStoreHandle = ConvertExtraStoreToSafeHandle(extraStore)) { CERT_CHAIN_PARA chainPara = new CERT_CHAIN_PARA(); chainPara.cbSize = Marshal.SizeOf <CERT_CHAIN_PARA>(); int applicationPolicyCount; using (SafeHandle applicationPolicyOids = applicationPolicy.ToLpstrArray(out applicationPolicyCount)) { if (!applicationPolicyOids.IsInvalid) { chainPara.RequestedUsage.dwType = CertUsageMatchType.USAGE_MATCH_TYPE_AND; chainPara.RequestedUsage.Usage.cUsageIdentifier = applicationPolicyCount; chainPara.RequestedUsage.Usage.rgpszUsageIdentifier = applicationPolicyOids.DangerousGetHandle(); } int certificatePolicyCount; using (SafeHandle certificatePolicyOids = certificatePolicy.ToLpstrArray(out certificatePolicyCount)) { if (!certificatePolicyOids.IsInvalid) { chainPara.RequestedIssuancePolicy.dwType = CertUsageMatchType.USAGE_MATCH_TYPE_AND; chainPara.RequestedIssuancePolicy.Usage.cUsageIdentifier = certificatePolicyCount; chainPara.RequestedIssuancePolicy.Usage.rgpszUsageIdentifier = certificatePolicyOids.DangerousGetHandle(); } chainPara.dwUrlRetrievalTimeout = (int)Math.Floor(timeout.TotalMilliseconds); FILETIME ft = FILETIME.FromDateTime(verificationTime); CertChainFlags flags = MapRevocationFlags(revocationMode, revocationFlag); ChainEngine chainEngine = useMachineContext ? ChainEngine.HCCE_LOCAL_MACHINE : ChainEngine.HCCE_CURRENT_USER; SafeX509ChainHandle chain; if (!Interop.crypt32.CertGetCertificateChain(chainEngine, certificatePal.CertContext, &ft, extraStoreHandle, ref chainPara, flags, IntPtr.Zero, out chain)) { return(null); } return(new ChainPal(chain)); } } } } }
private static bool CertificateHasLowerPrecedence(X509Store store, ChainEngine engine, string fqdn, X509Certificate2 certificate, out X509Certificate2 best) { CertificateSelectionOption options = CertificateSelectionOption.WildcardAllowed | CertificateSelectionOption.PreferedNonSelfSigned; string[] names = new string[] { fqdn }; IEnumerable <X509Certificate2> enumerable = TlsCertificateInfo.FindAll(store, names, options, engine, out best); bool flag = false; foreach (X509Certificate2 x509Certificate in enumerable) { if (string.Equals(certificate.Thumbprint, x509Certificate.Thumbprint, StringComparison.OrdinalIgnoreCase)) { flag = true; break; } } return(flag && best != null && !string.Equals(best.Thumbprint, certificate.Thumbprint, StringComparison.OrdinalIgnoreCase)); }
private static void WarnIfNotBestMatch(ExchangeCertificate certificate, IConfigurationSession session, Server server, List <LocalizedString> warningList) { if (warningList == null) { return; } X509Store x509Store = new X509Store(StoreName.My, StoreLocation.LocalMachine); try { x509Store.Open(OpenFlags.ReadOnly); using (ChainEngine chainEngine = new ChainEngine()) { IEnumerable <ManageExchangeCertificate.FqdnConnectors> connectorFQDNs = ManageExchangeCertificate.GetConnectorFQDNs(session, server); foreach (ManageExchangeCertificate.FqdnConnectors fqdnConnectors in connectorFQDNs) { X509Certificate2 x509Certificate; if (ManageExchangeCertificate.CertificateHasLowerPrecedence(x509Store, chainEngine, fqdnConnectors.Fqdn, certificate, out x509Certificate)) { if (!new ExchangeCertificate(x509Certificate).IsSelfSigned) { warningList.Add(Strings.WarnCertificateWillNotBeUsedBestIsPKI(x509Certificate.Thumbprint, fqdnConnectors.Fqdn, fqdnConnectors.Connectors)); } else { warningList.Add(Strings.WarnCertificateWillNotBeUsed(x509Certificate.Thumbprint, fqdnConnectors.Fqdn, fqdnConnectors.Connectors)); } } } } } finally { if (x509Store != null) { x509Store.Close(); } } }
public static unsafe bool CertGetCertificateChain(ChainEngine hChainEngine, SafeCertContextHandle pCertContext, FILETIME *pTime, SafeCertStoreHandle hStore, [In] ref CERT_CHAIN_PARA pChainPara, CertChainFlags dwFlags, IntPtr pvReserved, out SafeX509ChainHandle ppChainContext) { return(CertGetCertificateChain((IntPtr)hChainEngine, pCertContext, pTime, hStore, ref pChainPara, dwFlags, pvReserved, out ppChainContext)); }
public static unsafe bool CertGetCertificateChain(ChainEngine hChainEngine, SafeCertContextHandle pCertContext, FILETIME* pTime, SafeCertStoreHandle hStore, [In] ref CERT_CHAIN_PARA pChainPara, CertChainFlags dwFlags, IntPtr pvReserved, out SafeX509ChainHandle ppChainContext) { return CertGetCertificateChain((IntPtr)hChainEngine, pCertContext, pTime, hStore, ref pChainPara, dwFlags, pvReserved, out ppChainContext); }
private void CheckCertificateChainAndCacheProps() { if (this.status != CertificateStatus.Unknown) { return; } if (!string.IsNullOrEmpty(this.CertificateRequest)) { this.status = CertificateStatus.PendingRequest; this.selfSigned = false; this.rootCAType = CertificateAuthorityType.Unknown; return; } this.privateKeyExportable = TlsCertificateInfo.IsCertificateExportable(this); ChainPolicyParameters options = new BaseChainPolicyParameters(ChainPolicyOptions.None); ChainMatchIssuer pkixKpServerAuth = AndChainMatchIssuer.PkixKpServerAuth; ChainBuildParameter parameter = new ChainBuildParameter(pkixKpServerAuth, TimeSpan.FromSeconds(30.0), false, TimeSpan.Zero); using (ChainEngine chainEngine = new ChainEngine()) { using (ChainContext chainContext = chainEngine.Build(this, ChainBuildOptions.CacheEndCert | ChainBuildOptions.RevocationCheckChainExcludeRoot | ChainBuildOptions.RevocationAccumulativeTimeout, parameter)) { if (chainContext == null) { this.status = CertificateStatus.Unknown; this.selfSigned = false; this.rootCAType = CertificateAuthorityType.Unknown; } else { this.selfSigned = chainContext.IsSelfSigned; if (chainContext.Status == TrustStatus.IsUntrustedRoot) { if (chainContext.IsSelfSigned) { this.status = CertificateStatus.Valid; this.rootCAType = CertificateAuthorityType.None; } else { this.status = CertificateStatus.Untrusted; this.rootCAType = CertificateAuthorityType.Unknown; } } else { ChainSummary chainSummary = chainContext.Validate(options); ChainValidityStatus chainValidityStatus = chainSummary.Status; if (chainValidityStatus <= (ChainValidityStatus)2148081683U) { if (chainValidityStatus == ChainValidityStatus.Valid) { this.status = CertificateStatus.Valid; goto IL_168; } switch (chainValidityStatus) { case (ChainValidityStatus)2148081682U: case (ChainValidityStatus)2148081683U: break; default: goto IL_15A; } } else { if (chainValidityStatus == (ChainValidityStatus)2148204801U) { this.status = CertificateStatus.DateInvalid; goto IL_168; } switch (chainValidityStatus) { case (ChainValidityStatus)2148204812U: this.status = CertificateStatus.Revoked; goto IL_168; case (ChainValidityStatus)2148204813U: goto IL_15A; case (ChainValidityStatus)2148204814U: break; default: goto IL_15A; } } this.status = CertificateStatus.RevocationCheckFailure; goto IL_168; IL_15A: this.status = CertificateStatus.Invalid; this.rootCAType = CertificateAuthorityType.Unknown; IL_168: if (this.status != CertificateStatus.Invalid) { X509Certificate2 rootCertificate = chainContext.RootCertificate; if (rootCertificate == null) { throw new InvalidOperationException("Root certificate was null!"); } this.rootCAType = ExchangeCertificate.RootSource(rootCertificate.Thumbprint); } } } } } }