How to create a self-signed wildcard SSL certificate for IIS 6? - ssl

I'm trying to create a self-signed wildcard SSL certificate for use on a number of development and test servers running IIS 6. Following various guides has led to a couple ways of generating the certificates, but I haven't had any luck getting it to work. The most successful ways I've had were following this OpenSSL guide and using makecert.exe like so:
makecert.exe -r -b 01/01/2009 -e 01/01/2042 -sr LocalMachine -ss MY -a sha1 -n CN="*.example.com" -sky exchange -pe -eku 1.3.6.1.5.5.7.3.1 -sy 12 -sp "Microsoft RSA SChannel Cryptographic Provider" wildcard.cer
Both of which generate certificates that IIS 6 will accept, but when I actually try to view the site I get the following error in firefox:
Data Transfer Interrupted
The connection to dev.example.com was interrupted while the page was loading.
IE just gives:
Internet Explorer cannot display the webpage
Most likely causes:
You are not connected to the Internet.
The website is encountering problems.
There might be a typing error in the address.
This error happens whether I try to access it by domain name, machine name, localhost, local ip, or loopback ip.
So...how can I create a self-signed wildcard cert that IIS 6 will work with? Or how can I fix the problems I'm experiencing with the ones I've already created?

You can use the IIS 6 Resource Kit provided by MS, an command line app called SelfSSL. It can generate the SSL key and import it into your IIS installation.
IIS 6 Resource Kit

you can do a wildcard certificate with *.domain.local and multiple ssl protocols by using the c:\inetpub\adminscripts adsutil.vbs set w3svc[siteid]\SecureBindings ":443:name.domain.local"

Did you realize that you would need to change from "example.com" to some thing more appropriate to your situation ("localhost" might be one of them during testing).

For IIS 7 - there is a wzard to do this. It takes about 30 seconds to setup.
For IIS 6 - it's a bit trickier. It takes about 30 minutes to setup.
Which one are you using?
I strongly recommend moving to IIS 7 - it is very foreign at first, but they've made a lot of improvements.
Given that you probably can't upgrade to IIS 7, I had to do the following to implement what you want in IIS 6.
1) create certificate server
2) generate request
3) grant request
4) install certificate
It's a bit of a pain to setup the certificate authority server, but it comes with Windows Server and the walkthrough is pretty straight forward.

We discovered that the Certificate Authority wasn't being trusted because of domain settings and was causing the errors. We ended up deploying a star cert generated by a trusted CA and that cleared up the problems.

Related

LDAPS Microsoft Active Directory Multiple Certificates RFC6125

