Could not establish trust relationship with remote server.

When you use HTTPS for your web services, you may get a System.Net.WebException that, "The underlying connection was closed: Could not establish trust relationship with remote server." This indicates that the client is unable to negotiate a secure connection with the server.

Try visiting the URL of your web service with IE. You will likely get a Security Alert message box warning about one or more of the following:

1) The certificate is not from a trusted authority. This happens if the issuing authority is not trusted by the Certificate Manager. For testing, you can issue your own certificates and add yourself to the trusted authorities list. For production, you should probably buy a certificate.

2) The date on the certificate is invalid. The certificate's dates don't match those on the client computer. If this happens only on some computers, check that the clock on the offending computers is set to the right day.

3) The name on the certificate does not match the name of the site. Most certificates are issued with a www prefix; for example: www.yahoo.com. If your web service is hosted on a named server, (daffy.yahoo.com) you will get this warning. I understand you can buy wildcard certificates that accept any server name, but I've never used them.

Once you know the problem, you can decide to fix it, or ignore it when establishing the connection. The following class shows how to selectively ignore any CertificateProblems that you choose. Use this carefully, as establishing a secure connection to an attacker's server is worse than sending data in the clear.

using System;
using System.Net;
using System.Security.Cryptography.X509Certificates;

namespace Graham.Utilities
{
        public class AcceptServerNameMismatch : ICertificatePolicy
        {
                // HACK: This is a workaround.  The .NET Framwork should expose these, but they don't.
                public enum CertificateProblem : long
                {
                        CertEXPIRED                   = 2148204801,
                        CertVALIDITYPERIODNESTING     = 2148204802,
                        CertROLE                      = 2148204803,
                        CertPATHLENCONST              = 2148204804,
                        CertCRITICAL                  = 2148204805,
                        CertPURPOSE                   = 2148204806,
                        CertISSUERCHAINING            = 2148204807,
                        CertMALFORMED                 = 2148204808,
                        CertUNTRUSTEDROOT             = 2148204809,
                        CertCHAINING                  = 2148204810,
                        CertREVOKED                   = 2148204812,
                        CertUNTRUSTEDTESTROOT         = 2148204813,
                        CertREVOCATION_FAILURE        = 2148204814,
                        CertCN_NO_MATCH               = 2148204815,
                        CertWRONG_USAGE               = 2148204816,
                        CertUNTRUSTEDCA               = 2148204818
                }

                /// <summary>
                /// Implement CheckValidationResult to ignore problems that we are willing to accept.
                /// </summary>
                public bool CheckValidationResult(ServicePoint sp, X509Certificate cert,
                        WebRequest request, int problem)
                {       
                        int CertificateNameDoesntMatch = unchecked( (int) CertificateProblem.CertCN_NO_MATCH);
                        if ( problem == CertificateNameDoesntMatch ) // only accept server name failed match
                                return true;

                        // The 1.1 framework calls this method with a problem of 0, even if nothing is wrong
                        return (problem == 0);         
                } 
        }
}

Published 12 August 2004 08:03 AM by Ted_Graham

Comments

# Doug de la Torre said on 25 August, 2004 07:02 PM
This article from Microsoft shows how to fix the problem in a code-less way, via config file. This is very handy if you have an application that is already deployed and don't want to patch the deployed DLLs with a code-based solution.

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/html/cpconhostingremoteobjectsininternetinformationservicesiis.asp

According to that article, in

C:\WINDOWS\Microsoft.NET\Framework\v1.1.4322\Config\machine.config

Change

<servicePointManager checkCertificateName="true" checkCertificateRevocationList="false" />

to

<servicePointManager checkCertificateName="false"
checkCertificateRevocationList="false" />

I've tested this on a local environment here and it fixed the problem.
# TrackBack said on 20 June, 2005 05:09 AM
"The time has come", the Walrus said, "to speak of secure communications".
There's something I've been...
# Manish Jadhav said on 15 June, 2007 01:59 PM

The solution provided by Doug de la Torre can be implemented if you are hosting the web service and have control over the server's config. But if you are just utilizing a web service provided by somebody else, then the ICertificatePolicy hack provided by Ted is your only way around this issue.

# Richard Chen said on 17 August, 2007 01:28 AM

The solution provided by Doug de la Torre means modifying the machin.config of your local machine instead of the server machine. since it is the local machine's responsibility to check whether the server certificate is authticate or not.

Therefore, it has nothering to do with the web service being hosted by yourself or somebody else.

# Could not establish trust relationship with remote server. said on 26 November, 2007 05:25 PM

Pingback from  Could not establish trust relationship with remote server.

# Bob said on 14 May, 2008 11:26 AM

how do you use this class?  You have given no instruction on how to implement it.

Leave a Comment

(required) 
(required) 
(optional)
(required)