3. Configuração do Cliente

O cliente já deve ter bibliotecas do OpenLDAP do Seção 2.1.3, “Configurando o Cliente”, mas se você estiver instalando várias máquinas clientes, precisará instalar o net/openldap24-client em cada um deles.

O FreeBSD requer que dois ports sejam instalados para autenticação em um servidor LDAP, security/pam_ldap e net/nss_ldap.

3.1. Autenticação

O security/pam_ldap é configurado através do /usr/local/etc/ldap.conf.

Nota:

Este é um arquivo diferente que o arquivo de configuração das funções da biblioteca OpenLDAP, /usr/local/etc/openldap/ldap.conf; no entanto, são necessárias muitas das mesmas opções; na verdade, é um superconjunto desse arquivo. Para o resto desta seção, referências a ldap.conf irão significar o arquivo /usr/local/etc/ldap.conf.

Assim, vamos querer copiar todos os nossos parâmetros de configuração originais do openldap/ldap.conf para o novo ldap.conf. Feito isso, queremos informar ao security/pam_ldap o que procurar no servidor de diretório.

Estamos identificando nossos usuários com o atributo uid. Para configurar isso (embora seja o padrão), defina a diretiva pam_login_attribute no ldap.conf:

Exemplo 4. Definindo pam_login_attribute
pam_login_attribute uid

Com esta definição, o security/pam_ldap pesquisará todo o diretório LDAP na base para o valor uid=username . Se encontrar uma e apenas uma entrada, ela tentará se vincular como aquele usuário com a senha que foi fornecida. Se vincular corretamente, então permitirá o acesso. Caso contrário, falhará.

Os usuários cujo shell não está em /etc/shells não poderão efetuar login. Isto é particularmente importante quando o Bash é definido como o shell do usuário no servidor LDAP. O Bash não está incluído em uma instalação padrão do FreeBSD. Quando instalado a partir de um pacote ou port, ele está localizado em /usr/local/bin/bash. Verifique se o caminho para o shell no servidor está definido corretamente:

% getent passwd username

Existem duas opções quando a saída mostra /bin/bash na última coluna. A primeira é alterar a entrada do usuário no servidor LDAP para /usr/local/bin/bash. A segunda opção é criar um link simbólico no computador cliente LDAP para que o Bash seja encontrado no local correto:

# ln -s /usr/local/bin/bash /bin/bash

Certifique-se de que /etc/shells contenha entradas para ambos /usr/local/bin/bash e /bin/bash. O usuário poderá então efetuar login no sistema com Bash como seu shell.

3.1.1. PAM

PAM, que significa Pluggable Authentication Modules, é o método pelo qual o FreeBSD autentica a maioria de suas sessões. Para dizer ao FreeBSD que desejamos usar um servidor LDAP, teremos que adicionar uma linha ao arquivo PAM apropriado.

Na maioria das vezes o arquivo PAM apropriado é /etc/pam.d/sshd, se você quiser usar SSH (lembre-se de definir as opções relevantes em /etc/ssh/sshd_config, caso contrário o SSH não usará o PAM).

Para usar o PAM para autenticação, adicione a linha

auth suficiente /usr/local/lib/pam_ldap.so no_warn

Exatamente onde essa linha aparece no arquivo e quais opções aparecem na quarta coluna, determine o comportamento exato do mecanismo de autenticação; veja pam.d(5)

Com essa configuração, você deve conseguir autenticar um usuário em um diretório LDAP. O PAM executará uma ligação com suas credenciais e, se for bem-sucedido, informará ao SSH para permitir o acesso.

No entanto, não é uma boa idéia permitir que todo usuário no diretório dentro de todo computador cliente. Com a configuração atual, tudo o que um usuário precisa para efetuar login em uma máquina é uma entrada LDAP. Felizmente, existem algumas maneiras de restringir o acesso do usuário.

O ldap.conf suporta uma diretiva pam_groupdn; Cada conta que se conecta a essa máquina precisa ser membro do grupo especificado aqui. Por exemplo, se você tem

pam_groupdn cn=servername,ou=accessgroups,dc=example,dc=org

em ldap.conf, somente os membros desse grupo poderão efetuar login. Entretanto, há algumas coisas a serem lembradas.

Os membros desse grupo são especificados em um ou mais atributos memberUid e cada atributo deve ter o nome distinto completo do membro. Então memberUid:someuser não funcionará; deve ser:

memberUid: uid=algum usuário, ou=pessoas, dc=exemplo, dc=org

Além disso, essa diretiva não é verificada no PAM durante a autenticação, ela é verificada durante o gerenciamento de contas, portanto, você precisará de uma segunda linha em seus arquivos PAM sob account. Isso exigirá, por sua vez, que todo usuário seja listado no grupo, o que não é necessariamente o que queremos. Para evitar o bloqueio de usuários que não estão no LDAP, você deve ativar o atributo ignore_unknown_user. Finalmente, você deve definir a opção ignore_authinfo_unavail para que você não fique bloqueado em todos os computadores quando o servidor LDAP estiver indisponível.

Seu pam.d/sshd pode acabar ficando assim:

