DataMuseum.dk

Presents historical artifacts from the history of:

DKUUG/EUUG Conference tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about DKUUG/EUUG Conference tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - metrics - download
Index: T d

⟦6324356dc⟧ TextFile

    Length: 16641 (0x4101)
    Types: TextFile
    Names: »ds_modify.c«

Derivation

└─⟦2d1937cfd⟧ Bits:30007241 EUUGD22: P.P 5.0
    └─⟦35176feda⟧ »EurOpenD22/isode/isode-6.tar.Z« 
        └─⟦de7628f85⟧ 
            └─⟦this⟧ »isode-6.0/quipu/ds_modify.c« 

TextFile

/* ds_modify.c - */

#ifndef lint
static char *rcsid = "$Header: /f/osi/quipu/RCS/ds_modify.c,v 7.1 89/12/19 16:20:16 mrose Exp $";
#endif

/*
 * $Header: /f/osi/quipu/RCS/ds_modify.c,v 7.1 89/12/19 16:20:16 mrose Exp $
 *
 *
 * $Log:	ds_modify.c,v $
 * 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/util.h"
#include "quipu/entry.h"
#include "quipu/modify.h"
#include "quipu/malloc.h"
#include "config.h"

static check_remove_values ();
static check_remove_type ();
extern Entry database_root;
extern LLog * log_dsap;
extern int encode_DAS_ModifyEntryArgumentData();

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 AttributeType at_control;
extern AttributeType at_acl;
extern int read_only;
char * new_version ();
Attr_Sequence as;

	DLOG (log_dsap,LLOG_TRACE,("ds_modifyentry"));

	if (!dsp)
		target = arg->mea_object;

	(void) dn_decode (target);

	/* stop aliases being dereferenced */
	arg->mea_common.ca_servicecontrol.svc_options |= SVC_OPT_DONTDEREFERENCEALIAS;

	/* check for control sequence */
	if (!dsp && (arg->mea_changes->em_type == EM_ADDATTRIBUTE)) {
		(void) as_decode (arg->mea_changes->em_what);
		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))
	{
	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,
			encode_DAS_ModifyEntryArgumentData,
			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;

	for (eptr = arg->mea_changes; eptr!=NULLMOD; eptr=eptr->em_next) {
		(void) as_decode (eptr->em_what);
		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,TRUE) != OK) {
		GENERAL_HEAP;
		entry_free (entryptr);
		return (DS_ERROR_REMOTE);
	} else if (check_schema (entryptr,NULLATTR,error,TRUE) == 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)) { 
			as = as_find_type (entryptr->e_attributes,at_acl);
			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);
			}
		}

		/* changes made OK, so add new entry into tree */
		if (entryptr->e_parent == NULLENTRY) {
			database_root = entryptr;
			entry_free (real_entry);
		} 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;
		}

		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 (journal (entryptr) != OK)
			fatal (-33,"modify rewrite failed - check database");

		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;
extern oid_table_attr * tab_acl;

	DLOG (log_dsap,LLOG_DEBUG,("remove attribute"));

	(void) AttrT_decode (at);
	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) {
		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);
	}

	if ( (real_as = as_find_type (real_entry->e_attributes,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);
	}

	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;
{
extern AttributeType at_objectclass;

	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;
extern AttributeType at_objectclass;

	/* 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"));

	for  (as=eptr->e_attributes; as!=NULLATTR; as=as->attr_link) {
		if ((AttrT_cmp (&as->attr_type,&rmas->attr_type)) == 0)
			break;
	}
	if (as == 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);
	}

	if ( (real_as = as_find_type (real_entry->e_attributes,&as->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);
	}

	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,&rmas->attr_value->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);
	   }
	   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 (as_find_type (eptr->e_attributes,&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;

	DLOG (log_dsap,LLOG_DEBUG,("add value"));

	if ( (as = as_find_type (real_entry->e_attributes,&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);
	}

	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);
		}
		
	DATABASE_HEAP;
	eptr->e_attributes = as_merge (as_cpy(newas),eptr->e_attributes);
	GENERAL_HEAP;

	return (OK);
}