Start development on 386BSD 0.0
[unix-history] / .ref-BSD-4_3_Net_2 / usr / src / contrib / isode / quipu / ds_read.c
CommitLineData
9e8e5516
C
1/* ds_read.c - */
2
3#ifndef lint
4static 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
45extern LLog * log_dsap;
46
47Attr_Sequence eis_select ();
48Attr_Sequence dsa_eis_select ();
49extern Attr_Sequence entry_find_type();
50static cant_use_cache();
51static attribute_not_cached ();
52extern AttributeType at_control;
53extern unsigned bind_policy;
54extern unsigned strong_policy;
55extern DN mydsadn;
56extern struct di_block * di_alloc();
57
58do_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{
68Entry entryptr;
69int retval;
70int authenticated;
71DN 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
228out:;
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
242static cant_use_cache (ptr,dn,eis,target)
243Entry ptr;
244DN dn;
245EntryInfoSelection eis;
246DN target;
247{
248register Attr_Sequence as;
249char 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
298static attribute_not_cached (ptr,dn,at,target,level,dfltacl)
299Entry ptr;
300DN dn;
301OID at;
302DN target;
303int level;
304char dfltacl;
305{
306register struct acl_attr * aa;
307register 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
328static Attr_Sequence dsa_control_info()
329{
330extern int slave_edbs;
331extern int master_edbs;
332extern int local_master_size;
333extern int local_slave_size;
334extern int local_cache_size;
335char buffer [LINESIZE];
336Attr_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
353dsa_read_control (arg,result)
354 struct ds_read_arg *arg;
355 struct ds_read_result *result;
356{
357extern 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
388need_pseudo_dsa (eptr,arg)
389Entry eptr;
390struct ds_read_arg *arg;
391{
392Attr_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