Using FtpWebRequest to do FTP over SSL


Last few weeks we were busy to get Whidbey Beta-2 bits ready for release.


If you are looking for some API where your application could talk to a FTP server, which supports SSL. FtpWebRequest under System.Net namespace is your solution. Here I will just point to SSL specific features of the class


Enabling FtpWebrequest to use Ssl is pretty simple, you just need to set EnableSsl flag before calling GetResponse() or GetRequestStream() on the FtpWebRequest object. 


FtpWebRequest request = WebRequest.Create(ftp://myftpserver/dir/filename);
request.Method = WebRequestMethods.Ftp.DownloadFile;
request.EnableSsl = true; // Here you enabled request to use ssl instead of clear text
WebResponse response = request.GetResponse();


Some people asked me why FtpWebRequest support “ftps:” protocol based uri similar to “https:”, the reason is there is no standard “ftps” scheme specified (yet) and ftp-over-ssl mechanism actually does not demand dedicated port for ssl, you could do it on the same server port on which you are doing regular clear text ftp. It depends on server configuration choice to force the SSL or allow both.


Once you start doing Ftp over SSL there are two important things you will need to know


Validating Server Certificate


If you were old WebRequest user, you might already know about using ServicePointManager.CertificatePolicy for https server certificate validation. In whidbey you will notice the compiler warning saying ServicePointManager.CertificatePolicy is obsolete and replaced with ServicePointManager.ServerCertificateValidationCallback which is delegate of type RemoteCertificateValidationDelegate. New delegate provide better programming model with all certificate errors reported in a single callback and you will also get instance of X509Chain object, which allow you to make decision on certificate chain. 


     ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(myCertificateValidation);


Actual method will look as below
  public bool myCertificateValidation(Object sender,
      X509Certificate cert,
      X509Chain chain,
      SslPolicyErrors Errors)
{ return (certificate.GetName() == “my_trusted_name”); }; //Just an example, not real world scenaio


:) Another additional advantage you can take with delegate is from anonymous method support of C# 2.0, especially if you have very simple 1-2 line certificateplicy to implement, see follwing example.


ServicePointManager.ServerCertificateValidationCallback = delegate(Object obj, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors) 
                                                                                             { return (certificate.GetName() == “my_trusted_name”); }; //Just an example, not real world scenaio


Using Client Certificate


Using Client certificate based authentication when connecting to FTP-SSL is no different then existing HttpWebRequest. You just need to assign appropriate X509Certificate instance to the request object before making GetResponse() or GetRequestStream() call.


 


This posting is provided “AS IS” with no warranties, and confers no rights

