Seu script destina-se a implementar um shell . Isto é, um interpretador de linha de comando.
Quando você executa:
ssh host echo '$foo;' rm -rf '/*'
ssh (o cliente) concatena os argumentos (com caracteres ASCII SPC) e os envia para sshd . sshd chama o shell de login do usuário como:
exec("the-shell", "-c", "the command-line")
Está aqui:
exec("the-shell", "-c", "echo $foo; rm -rf /*")
E isso seria exatamente o mesmo se você tivesse executado:
ssh host echo '$foo;' 'rm -rf' '/*'
ssh host 'echo $foo;' "rm -rf /*"
ssh host 'echo $foo; rm -rf /*'
(o mais recente é o preferido, pois deixa mais claro o que está sendo feito).
Depende de the-shell decidir o que fazer com essa linha de comando. Por exemplo, um shell parecido com o Bourne expandiria $foo para o conteúdo da variável foo , consideraria ; como um separador de comando e expandiria /* para uma lista classificada de arquivos não ocultos em / .
Agora, no seu caso desde então, você pode fazer o que quiser. Mas como isso é um usuário restrito , você pode querer fazer o mínimo possível, por exemplo, não expandir variável, substituição de comando, globs, não permitir vários comandos, não redirecionar ...
Outra coisa a ter em conta é que bash lê ~/.bashrc quando chamado sobre ssh mesmo quando não é interativo (como na interpretação de scripts). Então, você provavelmente deve evitar bash (ou pelo menos chamá-lo como sh ) ou certificar-se de que ~/.bashrc não seja escrito pelo usuário ou use a opção --norc .
Agora, desde que você define como a linha de comando é interpretada, basta dividir um espaço, nova linha ou guia:
#!/bin/sh -
[ "$1" = "-c" ] || exit
set -f
set -- $2
case $1 in
(record)
shift
exec /usr/sbin/record.py "$@"
;;
("" | *[!0-9]*)
echo >&2 "command not supported"
exit 1
;;
(*)
nc ...
;;
esac
Mas isso significa que record não poderá receber argumentos que contenham espaços, tabulações ou novas linhas ou que estejam vazios.
Se você quiser que eles consigam fazer isso, você precisa fornecer algum tipo de sintaxe de cotação.
zsh tem uma ferramenta de análise de cotações que pode ajudá-lo:
#! /bin/zsh -f
[ "$1" = "-c" ] || exit
set -- "${(Q@)${(Z:cn:)2}}"
case $1 in
(record)
shift
exec /usr/sbin/record.py "$@"
;;
("" | *[!0-9]*)
echo >&2 "command not supported"
exit 1
;;
(*)
nc ...
;;
esac
Isso suporta aspas duplas e as barras invertidas. Mas também consideraria coisas como $(foo bar) como um único argumento (mesmo que não o expandisse).