Search code examples
shellsshscp

ssh works with my custom shell but can't execute commands directly using ssh


I searched through the website but could not find a similar problem and a solution. So asked a new question. I'm trying to build a custom shell with some limited commands. As an start point, I'm using this custom shell provided by Stephen Brennan. It has 3 built-in commands (cd, help, exit) and also can execute system commands.

I edited this line in /etc/passwd:

root:x:0:0:root:/root:/mnt/n1/custom-shell

and also added this line to /etc/shells:

/mnt/n1/custom-shell

Now I can connect to remote host using ssh and my custom shell comes up and I can enter commands in it; but I can't execute commands directly using ssh. for example when i try to run "help" command on remote host using ssh 192.168.32.1 help, nothing happens. I tried ssh -v 192.168.32.1 help and the result is as follows. It sticks at debug1: Sending command: help.

OpenSSH_4.3p2, OpenSSL 0.9.8b 04 May 2006
debug1: Reading configuration data /etc/ssh/ssh_config
debug1: Applying options for *
debug1: Connecting to 192.168.32.1 [192.168.32.1] port 22.
debug1: Connection established.
debug1: permanently_set_uid: 0/0
debug1: identity file /root/.ssh/identity type -1
debug1: identity file /root/.ssh/id_rsa type 1
debug1: identity file /root/.ssh/id_dsa type -1
debug1: loaded 3 keys
debug1: Remote protocol version 1.99, remote software version OpenSSH_4.3
debug1: match: OpenSSH_4.3 pat OpenSSH*
debug1: Enabling compatibility mode for protocol 2.0
debug1: Local version string SSH-2.0-OpenSSH_4.3
debug1: SSH2_MSG_KEXINIT sent
debug1: SSH2_MSG_KEXINIT received
debug1: kex: server->client aes128-cbc hmac-md5 none
debug1: kex: client->server aes128-cbc hmac-md5 none
debug1: SSH2_MSG_KEX_DH_GEX_REQUEST(1024<1024<8192) sent
debug1: expecting SSH2_MSG_KEX_DH_GEX_GROUP
debug1: SSH2_MSG_KEX_DH_GEX_INIT sent
debug1: expecting SSH2_MSG_KEX_DH_GEX_REPLY
debug1: Host '192.168.32.1' is known and matches the RSA host key.
debug1: Found key in /root/.ssh/known_hosts:5
debug1: ssh_rsa_verify: signature correct
debug1: SSH2_MSG_NEWKEYS sent
debug1: expecting SSH2_MSG_NEWKEYS
debug1: SSH2_MSG_NEWKEYS received
debug1: SSH2_MSG_SERVICE_REQUEST sent
debug1: SSH2_MSG_SERVICE_ACCEPT received
debug1: Authentications that can continue: publickey,password,keyboard-interactive
debug1: Next authentication method: publickey
debug1: Trying private key: /root/.ssh/identity
debug1: Offering public key: /root/.ssh/id_rsa
debug1: Authentications that can continue: publickey,password,keyboard-interactive
debug1: Trying private key: /root/.ssh/id_dsa
debug1: Next authentication method: keyboard-interactive
debug1: Authentications that can continue: publickey,password,keyboard-interactive
debug1: Next authentication method: password
root@192.168.32.1's password:
debug1: Authentication succeeded (password).
debug1: channel 0: new [client-session]
debug1: Entering interactive session.
debug1: Sending environment.
debug1: Sending env LANG = en_US.UTF-8
debug1: Sending command: help

As a result I can't copy files to remote host using scp -v devel/bin/i2c root@192.168.32.1:/mnt/n1/ and it sticks at this line:

debug1: Sending command: scp -v -t /mnt/n1/

I searched alot but could not come to an answer. Any help would be appreciated.


Solution

  • One of the standard ways to invoke a shell and have it run a command is to invoke the shell program with the command-line parameters -c and the command to run. This is the method used by the OpenSSH SSH server to invoke commands requested by clients.

    When an SSH client connects to the OpenSSH server and requests to run a command on the server, the server ends up invoking the equivalent of this:

    $SHELL -c 'the-command'
    

    where $SHELL is the default shell for the user, -c is a literal command-line option, and the-command is the command requested by the client. The command is passed to the shell as a single command-line argument.

    In your case, the shell will be your custom shell program. It will need to parse its command-line parameters to pick up the fact that it was run with "-c" and a command string. Then it'll have to execute the command that was specified on the command line, instead of reading commands from an input stream.

    Like any other C program, the entry point into your shell program is a function called main:

    int main(int argc, char **argv)
    {
        ...
    

    When your shell is invoked from the SSH server in this fashion, you should find that argc and argv will reflect the command-line arguments ["/name/of-shell", "-c", "the-command"]. There are standard functions like getopt(3) that you can call to help parse the command-line arguments.

    I'll add that scp works by having the server invoke a program through your shell. So you'll see your custom shell being invoked (with a -c parameter and a command to run) for scp sessions. You may also see this for sftp sessions, depending on how the server is configured.