Expect, automatisation de commandes interactive

Publié le par /

Il m’arrive parfois de devoir débloquer une clé SSH dont je ne me souviens qu’à moitié de la phrase de passe. Je me souviens de la phrase mais plus des pièges qu’elle contient. J’enchaîne alors les essais jusqu’à retrouver la bonne version. Pour être sûr de tester toutes les options, je préfèrerais créer un fichier avec toutes les variations possibles de la clé et envoyer ce fichier sur l’entrée de ssh. Malheureusement ssh est prévu pour fonctionner en mode interactif, on ne peut donc pas faire quelque chose comme cat keys | ssh. J’en étais réduit à tester à la main toutes les combinaisons… jusqu’à ce que je découvre expect.

Expect est un programme qui ajoute au langage de script TCL des instructions permettant d’automatiser des commandes interactives comme par exemple ftp ou ssh. Les trois principales instructions à connaître sont :

  • spawn pour exécuter une commande sous le contrôle d’Expect ;
  • expect pour attendre que le programme affiche une chaîne de caractères ;
  • send pour envoyer une chaîne au programme.

Un exemple valant mieux qu’un long discours, voici le script que je viens de torcher. Je ne garantis pas que c’est la meilleure façon de faire, mais ça marche. Il lit des phrases de passe dans le fichier pass.txt et s’arrête en affichant la bonne. Pour mieux comprendre son fonctionnement vous pouvez virer l’envoi vers /dev/null des sorties d’Expect.

  #!/bin/bash
  IFS=$'\n'
  for line in $(cat pass.txt);
  do
    expect >/dev/null 2>/dev/null << EOF
      spawn ssh-add ~/.ssh/id_rsa
      expect Enter
      send "$line\r"
      expect {
        Bad   {puts "NOT FOUND\n"; exit 1}
        added {puts "FOUND\n" ; exit 0}
      }
      close
  EOF
    if [ $? -eq 0 ]
    then
      echo -e "Passphrase is $line\r"
      break
    fi
  done

Voilà, dans trois mois lorsqu’ssh-agent tombera à nouveau, j’aurai moins de mal à me rappeler de toutes mes phrases de passe.

Pour réagir, n'hésitez-pas à m'écrire : clochix chez clochix.net ou à soumettre l'url de votre commentaire :
(Je traite les mentions à la main, elles peuvent mettre plusieurs jours avant d'apparaître)

Si vous avez un compte Github, vous pouvez me proposer des corrections en éditant ce billet

Fork me on GitHub