xref: /onnv-gate/usr/src/lib/libsldap/common/ns_confmgr.c (revision 10132:79e70ba10c05)
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
51914Scasper  * Common Development and Distribution License (the "License").
61914Scasper  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*
228821SMichen.Chang@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
230Sstevel@tonic-gate  * Use is subject to license terms.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate /* libsldap - cachemgr side configuration components */
270Sstevel@tonic-gate 
280Sstevel@tonic-gate #include <stdio.h>
290Sstevel@tonic-gate #include <sys/types.h>
300Sstevel@tonic-gate #include <stdlib.h>
310Sstevel@tonic-gate #include <libintl.h>
320Sstevel@tonic-gate #include <string.h>
330Sstevel@tonic-gate #include <ctype.h>
340Sstevel@tonic-gate 
350Sstevel@tonic-gate #include <sys/stat.h>
360Sstevel@tonic-gate #include <fcntl.h>
370Sstevel@tonic-gate #include <unistd.h>
380Sstevel@tonic-gate #include <syslog.h>
390Sstevel@tonic-gate #include <locale.h>
400Sstevel@tonic-gate #include <errno.h>
410Sstevel@tonic-gate #include <sys/time.h>
420Sstevel@tonic-gate 
430Sstevel@tonic-gate #include "ns_sldap.h"
440Sstevel@tonic-gate #include "ns_internal.h"
450Sstevel@tonic-gate #include "ns_cache_door.h"
460Sstevel@tonic-gate 
470Sstevel@tonic-gate #define	ALWAYS		1
480Sstevel@tonic-gate 
490Sstevel@tonic-gate 
500Sstevel@tonic-gate /*
510Sstevel@tonic-gate  * **************************************************************
520Sstevel@tonic-gate  * Configuration File Routines
530Sstevel@tonic-gate  * **************************************************************
540Sstevel@tonic-gate  */
550Sstevel@tonic-gate 
560Sstevel@tonic-gate 
570Sstevel@tonic-gate /* Size of the errstr buffer needs to be MAXERROR */
580Sstevel@tonic-gate static int
read_line(FILE * fp,char * buffer,int buflen,char * errstr)590Sstevel@tonic-gate read_line(FILE *fp, char *buffer, int buflen, char *errstr)
600Sstevel@tonic-gate {
610Sstevel@tonic-gate 	int	linelen;
620Sstevel@tonic-gate 	char	c;
630Sstevel@tonic-gate 
640Sstevel@tonic-gate 	*errstr = '\0';
650Sstevel@tonic-gate 
660Sstevel@tonic-gate 	for (linelen = 0; linelen < buflen; ) {
670Sstevel@tonic-gate 		c = getc(fp);
680Sstevel@tonic-gate 		if (c == EOF)
690Sstevel@tonic-gate 			break;
700Sstevel@tonic-gate 		switch (c) {
710Sstevel@tonic-gate 		case '\n':
726063Smj162486 			if (linelen > 0 && buffer[linelen - 1] == '\\') {
736063Smj162486 				/* Continuation line found */
746063Smj162486 				--linelen;
756063Smj162486 			} else {
766063Smj162486 				/* end of line found */
776063Smj162486 				buffer[linelen] = '\0';
786063Smj162486 				return (linelen);
796063Smj162486 			}
806063Smj162486 			break;
810Sstevel@tonic-gate 		default:
826063Smj162486 			buffer[linelen++] = c;
830Sstevel@tonic-gate 		}
840Sstevel@tonic-gate 	}
850Sstevel@tonic-gate 
860Sstevel@tonic-gate 	if (linelen >= buflen) {
870Sstevel@tonic-gate 		(void) snprintf(errstr, MAXERROR,
886063Smj162486 		    gettext("Buffer overflow, line too long."));
890Sstevel@tonic-gate 		return (-2);
900Sstevel@tonic-gate 	} else if (linelen > 0 && buffer[linelen - 1] == '\\') {
910Sstevel@tonic-gate 		(void) snprintf(errstr, MAXERROR,
926063Smj162486 		    gettext("Unterminated continuation line."));
930Sstevel@tonic-gate 		return (-2);
940Sstevel@tonic-gate 	} else {
950Sstevel@tonic-gate 		/* end of file */
960Sstevel@tonic-gate 		buffer[linelen] = '\0';
970Sstevel@tonic-gate 	}
980Sstevel@tonic-gate 	return (linelen > 0 ? linelen : -1);
990Sstevel@tonic-gate }
1000Sstevel@tonic-gate 
1010Sstevel@tonic-gate 
1020Sstevel@tonic-gate static ns_parse_status
read_file(ns_config_t * ptr,int cred_file,ns_ldap_error_t ** error)1030Sstevel@tonic-gate read_file(ns_config_t *ptr, int cred_file, ns_ldap_error_t **error)
1040Sstevel@tonic-gate {
1050Sstevel@tonic-gate 	ParamIndexType	i = 0;
1060Sstevel@tonic-gate 	char		errstr[MAXERROR];
1070Sstevel@tonic-gate 	char		buffer[BUFSIZE], *name, *value;
1080Sstevel@tonic-gate 	int		emptyfile, lineno;
1090Sstevel@tonic-gate 	FILE		*fp;
1100Sstevel@tonic-gate 	int		ret;
1110Sstevel@tonic-gate 	int		linelen;
1120Sstevel@tonic-gate 	char		*file;
1130Sstevel@tonic-gate 	int		first = 1;
1140Sstevel@tonic-gate 
1150Sstevel@tonic-gate 
1160Sstevel@tonic-gate 	if (cred_file) {
1170Sstevel@tonic-gate 		file = NSCREDFILE;
1180Sstevel@tonic-gate 	} else {
1190Sstevel@tonic-gate 		file = NSCONFIGFILE;
1200Sstevel@tonic-gate 	}
1211914Scasper 	fp = fopen(file, "rF");
1220Sstevel@tonic-gate 	if (fp == NULL) {
1230Sstevel@tonic-gate 		(void) snprintf(errstr, sizeof (errstr),
1246063Smj162486 		    gettext("Unable to open filename '%s' "
1256063Smj162486 		    "for reading (errno=%d)."), file, errno);
1260Sstevel@tonic-gate 		MKERROR(LOG_ERR, *error, NS_CONFIG_FILE, strdup(errstr), NULL);
1270Sstevel@tonic-gate 		return (NS_NOTFOUND);
1280Sstevel@tonic-gate 	}
1290Sstevel@tonic-gate 
1300Sstevel@tonic-gate 	emptyfile = 1;
1310Sstevel@tonic-gate 	lineno = 0;
1320Sstevel@tonic-gate 	for (; ; ) {
1330Sstevel@tonic-gate 		if ((linelen = read_line(fp, buffer, sizeof (buffer),
1346063Smj162486 		    errstr)) < 0)
1350Sstevel@tonic-gate 			/* End of file */
1360Sstevel@tonic-gate 			break;
1370Sstevel@tonic-gate 		lineno++;
1380Sstevel@tonic-gate 		if (linelen == 0)
1390Sstevel@tonic-gate 			continue;
1400Sstevel@tonic-gate 		/* get rid of comment lines */
1410Sstevel@tonic-gate 		if (buffer[0] == '#')
1420Sstevel@tonic-gate 			continue;
1430Sstevel@tonic-gate 		emptyfile = 0;
1440Sstevel@tonic-gate 		name = NULL;
1450Sstevel@tonic-gate 		value = NULL;
1460Sstevel@tonic-gate 		__s_api_split_key_value(buffer, &name, &value);
1470Sstevel@tonic-gate 		if (name == NULL || value == NULL) {
1480Sstevel@tonic-gate 			(void) snprintf(errstr, sizeof (errstr),
1490Sstevel@tonic-gate 			    gettext("Missing Name or Value on line %d."),
1506063Smj162486 			    lineno);
1510Sstevel@tonic-gate 			MKERROR(LOG_ERR, *error, NS_CONFIG_SYNTAX,
1526063Smj162486 			    strdup(errstr), NULL);
1530Sstevel@tonic-gate 			(void) fclose(fp);
1540Sstevel@tonic-gate 			return (NS_PARSE_ERR);
1550Sstevel@tonic-gate 		}
1560Sstevel@tonic-gate 		if (__s_api_get_versiontype(ptr, name, &i) != 0) {
1570Sstevel@tonic-gate 			(void) snprintf(errstr, sizeof (errstr),
1580Sstevel@tonic-gate 			    gettext("Illegal profile type on line %d."),
1596063Smj162486 			    lineno);
1600Sstevel@tonic-gate 			MKERROR(LOG_ERR, *error, NS_CONFIG_SYNTAX,
1616063Smj162486 			    strdup(errstr), NULL);
1620Sstevel@tonic-gate 			(void) fclose(fp);
1630Sstevel@tonic-gate 			return (NS_PARSE_ERR);
1640Sstevel@tonic-gate 		}
1650Sstevel@tonic-gate 		if (!first && i == NS_LDAP_FILE_VERSION_P) {
1660Sstevel@tonic-gate 			(void) snprintf(errstr, sizeof (errstr),
1676063Smj162486 			    gettext("Illegal NS_LDAP_FILE_VERSION "
1686063Smj162486 			    "on line %d."), lineno);
1690Sstevel@tonic-gate 			MKERROR(LOG_ERR, *error, NS_CONFIG_SYNTAX,
1706063Smj162486 			    strdup(errstr), NULL);
1710Sstevel@tonic-gate 			(void) fclose(fp);
1720Sstevel@tonic-gate 			return (NS_PARSE_ERR);
1730Sstevel@tonic-gate 		}
1740Sstevel@tonic-gate 		first = 0;
1750Sstevel@tonic-gate 		switch (__s_api_get_configtype(i)) {
1760Sstevel@tonic-gate 		case SERVERCONFIG:
1770Sstevel@tonic-gate 		case CLIENTCONFIG:
1780Sstevel@tonic-gate 			if (cred_file == 0) {
1790Sstevel@tonic-gate 				ret = __ns_ldap_setParamValue(ptr, i, value,
1806063Smj162486 				    error);
1810Sstevel@tonic-gate 				if (ret != NS_SUCCESS) {
1820Sstevel@tonic-gate 					(void) fclose(fp);
1830Sstevel@tonic-gate 					return (ret);
1840Sstevel@tonic-gate 				}
1850Sstevel@tonic-gate 			} else if (i != NS_LDAP_FILE_VERSION_P) {
1860Sstevel@tonic-gate 				(void) snprintf(errstr, sizeof (errstr),
1876063Smj162486 				    gettext("Illegal entry in '%s' on "
1886063Smj162486 				    "line %d"), file, lineno);
1890Sstevel@tonic-gate 				MKERROR(LOG_ERR, *error, NS_CONFIG_SYNTAX,
1906063Smj162486 				    strdup(errstr), NULL);
1910Sstevel@tonic-gate 				(void) fclose(fp);
1920Sstevel@tonic-gate 				return (NS_PARSE_ERR);
1930Sstevel@tonic-gate 			}
1940Sstevel@tonic-gate 			break;
1950Sstevel@tonic-gate 		case CREDCONFIG:
1960Sstevel@tonic-gate 			if (i == NS_LDAP_FILE_VERSION_P)
1970Sstevel@tonic-gate 				break;
1980Sstevel@tonic-gate 			if (cred_file) {
1990Sstevel@tonic-gate 				ret = __ns_ldap_setParamValue(ptr, i, value,
2006063Smj162486 				    error);
2010Sstevel@tonic-gate 				if (ret != NS_SUCCESS) {
2020Sstevel@tonic-gate 					(void) fclose(fp);
2030Sstevel@tonic-gate 					return (ret);
2040Sstevel@tonic-gate 				}
2050Sstevel@tonic-gate 			} else {
2060Sstevel@tonic-gate 				(void) snprintf(errstr, sizeof (errstr),
2076063Smj162486 				    gettext("Illegal entry in '%s' on "
2086063Smj162486 				    "line %d"), file, lineno);
2090Sstevel@tonic-gate 				MKERROR(LOG_ERR, *error, NS_CONFIG_SYNTAX,
2106063Smj162486 				    strdup(errstr), NULL);
2110Sstevel@tonic-gate 				(void) fclose(fp);
2120Sstevel@tonic-gate 				return (NS_PARSE_ERR);
2130Sstevel@tonic-gate 			}
2140Sstevel@tonic-gate 		}
2150Sstevel@tonic-gate 	}
2160Sstevel@tonic-gate 	(void) fclose(fp);
2170Sstevel@tonic-gate 	if (!cred_file && emptyfile) {
2180Sstevel@tonic-gate 		/* Error in read_line */
2190Sstevel@tonic-gate 		(void) snprintf(errstr, sizeof (errstr),
2206063Smj162486 		    gettext("Empty config file: '%s'"), file);
2210Sstevel@tonic-gate 		MKERROR(LOG_ERR, *error, NS_CONFIG_SYNTAX, strdup(errstr),
2226063Smj162486 		    NULL);
2230Sstevel@tonic-gate 		return (NS_PARSE_ERR);
2240Sstevel@tonic-gate 	}
2250Sstevel@tonic-gate 	if (linelen == -2) {
2260Sstevel@tonic-gate 		/* Error in read_line */
2270Sstevel@tonic-gate 		(void) snprintf(errstr, sizeof (errstr),
2286063Smj162486 		    gettext("Line too long in '%s'"), file);
2290Sstevel@tonic-gate 		MKERROR(LOG_ERR, *error, NS_CONFIG_SYNTAX, strdup(errstr),
2306063Smj162486 		    NULL);
2310Sstevel@tonic-gate 		return (NS_PARSE_ERR);
2320Sstevel@tonic-gate 	}
2330Sstevel@tonic-gate 	return (NS_SUCCESS);
2340Sstevel@tonic-gate }
2350Sstevel@tonic-gate 
2360Sstevel@tonic-gate 
2376842Sth160488 static
2386842Sth160488 ns_ldap_return_code
set_attr(ns_config_t * config_struct,char * attr_name,char * attr_val,ns_ldap_error_t ** errorp)2396842Sth160488 set_attr(ns_config_t *config_struct,
2406842Sth160488 		char *attr_name,
2416842Sth160488 		char *attr_val,
2426842Sth160488 		ns_ldap_error_t **errorp)
2436842Sth160488 {
2446842Sth160488 	ParamIndexType	idx;
2456842Sth160488 	char		errmsg[MAXERROR];
2466842Sth160488 
2476842Sth160488 	if (errorp == NULL) {
2486842Sth160488 		return (NS_LDAP_INVALID_PARAM);
2496842Sth160488 	}
2506842Sth160488 
2516842Sth160488 	*errorp = NULL;
2526842Sth160488 
2536842Sth160488 	/*
2546842Sth160488 	 * This double call is made due to the presence of
2556842Sth160488 	 * two sets of LDAP config. attribute names.
2566842Sth160488 	 * An LDAP configuration can be obtained either from a server
2576842Sth160488 	 * or from SMF. The former sends a DUA with attributes' names
2586842Sth160488 	 * styled like "preferredServerList". But local configurations
2596842Sth160488 	 * will have names inherited from the /var/ldap/ldap* files such as
2606842Sth160488 	 * "NS_LDAP_SERVER_PREF".
2616842Sth160488 	 * So, the standalone bits are able to process both sets of
2626842Sth160488 	 * attributes' names.
2636842Sth160488 	 */
2646842Sth160488 	if (__s_api_get_profiletype(attr_name, &idx) < 0 &&
2656842Sth160488 	    __s_api_get_versiontype(config_struct, attr_name, &idx) < 0) {
2666842Sth160488 		(void) snprintf(errmsg, sizeof (errmsg),
2676842Sth160488 		    gettext("Illegal DUAProfile property: <%s>."), attr_name);
2686842Sth160488 		MKERROR(LOG_ERR, *errorp, NS_LDAP_CONFIG, strdup(errmsg), NULL);
2696842Sth160488 		return (NS_LDAP_CONFIG);
2706842Sth160488 	}
2716842Sth160488 
2726842Sth160488 	return (__ns_ldap_setParamValue(config_struct, idx, attr_val, errorp));
2736842Sth160488 }
2746842Sth160488 
2756842Sth160488 
2766842Sth160488 /*
2776842Sth160488  * This function creates a configuration which will be used
2786842Sth160488  * for all LDAP requests in the Standalone mode.
2796842Sth160488  *
2806842Sth160488  * INPUT:
2816842Sth160488  *     config - a buffer returned by __ns_ldap_getConnectionInfo()'s
2826842Sth160488  *              dua_profile parameter.
2836842Sth160488  *
2846842Sth160488  */
2856842Sth160488 ns_config_t *
__s_api_create_config_door_str(char * config,ns_ldap_error_t ** errorp)2866842Sth160488 __s_api_create_config_door_str(char *config, ns_ldap_error_t **errorp)
2876842Sth160488 {
2886842Sth160488 	char		*attr, *attrName, *attrVal, *rest;
2896842Sth160488 	ns_config_t	*configStruct = NULL;
2906842Sth160488 	char		errmsg[MAXERROR];
2916842Sth160488 
2926842Sth160488 	if (config == NULL || errorp == NULL)
2936842Sth160488 		return (NULL);
2946842Sth160488 
2956842Sth160488 	if ((configStruct = __s_api_create_config()) == NULL) {
2966842Sth160488 		return (NULL);
2976842Sth160488 	}
2986842Sth160488 
2996842Sth160488 	*errorp = NULL;
3006842Sth160488 
3016842Sth160488 	attr = strtok_r(config, DOORLINESEP, &rest);
3026842Sth160488 	if (!attr) {
3036842Sth160488 		__s_api_destroy_config(configStruct);
3046842Sth160488 		(void) snprintf(errmsg, sizeof (errmsg),
3056842Sth160488 		    gettext("DUAProfile received from the server"
3066842Sth160488 		    " has bad format"));
3076842Sth160488 		MKERROR(LOG_ERR, *errorp, NS_LDAP_CONFIG, strdup(errmsg), NULL);
3086842Sth160488 		return (NULL);
3096842Sth160488 	}
3106842Sth160488 
3116842Sth160488 	do {
3126842Sth160488 		__s_api_split_key_value(attr, &attrName, &attrVal);
3136842Sth160488 
3146842Sth160488 		if (attrName == NULL || attrVal == NULL) {
3156842Sth160488 			__s_api_destroy_config(configStruct);
3166842Sth160488 			(void) snprintf(errmsg, sizeof (errmsg),
3176842Sth160488 			    gettext("Attribute %s is not valid"), attr);
3186842Sth160488 			MKERROR(LOG_ERR, *errorp, NS_LDAP_CONFIG,
3196842Sth160488 			    strdup(errmsg), NULL);
3206842Sth160488 			return (NULL);
3216842Sth160488 		}
3226842Sth160488 
3236842Sth160488 		/* Get the version of the profile. */
3246842Sth160488 		if (strcasecmp(attrName, "objectclass") == 0) {
3256842Sth160488 			if (strcasecmp(attrVal, _PROFILE2_OBJECTCLASS) == 0) {
3266842Sth160488 				if (__ns_ldap_setParamValue(configStruct,
3276842Sth160488 				    NS_LDAP_FILE_VERSION_P,
3286842Sth160488 				    NS_LDAP_VERSION_2,
3296842Sth160488 				    errorp) != NS_LDAP_SUCCESS) {
3306842Sth160488 					__s_api_destroy_config(configStruct);
3316842Sth160488 					return (NULL);
3326842Sth160488 				}
3338821SMichen.Chang@Sun.COM 			} else if (strcasecmp(attrVal,
3348821SMichen.Chang@Sun.COM 			    _PROFILE1_OBJECTCLASS) == 0) {
3358821SMichen.Chang@Sun.COM 				if (__ns_ldap_setParamValue(configStruct,
3368821SMichen.Chang@Sun.COM 				    NS_LDAP_FILE_VERSION_P,
3378821SMichen.Chang@Sun.COM 				    NS_LDAP_VERSION_1,
3388821SMichen.Chang@Sun.COM 				    errorp) != NS_LDAP_SUCCESS) {
3398821SMichen.Chang@Sun.COM 					__s_api_destroy_config(configStruct);
3408821SMichen.Chang@Sun.COM 					return (NULL);
3418821SMichen.Chang@Sun.COM 				}
3426842Sth160488 			}
3436842Sth160488 			continue;
3446842Sth160488 		}
3456842Sth160488 
3466842Sth160488 		if (set_attr(configStruct, attrName, attrVal, errorp) !=
3476842Sth160488 		    NS_LDAP_SUCCESS) {
3486842Sth160488 			__s_api_destroy_config(configStruct);
3496842Sth160488 			return (NULL);
3506842Sth160488 		}
3516842Sth160488 	} while (attr = strtok_r(NULL, DOORLINESEP, &rest));
3526842Sth160488 
3536842Sth160488 	if (__s_api_crosscheck(configStruct, errmsg, B_FALSE) != NS_SUCCESS) {
3546842Sth160488 		MKERROR(LOG_ERR, *errorp, NS_LDAP_CONFIG, strdup(errmsg), NULL);
3556842Sth160488 		__s_api_destroy_config(configStruct);
3566842Sth160488 		return (NULL);
3576842Sth160488 	}
3586842Sth160488 
3596842Sth160488 	return (configStruct);
3606842Sth160488 }
3616842Sth160488 
3626842Sth160488 
3630Sstevel@tonic-gate /*
3640Sstevel@tonic-gate  * Cache Manager side of configuration file loading
3650Sstevel@tonic-gate  */
3660Sstevel@tonic-gate 
3670Sstevel@tonic-gate ns_ldap_error_t *
__ns_ldap_LoadConfiguration()3680Sstevel@tonic-gate __ns_ldap_LoadConfiguration()
3690Sstevel@tonic-gate {
3700Sstevel@tonic-gate 	ns_ldap_error_t	*error = NULL;
3710Sstevel@tonic-gate 	ns_config_t	*ptr = NULL;
3720Sstevel@tonic-gate 	char		errstr[MAXERROR];
3730Sstevel@tonic-gate 	ns_parse_status	ret;
3740Sstevel@tonic-gate 
3750Sstevel@tonic-gate 
3760Sstevel@tonic-gate 	ptr = __s_api_create_config();
3770Sstevel@tonic-gate 	if (ptr == NULL) {
3780Sstevel@tonic-gate 		(void) snprintf(errstr, sizeof (errstr),
3796063Smj162486 		    gettext("__ns_ldap_LoadConfiguration: Out of memory."));
3800Sstevel@tonic-gate 		MKERROR(LOG_ERR, error, NS_CONFIG_NOTLOADED,
3816063Smj162486 		    strdup(errstr), NULL);
3820Sstevel@tonic-gate 		return (error);
3830Sstevel@tonic-gate 	}
3840Sstevel@tonic-gate 
3850Sstevel@tonic-gate 	/* Load in Configuration file */
3860Sstevel@tonic-gate 	ret = read_file(ptr, 0, &error);
3870Sstevel@tonic-gate 	if (ret != NS_SUCCESS) {
3880Sstevel@tonic-gate 		__s_api_destroy_config(ptr);
3890Sstevel@tonic-gate 		return (error);
3900Sstevel@tonic-gate 	}
3910Sstevel@tonic-gate 
3920Sstevel@tonic-gate 	/* Load in Credential file */
3930Sstevel@tonic-gate 	ret = read_file(ptr, 1, &error);
3940Sstevel@tonic-gate 	if (ret != NS_SUCCESS) {
3950Sstevel@tonic-gate 		__s_api_destroy_config(ptr);
3960Sstevel@tonic-gate 		return (error);
3970Sstevel@tonic-gate 	}
3980Sstevel@tonic-gate 
3990Sstevel@tonic-gate 	if (__s_api_crosscheck(ptr, errstr, B_TRUE) != NS_SUCCESS) {
4000Sstevel@tonic-gate 		__s_api_destroy_config(ptr);
4010Sstevel@tonic-gate 		MKERROR(LOG_ERR, error, NS_CONFIG_SYNTAX, strdup(errstr), NULL);
4020Sstevel@tonic-gate 		return (error);
4030Sstevel@tonic-gate 	}
4040Sstevel@tonic-gate 
4050Sstevel@tonic-gate 	__s_api_init_config(ptr);
4060Sstevel@tonic-gate 	return (NULL);
4070Sstevel@tonic-gate }
4080Sstevel@tonic-gate 
4090Sstevel@tonic-gate 
410*10132SMilan.Jurik@Sun.COM int
__print2buf(LineBuf * line,const char * toprint,char * sep)411*10132SMilan.Jurik@Sun.COM __print2buf(LineBuf *line, const char *toprint, char *sep)
4120Sstevel@tonic-gate {
4130Sstevel@tonic-gate 	int	newsz = 0;
4140Sstevel@tonic-gate 	int	newmax = 0;
4150Sstevel@tonic-gate 	char	*str;
4160Sstevel@tonic-gate 
4170Sstevel@tonic-gate 	if (line == NULL)
4180Sstevel@tonic-gate 		return (-1);
4190Sstevel@tonic-gate 
4200Sstevel@tonic-gate 	newsz = strlen(toprint) + line->len + 1;
421*10132SMilan.Jurik@Sun.COM 	if (sep != NULL) {
422*10132SMilan.Jurik@Sun.COM 		newsz += strlen(sep);
4230Sstevel@tonic-gate 	}
4240Sstevel@tonic-gate 	if (line->alloc == 0 || newsz > line->alloc) {
4250Sstevel@tonic-gate 		/* Round up to next buffer and add 1 */
4260Sstevel@tonic-gate 		newmax = (((newsz+(BUFSIZ-1))/BUFSIZ)+1) * BUFSIZ;
4270Sstevel@tonic-gate 		if (line->alloc == 0)
4280Sstevel@tonic-gate 			line->str = (char *)calloc(newmax, 1);
4290Sstevel@tonic-gate 		else {
4300Sstevel@tonic-gate 			/*
4310Sstevel@tonic-gate 			 * if realloc() returns NULL,
4320Sstevel@tonic-gate 			 * the original buffer is untouched.
4330Sstevel@tonic-gate 			 * It needs to be freed.
4340Sstevel@tonic-gate 			 */
4350Sstevel@tonic-gate 			str = (char *)realloc(line->str, newmax);
4360Sstevel@tonic-gate 			if (str == NULL) {
4370Sstevel@tonic-gate 				free(line->str);
4380Sstevel@tonic-gate 				line->str = NULL;
4390Sstevel@tonic-gate 			}
4400Sstevel@tonic-gate 			else
4410Sstevel@tonic-gate 				line->str = str;
4420Sstevel@tonic-gate 		}
4430Sstevel@tonic-gate 		line->alloc = newmax;
4440Sstevel@tonic-gate 		if (line->str == NULL) {
4450Sstevel@tonic-gate 			line->alloc = 0;
4460Sstevel@tonic-gate 			line->len = 0;
4470Sstevel@tonic-gate 			return (-1);
4480Sstevel@tonic-gate 		}
4490Sstevel@tonic-gate 	}
4500Sstevel@tonic-gate 	/* now add new 'toprint' data to buffer */
4510Sstevel@tonic-gate 	(void) strlcat(line->str, toprint, line->alloc);
452*10132SMilan.Jurik@Sun.COM 	if (sep != NULL) {
453*10132SMilan.Jurik@Sun.COM 		(void) strlcat(line->str, sep, line->alloc);
4540Sstevel@tonic-gate 	}
4550Sstevel@tonic-gate 	line->len = newsz;
4560Sstevel@tonic-gate 	return (0);
4570Sstevel@tonic-gate }
4580Sstevel@tonic-gate 
4590Sstevel@tonic-gate 
4600Sstevel@tonic-gate /*
4610Sstevel@tonic-gate  * __ns_ldap_LoadDoorInfo is a routine used by the ldapcachemgr
4620Sstevel@tonic-gate  * to create a configuration buffer to transmit back to a client
4630Sstevel@tonic-gate  * domainname is transmitted to ldapcachemgr and ldapcachemgr uses
4640Sstevel@tonic-gate  * it to select a configuration to transmit back.  Otherwise it
4650Sstevel@tonic-gate  * is essentially unused in sldap.
4669576SJulian.Pullen@Sun.COM  * If cred_only is not 0, then only the credentials for shadow
4679576SJulian.Pullen@Sun.COM  * update are taken care of.
4680Sstevel@tonic-gate  */
4690Sstevel@tonic-gate 
4700Sstevel@tonic-gate ns_ldap_error_t *
__ns_ldap_LoadDoorInfo(LineBuf * configinfo,char * domainname,ns_config_t * new,int cred_only)4719576SJulian.Pullen@Sun.COM __ns_ldap_LoadDoorInfo(LineBuf *configinfo, char *domainname,
4729576SJulian.Pullen@Sun.COM 			ns_config_t *new, int cred_only)
4730Sstevel@tonic-gate {
4740Sstevel@tonic-gate 	ns_config_t	*ptr;
4750Sstevel@tonic-gate 	char		errstr[MAXERROR];
4760Sstevel@tonic-gate 	ns_ldap_error_t	*errorp;
4770Sstevel@tonic-gate 	char		*str;
4780Sstevel@tonic-gate 	ParamIndexType	i = 0;
4796842Sth160488 	int		len;
4806842Sth160488 	ldap_config_out_t *cout;
4810Sstevel@tonic-gate 
4826842Sth160488 	/*
4836842Sth160488 	 * If new is NULL, it outputs the flatten data of current default
4846842Sth160488 	 * config, if it's non-NULL, it outputs the flatten data of a temporary
4856842Sth160488 	 * config. It's used to compare the new config data with the current
4866842Sth160488 	 * default config data.
4876842Sth160488 	 */
4886842Sth160488 	if (new == NULL)
4896842Sth160488 		ptr = __s_api_get_default_config();
4906842Sth160488 	else
4916842Sth160488 		ptr = new;
4920Sstevel@tonic-gate 	if (ptr == NULL) {
4930Sstevel@tonic-gate 		(void) snprintf(errstr, sizeof (errstr),
4940Sstevel@tonic-gate 		    gettext("No configuration information available for %s."),
4950Sstevel@tonic-gate 		    domainname == NULL ? "<no domain specified>" : domainname);
4960Sstevel@tonic-gate 		MKERROR(LOG_WARNING, errorp, NS_CONFIG_NOTLOADED,
4976063Smj162486 		    strdup(errstr), NULL);
4980Sstevel@tonic-gate 		return (errorp);
4990Sstevel@tonic-gate 	}
5000Sstevel@tonic-gate 	(void) memset((char *)configinfo, 0, sizeof (LineBuf));
5010Sstevel@tonic-gate 	for (i = 0; i <= NS_LDAP_MAX_PIT_P; i++) {
5029576SJulian.Pullen@Sun.COM 		if (cred_only) {
5039576SJulian.Pullen@Sun.COM 			/* only exposed credential for shadow update */
5049576SJulian.Pullen@Sun.COM 			if (i != NS_LDAP_ADMIN_BINDDN_P &&
5059576SJulian.Pullen@Sun.COM 			    i != NS_LDAP_ADMIN_BINDPASSWD_P)
5069576SJulian.Pullen@Sun.COM 				continue;
5079576SJulian.Pullen@Sun.COM 		} else {
5089576SJulian.Pullen@Sun.COM 			/* credential for shadow update is not to be exposed */
5099576SJulian.Pullen@Sun.COM 			if (i == NS_LDAP_ADMIN_BINDDN_P ||
5109576SJulian.Pullen@Sun.COM 			    i == NS_LDAP_ADMIN_BINDPASSWD_P)
5119576SJulian.Pullen@Sun.COM 				continue;
5129576SJulian.Pullen@Sun.COM 		}
513*10132SMilan.Jurik@Sun.COM 		str = __s_api_strValue(ptr, i, NS_DOOR_FMT);
5140Sstevel@tonic-gate 		if (str == NULL)
5150Sstevel@tonic-gate 			continue;
516*10132SMilan.Jurik@Sun.COM 		if (__print2buf(configinfo, str, DOORLINESEP)) {
5170Sstevel@tonic-gate 			(void) snprintf(errstr, sizeof (errstr),
518*10132SMilan.Jurik@Sun.COM 			    gettext("__print2buf: Out of memory."));
5190Sstevel@tonic-gate 			MKERROR(LOG_WARNING, errorp, NS_CONFIG_NOTLOADED,
5206063Smj162486 			    strdup(errstr), NULL);
5210Sstevel@tonic-gate 			__s_api_release_config(ptr);
522*10132SMilan.Jurik@Sun.COM 			free(str);
5230Sstevel@tonic-gate 			return (errorp);
5240Sstevel@tonic-gate 		}
525*10132SMilan.Jurik@Sun.COM 		free(str);
5260Sstevel@tonic-gate 	}
5276842Sth160488 	if (new == NULL)
5286842Sth160488 		__s_api_release_config(ptr);
5296842Sth160488 
5306842Sth160488 	/*
5316842Sth160488 	 * The new interface of the configuration between ldap_cachemgr
5326842Sth160488 	 * & libsldap contains a header structure ldap_config_out_t.
5336842Sth160488 	 * The flatten configuration data configinfo->str is cloned
5346842Sth160488 	 * to cout->config_str, configinfo->len is saved in
5356842Sth160488 	 * cout->data_size and cout->cookie is set later after this function
5366842Sth160488 	 * is returned in ldap_cachemgr.
5376842Sth160488 	 * configinfo->str & configinfo->len are reused to save info of
5386842Sth160488 	 * header + data.
5396842Sth160488 	 * The format:
5406842Sth160488 	 * [cookie|data_size|config_str .............]
5416842Sth160488 	 */
5426842Sth160488 
5436842Sth160488 	if (configinfo->str) {
5446842Sth160488 		len = sizeof (ldap_config_out_t) - sizeof (int) +
5456842Sth160488 		    configinfo->len;
5466842Sth160488 		if ((cout = calloc(1, len)) == NULL) {
5476842Sth160488 			free(configinfo->str);
5486842Sth160488 			configinfo->str = NULL;
5496842Sth160488 			configinfo->len = 0;
5506842Sth160488 			(void) snprintf(errstr, sizeof (errstr),
5516842Sth160488 			    gettext("calloc: Out of memory."));
5526842Sth160488 			MKERROR(LOG_WARNING, errorp, NS_CONFIG_NOTLOADED,
5536842Sth160488 			    strdup(errstr), NULL);
5546842Sth160488 			return (errorp);
5556842Sth160488 		}
5566842Sth160488 		/*
5576842Sth160488 		 * cout->cookie is set by the caller,
5586842Sth160488 		 * which is in ldap_cachemgr.
5596842Sth160488 		 */
5606842Sth160488 		cout->data_size = configinfo->len;
5616842Sth160488 		(void) memcpy(cout->config_str, configinfo->str,
5626842Sth160488 		    configinfo->len);
5636842Sth160488 		free(configinfo->str);
5646842Sth160488 		configinfo->str = (char *)cout;
5656842Sth160488 		configinfo->len = len;
5666842Sth160488 	}
5670Sstevel@tonic-gate 	return (NULL);
5680Sstevel@tonic-gate }
5690Sstevel@tonic-gate 
5700Sstevel@tonic-gate 
5710Sstevel@tonic-gate ns_ldap_error_t *
__ns_ldap_DumpLdif(char * filename)5720Sstevel@tonic-gate __ns_ldap_DumpLdif(char *filename)
5730Sstevel@tonic-gate {
5740Sstevel@tonic-gate 	ns_config_t	*ptr;
5750Sstevel@tonic-gate 	char		errstr[MAXERROR];
5760Sstevel@tonic-gate 	ns_ldap_error_t	*errorp;
5770Sstevel@tonic-gate 	char		*str;
5780Sstevel@tonic-gate 	FILE		*fp;
5790Sstevel@tonic-gate 	ParamIndexType	i = 0;
5800Sstevel@tonic-gate 	char		*profile, *container, *base;
5810Sstevel@tonic-gate 
5820Sstevel@tonic-gate 	ptr = __s_api_get_default_config();
5830Sstevel@tonic-gate 	if (ptr == NULL) {
5840Sstevel@tonic-gate 		(void) snprintf(errstr, sizeof (errstr),
5850Sstevel@tonic-gate 		    gettext("No configuration information available."));
5860Sstevel@tonic-gate 		MKERROR(LOG_ERR, errorp, NS_CONFIG_NOTLOADED, strdup(errstr),
5876063Smj162486 		    NULL);
5880Sstevel@tonic-gate 		return (errorp);
5890Sstevel@tonic-gate 	}
5900Sstevel@tonic-gate 
5910Sstevel@tonic-gate 	if (filename == NULL) {
5920Sstevel@tonic-gate 		fp = stdout;
5930Sstevel@tonic-gate 	} else {
5941914Scasper 		fp = fopen(filename, "wF");
5950Sstevel@tonic-gate 		if (fp == NULL) {
5960Sstevel@tonic-gate 			(void) snprintf(errstr, sizeof (errstr),
5976063Smj162486 			    gettext("Unable to open filename %s for ldif "
5986063Smj162486 			    "dump (errno=%d)."), filename, errno);
5990Sstevel@tonic-gate 			MKERROR(LOG_WARNING, errorp, NS_CONFIG_FILE,
6006063Smj162486 			    strdup(errstr), NULL);
6010Sstevel@tonic-gate 			__s_api_release_config(ptr);
6020Sstevel@tonic-gate 			return (errorp);
6030Sstevel@tonic-gate 		}
6040Sstevel@tonic-gate 		(void) fchmod(fileno(fp), 0444);
6050Sstevel@tonic-gate 	}
6060Sstevel@tonic-gate 
6070Sstevel@tonic-gate 	if (ptr->paramList[NS_LDAP_SEARCH_BASEDN_P].ns_ptype != CHARPTR ||
6080Sstevel@tonic-gate 	    ptr->paramList[NS_LDAP_PROFILE_P].ns_ptype != CHARPTR) {
6090Sstevel@tonic-gate 		(void) snprintf(errstr, sizeof (errstr),
6106063Smj162486 		    gettext("Required BaseDN and/or Profile name "
6116063Smj162486 		    "ldif fields not present"));
6120Sstevel@tonic-gate 		MKERROR(LOG_WARNING, errorp, NS_CONFIG_FILE, strdup(errstr),
6136063Smj162486 		    NULL);
6140Sstevel@tonic-gate 		__s_api_release_config(ptr);
6150Sstevel@tonic-gate 		return (errorp);
6160Sstevel@tonic-gate 	}
6170Sstevel@tonic-gate 
6180Sstevel@tonic-gate 	profile = ptr->paramList[NS_LDAP_PROFILE_P].ns_pc;
6190Sstevel@tonic-gate 	base = ptr->paramList[NS_LDAP_SEARCH_BASEDN_P].ns_pc;
6200Sstevel@tonic-gate 	container = _PROFILE_CONTAINER;
6210Sstevel@tonic-gate 
6220Sstevel@tonic-gate 	/*
6230Sstevel@tonic-gate 	 * Construct DN, but since this is the profile, there is no need
6240Sstevel@tonic-gate 	 * to worry about mapping.  The profile itself can not be mapped
6250Sstevel@tonic-gate 	 */
6260Sstevel@tonic-gate 	(void) fprintf(fp, "dn: cn=%s,ou=%s,%s\n", profile, container, base);
6270Sstevel@tonic-gate 
6280Sstevel@tonic-gate 	/* dump objectclass names */
6290Sstevel@tonic-gate 	if (ptr->version == NS_LDAP_V1) {
6306063Smj162486 		(void) fprintf(fp, "ObjectClass: top\nObjectClass: %s\n",
6316063Smj162486 		    _PROFILE1_OBJECTCLASS);
6320Sstevel@tonic-gate 	} else {
6336063Smj162486 		(void) fprintf(fp, "ObjectClass: top\nObjectClass: %s\n",
6346063Smj162486 		    _PROFILE2_OBJECTCLASS);
6350Sstevel@tonic-gate 	}
6360Sstevel@tonic-gate 
6370Sstevel@tonic-gate 	/* For each parameter - construct value */
6380Sstevel@tonic-gate 	for (i = 0; i <= NS_LDAP_MAX_PIT_P; i++) {
639*10132SMilan.Jurik@Sun.COM 		str = __s_api_strValue(ptr, i, NS_LDIF_FMT);
6400Sstevel@tonic-gate 		if (str == NULL)
6410Sstevel@tonic-gate 			continue;
6420Sstevel@tonic-gate 		/*
6438821SMichen.Chang@Sun.COM 		 * don't dump binddn, bind password, admin binddn, admin
6448821SMichen.Chang@Sun.COM 		 * bind password, enableShadowUpdate flag, or cert path
6458821SMichen.Chang@Sun.COM 		 * as they are not part of version 2 profiles
6460Sstevel@tonic-gate 		 */
6478821SMichen.Chang@Sun.COM 		if ((i != NS_LDAP_BINDDN_P) &&
6488821SMichen.Chang@Sun.COM 		    (i != NS_LDAP_BINDPASSWD_P) &&
6498821SMichen.Chang@Sun.COM 		    (i != NS_LDAP_ADMIN_BINDDN_P) &&
6508821SMichen.Chang@Sun.COM 		    (i != NS_LDAP_ADMIN_BINDPASSWD_P) &&
6518821SMichen.Chang@Sun.COM 		    (i != NS_LDAP_ENABLE_SHADOW_UPDATE_P) &&
6526063Smj162486 		    (i != NS_LDAP_HOST_CERTPATH_P))
6530Sstevel@tonic-gate 			(void) fprintf(fp, "%s\n", str);
654*10132SMilan.Jurik@Sun.COM 		free(str);
6550Sstevel@tonic-gate 	}
6560Sstevel@tonic-gate 
6570Sstevel@tonic-gate 	if (filename != NULL)
6580Sstevel@tonic-gate 		(void) fclose(fp);
6590Sstevel@tonic-gate 
6600Sstevel@tonic-gate 	__s_api_release_config(ptr);
6610Sstevel@tonic-gate 	return (NULL);
6620Sstevel@tonic-gate }
6630Sstevel@tonic-gate 
6640Sstevel@tonic-gate /*
6650Sstevel@tonic-gate  * This routine can process the configuration  and/or
6660Sstevel@tonic-gate  * the credential files at the same time.
6670Sstevel@tonic-gate  * files is char *[3] = { "config", "cred", NULL };
6680Sstevel@tonic-gate  */
6690Sstevel@tonic-gate 
6700Sstevel@tonic-gate static
6710Sstevel@tonic-gate ns_ldap_error_t *
__ns_ldap_DumpConfigFiles(char ** files)6720Sstevel@tonic-gate __ns_ldap_DumpConfigFiles(char **files)
6730Sstevel@tonic-gate {
6740Sstevel@tonic-gate 	char		*filename;
6750Sstevel@tonic-gate 	int		fi;
6760Sstevel@tonic-gate 	int		docred;
6770Sstevel@tonic-gate 	ns_config_t	*ptr;
6780Sstevel@tonic-gate 	char		*str;
6790Sstevel@tonic-gate 	char		errstr[MAXERROR];
6800Sstevel@tonic-gate 	ParamIndexType	i = 0;
6810Sstevel@tonic-gate 	FILE		*fp;
6820Sstevel@tonic-gate 	int		rc;
6836063Smj162486 	ns_ldap_error_t	*errorp = NULL;
6840Sstevel@tonic-gate 	struct stat	buf;
6850Sstevel@tonic-gate 	int		cfgtype;
6866063Smj162486 	boolean_t	file_export_error = B_FALSE;
6870Sstevel@tonic-gate 
6880Sstevel@tonic-gate 	ptr = __s_api_get_default_config();
6890Sstevel@tonic-gate 	if (ptr == NULL) {
6900Sstevel@tonic-gate 		(void) snprintf(errstr, sizeof (errstr),
6916063Smj162486 		    gettext("No configuration information available."));
6920Sstevel@tonic-gate 		MKERROR(LOG_ERR, errorp, NS_CONFIG_NOTLOADED, strdup(errstr),
6936063Smj162486 		    NULL);
6940Sstevel@tonic-gate 		return (errorp);
6950Sstevel@tonic-gate 	}
6960Sstevel@tonic-gate 
6970Sstevel@tonic-gate 	for (fi = 0; fi < 2; fi++) {
6980Sstevel@tonic-gate 		docred = 0;
6990Sstevel@tonic-gate 		filename = files[fi];
7000Sstevel@tonic-gate 		if (filename == NULL)
7010Sstevel@tonic-gate 			continue;
7020Sstevel@tonic-gate 		if (fi == 1)
7030Sstevel@tonic-gate 			docred++;
7040Sstevel@tonic-gate 		rc = stat(filename, &buf);
7051914Scasper 		fp = fopen(filename, "wF");
7060Sstevel@tonic-gate 		if (fp == NULL) {
7070Sstevel@tonic-gate 			(void) snprintf(errstr, sizeof (errstr),
7086063Smj162486 			    gettext("Unable to open filename %s"
7096063Smj162486 			    " for configuration dump (%s)."),
7106063Smj162486 			    filename, strerror(errno));
7116063Smj162486 			MKERROR(LOG_ERR, errorp, NS_CONFIG_FILE,
7126063Smj162486 			    strdup(errstr), NULL);
7130Sstevel@tonic-gate 			__s_api_release_config(ptr);
7140Sstevel@tonic-gate 			return (errorp);
7150Sstevel@tonic-gate 		}
7166063Smj162486 		if (rc == 0) {
7176063Smj162486 			if (fchmod(fileno(fp), buf.st_mode) != 0) {
7186063Smj162486 				(void) snprintf(errstr, sizeof (errstr),
7196063Smj162486 				    gettext("Unable to set permissions for file"
7206063Smj162486 				    " %s for configuration dump (%s)."),
7216063Smj162486 				    filename, strerror(errno));
7226063Smj162486 				(void) fclose(fp);
7236063Smj162486 				file_export_error = B_TRUE;
7246063Smj162486 				break;
7256063Smj162486 			}
7266063Smj162486 		} else {
7276063Smj162486 			if (fchmod(fileno(fp), 0400) != 0) {
7286063Smj162486 				(void) snprintf(errstr, sizeof (errstr),
7296063Smj162486 				    gettext("Unable to set permissions for file"
7306063Smj162486 				    " %s for configuration dump (%s)."),
7316063Smj162486 				    filename, strerror(errno));
7326063Smj162486 				(void) fclose(fp);
7336063Smj162486 				file_export_error = B_TRUE;
7346063Smj162486 				break;
7356063Smj162486 			}
7366063Smj162486 		}
7376063Smj162486 		if (fprintf(fp, "#\n# %s\n#\n", DONOTEDIT) < 0) {
7386063Smj162486 			(void) snprintf(errstr, sizeof (errstr), gettext(
7396063Smj162486 			    "Writing to file %s for configuration dump failed "
7406063Smj162486 			    "(%s)."), filename, strerror(errno));
7416063Smj162486 			file_export_error = B_TRUE;
7426063Smj162486 		}
7430Sstevel@tonic-gate 
7440Sstevel@tonic-gate 		/* assume VERSION is set and it outputs first */
7450Sstevel@tonic-gate 
7460Sstevel@tonic-gate 		/* For each parameter - construct value */
7476063Smj162486 		for (i = 0; !file_export_error && (i <= NS_LDAP_MAX_PIT_P);
7486063Smj162486 		    i++) {
7490Sstevel@tonic-gate 			cfgtype = __s_api_get_configtype(i);
7500Sstevel@tonic-gate 			if ((docred == 0 && cfgtype == CREDCONFIG) ||
7516063Smj162486 			    (docred == 1 && cfgtype != CREDCONFIG))
7520Sstevel@tonic-gate 				continue;
7530Sstevel@tonic-gate 
754*10132SMilan.Jurik@Sun.COM 			str = __s_api_strValue(ptr, i, NS_FILE_FMT);
7550Sstevel@tonic-gate 			if (str == NULL)
7560Sstevel@tonic-gate 				continue;
7576063Smj162486 			if (fprintf(fp, "%s\n", str) < 0) {
7586063Smj162486 				(void) snprintf(errstr, sizeof (errstr),
7596063Smj162486 				    gettext("Writing to file %s for"
7606063Smj162486 				    "configuration dump failed (%s)."),
7616063Smj162486 				    filename, strerror(errno));
7626063Smj162486 				file_export_error = B_TRUE;
7636063Smj162486 			}
7646063Smj162486 
765*10132SMilan.Jurik@Sun.COM 			free(str);
7660Sstevel@tonic-gate 		}
7676063Smj162486 		if (fclose(fp) != 0) {
7686063Smj162486 			/* Break if error already hit */
7696063Smj162486 			if (file_export_error)
7706063Smj162486 				break;
7716063Smj162486 
7726063Smj162486 			(void) snprintf(errstr, sizeof (errstr), gettext(
7736063Smj162486 			    "Writing to file %s for configuration dump failed "
7746063Smj162486 			    "during file close (%s)."), filename,
7756063Smj162486 			    strerror(errno));
7766063Smj162486 			file_export_error = B_TRUE;
7776063Smj162486 			break;
7786063Smj162486 		}
7796063Smj162486 
7806063Smj162486 	}
7816063Smj162486 
7826063Smj162486 	if (file_export_error) {
7836063Smj162486 		MKERROR(LOG_ERR, errorp, NS_CONFIG_FILE,
7846063Smj162486 		    strdup(errstr), NULL);
7856063Smj162486 		(void) unlink(filename);
7860Sstevel@tonic-gate 	}
7870Sstevel@tonic-gate 
7880Sstevel@tonic-gate 	__s_api_release_config(ptr);
7896063Smj162486 	return (errorp);
7900Sstevel@tonic-gate }
7910Sstevel@tonic-gate 
7920Sstevel@tonic-gate ns_ldap_error_t *
__ns_ldap_DumpConfiguration(char * file)7930Sstevel@tonic-gate __ns_ldap_DumpConfiguration(char *file)
7940Sstevel@tonic-gate {
7950Sstevel@tonic-gate 	ns_ldap_error_t	*ret;
7960Sstevel@tonic-gate 	char		*files[3];
7970Sstevel@tonic-gate 
7980Sstevel@tonic-gate 	files[0] = NULL;
7990Sstevel@tonic-gate 	files[1] = NULL;
8000Sstevel@tonic-gate 	files[2] = NULL;
8010Sstevel@tonic-gate 	if (strcmp(file, NSCONFIGFILE) == 0) {
8020Sstevel@tonic-gate 		files[0] = file;
8030Sstevel@tonic-gate 	} else if (strcmp(file, NSCONFIGREFRESH) == 0) {
8040Sstevel@tonic-gate 		files[0] = file;
8050Sstevel@tonic-gate 	} else if (strcmp(file, NSCREDFILE) == 0) {
8060Sstevel@tonic-gate 		files[1] = file;
8070Sstevel@tonic-gate 	} else if (strcmp(file, NSCREDREFRESH) == 0) {
8080Sstevel@tonic-gate 		files[1] = file;
8090Sstevel@tonic-gate 	}
8100Sstevel@tonic-gate 	ret = __ns_ldap_DumpConfigFiles(files);
8110Sstevel@tonic-gate 	return (ret);
8120Sstevel@tonic-gate }
8130Sstevel@tonic-gate 
8140Sstevel@tonic-gate /*
8150Sstevel@tonic-gate  * **************************************************************
8160Sstevel@tonic-gate  * Misc Routines
8170Sstevel@tonic-gate  * **************************************************************
8180Sstevel@tonic-gate  */
8190Sstevel@tonic-gate 
8200Sstevel@tonic-gate ns_config_t *
__ns_ldap_make_config(ns_ldap_result_t * result)8210Sstevel@tonic-gate __ns_ldap_make_config(ns_ldap_result_t *result)
8220Sstevel@tonic-gate {
8232095Smj162486 	int		l, m;
824*10132SMilan.Jurik@Sun.COM 	char		val[BUFSIZE];
8250Sstevel@tonic-gate 	char    	*attrname;
8260Sstevel@tonic-gate 	ns_ldap_entry_t	*entry;
8270Sstevel@tonic-gate 	ns_ldap_attr_t	*attr;
8280Sstevel@tonic-gate 	char		**attrval;
8290Sstevel@tonic-gate 	ParamIndexType	index;
8300Sstevel@tonic-gate 	ns_config_t	*ptr;
8310Sstevel@tonic-gate 	ns_ldap_error_t	*error = NULL;
8320Sstevel@tonic-gate 	int		prof_ver;
8330Sstevel@tonic-gate 	ns_config_t	*curr_ptr = NULL;
8342095Smj162486 	char		errstr[MAXERROR];
8352095Smj162486 	ns_ldap_error_t	*errorp;
836*10132SMilan.Jurik@Sun.COM 	LineBuf		buffer;
837*10132SMilan.Jurik@Sun.COM 	char		*sepstr;
8380Sstevel@tonic-gate 
8390Sstevel@tonic-gate 	if (result == NULL)
8400Sstevel@tonic-gate 		return (NULL);
8410Sstevel@tonic-gate 
8422095Smj162486 	if (result->entries_count > 1) {
8432095Smj162486 		(void) snprintf(errstr, MAXERROR,
8446063Smj162486 		    gettext("Configuration Error: More than one profile "
8456063Smj162486 		    "found"));
8462095Smj162486 		MKERROR(LOG_ERR, errorp, NS_PARSE_ERR, strdup(errstr), NULL);
8472095Smj162486 		(void) __ns_ldap_freeError(&errorp);
8482095Smj162486 		return (NULL);
8492095Smj162486 	}
8502095Smj162486 
8510Sstevel@tonic-gate 	ptr = __s_api_create_config();
8520Sstevel@tonic-gate 	if (ptr == NULL)
8530Sstevel@tonic-gate 		return (NULL);
8540Sstevel@tonic-gate 
8550Sstevel@tonic-gate 	curr_ptr = __s_api_get_default_config();
8560Sstevel@tonic-gate 	if (curr_ptr == NULL) {
8570Sstevel@tonic-gate 		__s_api_destroy_config(ptr);
8580Sstevel@tonic-gate 		return (NULL);
8590Sstevel@tonic-gate 	}
8600Sstevel@tonic-gate 
8610Sstevel@tonic-gate 	/* Check to see if the profile is version 1 or version 2 */
8620Sstevel@tonic-gate 	prof_ver = 1;
8630Sstevel@tonic-gate 	entry = result->entry;
8642095Smj162486 	for (l = 0; l < entry->attr_count; l++) {
8652095Smj162486 		attr = entry->attr_pair[l];
8660Sstevel@tonic-gate 
8672095Smj162486 		attrname = attr->attrname;
8682095Smj162486 		if (attrname == NULL)
8692095Smj162486 			continue;
8702095Smj162486 		if (strcasecmp(attrname, "objectclass") == 0) {
8712095Smj162486 			for (m = 0; m < attr->value_count; m++) {
8722095Smj162486 				if (strcasecmp(_PROFILE2_OBJECTCLASS,
8736063Smj162486 				    attr->attrvalue[m]) == 0) {
8742095Smj162486 					prof_ver = 2;
8752095Smj162486 					break;
8760Sstevel@tonic-gate 				}
8770Sstevel@tonic-gate 			}
8780Sstevel@tonic-gate 		}
8790Sstevel@tonic-gate 	}
8800Sstevel@tonic-gate 	/* update the configuration to accept v1 or v2 attributes */
8810Sstevel@tonic-gate 	if (prof_ver == 1) {
8820Sstevel@tonic-gate 		(void) strcpy(val, NS_LDAP_VERSION_1);
8836063Smj162486 		(void) __ns_ldap_setParamValue(ptr, NS_LDAP_FILE_VERSION_P,
8846063Smj162486 		    val, &error);
8850Sstevel@tonic-gate 	} else {
8860Sstevel@tonic-gate 		(void) strcpy(val, NS_LDAP_VERSION_2);
8876063Smj162486 		(void) __ns_ldap_setParamValue(ptr, NS_LDAP_FILE_VERSION_P,
8886063Smj162486 		    val, &error);
8890Sstevel@tonic-gate 	}
8900Sstevel@tonic-gate 
8912095Smj162486 	for (l = 0; l < entry->attr_count; l++) {
8922095Smj162486 		attr = entry->attr_pair[l];
8930Sstevel@tonic-gate 
8942095Smj162486 		attrname = attr->attrname;
8952095Smj162486 		if (attrname == NULL)
8962095Smj162486 			continue;
8972095Smj162486 		if (__s_api_get_profiletype(attrname, &index) != 0)
8982095Smj162486 			continue;
8990Sstevel@tonic-gate 
9002095Smj162486 		attrval = attr->attrvalue;
9012095Smj162486 		switch (index) {
9022095Smj162486 		case NS_LDAP_SEARCH_DN_P:
9032095Smj162486 		case NS_LDAP_SERVICE_SEARCH_DESC_P:
9042095Smj162486 		case NS_LDAP_ATTRIBUTEMAP_P:
9052095Smj162486 		case NS_LDAP_OBJECTCLASSMAP_P:
9062095Smj162486 		case NS_LDAP_SERVICE_CRED_LEVEL_P:
9072095Smj162486 		case NS_LDAP_SERVICE_AUTH_METHOD_P:
9082095Smj162486 			/* Multiple Value - insert 1 at a time */
9092095Smj162486 			for (m = 0; m < attr->value_count; m++) {
9102095Smj162486 				(void) __ns_ldap_setParamValue(ptr, index,
9116063Smj162486 				    attrval[m], &error);
9122095Smj162486 			}
9132095Smj162486 			break;
9142095Smj162486 		default:
915*10132SMilan.Jurik@Sun.COM 			(void) memset((void *)&buffer, 0, sizeof (LineBuf));
916*10132SMilan.Jurik@Sun.COM 
9172095Smj162486 			/* Single or Multiple Value */
9182095Smj162486 			for (m = 0; m < attr->value_count; m++) {
919*10132SMilan.Jurik@Sun.COM 				sepstr = NULL;
920*10132SMilan.Jurik@Sun.COM 				if (m != attr->value_count - 1) {
921*10132SMilan.Jurik@Sun.COM 					sepstr = SPACESEP;
9220Sstevel@tonic-gate 				}
923*10132SMilan.Jurik@Sun.COM 				if (__print2buf(&buffer, attrval[m], sepstr))
924*10132SMilan.Jurik@Sun.COM 					goto makeconfigerror;
9250Sstevel@tonic-gate 			}
926*10132SMilan.Jurik@Sun.COM 			(void) __ns_ldap_setParamValue(ptr, index, buffer.str,
927*10132SMilan.Jurik@Sun.COM 			    &error);
928*10132SMilan.Jurik@Sun.COM 			if (buffer.len > 0) {
929*10132SMilan.Jurik@Sun.COM 				free(buffer.str);
930*10132SMilan.Jurik@Sun.COM 				buffer.len = 0;
931*10132SMilan.Jurik@Sun.COM 			}
9322095Smj162486 			break;
9330Sstevel@tonic-gate 		}
9340Sstevel@tonic-gate 	}
9350Sstevel@tonic-gate 	if (ptr->version != NS_LDAP_V1) {
9368821SMichen.Chang@Sun.COM 		ParamIndexType i;
9376063Smj162486 		if (curr_ptr->paramList[NS_LDAP_BINDDN_P].ns_ptype == CHARPTR) {
9386063Smj162486 			(void) __ns_ldap_setParamValue(ptr, NS_LDAP_BINDDN_P,
9396063Smj162486 			    curr_ptr->paramList[NS_LDAP_BINDDN_P].ns_pc,
9406063Smj162486 			    &error);
9416063Smj162486 		}
9426063Smj162486 		if (curr_ptr->paramList[NS_LDAP_BINDPASSWD_P].ns_ptype ==
9436063Smj162486 		    CHARPTR) {
9446063Smj162486 			(void) __ns_ldap_setParamValue(ptr,
9456063Smj162486 			    NS_LDAP_BINDPASSWD_P,
9466063Smj162486 			    curr_ptr->paramList[NS_LDAP_BINDPASSWD_P].ns_pc,
9476063Smj162486 			    &error);
9486063Smj162486 		}
9498821SMichen.Chang@Sun.COM 		i = NS_LDAP_ENABLE_SHADOW_UPDATE_P;
9508821SMichen.Chang@Sun.COM 		if (curr_ptr->paramList[i].ns_ptype == INT) {
951*10132SMilan.Jurik@Sun.COM 			char *valt;
952*10132SMilan.Jurik@Sun.COM 			valt = __s_get_shadowupdate_name(
9538821SMichen.Chang@Sun.COM 			    curr_ptr->paramList[i].ns_i);
954*10132SMilan.Jurik@Sun.COM 			(void) __ns_ldap_setParamValue(ptr, i, valt, &error);
9558821SMichen.Chang@Sun.COM 		}
9568821SMichen.Chang@Sun.COM 		if (curr_ptr->paramList[NS_LDAP_ADMIN_BINDDN_P].ns_ptype ==
9578821SMichen.Chang@Sun.COM 		    CHARPTR) {
9588821SMichen.Chang@Sun.COM 			(void) __ns_ldap_setParamValue(ptr,
9598821SMichen.Chang@Sun.COM 			    NS_LDAP_ADMIN_BINDDN_P,
9608821SMichen.Chang@Sun.COM 			    curr_ptr->paramList[NS_LDAP_ADMIN_BINDDN_P].ns_pc,
9618821SMichen.Chang@Sun.COM 			    &error);
9628821SMichen.Chang@Sun.COM 		}
9638821SMichen.Chang@Sun.COM 		if (curr_ptr->paramList[NS_LDAP_ADMIN_BINDPASSWD_P].ns_ptype ==
9648821SMichen.Chang@Sun.COM 		    CHARPTR) {
9658821SMichen.Chang@Sun.COM 			(void) __ns_ldap_setParamValue(ptr,
9668821SMichen.Chang@Sun.COM 			    NS_LDAP_ADMIN_BINDPASSWD_P,
9678821SMichen.Chang@Sun.COM 			    curr_ptr->
9688821SMichen.Chang@Sun.COM 			    paramList[NS_LDAP_ADMIN_BINDPASSWD_P].ns_pc,
9698821SMichen.Chang@Sun.COM 			    &error);
9708821SMichen.Chang@Sun.COM 		}
9716063Smj162486 		if (curr_ptr->paramList[NS_LDAP_HOST_CERTPATH_P].ns_ptype ==
9726063Smj162486 		    CHARPTR) {
9736063Smj162486 			(void) __ns_ldap_setParamValue(ptr,
9746063Smj162486 			    NS_LDAP_HOST_CERTPATH_P,
9756063Smj162486 			    curr_ptr->paramList[NS_LDAP_HOST_CERTPATH_P].ns_pc,
9766063Smj162486 			    &error);
9776063Smj162486 		}
9780Sstevel@tonic-gate 	}
9790Sstevel@tonic-gate 	__s_api_release_config(curr_ptr);
9800Sstevel@tonic-gate 	return (ptr);
981*10132SMilan.Jurik@Sun.COM 
982*10132SMilan.Jurik@Sun.COM makeconfigerror:
983*10132SMilan.Jurik@Sun.COM 	if (buffer.len > 0)
984*10132SMilan.Jurik@Sun.COM 		free(buffer.str);
985*10132SMilan.Jurik@Sun.COM 
986*10132SMilan.Jurik@Sun.COM 	__s_api_debug_pause(LOG_ERR, NS_PARSE_ERR,
987*10132SMilan.Jurik@Sun.COM 	    "__ns_ldap_make_config: Not enough memory");
988*10132SMilan.Jurik@Sun.COM 	return (NULL);
9890Sstevel@tonic-gate }
9900Sstevel@tonic-gate 
9910Sstevel@tonic-gate /*
9920Sstevel@tonic-gate  * Download a profile into our internal structure.  The calling application
9930Sstevel@tonic-gate  * needs to DumpConfig() to save the information to NSCONFIGFILE and NSCREDFILE
9940Sstevel@tonic-gate  * if desired.
9950Sstevel@tonic-gate  */
9960Sstevel@tonic-gate int
__ns_ldap_download(const char * profile,char * addr,char * baseDN,ns_ldap_error_t ** errorp)9970Sstevel@tonic-gate __ns_ldap_download(const char *profile, char *addr, char *baseDN,
9980Sstevel@tonic-gate 	ns_ldap_error_t **errorp)
9990Sstevel@tonic-gate {
1000*10132SMilan.Jurik@Sun.COM 	char filter[BUFSIZE];
10010Sstevel@tonic-gate 	int rc;
10020Sstevel@tonic-gate 	ns_ldap_result_t *result = NULL;
10030Sstevel@tonic-gate 	ns_config_t	*ptr = NULL;
10040Sstevel@tonic-gate 	ns_config_t	*new_ptr = NULL;
10050Sstevel@tonic-gate 	char		errstr[MAXERROR];
10060Sstevel@tonic-gate 
10070Sstevel@tonic-gate 	*errorp = NULL;
10080Sstevel@tonic-gate 	if (baseDN == NULL)
10090Sstevel@tonic-gate 		return (NS_LDAP_INVALID_PARAM);
10100Sstevel@tonic-gate 
10110Sstevel@tonic-gate 	ptr = __s_api_get_default_config();
10120Sstevel@tonic-gate 	if (ptr == NULL) {
10130Sstevel@tonic-gate 		(void) snprintf(errstr, sizeof (errstr),
10140Sstevel@tonic-gate 		    gettext("No configuration information available."));
10150Sstevel@tonic-gate 		MKERROR(LOG_ERR, *errorp, NS_CONFIG_NOTLOADED, strdup(errstr),
10166063Smj162486 		    NULL);
10170Sstevel@tonic-gate 		return (NS_LDAP_CONFIG);
10180Sstevel@tonic-gate 	}
10190Sstevel@tonic-gate 
10206063Smj162486 	rc = __ns_ldap_setParamValue(ptr, NS_LDAP_SEARCH_BASEDN_P, baseDN,
10216063Smj162486 	    errorp);
10220Sstevel@tonic-gate 	if (rc != NS_LDAP_SUCCESS) {
10230Sstevel@tonic-gate 		__s_api_release_config(ptr);
10240Sstevel@tonic-gate 		return (rc);
10250Sstevel@tonic-gate 	}
10260Sstevel@tonic-gate 
10270Sstevel@tonic-gate 	rc = __ns_ldap_setParamValue(ptr, NS_LDAP_SERVERS_P, addr, errorp);
10280Sstevel@tonic-gate 	__s_api_release_config(ptr);
10290Sstevel@tonic-gate 	if (rc != NS_LDAP_SUCCESS)
10300Sstevel@tonic-gate 		return (rc);
10310Sstevel@tonic-gate 
10320Sstevel@tonic-gate 	(void) snprintf(filter, sizeof (filter), _PROFILE_FILTER,
10336063Smj162486 	    _PROFILE1_OBJECTCLASS, _PROFILE2_OBJECTCLASS, profile);
10340Sstevel@tonic-gate 	rc = __ns_ldap_list(_PROFILE_CONTAINER, (const char *)filter,
10356063Smj162486 	    NULL, NULL, NULL, 0, &result, errorp, NULL, NULL);
10360Sstevel@tonic-gate 
10370Sstevel@tonic-gate 	if (rc != NS_LDAP_SUCCESS)
10380Sstevel@tonic-gate 		return (rc);
10390Sstevel@tonic-gate 
10400Sstevel@tonic-gate 	new_ptr = __ns_ldap_make_config(result);
10410Sstevel@tonic-gate 	(void) __ns_ldap_freeResult(&result);
10420Sstevel@tonic-gate 
10432095Smj162486 	if (new_ptr == NULL)
10442095Smj162486 		return (NS_LDAP_OP_FAILED);
10452095Smj162486 
10460Sstevel@tonic-gate 	rc = __s_api_crosscheck(new_ptr, errstr, B_FALSE);
10470Sstevel@tonic-gate 	if (rc != NS_LDAP_SUCCESS) {
10480Sstevel@tonic-gate 		__s_api_destroy_config(new_ptr);
10490Sstevel@tonic-gate 		MKERROR(LOG_ERR, *errorp, NS_CONFIG_NOTLOADED, strdup(errstr),
10506063Smj162486 		    NULL);
10510Sstevel@tonic-gate 		return (NS_LDAP_CONFIG);
10520Sstevel@tonic-gate 	}
10530Sstevel@tonic-gate 
10540Sstevel@tonic-gate 	__s_api_init_config(new_ptr);
10550Sstevel@tonic-gate 	return (rc);
10560Sstevel@tonic-gate }
10570Sstevel@tonic-gate 
10580Sstevel@tonic-gate /*
10590Sstevel@tonic-gate  * **************************************************************
10600Sstevel@tonic-gate  * Configuration Printing Routines
10610Sstevel@tonic-gate  * **************************************************************
10620Sstevel@tonic-gate  */
10630Sstevel@tonic-gate 
10640Sstevel@tonic-gate /*
10650Sstevel@tonic-gate  * Yes the use of stdio is okay here because all we are doing is sending
10660Sstevel@tonic-gate  * output to stdout.  This would not be necessary if we could get to the
10670Sstevel@tonic-gate  * configuration pointer outside this file.
10680Sstevel@tonic-gate  */
10690Sstevel@tonic-gate ns_ldap_error_t *
__ns_ldap_print_config(int verbose)10700Sstevel@tonic-gate __ns_ldap_print_config(int verbose)
10710Sstevel@tonic-gate {
10720Sstevel@tonic-gate 	ns_config_t	*ptr;
10730Sstevel@tonic-gate 	char		errstr[MAXERROR];
10740Sstevel@tonic-gate 	ns_ldap_error_t *errorp;
10750Sstevel@tonic-gate 	char		*str;
10760Sstevel@tonic-gate 	int		i;
10770Sstevel@tonic-gate 
10780Sstevel@tonic-gate 	ptr = __s_api_get_default_config();
10790Sstevel@tonic-gate 	if (ptr == NULL) {
10800Sstevel@tonic-gate 		errorp = __ns_ldap_LoadConfiguration();
10810Sstevel@tonic-gate 		if (errorp != NULL)
10820Sstevel@tonic-gate 			return (errorp);
10830Sstevel@tonic-gate 		ptr = __s_api_get_default_config();
10840Sstevel@tonic-gate 		if (ptr == NULL) {
10850Sstevel@tonic-gate 			(void) snprintf(errstr, sizeof (errstr),
10860Sstevel@tonic-gate 			    gettext("No configuration information."));
10870Sstevel@tonic-gate 			MKERROR(LOG_WARNING, errorp, NS_CONFIG_NOTLOADED,
10886063Smj162486 			    strdup(errstr), NULL);
10890Sstevel@tonic-gate 			return (errorp);
10900Sstevel@tonic-gate 		}
10910Sstevel@tonic-gate 	}
10920Sstevel@tonic-gate 
10930Sstevel@tonic-gate 	if (verbose && (ptr->domainName != NULL)) {
10940Sstevel@tonic-gate 		(void) fputs("ptr->domainName ", stdout);
10950Sstevel@tonic-gate 		(void) fputs(ptr->domainName, stdout);
10960Sstevel@tonic-gate 		(void) putchar('\n');
10970Sstevel@tonic-gate 	}
10980Sstevel@tonic-gate 	/* For each parameter - construct value */
10990Sstevel@tonic-gate 	for (i = 0; i <= NS_LDAP_MAX_PIT_P; i++) {
11000Sstevel@tonic-gate 			/*
11010Sstevel@tonic-gate 			 * Version 1 skipped this entry because:
11020Sstevel@tonic-gate 			 *
11030Sstevel@tonic-gate 			 * don't print default cache TTL for now since
11040Sstevel@tonic-gate 			 * we don't store it in the ldap_client_file.
11050Sstevel@tonic-gate 			 */
11060Sstevel@tonic-gate 		if ((i == NS_LDAP_CACHETTL_P) && (ptr->version == NS_LDAP_V1))
11070Sstevel@tonic-gate 			continue;
11080Sstevel@tonic-gate 
11098821SMichen.Chang@Sun.COM 		/* the credential for shadow update is not to be exposed */
11108821SMichen.Chang@Sun.COM 		if (i == NS_LDAP_ADMIN_BINDDN_P ||
11118821SMichen.Chang@Sun.COM 		    i == NS_LDAP_ADMIN_BINDPASSWD_P)
11128821SMichen.Chang@Sun.COM 			continue;
11138821SMichen.Chang@Sun.COM 
1114*10132SMilan.Jurik@Sun.COM 		str = __s_api_strValue(ptr, i, NS_FILE_FMT);
11150Sstevel@tonic-gate 		if (str == NULL)
11160Sstevel@tonic-gate 			continue;
11170Sstevel@tonic-gate 		if (verbose)
11180Sstevel@tonic-gate 			(void) putchar('\t');
11190Sstevel@tonic-gate 		(void) fprintf(stdout, "%s\n", str);
1120*10132SMilan.Jurik@Sun.COM 		free(str);
11210Sstevel@tonic-gate 	}
11220Sstevel@tonic-gate 
11230Sstevel@tonic-gate 	__s_api_release_config(ptr);
11240Sstevel@tonic-gate 	return (NULL);
11250Sstevel@tonic-gate }
1126