Gibt es eine Möglichkeit, einen Benutzer innerhalb einer benutzerdefinierten PAM-Sitzung ordnungsgemäß zu authentifizieren?
Ich schreibe gerade mein eigenes PAM-Authentifizierungsmodul, das es dem Benutzer ermöglicht, sich über ein externes Token anzumelden. Dieses Token muss generiert werden, bevor sich der Benutzer mit meinem Modul anmelden kann. Daher möchte ich auf die Standard-PAM-Authentifizierung zurückgreifen, wenn kein Token vorhanden ist, und mit meinem Code fortfahren, sobald der Benutzer authentifiziert ist.
Ist das irgendwie möglich? Im Pseudocode sieht mein Modul so aus:
pam_sm_authenticate() {
if (first_login) {
code_copied_from_pam_unix_to_authenticate_user();
// do something else here?
} else {
custom_auth();
}
}
Als schnelle Lösung habe ich den Code aus dem pam_unix-Modul von Linux in mein eigenes kopiert und es funktioniert. Dies ist jedoch nicht sehr zufriedenstellend, da es viele zusätzliche Bibliotheken erfordert und außerdem nur funktioniert, solange sich pam_unix nicht ändert. Ich würde lieber eine weitere PAM-Sitzung innerhalb meiner Sitzung öffnen, habe es aber nicht zum Laufen gebracht.
Antwort1
Überlassen Sie nicht die gesamte Logik Ihrem Code: Verwenden Sie zuerst PAM und seine Konfiguration, um sicherzustellen, dass Ihr Modul unter den besten Bedingungen ausgeführt wird (d. h. kein Kopieren pam_unix
des Codes erforderlich ist).
Lassen Sie mich zunächst einen anderen Pseudocode für Ihr Modul vorschlagen:
pam_sm_authenticate() {
if (first_login) return PAM_CRED_INSUFFICIENT;
else custom_auth();
}
Hier betrachte ichErster Loginein Fall von unzureichenden Anmeldeinformationen zu sein. Ich sage PAM, dass das Modul ausfällt, weil es nicht alles hat, was es braucht, um den Benutzer vollständig zu authentifizieren. Angenommen, Ihr Modul heißt my_module
, wäre eine mögliche Konfiguration:
auth [cred_insufficient=ok success=done default=2] my_module.so
auth [success=ok default=1] pam_unix.so
auth sufficient my_module.so
auth requisite pam_deny.so
Hier sind die Details:
Zunächst geht die Anfrage durch
my_module
. Hier gibt es mehrere Möglichkeiten:- Erster Login: Ihr Modul hat zurückgegeben
PAM_CRED_INSUFFICIENT
. Dieser Fall isterwischtvon PAM (übercred_insufficient
). In diesem Fall wird die Kette als erfolgreich markiert (ok
), aberweitermachen. - Dies war nicht die erste Anmeldung, Sie haben sie durchgeführt
custom_auth()
und sie war erfolgreich (es wurde zurückgegebenPAM_SUCCESS
). In diesem Fall beenden wir die Kette (done
) :Zugriff gewährt. - Dies war nicht die erste Anmeldung und
custom_auth()
endete nicht gut (PAM_AUTH_ERR
oder andere Arten von internen Fehlern). Überspringen Sie in diesem Fall die nächsten beiden Zeilen (default=2
). Die Kette geht direkt inpam_deny
, was immer fehlschlägt:Zugriff abgelehnt.
- Erster Login: Ihr Modul hat zurückgegeben
Im ersten Szenario geht die Kette weiter bis
pam_unix
. Hier gibt es zwei Möglichkeiten:- Die UNIX-Authentifizierung ist erfolgreich. Dies kennzeichnet die Kette als erfolgreich (
ok
) undgeht weiter zum nächsten Modul. - Die UNIX-Authentifizierung schlägt fehl. Das nächste Modul wird übersprungen (
default=1
) und die Kette endet mitpam_deny
:Zugriff abgelehnt.
- Die UNIX-Authentifizierung ist erfolgreich. Dies kennzeichnet die Kette als erfolgreich (
Wenn Sie die dritte Zeile erreichen, bedeutet dies, dass dies
my_module
beim ersten Mal beendet wurdePAM_CRED_INSUFFICIENT
undpam_unix
erfolgreich war. Ihr Modul wird erneut (// do something else here?
) als aufgerufensufficient
. Wieder zwei Möglichkeiten:- Dieses Mal ist Ihr Modul erfolgreich:Zugriff gewährt.
- Das Modul schlägt erneut fehl, allerdings aus einem anderen Grund als unzureichenden Anmeldeinformationen:Zugriff abgelehnt.
Möglicherweise möchten Sie auch benutzerdefinierten Code ausführennach UNIX-Authentifizierung, auch wenn es fehlgeschlagen ist. Ändern Sie dazu die zweite Zeile wie folgt:
auth [success=ok default=bad] pam_unix.so
my_module
Dadurch wird die Kette auf jeden Fall noch einmal durchlaufen , aber die Kette wird markiert alsfehlgeschlagenAuch wenn Ihr Modul hier erfolgreich ist, schlägt die Kette fehl.
Sie möchten Ihrem Modul vielleicht auch mitteilen, wie oft wir es in einer Kette aufgerufen haben: Unterscheiden Sie den ersten Aufruf my_module
vom zweiten. Dies lässt sich ganz einfach mit Argumenten erreichen:
auth [cred_insufficient=ok success=done default=2] my_module.so
auth [success=ok default=1] pam_unix.so
auth sufficient my_module.so second_time
auth requisite pam_deny.so
Hier pam_sm_authenticate
wird dem zweiten Aufruf von ein Argument (durch argv
und argc
) übergeben, das Ihnen helfen sollteLokalisierenIhr Modul in der Kette zur Laufzeit. Natürlich firstLogin
sollte Ihre Bedingung ausreichen, um eine solche Unterscheidung zu treffen.