How to: Configure a Port with an SSL Certificate

When creating a self-hosted Windows Communication Foundation (WCF) service with the WSHttpBinding class that uses transport security, you must also configure a port with an X.509 certificate. If you are not creating a self-hosted service, you can host your service on Internet Information Services (IIS). For more information, see HTTP Transport Security.

To configure a port, the tool you use depends on the operating system that is running on your machine.

If you are running Windows Server 2003, use the HttpCfg.exe tool. On Windows Server 2003, this tool is installed. For more information, see Httpcfg Overview. The Windows Support Tools documentation explains the syntax for the Httpcfg.exe tool.

If you are running Windows Vista, use the Netsh.exe tool that is already installed.

Note

Modifying certificates stored on the computer requires administrative privileges.

Determine how ports are configured

  1. In Windows Server 2003 or Windows XP, use the HttpCfg.exe tool to view the current port configuration, using the query and ssl switches, as shown in the following example.

    httpcfg query ssl  
    
  2. In Windows Vista, use the Netsh.exe tool to view the current port configuration, as shown in the following example.

    netsh http show sslcert  
    

Get a certificate's thumbprint

  1. Use the Certificates MMC snap-in to find an X.509 certificate that has an intended purpose of client authentication. For more information, see How to: View Certificates with the MMC Snap-in.

  2. Access the certificate's thumbprint. For more information, see How to: Retrieve the Thumbprint of a Certificate.

  3. Copy the thumbprint of the certificate into a text editor, such as Notepad.

  4. Remove all spaces between the hexadecimal characters. One way to accomplish this is to use the text editor's find-and-replace feature and replace each space with a null character.

Bind an SSL certificate to a port number

  1. In Windows Server 2003 or Windows XP, use the HttpCfg.exe tool in "set" mode on the Secure Sockets Layer (SSL) store to bind the certificate to a port number. The tool uses the thumbprint to identify the certificate, as shown in the following example.

    httpcfg set ssl -i 0.0.0.0:8012 -h 0000000000003ed9cd0c315bbb6dc1c08da5e6  
    
    • The -i switch has the syntax of IP:port and instructs the tool to set the certificate to port 8012 of the computer. Optionally, the four zeroes that precede the number can also be replaced by the actual IP address of the computer.

    • The -h switch specifies the thumbprint of the certificate.

  2. In Windows Vista, use the Netsh.exe tool, as shown in the following example.

    netsh http add sslcert ipport=0.0.0.0:8000 certhash=0000000000003ed9cd0c315bbb6dc1c08da5e6 appid={00112233-4455-6677-8899-AABBCCDDEEFF}
    
    • The certhash parameter specifies the thumbprint of the certificate.

    • The ipport parameter specifies the IP address and port, and functions just like the -i switch of the Httpcfg.exe tool described.

    • The appid parameter is a GUID that can be used to identify the owning application.

Bind an SSL certificate to a port number and support client certificates

  1. In Windows Server 2003 or Windows XP, to support clients that authenticate with X.509 certificates at the transport layer, follow the preceding procedure but pass an additional command-line parameter to HttpCfg.exe, as shown in the following example.

    httpcfg set ssl -i 0.0.0.0:8012 -h 0000000000003ed9cd0c315bbb6dc1c08da5e6 -f 2  
    

    The -f switch has the syntax of n where n is a number between 1 and 7. A value of 2, as shown in the preceding example, enables client certificates at the transport layer. A value of 3 enables client certificates and maps those certificates to a Windows account. See HttpCfg.exe Help for the behavior of other values.

  2. In Windows Vista, to support clients that authenticate with X.509 certificates at the transport layer, follow the preceding procedure, but with an additional parameter, as shown in the following example.

    netsh http add sslcert ipport=0.0.0.0:8000 certhash=0000000000003ed9cd0c315bbb6dc1c08da5e6 appid={00112233-4455-6677-8899-AABBCCDDEEFF} clientcertnegotiation=enable  
    

Delete an SSL certificate from a port number

  1. Use the HttpCfg.exe or Netsh.exe tool to see the ports and thumbprints of all bindings on the computer. To print the information to disk, use the redirection character ">", as shown in the following example.

    httpcfg query ssl>myMachinePorts.txt  
    
  2. In Windows Server 2003 or Windows XP, use the HttpCfg.exe tool with the delete and ssl keywords. Use the -i switch to specify the IP:port number, and the -h switch to specify the thumbprint.

    httpcfg delete ssl -i 0.0.0.0:8005 -h 0000000000003ed9cd0c315bbb6dc1c08da5e6  
    
  3. In Windows Vista, use the Netsh.exe tool, as shown in the following example.

    Netsh http delete sslcert ipport=0.0.0.0:8005  
    

