PAM: Conociendo la autenticación en Linux
Autenticación PAM
En Linux, la autenticación de los usuarios en el sistema está estandarizado mediante el uso de PAM (Pluggable Authentication Modules).
El uso de diferentes módulos para cada servicio facilita que cada uno de ellos no tenga que implementar el mecanismo de acceso, sino simplemente pasar las credenciales a PAM y este se encargue de indicar si el usuario tiene acceso a no.
Como varios servicios pueden establecer diferentes políticas de acceso, PAM nos permite particularizar la configuración según el servicio y personalizar su modo de funcionamiento.
Documentación sobre PAM
Si quieres tener una referencia completa sobre PAM, te recomiendo que te instales en tu equipo la documentación off-line que te proporciona Debian, para ello abre tu terminal y escribe:
La documentación quedará instalada en la ruta: /usr/share/doc/libpam-doc
Dentro tienes documentación en formato HTML o TXT (comprimido con gzip)
Puedes ver la documentación instalada en tu navegador escribiendo en la barra de direcciones la URL:
file:///usr/share/doc/libpam-doc/html/index.html
Ficheros y Estructura
Por defecto Linux, usará la ruta /etc/pam.d/ para localizar los ficheros necesarios que le indiquen las operaciones que debe de ejecutar para cada servicio que requiera autenticación.
En caso de que no encuentre nada allí, usará la configuración que exista en el fichero /etc/pam.conf
Dependiendo del software instalado, en la ruta /etc/pam.d si listamos su contenido veremos una serie de ficheros:
ls /etc/pam.d/
atd chfn chpasswd chsh common-account common-auth common-password
common-session common-session-noninteractive cron cups login newusers
other passwd ppp runuser runuser-l sshd su sudo sudo-i su-l
Lo primero que debemos saber es que existen 3 tipos de ficheros:
- common-...: Son los ficheros base para la autenticación de casi todos los demás servicios.
- other: Este fichero se usa cuando a un programa no se le haya indicado ninguna configuración.
- Resto de ficheros: Cada programa instalará una configuración especial si necesita algún tipo de autenticación.
Ejemplo: login (para logarse en el equipo), passwd (para permitir cambio de contraseña) ó su (como vimos en un artículo anterior).
Sintaxis de un fichero PAM para un Servicio/Aplicación
# Comentario
# La almohadilla indica que se trata de un comentario
# Incluir otro modulo/fichero PAM para simplificar sintaxis
# y carga de otras reglas existentes que queremos incluir:
@include moduloPAM
# Reglas del Servicio/Aplicación
tipo control modulo-libreria opciones-modulo
Parte de las Reglas en PAM
tipo
Existen 4 tipos de reglas:
- auth: Autorización. Comprobación del usuario/contraseña ó credencial/token suministrados para determinar si nson válidas y pertenecen a un usuario existente.
- account: Cuenta. Comprueba que el usuario autorizado anteriormente tiene permiso de acceso al equipo/servidor o no ya sea por limitaciones de grupos, limitación horaria, etc.
- password: Cualquier tarea relacionada con la gestión de contraseñas (cambio de contraseña).
- session: Gestiona los procesos que hay que ejecutar y comprobar antes de iniciar la sesión del usuario y también para los cierres de sesión (creacion/copia de ficheros, montar/desmontar filesystem, etc)
Si el valor de tipo de la lista anterior se antepone con un carácter -, la biblioteca PAM no se registrará en el registro del sistema si no es posible cargar el módulo porque falta en el sistema.
Esto puede resultar útil especialmente para módulos que no siempre están instalados en el sistema y no son necesarios para la correcta autenticación y autorización de la sesión de inicio de sesión.
Cada tipo de regla se reúne en lo que se denomina 'modulo apilado' y la evaluación se realiza para toda la pila de cada tipo. La devolución del resultado PAM se produce cuando se ha evaluado toda la pila y reglas de un mismo tipo. Además se ejecutan en el orden
control
Esta parte indica el comportamiento de PAM-API en caso de que el módulo no tenga éxito en su tarea de autenticación.
Hay dos tipos de sintaxis para este campo de control:
- control simple: Tiene una única palabra clave simple.
- control avanzado: Sintaxis que implica una selección entre corchetes de pares valor=acción
Control Simple
Puede tener los siguientes valores:
- required: El error en este control PAM conducirá en última instancia a devolver un fallo de PAM-API, pero solo después de que se hayan invocado los módulos apilados restantes (para este servicio y tipo).
- requisite:Al igual que requerido, se evalua y si no se cumple directamente se devuelve un error a la aplicación que solicito la validacion PAM. Se devuelve el error asociado al modulo requerido o que falta.
- sufficient: Si dicho módulo tiene éxito y ningún módulo requerido anteriormente ha fallado, el marco PAM devuelve el éxito a la aplicación o a la pila PAM superior inmediatamente sin llamar a ningún módulo adicional en la pila. Se ignora una falla de un módulo suficiente y el procesamiento de la pila de módulos PAM continúa sin verse afectado.
- optional: El éxito o el fracaso de este módulo solo es importante si es el único módulo en la pila asociado con este tipo de servicio.
Control avanzado / substack (subpila)
Un subpila/substack permite incluir una serie de controles extras a un tipo de control según una serie de argumentos u opciones para un tipo determinado.
Un subpila tiene un comportamiento diferente a un control simple ya que la subpila no provoca que se omita el resto de la pila de módulos completa, sino solo la subpila.
En un substack se pueden definir salto a otra parte de esa misma subpila para ignorar ciertas parte.
Los saltos en una subpila no pueden hacer que una evaluación salte fuera de ella. La subpila se considera como un "bloque" en su conjunto.
Si una subpila incluye por ejemplo la acción de reinicio reset
, restablecerá el estado de una pila de módulos al estado en el que se encontraba al comienzo de la evaluación de la subpila.
Sintaxis no anidada (subpila)
[valor1=accion1 valor2=accion2 ... valorN=accionN]
Sintaxis anidada (subpila)
Si necesitamos incluir una serie de valores y acciones como un bloque de una subpila, hay que usar como cierre de corchetes \]
en la parte interior:
[valor1=accion1 [valor21=accion21 valor22=accion22\] ... valorN=accionN]
Valores/funciones posibles a evaluar en el control
Valor | Explicación |
---|---|
abort | Error crítico. |
acct_expired | La cuenta de usuario ha expirado. |
auth_err | Error en la autenticación. |
authinfo_unavail | No puede accederse a la información de autenticación. |
authtok_disable_aging | Autenticacion con tokek deshabilitada |
authtok_err | Error en el uso del token de autenticación. |
authtok_expired | Ha caducado el Token de autenticación |
authtok_lock_busy | Sistema de bloque del Token ocupado |
authtok_recover_err | No se puede recuperar la información de autenticación. |
bad_item | Elemento (item) de autenticación incorrecto |
buf_err | Error en el buffer de memoria. |
conv_again | La función de negociación(conversation) depende de evento y datos que aun no están disponibles |
conv_err | Error en la conversación. |
cred_err | Error al fijar las credenciales de usuario. |
cred_expired | Las credenciales del usuario han caducado. |
cred_insufficient | Sin acceso a datos de autenticación por falta de credenciales. |
cred_unavail | Credenciales de usuario no disponibles. |
default | Cualquier valor no mencionado implícitamente. |
ignore | Ignorar. No considerar el módulo. |
incomplete | Falta algun proceso. Reiniciar el módulo para que se complete. |
maxtries | Numero máximo número de intentos. |
module_unknown | Módulo desconocido. El módulo no existe |
new_authtok_reqd | Se necesita un nuevo token de autenticación. |
no_module_data | Módulo sin datos. |
open_err | No puede cargarse el módulo. |
perm_denied | Permiso denegado. |
service_err | Error de servicio en el módulo. |
session_err | Error de sesión. |
success | Proceso finalizado correctamente. |
symbol_err | Símbolo no encontrado. |
system_err | Error de sistema. |
try_again | Reintento. Servicio de verificación preliminar mediante contraseña. |
user_unknown | Usuario desconocido. |
Acciones/resultados con los que comparará el valor/función en el control
Accion/Resultado | Explicación |
---|---|
bad | Resultado es un fallo |
die | Resultado es un fallo, pero no se sigue comprobando nada |
done | Resultado correcto. No hace falta seguir comprobando en el substak |
ignore | El resultado no afecta al resultado global |
ok | El módulo acabo correctamente |
reset | Se resetea el resultado global del proceso/substack |
N (número) | Número de directivas del substack que se saltarán |
Módulo - Librería
En esta parte de la regla, hay que especificar que librería del sistema es la encargada de realizar la tarea que se le pida (auth, account, password, session) para poder usar las funciones internas que realicen esa validación.
El nombre de estos módulos/librerías son `nombre_libreria.so`
Dependiendo del sistema y la arquitectura, la ruta de ubicación de estas librerías de seguridad (security) puede ser diferente.
Ejemplos de rutas para security:
/lib/security
/lib64/security
/usr/lib/security
/usr/lib64/security
...
/usr/lib/x86_64-linux-gnu/security
Opciones del Módulo
Esta última parte de la regla, podemos detallar exactamente que es lo que esperamos obtener para que la regla aplique unos valores u otros y nos diga si se puede autenticar al usuario, puede cambiar la clave, etc.
Ejemplo y Explicación
Si tenemos por ejemplo una regla como la siguiente para una aplicación:
Línea| Regla
........................
Lin 1| auth [success=2 default=ignore] pam_unix.so nullok_secure
Lin 2| auth [success=1 default=ignore] pam_ldap.so use_first_pass minimum_uid=1000
Lin 3| auth requisite pam_deny.so
Lin 4| auth required pam_permit.so
........................
Linea 1: Al llegar a esta parte, se carga el modulo de autenticación de unix (pam_unix.so) se comprueba con nullok_secure, si el usuario es local (success=2) y se saltan las siguiente 2 lineas del modulo del substack y comprobará la línea 4 (pam_permit) y accedería como usuario.
En caso caso de fallo simplemente se ignora (default=ignore) e iría a la siguiente línea de las reglas (línea 2).
Línea 2: Se cargan las libreria de ldap (pam_ldap.so) y se verifica que su UID sea mayor que 1000 (mininum_uid=1000) y se comprueba la autenticación el usuario. Si es correcto (success=1) se salta una línea y ejecutará la línea 4 (que permite acceder al usuario).
Si falla, continuará (default=ignore) y ejecutará la siguiente línea (línea 3) en la que se le deniega el acceso.
Línea 3: Todo los que pasa por esta linea marcada como requisito (requisite) produce una denegación de acceso.
Línea 4: Todo lo que pase por esta línea marcada como obligatoria (required) permitirá el acceso.
Otro ejemplo
En el artículo anterior usamos el modulo `su` de PAM para modificar su comportamiento e incluimos:
Línea | Regla
........................
Línea 1| auth [success=ignore default=1] pam_succeed_if.so user = tomato
Línea 2| auth sufficient pam_succeed_if.so use_uid user ingroup tomato
........................
En este caso si el usuario es tomato (él mismo) se ignora (success=ignore) y se salta una línea (default=1), continuando con los procesos que tenga definidos.
En la siguiente línea es suficiente (sufficiente) con que el UID del usuario esté dentro el grupo (ingroup tomato) y se indica que la validación se ha completado y se continuará con los procesos definidos dentro del módulo su.
Esquema del funcionamiento PAM
╔════════════════╗
║ Aplicacion: X ║
╠════════════════╣ / ┌───────────┐ ╔═════════════════╗
│ Autenticación ├──⊳──⊳──\──┤ ├──⊲──╣ Fich config PAM ║
│ + ├──⊲──⊲──/──┤ Linux-PAM │ ╠═════════════════╣
│[Conversación()]├───┐ \ │ │ │ X auth .. a.so │
├────────────────┤ │ └────┬──────┘ │ X auth .. b.so │
│ Usuario │ │ ┌─────┤ │ ┌──────┘
│ del │ ∆ │ │ └──────────┘
│ servicio │ │ ∇ ∆
└────────────────┘ └──────┼─────┼─────────┬──────┬──────┐
│ │ │ │ │
┌───┴─────┴───┐ │ │ │
│ auth ├───[ a ]──[ b ]──[ c ]
├─────────────┤
│ account ├───[ b ]──[ d ]
├─────────────┤
│ password ├───[ b ]──[ c ]
├─────────────┤
│ session ├───[ e ]──[ c ]
└─────────────┘
A la izquierda del todo tenemos la Aplicación X, con la que el usuario se va a conectar.
La aplicación X interactúa con la biblioteca Linux-PAM (en el centro) que consulta si hay algún archivo de autenticación configurada para ella y carga las librerías/módulos (ficheros .so) del sistema para la aplicación.
Estos módulos pueden tener 4 tipos de gestión (parte de abajo). Apilados según el orden de la configuración de las reglas: auth, account, password y/o session.
Se inicia una "conversación" con el contenido de la regla definida y las opciones que se encuentren el en el fichero PAM para cada tipo se permitirá o no el acceso al usuario.
La evaluación se realiza por el conjunto de la "pila": auth+account+password+session y no son obligatorias todas las evaluaciones.
Si un programa va a utilizar PAM, entonces debe tener funciones PAM definidas explícitamente en su código o no podrá usar PAM.
En cualquier momento (si se dispone del código fuente del programa) se pueden implementar fácilmente las funciones PAM apropiadas para implementar la autenticación mediante Linux-PAM.
Si instaló libpam-doc en su equipo, puede ver cómo implementar el uso de PAM en su aplicación.