EldoS | Feel safer!

Software components for data protection, secure storage and transfer

[C#] TElSimpleSFTPClient throws System.IO.FileNotFoundException

Also by EldoS: CallbackRegistry
A component to monitor and control Windows registry access and create virtual registry keys.
#31005
Posted: 10/15/2014 17:11:05
by Alan Reinhold (Priority Standard support level)
Joined: 10/15/2014
Posts: 12

While working with the TElSimpleSFTPClient, I have noticed that the .OpenStream and .OpenFile methods will throw a System.IO.FileNotFoundException despite having SBSftpCommon.Unit.fmOpenOrCreate flag in the OpenModes when the destination file doesn't exist. However, if I add the SBSftpCommon.Unit.fmCreate flag, the file will be created as expected. According to the documentation, the fmOpenOrCreate should open the file if it exists or create it if it doesn't exist. It seems that I should not have to add the fmCreate flag as well for it to not throw this exception.

Here is the code that is throwing the exception

Code

SBSimpleSftp.TElSimpleSFTPClient _sftpClient = new SBSimpleSftp.TElSimpleSFTPClient();

<setup code...>

using (SBSftp.TElSftpStream stream = _sftpClient.OpenStream("new_file.txt", SBSftpCommon.Unit.fmWrite | SBSftpCommon.Unit.fmOpenOrCreate | SBSftpCommon.Unit.fmText))
{
   using (System.IO.StreamWrite writer = new StreamWriter(stream, Encoding.UTF8))
   {
      writer.Write(@"here is some sample text");
   }
}


Also, the documentation for the methods say that it should only be throwing EElSFTPError. Should I expect any function with in the TElSimpleSFTPClient to throw other .Net exception?

I am currently running SecureBlackbox version 12.0.260.0 with an Evaluation key and connecting to a Unix server. Currently seeing the behavior in both a .Net 4.0 Client profile and a standard .Net 4.0 profile.
#31008
Posted: 10/16/2014 01:11:30
by Eugene Mayevski (EldoS Corp.)

Thank you for contacting us.

You don't specify the path to the file. All paths in SFTP must be absolute. If you don't know the absolute path, you can try calling GetAbsolutePath(".") which will return something valid for the SFTP server (this will not necessarily be the absolute path valid for the remote file system, but the SFTP server can translate it).

I.e. you should call OpenStream("/path/to/filename.ext", ...).


Sincerely yours
Eugene Mayevski
#31012
Posted: 10/16/2014 02:03:46
by Alan Reinhold (Priority Standard support level)
Joined: 10/15/2014
Posts: 12

Interesting. The other times when this does work it creates the file with my home or starting directory of my SSH session without the need of an absolute path. So in this example, if my home directory was /home/user1, the file would be created at /home/user1/new_file.txt. I will try it with an absolute path and see if the behavior changes.
#31013
Posted: 10/16/2014 02:08:41
by Eugene Mayevski (EldoS Corp.)

Quote
Alan Reinhold wrote:
The other times when this does work it creates the file with my home or starting directory of my SSH session without the need of an absolute path.


This is server-specific and is not guaranteed to work even within the same server software. When you omit the path you are telling the server "put the file wherever you think current directory is" and the rest depends on factors that you don't usually control (architecture of the server, the OS, server setup).


Sincerely yours
Eugene Mayevski
#31027
Posted: 10/16/2014 14:57:13
by Alan Reinhold (Priority Standard support level)
Joined: 10/15/2014
Posts: 12

Ok, I have tested this code with a absolute path, and I am still getting the System.IO.FileNotFoundException ("No such file") when I specify the fmOpenOrCreate flag with an non-existing file name.

Here is the new code that I am using

Code
using (SBSftp.TElSftpStream stream = _sftpClient.OpenStream("/home/testuser/new_file.txt", SBSftpCommon.Unit.fmWrite | SBSftpCommon.Unit.fmOpenOrCreate | SBSftpCommon.Unit.fmText))
{
   using (System.IO.StreamWrite writer = new StreamWriter(stream, Encoding.UTF8))
   {
      writer.Write(@"here is some sample text");
   }
}


Now, if I add the "fmCreate" flag to the OpenStream/OpenFile command, I do not get the exception.

Quote
If you don't know the absolute path, you can try calling GetAbsolutePath(".")


I'm not finding a GetAbsolutePath function on the TElSimpleSFTPClient.
#31031
Posted: 10/17/2014 02:04:08
by Vsevolod Ievgiienko (EldoS Corp.)

Quote
I'm not finding a GetAbsolutePath function on the TElSimpleSFTPClient.

Sorry, its called TElSimpleSFTPClient.RequestAbsolutePath. Are you able to open the file using TElSimpleSFTPClient.OpenFile?
#31042
Posted: 10/17/2014 15:57:47
by Alan Reinhold (Priority Standard support level)
Joined: 10/15/2014
Posts: 12

TElSimpleSFTPClient.OpenFile exhibits a similar behavior as the TElSimpleSFTPClient.OpenStream. If the file does not exists and the fmOpenOrCreate flag is specified, the function throws a EElSFTPError ("No such file") on the OpenFile line. Here is the code that I am using to test the function

Code
SBSimpleSftp.TElSimpleSFTPClient _sftpClient = new SBSimpleSftp.TElSimpleSFTPClient();

<setup code...>

byte[] data = null;
using (MemoryStream memStream = new MemoryStream())
{
   using (StreamWriter writer = new StreamWriter(memStream, Encoding.UTF8))
   {
      writer.Write("This is a new set of tests words to be written during the write byte test");
   }
   data = memStream.ToArray();
}

_sftpClient.Open();

byte[] fileHandle =  _sftpClient.OpenFile("/home/testuser/new_sftp_file.txt", SBSftpCommon.Unit.fmWrite | SBSftpCommon.Unit.fmOpenOrCreate | SBSftpCommon.Unit.fmText, new SBSftpCommon.TElSftpFileAttributes());
_sftpClient.Write(fileHandle, 0, data);

_sftpClient.CloseHandle(fileHandle);

_sftpClient.Close();


Also, here is the stack trace for the error:

Code
   at SBSftp.TElSftpClient.OpenFileSync(String Filename, Int32 Modes, TElSftpFileAttributes Attributes)
   at SBSimpleSftp.TElSimpleSFTPClient.OpenFile(String Filename, Int32 Modes, TElSftpFileAttributes Attributes)
   at SecureBlackboxSFTP.Program.Main(String[] args) in C:\Projects\SecureBlackboxSFTP\SecureBlackboxSFTP\Program.cs:line 41
   at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
   at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
   at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
   at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Threading.ThreadHelper.ThreadStart()
#31043
Posted: 10/17/2014 16:04:14
by Eugene Mayevski (EldoS Corp.)

Thank you for the details.

OpenFileSync throws the error reported by the server itself (OpenStream() method emulates local errors by intercepting ESFTPError thrown by OpenFile() method).

I think the server is confused by some parameter that you pass. This does happen sometimes - SSH / SFTP servers have plenty of glitches unfortunately.

First of all please remove the text mode (fmText). Also (for simplicity) try passing null as Attributes.

The next thing to try is limit SFTP versions. The file is opened with different flags depending if it's SFTP version 3-4, 5 or 6 negotiated. Setting Versions to just SFTP 3 will change the flags a bit and maybe this affects the result.


Sincerely yours
Eugene Mayevski
#31044
Posted: 10/17/2014 16:42:21
by Alan Reinhold (Priority Standard support level)
Joined: 10/15/2014
Posts: 12

Ok, I tried the above changes, and the behavior is the same. I am currently testing against OpenSSH_6.6.1p1, OpenSSL 1.0.01i. I turned up the SFTP logging on the test server and I'm seeing the following logs when attempting to open the file:

Code
sftp-server[635]: received client version 3
sftp-server[635]: open "/home/testuser/new_sftp_file.txt" flags WRITE mode 0666
sftp-server[635]: sent status No such file


Now if I run this code (added the fmCreate flag)

Code
SBSimpleSftp.TElSimpleSFTPClient _sftpClient = new SBSimpleSftp.TElSimpleSFTPClient();
_sftpClient.Versions = SBSftpCommon.Unit.sbSFTP3;

<setup code...>

byte[] data = null;
using (MemoryStream memStream = new MemoryStream())
{
   using (StreamWriter writer = new StreamWriter(memStream, Encoding.UTF8))
   {
      writer.Write("This is a new set of tests words to be written during the write byte test");
   }
   data = memStream.ToArray();
}

_sftpClient.Open();

byte[] fileHandle =  _sftpClient.OpenFile("/home/testuser/new_sftp_file.txt", SBSftpCommon.Unit.fmWrite | SBSftpCommon.Unit.fmOpenOrCreate | SBSftpCommon.Unit.fmCreate, null);
_sftpClient.Write(fileHandle, 0, data);

_sftpClient.CloseHandle(fileHandle);

_sftpClient.Close();


I am seeing the "WRITE,CREATE" flag being handed to the sftp-server process for the open command in the logs.

Hopefully, this added information from the server logs will help a bit more and tracking down this issue.
#31102
Posted: 10/24/2014 04:37:04
by Ken Ivanov (EldoS Corp.)

Hello Alan,

Sorry for the delayed reply.

Sets of operations supported by different versions of SFTP protocol differ drastically. In particular, support for open-or-create mode was only added in SFTP version 5. In earlier versions the interpretation of the fmOpenOrCreate flag is subject to a particular implementation.

As you negotiate on SFTP version 3, there is no guarantee that fmOpenOrCreate flag will work as expected (though it probably *may* with some implementations).

Still, I agree that the behaviour exposed by TElSimpleSFTPClient is not something you would expect to see in this case. We will extend the implementation of TElSimpleSFTPClient to emulate fmOpenOrCreate on earlier SFTP versions.

Ken
Also by EldoS: Solid File System
A virtual file system that offers a feature-rich storage for application documents and data with built-in compression and encryption.

Reply

Statistics

Topic viewed 1889 times

Number of guests: 1, registered members: 0, in total hidden: 0




|

Back to top

As of July 15, 2016 EldoS Corporation will operate as a division of /n software inc. For more information, please read the announcement.

Got it!