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