We have an Microsoft Active Directory Domain with a large pool of domain controllers (DC) that are are setup with LDAP. These are all setup with LDAPS and uses Certificate Services via a template to setup a certificate with the domain name (i.e. test.corp) in the Subject Alternate Name (SAN) for the LDAPS server to serve.
Since these are DC's, DNS is setup in a pool for each these systems to respond to requests to test.corp in a round robin fashion.
Each of these DC's have multiple templates and multiple certificates in the Local Computer\Personal Certificate Store.
Upon testing, using a nodejs module, ldapjs when making a LDAPS request using the domain name, test.corp we notice that a handful of servers fail with the following message:
Error [ERR_TLS_CERT_ALTNAME_INVALID]: Hostname/IP does not match
certificate's altnames: Host: test.corp. is not in the cert's
altnames: othername:, DNS:.test.corp
As we investigated we found that these handful of LDAPS servers are serving the incorrect certificate. We determined this by using the following command
openssl s_client -connect .test.corp:636
If you take the certificate section of the output and put it in a file and use a tool such as the Certificate manager or certutil to read the file, you can see the certificate is not the correct one. (It does not have the domain "test.corp" SAN). We also verified this by comparing the Serial Numbers
As we investigated, since we have DC's that have multiple certificates in the Local Computer\Personal Certificate store, we came across the following article:
https://social.technet.microsoft.com/wiki/contents/articles/2980.ldap-over-ssl-ldaps-certificate.aspx
It suggests putting the certificate from the local computer\Personal certificate store to the Active Directory Domain Service\Personal store. We followed the steps outlined but we found the same results.
Upon further investigation, it was suggested to use a tool called ldp or adsiedit. We then proceeded to use these tools and spoofed the local machine's host file we were doing the test from, to point the domain (test.corp) to the ip's of one of the DC's that are giving us trouble. After a restart to clear any cache we tested the "ldp" and "adsiedit" tools to connect to test.corp. These systems did not report any errors.
We found this odd, we then ran the openssl command to see what certificate it was serving from this same system and we found it was still serving the incorrect certificate.
Upon further research, it appears that the "ldp" upon selecting the SSL checkbox and "adsiedit" tools were not compliant with RFC6125, specifically B.3
https://www.rfc-editor.org/rfc/rfc6125#appendix-B.3
, which basically states the identity of the certificate must match the identity of the request otherwise the handshake would fail. This identity verification is done by using the certificate common name (CN) or the SAN.
Based on this appears the tools "ldp" and "adsiedit" are not conforming to the RFC6125 standard.
All this to say, we need to first fix the handful of domain controllers that are serving the correct certificate. We are open to suggestions since we have been working on this problem for the past few months. Second, is there a way to get the MS tools in question to work to the RFC6125 standard?
This has been moved to:
https://serverfault.com/questions/939515/ldaps-microsoft-active-directory-multiple-certificates-rfc6125
RFC6125 specifically states that it does not supersede existing RFCs. LDAP cert handling is defined in RFC4513. Outside of that, RFC6125 has significant flaws. See also https://bugzilla.redhat.com/show_bug.cgi?id=1740070#c26
LDP will supposedly validate the SSL against the client store if you toggle the ssl checkbox on the connection screen.
That said, I'm not surprised that neither it nor ADSI edit enforce that part of the standard given they are often used to configure or repair broken configurations. Out of the box and without Certificate Services they use self signed certs on LDAPS. I would wager 80% of DCs never get a proper certificate for LDAP. If they enforced it most wouldn't be able to connect. A better design decision would have been to toggle off the validation.
I use a similar openssl command to verify my own systems. I think it's superior to LDP even if LDP were to validate the certificate. To save you some effort, I would suggest using this variant of the openssl command:
echo | openssl s_client -connect .test.corp:636 2>/dev/null | openssl x509 -noout -dates -issuer -subject -text
That should save you having to output to a file and having to read it with other tools.
I've found LDAPS on AD to be a huge pain for the exact reasons you describe. It just seems to pick up the first valid cert it can find. If you've already added it to the AD DS personal store, I'm not sure where else to suggest you go other than removing some of tother certs from the DCs computer store.

Testing if a URL requires SNI

I have a site which is served over HTTPS, but which iTunes can't find. My suspicion is that it's related to the iTunes backend server being Java 6, and Java 6 not supporting SNI. SSL Labs seems to hint that my site does require SNI (see this report, and search for SNI), but I can't think why. Have I misunderstood multi-domain certificates? I've got multiple sites running on the same server, but my understanding was that as long as all the URLs were listed as Subject Alternative Names on the certificate, that all would be well.
Does anyone know a good way to check if a URL requires SNI support on the client to access it? I don't have a Windows XP/Java 6 install around to play with sadly.
The reports from SSLLabs regarding SNI are usually correct. Your understanding that SNI is not needed if your certificate contains all possible hosts is correct too. But, not needed in theory does not mean that your server setup does not require SNI anyway.
I don't have a Windows XP/Java 6 install around to play with sadly.
Given that you only specify what you don't have I will assume that you have everything else which might be used. A simple way to check is openssl:
# without SNI
$ openssl s_client -connect host:port
# use SNI
$ openssl s_client -connect host:port -servername host
Compare the output of both calls of openssl s_client. If they differ in the certificate they serve or if the call w/o SNI fails to establish an SSL connection than you need SNI to get the correct certificate or to establish a SSL connection at all.
An easy way to check if a site relies on SNI is this:
openssl s_client -servername alice.sni.velox.ch -tlsextdebug -msg \
-connect alice.sni.velox.ch:443 2>/dev/null | grep "server name"
And if in that output you see the following, it means the site is using SNI.
TLS server extension "server name" (id=0), len=0
The above is a summary of an answer at serverfault.
Nginx in general, and your site in particular, accepts but doesn't require SNI. To test this you cannot easily use Oracle Java out of the box, because its cacerts does not include DST Root CA X3 which is the root cert used (initially) by 'Let's Encrypt' who issued your site's cert; this is true for all versions of Oracle Java up to current (8u74). Windows (hence IE and Chrome on Windows) and Firefox do have this root cert; I can't say for other OS or browsers.
To fix this so you can easily test, either:
use Oracle Java 6 but modify JRE/lib/security/cacerts to add the DSTX3 cert, obtained either from your OS or browser, or by following the link at https://letsencrypt.org/certificates/ to https://www.identrust.com/certificates/trustid/root-download-x3.html -- except that page nonstandardly gives you only the base64 body of the cert so you must manually add the PEM header and trailer lines before Java keytool will import it.
use Oracle Java 6 as-is but configure your application (with system properties) to use a custom truststore which you create containing the DSTX3 cert as above.
use a version of Java 6 that does include this root cert in cacerts. In particular I use CentOS 6 and its openjdk packages (for 6, 7, and 8) use a systemwide CA 'bundle' that includes DSTX3, which is what made it easy for me to do this test. I expect, but can't confirm, that other RedHat variants do the same. For other distros and platforms I can't say; if not, see above.
Monitor the connection attempt with wireshark or similar to see that the ClientHello does not contain SNI, but the connection succeeds and is successfully used for an HTTP request.
If you actually want to communicate with the server instead of testing it for SNI, simply omit the final 'monitor' step.

