Net2/usr/src/contrib/isode/dsap/common/attribute.c

/* attribute.c - */

#ifndef lint
static char *rcsid = "$Header: /f/osi/dsap/common/RCS/attribute.c,v 7.5 91/02/22 09:18:23 mrose Interim $";
#endif

/*
 * $Header: /f/osi/dsap/common/RCS/attribute.c,v 7.5 91/02/22 09:18:23 mrose Interim $
 *
 *
 * $Log:	attribute.c,v $
 * Revision 7.5  91/02/22  09:18:23  mrose
 * Interim 6.8
 * 
 * Revision 7.4  90/10/17  11:53:15  mrose
 * sync
 * 
 * Revision 7.3  90/04/18  08:49:44  mrose
 * 6.2
 * 
 * Revision 7.2  90/01/11  23:55:49  mrose
 * lint
 * 
 * Revision 7.1  90/01/11  18:37:17  mrose
 * real-sync
 * 
 * Revision 7.0  89/11/23  22:16:38  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/ds_error.h"
#include "quipu/oid.h"
#include "quipu/malloc.h"

AttributeType at_certificate;
AttributeType at_p_password;
AttributeType at_password;
AttributeType at_acl;
AttributeType at_control;
AttributeType at_schema;
AttributeType at_applctx;
AttributeType at_edbinfo;
AttributeType at_masterdsa;
AttributeType at_slavedsa;
AttributeType at_relaydsa;
AttributeType at_dsaaddress;
AttributeType at_version;
AttributeType at_inherit;
AttributeType at_subord;
AttributeType at_xref;
AttributeType at_nssr;
AttributeType at_listen;
OID alias_oc;
OID quipu_dsa_oid;
OID extern_obj_oid;

extern AttributeType at_objectclass;
extern AttributeType at_alias;
extern LLog * log_dsap;

extern short acl_sntx;

extern AV_Sequence oc_avs();
Attr_Sequence entry_find_type();

check_dsa_known_oids ()
{
	/* set pointers to special attributes */

	check_known_oids ();

	at_password 	= AttrT_new (PASSWORD_OID);
	at_control 	= AttrT_new (CONTROL_OID);
	at_acl 		= AttrT_new (ACL_OID);
	at_applctx 	= AttrT_new (APPLCTX_OID);
	at_schema 	= AttrT_new (SCHEMA_OID);
	at_edbinfo 	= AttrT_new (EDBINFO_OID);
	at_masterdsa 	= AttrT_new (MASTERDSA_OID);
	at_slavedsa 	= AttrT_new (SLAVEDSA_OID);
	at_relaydsa 	= AttrT_new (RELAYDSA_OID);
	at_dsaaddress 	= AttrT_new (DSAADDRESS_OID);
	at_version 	= AttrT_new (VERSION_OID);
	at_p_password 	= AttrT_new (PROTECTED_OID);
	at_certificate 	= AttrT_new (CERTIFICATE_OID);
	at_inherit 	= AttrT_new (INHERIT_OID);

	at_subord 	= AttrT_new (SUBORD_OID);
	at_xref 	= AttrT_new (XREF_OID);
	at_nssr 	= AttrT_new (NSSR_OID);
	at_listen 	= AttrT_new (LISTEN_OID);

	alias_oc = oid_cpy (str2oid (ALIAS_OC));
	quipu_dsa_oid = oid_cpy (str2oid(QUIPU_DSA));
	extern_obj_oid = oid_cpy (str2oid(EXTERNOBJECT));

}

real_unravel_attribute (eptr,error)
Entry eptr;
struct DSError * error;
{
register Attr_Sequence as;
Attr_Sequence ias;
RDN new_rdn, rdn_test;
AttributeType at;
AV_Sequence   avs;
struct acl * acl = (struct acl *) NULL;
extern oid_cmp ();
int rdn_print();

