1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * CDDL HEADER START 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*0Sstevel@tonic-gate * with the License. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*0Sstevel@tonic-gate * See the License for the specific language governing permissions 12*0Sstevel@tonic-gate * and limitations under the License. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * CDDL HEADER END 21*0Sstevel@tonic-gate */ 22*0Sstevel@tonic-gate /* 23*0Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24*0Sstevel@tonic-gate * Use is subject to license terms. 25*0Sstevel@tonic-gate */ 26*0Sstevel@tonic-gate 27*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*0Sstevel@tonic-gate 29*0Sstevel@tonic-gate /* 30*0Sstevel@tonic-gate * DESCRIPTION: Contains top level functions to read/write to the DIT. These 31*0Sstevel@tonic-gate * are the API between the shim and the mapping system. 32*0Sstevel@tonic-gate * Things calling these should have no knowledge of LDAP. Things 33*0Sstevel@tonic-gate * called by them should have no knowledge of NIS. 34*0Sstevel@tonic-gate * 35*0Sstevel@tonic-gate * Error handling here may appear to be limited but, because the 36*0Sstevel@tonic-gate * NIS protocol cannot carry meaningful information about why a 37*0Sstevel@tonic-gate * N2L operation failed, functions that don't work log 38*0Sstevel@tonic-gate * an error and then just return FAILURE. 39*0Sstevel@tonic-gate * 40*0Sstevel@tonic-gate */ 41*0Sstevel@tonic-gate 42*0Sstevel@tonic-gate /* 43*0Sstevel@tonic-gate * Includes. WE WANT TO USE REAL DBM FUNCTIONS SO DO NOT INCLUDE SHIM_HOOKS.H. 44*0Sstevel@tonic-gate */ 45*0Sstevel@tonic-gate #include <unistd.h> 46*0Sstevel@tonic-gate #include <syslog.h> 47*0Sstevel@tonic-gate #include <ndbm.h> 48*0Sstevel@tonic-gate #include <sys/systeminfo.h> 49*0Sstevel@tonic-gate #include <string.h> 50*0Sstevel@tonic-gate #include <lber.h> 51*0Sstevel@tonic-gate #include <ldap.h> 52*0Sstevel@tonic-gate #include <errno.h> 53*0Sstevel@tonic-gate #include "ypsym.h" 54*0Sstevel@tonic-gate #include "ypdefs.h" 55*0Sstevel@tonic-gate #include "shim.h" 56*0Sstevel@tonic-gate #include "../ldap_structs.h" 57*0Sstevel@tonic-gate #include "../ldap_parse.h" 58*0Sstevel@tonic-gate #include "../nisdb_ldap.h" 59*0Sstevel@tonic-gate #include "../ldap_util.h" 60*0Sstevel@tonic-gate #include "../ldap_op.h" 61*0Sstevel@tonic-gate #include "../ldap_attr.h" 62*0Sstevel@tonic-gate #include "../nis_parse_ldap_conf.h" 63*0Sstevel@tonic-gate #include "../nisdb_mt.h" 64*0Sstevel@tonic-gate #include "yptol.h" 65*0Sstevel@tonic-gate #include "dit_access_utils.h" 66*0Sstevel@tonic-gate #include "stdio.h" 67*0Sstevel@tonic-gate 68*0Sstevel@tonic-gate /* Enable standard YP code features defined in ypdefs.h */ 69*0Sstevel@tonic-gate USE_YP_PREFIX 70*0Sstevel@tonic-gate USE_YP_MASTER_NAME 71*0Sstevel@tonic-gate USE_YP_LAST_MODIFIED 72*0Sstevel@tonic-gate USE_YP_INPUT_FILE 73*0Sstevel@tonic-gate USE_YP_OUTPUT_NAME 74*0Sstevel@tonic-gate USE_YP_DOMAIN_NAME 75*0Sstevel@tonic-gate USE_YP_SECURE 76*0Sstevel@tonic-gate USE_YP_INTERDOMAIN 77*0Sstevel@tonic-gate 78*0Sstevel@tonic-gate /* 79*0Sstevel@tonic-gate * Decs 80*0Sstevel@tonic-gate */ 81*0Sstevel@tonic-gate suc_code add_special_entries(DBM *, map_ctrl *, bool_t *); 82*0Sstevel@tonic-gate void free_null_terminated_list(char **list); 83*0Sstevel@tonic-gate 84*0Sstevel@tonic-gate 85*0Sstevel@tonic-gate /* 86*0Sstevel@tonic-gate * FUNCTION: is_yptol_mode(); 87*0Sstevel@tonic-gate * 88*0Sstevel@tonic-gate * DESCRIPTION: Determines if we should run in N2L or traditional mode based 89*0Sstevel@tonic-gate * on the presence of the N2L mapping file. If there are problems 90*0Sstevel@tonic-gate * with the file, e.g. unreadable, this will be picked up latter. 91*0Sstevel@tonic-gate * 92*0Sstevel@tonic-gate * INPUTS: Nothing 93*0Sstevel@tonic-gate * 94*0Sstevel@tonic-gate * OUTPUTS: TRUE = Run in N2L mode 95*0Sstevel@tonic-gate * FALSE = Run in traditional mode. 96*0Sstevel@tonic-gate */ 97*0Sstevel@tonic-gate bool_t 98*0Sstevel@tonic-gate is_yptol_mode() 99*0Sstevel@tonic-gate { 100*0Sstevel@tonic-gate struct stat filestat; 101*0Sstevel@tonic-gate 102*0Sstevel@tonic-gate if (stat(YP_DEFAULTCONFFILE, &filestat) != -1) 103*0Sstevel@tonic-gate return (TRUE); 104*0Sstevel@tonic-gate 105*0Sstevel@tonic-gate return (FALSE); 106*0Sstevel@tonic-gate } 107*0Sstevel@tonic-gate 108*0Sstevel@tonic-gate /* 109*0Sstevel@tonic-gate * FUNCTION: read_from_dit(); 110*0Sstevel@tonic-gate * 111*0Sstevel@tonic-gate * DESCRIPTION: Read (i.e. get and map) a single NIS entry from the LDAP DIT. 112*0Sstevel@tonic-gate * Also handles retry attempts, on failure, and interpretation of 113*0Sstevel@tonic-gate * internal error codes. 114*0Sstevel@tonic-gate * 115*0Sstevel@tonic-gate * INPUTS: Map name (unqualified) 116*0Sstevel@tonic-gate * Domain name 117*0Sstevel@tonic-gate * Entry key 118*0Sstevel@tonic-gate * Pointer to return location 119*0Sstevel@tonic-gate * 120*0Sstevel@tonic-gate * OUTPUTS: If successful DBM datum containing result. 121*0Sstevel@tonic-gate * On error DBM datum pointing to NULL and, if the cached value 122*0Sstevel@tonic-gate * is not to be used, an error code. 123*0Sstevel@tonic-gate */ 124*0Sstevel@tonic-gate int 125*0Sstevel@tonic-gate read_from_dit(char *map, char *domain, datum *key, datum *value) 126*0Sstevel@tonic-gate { 127*0Sstevel@tonic-gate int count; 128*0Sstevel@tonic-gate int res; 129*0Sstevel@tonic-gate __nisdb_retry_t *retrieveRetry; 130*0Sstevel@tonic-gate 131*0Sstevel@tonic-gate /* Initialize tsd */ 132*0Sstevel@tonic-gate __nisdb_get_tsd()->domainContext = 0; 133*0Sstevel@tonic-gate __nisdb_get_tsd()->escapeFlag = '\0'; 134*0Sstevel@tonic-gate 135*0Sstevel@tonic-gate for (count = 0; count < ypDomains.numDomains; count++) { 136*0Sstevel@tonic-gate if (0 == ypDomains.domainLabels[count]) 137*0Sstevel@tonic-gate continue; 138*0Sstevel@tonic-gate if (0 == strcasecmp(domain, ypDomains.domainLabels[count])) { 139*0Sstevel@tonic-gate __nisdb_get_tsd()->domainContext = 140*0Sstevel@tonic-gate ypDomains.domains[count]; 141*0Sstevel@tonic-gate break; 142*0Sstevel@tonic-gate } 143*0Sstevel@tonic-gate } 144*0Sstevel@tonic-gate 145*0Sstevel@tonic-gate retrieveRetry = &ldapDBTableMapping.retrieveErrorRetry; 146*0Sstevel@tonic-gate 147*0Sstevel@tonic-gate /* Loop 'attempts' times of forever if -1 */ 148*0Sstevel@tonic-gate for (count = retrieveRetry->attempts; (0 <= count) || 149*0Sstevel@tonic-gate (-1 == retrieveRetry->attempts); count --) { 150*0Sstevel@tonic-gate if (TRUE == singleReadFromDIT(map, domain, key, value, &res)) 151*0Sstevel@tonic-gate /* It worked, return value irrelevant */ 152*0Sstevel@tonic-gate return (0); 153*0Sstevel@tonic-gate 154*0Sstevel@tonic-gate if (LDAP_TIMEOUT == res) { /* Exceeded search timeout */ 155*0Sstevel@tonic-gate value->dptr = NULL; 156*0Sstevel@tonic-gate return (0); 157*0Sstevel@tonic-gate } 158*0Sstevel@tonic-gate 159*0Sstevel@tonic-gate if (is_fatal_error(res)) 160*0Sstevel@tonic-gate break; 161*0Sstevel@tonic-gate 162*0Sstevel@tonic-gate /* 163*0Sstevel@tonic-gate * Didn't work. If not the special case where no repeats are 164*0Sstevel@tonic-gate * done sleep. 165*0Sstevel@tonic-gate */ 166*0Sstevel@tonic-gate if (0 != retrieveRetry->attempts) 167*0Sstevel@tonic-gate (void) poll(NULL, 0, retrieveRetry->timeout*1000); 168*0Sstevel@tonic-gate } 169*0Sstevel@tonic-gate 170*0Sstevel@tonic-gate /* Make sure returned pointer is NULL */ 171*0Sstevel@tonic-gate value->dptr = NULL; 172*0Sstevel@tonic-gate 173*0Sstevel@tonic-gate /* If we get here access failed work out what to return */ 174*0Sstevel@tonic-gate if (ldapDBTableMapping.retrieveError == use_cached) 175*0Sstevel@tonic-gate return (0); 176*0Sstevel@tonic-gate 177*0Sstevel@tonic-gate return (res); 178*0Sstevel@tonic-gate } 179*0Sstevel@tonic-gate 180*0Sstevel@tonic-gate /* 181*0Sstevel@tonic-gate * FUNCTION: write_to_dit(); 182*0Sstevel@tonic-gate * 183*0Sstevel@tonic-gate * DESCRIPTION: Maps and writes a NIS entry to the LDAP DIT. 184*0Sstevel@tonic-gate * Also handles retry attempts, on failure, and interpretation of 185*0Sstevel@tonic-gate * internal error codes. 186*0Sstevel@tonic-gate * 187*0Sstevel@tonic-gate * INPUTS: Pointer to (unqualified) map name 188*0Sstevel@tonic-gate * Pointer to domain name 189*0Sstevel@tonic-gate * The entries key 190*0Sstevel@tonic-gate * What to write 191*0Sstevel@tonic-gate * Replace flag indicating 192*0Sstevel@tonic-gate * TRUE = Replace (overwrite) any existing entries 193*0Sstevel@tonic-gate * FALSE = Return error if there are existing entries 194*0Sstevel@tonic-gate * Flag indicating if we should tolerate mapping errors. 195*0Sstevel@tonic-gate * 196*0Sstevel@tonic-gate * OUTPUTS: SUCCESS = Write was successful 197*0Sstevel@tonic-gate * FAILURE = Write failed 198*0Sstevel@tonic-gate * 199*0Sstevel@tonic-gate */ 200*0Sstevel@tonic-gate suc_code 201*0Sstevel@tonic-gate write_to_dit(char *map, char *domain, datum key, datum value, 202*0Sstevel@tonic-gate bool_t replace, bool_t ignore_map_errs) 203*0Sstevel@tonic-gate { 204*0Sstevel@tonic-gate int count; 205*0Sstevel@tonic-gate int res; 206*0Sstevel@tonic-gate __nisdb_retry_t *storeRetry = &ldapDBTableMapping.storeErrorRetry; 207*0Sstevel@tonic-gate 208*0Sstevel@tonic-gate /* Initialize tsd */ 209*0Sstevel@tonic-gate __nisdb_get_tsd()->domainContext = 0; 210*0Sstevel@tonic-gate __nisdb_get_tsd()->escapeFlag = '\0'; 211*0Sstevel@tonic-gate 212*0Sstevel@tonic-gate for (count = 0; count < ypDomains.numDomains; count++) { 213*0Sstevel@tonic-gate if (0 == ypDomains.domainLabels[count]) 214*0Sstevel@tonic-gate continue; 215*0Sstevel@tonic-gate if (0 == strcasecmp(domain, ypDomains.domainLabels[count])) { 216*0Sstevel@tonic-gate __nisdb_get_tsd()->domainContext = 217*0Sstevel@tonic-gate ypDomains.domains[count]; 218*0Sstevel@tonic-gate break; 219*0Sstevel@tonic-gate } 220*0Sstevel@tonic-gate } 221*0Sstevel@tonic-gate 222*0Sstevel@tonic-gate storeRetry = &ldapDBTableMapping.storeErrorRetry; 223*0Sstevel@tonic-gate 224*0Sstevel@tonic-gate /* Loop 'attempts' times of forever if -1 */ 225*0Sstevel@tonic-gate for (count = storeRetry->attempts; (0 <= count) || 226*0Sstevel@tonic-gate (-1 == storeRetry->attempts); count --) { 227*0Sstevel@tonic-gate res = singleWriteToDIT(map, domain, &key, &value, replace); 228*0Sstevel@tonic-gate if (LDAP_SUCCESS == res) 229*0Sstevel@tonic-gate return (SUCCESS); 230*0Sstevel@tonic-gate 231*0Sstevel@tonic-gate if (is_fatal_error(res)) { 232*0Sstevel@tonic-gate /* 233*0Sstevel@tonic-gate * The mapping failed and will fail again if it is 234*0Sstevel@tonic-gate * retried. However there are some cases where an 235*0Sstevel@tonic-gate * actual mapping fault (rather than a LDAP problem) 236*0Sstevel@tonic-gate * may be ignored. 237*0Sstevel@tonic-gate */ 238*0Sstevel@tonic-gate if (ignore_map_errs) { 239*0Sstevel@tonic-gate switch (res) { 240*0Sstevel@tonic-gate case LDAP_INVALID_DN_SYNTAX: 241*0Sstevel@tonic-gate case LDAP_OBJECT_CLASS_VIOLATION: 242*0Sstevel@tonic-gate case LDAP_NOT_ALLOWED_ON_RDN: 243*0Sstevel@tonic-gate case MAP_NAMEFIELD_MATCH_ERROR: 244*0Sstevel@tonic-gate case MAP_NO_DN: 245*0Sstevel@tonic-gate return (SUCCESS); 246*0Sstevel@tonic-gate default: 247*0Sstevel@tonic-gate break; 248*0Sstevel@tonic-gate } 249*0Sstevel@tonic-gate } 250*0Sstevel@tonic-gate return (FAILURE); 251*0Sstevel@tonic-gate } 252*0Sstevel@tonic-gate 253*0Sstevel@tonic-gate if (ldapDBTableMapping.storeError != sto_retry) 254*0Sstevel@tonic-gate return (FAILURE); 255*0Sstevel@tonic-gate 256*0Sstevel@tonic-gate /* 257*0Sstevel@tonic-gate * Didn't work. If not the special case where no repeats are 258*0Sstevel@tonic-gate * done sleep. 259*0Sstevel@tonic-gate */ 260*0Sstevel@tonic-gate if (0 != storeRetry->attempts) 261*0Sstevel@tonic-gate (void) poll(NULL, 0, storeRetry->timeout*1000); 262*0Sstevel@tonic-gate 263*0Sstevel@tonic-gate } 264*0Sstevel@tonic-gate return (FAILURE); 265*0Sstevel@tonic-gate } 266*0Sstevel@tonic-gate 267*0Sstevel@tonic-gate /* 268*0Sstevel@tonic-gate * FUNCTION : get_ttl_value() 269*0Sstevel@tonic-gate * 270*0Sstevel@tonic-gate * DESCRIPTION: Get the TTL value, derived from mapping file or DIT, for a 271*0Sstevel@tonic-gate * entry. 272*0Sstevel@tonic-gate * 273*0Sstevel@tonic-gate * GIVEN : Pointer to map 274*0Sstevel@tonic-gate * A flag indication if TTL should be max, min or random 275*0Sstevel@tonic-gate * 276*0Sstevel@tonic-gate * RETURNS : TTL value in seconds. 277*0Sstevel@tonic-gate * -1 on failure 278*0Sstevel@tonic-gate */ 279*0Sstevel@tonic-gate int 280*0Sstevel@tonic-gate get_ttl_value(map_ctrl *map, TTL_TYPE type) 281*0Sstevel@tonic-gate { 282*0Sstevel@tonic-gate __nis_table_mapping_t *table_map; 283*0Sstevel@tonic-gate struct timeval ret; 284*0Sstevel@tonic-gate int interval, res; 285*0Sstevel@tonic-gate char *myself = "get_ttl_value"; 286*0Sstevel@tonic-gate 287*0Sstevel@tonic-gate /* Get the mapping structure corresponding to `map.domain' */ 288*0Sstevel@tonic-gate table_map = mappingFromMap(map->map_name, map->domain, &res); 289*0Sstevel@tonic-gate 290*0Sstevel@tonic-gate if (0 == table_map) { 291*0Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR, 292*0Sstevel@tonic-gate "Get TTL request could not access map %s in domain %s " 293*0Sstevel@tonic-gate "(error %d)", map->map_name, map->domain, res); 294*0Sstevel@tonic-gate return (-1); 295*0Sstevel@tonic-gate } 296*0Sstevel@tonic-gate 297*0Sstevel@tonic-gate switch (type) { 298*0Sstevel@tonic-gate case TTL_MAX: 299*0Sstevel@tonic-gate return (table_map->initTtlHi); 300*0Sstevel@tonic-gate 301*0Sstevel@tonic-gate case TTL_MIN: 302*0Sstevel@tonic-gate return (table_map->initTtlLo); 303*0Sstevel@tonic-gate 304*0Sstevel@tonic-gate default: 305*0Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_INFO, 306*0Sstevel@tonic-gate "%s passed illegal TTL type (%d)", myself, type); 307*0Sstevel@tonic-gate /* If unknown TTL type drop through to TTL_RAND */ 308*0Sstevel@tonic-gate 309*0Sstevel@tonic-gate case TTL_RAND: 310*0Sstevel@tonic-gate interval = table_map->initTtlHi - table_map->initTtlLo; 311*0Sstevel@tonic-gate if (0 >= interval) 312*0Sstevel@tonic-gate return (table_map->initTtlLo); 313*0Sstevel@tonic-gate 314*0Sstevel@tonic-gate /* 315*0Sstevel@tonic-gate * Must get a random value. We assume srand48() got 316*0Sstevel@tonic-gate * called at initialization. 317*0Sstevel@tonic-gate */ 318*0Sstevel@tonic-gate return (lrand48() % interval); 319*0Sstevel@tonic-gate 320*0Sstevel@tonic-gate case TTL_RUNNING: 321*0Sstevel@tonic-gate return (table_map->ttl); 322*0Sstevel@tonic-gate 323*0Sstevel@tonic-gate 324*0Sstevel@tonic-gate } 325*0Sstevel@tonic-gate } 326*0Sstevel@tonic-gate 327*0Sstevel@tonic-gate /* 328*0Sstevel@tonic-gate * FUNCTION : get_mapping_domain_list() 329*0Sstevel@tonic-gate * 330*0Sstevel@tonic-gate * DESCRIPTION: Gets a list of domain names specified, by nisLDAPdomainContext 331*0Sstevel@tonic-gate * attributes, in the mapping file. This is used only for initial 332*0Sstevel@tonic-gate * DIT setup. Once the DIT has been set up get_domain_list() is 333*0Sstevel@tonic-gate * used instead. 334*0Sstevel@tonic-gate * 335*0Sstevel@tonic-gate * GIVEN : Pointer returned array. 336*0Sstevel@tonic-gate * 337*0Sstevel@tonic-gate * RETURNS : Number of element in returned array. 338*0Sstevel@tonic-gate * Array of elements this is in static memory 339*0Sstevel@tonic-gate * and must not be freed by the caller. 340*0Sstevel@tonic-gate */ 341*0Sstevel@tonic-gate int 342*0Sstevel@tonic-gate get_mapping_domain_list(char ***ptr) 343*0Sstevel@tonic-gate { 344*0Sstevel@tonic-gate *ptr = ypDomains.domainLabels; 345*0Sstevel@tonic-gate return (ypDomains.numDomains); 346*0Sstevel@tonic-gate } 347*0Sstevel@tonic-gate 348*0Sstevel@tonic-gate /* 349*0Sstevel@tonic-gate * FUNCTION : get_mapping_yppasswdd_domain_list() 350*0Sstevel@tonic-gate * 351*0Sstevel@tonic-gate * DESCRIPTION: Gets a list of domain names specified, by the 352*0Sstevel@tonic-gate * nisLDAPyppasswddDomains attribute, in the mapping file. This 353*0Sstevel@tonic-gate * is the list of domains for which passwords should be changed. 354*0Sstevel@tonic-gate * 355*0Sstevel@tonic-gate * GIVEN : Pointer returned array 356*0Sstevel@tonic-gate * 357*0Sstevel@tonic-gate * RETURNS : Number of element in returned array. 358*0Sstevel@tonic-gate * 0 if no nisLDAPyppasswddDomains attribute is present. 359*0Sstevel@tonic-gate * Array of elements this is in static memory 360*0Sstevel@tonic-gate * and must not be freed by the caller. 361*0Sstevel@tonic-gate */ 362*0Sstevel@tonic-gate int 363*0Sstevel@tonic-gate get_mapping_yppasswdd_domain_list(char ***ptr) 364*0Sstevel@tonic-gate { 365*0Sstevel@tonic-gate *ptr = ypDomains.yppasswddDomainLabels; 366*0Sstevel@tonic-gate return (ypDomains.numYppasswdd); 367*0Sstevel@tonic-gate } 368*0Sstevel@tonic-gate 369*0Sstevel@tonic-gate /* 370*0Sstevel@tonic-gate * FUNCTION : free_map_list() 371*0Sstevel@tonic-gate * 372*0Sstevel@tonic-gate * DESCRIPTION: Frees a map list. 373*0Sstevel@tonic-gate * 374*0Sstevel@tonic-gate * GIVEN : Pointer to the map list. 375*0Sstevel@tonic-gate * 376*0Sstevel@tonic-gate * RETURNS : Nothing 377*0Sstevel@tonic-gate */ 378*0Sstevel@tonic-gate void 379*0Sstevel@tonic-gate free_map_list(char **map_list) 380*0Sstevel@tonic-gate { 381*0Sstevel@tonic-gate free_null_terminated_list(map_list); 382*0Sstevel@tonic-gate } 383*0Sstevel@tonic-gate 384*0Sstevel@tonic-gate /* 385*0Sstevel@tonic-gate * FUNCTION : get_passwd_list() 386*0Sstevel@tonic-gate * 387*0Sstevel@tonic-gate * DESCRIPTION: Gets a list of either passwd or passwd.adjunct map files 388*0Sstevel@tonic-gate * defined in the mapping file. These are the files which have 389*0Sstevel@tonic-gate * 'magic' nisLDAPdatabaseIdMapping entries aliasing them to 390*0Sstevel@tonic-gate * passwd or passwd.adjunct. This function is required so that 391*0Sstevel@tonic-gate * yppasswdd can work out which maps to synchronize with any 392*0Sstevel@tonic-gate * password changes. 393*0Sstevel@tonic-gate * 394*0Sstevel@tonic-gate * This information is not currently stored by the parser but 395*0Sstevel@tonic-gate * we can recover it from the hash table. This makes hard work but 396*0Sstevel@tonic-gate * passwords should not be changed very frequently 397*0Sstevel@tonic-gate * 398*0Sstevel@tonic-gate * GIVEN : Flag indicating if a list is required for passwd or 399*0Sstevel@tonic-gate * passwd.adjunct 400*0Sstevel@tonic-gate * Domain to return the list for. 401*0Sstevel@tonic-gate * 402*0Sstevel@tonic-gate * RETURNS : Null terminated list of map names in malloced memory. To be 403*0Sstevel@tonic-gate * freed by caller. (Possibly empty if no passwd maps found) 404*0Sstevel@tonic-gate * NULL on error 405*0Sstevel@tonic-gate */ 406*0Sstevel@tonic-gate #define ARRAY_CHUNK 10 407*0Sstevel@tonic-gate char ** 408*0Sstevel@tonic-gate get_passwd_list(bool_t adjunct, char *domain) 409*0Sstevel@tonic-gate { 410*0Sstevel@tonic-gate char *myself = "get_passwd_list"; 411*0Sstevel@tonic-gate __nis_hash_item_mt *it; 412*0Sstevel@tonic-gate int i, size; 413*0Sstevel@tonic-gate char *end_ptr, *copy_ptr; 414*0Sstevel@tonic-gate char *target; /* What we are looking for */ 415*0Sstevel@tonic-gate int target_len; 416*0Sstevel@tonic-gate int domain_len; 417*0Sstevel@tonic-gate char **res; /* Result array */ 418*0Sstevel@tonic-gate char **res_old; /* Old value of res during realloc */ 419*0Sstevel@tonic-gate int array_size; /* Current malloced size */ 420*0Sstevel@tonic-gate int res_count = 0; /* Current result count */ 421*0Sstevel@tonic-gate 422*0Sstevel@tonic-gate /* 423*0Sstevel@tonic-gate * Always need an array even if just for terminator. Normally one 424*0Sstevel@tonic-gate * chunk will be enough. 425*0Sstevel@tonic-gate */ 426*0Sstevel@tonic-gate res = am(myself, ARRAY_CHUNK * sizeof (char *)); 427*0Sstevel@tonic-gate if (NULL == res) 428*0Sstevel@tonic-gate return (NULL); 429*0Sstevel@tonic-gate array_size = ARRAY_CHUNK; 430*0Sstevel@tonic-gate 431*0Sstevel@tonic-gate /* Set up target */ 432*0Sstevel@tonic-gate if (adjunct) 433*0Sstevel@tonic-gate target = PASSWD_ADJUNCT_PREFIX; 434*0Sstevel@tonic-gate else 435*0Sstevel@tonic-gate target = PASSWD_PREFIX; 436*0Sstevel@tonic-gate target_len = strlen(target); 437*0Sstevel@tonic-gate domain_len = strlen(domain); 438*0Sstevel@tonic-gate 439*0Sstevel@tonic-gate /* Work out hash table length */ 440*0Sstevel@tonic-gate size = sizeof (ldapMappingList.keys) / sizeof (ldapMappingList.keys[0]); 441*0Sstevel@tonic-gate /* For all hash table entries */ 442*0Sstevel@tonic-gate for (i = 0; i < size; i++) { 443*0Sstevel@tonic-gate /* Walk linked list for this hash table entry */ 444*0Sstevel@tonic-gate for (it = ldapMappingList.keys[i]; NULL != it; it = it->next) { 445*0Sstevel@tonic-gate /* Check right map */ 446*0Sstevel@tonic-gate if ((target_len + domain_len + 1) > strlen(it->name)) 447*0Sstevel@tonic-gate continue; 448*0Sstevel@tonic-gate if (0 != strncmp(it->name, target, target_len)) 449*0Sstevel@tonic-gate continue; 450*0Sstevel@tonic-gate 451*0Sstevel@tonic-gate /* Check right domain (minus trailing dot) */ 452*0Sstevel@tonic-gate if (strlen(domain) >= strlen(it->name)) 453*0Sstevel@tonic-gate continue; 454*0Sstevel@tonic-gate end_ptr = it->name + strlen(it->name) - 455*0Sstevel@tonic-gate strlen(domain) - 1; 456*0Sstevel@tonic-gate if (',' != *(end_ptr - 1)) 457*0Sstevel@tonic-gate continue; 458*0Sstevel@tonic-gate if (0 != strncmp(end_ptr, domain, strlen(domain))) 459*0Sstevel@tonic-gate continue; 460*0Sstevel@tonic-gate 461*0Sstevel@tonic-gate /* Check if we need to enlarge array */ 462*0Sstevel@tonic-gate if ((res_count + 1) >= array_size) { 463*0Sstevel@tonic-gate array_size += ARRAY_CHUNK; 464*0Sstevel@tonic-gate res_old = res; 465*0Sstevel@tonic-gate res = realloc(res, array_size * 466*0Sstevel@tonic-gate sizeof (char *)); 467*0Sstevel@tonic-gate if (NULL == res) { 468*0Sstevel@tonic-gate res_old[res_count] = NULL; 469*0Sstevel@tonic-gate free_passwd_list(res_old); 470*0Sstevel@tonic-gate return (NULL); 471*0Sstevel@tonic-gate } 472*0Sstevel@tonic-gate } 473*0Sstevel@tonic-gate 474*0Sstevel@tonic-gate /* What we really need is strndup() */ 475*0Sstevel@tonic-gate res[res_count] = am(myself, end_ptr - it->name + 1); 476*0Sstevel@tonic-gate if (NULL == res[res_count]) { 477*0Sstevel@tonic-gate free_passwd_list(res); 478*0Sstevel@tonic-gate return (NULL); 479*0Sstevel@tonic-gate } 480*0Sstevel@tonic-gate 481*0Sstevel@tonic-gate /* Copy from start to end_ptr */ 482*0Sstevel@tonic-gate memcpy(res[res_count], it->name, end_ptr-it->name - 1); 483*0Sstevel@tonic-gate res_count ++; 484*0Sstevel@tonic-gate } 485*0Sstevel@tonic-gate } 486*0Sstevel@tonic-gate 487*0Sstevel@tonic-gate /* Terminate array */ 488*0Sstevel@tonic-gate res[res_count] = NULL; 489*0Sstevel@tonic-gate return (res); 490*0Sstevel@tonic-gate } 491*0Sstevel@tonic-gate 492*0Sstevel@tonic-gate /* 493*0Sstevel@tonic-gate * FUNCTION : free_passwd_list() 494*0Sstevel@tonic-gate * 495*0Sstevel@tonic-gate * DESCRIPTION: Frees a password list obtained with get_passwd_list() 496*0Sstevel@tonic-gate * 497*0Sstevel@tonic-gate * INPUTS : Address of list to free. 498*0Sstevel@tonic-gate * 499*0Sstevel@tonic-gate * OUTPUTS : Nothing 500*0Sstevel@tonic-gate */ 501*0Sstevel@tonic-gate void 502*0Sstevel@tonic-gate free_passwd_list(char **list) 503*0Sstevel@tonic-gate { 504*0Sstevel@tonic-gate free_null_terminated_list(list); 505*0Sstevel@tonic-gate } 506*0Sstevel@tonic-gate 507*0Sstevel@tonic-gate /* 508*0Sstevel@tonic-gate * FUNCTION : free_null_terminated_list() 509*0Sstevel@tonic-gate * 510*0Sstevel@tonic-gate * DESCRIPTION: Frees a generic null terminated list. 511*0Sstevel@tonic-gate * 512*0Sstevel@tonic-gate * INPUTS : Address of list to free. 513*0Sstevel@tonic-gate * 514*0Sstevel@tonic-gate * OUTPUTS : Nothing 515*0Sstevel@tonic-gate */ 516*0Sstevel@tonic-gate void 517*0Sstevel@tonic-gate free_null_terminated_list(char **list) 518*0Sstevel@tonic-gate { 519*0Sstevel@tonic-gate int index; 520*0Sstevel@tonic-gate 521*0Sstevel@tonic-gate /* Free all the strings */ 522*0Sstevel@tonic-gate for (index = 0; NULL != list[index]; index ++) 523*0Sstevel@tonic-gate sfree(list[index]); 524*0Sstevel@tonic-gate 525*0Sstevel@tonic-gate /* Free the array */ 526*0Sstevel@tonic-gate sfree(list); 527*0Sstevel@tonic-gate } 528*0Sstevel@tonic-gate 529*0Sstevel@tonic-gate 530*0Sstevel@tonic-gate /* 531*0Sstevel@tonic-gate * FUNCTION : add_special_entries() 532*0Sstevel@tonic-gate * 533*0Sstevel@tonic-gate * DESCRIPTION: Adds the special (YP_*) entries to a map. 534*0Sstevel@tonic-gate * 535*0Sstevel@tonic-gate * Part of dit_access because requires access to the mapping 536*0Sstevel@tonic-gate * file in order to work out if secure and interdomain entries 537*0Sstevel@tonic-gate * should be created. 538*0Sstevel@tonic-gate * 539*0Sstevel@tonic-gate * GIVEN : Pointer to an open, temporary, DBM file 540*0Sstevel@tonic-gate * Pointer to map information (do not use DBM fields). 541*0Sstevel@tonic-gate * Pointer to a location in which to return security flag 542*0Sstevel@tonic-gate * 543*0Sstevel@tonic-gate * RETURNS : SUCCESS = All entries created 544*0Sstevel@tonic-gate * FAILURE = Some entries not created 545*0Sstevel@tonic-gate */ 546*0Sstevel@tonic-gate suc_code 547*0Sstevel@tonic-gate add_special_entries(DBM *db, map_ctrl *map, bool_t *secure_flag) 548*0Sstevel@tonic-gate { 549*0Sstevel@tonic-gate char local_host[MAX_MASTER_NAME]; 550*0Sstevel@tonic-gate char time_string[MAX_ASCII_ORDER_NUMBER_LENGTH]; 551*0Sstevel@tonic-gate struct timeval now; 552*0Sstevel@tonic-gate __nis_table_mapping_t *table_map; 553*0Sstevel@tonic-gate int res; 554*0Sstevel@tonic-gate 555*0Sstevel@tonic-gate /* Last modified time is now */ 556*0Sstevel@tonic-gate update_timestamp(db); 557*0Sstevel@tonic-gate 558*0Sstevel@tonic-gate /* Add domain name */ 559*0Sstevel@tonic-gate addpair(db, yp_domain_name, map->domain); 560*0Sstevel@tonic-gate 561*0Sstevel@tonic-gate /* For N2L input and output file are meaningless */ 562*0Sstevel@tonic-gate /* addpair(db, yp_input_file, infilename); */ 563*0Sstevel@tonic-gate /* addpair(db, yp_output_file, outfilename); */ 564*0Sstevel@tonic-gate 565*0Sstevel@tonic-gate /* For N2L mode local machine is always the master */ 566*0Sstevel@tonic-gate sysinfo(SI_HOSTNAME, local_host, sizeof (local_host)); 567*0Sstevel@tonic-gate addpair(db, yp_master_name, local_host); 568*0Sstevel@tonic-gate 569*0Sstevel@tonic-gate /* Get the mapping structure corresponding to `map.domain' */ 570*0Sstevel@tonic-gate table_map = mappingFromMap(map->map_name, map->domain, &res); 571*0Sstevel@tonic-gate if (0 == table_map) 572*0Sstevel@tonic-gate return (FAILURE); 573*0Sstevel@tonic-gate 574*0Sstevel@tonic-gate /* Add secure and interdomain flags if required */ 575*0Sstevel@tonic-gate if (table_map->securemap_flag) { 576*0Sstevel@tonic-gate addpair(db, yp_secure, ""); 577*0Sstevel@tonic-gate *secure_flag = TRUE; 578*0Sstevel@tonic-gate } else { 579*0Sstevel@tonic-gate *secure_flag = FALSE; 580*0Sstevel@tonic-gate } 581*0Sstevel@tonic-gate if (table_map->usedns_flag) 582*0Sstevel@tonic-gate addpair(db, yp_interdomain, ""); 583*0Sstevel@tonic-gate 584*0Sstevel@tonic-gate return (SUCCESS); 585*0Sstevel@tonic-gate } 586*0Sstevel@tonic-gate 587*0Sstevel@tonic-gate /* 588*0Sstevel@tonic-gate * FUNCTION: update_map_from_dit() 589*0Sstevel@tonic-gate * 590*0Sstevel@tonic-gate * DESCRIPTION: Core code called to update an entire map. 591*0Sstevel@tonic-gate * Information is recovered from LDAP and used to build a duplicate 592*0Sstevel@tonic-gate * copy of the live maps. When this is complete the maps are 593*0Sstevel@tonic-gate * locked and then overwritten by the new copy. 594*0Sstevel@tonic-gate * 595*0Sstevel@tonic-gate * INPUTS: map_ctrl containing lots of information about the map and a 596*0Sstevel@tonic-gate * pointer to it's lock which will be required. 597*0Sstevel@tonic-gate * Flag indicating if progress logging is required. 598*0Sstevel@tonic-gate * 599*0Sstevel@tonic-gate * OUTPUTS: SUCCESS = Map updated 600*0Sstevel@tonic-gate * FAILURE = Map not updated 601*0Sstevel@tonic-gate */ 602*0Sstevel@tonic-gate suc_code 603*0Sstevel@tonic-gate update_map_from_dit(map_ctrl *map, bool_t log_flag) { 604*0Sstevel@tonic-gate __nis_table_mapping_t *t; 605*0Sstevel@tonic-gate __nis_rule_value_t *rv, *frv; 606*0Sstevel@tonic-gate __nis_ldap_search_t *ls; 607*0Sstevel@tonic-gate __nis_object_dn_t *objectDN = NULL; 608*0Sstevel@tonic-gate datum *datval, *datkey; 609*0Sstevel@tonic-gate int nr = 0, i, j, nv, numDNs; 610*0Sstevel@tonic-gate int statP = SUCCESS, flag; 611*0Sstevel@tonic-gate char *objname, **dn; 612*0Sstevel@tonic-gate /* Name of temporary entries DBM file */ 613*0Sstevel@tonic-gate char *temp_entries; 614*0Sstevel@tonic-gate /* Name of temporary TTL DBM file */ 615*0Sstevel@tonic-gate char *temp_ttl; 616*0Sstevel@tonic-gate /* Temporary DBM handles */ 617*0Sstevel@tonic-gate DBM *temp_entries_db; 618*0Sstevel@tonic-gate DBM *temp_ttl_db; 619*0Sstevel@tonic-gate map_ctrl temp_map; 620*0Sstevel@tonic-gate datum key; 621*0Sstevel@tonic-gate char *myself = "update_map_from_dit"; 622*0Sstevel@tonic-gate bool_t secure_flag; 623*0Sstevel@tonic-gate int entry_count = 1; 624*0Sstevel@tonic-gate int next_print = PRINT_FREQ; 625*0Sstevel@tonic-gate 626*0Sstevel@tonic-gate if (!map || !map->map_name || !map->domain) { 627*0Sstevel@tonic-gate return (FAILURE); 628*0Sstevel@tonic-gate } 629*0Sstevel@tonic-gate 630*0Sstevel@tonic-gate __nisdb_get_tsd()->escapeFlag = '\0'; 631*0Sstevel@tonic-gate 632*0Sstevel@tonic-gate /* 633*0Sstevel@tonic-gate * netgroup.byxxx maps are a special case. They are regenerated from 634*0Sstevel@tonic-gate * the netgroup map, not the DIT, so handle special case. 635*0Sstevel@tonic-gate */ 636*0Sstevel@tonic-gate if ((0 == strcmp(map->map_name, NETGROUP_BYHOST)) || 637*0Sstevel@tonic-gate 0 == (strcmp(map->map_name, NETGROUP_BYUSER))) { 638*0Sstevel@tonic-gate return (update_netgroup_byxxx(map)); 639*0Sstevel@tonic-gate } 640*0Sstevel@tonic-gate 641*0Sstevel@tonic-gate /* Get the mapping information for the map */ 642*0Sstevel@tonic-gate if ((t = mappingFromMap(map->map_name, map->domain, &statP)) == 0) { 643*0Sstevel@tonic-gate if (statP == MAP_NO_MAPPING_EXISTS) 644*0Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_WARNING, 645*0Sstevel@tonic-gate "%s: No mapping information available for %s,%s", 646*0Sstevel@tonic-gate myself, map->map_name, map->domain); 647*0Sstevel@tonic-gate return (FAILURE); 648*0Sstevel@tonic-gate } 649*0Sstevel@tonic-gate 650*0Sstevel@tonic-gate /* Allocate and set up names */ 651*0Sstevel@tonic-gate if (SUCCESS != alloc_temp_names(map->map_path, 652*0Sstevel@tonic-gate &temp_entries, &temp_ttl)) { 653*0Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR, 654*0Sstevel@tonic-gate "%s: Unable to create map names for %s", 655*0Sstevel@tonic-gate myself, map->map_path); 656*0Sstevel@tonic-gate return (FAILURE); 657*0Sstevel@tonic-gate } 658*0Sstevel@tonic-gate 659*0Sstevel@tonic-gate /* Create temp entry and TTL file */ 660*0Sstevel@tonic-gate if ((temp_entries_db = dbm_open(temp_entries, O_RDWR | O_CREAT, 0644)) 661*0Sstevel@tonic-gate == NULL) { 662*0Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR, "%s: Could not open %s", 663*0Sstevel@tonic-gate myself, temp_entries); 664*0Sstevel@tonic-gate sfree(temp_entries); 665*0Sstevel@tonic-gate sfree(temp_ttl); 666*0Sstevel@tonic-gate return (FAILURE); 667*0Sstevel@tonic-gate } 668*0Sstevel@tonic-gate 669*0Sstevel@tonic-gate if ((temp_ttl_db = dbm_open(temp_ttl, O_RDWR | O_CREAT, 0644)) 670*0Sstevel@tonic-gate == NULL) { 671*0Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR, "%s: Could not open %s", 672*0Sstevel@tonic-gate myself, temp_ttl); 673*0Sstevel@tonic-gate dbm_close(temp_entries_db); 674*0Sstevel@tonic-gate delete_map(temp_entries); 675*0Sstevel@tonic-gate sfree(temp_entries); 676*0Sstevel@tonic-gate sfree(temp_ttl); 677*0Sstevel@tonic-gate return (FAILURE); 678*0Sstevel@tonic-gate } 679*0Sstevel@tonic-gate 680*0Sstevel@tonic-gate /* Initialize domainContext tsd */ 681*0Sstevel@tonic-gate __nisdb_get_tsd()->domainContext = 0; 682*0Sstevel@tonic-gate for (i = 0; i < ypDomains.numDomains; i++) { 683*0Sstevel@tonic-gate if (0 == ypDomains.domainLabels[i]) 684*0Sstevel@tonic-gate continue; 685*0Sstevel@tonic-gate if (0 == strcasecmp(map->domain, ypDomains.domainLabels[i])) { 686*0Sstevel@tonic-gate __nisdb_get_tsd()->domainContext = ypDomains.domains[i]; 687*0Sstevel@tonic-gate break; 688*0Sstevel@tonic-gate } 689*0Sstevel@tonic-gate } 690*0Sstevel@tonic-gate 691*0Sstevel@tonic-gate if (!(objname = getFullMapName(map->map_name, map->domain))) { 692*0Sstevel@tonic-gate if (temp_entries_db) 693*0Sstevel@tonic-gate dbm_close(temp_entries_db); 694*0Sstevel@tonic-gate if (temp_ttl_db) 695*0Sstevel@tonic-gate dbm_close(temp_ttl_db); 696*0Sstevel@tonic-gate delete_map(temp_entries); 697*0Sstevel@tonic-gate sfree(temp_entries); 698*0Sstevel@tonic-gate delete_map(temp_ttl); 699*0Sstevel@tonic-gate sfree(temp_ttl); 700*0Sstevel@tonic-gate return (FAILURE); 701*0Sstevel@tonic-gate } 702*0Sstevel@tonic-gate 703*0Sstevel@tonic-gate /* Try each mapping for the map */ 704*0Sstevel@tonic-gate for (flag = 0; t != 0; t = t->next) { 705*0Sstevel@tonic-gate 706*0Sstevel@tonic-gate /* Check if the mapping is the correct one */ 707*0Sstevel@tonic-gate if (strcmp(objname, t->objName) != 0) { 708*0Sstevel@tonic-gate continue; 709*0Sstevel@tonic-gate } 710*0Sstevel@tonic-gate 711*0Sstevel@tonic-gate /* Check if rulesFromLDAP are provided */ 712*0Sstevel@tonic-gate if (t->numRulesFromLDAP == 0) { 713*0Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR, 714*0Sstevel@tonic-gate "%s: No rulesFromLDAP available for %s (%s)", 715*0Sstevel@tonic-gate myself, t->dbId, map->map_name); 716*0Sstevel@tonic-gate continue; 717*0Sstevel@tonic-gate } 718*0Sstevel@tonic-gate 719*0Sstevel@tonic-gate /* Set flag to indicate update is enabled */ 720*0Sstevel@tonic-gate flag = 1; 721*0Sstevel@tonic-gate /* Create ldap request for enumeration */ 722*0Sstevel@tonic-gate for (objectDN = t->objectDN; 723*0Sstevel@tonic-gate objectDN && objectDN->read.base; 724*0Sstevel@tonic-gate objectDN = objectDN->next) { 725*0Sstevel@tonic-gate if ((ls = createLdapRequest(t, 0, 0, 1, NULL, 726*0Sstevel@tonic-gate objectDN)) == 0) { 727*0Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR, 728*0Sstevel@tonic-gate "%s: Failed to create " 729*0Sstevel@tonic-gate "ldapSearch request for " 730*0Sstevel@tonic-gate "%s (%s) for base %s", 731*0Sstevel@tonic-gate myself, t->dbId, 732*0Sstevel@tonic-gate map->map_name, 733*0Sstevel@tonic-gate objectDN->read.base); 734*0Sstevel@tonic-gate statP = FAILURE; 735*0Sstevel@tonic-gate break; 736*0Sstevel@tonic-gate } 737*0Sstevel@tonic-gate 738*0Sstevel@tonic-gate if (log_flag) { 739*0Sstevel@tonic-gate printf("Waiting for LDAP search results.\n"); 740*0Sstevel@tonic-gate } 741*0Sstevel@tonic-gate 742*0Sstevel@tonic-gate /* Query LDAP */ 743*0Sstevel@tonic-gate nr = (ls->isDN)?0:-1; 744*0Sstevel@tonic-gate rv = ldapSearch(ls, &nr, 0, &statP); 745*0Sstevel@tonic-gate freeLdapSearch(ls); 746*0Sstevel@tonic-gate if (rv == 0) { 747*0Sstevel@tonic-gate if (statP == LDAP_NO_SUCH_OBJECT) { 748*0Sstevel@tonic-gate /* 749*0Sstevel@tonic-gate * No Entry exists in the ldap server. Not 750*0Sstevel@tonic-gate * a problem. Maybe there are just no entries 751*0Sstevel@tonic-gate * in this map. 752*0Sstevel@tonic-gate */ 753*0Sstevel@tonic-gate continue; 754*0Sstevel@tonic-gate } 755*0Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR, 756*0Sstevel@tonic-gate "%s: ldapSearch error %d " 757*0Sstevel@tonic-gate "(%s) for %s (%s) for base %s", 758*0Sstevel@tonic-gate myself, statP, ldap_err2string(statP), 759*0Sstevel@tonic-gate t->dbId, map->map_name, 760*0Sstevel@tonic-gate objectDN->read.base); 761*0Sstevel@tonic-gate statP = FAILURE; 762*0Sstevel@tonic-gate break; 763*0Sstevel@tonic-gate } 764*0Sstevel@tonic-gate 765*0Sstevel@tonic-gate if (log_flag) { 766*0Sstevel@tonic-gate printf("Processing search results.\n"); 767*0Sstevel@tonic-gate } 768*0Sstevel@tonic-gate 769*0Sstevel@tonic-gate /* Obtain list of DNs for logging */ 770*0Sstevel@tonic-gate if ((dn = findDNs(myself, rv, nr, 0, &numDNs)) == 0) { 771*0Sstevel@tonic-gate statP = FAILURE; 772*0Sstevel@tonic-gate break; 773*0Sstevel@tonic-gate } 774*0Sstevel@tonic-gate 775*0Sstevel@tonic-gate /* For each entry in the result do the following */ 776*0Sstevel@tonic-gate for (i = 0; i < nr; i++) { 777*0Sstevel@tonic-gate /* Convert LDAP data to NIS equivalents */ 778*0Sstevel@tonic-gate statP = buildNISRuleValue(t, &rv[i], 779*0Sstevel@tonic-gate map->domain); 780*0Sstevel@tonic-gate if (statP == MAP_INDEXLIST_ERROR) 781*0Sstevel@tonic-gate continue; 782*0Sstevel@tonic-gate if (statP != SUCCESS) { 783*0Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_WARNING, 784*0Sstevel@tonic-gate "%s: Conversion error %d (LDAP to " 785*0Sstevel@tonic-gate "name=value pairs) " 786*0Sstevel@tonic-gate "for (dn: %s) for " 787*0Sstevel@tonic-gate "%s (%s) for base %s", 788*0Sstevel@tonic-gate myself, statP, NIL(dn[i]), 789*0Sstevel@tonic-gate t->dbId, map->map_name, 790*0Sstevel@tonic-gate objectDN->read.base); 791*0Sstevel@tonic-gate continue; 792*0Sstevel@tonic-gate } 793*0Sstevel@tonic-gate 794*0Sstevel@tonic-gate /* Obtain the datum for value */ 795*0Sstevel@tonic-gate datval = ruleValueToDatum(t, &rv[i], &statP); 796*0Sstevel@tonic-gate if (datval == 0) { 797*0Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_WARNING, 798*0Sstevel@tonic-gate "%s: Conversion error %d " 799*0Sstevel@tonic-gate "(name=value pairs to NIS)" 800*0Sstevel@tonic-gate " for (dn: %s) for " 801*0Sstevel@tonic-gate "%s (%s) for base %s", 802*0Sstevel@tonic-gate myself, statP, NIL(dn[i]), 803*0Sstevel@tonic-gate t->dbId, map->map_name, 804*0Sstevel@tonic-gate objectDN->read.base); 805*0Sstevel@tonic-gate continue; 806*0Sstevel@tonic-gate } 807*0Sstevel@tonic-gate 808*0Sstevel@tonic-gate /* Obtain the datum for key */ 809*0Sstevel@tonic-gate datkey = getKeyFromRuleValue(t, &rv[i], 810*0Sstevel@tonic-gate &nv, &statP); 811*0Sstevel@tonic-gate if (datkey == 0) { 812*0Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_WARNING, 813*0Sstevel@tonic-gate "%s: Unable to obtain NIS " 814*0Sstevel@tonic-gate "key from LDAP data (dn:%s) " 815*0Sstevel@tonic-gate "for %s (%s) for base %s", 816*0Sstevel@tonic-gate myself, NIL(dn[i]), t->dbId, 817*0Sstevel@tonic-gate map->map_name, 818*0Sstevel@tonic-gate objectDN->read.base); 819*0Sstevel@tonic-gate sfree(datval->dptr); 820*0Sstevel@tonic-gate sfree(datval); 821*0Sstevel@tonic-gate continue; 822*0Sstevel@tonic-gate } 823*0Sstevel@tonic-gate 824*0Sstevel@tonic-gate /* Write to the temporary map */ 825*0Sstevel@tonic-gate for (j = 0; j < nv; j++, entry_count ++) { 826*0Sstevel@tonic-gate if (datkey[j].dsize == 0) 827*0Sstevel@tonic-gate continue; 828*0Sstevel@tonic-gate errno = 0; 829*0Sstevel@tonic-gate /* DBM_INSERT to match */ 830*0Sstevel@tonic-gate /* singleReadFromDIT */ 831*0Sstevel@tonic-gate if (dbm_store(temp_entries_db, 832*0Sstevel@tonic-gate datkey[j], 833*0Sstevel@tonic-gate *datval, 834*0Sstevel@tonic-gate DBM_INSERT) < 0) { 835*0Sstevel@tonic-gate /* 836*0Sstevel@tonic-gate * For some cases errno may 837*0Sstevel@tonic-gate * still be 0 but dbm_error 838*0Sstevel@tonic-gate * isn't informative at all. 839*0Sstevel@tonic-gate */ 840*0Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, 841*0Sstevel@tonic-gate LOG_WARNING, 842*0Sstevel@tonic-gate "%s: dbm store error " 843*0Sstevel@tonic-gate "(errno=%d) " 844*0Sstevel@tonic-gate "for (key=%s, value=%s) " 845*0Sstevel@tonic-gate "for %s (%s) for base %s", 846*0Sstevel@tonic-gate myself, 847*0Sstevel@tonic-gate errno, 848*0Sstevel@tonic-gate datkey[j].dptr, 849*0Sstevel@tonic-gate datval->dptr, t->dbId, 850*0Sstevel@tonic-gate map->map_name, 851*0Sstevel@tonic-gate objectDN->read.base); 852*0Sstevel@tonic-gate /* clear the error */ 853*0Sstevel@tonic-gate dbm_clearerr(temp_entries_db); 854*0Sstevel@tonic-gate } 855*0Sstevel@tonic-gate sfree(datkey[j].dptr); 856*0Sstevel@tonic-gate 857*0Sstevel@tonic-gate if (log_flag && (entry_count >= 858*0Sstevel@tonic-gate next_print)) { 859*0Sstevel@tonic-gate printf("%d entries processed\n", 860*0Sstevel@tonic-gate entry_count); 861*0Sstevel@tonic-gate next_print *= 2; 862*0Sstevel@tonic-gate } 863*0Sstevel@tonic-gate 864*0Sstevel@tonic-gate } 865*0Sstevel@tonic-gate sfree(datkey); 866*0Sstevel@tonic-gate sfree(datval->dptr); 867*0Sstevel@tonic-gate sfree(datval); 868*0Sstevel@tonic-gate } 869*0Sstevel@tonic-gate 870*0Sstevel@tonic-gate freeRuleValue(rv, nr); 871*0Sstevel@tonic-gate freeDNs(dn, numDNs); 872*0Sstevel@tonic-gate } /* End of for over objectDN */ 873*0Sstevel@tonic-gate } 874*0Sstevel@tonic-gate sfree(objname); 875*0Sstevel@tonic-gate 876*0Sstevel@tonic-gate if (t != 0 || flag == 0) { 877*0Sstevel@tonic-gate if (temp_entries_db) 878*0Sstevel@tonic-gate dbm_close(temp_entries_db); 879*0Sstevel@tonic-gate if (temp_ttl_db) 880*0Sstevel@tonic-gate dbm_close(temp_ttl_db); 881*0Sstevel@tonic-gate delete_map(temp_entries); 882*0Sstevel@tonic-gate sfree(temp_entries); 883*0Sstevel@tonic-gate delete_map(temp_ttl); 884*0Sstevel@tonic-gate sfree(temp_ttl); 885*0Sstevel@tonic-gate return (statP); 886*0Sstevel@tonic-gate } 887*0Sstevel@tonic-gate /* Set up enough of map_ctrl to call update_entry_ttl */ 888*0Sstevel@tonic-gate temp_map.map_name = map->map_name; 889*0Sstevel@tonic-gate temp_map.domain = map->domain; 890*0Sstevel@tonic-gate temp_map.ttl = temp_ttl_db; 891*0Sstevel@tonic-gate 892*0Sstevel@tonic-gate /* Generate new TTL file */ 893*0Sstevel@tonic-gate key = dbm_firstkey(temp_entries_db); 894*0Sstevel@tonic-gate while (key.dptr != 0) { 895*0Sstevel@tonic-gate if (!is_special_key(&key)) 896*0Sstevel@tonic-gate /* 897*0Sstevel@tonic-gate * We don't want all the entries to time out at the 898*0Sstevel@tonic-gate * same time so create random TTLs. 899*0Sstevel@tonic-gate */ 900*0Sstevel@tonic-gate if (FAILURE == update_entry_ttl(&temp_map, &key, 901*0Sstevel@tonic-gate TTL_RAND)) 902*0Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR, 903*0Sstevel@tonic-gate "%s: Could not update TTL for " 904*0Sstevel@tonic-gate "(key=%s) for map %s,%s", 905*0Sstevel@tonic-gate myself, NIL(key.dptr), map->map_name, 906*0Sstevel@tonic-gate map->domain); 907*0Sstevel@tonic-gate key = dbm_nextkey(temp_entries_db); 908*0Sstevel@tonic-gate } 909*0Sstevel@tonic-gate 910*0Sstevel@tonic-gate /* Update map TTL */ 911*0Sstevel@tonic-gate if (SUCCESS != update_map_ttl(&temp_map)) { 912*0Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR, "%s: Could not update map TTL " 913*0Sstevel@tonic-gate "for %s,%s", myself, map->map_name, map->domain); 914*0Sstevel@tonic-gate } 915*0Sstevel@tonic-gate 916*0Sstevel@tonic-gate /* Set up 'special' nis entries */ 917*0Sstevel@tonic-gate add_special_entries(temp_entries_db, map, &secure_flag); 918*0Sstevel@tonic-gate 919*0Sstevel@tonic-gate /* Close temp DBM files */ 920*0Sstevel@tonic-gate dbm_close(temp_entries_db); 921*0Sstevel@tonic-gate dbm_close(temp_ttl_db); 922*0Sstevel@tonic-gate 923*0Sstevel@tonic-gate /* Lock access to the map for copy */ 924*0Sstevel@tonic-gate lock_map_ctrl(map); 925*0Sstevel@tonic-gate 926*0Sstevel@tonic-gate /* Move temp maps to real ones */ 927*0Sstevel@tonic-gate rename_map(temp_entries, map->map_path, secure_flag); 928*0Sstevel@tonic-gate rename_map(temp_ttl, map->ttl_path, secure_flag); 929*0Sstevel@tonic-gate 930*0Sstevel@tonic-gate /* Free file names */ 931*0Sstevel@tonic-gate sfree(temp_entries); 932*0Sstevel@tonic-gate sfree(temp_ttl); 933*0Sstevel@tonic-gate 934*0Sstevel@tonic-gate /* Unlock map */ 935*0Sstevel@tonic-gate unlock_map_ctrl(map); 936*0Sstevel@tonic-gate 937*0Sstevel@tonic-gate return (SUCCESS); 938*0Sstevel@tonic-gate } 939*0Sstevel@tonic-gate 940*0Sstevel@tonic-gate /* 941*0Sstevel@tonic-gate * FUNCTION : get_mapping_map_list() 942*0Sstevel@tonic-gate * 943*0Sstevel@tonic-gate * DESCRIPTION: Gets a list of nis maps for a given domain specified in the 944*0Sstevel@tonic-gate * mapping file. This information is not saved so have to go 945*0Sstevel@tonic-gate * through the entire hash table. At least this is only done at 946*0Sstevel@tonic-gate * initialization time. 947*0Sstevel@tonic-gate * 948*0Sstevel@tonic-gate * GIVEN : Domain name 949*0Sstevel@tonic-gate * 950*0Sstevel@tonic-gate * RETURNS : List of map names in malloced memory. MUST BE FREED BY CALLER. 951*0Sstevel@tonic-gate */ 952*0Sstevel@tonic-gate char ** 953*0Sstevel@tonic-gate get_mapping_map_list(char *domain) 954*0Sstevel@tonic-gate { 955*0Sstevel@tonic-gate char *myself = "get_mapping_map_list"; 956*0Sstevel@tonic-gate __nis_hash_item_mt *it; 957*0Sstevel@tonic-gate int i, j, size; 958*0Sstevel@tonic-gate char *end_ptr, *copy_ptr; 959*0Sstevel@tonic-gate char **res; /* Result array */ 960*0Sstevel@tonic-gate char **res_old; /* Old value of res during realloc */ 961*0Sstevel@tonic-gate int array_size; /* Current malloced size */ 962*0Sstevel@tonic-gate int res_count = 0; /* Current result count */ 963*0Sstevel@tonic-gate 964*0Sstevel@tonic-gate /* 965*0Sstevel@tonic-gate * Always need an array even if just for terminator. Normally one 966*0Sstevel@tonic-gate * chunk will be enough. 967*0Sstevel@tonic-gate */ 968*0Sstevel@tonic-gate res = am(myself, ARRAY_CHUNK * sizeof (char *)); 969*0Sstevel@tonic-gate if (NULL == res) 970*0Sstevel@tonic-gate return (NULL); 971*0Sstevel@tonic-gate array_size = ARRAY_CHUNK; 972*0Sstevel@tonic-gate 973*0Sstevel@tonic-gate /* Work out hash table length */ 974*0Sstevel@tonic-gate size = sizeof (ldapMappingList.keys) / sizeof (ldapMappingList.keys[0]); 975*0Sstevel@tonic-gate /* For all hash table entries */ 976*0Sstevel@tonic-gate for (i = 0; i < size; i++) { 977*0Sstevel@tonic-gate /* Walk linked list for this hash table entry */ 978*0Sstevel@tonic-gate for (it = ldapMappingList.keys[i]; NULL != it; it = it->next) { 979*0Sstevel@tonic-gate 980*0Sstevel@tonic-gate /* Check it's not a split field entry */ 981*0Sstevel@tonic-gate if (0 != ((__nis_table_mapping_t *)it)->numSplits) 982*0Sstevel@tonic-gate continue; 983*0Sstevel@tonic-gate 984*0Sstevel@tonic-gate /* Check right domain (minus trailing dot) */ 985*0Sstevel@tonic-gate if (strlen(domain) >= strlen(it->name)) 986*0Sstevel@tonic-gate continue; 987*0Sstevel@tonic-gate end_ptr = it->name + strlen(it->name) - 988*0Sstevel@tonic-gate strlen(domain) - 1; 989*0Sstevel@tonic-gate if (',' != *(end_ptr - 1)) 990*0Sstevel@tonic-gate continue; 991*0Sstevel@tonic-gate if (0 != strncmp(end_ptr, domain, strlen(domain))) 992*0Sstevel@tonic-gate continue; 993*0Sstevel@tonic-gate 994*0Sstevel@tonic-gate /* Check if we need to enlarge array */ 995*0Sstevel@tonic-gate if ((res_count + 1) >= array_size) { 996*0Sstevel@tonic-gate array_size += ARRAY_CHUNK; 997*0Sstevel@tonic-gate res_old = res; 998*0Sstevel@tonic-gate res = realloc(res, array_size * 999*0Sstevel@tonic-gate sizeof (char *)); 1000*0Sstevel@tonic-gate if (NULL == res) { 1001*0Sstevel@tonic-gate res_old[res_count] = NULL; 1002*0Sstevel@tonic-gate free_passwd_list(res_old); 1003*0Sstevel@tonic-gate return (NULL); 1004*0Sstevel@tonic-gate } 1005*0Sstevel@tonic-gate } 1006*0Sstevel@tonic-gate 1007*0Sstevel@tonic-gate /* 1008*0Sstevel@tonic-gate * We will need the sequence number when we come to 1009*0Sstevel@tonic-gate * sort the entries so for now store a pointer to 1010*0Sstevel@tonic-gate * the __nis_hash_item_mt. 1011*0Sstevel@tonic-gate */ 1012*0Sstevel@tonic-gate res[res_count] = (char *)it; 1013*0Sstevel@tonic-gate res_count ++; 1014*0Sstevel@tonic-gate } 1015*0Sstevel@tonic-gate } 1016*0Sstevel@tonic-gate 1017*0Sstevel@tonic-gate /* Terminate array */ 1018*0Sstevel@tonic-gate res[res_count] = NULL; 1019*0Sstevel@tonic-gate 1020*0Sstevel@tonic-gate /* Bubble sort entries into the same order as mapping file */ 1021*0Sstevel@tonic-gate for (i = res_count - 2; 0 <= i; i--) { 1022*0Sstevel@tonic-gate for (j = 0; j <= i; j++) { 1023*0Sstevel@tonic-gate if (((__nis_table_mapping_t *)res[j + 1])->seq_num < 1024*0Sstevel@tonic-gate ((__nis_table_mapping_t *)res[j])->seq_num) { 1025*0Sstevel@tonic-gate end_ptr = res[j]; 1026*0Sstevel@tonic-gate res[j] = res[j+1]; 1027*0Sstevel@tonic-gate res[j + 1] = end_ptr; 1028*0Sstevel@tonic-gate } 1029*0Sstevel@tonic-gate } 1030*0Sstevel@tonic-gate } 1031*0Sstevel@tonic-gate 1032*0Sstevel@tonic-gate /* Finally copy the real strings in to each entry */ 1033*0Sstevel@tonic-gate for (i = 0; NULL != res[i]; i ++) { 1034*0Sstevel@tonic-gate 1035*0Sstevel@tonic-gate /* Get hash table entry back */ 1036*0Sstevel@tonic-gate it = (__nis_hash_item_mt *)res[i]; 1037*0Sstevel@tonic-gate 1038*0Sstevel@tonic-gate end_ptr = it->name + strlen(it->name) - strlen(domain) - 1; 1039*0Sstevel@tonic-gate 1040*0Sstevel@tonic-gate /* What we really need is strndup() */ 1041*0Sstevel@tonic-gate res[i] = am(myself, end_ptr - it->name + 1); 1042*0Sstevel@tonic-gate if (NULL == res[i]) { 1043*0Sstevel@tonic-gate free_map_list(res); 1044*0Sstevel@tonic-gate return (NULL); 1045*0Sstevel@tonic-gate } 1046*0Sstevel@tonic-gate 1047*0Sstevel@tonic-gate /* Copy from start to end_ptr */ 1048*0Sstevel@tonic-gate memcpy(res[i], it->name, end_ptr-it->name - 1); 1049*0Sstevel@tonic-gate } 1050*0Sstevel@tonic-gate 1051*0Sstevel@tonic-gate return (res); 1052*0Sstevel@tonic-gate } 1053*0Sstevel@tonic-gate 1054*0Sstevel@tonic-gate /* 1055*0Sstevel@tonic-gate * FUNCTION : make_nis_container() 1056*0Sstevel@tonic-gate * 1057*0Sstevel@tonic-gate * DESCRIPTION: Sets up container for map_name in the DIT. 1058*0Sstevel@tonic-gate * 1059*0Sstevel@tonic-gate * GIVEN : Map name 1060*0Sstevel@tonic-gate * The domain name. 1061*0Sstevel@tonic-gate * Flag indicating if container should be created. 1062*0Sstevel@tonic-gate * 1063*0Sstevel@tonic-gate * RETURNS : SUCCESS = It worked 1064*0Sstevel@tonic-gate * FAILURE = There was a problem. 1065*0Sstevel@tonic-gate */ 1066*0Sstevel@tonic-gate suc_code 1067*0Sstevel@tonic-gate make_nis_container(char *map_name, char *domain, bool_t init_containers) { 1068*0Sstevel@tonic-gate int i, rc, statP = SUCCESS; 1069*0Sstevel@tonic-gate __nis_table_mapping_t *t; 1070*0Sstevel@tonic-gate char *dn; 1071*0Sstevel@tonic-gate char *myself = "make_nis_container"; 1072*0Sstevel@tonic-gate 1073*0Sstevel@tonic-gate if (!map_name || !domain) 1074*0Sstevel@tonic-gate return (FAILURE); 1075*0Sstevel@tonic-gate 1076*0Sstevel@tonic-gate if (FALSE == init_containers) { 1077*0Sstevel@tonic-gate /* 1078*0Sstevel@tonic-gate * If we are not creating containers it is debatable what we 1079*0Sstevel@tonic-gate * should do . Maybe we should check for a pre- 1080*0Sstevel@tonic-gate * existing container and return failure if it does not exist. 1081*0Sstevel@tonic-gate * 1082*0Sstevel@tonic-gate * For now we assume the user will not have called us in this 1083*0Sstevel@tonic-gate * mode unless they know what they are doing. So return 1084*0Sstevel@tonic-gate * success. If they have got it wrong then latter writes will 1085*0Sstevel@tonic-gate * fail. 1086*0Sstevel@tonic-gate */ 1087*0Sstevel@tonic-gate return (SUCCESS); 1088*0Sstevel@tonic-gate } 1089*0Sstevel@tonic-gate 1090*0Sstevel@tonic-gate /* Get the mapping information for the map */ 1091*0Sstevel@tonic-gate if ((t = mappingFromMap(map_name, domain, &statP)) == 0) { 1092*0Sstevel@tonic-gate if (statP == MAP_NO_MAPPING_EXISTS) 1093*0Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR, 1094*0Sstevel@tonic-gate "%s: No mapping information available for %s,%s", 1095*0Sstevel@tonic-gate myself, NIL(map_name), NIL(domain)); 1096*0Sstevel@tonic-gate return (FAILURE); 1097*0Sstevel@tonic-gate } 1098*0Sstevel@tonic-gate 1099*0Sstevel@tonic-gate /* Two times. One for readDN and other for writeDN */ 1100*0Sstevel@tonic-gate for (i = 0; i < 2; i++) { 1101*0Sstevel@tonic-gate if (i == 0) 1102*0Sstevel@tonic-gate dn = t->objectDN->read.base; 1103*0Sstevel@tonic-gate else { 1104*0Sstevel@tonic-gate if (t->objectDN->write.base == 0) { 1105*0Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_INFO, 1106*0Sstevel@tonic-gate "%s: No baseDN in writespec. Write " 1107*0Sstevel@tonic-gate "disabled for %s,%s", 1108*0Sstevel@tonic-gate myself, map_name, domain); 1109*0Sstevel@tonic-gate break; 1110*0Sstevel@tonic-gate } 1111*0Sstevel@tonic-gate if (!strcasecmp(dn, t->objectDN->write.base)) 1112*0Sstevel@tonic-gate break; 1113*0Sstevel@tonic-gate dn = t->objectDN->write.base; 1114*0Sstevel@tonic-gate } 1115*0Sstevel@tonic-gate 1116*0Sstevel@tonic-gate if ((rc = makeNISObject(0, dn)) == FAILURE) { 1117*0Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR, 1118*0Sstevel@tonic-gate "%s: Unable to create ldap container (dn: %s) " 1119*0Sstevel@tonic-gate "for %s,%s", myself, dn, map_name, domain); 1120*0Sstevel@tonic-gate return (FAILURE); 1121*0Sstevel@tonic-gate } 1122*0Sstevel@tonic-gate } 1123*0Sstevel@tonic-gate return (SUCCESS); 1124*0Sstevel@tonic-gate } 1125*0Sstevel@tonic-gate 1126*0Sstevel@tonic-gate /* 1127*0Sstevel@tonic-gate * FUNCTION : make_nis_domain() 1128*0Sstevel@tonic-gate * 1129*0Sstevel@tonic-gate * DESCRIPTION: Sets up a nisDomainObject in the DIT 1130*0Sstevel@tonic-gate * 1131*0Sstevel@tonic-gate * GIVEN: Name of the domain 1132*0Sstevel@tonic-gate * Flag indicating if domain should be create or possibly just 1133*0Sstevel@tonic-gate * checked for. 1134*0Sstevel@tonic-gate */ 1135*0Sstevel@tonic-gate suc_code 1136*0Sstevel@tonic-gate make_nis_domain(char *domain, bool_t init_containers) { 1137*0Sstevel@tonic-gate 1138*0Sstevel@tonic-gate if (FALSE == init_containers) { 1139*0Sstevel@tonic-gate /* 1140*0Sstevel@tonic-gate * If we are not creating containers it is debatable what we 1141*0Sstevel@tonic-gate * should do with domains. Maybe we should check for a pre- 1142*0Sstevel@tonic-gate * existing domain and return failure if it does not exist. 1143*0Sstevel@tonic-gate * 1144*0Sstevel@tonic-gate * For now we assume the user will not have called us in this 1145*0Sstevel@tonic-gate * mode unless they know what they are doing. So return 1146*0Sstevel@tonic-gate * success. If they have got it wrong then latter writes will 1147*0Sstevel@tonic-gate * fail. 1148*0Sstevel@tonic-gate */ 1149*0Sstevel@tonic-gate return (SUCCESS); 1150*0Sstevel@tonic-gate } 1151*0Sstevel@tonic-gate 1152*0Sstevel@tonic-gate /* Create the domain */ 1153*0Sstevel@tonic-gate return (makeNISObject(domain, 0)); 1154*0Sstevel@tonic-gate } 1155*0Sstevel@tonic-gate 1156*0Sstevel@tonic-gate /* 1157*0Sstevel@tonic-gate * FUNCTION: update_netgroup_byxxx() 1158*0Sstevel@tonic-gate * 1159*0Sstevel@tonic-gate * DESCRIPTION: Updates the netgroup.byxxx series of maps based on the current 1160*0Sstevel@tonic-gate * netgroup file. We invoke revnetgroup so that if any changes 1161*0Sstevel@tonic-gate * are made to this utility the same changes are made here. 1162*0Sstevel@tonic-gate * 1163*0Sstevel@tonic-gate * INPUTS: map_ctrl containing lots of information about the map and a 1164*0Sstevel@tonic-gate * pointer to it's lock which will be required. 1165*0Sstevel@tonic-gate * 1166*0Sstevel@tonic-gate * OUTPUTS: SUCCESS = Map updated 1167*0Sstevel@tonic-gate * FAILURE = Map not updated 1168*0Sstevel@tonic-gate */ 1169*0Sstevel@tonic-gate suc_code 1170*0Sstevel@tonic-gate update_netgroup_byxxx(map_ctrl *map) { 1171*0Sstevel@tonic-gate /* Name of temporary entries DBM file */ 1172*0Sstevel@tonic-gate char *temp_entries; 1173*0Sstevel@tonic-gate /* Name of temporary TTL DBM file */ 1174*0Sstevel@tonic-gate char *temp_ttl; 1175*0Sstevel@tonic-gate /* Temporary DBM handles */ 1176*0Sstevel@tonic-gate DBM *temp_entries_db; 1177*0Sstevel@tonic-gate DBM *temp_ttl_db; 1178*0Sstevel@tonic-gate map_ctrl temp_map; 1179*0Sstevel@tonic-gate char *myself = "update_netgroup_byxxx"; 1180*0Sstevel@tonic-gate char *cmdbuf; 1181*0Sstevel@tonic-gate int cmd_length; 1182*0Sstevel@tonic-gate datum key; 1183*0Sstevel@tonic-gate map_ctrl *netgroupmap; 1184*0Sstevel@tonic-gate int res; 1185*0Sstevel@tonic-gate /* Temporary revnetgroup files */ 1186*0Sstevel@tonic-gate const char *byhost = NETGROUP_BYHOST "_REV" TEMP_POSTFIX; 1187*0Sstevel@tonic-gate const char *byuser = NETGROUP_BYUSER "_REV" TEMP_POSTFIX; 1188*0Sstevel@tonic-gate const char *temp_file_name; 1189*0Sstevel@tonic-gate 1190*0Sstevel@tonic-gate 1191*0Sstevel@tonic-gate /* 1192*0Sstevel@tonic-gate * We need to use two different temporary files: one for netgroup.byhost 1193*0Sstevel@tonic-gate * and other for netgroup.byuser, since these two maps can be updated 1194*0Sstevel@tonic-gate * simultaneously. These temporary files will hold the output of 1195*0Sstevel@tonic-gate * revnetgroup [-h|-u] command. They are then used to generate the 1196*0Sstevel@tonic-gate * corresponding dbm files and thereafter deleted. 1197*0Sstevel@tonic-gate */ 1198*0Sstevel@tonic-gate if (0 == strcmp(map->map_name, NETGROUP_BYHOST)) 1199*0Sstevel@tonic-gate temp_file_name = byhost; 1200*0Sstevel@tonic-gate else 1201*0Sstevel@tonic-gate temp_file_name = byuser; 1202*0Sstevel@tonic-gate 1203*0Sstevel@tonic-gate /* Alloc enough cmd buf for revnet cmd */ 1204*0Sstevel@tonic-gate cmd_length = strlen("/usr/sbin/makedbm -u ") + 1205*0Sstevel@tonic-gate (strlen(map->map_path) - strlen(map->map_name)) + 1206*0Sstevel@tonic-gate strlen(NETGROUP_MAP) + 1207*0Sstevel@tonic-gate strlen(" | /usr/sbin/revnetgroup -h > ") + 1208*0Sstevel@tonic-gate (strlen(map->map_path) - strlen(map->map_name)) + 1209*0Sstevel@tonic-gate strlen(temp_file_name) + 1; 1210*0Sstevel@tonic-gate cmdbuf = am(myself, cmd_length); 1211*0Sstevel@tonic-gate 1212*0Sstevel@tonic-gate if (NULL == cmdbuf) { 1213*0Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR, 1214*0Sstevel@tonic-gate "%s: Could not alloc cmdbuf.", myself); 1215*0Sstevel@tonic-gate return (FAILURE); 1216*0Sstevel@tonic-gate } 1217*0Sstevel@tonic-gate 1218*0Sstevel@tonic-gate /* 1219*0Sstevel@tonic-gate * If necessary update (and wait for) netgroups map. This is a lot of 1220*0Sstevel@tonic-gate * work but if the netgroup map itself is not being accessed it may 1221*0Sstevel@tonic-gate * contain information that is not up to date with the DIT. 1222*0Sstevel@tonic-gate * 1223*0Sstevel@tonic-gate * We use the cmdbuf to store the qualified netgroup map name there will 1224*0Sstevel@tonic-gate * be enough space for this but we are not yet creating the cmd. 1225*0Sstevel@tonic-gate */ 1226*0Sstevel@tonic-gate strlcpy(cmdbuf, map->map_path, strlen(map->map_path) - 1227*0Sstevel@tonic-gate strlen(map->map_name) + 1); 1228*0Sstevel@tonic-gate strcat(cmdbuf, NETGROUP_MAP); 1229*0Sstevel@tonic-gate netgroupmap = (map_ctrl *)shim_dbm_open(cmdbuf, 1230*0Sstevel@tonic-gate O_RDWR | O_CREAT, 0644); 1231*0Sstevel@tonic-gate if (NULL == netgroupmap) { 1232*0Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR, 1233*0Sstevel@tonic-gate "%s: Could not update %s.", myself, cmdbuf); 1234*0Sstevel@tonic-gate sfree(cmdbuf); 1235*0Sstevel@tonic-gate return (FAILURE); 1236*0Sstevel@tonic-gate } 1237*0Sstevel@tonic-gate 1238*0Sstevel@tonic-gate if (has_map_expired(netgroupmap)) { 1239*0Sstevel@tonic-gate lock_map_ctrl(netgroupmap); 1240*0Sstevel@tonic-gate update_map_if_required(netgroupmap, TRUE); 1241*0Sstevel@tonic-gate unlock_map_ctrl(netgroupmap); 1242*0Sstevel@tonic-gate } 1243*0Sstevel@tonic-gate shim_dbm_close((DBM *)netgroupmap); 1244*0Sstevel@tonic-gate 1245*0Sstevel@tonic-gate /* Dump netgroup file through revnetgroup to a temp file */ 1246*0Sstevel@tonic-gate strcpy(cmdbuf, "/usr/sbin/makedbm -u "); 1247*0Sstevel@tonic-gate 1248*0Sstevel@tonic-gate /* Unmake the netgroup file in same domain as map */ 1249*0Sstevel@tonic-gate strncat(cmdbuf, map->map_path, strlen(map->map_path) - 1250*0Sstevel@tonic-gate strlen(map->map_name)); 1251*0Sstevel@tonic-gate strcat(cmdbuf, NETGROUP_MAP); 1252*0Sstevel@tonic-gate 1253*0Sstevel@tonic-gate if (0 == strcmp(map->map_name, NETGROUP_BYHOST)) { 1254*0Sstevel@tonic-gate strcat(cmdbuf, " | /usr/sbin/revnetgroup -h > "); 1255*0Sstevel@tonic-gate } else { 1256*0Sstevel@tonic-gate strcat(cmdbuf, " | /usr/sbin/revnetgroup -u > "); 1257*0Sstevel@tonic-gate } 1258*0Sstevel@tonic-gate 1259*0Sstevel@tonic-gate /* Create temp file file in same domain as map */ 1260*0Sstevel@tonic-gate strncat(cmdbuf, map->map_path, strlen(map->map_path) - 1261*0Sstevel@tonic-gate strlen(map->map_name)); 1262*0Sstevel@tonic-gate strcat(cmdbuf, temp_file_name); 1263*0Sstevel@tonic-gate 1264*0Sstevel@tonic-gate if (0 > system(cmdbuf)) { 1265*0Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR, "%s: Could not run \"%s\" " 1266*0Sstevel@tonic-gate "(errno=%d)", myself, cmdbuf, errno); 1267*0Sstevel@tonic-gate sfree(cmdbuf); 1268*0Sstevel@tonic-gate return (FAILURE); 1269*0Sstevel@tonic-gate } 1270*0Sstevel@tonic-gate sfree(cmdbuf); 1271*0Sstevel@tonic-gate 1272*0Sstevel@tonic-gate /* Allocate and set up names */ 1273*0Sstevel@tonic-gate if (SUCCESS != alloc_temp_names(map->map_path, 1274*0Sstevel@tonic-gate &temp_entries, &temp_ttl)) { 1275*0Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR, 1276*0Sstevel@tonic-gate "%s: Unable to create map names for %s", 1277*0Sstevel@tonic-gate myself, map->map_path); 1278*0Sstevel@tonic-gate return (FAILURE); 1279*0Sstevel@tonic-gate } 1280*0Sstevel@tonic-gate 1281*0Sstevel@tonic-gate /* Make the temporary DBM file */ 1282*0Sstevel@tonic-gate cmdbuf = am(myself, strlen("/usr/sbin/makedbm") + 1283*0Sstevel@tonic-gate (strlen(map->map_path) - strlen(map->map_name)) + 1284*0Sstevel@tonic-gate strlen(temp_file_name) + 1285*0Sstevel@tonic-gate strlen(temp_entries) + 3); 1286*0Sstevel@tonic-gate if (NULL == cmdbuf) { 1287*0Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR, 1288*0Sstevel@tonic-gate "%s: Could not allocate cmdbuf.", myself); 1289*0Sstevel@tonic-gate sfree(temp_entries); 1290*0Sstevel@tonic-gate sfree(temp_ttl); 1291*0Sstevel@tonic-gate return (FAILURE); 1292*0Sstevel@tonic-gate } 1293*0Sstevel@tonic-gate 1294*0Sstevel@tonic-gate strcpy(cmdbuf, "/usr/sbin/makedbm "); 1295*0Sstevel@tonic-gate strncat(cmdbuf, map->map_path, strlen(map->map_path) - 1296*0Sstevel@tonic-gate strlen(map->map_name)); 1297*0Sstevel@tonic-gate strcat(cmdbuf, temp_file_name); 1298*0Sstevel@tonic-gate strcat(cmdbuf, " "); 1299*0Sstevel@tonic-gate strcat(cmdbuf, temp_entries); 1300*0Sstevel@tonic-gate 1301*0Sstevel@tonic-gate if (0 > system(cmdbuf)) { 1302*0Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR, "%s: Could not run \"%s\" " 1303*0Sstevel@tonic-gate "(errno=%d)", myself, cmdbuf, errno); 1304*0Sstevel@tonic-gate sfree(cmdbuf); 1305*0Sstevel@tonic-gate sfree(temp_entries); 1306*0Sstevel@tonic-gate sfree(temp_ttl); 1307*0Sstevel@tonic-gate return (FAILURE); 1308*0Sstevel@tonic-gate } 1309*0Sstevel@tonic-gate 1310*0Sstevel@tonic-gate /* Already have enough command buffer to rm temporary file */ 1311*0Sstevel@tonic-gate strlcpy(cmdbuf, map->map_path, strlen(map->map_path) - 1312*0Sstevel@tonic-gate strlen(map->map_name) + 1); 1313*0Sstevel@tonic-gate strcat(cmdbuf, temp_file_name); 1314*0Sstevel@tonic-gate res = unlink(cmdbuf); 1315*0Sstevel@tonic-gate /* If the temp file did not exist no problem. Probably had no entries */ 1316*0Sstevel@tonic-gate if ((0 != res) && (ENOENT != errno)) { 1317*0Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR, "%s: Could not delete \"%s\" " 1318*0Sstevel@tonic-gate "(errno=%d)", myself, cmdbuf, errno); 1319*0Sstevel@tonic-gate sfree(temp_entries); 1320*0Sstevel@tonic-gate sfree(temp_ttl); 1321*0Sstevel@tonic-gate sfree(cmdbuf); 1322*0Sstevel@tonic-gate return (FAILURE); 1323*0Sstevel@tonic-gate } 1324*0Sstevel@tonic-gate sfree(cmdbuf); 1325*0Sstevel@tonic-gate 1326*0Sstevel@tonic-gate if ((temp_entries_db = dbm_open(temp_entries, O_RDWR | O_CREAT, 0644)) 1327*0Sstevel@tonic-gate == NULL) { 1328*0Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR, "%s: Could not open %s", 1329*0Sstevel@tonic-gate myself, temp_entries); 1330*0Sstevel@tonic-gate sfree(temp_entries); 1331*0Sstevel@tonic-gate sfree(temp_ttl); 1332*0Sstevel@tonic-gate return (FAILURE); 1333*0Sstevel@tonic-gate } 1334*0Sstevel@tonic-gate 1335*0Sstevel@tonic-gate if ((temp_ttl_db = dbm_open(temp_ttl, O_RDWR | O_CREAT, 0644)) 1336*0Sstevel@tonic-gate == NULL) { 1337*0Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR, "%s: Could not open %s", 1338*0Sstevel@tonic-gate myself, temp_ttl); 1339*0Sstevel@tonic-gate dbm_close(temp_entries_db); 1340*0Sstevel@tonic-gate sfree(temp_entries); 1341*0Sstevel@tonic-gate sfree(temp_ttl); 1342*0Sstevel@tonic-gate return (FAILURE); 1343*0Sstevel@tonic-gate } 1344*0Sstevel@tonic-gate 1345*0Sstevel@tonic-gate /* 1346*0Sstevel@tonic-gate * Set up enough of map_ctrl to call update_entry_ttl. Since there is 1347*0Sstevel@tonic-gate * no mapping, and thus not TTL, defined for these maps use the TTL 1348*0Sstevel@tonic-gate * values for netgroup map 1349*0Sstevel@tonic-gate */ 1350*0Sstevel@tonic-gate temp_map.map_name = NETGROUP_MAP; 1351*0Sstevel@tonic-gate temp_map.domain = map->domain; 1352*0Sstevel@tonic-gate temp_map.ttl = temp_ttl_db; 1353*0Sstevel@tonic-gate 1354*0Sstevel@tonic-gate /* 1355*0Sstevel@tonic-gate * Generate new TTL file. Since these maps work only on the whole map 1356*0Sstevel@tonic-gate * expiry these will not actually be used but there presence makes it 1357*0Sstevel@tonic-gate * easier to handle these maps in the same way as other maps. 1358*0Sstevel@tonic-gate */ 1359*0Sstevel@tonic-gate key = dbm_firstkey(temp_entries_db); 1360*0Sstevel@tonic-gate while (key.dptr != 0) { 1361*0Sstevel@tonic-gate if (!is_special_key(&key)) 1362*0Sstevel@tonic-gate /* 1363*0Sstevel@tonic-gate * For these maps want all timouts to be maximum 1364*0Sstevel@tonic-gate */ 1365*0Sstevel@tonic-gate if (FAILURE == update_entry_ttl(&temp_map, &key, 1366*0Sstevel@tonic-gate TTL_MAX)) 1367*0Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR, 1368*0Sstevel@tonic-gate "%s: Could not update TTL for " 1369*0Sstevel@tonic-gate "(key=%s) for map %s,%s", 1370*0Sstevel@tonic-gate myself, NIL(key.dptr), map->map_name, 1371*0Sstevel@tonic-gate map->domain); 1372*0Sstevel@tonic-gate key = dbm_nextkey(temp_entries_db); 1373*0Sstevel@tonic-gate } 1374*0Sstevel@tonic-gate 1375*0Sstevel@tonic-gate /* Update map TTL */ 1376*0Sstevel@tonic-gate update_map_ttl(&temp_map); 1377*0Sstevel@tonic-gate 1378*0Sstevel@tonic-gate /* Close temp DBM files */ 1379*0Sstevel@tonic-gate dbm_close(temp_entries_db); 1380*0Sstevel@tonic-gate dbm_close(temp_ttl_db); 1381*0Sstevel@tonic-gate 1382*0Sstevel@tonic-gate /* Lock access to the map for copy */ 1383*0Sstevel@tonic-gate lock_map_ctrl(map); 1384*0Sstevel@tonic-gate 1385*0Sstevel@tonic-gate /* Move temp maps to real ones */ 1386*0Sstevel@tonic-gate rename_map(temp_entries, map->map_path, FALSE); 1387*0Sstevel@tonic-gate rename_map(temp_ttl, map->ttl_path, FALSE); 1388*0Sstevel@tonic-gate 1389*0Sstevel@tonic-gate /* Free file names */ 1390*0Sstevel@tonic-gate sfree(temp_entries); 1391*0Sstevel@tonic-gate sfree(temp_ttl); 1392*0Sstevel@tonic-gate 1393*0Sstevel@tonic-gate /* Unlock map */ 1394*0Sstevel@tonic-gate unlock_map_ctrl(map); 1395*0Sstevel@tonic-gate 1396*0Sstevel@tonic-gate return (SUCCESS); 1397*0Sstevel@tonic-gate } 1398