0

I have developped a web service in C# .Net 4.5, which connect to a ftp server (with SSL) and list all the files stored in a directory of the ftp server. The code worked fine last year (beginning of 2019 or end of 2018) but since I tested the code again 3 weeks ago and it doesnt not work anymore. I have tried many things:

-I have changed the target framework from 4.5 to 4.8 (Link of the article)

-Use the fluentFTP nuget package (but I have the same error

The thing is that I can connect to the ftp server with Filezilla and access to the directory without any error (So I guess that it is not a firewall issue) I have checked the logs of ftp exchanges between my computer and the ftp server and the error occurs during the ftp command MLSD -> Opening data channel for directory listing of "directory" (last message from the server -> .Net error: "authentication failed because the remote party has closed the transport stream"

Here is the code:

            FtpWebRequest request = (FtpWebRequest)WebRequest.Create("ftp://urlFtpServer:21/directory");
            request.Method = WebRequestMethods.Ftp.ListDirectory;
            request.EnableSsl = true;
            // Sets the user login and password.  
            request.Credentials = new NetworkCredential("login", "password");

            request.KeepAlive = true;

            try
            {
                // Send the request.
                using (FtpWebResponse response = (FtpWebResponse)request.GetResponse())
                {
                    using (Stream responseStream = response.GetResponseStream())
                    {
                        using (StreamReader reader = new StreamReader(responseStream))
                        {
                            IEnumerable<string> lstDirectoryFiles = reader.ReadToEnd()
                                                                   .Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);

                            // Use the user criteria to get only the file needed.
                            if (string.IsNullOrEmpty(in_searchPattern))
                                return lstDirectoryFiles.ToList();

                            Regex rgx = new Regex(in_searchPattern);

                            return lstDirectoryFiles.Where(st => rgx.IsMatch(st)).ToList();
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                //Here is the exception: authentication failed because the remote party has closed the transport stream
            }

Please help :)

I forgot to mention that the ftp request method WebRequestMethods.Ftp.MakeDirectory works fine

Bobson
  • 1
  • 2
  • If you're on Windows 7, set `ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;` before you create the connection. You might also need to validate the server certificate(s). If you have he same exception after setting the SecurityProtocol, add `ServicePointManager.ServerCertificateValidationCallback = (s, cert, ch, sec) => { return true; };`, for testing. – Jimi Feb 25 '20 at 09:30
  • Thanks Jimi for your answer. I'm on Windows 10 and have already tried: ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; ServicePointManager.ServerCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) => true; But still the exact same issue – Bobson Feb 25 '20 at 09:52
  • Just for testing, try `Ftp.ListDirectoryDetails` instead of `Ftp.ListDirectory`. See whether you have another error, the same or it goes on. If the listing returns empty results (server side), the connection may be lost (because it generates an exception, since WebRequest handles HttpStatusCodes > 399 as exceptions). Remove `:21` from the ftp address. – Jimi Feb 25 '20 at 10:19
  • With the method Ftp.ListDirectoryDetails I have exactly the same error... When I remove :21 from the ftp adress too (ftp://ftpUrl/Directory)... – Bobson Feb 25 '20 at 10:34
  • `Ftp.ListDirectoryDetails` doesn't send a `MLSD` command, it sends a `LIST` command. `Ftp.ListDirectory` sends a `NLST` command. – Jimi Feb 25 '20 at 10:59
  • FileZilla, AFAIK, doesn't use `MLSD` either. – Jimi Feb 25 '20 at 11:05
  • @Jimi FileZilla use MLSD command. With the method Ftp.ListDirectoryDetails I have the same error: "authentication failed because the remote party has closed the transport stream" – Bobson Feb 25 '20 at 11:13
  • With what configuration? I just tested it and the logs all have `LIST` commands. Anyway, not really important here, since it's `MLSD` that is less supported. `LIST` - what `Ftp.ListDirectoryDetails` sends - is supported everywhere. Try changing the path you're providing. The error you're reporting is related to SSL auth, though. – Jimi Feb 25 '20 at 11:19
  • @Jimi Here are the Filezilla command's logs when i try to access to a directory (Sorry it is in french): Statut : Récupération du contenu du dossier "/T"... Commande : CWD /T Réponse : 250 CWD successful. "/T" is current directory. Commande : PWD Réponse : 257 "/T" is current directory. Commande : PASV Réponse : 227 Entering Passive Mode (10,4,9,64,78,33) Commande : MLSD Réponse : 150 Opening data channel for directory listing of "/T" Réponse : 226 Successfully transferred "/T" Statut : Contenu du dossier "/T" affiché avec succès I changed the path and same error... – Bobson Feb 25 '20 at 14:09

2 Answers2

0

It could be due to the TLS support of the FTP server.

Try setting your ServicePointManager.SecurityProtocol to the different variants of TLS.

This article may also be of help.

  • Thanks for your answers but I have already tried: ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; ServicePointManager.ServerCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) => true; But still the same issue – Bobson Feb 25 '20 at 09:49
0

It is mostly caused by application's default security protocol type is set too low.

Set the SecurityProtocol in your application by adding this line.

ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls;

This can be added just before you call the FTP, or it can even be added in the application startup method.

Jaydeep Jadav
  • 836
  • 1
  • 11
  • 26