Search code examples
c#x509syncfusion

How do I access X.509 certificates stored in a service account?


I'm trying to digitally sign a PDF document using Syncfusion PDF 10.4, like so:

PdfLoadedDocument document = new PdfLoadedDocument(inputStream);
PdfCertificate certificate = PdfCertificate.FindBySubject(certificateStoreType, certificateSubjectName);

PdfSignature signature = new PdfSignature(document, document.Pages[0], certificate, "Signatur");
signature.Bounds = new RectangleF(new PointF(5, 5), new SizeF(100, 100));

This works great for my local user account after installing a suitable certificate using MMC (adding the Certificates snap-in for My user account and storing it in Personal), but not for a service (choosing Service account this time, and picking my service). Running the same code results in no suitable certificate being found, i.e. certificate is null. Furthermore, PdfCertificate.GetCertificates() throws an AccessViolationException, which I assume is a bug on Syncfusion's end.

I can, however, reproduce the same problem without Syncfusion code:

var store = new System.Security.Cryptography.X509Certificates.X509Store("My");
store.Open(System.Security.Cryptography.X509Certificates.OpenFlags.ReadOnly);
foreach (var item in store.Certificates)
{
    …
}

Run as my own user, the certificate shows up (as do all the others shown in MMC under Personal), but if I debug the service (by running it, then invoking System.Diagnostics.Debugger.Launch()), I only get a "CN=LOCAL SERVICE" certificate, which doesn't show up in MMC at all.

I'm assuming that I need to A) tell it to open the correct certificate store, or B) change something about the way the service is installed or run, such as giving it a different identity, enabling UserInteraction, etc. Currently, it runs using LocalService and with UserInteraction disabled.


Solution

  • The answer appears to be that .NET doesn't support accessing service account certificate stores without P/Invoke or the like:

    I don't think that any of the .NET APIs allow access to the Services Certificate store.

    However, you can install the certificate into the CurrentUser store of the account that the service runs under.

    I've changed the service to run under its own user (which doesn't need admin rights), ran mmc.exe as that user using runas, and imported the certificate to that user's personal store.