                       Modulos de Autenticac,ao Plugaveis

  Dag-Erling Smo/rgrav

   Contributed by  
   Revisao: 374a3c75a7

   Copyright (c) 2001-2003 Networks Associates Technology, Inc.

   This article was written for the FreeBSD Project by ThinkSec AS and
   Network Associates Laboratories, the Security Research Division of Network
   Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"),
   as part of the DARPA CHATS research program.

   FreeBSD is a registered trademark of the FreeBSD Foundation.

   Linux is a registered trademark of Linus Torvalds.

   Motif, OSF/1, and UNIX are registered trademarks and IT DialTone and The
   Open Group are trademarks of The Open Group in the United States and other
   countries.

   Sun, Sun Microsystems, Java, Java Virtual Machine, JDK, JRE, JSP, JVM,
   Netra, OpenJDK, Solaris, StarOffice, SunOS and VirtualBox are trademarks
   or registered trademarks of Sun Microsystems, Inc. in the United States
   and other countries.

   Many of the designations used by manufacturers and sellers to distinguish
   their products are claimed as trademarks. Where those designations appear
   in this document, and the FreeBSD Project was aware of the trademark
   claim, the designations have been followed by the "(TM)" or the "(R)"
   symbol.

   Resumo

   Esse artigo descreve principios subjacentes e mecanismos da biblioteca de
   Modulos de Autenticac,ao Plugaveis (PAM), e explica como configurar, como
   integrar com outras aplicac,oes e como escrever novos modulos.

   [ Documento HTML em partes / Documento HTML completo ]

     ----------------------------------------------------------------------

   Indice

   1. Introduc,ao

   2. Termos e convenc,oes

   3. PAM Essencial

   4. Configurac,ao do PAM

   5. Modulos PAM do FreeBSD

   6. Programac,ao de Aplicac,ao PAM

   7. Programac,ao de Modulos PAM

   A. Exemplo de Aplicac,ao PAM

   B. Exemplo do modulo PAM

   C. Exemplo de func,ao de conversac,ao PAM

   Leitura Adicional

1. Introduc,ao

   A biblioteca dos Modulos de Autenticac,ao Plugaveis (PAM) e uma API
   generalizada para servic,os relacionados com autenticac,oes as quais
   permitem ao administrador de sistema adicionar um novo metodo de
   autenticac,ao simplesmente pela instalac,ao de um novo modulo PAM, e
   modificar a politica de autenticac,ao pela edic,ao do arquivo de
   configurac,ao.

   O PAM foi definido e desenvolvido em 1995 por Vipin Samar e Charlie Lai da
   Sun Microsystems, e nao teve muitas mudanc,as ate hoje. Em 1997, o Open
   Group publicou a especificac,ao preliminar do X/Open Single Sign-on
   (XSSO), a qual padroniza a API do PAM e adiciona extensoes para
   autenticac,ao unica ou integrada. No momento da redac,ao deste documento,
   esta especificac,ao ainda nao tinha sido adotada como padrao.

   Apesar deste artigo focar primariamente no sistema FreeBSD 5.x, o qual usa
   o OpenPAM, ele podera ser igualmente aplicado ao FreeBSD 4.x, o qual usa o
   Linux-PAM, e a outros systemas operacionais, tais como o Linux e o
   Solaris(TM).

