Start development on 386BSD 0.0
[unix-history] / .ref-BSD-4_3_Net_2 / usr / src / contrib / isode / quipu / ds_list.c
CommitLineData
fc4ef1d0
C
1/* ds_list.c - */
2
3#ifndef lint
4static char *rcsid = "$Header: /f/osi/quipu/RCS/ds_list.c,v 7.4 91/03/09 11:56:42 mrose Exp $";
5#endif
6
7/*
8 * $Header: /f/osi/quipu/RCS/ds_list.c,v 7.4 91/03/09 11:56:42 mrose Exp $
9 *
10 *
11 * $Log: ds_list.c,v $
12 * Revision 7.4 91/03/09 11:56:42 mrose
13 * update
14 *
15 * Revision 7.3 91/02/22 09:38:50 mrose
16 * Interim 6.8
17 *
18 * Revision 7.2 90/10/17 11:53:44 mrose
19 * sync
20 *
21 * Revision 7.1 90/07/09 14:45:43 mrose
22 * sync
23 *
24 * Revision 7.0 89/11/23 22:17:09 mrose
25 * Release 6.0
26 *
27 */
28
29/*
30 * NOTICE
31 *
32 * Acquisition, use, and distribution of this module and related
33 * materials are subject to the restrictions of a license agreement.
34 * Consult the Preface in the User's Manual for the full terms of
35 * this agreement.
36 *
37 */
38
39
40#include "quipu/util.h"
41#include "quipu/connection.h"
42#include "quipu/list.h"
43#ifdef TURBO_AVL
44#include "quipu/turbo.h"
45#endif
46#include "pepsy.h"
47#include "quipu/DAS_pre_defs.h"
48
49extern LLog * log_dsap;
50extern Entry database_root;
51static int build_result();
52
53do_ds_list (arg, error, result, binddn, target, di_p, dsp)
54 register struct ds_list_arg *arg;
55 register struct ds_list_result *result;
56 struct DSError *error;
57 DN binddn;
58 DN target;
59 struct di_block **di_p;
60 char dsp;
61{
62Entry entryptr;
63int retval;
64DN realtarget;
65
66 DLOG (log_dsap,LLOG_TRACE,("ds_list"));
67
68 if (!dsp)
69 target = arg->lsa_object;
70
71 switch(find_child_entry(target,&(arg->lsa_common),binddn,NULLDNSEQ,FALSE,&(entryptr),error,di_p))
72 {
73 case DS_OK:
74 /* Filled out entryptr - carry on */
75 break;
76 case DS_CONTINUE:
77 /* Filled out di_p - what do we do with it ?? */
78 return(DS_CONTINUE);
79
80 case DS_X500_ERROR:
81 /* Filled out error - what do we do with it ?? */
82 return(DS_X500_ERROR);
83 default:
84 /* SCREAM */
85 LLOG(log_dsap, LLOG_EXCEPTIONS, ("do_ds_list() - find_child_entry failed"));
86 return(DS_ERROR_LOCAL);
87 }
88
89 /* Strong authentication */
90 if ((retval = check_security_parms((caddr_t) arg,
91 _ZListArgumentDataDAS,
92 &_ZDAS_mod,
93 arg->lsa_common.ca_security,
94 arg->lsa_common.ca_sig, &binddn)) != 0)
95 {
96 error->dse_type = DSE_SECURITYERROR;
97 error->ERR_SECURITY.DSE_sc_problem = retval;
98 return (DS_ERROR_REMOTE);
99 }
100
101 realtarget = get_copy_dn(entryptr);
102
103 if (isleaf(entryptr)) {
104
105#ifdef NOTANYMORE
106
107 if ((entryptr->e_master != NULLAV) || (entryptr->e_slave != NULLAV)) {
108 int res;
109 /* PROBLEM: Might not list everything if user is entitled to more... */
110 if (try_cache (arg,result,realtarget) == OK) {
111 dn_free (realtarget);
112 return (DS_OK);
113 }
114 res = constructor_dsa_info(realtarget,NULLDNSEQ,FALSE,entryptr,error,di_p);
115 dn_free (realtarget);
116 return res;
117 }
118#endif
119
120 dn_free (realtarget);
121
122 result->lsr_subordinates = NULLSUBORD;
123 result->lsr_age = (time_t) 0 ;
124 result->lsr_common.cr_requestor = NULLDN;
125 if ( error->dse_type == DSE_NOERROR ) {
126 result->lsr_object = NULLDN;
127 result->lsr_common.cr_aliasdereferenced = FALSE;
128 } else {
129 result->lsr_common.cr_aliasdereferenced = TRUE;
130 result->lsr_object = get_copy_dn (entryptr->e_parent);
131 }
132 result->lsr_cr = NULLCONTINUATIONREF;
133 result->lsr_limitproblem = LSR_NOLIMITPROBLEM;
134 return (DS_OK);
135 }
136
137 /* check parent will allow listing */
138 if (check_acl (dsp ? NULLDN : binddn,ACL_READ, entryptr->e_acl->ac_child, realtarget) != OK) {
139 if (dsp && (check_acl (binddn,ACL_READ, entryptr->e_acl->ac_child, realtarget) == OK)) {
140 error->dse_type = DSE_SECURITYERROR;
141 error->ERR_SECURITY.DSE_sc_problem = DSE_SC_AUTHENTICATION;
142 dn_free (realtarget);
143 return (DS_ERROR_REMOTE);
144 }
145 error->dse_type = DSE_SECURITYERROR;
146 error->ERR_SECURITY.DSE_sc_problem = DSE_SC_ACCESSRIGHTS;
147 dn_free (realtarget);
148 return (DS_ERROR_REMOTE);
149 }
150
151#ifdef TURBO_AVL
152 if (entryptr->e_children == NULLAVL) {
153#else
154 if (entryptr->e_child == NULLENTRY) {
155#endif
156 int res;
157 if (try_cache (arg,result,realtarget) == OK) {
158 dn_free (realtarget);
159 return (DS_OK);
160 }
161 res = constructor_dsa_info(realtarget,NULLDNSEQ,FALSE,entryptr,error,di_p);
162 dn_free (realtarget);
163 return res;
164 }
165
166 dn_free (realtarget);
167
168#ifdef TURBO_AVL
169 build_result (arg,entryptr,result,error,dsp ? NULLDN : binddn, dsp);
170#else
171 build_result (arg,entryptr->e_child,result,error,dsp ? NULLDN : binddn, dsp);
172#endif
173 return (DS_OK);
174}
175
176#ifdef TURBO_AVL
177/*
178 * these are globals changed by build_result and build_list. they have
179 * to be globals because build_list is called by avl_apply, and it only
180 * allows one additional argument to be passed. pretty gross, but that's
181 * the way it is...
182 */
183
184static struct subordinate *g_sub;
185static struct subordinate *g_trail = NULLSUBORD;
186static int g_count;
187static int g_size;
188static DN g_dn;
189static DN g_dnend;
190
191static int build_list(e, dn)
192Entry e;
193DN dn;
194{
195 struct subordinate *sub;
196
197 if (g_size != SVC_NOSIZELIMIT && g_count >= g_size)
198 return(NOTOK);
199
200 g_dnend->dn_rdn = e->e_name;
201 if (check_acl(dn, ACL_READ, e->e_acl->ac_entry, g_dn) != OK)
202 return(0);
203
204 sub = (struct subordinate *) smalloc(sizeof(struct subordinate));
205 sub->sub_copy = e->e_data;
206 sub->sub_rdn = rdn_cpy(e->e_name);
207 sub->sub_aliasentry = (e->e_alias == NULLDN ? FALSE : TRUE);
208 sub->sub_next = NULLSUBORD;
209
210 if (g_sub == NULLSUBORD) {
211 g_sub = sub;
212 g_trail = sub;
213 } else {
214 g_trail->sub_next = sub;
215 g_trail = sub;
216 }
217
218 g_count++;
219 return(0);
220}
221#endif /* TURBO_AVL */
222
223static int build_result (arg,ptr,result,error,binddn,dsp)
224register Entry ptr;
225struct ds_list_arg *arg;
226struct ds_list_result *result;
227struct DSError * error;
228DN binddn;
229char dsp;
230{
231DN dn;
232DN dnend;
233int size;
234RDN dnrdn;
235extern int admin_size;
236char adminlimit = FALSE;
237#ifdef TURBO_AVL
238int rc;
239Entry akid;
240#else
241register struct subordinate *sub = NULLSUBORD;
242register struct subordinate *trail = NULLSUBORD;
243register int cnt;
244#endif
245
246 DLOG (log_dsap,LLOG_DEBUG,("building list results"));
247
248 result->lsr_subordinates = NULLSUBORD;
249 if (!dsp && manager (binddn))
250 size = arg->lsa_common.ca_servicecontrol.svc_sizelimit;
251 else
252 if ((size = MIN(admin_size,arg->lsa_common.ca_servicecontrol.svc_sizelimit)) == SVC_NOSIZELIMIT) {
253 size = admin_size;
254 adminlimit = TRUE;
255 }
256
257 result->lsr_age = (time_t) 0 ;
258 result->lsr_common.cr_requestor = NULLDN;
259 /* if no error and NOT SVC_OPT_DONTDEREFERENCEALIASES then */
260 /* the alias will have been derefeferenced -signified by */
261 /* NO_ERROR !!! */
262 if ( error->dse_type == DSE_NOERROR ) {
263 result->lsr_object = NULLDN;
264 result->lsr_common.cr_aliasdereferenced = FALSE;
265 } else {
266 result->lsr_common.cr_aliasdereferenced = TRUE;
267#ifdef TURBO_AVL
268 result->lsr_object = get_copy_dn (ptr);
269#else
270 result->lsr_object = get_copy_dn (ptr->e_parent);
271#endif
272 }
273 result->lsr_cr = NULLCONTINUATIONREF;
274
275#ifdef TURBO_AVL
276 /* we already checked for null kids ... */
277 akid = (Entry) avl_getone(ptr->e_children);
278 dn = get_copy_dn(akid);
279#else
280 dn = get_copy_dn (ptr);
281#endif
282 for (dnend = dn; dnend->dn_parent != NULLDN; dnend=dnend->dn_parent)
283 ; /* NO-OP */
284 dnrdn = dnend->dn_rdn;
285
286#ifdef TURBO_AVL
287 g_dn = dn;
288 g_dnend = dnend;
289 g_sub = NULLSUBORD;
290 g_size = size;
291 g_count = 0;
292
293 /*
294 * preorder would be a little faster in case of small size limit,
295 * but inorder is more user-predictable, which is nice, though not
296 * required...
297 */
298
299 rc = avl_apply(ptr->e_children, build_list, (caddr_t) binddn, NOTOK,
300 AVL_INORDER);
301
302 /*
303 * build_list has updated g_count and g_sub to contain a count of
304 * the number of entries in the list and the list itself,
305 * respectively. if avl_apply was not cut short because the size
306 * limit was reached (i.e. instead it ran out of nodes), rc will
307 * be NOTOK.
308 */
309
310 size = g_size;
311 result->lsr_subordinates = g_sub;
312#else
313 for (cnt =0; (ptr!=NULLENTRY) && (size == SVC_NOSIZELIMIT || cnt < size) ; ptr=ptr->e_sibling) {
314 dnend->dn_rdn = ptr->e_name;
315 if (check_acl (binddn,ACL_READ,ptr->e_acl->ac_entry,dn) == OK) {
316 sub = (struct subordinate *) smalloc (sizeof(struct subordinate));
317 sub->sub_copy = ptr->e_data;
318 sub->sub_rdn = rdn_cpy(ptr->e_name);
319 sub->sub_aliasentry = (ptr->e_alias == NULLDN ? FALSE : TRUE);
320 if (trail != NULLSUBORD)
321 trail->sub_next = sub;
322 else
323 result->lsr_subordinates = sub;
324 trail = sub;
325 cnt++;
326 }
327 }
328 if (sub)
329 sub->sub_next = NULLSUBORD;
330#endif /* TURBO_AVL */
331
332
333#ifdef TURBO_AVL
334 if ( rc != AVL_NOMORE )
335#else
336 if ( (size != SVC_NOSIZELIMIT && cnt >= size) && (ptr!=NULLENTRY) )
337#endif
338 /* stopped look up due to size limit */
339 /* need to send continuation reference */
340 result->lsr_limitproblem = adminlimit ?
341 LSR_ADMINSIZEEXCEEDED : LSR_SIZELIMITEXCEEDED;
342 else
343 result->lsr_limitproblem = LSR_NOLIMITPROBLEM;
344
345 dnend->dn_rdn = NULLRDN;
346 dn_free (dn);
347 rdn_free (dnrdn);
348}
349
350
351try_cache (arg,result,target)
352 register struct ds_list_arg *arg;
353 register struct ds_list_result *result;
354 DN target;
355{
356struct list_cache *ptr;
357struct subordinate * subord_cpy();
358
359 if ((arg->lsa_common.ca_servicecontrol.svc_options & SVC_OPT_DONTUSECOPY) == 0) {
360 if ((ptr = find_list_cache (target,arg->lsa_common.ca_servicecontrol.svc_sizelimit)) != NULLCACHE) {
361 DLOG (log_dsap,LLOG_DEBUG,("building list results using cache"));
362 result->lsr_subordinates = subord_cpy(ptr->list_subs);
363 result->lsr_age = (time_t) 0 ;
364 result->lsr_common.cr_aliasdereferenced = FALSE;
365 result->lsr_common.cr_requestor = NULLDN;
366 result->lsr_object = NULLDN;
367 result->lsr_cr = NULLCONTINUATIONREF;
368 result->lsr_limitproblem = ptr->list_problem;
369 return (OK);
370 }
371 }
372
373 return (NOTOK);
374}
375