Commit | Line | Data |
---|---|---|
9e8e5516 C |
1 | /* ds_read.c - */ |
2 | ||
3 | #ifndef lint | |
4 | static char *rcsid = "$Header: /f/osi/quipu/RCS/ds_read.c,v 7.3 91/02/22 09:38:56 mrose Interim $"; | |
5 | #endif | |
6 | ||
7 | /* | |
8 | * $Header: /f/osi/quipu/RCS/ds_read.c,v 7.3 91/02/22 09:38:56 mrose Interim $ | |
9 | * | |
10 | * | |
11 | * $Log: ds_read.c,v $ | |
12 | * Revision 7.3 91/02/22 09:38:56 mrose | |
13 | * Interim 6.8 | |
14 | * | |
15 | * Revision 7.2 90/10/17 11:53:50 mrose | |
16 | * sync | |
17 | * | |
18 | * Revision 7.1 90/07/09 14:45:48 mrose | |
19 | * sync | |
20 | * | |
21 | * Revision 7.0 89/11/23 22:17:14 mrose | |
22 | * Release 6.0 | |
23 | * | |
24 | */ | |
25 | ||
26 | /* | |
27 | * NOTICE | |
28 | * | |
29 | * Acquisition, use, and distribution of this module and related | |
30 | * materials are subject to the restrictions of a license agreement. | |
31 | * Consult the Preface in the User's Manual for the full terms of | |
32 | * this agreement. | |
33 | * | |
34 | */ | |
35 | ||
36 | ||
37 | #include "quipu/util.h" | |
38 | #include "quipu/entry.h" | |
39 | #include "quipu/read.h" | |
40 | #include "quipu/policy.h" | |
41 | #include "quipu/connection.h" | |
42 | #include "pepsy.h" | |
43 | #include "quipu/DAS_pre_defs.h" | |
44 | ||
45 | extern LLog * log_dsap; | |
46 | ||
47 | Attr_Sequence eis_select (); | |
48 | Attr_Sequence dsa_eis_select (); | |
49 | extern Attr_Sequence entry_find_type(); | |
50 | static cant_use_cache(); | |
51 | static attribute_not_cached (); | |
52 | extern AttributeType at_control; | |
53 | extern unsigned bind_policy; | |
54 | extern unsigned strong_policy; | |
55 | extern DN mydsadn; | |
56 | extern struct di_block * di_alloc(); | |
57 | ||
58 | do_ds_read (arg, error, result, binddn, target, di_p, dsp, quipu_ctx) | |
59 | struct ds_read_arg *arg; | |
60 | struct ds_read_result *result; | |
61 | struct DSError *error; | |
62 | DN binddn; | |
63 | DN target; | |
64 | struct di_block **di_p; | |
65 | char dsp; | |
66 | char quipu_ctx; | |
67 | { | |
68 | Entry entryptr; | |
69 | int retval; | |
70 | int authenticated; | |
71 | DN realtarget; | |
72 | ||
73 | DLOG (log_dsap,LLOG_TRACE,("ds_read")); | |
74 | ||
75 | if (!dsp) | |
76 | target = arg->rda_object; | |
77 | ||
78 | if (!dsp && dsa_read_control(arg,result)) | |
79 | return (DS_OK); | |
80 | ||
81 | if (target == NULLDN) { | |
82 | /* can't read from the root */ | |
83 | error->dse_type = DSE_NAMEERROR; | |
84 | error->ERR_NAME.DSE_na_problem = DSE_NA_NOSUCHOBJECT; | |
85 | error->ERR_NAME.DSE_na_matched = NULLDN; | |
86 | return (DS_ERROR_REMOTE); | |
87 | } | |
88 | ||
89 | switch(find_entry(target,&(arg->rda_common),binddn,NULLDNSEQ,FALSE,&(entryptr), error, di_p, OP_READ)) | |
90 | { | |
91 | case DS_OK: | |
92 | /* Filled out entryptr - carry on */ | |
93 | break; | |
94 | case DS_CONTINUE: | |
95 | /* Filled out di_p - what do we do with it ?? */ | |
96 | return(DS_CONTINUE); | |
97 | ||
98 | case DS_X500_ERROR: | |
99 | /* Filled out error - what do we do with it ?? */ | |
100 | return(DS_X500_ERROR); | |
101 | default: | |
102 | /* SCREAM */ | |
103 | LLOG(log_dsap, LLOG_EXCEPTIONS, ("do_ds_read() - find_entry failed")); | |
104 | return(DS_ERROR_LOCAL); | |
105 | } | |
106 | ||
107 | realtarget = get_copy_dn (entryptr); | |
108 | ||
109 | /* User can be authenticated by using strong authentication for this | |
110 | * operation, or by using the credntials from the bind. | |
111 | */ | |
112 | ||
113 | authenticated = 0; | |
114 | ||
115 | /* Credentials provided in the ds_bind */ | |
116 | if ((bind_policy & POLICY_ACCESS_READ) && (!dsp) && (binddn != NULLDN)) | |
117 | authenticated = 1; | |
118 | ||
119 | /* Strong authentication */ | |
120 | /* If it's there, check it, even if you won't believe it anyway */ | |
121 | if ((retval = check_security_parms((caddr_t) arg, | |
122 | _ZReadArgumentDataDAS, | |
123 | &_ZDAS_mod, | |
124 | arg->rda_common.ca_security, | |
125 | arg->rda_common.ca_sig, &binddn)) != 0) | |
126 | { | |
127 | error->dse_type = DSE_SECURITYERROR; | |
128 | error->ERR_SECURITY.DSE_sc_problem = retval; | |
129 | dn_free (realtarget); | |
130 | return (DS_ERROR_REMOTE); | |
131 | } | |
132 | ||
133 | if ((strong_policy & POLICY_ACCESS_READ) && | |
134 | (arg->rda_common.ca_sig != (struct signature *) 0)) | |
135 | authenticated = 1; | |
136 | ||
137 | /* entry has got a full list of attributes, eventually | |
138 | select one required */ | |
139 | if (check_acl (authenticated ? binddn : NULLDN,ACL_READ,entryptr->e_acl->ac_entry, realtarget) == NOTOK) { | |
140 | if (dsp && (check_acl (binddn,ACL_READ,entryptr->e_acl->ac_entry, realtarget) == OK)) { | |
141 | error->dse_type = DSE_SECURITYERROR; | |
142 | error->ERR_SECURITY.DSE_sc_problem = DSE_SC_AUTHENTICATION; | |
143 | dn_free (realtarget); | |
144 | return (DS_ERROR_REMOTE); | |
145 | } else { | |
146 | error->dse_type = DSE_SECURITYERROR; | |
147 | error->ERR_SECURITY.DSE_sc_problem = DSE_SC_ACCESSRIGHTS; | |
148 | dn_free (realtarget); | |
149 | return (DS_ERROR_REMOTE); | |
150 | } | |
151 | } | |
152 | ||
153 | if (entryptr->e_dsainfo && need_pseudo_dsa(entryptr,arg)) { | |
154 | ||
155 | /* Its a 7.0 or better DSA. | |
156 | * pseudo attributes asked for. | |
157 | * special routing req'd | |
158 | */ | |
159 | ||
160 | if (dn_cmp (realtarget, mydsadn) == 0) { | |
161 | /* Its me - generate result */ | |
162 | ||
163 | if ((result->rdr_entry.ent_attr = dsa_eis_select ( | |
164 | arg->rda_eis,entryptr, dsp ? NULLDN : binddn, | |
165 | quipu_ctx, realtarget)) != NULLATTR) | |
166 | goto out; | |
167 | ||
168 | error->dse_type = DSE_ATTRIBUTEERROR; | |
169 | error->ERR_ATTRIBUTE.DSE_at_name = get_copy_dn (entryptr); | |
170 | error->ERR_ATTRIBUTE.DSE_at_plist.DSE_at_what =DSE_AT_NOSUCHATTRIBUTE; | |
171 | if (arg->rda_eis.eis_select != NULLATTR) | |
172 | error->ERR_ATTRIBUTE.DSE_at_plist.DSE_at_type = AttrT_cpy(arg->rda_eis.eis_select->attr_type); | |
173 | else | |
174 | error->ERR_ATTRIBUTE.DSE_at_plist.DSE_at_type = NULLAttrT; | |
175 | error->ERR_ATTRIBUTE.DSE_at_plist.DSE_at_value = NULLAttrV; | |
176 | error->ERR_ATTRIBUTE.DSE_at_plist.dse_at_next = DSE_AT_NOPROBLEM; | |
177 | dn_free (realtarget); | |
178 | return (DS_ERROR_REMOTE); | |
179 | ||
180 | } else { | |
181 | /* make referral to DSA in this entry */ | |
182 | (*di_p) = di_alloc(); | |
183 | (*di_p)->di_type = DI_TASK; | |
184 | (*di_p)->di_dn = realtarget; | |
185 | (*di_p)->di_target = dn_cpy(realtarget); | |
186 | (*di_p)->di_reftype = RT_UNDEFINED; | |
187 | (*di_p)->di_rdn_resolved = CR_RDNRESOLVED_NOTDEFINED; | |
188 | (*di_p)->di_aliasedRDNs = CR_NOALIASEDRDNS; | |
189 | (*di_p)->di_entry = entryptr; | |
190 | entryptr->e_refcount++; | |
191 | (*di_p)->di_state = DI_COMPLETE; | |
192 | ||
193 | return DS_CONTINUE; | |
194 | } | |
195 | ||
196 | } | |
197 | ||
198 | if (cant_use_cache (entryptr,binddn,arg->rda_eis,realtarget)) { | |
199 | int res = referral_dsa_info(realtarget,NULLDNSEQ,FALSE,entryptr,error,di_p, | |
200 | arg->rda_common.ca_servicecontrol.svc_options & SVC_OPT_PREFERCHAIN); | |
201 | dn_free (realtarget); | |
202 | return res; | |
203 | } | |
204 | ||
205 | if (dsp && (eis_check (arg->rda_eis,entryptr, binddn) != OK)) { | |
206 | /* Can only send public things over DSP - but user is entitled to more */ | |
207 | error->dse_type = DSE_SECURITYERROR; | |
208 | error->ERR_SECURITY.DSE_sc_problem = DSE_SC_AUTHENTICATION; | |
209 | dn_free (realtarget); | |
210 | return (DS_ERROR_REMOTE); | |
211 | } | |
212 | ||
213 | if ((result->rdr_entry.ent_attr = eis_select (arg->rda_eis,entryptr, dsp ? NULLDN : binddn, quipu_ctx, realtarget)) == NULLATTR) | |
214 | if (! arg->rda_eis.eis_allattributes) { | |
215 | error->dse_type = DSE_ATTRIBUTEERROR; | |
216 | error->ERR_ATTRIBUTE.DSE_at_name = get_copy_dn (entryptr); | |
217 | error->ERR_ATTRIBUTE.DSE_at_plist.DSE_at_what =DSE_AT_NOSUCHATTRIBUTE; | |
218 | if (arg->rda_eis.eis_select != NULLATTR) | |
219 | error->ERR_ATTRIBUTE.DSE_at_plist.DSE_at_type = AttrT_cpy(arg->rda_eis.eis_select->attr_type); | |
220 | else | |
221 | error->ERR_ATTRIBUTE.DSE_at_plist.DSE_at_type = NULLAttrT; | |
222 | error->ERR_ATTRIBUTE.DSE_at_plist.DSE_at_value = NULLAttrV; | |
223 | error->ERR_ATTRIBUTE.DSE_at_plist.dse_at_next = DSE_AT_NOPROBLEM; | |
224 | dn_free (realtarget); | |
225 | return (DS_ERROR_REMOTE); | |
226 | } | |
227 | ||
228 | out:; | |
229 | result->rdr_entry.ent_dn = realtarget; | |
230 | result->rdr_entry.ent_iscopy = entryptr->e_data; | |
231 | result->rdr_entry.ent_age = (time_t) 0; | |
232 | result->rdr_entry.ent_next = NULLENTRYINFO; | |
233 | result->rdr_common.cr_requestor = NULLDN; | |
234 | /* if no error and NOT SVC_OPT_DONTDEREFERENCEALIASES then */ | |
235 | /* the alias will have been derefeferenced -signified by */ | |
236 | /* NO_ERROR !!! */ | |
237 | result->rdr_common.cr_aliasdereferenced = (error->dse_type == DSE_NOERROR) ? FALSE : TRUE; | |
238 | return (DS_OK); | |
239 | ||
240 | } | |
241 | ||
242 | static cant_use_cache (ptr,dn,eis,target) | |
243 | Entry ptr; | |
244 | DN dn; | |
245 | EntryInfoSelection eis; | |
246 | DN target; | |
247 | { | |
248 | register Attr_Sequence as; | |
249 | char dfltacl = FALSE; | |
250 | ||
251 | if (dn == NULLDN) | |
252 | return FALSE; | |
253 | ||
254 | if ((ptr->e_data == E_DATA_MASTER) || (ptr->e_data == E_TYPE_SLAVE)) | |
255 | return FALSE; | |
256 | ||
257 | /* see if more than cached data is required */ | |
258 | ||
259 | if (eis.eis_allattributes) { | |
260 | struct acl_attr * aa; | |
261 | struct oid_seq * oidptr; | |
262 | /* look for attr acl */ | |
263 | /* see if any attributes use can see */ | |
264 | ||
265 | if (check_acl (NULLDN,ACL_READ,ptr->e_acl->ac_default,target) == NOTOK) | |
266 | if (check_acl (dn,ACL_READ,ptr->e_acl->ac_default,target) == OK) | |
267 | return TRUE; | |
268 | ||
269 | if (ptr->e_acl->ac_attributes == NULLACL_ATTR) | |
270 | return FALSE; | |
271 | ||
272 | for ( aa = ptr->e_acl->ac_attributes; aa!=NULLACL_ATTR; aa=aa->aa_next) | |
273 | for ( oidptr=aa->aa_types;oidptr != NULLOIDSEQ; oidptr=oidptr->oid_next) | |
274 | /* The attribute is in the attribute ACL list */ | |
275 | /* Would a referral help the DUA ? */ | |
276 | if (check_acl (NULLDN,ACL_READ,aa->aa_acl,target) == NOTOK) | |
277 | if (check_acl (dn,ACL_READ,aa->aa_acl,target) == OK) | |
278 | return TRUE; | |
279 | ||
280 | } else { | |
281 | /* for each attribute in eis.eis_select, see is user | |
282 | entitled to it. */ | |
283 | ||
284 | if (check_acl (NULLDN,ACL_READ,ptr->e_acl->ac_default,target) == NOTOK) | |
285 | if (check_acl (dn,ACL_READ,ptr->e_acl->ac_default,target) == OK) | |
286 | dfltacl = TRUE; | |
287 | ||
288 | for(as=eis.eis_select; as != NULLATTR; as=as->attr_link) { | |
289 | if (entry_find_type (ptr, as->attr_type) == NULLATTR) | |
290 | if (attribute_not_cached (ptr,dn,grab_oid(as->attr_type),target,ACL_READ,dfltacl)) | |
291 | return TRUE; | |
292 | ||
293 | } | |
294 | } | |
295 | return FALSE; | |
296 | } | |
297 | ||
298 | static attribute_not_cached (ptr,dn,at,target,level,dfltacl) | |
299 | Entry ptr; | |
300 | DN dn; | |
301 | OID at; | |
302 | DN target; | |
303 | int level; | |
304 | char dfltacl; | |
305 | { | |
306 | register struct acl_attr * aa; | |
307 | register struct oid_seq * oidptr; | |
308 | ||
309 | /* see if more than cached data is required */ | |
310 | if (ptr->e_acl->ac_attributes == NULLACL_ATTR) | |
311 | return (dfltacl); | |
312 | ||
313 | for ( aa = ptr->e_acl->ac_attributes; aa!=NULLACL_ATTR; aa=aa->aa_next) | |
314 | for ( oidptr=aa->aa_types;oidptr != NULLOIDSEQ; oidptr=oidptr->oid_next) | |
315 | if (oid_cmp (oidptr->oid_oid,at) == 0) { | |
316 | /* The attribute is in the attribute ACL list */ | |
317 | /* Would a referral help the DUA ? */ | |
318 | if (check_acl (NULLDN,level,aa->aa_acl,target) == NOTOK) | |
319 | if (check_acl (dn,level,aa->aa_acl,target) == OK) | |
320 | return TRUE; | |
321 | return FALSE; | |
322 | } | |
323 | return (dfltacl); | |
324 | ||
325 | } | |
326 | ||
327 | ||
328 | static Attr_Sequence dsa_control_info() | |
329 | { | |
330 | extern int slave_edbs; | |
331 | extern int master_edbs; | |
332 | extern int local_master_size; | |
333 | extern int local_slave_size; | |
334 | extern int local_cache_size; | |
335 | char buffer [LINESIZE]; | |
336 | Attr_Sequence as; | |
337 | ||
338 | (void) sprintf (buffer,"%d Master entries (in %d EDBs), %d Slave entries (in %d EDBs), %d Cached entries", | |
339 | local_master_size,master_edbs,local_slave_size,slave_edbs,local_cache_size); | |
340 | ||
341 | as=as_comp_alloc(); | |
342 | as->attr_acl = NULLACL_INFO; | |
343 | as->attr_type = at_control; | |
344 | as->attr_link = NULLATTR; | |
345 | if ((as->attr_value = str2avs (buffer,as->attr_type)) == NULLAV) { | |
346 | as_free (as); | |
347 | return (NULLATTR); | |
348 | } | |
349 | ||
350 | return (as); | |
351 | } | |
352 | ||
353 | dsa_read_control (arg,result) | |
354 | struct ds_read_arg *arg; | |
355 | struct ds_read_result *result; | |
356 | { | |
357 | extern DN mydsadn; | |
358 | ||
359 | if ((arg->rda_eis.eis_allattributes) || | |
360 | (arg->rda_eis.eis_infotypes == EIS_ATTRIBUTETYPESONLY)) | |
361 | return FALSE; | |
362 | ||
363 | if ((arg->rda_eis.eis_select == NULLATTR) | |
364 | || (arg->rda_eis.eis_select->attr_link != NULLATTR)) | |
365 | return FALSE; | |
366 | ||
367 | if (AttrT_cmp (at_control,arg->rda_eis.eis_select->attr_type) != 0) | |
368 | return FALSE; | |
369 | ||
370 | if ((result->rdr_entry.ent_attr = dsa_control_info()) == NULLATTR) | |
371 | return FALSE; | |
372 | ||
373 | /* Fiddle DN - for DUA caching !!! */ | |
374 | result->rdr_entry.ent_dn = dn_cpy (mydsadn); | |
375 | ||
376 | result->rdr_entry.ent_iscopy = FALSE; | |
377 | result->rdr_entry.ent_age = (time_t) 0; | |
378 | result->rdr_entry.ent_next = NULLENTRYINFO; | |
379 | result->rdr_common.cr_requestor = NULLDN; | |
380 | result->rdr_common.cr_aliasdereferenced = FALSE; | |
381 | ||
382 | return TRUE; | |
383 | } | |
384 | ||
385 | ||
386 | ||
387 | ||
388 | need_pseudo_dsa (eptr,arg) | |
389 | Entry eptr; | |
390 | struct ds_read_arg *arg; | |
391 | { | |
392 | Attr_Sequence as; | |
393 | ||
394 | if (quipu_ctx_supported (eptr) != 2) | |
395 | return FALSE; | |
396 | ||
397 | if (!quipu_version_7 (eptr)) | |
398 | return FALSE; | |
399 | ||
400 | if ((arg->rda_common.ca_servicecontrol.svc_options & SVC_OPT_DONTUSECOPY) != 0) | |
401 | return TRUE; | |
402 | ||
403 | if (arg->rda_eis.eis_allattributes) | |
404 | return FALSE; | |
405 | ||
406 | for (as = arg->rda_eis.eis_select; as!= NULLATTR; as=as->attr_link) { | |
407 | if (check_avs_schema (as->attr_type, eptr->e_oc) != OK) | |
408 | return TRUE; | |
409 | } | |
410 | ||
411 | return FALSE; | |
412 | } | |
413 |