I'm working on a simple tool for a test environment where I have to set up a few dozen sites through C# code. Thus I have a list of (sub)domain names (and other properties) in an array and I run through it to create the sites with their bindings. This works fine, except for the HTTPS bindings where I need to bind the proper SSL certificates from the store. For whatever reason, all sites end up with the same certificate.
The code is relatively straightforward. I first open the certificate store like this:
var store = new X509Store("MY", StoreLocation.LocalMachine);
store.Open(OpenFlags.OpenExistingOnly);
I then find for each domain the certificate where Certificate.Subject.EndsWith(domain.Domain)
which also works fine. I display the hash and name and these are correct.
I then move on to create each domain with basic binding on port 80:
var site = manager.Sites.Add(domain.Name, "http", $"*:80:{domain.Domain}", domain.Folder);
And if a certificate is found, I'll also bind the HTTPS connection:
site.Bindings.Add($"*:443:{domain.Domain}", domain.Certificate.GetCertHash(), "MY");
I also write the hash to the console just to make sure I have the right value! And afterwards manager.CommitChanges();
gets called to commit the added site.
Then I check in IIS which certificate is attached and it turns out to be the wrong one! So each site has a certificate error and I don't understand why it goes wrong as everything seems to be correct.
So after the commit I again print the hash by enumerating the bindings to the console and it still shows the right hash. This is becoming really annoying!
As for the certificate that does gets picked... It seems to be the certificate for the last domain in my list. But why it gets assigned to all other bindings?
Is this a bug in the IIS manager?
A minor discovery: I went to IIS and changed the certificate to the proper one. This results in this message in IIS:
This is interesting as it will change the certificates for all the sites when I click "Yes". If I click "No" then I get back to the edit dialog so that doesn't solve anything. Don't think it's related, though...
CodePudding user response:
Dum! Dum! Dumb! Solved it...
site.Bindings.Add($"*:443:{domain.Domain}", domain.Certificate.GetCertHash(), "MY", SslFlags.Sni);
It's the SslFlags.Sni flag in the end, as 5th parameter, that does the trick. It stands for "Server Name Indication", duh! And apparently you need it if you bind certificates by domain name...
Such a minor thing can be so annoying...