mirror of
https://git.openldap.org/openldap/openldap.git
synced 2024-12-21 03:10:25 +08:00
Modifications must be copied before calling slap_mods_check() because
the pretty function may replace values which are owned by the SLAPI plugin slapi_entry_dup() optimization - avoid string re-encoding Fix slapi_add_internal() logic errors (was this ever tested?) Don't attempt to free entries that have been cached; see new internal slapi_add_entry_internal_locked() API
This commit is contained in:
parent
aee837c999
commit
b299d7e067
@ -19,6 +19,12 @@
|
||||
*/
|
||||
|
||||
#include "portable.h"
|
||||
|
||||
#include <ac/string.h>
|
||||
#include <ac/stdarg.h>
|
||||
#include <ac/ctype.h>
|
||||
#include <ac/unistd.h>
|
||||
|
||||
#include <slap.h>
|
||||
#include <lber_pvt.h>
|
||||
#include <slapi.h>
|
||||
@ -32,8 +38,6 @@ static struct slap_listener slap_unknown_listener = {
|
||||
BER_BVC("UNKNOWN")
|
||||
};
|
||||
|
||||
int bvptr2obj( struct berval **bvptr, struct berval **bvobj );
|
||||
|
||||
static void
|
||||
internal_result_v3(
|
||||
Operation *op,
|
||||
@ -258,7 +262,7 @@ static void slapiConnectionDestroy( Connection **pConn )
|
||||
* the strings.
|
||||
*/
|
||||
static int
|
||||
values2obj(
|
||||
values2obj_copy(
|
||||
char **ppValue,
|
||||
BerVarray *bvobj )
|
||||
{
|
||||
@ -278,8 +282,11 @@ values2obj(
|
||||
return LDAP_NO_MEMORY;
|
||||
}
|
||||
for ( i = 0; ppValue[i] != NULL; i++ ) {
|
||||
tmpberval[i].bv_val = ppValue[i];
|
||||
tmpberval[i].bv_len = strlen( ppValue[i] );
|
||||
size_t len = strlen( ppValue[i] );
|
||||
|
||||
tmpberval[i].bv_val = slapi_ch_malloc( len + 1 );
|
||||
AC_MEMCPY( tmpberval[i].bv_val, ppValue[i], len + 1 );
|
||||
tmpberval[i].bv_len = len;
|
||||
}
|
||||
tmpberval[i].bv_val = NULL;
|
||||
tmpberval[i].bv_len = 0;
|
||||
@ -289,23 +296,41 @@ values2obj(
|
||||
return LDAP_SUCCESS;
|
||||
}
|
||||
|
||||
static void
|
||||
freeMods( Modifications *ml )
|
||||
static int
|
||||
bvptr2obj_copy(
|
||||
struct berval **bvptr,
|
||||
BerVarray *bvobj )
|
||||
{
|
||||
/*
|
||||
* Free a modification list whose values have been
|
||||
* set with bvptr2obj() or values2obj() (ie. they
|
||||
* do not own the pointer to the underlying values)
|
||||
*/
|
||||
Modifications *next;
|
||||
int rc = LDAP_SUCCESS;
|
||||
int i;
|
||||
BerVarray tmpberval;
|
||||
|
||||
for ( ; ml != NULL; ml = next ) {
|
||||
next = ml->sml_next;
|
||||
|
||||
if ( ml->sml_bvalues ) slapi_ch_free( (void **)&ml->sml_bvalues );
|
||||
if ( ml->sml_nvalues ) slapi_ch_free( (void **)&ml->sml_nvalues );
|
||||
slapi_ch_free( (void **)&ml );
|
||||
if ( bvptr == NULL || *bvptr == NULL ) {
|
||||
return LDAP_OTHER;
|
||||
}
|
||||
|
||||
for ( i = 0; bvptr != NULL && bvptr[i] != NULL; i++ ) {
|
||||
; /* EMPTY */
|
||||
}
|
||||
|
||||
tmpberval = (BerVarray)slapi_ch_malloc( (i + 1)*sizeof(struct berval));
|
||||
if ( tmpberval == NULL ) {
|
||||
return LDAP_NO_MEMORY;
|
||||
}
|
||||
|
||||
for ( i = 0; bvptr[i] != NULL; i++ ) {
|
||||
tmpberval[i].bv_val = slapi_ch_malloc( bvptr[i]->bv_len );
|
||||
tmpberval[i].bv_len = bvptr[i]->bv_len;
|
||||
AC_MEMCPY( tmpberval[i].bv_val, bvptr[i]->bv_val, bvptr[i]->bv_len );
|
||||
}
|
||||
tmpberval[i].bv_val = NULL;
|
||||
tmpberval[i].bv_len = 0;
|
||||
|
||||
if ( rc == LDAP_SUCCESS ) {
|
||||
*bvobj = tmpberval;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -338,7 +363,7 @@ LDAPModToEntry(
|
||||
|
||||
|
||||
op = (Operation *) slapi_ch_calloc(1, sizeof(Operation));
|
||||
if ( pEntry == NULL) {
|
||||
if ( op == NULL) {
|
||||
rc = LDAP_NO_MEMORY;
|
||||
goto cleanup;
|
||||
}
|
||||
@ -354,16 +379,24 @@ LDAPModToEntry(
|
||||
dn.bv_len = strlen(ldn);
|
||||
|
||||
rc = dnPrettyNormal( NULL, &dn, &pEntry->e_name, &pEntry->e_nname, NULL );
|
||||
if ( rc != LDAP_SUCCESS )
|
||||
if ( rc != LDAP_SUCCESS ) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if ( rc == LDAP_SUCCESS ) {
|
||||
for ( i = 0, pMod = mods[0]; rc == LDAP_SUCCESS && pMod != NULL; pMod = mods[++i]) {
|
||||
Modifications *mod;
|
||||
|
||||
if ( (pMod->mod_op & LDAP_MOD_BVALUES) != 0 ) {
|
||||
/* attr values are in berval format */
|
||||
/* convert an array of pointers to bervals to an array of bervals */
|
||||
rc = bvptr2obj(pMod->mod_bvalues, &bv);
|
||||
/*
|
||||
* Convert an array of pointers to bervals to
|
||||
* an array of bervals. Note that we need to copy the
|
||||
* values too, as the slap_mods_check() will free the
|
||||
* original values after prettying; the modifications
|
||||
* being passed in may not have been allocated on the
|
||||
* heap.
|
||||
*/
|
||||
rc = bvptr2obj_copy( pMod->mod_bvalues, &bv );
|
||||
if ( rc != LDAP_SUCCESS ) goto cleanup;
|
||||
tmp.sml_type.bv_val = pMod->mod_type;
|
||||
tmp.sml_type.bv_len = strlen( pMod->mod_type );
|
||||
@ -388,7 +421,7 @@ LDAPModToEntry(
|
||||
if ( pMod->mod_values == NULL ) {
|
||||
rc = LDAP_OTHER;
|
||||
} else {
|
||||
rc = values2obj( pMod->mod_values, &bv );
|
||||
rc = values2obj_copy( pMod->mod_values, &bv );
|
||||
if ( rc != LDAP_SUCCESS ) goto cleanup;
|
||||
tmp.sml_type.bv_val = pMod->mod_type;
|
||||
tmp.sml_type.bv_len = strlen( pMod->mod_type );
|
||||
@ -436,10 +469,6 @@ LDAPModToEntry(
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* FIXME: slap_mods2entry is declared static
|
||||
* in servers/slapd/add.c
|
||||
*/
|
||||
rc = slap_mods2entry( modlist, &pEntry, repl_user,
|
||||
0, &text, textbuf, textlen );
|
||||
if (rc != LDAP_SUCCESS) {
|
||||
@ -458,7 +487,7 @@ cleanup:
|
||||
if ( op )
|
||||
slapi_ch_free( (void **)&op );
|
||||
if ( modlist != NULL )
|
||||
freeMods( modlist );
|
||||
slap_mods_free( modlist );
|
||||
if ( rc != LDAP_SUCCESS ) {
|
||||
if ( pEntry != NULL ) {
|
||||
slapi_entry_free( pEntry );
|
||||
@ -567,13 +596,13 @@ cleanup:
|
||||
#endif /* LDAP_SLAPI */
|
||||
}
|
||||
|
||||
Slapi_PBlock *
|
||||
slapi_add_entry_internal(
|
||||
Slapi_Entry *e,
|
||||
#ifdef LDAP_SLAPI
|
||||
static Slapi_PBlock *
|
||||
slapi_add_entry_internal_locked(
|
||||
Slapi_Entry **e,
|
||||
LDAPControl **controls,
|
||||
int log_changes )
|
||||
{
|
||||
#ifdef LDAP_SLAPI
|
||||
Connection *pConn = NULL;
|
||||
Operation *op = NULL;
|
||||
Slapi_PBlock *pPB = NULL, *pSavePB = NULL;
|
||||
@ -582,7 +611,7 @@ slapi_add_entry_internal(
|
||||
int isCritical;
|
||||
SlapReply rs = { REP_RESULT };
|
||||
|
||||
if ( e == NULL ) {
|
||||
if ( *e == NULL ) {
|
||||
rs.sr_err = LDAP_PARAM_ERROR;
|
||||
goto cleanup;
|
||||
}
|
||||
@ -602,7 +631,7 @@ slapi_add_entry_internal(
|
||||
pPB = (Slapi_PBlock *)op->o_pb;
|
||||
op->o_ctrls = controls;
|
||||
|
||||
op->o_bd = select_backend( &e->e_nname, manageDsaIt, 0 );
|
||||
op->o_bd = select_backend( &((*e)->e_nname), manageDsaIt, 0 );
|
||||
if ( op->o_bd == NULL ) {
|
||||
rs.sr_err = LDAP_PARTIAL_RESULTS;
|
||||
goto cleanup;
|
||||
@ -610,7 +639,7 @@ slapi_add_entry_internal(
|
||||
|
||||
op->o_dn = pConn->c_dn = op->o_bd->be_rootdn;
|
||||
op->o_ndn = pConn->c_ndn = op->o_bd->be_rootndn;
|
||||
op->oq_add.rs_e = e;
|
||||
op->oq_add.rs_e = *e;
|
||||
|
||||
if ( op->o_bd->be_add ) {
|
||||
int repl_user = be_isupdate( op->o_bd, &op->o_ndn );
|
||||
@ -619,6 +648,8 @@ slapi_add_entry_internal(
|
||||
if ( log_changes ) {
|
||||
replog( op );
|
||||
}
|
||||
be_entry_release_w( op, *e );
|
||||
*e = NULL;
|
||||
}
|
||||
} else {
|
||||
rs.sr_err = LDAP_REFERRAL;
|
||||
@ -640,12 +671,34 @@ cleanup:
|
||||
slapiConnectionDestroy( &pConn );
|
||||
|
||||
return( pSavePB );
|
||||
}
|
||||
#endif /* LDAP_SLAPI */
|
||||
|
||||
Slapi_PBlock *
|
||||
slapi_add_entry_internal(
|
||||
Slapi_Entry *e,
|
||||
LDAPControl **controls,
|
||||
int log_changes )
|
||||
{
|
||||
#ifdef LDAP_SLAPI
|
||||
Slapi_PBlock *pb;
|
||||
Slapi_Entry *entry;
|
||||
|
||||
/*
|
||||
* We make a copy to avoid an entry that may be freed later
|
||||
* by the caller being placed in the cache.
|
||||
*/
|
||||
entry = slapi_entry_dup( e );
|
||||
pb = slapi_add_entry_internal_locked( &entry, controls, log_changes );
|
||||
if ( entry != NULL ) {
|
||||
slapi_entry_free( entry );
|
||||
}
|
||||
return pb;
|
||||
#else
|
||||
return NULL;
|
||||
#endif /* LDAP_SLAPI */
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
Slapi_PBlock *
|
||||
slapi_add_internal(
|
||||
char *dn,
|
||||
@ -673,7 +726,8 @@ slapi_add_internal(
|
||||
}
|
||||
|
||||
if ( rc == LDAP_SUCCESS ) {
|
||||
if((pEntry = LDAPModToEntry( dn, mods )) == NULL) {
|
||||
pEntry = LDAPModToEntry( dn, mods );
|
||||
if ( pEntry == NULL ) {
|
||||
rc = LDAP_OTHER;
|
||||
}
|
||||
}
|
||||
@ -682,10 +736,10 @@ slapi_add_internal(
|
||||
pb = slapi_pblock_new();
|
||||
slapi_pblock_set( pb, SLAPI_PLUGIN_INTOP_RESULT, (void *)rc );
|
||||
} else {
|
||||
pb = slapi_add_entry_internal( pEntry, controls, log_changes );
|
||||
pb = slapi_add_entry_internal_locked( &pEntry, controls, log_changes );
|
||||
}
|
||||
|
||||
if ( pEntry ) {
|
||||
if ( pEntry != NULL ) {
|
||||
slapi_entry_free(pEntry);
|
||||
}
|
||||
|
||||
@ -909,7 +963,7 @@ slapi_modify_internal(
|
||||
* convert an array of pointers to bervals
|
||||
* to an array of bervals
|
||||
*/
|
||||
rs.sr_err = bvptr2obj( pMod->mod_bvalues, &bv );
|
||||
rs.sr_err = bvptr2obj_copy( pMod->mod_bvalues, &bv );
|
||||
if ( rs.sr_err != LDAP_SUCCESS )
|
||||
goto cleanup;
|
||||
tmp.sml_type.bv_val = pMod->mod_type;
|
||||
@ -926,7 +980,7 @@ slapi_modify_internal(
|
||||
mod->sml_bvalues = tmp.sml_bvalues;
|
||||
mod->sml_nvalues = tmp.sml_nvalues;
|
||||
} else {
|
||||
rs.sr_err = values2obj( pMod->mod_values, &bv );
|
||||
rs.sr_err = values2obj_copy( pMod->mod_values, &bv );
|
||||
if ( rs.sr_err != LDAP_SUCCESS )
|
||||
goto cleanup;
|
||||
tmp.sml_type.bv_val = pMod->mod_type;
|
||||
@ -1017,7 +1071,7 @@ cleanup:
|
||||
slapi_ch_free( (void **)&dn.bv_val );
|
||||
|
||||
if ( modlist != NULL )
|
||||
freeMods( modlist );
|
||||
slap_mods_free( modlist );
|
||||
|
||||
if ( pConn != NULL ) {
|
||||
pSavePB = pPB;
|
||||
|
@ -170,26 +170,17 @@ Slapi_Entry *
|
||||
slapi_entry_dup( Slapi_Entry *e )
|
||||
{
|
||||
#ifdef LDAP_SLAPI
|
||||
char *tmp = NULL;
|
||||
Slapi_Entry *tmpEnt;
|
||||
int len = 0;
|
||||
Slapi_Entry *ret;
|
||||
|
||||
tmp = slapi_entry2str( e, &len );
|
||||
if ( tmp == NULL ) {
|
||||
return (Slapi_Entry *)NULL;
|
||||
}
|
||||
ret = (Slapi_Entry *)slapi_ch_calloc( 1, sizeof(*ret) );
|
||||
|
||||
tmpEnt = (Slapi_Entry *)str2entry( tmp );
|
||||
if ( tmpEnt == NULL ) {
|
||||
slapi_ch_free( (void **)&tmp );
|
||||
return (Slapi_Entry *)NULL;
|
||||
}
|
||||
|
||||
if (tmp != NULL) {
|
||||
slapi_ch_free( (void **)&tmp );
|
||||
}
|
||||
|
||||
return tmpEnt;
|
||||
ret->e_id = e->e_id;
|
||||
ber_dupbv( &ret->e_name, &e->e_name );
|
||||
ber_dupbv( &ret->e_nname, &e->e_nname );
|
||||
ret->e_attrs = attrs_dup( e->e_attrs );
|
||||
ret->e_ocflags = e->e_ocflags;
|
||||
ber_dupbv( &ret->e_bv, &e->e_bv );
|
||||
ret->e_private = NULL;
|
||||
#else /* LDAP_SLAPI */
|
||||
return NULL;
|
||||
#endif /* LDAP_SLAPI */
|
||||
|
Loading…
Reference in New Issue
Block a user