Thomas Touhey
:
Logs de connexion sur UNIX-like
Sur systèmes type UNIX (respectant la norme POSIX), il y a plusieurs fichiers
historiques qui contiennent des données importantes pour le système.
Le plus connu est sans doute /etc/passwd
, qui donne la liste des
utilisateurs locaux et des donées les caractérisant, comme leur numéro
d’utilisateur (uid
), le nom complet, le shell par défaut, le dossier
personnel, aussi nommé “home” ou “home directory”. Il existe d’autres types
d’identification sur UNIX-like à présent, mais celui-ci reste celui par défaut.
Parmi d’autres fichiers un peu moins connus, on trouve /etc/group
, qui donne
la liste des groupes ainsi que les utilisateurs en faisant partie, ou
/etc/shadow
, qui donne le hash des mots de passe pour les utilisateurs dans
/etc/passwd
, mais qui n’est accessible qu’à root
, qui est ainsi le seul
à pouvoir déterminer si un mot de passe est le bon pour un utilisateur
(alors que tout le monde peut lire /etc/passwd
pour découvrir les
utilisateurs locaux existants).
Mais si vous avez déjà lancé who
ou, plus improbable, finger
, vous
verrez quelques champs qui ne s’obtiennent pas avec ces fichiers-là :
le login time (quand l’utilisateur s’est-il connecté pour la dernière
fois ?),, le TTY sur lequel l’utilisateur est connecté, et l’idle time
(de combien de temps date la dernière action de l’utilisateur ?).
Pour trouver ces informations-là, il faut aller farfouiller du côté
de quelques fichiers : l’utmp
, le wtmp
, et le btmp
.
Ces fichiers sont ceux où sont archivés les détails de tous les
évènements de connexion et de déconnexion. Ceux-ci y sont inscrits non pas
par un programme centralisé (un daemon de poil quelconque), mais par tout
programme procédant à une connexion – cela induit d’ailleurs qu’il est
impossible de savoir tous les utilisateurs connectés, puisqu’un programme
authentifiant peut ne pas alimenter le fichier. En général, les utilisateurs
touchant à ces fichiers sont dans un groupe particulier, utmp
par exemple.
Les trois fichiers ont le même format, mais trois différents rôles :
- l’
utmp
présente le statut actuel de la machine et de l’ensemble des utilisateurs connectés ; - le
wtmp
est un historique des connexions ; - le
btmp
est un historique des connexions non réussies.
À noter qu’il existe deux versions de ces fichiers :
- la version non standardisée, obsolète sauf dans quelques cas ;
- la version standardisée dans POSIX et la Single Unix Specification,
qui définit
utmpx
,wtmpx
etbtmpx
au lieu des trois par défaut.
La version Linux est un peu spéciale, puisqu’elle est conforme au standard tout en reprenant les éléments de System V et de BSD, rendant indistinguable les deux versions sur cette plateforme.
Le chemin de ces fichiers varie entre les plateformes (non standardisés), mais
la page Wikipédia recense ceux-ci pour quelques plateformes
répandues. Nous nous intéresserons au cas Linux, où les chemins sont
/var/run/utmp
, /var/log/wtmp
et /var/log/btmp
.
Au passage, plusieurs choses sont intéressantes à noter avec ces chemins :
puisque la structure est la même entre les deux versions des fichiers sous
distributions Linux, il n’y a pas de version ‘x’ de ces fichiers.
De plus, les dossiers ont du sens : /var/log
est persistent, et /var/run
est un dossier temporaire (tmpfs
est monté dessus comme sur /run
).
Le format de ce fichier, au cas où vous ne vous en doutiez pas déjà, est
binaire et non textuel (pour rappel, les trois fichiers ont le même).
Il est décrit dans la définition du header utmp.h
prévu pour les
programmes en langage C. À noter que les programmes doivent parcourir le
fichier eux-mêmes, puisqu’il n’y a pas de fonction standardisée (pas de
libutmp non plus, mais ça ne m’étonne qu’à moitié, puisque ces fichiers
ne sont pas tant utilisés que ça).
En Python pour Linux (puisque c’est le contexte dans lequel je voulais
l’utiliser), le module utmp est plutôt bien fait, mais “hardcode”
la structure, donc n’est utilisable que pour Linux. Une idée serait donc de
faire un module équivalent en natif pour CPython (l’implémentation de
référence de Python), qui utiliserait donc le header <utmp.h>
standard
(bien que le chemin vers les fichiers devra donc être caché derrière des
OS-specific macros, type __linux__
ou autre).
Un dernier point avant de terminer cet article : l’idle time n’est pas
contenu dans une entrée. Pour l’obtenir, si l’utilisateur n’utilise pas Xorg
ou quelque chose d’équivalent (donc généralement un shell directement),
il suffit de récupérer le tty sur lequel l’utilisateur est connecté depuis
l’entrée correspondante dans l’utmp
, puis faire un stat
dessus (en
n’oubliant pas de préfixer la chaîne obtenu de l’entrée d’utmp
par /dev/
,
non inclus dans l’entrée pour garder de la place). La date de dernier accès,
accessible sous la forme d’un timestamp sur st_atime
, correspond à la
dernière fois où l’utilisateur a entré quelque chose sur le terminal.
Je n’entrerai pas davantage dans les détails, mais si vous souhaitez vous servir de ces fichiers plutôt utiles, la page de manuel est bien faite !