xref: /onnv-gate/usr/src/cmd/ldap/ns_ldap/ldapaddrbac.c (revision 12788:c71b0e8f856c)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
51676Sjpk  * Common Development and Distribution License (the "License").
61676Sjpk  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*
22*12788Sgary.winiger@oracle.com  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
230Sstevel@tonic-gate  */
240Sstevel@tonic-gate 
250Sstevel@tonic-gate /*
260Sstevel@tonic-gate  * ldapaddrbac.c
270Sstevel@tonic-gate  *
280Sstevel@tonic-gate  * Routines to add RBAC /etc files into LDAP.
290Sstevel@tonic-gate  * Can also be used to dump entries from a ldap container in /etc format.
300Sstevel@tonic-gate  */
310Sstevel@tonic-gate 
320Sstevel@tonic-gate #include <stdio.h>
330Sstevel@tonic-gate #include <stdlib.h>
340Sstevel@tonic-gate #include <libintl.h>
350Sstevel@tonic-gate #include <strings.h>
360Sstevel@tonic-gate #include <sys/param.h>
370Sstevel@tonic-gate #include <ctype.h>
380Sstevel@tonic-gate #include <sys/types.h>
390Sstevel@tonic-gate #include <sys/socket.h>
400Sstevel@tonic-gate #include <netinet/in.h>
410Sstevel@tonic-gate #include <arpa/inet.h>
420Sstevel@tonic-gate #include <locale.h>
430Sstevel@tonic-gate #include <syslog.h>
440Sstevel@tonic-gate #include "ldapaddent.h"
450Sstevel@tonic-gate 
460Sstevel@tonic-gate #undef opaque
470Sstevel@tonic-gate #undef	GROUP
480Sstevel@tonic-gate #include <bsm/libbsm.h>
490Sstevel@tonic-gate 
500Sstevel@tonic-gate extern	char	*_strtok_escape(char *, char *, char **); /* from libnsl */
510Sstevel@tonic-gate 
520Sstevel@tonic-gate #include <user_attr.h>
530Sstevel@tonic-gate #include <prof_attr.h>
540Sstevel@tonic-gate #include <exec_attr.h>
550Sstevel@tonic-gate #include <auth_attr.h>
560Sstevel@tonic-gate 
570Sstevel@tonic-gate /*
58*12788Sgary.winiger@oracle.com  * The parsing routines for RBAC databases
590Sstevel@tonic-gate  */
600Sstevel@tonic-gate 
610Sstevel@tonic-gate /*
620Sstevel@tonic-gate  * genent_attr:
630Sstevel@tonic-gate  *   Generic function for generating entries for all of the *_attr databases.
640Sstevel@tonic-gate  */
651676Sjpk int
genent_attr(char * line,int ncol,entry_col ** ecolret)660Sstevel@tonic-gate genent_attr(
670Sstevel@tonic-gate 	char	*line,		/* entry to parse */
680Sstevel@tonic-gate 	int	ncol,		/* number of columns in the database */
690Sstevel@tonic-gate 	entry_col	**ecolret)	/* return entry array */
700Sstevel@tonic-gate {
710Sstevel@tonic-gate 	int		i;
720Sstevel@tonic-gate 	char		(*buf)[BUFSIZ + 1];
730Sstevel@tonic-gate 	char		*s;
740Sstevel@tonic-gate 	char		*sep = KV_TOKEN_DELIMIT;
750Sstevel@tonic-gate 	char		*lasts;
760Sstevel@tonic-gate 	entry_col	*ecol;
770Sstevel@tonic-gate 
780Sstevel@tonic-gate 	/*
790Sstevel@tonic-gate 	 * check input length
800Sstevel@tonic-gate 	 */
810Sstevel@tonic-gate 	if (strlen(line) >= sizeof (*buf)) {
820Sstevel@tonic-gate 		(void) strcpy(parse_err_msg, "line too long");
830Sstevel@tonic-gate 		return (GENENT_PARSEERR);
840Sstevel@tonic-gate 	}
850Sstevel@tonic-gate 
860Sstevel@tonic-gate 	/*
870Sstevel@tonic-gate 	 * setup and clear column data
880Sstevel@tonic-gate 	 */
890Sstevel@tonic-gate 	if ((ecol = (entry_col *)malloc(ncol * sizeof (entry_col) +
900Sstevel@tonic-gate 	    sizeof (*buf))) == NULL)
910Sstevel@tonic-gate 		return (GENENT_ERR);
920Sstevel@tonic-gate 	(void) memset((char *)ecol, 0, ncol * sizeof (ecol));
930Sstevel@tonic-gate 
940Sstevel@tonic-gate 	/* don't scribble over input */
950Sstevel@tonic-gate 	buf = (char (*)[sizeof (*buf)]) (ecol + ncol);
960Sstevel@tonic-gate 	(void) strncpy((char *)buf, line, sizeof (*buf));
970Sstevel@tonic-gate 
980Sstevel@tonic-gate 	/* Split up columns */
990Sstevel@tonic-gate 	for (i = 0; i < ncol; i++, buf = NULL) {
1000Sstevel@tonic-gate 		s = _strtok_escape((char *)buf, sep, &lasts);
1010Sstevel@tonic-gate 		if (s == NULL) {
1020Sstevel@tonic-gate 			ecol[i].ec_value.ec_value_val = "";
1030Sstevel@tonic-gate 			ecol[i].ec_value.ec_value_len = 0;
1040Sstevel@tonic-gate 		} else {
1050Sstevel@tonic-gate 			ecol[i].ec_value.ec_value_val = s;
1060Sstevel@tonic-gate 			ecol[i].ec_value.ec_value_len = strlen(s)+1;
1070Sstevel@tonic-gate 		}
1080Sstevel@tonic-gate 	}
1090Sstevel@tonic-gate 
1100Sstevel@tonic-gate 	*ecolret = ecol;
1110Sstevel@tonic-gate 	return (GENENT_OK);
1120Sstevel@tonic-gate }
1130Sstevel@tonic-gate 
1140Sstevel@tonic-gate int
genent_user_attr(char * line,int (* cback)())1150Sstevel@tonic-gate genent_user_attr(char *line, int (*cback)())
1160Sstevel@tonic-gate {
1170Sstevel@tonic-gate 	entry_col	*ecol;
1180Sstevel@tonic-gate 	userstr_t	data;
1190Sstevel@tonic-gate 	int		res, retval;
1200Sstevel@tonic-gate 
1210Sstevel@tonic-gate 	/*
1220Sstevel@tonic-gate 	 * parse entry into columns
1230Sstevel@tonic-gate 	 */
1240Sstevel@tonic-gate 	res = genent_attr(line, USERATTR_DB_NCOL, &ecol);
1250Sstevel@tonic-gate 	if (res != GENENT_OK)
1260Sstevel@tonic-gate 		return (res);
1270Sstevel@tonic-gate 
1280Sstevel@tonic-gate 	data.name = ecol[0].ec_value.ec_value_val;
1290Sstevel@tonic-gate 	data.qualifier = ecol[1].ec_value.ec_value_val;
1300Sstevel@tonic-gate 	data.res1 = NULL;
1310Sstevel@tonic-gate 	data.res2 = NULL;
1320Sstevel@tonic-gate 	data.attr = ecol[4].ec_value.ec_value_val;
1330Sstevel@tonic-gate 
1340Sstevel@tonic-gate 	if (flags & F_VERBOSE)
1350Sstevel@tonic-gate 		(void) fprintf(stdout,
1360Sstevel@tonic-gate 		    gettext("Adding entry : %s\n"), data.name);
1370Sstevel@tonic-gate 
1380Sstevel@tonic-gate 	retval = (*cback)(&data, 1);
1392277Sjs198686 	if (retval != NS_LDAP_SUCCESS) {
1402277Sjs198686 		if (retval == LDAP_NO_SUCH_OBJECT)
1412277Sjs198686 			(void) fprintf(stdout,
1422277Sjs198686 			gettext("Cannot add user_attr entry (%s), "
1432277Sjs198686 			"add passwd entry first\n"), data.name);
1442277Sjs198686 		if (continue_onerror == 0) res = GENENT_CBERR;
1452277Sjs198686 	}
1460Sstevel@tonic-gate 
1470Sstevel@tonic-gate 	free(ecol);
1480Sstevel@tonic-gate 
1490Sstevel@tonic-gate 	return (res);
1500Sstevel@tonic-gate }
1510Sstevel@tonic-gate 
1520Sstevel@tonic-gate void
dump_user_attr(ns_ldap_result_t * res)1530Sstevel@tonic-gate dump_user_attr(ns_ldap_result_t *res)
1540Sstevel@tonic-gate {
1550Sstevel@tonic-gate 	char	**value = NULL;
1560Sstevel@tonic-gate 
1570Sstevel@tonic-gate 	value = __ns_ldap_getAttr(res->entry, "uid");
1580Sstevel@tonic-gate 	if (value && value[0])
1590Sstevel@tonic-gate 		(void) fprintf(stdout, "%s", value[0]);
1600Sstevel@tonic-gate 	else
1610Sstevel@tonic-gate 		return;
1620Sstevel@tonic-gate 
1630Sstevel@tonic-gate 	(void) fprintf(stdout, "::::");
1640Sstevel@tonic-gate 	value = __ns_ldap_getAttr(res->entry, "SolarisAttrKeyValue");
1650Sstevel@tonic-gate 	if (value && value[0])
1660Sstevel@tonic-gate 		(void) fprintf(stdout, "%s", value[0]);
1670Sstevel@tonic-gate 	(void) fprintf(stdout, "\n");
1680Sstevel@tonic-gate }
1690Sstevel@tonic-gate 
1700Sstevel@tonic-gate int
genent_prof_attr(char * line,int (* cback)())1710Sstevel@tonic-gate genent_prof_attr(char *line, int (*cback)())
1720Sstevel@tonic-gate {
1730Sstevel@tonic-gate 	entry_col	*ecol;
1740Sstevel@tonic-gate 	profstr_t	data;
1750Sstevel@tonic-gate 	int		res, retval;
1760Sstevel@tonic-gate 
1770Sstevel@tonic-gate 	/*
1780Sstevel@tonic-gate 	 * parse entry into columns
1790Sstevel@tonic-gate 	 */
1800Sstevel@tonic-gate 	res = genent_attr(line, PROFATTR_DB_NCOL, &ecol);
1810Sstevel@tonic-gate 	if (res != GENENT_OK)
1820Sstevel@tonic-gate 		return (res);
1830Sstevel@tonic-gate 
1840Sstevel@tonic-gate 	data.name = ecol[0].ec_value.ec_value_val;
1850Sstevel@tonic-gate 	data.res1 = NULL;
1860Sstevel@tonic-gate 	data.res2 = NULL;
1870Sstevel@tonic-gate 	data.desc = ecol[3].ec_value.ec_value_val;
1880Sstevel@tonic-gate 	data.attr = ecol[4].ec_value.ec_value_val;
1890Sstevel@tonic-gate 
1900Sstevel@tonic-gate 	if (flags & F_VERBOSE)
1910Sstevel@tonic-gate 		(void) fprintf(stdout,
1920Sstevel@tonic-gate 		    gettext("Adding entry : %s\n"), data.name);
1930Sstevel@tonic-gate 
1940Sstevel@tonic-gate 	retval = (*cback)(&data, 0);
1950Sstevel@tonic-gate 	if (retval == LDAP_ALREADY_EXISTS) {
1960Sstevel@tonic-gate 		if (continue_onerror)
1970Sstevel@tonic-gate 			(void) fprintf(stderr,
1980Sstevel@tonic-gate 			    gettext("Entry: %s - already Exists,"
1990Sstevel@tonic-gate 			    " skipping it.\n"),
2000Sstevel@tonic-gate 			    data.name);
2010Sstevel@tonic-gate 		else {
2020Sstevel@tonic-gate 			res = GENENT_CBERR;
2030Sstevel@tonic-gate 			(void) fprintf(stderr,
2040Sstevel@tonic-gate 			    gettext("Entry: %s - already Exists\n"),
2050Sstevel@tonic-gate 			    data.name);
2060Sstevel@tonic-gate 		}
2070Sstevel@tonic-gate 	} else if (retval)
2080Sstevel@tonic-gate 		res = GENENT_CBERR;
2090Sstevel@tonic-gate 
2100Sstevel@tonic-gate 	free(ecol);
2110Sstevel@tonic-gate 
2120Sstevel@tonic-gate 	return (res);
2130Sstevel@tonic-gate }
2140Sstevel@tonic-gate 
2150Sstevel@tonic-gate void
dump_prof_attr(ns_ldap_result_t * res)2160Sstevel@tonic-gate dump_prof_attr(ns_ldap_result_t *res)
2170Sstevel@tonic-gate {
2180Sstevel@tonic-gate 	char	**value = NULL;
2190Sstevel@tonic-gate 
2200Sstevel@tonic-gate 	value = __ns_ldap_getAttr(res->entry, "cn");
2210Sstevel@tonic-gate 	if (value && value[0])
2220Sstevel@tonic-gate 		(void) fprintf(stdout, "%s", value[0]);
2230Sstevel@tonic-gate 	else
2240Sstevel@tonic-gate 		return;
2250Sstevel@tonic-gate 
2260Sstevel@tonic-gate 	(void) fprintf(stdout, ":::");
2270Sstevel@tonic-gate 	value = __ns_ldap_getAttr(res->entry, "SolarisAttrLongDesc");
2280Sstevel@tonic-gate 	if (value && value[0])
2290Sstevel@tonic-gate 		(void) fprintf(stdout, "%s", value[0]);
2300Sstevel@tonic-gate 	(void) fprintf(stdout, ":");
2310Sstevel@tonic-gate 	value = __ns_ldap_getAttr(res->entry, "SolarisAttrKeyValue");
2320Sstevel@tonic-gate 	if (value && value[0])
2330Sstevel@tonic-gate 		(void) fprintf(stdout, "%s", value[0]);
2340Sstevel@tonic-gate 	(void) fprintf(stdout, "\n");
2350Sstevel@tonic-gate }
2360Sstevel@tonic-gate 
2370Sstevel@tonic-gate int
genent_exec_attr(char * line,int (* cback)())2380Sstevel@tonic-gate genent_exec_attr(char *line, int (*cback)())
2390Sstevel@tonic-gate {
2400Sstevel@tonic-gate 	entry_col	*ecol;
2410Sstevel@tonic-gate 	execstr_t	data;
2420Sstevel@tonic-gate 	int		res, retval;
2430Sstevel@tonic-gate 
2440Sstevel@tonic-gate 	/*
2450Sstevel@tonic-gate 	 * parse entry into columns
2460Sstevel@tonic-gate 	 */
2470Sstevel@tonic-gate 	res = genent_attr(line, EXECATTR_DB_NCOL, &ecol);
2480Sstevel@tonic-gate 	if (res != GENENT_OK)
2490Sstevel@tonic-gate 		return (res);
2500Sstevel@tonic-gate 
2510Sstevel@tonic-gate 	data.name = ecol[0].ec_value.ec_value_val;
2520Sstevel@tonic-gate 	data.policy = ecol[1].ec_value.ec_value_val;
2530Sstevel@tonic-gate 	data.type = ecol[2].ec_value.ec_value_val;
2540Sstevel@tonic-gate 	data.res1 = NULL;
2550Sstevel@tonic-gate 	data.res2 = NULL;
2560Sstevel@tonic-gate 	data.id = ecol[5].ec_value.ec_value_val;
2570Sstevel@tonic-gate 	data.attr = ecol[6].ec_value.ec_value_val;
2580Sstevel@tonic-gate 	data.next = NULL;
2590Sstevel@tonic-gate 
2600Sstevel@tonic-gate 	if (flags & F_VERBOSE)
2610Sstevel@tonic-gate 		(void) fprintf(stdout,
2620Sstevel@tonic-gate 		    gettext("Adding entry : %s+%s+%s+%s\n"),
2630Sstevel@tonic-gate 		    data.name, data.policy, data.type, data.id);
2640Sstevel@tonic-gate 
2650Sstevel@tonic-gate 	retval = (*cback)(&data, 0);
2660Sstevel@tonic-gate 	if (retval == LDAP_ALREADY_EXISTS) {
2670Sstevel@tonic-gate 		if (continue_onerror)
2680Sstevel@tonic-gate 			(void) fprintf(stderr,
2690Sstevel@tonic-gate 			    gettext("Entry: %s+%s+%s+%s - already Exists,"
2700Sstevel@tonic-gate 			    " skipping it.\n"),
2710Sstevel@tonic-gate 			    data.name, data.policy, data.type, data.id);
2720Sstevel@tonic-gate 		else {
2730Sstevel@tonic-gate 			res = GENENT_CBERR;
2740Sstevel@tonic-gate 			(void) fprintf(stderr,
2750Sstevel@tonic-gate 			    gettext("Entry: %s+%s+%s+%s - already Exists\n"),
2760Sstevel@tonic-gate 			    data.name, data.policy, data.type, data.id);
2770Sstevel@tonic-gate 		}
2780Sstevel@tonic-gate 	} else if (retval)
2790Sstevel@tonic-gate 		res = GENENT_CBERR;
2800Sstevel@tonic-gate 
2810Sstevel@tonic-gate 	free(ecol);
2820Sstevel@tonic-gate 
2830Sstevel@tonic-gate 	return (res);
2840Sstevel@tonic-gate }
2850Sstevel@tonic-gate 
2860Sstevel@tonic-gate void
dump_exec_attr(ns_ldap_result_t * res)2870Sstevel@tonic-gate dump_exec_attr(ns_ldap_result_t *res)
2880Sstevel@tonic-gate {
2890Sstevel@tonic-gate 	char	**profile;
2900Sstevel@tonic-gate 	char	**policy;
2910Sstevel@tonic-gate 	char	**type;
2920Sstevel@tonic-gate 	char	**id;
2930Sstevel@tonic-gate 	char	**value;
2940Sstevel@tonic-gate 
2950Sstevel@tonic-gate 	profile = __ns_ldap_getAttr(res->entry, "cn");
2960Sstevel@tonic-gate 	policy = __ns_ldap_getAttr(res->entry, "SolarisKernelSecurityPolicy");
2970Sstevel@tonic-gate 	type = __ns_ldap_getAttr(res->entry, "SolarisProfileType");
2980Sstevel@tonic-gate 	id = __ns_ldap_getAttr(res->entry, "SolarisProfileId");
2990Sstevel@tonic-gate 
3000Sstevel@tonic-gate 	if (profile == NULL || profile[0] == NULL ||
3010Sstevel@tonic-gate 	    policy == NULL || policy[0] == NULL ||
3020Sstevel@tonic-gate 	    type == NULL || type[0] == NULL ||
3030Sstevel@tonic-gate 	    id == NULL || id[0] == NULL)
3040Sstevel@tonic-gate 		return;
3050Sstevel@tonic-gate 
3060Sstevel@tonic-gate 	(void) fprintf(stdout, "%s", profile[0]);
3070Sstevel@tonic-gate 	(void) fprintf(stdout, ":");
3080Sstevel@tonic-gate 	(void) fprintf(stdout, "%s", policy[0]);
3090Sstevel@tonic-gate 	(void) fprintf(stdout, ":");
3100Sstevel@tonic-gate 	(void) fprintf(stdout, "%s", type[0]);
3110Sstevel@tonic-gate 	(void) fprintf(stdout, ":::");
3120Sstevel@tonic-gate 	(void) fprintf(stdout, "%s", id[0]);
3130Sstevel@tonic-gate 	(void) fprintf(stdout, ":");
3140Sstevel@tonic-gate 	value = __ns_ldap_getAttr(res->entry, "SolarisAttrKeyValue");
3150Sstevel@tonic-gate 	if (value && value[0])
3160Sstevel@tonic-gate 		(void) fprintf(stdout, "%s", value[0]);
3170Sstevel@tonic-gate 	(void) fprintf(stdout, "\n");
3180Sstevel@tonic-gate }
3190Sstevel@tonic-gate 
3200Sstevel@tonic-gate int
genent_auth_attr(char * line,int (* cback)())3210Sstevel@tonic-gate genent_auth_attr(char *line, int (*cback)())
3220Sstevel@tonic-gate {
3230Sstevel@tonic-gate 	entry_col	*ecol;
3240Sstevel@tonic-gate 	authstr_t	data;
3250Sstevel@tonic-gate 	int		res, retval;
3260Sstevel@tonic-gate 
3270Sstevel@tonic-gate 	/*
3280Sstevel@tonic-gate 	 * parse entry into columns
3290Sstevel@tonic-gate 	 */
3300Sstevel@tonic-gate 	res = genent_attr(line, AUTHATTR_DB_NCOL, &ecol);
3310Sstevel@tonic-gate 	if (res != GENENT_OK)
3320Sstevel@tonic-gate 		return (res);
3330Sstevel@tonic-gate 
3340Sstevel@tonic-gate 	data.name = ecol[0].ec_value.ec_value_val;
3350Sstevel@tonic-gate 	data.res1 = NULL;
3360Sstevel@tonic-gate 	data.res2 = NULL;
3370Sstevel@tonic-gate 	data.short_desc = ecol[3].ec_value.ec_value_val;
3380Sstevel@tonic-gate 	data.long_desc = ecol[4].ec_value.ec_value_val;
3390Sstevel@tonic-gate 	data.attr = ecol[5].ec_value.ec_value_val;
3400Sstevel@tonic-gate 
3410Sstevel@tonic-gate 	if (flags & F_VERBOSE)
3420Sstevel@tonic-gate 		(void) fprintf(stdout,
3430Sstevel@tonic-gate 		    gettext("Adding entry : %s\n"), data.name);
3440Sstevel@tonic-gate 
3450Sstevel@tonic-gate 	retval = (*cback)(&data, 0);
3460Sstevel@tonic-gate 	if (retval == LDAP_ALREADY_EXISTS) {
3470Sstevel@tonic-gate 		if (continue_onerror)
3480Sstevel@tonic-gate 			(void) fprintf(stderr,
3490Sstevel@tonic-gate 			    gettext("Entry: %s - already Exists,"
3500Sstevel@tonic-gate 			    " skipping it.\n"), data.name);
3510Sstevel@tonic-gate 		else {
3520Sstevel@tonic-gate 			res = GENENT_CBERR;
3530Sstevel@tonic-gate 			(void) fprintf(stderr,
3540Sstevel@tonic-gate 			    gettext("Entry: %s - already Exists\n"),
3550Sstevel@tonic-gate 			    data.name);
3560Sstevel@tonic-gate 		}
3570Sstevel@tonic-gate 	} else if (retval)
3580Sstevel@tonic-gate 		res = GENENT_CBERR;
3590Sstevel@tonic-gate 
3600Sstevel@tonic-gate 	free(ecol);
3610Sstevel@tonic-gate 
3620Sstevel@tonic-gate 	return (res);
3630Sstevel@tonic-gate }
3640Sstevel@tonic-gate 
3650Sstevel@tonic-gate void
dump_auth_attr(ns_ldap_result_t * res)3660Sstevel@tonic-gate dump_auth_attr(ns_ldap_result_t *res)
3670Sstevel@tonic-gate {
3680Sstevel@tonic-gate 	char	**value = NULL;
3690Sstevel@tonic-gate 
3700Sstevel@tonic-gate 	value = __ns_ldap_getAttr(res->entry, "cn");
3710Sstevel@tonic-gate 	if (value && value[0])
3720Sstevel@tonic-gate 		(void) fprintf(stdout, "%s", value[0]);
3730Sstevel@tonic-gate 	else
3740Sstevel@tonic-gate 		return;
3750Sstevel@tonic-gate 
3760Sstevel@tonic-gate 	(void) fprintf(stdout, ":::");
3770Sstevel@tonic-gate 	value = __ns_ldap_getAttr(res->entry, "SolarisAttrShortDesc");
3780Sstevel@tonic-gate 	if (value && value[0])
3790Sstevel@tonic-gate 		(void) fprintf(stdout, "%s", value[0]);
3800Sstevel@tonic-gate 	(void) fprintf(stdout, ":");
3810Sstevel@tonic-gate 	value = __ns_ldap_getAttr(res->entry, "SolarisAttrLongDesc");
3820Sstevel@tonic-gate 	if (value && value[0])
3830Sstevel@tonic-gate 		(void) fprintf(stdout, "%s", value[0]);
3840Sstevel@tonic-gate 	(void) fprintf(stdout, ":");
3850Sstevel@tonic-gate 	value = __ns_ldap_getAttr(res->entry, "SolarisAttrKeyValue");
3860Sstevel@tonic-gate 	if (value && value[0])
3870Sstevel@tonic-gate 		(void) fprintf(stdout, "%s", value[0]);
3880Sstevel@tonic-gate 	(void) fprintf(stdout, "\n");
3890Sstevel@tonic-gate }
390