0

The title seems contradictory? Read on...

I am attempting to list a folder on an FTP server using FtpWebRequest.

When I list a single folder "myserver.whatever.com/folder" It succeeds.

When I list a nested folder, "myserver.whatever.com/folder/folder1" It fails. Except it throws an exception that tells me it succeeds.

Specifically, this code:

request = (FtpWebRequest)WebRequest.Create(m_server + folder);
request.ClientCertificates = m_certificates;
request.Credentials = new NetworkCredential(m_userName.Normalize(), password.Normalize() );
request.EnableSsl = true;
request.Method = WebRequestMethods.Ftp.ListDirectory;
response = (FtpWebResponse)request.GetResponse();
Stream responseStream = response.GetResponseStream();
StreamReader reader = new StreamReader(responseStream);

Throws this exception:

The remote server returned an error: 150 Opening data connection. List started\r\n

Does Microsoft not know that a code of 150 is NOT AN ERROR? It there any workaround for Microsoft's defect?

Based on other posts, I have already tried removing and reinstalling a number of KBs, to no avail.

If there was a way to issue a "chdir" with this the FtpWebRequest object, I might get around this problem. But I can't find anything.

It does not appear to be an access rights issue. Otherwise the server should return a 550.

There were some posts regarding session resumption on the data port, however, since this does NOT fail on one folder level, only on two, the data connection would not seem to be the problem.

Does anyone have any suggestions?

SpacemanScott
  • 953
  • 9
  • 21
  • You may not have permission to do a ListDirectory on the default login folder. Error 150 " File status okay; about to open data connection.. You can add the default start folder to the uri. See : https://stackoverflow.com/questions/330155/how-do-you-change-directories-using-ftpwebrequest-net – jdweng Dec 23 '20 at 16:17
  • 2
    Some of my biggest file transfer headaches were resolved when I switched away from using System.Net.FtpWebRequest and to using a third party FTP lib; FtpWebRequest is kinda geared towards treating FTP servers like HTTP servers, whereas a usual FTP dialogue is more of an enduring session. Take a look at the .net wrapper for WinSCP - the author inhabits here and is a great source of tech advice – Caius Jard Dec 23 '20 at 16:39
  • Thanks @CaiusJard. – If OP wants to stick with `FtpWebRequest`, we need [log files](https://stackoverflow.com/q/9664650/850848) for both the forking and failing folder.. – Martin Prikryl Dec 23 '20 at 17:48
  • Thanks @MartinPrikryl C# isn't my language of choice, and this WebRequest as a FTP "WannaBe" is horrible. I wasn't aware of the logging option. That may help. – SpacemanScott Dec 24 '20 at 17:39
  • Thanks @jdweng. I got a trace and compared the good and the bad. I suspect it's a permissions issue. The server is in a behemoth company with red tape, hopefully we can unravel some of it. – SpacemanScott Dec 24 '20 at 18:04
  • Thanks @CaiusJard I also despise that WebRequest mess. But WinSCP has too much extra baggage to install on a client machine for my clients taste. I wrote my own C++/OpenSSL version for another project, but was hoping to avoid doing that here. – SpacemanScott Dec 24 '20 at 18:07
  • You can take a look at [something else](https://stackoverflow.com/questions/1371964/free-ftp-library). I've used edFTP and Fluent before now – Caius Jard Dec 24 '20 at 18:11
  • Use a sniffer like wireshark or fiddler and compare the first header of the good and bad requests. Make the c# look like the working request. You may need to add additional headers. – jdweng Dec 24 '20 at 18:47
  • Thanks. I was hoping someone knew the inner guts of that C# assembly, and why a success throws an exception as a failure. The trace seems to indicate that it's coming from the server. So I'll pressure the client to participate more. – SpacemanScott Dec 25 '20 at 21:04

1 Answers1

0

I have found what appears to be the issue. It may not be a complete solution, but it is a workaround.

First, thanks to MartinPrikryl for directing me to the log. A segment of the log looks like this:

System.Net Information: 0 : [24980] InitializeSecurityContext(In-Buffer length=0, Out-Buffer length=188, returned code=ContinueNeeded).
System.Net Information: 0 : [24980] FtpWebRequest#8810861::(Releasing FTP connection#49582139.)
System.Net Error: 0 : [24980] Exception in FtpWebRequest#8810861::GetResponse - The remote server returned an error: 150 Opening data connection. List started
..
   at System.Net.FtpWebRequest.SyncRequestCallback(Object obj)
   at System.Net.CommandStream.Dispose(Boolean disposing)
   at System.IO.Stream.Close()
   at System.Net.ConnectionPool.Destroy(PooledStream pooledStream)
   at System.Net.ConnectionPool.PutConnection(PooledStream pooledStream, Object owningObject, Int32 creationTimeout, Boolean canReuse)
   at System.Net.FtpWebRequest.FinishRequestStage(RequestStage stage)
   at System.Net.FtpWebRequest.GetResponse()

So, this appears to be coming from the data connection, which the server closed early. I have no indication what this server is, or what flavor of *NIX is it.

My solution was to simply change

request.Method = WebRequestMethods.Ftp.ListDirectory;

to

request.Method = WebRequestMethods.Ftp.ListDirectoryDetails;

That will result in a Unix style listing which will have to be parsed manually. In this case of an empty directory, it was simply:

dr-xr-xr-x   0 --NA--   --NA--            2 Dec 18 15:48 .
dr-xr-xr-x   0 --NA--   --NA--           16 Dec 18 15:48 ..

So, there is something to read, and the data channel does not close prematurely.

This differs from a Windows style directory listing which is (not an empty listing, obviously)

12-28-20  06:45PM       <DIR>          Some_Folder
10-07-20  09:35AM                 1148 a_file

Therefore when using "ListDirectoryDetails" is will be necessary to determine which type of server provided the reply, an easy enough task.

Note:

I repeated the test on a local Ubuntu machine, and did NOT have this issue that the customers server was giving me. So I am not clear what the difference is between vsftpd and their server, which does not identify itself (obviously for security reasons).

SpacemanScott
  • 953
  • 9
  • 21