What is Apache's OpenSSL and why does one server have it but another not

I'm working with two servers; one localhost one on the web. Both are http; I don't have an SSL certificate installed on either.
When I'm trying to make a Curl request to an https url (in this case the Facebook API), one of the servers works and the other doesn't. The CURL error is "SSL certificate problem: unable to get local issuer certificate." Upon investigation, I noticed that $_SERVER["SERVER_SOFTWARE"] outputs something different on the two servers.
Server 1, which works with CURL to https
$_SERVER["SERVER_SOFTWARE"] = Apache/2.4.10 (Win32) OpenSSL/1.0.1i PHP/5.6.3
Server 2, which doesn't work with CURL to https
$_SERVER["SERVER_SOFTWARE"] = Apache
I'm guessing that the fact that the second server has no mention of OpenSSL may have something to do with the error? Is that possible? What would I need to do to get OpenSSL on that server? Why would the first server be able to "find issuer certificate" when I don't have an SSL cert installed on it?
Since you are doing a request with curl to an external server the problem is completely unrelated to the web server software you are running locally, i.e. you don't even need to run a local web server at all. It only depends on the certificate the external server sends back to curl and if the necessary root CA can be found in the trust store of curl.

How configure SSL for an IIS Express site that uses multiple hostnames?

My web application project encompasses multiple web sites served under the umbrella of a single IIS Express site. I succeeded in following Scott Hanselman's excellent blog post, and IIS Express successfully serves both http://foo.local and http://bar.local from the same web application root directory.
However, I need both sites to support SSL. Following Hanselman's advice, I can create an SSL certificate and "attach" it to a single IP-port combination.
makecert -r -pe -n "CN=foo.local" -b 01/01/2000 -e 01/01/2036 -eku 1.3.6.1.5.5.7.3.1 -ss my -sr localMachine -sky exchange -sp "Microsoft RSA SChannel Cryptographic Provider" -sy 12
netsh http add sslcert ipport=0.0.0.0:443 appid='{214124cd-d05b-4309-9af9-9caa44b2b74b}' certhash=284475d4a4eb5c4d3ab7da4fdefa928186482376
That succeeds, but I am unable to repeat the process for the second site. Evidently only one SSL certificate can be applied to a single IP-port combination.
How can I make an SSL certificate that covers both https://foo.local and https://bar.local, or otherwise "attach" one for each site?
jww's answer led me in the right direction. Beyond Hanselman's instructions, here's what I had to do.
First of all, I enabled SNI on my site bindings in IIS Express' applicationhosts.config. This just meant appending the sslFlags attribute:
<binding protocol="https" bindingInformation="*:443:foo.local" sslFlags="1" />
<binding protocol="https" bindingInformation="*:443:bar.local" sslFlags="1" />
(credit: Configure SNI On IIS8?)
Then instead of using makecert, I created a self-signed certificate using PowerShell's New-SelfSignedCertificate cmdlet:
New-SelfSignedCertificate -DnsName foo.local, bar.local -CertStoreLocation cert:\LocalMachine\My
(credit: How to create a Self-Signed SAN Certificate in Windows 8)
Beside that, I followed Hanselman's instructions to use netsh http add sslcert... to "register" the certificate for the IP-port, and to use the MMC "Certificates" snap-in to make it trusted.
Evidently only one SSL certificate can be applied to a single IP-port combination...
You need IIS 8 or above to use multiple certificates. IIS 8 support Server Name Indication (SNI). See Server Name Indication (SNI) with IIS 8 (Windows Server 2012).
How can I make an SSL certificate that covers both https://foo.local and https://bar.local ...
Create one certificate. In the certificate, place both names in the Subject Alternate Name (SAN). Place a friendly name in the CN.
The CN should be a friendly name because:
The IETF deprecated placing a DNS name in the CN
The CA/Browser Forums deprecated placing a DNS name in the CN
CN's are often displayed to users, so they should be friendly
... or otherwise "attach" one for each site?
Upgrade to IIS 8 or Server 2012.
Following Hanselman's advice... makecert -r -pe -n "CN=foo.local"
His advice is wrong here.