2. Termos e convenc,oes

  2.1. Definic,oes

   A terminologia em torno do PAM e bastante confusa. Nem o artigo original
   de Neither Samar e Lai nem a especificac,ao original do XSSO fizeram algum
   esforc,o para definir formalmente os termos de varios atores e entidades
   envolvidas no PAM, e os termos que eles usam (mas nao definem) sao algumas
   vezes duvidosos ou ambiguos. A primeira tentativa de estabelecer uma
   terminologia consistente e nao ambigua foi feita no artigo escrito por
   Andrew G. Morgan (autor do Linux-PAM) em 1999. A escolha da terminologia
   de Morgan foi um grande avanc,o, mas na opiniao deste autor, nao e
   perfeita. O que segue e uma tentativa, fortemente inspirada por Morgan, de
   definir termos precisos e nao ambiguos para todos os atores e entidades
   envolvidas no PAM.

   conta (account)

           Um conjunto de credenciais que o requerente esta solicitando ao
           mediador.

   requerente (applicant)

           Usuario ou entidade que solicita autenticac,ao

   Mediador (arbitrator)

           Usuario ou entidade a qual tem privilegios necessarios para
           verificar as credenciais do requerente e autorizar ou nao a
           solicitac,ao

   chain

           Uma sequencia de modulos que ira ser chamada em resposta a uma
           solicitac,ao do PAM. A chain inclui informac,oes sobre a ordem a
           qual invocar os modulos, quais argumentos foram passados e como
           interpretar os resultados.

   client

           A aplicac,ao responsavel por inicializar uma solicitac,ao de
           autenticac,ao em nome do requerente para obter as informac,oes
           necessarias da autenticac,ao dele.

   recursos

           Um dos quatro grupos basicos de funcionalidades fornecidos pelo
           PAM: autenticac,ao, gerenciamento de conta, gerenciamento de
           sessao e atualizac,ao de token de autenticac,ao.

   modulo

           Uma colec,ao de uma ou mais func,oes relacionadas implementando um
           recurso de autenticac,ao especifico, reunidas em um unico arquivo
           binario (normalmente carregavel dinamicamente) e identificadas por
           um unico nome.

   politica

           O conjunto completo de instruc,oes de configurac,ao que descrevem
           como lidar com solicitac,oes do PAM para um servic,o especifico.
           Uma politica normalmente consiste em quatro chains, uma para cada
           recurso, embora alguns servic,os nao utilizem os quatro recursos.

   servidor

           O aplicativo agindo em nome do mediador para conversar com o
           cliente, recuperar informac,oes de autenticac,ao, verificar as
           credenciais do requerente e conceder ou negar solicitac,oes.

   servic,o

           Classe de servidores que provem recursos similares ou relacionados
           e requerem autenticac,ao similar. As politicas do PAM sao
           definidas por servic,o, portanto, todos os servidores que
           reivindicam o mesmo nome de servic,o estarao sujeitos `a mesma
           politica.

   sessao

           O contexto com o qual servic,os sao apresentados para o requerente
           pelo servidor. Um dos quatro recursos do PAM, gerenciamento de
           sessao, e concedido exclusivamente configurando e derrubando esse
           contexto.

   token

           Um pedac,o de informac,ao associada `a conta, como uma senha sendo
           uma palavra ou uma frase, que o solicitante deve fornecer para
           provar sua identidade.

   transac,ao

           Uma sequencia de solicitac,oes do mesmo requerente para a mesma
           instancia do mesmo servidor, comec,ando com a configurac,ao de
           autenticac,ao e sessao e terminando com a desmontagem da sessao.

  2.2. Exemplos de uso

   Esta sec,ao tem como objetivo ilustrar os significados de alguns dos
   termos definidos acima por meio de alguns exemplos simples.

    2.2.1. O cliente e o servidor sao um

   Este exemplo simples mostra alice usando su(1) para se tornar root.

 % whoami
 alice
 % ls -l `which su`
 -r-sr-xr-x  1 root  wheel  10744 Dec  6 19:06 /usr/bin/su
 % su -
 Password: xi3kiune
 # whoami
 root

     * O requerente e alice.

     * A conta e root.

     * O processo su(1) e ao mesmo tempo, o cliente e o servidor.

     * O token de autenticac,ao e xi3kiune.

     * O mediador e root, e e por isso que su(1) possui setuid para root.

    2.2.2. O cliente e o servidor sao separados

   O exemplo abaixo mostra eve tentar iniciar uma conexao ssh(1) com
   login.example.com, solicitar para efetuar login como bob e ter exito. Bob
   deveria ter escolhido uma senha melhor!

 % whoami
 eve
 % ssh bob@login.example.com
 bob@login.example.com's password: god
 Last login: Thu Oct 11 09:52:57 2001 from 192.168.0.1
 Copyright (c) 1980, 1983, 1986, 1988, 1990, 1991, 1993, 1994
         The Regents of the University of California.  All rights reserved.
 FreeBSD 4.4-STABLE (LOGIN) #4: Tue Nov 27 18:10:34 PST 2001

 Welcome to FreeBSD!
 %

     * O requerente e eve.

     * O cliente e o processo ssh(1) de Eve.

     * O servidor e o processo sshd(8) em login.example.com

     * A conta e bob.

     * O token de autenticac,ao e god.

     * Embora isso nao seja mostrado neste exemplo, o mediador e root.

    2.2.3. Exemplo de politica

   A seguir, a politica padrao do FreeBSD para sshd:

 sshd    auth            required        pam_nologin.so  no_warn
 sshd    auth            required        pam_unix.so     no_warn try_first_pass
 sshd    account         required        pam_login_access.so
 sshd    account         required        pam_unix.so
 sshd    session         required        pam_lastlog.so  no_fail
 sshd    password        required        pam_permit.so

     * Esta politica se aplica ao servic,o sshd (que nao e necessariamente
       restrito ao servidor sshd(8)).

     * auth, account, session e password sao recursos.

     * pam_nologin.so, pam_unix.so, pam_login_access.so, pam_lastlog.so e
       pam_permit.so sao modulos. Fica claro neste exemplo que o pam_unix.so
       fornece pelo menos dois recursos (autenticac,ao e gerenciamento de
       conta).

