|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T d
Length: 34076 (0x851c) Types: TextFile Names: »ds_search.c«
└─⟦2d1937cfd⟧ Bits:30007241 EUUGD22: P.P 5.0 └─⟦35176feda⟧ »EurOpenD22/isode/isode-6.tar.Z« └─⟦de7628f85⟧ └─⟦this⟧ »isode-6.0/quipu/ds_search.c«
/* ds_search.c - DSA search of the directory */ #ifndef lint static char *rcsid = "$Header: /f/osi/quipu/RCS/ds_search.c,v 7.2 90/01/11 23:55:52 mrose Exp $"; #endif /* * $Header: /f/osi/quipu/RCS/ds_search.c,v 7.2 90/01/11 23:55:52 mrose Exp $ * * * $Log: ds_search.c,v $ * Revision 7.2 90/01/11 23:55:52 mrose * lint * * Revision 7.1 89/12/19 16:20:21 mrose * sync * * Revision 7.0 89/11/23 22:17:16 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/list.h" /* to get LSR # defs */ #include "quipu/ds_search.h" #include "config.h" extern int encode_DAS_SearchArgumentData(); extern LLog * log_dsap; #ifndef NO_STATS extern LLog * log_stat; extern int dn_print (); static PS filter_ps; #endif static EntryInfo *filterentry(); static EntryInfo *filterchildren(); static test_avs(); static apply_search(); static substr_search(); static aux_substr_search(); static check_filteritem_presrch (); static check_filter_presrch (); static check_filterop_presrch (); static check_filteritem (); static check_filter (); static check_filterop (); struct ds_search_task * st_done (); static search_refer (); static do_alias (); extern Entry database_root; static int size; static char qctx; extern int search_level; IFP approxfn(); IFP av_cmp_fn(); #ifndef NBBY #define NBBY 8 #endif static int big_size = 0; static int timelimit; extern time_t time(); Attr_Sequence eis_select (); do_ds_search (arg, error, result, dnbind, target, local, refer, di_p, dsp, quipu_ctx, tktime) register struct ds_search_arg *arg; struct ds_search_result *result; struct DSError *error; DN dnbind; DN target; struct ds_search_task ** local, ** refer; struct di_block ** di_p; char dsp; char quipu_ctx; time_t tktime; { extern int admin_size; extern time_t admin_time; int ismanager = FALSE; DN path; int retval; qctx = quipu_ctx; if ((timelimit = tktime) == (time_t) 0) { register int i; for (i = NBBY * sizeof timelimit - 1; i > 0; i--) timelimit <<= 1, timelimit |= 1; } if (!dsp) ismanager = manager (dnbind); if (ismanager && big_size == 0) { register int i; for (i = NBBY * sizeof big_size - 1; i > 0; i--) big_size <<= 1, big_size |= 1; } if (*local == NULL_ST) { DLOG (log_dsap,LLOG_TRACE,("ds_search")); if (!dsp) target = arg->sra_baseobject; /* Put local stuff straight into result structure (dangerous) */ result->srr_correlated = TRUE; result->srr_un.srr_unit = (struct ds_search_unit *) calloc(1, sizeof(struct ds_search_unit)); result->CSR_cr = NULLCONTINUATIONREF; (void) dn_decode (target); *local = st_alloc(); (*local)->st_baseobject = dn_cpy (target); (*local)->st_subset = arg->sra_subset; (*local)->st_alias = NULLDN; if (ismanager) { if (((*local)->st_size = arg->sra_common.ca_servicecontrol.svc_sizelimit) == SVC_NOSIZELIMIT) (*local)->st_size = big_size; } else if (((*local)->st_size = MIN(admin_size,arg->sra_common.ca_servicecontrol.svc_sizelimit)) == SVC_NOSIZELIMIT) (*local)->st_size = admin_size; (*local)->st_next = NULL_ST; result->CSR_entries = NULLENTRYINFO; #ifndef NO_STATS if ((filter_ps = ps_alloc(str_open)) == NULLPS) { st_comp_free (*local); *local = NULL_ST; return (DS_ERROR_LOCAL); } if (str_setup (filter_ps,NULLCP, BUFSIZ, 0) == NOTOK) { st_comp_free (*local); *local = NULL_ST; return (DS_ERROR_LOCAL); } #endif if (check_filter_presrch (arg->sra_filter,error,target) != OK) { #ifndef NO_STATS ps_free (filter_ps); #endif st_comp_free (*local); *local = NULL_ST; return (DS_ERROR_REMOTE); } else { Entry entryptr; #ifndef NO_STATS *filter_ps->ps_ptr = 0; switch (arg->sra_subset) { case SRA_ONELEVEL: LLOG (log_stat, LLOG_TRACE, ("Search onelevel %s",filter_ps->ps_base)); break; case SRA_WHOLESUBTREE: LLOG (log_stat, LLOG_TRACE, ("Search subtree %s",filter_ps->ps_base)); break; default: LLOG (log_stat, LLOG_TRACE, ("Search base %s",filter_ps->ps_base)); break; } ps_free (filter_ps); #endif if ((arg->sra_subset == SRA_ONELEVEL) || (quipu_ctx && (arg->sra_subset == SRA_WHOLESUBTREE))) { switch(find_child_entry((*local)->st_baseobject,&(arg->sra_common),dnbind,NULLDNSEQ,FALSE,&(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 ?? */ st_comp_free (*local); *local = NULL_ST; return(DS_CONTINUE); case DS_X500_ERROR: /* Filled out error - what do we do with it ?? */ st_comp_free (*local); *local = NULL_ST; return(DS_X500_ERROR); default: /* SCREAM */ LLOG(log_dsap, LLOG_EXCEPTIONS, ("do_ds_search() - find_child_entry failed 1")); st_comp_free (*local); *local = NULL_ST; return(DS_ERROR_LOCAL); } } else { if ((arg->sra_subset == SRA_BASEOBJECT) && ((*local)->st_baseobject == NULLDN)) { error->dse_type = DSE_NAMEERROR; error->ERR_NAME.DSE_na_problem = DSE_NA_NOSUCHOBJECT; error->ERR_NAME.DSE_na_matched = NULLDN; st_comp_free (*local); *local = NULL_ST; return (DS_ERROR_REMOTE); } switch(find_entry((*local)->st_baseobject,&(arg->sra_common),dnbind,NULLDNSEQ,FALSE,&(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 ?? */ st_comp_free (*local); *local = NULL_ST; return(DS_CONTINUE); case DS_X500_ERROR: /* Filled out error - what do we do with it ?? */ st_comp_free (*local); *local = NULL_ST; return(DS_X500_ERROR); default: /* SCREAM */ LLOG(log_dsap, LLOG_EXCEPTIONS, ("do_ds_search() - find_entry failed 1")); st_comp_free (*local); *local = NULL_ST; return(DS_ERROR_LOCAL); } } /* if no error and NOT SVC_OPT_DONTDEREFERENCEALIASES then */ /* the alias will have been derefeferenced -signified by */ /* NO_ERROR !!! */ if (error->dse_type == DSE_NOERROR) { result->CSR_object = NULLDN; result->CSR_common.cr_aliasdereferenced = FALSE; } else { result->CSR_common.cr_aliasdereferenced = TRUE; result->CSR_object = get_copy_dn (entryptr); } /* Strong authentication */ if ((retval = check_security_parms((caddr_t) arg, encode_DAS_SearchArgumentData, arg->sra_common.ca_security, arg->sra_common.ca_sig, &dnbind)) != 0) { error->dse_type = DSE_SECURITYERROR; error->ERR_SECURITY.DSE_sc_problem = retval; st_comp_free (*local); *local = NULL_ST; return (DS_ERROR_REMOTE); } /* one final check - will we allow such searched in this DSA ? */ if (arg->sra_subset == SRA_WHOLESUBTREE) { DN dn; int x = 0; for (dn = (*local)->st_baseobject; dn!= NULLDN; dn=dn->dn_parent, x++) ; if ( x < search_level ) { if ( ! ismanager ) { /* Too high */ error->dse_type = DSE_SERVICEERROR; error->ERR_SERVICE.DSE_sv_problem = DSE_SV_UNWILLINGTOPERFORM; st_comp_free (*local); *local = NULL_ST; return (DS_ERROR_REMOTE); } } if ((!quipu_ctx) && ((*local)->st_baseobject != NULLDN)) { /* search base object */ if ((*local)->st_alias == NULLDN) path = (*local)->st_baseobject; else path = (*local)->st_alias; if ((result->CSR_entries = filterentry (arg,entryptr,path)) != NULLENTRYINFO) (*local)->st_size--; } } result->CSR_limitproblem = LSR_NOLIMITPROBLEM; return (DS_SUSPEND); /* yup - we will take the search on */ } } else { DLOG (log_dsap,LLOG_TRACE,("ds_search continuing")); size = (*local)->st_size; if ((*local)->st_alias == NULLDN) path = (*local)->st_baseobject; else path = (*local)->st_alias; if ((apply_search (arg,error,result,local,refer,ismanager,path)) == NOTOK) { st_free (local); st_free (refer); return (DS_ERROR_REMOTE); } if (size < 0) { st_free (local); st_free (refer); result -> CSR_limitproblem = arg -> sra_common.ca_servicecontrol.svc_sizelimit == SVC_NOSIZELIMIT || arg -> sra_common.ca_servicecontrol.svc_sizelimit > admin_size ? LSR_ADMINSIZEEXCEEDED : LSR_SIZELIMITEXCEEDED; /* should fill out a POQ */ return (DS_OK); } if (timelimit <= time ((time_t *)0)) { st_free (local); st_free (refer); result -> CSR_limitproblem = arg -> sra_common.ca_servicecontrol.svc_timelimit == SVC_NOTIMELIMIT || arg -> sra_common.ca_servicecontrol.svc_timelimit > admin_time ? LSR_ADMINSIZEEXCEEDED : LSR_TIMELIMITEXCEEDED; /* should fill out a POQ */ return (DS_OK); } if ((*local)->st_next == NULL_ST) { st_free (local); result->CSR_limitproblem = LSR_NOLIMITPROBLEM; (void) dsa_search_control(arg,result); return (DS_OK); } (*local) = st_done(local); (*local)->st_size = size; return (DS_SUSPEND); } } /* * SEARCH TASK HANDLING */ st_comp_free (st) struct ds_search_task *st; { dn_free (st->st_baseobject); dn_free (st->st_alias); free ((char *)st); } st_free (st) struct ds_search_task **st; { struct ds_search_task *next; for (; (*st) != NULL_ST; (*st) = next) { next = (*st)->st_next; st_comp_free (*st); } } struct ds_search_task * st_done (st) struct ds_search_task **st; { struct ds_search_task *next; next = (*st)->st_next; st_comp_free (*st); return (next); } /* * CHECK FILTER BEFORE SEARCHING */ static check_filter_presrch (fltr,error,dn) register Filter fltr; struct DSError *error; DN dn; { DLOG (log_dsap,LLOG_DEBUG,("in check filter aux")); switch (fltr->flt_type) { case FILTER_ITEM: return (check_filteritem_presrch (&fltr->FUITEM,error,dn)); case FILTER_AND: #ifndef NO_STATS ps_print (filter_ps,"& "); #endif return(check_filterop_presrch (fltr->FUFILT,error,dn)); case FILTER_OR: #ifndef NO_STATS ps_print (filter_ps,"| "); #endif return(check_filterop_presrch (fltr->FUFILT,error,dn)); case FILTER_NOT: #ifndef NO_STATS ps_print (filter_ps,"! "); #endif return(check_filter_presrch (fltr->FUFILT,error,dn)); default: LLOG (log_dsap,LLOG_EXCEPTIONS,("check_filter protocol error")); error->dse_type = DSE_SERVICEERROR; error->ERR_SERVICE.DSE_sv_problem = DSE_SV_UNAVAILABLE; return (NOTOK); } /* NOTREACHED */ } static check_filterop_presrch (fltr,error,dn) register Filter fltr; struct DSError * error; DN dn; { register Filter ptr; int i; #ifndef NO_STATS ps_print (filter_ps,"("); #endif DLOG (log_dsap,LLOG_DEBUG,("in filter op aux")); for (ptr=fltr; ptr!=NULLFILTER ; ptr=ptr->flt_next) { i = check_filter_presrch (ptr,error,dn); if (i != OK) return (NOTOK); } #ifndef NO_STATS ps_print (filter_ps,")"); #endif return (OK); } static check_filteritem_presrch (fitem,error,dn) register struct filter_item *fitem; struct DSError * error; DN dn; { int av_acl, av_update, av_schema, av_syntax; extern char chrcnv[]; extern char nochrcnv[]; DLOG (log_dsap,LLOG_DEBUG,("search: check filter item aux")); if (fitem == NULLFITEM) { LLOG (log_dsap,LLOG_EXCEPTIONS,("check_filter_item protocol error (1)")); error->dse_type = DSE_SERVICEERROR; error->ERR_SERVICE.DSE_sv_problem = DSE_SV_UNAVAILABLE; return (NOTOK); } switch ( fitem->fi_type) { case FILTERITEM_APPROX: if (ava_decode (&fitem->UNAVA) == NOTOK) { error->dse_type = DSE_ATTRIBUTEERROR; error->ERR_ATTRIBUTE.DSE_at_name = NULLDN; error->ERR_ATTRIBUTE.DSE_at_plist.DSE_at_what = DSE_AT_INVALIDATTRIBUTESYNTAX; error->ERR_ATTRIBUTE.DSE_at_plist.DSE_at_type = AttrT_cpy(fitem->UNAVA.ava_type); error->ERR_ATTRIBUTE.DSE_at_plist.DSE_at_value = AttrV_cpy(fitem->UNAVA.ava_value); error->ERR_ATTRIBUTE.DSE_at_plist.dse_at_next = DSE_AT_NOPROBLEM; return (NOTOK); } if (fitem->UNAVA.ava_type->at_table == NULLTABLE_ATTR) return (invalid_matching (fitem->UNAVA.ava_type,error,dn)); if ( (fitem->fi_ifp = approxfn (fitem->UNAVA.ava_type->at_table->oa_syntax)) == NULLIFP) /* approx not suported for this type */ /* so set it to equality */ fitem->fi_type = FILTERITEM_EQUALITY; /* NO break - check equality is OK */ case FILTERITEM_EQUALITY: case FILTERITEM_GREATEROREQUAL: case FILTERITEM_LESSOREQUAL: if (ava_decode (&fitem->UNAVA) == NOTOK) { error->dse_type = DSE_ATTRIBUTEERROR; error->ERR_ATTRIBUTE.DSE_at_name = NULLDN; error->ERR_ATTRIBUTE.DSE_at_plist.DSE_at_what = DSE_AT_INVALIDATTRIBUTESYNTAX; error->ERR_ATTRIBUTE.DSE_at_plist.DSE_at_type = AttrT_cpy(fitem->UNAVA.ava_type); error->ERR_ATTRIBUTE.DSE_at_plist.DSE_at_value = AttrV_cpy(fitem->UNAVA.ava_value); error->ERR_ATTRIBUTE.DSE_at_plist.dse_at_next = DSE_AT_NOPROBLEM; return (NOTOK); } if (fitem->UNAVA.ava_type->at_table == NULLTABLE_ATTR) return (invalid_matching (fitem->UNAVA.ava_type,error,dn)); if (fitem->fi_type != FILTERITEM_APPROX) if ( (fitem->fi_ifp = av_cmp_fn (fitem->UNAVA.ava_type->at_table->oa_syntax)) == NULLIFP) return (invalid_matching (fitem->UNAVA.ava_type,error,dn)); av_acl = str2syntax ("acl"); av_schema = str2syntax ("schema"); av_update = str2syntax ("edbinfo"); av_syntax = fitem->UNAVA.ava_type->at_table->oa_syntax; if (( av_syntax == av_acl ) || (av_syntax == av_schema) || (av_syntax == av_update)) return (invalid_matching (fitem->UNAVA.ava_type,error,dn)); break; case FILTERITEM_SUBSTRINGS: if (avs_decode (fitem->UNSUB.fi_sub_type, fitem->UNSUB.fi_sub_initial) == NOTOK) { error->dse_type = DSE_ATTRIBUTEERROR; error->ERR_ATTRIBUTE.DSE_at_name = NULLDN; error->ERR_ATTRIBUTE.DSE_at_plist.DSE_at_what = DSE_AT_INVALIDATTRIBUTESYNTAX; error->ERR_ATTRIBUTE.DSE_at_plist.DSE_at_type = AttrT_cpy(fitem->UNSUB.fi_sub_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 (avs_decode (fitem->UNSUB.fi_sub_type, fitem->UNSUB.fi_sub_any) == NOTOK) { error->dse_type = DSE_ATTRIBUTEERROR; error->ERR_ATTRIBUTE.DSE_at_name = NULLDN; error->ERR_ATTRIBUTE.DSE_at_plist.DSE_at_what = DSE_AT_INVALIDATTRIBUTESYNTAX; error->ERR_ATTRIBUTE.DSE_at_plist.DSE_at_type = AttrT_cpy(fitem->UNSUB.fi_sub_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 (avs_decode (fitem->UNSUB.fi_sub_type, fitem->UNSUB.fi_sub_final) == NOTOK) { error->dse_type = DSE_ATTRIBUTEERROR; error->ERR_ATTRIBUTE.DSE_at_name = NULLDN; error->ERR_ATTRIBUTE.DSE_at_plist.DSE_at_what = DSE_AT_INVALIDATTRIBUTESYNTAX; error->ERR_ATTRIBUTE.DSE_at_plist.DSE_at_type = AttrT_cpy(fitem->UNSUB.fi_sub_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 (fitem->UNSUB.fi_sub_type->at_table == NULLTABLE_ATTR) return (invalid_matching (fitem->UNSUB.fi_sub_type,error,dn)); av_syntax = fitem->UNSUB.fi_sub_type->at_table->oa_syntax; if (! sub_string(av_syntax)) return (invalid_matching (fitem->UNSUB.fi_sub_type,error,dn)); if ( case_exact_match (av_syntax) ) fitem->UNSUB.fi_sub_match = &nochrcnv[0]; else fitem->UNSUB.fi_sub_match = &chrcnv[0]; case FILTERITEM_PRESENT: break; default: LLOG (log_dsap,LLOG_EXCEPTIONS,("check_filter_item protocol error (2)")); error->dse_type = DSE_SERVICEERROR; error->ERR_SERVICE.DSE_sv_problem = DSE_SV_UNAVAILABLE; return (NOTOK); } #ifndef NO_STATS ps_print (filter_ps,"("); switch ( fitem->fi_type) { case FILTERITEM_APPROX: AttrT_print (filter_ps,fitem->UNAVA.ava_type,EDBOUT); ps_print (filter_ps,"~="); AttrV_print (filter_ps,fitem->UNAVA.ava_value,EDBOUT); break; case FILTERITEM_EQUALITY: AttrT_print (filter_ps,fitem->UNAVA.ava_type,EDBOUT); ps_print (filter_ps,"="); AttrV_print (filter_ps,fitem->UNAVA.ava_value,EDBOUT); break; case FILTERITEM_GREATEROREQUAL: AttrT_print (filter_ps,fitem->UNAVA.ava_type,EDBOUT); ps_print (filter_ps,">="); AttrV_print (filter_ps,fitem->UNAVA.ava_value,EDBOUT); break; case FILTERITEM_LESSOREQUAL: AttrT_print (filter_ps,fitem->UNAVA.ava_type,EDBOUT); ps_print (filter_ps,"<="); AttrV_print (filter_ps,fitem->UNAVA.ava_value,EDBOUT); break; case FILTERITEM_SUBSTRINGS: AttrT_print (filter_ps,fitem->UNSUB.fi_sub_type,EDBOUT); ps_print (filter_ps,"="); avs_print_aux (filter_ps,fitem->UNSUB.fi_sub_initial,EDBOUT,"*"); ps_print (filter_ps,"*"); avs_print_aux (filter_ps,fitem->UNSUB.fi_sub_any,EDBOUT,"*"); ps_print (filter_ps,"*"); avs_print_aux (filter_ps,fitem->UNSUB.fi_sub_final,EDBOUT,"*"); break; case FILTERITEM_PRESENT: AttrT_print (filter_ps,fitem->UNTYPE,EDBOUT); ps_print (filter_ps,"=*"); break; } ps_print (filter_ps,")"); #endif return (OK); } /* APPLY SEARCH TO ONE LEVEL */ static apply_search (arg,error,result,local,refer,ismanager,path) struct ds_search_arg *arg; struct DSError *error; struct ds_search_result *result; struct ds_search_task **local, **refer; int ismanager; DN path; { Entry entryptr; EntryInfo *einfo = NULLENTRYINFO; struct di_block * di_tmp; if ((*local)->st_subset == SRA_BASEOBJECT) { if ((*local)->st_baseobject == NULLDN) { LLOG (log_dsap,LLOG_NOTICE,("NULL Base in search ignored")); /* to stop poisoning... */ return (DS_OK); } switch(find_entry((*local)->st_baseobject,&(arg->sra_common),NULLDN,NULLDNSEQ,FALSE,&(entryptr), error, &(di_tmp))) { case DS_OK: /* Filled out entryptr - carry on */ break; case DS_CONTINUE: /* Filled out di_p - what do we do with it ?? */ subtask_refer(arg, local, refer, ismanager, di_tmp); return(DS_OK); case DS_X500_ERROR: /* Filled out error - what do we do with it ?? */ /* The only problem can be alias error etc */ /* to stop poisoning return OK */ log_ds_error (error); ds_error_free (error); return (DS_OK); default: /* SCREAM */ LLOG(log_dsap, LLOG_EXCEPTIONS, ("do_ds_search() - find_entry failed 2")); return(DS_ERROR_LOCAL); } } else { switch(find_child_entry((*local)->st_baseobject,&(arg->sra_common),NULLDN,NULLDNSEQ,FALSE,&(entryptr), error, &(di_tmp))) { case DS_OK: /* Filled out entryptr - carry on */ break; case DS_CONTINUE: /* Filled out di_p - what do we do with it ?? */ subtask_refer(arg, local, refer, ismanager, di_tmp); return(DS_OK); case DS_X500_ERROR: /* Filled out error - what do we do with it ?? */ /* The only problem can be alias error etc */ /* to stop poisoning return OK */ log_ds_error (error); return (DS_OK); default: /* SCREAM */ LLOG(log_dsap, LLOG_EXCEPTIONS, ("do_ds_search() - find_child_entry failed 2")); return(DS_ERROR_LOCAL); } } switch ((*local)->st_subset) { case SRA_BASEOBJECT: einfo = filterentry (arg,entryptr,path); break; case SRA_ONELEVEL: case SRA_WHOLESUBTREE: einfo = filterchildren (arg,entryptr,local,refer,(*local)->st_subset,ismanager,path); break; default: LLOG (log_dsap,LLOG_EXCEPTIONS,("search protocol error")); error->dse_type = DSE_SERVICEERROR; error->ERR_SERVICE.DSE_sv_problem = DSE_SV_UNAVAILABLE; return (DS_X500_ERROR); } if (einfo != NULLENTRYINFO) if (result->CSR_entries == NULLENTRYINFO) result->CSR_entries = einfo; else entryinfo_append (result->CSR_entries,einfo); result->CSR_common.cr_requestor = NULLDN; return (DS_OK); } /* * SEARCH CHILDREN */ static EntryInfo * filterchildren (arg,entryptr,local,refer,extent, ismanager,path) struct ds_search_arg *arg; Entry entryptr; struct ds_search_task **local, **refer; int extent; int ismanager; DN path; { register EntryInfo *einfo = NULLENTRYINFO; register EntryInfo *eptr = NULLENTRYINFO; register Entry ptr; DN dnend, dnsave; RDN freeend; struct ds_search_task * new_task; DLOG (log_dsap,LLOG_DEBUG,("search: filter children")); if (entryptr == NULLENTRY) return (NULLENTRYINFO); if (entryptr->e_leaf) return (NULLENTRYINFO); if (check_acl (NULLDN, ACL_READ, entryptr->e_acl->ac_child, (*local)->st_baseobject) == NOTOK) { return (NULLENTRYINFO); } if (( ptr=entryptr->e_child ) == NULLENTRY) { search_refer (arg,entryptr,local,refer,ismanager); return (NULLENTRYINFO); } if (path == NULLDN) { path = dn_comp_new(rdn_cpy(entryptr->e_child->e_name)); freeend = path->dn_rdn; dnend = path; } else { for (dnend=path; dnend->dn_parent != NULLDN; dnend=dnend->dn_parent) ; /* NULL */ dnend->dn_parent = dn_comp_new(rdn_cpy(entryptr->e_child->e_name)); freeend = dnend->dn_parent->dn_rdn; dnsave = dnend; dnend = dnend ->dn_parent; } for (; (ptr != NULLENTRY) && (size >= 0) ; ptr=ptr->e_sibling) { dnend->dn_rdn = ptr->e_name; if ((ptr->e_alias != NULLDN) && (do_alias (arg,ptr,local) == OK)) continue; eptr = filterentry (arg,ptr,path); if ((eptr != NULLENTRYINFO) && (size != -1)) if (einfo == NULLENTRYINFO) einfo = eptr; else entryinfo_append (einfo,eptr); if ( (extent == SRA_WHOLESUBTREE) && (!ptr->e_leaf)) { if (check_acl (NULLDN, ACL_READ, ptr->e_acl->ac_child, path) == OK) { if (((ptr->e_child != NULLENTRY) && (ptr->e_allchildrenpresent == FALSE)) || (ptr->e_child == NULLENTRY)) search_refer (arg,ptr,local,refer,ismanager); else { new_task = st_alloc(); new_task->st_baseobject = dn_cpy(path); new_task->st_size = 0; /* fill in later */ new_task->st_alias = NULLDN; new_task->st_subset = SRA_WHOLESUBTREE; new_task->st_next = (*local)->st_next; (*local)->st_next = new_task; } } } if (timelimit <= time ((time_t *)0)) break; } if (path->dn_parent == NULLDN) { path->dn_rdn = NULLRDN; dn_free (path); path = NULLDN; } else { dnend->dn_rdn = NULLRDN; dn_free (dnend); dnsave->dn_parent = NULLDN; } rdn_free (freeend); return (einfo); } /* * HANDLE ALIASES AND REFERRALS */ static do_alias (arg,eptr,local) struct ds_search_arg *arg; Entry eptr; struct ds_search_task **local; { struct ds_search_task *new_task; if ( ! arg->sra_searchaliases) return NOTOK; DLOG (log_dsap,LLOG_DEBUG,("alias in search path")); new_task = st_alloc(); new_task->st_baseobject = dn_cpy(eptr->e_alias); new_task->st_size = 0; /* fill in later */ new_task->st_alias = get_copy_dn (eptr); switch ((*local)->st_subset) { case SRA_ONELEVEL: case SRA_BASEOBJECT: new_task->st_subset = SRA_BASEOBJECT; break; case SRA_WHOLESUBTREE: new_task->st_subset = SRA_WHOLESUBTREE; break; } new_task->st_next = (*local)->st_next; (*local)->st_next = new_task; return (OK); } static search_refer(arg,entryptr,local,refer,ismanager) struct ds_search_arg *arg; Entry entryptr; struct ds_search_task **local, **refer; int ismanager; { struct ds_search_task * new_task; struct DSError error; struct di_block * di_tmp; DN name; name = get_copy_dn (entryptr); switch(dsa_info_new(name, NULLDNSEQ, FALSE, entryptr, &(error), &(di_tmp))) { case DS_OK: /* A di_block ready for use */ break; case DS_CONTINUE: /* A deferred di_block */ break; case DS_X500_ERROR: /* An error */ LLOG(log_dsap, LLOG_EXCEPTIONS, ("search_refer - dsa_info_new() generated x500 error")); log_ds_error(&(error)); ds_error_free(&(error)); return; default: /* A local error - scream */ LLOG(log_dsap, LLOG_EXCEPTIONS, ("search_refer - dsa_info_new() failed")); return; } DLOG (log_dsap,LLOG_DEBUG,("referral in search path")); new_task = st_alloc(); new_task->st_baseobject = name; new_task->st_subset = (*local)->st_subset; new_task->st_alias = NULLDN; if (ismanager) { if ((new_task->st_size = arg->sra_common.ca_servicecontrol.svc_sizelimit) == SVC_NOSIZELIMIT) new_task->st_size = big_size; } else if ((new_task->st_size = MIN(admin_size,arg->sra_common.ca_servicecontrol.svc_sizelimit)) == SVC_NOSIZELIMIT) new_task->st_size = admin_size; new_task->st_di = di_tmp; new_task->st_next = *refer; *refer = new_task; } /* * SEARCH ENTRY */ static EntryInfo * filterentry (arg,entryptr,path) struct ds_search_arg *arg; register Entry entryptr; DN path; { register EntryInfo * einfo; DLOG (log_dsap,LLOG_DEBUG,("search: filter entry")); if (check_filter (arg->sra_filter,entryptr,path) != OK ) { DLOG (log_dsap,LLOG_DEBUG,("none found")); return (NULLENTRYINFO); } einfo = entryinfo_alloc (); einfo->ent_dn = dn_cpy (path); if (check_acl (NULLDN, ACL_READ, entryptr->e_acl->ac_entry, path) == NOTOK) return (NULLENTRYINFO); einfo->ent_attr = eis_select (arg->sra_eis, entryptr, NULLDN, qctx && arg->sra_eis.eis_allattributes); einfo->ent_iscopy = entryptr->e_data; einfo->ent_age = (time_t) 0; einfo->ent_next = NULLENTRYINFO; size--; return (einfo); } /* * TEST FILTER AGAINST SINGLE ENTRY */ static check_filter (fltr,entryptr,path) register Filter fltr; register Entry entryptr; DN path; { register int i; DLOG (log_dsap,LLOG_DEBUG,("in check filter")); switch (fltr->flt_type) { case FILTER_ITEM: return (check_filteritem (&fltr->FUITEM,entryptr,path)); case FILTER_AND: case FILTER_OR: return(check_filterop (fltr->FUFILT,entryptr,fltr->flt_type,path)); case FILTER_NOT: if ((i=check_filter (fltr->FUFILT,entryptr,path)) == OK) return NOTOK; else if ( i == NOTOK ) return OK; else return i; } /* NOTREACHED */ } static check_filterop (fltr,entryptr,op,path) register Filter fltr; register Entry entryptr; int op; DN path; { register Filter ptr; int result; DLOG (log_dsap,LLOG_DEBUG,("in filter op")); /* effect of applying logical operator to zero operands */ if (op == FILTER_OR) result = NOTOK; else result = OK; for (ptr=fltr; ptr!=NULLFILTER ; ptr=ptr->flt_next) switch (check_filter (ptr,entryptr,path)) { case MAYBE: /* Beware of 'Pathological NOT' here. * To comply with the December '88 X.500, should just drop through here. * For the security to work properly, also set result to MAYBE. */ result = MAYBE; break; case OK: if (op == FILTER_OR) { DLOG (log_dsap,LLOG_DEBUG,("or ok")); return (OK); } break; case NOTOK: if (op == FILTER_AND) { DLOG (log_dsap,LLOG_DEBUG,("and not")); return (NOTOK); } break; case -2: default: return (-2); } return (result); } /* * CHECK FILTER ITEM AGAINST ENTRY */ static check_filteritem (fitem,entryptr,path) register struct filter_item *fitem; register Entry entryptr; DN path; { register Attr_Sequence as; AttributeType at; DLOG (log_dsap,LLOG_DEBUG,("search: check filter item")); switch ( fitem->fi_type) { case FILTERITEM_APPROX: case FILTERITEM_EQUALITY: case FILTERITEM_GREATEROREQUAL: case FILTERITEM_LESSOREQUAL: at = fitem->UNAVA.ava_type; break; case FILTERITEM_SUBSTRINGS: at = fitem->UNSUB.fi_sub_type; break; case FILTERITEM_PRESENT: if ((as = as_find_type (entryptr->e_attributes, fitem->UNTYPE)) == NULLATTR) return NOTOK; else return OK; } if ((as = as_find_type (entryptr->e_attributes, at)) == NULLATTR) return MAYBE; if ( check_acl (NULLDN,ACL_COMPARE,as->attr_acl,path) != OK) return MAYBE; switch ( fitem->fi_type) { case FILTERITEM_SUBSTRINGS: return (substr_search (fitem,as->attr_value)); case FILTERITEM_APPROX: return ((int)(*fitem->fi_ifp)(fitem,as->attr_value)); default: return (test_avs (fitem,as->attr_value,fitem->fi_type)); } /* NOTREACHED */ } static test_avs (fitem,avs,mode) register struct filter_item *fitem; register AV_Sequence avs; register int mode; { for (; avs != NULLAV; avs=avs->avseq_next) { switch (((int)(*fitem->fi_ifp)(avs->avseq_av.av_struct, fitem->UNAVA.ava_value->av_struct))) { case 0: return (OK); case 1: if (mode == FILTERITEM_GREATEROREQUAL) return (OK); break; case -1: if (mode == FILTERITEM_LESSOREQUAL) return (OK); break; case 2: return (NOTOK); default: return (MAYBE); } } return (NOTOK); } /* * SUBSTRING MATCH */ static substr_search (fitem,avs) register struct filter_item *fitem; register AV_Sequence avs; { for (; avs != NULLAV; avs=avs->avseq_next) if (aux_substr_search (fitem,avs,fitem->UNSUB.fi_sub_match) == OK) return (OK); return (NOTOK); } static aux_substr_search (fitem,avs,chrmatch) struct filter_item *fitem; AV_Sequence avs; char chrmatch []; { register AV_Sequence loopavs; register char * compstr; char * top; register char * temp; char * temp2; int offset; compstr = (char *)avs->avseq_av.av_struct; top = compstr; if (fitem->UNSUB.fi_sub_initial != NULLAV) { temp = (char *)fitem->UNSUB.fi_sub_initial->avseq_av.av_struct; do if (chrmatch[*compstr++] != chrmatch[*temp++]) { DLOG (log_dsap,LLOG_DEBUG,("initial failure (%s, %s)",top,(char *)fitem->UNSUB.fi_sub_initial->avseq_av.av_struct)); return (NOTOK); } while (*temp != '\0') ; } for (loopavs=fitem->UNSUB.fi_sub_any; loopavs!=NULLAV; loopavs=loopavs->avseq_next, compstr += offset) if ((offset= attr_substr (compstr, &loopavs->avseq_av,chrmatch)) == -1) { DLOG (log_dsap,LLOG_DEBUG,("any failure (%s, %s)",top,(char *)loopavs->avseq_av.av_struct)); return (NOTOK); } if (fitem->UNSUB.fi_sub_final != NULLAV) { temp = (char *)fitem->UNSUB.fi_sub_final->avseq_av.av_struct; temp2 = temp; while (*++compstr != '\0') ; /* NO-OP*/ while (*temp++ != '\0') compstr--; if (compstr < top) { DLOG (log_dsap,LLOG_DEBUG,("final too long failure (%s,%s)",top,temp2)); return (NOTOK); } temp = temp2; while (*compstr != '\0') if (chrmatch[*compstr++] != chrmatch[*temp++]) { /* free (top); */ DLOG (log_dsap,LLOG_DEBUG,("final failure (%s, %s)",top,temp2)); return (NOTOK); } } return (OK); } attr_substr (str1,av,chrmatch) register char * str1; AttributeValue av; char chrmatch[]; { register char * str2; register int count; char * top; int found = 0; int slen; top = str1; str2 = (char *)av->av_struct; while (*str1 != '\0') { if (chrmatch[*str1++] == chrmatch[*str2]) { str2++; found = 1; break; } } if ( found == 0 ) return (-1); slen = strlen (str2) + 1; for (count = 1; count < slen ; count ++) { if (*str1 == '\0') return (-1); if (chrmatch[*str1++] != chrmatch[*str2++]) { /* not found here, but may still be in the string !! */ str1 -= count; str2 -= count + 1; while (*str1 != '\0') { if (chrmatch[*str1++] == chrmatch[*str2]) { str2++; break; } } count = 0; /* for loop ++ will make it 1 !!! */ } } return (str1 - top); } subtask_refer(arg, local, refer, ismanager, di) struct ds_search_arg *arg; struct ds_search_task **local, **refer; int ismanager; struct di_block * di; { /* turn query into a referral */ struct ds_search_task * new_task; new_task = st_alloc(); new_task->st_baseobject = dn_cpy ((*local)->st_baseobject); new_task->st_subset = (*local)->st_subset; new_task->st_alias = dn_cpy ((*local)->st_alias); if (ismanager) { if ((new_task->st_size = arg->sra_common.ca_servicecontrol.svc_sizelimit) == SVC_NOSIZELIMIT) new_task->st_size = big_size; } else if ((new_task->st_size = MIN(admin_size,arg->sra_common.ca_servicecontrol.svc_sizelimit)) == SVC_NOSIZELIMIT) new_task->st_size = admin_size; new_task->st_di = di; new_task->st_next = *refer; *refer = new_task; } dsa_search_control (arg,result) struct ds_search_arg *arg; struct ds_search_result *result; { extern DN mydsadn; char buffer [LINESIZE]; Attr_Sequence as; extern AttributeType at_control; int i; if (big_size == 0) for (i = NBBY * sizeof big_size - 1; i > 0; i--) big_size <<= 1, big_size |= 1; if ((arg->sra_eis.eis_allattributes) || (arg->sra_eis.eis_infotypes == EIS_ATTRIBUTETYPESONLY)) return FALSE; if (arg->sra_eis.eis_select == NULLATTR) return FALSE; if (arg->sra_eis.eis_select->attr_link != NULLATTR) return FALSE; if (AttrT_cmp (at_control,&arg->sra_eis.eis_select->attr_type) != 0) return FALSE; if (result->CSR_entries) entryinfo_free (result->CSR_entries,1); (void) sprintf (buffer,"%d",big_size-size); as=as_comp_alloc(); as->attr_acl = NULLACL_INFO; as->attr_type.at_oid = NULLOID; as->attr_type.at_table = at_control->at_table; as->attr_link = NULLATTR; if ((as->attr_value = str2avs (buffer,&as->attr_type)) == NULLAV) { as_free (as); result->CSR_entries = NULLENTRYINFO; return FALSE; } result->CSR_entries = entryinfo_alloc (); result->CSR_entries->ent_dn = dn_cpy (mydsadn); result->CSR_entries->ent_next = NULLENTRYINFO; result->CSR_entries->ent_age = (time_t) 0; result->CSR_entries->ent_iscopy = TRUE; result->CSR_entries->ent_attr = as; return TRUE; }