
como minha pergunta relacionada não parece receber muito amor, aqui está outra: Qual é a maneira correta de autenticar um usuário via prompt de nome de usuário/senha no Linux hoje em dia?
Em princípio, suponho que teria que obter nome de usuário e senha, ler salt e hash do usuário correspondente em /etc/shadow
. Eu então calcularia o hash da senha fornecida e do salt armazenado e verificaria se o resultado corresponde ao hash armazenado em /etc/shadow
.
Normalmente, eu poderia simplesmente autenticar via PAM (por exemplo pam_unix
), que já faz tudo isso, mas meu aplicativo é um módulo PAM personalizado e não encontrei nenhum método para chamar um módulo PAM de outro. Se isso for possível de alguma forma, eu ficaria feliz em optar por esta solução.
A partir de agora, achei este tutorial realmente desatualizadohttp://www.tldp.org/HOWTO/Shadow-Password-HOWTO-8.htmldesde 1996, quando, aparentemente, o suporte shadow ainda não estava incorporado na libc. Menciona pw_auth
e valid
como funções auxiliares para autenticação. Tentei implantá-los em meu código e vinculá-los libshadow.a
às ferramentas de sombra, mas recebo erros de 'referência externa não resolvida' para pw_auth
e valid
. O código é mais ou menos assim:
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);
}
Não verifiquei isso ainda mais, mas de qualquer forma, esta não é uma solução preferida, pois eu teria que atualizar meu código toda vez que os shadow-utils fossem atualizados.
Prefiro vincular a uma biblioteca (que não seja PAM) que forneça autenticação contra arquivos /etc/shadow
. Existe tal coisa e eu ainda não encontrei? Ou alguma outra solução?
Responder1
Seu medo de uma atualização de shadow-utils é IMO injustificado. As rotinas descritas nesse HOWTO estão disponíveis em meus sistemas Ubuntu 12.04 e Mint 17 sem instalar nada de especial.
A estrutura para ler /etc/shadow
informações em um programa C pode ser encontrada em /usr/include/shadow.h
e com man 5 shadow
e as funções que você precisaria encontrar, por exemplo, uma entrada de senha shadow por nome, conforme definido em /usr/include/shadow.h
is getspnam
e que também fornecerá uma página de manual ( man getspnam
) descrevendo isso e todas as funções relacionadas.
Com base nisso, você poderá obter a entrada de senha com hash para qualquer nome. A senha com hash deve ter vários tokens '$', cortar tudo depois e incluindo o último '$' da senha com hash e apresentar isso como salt para crypt()
, a versão glibc (de acordo com man 3 crypt
) deve ser capaz de lidar com os sais "estendidos" que indicam entradas SHA512 como são mais comuns hoje em dia.