SSH/SFTP Error: Must first connect to the SSH server

The following error is explained in this post:

ChilkatLog:
  DownloadFileByName:
    DllDate: Apr 25 2018
    ChilkatVersion: 9.5.0.73
    UnlockPrefix: *
    Architecture: Little Endian; 64-bit
    Language: Cocoa Objective-C
    VerboseLogging: 0
    SftpVersion: 3
    Component successfully unlocked using purchased unlock code.
    Must first connect to the SSH server.
  --DownloadFileByName
--ChilkatLog

The above error can happen after a long period of inactivity. Let’s say your application successfully connected and authenticated w/ the SFTP server, did some things, and then did not do anything else for a long period of time.  Meanwhile, the SFTP server decides to disconnect because the client has been inactive for too long.  The client (your app + Chilkat) would only discover that the server has dropped the connection once it tries to do something, such as in a call to DownloadFileByName.  The non-connected socket is discovered in the 1st attempt to send a message, and thus you receive the above error.

There are two possible actions an application might take:

  1. Prevent the disconnect by periodically calling sftp.SendIgnore to keep the connection from being inactive.
  2. (auto-recovery)  If DownloadFileByName (or some other method) returns false/0 to indicate failure, examine the sftp.IsConnected property.  If not connected, then automatically re-connect, re-authenticate, and call InitializeSftp to get back to a connected state, and then retry the method.

C# SFTP Upload from Byte[]

This example demonstrates how to open a remote file on an SSH/SFTP server,
write to the file, and then close it.  This is analogous to opening a local file,
writing to it, and closing it.  The SFTP protocol (i.e. Secure File Transfer over SSH),
follows the same concepts as typical file I/O programming -- i.e. open a file,
read, write, close, etc.).

// Assume at this point we already have a Chilkat.SFtp object
// connected to a server, authenticated, and InitializeSftp has
// already been called..


// To upload a binary file from Byte[], the procedure is to open the remote file,
// write the data, and then close the file.

// Open a remote file, returning a handle to the open file.
string handle = sftp.OpenFile("test.dat", "readWrite", "createTruncate");
if (!sftp.LastMethodSuccess)
    {
    textBox2.Text = sftp.LastErrorText;
    return;
    }

string text = "To live is the rarest thing in the world. Most people exist, that is all. -- Oscar Wilde\r\n";
byte[] bytes= System.Text.Encoding.UTF8.GetBytes(text);

// Write some data to the file.
bool success;
for (int i = 0; i < 20; i++)
    {
    // It is possible to write bytes:
    success = sftp.WriteFileBytes(handle, bytes);
    // It is also possible to write the string:
    if (success) success = sftp.WriteFileText(handle, "utf-8", text);

    if (!success)
        {
        textBox2.Text = sftp.LastErrorText;
        return;
        }
    }

// Close the remote file.
if (!sftp.CloseHandle(handle))
    {
    textBox2.Text = sftp.LastErrorText;
    return;
    }
 

How to know that SFTP Upload was Transferred Successfully?

Question:

In the online reference documentation, it says that “bool UploadFileByName(string remoteFilePath, string localFilePath)” will return true if success or false for failure.

My question is that how does your component know that the file had been transferred successfully? Does it get ACK from SFTP server or that only means that client had sent the file successfully but not guarantee that SFTP server had received the file successfully?

Answer:

The SFTP Specifications are such that each data packet must be acknowledged by the server with a response message.  The upload is successful after all packets have been sent and all responses (acks) have been received.

SSH/SFTP Specifications (RFC)

