Guys, please tell me how to install *.crl in computer storage in C #. There is a code to install the certificate in root certificates:

 private static void InstallRootCertificate(string cerFileName) { X509Store store = new X509Store(StoreName.AuthRoot, StoreLocation.LocalMachine); X509Certificate2 certificate = new X509Certificate2(cerFileName); store.Open(OpenFlags.ReadWrite); store.Add(certificate); store.Close(); } 

But for obvious reasons, it is not suitable for crl. Thank you in advance.

    1 answer 1

    Although the question was asked a long time ago, and perhaps it is not relevant, I will still propose a solution, since the problem is interesting. Its solution can be useful, for example, when you need to automate the updating of certificate revocation lists on dozens of servers.

    Unfortunately, .NET does not provide any standard tools for solving this problem. You will have to use wrappers for crypt32.dll and unsafe code. Below is an example solution. It is based on the CrlFile class, which allows you to open a crl file and import it into standard storage ( System.Security.Cryptography.X509Certificates.X509Store class).

    Additional Information:

     class Program { static void Main(string[] args) { var store = new X509Store(StoreName.CertificateAuthority, StoreLocation.CurrentUser); store.Open(OpenFlags.ReadWrite); var crl = new CrlFile(@"d:\tmp\ca\root.crl"); crl.Import(store, CrlAddDisposition.CERT_STORE_ADD_REPLACE_EXISTING); store.Close(); } } public class CrlFile { // по уму здесь нужна реализация SafeHandle, // но чтобы не удлинять код оставим, как есть private IntPtr _context; private readonly string _file; public CrlFile(string file) { _file = file; } public bool Import(X509Store store, CrlAddDisposition disp, ref IntPtr storeContext) { EnsureCrlContext(); return Crypto32Interop.CertAddCRLContextToStore(store.StoreHandle, _context, (uint)disp, storeContext); } public bool Import(X509Store store, CrlAddDisposition disp) { var storeContext = IntPtr.Zero; return Import(store, disp, ref storeContext); } private unsafe void EnsureCrlContext() { if (_context != IntPtr.Zero) return; var context = new IntPtr(Crypto32Interop.CERT_QUERY_CONTENT_CRL); var handle = GCHandle.Alloc(_file, GCHandleType.Pinned); var data = handle.AddrOfPinnedObject(); bool ret = Crypto32Interop.CryptQueryObject( Crypto32Interop.CERT_QUERY_OBJECT_FILE, data, Crypto32Interop.CERT_QUERY_CONTENT_FLAG_CRL, Crypto32Interop.CERT_QUERY_FORMAT_FLAG_ALL, 0, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, new IntPtr(&context)); _context = Crypto32Interop.CertDuplicateCRLContext(context); Crypto32Interop.CertFreeCRLContext(context); handle.Free(); } ~CrlFile() { if (_context != IntPtr.Zero) Crypto32Interop.CertFreeCRLContext(_context); } } public static class Crypto32Interop { public const uint CERT_QUERY_CONTENT_CTL = 2; public const uint CERT_QUERY_CONTENT_CRL = 3; public const uint CERT_QUERY_OBJECT_FILE = 1; public const uint CERT_QUERY_FORMAT_BINARY = 1; public const uint CERT_QUERY_FORMAT_BASE64_ENCODED = 2; public const uint CERT_QUERY_FORMAT_ASN_ASCII_HEX_ENCODED = 3; public const uint CERT_QUERY_CONTENT_FLAG_CRL = (1 << (int)CERT_QUERY_CONTENT_CRL); public const uint CERT_QUERY_CONTENT_FLAG_CTL = (1 << (int)CERT_QUERY_CONTENT_CTL); public const uint CERT_QUERY_FORMAT_FLAG_BINARY = (1 << (int)CERT_QUERY_FORMAT_BINARY); public const uint CERT_QUERY_FORMAT_FLAG_BASE64_ENCODED = (1 << (int)CERT_QUERY_FORMAT_BASE64_ENCODED); public const uint CERT_QUERY_FORMAT_FLAG_ASN_ASCII_HEX_ENCODED = (1 << (int)CERT_QUERY_FORMAT_ASN_ASCII_HEX_ENCODED); public const uint CERT_QUERY_FORMAT_FLAG_ALL = (CERT_QUERY_FORMAT_FLAG_BINARY | CERT_QUERY_FORMAT_FLAG_BASE64_ENCODED | CERT_QUERY_FORMAT_FLAG_ASN_ASCII_HEX_ENCODED); [DllImport("crypt32.dll", CharSet = CharSet.Auto, SetLastError = true)] public static extern IntPtr CertDuplicateCRLContext(IntPtr pCrlContext); [DllImport("crypt32.dll", CharSet = CharSet.Auto, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool CertFreeCRLContext(IntPtr pCrlContext); [DllImport("crypt32.dll", CharSet = CharSet.Auto, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool CertAddCRLContextToStore( [In] IntPtr hCertStore, [In] IntPtr pCrlContext, [In] uint dwAddDisposition, [Out] IntPtr ppStoreContext); [DllImport("crypt32.dll", CharSet = CharSet.Auto, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool CryptQueryObject( [In] uint dwObjectType, [In] IntPtr pvObject, [In] uint dwExpectedContentTypeFlags, [In] uint dwExpectedFormatTypeFlags, [In] uint dwFlags, [Out] IntPtr pdwMsgAndCertEncodingType, [Out] IntPtr pdwContentType, [Out] IntPtr pdwFormatType, [In, Out] IntPtr phCertStore, [In, Out] IntPtr phMsg, [In, Out] IntPtr ppvContext); } public enum CrlAddDisposition : uint { CERT_STORE_ADD_NEW = 1, CERT_STORE_ADD_USE_EXISTING = 2, CERT_STORE_ADD_REPLACE_EXISTING = 3, CERT_STORE_ADD_ALWAYS = 4, CERT_STORE_ADD_REPLACE_EXISTING_INHERIT_PROPERTIES = 5, CERT_STORE_ADD_NEWER = 6, CERT_STORE_ADD_NEWER_INHERIT_PROPERTIES = 7, } 
    • Wow! Is it possible to take the address from context without fixed ? - VladD
    • one
      @VladD, IntPtr is a structure, so its instance is created on the stack. For a stack variable within a function, you can take an address without fixed. - kmv
    • Well, yes, but this is a rather fragile assumption, since the function can turn into an iterator or an async function, and the variables go to hip. - VladD
    • @VladD coroutines can not be unsafe, the compiler swears - kmv
    • one
      However, this is a fragile assumption. In the C # standard, the stack is not mentioned at all, so conformal implementation (for example, on a system with no stack concept) has the right to put all variables in a heap. - VladD