BSD 4_3_Net_2 release
[unix-history] / usr / src / contrib / isode / quipu / get_dsa_info.c
CommitLineData
fc4ef1d0
C
1/* get_dsa_info.c - Get DSA info given its distinguished name */
2
3#ifndef lint
4static char *rcsid = "$Header: /f/osi/quipu/RCS/get_dsa_info.c,v 7.5 91/03/09 11:56:59 mrose Exp $";
5#endif
6
7/*
8 * $Header: /f/osi/quipu/RCS/get_dsa_info.c,v 7.5 91/03/09 11:56:59 mrose Exp $
9 *
10 *
11 * $Log: get_dsa_info.c,v $
12 * Revision 7.5 91/03/09 11:56:59 mrose
13 * update
14 *
15 * Revision 7.4 91/02/22 09:39:25 mrose
16 * Interim 6.8
17 *
18 * Revision 7.3 90/10/17 11:54:22 mrose
19 * sync
20 *
21 * Revision 7.2 89/12/19 16:20:36 mrose
22 * sync
23 *
24 * Revision 7.1 89/11/24 16:21:59 mrose
25 * sync
26 *
27 * Revision 7.0 89/11/23 22:17:42 mrose
28 * Release 6.0
29 *
30 */
31
32/*
33 * NOTICE
34 *
35 * Acquisition, use, and distribution of this module and related
36 * materials are subject to the restrictions of a license agreement.
37 * Consult the Preface in the User's Manual for the full terms of
38 * this agreement.
39 *
40 */
41
42
43#include "quipu/util.h"
44#include "quipu/read.h"
45#include "quipu/entry.h"
46#include "quipu/dua.h"
47#include "quipu/bind.h"
48#include "quipu/connection.h"
49
50extern LLog * log_dsap;
51extern DN mydsadn;
52extern int dn_print();
53
54struct oper_act * oper_alloc();
55struct di_block * di_alloc();
56struct oper_act * make_get_dsa_info_op();
57extern Attr_Sequence entry_find_type();
58extern char * index();
59
60/*
61* This routine is used to read the info (including presentation address)
62* for a dsa given its distinguished name.
63* This is called during the DSA initialisation, to find the name THIS dsa.
64*/
65
66int get_dsa_info(dn, dn_stack, err, di_p)
67DN dn;
68struct dn_seq * dn_stack;
69struct DSError * err;
70struct di_block **di_p;
71{
72 struct di_block * di_tmp;
73 struct di_block * di_lookup;
74 struct oper_act * on = NULLOPER;
75 int res;
76
77 DLOG (log_dsap,LLOG_TRACE,("get_dsa_info()"));
78
79 if (dn_in_dnseq(dn, dn_stack))
80 {
81 LLOG (log_dsap,LLOG_NOTICE,("get_dsa_info - loop detected"));
82 err->dse_type = DSE_SERVICEERROR;
83 err->dse_un.dse_un_service.DSE_sv_problem = DSE_SV_LOOPDETECT;
84 return(DS_X500_ERROR);
85 }
86
87 /* if asking about me, use my cached entry */
88 if (dn_cmp (dn,mydsadn) == 0)
89 {
90 LLOG (log_dsap,LLOG_NOTICE,("get_dsa_info - referring to self :-)"));
91 err->dse_type = DSE_SERVICEERROR;
92 err->dse_un.dse_un_service.DSE_sv_problem = DSE_SV_DITERROR;
93 return(DS_X500_ERROR);
94 }
95
96
97 (*di_p) = di_alloc();
98 (*di_p)->di_type = DI_TASK;
99 (*di_p)->di_dn = dn_cpy(dn);
100 (*di_p)->di_target = NULLDN;
101 (*di_p)->di_reftype = RT_SUBORDINATE;
102 (*di_p)->di_rdn_resolved = CR_RDNRESOLVED_NOTDEFINED;
103 (*di_p)->di_aliasedRDNs = CR_NOALIASEDRDNS;
104
105 /*
106 * Check for a GetDSAInfo operation already in the pipeline.
107 */
108 for(di_tmp=deferred_dis; di_tmp != NULL_DI_BLOCK; di_tmp=di_tmp->di_next)
109 {
110 if(dn_cmp(dn, di_tmp->di_dn) == 0)
111 {
112 (*di_p)->di_state = DI_DEFERRED;
113 (*di_p)->di_entry = NULLENTRY;
114
115 /* link to the performing operation */
116 (*di_p)->di_perform = di_tmp->di_perform;
117
118 /* Add to wake list leaving global block first to be woken */
119 (*di_p)->di_wake_next = di_tmp->di_wake_next;
120 di_tmp->di_wake_next = (*di_p);
121
122 DLOG(log_dsap, LLOG_DEBUG, ("Found global deferred di_block:"));
123#ifdef DEBUG
124 di_list_log((*di_p));
125#endif
126 return(DS_CONTINUE);
127 }
128 }
129
130 if ((res = really_find_entry(dn, TRUE, dn_stack, FALSE, &((*di_p)->di_entry), err, &(di_lookup))) == DS_OK)
131 /* is it really OK ??? */
132 if (((*di_p)->di_entry ->e_data == E_TYPE_CONSTRUCTOR)
133 || ((*di_p)->di_entry->e_dsainfo == NULL)
134 || ((*di_p)->di_entry->e_dsainfo->dsa_addr == NULLPA)) {
135 DN dn_found;
136 DLOG(log_dsap, LLOG_NOTICE, ("rfe returned a constructor"));
137 dn_found = get_copy_dn((*di_p)->di_entry);
138 res = constructor_dsa_info(dn_found,dn_stack,FALSE,(*di_p)->di_entry,err,&(di_lookup));
139 dn_free (dn_found);
140 } else
141 (*di_p)->di_entry->e_refcount++;
142
143 switch (res)
144 {
145 case DS_OK:
146 /* really_find_entry has found the entry and placed it in di_entry */
147 DLOG(log_dsap, LLOG_DEBUG, ("get_dsa_info - really_fe returns DS_OK"));
148 (*di_p)->di_state = DI_COMPLETE;
149#ifdef DEBUG
150 di_list_log((*di_p));
151#endif
152 return(DS_OK);
153
154 case DS_CONTINUE:
155 /*
156 * A list of di_blocks (di_lookup) has been generated by get_dsa_info.
157 * These should be used to chain the get_dsa_info operation.
158 * Attempt to generate an operation using the di_blocks returned
159 * and if successful, defer the current di_block to it.
160 */
161 DLOG(log_dsap, LLOG_DEBUG, ("gdi rfe returned DS_CONT:"));
162#ifdef DEBUG
163 di_list_log(di_lookup);
164#endif
165 if((on = make_get_dsa_info_op(dn, di_lookup)) == NULLOPER)
166 {
167 /* Flake out screaming */
168 LLOG(log_dsap, LLOG_EXCEPTIONS, ("make_get_dsa_info_op failed for get_dsa_info"));
169 free((char *)*di_p);
170 (*di_p) = NULL_DI_BLOCK;
171 err->dse_type = DSE_SERVICEERROR;
172 err->ERR_SERVICE.DSE_sv_problem = DSE_SV_UNABLETOPROCEED;
173 return(DS_X500_ERROR);
174 }
175
176 if(oper_chain(on) != OK)
177 {
178 /* Flake out screaming */
179 LLOG(log_dsap, LLOG_NOTICE, ("send_op failed for get_dsa_info"));
180 free((char *)*di_p);
181 (*di_p) = NULL_DI_BLOCK;
182 err->dse_type = DSE_SERVICEERROR;
183 err->ERR_SERVICE.DSE_sv_problem = DSE_SV_UNABLETOPROCEED;
184 return(DS_X500_ERROR);
185 }
186
187 di_tmp = di_alloc();
188 di_tmp->di_dn = dn_cpy(dn);
189 DLOG(log_dsap, LLOG_DEBUG, ("get_dsa_info allocates di_block with dn[%x]", di_tmp->di_dn));
190 di_tmp->di_state = DI_DEFERRED;
191 di_tmp->di_type = DI_GLOBAL;
192 di_tmp->di_perform = on;
193 on->on_wake_list = di_tmp; /* wake globals first */
194
195 (*di_p)->di_state = DI_DEFERRED;
196 (*di_p)->di_perform = on;
197
198 /* Add to wake list leaving global block first to be woken */
199 (*di_p)->di_wake_next = NULL_DI_BLOCK;
200 di_tmp->di_wake_next = (*di_p);
201
202 di_tmp->di_next = deferred_dis;
203 deferred_dis = di_tmp;
204
205 DLOG(log_dsap, LLOG_DEBUG, ("gdi DS_CONT: generated:"));
206#ifdef DEBUG
207 di_list_log((*di_p));
208#endif
209 return(DS_CONTINUE);
210
211 case DS_X500_ERROR:
212 /* something wrong with the request - err should be filled out */
213 DLOG(log_dsap, LLOG_DEBUG, ("gdi X500_ERROR"));
214 free((char *)*di_p);
215 (*di_p) = NULL_DI_BLOCK;
216 return(DS_X500_ERROR);
217
218 default:
219 LLOG(log_dsap, LLOG_EXCEPTIONS, ("Unexpected return from read_dsa_info"));
220 free((char *)*di_p);
221 (*di_p) = NULL_DI_BLOCK;
222 err->dse_type = DSE_SERVICEERROR;
223 err->ERR_SERVICE.DSE_sv_problem = DSE_SV_UNABLETOPROCEED;
224 return(DS_X500_ERROR);
225 }
226}
227
228
229dsa_info_result_wakeup(on)
230struct oper_act * on;
231{
232EntryInfo * ent_res;
233Entry di_ent;
234struct di_block * di;
235struct di_block * next_di;
236struct di_block **di_p;
237Entry cache_dsp_entry();
238
239 DLOG(log_dsap, LLOG_DEBUG, ("dsa_info_result_wakeup()"));
240
241 /*
242 * Cache the entry returned, flake out if it is not unravellable,
243 * otherwise grab a reference to the unravelled entry.
244 */
245
246 ent_res = &(on->on_resp.di_result.dr_res.dcr_dsres.res_rd.rdr_entry);
247 if((di_ent = cache_dsp_entry (ent_res)) == NULLENTRY)
248 {
249 LLOG (log_dsap, LLOG_EXCEPTIONS, ("dsa_info_result_wakeup - cache_dsp_entry failure"));
250 /* This could mean the cached entry was a SLAVE - if so why were we
251 * doing a get dsa info ?
252 */
253 dsa_info_error_wakeup(on);
254 return;
255 }
256
257 DLOG(log_dsap, LLOG_DEBUG, ("dsa_info_result_wakeup - cached dsa_info"));
258
259 /*
260 * First block on the wake up list should be the global marker.
261 * Verify this and remove it.
262 */
263 if(on->on_wake_list->di_type != DI_GLOBAL)
264 {
265 LLOG(log_dsap, LLOG_EXCEPTIONS, ("First di_block to wake not global"));
266 }
267 else
268 {
269 di_p = &(deferred_dis);
270 for(di = deferred_dis; di != NULL_DI_BLOCK; di=(*di_p))
271 {
272 if(di == on->on_wake_list)
273 break;
274
275 di_p = &(di->di_next);
276 }
277 if(di == NULL_DI_BLOCK)
278 {
279 LLOG(log_dsap, LLOG_EXCEPTIONS, ("Global di_block wasn't on global list"));
280 }
281 else
282 {
283 (*di_p)=di->di_next;
284 }
285 }
286
287 DLOG(log_dsap, LLOG_DEBUG, ("dsa_info_result_wakeup - dealt with global block"));
288
289 for(di = on->on_wake_list->di_wake_next; di != NULL_DI_BLOCK; di = next_di)
290 {
291 next_di = di->di_wake_next;
292 di->di_state = DI_COMPLETE;
293 di->di_entry = di_ent;
294 di_ent->e_refcount++;
295
296 switch(di->di_type)
297 {
298 case DI_OPERATION:
299 if (di->di_oper == NULLOPER) {
300 di_free (di);
301 break;
302 }
303 if(di->di_oper->on_state == ON_DEFERRED)
304 {
305 if (oper_chain(di->di_oper) != OK) {
306 LLOG (log_dsap,LLOG_EXCEPTIONS, ("oper_chain failed in dsa_info_wakeup"));
307 di_free(di);
308 }
309 }
310 break;
311
312 case DI_TASK:
313 task_dsa_info_wakeup(di);
314 di_free(di);
315 break;
316
317 default:
318 LLOG(log_dsap, LLOG_EXCEPTIONS, ("get_dsa_info_aux - unknown di-type %d",di->di_type));
319 oper_extract(on);
320 return;
321 }
322 }
323
324 DLOG(log_dsap, LLOG_DEBUG, ("dsa_info_result_wakeup - woke all blocks"));
325
326 /*
327 * Everthing should have been woken up by now so the di_blocks on
328 * the wake list and the operation itself can be extracted.
329 */
330 di_free(on->on_wake_list);
331
332 oper_extract(on);
333}
334
335dsa_info_error_wakeup(on)
336struct oper_act * on;
337{
338struct DSError * err = &(on->on_resp.di_error.de_err);
339struct di_block * di;
340
341 /*
342 * Error can fall into 3 categories:
343 * 1) Problem with remote DSA performing operation - try another;
344 * 2) A referral error - follow the referral;
345 * 3) An error with the operation itself;
346 */
347
348 switch(err->dse_type)
349 {
350 case DSE_NOERROR:
351 LLOG(log_dsap, LLOG_NOTICE, ("dsa_info_error_wakeup - No Error!"));
352 dsa_info_fail_wakeup(on);
353 return;
354 case DSE_REFERRAL:
355 LLOG(log_dsap, LLOG_NOTICE, ("dsa_info_error_wakeup - DAP Referral!"));
356 case DSE_DSAREFERRAL:
357 if(oper_rechain(on) == OK)
358 return;
359 /* Fall through */
360 default:
361 DLOG(log_dsap, LLOG_DEBUG, ("dsa_info_error_wakeup - Assuming all non-referral errors are to be propogated"));
362 /* Lose the di_block */
363 for(di=on->on_wake_list; di!=NULL_DI_BLOCK; di=di->di_wake_next)
364 {
365 switch(di->di_type)
366 {
367 case DI_OPERATION:
368 LLOG(log_dsap, LLOG_EXCEPTIONS, ("Should wake oper"));
369 oper_log(di->di_oper);
370 break;
371 case DI_TASK:
372 LLOG(log_dsap, LLOG_EXCEPTIONS, ("Should wake task"));
373 task_log(di->di_task);
374 break;
375 case DI_GLOBAL:
376 LLOG(log_dsap, LLOG_EXCEPTIONS, ("Should wake global"));
377 break;
378 default:
379 LLOG(log_dsap, LLOG_EXCEPTIONS, ("dsa_info_error_wakeup - invalid di_type"));
380 break;
381 }
382 }
383 return;
384 }
385}
386
387
388dsa_info_fail_wakeup(on)
389struct oper_act * on;
390{
391 /*
392 * Last attempt to get dsa info failed somehow.
393 * If there are any more "di_block"s to attempt it must be
394 * worth a go (perhaps this depends on the failure which
395 * has occurrred).
396 */
397 if (on -> on_resp.di_type == DI_ERROR) {
398 pslog (log_dsap,LLOG_EXCEPTIONS,"Remote dsainfo error",dn_print,
399 (caddr_t) on -> on_req.dca_dsarg.arg_rd.rda_object);
400 log_ds_error (& on -> on_resp.di_error.de_err);
401 }
402
403 if(on->on_dsas)
404 {
405 if(oper_chain(on) == OK)
406 return;
407 }
408
409 if(on->on_dsas)
410 {
411 /* oper_chain must be awaiting deferred di_blocks */
412 return;
413 }
414
415 /*
416 * There is nowhere left to chain this operation to so no way to get
417 * the dsa info required. Walk through the wake up list extracting,
418 * waking things up and tidying up afterwords.
419 */
420}
421
422char * get_entry_passwd (as)
423Attr_Sequence as;
424{
425extern AttributeType at_password;
426Attr_Sequence at;
427
428 if ((at = as_find_type (as,at_password)) == NULLATTR)
429 return (NULLCP);
430
431 if (at->attr_value == NULLAV)
432 return (NULLCP);
433
434 if (at->attr_value->avseq_av.av_struct == NULL)
435 return (NULLCP);
436
437 return( (char *)at->attr_value->avseq_av.av_struct);
438
439}
440
441make_dsa_bind_arg (arg)
442struct ds_bind_arg *arg;
443{
444#ifdef NEXT_VERSION
445Entry my_entry;
446char * passwd;
447
448 arg->dba_version = DBA_VERSION_V1988;
449 arg->dba_auth_type = DBA_AUTH_SIMPLE;
450 arg->dba_time1 = NULLCP;
451 arg->dba_time2 = NULLCP;
452
453 if ((my_entry = local_find_entry (mydsadn ,TRUE)) == NULLENTRY) {
454 arg->dba_dn = NULLDN;
455 arg->dba_auth_type = DBA_AUTH_NONE;
456 arg->dba_passwd[0] = 0;
457 arg->dba_passwd_len = 0;
458 } else {
459 arg->dba_dn = dn_cpy(mydsadn);
460 if ( (passwd = get_entry_passwd(my_entry->e_attributes)) != NULLCP) {
461 (void) strncpy (arg->dba_passwd,passwd,DBA_MAX_PASSWD_LEN);
462 arg->dba_passwd_len = strlen (passwd);
463 } else {
464 arg->dba_auth_type = DBA_AUTH_NONE;
465 arg->dba_passwd[0] = 0;
466 arg->dba_passwd_len = 0;
467 }
468 }
469#else
470 arg->dba_version = DBA_VERSION_V1988;
471 arg->dba_auth_type = DBA_AUTH_SIMPLE;
472 arg->dba_time1 = NULLCP;
473 arg->dba_time2 = NULLCP;
474 arg->dba_passwd[0] = 0;
475 arg->dba_passwd_len = 0;
476 arg->dba_dn = dn_cpy(mydsadn);
477#endif
478}
479
480struct oper_act * make_get_dsa_info_op(dn, di)
481DN dn;
482struct di_block * di;
483{
484struct di_block * di_tmp;
485struct oper_act * on_tmp;
486struct ds_read_arg * arg;
487
488 DLOG(log_dsap, LLOG_TRACE, ("make_get_dsa_info_op"));
489
490 if((on_tmp = oper_alloc()) == NULLOPER)
491 {
492 LLOG(log_dsap, LLOG_EXCEPTIONS, ("make_get_dsa_info_op - out of memory"));
493 return(NULLOPER);
494 }
495
496 on_tmp->on_type = ON_TYPE_GET_DSA_INFO;
497 on_tmp->on_arg = &(on_tmp->on_req);
498 set_my_chain_args(&(on_tmp->on_req.dca_charg), dn);
499
500 on_tmp->on_req.dca_dsarg.arg_type = OP_READ;
501 arg = &(on_tmp->on_req.dca_dsarg.arg_rd);
502
503 set_my_common_args(&(arg->rda_common));
504 arg->rda_common.ca_servicecontrol.svc_prio = SVC_PRIO_HIGH;
505
506 arg->rda_object = dn_cpy(dn); /* The important bit */
507 arg->rda_eis.eis_allattributes = TRUE;
508 arg->rda_eis.eis_select = NULLATTR;
509 arg->rda_eis.eis_infotypes = EIS_ATTRIBUTESANDVALUES;
510
511 on_tmp->on_dsas = di;
512 for(di_tmp=di; di_tmp!=NULL_DI_BLOCK; di_tmp=di_tmp->di_next)
513 {
514 di_tmp->di_type = DI_OPERATION;
515 di_tmp->di_oper = on_tmp;
516 }
517
518 return(on_tmp);
519}
520
521set_my_chain_args(cha, dn)
522struct chain_arg * cha;
523DN dn;
524{
525 cha->cha_originator = dn_cpy(mydsadn);
526 cha->cha_target = dn_cpy(dn);
527 cha->cha_progress.op_resolution_phase = OP_PHASE_NOTSTARTED;
528 cha->cha_progress.op_nextrdntoberesolved = OP_PHASE_NOTDEFINED;
529 cha->cha_trace = NULLTRACEINFO;
530 cha->cha_aliasderef = 0;
531 cha->cha_aliasedrdns = 0;
532 cha->cha_returnrefs = FALSE;
533 cha->cha_reftype = RT_SUBORDINATE;
534 cha->cha_domaininfo = NULLPE;
535 cha->cha_timelimit = NULLCP;
536}
537
538set_my_common_args(ca)
539struct common_args * ca;
540{
541 ca->ca_servicecontrol.svc_options = SVC_OPT_PREFERCHAIN;
542 ca->ca_servicecontrol.svc_prio = SVC_PRIO_HIGH;
543 ca->ca_servicecontrol.svc_timelimit = SVC_NOTIMELIMIT;
544 ca->ca_servicecontrol.svc_sizelimit = SVC_NOSIZELIMIT;
545 ca->ca_servicecontrol.svc_scopeofreferral = SVC_REFSCOPE_NONE;
546 ca->ca_requestor = dn_cpy(mydsadn);
547 ca->ca_progress.op_resolution_phase = OP_PHASE_NOTSTARTED;
548 ca->ca_progress.op_nextrdntoberesolved = OP_PHASE_NOTDEFINED;
549 ca->ca_aliased_rdns = CA_NO_ALIASDEREFERENCED;
550 ca->ca_security = (struct security_parms *) NULL;
551 ca->ca_sig = (struct signature *) NULL;
552 ca->ca_extensions = (struct extension *) NULL;
553}
554
555quipu_ctx_supported (ptr)
556Entry ptr;
557{
558AV_Sequence avs;
559Attr_Sequence as;
560extern OID quipu_dsa_oid;
561extern AttributeType at_applctx;
562char dap_only = TRUE;
563char res = 1;
564static OID dsp = NULLOID;
565static OID quipu_dsp = NULLOID;
566
567 /* return 0 if "ptr" is not a quipu DSA */
568 /* return 1 if "ptr" represents a quipu_dsa (by objectclass) */
569 /* return 2 if "ptr" represents a quipu_dsa with quipu context */
570 /* return -1 if "ptr" represents a DAP only DSA */
571
572 /* Should we use QuipuDSP to a non-Quipu DSA, if is claims
573 * to support it - currently implemented as "NO" ?
574 */
575
576 if (!check_in_oc (quipu_dsa_oid,ptr->e_oc))
577 res = 0; /* not a Quipu DSA */
578
579 if (( as = entry_find_type (ptr,at_applctx)) == NULLATTR)
580 return 1;
581
582 if (dsp == NULLOID) {
583 /* will both be null first time around... */
584 dsp = oid_cpy (DIR_SYSTEM_AC);
585 quipu_dsp = oid_cpy (DIR_QUIPU_AC);
586 }
587
588 for (avs=as->attr_value; avs != NULLAV; avs=avs->avseq_next) {
589 if ((res != 0) && (oid_cmp ((OID)avs->avseq_av.av_struct, quipu_dsp) == 0 ))
590 return 2;
591 if (oid_cmp ((OID)avs->avseq_av.av_struct, dsp) == 0 )
592 dap_only = FALSE;
593 }
594
595 if (dap_only)
596 return -1;
597
598 return res;
599}
600
601
602quipu_version_7(eptr)
603Entry eptr;
604{
605char * p, *t, *s;
606int res, vrsn;
607char * v;
608
609 /* return true is the string suggests quipu version 6.8 or more */
610
611 /* Format of string is typically...
612 * quipu 6.8 #69 (trellis) of Thu Nov 15 15:58:24 GMT 1990
613 */
614
615 if (!eptr || !eptr->e_dsainfo)
616 return FALSE;
617
618 if (((v = eptr->e_dsainfo->dsa_version) == NULLCP) ||
619 ((p = index (v,' ')) == NULLCP ) ||
620 ((t = index (p,'.')) == NULLCP ))
621 return FALSE;
622
623 if ((s = index (t,' ')) != NULLCP )
624 *s = 0;
625
626 *p++ = 0;
627 *t++ = 0;
628
629 vrsn = ( atoi (p) * 10 ) + atoi (t);
630
631 if ((strcmp (v,"quipu") == 0) && (vrsn >= 68))
632 res = TRUE;
633 else
634 res = FALSE;
635
636 *--p = ' ';
637 *--t = '.';
638
639 if (s)
640 *s = ' ';
641
642 return res;
643}