	/* take rdn's and make sure an attribute, if not add it in */
    for (new_rdn = eptr->e_name; new_rdn != NULLRDN; new_rdn = new_rdn->rdn_next) {
	if (new_rdn->rdn_at != NULLTABLE_ATTR)
		new_rdn->rdn_av.av_syntax = new_rdn->rdn_at->oa_syntax;

	if (new_rdn->rdn_av.av_syntax == 0) {
		/* Check we know about local RDNs syntax */
		if (eptr->e_data == E_DATA_MASTER) {
			LLOG (log_dsap, LLOG_EXCEPTIONS, ("RDN of unknown attribute type"));
			error->dse_type = DSE_UPDATEERROR;
			error->ERR_UPDATE.DSE_up_problem = DSE_UP_NAMINGVIOLATION;
			return NOTOK;
		}
	}

	for (rdn_test = eptr->e_name; rdn_test != new_rdn; rdn_test = rdn_test->rdn_next)
		/* check for repeated attribute in RDN */
		if (AttrT_cmp (new_rdn->rdn_at, rdn_test->rdn_at) == 0) {
			LLOG (log_dsap, LLOG_EXCEPTIONS, ("RDN with two AVAs of same attribute type"));
			error->dse_type = DSE_UPDATEERROR;
			error->ERR_UPDATE.DSE_up_problem = DSE_UP_NAMINGVIOLATION;
			return NOTOK;
		}
			
	if ((as = as_find_type (eptr->e_attributes,new_rdn->rdn_at)) == NULLATTR) {
		SET_HEAP (new_rdn->rdn_at);
		at  = AttrT_cpy (new_rdn->rdn_at);
		avs = avs_comp_new (AttrV_cpy(&new_rdn->rdn_av));
		as  = as_comp_new (at, avs, NULLACL_INFO);
		eptr->e_attributes = as_merge (eptr->e_attributes,as);
		RESTORE_HEAP;
	} else {
		for (avs=as->attr_value; avs!=NULLAV; avs=avs->avseq_next) 
			if (AttrV_cmp (&new_rdn->rdn_av,&avs->avseq_av) == 0)
				break;
		if (avs == NULLAV) {
			SET_HEAP (new_rdn->rdn_at);
			avs = avs_comp_new (AttrV_cpy(&new_rdn->rdn_av));
			as->attr_value = avs_merge (as->attr_value,avs);
			RESTORE_HEAP;
		}
	}
    }

	/* now get special attributes into structure */
	/* first reset pointers - incase deleted. */

	eptr->e_alias = NULLDN;
	eptr->e_dsainfo = NULLDSA;
	eptr->e_external = 0;
	eptr->e_master = NULLAV;
	eptr->e_slave = NULLAV;
	eptr->e_leaf = TRUE;
	eptr->e_oc = NULLAV;

	if ((as = entry_find_type (eptr,at_objectclass)) == NULLATTR) {
		/* Might inherit it ! */
		set_inheritance (eptr);
		if ((as = entry_find_type (eptr,at_objectclass)) == NULLATTR) {
			LLOG (log_dsap, LLOG_EXCEPTIONS, ("Object class attribute missing"));
			error->dse_type = DSE_UPDATEERROR;
			error->ERR_UPDATE.DSE_up_problem = DSE_UP_OBJECTCLASSVIOLATION;
			return (NOTOK);
		}
		eptr->e_oc = as->attr_value;
	} else {
		set_inheritance (eptr);
		eptr->e_oc = as->attr_value;
	/* order swapped ! */
	}

	if (as = entry_find_type (eptr,at_acl)) {
		eptr->e_acl = (struct acl *) as->attr_value->avseq_av.av_struct;
		acl = eptr->e_acl;
		if (acl->ac_child == NULLACL_INFO)
			acl->ac_child = acl_default ();
		if (acl->ac_entry == NULLACL_INFO)
			acl->ac_entry = acl_default ();
		if (acl->ac_default == NULLACL_INFO)
			acl->ac_default = acl_default ();
	}

	if (as = entry_find_type (eptr,at_edbinfo)) {
		if (eptr->e_dsainfo == NULLDSA) {
			eptr->e_dsainfo = (struct dsa_info *) smalloc (sizeof (struct dsa_info));
			bzero ((char *)eptr->e_dsainfo,sizeof (struct dsa_info));
		}
		eptr->e_dsainfo->dsa_attr = as->attr_value;
	}

	if (as = entry_find_type (eptr,at_dsaaddress)) {
		if (eptr->e_dsainfo == NULLDSA) {
			eptr->e_dsainfo = (struct dsa_info *) smalloc (sizeof (struct dsa_info));
			bzero ((char *)eptr->e_dsainfo,sizeof (struct dsa_info));
		}
		eptr->e_dsainfo->dsa_addr = (struct PSAPaddr *) as->attr_value->avseq_av.av_struct;
	}

	if (as = entry_find_type (eptr,at_masterdsa)) {
		eptr->e_master = as->attr_value;
		eptr->e_leaf = FALSE;
	}

	if (as = entry_find_type (eptr,at_slavedsa)) {
		eptr->e_slave = as->attr_value;
		eptr->e_leaf = FALSE;
	}

	if (as = entry_find_type (eptr,at_alias))
		eptr->e_alias = (DN) as->attr_value->avseq_av.av_struct;