Example

The following code shows how to create a self-hosted service using the WSHttpBinding class set to transport security. When creating an application, specify the port number in the address.

// This string uses a function to prepend the computer name at run time.
string addressHttp = String.Format(
    "http://{0}:8080/Calculator",
    System.Net.Dns.GetHostEntry("").HostName);

WSHttpBinding b = new WSHttpBinding();
b.Security.Mode = SecurityMode.Transport;
b.Security.Transport.ClientCredentialType = HttpClientCredentialType.Certificate;

// You must create an array of URI objects to have a base address.
Uri a = new Uri(addressHttp);
Uri[] baseAddresses = new Uri[] { a };

// Create the ServiceHost. The service type (Calculator) is not
// shown here.
ServiceHost sh = new ServiceHost(typeof(Calculator), baseAddresses);

// Add an endpoint to the service. Insert the thumbprint of an X.509
// certificate found on your computer.
Type c = typeof(ICalculator);
sh.AddServiceEndpoint(c, b, "MyCalculator");
sh.Credentials.ServiceCertificate.SetCertificate(
    StoreLocation.LocalMachine,
    StoreName.My,
    X509FindType.FindBySubjectName,
    "contoso.com");

// This next line is optional. It specifies that the client's certificate
// does not have to be issued by a trusted authority, but can be issued
// by a peer if it is in the Trusted People store. Do not use this setting
// for production code. The default is PeerTrust, which specifies that
// the certificate must originate from a trusted certificate authority.

// sh.Credentials.ClientCertificate.Authentication.CertificateValidationMode =
// X509CertificateValidationMode.PeerOrChainTrust;
try
{
    sh.Open();

    string address = sh.Description.Endpoints[0].ListenUri.AbsoluteUri;
    Console.WriteLine("Listening @ {0}", address);
    Console.WriteLine("Press enter to close the service");
    Console.ReadLine();
    sh.Close();
}
catch (CommunicationException ce)
{
    Console.WriteLine("A communication error occurred: {0}", ce.Message);
    Console.WriteLine();
}
catch (System.Exception exc)
{
    Console.WriteLine("An unforeseen error occurred: {0}", exc.Message);
    Console.ReadLine();
}
' This string uses a function to prepend the computer name at run time.
Dim addressHttp As String = String.Format("http://{0}:8080/Calculator", _
System.Net.Dns.GetHostEntry("").HostName)

Dim b As New WSHttpBinding()
b.Security.Mode = SecurityMode.Transport
b.Security.Transport.ClientCredentialType = HttpClientCredentialType.Certificate

' You must create an array of URI objects to have a base address.
Dim a As New Uri(addressHttp)
Dim baseAddresses() As Uri = {a}

' Create the ServiceHost. The service type (Calculator) is not
' shown here.
Dim sh As New ServiceHost(GetType(Calculator), baseAddresses)

' Add an endpoint to the service. Insert the thumbprint of an X.509 
' certificate found on your computer. 
Dim c As Type = GetType(ICalculator)
sh.AddServiceEndpoint(c, b, "MyCalculator")
sh.Credentials.ServiceCertificate.SetCertificate( _
                StoreLocation.LocalMachine, _
                StoreName.My, _
                X509FindType.FindBySubjectName, _
                "contoso.com")

' This next line is optional. It specifies that the client's certificate
' does not have to be issued by a trusted authority, but can be issued
' by a peer if it is in the Trusted People store. Do not use this setting
' for production code. The default is PeerTrust, which specifies that 
' the certificate must originate from a trusted certificate authority.
' sh.Credentials.ClientCertificate.Authentication.CertificateValidationMode =
' X509CertificateValidationMode.PeerOrChainTrust
Try
    sh.Open()

    Dim address As String = sh.Description.Endpoints(0).ListenUri.AbsoluteUri
    Console.WriteLine("Listening @ {0}", address)
    Console.WriteLine("Press enter to close the service")
    Console.ReadLine()
    sh.Close()
Catch ce As CommunicationException
    Console.WriteLine("A communication error occurred: {0}", ce.Message)
    Console.WriteLine()
Catch exc As System.Exception
    Console.WriteLine("An unforeseen error occurred: {0}", exc.Message)
    Console.ReadLine()
End Try

See also