SSH

  • RFC 4250 The Secure Shell (SSH) Protocol Assigned Numbers
  • RFC 4251 The Secure Shell (SSH) Protocol Architecture
  • RFC 4252 The Secure Shell (SSH) Authentication Protocol
  • RFC 4253 The Secure Shell (SSH) Transport Layer Protocol
  • RFC 4254 The Secure Shell (SSH) Connection Protocol
  • RFC 4255 Using DNS to Securely Publish Secure Shell (SSH) Key Fingerprints
  • RFC 4256 Generic Message Exchange Authentication for the Secure Shell Protocol (SSH)
  • RFC 4335 The Secure Shell (SSH) Session Channel Break Extension
  • RFC 4344 The Secure Shell (SSH) Transport Layer Encryption Modes
  • RFC 4419 Diffie-Hellman Group Exchange for the Secure Shell (SSH) Transport Layer Protocol
  • RFC 4462 Generic Security Service Application Program Interface (GSS-API) Authentication and Key Exchange for the Secure Shell (SSH) Protocol
  • RFC 4716 The Secure Shell (SSH) Public Key File Format
  • RFC 4819 Secure Shell Public Key Subsystem

SFTP

SFTP vs. FTPS

Clarification on the acronyms “SFTP” and “FTPS”

“SFTP” is the Secure File Transfer Protocol over SSH.  It is a protocol unrelated to the FTP protocol. (It is actually a subsystem of SSH.)  The Chilkat SSH / SFTP component is used for “SFTP”.  SFTP is achieved by connecting to an SSH server at port 22.

On the other hand, the Chilkat FTP2 component is for FTP.   FTP servers listen at port 21 (non-SSL/TLS) and port 990 (SSL).  FTP over SSL (i.e. port 990) is called “FTPS”.

SSH/SFTP RemoveFile: “Permission Denied”

If the SFTP server responds to a request to delete a file with the error “Permission Denied”, it means the SSH/SFTP user account does not have permission to delete the file. Here is a sample LastErrorText that shows the path of the remote file to be deleted, and the “Permission Denied” response from the server.

ChilkatLog:
  RemoveFile:
    DllDate: Jan 19 2012
    UnlockPrefix: abcxyz
    Username: abcxyz
    Architecture: Little Endian; 64-bit
    Language: .NET 2.0 / x64
    SshVersion: SSH-2.0-CoreFTP-0.2.3
    SftpVersion: 3
    filename: /something1/something2/something.dat
    StatusResponse:
      Request: FXP_REMOVE
      StatusCode: 3
      StatusMessage: Permission denied
    Failed.

The LastErrorText shows the exact path of the file passed to the server.  In the case above, it is an absolute path.  If a relative path was passed, it would be relative to the HOME directory of the SSH/SFTP user account.  The “Permission denied” response from the server indicates that the FXP_REMOVE message was properly formatted and correctly sent to the server.  It was received correctly by the server, but the SSH/SFTP user account does not have permission to delete the requested file.  The fix to this problem is not on the client-side (unless a mistake in the file path was made).  The fix is on the server-side to give the SSH/SFTP user account permission to delete the requested file.

SFTP Open: The meaning of “No Such File”

When an SSH/SFTP server responds to a file open request with the error message “No Such File”, it means that it could not find the file (i.e. there was no such file).

This is a snippet from the LastErrorText property:

...
    OpenRemoteFile:
      filename: something.dat
      access: readOnly
      createDisposition: openExisting
      v3Flags: 0x1
      Sent FXP_OPEN
      StatusResponse:
        Request: FXP_OPEN
        StatusCode: 2
        StatusMessage: No such file
...

If a relative path is used, then the path is relative to the HOME directory of the SSH/SFTP user account.  In the case above, only a filename is provided, and therefore the SSH/SFTP server is expecting to find “something.dat” in the HOME directory of the SSH/SFTP user account.  If the file is not there, the response will be “No Such File”.

If an absolute path is used (i.e. a path starting with “/”), then it is a request to open that exact absolute path (relative to the filesystem’s root “/” directory).  It is likely that if the path is not under the SSH/SFTP user’s home directory, the server will not have permission to access the file and the error returned will be “No Permission” (or something pertaining to not having permission to access a file or directory..)