.NET doesn't trust my self-signed certificate, but IE does? - c#

I've got a self-signed certificate for testing in development. I've added it under the "Trusted Root Certification Authorities" folder in certificate manager, and when visiting the site under IE or Chrome it's accepted as valid (under Firefox it doesn't like the fact it is self-signed).
However, when my C# client tries to connect to call a webservice or to open an SSL socket, it get an exception saying "Could not establish trust relationship for the SSL/TLS secure channel with authority '[server address]'.". And even more annoyingly this doesn't happen when I debug via Visual Studio, it only happens when I try and run it from a test machine which has also had the certificate added to the trusted group.
What criteria is .NET using to validate my certificate?

Did you add the certificate as a trusted root authority under the Current User, a specific Service Account or under Local Machine? Most likely you only added the new root authority for the current user only, so any service that runs under a different account will not trust the certificate.

Related

Setting up custom certificate authentication in IIS 10 using OWIN

We are trying to setup multiple authentication using OWIN/Katana and the webapi will be hosted on IIS 10 with certificate authentication and windows authentication. I'm following this blog by Andras Nemes to setup my local client and server certificate authentication. Unfortunately, after setting up the Web API in IIS, when I try to access the website with the client certificate, I'm getting 403 Forbidden error which says that the certificate is not trusted or invalid. I'm not sure what is causing this issue.
I tried setting up my IIS by following other posts also, I've tried to add the website certificate to IIS and bind it with mylocalsite.local and tried with and without editing “system.webServer/security/authentication/iisClientCertificateMappingAuthentication”.
After searching a lot I found similar results but none of them worked. I'm not sure if it is because of the IIS 10 has a different workflow of configuring client server certificate authentication mechanism or is there a problem with my certificates.
Following are my self signed certificates, and I also have there pfx files.
RootCertificate:
RootCertificate.cer has been installed in Local Computer Trusted Root Certification Authorities as well as in Current User Trusted certificates.
localtestclientcert:
localtestclientcert.pfx has been installed in Current User under Personal certificates.
mylocalsite.local:
mylocalsite.local.pfx has been installed in Local Computer under personal certificates.
IIS Server certificates
website bindings
SSL settings of the website
EDIT 1: Modified "Trusted Certificates" to "Trusted Root Certification Authorities" for clarity
The solution is to add the root certificate to the trusted authorities using MMC (machine account) as indicated in this tutorial
https://learn.microsoft.com/en-gb/archive/blogs/asiatech/how-to-create-an-iis-website-that-requires-client-certificate-using-self-signed-certificates
If you import the certif to perosnal account using certmgr you'll get this error

How do I programmatically find whether the intermediate certificate was served by the web server?

My C# code uses HttpWebRequest to send requests to a web service via HTTP over SSL (https:// prefixed URLs). The service has it's coolservice.example.com certificate which is signed by certificate authority intermediate certificate which is in turn signed by the trusted root certificate authority certificate. The latter must be in the caller certificate store and marked as "trusted root", otherwise all that SSL trust chain thing makes no sense. However the intermediate certificate may come from either of the different sources:
the web server may serve it together with its own certificate (as in "here's my certificate and btw it was signed with this certificate which was signed with something you likely trust, please just check the signatures along the trust chain")
the caller may automagically retrieve the intermediate from the certificate authority (AIA protocol or something) - I know this because I've been interfacing with a web service which didn't have the intermediate certificate installed and "it just worked"
the caller may have the intermediate certificate installed in their store
I need to check that the web server properly serves (not only has in the trust store but actually serves the certificate) the intermediate while the SSL handshake is in progress. This test site even shows "sent by server" next to the intermediate. So I guess such check is possible.
How do I craft such a check with C# and .NET Framework?
So far I've only come across HttpWebRequest.ServerCertificateValidationCallback which accepts the web service certificate (X509Certificate object) and the trust chain (X509Chain object). The trust chain lists all the certificates in the chain however I cannot see anything detailing where the certificate was obtained.
How I programmatically find whether the intermediate certificate was server by the web server or it was obtained from elsewhere?

Create Self signed CA certificate and install in IIS

