Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to validate a certificate?

I am just starting a project where by I will need to connect, using FTPS, to a 3rd party server. They are to provide us with their certificate I don't have it yet, so I am going to create our own development environment to get started. I am using the Alex FTPS Client as my starting point (http://ftps.codeplex.com/)... but am also open to using WinSCP as a different client.

My question(s) below is - how do I validate a certificate in .Net?

Steps Done So Far

  1. Installed and configured FileZilla Server

  2. created a self signed certificate using FileZilla

3. In the Alex FTPS Client, they have a callback with this signature

private static bool ValidateTestServerCertificate(
    object sender, 
    X509Certificate certificate, 
    X509Chain chain, 
    SslPolicyErrors sslPolicyErrors)
{
    // what goes here?
}

My (Various Questions) are:

  1. What is suppose to go in the method?

  2. I only have a modest understanding of certificates. Is the FileZilla self generated certificate even an X509 certificate? I must admit, I do not know the different types of certificate formats.

  3. What type of code do I write? When I use SSL in WCF or HTTP, alot of the plumbing was handled for me already. Is this not the case for FTPS? i.e. I would import or install a certificate using MMC snap-in Console in Windows.

  4. If I don't implement the Callback method in Alex FTPS, I get the message: "The remote certificate is invalid according to the validation procedure"

Thank you for any tips and pointers

like image 808
Raymond Avatar asked Feb 27 '14 17:02

Raymond


1 Answers

Gee, no answers... so I will answer my own question and it might be helpful for others. Here are my steps, not sure if everyone is needed, but this is what I ended up doing.

1) Installed FileZilla Server

  • Used it to create its own self-signed certificate
  • menu: Settings | SSL/TSL Settings | Generate New Certificate
  • enter in the appropriate values
  • ensuring I had the common name = server address correct.
  • this generated a certificate with private key in the .crt extension/format

2) As I was on Windows, I found I couldn't install this certificate in the certificate store, so the extra step was I needed to convert it first

  • downloaded OpenSSL http://www.openssl.org/related/binaries.html use command line to convert it to the .pfx format
  • openssl pkcs12 -export -out mycert.pfx -inkey myFileZilla.crt -in myFileZilla.crt

3) Launch windows MMC Snap-in Console

  • install the certificate into the Computer Account, Trusted Root Certification Authorities store

4) In my code (in FTPS library, in this case Alex FTPS My connection looks like this:

var credential = new NetworkCredential(username, password);
string message = _client.Connect(hostname, port, credential, 
    ESSLSupportMode.Implicit,
    null, // new RemoteCertificateValidationCallback(ValidateTestServerCertificate), 
    null, 0, 0, 0, null); 

The .net/Windows infrastructure plumbing handles all validation for me already

5) But if you wanted custom validation, or if you didn't want to install the certificate in the windows store, you can use this sample code here: http://msdn.microsoft.com/en-us/library/office/dd633677%28v=exchg.80%29.aspx

private static bool ValidateTestServerCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
    {
      // If the certificate is a valid, signed certificate, return true.
      if (sslPolicyErrors == System.Net.Security.SslPolicyErrors.None)
      {
        return true;
      }

      // If there are errors in the certificate chain, look at each error to determine the cause.
      if ((sslPolicyErrors & System.Net.Security.SslPolicyErrors.RemoteCertificateChainErrors) != 0)
      {
        if (chain != null && chain.ChainStatus != null)
        {
          foreach (System.Security.Cryptography.X509Certificates.X509ChainStatus status in chain.ChainStatus)
          {
            if ((certificate.Subject == certificate.Issuer) &&
               (status.Status == System.Security.Cryptography.X509Certificates.X509ChainStatusFlags.UntrustedRoot))
            {
              // Self-signed certificates with an untrusted root are valid. 
              continue;
            }
            else
            {
              if (status.Status != System.Security.Cryptography.X509Certificates.X509ChainStatusFlags.NoError)
              {
                // If there are any other errors in the certificate chain, the certificate is invalid,
             // so the method returns false.
                return false;
              }
            }
          }
        }

        // When processing reaches this line, the only errors in the certificate chain are 
    // untrusted root errors for self-signed certificates. These certificates are valid
    // for default Exchange server installations, so return true.
        return true;
      }
      else
      {
     // In all other cases, return false.
        return false;
      }
    }

Hope that helps people.

like image 132
Raymond Avatar answered Oct 19 '22 23:10

Raymond