Comments (31)

  1. Cindy Ferguson says:

    When I turn on EnableSSL = true I get the following exception:

    ex.InnerException.Message = "The message or signature supplied for verification has been altered"

    Here is my code:

    FtpWebRequest ftpRequest = (FtpWebRequest)WebRequest.Create(myUrl);

    ftpRequest.Credentials = myCredentials;

    ftpRequest.EnableSsl = true;

    ftpRequest.Method = WebRequestMethods.Ftp.ListDirectory;

    using (FtpWebResponse ftpResponse = (FtpWebResponse)ftpRequest.GetResponse())

    It throws the exception on the final line of code. If comment out the ftpRequest.EnableSSL = true;, I do not get the error.

  2. Hari says:

    while using SSL(request.EnableSsl = True), the following error occurs: The remote server returned an error: (530) Not logged in

  3. LastHope says:

    Hi,

    I’d like an information: enabling the EnableSsl, it’ll make work the FTP connection as a SFTP connection

    http://en.wikipedia.org/wiki/SSH_file_transfer_protocol

    or not?

    If the answer is no, have you got some reference on how I might do it? 😉

  4. adarshk says:

    Actually current SSL support on ftp does not include SSH FTP. Currently it is based on ftps mentioned in http://en.wikipedia.org/wiki/FTPS, which is basically FTP over SSL/TLS. Future versions of FtpWebRequest may support SSH/FTP.

  5. Lucky says:

    I have looked at your sample code how do you implent this in a solution

  6. Navneet says:

    What other options available to to SFTP using .Net?

    Thanks,

    Navneet

  7. adarshk says:

    Until .net frameworks 3.0, there is no API available in .net frameworks. There may be some third party options available. (Ex. one I came across is http://www.jscape.com/articles/sftp_using_csharp.html). I could not get chance to try any of them, so can not recommend any from my side.

  8. Squish says:

    Hi,

    I’m using exactly the same code, but when I send a RETR to the FTP server the FTP server thinks its a GET instead.

    I’ve check the FTPWebRequest method and it thinks it’s a RETR because of the URI.

    I’ve tried it with other ftp servers and still nothing.

    Help..please

    Squish

  9. Milan Petrovic says:

    Can I see the code to implement SSL connection to a server? I have tried this:

    FtpWebRequest request = (FtpWebRequest)WebRequest.Create(serverUri);

    request.Credentials = new NetworkCredential("username", "password");

    request.Method = WebRequestMethods.Ftp.ListDirectory;

    request.UsePassive = true;

    request.EnableSsl = true;

    FtpWebResponse response = (FtpWebResponse)request.GetResponse();

    And I get following error: The remote certificate is invalid according to the validation procedure.

    Server I am trying to connect is FileZilla Server. How to validate this for connection? FileZilla Client works without any problem.

  10. Tom says:

    I am very confused as to the purpose of ClientCertificates on FtpWebRequest.  I need to authenticate to the FTP server using ONLY an X.509 certificate, no username or password.  It does not appear that there is any way to do this without going to a third-party component.

  11. Bob says:

    I am trying to call a web service over https that has an invalid ssl cert. The .Net 2.0 framework throws an "unable to connect to remote host" error every time I try to call a method on the web service. How do I override this. Here is my code:

    ServicePointManager.ServerCertificateValidationCallback = ValidateServerCertificate;

            hew.apshealthcare.healtheweb_test.HealthEWebService webservice = new hew.apshealthcare.healtheweb_test.HealthEWebService();

            DataSet ds = webservice.GetEligibleFamilyMembers(this.tbMemberId.Text);

            this.GridView1.DataSource = ds;

            this.GridView1.DataBind();

       }

       public static bool ValidateServerCertificate(

         object sender,

         X509Certificate certificate,

         X509Chain chain,

         SslPolicyErrors sslPolicyErrors)

       {

           return true;

       }

  12. Amit says:

    after enabling Enablessl property it gives an exception on  

       request.GetResponse();

    error(500): unrecognized command.

  13. Smoother says:

    I am also getting the exception (500) unrecognized command. I just remove the line enableSsl = true; and it works flawless. Is this bug or i am mising something?

  14. ftp server says:

    Does anyone know if this works with RaidenFTPD ftp server ssl connection?

  15. Sid says:

    I would like to know is there any way we can implement FTPS in implicit mode.

  16. Fx says:

    Hi,

    Does anybody have sample that works ?

  17. Sam says:

    If u don’t want to answer why u create this blog

  18. Shashikant Patil says:

    Perhaps you are trying to connect FTP port. FTPS port is different. Try putting correct SSL FTP port.

  19. artcoding says:

    The C# ftp SSL works in combination with FileZilla.

    Configure Filezilla:

    Server options: "SSL/TLS settings"

    • check "Enable SSL/TLS Support"
    • "Generate new certificate", file path should appear in "Private key file" and in "Certificate file"

    • check "Allow esplicit SSL/TLS on normal connections" and optionally recommanded "Force explicit SSL/TLS"

    Users:

    • "Add" user
  20. set the password

  21. check "Force SSL for user login"

  22. at "Shared folders", "Add" only one without alias and "Set as the home dir"

  23. In C#:

    request.EnableSsl = true;

    ServicePointManager.ServerCertificateValidationCallback = … return true;}

  • This is a current compile of the team’s existing blogs on FtpWebRequest. I am going to update it periodically

  • Guest says:

    This is an error when I call function reqFTP.GetRequestStream()

    "A call to SSPI failed, see inner exception."

    and this is innner exception message "The message received was unexpected or badly formatted"

  • varun says:

     try this .. ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(ValidateServerCertificate);

                                        {

                   FtpWebResponse response =

                   (FtpWebResponse)reqFTP.GetResponse();

    }

  • varun says:

     try this ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(ValidateServerCertificate);

                                        {

                   FtpWebResponse response =

                   (FtpWebResponse)reqFTP.GetResponse();

    }

  • Fatou says:

    Thanks for the post. It helped me a lot!

  • chaminda says:

    hey I had the same issue, but i was able to get this solved using the content in following posting

    http://www.codeguru.com/csharp/.net/net_security/authentication/article.php/c15051

  • chaminda says:

    hey I had the same issue, but i was able to get this solved using the content in following posting

    http://www.codeguru.com/csharp/.net/net_security/authentication/article.php/c15051

  • Chri says:

    Hm. im scratching my hair off. Why wont FtpWebRequest.EnableSsl=true; work? Anyone got some ideas why it wont work? It seems like its a big problem noone can sove.

    Regards

  • Giri says:

    I tried this and it worked, but the enablessl flag must be set to true right after you create the ftpwebrequest and before sending the network credential.