views:

975

answers:

4

I need to download and install about 50 CRLs once a week and install them on several Windows servers. Downloading is the easy part, is there a way I could script the CRL import process?

+2  A: 

I don't know a way to do it via script. Can you write C code? If I understand what you want to do, you will use the CryptUiWizImport function, and the CRYPTUI_WIZ_IMPORT_SRC_INFO structure.

Here's a sample of code that installs a Cert; the corresponding CRL import is similar.

Addendum:
This post points out that Win32 APIs (such as CryptUiWizImport) are not directly accessible from PowerShell, and then describes a possible workaround: from within the PowerShell script, dynamically generate and compile C# code that does the P/Invoke stuff, and then run the resulting assembly. This would allow you to do the CryptUiWizImport strictly from a powershell script, although it would be a pretty exotic one.

Cheeso
I wrapped the CryptUIWizImport function as a C# console application and it works like a charm for installing both certs and CRLs. Thank you very much!
Goyuix
You interested in posting the source, to help the next person?
Cheeso
I would be really interested in the source... for I have exactly the same problem.
Mephisztoe
+1  A: 

In Powershell there is a Cert: provider which represents the certificate store. Manipulating it is done via the standard cmdlets so you might be able to integrate a revocation list there somewhere. I just don't know enough about how Windows handles certificates to be of any further help here.

Joey
+2  A: 

Hm. Is there any reason not to use the certutil.exe utility? I can import a Certificate Revocation List into the appropriate store by running the following command:

certutil -addstore CA <FileName>.crl
Mephisztoe
certutil is not part of a standard installation. I believe it only is installed when certificate services have been installed (though I could be wrong).
Goyuix
+1  A: 

Here is my final source (slightly scrubbed for the public) - but should work. I won't change the accepted answer, but I do hope this helps (as does upvoting the question and answers!).

Note: This will import both a CRL or a regular certificate into the LOCAL MACHINE Trusted Root store. Swapping the below string "ROOT" to "MY" should change it to work for the Current User store.

using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;

namespace ConsoleApplication2
{
  class Program
  {
    public struct CRYPTUI_WIZ_IMPORT_SRC_INFO
    {
      public Int32 dwSize;
      public Int32 dwSubjectChoice;
      [MarshalAs(UnmanagedType.LPWStr)]public String pwszFileName;
      public Int32 dwFlags;
      [MarshalAs(UnmanagedType.LPWStr)]public String pwszPassword;
    }

    [DllImport("CryptUI.dll", CharSet = CharSet.Auto, SetLastError = true)]
    public static extern Boolean CryptUIWizImport(
      Int32 dwFlags,
      IntPtr hwndParent,
      IntPtr pwszWizardTitle,
      ref CRYPTUI_WIZ_IMPORT_SRC_INFO pImportSrc,
      IntPtr hDestCertStore
    );

    [DllImport("CRYPT32.DLL", CharSet = CharSet.Auto, SetLastError = true)]
    public static extern IntPtr CertOpenStore(
      int storeProvider,
      int encodingType,
      IntPtr hcryptProv,
      int flags,
      String pvPara
    );

    public const Int32 CRYPTUI_WIZ_IMPORT_SUBJECT_FILE = 1;
    public const Int32 CRYPT_EXPORTABLE = 0x00000001;
    public const Int32 CRYPT_USER_PROTECTED = 0x00000002;
    public const Int32 CRYPTUI_WIZ_NO_UI = 0x0001;

    private static int CERT_STORE_PROV_SYSTEM = 10;
    private static int CERT_SYSTEM_STORE_CURRENT_USER = (1 << 16);
    private static int CERT_SYSTEM_STORE_LOCAL_MACHINE = (2 << 16);

    static void Main(string[] args)
    {
      if (args.Length != 1)
      {
        Console.WriteLine("Usage: certimp.exe list.crl");
        Environment.ExitCode = 1;
      }
      else
      {
        IntPtr hLocalCertStore = CertOpenStore(
          CERT_STORE_PROV_SYSTEM,
          0,
          IntPtr.Zero,
          CERT_SYSTEM_STORE_LOCAL_MACHINE,
          "ROOT"
        );

        CRYPTUI_WIZ_IMPORT_SRC_INFO importSrc = new CRYPTUI_WIZ_IMPORT_SRC_INFO();
        importSrc.dwSize = Marshal.SizeOf(importSrc);
        importSrc.dwSubjectChoice = CRYPTUI_WIZ_IMPORT_SUBJECT_FILE;
        importSrc.pwszFileName = args[0];
        importSrc.pwszPassword = null;
        importSrc.dwFlags = CRYPT_EXPORTABLE | CRYPT_USER_PROTECTED;

        if (!CryptUIWizImport(
            CRYPTUI_WIZ_NO_UI,
            IntPtr.Zero,
            IntPtr.Zero,
            ref importSrc,
            hLocalCertStore
          ))
        {
          Console.WriteLine("CryptUIWizImport error " + Marshal.GetLastWin32Error());
          Environment.ExitCode = -1;
        }
      }
    }
  }
}
Goyuix