I have created WCF Service with username/password & certificate authentication. It works fine from visual studio.
Now,I would like to host the WCF service on IIS(development server)
Server: Windows Server Standard without Hyper-V (Service pack 2)
IIS: 7
Can someone show me the way to create self signed certificate on server and assign it to IIS for the WCF service(Chain Trust Certificate). And how can I generate the key certificate for the clients to consume service.
Thank You
Bear with me if the procedure is quite long but this procedure helped me to create self-sign CA during our development.
Steps on how to create self-signed certificate:
Assumptions:
Visual Studio was already installed (2012/2013/2015).
You have already basic knowlegdge of digital certificate (x.509).
Steps:
Open Visual Studio Tools and choose Developer Command Prompt for
VS2013/VS2012 as an administrator. And navigate or cd to location
where you want to save your certificates.
We need to create first Root Authority as our CA for signing
certificate. To create Root Authority certificate, we used
makecert.exe tool that comes from visual studio. For more detail
regarding makecert.exe please refer here.
Command: makecert –n “CN=DevRootCA” –r –sv DevRootCA.pvk DevRootCA.cer
Explanation: The command above will generate a root authority
certificate for signing certificate.
Create self-signed certificate using our Root Authority certificate came from Step 2.
Command: makecert –pe –n “CN= localhost” –ss my –sky exchange –sk DevCert –iv DevRootCA.pvk –ic DevRootCA.cer –sr localmachine DevCert.cer
Explanation: The command above will create and store certificate named “DevCert.cer” and it will be stored in Local Computer. To view certificates stored in your local computer Use Microsoft Management Console (mmc.exe). Please refer here
In able for the server and client to trust each certificate named
“DevCert.cer” you need to install Root Authority certificate in
client and server.
Open Microsoft Management Console and follow here.
Navigate to Certificate (Local Computer)
Trusted Root Certification Authority
Certificates
At right side of panel right click at empty space All Task
Import certificate then locate your Root Authority certificate.
Export self-signed certificate named “DevCert.cer” with private key
for your client.
Use MMC again for this step and navigate to
Certificate (Local Computer)
Trusted Root Certification Authority
Certificates
At the right side of panel right click the certificate that you want to export
All tasks
Export (Press Next)
Choose option Yes
Export the private key
Leave default option (Press Next)
Enter password (Press Next). Note : The password must much to the previouse password you enter upon creation.
Browse where you want to save
Next and Finish
Use exported certificate and install to your client machine.
How to install self-sign certificate in IIS:
Assumptions:
You have already the certificate installed in your client machine or server.
How to install self-sign certificate using MMC.
Steps :
Open IIS manager and click local host that correspond to your machine
right after start page.
Click Default Web Site.
At the right side of the Actions Pane click Bindings.
Click Add and choose Type: https and OK button. (if https already
exists just change the certificate )
And choose SSL Certificate that correspond to you certificate. Then,
Click OK and close.
To verify if your website is already using the certificate you setup.
Go to your browse and navigate to your site and see if it prompt you
about the certificate or if the site has padlock beside the URL.
Click the padlock and see if it is your certificate.
Important: This procedure is for development cycle only and not for production. For production you need to acquire SSL certificate from Certificate Authority.

Cannot find the certificate in either the LocalMachine store or the CurrentUser store

I have already installed the ssl cert in user PC. And, I also imported the cert under Local computer of Trusted Root Certification Authorities. I am trying to consume the web servcie. In my code I attach the cert as below.
webservice.ClientCertificates.Add(X509Certificate.CreateFromCertFile(certPath));
But I got the following error.
Cannot find the certificate in either the LocalMachine store or the CurrentUser store
What could be the issue? I'm using .Net Framework 2.0. So, not able to use WCF. Thanks.
That means,
probably you have the wrong certificates installed.
you installed the certificates to the wrong place.
An easy way to tell if you have a client certificate installed properly is
launch IE.
Open Tools | Internet options.
In Content tab, click Certificates button.
Then you should see the cert in Personal (read cert path and see whether it contains errors), and will be able to use it in your WinForms application.
I experienced similar issue. In my case it was solved by using MMC and giving Full control rights of the certificate for user IIS_IUSRS. My Website is running under ApplicationPoolIdentity. This answer guided me to the right path: How to give ASP.NET access to a private key in a certificate in the certificate store?
I had the same error when trying to connect to a service that hadn't been set to use SSL. Once I change the configuration of the service to use SSL, the connection worked fine.
Also you may get that error if the account doesn't have access to the private key, which WinHttpCertCfg.exe from the Windows Resource Kit can solve.

