Terraria v1.4.4.9
Terraria source code documentation
Loading...
Searching...
No Matches
ChainPal.cs
Go to the documentation of this file.
1using System;
7
9
10internal sealed class ChainPal : IDisposable, IChainPal
11{
12 private readonly struct X509ChainErrorMapping
13 {
15
16 public readonly int Win32ErrorCode;
17
19
20 public readonly string Message;
21
22 public X509ChainErrorMapping(CertTrustErrorStatus win32Flag, int win32ErrorCode, X509ChainStatusFlags chainStatusFlag)
23 {
24 Win32Flag = win32Flag;
25 Win32ErrorCode = win32ErrorCode;
26 ChainStatusFlag = chainStatusFlag;
27 Message = global::Interop.Kernel32.GetMessage(win32ErrorCode);
28 }
29 }
30
32
34 {
35 new X509ChainErrorMapping(CertTrustErrorStatus.CERT_TRUST_IS_NOT_SIGNATURE_VALID, -2146869244, X509ChainStatusFlags.NotSignatureValid),
36 new X509ChainErrorMapping(CertTrustErrorStatus.CERT_TRUST_CTL_IS_NOT_SIGNATURE_VALID, -2146869244, X509ChainStatusFlags.CtlNotSignatureValid),
37 new X509ChainErrorMapping(CertTrustErrorStatus.CERT_TRUST_IS_UNTRUSTED_ROOT, -2146762487, X509ChainStatusFlags.UntrustedRoot),
38 new X509ChainErrorMapping(CertTrustErrorStatus.CERT_TRUST_IS_PARTIAL_CHAIN, -2146762486, X509ChainStatusFlags.PartialChain),
39 new X509ChainErrorMapping(CertTrustErrorStatus.CERT_TRUST_IS_REVOKED, -2146885616, X509ChainStatusFlags.Revoked),
40 new X509ChainErrorMapping(CertTrustErrorStatus.CERT_TRUST_IS_NOT_VALID_FOR_USAGE, -2146762480, X509ChainStatusFlags.NotValidForUsage),
41 new X509ChainErrorMapping(CertTrustErrorStatus.CERT_TRUST_CTL_IS_NOT_VALID_FOR_USAGE, -2146762480, X509ChainStatusFlags.CtlNotValidForUsage),
42 new X509ChainErrorMapping(CertTrustErrorStatus.CERT_TRUST_IS_NOT_TIME_VALID, -2146762495, X509ChainStatusFlags.NotTimeValid),
43 new X509ChainErrorMapping(CertTrustErrorStatus.CERT_TRUST_CTL_IS_NOT_TIME_VALID, -2146762495, X509ChainStatusFlags.CtlNotTimeValid),
44 new X509ChainErrorMapping(CertTrustErrorStatus.CERT_TRUST_INVALID_NAME_CONSTRAINTS, -2146762476, X509ChainStatusFlags.InvalidNameConstraints),
45 new X509ChainErrorMapping(CertTrustErrorStatus.CERT_TRUST_HAS_NOT_SUPPORTED_NAME_CONSTRAINT, -2146762476, X509ChainStatusFlags.HasNotSupportedNameConstraint),
46 new X509ChainErrorMapping(CertTrustErrorStatus.CERT_TRUST_HAS_NOT_DEFINED_NAME_CONSTRAINT, -2146762476, X509ChainStatusFlags.HasNotDefinedNameConstraint),
47 new X509ChainErrorMapping(CertTrustErrorStatus.CERT_TRUST_HAS_NOT_PERMITTED_NAME_CONSTRAINT, -2146762476, X509ChainStatusFlags.HasNotPermittedNameConstraint),
48 new X509ChainErrorMapping(CertTrustErrorStatus.CERT_TRUST_HAS_EXCLUDED_NAME_CONSTRAINT, -2146762476, X509ChainStatusFlags.HasExcludedNameConstraint),
49 new X509ChainErrorMapping(CertTrustErrorStatus.CERT_TRUST_INVALID_POLICY_CONSTRAINTS, -2146762477, X509ChainStatusFlags.InvalidPolicyConstraints),
50 new X509ChainErrorMapping(CertTrustErrorStatus.CERT_TRUST_NO_ISSUANCE_CHAIN_POLICY, -2146762477, X509ChainStatusFlags.NoIssuanceChainPolicy),
51 new X509ChainErrorMapping(CertTrustErrorStatus.CERT_TRUST_INVALID_BASIC_CONSTRAINTS, -2146869223, X509ChainStatusFlags.InvalidBasicConstraints),
52 new X509ChainErrorMapping(CertTrustErrorStatus.CERT_TRUST_IS_NOT_TIME_NESTED, -2146762494, X509ChainStatusFlags.NotTimeNested),
53 new X509ChainErrorMapping(CertTrustErrorStatus.CERT_TRUST_REVOCATION_STATUS_UNKNOWN, -2146885614, X509ChainStatusFlags.RevocationStatusUnknown),
54 new X509ChainErrorMapping(CertTrustErrorStatus.CERT_TRUST_IS_OFFLINE_REVOCATION, -2146885613, X509ChainStatusFlags.OfflineRevocation),
55 new X509ChainErrorMapping(CertTrustErrorStatus.CERT_TRUST_IS_EXPLICIT_DISTRUST, -2146762479, X509ChainStatusFlags.ExplicitDistrust),
56 new X509ChainErrorMapping(CertTrustErrorStatus.CERT_TRUST_HAS_NOT_SUPPORTED_CRITICAL_EXT, -2146762491, X509ChainStatusFlags.HasNotSupportedCriticalExtension),
57 new X509ChainErrorMapping(CertTrustErrorStatus.CERT_TRUST_HAS_WEAK_SIGNATURE, -2146877418, X509ChainStatusFlags.HasWeakSignature)
58 };
59
61 {
62 get
63 {
65 CERT_SIMPLE_CHAIN* rgpChain = *ptr->rgpChain;
67 for (int i = 0; i < rgpChain->cElement; i++)
68 {
69 CERT_CHAIN_ELEMENT* ptr2 = rgpChain->rgpElement[i];
70 X509Certificate2 certificate = new X509Certificate2((IntPtr)ptr2->pCertContext);
72 string information = Marshal.PtrToStringUni(ptr2->pwszExtendedErrorInfo);
73 X509ChainElement x509ChainElement = new X509ChainElement(certificate, chainStatusInformation, information);
74 array[i] = x509ChainElement;
75 }
76 GC.KeepAlive(this);
77 return array;
78 }
79 }
80
82 {
83 get
84 {
87 GC.KeepAlive(this);
88 return chainStatusInformation;
89 }
90 }
91
93
94 public unsafe static ChainPal BuildChain(bool useMachineContext, ICertificatePal cert, X509Certificate2Collection extraStore, OidCollection applicationPolicy, OidCollection certificatePolicy, X509RevocationMode revocationMode, X509RevocationFlag revocationFlag, X509Certificate2Collection customTrustStore, X509ChainTrustMode trustMode, DateTime verificationTime, TimeSpan timeout, bool disableAia)
95 {
96 CertificatePal certificatePal = (CertificatePal)cert;
97 using SafeChainEngineHandle safeChainEngineHandle = GetChainEngine(trustMode, customTrustStore, useMachineContext);
98 using SafeCertStoreHandle hStore = ConvertStoreToSafeHandle(extraStore);
99 CERT_CHAIN_PARA pChainPara = default(CERT_CHAIN_PARA);
100 pChainPara.cbSize = Marshal.SizeOf<CERT_CHAIN_PARA>();
101 int numOids;
102 using SafeHandle safeHandle = applicationPolicy.ToLpstrArray(out numOids);
103 if (!safeHandle.IsInvalid)
104 {
105 pChainPara.RequestedUsage.dwType = CertUsageMatchType.USAGE_MATCH_TYPE_AND;
106 pChainPara.RequestedUsage.Usage.cUsageIdentifier = numOids;
107 pChainPara.RequestedUsage.Usage.rgpszUsageIdentifier = safeHandle.DangerousGetHandle();
108 }
109 int numOids2;
110 using SafeHandle safeHandle2 = certificatePolicy.ToLpstrArray(out numOids2);
111 if (!safeHandle2.IsInvalid)
112 {
113 pChainPara.RequestedIssuancePolicy.dwType = CertUsageMatchType.USAGE_MATCH_TYPE_AND;
114 pChainPara.RequestedIssuancePolicy.Usage.cUsageIdentifier = numOids2;
115 pChainPara.RequestedIssuancePolicy.Usage.rgpszUsageIdentifier = safeHandle2.DangerousGetHandle();
116 }
117 pChainPara.dwUrlRetrievalTimeout = (int)Math.Floor(timeout.TotalMilliseconds);
118 FILETIME fILETIME = FILETIME.FromDateTime(verificationTime);
119 CertChainFlags dwFlags = MapRevocationFlags(revocationMode, revocationFlag, disableAia);
120 if (!global::Interop.crypt32.CertGetCertificateChain(safeChainEngineHandle.DangerousGetHandle(), certificatePal.CertContext, &fILETIME, hStore, ref pChainPara, dwFlags, IntPtr.Zero, out var ppChainContext))
121 {
122 return null;
123 }
124 return new ChainPal(ppChainContext);
125 }
126
127 private static SafeChainEngineHandle GetChainEngine(X509ChainTrustMode trustMode, X509Certificate2Collection customTrustStore, bool useMachineContext)
128 {
129 if (trustMode == X509ChainTrustMode.CustomRootTrust)
130 {
131 using (SafeCertStoreHandle safeCertStoreHandle = ConvertStoreToSafeHandle(customTrustStore, returnEmptyHandle: true))
132 {
134 config.cbSize = Marshal.SizeOf<CERT_CHAIN_ENGINE_CONFIG>();
135 config.hExclusiveRoot = safeCertStoreHandle.DangerousGetHandle();
136 return global::Interop.crypt32.CertCreateCertificateChainEngine(ref config);
137 }
138 }
139 return useMachineContext ? SafeChainEngineHandle.MachineChainEngine : SafeChainEngineHandle.UserChainEngine;
140 }
141
142 private static SafeCertStoreHandle ConvertStoreToSafeHandle(X509Certificate2Collection extraStore, bool returnEmptyHandle = false)
143 {
144 if ((extraStore == null || extraStore.Count == 0) && !returnEmptyHandle)
145 {
147 }
148 return ((StorePal)StorePal.LinkFromCertificateCollection(extraStore)).SafeCertStoreHandle;
149 }
150
151 private static CertChainFlags MapRevocationFlags(X509RevocationMode revocationMode, X509RevocationFlag revocationFlag, bool disableAia)
152 {
153 CertChainFlags certChainFlags = (disableAia ? (CertChainFlags.CERT_CHAIN_DISABLE_AUTH_ROOT_AUTO_UPDATE | CertChainFlags.CERT_CHAIN_DISABLE_AIA) : CertChainFlags.None);
154 switch (revocationMode)
155 {
156 case X509RevocationMode.NoCheck:
157 return certChainFlags;
158 case X509RevocationMode.Offline:
159 certChainFlags |= CertChainFlags.CERT_CHAIN_REVOCATION_CHECK_CACHE_ONLY;
160 break;
161 }
162 return revocationFlag switch
163 {
164 X509RevocationFlag.EndCertificateOnly => certChainFlags | CertChainFlags.CERT_CHAIN_REVOCATION_CHECK_END_CERT,
165 X509RevocationFlag.EntireChain => certChainFlags | CertChainFlags.CERT_CHAIN_REVOCATION_CHECK_CHAIN,
166 _ => certChainFlags | CertChainFlags.CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT,
167 };
168 }
169
171 {
172 _chain = chain;
173 }
174
175 public static IChainPal FromHandle(IntPtr chainContext)
176 {
177 if (chainContext == IntPtr.Zero)
178 {
179 throw new ArgumentNullException("chainContext");
180 }
181 SafeX509ChainHandle safeX509ChainHandle = global::Interop.crypt32.CertDuplicateCertificateChain(chainContext);
182 if (safeX509ChainHandle == null || safeX509ChainHandle.IsInvalid)
183 {
185 }
186 return new ChainPal(safeX509ChainHandle);
187 }
188
189 public unsafe bool? Verify(X509VerificationFlags flags, out Exception exception)
190 {
191 exception = null;
192 CERT_CHAIN_POLICY_PARA pPolicyPara = default(CERT_CHAIN_POLICY_PARA);
193 pPolicyPara.cbSize = sizeof(CERT_CHAIN_POLICY_PARA);
194 pPolicyPara.dwFlags = (int)flags;
195 CERT_CHAIN_POLICY_STATUS pPolicyStatus = default(CERT_CHAIN_POLICY_STATUS);
196 pPolicyStatus.cbSize = sizeof(CERT_CHAIN_POLICY_STATUS);
197 if (!global::Interop.crypt32.CertVerifyCertificateChainPolicy(ChainPolicy.CERT_CHAIN_POLICY_BASE, _chain, ref pPolicyPara, ref pPolicyStatus))
198 {
199 int lastWin32Error = Marshal.GetLastWin32Error();
200 exception = lastWin32Error.ToCryptographicException();
201 return null;
202 }
203 return pPolicyStatus.dwError == 0;
204 }
205
207 {
208 global::Interop.crypt32.CertFreeCertificateChain(handle);
209 return true;
210 }
211
212 public void Dispose()
213 {
215 _chain = null;
216 chain?.Dispose();
217 }
218
220 {
221 if (dwStatus == CertTrustErrorStatus.CERT_TRUST_NO_ERROR)
222 {
223 return Array.Empty<X509ChainStatus>();
224 }
225 int num = 0;
226 for (uint num2 = (uint)dwStatus; num2 != 0; num2 >>= 1)
227 {
228 if ((num2 & (true ? 1u : 0u)) != 0)
229 {
230 num++;
231 }
232 }
234 int num3 = 0;
236 for (int i = 0; i < array2.Length; i++)
237 {
238 X509ChainErrorMapping x509ChainErrorMapping = array2[i];
239 if ((dwStatus & x509ChainErrorMapping.Win32Flag) != 0)
240 {
241 array[num3].StatusInformation = x509ChainErrorMapping.Message;
242 array[num3].Status = x509ChainErrorMapping.ChainStatusFlag;
243 num3++;
244 dwStatus &= ~x509ChainErrorMapping.Win32Flag;
245 }
246 }
247 int num4 = 0;
248 for (uint num5 = (uint)dwStatus; num5 != 0; num5 >>= 1)
249 {
250 if ((num5 & (true ? 1u : 0u)) != 0)
251 {
252 array[num3].Status = (X509ChainStatusFlags)(1 << num4);
253 array[num3].StatusInformation = System.SR.Unknown_Error;
254 num3++;
255 }
256 num4++;
257 }
258 return array;
259 }
260}
static readonly X509ChainErrorMapping[] s_x509ChainErrorMappings
Definition ChainPal.cs:33
unsafe X509ChainStatus[] ChainStatus
Definition ChainPal.cs:82
static SafeChainEngineHandle GetChainEngine(X509ChainTrustMode trustMode, X509Certificate2Collection customTrustStore, bool useMachineContext)
Definition ChainPal.cs:127
static bool ReleaseSafeX509ChainHandle(IntPtr handle)
Definition ChainPal.cs:206
SafeX509ChainHandle _chain
Definition ChainPal.cs:31
unsafe? bool Verify(X509VerificationFlags flags, out Exception exception)
Definition ChainPal.cs:189
ChainPal(SafeX509ChainHandle chain)
Definition ChainPal.cs:170
static unsafe ChainPal BuildChain(bool useMachineContext, ICertificatePal cert, X509Certificate2Collection extraStore, OidCollection applicationPolicy, OidCollection certificatePolicy, X509RevocationMode revocationMode, X509RevocationFlag revocationFlag, X509Certificate2Collection customTrustStore, X509ChainTrustMode trustMode, DateTime verificationTime, TimeSpan timeout, bool disableAia)
Definition ChainPal.cs:94
unsafe X509ChainElement[] ChainElements
Definition ChainPal.cs:61
static CertChainFlags MapRevocationFlags(X509RevocationMode revocationMode, X509RevocationFlag revocationFlag, bool disableAia)
Definition ChainPal.cs:151
static SafeCertStoreHandle ConvertStoreToSafeHandle(X509Certificate2Collection extraStore, bool returnEmptyHandle=false)
Definition ChainPal.cs:142
static X509ChainStatus[] GetChainStatusInformation(CertTrustErrorStatus dwStatus)
Definition ChainPal.cs:219
static IChainPal FromHandle(IntPtr chainContext)
Definition ChainPal.cs:175
static IExportPal LinkFromCertificateCollection(X509Certificate2Collection certificates)
Definition StorePal.cs:269
static void KeepAlive(object? obj)
Definition GC.cs:180
Definition GC.cs:8
static double Floor(double d)
static unsafe? string PtrToStringUni(IntPtr ptr)
Definition Marshal.cs:652
static int SizeOf(object structure)
Definition Marshal.cs:697
static string Unknown_Error
Definition SR.cs:118
static string Cryptography_InvalidContextHandle
Definition SR.cs:70
Definition SR.cs:7
X509ChainErrorMapping(CertTrustErrorStatus win32Flag, int win32ErrorCode, X509ChainStatusFlags chainStatusFlag)
Definition ChainPal.cs:22
static FILETIME FromDateTime(DateTime dt)
Definition FILETIME.cs:17
static readonly IntPtr Zero
Definition IntPtr.cs:18