Self-hosting using SSL and WCF - can't bind certificate to port

I have a WCF service that I want to access using SSL. I'm on my developer machine, so I was thinking of self-hosting the service. I've been following Configuring HTTP and HTTPS.
I've created a self-signed certificate which I added to the Trusted Root Certification Authorities. I've created another two certificates signed by the first one, one for the client and the other for the server. I followed Using makecert to create certificates for development.
I can't get past the SSL certificates configuration step. When I'm binding the certificate to the port number using netsh it throws an SSL error:
Certificate add failed, Error: 1312 A specified logon session does not exist. It may already have been terminated.
Does the certificate need some special field or some other thing for this to work?
CA certificate:
makecert -n "CN=TestCA" -cy authority -a sha1 -sv "TestCA.pvk" -r "TEST_CA.cer"
Service certificate:
makecert -n "CN=rneapp.com" -ic "TEST_CA.cer" -iv "TestCA.pvk" -a sha1 -sky exchange -pe -sv "rneapp.com.pvk" "rneapp.com.cer"
Client certificate:
makecert -n "CN=rneClient" -ic "TEST_CA.cer" -iv "TestCA.pvk" -a sha1 -sky exchange -pe -sv "rneClient.pvk" "rneClient.cer"
I'm using this command to bind the certificate to the port:
netsh http add sslcert ipport=0.0.0.0:8465 certhash=a853f3b5b48b8a506bdc4212ba2726a3bfea2bb6 appid={2E53B9B0-17AE-4EBC-A1AE-43D53A6FD07D} clientcertnegotiation=enable
When I encountered the same issue, moving the certificate from Current User to Local Computer storage helped, so try checking your certificate storage.
Built-in help for netsh http add sslcert also mentions this with regard to certstorename option:
certstorename - Store name for the certificate. Defaults
to MY. Certificate must be stored in the
local machine context.
I also run into similar error code through different process of creating the self-signed certificate and find the source of my own problem. Using netsh, bind an SSL certificate to a port number is failing
Here is the article I follow to create the self-signed certificate and it is quite complete and thorough.
I have exactly the same issue on Windows 7 and Windows Server 2008 R2 but for me it is working the first time I bind the certificate with the port. However if I delete the binding (netsh.exe http delete sslcert ipport=0.0.0.0:9101) and bind again with the same certificate, it fails. If I try another port, it fails. If I create a brand new certificate then I can bind again. But again deleting/binding will fail.
I follow the same rules as this question:
Can't register a C# generated selfsigned SSL certificate with netsh (error 1312)
I also tried to install KB981506 http://support.microsoft.com/kb/981506 but it failed to install "The update is not applicable to your computer". Maybe I have it already.
I have a feeling something is not deleted in a right way when the binding is deleted. ProcessMonitor doesn't show any thing weird when I try to bind again.
This seems to be a known issue. Check out this Microsoft KB article.
You may also be setting up the certificates incorrectly. Check out this MSDN forum post for how another person was making a similar mistake and getting the 1312 error which was just distracting him from the real problem which was his certificate configuration.
I had a similar problem today, and this is how I fixed it. When I have watched certificates installed on my local computer/my in mmc.exe, I have seen that my certificate haven't icon with key.
So when I combine *.cer and *.pvk file to *.pfx with:
pvk2pfx -pvk "private_key.pvk" -spc "public.cert" -pfx "test.pfx"
And then import *.pfx file with mmc.exe.
Then the next commands will execute with no errors:
netsh http add sslcert...
netsh http delete sslcert...
I have posted this answer to similar Stack Overflow question, Can't register a C# generated selfsigned SSL certificate with netsh (error 1312).