WebException Could not establish trust relationship for the SSL/TLS secure channel

My company has developed a .NET web service and a client dll that uses that web service. The webservice is hosted on our server over ssl and the cert is provided and signed by GoDaddy. We have some clients in a hosted environment that are getting the following error message from the client dll when it tries to access our web service.
System.Net.WebException The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel.
Our fix has been to have them open IE on the server, which is a challenge in and of itself for a lot of the hosted services, and go to the WSDL url. IE then prompts them with a security alert dialog. It says the cert date is valid and a valid name matching the name of the page, but was issued by a company you have not chosen to trust. When they click Yes to proceed, the client dll can then succesfully connect to the web service and operate as normal.
Does anyone have any idea why GoDaddy would not have been in there valid publishers list? All of the servers we have running has GoDaddy as a valid authority. I'm guessing, for security reasons, they've uninstalled the authority for GoDaddy, but not totally convinced that there's not some other underlying issue.
Unfortunately, I haven't had much luck trying to recreate this locally. If I go into Internet Options and remove the GoDaddy authorities and hit our service, ssl works just fine. I go back into the list of publishers and GoDaddy gets put right back in. So my second question is, How the heck do you get rid of GoDaddy so I can get an invalid cert warning?
Okay, last question. Is there a way in code I can tell the web service to ignore invalid certs. I've seen some posts on doing this programatically with WCF but not old web services.
I fixed this error by adding this line before calling the web method:
System.Net.ServicePointManager.ServerCertificateValidationCallback = (senderX, certificate, chain, sslPolicyErrors) => { return true; };
You may need to install on your servers the intermediate certificates used to sign your SSL certs.
Browsers will attempt to validate the SSL certificate by checking the validation of the chain of certs that signed the SSL cert. If the server doesn't supply the certificate chain with the SSL certificate, the browser may reject the SSL cert. (More of an issue for Firefox than IE). The root certificate must still be installed on the client machine for any of this to work.
VB.NET equivalent is
System.Net.ServicePointManager.ServerCertificateValidationCallback = Function(senderX, certificate, chain, sslPolicyErrors)
Return True
End Function
This is really more of a serverfault question, but I'll add what I can here.
The root cert authority list that windows machines normally trust is updated fairly regularly. This comes down as a windows update to IE. You can see MSDN for more information.
If your clients do not have windows update turned on or are actively ignoring windows updates, which is unfortunately very common for a lot of IT departments, then there's not much you can do other than switch SSL providers.
Basically, they need to get the certificate updates or you need to switch to a cert provider that has a high probability of already being trusted by the machines in question. Typically this means Verisign or Thawte. The third alternative is the route you've been going down: have them manually trust the root CA.
At the end of the day I hate the idea of changing an app in this way simply because the IT departments in question are morons but the real question boils down to how your company wants to handle this.
When you look at the Go Daddy Certification Path of that certificate on the web server, do you see Go Daddy Class xxx or Starfield Class xxx ?
And from your non-legacy client i.e Windows Vista upwards, what does the Go Daddy Certification Path display? Go Daddy Class xxx or Starfield Class xxx ?
And these clients that get the warning, are they legacy clients? i.e WinXP and older?
Root Certificate updates works differently as of Windows Vista.
http://support.microsoft.com/kb/931125
Root certificates on Windows Vista and later are distributed via the automatic root update mechanism – that is, per root certificate. When a user visits a secure Web site (by using HTTPS SSL), reads a secure email (S/MIME), or downloads an ActiveX control that is signed (code signing) and encounters a new root certificate, the Windows certificate chain verification software checks Microsoft Update for the root certificate. If it finds it, it downloads the current Certificate Trust List (CTL) containing the list of all trusted root certificates in the Program, and verifies that the root certificate is listed there; it then downloads the specified root certificate to the system and installs it in the Windows Trusted Root Certification Authorities Store.
You'll probably find that your Go Daddy Certification Path on the web server thinks it's Starfield Class 2 instead of Go Daddy Class 2 so you installed the wrong root certificate. It caught me out as when you view in on the web server it doesn't display a root certificate warning, download and install the Do Daddy class 2 root cert and remove the Starfield one and your problem should dissapear.

Categories