Autenticar externamente al usuario dentro de la sesión PAM/sesión PAM dentro de la sesión PAM

Autenticar externamente al usuario dentro de la sesión PAM/sesión PAM dentro de la sesión PAM

¿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_unixel 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í:

    1. Primer inicio de sesión: su módulo regresó PAM_CRED_INSUFFICIENT. Este caso esatrapópor PAM (a través de cred_insufficient), en cuyo caso está configurado para marcar la cadena como exitosa ( ok) pero parasigue adelante.
    2. 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.
    3. Este no fue el primer inicio de sesión y custom_auth()no terminó bien ( PAM_AUTH_ERRu otros tipos de errores internos). En este caso, omita las siguientes 2 líneas ( default=2). La cadena va directo a pam_deny, que siempre falla:acceso denegado.
  • En el primer escenario, la cadena continúa hasta pam_unix. Dos posibilidades aquí:

    1. La autenticación UNIX se realiza correctamente. Esto marca la cadena como exitosa ( ok) ypasa al siguiente módulo.
    2. La autenticación UNIX falla. El siguiente módulo se omite ( default=1) y la cadena termina en pam_deny:acceso denegado.
  • Si llegas a la tercera línea, significa que my_moduleterminó PAM_CRED_INSUFFICIENTla primera vez y pam_unixtuvo éxito. Su módulo se llama nuevamente ( // do something else here?) como sufficient. Dos posibilidades nuevamente:

    1. Esta vez, su módulo tiene éxito:acceso permitido.
    2. 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_moduleotro 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_modulede 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_authenticatese le pasará un argumento (a través de argvy argc) que debería ayudarlelocalizarsu módulo en la cadena en tiempo de ejecución. Por supuesto, su firstLogincondición debería ser suficiente para hacer tal distinción.

información relacionada