mirror of
https://git.openldap.org/openldap/openldap.git
synced 2025-03-31 14:50:34 +08:00
Modrdn fix to support deleteoldrdn (LDAP v2).
This commit is contained in:
parent
9f0a274a5b
commit
991042b89f
@ -14,37 +14,114 @@
|
||||
static int add_values(Entry *e, LDAPMod *mod, char *dn);
|
||||
static int delete_values(Entry *e, LDAPMod *mod, char *dn);
|
||||
static int replace_values(Entry *e, LDAPMod *mod, char *dn);
|
||||
static void add_lastmods(Operation *op, LDAPMod **mods);
|
||||
|
||||
int
|
||||
ldbm_back_modify(
|
||||
|
||||
static void
|
||||
add_lastmods( Operation *op, LDAPMod **mods )
|
||||
{
|
||||
char buf[22];
|
||||
struct berval bv;
|
||||
struct berval *bvals[2];
|
||||
LDAPMod **m;
|
||||
LDAPMod *tmp;
|
||||
struct tm *ltm;
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "add_lastmods\n", 0, 0, 0 );
|
||||
|
||||
bvals[0] = &bv;
|
||||
bvals[1] = NULL;
|
||||
|
||||
/* remove any attempts by the user to modify these attrs */
|
||||
for ( m = mods; *m != NULL; m = &(*m)->mod_next ) {
|
||||
if ( strcasecmp( (*m)->mod_type, "modifytimestamp" ) == 0 ||
|
||||
strcasecmp( (*m)->mod_type, "modifiersname" ) == 0 ||
|
||||
strcasecmp( (*m)->mod_type, "createtimestamp" ) == 0 ||
|
||||
strcasecmp( (*m)->mod_type, "creatorsname" ) == 0 ) {
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"add_lastmods: found lastmod attr: %s\n",
|
||||
(*m)->mod_type, 0, 0 );
|
||||
tmp = *m;
|
||||
*m = (*m)->mod_next;
|
||||
free( tmp->mod_type );
|
||||
if ( tmp->mod_bvalues != NULL ) {
|
||||
ber_bvecfree( tmp->mod_bvalues );
|
||||
}
|
||||
free( tmp );
|
||||
if (!*m)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( op->o_dn == NULL || op->o_dn[0] == '\0' ) {
|
||||
bv.bv_val = "NULLDN";
|
||||
bv.bv_len = strlen( bv.bv_val );
|
||||
} else {
|
||||
bv.bv_val = op->o_dn;
|
||||
bv.bv_len = strlen( bv.bv_val );
|
||||
}
|
||||
tmp = (LDAPMod *) ch_calloc( 1, sizeof(LDAPMod) );
|
||||
tmp->mod_type = ch_strdup( "modifiersname" );
|
||||
tmp->mod_op = LDAP_MOD_REPLACE;
|
||||
tmp->mod_bvalues = (struct berval **) ch_calloc( 1,
|
||||
2 * sizeof(struct berval *) );
|
||||
tmp->mod_bvalues[0] = ber_bvdup( &bv );
|
||||
tmp->mod_next = *mods;
|
||||
*mods = tmp;
|
||||
|
||||
ldap_pvt_thread_mutex_lock( ¤ttime_mutex );
|
||||
#ifndef LDAP_LOCALTIME
|
||||
ltm = gmtime( ¤ttime );
|
||||
strftime( buf, sizeof(buf), "%Y%m%d%H%M%SZ", ltm );
|
||||
#else
|
||||
ltm = localtime( ¤ttime );
|
||||
strftime( buf, sizeof(buf), "%y%m%d%H%M%SZ", ltm );
|
||||
#endif
|
||||
ldap_pvt_thread_mutex_unlock( ¤ttime_mutex );
|
||||
bv.bv_val = buf;
|
||||
bv.bv_len = strlen( bv.bv_val );
|
||||
tmp = (LDAPMod *) ch_calloc( 1, sizeof(LDAPMod) );
|
||||
tmp->mod_type = ch_strdup( "modifytimestamp" );
|
||||
tmp->mod_op = LDAP_MOD_REPLACE;
|
||||
tmp->mod_bvalues = (struct berval **) ch_calloc( 1, 2 * sizeof(struct berval *) );
|
||||
tmp->mod_bvalues[0] = ber_bvdup( &bv );
|
||||
tmp->mod_next = *mods;
|
||||
*mods = tmp;
|
||||
}
|
||||
|
||||
/* We need this function because of LDAP modrdn. If we do not
|
||||
* add this there would be a bunch of code replication here
|
||||
* and there and of course the likelihood of bugs increases.
|
||||
* Juan C. Gomez (gomez@engr.sgi.com) 05/18/99
|
||||
*/
|
||||
|
||||
int ldbm_internal_modify(
|
||||
Backend *be,
|
||||
Connection *conn,
|
||||
Operation *op,
|
||||
char *dn,
|
||||
LDAPMod *mods
|
||||
LDAPMod *mods,
|
||||
Entry *e
|
||||
)
|
||||
{
|
||||
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
|
||||
char *matched;
|
||||
Entry *e;
|
||||
int i, err;
|
||||
LDAPMod *mod;
|
||||
|
||||
Debug(LDAP_DEBUG_ARGS, "ldbm_back_modify:\n", 0, 0, 0);
|
||||
if ( ((be->be_lastmod == ON)
|
||||
|| ((be->be_lastmod == UNDEFINED)&&(global_lastmod == ON)))
|
||||
&& (be->be_update_ndn == NULL)) {
|
||||
|
||||
/* XXX: It may be wrong, it changes mod time even if
|
||||
* mod fails!
|
||||
*/
|
||||
add_lastmods( op, &mods );
|
||||
|
||||
/* acquire and lock entry */
|
||||
if ( (e = dn2entry_w( be, dn, &matched )) == NULL ) {
|
||||
send_ldap_result( conn, op, LDAP_NO_SUCH_OBJECT, matched,
|
||||
NULL );
|
||||
if ( matched != NULL ) {
|
||||
free( matched );
|
||||
}
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
if ( (err = acl_check_mods( be, conn, op, e, mods )) != LDAP_SUCCESS ) {
|
||||
send_ldap_result( conn, op, err, NULL, NULL );
|
||||
goto error_return;
|
||||
return -1;
|
||||
}
|
||||
|
||||
for ( mod = mods; mod != NULL; mod = mod->mod_next ) {
|
||||
@ -65,7 +142,7 @@ ldbm_back_modify(
|
||||
if ( err != LDAP_SUCCESS ) {
|
||||
/* unlock entry, delete from cache */
|
||||
send_ldap_result( conn, op, err, NULL, NULL );
|
||||
goto error_return;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
@ -73,35 +150,73 @@ ldbm_back_modify(
|
||||
if ( global_schemacheck && oc_schema_check( e ) != 0 ) {
|
||||
Debug( LDAP_DEBUG_ANY, "entry failed schema check\n", 0, 0, 0 );
|
||||
send_ldap_result( conn, op, LDAP_OBJECT_CLASS_VIOLATION, NULL, NULL );
|
||||
goto error_return;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* check for abandon */
|
||||
ldap_pvt_thread_mutex_lock( &op->o_abandonmutex );
|
||||
if ( op->o_abandon ) {
|
||||
ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
|
||||
goto error_return;
|
||||
return -1;
|
||||
}
|
||||
ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
|
||||
|
||||
/* modify indexes */
|
||||
if ( index_add_mods( be, mods, e->e_id ) != 0 ) {
|
||||
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL, NULL );
|
||||
goto error_return;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* check for abandon */
|
||||
ldap_pvt_thread_mutex_lock( &op->o_abandonmutex );
|
||||
if ( op->o_abandon ) {
|
||||
ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
|
||||
goto error_return;
|
||||
return -1;
|
||||
}
|
||||
ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
|
||||
|
||||
return 0;
|
||||
|
||||
}/* int ldbm_internal_modify() */
|
||||
|
||||
|
||||
int
|
||||
ldbm_back_modify(
|
||||
Backend *be,
|
||||
Connection *conn,
|
||||
Operation *op,
|
||||
char *dn,
|
||||
LDAPMod *mods
|
||||
)
|
||||
{
|
||||
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
|
||||
char *matched;
|
||||
Entry *e;
|
||||
|
||||
Debug(LDAP_DEBUG_ARGS, "ldbm_back_modify:\n", 0, 0, 0);
|
||||
|
||||
/* acquire and lock entry */
|
||||
if ( (e = dn2entry_w( be, dn, &matched )) == NULL ) {
|
||||
send_ldap_result( conn, op, LDAP_NO_SUCH_OBJECT, matched,
|
||||
NULL );
|
||||
if ( matched != NULL ) {
|
||||
free( matched );
|
||||
}
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
/* Modify the entry */
|
||||
if ( ldbm_internal_modify( be, conn, op, dn, mods, e ) != 0 ) {
|
||||
|
||||
goto error_return;
|
||||
|
||||
}
|
||||
|
||||
/* change the entry itself */
|
||||
if ( id2entry_add( be, e ) != 0 ) {
|
||||
entry_free( e );
|
||||
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL, NULL );
|
||||
goto error_return;
|
||||
return -1;
|
||||
}
|
||||
|
||||
send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL );
|
||||
|
@ -27,8 +27,23 @@ ldbm_back_modrdn(
|
||||
char *new_dn = NULL, *new_ndn = NULL;
|
||||
char sep[2];
|
||||
Entry *e, *p = NULL;
|
||||
int rootlock = 0;
|
||||
int rc = -1;
|
||||
int rootlock = 0;
|
||||
int rc = -1;
|
||||
|
||||
char *new_rdn_val = NULL; /* Val of new rdn */
|
||||
char *new_rdn_type = NULL; /* Type of new rdn */
|
||||
char *old_rdn; /* Old rdn's attr type & val */
|
||||
char *old_rdn_type = NULL; /* Type of old rdn attr. */
|
||||
char *old_rdn_val = NULL; /* Old rdn attribute value */
|
||||
struct berval add_bv; /* Stores new rdn att */
|
||||
struct berval *add_bvals[2]; /* Stores new rdn att */
|
||||
struct berval del_bv; /* Stores old rdn att */
|
||||
struct berval *del_bvals[2]; /* Stores old rdn att */
|
||||
LDAPMod mod[2]; /* Used to delete old rdn */
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"ldbm_back_modrdn:()==>\n",
|
||||
0, 0, 0 );
|
||||
|
||||
/* get entry with writer lock */
|
||||
if ( (e = dn2entry_w( be, dn, &matched )) == NULL ) {
|
||||
@ -76,26 +91,7 @@ ldbm_back_modrdn(
|
||||
#endif
|
||||
|
||||
p_dn = dn_parent( be, e->e_dn );
|
||||
new_dn = (char *) ch_malloc( strlen( p_dn ) + strlen( newrdn )
|
||||
+ 3 );
|
||||
if ( dn_type( e->e_dn ) == DN_X500 ) {
|
||||
strcpy( new_dn, newrdn );
|
||||
strcat( new_dn, "," );
|
||||
strcat( new_dn, p_dn );
|
||||
} else {
|
||||
char *s;
|
||||
strcpy( new_dn, newrdn );
|
||||
s = strchr( newrdn, '\0' );
|
||||
s--;
|
||||
if ( *s != '.' && *s != '@' ) {
|
||||
if ( (s = strpbrk( dn, ".@" )) != NULL ) {
|
||||
sep[0] = *s;
|
||||
sep[1] = '\0';
|
||||
strcat( new_dn, sep );
|
||||
}
|
||||
}
|
||||
strcat( new_dn, p_dn );
|
||||
}
|
||||
|
||||
|
||||
} else {
|
||||
/* no parent, modrdn entry directly under root */
|
||||
@ -110,11 +106,154 @@ ldbm_back_modrdn(
|
||||
ldap_pvt_thread_mutex_lock(&li->li_root_mutex);
|
||||
rootlock = 1;
|
||||
|
||||
new_dn = ch_strdup( newrdn );
|
||||
|
||||
}
|
||||
|
||||
build_new_dn( &new_dn, e->e_dn, p_dn, newrdn );
|
||||
new_ndn = dn_normalize_case( ch_strdup( new_dn ) );
|
||||
|
||||
/* Get attribute type and attribute value of our new rdn, we will
|
||||
* need to add that to our new entry
|
||||
*/
|
||||
|
||||
if ( (new_rdn_type = rdn_attr_type( newrdn )) == NULL ) {
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"ldbm_back_modrdn: can't figure out type of newrdn\n",
|
||||
0, 0, 0 );
|
||||
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
|
||||
goto return_results;
|
||||
|
||||
}
|
||||
|
||||
if ( (new_rdn_val = rdn_attr_value( newrdn )) == NULL ) {
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"ldbm_back_modrdn: can't figure out val of newrdn\n",
|
||||
0, 0, 0 );
|
||||
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
|
||||
goto return_results;
|
||||
|
||||
}
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"ldbm_back_modrdn: new_rdn_val=\"%s\", new_rdn_type=\"%s\"\n",
|
||||
new_rdn_val, new_rdn_type, 0 );
|
||||
|
||||
/* Retrieve the old rdn from the entry's dn */
|
||||
|
||||
if ( (old_rdn = dn_rdn( be, dn )) == NULL ) {
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"ldbm_back_modrdn: can't figure out old_rdn from dn\n",
|
||||
0, 0, 0 );
|
||||
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
|
||||
goto return_results;
|
||||
|
||||
}
|
||||
|
||||
if ( (old_rdn_type = rdn_attr_type( old_rdn )) == NULL ) {
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"ldbm_back_modrdn: can't figure out the old_rdn type\n",
|
||||
0, 0, 0 );
|
||||
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
|
||||
goto return_results;
|
||||
|
||||
}
|
||||
|
||||
if ( strcasecmp( old_rdn_type, new_rdn_type ) != 0 ) {
|
||||
|
||||
/* Not a big deal but we may say something */
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"ldbm_back_modrdn: old_rdn_type=%s, new_rdn_type=%s!\n",
|
||||
old_rdn_type, new_rdn_type, 0 );
|
||||
|
||||
}
|
||||
|
||||
if ( dn_type( old_rdn ) == DN_X500 ) {
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "ldbm_back_modrdn: DN_X500\n",
|
||||
0, 0, 0 );
|
||||
|
||||
/* Add new attribute value to the entry.
|
||||
*/
|
||||
|
||||
add_bvals[0] = &add_bv; /* Array of bervals */
|
||||
add_bvals[1] = NULL;
|
||||
|
||||
add_bv.bv_val = new_rdn_val;
|
||||
add_bv.bv_len = strlen(new_rdn_val);
|
||||
|
||||
mod[0].mod_type = old_rdn_type;
|
||||
mod[0].mod_bvalues = add_bvals;
|
||||
mod[0].mod_op = LDAP_MOD_ADD;
|
||||
mod[0].mod_next = NULL;
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"ldbm_back_modrdn: adding new rdn attr val =\"%s\"\n",
|
||||
new_rdn_val, 0, 0 );
|
||||
|
||||
/* Remove old rdn value if required */
|
||||
|
||||
if (deleteoldrdn) {
|
||||
|
||||
del_bvals[0] = &del_bv; /* Array of bervals */
|
||||
del_bvals[1] = NULL;
|
||||
/* Get value of old rdn */
|
||||
|
||||
if ((old_rdn_val = rdn_attr_value( old_rdn ))
|
||||
== NULL) {
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"ldbm_back_modrdn: can't figure out old_rdn_val from old_rdn\n",
|
||||
0, 0, 0 );
|
||||
send_ldap_result( conn, op,
|
||||
LDAP_OPERATIONS_ERROR,
|
||||
"", "" );
|
||||
goto return_results;
|
||||
|
||||
|
||||
}
|
||||
|
||||
/* Remove old value of rdn as an attribute. */
|
||||
|
||||
del_bv.bv_val = old_rdn_val;
|
||||
del_bv.bv_len = strlen(old_rdn_val);
|
||||
|
||||
/* No need to normalize old_rdn_type, delete_values()
|
||||
* does that for us
|
||||
*/
|
||||
mod[0].mod_next = &mod[1];
|
||||
mod[1].mod_type = old_rdn_type;
|
||||
mod[1].mod_bvalues = del_bvals;
|
||||
mod[1].mod_op = LDAP_MOD_DELETE;
|
||||
mod[1].mod_next = NULL;
|
||||
|
||||
}/* if (deleteoldrdn) */
|
||||
|
||||
/* modify memory copy of entry */
|
||||
if ( ldbm_internal_modify( be, conn, op, dn, &mod[0], e )
|
||||
!= 0 ) {
|
||||
|
||||
goto return_results;
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "ldbm_back_modrdn: DNS DN\n",
|
||||
0, 0, 0 );
|
||||
/* XXXV3: not sure of what to do here */
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"ldbm_back_modrdn: not fully implemented...\n",
|
||||
0, 0, 0 );
|
||||
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL, NULL );
|
||||
goto return_results;
|
||||
|
||||
}
|
||||
|
||||
if ( (dn2id ( be, new_ndn ) ) != NOID ) {
|
||||
send_ldap_result( conn, op, LDAP_ALREADY_EXISTS, NULL, NULL );
|
||||
goto return_results;
|
||||
@ -140,6 +279,7 @@ ldbm_back_modrdn(
|
||||
goto return_results;
|
||||
}
|
||||
|
||||
|
||||
(void) cache_delete_entry( &li->li_cache, e );
|
||||
free( e->e_dn );
|
||||
free( e->e_ndn );
|
||||
@ -147,33 +287,41 @@ ldbm_back_modrdn(
|
||||
e->e_ndn = new_ndn;
|
||||
(void) cache_update_entry( &li->li_cache, e );
|
||||
|
||||
/* XXX
|
||||
* At some point here we need to update the attribute values in
|
||||
* the entry itself that were effected by this RDN change
|
||||
* (respecting the value of the deleteoldrdn parameter).
|
||||
*
|
||||
* Since the code to do this has not yet been written, treat this
|
||||
* omission as a (documented) bug.
|
||||
*/
|
||||
|
||||
/* id2entry index */
|
||||
/* id2entry index: commit */
|
||||
if ( id2entry_add( be, e ) != 0 ) {
|
||||
entry_free( e );
|
||||
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
|
||||
goto return_results;
|
||||
goto return_results_new;
|
||||
}
|
||||
|
||||
send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL );
|
||||
rc = 0;
|
||||
|
||||
return_results:
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"ldbm_back_modrdn:()<==\n",
|
||||
0, 0, 0 );
|
||||
goto return_results_new;
|
||||
|
||||
return_results:
|
||||
if( new_dn != NULL ) free( new_dn );
|
||||
if( new_ndn != NULL ) free( new_ndn );
|
||||
return_results_new:
|
||||
/* NOTE:
|
||||
* new_dn and new_ndn are not deallocated because they are used by
|
||||
* the cache entry at this point.
|
||||
*/
|
||||
if( p_dn != NULL ) free( p_dn );
|
||||
if( p_ndn != NULL ) free( p_ndn );
|
||||
|
||||
if( matched != NULL ) free( matched );
|
||||
|
||||
/* LDAP v2 supporting correct attribute handling. */
|
||||
if( new_rdn_type != NULL ) free(new_rdn_type);
|
||||
if( new_rdn_val != NULL ) free(new_rdn_val);
|
||||
if( old_rdn != NULL ) free(old_rdn);
|
||||
if( old_rdn_type != NULL ) free(old_rdn_type);
|
||||
if( old_rdn_val != NULL ) free(old_rdn_val);
|
||||
|
||||
if( p != NULL ) {
|
||||
/* free parent and writer lock */
|
||||
cache_return_entry_w( &li->li_cache, p );
|
||||
|
@ -122,6 +122,18 @@ int index_add_values LDAP_P(( Backend *be, char *type, struct berval **vals, ID
|
||||
/* krbv4_ldap_auth LDAP_P(( Backend *be, struct berval *cred, AUTH_DAT *ad )); */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* modify.c
|
||||
*/
|
||||
|
||||
/* We need this function because of LDAP modrdn. If we do not
|
||||
* add this there would be a bunch of code replication here
|
||||
* and there and of course the likelihood of bugs increases.
|
||||
* Juan C. Gomez (gomez@engr.sgi.com) 05/18/99
|
||||
*/
|
||||
int ldbm_internal_modify LDAP_P((Backend *be, Connection *conn, Operation *op,
|
||||
char *dn, LDAPMod *mods, Entry *e));
|
||||
|
||||
/*
|
||||
* nextid.c
|
||||
*/
|
||||
|
@ -220,6 +220,77 @@ dn_parent(
|
||||
return( ch_strdup( "" ) );
|
||||
}
|
||||
|
||||
char * dn_rdn(
|
||||
Backend *be,
|
||||
char *dn )
|
||||
{
|
||||
char *s;
|
||||
int inquote;
|
||||
|
||||
if( dn == NULL ) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
while(*dn && SPACE(*dn)) {
|
||||
dn++;
|
||||
}
|
||||
|
||||
if( *dn == '\0' ) {
|
||||
return( NULL );
|
||||
}
|
||||
|
||||
if ( be != NULL && be_issuffix( be, dn ) ) {
|
||||
return( NULL );
|
||||
}
|
||||
|
||||
dn = ch_strdup( dn );
|
||||
|
||||
/*
|
||||
* no =, assume it is a dns name, like blah@some.domain.name
|
||||
* if the blah@ part is there, return some.domain.name. if
|
||||
* it's just some.domain.name, return domain.name.
|
||||
*/
|
||||
if ( strchr( dn, '=' ) == NULL ) {
|
||||
if ( (s = strchr( dn, '@' )) == NULL ) {
|
||||
if ( (s = strchr( dn, '.' )) == NULL ) {
|
||||
return( dn );
|
||||
}
|
||||
}
|
||||
*s = '\0';
|
||||
return( dn );
|
||||
}
|
||||
|
||||
/*
|
||||
* else assume it is an X.500-style name, which looks like
|
||||
* foo=bar,sha=baz,...
|
||||
*/
|
||||
|
||||
inquote = 0;
|
||||
|
||||
for ( s = dn; *s; s++ ) {
|
||||
if ( *s == '\\' ) {
|
||||
if ( *(s + 1) ) {
|
||||
s++;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if ( inquote ) {
|
||||
if ( *s == '"' ) {
|
||||
inquote = 0;
|
||||
}
|
||||
} else {
|
||||
if ( *s == '"' ) {
|
||||
inquote = 1;
|
||||
} else if ( DNSEPARATOR( *s ) ) {
|
||||
*s = '\0';
|
||||
return( dn );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return( dn );
|
||||
}
|
||||
|
||||
/*
|
||||
* dn_issuffix - tells whether suffix is a suffix of dn. both dn
|
||||
* and suffix must be normalized.
|
||||
@ -271,3 +342,156 @@ dn_upcase( char *dn )
|
||||
|
||||
return( dn );
|
||||
}
|
||||
|
||||
/*
|
||||
* get_next_substring(), rdn_attr_type(), rdn_attr_value(), and
|
||||
* build_new_dn().
|
||||
*
|
||||
* Copyright 1999, Juan C. Gomez, All rights reserved.
|
||||
* This software is not subject to any license of Silicon Graphics
|
||||
* 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:
|
||||
*
|
||||
* 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
|
||||
* spaces are ignored. String s **must** be null-terminated.
|
||||
*/
|
||||
|
||||
static char *
|
||||
get_next_substring( char * s, char d )
|
||||
{
|
||||
|
||||
char *str, *r;
|
||||
|
||||
r = str = ch_malloc( strlen(s) + 1 );
|
||||
|
||||
/* Skip leading spaces */
|
||||
|
||||
while ( *s && SPACE(*s) ) {
|
||||
|
||||
s++;
|
||||
|
||||
}/* while ( *s && SPACE(*s) ) */
|
||||
|
||||
/* 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++;
|
||||
|
||||
}/* while ( *s && (*s != d) ) */
|
||||
|
||||
*str = '\0';
|
||||
|
||||
return r;
|
||||
|
||||
}/* char * get_word() */
|
||||
|
||||
|
||||
/* rdn_attr_type:
|
||||
*
|
||||
* Given a string (i.e. an rdn) of the form:
|
||||
* "attribute_type = attribute_value"
|
||||
* this function returns the type of an attribute, that is the
|
||||
* string "attribute_type" which is placed in newly allocated
|
||||
* memory. The returned string will be null-terminated.
|
||||
*/
|
||||
|
||||
char * rdn_attr_type( char * s )
|
||||
{
|
||||
|
||||
return get_next_substring( s, '=' );
|
||||
|
||||
}/* char * rdn_attr_type() */
|
||||
|
||||
|
||||
/* rdn_attr_value:
|
||||
*
|
||||
* Given a string (i.e. an rdn) of the form:
|
||||
* "attribute_type = attribute_value"
|
||||
* this function returns "attribute_type" which is placed in newly allocated
|
||||
* memory. The returned string will be null-terminated and may contain
|
||||
* spaces (i.e. "John Doe\0").
|
||||
*/
|
||||
|
||||
char *
|
||||
rdn_attr_value( char * rdn )
|
||||
{
|
||||
|
||||
char *str;
|
||||
|
||||
if ( (str = strchr( rdn, '=' )) != NULL ) {
|
||||
|
||||
return get_next_substring(++str, '\0');
|
||||
|
||||
}/* if ( (str = strpbrk( rdn, "=" )) != NULL ) */
|
||||
|
||||
return NULL;
|
||||
|
||||
}/* char * rdn_attr_value() */
|
||||
|
||||
|
||||
/* build_new_dn:
|
||||
*
|
||||
* Used by ldbm/bdb2_back_modrdn to create the new dn of entries being
|
||||
* renamed.
|
||||
*
|
||||
* new_dn = parent (p_dn) + separator(s) + rdn (newrdn) + null.
|
||||
*/
|
||||
|
||||
void
|
||||
build_new_dn( char ** new_dn, char *e_dn, char * p_dn, char * newrdn )
|
||||
{
|
||||
|
||||
if ( p_dn == NULL ) {
|
||||
|
||||
*new_dn = ch_strdup( newrdn );
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
*new_dn = (char *) ch_malloc( strlen( p_dn ) + strlen( newrdn ) + 3 );
|
||||
|
||||
if ( dn_type( e_dn ) == DN_X500 ) {
|
||||
|
||||
strcpy( *new_dn, newrdn );
|
||||
strcat( *new_dn, "," );
|
||||
strcat( *new_dn, p_dn );
|
||||
|
||||
} else {
|
||||
|
||||
char *s;
|
||||
char sep[2];
|
||||
|
||||
strcpy( *new_dn, newrdn );
|
||||
s = strchr( newrdn, '\0' );
|
||||
s--;
|
||||
|
||||
if ( (*s != '.') && (*s != '@') ) {
|
||||
|
||||
if ( (s = strpbrk( e_dn, ".@" )) != NULL ) {
|
||||
|
||||
sep[0] = *s;
|
||||
sep[1] = '\0';
|
||||
strcat( *new_dn, sep );
|
||||
|
||||
}/* if ( (s = strpbrk( dn, ".@" )) != NULL ) */
|
||||
|
||||
}/* if ( *s != '.' && *s != '@' ) */
|
||||
|
||||
strcat( *new_dn, p_dn );
|
||||
|
||||
}/* if ( dn_type( e_dn ) == DN_X500 ) {}else */
|
||||
|
||||
}/* void build_new_dn() */
|
||||
|
@ -21,7 +21,6 @@
|
||||
#include "slap.h"
|
||||
|
||||
static void modlist_free(LDAPMod *mods);
|
||||
static void add_lastmods(Operation *op, LDAPMod **mods);
|
||||
|
||||
|
||||
void
|
||||
@ -154,10 +153,7 @@ do_modify(
|
||||
if ( be->be_update_ndn == NULL ||
|
||||
strcmp( be->be_update_ndn, op->o_ndn ) == 0 )
|
||||
{
|
||||
if ( (be->be_lastmod == ON || ( be->be_lastmod == UNDEFINED &&
|
||||
global_lastmod == ON ) ) && be->be_update_ndn == NULL ) {
|
||||
add_lastmods( op, &mods );
|
||||
}
|
||||
|
||||
if ( (*be->be_modify)( be, conn, op, ndn, mods ) == 0 ) {
|
||||
replog( be, LDAP_REQ_MODIFY, ndn, mods, 0 );
|
||||
}
|
||||
@ -191,76 +187,3 @@ modlist_free(
|
||||
free( mods );
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
add_lastmods( Operation *op, LDAPMod **mods )
|
||||
{
|
||||
char buf[22];
|
||||
struct berval bv;
|
||||
struct berval *bvals[2];
|
||||
LDAPMod **m;
|
||||
LDAPMod *tmp;
|
||||
struct tm *ltm;
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "add_lastmods\n", 0, 0, 0 );
|
||||
|
||||
bvals[0] = &bv;
|
||||
bvals[1] = NULL;
|
||||
|
||||
/* remove any attempts by the user to modify these attrs */
|
||||
for ( m = mods; *m != NULL; m = &(*m)->mod_next ) {
|
||||
if ( strcasecmp( (*m)->mod_type, "modifytimestamp" ) == 0 ||
|
||||
strcasecmp( (*m)->mod_type, "modifiersname" ) == 0 ||
|
||||
strcasecmp( (*m)->mod_type, "createtimestamp" ) == 0 ||
|
||||
strcasecmp( (*m)->mod_type, "creatorsname" ) == 0 ) {
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"add_lastmods: found lastmod attr: %s\n",
|
||||
(*m)->mod_type, 0, 0 );
|
||||
tmp = *m;
|
||||
*m = (*m)->mod_next;
|
||||
free( tmp->mod_type );
|
||||
if ( tmp->mod_bvalues != NULL ) {
|
||||
ber_bvecfree( tmp->mod_bvalues );
|
||||
}
|
||||
free( tmp );
|
||||
if (!*m)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( op->o_dn == NULL || op->o_dn[0] == '\0' ) {
|
||||
bv.bv_val = "NULLDN";
|
||||
bv.bv_len = strlen( bv.bv_val );
|
||||
} else {
|
||||
bv.bv_val = op->o_dn;
|
||||
bv.bv_len = strlen( bv.bv_val );
|
||||
}
|
||||
tmp = (LDAPMod *) ch_calloc( 1, sizeof(LDAPMod) );
|
||||
tmp->mod_type = ch_strdup( "modifiersname" );
|
||||
tmp->mod_op = LDAP_MOD_REPLACE;
|
||||
tmp->mod_bvalues = (struct berval **) ch_calloc( 1,
|
||||
2 * sizeof(struct berval *) );
|
||||
tmp->mod_bvalues[0] = ber_bvdup( &bv );
|
||||
tmp->mod_next = *mods;
|
||||
*mods = tmp;
|
||||
|
||||
ldap_pvt_thread_mutex_lock( ¤ttime_mutex );
|
||||
#ifndef LDAP_LOCALTIME
|
||||
ltm = gmtime( ¤ttime );
|
||||
strftime( buf, sizeof(buf), "%Y%m%d%H%M%SZ", ltm );
|
||||
#else
|
||||
ltm = localtime( ¤ttime );
|
||||
strftime( buf, sizeof(buf), "%y%m%d%H%M%SZ", ltm );
|
||||
#endif
|
||||
ldap_pvt_thread_mutex_unlock( ¤ttime_mutex );
|
||||
bv.bv_val = buf;
|
||||
bv.bv_len = strlen( bv.bv_val );
|
||||
tmp = (LDAPMod *) ch_calloc( 1, sizeof(LDAPMod) );
|
||||
tmp->mod_type = ch_strdup( "modifytimestamp" );
|
||||
tmp->mod_op = LDAP_MOD_REPLACE;
|
||||
tmp->mod_bvalues = (struct berval **) ch_calloc( 1, 2 * sizeof(struct berval *) );
|
||||
tmp->mod_bvalues[0] = ber_bvdup( &bv );
|
||||
tmp->mod_next = *mods;
|
||||
*mods = tmp;
|
||||
}
|
||||
|
@ -102,10 +102,14 @@ void connection_activity LDAP_P(( Connection *conn ));
|
||||
char * dn_normalize LDAP_P(( char *dn ));
|
||||
char * dn_normalize_case LDAP_P(( char *dn ));
|
||||
char * dn_parent LDAP_P(( Backend *be, char *dn ));
|
||||
char * dn_rdn LDAP_P(( Backend *be, char *dn ));
|
||||
int dn_issuffix LDAP_P(( char *dn, char *suffix ));
|
||||
int dn_type LDAP_P(( char *dn ));
|
||||
char * dn_upcase LDAP_P(( char *dn ));
|
||||
|
||||
char * rdn_attr_value LDAP_P(( char * rdn ));
|
||||
char * rdn_attr_type LDAP_P(( char * rdn ));
|
||||
void build_new_dn LDAP_P(( char ** new_dn, char *e_dn, char * p_dn,
|
||||
char * newrdn ));
|
||||
/*
|
||||
* entry.c
|
||||
*/
|
||||
|
@ -5,6 +5,7 @@ SLAPD=../servers/slapd/slapd
|
||||
SLURPD=../servers/slurpd/slurpd
|
||||
LDAPSEARCH=../clients/tools/ldapsearch
|
||||
LDAPMODIFY=../clients/tools/ldapmodify
|
||||
LDAPMODRDN=../clients/tools/ldapmodrdn
|
||||
LDAPADD=../clients/tools/ldapadd
|
||||
LVL=5
|
||||
PORT=9009
|
||||
@ -32,6 +33,7 @@ LDIFFLT=$DBDIR/ldif.flt
|
||||
MASTEROUT=$DBDIR/master.out
|
||||
SLAVEOUT=$DBDIR/slave.out
|
||||
TESTOUT=$DBDIR/ldapsearch.out
|
||||
TESTOUT_MODRDN=$DBDIR/ldapmodrdn.out
|
||||
SEARCHOUTMASTER=$DATADIR/search.out.master
|
||||
MODIFYOUTMASTER=$DATADIR/modify.out.master
|
||||
ADDDELOUTMASTER=$DATADIR/adddel.out.master
|
||||
|
@ -1,12 +1,99 @@
|
||||
#!/bin/sh
|
||||
#! /bin/sh
|
||||
|
||||
if [ $# -eq 0 ]; then
|
||||
if test $# -eq 0 ; then
|
||||
SRCDIR="."
|
||||
else
|
||||
SRCDIR=$1; shift
|
||||
fi
|
||||
if test $# -eq 1 ; then
|
||||
BACKEND=$1; shift
|
||||
fi
|
||||
|
||||
. $SRCDIR/scripts/defines.sh $SRCDIR
|
||||
echo "running defines.sh $SRCDIR $BACKEND"
|
||||
. $SRCDIR/scripts/defines.sh
|
||||
|
||||
echo "Cleaning up in $DBDIR..."
|
||||
|
||||
rm -f $DBDIR/[!C]*
|
||||
|
||||
echo "Running ldif2ldbm to build slapd database..."
|
||||
$LDIF2LDBM -f $CONF -i $LDIF -e ../servers/slapd/tools
|
||||
RC=$?
|
||||
if test $RC != 0 ; then
|
||||
echo "ldif2ldbm failed!"
|
||||
exit $RC
|
||||
fi
|
||||
|
||||
echo "Starting slapd on TCP/IP port $PORT..."
|
||||
$SLAPD -f $CONF -p $PORT -d $LVL $TIMING > $MASTERLOG 2>&1 &
|
||||
PID=$!
|
||||
echo "Testing slapd modrdn operations..."
|
||||
|
||||
# Make sure we can search the database
|
||||
for i in 0 1 2 3 4 5; do
|
||||
$LDAPSEARCH -L -S "" -b "$BASEDN" -h localhost -p $PORT \
|
||||
'cn=Manager' > /dev/null 2>&1
|
||||
RC=$?
|
||||
if test $RC = 1 ; then
|
||||
echo "Waiting 5 seconds for slapd to start..."
|
||||
sleep 5
|
||||
fi
|
||||
done
|
||||
|
||||
if test $RC != 0 ; then
|
||||
echo "ldapsearch failed!"
|
||||
kill -HUP $PID
|
||||
exit $RC
|
||||
fi
|
||||
|
||||
cat /dev/null > $TESTOUT_MODRDN
|
||||
|
||||
# -r used to do remove of old rdn
|
||||
|
||||
echo "Testing modrdn(deleteoldrdn=0)..."
|
||||
$LDAPMODRDN -v -D "$MANAGERDN" -h localhost -p $PORT -w $PASSWD > \
|
||||
/dev/null 2>&1 'cn=James A Jones 1, ou=Alumni Association, ou=People, o=University of Michigan, c=US' 'cn=James A Jones III'
|
||||
|
||||
RC=$?
|
||||
if test $RC != 0 ; then
|
||||
echo "ldapmodrdn failed!"
|
||||
kill -HUP $PID
|
||||
exit $RC
|
||||
fi
|
||||
|
||||
echo "Testing modrdn(deleteoldrdn=1)..."
|
||||
$LDAPMODRDN -v -D "$MANAGERDN" -r -h localhost -p $PORT -w $PASSWD > \
|
||||
/dev/null 2>&1 'cn=James A Jones 2, ou=Information Technology Division, ou=People, o=University of Michigan, c=US' 'cn=James A Jones II'
|
||||
|
||||
RC=$?
|
||||
if test $RC != 0 ; then
|
||||
echo "ldapmodrdn failed!"
|
||||
kill -HUP $PID
|
||||
exit $RC
|
||||
fi
|
||||
|
||||
echo "Using ldapsearch to retrieve all the entries..."
|
||||
$LDAPSEARCH -L -S "" -b "$BASEDN" -h localhost -p $PORT \
|
||||
'objectClass=*' | egrep -iv '^createtimestamp:|^modifytimestamp:' \
|
||||
> $SEARCHOUT 2>&1
|
||||
RC=$?
|
||||
kill -HUP $PID
|
||||
if test $RC != 0 ; then
|
||||
echo "ldapsearch failed!"
|
||||
exit $RC
|
||||
fi
|
||||
|
||||
echo "Comparing database to reference file"
|
||||
cmp $SEARCHOUT $MODRDNOUTMASTER
|
||||
if test $? != 0 ; then
|
||||
echo "comparison failed - modrdn operations did not complete correctly"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo ">>>>> Test succeeded"
|
||||
|
||||
|
||||
|
||||
# echo "modrdn test not yet written"
|
||||
|
||||
echo "modrdn test not yet written"
|
||||
exit 0
|
||||
|
Loading…
x
Reference in New Issue
Block a user