Learn how to a build a cloud-first strategyRegister Now

  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 2758
  • Last Modified:

Unable to call SSL web service with Vista/Server 2008

I'm attempting to call an external web service that requires SSL and uses client certificate authentication. I am able to successfully do this on windows XP and server 2003, but the code will not work on Vista/Server 2008.  The web service call returns an exception "The request was aborted: Could not create SSL/TLS secure channel."

I've confirmed the user account that is running the client code has read and write access to the client cert's private key, and I've enabled a debug trace.  The code successfully reads the cert and key from the store, then the following happens:
System.Net Information: 0 : [4140] SecureChannel#11622431 - Certificate is of type X509Certificate2 and contains the private key.
System.Net Information: 0 : [4140] AcquireCredentialsHandle(package = Microsoft Unified Security Protocol Provider, intent  = Outbound, scc     = System.Net.SecureCredential)
System.Net Information: 0 : [4140] InitializeSecurityContext(credential = System.Net.SafeFreeCredential_SECURITY, context = 4dfba60:15852f0, targetName = datapower.test.eai.srv.westpac.com.au, inFlags = ReplayDetect, SequenceDetect, Confidentiality, AllocateMemory, InitManualCredValidation)
System.Net Information: 0 : [4140] InitializeSecurityContext(In-Buffers count=2, Out-Buffer length=0, returned code=InternalError).
System.Net.Sockets Verbose: 0 : [4140] Socket#59312024::Dispose()
System.Net Error: 0 : [4140] Exception in the HttpWebRequest#23397093:: - The request was aborted: Could not create SSL/TLS secure channel.
System.Net Error: 0 : [4140] Exception in the HttpWebRequest#23397093::EndGetResponse - The request was aborted: Could not create SSL/TLS secure channel.

The following Audit Failure event is logged in the windows security log:
Cryptographic operation.

      Security ID:            <account details>
      Account Name:            <account name>
      Account Domain:            <domain>
      Logon ID:            <logonID>

Cryptographic Parameters:
      Provider Name:      Microsoft Software Key Storage Provider
      Algorithm Name:      RSA
      Key Name:      {25957D21-7338-42F4-950A-22513D14CA38}
      Key Type:      Machine key.

Cryptographic Operation:
      Operation:      Sign hash.

To try to debug further I put together code that establishes a TCP connection then tries to set up a ssl session (see attached code).  This code returns an exception: "System.Security.Authentication.AuthenticationException: A call to SSPI failed, see inner exception. ---> System.ComponentModel.Win32Exception: The Local Security Authority cannot be contacted", and the same event as above is logged in the Security event log

Any ideas what I'm doing wrong?

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Net.Security;
using System.Security.Authentication;
using System.Security.Cryptography.X509Certificates;
namespace ConsoleApplication1
   class Program
      // The following method is invoked by the RemoteCertificateValidationDelegate.
      public static bool ValidateServerCertificate(
            object sender,
            X509Certificate certificate,
            X509Chain chain,
            SslPolicyErrors sslPolicyErrors)
         if (sslPolicyErrors == SslPolicyErrors.None)
            return true;
         Console.WriteLine("Certificate error: {0}", sslPolicyErrors);
         // Do not allow this client to communicate with unauthenticated servers.
         return false;
      public static X509Certificate SelectLocalCertificate(
object sender,
string targetHost,
X509CertificateCollection localCertificates,
X509Certificate remoteCertificate,
string[] acceptableIssuers)
         Console.WriteLine("Client is selecting a local certificate.");
         if (acceptableIssuers != null &&
             acceptableIssuers.Length > 0 &&
             localCertificates != null &&
             localCertificates.Count > 0)
            // Use the first certificate that is from an acceptable issuer.
            foreach (X509Certificate certificate in localCertificates)
               string issuer = certificate.Issuer;
               if (Array.IndexOf(acceptableIssuers, issuer) != -1)
                  return certificate;
         if (localCertificates != null &&
             localCertificates.Count > 0)
            return localCertificates[0];
         return null;
      static void Main(string[] args)
         // Get the client cert name to use for certificate auth
         string certName = "<DN of the client cert for authentication>";
         TcpClient client;
         SslStream sslStream;
         //load the cert from the personal machine store
         X509Store store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
         X509Certificate2 cert = null;
         X509Certificate2Collection certs = (X509Certificate2Collection)store.Certificates;
         foreach (X509Certificate2 computerCert in certs)
            if (computerCert.Subject.ToString() == certName)
               cert = computerCert;
         if (cert == null)
            throw new Exception("Errror: Certificate with subject name " + certName + " could not be loaded from the personal cert store of this machine");
            // Create a TCP/IP client socket.
            // machineName is the host running the server application.
            client = new TcpClient("<target server>", 7163);
            Console.WriteLine("Client connected.");
            // Create an SSL stream that will close the client's stream.
            sslStream = new SslStream(
                new RemoteCertificateValidationCallback(ValidateServerCertificate),
                new LocalCertificateSelectionCallback(SelectLocalCertificate)
            // The server name must match the name on the server certificate.
               sslStream.AuthenticateAsClient("<target server>", certs, SslProtocols.Default, true);
            catch (AuthenticationException e)
               Console.WriteLine("Exception: {0}", e.Message);
               if (e.InnerException != null)
                  Console.WriteLine("Inner exception: {0}", e.InnerException.Message);
               Console.WriteLine("Authentication failed - closing the connection.");

Open in new window

1 Solution
ParanormasticCryptographic EngineerCommented:
Does this only happen on the local development box, or does it also happen from remote boxes as well?

For local issues, start with this (the KB doesn't describe it exactly, but it is a different context for IIS stuff - you still need to have it in place to address anything locally in response to a recent security patch):

If that doesn't take care of it, read through this:

and double check certificate stuff:
1) Make sure you are entering the servername as it is specified in the certificate - e.g. if you have 'server1' for the subject name of the cert, then you need to address it as 'server1' not 'server1.domain.com' or its IP address or localhost; same thing if the subject is 'server1.domain.com' then you can't use the hostname or another dns alias.

2) Make sure you have the root certificate installed - if it is a self-signed cer then make sure it is in the trusted root certificate store.

3) Make sure the cert isn't expired.  Can double check time and date settings in windows and in bios on the box that is having the issue.

Featured Post

NFR key for Veeam Agent for Linux

Veeam is happy to provide a free NFR license for one year.  It allows for the non‑production use and valid for five workstations and two servers. Veeam Agent for Linux is a simple backup tool for your Linux installations, both on‑premises and in the public cloud.

Tackle projects and never again get stuck behind a technical roadblock.
Join Now