Não deixe seu código executar toda a lógica: use o PAM e sua configuração primeiro para garantir que seu módulo seja executado nas melhores condições (isto é, não exija a cópia do código pam_unix
).
Primeiro, deixe-me sugerir outro pseudo código para o seu módulo:
pam_sm_authenticate() {
if (first_login) return PAM_CRED_INSUFFICIENT;
else custom_auth();
}
Aqui, considero que primeiro login seja um caso de insuficiência de credenciais. Estou dizendo ao PAM que o módulo está falhando porque não tem tudo de que precisa para autenticar completamente o usuário. Agora, supondo que seu módulo seja chamado de 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 passa por
my_module
. Várias possibilidades aqui:- Primeiro login: seu módulo retornou
PAM_CRED_INSUFFICIENT
. Este caso é capturado pelo PAM (por meio decred_insufficient
), caso em que está configurado para marcar a cadeia como bem-sucedida (ok
), mas para continuar . - Este não foi o primeiro login, você passou por
custom_auth()
e foi um sucesso (retornouPAM_SUCCESS
). Nesse caso, colocamos um fim na cadeia (done
): acesso concedido . - Este não foi o primeiro login, e
custom_auth()
não foi bem (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 passa para
pam_unix
. Duas possibilidades aqui:- A autenticação do UNIX é bem-sucedida. Isso marca a cadeia como bem-sucedida (
ok
) e passa para o próximo módulo . - A autenticação do UNIX falha. O próximo módulo é ignorado (
default=1
) e a cadeia termina empam_deny
: acesso negado .
- A autenticação do UNIX é bem-sucedida. Isso marca a cadeia como bem-sucedida (
-
Se você atingir a terceira linha, isso significa que
my_module
terminou comPAM_CRED_INSUFFICIENT
na primeira vez e quepam_unix
foi bem-sucedido. Seu módulo é chamado novamente (// do something else here?
) comosufficient
. Duas possibilidades novamente:- Desta vez, o seu módulo é 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 um código personalizado após a autenticação do UNIX , mesmo que tenha falhado. Para fazer isso, mude a segunda linha para:
auth [success=ok default=bad] pam_unix.so
Isso fará com que a cadeia passe por my_module
outra vez, não importa o que aconteça, mas a cadeia será marcada como falha . Mesmo que seu módulo seja bem-sucedido aqui, a cadeia falhará.
Você também pode tornar seu módulo ciente de quantas vezes o chamamos em uma cadeia: diferencie a primeira chamada para my_module
da segunda. Isso pode 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
), o que deve ajudá-lo a localizar seu módulo na cadeia em tempo de execução. Naturalmente, sua condição firstLogin
deve ser suficiente para fazer tal distinção.