Welcome to witters:World     Sign in

FTPS over TLS/SSL using C#

One of the projects I'm working on has a requirement to send a document over a secure FTP connection.  The .NET framework has a built-in class to handle FTP (FTPWebRequest) so that was a good starting point.

The documentation for FTPWebRequest does not provide a great deal of detail on securing the communications between the client and the server.  There is simply a boolean property named EnableSSL to turn the encryption on or off.  Sounded pretty simple, so here's what I came up with for my upload method:

public bool UploadFile(Uri serverUri, string userName, string password, string fileName)
{
    // the serverUri should start with the ftp:// scheme.
    if (serverUri.Scheme != Uri.UriSchemeFtp)
        return false;

    try
    {
        // get the object used to communicate with the server.
        FtpWebRequest request = (FtpWebRequest)WebRequest.Create(serverUri);
        request.EnableSsl = true;
        request.Credentials = new NetworkCredential(userName, password);
        request.Method = WebRequestMethods.Ftp.UploadFile;

        // read file into byte array
        StreamReader sourceStream = new StreamReader(fileName);
        byte[] fileContents = Encoding.UTF8.GetBytes(sourceStream.ReadToEnd());
        sourceStream.Close();
        request.ContentLength = fileContents.Length;

        // send bytes to server
        Stream requestStream = request.GetRequestStream();
        requestStream.Write(fileContents, 0, fileContents.Length);
        requestStream.Close();

        FtpWebResponse response = (FtpWebResponse)request.GetResponse();
        Console.WriteLine("Response status: {0}", response.StatusDescription);
    }
    catch (Exception exc)
    {
        throw exc;
    }

    return true;
}

 

When I ran my app with that method, things didn't work quite like I wanted them to.  Here's the error I ended up with: "System.Security.Authentication.AuthenticationException: The remote certificate is invalid according to the validation procedure."

The problem is there is no validation procedure.  None of the MSDN articles I read said anything about certificate validation.  So after much googling, I finally found the missing piece of code in a forum post.  So I added a validation procedure and assigned it as the ServicePointManager.ServerCertificateValidationCallback.

public Program()
{
    ServicePointManager.ServerCertificateValidationCallback = AcceptAllCertificatePolicy;
}

public bool AcceptAllCertificatePolicy(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
    return true;
}

 

With that, my secure FTP was a success!  Of course, in real-world applications you will want to do some actual validation of the server certificate, but I'll leave that as an exercise for the reader.

Currently rated 5.0 by 2 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Posted by martin on Friday, December 12, 2008 8:10 PM
Permalink | Comments (2) | Post RSSRSS comment feed