validador de nome distinto LDAP

4

Existe uma biblioteca, programa ou regex simples para verificar se um DN especificado na entrada está bem formado?

Exemplo: INPUT: gerente, ou = empresa, dc = net --- > SAÍDA: não bem formada

ENTRADA: cn = gerente, ou = empresa, dc = rede --- > SAÍDA: bem formada

    
por andPat 31.10.2013 / 17:47

4 respostas

7

Em perl, com Net::LDAP é quase trivial:

#!/usr/bin/perl
use strict;
use warnings;
use Net::LDAP::Util qw/canonical_dn/;
foreach my $dn (@ARGV) {
   if (!defined(canonical_dn($dn))) { print "not well formed: $dn\n"; }
   else                             { print "well formed: $dn\n"; }
}

Então:

$ perl ldapdn.pl "manager, ou=company, dc=net" "cn=manager, ou=company, dc=net"
not well formed: manager, ou=company, dc=net
well formed: cn=manager, ou=company, dc=net

Existem várias funções que validam DNs, ldap_explode_dn() também pode ser útil se você deseja normalizar e processar DNs ainda mais.

É importante notar que "bem formado" e "válido" não são a mesma coisa, já que um DN sintaticamente bem formado pode não corresponder ao esquema de um determinado LDAP DIT e, portanto, ser rejeitado.

Se você tiver o OpenLDAP, qualquer versão recente deve vir com um programa slapdn . Isso faz a verificação do esquema adequada, mas você deve ter um viável slapd.conf e um esquema configurado no sistema que você executa naturalmente (o que pode exigir sua execução como root ou um usuário especial devido a permissões de arquivo arquivos de configuração operacional).

$ /usr/local/sbin/slapdn  -v "cn=manager, ou=company, dc=net"
DN: <cn=manager, ou=company, dc=net> check succeeded
normalized: <cn=manager,ou=company,dc=net>
pretty:     <cn=manager,ou=company,dc=net>

(Se você tiver o OpenLDAP construído a partir do código-fonte, ele também vem com um programa dntest criado como parte de seu conjunto de testes. Ele só analisa DNs, nenhuma verificação de esquema. Infelizmente não possui um código de erro utilizável e parece ocasionalmente indicar DNs malformados com um segfault ...)

E finalmente, a abordagem regex. Como sugerido por @ voretaq7, você pode usar o ABNF de RFC 4514 , embora você também precise das sintaxes básicas de RFC 4512 (§1.4). Execute aqueles que qualquer conversor ABNF para ERE (por exemplo, abnf2regex , implementado em Java), e para fora ele aparece. Eu não vou colá-lo aqui, é aproximadamente 4k de ruído de linha. Você pode quebrar a porca inteira com abnf2regex embora:

$ java -jar abnf2regex.jar -t distinguishedName \
        "cn=manager,ou=company,dc=net" rfc4512.abnf rfc4514dn.abnf
Rule "distinguishedName" matches: cn=manager,ou=company,dc=net
Rule: [relativeDistinguishedName *(COMMA relativeDistinguishedName)]
Expanded: [(((%x41-5a / %x61-7a) *(%x41-5a / %x61-7a / %x30 / %x31-39 / %x2d))
 ... <<expanded ABNF snipped>>
Regex: (?:(?:[A-Za-z][\-01-9A-Za-z]*|(?:[01-9]|[1-9][01-9]+)(?:\.(?:[01-9]
 ... <<expanded regex snipped>>

O acima está testando uma string contra o regex gerado a partir da regra nomeada específica ( -t distinguishedName ). Se você tiver olhos aguçados, perceberá que eu trapacei um pouco, removi o espaço em branco do DN, já que ele não é tecnicamente parte do DN e quebrará o jogo.

E finalmente (realmente desta vez) um simplificado e imperfeito regex que você pode usar com < href="http://www.pcre.org/"> pcregrep -i :

 ^([a-z][a-z0-9-]*)=(?![ #])(((?![\="+,;<>]).)|(\[ \#="+,;<>])|(\[a-f0-9][a-f0-9]))*
(,([a-z][a-z0-9-]*)=(?![ #])(((?![\="+,;<>]).)|(\[ \#="+,;<>])|(\[a-f0-9][a-f0-9]))*)*$

Eu tenho acolchoado e enrolado para torná-lo legível, bem, menos ilegível, talvez. Repartição simplificada é

^(attributename)=(attributevalue)(,(attributename)=(attributevalue))*$

com

 attributevalue = not leading space or octothorpe |
                  any char except specials | 
                  escaped specials |
                  escaped hex-digit pair         

Isso leva pelo menos as seguintes liberdades:

  • ele ignora em grande parte o Unicode (embora você possa achar que o pcregrep --utf ajuda) e não validará o UTF-8
  • não suporta OIDs numéricos diretos em tipos de atributo
  • não suporta RDNs com valores múltiplos (por exemplo, cn=Bob+sn=Smith )
  • ele não manipula espaços em branco sem escape

Como por-especificação, ele não lida com formatação de espaço em branco no começo, fim ou próximo ",".

    
por 31.10.2013 / 18:25
4

Não se incomode. O servidor LDAP que você está falando também já sabe como é um DN inválido. Apenas pegue o erro (código de resposta) e aja apropriadamente.

    
por 31.10.2013 / 18:04
0

A biblioteca openldap fornece esta sub-rotina, não estou ciente de nenhuma interface do ldap para ruby, perl, etc. que forneça acesso a esta API. Mas eu não pareço tão difícil.

ldap_str2dn() parses a string representation of  a  distinguished  name
   contained  in  str  into  its  components,  which  are  stored in dn as
   ldap_ava structures, arranged in LDAPAVA, LDAPRDN,  and  LDAPDN  terms,
   defined as:

   typedef struct ldap_ava {
       char *la_attr;
       struct berval *la_value;
       unsigned la_flags;
   } LDAPAVA;
    
por 31.10.2013 / 18:14
0

Eu melhorei minha pergunta adicionando minha resposta alternativa simples (talvez muito simples): eu criei um regexp para combinar com todos os dns possíveis

(\w+[=]{1}[a-zA-Z0-9\-\$&\(\)\[\]\{\}\.\s]+)([,{1}]\w+[=]{1}[a-zA-Z0-9\-\(\)\[\]\{\}\.\s]+)*

    
por 04.11.2013 / 11:15

Tags