Existe uma maneira de autenticar adequadamente um usuário em uma sessão PAM personalizada?
Atualmente estou escrevendo meu próprio módulo de autenticação PAM que permite ao usuário fazer login através de um token externo. Este token deve ser gerado antes que o usuário possa fazer login com meu módulo. Portanto, gostaria de voltar à autenticação PAM padrão quando não existir nenhum token e continuar com meu código assim que o usuário for autenticado.
Isso é possível de alguma forma? Em pseudocódigo, meu módulo fica assim:
pam_sm_authenticate() {
if (first_login) {
code_copied_from_pam_unix_to_authenticate_user();
// do something else here?
} else {
custom_auth();
}
}
Como solução rápida, copiei o código do módulo pam_unix do Linux para o meu e funcionou. No entanto, isso não é muito satisfatório, pois envolve muitas bibliotecas adicionais e também só funcionará enquanto o pam_unix não for alterado. Eu preferiria abrir outra sessão PAM dentro da minha sessão, mas não consegui fazê-la funcionar.
Responder1
Não deixe seu código executar toda a lógica: use primeiro o PAM e sua configuração para garantir que seu módulo funcione nas melhores condições (ou seja, não requer cópia pam_unix
do código).
Primeiro, deixe-me sugerir outro pseudocódigo para o seu módulo:
pam_sm_authenticate() {
if (first_login) return PAM_CRED_INSUFFICIENT;
else custom_auth();
}
Aqui, consideroprimeiro loginser um caso de insuficiência de credenciais. Estou dizendo ao PAM que o módulo está falhando porque não tem tudo o que precisa para autenticar totalmente o usuário. Agora, supondo que seu módulo seja chamado my_module
, uma configuração possível seria:
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
Aqui estão os detalhes:
Primeiro, a solicitação é processada
my_module
. Várias possibilidades aqui:- Primeiro login: seu módulo retornou
PAM_CRED_INSUFFICIENT
. Este caso écapturadopelo PAM (através decred_insufficient
), caso em que é configurado para marcar a cadeia como bem-sucedida (ok
), mas paracontinue. - Esse não foi o primeiro login, você realizou
custom_auth()
e foi um sucesso (devolveuPAM_SUCCESS
). Neste caso, encerramos a cadeia (done
) :acesso concedido. - Este não foi o primeiro login e
custom_auth()
não deu certo (PAM_AUTH_ERR
ou outros tipos de erros internos). Neste caso, pule as próximas 2 linhas (default=2
). A cadeia vai direto parapam_deny
, que sempre falha:acesso negado.
- Primeiro login: seu módulo retornou
No primeiro cenário, a cadeia segue para
pam_unix
. Duas possibilidades aqui:- A autenticação UNIX foi bem-sucedida. Isso marca a cadeia como bem-sucedida (
ok
) esegue para o próximo módulo. - A autenticação UNIX falha. O próximo módulo é ignorado (
default=1
) e a cadeia termina empam_deny
:acesso negado.
- A autenticação UNIX foi bem-sucedida. Isso marca a cadeia como bem-sucedida (
Se você chegar à terceira linha, significa que
my_module
terminou naPAM_CRED_INSUFFICIENT
primeira vez e deupam_unix
certo. Seu módulo é chamado novamente (// do something else here?
) comosufficient
. Duas possibilidades novamente:- Desta vez, seu módulo foi bem-sucedido:acesso concedido.
- O módulo falha novamente, mas por outro motivo que não a insuficiência de credenciais:acesso negado.
Você também pode querer executar código personalizadoapós autenticação UNIX, mesmo que tenha falhado. Para fazer isso, altere a segunda linha para:
auth [success=ok default=bad] pam_unix.so
Isso fará com que a cadeia passe por my_module
outro momento, não importa o que aconteça, mas a cadeia será marcada comofracassado. Mesmo que o seu módulo tenha sucesso aqui, a cadeia falhará.
Você também pode deixar seu módulo ciente de quantas vezes o chamamos em uma cadeia: diferencie a primeira chamada my_module
da segunda. Isso poderia ser feito facilmente com 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
Aqui, a segunda chamada para pam_sm_authenticate
receberá um argumento (através de argv
e argc
) que deve ajudá-lolocalizarseu módulo na cadeia em tempo de execução. É claro que sua firstLogin
condição deveria ser suficiente para fazer tal distinção.