Autenticar externamente o usuário na sessão do PAM / sessão do PAM na sessão do PAM

2

Existe uma maneira de autenticar um usuário de dentro de uma sessão personalizada do PAM?

Atualmente, estou escrevendo meu próprio módulo de autenticação PAM, que permite ao usuário fazer login por meio de um token externo. Este token deve ser gerado antes que o usuário possa efetuar login com meu módulo. Portanto, gostaria de voltar para a autenticação padrão do PAM quando não existir nenhum token e continuar com o código assim que o usuário for autenticado.

Isso é possível de alguma forma? No pseudo-código meu módulo se parece com isto:

pam_sm_authenticate() {
  if (first_login) {
    code_copied_from_pam_unix_to_authenticate_user();
    // do something else here?
  } else {
    custom_auth();
  }
}

Como uma solução rápida, eu copiei o código do módulo pam_unix do Linux para o meu e ele funciona. No entanto, isso não é muito satisfatório, pois incorre em muitas bibliotecas adicionais e também funcionará apenas enquanto o pam_unix não mudar. Eu preferiria abrir outro Sessão do PAM em minha sessão, mas não consegui que funcionasse.

    
por Sonny O'Rullivan 16.10.2014 / 19:48

1 resposta

2

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:

    1. Primeiro login: seu módulo retornou PAM_CRED_INSUFFICIENT . Este caso é capturado pelo PAM (por meio de cred_insufficient ), caso em que está configurado para marcar a cadeia como bem-sucedida ( ok ), mas para continuar .
    2. Este não foi o primeiro login, você passou por custom_auth() e foi um sucesso (retornou PAM_SUCCESS ). Nesse caso, colocamos um fim na cadeia ( done ): acesso concedido .
    3. 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 para pam_deny , que sempre falha: acesso negado .
  • No primeiro cenário, a cadeia passa para pam_unix . Duas possibilidades aqui:

    1. A autenticação do UNIX é bem-sucedida. Isso marca a cadeia como bem-sucedida ( ok ) e passa para o próximo módulo .
    2. A autenticação do UNIX falha. O próximo módulo é ignorado ( default=1 ) e a cadeia termina em pam_deny : acesso negado .
  • Se você atingir a terceira linha, isso significa que my_module terminou com PAM_CRED_INSUFFICIENT na primeira vez e que pam_unix foi bem-sucedido. Seu módulo é chamado novamente ( // do something else here? ) como sufficient . Duas possibilidades novamente:

    1. Desta vez, o seu módulo é bem-sucedido: acesso concedido .
    2. 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.

    
por 29.04.2015 / 13:39