Skip to content
Snippets Groups Projects
Commit 64c7e39a authored by Pierangelo Masarati's avatar Pierangelo Masarati
Browse files

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.
parent 8cc0b833
No related branches found
No related tags found
No related merge requests found
......@@ -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.
......
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 */
......
This diff is collapsed.
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment