/* dased.c - stand-alone DASE */
static char *rcsid
= "$Header: /f/osi/acsap/RCS/dased.c,v 7.9 91/02/22 09:14:33 mrose Interim $";
* $Header: /f/osi/acsap/RCS/dased.c,v 7.9 91/02/22 09:14:33 mrose Interim $
* Revision 7.9 91/02/22 09:14:33 mrose
* Revision 7.8 91/01/07 12:39:44 mrose
* Revision 7.7 90/12/23 18:39:06 mrose
* Revision 7.6 90/12/17 22:12:53 mrose
* Revision 7.5 90/12/11 10:52:08 mrose
* Revision 7.4 90/11/04 19:14:45 mrose
* Revision 7.3 90/10/29 18:37:57 mrose
* Revision 7.2 90/07/27 08:41:41 mrose
* Revision 7.1 90/07/09 14:30:57 mrose
* Revision 7.0 90/07/07 16:11:31 mrose
* *** empty log message ***
* Acquisition, use, and distribution of this module and related
* materials are subject to the restrictions of a license agreement.
* Consult the Preface in the User's Manual for the full terms of
static int nbits
= FD_SETSIZE
;
"dased.log", NULLCP
, NULLCP
,
LLOG_FATAL
| LLOG_EXCEPTIONS
| LLOG_NOTICE
, LLOG_FATAL
,
-1, LLOGCLS
| LLOGCRT
| LLOGZER
, NOTOK
static LLog
*pgm_log
= &_pgm_log
;
static char *pgmname
= "dased";
static struct TSAPaddr tas
;
static char passwd
[DBA_MAX_PASSWD_LEN
];
DNS
dase_interact (), just_say_no ();
void adios (), advise (), ts_adios (), ts_advise ();
struct TSAPdisconnect tds
;
register struct TSAPdisconnect
*td
= &tds
;
advise (LLOG_NOTICE
, NULLCP
, "listening on %s", taddr2str (&tas
));
if (TNetListen (&tas
, td
) == NOTOK
)
ts_adios (td
, "TNetListen failed");
nfds
= 0, rfds
= NULLFD
, secs
= prebind
? 5 * 60L : NOTOK
;
if (TNetAcceptAux (&vecp
, vec
, NULLIP
, NULLTA
, nfds
, rfds
, NULLFD
,
NULLFD
, secs
, td
) == NOTOK
) {
ts_advise (td
, LLOG_EXCEPTIONS
, "TNetAccept failed");
if (rfds
&& FD_ISSET (dsap_ad
, rfds
)) { /* DSA timed us out... */
advise (LLOG_DEBUG
, NULLCP
, "unbound from directory");
switch (TNetFork (vecp
, vec
, td
)) {
ll_hdinit (pgm_log
, pgmname
);
ts_advise (td
, LLOG_EXCEPTIONS
, "TNetFork failed");
(void) close (dsap_ad
), dsap_ad
= NOTOK
;
register struct TSAPstart
*ts
= &tss
;
struct TSAPdisconnect tds
;
register struct TSAPdisconnect
*td
= &tds
;
if (TInit (vecp
, vec
, ts
, td
) == NOTOK
)
ts_adios (td
, "T-CONNECT.INDICATION failed");
advise (LLOG_NOTICE
, NULLCP
, "T-CONNECT.INDICATION: <%d, %s, %s, %d, %d>",
ts
-> ts_sd
, taddr2str (&ts
-> ts_calling
),
taddr2str (&ts
-> ts_called
), ts
-> ts_expedited
,
if (TConnResponse (sd
, NULLTA
, 0, NULLCP
, 0, NULLQOS
, td
) == NOTOK
)
ts_adios (td
, "T-CONNECT.RESPONSE failed");
if ((ps
= ps_alloc (dg_open
)) == NULLPS
)
adios (NULLCP
, "ps_alloc: out of memory");
if (dg_setup (ps
, sd
, MAXDGRAM
, ts_read
, ts_write
, NULLIFP
) == NOTOK
)
adios (NULLCP
, "dg_setup: %s", ps_error (ps
-> ps_errno
));
struct type_DASE_Query__REQ
*req
;
if ((pe
= ps2pe (ps
)) == NULLPE
) {
if (ps
-> ps_errno
== PS_ERR_NONE
) {
advise (LLOG_NOTICE
, NULLCP
, "T-DISCONNECT.INDICATION");
adios (NULLCP
, "ps2pe: %s", ps_error (ps
-> ps_errno
));
if (decode_DASE_Query__REQ (pe
, 1, NULLIP
, NULLVP
, &req
) == NOTOK
)
adios (NULLCP
, "decode_DASE_Query__REQ: %s", PY_pepy
);
PLOGP (pgm_log
,DASE_Message
, pe
, "message", 1);
free_DASE_Query__REQ (req
);
advise (LLOG_DEBUG
, NULLCP
, "unbound from directory");
register struct type_DASE_Query__REQ
*req
;
register struct type_DASE_Query__RSP
*rsp
;
register struct element_DASE_0
*d0
;
register struct element_DASE_1
*d1
;
if ((rsp
= (struct type_DASE_Query__RSP
*) calloc (1, sizeof *rsp
))
adios (NULLCP
, "out of memory");
vec
= NULL
, el
= NULL
, context
= NULL
, dns
= NULL
;
for (d0
= req
-> name
; d0
; d0
= d0
-> next
)
if ((vec
= (char **) calloc ((unsigned) i
, sizeof *vec
)) == NULL
)
for (vp
= vec
, d0
= req
-> name
; d0
; vp
++, d0
= d0
-> next
)
if ((*vp
= qb2str (d0
-> IA5String
)) == NULL
)
advise (LLOG_NOTICE
, NULLCP
, "lookup: %s", *vp
);
for (d1
= req
-> envlist
; d1
; d1
= d1
-> next
) {
struct type_DASE_Environment
*ev
= d1
-> Environment
;
register struct element_DASE_2
*d2
;
register struct dn_seq
**dp
;
if ((en
= (envlist
) calloc (1, sizeof *en
)) == NULL
)
*ep
= en
, ep
= &en
-> Next
;
en
-> Upper
= ev
-> upper
;
en
-> Lower
= ev
-> lower
;
for (d2
= ev
-> path
; d2
; d2
= d2
-> next
) {
register struct dn_seq
*ds
;
if ((ds
= (struct dn_seq
*) calloc (1, sizeof *ds
)) == NULL
)
*dp
= ds
, dp
= &ds
-> dns_next
;
if ((cp
= qb2str (d2
-> IA5String
)) == NULL
)
ds
-> dns_dn
= str2dn (cp
);
if (*cp
!= '-' && ds
-> dns_dn
== NULLDN
) {
PY_advise (NULLCP
, "bad DN in environment (%s)", cp
);
if ((context
= qb2str (req
-> context
)) == NULL
)
advise (LLOG_NOTICE
, NULLCP
, "context: %s", context
);
if ((cp
= qb2str (req
-> userdn
)) == NULL
)
advise (LLOG_NOTICE
, NULLCP
, "userdn: %s", cp
);
if ((newdn
= str2dn (*cp
!= '@' ? cp
: cp
+ 1)) == NULLDN
) {
PY_advise (NULLCP
, "bad DN for userdn (%s)", cp
);
if (!userdn
|| dn_cmp (userdn
, newdn
))
if ((cp
= qb2str (req
-> passwd
)) == NULL
)
(void) strcpy (passwd
, cp
);
if (isbound
&& changed
) {
if (!isbound
&& bind_to_dsa () == NOTOK
)
if (vecp
== 1 && *vec
[0] == '@') {
if ((dnstat
= str2dn (vec
[0])) == NULLDN
) {
PY_advise (NULLCP
, "invalid name");
rsp
-> value
= name2psap (*(dn
= &dnstat
));
if (!aet_match (vecp
, vec
, req
-> interactive
? dase_interact
PY_advise (NULLCP
, "unable to resolve name");
PY_advise (NULLCP
, "search failed to find anything");
(void) dnSelect (vec
[0], &dns
, dase_interact
, el
-> Dns
);
for (; dns
; dns
= dns
-> dns_next
) {
if (rsp
-> value
= name2psap (*dn
))
rsp
-> value
= name2psap (*dn
);
(void) encode_IF_DistinguishedName (&rsp
-> name
, 1, NULL
, NULLCP
,*dn
);
advise (LLOG_NOTICE
, NULLCP
, "answer: %s", dn2str (*dn
));
ufn_dn_print_aux (nps
, *dn
, NULLDN
, 0);
*--nps
-> ps_ptr
= NULL
, nps
-> ps_cnt
++;
rsp
-> friendly
= str2qb (nps
-> ps_base
, strlen (nps
-> ps_base
), 1);
nps
-> ps_ptr
= nps
-> ps_base
, nps
-> ps_cnt
= nps
-> ps_bufsiz
;
advise (LLOG_NOTICE
, NULLCP
, "diagnostic: %s", PY_pepy
);
if ((rsp
-> diagnostic
= str2qb (PY_pepy
, strlen (PY_pepy
), 1))
if (encode_DASE_Query__RSP (&pe
, 1, NULL
, NULLCP
, rsp
) == NOTOK
)
adios (NULLCP
, "encode_DASE_Query__RSP: %s", PY_pepy
);
if (pe2ps (ps
, pe
) == NOTOK
)
adios (NULLCP
, "pe2ps: %s", ps_error (ps
-> ps_errno
));
PLOGP (pgm_log
,DASE_Message
, pe
, "message", 0);
free_DASE_Query__RSP (rsp
);
for (vp
= vec
; *vp
; vp
++)
static int very_first_time
= 1;
advise (LLOG_DEBUG
, NULLCP
, "unbound from directory");
make_bind_args (&ba
, &br
, &be
);
if (ds_bind (&ba
, &be
, &br
) == DS_OK
) {
advise (LLOG_DEBUG
, NULLCP
, "bound to directory");
PY_advise (NULLCP
, "unable to bind to directory (%s)",
be
.dbe_type
== DBE_TYPE_SECURITY
? "security error"
if (prebind
&& very_first_time
)
advise (LLOG_EXCEPTIONS
, NULLCP
, "%s", PY_pepy
);
static int make_bind_args (ba
, br
, be
)
register struct ds_bind_arg
*ba
,
register struct ds_bind_error
*be
;
bzero ((char *) ba
, sizeof *ba
);
bzero ((char *) br
, sizeof *br
);
bzero ((char *) be
, sizeof *be
);
ba
-> dba_version
= DBA_VERSION_V1988
;
if (ba
-> dba_dn
= userdn
)
ba
-> dba_auth_type
= DBA_AUTH_SIMPLE
;
if (ba
-> dba_passwd_len
= strlen (passwd
))
(void) strcpy (ba
-> dba_passwd
, passwd
);
static DNS
dase_interact (dns
, dn
, s
)
register struct type_DASE_Callback__REQ
*req
= NULL
;
register struct element_DASE_3
**dp
;
struct type_DASE_Callback__RSP
*rsp
= NULL
;
register struct type_DASE_Callback__RSP
*rp
;
for (ds
= dns
; ds
; ds
= ds
-> dns_next
)
if (base
= (struct dn_seq
**) malloc ((unsigned) (i
* sizeof *base
))) {
for (ds
= dns
; ds
; ds
= ds
-> dns_next
)
qsort ((char *) base
, i
, sizeof *base
, dns_compar
);
if ((req
= (struct type_DASE_Callback__REQ
*) calloc (1, sizeof *req
))
advise (LLOG_EXCEPTIONS
, NULLCP
, "out of memory");
free_DASE_Callback__REQ (req
);
free_DASE_Callback__RSP (rsp
);
if ((req
-> string
= str2qb (s
, strlen (s
), 1)) == NULL
)
register struct element_DASE_3
*d3
;
register struct type_DASE_Pair
*pair
;
if ((d3
= (struct element_DASE_3
*) calloc (1, sizeof *d3
)) == NULL
)
*dp
= d3
, dp
= &d3
-> next
;
if ((pair
= (struct type_DASE_Pair
*) calloc (1, sizeof *pair
))
dn_print (nps
, dns
-> dns_dn
, EDBOUT
);
*--nps
-> ps_ptr
= NULL
, nps
-> ps_cnt
++;
pair
-> complete
= str2qb (nps
-> ps_base
, strlen (nps
-> ps_base
), 1);
nps
-> ps_ptr
= nps
-> ps_base
, nps
-> ps_cnt
= nps
-> ps_bufsiz
;
ufn_dn_print_aux (nps
, dns
-> dns_dn
, dn
, 0);
*--nps
-> ps_ptr
= NULL
, nps
-> ps_cnt
++;
pair
-> friendly
= str2qb (nps
-> ps_base
, strlen (nps
-> ps_base
), 1);
nps
-> ps_ptr
= nps
-> ps_base
, nps
-> ps_cnt
= nps
-> ps_bufsiz
;
if (pair
-> complete
== NULL
|| pair
-> friendly
== NULL
)
if (encode_DASE_Callback__REQ (&pe
, 1, NULL
, NULLCP
, req
) == NOTOK
) {
advise (LLOG_EXCEPTIONS
, NULLCP
, "encode_DASE_Callback__REQ: %s",
if (pe2ps (ps
, pe
) == NOTOK
)
adios (NULLCP
, "pe2ps: %s", ps_error (ps
-> ps_errno
));
PLOGP (pgm_log
,DASE_Message
, pe
, "message", 0);
free_DASE_Callback__REQ (req
);
if ((pe
= ps2pe (ps
)) == NULLPE
)
adios (NULLCP
, "ps2pe: %s", ps_error (ps
-> ps_errno
));
if (decode_DASE_Callback__RSP (pe
, 1, NULLIP
, NULLVP
, &rsp
) == NOTOK
) {
advise (LLOG_EXCEPTIONS
, NULLCP
, "decode_DASE_Callback__RSP: %s",
PLOGP (pgm_log
,DASE_Message
, pe
, "message", 1);
for (rp
= rsp
; rp
; rp
= rp
-> next
) {
if ((ds
= (struct dn_seq
*) calloc (1, sizeof *ds
)) == NULL
)
*dq
= ds
, dq
= &ds
-> dns_next
;
if ((cp
= qb2str (rp
-> IA5String
)) == NULL
)
ds
-> dns_dn
= str2dn (cp
);
free_DASE_Callback__RSP (rsp
);
static int dns_compar (a
, b
)
for (adn
= (*a
) -> dns_dn
; adn
-> dn_parent
; adn
= adn
-> dn_parent
)
for (bdn
= (*b
) -> dns_dn
; bdn
-> dn_parent
; bdn
= bdn
-> dn_parent
)
i
= rdn_cmp (adn
-> dn_rdn
, bdn
-> dn_rdn
);
return (i
== (-1) || i
== 1 ? i
: 0);
static DNS
just_say_no (dns
, dn
, s
)
static struct ds_read_arg read_arg
=
NULLDN
, /* read_arg DN */
{ /* entry info selection */
struct ds_read_result result
;
if ((at
= AttrT_new (DSAADDRESS_OID
)) == NULLAttrT
) {
PY_advise (NULLCP
, "build of attribute failed (%s)", DSAADDRESS_OID
);
read_arg
.rda_common
.ca_servicecontrol
.svc_prio
= SVC_PRIO_HIGH
;
read_arg
.rda_object
= dn
;
read_arg
.rda_eis
.eis_select
= as_comp_new (AttrT_cpy (at
), NULLAV
,
i
= ds_read (&read_arg
, &error
, &result
);
as_free (read_arg
.rda_eis
.eis_select
);
PY_advise (NULLCP
, "DAP lookup failed (%s)", dn2str (dn
));
if (result
.rdr_entry
.ent_attr
== NULLATTR
) {
PY_advise (NULLCP
, "no '%s' attribute in entry '%s'",
DSAADDRESS_OID
, dn2str (dn
));
pe
= grab_pe (&result
.rdr_entry
.ent_attr
-> attr_value
-> avseq_av
);
as_free (result
.rdr_entry
.ent_attr
);
register struct TSAPaddr
*ta
= NULL
;
if (pgmname
= rindex (*vec
, '/'))
if (pgmname
== NULL
|| *pgmname
== NULL
)
isodetailor (pgmname
, 0);
ll_hdinit (pgm_log
, pgmname
);
for (argptr
= vec
, argptr
++; ap
= *argptr
; argptr
++) {
if ((ap
= *++argptr
) == NULL
|| *ap
== '-')
if ((ap
= *++argptr
) == NULL
|| *ap
== '-')
dsap_init (&argp
, (argptr
= args
, &argptr
));
userdn
= NULLDN
, passwd
[0] = NULL
;
for (vec
++; ap
= *vec
; vec
++) {
if ((ap
= *++vec
) == NULL
|| *ap
== '-')
adios (NULLCP
, "usage: %s -a address", pgmname
);
if ((ta
= str2taddr (ap
)) == NULLTA
)
adios (NULLCP
, "bad address \"%s\"", ap
);
if ((ap
= *++vec
) == NULL
|| *ap
== '-')
adios (NULLCP
, "usage: %s -c DSA-name-or-address",
if ((ap
= *++vec
) == NULL
|| *ap
== '-')
adios (NULLCP
, "usage: %s -u username", pgmname
);
if ((userdn
= str2dn (*ap
!= '@' ? ap
: ap
+ 1)) == NULLDN
)
adios (NULLCP
, "invalid DN for username: %s", ap
);
bzero ((char *) ap
, strlen (ap
));
if ((ap
= *++vec
) == NULL
|| *ap
== '-')
adios (NULLCP
, "usage: %s -p passwd", pgmname
);
(void) strcpy (passwd
, ap
);
bzero ((char *) ap
, strlen (ap
));
adios (NULLCP
, "unknown switch -%s", ap
);
adios (NULLCP
, "usage: %s [switches]", pgmname
);
if (ta
== NULL
&& (ta
= str2taddr (ns_address
)) == NULLTA
)
adios (NULLCP
, "bad default address \"%s\"", ns_address
);
tas
= *ta
; /* struct copy */
if ((nps
= ps_alloc (str_open
)) == NULLPS
)
adios (NULLCP
, "ps_alloc: out of memory");
if (str_setup (nps
, NULLCP
, 0, 0) == NOTOK
)
adios (NULLCP
, "str_setup: %s", ps_error (ps
-> ps_errno
));
nbits
= getdtablesize ();
if (debug
== 0 && !(debug
= isatty (2))) {
for (i
= 0; i
< 5; i
++) {
if ((sd
= open ("/dev/null", O_RDWR
)) == NOTOK
)
adios ("/dev/null", "unable to read");
(void) dup2 (sd
, 0), (void) close (sd
);
advise (LLOG_EXCEPTIONS
, "failed", "setsid");
if ((sd
= open ("/dev/tty", O_RDWR
)) != NOTOK
) {
(void) ioctl (sd
, TIOCNOTTY
, NULLCP
);
(void) signal (SIGINT
, SIG_IGN
);
(void) signal (SIGQUIT
, SIG_IGN
);
ll_dbinit (pgm_log
, pgmname
);
#ifndef sun /* damn YP... */
for (sd
= 3; sd
< nbits
; sd
++)
if (pgm_log
-> ll_fd
!= sd
)
(void) signal (SIGPIPE
, SIG_IGN
);
ll_hdinit (pgm_log
, pgmname
);
advise (LLOG_NOTICE
, NULLCP
, "starting");
static void adios (va_alist
)
_ll_log (pgm_log
, LLOG_FATAL
, ap
);
static void adios (what
, fmt
)
static void advise (va_alist
)
_ll_log (pgm_log
, code
, ap
);
static void advise (code
, what
, fmt
)
advise (code
, what
, fmt
);
static void ts_adios (td
, event
)
register struct TSAPdisconnect
*td
;
ts_advise (td
, LLOG_EXCEPTIONS
, event
);
static void ts_advise (td
, code
, event
)
register struct TSAPdisconnect
*td
;
(void) sprintf (buffer
, "[%s] %*.*s",
TErrString (td
-> td_reason
),
td
-> td_cc
, td
-> td_cc
, td
-> td_data
);
(void) sprintf (buffer
, "[%s]", TErrString (td
-> td_reason
));
advise (code
, NULLCP
, "%s: %s", event
, buffer
);