[y’know, I always thought that was pronounced “pr(eye)mer”, not “pr(imm)er”…]
So here I am with Visual Studio 2008 and .NET Framework 3.5, and I can’t for the life of me find a managed class that would submit an enrollment request to a Windows Certificate Server. I know that the System.Security namespace has had a bunch of classes available (e.g. .Cryptography.Pkcs, .Cryptography.X509Certificates) that assist in the digital certificates arena. However, there’s nothing in the framework (at least through v3.5) that appears to map in any way to the functionality in XENROLL (the Win32 container for certificate enrollment, which included COM interfaces) or CERTENROLL (the same control renamed in Windows Vista).
The only way I knew so far to take advantage of Win32 functionality in .NET was to use p/invoke to map/marshal the unmanaged call with a .NET “wrapper”. However, when I went looking on pinvoke.net for anything mentioning XENROLL or CERTENROLL, I came up snake eyes.
The clue that finally broke the mystery wide open for me was this article (“XENROLLLib reference for C# and VB.NET”), that seemed to indicate there was some way of getting a set of classes that exposed the XENROLL functionality. I tried pasting some of the example code into a new Visual Studio project but that didn’t work, and when I searched the Object Browser for any default classes that contained XENROLL, XENROLLLib, CENROLL or other terms that looked like they would be base classes, I still didn’t succeed.
I don’t recall how anymore, but somewhere I connected a few dots between that article and “adding a reference” to the COM object, and then it clicked! Damn, it seems so obvious once you know what you were supposed to do. All I had to do was look in the Solution Explorer view, right-click on References, choose “Add Reference…”, choose the COM tab, and select the Component name “xenroll 1.0 Type Library”.
Oh, that’s right, now I remember: there was some discussion about XENROLL being a COM object, and other discussions that helped me piece together various ways to “wrap” a COM object for use by managed code.
Your best bet would be to find the Primary Interop Assembly (PIA) — i.e. the “official” RCW for the COM object in which you’re interested. [Unfortunately, the developers of XENROLL have so far refused to acknowledge any need for a PIA for XENROLL.]
Another option would be to build an interop assembly to wrap the COM object, which requires some degree of hand-coding, but not as bad as writing the p/invoke signatures around each and every function exposed by that COM object.
However, the easiest of the “do-it-yourself” options is by adding a Reference to the COM object, and letting Visual Studio “magically”, automatically create the interop assembly (aka/or RCW) that’s needed to access the functions.
It turns out that the XENROLLLib article I’d found was really just documenting what was exposed automatically by Visual Studio when you add the Reference to “xenroll 1.0 Type Library”, but that wasn’t obvious to me (and may not be obvious to most folks who happened to stumble on the article).
Tip: the IC* interfaces are COM (scripting) oriented, and the I* interfaces are C++ oriented. Thus, any manual work to “wrap” the native cert enrollment code in .NET interop assemblies should probably focus on IEnroll4 (which inherits from IEnroll2 and IEnroll), rather than ICEnroll4 and its predecessors.
So if I’m going to add COM references in my code to create a Cert enrollment assembly, do I just need to reference XENROLLib? Apparently not — this discussion indicates that I’ll also need a reference “CERTCLIENTLib” to kick off the actual submission of the Certificate enrollment request to the Windows CA’s web interface.
And which COM reference will this require then? A quick Google search on CERTCLIENTLib.CCertRequest should give me a lead pretty quick. And bingo! The second link is to this article, which mentions “…code below that uses the CertCli library get the certificate from the CA”, and this corresponds in Visual Studio’s “Add Reference” COM tab to “CertCli 1.0 Type Library”. Now I’m getting the hang of this!
One open question: how do I go about actually using the Interfaces vs. the Class implementations such as CEnroll or CEnrollClass?
Summary of Findings
So there we go: to write a certificate enrollment client in C# requires a whole lot of COM interop, using COM References to “xenroll 1.0 Type Library” and “CertCli 1.0 Type Library”. That, plus leaning heavily on samples from others who’ve gone down this path before (like here and here), should enable a pretty reusable .NET certificate enrollment library. [Now if only Microsoft’s CERTENROLL team would add “releasing a CERTENROLL PIA” to their development schedule.]
These will be useful at least for myself, even if they’re not useful to anyone else.
MSDN: implementation of initializing a certificate request using a cert template (including C# code in Community section)
some native code & discussion of using IEnroll “class” (though I don’t know if the concept is known as a “class” in Win32)
An MSDN newsgroup article on requesting a certificate in managed code