Ejemplo n.º 1
0
static 
dased (int vecp, char **vec)
{
	int	    sd;
	struct TSAPstart tss;
	struct TSAPstart *ts = &tss;
	struct TSAPdisconnect   tds;
	struct TSAPdisconnect  *td = &tds;

	if (TInit (vecp, vec, ts, td) == NOTOK)
		ts_adios (td, "T-CONNECT.INDICATION failed");

	sd = ts -> ts_sd;
	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,
			ts -> ts_tsdusize);

	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));

	for (;;) {
		struct type_DASE_Query__REQ *req;
		PE	pe;

		if ((pe = ps2pe (ps)) == NULLPE) {
			if (ps -> ps_errno == PS_ERR_NONE) {
				advise (LLOG_NOTICE, NULLCP, "T-DISCONNECT.INDICATION");
				break;
			} else
				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);

		dase_aux (req);

		free_DASE_Query__REQ (req);
		pe_free (pe);
	}

	if (isbound) {
		if (debug)
			advise (LLOG_DEBUG, NULLCP, "unbound from directory");

		 ds_unbind ();
		isbound = 0;
	}

	exit (0);
}
Ejemplo n.º 2
0
void 
quit (int sig)
{
	 ds_unbind();
	exit(sig);
}
Ejemplo n.º 3
0
main()
{
	struct  passwd  *pw_entry ;
	struct  passwd  *getpwuid() ;
	struct	stat	buf ;

	int	i = 1 ;
	int     uid ;
	int	um ;
	char	pass1[LINESIZE] ;
	char	pass2[LINESIZE] ;
	char	Read_in_Stuff[LINESIZE] ;
	char	**vecptr ;
	char 	*tmpdraft ;
	char	home_dir[LINESIZE] ;
	char	*p, *part1, *part2 ;
	char	quipurc_file[100] ;
	char	tailor_file[100] ;
	char	user_name[9] ;
	char	*localptr = Local ;
	char	print_format = EDBOUT ;
	EntryInfo	*ptr ;
	static  CommonArgs ca = default_common_args;
	
	vecptr = (char **) malloc(100) ;
	vecptr[0] = malloc (LINESIZE) ;
	(void) strcpy(vecptr[0], "showentry") ;
	(void) strcpy(pass1, "x") ;
	(void) strcpy(pass2, "y") ;
	tmpdraft = malloc (LINESIZE) ;
	(void) strcpy(tmpdraft, "/tmp/dish-") ;

	if ((opt = ps_alloc (std_open)) == NULLPS)
		fatal (-62, "ps_alloc failed");
	if (std_setup (opt, stderr) == NOTOK)
		fatal (-63, "std_setup failed");
	if ((rps = ps_alloc (std_open)) == NULLPS)
		fatal (-64, "ps_alloc 2 failed");
	if (std_setup (rps, stdout) == NOTOK)
		fatal (-65, "std_setup 2 failed");
	(void) strcpy(filterstring, "userid=") ;

	/* Sort out files, userids etc. */
	uid=getuid() ;
	if ((pw_entry=getpwuid(uid)) == 0)
	{
		ps_printf(rps, "Who are you? (no name for your uid number)\n") ;
		exit(1) ;
	}
	(void) strcpy(user_name, pw_entry->pw_name) ;
	(void) strcat(tmpdraft, user_name) ;

	if (getenv("HOME") == 0) 
	{
		ps_printf(rps, "No home directory?!!") ;
		(void) strcpy(home_dir, pw_entry->pw_dir) ;
	}
	else
	{
		(void) strcpy(home_dir, getenv("HOME")) ;
	}

	(void) strcpy(quipurc_file, home_dir) ;
	(void) strcat(quipurc_file, "/.quipurc") ;

	(void) strcpy(tailor_file, isodefile ("dishinit", 1));

	Manager[0] = 0;
	Password[0] = 0;
	Local[0] = 0;

	(void) stat(tailor_file, &buf) ;
	(void) seteuid(buf.st_uid) ;	/* set effective to enable */
					/* us to read protected file */

	if ((fp_tailor = fopen(tailor_file, "r")) == 0)
	{
		ps_print(rps, "Can't open Tailor File. Abort.\n") ;
		exit(1) ;
	}

	while (fgets (Read_in_Stuff, LINESIZE, fp_tailor) != 0)
	{
		if (!strcmp(Read_in_Stuff, "##Anything after this line is copied into the users ~/.quipurc file\n"))
		{
			break ;
		}

		p = SkipSpace (Read_in_Stuff);
		if (( *p == '#') || (*p == '\0'))
			continue;  		/* ignore comments and blanks */

		part1 = p;
		if ((part2 = index (p,':')) == NULLCP) {
			ps_printf (opt,"Seperator missing '%s'. Ignoring..\n",p);
		}

		*part2++ = '\0';
		part2 = TidyString (part2);

		if (lexequ(part1, "manager") == 0)
		{
			(void) strcpy(Manager, part2) ;
		}
		else
		if (lexequ(part1, "password") == 0)
		{
			(void) strcpy(Password, part2) ;
		}
		else
		if (lexequ(part1, "local") == 0)
		{
			(void) strcpy(Local, part2) ;
		}
		else
		{
			ps_printf(rps, "Error in tailor. What's a %s?\n", part1) ;
		}

	}
	(void) setuid(uid) ;			/* Restore Userid to original user. */

/* create ~/.quipurc file. NB this does eradicate anything in there.
 * 			   (Theoretically nothing.) 
 */

	if (Manager[0] == 0) {
		ps_print(rps, "Can't find out the managers name\n") ;
		exit(1) ;
	}
	if (Password[0] == 0) {
		ps_print(rps, "Can't find out the managers password\n") ;
		exit(1) ;
	}
	if (Local[0] == 0) {
		ps_print(rps, "Can't find out where to search\n") ;
		exit(1) ;
	}

	um = umask(0177) ;
	if ((fp_quipurc = fopen(quipurc_file, "w")) == 0)
	{
		ps_printf(rps, "Can't open ~/.quipurc. Aborting..\n") ;
		exit(1) ;
	}
	(void) umask(um) ;	

	if ((fileps = ps_alloc(std_open)) == NULLPS)
	{
		fatal (-66, "ps_alloc 2 failed");
	}
	if (std_setup (fileps, fp_quipurc) == NOTOK)
	{
		fatal (-67, "std_setup 2 failed");
	}


	/* Sorting out the bind section */
	quipu_syntaxes() ;		/* set up the needed function pointers */
	dsap_init(&i, &vecptr) ;

	(void) strcpy(bindarg.dba_passwd, Password) ;
	bindarg.dba_version = DBA_VERSION_V1988;
	bindarg.dba_passwd_len = strlen(bindarg.dba_passwd) ;

	if ((bindarg.dba_dn = str2dn (Manager)) == NULLDN) 
	{
		ps_printf (opt,"Invalid Manager name %s (???!)\n",Manager) ;
		exit(1) ;
	}

	if (ds_bind (&bindarg, &binderr, &bindresult) != OK)
	{
		ps_printf(rps, "Can't bind as the manager.\n") ;
		exit(1);
	}
	/* Hopefully, should be successfully bound */

/*
 * We now call the search stuff with the right bits, to see if we can get a
 * match of uid='user_name'. Once there, we echo lots of information from
 * their entry out to the .quipurc file.
 * Hopefully there should only be one match. This assumes that ALL dir info
 * up to date, and that SG do not allow multiple users with the same login.
 */

/* set up the appropriate structures and defaults. */

	search_arg.sra_common = ca; /* struct copy */
	search_arg.sra_common.ca_servicecontrol.svc_sizelimit = 2 ;
	search_arg.sra_eis.eis_allattributes = FALSE ;
	search_arg.sra_searchaliases = FALSE;
	search_arg.sra_subset = SRA_ONELEVEL;
	search_arg.sra_eis.eis_infotypes = EIS_ATTRIBUTESANDVALUES ;
	search_arg.sra_eis.eis_select = NULLATTR ;
	search_arg.sra_eis.eis_allattributes = TRUE ;
	search_arg.sra_filter = filter_alloc() ;
		/* Default filter. */
		search_arg.sra_filter->flt_next = NULLFILTER;
		search_arg.sra_filter->flt_type = FILTER_ITEM;
		search_arg.sra_filter->FUFILT = NULLFILTER;
		

	if (*localptr == '@')
	{
		localptr++;
	}
	if ((search_arg.sra_baseobject = str2dn(localptr)) == NULLDN)
	{
		ps_printf (opt,"Invalid sequence in username %s.\n", localptr);
		exit(1) ;
	}

	(void) strcat(filterstring, user_name) ;

	search_arg.sra_filter->flt_un.flt_un_item.fi_type = FILTERITEM_EQUALITY ;

	if ((search_arg.sra_filter->flt_un.flt_un_item.fi_un.fi_un_ava.ava_type = AttrT_new ("userid")) == NULLAttrT)
	{
		ps_printf(rps, "Oops, userid is not a valid attr type. ABORT!!\n") ;
		exit(1) ;
	}
	if ((search_arg.sra_filter->flt_un.flt_un_item.fi_un.fi_un_ava.ava_value = str2AttrV (user_name, search_arg.sra_filter->flt_un.flt_un_item.fi_un.fi_un_ava.ava_type->oa_syntax)) == NULLAttrV)
	{
		ps_printf(rps, "%s is not a valid attribute value.\n", user_name) ;
	}

/* call search */
/* We now ought to be in the right place, and with the search stuff set,
 * ready to call search, and receive one (or no) entry back, which then 
 * gets processed accordingly.
 */

	if (ds_search (&search_arg, &search_error, &search_result) != DS_OK)
	{
		ps_printf(rps, "Search failed...\n") ;
		exit (1) ;
		/* This is not the same as coming back with */
		/* message "search failed to find anything. */
	}

/* If the user does not exist in the DIT, print out the limited .quipurc
 * and the warning message, and allow the user to play DISH.
 */

	if (search_result.CSR_entries == NULLENTRYINFO)
	{
		ps_printf(opt, "Unfortunately, you seem to have no entry in\n") ;
		ps_printf(opt, "the directory. Contact '%s' who should be able to help.\n", Manager) ;
		ps_printf(opt, "In the mean time, you can read, but not write.\n") ;
	}
	else
	{
		ptr = search_result.CSR_entries ;
		dn = dn_cpy(ptr->ent_dn) ;	/* Essence of move user_name. */

		/* collect the info and put it into current_entry */

		/* Set up the desired attribute type to be read*/
		/* from read.c */
		if ((at = AttrT_new ("userPassword")) != NULLAttrT) 
		{
			as_flag = as_merge (as_flag, as_comp_new (AttrT_cpy (at), NULLAV, NULLACL_INFO));
		}
		else
		{
			ps_printf(rps, "Oops, Serious error. unknown attribute type 'userPassword'.\n") ;
			exit(1) ;
		}

		if ((current_entry = local_find_entry (dn, FALSE)) == NULLENTRY)
		{	
			read_arg.rda_common = ca; /* struct copy */
			read_arg.rda_object = dn;
			read_arg.rda_eis.eis_infotypes = EIS_ATTRIBUTESANDVALUES;
			read_arg.rda_eis.eis_allattributes = TRUE ;
			read_arg.rda_eis.eis_select = NULLATTR ;

			if (ds_read (&read_arg, &read_error, &read_result) != DS_OK)
			{
				ps_printf(rps, "We even seem to be having problems reading\n" ) ;
				ps_printf(rps, "an entry we searched and found!! HELP!!\n") ;
				exit(1) ;
			}
			if (read_result.rdr_entry.ent_attr == NULLATTR)
			{
				ps_printf(rps, "No attributes present. Even though\n") ;
				ps_printf(rps, "we found you by userid attribute!!! HELP!!\n") ;
				exit (1) ;
			}
			cache_entry (&(read_result.rdr_entry), read_arg.rda_eis.eis_allattributes, TRUE) ;
		}

		if ((current_entry = local_find_entry (dn, FALSE)) == NULLENTRY)
		{
			ps_printf(rps, "We still have nothing.Even after reading? Abort.\n") ;
			exit(1) ;
		}

		ps_printf(fileps, "username: "******"\n") ;

		ps_printf(fileps, "me: ") ;
		dn_print(fileps, dn, EDBOUT) ;
		ps_printf(fileps, "\n") ;

		/* now showattribute -nokey to display it. */

		ps_printf(fileps, "password: "******"You need a password...\n") ;
				(void) strcpy(pass1, getpassword("Enter Password: "******"Re-enter password: "******"\nMismatch - Try again.\n") ;
				}
			}
			ps_printf(fileps, "%s\n", pass1) ;

			um = umask(0177) ;
			if ((fp_draft = fopen(tmpdraft, "w")) == 0)
			{
				ps_print(rps, "Can't open draft file... Abort.\n") ;
				exit(1) ;
			}
			(void) umask(um) ;

			(void) fprintf(fp_draft, "UserPassword = %s\n", pass1) ;
		 	(void) fprintf(fp_draft, "acl = self # write # attributes # acl $ userPassword\n") ;
			(void) fprintf(fp_draft, "acl = others # compare # attributes # acl $ userPassword\n\n") ;
			(void) fclose(fp_draft) ;

			if ((fp_draft = fopen (tmpdraft, "r")) == NULL) {
				ps_printf (opt, "Can't open draft entry %s\n", tmpdraft);
				exit(1) ;
			}

			entry_ptr = get_default_entry (NULLENTRY);
#ifdef TURBO_DISK
			entry_ptr->e_attributes = fget_attributes (fp_draft);
#else
			entry_ptr->e_attributes = get_attributes (fp_draft);
#endif

			(void) fclose (fp_draft);

			mod_arg.mea_common = ca; /* struct copy */
			mod_arg.mea_object = dn;
			for (moddn = dn ; moddn->dn_parent != NULLDN; moddn=moddn->dn_parent)
				;
			entry_ptr->e_name = rdn_cpy (moddn->dn_rdn);
	
			/* add rdn as attribute */
			avst = avs_comp_new (AttrV_cpy (&entry_ptr->e_name->rdn_av));
			temp = as_comp_new (AttrT_cpy (entry_ptr->e_name->rdn_at), avst, NULLACL_INFO);
			entry_ptr->e_attributes = as_merge (entry_ptr->e_attributes, temp);

			for (as = entry_ptr->e_attributes; as != NULLATTR; as = as->attr_link)
			{
				emnew = NULLMOD;
				trail = as->attr_link;
				as->attr_link = NULLATTR;
				temp = current_entry->e_attributes;
				for (; temp != NULLATTR; temp = temp->attr_link) 
					if (AttrT_cmp (as->attr_type, temp->attr_type) == 0)
					{
						/* found it - does it need changing ? */
						if (avs_cmp (as->attr_value, temp->attr_value) != 0) 
							emnew = modify_avs (as->attr_value, temp->attr_value,as->attr_type);
						break;
					}

				if (temp == NULLATTR) 
				{
					emnew = em_alloc ();
					emnew->em_type = EM_ADDATTRIBUTE;
					emnew->em_what = as_cpy(as);
					emnew->em_next = NULLMOD;
				}
				if (emnew != NULLMOD)
				{
					mod_arg.mea_changes = ems_append (mod_arg.mea_changes,emnew);
				}
				as->attr_link = trail;
			}

			while (ds_modifyentry (&mod_arg, &mod_error) != DS_OK)
			{
				if (dish_error (opt, &mod_error) == 0)
				{
					ps_printf(rps,"We have a dish error. Bye.\n") ;
					entry_free (entry_ptr);
					exit(1) ;
				}
				mod_arg.mea_object = mod_error.ERR_REFERRAL.DSE_ref_candidates->cr_name;
			}
			ps_print (rps, "Modified ");
			dn_print (rps, dn, EDBOUT);
			ps_print (rps, "\n");
			delete_cache (dn);	/* re-cache when next read */

			entry_free (entry_ptr);
			ems_part_free (mod_arg.mea_changes);
		}
	}

	while(fgets(Read_in_Stuff, LINESIZE, fp_tailor) != 0)
	{
		fputs(Read_in_Stuff, fp_quipurc) ;
	}
		
	(void) fclose(fp_quipurc) ;	
	(void) fclose(fp_tailor) ;

