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.

[adsense_id=”1″]