BSD 4_3_Net_2 development
[unix-history] / usr / src / contrib / isode / quipu / ds_add.c
/* ds_add.c - */
#ifndef lint
static char *rcsid = "$Header: /f/osi/quipu/RCS/ds_add.c,v 7.4 91/02/22 09:38:41 mrose Interim $";
#endif
/*
* $Header: /f/osi/quipu/RCS/ds_add.c,v 7.4 91/02/22 09:38:41 mrose Interim $
*
*
* $Log: ds_add.c,v $
* Revision 7.4 91/02/22 09:38:41 mrose
* Interim 6.8
*
* Revision 7.3 90/10/17 11:53:36 mrose
* sync
*
* Revision 7.2 90/07/09 14:45:37 mrose
* sync
*
* Revision 7.1 90/01/11 18:37:19 mrose
* real-sync
*
* Revision 7.0 89/11/23 22:17:03 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/add.h"
#include "quipu/malloc.h"
#ifdef TURBO_AVL
#include "quipu/turbo.h"
#endif
#include "pepsy.h"
#include "quipu/DAS_pre_defs.h"
extern Entry database_root;
extern LLog * log_dsap;
extern int local_master_size;
extern DN mydsadn;
extern AttributeType at_masterdsa;
extern AttributeType at_slavedsa;
extern AttributeType at_objectclass;
#ifdef TURBO_INDEX
extern AttributeType *turbo_index_types;
#endif
do_ds_addentry (arg, error, binddn,target,di_p,dsp)
struct ds_addentry_arg *arg;
struct DSError *error;
DN binddn;
DN target;
struct di_block **di_p;
char dsp;
{
Entry entryptr,ptr;
register DN dntop, dn = NULLDN;
DN trail = NULLDN;
extern Entry database_root;
ContinuationRef cont_ref_parent ();
char * new_version ();
int retval;
extern int read_only;
#ifdef TURBO_AVL
extern int entry_cmp();
#endif
DLOG (log_dsap,LLOG_TRACE,("ds_add"));
if (!dsp)
target = arg->ada_object;
/* stop aliases being dereferenced */
arg->ada_common.ca_servicecontrol.svc_options |= SVC_OPT_DONTDEREFERENCEALIAS;
error ->dse_type = DSE_NOERROR;
/* first of all see if entry exists */
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->ada_common),binddn,NULLDNSEQ,TRUE,&entryptr, error, di_p, OP_ADDENTRY))
{
case DS_OK:
error->dse_type = DSE_UPDATEERROR;
error->ERR_UPDATE.DSE_up_problem = DSE_UP_ALREADYEXISTS;
return(DS_ERROR_REMOTE);
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 ?? */
if ((error->dse_type != DSE_NAMEERROR) || (error->ERR_NAME.DSE_na_problem != DSE_NA_NOSUCHOBJECT)) {
return(DS_X500_ERROR);
}
ds_error_free (error); /* not interested - know it does not exist */
break;
default:
/* SCREAM */
LLOG(log_dsap, LLOG_EXCEPTIONS, ("do_ds_read() - find_entry failed"));
return(DS_ERROR_LOCAL);
}
/* object does not exist, so create it */
/* Strong authentication */
if ((retval = check_security_parms((caddr_t) arg,
_ZAddEntryArgumentDataDAS,
&_ZDAS_mod,
arg->ada_common.ca_security,
arg->ada_common.ca_sig, &binddn)) != 0)
{
error->dse_type = DSE_SECURITYERROR;
error->ERR_SECURITY.DSE_sc_problem = retval;
return (DS_ERROR_REMOTE);
}
DLOG (log_dsap,LLOG_TRACE,("add - find parent"));
if ((dntop = dn_cpy(target)) != NULLDN)
for (dn=dntop; dn->dn_parent != NULLDN; dn=dn->dn_parent)
trail = dn;
if (trail == NULLDN) {
dntop = NULLDN;
entryptr = database_root;
if (entryptr->e_data != E_DATA_MASTER) {
error->dse_type = DSE_REFERRAL;
error->ERR_REFERRAL.DSE_ref_prefix = NULLDN;
if ((error->ERR_REFERRAL.DSE_ref_candidates = cont_ref_parent (NULLDN)) == NULLCONTINUATIONREF) {
error->dse_type = DSE_SERVICEERROR;
error->ERR_SERVICE.DSE_sv_problem = DSE_SV_INVALIDREFERENCE;
}
return (DS_ERROR_CONNECT);
}
} else {
trail->dn_parent = NULLDN;
switch(find_child_entry(dntop,&(arg->ada_common),binddn,NULLDNSEQ,TRUE,&(entryptr), error, di_p))
{
case DS_OK:
/* Filled out entryptr - carry on */
break;
case DS_CONTINUE:
/* Filled out di_p - what do we do with it ?? */
/* When add returns DS_CONTINUE the target must be changed */
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_add() - find_child_entry failed"));
return(DS_ERROR_LOCAL);
}
}
if ( read_only || ((entryptr->e_parent != NULLENTRY) && (entryptr->e_parent->e_lock))) {
error->dse_type = DSE_SERVICEERROR;
error->ERR_SERVICE.DSE_sv_problem = DSE_SV_UNWILLINGTOPERFORM;
dn_free (dntop);
dn_free (dn);
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;
dn_free (dntop);
dn_free (dn);
return (DS_ERROR_REMOTE);
}
DLOG (log_dsap,LLOG_TRACE,("add - acl"));
if (check_acl (binddn,ACL_ADD,entryptr->e_acl->ac_child,dntop) == NOTOK) {
error->dse_type = DSE_SECURITYERROR;
error->ERR_SECURITY.DSE_sc_problem = DSE_SC_ACCESSRIGHTS;
dn_free (dntop);
dn_free (dn);
return (DS_ERROR_REMOTE);
}
DLOG (log_dsap,LLOG_TRACE,("add - default"));
DATABASE_HEAP;
ptr = get_default_entry (entryptr);
ptr->e_name = rdn_cpy (dn->dn_rdn);
ptr->e_attributes = as_cpy (arg->ada_entry);
modify_attr (ptr,binddn);
DLOG (log_dsap,LLOG_TRACE,("add - unravel"));
if (unravel_attribute (ptr,error) != OK) {
dn_free (dntop);
dn_free (dn);
entry_free (ptr);
GENERAL_HEAP;
return (DS_ERROR_REMOTE);
}
if ( ! check_oc_hierarchy(ptr->e_oc)) {
error->dse_type = DSE_UPDATEERROR;
error->ERR_UPDATE.DSE_up_problem = DSE_UP_OBJECTCLASSVIOLATION;
dn_free (dntop);
dn_free (dn);
entry_free (ptr);
GENERAL_HEAP;
return (DS_ERROR_REMOTE);
}
DLOG (log_dsap,LLOG_TRACE,("add - schema"));
if (check_schema (ptr,NULLATTR,error) != OK) {
dn_free (dntop);
dn_free (dn);
entry_free (ptr);
GENERAL_HEAP;
return (DS_ERROR_REMOTE);
}
GENERAL_HEAP;
dn_free (dn);
dn_free (dntop);
#ifdef TURBO_AVL
if ( (!ptr->e_leaf) && (!ptr->e_external) && (!ptr->e_children)) {
#else
if ( (!ptr->e_leaf) && (!ptr->e_external) && (!ptr->e_child)) {
#endif
AV_Sequence avs;
for (avs = ptr->e_master; avs != NULLAV; avs=avs->avseq_next)
if (dn_cmp ((DN)avs->avseq_av.av_struct, mydsadn) == 0) {
create_null_edb (ptr);
break;
}
if (avs == NULLAV)
ptr->e_allchildrenpresent = FALSE;
}
#ifdef TURBO_AVL
/* add the entry */
DATABASE_HEAP;
(void) avl_insert(&entryptr->e_children, (caddr_t) ptr, entry_cmp, avl_dup_error);
GENERAL_HEAP;
#endif
if (entryptr->e_leaf) {
#ifdef COMPAT_6_0
/* Turn leaf into non leaf, and add child */
/* Temporary until managemnet tools do it */
Attr_Sequence newas;
if (entryptr->e_data != E_DATA_MASTER) {
DN dn_found;
struct dn_seq * dn_stack = NULLDNSEQ;
int res;
dn_found = get_copy_dn (entryptr);
res = constructor_dsa_info(dn_found,dn_stack,TRUE,entryptr,error,di_p);
dn_free (dn_found);
entry_free (ptr);
switch (res) {
case DS_CONTINUE:
return(DS_CONTINUE);
case DS_X500_ERROR:
return(DS_CONTINUE);
default:
return(DS_ERROR_LOCAL);
}
/* NOTREACHED */
}
#ifndef TURBO_AVL
entryptr->e_child = ptr;
#endif
/* add master and slave attributes */
DATABASE_HEAP;
if ((entryptr->e_parent->e_slave == NULLAV) && (entryptr->e_parent->e_master == NULLAV)) {
extern char * mydsaname;
entryptr->e_master = str2avs (mydsaname,at_masterdsa);
newas = as_comp_new (AttrT_cpy(at_masterdsa),entryptr->e_master,NULLACL_INFO);
entryptr->e_attributes = as_merge (entryptr->e_attributes,newas);
} else {
if ((entryptr->e_master = avs_cpy(entryptr->e_parent->e_master)) != NULLAV) {
newas = as_comp_new (AttrT_cpy(at_masterdsa),entryptr->e_master,NULLACL_INFO);
entryptr->e_attributes = as_merge (entryptr->e_attributes,newas);
}
if ((entryptr->e_slave = avs_cpy (entryptr->e_parent->e_slave)) != NULLAV) {
newas = as_comp_new (AttrT_cpy(at_slavedsa),entryptr->e_slave,NULLACL_INFO);
entryptr->e_attributes = as_merge (entryptr->e_attributes,newas);
}
}
/* add new QuipuNonLeaf objectclass */
/* see if OC inherited */
if (as_find_type(entryptr->e_attributes,at_objectclass) == NULLATTR) {
/* OC inherited - pull down */
newas = as_comp_new (AttrT_cpy(at_objectclass),avs_cpy(entryptr->e_oc),NULLACL_INFO);
entryptr->e_attributes = as_merge (entryptr->e_attributes,newas);
}
newas = as_comp_new (AttrT_cpy(at_objectclass),str2avs(NONLEAFOBJECT,at_objectclass),NULLACL_INFO);
entryptr->e_attributes = as_merge (entryptr->e_attributes,newas);
if (entryptr->e_parent != NULLENTRY) {
if (entryptr->e_parent->e_edbversion)
free (entryptr->e_parent->e_edbversion);
entryptr->e_parent->e_edbversion = new_version();
}
if (entryptr->e_edbversion)
free (entryptr->e_edbversion);
entryptr->e_edbversion = new_version();
ptr->e_edbversion = new_version();
entryptr->e_allchildrenpresent = 2; /* Subtree ! */
modify_attr (entryptr,binddn);
if (unravel_attribute (entryptr,error) != OK)
fatal (-31,"serious schema error");
#ifdef TURBO_INDEX
turbo_add2index(ptr); /* add new entry to index */
turbo_add2index(entryptr); /* add parent to index */
#endif
#ifdef TURBO_DISK
/* write the new entry */
if (turbo_write(ptr) == NOTOK)
fatal(-32,"add turbo_write (2) failure - check database");
#else
if (journal (ptr) == NOTOK)
fatal (-32,"add journal (2) failure - check database");
#endif
entryptr->e_leaf = FALSE;
#ifdef TURBO_DISK
/* rewrite the parent as well */
if (turbo_write(entryptr) == NOTOK)
fatal(-31,"add parent turbo_write failed - check database");
#else
if (journal (entryptr) != OK)
fatal (-31,"add parent journal failed - check database");
#endif
GENERAL_HEAP;
local_master_size++;
return (OK);
#else /* COMPAT_6_0 */
/* Management tools will take care of the situation properly */
error->ERR_SERVICE.DSE_sv_problem = DSE_SV_UNWILLINGTOPERFORM;
return(DS_ERROR_REMOTE) ;
#endif /* COMPAT_6_0 */
#ifdef TURBO_AVL
}
#else
} else {
ptr->e_sibling = entryptr->e_child;
entryptr->e_child = ptr;
}
#endif
if (ptr->e_parent != NULLENTRY) {
if (ptr->e_parent->e_edbversion)
free (ptr->e_parent->e_edbversion);
ptr->e_parent->e_edbversion = new_version();
}
#ifdef TURBO_INDEX
turbo_add2index(ptr);
#endif
#ifdef TURBO_DISK
if (turbo_write(ptr) == NOTOK)
fatal(-32,"add turbo_write failure - check database");
#else
if (journal (ptr) == NOTOK)
fatal (-32,"add journal failure - check database");
#endif
local_master_size++;
return (DS_OK);
}