openldap/servers/slapd/slapi/slapi_ops.c.all
2003-01-03 20:20:47 +00:00

1304 lines
34 KiB
Plaintext

/*
* Copyright 1998-2003 The OpenLDAP Foundation, All Rights Reserved.
* COPYING RESTRICTIONS APPLY, see COPYRIGHT file
*/
/*
* (C) Copyright IBM Corp. 1997,2002
* Redistribution and use in source and binary forms are permitted
* provided that this notice is preserved and that due credit is
* given to IBM Corporation. This software is provided ``as is''
* without express or implied warranty.
*/
#include "portable.h"
#include "slapi_common.h"
#include <slap.h>
#include <slapi.h>
#include <lber.h>
#include "../../../libraries/liblber/lber-int.h"
int
bvptr2obj( struct berval **bvptr,
struct berval **bvobj);
Slapi_PBlock *
slapi_simple_bind_internal( char *dn,
struct berval *cred,
int method,
int version);
Connection *
fakeConnection( char *DN,
int OpType)
{
Connection *pConn, *c;
if((pConn = (Connection *) slapi_ch_calloc(sizeof(Connection))) == NULL)
return (Connection *)NULL;
LDAP_STAILQ_INIT(&c->c_pending_ops);
LDAP_STAILQ_INIT(&c->c_ops);
if((pConn->c_pending_ops.stqh_first=(Operation *) slapi_ch_calloc(sizeof(Operation))) == NULL) {
slapi_ch_free( pConn );
return (Connection *)NULL;
}
if((pConn->c_pending_ops.stqh_first->o_pb=(Slapi_PBlock *) slapi_pblock_new()) == NULL) {
slapi_ch_free( pConn->c_pending_ops.stqh_first );
slapi_ch_free( pConn );
return (Connection *)NULL;
}
c = pConn;
c->c_ops->o_opid = 0;
c->c_ops->o_msgid = 0;
c->c_ops->o_next = NULL;
c->c_ops->o_tag = OpType;
i->c_ops->o_abandon = 0;
c->c_authmech.bv_val = NULL;
c->c_authmech.bv_len = 0;
c->c_dn.bv_val = NULL;
c->c_dn.bv_len = 0;
c->c_ndn.bv_val = NULL;
c->c_ndn.bv_len = 0;
c->c_cdn.bv_val = NULL;
c->c_cdn.bv_len = 0;
c->c_groups = NULL;
c->c_listener_url.bv_val = NULL;
c->c_listener_url.bv_len = 0;
c->c_peer_domain.bv_val = NULL;
c->c_peer_domain.bv_len = 0;
c->c_peer_name.bv_val = NULL;
c->c_peer_name.bv_len = 0;
c->c_sock_name.bv_val = NULL;
c->c_sock_name.bv_len = 0;
c->c_sasl_bind_mech.bv_val = NULL;
c->c_sasl_bind_mech.bv_len = 0;
c->c_sasl_context = NULL;
c->c_sasl_extra = NULL;
c->c_sb = ber_sockbuf_alloc( );
c->c_currentber = NULL;
c->c_struct_state = SLAP_C_UNUSED;
c->c_n_get = 0;
c->c_n_read = 0;
c->c_n_write = 0;
c->c_protocol = LDAP_VERSION3;
time(&pConn->c_pending_ops.stqh_first->o_time);
pConn->c_send_ldap_result_v3 = (SEND_LDAP_RESULT_V3) internal_result_v3;
pConn->c_send_search_entry = (SEND_SEARCH_ENTRY) internal_search_entry;
pConn->c_send_ldap_search_result = (SEND_LDAP_SEARCH_RESULT) internal_search_result;
pConn->c_send_ldap_result_ext = (SEND_LDAP_RESULT_EXT) internal_result_ext;
pConn->c_send_ldap_search_reference = (SEND_SEARCH_REFERENCE) internal_search_reference;
return pConn;
}
/* Function : slapi_delete_internal
*
* Description : Plugin functions call this routine to delete an entry
* in the backend directly
* Return values : LDAP_SUCCESS
* LDAP_OPERAITONS_ERROR
* LDAP_NO_MEMORY
* LDAP_OTHER
* LDAP_UNWILLING_TO_PERFORM
*/
Slapi_PBlock *
slapi_delete_internal( char *ldn,
LDAPControl **controls,
int log_change)
{
int rc=LDAP_SUCCESS;
Backend *be;
Slapi_PBlock *pPB=NULL;
Slapi_PBlock *pSavePB=NULL;
Connection *pConn=NULL;
Operation *op;
int manageDsaIt = 0;
int isCritical;
struct berval dn = { 0, NULL };
struct berval pdn = { 0, NULL };
struct berval ndn = { 0, NULL };
if ( ldn == NULL ) {
rc = LDAP_OPERATIONS_ERROR;
}
if ( rc == LDAP_SUCCESS ) {
pConn = fakeConnection( NULL, LDAP_REQ_DELETE );
}
if ( pConn == NULL ) {
rc = LDAP_NO_MEMORY;
} else {
pPB = (Slapi_PBlock *)pConn->c_pending_ops.stqh_first->o_pb;
op = (Operation *)pConn->c_pending_ops.stqh_first;
op->o_ctrls = controls;
op->o_ndn.bv_val = slapi_strdup(be->be_update_ndn.bv_val);
op->o_ndn.bv_len = be->be_update_ndn.bv_len;
pConn->c_dn.bv_val = slapi_strdup(be->be_update_ndn.bv_val);
pConn->c_dn.bv_len = be->be_update_ndn.bv_len;
}
if ( rc == LDAP_SUCCESS ) {
dn.bv_val = slapi_strdup(ldn);
dn.bv_len = slapi_strlen(ldn);
rc = dnPrettyNormal( NULL, &dn, &pdn, &ndn );
if( rc != LDAP_SUCCESS ) {
#ifdef NEW_LOGGING
LDAP_LOG(( "operation", LDAP_LEVEL_INFO,
"do_delete: conn %d invalid dn (%s)\n",
conn->c_connid, dn.bv_val ));
#else
Debug( LDAP_DEBUG_ANY,
"do_delete: invalid dn (%s)\n", dn.bv_val, 0, 0 );
#endif
}
}
if( ndn.bv_len == 0 ) {
#ifdef NEW_LOGGING
LDAP_LOG(( "operation", LDAP_LEVEL_INFO, "do_delete: conn %d: "
"Attempt to delete root DSE.\n", conn->c_connid ));
#else
Debug( LDAP_DEBUG_ANY, "Attempt to delete root DSE.\n", 0, 0, 0 );
#endif
rc = LDAP_UNWILLING_TO_PERFORM;
#ifdef SLAPD_SCHEMA_DN
} else if ( strcasecmp( ndn.bv_val, SLAPD_SCHEMA_DN ) == 0 ) {
#ifdef NEW_LOGGING
LDAP_LOG(( "operation", LDAP_LEVEL_INFO, "do_delete: conn %d: "
"Attempt to delete subschema subentry.\n", conn->c_connid ));
#else
Debug( LDAP_DEBUG_ANY, "Attempt to delete subschema subentry.\n", 0, 0, 0 );
#endif
rc = LDAP_UNWILLING_TO_PERFORM;
#endif
}
if ( rc = slapi_control_present( controls, LDAP_MANAGEDSAIT_OID, NULL, &isCritical)){
manageDsaIt = 1; /* turn off referral */
}
if ( rc == LDAP_SUCCESS ) {
be = select_backend(&bv, manageDsaIt, 0);
if ( be == NULL ) rc = LDAP_PARTIAL_RESULTS;
}
if ( rc == LDAP_SUCCESS ) {
rc = backend_check_restrictions( be, conn, op, NULL, &text ) ;
}
if ( rc == LDAP_SUCCESS ) {
rc = backend_check_referrals( be, conn, op, &pdn, &ndn );
}
suffix_alias( be, &ndn );
if ( be->be_delete ) {
/* do the update here */
int repl_user = be_isupdate( be, &op->o_ndn );
#ifndef SLAPD_MULTIMASTER
if ( !be->be_update_ndn.bv_len || repl_user )
#endif
{
if ( (*be->be_delete)( be, conn, op, &pdn, &ndn ) == 0 ) {
#ifdef SLAPD_MULTIMASTER
if ( !be->be_update_ndn.bv_len || !repl_user )
#endif
{
if (log_change) replog( be, op, &pdn, &ndn, NULL );
}
}
#ifndef SLAPD_MULTIMASTER
} else {
rc = LDAP_REFERRAL;
#endif
}
} else {
rc = LDAP_UNWILLING_TO_PERFORM;
}
if ( pPB != NULL ) {
slapi_pblock_set( pPB, SLAPI_PLUGIN_INTOP_RESULT, (void *)rc );
}
if ( pConn != NULL ) {
if ( pConn->c_dn.bv_val )
slapi_ch_free( pConn->c_dn.bv_val );
if ( pConn->c_pending_ops.stqh_first->o_dn.bv_val )
slapi_ch_free( pConn->c_pending_ops.stqh_first->o_dn.bv_val );
if ( pConn->c_pending_ops.stqh_first )
slapi_ch_free( pConn->c_pending_ops.stqh_first );
if (dn.bv_val)
slapi_ch_free(dn.bv_val);
if (pdn.bv_val)
slapi_ch_free(pdn.bv_val);
if (ndn.bv_val)
slapi_ch_free(ndn_bv.val);
pSavePB = pPB;
free( pConn );
}
return( pSavePB );
}
/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/
int
internal_result_v3( Connection *conn,
Operation *op,
int err,
char *matched,
char *text,
char **referrals)
{
return LDAP_SUCCESS;
}
int
internal_result_ext( Connection *conn,
Operation *op,
int errnum,
char *respname,
struct berval *response )
{
return LDAP_SUCCESS;
}
int
internal_search_reference( Connection *conn,
Operation *op,
char **ref)
{
return LDAP_SUCCESS;
}
int
internal_search_result( Connection *conn,
Operation *op,
int err,
char *matched,
char *text,
int nentries)
{
slapi_pblock_set((Slapi_PBlock *)op->o_pb,SLAPI_NENTRIES,(void *)nentries);
return LDAP_SUCCESS;
}
int
internal_search_entry( Backend *be,
Connection *conn,
Operation *op,
Entry *e,
char **attrs,
int attrsonly,
char **denied_attrs)
{
char *ent2str = NULL;
int nentries = 0, len = 0, i = 0;
Slapi_Entry **head = NULL, **tp;
if((ent2str=slapi_entry2str(e,&len)) == NULL) {
return SLAPD_NO_MEMORY;
}
slapi_pblock_get((Slapi_PBlock *)op->o_pb, SLAPI_NENTRIES, &nentries);
slapi_pblock_get((Slapi_PBlock *)op->o_pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &head);
i=nentries + 1;
if(nentries == 0 ) {
if((tp=(Slapi_Entry **)slapi_ch_malloc(2 * sizeof(Slapi_Entry *))) == NULL) {
return SLAPD_NO_MEMORY;
}
if((tp[0]=(Slapi_Entry *)str2entry(ent2str)) == NULL) {
return SLAPD_NO_MEMORY;
}
} else {
if((tp=(Slapi_Entry **)slapi_ch_realloc((char *)head,
(sizeof(Slapi_Entry *) * (i+1)))) == NULL) {
return SLAPD_NO_MEMORY;
}
if((tp[i-1]=(Slapi_Entry *)str2entry(ent2str)) == NULL) {
return SLAPD_NO_MEMORY;
}
}
tp[i] = NULL;
slapi_pblock_set((Slapi_PBlock *)op->o_pb,SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES,(void *)tp);
slapi_pblock_set((Slapi_PBlock *)op->o_pb,SLAPI_NENTRIES,(void *)i);
slapi_ch_free(ent2str);
return LDAP_SUCCESS;
}
/*
* Function : freeModList
* Free a list of LDAPMod structures which has the bvalue defined.
*/
static void
freeModList( LDAPMod *pMod )
{
LDAPMod *pNextMod;
while ( pMod != NULL ) {
pNextMod = pMod->mod_next;
free( pMod->mod_type );
ber_bvecfree( pMod->mod_bvalues );
free( pMod );
pMod = pNextMod;
}
}
/*
* Function : duplicateBVMod
* Duplicate a LDAPMod structure in which the bervals are defined.
* return code : LDAP_SUCEESS,
* LDAP_OTHER,
* LDAP_NO_MEMORY
*/
int
duplicateBVMod( LDAPMod *pMod,
LDAPMod **ppNewMod )
{
int rc = LDAP_SUCCESS;
int i;
struct berval **ppNewBV;
struct berval *pNewBV;
if ( pMod == NULL ) {
rc = LDAP_OTHER;
} else {
*ppNewMod = (LDAPMod *)slapi_ch_malloc(sizeof(LDAPMod));
if ( *ppNewMod == NULL ) {
rc = LDAP_NO_MEMORY;
} else {
memset( (*ppNewMod),'\0',sizeof(LDAPMod) );
(*ppNewMod)->mod_op = pMod->mod_op;
(*ppNewMod)->mod_type = slapi_ch_strdup( pMod->mod_type);
if ( (*ppNewMod)->mod_type == NULL) {
rc = LDAP_NO_MEMORY;
} else {
if ( pMod->mod_bvalues == NULL ) {
(*ppNewMod)->mod_values = NULL;
} else {
for ( i=0; pMod->mod_bvalues[i] != NULL; i++ ) {
;
}
ppNewBV = (struct berval **)slapi_ch_malloc( (i+1)*sizeof(struct berval *));
if ( ppNewBV == NULL ) {
rc = LDAP_NO_MEMORY;
} else {
for ( i=0; pMod->mod_bvalues[i] != NULL &&
rc == LDAP_SUCCESS; i++ ) {
pNewBV = (struct berval *)slapi_ch_malloc(sizeof(struct berval));
if ( pNewBV == NULL ) {
rc = LDAP_NO_MEMORY;
} else {
pNewBV->bv_val = slapi_ch_malloc(pMod->mod_bvalues[i]->bv_len+1);
if ( pNewBV->bv_val == NULL ) {
rc = LDAP_NO_MEMORY;
} else {
memset(pNewBV->bv_val,'\0',pMod->mod_bvalues[i]->bv_len+1);
pNewBV->bv_len = pMod->mod_bvalues[i]->bv_len;
memcpy(pNewBV->bv_val,pMod->mod_bvalues[i]->bv_val,pNewBV->bv_len);
ppNewBV[i] = pNewBV;
}
}
} /* for each bvalue */
if ( rc == LDAP_SUCCESS ) {
ppNewBV[i] = NULL;
(*ppNewMod)->mod_bvalues = ppNewBV;
}
}
}
}
}
}
return( rc );
}
/*
* Function : ValuestoBValues
* Convert an array of char ptrs to an array of berval ptrs.
* return value : LDAP_SUCCESS
* LDAP_NO_MEMORY
* LDAP_OTHER
*/
static int
ValuesToBValues( char **ppValue,
struct berval ***pppBV )
{
int rc = LDAP_SUCCESS;
int i;
struct berval *pTmpBV;
struct berval **ppNewBV;
/* count the number of char ptrs. */
for ( i=0; ppValue != NULL && ppValue[i] != NULL; i++ ) {
; /* NULL */
}
if ( i == 0 ) {
rc = LDAP_OTHER;
} else {
*pppBV = ppNewBV = (struct berval **)slapi_ch_malloc( (i+1)*(sizeof(struct berval *)) );
if ( *pppBV == NULL ) {
rc = LDAP_NO_MEMORY;
} else {
while ( ppValue != NULL && *ppValue != NULL && rc == LDAP_SUCCESS ) {
pTmpBV = (struct berval *)slapi_ch_malloc(sizeof(struct berval));
if ( pTmpBV == NULL) {
rc = LDAP_NO_MEMORY;
} else {
pTmpBV->bv_val = slapi_ch_strdup(*ppValue);
if ( pTmpBV->bv_val == NULL ) {
rc = LDAP_NO_MEMORY;
} else {
pTmpBV->bv_len = strlen(*ppValue);
*ppNewBV = pTmpBV;
ppNewBV++;
}
ppValue++;
}
}
/* null terminate the array of berval ptrs */
*ppNewBV = NULL;
}
}
return( rc );
}
/*
* Function : LDAPModToEntry
* convert a dn plus an array of LDAPMod struct ptrs to an entry structure
* with a link list of the correspondent attributes.
* Return value : LDAP_SUCCESS
* LDAP_NO_MEMORY
* LDAP_OTHER
*/
Entry *
LDAPModToEntry( char *ldn,
LDAPMod **mods )
{
int rc=LDAP_SUCCESS;
LDAPMod *pMod;
Entry *pEntry=NULL;
int i,j;
struct berval **ppSaveBV;
struct berval **ppBV;
struct berval *pTmpBV;
char **ppValue;
AttributeDescription *ad;
struct berval *bv;
const char *text;
Modifications *modlist = NULL;
Modifications **modtail = &modlist;
Modifications tmp;
struct berval dn = { 0, NULL };
dn.ber_val = slapi_ch_strdup(ldn);
dn.ber_len = slapi_ch_strlen(ldn);
pEntry = (Entry *) ch_calloc( 1, sizeof(Entry) );
if ( pEntry == NULL) {
rc = LDAP_NO_MEMORY;
} else {
rc = dnPrettyNormal( NULL, &dn, &e->e_name, &e->e_nname );
if( rc != LDAP_SUCCESS ) {
#ifdef NEW_LOGGING
LDAP_LOG(( "operation", LDAP_LEVEL_ERR,
"LDAPModToEntry: invalid dn (%s)\n", dn.bv_val ));
#else
Debug( LDAP_DEBUG_ANY, "LDAPModToEntry: invalid dn (%s)\n", dn.bv_val, 0, 0 );
#endif
rc = LDAP_INVALID_DN_SYNTAX;
}
}
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);
if (rc != LDAP_SUCCESS) break;
tmp.sml_type = pMod->mod_type;
tmp.sml_bvalues = bv;
mod = (Modifications *) ch_malloc( sizeof(Modifications) );
mod->sml_op = LDAP_MOD_ADD;
mod->sml_next = NULL;
mod->sml_desc = NULL;
mod->sml_type = tmp.sml_type;
mod->sml_bvalues = tmp.sml_bvalues;
*modtail = mod;
modtail = &mod->sml_next;
} else {
/* attr values are in string format, need to be converted */
/* to an array of bervals */
if ( pMod->mod_values == NULL ) {
rc = LDAP_OTHER;
} else {
rc = ValuesToBValues( pMod->mod_values, &ppBV );
if (rc != LDAP_SUCCESS) break;
rc = bvptr2obj(ppBV, &bv);
if (rc != LDAP_SUCCESS) break;
tmp.sml_type = pMod->mod_type;
tmp.sml_bvalues = bv;
mod = (Modifications *) ch_malloc( sizeof(Modifications) );
mod->sml_op = LDAP_MOD_ADD;
mod->sml_next = NULL;
mod->sml_desc = NULL;
mod->sml_type = tmp.sml_type;
mod->sml_bvalues = tmp.sml_bvalues;
*modtail = mod;
modtail = &mod->sml_next;
if ( ppBV != NULL ) {
ber_bvecfree( ppBV );
}
}
}
} /* for each LDAPMod */
}
if( e->e_nname.bv_len == 0 )
rc = LDAP_ALREADY_EXISTS;
/* check if ManageDsaIt control is set */
if ( rc = slapi_control_present( controls, LDAP_MANAGEDSAIT_OID, NULL, &isCritical)){
manageDsaIt = 1; /* turn off referral */
}
if ( rc == LDAP_SUCCESS ) {
be = select_backend(&bv, manageDsaIt, 0);
if ( be == NULL ) rc = LDAP_PARTIAL_RESULTS;
}
if ( rc == LDAP_SUCCESS ) {
rc = backend_check_restrictions( be, conn, op, NULL, &text ) ;
}
if ( rc == LDAP_SUCCESS ) {
rc = backend_check_referrals( be, conn, op, &pdn, &ndn );
}
if ( rc != LDAP_SUCCESS ) {
if ( pEntry != NULL ) {
slapi_entry_free( pEntry );
}
pEntry = NULL;
}
return( pEntry );
}
/*xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/
Slapi_PBlock *
slapi_add_entry_internal( Slapi_Entry *e,
LDAPControl **controls,
int log_changes)
{
int rc=LDAP_SUCCESS, i;
Backend *be;
Connection *pConn=NULL;
Operation *op;
Slapi_PBlock *pPB=NULL, *pSavePB=NULL;
char *pDn=NULL;
int manageDsaIt = 0; /* referral is on */
int isCritical;
struct berval bv;
/* check if ManageDsaIt control is set */
if (slapi_control_present( controls, LDAP_CONTROL_MANAGEDSAIT, NULL, &isCritical)) {
manageDsaIt = 1; /* turn off referral */
}
pConn = fakeConnection(NULL, LDAP_REQ_ADD);
if ( pConn == NULL ) {
rc = LDAP_NO_MEMORY;
} else {
pPB = (Slapi_PBlock *)pConn->c_pending_ops.stqh_first->o_pb;
if (e == NULL) {
rc = LDAP_OPERATIONS_ERROR;
} else {
if ( rc == LDAP_SUCCESS ) {
be = select_backend(&e->e_nname, manageDsaIt, 0);
if ( be == NULL ) {
rc = LDAP_PARTIAL_RESULTS;
} else if ( be->be_add == NULL) {
rc = LDAP_UNWILLING_TO_PERFORM;
} else {
op = (Operation *)pConn->c_pending_ops.stqh_first;
op->o_ctrls = controls;
rc = (*be->be_add)( be, pConn, op, e );
if (rc == LDAP_SUCCESS)
Debug (LDAP_DEBUG_TRACE, " backend routine successful \n", 0, 0, 0);
else
Debug (LDAP_DEBUG_TRACE, " backend routine NOT successful \n", 0, 0, 0);
}
}
}
}
if ( pPB != NULL )
slapi_pblock_set( pPB, SLAPI_PLUGIN_INTOP_RESULT, (void *)rc );
if ( pDn != NULL )
slapi_ch_free( pDn );
if (bv.bv_val != NULL)
slapi_ch_free(bv.bv_val);
if ( pConn != NULL ) {
if ( pConn->c_dn.bv_val )
slapi_ch_free( pConn->c_dn.bv_val );
if ( pConn->c_pending_ops.stqh_first->o_dn.bv_val )
slapi_ch_free( pConn->c_pending_ops.stqh_first->o_dn.bv_val );
if ( pConn->c_pending_ops.stqh_first )
slapi_ch_free( pConn->c_pending_ops.stqh_first);
if (pConn->c_original_dn)
slapi_ch_free(pConn->c_original_dn);
pSavePB = pPB;
free( pConn );
}
return( pSavePB );
}
Slapi_PBlock *
slapi_add_internal( char *dn,
LDAPMod **mods,
LDAPControl **controls,
int log_changes )
{
LDAPMod *pMod=NULL;
Slapi_PBlock *pb=NULL;
Entry *pEntry=NULL;
int i, rc=LDAP_SUCCESS;
if(mods == NULL || *mods == NULL || dn == NULL || *dn == NULL)
rc = LDAP_OPERATIONS_ERROR ;
if (rc == LDAP_SUCCESS) {
for (i=0, pMod=mods[0]; pMod != NULL; pMod=mods[++i] ) {
if ((pMod->mod_op & ~LDAP_MOD_BVALUES) != LDAP_MOD_ADD) {
rc = LDAP_OTHER;
break;
}
}
}
if ( rc == LDAP_SUCCESS ) {
if((pEntry = LDAPModToEntry( dn, mods )) == NULL) {
rc = LDAP_OTHER;
}
}
if(rc != LDAP_SUCCESS) {
pb = slapi_pblock_new();
slapi_pblock_set(pb, SLAPI_PLUGIN_INTOP_RESULT, (void *)rc );
} else {
pb = slapi_add_entry_internal(pEntry, controls, log_changes);
}
if(pEntry)
slapi_entry_free(pEntry);
return(pb);
}
/*dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd*/
/* Function : slapi_modify_internal
*
* Description : Plugin functions call this routine to modify an entry in the backend directly
* Return values : LDAP_SUCCESS
* LDAP_OPERAITONS_ERROR
* LDAP_NO_MEMORY
* LDAP_OTHER
* LDAP_UNWILLING_TO_PERFORM
*/
Slapi_PBlock *
slapi_modify_internal( char *dn, LDAPMod **mods, LDAPControl **controls, int log_change)
{
int rc=LDAP_SUCCESS;
int i;
int dnBadChar;
LDAPMod *pMod;
LDAPMod *pNewMod;
LDAPMod *pTmpMod;
LDAPMod *pSaveMod;
LDAPMod *pModList=NULL;
Backend *be;
Slapi_PBlock *pPB=NULL;
Slapi_PBlock *pSavePB=NULL;
Connection *pConn=NULL;
int manageDsaIt = 0;
int isCritical;
struct berval bv;
struct berval *pbv;
AttributeDescription *ad;
const char *text;
Operation *op;
Modifications *modlist = NULL;
Modifications **modtail = &modlist;
struct berval pdn = { 0, NULL };
struct berval ndn = { 0, NULL };
pConn = fakeConnection( NULL, LDAP_REQ_MODIFY );
if ( pConn == NULL ) {
rc = LDAP_NO_MEMORY;
} else {
pPB = (Slapi_PBlock *)pConn->c_pending_ops.stqh_first->o_pb;
if ( dn == NULL || mods == NULL || *mods == NULL ) {
rc = LDAP_OPERATIONS_ERROR;
}
}
if ( rc == LDAP_SUCCESS ) {
dn_normalize( dn );
Debug(LDAP_DEBUG_TRACE,"slapi modifying object %s.\n", dn, 0, 0);
rc = dn_check(dn, &dnBadChar);
if ( rc == LDAP_SUCCESS ) {
/* We could be serving multiple database backends. Select the
* appropriate one, or send a referral to our "referral server"
* if we don't hold it.
*/
/* check if ManageDsaIt control is set */
if ( slapi_control_present( controls,
LDAP_CONTROL_MANAGEDSAIT, NULL, &isCritical ) ) {
manageDsaIt = 1; /* turn off referral */
}
bv.bv_val = strdup(dn);
bv.bv_len = strlen(dn);
be = select_backend(&bv, manageDsaIt, 0);
if ( be == NULL ) {
rc = LDAP_PARTIAL_RESULTS;
} else if ( be->be_modify == NULL ) {
rc = LDAP_UNWILLING_TO_PERFORM;
}
}
}
if ( rc == LDAP_SUCCESS ) {
for ( i=0, pMod=mods[0]; pMod != NULL; pMod=mods[++i] ) {
if ( (pMod->mod_op & LDAP_MOD_BVALUES) != 0 ) {
/* attr values are in berval format, merge them with the Entry's attr list */
rc = duplicateBVMod( pMod, &pNewMod );
} else {
pNewMod = (LDAPMod *)slapi_ch_malloc(sizeof(LDAPMod));
if ( pNewMod == NULL ) {
rc = LDAP_NO_MEMORY;
} else {
memset( pNewMod, '\0', sizeof(LDAPMod) );
pNewMod->mod_op = pMod->mod_op | LDAP_MOD_BVALUES;
pNewMod->mod_type = slapi_ch_strdup( pMod->mod_type );
if ( pNewMod->mod_type == NULL ) {
rc = LDAP_NO_MEMORY;
} else {
if ( (pMod->mod_op & ~LDAP_MOD_BVALUES) == LDAP_MOD_DELETE ) {
rc = ValuesToBValues( pMod->mod_values, &(pNewMod->mod_bvalues) );
} else {
if ( pMod->mod_values == NULL ) {
Debug(LDAP_DEBUG_TRACE,
"slapi_modify_internal:mod_values is null\n",0, 0, 0);
rc = LDAP_OTHER;
} else {
rc = ValuesToBValues( pMod->mod_values,
&(pNewMod->mod_bvalues) );
}
}
}
}
}
if ( rc == LDAP_SUCCESS ) {
/* add the new mod to the end of mod list */
if ( pModList == NULL ) {
pModList = pNewMod;
} else {
pTmpMod = pModList;
while ( pTmpMod != NULL ) {
pSaveMod = pTmpMod;
pTmpMod = pTmpMod->mod_next;
}
pSaveMod->mod_next = pNewMod;
}
}
} /* for each LDAPMod */
}
if ( rc == LDAP_SUCCESS ) {
/* convert LDAPModList to Modification list */
pTmpMod = pModList;
while (pTmpMod != NULL) {
Modifications *mod;
mod = (Modifications *) ch_malloc( sizeof(Modifications) );
mod->sml_type.bv_val = ch_strdup(pTmpMod->mod_type);
mod->sml_type.bv_len = strlen(pTmpMod->mod_type);
mod->sml_op = pTmpMod->mod_op;
pbv = NULL;
rc = bvptr2obj(pTmpMod->mod_bvalues, &pbv);
mod->sml_bvalues = pbv;
ad = NULL;
rc = slap_str2ad(pTmpMod->mod_type, &ad, &text );
mod->sml_desc = ad;
*modtail = mod;
modtail = &mod->sml_next;
pTmpMod = pTmpMod->mod_next;
}
*modtail = NULL;
}
if ( rc == LDAP_SUCCESS ) {
op = (Operation *)pConn->c_pending_ops.stqh_first;
op->o_ctrls = controls;
Debug (LDAP_DEBUG_TRACE, "Calling backend routine \n", 0, 0, 0);
pdn.bv_val = ch_strdup(dn);
pdn.bv_len = strlen(dn);
ndn.bv_val = ch_strdup(dn);
ndn.bv_len = strlen(dn);
rc = (*be->be_modify)( be, pConn, op, &pdn, &ndn, modlist );
if (rc == LDAP_SUCCESS)
Debug (LDAP_DEBUG_TRACE, " backend routine successful \n", 0, 0, 0);
else
Debug (LDAP_DEBUG_TRACE, " backend routine NOT successful \n", 0, 0, 0);
} else {
rc = LDAP_OPERATIONS_ERROR;
}
if ( pPB != NULL ) {
slapi_pblock_set( pPB, SLAPI_PLUGIN_INTOP_RESULT, (void *)rc );
}
if (pModList != NULL) {
freeModList( pModList );
}
if ( pConn != NULL ) {
if ( pConn->c_dn.bv_val )
slapi_ch_free( pConn->c_dn.bv_val );
if ( pConn->c_original_dn )
slapi_ch_free( pConn->c_original_dn );
if ( pConn->c_pending_ops.stqh_first->o_dn.bv_val )
slapi_ch_free( pConn->c_pending_ops.stqh_first->o_dn.bv_val);
if ( pConn->c_pending_ops.stqh_first )
slapi_ch_free( pConn->c_pending_ops.stqh_first );
pSavePB = pPB;
free( pConn );
}
return( pSavePB );
}
/* Function : slapi_modrdn_internal
*
* Description : Plugin functions call this routine to modify the rdn
* of an entry in the backend directly
* Return values : LDAP_SUCCESS
* LDAP_OPERAITONS_ERROR
* LDAP_NO_MEMORY
* LDAP_OTHER
* LDAP_UNWILLING_TO_PERFORM
*/
Slapi_PBlock *
slapi_modrdn_internal( char *olddn,
char *newrdn,
int deloldrdn,
LDAPControl **controls,
int log_change)
{
int rc=LDAP_SUCCESS;
int dnBadChar;
Backend *be;
char *pDn=NULL;
Slapi_PBlock *pPB=NULL;
Slapi_PBlock *pSavePB=NULL;
Connection *pConn=NULL;
int manageDsaIt = 0;
int isCritical;
struct berval bv = { 0, NULL };
Operation *op;
struct berval dn = { 0, NULL };
struct berval ndn = { 0, NULL };
struct berval pdn = { 0, NULL };
struct berval newrdnO = { 0, NULL };
struct berval nnewrdnO = { 0, NULL };
struct berval pnewrdnO = { 0, NULL };
struct berval *nnewS = NULL;
struct berval *pnewS = NULL;
dn.bv_val = ch_strdup(olddn);
if (dn.bv_val == NULL) {
rc = LDAP_NO_MEMORY;
} else {
dn.bv_len = strlen(olddn);
}
if (rc == LDAP_SUCCESS) {
newrdnO.bv_val = ch_strdup(newrdn);
if (newrdnO.bv_val == NULL) {
rc = LDAP_NO_MEMORY;
} else {
newrdnO.bv_len = strlen(newrdn);
}
}
if (rc == LDAP_SUCCESS) {
rc = dnPrettyNormal( NULL, &dn, &pdn, &ndn );
}
if (rc == LDAP_SUCCESS) {
rc = dnPrettyNormal( NULL, &newrdnO, &pnewrdnO, &nnewrdnO );
}
if ( rc == LDAP_SUCCESS ) {
pConn = fakeConnection(NULL, LDAP_REQ_MODRDN );
}
if ( pConn == NULL ) {
rc = LDAP_NO_MEMORY;
} else {
pPB = (Slapi_PBlock *)pConn->c_pending_ops.stqh_first->o_pb;
if ( olddn == NULL || newrdn == NULL ) {
rc = LDAP_OPERATIONS_ERROR;
}
}
if ( rc == LDAP_SUCCESS ) {
Debug(LDAP_DEBUG_TRACE,"slapi modify rdn %s new RDN: %s.\n", olddn, newrdn, 0);
rc = dn_check(olddn, &dnBadChar);
}
if ( rc == LDAP_SUCCESS ) {
/* We could be serving multiple database backends. Select the
* appropriate one, or send a referral to our "referral server"
* if we don't hold it. */
op = (Operation *)pConn->c_pending_ops.stqh_first;
op->o_ctrls = controls;
/* check if ManageDsaIt control is set */
if ( slapi_control_present( controls,
LDAP_CONTROL_MANAGEDSAIT, NULL, &isCritical ) ) {
manageDsaIt = 1; /* turn off referral */
}
be = select_backend(&bv, manageDsaIt, 0);
if ( be == NULL ) {
rc = LDAP_PARTIAL_RESULTS;
}
}
if ( rc == LDAP_SUCCESS ) {
if ( be->be_modrdn == NULL ) {
rc = LDAP_UNWILLING_TO_PERFORM;
} else {
Debug (LDAP_DEBUG_TRACE, "Calling backend routine \n", 0, 0, 0);
rc = (*be->be_modrdn)( be, pConn, op, &pdn, &ndn,
&pnewrdnO, &nnewrdnO, deloldrdn, pnewS, nnewS );
if (rc == LDAP_SUCCESS)
Debug (LDAP_DEBUG_TRACE, " backend routine successful \n", 0, 0, 0);
else
Debug (LDAP_DEBUG_TRACE, " backend routine NOT successful \n", 0, 0, 0);
}
}
if (dn.bv_val)
ch_free(dn.bv_val);
if (pdn.bv_val)
ch_free(pdn.bv_val);
if (ndn.bv_val)
ch_free(ndn.bv_val);
if (newrdnO.bv_val)
ch_free(newrdnO.bv_val);
if (pnewrdnO.bv_val)
ch_free(newrdnO.bv_val);
if (nnewrdnO.bv_val)
ch_free(newrdnO.bv_val);
if ( pPB != NULL ) {
slapi_pblock_set( pPB, SLAPI_PLUGIN_INTOP_RESULT, (void *)rc );
}
if ( pConn != NULL ) {
if ( pConn->c_dn.bv_val )
slapi_ch_free( pConn->c_dn.bv_val );
if (pConn->c_original_dn)
slapi_ch_free(pConn->c_original_dn);
if ( pConn->c_pending_ops.stqh_first->o_dn.bv_val )
slapi_ch_free( pConn->c_pending_ops.stqh_first->o_dn.bv_val );
if ( pConn->c_pending_ops.stqh_first )
slapi_ch_free( pConn->c_pending_ops.stqh_first );
pSavePB = pPB;
free( pConn );
}
return( pSavePB );
}
Slapi_PBlock *
slapi_search_internal( char *base, int scope, char *filStr,
LDAPControl **controls, char **attrs, int attrsonly )
{
return slapi_search_internal_bind(NULL,base,scope,filStr,controls, attrs,attrsonly);
}
Slapi_PBlock *
slapi_search_internal_bind( char *bindDN, char *b, int scope, char *filStr,
LDAPControl **controls, char **attrs, int attrsonly )
{
Slapi_PBlock *ptr;
Connection *c;
Backend *be;
Filter *filter=NULL;
int i, deref=0, sizelimit=-1, timelimit=-1, rc, dnCheckJunk=0;
int manageDsaIt = 0;
int isCritical;
struct berval bv;
Operation *op;
struct berval base = { 0, NULL };
struct berval pbase = { 0, NULL };
struct berval nbase = { 0, NULL };
AttributeName *an;
const char *text;
struct berval fstr = { 0, NULL };
c=fakeConnection(bindDN,LDAP_REQ_SEARCH);
if ( c == NULL ) {
rc = LDAP_NO_MEMORY;
} else {
ptr = (Slapi_PBlock *)c->c_pending_ops.stqh_first->o_pb;
}
/* check if ManageDsaIt control is set */
if ( rc = slapi_control_present( controls,
LDAP_CONTROL_MANAGEDSAIT, NULL, &isCritical ) ) {
manageDsaIt = 1; /* turn off referral */
}
if ( scope != LDAP_SCOPE_BASE && scope != LDAP_SCOPE_ONELEVEL
&& scope != LDAP_SCOPE_SUBTREE ) {
slapi_pblock_set(ptr,SLAPI_PLUGIN_INTOP_RESULT,(void *)LDAP_PROTOCOL_ERROR);
return ptr;
}
dn_normalize( b );
rc=dn_check(b, &dnCheckJunk);
if(rc != LDAP_SUCCESS) {
slapi_pblock_set(ptr,SLAPI_PLUGIN_INTOP_RESULT,(void *)rc);
return ptr;
}
if ( attrs != NULL ) {
for ( i = 0; attrs[i] != NULL; i++ )
attr_normalize( attrs[i] );
}
if((filter=slapi_str2filter(filStr)) == NULL) {
slapi_pblock_set(ptr,SLAPI_PLUGIN_INTOP_RESULT,(void *)LDAP_PROTOCOL_ERROR);
return ptr;
}
bv.bv_val = ch_strdup(b);
bv.bv_len = strlen(b);
/* check if ManageDsaIt control is set */
if ( slapi_control_present( controls,
LDAP_CONTROL_MANAGEDSAIT, NULL, &isCritical ) ) {
manageDsaIt = 1; /* turn off referral */
}
if ((be = select_backend( &bv, manageDsaIt, 0 )) == NULL) {
if ( manageDsaIt == 1 ) { /* referral turned off */
slapi_pblock_set(ptr,SLAPI_PLUGIN_INTOP_RESULT,(void *)LDAP_NO_SUCH_OBJECT);
} else {
slapi_pblock_set(ptr,SLAPI_PLUGIN_INTOP_RESULT,(void *)LDAP_PARTIAL_RESULTS);
}
return ptr;
} else if ( be->be_search == NULL ) {
slapi_pblock_set(ptr,SLAPI_PLUGIN_INTOP_RESULT,(void *)LDAP_UNWILLING_TO_PERFORM);
return ptr;
} else {
base.bv_val = ch_strdup(b);
base.bv_len = strlen(b);
rc = dnPrettyNormal( NULL, &base, &pbase, &nbase );
for (i = 0; attrs[i] != 0; i++) {
an[i].an_desc = NULL;
an[i].an_name.bv_val = ch_strdup(attrs[i]);
an[i].an_name.bv_len = strlen(attrs[i]);
slap_bv2ad(&an[i].an_name, &an[i].an_desc, &text);
}
fstr.bv_val = ch_strdup(filStr);
fstr.bv_len = strlen(filStr);
rc = (*be->be_search)( be, c, op, &pbase, &nbase, scope, deref,
sizelimit, timelimit, filter, &fstr, an, attrsonly );
}
slapi_pblock_set(ptr,SLAPI_PLUGIN_INTOP_RESULT,(void *)rc);
if ( c->c_pending_ops.stqh_first ){
if(c->c_dn.bv_val)
slapi_ch_free(c->c_dn.bv_val);
if (c->c_original_dn)
slapi_ch_free(c->c_original_dn);
if(c->c_pending_ops.stqh_first->o_dn.bv_val)
slapi_ch_free(c->c_pending_ops.stqh_first->o_dn.bv_val);
slapi_ch_free( c->c_pending_ops.stqh_first );
}
slapi_ch_free((void **)c);
if (filter)
slapi_filter_free(filter,1);
return ptr;
}
/*
Function : slapi_get_supported_extended_ops
Description : This function returns a pointer points to an array of Null terminated char pointers.
Each char pointer points to an oid of an extended operation.
If there is no defined extended operaitons, this routine returns NULL.
Input : none
Output : pointer to an null terminated char pointer array or null.
Notes: The caller of this routine needs to free the retuned array pointer, but
should not free the pointers inside the array.
*/
char
**slapi_get_supported_extended_ops(void)
{
ExtendedOp *pTmpExtOp;
int numExtOps = 0;
int i=0;
char **ppExtOpOID = NULL;
if ( pGExtendedOps != NULL ) {
pTmpExtOp = pGExtendedOps;
while ( pTmpExtOp != NULL ) {
numExtOps++;
pTmpExtOp = pTmpExtOp->ext_next;
}
if ( numExtOps > 0 ) {
ppExtOpOID = (char **)slapi_ch_malloc( (numExtOps+1) * sizeof(char *) );
if ( ppExtOpOID != NULL ) {
pTmpExtOp = pGExtendedOps;
while ( pTmpExtOp != NULL ) {
ppExtOpOID[i] = pTmpExtOp->ext_oid;
i++;
pTmpExtOp = pTmpExtOp->ext_next;
}
ppExtOpOID[i] = NULL;
}
}
}
return( ppExtOpOID );
}
Slapi_PBlock *
slapi_simple_bind_internal( char *d, struct berval *cred, int method, int version)
{
int rc=LDAP_SUCCESS;
Connection *pConn=NULL;
Backend *be;
Slapi_PBlock *pPB=NULL;
int dnBadChar;
int isCritical;
struct berval bv;
struct berval dn = { 0, NULL };
struct berval pdn = { 0, NULL };
struct berval ndn = { 0, NULL };
Operation *op;
pConn = fakeConnection(NULL, LDAP_REQ_BIND );
if ( pConn == NULL ) {
rc = LDAP_NO_MEMORY;
} else {
pPB = (Slapi_PBlock *)pConn->c_pending_ops.stqh_first->o_pb;
pConn->c_version = version;
op = (Operation *)pConn->c_pending_ops.stqh_first;
}
if ( d == NULL ) {
rc = LDAP_OPERATIONS_ERROR;
} else {
dn.bv_val = ch_strdup (d);
dn.bv_len = strlen(d);
rc = dnPrettyNormal( NULL, &dn, &pdn, &ndn );
}
if ( rc == LDAP_SUCCESS ) {
be = select_backend(&ndn, 0, 0 );
if ( be == NULL ) {
rc = LDAP_PARTIAL_RESULTS;
} else if ( be->be_bind == NULL ) {
rc = LDAP_UNWILLING_TO_PERFORM;
}
}
rc = (*be->be_bind)( be, pConn, op,
&pdn, &ndn, method, cred, NULL );
if (rc == LDAP_SUCCESS) {
pConn->c_version = version;
pConn->c_dn.bv_val = strdup( d );
pConn->c_dn.bv_len = strlen( d );
if (pConn->c_dn.bv_val == NULL) {
rc = LDAP_NO_MEMORY;
Debug (LDAP_DEBUG_TRACE, " backend routine successful, but has no more memory \n",0, 0, 0);
}
Debug (LDAP_DEBUG_TRACE, " backend routine NOT successful \n", 0, 0, 0);
}
if ( pPB != NULL )
slapi_pblock_set( pPB, SLAPI_PLUGIN_INTOP_RESULT, (void *)rc );
return(pPB);
}