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:
Pierangelo Masarati 2001-10-29 08:05:23 +00:00
parent 8cc0b83319
commit 64c7e39aa8
5 changed files with 724 additions and 312 deletions

View file

@ -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.

View file

@ -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

View file

@ -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
*/

View file

@ -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