Si pour la protection de vos données vous avez opté pour l'option d'un dossier sécurisé par encfs ou LUKS, saisir à chaque ouverture de session un mot de passe supplémentaire devient vite pénible. Et comme c'est humain, dés que quelque chose est trop pénible, on a tendance à le contourner. L'objectif est donc ici de n'utiliser qu'un seul et même mot de passe pour se connecter ET ouvrir le dossier protégé dans la foulée.
Si le module LDAP est capable de récupérer le mot de passe saisi via pam_tcb, cela implique que ce mot de passe peut être aussi récupéré par un module qui peut du coup l'utiliser comme clef pour un montage encfs. Faut-il encore qu'un tel module existe...
En réalité il existe trois modules capables de faire cela : pam_encfs, pam_mount et pam_script. pam_encfs n'est plus développé, on va donc éviter. pam_mount semble parfaitement fait pour le job mais reste plus limité dans son champ d'action que pam_script qui va tout simplement nous mettre à disposition trois scripts :
Ce module PAM s'installe très facile par le paquet idoine. Après cela, il va nous falloir modifier /etc/pam.d/system-auth pour prendre en charge notre module :
#%PAM-1.0
auth required pam_env.so
auth [success=2 default=ignore] pam_tcb.so shadow fork nullok prefix=$2a$ count=8
auth [success=1 default=ignore] pam_ldap.so use_first_pass
auth requisite pam_deny.so
auth optional pam_script.so expose=1 runas=root
...
session optional pam_keyinit.so revoke
session required pam_limits.so
session [success=1 default=ignore] pam_succeed_if.so service in crond quiet use_uid
session required pam_tcb.so
session required pam_script.so
Pour le groupe de gestion session, c'est relativement simple, on rajoute simplement une règle à la fin avec required comme contrôle. Nous aurions aussi pu mettre optionnal cela n'aurait pas changé grand chose ici. Dans tous les cas deux scripts /etc/security/onsessionopen et /etc/security/onsessionclose seront appelés à l'arrivée et au départ de l'utilisateur.
Le groupe auth est en revanche un peu plus compliqué si vous le comparez à la version originale. A l'origine nos règles 2 et 3 étaient associées à un contrôle sufficient. Le problème de cette approche est que si l'utilisateur réussi son authentification, notre module script ne sera jamais appelé. Nous allons donc utiliser la syntaxe étendue pour régler cela.
Pour ceux qui ont fait un peu d'assembleur dans leur vie, la méthode ne devrait pas trop dépayser. L'idée est d'indiquer que l'action pour success est un saut de 2 modules pour pam_tcb et de 1 module pour pam_ldap. Ainsi nous réglons le problème du sufficient. En cas de succès, le traitement saute sur pam_script, sinon il se poursuit sur pam_deny.
Concernant pam_script dans le groupe auth, le paramètre de module expose=1 permet (attention à ce que vous faite !!) de transmettre le mot de passe dans l'environnement d'exécution script /etc/security/onauth, par la variable $PAM_AUTHTOK. Enfin runas=root lance le module en tant qu'utilisateur privilégié. Normalement rien ne devrait nous obliger à faire cela. Malheureusement pour des raisons qui me sont encore assez obscures, si c'est l'utilisateur se connectant qui lance ce script, le montage se fait une fois sur deux. Plus exactement une fois sur deux encfs déclare que l'utilisateur n'a pas les droits sur /dev/fuse...
Que les scripts soient lancé par root ou pas, ils auront toujours les deux mêmes paramètres. Tout d'abord l'UID de l'utilisateur qui s'authentifie/ouvre sa session, suivi du nom du groupe de gestion (auth ou session). Maintenant ne nous reste maintenant plus qu'à écrire ces scripts. Ils sont auto documentés et j'espère pas trop difficile à comprendre :
#! /bin/sh
# pam_script passe l'UID de l'utlisateur en paramètre
user=$(awk -F : "/:$1:/ {print \$1}" /etc/passwd)
# récupération du mot de passe
password=$PAM_AUTHTOK
# si l'utilisateur est le bon...
if [ $user == "gaston" ] ; then
# définition du montage
mount_point="/home/gaston/vault";
crypt_point="/home/gaston/.vault";
# vérification de l'existence du montage (pas la peine de faire cela deux fois)
mount=$(mount | grep "$mount_point");
if [ -z "$mount" ] ; then
# montage encfs. -S indique un mot de passe via stdin
echo "$password" | encfs -S $crypt_point $mount_point --public -o user=$user
fi
fi
Dans la suite de l'obligation de mettre pam_script en runas=root, il faut du coup rajouter les options --public -o user=$user pour que l'utilisateur gaston puisse voir son dossier protégé.
Ensuite pour la déconnexion
#! /bin/sh
# pam_script passe l'UID de l'utlisateur en paramètre
user=$(awk -F : "/:$1:/ {print \$1}" /etc/passwd)
# si l'utilisateur est le bon...
if [ $user == "gaston" ] ; then
mount_point="/home/gaston/vault";
crypt_point="/home/gaston/.vault";
mount=$(mount | grep "$mount_point");
# si le montage existe
if [ ! -z "$mount" ] ; then
fusermount -u $mount_point
fi
fi
Voilà, à partir de maintenant, toute connection de l'utilisation gaston implique le montage de son dossier protégé (sous réserve que les deux mots de passe soient les mêmes, évidemment). Et lorsque gaston clôture sa session, le dossier est automatiquement démonté. Cette protection ne sert évidemment à rien si gaston oublie de verrouiller sa session lorsqu'il part au petit coin. De même il est plus qu'utile d'ajouter le verrouillage de la console lors du lancement de l'économiseur d'écran.
Merci pour cet article très intéressant et comme toujours bien documenté.
J'imagine qu'il doit être possible de faire sur le même principe de l'authentification par reconnaissance vocale mais je ne trouve rien sur le sujet
Je verrai bien un 'monte moi la partition toto', synthèse vocale, authentification, montage.
@Dab Arf, on a les mêmes idées
il y a eu un tel projet il y a quelques années mais il a été abandonné (un projet de thèse) et il est enterré quelque par dans la LT de google... C'est pour cela que je m'étais rabattu sur la clef USB qui marche pas si mal ma foi, mais qui est incompatible avec le montage automatique vu qu'il n'y a pas de mot de passe.
petite typo : "required - La même chose que required sauf que l'utilisateur est averti tout de suite."
je suppose que tu voulais dire "requisite- La même chose que required sauf que l'utilisateur est averti tout de suite."
Sinon merci pour ton blog qui est une source d'information très utile (et très bien expliqué)
@myquist merci
C'est corrigé.
Poster un nouveau commentaire