mirror of
https://git.openldap.org/openldap/openldap.git
synced 2025-12-25 17:19:43 -05:00
More compliant version of str2dn/dn2str;
may need optimization; uncomment #define USE_LDAP_DN_PARSING in libraries/libldap/getdn.c to enable its use. The ava/rdn/dn handling routines (append, insert, free and so) must be made available thru declaration in some header.
This commit is contained in:
parent
8cc0b83319
commit
64c7e39aa8
5 changed files with 724 additions and 312 deletions
|
|
@ -20,6 +20,21 @@ char **ldap_explode_rdn( const char *rdn, int notypes )
|
|||
.LP
|
||||
.ft B
|
||||
char *ldap_dn2ufn( const char * dn )
|
||||
.LP
|
||||
.ft B
|
||||
char *ldap_dn2dcedn( const char * dn )
|
||||
.LP
|
||||
.ft B
|
||||
char *ldap_dcedn2dn( const char * dn )
|
||||
.LP
|
||||
.ft B
|
||||
char *ldap_dn2ad_canonical( const char * dn )
|
||||
.LP
|
||||
.ft B
|
||||
int ldap_str2dn( const char *str, LDAPDN **dn, unsigned flags )
|
||||
.LP
|
||||
.ft B
|
||||
int ldap_dn2str( LDAPDN *dn, char **str, unsigned flags )
|
||||
.SH DESCRIPTION
|
||||
These routines allow LDAP entry names (Distinguished Names, or DNs)
|
||||
to be obtained, parsed, converted to a user-friendly form, and tested.
|
||||
|
|
@ -73,6 +88,116 @@ of the format, it is generally only used for display purposes.
|
|||
The space for the UFN returned is obtained dynamically and the user
|
||||
is responsible for freeing it via a call to
|
||||
.BR ldap_memfree (3).
|
||||
.LP
|
||||
.B ldap_dn2dcedn()
|
||||
is used to turn a DN as returned by
|
||||
.BR ldap_get_dn (3)
|
||||
into a DCE-style DN, e.g. a string with most-significant to least
|
||||
significant rdns separated by slashes ('/'); rdn components
|
||||
are separated by commas (',').
|
||||
Only printable chars (e.g. LDAPv2 printable string) are allowed,
|
||||
at least in this implementation.
|
||||
.B ldap_dcedn2dn()
|
||||
performs the opposite operation.
|
||||
.B ldap_dn2ad_canonical()
|
||||
turns a DN into a AD canonical name, which is basically a DCE dn
|
||||
with attribute types omitted.
|
||||
The trailing domain, if present, is turned in a DNS-like domain.
|
||||
The space for the returned value is obtained dynamically and the user
|
||||
is responsible for freeing it via a call to
|
||||
.BR ldap_memfree (3).
|
||||
.LP
|
||||
.B ldap_str2dn()
|
||||
parses a string representation of a distinguished name contained in
|
||||
.B str
|
||||
into its components,
|
||||
which are stored in
|
||||
.B dn
|
||||
as
|
||||
.B ldap_ava
|
||||
structures, arranged in
|
||||
.B LDAPAVA,
|
||||
.B LDAPRDN,
|
||||
and
|
||||
.B LDAPDN
|
||||
terms, defined as:
|
||||
.nf
|
||||
.ft B
|
||||
|
||||
typedef struct ldap_ava {
|
||||
char *la_attr;
|
||||
struct berval *la_value;
|
||||
unsigned la_flags;
|
||||
} LDAPAVA;
|
||||
|
||||
typedef LDAPAVA** LDAPRDN;
|
||||
typedef LDAPRDN** LDAPDN;
|
||||
|
||||
.ft
|
||||
.fi
|
||||
The attribute types and the attribute values are not normalized.
|
||||
The
|
||||
.B la_flags
|
||||
can be either
|
||||
.B LDAP_AVA_STRING
|
||||
or
|
||||
.B LDAP_AVA_BINARY,
|
||||
the latter meaning that the value is BER/DER encoded and thus must
|
||||
be represented as, quoting from RFC 2253, " ... an
|
||||
octothorpe character ('#' ASCII 35) followed by the hexadecimal
|
||||
representation of each of the bytes of the BER encoding of the X.500
|
||||
AttributeValue."
|
||||
The
|
||||
.B flags
|
||||
parameter to
|
||||
.B ldap_str2dn()
|
||||
can be
|
||||
.LP
|
||||
.nf
|
||||
LDAP_DN_FORMAT_LDAPV3
|
||||
LDAP_DN_FORMAT_LDAPV2
|
||||
LDAP_DN_FORMAT_DCE
|
||||
|
||||
.fi
|
||||
which defines what DN syntax is expected (according to RFC 2253,
|
||||
RFC 1779 and DCE, respectively).
|
||||
The format can be \fIOR\fPed to the flags
|
||||
.LP
|
||||
.nf
|
||||
LDAP_DN_P_NO_SPACES
|
||||
LDAP_DN_P_NO_SPACE_AFTER_RDN
|
||||
...
|
||||
LDAP_DN_PEDANTIC
|
||||
|
||||
.fi
|
||||
The latter is a shortcut for all the previous limitations.
|
||||
.LP
|
||||
.B LDAP_DN_P_NO_SPACES
|
||||
does not allow extra spaces in the dn; the default is to silently
|
||||
eliminate spaces around AVA separators ('='), RDN component separators
|
||||
('+' for LDAPv3/LDAPv2 or ',' for DCE) and RDN separators
|
||||
(',' LDAPv3/LDAPv2 or '/' for DCE).
|
||||
.LP
|
||||
.B LDAP_DN_P_NO_SPACE_AFTER_RDN
|
||||
does not allow a single space after RDN separators.
|
||||
.LP
|
||||
.B ldap_dn2str()
|
||||
performs the inverse operation, yielding in
|
||||
.B str
|
||||
a string representation of
|
||||
.B dn.
|
||||
It allows the same values for
|
||||
.B flags
|
||||
as
|
||||
.B ldap_str2dn(),
|
||||
plus
|
||||
.LP
|
||||
.nf
|
||||
LDAP_DN_FORMAT_UFN
|
||||
LDAP_DN_FORMAT_AD_CANONICAL
|
||||
|
||||
.fi
|
||||
for user-friendly naming (RFC 1781) and AD canonical.
|
||||
.SH ERRORS
|
||||
If an error occurs in
|
||||
.BR ldap_get_dn() ,
|
||||
|
|
@ -83,8 +208,11 @@ field in the \fIld\fP parameter is set to indicate the error. See
|
|||
for a description of possible error codes.
|
||||
.BR ldap_explode_dn() ,
|
||||
.BR ldap_explode_rdn() ,
|
||||
.B ldap_dn2ufn(),
|
||||
.B ldap_dn2dcedn(),
|
||||
.B ldap_dcedn2dn(),
|
||||
and
|
||||
.B ldap_dn2ufn()
|
||||
.B ldap_dn2ad_canonical()
|
||||
will return NULL with
|
||||
.BR errno (3)
|
||||
set appropriately in case of trouble.
|
||||
|
|
|
|||
|
|
@ -1,3 +1,8 @@
|
|||
ldap_explode_dn.3
|
||||
ldap_explode_rdn.3
|
||||
ldap_dn2ufn.3
|
||||
ldap_str2dn.3
|
||||
ldap_dn2str.3
|
||||
ldap_dn2dcedn.3
|
||||
ldap_dcedn2dn.3
|
||||
ldap_dn2ad_canonical.3
|
||||
|
|
|
|||
|
|
@ -1179,7 +1179,7 @@ typedef struct ldap_ava {
|
|||
unsigned la_flags;
|
||||
#define LDAP_AVA_STRING 0x0000U
|
||||
#define LDAP_AVA_BINARY 0x0001U
|
||||
#define LDAP_AVA_PRINTABLE 0x0002U
|
||||
#define LDAP_AVA_NONPRINTABLE 0x0002U
|
||||
} LDAPAVA;
|
||||
|
||||
typedef LDAPAVA** LDAPRDN;
|
||||
|
|
@ -1194,7 +1194,8 @@ typedef LDAPRDN** LDAPDN;
|
|||
#define LDAP_DN_FORMAT_MASK 0x000FU
|
||||
|
||||
/* str2dn flags */
|
||||
#define LDAP_DN_P_LEADTRAILSPACES 0x1000U
|
||||
#define LDAP_DN_P_NOLEADTRAILSPACES 0x1000U
|
||||
#define LDAP_DN_P_NOSPACEAFTERRDN 0x2000U
|
||||
#define LDAP_DN_PEDANTIC 0xF000U
|
||||
|
||||
LDAP_F( int )
|
||||
|
|
@ -1209,6 +1210,9 @@ ldap_dn2str LDAP_P((
|
|||
char **str,
|
||||
unsigned flags ));
|
||||
|
||||
LDAP_F( void )
|
||||
ldapava_free_dn LDAP_P(( LDAPDN *dn ));
|
||||
|
||||
LDAP_F( int )
|
||||
ldap_dn_normalize LDAP_P((
|
||||
LDAP_CONST char *in, unsigned iflags,
|
||||
|
|
@ -1234,6 +1238,9 @@ ldap_dn2dcedn LDAP_P(( LDAP_CONST char *dn )); /* deprecated */
|
|||
LDAP_F( char * )
|
||||
ldap_dcedn2dn LDAP_P(( LDAP_CONST char *dce )); /* deprecated */
|
||||
|
||||
LDAP_F( char * )
|
||||
ldap_dn2ad_canonical LDAP_P(( LDAP_CONST char *dn )); /* deprecated */
|
||||
|
||||
/*
|
||||
* in getattr.c
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ main( int argc, char *argv[] )
|
|||
int rc, i, debug = 0, f2 = 0;
|
||||
unsigned flags[ 2 ] = { 0U, 0U };
|
||||
char *strin, *str, *str2, buf[ 1024 ];
|
||||
LDAPDN *dn = NULL;
|
||||
LDAPDN *dn, *dn2 = NULL;
|
||||
|
||||
while ( 1 ) {
|
||||
int opt = getopt( argc, argv, "d:" );
|
||||
|
|
@ -57,8 +57,9 @@ main( int argc, char *argv[] )
|
|||
|
||||
if ( argc < 2 ) {
|
||||
fprintf( stderr, "usage: dntest <dn> [flags-in[,...]] [flags-out[,...]]\n\n" );
|
||||
fprintf( stderr, "\tflags-in: V3,V2,DCE,PEDANTIC\n" );
|
||||
fprintf( stderr, "\tflags-out: V3,V2,UFN,DCE,AD,PEDANTIC\n\n" );
|
||||
fprintf( stderr, "\tflags-in: V3,V2,DCE,<pedantic>\n" );
|
||||
fprintf( stderr, "\tflags-out: V3,V2,UFN,DCE,AD,<pedantic>\n\n" );
|
||||
fprintf( stderr, "\t<pedantic>: PEDANTIC,NOSPACES,NOONESPACE\n\n" );
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
|
|
@ -104,6 +105,10 @@ main( int argc, char *argv[] )
|
|||
flags[ i ] |= LDAP_DN_FORMAT_AD_CANONICAL;
|
||||
} else if ( !strcasecmp( s, "PEDANTIC" ) ) {
|
||||
flags[ i ] |= LDAP_DN_PEDANTIC;
|
||||
} else if ( !strcasecmp( s, "NOSPACES" ) ) {
|
||||
flags[ i ] |= LDAP_DN_P_NOLEADTRAILSPACES;
|
||||
} else if ( !strcasecmp( s, "NOONESPACE" ) ) {
|
||||
flags[ i ] |= LDAP_DN_P_NOSPACEAFTERRDN;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -118,6 +123,9 @@ main( int argc, char *argv[] )
|
|||
char **values, *tmp, *tmp2;
|
||||
int n;
|
||||
|
||||
fprintf( stdout, "\nldap_dn2str(ldap_str2dn(\"%s\"))\n"
|
||||
"\t= \"%s\"\n", strin, str );
|
||||
|
||||
switch ( flags[ f2 ] & LDAP_DN_FORMAT_MASK ) {
|
||||
case LDAP_DN_FORMAT_UFN:
|
||||
case LDAP_DN_FORMAT_AD_CANONICAL:
|
||||
|
|
@ -125,23 +133,21 @@ main( int argc, char *argv[] )
|
|||
|
||||
case LDAP_DN_FORMAT_LDAPV3:
|
||||
case LDAP_DN_FORMAT_LDAPV2:
|
||||
fprintf( stdout, "\nldap_dn2str(ldap_str2dn(\"%s\"))\n"
|
||||
"\t=\"%s\"\n", strin, str );
|
||||
tmp = ldap_dn2ufn( strin );
|
||||
fprintf( stdout, "\nldap_dn2ufn(\"%s\")\n\t=\"%s\"\n",
|
||||
strin, tmp );
|
||||
fprintf( stdout, "\nldap_dn2ufn(\"%s\")\n"
|
||||
"\t= \"%s\"\n", strin, tmp );
|
||||
ldap_memfree( tmp );
|
||||
tmp = ldap_dn2dcedn( strin );
|
||||
fprintf( stdout, "\nldap_dn2dcedn(\"%s\")\n"
|
||||
"\t=\"%s\"\n", strin, tmp );
|
||||
"\t= \"%s\"\n", strin, tmp );
|
||||
tmp2 = ldap_dcedn2dn( tmp );
|
||||
fprintf( stdout, "\nldap_dcedn2dn(\"%s\")\n"
|
||||
"\t=\"%s\"\n", tmp, tmp2 );
|
||||
"\t= \"%s\"\n", tmp, tmp2 );
|
||||
ldap_memfree( tmp );
|
||||
ldap_memfree( tmp2 );
|
||||
tmp = ldap_dn2ad_canonical( strin );
|
||||
fprintf( stdout, "\nldap_dn2ad_canonical(\"%s\")\n"
|
||||
"\t=\"%s\"\n", strin, tmp );
|
||||
"\t= \"%s\"\n", strin, tmp );
|
||||
ldap_memfree( tmp );
|
||||
|
||||
fprintf( stdout, "\nldap_explode_dn(\"%s\"):\n", str );
|
||||
|
|
@ -184,17 +190,41 @@ main( int argc, char *argv[] )
|
|||
break;
|
||||
}
|
||||
|
||||
rc = ldap_str2dn( str, &dn, flags[ f2 ] );
|
||||
rc = ldap_str2dn( str, &dn2, flags[ f2 ] );
|
||||
if ( rc == LDAP_SUCCESS &&
|
||||
ldap_dn2str( dn, &str2, flags[ f2 ] )
|
||||
ldap_dn2str( dn2, &str2, flags[ f2 ] )
|
||||
== LDAP_SUCCESS ) {
|
||||
int iRDN;
|
||||
|
||||
fprintf( stdout, "\n\"%s\"\n\t == \"%s\" ? %s\n",
|
||||
str, str2,
|
||||
strcmp( str, str2 ) == 0 ? "yes" : "no" );
|
||||
|
||||
for ( iRDN = 0; dn[ iRDN ] && dn2[ iRDN ]; iRDN++ ) {
|
||||
LDAPRDN *r = dn[ iRDN ][ 0 ];
|
||||
LDAPRDN *r2 = dn2[ iRDN ][ 0 ];
|
||||
int iAVA;
|
||||
|
||||
for ( iAVA = 0; r[ iAVA ] && r[ iAVA ]; iAVA++ ) {
|
||||
LDAPAVA *a = r[ iAVA ][ 0 ];
|
||||
LDAPAVA *a2 = r2[ iAVA ][ 0 ];
|
||||
|
||||
if ( strcmp( a->la_attr, a2->la_attr )
|
||||
|| a->la_flags != a2->la_flags
|
||||
|| a->la_value->bv_len != a2->la_value->bv_len
|
||||
|| memcmp( a->la_value->bv_val, a2->la_value->bv_val, a->la_value->bv_len ) ) {
|
||||
fprintf( stdout, "mismatch\n" );
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ldapava_free_dn( dn2 );
|
||||
ldap_memfree( str2 );
|
||||
}
|
||||
ldap_memfree( str );
|
||||
}
|
||||
ldapava_free_dn( dn );
|
||||
|
||||
/* note: dn is not freed */
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue