Keith Stein
Keith Stein

Reputation: 6724

X509Certificate2 only works temporarily when added to Current User store as Administrator

When installing a self-signed certificate for use in VPN authentication, I ran into an interesting problem: the VPN would successfully authenticate for some time after the installation, but after a reboot I would start getting the following message:

Error 798: A certificate could not be found that can be used with this Extensible Authentication Protocol

(I actually wrote a full question while I was debugging this, when I didn't know the cause, which you can find here: Some clients can only authenticate to VPN when connecting as Administrator. But to summarize: after a reboot users would start getting this message and from that point the connection could only be established by connecting as Administrator [i.e. running rasphone or rasdial as Administrator].)

It's worth noting that redoing the installation would make the connection work again until the next reboot.

What ended up being important- and the reason this belongs on StackOverflow and not another site- is that I was installing this certificate via code. I had written a program to automate the VPN installation; it did a number of things, one of which was installing the client certificate for authentication. Here is an abbreviated version of the certificate installation code:

Dim Certs As New X509Certificate2Collection()
Certs.Import(PfxFileName, Password, X509KeyStorageFlags.PersistKeySet)

Dim ClientCert, IssuerCert As X509Certificate2

If Certs(0).HasPrivateKey Then
    ClientCert = Certs(0)
    IssuerCert = Certs(1)
Else
    ClientCert = Certs(1)
    IssuerCert = Certs(0)
End If

Using Store As New X509Store(StoreName.Root, StoreLocation.LocalMachine)
    Store.Open(OpenFlags.ReadWrite)
    Store.Add(IssuerCert)
End Using

Using Store As New X509Store(StoreName.My, StoreLocation.CurrentUser)
    Store.Open(OpenFlags.ReadWrite)
    Store.Add(ClientCert)
End Using

My pfx files always had two certificates: the client's with its private key, and the root without one. The root certificate needed to go in cert:/LocalMachine/Root and the client certificate needed to go in cert:/CurrentUser/My.

Using the above code, the previously stated problem would result.

Upvotes: 0

Views: 527

Answers (1)

Keith Stein
Keith Stein

Reputation: 6724

Using the process of elimination, I ran each part of my custom installation software and found that it was the re-installtion of the certificate alone (using the code above) that caused the connection to temporarily start working again. I then tried installing the certificate manually (by double-clicking the pfx file and using the dialog box).

I found that when I installed the certificate manually, the VPN connection worked stabily, but when I installed it via the previous code, it only worked until my next reboot. This indicated to me that there must be some difference between what my code was doing, and what the dialog box was doing.

And then it hit me: my program is running as Administrator. But the dialog box for adding a certificate to the CurrentUser store never gives a UAC prompt, so it's running under my normal user context.

Now, there are parts of my program that do need to run as Administrator, so I had to rework the whole thing to use two processes (one admin and one non-admin) to do different parts of the installation. I won't get into that here, but once I had it all working I tried running the following part of the code as a non-admin:

Using Store As New X509Store(StoreName.My, StoreLocation.CurrentUser)
    Store.Open(OpenFlags.ReadWrite)
    Store.Add(ClientCert)
End Using

And it worked! As long as I added the client certificate to the CurrentUser store as a non-admin, the VPN connection was able to consistantly connect across reboots.

I still don't quite understand why running the code as Administrator causes the problems it does. The certificate does appear in the cert:/CurrentUser/My, but it just doesn't work once it's there. Maybe it has something to do with some hidden permissions on the associated private key? That might explain why connecting as Administrator always worked, but not why connecting as a non-admin worked until a reboot occurred.

Upvotes: 1

Related Questions