title: How do I identify my server name for server authentication by client in c#
body: <p>I have recently been trying to make a SSL encrypted Server/Client in C#.</p>
  
  <p>I have followed <a href="http://msdn.microsoft.com/en-us/library/system.net.security.sslstream.aspx" rel="noreferrer">this</a> tutorial on MSDN, however, it required a certificate to be created for the server and client usage using <em>makecert.exe</em> so I found an example and it created the certificate fine:</p>
  
  <blockquote>
    <p>makecert -sr LocalMachine -ss My -n "CN=Test" -sky exchange -sk 123456 c:/Test.cer</p>
  </blockquote>
  
  <p>but now the problem is the server starts and waits for clients, when the client connects it uses the <em>machine name</em> which as far as I can gather is my IP in this case:</p>
  
  <blockquote>
    <p>127.0.0.1</p>
  </blockquote>
  
  <p>, and then it requires the <em>servers name</em> which must match the <em>servers name</em> on the certificate (<em>Test.cer</em>). I have tried multiple combinations (such as "Test" "LocalMachine","127.0.0.1" but cant seem to get the clients given <em>server name</em> to match thus allowing the connection. The error I get is:</p>
  
  <blockquote>
    <p>Certificate error: RemoteCertificateNameMismatch, RemoteCertificateChainErrors
    Exception: the remote certificate is invalid according to the validation procedure</p>
  </blockquote>
  
  <p>here is the code I'm using it differs from the MSDN example only in the fact that I assign the certificate path for the server in the app and the machine name and server name of the client too:</p>
  
  <p><strong>SslTcpServer.cs</strong></p>
  
  <pre><code>using System;
  using System.Collections;
  using System.Net;
  using System.Net.Sockets;
  using System.Net.Security;
  using System.Security.Authentication;
  using System.Text;
  using System.Security.Cryptography.X509Certificates;
  using System.IO;
  
  namespace Examples.System.Net
  {
      public sealed class SslTcpServer
      {
          static X509Certificate serverCertificate = null;
          // The certificate parameter specifies the name of the file  
          // containing the machine certificate. 
          public static void RunServer(string certificate)
          {
              serverCertificate = X509Certificate.CreateFromCertFile(certificate);
              // Create a TCP/IP (IPv4) socket and listen for incoming connections.
              TcpListener listener = new TcpListener(IPAddress.Any, 8080);
              listener.Start();
              while (true)
              {
                  Console.WriteLine("Waiting for a client to connect...");
                  // Application blocks while waiting for an incoming connection. 
                  // Type CNTL-C to terminate the server.
                  TcpClient client = listener.AcceptTcpClient();
                  ProcessClient(client);
              }
          }
          static void ProcessClient(TcpClient client)
          {
              // A client has connected. Create the  
              // SslStream using the client's network stream.
              SslStream sslStream = new SslStream(
                  client.GetStream(), false);
              // Authenticate the server but don't require the client to authenticate. 
              try
              {
                  sslStream.AuthenticateAsServer(serverCertificate,
                      false, SslProtocols.Tls, true);
                  // Display the properties and settings for the authenticated stream.
                  DisplaySecurityLevel(sslStream);
                  DisplaySecurityServices(sslStream);
                  DisplayCertificateInformation(sslStream);
                  DisplayStreamProperties(sslStream);
  
                  // Set timeouts for the read and write to 5 seconds.
                  sslStream.ReadTimeout = 5000;
                  sslStream.WriteTimeout = 5000;
                  // Read a message from the client.   
                  Console.WriteLine("Waiting for client message...");
                  string messageData = ReadMessage(sslStream);
                  Console.WriteLine("Received: {0}", messageData);
  
                  // Write a message to the client. 
                  byte[] message = Encoding.UTF8.GetBytes("Hello from the server.&lt;EOF&gt;");
                  Console.WriteLine("Sending hello message.");
                  sslStream.Write(message);
              }
              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.");
                  sslStream.Close();
                  client.Close();
                  return;
              }
              finally
              {
                  // The client stream will be closed with the sslStream 
                  // because we specified this behavior when creating 
                  // the sslStream.
                  sslStream.Close();
                  client.Close();
              }
          }
          static string ReadMessage(SslStream sslStream)
          {
              // Read the  message sent by the client. 
              // The client signals the end of the message using the 
              // "&lt;EOF&gt;" marker.
              byte[] buffer = new byte[2048];
              StringBuilder messageData = new StringBuilder();
              int bytes = -1;
              do
              {
                  // Read the client's test message.
                  bytes = sslStream.Read(buffer, 0, buffer.Length);
  
                  // Use Decoder class to convert from bytes to UTF8 
                  // in case a character spans two buffers.
                  Decoder decoder = Encoding.UTF8.GetDecoder();
                  char[] chars = new char[decoder.GetCharCount(buffer, 0, bytes)];
                  decoder.GetChars(buffer, 0, bytes, chars, 0);
                  messageData.Append(chars);
                  // Check for EOF or an empty message. 
                  if (messageData.ToString().IndexOf("&lt;EOF&gt;") != -1)
                  {
                      break;
                  }
              } while (bytes != 0);
  
              return messageData.ToString();
          }
          static void DisplaySecurityLevel(SslStream stream)
          {
              Console.WriteLine("Cipher: {0} strength {1}", stream.CipherAlgorithm, stream.CipherStrength);
              Console.WriteLine("Hash: {0} strength {1}", stream.HashAlgorithm, stream.HashStrength);
              Console.WriteLine("Key exchange: {0} strength {1}", stream.KeyExchangeAlgorithm, stream.KeyExchangeStrength);
              Console.WriteLine("Protocol: {0}", stream.SslProtocol);
          }
          static void DisplaySecurityServices(SslStream stream)
          {
              Console.WriteLine("Is authenticated: {0} as server? {1}", stream.IsAuthenticated, stream.IsServer);
              Console.WriteLine("IsSigned: {0}", stream.IsSigned);
              Console.WriteLine("Is Encrypted: {0}", stream.IsEncrypted);
          }
          static void DisplayStreamProperties(SslStream stream)
          {
              Console.WriteLine("Can read: {0}, write {1}", stream.CanRead, stream.CanWrite);
              Console.WriteLine("Can timeout: {0}", stream.CanTimeout);
          }
          static void DisplayCertificateInformation(SslStream stream)
          {
              Console.WriteLine("Certificate revocation list checked: {0}", stream.CheckCertRevocationStatus);
  
              X509Certificate localCertificate = stream.LocalCertificate;
              if (stream.LocalCertificate != null)
              {
                  Console.WriteLine("Local cert was issued to {0} and is valid from {1} until {2}.",
                      localCertificate.Subject,
                      localCertificate.GetEffectiveDateString(),
                      localCertificate.GetExpirationDateString());
              }
              else
              {
                  Console.WriteLine("Local certificate is null.");
              }
              // Display the properties of the client's certificate.
              X509Certificate remoteCertificate = stream.RemoteCertificate;
              if (stream.RemoteCertificate != null)
              {
                  Console.WriteLine("Remote cert was issued to {0} and is valid from {1} until {2}.",
                      remoteCertificate.Subject,
                      remoteCertificate.GetEffectiveDateString(),
                      remoteCertificate.GetExpirationDateString());
              }
              else
              {
                  Console.WriteLine("Remote certificate is null.");
              }
          }
          public static void Main(string[] args)
          {
              string certificate = "c:/Test.cer";
              SslTcpServer.RunServer(certificate);
          }
      }
  }
  </code></pre>
  
  <p><strong>SslTcpClient.cs</strong></p>
  
  <pre><code>using System;
  using System.Collections;
  using System.Net;
  using System.Net.Security;
  using System.Net.Sockets;
  using System.Security.Authentication;
  using System.Text;
  using System.Security.Cryptography.X509Certificates;
  using System.IO;
  
  namespace Examples.System.Net
  {
      public class SslTcpClient
      {
          private static Hashtable certificateErrors = new Hashtable();
  
          // 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 void RunClient(string machineName, string serverName)
          {
              // Create a TCP/IP client socket. 
              // machineName is the host running the server application.
              TcpClient client = new TcpClient(machineName, 8080);
              Console.WriteLine("Client connected.");
              // Create an SSL stream that will close the client's stream.
              SslStream sslStream = new SslStream(
                  client.GetStream(),
                  false,
                  new RemoteCertificateValidationCallback(ValidateServerCertificate),
                  null
                  );
              // The server name must match the name on the server certificate. 
              try
              {
                  sslStream.AuthenticateAsClient(serverName);
              }
              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.");
                  client.Close();
                  return;
              }
              // Encode a test message into a byte array. 
              // Signal the end of the message using the "&lt;EOF&gt;".
              byte[] messsage = Encoding.UTF8.GetBytes("Hello from the client.&lt;EOF&gt;");
              // Send hello message to the server. 
              sslStream.Write(messsage);
              sslStream.Flush();
              // Read message from the server. 
              string serverMessage = ReadMessage(sslStream);
              Console.WriteLine("Server says: {0}", serverMessage);
              // Close the client connection.
              client.Close();
              Console.WriteLine("Client closed.");
          }
          static string ReadMessage(SslStream sslStream)
          {
              // Read the  message sent by the server. 
              // The end of the message is signaled using the 
              // "&lt;EOF&gt;" marker.
              byte[] buffer = new byte[2048];
              StringBuilder messageData = new StringBuilder();
              int bytes = -1;
              do
              {
                  bytes = sslStream.Read(buffer, 0, buffer.Length);
  
                  // Use Decoder class to convert from bytes to UTF8 
                  // in case a character spans two buffers.
                  Decoder decoder = Encoding.UTF8.GetDecoder();
                  char[] chars = new char[decoder.GetCharCount(buffer, 0, bytes)];
                  decoder.GetChars(buffer, 0, bytes, chars, 0);
                  messageData.Append(chars);
                  // Check for EOF. 
                  if (messageData.ToString().IndexOf("&lt;EOF&gt;") != -1)
                  {
                      break;
                  }
              } while (bytes != 0);
  
              return messageData.ToString();
          }
          public static void Main(string[] args)
          {
              string serverCertificateName = null;
              string machineName = null;
              /*
              // User can specify the machine name and server name. 
              // Server name must match the name on the server's certificate. 
              machineName = args[0];
              if (args.Length &lt; 2)
              {
                  serverCertificateName = machineName;
              }
              else
              {
                  serverCertificateName = args[1];
              }*/
              machineName = "127.0.0.1";
              serverCertificateName = "David-PC";// tried Test, LocalMachine and 127.0.0.1
              SslTcpClient.RunClient(machineName, serverCertificateName);
              Console.ReadKey();
          }
      }
  }
  </code></pre>
  
  <p>EDIT:</p>
  
  <p>The server accepts the clients connection and everything but it times out while waiting for the client to send a message. (The client wont authenticate with server due to the server name in the certificate being different from the one I supplied in the client) well thats my thoughts on it just to clarify</p>
  
  <p>UPDATE:</p>
  
  <p>According to an answer I have changed the certficiate maker to:</p>
  
  <blockquote>
    <p>makecert -sr LocalMachine -ss My -n "CN=localhost" -sky exchange -sk 123456 c:/Test.cer
    and in my client I have:</p>
  </blockquote>
  
  <pre><code>        machineName = "127.0.0.1";
          serverCertificateName = "localhost";// tried Test, LocalMachine and 127.0.0.1
          SslTcpClient.RunClient(machineName, serverCertificateName);
  </code></pre>
  
  <p>now I get the exception:</p>
  
  <blockquote>
    <p>RemoteCertificateChainErrors
    Exception: the remote certificate is invalid according to the validation procedure</p>
  </blockquote>
  
  <p>which is occuring here:</p>
  
  <pre><code>  // The server name must match the name on the server certificate. 
              try
              {
                  sslStream.AuthenticateAsClient(serverName);
              }
              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. "+ e.Message);
                  client.Close();
                  return;
              }  
  </code></pre>