I'm currently attempting to dynamically add a new website using the Microsoft.Web.Administration
library provided by IIS7+. This is going to be a part of an installation process in which a self-signed certificate needs to be added and bound to the HTTPS binding of this website.
My research took me to this post on StackOverflow which makes use of the BouncyCastle API: Generate self signed certificate on the fly. I have tried to replicate the functionality provided by IIS administration tool for creating such a certificate by making slight alterations to the code. I have modified the signature algorithm in both methods from SHA256WithRSA
to SHA1WithRSA
. I am also passing the SubjectName and IssuerName as the local machine's name using Dns.GetHostEntry("127.0.0.1").HostName
. I'm also setting the FriendlyName property of the X509Certificate2
object. The final modification involved passing the sl parameter of the addCertToStore
method as StoreLocation.LocalMachine
.
The following is a snippet of the code for dynamically creating the website and adding an HTTPS binding passing the cert.GetCertHash()
data as a parameter to the Site.Bindings.Add(...)
method which takes in the Binding Information, Certificate Hash and the Certificate Store Name (see MSDN documentation):
using (ServerManager iisManager = new ServerManager())
{
Site testSite = iisManager.Sites.Add(siteName, targetDir, sitePortNumber);
testSite.Bindings.Add("*:" + sitePortNumber + ":", certificateHash, "MY");
iisManager.CommitChanges();
}
The issue is that when attempting to commit the changes in IIS I get the following COMException
:
A specified logon session does not exist. It may already have been terminated. (Exception from HRESULT: 0x80070520)
Checking what happened in IIS it seems that the certificate is present but it is not being mapped correctly:
In the image linked above, the topmost certificate is the one being added dynamically i.e. the one mentioned in my post. The last one is a sample self-signed certificate created through the IIS administration tool.
The image linked above shows that the mapping between the HTTPS binding and the newly created SSL certificate failed.
Personal Certificates under Local Computer -> Personal:
This image contains a list of personal certificates which are present in certificate manager under the Local Computer section. The top one is the dynamically generated one whilst the bottom one was created using the IIS administration tool.
Above are the certificate details of the self-signed certificates created using the IIS administration tool (left hand side) and the dynamically generated one (right hand side).
Some of the most notable differences between the two of them are:
So the question is what is wrong with the code involving the creation of the self-signed certificate which is causing the mapping to the new IIS website to fail?
Thanks
Moved the SSL certificate from current user to local machine and it worked.
Here is my code to add the certificate.
I also noticed X509KeyStorageFlags.MachineKeySet
was the only flag that did not produce the error.
string certPath = "c:/test2/certName.p12";
string certPass = "TestPassword";
// Create a collection object and populate it using the PFX file
X509Certificate2Collection collection = new X509Certificate2Collection();
collection.Import(certPath, certPass, X509KeyStorageFlags.MachineKeySet);
foreach (X509Certificate2 cert in collection)
{
if(cert.Subject.Equals("CN=TestServer, O=Test"))
{
X509Store store1 = new X509Store(StoreName.Root, StoreLocation.LocalMachine);
store1.Open(OpenFlags.ReadWrite);
store1.Add(cert);
store1.Close();
}
if (cert.Subject.Equals("CN=TestClient, OU=Applications, O=Test"))
{
X509Store store1 = new X509Store(StoreName.My, StoreLocation.LocalMachine);
store1.Open(OpenFlags.ReadWrite);
store1.Add(cert);
store1.Close();
}
}
And here is my code to create the binding
ServerManager serverManager = new ServerManager();
var site = serverManager.Sites["Default Web Site"];
site.Bindings.Add("*:443:TestClient", certificate[0].GetCertHash(), "MY");
// site.Bindings.Add("*:443:TestClient", "https");
serverManager.CommitChanges();
User contributions licensed under CC BY-SA 3.0