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 );
|
|
|
|
|
|
|
|
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 );
|
|
|
|
|
|
|
|
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
|
|
|
*
|
|
|
|
* note: uses exact string match (strcmp) because it is supposed to work
|
|
|
|
* on normalized DNs.
|
|
|
|
*/
|
|
|
|
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 ) {
|
|
|
|
match = strcmp( value->bv_val, asserted->bv_val );
|
|
|
|
}
|
|
|
|
|
|
|
|
#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-24 12:39:15 +08:00
|
|
|
struct berval val, *pretty;
|
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-05 04:22:26 +08:00
|
|
|
struct berval val, *normalized;
|
|
|
|
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 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
|
1998-08-09 08:43:13 +08:00
|
|
|
*/
|
|
|
|
char *
|
2001-12-08 18:37:42 +08:00
|
|
|
dn_parent(
|
2001-07-22 07:45:04 +08:00
|
|
|
Backend *be,
|
2001-12-08 14:57:06 +08:00
|
|
|
const char *dn )
|
1998-08-09 08:43:13 +08:00
|
|
|
{
|
1999-08-21 03:00:44 +08:00
|
|
|
const char *s;
|
1999-03-09 15:15:35 +08:00
|
|
|
int inquote;
|
1998-08-09 08:43:13 +08:00
|
|
|
|
1999-01-24 03:34:02 +08:00
|
|
|
if( dn == NULL ) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2000-02-15 04:57:34 +08:00
|
|
|
while(*dn != '\0' && ASCII_SPACE(*dn)) {
|
1999-01-24 03:34:02 +08:00
|
|
|
dn++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if( *dn == '\0' ) {
|
2000-09-29 10:50:34 +08:00
|
|
|
return NULL;
|
1999-01-24 03:34:02 +08:00
|
|
|
}
|
|
|
|
|
1999-04-29 14:50:00 +08:00
|
|
|
if ( be != NULL && be_issuffix( be, dn ) ) {
|
2000-09-29 10:50:34 +08:00
|
|
|
return NULL;
|
1998-08-09 08:43:13 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2000-02-15 04:57:34 +08:00
|
|
|
* assume it is an X.500-style name, which looks like
|
1998-08-09 08:43:13 +08:00
|
|
|
* foo=bar,sha=baz,...
|
|
|
|
*/
|
|
|
|
|
|
|
|
inquote = 0;
|
|
|
|
for ( s = dn; *s; s++ ) {
|
|
|
|
if ( *s == '\\' ) {
|
1999-01-24 03:34:02 +08:00
|
|
|
if ( *(s + 1) ) {
|
1998-08-09 08:43:13 +08:00
|
|
|
s++;
|
1999-01-24 03:34:02 +08:00
|
|
|
}
|
1998-08-09 08:43:13 +08:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if ( inquote ) {
|
1999-01-24 03:34:02 +08:00
|
|
|
if ( *s == '"' ) {
|
1998-08-09 08:43:13 +08:00
|
|
|
inquote = 0;
|
1999-01-24 03:34:02 +08:00
|
|
|
}
|
1998-08-09 08:43:13 +08:00
|
|
|
} else {
|
1999-01-24 03:34:02 +08:00
|
|
|
if ( *s == '"' ) {
|
1998-08-09 08:43:13 +08:00
|
|
|
inquote = 1;
|
2000-02-15 04:57:34 +08:00
|
|
|
} else if ( DN_SEPARATOR( *s ) ) {
|
2001-12-08 16:41:39 +08:00
|
|
|
return (char *)s + 1;
|
1999-01-24 03:34:02 +08:00
|
|
|
}
|
1998-08-09 08:43:13 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-12-08 16:41:39 +08:00
|
|
|
return "";
|
|
|
|
}
|
|
|
|
|
2001-12-08 19:08:26 +08:00
|
|
|
int dn_rdnlen(
|
2001-07-22 07:45:04 +08:00
|
|
|
Backend *be,
|
|
|
|
const char *dn_in )
|
1999-01-29 05:40:04 +08:00
|
|
|
{
|
2001-12-08 19:15:55 +08:00
|
|
|
char *s;
|
1999-03-09 15:15:35 +08:00
|
|
|
int inquote;
|
1999-01-29 05:40:04 +08:00
|
|
|
|
2000-05-22 11:46:57 +08:00
|
|
|
if( dn_in == NULL ) {
|
2001-12-08 19:08:26 +08:00
|
|
|
return 0;
|
1999-01-29 05:40:04 +08:00
|
|
|
}
|
|
|
|
|
2000-05-22 11:46:57 +08:00
|
|
|
while(*dn_in && ASCII_SPACE(*dn_in)) {
|
2000-06-14 11:59:19 +08:00
|
|
|
dn_in++;
|
1999-01-29 05:40:04 +08:00
|
|
|
}
|
|
|
|
|
2000-05-22 11:46:57 +08:00
|
|
|
if( *dn_in == '\0' ) {
|
2001-12-08 19:08:26 +08:00
|
|
|
return( 0 );
|
1999-01-29 05:40:04 +08:00
|
|
|
}
|
|
|
|
|
2000-05-22 11:46:57 +08:00
|
|
|
if ( be != NULL && be_issuffix( be, dn_in ) ) {
|
2001-12-08 19:08:26 +08:00
|
|
|
return( 0 );
|
1999-01-29 05:40:04 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
inquote = 0;
|
|
|
|
|
2001-12-08 19:15:55 +08:00
|
|
|
for ( s = (char *)dn_in; *s; s++ ) {
|
1999-01-29 05:40:04 +08:00
|
|
|
if ( *s == '\\' ) {
|
|
|
|
if ( *(s + 1) ) {
|
|
|
|
s++;
|
|
|
|
}
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if ( inquote ) {
|
|
|
|
if ( *s == '"' ) {
|
|
|
|
inquote = 0;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if ( *s == '"' ) {
|
|
|
|
inquote = 1;
|
2000-02-15 04:57:34 +08:00
|
|
|
} else if ( DN_SEPARATOR( *s ) ) {
|
2001-12-08 19:08:26 +08:00
|
|
|
break;
|
1999-01-29 05:40:04 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-12-08 19:15:55 +08:00
|
|
|
return( s - dn_in );
|
1999-01-29 05:40:04 +08:00
|
|
|
}
|
|
|
|
|
2001-12-08 19:08:26 +08:00
|
|
|
char * dn_rdn(
|
|
|
|
Backend *be,
|
|
|
|
const char *dn_in )
|
|
|
|
{
|
|
|
|
char *rdn;
|
|
|
|
int i = dn_rdnlen( be, dn_in );
|
|
|
|
|
|
|
|
rdn = ch_malloc( i + 1 );
|
|
|
|
strncpy(rdn, dn_in, i);
|
|
|
|
rdn[i] = '\0';
|
|
|
|
return rdn;
|
|
|
|
}
|
1999-08-12 04:59:28 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* return a charray of all subtrees to which the DN resides in
|
|
|
|
*/
|
|
|
|
char **dn_subtree(
|
|
|
|
Backend *be,
|
2001-07-22 07:45:04 +08:00
|
|
|
const char *dn )
|
1999-08-12 04:59:28 +08:00
|
|
|
{
|
1999-08-12 12:20:32 +08:00
|
|
|
char **subtree = NULL;
|
|
|
|
|
|
|
|
do {
|
2001-12-08 16:41:39 +08:00
|
|
|
charray_add( &subtree, dn );
|
1999-08-12 12:20:32 +08:00
|
|
|
|
2001-12-08 18:37:42 +08:00
|
|
|
dn = dn_parent( be, dn );
|
1999-08-12 12:20:32 +08:00
|
|
|
|
2001-12-08 16:41:39 +08:00
|
|
|
} while ( dn != NULL );
|
1999-08-12 12:20:32 +08:00
|
|
|
|
|
|
|
return subtree;
|
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
|
|
|
/*
|
1999-03-25 04:26:43 +08:00
|
|
|
* get_next_substring(), rdn_attr_type(), rdn_attr_value(), and
|
|
|
|
* build_new_dn().
|
2001-07-22 07:45:04 +08:00
|
|
|
*
|
1999-03-04 08:31:19 +08:00
|
|
|
* Copyright 1999, Juan C. Gomez, All rights reserved.
|
2001-07-22 07:45:04 +08:00
|
|
|
* This software is not subject to any license of Silicon Graphics
|
1999-03-04 08:31:19 +08:00
|
|
|
* Inc. or Purdue University.
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms are permitted
|
|
|
|
* without restriction or fee of any kind as long as this notice
|
|
|
|
* is preserved.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* get_next_substring:
|
|
|
|
*
|
2001-07-22 07:45:04 +08:00
|
|
|
* Gets next substring in s, using d (or the end of the string '\0') as a
|
|
|
|
* string delimiter, and places it in a duplicated memory space. Leading
|
1999-03-04 08:31:19 +08:00
|
|
|
* spaces are ignored. String s **must** be null-terminated.
|
2001-07-22 07:45:04 +08:00
|
|
|
*/
|
1999-03-04 08:31:19 +08:00
|
|
|
|
2001-07-22 07:45:04 +08:00
|
|
|
static char *
|
2000-05-22 11:46:57 +08:00
|
|
|
get_next_substring( const char * s, char d )
|
1999-03-04 08:31:19 +08:00
|
|
|
{
|
|
|
|
|
|
|
|
char *str, *r;
|
|
|
|
|
|
|
|
r = str = ch_malloc( strlen(s) + 1 );
|
|
|
|
|
|
|
|
/* Skip leading spaces */
|
|
|
|
|
2000-02-15 04:57:34 +08:00
|
|
|
while ( *s && ASCII_SPACE(*s) ) {
|
1999-03-04 08:31:19 +08:00
|
|
|
s++;
|
1999-07-23 01:14:42 +08:00
|
|
|
}
|
1999-03-04 08:31:19 +08:00
|
|
|
|
|
|
|
/* Copy word */
|
|
|
|
|
|
|
|
while ( *s && (*s != d) ) {
|
|
|
|
|
|
|
|
/* Don't stop when you see trailing spaces may be a multi-word
|
|
|
|
* string, i.e. name=John Doe!
|
|
|
|
*/
|
|
|
|
|
|
|
|
*str++ = *s++;
|
1999-07-23 01:14:42 +08:00
|
|
|
}
|
1999-03-04 08:31:19 +08:00
|
|
|
|
|
|
|
*str = '\0';
|
|
|
|
|
|
|
|
return r;
|
|
|
|
|
1999-07-23 01:14:42 +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.
|
|
|
|
*/
|
|
|
|
|
2000-05-22 11:46:57 +08:00
|
|
|
char * rdn_attr_type( const char * s )
|
1999-03-04 08:31:19 +08:00
|
|
|
{
|
|
|
|
return get_next_substring( s, '=' );
|
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-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
|
|
|
{
|
|
|
|
|
2000-05-22 11:46:57 +08:00
|
|
|
const char *str;
|
1999-03-04 08:31:19 +08:00
|
|
|
|
|
|
|
if ( (str = strchr( rdn, '=' )) != NULL ) {
|
|
|
|
return get_next_substring(++str, '\0');
|
1999-07-23 01:14:42 +08:00
|
|
|
}
|
1999-03-04 08:31:19 +08:00
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
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-07-11 02:19:22 +08:00
|
|
|
|
2001-07-06 20:22:01 +08:00
|
|
|
int
|
|
|
|
rdn_attrs( const char * rdn_in, char ***ptypes, char ***pvalues)
|
|
|
|
{
|
2001-07-11 02:19:22 +08:00
|
|
|
char **parts, **p;
|
2001-07-06 20:22:01 +08:00
|
|
|
|
|
|
|
*ptypes = NULL;
|
|
|
|
*pvalues = NULL;
|
|
|
|
|
2001-07-11 02:19:22 +08:00
|
|
|
/*
|
|
|
|
* explode the rdn in parts
|
|
|
|
*/
|
|
|
|
parts = ldap_explode_rdn( rdn_in, 0 );
|
2001-07-06 20:22:01 +08:00
|
|
|
|
2001-07-11 02:19:22 +08:00
|
|
|
if ( parts == NULL ) {
|
|
|
|
return( -1 );
|
2001-07-06 20:22:01 +08:00
|
|
|
}
|
|
|
|
|
2001-07-11 02:19:22 +08:00
|
|
|
for ( p = parts; p[0]; p++ ) {
|
|
|
|
char *s, *e, *d;
|
|
|
|
|
|
|
|
/* split each rdn part in type value */
|
|
|
|
s = strchr( p[0], '=' );
|
|
|
|
if ( s == NULL ) {
|
|
|
|
charray_free( *ptypes );
|
|
|
|
charray_free( *pvalues );
|
|
|
|
charray_free( parts );
|
|
|
|
return( -1 );
|
2001-07-06 20:22:01 +08:00
|
|
|
}
|
2001-07-11 02:19:22 +08:00
|
|
|
|
|
|
|
/* type should be fine */
|
|
|
|
charray_add_n( ptypes, p[0], ( s-p[0] ) );
|
|
|
|
|
2001-07-22 07:45:04 +08:00
|
|
|
/* value needs to be unescaped
|
2001-07-11 02:19:22 +08:00
|
|
|
* (maybe this should be moved to ldap_explode_rdn?) */
|
|
|
|
for ( e = d = s + 1; e[0]; e++ ) {
|
|
|
|
if ( *e != '\\' ) {
|
|
|
|
*d++ = *e;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
d[0] = '\0';
|
|
|
|
charray_add( pvalues, s + 1 );
|
2001-07-06 20:22:01 +08:00
|
|
|
}
|
|
|
|
|
2001-07-11 02:19:22 +08:00
|
|
|
/* free array */
|
|
|
|
charray_free( parts );
|
2001-07-06 20:22:01 +08:00
|
|
|
|
|
|
|
return( 0 );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2001-07-05 16:40:40 +08:00
|
|
|
/* rdn_validate:
|
2001-07-22 07:45:04 +08:00
|
|
|
*
|
|
|
|
* 1 if rdn is a legal rdn;
|
2001-07-05 16:40:40 +08:00
|
|
|
* 0 otherwise (including a sequence of rdns)
|
2001-07-06 04:33:15 +08:00
|
|
|
*
|
2001-07-22 07:45:04 +08:00
|
|
|
* note: got it from dn_rdn; it should be rewritten
|
2001-07-06 04:33:15 +08:00
|
|
|
* according to dn_validate
|
2001-07-05 16:40:40 +08:00
|
|
|
*/
|
|
|
|
int
|
|
|
|
rdn_validate( const char * rdn )
|
1999-07-23 01:14:42 +08:00
|
|
|
{
|
2001-07-05 16:40:40 +08:00
|
|
|
int inquote;
|
|
|
|
|
|
|
|
if ( rdn == NULL ) {
|
|
|
|
return( 0 );
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( strchr( rdn, '=' ) == NULL ) {
|
|
|
|
return( 0 );
|
|
|
|
}
|
|
|
|
|
|
|
|
while ( *rdn && ASCII_SPACE( *rdn ) ) {
|
|
|
|
rdn++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if( *rdn == '\0' ) {
|
|
|
|
return( 0 );
|
|
|
|
}
|
|
|
|
|
|
|
|
inquote = 0;
|
|
|
|
|
|
|
|
for ( ; *rdn; rdn++ ) {
|
|
|
|
if ( *rdn == '\\' ) {
|
|
|
|
if ( *(rdn + 1) ) {
|
|
|
|
rdn++;
|
|
|
|
}
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if ( inquote ) {
|
|
|
|
if ( *rdn == '"' ) {
|
|
|
|
inquote = 0;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if ( *rdn == '"' ) {
|
|
|
|
inquote = 1;
|
|
|
|
} else if ( DN_SEPARATOR( *rdn ) ) {
|
|
|
|
return( 0 );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return( 1 );
|
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-07-22 07:45:04 +08:00
|
|
|
* new_dn = parent (p_dn) + separator(s) + rdn (newrdn) + null.
|
1999-03-25 04:26:43 +08:00
|
|
|
*/
|
|
|
|
|
|
|
|
void
|
1999-08-21 03:00:44 +08:00
|
|
|
build_new_dn( char ** new_dn,
|
|
|
|
const char *e_dn,
|
|
|
|
const char * p_dn,
|
|
|
|
const char * newrdn )
|
1999-03-25 04:26:43 +08:00
|
|
|
{
|
1999-03-25 05:45:15 +08:00
|
|
|
|
2001-07-22 07:45:04 +08:00
|
|
|
if ( p_dn == NULL ) {
|
|
|
|
*new_dn = ch_strdup( newrdn );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
*new_dn = (char *) ch_malloc( strlen( p_dn ) + strlen( newrdn ) + 3 );
|
1999-03-25 04:26:43 +08:00
|
|
|
|
|
|
|
strcpy( *new_dn, newrdn );
|
1999-03-25 05:45:15 +08:00
|
|
|
strcat( *new_dn, "," );
|
1999-03-25 04:26:43 +08:00
|
|
|
strcat( *new_dn, p_dn );
|
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 );
|
|
|
|
}
|