Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Clarify docs on ssh command behaviour #139

Closed
wants to merge 1 commit into from

Conversation

EvanTheB
Copy link

From what I can tell empirically, and looking at the source, all user commands are executed via a shell. Update the docs to match the behaviour.

it is executed on the remote host instead of a login shell.

* Execute the command using the user's shell. This uses the -c

@daztucker
Copy link
Contributor

The more I read this the more the original language seems correct. The fact that our sshd uses sh -c is an implementation detail on the server side and other servers might do something different. From the client's perspective the visible difference is that the command is run non-interactively instead of an interactive login, which is what the current text says to me.

@EvanTheB
Copy link
Author

Thanks Darren. Try this c program:

main (int argc, char** argv) {
  printf("argc:%d\n", argc);
  while (*argv) {
    printf("%s\n", *argv);
    argv++;
  }
}

Call it locally from bash like this:

> ./print_args 2 "3 3"
argc:3
./print_args
2
3 3

Then call it from bash but over ssh:

$ ssh evanbenn@evanbenn ./print_args 2 "3 3"
argc:4
./print_args
2
3
3

The result is different because the program is invoked via sh -c without quoting the arguments. To get the documented behaviour you need to know the implementation detail that ssh concatenates the args with spaces between, and then passes them to sh -c, and then quote your own args to undo the damage:

$ ssh evanbenn@evanbenn ./print_args 2 \"3 3\"
argc:3
bin/print_args
2
3 3

@daztucker
Copy link
Contributor

The result is different because the program is invoked via sh -c without quoting the arguments.

Actually, the damage has been done before it gets to the sh -c on the server. The SSH protocol only specifies a single string for the "exec" protocol message: https://datatracker.ietf.org/doc/html/rfc4254#section-6.5 so the client concatenates all of its arguments with single spaces before sending it all to the server. What the server does with that string depends on the server, and in the case of OpenSSH, also the what the user's shell is.

There's an enhancement request to provide a better way to pass arguments (https://bugzilla.mindrot.org/show_bug.cgi?id=2283), but that needs a protocol extension and even then it's not without its problems (eg to execvp something you need to know its path, but those are often set by shell startups, and sometimes shells form part of security controls, and so on).

Anyway, back to this PR: I think we could start by documenting the concatenate-the-args-with-spaces behaviour in ssh(1). A description of the $shell -c behaviour might be appropriate for sshd(8) but IMO it doesn't belong in ssh(1).

@daztucker
Copy link
Contributor

66a658b is an attempt to document the join-args-with-spaces behaviour.

@daztucker
Copy link
Contributor

And b0ec59a attempts to document the behaviour on the server side

@EvanTheB
Copy link
Author

That's great thanks for the explanation and patches Darren!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
2 participants