1998-08-09 08:43:13 +08:00
|
|
|
/* dn.c - routines for dealing with distinguished names */
|
1999-09-09 03:06:24 +08:00
|
|
|
/* $OpenLDAP$ */
|
1999-08-07 07:07:46 +08:00
|
|
|
/*
|
2000-05-13 10:47:56 +08:00
|
|
|
* Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved.
|
1999-08-07 07:07:46 +08:00
|
|
|
* COPYING RESTRICTIONS APPLY, see COPYRIGHT file
|
|
|
|
*/
|
1998-08-09 08:43:13 +08:00
|
|
|
|
|
|
|
#include "portable.h"
|
1998-10-25 09:41:42 +08:00
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
|
|
|
#include <ac/ctype.h>
|
|
|
|
#include <ac/socket.h>
|
|
|
|
#include <ac/string.h>
|
|
|
|
#include <ac/time.h>
|
|
|
|
|
1999-08-25 14:44:08 +08:00
|
|
|
#include "ldap_pvt.h"
|
|
|
|
|
1998-08-09 08:43:13 +08:00
|
|
|
#include "slap.h"
|
|
|
|
|
2001-12-23 09:19:46 +08:00
|
|
|
#define SLAP_LDAPDN_PRETTY 0x1
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The DN syntax-related functions take advantage of the dn representation
|
|
|
|
* handling functions ldap_str2dn/ldap_dn2str. The latter are not schema-
|
|
|
|
* aware, so the attributes and their values need be validated (and possibly
|
|
|
|
* normalized). In the current implementation the required validation/nor-
|
|
|
|
* malization/"pretty"ing are done on newly created DN structural represen-
|
|
|
|
* tations; however the idea is to move towards DN handling in structural
|
|
|
|
* representation instead of the current string representation. To this
|
|
|
|
* purpose, we need to do only the required operations and keep track of
|
|
|
|
* what has been done to minimize their impact on performances.
|
|
|
|
*
|
|
|
|
* Developers are strongly encouraged to use this feature, to speed-up
|
|
|
|
* its stabilization.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#define AVA_PRIVATE( ava ) ( ( AttributeDescription * )(ava)->la_private )
|
|
|
|
|
|
|
|
/*
|
|
|
|
* In-place, schema-aware validation of the
|
|
|
|
* structural representation of a distinguished name.
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
LDAPDN_validate( LDAPDN *dn )
|
|
|
|
{
|
|
|
|
int iRDN;
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
assert( dn );
|
|
|
|
|
|
|
|
for ( iRDN = 0; dn[ iRDN ]; iRDN++ ) {
|
|
|
|
LDAPRDN *rdn = dn[ iRDN ][ 0 ];
|
|
|
|
int iAVA;
|
|
|
|
|
|
|
|
assert( rdn );
|
|
|
|
|
|
|
|
for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) {
|
|
|
|
LDAPAVA *ava = rdn[ iAVA ][ 0 ];
|
|
|
|
AttributeDescription *ad;
|
|
|
|
slap_syntax_validate_func *validate = NULL;
|
|
|
|
|
|
|
|
assert( ava );
|
|
|
|
|
|
|
|
if ( ( ad = AVA_PRIVATE( ava ) ) == NULL ) {
|
|
|
|
const char *text = NULL;
|
|
|
|
|
|
|
|
rc = slap_bv2ad( ava->la_attr, &ad, &text );
|
|
|
|
if ( rc != LDAP_SUCCESS ) {
|
|
|
|
return LDAP_INVALID_SYNTAX;
|
|
|
|
}
|
|
|
|
|
|
|
|
ava->la_private = ( void * )ad;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Replace attr oid/name with the canonical name
|
|
|
|
*/
|
|
|
|
ber_bvfree( ava->la_attr );
|
|
|
|
ava->la_attr = ber_bvdup( &ad->ad_cname );
|
|
|
|
|
|
|
|
validate = ad->ad_type->sat_syntax->ssyn_validate;
|
|
|
|
|
|
|
|
if ( validate ) {
|
|
|
|
/*
|
|
|
|
* validate value by validate function
|
|
|
|
*/
|
|
|
|
rc = ( *validate )( ad->ad_type->sat_syntax,
|
|
|
|
ava->la_value );
|
|
|
|
|
|
|
|
if ( rc != LDAP_SUCCESS ) {
|
|
|
|
return LDAP_INVALID_SYNTAX;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return LDAP_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2001-12-08 14:57:06 +08:00
|
|
|
/*
|
2001-12-23 09:19:46 +08:00
|
|
|
* dn validate routine
|
2001-12-08 14:57:06 +08:00
|
|
|
*/
|
2001-12-23 09:19:46 +08:00
|
|
|
int
|
|
|
|
dnValidate(
|
|
|
|
Syntax *syntax,
|
|
|
|
struct berval *in )
|
2001-12-08 14:57:06 +08:00
|
|
|
{
|
2001-12-23 09:19:46 +08:00
|
|
|
int rc;
|
|
|
|
LDAPDN *dn = NULL;
|
|
|
|
|
|
|
|
assert( in );
|
|
|
|
|
|
|
|
if ( in->bv_len == 0 ) {
|
|
|
|
return( LDAP_SUCCESS );
|
|
|
|
}
|
|
|
|
|
|
|
|
rc = ldap_str2dn( in->bv_val, &dn, LDAP_DN_FORMAT_LDAP );
|
|
|
|
|
2001-12-08 14:57:06 +08:00
|
|
|
/*
|
2001-12-23 09:19:46 +08:00
|
|
|
* Schema-aware validate
|
2001-12-08 14:57:06 +08:00
|
|
|
*/
|
2001-12-23 09:19:46 +08:00
|
|
|
if ( rc == LDAP_SUCCESS ) {
|
|
|
|
rc = LDAPDN_validate( dn );
|
|
|
|
}
|
|
|
|
|
2001-12-24 06:46:37 +08:00
|
|
|
ldap_dnfree( dn );
|
2001-12-23 09:19:46 +08:00
|
|
|
|
|
|
|
if ( rc != LDAP_SUCCESS ) {
|
|
|
|
return( LDAP_INVALID_SYNTAX );
|
|
|
|
}
|
|
|
|
|
|
|
|
return( LDAP_SUCCESS );
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* AVA sorting inside a RDN
|
|
|
|
*
|
|
|
|
* rule: sort attributeTypes in alphabetical order; in case of multiple
|
|
|
|
* occurrences of the same attributeType, sort values in byte order
|
|
|
|
* (use memcmp, which implies alphabetical order in case of IA5 value;
|
|
|
|
* this should guarantee the repeatability of the operation).
|
|
|
|
*
|
|
|
|
* uses a linear search; should be fine since the number of AVAs in
|
|
|
|
* a RDN should be limited.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
AVA_Sort( LDAPRDN *rdn, int iAVA )
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
LDAPAVA *ava_in = rdn[ iAVA ][ 0 ];
|
|
|
|
|
|
|
|
assert( rdn );
|
|
|
|
assert( ava_in );
|
|
|
|
|
|
|
|
for ( i = 0; i < iAVA; i++ ) {
|
|
|
|
LDAPAVA *ava = rdn[ i ][ 0 ];
|
|
|
|
int a, j;
|
|
|
|
|
|
|
|
assert( ava );
|
|
|
|
|
|
|
|
a = strcmp( ava_in->la_attr->bv_val, ava->la_attr->bv_val );
|
|
|
|
|
|
|
|
if ( a > 0 ) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
while ( a == 0 ) {
|
|
|
|
int v, d;
|
|
|
|
|
|
|
|
d = ava_in->la_value->bv_len - ava->la_value->bv_len;
|
|
|
|
|
|
|
|
v = memcmp( ava_in->la_value->bv_val,
|
|
|
|
ava->la_value->bv_val,
|
|
|
|
d <= 0 ? ava_in->la_value->bv_len
|
|
|
|
: ava->la_value->bv_len );
|
|
|
|
|
|
|
|
if ( v == 0 && d != 0 ) {
|
|
|
|
v = d;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( v <= 0 ) {
|
|
|
|
/*
|
|
|
|
* got it!
|
|
|
|
*/
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( ++i == iAVA ) {
|
|
|
|
/*
|
|
|
|
* already sorted
|
|
|
|
*/
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
ava = rdn[ i ][ 0 ];
|
|
|
|
a = strcmp( ava_in->la_value->bv_val,
|
|
|
|
ava->la_value->bv_val );
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* move ahead
|
|
|
|
*/
|
|
|
|
for ( j = iAVA; j > i; j-- ) {
|
|
|
|
rdn[ j ][ 0 ] = rdn[ j - 1 ][ 0 ];
|
|
|
|
}
|
|
|
|
rdn[ i ][ 0 ] = ava_in;
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* In-place, schema-aware normalization / "pretty"ing of the
|
|
|
|
* structural representation of a distinguished name.
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
LDAPDN_rewrite( LDAPDN *dn, unsigned flags )
|
|
|
|
{
|
|
|
|
int iRDN;
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
assert( dn );
|
|
|
|
|
|
|
|
for ( iRDN = 0; dn[ iRDN ]; iRDN++ ) {
|
|
|
|
LDAPRDN *rdn = dn[ iRDN ][ 0 ];
|
|
|
|
int iAVA;
|
|
|
|
|
|
|
|
assert( rdn );
|
|
|
|
|
|
|
|
for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) {
|
|
|
|
LDAPAVA *ava = rdn[ iAVA ][ 0 ];
|
|
|
|
AttributeDescription *ad;
|
|
|
|
slap_syntax_transform_func *transf = NULL;
|
|
|
|
MatchingRule *mr;
|
|
|
|
struct berval *bv = NULL;
|
2001-12-08 14:57:06 +08:00
|
|
|
|
2001-12-23 09:19:46 +08:00
|
|
|
assert( ava );
|
|
|
|
|
|
|
|
if ( ( ad = AVA_PRIVATE( ava ) ) == NULL ) {
|
|
|
|
const char *text = NULL;
|
|
|
|
|
|
|
|
rc = slap_bv2ad( ava->la_attr, &ad, &text );
|
|
|
|
if ( rc != LDAP_SUCCESS ) {
|
|
|
|
return LDAP_INVALID_SYNTAX;
|
|
|
|
}
|
|
|
|
|
|
|
|
ava->la_private = ( void * )ad;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Replace attr oid/name with the canonical name
|
|
|
|
*/
|
|
|
|
ber_bvfree( ava->la_attr );
|
|
|
|
ava->la_attr = ber_bvdup( &ad->ad_cname );
|
|
|
|
|
|
|
|
if( flags & SLAP_LDAPDN_PRETTY ) {
|
|
|
|
transf = ad->ad_type->sat_syntax->ssyn_pretty;
|
|
|
|
mr = NULL;
|
|
|
|
} else {
|
|
|
|
transf = ad->ad_type->sat_syntax->ssyn_normalize;
|
|
|
|
mr = ad->ad_type->sat_equality;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( transf ) {
|
|
|
|
/*
|
|
|
|
* transform value by normalize/pretty function
|
|
|
|
*/
|
|
|
|
rc = ( *transf )( ad->ad_type->sat_syntax,
|
|
|
|
ava->la_value, &bv );
|
|
|
|
|
|
|
|
if ( rc != LDAP_SUCCESS ) {
|
|
|
|
return LDAP_INVALID_SYNTAX;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if( mr && ( mr->smr_usage & SLAP_MR_DN_FOLD ) ) {
|
|
|
|
struct berval *s = bv;
|
|
|
|
|
|
|
|
bv = ber_bvstr( UTF8normalize( bv ? bv : ava->la_value,
|
|
|
|
UTF8_CASEFOLD ) );
|
|
|
|
|
|
|
|
ber_bvfree( s );
|
|
|
|
}
|
|
|
|
|
|
|
|
if( bv ) {
|
|
|
|
ber_bvfree( ava->la_value );
|
|
|
|
ava->la_value = bv;
|
|
|
|
}
|
|
|
|
|
|
|
|
AVA_Sort( rdn, iAVA );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return LDAP_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* dn normalize routine
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
dnNormalize(
|
|
|
|
Syntax *syntax,
|
|
|
|
struct berval *val,
|
|
|
|
struct berval **normalized )
|
|
|
|
{
|
|
|
|
struct berval *out = NULL;
|
|
|
|
|
|
|
|
Debug( LDAP_DEBUG_TRACE, ">>> dnNormalize: <%s>\n", val->bv_val, 0, 0 );
|
|
|
|
|
|
|
|
assert( val );
|
|
|
|
assert( normalized );
|
|
|
|
|
2001-12-25 02:38:20 +08:00
|
|
|
assert( *normalized == NULL );
|
|
|
|
|
2001-12-23 09:19:46 +08:00
|
|
|
if ( val->bv_len != 0 ) {
|
|
|
|
LDAPDN *dn = NULL;
|
|
|
|
char *dn_out = NULL;
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Go to structural representation
|
|
|
|
*/
|
|
|
|
rc = ldap_str2dn( val->bv_val, &dn, LDAP_DN_FORMAT_LDAP );
|
|
|
|
if ( rc != LDAP_SUCCESS ) {
|
|
|
|
return LDAP_INVALID_SYNTAX;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Schema-aware rewrite
|
|
|
|
*/
|
|
|
|
if ( LDAPDN_rewrite( dn, 0 ) != LDAP_SUCCESS ) {
|
2001-12-24 06:46:37 +08:00
|
|
|
ldap_dnfree( dn );
|
2001-12-23 09:19:46 +08:00
|
|
|
return LDAP_INVALID_SYNTAX;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Back to string representation
|
|
|
|
*/
|
|
|
|
rc = ldap_dn2str( dn, &dn_out, LDAP_DN_FORMAT_LDAPV3 );
|
|
|
|
|
2001-12-24 06:46:37 +08:00
|
|
|
ldap_dnfree( dn );
|
2001-12-23 09:19:46 +08:00
|
|
|
|
|
|
|
if ( rc != LDAP_SUCCESS ) {
|
|
|
|
return LDAP_INVALID_SYNTAX;
|
|
|
|
}
|
|
|
|
|
|
|
|
out = ber_bvstr( dn_out );
|
|
|
|
|
|
|
|
} else {
|
|
|
|
out = ber_bvdup( val );
|
|
|
|
}
|
|
|
|
|
|
|
|
Debug( LDAP_DEBUG_TRACE, "<<< dnNormalize: <%s>\n", out->bv_val, 0, 0 );
|
|
|
|
|
|
|
|
*normalized = out;
|
|
|
|
return LDAP_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* dn "pretty"ing routine
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
dnPretty(
|
|
|
|
Syntax *syntax,
|
|
|
|
struct berval *val,
|
|
|
|
struct berval **pretty)
|
|
|
|
{
|
|
|
|
struct berval *out = NULL;
|
|
|
|
|
|
|
|
Debug( LDAP_DEBUG_TRACE, ">>> dnPretty: <%s>\n", val->bv_val, 0, 0 );
|
|
|
|
|
|
|
|
assert( val );
|
|
|
|
assert( pretty );
|
2001-12-25 02:38:20 +08:00
|
|
|
assert( *pretty == NULL );
|
2001-12-23 09:19:46 +08:00
|
|
|
|
|
|
|
if ( val->bv_len != 0 ) {
|
|
|
|
LDAPDN *dn = NULL;
|
|
|
|
char *dn_out = NULL;
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
/* FIXME: should be liberal in what we accept */
|
|
|
|
rc = ldap_str2dn( val->bv_val, &dn, LDAP_DN_FORMAT_LDAP );
|
|
|
|
if ( rc != LDAP_SUCCESS ) {
|
|
|
|
return LDAP_INVALID_SYNTAX;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Schema-aware rewrite
|
|
|
|
*/
|
|
|
|
if ( LDAPDN_rewrite( dn, SLAP_LDAPDN_PRETTY ) != LDAP_SUCCESS ) {
|
2001-12-24 06:46:37 +08:00
|
|
|
ldap_dnfree( dn );
|
2001-12-23 09:19:46 +08:00
|
|
|
return LDAP_INVALID_SYNTAX;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* FIXME: not sure why the default isn't pretty */
|
|
|
|
/* RE: the default is the form that is used as
|
|
|
|
* an internal representation; the pretty form
|
|
|
|
* is a variant */
|
|
|
|
rc = ldap_dn2str( dn, &dn_out,
|
|
|
|
LDAP_DN_FORMAT_LDAPV3 | LDAP_DN_PRETTY );
|
|
|
|
|
2001-12-24 06:46:37 +08:00
|
|
|
ldap_dnfree( dn );
|
2001-12-23 09:19:46 +08:00
|
|
|
|
|
|
|
if ( rc != LDAP_SUCCESS ) {
|
|
|
|
return LDAP_INVALID_SYNTAX;
|
|
|
|
}
|
|
|
|
|
|
|
|
out = ber_bvstr( dn_out );
|
|
|
|
|
|
|
|
} else {
|
|
|
|
out = ber_bvdup( val );
|
|
|
|
}
|
|
|
|
|
|
|
|
Debug( LDAP_DEBUG_TRACE, "<<< dnPretty: <%s>\n", out->bv_val, 0, 0 );
|
|
|
|
|
|
|
|
*pretty = out;
|
|
|
|
|
|
|
|
return LDAP_SUCCESS;
|
2001-12-08 14:57:06 +08:00
|
|
|
}
|
2001-12-23 09:19:46 +08:00
|
|
|
|
|
|
|
/*
|
2001-12-24 14:00:02 +08:00
|
|
|
* dnMatch routine
|
2001-12-23 09:19:46 +08:00
|
|
|
*/
|
|
|
|
int
|
|
|
|
dnMatch(
|
|
|
|
int *matchp,
|
|
|
|
slap_mask_t flags,
|
|
|
|
Syntax *syntax,
|
|
|
|
MatchingRule *mr,
|
|
|
|
struct berval *value,
|
|
|
|
void *assertedValue )
|
|
|
|
{
|
|
|
|
int match;
|
|
|
|
struct berval *asserted = (struct berval *) assertedValue;
|
|
|
|
|
|
|
|
assert( matchp );
|
|
|
|
assert( value );
|
|
|
|
assert( assertedValue );
|
|
|
|
|
|
|
|
match = value->bv_len - asserted->bv_len;
|
|
|
|
|
|
|
|
if ( match == 0 ) {
|
2001-12-25 04:42:05 +08:00
|
|
|
match = strcmp( value->bv_val, asserted->bv_val );
|
2001-12-23 09:19:46 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef NEW_LOGGING
|
|
|
|
LDAP_LOG(( "schema", LDAP_LEVEL_ENTRY,
|
|
|
|
"dnMatch: %d\n %s\n %s\n", match,
|
|
|
|
value->bv_val, asserted->bv_val ));
|
|
|
|
#else
|
|
|
|
Debug( LDAP_DEBUG_ARGS, "dnMatch %d\n\t\"%s\"\n\t\"%s\"\n",
|
|
|
|
match, value->bv_val, asserted->bv_val );
|
2001-12-23 08:43:57 +08:00
|
|
|
#endif
|
2001-12-08 14:57:06 +08:00
|
|
|
|
2001-12-23 09:19:46 +08:00
|
|
|
*matchp = match;
|
|
|
|
return( LDAP_SUCCESS );
|
|
|
|
}
|
|
|
|
|
2001-12-24 12:39:15 +08:00
|
|
|
#ifdef SLAP_DN_MIGRATION
|
|
|
|
/*
|
|
|
|
* these routines are provided for migration purposes only!
|
|
|
|
* dn_validate is deprecated in favor of dnValidate
|
|
|
|
* dn_normalize is deprecated in favor of dnNormalize
|
|
|
|
* strcmp/strcasecmp for DNs is deprecated in favor of dnMatch
|
|
|
|
*
|
|
|
|
* other routines are likewise deprecated but may not yet have
|
|
|
|
* replacement functions.
|
|
|
|
*/
|
|
|
|
|
2001-07-22 06:44:55 +08:00
|
|
|
/*
|
|
|
|
* dn_validate - validate and compress dn. the dn is
|
|
|
|
* compressed in place are returned if valid.
|
2001-12-24 14:00:02 +08:00
|
|
|
* Deprecated in favor of dnValidate()
|
dn_validate/dn_normalize has been rewritten by
David A. Cooper <david.cooper@nist.gov> (ITS#1232)
according to draft-ietf-ldapbis-dn-05.txt
A copyright statement follows:
The functions normalize_unicode(), get_hexpair(), write_hex_pair(),
get_next_byte(), get_next_char(), get_ber_length(),
ber_parse_primitive_string(), ber_parse_string(), String_normalize(),
DirectoryString_normalize(), PrintableString_normalize(),
IA5String_normalize(), ber_parse_primitive_bitstring(),
ber_parse_bitstring(), getNext8bits(), bitString_normalize(), match_oid(),
match_key(), get_validated_av_in_dn(), get_validated_rdn_in_dn(),
and get_validated_dn() in this file were developed at the National Institute
of Standards and Technology by employees of the Federal Government in the
course of their official duties. Pursuant to title 17 Section 105 of the
United States Code the code in these functions is not subject to copyright
protection and is in the public domain. The copyright for all other code in
this file is as specified below.
2001-07-13 16:21:14 +08:00
|
|
|
*/
|
2001-07-22 06:44:55 +08:00
|
|
|
char *
|
2001-12-24 12:39:15 +08:00
|
|
|
dn_validate( char *dn )
|
dn_validate/dn_normalize has been rewritten by
David A. Cooper <david.cooper@nist.gov> (ITS#1232)
according to draft-ietf-ldapbis-dn-05.txt
A copyright statement follows:
The functions normalize_unicode(), get_hexpair(), write_hex_pair(),
get_next_byte(), get_next_char(), get_ber_length(),
ber_parse_primitive_string(), ber_parse_string(), String_normalize(),
DirectoryString_normalize(), PrintableString_normalize(),
IA5String_normalize(), ber_parse_primitive_bitstring(),
ber_parse_bitstring(), getNext8bits(), bitString_normalize(), match_oid(),
match_key(), get_validated_av_in_dn(), get_validated_rdn_in_dn(),
and get_validated_dn() in this file were developed at the National Institute
of Standards and Technology by employees of the Federal Government in the
course of their official duties. Pursuant to title 17 Section 105 of the
United States Code the code in these functions is not subject to copyright
protection and is in the public domain. The copyright for all other code in
this file is as specified below.
2001-07-13 16:21:14 +08:00
|
|
|
{
|
2001-12-25 02:38:20 +08:00
|
|
|
struct berval val;
|
|
|
|
struct berval *pretty = NULL;
|
2001-12-05 04:22:26 +08:00
|
|
|
int rc;
|
|
|
|
|
2001-12-24 12:39:15 +08:00
|
|
|
if ( dn == NULL || dn[0] == '\0' ) {
|
|
|
|
return dn;
|
2001-12-05 04:22:26 +08:00
|
|
|
}
|
|
|
|
|
2001-12-24 12:39:15 +08:00
|
|
|
val.bv_val = dn;
|
|
|
|
val.bv_len = strlen( dn );
|
2001-12-05 04:22:26 +08:00
|
|
|
|
2001-12-24 12:39:15 +08:00
|
|
|
rc = dnPretty( NULL, &val, &pretty );
|
2001-12-05 04:22:26 +08:00
|
|
|
if ( rc != LDAP_SUCCESS ) {
|
2001-12-24 12:39:15 +08:00
|
|
|
return NULL;
|
2001-12-05 04:22:26 +08:00
|
|
|
}
|
|
|
|
|
2001-12-24 12:39:15 +08:00
|
|
|
if ( val.bv_len < pretty->bv_len ) {
|
|
|
|
ber_bvfree( pretty );
|
|
|
|
return NULL;
|
2001-12-05 04:22:26 +08:00
|
|
|
}
|
|
|
|
|
2001-12-24 12:39:15 +08:00
|
|
|
AC_MEMCPY( dn, pretty->bv_val, pretty->bv_len + 1 );
|
|
|
|
ber_bvfree( pretty );
|
2001-12-05 04:22:26 +08:00
|
|
|
|
2001-12-24 12:39:15 +08:00
|
|
|
return dn;
|
dn_validate/dn_normalize has been rewritten by
David A. Cooper <david.cooper@nist.gov> (ITS#1232)
according to draft-ietf-ldapbis-dn-05.txt
A copyright statement follows:
The functions normalize_unicode(), get_hexpair(), write_hex_pair(),
get_next_byte(), get_next_char(), get_ber_length(),
ber_parse_primitive_string(), ber_parse_string(), String_normalize(),
DirectoryString_normalize(), PrintableString_normalize(),
IA5String_normalize(), ber_parse_primitive_bitstring(),
ber_parse_bitstring(), getNext8bits(), bitString_normalize(), match_oid(),
match_key(), get_validated_av_in_dn(), get_validated_rdn_in_dn(),
and get_validated_dn() in this file were developed at the National Institute
of Standards and Technology by employees of the Federal Government in the
course of their official duties. Pursuant to title 17 Section 105 of the
United States Code the code in these functions is not subject to copyright
protection and is in the public domain. The copyright for all other code in
this file is as specified below.
2001-07-13 16:21:14 +08:00
|
|
|
}
|
|
|
|
|
2001-07-22 06:44:55 +08:00
|
|
|
/*
|
|
|
|
* dn_normalize - put dn into a canonical form suitable for storing
|
|
|
|
* in a hash database. this involves normalizing the case as well as
|
|
|
|
* the format. the dn is normalized in place as well as returned if valid.
|
2001-12-24 14:00:02 +08:00
|
|
|
* Deprecated in favor of dnNormalize()
|
dn_validate/dn_normalize has been rewritten by
David A. Cooper <david.cooper@nist.gov> (ITS#1232)
according to draft-ietf-ldapbis-dn-05.txt
A copyright statement follows:
The functions normalize_unicode(), get_hexpair(), write_hex_pair(),
get_next_byte(), get_next_char(), get_ber_length(),
ber_parse_primitive_string(), ber_parse_string(), String_normalize(),
DirectoryString_normalize(), PrintableString_normalize(),
IA5String_normalize(), ber_parse_primitive_bitstring(),
ber_parse_bitstring(), getNext8bits(), bitString_normalize(), match_oid(),
match_key(), get_validated_av_in_dn(), get_validated_rdn_in_dn(),
and get_validated_dn() in this file were developed at the National Institute
of Standards and Technology by employees of the Federal Government in the
course of their official duties. Pursuant to title 17 Section 105 of the
United States Code the code in these functions is not subject to copyright
protection and is in the public domain. The copyright for all other code in
this file is as specified below.
2001-07-13 16:21:14 +08:00
|
|
|
*/
|
2001-07-22 06:44:55 +08:00
|
|
|
char *
|
|
|
|
dn_normalize( char *dn )
|
|
|
|
{
|
2001-12-25 02:38:20 +08:00
|
|
|
struct berval val;
|
|
|
|
struct berval *normalized = NULL;
|
2001-12-05 04:22:26 +08:00
|
|
|
int rc;
|
|
|
|
|
2001-12-24 12:39:15 +08:00
|
|
|
if ( dn == NULL || dn[0] == '\0' ) {
|
|
|
|
return dn;
|
2001-12-05 04:22:26 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
val.bv_val = dn;
|
|
|
|
val.bv_len = strlen( dn );
|
|
|
|
|
|
|
|
rc = dnNormalize( NULL, &val, &normalized );
|
|
|
|
if ( rc != LDAP_SUCCESS ) {
|
2001-12-24 12:39:15 +08:00
|
|
|
return NULL;
|
2001-12-05 04:22:26 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if ( val.bv_len < normalized->bv_len ) {
|
|
|
|
ber_bvfree( normalized );
|
2001-12-24 12:39:15 +08:00
|
|
|
return NULL;
|
2001-12-05 04:22:26 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
AC_MEMCPY( dn, normalized->bv_val, normalized->bv_len + 1 );
|
|
|
|
ber_bvfree( normalized );
|
|
|
|
|
2001-12-24 12:39:15 +08:00
|
|
|
return dn;
|
2001-12-05 04:22:26 +08:00
|
|
|
}
|
|
|
|
|
2001-12-24 23:48:35 +08:00
|
|
|
/*
|
|
|
|
* dnParent - dn's parent, in-place
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
dnParent(
|
|
|
|
const char *dn,
|
|
|
|
const char **pdn )
|
|
|
|
{
|
|
|
|
LDAPRDN *tmpRDN;
|
|
|
|
const char *p;
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
rc = ldap_str2rdn( dn, &tmpRDN, &p, LDAP_DN_FORMAT_LDAP );
|
|
|
|
if ( rc != LDAP_SUCCESS ) {
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
ldap_rdnfree( tmpRDN );
|
|
|
|
|
|
|
|
assert( DN_SEPARATOR( p[ 0 ] ) );
|
|
|
|
p++;
|
|
|
|
|
|
|
|
while ( ASCII_SPACE( p[ 0 ] ) ) {
|
|
|
|
p++;
|
|
|
|
}
|
|
|
|
|
|
|
|
*pdn = p;
|
|
|
|
|
|
|
|
return LDAP_SUCCESS;
|
|
|
|
}
|
2001-12-24 12:39:15 +08:00
|
|
|
|
1998-08-09 08:43:13 +08:00
|
|
|
/*
|
2001-12-08 18:37:42 +08:00
|
|
|
* dn_parent - return the dn's parent, in-place
|
2001-12-24 23:48:35 +08:00
|
|
|
* FIXME: should be replaced by dnParent()
|
1998-08-09 08:43:13 +08:00
|
|
|
*/
|
|
|
|
char *
|
2001-12-08 18:37:42 +08:00
|
|
|
dn_parent(
|
2001-12-24 23:48:35 +08:00
|
|
|
Backend *be,
|
2001-12-08 14:57:06 +08:00
|
|
|
const char *dn )
|
1998-08-09 08:43:13 +08:00
|
|
|
{
|
2001-12-24 23:48:35 +08:00
|
|
|
const char *pdn;
|
|
|
|
|
|
|
|
if ( dn == NULL ) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
while ( dn[ 0 ] != '\0' && ASCII_SPACE( dn[ 0 ] ) ) {
|
|
|
|
dn++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( dn[ 0 ] == '\0' ) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( be != NULL && be_issuffix( be, dn ) ) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( dnParent( dn, &pdn ) != LDAP_SUCCESS ) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ( char * )pdn;
|
2001-12-08 16:41:39 +08:00
|
|
|
}
|
|
|
|
|
2001-12-24 23:48:35 +08:00
|
|
|
int
|
|
|
|
dnExtractRdn(
|
2001-12-28 01:17:01 +08:00
|
|
|
struct berval *dn,
|
2001-12-24 23:48:35 +08:00
|
|
|
struct berval **rdn )
|
|
|
|
{
|
|
|
|
LDAPRDN *tmpRDN;
|
|
|
|
const char *p;
|
|
|
|
char *rdnout;
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
assert( dn );
|
|
|
|
assert( rdn );
|
|
|
|
|
2001-12-28 01:17:01 +08:00
|
|
|
if( dn->bv_len == 0 ) {
|
|
|
|
return LDAP_OTHER;
|
|
|
|
}
|
|
|
|
|
|
|
|
rc = ldap_str2rdn( dn->bv_val, &tmpRDN, &p, LDAP_DN_FORMAT_LDAP );
|
2001-12-24 23:48:35 +08:00
|
|
|
if ( rc != LDAP_SUCCESS ) {
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
rc = ldap_rdn2str( tmpRDN, &rdnout, LDAP_DN_FORMAT_LDAPV3 );
|
|
|
|
ldap_rdnfree( tmpRDN );
|
|
|
|
if ( rc != LDAP_SUCCESS ) {
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
*rdn = ber_bvstr( rdnout );
|
|
|
|
if ( *rdn == NULL ) {
|
|
|
|
free( rdnout );
|
|
|
|
return LDAP_NO_MEMORY;
|
|
|
|
}
|
|
|
|
|
|
|
|
return LDAP_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* FIXME: should be replaced by dnExtractRdn() (together with dn_rdn)
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
dn_rdnlen(
|
|
|
|
Backend *be,
|
2001-07-22 07:45:04 +08:00
|
|
|
const char *dn_in )
|
1999-01-29 05:40:04 +08:00
|
|
|
{
|
2001-12-28 01:17:01 +08:00
|
|
|
struct berval bv;
|
2001-12-24 23:48:35 +08:00
|
|
|
struct berval *rdn = NULL;
|
|
|
|
int retval = 0;
|
|
|
|
|
|
|
|
assert( dn_in );
|
|
|
|
|
|
|
|
if ( dn_in == NULL ) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
while ( dn_in[ 0 ] && ASCII_SPACE( dn_in[ 0 ] ) ) {
|
|
|
|
dn_in++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( dn_in[ 0 ] == '\0' ) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( be != NULL && be_issuffix( be, dn_in ) ) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2001-12-28 01:17:01 +08:00
|
|
|
bv.bv_val = (char *) dn_in;
|
|
|
|
bv.bv_len = strlen( bv.bv_val );
|
|
|
|
|
|
|
|
if ( dnExtractRdn( &bv, &rdn ) != LDAP_SUCCESS ) {
|
2001-12-24 23:48:35 +08:00
|
|
|
ber_bvfree( rdn );
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
retval = rdn->bv_len;
|
|
|
|
ber_bvfree( rdn );
|
|
|
|
|
|
|
|
return retval;
|
1999-01-29 05:40:04 +08:00
|
|
|
}
|
|
|
|
|
2001-12-24 23:48:35 +08:00
|
|
|
/*
|
|
|
|
* FIXME: should be replaced by dnExtractRdn() (together with dn_rdnlen)
|
|
|
|
*/
|
2001-12-08 19:08:26 +08:00
|
|
|
char * dn_rdn(
|
|
|
|
Backend *be,
|
|
|
|
const char *dn_in )
|
|
|
|
{
|
2001-12-28 01:17:01 +08:00
|
|
|
struct berval bv;
|
2001-12-24 23:48:35 +08:00
|
|
|
struct berval *rdn = NULL;
|
|
|
|
char *retval;
|
|
|
|
|
|
|
|
assert( dn_in );
|
|
|
|
|
|
|
|
if ( dn_in == NULL ) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
while ( dn_in[ 0 ] && ASCII_SPACE( dn_in[ 0 ] ) ) {
|
|
|
|
dn_in++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( dn_in[ 0 ] == '\0' ) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( be != NULL && be_issuffix( be, dn_in ) ) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2001-12-28 01:17:01 +08:00
|
|
|
bv.bv_val = (char *) dn_in;
|
|
|
|
bv.bv_len = strlen( bv.bv_val );
|
|
|
|
|
|
|
|
if ( dnExtractRdn( &bv, &rdn ) != LDAP_SUCCESS ) {
|
2001-12-24 23:48:35 +08:00
|
|
|
ber_bvfree( rdn );
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
retval = rdn->bv_val;
|
|
|
|
free( rdn );
|
|
|
|
|
|
|
|
return retval;
|
2001-12-08 19:08:26 +08:00
|
|
|
}
|
1999-08-12 04:59:28 +08:00
|
|
|
|
1998-08-09 08:43:13 +08:00
|
|
|
/*
|
2001-12-24 14:00:02 +08:00
|
|
|
* dn_issuffix - tells whether suffix is a suffix of dn.
|
|
|
|
* Both dn and suffix must be normalized.
|
|
|
|
* deprecated in favor of dnIsSuffix()
|
1998-08-09 08:43:13 +08:00
|
|
|
*/
|
|
|
|
int
|
|
|
|
dn_issuffix(
|
2001-07-22 07:45:04 +08:00
|
|
|
const char *dn,
|
|
|
|
const char *suffix
|
1998-08-09 08:43:13 +08:00
|
|
|
)
|
|
|
|
{
|
2001-12-11 20:36:54 +08:00
|
|
|
struct berval bvdn, bvsuffix;
|
1998-08-09 08:43:13 +08:00
|
|
|
|
2001-12-12 15:56:17 +08:00
|
|
|
assert( dn );
|
|
|
|
assert( suffix );
|
|
|
|
|
2001-12-11 20:36:54 +08:00
|
|
|
bvdn.bv_val = (char *) dn;
|
|
|
|
bvdn.bv_len = strlen( dn );
|
|
|
|
bvsuffix.bv_val = (char *) suffix;
|
|
|
|
bvsuffix.bv_len = strlen( suffix );
|
1998-08-09 08:43:13 +08:00
|
|
|
|
2001-12-24 14:00:02 +08:00
|
|
|
return dnIsSuffix( &bvdn, &bvsuffix );
|
1998-08-09 08:43:13 +08:00
|
|
|
}
|
|
|
|
|
1999-03-04 08:31:19 +08:00
|
|
|
/* rdn_attr_type:
|
|
|
|
*
|
|
|
|
* Given a string (i.e. an rdn) of the form:
|
|
|
|
* "attribute_type = attribute_value"
|
2001-07-22 07:45:04 +08:00
|
|
|
* this function returns the type of an attribute, that is the
|
|
|
|
* string "attribute_type" which is placed in newly allocated
|
1999-03-04 08:31:19 +08:00
|
|
|
* memory. The returned string will be null-terminated.
|
2001-12-25 02:42:51 +08:00
|
|
|
*
|
|
|
|
* Deprecated
|
1999-03-04 08:31:19 +08:00
|
|
|
*/
|
|
|
|
|
2000-05-22 11:46:57 +08:00
|
|
|
char * rdn_attr_type( const char * s )
|
1999-03-04 08:31:19 +08:00
|
|
|
{
|
2001-12-25 02:42:51 +08:00
|
|
|
char **attrs, **values, *retval;
|
|
|
|
|
|
|
|
if ( rdn_attrs( s, &attrs, &values ) != LDAP_SUCCESS ) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
retval = ch_strdup( attrs[ 0 ] );
|
|
|
|
|
|
|
|
charray_free( attrs );
|
|
|
|
charray_free( values );
|
|
|
|
|
|
|
|
return retval;
|
1999-07-23 01:14:42 +08:00
|
|
|
}
|
1999-03-04 08:31:19 +08:00
|
|
|
|
|
|
|
|
|
|
|
/* rdn_attr_value:
|
|
|
|
*
|
|
|
|
* Given a string (i.e. an rdn) of the form:
|
|
|
|
* "attribute_type = attribute_value"
|
2001-07-22 07:45:04 +08:00
|
|
|
* this function returns "attribute_type" which is placed in newly allocated
|
|
|
|
* memory. The returned string will be null-terminated and may contain
|
1999-03-04 08:31:19 +08:00
|
|
|
* spaces (i.e. "John Doe\0").
|
2001-12-25 02:42:51 +08:00
|
|
|
*
|
|
|
|
* Deprecated
|
1999-03-04 08:31:19 +08:00
|
|
|
*/
|
|
|
|
|
2001-07-22 07:45:04 +08:00
|
|
|
char *
|
2000-05-22 11:46:57 +08:00
|
|
|
rdn_attr_value( const char * rdn )
|
1999-03-04 08:31:19 +08:00
|
|
|
{
|
2001-12-25 02:42:51 +08:00
|
|
|
char **attrs, **values, *retval;
|
1999-03-04 08:31:19 +08:00
|
|
|
|
2001-12-25 02:42:51 +08:00
|
|
|
if ( rdn_attrs( rdn, &attrs, &values ) != LDAP_SUCCESS ) {
|
|
|
|
return NULL;
|
1999-07-23 01:14:42 +08:00
|
|
|
}
|
1999-03-04 08:31:19 +08:00
|
|
|
|
2001-12-25 02:42:51 +08:00
|
|
|
retval = ch_strdup( values[ 0 ] );
|
|
|
|
|
|
|
|
charray_free( attrs );
|
|
|
|
charray_free( values );
|
1999-03-04 08:31:19 +08:00
|
|
|
|
2001-12-25 02:42:51 +08:00
|
|
|
return retval;
|
1999-07-23 01:14:42 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2001-07-06 20:22:01 +08:00
|
|
|
/* rdn_attrs:
|
|
|
|
*
|
|
|
|
* Given a string (i.e. an rdn) of the form:
|
2001-07-22 07:45:04 +08:00
|
|
|
* "attribute_type=attribute_value[+attribute_type=attribute_value[...]]"
|
|
|
|
* this function stores the types of the attributes in ptypes, that is the
|
|
|
|
* array of strings "attribute_type" which is placed in newly allocated
|
2001-07-06 20:22:01 +08:00
|
|
|
* memory, and the values of the attributes in pvalues, that is the
|
|
|
|
* array of strings "attribute_value" which is placed in newly allocated
|
2001-07-11 02:19:22 +08:00
|
|
|
* memory. Returns 0 on success, -1 on failure.
|
2001-07-06 20:22:01 +08:00
|
|
|
*
|
|
|
|
* note: got part of the code from dn_validate
|
2001-12-25 02:42:51 +08:00
|
|
|
*
|
|
|
|
* Deprecated; directly use LDAPRDN from ldap_str2rdn
|
2001-07-06 20:22:01 +08:00
|
|
|
*/
|
|
|
|
int
|
2001-12-25 02:42:51 +08:00
|
|
|
rdn_attrs( const char * rdn, char ***types, char ***values)
|
2001-07-06 20:22:01 +08:00
|
|
|
{
|
2001-12-25 02:42:51 +08:00
|
|
|
LDAPRDN *tmpRDN;
|
|
|
|
const char *p;
|
|
|
|
int iAVA;
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
assert( rdn );
|
|
|
|
assert( values );
|
2001-07-06 20:22:01 +08:00
|
|
|
|
2001-12-25 02:42:51 +08:00
|
|
|
rc = ldap_str2rdn( rdn, &tmpRDN, &p, LDAP_DN_FORMAT_LDAP );
|
|
|
|
if ( rc != LDAP_SUCCESS ) {
|
|
|
|
return rc;
|
|
|
|
}
|
2001-07-06 20:22:01 +08:00
|
|
|
|
2001-12-25 02:42:51 +08:00
|
|
|
for ( iAVA = 0; tmpRDN[ iAVA ]; iAVA++ ) {
|
|
|
|
LDAPAVA *ava = tmpRDN[ iAVA ][ 0 ];
|
2001-07-06 20:22:01 +08:00
|
|
|
|
2001-12-25 02:42:51 +08:00
|
|
|
assert( ava );
|
|
|
|
assert( ava->la_attr );
|
|
|
|
assert( ava->la_value );
|
2001-07-06 20:22:01 +08:00
|
|
|
|
2001-12-27 23:15:30 +08:00
|
|
|
if ( types ) {
|
|
|
|
charray_add_n( types, ava->la_attr->bv_val,
|
|
|
|
ava->la_attr->bv_len );
|
|
|
|
}
|
2001-12-25 02:42:51 +08:00
|
|
|
charray_add_n( values, ava->la_value->bv_val,
|
|
|
|
ava->la_value->bv_len );
|
2001-07-06 20:22:01 +08:00
|
|
|
}
|
|
|
|
|
2001-12-25 02:42:51 +08:00
|
|
|
ldap_rdnfree( tmpRDN );
|
2001-07-06 20:22:01 +08:00
|
|
|
|
2001-12-25 02:42:51 +08:00
|
|
|
return LDAP_SUCCESS;
|
2001-07-06 20:22:01 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2001-12-27 15:13:13 +08:00
|
|
|
/* rdnValidate:
|
2001-07-22 07:45:04 +08:00
|
|
|
*
|
2001-12-27 15:13:13 +08:00
|
|
|
* LDAP_SUCCESS if rdn is a legal rdn;
|
|
|
|
* LDAP_INVALID_SYNTAX otherwise (including a sequence of rdns)
|
2001-07-05 16:40:40 +08:00
|
|
|
*/
|
|
|
|
int
|
2001-12-27 15:13:13 +08:00
|
|
|
rdnValidate( struct berval *rdn )
|
1999-07-23 01:14:42 +08:00
|
|
|
{
|
2001-12-27 15:13:13 +08:00
|
|
|
#if 1
|
|
|
|
/* Major cheat!
|
|
|
|
* input is a pretty or normalized DN
|
|
|
|
* hence, we can just search for ','
|
|
|
|
*/
|
|
|
|
if( rdn == NULL || rdn->bv_len == 0 ) {
|
|
|
|
return LDAP_INVALID_SYNTAX;
|
|
|
|
}
|
|
|
|
|
|
|
|
return strchr( rdn->bv_val, ',' ) == NULL
|
|
|
|
? LDAP_SUCCESS : LDAP_INVALID_SYNTAX;
|
|
|
|
|
|
|
|
#else
|
2001-12-25 02:42:51 +08:00
|
|
|
LDAPRDN *RDN, **DN[ 2 ] = { &RDN, NULL };
|
|
|
|
const char *p;
|
|
|
|
int rc;
|
2001-07-05 16:40:40 +08:00
|
|
|
|
2001-12-25 02:42:51 +08:00
|
|
|
/*
|
|
|
|
* must be non-empty
|
|
|
|
*/
|
|
|
|
if ( rdn == NULL || rdn == '\0' ) {
|
|
|
|
return 0;
|
2001-07-05 16:40:40 +08:00
|
|
|
}
|
|
|
|
|
2001-12-25 02:42:51 +08:00
|
|
|
/*
|
|
|
|
* must be parsable
|
|
|
|
*/
|
|
|
|
rc = ldap_str2rdn( rdn, &RDN, &p, LDAP_DN_FORMAT_LDAP );
|
|
|
|
if ( rc != LDAP_SUCCESS ) {
|
|
|
|
return 0;
|
2001-07-05 16:40:40 +08:00
|
|
|
}
|
|
|
|
|
2001-12-25 02:42:51 +08:00
|
|
|
/*
|
|
|
|
* Must be one-level
|
|
|
|
*/
|
|
|
|
if ( p[ 0 ] != '\0' ) {
|
|
|
|
return 0;
|
2001-07-05 16:40:40 +08:00
|
|
|
}
|
|
|
|
|
2001-12-25 02:42:51 +08:00
|
|
|
/*
|
|
|
|
* Schema-aware validate
|
|
|
|
*/
|
|
|
|
if ( rc == LDAP_SUCCESS ) {
|
|
|
|
rc = LDAPDN_validate( DN );
|
2001-07-05 16:40:40 +08:00
|
|
|
}
|
2001-12-25 02:42:51 +08:00
|
|
|
ldap_rdnfree( RDN );
|
2001-07-05 16:40:40 +08:00
|
|
|
|
2001-12-25 02:42:51 +08:00
|
|
|
/*
|
|
|
|
* Must validate (there's a repeated parsing ...)
|
|
|
|
*/
|
|
|
|
return ( rc == LDAP_SUCCESS );
|
2001-12-27 15:13:13 +08:00
|
|
|
#endif
|
1999-07-23 01:14:42 +08:00
|
|
|
}
|
1999-03-25 04:26:43 +08:00
|
|
|
|
|
|
|
|
|
|
|
/* build_new_dn:
|
|
|
|
*
|
2001-07-22 07:45:04 +08:00
|
|
|
* Used by ldbm/bdb2 back_modrdn to create the new dn of entries being
|
1999-03-25 04:26:43 +08:00
|
|
|
* renamed.
|
|
|
|
*
|
2001-12-25 02:42:51 +08:00
|
|
|
* new_dn = parent (p_dn) + separator + rdn (newrdn) + null.
|
1999-03-25 04:26:43 +08:00
|
|
|
*/
|
|
|
|
|
|
|
|
void
|
2001-12-27 08:58:14 +08:00
|
|
|
build_new_dn( struct berval * new_dn,
|
|
|
|
struct berval * parent_dn,
|
|
|
|
struct berval * newrdn )
|
1999-03-25 04:26:43 +08:00
|
|
|
{
|
2001-12-27 00:25:18 +08:00
|
|
|
char *ptr;
|
1999-03-25 05:45:15 +08:00
|
|
|
|
2001-12-25 00:53:47 +08:00
|
|
|
if ( parent_dn == NULL ) {
|
2001-12-27 08:58:14 +08:00
|
|
|
ber_dupbv( new_dn, newrdn );
|
2001-07-22 07:45:04 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2001-12-27 08:58:14 +08:00
|
|
|
new_dn->bv_len = parent_dn->bv_len + newrdn->bv_len + 1;
|
|
|
|
new_dn->bv_val = (char *) ch_malloc( new_dn->bv_len + 1 );
|
1999-03-25 04:26:43 +08:00
|
|
|
|
2001-12-27 08:58:14 +08:00
|
|
|
ptr = slap_strcopy( new_dn->bv_val, newrdn->bv_val );
|
2001-12-27 00:25:18 +08:00
|
|
|
*ptr++ = ',';
|
2001-12-27 08:58:14 +08:00
|
|
|
strcpy( ptr, parent_dn->bv_val );
|
1999-07-23 01:14:42 +08:00
|
|
|
}
|
2001-12-24 12:39:15 +08:00
|
|
|
|
|
|
|
#endif /* SLAP_DN_MIGRATION */
|
2001-12-24 14:00:02 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* dnIsSuffix - tells whether suffix is a suffix of dn.
|
|
|
|
* Both dn and suffix must be normalized.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
dnIsSuffix(
|
|
|
|
const struct berval *dn,
|
|
|
|
const struct berval *suffix )
|
|
|
|
{
|
|
|
|
int d = dn->bv_len - suffix->bv_len;
|
|
|
|
|
|
|
|
assert( dn );
|
|
|
|
assert( suffix );
|
|
|
|
|
|
|
|
/* empty suffix matches any dn */
|
|
|
|
if ( suffix->bv_len == 0 ) {
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* suffix longer than dn */
|
|
|
|
if ( d < 0 ) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* no rdn separator or escaped rdn separator */
|
|
|
|
if ( d > 1 && ( !DN_SEPARATOR( dn->bv_val[ d - 1 ] )
|
|
|
|
|| DN_ESCAPE( dn->bv_val[ d - 2 ] ) ) ) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* no possible match or malformed dn */
|
|
|
|
if ( d == 1 ) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* compare */
|
|
|
|
return( strcmp( dn->bv_val + d, suffix->bv_val ) == 0 );
|
|
|
|
}
|