Exemplo 5. Exemplo pam.d/sshd
auth            required        pam_nologin.so          no_warn
auth            sufficient      pam_opie.so             no_warn no_fake_prompts
auth            requisite       pam_opieaccess.so       no_warn allow_local
auth            sufficient      /usr/local/lib/pam_ldap.so      no_warn
auth            required        pam_unix.so             no_warn try_first_pass

account         required        pam_login_access.so
account         required        /usr/local/lib/pam_ldap.so      no_warn ignore_authinfo_unavail ignore_unknown_user

Nota:

Como estamos adicionando essas linhas especificamente para pam.d/sshd, isso só terá um efeito nas sessões SSH. Os usuários LDAP não poderão efetuar login no console. Para mudar este comportamento, examine os outros arquivos em /etc/pam.d e modifique-os de acordo.

3.2. Switch de serviço de nome

NSS é o serviço que mapeia atributos para nomes. Assim, por exemplo, se um arquivo é de propriedade do usuário 1001, um aplicativo consultará o NSS para o nome de 1001, e ele pode obter bob ou ted ou qualquer que seja o nome do usuário.

Agora que nossas informações sobre o usuário são mantidas no LDAP, precisamos dizer ao NSS para procurar lá quando perguntado.

O port net/nss_ldap faz isso. Ele usa o mesmo arquivo de configuração como security/pam_ldap e não deve precisar de nenhum parâmetro extra depois de instalado. Em vez disso, o que resta é simplesmente editar é /etc/nsswitch.conf para aproveitar o diretório. Simplesmente substitua as seguintes linhas:

group: compat
passwd: compat

com

group: files ldap
passwd: files ldap

Isso permitirá que você mapeie nomes de usuários para UIDs e UIDs para nomes de usuários.

Parabéns! Agora você deve ter autenticação LDAP em funcionamento.

3.3. Ressalvas

Infelizmente, a partir do momento em que isso foi escrito, o FreeBSD não suportava a mudança de senhas de usuário com passwd(1). Por causa disso, a maioria dos administradores estão deixando para implementar uma solução por conta própria. Eu forneço alguns exemplos aqui. Observe que, se você escrever seu próprio script de alteração de senha, há alguns problemas de segurança dos quais você deve estar ciente; veja Seção 4.3, “Armazenamento de Senha”

Exemplo 6. Script de shell para alteração de senhas
#!/bin/sh

stty -echo
read -p "Old Password: " oldp; echo
read -p "New Password: " np1; echo
read -p "Retype New Password: " np2; echo
stty echo

if [ "$np1" != "$np2" ]; then
  echo "Passwords do not match."
  exit 1
fi

ldappasswd -D uid="$USER",ou=people,dc=example,dc=org \
  -w "$oldp" \
  -a "$oldp" \
  -s "$np1"

Cuidado:

Esse script dificilmente faz qualquer verificação de erros, mas, o mais importante, é muito indiferente sobre como ele armazena suas senhas. Se você fizer algo assim, ajuste pelo menos o valor de sysctl security.bsd.see_other_uids:

# sysctl security.bsd.see_other_uids=0

Uma abordagem mais flexível (e provavelmente mais segura) pode ser usada escrevendo um programa personalizado, ou até mesmo uma interface web. A seguir, parte de uma biblioteca Ruby que pode alterar senhas LDAP. Ele vê o uso na linha de comando e na web.

Exemplo 7. Script Ruby para Alterar Senhas
require 'ldap'
require 'base64'
require 'digest'
require 'password' # ruby-password

ldap_server = "ldap.example.org"
luser = "uid=#{ENV['USER']},ou=people,dc=example,dc=org"

# get the new password, check it, and create a salted hash from it
def get_password
  pwd1 = Password.get("New Password: ")
  pwd2 = Password.get("Retype New Password: ")

  raise if pwd1 != pwd2
  pwd1.check # check password strength

  salt = rand.to_s.gsub(/0\./, '')
  pass = pwd1.to_s
  hash = "{SSHA}"+Base64.encode64(Digest::SHA1.digest("#{pass}#{salt}")+salt).chomp!
  return hash
end

oldp = Password.get("Old Password: ")
newp = get_password

# We'll just replace it.  That we can bind proves that we either know
# the old password or are an admin.

replace = LDAP::Mod.new(LDAP::LDAP_MOD_REPLACE | LDAP::LDAP_MOD_BVALUES,
                        "userPassword",
                        [newp])

conn = LDAP::SSLConn.new(ldap_server, 389, true)
conn.set_option(LDAP::LDAP_OPT_PROTOCOL_VERSION, 3)
conn.bind(luser, oldp)
conn.modify(luser, [replace])

Apesar de não ter a garantia de estar livre de falhas de segurança (a senha é mantida na memória, por exemplo), isso é mais limpo e mais flexível do que um simples script sh.

All FreeBSD documents are available for download at https://download.freebsd.org/ftp/doc/

Questions that are not answered by the documentation may be sent to <freebsd-questions@FreeBSD.org>.
Send questions about this document to <freebsd-doc@FreeBSD.org>.