X509Chain is not building the full chain during RemoteCertificateValidationCallback - c#

My Windows service is trying to connect to a website that is signed by the certificate C. C is signed by Symantec Class 3 Secure Server CA - G4 (Intermediate CA) and Symantec Class 3 Secure Server CA - G4 is signed by VeriSign Class 3 Public Primary Certification Authority - G5 (Root CA).
Note: My windows service is running under the privilege of Network Service.
In the client machine where the windows service is installed , I am trying to validate the server certificate. In my certificate store of the local machine I have the VeriSign Class 3 Public Primary Certification Authority - G5 (Root CA) in the trusted root CA , but I do not have the intermediate CA in the trusted intermediate root.
Now in the callback of RemoteCertificateValidationCallback , the X509Chain is containing only 1 element i.e certificate C.
Can anyone explain the reason why and what needs to be done so that the full chain is built.
Additional Observations:
Note : When I ran the windows service as a user X who is in the administrator group on the same machine. The full chain was built and the intermediate certificate was installed in the User's Store trusted intermediate certificates.
Note: When I elevated the NETWORK SERVICE as part of the administrator group , the problem was still there and the full chain is not built.
Note : When I ran the windows service as Local system account and the logged in user is part of the administrator group on the same machine.the problem was still there and the full chain is not built.

The main reason why the full chain was not built is due to a missing proxy configuration! in a windows machine there are 3 classes of applications and the way you configure proxies for them are different. The 3 classes are
Applications that have their own proxy settings which uses winsock. These applications has to manage proxy settings themselves.
Applications using the WinINET library - WinINET is the core of Internet Explorer and it can also be used by other applications. Any applications that use this library would use the proxy settings provided in Internet Explorer.
Applications using the WinHTTP library - Non Interactive applications mainly use WinHTTP library. The proxy settings provided in Internet explorer will not be used by WinHTTP library.
The Windows service in the question belongs to the 3rd category and it was not using the Proxy settings of Internet Exploror. So the Chain building engine of .net was not able to download the intermediate CA! Once we configured the Proxy Server settings of Win HTTP it worked!
Also , the follwing links has explaination on how the certificate chain is built.
https://technet.microsoft.com/en-us/library/cc700843.aspx
https://technet.microsoft.com/en-us/library/ee619754(v=ws.10).aspx
The interesting part of chain building is that it also looks into the disk and memory caches before using the AIA (Authority Information Access) , thus even if you put wireshark you will not find a trace of the http call to the AIA url . This is because it is there in the memory cache and to see the AIA call one needs to either invalidate the cache settings or delete them.
Location:
Per User ==>
C:\Users\username\AppData\LocalLow\ Microsoft\CryptnetUrlCache
For Network Service in my case ==>
C:\Windows\ServiceProfiles\NetworkService\AppData\LocalLow\Microsoft\CryptnetUrlCache

Related

Certificate chain contained within the public key exposed by RabbitMQ

