Linux PAM

PAM, die sog. Pluggable Authentication Modules, bieten eine Schnittstelle in unixoiden Betriebssystemen für die Authentisierung von z.B. Benutzern. Bekanntestes Beispiel für ein PAM Modul ist wohl die standardmäßige Passwort-Eingabe nach dem Boot des Betriebssystems. Der Benutzer authentisiert sich dabei gegenüber PAM mit seinem Passwort und PAM authentifizert diesen bei korrekter Passwort-Eingabe, sodass er sich in sein Benutzer-Konto einloggen kann. Der Vorteil bei PAM: Es kann anstatt einer Passwort-Eingabe jedes beliebige Authentisierungs-Verfahren verwendet werden. Das Erstellen eigener Module und das Anmelden darüber am System ist somit möglich. Da der Einstieg in die PAM Programmierung nicht ganz so einfach ist, wird im Folgenden die Erstellung eines sehr einfachen PAM Moduls und dessen Integration in Linux erklärt.

Beispiel für ein Linux PAM Modul mit PAM Python

Ein PAM Modul kann sehr schnell sehr komplex werden. Schließlich findet die komplette Authentisierung eines Benutzers oder Dienstes dort statt. Ein einfaches PAM Modul, um die Funktion von PAM zu erklären und zu verstehen, ist daher generell ein guter Einstieg. Die Programmiersprache für PAM ist C. Da diese Sprache ihre Eigenheiten hat und nicht sehr leicht zu lesen ist, gibt es zum Glück eine Möglichkeit, PAM Module auch in Python zu implementieren. Das Projekt, das dieses bietet, nennt sich PAM Python. Dieses wird für folgendes Beispiel benötigt. Folgender Befehl installiert das Paket:
~# apt-get install libpam-python

PAM Module befinden sich in dem Ordner /lib/security/ und beginnen mit "pam_" gefolgt von einem Namen. Bei PAM Fingerprint heißt das PAM Modul beispielsweise pam_fingerprint.py. Der Aufbau des PAM Moduls als Beispiel ergibt sich wie folgt:

def pam_sm_authenticate(pamh, flags, argv):

    return pamh.PAM_SUCCESS
   

def pam_sm_setcred(pamh, flags, argv):

    return pamh.PAM_SUCCESS

In der Methode pam_sm_authenticate findet die eigentliche Authentisierung eines Benutzers statt. Dort sollte über return pamh.PAM_SUCCESS bei Erfolg und pamh.PAM_AUTH_ERR bei Misserfolg zurückgegeben werden. Um die Rückgabewerte kümmert sich die interne PAM Verwaltung. Wie in dem Beispiel zu sehen ist, wird immer Erfolg zurückgeliefert. Dadurch wird die Authentisierung eines Benutzers übersprungen. Somit ist es z.B. möglich, sich ohne jegliche Berechtigungen als beliebiger Benutzer anzumelden oder sogar Root-Rechte zu erlangen.

Hinweis: Dies ist nur ein einfaches Beispiel! Niemals sollte ein eigenes PAM Modul so aussehen! Es sei denn, es ist so gewollt.

PAM Module verwalten

Unter Debian Linux gibt es einen sehr praktischen Befehl, um PAM Module zu verwalten:
~# pam-auth-update

Mit diesem Befehl öffnet sich eine halb-grafische Oberfläche mit einer Liste, in der alle PAM Module des Systems aufgelistet werden:

pam-auth-update

Mit der Leertaste können Module aktiviert (*) oder deaktiviert werden. Das Programm hält sich dabei an die sog. PAM Profile.

PAM Profile

PAM Profile bieten die Möglichkeit, PAM Module einfach zu aktivieren oder deaktivieren und beliebig zu verschachteln. Dadurch sind die Module erst modular. Die Profile befinden sich im Ordner /usr/lib/share/pam-configs/.

Als Beispiel wurde ein PAM Modul erstellt, welches jedoch dem System noch unbekannt ist und demnach noch nicht verwendet wird. Deswegen muss ein eigenes PAM Profil im Ordner /usr/lib/share/pam-configs/erstellt werden. Der Name des Profils ist konventionsgemäß der des Projekts. Diese Profile werden nach dem Stack-Prinzip abgearbeitet. Ein PAM Profil sieht z.B. bei PAM Fingerprint wie folgt aus:

Name: Fingerprint authentication
Default: yes
Priority: 257
Auth-Type: Primary
Auth:
    sufficient            pam_python.so pam_fingerprint.py

Hinter "Name" steht dabei der angezeigte Name, der in der Liste von pam-auth-update enthalten ist. "sufficient" bewirkt, dass falls PAM Fingerprint nach der Benutzung Erfolg zurückliefert, keine weiteren PAM Module ausgeführt werden. Liefert PAM Fingerprint jedoch Misserfolg zurück, greift nach dem Stack-Prinzip das nächste PAM Modul. Nach der Liste von pam-auth-update ist dies "Unix authentication", also die Standard Passwort-Authentisierung. Dieses Prinzip geht so lange weiter, bis der Stack abgearbeitet wurde bzw. ein PAM Modul Erfolg zurückliefert. Erreicht der Stack jedoch den Boden ohne Erfolg, wird die Authentisierung abgebrochen und der Stack beginnt von vorne.

Außer "sufficient" gibt es natürlich noch weitere Flags wie z.B. "required". Dieses Flag bewirkt, dass das Modul Erfolg zurückliefern muss. Falls nicht, wird die Authentisierung abgebrochen und der Stack beginnt von vorne.

Fazit

Wie zu sehen ist, ist die Erstellung und Integration von PAM Modulen kein Hexenwerk. Die Verwendung von Python als Programmiersprache durch PAM Python bietet zudem einen syntaktischen Luxus. PAM Fingerprint und PAM RFID sind auch mit Hilfe von PAM Python in Python implementiert worden. Beide wurden als Open-Source veröffentlicht und bieten somit weiterführende Source-Code Beispiele für die Entwicklung eigener PAM Module.