	if (eptr->e_dsainfo != NULLDSA) /* set version number */
		if (as = entry_find_type (eptr,at_version))
			eptr->e_dsainfo->dsa_version = (char *) as->attr_value->avseq_av.av_struct;

	if (eptr->e_leaf) {
		/* still a leaf -> look for any external references */
		if (as = entry_find_type (eptr,at_xref)) {
			eptr->e_reference = as->attr_value;
			eptr->e_reftype = RT_CROSS;
			eptr->e_external = TRUE;
			eptr->e_leaf = FALSE;
			eptr->e_allchildrenpresent = FALSE;
			if (as->attr_value->avseq_next)
				pslog (log_dsap,LLOG_EXCEPTIONS,
				       "Multi valued cross reference",
				       rdn_print, (caddr_t)eptr->e_name);
		}
		if (as = entry_find_type (eptr,at_subord)) {
			if (eptr->e_external)
				pslog (log_dsap,LLOG_EXCEPTIONS,
				       "cross & subordinate reference",
				       rdn_print, (caddr_t)eptr->e_name);
			eptr->e_reference = as->attr_value;
			eptr->e_reftype = RT_SUBORDINATE;
			eptr->e_external = TRUE;
			eptr->e_leaf = FALSE;
			eptr->e_allchildrenpresent = FALSE;
			if (as->attr_value->avseq_next)
				pslog (log_dsap,LLOG_EXCEPTIONS,
				       "Multi valued subordinate reference",
				       rdn_print, (caddr_t)eptr->e_name);
		}
		if (as = entry_find_type (eptr,at_nssr)) {
			if (eptr->e_external)
				pslog (log_dsap,LLOG_EXCEPTIONS,
				       "NSSR & cross | subordinate reference",
				       rdn_print, (caddr_t)eptr->e_name);
			eptr->e_reference = as->attr_value;
			eptr->e_reftype = RT_NONSPECIFICSUBORDINATE;
			eptr->e_external = TRUE;
			eptr->e_leaf = FALSE;
			eptr->e_allchildrenpresent = FALSE;
		}
	}

	/* Make sure acl attribute exists */
	if (eptr->e_acl == (struct acl *) NULL) {
		Attr_Sequence as1;
		AV_Sequence avs1;
		AttributeValue av;

		SET_HEAP (at_acl);

		acl = acl_alloc();
		eptr->e_acl = acl;
		acl->ac_child = acl_default ();
		acl->ac_entry = acl_default ();
		acl->ac_default = acl_default ();
		acl->ac_attributes = NULLACL_ATTR;
		av = AttrV_alloc();
		av->av_syntax = acl_sntx;
		av->av_struct = (caddr_t) acl;
		avs1 = avs_comp_new (av);
		as1 = as_comp_new (AttrT_cpy(at_acl),avs1,NULLACL_INFO);
		eptr->e_attributes = as_merge(eptr->e_attributes,as1);

		RESTORE_HEAP;
	}