3. PAM Essencial

  3.1. Recursos e Primitivas

   A API do PAM oferece seis primitivas de autenticac,ao diferentes agrupadas
   em quatro recursos, descritos abaixo.

   auth

           Autenticac,ao. Este recurso se preocupa em autenticar o requerente
           e estabelecer as credenciais da conta. Ele fornece duas
           primitivas:

              * pam_authenticate(3) autentica o requerente, geralmente
                solicitando um token de autenticac,ao e comparando-o com um
                valor armazenado em um banco de dados ou obtido de um
                servidor de autenticac,ao.

              * pam_setcred(3) estabelece credenciais de conta, como ID de
                usuario, associac,ao de grupo e limites de recursos.

   account

           Gerenciamento de contas. Esse recurso lida com problemas de
           disponibilidade de conta nao relacionados `a autenticac,ao, como
           restric,oes de acesso com base na hora do dia ou na carga de
           trabalho do servidor. Ele fornece uma unica primitiva:

              * pam_acct_mgmt(3) verifica se a conta solicitada esta
                disponivel.

   session

           Gerenciamento de sessao. Esse recurso lida com tarefas associadas
           `a configurac,ao e desmontagem da sessao, como a contabilizac,ao
           de login. Ele fornece duas primitivas:

              * pam_open_session(3) executa tarefas associadas `a
                configurac,ao da sessao: adiciona uma entrada nos bancos de
                dados utmp e wtmp, inicia um agente SSH, etc.

              * pam_close_session(3) executa tarefas associadas `a
                desmontagem da sessao: adiciona uma entrada nos bancos de
                dados utmp e wtmp, pare o agente SSH, etc.

   password

           Gerenciamento de senhas. Esse recurso e usado para alterar o token
           de autenticac,ao associado a uma conta, porque expirou ou porque o
           usuario deseja altera-lo. Ele fornece uma unica primitiva:

              * pam_chauthtok(3) altera o token de autenticac,ao,
                opcionalmente, verificando se e suficientemente dificil de
                adivinhar, se nao foi usado anteriormente etc.

  3.2. Modulos

   Modulos sao um conceito muito central no PAM; afinal, eles sao os "M" no
   "PAM". Um modulo PAM e um codigo de programa autocontido que implementa as
   primitivas em uma ou mais instalac,oes para um mecanismo especifico;
   possiveis mecanismos para o recurso de autenticac,ao, por exemplo, incluem
   os bancos de dados de senhas UNIX(R), NIS, LDAP e Radius.

    3.2.1. Nomeac,ao de Modulos

   O FreeBSD implementa cada mecanismo em um unico modulo, chamado
   pam_mechanism.so (por exemplo, pam_unix.so para o mecanismo UNIX(R).
   Outras implementac,oes `as vezes possuem modulos separados para
   instalac,oes separadas e incluem o nome do recurso, bem como o nome do
   mecanismo no nome do modulo. Para citar um exemplo, Solaris(TM) tem um
   modulo pam_dial_auth.so.1 que e comumente usado para autenticar usuarios
   de conexoes discadas.

    3.2.2. Versionando Modulos

   A implementac,ao original do PAM no FreeBSD, baseada no Linux-PAM, nao
   utilizou numeros de versao para os modulos PAM. Isso normalmente causaria
   problemas com aplicativos legados, que poderiam estar vinculados a versoes
   mais antigas das bibliotecas do sistema, pois nao havia como carregar uma
   versao correspondente dos modulos necessarios.

   O OpenPAM, por outro lado, procura por modulos que possuam o mesmo numero
   de versao que a biblioteca PAM (atualmente 2), e so retorna a um modulo
   nao versionado se nenhum modulo versionado puder ser carregado. Assim, os
   modulos legados podem ser fornecidos para aplicativos legados, permitindo
   que novos aplicativos (ou recem-construidos) aproveitem os modulos mais
   recentes.

   Embora os modulos PAM do Solaris(TM) normalmente tenham um numero de
   versao, eles nao sao realmente versionados, porque o numero e uma parte do
   nome do modulo e deve ser incluido na configurac,ao.

  3.3. Cadeias e Politicas

   Quando um servidor inicia uma transac,ao PAM, a biblioteca PAM tenta
   carregar uma politica para o servic,o especificado na chamada
   pam_start(3). A politica especifica como as solicitac,oes de autenticac,ao
   devem ser processadas e definidas em um arquivo de configurac,ao. Este e o
   outro conceito central no PAM: a possibilidade de o administrador ajustar
   a politica de seguranc,a do sistema (no sentido mais amplo da palavra)
   simplesmente editando um arquivo de texto.

   Uma politica consiste em quatro cadeias, uma para cada uma dos quatro
   recursos do PAM. Cada chain e uma sequencia de instruc,oes de
   configurac,ao, cada uma especificando um modulo para invocar, alguns
   parametros (opcionais) para passar para o modulo e um sinalizador de
   controle que descreve como interpretar o codigo de retorno do modulo.

   Entender os sinalizadores de controle e essencial para entender os
   arquivos de configurac,ao do PAM. Existem quatro diferentes flags de
   controle:

   binding

           Se o modulo tiver exito e nenhum modulo anterior na chain tiver
           falhado, a chain sera encerrada imediatamente e a solicitac,ao
           sera concedida. Se o modulo falhar, o resto da chain e executado,
           mas a solicitac,ao e negada no final.

           Esta flag de controle foi introduzida pela Sun no Solaris(TM)9
           (SunOS(TM) 5.9), e tambem e suportado pelo OpenPAM.

   required

           Se o modulo tiver exito, o restante da chain sera executada e a
           solicitac,ao sera concedida, a menos que algum outro modulo falhe.
           Se o modulo falhar, o restante da chain tambem sera executado, mas
           a solicitac,ao sera negada no final.

   requisite

           Se o modulo for tiver exito, o restante da chain sera executado e
           a solicitac,ao sera concedida, a menos que algum outro modulo
           falhe. Se o modulo falhar, a chain sera encerrada imediatamente e
           a solicitac,ao sera negada.

   sufficient

           Se o modulo tiver exito e nenhum modulo anterior na chain tiver
           falhado, a chain sera encerrada imediatamente e a solicitac,ao
           sera concedida. Se o modulo falhar, o modulo sera ignorado e o
           resto da chain sera executado.

           Como a semantica dessa flag pode ser um pouco confusa,
           especialmente quando ela e usada para o ultimo modulo em uma
           chain, e recomendado que a flag de controle binding seja usada em
           seu lugar, se a implementac,ao o suportar.

   optional

           O modulo e executado, mas seu resultado e ignorado. Se todos os
           modulos em uma chain estiverem marcados como optional, todas as
           solicitac,oes serao sempre concedidas.

   Quando um servidor invoca uma das seis primitivas PAM, o PAM recupera a
   chain para o recurso ao qual a primitiva pertence, e invoca cada um dos
   modulos listados na chain, na ordem em que estao listados, ate chegar ao
   fim ou determina que nenhum processamento adicional e necessario (porque
   um modulo binding ou sufficient teve exito, ou porque um modulo requisite
   falhou.) O pedido e concedido se e somente se pelo menos um modulo foi
   chamado e todos os modulos nao opcionais tiveram exito.

   Note que e possivel, embora nao muito comum, ter o mesmo modulo listado
   varias vezes na mesma chain. Por exemplo, um modulo que procura nomes de
   usuario e senhas em um servidor de diretorio pode ser chamado varias vezes
   com parametros diferentes, especificando diferentes servidores de
   diretorios para contato. O PAM trata diferentes ocorrencias do mesmo
   modulo na mesma chain de modulos diferentes e nao relacionados.

  3.4. Transac,oes

   O ciclo de vida de uma transac,ao tipica do PAM e descrito abaixo. Observe
   que, se qualquer uma dessas etapas falhar, o servidor devera informar uma
   mensagem de erro adequada ao cliente e anular a transac,ao.

    1. Se necessario, o servidor obtem as credenciais do mediador por meio de
       um mecanismo independente do PAM - mais comumente em virtude de ter
       sido iniciado por root ou de ser setuid root.

    2. O servidor chama pam_start(3) para inicializar a biblioteca PAM,
       especificar seu nome de servic,o e a conta de destino e registrar uma
       func,ao de conversac,ao adequada.

    3. O servidor obtem varias informac,oes relacionadas `a transac,ao (como
       o nome de usuario do requerente e o nome do host no qual o cliente e
       executado) e o envia ao PAM usando pam_set_item(3).

    4. O servidor chama pam_authenticate(3) para autenticar o requerente.

    5. O servidor chama pam_acct_mgmt(3) para verificar se a conta solicitada
       esta disponivel e e valida. Se a senha estiver correta mas expirar,
       pam_acct_mgmt(3) retornara PAM_NEW_AUTHTOK_REQD em vez de PAM_SUCCESS.

    6. Se a etapa anterior retornasse PAM_NEW_AUTHTOK_REQD, o servidor agora
       chamaria pam_chauthtok(3) para forc,ar o cliente a alterar o token de
       autenticac,ao para a conta solicitada.

    7. Agora que o requerente foi devidamente autenticado, o servidor chama
       pam_setcred(3) para estabelecer as credenciais da conta solicitada. E
       capaz de fazer isso porque age em nome do mediador e possui as
       credenciais do madiador.

    8. Depois que as credenciais corretas forem estabelecidas, o servidor
       chamara pam_open_session(3) para configurar a sessao.

    9. O servidor agora executa qualquer servic,o solicitado pelo cliente -
       por exemplo, fornecer ao requerente um shell.

   10. Quando o servidor terminar de atender ao cliente, ele chamara
       pam_close_session(3) para derrubar a sessao.

   11. Finalmente, o servidor chama pam_end(3) para notificar a biblioteca
       PAM que ela esta pronta e que pode liberar quaisquer recursos alocados
       no curso da transac,ao.

4. Configurac,ao do PAM

  4.1. Arquivos de politica do PAM

    4.1.1. O arquivo /etc/pam.conf

   O arquivo de politica tradicional do PAM e /etc/pam.conf. Este arquivo
   contem todas as politicas do PAM para o seu sistema. Cada linha do arquivo
   descreve uma etapa em uma chain, conforme mostrado abaixo:

 login   auth    required        pam_nologin.so  no_warn

   Os campos estao, na ordem: nome do servic,o, nome do recurso, flag de
   controle, nome do modulo e argumentos do modulo. Quaisquer campos
   adicionais sao interpretados como argumentos adicionais do modulo.

   Uma chain separada e construida para cada par de servic,o/recurso,
   portanto, embora a ordem na qual as linhas para o mesmo servic,o e recurso
   aparec,am seja significativa, a ordem na qual os servic,os e recursos
   individuais sao listados nao e. Os exemplos no artigo original do PAM
   agruparam as linhas de configurac,ao por recurso, e o suporte do
   Solaris(TM) ao pam.conf ainda faz isso, mas a configurac,ao de ac,oes do
   FreeBSD configura as linhas por servic,o. De qualquer maneira esta bem; De
   qualquer forma, faz o mesmo sentido.

    4.1.2. O diretorio /etc/pam.d

   O OpenPAM e o Linux-PAM suportam um mecanismo de configurac,ao
   alternativo, que e o mecanismo preferido no FreeBSD. Neste esquema, cada
   politica esta contida em um arquivo separado com o nome do servic,o ao
   qual se aplica. Esses arquivos sao armazenados em /etc/pam.d/.

   Esses arquivos de politicas por servic,o possuem apenas quatro campos, em
   vez de cinco no pam.conf: o campo nome do servic,o e omitido. Assim, em
   vez da linha de exemplo no pam.conf da sec,ao anterior, a seguinte linha
   deve estar em /etc/pam.d/login:

 auth    required        pam_nologin.so  no_warn

   Como consequencia dessa sintaxe simplificada, e possivel usar a mesma
   politica para varios servic,os vinculando cada nome de servic,o a um mesmo
   arquivo de politica. Por exemplo, para usar a mesma politica para os
   servic,os su e sudo, pode-se fazer o seguinte:

 # cd /etc/pam.d
 # ln -s su sudo

   Isso funciona porque o nome do servic,o e determinado a partir do nome do
   arquivo em vez de ser especificado no arquivo de politicas, portanto, o
   mesmo arquivo pode ser usado para varios servic,os com nomes diferentes.

   Como a politica de cada servic,o e armazenada em um arquivo separado, o
   mecanismo pam.d tambem facilita a instalac,ao de politicas adicionais para
   pacotes de software de terceiros.

    4.1.3. A ordem de pesquisa da politica

   Como vimos acima, as politicas do PAM podem ser encontradas em varios
   lugares. O que acontece se as politicas para o mesmo servic,o existirem em
   varios lugares?

   E essencial entender que o sistema de configurac,ao do PAM esta centrado
   em chains.

  4.2. Quebra de uma linha de configurac,ao

   Como explicado em Sec,ao 4.1, "Arquivos de politica do PAM", cada linha em
   /etc/pam.conf consiste em quatro ou mais campos: o nome do servic,o, o
   nome do recurso, a flag de controle, o nome do modulo e nenhum ou mais
   argumentos do modulo.

   O nome do servic,o e geralmente (embora nem sempre) o nome do aplicativo
   ao qual a instruc,ao se aplica. Se nao tiver certeza, consulte a
   documentac,ao do aplicativo individual para determinar qual nome de
   servic,o ele usa.

   Note que se voce usar /etc/pam.d/ em vez de /etc/pam.conf, o nome do
   servic,o e especificado pelo nome do arquivo de politica e omitido a
   partir das linhas de configurac,ao atuais, que entao comec,am com o nome
   da instalac,ao.

   O recurso e uma das quatro palavras-chave do recurso descritas em
   Sec,ao 3.1, "Recursos e Primitivas".

   Da mesma forma, a flag de controle e uma das quatro palavras-chave
   descritas em Sec,ao 3.3, "Cadeias e Politicas", descrevendo como
   interpretar o codigo de retorno do modulo. O Linux-PAM suporta uma sintaxe
   alternativa que permite especificar a ac,ao para associar com cada codigo
   de retorno possivel, mas isso deve ser evitado, pois nao e padrao e esta
   intimamente ligado `a forma como o Linux-PAM envia chamadas de servic,o
   (que difere muito da maneira que Solaris(TM) e OpenPAM fazem isso). Nao
   surpreendentemente, o OpenPAM nao suporta esta sintaxe.

  4.3. Politicas

   Para configurar o PAM corretamente, e essencial entender como as politicas
   sao interpretadas.

   Quando um aplicativo chama pam_start(3), a biblioteca PAM carrega a
   diretiva do servic,o especificado e constroi quatro chains de modulos (uma
   para cada recurso). Se uma ou mais dessas chains estiverem vazias, as
   chains correspondentes da politica para o outro servic,o sao substituidas.

   Quando o aplicativo chama mais tarde uma das seis primitivas PAM, a
   biblioteca PAM recupera a chain para o recurso correspondente e chama a
   func,ao de servic,o apropriado em cada modulo listado na chain, na ordem
   em que foram listadas na configurac,ao. Apos cada chamada para uma func,ao
   de servic,o, o tipo de modulo e o codigo de erro retornado pela func,ao de
   servic,o sao usados &#8203;&#8203;para determinar o que acontece a seguir.
   Com algumas excec,oes, discutidas abaixo, a tabela a seguir se aplica:

   Tabela 1. Resumo de execuc,ao da cadeia PAM

   +-------------------------------------------------------------------+
   |            |    PAM_SUCCESS    | PAM_IGNORE |        other        |
   |------------+-------------------+------------+---------------------|
   | binding    | if (!fail) break; | -          | fail = true;        |
   |------------+-------------------+------------+---------------------|
   | required   | -                 | -          | fail = true;        |
   |------------+-------------------+------------+---------------------|
   | requisite  | -                 | -          | fail = true; break; |
   |------------+-------------------+------------+---------------------|
   | sufficient | if (!fail) break; | -          | -                   |
   |------------+-------------------+------------+---------------------|
   | optional   | -                 | -          | -                   |
   +-------------------------------------------------------------------+

   Se fail for true no final de uma chain, ou quando um "break" for atingido,
   o dispatcher retornara o codigo de erro retornado pelo primeiro modulo que
   falhou. Caso contrario, retorna PAM_SUCCESS.

   A primeira excec,ao e que o codigo de erro PAM_NEW_AUTHTOK_REQD e tratado
   como um sucesso, exceto que se nenhum modulo falhar e pelo menos um modulo
   retornar PAM_NEW_AUTHTOK_REQD, o dispatcher retornara
   PAM_NEW_AUTHTOK_REQD.

   A segunda excec,ao e que pam_setcred(3) trata os modulos binding e
   sufficient como se eles fossem required.

   A terceira e ultima excec,ao e que pam_chauthtok(3) executa a chain
   inteira duas vezes (uma vez para verificac,oes preliminares e uma vez para
   definir a senha), e na fase preliminar, ele trata os modulos binding e
   sufficient como se fossem required.

5. Modulos PAM do FreeBSD

  5.1. pam_deny(8)

   O modulo pam_deny(8) e um dos modulos mais simples disponiveis; responde a
   qualquer pedido com PAM_AUTH_ERR. E util para desabilitar rapidamente um
   servic,o (adiciona-lo ao topo de cada chain) ou para encerrar chains de
   modulos sufficient.

  5.2. pam_echo(8)

   O modulo pam_echo(8) simplesmente passa seus argumentos para a func,ao de
   conversac,ao como uma mensagem PAM_TEXT_INFO. E principalmente util para
   depurac,ao, mas tambem pode servir para exibir mensagens como "O acesso
   nao autorizado sera processado" antes de iniciar o procedimento de
   autenticac,ao.

  5.3. pam_exec(8)

   O modulo pam_exec(8) leva seu primeiro argumento a ser o nome de um
   programa a ser executado, e os argumentos restantes sao passados
   &#8203;&#8203;para esse programa como argumentos de linha de comando. Uma
   aplicac,ao possivel e usa-lo para executar um programa no momento do
   login, que monta o diretorio pessoal do usuario.

  5.4. pam_ftpusers(8)

   The pam_ftpusers(8) module

  5.5. pam_group(8)

   O modulo pam_group(8) aceita ou rejeita os requerentes com base em sua
   participac,ao em um determinado grupo de arquivos (normalmente wheel para
   su(1)). Ele e destinado principalmente para manter o comportamento
   tradicional do su(1) do BSD, mas tem muitos outros usos, como excluir
   determinados grupos de usuarios de um servic,o particular.

  5.6. pam_guest(8)

   O modulo pam_guest(8) permite logins convidados usando nomes de login
   fixos. Varios requerimentos podem ser colocados na senha, mas o
   comportamento padrao e permitir qualquer senha, desde que o nome de login
   seja o de uma conta de convidado. O modulo pam_guest(8) pode ser
   facilmente utilizado para implementar logins FTP anonimos.

  5.7. pam_krb5(8)

   O modulo pam_krb5(8)

  5.8. pam_ksu(8)

   O modulo pam_ksu(8)

  5.9. pam_lastlog(8)

   O modulo pam_lastlog(8)

  5.10. pam_login_access(8)

   O modulo pam_login_access(8) fornece uma implementac,ao da primitiva de
   gerenciamento de contas que impoe as restric,oes de login especificadas na
   tabela login.access(5).

  5.11. pam_nologin(8)

   O modulo pam_nologin(8) recusa logins nao-root quando existe um
   /var/run/nologin. Este arquivo e normalmente criado por shutdown(8) quando
   restam menos de cinco minutos ate o horario de encerramento programado.

  5.12. pam_opie(8)

   O modulo pam_opie(8) implementa o metodo de autenticac,ao opie(4). O
   sistema opie(4) e um mecanismo de desafio-resposta em que a resposta a
   cada desafio e uma func,ao direta do desafio e uma frase-senha, entao a
   resposta pode ser facilmente computada "just in time" por qualquer pessoa
   que possua a senha, eliminando a necessidade de listas de senhas. Alem
   disso, como opie(4) nunca reutiliza um desafio que tenha sido respondido
   corretamente, ele nao e vulneravel a ataques de repetic,ao.

  5.13. pam_opieaccess(8)

   O modulo pam_opieaccess(8) e um modulo complementar para pam_opie(8). Sua
   finalidade e impor as restric,oes codificadas em opieaccess(5), que
   regulam as condic,oes sob as quais um usuario que normalmente se
   autenticaria usando opie(4) tem permissao para usar metodos alternativos.
   Isso geralmente e usado para proibir o uso de autenticac,ao de senha de
   hosts nao confiaveis.

   Para ser eficaz, o modulo pam_opieaccess(8) deve ser listado como
   requisite imediatamente apos uma entrada sufficient para pam_opie(8), e
   antes de qualquer outro modulo, na chain auth.

  5.14. pam_passwdqc(8)

   O modulo pam_passwdqc(8)

  5.15. pam_permit(8)

   O modulo pam_permit(8) e um dos modulos mais simples disponiveis; responde
   a qualquer pedido com PAM_SUCCESS. E util como um espac,o reservado para
   servic,os onde uma ou mais chains estariam vazias.

  5.16. pam_radius(8)

   O modulo pam_radius(8)

  5.17. pam_rhosts(8)

   O modulo pam_rhosts(8)

  5.18. pam_rootok(8)

   O modulo pam_rootok(8) reporta sucesso se e somente se o ID do usuario
   real do processo que o chama (que e assumido como sendo executado pelo
   requerente) e 0. Isso e util para servic,os que nao estao em rede, como
   su(1) ou passwd(1), para o qual o root deve ter acesso automatico.

  5.19. pam_securetty(8)

   O modulo pam_securetty(8)

  5.20. pam_self(8)

   O modulo pam_self(8) reporta sucesso se, e somente se, os nomes do
   requerente coincidem com os da conta de destino. E mais util para
   servic,os que nao estao em rede, como su(1), onde a identidade do
   requerente pode ser facilmente verificada.

  5.21. pam_ssh(8)

   O modulo pam_ssh(8) fornece servic,os de autenticac,ao e de sessao. O
   servic,o de autenticac,ao permite que os usuarios que tenham chaves
   secretas SSH protegidas por senha em seu diretorio ~/.ssh se autentiquem
   digitando sua frase secreta. O servic,o de sessao inicia o ssh-agent(1) e
   o pre-carrega com as chaves que foram descriptografadas na fase de
   autenticac,ao. Esse recurso e particularmente util para logins locais,
   seja em X (usando xdm(1) ou outro gerenciador de login X que reconhece o
   PAM ) ou no console.

  5.22. pam_tacplus(8)

   O modulo pam_tacplus(8)

  5.23. pam_unix(8)

   O modulo pam_unix(8) implementa a autenticac,ao de senha UNIX(R)
   tradicional, usando getpwnam(3) para obter a senha da conta de destino e
   compara-la com a fornecida pelo requerente. Ele tambem fornece servic,os
   de gerenciamento de conta (impondo tempos de expirac,ao de conta e senha)
   e servic,os de alterac,ao de senha. Este e provavelmente o modulo mais
   util, ja que a grande maioria dos administradores desejara manter um
   comportamento historico para pelo menos alguns servic,os.

6. Programac,ao de Aplicac,ao PAM

   Esta sec,ao ainda nao foi escrita.

7. Programac,ao de Modulos PAM

   Esta sec,ao ainda nao foi escrita.

A. Exemplo de Aplicac,ao PAM

   O que vem a seguir e uma implementac,ao minima de su(1) utilizando o PAM.
   Observe que ele usa a func,ao de conversa openpam_ttyconv(3) especifica do
   OpenPAM, que e prototipada em security/openpam.h . Se voce deseja
   construir este aplicativo em um sistema com uma biblioteca PAM diferente,
   voce tera que fornecer sua propria func,ao de conversac,ao. Uma func,ao de
   conversa robusta e surpreendentemente dificil de implementar; o
   apresentado em Apendice C, Exemplo de func,ao de conversac,ao PAM e um bom
   ponto de partida, mas nao deve ser usado em aplicac,oes do mundo real.

 /*-
  * Copyright (c) 2002,2003 Networks Associates Technology, Inc.
  * All rights reserved.
  *
  * This software was developed for the FreeBSD Project by ThinkSec AS and
  * Network Associates Laboratories, the Security Research Division of
  * Network Associates, Inc.  under DARPA/SPAWAR contract N66001-01-C-8035
  * ("CBOSS"), as part of the DARPA CHATS research program.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  * 3. The name of the author may not be used to endorse or promote
  *    products derived from this software without specific prior written
  *    permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
  * $P4: //depot/projects/openpam/bin/su/su.c#10 $
  * $FreeBSD$
  */

 #include <sys/param.h>
 #include <sys/wait.h>

 #include <err.h>
 #include <pwd.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <syslog.h>
 #include <unistd.h>

 #include <security/pam_appl.h>
 #include <security/openpam.h>   /* for openpam_ttyconv() */

 extern char **environ;

 static pam_handle_t *pamh;
 static struct pam_conv pamc;

 static void
 usage(void)
 {

         fprintf(stderr, "Usage: su [login [args]]\n");
         exit(1);
 }

 int
 main(int argc, char *argv[])
 {
         char hostname[MAXHOSTNAMELEN];
         const char *user, *tty;
         char **args, **pam_envlist, **pam_env;
         struct passwd *pwd;
         int o, pam_err, status;
         pid_t pid;

         while ((o = getopt(argc, argv, "h")) != -1)
                 switch (o) {
                 case 'h':
                 default:
                         usage();
                 }

         argc -= optind;
         argv += optind;

         if (argc > 0) {
                 user = *argv;
                 --argc;
                 ++argv;
         } else {
                 user = "root";
         }

         /* initialize PAM */
         pamc.conv = &openpam_ttyconv;
         pam_start("su", user, &pamc, &pamh);

         /* set some items */
         gethostname(hostname, sizeof(hostname));
         if ((pam_err = pam_set_item(pamh, PAM_RHOST, hostname)) != PAM_SUCCESS)
                 goto pamerr;
         user = getlogin();
         if ((pam_err = pam_set_item(pamh, PAM_RUSER, user)) != PAM_SUCCESS)
                 goto pamerr;
         tty = ttyname(STDERR_FILENO);
         if ((pam_err = pam_set_item(pamh, PAM_TTY, tty)) != PAM_SUCCESS)
                 goto pamerr;

         /* authenticate the applicant */
         if ((pam_err = pam_authenticate(pamh, 0)) != PAM_SUCCESS)
                 goto pamerr;
         if ((pam_err = pam_acct_mgmt(pamh, 0)) == PAM_NEW_AUTHTOK_REQD)
                 pam_err = pam_chauthtok(pamh, PAM_CHANGE_EXPIRED_AUTHTOK);
         if (pam_err != PAM_SUCCESS)
                 goto pamerr;

         /* establish the requested credentials */
         if ((pam_err = pam_setcred(pamh, PAM_ESTABLISH_CRED)) != PAM_SUCCESS)
                 goto pamerr;

         /* authentication succeeded; open a session */
         if ((pam_err = pam_open_session(pamh, 0)) != PAM_SUCCESS)
                 goto pamerr;

         /* get mapped user name; PAM may have changed it */
         pam_err = pam_get_item(pamh, PAM_USER, (const void **)&user);
         if (pam_err != PAM_SUCCESS || (pwd = getpwnam(user)) == NULL)
                 goto pamerr;

         /* export PAM environment */
         if ((pam_envlist = pam_getenvlist(pamh)) != NULL) {
                 for (pam_env = pam_envlist; *pam_env != NULL; ++pam_env) {
                         putenv(*pam_env);
                         free(*pam_env);
                 }
                 free(pam_envlist);
         }

         /* build argument list */
         if ((args = calloc(argc + 2, sizeof *args)) == NULL) {
                 warn("calloc()");
                 goto err;
         }
         *args = pwd->pw_shell;
         memcpy(args + 1, argv, argc * sizeof *args);

         /* fork and exec */
         switch ((pid = fork())) {
         case -1:
                 warn("fork()");
                 goto err;
         case 0:
                 /* child: give up privs and start a shell */

                 /* set uid and groups */
                 if (initgroups(pwd->pw_name, pwd->pw_gid) == -1) {
                         warn("initgroups()");
                         _exit(1);
                 }
                 if (setgid(pwd->pw_gid) == -1) {
                         warn("setgid()");
                         _exit(1);
                 }
                 if (setuid(pwd->pw_uid) == -1) {
                         warn("setuid()");
                         _exit(1);
                 }
                 execve(*args, args, environ);
                 warn("execve()");
                 _exit(1);
         default:
                 /* parent: wait for child to exit */
                 waitpid(pid, &status, 0);

                 /* close the session and release PAM resources */
                 pam_err = pam_close_session(pamh, 0);
                 pam_end(pamh, pam_err);

                 exit(WEXITSTATUS(status));
         }

 pamerr:
         fprintf(stderr, "Sorry\n");
 err:
         pam_end(pamh, pam_err);
         exit(1);
 }

B. Exemplo do modulo PAM

   Segue-se uma implementac,ao minima de pam_unix(8), oferecendo apenas
   servic,os de autenticac,ao. Ele deve ser compilado e executado com a
   maioria das implementac,oes do PAM, mas aproveita as extensoes do OpenPAM,
   se disponivel: observe o uso de pam_get_authtok(3), que simplifica
   enormemente solicitando ao usuario uma senha.

 /*-
  * Copyright (c) 2002 Networks Associates Technology, Inc.
  * All rights reserved.
  *
  * This software was developed for the FreeBSD Project by ThinkSec AS and
  * Network Associates Laboratories, the Security Research Division of
  * Network Associates, Inc.  under DARPA/SPAWAR contract N66001-01-C-8035
  * ("CBOSS"), as part of the DARPA CHATS research program.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  * 3. The name of the author may not be used to endorse or promote
  *    products derived from this software without specific prior written
  *    permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
  * $P4: //depot/projects/openpam/modules/pam_unix/pam_unix.c#3 $
  * $FreeBSD$
  */

 #include <sys/param.h>

 #include <pwd.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
 #include <unistd.h>

 #include <security/pam_modules.h>
 #include <security/pam_appl.h>

 #ifndef _OPENPAM
 static char password_prompt[] = "Password:";
 #endif

 #ifndef PAM_EXTERN
 #define PAM_EXTERN
 #endif

 PAM_EXTERN int
 pam_sm_authenticate(pam_handle_t *pamh, int flags,
         int argc, const char *argv[])
 {
 #ifndef _OPENPAM
         struct pam_conv *conv;
         struct pam_message msg;
         const struct pam_message *msgp;
         struct pam_response *resp;
 #endif
         struct passwd *pwd;
         const char *user;
         char *crypt_password, *password;
         int pam_err, retry;

         /* identify user */
         if ((pam_err = pam_get_user(pamh, &user, NULL)) != PAM_SUCCESS)
                 return (pam_err);
         if ((pwd = getpwnam(user)) == NULL)
                 return (PAM_USER_UNKNOWN);

         /* get password */
 #ifndef _OPENPAM
         pam_err = pam_get_item(pamh, PAM_CONV, (const void **)&conv);
         if (pam_err != PAM_SUCCESS)
                 return (PAM_SYSTEM_ERR);
         msg.msg_style = PAM_PROMPT_ECHO_OFF;
         msg.msg = password_prompt;
         msgp = &msg;
 #endif
         for (retry = 0; retry < 3; ++retry) {
 #ifdef _OPENPAM
                 pam_err = pam_get_authtok(pamh, PAM_AUTHTOK,
                     (const char **)&password, NULL);
 #else
                 resp = NULL;
                 pam_err = (*conv->conv)(1, &msgp, &resp, conv->appdata_ptr);
                 if (resp != NULL) {
                         if (pam_err == PAM_SUCCESS)
                                 password = resp->resp;
                         else
                                 free(resp->resp);
                         free(resp);
                 }
 #endif
                 if (pam_err == PAM_SUCCESS)
                         break;
         }
         if (pam_err == PAM_CONV_ERR)
                 return (pam_err);
         if (pam_err != PAM_SUCCESS)
                 return (PAM_AUTH_ERR);

         /* compare passwords */
         if ((!pwd->pw_passwd[0] && (flags & PAM_DISALLOW_NULL_AUTHTOK)) ||
             (crypt_password = crypt(password, pwd->pw_passwd)) == NULL ||
             strcmp(crypt_password, pwd->pw_passwd) != 0)
                 pam_err = PAM_AUTH_ERR;
         else
                 pam_err = PAM_SUCCESS;
 #ifndef _OPENPAM
         free(password);
 #endif
         return (pam_err);
 }

 PAM_EXTERN int
 pam_sm_setcred(pam_handle_t *pamh, int flags,
         int argc, const char *argv[])
 {

         return (PAM_SUCCESS);
 }

 PAM_EXTERN int
 pam_sm_acct_mgmt(pam_handle_t *pamh, int flags,
         int argc, const char *argv[])
 {

         return (PAM_SUCCESS);
 }

 PAM_EXTERN int
 pam_sm_open_session(pam_handle_t *pamh, int flags,
         int argc, const char *argv[])
 {

         return (PAM_SUCCESS);
 }

 PAM_EXTERN int
 pam_sm_close_session(pam_handle_t *pamh, int flags,
         int argc, const char *argv[])
 {

         return (PAM_SUCCESS);
 }

 PAM_EXTERN int
 pam_sm_chauthtok(pam_handle_t *pamh, int flags,
         int argc, const char *argv[])
 {

         return (PAM_SERVICE_ERR);
 }

 #ifdef PAM_MODULE_ENTRY
 PAM_MODULE_ENTRY("pam_unix");
 #endif

C. Exemplo de func,ao de conversac,ao PAM

   A func,ao de conversac,ao apresentada abaixo e uma versao bastante
   simplificada do openpam_ttyconv() do OpenPAM. Ele e totalmente funcional e
   deve dar ao leitor uma boa ideia de como uma func,ao de conversa deve se
   comportar, mas e simples demais para uso no mundo real. Mesmo se voce nao
   estiver usando o OpenPAM, sinta-se `a vontade para baixar o codigo-fonte e
   adaptar openpam_ttyconv(3) aos seus usos; acreditamos que seja tao robusto
   quanto uma func,ao de conversa orientada para tty pode razoavelmente ser.

 /*-
  * Copyright (c) 2002 Networks Associates Technology, Inc.
  * All rights reserved.
  *
  * This software was developed for the FreeBSD Project by ThinkSec AS and
  * Network Associates Laboratories, the Security Research Division of
  * Network Associates, Inc.  under DARPA/SPAWAR contract N66001-01-C-8035
  * ("CBOSS"), as part of the DARPA CHATS research program.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  * 3. The name of the author may not be used to endorse or promote
  *    products derived from this software without specific prior written
  *    permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
  * $FreeBSD$
  */

 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>

 #include <security/pam_appl.h>

 int
 converse(int n, const struct pam_message **msg,
         struct pam_response **resp, void *data)
 {
         struct pam_response *aresp;
         char buf[PAM_MAX_RESP_SIZE];
         int i;

         data = data;
         if (n <= 0 || n > PAM_MAX_NUM_MSG)
                 return (PAM_CONV_ERR);
         if ((aresp = calloc(n, sizeof *aresp)) == NULL)
                 return (PAM_BUF_ERR);
         for (i = 0; i < n; ++i) {
                 aresp[i].resp_retcode = 0;
                 aresp[i].resp = NULL;
                 switch (msg[i]->msg_style) {
                 case PAM_PROMPT_ECHO_OFF:
                         aresp[i].resp = strdup(getpass(msg[i]->msg));
                         if (aresp[i].resp == NULL)
                                 goto fail;
                         break;
                 case PAM_PROMPT_ECHO_ON:
                         fputs(msg[i]->msg, stderr);
                         if (fgets(buf, sizeof buf, stdin) == NULL)
                                 goto fail;
                         aresp[i].resp = strdup(buf);
                         if (aresp[i].resp == NULL)
                                 goto fail;
                         break;
                 case PAM_ERROR_MSG:
                         fputs(msg[i]->msg, stderr);
                         if (strlen(msg[i]->msg) > 0 &&
                             msg[i]->msg[strlen(msg[i]->msg) - 1] != '\n')
                                 fputc('\n', stderr);
                         break;
                 case PAM_TEXT_INFO:
                         fputs(msg[i]->msg, stdout);
                         if (strlen(msg[i]->msg) > 0 &&
                             msg[i]->msg[strlen(msg[i]->msg) - 1] != '\n')
                                 fputc('\n', stdout);
                         break;
                 default:
                         goto fail;
                 }
         }
         *resp = aresp;
         return (PAM_SUCCESS);
  fail:
         for (i = 0; i < n; ++i) {
                 if (aresp[i].resp != NULL) {
                         memset(aresp[i].resp, 0, strlen(aresp[i].resp));
                         free(aresp[i].resp);
                 }
         }
         memset(aresp, 0, n * sizeof *aresp);
         *resp = NULL;
         return (PAM_CONV_ERR);
 }

Leitura Adicional

  Papers

   Tornando os Servic,os de Login Independentes das Tecnologias de
   Autenticac,ao. Vipin Samar e Charlie Lai. Sun Microsystems.

   Especificac,ao Preliminar do X/Open Single Sign-on. O grupo aberto.
   1-85912-144-6. Junho de 1997.

   Modulos de Autenticac,ao Plugaveis. Andrew G. Morgan. 06-10-1999.

  Manuais do usuario

   Administrac,ao do PAM. Sun Microsystems.

  Paginas Web Relacionadas

   Homepage do OpenPAM. Dag-Erling Smo/rgrav. ThinkSec AS.

   Pagina inicial do Linux-PAM. Andrew G. Morgan.

   Homepage do Solaris PAM. Sun Microsystems.
