L’authentificateur affiche un nouveau code à six chiffres, le VPN le rejette, et le même code se vérifie parfaitement lorsque vous le testez depuis votre propre shell. Cet écart est toute l’histoire. Un module PAM qui ne peut pas ouvrir le secret d’enrôlement renvoie un échec qui ressemble à s’y méprendre à un code erroné, et l’environnement de service qui masque les répertoires personnels en est une cause fréquente. Avant d’assouplir une quelconque permission, déterminez dans laquelle des trois situations vous vous trouvez.

Laquelle des trois défaillances est-ce ?

La première est un secret que le module ne peut pas lire du tout. La seconde est un secret qu’il peut lire mais pas mettre à jour. La troisième est un code qui est vraiment faux, généralement à cause d’une dérive d’horloge ou d’une valeur rejouée.

Distinguez-les en lisant le journal du service et le journal d’authentification du système pour une tentative échouée, puis confirmez quel service PAM le greffon charge et quelle ligne de module ce service utilise. Un message générique d’échec d’authentification ne les distingue pas, pas plus qu’un test manuel réussi, car votre shell n’est pas l’environnement du service.

La vue du système de fichiers de l’unité est le coupable habituel lorsque seul le service échoue.

systemctl show -p ProtectHome -p ProtectSystem -p ReadWritePaths [email protected]
ls -l /var/lib/vpn-otp/*/.google_authenticator 2>/dev/null | head -n 20

Option A : sortir le secret du répertoire personnel

Lorsque le service masque /home et que vous préférez conserver cette protection, stockez le secret là où il peut le voir. Le module accepte un chemin secret= et un compte user= qui effectue les opérations de fichiers, ce qui permet à un magasin central de servir de nombreuses identités.

C’est l’option propre, et c’est celle qui demande le plus de soin, car un magasin partagé fait d’un seul répertoire la frontière de sécurité de chaque compte.

auth required pam_google_authenticator.so secret=/var/lib/vpn-otp/${USER}/.google_authenticator user=vpn-otp

Vérifiez trois choses avant de lui faire confiance : le compte existe, le processus de travail du module peut basculer vers lui, et les fichiers lui appartiennent avec des modes restrictifs. N’utilisez pas ~ ni un chemin avec variable personnelle avec user=, et ne désactivez pas les contrôles de propriété du module pour faire fonctionner un chemin. Gardez l’étape du mot de passe et le reste de la pile intacts.

Option B : laisser le fichier et ouvrir un chemin

Si le secret doit rester dans le répertoire personnel de l’utilisateur, l’unité a besoin d’une vue qui inclut ce seul répertoire sans exposer tous les répertoires personnels de l’hôte. Un drop-in peut ajouter un montage lié strictement délimité sous un répertoire personnel isolé.

Cela maintient la propriété par utilisateur comme modèle, au prix d’une modification de l’unité qui doit être revue à chaque changement du bac à sable.

Deux limites sont faciles à manquer. Un chemin en lecture seule ajouté sous un répertoire que le bac à sable masque ne l’expose pas, car le parent n’est tout simplement pas là. Et le montage doit être inscriptible si le module doit mettre à jour l’état, ce qui fait entrer en jeu l’option suivante. Écrivez le drop-in comme un fichier séparé plutôt que de modifier l’unité empaquetée sous /usr/lib, afin qu’une mise à jour du paquet ne l’annule pas silencieusement.

Option C : garder le bac à sable et corriger les écritures d’état

Lire le secret n’est que la moitié de l’authentification. Le module peut réécrire des informations de dérive temporelle, une protection contre le rejeu ou un compteur, et un fichier qui passe le contrôle de lecture peut encore échouer à l’écriture.

Cet échec ressemble à un mauvais code à la tentative suivante plutôt qu’à celle-ci, ce qui le fait confondre avec une dérive d’horloge.

Donnez-lui un répertoire inscriptible qui lui soit propre et dirigez-y le chemin du secret, plutôt que de rendre tout le répertoire personnel inscriptible. Confirmez le propriétaire du répertoire, l’espace libre du système de fichiers et si l’unité restreint les écritures ailleurs. Testez ensuite deux connexions consécutives, car la seconde prouve le chemin d’écriture et la première seulement la lecture.

Vérifiez en tant que service, pas en tant que vous

Chaque contrôle important doit s’exécuter dans le bac à sable de l’unité avec l’identité de l’unité.

Une commande qui réussit en root vous dit que le fichier existe, et rien de plus. Une connexion par le service réel vous dit si le module peut lire le secret, l’utiliser et réécrire ce dont il a besoin.

Enfin, gardez l’exigence intacte. Ajouter une option de mot de passe nul, accepter les échecs en lecture seule ou supprimer le bac à sable feraient tous disparaître le symptôme en changeant la politique. Un utilisateur tenu de présenter un code doit toujours être rejeté lorsque le secret est inaccessible.

Articles similaires