in src/Microsoft.Diagnostics.Runtime/Utilities/Platform/AuthenticodeUtil.cs [29:135]
public static bool VerifyDacDll(string dacPath, out IDisposable? fileLock)
{
fileLock = null;
string filePath = Path.GetFullPath(dacPath);
if (!File.Exists(filePath))
{
throw new FileNotFoundException(filePath);
}
if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
Trace.TraceError("VerifyDacDll: not supported on Linux/MacOS");
return false;
}
FileStream fs = File.OpenRead(filePath);
fileLock = fs;
WINTRUST_FILE_INFO trustInfo = new()
{
cbStruct = (uint)sizeof(WINTRUST_FILE_INFO),
hFile = fs.SafeFileHandle.DangerousGetHandle(),
};
WINTRUST_DATA trustData = new()
{
cbStruct = (uint)sizeof(WINTRUST_DATA),
dwUIChoice = 2, // WTD_UI_NONE
dwProvFlags = 0x1040, // WTD_REVOCATION_CHECK_CHAIN | WTD_CACHE_ONLY_URL_RETRIEVAL
dwStateAction = 1, // WTD_STATEACTION_VERIFY
dwUnionChoice = 1, // WTD_CHOICE_FILE
pFile = new IntPtr(&trustInfo)
};
Guid WINTRUST_ACTION_GENERIC_VERIFY_V2 = new(0xaac56b, 0xcd44, 0x11d0, 0x8c, 0xc2, 0x0, 0xc0, 0x4f, 0xc2, 0x95, 0xee);
int result = WinVerifyTrust(IntPtr.Zero, &WINTRUST_ACTION_GENERIC_VERIFY_V2, &trustData);
try
{
if (result != 0)
{
Trace.TraceError($"VerifyDacDll: WinVerifyTrust failed {result:X} {filePath}");
return false;
}
IntPtr provider = WTHelperProvDataFromStateData(trustData.hWVTStateData);
if (provider == IntPtr.Zero)
{
Trace.TraceError($"VerifyDacDll: WTHelperProvDataFromStateData failed {filePath}");
return false;
}
CRYPT_PROVIDER_SGNR* signer = WTHelperGetProvSignerFromChain(provider, 0, false, 0);
if (signer == null)
{
Trace.TraceError($"VerifyDacDll: WTHelperGetProvSignerFromChain failed {filePath}");
return false;
}
CERT_CHAIN_POLICY_PARA parameters = new()
{
cbSize = (uint)sizeof(CERT_CHAIN_POLICY_PARA)
};
CERT_CHAIN_POLICY_STATUS status = new()
{
cbSize = (uint)sizeof(CERT_CHAIN_POLICY_STATUS)
};
IntPtr policyOID = new(CERT_CHAIN_POLICY_MICROSOFT_ROOT);
bool bTrusted = CertVerifyCertificateChainPolicy(policyOID, signer->pChainContext, ¶meters, &status) && status.dwError == 0;
if (!bTrusted)
{
Trace.TraceError($"VerifyDacDll: chain can't be verified for the specified policy or does not meet the policy: {status.dwError:X} {filePath}");
return false;
}
CRYPT_PROVIDER_CERT* leafCert = WTHelperGetProvCertFromChain(signer, 0);
if (leafCert == null)
{
Trace.TraceError($"VerifyDacDll: could not obtain the leaf most cert in signing chain {filePath}");
return false;
}
using X509Certificate2 cert = new(leafCert->pCert);
foreach (X509EnhancedKeyUsageExtension ekuExt in cert.Extensions.OfType<X509EnhancedKeyUsageExtension>())
{
foreach (Oid oid in ekuExt.EnhancedKeyUsages)
{
if (oid.Value == DOTNET_DAC_CERT_OID)
{
return true;
}
}
}
Trace.TraceError($"VerifyDacDll: could not find DAC special OID EKU extension {filePath}");
return false;
}
finally
{
trustData.dwStateAction = WTD_STATEACTION_CLOSE;
result = WinVerifyTrust(IntPtr.Zero, &WINTRUST_ACTION_GENERIC_VERIFY_V2, &trustData);
}
}