/*	(void) fprintf(fp_quipurc, "dsap: local_dit \"%s\"\n", Local) ;
	(void) fprintf(fp_quipurc, "notype: acl\n") ;
	(void) fprintf(fp_quipurc, "notype: treestructure\n") ;
	(void) fprintf(fp_quipurc, "notype: masterdsa\n") ;
	(void) fprintf(fp_quipurc, "notype: slavedsa\n") ;
	(void) fprintf(fp_quipurc, "notype: objectclass\n") ;
	(void) fprintf(fp_quipurc, "cache_time: 30\n") ;
	(void) fprintf(fp_quipurc, "connect_time: 2\n") ;
 */
	(void) ds_unbind() ;
	(void) unlink(tmpdraft) ;
}
Ejemplo n.º 4
0
int 
main (int argc, char **argv, char **envp)
{
	int	    vecp;
	char   *vec[4];
	struct TSAPdisconnect   tds;
	struct TSAPdisconnect  *td = &tds;

	arginit (argv);
	envinit ();

	advise (LLOG_NOTICE, NULLCP, "listening on %s", taddr2str (&tas));
	if (TNetListen (&tas, td) == NOTOK)
		ts_adios (td, "TNetListen failed");

	for (;;) {
		int	nfds,
			secs;
		fd_set  ifds,
				*rfds;

		if (!isbound && prebind)
			 bind_to_dsa ();

		if (isbound) {
			rfds = &ifds;

			nfds = dsap_ad + 1;

			FD_ZERO (rfds);
			FD_SET (dsap_ad, rfds);

			secs = NOTOK;
		} else
			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");
			continue;
		}

		if (rfds && FD_ISSET (dsap_ad, rfds)) {	/* DSA timed us out... */
			if (debug)
				advise (LLOG_DEBUG, NULLCP, "unbound from directory");

			 ds_unbind ();
			isbound = 0;
		}

		if (vecp <= 0)
			continue;

		if (debug)
			break;

		switch (TNetFork (vecp, vec, td)) {
		case OK:
			ll_hdinit (pgm_log, pgmname);
			break;

		case NOTOK:
			ts_advise (td, LLOG_EXCEPTIONS, "TNetFork failed");
			continue;

		default:
			if (isbound) {
				if (dsap_ad != NOTOK)
					 close (dsap_ad), dsap_ad = NOTOK;
				isbound = 0;
			}
			continue;
		}
		break;
	}

	dased (vecp, vec);

	return 0;
}
Ejemplo n.º 5
0
static 
dase_aux (struct type_DASE_Query__REQ *req)
{
	int    i;
	int	    vecp;
	char **vp;
	char   *context,
		   **vec;
	struct type_DASE_Query__RSP *rsp;
	struct element_DASE_0 *d0;
	struct element_DASE_1 *d1;
	envlist el;
	envlist  en,
			 *ep;
	DN	   *dn;
	DNS	    dns;
	PE	    pe;

	if ((rsp = (struct type_DASE_Query__RSP *) calloc (1, sizeof *rsp))
			== NULL) {
no_mem:
		;
		adios (NULLCP, "out of memory");
	}

	vec = NULL, el = NULL, context = NULL, dns = NULL;

	i = 1;
	for (d0 = req -> name; d0; d0 = d0 -> next)
		i++;
	if ((vec = (char **) calloc ((unsigned) i, sizeof *vec)) == NULL)
		goto no_mem;
	for (vp = vec, d0 = req -> name; d0; vp++, d0 = d0 -> next)
		if ((*vp = qb2str (d0 -> IA5String)) == NULL)
			goto no_mem;
#ifdef	STATS
		else
			advise (LLOG_NOTICE, NULLCP, "lookup: %s", *vp);
#endif
	vecp = i - 1;

	el = NULL, ep = &el;
	for (d1 = req -> envlist; d1; d1 = d1 -> next) {
		struct type_DASE_Environment *ev = d1 -> Environment;
		struct element_DASE_2 *d2;
		struct dn_seq **dp;

		if ((en = (envlist) calloc (1, sizeof *en)) == NULL)
			goto no_mem;
		*ep = en, ep = &en -> Next;

		en -> Upper = ev -> upper;
		en -> Lower = ev -> lower;

		dp = &en -> Dns;
		for (d2 = ev -> path; d2; d2 = d2 -> next) {
			char   *cp;
			struct dn_seq *ds;

			if ((ds = (struct dn_seq *) calloc (1, sizeof *ds)) == NULL)
				goto no_mem;
			*dp = ds, dp = &ds -> dns_next;

			if ((cp = qb2str (d2 -> IA5String)) == NULL)
				goto no_mem;
			if (*cp != '-')
				ds -> dns_dn = str2dn (cp);
			free (cp);

			if (*cp != '-' && ds -> dns_dn == NULLDN) {
				PY_advise (NULLCP, "bad DN in environment (%s)", cp);
				goto send_rsp;
			}
		}
	}

	if ((context = qb2str (req -> context)) == NULL)
		goto no_mem;
#ifdef	STATS
	advise (LLOG_NOTICE, NULLCP, "context: %s", context);
#endif

	if (req -> userdn) {
		int	changed = 0;
		char   *cp;
		DN	newdn;

		if ((cp = qb2str (req -> userdn)) == NULL)
			goto no_mem;
#ifdef	STATS
		advise (LLOG_NOTICE, NULLCP, "userdn: %s", cp);
#endif
		if ((newdn = str2dn (*cp != '@' ? cp : cp + 1)) == NULLDN) {
			PY_advise (NULLCP, "bad DN for userdn (%s)", cp);
			free (cp);
			goto send_rsp;
		}
		if (!userdn || dn_cmp (userdn, newdn))
			changed++;
		if (userdn)
			dn_free (userdn);
		userdn = newdn;
		free (cp);

		if (req -> passwd) {
			if ((cp = qb2str (req -> passwd)) == NULL)
				goto no_mem;
			if (strcmp (passwd, cp))
				changed++;
			 strcpy (passwd, cp);
			free (cp);
		} else {
			if (passwd[0])
				changed++;
			passwd[0] = NULL;
		}

		if (isbound && changed) {
			 ds_unbind ();
			isbound = 0;
		}
	}

	if (!isbound && bind_to_dsa () == NOTOK)
		goto send_rsp;

	PY_pepy[0] = NULL;
	pe = NULLPE;
	if (vecp == 1 && *vec[0] == '@') {
		static DN dnstat;

		if ((dnstat = str2dn (vec[0])) == NULLDN) {
			PY_advise (NULLCP, "invalid name");
			goto send_rsp;
		}

		rsp -> value = name2psap (*(dn = &dnstat));
		goto all_done;
	}

	if (!aet_match (vecp, vec, req -> interactive ? dase_interact
					: just_say_no,
					&dns, el, context)) {
		if (PY_pepy[0] == NULL)
			PY_advise (NULLCP, "unable to resolve name");
		goto send_rsp;
	}

	if (dns == NULL) {
		PY_advise (NULLCP, "search failed to find anything");
		goto send_rsp;
	}
	dn = NULL;

	if (dns -> dns_next) {
		if (req -> interactive)
			 dnSelect (vec[0], &dns, dase_interact, el -> Dns);

		for (; dns; dns = dns -> dns_next) {
			dn = &dns -> dns_dn;
			if (rsp -> value = name2psap (*dn))
				break;
		}
	} else {
		dn = &dns -> dns_dn;
		rsp -> value = name2psap (*dn);
	}

all_done:
	;
	if (dn) {
		 encode_IF_DistinguishedName (&rsp -> name, 1, NULL, NULLCP,*dn);
#ifdef	STATS
		advise (LLOG_NOTICE, NULLCP, "answer: %s", dn2str (*dn));
#endif

		ufn_dn_print_aux (nps, *dn, NULLDN, 0);
		ps_print (nps, " ");
		*--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;

		dn_free (*dn);
		*dn = NULLDN;
	}

send_rsp:
	;
	if (PY_pepy[0]) {
		advise (LLOG_NOTICE, NULLCP, "diagnostic: %s", PY_pepy);

		if ((rsp -> diagnostic = str2qb (PY_pepy, strlen (PY_pepy), 1))
				== NULL)
			goto no_mem;
	}

	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);
	pe_free (pe);

	if (vec) {
		for (vp = vec; *vp; vp++)
			free (*vp);
		free ((char *) vec);
	}

	for (; el; el = en) {
		en = el -> Next;

		dn_seq_free (el -> Dns);
		free ((char *) el);
	}

	if (context)
		free (context);

	if (dns)
		dn_seq_free (dns);
}