Ma première idée fût d'utiliser pam usb. Ce projet permet de s'authentifier avec une clef USB et fournit un module PAM. Que fait pam usb ? Il génére une clef RSA sur la clef. La signature de la clef est sauvegardée dans le répertoire .auth de l'utilisateur. Cette clef peut-être chiffrée avec une passphrase. Il est également possible d'ajouter une access-list contenant les n° de série des clefs autorisées
Lors de l'insertion de la clef USB, pam usb vérifie la présence de la clef RSA et compare sa signature avec le .auth. Si la clef est chiffrée, le module PAM de pam usb demande la passphrase. En cas de présence d'une acl, le n° de série est comparé aux n° autorisés.
Premier inconvénient de pam usb, il n'y pas de paquet DEBIAN. La compilation est cependant très facile. Cette solution ne permet de déchiffrée la clef ssh et de l'ajoutée à l'agent ssh. Pour cela il faut utiliser pam ssh pour lequel il existe un paquet DEBIAN pour stable, testing et unstable. pam ssh fournit également un module PAM. Il est possible d'utiliser plusieurs modules PAM qui se "passent" le mot de passe. Dans notre cas, il faut donc utiliser le même mot de passe pour la clef privée pam usb et la clef privée ssh. Ce n'est pas trés pratique, notamment quand on souhaite modifier le mot de passe.
pam usb et pam ssh ont un point commum : tous les deux utilisent une clef privée chiffrée RSA (DSA est également utilisable avec openSSH). Dans ce cas pourquoi utiliser un clef supplémentaire pour pam usb ? En effet, un des buts est d'utiliser ssh-agent, l'utilisation de la clef privée est donc indispensable. À ce stade, il faut trouver un moyen pour utiliser uniquiement pam ssh, c'est-à-dire :
Cette solution peut-être mise en place en utilisant les outils standards de GNU/Linux, c'est donc cette solution qui sera développée et pam usb ne sera pas retenu.
Je ne suivrai pas le chemin complet qui m'a amené à la solution. En effet, j'ai essayé diverses méthodes pour arriver à ce que je voulais à cause de certaines contraintes de udev et hotplug. Pour résumer : il fallait assurer le montage et le démontage de la clef et également d'autres actions détaillée ci-après. Por cela, il faut que udev et/ou hotplug exécutent un script au branchement et débranchement de la clef. Faire exécuter un script au branchement est simple avec hotplug mais pour assurer le débranchement, il faut obligatoirement passer par udev.
Au branchement d'un périphérique, udev applique les régles présentes dans /etc/urdev/rules.d/ (ce répertoire peut-être différent sur une autre distribution). La suite a été écrite grâce à http://wiki.archlinux.org/index.php/Using_udev_to_map_multiple_entries_to_a_device et http://www.reactivated.net/writing_udev_rules.html.
Il est possible de changer le nom, les permissions, le groupe le owner du fichier périphérique, etc.. Il est également possible de lancer un script avec udev à partir de la version 0.58 (pas dans sarge ou ubuntu hoary)
hotplug prend la suite de udev. Pour cela, hotplug consulte les fichiers .usermap contenus dans le répertoire /etc/hotplug.d/usb/ pour les périphériques USB. Il faut donc constituer un fichier que j'ai appelé athentification.usermap. Pour connaitre les paramètres à inclure dans ce fichier, il y a un trés bon commentaire sur un forum linuxfr. Ce fichier permet de lancer également un script au branchement comme udev.
Faut-il utiliser udev ou hotplug pour lancer le script ? Ma préférence va à hotplug car c'est la méthode la plus standard par rapport à ce qui est fait dans DEBIAN. Il faut noter que les scripts udev et hotplug n'ont pas accès aux mêmes variables d'environnement qui contiennent le nom du périphérique, son constructeur, etc. De plus il y a un bug ou une feature avec hotplug. Au branchement d'un périphérique, hotplug exécute le script qui est configuré dans le fichier .usermap mais lors du débranchement, il exécute le script contenu dans /var/run/usb/ qui se nomme par exemple %proc%bus%usb%001%002 (vous aurez remarquer le chemin vers le périphérique dans /proc en remplaçant les / par des %. Il faut donc créer ce fichier au moment du branchement du périphérique
Pour commencer, voici quelques informations sur la clef USB utilisée. C'est une clef de 256Mo partitionnée en 2. J'ai créé une partition de ~50 ko en fin de clef pour stocker la clef privée SSH.
Contenu de la clef :
$ ls -la
total 18
drwxr-xr-x 3 root root 1024 2005-08-25 23:48 .
drwxr-xr-x 6 root root 4096 2005-08-26 01:17 ..
-rw------- 1 sylvain root 736 2005-08-25 23:48 .id_dsa
drwx------ 2 root root 12288 2005-08-25 18:10 lost+found
Habituellement, ssh recherche la clef privée dans $HOME/.ssh, pour cela il suffit de créer un lien : ln -s /media/disk_by-uuid_xxxx-xxx-xxxxxx-xxxxx/.id_dsa id_dsa. Le nom du répertoire dans /media sera expliquée dans quelques lignes
Régle pour udev
sylvain@milhouse /home/sylvain $ cat /etc/udev/rules.d/z99-authentification.rules
BUS="usb", SYSFS{product}="product name", SYSFS{serial}="XXXXXXXXXXX", KERNEL="sd?2", GROUP="sylvain", MODE="640", RUN+="/usr/local/sbin/udev_authentification"
Quelques explications : le fichier doit être suffixé par .rules. Le préfixe z99- est présent pour que cette règle soit exécutée en dernier. Cette régle sera utilsée avec la clef USB identifiée par "product name" avec le numéro de série "XXXXXXXXX"sur la deuxième partition du périphérique (sd?2). Elle positionne le groupe du périphérique à sylvain, positionne les permisssions à 640 (user:rw group:r) et exécute le fichier /usr/local/sbin/udev_authentification. Le changement de groupe et de permission évite que d'autres utlisateurs puissent monter cette partition.
Script exécuté par udev et hotplug
Lors de l'insertion de la clef USB, c'est udev qui lance ce script et qui positionne $ACTION, lors du dénranchement de la clef, c'est hotplug qui lance le script et positionne la variable. C'est important de retenir ce point car les informations disponibles avec udev et hotplug sont différentes.
sylvain@milhouse /home/sylvain $ cat /usr/local/sbin/udev_authentification
#!/bin/bash
ID_FS_UUID_FILE=/var/run/usb/authentification
MOUNT_PATH=/media/disk_by-uuid_
if [ "$ACTION" = "add" ]
then
# Montage du périphérique en mode read-only par mesure de sécurité :
# pas de risque d'écriture lors du débranchement, pas de possibilité de lecture pour les autres utiisateurs
mount -t ext2 -o ro,nosuid,noexec,nodev,noatime /dev/disk/by-uuid/${ID_FS_UUID} ${MOUNT_PATH}${ID_FS_UUID}
# Le script sera exécuté par hotplug lors du débranchement, la variable $ID_FS_UUID n'est alors plus disponible
# mais indispensable au démontage de la clef. La valeur est stockée dans un fichier
# TODO: trouver une autre solution
echo "ID_FS_UUID=$ID_FS_UUID" > $ID_FS_UUID_FILE
# Le username sera utile lors du débranchement de la cler et
# donc du blocage de l'écran par l'économiseur d'écran
# il est stocké dans le même fichier
# TODO: trouver une autre solution, c'est vriament pas propore
echo username=`stat -c %U ${MOUNT_PATH}${ID_FS_UUID}/.id_dsa` >> $ID_FS_UUID_FILE
fi
if [ "$ACTION" = "remove" ]
then
# Il faut exécuter umount avec le point de montage, la clef étant débranchée,
# le fichier périphérique n'existe plus.
# On retrouve le UUID dans /var/run/usb/authentification
. $ID_FS_UUID_FILE # charge les variables positionnées lors du branchement
rm $ID_FS_UUID_FILE # ménage
# bloquage de l'écran
# pour que ça fonctionne, il faut que la commande soit exécutée en tant qu'utilisateur
# BUG : si plusieurs displays sur la machine, ça ne marche pas
su $username -c 'xscreensaver-command -lock -display :0'
# Démontage de la clef
# À noter : la clef est déjà débranchée, le fichier périphérique n'existe plus
umount ${MOUNT_PATH}${ID_FS_UUID}
fi
Ce script est largement commenté mais quelques explications s'imposent tout de même. Commençons pas la variable La variable Pour le moment, la clef est montée automatiquement lors du branchement et un débranchement provoque le blocage de l'écran mais la solution ne permet pas encore de s'authentifier et de bébloquer l'écran de veille grâce à la passphrase de la clef privée SSH. Pour cela, nous aurons besoin de PAM. Pour les distibutions qui n'utilise une ancienne version de udev (< 0.58), le mot clef Pour installation pam ssh sous DEBIAN Le module pam ssh permet de s'authentifier avec la passphrase de la clef privée SSH. Si la passphrase est correcte, le module retourne OK. PAM offre une architecture qui permet d'utiliser plusieurs modules pour s'authentifier. On pourrait choisir que la passphrase n'est pas suffisante et qu'il faut également entrer son mot de passe "classique". Pour chaque service nécessitant une authentification, il existe un fichier dans le répertoire La documentation de pam ssh montre comment utiliser son module pam et l'authentification "classique" en secours. Dans ce cas, si l'authentification par pam ssh échoue (passphrase incorrecte), le système demandera le mot de passe "classique". Cette méthode permet donc de se loguer sans la clef USB ce qui n'est pas le but recherché. Voici le fichier Acutellement, il y a un bug dans le paquet libpam-ssh de DEBIAN que j'ai signalé. Le fichier ID_FS_UUID. Elle est positionnée par udev et n'est pas disponible avec hotplug (ou alors je n'ai pas trouvé). La valeur stockée dans $ID_FS_UUID identifie une partition, on peut retouver sa valeur en tapant la commande blkid /dev/sda2. Les régles par défaut de hotplug crée un lien entre le fichier périphérique /dev/sdxx et /dev/disk/by-uuid/uuid_de_la_partition. Cette même règle crée plusieurs autres liens, dans /dev/disk/ (by-id, by-path) qui ne sont pas utilisés ici. En créant un lien symbolique entre $HOME/.ssh/id_dsa et /media/disk_bu-uuid_xxx--xxxx-xxxx-xxx, on s'assure qu'une autre clef ne pourra pas être utilisée à la place de celle prévue.
$ACTION est positionée par udev et hotplug. Par contre les variables d'environnement comme $ID_FS_UUID ne sont pas disponibles avec hotplug. Quand la clef USB est branchée la variable $ACTION est positonnée à la valeur "add".RUN n'est pas utilisable dans les règles udev et le répertoire /dev/disk n'existe pas. Dans cas, le plus simple est de faire exécuter le montage par hotplug, par contre je ne sais pas comment gérer le "demontage" car le fichier /var/run/usb/xxxxx ne pointra pas vers le script sui permet de démonter la clef.pam ssh
apt-get install libpam-ssh/etc/pam.d/. Pour tester, il est préférable de ne pas modifier tous les services qui peuvent permettre de se loguer sur la machine au risque de ne plus pouvoir se loguer ;-).pam ssh pour l'authentification
/etc/pam.d/gdm où j'ai inséré l'authentification par pam ssh.
J'ai donc commenté la ligne
# (Replaces the `NOLOGINS_FILE' option from login.defs)
auth requisite pam_nologin.so
# This module parses /etc/environment (the standard for setting
# environ vars) and also allows you to use an extended config
# file /etc/security/pam_env.conf.
# (Replaces the `ENVIRON_FILE' setting from login.defs)
auth required pam_env.so
# Standard Un*x authentication.
@include pam-ssh-auth
#@include common-auth
# This allows certain extra groups to be granted to a user
# based on things like time of day, tty, service, and user.
# Please uncomment and edit /etc/security/group.conf if you
# wish to use this.
# (Replaces the `CONSOLE_GROUPS' option in login.defs)
# auth optional pam_group.so
# Uncomment and edit /etc/security/time.conf if you need to set
# time restrainst on logins.
# (Replaces the `PORTTIME_CHECKS_ENAB' option from login.defs
# as well as /etc/porttime)
# account requisite pam_time.so
# Uncomment and edit /etc/security/access.conf if you need to
# set access limits.
# (Replaces /etc/login.access file)
# account required pam_access.so
# Standard Un*x account and session
@include common-account
@include common-session
@include pam-ssh-session
# Sets up user limits according to /etc/security/limits.conf
# (Replaces the use of /etc/limits in old login)
session required pam_limits.so
# Prints the last login info upon succesful login
# (Replaces the `LASTLOG_ENAB' option from login.defs)
session optional pam_lastlog.so
# Prints the motd upon succesful login
# (Replaces the `MOTD_FILE' option in login.defs)
session optional pam_motd.so
# Prints the status of the user's mailbox upon succesful login
# (Replaces the `MAIL_CHECK_ENAB' option from login.defs). You
# can also enable a MAIL environment variable from here, but it
# is better handled by /etc/login.defs, since userdel also uses
# it to make sure that removing a user, also removes their mail
# spool file.
session optional pam_mail.so standard noenv
@include common-password
@include common-auth, ajouté la ligne @include pam-ssh-auth et @include pam-ssh-session. pam-ssh-auth est chargé du contrôle de la passphrase, pam-ssh-session insère la clef dans l'agent ssh. Ces lignes incluent dans le fichier /etc/pam.d/pam-ssh-auth et /etc/pam.d/pam-ssh-session, c'est la méthode utilisée par debian. En modifiant ces 2 fichiers, il est facile de changer le comportement de tous les services qui les utilisent./etc/pam.d/pam-ssh-auth contient par défaut auth sufficient pam_ssh.so try_first_pass keyfiles=id_dsa,id_rsa. Avec ce fichier, si on supprime l'authentification classique common-auth, il est possible de se loguer sans passphrase ou avec une passphrase erronée. Pour corriger ce grave problème de sécurité, il faut remplacer sufficient par required.
Comme écrit plus haut, il faut également utiliser pam pour permettre de débloquer l'économiseur d'écran. Pour cela, il faut modifier le fichier /etc/pam.d/xscreensaver
Il suffit de commenter la ligne concernant sylvain@milhouse /home/sylvain $ cat /etc/pam.d/xscreensaver
#
# /etc/pam.d/xscreensaver - PAM behavior for xscreensaver
#
#@include common-auth
@include pam-ssh-auth
@include pam-ssh-session
common-auth et d'ajouter celle concernant pam-ssh. Dans la pratique, la deuxième ligne pam-sss n'est pas utile. En effet, xscreensaver (idem pour xlock) ne fait pas appel au niveau "session" de PAM. Ce serait pourtant pratique car c'est ce niveau qui gère l'insertion de la clef dans l'agent SSH. Pour le moment, je n'ai donc pas trouvé de moyen d'insérer la clef privée SSH à ssh-agent lors de la désactivation du l'écran de veille.
encfs et le module PAM associé sont faciles à mettre en oeuvre en suivant la doc fournie Après juste quelques minutes d'essais et Thunderbird m'a lancé des insultes au démarrage, j'ai perdu qq mails (illisibles, vides, plusieurs textes identiques pour des mail différents). Bref, je n'ai pas continué l'expérience plus loin. Je me demande si les performances de mon PC (PIII 800) ne sont pas un peu faible chiffrer/déchifrrer de gros fichiers à la volée. En effet, j'ia rencontré des pbs avec le répertoire de Thunderbird où je garde les mails de Gulliver soient 26 Mo au total.