Start development on 386BSD 0.0
[unix-history] / .ref-BSD-4_3_Net_2 / usr / src / contrib / isode / quipu / ds_modify.c
/* ds_modify.c - */
#ifndef lint
static char *rcsid = "$Header: /f/osi/quipu/RCS/ds_modify.c,v 7.5 91/03/09 11:56:44 mrose Exp $";
#endif
/*
* $Header: /f/osi/quipu/RCS/ds_modify.c,v 7.5 91/03/09 11:56:44 mrose Exp $
*
*
* $Log: ds_modify.c,v $
* Revision 7.5 91/03/09 11:56:44 mrose
* update
*
* Revision 7.4 91/02/22 09:38:51 mrose
* Interim 6.8
*
* Revision 7.3 90/10/17 11:53:46 mrose
* sync
*
* Revision 7.2 90/07/09 14:45:45 mrose
* sync
*
* Revision 7.1 89/12/19 16:20:16 mrose
* sync
*
* Revision 7.0 89/11/23 22:17:10 mrose
* Release 6.0
*
*/
/*
* NOTICE
*
* Acquisition, use, and distribution of this module and related
* materials are subject to the restrictions of a license agreement.
* Consult the Preface in the User's Manual for the full terms of
* this agreement.
*
*/
#include "quipu/config.h"
#include "quipu/util.h"
#include "quipu/entry.h"
#include "quipu/modify.h"
#include "quipu/malloc.h"
#include "config.h"
#include "pepsy.h"
#include "quipu/DAS_pre_defs.h"
static check_remove_values ();
static check_remove_type ();
extern Entry database_root;
extern LLog * log_dsap;
extern Attr_Sequence entry_find_type();
extern DN mydsadn;
extern AttributeType at_control;
extern AttributeType at_acl;
extern AttributeType at_objectclass;
#ifdef TURBO_AVL
extern int inherit_link();
#endif
Entry nulledb;
static AttributeValue nonleafav = NULLAttrV;
struct acl *acl_list;
int updateerror;
do_ds_modifyentry (arg, error, binddn, target, di_p, dsp)
struct ds_modifyentry_arg *arg;
struct DSError *error;
DN binddn;
DN target;
struct di_block **di_p;
char dsp;
{
Entry entryptr;
Entry real_entry;
struct entrymod *eptr;
Entry entry_cpy ();
int remove = NOTOK;
int retval;
extern int read_only;
char * new_version ();
Attr_Sequence as;
DLOG (log_dsap,LLOG_TRACE,("ds_modifyentry"));
if (!dsp)
target = arg->mea_object;
/* stop aliases being dereferenced */
arg->mea_common.ca_servicecontrol.svc_options |= SVC_OPT_DONTDEREFERENCEALIAS;
/* check for control sequence */
if (!dsp && arg->mea_changes
&& (arg->mea_changes->em_type == EM_ADDATTRIBUTE)) {
if ( AttrT_cmp (arg->mea_changes->em_what->attr_type,at_control) == 0) {
int res;
res = dsa_control (arg->mea_changes->em_what,error,binddn);
return (res);
}
}
if (target == NULLDN) {
error->dse_type = DSE_NAMEERROR;
error->ERR_NAME.DSE_na_problem = DSE_NA_NOSUCHOBJECT;
error->ERR_NAME.DSE_na_matched = NULLDN;
return (DS_ERROR_REMOTE);
}
switch(find_entry(target,&(arg->mea_common),binddn,NULLDNSEQ,TRUE,&(real_entry), error, di_p, OP_MODIFYENTRY))
{
case DS_OK:
/* Filled out entryptr - carry on */
break;
case DS_CONTINUE:
/* Filled out di_p - what do we do with it ?? */
return(DS_CONTINUE);
case DS_X500_ERROR:
/* Filled out error - what do we do with it ?? */
return(DS_X500_ERROR);
default:
/* SCREAM */
LLOG(log_dsap, LLOG_EXCEPTIONS, ("do_ds_modify() - find_entry failed"));
return(DS_ERROR_LOCAL);
}
/* Strong authentication */
if ((retval = check_security_parms((caddr_t) arg,
_ZModifyEntryArgumentDataDAS,
&_ZDAS_mod,
arg->mea_common.ca_security,
arg->mea_common.ca_sig, &binddn)) != 0)
{
error->dse_type = DSE_SECURITYERROR;
error->ERR_SECURITY.DSE_sc_problem = retval;
return (DS_ERROR_REMOTE);
}
if (read_only || real_entry->e_parent->e_lock) {
error->dse_type = DSE_SERVICEERROR;
error->ERR_SERVICE.DSE_sv_problem = DSE_SV_UNAVAILABLE;
return (DS_ERROR_REMOTE);
}
/* not prepared to accept operation over DSP */
if (dsp) {
error->dse_type = DSE_SECURITYERROR;
error->ERR_SECURITY.DSE_sc_problem = DSE_SC_AUTHENTICATION;
return (DS_ERROR_REMOTE);
}
DATABASE_HEAP;
entryptr = entry_cpy (real_entry);
acl_list = real_entry->e_acl;
GENERAL_HEAP;
if (check_acl (binddn, ACL_ADD, acl_list->ac_entry,target) == NOTOK) {
error->dse_type = DSE_SECURITYERROR;
error->ERR_SECURITY.DSE_sc_problem = DSE_SC_ACCESSRIGHTS;
entry_free (entryptr);
return (DS_ERROR_REMOTE);
}
if (check_acl (binddn, ACL_WRITE, acl_list->ac_entry,target) == OK)
remove = OK;
nulledb = NULLENTRY;
for (eptr = arg->mea_changes; eptr!=NULLMOD; eptr=eptr->em_next) {
switch (eptr->em_type) {
case EM_ADDVALUES:
if (mod_add_value (entryptr,eptr->em_what,error,binddn,target,real_entry) != OK) {
entry_free (entryptr);
return (DS_ERROR_REMOTE);
}
break;
case EM_ADDATTRIBUTE:
if (add_attribute (entryptr,eptr->em_what,error,binddn,target) != OK) {
entry_free (entryptr);
return (DS_ERROR_REMOTE);
}
break;
case EM_REMOVEATTRIBUTE:
/* must not do this if attribute is rdn */
if (check_remove_type (entryptr->e_name,eptr->em_what->attr_type) == NOTOK) {
error->dse_type = DSE_UPDATEERROR;
error->ERR_UPDATE.DSE_up_problem = updateerror;
entry_free (entryptr);
return (DS_ERROR_REMOTE);
}
if (remove == OK) {
if (remove_attribute (entryptr,eptr->em_what->attr_type,error,binddn,target,real_entry) != OK) {
entry_free (entryptr);
return (DS_ERROR_REMOTE);
}
} else {
error->dse_type = DSE_SECURITYERROR;
error->ERR_SECURITY.DSE_sc_problem = DSE_SC_ACCESSRIGHTS;
entry_free (entryptr);
return (DS_ERROR_REMOTE);
}
break;
case EM_REMOVEVALUES:
if (check_remove_values (entryptr->e_name, eptr->em_what) == NOTOK) {
error->dse_type = DSE_UPDATEERROR;
error->ERR_UPDATE.DSE_up_problem = updateerror;
entry_free (entryptr);
return (DS_ERROR_REMOTE);
}
if (remove == OK) {
if (remove_value (entryptr,eptr->em_what,error,binddn,target,real_entry) != OK) {
entry_free (entryptr);
return (DS_ERROR_REMOTE);
}
} else {
error->dse_type = DSE_SECURITYERROR;
error->ERR_SECURITY.DSE_sc_problem = DSE_SC_ACCESSRIGHTS;
entry_free (entryptr);
return (DS_ERROR_REMOTE);
}
break;
}
}
/* check the last value of an attribute has not been removed */
for (as = entryptr->e_attributes; as!=NULLATTR; as=as->attr_link)
if (as->attr_value == NULLAV) {
error->dse_type = DSE_ATTRIBUTEERROR;
error->ERR_ATTRIBUTE.DSE_at_name = get_copy_dn (entryptr);
error->ERR_ATTRIBUTE.DSE_at_plist.DSE_at_what =DSE_AT_CONSTRAINTVIOLATION;
error->ERR_ATTRIBUTE.DSE_at_plist.DSE_at_type = AttrT_cpy (as->attr_type);
error->ERR_ATTRIBUTE.DSE_at_plist.DSE_at_value = NULLAttrV;
error->ERR_ATTRIBUTE.DSE_at_plist.dse_at_next = DSE_AT_NOPROBLEM;
entry_free (entryptr);
return (DS_ERROR_REMOTE);
}
DATABASE_HEAP;
modify_attr (entryptr,binddn);
if (unravel_attribute (entryptr,error) != OK) {
GENERAL_HEAP;
entry_free (entryptr);
return (DS_ERROR_REMOTE);
} else if ( ! check_oc_hierarchy(entryptr->e_oc)) {
error->dse_type = DSE_UPDATEERROR;
error->ERR_UPDATE.DSE_up_problem = DSE_UP_OBJECTCLASSVIOLATION;
GENERAL_HEAP;
entry_free (entryptr);
return (DS_ERROR_REMOTE);
} else if (check_schema (entryptr,NULLATTR,error) == OK) {
GENERAL_HEAP;
/* Check user has not prevented further modification by themselves ! */
if ((acl_list != entryptr->e_acl)
&& (acl_cmp (acl_list,entryptr->e_acl) != 0)) {
if ((as = entry_find_type (entryptr,at_acl)) == NULLATTR) {
LLOG(log_dsap,LLOG_NOTICE,("Attempt to remove ACL"));
error->dse_type = DSE_SERVICEERROR;
error->ERR_SERVICE.DSE_sv_problem = DSE_SV_UNWILLINGTOPERFORM;
return (DS_ERROR_REMOTE);
}
if ((check_acl (binddn, ACL_WRITE, as->attr_acl,target) == NOTOK) ||
(check_acl (binddn, ACL_WRITE, entryptr->e_acl->ac_entry,target) == NOTOK)) {
entry_free (entryptr);
LLOG(log_dsap,LLOG_NOTICE,("Not modifying due to future access problem"));
error->dse_type = DSE_SERVICEERROR;
error->ERR_SERVICE.DSE_sv_problem = DSE_SV_UNWILLINGTOPERFORM;
return (DS_ERROR_REMOTE);
}
}
if (nulledb) {
AV_Sequence avs;
for (avs = entryptr->e_master; avs != NULLAV; avs=avs->avseq_next) {
if (avs->avseq_av.av_struct == NULL)
continue;
if (dn_cmp ((DN)avs->avseq_av.av_struct,mydsadn) == 0) {
create_null_edb (nulledb);
break;
}
}
if (avs == NULLAV)
entryptr->e_allchildrenpresent = FALSE;
}
write_dsa_entry (entryptr);
#ifdef TURBO_AVL
/*
* changes made OK, so add new entry into tree.
* instead of inserting entryptr (the ptr to the
* modified version of the entry), we free the
* old contents of the old entry and copy in the
* new data. this saves us from having to update
* all parent pointers in child nodes.
*/
#ifdef TURBO_INDEX
/* delete old entry from index first */
turbo_index_delete(real_entry);
#endif
if (entryptr->e_parent == NULLENTRY) {
entry_replace(database_root, entryptr);
} else {
entry_replace(real_entry, entryptr);
}
entry_free (entryptr);
entryptr = real_entry;
if (unravel_attribute(real_entry, error) != OK)
return(DS_ERROR_REMOTE);
if (real_entry->e_parent != NULLENTRY) {
if (real_entry->e_parent->e_edbversion)
free (real_entry->e_parent->e_edbversion);
real_entry->e_parent->e_edbversion = new_version();
}
(void) avl_apply(real_entry->e_children, inherit_link,
(caddr_t) real_entry, NOTOK, AVL_PREORDER);
#ifdef TURBO_INDEX
/* add the new modified entry to the index */
turbo_add2index(real_entry);
#endif
#else
/* changes made OK, so add new entry into tree */
if (entryptr->e_parent == NULLENTRY) {
database_root = entryptr;
entry_free (real_entry);
if (entryptr->e_data == E_TYPE_SLAVE)
/* Our copy of DSA entry - don't rewrite EDB */
return DS_OK;
} else {
entryptr->e_parent->e_child = entryptr;
entry_free (real_entry);
/* now alter all parent pointers */
for (real_entry = entryptr->e_child; real_entry!=NULLENTRY; real_entry=real_entry->e_sibling) {
real_entry->e_parent = entryptr;
set_inheritance (real_entry);
}
if (entryptr->e_data == E_TYPE_SLAVE)
/* Our copy of DSA entry - don't rewrite EDB */
return DS_OK;
if (entryptr->e_parent->e_edbversion)
free (entryptr->e_parent->e_edbversion);
entryptr->e_parent->e_edbversion = new_version();
}
#endif /* TURBO_AVL */
#ifdef TURBO_DISK
if (turbo_write(entryptr) != OK)
fatal (-33,"modify rewrite failed - check database");
#else
if (journal (entryptr) != OK)
fatal (-33,"modify rewrite failed - check database");
#endif
return (DS_OK);
} else {
entry_free (entryptr);
return (DS_ERROR_REMOTE);
}
}
remove_attribute (eptr,at,error,requestor,dn,real_entry)
Entry eptr,real_entry;
AttributeType at;
struct DSError *error;
DN requestor,dn;
{
register Attr_Sequence as, trail= NULLATTR, real_as;
DLOG (log_dsap,LLOG_DEBUG,("remove attribute"));
for (as=eptr->e_attributes; as!=NULLATTR; as=as->attr_link) {
if ((AttrT_cmp (as->attr_type,at)) == 0)
break;
trail = as;
}
if ((as == NULLATTR) ||
((real_as = as_find_type (real_entry->e_attributes,at)) == NULLATTR)) {
if (entry_find_type(real_entry,at) == NULLATTR) {
error->dse_type = DSE_ATTRIBUTEERROR;
error->ERR_ATTRIBUTE.DSE_at_name = get_copy_dn (eptr);
error->ERR_ATTRIBUTE.DSE_at_plist.DSE_at_what =DSE_AT_NOSUCHATTRIBUTE;
error->ERR_ATTRIBUTE.DSE_at_plist.DSE_at_type = AttrT_cpy (at);
error->ERR_ATTRIBUTE.DSE_at_plist.DSE_at_value = NULLAttrV;
error->ERR_ATTRIBUTE.DSE_at_plist.dse_at_next = DSE_AT_NOPROBLEM;
return (DS_ERROR_REMOTE);
} else {
LLOG (log_dsap,LLOG_EXCEPTIONS,("Can't remove inherited attribute"));
error->dse_type = DSE_SECURITYERROR;
error->ERR_SECURITY.DSE_sc_problem = DSE_SC_ACCESSRIGHTS;
return (DS_ERROR_REMOTE);
}
}
if (check_acl(requestor,ACL_WRITE,real_as->attr_acl,dn) == NOTOK) {
error->dse_type = DSE_SECURITYERROR;
error->ERR_SECURITY.DSE_sc_problem = DSE_SC_ACCESSRIGHTS;
return (DS_ERROR_REMOTE);
}
if (trail == NULLATTR) {
/* first in sequence */
eptr->e_attributes = as->attr_link;
as_comp_free (as);
} else
as_delnext (trail);
return (OK);
}
static check_remove_type (rdn,at)
register RDN rdn;
register AttributeType at;
{
if ( AttrT_cmp (at,at_objectclass) == 0) {
updateerror = DSE_UP_NOOBJECTCLASSMODS;
return (NOTOK);
}
/* check attribute type is not distinguished */
for (; rdn!=NULLRDN; rdn=rdn->rdn_next)
if (AttrT_cmp (rdn->rdn_at,at) == 0) {
updateerror = DSE_UP_NOTONRDN;
return (NOTOK);
}
return (OK);
}
static check_remove_values (rdn,as)
register RDN rdn;
register Attr_Sequence as;
{
register AV_Sequence as_avs;
/* check that the value trying to remove is not distinguished */
for (; rdn!=NULLRDN; rdn=rdn->rdn_next)
if (AttrT_cmp (rdn->rdn_at,as->attr_type) == 0)
for (as_avs=as->attr_value; as_avs!=NULLAV; as_avs=as_avs->avseq_next)
if (AttrV_cmp (&rdn->rdn_av,&as_avs->avseq_av) == 0) {
updateerror = DSE_UP_NOTONRDN;
return (NOTOK);
}
return (OK);
}
remove_value (eptr,rmas,error,requestor,dn,real_entry)
Entry eptr, real_entry;
Attr_Sequence rmas;
struct DSError *error;
DN requestor,dn;
{
register Attr_Sequence as,real_as;
register AV_Sequence rmavs,avs,trail = NULLAV;
int i;
DLOG (log_dsap,LLOG_DEBUG,("remove attribute value"));
if (((as = as_find_type (eptr->e_attributes,rmas->attr_type)) == NULLATTR)
|| (((real_as = as_find_type (real_entry->e_attributes,rmas->attr_type)) == NULLATTR))) {
if (((as = entry_find_type (eptr,rmas->attr_type)) == NULLATTR)
|| (((real_as = entry_find_type (real_entry,rmas->attr_type)) == NULLATTR))) {
error->dse_type = DSE_ATTRIBUTEERROR;
error->ERR_ATTRIBUTE.DSE_at_name = get_copy_dn (eptr);
error->ERR_ATTRIBUTE.DSE_at_plist.DSE_at_what =DSE_AT_NOSUCHATTRIBUTE;
error->ERR_ATTRIBUTE.DSE_at_plist.DSE_at_type = AttrT_cpy (rmas->attr_type);
error->ERR_ATTRIBUTE.DSE_at_plist.DSE_at_value = NULLAttrV;
error->ERR_ATTRIBUTE.DSE_at_plist.dse_at_next = DSE_AT_NOPROBLEM;
return (DS_ERROR_REMOTE);
} else {
/* inherited - ignore removal if allowed */
if (check_acl(requestor,ACL_WRITE,real_as->attr_acl,dn) == NOTOK) {
LLOG (log_dsap,LLOG_EXCEPTIONS,("Can't remove inherited value"));
error->dse_type = DSE_SECURITYERROR;
error->ERR_SECURITY.DSE_sc_problem = DSE_SC_ACCESSRIGHTS;
return (NOTOK);
}
return OK;
}
}
if (check_acl(requestor,ACL_WRITE,real_as->attr_acl,dn) == NOTOK) {
error->dse_type = DSE_SECURITYERROR;
error->ERR_SECURITY.DSE_sc_problem = DSE_SC_ACCESSRIGHTS;
return (NOTOK);
}
for (rmavs=rmas->attr_value; rmavs != NULLAV; rmavs = rmavs->avseq_next) {
for (avs=as->attr_value; avs!=NULLAV; avs=avs->avseq_next) {
if ((i = AttrV_cmp(&avs->avseq_av,&rmavs->avseq_av)) == 0)
break;
if (i == -2) {
error->dse_type = DSE_ATTRIBUTEERROR;
error->ERR_ATTRIBUTE.DSE_at_name = NULLDN;
error->ERR_ATTRIBUTE.DSE_at_plist.DSE_at_what = DSE_AT_INAPPROPRIATEMATCHING;
error->ERR_ATTRIBUTE.DSE_at_plist.DSE_at_type = AttrT_cpy (as->attr_type);
error->ERR_ATTRIBUTE.DSE_at_plist.DSE_at_value = AttrV_cpy(&rmas->attr_value->avseq_av);
error->ERR_ATTRIBUTE.DSE_at_plist.dse_at_next = DSE_AT_NOPROBLEM;
return (DS_ERROR_REMOTE);
}
trail = avs;
}
if (avs == NULLAV) {
error->dse_type = DSE_ATTRIBUTEERROR;
error->ERR_ATTRIBUTE.DSE_at_name = get_copy_dn (eptr);
error->ERR_ATTRIBUTE.DSE_at_plist.DSE_at_what =DSE_AT_NOSUCHATTRIBUTE;
error->ERR_ATTRIBUTE.DSE_at_plist.DSE_at_type = AttrT_cpy (rmas->attr_type);
error->ERR_ATTRIBUTE.DSE_at_plist.DSE_at_value = AttrV_cpy (&rmas->attr_value->avseq_av);
error->ERR_ATTRIBUTE.DSE_at_plist.dse_at_next = DSE_AT_NOPROBLEM;
return (DS_ERROR_REMOTE);
}
/* SPT addition for empty non-leaves */
/* Removing the nonLeafObject objectclass makes it a leaf again,
* if this is allowed. */
if (nonleafav == NULLAttrV)
nonleafav = str2AttrV(NONLEAFOBJECT, str2syntax("objectClass"));
if (AttrT_cmp(as->attr_type, at_objectclass) == 0 &&
AttrV_cmp(&avs->avseq_av, nonleafav ) == 0)
{
#ifdef TURBO_AVL
Entry chld;
chld = (Entry) avl_getone(eptr->e_children);
if (!eptr->e_leaf && chld && chld->e_data == E_DATA_MASTER)
#else
if ((!eptr->e_leaf && eptr->e_child &&
(eptr->e_child->e_data == E_DATA_MASTER))
#endif
{
LLOG (log_dsap, LLOG_EXCEPTIONS,("Can't remove non leaf object class - children below"));
error->dse_type = DSE_UPDATEERROR;
error->ERR_UPDATE.DSE_up_problem = DSE_UP_NOTONNONLEAF;
return(DS_ERROR_REMOTE) ;
}
/*After all that, we should be able to remove stuff... */
eptr->e_leaf = TRUE ; /* Make it a leaf */
/* Let it continue, & remove attrV */
/* Also have to remove the EDB File that was generated there */
}
if (trail == NULLAV) {
/* first in sequence */
as->attr_value = avs->avseq_next;
avs_comp_free (avs);
} else
avs_delnext (trail);
}
return (OK);
}
add_attribute (eptr,newas,error,requestor,dn)
Entry eptr;
Attr_Sequence newas;
struct DSError *error;
DN requestor,dn;
{
struct acl_attr * aa;
struct acl_info * ai = NULLACL_INFO;
struct oid_seq * oidptr;
DLOG (log_dsap,LLOG_DEBUG,("add attribute"));
if (entry_find_type (eptr,newas->attr_type) != NULLATTR) {
error->dse_type = DSE_ATTRIBUTEERROR;
error->ERR_ATTRIBUTE.DSE_at_name = dn_cpy (dn);
error->ERR_ATTRIBUTE.DSE_at_plist.DSE_at_what = DSE_AT_TYPEORVALUEEXISTS;
error->ERR_ATTRIBUTE.DSE_at_plist.DSE_at_type = AttrT_cpy (newas->attr_type);
error->ERR_ATTRIBUTE.DSE_at_plist.DSE_at_value = NULLAttrV;
error->ERR_ATTRIBUTE.DSE_at_plist.dse_at_next = DSE_AT_NOPROBLEM;
DLOG (log_dsap,LLOG_DEBUG,("add exists error"));
return (NOTOK);
}
for ( aa = acl_list->ac_attributes; aa!=NULLACL_ATTR; aa=aa->aa_next) {
for ( oidptr=aa->aa_types;oidptr != NULLOIDSEQ; oidptr=oidptr->oid_next) {
if (oid_cmp (oidptr->oid_oid,grab_oid(newas->attr_type)) == 0) {
ai = aa->aa_acl;
break;
}
}
if (ai != NULLACL_INFO)
break;
}
if (ai == NULLACL_INFO)
ai = acl_list->ac_default;
if (check_acl(requestor,ACL_WRITE,ai,dn) == NOTOK) {
error->dse_type = DSE_SECURITYERROR;
error->ERR_SECURITY.DSE_sc_problem = DSE_SC_ACCESSRIGHTS;
DLOG (log_dsap,LLOG_DEBUG,("add acl failed"));
return (NOTOK);
}
DATABASE_HEAP;
eptr->e_attributes = as_merge (as_cpy(newas),eptr->e_attributes);
GENERAL_HEAP;
return (OK);
}
mod_add_value (eptr,newas,error,requestor,dn,real_entry)
Entry eptr,real_entry;
Attr_Sequence newas;
struct DSError *error;
DN requestor,dn;
{
register Attr_Sequence as;
AV_Sequence avs;
char * dn2edbfile();
DLOG (log_dsap,LLOG_DEBUG,("add value"));
if ( (as = entry_find_type (real_entry,newas->attr_type)) == NULLATTR) {
error->dse_type = DSE_ATTRIBUTEERROR;
error->ERR_ATTRIBUTE.DSE_at_name = dn_cpy (dn);
error->ERR_ATTRIBUTE.DSE_at_plist.DSE_at_what = DSE_AT_NOSUCHATTRIBUTE;
error->ERR_ATTRIBUTE.DSE_at_plist.DSE_at_type = AttrT_cpy (newas->attr_type);
error->ERR_ATTRIBUTE.DSE_at_plist.DSE_at_value = NULLAttrV;
error->ERR_ATTRIBUTE.DSE_at_plist.dse_at_next = DSE_AT_NOPROBLEM;
return (NOTOK);
}
if (check_acl(requestor,ACL_WRITE,as->attr_acl,dn) == NOTOK) {
error->dse_type = DSE_SECURITYERROR;
error->ERR_SECURITY.DSE_sc_problem = DSE_SC_ACCESSRIGHTS;
DLOG (log_dsap,LLOG_DEBUG,("add acl failed"));
return (NOTOK);
}
if ( as_find_type (real_entry->e_attributes,newas->attr_type) == NULLATTR) {
/* its inherited - add into the entry itself */
DATABASE_HEAP;
eptr->e_attributes = as_merge (as_cpy(newas),eptr->e_attributes);
GENERAL_HEAP;
return (OK);
}
for (avs=as->attr_value; avs != NULLAV; avs=avs->avseq_next)
if (AttrV_cmp(&avs->avseq_av,&newas->attr_value->avseq_av) == 0) {
error->dse_type = DSE_ATTRIBUTEERROR;
error->ERR_ATTRIBUTE.DSE_at_name = dn_cpy (dn);
error->ERR_ATTRIBUTE.DSE_at_plist.DSE_at_what = DSE_AT_TYPEORVALUEEXISTS;
error->ERR_ATTRIBUTE.DSE_at_plist.DSE_at_type = AttrT_cpy (newas->attr_type);
error->ERR_ATTRIBUTE.DSE_at_plist.DSE_at_value = AttrV_cpy (&newas->attr_value->avseq_av);
error->ERR_ATTRIBUTE.DSE_at_plist.dse_at_next = DSE_AT_NOPROBLEM;
DLOG (log_dsap,LLOG_DEBUG,("add value exists error"));
return (NOTOK);
}
if (nonleafav == NULLAttrV)
nonleafav = str2AttrV(NONLEAFOBJECT, str2syntax("objectClass"));
if ((AttrT_cmp(as->attr_type, at_objectclass) == 0) &&
AttrV_cmp(&newas->attr_value->avseq_av, nonleafav) == 0)
{
nulledb = eptr;
/* will sort out the EDB file later if needed */
}
DATABASE_HEAP;
eptr->e_attributes = as_merge (as_cpy(newas),eptr->e_attributes);
GENERAL_HEAP;
return (OK);
}
create_null_edb (eptr)
Entry eptr;
{
DN save_dn ;
char *filename, *dn2edbfile();
Entry empty_entry;
#ifdef TURBO_DISK
char gfname[1024];
#endif
eptr->e_leaf = FALSE ;
#ifdef TURBO_AVL
eptr->e_children = NULLAVL ;
#else
eptr->e_child = NULLENTRY ;
#endif
eptr->e_allchildrenpresent = 2 ;
empty_entry = get_default_entry (eptr);
empty_entry->e_data = E_DATA_MASTER ;
if (eptr->e_parent->e_edbversion)
free (eptr->e_parent->e_edbversion);
eptr->e_parent->e_edbversion = new_version();
save_dn = get_copy_dn(eptr) ;
if ((filename = dn2edbfile(save_dn)) == NULLCP)
{
fatal(-33, "SPT: ds_modify: 1 creating new NLN out failed.\n");
}
#ifdef TURBO_DISK
strcpy(gfname, filename);
strcat(gfname, ".gdbm");
if (turbo_writeall(eptr) != OK) {
fatal(-33, "create_null_edb: turbo_writeall failed.\n");
}
#else
if (write_edb(empty_entry, filename) != OK)
{
(void) unlink (filename);
fatal(-33, "SPT: ds_modify: 2 writing new NLN out failed.\n") ;
}
#endif
dn_free (save_dn);
free ((char *)empty_entry);
}