¿Existe alguna forma de autenticar correctamente a un usuario desde una sesión PAM personalizada?
Actualmente estoy escribiendo mi propio módulo de autenticación PAM que permite al usuario iniciar sesión mediante un token externo. Este token debe generarse antes de que el usuario pueda iniciar sesión en mi módulo. Por lo tanto, me gustaría volver a la autenticación PAM predeterminada cuando no existe ningún token y continuar con mi código tan pronto como el usuario esté autenticado.
¿Es esto posible de alguna manera? En pseudocódigo mi módulo se ve así:
pam_sm_authenticate() {
if (first_login) {
code_copied_from_pam_unix_to_authenticate_user();
// do something else here?
} else {
custom_auth();
}
}
Como solución rápida, copié el código del módulo pam_unix de Linux al mío y funciona. Sin embargo, esto no es muy satisfactorio ya que requiere muchas bibliotecas adicionales y además sólo funcionará mientras pam_unix no cambie. Preferiría abrir otra sesión PAM dentro de mi sesión pero no logro que funcione.
Respuesta1
No permita que su código lleve a cabo toda la lógica: use PAM y su configuración primero para asegurarse de que su módulo se ejecute en las mejores condiciones (es decir, no requiere copiar pam_unix
el código).
Primero, déjame sugerirte otro pseudocódigo para tu módulo:
pam_sm_authenticate() {
if (first_login) return PAM_CRED_INSUFFICIENT;
else custom_auth();
}
Aquí consideroprimer inicio de sesiónse trata de un caso de insuficiencia de credenciales. Le digo a PAM que el módulo está fallando porque no tiene todo lo que necesita para autenticar completamente al usuario. Ahora, suponiendo que su módulo se llame my_module
, una posible configuración sería:
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
Aquí están los detalles:
Primero, la solicitud se procesa
my_module
. Varias posibilidades aquí:- Primer inicio de sesión: su módulo regresó
PAM_CRED_INSUFFICIENT
. Este caso esatrapópor PAM (a través decred_insufficient
), en cuyo caso está configurado para marcar la cadena como exitosa (ok
) pero parasigue adelante. - Este no fue el primer inicio de sesión, lo realizó
custom_auth()
y fue exitoso (regresóPAM_SUCCESS
). En este caso ponemos fin a la cadena (done
):acceso permitido. - Este no fue el primer inicio de sesión y
custom_auth()
no terminó bien (PAM_AUTH_ERR
u otros tipos de errores internos). En este caso, omita las siguientes 2 líneas (default=2
). La cadena va directo apam_deny
, que siempre falla:acceso denegado.
- Primer inicio de sesión: su módulo regresó
En el primer escenario, la cadena continúa hasta
pam_unix
. Dos posibilidades aquí:- La autenticación UNIX se realiza correctamente. Esto marca la cadena como exitosa (
ok
) ypasa al siguiente módulo. - La autenticación UNIX falla. El siguiente módulo se omite (
default=1
) y la cadena termina enpam_deny
:acceso denegado.
- La autenticación UNIX se realiza correctamente. Esto marca la cadena como exitosa (
Si llegas a la tercera línea, significa que
my_module
terminóPAM_CRED_INSUFFICIENT
la primera vez ypam_unix
tuvo éxito. Su módulo se llama nuevamente (// do something else here?
) comosufficient
. Dos posibilidades nuevamente:- Esta vez, su módulo tiene éxito:acceso permitido.
- El módulo vuelve a fallar, pero por otro motivo además de la insuficiencia de credenciales:acceso denegado.
Es posible que también desees ejecutar código personalizado.después de la autenticación UNIX, incluso si falló. Para hacer eso, cambie la segunda línea a:
auth [success=ok default=bad] pam_unix.so
Esto hará que la cadena pase por my_module
otro momento pase lo que pase, pero la cadena quedará marcada comofallido. Incluso si su módulo termina exitosamente aquí, la cadena fallará.
También es posible que desees que tu módulo sepa cuántas veces lo hemos llamado en una cadena: distingue la primera llamada my_module
de la segunda. Esto podría hacerse fácilmente con argumentos:
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
Aquí, a la segunda llamada pam_sm_authenticate
se le pasará un argumento (a través de argv
y argc
) que debería ayudarlelocalizarsu módulo en la cadena en tiempo de ejecución. Por supuesto, su firstLogin
condición debería ser suficiente para hacer tal distinción.