xref: /onnv-gate/usr/src/lib/libnisdb/yptol/dit_access.c (revision 13143:317a09ef2c51)
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
52189Ssdussud  * Common Development and Distribution License (the "License").
62189Ssdussud  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*
22*13143SBenjamin.Chang@Oracle.COM  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
230Sstevel@tonic-gate  */
240Sstevel@tonic-gate 
250Sstevel@tonic-gate /*
260Sstevel@tonic-gate  * DESCRIPTION: Contains top level functions to read/write to the DIT. These
270Sstevel@tonic-gate  *		are the API between the shim and the mapping system.
280Sstevel@tonic-gate  *		Things calling these should have no knowledge of LDAP. Things
290Sstevel@tonic-gate  *		called by them should have no knowledge of NIS.
300Sstevel@tonic-gate  *
310Sstevel@tonic-gate  *		Error handling here may appear to be limited but, because the
320Sstevel@tonic-gate  *		NIS protocol cannot carry meaningful information about why a
330Sstevel@tonic-gate  *		N2L operation failed, functions that don't work log
340Sstevel@tonic-gate  *		an error and then just return FAILURE.
350Sstevel@tonic-gate  *
360Sstevel@tonic-gate  */
370Sstevel@tonic-gate 
380Sstevel@tonic-gate /*
390Sstevel@tonic-gate  * Includes. WE WANT TO USE REAL DBM FUNCTIONS SO DO NOT INCLUDE SHIM_HOOKS.H.
400Sstevel@tonic-gate  */
410Sstevel@tonic-gate #include <unistd.h>
420Sstevel@tonic-gate #include <syslog.h>
430Sstevel@tonic-gate #include <ndbm.h>
440Sstevel@tonic-gate #include <sys/systeminfo.h>
450Sstevel@tonic-gate #include <string.h>
460Sstevel@tonic-gate #include <lber.h>
470Sstevel@tonic-gate #include <ldap.h>
480Sstevel@tonic-gate #include <errno.h>
490Sstevel@tonic-gate #include "ypsym.h"
500Sstevel@tonic-gate #include "ypdefs.h"
510Sstevel@tonic-gate #include "shim.h"
520Sstevel@tonic-gate #include "../ldap_structs.h"
530Sstevel@tonic-gate #include "../ldap_parse.h"
540Sstevel@tonic-gate #include "../nisdb_ldap.h"
550Sstevel@tonic-gate #include "../ldap_util.h"
560Sstevel@tonic-gate #include "../ldap_op.h"
570Sstevel@tonic-gate #include "../ldap_attr.h"
580Sstevel@tonic-gate #include "../nis_parse_ldap_conf.h"
590Sstevel@tonic-gate #include "../nisdb_mt.h"
600Sstevel@tonic-gate #include "yptol.h"
610Sstevel@tonic-gate #include "dit_access_utils.h"
620Sstevel@tonic-gate #include "stdio.h"
630Sstevel@tonic-gate 
642189Ssdussud extern bool delete_map(char *name);
652189Ssdussud extern bool rename_map(char *from, char *to, bool_t secure_map);
662189Ssdussud 
670Sstevel@tonic-gate /* Enable standard YP code features defined in ypdefs.h */
680Sstevel@tonic-gate USE_YP_MASTER_NAME
690Sstevel@tonic-gate USE_YP_DOMAIN_NAME
700Sstevel@tonic-gate USE_YP_SECURE
710Sstevel@tonic-gate USE_YP_INTERDOMAIN
720Sstevel@tonic-gate 
730Sstevel@tonic-gate /*
740Sstevel@tonic-gate  * Decs
750Sstevel@tonic-gate  */
760Sstevel@tonic-gate suc_code add_special_entries(DBM *, map_ctrl *, bool_t *);
770Sstevel@tonic-gate void free_null_terminated_list(char **list);
780Sstevel@tonic-gate 
790Sstevel@tonic-gate 
800Sstevel@tonic-gate /*
810Sstevel@tonic-gate  * FUNCTION:    is_yptol_mode();
820Sstevel@tonic-gate  *
830Sstevel@tonic-gate  * DESCRIPTION:	Determines if we should run in N2L or traditional mode based
840Sstevel@tonic-gate  *		on the presence of the N2L mapping file. If there are problems
850Sstevel@tonic-gate  *		with the file, e.g. unreadable, this will be picked up latter.
860Sstevel@tonic-gate  *
870Sstevel@tonic-gate  * INPUTS:     	Nothing
880Sstevel@tonic-gate  *
890Sstevel@tonic-gate  * OUTPUTS:   	TRUE = Run in N2L mode
900Sstevel@tonic-gate  *		FALSE = Run in traditional mode.
910Sstevel@tonic-gate  */
920Sstevel@tonic-gate bool_t
is_yptol_mode()930Sstevel@tonic-gate is_yptol_mode()
940Sstevel@tonic-gate {
950Sstevel@tonic-gate 	struct stat filestat;
960Sstevel@tonic-gate 
970Sstevel@tonic-gate 	if (stat(YP_DEFAULTCONFFILE, &filestat) != -1)
980Sstevel@tonic-gate 		return (TRUE);
990Sstevel@tonic-gate 
1000Sstevel@tonic-gate 	return (FALSE);
1010Sstevel@tonic-gate }
1020Sstevel@tonic-gate 
1030Sstevel@tonic-gate /*
1040Sstevel@tonic-gate  * FUNCTION:    read_from_dit();
1050Sstevel@tonic-gate  *
1060Sstevel@tonic-gate  * DESCRIPTION:	Read (i.e. get and map) a single NIS entry from the LDAP DIT.
1070Sstevel@tonic-gate  *		Also handles retry attempts, on failure, and interpretation of
1080Sstevel@tonic-gate  *		internal error codes.
1090Sstevel@tonic-gate  *
1100Sstevel@tonic-gate  * INPUTS:     	Map name (unqualified)
1110Sstevel@tonic-gate  *		Domain name
1120Sstevel@tonic-gate  *		Entry key
1130Sstevel@tonic-gate  *		Pointer to return location
1140Sstevel@tonic-gate  *
1150Sstevel@tonic-gate  * OUTPUTS:   	If successful DBM datum containing result.
1160Sstevel@tonic-gate  *		On error DBM datum pointing to NULL and, if the cached value
1170Sstevel@tonic-gate  *		is not to be used, an error code.
1180Sstevel@tonic-gate  */
1190Sstevel@tonic-gate int
read_from_dit(char * map,char * domain,datum * key,datum * value)1200Sstevel@tonic-gate read_from_dit(char *map, char *domain, datum *key, datum *value)
1210Sstevel@tonic-gate {
1220Sstevel@tonic-gate 	int count;
1230Sstevel@tonic-gate 	int res;
1240Sstevel@tonic-gate 	__nisdb_retry_t	*retrieveRetry;
1250Sstevel@tonic-gate 
1260Sstevel@tonic-gate 	/* Initialize tsd */
1270Sstevel@tonic-gate 	__nisdb_get_tsd()->domainContext = 0;
1280Sstevel@tonic-gate 	__nisdb_get_tsd()->escapeFlag = '\0';
1290Sstevel@tonic-gate 
1300Sstevel@tonic-gate 	for (count = 0; count < ypDomains.numDomains; count++) {
1310Sstevel@tonic-gate 		if (0 == ypDomains.domainLabels[count])
1320Sstevel@tonic-gate 			continue;
1330Sstevel@tonic-gate 		if (0 == strcasecmp(domain, ypDomains.domainLabels[count])) {
1340Sstevel@tonic-gate 			__nisdb_get_tsd()->domainContext =
1356772Sandra 			    ypDomains.domains[count];
1360Sstevel@tonic-gate 			break;
1370Sstevel@tonic-gate 		}
1380Sstevel@tonic-gate 	}
1390Sstevel@tonic-gate 
1400Sstevel@tonic-gate 	retrieveRetry = &ldapDBTableMapping.retrieveErrorRetry;
1410Sstevel@tonic-gate 
1420Sstevel@tonic-gate 	/* Loop 'attempts' times of forever if -1 */
1430Sstevel@tonic-gate 	for (count = retrieveRetry->attempts; (0 <= count) ||
1446772Sandra 	    (-1 == retrieveRetry->attempts); count --) {
1450Sstevel@tonic-gate 		if (TRUE == singleReadFromDIT(map, domain, key, value, &res))
1460Sstevel@tonic-gate 			/* It worked, return value irrelevant */
1470Sstevel@tonic-gate 			return (0);
1480Sstevel@tonic-gate 
1490Sstevel@tonic-gate 		if (LDAP_TIMEOUT == res) { /* Exceeded search timeout */
1500Sstevel@tonic-gate 			value->dptr = NULL;
1510Sstevel@tonic-gate 			return (0);
1520Sstevel@tonic-gate 		}
1530Sstevel@tonic-gate 
1540Sstevel@tonic-gate 		if (is_fatal_error(res))
1550Sstevel@tonic-gate 			break;
1560Sstevel@tonic-gate 
1570Sstevel@tonic-gate 		/*
1580Sstevel@tonic-gate 		 * Didn't work. If not the special case where no repeats are
1590Sstevel@tonic-gate 		 * done sleep.
1600Sstevel@tonic-gate 		 */
1610Sstevel@tonic-gate 		if (0 != retrieveRetry->attempts)
1620Sstevel@tonic-gate 			(void) poll(NULL, 0, retrieveRetry->timeout*1000);
1630Sstevel@tonic-gate 	}
1640Sstevel@tonic-gate 
1650Sstevel@tonic-gate 	/* Make sure returned pointer is NULL */
1660Sstevel@tonic-gate 	value->dptr = NULL;
1670Sstevel@tonic-gate 
1680Sstevel@tonic-gate 	/* If we get here access failed work out what to return */
1690Sstevel@tonic-gate 	if (ldapDBTableMapping.retrieveError == use_cached)
1700Sstevel@tonic-gate 		return (0);
1710Sstevel@tonic-gate 
1720Sstevel@tonic-gate 	return (res);
1730Sstevel@tonic-gate }
1740Sstevel@tonic-gate 
1750Sstevel@tonic-gate /*
1760Sstevel@tonic-gate  * FUNCTION:    write_to_dit();
1770Sstevel@tonic-gate  *
1780Sstevel@tonic-gate  * DESCRIPTION:	Maps and writes a NIS entry to the LDAP DIT.
1790Sstevel@tonic-gate  *		Also handles retry attempts, on failure, and interpretation of
1800Sstevel@tonic-gate  *		internal error codes.
1810Sstevel@tonic-gate  *
1820Sstevel@tonic-gate  * INPUTS:     	Pointer to (unqualified) map name
1830Sstevel@tonic-gate  *		Pointer to domain name
1840Sstevel@tonic-gate  *		The entries key
1850Sstevel@tonic-gate  *		What to write
1860Sstevel@tonic-gate  *		Replace flag indicating
1870Sstevel@tonic-gate  *			TRUE = Replace (overwrite) any existing entries
1880Sstevel@tonic-gate  *			FALSE = Return error if there are existing entries
1890Sstevel@tonic-gate  *		Flag indicating if we should tolerate mapping errors.
1900Sstevel@tonic-gate  *
1910Sstevel@tonic-gate  * OUTPUTS:   	SUCCESS = Write was successful
1920Sstevel@tonic-gate  *		FAILURE = Write failed
1930Sstevel@tonic-gate  *
1940Sstevel@tonic-gate  */
1950Sstevel@tonic-gate suc_code
write_to_dit(char * map,char * domain,datum key,datum value,bool_t replace,bool_t ignore_map_errs)1960Sstevel@tonic-gate write_to_dit(char *map, char *domain, datum key, datum value,
1970Sstevel@tonic-gate 					bool_t replace, bool_t ignore_map_errs)
1980Sstevel@tonic-gate {
1990Sstevel@tonic-gate 	int count;
2000Sstevel@tonic-gate 	int res;
2010Sstevel@tonic-gate 	__nisdb_retry_t	*storeRetry = &ldapDBTableMapping.storeErrorRetry;
2020Sstevel@tonic-gate 
2030Sstevel@tonic-gate 	/* Initialize tsd */
2040Sstevel@tonic-gate 	__nisdb_get_tsd()->domainContext = 0;
2050Sstevel@tonic-gate 	__nisdb_get_tsd()->escapeFlag = '\0';
2060Sstevel@tonic-gate 
2070Sstevel@tonic-gate 	for (count = 0; count < ypDomains.numDomains; count++) {
2080Sstevel@tonic-gate 		if (0 == ypDomains.domainLabels[count])
2090Sstevel@tonic-gate 			continue;
2100Sstevel@tonic-gate 		if (0 == strcasecmp(domain, ypDomains.domainLabels[count])) {
2110Sstevel@tonic-gate 			__nisdb_get_tsd()->domainContext =
2126772Sandra 			    ypDomains.domains[count];
2130Sstevel@tonic-gate 			break;
2140Sstevel@tonic-gate 		}
2150Sstevel@tonic-gate 	}
2160Sstevel@tonic-gate 
2170Sstevel@tonic-gate 	storeRetry = &ldapDBTableMapping.storeErrorRetry;
2180Sstevel@tonic-gate 
2190Sstevel@tonic-gate 	/* Loop 'attempts' times of forever if -1 */
2200Sstevel@tonic-gate 	for (count = storeRetry->attempts; (0 <= count) ||
2216772Sandra 	    (-1 == storeRetry->attempts); count --) {
2220Sstevel@tonic-gate 		res = singleWriteToDIT(map, domain, &key, &value, replace);
2230Sstevel@tonic-gate 		if (LDAP_SUCCESS == res)
2240Sstevel@tonic-gate 			return (SUCCESS);
2250Sstevel@tonic-gate 
2260Sstevel@tonic-gate 		if (is_fatal_error(res)) {
2270Sstevel@tonic-gate 			/*
2280Sstevel@tonic-gate 			 * The mapping failed and will fail again if it is
2290Sstevel@tonic-gate 			 * retried. However there are some cases where an
2300Sstevel@tonic-gate 			 * actual mapping fault (rather than a LDAP problem)
2310Sstevel@tonic-gate 			 * may be ignored.
2320Sstevel@tonic-gate 			 */
2330Sstevel@tonic-gate 			if (ignore_map_errs) {
2340Sstevel@tonic-gate 				switch (res) {
2350Sstevel@tonic-gate 					case LDAP_INVALID_DN_SYNTAX:
2360Sstevel@tonic-gate 					case LDAP_OBJECT_CLASS_VIOLATION:
2370Sstevel@tonic-gate 					case LDAP_NOT_ALLOWED_ON_RDN:
2380Sstevel@tonic-gate 					case MAP_NAMEFIELD_MATCH_ERROR:
2390Sstevel@tonic-gate 					case MAP_NO_DN:
2400Sstevel@tonic-gate 						return (SUCCESS);
2410Sstevel@tonic-gate 					default:
2420Sstevel@tonic-gate 						break;
2430Sstevel@tonic-gate 				}
2440Sstevel@tonic-gate 			}
2450Sstevel@tonic-gate 			return (FAILURE);
2460Sstevel@tonic-gate 		}
2470Sstevel@tonic-gate 
2480Sstevel@tonic-gate 		if (ldapDBTableMapping.storeError != sto_retry)
2490Sstevel@tonic-gate 			return (FAILURE);
2500Sstevel@tonic-gate 
2510Sstevel@tonic-gate 		/*
2520Sstevel@tonic-gate 		 * Didn't work. If not the special case where no repeats are
2530Sstevel@tonic-gate 		 * done sleep.
2540Sstevel@tonic-gate 		 */
2550Sstevel@tonic-gate 		if (0 != storeRetry->attempts)
2560Sstevel@tonic-gate 			(void) poll(NULL, 0, storeRetry->timeout*1000);
2570Sstevel@tonic-gate 
2580Sstevel@tonic-gate 	}
2590Sstevel@tonic-gate 	return (FAILURE);
2600Sstevel@tonic-gate }
2610Sstevel@tonic-gate 
2620Sstevel@tonic-gate /*
2630Sstevel@tonic-gate  * FUNCTION :	get_ttl_value()
2640Sstevel@tonic-gate  *
2650Sstevel@tonic-gate  * DESCRIPTION:	Get the TTL value, derived from mapping file or DIT, for a
2660Sstevel@tonic-gate  *		entry.
2670Sstevel@tonic-gate  *
2680Sstevel@tonic-gate  * GIVEN :	Pointer to map
2690Sstevel@tonic-gate  *		A flag indication if TTL should be max, min or random
2700Sstevel@tonic-gate  *
2710Sstevel@tonic-gate  * RETURNS :	TTL value in seconds.
2720Sstevel@tonic-gate  *		-1 on failure
2730Sstevel@tonic-gate  */
2740Sstevel@tonic-gate int
get_ttl_value(map_ctrl * map,TTL_TYPE type)2750Sstevel@tonic-gate get_ttl_value(map_ctrl *map, TTL_TYPE type)
2760Sstevel@tonic-gate {
2770Sstevel@tonic-gate 	__nis_table_mapping_t *table_map;
2780Sstevel@tonic-gate 	int interval, res;
2790Sstevel@tonic-gate 	char *myself = "get_ttl_value";
2800Sstevel@tonic-gate 
2810Sstevel@tonic-gate 	/*  Get the mapping structure corresponding to `map.domain' */
2820Sstevel@tonic-gate 	table_map = mappingFromMap(map->map_name, map->domain, &res);
2830Sstevel@tonic-gate 
2840Sstevel@tonic-gate 	if (0 == table_map) {
2850Sstevel@tonic-gate 		logmsg(MSG_NOTIMECHECK, LOG_ERR,
2866772Sandra 		    "Get TTL request could not access map %s in domain %s "
2876772Sandra 		    "(error %d)", map->map_name, map->domain, res);
2880Sstevel@tonic-gate 		return (-1);
2890Sstevel@tonic-gate 	}
2900Sstevel@tonic-gate 
2910Sstevel@tonic-gate 	switch (type) {
2920Sstevel@tonic-gate 		case TTL_MAX:
2930Sstevel@tonic-gate 			return (table_map->initTtlHi);
2940Sstevel@tonic-gate 
2950Sstevel@tonic-gate 		case TTL_MIN:
2960Sstevel@tonic-gate 			return (table_map->initTtlLo);
2970Sstevel@tonic-gate 
2980Sstevel@tonic-gate 		default:
2990Sstevel@tonic-gate 			logmsg(MSG_NOTIMECHECK, LOG_INFO,
3000Sstevel@tonic-gate 			"%s passed illegal TTL type (%d)", myself, type);
3010Sstevel@tonic-gate 			/* If unknown TTL type drop through to TTL_RAND */
3020Sstevel@tonic-gate 
3030Sstevel@tonic-gate 		case TTL_RAND:
3040Sstevel@tonic-gate 			interval = table_map->initTtlHi - table_map->initTtlLo;
3050Sstevel@tonic-gate 			if (0 >= interval)
3060Sstevel@tonic-gate 				return (table_map->initTtlLo);
3070Sstevel@tonic-gate 
3080Sstevel@tonic-gate 			/*
3090Sstevel@tonic-gate 			 * Must get a random value. We assume srand48() got
3100Sstevel@tonic-gate 			 * called at initialization.
3110Sstevel@tonic-gate 			 */
3120Sstevel@tonic-gate 			return (lrand48() % interval);
3130Sstevel@tonic-gate 
3140Sstevel@tonic-gate 		case TTL_RUNNING:
3150Sstevel@tonic-gate 			return (table_map->ttl);
3160Sstevel@tonic-gate 
3170Sstevel@tonic-gate 
3180Sstevel@tonic-gate 	}
3190Sstevel@tonic-gate }
3200Sstevel@tonic-gate 
3210Sstevel@tonic-gate /*
3220Sstevel@tonic-gate  * FUNCTION :	get_mapping_domain_list()
3230Sstevel@tonic-gate  *
3240Sstevel@tonic-gate  * DESCRIPTION:	Gets a list of domain names specified, by nisLDAPdomainContext
3250Sstevel@tonic-gate  *		attributes, in the mapping file. This is used only for initial
3260Sstevel@tonic-gate  *		DIT setup. Once the DIT has been set up get_domain_list() is
3270Sstevel@tonic-gate  *		used instead.
3280Sstevel@tonic-gate  *
3290Sstevel@tonic-gate  * GIVEN :	Pointer returned array.
3300Sstevel@tonic-gate  *
3310Sstevel@tonic-gate  * RETURNS :	Number of element in returned array.
3320Sstevel@tonic-gate  *		Array of elements this is in static memory
3330Sstevel@tonic-gate  *		and must not be freed by the caller.
3340Sstevel@tonic-gate  */
3350Sstevel@tonic-gate int
get_mapping_domain_list(char *** ptr)3360Sstevel@tonic-gate get_mapping_domain_list(char ***ptr)
3370Sstevel@tonic-gate {
3380Sstevel@tonic-gate 	*ptr = ypDomains.domainLabels;
3390Sstevel@tonic-gate 	return (ypDomains.numDomains);
3400Sstevel@tonic-gate }
3410Sstevel@tonic-gate 
3420Sstevel@tonic-gate /*
3430Sstevel@tonic-gate  * FUNCTION :	get_mapping_yppasswdd_domain_list()
3440Sstevel@tonic-gate  *
3450Sstevel@tonic-gate  * DESCRIPTION:	Gets a list of domain names specified, by the
3460Sstevel@tonic-gate  *		nisLDAPyppasswddDomains attribute, in the mapping file. This
3470Sstevel@tonic-gate  *		is the list of domains for which passwords should be changed.
3480Sstevel@tonic-gate  *
3490Sstevel@tonic-gate  * GIVEN :	Pointer returned array
3500Sstevel@tonic-gate  *
3510Sstevel@tonic-gate  * RETURNS :	Number of element in returned array.
3520Sstevel@tonic-gate  *		0 if no nisLDAPyppasswddDomains attribute is present.
3530Sstevel@tonic-gate  *		Array of elements this is in static memory
3540Sstevel@tonic-gate  *		and must not be freed by the caller.
3550Sstevel@tonic-gate  */
3560Sstevel@tonic-gate int
get_mapping_yppasswdd_domain_list(char *** ptr)3570Sstevel@tonic-gate get_mapping_yppasswdd_domain_list(char ***ptr)
3580Sstevel@tonic-gate {
3590Sstevel@tonic-gate 	*ptr = ypDomains.yppasswddDomainLabels;
3600Sstevel@tonic-gate 	return (ypDomains.numYppasswdd);
3610Sstevel@tonic-gate }
3620Sstevel@tonic-gate 
3630Sstevel@tonic-gate /*
3640Sstevel@tonic-gate  * FUNCTION :	free_map_list()
3650Sstevel@tonic-gate  *
3660Sstevel@tonic-gate  * DESCRIPTION:	Frees a map list.
3670Sstevel@tonic-gate  *
3680Sstevel@tonic-gate  * GIVEN :	Pointer to the map list.
3690Sstevel@tonic-gate  *
3700Sstevel@tonic-gate  * RETURNS :	Nothing
3710Sstevel@tonic-gate  */
3720Sstevel@tonic-gate void
free_map_list(char ** map_list)3730Sstevel@tonic-gate free_map_list(char **map_list)
3740Sstevel@tonic-gate {
3750Sstevel@tonic-gate 	free_null_terminated_list(map_list);
3760Sstevel@tonic-gate }
3770Sstevel@tonic-gate 
3780Sstevel@tonic-gate /*
3790Sstevel@tonic-gate  * FUNCTION :	get_passwd_list()
3800Sstevel@tonic-gate  *
3810Sstevel@tonic-gate  * DESCRIPTION:	Gets a list of either passwd or passwd.adjunct map files
3820Sstevel@tonic-gate  *		defined in the mapping file. These are the files which have
3830Sstevel@tonic-gate  *		'magic' nisLDAPdatabaseIdMapping entries aliasing them to
3840Sstevel@tonic-gate  *		passwd or passwd.adjunct. This function is required so that
3850Sstevel@tonic-gate  *		yppasswdd can work out which maps to synchronize with any
3860Sstevel@tonic-gate  *		password changes.
3870Sstevel@tonic-gate  *
3880Sstevel@tonic-gate  *		This information is not currently stored by the parser but
3890Sstevel@tonic-gate  *		we can recover it from the hash table. This makes hard work but
3900Sstevel@tonic-gate  *		passwords should not be changed very frequently
3910Sstevel@tonic-gate  *
3920Sstevel@tonic-gate  * GIVEN :	Flag indicating if a list is required for passwd or
3930Sstevel@tonic-gate  *		passwd.adjunct
3940Sstevel@tonic-gate  *		Domain to return the list for.
3950Sstevel@tonic-gate  *
3960Sstevel@tonic-gate  * RETURNS :	Null terminated list of map names in malloced memory. To be
3970Sstevel@tonic-gate  *		freed by caller. (Possibly empty if no passwd maps found)
3980Sstevel@tonic-gate  *		NULL on error
3990Sstevel@tonic-gate  */
4000Sstevel@tonic-gate char **
get_passwd_list(bool_t adjunct,char * domain)4010Sstevel@tonic-gate get_passwd_list(bool_t adjunct, char *domain)
4020Sstevel@tonic-gate {
4030Sstevel@tonic-gate 	char *myself = "get_passwd_list";
4040Sstevel@tonic-gate 	__nis_hash_item_mt *it;
4050Sstevel@tonic-gate 	int	i, size;
4062189Ssdussud 	char 	*end_ptr;
4070Sstevel@tonic-gate 	char	*target;	/* What we are looking for */
4080Sstevel@tonic-gate 	int	target_len;
4090Sstevel@tonic-gate 	int	domain_len;
4100Sstevel@tonic-gate 	char	**res;		/* Result array */
4110Sstevel@tonic-gate 	char	**res_old;	/* Old value of res during realloc */
4120Sstevel@tonic-gate 	int	array_size;	/* Current malloced size */
4130Sstevel@tonic-gate 	int	res_count = 0;	/* Current result count */
4140Sstevel@tonic-gate 
4150Sstevel@tonic-gate 	/*
4160Sstevel@tonic-gate 	 * Always need an array even if just for terminator. Normally one
4170Sstevel@tonic-gate 	 * chunk will be enough.
4180Sstevel@tonic-gate 	 */
4190Sstevel@tonic-gate 	res = am(myself, ARRAY_CHUNK * sizeof (char *));
4200Sstevel@tonic-gate 	if (NULL == res)
4210Sstevel@tonic-gate 		return (NULL);
4220Sstevel@tonic-gate 	array_size = ARRAY_CHUNK;
4230Sstevel@tonic-gate 
4240Sstevel@tonic-gate 	/* Set up target */
4250Sstevel@tonic-gate 	if (adjunct)
4260Sstevel@tonic-gate 		target = PASSWD_ADJUNCT_PREFIX;
4270Sstevel@tonic-gate 	else
4280Sstevel@tonic-gate 		target = PASSWD_PREFIX;
4290Sstevel@tonic-gate 	target_len = strlen(target);
4300Sstevel@tonic-gate 	domain_len = strlen(domain);
4310Sstevel@tonic-gate 
4320Sstevel@tonic-gate 	/* Work out hash table length */
4330Sstevel@tonic-gate 	size = sizeof (ldapMappingList.keys) / sizeof (ldapMappingList.keys[0]);
4340Sstevel@tonic-gate 	/* For all hash table entries */
4350Sstevel@tonic-gate 	for (i = 0; i < size; i++) {
4360Sstevel@tonic-gate 		/* Walk linked list for this hash table entry */
4370Sstevel@tonic-gate 		for (it = ldapMappingList.keys[i]; NULL != it; it = it->next) {
4380Sstevel@tonic-gate 			/* Check right map */
4390Sstevel@tonic-gate 			if ((target_len + domain_len + 1) > strlen(it->name))
4400Sstevel@tonic-gate 				continue;
4410Sstevel@tonic-gate 			if (0 != strncmp(it->name, target, target_len))
4420Sstevel@tonic-gate 				continue;
4430Sstevel@tonic-gate 
4440Sstevel@tonic-gate 			/* Check right domain (minus trailing dot) */
4450Sstevel@tonic-gate 			if (strlen(domain) >= strlen(it->name))
4460Sstevel@tonic-gate 				continue;
4470Sstevel@tonic-gate 			end_ptr = it->name + strlen(it->name) -
4486772Sandra 			    strlen(domain) - 1;
4490Sstevel@tonic-gate 			if (',' != *(end_ptr - 1))
4500Sstevel@tonic-gate 				continue;
4510Sstevel@tonic-gate 			if (0 != strncmp(end_ptr, domain, strlen(domain)))
4520Sstevel@tonic-gate 				continue;
4530Sstevel@tonic-gate 
4540Sstevel@tonic-gate 			/* Check if we need to enlarge array */
4550Sstevel@tonic-gate 			if ((res_count + 1) >= array_size) {
4560Sstevel@tonic-gate 				array_size += ARRAY_CHUNK;
4570Sstevel@tonic-gate 				res_old = res;
4580Sstevel@tonic-gate 				res = realloc(res, array_size *
4596772Sandra 				    sizeof (char *));
4600Sstevel@tonic-gate 				if (NULL == res) {
4610Sstevel@tonic-gate 					res_old[res_count] = NULL;
4620Sstevel@tonic-gate 					free_passwd_list(res_old);
4630Sstevel@tonic-gate 					return (NULL);
4640Sstevel@tonic-gate 				}
4650Sstevel@tonic-gate 			}
4660Sstevel@tonic-gate 
4670Sstevel@tonic-gate 			/* What we really need is strndup() */
4680Sstevel@tonic-gate 			res[res_count] = am(myself, end_ptr - it->name + 1);
4690Sstevel@tonic-gate 			if (NULL == res[res_count]) {
4700Sstevel@tonic-gate 				free_passwd_list(res);
4710Sstevel@tonic-gate 				return (NULL);
4720Sstevel@tonic-gate 			}
4730Sstevel@tonic-gate 
4740Sstevel@tonic-gate 			/* Copy from start to end_ptr */
4752189Ssdussud 			(void) memcpy(res[res_count], it->name,
4766772Sandra 			    end_ptr-it->name - 1);
4770Sstevel@tonic-gate 			res_count ++;
4780Sstevel@tonic-gate 		}
4790Sstevel@tonic-gate 	}
4800Sstevel@tonic-gate 
4810Sstevel@tonic-gate 	/* Terminate array */
4820Sstevel@tonic-gate 	res[res_count] = NULL;
4830Sstevel@tonic-gate 	return (res);
4840Sstevel@tonic-gate }
4850Sstevel@tonic-gate 
4860Sstevel@tonic-gate /*
4870Sstevel@tonic-gate  * FUNCTION :	free_passwd_list()
4880Sstevel@tonic-gate  *
4890Sstevel@tonic-gate  * DESCRIPTION:	Frees a password list obtained with get_passwd_list()
4900Sstevel@tonic-gate  *
4910Sstevel@tonic-gate  * INPUTS :	Address of list to free.
4920Sstevel@tonic-gate  *
4930Sstevel@tonic-gate  * OUTPUTS :	Nothing
4940Sstevel@tonic-gate  */
4950Sstevel@tonic-gate void
free_passwd_list(char ** list)4960Sstevel@tonic-gate free_passwd_list(char **list)
4970Sstevel@tonic-gate {
4980Sstevel@tonic-gate 	free_null_terminated_list(list);
4990Sstevel@tonic-gate }
5000Sstevel@tonic-gate 
5010Sstevel@tonic-gate /*
5020Sstevel@tonic-gate  * FUNCTION :	free_null_terminated_list()
5030Sstevel@tonic-gate  *
5040Sstevel@tonic-gate  * DESCRIPTION:	Frees a generic null terminated list.
5050Sstevel@tonic-gate  *
5060Sstevel@tonic-gate  * INPUTS :	Address of list to free.
5070Sstevel@tonic-gate  *
5080Sstevel@tonic-gate  * OUTPUTS :	Nothing
5090Sstevel@tonic-gate  */
5100Sstevel@tonic-gate void
free_null_terminated_list(char ** list)5110Sstevel@tonic-gate free_null_terminated_list(char **list)
5120Sstevel@tonic-gate {
5130Sstevel@tonic-gate 	int index;
5140Sstevel@tonic-gate 
5150Sstevel@tonic-gate 	/* Free all the strings */
5160Sstevel@tonic-gate 	for (index = 0; NULL != list[index]; index ++)
5170Sstevel@tonic-gate 		sfree(list[index]);
5180Sstevel@tonic-gate 
5190Sstevel@tonic-gate 	/* Free the array */
5200Sstevel@tonic-gate 	sfree(list);
5210Sstevel@tonic-gate }
5220Sstevel@tonic-gate 
5230Sstevel@tonic-gate 
5240Sstevel@tonic-gate /*
5250Sstevel@tonic-gate  * FUNCTION :	add_special_entries()
5260Sstevel@tonic-gate  *
5270Sstevel@tonic-gate  * DESCRIPTION:	Adds the special (YP_*) entries to a map.
5280Sstevel@tonic-gate  *
5290Sstevel@tonic-gate  *		Part of dit_access because requires access to the mapping
5300Sstevel@tonic-gate  *		file in order to work out if secure and interdomain entries
5310Sstevel@tonic-gate  *		should be created.
5320Sstevel@tonic-gate  *
5330Sstevel@tonic-gate  * GIVEN :	Pointer to an open, temporary, DBM file
5340Sstevel@tonic-gate  *		Pointer to map information (do not use DBM fields).
5350Sstevel@tonic-gate  *		Pointer to a location in which to return security flag
5360Sstevel@tonic-gate  *
5370Sstevel@tonic-gate  * RETURNS :	SUCCESS = All entries created
5380Sstevel@tonic-gate  *		FAILURE = Some entries not created
5390Sstevel@tonic-gate  */
5400Sstevel@tonic-gate suc_code
add_special_entries(DBM * db,map_ctrl * map,bool_t * secure_flag)5410Sstevel@tonic-gate add_special_entries(DBM *db, map_ctrl *map, bool_t *secure_flag)
5420Sstevel@tonic-gate {
5430Sstevel@tonic-gate 	char local_host[MAX_MASTER_NAME];
5440Sstevel@tonic-gate 	__nis_table_mapping_t *table_map;
5450Sstevel@tonic-gate 	int res;
5460Sstevel@tonic-gate 
5470Sstevel@tonic-gate 	/* Last modified time is now */
5480Sstevel@tonic-gate 	update_timestamp(db);
5490Sstevel@tonic-gate 
5500Sstevel@tonic-gate 	/* Add domain name */
5510Sstevel@tonic-gate 	addpair(db, yp_domain_name, map->domain);
5520Sstevel@tonic-gate 
5530Sstevel@tonic-gate 	/* For N2L mode local machine is always the master */
5540Sstevel@tonic-gate 	sysinfo(SI_HOSTNAME, local_host, sizeof (local_host));
5550Sstevel@tonic-gate 	addpair(db, yp_master_name, local_host);
5560Sstevel@tonic-gate 
5570Sstevel@tonic-gate 	/*  Get the mapping structure corresponding to `map.domain' */
5580Sstevel@tonic-gate 	table_map = mappingFromMap(map->map_name, map->domain, &res);
5590Sstevel@tonic-gate 	if (0 == table_map)
5600Sstevel@tonic-gate 		return (FAILURE);
5610Sstevel@tonic-gate 
5620Sstevel@tonic-gate 	/* Add secure and interdomain flags if required */
5630Sstevel@tonic-gate 	if (table_map->securemap_flag) {
5640Sstevel@tonic-gate 		addpair(db, yp_secure, "");
5650Sstevel@tonic-gate 		*secure_flag = TRUE;
5660Sstevel@tonic-gate 	} else {
5670Sstevel@tonic-gate 		*secure_flag = FALSE;
5680Sstevel@tonic-gate 	}
5690Sstevel@tonic-gate 	if (table_map->usedns_flag)
5700Sstevel@tonic-gate 		addpair(db, yp_interdomain, "");
5710Sstevel@tonic-gate 
5720Sstevel@tonic-gate 	return (SUCCESS);
5730Sstevel@tonic-gate }
5740Sstevel@tonic-gate 
5750Sstevel@tonic-gate /*
5760Sstevel@tonic-gate  * FUNCTION:	update_map_from_dit()
5770Sstevel@tonic-gate  *
5780Sstevel@tonic-gate  * DESCRIPTION:	Core code called to update an entire map.
5790Sstevel@tonic-gate  *		Information is recovered from LDAP and used to build a duplicate
5800Sstevel@tonic-gate  *		copy of the live maps. When this is complete the maps are
5810Sstevel@tonic-gate  *		locked and then overwritten by the new copy.
5820Sstevel@tonic-gate  *
5830Sstevel@tonic-gate  * INPUTS:	map_ctrl containing lots of information about the map and a
5840Sstevel@tonic-gate  *		pointer to it's lock which will be required.
5850Sstevel@tonic-gate  *		Flag indicating if progress logging is required.
5860Sstevel@tonic-gate  *
5870Sstevel@tonic-gate  * OUTPUTS:	SUCCESS = Map updated
5880Sstevel@tonic-gate  *		FAILURE = Map not updated
5890Sstevel@tonic-gate  */
5900Sstevel@tonic-gate suc_code
update_map_from_dit(map_ctrl * map,bool_t log_flag)5910Sstevel@tonic-gate update_map_from_dit(map_ctrl *map, bool_t log_flag) {
5920Sstevel@tonic-gate 	__nis_table_mapping_t	*t;
5932189Ssdussud 	__nis_rule_value_t	*rv;
5940Sstevel@tonic-gate 	__nis_ldap_search_t	*ls;
5950Sstevel@tonic-gate 	__nis_object_dn_t	*objectDN = NULL;
5960Sstevel@tonic-gate 	datum			*datval, *datkey;
5970Sstevel@tonic-gate 	int			nr = 0, i, j, nv, numDNs;
5980Sstevel@tonic-gate 	int			statP = SUCCESS, flag;
5990Sstevel@tonic-gate 	char			*objname, **dn;
6000Sstevel@tonic-gate 	/* Name of temporary entries DBM file */
6010Sstevel@tonic-gate 	char			*temp_entries;
6020Sstevel@tonic-gate 	/* Name of temporary TTL DBM file */
6030Sstevel@tonic-gate 	char			*temp_ttl;
6040Sstevel@tonic-gate 	/* Temporary DBM handles */
6050Sstevel@tonic-gate 	DBM			*temp_entries_db;
6060Sstevel@tonic-gate 	DBM			*temp_ttl_db;
6070Sstevel@tonic-gate 	map_ctrl		temp_map;
6080Sstevel@tonic-gate 	datum			key;
6090Sstevel@tonic-gate 	char			*myself = "update_map_from_dit";
6100Sstevel@tonic-gate 	bool_t			secure_flag;
6110Sstevel@tonic-gate 	int			entry_count = 1;
6120Sstevel@tonic-gate 	int			next_print = PRINT_FREQ;
6136772Sandra 	int			search_flag = SUCCESS;
6140Sstevel@tonic-gate 
615*13143SBenjamin.Chang@Oracle.COM 	int			m;
616*13143SBenjamin.Chang@Oracle.COM 
617*13143SBenjamin.Chang@Oracle.COM 	/* list of maps whose keys will be transliterated to lowercase */
618*13143SBenjamin.Chang@Oracle.COM 	char			*xlate_to_lcase_maps[] = {
619*13143SBenjamin.Chang@Oracle.COM 		"hosts.byname",
620*13143SBenjamin.Chang@Oracle.COM 		"ipnodes.byname",
621*13143SBenjamin.Chang@Oracle.COM 		NULL
622*13143SBenjamin.Chang@Oracle.COM 	};
623*13143SBenjamin.Chang@Oracle.COM 	bool_t			xlate_to_lcase = FALSE;
624*13143SBenjamin.Chang@Oracle.COM 
6250Sstevel@tonic-gate 	if (!map || !map->map_name || !map->domain) {
6260Sstevel@tonic-gate 		return (FAILURE);
6270Sstevel@tonic-gate 	}
6280Sstevel@tonic-gate 
6290Sstevel@tonic-gate 	__nisdb_get_tsd()->escapeFlag = '\0';
6300Sstevel@tonic-gate 
6310Sstevel@tonic-gate 	/*
6320Sstevel@tonic-gate 	 * netgroup.byxxx maps are a special case. They are regenerated from
6330Sstevel@tonic-gate 	 * the netgroup map, not the DIT, so handle special case.
6340Sstevel@tonic-gate 	 */
6350Sstevel@tonic-gate 	if ((0 == strcmp(map->map_name, NETGROUP_BYHOST)) ||
6360Sstevel@tonic-gate 		0 == (strcmp(map->map_name,  NETGROUP_BYUSER))) {
6370Sstevel@tonic-gate 		return (update_netgroup_byxxx(map));
6380Sstevel@tonic-gate 	}
6390Sstevel@tonic-gate 
6400Sstevel@tonic-gate 	/* Get the mapping information for the map */
6410Sstevel@tonic-gate 	if ((t = mappingFromMap(map->map_name, map->domain, &statP)) == 0) {
6420Sstevel@tonic-gate 		if (statP == MAP_NO_MAPPING_EXISTS)
6430Sstevel@tonic-gate 			logmsg(MSG_NOTIMECHECK, LOG_WARNING,
6440Sstevel@tonic-gate 			"%s: No mapping information available for %s,%s",
6450Sstevel@tonic-gate 				myself, map->map_name, map->domain);
6460Sstevel@tonic-gate 		return (FAILURE);
6470Sstevel@tonic-gate 	}
6480Sstevel@tonic-gate 
6490Sstevel@tonic-gate 	/* Allocate and set up names */
6500Sstevel@tonic-gate 	if (SUCCESS != alloc_temp_names(map->map_path,
6510Sstevel@tonic-gate 				&temp_entries, &temp_ttl)) {
6520Sstevel@tonic-gate 		logmsg(MSG_NOTIMECHECK, LOG_ERR,
6530Sstevel@tonic-gate 			"%s: Unable to create map names for %s",
6540Sstevel@tonic-gate 			myself, map->map_path);
6550Sstevel@tonic-gate 		return (FAILURE);
6560Sstevel@tonic-gate 	}
6570Sstevel@tonic-gate 
6580Sstevel@tonic-gate 	/* Create temp entry and TTL file */
6590Sstevel@tonic-gate 	if ((temp_entries_db = dbm_open(temp_entries, O_RDWR | O_CREAT, 0644))
6600Sstevel@tonic-gate 						== NULL) {
6610Sstevel@tonic-gate 		logmsg(MSG_NOTIMECHECK, LOG_ERR, "%s: Could not open %s",
6620Sstevel@tonic-gate 						myself, temp_entries);
6630Sstevel@tonic-gate 		sfree(temp_entries);
6640Sstevel@tonic-gate 		sfree(temp_ttl);
6650Sstevel@tonic-gate 		return (FAILURE);
6660Sstevel@tonic-gate 	}
6670Sstevel@tonic-gate 
6680Sstevel@tonic-gate 	if ((temp_ttl_db = dbm_open(temp_ttl, O_RDWR | O_CREAT, 0644))
6690Sstevel@tonic-gate 						== NULL) {
6700Sstevel@tonic-gate 		logmsg(MSG_NOTIMECHECK, LOG_ERR, "%s: Could not open %s",
6710Sstevel@tonic-gate 						myself, temp_ttl);
6720Sstevel@tonic-gate 		dbm_close(temp_entries_db);
6730Sstevel@tonic-gate 		delete_map(temp_entries);
6740Sstevel@tonic-gate 		sfree(temp_entries);
6750Sstevel@tonic-gate 		sfree(temp_ttl);
6760Sstevel@tonic-gate 		return (FAILURE);
6770Sstevel@tonic-gate 	}
6780Sstevel@tonic-gate 
6790Sstevel@tonic-gate 	/* Initialize domainContext tsd */
6800Sstevel@tonic-gate 	__nisdb_get_tsd()->domainContext = 0;
6810Sstevel@tonic-gate 	for (i = 0; i < ypDomains.numDomains; i++) {
6820Sstevel@tonic-gate 		if (0 == ypDomains.domainLabels[i])
6830Sstevel@tonic-gate 			continue;
6840Sstevel@tonic-gate 		if (0 == strcasecmp(map->domain, ypDomains.domainLabels[i])) {
6850Sstevel@tonic-gate 			__nisdb_get_tsd()->domainContext = ypDomains.domains[i];
6860Sstevel@tonic-gate 			break;
6870Sstevel@tonic-gate 		}
6880Sstevel@tonic-gate 	}
6890Sstevel@tonic-gate 
6900Sstevel@tonic-gate 	if (!(objname = getFullMapName(map->map_name, map->domain))) {
6910Sstevel@tonic-gate 		if (temp_entries_db)
6920Sstevel@tonic-gate 			dbm_close(temp_entries_db);
6930Sstevel@tonic-gate 		if (temp_ttl_db)
6940Sstevel@tonic-gate 			dbm_close(temp_ttl_db);
6950Sstevel@tonic-gate 		delete_map(temp_entries);
6960Sstevel@tonic-gate 		sfree(temp_entries);
6970Sstevel@tonic-gate 		delete_map(temp_ttl);
6980Sstevel@tonic-gate 		sfree(temp_ttl);
6990Sstevel@tonic-gate 		return (FAILURE);
7000Sstevel@tonic-gate 	}
7010Sstevel@tonic-gate 
702*13143SBenjamin.Chang@Oracle.COM 	/*
703*13143SBenjamin.Chang@Oracle.COM 	 * set xlate_to_lcase to TRUE if map_name is found in
704*13143SBenjamin.Chang@Oracle.COM 	 * xlate_to_lcase_maps[]
705*13143SBenjamin.Chang@Oracle.COM 	 */
706*13143SBenjamin.Chang@Oracle.COM 	m = 0;
707*13143SBenjamin.Chang@Oracle.COM 	while (xlate_to_lcase_maps[m] != NULL) {
708*13143SBenjamin.Chang@Oracle.COM 		if (strncmp(map->map_name, xlate_to_lcase_maps[m],
709*13143SBenjamin.Chang@Oracle.COM 			strlen(xlate_to_lcase_maps[m])) == 0) {
710*13143SBenjamin.Chang@Oracle.COM 			xlate_to_lcase = TRUE;
711*13143SBenjamin.Chang@Oracle.COM 			break;
712*13143SBenjamin.Chang@Oracle.COM 		}
713*13143SBenjamin.Chang@Oracle.COM 		++m;
714*13143SBenjamin.Chang@Oracle.COM 	}
715*13143SBenjamin.Chang@Oracle.COM 
7160Sstevel@tonic-gate 	/* Try each mapping for the map */
7176772Sandra 	for (flag = 0; t != 0 && search_flag != FAILURE; t = t->next) {
7180Sstevel@tonic-gate 
7190Sstevel@tonic-gate 		/* Check if the mapping is the correct one */
7200Sstevel@tonic-gate 		if (strcmp(objname, t->objName) != 0) {
7210Sstevel@tonic-gate 			continue;
7220Sstevel@tonic-gate 		}
7230Sstevel@tonic-gate 
7240Sstevel@tonic-gate 		/* Check if rulesFromLDAP are provided */
7250Sstevel@tonic-gate 		if (t->numRulesFromLDAP == 0) {
7260Sstevel@tonic-gate 			logmsg(MSG_NOTIMECHECK, LOG_ERR,
7270Sstevel@tonic-gate 				"%s: No rulesFromLDAP available for %s (%s)",
7280Sstevel@tonic-gate 				myself, t->dbId, map->map_name);
7290Sstevel@tonic-gate 			continue;
7300Sstevel@tonic-gate 		}
7310Sstevel@tonic-gate 
7320Sstevel@tonic-gate 		/* Set flag to indicate update is enabled */
7330Sstevel@tonic-gate 		flag = 1;
7340Sstevel@tonic-gate 		/* Create ldap request for enumeration */
7350Sstevel@tonic-gate 		for (objectDN = t->objectDN;
7360Sstevel@tonic-gate 				objectDN && objectDN->read.base;
7370Sstevel@tonic-gate 				objectDN = objectDN->next) {
7380Sstevel@tonic-gate 			if ((ls = createLdapRequest(t, 0, 0, 1, NULL,
7390Sstevel@tonic-gate 						objectDN)) == 0) {
7400Sstevel@tonic-gate 				logmsg(MSG_NOTIMECHECK, LOG_ERR,
7410Sstevel@tonic-gate 					"%s: Failed to create "
7420Sstevel@tonic-gate 					"ldapSearch request for "
7430Sstevel@tonic-gate 					"%s (%s) for base %s",
7440Sstevel@tonic-gate 					myself, t->dbId,
7450Sstevel@tonic-gate 					map->map_name,
7460Sstevel@tonic-gate 					objectDN->read.base);
7470Sstevel@tonic-gate 				statP = FAILURE;
7486772Sandra 				search_flag = FAILURE;
7490Sstevel@tonic-gate 				break;
7500Sstevel@tonic-gate 			}
7510Sstevel@tonic-gate 
7520Sstevel@tonic-gate 			if (log_flag) {
7530Sstevel@tonic-gate 				printf("Waiting for LDAP search results.\n");
7540Sstevel@tonic-gate 			}
7550Sstevel@tonic-gate 
7560Sstevel@tonic-gate 			/* Query LDAP */
7570Sstevel@tonic-gate 			nr = (ls->isDN)?0:-1;
7580Sstevel@tonic-gate 			rv = ldapSearch(ls, &nr, 0, &statP);
7590Sstevel@tonic-gate 			freeLdapSearch(ls);
7600Sstevel@tonic-gate 			if (rv == 0) {
7610Sstevel@tonic-gate 				if (statP == LDAP_NO_SUCH_OBJECT) {
7620Sstevel@tonic-gate 				/*
7630Sstevel@tonic-gate 				 * No Entry exists in the ldap server. Not
7640Sstevel@tonic-gate 				 * a problem. Maybe there are just no entries
7650Sstevel@tonic-gate 				 * in this map.
7660Sstevel@tonic-gate 				 */
7670Sstevel@tonic-gate 					continue;
7680Sstevel@tonic-gate 				}
7690Sstevel@tonic-gate 				logmsg(MSG_NOTIMECHECK, LOG_ERR,
7700Sstevel@tonic-gate 					"%s: ldapSearch error %d "
7710Sstevel@tonic-gate 					"(%s) for %s (%s) for base %s",
7720Sstevel@tonic-gate 					myself, statP, ldap_err2string(statP),
7730Sstevel@tonic-gate 					t->dbId, map->map_name,
7740Sstevel@tonic-gate 					objectDN->read.base);
7750Sstevel@tonic-gate 				statP = FAILURE;
7766772Sandra 				search_flag = FAILURE;
7770Sstevel@tonic-gate 				break;
7780Sstevel@tonic-gate 			}
7790Sstevel@tonic-gate 
7800Sstevel@tonic-gate 			if (log_flag) {
7810Sstevel@tonic-gate 				printf("Processing search results.\n");
7820Sstevel@tonic-gate 			}
7830Sstevel@tonic-gate 
7840Sstevel@tonic-gate 			/* Obtain list of DNs for logging */
7850Sstevel@tonic-gate 			if ((dn = findDNs(myself, rv, nr, 0, &numDNs)) == 0) {
7860Sstevel@tonic-gate 				statP = FAILURE;
7876772Sandra 				search_flag = FAILURE;
7880Sstevel@tonic-gate 				break;
7890Sstevel@tonic-gate 			}
7900Sstevel@tonic-gate 
7910Sstevel@tonic-gate 			/* For each entry in the result  do the following */
7920Sstevel@tonic-gate 			for (i = 0; i < nr; i++) {
7930Sstevel@tonic-gate 			/* Convert LDAP data to NIS equivalents */
7940Sstevel@tonic-gate 				statP = buildNISRuleValue(t, &rv[i],
7950Sstevel@tonic-gate 						map->domain);
7960Sstevel@tonic-gate 				if (statP == MAP_INDEXLIST_ERROR)
7970Sstevel@tonic-gate 					continue;
7980Sstevel@tonic-gate 				if (statP != SUCCESS) {
7990Sstevel@tonic-gate 					logmsg(MSG_NOTIMECHECK, LOG_WARNING,
8000Sstevel@tonic-gate 					    "%s: Conversion error %d (LDAP to "
8010Sstevel@tonic-gate 					    "name=value pairs) "
8020Sstevel@tonic-gate 					    "for (dn: %s) for "
8030Sstevel@tonic-gate 					    "%s (%s) for base %s",
8040Sstevel@tonic-gate 					    myself, statP, NIL(dn[i]),
8050Sstevel@tonic-gate 					    t->dbId, map->map_name,
8060Sstevel@tonic-gate 					    objectDN->read.base);
8070Sstevel@tonic-gate 					continue;
8080Sstevel@tonic-gate 				}
8090Sstevel@tonic-gate 
8100Sstevel@tonic-gate 				/* Obtain the datum for value */
8110Sstevel@tonic-gate 				datval = ruleValueToDatum(t, &rv[i], &statP);
8120Sstevel@tonic-gate 				if (datval == 0) {
8130Sstevel@tonic-gate 					logmsg(MSG_NOTIMECHECK, LOG_WARNING,
8140Sstevel@tonic-gate 						"%s: Conversion error %d "
8150Sstevel@tonic-gate 						"(name=value pairs to NIS)"
8160Sstevel@tonic-gate 						" for (dn: %s) for "
8170Sstevel@tonic-gate 						"%s (%s) for base %s",
8180Sstevel@tonic-gate 						myself, statP, NIL(dn[i]),
8190Sstevel@tonic-gate 						t->dbId, map->map_name,
8200Sstevel@tonic-gate 						objectDN->read.base);
8210Sstevel@tonic-gate 					continue;
8220Sstevel@tonic-gate 				}
8230Sstevel@tonic-gate 
8240Sstevel@tonic-gate 				/* Obtain the datum for key */
8250Sstevel@tonic-gate 				datkey = getKeyFromRuleValue(t, &rv[i],
826*13143SBenjamin.Chang@Oracle.COM 				    &nv, &statP, xlate_to_lcase);
8270Sstevel@tonic-gate 				if (datkey == 0) {
8280Sstevel@tonic-gate 					logmsg(MSG_NOTIMECHECK, LOG_WARNING,
8290Sstevel@tonic-gate 						"%s: Unable to obtain NIS "
8300Sstevel@tonic-gate 						"key from LDAP data (dn:%s) "
8310Sstevel@tonic-gate 						"for %s (%s) for base %s",
8320Sstevel@tonic-gate 						myself, NIL(dn[i]), t->dbId,
8330Sstevel@tonic-gate 						map->map_name,
8340Sstevel@tonic-gate 						objectDN->read.base);
8350Sstevel@tonic-gate 					sfree(datval->dptr);
8360Sstevel@tonic-gate 					sfree(datval);
8370Sstevel@tonic-gate 					continue;
8380Sstevel@tonic-gate 				}
8390Sstevel@tonic-gate 
8400Sstevel@tonic-gate 				/* Write to the temporary map */
8410Sstevel@tonic-gate 				for (j = 0; j < nv; j++, entry_count ++) {
8420Sstevel@tonic-gate 					if (datkey[j].dsize == 0)
8430Sstevel@tonic-gate 						continue;
8440Sstevel@tonic-gate 					errno = 0;
8450Sstevel@tonic-gate 					/* DBM_INSERT to match */
8460Sstevel@tonic-gate 					/* singleReadFromDIT */
8470Sstevel@tonic-gate 					if (dbm_store(temp_entries_db,
8480Sstevel@tonic-gate 						datkey[j],
8490Sstevel@tonic-gate 						*datval,
8500Sstevel@tonic-gate 						DBM_INSERT) < 0) {
8510Sstevel@tonic-gate 						/*
8520Sstevel@tonic-gate 						 * For some cases errno may
8530Sstevel@tonic-gate 						 * still be 0 but dbm_error
8540Sstevel@tonic-gate 						 * isn't informative at all.
8550Sstevel@tonic-gate 						 */
8560Sstevel@tonic-gate 						logmsg(MSG_NOTIMECHECK,
8570Sstevel@tonic-gate 						    LOG_WARNING,
8580Sstevel@tonic-gate 						    "%s: dbm store error "
8590Sstevel@tonic-gate 						    "(errno=%d) "
8600Sstevel@tonic-gate 						    "for (key=%s, value=%s) "
8610Sstevel@tonic-gate 						    "for %s (%s) for base %s",
8620Sstevel@tonic-gate 						    myself,
8630Sstevel@tonic-gate 						    errno,
8640Sstevel@tonic-gate 						    datkey[j].dptr,
8650Sstevel@tonic-gate 						    datval->dptr, t->dbId,
8660Sstevel@tonic-gate 						    map->map_name,
8670Sstevel@tonic-gate 						    objectDN->read.base);
8680Sstevel@tonic-gate 						/* clear the error */
8690Sstevel@tonic-gate 						dbm_clearerr(temp_entries_db);
8700Sstevel@tonic-gate 					}
8710Sstevel@tonic-gate 					sfree(datkey[j].dptr);
8720Sstevel@tonic-gate 
8730Sstevel@tonic-gate 					if (log_flag && (entry_count >=
8740Sstevel@tonic-gate 							next_print)) {
8750Sstevel@tonic-gate 						printf("%d entries processed\n",
8760Sstevel@tonic-gate 							entry_count);
8770Sstevel@tonic-gate 						next_print *= 2;
8780Sstevel@tonic-gate 					}
8790Sstevel@tonic-gate 
8800Sstevel@tonic-gate 				}
8810Sstevel@tonic-gate 				sfree(datkey);
8820Sstevel@tonic-gate 				sfree(datval->dptr);
8830Sstevel@tonic-gate 				sfree(datval);
8840Sstevel@tonic-gate 			}
8850Sstevel@tonic-gate 
8860Sstevel@tonic-gate 			freeRuleValue(rv, nr);
8870Sstevel@tonic-gate 			freeDNs(dn, numDNs);
8880Sstevel@tonic-gate 		} /* End of for over objectDN */
8890Sstevel@tonic-gate 	}
8900Sstevel@tonic-gate 	sfree(objname);
8910Sstevel@tonic-gate 
8926772Sandra 	if (t != 0 || flag == 0 || search_flag == FAILURE) {
8930Sstevel@tonic-gate 		if (temp_entries_db)
8940Sstevel@tonic-gate 			dbm_close(temp_entries_db);
8950Sstevel@tonic-gate 		if (temp_ttl_db)
8960Sstevel@tonic-gate 			dbm_close(temp_ttl_db);
8970Sstevel@tonic-gate 		delete_map(temp_entries);
8980Sstevel@tonic-gate 		sfree(temp_entries);
8990Sstevel@tonic-gate 		delete_map(temp_ttl);
9000Sstevel@tonic-gate 		sfree(temp_ttl);
9010Sstevel@tonic-gate 		return (statP);
9020Sstevel@tonic-gate 	}
9030Sstevel@tonic-gate 	/* Set up enough of map_ctrl to call update_entry_ttl */
9040Sstevel@tonic-gate 	temp_map.map_name = map->map_name;
9050Sstevel@tonic-gate 	temp_map.domain = map->domain;
9060Sstevel@tonic-gate 	temp_map.ttl = temp_ttl_db;
9070Sstevel@tonic-gate 
9080Sstevel@tonic-gate 	/* Generate new TTL file */
9090Sstevel@tonic-gate 	key = dbm_firstkey(temp_entries_db);
9100Sstevel@tonic-gate 	while (key.dptr != 0) {
9110Sstevel@tonic-gate 		if (!is_special_key(&key))
9120Sstevel@tonic-gate 			/*
9130Sstevel@tonic-gate 			 * We don't want all the entries to time out at the
9140Sstevel@tonic-gate 			 * same time so create random TTLs.
9150Sstevel@tonic-gate 			 */
9160Sstevel@tonic-gate 			if (FAILURE == update_entry_ttl(&temp_map, &key,
9170Sstevel@tonic-gate 								TTL_RAND))
9180Sstevel@tonic-gate 				logmsg(MSG_NOTIMECHECK, LOG_ERR,
9190Sstevel@tonic-gate 					"%s: Could not update TTL for "
9200Sstevel@tonic-gate 					"(key=%s) for map %s,%s",
9210Sstevel@tonic-gate 					myself, NIL(key.dptr), map->map_name,
9220Sstevel@tonic-gate 					map->domain);
9230Sstevel@tonic-gate 		key = dbm_nextkey(temp_entries_db);
9240Sstevel@tonic-gate 	}
9250Sstevel@tonic-gate 
9260Sstevel@tonic-gate 	/* Update map TTL */
9270Sstevel@tonic-gate 	if (SUCCESS != update_map_ttl(&temp_map)) {
9280Sstevel@tonic-gate 		logmsg(MSG_NOTIMECHECK, LOG_ERR, "%s: Could not update map TTL "
9290Sstevel@tonic-gate 			"for %s,%s", myself, map->map_name, map->domain);
9300Sstevel@tonic-gate 	}
9310Sstevel@tonic-gate 
9320Sstevel@tonic-gate 	/* Set up 'special' nis entries */
9330Sstevel@tonic-gate 	add_special_entries(temp_entries_db, map, &secure_flag);
9340Sstevel@tonic-gate 
9350Sstevel@tonic-gate 	/* Close temp DBM files */
9360Sstevel@tonic-gate 	dbm_close(temp_entries_db);
9370Sstevel@tonic-gate 	dbm_close(temp_ttl_db);
9380Sstevel@tonic-gate 
9390Sstevel@tonic-gate 	/* Lock access to the map for copy */
9400Sstevel@tonic-gate 	lock_map_ctrl(map);
9410Sstevel@tonic-gate 
9420Sstevel@tonic-gate 	/* Move temp maps to real ones */
9430Sstevel@tonic-gate 	rename_map(temp_entries, map->map_path, secure_flag);
9440Sstevel@tonic-gate 	rename_map(temp_ttl, map->ttl_path, secure_flag);
9450Sstevel@tonic-gate 
9460Sstevel@tonic-gate 	/* Free file names */
9470Sstevel@tonic-gate 	sfree(temp_entries);
9480Sstevel@tonic-gate 	sfree(temp_ttl);
9490Sstevel@tonic-gate 
9500Sstevel@tonic-gate 	/* Unlock map */
9510Sstevel@tonic-gate 	unlock_map_ctrl(map);
9520Sstevel@tonic-gate 
9530Sstevel@tonic-gate 	return (SUCCESS);
9540Sstevel@tonic-gate }
9550Sstevel@tonic-gate 
9560Sstevel@tonic-gate /*
9570Sstevel@tonic-gate  * FUNCTION :	get_mapping_map_list()
9580Sstevel@tonic-gate  *
9590Sstevel@tonic-gate  * DESCRIPTION:	Gets a list of nis maps for a given domain specified in the
9600Sstevel@tonic-gate  *		mapping file. This information is not saved so have to go
9610Sstevel@tonic-gate  *		through the entire hash table. At least this is only done at
9620Sstevel@tonic-gate  *		initialization time.
9630Sstevel@tonic-gate  *
9640Sstevel@tonic-gate  * GIVEN :	Domain name
9650Sstevel@tonic-gate  *
9660Sstevel@tonic-gate  * RETURNS :	List of map names in malloced memory. MUST BE FREED BY CALLER.
9670Sstevel@tonic-gate  */
9680Sstevel@tonic-gate char **
get_mapping_map_list(char * domain)9690Sstevel@tonic-gate get_mapping_map_list(char *domain)
9700Sstevel@tonic-gate {
9710Sstevel@tonic-gate 	char *myself = "get_mapping_map_list";
9720Sstevel@tonic-gate 	__nis_hash_item_mt *it;
9730Sstevel@tonic-gate 	int	i, j, size;
9742189Ssdussud 	char 	*end_ptr;
9750Sstevel@tonic-gate 	char	**res;		/* Result array */
9760Sstevel@tonic-gate 	char	**res_old;	/* Old value of res during realloc */
9770Sstevel@tonic-gate 	int	array_size;	/* Current malloced size */
9780Sstevel@tonic-gate 	int	res_count = 0;	/* Current result count */
9790Sstevel@tonic-gate 
9800Sstevel@tonic-gate 	/*
9810Sstevel@tonic-gate 	 * Always need an array even if just for terminator. Normally one
9820Sstevel@tonic-gate 	 * chunk will be enough.
9830Sstevel@tonic-gate 	 */
9840Sstevel@tonic-gate 	res = am(myself, ARRAY_CHUNK * sizeof (char *));
9850Sstevel@tonic-gate 	if (NULL == res)
9860Sstevel@tonic-gate 		return (NULL);
9870Sstevel@tonic-gate 	array_size = ARRAY_CHUNK;
9880Sstevel@tonic-gate 
9890Sstevel@tonic-gate 	/* Work out hash table length */
9900Sstevel@tonic-gate 	size = sizeof (ldapMappingList.keys) / sizeof (ldapMappingList.keys[0]);
9910Sstevel@tonic-gate 	/* For all hash table entries */
9920Sstevel@tonic-gate 	for (i = 0; i < size; i++) {
9930Sstevel@tonic-gate 		/* Walk linked list for this hash table entry */
9940Sstevel@tonic-gate 		for (it = ldapMappingList.keys[i]; NULL != it; it = it->next) {
9950Sstevel@tonic-gate 
9960Sstevel@tonic-gate 			/* Check it's not a split field entry */
9970Sstevel@tonic-gate 			if (0 != ((__nis_table_mapping_t *)it)->numSplits)
9980Sstevel@tonic-gate 				continue;
9990Sstevel@tonic-gate 
10000Sstevel@tonic-gate 			/* Check right domain (minus trailing dot) */
10010Sstevel@tonic-gate 			if (strlen(domain) >= strlen(it->name))
10020Sstevel@tonic-gate 				continue;
10030Sstevel@tonic-gate 			end_ptr = it->name + strlen(it->name) -
10046772Sandra 			    strlen(domain) - 1;
10050Sstevel@tonic-gate 			if (',' != *(end_ptr - 1))
10060Sstevel@tonic-gate 				continue;
10070Sstevel@tonic-gate 			if (0 != strncmp(end_ptr, domain, strlen(domain)))
10080Sstevel@tonic-gate 				continue;
10090Sstevel@tonic-gate 
10100Sstevel@tonic-gate 			/* Check if we need to enlarge array */
10110Sstevel@tonic-gate 			if ((res_count + 1) >= array_size) {
10120Sstevel@tonic-gate 				array_size += ARRAY_CHUNK;
10130Sstevel@tonic-gate 				res_old = res;
10140Sstevel@tonic-gate 				res = realloc(res, array_size *
10156772Sandra 				    sizeof (char *));
10160Sstevel@tonic-gate 				if (NULL == res) {
10170Sstevel@tonic-gate 					res_old[res_count] = NULL;
10180Sstevel@tonic-gate 					free_passwd_list(res_old);
10190Sstevel@tonic-gate 					return (NULL);
10200Sstevel@tonic-gate 				}
10210Sstevel@tonic-gate 			}
10220Sstevel@tonic-gate 
10230Sstevel@tonic-gate 			/*
10240Sstevel@tonic-gate 			 * We will need the sequence number when we come to
10250Sstevel@tonic-gate 			 * sort the entries so for now store a pointer to
10260Sstevel@tonic-gate 			 * the __nis_hash_item_mt.
10270Sstevel@tonic-gate 			 */
10280Sstevel@tonic-gate 			res[res_count] = (char *)it;
10290Sstevel@tonic-gate 			res_count ++;
10300Sstevel@tonic-gate 		}
10310Sstevel@tonic-gate 	}
10320Sstevel@tonic-gate 
10330Sstevel@tonic-gate 	/* Terminate array */
10340Sstevel@tonic-gate 	res[res_count] = NULL;
10350Sstevel@tonic-gate 
10360Sstevel@tonic-gate 	/* Bubble sort entries into the same order as mapping file */
10370Sstevel@tonic-gate 	for (i = res_count - 2; 0 <= i; i--) {
10380Sstevel@tonic-gate 		for (j = 0; j <= i; j++) {
10390Sstevel@tonic-gate 			if (((__nis_table_mapping_t *)res[j + 1])->seq_num <
10406772Sandra 			    ((__nis_table_mapping_t *)res[j])->seq_num) {
10410Sstevel@tonic-gate 				end_ptr = res[j];
10420Sstevel@tonic-gate 				res[j] = res[j+1];
10430Sstevel@tonic-gate 				res[j + 1] = end_ptr;
10440Sstevel@tonic-gate 			}
10450Sstevel@tonic-gate 		}
10460Sstevel@tonic-gate 	}
10470Sstevel@tonic-gate 
10480Sstevel@tonic-gate 	/* Finally copy the real strings in to each entry */
10490Sstevel@tonic-gate 	for (i = 0; NULL != res[i]; i ++) {
10500Sstevel@tonic-gate 
10510Sstevel@tonic-gate 		/* Get hash table entry back */
10520Sstevel@tonic-gate 		it = (__nis_hash_item_mt *)res[i];
10530Sstevel@tonic-gate 
10540Sstevel@tonic-gate 		end_ptr = it->name + strlen(it->name) - strlen(domain) - 1;
10550Sstevel@tonic-gate 
10560Sstevel@tonic-gate 		/* What we really need is strndup() */
10570Sstevel@tonic-gate 		res[i] = am(myself, end_ptr - it->name + 1);
10580Sstevel@tonic-gate 		if (NULL == res[i]) {
10590Sstevel@tonic-gate 			free_map_list(res);
10600Sstevel@tonic-gate 			return (NULL);
10610Sstevel@tonic-gate 		}
10620Sstevel@tonic-gate 
10630Sstevel@tonic-gate 		/* Copy from start to end_ptr */
10642189Ssdussud 		(void) memcpy(res[i], it->name, end_ptr-it->name - 1);
10650Sstevel@tonic-gate 	}
10660Sstevel@tonic-gate 
10670Sstevel@tonic-gate 	return (res);
10680Sstevel@tonic-gate }
10690Sstevel@tonic-gate 
10700Sstevel@tonic-gate /*
10710Sstevel@tonic-gate  * FUNCTION :	make_nis_container()
10720Sstevel@tonic-gate  *
10730Sstevel@tonic-gate  * DESCRIPTION: Sets up container for map_name in the DIT.
10740Sstevel@tonic-gate  *
10750Sstevel@tonic-gate  * GIVEN :	Map name
10760Sstevel@tonic-gate  *		The domain name.
10770Sstevel@tonic-gate  *		Flag indicating if container should be created.
10780Sstevel@tonic-gate  *
10790Sstevel@tonic-gate  * RETURNS :	SUCCESS	= It worked
10800Sstevel@tonic-gate  *		FAILURE	= There was a problem.
10810Sstevel@tonic-gate  */
10820Sstevel@tonic-gate suc_code
make_nis_container(char * map_name,char * domain,bool_t init_containers)10830Sstevel@tonic-gate make_nis_container(char *map_name, char *domain, bool_t init_containers) {
10840Sstevel@tonic-gate 	int			i, rc, statP = SUCCESS;
10850Sstevel@tonic-gate 	__nis_table_mapping_t	*t;
10860Sstevel@tonic-gate 	char			*dn;
10870Sstevel@tonic-gate 	char			*myself = "make_nis_container";
10880Sstevel@tonic-gate 
10890Sstevel@tonic-gate 	if (!map_name || !domain)
10900Sstevel@tonic-gate 		return (FAILURE);
10910Sstevel@tonic-gate 
10920Sstevel@tonic-gate 	if (FALSE == init_containers) {
10930Sstevel@tonic-gate 		/*
10940Sstevel@tonic-gate 		 * If we are not creating containers it is debatable what we
10950Sstevel@tonic-gate 		 * should do . Maybe we should check for a pre-
10960Sstevel@tonic-gate 		 * existing container and return failure if it does not exist.
10970Sstevel@tonic-gate 		 *
10980Sstevel@tonic-gate 		 * For now we assume the user will not have called us in this
10990Sstevel@tonic-gate 		 * mode unless they know what they are doing. So return
11000Sstevel@tonic-gate 		 * success. If they have got it wrong then latter writes will
11010Sstevel@tonic-gate 		 * fail.
11020Sstevel@tonic-gate 		 */
11030Sstevel@tonic-gate 		return (SUCCESS);
11040Sstevel@tonic-gate 	}
11050Sstevel@tonic-gate 
11060Sstevel@tonic-gate 	/* Get the mapping information for the map */
11070Sstevel@tonic-gate 	if ((t = mappingFromMap(map_name, domain, &statP)) == 0) {
11080Sstevel@tonic-gate 		if (statP == MAP_NO_MAPPING_EXISTS)
11090Sstevel@tonic-gate 			logmsg(MSG_NOTIMECHECK, LOG_ERR,
11100Sstevel@tonic-gate 			"%s: No mapping information available for %s,%s",
11110Sstevel@tonic-gate 				myself, NIL(map_name), NIL(domain));
11120Sstevel@tonic-gate 		return (FAILURE);
11130Sstevel@tonic-gate 	}
11140Sstevel@tonic-gate 
11150Sstevel@tonic-gate 	/* Two times. One for readDN and other for writeDN */
11160Sstevel@tonic-gate 	for (i = 0; i < 2; i++) {
11170Sstevel@tonic-gate 		if (i == 0)
11180Sstevel@tonic-gate 			dn = t->objectDN->read.base;
11190Sstevel@tonic-gate 		else {
11200Sstevel@tonic-gate 			if (t->objectDN->write.base == 0) {
11210Sstevel@tonic-gate 				logmsg(MSG_NOTIMECHECK, LOG_INFO,
11220Sstevel@tonic-gate 					"%s: No baseDN in writespec. Write "
11230Sstevel@tonic-gate 					"disabled for %s,%s",
11240Sstevel@tonic-gate 					myself, map_name, domain);
11250Sstevel@tonic-gate 				break;
11260Sstevel@tonic-gate 			}
11270Sstevel@tonic-gate 			if (!strcasecmp(dn, t->objectDN->write.base))
11280Sstevel@tonic-gate 				break;
11290Sstevel@tonic-gate 			dn = t->objectDN->write.base;
11300Sstevel@tonic-gate 		}
11310Sstevel@tonic-gate 
11320Sstevel@tonic-gate 		if ((rc = makeNISObject(0, dn)) == FAILURE) {
11330Sstevel@tonic-gate 			logmsg(MSG_NOTIMECHECK, LOG_ERR,
11340Sstevel@tonic-gate 				"%s: Unable to create ldap container (dn: %s) "
11350Sstevel@tonic-gate 				"for %s,%s", myself, dn, map_name, domain);
11360Sstevel@tonic-gate 			return (FAILURE);
11370Sstevel@tonic-gate 		}
11380Sstevel@tonic-gate 	}
11390Sstevel@tonic-gate 	return (SUCCESS);
11400Sstevel@tonic-gate }
11410Sstevel@tonic-gate 
11420Sstevel@tonic-gate /*
11430Sstevel@tonic-gate  * FUNCTION :	make_nis_domain()
11440Sstevel@tonic-gate  *
11450Sstevel@tonic-gate  * DESCRIPTION:	Sets up a nisDomainObject in the DIT
11460Sstevel@tonic-gate  *
11470Sstevel@tonic-gate  * GIVEN:	Name of the domain
11480Sstevel@tonic-gate  *		Flag indicating if domain should be create or possibly just
11490Sstevel@tonic-gate  *		checked for.
11500Sstevel@tonic-gate  */
11510Sstevel@tonic-gate suc_code
make_nis_domain(char * domain,bool_t init_containers)11520Sstevel@tonic-gate make_nis_domain(char *domain, bool_t init_containers) {
11530Sstevel@tonic-gate 
11540Sstevel@tonic-gate 	if (FALSE == init_containers) {
11550Sstevel@tonic-gate 		/*
11560Sstevel@tonic-gate 		 * If we are not creating containers it is debatable what we
11570Sstevel@tonic-gate 		 * should do with domains. Maybe we should check for a pre-
11580Sstevel@tonic-gate 		 * existing domain and return failure if it does not exist.
11590Sstevel@tonic-gate 		 *
11600Sstevel@tonic-gate 		 * For now we assume the user will not have called us in this
11610Sstevel@tonic-gate 		 * mode unless they know what they are doing. So return
11620Sstevel@tonic-gate 		 * success. If they have got it wrong then latter writes will
11630Sstevel@tonic-gate 		 * fail.
11640Sstevel@tonic-gate 		 */
11650Sstevel@tonic-gate 		return (SUCCESS);
11660Sstevel@tonic-gate 	}
11670Sstevel@tonic-gate 
11680Sstevel@tonic-gate 	/* Create the domain */
11690Sstevel@tonic-gate 	return (makeNISObject(domain, 0));
11700Sstevel@tonic-gate }
11710Sstevel@tonic-gate 
11720Sstevel@tonic-gate /*
11730Sstevel@tonic-gate  * FUNCTION:	update_netgroup_byxxx()
11740Sstevel@tonic-gate  *
11750Sstevel@tonic-gate  * DESCRIPTION:	Updates the netgroup.byxxx series of maps based on the current
11760Sstevel@tonic-gate  *		netgroup file. We invoke revnetgroup so that if any changes
11770Sstevel@tonic-gate  *		are made to this utility the same changes are made here.
11780Sstevel@tonic-gate  *
11790Sstevel@tonic-gate  * INPUTS:	map_ctrl containing lots of information about the map and a
11800Sstevel@tonic-gate  *		pointer to it's lock which will be required.
11810Sstevel@tonic-gate  *
11820Sstevel@tonic-gate  * OUTPUTS:	SUCCESS = Map updated
11830Sstevel@tonic-gate  *		FAILURE = Map not updated
11840Sstevel@tonic-gate  */
11850Sstevel@tonic-gate suc_code
update_netgroup_byxxx(map_ctrl * map)11860Sstevel@tonic-gate update_netgroup_byxxx(map_ctrl *map) {
11870Sstevel@tonic-gate 	/* Name of temporary entries DBM file */
11880Sstevel@tonic-gate 	char			*temp_entries;
11890Sstevel@tonic-gate 	/* Name of temporary TTL DBM file */
11900Sstevel@tonic-gate 	char			*temp_ttl;
11910Sstevel@tonic-gate 	/* Temporary DBM handles */
11920Sstevel@tonic-gate 	DBM			*temp_entries_db;
11930Sstevel@tonic-gate 	DBM			*temp_ttl_db;
11940Sstevel@tonic-gate 	map_ctrl		temp_map;
11950Sstevel@tonic-gate 	char			*myself = "update_netgroup_byxxx";
11960Sstevel@tonic-gate 	char			*cmdbuf;
11970Sstevel@tonic-gate 	int			cmd_length;
11980Sstevel@tonic-gate 	datum			key;
11990Sstevel@tonic-gate 	map_ctrl		*netgroupmap;
12000Sstevel@tonic-gate 	int			res;
12010Sstevel@tonic-gate 	/* Temporary revnetgroup files */
12020Sstevel@tonic-gate 	const char 		*byhost = NETGROUP_BYHOST "_REV" TEMP_POSTFIX;
12030Sstevel@tonic-gate 	const char 		*byuser = NETGROUP_BYUSER "_REV" TEMP_POSTFIX;
12040Sstevel@tonic-gate 	const char		*temp_file_name;
12050Sstevel@tonic-gate 
12060Sstevel@tonic-gate 
12070Sstevel@tonic-gate 	/*
12080Sstevel@tonic-gate 	 * We need to use two different temporary files: one for netgroup.byhost
12090Sstevel@tonic-gate 	 * and other for netgroup.byuser, since these two maps can be updated
12100Sstevel@tonic-gate 	 * simultaneously. These temporary files will hold the output of
12110Sstevel@tonic-gate 	 * revnetgroup [-h|-u] command. They are then used to generate the
12120Sstevel@tonic-gate 	 * corresponding dbm files and thereafter deleted.
12130Sstevel@tonic-gate 	 */
12140Sstevel@tonic-gate 	if (0 == strcmp(map->map_name, NETGROUP_BYHOST))
12150Sstevel@tonic-gate 		temp_file_name = byhost;
12160Sstevel@tonic-gate 	else
12170Sstevel@tonic-gate 		temp_file_name = byuser;
12180Sstevel@tonic-gate 
12190Sstevel@tonic-gate 	/* Alloc enough cmd buf for revnet cmd */
12200Sstevel@tonic-gate 	cmd_length = strlen("/usr/sbin/makedbm -u ") +
12210Sstevel@tonic-gate 			(strlen(map->map_path) - strlen(map->map_name)) +
12220Sstevel@tonic-gate 			strlen(NETGROUP_MAP) +
12230Sstevel@tonic-gate 			strlen(" | /usr/sbin/revnetgroup -h > ") +
12240Sstevel@tonic-gate 			(strlen(map->map_path) - strlen(map->map_name)) +
12250Sstevel@tonic-gate 			strlen(temp_file_name) + 1;
12260Sstevel@tonic-gate 	cmdbuf = am(myself, cmd_length);
12270Sstevel@tonic-gate 
12280Sstevel@tonic-gate 	if (NULL == cmdbuf) {
12290Sstevel@tonic-gate 		logmsg(MSG_NOTIMECHECK, LOG_ERR,
12300Sstevel@tonic-gate 				"%s: Could not alloc cmdbuf.", myself);
12310Sstevel@tonic-gate 		return (FAILURE);
12320Sstevel@tonic-gate 	}
12330Sstevel@tonic-gate 
12340Sstevel@tonic-gate 	/*
12350Sstevel@tonic-gate 	 * If necessary update (and wait for) netgroups map. This is a lot of
12360Sstevel@tonic-gate 	 * work but if the netgroup map itself is not being accessed it may
12370Sstevel@tonic-gate 	 * contain information that is not up to date with the DIT.
12380Sstevel@tonic-gate 	 *
12390Sstevel@tonic-gate 	 * We use the cmdbuf to store the qualified netgroup map name there will
12400Sstevel@tonic-gate 	 * be enough space for this but we are not yet creating the cmd.
12410Sstevel@tonic-gate 	 */
12420Sstevel@tonic-gate 	strlcpy(cmdbuf, map->map_path, strlen(map->map_path) -
12430Sstevel@tonic-gate 						strlen(map->map_name) + 1);
12440Sstevel@tonic-gate 	strcat(cmdbuf, NETGROUP_MAP);
12450Sstevel@tonic-gate 	netgroupmap = (map_ctrl *)shim_dbm_open(cmdbuf,
12460Sstevel@tonic-gate 						O_RDWR | O_CREAT, 0644);
12470Sstevel@tonic-gate 	if (NULL == netgroupmap) {
12480Sstevel@tonic-gate 		logmsg(MSG_NOTIMECHECK, LOG_ERR,
12490Sstevel@tonic-gate 				"%s: Could not update %s.", myself, cmdbuf);
12500Sstevel@tonic-gate 		sfree(cmdbuf);
12510Sstevel@tonic-gate 		return (FAILURE);
12520Sstevel@tonic-gate 	}
12530Sstevel@tonic-gate 
12540Sstevel@tonic-gate 	if (has_map_expired(netgroupmap)) {
12550Sstevel@tonic-gate 		lock_map_ctrl(netgroupmap);
12560Sstevel@tonic-gate 		update_map_if_required(netgroupmap, TRUE);
12570Sstevel@tonic-gate 		unlock_map_ctrl(netgroupmap);
12580Sstevel@tonic-gate 	}
12590Sstevel@tonic-gate 	shim_dbm_close((DBM *)netgroupmap);
12600Sstevel@tonic-gate 
12610Sstevel@tonic-gate 	/* Dump netgroup file through revnetgroup to a temp file */
12620Sstevel@tonic-gate 	strcpy(cmdbuf, "/usr/sbin/makedbm -u ");
12630Sstevel@tonic-gate 
12640Sstevel@tonic-gate 	/* Unmake the netgroup file in same domain as map */
12650Sstevel@tonic-gate 	strncat(cmdbuf, map->map_path, strlen(map->map_path) -
12660Sstevel@tonic-gate 						strlen(map->map_name));
12670Sstevel@tonic-gate 	strcat(cmdbuf, NETGROUP_MAP);
12680Sstevel@tonic-gate 
12690Sstevel@tonic-gate 	if (0 == strcmp(map->map_name, NETGROUP_BYHOST)) {
12700Sstevel@tonic-gate 		strcat(cmdbuf, " | /usr/sbin/revnetgroup -h > ");
12710Sstevel@tonic-gate 	} else {
12720Sstevel@tonic-gate 		strcat(cmdbuf, " | /usr/sbin/revnetgroup -u > ");
12730Sstevel@tonic-gate 	}
12740Sstevel@tonic-gate 
12750Sstevel@tonic-gate 	/* Create temp file file in same domain as map */
12760Sstevel@tonic-gate 	strncat(cmdbuf, map->map_path, strlen(map->map_path) -
12770Sstevel@tonic-gate 						strlen(map->map_name));
12780Sstevel@tonic-gate 	strcat(cmdbuf, temp_file_name);
12790Sstevel@tonic-gate 
12800Sstevel@tonic-gate 	if (0 > system(cmdbuf)) {
12810Sstevel@tonic-gate 		logmsg(MSG_NOTIMECHECK, LOG_ERR, "%s: Could not run \"%s\" "
12820Sstevel@tonic-gate 			"(errno=%d)", myself, cmdbuf, errno);
12830Sstevel@tonic-gate 		sfree(cmdbuf);
12840Sstevel@tonic-gate 		return (FAILURE);
12850Sstevel@tonic-gate 	}
12860Sstevel@tonic-gate 	sfree(cmdbuf);
12870Sstevel@tonic-gate 
12880Sstevel@tonic-gate 	/* Allocate and set up names */
12890Sstevel@tonic-gate 	if (SUCCESS != alloc_temp_names(map->map_path,
12900Sstevel@tonic-gate 				&temp_entries, &temp_ttl)) {
12910Sstevel@tonic-gate 		logmsg(MSG_NOTIMECHECK, LOG_ERR,
12920Sstevel@tonic-gate 			"%s: Unable to create map names for %s",
12930Sstevel@tonic-gate 			myself, map->map_path);
12940Sstevel@tonic-gate 		return (FAILURE);
12950Sstevel@tonic-gate 	}
12960Sstevel@tonic-gate 
12970Sstevel@tonic-gate 	/* Make the temporary DBM file */
12980Sstevel@tonic-gate 	cmdbuf = am(myself, strlen("/usr/sbin/makedbm") +
12990Sstevel@tonic-gate 			(strlen(map->map_path) - strlen(map->map_name)) +
13000Sstevel@tonic-gate 			strlen(temp_file_name) +
13010Sstevel@tonic-gate 			strlen(temp_entries) + 3);
13020Sstevel@tonic-gate 	if (NULL == cmdbuf) {
13030Sstevel@tonic-gate 		logmsg(MSG_NOTIMECHECK, LOG_ERR,
13040Sstevel@tonic-gate 				"%s: Could not allocate cmdbuf.", myself);
13050Sstevel@tonic-gate 		sfree(temp_entries);
13060Sstevel@tonic-gate 		sfree(temp_ttl);
13070Sstevel@tonic-gate 		return (FAILURE);
13080Sstevel@tonic-gate 	}
13090Sstevel@tonic-gate 
13100Sstevel@tonic-gate 	strcpy(cmdbuf, "/usr/sbin/makedbm ");
13110Sstevel@tonic-gate 	strncat(cmdbuf, map->map_path, strlen(map->map_path) -
13120Sstevel@tonic-gate 						strlen(map->map_name));
13130Sstevel@tonic-gate 	strcat(cmdbuf, temp_file_name);
13140Sstevel@tonic-gate 	strcat(cmdbuf, " ");
13150Sstevel@tonic-gate 	strcat(cmdbuf, temp_entries);
13160Sstevel@tonic-gate 
13170Sstevel@tonic-gate 	if (0 > system(cmdbuf)) {
13180Sstevel@tonic-gate 		logmsg(MSG_NOTIMECHECK, LOG_ERR, "%s: Could not run \"%s\" "
13190Sstevel@tonic-gate 			"(errno=%d)", myself, cmdbuf, errno);
13200Sstevel@tonic-gate 		sfree(cmdbuf);
13210Sstevel@tonic-gate 		sfree(temp_entries);
13220Sstevel@tonic-gate 		sfree(temp_ttl);
13230Sstevel@tonic-gate 		return (FAILURE);
13240Sstevel@tonic-gate 	}
13250Sstevel@tonic-gate 
13260Sstevel@tonic-gate 	/* Already have enough command buffer to rm temporary file */
13270Sstevel@tonic-gate 	strlcpy(cmdbuf, map->map_path, strlen(map->map_path) -
13280Sstevel@tonic-gate 						strlen(map->map_name) + 1);
13290Sstevel@tonic-gate 	strcat(cmdbuf, temp_file_name);
13300Sstevel@tonic-gate 	res = unlink(cmdbuf);
13310Sstevel@tonic-gate 	/* If the temp file did not exist no problem. Probably had no entries */
13320Sstevel@tonic-gate 	if ((0 != res) && (ENOENT != errno)) {
13330Sstevel@tonic-gate 		logmsg(MSG_NOTIMECHECK, LOG_ERR, "%s: Could not delete \"%s\" "
13340Sstevel@tonic-gate 			"(errno=%d)", myself, cmdbuf, errno);
13350Sstevel@tonic-gate 		sfree(temp_entries);
13360Sstevel@tonic-gate 		sfree(temp_ttl);
13370Sstevel@tonic-gate 		sfree(cmdbuf);
13380Sstevel@tonic-gate 		return (FAILURE);
13390Sstevel@tonic-gate 	}
13400Sstevel@tonic-gate 	sfree(cmdbuf);
13410Sstevel@tonic-gate 
13420Sstevel@tonic-gate 	if ((temp_entries_db = dbm_open(temp_entries, O_RDWR | O_CREAT, 0644))
13430Sstevel@tonic-gate 						== NULL) {
13440Sstevel@tonic-gate 		logmsg(MSG_NOTIMECHECK, LOG_ERR, "%s: Could not open %s",
13450Sstevel@tonic-gate 						myself, temp_entries);
13460Sstevel@tonic-gate 		sfree(temp_entries);
13470Sstevel@tonic-gate 		sfree(temp_ttl);
13480Sstevel@tonic-gate 		return (FAILURE);
13490Sstevel@tonic-gate 	}
13500Sstevel@tonic-gate 
13510Sstevel@tonic-gate 	if ((temp_ttl_db = dbm_open(temp_ttl, O_RDWR | O_CREAT, 0644))
13520Sstevel@tonic-gate 						== NULL) {
13530Sstevel@tonic-gate 		logmsg(MSG_NOTIMECHECK, LOG_ERR, "%s: Could not open %s",
13540Sstevel@tonic-gate 						myself, temp_ttl);
13550Sstevel@tonic-gate 		dbm_close(temp_entries_db);
13560Sstevel@tonic-gate 		sfree(temp_entries);
13570Sstevel@tonic-gate 		sfree(temp_ttl);
13580Sstevel@tonic-gate 		return (FAILURE);
13590Sstevel@tonic-gate 	}
13600Sstevel@tonic-gate 
13610Sstevel@tonic-gate 	/*
13620Sstevel@tonic-gate 	 * Set up enough of map_ctrl to call update_entry_ttl. Since there is
13630Sstevel@tonic-gate 	 * no mapping, and thus not TTL, defined for these maps use the TTL
13640Sstevel@tonic-gate 	 * values for netgroup map
13650Sstevel@tonic-gate 	 */
13660Sstevel@tonic-gate 	temp_map.map_name = NETGROUP_MAP;
13670Sstevel@tonic-gate 	temp_map.domain = map->domain;
13680Sstevel@tonic-gate 	temp_map.ttl = temp_ttl_db;
13690Sstevel@tonic-gate 
13700Sstevel@tonic-gate 	/*
13710Sstevel@tonic-gate 	 * Generate new TTL file.  Since these maps work only on the whole map
13720Sstevel@tonic-gate 	 * expiry these will not actually be used but there presence makes it
13730Sstevel@tonic-gate 	 * easier to handle these maps in the same way as other maps.
13740Sstevel@tonic-gate 	 */
13750Sstevel@tonic-gate 	key = dbm_firstkey(temp_entries_db);
13760Sstevel@tonic-gate 	while (key.dptr != 0) {
13770Sstevel@tonic-gate 		if (!is_special_key(&key))
13780Sstevel@tonic-gate 			/*
13790Sstevel@tonic-gate 			 * For these maps want all timouts to be maximum
13800Sstevel@tonic-gate 			 */
13810Sstevel@tonic-gate 			if (FAILURE == update_entry_ttl(&temp_map, &key,
13820Sstevel@tonic-gate 								TTL_MAX))
13830Sstevel@tonic-gate 				logmsg(MSG_NOTIMECHECK, LOG_ERR,
13840Sstevel@tonic-gate 					"%s: Could not update TTL for "
13850Sstevel@tonic-gate 					"(key=%s) for map %s,%s",
13860Sstevel@tonic-gate 					myself, NIL(key.dptr), map->map_name,
13870Sstevel@tonic-gate 					map->domain);
13880Sstevel@tonic-gate 		key = dbm_nextkey(temp_entries_db);
13890Sstevel@tonic-gate 	}
13900Sstevel@tonic-gate 
13910Sstevel@tonic-gate 	/* Update map TTL */
13920Sstevel@tonic-gate 	update_map_ttl(&temp_map);
13930Sstevel@tonic-gate 
13940Sstevel@tonic-gate 	/* Close temp DBM files */
13950Sstevel@tonic-gate 	dbm_close(temp_entries_db);
13960Sstevel@tonic-gate 	dbm_close(temp_ttl_db);
13970Sstevel@tonic-gate 
13980Sstevel@tonic-gate 	/* Lock access to the map for copy */
13990Sstevel@tonic-gate 	lock_map_ctrl(map);
14000Sstevel@tonic-gate 
14010Sstevel@tonic-gate 	/* Move temp maps to real ones */
14020Sstevel@tonic-gate 	rename_map(temp_entries, map->map_path, FALSE);
14030Sstevel@tonic-gate 	rename_map(temp_ttl, map->ttl_path, FALSE);
14040Sstevel@tonic-gate 
14050Sstevel@tonic-gate 	/* Free file names */
14060Sstevel@tonic-gate 	sfree(temp_entries);
14070Sstevel@tonic-gate 	sfree(temp_ttl);
14080Sstevel@tonic-gate 
14090Sstevel@tonic-gate 	/* Unlock map */
14100Sstevel@tonic-gate 	unlock_map_ctrl(map);
14110Sstevel@tonic-gate 
14120Sstevel@tonic-gate 	return (SUCCESS);
14130Sstevel@tonic-gate }
1414