FAST ESP/ Troubleshooting SSL with .NET Applications


While attempting to connect to the QRServer over SSL with ASP.NET, one may experience the following errors during the SSL handshake:  

An existing connection was forcibly closed by the remote host


The underlying connection was closed: Could not establish secure channel for SSL/TLS


This can be caused by multiple problems:  

1. Private Key

2. Certificate Location  

3. Permissions

4. Certificate Type

5. Trust

6. Certificate validity

Note: If any of these certificate requirements are not met, the SSL handshake will fail.  


Each one of the potential causes from above have separate resolutions that are detailed below:  

1. Private Key:

Confirm a private key is associated with the certificate that is being used with the .NET ASP Web App.

A private key is required to send client credentials to the server during the mutual SSL authentication handshake. If the private key is not found in the Local Computer Certificate Store or does not match the certificate used by the application configuration, the SSL handshake will fail.

To confirm, open the certificate and on the general tab, one should see "You have a private key that corresponds with this certificate". If this is not seen on the certificate, the private key was not included.  

In this case, one needs to issue a new certificate from the CA (Certificate Authority), which includes a private key for your ASP .NET Application.  

2. Certificate Location:  

ASP.NET Web Applications require that the certificate is located in the Local Machine Certificate store and NOT the Current User Certificate Store.

ASP.NET web applications usually run in the context of process/thread identity, not a particular user. Because of this, the certificate needs to be installed into "Local Machine Certificate store" in order to read the certificate properly. If the certificate is not installed into the certificate store or is installed in the "Current User Certificate Store", the SSL handshake will fail.

Make sure the correct certificate with the associated private key is "imported" into "Local Machine Certificate store".

Note: If the certificate is found in the "Current User Certificate Store", it must be deleted.

3. Permissions:

The Everyone ACL needs to be granted full control of the certificate and key.  

As stated previously, ASP.NET web applications usually run in the context of process/thread identity, not a particular user. In this case, the web service user context will not have access to the private key and the SSL handshake will fail.  

One will need to manually assign full control permissions for the "everyone" user object to the private key.  

In Windows 2008:

- Run MMC and add the Certificates snap-in

- Choose “Computer Account”

- Choose “Local Computer”

- Locate the correct certificate in “Certificates\personal\certificates”

- Right Click the certificate

- Choose "All Tasks" 

- Then, "Manage Private Keys"

- Add, the "everyone" User and assign full control

In Windows 2003:
One will need to download and use a tool called WSE:

- Install the tool with custom installation

- Make sure to include the "Tools" portion of this software

- Run “certificate tools” from the WSE program group  

- Choose “Local Computer” for "Certificate Location" and "Personal" for "Store Name"

- Open certificate  

- Choose the correct certificate

- Choose "View Private Key File Properties"

Note: The physical file should now open and make sure the path indicates “all users”. This is default and will ensure everyone has access to the folder.  

- Click the security tab

- Add the “Everyone” User object and give full control

- Apply the changes and exit  

These steps will ensure that the ASP .NET Web Application will have permissions to the certificate private key through the "Everyone" ACL (Access Control List).  

4. Certificate Type: 

The "intended purposes" of certificate needs to be enabled for "all purposes" or at a minimum "Client authentication" purposes.

Certificate type needs to be correctly set. If the "intended purposes" is not "Client authentication" or "all purposes", the SSL handshake will fail. If the certificate type is incorrect, one will need to edit the properties of the certificate and make the necessary corrections, or issue a new certificate with the correct "intended purposes" set.  

5. Trust:

Any subordinate CA (Certificate Authority), if applicable, needs to be installed in either the intermediate or trusted root store as appropriate.  

If the certificate was issued by an untrusted CA (Internal or Test CA), is being used by the ASP .NET Web Application and one has not trusted the entire certificate path, theSSL Handshake will fail.  

To resolve this issue, install all Root and Subordinate CA certificate(s) in the intermediate or trusted root store as appropriate for the "Local Machine Certificate store.  

6. Certificate validity:

The certificate needs to be fully valid and issued to the service that is using the certificate.

If the certificate is not valid, the SSL Handshake will fail. This includes "expiry date" and "issued to", for example. If one finds that the certificate is not valid, one will need to issue a new valid certificate from the CA, included with the private key.  

More Information

If problems making a successful SSL connection persist after verifying all the steps in this article, one can further debug the SSL handshake using .Net Network Tracing code in the application.

1.  Add the following contents into the application configuration file.

a. If one has a desktop application, the configuration file will be a file called YourApp.exe.config

b. If it is an application, the configuration file will be a file called web.config residing in the application directory.
<trace autoflush="true" />
<source name="System.Net">
<add name="System.Net"/>
<source name="System.Net.HttpListener">
<add name="System.Net"/>
<source name="System.Net.Sockets">
<add name="System.Net"/>
<source name="System.Net.Cache">
<add name="System.Net"/>
<add name="System.Net" type="System.Diagnostics.TextWriterTraceListener" initializeData="c:\traces\System.Net.trace.log" />
<add name="System.Net" value="Verbose" />
<add name="System.Net.Sockets" value="Verbose" />
<add name="System.Net.Cache" value="Verbose" />
<add name="System.Net.HttpListener" value="Verbose" />

2. Create a folder called C:\traces, and give full permissions to “Everyone”. This will ensure that the log will get created regardless of the process/thread identity.

Note: The folder and log file is specifed by the following line: initializeData="C:\traces\System.Net.trace.log"

3. Restart the application process (YourApp.exe for desktop applications and w3wp.exe for applications)

4. Reproduce the problem

5. One should see a file called System.Net.trace.log in the C:\traces folder.

6. This file can be analyzed for debug level details of the entire SSL Handshake process.

See the following article for more information:

How to: Configure Network Tracing

For more information on the SSL handshake process see the following article:

Description of the Secure Sockets Layer (SSL) Handshake

Article ID: 2503806 - Last Review: May 16, 2011 - Revision: 1