	/* now do the attribute acl */
	/* first of all create and oid_seq of all attribute, and point them to */
	/* the default.  */
	if (acl->ac_attributes == NULLACL_ATTR) {
		/* the easy case !!! - set every attribute to ac_default */
		for ( as = eptr->e_attributes; as != NULLATTR; as = as->attr_link) 
			as->attr_acl = acl->ac_default;
	} else {
		register struct acl_attr * aa;
		struct acl_attr * found_aa;
		register struct oid_seq * oidptr;
		char once;

		/* The following is probably in efficient */
		/* There must be a better way of setting these pointers */
		for ( as = eptr->e_attributes; as != NULLATTR; as = as->attr_link) {
			found_aa = NULLACL_ATTR;
			once = FALSE;

			for ( aa = acl->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(as->attr_type)) == 0) {
						if (once == TRUE)
							pslog (log_dsap,LLOG_EXCEPTIONS,
								"WARNING Inconsistent ACL in entry",
								rdn_print,
							        (caddr_t)eptr->e_name);
						else
							once = TRUE;
						found_aa = aa;
					}
				}
			}

			if (found_aa != NULLACL_ATTR) 
				/* found the apprioriate acl - add oid to it */
				as->attr_acl = found_aa->aa_acl;
			else
				as->attr_acl = acl->ac_default;
		}
	}

	if (ias = entry_find_type (eptr,at_inherit)) {
		/* set inherit ACL pointers */
		InheritAttr tmp;
		Attr_Sequence nas;

		eptr->e_inherit = avs_cpy (ias->attr_value);

		for (avs=eptr->e_inherit; avs!=NULLAV; avs=avs->avseq_next) {
			tmp = (InheritAttr) avs->avseq_av.av_struct;
			for (as = tmp->i_always; as != NULLATTR; as=as->attr_link) {
				if (  (AttrT_cmp (as->attr_type,at_acl) == 0)
				   || (AttrT_cmp (as->attr_type,at_masterdsa) == 0)
				   || (AttrT_cmp (as->attr_type,at_slavedsa) == 0)
				   || (AttrT_cmp (as->attr_type,at_relaydsa) == 0)
				   || (AttrT_cmp (as->attr_type,at_schema) == 0)
				   || (AttrT_cmp (as->attr_type,at_applctx) == 0)
				   || (AttrT_cmp (as->attr_type,at_objectclass) == 0)
				   || (AttrT_cmp (as->attr_type,at_edbinfo) == 0)
				   || (AttrT_cmp (as->attr_type,at_dsaaddress) == 0)
				   || (AttrT_cmp (as->attr_type,at_alias) == 0)
				   || (AttrT_cmp (as->attr_type,at_inherit) == 0)) {
					LLOG(log_dsap,LLOG_EXCEPTIONS,("Inherited system attribute only allowed in default case"));
					error->ERR_ATTRIBUTE.DSE_at_name = get_copy_dn (eptr);
					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;
					return (DS_ERROR_REMOTE);
				   }
				as->attr_acl = ias->attr_acl;
				if (as->attr_value == NULLAV) {
					if ((nas = entry_find_type (eptr,as->attr_type)) == NULLATTR) {
						LLOG(log_dsap,LLOG_EXCEPTIONS,("Value missing for always inherited attribute type"));
						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 (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;
						return (DS_ERROR_REMOTE);
					}
					as->attr_value = avs_cpy(nas->attr_value);
				}
			}
			for (as = tmp->i_default; as != NULLATTR; as=as->attr_link) {
				as->attr_acl = ias->attr_acl;
				if (as->attr_value == NULLAV) {
					if ((nas = entry_find_type (eptr,as->attr_type)) == NULLATTR) {
						LLOG(log_dsap,LLOG_EXCEPTIONS,("Value missing for default inherited attribute type"));
						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 (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;
						return (DS_ERROR_REMOTE);
					}
					as->attr_value = avs_cpy(nas->attr_value);
				}
			}
		}
	}

	return (OK);
}


set_inheritance (eptr)
Entry eptr;
{
AV_Sequence avs;
InheritAttr tmp;
Attr_Sequence as;

	if ((eptr == NULLENTRY)
		|| (eptr->e_parent == NULLENTRY)
		|| (eptr->e_parent->e_inherit == NULLAV))
		return;

	eptr->e_iattr = NULLINHERIT;

	if ((eptr->e_oc == NULLAV) &&
	   ((as = entry_find_type (eptr,at_objectclass)) != NULLATTR))
		eptr->e_oc = as->attr_value;

	if (eptr->e_oc == NULLAV)
		for (avs=eptr->e_parent->e_inherit; avs != NULLAV; avs=avs->avseq_next) {
			tmp = (InheritAttr) avs->avseq_av.av_struct;
			if (tmp->i_oid == NULLOID) {
				eptr->e_iattr = tmp;
				return;
			}
		}

	/* scan through inherit atribute looking of the right object class */
	for (avs=eptr->e_parent->e_inherit; avs != NULLAV; avs=avs->avseq_next) {
		tmp = (InheritAttr) avs->avseq_av.av_struct;
		if (check_in_oc (tmp->i_oid,eptr->e_oc)) {
			eptr->e_iattr = tmp;
			return;
		}
	}
	return;

}


Attr_Sequence entry_find_type (a,b)
Entry a;
AttributeType b;
{
register int i;
register Attr_Sequence ptr;

	/* if Attr_cmp returns <0 no point in continuing due to ordering */

	for(ptr = a->e_attributes; ptr != NULLATTR; ptr=ptr->attr_link) {
		if (  (i = AttrT_cmp (ptr->attr_type,b)) <= 0)
			if ( i == 0 )
				return ptr;
			else 
				break;
	}

	if (a->e_iattr == NULLINHERIT)
		return (NULLATTR);

	for(ptr = a->e_iattr->i_default; ptr != NULLATTR; ptr=ptr->attr_link) {
		if (  (i = AttrT_cmp (ptr->attr_type,b)) <= 0)
			if ( i == 0 )
				return ptr;
			else 
				break;
	}
	for(ptr = a->e_iattr->i_always; ptr != NULLATTR; ptr=ptr->attr_link) {
		if (  (i = AttrT_cmp (ptr->attr_type,b)) <= 0)
			return (i ? NULLATTR : ptr);
	}

	return (NULLATTR);
}