The SSH Shell subsystem
An SSH client can ask a server for several things over one connection. Most file transfer clients ask for the sftp subsystem, some automation asks to run a single command with exec, and an interactive client such as ssh user@host with no arguments asks for a shell.
Syncplify Server! answers that last request with a virtual shell: a small, fixed set of commands, interpreted by the server itself, operating on the session's own Virtual File System. It is not a shell on the host operating system, and it never starts an operating system process.
Whether a user may ask for it at all is governed by the ssh2_shell permission, like every other SSH subsystem.
IMPORTANT
This is a change in behaviour. See What changed, and why below if you are upgrading and you have automation that expected an operating system shell.
The command set
The virtual shell understands the following, and nothing else.
| Command | What it does |
|---|---|
help | List the available commands. ? does the same. |
pwd | Print the current directory. |
cd [directory] | Change the current directory. With no argument, return to the home directory. |
ls [-l] [path] | List a directory. -l shows size, modification time and permissions. |
stat <path> | Show the details of one entry. |
mkdir <directory> | Create a directory. |
rmdir <directory> | Remove a directory. The directory must be empty. |
rm <file> | Remove a file. |
mv <source> <destination> | Move or rename an entry. |
whoami | Show the account this session is signed in as. |
clear | Clear the screen. |
exit | Close the session. quit and logout do the same. |
For the convenience of people arriving from a Windows command prompt, dir, del, md, rd and ren are accepted as aliases for ls, rm, mkdir, rmdir and mv respectively.
Paths use forward slashes and are resolved inside the session's virtual file system, exactly as they are for SFTP. A path starting with / is relative to the root of that virtual file system, never to the root of the host. There is no way to name a location outside it.
Anything not in the table above is answered with unknown command. The reply does not enumerate what is available, so probing for a command tells the caller nothing they could not have learned from help.
What the virtual shell deliberately does not do
- It does not run programs. There is no
exec, no pipes, no redirection, no shell metacharacters, no environment variables and no globbing. - It does not expand wildcards.
rm *.tmpremoves a file literally named*.tmp, or reports that no such file exists. - It does not remove directory trees.
rmdirremoves an empty directory and refuses anything else, so a mistyped path cannot take a whole tree with it. - It does not read or write file contents. Use SFTP or SCP for that; the shell is for looking around and tidying up.
Quoting is supported so that names containing spaces can be given as a single argument, for example mv "quarterly report.xlsx" archive/. Quotes group, and do nothing else: there are no escape sequences and no substitutions.
What changed, and why
In previous versions, granting ssh2_shell caused the server to start a real operating system shell, /bin/sh on Unix or cmd.exe on Windows.
That child process carried no user credential. It inherited the identity of the service, which is root on Linux and SYSTEM on Windows. Every account granted ssh2_shell therefore held complete control of the host: not of their virtual file system, of the machine. It was also outside the product's permission model entirely, so virtual file system boundaries, per user permissions, quotas, speed limits and the audit log all stopped applying the moment the shell started.
The obvious fix, running the child as the user instead, is not available. A single process cannot hold different operating system identities for different sessions. On Linux, changing credentials is applied to the whole process by design, so it would change the identity of every session at once. Windows does offer per thread impersonation, but a Go program moves work between threads freely, so the identity would not reliably follow the session's work. This is a property of the operating systems, not a defect that a library could paper over, which is why earlier attempts in this area were abandoned.
So the shell no longer starts anything. It is an interpreter over the session's own virtual file system, using the same code path, the same permissions and the same logging as SFTP. This is the pattern the exec subsystem has always used in this product.
If you are upgrading
Automation that connected with an interactive shell and issued operating system commands will stop working, by design. Rewrite it in one of these ways:
- For file transfer, use SFTP or SCP, which is what almost all such automation is really doing.
- For anything the file transfer protocols cannot express, write a script and bind it to an event handler. Scripts run on the server under the operator's control, rather than under the control of whoever holds an account.
- If a user genuinely needs an operating system shell on that machine, give them an operating system account on that machine. That is a decision for whoever administers the host, and it should not be a side effect of a file transfer permission.
Revoking ssh2_shell from accounts that do not need to browse interactively remains good practice, as it always was.
