xref: /onnv-gate/usr/src/lib/libsldap/common/ns_writes.c (revision 12882:5213e1b8c605)
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  */
21*12882SJulian.Pullen@Sun.COM 
220Sstevel@tonic-gate /*
23*12882SJulian.Pullen@Sun.COM  * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate #include <stdio.h>
270Sstevel@tonic-gate #include <sys/types.h>
280Sstevel@tonic-gate #include <stdlib.h>
290Sstevel@tonic-gate #include <libintl.h>
300Sstevel@tonic-gate 
310Sstevel@tonic-gate #include <sys/stat.h>
320Sstevel@tonic-gate #include <fcntl.h>
330Sstevel@tonic-gate #include <unistd.h>
340Sstevel@tonic-gate #include <string.h>
350Sstevel@tonic-gate #include <strings.h>
360Sstevel@tonic-gate #include <lber.h>
370Sstevel@tonic-gate #include <ldap.h>
380Sstevel@tonic-gate #include <syslog.h>
398821SMichen.Chang@Sun.COM #include <stddef.h>
408821SMichen.Chang@Sun.COM #include <sys/mman.h>
410Sstevel@tonic-gate 
420Sstevel@tonic-gate #include "ns_sldap.h"
430Sstevel@tonic-gate #include "ns_internal.h"
446842Sth160488 #include "ns_connmgmt.h"
458821SMichen.Chang@Sun.COM #include "ns_cache_door.h"
460Sstevel@tonic-gate 
470Sstevel@tonic-gate /* Additional headers for addTypedEntry Conversion routines */
480Sstevel@tonic-gate #include <pwd.h>
496842Sth160488 #include <project.h>
500Sstevel@tonic-gate #include <shadow.h>
510Sstevel@tonic-gate #include <grp.h>
520Sstevel@tonic-gate #include <netinet/in.h>
530Sstevel@tonic-gate #include <arpa/inet.h>
540Sstevel@tonic-gate #include <netdb.h>
550Sstevel@tonic-gate #include <rpc/rpcent.h>
560Sstevel@tonic-gate #include <auth_attr.h>
570Sstevel@tonic-gate #include <exec_attr.h>
580Sstevel@tonic-gate #include <prof_attr.h>
590Sstevel@tonic-gate #include <user_attr.h>
600Sstevel@tonic-gate #include <bsm/libbsm.h>
611676Sjpk #include <sys/tsol/tndb.h>
621676Sjpk #include <tsol/label.h>
630Sstevel@tonic-gate 
648821SMichen.Chang@Sun.COM static int send_to_cachemgr(const char *,
658821SMichen.Chang@Sun.COM     ns_ldap_attr_t **, ns_ldap_error_t **);
669288SSreedhar.Chalamalasetti@Sun.COM 
679288SSreedhar.Chalamalasetti@Sun.COM static int escape_str(char *, char *);
689288SSreedhar.Chalamalasetti@Sun.COM 
690Sstevel@tonic-gate /*
700Sstevel@tonic-gate  * If the rdn is a mapped attr:
710Sstevel@tonic-gate  * 	return NS_LDAP_SUCCESS and a new_dn.
720Sstevel@tonic-gate  * If no mapped attr is found in the rdn:
730Sstevel@tonic-gate  * 	return NS_LDAP_SUCCESS and *new_dn == NULL
740Sstevel@tonic-gate  * For example:
750Sstevel@tonic-gate  *  service = abc
760Sstevel@tonic-gate  *  dn =  cn=foo,dc=bar,dc=com
770Sstevel@tonic-gate  *  attributeMapping: abc:cn=sn
780Sstevel@tonic-gate  * Then:
790Sstevel@tonic-gate  *  new_dn = sn=foo,dc=bar,dc=com
800Sstevel@tonic-gate  *
810Sstevel@tonic-gate  */
820Sstevel@tonic-gate static int
replace_mapped_attr_in_dn(const char * service,const char * dn,char ** new_dn)830Sstevel@tonic-gate replace_mapped_attr_in_dn(
840Sstevel@tonic-gate 	const char *service, const char *dn, char **new_dn)
850Sstevel@tonic-gate {
860Sstevel@tonic-gate 	char	**mappedattr;
870Sstevel@tonic-gate 	char	**dnArray = NULL;
880Sstevel@tonic-gate 	char	*rservice;
890Sstevel@tonic-gate 	char	*cur = NULL;
900Sstevel@tonic-gate 	int	len = 0, orig_len = 0, mapped_len = 0;
910Sstevel@tonic-gate 	int	dn_len = 0;
920Sstevel@tonic-gate 
930Sstevel@tonic-gate 	*new_dn = NULL;
940Sstevel@tonic-gate 
950Sstevel@tonic-gate 	/*
965331Samw 	 * separate dn into individual componets
970Sstevel@tonic-gate 	 * e.g.
980Sstevel@tonic-gate 	 * "automountKey=user_01" , "automountMapName_test=auto_home", ...
990Sstevel@tonic-gate 	 */
1000Sstevel@tonic-gate 	dnArray = ldap_explode_dn(dn, 0);
1010Sstevel@tonic-gate 	if (!dnArray || !*dnArray)
1020Sstevel@tonic-gate 		return (NS_LDAP_INVALID_PARAM);
1030Sstevel@tonic-gate 
1040Sstevel@tonic-gate 	cur = strchr(dnArray[0], '=');
1050Sstevel@tonic-gate 	if (!cur) {
1060Sstevel@tonic-gate 		__s_api_free2dArray(dnArray);
1070Sstevel@tonic-gate 		return (NS_LDAP_INVALID_PARAM);
1080Sstevel@tonic-gate 	}
1090Sstevel@tonic-gate 	*cur = '\0';
1100Sstevel@tonic-gate 
1110Sstevel@tonic-gate 	/* we only check schema mapping for automount, not for auto_* */
1120Sstevel@tonic-gate 	if (strncasecmp(service, NS_LDAP_TYPE_AUTOMOUNT,
1130Sstevel@tonic-gate 	    sizeof (NS_LDAP_TYPE_AUTOMOUNT) - 1) == 0)
1140Sstevel@tonic-gate 		rservice = "automount";
1150Sstevel@tonic-gate 	else
1160Sstevel@tonic-gate 		rservice = (char *)service;
1170Sstevel@tonic-gate 
1180Sstevel@tonic-gate 	mappedattr = __ns_ldap_getMappedAttributes(rservice, dnArray[0]);
1190Sstevel@tonic-gate 	if (!mappedattr || !mappedattr[0]) {
1200Sstevel@tonic-gate 		__s_api_free2dArray(dnArray);
1210Sstevel@tonic-gate 		if (mappedattr)
1220Sstevel@tonic-gate 			__s_api_free2dArray(mappedattr);
1230Sstevel@tonic-gate 		return (NS_LDAP_SUCCESS);
1240Sstevel@tonic-gate 	}
1250Sstevel@tonic-gate 	orig_len = strlen(dnArray[0]);
1260Sstevel@tonic-gate 
1270Sstevel@tonic-gate 	/*
1280Sstevel@tonic-gate 	 * The new length is *dn length + (difference between
1290Sstevel@tonic-gate 	 * orig attr and mapped attr) + 1 ;
1300Sstevel@tonic-gate 	 * e.g.
1310Sstevel@tonic-gate 	 * automountKey=aa,automountMapName=auto_home,dc=foo,dc=com
1320Sstevel@tonic-gate 	 * ==>
1330Sstevel@tonic-gate 	 * cn=aa,automountMapName=auto_home,dc=foo,dc=com
1340Sstevel@tonic-gate 	 */
1350Sstevel@tonic-gate 	mapped_len = strlen(mappedattr[0]);
1360Sstevel@tonic-gate 	dn_len = strlen(dn);
1370Sstevel@tonic-gate 	len = dn_len - orig_len + mapped_len + 1;
1380Sstevel@tonic-gate 	*new_dn = (char *)calloc(1, len);
1390Sstevel@tonic-gate 	if (*new_dn == NULL) {
1400Sstevel@tonic-gate 		__s_api_free2dArray(dnArray);
1410Sstevel@tonic-gate 		__s_api_free2dArray(mappedattr);
1420Sstevel@tonic-gate 		return (NS_LDAP_MEMORY);
1430Sstevel@tonic-gate 	}
1440Sstevel@tonic-gate 
1450Sstevel@tonic-gate 	(void) snprintf(*new_dn, len, "%s=%s", mappedattr[0], dn + orig_len +1);
1460Sstevel@tonic-gate 	__s_api_free2dArray(dnArray);
1470Sstevel@tonic-gate 	__s_api_free2dArray(mappedattr);
1480Sstevel@tonic-gate 
1490Sstevel@tonic-gate 	return (NS_LDAP_SUCCESS);
1500Sstevel@tonic-gate }
1510Sstevel@tonic-gate 
1520Sstevel@tonic-gate 
1530Sstevel@tonic-gate /*
1540Sstevel@tonic-gate  * The following function is only used by the
1550Sstevel@tonic-gate  * "gecos" 1 to N attribute mapping code. It expects
1560Sstevel@tonic-gate  * and handle only one data/length pair.
1570Sstevel@tonic-gate  */
1580Sstevel@tonic-gate static int
init_bval_mod(LDAPMod * mod,int mop,char * mtype,char * mvptr,int mvlen)1590Sstevel@tonic-gate init_bval_mod(
1600Sstevel@tonic-gate 	LDAPMod *mod,
1610Sstevel@tonic-gate 	int	mop,
1620Sstevel@tonic-gate 	char	*mtype,
1630Sstevel@tonic-gate 	char	*mvptr,
1640Sstevel@tonic-gate 	int 	mvlen)
1650Sstevel@tonic-gate {
1660Sstevel@tonic-gate 
1670Sstevel@tonic-gate 	struct berval	**bmodval;
1680Sstevel@tonic-gate 
1690Sstevel@tonic-gate 	/* dup attribute name */
1700Sstevel@tonic-gate 	mod->mod_type = strdup(mtype);
1710Sstevel@tonic-gate 	if (mod->mod_type == NULL)
1720Sstevel@tonic-gate 		return (-1);
1730Sstevel@tonic-gate 
1740Sstevel@tonic-gate 	/*
1750Sstevel@tonic-gate 	 * assume single value,
1760Sstevel@tonic-gate 	 * since only one value/length pair passed in
1770Sstevel@tonic-gate 	 */
1786842Sth160488 	bmodval = (struct berval **)calloc(2, sizeof (struct berval *));
1790Sstevel@tonic-gate 	if (bmodval == NULL) {
1800Sstevel@tonic-gate 		free(mod->mod_type);
1810Sstevel@tonic-gate 		mod->mod_type = NULL;
1820Sstevel@tonic-gate 		return	(-1);
1830Sstevel@tonic-gate 	}
1846842Sth160488 	bmodval[0] = (struct berval *)calloc(1, sizeof (struct berval));
1850Sstevel@tonic-gate 	if (bmodval[0] == NULL) {
1860Sstevel@tonic-gate 		free(mod->mod_type);
1870Sstevel@tonic-gate 		mod->mod_type = NULL;
1880Sstevel@tonic-gate 		free(bmodval);
1890Sstevel@tonic-gate 		return	(-1);
1900Sstevel@tonic-gate 	}
1910Sstevel@tonic-gate 
1920Sstevel@tonic-gate 	/* set pointer to data */
1930Sstevel@tonic-gate 	bmodval[0]->bv_val = mvptr;
1940Sstevel@tonic-gate 
1950Sstevel@tonic-gate 	/* set length */
1960Sstevel@tonic-gate 	bmodval[0]->bv_len = mvlen;
1970Sstevel@tonic-gate 
1980Sstevel@tonic-gate 	/*
1990Sstevel@tonic-gate 	 * turn on the BVALUE bit to indicate
2000Sstevel@tonic-gate 	 * that the length of data is supplied
2010Sstevel@tonic-gate 	 */
2020Sstevel@tonic-gate 	mod->mod_op = mop | LDAP_MOD_BVALUES;
2030Sstevel@tonic-gate 
2040Sstevel@tonic-gate 	mod->mod_bvalues = bmodval;
2050Sstevel@tonic-gate 
2060Sstevel@tonic-gate 	return	(0);
2070Sstevel@tonic-gate }
2080Sstevel@tonic-gate 
2090Sstevel@tonic-gate static void
freeModList(LDAPMod ** mods)2100Sstevel@tonic-gate freeModList(LDAPMod **mods)
2110Sstevel@tonic-gate {
2120Sstevel@tonic-gate 	int i, j;
2130Sstevel@tonic-gate 	int name_is_oc;
2140Sstevel@tonic-gate 
2150Sstevel@tonic-gate 	if (mods == NULL)
2160Sstevel@tonic-gate 		return;
2170Sstevel@tonic-gate 
2180Sstevel@tonic-gate 	for (i = 0; mods[i]; i++) {
2190Sstevel@tonic-gate 
2200Sstevel@tonic-gate 		/* free attribute name */
2210Sstevel@tonic-gate 		name_is_oc = FALSE;
2220Sstevel@tonic-gate 		if (mods[i]->mod_type) {
2236842Sth160488 			if (strcasecmp(mods[i]->mod_type, "objectclass") == 0)
2240Sstevel@tonic-gate 				name_is_oc = TRUE;
2250Sstevel@tonic-gate 			free(mods[i]->mod_type);
2260Sstevel@tonic-gate 		}
2270Sstevel@tonic-gate 
2280Sstevel@tonic-gate 		if (mods[i]->mod_bvalues == NULL)
2290Sstevel@tonic-gate 			continue;
2300Sstevel@tonic-gate 		/*
2310Sstevel@tonic-gate 		 * LDAP_MOD_BVALUES is only set by
2320Sstevel@tonic-gate 		 * the "gecos" 1 to N attribute mapping
2330Sstevel@tonic-gate 		 * code, and the attribute is single valued.
2340Sstevel@tonic-gate 		 */
2350Sstevel@tonic-gate 		if (mods[i]->mod_op & LDAP_MOD_BVALUES) {
2360Sstevel@tonic-gate 			if (mods[i]->mod_bvalues[0])
2370Sstevel@tonic-gate 				free(mods[i]->mod_bvalues[0]);
2380Sstevel@tonic-gate 		} else {
2390Sstevel@tonic-gate 			if (name_is_oc) {
2400Sstevel@tonic-gate 				/*
2410Sstevel@tonic-gate 				 * only values for the "objectclass"
2420Sstevel@tonic-gate 				 * were dupped using strdup.
2430Sstevel@tonic-gate 				 * other attribute values were
2440Sstevel@tonic-gate 				 * not dupped, but via pointer
2450Sstevel@tonic-gate 				 * assignment. So here the
2460Sstevel@tonic-gate 				 * values for "objectclass"
2470Sstevel@tonic-gate 				 * is freed one by one,
2480Sstevel@tonic-gate 				 * but the values for other
2490Sstevel@tonic-gate 				 * attributes need not be freed.
2500Sstevel@tonic-gate 				 */
2510Sstevel@tonic-gate 				for (j = 0; mods[i]->mod_values[j]; j++)
2520Sstevel@tonic-gate 					free(mods[i]->mod_values[j]);
2530Sstevel@tonic-gate 			}
2540Sstevel@tonic-gate 
2550Sstevel@tonic-gate 		}
2560Sstevel@tonic-gate 		free(mods[i]->mod_bvalues);
2570Sstevel@tonic-gate 	}
2580Sstevel@tonic-gate 
2590Sstevel@tonic-gate 	/* modlist */
2600Sstevel@tonic-gate 	free((char *)(mods[0]));
2610Sstevel@tonic-gate 	free(mods);
2620Sstevel@tonic-gate }
2630Sstevel@tonic-gate 
2640Sstevel@tonic-gate static LDAPMod **
__s_api_makeModListCount(const char * service,const ns_ldap_attr_t * const * attr,const int mod_op,const int count,const int flags)2650Sstevel@tonic-gate __s_api_makeModListCount(
2660Sstevel@tonic-gate 	const char *service,
2670Sstevel@tonic-gate 	const ns_ldap_attr_t * const *attr,
2680Sstevel@tonic-gate 	const int mod_op,
2690Sstevel@tonic-gate 	const int count,
2700Sstevel@tonic-gate 	const int flags)
2710Sstevel@tonic-gate {
2720Sstevel@tonic-gate 	LDAPMod		**mods, *modlist;
2730Sstevel@tonic-gate 	char		**modval;
2740Sstevel@tonic-gate 	char		**mapping;
2750Sstevel@tonic-gate 	int		i;
2760Sstevel@tonic-gate 	int		j;
2770Sstevel@tonic-gate 	int		k, rc, vlen;
2780Sstevel@tonic-gate 	char		*c, *comma1 = NULL, *comma2 = NULL;
2790Sstevel@tonic-gate 	int		schema_mapping_existed = FALSE;
2800Sstevel@tonic-gate 	int		auto_service = FALSE;
2810Sstevel@tonic-gate 
2820Sstevel@tonic-gate 
2830Sstevel@tonic-gate 	/*
2840Sstevel@tonic-gate 	 * add 2 for "gecos" 1 to up to 3 attribute mapping
2850Sstevel@tonic-gate 	 */
2860Sstevel@tonic-gate 	mods = (LDAPMod **)calloc((count + 3), sizeof (LDAPMod *));
2870Sstevel@tonic-gate 	if (mods == NULL) {
2880Sstevel@tonic-gate 		return (NULL);
2890Sstevel@tonic-gate 	}
2900Sstevel@tonic-gate 	/*
2910Sstevel@tonic-gate 	 * add 2 for "gecos" 1 to up to 3 attribute mapping
2920Sstevel@tonic-gate 	 */
2930Sstevel@tonic-gate 	modlist = (LDAPMod *)calloc(count + 2, sizeof (LDAPMod));
2940Sstevel@tonic-gate 	if (modlist == NULL) {
2950Sstevel@tonic-gate 		free(mods);
2960Sstevel@tonic-gate 		return (NULL);
2970Sstevel@tonic-gate 	}
2980Sstevel@tonic-gate 
2990Sstevel@tonic-gate 	if (service != NULL && strncasecmp(service, NS_LDAP_TYPE_AUTOMOUNT,
3000Sstevel@tonic-gate 	    sizeof (NS_LDAP_TYPE_AUTOMOUNT) - 1) == 0)
3010Sstevel@tonic-gate 		auto_service = TRUE;
3020Sstevel@tonic-gate 
3030Sstevel@tonic-gate 	/*
3040Sstevel@tonic-gate 	 * see if schema mapping existed for the given service
3050Sstevel@tonic-gate 	 */
3060Sstevel@tonic-gate 	mapping = __ns_ldap_getOrigAttribute(service,
3070Sstevel@tonic-gate 	    NS_HASH_SCHEMA_MAPPING_EXISTED);
3080Sstevel@tonic-gate 	if (mapping) {
3090Sstevel@tonic-gate 		schema_mapping_existed = TRUE;
3100Sstevel@tonic-gate 		__s_api_free2dArray(mapping);
3110Sstevel@tonic-gate 		mapping = NULL;
3120Sstevel@tonic-gate 	}
3130Sstevel@tonic-gate 
3140Sstevel@tonic-gate 	for (i = 0, k = 0; k < count && attr[k] != NULL; i++, k++) {
3150Sstevel@tonic-gate 		mods[i] = &modlist[i];
3160Sstevel@tonic-gate 		mods[i]->mod_op = mod_op;
3170Sstevel@tonic-gate 		/*
3180Sstevel@tonic-gate 		 * Perform attribute mapping if necessary.
3190Sstevel@tonic-gate 		 */
3206842Sth160488 		if (schema_mapping_existed && (flags & NS_LDAP_NOMAP) == 0) {
3210Sstevel@tonic-gate 			mapping = __ns_ldap_getMappedAttributes(service,
3220Sstevel@tonic-gate 			    attr[k]->attrname);
3230Sstevel@tonic-gate 		} else
3240Sstevel@tonic-gate 			mapping = NULL;
3250Sstevel@tonic-gate 
3260Sstevel@tonic-gate 		if (mapping == NULL && auto_service &&
3270Sstevel@tonic-gate 		    (flags & NS_LDAP_NOMAP) == 0) {
3280Sstevel@tonic-gate 			/*
3290Sstevel@tonic-gate 			 * if service == auto_xxx and
3300Sstevel@tonic-gate 			 * no mapped attribute is found
3310Sstevel@tonic-gate 			 * and NS_LDAP_NOMAP is not set
3320Sstevel@tonic-gate 			 * then try automount's mapped attribute
3330Sstevel@tonic-gate 			 */
3340Sstevel@tonic-gate 			mapping = __ns_ldap_getMappedAttributes("automount",
3350Sstevel@tonic-gate 			    attr[k]->attrname);
3360Sstevel@tonic-gate 		}
3370Sstevel@tonic-gate 
3380Sstevel@tonic-gate 		if (mapping == NULL) {
3396842Sth160488 			mods[i]->mod_type = strdup(attr[k]->attrname);
3406842Sth160488 			if (mods[i]->mod_type == NULL)
3416842Sth160488 				goto free_memory;
3420Sstevel@tonic-gate 		} else {
3430Sstevel@tonic-gate 			/*
3440Sstevel@tonic-gate 			 * 1 to N attribute mapping is only done for "gecos",
3450Sstevel@tonic-gate 			 * and only 1 to 3 mapping.
3460Sstevel@tonic-gate 			 * nine cases here:
3470Sstevel@tonic-gate 			 *
3480Sstevel@tonic-gate 			 * A. attrMap=passwd:gecos=a
3490Sstevel@tonic-gate 			 *    1. gecos="xx,yy,zz" -> a="xx,yy,zz"
3500Sstevel@tonic-gate 			 *    2. gecos="xx,yy" -> a="xx,yy"
3510Sstevel@tonic-gate 			 *    3. gecos="xx" -> a="xx"
3520Sstevel@tonic-gate 			 *
3530Sstevel@tonic-gate 			 * B. attrMap=passwd:gecos=a b
3540Sstevel@tonic-gate 			 *    4. gecos="xx,yy,zz" -> a="xx" b="yy,zz"
3550Sstevel@tonic-gate 			 *    5. gecos="xx,yy" -> a="xx" b="yy"
3560Sstevel@tonic-gate 			 *    6. gecos="xx" -> a="xx"
3570Sstevel@tonic-gate 			 *
3580Sstevel@tonic-gate 			 * C. attrMap=passwd:gecos=a b c
3590Sstevel@tonic-gate 			 *    7. gecos="xx,yy,zz" -> a="xx" b="yy" c="zz"
3600Sstevel@tonic-gate 			 *    8. gecos="xx,yy" -> a="xx" b="yy"
3610Sstevel@tonic-gate 			 *    9. gecos="xx" -> a="xx"
3620Sstevel@tonic-gate 			 *
3630Sstevel@tonic-gate 			 * This can be grouped as:
3640Sstevel@tonic-gate 			 *
3650Sstevel@tonic-gate 			 * c1 cases: 1,2,3,6,9
3660Sstevel@tonic-gate 			 *    if ((attrMap=passwd:gecos=a) ||
3670Sstevel@tonic-gate 			 *		(no "," in gecos value))
3680Sstevel@tonic-gate 			 *	same as other no-mapping attributes,
3690Sstevel@tonic-gate 			 *	no special processing needed
3700Sstevel@tonic-gate 			 *    else
3710Sstevel@tonic-gate 			 *
3720Sstevel@tonic-gate 			 * c2 cases: 4,5,8
3730Sstevel@tonic-gate 			 *    if ((attrMap=passwd:gecos=a b) ||
3740Sstevel@tonic-gate 			 *	(only one "," in gecos value))
3750Sstevel@tonic-gate 			 *	a=xx b=yy[,...]
3760Sstevel@tonic-gate 			 *    else
3770Sstevel@tonic-gate 			 *
3780Sstevel@tonic-gate 			 * c3 case: 7
3790Sstevel@tonic-gate 			 *    a=xx b=yy c=...
3800Sstevel@tonic-gate 			 *
3810Sstevel@tonic-gate 			 * notes: in case c2 and c3, ... could still contain ","
3820Sstevel@tonic-gate 			 */
3836842Sth160488 			if (strcasecmp(service, "passwd") == 0 &&
3846842Sth160488 			    strcasecmp(attr[k]->attrname, "gecos") == 0 &&
3856842Sth160488 			    mapping[1] && attr[k]->attrvalue[0] &&
3866842Sth160488 			    (comma1 = strchr(attr[k]->attrvalue[0],
3876842Sth160488 			    COMMATOK)) != NULL) {
3880Sstevel@tonic-gate 
3890Sstevel@tonic-gate 			/* is there a second comma? */
3900Sstevel@tonic-gate 			if (*(comma1 + 1) != '\0')
3910Sstevel@tonic-gate 				comma2 = strchr(comma1 + 1, COMMATOK);
3920Sstevel@tonic-gate 
3930Sstevel@tonic-gate 			/*
3940Sstevel@tonic-gate 			 * Process case c2 or c3.
3950Sstevel@tonic-gate 			 * case c2: mapped to two attributes or just
3960Sstevel@tonic-gate 			 * one comma
3970Sstevel@tonic-gate 			 */
3986842Sth160488 			if (mapping[2] == NULL || comma2 == NULL) {
3990Sstevel@tonic-gate 				/* case c2 */
4000Sstevel@tonic-gate 
4010Sstevel@tonic-gate 				/*
4020Sstevel@tonic-gate 				 * int mod structure for the first attribute
4030Sstevel@tonic-gate 				 */
4040Sstevel@tonic-gate 				vlen = comma1 - attr[k]->attrvalue[0];
4050Sstevel@tonic-gate 				c = attr[k]->attrvalue[0];
4060Sstevel@tonic-gate 
4070Sstevel@tonic-gate 				if (vlen > 0 && c) {
4080Sstevel@tonic-gate 					rc = init_bval_mod(mods[i], mod_op,
4096842Sth160488 					    mapping[0], c, vlen);
4100Sstevel@tonic-gate 					if (rc != 0)
4110Sstevel@tonic-gate 						goto free_memory;
4120Sstevel@tonic-gate 				} else {
4130Sstevel@tonic-gate 					/* don't leave a hole in mods array */
4140Sstevel@tonic-gate 					mods[i] = NULL;
4150Sstevel@tonic-gate 					i--;
4160Sstevel@tonic-gate 				}
4170Sstevel@tonic-gate 
4180Sstevel@tonic-gate 
4190Sstevel@tonic-gate 				/*
4200Sstevel@tonic-gate 				 * init mod structure for the 2nd attribute
4210Sstevel@tonic-gate 				 */
4220Sstevel@tonic-gate 				if (*(comma1 + 1) == '\0') {
4230Sstevel@tonic-gate 					__s_api_free2dArray(mapping);
4240Sstevel@tonic-gate 					mapping = NULL;
4250Sstevel@tonic-gate 					continue;
4260Sstevel@tonic-gate 				}
4270Sstevel@tonic-gate 
4280Sstevel@tonic-gate 				i++;
4290Sstevel@tonic-gate 				mods[i] = &modlist[i];
4300Sstevel@tonic-gate 
4310Sstevel@tonic-gate 				/*
4320Sstevel@tonic-gate 				 * get pointer to data.
4330Sstevel@tonic-gate 				 * Skip leading spaces.
4340Sstevel@tonic-gate 				 */
4356842Sth160488 				for (c = comma1 + 1; *c == SPACETOK; c++) {
4366842Sth160488 					/* empty */
4376842Sth160488 				}
4380Sstevel@tonic-gate 
4390Sstevel@tonic-gate 				/* get data length */
4400Sstevel@tonic-gate 				vlen = strlen(attr[k]->attrvalue[0]) -
4416842Sth160488 				    (c - attr[k]->attrvalue[0]);
4420Sstevel@tonic-gate 
4430Sstevel@tonic-gate 				if (vlen > 0 && c) {
4440Sstevel@tonic-gate 					rc = init_bval_mod(mods[i], mod_op,
4456842Sth160488 					    mapping[1], c, vlen);
4460Sstevel@tonic-gate 					if (rc != 0)
4470Sstevel@tonic-gate 						goto free_memory;
4480Sstevel@tonic-gate 				} else {
4490Sstevel@tonic-gate 					/* don't leave a hole in mods array */
4500Sstevel@tonic-gate 					mods[i] = NULL;
4510Sstevel@tonic-gate 					i--;
4520Sstevel@tonic-gate 				}
4530Sstevel@tonic-gate 
4540Sstevel@tonic-gate 				/* done with the mapping array */
4550Sstevel@tonic-gate 				__s_api_free2dArray(mapping);
4560Sstevel@tonic-gate 				mapping = NULL;
4570Sstevel@tonic-gate 
4580Sstevel@tonic-gate 				continue;
4590Sstevel@tonic-gate 			} else {
4600Sstevel@tonic-gate 				/* case c3 */
4610Sstevel@tonic-gate 
4620Sstevel@tonic-gate 				/*
4630Sstevel@tonic-gate 				 * int mod structure for the first attribute
4640Sstevel@tonic-gate 				 */
4650Sstevel@tonic-gate 				vlen = comma1 - attr[k]->attrvalue[0];
4660Sstevel@tonic-gate 				c = attr[k]->attrvalue[0];
4670Sstevel@tonic-gate 
4680Sstevel@tonic-gate 				if (vlen > 0 && c) {
4690Sstevel@tonic-gate 					rc = init_bval_mod(mods[i], mod_op,
4706842Sth160488 					    mapping[0], c, vlen);
4710Sstevel@tonic-gate 					if (rc != 0)
4720Sstevel@tonic-gate 						goto free_memory;
4730Sstevel@tonic-gate 				} else {
4740Sstevel@tonic-gate 					/* don't leave a hole in mods array */
4750Sstevel@tonic-gate 					mods[i] = NULL;
4760Sstevel@tonic-gate 					i--;
4770Sstevel@tonic-gate 				}
4780Sstevel@tonic-gate 
4790Sstevel@tonic-gate 				/*
4800Sstevel@tonic-gate 				 * init mod structure for the 2nd attribute
4810Sstevel@tonic-gate 				 */
4820Sstevel@tonic-gate 				i++;
4830Sstevel@tonic-gate 				mods[i] = &modlist[i];
4840Sstevel@tonic-gate 
4850Sstevel@tonic-gate 				/*
4860Sstevel@tonic-gate 				 * get pointer to data.
4870Sstevel@tonic-gate 				 * Skip leading spaces.
4880Sstevel@tonic-gate 				 */
4896842Sth160488 				for (c = comma1 + 1; *c == SPACETOK; c++) {
4906842Sth160488 					/* empty */
4916842Sth160488 				};
4920Sstevel@tonic-gate 
4930Sstevel@tonic-gate 				/* get data length */
4940Sstevel@tonic-gate 				vlen = comma2 - c;
4950Sstevel@tonic-gate 
4960Sstevel@tonic-gate 				if (vlen > 0 && c) {
4970Sstevel@tonic-gate 					rc = init_bval_mod(mods[i], mod_op,
4986842Sth160488 					    mapping[1], c, vlen);
4990Sstevel@tonic-gate 					if (rc != 0)
5000Sstevel@tonic-gate 						goto free_memory;
5010Sstevel@tonic-gate 				} else {
5020Sstevel@tonic-gate 					/* don't leave a hole in mods array */
5030Sstevel@tonic-gate 					mods[i] = NULL;
5040Sstevel@tonic-gate 					i--;
5050Sstevel@tonic-gate 				}
5060Sstevel@tonic-gate 
5070Sstevel@tonic-gate 				/*
5080Sstevel@tonic-gate 				 * init mod structure for the 3rd attribute
5090Sstevel@tonic-gate 				 */
5100Sstevel@tonic-gate 				if (*(comma2 + 1) == '\0') {
5110Sstevel@tonic-gate 					__s_api_free2dArray(mapping);
5120Sstevel@tonic-gate 					mapping = NULL;
5130Sstevel@tonic-gate 					continue;
5140Sstevel@tonic-gate 				}
5150Sstevel@tonic-gate 
5160Sstevel@tonic-gate 				i++;
5170Sstevel@tonic-gate 				mods[i] = &modlist[i];
5180Sstevel@tonic-gate 				/*
5190Sstevel@tonic-gate 				 * get pointer to data.
5200Sstevel@tonic-gate 				 * Skip leading spaces.
5210Sstevel@tonic-gate 				 */
5226842Sth160488 				for (c = comma2 + 1; *c == SPACETOK; c++) {
5236842Sth160488 					/* empty */
5246842Sth160488 				}
5250Sstevel@tonic-gate 
5260Sstevel@tonic-gate 				/* get data length */
5270Sstevel@tonic-gate 				vlen = strlen(attr[k]->attrvalue[0]) -
5286842Sth160488 				    (c - attr[k]->attrvalue[0]);
5290Sstevel@tonic-gate 
5300Sstevel@tonic-gate 				if (vlen > 0 && c) {
5310Sstevel@tonic-gate 					rc = init_bval_mod(mods[i], mod_op,
5326842Sth160488 					    mapping[2], c, vlen);
5330Sstevel@tonic-gate 					if (rc != 0)
5340Sstevel@tonic-gate 						goto free_memory;
5350Sstevel@tonic-gate 				} else {
5360Sstevel@tonic-gate 					/* don't leave a hole in mods array */
5370Sstevel@tonic-gate 					mods[i] = NULL;
5380Sstevel@tonic-gate 					i--;
5390Sstevel@tonic-gate 				}
5400Sstevel@tonic-gate 
5410Sstevel@tonic-gate 				/* done with the mapping array */
5420Sstevel@tonic-gate 				__s_api_free2dArray(mapping);
5430Sstevel@tonic-gate 				mapping = NULL;
5440Sstevel@tonic-gate 
5450Sstevel@tonic-gate 				continue;
5466842Sth160488 				}
5470Sstevel@tonic-gate 			}
5486842Sth160488 
5496842Sth160488 			/* case c1 */
5506842Sth160488 			mods[i]->mod_type = strdup(mapping[0]);
5516842Sth160488 			if (mods[i]->mod_type == NULL) {
5520Sstevel@tonic-gate 				goto free_memory;
5536842Sth160488 			}
5546842Sth160488 			__s_api_free2dArray(mapping);
5556842Sth160488 			mapping = NULL;
5560Sstevel@tonic-gate 		}
5570Sstevel@tonic-gate 
5580Sstevel@tonic-gate 		modval = (char **)calloc(attr[k]->value_count+1,
5596842Sth160488 		    sizeof (char *));
5600Sstevel@tonic-gate 		if (modval == NULL)
5610Sstevel@tonic-gate 			goto free_memory;
5620Sstevel@tonic-gate 		/*
5630Sstevel@tonic-gate 		 * Perform objectclass mapping.
5640Sstevel@tonic-gate 		 * Note that the values for the "objectclass" attribute
5650Sstevel@tonic-gate 		 * will be dupped using strdup. Values for other
5660Sstevel@tonic-gate 		 * attributes will be referenced via pointer
5670Sstevel@tonic-gate 		 * assignments.
5680Sstevel@tonic-gate 		 */
5690Sstevel@tonic-gate 		if (strcasecmp(mods[i]->mod_type, "objectclass") == 0) {
5700Sstevel@tonic-gate 			for (j = 0; j < attr[k]->value_count; j++) {
5710Sstevel@tonic-gate 				if (schema_mapping_existed &&
5726842Sth160488 				    (flags & NS_LDAP_NOMAP) == 0)
5730Sstevel@tonic-gate 					mapping =
5746842Sth160488 					    __ns_ldap_getMappedObjectClass(
5756842Sth160488 					    service, attr[k]->attrvalue[j]);
5760Sstevel@tonic-gate 				else
5770Sstevel@tonic-gate 					mapping = NULL;
5780Sstevel@tonic-gate 
5790Sstevel@tonic-gate 				if (mapping == NULL && auto_service &&
5806842Sth160488 				    (flags & NS_LDAP_NOMAP) == 0)
5810Sstevel@tonic-gate 					/*
5820Sstevel@tonic-gate 					 * if service == auto_xxx and
5830Sstevel@tonic-gate 					 * no mapped objectclass is found
5840Sstevel@tonic-gate 					 * then try automount
5850Sstevel@tonic-gate 					 */
5860Sstevel@tonic-gate 					mapping =
5876842Sth160488 					    __ns_ldap_getMappedObjectClass(
5886842Sth160488 					    "automount", attr[k]->attrvalue[j]);
5890Sstevel@tonic-gate 
5900Sstevel@tonic-gate 				if (mapping && mapping[0]) {
5910Sstevel@tonic-gate 					/* assume single mapping */
5920Sstevel@tonic-gate 					modval[j] = strdup(mapping[0]);
5930Sstevel@tonic-gate 				} else {
5940Sstevel@tonic-gate 					modval[j] = strdup(attr[k]->
5956842Sth160488 					    attrvalue[j]);
5960Sstevel@tonic-gate 				}
5970Sstevel@tonic-gate 				if (modval[j] == NULL)
5980Sstevel@tonic-gate 					goto free_memory;
5990Sstevel@tonic-gate 			}
6000Sstevel@tonic-gate 		} else {
6010Sstevel@tonic-gate 			for (j = 0; j < attr[k]->value_count; j++) {
6020Sstevel@tonic-gate 				/* ASSIGN NOT COPY */
6030Sstevel@tonic-gate 				modval[j] = attr[k]->attrvalue[j];
6040Sstevel@tonic-gate 			}
6050Sstevel@tonic-gate 		}
6060Sstevel@tonic-gate 		mods[i]->mod_values = modval;
6070Sstevel@tonic-gate 	}
6080Sstevel@tonic-gate 
6090Sstevel@tonic-gate 	return (mods);
6100Sstevel@tonic-gate 
6110Sstevel@tonic-gate free_memory:
6120Sstevel@tonic-gate 	freeModList(mods);
6130Sstevel@tonic-gate 	if (mapping)
6140Sstevel@tonic-gate 	__s_api_free2dArray(mapping);
6150Sstevel@tonic-gate 
6160Sstevel@tonic-gate 	return (NULL);
6170Sstevel@tonic-gate 
6180Sstevel@tonic-gate }
6190Sstevel@tonic-gate 
6200Sstevel@tonic-gate static LDAPMod **
__s_api_makeModList(const char * service,const ns_ldap_attr_t * const * attr,const int mod_op,const int flags)6210Sstevel@tonic-gate __s_api_makeModList(
6220Sstevel@tonic-gate 	const char *service,
6230Sstevel@tonic-gate 	const ns_ldap_attr_t * const *attr,
6240Sstevel@tonic-gate 	const int mod_op,
6250Sstevel@tonic-gate 	const int flags)
6260Sstevel@tonic-gate {
6270Sstevel@tonic-gate 	ns_ldap_attr_t	**aptr = (ns_ldap_attr_t **)attr;
6280Sstevel@tonic-gate 	int		count = 0;
6290Sstevel@tonic-gate 
6300Sstevel@tonic-gate 	if (aptr == NULL)
6310Sstevel@tonic-gate 		return (NULL);
6320Sstevel@tonic-gate 
6330Sstevel@tonic-gate 	/* count number of attributes */
6340Sstevel@tonic-gate 	while (*aptr++)
6350Sstevel@tonic-gate 		count++;
6360Sstevel@tonic-gate 
6370Sstevel@tonic-gate 	return (__s_api_makeModListCount(service, attr, mod_op, count, flags));
6380Sstevel@tonic-gate }
6390Sstevel@tonic-gate 
6400Sstevel@tonic-gate static void
__s_cvt_freeEntryRdn(ns_ldap_entry_t ** entry,char ** rdn)6410Sstevel@tonic-gate __s_cvt_freeEntryRdn(ns_ldap_entry_t **entry, char **rdn)
6420Sstevel@tonic-gate {
6430Sstevel@tonic-gate 	if (*entry != NULL) {
6440Sstevel@tonic-gate 		__ns_ldap_freeEntry(*entry);
6450Sstevel@tonic-gate 		*entry = NULL;
6460Sstevel@tonic-gate 	}
6470Sstevel@tonic-gate 	if (*rdn != NULL) {
6480Sstevel@tonic-gate 		free(*rdn);
6490Sstevel@tonic-gate 		*rdn = NULL;
6500Sstevel@tonic-gate 	}
6510Sstevel@tonic-gate }
6520Sstevel@tonic-gate 
6530Sstevel@tonic-gate /*
6540Sstevel@tonic-gate  * This state machine performs one or more LDAP add/delete/modify
6550Sstevel@tonic-gate  * operations to configured LDAP servers.
6560Sstevel@tonic-gate  */
6570Sstevel@tonic-gate static int
write_state_machine(int ldap_op,char * dn,LDAPMod ** mods,const ns_cred_t * cred,const int flags,ns_ldap_error_t ** errorp)6580Sstevel@tonic-gate write_state_machine(
6590Sstevel@tonic-gate 	int 		ldap_op,
6600Sstevel@tonic-gate 	char 		*dn,
6610Sstevel@tonic-gate 	LDAPMod		**mods,
6620Sstevel@tonic-gate 	const ns_cred_t *cred,
6630Sstevel@tonic-gate 	const int 	flags,
6640Sstevel@tonic-gate 	ns_ldap_error_t ** errorp)
6650Sstevel@tonic-gate {
6660Sstevel@tonic-gate 	ConnectionID    connectionId = -1;
6670Sstevel@tonic-gate 	Connection	*conp = NULL;
6680Sstevel@tonic-gate 	LDAPMessage 	*res;
6690Sstevel@tonic-gate 	char		*target_dn = NULL;
6700Sstevel@tonic-gate 	char		errstr[MAXERROR];
6710Sstevel@tonic-gate 	int		rc = NS_LDAP_SUCCESS;
6720Sstevel@tonic-gate 	int		return_rc = NS_LDAP_SUCCESS;
6730Sstevel@tonic-gate 	int		followRef = FALSE;
6740Sstevel@tonic-gate 	int		target_dn_allocated = FALSE;
6750Sstevel@tonic-gate 	int		len;
6760Sstevel@tonic-gate 	int		msgid;
6770Sstevel@tonic-gate 	int		Errno;
67811884SMichen.Chang@Sun.COM 	boolean_t	from_get_lderrno = B_FALSE;
6790Sstevel@tonic-gate 	int		always = 1;
6800Sstevel@tonic-gate 	char		*err, *errmsg = NULL;
681441Ssdussud 	/* referrals returned by the LDAP operation */
6820Sstevel@tonic-gate 	char		**referrals = NULL;
683441Ssdussud 	/*
684441Ssdussud 	 * list of referrals used by the state machine, built from
685441Ssdussud 	 * the referrals variable above
686441Ssdussud 	 */
687441Ssdussud 	ns_referral_info_t *ref_list = NULL;
688441Ssdussud 	/* current referral */
689441Ssdussud 	ns_referral_info_t *current_ref = NULL;
6900Sstevel@tonic-gate 	ns_write_state_t state = W_INIT, new_state, err_state = W_INIT;
6910Sstevel@tonic-gate 	int		do_not_fail_if_new_pwd_reqd = 0;
6920Sstevel@tonic-gate 	ns_ldap_passwd_status_t	pwd_status = NS_PASSWD_GOOD;
6930Sstevel@tonic-gate 	int		passwd_mgmt = 0;
694441Ssdussud 	int		i = 0;
695441Ssdussud 	int		ldap_error;
6961179Svv149972 	int		nopasswd_acct_mgmt = 0;
6976842Sth160488 	ns_conn_user_t	*conn_user = NULL;
6980Sstevel@tonic-gate 
6990Sstevel@tonic-gate 	while (always) {
7000Sstevel@tonic-gate 		switch (state) {
7010Sstevel@tonic-gate 		case W_EXIT:
7026842Sth160488 			/* return the MT connection and free the conn user */
7036842Sth160488 			if (conn_user != NULL) {
7046842Sth160488 				if (conn_user->use_mt_conn == B_TRUE) {
7056842Sth160488 					if (conn_user->ns_error != NULL) {
7066842Sth160488 						*errorp = conn_user->ns_error;
7076842Sth160488 						conn_user->ns_error = NULL;
7086842Sth160488 						return_rc = conn_user->ns_rc;
7096842Sth160488 					}
7106842Sth160488 					if (conn_user->conn_mt != NULL)
7116842Sth160488 						__s_api_conn_mt_return(
7126842Sth160488 						    conn_user);
7136842Sth160488 				}
7146842Sth160488 				__s_api_conn_user_free(conn_user);
7156842Sth160488 			}
7166842Sth160488 
7170Sstevel@tonic-gate 			if (connectionId > -1)
7182830Sdjl 				DropConnection(connectionId, NS_LDAP_NEW_CONN);
719441Ssdussud 			if (ref_list)
720441Ssdussud 				__s_api_deleteRefInfo(ref_list);
7210Sstevel@tonic-gate 			if (target_dn && target_dn_allocated)
7220Sstevel@tonic-gate 				free(target_dn);
7230Sstevel@tonic-gate 			return (return_rc);
7240Sstevel@tonic-gate 		case W_INIT:
7250Sstevel@tonic-gate 			/* see if need to follow referrals */
7260Sstevel@tonic-gate 			rc = __s_api_toFollowReferrals(flags,
7276842Sth160488 			    &followRef, errorp);
7280Sstevel@tonic-gate 			if (rc != NS_LDAP_SUCCESS) {
7290Sstevel@tonic-gate 				return_rc = rc;
7300Sstevel@tonic-gate 				new_state = W_ERROR;
7310Sstevel@tonic-gate 				break;
7320Sstevel@tonic-gate 			}
7330Sstevel@tonic-gate 			len = strlen(dn);
7340Sstevel@tonic-gate 			if (dn[len-1] == COMMATOK)
7350Sstevel@tonic-gate 				rc = __s_api_append_default_basedn(
7366842Sth160488 				    dn, &target_dn, &target_dn_allocated,
7376842Sth160488 				    errorp);
7380Sstevel@tonic-gate 			else
7390Sstevel@tonic-gate 				target_dn = dn;
7400Sstevel@tonic-gate 			if (rc != NS_LDAP_SUCCESS) {
7410Sstevel@tonic-gate 				return_rc = rc;
7420Sstevel@tonic-gate 				new_state = W_ERROR;
7430Sstevel@tonic-gate 			}
7440Sstevel@tonic-gate 			else
7450Sstevel@tonic-gate 				new_state = GET_CONNECTION;
7460Sstevel@tonic-gate 			break;
7470Sstevel@tonic-gate 		case GET_CONNECTION:
7486842Sth160488 			/* identify self as a write user */
7496842Sth160488 			conn_user = __s_api_conn_user_init(NS_CONN_USER_WRITE,
7506842Sth160488 			    NULL, B_FALSE);
7510Sstevel@tonic-gate 			rc = __s_api_getConnection(NULL,
7526842Sth160488 			    flags, cred, &connectionId, &conp, errorp,
7536842Sth160488 			    do_not_fail_if_new_pwd_reqd, nopasswd_acct_mgmt,
7546842Sth160488 			    conn_user);
7550Sstevel@tonic-gate 
7560Sstevel@tonic-gate 			/*
7570Sstevel@tonic-gate 			 * If password control attached
7580Sstevel@tonic-gate 			 * in *errorp,
7590Sstevel@tonic-gate 			 * e.g. rc == NS_LDAP_SUCCESS_WITH_INFO,
7600Sstevel@tonic-gate 			 * free the error structure (we do not need
7610Sstevel@tonic-gate 			 * the password management info).
7620Sstevel@tonic-gate 			 * Reset rc to NS_LDAP_SUCCESS.
7630Sstevel@tonic-gate 			 */
7640Sstevel@tonic-gate 			if (rc == NS_LDAP_SUCCESS_WITH_INFO) {
7656842Sth160488 				(void) __ns_ldap_freeError(errorp);
7660Sstevel@tonic-gate 				*errorp = NULL;
7670Sstevel@tonic-gate 				rc = NS_LDAP_SUCCESS;
7680Sstevel@tonic-gate 			}
7690Sstevel@tonic-gate 
7700Sstevel@tonic-gate 			if (rc != NS_LDAP_SUCCESS) {
7710Sstevel@tonic-gate 				return_rc = rc;
7720Sstevel@tonic-gate 				new_state = W_ERROR;
7730Sstevel@tonic-gate 				break;
7740Sstevel@tonic-gate 			}
7750Sstevel@tonic-gate 			if (followRef)
7760Sstevel@tonic-gate 				new_state = SELECT_OPERATION_ASYNC;
7770Sstevel@tonic-gate 			else
7780Sstevel@tonic-gate 				new_state = SELECT_OPERATION_SYNC;
7790Sstevel@tonic-gate 			break;
7800Sstevel@tonic-gate 		case SELECT_OPERATION_SYNC:
7810Sstevel@tonic-gate 			if (ldap_op == LDAP_REQ_ADD)
7820Sstevel@tonic-gate 				new_state = DO_ADD_SYNC;
7830Sstevel@tonic-gate 			else if (ldap_op == LDAP_REQ_DELETE)
7840Sstevel@tonic-gate 				new_state = DO_DELETE_SYNC;
7850Sstevel@tonic-gate 			else if (ldap_op == LDAP_REQ_MODIFY)
7860Sstevel@tonic-gate 				new_state = DO_MODIFY_SYNC;
7870Sstevel@tonic-gate 			break;
7880Sstevel@tonic-gate 		case SELECT_OPERATION_ASYNC:
7890Sstevel@tonic-gate 			if (ldap_op == LDAP_REQ_ADD)
7900Sstevel@tonic-gate 				new_state = DO_ADD_ASYNC;
7910Sstevel@tonic-gate 			else if (ldap_op == LDAP_REQ_DELETE)
7920Sstevel@tonic-gate 				new_state = DO_DELETE_ASYNC;
7930Sstevel@tonic-gate 			else if (ldap_op == LDAP_REQ_MODIFY)
7940Sstevel@tonic-gate 				new_state = DO_MODIFY_ASYNC;
7950Sstevel@tonic-gate 			break;
7960Sstevel@tonic-gate 		case DO_ADD_SYNC:
7970Sstevel@tonic-gate 			rc = ldap_add_ext_s(conp->ld, target_dn,
7986842Sth160488 			    mods, NULL, NULL);
7990Sstevel@tonic-gate 			new_state = GET_RESULT_SYNC;
8000Sstevel@tonic-gate 			break;
8010Sstevel@tonic-gate 		case DO_DELETE_SYNC:
8020Sstevel@tonic-gate 			rc = ldap_delete_ext_s(conp->ld, target_dn,
8036842Sth160488 			    NULL, NULL);
8040Sstevel@tonic-gate 			new_state = GET_RESULT_SYNC;
8050Sstevel@tonic-gate 			break;
8060Sstevel@tonic-gate 		case DO_MODIFY_SYNC:
8070Sstevel@tonic-gate 			rc = ldap_modify_ext_s(conp->ld, target_dn,
8086842Sth160488 			    mods, NULL, NULL);
8090Sstevel@tonic-gate 			new_state = GET_RESULT_SYNC;
8100Sstevel@tonic-gate 			break;
8110Sstevel@tonic-gate 		case DO_ADD_ASYNC:
8120Sstevel@tonic-gate 			rc = ldap_add_ext(conp->ld, target_dn,
8136842Sth160488 			    mods, NULL, NULL, &msgid);
8140Sstevel@tonic-gate 			new_state = GET_RESULT_ASYNC;
8150Sstevel@tonic-gate 			break;
8160Sstevel@tonic-gate 		case DO_DELETE_ASYNC:
8170Sstevel@tonic-gate 			rc = ldap_delete_ext(conp->ld, target_dn,
8186842Sth160488 			    NULL, NULL, &msgid);
8190Sstevel@tonic-gate 			new_state = GET_RESULT_ASYNC;
8200Sstevel@tonic-gate 			break;
8210Sstevel@tonic-gate 		case DO_MODIFY_ASYNC:
8220Sstevel@tonic-gate 			rc = ldap_modify_ext(conp->ld, target_dn,
8236842Sth160488 			    mods, NULL, NULL, &msgid);
8240Sstevel@tonic-gate 			new_state = GET_RESULT_ASYNC;
8250Sstevel@tonic-gate 			break;
8260Sstevel@tonic-gate 		case GET_RESULT_SYNC:
8270Sstevel@tonic-gate 			if (rc != LDAP_SUCCESS) {
8280Sstevel@tonic-gate 				Errno = rc;
8290Sstevel@tonic-gate 				(void) ldap_get_lderrno(conp->ld,
8306842Sth160488 				    NULL, &errmsg);
83111884SMichen.Chang@Sun.COM 
8320Sstevel@tonic-gate 				/*
83311884SMichen.Chang@Sun.COM 				 * No need to deal with the error message if
83411884SMichen.Chang@Sun.COM 				 * it's an empty string.
8350Sstevel@tonic-gate 				 */
83611884SMichen.Chang@Sun.COM 				if (errmsg != NULL && *errmsg == '\0')
8370Sstevel@tonic-gate 					errmsg = NULL;
83811884SMichen.Chang@Sun.COM 
83911884SMichen.Chang@Sun.COM 				if (errmsg != NULL) {
84011884SMichen.Chang@Sun.COM 					/*
84111884SMichen.Chang@Sun.COM 					 * ldap_get_lderrno does not expect
84211884SMichen.Chang@Sun.COM 					 * errmsg to be freed after use, while
84311884SMichen.Chang@Sun.COM 					 * ldap_parse_result below does, so set
84411884SMichen.Chang@Sun.COM 					 * a flag to indicate source.
84511884SMichen.Chang@Sun.COM 					 */
84611884SMichen.Chang@Sun.COM 					from_get_lderrno = B_TRUE;
8470Sstevel@tonic-gate 				}
84811884SMichen.Chang@Sun.COM 
8490Sstevel@tonic-gate 				new_state = W_LDAP_ERROR;
8500Sstevel@tonic-gate 			} else {
8510Sstevel@tonic-gate 				return_rc = NS_LDAP_SUCCESS;
8520Sstevel@tonic-gate 				new_state = W_EXIT;
8530Sstevel@tonic-gate 			}
8540Sstevel@tonic-gate 			break;
8550Sstevel@tonic-gate 		case GET_RESULT_ASYNC:
8560Sstevel@tonic-gate 			rc = ldap_result(conp->ld, msgid, 1,
8576842Sth160488 			    (struct timeval *)NULL, &res);
8580Sstevel@tonic-gate 			/* if no server response, set Errno */
8590Sstevel@tonic-gate 			if (rc == -1) {
8600Sstevel@tonic-gate 				(void) ldap_get_option(conp->ld,
8610Sstevel@tonic-gate 				    LDAP_OPT_ERROR_NUMBER, &Errno);
8620Sstevel@tonic-gate 				new_state = W_LDAP_ERROR;
8630Sstevel@tonic-gate 				break;
8640Sstevel@tonic-gate 			}
8656842Sth160488 			if (rc == LDAP_RES_ADD || rc == LDAP_RES_MODIFY ||
8666842Sth160488 			    rc == LDAP_RES_DELETE) {
8670Sstevel@tonic-gate 				new_state = PARSE_RESULT;
8680Sstevel@tonic-gate 				break;
8690Sstevel@tonic-gate 			} else {
8700Sstevel@tonic-gate 				return_rc = rc;
8710Sstevel@tonic-gate 				new_state = W_ERROR;
8720Sstevel@tonic-gate 			}
8730Sstevel@tonic-gate 			break;
8740Sstevel@tonic-gate 		case PARSE_RESULT:
8750Sstevel@tonic-gate 			/*
8760Sstevel@tonic-gate 			 * need Errno, referrals, error msg,
8770Sstevel@tonic-gate 			 * and the last "1" is to free
8780Sstevel@tonic-gate 			 * the result (res)
8790Sstevel@tonic-gate 			 */
8806842Sth160488 			rc = ldap_parse_result(conp->ld, res, &Errno,
8816842Sth160488 			    NULL, &errmsg, &referrals, NULL, 1);
8820Sstevel@tonic-gate 			/*
8830Sstevel@tonic-gate 			 * free errmsg if it is an empty string
8840Sstevel@tonic-gate 			 */
8850Sstevel@tonic-gate 			if (errmsg && *errmsg == '\0') {
8860Sstevel@tonic-gate 				ldap_memfree(errmsg);
8870Sstevel@tonic-gate 				errmsg = NULL;
8880Sstevel@tonic-gate 			}
889441Ssdussud 			/*
890441Ssdussud 			 * If we received referral data, process
891441Ssdussud 			 * it if:
892441Ssdussud 			 * - we are configured to follow referrals
893441Ssdussud 			 * - and not already in referral mode (to keep
894441Ssdussud 			 *   consistency with search_state_machine()
895441Ssdussud 			 *   which follows 1 level of referrals only;
896441Ssdussud 			 *   see proc_result_referrals() and
897441Ssdussud 			 *   proc_search_references().
898441Ssdussud 			 */
899441Ssdussud 			if (Errno == LDAP_REFERRAL && followRef && !ref_list) {
900441Ssdussud 				for (i = 0; referrals[i] != NULL; i++) {
901441Ssdussud 					/* add to referral list */
902441Ssdussud 					rc = __s_api_addRefInfo(&ref_list,
9036842Sth160488 					    referrals[i], NULL, NULL, NULL,
9046842Sth160488 					    conp->ld);
905441Ssdussud 					if (rc != NS_LDAP_SUCCESS) {
906441Ssdussud 						__s_api_deleteRefInfo(ref_list);
907441Ssdussud 						ref_list = NULL;
908441Ssdussud 						break;
909441Ssdussud 					}
9100Sstevel@tonic-gate 				}
9110Sstevel@tonic-gate 				ldap_value_free(referrals);
912441Ssdussud 				if (ref_list == NULL) {
9130Sstevel@tonic-gate 					if (rc != NS_LDAP_MEMORY)
9140Sstevel@tonic-gate 						rc = NS_LDAP_INTERNAL;
915441Ssdussud 					return_rc = rc;
9160Sstevel@tonic-gate 					new_state = W_ERROR;
917441Ssdussud 				} else {
9180Sstevel@tonic-gate 					new_state = GET_REFERRAL_CONNECTION;
919441Ssdussud 					current_ref = ref_list;
920441Ssdussud 				}
9210Sstevel@tonic-gate 				if (errmsg) {
9220Sstevel@tonic-gate 					ldap_memfree(errmsg);
9230Sstevel@tonic-gate 					errmsg = NULL;
9240Sstevel@tonic-gate 				}
9250Sstevel@tonic-gate 				break;
9260Sstevel@tonic-gate 			}
9270Sstevel@tonic-gate 			if (Errno != LDAP_SUCCESS) {
9280Sstevel@tonic-gate 				new_state = W_LDAP_ERROR;
9290Sstevel@tonic-gate 			} else {
9300Sstevel@tonic-gate 				return_rc = NS_LDAP_SUCCESS;
9310Sstevel@tonic-gate 				new_state = W_EXIT;
9320Sstevel@tonic-gate 			}
9330Sstevel@tonic-gate 			break;
9340Sstevel@tonic-gate 		case GET_REFERRAL_CONNECTION:
935441Ssdussud 			/*
936441Ssdussud 			 * since we are starting over,
937441Ssdussud 			 * discard the old error info
938441Ssdussud 			 */
939441Ssdussud 			return_rc = NS_LDAP_SUCCESS;
940441Ssdussud 			if (*errorp)
941441Ssdussud 				(void) __ns_ldap_freeError(errorp);
9420Sstevel@tonic-gate 			if (connectionId > -1)
9432830Sdjl 				DropConnection(connectionId, NS_LDAP_NEW_CONN);
9446842Sth160488 
9456842Sth160488 			/* set it up to use a referral connection */
9466842Sth160488 			if (conn_user != NULL) {
9476842Sth160488 				/*
9486842Sth160488 				 * If an MT connection is being used,
9496842Sth160488 				 * return it to the pool.
9506842Sth160488 				 */
9516842Sth160488 				if (conn_user->conn_mt != NULL)
9526842Sth160488 					__s_api_conn_mt_return(conn_user);
9536842Sth160488 
9546842Sth160488 				conn_user->referral = B_TRUE;
9556842Sth160488 			}
956441Ssdussud 			rc = __s_api_getConnection(current_ref->refHost,
9576842Sth160488 			    0, cred, &connectionId, &conp, errorp,
9586842Sth160488 			    do_not_fail_if_new_pwd_reqd,
9596842Sth160488 			    nopasswd_acct_mgmt, conn_user);
9600Sstevel@tonic-gate 
9610Sstevel@tonic-gate 			/*
9620Sstevel@tonic-gate 			 * If password control attached
9630Sstevel@tonic-gate 			 * in errorp,
9640Sstevel@tonic-gate 			 * e.g. rc == NS_LDAP_SUCCESS_WITH_INFO,
9650Sstevel@tonic-gate 			 * free the error structure (we do not need
9660Sstevel@tonic-gate 			 * the password management info).
9670Sstevel@tonic-gate 			 * Reset rc to NS_LDAP_SUCCESS.
9680Sstevel@tonic-gate 			 */
9690Sstevel@tonic-gate 			if (rc == NS_LDAP_SUCCESS_WITH_INFO) {
9706842Sth160488 				(void) __ns_ldap_freeError(errorp);
9710Sstevel@tonic-gate 				*errorp = NULL;
9720Sstevel@tonic-gate 				rc = NS_LDAP_SUCCESS;
9730Sstevel@tonic-gate 			}
9740Sstevel@tonic-gate 
9750Sstevel@tonic-gate 			if (rc != NS_LDAP_SUCCESS) {
9760Sstevel@tonic-gate 				return_rc = rc;
977441Ssdussud 				/*
978441Ssdussud 				 * If current referral is not
979441Ssdussud 				 * available for some reason,
980441Ssdussud 				 * try next referral in the list.
981441Ssdussud 				 * Get LDAP error code from errorp.
982441Ssdussud 				 */
983441Ssdussud 				if (*errorp != NULL) {
9846842Sth160488 					ns_write_state_t get_ref =
9856842Sth160488 					    GET_REFERRAL_CONNECTION;
9866842Sth160488 
987441Ssdussud 					ldap_error = (*errorp)->status;
988441Ssdussud 					if (ldap_error == LDAP_BUSY ||
989441Ssdussud 					    ldap_error == LDAP_UNAVAILABLE ||
990441Ssdussud 					    ldap_error ==
9916842Sth160488 					    LDAP_UNWILLING_TO_PERFORM ||
992441Ssdussud 					    ldap_error == LDAP_CONNECT_ERROR ||
993441Ssdussud 					    ldap_error == LDAP_SERVER_DOWN) {
994441Ssdussud 						current_ref = current_ref->next;
995441Ssdussud 						if (current_ref == NULL) {
9966842Sth160488 						/* no more referral to follow */
9976842Sth160488 							new_state = W_ERROR;
9986842Sth160488 						} else
9996842Sth160488 							new_state = get_ref;
1000441Ssdussud 						/*
1001441Ssdussud 						 * free errorp before going to
1002441Ssdussud 						 * next referral
1003441Ssdussud 						 */
1004441Ssdussud 						(void) __ns_ldap_freeError(
10056842Sth160488 						    errorp);
1006441Ssdussud 						*errorp = NULL;
1007441Ssdussud 						break;
1008441Ssdussud 					}
1009441Ssdussud 					/*
1010441Ssdussud 					 * free errorp before going to W_ERROR
1011441Ssdussud 					 */
1012441Ssdussud 					(void) __ns_ldap_freeError(errorp);
1013441Ssdussud 					*errorp = NULL;
1014441Ssdussud 				}
1015441Ssdussud 				/* else, exit */
1016441Ssdussud 				__s_api_deleteRefInfo(ref_list);
1017441Ssdussud 				ref_list = NULL;
10180Sstevel@tonic-gate 				new_state = W_ERROR;
10196842Sth160488 				if (conn_user != NULL)
10206842Sth160488 					conn_user->referral = B_FALSE;
10210Sstevel@tonic-gate 				break;
10220Sstevel@tonic-gate 			}
10230Sstevel@tonic-gate 			/* target DN may changed due to referrals */
1024441Ssdussud 			if (current_ref->refDN) {
10250Sstevel@tonic-gate 				if (target_dn && target_dn_allocated) {
10260Sstevel@tonic-gate 					free(target_dn);
10270Sstevel@tonic-gate 					target_dn = NULL;
10280Sstevel@tonic-gate 					target_dn_allocated = FALSE;
10290Sstevel@tonic-gate 				}
1030441Ssdussud 				target_dn = current_ref->refDN;
10310Sstevel@tonic-gate 			}
10320Sstevel@tonic-gate 			new_state = SELECT_OPERATION_SYNC;
10330Sstevel@tonic-gate 			break;
10340Sstevel@tonic-gate 		case W_LDAP_ERROR:
10350Sstevel@tonic-gate 			/*
10360Sstevel@tonic-gate 			 * map error code and error message
10370Sstevel@tonic-gate 			 * to password status if necessary.
10380Sstevel@tonic-gate 			 * This is to see if password updates
10390Sstevel@tonic-gate 			 * failed due to password policy or
10400Sstevel@tonic-gate 			 * password syntax checking.
10410Sstevel@tonic-gate 			 */
10420Sstevel@tonic-gate 			if (errmsg) {
10430Sstevel@tonic-gate 				/*
10440Sstevel@tonic-gate 				 * check if server supports
10450Sstevel@tonic-gate 				 * password management
10460Sstevel@tonic-gate 				 */
10470Sstevel@tonic-gate 				passwd_mgmt =
10486842Sth160488 				    __s_api_contain_passwd_control_oid(
10496842Sth160488 				    conp->controls);
10500Sstevel@tonic-gate 					if (passwd_mgmt)
10510Sstevel@tonic-gate 						pwd_status =
10526842Sth160488 						    __s_api_set_passwd_status(
10536842Sth160488 						    Errno, errmsg);
105411884SMichen.Chang@Sun.COM 				/*
105511884SMichen.Chang@Sun.COM 				 * free only if not returned by ldap_get_lderrno
105611884SMichen.Chang@Sun.COM 				 */
105711884SMichen.Chang@Sun.COM 				if (!from_get_lderrno)
105811884SMichen.Chang@Sun.COM 					ldap_memfree(errmsg);
10590Sstevel@tonic-gate 				errmsg = NULL;
106011884SMichen.Chang@Sun.COM 				from_get_lderrno = B_FALSE;
10610Sstevel@tonic-gate 			}
10620Sstevel@tonic-gate 
10638821SMichen.Chang@Sun.COM 			(void) snprintf(errstr, sizeof (errstr),
10648821SMichen.Chang@Sun.COM 			    "%s", ldap_err2string(Errno));
10650Sstevel@tonic-gate 			err = strdup(errstr);
10660Sstevel@tonic-gate 			if (pwd_status != NS_PASSWD_GOOD) {
10670Sstevel@tonic-gate 				MKERROR_PWD_MGMT(*errorp, Errno, err,
10686842Sth160488 				    pwd_status, 0, NULL);
10690Sstevel@tonic-gate 			} else {
10700Sstevel@tonic-gate 				MKERROR(LOG_INFO, *errorp, Errno, err, NULL);
10710Sstevel@tonic-gate 			}
10726842Sth160488 			if (conn_user != NULL &&
10736842Sth160488 			    (Errno == LDAP_SERVER_DOWN ||
10746842Sth160488 			    Errno == LDAP_CONNECT_ERROR)) {
10756842Sth160488 				__s_api_conn_mt_close(conn_user, Errno, errorp);
10766842Sth160488 			}
10770Sstevel@tonic-gate 			return_rc = NS_LDAP_INTERNAL;
10780Sstevel@tonic-gate 			new_state = W_EXIT;
10790Sstevel@tonic-gate 			break;
10800Sstevel@tonic-gate 		case W_ERROR:
10810Sstevel@tonic-gate 		default:
10820Sstevel@tonic-gate 			(void) sprintf(errstr,
10836842Sth160488 			    gettext("Internal write State machine exit"
10846842Sth160488 			    " (state = %d, rc = %d)."),
10856842Sth160488 			    err_state, return_rc);
10860Sstevel@tonic-gate 			err = strdup(errstr);
10870Sstevel@tonic-gate 			MKERROR(LOG_WARNING, *errorp, return_rc, err, NULL);
10880Sstevel@tonic-gate 			new_state = W_EXIT;
10890Sstevel@tonic-gate 			break;
10900Sstevel@tonic-gate 		}
10910Sstevel@tonic-gate 
10920Sstevel@tonic-gate 		if (new_state == W_ERROR)
10930Sstevel@tonic-gate 			err_state = state;
10946842Sth160488 
10956842Sth160488 		if (conn_user != NULL && conn_user->bad_mt_conn == B_TRUE) {
10966842Sth160488 			__s_api_conn_mt_close(conn_user, 0, NULL);
10976842Sth160488 			new_state = W_EXIT;
10986842Sth160488 		}
10996842Sth160488 
11000Sstevel@tonic-gate 		state = new_state;
11010Sstevel@tonic-gate 	}
11020Sstevel@tonic-gate 
11030Sstevel@tonic-gate 	/*
11040Sstevel@tonic-gate 	 * should never be here, the next line is to eliminating
11050Sstevel@tonic-gate 	 * lint message
11060Sstevel@tonic-gate 	 */
11070Sstevel@tonic-gate 	return (NS_LDAP_INTERNAL);
11080Sstevel@tonic-gate }
11090Sstevel@tonic-gate 
11100Sstevel@tonic-gate 
11110Sstevel@tonic-gate /*ARGSUSED*/
11120Sstevel@tonic-gate int
__ns_ldap_addAttr(const char * service,const char * dn,const ns_ldap_attr_t * const * attr,const ns_cred_t * cred,const int flags,ns_ldap_error_t ** errorp)11130Sstevel@tonic-gate __ns_ldap_addAttr(
11140Sstevel@tonic-gate 	const char *service,
11150Sstevel@tonic-gate 	const char *dn,
11160Sstevel@tonic-gate 	const ns_ldap_attr_t * const *attr,
11170Sstevel@tonic-gate 	const ns_cred_t *cred,
11180Sstevel@tonic-gate 	const int flags,
11190Sstevel@tonic-gate 	ns_ldap_error_t ** errorp)
11200Sstevel@tonic-gate {
11210Sstevel@tonic-gate 	LDAPMod		**mods;
11220Sstevel@tonic-gate 	int		rc = 0;
11230Sstevel@tonic-gate 
11240Sstevel@tonic-gate #ifdef DEBUG
11250Sstevel@tonic-gate 	(void) fprintf(stderr, "__ns_ldap_addAttr START\n");
11260Sstevel@tonic-gate #endif
11270Sstevel@tonic-gate 	*errorp = NULL;
11280Sstevel@tonic-gate 
11290Sstevel@tonic-gate 	/* Sanity check */
11300Sstevel@tonic-gate 	if ((attr == NULL) || (*attr == NULL) ||
11310Sstevel@tonic-gate 	    (dn == NULL) || (cred == NULL))
11320Sstevel@tonic-gate 		return (NS_LDAP_INVALID_PARAM);
11330Sstevel@tonic-gate 
11340Sstevel@tonic-gate 	mods = __s_api_makeModList(service, attr, LDAP_MOD_ADD, flags);
11350Sstevel@tonic-gate 	if (mods == NULL) {
11360Sstevel@tonic-gate 		return (NS_LDAP_MEMORY);
11370Sstevel@tonic-gate 	}
11380Sstevel@tonic-gate 
11390Sstevel@tonic-gate 	rc = write_state_machine(LDAP_REQ_MODIFY,
11400Sstevel@tonic-gate 	    (char *)dn, mods, cred, flags, errorp);
11410Sstevel@tonic-gate 	freeModList(mods);
11420Sstevel@tonic-gate 
11430Sstevel@tonic-gate 	return (rc);
11440Sstevel@tonic-gate }
11450Sstevel@tonic-gate 
11460Sstevel@tonic-gate 
11470Sstevel@tonic-gate /*ARGSUSED*/
11480Sstevel@tonic-gate int
__ns_ldap_delAttr(const char * service,const char * dn,const ns_ldap_attr_t * const * attr,const ns_cred_t * cred,const int flags,ns_ldap_error_t ** errorp)11490Sstevel@tonic-gate __ns_ldap_delAttr(
11500Sstevel@tonic-gate 	const char *service,
11510Sstevel@tonic-gate 	const char *dn,
11520Sstevel@tonic-gate 	const ns_ldap_attr_t * const *attr,
11530Sstevel@tonic-gate 	const ns_cred_t *cred,
11540Sstevel@tonic-gate 	const int flags,
11550Sstevel@tonic-gate 	ns_ldap_error_t ** errorp)
11560Sstevel@tonic-gate {
11570Sstevel@tonic-gate 	LDAPMod		**mods;
11580Sstevel@tonic-gate 	int		rc = 0;
11590Sstevel@tonic-gate 
11600Sstevel@tonic-gate #ifdef DEBUG
11610Sstevel@tonic-gate 	(void) fprintf(stderr, "__ns_ldap_delAttr START\n");
11620Sstevel@tonic-gate #endif
11630Sstevel@tonic-gate 	*errorp = NULL;
11640Sstevel@tonic-gate 
11650Sstevel@tonic-gate 	/* Sanity check */
11660Sstevel@tonic-gate 	if ((attr == NULL) || (*attr == NULL) ||
11670Sstevel@tonic-gate 	    (dn == NULL) || (cred == NULL))
11680Sstevel@tonic-gate 		return (NS_LDAP_INVALID_PARAM);
11690Sstevel@tonic-gate 
11700Sstevel@tonic-gate 	mods = __s_api_makeModList(service, attr, LDAP_MOD_DELETE, flags);
11710Sstevel@tonic-gate 	if (mods == NULL) {
11720Sstevel@tonic-gate 		return (NS_LDAP_MEMORY);
11730Sstevel@tonic-gate 	}
11740Sstevel@tonic-gate 
11750Sstevel@tonic-gate 	rc = write_state_machine(LDAP_REQ_MODIFY,
11760Sstevel@tonic-gate 	    (char *)dn, mods, cred, flags, errorp);
11770Sstevel@tonic-gate 
11780Sstevel@tonic-gate 	freeModList(mods);
11790Sstevel@tonic-gate 	return (rc);
11800Sstevel@tonic-gate }
11810Sstevel@tonic-gate 
11828821SMichen.Chang@Sun.COM /* Retrieve the admin bind password from the configuration, if allowed. */
11838821SMichen.Chang@Sun.COM static int
get_admin_passwd(ns_cred_t * cred,ns_ldap_error_t ** errorp)11848821SMichen.Chang@Sun.COM get_admin_passwd(ns_cred_t *cred, ns_ldap_error_t **errorp)
11858821SMichen.Chang@Sun.COM {
11868821SMichen.Chang@Sun.COM 	void	**paramVal = NULL;
11878821SMichen.Chang@Sun.COM 	int	rc, ldaprc;
11888821SMichen.Chang@Sun.COM 	char	*modparamVal = NULL;
11898821SMichen.Chang@Sun.COM 
11908821SMichen.Chang@Sun.COM 	/*
11918821SMichen.Chang@Sun.COM 	 * For GSSAPI/Kerberos, host credential is used, no need to get
11928821SMichen.Chang@Sun.COM 	 * admin bind password
11938821SMichen.Chang@Sun.COM 	 */
11948821SMichen.Chang@Sun.COM 	if (cred->auth.saslmech == NS_LDAP_SASL_GSSAPI)
11958821SMichen.Chang@Sun.COM 		return (NS_LDAP_SUCCESS);
11968821SMichen.Chang@Sun.COM 
11978821SMichen.Chang@Sun.COM 	/*
11988821SMichen.Chang@Sun.COM 	 * Retrieve admin bind password.
11998821SMichen.Chang@Sun.COM 	 * The admin bind password is available
12008821SMichen.Chang@Sun.COM 	 * only in the ldap_cachemgr process as
12018821SMichen.Chang@Sun.COM 	 * they are not exposed outside of that
12028821SMichen.Chang@Sun.COM 	 * process.
12038821SMichen.Chang@Sun.COM 	 */
12048821SMichen.Chang@Sun.COM 	paramVal = NULL;
12058821SMichen.Chang@Sun.COM 	if ((ldaprc = __ns_ldap_getParam(NS_LDAP_ADMIN_BINDPASSWD_P,
12068821SMichen.Chang@Sun.COM 	    &paramVal, errorp)) != NS_LDAP_SUCCESS)
12078821SMichen.Chang@Sun.COM 		return (ldaprc);
12088821SMichen.Chang@Sun.COM 	if (paramVal == NULL || *paramVal == NULL) {
12098821SMichen.Chang@Sun.COM 		rc = NS_LDAP_CONFIG;
12108821SMichen.Chang@Sun.COM 		*errorp = __s_api_make_error(NS_CONFIG_NODEFAULT,
12118821SMichen.Chang@Sun.COM 		    gettext("Admin bind password not configured"));
12128821SMichen.Chang@Sun.COM 		if (*errorp == NULL)
12138821SMichen.Chang@Sun.COM 			rc = NS_LDAP_MEMORY;
12148821SMichen.Chang@Sun.COM 		return (rc);
12158821SMichen.Chang@Sun.COM 	}
12168821SMichen.Chang@Sun.COM 	modparamVal = dvalue((char *)*paramVal);
12178821SMichen.Chang@Sun.COM 	(void) memset(*paramVal, 0, strlen((char *)*paramVal));
12188821SMichen.Chang@Sun.COM 	(void) __ns_ldap_freeParam(&paramVal);
12198821SMichen.Chang@Sun.COM 	if (modparamVal == NULL || *((char *)modparamVal) == '\0') {
12208821SMichen.Chang@Sun.COM 		if (modparamVal != NULL)
12218821SMichen.Chang@Sun.COM 			free(modparamVal);
12228821SMichen.Chang@Sun.COM 		rc = NS_LDAP_CONFIG;
12238821SMichen.Chang@Sun.COM 		*errorp = __s_api_make_error(NS_CONFIG_SYNTAX,
12248821SMichen.Chang@Sun.COM 		    gettext("bind password not valid"));
12258821SMichen.Chang@Sun.COM 		if (*errorp == NULL)
12268821SMichen.Chang@Sun.COM 			rc = NS_LDAP_MEMORY;
12278821SMichen.Chang@Sun.COM 		return (rc);
12288821SMichen.Chang@Sun.COM 	}
12298821SMichen.Chang@Sun.COM 
12308821SMichen.Chang@Sun.COM 	cred->cred.unix_cred.passwd = modparamVal;
12318821SMichen.Chang@Sun.COM 	return (NS_LDAP_SUCCESS);
12328821SMichen.Chang@Sun.COM }
12338821SMichen.Chang@Sun.COM 
12348821SMichen.Chang@Sun.COM boolean_t
__ns_ldap_is_shadow_update_enabled(void)1235*12882SJulian.Pullen@Sun.COM __ns_ldap_is_shadow_update_enabled(void)
1236*12882SJulian.Pullen@Sun.COM {
1237*12882SJulian.Pullen@Sun.COM 	int			**enable_shadow = NULL;
1238*12882SJulian.Pullen@Sun.COM 	ns_ldap_error_t		*errorp = NULL;
12398821SMichen.Chang@Sun.COM 
12408821SMichen.Chang@Sun.COM 	if (__ns_ldap_getParam(NS_LDAP_ENABLE_SHADOW_UPDATE_P,
1241*12882SJulian.Pullen@Sun.COM 	    (void ***)&enable_shadow, &errorp) != NS_LDAP_SUCCESS) {
1242*12882SJulian.Pullen@Sun.COM 		if (errorp)
1243*12882SJulian.Pullen@Sun.COM 			(void) __ns_ldap_freeError(&errorp);
12448821SMichen.Chang@Sun.COM 		return (B_FALSE);
12458821SMichen.Chang@Sun.COM 	}
12468821SMichen.Chang@Sun.COM 	if ((enable_shadow != NULL && *enable_shadow != NULL) &&
12478821SMichen.Chang@Sun.COM 	    (*enable_shadow[0] == NS_LDAP_ENABLE_SHADOW_UPDATE_TRUE)) {
12488821SMichen.Chang@Sun.COM 		(void) __ns_ldap_freeParam((void ***)&enable_shadow);
12498821SMichen.Chang@Sun.COM 		return (B_TRUE);
12508821SMichen.Chang@Sun.COM 	}
12518821SMichen.Chang@Sun.COM 	if (enable_shadow != NULL)
12528821SMichen.Chang@Sun.COM 		(void) __ns_ldap_freeParam((void ***)&enable_shadow);
12538821SMichen.Chang@Sun.COM 	return (B_FALSE);
12548821SMichen.Chang@Sun.COM }
12558821SMichen.Chang@Sun.COM 
12568821SMichen.Chang@Sun.COM /*
12578821SMichen.Chang@Sun.COM  * __ns_ldap_repAttr modifies ldap attributes of the 'dn' entry stored
12588821SMichen.Chang@Sun.COM  * on the LDAP server. 'service' indicates the type of database entries
12598821SMichen.Chang@Sun.COM  * to modify. When the Native LDAP client is configured with 'shadow update
12608821SMichen.Chang@Sun.COM  * enabled', Shadowshadow(4) entries can only be modified by privileged users.
12618821SMichen.Chang@Sun.COM  * Such users use the NS_LDAP_UPDATE_SHADOW flag to indicate the call is
12628821SMichen.Chang@Sun.COM  * for such a shadow(4) update, which would be forwarded to ldap_cachemgr
12638821SMichen.Chang@Sun.COM  * for performing the LDAP modify operation. ldap_cachemgr would call
12648821SMichen.Chang@Sun.COM  * this function again and use the special service NS_ADMIN_SHADOW_UPDATE
12658821SMichen.Chang@Sun.COM  * to identify itself, so that admin credential would be obtained and
12668821SMichen.Chang@Sun.COM  * the actual LDAP modify operation be done.
12678821SMichen.Chang@Sun.COM  */
12680Sstevel@tonic-gate /*ARGSUSED*/
12690Sstevel@tonic-gate int
__ns_ldap_repAttr(const char * service,const char * dn,const ns_ldap_attr_t * const * attr,const ns_cred_t * cred,const int flags,ns_ldap_error_t ** errorp)12700Sstevel@tonic-gate __ns_ldap_repAttr(
12710Sstevel@tonic-gate 	const char *service,
12720Sstevel@tonic-gate 	const char *dn,
12730Sstevel@tonic-gate 	const ns_ldap_attr_t * const *attr,
12740Sstevel@tonic-gate 	const ns_cred_t *cred,
12750Sstevel@tonic-gate 	const int flags,
12760Sstevel@tonic-gate 	ns_ldap_error_t ** errorp)
12770Sstevel@tonic-gate {
12780Sstevel@tonic-gate 	LDAPMod		**mods;
12790Sstevel@tonic-gate 	int		rc = 0;
12808821SMichen.Chang@Sun.COM 	boolean_t	priv;
12818821SMichen.Chang@Sun.COM 	boolean_t	shadow_update_enabled = B_FALSE;
12820Sstevel@tonic-gate 
12830Sstevel@tonic-gate #ifdef DEBUG
12840Sstevel@tonic-gate 	(void) fprintf(stderr, "__ns_ldap_repAttr START\n");
12850Sstevel@tonic-gate #endif
12860Sstevel@tonic-gate 	*errorp = NULL;
12870Sstevel@tonic-gate 
12880Sstevel@tonic-gate 	/* Sanity check */
12898821SMichen.Chang@Sun.COM 	if (attr == NULL || *attr == NULL || dn == NULL)
12900Sstevel@tonic-gate 		return (NS_LDAP_INVALID_PARAM);
12918821SMichen.Chang@Sun.COM 
12928821SMichen.Chang@Sun.COM 	/* Privileged shadow modify? */
12938821SMichen.Chang@Sun.COM 	if ((flags & NS_LDAP_UPDATE_SHADOW) != 0 &&
12948821SMichen.Chang@Sun.COM 	    strcmp(service, "shadow") == 0) {
12958821SMichen.Chang@Sun.COM 
12968821SMichen.Chang@Sun.COM 		/* Shadow update enabled ? If not, error out */
12978821SMichen.Chang@Sun.COM 		shadow_update_enabled = __ns_ldap_is_shadow_update_enabled();
12988821SMichen.Chang@Sun.COM 		if (!shadow_update_enabled) {
12998821SMichen.Chang@Sun.COM 			*errorp = __s_api_make_error(NS_CONFIG_NOTALLOW,
13008821SMichen.Chang@Sun.COM 			    gettext("Shadow Update is not enabled"));
13018821SMichen.Chang@Sun.COM 			return (NS_LDAP_CONFIG);
13028821SMichen.Chang@Sun.COM 		}
13038821SMichen.Chang@Sun.COM 
13048821SMichen.Chang@Sun.COM 		/* privileged shadow modify requires euid 0 or all zone privs */
13058821SMichen.Chang@Sun.COM 		priv = (geteuid() == 0);
13068821SMichen.Chang@Sun.COM 		if (!priv) {
13078821SMichen.Chang@Sun.COM 			priv_set_t *ps = priv_allocset();	/* caller */
13088821SMichen.Chang@Sun.COM 			priv_set_t *zs;				/* zone */
13098821SMichen.Chang@Sun.COM 
13108821SMichen.Chang@Sun.COM 			(void) getppriv(PRIV_EFFECTIVE, ps);
13118821SMichen.Chang@Sun.COM 			zs = priv_str_to_set("zone", ",", NULL);
13128821SMichen.Chang@Sun.COM 			priv = priv_isequalset(ps, zs);
13138821SMichen.Chang@Sun.COM 			priv_freeset(ps);
13148821SMichen.Chang@Sun.COM 			priv_freeset(zs);
13158821SMichen.Chang@Sun.COM 		}
13168821SMichen.Chang@Sun.COM 		if (!priv)
13178821SMichen.Chang@Sun.COM 			return (NS_LDAP_OP_FAILED);
13188821SMichen.Chang@Sun.COM 
13198821SMichen.Chang@Sun.COM 		rc = send_to_cachemgr(dn, (ns_ldap_attr_t **)attr, errorp);
13208821SMichen.Chang@Sun.COM 		return (rc);
13218821SMichen.Chang@Sun.COM 	}
13228821SMichen.Chang@Sun.COM 
13238821SMichen.Chang@Sun.COM 	if (cred == NULL)
13248821SMichen.Chang@Sun.COM 		return (NS_LDAP_INVALID_PARAM);
13258821SMichen.Chang@Sun.COM 
13268821SMichen.Chang@Sun.COM 	/*
13278821SMichen.Chang@Sun.COM 	 * If service is NS_ADMIN_SHADOW_UPDATE, the caller should be
13288821SMichen.Chang@Sun.COM 	 * ldap_cachemgr. We need to get the admin cred to do work.
13298821SMichen.Chang@Sun.COM 	 * If the caller is not ldap_cachemgr, but use the service
13308821SMichen.Chang@Sun.COM 	 * NS_ADMIN_SHADOW_UPDATE, get_admin_passwd() will fail,
13318821SMichen.Chang@Sun.COM 	 * as the admin cred is not available to the caller.
13328821SMichen.Chang@Sun.COM 	 */
13338821SMichen.Chang@Sun.COM 	if (strcmp(service, NS_ADMIN_SHADOW_UPDATE) == 0) {
13348821SMichen.Chang@Sun.COM 		if ((rc = get_admin_passwd((ns_cred_t *)cred, errorp)) !=
13358821SMichen.Chang@Sun.COM 		    NS_LDAP_SUCCESS)
13368821SMichen.Chang@Sun.COM 			return (rc);
13378821SMichen.Chang@Sun.COM 	}
13388821SMichen.Chang@Sun.COM 
13390Sstevel@tonic-gate 	mods = __s_api_makeModList(service, attr, LDAP_MOD_REPLACE, flags);
13408821SMichen.Chang@Sun.COM 	if (mods == NULL)
13410Sstevel@tonic-gate 		return (NS_LDAP_MEMORY);
13420Sstevel@tonic-gate 
13430Sstevel@tonic-gate 	rc = write_state_machine(LDAP_REQ_MODIFY,
13440Sstevel@tonic-gate 	    (char *)dn, mods, cred, flags, errorp);
13450Sstevel@tonic-gate 
13460Sstevel@tonic-gate 	freeModList(mods);
13470Sstevel@tonic-gate 	return (rc);
13480Sstevel@tonic-gate }
13490Sstevel@tonic-gate 
13500Sstevel@tonic-gate /*ARGSUSED*/
13510Sstevel@tonic-gate int
__ns_ldap_addEntry(const char * service,const char * dn,const ns_ldap_entry_t * entry,const ns_cred_t * cred,const int flags,ns_ldap_error_t ** errorp)13520Sstevel@tonic-gate __ns_ldap_addEntry(
13530Sstevel@tonic-gate 	const char *service,
13540Sstevel@tonic-gate 	const char *dn,
13550Sstevel@tonic-gate 	const ns_ldap_entry_t *entry,
13560Sstevel@tonic-gate 	const ns_cred_t *cred,
13570Sstevel@tonic-gate 	const int flags,
13580Sstevel@tonic-gate 	ns_ldap_error_t ** errorp)
13590Sstevel@tonic-gate {
13600Sstevel@tonic-gate 	char		*new_dn = NULL;
13610Sstevel@tonic-gate 	LDAPMod		**mods = NULL;
13620Sstevel@tonic-gate 	const ns_ldap_attr_t	* const *attr;
13630Sstevel@tonic-gate 	int		nAttr = 0;
13640Sstevel@tonic-gate 	int		rc = 0;
13650Sstevel@tonic-gate 
13660Sstevel@tonic-gate #ifdef DEBUG
13670Sstevel@tonic-gate 	(void) fprintf(stderr, "__ns_ldap_addEntry START\n");
13680Sstevel@tonic-gate #endif
13690Sstevel@tonic-gate 
13700Sstevel@tonic-gate 	if ((entry == NULL) || (dn == NULL) || (cred == NULL))
13710Sstevel@tonic-gate 		return (NS_LDAP_INVALID_PARAM);
13720Sstevel@tonic-gate 	*errorp = NULL;
13730Sstevel@tonic-gate 
13740Sstevel@tonic-gate 	/* Construct array of LDAPMod representing attributes of new entry. */
13750Sstevel@tonic-gate 
13760Sstevel@tonic-gate 	nAttr = entry->attr_count;
13770Sstevel@tonic-gate 	attr = (const ns_ldap_attr_t * const *)(entry->attr_pair);
13780Sstevel@tonic-gate 	mods = __s_api_makeModListCount(service, attr, LDAP_MOD_ADD,
13790Sstevel@tonic-gate 	    nAttr, flags);
13800Sstevel@tonic-gate 	if (mods == NULL) {
13810Sstevel@tonic-gate 		return (NS_LDAP_MEMORY);
13820Sstevel@tonic-gate 	}
13830Sstevel@tonic-gate 
13840Sstevel@tonic-gate 	rc = replace_mapped_attr_in_dn(service, dn, &new_dn);
13850Sstevel@tonic-gate 	if (rc != NS_LDAP_SUCCESS) {
13860Sstevel@tonic-gate 		freeModList(mods);
13870Sstevel@tonic-gate 		return (rc);
13880Sstevel@tonic-gate 	}
13890Sstevel@tonic-gate 
13900Sstevel@tonic-gate 	rc = write_state_machine(LDAP_REQ_ADD,
13910Sstevel@tonic-gate 	    new_dn ? new_dn : (char *)dn, mods, cred, flags, errorp);
13920Sstevel@tonic-gate 
13930Sstevel@tonic-gate 	if (new_dn)
13940Sstevel@tonic-gate 		free(new_dn);
13950Sstevel@tonic-gate 	freeModList(mods);
13960Sstevel@tonic-gate 	return (rc);
13970Sstevel@tonic-gate }
13980Sstevel@tonic-gate 
13990Sstevel@tonic-gate 
14000Sstevel@tonic-gate /*ARGSUSED*/
14010Sstevel@tonic-gate int
__ns_ldap_delEntry(const char * service,const char * dn,const ns_cred_t * cred,const int flags,ns_ldap_error_t ** errorp)14020Sstevel@tonic-gate __ns_ldap_delEntry(
14030Sstevel@tonic-gate 	const char *service,
14040Sstevel@tonic-gate 	const char *dn,
14050Sstevel@tonic-gate 	const ns_cred_t *cred,
14060Sstevel@tonic-gate 	const int flags,
14070Sstevel@tonic-gate 	ns_ldap_error_t ** errorp)
14080Sstevel@tonic-gate {
14090Sstevel@tonic-gate 	int		rc;
14100Sstevel@tonic-gate 
14110Sstevel@tonic-gate #ifdef DEBUG
14120Sstevel@tonic-gate 	(void) fprintf(stderr, "__ns_ldap_delEntry START\n");
14130Sstevel@tonic-gate #endif
14140Sstevel@tonic-gate 	if ((dn == NULL) || (cred == NULL))
14150Sstevel@tonic-gate 		return (NS_LDAP_INVALID_PARAM);
14160Sstevel@tonic-gate 
14170Sstevel@tonic-gate 	*errorp = NULL;
14180Sstevel@tonic-gate 
14190Sstevel@tonic-gate 	rc = write_state_machine(LDAP_REQ_DELETE,
14200Sstevel@tonic-gate 	    (char *)dn, NULL, cred, flags, errorp);
14210Sstevel@tonic-gate 
14220Sstevel@tonic-gate 	return (rc);
14230Sstevel@tonic-gate }
14240Sstevel@tonic-gate 
14250Sstevel@tonic-gate /*
14260Sstevel@tonic-gate  * Add Typed Entry Helper routines
14270Sstevel@tonic-gate  */
14280Sstevel@tonic-gate 
14290Sstevel@tonic-gate /*
14300Sstevel@tonic-gate  * Add Typed Entry Conversion routines
14310Sstevel@tonic-gate  */
14320Sstevel@tonic-gate 
14330Sstevel@tonic-gate static int
__s_add_attr(ns_ldap_entry_t * e,char * attrname,char * value)14340Sstevel@tonic-gate __s_add_attr(ns_ldap_entry_t *e, char *attrname, char *value)
14350Sstevel@tonic-gate {
14360Sstevel@tonic-gate 	ns_ldap_attr_t	*a;
14370Sstevel@tonic-gate 	char		*v;
14380Sstevel@tonic-gate 
14390Sstevel@tonic-gate 	a = (ns_ldap_attr_t *)calloc(1, sizeof (ns_ldap_attr_t));
14400Sstevel@tonic-gate 	if (a == NULL)
14410Sstevel@tonic-gate 		return (NS_LDAP_MEMORY);
14420Sstevel@tonic-gate 	a->attrname = strdup(attrname);
14430Sstevel@tonic-gate 	if (a->attrname == NULL)
14440Sstevel@tonic-gate 		return (NS_LDAP_MEMORY);
14450Sstevel@tonic-gate 	a->attrvalue = (char **)calloc(1, sizeof (char **));
14460Sstevel@tonic-gate 	if (a->attrvalue == NULL)
14470Sstevel@tonic-gate 		return (NS_LDAP_MEMORY);
14480Sstevel@tonic-gate 	a->value_count = 1;
14490Sstevel@tonic-gate 	a->attrvalue[0] = NULL;
14500Sstevel@tonic-gate 	v = strdup(value);
14510Sstevel@tonic-gate 	if (v == NULL)
14520Sstevel@tonic-gate 		return (NS_LDAP_MEMORY);
14530Sstevel@tonic-gate 	a->attrvalue[0] = v;
14540Sstevel@tonic-gate 	e->attr_pair[e->attr_count] = a;
14550Sstevel@tonic-gate 	e->attr_count++;
14560Sstevel@tonic-gate 	return (NS_LDAP_SUCCESS);
14570Sstevel@tonic-gate }
14580Sstevel@tonic-gate 
14590Sstevel@tonic-gate static int
__s_add_attrlist(ns_ldap_entry_t * e,char * attrname,char ** argv)14600Sstevel@tonic-gate __s_add_attrlist(ns_ldap_entry_t *e, char *attrname, char **argv)
14610Sstevel@tonic-gate {
14620Sstevel@tonic-gate 	ns_ldap_attr_t	*a;
14630Sstevel@tonic-gate 	char		*v;
14640Sstevel@tonic-gate 	char		**av;
14650Sstevel@tonic-gate 	int		i, j;
14660Sstevel@tonic-gate 
14670Sstevel@tonic-gate 	a = (ns_ldap_attr_t *)calloc(1, sizeof (ns_ldap_attr_t));
14680Sstevel@tonic-gate 	if (a == NULL)
14690Sstevel@tonic-gate 		return (NS_LDAP_MEMORY);
14700Sstevel@tonic-gate 	a->attrname = strdup(attrname);
14710Sstevel@tonic-gate 	if (a->attrname == NULL)
14720Sstevel@tonic-gate 		return (NS_LDAP_MEMORY);
14730Sstevel@tonic-gate 
14740Sstevel@tonic-gate 	for (i = 0, av = argv; *av != NULL; av++, i++)
14750Sstevel@tonic-gate 		;
14760Sstevel@tonic-gate 
14770Sstevel@tonic-gate 	a->attrvalue = (char **)calloc(i, sizeof (char *));
14780Sstevel@tonic-gate 
14790Sstevel@tonic-gate 	if (a->attrvalue == NULL)
14800Sstevel@tonic-gate 		return (NS_LDAP_MEMORY);
14810Sstevel@tonic-gate 
14820Sstevel@tonic-gate 	a->value_count = i;
14830Sstevel@tonic-gate 	for (j = 0; j < i; j++) {
14840Sstevel@tonic-gate 		v = strdup(argv[j]);
14850Sstevel@tonic-gate 		if (v == NULL)
14860Sstevel@tonic-gate 			return (NS_LDAP_MEMORY);
14870Sstevel@tonic-gate 		a->attrvalue[j] = v;
14880Sstevel@tonic-gate 	}
14890Sstevel@tonic-gate 	e->attr_pair[e->attr_count] = a;
14900Sstevel@tonic-gate 	e->attr_count++;
14910Sstevel@tonic-gate 	return (NS_LDAP_SUCCESS);
14920Sstevel@tonic-gate }
14930Sstevel@tonic-gate 
14940Sstevel@tonic-gate static ns_ldap_entry_t *
__s_mk_entry(char ** objclass,int max_attr)14950Sstevel@tonic-gate __s_mk_entry(char **objclass, int max_attr)
14960Sstevel@tonic-gate {
14970Sstevel@tonic-gate 	ns_ldap_entry_t *e;
14980Sstevel@tonic-gate 	e = (ns_ldap_entry_t *)calloc(1, sizeof (ns_ldap_entry_t));
14990Sstevel@tonic-gate 	if (e == NULL)
15000Sstevel@tonic-gate 		return (NULL);
15010Sstevel@tonic-gate 	/* allocate attributes, +1 for objectclass, +1 for NULL terminator */
15020Sstevel@tonic-gate 	e->attr_pair = (ns_ldap_attr_t **)
15030Sstevel@tonic-gate 	    calloc(max_attr + 2, sizeof (ns_ldap_attr_t *));
15040Sstevel@tonic-gate 	if (e->attr_pair == NULL) {
15050Sstevel@tonic-gate 		free(e);
15060Sstevel@tonic-gate 		return (NULL);
15070Sstevel@tonic-gate 	}
15080Sstevel@tonic-gate 	e->attr_count = 0;
15090Sstevel@tonic-gate 	if (__s_add_attrlist(e, "objectClass", objclass) != NS_LDAP_SUCCESS) {
15100Sstevel@tonic-gate 		free(e->attr_pair);
15110Sstevel@tonic-gate 		free(e);
15120Sstevel@tonic-gate 		return (NULL);
15130Sstevel@tonic-gate 	}
15140Sstevel@tonic-gate 	return (e);
15150Sstevel@tonic-gate }
15160Sstevel@tonic-gate 
15170Sstevel@tonic-gate 
15180Sstevel@tonic-gate /*
15190Sstevel@tonic-gate  * Conversion:			passwd
15200Sstevel@tonic-gate  * Input format:		struct passwd
15210Sstevel@tonic-gate  * Exported objectclass:	posixAccount
15220Sstevel@tonic-gate  */
15230Sstevel@tonic-gate static int
__s_cvt_passwd(const void * data,char ** rdn,ns_ldap_entry_t ** entry,ns_ldap_error_t ** errorp)15240Sstevel@tonic-gate __s_cvt_passwd(const void *data, char **rdn,
15250Sstevel@tonic-gate 	ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
15260Sstevel@tonic-gate {
15270Sstevel@tonic-gate 	ns_ldap_entry_t	*e;
15280Sstevel@tonic-gate 	int		rc;
15290Sstevel@tonic-gate 	char		trdn[RDNSIZE];
15300Sstevel@tonic-gate 	/* routine specific */
15310Sstevel@tonic-gate 	struct passwd	*ptr;
15320Sstevel@tonic-gate 	int		max_attr = 9;
15330Sstevel@tonic-gate 	char		ibuf[10];
15340Sstevel@tonic-gate 	static		char *oclist[] = {
15350Sstevel@tonic-gate 			"posixAccount",
15360Sstevel@tonic-gate 			"shadowAccount",
15370Sstevel@tonic-gate 			"account",
15380Sstevel@tonic-gate 			"top",
15390Sstevel@tonic-gate 			NULL
15400Sstevel@tonic-gate 			};
15410Sstevel@tonic-gate 
15420Sstevel@tonic-gate 	if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
15430Sstevel@tonic-gate 		return (NS_LDAP_OP_FAILED);
15440Sstevel@tonic-gate 	*entry = e = __s_mk_entry(oclist, max_attr);
15450Sstevel@tonic-gate 	if (e == NULL)
15460Sstevel@tonic-gate 		return (NS_LDAP_MEMORY);
15470Sstevel@tonic-gate 
15480Sstevel@tonic-gate 	/* Convert the structure */
15490Sstevel@tonic-gate 	ptr = (struct passwd *)data;
15500Sstevel@tonic-gate 
15514321Scasper 	if (ptr->pw_name == NULL || ptr->pw_uid > MAXUID ||
15524321Scasper 	    ptr->pw_gid > MAXUID || ptr->pw_dir == NULL) {
15530Sstevel@tonic-gate 		__ns_ldap_freeEntry(e);
15540Sstevel@tonic-gate 		*entry = NULL;
15550Sstevel@tonic-gate 		return (NS_LDAP_INVALID_PARAM);
15560Sstevel@tonic-gate 	}
15570Sstevel@tonic-gate 
15580Sstevel@tonic-gate 	/* Create an appropriate rdn */
15590Sstevel@tonic-gate 	(void) snprintf(trdn, RDNSIZE, "uid=%s", ptr->pw_name);
15600Sstevel@tonic-gate 	*rdn = strdup(trdn);
15610Sstevel@tonic-gate 	if (*rdn == NULL) {
15620Sstevel@tonic-gate 		__ns_ldap_freeEntry(e);
15630Sstevel@tonic-gate 		*entry = NULL;
15640Sstevel@tonic-gate 		return (NS_LDAP_MEMORY);
15650Sstevel@tonic-gate 	}
15660Sstevel@tonic-gate 
15670Sstevel@tonic-gate 	/* Error check the data and add the attributes */
15680Sstevel@tonic-gate 	rc = __s_add_attr(e, "uid", ptr->pw_name);
15690Sstevel@tonic-gate 	if (rc != NS_LDAP_SUCCESS) {
15700Sstevel@tonic-gate 		__s_cvt_freeEntryRdn(entry, rdn);
15710Sstevel@tonic-gate 		return (rc);
15720Sstevel@tonic-gate 	}
15730Sstevel@tonic-gate 	rc = __s_add_attr(e, "cn", ptr->pw_name);
15740Sstevel@tonic-gate 	if (rc != NS_LDAP_SUCCESS) {
15750Sstevel@tonic-gate 		__s_cvt_freeEntryRdn(entry, rdn);
15760Sstevel@tonic-gate 		return (rc);
15770Sstevel@tonic-gate 	}
15780Sstevel@tonic-gate 
15790Sstevel@tonic-gate 	if (ptr->pw_passwd != NULL &&
15806842Sth160488 	    ptr->pw_passwd[0] != '\0') {
15810Sstevel@tonic-gate 		rc = __s_add_attr(e, "userPassword", ptr->pw_passwd);
15820Sstevel@tonic-gate 		if (rc != NS_LDAP_SUCCESS) {
15830Sstevel@tonic-gate 			__s_cvt_freeEntryRdn(entry, rdn);
15840Sstevel@tonic-gate 			return (rc);
15850Sstevel@tonic-gate 		}
15860Sstevel@tonic-gate 	}
15870Sstevel@tonic-gate 
15884321Scasper 	(void) sprintf(ibuf, "%u", ptr->pw_uid);
15890Sstevel@tonic-gate 	rc = __s_add_attr(e, "uidNumber", ibuf);
15900Sstevel@tonic-gate 	if (rc != NS_LDAP_SUCCESS) {
15910Sstevel@tonic-gate 		__s_cvt_freeEntryRdn(entry, rdn);
15920Sstevel@tonic-gate 		return (rc);
15930Sstevel@tonic-gate 	}
15940Sstevel@tonic-gate 
15954321Scasper 	(void) sprintf(ibuf, "%u", ptr->pw_gid);
15960Sstevel@tonic-gate 	rc = __s_add_attr(e, "gidNumber", ibuf);
15970Sstevel@tonic-gate 	if (rc != NS_LDAP_SUCCESS) {
15980Sstevel@tonic-gate 		__s_cvt_freeEntryRdn(entry, rdn);
15990Sstevel@tonic-gate 		return (rc);
16000Sstevel@tonic-gate 	}
16010Sstevel@tonic-gate 	if (ptr->pw_gecos != NULL &&
16026842Sth160488 	    ptr->pw_gecos[0] != '\0') {
16030Sstevel@tonic-gate 		rc = __s_add_attr(e, "gecos", ptr->pw_gecos);
16040Sstevel@tonic-gate 		if (rc != NS_LDAP_SUCCESS) {
16050Sstevel@tonic-gate 			__s_cvt_freeEntryRdn(entry, rdn);
16060Sstevel@tonic-gate 			return (rc);
16070Sstevel@tonic-gate 		}
16080Sstevel@tonic-gate 	}
16090Sstevel@tonic-gate 
16100Sstevel@tonic-gate 	rc = __s_add_attr(e, "homeDirectory", ptr->pw_dir);
16110Sstevel@tonic-gate 	if (rc != NS_LDAP_SUCCESS) {
16120Sstevel@tonic-gate 		__s_cvt_freeEntryRdn(entry, rdn);
16130Sstevel@tonic-gate 		return (rc);
16140Sstevel@tonic-gate 	}
16150Sstevel@tonic-gate 	if (ptr->pw_shell != NULL &&
16166842Sth160488 	    ptr->pw_shell[0] != '\0') {
16170Sstevel@tonic-gate 		rc = __s_add_attr(e, "loginShell", ptr->pw_shell);
16180Sstevel@tonic-gate 		if (rc != NS_LDAP_SUCCESS) {
16190Sstevel@tonic-gate 			__s_cvt_freeEntryRdn(entry, rdn);
16200Sstevel@tonic-gate 			return (rc);
16210Sstevel@tonic-gate 		}
16220Sstevel@tonic-gate 	}
16230Sstevel@tonic-gate 
16240Sstevel@tonic-gate 	return (NS_LDAP_SUCCESS);
16250Sstevel@tonic-gate }
16260Sstevel@tonic-gate 
16270Sstevel@tonic-gate /*
16289288SSreedhar.Chalamalasetti@Sun.COM  * escape_str function escapes special characters in str and
16299288SSreedhar.Chalamalasetti@Sun.COM  * copies to escstr string.
16309288SSreedhar.Chalamalasetti@Sun.COM  *
16319288SSreedhar.Chalamalasetti@Sun.COM  * return 0 for successful
16329288SSreedhar.Chalamalasetti@Sun.COM  *        1 for fail
16339288SSreedhar.Chalamalasetti@Sun.COM  */
escape_str(char * escstr,char * str)16349288SSreedhar.Chalamalasetti@Sun.COM static int escape_str(char *escstr, char *str)
16359288SSreedhar.Chalamalasetti@Sun.COM {
16369288SSreedhar.Chalamalasetti@Sun.COM 	int	index = 0;
16379288SSreedhar.Chalamalasetti@Sun.COM 
16389288SSreedhar.Chalamalasetti@Sun.COM 	while ((*str != '\0') && (index < (RDNSIZE - 1))) {
16399288SSreedhar.Chalamalasetti@Sun.COM 		if (*str == '+' || *str == ';' || *str == '>' ||
16409288SSreedhar.Chalamalasetti@Sun.COM 		    *str == '<' || *str == ',' || *str == '"' ||
16419288SSreedhar.Chalamalasetti@Sun.COM 		    *str == '\\' || *str == '=' ||
16429288SSreedhar.Chalamalasetti@Sun.COM 		    (*str == '#' && index == 0)) {
16439288SSreedhar.Chalamalasetti@Sun.COM 			*escstr++ = '\\';
16449288SSreedhar.Chalamalasetti@Sun.COM 			*escstr++ = *str++;
16459288SSreedhar.Chalamalasetti@Sun.COM 			index += 2;
16469288SSreedhar.Chalamalasetti@Sun.COM 		} else {
16479288SSreedhar.Chalamalasetti@Sun.COM 			*escstr++ = *str++;
16489288SSreedhar.Chalamalasetti@Sun.COM 			index++;
16499288SSreedhar.Chalamalasetti@Sun.COM 		}
16509288SSreedhar.Chalamalasetti@Sun.COM 	}
16519288SSreedhar.Chalamalasetti@Sun.COM 
16529288SSreedhar.Chalamalasetti@Sun.COM 	if (*str == '\0') {
16539288SSreedhar.Chalamalasetti@Sun.COM 		*escstr = '\0';
16549288SSreedhar.Chalamalasetti@Sun.COM 		return (0);
16559288SSreedhar.Chalamalasetti@Sun.COM 	} else {
16569288SSreedhar.Chalamalasetti@Sun.COM 		return (1);
16579288SSreedhar.Chalamalasetti@Sun.COM 	}
16589288SSreedhar.Chalamalasetti@Sun.COM }
16599288SSreedhar.Chalamalasetti@Sun.COM 
16609288SSreedhar.Chalamalasetti@Sun.COM /*
16616842Sth160488  * Conversion:			project
16626842Sth160488  * Input format:		struct project
16636842Sth160488  * Exported objectclass:	SolarisProject
16646842Sth160488  */
16656842Sth160488 static int
__s_cvt_project(const void * data,char ** rdn,ns_ldap_entry_t ** entry,ns_ldap_error_t ** errorp)16666842Sth160488 __s_cvt_project(const void *data, char **rdn,
16676842Sth160488 	ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
16686842Sth160488 {
16696842Sth160488 	ns_ldap_entry_t	*e;
16706842Sth160488 	int		rc;
16716842Sth160488 	char		trdn[RDNSIZE];
16726842Sth160488 
16736842Sth160488 	/* routine specific */
16746842Sth160488 	struct project	*ptr;
16756842Sth160488 	int		max_attr = 9;
16766842Sth160488 	char		ibuf[11];
16776842Sth160488 	static char 	*oclist[] = {
16786842Sth160488 			"SolarisProject",
16796842Sth160488 			"top",
16806842Sth160488 			NULL
16816842Sth160488 			};
16826842Sth160488 
16836842Sth160488 	if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
16846842Sth160488 		return (NS_LDAP_OP_FAILED);
16856842Sth160488 
16866842Sth160488 	*entry = e = __s_mk_entry(oclist, max_attr);
16876842Sth160488 	if (e == NULL)
16886842Sth160488 		return (NS_LDAP_MEMORY);
16896842Sth160488 
16906842Sth160488 	/* Convert the structure */
16916842Sth160488 	ptr = (struct project *)data;
16926842Sth160488 
16936842Sth160488 	if (ptr->pj_name == NULL || ptr->pj_projid > MAXUID) {
16946842Sth160488 		__ns_ldap_freeEntry(e);
16956842Sth160488 		*entry = NULL;
16966842Sth160488 		return (NS_LDAP_INVALID_PARAM);
16976842Sth160488 	}
16986842Sth160488 
16996842Sth160488 	/* Create an appropriate rdn */
17006842Sth160488 	(void) snprintf(trdn, RDNSIZE, "SolarisProjectName=%s", ptr->pj_name);
17016842Sth160488 	*rdn = strdup(trdn);
17026842Sth160488 	if (*rdn == NULL) {
17036842Sth160488 		__ns_ldap_freeEntry(e);
17046842Sth160488 		*entry = NULL;
17056842Sth160488 		return (NS_LDAP_MEMORY);
17066842Sth160488 	}
17076842Sth160488 
17086842Sth160488 	/* Error check the data and add the attributes */
17096842Sth160488 
17106842Sth160488 	/* Project name */
17116842Sth160488 	rc = __s_add_attr(e, "SolarisProjectName", ptr->pj_name);
17126842Sth160488 	if (rc != NS_LDAP_SUCCESS) {
17136842Sth160488 		__s_cvt_freeEntryRdn(entry, rdn);
17146842Sth160488 		return (rc);
17156842Sth160488 	}
17166842Sth160488 
17176842Sth160488 	/*
17186842Sth160488 	 * Project ID:
17196842Sth160488 	 * ibuf is 11 chars big, which should be enough for string
17206842Sth160488 	 * representation of 32bit number + nul-car
17216842Sth160488 	 */
17226842Sth160488 	if (snprintf(ibuf, sizeof (ibuf), "%u", ptr->pj_projid) < 0) {
17236842Sth160488 		__s_cvt_freeEntryRdn(entry, rdn);
17246842Sth160488 		return (NS_LDAP_INVALID_PARAM);
17256842Sth160488 	}
17266842Sth160488 	rc = __s_add_attr(e, "SolarisProjectID", ibuf);
17276842Sth160488 	if (rc != NS_LDAP_SUCCESS) {
17286842Sth160488 		__s_cvt_freeEntryRdn(entry, rdn);
17296842Sth160488 		return (rc);
17306842Sth160488 	}
17316842Sth160488 
17326842Sth160488 	/* Comment/Description */
17336842Sth160488 	if (ptr->pj_comment != NULL && ptr->pj_comment[0] != '\0') {
17346842Sth160488 		rc = __s_add_attr(e, "description", ptr->pj_comment);
17356842Sth160488 		if (rc != NS_LDAP_SUCCESS) {
17366842Sth160488 			__s_cvt_freeEntryRdn(entry, rdn);
17376842Sth160488 			return (rc);
17386842Sth160488 		}
17396842Sth160488 	}
17406842Sth160488 
17416842Sth160488 	/* Attributes */
17426842Sth160488 	if (ptr->pj_attr != NULL && ptr->pj_attr[0] != '\0') {
17436842Sth160488 		rc = __s_add_attr(e, "SolarisProjectAttr", ptr->pj_attr);
17446842Sth160488 		if (rc != NS_LDAP_SUCCESS) {
17456842Sth160488 			__s_cvt_freeEntryRdn(entry, rdn);
17466842Sth160488 			return (rc);
17476842Sth160488 		}
17486842Sth160488 	}
17496842Sth160488 
17506842Sth160488 	/* Users */
17516842Sth160488 	if (ptr->pj_users != NULL) {
17526842Sth160488 		rc = __s_add_attrlist(e, "memberUid", ptr->pj_users);
17536842Sth160488 		if (rc != NS_LDAP_SUCCESS) {
17546842Sth160488 			__s_cvt_freeEntryRdn(entry, rdn);
17556842Sth160488 			return (rc);
17566842Sth160488 		}
17576842Sth160488 	}
17586842Sth160488 
17596842Sth160488 	/* Groups */
17606842Sth160488 	if (ptr->pj_groups != NULL) {
17616842Sth160488 		rc = __s_add_attrlist(e, "memberGid", ptr->pj_groups);
17626842Sth160488 		if (rc != NS_LDAP_SUCCESS) {
17636842Sth160488 			__s_cvt_freeEntryRdn(entry, rdn);
17646842Sth160488 			return (rc);
17656842Sth160488 		}
17666842Sth160488 	}
17676842Sth160488 
17686842Sth160488 
17696842Sth160488 
17706842Sth160488 	return (NS_LDAP_SUCCESS);
17716842Sth160488 }
17726842Sth160488 /*
17730Sstevel@tonic-gate  * Conversion:			shadow
17740Sstevel@tonic-gate  * Input format:		struct shadow
17750Sstevel@tonic-gate  * Exported objectclass:	shadowAccount
17760Sstevel@tonic-gate  */
17770Sstevel@tonic-gate static int
__s_cvt_shadow(const void * data,char ** rdn,ns_ldap_entry_t ** entry,ns_ldap_error_t ** errorp)17780Sstevel@tonic-gate __s_cvt_shadow(const void *data, char **rdn,
17790Sstevel@tonic-gate 	ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
17800Sstevel@tonic-gate {
17810Sstevel@tonic-gate 	ns_ldap_entry_t	*e;
17820Sstevel@tonic-gate 	int		rc;
17830Sstevel@tonic-gate 	char		trdn[RDNSIZE];
17840Sstevel@tonic-gate 	/* routine specific */
17850Sstevel@tonic-gate 	struct spwd	*ptr;
17860Sstevel@tonic-gate 	int		max_attr = 10;
17870Sstevel@tonic-gate 	char		ibuf[10];
17880Sstevel@tonic-gate 	static		char *oclist[] = {
17890Sstevel@tonic-gate 			"posixAccount",
17900Sstevel@tonic-gate 			"shadowAccount",
17910Sstevel@tonic-gate 			"account",
17920Sstevel@tonic-gate 			"top",
17930Sstevel@tonic-gate 			NULL
17940Sstevel@tonic-gate 			};
17950Sstevel@tonic-gate 
17960Sstevel@tonic-gate 	if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
17970Sstevel@tonic-gate 		return (NS_LDAP_OP_FAILED);
17980Sstevel@tonic-gate 	*entry = e = __s_mk_entry(oclist, max_attr);
17990Sstevel@tonic-gate 	if (e == NULL)
18000Sstevel@tonic-gate 		return (NS_LDAP_MEMORY);
18010Sstevel@tonic-gate 
18020Sstevel@tonic-gate 	/* Convert the structure */
18030Sstevel@tonic-gate 	ptr = (struct spwd *)data;
18040Sstevel@tonic-gate 
18050Sstevel@tonic-gate 	if (ptr->sp_namp == NULL) {
18060Sstevel@tonic-gate 		__ns_ldap_freeEntry(e);
18070Sstevel@tonic-gate 		*entry = NULL;
18080Sstevel@tonic-gate 		return (NS_LDAP_INVALID_PARAM);
18090Sstevel@tonic-gate 	}
18100Sstevel@tonic-gate 
18110Sstevel@tonic-gate 	/* Create an appropriate rdn */
18120Sstevel@tonic-gate 	(void) snprintf(trdn, RDNSIZE, "uid=%s", ptr->sp_namp);
18130Sstevel@tonic-gate 	*rdn = strdup(trdn);
18140Sstevel@tonic-gate 	if (*rdn == NULL) {
18150Sstevel@tonic-gate 		__ns_ldap_freeEntry(e);
18160Sstevel@tonic-gate 		*entry = NULL;
18170Sstevel@tonic-gate 		return (NS_LDAP_MEMORY);
18180Sstevel@tonic-gate 	}
18190Sstevel@tonic-gate 
18200Sstevel@tonic-gate 	/* Error check the data and add the attributes */
18210Sstevel@tonic-gate 	rc = __s_add_attr(e, "uid", ptr->sp_namp);
18220Sstevel@tonic-gate 	if (rc != NS_LDAP_SUCCESS) {
18230Sstevel@tonic-gate 		__s_cvt_freeEntryRdn(entry, rdn);
18240Sstevel@tonic-gate 		return (rc);
18250Sstevel@tonic-gate 	}
18260Sstevel@tonic-gate 
18270Sstevel@tonic-gate 	if (ptr->sp_pwdp == NULL) {
18280Sstevel@tonic-gate 		__s_cvt_freeEntryRdn(entry, rdn);
18290Sstevel@tonic-gate 		return (NS_LDAP_INVALID_PARAM);
18300Sstevel@tonic-gate 	} else {
18310Sstevel@tonic-gate 		rc = __s_add_attr(e, "userPassword", ptr->sp_pwdp);
18320Sstevel@tonic-gate 		if (rc != NS_LDAP_SUCCESS) {
18330Sstevel@tonic-gate 			__s_cvt_freeEntryRdn(entry, rdn);
18340Sstevel@tonic-gate 			return (rc);
18350Sstevel@tonic-gate 		}
18360Sstevel@tonic-gate 	}
18370Sstevel@tonic-gate 	if (ptr->sp_lstchg >= 0) {
18380Sstevel@tonic-gate 		(void) sprintf(ibuf, "%d", ptr->sp_lstchg);
18390Sstevel@tonic-gate 		rc = __s_add_attr(e, "shadowLastChange", ibuf);
18400Sstevel@tonic-gate 		if (rc != NS_LDAP_SUCCESS) {
18410Sstevel@tonic-gate 			__s_cvt_freeEntryRdn(entry, rdn);
18420Sstevel@tonic-gate 			return (rc);
18430Sstevel@tonic-gate 		}
18440Sstevel@tonic-gate 	}
18450Sstevel@tonic-gate 	if (ptr->sp_min >= 0) {
18460Sstevel@tonic-gate 		(void) sprintf(ibuf, "%d", ptr->sp_min);
18470Sstevel@tonic-gate 		rc = __s_add_attr(e, "shadowMin", ibuf);
18480Sstevel@tonic-gate 		if (rc != NS_LDAP_SUCCESS) {
18490Sstevel@tonic-gate 			__s_cvt_freeEntryRdn(entry, rdn);
18500Sstevel@tonic-gate 			return (rc);
18510Sstevel@tonic-gate 		}
18520Sstevel@tonic-gate 	}
18530Sstevel@tonic-gate 	if (ptr->sp_max >= 0) {
18540Sstevel@tonic-gate 		(void) sprintf(ibuf, "%d", ptr->sp_max);
18550Sstevel@tonic-gate 		rc = __s_add_attr(e, "shadowMax", ibuf);
18560Sstevel@tonic-gate 		if (rc != NS_LDAP_SUCCESS) {
18570Sstevel@tonic-gate 			__s_cvt_freeEntryRdn(entry, rdn);
18580Sstevel@tonic-gate 			return (rc);
18590Sstevel@tonic-gate 		}
18600Sstevel@tonic-gate 	}
18610Sstevel@tonic-gate 	if (ptr->sp_warn >= 0) {
18620Sstevel@tonic-gate 		(void) sprintf(ibuf, "%d", ptr->sp_warn);
18630Sstevel@tonic-gate 		rc = __s_add_attr(e, "shadowWarning", ibuf);
18640Sstevel@tonic-gate 		if (rc != NS_LDAP_SUCCESS) {
18650Sstevel@tonic-gate 			__s_cvt_freeEntryRdn(entry, rdn);
18660Sstevel@tonic-gate 			return (rc);
18670Sstevel@tonic-gate 		}
18680Sstevel@tonic-gate 	}
18690Sstevel@tonic-gate 	if (ptr->sp_inact >= 0) {
18700Sstevel@tonic-gate 		(void) sprintf(ibuf, "%d", ptr->sp_inact);
18710Sstevel@tonic-gate 		rc = __s_add_attr(e, "shadowInactive", ibuf);
18720Sstevel@tonic-gate 		if (rc != NS_LDAP_SUCCESS) {
18730Sstevel@tonic-gate 			__s_cvt_freeEntryRdn(entry, rdn);
18740Sstevel@tonic-gate 			return (rc);
18750Sstevel@tonic-gate 		}
18760Sstevel@tonic-gate 	}
18770Sstevel@tonic-gate 	if (ptr->sp_expire >= 0) {
18780Sstevel@tonic-gate 		(void) sprintf(ibuf, "%d", ptr->sp_expire);
18790Sstevel@tonic-gate 		rc = __s_add_attr(e, "shadowExpire", ibuf);
18800Sstevel@tonic-gate 		if (rc != NS_LDAP_SUCCESS) {
18810Sstevel@tonic-gate 			__s_cvt_freeEntryRdn(entry, rdn);
18820Sstevel@tonic-gate 			return (rc);
18830Sstevel@tonic-gate 		}
18840Sstevel@tonic-gate 	}
18850Sstevel@tonic-gate 	(void) sprintf(ibuf, "%d", ptr->sp_flag);
18860Sstevel@tonic-gate 	rc = __s_add_attr(e, "shadowFlag", ibuf);
18870Sstevel@tonic-gate 	if (rc != NS_LDAP_SUCCESS) {
18880Sstevel@tonic-gate 		__s_cvt_freeEntryRdn(entry, rdn);
18890Sstevel@tonic-gate 		return (rc);
18900Sstevel@tonic-gate 	}
18910Sstevel@tonic-gate 
18920Sstevel@tonic-gate 	return (NS_LDAP_SUCCESS);
18930Sstevel@tonic-gate }
18940Sstevel@tonic-gate 
18950Sstevel@tonic-gate 
18960Sstevel@tonic-gate /*
18970Sstevel@tonic-gate  * Conversion:			group
18980Sstevel@tonic-gate  * Input format:		struct group
18990Sstevel@tonic-gate  * Exported objectclass:	posixGroup
19000Sstevel@tonic-gate  */
19010Sstevel@tonic-gate static int
__s_cvt_group(const void * data,char ** rdn,ns_ldap_entry_t ** entry,ns_ldap_error_t ** errorp)19020Sstevel@tonic-gate __s_cvt_group(const void *data, char **rdn,
19030Sstevel@tonic-gate 	ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
19040Sstevel@tonic-gate {
19050Sstevel@tonic-gate 	ns_ldap_entry_t	*e;
19060Sstevel@tonic-gate 	int		rc;
19070Sstevel@tonic-gate 	char		trdn[RDNSIZE];
19080Sstevel@tonic-gate 	/* routine specific */
19090Sstevel@tonic-gate 	struct group	*ptr;
19100Sstevel@tonic-gate 	int		i, j, k;
19110Sstevel@tonic-gate 	char		**nm, **lm;
19120Sstevel@tonic-gate 	int		max_attr = 4;
19130Sstevel@tonic-gate 	char		ibuf[10];
19140Sstevel@tonic-gate 	static		char *oclist[] = {
19150Sstevel@tonic-gate 			"posixGroup",
19160Sstevel@tonic-gate 			"top",
19170Sstevel@tonic-gate 			NULL
19180Sstevel@tonic-gate 			};
19190Sstevel@tonic-gate 
19200Sstevel@tonic-gate 	if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
19210Sstevel@tonic-gate 		return (NS_LDAP_OP_FAILED);
19220Sstevel@tonic-gate 	*entry = e = __s_mk_entry(oclist, max_attr);
19230Sstevel@tonic-gate 	if (e == NULL)
19240Sstevel@tonic-gate 		return (NS_LDAP_MEMORY);
19250Sstevel@tonic-gate 
19260Sstevel@tonic-gate 	/* Convert the structure */
19270Sstevel@tonic-gate 	ptr = (struct group *)data;
19280Sstevel@tonic-gate 
19294321Scasper 	if (ptr->gr_name == NULL || ptr->gr_gid > MAXUID) {
19300Sstevel@tonic-gate 		__ns_ldap_freeEntry(e);
19310Sstevel@tonic-gate 		*entry = NULL;
19320Sstevel@tonic-gate 		return (NS_LDAP_INVALID_PARAM);
19330Sstevel@tonic-gate 	}
19340Sstevel@tonic-gate 
19350Sstevel@tonic-gate 	/* Create an appropriate rdn */
19360Sstevel@tonic-gate 	(void) snprintf(trdn, RDNSIZE, "cn=%s", ptr->gr_name);
19370Sstevel@tonic-gate 	*rdn = strdup(trdn);
19380Sstevel@tonic-gate 	if (*rdn == NULL) {
19390Sstevel@tonic-gate 		__ns_ldap_freeEntry(e);
19400Sstevel@tonic-gate 		*entry = NULL;
19410Sstevel@tonic-gate 		return (NS_LDAP_MEMORY);
19420Sstevel@tonic-gate 	}
19430Sstevel@tonic-gate 
19440Sstevel@tonic-gate 	/* Error check the data and add the attributes */
19450Sstevel@tonic-gate 	rc = __s_add_attr(e, "cn", ptr->gr_name);
19460Sstevel@tonic-gate 	if (rc != NS_LDAP_SUCCESS) {
19470Sstevel@tonic-gate 		__s_cvt_freeEntryRdn(entry, rdn);
19480Sstevel@tonic-gate 		return (rc);
19490Sstevel@tonic-gate 	}
19500Sstevel@tonic-gate 
19514321Scasper 	(void) sprintf(ibuf, "%u", ptr->gr_gid);
19520Sstevel@tonic-gate 	rc = __s_add_attr(e, "gidNumber", ibuf);
19530Sstevel@tonic-gate 	if (rc != NS_LDAP_SUCCESS) {
19540Sstevel@tonic-gate 		__s_cvt_freeEntryRdn(entry, rdn);
19550Sstevel@tonic-gate 		return (rc);
19560Sstevel@tonic-gate 	}
19570Sstevel@tonic-gate 	if (ptr->gr_passwd && ptr->gr_passwd[0] != '\0') {
19580Sstevel@tonic-gate 		rc = __s_add_attr(e, "userPassword", ptr->gr_passwd);
19590Sstevel@tonic-gate 		if (rc != NS_LDAP_SUCCESS) {
19600Sstevel@tonic-gate 			__s_cvt_freeEntryRdn(entry, rdn);
19610Sstevel@tonic-gate 			return (rc);
19620Sstevel@tonic-gate 		}
19630Sstevel@tonic-gate 	}
19640Sstevel@tonic-gate 
19650Sstevel@tonic-gate 	if (ptr->gr_mem && ptr->gr_mem[0]) {
19660Sstevel@tonic-gate 		lm = ptr->gr_mem;
19670Sstevel@tonic-gate 		for (i = 0; *lm; i++, lm++)
19680Sstevel@tonic-gate 			;
19690Sstevel@tonic-gate 		lm = ptr->gr_mem;
19700Sstevel@tonic-gate 		nm = (char **)calloc(i+2, sizeof (char *));
19710Sstevel@tonic-gate 		if (nm == NULL) {
19720Sstevel@tonic-gate 			__s_cvt_freeEntryRdn(entry, rdn);
19730Sstevel@tonic-gate 			return (NS_LDAP_MEMORY);
19740Sstevel@tonic-gate 		}
19750Sstevel@tonic-gate 		for (j = 0; j < i; j++) {
19760Sstevel@tonic-gate 			nm[j] = strdup(lm[j]);
19770Sstevel@tonic-gate 			if (nm[j] == NULL) {
19780Sstevel@tonic-gate 				for (k = 0; k < j; k++)
19790Sstevel@tonic-gate 					free(nm[k]);
19800Sstevel@tonic-gate 				free(nm);
19810Sstevel@tonic-gate 				__s_cvt_freeEntryRdn(entry, rdn);
19820Sstevel@tonic-gate 				return (NS_LDAP_MEMORY);
19830Sstevel@tonic-gate 			}
19840Sstevel@tonic-gate 		}
19850Sstevel@tonic-gate 		rc = __s_add_attrlist(e, "memberUid", nm);
19860Sstevel@tonic-gate 		for (j = 0; j < i; j++) {
19870Sstevel@tonic-gate 			free(nm[j]);
19880Sstevel@tonic-gate 		}
19890Sstevel@tonic-gate 		free(nm);
19900Sstevel@tonic-gate 		nm = NULL;
19910Sstevel@tonic-gate 		if (rc != NS_LDAP_SUCCESS) {
19920Sstevel@tonic-gate 			__s_cvt_freeEntryRdn(entry, rdn);
19930Sstevel@tonic-gate 			return (rc);
19940Sstevel@tonic-gate 		}
19950Sstevel@tonic-gate 	}
19960Sstevel@tonic-gate 
19970Sstevel@tonic-gate 	return (NS_LDAP_SUCCESS);
19980Sstevel@tonic-gate }
19990Sstevel@tonic-gate 
20000Sstevel@tonic-gate /*
20010Sstevel@tonic-gate  * Conversion:			hosts
20020Sstevel@tonic-gate  * Input format:		struct hostent
20030Sstevel@tonic-gate  * Exported objectclass:	ipHost
20040Sstevel@tonic-gate  */
20050Sstevel@tonic-gate static int
__s_cvt_hosts(const void * data,char ** rdn,ns_ldap_entry_t ** entry,ns_ldap_error_t ** errorp)20060Sstevel@tonic-gate __s_cvt_hosts(const void *data, char **rdn,
20070Sstevel@tonic-gate 	ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
20080Sstevel@tonic-gate {
20090Sstevel@tonic-gate 	ns_ldap_entry_t	*e;
20100Sstevel@tonic-gate 	int		rc;
20110Sstevel@tonic-gate 	char		trdn[RDNSIZE];
20120Sstevel@tonic-gate 	/* routine specific */
20130Sstevel@tonic-gate 	struct hostent	*ptr;
20140Sstevel@tonic-gate 	int		max_attr = 6;
20150Sstevel@tonic-gate 	int		i, j, k;
20160Sstevel@tonic-gate 	char		**nm, **lm;
20170Sstevel@tonic-gate 	static		char *oclist[] = {
20180Sstevel@tonic-gate 			"ipHost",
20190Sstevel@tonic-gate 			"device",
20200Sstevel@tonic-gate 			"top",
20210Sstevel@tonic-gate 			NULL
20220Sstevel@tonic-gate 			};
20230Sstevel@tonic-gate 
20240Sstevel@tonic-gate 	if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
20250Sstevel@tonic-gate 		return (NS_LDAP_OP_FAILED);
20260Sstevel@tonic-gate 	*entry = e = __s_mk_entry(oclist, max_attr);
20270Sstevel@tonic-gate 	if (e == NULL)
20280Sstevel@tonic-gate 		return (NS_LDAP_MEMORY);
20290Sstevel@tonic-gate 
20300Sstevel@tonic-gate 	/* Convert the structure */
20310Sstevel@tonic-gate 	ptr = (struct hostent *)data;
20320Sstevel@tonic-gate 
20330Sstevel@tonic-gate 	if (ptr->h_name == NULL ||
20340Sstevel@tonic-gate 	    ptr->h_addr_list == NULL || ptr->h_addr_list[0] == '\0') {
20350Sstevel@tonic-gate 		__ns_ldap_freeEntry(e);
20360Sstevel@tonic-gate 		*entry = NULL;
20370Sstevel@tonic-gate 		return (NS_LDAP_INVALID_PARAM);
20380Sstevel@tonic-gate 	}
20390Sstevel@tonic-gate 
20400Sstevel@tonic-gate 	/* Create an appropriate rdn */
20410Sstevel@tonic-gate 	(void) snprintf(trdn, RDNSIZE, "cn=%s+ipHostNumber=%s",
20420Sstevel@tonic-gate 	    ptr->h_name, ptr->h_addr_list[0]);
20430Sstevel@tonic-gate 	*rdn = strdup(trdn);
20440Sstevel@tonic-gate 	if (*rdn == NULL) {
20450Sstevel@tonic-gate 		__ns_ldap_freeEntry(e);
20460Sstevel@tonic-gate 		*entry = NULL;
20470Sstevel@tonic-gate 		return (NS_LDAP_MEMORY);
20480Sstevel@tonic-gate 	}
20490Sstevel@tonic-gate 
20500Sstevel@tonic-gate 	/* Error check the data and add the attributes */
20510Sstevel@tonic-gate 	if (ptr->h_aliases && ptr->h_aliases[0]) {
20520Sstevel@tonic-gate 		lm = ptr->h_aliases;
20532689Siz202018 		/*
20542689Siz202018 		 * If there is a description, 'i' will contain
20552689Siz202018 		 * the index of the description in the aliases list
20562689Siz202018 		 */
20572689Siz202018 		for (i = 0; *lm && (*lm)[0] != '#'; i++, lm++)
20580Sstevel@tonic-gate 			;
20590Sstevel@tonic-gate 		lm = ptr->h_aliases;
20600Sstevel@tonic-gate 		nm = (char **)calloc(i+2, sizeof (char *));
20610Sstevel@tonic-gate 		if (nm == NULL) {
20620Sstevel@tonic-gate 			__s_cvt_freeEntryRdn(entry, rdn);
20630Sstevel@tonic-gate 			return (NS_LDAP_MEMORY);
20640Sstevel@tonic-gate 		}
20650Sstevel@tonic-gate 		nm[0] = ptr->h_name;
20660Sstevel@tonic-gate 		for (j = 0; j < i; j++)
20670Sstevel@tonic-gate 			nm[j+1] = ptr->h_aliases[j];
20680Sstevel@tonic-gate 
20690Sstevel@tonic-gate 		rc = __s_add_attrlist(e, "cn", nm);
20702689Siz202018 
20712689Siz202018 		if (rc != NS_LDAP_SUCCESS) {
20722689Siz202018 			__s_cvt_freeEntryRdn(entry, rdn);
20732689Siz202018 			free(nm);
20742689Siz202018 			return (rc);
20752689Siz202018 		}
20762689Siz202018 
20772689Siz202018 		if (lm[i] && lm[i][0] == '#') {
20782689Siz202018 			nm[0] = &(lm[i][1]);
20792689Siz202018 			nm[1] = NULL;
20802689Siz202018 			rc = __s_add_attrlist(e, "description", nm);
20812689Siz202018 		}
20820Sstevel@tonic-gate 		free(nm);
20830Sstevel@tonic-gate 		nm = NULL;
20840Sstevel@tonic-gate 		if (rc != NS_LDAP_SUCCESS) {
20850Sstevel@tonic-gate 			__s_cvt_freeEntryRdn(entry, rdn);
20860Sstevel@tonic-gate 			return (rc);
20870Sstevel@tonic-gate 		}
20880Sstevel@tonic-gate 	} else {
20890Sstevel@tonic-gate 		rc = __s_add_attr(e, "cn", ptr->h_name);
20900Sstevel@tonic-gate 		if (rc != NS_LDAP_SUCCESS) {
20910Sstevel@tonic-gate 			__s_cvt_freeEntryRdn(entry, rdn);
20920Sstevel@tonic-gate 			return (rc);
20930Sstevel@tonic-gate 		}
20940Sstevel@tonic-gate 	}
20950Sstevel@tonic-gate 
20960Sstevel@tonic-gate 	if (ptr->h_addr_list && ptr->h_addr_list[0]) {
20970Sstevel@tonic-gate 		lm = ptr->h_addr_list;
20980Sstevel@tonic-gate 		for (i = 0; *lm; i++, lm++)
20990Sstevel@tonic-gate 			;
21000Sstevel@tonic-gate 		lm = ptr->h_addr_list;
21010Sstevel@tonic-gate 		nm = (char **)calloc(i+2, sizeof (char *));
21020Sstevel@tonic-gate 		if (nm == NULL) {
21030Sstevel@tonic-gate 			__s_cvt_freeEntryRdn(entry, rdn);
21040Sstevel@tonic-gate 			return (NS_LDAP_MEMORY);
21050Sstevel@tonic-gate 		}
21060Sstevel@tonic-gate 		for (j = 0; j < i; j++) {
21070Sstevel@tonic-gate 			nm[j] = strdup(lm[j]);
21080Sstevel@tonic-gate 			if (nm[j] == NULL) {
21090Sstevel@tonic-gate 				for (k = 0; k < j; k++)
21100Sstevel@tonic-gate 					free(nm[k]);
21110Sstevel@tonic-gate 				free(nm);
21120Sstevel@tonic-gate 				__s_cvt_freeEntryRdn(entry, rdn);
21130Sstevel@tonic-gate 				return (NS_LDAP_MEMORY);
21140Sstevel@tonic-gate 			}
21150Sstevel@tonic-gate 		}
21160Sstevel@tonic-gate 		rc = __s_add_attrlist(e, "ipHostNumber", nm);
21170Sstevel@tonic-gate 		for (j = 0; j < i; j++) {
21180Sstevel@tonic-gate 			free(nm[j]);
21190Sstevel@tonic-gate 		}
21200Sstevel@tonic-gate 		free(nm);
21210Sstevel@tonic-gate 		nm = NULL;
21220Sstevel@tonic-gate 		if (rc != NS_LDAP_SUCCESS) {
21230Sstevel@tonic-gate 			__s_cvt_freeEntryRdn(entry, rdn);
21240Sstevel@tonic-gate 			return (rc);
21250Sstevel@tonic-gate 		}
21260Sstevel@tonic-gate 	} else {
21270Sstevel@tonic-gate 		__s_cvt_freeEntryRdn(entry, rdn);
21280Sstevel@tonic-gate 		return (NS_LDAP_INVALID_PARAM);
21290Sstevel@tonic-gate 	}
21300Sstevel@tonic-gate 
21310Sstevel@tonic-gate 	return (NS_LDAP_SUCCESS);
21320Sstevel@tonic-gate }
21330Sstevel@tonic-gate 
21340Sstevel@tonic-gate /*
21350Sstevel@tonic-gate  * Conversion:			rpc
21360Sstevel@tonic-gate  * Input format:		struct rpcent
21370Sstevel@tonic-gate  * Exported objectclass:	oncRpc
21380Sstevel@tonic-gate  */
21390Sstevel@tonic-gate static int
__s_cvt_rpc(const void * data,char ** rdn,ns_ldap_entry_t ** entry,ns_ldap_error_t ** errorp)21400Sstevel@tonic-gate __s_cvt_rpc(const void *data, char **rdn,
21410Sstevel@tonic-gate 	ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
21420Sstevel@tonic-gate {
21430Sstevel@tonic-gate 	ns_ldap_entry_t	*e;
21440Sstevel@tonic-gate 	int		rc;
21450Sstevel@tonic-gate 	char		trdn[RDNSIZE];
21460Sstevel@tonic-gate 	/* routine specific */
21470Sstevel@tonic-gate 	struct rpcent	*ptr;
21480Sstevel@tonic-gate 	int		max_attr = 3;
21490Sstevel@tonic-gate 	int		i, j;
21500Sstevel@tonic-gate 	char		**nm;
21510Sstevel@tonic-gate 	char		ibuf[10];
21520Sstevel@tonic-gate 	static		char *oclist[] = {
21530Sstevel@tonic-gate 			"oncRpc",
21540Sstevel@tonic-gate 			"top",
21550Sstevel@tonic-gate 			NULL
21560Sstevel@tonic-gate 			};
21570Sstevel@tonic-gate 
21580Sstevel@tonic-gate 	if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
21590Sstevel@tonic-gate 		return (NS_LDAP_OP_FAILED);
21600Sstevel@tonic-gate 	*entry = e = __s_mk_entry(oclist, max_attr);
21610Sstevel@tonic-gate 	if (e == NULL)
21620Sstevel@tonic-gate 		return (NS_LDAP_MEMORY);
21630Sstevel@tonic-gate 
21640Sstevel@tonic-gate 	/* Convert the structure */
21650Sstevel@tonic-gate 	ptr = (struct rpcent *)data;
21660Sstevel@tonic-gate 
21670Sstevel@tonic-gate 	if (ptr->r_name == NULL || ptr->r_number < 0) {
21680Sstevel@tonic-gate 		__ns_ldap_freeEntry(e);
21690Sstevel@tonic-gate 		*entry = NULL;
21700Sstevel@tonic-gate 		return (NS_LDAP_INVALID_PARAM);
21710Sstevel@tonic-gate 	}
21720Sstevel@tonic-gate 
21730Sstevel@tonic-gate 	/* Create an appropriate rdn */
21740Sstevel@tonic-gate 	(void) snprintf(trdn, RDNSIZE, "cn=%s", ptr->r_name);
21750Sstevel@tonic-gate 	*rdn = strdup(trdn);
21760Sstevel@tonic-gate 	if (*rdn == NULL) {
21770Sstevel@tonic-gate 		__ns_ldap_freeEntry(e);
21780Sstevel@tonic-gate 		*entry = NULL;
21790Sstevel@tonic-gate 		return (NS_LDAP_MEMORY);
21800Sstevel@tonic-gate 	}
21810Sstevel@tonic-gate 
21820Sstevel@tonic-gate 	/* Error check the data and add the attributes */
21830Sstevel@tonic-gate 	if (ptr->r_aliases && ptr->r_aliases[0]) {
21840Sstevel@tonic-gate 		nm = ptr->r_aliases;
21850Sstevel@tonic-gate 		for (i = 0; *nm; i++, nm++)
21860Sstevel@tonic-gate 			;
21870Sstevel@tonic-gate 		nm = (char **)calloc(i+2, sizeof (char *));
21880Sstevel@tonic-gate 		if (nm == NULL) {
21890Sstevel@tonic-gate 			__s_cvt_freeEntryRdn(entry, rdn);
21900Sstevel@tonic-gate 			return (NS_LDAP_MEMORY);
21910Sstevel@tonic-gate 		}
21920Sstevel@tonic-gate 		nm[0] = ptr->r_name;
21930Sstevel@tonic-gate 		for (j = 0; j < i; j++)
21940Sstevel@tonic-gate 			nm[j+1] = ptr->r_aliases[j];
21950Sstevel@tonic-gate 
21960Sstevel@tonic-gate 		rc = __s_add_attrlist(e, "cn", nm);
21970Sstevel@tonic-gate 		free(nm);
21980Sstevel@tonic-gate 		nm = NULL;
21990Sstevel@tonic-gate 		if (rc != NS_LDAP_SUCCESS) {
22000Sstevel@tonic-gate 			__s_cvt_freeEntryRdn(entry, rdn);
22010Sstevel@tonic-gate 			return (rc);
22020Sstevel@tonic-gate 		}
22030Sstevel@tonic-gate 	} else {
22040Sstevel@tonic-gate 		rc = __s_add_attr(e, "cn", ptr->r_name);
22050Sstevel@tonic-gate 		if (rc != NS_LDAP_SUCCESS) {
22060Sstevel@tonic-gate 			__s_cvt_freeEntryRdn(entry, rdn);
22070Sstevel@tonic-gate 			return (rc);
22080Sstevel@tonic-gate 		}
22090Sstevel@tonic-gate 	}
22100Sstevel@tonic-gate 
22110Sstevel@tonic-gate 	if (ptr->r_number >= 0) {
22120Sstevel@tonic-gate 		(void) sprintf(ibuf, "%d", ptr->r_number);
22130Sstevel@tonic-gate 		rc = __s_add_attr(e, "oncRpcNumber", ibuf);
22140Sstevel@tonic-gate 		if (rc != NS_LDAP_SUCCESS) {
22150Sstevel@tonic-gate 			__s_cvt_freeEntryRdn(entry, rdn);
22160Sstevel@tonic-gate 			return (rc);
22170Sstevel@tonic-gate 		}
22180Sstevel@tonic-gate 	}
22190Sstevel@tonic-gate 
22200Sstevel@tonic-gate 	return (NS_LDAP_SUCCESS);
22210Sstevel@tonic-gate 
22220Sstevel@tonic-gate }
22230Sstevel@tonic-gate 
22240Sstevel@tonic-gate /*
22250Sstevel@tonic-gate  * Conversion:			protocols
22260Sstevel@tonic-gate  * Input format:		struct protoent
22270Sstevel@tonic-gate  * Exported objectclass:	ipProtocol
22280Sstevel@tonic-gate  */
22290Sstevel@tonic-gate static int
__s_cvt_protocols(const void * data,char ** rdn,ns_ldap_entry_t ** entry,ns_ldap_error_t ** errorp)22300Sstevel@tonic-gate __s_cvt_protocols(const void *data, char **rdn,
22310Sstevel@tonic-gate 	ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
22320Sstevel@tonic-gate {
22330Sstevel@tonic-gate 	ns_ldap_entry_t	*e;
22340Sstevel@tonic-gate 	int		rc;
22350Sstevel@tonic-gate 	char		trdn[RDNSIZE];
22360Sstevel@tonic-gate 	/* routine specific */
22370Sstevel@tonic-gate 	struct protoent	*ptr;
22380Sstevel@tonic-gate 	int		max_attr = 3;
22390Sstevel@tonic-gate 	int		i, j;
22400Sstevel@tonic-gate 	char		ibuf[10];
22410Sstevel@tonic-gate 	char		**nm;
22420Sstevel@tonic-gate 	static		char *oclist[] = {
22430Sstevel@tonic-gate 			"ipProtocol",
22440Sstevel@tonic-gate 			"top",
22450Sstevel@tonic-gate 			NULL
22460Sstevel@tonic-gate 			};
22470Sstevel@tonic-gate 
22480Sstevel@tonic-gate 	if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
22490Sstevel@tonic-gate 		return (NS_LDAP_OP_FAILED);
22500Sstevel@tonic-gate 	*entry = e = __s_mk_entry(oclist, max_attr);
22510Sstevel@tonic-gate 	if (e == NULL)
22520Sstevel@tonic-gate 		return (NS_LDAP_MEMORY);
22530Sstevel@tonic-gate 
22540Sstevel@tonic-gate 	/* Convert the structure */
22550Sstevel@tonic-gate 	ptr = (struct protoent *)data;
22560Sstevel@tonic-gate 
22570Sstevel@tonic-gate 	if (ptr->p_name == NULL || ptr->p_proto < 0) {
22580Sstevel@tonic-gate 		__ns_ldap_freeEntry(e);
22590Sstevel@tonic-gate 		*entry = NULL;
22600Sstevel@tonic-gate 		return (NS_LDAP_INVALID_PARAM);
22610Sstevel@tonic-gate 	}
22620Sstevel@tonic-gate 
22630Sstevel@tonic-gate 	/* Create an appropriate rdn */
22640Sstevel@tonic-gate 	(void) snprintf(trdn, RDNSIZE, "cn=%s", ptr->p_name);
22650Sstevel@tonic-gate 	*rdn = strdup(trdn);
22660Sstevel@tonic-gate 	if (*rdn == NULL) {
22670Sstevel@tonic-gate 		__ns_ldap_freeEntry(e);
22680Sstevel@tonic-gate 		*entry = NULL;
22690Sstevel@tonic-gate 		return (NS_LDAP_MEMORY);
22700Sstevel@tonic-gate 	}
22710Sstevel@tonic-gate 
22720Sstevel@tonic-gate 	/* Error check the data and add the attributes */
22730Sstevel@tonic-gate 	if (ptr->p_aliases && ptr->p_aliases[0]) {
22740Sstevel@tonic-gate 		nm = ptr->p_aliases;
22750Sstevel@tonic-gate 		for (i = 0; *nm; i++, nm++)
22760Sstevel@tonic-gate 			;
22770Sstevel@tonic-gate 		nm = (char **)calloc(i+2, sizeof (char *));
22780Sstevel@tonic-gate 		if (nm == NULL) {
22790Sstevel@tonic-gate 			__s_cvt_freeEntryRdn(entry, rdn);
22800Sstevel@tonic-gate 			return (NS_LDAP_MEMORY);
22810Sstevel@tonic-gate 		}
22820Sstevel@tonic-gate 		nm[0] = ptr->p_name;
22830Sstevel@tonic-gate 		for (j = 0; j < i; j++)
22840Sstevel@tonic-gate 			nm[j+1] = ptr->p_aliases[j];
22850Sstevel@tonic-gate 
22860Sstevel@tonic-gate 		rc = __s_add_attrlist(e, "cn", nm);
22870Sstevel@tonic-gate 		free(nm);
22880Sstevel@tonic-gate 		nm = NULL;
22890Sstevel@tonic-gate 		if (rc != NS_LDAP_SUCCESS) {
22900Sstevel@tonic-gate 			__s_cvt_freeEntryRdn(entry, rdn);
22910Sstevel@tonic-gate 			return (rc);
22920Sstevel@tonic-gate 		}
22930Sstevel@tonic-gate 	} else {
22940Sstevel@tonic-gate 		rc = __s_add_attr(e, "cn", ptr->p_name);
22950Sstevel@tonic-gate 		if (rc != NS_LDAP_SUCCESS) {
22960Sstevel@tonic-gate 			__s_cvt_freeEntryRdn(entry, rdn);
22970Sstevel@tonic-gate 			return (rc);
22980Sstevel@tonic-gate 		}
22990Sstevel@tonic-gate 	}
23000Sstevel@tonic-gate 
23010Sstevel@tonic-gate 	(void) sprintf(ibuf, "%d", ptr->p_proto);
23020Sstevel@tonic-gate 	rc = __s_add_attr(e, "ipProtocolNumber", ibuf);
23030Sstevel@tonic-gate 	if (rc != NS_LDAP_SUCCESS) {
23040Sstevel@tonic-gate 		__s_cvt_freeEntryRdn(entry, rdn);
23050Sstevel@tonic-gate 		return (rc);
23060Sstevel@tonic-gate 	}
23070Sstevel@tonic-gate 
23080Sstevel@tonic-gate 	return (NS_LDAP_SUCCESS);
23090Sstevel@tonic-gate 
23100Sstevel@tonic-gate }
23110Sstevel@tonic-gate 
23120Sstevel@tonic-gate /*
23130Sstevel@tonic-gate  * Conversion:			services
23140Sstevel@tonic-gate  * Input format:		struct servent
23150Sstevel@tonic-gate  * Exported objectclass:	ipService
23160Sstevel@tonic-gate  */
23170Sstevel@tonic-gate static int
__s_cvt_services(const void * data,char ** rdn,ns_ldap_entry_t ** entry,ns_ldap_error_t ** errorp)23180Sstevel@tonic-gate __s_cvt_services(const void *data, char **rdn,
23190Sstevel@tonic-gate 	ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
23200Sstevel@tonic-gate {
23210Sstevel@tonic-gate 	ns_ldap_entry_t	*e;
23220Sstevel@tonic-gate 	int		rc;
23230Sstevel@tonic-gate 	char		trdn[RDNSIZE];
23249288SSreedhar.Chalamalasetti@Sun.COM 	char		esc_str[RDNSIZE];
23250Sstevel@tonic-gate 	/* routine specific */
23260Sstevel@tonic-gate 	struct servent	*ptr;
23270Sstevel@tonic-gate 	int		max_attr = 4;
23280Sstevel@tonic-gate 	int		i, j;
23290Sstevel@tonic-gate 	char		ibuf[10];
23300Sstevel@tonic-gate 	char		**nm;
23310Sstevel@tonic-gate 	static		char *oclist[] = {
23320Sstevel@tonic-gate 			"ipService",
23330Sstevel@tonic-gate 			"top",
23340Sstevel@tonic-gate 			NULL
23350Sstevel@tonic-gate 			};
23360Sstevel@tonic-gate 
23370Sstevel@tonic-gate 	if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
23380Sstevel@tonic-gate 		return (NS_LDAP_OP_FAILED);
23390Sstevel@tonic-gate 	*entry = e = __s_mk_entry(oclist, max_attr);
23400Sstevel@tonic-gate 	if (e == NULL)
23410Sstevel@tonic-gate 		return (NS_LDAP_MEMORY);
23420Sstevel@tonic-gate 
23430Sstevel@tonic-gate 	/* Convert the structure */
23440Sstevel@tonic-gate 	ptr = (struct servent *)data;
23450Sstevel@tonic-gate 
23460Sstevel@tonic-gate 	if (ptr->s_name == NULL || ptr->s_port < 0 || ptr->s_proto == '\0') {
23470Sstevel@tonic-gate 		__ns_ldap_freeEntry(e);
23480Sstevel@tonic-gate 		*entry = NULL;
23490Sstevel@tonic-gate 		return (NS_LDAP_INVALID_PARAM);
23500Sstevel@tonic-gate 	}
23510Sstevel@tonic-gate 
23529288SSreedhar.Chalamalasetti@Sun.COM 	/*
23539288SSreedhar.Chalamalasetti@Sun.COM 	 * Escape special characters in service name.
23549288SSreedhar.Chalamalasetti@Sun.COM 	 */
23559288SSreedhar.Chalamalasetti@Sun.COM 	if (escape_str(esc_str, ptr->s_name) != 0) {
23569288SSreedhar.Chalamalasetti@Sun.COM 		__ns_ldap_freeEntry(e);
23579288SSreedhar.Chalamalasetti@Sun.COM 		*entry = NULL;
23589288SSreedhar.Chalamalasetti@Sun.COM 		return (NS_LDAP_INVALID_PARAM);
23599288SSreedhar.Chalamalasetti@Sun.COM 	}
23609288SSreedhar.Chalamalasetti@Sun.COM 
23610Sstevel@tonic-gate 	/* Create an appropriate rdn */
23620Sstevel@tonic-gate 	(void) snprintf(trdn, RDNSIZE, "cn=%s+ipServiceProtocol=%s",
23639288SSreedhar.Chalamalasetti@Sun.COM 	    esc_str, ptr->s_proto);
23649288SSreedhar.Chalamalasetti@Sun.COM 
23650Sstevel@tonic-gate 	*rdn = strdup(trdn);
23660Sstevel@tonic-gate 	if (*rdn == NULL) {
23670Sstevel@tonic-gate 		__ns_ldap_freeEntry(e);
23680Sstevel@tonic-gate 		*entry = NULL;
23690Sstevel@tonic-gate 		return (NS_LDAP_MEMORY);
23700Sstevel@tonic-gate 	}
23710Sstevel@tonic-gate 
23720Sstevel@tonic-gate 	/* Error check the data and add the attributes */
23730Sstevel@tonic-gate 	if (ptr->s_aliases && ptr->s_aliases[0]) {
23740Sstevel@tonic-gate 		nm = ptr->s_aliases;
23750Sstevel@tonic-gate 		for (i = 0; *nm; i++, nm++)
23760Sstevel@tonic-gate 			;
23770Sstevel@tonic-gate 		nm = (char **)calloc(i+2, sizeof (char *));
23780Sstevel@tonic-gate 		if (nm == NULL) {
23790Sstevel@tonic-gate 			__s_cvt_freeEntryRdn(entry, rdn);
23800Sstevel@tonic-gate 			return (NS_LDAP_MEMORY);
23810Sstevel@tonic-gate 		}
23820Sstevel@tonic-gate 		nm[0] = ptr->s_name;
23830Sstevel@tonic-gate 		for (j = 0; j < i; j++)
23840Sstevel@tonic-gate 			nm[j+1] = ptr->s_aliases[j];
23850Sstevel@tonic-gate 
23860Sstevel@tonic-gate 		rc = __s_add_attrlist(e, "cn", nm);
23870Sstevel@tonic-gate 		free(nm);
23880Sstevel@tonic-gate 		nm = NULL;
23890Sstevel@tonic-gate 		if (rc != NS_LDAP_SUCCESS) {
23900Sstevel@tonic-gate 			__s_cvt_freeEntryRdn(entry, rdn);
23910Sstevel@tonic-gate 			return (rc);
23920Sstevel@tonic-gate 		}
23930Sstevel@tonic-gate 	} else {
23940Sstevel@tonic-gate 		rc = __s_add_attr(e, "cn", ptr->s_name);
23950Sstevel@tonic-gate 		if (rc != NS_LDAP_SUCCESS) {
23960Sstevel@tonic-gate 			__s_cvt_freeEntryRdn(entry, rdn);
23970Sstevel@tonic-gate 			return (rc);
23980Sstevel@tonic-gate 		}
23990Sstevel@tonic-gate 	}
24000Sstevel@tonic-gate 
24010Sstevel@tonic-gate 	(void) sprintf(ibuf, "%d", ptr->s_port);
24020Sstevel@tonic-gate 	rc = __s_add_attr(e, "ipServicePort", ibuf);
24030Sstevel@tonic-gate 	if (rc != NS_LDAP_SUCCESS) {
24040Sstevel@tonic-gate 		__s_cvt_freeEntryRdn(entry, rdn);
24050Sstevel@tonic-gate 		return (rc);
24060Sstevel@tonic-gate 	}
24070Sstevel@tonic-gate 	rc = __s_add_attr(e, "ipServiceProtocol", ptr->s_proto);
24080Sstevel@tonic-gate 	if (rc != NS_LDAP_SUCCESS) {
24090Sstevel@tonic-gate 		__s_cvt_freeEntryRdn(entry, rdn);
24100Sstevel@tonic-gate 		return (rc);
24110Sstevel@tonic-gate 	}
24120Sstevel@tonic-gate 
24130Sstevel@tonic-gate 	return (NS_LDAP_SUCCESS);
24140Sstevel@tonic-gate }
24150Sstevel@tonic-gate 
24160Sstevel@tonic-gate /*
24170Sstevel@tonic-gate  * Conversion:			networks
24180Sstevel@tonic-gate  * Input format:		struct netent
24190Sstevel@tonic-gate  * Exported objectclass:	ipNetwork
24200Sstevel@tonic-gate  */
24210Sstevel@tonic-gate static int
__s_cvt_networks(const void * data,char ** rdn,ns_ldap_entry_t ** entry,ns_ldap_error_t ** errorp)24220Sstevel@tonic-gate __s_cvt_networks(const void *data, char **rdn,
24230Sstevel@tonic-gate 	ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
24240Sstevel@tonic-gate {
24250Sstevel@tonic-gate 	ns_ldap_entry_t	*e;
24260Sstevel@tonic-gate 	int		rc;
24270Sstevel@tonic-gate 	char		trdn[RDNSIZE];
24280Sstevel@tonic-gate 	/* routine specific */
24290Sstevel@tonic-gate 	struct netent	*ptr;
24300Sstevel@tonic-gate 	int		max_attr = 4;
24310Sstevel@tonic-gate 	int		i, j;
24320Sstevel@tonic-gate 	char		cp[64];
24330Sstevel@tonic-gate 	char		**nm;
24340Sstevel@tonic-gate 	static		char *oclist[] = {
24350Sstevel@tonic-gate 			"ipNetwork",
24360Sstevel@tonic-gate 			"top",
24370Sstevel@tonic-gate 			NULL
24380Sstevel@tonic-gate 			};
24390Sstevel@tonic-gate 
24400Sstevel@tonic-gate 	if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
24410Sstevel@tonic-gate 		return (NS_LDAP_OP_FAILED);
24420Sstevel@tonic-gate 	*entry = e = __s_mk_entry(oclist, max_attr);
24430Sstevel@tonic-gate 	if (e == NULL)
24440Sstevel@tonic-gate 		return (NS_LDAP_MEMORY);
24450Sstevel@tonic-gate 
24460Sstevel@tonic-gate 	/* Convert the structure */
24470Sstevel@tonic-gate 	ptr = (struct netent *)data;
24480Sstevel@tonic-gate 
24490Sstevel@tonic-gate 	if (ptr->n_name == NULL || ptr->n_net == 0) {
24500Sstevel@tonic-gate 		__ns_ldap_freeEntry(e);
24510Sstevel@tonic-gate 		*entry = NULL;
24520Sstevel@tonic-gate 		return (NS_LDAP_INVALID_PARAM);
24530Sstevel@tonic-gate 	}
24540Sstevel@tonic-gate 
24550Sstevel@tonic-gate 	(void) snprintf(cp, sizeof (cp), "%d.%d.%d.%d",
24566842Sth160488 	    (ptr->n_net & 0xFF000000) >> 24,
24576842Sth160488 	    (ptr->n_net & 0x00FF0000) >> 16,
24586842Sth160488 	    (ptr->n_net & 0x0000FF00) >> 8,
24596842Sth160488 	    (ptr->n_net & 0x000000FF));
24600Sstevel@tonic-gate 
24610Sstevel@tonic-gate 	/* Create an appropriate rdn */
24620Sstevel@tonic-gate 	(void) snprintf(trdn, RDNSIZE, "ipNetworkNumber=%s", cp);
24630Sstevel@tonic-gate 	*rdn = strdup(trdn);
24640Sstevel@tonic-gate 	if (*rdn == NULL) {
24650Sstevel@tonic-gate 		__ns_ldap_freeEntry(e);
24660Sstevel@tonic-gate 		*entry = NULL;
24670Sstevel@tonic-gate 		return (NS_LDAP_MEMORY);
24680Sstevel@tonic-gate 	}
24690Sstevel@tonic-gate 
24700Sstevel@tonic-gate 	/* Error check the data and add the attributes */
24710Sstevel@tonic-gate 	if (ptr->n_aliases && ptr->n_aliases[0]) {
24720Sstevel@tonic-gate 		nm = ptr->n_aliases;
24730Sstevel@tonic-gate 		for (i = 0; *nm; i++, nm++)
24740Sstevel@tonic-gate 			;
24750Sstevel@tonic-gate 		nm = (char **)calloc(i+2, sizeof (char *));
24760Sstevel@tonic-gate 		if (nm == NULL) {
24770Sstevel@tonic-gate 			__s_cvt_freeEntryRdn(entry, rdn);
24780Sstevel@tonic-gate 			return (NS_LDAP_MEMORY);
24790Sstevel@tonic-gate 		}
24800Sstevel@tonic-gate 		nm[0] = ptr->n_name;
24810Sstevel@tonic-gate 		for (j = 0; j < i; j++)
24820Sstevel@tonic-gate 			nm[j+1] = ptr->n_aliases[j];
24830Sstevel@tonic-gate 
24840Sstevel@tonic-gate 		rc = __s_add_attrlist(e, "cn", nm);
24850Sstevel@tonic-gate 		free(nm);
24860Sstevel@tonic-gate 		nm = NULL;
24870Sstevel@tonic-gate 		if (rc != NS_LDAP_SUCCESS) {
24880Sstevel@tonic-gate 			__s_cvt_freeEntryRdn(entry, rdn);
24890Sstevel@tonic-gate 			return (rc);
24900Sstevel@tonic-gate 		}
24910Sstevel@tonic-gate 	} else {
24920Sstevel@tonic-gate 		rc = __s_add_attr(e, "cn", ptr->n_name);
24930Sstevel@tonic-gate 		if (rc != NS_LDAP_SUCCESS) {
24940Sstevel@tonic-gate 			__s_cvt_freeEntryRdn(entry, rdn);
24950Sstevel@tonic-gate 			return (rc);
24960Sstevel@tonic-gate 		}
24970Sstevel@tonic-gate 	}
24980Sstevel@tonic-gate 
24990Sstevel@tonic-gate 	rc = __s_add_attr(e, "ipNetworkNumber", cp);
25000Sstevel@tonic-gate 	if (rc != NS_LDAP_SUCCESS) {
25010Sstevel@tonic-gate 		__s_cvt_freeEntryRdn(entry, rdn);
25020Sstevel@tonic-gate 		return (rc);
25030Sstevel@tonic-gate 	}
25040Sstevel@tonic-gate 
25050Sstevel@tonic-gate 	return (NS_LDAP_SUCCESS);
25060Sstevel@tonic-gate 
25070Sstevel@tonic-gate }
25080Sstevel@tonic-gate /*
25090Sstevel@tonic-gate  * Conversion:			netmasks
25100Sstevel@tonic-gate  * Input format:		struct _ns_netmasks
25110Sstevel@tonic-gate  * Exported objectclass:	ipNetwork
25120Sstevel@tonic-gate  */
25130Sstevel@tonic-gate static int
__s_cvt_netmasks(const void * data,char ** rdn,ns_ldap_entry_t ** entry,ns_ldap_error_t ** errorp)25140Sstevel@tonic-gate __s_cvt_netmasks(const void *data, char **rdn,
25150Sstevel@tonic-gate 	ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
25160Sstevel@tonic-gate {
25170Sstevel@tonic-gate 	ns_ldap_entry_t	*e;
25180Sstevel@tonic-gate 	int		rc;
25190Sstevel@tonic-gate 	char		trdn[RDNSIZE];
25200Sstevel@tonic-gate 	/* routine specific */
25210Sstevel@tonic-gate 	struct _ns_netmasks *ptr;
25220Sstevel@tonic-gate 	int		max_attr = 4;
25230Sstevel@tonic-gate 	static		char *oclist[] = {
25240Sstevel@tonic-gate 			"ipNetwork",
25250Sstevel@tonic-gate 			"top",
25260Sstevel@tonic-gate 			NULL
25270Sstevel@tonic-gate 			};
25280Sstevel@tonic-gate 
25290Sstevel@tonic-gate 	if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
25300Sstevel@tonic-gate 		return (NS_LDAP_OP_FAILED);
25310Sstevel@tonic-gate 	*entry = e = __s_mk_entry(oclist, max_attr);
25320Sstevel@tonic-gate 	if (e == NULL)
25330Sstevel@tonic-gate 		return (NS_LDAP_MEMORY);
25340Sstevel@tonic-gate 
25350Sstevel@tonic-gate 	/* Convert the structure */
25360Sstevel@tonic-gate 	ptr = (struct _ns_netmasks *)data;
25370Sstevel@tonic-gate 
25380Sstevel@tonic-gate 	if (ptr->netnumber == NULL) {
25390Sstevel@tonic-gate 		__ns_ldap_freeEntry(e);
25400Sstevel@tonic-gate 		*entry = NULL;
25410Sstevel@tonic-gate 		return (NS_LDAP_INVALID_PARAM);
25420Sstevel@tonic-gate 	}
25430Sstevel@tonic-gate 
25440Sstevel@tonic-gate 	/* Create an appropriate rdn */
25450Sstevel@tonic-gate 	(void) snprintf(trdn, RDNSIZE, "ipNetworkNumber=%s", ptr->netnumber);
25460Sstevel@tonic-gate 	*rdn = strdup(trdn);
25470Sstevel@tonic-gate 	if (*rdn == NULL) {
25480Sstevel@tonic-gate 		__ns_ldap_freeEntry(e);
25490Sstevel@tonic-gate 		*entry = NULL;
25500Sstevel@tonic-gate 		return (NS_LDAP_MEMORY);
25510Sstevel@tonic-gate 	}
25520Sstevel@tonic-gate 
25530Sstevel@tonic-gate 	/* Error check the data and add the attributes */
25540Sstevel@tonic-gate 		rc = __s_add_attr(e, "ipNetworkNumber", ptr->netnumber);
25550Sstevel@tonic-gate 		if (rc != NS_LDAP_SUCCESS) {
25560Sstevel@tonic-gate 			__s_cvt_freeEntryRdn(entry, rdn);
25570Sstevel@tonic-gate 			return (rc);
25580Sstevel@tonic-gate 		}
25590Sstevel@tonic-gate 
25600Sstevel@tonic-gate 	if (ptr->netmask != '\0') {
25610Sstevel@tonic-gate 		rc = __s_add_attr(e, "ipNetmaskNumber", ptr->netmask);
25620Sstevel@tonic-gate 		if (rc != NS_LDAP_SUCCESS) {
25630Sstevel@tonic-gate 			__s_cvt_freeEntryRdn(entry, rdn);
25640Sstevel@tonic-gate 			return (rc);
25650Sstevel@tonic-gate 		}
25660Sstevel@tonic-gate 	}
25670Sstevel@tonic-gate 
25680Sstevel@tonic-gate 	return (NS_LDAP_SUCCESS);
25690Sstevel@tonic-gate 
25700Sstevel@tonic-gate }
25710Sstevel@tonic-gate /*
25720Sstevel@tonic-gate  * Conversion:			netgroups
25730Sstevel@tonic-gate  * Input format:		struct _ns_netgroups
25740Sstevel@tonic-gate  * Exported objectclass:	nisNetgroup
25750Sstevel@tonic-gate  */
25760Sstevel@tonic-gate static int
__s_cvt_netgroups(const void * data,char ** rdn,ns_ldap_entry_t ** entry,ns_ldap_error_t ** errorp)25770Sstevel@tonic-gate __s_cvt_netgroups(const void *data, char **rdn,
25780Sstevel@tonic-gate 	ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
25790Sstevel@tonic-gate {
25800Sstevel@tonic-gate 	ns_ldap_entry_t	*e;
25810Sstevel@tonic-gate 	int		rc;
25820Sstevel@tonic-gate 	char		trdn[RDNSIZE];
25830Sstevel@tonic-gate 	/* routine specific */
25840Sstevel@tonic-gate 	struct _ns_netgroups *ptr;
25850Sstevel@tonic-gate 	int		max_attr = 6;
25860Sstevel@tonic-gate 	int		i, j;
25870Sstevel@tonic-gate 	char		**nm;
25880Sstevel@tonic-gate 	static		char *oclist[] = {
25890Sstevel@tonic-gate 			"nisNetgroup",
25900Sstevel@tonic-gate 			"top",
25910Sstevel@tonic-gate 			NULL
25920Sstevel@tonic-gate 			};
25930Sstevel@tonic-gate 
25940Sstevel@tonic-gate 	if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
25950Sstevel@tonic-gate 		return (NS_LDAP_OP_FAILED);
25960Sstevel@tonic-gate 	*entry = e = __s_mk_entry(oclist, max_attr);
25970Sstevel@tonic-gate 	if (e == NULL)
25980Sstevel@tonic-gate 		return (NS_LDAP_MEMORY);
25990Sstevel@tonic-gate 
26000Sstevel@tonic-gate 	/* Convert the structure */
26010Sstevel@tonic-gate 	ptr = (struct _ns_netgroups *)data;
26020Sstevel@tonic-gate 
26030Sstevel@tonic-gate 	if (ptr->name == NULL) {
26040Sstevel@tonic-gate 		__ns_ldap_freeEntry(e);
26050Sstevel@tonic-gate 		*entry = NULL;
26060Sstevel@tonic-gate 		return (NS_LDAP_INVALID_PARAM);
26070Sstevel@tonic-gate 	}
26080Sstevel@tonic-gate 
26090Sstevel@tonic-gate 	/* Create an appropriate rdn */
26100Sstevel@tonic-gate 	(void) snprintf(trdn, RDNSIZE, "cn=%s", ptr->name);
26110Sstevel@tonic-gate 	*rdn = strdup(trdn);
26120Sstevel@tonic-gate 	if (*rdn == NULL) {
26130Sstevel@tonic-gate 		__ns_ldap_freeEntry(e);
26140Sstevel@tonic-gate 		*entry = NULL;
26150Sstevel@tonic-gate 		return (NS_LDAP_MEMORY);
26160Sstevel@tonic-gate 	}
26170Sstevel@tonic-gate 
26180Sstevel@tonic-gate 	if (ptr->name != '\0') {
26190Sstevel@tonic-gate 		rc = __s_add_attr(e, "cn", ptr->name);
26200Sstevel@tonic-gate 		if (rc != NS_LDAP_SUCCESS) {
26210Sstevel@tonic-gate 			__s_cvt_freeEntryRdn(entry, rdn);
26220Sstevel@tonic-gate 			return (rc);
26230Sstevel@tonic-gate 		}
26240Sstevel@tonic-gate 	}
26250Sstevel@tonic-gate 
26260Sstevel@tonic-gate 	/* Error check the data and add the attributes */
26270Sstevel@tonic-gate 	if (ptr->triplet && ptr->triplet[0]) {
26280Sstevel@tonic-gate 		nm = ptr->triplet;
26290Sstevel@tonic-gate 		for (i = 0; *nm; i++, nm++)
26300Sstevel@tonic-gate 			;
26310Sstevel@tonic-gate 		nm = (char **)calloc(i+2, sizeof (char *));
26320Sstevel@tonic-gate 		if (nm == NULL) {
26330Sstevel@tonic-gate 			__s_cvt_freeEntryRdn(entry, rdn);
26340Sstevel@tonic-gate 			return (NS_LDAP_MEMORY);
26350Sstevel@tonic-gate 		}
26360Sstevel@tonic-gate 		for (j = 0; j < i; j++)
26370Sstevel@tonic-gate 			nm[j] = ptr->triplet[j];
26380Sstevel@tonic-gate 
26390Sstevel@tonic-gate 		rc = __s_add_attrlist(e, "nisNetgroupTriple", nm);
26400Sstevel@tonic-gate 		free(nm);
26410Sstevel@tonic-gate 		nm = NULL;
26420Sstevel@tonic-gate 		if (rc != NS_LDAP_SUCCESS) {
26430Sstevel@tonic-gate 			__s_cvt_freeEntryRdn(entry, rdn);
26440Sstevel@tonic-gate 			return (rc);
26450Sstevel@tonic-gate 		}
26460Sstevel@tonic-gate 	}
26470Sstevel@tonic-gate 	if (ptr->netgroup && ptr->netgroup[0]) {
26480Sstevel@tonic-gate 		nm = ptr->netgroup;
26490Sstevel@tonic-gate 		for (i = 0; *nm; i++, nm++)
26500Sstevel@tonic-gate 			;
26510Sstevel@tonic-gate 		nm = (char **)calloc(i+2, sizeof (char *));
26520Sstevel@tonic-gate 		if (nm == NULL) {
26530Sstevel@tonic-gate 			__s_cvt_freeEntryRdn(entry, rdn);
26540Sstevel@tonic-gate 			return (NS_LDAP_MEMORY);
26550Sstevel@tonic-gate 		}
26560Sstevel@tonic-gate 		for (j = 0; j < i; j++)
26570Sstevel@tonic-gate 			nm[j] = ptr->netgroup[j];
26580Sstevel@tonic-gate 
26590Sstevel@tonic-gate 		rc = __s_add_attrlist(e, "memberNisNetgroup", nm);
26600Sstevel@tonic-gate 		free(nm);
26610Sstevel@tonic-gate 		nm = NULL;
26620Sstevel@tonic-gate 		if (rc != NS_LDAP_SUCCESS) {
26630Sstevel@tonic-gate 			__s_cvt_freeEntryRdn(entry, rdn);
26640Sstevel@tonic-gate 			return (rc);
26650Sstevel@tonic-gate 		}
26660Sstevel@tonic-gate 	}
26670Sstevel@tonic-gate 	return (NS_LDAP_SUCCESS);
26680Sstevel@tonic-gate }
26690Sstevel@tonic-gate /*
26700Sstevel@tonic-gate  * Conversion:			bootparams
26710Sstevel@tonic-gate  * Input format:		struct _ns_bootp
26720Sstevel@tonic-gate  * Exported objectclass:	bootableDevice, device
26730Sstevel@tonic-gate  */
26740Sstevel@tonic-gate static int
__s_cvt_bootparams(const void * data,char ** rdn,ns_ldap_entry_t ** entry,ns_ldap_error_t ** errorp)26750Sstevel@tonic-gate __s_cvt_bootparams(const void *data, char **rdn,
26760Sstevel@tonic-gate 	ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
26770Sstevel@tonic-gate {
26780Sstevel@tonic-gate 	ns_ldap_entry_t	*e;
26790Sstevel@tonic-gate 	int		rc;
26800Sstevel@tonic-gate 	char		trdn[RDNSIZE];
26810Sstevel@tonic-gate 	/* routine specific */
26820Sstevel@tonic-gate 	struct _ns_bootp *ptr;
26830Sstevel@tonic-gate 	int		max_attr = 4;
26840Sstevel@tonic-gate 	int		i, j;
26850Sstevel@tonic-gate 	char		**nm;
26860Sstevel@tonic-gate 	static		char *oclist[] = {
26870Sstevel@tonic-gate 			"bootableDevice",
26880Sstevel@tonic-gate 			"device",
26890Sstevel@tonic-gate 			"top",
26900Sstevel@tonic-gate 			NULL
26910Sstevel@tonic-gate 			};
26920Sstevel@tonic-gate 
26930Sstevel@tonic-gate 	if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
26940Sstevel@tonic-gate 		return (NS_LDAP_OP_FAILED);
26950Sstevel@tonic-gate 	*entry = e = __s_mk_entry(oclist, max_attr);
26960Sstevel@tonic-gate 	if (e == NULL)
26970Sstevel@tonic-gate 		return (NS_LDAP_MEMORY);
26980Sstevel@tonic-gate 
26990Sstevel@tonic-gate 	/* Convert the structure */
27000Sstevel@tonic-gate 	ptr = (struct _ns_bootp *)data;
27010Sstevel@tonic-gate 
27020Sstevel@tonic-gate 	if (ptr->name == NULL) {
27030Sstevel@tonic-gate 		__ns_ldap_freeEntry(e);
27040Sstevel@tonic-gate 		*entry = NULL;
27050Sstevel@tonic-gate 		return (NS_LDAP_INVALID_PARAM);
27060Sstevel@tonic-gate 	}
27070Sstevel@tonic-gate 
27080Sstevel@tonic-gate 	/* Create an appropriate rdn */
27090Sstevel@tonic-gate 	(void) snprintf(trdn, RDNSIZE, "cn=%s", ptr->name);
27100Sstevel@tonic-gate 	*rdn = strdup(trdn);
27110Sstevel@tonic-gate 	if (*rdn == NULL) {
27120Sstevel@tonic-gate 		__ns_ldap_freeEntry(e);
27130Sstevel@tonic-gate 		*entry = NULL;
27140Sstevel@tonic-gate 		return (NS_LDAP_MEMORY);
27150Sstevel@tonic-gate 	}
27160Sstevel@tonic-gate 
27170Sstevel@tonic-gate 	if (ptr->name != '\0') {
27180Sstevel@tonic-gate 		rc = __s_add_attr(e, "cn", ptr->name);
27190Sstevel@tonic-gate 		if (rc != NS_LDAP_SUCCESS) {
27200Sstevel@tonic-gate 			__s_cvt_freeEntryRdn(entry, rdn);
27210Sstevel@tonic-gate 			return (rc);
27220Sstevel@tonic-gate 		}
27230Sstevel@tonic-gate 	}
27240Sstevel@tonic-gate 
27250Sstevel@tonic-gate 	/* Error check the data and add the attributes */
27260Sstevel@tonic-gate 	if (ptr->param && ptr->param[0]) {
27270Sstevel@tonic-gate 		nm = ptr->param;
27280Sstevel@tonic-gate 		for (i = 0; *nm; i++, nm++)
27290Sstevel@tonic-gate 			;
27300Sstevel@tonic-gate 		nm = (char **)calloc(i+2, sizeof (char *));
27310Sstevel@tonic-gate 		if (nm == NULL) {
27320Sstevel@tonic-gate 			__s_cvt_freeEntryRdn(entry, rdn);
27330Sstevel@tonic-gate 			return (NS_LDAP_MEMORY);
27340Sstevel@tonic-gate 		}
27350Sstevel@tonic-gate 		for (j = 0; j < i; j++)
27360Sstevel@tonic-gate 			nm[j] = ptr->param[j];
27370Sstevel@tonic-gate 
27380Sstevel@tonic-gate 		rc = __s_add_attrlist(e, "bootParameter", nm);
27390Sstevel@tonic-gate 		free(nm);
27400Sstevel@tonic-gate 		nm = NULL;
27410Sstevel@tonic-gate 		if (rc != NS_LDAP_SUCCESS) {
27420Sstevel@tonic-gate 			__s_cvt_freeEntryRdn(entry, rdn);
27430Sstevel@tonic-gate 			return (rc);
27440Sstevel@tonic-gate 		}
27450Sstevel@tonic-gate 	}
27460Sstevel@tonic-gate 
27470Sstevel@tonic-gate 	return (NS_LDAP_SUCCESS);
27480Sstevel@tonic-gate 
27490Sstevel@tonic-gate }
27500Sstevel@tonic-gate /*
27510Sstevel@tonic-gate  * Conversion:			ethers
27520Sstevel@tonic-gate  * Input format:		struct _ns_ethers
27530Sstevel@tonic-gate  * Exported objectclass:	ieee802Device, device
27540Sstevel@tonic-gate  */
27550Sstevel@tonic-gate static int
__s_cvt_ethers(const void * data,char ** rdn,ns_ldap_entry_t ** entry,ns_ldap_error_t ** errorp)27560Sstevel@tonic-gate __s_cvt_ethers(const void *data, char **rdn,
27570Sstevel@tonic-gate 	ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
27580Sstevel@tonic-gate {
27590Sstevel@tonic-gate 	ns_ldap_entry_t	*e;
27600Sstevel@tonic-gate 	int		rc;
27610Sstevel@tonic-gate 	char		trdn[RDNSIZE];
27620Sstevel@tonic-gate 	/* routine specific */
27630Sstevel@tonic-gate 	struct _ns_ethers	*ptr;
27640Sstevel@tonic-gate 	int		max_attr = 4;
27650Sstevel@tonic-gate 	static		char *oclist[] = {
27660Sstevel@tonic-gate 			"ieee802Device",
27670Sstevel@tonic-gate 			"device",
27680Sstevel@tonic-gate 			"top",
27690Sstevel@tonic-gate 			NULL
27700Sstevel@tonic-gate 			};
27710Sstevel@tonic-gate 
27720Sstevel@tonic-gate 	if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
27730Sstevel@tonic-gate 		return (NS_LDAP_OP_FAILED);
27740Sstevel@tonic-gate 	*entry = e = __s_mk_entry(oclist, max_attr);
27750Sstevel@tonic-gate 	if (e == NULL)
27760Sstevel@tonic-gate 		return (NS_LDAP_MEMORY);
27770Sstevel@tonic-gate 
27780Sstevel@tonic-gate 	/* Convert the structure */
27790Sstevel@tonic-gate 	ptr = (struct _ns_ethers *)data;
27800Sstevel@tonic-gate 
27810Sstevel@tonic-gate 	if (ptr->name == NULL || ptr->ether == '\0') {
27820Sstevel@tonic-gate 		__ns_ldap_freeEntry(e);
27830Sstevel@tonic-gate 		*entry = NULL;
27840Sstevel@tonic-gate 		return (NS_LDAP_INVALID_PARAM);
27850Sstevel@tonic-gate 	}
27860Sstevel@tonic-gate 
27870Sstevel@tonic-gate 	/* Create an appropriate rdn */
27880Sstevel@tonic-gate 	(void) snprintf(trdn, RDNSIZE, "cn=%s", ptr->name);
27890Sstevel@tonic-gate 	*rdn = strdup(trdn);
27900Sstevel@tonic-gate 	if (*rdn == NULL) {
27910Sstevel@tonic-gate 		__ns_ldap_freeEntry(e);
27920Sstevel@tonic-gate 		*entry = NULL;
27930Sstevel@tonic-gate 		return (NS_LDAP_MEMORY);
27940Sstevel@tonic-gate 	}
27950Sstevel@tonic-gate 
27960Sstevel@tonic-gate 	/* Error check the data and add the attributes */
27970Sstevel@tonic-gate 	rc = __s_add_attr(e, "cn", ptr->name);
27980Sstevel@tonic-gate 	if (rc != NS_LDAP_SUCCESS) {
27990Sstevel@tonic-gate 		__s_cvt_freeEntryRdn(entry, rdn);
28000Sstevel@tonic-gate 		return (rc);
28010Sstevel@tonic-gate 	}
28020Sstevel@tonic-gate 
28030Sstevel@tonic-gate 	rc = __s_add_attr(e, "macAddress", ptr->ether);
28040Sstevel@tonic-gate 	if (rc != NS_LDAP_SUCCESS) {
28050Sstevel@tonic-gate 		__s_cvt_freeEntryRdn(entry, rdn);
28060Sstevel@tonic-gate 		return (rc);
28070Sstevel@tonic-gate 	}
28080Sstevel@tonic-gate 
28090Sstevel@tonic-gate 	return (NS_LDAP_SUCCESS);
28100Sstevel@tonic-gate }
28110Sstevel@tonic-gate /*
28120Sstevel@tonic-gate  * This function is used when processing an ethers (objectclass: ieee802Device)
28130Sstevel@tonic-gate  * or a bootparams (objectclass: bootableDevice) entry, and the entry is
28140Sstevel@tonic-gate  * already found in LDAP. Since both ethers and bootparams share the same
28150Sstevel@tonic-gate  * LDAP container, we want to check that the entry found in LDAP is:
28160Sstevel@tonic-gate  * - either the same entry (same cn, same objectclass): we don't do anything
28170Sstevel@tonic-gate  *   in this case
28180Sstevel@tonic-gate  * - or an entry which does not have the objectclass we are interesting in:
28190Sstevel@tonic-gate  *   in this case, we modify the existing entry by adding the relevant
28200Sstevel@tonic-gate  *   objectclass (ieee802Device or bootableDevice) and the relevant attribute(s)
28210Sstevel@tonic-gate  *   from the attribute list previously computing by the relevant conversion
28220Sstevel@tonic-gate  *   function.
28230Sstevel@tonic-gate  *   Note: from conversion functions __s_cvt_ethers() and  __s_cvt_bootparams()
28240Sstevel@tonic-gate  *   we know that there is only 1 more attribute today to add (macAddress
28250Sstevel@tonic-gate  *   or bootParameter)
28260Sstevel@tonic-gate  */
28270Sstevel@tonic-gate #define	_MAX_ATTR_ETHBOOTP	2
28280Sstevel@tonic-gate static int
modify_ethers_bootp(const char * service,const char * rdn,const char * fulldn,const ns_ldap_attr_t * const * attrlist,const ns_cred_t * cred,const int flags,ns_ldap_error_t ** errorp)28290Sstevel@tonic-gate modify_ethers_bootp(
28300Sstevel@tonic-gate 	const char *service,
28310Sstevel@tonic-gate 	const char *rdn,
28320Sstevel@tonic-gate 	const char *fulldn,
28330Sstevel@tonic-gate 	const ns_ldap_attr_t * const *attrlist,
28340Sstevel@tonic-gate 	const ns_cred_t *cred,
28350Sstevel@tonic-gate 	const int flags,
28360Sstevel@tonic-gate 	ns_ldap_error_t	 **errorp)
28370Sstevel@tonic-gate {
28380Sstevel@tonic-gate 	char	filter[BUFSIZ];
28390Sstevel@tonic-gate 	ns_ldap_result_t *resultp;
28400Sstevel@tonic-gate 	int rc = 0;
28410Sstevel@tonic-gate 	int i;
28420Sstevel@tonic-gate 	ns_ldap_attr_t *new_attrlist[_MAX_ATTR_ETHBOOTP+1];
28430Sstevel@tonic-gate 	ns_ldap_attr_t new_attrlist0;
28440Sstevel@tonic-gate 	char *new_attrvalue0[1];
28450Sstevel@tonic-gate 	const ns_ldap_attr_t	* const *aptr = attrlist;
28460Sstevel@tonic-gate 	ns_ldap_attr_t *aptr2;
28470Sstevel@tonic-gate 	ns_ldap_error_t	 *new_errorp = NULL;
28480Sstevel@tonic-gate 
28490Sstevel@tonic-gate 	if (rdn == NULL || fulldn == NULL || attrlist == NULL ||
28506842Sth160488 	    errorp == NULL || service == NULL)
28510Sstevel@tonic-gate 		return (NS_LDAP_OP_FAILED);
28520Sstevel@tonic-gate 
28530Sstevel@tonic-gate 	bzero(&new_attrlist, sizeof (new_attrlist));
28540Sstevel@tonic-gate 	bzero(&new_attrlist0, sizeof (new_attrlist0));
28550Sstevel@tonic-gate 	new_attrlist[0] = &new_attrlist0;
28560Sstevel@tonic-gate 	new_attrlist[0]->attrvalue = new_attrvalue0;
28570Sstevel@tonic-gate 
28580Sstevel@tonic-gate 	new_attrlist[0]->attrname = "objectclass";
28590Sstevel@tonic-gate 	new_attrlist[0]->value_count = 1;
28600Sstevel@tonic-gate 	if (strcasecmp(service, "ethers") == NULL) {
28610Sstevel@tonic-gate 		(void) snprintf(&filter[0], sizeof (filter),
28626842Sth160488 		    "(&(objectClass=ieee802Device)(%s))", rdn);
28630Sstevel@tonic-gate 		new_attrlist[0]->attrvalue[0] = "ieee802Device";
28640Sstevel@tonic-gate 	} else {
28650Sstevel@tonic-gate 		(void) snprintf(&filter[0], sizeof (filter),
28666842Sth160488 		    "(&(objectClass=bootableDevice)(%s))", rdn);
28670Sstevel@tonic-gate 		new_attrlist[0]->attrvalue[0] = "bootableDevice";
28680Sstevel@tonic-gate 	}
28690Sstevel@tonic-gate 
28700Sstevel@tonic-gate 	rc =  __ns_ldap_list(service, filter, NULL, (const char **)NULL,
28716842Sth160488 	    NULL, NS_LDAP_SCOPE_SUBTREE, &resultp, &new_errorp,
28726842Sth160488 	    NULL, NULL);
28730Sstevel@tonic-gate 
28740Sstevel@tonic-gate 	switch (rc) {
28750Sstevel@tonic-gate 	case NS_LDAP_SUCCESS:
28760Sstevel@tonic-gate 		/*
28770Sstevel@tonic-gate 		 * entry already exists for this service
28780Sstevel@tonic-gate 		 * return NS_LDAP_INTERNAL and do not modify the incoming errorp
28790Sstevel@tonic-gate 		 */
28800Sstevel@tonic-gate 		rc = NS_LDAP_INTERNAL;
28810Sstevel@tonic-gate 		break;
28820Sstevel@tonic-gate 	case NS_LDAP_NOTFOUND:
28830Sstevel@tonic-gate 		/*
28840Sstevel@tonic-gate 		 * entry not found with the given objectclasss but entry exists
28850Sstevel@tonic-gate 		 * hence add the relevant attribute (macAddress or bootparams).
28860Sstevel@tonic-gate 		 */
28870Sstevel@tonic-gate 		i = 1;
28880Sstevel@tonic-gate 		while (*aptr && (i < _MAX_ATTR_ETHBOOTP)) {
28890Sstevel@tonic-gate 			/* aptr2 needed here to avoid lint warning */
28900Sstevel@tonic-gate 			aptr2 = (ns_ldap_attr_t *)*aptr++;
28910Sstevel@tonic-gate 			if ((strcasecmp(aptr2->attrname, "cn") != 0) &&
28926842Sth160488 			    (strcasecmp(aptr2->attrname,
28936842Sth160488 			    "objectclass") != 0)) {
28946842Sth160488 				new_attrlist[i++] = (ns_ldap_attr_t *)aptr2;
28950Sstevel@tonic-gate 			}
28960Sstevel@tonic-gate 		}
28970Sstevel@tonic-gate 
28980Sstevel@tonic-gate 		if (i != _MAX_ATTR_ETHBOOTP) {
28990Sstevel@tonic-gate 			/* we haven't found all expected attributes */
29000Sstevel@tonic-gate 			rc = NS_LDAP_OP_FAILED;
29010Sstevel@tonic-gate 			break;
29020Sstevel@tonic-gate 		}
29030Sstevel@tonic-gate 
29040Sstevel@tonic-gate 		aptr = (const ns_ldap_attr_t	* const *) new_attrlist;
29050Sstevel@tonic-gate 		/* clean errorp first */
29060Sstevel@tonic-gate 		(void) __ns_ldap_freeError(errorp);
29070Sstevel@tonic-gate 		rc =  __ns_ldap_addAttr(service, fulldn, aptr, cred, flags,
29086842Sth160488 		    errorp);
29090Sstevel@tonic-gate 		break;
29100Sstevel@tonic-gate 	default:
29110Sstevel@tonic-gate 		/*
29120Sstevel@tonic-gate 		 * unexpected error happenned
29130Sstevel@tonic-gate 		 * returning relevant error
29140Sstevel@tonic-gate 		 */
29150Sstevel@tonic-gate 		(void) __ns_ldap_freeError(errorp);
29160Sstevel@tonic-gate 		*errorp = new_errorp;
29170Sstevel@tonic-gate 		break;
29180Sstevel@tonic-gate 	}
29190Sstevel@tonic-gate 
29200Sstevel@tonic-gate 	return (rc);
29210Sstevel@tonic-gate }
29220Sstevel@tonic-gate 
29230Sstevel@tonic-gate /*
29240Sstevel@tonic-gate  * Conversion:			publickey
29250Sstevel@tonic-gate  * Input format:		struct _ns_pubkey
29260Sstevel@tonic-gate  * Exported objectclass:	NisKeyObject
29270Sstevel@tonic-gate  */
29280Sstevel@tonic-gate static int
__s_cvt_publickey(const void * data,char ** rdn,ns_ldap_entry_t ** entry,ns_ldap_error_t ** errorp)29290Sstevel@tonic-gate __s_cvt_publickey(const void *data, char **rdn,
29300Sstevel@tonic-gate 	ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
29310Sstevel@tonic-gate {
29320Sstevel@tonic-gate 	ns_ldap_entry_t	*e;
29330Sstevel@tonic-gate 	int		rc;
29340Sstevel@tonic-gate 	char		trdn[RDNSIZE];
29350Sstevel@tonic-gate 	/* routine specific */
29360Sstevel@tonic-gate 	struct _ns_pubkey	*ptr;
29370Sstevel@tonic-gate 	int		max_attr = 3;
29380Sstevel@tonic-gate 	static		char *oclist[] = {
29390Sstevel@tonic-gate 			"NisKeyObject",
29400Sstevel@tonic-gate 			NULL
29410Sstevel@tonic-gate 			};
29420Sstevel@tonic-gate 
29430Sstevel@tonic-gate 	if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
29440Sstevel@tonic-gate 		return (NS_LDAP_OP_FAILED);
29450Sstevel@tonic-gate 	*entry = e = __s_mk_entry(oclist, max_attr);
29460Sstevel@tonic-gate 	if (e == NULL)
29470Sstevel@tonic-gate 		return (NS_LDAP_MEMORY);
29480Sstevel@tonic-gate 
29490Sstevel@tonic-gate 	/* Convert the structure */
29500Sstevel@tonic-gate 	ptr = (struct _ns_pubkey *)data;
29510Sstevel@tonic-gate 
29520Sstevel@tonic-gate 	if (ptr->name == NULL || ptr->pubkey == '\0' || ptr->privkey == '\0') {
29530Sstevel@tonic-gate 		__ns_ldap_freeEntry(e);
29540Sstevel@tonic-gate 		*entry = NULL;
29550Sstevel@tonic-gate 		return (NS_LDAP_INVALID_PARAM);
29560Sstevel@tonic-gate 	}
29570Sstevel@tonic-gate 
29580Sstevel@tonic-gate 	/* Create an appropriate rdn */
29590Sstevel@tonic-gate 	if (ptr->hostcred == NS_HOSTCRED_FALSE)
29600Sstevel@tonic-gate 		(void) snprintf(trdn, RDNSIZE, "uid=%s", ptr->name);
29610Sstevel@tonic-gate 	else
29620Sstevel@tonic-gate 		(void) snprintf(trdn, RDNSIZE, "cn=%s", ptr->name);
29630Sstevel@tonic-gate 	*rdn = strdup(trdn);
29640Sstevel@tonic-gate 	if (*rdn == NULL) {
29650Sstevel@tonic-gate 		__ns_ldap_freeEntry(e);
29660Sstevel@tonic-gate 		*entry = NULL;
29670Sstevel@tonic-gate 		return (NS_LDAP_MEMORY);
29680Sstevel@tonic-gate 	}
29690Sstevel@tonic-gate 
29700Sstevel@tonic-gate 	/* Error check the data and add the attributes */
29710Sstevel@tonic-gate 
29720Sstevel@tonic-gate 	rc = __s_add_attr(e, "nisPublickey", ptr->pubkey);
29730Sstevel@tonic-gate 	if (rc != NS_LDAP_SUCCESS) {
29740Sstevel@tonic-gate 		__s_cvt_freeEntryRdn(entry, rdn);
29750Sstevel@tonic-gate 		return (rc);
29760Sstevel@tonic-gate 	}
29770Sstevel@tonic-gate 
29780Sstevel@tonic-gate 	rc = __s_add_attr(e, "nisSecretkey", ptr->privkey);
29790Sstevel@tonic-gate 	if (rc != NS_LDAP_SUCCESS) {
29800Sstevel@tonic-gate 		__s_cvt_freeEntryRdn(entry, rdn);
29810Sstevel@tonic-gate 		return (rc);
29820Sstevel@tonic-gate 	}
29830Sstevel@tonic-gate 
29840Sstevel@tonic-gate 	return (NS_LDAP_SUCCESS);
29850Sstevel@tonic-gate }
29860Sstevel@tonic-gate /*
29870Sstevel@tonic-gate  * Conversion:			aliases
29880Sstevel@tonic-gate  * Input format:		struct _ns_alias
29890Sstevel@tonic-gate  * Exported objectclass:	mailGroup
29900Sstevel@tonic-gate  */
29910Sstevel@tonic-gate static int
__s_cvt_aliases(const void * data,char ** rdn,ns_ldap_entry_t ** entry,ns_ldap_error_t ** errorp)29920Sstevel@tonic-gate __s_cvt_aliases(const void *data, char **rdn,
29930Sstevel@tonic-gate 	ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
29940Sstevel@tonic-gate {
29950Sstevel@tonic-gate 	ns_ldap_entry_t	*e;
29960Sstevel@tonic-gate 	int		rc;
29970Sstevel@tonic-gate 	char		trdn[RDNSIZE];
29980Sstevel@tonic-gate 	/* routine specific */
29990Sstevel@tonic-gate 	struct _ns_alias *ptr;
30000Sstevel@tonic-gate 	int		max_attr = 4;
30010Sstevel@tonic-gate 	int		i, j;
30020Sstevel@tonic-gate 	char		**nm;
30030Sstevel@tonic-gate 	static		char *oclist[] = {
30040Sstevel@tonic-gate 			"mailGroup",
30050Sstevel@tonic-gate 			"top",
30060Sstevel@tonic-gate 			NULL
30070Sstevel@tonic-gate 			};
30080Sstevel@tonic-gate 
30090Sstevel@tonic-gate 	if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
30100Sstevel@tonic-gate 		return (NS_LDAP_OP_FAILED);
30110Sstevel@tonic-gate 	*entry = e = __s_mk_entry(oclist, max_attr);
30120Sstevel@tonic-gate 	if (e == NULL)
30130Sstevel@tonic-gate 		return (NS_LDAP_MEMORY);
30140Sstevel@tonic-gate 
30150Sstevel@tonic-gate 	/* Convert the structure */
30160Sstevel@tonic-gate 	ptr = (struct _ns_alias *)data;
30170Sstevel@tonic-gate 
30180Sstevel@tonic-gate 	if (ptr->alias == NULL) {
30190Sstevel@tonic-gate 		__ns_ldap_freeEntry(e);
30200Sstevel@tonic-gate 		*entry = NULL;
30210Sstevel@tonic-gate 		return (NS_LDAP_INVALID_PARAM);
30220Sstevel@tonic-gate 	}
30230Sstevel@tonic-gate 
30240Sstevel@tonic-gate 	/* Create an appropriate rdn */
30250Sstevel@tonic-gate 	(void) snprintf(trdn, RDNSIZE, "cn=%s", ptr->alias);
30260Sstevel@tonic-gate 	*rdn = strdup(trdn);
30270Sstevel@tonic-gate 	if (*rdn == NULL) {
30280Sstevel@tonic-gate 		__ns_ldap_freeEntry(e);
30290Sstevel@tonic-gate 		*entry = NULL;
30300Sstevel@tonic-gate 		return (NS_LDAP_MEMORY);
30310Sstevel@tonic-gate 	}
30320Sstevel@tonic-gate 
30330Sstevel@tonic-gate 	if (ptr->alias != '\0') {
30340Sstevel@tonic-gate 		rc = __s_add_attr(e, "mail", (char *)ptr->alias);
30350Sstevel@tonic-gate 		if (rc != NS_LDAP_SUCCESS) {
30360Sstevel@tonic-gate 			__s_cvt_freeEntryRdn(entry, rdn);
30370Sstevel@tonic-gate 			return (rc);
30380Sstevel@tonic-gate 		}
30390Sstevel@tonic-gate 	}
30400Sstevel@tonic-gate 
30410Sstevel@tonic-gate 	/* Error check the data and add the attributes */
30420Sstevel@tonic-gate 	if (ptr->member && ptr->member[0]) {
30430Sstevel@tonic-gate 		nm = ptr->member;
30440Sstevel@tonic-gate 		for (i = 0; *nm; i++, nm++)
30450Sstevel@tonic-gate 			;
30460Sstevel@tonic-gate 		nm = (char **)calloc(i+2, sizeof (char *));
30470Sstevel@tonic-gate 		if (nm == NULL) {
30480Sstevel@tonic-gate 			__s_cvt_freeEntryRdn(entry, rdn);
30490Sstevel@tonic-gate 			return (NS_LDAP_MEMORY);
30500Sstevel@tonic-gate 		}
30510Sstevel@tonic-gate 		for (j = 0; j < i; j++)
30520Sstevel@tonic-gate 			nm[j] = ptr->member[j];
30530Sstevel@tonic-gate 
30540Sstevel@tonic-gate 		rc = __s_add_attrlist(e, "mgrpRFC822MailMember", nm);
30550Sstevel@tonic-gate 		free(nm);
30560Sstevel@tonic-gate 		nm = NULL;
30570Sstevel@tonic-gate 		if (rc != NS_LDAP_SUCCESS) {
30580Sstevel@tonic-gate 			__s_cvt_freeEntryRdn(entry, rdn);
30590Sstevel@tonic-gate 			return (rc);
30600Sstevel@tonic-gate 		}
30610Sstevel@tonic-gate 	}
30620Sstevel@tonic-gate 
30630Sstevel@tonic-gate 	return (NS_LDAP_SUCCESS);
30640Sstevel@tonic-gate 
30650Sstevel@tonic-gate }
30660Sstevel@tonic-gate /*
30670Sstevel@tonic-gate  * Conversion:			automount
30680Sstevel@tonic-gate  * Input format:		struct _ns_automount
30690Sstevel@tonic-gate  * Exported objectclass:	automount
30700Sstevel@tonic-gate  */
30710Sstevel@tonic-gate static int
__s_cvt_auto_mount(const void * data,char ** rdn,ns_ldap_entry_t ** entry,ns_ldap_error_t ** errorp)30720Sstevel@tonic-gate __s_cvt_auto_mount(const void *data, char **rdn,
30730Sstevel@tonic-gate 	ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
30740Sstevel@tonic-gate {
30750Sstevel@tonic-gate 	ns_ldap_entry_t	*e;
30760Sstevel@tonic-gate 	int		rc;
30770Sstevel@tonic-gate 	char		trdn[RDNSIZE];
30780Sstevel@tonic-gate 	/* routine specific */
30790Sstevel@tonic-gate 	struct _ns_automount *ptr;
30800Sstevel@tonic-gate 	int		max_attr = 6;
30810Sstevel@tonic-gate 	void		**paramVal = NULL;
30820Sstevel@tonic-gate 	char		**mappedschema = NULL;
30830Sstevel@tonic-gate 	int		version1 = 0;
30840Sstevel@tonic-gate 	static		char *oclist[] = {
30850Sstevel@tonic-gate 			NULL,
30860Sstevel@tonic-gate 			"top",
30870Sstevel@tonic-gate 			NULL
30880Sstevel@tonic-gate 			};
30890Sstevel@tonic-gate 
30900Sstevel@tonic-gate 	if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
30910Sstevel@tonic-gate 		return (NS_LDAP_OP_FAILED);
30920Sstevel@tonic-gate 
30930Sstevel@tonic-gate 	/* determine profile version number */
30940Sstevel@tonic-gate 	rc = __ns_ldap_getParam(NS_LDAP_FILE_VERSION_P, &paramVal, errorp);
30950Sstevel@tonic-gate 	if (paramVal && *paramVal &&
30966842Sth160488 	    strcasecmp(*paramVal, NS_LDAP_VERSION_1) == 0)
30970Sstevel@tonic-gate 		version1 = 1;
30980Sstevel@tonic-gate 	if (paramVal)
30990Sstevel@tonic-gate 		(void) __ns_ldap_freeParam(&paramVal);
31000Sstevel@tonic-gate 	if (rc && errorp)
31010Sstevel@tonic-gate 		(void) __ns_ldap_freeError(errorp);
31020Sstevel@tonic-gate 
31030Sstevel@tonic-gate 	/* use old schema for version 1 profiles */
31040Sstevel@tonic-gate 	if (version1)
31050Sstevel@tonic-gate 		oclist[0] = "nisObject";
31060Sstevel@tonic-gate 	else
31070Sstevel@tonic-gate 		oclist[0] = "automount";
31080Sstevel@tonic-gate 
31090Sstevel@tonic-gate 	*entry = e = __s_mk_entry(oclist, max_attr);
31100Sstevel@tonic-gate 	if (e == NULL)
31110Sstevel@tonic-gate 		return (NS_LDAP_MEMORY);
31120Sstevel@tonic-gate 
31130Sstevel@tonic-gate 	/* Convert the structure */
31140Sstevel@tonic-gate 	ptr = (struct _ns_automount *)data;
31150Sstevel@tonic-gate 
31160Sstevel@tonic-gate 	if (ptr->key == NULL || ptr->value == '\0' || ptr->mapname == '\0') {
31170Sstevel@tonic-gate 		__ns_ldap_freeEntry(e);
31180Sstevel@tonic-gate 		*entry = NULL;
31190Sstevel@tonic-gate 		return (NS_LDAP_INVALID_PARAM);
31200Sstevel@tonic-gate 	}
31210Sstevel@tonic-gate 
31220Sstevel@tonic-gate 	/* Create an appropriate rdn */
31230Sstevel@tonic-gate 	(void) snprintf(trdn, RDNSIZE, version1 ? "cn=%s" : "automountKey=%s",
31246842Sth160488 	    ptr->key);
31250Sstevel@tonic-gate 	*rdn = strdup(trdn);
31260Sstevel@tonic-gate 	if (*rdn == NULL) {
31270Sstevel@tonic-gate 		__ns_ldap_freeEntry(e);
31280Sstevel@tonic-gate 		*entry = NULL;
31290Sstevel@tonic-gate 		return (NS_LDAP_MEMORY);
31300Sstevel@tonic-gate 	}
31310Sstevel@tonic-gate 
31320Sstevel@tonic-gate 	if (ptr->key != '\0') {
31330Sstevel@tonic-gate 		rc = __s_add_attr(e, version1 ? "cn" : "automountKey",
31346842Sth160488 		    (char *)ptr->key);
31350Sstevel@tonic-gate 		if (rc != NS_LDAP_SUCCESS) {
31360Sstevel@tonic-gate 			__s_cvt_freeEntryRdn(entry, rdn);
31370Sstevel@tonic-gate 			return (rc);
31380Sstevel@tonic-gate 		}
31390Sstevel@tonic-gate 	}
31400Sstevel@tonic-gate 
31410Sstevel@tonic-gate 	rc = __s_add_attr(e, version1 ? "nisMapEntry" : "automountInformation",
31426842Sth160488 	    (char *)ptr->value);
31430Sstevel@tonic-gate 	if (rc != NS_LDAP_SUCCESS) {
31440Sstevel@tonic-gate 		__s_cvt_freeEntryRdn(entry, rdn);
31450Sstevel@tonic-gate 		return (rc);
31460Sstevel@tonic-gate 	}
31470Sstevel@tonic-gate 
31480Sstevel@tonic-gate 	/*
31490Sstevel@tonic-gate 	 * even for version 2, if automount is mapped to nisObject we
31500Sstevel@tonic-gate 	 * still need 'nisMapName' attribute
31510Sstevel@tonic-gate 	 */
31520Sstevel@tonic-gate 	mappedschema = __ns_ldap_getMappedObjectClass("automount", "automount");
31530Sstevel@tonic-gate 	if (mappedschema && mappedschema[0] &&
31546842Sth160488 	    strcasecmp(mappedschema[0], "nisObject") == 0)
31550Sstevel@tonic-gate 		version1 = 1;
31560Sstevel@tonic-gate 	if (mappedschema)
31570Sstevel@tonic-gate 		__s_api_free2dArray(mappedschema);
31580Sstevel@tonic-gate 
31590Sstevel@tonic-gate 	if (version1) {
31600Sstevel@tonic-gate 		rc = __s_add_attr(e, "nisMapName", (char *)ptr->mapname);
31610Sstevel@tonic-gate 		if (rc != NS_LDAP_SUCCESS) {
31620Sstevel@tonic-gate 			__s_cvt_freeEntryRdn(entry, rdn);
31630Sstevel@tonic-gate 			return (rc);
31640Sstevel@tonic-gate 		}
31650Sstevel@tonic-gate 	}
31660Sstevel@tonic-gate 
31670Sstevel@tonic-gate 	return (NS_LDAP_SUCCESS);
31680Sstevel@tonic-gate }
31690Sstevel@tonic-gate /*
31700Sstevel@tonic-gate  * Conversion:			auth_attr
31710Sstevel@tonic-gate  * Input format:		authstr_t
31720Sstevel@tonic-gate  * Exported objectclass:	SolarisAuthAttr
31730Sstevel@tonic-gate  */
31740Sstevel@tonic-gate static int
__s_cvt_authattr(const void * data,char ** rdn,ns_ldap_entry_t ** entry,ns_ldap_error_t ** errorp)31750Sstevel@tonic-gate __s_cvt_authattr(const void *data, char **rdn,
31760Sstevel@tonic-gate 	ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
31770Sstevel@tonic-gate {
31780Sstevel@tonic-gate 	ns_ldap_entry_t	*e;
31790Sstevel@tonic-gate 	int		rc;
31800Sstevel@tonic-gate 	char		trdn[RDNSIZE];
31810Sstevel@tonic-gate 	/* routine specific */
31820Sstevel@tonic-gate 	authstr_t	*ptr;
31830Sstevel@tonic-gate 	int		max_attr = 6;
31840Sstevel@tonic-gate 	static		char *oclist[] = {
31850Sstevel@tonic-gate 			"SolarisAuthAttr",
31860Sstevel@tonic-gate 			"top",
31870Sstevel@tonic-gate 			NULL
31880Sstevel@tonic-gate 			};
31890Sstevel@tonic-gate 
31900Sstevel@tonic-gate 	if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
31910Sstevel@tonic-gate 		return (NS_LDAP_OP_FAILED);
31920Sstevel@tonic-gate 
31930Sstevel@tonic-gate 	*entry = e = __s_mk_entry(oclist, max_attr);
31940Sstevel@tonic-gate 	if (e == NULL)
31950Sstevel@tonic-gate 		return (NS_LDAP_MEMORY);
31960Sstevel@tonic-gate 
31970Sstevel@tonic-gate 	/* Convert the structure */
31980Sstevel@tonic-gate 	ptr = (authstr_t *)data;
31990Sstevel@tonic-gate 
32000Sstevel@tonic-gate 	if (ptr->name == NULL || ptr->name[0] == '\0' || ptr->attr == NULL) {
32010Sstevel@tonic-gate 		__ns_ldap_freeEntry(e);
32020Sstevel@tonic-gate 		*entry = NULL;
32030Sstevel@tonic-gate 		return (NS_LDAP_INVALID_PARAM);
32040Sstevel@tonic-gate 	}
32050Sstevel@tonic-gate 
32060Sstevel@tonic-gate 	/* Create an appropriate rdn */
32070Sstevel@tonic-gate 	(void) snprintf(trdn, RDNSIZE, "cn=%s", ptr->name);
32080Sstevel@tonic-gate 	*rdn = strdup(trdn);
32090Sstevel@tonic-gate 	if (*rdn == NULL) {
32100Sstevel@tonic-gate 		__ns_ldap_freeEntry(e);
32110Sstevel@tonic-gate 		*entry = NULL;
32120Sstevel@tonic-gate 		return (NS_LDAP_MEMORY);
32130Sstevel@tonic-gate 	}
32140Sstevel@tonic-gate 
32150Sstevel@tonic-gate 	rc = __s_add_attr(e, "cn", ptr->name);
32160Sstevel@tonic-gate 	if (rc != NS_LDAP_SUCCESS) {
32170Sstevel@tonic-gate 		__s_cvt_freeEntryRdn(entry, rdn);
32180Sstevel@tonic-gate 		return (rc);
32190Sstevel@tonic-gate 	}
32200Sstevel@tonic-gate 
32210Sstevel@tonic-gate 	rc = __s_add_attr(e, "SolarisAttrKeyValue", ptr->attr);
32220Sstevel@tonic-gate 	if (rc != NS_LDAP_SUCCESS) {
32230Sstevel@tonic-gate 		__s_cvt_freeEntryRdn(entry, rdn);
32240Sstevel@tonic-gate 		return (rc);
32250Sstevel@tonic-gate 	}
32260Sstevel@tonic-gate 
32270Sstevel@tonic-gate 	if (ptr->res1 != NULL) {
32280Sstevel@tonic-gate 		rc = __s_add_attr(e, "SolarisAttrReserved1", ptr->res1);
32290Sstevel@tonic-gate 		if (rc != NS_LDAP_SUCCESS) {
32300Sstevel@tonic-gate 			__s_cvt_freeEntryRdn(entry, rdn);
32310Sstevel@tonic-gate 			return (rc);
32320Sstevel@tonic-gate 		}
32330Sstevel@tonic-gate 	}
32340Sstevel@tonic-gate 
32350Sstevel@tonic-gate 	if (ptr->res2 != NULL) {
32360Sstevel@tonic-gate 		rc = __s_add_attr(e, "SolarisAttrReserved2", ptr->res2);
32370Sstevel@tonic-gate 		if (rc != NS_LDAP_SUCCESS) {
32380Sstevel@tonic-gate 			__s_cvt_freeEntryRdn(entry, rdn);
32390Sstevel@tonic-gate 			return (rc);
32400Sstevel@tonic-gate 		}
32410Sstevel@tonic-gate 	}
32420Sstevel@tonic-gate 
32430Sstevel@tonic-gate 	if (ptr->short_desc != NULL) {
32440Sstevel@tonic-gate 		rc = __s_add_attr(e, "SolarisAttrShortDesc", ptr->short_desc);
32450Sstevel@tonic-gate 		if (rc != NS_LDAP_SUCCESS) {
32460Sstevel@tonic-gate 			__s_cvt_freeEntryRdn(entry, rdn);
32470Sstevel@tonic-gate 			return (rc);
32480Sstevel@tonic-gate 		}
32490Sstevel@tonic-gate 	}
32500Sstevel@tonic-gate 
32510Sstevel@tonic-gate 	if (ptr->long_desc != NULL) {
32520Sstevel@tonic-gate 		rc = __s_add_attr(e, "SolarisAttrLongDesc", ptr->long_desc);
32530Sstevel@tonic-gate 		if (rc != NS_LDAP_SUCCESS) {
32540Sstevel@tonic-gate 			__s_cvt_freeEntryRdn(entry, rdn);
32550Sstevel@tonic-gate 			return (rc);
32560Sstevel@tonic-gate 		}
32570Sstevel@tonic-gate 	}
32580Sstevel@tonic-gate 
32590Sstevel@tonic-gate 	return (NS_LDAP_SUCCESS);
32600Sstevel@tonic-gate }
32610Sstevel@tonic-gate /*
32620Sstevel@tonic-gate  * Conversion:			exec_attr
32630Sstevel@tonic-gate  * Input format:		execstr_t
32640Sstevel@tonic-gate  * Exported objectclass:	SolarisExecAttr
32650Sstevel@tonic-gate  */
32660Sstevel@tonic-gate static int
__s_cvt_execattr(const void * data,char ** rdn,ns_ldap_entry_t ** entry,ns_ldap_error_t ** errorp)32670Sstevel@tonic-gate __s_cvt_execattr(const void *data, char **rdn,
32680Sstevel@tonic-gate 	ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
32690Sstevel@tonic-gate {
32700Sstevel@tonic-gate 	ns_ldap_entry_t	*e;
32710Sstevel@tonic-gate 	int		rc;
32720Sstevel@tonic-gate 	char		trdn[RDNSIZE];
32739288SSreedhar.Chalamalasetti@Sun.COM 	char		esc_str[RDNSIZE];
32740Sstevel@tonic-gate 	/* routine specific */
32750Sstevel@tonic-gate 	execstr_t	*ptr;
32760Sstevel@tonic-gate 	int		max_attr = 7;
32770Sstevel@tonic-gate 	static		char *oclist[] = {
32780Sstevel@tonic-gate 			"SolarisExecAttr",
32790Sstevel@tonic-gate 			"SolarisProfAttr",
32800Sstevel@tonic-gate 			"top",
32810Sstevel@tonic-gate 			NULL
32820Sstevel@tonic-gate 			};
32830Sstevel@tonic-gate 
32840Sstevel@tonic-gate 	if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
32850Sstevel@tonic-gate 		return (NS_LDAP_OP_FAILED);
32860Sstevel@tonic-gate 
32870Sstevel@tonic-gate 	*entry = e = __s_mk_entry(oclist, max_attr);
32880Sstevel@tonic-gate 	if (e == NULL)
32890Sstevel@tonic-gate 		return (NS_LDAP_MEMORY);
32900Sstevel@tonic-gate 
32910Sstevel@tonic-gate 	/* Convert the structure */
32920Sstevel@tonic-gate 	ptr = (execstr_t *)data;
32930Sstevel@tonic-gate 
32940Sstevel@tonic-gate 	if (ptr->name == NULL || ptr->name[0] == '\0' ||
32950Sstevel@tonic-gate 	    ptr->policy == NULL || ptr->policy[0] == '\0' ||
32960Sstevel@tonic-gate 	    ptr->type == NULL || ptr->type[0] == '\0' ||
32970Sstevel@tonic-gate 	    ptr->id == NULL || ptr->id[0] == '\0') {
32980Sstevel@tonic-gate 		__ns_ldap_freeEntry(e);
32990Sstevel@tonic-gate 		*entry = NULL;
33000Sstevel@tonic-gate 		return (NS_LDAP_INVALID_PARAM);
33010Sstevel@tonic-gate 	}
33020Sstevel@tonic-gate 
33039288SSreedhar.Chalamalasetti@Sun.COM 	/*
33049288SSreedhar.Chalamalasetti@Sun.COM 	 * Escape special characters in ProfileID.
33059288SSreedhar.Chalamalasetti@Sun.COM 	 */
33069288SSreedhar.Chalamalasetti@Sun.COM 	if (escape_str(esc_str, ptr->id) != 0) {
33079288SSreedhar.Chalamalasetti@Sun.COM 		__ns_ldap_freeEntry(e);
33089288SSreedhar.Chalamalasetti@Sun.COM 		*entry = NULL;
33099288SSreedhar.Chalamalasetti@Sun.COM 		return (NS_LDAP_INVALID_PARAM);
33109288SSreedhar.Chalamalasetti@Sun.COM 	}
33119288SSreedhar.Chalamalasetti@Sun.COM 
33120Sstevel@tonic-gate 	/* Create an appropriate rdn */
33130Sstevel@tonic-gate 	(void) snprintf(trdn, RDNSIZE, "cn=%s+SolarisKernelSecurityPolicy=%s"
33140Sstevel@tonic-gate 	    "+SolarisProfileType=%s+SolarisProfileId=%s",
33159288SSreedhar.Chalamalasetti@Sun.COM 	    ptr->name, ptr->policy, ptr->type, esc_str);
33169288SSreedhar.Chalamalasetti@Sun.COM 
33170Sstevel@tonic-gate 	*rdn = strdup(trdn);
33180Sstevel@tonic-gate 	if (*rdn == NULL) {
33190Sstevel@tonic-gate 		__ns_ldap_freeEntry(e);
33200Sstevel@tonic-gate 		*entry = NULL;
33210Sstevel@tonic-gate 		return (NS_LDAP_MEMORY);
33220Sstevel@tonic-gate 	}
33230Sstevel@tonic-gate 
33240Sstevel@tonic-gate 	rc = __s_add_attr(e, "cn", ptr->name);
33250Sstevel@tonic-gate 	if (rc != NS_LDAP_SUCCESS) {
33260Sstevel@tonic-gate 		__s_cvt_freeEntryRdn(entry, rdn);
33270Sstevel@tonic-gate 		return (rc);
33280Sstevel@tonic-gate 	}
33290Sstevel@tonic-gate 
33300Sstevel@tonic-gate 	rc = __s_add_attr(e, "SolarisKernelSecurityPolicy", ptr->policy);
33310Sstevel@tonic-gate 	if (rc != NS_LDAP_SUCCESS) {
33320Sstevel@tonic-gate 		__s_cvt_freeEntryRdn(entry, rdn);
33330Sstevel@tonic-gate 		return (rc);
33340Sstevel@tonic-gate 	}
33350Sstevel@tonic-gate 
33360Sstevel@tonic-gate 	rc = __s_add_attr(e, "SolarisProfileType", ptr->type);
33370Sstevel@tonic-gate 	if (rc != NS_LDAP_SUCCESS) {
33380Sstevel@tonic-gate 		__s_cvt_freeEntryRdn(entry, rdn);
33390Sstevel@tonic-gate 		return (rc);
33400Sstevel@tonic-gate 	}
33410Sstevel@tonic-gate 
33420Sstevel@tonic-gate 	rc = __s_add_attr(e, "SolarisProfileId", ptr->id);
33430Sstevel@tonic-gate 	if (rc != NS_LDAP_SUCCESS) {
33440Sstevel@tonic-gate 		__s_cvt_freeEntryRdn(entry, rdn);
33450Sstevel@tonic-gate 		return (rc);
33460Sstevel@tonic-gate 	}
33470Sstevel@tonic-gate 
33480Sstevel@tonic-gate 	rc = __s_add_attr(e, "SolarisAttrKeyValue", ptr->attr);
33490Sstevel@tonic-gate 	if (rc != NS_LDAP_SUCCESS) {
33500Sstevel@tonic-gate 		__s_cvt_freeEntryRdn(entry, rdn);
33510Sstevel@tonic-gate 		return (rc);
33520Sstevel@tonic-gate 	}
33530Sstevel@tonic-gate 
33540Sstevel@tonic-gate 	if (ptr->res1 != NULL) {
33550Sstevel@tonic-gate 		rc = __s_add_attr(e, "SolarisAttrRes1", ptr->res1);
33560Sstevel@tonic-gate 		if (rc != NS_LDAP_SUCCESS) {
33570Sstevel@tonic-gate 			__s_cvt_freeEntryRdn(entry, rdn);
33580Sstevel@tonic-gate 			return (rc);
33590Sstevel@tonic-gate 		}
33600Sstevel@tonic-gate 	}
33610Sstevel@tonic-gate 
33620Sstevel@tonic-gate 	if (ptr->res2 != NULL) {
33630Sstevel@tonic-gate 		rc = __s_add_attr(e, "SolarisAttrRes2", ptr->res2);
33640Sstevel@tonic-gate 		if (rc != NS_LDAP_SUCCESS) {
33650Sstevel@tonic-gate 			__s_cvt_freeEntryRdn(entry, rdn);
33660Sstevel@tonic-gate 			return (rc);
33670Sstevel@tonic-gate 		}
33680Sstevel@tonic-gate 	}
33690Sstevel@tonic-gate 
33700Sstevel@tonic-gate 	return (NS_LDAP_SUCCESS);
33710Sstevel@tonic-gate }
33720Sstevel@tonic-gate /*
33730Sstevel@tonic-gate  * Conversion:			prof_attr
33740Sstevel@tonic-gate  * Input format:		profstr_t
33750Sstevel@tonic-gate  * Exported objectclass:	SolarisProfAttr
33760Sstevel@tonic-gate  */
33770Sstevel@tonic-gate static int
__s_cvt_profattr(const void * data,char ** rdn,ns_ldap_entry_t ** entry,ns_ldap_error_t ** errorp)33780Sstevel@tonic-gate __s_cvt_profattr(const void *data, char **rdn,
33790Sstevel@tonic-gate 	ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
33800Sstevel@tonic-gate {
33810Sstevel@tonic-gate 	ns_ldap_entry_t	*e;
33820Sstevel@tonic-gate 	int		rc;
33830Sstevel@tonic-gate 	char		trdn[RDNSIZE];
33840Sstevel@tonic-gate 	/* routine specific */
33850Sstevel@tonic-gate 	profstr_t	*ptr;
33860Sstevel@tonic-gate 	int		max_attr = 5;
33870Sstevel@tonic-gate 	static		char *oclist[] = {
33880Sstevel@tonic-gate 			"SolarisProfAttr",
33890Sstevel@tonic-gate 			"top",
33900Sstevel@tonic-gate 			NULL
33910Sstevel@tonic-gate 			};
33920Sstevel@tonic-gate 
33930Sstevel@tonic-gate 	if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
33940Sstevel@tonic-gate 		return (NS_LDAP_OP_FAILED);
33950Sstevel@tonic-gate 
33960Sstevel@tonic-gate 	*entry = e = __s_mk_entry(oclist, max_attr);
33970Sstevel@tonic-gate 	if (e == NULL)
33980Sstevel@tonic-gate 		return (NS_LDAP_MEMORY);
33990Sstevel@tonic-gate 
34000Sstevel@tonic-gate 	/* Convert the structure */
34010Sstevel@tonic-gate 	ptr = (profstr_t *)data;
34020Sstevel@tonic-gate 
34030Sstevel@tonic-gate 	if (ptr->name == NULL || ptr->name[0] == '\0' || ptr->attr == NULL) {
34040Sstevel@tonic-gate 		__ns_ldap_freeEntry(e);
34050Sstevel@tonic-gate 		*entry = NULL;
34060Sstevel@tonic-gate 		return (NS_LDAP_INVALID_PARAM);
34070Sstevel@tonic-gate 	}
34080Sstevel@tonic-gate 
34090Sstevel@tonic-gate 	/* Create an appropriate rdn */
34100Sstevel@tonic-gate 	(void) snprintf(trdn, RDNSIZE, "cn=%s", ptr->name);
34110Sstevel@tonic-gate 	*rdn = strdup(trdn);
34120Sstevel@tonic-gate 	if (*rdn == NULL) {
34130Sstevel@tonic-gate 		__ns_ldap_freeEntry(e);
34140Sstevel@tonic-gate 		*entry = NULL;
34150Sstevel@tonic-gate 		return (NS_LDAP_MEMORY);
34160Sstevel@tonic-gate 	}
34170Sstevel@tonic-gate 
34180Sstevel@tonic-gate 	rc = __s_add_attr(e, "cn", ptr->name);
34190Sstevel@tonic-gate 	if (rc != NS_LDAP_SUCCESS) {
34200Sstevel@tonic-gate 		__s_cvt_freeEntryRdn(entry, rdn);
34210Sstevel@tonic-gate 		return (rc);
34220Sstevel@tonic-gate 	}
34230Sstevel@tonic-gate 
34240Sstevel@tonic-gate 	rc = __s_add_attr(e, "SolarisAttrKeyValue", ptr->attr);
34250Sstevel@tonic-gate 	if (rc != NS_LDAP_SUCCESS) {
34260Sstevel@tonic-gate 		__s_cvt_freeEntryRdn(entry, rdn);
34270Sstevel@tonic-gate 		return (rc);
34280Sstevel@tonic-gate 	}
34290Sstevel@tonic-gate 
34300Sstevel@tonic-gate 	if (ptr->res1 != NULL) {
34310Sstevel@tonic-gate 		rc = __s_add_attr(e, "SolarisAttrReserved1", ptr->res1);
34320Sstevel@tonic-gate 		if (rc != NS_LDAP_SUCCESS) {
34330Sstevel@tonic-gate 			__s_cvt_freeEntryRdn(entry, rdn);
34340Sstevel@tonic-gate 			return (rc);
34350Sstevel@tonic-gate 		}
34360Sstevel@tonic-gate 	}
34370Sstevel@tonic-gate 
34380Sstevel@tonic-gate 	if (ptr->res2 != NULL) {
34390Sstevel@tonic-gate 		rc = __s_add_attr(e, "SolarisAttrReserved2", ptr->res2);
34400Sstevel@tonic-gate 		if (rc != NS_LDAP_SUCCESS) {
34410Sstevel@tonic-gate 			__s_cvt_freeEntryRdn(entry, rdn);
34420Sstevel@tonic-gate 			return (rc);
34430Sstevel@tonic-gate 		}
34440Sstevel@tonic-gate 	}
34450Sstevel@tonic-gate 
34460Sstevel@tonic-gate 	if (ptr->desc != NULL) {
34470Sstevel@tonic-gate 		rc = __s_add_attr(e, "SolarisAttrLongDesc", ptr->desc);
34480Sstevel@tonic-gate 		if (rc != NS_LDAP_SUCCESS) {
34490Sstevel@tonic-gate 			__s_cvt_freeEntryRdn(entry, rdn);
34500Sstevel@tonic-gate 			return (rc);
34510Sstevel@tonic-gate 		}
34520Sstevel@tonic-gate 	}
34530Sstevel@tonic-gate 
34540Sstevel@tonic-gate 	return (NS_LDAP_SUCCESS);
34550Sstevel@tonic-gate }
34560Sstevel@tonic-gate /*
34570Sstevel@tonic-gate  * Conversion:			user_attr
34580Sstevel@tonic-gate  * Input format:		userstr_t
34590Sstevel@tonic-gate  * Exported objectclass:	SolarisUserAttr
34600Sstevel@tonic-gate  */
34610Sstevel@tonic-gate static int
__s_cvt_userattr(const void * data,char ** rdn,ns_ldap_entry_t ** entry,ns_ldap_error_t ** errorp)34620Sstevel@tonic-gate __s_cvt_userattr(const void *data, char **rdn,
34630Sstevel@tonic-gate 	ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
34640Sstevel@tonic-gate {
34650Sstevel@tonic-gate 	ns_ldap_entry_t	*e;
34660Sstevel@tonic-gate 	int		rc;
34670Sstevel@tonic-gate 	char		trdn[RDNSIZE];
34680Sstevel@tonic-gate 	/* routine specific */
34690Sstevel@tonic-gate 	userstr_t	*ptr;
34700Sstevel@tonic-gate 	int		max_attr = 5;
34710Sstevel@tonic-gate 	static		char *oclist[] = {
34720Sstevel@tonic-gate 			"SolarisUserAttr",
34730Sstevel@tonic-gate 			NULL
34740Sstevel@tonic-gate 			};
34750Sstevel@tonic-gate 
34760Sstevel@tonic-gate 	if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
34770Sstevel@tonic-gate 		return (NS_LDAP_OP_FAILED);
34780Sstevel@tonic-gate 
34790Sstevel@tonic-gate 	*entry = e = __s_mk_entry(oclist, max_attr);
34800Sstevel@tonic-gate 	if (e == NULL)
34810Sstevel@tonic-gate 		return (NS_LDAP_MEMORY);
34820Sstevel@tonic-gate 
34830Sstevel@tonic-gate 	/* Convert the structure */
34840Sstevel@tonic-gate 	ptr = (userstr_t *)data;
34850Sstevel@tonic-gate 
34860Sstevel@tonic-gate 	if (ptr->name == NULL || ptr->name[0] == '\0' ||
34870Sstevel@tonic-gate 	    ptr->attr == NULL) {
34880Sstevel@tonic-gate 		__ns_ldap_freeEntry(e);
34890Sstevel@tonic-gate 		*entry = NULL;
34900Sstevel@tonic-gate 		return (NS_LDAP_INVALID_PARAM);
34910Sstevel@tonic-gate 	}
34920Sstevel@tonic-gate 
34930Sstevel@tonic-gate 	/* Create an appropriate rdn */
34940Sstevel@tonic-gate 	(void) snprintf(trdn, RDNSIZE, "uid=%s", ptr->name);
34950Sstevel@tonic-gate 	*rdn = strdup(trdn);
34960Sstevel@tonic-gate 	if (*rdn == NULL) {
34970Sstevel@tonic-gate 		__ns_ldap_freeEntry(e);
34980Sstevel@tonic-gate 		*entry = NULL;
34990Sstevel@tonic-gate 		return (NS_LDAP_MEMORY);
35000Sstevel@tonic-gate 	}
35010Sstevel@tonic-gate 
35020Sstevel@tonic-gate 	/*
35030Sstevel@tonic-gate 	 * SolarisUserAttr has no uid attribute
35040Sstevel@tonic-gate 	 */
35050Sstevel@tonic-gate 
35060Sstevel@tonic-gate 	rc = __s_add_attr(e, "SolarisAttrKeyValue", ptr->attr);
35070Sstevel@tonic-gate 	if (rc != NS_LDAP_SUCCESS) {
35080Sstevel@tonic-gate 		__s_cvt_freeEntryRdn(entry, rdn);
35090Sstevel@tonic-gate 		return (rc);
35100Sstevel@tonic-gate 	}
35110Sstevel@tonic-gate 
35120Sstevel@tonic-gate 	if (ptr->qualifier != NULL) {
35130Sstevel@tonic-gate 		rc = __s_add_attr(e, "SolarisUserQualifier", ptr->qualifier);
35140Sstevel@tonic-gate 		if (rc != NS_LDAP_SUCCESS) {
35150Sstevel@tonic-gate 			__s_cvt_freeEntryRdn(entry, rdn);
35160Sstevel@tonic-gate 			return (rc);
35170Sstevel@tonic-gate 		}
35180Sstevel@tonic-gate 	}
35190Sstevel@tonic-gate 
35200Sstevel@tonic-gate 	if (ptr->res1 != NULL) {
35210Sstevel@tonic-gate 		rc = __s_add_attr(e, "SolarisAttrReserved1", ptr->res1);
35220Sstevel@tonic-gate 		if (rc != NS_LDAP_SUCCESS) {
35230Sstevel@tonic-gate 			__s_cvt_freeEntryRdn(entry, rdn);
35240Sstevel@tonic-gate 			return (rc);
35250Sstevel@tonic-gate 		}
35260Sstevel@tonic-gate 	}
35270Sstevel@tonic-gate 
35280Sstevel@tonic-gate 	if (ptr->res2 != NULL) {
35290Sstevel@tonic-gate 		rc = __s_add_attr(e, "SolarisAttrReserved2", ptr->res2);
35300Sstevel@tonic-gate 		if (rc != NS_LDAP_SUCCESS) {
35310Sstevel@tonic-gate 			__s_cvt_freeEntryRdn(entry, rdn);
35320Sstevel@tonic-gate 			return (rc);
35330Sstevel@tonic-gate 		}
35340Sstevel@tonic-gate 	}
35350Sstevel@tonic-gate 
35360Sstevel@tonic-gate 	return (NS_LDAP_SUCCESS);
35370Sstevel@tonic-gate }
35380Sstevel@tonic-gate /*
35390Sstevel@tonic-gate  * Conversion:			audit_user
35400Sstevel@tonic-gate  * Input format:		au_user_str_t
35410Sstevel@tonic-gate  * Exported objectclass:	SolarisAuditUser
35420Sstevel@tonic-gate  */
35430Sstevel@tonic-gate static int
__s_cvt_audituser(const void * data,char ** rdn,ns_ldap_entry_t ** entry,ns_ldap_error_t ** errorp)35440Sstevel@tonic-gate __s_cvt_audituser(const void *data, char **rdn,
35450Sstevel@tonic-gate 	ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
35460Sstevel@tonic-gate {
35470Sstevel@tonic-gate 	ns_ldap_entry_t	*e;
35480Sstevel@tonic-gate 	int		rc;
35490Sstevel@tonic-gate 	char		trdn[RDNSIZE];
35500Sstevel@tonic-gate 	/* routine specific */
35510Sstevel@tonic-gate 	au_user_str_t	*ptr;
35520Sstevel@tonic-gate 	int		max_attr = 3;
35530Sstevel@tonic-gate 	static		char *oclist[] = {
35540Sstevel@tonic-gate 			"SolarisAuditUser",
35550Sstevel@tonic-gate 			NULL
35560Sstevel@tonic-gate 			};
35570Sstevel@tonic-gate 
35580Sstevel@tonic-gate 	if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
35590Sstevel@tonic-gate 		return (NS_LDAP_OP_FAILED);
35600Sstevel@tonic-gate 
35610Sstevel@tonic-gate 	*entry = e = __s_mk_entry(oclist, max_attr);
35620Sstevel@tonic-gate 	if (e == NULL)
35630Sstevel@tonic-gate 		return (NS_LDAP_MEMORY);
35640Sstevel@tonic-gate 
35650Sstevel@tonic-gate 	/* Convert the structure */
35660Sstevel@tonic-gate 	ptr = (au_user_str_t *)data;
35670Sstevel@tonic-gate 
35680Sstevel@tonic-gate 	if (ptr->au_name == NULL || ptr->au_name[0] == '\0') {
35690Sstevel@tonic-gate 		__ns_ldap_freeEntry(e);
35700Sstevel@tonic-gate 		*entry = NULL;
35710Sstevel@tonic-gate 		return (NS_LDAP_INVALID_PARAM);
35720Sstevel@tonic-gate 	}
35730Sstevel@tonic-gate 
35740Sstevel@tonic-gate 	/* Create an appropriate rdn */
35750Sstevel@tonic-gate 	(void) snprintf(trdn, RDNSIZE, "uid=%s", ptr->au_name);
35760Sstevel@tonic-gate 	*rdn = strdup(trdn);
35770Sstevel@tonic-gate 	if (*rdn == NULL) {
35780Sstevel@tonic-gate 		__ns_ldap_freeEntry(e);
35790Sstevel@tonic-gate 		*entry = NULL;
35800Sstevel@tonic-gate 		return (NS_LDAP_MEMORY);
35810Sstevel@tonic-gate 	}
35820Sstevel@tonic-gate 
35830Sstevel@tonic-gate 	/*
35840Sstevel@tonic-gate 	 * Solaris AuditUser has no uid attribute
35850Sstevel@tonic-gate 	 */
35860Sstevel@tonic-gate 
35870Sstevel@tonic-gate 	if (ptr->au_always != NULL) {
35880Sstevel@tonic-gate 		rc = __s_add_attr(e, "SolarisAuditAlways", ptr->au_always);
35890Sstevel@tonic-gate 		if (rc != NS_LDAP_SUCCESS) {
35900Sstevel@tonic-gate 			__s_cvt_freeEntryRdn(entry, rdn);
35910Sstevel@tonic-gate 			return (rc);
35920Sstevel@tonic-gate 		}
35930Sstevel@tonic-gate 	}
35940Sstevel@tonic-gate 
35950Sstevel@tonic-gate 	if (ptr->au_never != NULL) {
35960Sstevel@tonic-gate 		rc = __s_add_attr(e, "SolarisAuditNever", ptr->au_never);
35970Sstevel@tonic-gate 		if (rc != NS_LDAP_SUCCESS) {
35980Sstevel@tonic-gate 			__s_cvt_freeEntryRdn(entry, rdn);
35990Sstevel@tonic-gate 			return (rc);
36000Sstevel@tonic-gate 		}
36010Sstevel@tonic-gate 	}
36020Sstevel@tonic-gate 
36030Sstevel@tonic-gate 	return (NS_LDAP_SUCCESS);
36040Sstevel@tonic-gate }
36051676Sjpk /*
36061676Sjpk  * Conversion:			tnrhtp
36071676Sjpk  * Input format:		tsol_tpstr_t
36081676Sjpk  * Exported objectclass:	ipTnetTemplate
36091676Sjpk  */
36101676Sjpk static int
__s_cvt_tnrhtp(const void * data,char ** rdn,ns_ldap_entry_t ** entry,ns_ldap_error_t ** errorp)36111676Sjpk __s_cvt_tnrhtp(const void *data, char **rdn,
36121676Sjpk 	ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
36131676Sjpk {
36141676Sjpk 	ns_ldap_entry_t	*e;
36151676Sjpk 	int		rc;
36161676Sjpk 	char		trdn[RDNSIZE];
36179288SSreedhar.Chalamalasetti@Sun.COM 	char		esc_str[RDNSIZE];
36181676Sjpk 	/* routine specific */
36191676Sjpk 	int		max_attr = 2;
36201676Sjpk 	tsol_tpstr_t	*ptr;
36211676Sjpk 	static		char *oclist[] = {
36221676Sjpk 			"ipTnetTemplate",
36231676Sjpk 			"top",
36241676Sjpk 			NULL
36251676Sjpk 			};
36261676Sjpk 
36271676Sjpk 	if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
36281676Sjpk 		return (NS_LDAP_OP_FAILED);
36291676Sjpk 
36301676Sjpk 	*entry = e = __s_mk_entry(oclist, max_attr);
36311676Sjpk 	if (e == NULL)
36321676Sjpk 		return (NS_LDAP_MEMORY);
36331676Sjpk 
36341676Sjpk 	/* Convert the structure */
36351676Sjpk 	ptr = (tsol_tpstr_t *)data;
36361676Sjpk 
36376956Sth160488 	if (ptr->template == NULL || *ptr->template == '\0') {
36381676Sjpk 		__ns_ldap_freeEntry(e);
36391676Sjpk 		*entry = NULL;
36401676Sjpk 		return (NS_LDAP_INVALID_PARAM);
36411676Sjpk 	}
36421676Sjpk 
36439288SSreedhar.Chalamalasetti@Sun.COM 	/*
36449288SSreedhar.Chalamalasetti@Sun.COM 	 * Escape special characters in Template name.
36459288SSreedhar.Chalamalasetti@Sun.COM 	 */
36469288SSreedhar.Chalamalasetti@Sun.COM 	if (escape_str(esc_str, ptr->template) != 0) {
36479288SSreedhar.Chalamalasetti@Sun.COM 		__ns_ldap_freeEntry(e);
36489288SSreedhar.Chalamalasetti@Sun.COM 		*entry = NULL;
36499288SSreedhar.Chalamalasetti@Sun.COM 		return (NS_LDAP_INVALID_PARAM);
36509288SSreedhar.Chalamalasetti@Sun.COM 	}
36519288SSreedhar.Chalamalasetti@Sun.COM 
36521676Sjpk 	/* Create an appropriate rdn */
36539288SSreedhar.Chalamalasetti@Sun.COM 	(void) snprintf(trdn, RDNSIZE, "ipTnetTemplateName=%s", esc_str);
36541676Sjpk 	*rdn = strdup(trdn);
36551676Sjpk 	if (*rdn == NULL) {
36561676Sjpk 		__ns_ldap_freeEntry(e);
36571676Sjpk 		*entry = NULL;
36581676Sjpk 		return (NS_LDAP_MEMORY);
36591676Sjpk 	}
36601676Sjpk 
36611676Sjpk 	rc = __s_add_attr(e, "ipTnetTemplateName", ptr->template);
36621676Sjpk 	if (rc != NS_LDAP_SUCCESS) {
36631676Sjpk 		__s_cvt_freeEntryRdn(entry, rdn);
36641676Sjpk 		return (rc);
36651676Sjpk 	}
36661676Sjpk 
36671676Sjpk 	rc = __s_add_attr(e, "SolarisAttrKeyValue", ptr->attrs);
36681676Sjpk 	if (rc != NS_LDAP_SUCCESS) {
36691676Sjpk 		__s_cvt_freeEntryRdn(entry, rdn);
36701676Sjpk 		return (rc);
36711676Sjpk 	}
36721676Sjpk 
36731676Sjpk 	return (NS_LDAP_SUCCESS);
36741676Sjpk }
36751676Sjpk /*
36761676Sjpk  * Conversion:			tnrhdb
36771676Sjpk  * Input format:		tsol_rhstr_t
36781676Sjpk  * Exported objectclass:	ipTnetHost
36791676Sjpk  */
36801676Sjpk static int
__s_cvt_tnrhdb(const void * data,char ** rdn,ns_ldap_entry_t ** entry,ns_ldap_error_t ** errorp)36811676Sjpk __s_cvt_tnrhdb(const void *data, char **rdn,
36821676Sjpk 	ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
36831676Sjpk {
36841676Sjpk 	ns_ldap_entry_t	*e;
36851676Sjpk 	int		rc;
36861676Sjpk 	char		trdn[RDNSIZE];
36871676Sjpk 	/* routine specific */
36881676Sjpk 	tsol_rhstr_t	*ptr;
36891676Sjpk 	int		max_attr = 2;
36901676Sjpk 	static		char *oclist[] = {
36911676Sjpk 			"ipTnetHost",
36921676Sjpk 			"ipTnetTemplate",
36931676Sjpk 			"top",
36941676Sjpk 			NULL
36951676Sjpk 			};
36961676Sjpk 
36971676Sjpk 	if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
36981676Sjpk 		return (NS_LDAP_OP_FAILED);
36991676Sjpk 
37001676Sjpk 	*entry = e = __s_mk_entry(oclist, max_attr);
37011676Sjpk 	if (e == NULL)
37021676Sjpk 		return (NS_LDAP_MEMORY);
37031676Sjpk 
37041676Sjpk 	/* Convert the structure */
37051676Sjpk 	ptr = (tsol_rhstr_t *)data;
37061676Sjpk 
37076956Sth160488 	if (ptr->address == NULL || *ptr->address == '\0' ||
37086956Sth160488 	    ptr->template == NULL || *ptr->template == '\0') {
37091676Sjpk 		__ns_ldap_freeEntry(e);
37101676Sjpk 		*entry = NULL;
37111676Sjpk 		return (NS_LDAP_INVALID_PARAM);
37121676Sjpk 	}
37131676Sjpk 
37141676Sjpk 	/* Create an appropriate rdn */
37151676Sjpk 	(void) snprintf(trdn, RDNSIZE, "ipTnetNumber=%s", ptr->address);
37161676Sjpk 	*rdn = strdup(trdn);
37171676Sjpk 	if (*rdn == NULL) {
37181676Sjpk 		__ns_ldap_freeEntry(e);
37191676Sjpk 		*entry = NULL;
37201676Sjpk 		return (NS_LDAP_MEMORY);
37211676Sjpk 	}
37221676Sjpk 
37231676Sjpk 	rc = __s_add_attr(e, "ipTnetNumber", ptr->address);
37241676Sjpk 	if (rc != NS_LDAP_SUCCESS) {
37251676Sjpk 		__s_cvt_freeEntryRdn(entry, rdn);
37261676Sjpk 		return (rc);
37271676Sjpk 	}
37281676Sjpk 
37291676Sjpk 	rc = __s_add_attr(e, "ipTnetTemplateName", ptr->template);
37301676Sjpk 	if (rc != NS_LDAP_SUCCESS) {
37311676Sjpk 		__s_cvt_freeEntryRdn(entry, rdn);
37321676Sjpk 		return (rc);
37331676Sjpk 	}
37341676Sjpk 
37351676Sjpk 	return (NS_LDAP_SUCCESS);
37361676Sjpk }
37370Sstevel@tonic-gate /*
37380Sstevel@tonic-gate  * Add Typed Entry Conversion data structures
37390Sstevel@tonic-gate  */
37400Sstevel@tonic-gate 
37410Sstevel@tonic-gate typedef struct	__ns_cvt_type {
37420Sstevel@tonic-gate 	const char	*service;
37430Sstevel@tonic-gate 	int		flags;
37440Sstevel@tonic-gate #define	AE		1	/* alway add entries */
37450Sstevel@tonic-gate 	int		(*cvt_rtn)(const void *data,
37460Sstevel@tonic-gate 				char		**rdn,
37470Sstevel@tonic-gate 				ns_ldap_entry_t	**entry,
37480Sstevel@tonic-gate 				ns_ldap_error_t	**errorp);
37490Sstevel@tonic-gate } __ns_cvt_type_t;
37500Sstevel@tonic-gate 
37510Sstevel@tonic-gate static __ns_cvt_type_t __s_cvtlist[] = {
37520Sstevel@tonic-gate 	{ NS_LDAP_TYPE_PASSWD,		0, __s_cvt_passwd },
37530Sstevel@tonic-gate 	{ NS_LDAP_TYPE_GROUP,		0, __s_cvt_group },
37540Sstevel@tonic-gate 	{ NS_LDAP_TYPE_HOSTS,		0, __s_cvt_hosts },
37550Sstevel@tonic-gate 	{ NS_LDAP_TYPE_IPNODES,		0, __s_cvt_hosts },
37560Sstevel@tonic-gate 	{ NS_LDAP_TYPE_RPC,		0, __s_cvt_rpc },
37570Sstevel@tonic-gate 	{ NS_LDAP_TYPE_PROTOCOLS,	0, __s_cvt_protocols },
37580Sstevel@tonic-gate 	{ NS_LDAP_TYPE_NETWORKS,	0, __s_cvt_networks },
37590Sstevel@tonic-gate 	{ NS_LDAP_TYPE_NETGROUP,	0, __s_cvt_netgroups },
37600Sstevel@tonic-gate 	{ NS_LDAP_TYPE_ALIASES,		0, __s_cvt_aliases },
37610Sstevel@tonic-gate 	{ NS_LDAP_TYPE_SERVICES,	0, __s_cvt_services },
37620Sstevel@tonic-gate 	{ NS_LDAP_TYPE_ETHERS,		0, __s_cvt_ethers },
37630Sstevel@tonic-gate 	{ NS_LDAP_TYPE_SHADOW,		0, __s_cvt_shadow },
37640Sstevel@tonic-gate 	{ NS_LDAP_TYPE_NETMASKS,	0, __s_cvt_netmasks },
37650Sstevel@tonic-gate 	{ NS_LDAP_TYPE_BOOTPARAMS,	0, __s_cvt_bootparams },
37660Sstevel@tonic-gate 	{ NS_LDAP_TYPE_AUTHATTR,	0, __s_cvt_authattr },
37670Sstevel@tonic-gate 	{ NS_LDAP_TYPE_EXECATTR,	0, __s_cvt_execattr },
37680Sstevel@tonic-gate 	{ NS_LDAP_TYPE_PROFILE,		0, __s_cvt_profattr },
37690Sstevel@tonic-gate 	{ NS_LDAP_TYPE_USERATTR,	AE, __s_cvt_userattr },
37700Sstevel@tonic-gate 	{ NS_LDAP_TYPE_AUTOMOUNT,	0, __s_cvt_auto_mount },
37710Sstevel@tonic-gate 	{ NS_LDAP_TYPE_PUBLICKEY,	AE, __s_cvt_publickey },
37720Sstevel@tonic-gate 	{ NS_LDAP_TYPE_AUUSER,		AE, __s_cvt_audituser },
37731676Sjpk 	{ NS_LDAP_TYPE_TNRHTP,		0,  __s_cvt_tnrhtp },
37741676Sjpk 	{ NS_LDAP_TYPE_TNRHDB,		0,  __s_cvt_tnrhdb },
37756842Sth160488 	{ NS_LDAP_TYPE_PROJECT,		0,  __s_cvt_project },
37760Sstevel@tonic-gate 	{ NULL,				0, NULL },
37770Sstevel@tonic-gate };
37780Sstevel@tonic-gate 
37790Sstevel@tonic-gate /*
37800Sstevel@tonic-gate  * Add Typed Entry Routine
37810Sstevel@tonic-gate  */
37820Sstevel@tonic-gate 
37830Sstevel@tonic-gate /*ARGSUSED*/
__ns_ldap_addTypedEntry(const char * servicetype,const char * basedn,const void * data,const int create,const ns_cred_t * cred,const int flags,ns_ldap_error_t ** errorp)37840Sstevel@tonic-gate int  __ns_ldap_addTypedEntry(
37850Sstevel@tonic-gate 	const char *servicetype,
37860Sstevel@tonic-gate 	const char *basedn,
37870Sstevel@tonic-gate 	const void *data,
37880Sstevel@tonic-gate 	const int  create,
37890Sstevel@tonic-gate 	const ns_cred_t *cred,
37900Sstevel@tonic-gate 	const int flags,
37910Sstevel@tonic-gate 	ns_ldap_error_t **errorp)
37920Sstevel@tonic-gate {
37930Sstevel@tonic-gate 	char			*rdn = NULL, *fulldn = NULL;
37940Sstevel@tonic-gate 	void			**paramVal = NULL;
37950Sstevel@tonic-gate 	ns_ldap_entry_t 	*entry = NULL;
37960Sstevel@tonic-gate 	const ns_ldap_attr_t	*const *modattrlist;
37970Sstevel@tonic-gate 	ns_ldap_search_desc_t	**sdlist;
37980Sstevel@tonic-gate 	char			**dns = NULL;
37990Sstevel@tonic-gate 	char			trdn[RDNSIZE];
38000Sstevel@tonic-gate 	char			service[BUFSIZE];
38010Sstevel@tonic-gate 	int			rc = 0;
38020Sstevel@tonic-gate 	int			automount = 0;
38030Sstevel@tonic-gate 	int			i, s;
38040Sstevel@tonic-gate 
38050Sstevel@tonic-gate 	rc = NS_LDAP_OP_FAILED;
38060Sstevel@tonic-gate 	for (s = 0; __s_cvtlist[s].service != NULL; s++) {
38070Sstevel@tonic-gate 		if (__s_cvtlist[s].cvt_rtn == NULL)
38080Sstevel@tonic-gate 			continue;
38090Sstevel@tonic-gate 		if (strcasecmp(__s_cvtlist[s].service, servicetype) == 0)
38100Sstevel@tonic-gate 			break;
38110Sstevel@tonic-gate 		/* Or, check if the servicetype is  auto_ */
38120Sstevel@tonic-gate 		if (strcmp(__s_cvtlist[s].service,
38130Sstevel@tonic-gate 		    NS_LDAP_TYPE_AUTOMOUNT) == 0 &&
38140Sstevel@tonic-gate 		    strncasecmp(servicetype, NS_LDAP_TYPE_AUTOMOUNT,
38150Sstevel@tonic-gate 		    sizeof (NS_LDAP_TYPE_AUTOMOUNT) - 1) == 0) {
38160Sstevel@tonic-gate 			automount++;
38170Sstevel@tonic-gate 			break;
38180Sstevel@tonic-gate 		}
38190Sstevel@tonic-gate 	}
38200Sstevel@tonic-gate 	if (__s_cvtlist[s].service == NULL)
38210Sstevel@tonic-gate 		return (rc);
38220Sstevel@tonic-gate 
38230Sstevel@tonic-gate 	/* Convert the data */
38240Sstevel@tonic-gate 	rc = (*__s_cvtlist[s].cvt_rtn)(data, &rdn, &entry, errorp);
38250Sstevel@tonic-gate 	if (rc != NS_LDAP_SUCCESS) {
38260Sstevel@tonic-gate 		__s_cvt_freeEntryRdn(&entry, &rdn);
38270Sstevel@tonic-gate 		return (rc);
38280Sstevel@tonic-gate 	}
38290Sstevel@tonic-gate 	if (rdn == NULL) {
38300Sstevel@tonic-gate 		__ns_ldap_freeEntry(entry);
38310Sstevel@tonic-gate 		return (NS_LDAP_OP_FAILED);
38320Sstevel@tonic-gate 	}
38330Sstevel@tonic-gate 
38340Sstevel@tonic-gate 	if (strcmp(servicetype, "publickey") == 0) {
38350Sstevel@tonic-gate 		struct _ns_pubkey *ptr;
38360Sstevel@tonic-gate 		ptr = (struct _ns_pubkey *)data;
38370Sstevel@tonic-gate 		if (ptr->hostcred == NS_HOSTCRED_TRUE)
38380Sstevel@tonic-gate 			(void) strcpy(service, "hosts");
38390Sstevel@tonic-gate 		else
38400Sstevel@tonic-gate 			(void) strcpy(service, "passwd");
38410Sstevel@tonic-gate 	} else
38420Sstevel@tonic-gate 		(void) strcpy(service, servicetype);
38430Sstevel@tonic-gate 
38440Sstevel@tonic-gate 	/* Create the Full DN */
38450Sstevel@tonic-gate 	if (basedn == NULL) {
38460Sstevel@tonic-gate 		rc = __s_api_get_SSD_from_SSDtoUse_service(service,
38470Sstevel@tonic-gate 		    &sdlist, errorp);
38480Sstevel@tonic-gate 		if (rc != NS_LDAP_SUCCESS) {
38490Sstevel@tonic-gate 			__s_cvt_freeEntryRdn(&entry, &rdn);
38500Sstevel@tonic-gate 			return (rc);
38510Sstevel@tonic-gate 		}
38520Sstevel@tonic-gate 
38530Sstevel@tonic-gate 		if (sdlist == NULL) {
38540Sstevel@tonic-gate 			rc = __s_api_getDNs(&dns, service, errorp);
38550Sstevel@tonic-gate 			if (rc != NS_LDAP_SUCCESS) {
38560Sstevel@tonic-gate 				if (dns) {
38570Sstevel@tonic-gate 					__s_api_free2dArray(dns);
38580Sstevel@tonic-gate 					dns = NULL;
38590Sstevel@tonic-gate 				}
38600Sstevel@tonic-gate 				__s_cvt_freeEntryRdn(&entry, &rdn);
38610Sstevel@tonic-gate 				return (rc);
38620Sstevel@tonic-gate 			}
38630Sstevel@tonic-gate 			(void) snprintf(trdn, RDNSIZE, "%s,%s", rdn, dns[0]);
38640Sstevel@tonic-gate 			__s_api_free2dArray(dns);
38650Sstevel@tonic-gate 		} else {
38660Sstevel@tonic-gate 			if (sdlist[0]->basedn) {
38670Sstevel@tonic-gate 				(void) snprintf(trdn, RDNSIZE, "%s,%s",
38680Sstevel@tonic-gate 				    rdn, sdlist[0]->basedn);
38690Sstevel@tonic-gate 			} else {
38700Sstevel@tonic-gate 				__s_cvt_freeEntryRdn(&entry, &rdn);
38710Sstevel@tonic-gate 				return (NS_LDAP_OP_FAILED);
38720Sstevel@tonic-gate 			}
38730Sstevel@tonic-gate 		}
38740Sstevel@tonic-gate 		i = strlen(trdn) - 1;
38750Sstevel@tonic-gate 		if (trdn[i] == COMMATOK) {
38760Sstevel@tonic-gate 			rc = __ns_ldap_getParam(NS_LDAP_SEARCH_BASEDN_P,
38770Sstevel@tonic-gate 			    &paramVal, errorp);
38780Sstevel@tonic-gate 			if (rc != NS_LDAP_SUCCESS) {
38790Sstevel@tonic-gate 				__s_cvt_freeEntryRdn(&entry, &rdn);
38800Sstevel@tonic-gate 				return (rc);
38810Sstevel@tonic-gate 			}
38820Sstevel@tonic-gate 			i = strlen(trdn) + strlen((char *)(paramVal[0])) + 1;
38830Sstevel@tonic-gate 			fulldn = (char *)calloc(i, 1);
38840Sstevel@tonic-gate 			if (fulldn == NULL) {
38850Sstevel@tonic-gate 				(void) __ns_ldap_freeParam(&paramVal);
38860Sstevel@tonic-gate 				__s_cvt_freeEntryRdn(&entry, &rdn);
38870Sstevel@tonic-gate 				return (NS_LDAP_MEMORY);
38880Sstevel@tonic-gate 			}
38890Sstevel@tonic-gate 			(void) snprintf(fulldn, i, "%s%s", trdn,
38900Sstevel@tonic-gate 			    (char *)(paramVal[0]));
38910Sstevel@tonic-gate 			(void) __ns_ldap_freeParam(&paramVal);
38920Sstevel@tonic-gate 		} else {
38930Sstevel@tonic-gate 			fulldn = strdup(trdn);
38940Sstevel@tonic-gate 			if (fulldn == NULL) {
38950Sstevel@tonic-gate 				__s_cvt_freeEntryRdn(&entry, &rdn);
38960Sstevel@tonic-gate 				return (NS_LDAP_MEMORY);
38970Sstevel@tonic-gate 			}
38980Sstevel@tonic-gate 		}
38990Sstevel@tonic-gate 	} else {
39000Sstevel@tonic-gate 		i = strlen(rdn) + strlen(basedn) + 2;
39010Sstevel@tonic-gate 		fulldn = (char *)calloc(i, 1);
39020Sstevel@tonic-gate 		if (fulldn == NULL) {
39030Sstevel@tonic-gate 			__s_cvt_freeEntryRdn(&entry, &rdn);
39040Sstevel@tonic-gate 			return (NS_LDAP_MEMORY);
39050Sstevel@tonic-gate 		}
39060Sstevel@tonic-gate 		(void) snprintf(fulldn, i, "%s,%s", rdn, basedn);
39070Sstevel@tonic-gate 	}
39080Sstevel@tonic-gate 
39090Sstevel@tonic-gate 	modattrlist = (const ns_ldap_attr_t * const *)entry->attr_pair;
39100Sstevel@tonic-gate 	/* Check to see if the entry exists already */
39110Sstevel@tonic-gate 	/* May need to delete or update first */
39120Sstevel@tonic-gate 
39130Sstevel@tonic-gate 	if (create != 1) {
39140Sstevel@tonic-gate 		/* Modify the entry */
39152277Sjs198686 		/*
39162277Sjs198686 		 * To add a shadow-like entry, the addTypedEntry function
39172277Sjs198686 		 * would call __ns_ldap_repAttr first, and if server says
39182277Sjs198686 		 * LDAP_NO_SUCH_OBJECT, then it tries __ns_ldap_addEntry.
39192277Sjs198686 		 * This is to allow a netmask entry to be added even if the
39202277Sjs198686 		 * base network entry is not in the directory. It would work
39212277Sjs198686 		 * because the difference between the schema for the network
39222277Sjs198686 		 * and netmask data contains only MAY attributes.
39232277Sjs198686 		 *
39242277Sjs198686 		 * But for shadow data, the attributes do not have MUST
39252277Sjs198686 		 * attributes the base entry needs, so if the __ns_ldap_addEntry
39262277Sjs198686 		 * is executed, it would fail. The real reason, however, is that
39272277Sjs198686 		 * the base entry did not exist. So returning
39282277Sjs198686 		 * LDAP_OBJECT_CLASS_VIOLATION would just confused.
39292277Sjs198686 		 */
39300Sstevel@tonic-gate 		if ((__s_cvtlist[s].flags & AE) != 0)
39310Sstevel@tonic-gate 			rc = __ns_ldap_addAttr(service, fulldn, modattrlist,
39320Sstevel@tonic-gate 			    cred, flags, errorp);
39330Sstevel@tonic-gate 		else {
39340Sstevel@tonic-gate 			rc = __ns_ldap_repAttr(service, fulldn, modattrlist,
39356842Sth160488 			    cred, flags, errorp);
39360Sstevel@tonic-gate 			if (rc == NS_LDAP_INTERNAL && *errorp &&
39370Sstevel@tonic-gate 			    (*errorp)->status == LDAP_NO_SUCH_OBJECT) {
39380Sstevel@tonic-gate 				(void) __ns_ldap_freeError(errorp);
39390Sstevel@tonic-gate 				rc = __ns_ldap_addEntry(service, fulldn,
39400Sstevel@tonic-gate 				    entry, cred, flags, errorp);
39412277Sjs198686 				if (rc == NS_LDAP_INTERNAL && *errorp &&
39426842Sth160488 				    (*errorp)->status ==
39436842Sth160488 				    LDAP_OBJECT_CLASS_VIOLATION)
39442277Sjs198686 					(*errorp)->status = LDAP_NO_SUCH_OBJECT;
39450Sstevel@tonic-gate 			}
39460Sstevel@tonic-gate 		}
39470Sstevel@tonic-gate 	} else {
39480Sstevel@tonic-gate 		/* Add the entry */
39490Sstevel@tonic-gate 		rc = __ns_ldap_addEntry(service, fulldn, entry,
39500Sstevel@tonic-gate 		    cred, flags, errorp);
39510Sstevel@tonic-gate 		if (rc == NS_LDAP_INTERNAL && *errorp &&
39520Sstevel@tonic-gate 		    (*errorp)->status == LDAP_ALREADY_EXISTS &&
39530Sstevel@tonic-gate 		    ((strcmp(service, "ethers") == 0) ||
39540Sstevel@tonic-gate 		    (strcmp(service, "bootparams") == 0))) {
39550Sstevel@tonic-gate 			rc = modify_ethers_bootp(service, rdn, fulldn,
39560Sstevel@tonic-gate 			    modattrlist, cred, flags, errorp);
39570Sstevel@tonic-gate 		}
39580Sstevel@tonic-gate 	}
39590Sstevel@tonic-gate 
39600Sstevel@tonic-gate 	/* Free up entry created by conversion routine */
39610Sstevel@tonic-gate 	if (fulldn != NULL)
39620Sstevel@tonic-gate 		free(fulldn);
39630Sstevel@tonic-gate 	__s_cvt_freeEntryRdn(&entry, &rdn);
39640Sstevel@tonic-gate 	return (rc);
39650Sstevel@tonic-gate }
39660Sstevel@tonic-gate 
39670Sstevel@tonic-gate 
39680Sstevel@tonic-gate /*
39690Sstevel@tonic-gate  * Append the default base dn to the dn
39700Sstevel@tonic-gate  * when it ends with ','.
39710Sstevel@tonic-gate  * e.g.
39720Sstevel@tonic-gate  * SSD = service:ou=foo,
39730Sstevel@tonic-gate  */
39740Sstevel@tonic-gate int
__s_api_append_default_basedn(const char * dn,char ** new_dn,int * allocated,ns_ldap_error_t ** errp)39750Sstevel@tonic-gate __s_api_append_default_basedn(
39760Sstevel@tonic-gate 	const char *dn,
39770Sstevel@tonic-gate 	char **new_dn,
39780Sstevel@tonic-gate 	int *allocated,
39790Sstevel@tonic-gate 	ns_ldap_error_t **errp) {
39800Sstevel@tonic-gate 
39810Sstevel@tonic-gate 	int		rc = NS_LDAP_SUCCESS, len = 0;
39820Sstevel@tonic-gate 	void		**param = NULL;
39830Sstevel@tonic-gate 	char		*str = NULL;
39840Sstevel@tonic-gate 
39850Sstevel@tonic-gate 	*allocated = FALSE;
39860Sstevel@tonic-gate 	*new_dn = NULL;
39870Sstevel@tonic-gate 
39880Sstevel@tonic-gate 	if (dn == NULL)
39890Sstevel@tonic-gate 		return (NS_LDAP_INVALID_PARAM);
39900Sstevel@tonic-gate 
39910Sstevel@tonic-gate 	rc = __ns_ldap_getParam(NS_LDAP_SEARCH_BASEDN_P,
39920Sstevel@tonic-gate 		(void ***)&param, errp);
39930Sstevel@tonic-gate 
39940Sstevel@tonic-gate 	if (rc != NS_LDAP_SUCCESS) {
39950Sstevel@tonic-gate 		if (param)
39960Sstevel@tonic-gate 			(void) __ns_ldap_freeParam(&param);
39970Sstevel@tonic-gate 		return (rc);
39980Sstevel@tonic-gate 	}
39990Sstevel@tonic-gate 
40000Sstevel@tonic-gate 	len = strlen(dn);
40010Sstevel@tonic-gate 	str = ((char **)param)[0];
40020Sstevel@tonic-gate 	len = len + strlen(str) +1;
40030Sstevel@tonic-gate 	*new_dn = (char *)malloc(len);
40040Sstevel@tonic-gate 	if (*new_dn == NULL) {
40050Sstevel@tonic-gate 		(void) __ns_ldap_freeParam(&param);
40060Sstevel@tonic-gate 		return (NS_LDAP_MEMORY);
40070Sstevel@tonic-gate 	}
40080Sstevel@tonic-gate 	*allocated = TRUE;
40090Sstevel@tonic-gate 
40100Sstevel@tonic-gate 	(void) strcpy(*new_dn, dn);
40110Sstevel@tonic-gate 	(void) strcat(*new_dn, str);
40120Sstevel@tonic-gate 
40130Sstevel@tonic-gate 	(void) __ns_ldap_freeParam(&param);
40140Sstevel@tonic-gate 	return (NS_LDAP_SUCCESS);
40150Sstevel@tonic-gate }
40168821SMichen.Chang@Sun.COM 
40178821SMichen.Chang@Sun.COM /*
40188821SMichen.Chang@Sun.COM  * Flatten the input ns_ldap_attr_t list, 'attr', and convert it into an
40198821SMichen.Chang@Sun.COM  * ldap_strlist_t structure in buffer 'buf', to be used by ldap_cachemgr.
40208821SMichen.Chang@Sun.COM  * The output contains a count, a list of offsets, which show where the
40218821SMichen.Chang@Sun.COM  * corresponding copied attribute type and attribute value are located.
40228821SMichen.Chang@Sun.COM  * For example, for dn=aaaa, userpassword=bbbb, shadowlastchange=cccc,
40238821SMichen.Chang@Sun.COM  * the output is the ldap_strlist_t structure with: ldap_count = 6,
40248821SMichen.Chang@Sun.COM  * (buf + ldap_offsets[0]) -> "dn"
40258821SMichen.Chang@Sun.COM  * (buf + ldap_offsets[1]) -> "aaaa"
40268821SMichen.Chang@Sun.COM  * (buf + ldap_offsets[2]) -> "userPassword"
40278821SMichen.Chang@Sun.COM  * (buf + ldap_offsets[3]) -> "bbbb"
40288821SMichen.Chang@Sun.COM  * (buf + ldap_offsets[4]) -> "shadowlastchange"
40298821SMichen.Chang@Sun.COM  * (buf + ldap_offsets[5]) -> "cccc"
40308821SMichen.Chang@Sun.COM  * and all the string data shown above copied into the buffer after
40318821SMichen.Chang@Sun.COM  * the offset array. The total length of the data will be the return
40328821SMichen.Chang@Sun.COM  * value, or -1 if error.
40338821SMichen.Chang@Sun.COM  */
40348821SMichen.Chang@Sun.COM static int
attr2list(const char * dn,ns_ldap_attr_t ** attr,char * buf,int bufsize)40358821SMichen.Chang@Sun.COM attr2list(const char *dn, ns_ldap_attr_t **attr,
40368821SMichen.Chang@Sun.COM     char *buf, int bufsize)
40378821SMichen.Chang@Sun.COM {
40388821SMichen.Chang@Sun.COM 	int		c = 0;
40398821SMichen.Chang@Sun.COM 	char		*ap;
40408821SMichen.Chang@Sun.COM 	int		ao;
40418821SMichen.Chang@Sun.COM 	ldap_strlist_t	*al = (ldap_strlist_t *)buf;
40428821SMichen.Chang@Sun.COM 	ns_ldap_attr_t	*a = (ns_ldap_attr_t *)*attr;
40438821SMichen.Chang@Sun.COM 	ns_ldap_attr_t	**aptr = (ns_ldap_attr_t **)attr;
40448821SMichen.Chang@Sun.COM 
40458821SMichen.Chang@Sun.COM 	/* bufsize > strlen(dn) + strlen("dn") + 1 ('\0') */
40468821SMichen.Chang@Sun.COM 	if ((strlen(dn) + 2 + 1) >= bufsize)
40478821SMichen.Chang@Sun.COM 		return (-1);
40488821SMichen.Chang@Sun.COM 
40498821SMichen.Chang@Sun.COM 	/* count number of attributes */
40508821SMichen.Chang@Sun.COM 	while (*aptr++)
40518821SMichen.Chang@Sun.COM 		c++;
40528821SMichen.Chang@Sun.COM 	al->ldap_count = 2 + c * 2;
40538821SMichen.Chang@Sun.COM 	ao = sizeof (al->ldap_count) + sizeof (al->ldap_offsets[0]) *
40548821SMichen.Chang@Sun.COM 	    al->ldap_count;
40558821SMichen.Chang@Sun.COM 	if (ao > bufsize)
40568821SMichen.Chang@Sun.COM 		return (-1);
40578821SMichen.Chang@Sun.COM 	al->ldap_offsets[0] = ao;
40588821SMichen.Chang@Sun.COM 	ap = buf + ao;
40598821SMichen.Chang@Sun.COM 	ao += 3;
40608821SMichen.Chang@Sun.COM 
40618821SMichen.Chang@Sun.COM 	/* copy entry DN */
40628821SMichen.Chang@Sun.COM 	if (ao > bufsize)
40638821SMichen.Chang@Sun.COM 		return (-1);
40648821SMichen.Chang@Sun.COM 	(void) strlcpy(ap, "dn", bufsize);
40658821SMichen.Chang@Sun.COM 	ap += 3;
40668821SMichen.Chang@Sun.COM 
40678821SMichen.Chang@Sun.COM 	al->ldap_offsets[1] = ao;
40688821SMichen.Chang@Sun.COM 	ao += strlen(dn) + 1;
40698821SMichen.Chang@Sun.COM 	if (ao > bufsize)
40708821SMichen.Chang@Sun.COM 		return (-1);
40718821SMichen.Chang@Sun.COM 	(void) strlcpy(ap, dn, bufsize);
40728821SMichen.Chang@Sun.COM 	ap = buf + ao;
40738821SMichen.Chang@Sun.COM 
40748821SMichen.Chang@Sun.COM 	aptr = attr;
40758821SMichen.Chang@Sun.COM 	for (c = 2; c < al->ldap_count; c++, aptr++) {
40768821SMichen.Chang@Sun.COM 		a = *aptr;
40778821SMichen.Chang@Sun.COM 		if (a->attrname == NULL || a->attrvalue == NULL ||
40788821SMichen.Chang@Sun.COM 		    a->value_count != 1 || a->attrvalue[0] == NULL)
40798821SMichen.Chang@Sun.COM 			return (-1);
40808821SMichen.Chang@Sun.COM 		al->ldap_offsets[c] = ao;
40818821SMichen.Chang@Sun.COM 		ao += strlen(a->attrname) + 1;
40828821SMichen.Chang@Sun.COM 		if (ao > bufsize)
40838821SMichen.Chang@Sun.COM 			return (-1);
40848821SMichen.Chang@Sun.COM 		(void) strlcpy(ap, a->attrname, bufsize);
40858821SMichen.Chang@Sun.COM 		ap = buf + ao;
40868821SMichen.Chang@Sun.COM 
40878821SMichen.Chang@Sun.COM 		c++;
40888821SMichen.Chang@Sun.COM 		al->ldap_offsets[c] = ao;
40898821SMichen.Chang@Sun.COM 		ao += strlen(a->attrvalue[0]) + 1;
40908821SMichen.Chang@Sun.COM 		(void) strlcpy(ap, a->attrvalue[0], bufsize);
40918821SMichen.Chang@Sun.COM 		ap = buf + ao;
40928821SMichen.Chang@Sun.COM 	};
40938821SMichen.Chang@Sun.COM 
40948821SMichen.Chang@Sun.COM 	return (ao);
40958821SMichen.Chang@Sun.COM }
40968821SMichen.Chang@Sun.COM 
40978821SMichen.Chang@Sun.COM /*
40988821SMichen.Chang@Sun.COM  * Send a modify request to the ldap_cachemgr daemon
40998821SMichen.Chang@Sun.COM  * which will use the admin credential to perform the
41008821SMichen.Chang@Sun.COM  * operation.
41018821SMichen.Chang@Sun.COM  */
41028821SMichen.Chang@Sun.COM 
41038821SMichen.Chang@Sun.COM static int
send_to_cachemgr(const char * dn,ns_ldap_attr_t ** attr,ns_ldap_error_t ** errorp)41048821SMichen.Chang@Sun.COM send_to_cachemgr(
41058821SMichen.Chang@Sun.COM 	const char *dn,
41068821SMichen.Chang@Sun.COM 	ns_ldap_attr_t **attr,
41078821SMichen.Chang@Sun.COM 	ns_ldap_error_t **errorp)
41088821SMichen.Chang@Sun.COM {
41098821SMichen.Chang@Sun.COM 	union {
41108821SMichen.Chang@Sun.COM 		ldap_data_t	s_d;
41118821SMichen.Chang@Sun.COM 		char		s_b[DOORBUFFERSIZE];
41128821SMichen.Chang@Sun.COM 	} space;
41138821SMichen.Chang@Sun.COM 
41148821SMichen.Chang@Sun.COM 	ldap_data_t		*sptr;
41158821SMichen.Chang@Sun.COM 	int			ndata;
41168821SMichen.Chang@Sun.COM 	int			adata;
41178821SMichen.Chang@Sun.COM 	int			len;
41188821SMichen.Chang@Sun.COM 	int			rc;
41198821SMichen.Chang@Sun.COM 	char			errstr[MAXERROR];
41208821SMichen.Chang@Sun.COM 	ldap_admin_mod_result_t	*admin_result;
41218821SMichen.Chang@Sun.COM 
41228821SMichen.Chang@Sun.COM 	*errorp = NULL;
41238821SMichen.Chang@Sun.COM 	(void) memset(space.s_b, 0, DOORBUFFERSIZE);
41248821SMichen.Chang@Sun.COM 	len = attr2list(dn, attr, (char *)&space.s_d.ldap_call.ldap_u.strlist,
41258821SMichen.Chang@Sun.COM 	    sizeof (space) - offsetof(ldap_return_t, ldap_u));
41268821SMichen.Chang@Sun.COM 	if (len <= 0)
41278821SMichen.Chang@Sun.COM 		return (NS_LDAP_INVALID_PARAM);
41288821SMichen.Chang@Sun.COM 
41298821SMichen.Chang@Sun.COM 	adata = sizeof (ldap_call_t) + len;
41308821SMichen.Chang@Sun.COM 	ndata = sizeof (space);
41318821SMichen.Chang@Sun.COM 	space.s_d.ldap_call.ldap_callnumber = ADMINMODIFY;
41328821SMichen.Chang@Sun.COM 	sptr = &space.s_d;
41338821SMichen.Chang@Sun.COM 
41348821SMichen.Chang@Sun.COM 	switch (__ns_ldap_trydoorcall(&sptr, &ndata, &adata)) {
41358821SMichen.Chang@Sun.COM 	case NS_CACHE_SUCCESS:
41368821SMichen.Chang@Sun.COM 		break;
41378821SMichen.Chang@Sun.COM 	case NS_CACHE_NOTFOUND:
41388821SMichen.Chang@Sun.COM 		(void) snprintf(errstr, sizeof (errstr),
41398821SMichen.Chang@Sun.COM 		    gettext("Door call ADMINMODIFY to "
41408821SMichen.Chang@Sun.COM 		    "ldap_cachemgr failed - error: %d"),
41418821SMichen.Chang@Sun.COM 		    space.s_d.ldap_ret.ldap_errno);
41428821SMichen.Chang@Sun.COM 		MKERROR(LOG_WARNING, *errorp, NS_CONFIG_CACHEMGR,
41438821SMichen.Chang@Sun.COM 		    strdup(errstr), NULL);
41448821SMichen.Chang@Sun.COM 		return (NS_LDAP_OP_FAILED);
41458821SMichen.Chang@Sun.COM 		break;
41468821SMichen.Chang@Sun.COM 	default:
41478821SMichen.Chang@Sun.COM 		return (NS_LDAP_OP_FAILED);
41488821SMichen.Chang@Sun.COM 	}
41498821SMichen.Chang@Sun.COM 
41508821SMichen.Chang@Sun.COM 	admin_result = &sptr->ldap_ret.ldap_u.admin_result;
41518821SMichen.Chang@Sun.COM 	if (admin_result->ns_err == NS_LDAP_SUCCESS)
41528821SMichen.Chang@Sun.COM 		rc = NS_LDAP_SUCCESS;
41538821SMichen.Chang@Sun.COM 	else {
41548821SMichen.Chang@Sun.COM 		rc = admin_result->ns_err;
41558821SMichen.Chang@Sun.COM 		if (admin_result->msg_size == 0)
41568821SMichen.Chang@Sun.COM 			*errorp = __s_api_make_error(admin_result->status,
41578821SMichen.Chang@Sun.COM 			    NULL);
41588821SMichen.Chang@Sun.COM 		else
41598821SMichen.Chang@Sun.COM 			*errorp = __s_api_make_error(admin_result->status,
41608821SMichen.Chang@Sun.COM 			    admin_result->msg);
41618821SMichen.Chang@Sun.COM 	}
41628821SMichen.Chang@Sun.COM 
41638821SMichen.Chang@Sun.COM 	/* clean up the door call */
41648821SMichen.Chang@Sun.COM 	if (sptr != &space.s_d) {
41658821SMichen.Chang@Sun.COM 		(void) munmap((char *)sptr, ndata);
41668821SMichen.Chang@Sun.COM 	}
41678821SMichen.Chang@Sun.COM 
41688821SMichen.Chang@Sun.COM 	return (rc);
41698821SMichen.Chang@Sun.COM }
4170