I have developed a self-hosted api.
The api traffic needs to run over SSL.
Using a combination of netsh commands I have managed to successfully add the certificate and then bind a route to my service. Happy Days.
But, I have to write an installer to do this programmatically.
The problem is that when I add the certificate using my c# code, I can see it the certificate MMC but when I try to bind to it I get an error of:
SSL Certificate add failed, Error: 1312
A specified log-on session does not exist. It may already have been terminated.
As I say, when I do it manually with these steps I don't get the problem...
I can then see it in MMC under Personal > Certificates
And it lets me add the route using netsh from a command prompt - Happy Days.
When I try an do it programmatically with the following code:
public static bool ConfigureSSLCertificate(string file, string password, string method)
{
try
{
X509Certificate2 cert = new X509Certificate2(file, password);
var store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
store.Open(OpenFlags.ReadWrite);
if (!store.Certificates.Contains(cert))
{
if (method == "add")
{
store.Add(cert);
}
}
if (method == "remove")
{
store.Remove(cert);
}
return true;
}
catch { return false; }
}
The certificate appears in my MMC in exactly the same place but when I try and add the route with the exact same netsh command as before I get the error mentioned above:
netsh>http add sslcert ipport=0.0.0.0:8088 certhash=fb93ce2c4d8bd88c82e63e3372a050ba84f15e94 appid={bb14356a-a14f-4589-82ce-b80d38b8741e}
For some reason, when I add the certificate manually using the MMC and when I run my code something is different. Something that is stopping the route being added.
The solution is actually simple - I too have struggled with this, and have now found the solution. How can a manually added certificate differ from the programatically added one? Well, the short answer is to change your certificate load line to this:
X509Certificate2 cert = new X509Certificate2(file, password, X509KeyStorageFlags.MachineKeySet);
The key being that last parameter, which tells the certificate to save the private key stored in the machine location, and not the user location. Then the netsh
command can find the private key, and can work.
The solution was found in the explanatory text by Paul Stovell and some digging to see how I could set that flag when loading the certificate into the store.
Now, why I can't programmatically do the netsh function is another matter...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With