Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why do I get an Access Denied error when creating an X509Certificate2 object?

We have some unit tests which have PFX certificates embedded in them. These certificates are read during test execution and turned into X509Certificate2 objects. Unfortunately, when run as an unprivileged user, we get Access Denied exceptions:

using (var s = EmbeddedResourceUtilities.GetEmbeddedResourceAsStream(typeThatContainsEmbeddedResource, certFileName))
{
    if (s == null)
    {

        throw new ApplicationException(String.Format("Embedded certificate {0} for type {1} not found.", certFileName, typeThatContainsEmbeddedResource.FullName));
    }

    try
    {
        var bytes = new byte[s.Length];
        s.Read(bytes, 0, (int)s.Length);
        return new X509Certificate2(bytes);
    }
    catch (Exception ex)
    {
        throw new ApplicationException(String.Format("Error loading embedded certificate {0} for type {1}.", certFileName, typeThatContainsEmbeddedResource.FullName), ex);
    }
}

Here's the exception:

System.Security.Cryptography.CryptographicException : Access denied.
at System.Security.Cryptography.CryptographicException.ThrowCryptographicException(Int32 hr)
at System.Security.Cryptography.X509Certificates.X509Utils._LoadCertFromBlob(Byte[] rawData, IntPtr password, UInt32 dwFlags, Boolean persistKeySet, SafeCertContextHandle& pCertCtx)
at System.Security.Cryptography.X509Certificates.X509Certificate.LoadCertificateFromBlob(Byte[] rawData, Object password, X509KeyStorageFlags keyStorageFlags)
at System.Security.Cryptography.X509Certificates.X509Certificate2..ctor(Byte[] rawData)

I've tried modifying the constructor to use an empty password and explicit keyset flags, but that doesn't fix it:

// this doesn't work, either
return new X509Certificate2(bytes, String.Empty, X509KeyStorageFlags.MachineKeySet);

I've read elsewhere that I should give my unprivileged user increased permissions on the MachineKeys directory, but I'm loathe to do that as it would allow production code to assume those permissions are available on that directory outside the test environment.

Is there any way of allowing an unprivileged user to load an X509Certificate from a file?

like image 602
Aaron Jensen Avatar asked Mar 08 '13 01:03

Aaron Jensen


2 Answers

This is my best guess about what's going on.

The X509Certificate2 constructor creates temporary public/private key objects in the Machine Keys directory (I believe via the Windows local security authority). Because the our unprivileged user doesn’t have access to these keys or the Machine Keys directory, the tests fail.

Our solution was to update our environment setup scripts to install these test certificates ahead of time, grant the unprivileged user permissions to them, and re-write the tests to load the certificates from the appropriate certificate store.

like image 174
Aaron Jensen Avatar answered Sep 21 '22 23:09

Aaron Jensen


Using the "X509KeyStorageFlags.UserKeySet" flag in the X509Certificate2 constructor helped me.

like image 31
dajuric Avatar answered Sep 20 '22 23:09

dajuric