Linux Embedded

Le blog des technologies libres et embarquées

Authentification avec PAM sous Linux

Introduction

PAM est un mécanisme qui gère les tâches d'authentification des applications sous Linux, en utilisant un ensemble de bibliothèques dynamiques et de fichiers de configuration. Il a été créé par Sun Microsystems en 1995 dans le but de rendre les applications indépendantes de la méthode d'authentification, et a été implémenté par Red Hat (voir [1]) en 1996 dans sa version 3.0.4 (selon [2]).

Les nombreux avantages qu'il procure lui ont permis de s'imposer rapidement dans le monde Linux, et font de lui un outil incontournable d'authentification et d'accès, utilisable aussi bien sur les serveurs et postes de travail que dans le monde de l'embarqué. Il présente également l'incomparable avantage d'être disponible en Open Source : son code est déposé sur github ([3]).

1. Objectifs de PAM

Les objectifs de PAM sont en fait multiples et variés, en voici quelques-uns :

  • permettre de modifier la méthode d'authentification et d'accès sans avoir besoin de recompiler le code de l'application,
  • pouvoir définir des plages horaires auxquelles les connexions sont autorisées ou interdites,
  • pouvoir définir les lieux (TTY, réseau, machine, etc.) depuis lesquels des utilisateurs sont autorisés à se connecter, ou au contraire depuis lesquels ils n'ont pas le droit de se connecter,
  • pouvoir authentifier les utilisateurs par des moyens différents des habituels mots de passe, tels que, par exemple, des cartes à puce, des clés SSH, ou des mesures biométriques (empreinte digitale, réseau veineux, reconnaissance de l'iris, empreinte palmaire, reconnaissance faciale, reconnaissance comportementale, etc.),
  • pouvoir gérer les utilisateurs en utilisant un annuaire LDAP (éventuellement connecté à un serveur ActiveDirectory) au lieu des classiques fichiers /etc/passwd et /etc/shadow,
  • pouvoir gérer des autorisations ou interdictions de connexion, individuelles ou par groupes,
  • utiliser une méthode d'authentification forte et robuste telle que Kerberos,
  • etc.

Le but de PAM est de permettre une grande souplesse dans les mécanismes d'authentification et d'autorisation d'accès aux systèmes, souplesse dont on ne disposait pas avec le mécanisme d'authentification basé sur le fichier /etc/passwd originel.

2. Principe de fonctionnement

Afin de pouvoir modifier les méthodes d'authentification et les autorisations d'accès sans modifier la moindre ligne de code des applications utilisant PAM (donc sans nécessiter une recompilation), il est nécessaire de rendre les actions dynamiques, et notamment d'utiliser des bibliothèques dynamiques. Les configurations PAM sont donc constituées d'un ensemble de directives permettant l'utilisation de bibliothèques dynamiques (.so), possédant des interfaces standardisées.

Avant d'autoriser l'accès à un utilisateur, il faut être capable de l'authentifier, mais également de vérifier que les conditions de son accès sont remplies. En effet, même si un utilisateur est autorisé à se connecter à une machine, il faut parfois aussi vérifier que l'horaire auquel il demande une autorisation est bien celui auquel il est censé se connecter, que le terminal à partir duquel il se connecte est bien un terminal autorisé (l'usage de la console système ou de certains TTY pouvant être limité à quelques utilisateurs particuliers), ou que son mot de passe  n'a pas expiré.

Une fois l'utilisateur autorisé à se connecter, il faut parfois lui configurer un environnement de travail particulier, et aussi lui autoriser ou non à modifier ses attributs d'authentification en contrôlant leur légitimité (vérifier la robustesse du mot de passe, par exemple).

Pour toutes ces actions (authentification, gestion du compte, gestion de la session et gestion des mots de passe), PAM permet une grande souplesse grâce à des configurations par application qui décrivent et implémentent des suites de contrôles, tant pour l'authentification que pour la gestion des comptes et des sessions. Et pour toutes les actions que les modules standard ne savent pas gérer, PAM fournit des fonctions en bibliothèque et des interfaces qui permettent de développer les modules nécessaires.
La bibliothèque de fonctions à utiliser pour développer les applications est décrite dans la page de manuel pam(3), et est localisée, sur Debian 12, dans le fichier /usr/lib/x86_64-linux-gnu/libpam.so .

Les mécanismes mis en jeu dans l'utilisation de PAM sont les suivants : un processus souhaitant utiliser une configuration PAM va demander à PAM l'utilisation de ses services en exécutant la fonction pam_start() à laquelle il va passer le nom de la configuration choisie. En cas de succès de cet appel, le processus va pouvoir utiliser les fonctions que PAM met à disposition des applications pour interagir avec les différents types de gestion que nous verrons dans la suite de cet article (authentication, account, session, password). Ces fonctions permettent l'exécution, sous le contrôle de PAM, de leur équivalent du côté des modules pour la configuration spécifiée.

La fonction pam_authenticate(), par exemple, va pouvoir exécuter les fonctions pam_sm_authenticate() des différents modules PAM listés dans la configuration.

Il en est de même pour la fonction pam_acct_mgmt() (gestion des comptes) qui va pouvoir, via PAM, exécuter les fonctions pam_sm_acct_mgmt() des différents modules de la configuration, et ainsi de suite pour les autres fonctions de gestion.

Le code des modules est, grâce à PAM, linké dynamiquement au processus utilisateur (grâce à la fonction dlopen()), et son exécution est orchestrée par le code de PAM en fonction des directives contenues dans les fichiers de configuration (/etc/pam.conf ou /etc/pam.d/*).

La documentation des interfaces permettant de développer les modules et les applications les utilisant est donnée sous la forme d'une liste de pages de manuel au paragraphe 11.2.1 (Fonctions).

3. Fichiers de configuration

Lorsque l'on parle de fichiers de configuration, il est nécessaire de bien comprendre de quoi l'on parle. Il faut distinguer les fichiers de configuration des applications utilisant PAM et les fichiers de configuration des modules utilisés par PAM.

3.1. Liste des fichiers de configuration des applications

La configuration des applications utilisant PAM se trouve dans le fichier /etc/pam.conf, mais si le répertoire /etc/pam.d est présent, cette configuration est ignorée et remplacée par celle se trouvant dans les fichiers de ce répertoire. C'est le cas le plus répandu car il permet une configuration modulaire, bien plus facile à gérer qu'avec un fichier monolithique.

Par exemple, la configuration de sshd se trouve dans le fichier /etc/pam.d/sshd. Ce fichier contient, entre autre, des références aux modules pam_nologin.so, pam_loginuid.so et pam_limits.so, pour ne citer que ceux-là. 
Il est spécifié dans la page PAM(7) que les configurations fournies par les revendeurs de solutions doivent se trouver dans le répertoire /usr/lib/pam.d ou tout autre répertoire de configuration spécifié par le revendeur, et que toute configuration située dans le répertoire /etc/pam.d remplace une configuration de même nom (basename) située dans les autres répertoires.

3.2. Liste des fichiers de configuration des modules PAM

Certains modules PAM disposent de leur propre configuration. C'est le cas, entre autres, des modules pam_access.so, pam_limits.so, et pam_time.so. Les fichiers de configuration des modules sont situés dans le répertoire /etc/security.

La syntaxe des fichiers de configuration des modules PAM est en général spécifique à chaque module, elle n'est pas générique ni commune à un ensemble de modules.

Si nous prenons le cas du module pam_access.so, décrit dans la page de manuel pam_access(8), la syntaxe de son fichier de configuration est décrite dans la page de manuel access.conf(5) ainsi que dans le fichier /etc/security/access.conf lui-même. Les fichiers de configuration contiennent généralement une section de commentaires reprenant la description de la syntaxe du fichier en question.

Les fichiers de configuration situés dans /etc/security sont les suivants :

/etc/security/access.conf
/etc/security/faillock.conf
/etc/security/group.conf
/etc/security/limits.conf
/etc/security/namespace.conf
/etc/security/pam_env.conf
/etc/security/pwquality.conf
/etc/security/sepermit.conf
/etc/security/time.conf
/etc/security/user_map.conf

Cependant, certains modules possèdent également leur configuration éclatée en utilisant un répertoire contenant potentiellement une multitude de fichiers, comme par exemple pam_limits.so avec /etc/security/limits.conf ou /etc/security/limits.d/* , et pam_namespace.so avec /etc/security/namespace.conf ou /etc/security/namespace.d/* .

Configurer un module spécifique nécessite de lire la documentation du module en question, la documentation générique du fonctionnement de PAM ne décrivant pas les spécificités des différents modules.

3.3. Syntaxe des fichiers de configuration des applications

La syntaxe des fichiers de configuration des applications utilisant PAM est décrite dans la page de manuel pam.conf(5). Nous n'allons, dans cet article, en faire qu'une description rapide. Pour une description complète, veuillez vous référer à la page de manuel.

Dans le cas du fichier /etc/pam.conf, la syntaxe des lignes est la suivante :

service type control module-path module-arguments

Les trois premiers arguments de chaque ligne ne sont pas sensibles à la casse (case-insensitive). 
Le fichier pam.conf étant généralement abandonné au profit d'une multitude de fichiers de configuration dans /etc/pam.d, nous examinerons plus spécifiquement la syntaxe de ces derniers fichiers. Ce qui les distingue du fichier pam.conf est que le nom du service y est absent puisqu'il correspond au nom court (basename) du fichier de configuration. La syntaxe des lignes est donc réduite à :

type control module-path module-arguments

Le champ type permet de spécifier l'un des quatre groupes de gestion indépendants :

  • authentication : l'authentification proprement dite,
  • account : la gestion du compte utilisateur,
  • session : la gestion du service utilisateur,
  • password : la gestion des mécanismes permettant l'authentification.

Des lignes contenues dans les fichiers de configuration, on peut extraire des piles de modules pour chacun des types : une pile authentication, une pile account, etc. Les éléments de ces piles sont fréquemment entrelacés dans les fichiers de configuration. Lorsque que le terme pile sera utilisé dans la suite, il désignera une pile de modules d'un même type.

Le champ control peut prendre les valeurs suivantes :

  • required : une erreur d'un module portant cet attribut aura pour effet de retourner une erreur, mais uniquement après que les autres modules de la pile ont été invoqués,
  • requisite : cet attribut a le même fonction que l'attribut required mais son effet est immédiat,
  • sufficient : si aucun module possédant l'attribut required n'a retourné d'erreur, le succès d'un module possédant l'attribut sufficient provoquera le retour avec un code de succès sans autre invocation de modules dans la pile,
  • optional : le succès ou l'échec sur un module possédant cet attribut n'est important que dans le cas où il est le seul de la pile,
  • include : a pour effet d'inclure toutes les lignes de même type depuis la configuration spécifiée en argument,
  • substack : identique à include, mais les actions done et die de la sous-pile ne provoquent pas l'arrêt de l'évaluation de la pile complète des modules, mais uniquement de ceux définis dans la sous-pile.

Il existe une autre syntaxe plus compliquée au format :

[value1=action1 value2=action2 ...]

mais sa description serait trop longue pour cet article. Reportez-vous à la page de manuel pour en comprendre les détails.

Le champ module-path contient le nom court (basename) du module, soit par exemple pam_limits.so .

Le champ module-arguments contient une liste, éventuellement vide, d'arguments qui seront passés au module lors de son appel.

4. Interface proposée par PAM

L'interface de programmation proposée par PAM est décrite dans la page de manuel pam(3). Il s'agit d'une bibliothèque de fonctions utilisant les fichiers d'en-tête suivants :

<security/pam_appl.h>
<security/pam_modules.h>
<security/pam_ext.h>

Voici ci-après, une brève synthèse (incomplète) de ce que l'on trouve dans la page de manuel. Pour une utilisation effective de ces fonctions, veuillez vous référer à la documentation de référence.

Ces fonctions sont classées en plusieurs groupes :

4.1. Initialisation et terminaison.

La fonction pam_start() alloue et initialise un contexte de transaction. Il est nécessaire de l'appeler avant toute autre interaction avec PAM.

A l'inverse, la fonction pam_end() termine la transaction.

4.2. Authentification.

La fonction pam_authenticate() sert à authentifier un utilisateur.

La fonction pam_setcred() sert à gérer les informations d'identification d'un utilisateur.

4.3. Gestion de compte.

La fonction pam_acct_mgmt() sert à déterminer si le compte de l'utilisateur est valide. Elle est appelée après que l'utilisateur a été authentifié.

4.4. Gestion de mot de passe.

La fonction pam_chauthtok() sert à modifier le jeton d'authentification de l'utilisateur, sur demande ou suite à une expiration.

4.5. Gestion de session.

La fonction pam_open_session() initialise une session pour un utilisateur préalablement authentifié.

La fonction pam_close_session() sert à terminer la session ouverte par pam_open_session().

4.6. Conversation.

La bibliothèque PAM permet la communication directe entre un module et l'application. Cette communication est effectuée par l'intermédiaire d'un callback spécifié par la structure pam_conv (voir pam_conv(3)). Ce callback est spécifié lors de l'appel de la fonction pam_start(), au début de la transaction.

4.7. Manipulation de données.

Les fonctions pam_set_item() et pam_get_item() servent aux applications et aux modules PAM à définir et à récupérer des données.

La fonction pam_get_user() sert à obtenir le nom de l'utilisateur.

Les fonctions pam_set_data() et pam_get_data() permettent aux modules PAM de définir et récupérer des données d'une invocation à une autre.

4.8. Environnement et gestion d'erreurs.

Les fonctions pam_putenv(), pam_getenv() et pam_getenvlist() servent à gérer un jeu de variables d'environnement privées.

La fonction pam_strerror() retourne un pointeur vers une chaîne de caractères donnant la signification d'un code d'erreur PAM.

 

Toutes les fonctions citées précédemment peuvent être utilisées par les applications souhaitant interagir avec PAM, en fonction du besoin. Chacune d'entre elles possède sa propre page de manuel, incluant son usage, son prototype et ses codes retours possibles.

5. Modules PAM

5.1. Liste de modules PAM

Sur un système Debian 12, les modules PAM sont localisés dans le répertoire /lib/x86_64-linux-gnu/security . Voici un exemple des fichiers que l'on peut trouver dans ce répertoire :

pam_access.so     pam_gnome_keyring.so  pam_mkhomedir.so  pam_sepermit.so    pam_unix.so
pam_debug.so      pam_group.so          pam_motd.so       pam_setquota.so    pam_user_map.so
pam_echo.so       pam_keyinit.so        pam_nologin.so    pam_stress.so      pam_usertype.so
pam_env.so        pam_lastlog.so        pam_permit.so     pam_succeed_if.so  pam_warn.so
pam_exec.so       pam_limits.so         pam_pwhistory.so  pam_systemd.so     pam_wheel.so
pam_faildelay.so  pam_listfile.so       pam_rhosts.so     pam_time.so        pam_xauth.so
pam_faillock.so   pam_localuser.so      pam_rootok.so     pam_timestamp.so
pam_filter.so     pam_loginuid.so       pam_securetty.so  pam_tty_audit.so
pam_ftp.so        pam_mail.so           pam_selinux.so    pam_umask.so

5.2. Documentation des modules

On peut connaître la fonction et l'usage des modules à l'aide de la commande man, comme par exemple pour le module pam_faillock.so :

$ man pam_faillock
PAM_FAILLOCK(8)                       Linux-PAM Manual                      PAM_FAILLOCK(8)
NAME
       pam_faillock - Module counting authentication failures during a specified interval
SYNOPSIS
       auth ... pam_faillock.so {preauth|authfail|authsucc} [conf=/path/to/config-file]
                                [dir=/path/to/tally-directory] [even_deny_root] [deny=n]
                                [fail_interval=n] [unlock_time=n] [root_unlock_time=n]
                                [admin_group=name] [audit] [silent] [no_log_info]
       account ... pam_faillock.so [dir=/path/to/tally-directory] [no_log_info]
[...]

Les pages de manuel des modules sont situées dans la section 8 (voir paragraphe 11.2.4 ci-dessous).

5.3. Fonctions contenues dans les modules PAM

On peut lister les fonctions d'un module PAM (c'est-à-dire d'une bibliothèque dynamique) avec différentes commandes. Par exemple avec nm :

    # nm -D pam_unix.so | grep '\<T\>'
    0000000000002bb0 T pam_sm_acct_mgmt
    0000000000002e70 T pam_sm_authenticate
    0000000000003680 T pam_sm_chauthtok
    0000000000004260 T pam_sm_close_session
    00000000000040c0 T pam_sm_open_session
    00000000000030f0 T pam_sm_setcred

ou avec objdump (en cherchant un affichant équivalent) :

    # objdump -T pam_unix.so | awk '$3 ~ /F/ && $4 == ".text" { printf "%s T %s\n", $1, $7 }'
    0000000000002bb0 T pam_sm_acct_mgmt
    0000000000002e70 T pam_sm_authenticate
    0000000000004260 T pam_sm_close_session
    00000000000030f0 T pam_sm_setcred
    0000000000003680 T pam_sm_chauthtok
    00000000000040c0 T pam_sm_open_session

ou avec readelf (toujours en cherchant un affichant équivalent) :

    # readelf -Ws pam_unix.so | awk '$4 == "FUNC" && $7 != "UND" { printf "%s T %s\n", $2, $8 }'
    0000000000002bb0 T pam_sm_acct_mgmt
    0000000000002e70 T pam_sm_authenticate
    0000000000004260 T pam_sm_close_session
    00000000000030f0 T pam_sm_setcred
    0000000000003680 T pam_sm_chauthtok
    00000000000040c0 T pam_sm_open_session

6. Commandes utilisant PAM

Pour savoir si une commande utilise PAM, il suffit de regarder si une librairie PAM dynamique figure dans les bibliothèques référencées par la commande en question. Prenons, par exemple, le cas de la commande /usr/bin/login :

# ldd /usr/bin/login | grep pam
	libpam.so.0 => /lib/x86_64-linux-gnu/libpam.so.0 (0x00007fe770e46000)
	libpam_misc.so.0 => /lib/x86_64-linux-gnu/libpam_misc.so.0 (0x00007fe770e41000)

Deux bibliothèques PAM sont présentes dans la liste : la commande login utilise bien PAM.

On peut effectuer, à titre d'information, ce type de recherche pour les commandes des répertoires /usr/bin et /usr/sbin.

6.1. Commandes de /usr/bin utilisant PAM

Sous Debian 12, voici une liste de commandes (hors systemd-*) de /usr/bin utilisant PAM :

/usr/bin/busctl
/usr/bin/chfn
/usr/bin/chsh
/usr/bin/hostnamectl
/usr/bin/journalctl
/usr/bin/localectl
/usr/bin/login
/usr/bin/loginctl
/usr/bin/machinectl
/usr/bin/networkctl
/usr/bin/passwd
/usr/bin/pkexec
/usr/bin/portablectl
/usr/bin/su
/usr/bin/timedatectl

Certaines d'entre elles auraient pu être citées sans que l'on ait besoin de faire cette recherche : c'est le cas pour login, passwd, su, mais pour les autres, ce n'était pas forcément évident.

6.2. Commandes de /usr/sbin utilisant PAM

Le même type de recherche pour /usr/sbin, toujours sous Debian 12, donne la liste suivante, potentiellement non-exhaustive en fonction des packages installés sur la machine :

/usr/sbin/chpasswd
/usr/sbin/cron
/usr/sbin/cupsd
/usr/sbin/faillock
/usr/sbin/groupmems
/usr/sbin/init
/usr/sbin/ippeveprinter
/usr/sbin/lightdm
/usr/sbin/mkhomedir_helper
/usr/sbin/newusers
/usr/sbin/pam_timestamp_check
/usr/sbin/pppd
/usr/sbin/runuser
/usr/sbin/sshd

On reconnait, entre autres, cupsd (le daemon d'impression), init (désormais systemd, sur la plupart des distributions), sshd (le démon SSH), et lightdm qui gère les affichages graphiques.

7. Objectifs des fonctions de PAM

Voici, ci-dessous, un récapitulatif des objectifs des fonctions proposées par PAM. Ces informations sont extraites des pages de manuel de la section 3.

pam_acct_mgmt            PAM account validation management
pam_authenticate         Account authentication
pam_chauthtok            Updating authentication tokens
pam_close_session        Terminate PAM session management
pam_conv                 PAM conversation function
pam_end                  Termination of PAM transaction
pam_error                Display error messages to the user
pam_verror               Display error messages to the user
pam_fail_delay           Request a delay on failure
pam_get_authtok          Get authentication token
pam_get_authtok_verify   Get authentication token
pam_get_authtok_noverify Get authentication token
pam_get_data             Get module internal data
pam_getenv               Get a PAM environment variable
pam_getenvlist           Getting the PAM environment
pam_get_item             Getting PAM information
pam_get_user             Get user name
pam_info                 Display messages to the user
pam_vinfo                Display messages to the user
pam_misc_drop_env        Liberating a locally saved environment
pam_misc_paste_env       Transcribing an environment to that of PAM
pam_misc_setenv          BSD like PAM environment variable setting
pam_open_session         Start PAM session management
pam_prompt               Interface to conversation function
pam_vprompt              Interface to conversation function
pam_putenv               Set or change PAM environment variable
pam_setcred              Establish / delete user credentials
pam_set_data             Set module internal data
pam_set_item             Set and update PAM information
pam_sm_acct_mgmt         PAM service function for account management
pam_sm_authenticate      PAM service function for user authentication
pam_sm_chauthtok         PAM service function for authentication token management
pam_sm_close_session     PAM service function to terminate session management
pam_sm_open_session      PAM service function to start session management
pam_sm_setcred           PAM service function to alter credentials
pam_start                Initialization of PAM transaction
pam_start_confdir        Initialization of PAM transaction
pam_strerror             Return string describing PAM error code
pam_syslog               Send messages to the system logger
pam_vsyslog              Send messages to the system logger
pam_xauth_data           Structure containing X authentication data

8. Création de modules de test

8.1. Installation de packages

Avant de pouvoir créer des modules de tests, nous allons  installer un package permettant de faire du développement en utilisant PAM : ce package a pour nom libpam0g-dev. On l'installe de la façon suivante :

    # apt-get install libpam0g-dev

Une fois le package installé, la commande dpkg reporte les informations suivantes :

    # dpkg -l libpam0g-dev
    [..]
    ||/ Name               Version         Architecture Description
    +++-==================-===============-============-=========================
    ii  libpam0g-dev:amd64 1.5.2-6+deb12u1 amd64        Development files for PAM

Ce package contient :

  • les fichiers d'en-tête,
  • les bibliothèques statiques et dynamiques,
  • les exemples de codes,
  • les pages de manuel de la section 3 décrivant l'interface de programmation.

8.2. Module d'authentification

Le premier module de test que nous allons créer va permettre l'authentification d'un utilisateur, quel qu'il soit, par la simple comparaison du mot de passe fourni par l'utilisateur avec un mot de passe en clair se trouvant dans un fichier. Bien évidemment, ce module ne doit être utilisé qu'à des fins de tests, et en aucun cas sur un serveur sécurisé. Le code est donné ici uniquement dans un but pédagogique, et il serait irresponsable de le déposer sur un serveur sensible.

Le module doit être un module de type auth, et donc comporter une fonction pam_sm_authenticate().

Voici un code possible de ce module :

#define _GNU_SOURCE
 
#include <security/pam_modules.h>
#include <security/pam_ext.h>
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
#define PASSWORD_FILE    "/tmp/passwd.demo_pam"
 
#define MAX_PASSWORD_LEN 256
#define AUTH_MODULE_KEY  "pam_demo"
 
static void cleanup_data(pam_handle_t *pamh, void *data, int error_status)
{
     if (data) {
          free(data);
     }
}
 
PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv)
{
     const char     *_password = NULL;
     char            _stored_password[MAX_PASSWORD_LEN] = {0};
     FILE           *_fp;
     int             _retval;
     size_t          _len;
 
     // Lecture du mot de passe utilisateur
     _retval        = pam_get_authtok(pamh, PAM_AUTHTOK, &_password, NULL);
     if (_retval != PAM_SUCCESS || _password == NULL) {
          return PAM_AUTH_ERR;
     }
 
     // Lecture du mot de passe stocke dans le fichier
     _fp            = fopen(PASSWORD_FILE, "r");
     if (_fp == NULL) {
          return PAM_AUTH_ERR;
     }
 
     if (fgets(_stored_password, sizeof(_stored_password), _fp) == NULL) {
          fclose(_fp);
          return PAM_AUTH_ERR;
     }
     fclose(_fp);
 
     // (Suppression du saut de ligne s'il est present)
     _len           = strlen(_stored_password);
     if (_len > 0 && _stored_password[_len - 1] == '\n') {
          _stored_password[_len - 1] = '\0';
     }
 
     // Comparaison des mots de passe
     if (!strcmp(_password, _stored_password)) {
          const char *module_name = AUTH_MODULE_KEY;
          // Copie de la chaine
          char *stored_name;
          if ((stored_name = strdup(module_name)) == NULL) {
               return PAM_BUF_ERR;
          }
          int ret = pam_set_data(pamh, AUTH_MODULE_KEY, stored_name, cleanup_data);
          if (ret != PAM_SUCCESS) {
               free(stored_name);
               return ret;
          }
          return PAM_SUCCESS;
     }
     return PAM_AUTH_ERR;
}
 
PAM_EXTERN int pam_sm_setcred(pam_handle_t *pamh, int flags, int argc, const char **argv)
{
     return PAM_SUCCESS;
}

Les règles de Makefile permettant de le compiler sont les suivantes :

pam_demo   : pam_demo.c
             gcc -fPIC -fno-stack-protector -c pam_demo.c -o pam_demo.o
             gcc -shared -o pam_demo.so pam_demo.o

et sa compilation est effectuée tout simplement par la commande :

$ make pam_demo
gcc -fPIC -fno-stack-protector -c pam_demo.c -o pam_demo.o
gcc -shared -o pam_demo.so pam_demo.o

La bibliothèque dynamique ainsi générée (pam_demo.so) doit être déposée dans le répertoire /lib/x86_64-linux-gnu/security par une simple copie, comme par exemple :

# cp pam_demo.so /lib/x86_64-linux-gnu/security

Si l'on veut que cette fonctionnalité soit prise en compte par le démon sshd pour permettre une autorisation par ssh, il faut ajouter les lignes suivantes en tête du fichier de configuration /etc/pam.d/sshd :

# TEST DE PAM
auth sufficient pam_demo.so

Il n'est pas nécessaire de recharger la configuration de sshd : la configuration PAM est lue à chaque nouvelle invocation du service PAM liée à une tentative de connexion via SSH.

Une fois le module installé et la configuration effectuée, il ne reste plus qu'à mettre le mot de passe dans le fichier connu du module, à savoir /tmp/passwd.demo_pam . Si l'on place dans ce fichier la chaîne abcd1234, tout utilisateur existant se connectant via ssh pourra désormais être authentifié en utilisant le mot de passe abcd1234. Il est évident que ce genre de configuration doit être uniquement utilisée dans un environnement de tests (idéalement une machine virtuelle).
Si l'on souhaite disposer de cette fonctionnalité pour les connexions sur les terminaux (TTY), il faut ajouter les lignes suivantes dans le fichier /etc/pam.d/login :

# TEST DE PAM
auth sufficient pam_demo.so

De même, si l'on souhaite bénéficier de cette fonctionnalité dans la commande su, il suffit d'ajouter cette même ligne de configuration dans le fichier /etc/pam.d/su.

Aucune des commandes ssh (ou plutôt sshd), login et su n'a été modifiée, mais nous leur avons pourtant ajouté, grâce à PAM, un nouveau moyen d'authentification. Il est évident qu'un cas réel d'authentification consisterait plutôt à gérer une authentification par carte à puce ou par une mesure biométrique, et non une authentification de tous les utilisateurs par un mot de passe unique qui constitue une importante faille de sécurité. Mais, cela dit, le principe reste le même.

8.3. Module de gestion de compte

Nous allons maintenant prendre deux exemples de modules de gestion de compte (account) correpondant à deux contraintes spécifiques :

  1. une limitation liée au nombre de connexions par utilisateur,
  2. une limitation liée à la période de connexion.

8.3.1. Limitation du nombre de connexions par utilisateur

Commençons par la limitation du nombre de connexions par utilisateur, avec le programme pam_limitconn.c suivant :

#include <security/pam_modules.h>
#include <security/pam_ext.h>
#include <security/pam_appl.h>
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <syslog.h>
#include <utmp.h>
 
#define MAX_SESSIONS 3
 
int count_user_sessions(const char *username) {
    struct utmp entry;
    FILE *utmp_file;
    int count = 0;
    if (username == NULL || *username == '\0') {
        return -1;
    }
    utmp_file = fopen(_PATH_UTMP, "rb");
    if (!utmp_file) {
        return -1;
    }
    while (fread(&entry, sizeof(entry), 1, utmp_file) == 1) {
        if (entry.ut_type == USER_PROCESS) {
            char userbuf[UT_NAMESIZE + 1];
            memcpy(userbuf, entry.ut_user, UT_NAMESIZE);
            userbuf[UT_NAMESIZE] = '\0';
            if (strcmp(userbuf, username) == 0) {
                count++;
            }
        }
    }
    fclose(utmp_file);
    return count;
}
 
PAM_EXTERN int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, int argc, const char **argv) {
    const char *user;
    int ret = pam_get_user(pamh, &user, "Utilisateur: ");
    if (ret != PAM_SUCCESS || !user) return PAM_AUTH_ERR;
    int sessions = count_user_sessions(user);
    if (sessions < 0) {
        pam_error(pamh, "Impossible de vérifier le nombre de connexions");
        return PAM_AUTH_ERR;
    }
    if (sessions >= MAX_SESSIONS) {
        pam_syslog(pamh, LOG_NOTICE,
	              "Connexion refusee pour l'utilisateur %s : limite maximale de %d connexions atteinte",
			    user, MAX_SESSIONS);
        pam_error(pamh, "Limite maximale de connexions (%d) atteinte", MAX_SESSIONS);
        return PAM_PERM_DENIED;
    }
    return PAM_SUCCESS;
}
 
PAM_EXTERN int pam_sm_setcred(pam_handle_t *pamh, int flags, int argc, const char **argv) {
    return PAM_SUCCESS;
}

Les règles de Makefile permettant de le compiler sont les suivantes :

pam_limitconn : pam_limitconn.c
                gcc -fPIC -fno-stack-protector -c pam_limitconn.c -o pam_limitconn.o
                gcc -shared -o pam_limitconn.so pam_limitconn.o

et sa compilation est effectuée tout simplement par la commande :

$ make
gcc -fPIC -fno-stack-protector -c pam_limitconn.c -o pam_limitconn.o
gcc -shared -o pam_limitconn.so pam_limitconn.o

Comme précédemment, le module doit être déposé dans le répertoire /lib/x86_64-linux-gnu/security.

Si l'on veut que ce module soit utilisé lors des connexions ssh, on doit placer la directive suivante dans le fichier /etc/pam.d/sshd :

account required pam_limitconn.so

Le principe de ce module est le suivant : la fonction pam_sm_acct_mgmt(), qui est exécutée après que l'utilisateur a été authentifié, appelle la fonction count_user_sessions() (qui retourne le nombre de connexions courantes de l'utilisateur spécifié) afin de vérifier que le nombre maximal de connexions n'est pas atteint. Si ce nombre est inférieur au maximum, elle retourne PAM_SUCCESS et la connexion est autorisée. Mais si l'utilisateur tente de se connecter une 4ème fois, sa demande de connexion échoue (code retour : PAM_PERM_DENIED), et les logs système signalent l'interdiction avec un message du type :

debian12-tests sshd[1752]: pam_limitconn(sshd:account): Connexion refusee pour l'utilisateur mb : limite maximale de 3 connexions atteinte

8.3.2. Limitation par plages horaires

Voyons maintenant un module qui autorise la connexion à certaines plages horaires. Pour faire les tests plus rapidement, nous allons interdire les connexions lorsque le nombre de minutes de l'horloge système est impair, ce qui permettra de faire des tests différents sans trop de temps d'attente.

Nous conserverons, pour ce test, le module d'authentification utilisé au paragraphe 8.2 (pam_demo).

Le programme du module est le suivant :

$ cat pam_even_mn.c
#include <security/pam_modules.h>
#include <security/pam_ext.h>
 
#include <time.h>
#include <syslog.h>
 
#define AUTH_MODULE_KEY  "pam_demo"
 
PAM_EXTERN int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags,
                                int argc, const char **argv)
{
	time_t		 _clock;
	struct tm		*_tm_info;
	int			 _retcode;
	for (int _i = 0; _i < argc; _i++) {
          pam_syslog(pamh, LOG_INFO, "argv[%2d] = \"%s\"\n", _i, argv[_i]);
	}
	const void *data = NULL;
	int ret = pam_get_data(pamh, AUTH_MODULE_KEY, &data);
	if (ret == PAM_SUCCESS && data != NULL) {
		const char *auth_module = (const char *)data;
        
		pam_syslog(pamh, LOG_INFO, "Utilisateur authentifié via le module : %s", auth_module);
		// Pas d'autre controle a effectuer
		_retcode		= PAM_SUCCESS;
	}
	else {
		pam_syslog(pamh, LOG_WARNING, "Aucun module d'authentification enregistré dans le contexte PAM.");
		pam_syslog(pamh, LOG_INFO, "Test de la parite du nombre de minutes\n");
		if ((_clock = time(NULL)) < 0) {
			pam_syslog(pamh, LOG_INFO, "Erreur de lecture de l'horloge\n");
			_retcode		= PAM_SYSTEM_ERR;
		}
		else if ((_tm_info = localtime(&_clock)) == NULL) {
			pam_syslog(pamh, LOG_INFO, "Erreur de conversion de l'horloge\n");
			_retcode		= PAM_SYSTEM_ERR;
		}
		else if (_tm_info->tm_min % 2 == 0) {
			pam_syslog(pamh, LOG_INFO, "Nombre de minutes : pair\n");
			_retcode		= PAM_SUCCESS;
		}
		else {
			pam_syslog(pamh, LOG_INFO, "Nombre de minutes : impair\n");
			_retcode		= PAM_ACCT_EXPIRED;
		}
	}
	pam_syslog(pamh, LOG_INFO, "Code retour de %s() : %d (%s)\n",
	           __func__, _retcode, pam_strerror(pamh, _retcode));
	return _retcode;
}
 
PAM_EXTERN int pam_sm_setcred(pam_handle_t *pamh, int flags,
                              int argc, const char **argv)
{
    return PAM_SUCCESS;
}

Si l'on tente une connexion alors que le nombre de minutes indiqué par l'horloge système est impair, on aura un refus de connexion et on verra dans les logs des messages ressemblant aux suivants :

debian12-tests sshd[1985]: pam_even_mn(sshd:account): Test de la parite du nombre de minutes
debian12-tests sshd[1985]: pam_even_mn(sshd:account): Nombre de minutes : impair
debian12-tests sshd[1985]: pam_even_mn(sshd:account): Code retour de pam_sm_acct_mgmt() : 13  (User account has expired)
debian12-tests sshd[1985]: Failed password for mb from 192.168.122.1 port 59806 ssh2

Ce programme a été donné à titre d'exemple afin de montrer comment il est possible de gérer les autorisations en fonction de certaines plages horaires, mais si vous souhaitez mettre en place une politique de ce type, il est préférable que vous regardiez préalablement les fonctions du module pam_time.so avant de commencer à développer un nouveau module, car ses fonctions seront peut-être suffisantes pour votre besoin. Voici un extrait de la page de manuel de ce module (pam_time(8)) :
The pam_time PAM module does not authenticate the user, but instead it restricts access to a system and or specific applications at various times of the day and on specific days or over various terminal lines.

La configuration du module pam_time.so est localisée dans le fichier /etc/security/time.conf, ou dans un fichier spécifié par le paramètre conffile=conf-file.

9. Création d'une application de test

L'application de test qui suit a pour but de valider l'authentification d'un utilisateur en utilisant la configuration /etc/pam.d/demo suivante :

auth       required      pam_debug.so
auth       optional      pam_show_user.so
auth       required      pam_succeed_if.so user = mb
auth       sufficient    pam_demo.so
auth       required      pam_deny.so
account    required      pam_permit.so

Elle exploite le module pam_demo.so vu précédemment dont le retour PAM_SUCCESS est suffisant pour valider l'authentification. Toutefois, au cas où le mot de passe fourni ne correspondrait pas, il est nécessaire de faire en sorte que l'utilisateur ne soit pas authentifié et que l'accès soit refusé. Or si le module pam_demo.so est le dernier module d'authentification de la configuration (dit autrement : de la pile d'authentification), l'authentification sera validée malgré l'échec de l'exécution de pam_demo.so. Il est donc indispensable d'ajouter la ligne suivante après pam_demo.so :

auth       required      pam_deny.so

Cette ligne  garantit l'échec de connexion en cas de fourniture d'un mot de passe incorrect. En effet, le module pam_deny.so indique toujours un échec d'authentification.

L'application est la suivante :

$ cat pam_test_demo.c
#include <security/pam_appl.h>
#include <security/pam_misc.h>
#include <security/pam_ext.h>
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <syslog.h>
 
static const char *xx_password = NULL;
 
static int xx_conv_func(int _num_msg, const struct pam_message **_msg,
                       struct pam_response **_resp, void *_appdata_ptr)
{
    int _i;
	if (_num_msg <= 0) {
		return PAM_CONV_ERR;
	}
	struct pam_response *_responses = calloc(_num_msg, sizeof(struct pam_response));
	if (_responses == NULL) {
		return PAM_CONV_ERR;
	}
	for (_i = 0; _i < _num_msg; _i++) {
		switch (_msg[_i]->msg_style) {
		case PAM_PROMPT_ECHO_OFF:
		case PAM_PROMPT_ECHO_ON:
			_responses[_i].resp = strdup(xx_password);
			if (_responses[_i].resp == NULL) {
				for (int _j = 0; _j < _i; _j++) {
					free(_responses[_j].resp);
				}
				free(_responses);
				return PAM_CONV_ERR;
			}
			_responses[_i].resp_retcode = 0;
			break;
		case PAM_TEXT_INFO:
		case PAM_ERROR_MSG:
			_responses[_i].resp = NULL;
			_responses[_i].resp_retcode = 0;
			break;
		default:
			free(_responses);
			return PAM_CONV_ERR;
		}
	}
	*_resp = _responses;
	return PAM_SUCCESS;
}
 
int main(int _argc, char **_argv)
{
    pam_handle_t *_pamh = NULL;
    struct pam_conv _conv = { xx_conv_func, NULL };
    const char *_module_name = NULL, *_user_check = NULL, *_username = NULL;
    int _pam_ret;
    if (_argc != 4) {
        fprintf(stderr, "Usage: %s module_name username password\n", _argv[0]);
        return EXIT_FAILURE;
    }
    _module_name		= _argv[1];
    _user_check		= _argv[2];
    xx_password		= _argv[3];
    _conv.appdata_ptr	= NULL;
    _pam_ret = pam_start(_module_name, _user_check, &_conv, &_pamh);
    if (_pam_ret != PAM_SUCCESS) {
        fprintf(stderr, "pam_start() failed: %s\n", pam_strerror(_pamh, _pam_ret));
        return EXIT_FAILURE;
    }
	_pam_ret	= pam_get_item(_pamh, PAM_USER, (const void **) &_username);
    if (_pam_ret == PAM_SUCCESS) {
		pam_syslog(_pamh, LOG_INFO, "pam_get_item(PAM_USER) OK for user '%s' : returned '%s'\n",
		           _user_check, _username);
    }
    else {
        return EXIT_FAILURE;
    }
    _pam_ret = pam_authenticate(_pamh, 0);
    if (_pam_ret != PAM_SUCCESS) {
        fprintf(stderr, "Authentication failed for user '%s': %s\n", _user_check, pam_strerror(_pamh, _pam_ret));
        pam_end(_pamh, _pam_ret);
        return EXIT_FAILURE;
    }
    _pam_ret = pam_acct_mgmt(_pamh, 0);
    if (_pam_ret != PAM_SUCCESS) {
        fprintf(stderr, "Account management failed for user '%s': %s\n", _user_check, pam_strerror(_pamh, _pam_ret));
        pam_end(_pamh, _pam_ret);
        return EXIT_FAILURE;
    }
    printf("Authentication success for user '%s'\n", _user_check);
    pam_end(_pamh, PAM_SUCCESS);
    return EXIT_SUCCESS;
}

L'application est compilée à l'aide de la commande suivante :

$ gcc -o pam_test_demo pam_test_demo.c -lpam

Le nom de la configuration à utiliser (demo) pour l'authentification est passé en premier argument de la commande et correspond à la configuration définie dans /etc/pam.d (/etc/pam.d/demo). La commande peut être testée de la façon suivante :

$ ./pam_test_demo demo mb toto
Authentication failed for user 'mb': Authentication failure

Dans ce premier test, le mot de passe fourni (toto) est incorrect, le résultat est donc un refus de connexion.

$ ./pam_test_demo demo mb abcd1234
Authentication success for user 'mb'

Dans ce deuxième test, le mot de passe fourni est correct, ainsi que le nom de l'utilisateur, donc le résultat conduit à l'acceptation de la connexion.

$ ./pam_test_demo demo lambda abcd1234
Authentication failed for user 'lambda': Authentication failure

Dans ce troisième test, le mot de passe est correct mais l'utilisateur qui tente de se connecter (lambda) n'est pas le bon puisque le module pam_succeed_if.so attend que l'utilisateur qui se connecte soit identifié sous le login mb.

Remarque : Etant donné que le nom de la configuration PAM (fichier dans /etc/pam.d) est un paramètre de la commande pam_test_demo, il vous est possible de tester d'autres configurations sans avoir besoin de modifier ni recompiler l'application.

10. Outils d'aide à la mise au point

Quel que soit le type de développement que l'on effectue, il est toujours agréable de disposer d'outils d'aide à la mise au point ou au diagnostic, car les nouvelles solutions ne fonctionnent pas toujours au premier essai. Dans le cas de PAM, nous disposons de plusieurs moyens qui peuvent nous faciliter l'analyse des problèmes.

Tout d'abord, en restant au niveau de l'administration système, nous pouvons utiliser le module pam_echo.so qui permet d'afficher des messages de traces récupérables à l'aide de la commande journalctl (pour les systèmes disposant de systemd). Ainsi, on peut ajouter des traces dans la configuration d'une application particulière afin de savoir si elle est bien exécutée, et jusqu'à quel module la configuration est exécutée.

La syntaxe de pam_echo est la suivante :

pam_echo.so [file=/path/message]

Dans ce cas, /path/message est le pathname d'un fichier texte dans lequel on peut utiliser des chaînes de format ressemblant à celles de la fonction C printf(), mais qui sont toutefois spécifiques à pam_echo :

  • %H : nom de l'hôte distant (remote hostname)
  • %h : nom de l'hôte local (local hostname)
  • %s : nom du service (service name)
  • %t : terminal de contrôle (controlling terminal)
  • %U : utilisateur distant (remote user)
  • %u : utilisateur local (local user)

Le fichier suivant :

# cat /tmp/message.txt
=======================================
     Test de message par pam_echo
     Rhost     = %H
     host      = %h
     service   = %s
     TTY       = %t
     Ruser     = %U
     user      = %u
=======================================

sera, par exemple, évalué de la façon suivante :

=======================================
     Test de message par pam_echo
     Rhost     = 192.168.122.1
     host      = debian12-tests
     service   = sshd
     TTY       = ssh
     Ruser     = (null)
     user      = mb
=======================================

Pour récupérer les traces système, on pourra utiliser, par exemple, la commande suivante :

# journalctl -o short-iso

(si l'on souhaite avoir des dates au standard ISO 8601).

Si l'on souhaite tracer le fonctionnement interne d'un module, on peut utiliser les fonctions pam_syslog() et pam_vsyslog() qui permettent d'ajouter des messages de trace dans les logs du système. Elles nécessitent l'ajout des directives d'inclusion suivantes :

#include <syslog.h>
#include <security/pam_ext.h>

Leurs prototypes sont les suivants :

void pam_syslog(const pam_handle_t *pamh, int priority, const char *fmt, ...);
void pam_vsyslog(const pam_handle_t *pamh, int priority, const char *fmt, va_list args);

La fonction pam_syslog() s'utilise comme la fonction printf(), et la fonction pam_vsyslog() s'utilise comme la fonction vprintf().

Cela dit, bien que les outils d'aide à la mise au point soient effectivement une aide précieuse, il ne faut pas compter uniquement sur eux pour espérer régler un problème : une relecture attentive permet aussi, bien souvent, de résoudre des problèmes que les outils n'auraient pas pu trouver, comme par exemple une incohérence entre le type de module développé (par exemple de type authentification) et la configuration spécifiée dans le fichier contenu dans /etc/pam.d (par exemple account) : bien contrôler la cohérence de votre configuration avant d'avoir recours aux outils peut vous faire gagner un temps précieux.

11. Documentation

11.1. Documentation HTML

PAM dispose d'une documentation HTML située dans le package libpam-doc, installable par :

# apt-get install libpam-doc

Une fois ce package installé, les fichiers HTML sont disponibles dans le répertoire /usr/share/doc/libpam-doc/html/ .

La documentation du module pam_echo, par exemple, est consultable depuis un navigateur web local avec l'URL file:///usr/share/doc/libpam-doc/html/sag-pam_echo.html .

11.2. Pages de manuel

De façon à vous permettre de naviguer plus facilement dans la documentation de PAM et de localiser plus facilement l'information qui vous intéresse, les noms des pages de manuel disponibles pour PAM ont été, ci-dessous, regroupées par thème : fonctions, configuration, divers, modules et outils.

11.2.1. Fonctions

pam(3)
pam_acct_mgmt(3)
pam_authenticate(3)
pam_chauthtok(3)
pam_close_session(3)
pam_conv(3)
pam_end(3)
pam_error(3)
pam_fail_delay(3)
pam_get_authtok(3)
pam_get_data(3)
pam_get_item(3)
pam_get_user(3)
pam_getenv(3)
pam_getenvlist(3)
pam_info(3)
pam_misc_drop_env(3)
pam_misc_paste_env(3)
pam_misc_setenv(3)
pam_open_session(3)
pam_prompt(3)
pam_putenv(3)
pam_set_data(3)
pam_set_item(3)
pam_setcred(3)
pam_sm_acct_mgmt(3)
pam_sm_authenticate(3)
pam_sm_chauthtok(3)
pam_sm_close_session(3)
pam_sm_open_session(3)
pam_sm_setcred(3)
pam_start(3)
pam_strerror(3)
pam_syslog(3)
pam_xauth_data(3)
misc_conv(3)

11.2.2. Configuration

access.conf(5)
faillock.conf(5)
group.conf(5)
limits.conf(5)
namespace.conf(5)
pam.conf(5)
pam_env.conf(5)
sepermit.conf(5)
time.conf(5)
pam.conf(5)

11.2.3. Divers

PAM(7)
pam_env(7)
pam_selinux(7)

11.2.4. Modules

pam_access(8)
pam_debug(8)
pam_deny(8)
pam_echo(8)
pam_exec(8)
pam_faildelay(8)
pam_faillock(8)
pam_filter(8)
pam_ftp(8)
pam_getenv(8)
pam_group(8)
pam_issue(8)
pam_keyinit(8)
pam_lastlog(8)
pam_limits(8)
pam_listfile(8)
pam_localuser(8)
pam_loginuid(8)
pam_mail(8)
pam_mkhomedir(8)
pam_motd(8)
pam_namespace(8)
pam_namespace_helper(8)
pam_nologin(8)
pam_permit(8)
pam_pwhistory(8)
pam_rhosts(8)
pam_rootok(8)
pam_securetty(8)
pam_sepermit(8)
pam_setquota(8)
pam_shells(8)
pam_stress(8)
pam_succeed_if(8)
pam_systemd(8)
pam_time(8)
pam_timestamp(8)
pam_timestamp_check(8)
pam_tty_audit(8)
pam_umask(8)
pam_unix(8)
pam_userdb(8)
pam_usertype(8)
pam_warn(8)
pam_wheel(8)
pam_xauth(8)

11.2.5. Outils

faillock(8)
mkhomedir_helper(8)
pam_namespace_helper(8)
pam_timestamp_check(8)
pwhistory_helper(8)
unix_chkpwd(8)
unix_update(8)

12. Packages PAM

Voici une liste des packages relatifs à PAM :

libpam-doc
libpam-gnome-keyring
libpam-modules
libpam-modules-bin
libpam-runtime
libpam-systemd
libpam0g
libpam0g-dev

Conclusion

Grâce à PAM, nous avons pu constater la simplicité de la mise en oeuvre de nouveaux moyens d'authentification ou de gestion des comptes utilisateurs. Dès lors que l'application d'authentification utilise PAM, modifier sa configuration est un exercice assez basique. On se rend mieux compte de la puissance de cette solution lorsque l'on commence à réfléchir aux modifications qu'il aurait fallu apporter aux commandes existantes pour leur ajouter de nouvelles fonctionnalités telles que celles qui ont été décrites précédemment.

La modularité des configurations, le fait que l'on puisse, sans modifier la moindre ligne de code, modifier les moyens d'authentification et d'accès, et même développer très simplement de nouveaux modules de gestion font de PAM un outil très puissant dont tout administrateur ou ingénieur système Linux doit connaître et comprendre le fonctionnement. Le but de cet article était de vous aider à atteindre cet objectif, la pratique et les tests achèveront de vous transformer en expert du sujet.

Il faut toutefois rester très vigilant si l'on doit ajouter ou modifier des configurations, car il est relativement facile d'introduire involontairement des failles de sécurité. Dans le doute, faites des tests intensifs ou faites-vous aider par un expert.

Références

[1] "Pluggable Authentication Modules for Linux", Andrew G. Morgan on December 1, 1997, https://www.linuxjournal.com/article/2120

[2] "Pluggable Authentication Module", https://en.wikipedia.org/wiki/Pluggable_Authentication_Module

[3] Code source de PAM sur github, https://github.com/linux-pam/linux-pam

Pour aller plus loin

Maintenant que nous avons constaté que - grâce à PAM - l'authentification d'un utilisateur sous Linux n'est pas limitée à la vérification d'un identifiant et d'un mot de passe, nous allons pouvoir explorer les autres méthodes d'identification / authentification des utilisateurs, notamment celles basées sur la biométrie. 

Pour mettre en place une solution basée sur ces méthodes, il  faudra bien sûr disposer des moyens de reconnaissance adaptés (matériel et logiciel), mais l'intégration dans PAM ne devrait plus constituer un problème pour vous. Cela dit, comme il est ici question  de sécurité, on se doit de rester vigilant et de ne jamais considérer ces solutions, si perfectionnées soient-elles, comme infaillibles. La conférence donnée par Jean-François Mainguet (expert sécurité au CEA / LETI) sur les deepfakes (voir lien ci-dessous) devrait  convaincre que même les toutes nouvelles méthodes biométriques, censées être plus robustes que les mots de passe, ont elles aussi leur faiblesses.

- "Authentification biométrique, les bons côtés, les mauvais côtés et le côté obscur de la Force", https://www.onelogin.com/fr-fr/learn/biometric-authentication

- Biographie de Jean-François Mainguet (inventeur du FingerChip) , https://mainguet.org/jfm/biography.htm

- "PYCSEL, un capteur d’empreinte digitale thermique actif et la détection du vivant", Jean-François MAINGUET", https://gdr-securite.irisa.fr/wp-content/uploads/jn_2019_Mainguet_Jean-Francois.pdf

- "Les deepfakes : un danger pour l’identité ?", https://www.youtube.com/watch?v=lJRERbNj0YU

- "Lecteurs biométriques de la main", https://www.abiova.fr/biometrie_main.html

- Tout savoir sur la biométrie du réseau veineux, https://www.abiova.fr/biometrie_veine.html

- "Révolutionner les Paiements grâce à la Biométrie Palmaire", https://ingenico.com/fr/espace-presse/blogs/mainmise-sur-linnovation-revolutionner-les-paiements-grace-la-biometrie

- "La technologie de reconnaissance de l’iris est en plein essor", https://www.idemia.com/fr/perspective/la-technologie-de-reconnaissance-de-liris-est-en-plein-essor



 



 

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée.