title: WCF SSL certificate using an enterprise CA
body: <p>For an application, I need to have a SSL certificate for a WCF service,</p>
  
  <p>So we installed it. If I go with an internet browser with a web browser trough https, I've got no problem, no warning, nothing, so I suppose that this certificate is considered as valid for windows.</p>
  
  <p>The problem is that when I'm trying to connect to my WCF server, I got this error:</p>
  
  <blockquote>
  <pre><code>The X.509 certificate CN=myHostName, OU=tom, O=myDomainName,
  </code></pre>
    
    <p>L=MyLocation, S=SO, C=CH chain building failed. The certificate that
    was used has a trust chain that cannot be verified. Replace the
    certificate or change the certificateValidationMode. The revocation
    function was unable to check revocation because the revocation server
    was offline.</p>
  </blockquote>
  
  <p>What can be wrong? How can I know which part of the chain is unvalid? Is there any way to know what is the missing part?</p>
  
  <p>Here is my code
  The server:</p>
  
  <pre><code>ServiceHost myHost = new ServiceHost(typeof(MyService));
  WSHttpBinding binding = new WSHttpBinding
  {
      ReaderQuotas = { MaxStringContentLength = int.MaxValue, MaxArrayLength = int.MaxValue, MaxDepth = int.MaxValue, MaxBytesPerRead = int.MaxValue, MaxNameTableCharCount = int.MaxValue },
      MaxReceivedMessageSize = int.MaxValue
  };
  TimeSpan timeoutSpan = TimeSpan.FromMilliseconds(timeout);
  binding.CloseTimeout = timeoutSpan;
  binding.OpenTimeout = timeoutSpan;
  binding.ReceiveTimeout = timeoutSpan;
  binding.SendTimeout = timeoutSpan;
  binding.ReliableSession.InactivityTimeout = timeoutSpan;
  
  binding.MaxBufferPoolSize = int.MaxValue;
  
  //we set the security type
  binding.Security.Mode = SecurityMode.Message;
  binding.Security.Message.ClientCredentialType = MessageCredentialType.UserName;
  binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.None;
  
  //we set the server's certificate
  myHost.Credentials.ServiceCertificate.SetCertificate(StoreLocation.LocalMachine, StoreName.My, X509FindType.FindBySubjectName, ConfigurationManager.AppSettings["Hostname"]);
  myHost.Credentials.ClientCertificate.Authentication.CertificateValidationMode = X509CertificateValidationMode.None;
  //we add the endPoint(and we indicate which methods are exposed through the interface
  
  myHost.AddServiceEndpoint(services[port], binding,                  String.Format("http://localhost:{0}", port));
  
  
  
  
  //Some services doesn't need an authentication
  if (!servicesWithoutAuth.Contains(services[port]))
  {
      //We set the authentifier:
      myHost.Credentials.UserNameAuthentication.UserNamePasswordValidationMode = UserNamePasswordValidationMode.Custom;
      myHost.Credentials.UserNameAuthentication.CustomUserNamePasswordValidator = new CustomUserNameValidator();
      myHost.Authorization.PrincipalPermissionMode = PrincipalPermissionMode.Custom;
  
  
      //we set the AuthorizationPolicy
      List&lt;IAuthorizationPolicy&gt; policies = new List&lt;IAuthorizationPolicy&gt; { new CustomAuthorizationPolicy() };
      myHost.Authorization.ExternalAuthorizationPolicies = policies.AsReadOnly();
  }
  else
  {
      //We set the authentifier:
      myHost.Credentials.UserNameAuthentication.UserNamePasswordValidationMode = UserNamePasswordValidationMode.Custom;
      myHost.Credentials.UserNameAuthentication.CustomUserNamePasswordValidator = new NoUserNamePasswordValidator();
  }
  
  //We bypass the certificate verification(our certificate is only self signed)
  //HACK Only to desactivate the SSL check: 
  ServicePointManager.ServerCertificateValidationCallback += ValidateCertificate;
  
  
  
  //HACK: Remove when debug finished
  private static bool ValidateCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslpolicyerrors)
  {
      return true;
  }
  </code></pre>
  
  <p>My client side:</p>
  
  <pre><code>// the remote adress is of the form "net.tcp://localhost:8000"
  string remoteAddress = String.Format("{0}://{1}:{2}", Tools.GetDescription(accessInfo.ServiceHost.Protocol), accessInfo.ServiceHost.HostName, accessInfo.PortNumber);
  
  // HACK: binding depends on protocol -&gt; switch over accessInfo.ServiceHost.Protocol
  
  // avoid seralization/deserialization problems with large XML's
  WSHttpBinding binding = new WSHttpBinding();
  binding.ReaderQuotas.MaxStringContentLength = int.MaxValue;
  binding.ReaderQuotas.MaxArrayLength = int.MaxValue;
  binding.MaxReceivedMessageSize = int.MaxValue;
  binding.ReaderQuotas.MaxStringContentLength = int.MaxValue;
  binding.ReaderQuotas.MaxArrayLength = int.MaxValue;
  binding.ReaderQuotas.MaxDepth = int.MaxValue;
  binding.ReaderQuotas.MaxBytesPerRead = int.MaxValue;
  binding.ReaderQuotas.MaxNameTableCharCount = int.MaxValue;
  TimeSpan timeoutSpan = DateTime.Now.AddMinutes(30) - DateTime.Now;
  binding.CloseTimeout = timeoutSpan;
  binding.OpenTimeout = timeoutSpan;
  binding.ReceiveTimeout = timeoutSpan;
  binding.SendTimeout = timeoutSpan;
  binding.ReliableSession.InactivityTimeout = timeoutSpan;
  
  
  //++
  binding.MaxBufferPoolSize = int.MaxValue;
  
  //we set the security type
  binding.Security.Mode = SecurityMode.Message;
  binding.Security.Message.ClientCredentialType = MessageCredentialType.UserName;
  binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.None;
  
  ChannelFactory&lt;TService&gt; channelFactory = new ChannelFactory&lt;TService&gt;(binding, remoteAddress);
  
  channelFactory.Credentials.UserName.UserName = ((UsernamePasswordAuthentication)authInfos).Username;
  channelFactory.Credentials.UserName.Password = ((UsernamePasswordAuthentication)authInfos).Password;
  
  
  //We set the maxItemsInObjectGraph
  foreach (OperationDescription op in channelFactory.Endpoint.Contract.Operations)
  {
      DataContractSerializerOperationBehavior dataContractBehavior = op.Behaviors.Find&lt;DataContractSerializerOperationBehavior&gt;();
      if (dataContractBehavior != null)
      {
          dataContractBehavior.MaxItemsInObjectGraph = int.MaxValue;
      }
  }
  SamlSecurityTokenAuthenticator authenticator = new SamlSecurityTokenAuthenticator(new List&lt;SecurityTokenAuthenticator&gt;(new SecurityTokenAuthenticator[] { new RsaSecurityTokenAuthenticator(), new X509SecurityTokenAuthenticator(X509CertificateValidator.None) }), TimeSpan.FromDays(5));
  
  _service = channelFactory.CreateChannel();
  </code></pre>