
Como mi pregunta relacionada no parece recibir mucho amor, aquí otra: ¿Cuál es la forma correcta de autenticar a un usuario mediante la solicitud de nombre de usuario/contraseña en Linux hoy en día?
En principio, supongo que tendría que obtener el nombre de usuario y la contraseña, leer salt y hash del usuario correspondiente de /etc/shadow
. Luego calcularía el hash de la contraseña dada y la sal almacenada y comprobaría si el resultado coincide con el hash almacenado en /etc/shadow
.
Normalmente, podría simplemente autenticarme a través de PAM (por ejemplo pam_unix
), que ya hace todo esto, pero mi aplicación es un módulo PAM personalizado y no encontré ningún método para llamar a un módulo PAM desde otro. Si esto es posible de alguna manera, con mucho gusto buscaría esta solución.
A partir de ahora, encontré este tutorial realmente anticuado.http://www.tldp.org/HOWTO/Shadow-Password-HOWTO-8.htmldesde 1996 cuando, aparentemente, el soporte oculto aún no estaba integrado en libc. Menciona pw_auth
y valid
como funciones auxiliares para la autenticación. Intenté implantarlos en mi código y vincularlos con libshadow.a
las herramientas de sombra, pero obtengo errores de "referencia externa no resuelta" para pw_auth
y valid
. El código se parece a esto:
if ((pw->pw_passwd && pw->pw_passwd[0] == '@'
&& pw_auth (pw->pw_passwd+1, pw->pw_name, PW_LOGIN, NULL))
|| !valid (passwd, pw)) {
return (UPAP_AUTHNAK);
}
No he verificado esto más, pero de todos modos esta no es la solución preferida ya que tendría que actualizar mi código cada vez que se actualizan Shadow-Utils.
Preferiría vincularme a una biblioteca (que no sea PAM) que proporcione autenticación contra /etc/shadow
. ¿Existe tal cosa y aún no la encontré? ¿O alguna otra solución?
Respuesta1
En mi opinión, el miedo a una actualización de Shadow-Utils es injustificado. Las rutinas descritas en ese CÓMO están disponibles en mis sistemas Ubuntu 12.04 y Mint 17 sin instalar nada especial.
La estructura para leer /etc/shadow
información en un programa C se puede encontrar en /usr/include/shadow.h
y con man 5 shadow
las funciones que necesitaría encontrar, por ejemplo, una entrada de contraseña oculta por nombre como se define en /usr/include/shadow.h
is getspnam
y que también le brindará una página de manual ( man getspnam
) que describe eso y todas las funciones relacionadas.
En base a eso, debería poder obtener la entrada de contraseña con hash para cualquier nombre de pila. La contraseña con hash debe tener múltiples tokens '$', eliminar todo lo que sigue e incluir el último '$' de la contraseña con hash y presentarlo como salt a crypt()
, la versión glibc (según man 3 crypt
) debería poder manejar las sales "extendidas" que indican entradas SHA512 como son más comunes hoy en día.