Queridos compañeros expertos en sistemas,
un amigo administrador me ha hecho la siguiente pregunta:
En varios elementos de red y servidores, utiliza autenticación remota contra un servidor TACACS+. En algunos de estos dispositivos propietarios, la autenticación solo solicita una base de datos de autenticación local si el método remoto devuelve "servidor de autenticación no disponible" (inalcanzable, agotado el tiempo de espera). Si el servidor de autenticación remotaesdisponible y devuelve una respuesta negativa, el cuadro en cuestión lo toma al pie de la letra y no intenta realizar la autenticación en una base de datos de usuarios local.
Ahora... en una máquina basada en Linux, le gustaría lograr el mismo comportamiento. Y parece que no puede hacerlo. El sistema operativo Linux primero intenta la autenticación remota, pero ante una respuesta negativa clara (el servidor responde "fallo de autenticación, esas no son credenciales válidas") continúa y simplemente prueba también la base de datos local.
He llegado a comprender que la autenticación TACACS+ remota está organizada por un bonito módulo PAM llamado pam_tacplus. Al leer sobre PAM en general, me doy cuenta de que pam_tacplus no tiene la culpa. Más bien, el comportamiento observado es simplemente la forma en que funciona PAM en su conjunto. Si ese es el caso, una solución directa probablemente tendría que implicar agregar una opción global configurable al código base de PAM, y tal vez palabras clave/sintaxis específicas del archivo de configuración de PAM, para modificar el comportamiento en la dirección deseada.
Cualquier otra nota sobre este tema es bienvenida :-)
Respuesta1
...basado en lecturas adicionales, permítanme sugerir una respuesta. Cualquier adición o corrección es obviamente bienvenida.
En primer lugar, encontré esto antiguo.introducción a PAM. Probablemente no ha perdido nada de su ingenio a lo largo de los años.
Si echo un vistazo debajo del capó, los valores de retorno del módulo de autenticación sondocumentado en la documentación oficial de linux-pam.
En la lista, puedo ver una recuperación prometedora llamada PAM_AUTHINFO_UNAVAIL.
Realmente definido enlibpam/include/security/_pam_types.h.
#define PAM_SUCCESS 0
#define PAM_AUTHINFO_UNAVAIL 9
#define _PAM_RETURN_VALUES 32
Parece haber una definición contradictoria de PAM_AUTHINFO_UNAVAIL enlibpam/include/security/_pam_compat.h
# define PAM_AUTHINFO_UNAVAIL 12
- probablemente sea seguro ignorarlo.
El archivo fuentelibpam/pam_dispatch.c contiene una función clave llamada _pam_dispatch_aux()que realmente recorre la pila de módulos de autenticación registrados y actúa sobre sus valores de retorno. Y resulta que no hace mucho basándose directamente en el "retval", posiblemente conteniendo PAM_AUTHINFO_UNAVAIL
. Responde directamente a algunos valores particulares de "uso especial interno" de retval
, pero no tiene un manejo especial para PAM_AUTHINFO_UNAVAIL
. retval
no es un valor de retorno en _pam_dispatch_aux()
sí mismo: más bien, retval
es solo una variable local declarada dentro del bucle for(;;) que recorre la pila de módulos de autenticación registrados, donde el bloque local retval
recopila el valor de retorno del módulo en particular. El ciclo de stackwalking en realidad toma decisiones importantes basadas en otras variables: una de ellas derivada, llamada action
y la otra es un miembro de la estructura llamado impression
"devuelto" por los módulos por referencia. Entonces, ¿quizás después de todo podría estar influenciado por el propio código del módulo?
En realidad resulta que action
está tomado de una "tabla de búsqueda de acciones",
indexado porel retval
- ¡ajá!
action = h->actions[cached_retval];
¿La tabla de acciones está definida por el módulo? Pero ¿cómo, si las macros _PAM_ACTION_* son un #definido enlibpam/pam_private.h?
Resulta que la tabla de acciones[] esinicializado de forma genéricapor una función llamada _pam_parse_conf_file()
en libpam/pam_handlers.c
, que hace uncomparación directa de cadenas(coincidencia) en palabras clave como
required
, requisite
, optional
, sufficient
.
Y, actualmente, toda la tabla tiene 32 posiciones (consulte la definición de macro citada anteriormente) que obtienenventa al por mayor inicializadoa _PAM_ACTION_UNDEF antes de analizar la entrada de configuración para el módulo en particular. Las "palabras claves fuertes" individuales luego reasignan retval
las s individuales a acciones deseadas particulares.
Entonces: parece bastante obvio, por ejemplo, inspirarse en esto:
} else if (!strcasecmp("required", tok)) {
D(("*PAM_F_REQUIRED*"));
actions[PAM_SUCCESS] = _PAM_ACTION_OK;
actions[PAM_NEW_AUTHTOK_REQD] = _PAM_ACTION_OK;
actions[PAM_IGNORE] = _PAM_ACTION_IGNORE;
_pam_set_default_control(actions, _PAM_ACTION_BAD);
} else if (!strcasecmp("sufficient", tok)) {
D(("*PAM_F_SUFFICIENT*"));
actions[PAM_SUCCESS] = _PAM_ACTION_DONE;
actions[PAM_NEW_AUTHTOK_REQD] = _PAM_ACTION_DONE;
_pam_set_default_control(actions, _PAM_ACTION_IGNORE);
}
y agrega algo como
} else if (!strcasecmp("reqd_if_avail", tok)) {
D(("*PAM_F_REQD_IF_AVAIL*"));
actions[PAM_SUCCESS] = _PAM_ACTION_OK;
actions[PAM_AUTHINFO_UNAVAIL] = _PAM_ACTION_IGNORE; // !!!!!!!!!!
actions[PAM_NEW_AUTHTOK_REQD] = _PAM_ACTION_OK; // ?
actions[PAM_IGNORE] = _PAM_ACTION_IGNORE;
_pam_set_default_control(actions, _PAM_ACTION_BAD); // !!!
}
Y aparentemente pam_tacplusnos ayuda en ese camino.
Sin duda, sería bueno si se pudiera lograr el mismo efecto mediante la sintaxis del archivo de configuración PAM existente, sin tener que piratear el código fuente.