Comment utiliser un shell de connexion non par défaut pour la connexion ssh

9

Je travaille actuellement dans un réseau qui utilise LDAP pour l'authentification. Ayant défini zshmon shell de connexion, j'ai rencontré un problème d'accès à distance sshà l'une des machines du réseau qui, apparemment, n'a pas été zshinstallée. La connexion échoue avec

Dec 8 19:16:11 abert sshd[20649]: User sorokine not allowed because shell /bin/zsh does not exist

La question est donc la suivante: comment dire à la machine distante d'utiliser un shell de connexion différent de celui qui a été configuré dans LDAP?

OpenSSH_6.0p1 Debian-4 + deb7u2, OpenSSL 1.0.1e

Sascha
la source
Avez-vous envisagé de changer votre shell LDAP en quelque chose de plus universel tel que /bin/sh, puis demandez à votre ~/.profileexécutable distant le shell approprié si disponible?
RobertL
Ce serait une option, mais pas très propre, donc je préfère l'éviter si possible.
Sascha

Réponses:

10

Si votre shell de connexion ne peut pas être exécuté sur une machine, vous ne pouvez pas vous y connecter via SSH, ou par la plupart des autres méthodes d'ailleurs. Le serveur SSH exécute toujours votre shell de connexion. Si vous passez une commande sur la sshligne de commande, le shell de connexion est exécuté avec -cet la chaîne de commande¹ comme arguments; sinon, le shell de connexion est exécuté comme un shell de connexion sans argument.

S'il y avait un moyen de contourner le shell de connexion, ce serait un trou de sécurité. Un compte peut être configuré comme un compte restreint en faisant de son shell de connexion un programme qui n'effectue qu'une seule tâche spécifique; par exemple, le shell de connexion pourrait être git-shellde n'autoriser que l'accès à un référentiel git, ou rssh, etc.

Pour vous connecter à cette machine, vous devrez soit vous organiser pour /bin/zshêtre présent, soit changer votre shell de connexion en quelque chose qui est présent.

Ce que je recommande dans un environnement hétérogène comme celui-ci, c'est de s'en tenir à /bin/shvotre shell de connexion, car il est présent partout. Définissez la SHELLvariable d'environnement sur /bin/zshsi elle est présente, de cette façon vous obtiendrez zsh comme un shell interactif.

if [ -x /bin/zsh ]; then
  export SHELL=/bin/zsh
fi

Pendant que vous y êtes, cela vous permet d'éviter de coder en dur le chemin vers zsh.

if SHELL=$(command -v zsh); then
  export SHELL
else
  unset SHELL
fi

Pour que zsh s'exécute automatiquement pour une connexion en mode texte, appelez-le depuis votre .profile. Si vous souhaitez utiliser .zprofilepour configurer les choses, faites-en un shell de connexion (mais vous n'obtiendrez pas le même environnement sur les machines où zsh n'est pas présent, donc je ne le recommande pas). Ne faites cela que s'il s'agit d'une connexion interactive, pas lorsque votre .profileest exécuté par un script, pendant la connexion en mode GUI, etc.

if case $- in *i*) true;; *) false;; esac &&  # interactive shell
   [ -z "$ZSH_VERSION" ] &&                   # not running zsh yet
   type zsh >/dev/null 2>/dev/null; then      # zsh is present
  exec zsh
fi

¹ Le client SSH concatène ses arguments sans option avec des espaces entre les deux et envoie la chaîne résultante via la connexion. Les protocoles SSH définissent la commande comme une chaîne, pas une liste de chaînes.

Gilles 'SO- arrête d'être méchant'
la source
Merci pour l'explication détaillée. Il semble que ce soit la seule façon de procéder qui n'implique pas l'installation de zsh sur la machine distante, et cela fonctionne parfaitement, alors je m'en tiendrai.
Sascha
Je suggère également d'ajouter un test [ "0$SHLVL" -lt 2 ]au cas où le shell de connexion par défaut prend en charge $SHLVLafin que bash -lou un autre shell puisse être exécuté si besoin est (par exemple en cas d'échec de zsh pour une raison quelconque). Ainsi ssh -t host bash -lexécuterait un bashshell de connexion sans exécuter zsh derrière. En outre, je remplacerais exec zshpar exec zsh -lpour que le .zloginfichier provienne.
vinc17
2

Vous devez éther installer le shell sur la machine spécifiée si vous avez un accès différent ou le demander à un administrateur de le faire pour vous ou changer votre shell dans ldap en un shell qui existe sur la machine distante.

(open) sshd vérifiera toujours le shell utilisateur et exécutera toujours ce shell tout ce qui est passé à exécuter. Si un autre shell est passé pour s'exécuter, il l'exécutera en le passant en argument au shell utilisateur, par exemple le shell utilisateur est '/ bin / sh' et vous passez en argument un shell csh qu'il exécutera "/ bin / sh -c / bin / csh '.

nkms
la source
Lire le commentaire redfast. openssh vous permet de contourner le shell par défaut.
Rui F Ribeiro
@Rui F Ribeiro S'il l'a fait, cela enlève en quelque sorte la logique derrière la définition du shell sur quelque chose comme '/ bin / false' ou '/ sbin / nologin'. Si vous faites référence à la modification du shell après la connexion, vous devez le faire comme je l'ai écrit ci-dessus (sh -c othersh), s'il n'y a pas de '/ bin / sh', vous n'avez pas de chance. (Testé sur Redhat).
nkms
Certes, si passwd a un shell qui n'est pas répertorié dans / etc / shells, vous ne vous connecterez pas de toute façon. Mais si vous êtes en mesure de vous connecter, et à moins que sshd_config ne vous oblige pas à un shell particulier, toute commande que l'utilisateur est capable d'exécuter est un jeu équitable. Si vous effectuez quelques tests supplémentaires, par exemple, ssh -l user server "ps ax" | grep bashil est facile de remarquer que le shell par défaut n'est pas toujours appelé. Ce qui empêche vraiment l'autre solution de fonctionner, c'est le contrôle de sécurité de zsh qui n'est pas dans / etc / shells
Rui F Ribeiro
@Rui F Ribeiro Exécutez strace -f sshd côté serveur. Vous verrez quelque chose comme "execve (" / bin / bash ", [" bash "," -c "," ps "] ..." De plus, / sbin / nologin est un shell valide dans / etc / shells.
nkms
La réponse de @RuiFRibeiro redfast00 est tout simplement fausse. Nkms a raison.
Gilles 'SO- arrête d'être méchant'