PAM et pam-auth-update ---------------------- L'authentification par mot de passe est gérée par le profil `common-auth`. Ce profil n'est pas utilisé directement, il est inclus depuis les profils de service présents dans `/etc/pam.d`. Le contenu de ce profil commun est généré automatiquement par la commande `pam-auth-update` pour tous les modules PAM qui livrent une définition dans `/usr/share/pam-configs`. Cette commande peut être invoquée en mode interactif (menu curses) ou en ligne de commande, éventuellement depuis un script de paquet `postinst`. Voir [pam-auth-update(8)] pour les détails. Les fichiers de définition dans `/usr/share/pam-configs` contiennent des fragments de profil PAM, et aussi des méta-données qui sont utilisées pendant l'exécution de `pam-auth-update`. La propriété la plus intéressante est `Priority`: elle détermine l'ordre d'apparition du module dans la liste du menu curses et dans le fichier `common-auth`. Les modules sont classés par ordre de priorité décroissante. Voir [PAMConfigFrameworkSpec]. Extrait d'un `common-auth` généré avec les définitions `krb5`, `unix` et `ccreds`: ``` # here are the per-package modules (the "Primary" block) auth [success=4 default=ignore] pam_krb5.so minimum_uid=1000 auth [success=3 default=ignore] pam_unix.so nullok_secure try_first_pass auth [success=2 default=ignore] pam_ccreds.so minimum_uid=1000 action=validate use_first_pass auth [default=ignore] pam_ccreds.so minimum_uid=1000 action=update # here's the fallback if no module succeeds auth requisite pam_deny.so # prime the stack with a positive return value if there isn't one already; # this avoids us returning an error just because nothing sets a success code # since the modules above will each just jump around auth required pam_permit.so ``` Les modules sont testés dans l'ordre d'apparition: d'abord `krb5`, si l'authentification Kerberos échoue on passe à `unix`, si l'authentification avec mot de passe local échoue on passe à `ccreds`, etc. Important: l'option `success=N` est une instruction de saut: si le module concerné authentifie l'utilisateur, alors les N modules suivants seront sautés, ce n'est pas la peine de les invoquer. Autrement dit, si `pam_krb5` réussit, on passe directement à `pam_permit`. Voir [pam.conf(5)] pour les détails sur les options. Mise en place de `pam_sss` -------------------------- Après avoir configuré SSSD, on active le profil `sss` avec `pam-auth-update`: ``` # pam-auth-update --remove krb5 --enable sss ``` Et là, c'est le drame : à l'ouverture de session, l'utilisateur n'obtient pas de ticket Kerberos :-( alors que la machine est bien connectée au réseau. Dans les logs, on a: ``` pam_unix(gdm-password:session): session opened for user meyd7400 by (uid=0) ``` C'est le module `unix` qui a authentifié l'utilisateur. Sur une autre machine, où (par chance) le mot de passe local est différent du mot de passe AD, le comportement est différent, le TGT est bien obtenu à l'ouverture de session en utilisant le mot de passe AD. Dans les logs, on a maintenant: ``` pam_unix(gdm-password:auth): authentication failure; logname= uid=0 euid=0 tty=/dev/tty1 ruser= rhost= user=meyd7400 pam_sss(gdm-password:auth): authentication success; logname= uid=0 euid=0 tty=/dev/tty1 ruser= rhost= user=meyd7400 [...] pam_unix(gdm-password:session): session opened for user meyd7400 by (uid=0) ``` Le module `unix` a échoué (normal) et le module `sss` a réussit. Pour comprendre ce comportement, il faut regarder dans le profil `common-auth`, qui contient maintenant ceci: ``` # here are the per-package modules (the "Primary" block) auth [success=4 default=ignore] pam_unix.so nullok_secure auth [success=3 default=ignore] pam_sss.so use_first_pass auth [success=2 default=ignore] pam_ccreds.so minimum_uid=1000 action=validate use_first_pass auth [default=ignore] pam_ccreds.so minimum_uid=1000 action=update ``` Le module `unix` est placé en premier, donc il réussit toujours quand le mot de passe local est synchronisé avec le mot de passe AD, et alors le module `sss` n'est pas appelé à cause de l'option `success`, cf plus haut. Si le module `sss` était placé en premier, comme l'était `krb5`, alors on aurait eu le résultat attendu. Mais il est placé en second par `pam-auth-update`, parce que sa priorité (128) est inférieure à celle de `unix` (256). Le module `pam_sss` en premier ------------------------------ D'apres [PAMConfigFrameworkSpec], le module `pam_sss` devrait avoir une priorité supérieure ou égale à 512, puisqu'il s'agit d'un profil qui "authenticates against a central network service, with rules to exclude administrative/system accounts". Or sa priorité définie dans `/usr/share/pam-configs/sss` est 128 ... pourquoi ? Une réponse possible: le module `pam_sss` ne prend pas en compte l'option PAM classique `minimum_uid` comme le font `pam_krb5` et `pam_ccreds`, il utilise pour faire la même chose une propriéte `min_id` à définir dans le fichier de configuration `sssd.conf`. Comme la règle d'exclusion n'est pas explicitement dans la configuration PAM, ca pourrait expliquer le choix d'une priorité inférieure. => chercher dans le bugtracker ? On dirait vraiment que `pam_sss` est conçu et configuré pour des utilisateurs qui sont enregistrés dans un LDAP et pas en local (dans ce cas ça marche direct). Moi je veux bien, c'est parfait pour un poste fixe qui est toujours connecté au réseau, mais que se passe-t'il avec un laptop déconnecté, si on n'a pas de mot de passe local ? On pourrait envisager de désactiver le profil `pam_unix`, comme cela il ne reste que `pam_sss` et le problème disparait, mais je soupçonne qu'il va y avoir des effets de bord ;-) Pour passer `pam_sss` en premier, il faut augmenter sa priorité. On peut faire cela en modifiant le fichier `/usr/share/pam-configs/sss` à la volée depuis le `postinst` avec `sed`, mais c'est très moche, et cela ne résiste pas à une mise à jour du paquet `libpam-sss`, il faudrait mettre en place un `trigger` ou mieux encore un `divert` ... ça reste du bricolage. Autre solution, plus propre: - ajouter un fichier `/usr/share/pam-configs/yourdev`, copie de `sss` - modifier sa propriété `Name` et augmenter la valeur de `Priority` - rajouter une propriété `Conflicts: sss` - dans le `postinst`, activer `yourdev` et désactiver `sss` Important: ne pas utiliser --force dans les scripts, seulement --package Important: bien verifier uid >= 1000 et users interdits. Note: les deux profils `sss` et `yourdev` sont en conflit, mais leur propriété `Default` vaut `yes`, ce qui a une conséquence particulière : quand on lance `pam-auth-update` une première fois en mode interactif, sans avoir exécuté la configuration automatique via le `postinst`, alors les deux profils sont sélectionnés dans le dialogue `debconf`. Si on valide à ce moment, le dialogue se plaint qu'il y a conflit, et refuse de valider la sélection. Il faut modifier et choisir l'un ou l'autre. Ensuite, le dialogue se souvient du choix qui a été fait. Changement de mot de passe -------------------------- Avec le module `pam_sss` en premier, on a le comportement attendu, c'est SSSD qui fait l'authentification et fournit un TGT Kerberos à l'ouverture de session. Mais c'est aussi SSSD qui gère le changement de mot de passe, avec des conséquences imprévues: - c'est le mot de passe réseau qui est changé via la commande `passwd`, pas le mot de passe local, et celui-ci est pénible à modifier, voir plus bas. - sur le réseau, le mot de passe AD est changé, mais pas le mot de passe du Gassi, les deux bases ne sont pas synchronisées, changer l'une ne modifie pas l'autre, le nouveau mot de passe sera requis pour Kerberos, IMAP, SMTP, SMB, etc. mais ne fonctionnera pas pour tous les sites en SSO derrière le Gassi qui utilise toujours l'ancien ... Commandes pour modifier le mot de passe local alors que SSSD est utilisé: ``` $ sudo pam-auth-update --remove yourdev $ passwd $ sudo pam-auth-update --enable yourdev ``` Tout ceci est très pénible... une méthode simple de résoudre le problème serait d'empêcher la modification du mot de passe réseau depuis l'hôte, puisque de toute façon cela ne fonctionne pas complètement (cf la synchronisation AD/Gassi). Pour désactiver la fonctionnalité "changement de mot de passe" pour le module `pam_sss` depuis `pam-configs`, il suffit d'éditer la configuration, puis supprimer toute la section concernée (propriétés `Password-Type`, `Password` et `Password-Initial`), et relancer la commande `pam-auth-update`. La section à supprimer dans `/usr/share/pam-configs/yourdev`: ``` Password-Type: Primary Password: sufficient pam_sss.so use_authtok Password-Initial: sufficient pam_sss.so ``` Après génération, on constate qu'il n'y a plus aucune mention du module `pam_sss` dans le profil `/etc/pam.d/common-passwd`. A partir de là, pour changer le mot de passe local, il suffit d'utiliser la commande classique `passwd` comme ceci: ``` $ passwd Changement du mot de passe pour pipo1234. Mot de passe actuel : Nouveau mot de passe : Retapez le nouveau mot de passe : passwd : le mot de passe a été mis à jour avec succès ``` Le "mot de passe actuel" est bien entendu le mot de passe _local_ courant, puisque la commande ne pourra invoquer que le module `pam_unix`. Il est toujours possible de changer le mot de passe réseau avec la commande `kpasswd` du paquet `krb5-user` qui discute en direct avec le serveur Kerberos, sans passer par la configuration PAM ou le démon SSSD, mais cela n'est pas conseillé. Pour plus de "sécurité", afin d'éviter les fausses manoeuvres et une desynchronisation accidentelle des mots de passes AD et Gassi, on peut désactiver le changement de mot de passe par SSSD en rajoutant la propriété `chpass_provider = none` pour chaque domaine dans `sssd.conf`. Une fois ce réglage en place, les tentatives de modification du mot de passe réseau par SSSD vont échouer systématiquement avec une "erreur système" lors de l'authentification préalable. On conseille de synchroniser le mot de passe local avec le mot de passe réseau, pour éviter les surprises lorsque le serveur d'authentification n'est pas joignable. Pour changer le mot de passe, la procédure se décompose en deux étapes: 1. changer le mot de passe réseau sur [Mot de passe attitude] 2. changer le mot de passe local avec `passwd` Reste à faire ------------- Il doit bien y avoir une raison explicite pour que `pam_sss` ne soit pas prioritaire dans la configuration par défaut Debian/Ubuntu, la "réponse possible" ci-dessus n'est qu'une supposition de ma part, tant que je n'aurais pas trouvé l'explication dans une documenation officielle il restera un doute sur la méthode ci-dessus. Références ---------- - [pam.conf(5)] - [pam-auth-update(8)] - [PAMConfigFrameworkSpec] [PAMConfigFrameworkSpec]: https://wiki.ubuntu.com/PAMConfigFrameworkSpec [pam.conf(5)]: https://manpages.debian.org/bullseye/libpam-runtime/pam.conf.5.en.html [pam-auth-update(8)]: https://manpages.debian.org/bullseye/libpam-runtime/pam-auth-update.8.en.html [Mot de passe attitude]: https://mpa.itn.ftgroup/QPM/User/