Commit | Line | Data |
---|---|---|
fc4ef1d0 C |
1 | /* ds_list.c - */ |
2 | ||
3 | #ifndef lint | |
4 | static 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 | ||
49 | extern LLog * log_dsap; | |
50 | extern Entry database_root; | |
51 | static int build_result(); | |
52 | ||
53 | do_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 | { | |
62 | Entry entryptr; | |
63 | int retval; | |
64 | DN 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 | ||
184 | static struct subordinate *g_sub; | |
185 | static struct subordinate *g_trail = NULLSUBORD; | |
186 | static int g_count; | |
187 | static int g_size; | |
188 | static DN g_dn; | |
189 | static DN g_dnend; | |
190 | ||
191 | static int build_list(e, dn) | |
192 | Entry e; | |
193 | DN 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 | ||
223 | static int build_result (arg,ptr,result,error,binddn,dsp) | |
224 | register Entry ptr; | |
225 | struct ds_list_arg *arg; | |
226 | struct ds_list_result *result; | |
227 | struct DSError * error; | |
228 | DN binddn; | |
229 | char dsp; | |
230 | { | |
231 | DN dn; | |
232 | DN dnend; | |
233 | int size; | |
234 | RDN dnrdn; | |
235 | extern int admin_size; | |
236 | char adminlimit = FALSE; | |
237 | #ifdef TURBO_AVL | |
238 | int rc; | |
239 | Entry akid; | |
240 | #else | |
241 | register struct subordinate *sub = NULLSUBORD; | |
242 | register struct subordinate *trail = NULLSUBORD; | |
243 | register 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 | ||
351 | try_cache (arg,result,target) | |
352 | register struct ds_list_arg *arg; | |
353 | register struct ds_list_result *result; | |
354 | DN target; | |
355 | { | |
356 | struct list_cache *ptr; | |
357 | struct 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 |