I have a c# .net client consuming messages from a RabbitMQ instance (using RabbitMQ.Client) secured using TLS. I got everything working nicely using a self signed certificate.
We've purchased a wildcard certificate from an accredited CA to use going forward. This certificate has actually been signed by an intermediary authority of the Root CA which is trusted by the root CA itself.
Because the intermediary CA will not be trusted by the client machine (the certificate won't be installed into the local machine certificate store), we downloaded a PEM file that contains all the certificates that make up the chain of trust. However, the .net client will not validate this certificate, failing because it cannot establish the chain of trust.
I've had a look around and can find nothing that says .net cannot validate PEM certificates that themselves contain multiple certificates. If I assign a custom delegate to the CertificateValidationCallback property of the RabbitMQ ConnectionFactory I can see that the certificate chain contains only one certificate, which is the certificate that is signed by the intermediate CA.
The client will ultimately be deployed to hundreds of machines so we'd rather not have to deploy the intermediate certificate to all of them and then have to manage them going forward. I'm aware that I can set turn off chain validation by setting the AcceptablePolicyErrors property to SslPolicyErrors.RemoteCertificateChainErrors but this seems to me to be making things a little less secure.
So, there are two main questions I have here:
Does .net cryptographic validation simply not support certificates that contain all the other certificates in the chain (at least if that certificate is a PEM)?
Is there a way of working round this?
I'm using .net 4.5.2 although the same problem occurs in .net 4.6.2 and .net 4.7.1.
I'm running it on a Windows 7 machine. The RabbitMQ node is running on a windows 2012 server.
The RabbitMQ team monitors the rabbitmq-users mailing list](https://groups.google.com/forum/#!forum/rabbitmq-users) and only sometimes answers questions on StackOverflow.
You should concatenate the Root CA certificate and Intermediate CA certificate (both pem format) into a single file, and use that as the cacertfile for RabbitMQ. The Erlang VM should then present both certificates during the handshake phase of session establishment and they should be used by the .NET TLS/SSL code to verify the server's certificate.
You can use these instructions to assist in troubleshooting your environment. If something still doesn't work, follow up on the mailing list and we'll help out. Thanks!

Access SignalR application running on localhost from browser

I have an application that can be downloaded from my website and run on user PC. This application doesn't do anything special and just allows the web page to access the scanner. It uses SignalR for communication.
Basically, I run SignalR server under WinForms application and have javascript client that tries to access it through http://localhost:8084/signalR.
Everything works fine when I use HTTP version of the web application, but fails, when I use HTTPS for my web application: Most of the browsers don't allow unsecured connections from a secure page.
So, I've created a self-signed certificate that is installed on user system during installation and it works fine for Chrome, IE and Opera, but fails for Firefox and Edge.
So I was thinking, is there a better way to access SignalR applications that are running on localhost from webpage under https?
There isn't a better way. You are correct in your understanding that "[m]ost of the browsers don't allow unsecured connections from a secure page". I believe there isn't a browser that will allow this. Therefore if you want to call out from a secured website, you must use a secured connection as well.
I don't know the issue you're experiencing with Edge, as I can confirm that it does work. Firefox will NOT trust a certificate in the cert store, even if it is a trusted root or has a trusted root certificate. You have to manually add an exception for this certificate. Details, or at least information that will let you find the correct method to do this, can be found here.
There are some things you have to do in order to make sure your certificate and configuration is correct. First, you have to have a well formed certificate with a public and private key and a well formed certificate authority cert with only its public key. By "well formed" I mean it must contain all information required by browsers for full trust, such as a Subject Alternative Name entry.
You can use OpenSSL to generate the CA, then use that to sign a certificate you will use for the SSL port. Export the CA's public key and the SSL certificate's public and private keys. Exporting the CA's private key is a MAJOR no no. That would allow third parties to create new certs from it and install them on your client's machine. The CA gets installed in the machine's Trusted Root Certification Authorities store. The SSL cert can go into the Personal/Certificates store.
Once you have these, you have to configure the URL/Port you will use for access and SSL using the netsh command line tool. Add a URLACL to allow the application to access the url and port (netsh.exe http add urlacl), and then assign the certificate to the port (netsh.exe http add sslcert ).
Having done all this, you should be good to go. The only real problems you should have are Chrome being very demanding about the configuration of your certificates and Firefox refusing to trust your CA certificate even though it is in your trusted certificate store. Bastard.
And for Edge, I can definitely guarantee if you do all the above it will work. If it doesn't, you need to consult the js console to see what errors it is throwing.

Different certificates for each REST-service installation

We are about to implement SSL for a .NET Framework product that uses a service layer which in turn uses NancyFX and REST/JSON.
The clients communicating with the service need to access it through HTTPS, hence the need for a certificate. We are running on both Windows and Linux (through Mono) and the user is prompted for a username/password or sending it through auth header.
To get the clients to trust the certificate, it must be assigned by a trusted CA but how do we solve this when we do not know anything about the address on which the service is configured?
So - how to get a trusted certificate assigned to the installed service with a minimum effort for the user. Best thing would be to handle this through a normal Install procedure (on Windows). Is this possible?
We have a large number of users (> 5000) that will go through the upgrade process and will be needing the certificate, so to manually create and assign certificates does not seem like an option.

Websphere MQ access to SSL certificate when running inside IIS7 as DefaultAppPool?

I have a C# Web service which is running under IIS 7.5 on Windows Server 2008 R2 using the DefaultAppPool user as the application identity (IIS APPPOOL\DefaultAppPool). The Web service uses IBM Websphere MQ (7.0.1.2) to do it's stuff and uses the SSL certificates stored in a key.kdb setup via IBMs KeyMan utility.
Normally (for C# apps that are not running IIS) I need to label the personal certificate within the kdb so that it's name matches the user that is running the app i.e. the certificate would be labelled as ibmwebspheremqbs6mjb (see http://www-01.ibm.com/support/docview.wss?uid=swg21245474) and this allows the app to successfully access the SSL certificates within the key.kdb.
But..... when running as a Web service and naming the certificate ibmwebspheremqdefaultapppool the application cannot access the SSL certs. If I change the AppPool identity to be bs6mjb then everything works (I'm not allowed to run the app pool as bs6mjb).
I'd prefer not to setup a default certificate as mentioned in the link above, does anyone know what the certificate should be labelled as to work with DefaultAppPool?
For MQ clients the certificate label must have the user name who runs the client. In your case, for example ibmwebspheremqbs6mjb. If the certificate label is something else, the MQ client (actually GSKit libraries) will not find the certificate to connect to queue manager. I think that's what is happening when you have the label as ibmwebspheremqdefaultapppool.
This blog has interesting and useful details. You may want to check under what user IIS runs and create a certificate for that user and do the required SSL setup between client and MQ queue manager.

self signed certificate in windows server

I have a C# console app that consumes a web service that is outside of my network. I am told that the web services uses self-signed certificate for SSL. I am not familiar with the certificate and I am wondering what I need to do in .net/windows server environment.
Thanks.
Self signed certificates will not be viewed by your application as valid by default because there is not a trusted third party validating the certificate. Typically you'll see self signed certificates on test servers, and you can find more info on self signed versus signed certificates here.
If you are having trouble calling the web services then you'll need to either install the certificate on the machine that your application is running on, or create a custom validator that you can use to tell your application to accept the self signed certificate. From .NET 2.0 onward, custom SSL validation is done by specifying a custom method on the ServicePointManager.ServerCertificateValidationCallback property.
An example of using the ServerCertificateValidationCallback property can be found here:
http://weblogs.asp.net/smehaffie/archive/2009/09/10/calling-web-services-that-use-self-signed-certificates.aspx
That's a large question especially regarding X.509 security. Usually with self-signed certificate, you have to import the initial CA used to sign this certificate (usually the self-signed CA used by the application) into your keyring (to be sure that you are connecting to the right server). It's usually required because your client application will check at the connection if the certificate is signed by a known and trusted CA or matching an existing certificate in your keyring.
In C#, you can check the System.Net.Security namespace and especially the SSlStream class for more details.
If you need to import certificate in your keyring, you can use various interfaces to access the keyring from the GUI, using the command line "Certutil.exe" or via the various APIs.

Categories

Resources