1cb5caa98Sdjl /* 2cb5caa98Sdjl * CDDL HEADER START 3cb5caa98Sdjl * 4cb5caa98Sdjl * The contents of this file are subject to the terms of the 5cb5caa98Sdjl * Common Development and Distribution License (the "License"). 6cb5caa98Sdjl * You may not use this file except in compliance with the License. 7cb5caa98Sdjl * 8cb5caa98Sdjl * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9cb5caa98Sdjl * or http://www.opensolaris.org/os/licensing. 10cb5caa98Sdjl * See the License for the specific language governing permissions 11cb5caa98Sdjl * and limitations under the License. 12cb5caa98Sdjl * 13cb5caa98Sdjl * When distributing Covered Code, include this CDDL HEADER in each 14cb5caa98Sdjl * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15cb5caa98Sdjl * If applicable, add the following below this CDDL HEADER, with the 16cb5caa98Sdjl * fields enclosed by brackets "[]" replaced with your own identifying 17cb5caa98Sdjl * information: Portions Copyright [yyyy] [name of copyright owner] 18cb5caa98Sdjl * 19cb5caa98Sdjl * CDDL HEADER END 20cb5caa98Sdjl */ 21cb5caa98Sdjl /* 22cb5caa98Sdjl * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 23cb5caa98Sdjl * Use is subject to license terms. 24cb5caa98Sdjl */ 25cb5caa98Sdjl 26cb5caa98Sdjl #pragma ident "%Z%%M% %I% %E% SMI" 27cb5caa98Sdjl 28cb5caa98Sdjl #include <stdlib.h> /* getenv() */ 29cb5caa98Sdjl #include <assert.h> 30cb5caa98Sdjl #include <unistd.h> 31cb5caa98Sdjl #include <string.h> 32cb5caa98Sdjl #include <dlfcn.h> 33cb5caa98Sdjl #include <nss_dbdefs.h> 34cb5caa98Sdjl #include <exec_attr.h> 35cb5caa98Sdjl #include <gssapi/gssapi.h> 36cb5caa98Sdjl #include "nscd_door.h" 37cb5caa98Sdjl #include "nscd_switch.h" 38cb5caa98Sdjl #include "nscd_log.h" 39cb5caa98Sdjl #include "nscd_frontend.h" 40cb5caa98Sdjl 41cb5caa98Sdjl #pragma weak nss_search = _nss_search 42cb5caa98Sdjl #define nss_search _nss_search 43cb5caa98Sdjl 44cb5caa98Sdjl extern rwlock_t nscd_smf_service_state_lock; 45cb5caa98Sdjl 46cb5caa98Sdjl /* nscd id: main, forker, or child */ 47cb5caa98Sdjl extern int _whoami; 48cb5caa98Sdjl 49cb5caa98Sdjl static int 50cb5caa98Sdjl retry_test(nss_status_t res, int n, struct __nsw_lookup_v1 *lkp) 51cb5caa98Sdjl { 52cb5caa98Sdjl if (res != NSS_TRYAGAIN && res != NSS_NISSERVDNS_TRYAGAIN) { 53cb5caa98Sdjl if (res == NSS_SUCCESS) { 54cb5caa98Sdjl __NSW_UNPAUSE_ACTION(lkp->actions[__NSW_TRYAGAIN]); 55cb5caa98Sdjl __NSW_UNPAUSE_ACTION( 56cb5caa98Sdjl lkp->actions[__NSW_NISSERVDNS_TRYAGAIN]); 57cb5caa98Sdjl } 58cb5caa98Sdjl return (0); 59cb5caa98Sdjl } 60cb5caa98Sdjl 61cb5caa98Sdjl if ((res == NSS_TRYAGAIN && 62cb5caa98Sdjl lkp->actions[__NSW_TRYAGAIN] == __NSW_TRYAGAIN_FOREVER) || 63cb5caa98Sdjl (res == NSS_NISSERVDNS_TRYAGAIN && 64cb5caa98Sdjl lkp->actions[__NSW_NISSERVDNS_TRYAGAIN] == __NSW_TRYAGAIN_FOREVER)) 65cb5caa98Sdjl return (1); 66cb5caa98Sdjl 67cb5caa98Sdjl if (res == NSS_TRYAGAIN && 68cb5caa98Sdjl lkp->actions[__NSW_TRYAGAIN] == __NSW_TRYAGAIN_NTIMES) 69cb5caa98Sdjl if (n <= lkp->max_retries) 70cb5caa98Sdjl return (1); 71cb5caa98Sdjl else { 72cb5caa98Sdjl lkp->actions[__NSW_TRYAGAIN] = __NSW_TRYAGAIN_PAUSED; 73cb5caa98Sdjl return (0); 74cb5caa98Sdjl } 75cb5caa98Sdjl 76cb5caa98Sdjl if (res == NSS_NISSERVDNS_TRYAGAIN && 77cb5caa98Sdjl lkp->actions[__NSW_NISSERVDNS_TRYAGAIN] == __NSW_TRYAGAIN_NTIMES) 78cb5caa98Sdjl if (n <= lkp->max_retries) 79cb5caa98Sdjl return (1); 80cb5caa98Sdjl else { 81cb5caa98Sdjl lkp->actions[__NSW_NISSERVDNS_TRYAGAIN] = 82cb5caa98Sdjl __NSW_TRYAGAIN_PAUSED; 83cb5caa98Sdjl return (0); 84cb5caa98Sdjl } 85cb5caa98Sdjl 86cb5caa98Sdjl return (0); 87cb5caa98Sdjl } 88cb5caa98Sdjl 89cb5caa98Sdjl static thread_key_t loopback_key; 90cb5caa98Sdjl static mutex_t loopback_key_lock = DEFAULTMUTEX; 91cb5caa98Sdjl static int loopback_key_created = 0; 92cb5caa98Sdjl typedef struct lb_key { 93cb5caa98Sdjl int srci; 94cb5caa98Sdjl int dbi; 95cb5caa98Sdjl int fnum; 96cb5caa98Sdjl int *lb_flagp; 97cb5caa98Sdjl } lb_key_t; 98cb5caa98Sdjl 99cb5caa98Sdjl static int 100cb5caa98Sdjl set_loopback_key(lb_key_t *key) { 101cb5caa98Sdjl 102cb5caa98Sdjl int rc = 0; 103cb5caa98Sdjl lb_key_t *k; 104cb5caa98Sdjl 105cb5caa98Sdjl if (!loopback_key_created) { 106cb5caa98Sdjl (void) mutex_lock(&loopback_key_lock); 107cb5caa98Sdjl if (!loopback_key_created) { 108cb5caa98Sdjl if ((rc = thr_keycreate(&loopback_key, 109cb5caa98Sdjl NULL)) == 0) 110cb5caa98Sdjl loopback_key_created = 1; 111cb5caa98Sdjl } 112cb5caa98Sdjl (void) mutex_unlock(&loopback_key_lock); 113cb5caa98Sdjl } 114cb5caa98Sdjl if (rc == 0) { 115cb5caa98Sdjl /* set key if not already set */ 116cb5caa98Sdjl if (thr_getspecific(loopback_key, (void **)&k) == 0 && 117cb5caa98Sdjl k == NULL) { 118cb5caa98Sdjl rc = thr_setspecific(loopback_key, key); 119cb5caa98Sdjl } 120cb5caa98Sdjl } 121cb5caa98Sdjl 122cb5caa98Sdjl return (rc); 123cb5caa98Sdjl } 124cb5caa98Sdjl 125cb5caa98Sdjl static lb_key_t * 126cb5caa98Sdjl get_loopback_key(void) { 127cb5caa98Sdjl 128cb5caa98Sdjl char *me = "get_loopback_key"; 129cb5caa98Sdjl int rc = 0; 130cb5caa98Sdjl lb_key_t *k = NULL; 131cb5caa98Sdjl 132cb5caa98Sdjl if (!loopback_key_created) 133cb5caa98Sdjl return (NULL); 134cb5caa98Sdjl 135cb5caa98Sdjl rc = thr_getspecific(loopback_key, (void **)&k); 136cb5caa98Sdjl 137cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG) 138cb5caa98Sdjl (me, "get loopback key rc= %d, key = %p\n", rc, k); 139cb5caa98Sdjl 140cb5caa98Sdjl if (rc == 0 && k != NULL) 141cb5caa98Sdjl return (k); 142cb5caa98Sdjl 143cb5caa98Sdjl return (NULL); 144cb5caa98Sdjl } 145cb5caa98Sdjl 146cb5caa98Sdjl static void 147cb5caa98Sdjl clear_loopback_key(lb_key_t *key) { 148cb5caa98Sdjl 149cb5caa98Sdjl char *me = "clear_loopback_key"; 150cb5caa98Sdjl 151cb5caa98Sdjl if (loopback_key_created && key != 0) { 152cb5caa98Sdjl /* 153cb5caa98Sdjl * key->lb_flagp points to the location of the 154cb5caa98Sdjl * flag, check_flag, in the stack where it was 155cb5caa98Sdjl * first set; clearing the flag tells that 156cb5caa98Sdjl * stack the loopback error has been resolved 157cb5caa98Sdjl */ 158cb5caa98Sdjl *key->lb_flagp = 0; 159cb5caa98Sdjl (void) thr_setspecific(loopback_key, NULL); 160cb5caa98Sdjl } 161cb5caa98Sdjl 162cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG) 163cb5caa98Sdjl (me, "key %p cleared\n", key); 164cb5caa98Sdjl } 165cb5caa98Sdjl 166cb5caa98Sdjl static thread_key_t initf_key; 167cb5caa98Sdjl static mutex_t initf_key_lock = DEFAULTMUTEX; 168cb5caa98Sdjl static int initf_key_created = 0; 169cb5caa98Sdjl 170cb5caa98Sdjl static int 171cb5caa98Sdjl set_initf_key(void *pbuf) { 172cb5caa98Sdjl 173cb5caa98Sdjl int rc = 0; 174cb5caa98Sdjl 175cb5caa98Sdjl if (!initf_key_created) { 176cb5caa98Sdjl (void) mutex_lock(&initf_key_lock); 177cb5caa98Sdjl if (!initf_key_created) { 178cb5caa98Sdjl if ((rc = thr_keycreate(&initf_key, NULL)) == 0) 179cb5caa98Sdjl initf_key_created = 1; 180cb5caa98Sdjl } 181cb5caa98Sdjl (void) mutex_unlock(&initf_key_lock); 182cb5caa98Sdjl } 183cb5caa98Sdjl if (rc == 0) 184cb5caa98Sdjl rc = thr_setspecific(initf_key, pbuf); 185cb5caa98Sdjl 186cb5caa98Sdjl return (rc); 187cb5caa98Sdjl } 188cb5caa98Sdjl 189cb5caa98Sdjl static void * 190cb5caa98Sdjl get_initf_key(void) { 191cb5caa98Sdjl 192cb5caa98Sdjl char *me = "get_initf_key"; 193cb5caa98Sdjl void *pbuf; 194cb5caa98Sdjl int rc = 0; 195cb5caa98Sdjl 196cb5caa98Sdjl if (!initf_key_created) 197cb5caa98Sdjl return (NULL); 198cb5caa98Sdjl 199cb5caa98Sdjl rc = thr_getspecific(initf_key, (void **)&pbuf); 200cb5caa98Sdjl 201cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG) 202cb5caa98Sdjl (me, "got initf pbuf rc= %d, key = %p\n", rc, pbuf); 203cb5caa98Sdjl 204cb5caa98Sdjl if (rc == 0 && pbuf != NULL) 205cb5caa98Sdjl return (pbuf); 206cb5caa98Sdjl 207cb5caa98Sdjl return (NULL); 208cb5caa98Sdjl } 209cb5caa98Sdjl 210cb5caa98Sdjl static void 211cb5caa98Sdjl clear_initf_key(void) { 212cb5caa98Sdjl 213cb5caa98Sdjl char *me = "clear_initf_key"; 214cb5caa98Sdjl 215cb5caa98Sdjl if (initf_key_created) 216cb5caa98Sdjl (void) thr_setspecific(initf_key, NULL); 217cb5caa98Sdjl 218cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG) 219cb5caa98Sdjl (me, "initf pbuf cleared\n"); 220cb5caa98Sdjl } 221cb5caa98Sdjl 222cb5caa98Sdjl /* 223cb5caa98Sdjl * Call the input initf function to extract the 224cb5caa98Sdjl * NSS front end parameters and examine them to 225cb5caa98Sdjl * determine if an NSS lookup is to be performed 226cb5caa98Sdjl * on a regular or a pseudo (called from compat 227cb5caa98Sdjl * backend) database. Then set the necessary 228cb5caa98Sdjl * parameters for later data structures creation 229cb5caa98Sdjl * and processing. 230cb5caa98Sdjl */ 231cb5caa98Sdjl static nscd_rc_t 232cb5caa98Sdjl getparams( 233cb5caa98Sdjl int search_fnum, 234cb5caa98Sdjl nss_db_initf_t initf, 235cb5caa98Sdjl nscd_nsw_params_t *params) 236cb5caa98Sdjl { 237cb5caa98Sdjl 238cb5caa98Sdjl nscd_rc_t rc = NSCD_SUCCESS; 239cb5caa98Sdjl nss_db_params_t *p; 240cb5caa98Sdjl int j; 241cb5caa98Sdjl char *dbn; 242cb5caa98Sdjl const char *n; 243cb5caa98Sdjl 244cb5caa98Sdjl p = ¶ms->p; 245cb5caa98Sdjl (void) memset(p, 0, sizeof (*p)); 246cb5caa98Sdjl (*initf)(p); 247cb5caa98Sdjl params->dbi = -1; 248cb5caa98Sdjl params->cfgdbi = -1; 249cb5caa98Sdjl params->compati = -1; 250cb5caa98Sdjl params->dnsi = -1; 251cb5caa98Sdjl 252cb5caa98Sdjl /* map database name to index */ 253cb5caa98Sdjl n = p->name; 254cb5caa98Sdjl for (j = 0; j < NSCD_NUM_DB; j++) { 255cb5caa98Sdjl dbn = NSCD_NSW_DB_NAME(j); 256cb5caa98Sdjl if (*n != *dbn) 257cb5caa98Sdjl continue; 258cb5caa98Sdjl if (strcmp(n, dbn) == 0) { 259cb5caa98Sdjl params->dbi = j; 260cb5caa98Sdjl if (*n != 'h' && *n != 'i' && *n != 's' && *n != 'a') 261cb5caa98Sdjl break; 262cb5caa98Sdjl if (strcmp(n, NSS_DBNAM_HOSTS) == 0 && 263cb5caa98Sdjl search_fnum == NSS_DBOP_HOSTS_BYNAME) 264cb5caa98Sdjl params->dnsi = 0; 265cb5caa98Sdjl else if (strcmp(n, NSS_DBNAM_IPNODES) == 0 && 266cb5caa98Sdjl search_fnum == NSS_DBOP_IPNODES_BYNAME) 267cb5caa98Sdjl params->dnsi = 1; 268cb5caa98Sdjl else if (strcmp(n, NSS_DBNAM_SHADOW) == 0) 269cb5caa98Sdjl params->privdb = 1; 270cb5caa98Sdjl else if (strcmp(n, NSS_DBNAM_AUDITUSER) == 0) 271cb5caa98Sdjl params->privdb = 1; 272cb5caa98Sdjl break; 273cb5caa98Sdjl } 274cb5caa98Sdjl } 275cb5caa98Sdjl 276cb5caa98Sdjl /* 277cb5caa98Sdjl * use the switch policy for passwd_compat or 278cb5caa98Sdjl * group_compat? 279cb5caa98Sdjl */ 280cb5caa98Sdjl if (p->config_name != NULL) { 281cb5caa98Sdjl 282cb5caa98Sdjl n = p->config_name; 283cb5caa98Sdjl for (j = 0; j < NSCD_NUM_DB; j++) { 284cb5caa98Sdjl dbn = NSCD_NSW_DB_NAME(j); 285cb5caa98Sdjl if (*n == *dbn) { 286cb5caa98Sdjl if (strcmp(n, dbn) == 0) { 287cb5caa98Sdjl params->cfgdbi = j; 288cb5caa98Sdjl break; 289cb5caa98Sdjl } 290cb5caa98Sdjl } 291cb5caa98Sdjl } 292cb5caa98Sdjl } 293cb5caa98Sdjl 294cb5caa98Sdjl /* map the database name to the pseudo database index */ 295cb5caa98Sdjl if (params->cfgdbi != -1) { 296cb5caa98Sdjl if (strstr(p->config_name, "_compat") != NULL) { 297cb5caa98Sdjl n = p->name; 298cb5caa98Sdjl for (j = params->cfgdbi; j < NSCD_NUM_DB; j++) { 299cb5caa98Sdjl dbn = NSCD_NSW_DB_NAME(j); 300cb5caa98Sdjl if (*n == *dbn) { 301cb5caa98Sdjl if (strcmp(n, dbn) == 0) { 302cb5caa98Sdjl params->compati = j; 303cb5caa98Sdjl break; 304cb5caa98Sdjl } 305cb5caa98Sdjl } 306cb5caa98Sdjl } 307cb5caa98Sdjl } 308cb5caa98Sdjl } 309cb5caa98Sdjl 310cb5caa98Sdjl assert(params->dbi != -1); 311cb5caa98Sdjl return (rc); 312cb5caa98Sdjl } 313cb5caa98Sdjl 314cb5caa98Sdjl static void 315cb5caa98Sdjl nscd_initf(nss_db_params_t *p) 316cb5caa98Sdjl { 317cb5caa98Sdjl nss_pheader_t *pbuf; 318cb5caa98Sdjl nssuint_t off; 319cb5caa98Sdjl nss_dbd_t *pdbd; 320cb5caa98Sdjl char *me = "nscd_initf"; 321cb5caa98Sdjl 322cb5caa98Sdjl pbuf = (nss_pheader_t *)get_initf_key(); 323cb5caa98Sdjl if (pbuf == NULL) { 324cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG) 325cb5caa98Sdjl (me, "ERROR: initf key not set\n"); 326cb5caa98Sdjl return; 327cb5caa98Sdjl } 328cb5caa98Sdjl 329cb5caa98Sdjl if (pbuf->dbd_len <= sizeof (nss_dbd_t)) { 330cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG) 331cb5caa98Sdjl (me, "invalid db front params data ? dbd_len = %d\n", 332cb5caa98Sdjl pbuf->dbd_len); 333cb5caa98Sdjl return; 334cb5caa98Sdjl } 335cb5caa98Sdjl 336cb5caa98Sdjl off = pbuf->dbd_off; 337cb5caa98Sdjl pdbd = (nss_dbd_t *)((void *)((char *)pbuf + off)); 338cb5caa98Sdjl 339cb5caa98Sdjl p->name = (char *)pdbd + pdbd->o_name; 340cb5caa98Sdjl p->config_name = (char *)pdbd + pdbd->o_config_name; 341cb5caa98Sdjl p->default_config = (char *)pdbd + pdbd->o_default_config; 342cb5caa98Sdjl p->flags = (enum nss_dbp_flags)pdbd->flags; 343cb5caa98Sdjl (void) memcpy(&p->private, &pbuf->nscdpriv, sizeof (p->private)); 344cb5caa98Sdjl 345cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG) 346cb5caa98Sdjl (me, "db frontend params: name =%s, config_name = %s, " 347cb5caa98Sdjl "default_config = %s, flags = %x\n", p->name, 348cb5caa98Sdjl (p->config_name && *p->config_name != '\0' ? 349cb5caa98Sdjl p->config_name : "<NOT SPECIFIED>"), 350cb5caa98Sdjl (p->default_config && *p->default_config != '\0' ? 351cb5caa98Sdjl p->default_config : "<NOT SPECIFIED>"), 352cb5caa98Sdjl p->flags); 353cb5caa98Sdjl } 354cb5caa98Sdjl 355cb5caa98Sdjl 356cb5caa98Sdjl static void 357cb5caa98Sdjl trace_result( 358cb5caa98Sdjl int dbi, 359cb5caa98Sdjl int srci, 360cb5caa98Sdjl int op, 361cb5caa98Sdjl nss_status_t res, 362cb5caa98Sdjl nss_XbyY_args_t *arg) 363cb5caa98Sdjl { 364cb5caa98Sdjl char *res_str; 365cb5caa98Sdjl char *src = "?"; 366cb5caa98Sdjl char *db = "?"; 367cb5caa98Sdjl char *me = "nss_search"; 368cb5caa98Sdjl 369cb5caa98Sdjl switch (res) { 370cb5caa98Sdjl case NSS_SUCCESS: 371cb5caa98Sdjl res_str = "NSS_SUCCESS"; 372cb5caa98Sdjl break; 373cb5caa98Sdjl case NSS_NOTFOUND: 374cb5caa98Sdjl res_str = "NSS_NOTFOUND"; 375cb5caa98Sdjl break; 376cb5caa98Sdjl case NSS_UNAVAIL: 377cb5caa98Sdjl res_str = "NSS_UNAVAIL"; 378cb5caa98Sdjl break; 379cb5caa98Sdjl case NSS_TRYAGAIN: 380cb5caa98Sdjl res_str = "NSS_TRYAGAIN"; 381cb5caa98Sdjl break; 382cb5caa98Sdjl case NSS_NISSERVDNS_TRYAGAIN: 383cb5caa98Sdjl res_str = "NSS_NISSERVDNS_TRYAGAIN"; 384cb5caa98Sdjl break; 385cb5caa98Sdjl default: 386cb5caa98Sdjl res_str = "UNKNOWN STATUS"; 387cb5caa98Sdjl break; 388cb5caa98Sdjl } 389cb5caa98Sdjl 390cb5caa98Sdjl if (dbi != -1) 391cb5caa98Sdjl db = NSCD_NSW_DB_NAME(dbi); 392cb5caa98Sdjl if (srci != -1) 393cb5caa98Sdjl src = NSCD_NSW_SRC_NAME(srci); 394cb5caa98Sdjl 395cb5caa98Sdjl if (res == NSS_SUCCESS) { 396cb5caa98Sdjl _nscd_logit(me, 397cb5caa98Sdjl "%s: database: %s, operation: %d, source: %s returned \"%s\", length = %d\n", 398cb5caa98Sdjl res_str, db, op, src, arg->buf.buffer, arg->returnlen); 399cb5caa98Sdjl 400cb5caa98Sdjl return; 401cb5caa98Sdjl } 402cb5caa98Sdjl 403cb5caa98Sdjl _nscd_logit(me, 404cb5caa98Sdjl "%s: database: %s, operation: %d, source: %s, erange= %d, errno: %s \n", 405cb5caa98Sdjl res_str, db, op, src, arg->erange, strerror(arg->h_errno)); 406cb5caa98Sdjl } 407cb5caa98Sdjl 408cb5caa98Sdjl /* 409cb5caa98Sdjl * Determine if a request should be done locally in the getXbyY caller's 410cb5caa98Sdjl * process. Return none zero if yes, 0 otherwise. 411cb5caa98Sdjl * This function returnis 1 if: 412cb5caa98Sdjl * -- the database is exec_attr and the search_flag is GET_ALL 413cb5caa98Sdjl */ 414cb5caa98Sdjl static int 415cb5caa98Sdjl try_local( 416cb5caa98Sdjl int dbi, 417cb5caa98Sdjl void *arg) 418cb5caa98Sdjl { 419cb5caa98Sdjl struct nss_XbyY_args *ap = (struct nss_XbyY_args *)arg; 420cb5caa98Sdjl _priv_execattr *ep; 421cb5caa98Sdjl int rc = 0; 422cb5caa98Sdjl char *me = "try_local"; 423cb5caa98Sdjl 424cb5caa98Sdjl if (strcmp(NSCD_NSW_DB_NAME(dbi), NSS_DBNAM_EXECATTR) == 0) { 425cb5caa98Sdjl if ((ep = ap->key.attrp) != NULL && 426cb5caa98Sdjl ep->search_flag == GET_ALL) 427cb5caa98Sdjl rc = 1; 428cb5caa98Sdjl } 429cb5caa98Sdjl 430cb5caa98Sdjl if (rc != 0) { 431cb5caa98Sdjl 432cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG) 433cb5caa98Sdjl (me, "TRYLOCAL: exec_attr:GET_ALL\n"); 434cb5caa98Sdjl } 435cb5caa98Sdjl 436cb5caa98Sdjl return (rc); 437cb5caa98Sdjl } 438cb5caa98Sdjl 439cb5caa98Sdjl static nscd_rc_t 440cb5caa98Sdjl get_dns_funcs(int dnsi, void **func_p) 441cb5caa98Sdjl { 442cb5caa98Sdjl char *me = "get_dns_funcs"; 443cb5caa98Sdjl static void *handle = NULL; 444cb5caa98Sdjl static mutex_t func_lock = DEFAULTMUTEX; 445cb5caa98Sdjl void *sym; 446cb5caa98Sdjl char *func_name[2] = { "_nss_get_dns_hosts_name", 447cb5caa98Sdjl "_nss_get_dns_ipnodes_name" }; 448cb5caa98Sdjl static void *func[2] = {NULL, NULL}; 449cb5caa98Sdjl 450cb5caa98Sdjl if (handle != NULL && dnsi > 0 && func[dnsi] != NULL) { 451cb5caa98Sdjl (void) memcpy(func_p, &func[dnsi], sizeof (void *)); 452cb5caa98Sdjl return (NSCD_SUCCESS); 453cb5caa98Sdjl } 454cb5caa98Sdjl 455cb5caa98Sdjl (void) mutex_lock(&func_lock); 456cb5caa98Sdjl 457cb5caa98Sdjl /* close the handle if requested */ 458cb5caa98Sdjl if (dnsi < 0) { 459cb5caa98Sdjl if (handle != NULL) { 460cb5caa98Sdjl (void) dlclose(handle); 461cb5caa98Sdjl func[0] = NULL; 462cb5caa98Sdjl func[1] = NULL; 463cb5caa98Sdjl } 464cb5caa98Sdjl (void) mutex_unlock(&func_lock); 465cb5caa98Sdjl return (NSCD_SUCCESS); 466cb5caa98Sdjl } 467cb5caa98Sdjl 468cb5caa98Sdjl if (handle != NULL && func[dnsi] != NULL) { 469cb5caa98Sdjl (void) memcpy(func_p, &func[dnsi], sizeof (void *)); 470cb5caa98Sdjl (void) mutex_unlock(&func_lock); 471cb5caa98Sdjl return (NSCD_SUCCESS); 472cb5caa98Sdjl } 473cb5caa98Sdjl 474cb5caa98Sdjl if (handle == NULL) { 475cb5caa98Sdjl handle = dlopen("nss_dns.so.1", RTLD_LAZY); 476cb5caa98Sdjl if (handle == NULL) { 477cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, 478cb5caa98Sdjl NSCD_LOG_LEVEL_ERROR) 479cb5caa98Sdjl (me, "unable to dlopen nss_dns.so.1\n"); 480cb5caa98Sdjl (void) mutex_unlock(&func_lock); 481cb5caa98Sdjl return (NSCD_CFG_DLOPEN_ERROR); 482cb5caa98Sdjl } 483cb5caa98Sdjl } 484cb5caa98Sdjl 485cb5caa98Sdjl if ((sym = dlsym(handle, func_name[dnsi])) == NULL) { 486cb5caa98Sdjl 487cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_ERROR) 488cb5caa98Sdjl (me, "unable to find symbol %s\n", func_name[dnsi]); 489cb5caa98Sdjl (void) mutex_unlock(&func_lock); 490cb5caa98Sdjl return (NSCD_CFG_DLSYM_ERROR); 491cb5caa98Sdjl } else { 492cb5caa98Sdjl (void) memcpy(func_p, &sym, sizeof (void *)); 493cb5caa98Sdjl (void) memcpy(&func[dnsi], &sym, sizeof (void *)); 494cb5caa98Sdjl } 495cb5caa98Sdjl 496cb5caa98Sdjl (void) mutex_unlock(&func_lock); 497cb5caa98Sdjl return (NSCD_SUCCESS); 498cb5caa98Sdjl } 499cb5caa98Sdjl 500cb5caa98Sdjl static nss_status_t 501cb5caa98Sdjl search_dns_withttl(nscd_sw_return_t *swret, char *srcname, int dnsi) 502cb5caa98Sdjl { 503cb5caa98Sdjl nss_status_t (*func)(); 504cb5caa98Sdjl nss_status_t res = NSS_UNAVAIL; 505cb5caa98Sdjl nscd_rc_t rc; 506cb5caa98Sdjl 507cb5caa98Sdjl swret->noarg = 0; 508cb5caa98Sdjl if (strcmp(srcname, "dns") != 0) 509cb5caa98Sdjl return (NSS_ERROR); 510cb5caa98Sdjl 511cb5caa98Sdjl rc = get_dns_funcs(dnsi, (void **)&func); 512cb5caa98Sdjl if (rc == NSCD_SUCCESS) 513cb5caa98Sdjl res = (func)(NULL, &swret->pbuf, &swret->pbufsiz); 514cb5caa98Sdjl return (res); 515cb5caa98Sdjl } 516cb5caa98Sdjl 517cb5caa98Sdjl /* 518cb5caa98Sdjl * Returns a flag to indicate if needs to fall back to the 519cb5caa98Sdjl * main nscd when a per-user lookup failed with rc NSS_NOTFOUND. 520cb5caa98Sdjl */ 521cb5caa98Sdjl static int 522cb5caa98Sdjl set_fallback_flag(char *srcname, nss_status_t rc) 523cb5caa98Sdjl { 524cb5caa98Sdjl char *me = "set_fallback_flag"; 525cb5caa98Sdjl if (strcmp(srcname, "ldap") == 0 && rc == NSS_NOTFOUND) { 526cb5caa98Sdjl 527cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG) 528cb5caa98Sdjl (me, "NSS_NOTFOUND (ldap): fallback to main nscd " 529cb5caa98Sdjl "may be needed\n"); 530cb5caa98Sdjl return (1); 531cb5caa98Sdjl } 532cb5caa98Sdjl return (0); 533cb5caa98Sdjl } 534cb5caa98Sdjl 535cb5caa98Sdjl nss_status_t 536cb5caa98Sdjl nss_search(nss_db_root_t *rootp, nss_db_initf_t initf, int search_fnum, 537cb5caa98Sdjl void *search_args) 538cb5caa98Sdjl { 539cb5caa98Sdjl char *me = "nss_search"; 540cb5caa98Sdjl nss_status_t res = NSS_UNAVAIL; 541cb5caa98Sdjl nscd_nsw_state_t *s = NULL; 542cb5caa98Sdjl int n_src; 543cb5caa98Sdjl unsigned int status_vec = 0; 544cb5caa98Sdjl int dbi, srci = -1; 545cb5caa98Sdjl int check_loopback = 0; 546cb5caa98Sdjl int state_thr = 0; 547cb5caa98Sdjl lb_key_t key, *k = NULL; 548cb5caa98Sdjl nss_db_root_t root_db; 549cb5caa98Sdjl nscd_nsw_params_t params; 550cb5caa98Sdjl nscd_sw_return_t *swret; 551cb5caa98Sdjl 552cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG) 553cb5caa98Sdjl (me, "rootp = %p, initf = %p, search_fnum = %d, " 554cb5caa98Sdjl "search_args = %p\n", rootp, initf, 555cb5caa98Sdjl search_fnum, search_args); 556cb5caa98Sdjl 557cb5caa98Sdjl NSCD_SW_STATS_G.lookup_request_received_g++; 558cb5caa98Sdjl NSCD_SW_STATS_G.lookup_request_in_progress_g++; 559cb5caa98Sdjl NSCD_SW_STATS_G.lookup_request_queued_g++; 560cb5caa98Sdjl 561cb5caa98Sdjl /* determine db index, cfg db index, etc */ 562cb5caa98Sdjl (void) getparams(search_fnum, initf, ¶ms); 563cb5caa98Sdjl dbi = params.dbi; 564cb5caa98Sdjl 565cb5caa98Sdjl /* get address of the switch engine return data area */ 566cb5caa98Sdjl if (initf == nscd_initf) { 567cb5caa98Sdjl swret = (nscd_sw_return_t *)params.p.private; 568cb5caa98Sdjl swret->srci = -1; 569cb5caa98Sdjl } else { 570cb5caa98Sdjl swret = NULL; 571cb5caa98Sdjl params.dnsi = -1; 572cb5caa98Sdjl } 573cb5caa98Sdjl 574cb5caa98Sdjl /* 575cb5caa98Sdjl * for request that should be processed by the client, 576cb5caa98Sdjl * send it back with status NSS_TRYLOCAL 577cb5caa98Sdjl */ 578cb5caa98Sdjl if (try_local(dbi, search_args) == 1) { 579cb5caa98Sdjl res = NSS_TRYLOCAL; 580cb5caa98Sdjl goto error_exit; 581cb5caa98Sdjl } 582cb5caa98Sdjl 583cb5caa98Sdjl NSCD_SW_STATS(dbi).lookup_request_received++; 584cb5caa98Sdjl NSCD_SW_STATS(dbi).lookup_request_in_progress++; 585cb5caa98Sdjl NSCD_SW_STATS(dbi).lookup_request_queued++; 586cb5caa98Sdjl 587cb5caa98Sdjl /* if lookup not enabled, return NSS_UNAVAIL */ 588cb5caa98Sdjl if (!(NSCD_SW_CFG_G.enable_lookup_g == nscd_true && 589cb5caa98Sdjl NSCD_SW_CFG(dbi).enable_lookup == nscd_true)) { 590cb5caa98Sdjl 591cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG) 592cb5caa98Sdjl (me, "lookup not enabled for %s\n", NSCD_NSW_DB_NAME(dbi)); 593cb5caa98Sdjl 594cb5caa98Sdjl goto error_exit; 595cb5caa98Sdjl } 596cb5caa98Sdjl 597cb5caa98Sdjl /* determine if loopback checking is configured */ 598cb5caa98Sdjl if (NSCD_SW_CFG_G.enable_loopback_checking_g == nscd_true && 599cb5caa98Sdjl NSCD_SW_CFG(dbi).enable_loopback_checking == nscd_true) { 600cb5caa98Sdjl check_loopback = 1; 601cb5caa98Sdjl 602cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG) 603cb5caa98Sdjl (me, "loopback checking enabled for %s\n", 604cb5caa98Sdjl NSCD_NSW_DB_NAME(dbi)); 605cb5caa98Sdjl } 606cb5caa98Sdjl 607cb5caa98Sdjl if (check_loopback) { 608cb5caa98Sdjl k = get_loopback_key(); 609cb5caa98Sdjl if (k != NULL) { 610cb5caa98Sdjl if (k->dbi != dbi || k->fnum != search_fnum) { 611cb5caa98Sdjl clear_loopback_key(k); 612cb5caa98Sdjl k = NULL; 613cb5caa98Sdjl } 614cb5caa98Sdjl } 615cb5caa98Sdjl } 616cb5caa98Sdjl 617cb5caa98Sdjl if (s == 0) { 618cb5caa98Sdjl nscd_rc_t rc; 619cb5caa98Sdjl 620cb5caa98Sdjl if (check_loopback) { 621cb5caa98Sdjl rc = _nscd_get_nsw_state_thread(&root_db, ¶ms); 622cb5caa98Sdjl state_thr = 1; 623cb5caa98Sdjl } else 624cb5caa98Sdjl rc = _nscd_get_nsw_state(&root_db, ¶ms); 625cb5caa98Sdjl 626cb5caa98Sdjl NSCD_SW_STATS_G.lookup_request_queued_g--; 627cb5caa98Sdjl NSCD_SW_STATS(dbi).lookup_request_queued--; 628cb5caa98Sdjl 629cb5caa98Sdjl if (rc != NSCD_SUCCESS) 630cb5caa98Sdjl goto error_exit; 631cb5caa98Sdjl 632cb5caa98Sdjl s = (nscd_nsw_state_t *)root_db.s; 633cb5caa98Sdjl } 634cb5caa98Sdjl 635cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG) 636cb5caa98Sdjl (me, "database = %s, config = [ %s ]\n", NSCD_NSW_DB_NAME(dbi), 637cb5caa98Sdjl (*s->nsw_cfg_p)->nsw_cfg_str); 638cb5caa98Sdjl 639cb5caa98Sdjl for (n_src = 0; n_src < s->max_src; n_src++) { 640cb5caa98Sdjl nss_backend_t *be; 641cb5caa98Sdjl nss_backend_op_t funcp; 642cb5caa98Sdjl struct __nsw_lookup_v1 *lkp; 643cb5caa98Sdjl int smf_state; 644cb5caa98Sdjl int n_loop = 0; 645cb5caa98Sdjl int max_retry = 10; 646cb5caa98Sdjl 647cb5caa98Sdjl res = NSS_UNAVAIL; 648cb5caa98Sdjl 649cb5caa98Sdjl if (n_src == 0) 650cb5caa98Sdjl lkp = s->config->lookups; 651cb5caa98Sdjl else 652cb5caa98Sdjl lkp = lkp->next; 653cb5caa98Sdjl 654cb5caa98Sdjl /* set the number of max. retries */ 655cb5caa98Sdjl if (lkp->actions[__NSW_TRYAGAIN] == __NSW_TRYAGAIN_NTIMES) 656cb5caa98Sdjl max_retry = lkp->max_retries; 657cb5caa98Sdjl 658cb5caa98Sdjl srci = (*s->nsw_cfg_p)->src_idx[n_src]; 659cb5caa98Sdjl if (swret != NULL) 660cb5caa98Sdjl swret->srci = srci; 661cb5caa98Sdjl 662cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG) 663cb5caa98Sdjl (me, "nsw source = %s\n", NSCD_NSW_SRC_NAME(srci)); 664cb5caa98Sdjl 665cb5caa98Sdjl /* if no privilege to look up, skip */ 666cb5caa98Sdjl if (params.privdb == 1 && swret != NULL && 667cb5caa98Sdjl strcmp(NSCD_NSW_SRC_NAME(srci), "files") == 0 && 668cb5caa98Sdjl _nscd_get_client_euid() != 0) { 669cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, 670cb5caa98Sdjl NSCD_LOG_LEVEL_DEBUG) 671cb5caa98Sdjl (me, "no privilege to look up, skip source\n"); 672cb5caa98Sdjl 673cb5caa98Sdjl goto next_src; 674cb5caa98Sdjl } 675cb5caa98Sdjl 676cb5caa98Sdjl /* get state of the (backend) client service */ 677cb5caa98Sdjl smf_state = _nscd_get_smf_state(srci, dbi, 0); 678cb5caa98Sdjl 679cb5caa98Sdjl /* stop if the source is one that should be TRYLOCAL */ 680cb5caa98Sdjl if (smf_state == NSCD_SVC_STATE_UNKNOWN_SRC) { 681cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, 682cb5caa98Sdjl NSCD_LOG_LEVEL_DEBUG) 683cb5caa98Sdjl (me, "returning TRYLOCAL ... \n"); 684cb5caa98Sdjl res = NSS_TRYLOCAL; 685cb5caa98Sdjl goto free_nsw_state; 686cb5caa98Sdjl } 687cb5caa98Sdjl 688cb5caa98Sdjl if (check_loopback && k != NULL) { 689cb5caa98Sdjl 690cb5caa98Sdjl if (k->srci == srci && k->dbi == dbi) 691cb5caa98Sdjl if (k->fnum == search_fnum) { 692cb5caa98Sdjl 693cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, 694cb5caa98Sdjl NSCD_LOG_LEVEL_DEBUG) 695cb5caa98Sdjl (me, "loopback detected: " 696cb5caa98Sdjl "source = %s, database = %s " 697cb5caa98Sdjl "search fnum = %d\n", 698cb5caa98Sdjl NSCD_NSW_SRC_NAME(srci), 699cb5caa98Sdjl NSCD_NSW_DB_NAME(dbi), search_fnum); 700cb5caa98Sdjl 701cb5caa98Sdjl NSCD_SW_STATS_G.loopback_nsw_db_skipped_g++; 702cb5caa98Sdjl NSCD_SW_STATS(dbi).loopback_nsw_db_skipped++; 703cb5caa98Sdjl continue; 704cb5caa98Sdjl } 705cb5caa98Sdjl } 706cb5caa98Sdjl 707cb5caa98Sdjl be = s->be[n_src]; 708cb5caa98Sdjl if (be != NULL) 709cb5caa98Sdjl funcp = NSS_LOOKUP_DBOP(be, search_fnum); 710cb5caa98Sdjl 711cb5caa98Sdjl if ((params.dnsi >= 0 && be == 0) || (params.dnsi < 0 && 712cb5caa98Sdjl (be == 0 || (smf_state != NSCD_SVC_STATE_UNINITED && 713cb5caa98Sdjl smf_state < SCF_STATE_ONLINE) || funcp == 0))) { 714cb5caa98Sdjl 715cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, 716cb5caa98Sdjl NSCD_LOG_LEVEL_DEBUG) 717cb5caa98Sdjl (me, "unable to look up source %s: be = %p, " 718cb5caa98Sdjl "smf state = %d, funcp = %p\n", 719cb5caa98Sdjl NSCD_NSW_SRC_NAME(srci), be, smf_state, funcp); 720cb5caa98Sdjl 721cb5caa98Sdjl goto next_src; 722cb5caa98Sdjl } 723cb5caa98Sdjl 724cb5caa98Sdjl do { 725cb5caa98Sdjl /* 726cb5caa98Sdjl * we can only retry max_retry times, 727cb5caa98Sdjl * otherwise threads may get stuck in this 728cb5caa98Sdjl * do-while loop forever 729cb5caa98Sdjl */ 730cb5caa98Sdjl if (n_loop > max_retry) { 731cb5caa98Sdjl if (swret != NULL) 732cb5caa98Sdjl res = NSS_TRYLOCAL; 733cb5caa98Sdjl goto free_nsw_state; 734cb5caa98Sdjl } 735cb5caa98Sdjl 736cb5caa98Sdjl /* 737cb5caa98Sdjl * set up to prevent loopback 738cb5caa98Sdjl */ 739cb5caa98Sdjl if (check_loopback && k == NULL) { 740cb5caa98Sdjl key.srci = srci; 741cb5caa98Sdjl key.dbi = dbi; 742cb5caa98Sdjl key.fnum = search_fnum; 743cb5caa98Sdjl key.lb_flagp = &check_loopback; 744cb5caa98Sdjl (void) set_loopback_key(&key); 745cb5caa98Sdjl k = &key; 746cb5caa98Sdjl } 747cb5caa98Sdjl 748cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, 749cb5caa98Sdjl NSCD_LOG_LEVEL_DEBUG) 750cb5caa98Sdjl (me, "looking up source = %s, loop# = %d \n", 751cb5caa98Sdjl NSCD_NSW_SRC_NAME(srci), n_loop); 752cb5caa98Sdjl 753cb5caa98Sdjl /* 754cb5caa98Sdjl * search the backend, if hosts lookups, 755cb5caa98Sdjl * try to get the hosts data with ttl first 756cb5caa98Sdjl */ 757cb5caa98Sdjl if (params.dnsi >= 0) { 758cb5caa98Sdjl res = search_dns_withttl(swret, 759cb5caa98Sdjl NSCD_NSW_SRC_NAME(srci), 760cb5caa98Sdjl params.dnsi); 761cb5caa98Sdjl /* 762cb5caa98Sdjl * if not able to get ttl, fall back 763cb5caa98Sdjl * to the regular backend call 764cb5caa98Sdjl */ 765cb5caa98Sdjl if (res == NSS_ERROR) 766cb5caa98Sdjl res = (*funcp)(be, search_args); 767cb5caa98Sdjl else { 768cb5caa98Sdjl /* 769cb5caa98Sdjl * status/result are in the 770cb5caa98Sdjl * packed buffer, not 771cb5caa98Sdjl * search_args 772cb5caa98Sdjl */ 773cb5caa98Sdjl swret->noarg = 1; 774cb5caa98Sdjl } 775cb5caa98Sdjl } else 776cb5caa98Sdjl res = (*funcp)(be, search_args); 777cb5caa98Sdjl if (swret != NULL) 778cb5caa98Sdjl swret->errnum = errno; 779cb5caa98Sdjl 780cb5caa98Sdjl /* 781cb5caa98Sdjl * backend is not up, check and update the 782cb5caa98Sdjl * smf state table 783cb5caa98Sdjl */ 784cb5caa98Sdjl if (res == NSS_UNAVAIL) 785cb5caa98Sdjl (void) _nscd_get_smf_state(srci, dbi, 1); 786cb5caa98Sdjl 787cb5caa98Sdjl /* 788cb5caa98Sdjl * may need to fall back to use the main nscd 789cb5caa98Sdjl * if per-user lookup 790cb5caa98Sdjl */ 791cb5caa98Sdjl if (_whoami == NSCD_CHILD && swret != NULL) 792cb5caa98Sdjl swret->fallback = set_fallback_flag( 793cb5caa98Sdjl NSCD_NSW_SRC_NAME(srci), res); 794cb5caa98Sdjl 795cb5caa98Sdjl _NSCD_LOG_IF(NSCD_LOG_SWITCH_ENGINE, 796cb5caa98Sdjl NSCD_LOG_LEVEL_DEBUG) { 797cb5caa98Sdjl 798cb5caa98Sdjl /* 799cb5caa98Sdjl * set up to trace the result/status 800cb5caa98Sdjl * of the dns/ttl lookup 801cb5caa98Sdjl */ 802cb5caa98Sdjl if (swret != NULL && swret->noarg == 1) { 803cb5caa98Sdjl nss_pheader_t *phdr; 804cb5caa98Sdjl struct nss_XbyY_args *arg; 805cb5caa98Sdjl arg = (struct nss_XbyY_args *) 806cb5caa98Sdjl search_args; 807cb5caa98Sdjl phdr = (nss_pheader_t *)swret->pbuf; 808cb5caa98Sdjl arg->buf.buffer = (char *)phdr + 809cb5caa98Sdjl phdr->data_off; 810cb5caa98Sdjl arg->returnlen = phdr->data_len; 811cb5caa98Sdjl if (phdr->p_errno == ERANGE) 812cb5caa98Sdjl arg->erange = 1; 813cb5caa98Sdjl arg->h_errno = phdr->p_herrno; 814cb5caa98Sdjl } 815cb5caa98Sdjl 816cb5caa98Sdjl trace_result(dbi, srci, search_fnum, res, 817cb5caa98Sdjl (nss_XbyY_args_t *)search_args); 818cb5caa98Sdjl } 819cb5caa98Sdjl 820cb5caa98Sdjl n_loop++; 821cb5caa98Sdjl } while (retry_test(res, n_loop, lkp)); 822cb5caa98Sdjl 823cb5caa98Sdjl next_src: 824cb5caa98Sdjl 825cb5caa98Sdjl status_vec |= (1 << res); 826cb5caa98Sdjl 827cb5caa98Sdjl if (__NSW_ACTION_V1(lkp, res) == __NSW_RETURN) { 828cb5caa98Sdjl break; 829cb5caa98Sdjl } 830cb5caa98Sdjl } 831cb5caa98Sdjl 832cb5caa98Sdjl free_nsw_state: 833cb5caa98Sdjl 834cb5caa98Sdjl if (state_thr == 1) 835cb5caa98Sdjl _nscd_put_nsw_state_thread(s); 836cb5caa98Sdjl else 837cb5caa98Sdjl _nscd_put_nsw_state(s); 838cb5caa98Sdjl if (check_loopback && k != NULL) 839cb5caa98Sdjl clear_loopback_key(k); 840cb5caa98Sdjl 841cb5caa98Sdjl if (res != NSS_SUCCESS) 842cb5caa98Sdjl goto error_exit; 843cb5caa98Sdjl 844cb5caa98Sdjl NSCD_SW_STATS_G.lookup_request_succeeded_g++; 845cb5caa98Sdjl NSCD_SW_STATS(dbi).lookup_request_succeeded++; 846cb5caa98Sdjl NSCD_SW_STATS_G.lookup_request_in_progress_g--; 847cb5caa98Sdjl NSCD_SW_STATS(dbi).lookup_request_in_progress--; 848cb5caa98Sdjl 849cb5caa98Sdjl return (NSS_SUCCESS); 850cb5caa98Sdjl 851cb5caa98Sdjl error_exit: 852cb5caa98Sdjl 853cb5caa98Sdjl NSCD_SW_STATS_G.lookup_request_failed_g++; 854cb5caa98Sdjl NSCD_SW_STATS_G.lookup_request_in_progress_g--; 855cb5caa98Sdjl NSCD_SW_STATS(dbi).lookup_request_failed++; 856cb5caa98Sdjl NSCD_SW_STATS(dbi).lookup_request_in_progress--; 857cb5caa98Sdjl 858cb5caa98Sdjl return (res); 859cb5caa98Sdjl } 860cb5caa98Sdjl 861cb5caa98Sdjl 862cb5caa98Sdjl /* ===> get/set/endent */ 863cb5caa98Sdjl 864cb5caa98Sdjl static void nss_setent_u(nss_db_root_t *, 865cb5caa98Sdjl nss_db_initf_t, 866cb5caa98Sdjl nss_getent_t *); 867cb5caa98Sdjl static nss_status_t nss_getent_u(nss_db_root_t *, 868cb5caa98Sdjl nss_db_initf_t, 869cb5caa98Sdjl nss_getent_t *, 870cb5caa98Sdjl void *); 871cb5caa98Sdjl static void nss_endent_u(nss_db_root_t *, 872cb5caa98Sdjl nss_db_initf_t, 873cb5caa98Sdjl nss_getent_t *); 874cb5caa98Sdjl 875cb5caa98Sdjl void 876cb5caa98Sdjl nss_setent(nss_db_root_t *rootp, nss_db_initf_t initf, 877cb5caa98Sdjl nss_getent_t *contextpp) 878cb5caa98Sdjl { 879cb5caa98Sdjl if (contextpp == 0) 880cb5caa98Sdjl return; 881cb5caa98Sdjl nss_setent_u(rootp, initf, contextpp); 882cb5caa98Sdjl } 883cb5caa98Sdjl 884cb5caa98Sdjl nss_status_t 885cb5caa98Sdjl nss_getent(nss_db_root_t *rootp, nss_db_initf_t initf, nss_getent_t *contextpp, 886cb5caa98Sdjl void *args) 887cb5caa98Sdjl { 888cb5caa98Sdjl nss_status_t status; 889cb5caa98Sdjl 890cb5caa98Sdjl if (contextpp == 0) { 891cb5caa98Sdjl return (NSS_UNAVAIL); 892cb5caa98Sdjl } 893cb5caa98Sdjl status = nss_getent_u(rootp, initf, contextpp, args); 894cb5caa98Sdjl return (status); 895cb5caa98Sdjl } 896cb5caa98Sdjl 897cb5caa98Sdjl void 898cb5caa98Sdjl nss_endent(nss_db_root_t *rootp, nss_db_initf_t initf, 899cb5caa98Sdjl nss_getent_t *contextpp) 900cb5caa98Sdjl { 901cb5caa98Sdjl if (contextpp == 0) 902cb5caa98Sdjl return; 903cb5caa98Sdjl nss_endent_u(rootp, initf, contextpp); 904cb5caa98Sdjl } 905cb5caa98Sdjl 906cb5caa98Sdjl /*ARGSUSED*/ 907cb5caa98Sdjl static void 908cb5caa98Sdjl end_iter_u(nss_db_root_t *rootp, struct nss_getent_context *contextp) 909cb5caa98Sdjl { 910cb5caa98Sdjl nscd_getent_context_t *ctx; 911cb5caa98Sdjl nscd_nsw_state_t *s; 912cb5caa98Sdjl nss_backend_t *be; 913cb5caa98Sdjl int n_src; 914cb5caa98Sdjl 915cb5caa98Sdjl ctx = (nscd_getent_context_t *)contextp; 916cb5caa98Sdjl s = ctx->nsw_state; 917cb5caa98Sdjl n_src = ctx->n_src; 918cb5caa98Sdjl be = ctx->be; 919cb5caa98Sdjl 920cb5caa98Sdjl if (s != 0) { 921cb5caa98Sdjl if (n_src < s->max_src && be != 0) { 922cb5caa98Sdjl (void) NSS_INVOKE_DBOP(be, NSS_DBOP_ENDENT, 0); 923cb5caa98Sdjl ctx->be = 0; /* Should be unnecessary, but hey */ 924cb5caa98Sdjl } 925cb5caa98Sdjl } 926cb5caa98Sdjl ctx->n_src = 0; 927cb5caa98Sdjl } 928cb5caa98Sdjl 929cb5caa98Sdjl static void 930cb5caa98Sdjl nss_setent_u(nss_db_root_t *rootp, nss_db_initf_t initf, 931cb5caa98Sdjl nss_getent_t *contextpp) 932cb5caa98Sdjl { 933cb5caa98Sdjl char *me = "nss_setent_u"; 934cb5caa98Sdjl nscd_nsw_state_t *s; 935cb5caa98Sdjl nscd_getent_context_t *contextp; 936cb5caa98Sdjl nscd_nsw_params_t params; 937cb5caa98Sdjl nss_db_root_t root; 938cb5caa98Sdjl nss_backend_t *be; 939cb5caa98Sdjl int n_src, i; 940cb5caa98Sdjl nscd_sw_return_t *swret = NULL; 941cb5caa98Sdjl 942cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG) 943cb5caa98Sdjl (me, "rootp = %p, initf = %p, contextpp = %p \n", 944cb5caa98Sdjl rootp, initf, contextpp); 945cb5caa98Sdjl 946cb5caa98Sdjl /* get the nsw db index via the initf function */ 947cb5caa98Sdjl (void) getparams(-1, initf, ¶ms); 948cb5caa98Sdjl 949cb5caa98Sdjl /* get address of the switch engine return data area */ 950cb5caa98Sdjl if (initf == nscd_initf) 951cb5caa98Sdjl swret = (nscd_sw_return_t *)params.p.private; 952cb5caa98Sdjl 953cb5caa98Sdjl /* if no privilege to look up, return */ 954cb5caa98Sdjl if (params.privdb == 1 && swret != NULL && 955cb5caa98Sdjl ((nss_pheader_t *)(swret->pbuf))->p_euid != 0) { 956cb5caa98Sdjl 957cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG) 958cb5caa98Sdjl (me, "no privilege \n"); 959cb5caa98Sdjl return; 960cb5caa98Sdjl } 961cb5caa98Sdjl 962cb5caa98Sdjl if ((contextp = (nscd_getent_context_t *)contextpp->ctx) == 0) { 963cb5caa98Sdjl if ((_nscd_get_getent_ctx(contextpp, ¶ms)) != 964cb5caa98Sdjl NSCD_SUCCESS) { 965cb5caa98Sdjl return; 966cb5caa98Sdjl } 967cb5caa98Sdjl contextp = (nscd_getent_context_t *)contextpp->ctx; 968cb5caa98Sdjl } 969cb5caa98Sdjl s = contextp->nsw_state; 970cb5caa98Sdjl 971cb5caa98Sdjl if (s == 0) { 972cb5caa98Sdjl if (_nscd_get_nsw_state(&root, ¶ms) != 973cb5caa98Sdjl NSCD_SUCCESS) { 974cb5caa98Sdjl return; 975cb5caa98Sdjl } 976cb5caa98Sdjl s = (nscd_nsw_state_t *)root.s; 977cb5caa98Sdjl contextp->nsw_state = s; 978cb5caa98Sdjl 979cb5caa98Sdjl } else { 980cb5caa98Sdjl s = contextp->nsw_state; 981cb5caa98Sdjl n_src = contextp->n_src; 982cb5caa98Sdjl be = contextp->be; 983cb5caa98Sdjl if (n_src == 0 && be != 0) { 984cb5caa98Sdjl /* 985cb5caa98Sdjl * Optimization: don't do endent, don't change 986cb5caa98Sdjl * backends, just do the setent. Look Ma, no locks 987cb5caa98Sdjl * (nor any context that needs updating). 988cb5caa98Sdjl */ 989cb5caa98Sdjl (void) NSS_INVOKE_DBOP(be, NSS_DBOP_SETENT, 0); 990cb5caa98Sdjl return; 991cb5caa98Sdjl } 992cb5caa98Sdjl if (n_src < s->max_src && be != 0) { 993cb5caa98Sdjl (void) NSS_INVOKE_DBOP(be, NSS_DBOP_ENDENT, 0); 994cb5caa98Sdjl contextp->be = 0; /* Play it safe */ 995cb5caa98Sdjl } 996cb5caa98Sdjl } 997cb5caa98Sdjl for (n_src = 0, be = 0; n_src < s->max_src && 998cb5caa98Sdjl (be = s->be[n_src]) == 0; n_src++) { 999cb5caa98Sdjl ; 1000cb5caa98Sdjl } 1001cb5caa98Sdjl 1002cb5caa98Sdjl contextp->n_src = n_src; 1003cb5caa98Sdjl contextp->be = be; 1004cb5caa98Sdjl 1005cb5caa98Sdjl if (be == 0) { 1006cb5caa98Sdjl /* Things are broken enough that we can't do setent/getent */ 1007cb5caa98Sdjl nss_endent_u(rootp, initf, contextpp); 1008cb5caa98Sdjl return; 1009cb5caa98Sdjl } 1010cb5caa98Sdjl 1011cb5caa98Sdjl /* 1012cb5caa98Sdjl * make sure all the backends are supported 1013cb5caa98Sdjl */ 1014cb5caa98Sdjl for (i = 0; i < s->max_src; i++) { 1015cb5caa98Sdjl int st, srci; 1016cb5caa98Sdjl 1017cb5caa98Sdjl srci = (*s->nsw_cfg_p)->src_idx[i]; 1018cb5caa98Sdjl st = _nscd_get_smf_state(srci, params.dbi, 1); 1019cb5caa98Sdjl if (st == NSCD_SVC_STATE_UNKNOWN_SRC || 1020cb5caa98Sdjl st == NSCD_SVC_STATE_UNINITED) { 1021cb5caa98Sdjl nss_endent_u(rootp, initf, contextpp); 1022cb5caa98Sdjl 1023cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, 1024cb5caa98Sdjl NSCD_LOG_LEVEL_DEBUG) 1025cb5caa98Sdjl (me, "backend (%s) not available (state = %d)\n", 1026cb5caa98Sdjl NSCD_NSW_SRC_NAME(srci), st); 1027cb5caa98Sdjl 1028cb5caa98Sdjl return; 1029cb5caa98Sdjl } 1030cb5caa98Sdjl } 1031cb5caa98Sdjl 1032cb5caa98Sdjl (void) NSS_INVOKE_DBOP(be, NSS_DBOP_SETENT, 0); 1033cb5caa98Sdjl } 1034cb5caa98Sdjl 1035cb5caa98Sdjl nss_status_t 1036cb5caa98Sdjl nss_getent_u(nss_db_root_t *rootp, nss_db_initf_t initf, 1037cb5caa98Sdjl nss_getent_t *contextpp, void *args) 1038cb5caa98Sdjl { 1039cb5caa98Sdjl char *me = "nss_getent_u"; 1040cb5caa98Sdjl nscd_nsw_state_t *s; 1041cb5caa98Sdjl nscd_getent_context_t *contextp; 1042cb5caa98Sdjl int n_src; 1043cb5caa98Sdjl nss_backend_t *be; 1044cb5caa98Sdjl 1045cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG) 1046cb5caa98Sdjl (me, "rootp = %p, initf = %p, contextpp = %p, args = %p\n", 1047cb5caa98Sdjl rootp, initf, contextpp, args); 1048cb5caa98Sdjl 1049cb5caa98Sdjl if ((contextp = (nscd_getent_context_t *)contextpp->ctx) == 0) { 1050cb5caa98Sdjl nss_setent_u(rootp, initf, contextpp); 1051cb5caa98Sdjl if ((contextp = (nscd_getent_context_t *)contextpp->ctx) == 0) { 1052cb5caa98Sdjl /* Give up */ 1053cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, 1054cb5caa98Sdjl NSCD_LOG_LEVEL_ERROR) 1055cb5caa98Sdjl (me, "not able to obtain getent context ... give up\n"); 1056cb5caa98Sdjl 1057cb5caa98Sdjl return (NSS_UNAVAIL); 1058cb5caa98Sdjl } 1059cb5caa98Sdjl } 1060cb5caa98Sdjl 1061cb5caa98Sdjl s = contextp->nsw_state; 1062cb5caa98Sdjl n_src = contextp->n_src; 1063cb5caa98Sdjl be = contextp->be; 1064cb5caa98Sdjl 1065cb5caa98Sdjl if (s == 0) { 1066cb5caa98Sdjl /* 1067cb5caa98Sdjl * We've done an end_iter() and haven't done nss_setent() 1068cb5caa98Sdjl * or nss_endent() since; we should stick in this state 1069cb5caa98Sdjl * until the caller invokes one of those two routines. 1070cb5caa98Sdjl */ 1071cb5caa98Sdjl return (NSS_SUCCESS); 1072cb5caa98Sdjl } 1073cb5caa98Sdjl 1074cb5caa98Sdjl while (n_src < s->max_src) { 1075cb5caa98Sdjl nss_status_t res; 1076cb5caa98Sdjl struct __nsw_lookup_v1 *lkp = NULL; 1077cb5caa98Sdjl int n; 1078cb5caa98Sdjl 1079cb5caa98Sdjl /* get the nsw config for the current source */ 1080cb5caa98Sdjl lkp = s->config->lookups; 1081cb5caa98Sdjl for (n = 0; n < n_src; n++) 1082cb5caa98Sdjl lkp = lkp->next; 1083cb5caa98Sdjl 1084cb5caa98Sdjl if (be == 0) { 1085cb5caa98Sdjl /* If it's null it's a bug, but let's play safe */ 1086cb5caa98Sdjl res = NSS_UNAVAIL; 1087cb5caa98Sdjl } else { 1088cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, 1089cb5caa98Sdjl NSCD_LOG_LEVEL_DEBUG) 1090cb5caa98Sdjl (me, "database: %s, backend: %s, nsswitch config: %s\n", 1091cb5caa98Sdjl NSCD_NSW_DB_NAME(s->dbi), 1092cb5caa98Sdjl lkp->service_name, 1093cb5caa98Sdjl (*s->nsw_cfg_p)->nsw_cfg_str); 1094cb5caa98Sdjl 1095cb5caa98Sdjl res = NSS_INVOKE_DBOP(be, NSS_DBOP_GETENT, args); 1096cb5caa98Sdjl } 1097cb5caa98Sdjl 1098cb5caa98Sdjl if (__NSW_ACTION_V1(lkp, res) == __NSW_RETURN) { 1099cb5caa98Sdjl if (res != __NSW_SUCCESS) { 1100cb5caa98Sdjl end_iter_u(rootp, 1101cb5caa98Sdjl (struct nss_getent_context *)contextp); 1102cb5caa98Sdjl } 1103cb5caa98Sdjl return (res); 1104cb5caa98Sdjl } 1105cb5caa98Sdjl (void) NSS_INVOKE_DBOP(be, NSS_DBOP_ENDENT, 0); 1106cb5caa98Sdjl do { 1107cb5caa98Sdjl n_src++; 1108cb5caa98Sdjl } while (n_src < s->max_src && 1109cb5caa98Sdjl (be = s->be[n_src]) == 0); 1110cb5caa98Sdjl if (be == 0) { 1111cb5caa98Sdjl /* 1112cb5caa98Sdjl * This is the case where we failed to get the backend 1113cb5caa98Sdjl * for the last source. We exhausted all sources. 1114cb5caa98Sdjl */ 1115cb5caa98Sdjl nss_endent_u(rootp, initf, contextpp); 1116cb5caa98Sdjl return (NSS_SUCCESS); 1117cb5caa98Sdjl } 1118cb5caa98Sdjl contextp->n_src = n_src; 1119cb5caa98Sdjl contextp->be = be; 1120cb5caa98Sdjl (void) NSS_INVOKE_DBOP(be, NSS_DBOP_SETENT, 0); 1121cb5caa98Sdjl } 1122cb5caa98Sdjl /* Got to the end of the sources without finding another entry */ 1123cb5caa98Sdjl end_iter_u(rootp, (struct nss_getent_context *)contextp); 1124cb5caa98Sdjl return (NSS_SUCCESS); 1125cb5caa98Sdjl /* success is either a successful entry or end of the sources */ 1126cb5caa98Sdjl } 1127cb5caa98Sdjl 1128cb5caa98Sdjl /*ARGSUSED*/ 1129cb5caa98Sdjl void 1130cb5caa98Sdjl nss_endent_u(nss_db_root_t *rootp, nss_db_initf_t initf, 1131cb5caa98Sdjl nss_getent_t *contextpp) 1132cb5caa98Sdjl { 1133cb5caa98Sdjl char *me = "nss_endent_u"; 1134cb5caa98Sdjl nscd_getent_context_t *contextp; 1135cb5caa98Sdjl 1136cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG) 1137cb5caa98Sdjl (me, "rootp = %p, initf = %p, contextpp = %p \n", 1138cb5caa98Sdjl rootp, initf, contextpp); 1139cb5caa98Sdjl 1140cb5caa98Sdjl if ((contextp = (nscd_getent_context_t *)contextpp->ctx) == 0) { 1141cb5caa98Sdjl /* nss_endent() on an unused context is a no-op */ 1142cb5caa98Sdjl return; 1143cb5caa98Sdjl } 1144cb5caa98Sdjl end_iter_u(rootp, (struct nss_getent_context *)contextp); 1145cb5caa98Sdjl _nscd_put_getent_ctx(contextp); 1146cb5caa98Sdjl contextpp->ctx = NULL; 1147cb5caa98Sdjl } 1148cb5caa98Sdjl 1149cb5caa98Sdjl /* 1150cb5caa98Sdjl * _nss_db_state_destr() and nss_delete() do nothing in nscd 1151cb5caa98Sdjl * but is needed to make the caller (below nscd) happy 1152cb5caa98Sdjl */ 1153cb5caa98Sdjl /*ARGSUSED*/ 1154cb5caa98Sdjl void 1155cb5caa98Sdjl _nss_db_state_destr(struct nss_db_state *s) 1156cb5caa98Sdjl { 1157cb5caa98Sdjl /* nsw state in nscd is always reused, so do nothing here */ 1158cb5caa98Sdjl } 1159cb5caa98Sdjl 1160cb5caa98Sdjl /*ARGSUSED*/ 1161cb5caa98Sdjl void 1162cb5caa98Sdjl nss_delete(nss_db_root_t *rootp) 1163cb5caa98Sdjl { 1164cb5caa98Sdjl /* 1165cb5caa98Sdjl * the only resource kept tracked by the nss_db_root_t 1166cb5caa98Sdjl * is the nsw state which is always reused and no need 1167cb5caa98Sdjl * to be freed. So just return. 1168cb5caa98Sdjl */ 1169cb5caa98Sdjl } 1170cb5caa98Sdjl 1171cb5caa98Sdjl /* 1172cb5caa98Sdjl * Start of nss_psearch/nss_psetent()/nss_pgetent()/nss_pendent() 1173cb5caa98Sdjl * buffers switch entry points 1174cb5caa98Sdjl */ 1175cb5caa98Sdjl 1176cb5caa98Sdjl /* 1177cb5caa98Sdjl * nss_psearch opens a packed structure header, assembles a local 1178cb5caa98Sdjl * nss_XbyY_args_t structure and calls the local copy of nss_search. 1179cb5caa98Sdjl * The return data is assembled in "files native format" in the 1180cb5caa98Sdjl * return buffer location. Status if packed back up with the buffer 1181cb5caa98Sdjl * and the whole wad is returned to the cache or the client. 1182cb5caa98Sdjl */ 1183cb5caa98Sdjl 1184cb5caa98Sdjl void 1185cb5caa98Sdjl nss_psearch(void *buffer, size_t length) 1186cb5caa98Sdjl { 1187cb5caa98Sdjl /* inputs */ 1188cb5caa98Sdjl nss_db_initf_t initf; 1189cb5caa98Sdjl int dbop; 1190cb5caa98Sdjl int rc; 1191cb5caa98Sdjl nss_XbyY_args_t arg; 1192cb5caa98Sdjl nss_status_t status; 1193cb5caa98Sdjl nscd_sw_return_t swret = { 0 }, *swrp = &swret; 1194cb5caa98Sdjl nss_pheader_t *pbuf = (nss_pheader_t *)buffer; 1195cb5caa98Sdjl char *me = "nss_psearch"; 1196cb5caa98Sdjl 1197cb5caa98Sdjl if (buffer == NULL || length == 0) { 1198cb5caa98Sdjl NSCD_RETURN_STATUS(pbuf, NSS_ERROR, EFAULT); 1199cb5caa98Sdjl } 1200cb5caa98Sdjl 1201cb5caa98Sdjl status = nss_packed_arg_init(buffer, length, 1202cb5caa98Sdjl NULL, &initf, &dbop, &arg); 1203cb5caa98Sdjl if (status != NSS_SUCCESS) { 1204cb5caa98Sdjl NSCD_RETURN_STATUS(pbuf, status, -1); 1205cb5caa98Sdjl } 1206cb5caa98Sdjl 1207cb5caa98Sdjl /* 1208cb5caa98Sdjl * pass the address of the return data area 1209cb5caa98Sdjl * for the switch engine to return its own data 1210cb5caa98Sdjl */ 1211cb5caa98Sdjl (void) memcpy(&pbuf->nscdpriv, &swrp, sizeof (swrp)); 1212cb5caa98Sdjl swret.pbuf = buffer; 1213cb5caa98Sdjl swret.pbufsiz = length; 1214cb5caa98Sdjl 1215cb5caa98Sdjl /* 1216cb5caa98Sdjl * use the generic nscd_initf for all database lookups 1217cb5caa98Sdjl * (the TSD key is the pointer to the packed header) 1218cb5caa98Sdjl */ 1219cb5caa98Sdjl rc = set_initf_key(pbuf); 1220cb5caa98Sdjl if (rc != 0) { 1221cb5caa98Sdjl NSCD_RETURN_STATUS(pbuf, NSS_UNAVAIL, EINVAL); 1222cb5caa98Sdjl } 1223cb5caa98Sdjl initf = nscd_initf; 1224cb5caa98Sdjl 1225cb5caa98Sdjl /* Perform local search and pack results into return buffer */ 1226cb5caa98Sdjl /* nscd's search ignores db_root */ 1227cb5caa98Sdjl status = nss_search(NULL, initf, dbop, &arg); 1228cb5caa98Sdjl 1229cb5caa98Sdjl /* 1230cb5caa98Sdjl * If status is NSS_NOTFOUND and ldap also returned 1231cb5caa98Sdjl * NSS_NOTFOUND, it is possible that the user does 1232cb5caa98Sdjl * not have a credential, so check and see if 1233cb5caa98Sdjl * needs to return NSS_ALTRETRY to let the main 1234cb5caa98Sdjl * nscd get a chance to process the lookup 1235cb5caa98Sdjl */ 1236cb5caa98Sdjl if (swret.fallback == 1 && status == NSS_NOTFOUND) { 1237cb5caa98Sdjl OM_uint32 stat; 1238cb5caa98Sdjl 1239cb5caa98Sdjl if (gss_inquire_cred(&stat, GSS_C_NO_CREDENTIAL, 1240cb5caa98Sdjl NULL, NULL, NULL, NULL) != GSS_S_COMPLETE) { 1241cb5caa98Sdjl 1242cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, 1243cb5caa98Sdjl NSCD_LOG_LEVEL_DEBUG) 1244cb5caa98Sdjl (me, "NSS_ALTRETRY: fallback to main nscd needed\n"); 1245cb5caa98Sdjl 1246cb5caa98Sdjl status = NSS_ALTRETRY; 1247cb5caa98Sdjl } 1248cb5caa98Sdjl } 1249cb5caa98Sdjl 1250cb5caa98Sdjl NSCD_SET_STATUS(pbuf, status, -1); 1251cb5caa98Sdjl errno = swret.errnum; 1252cb5caa98Sdjl 1253cb5caa98Sdjl /* 1254cb5caa98Sdjl * move result/status from args to packed buffer only if 1255cb5caa98Sdjl * arg was being used 1256cb5caa98Sdjl */ 1257cb5caa98Sdjl if (!swret.noarg) 1258cb5caa98Sdjl nss_packed_set_status(buffer, length, status, &arg); 1259cb5caa98Sdjl 1260cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG) 1261cb5caa98Sdjl (me, "switch engine result: source is %s, status %d, " 1262cb5caa98Sdjl "herrno is %d, errno is %s\n", 1263cb5caa98Sdjl (swret.srci != -1) ? NSCD_NSW_SRC_NAME(swret.srci) : "<NOTSET>", 1264cb5caa98Sdjl pbuf->p_status, pbuf->p_herrno, strerror(pbuf->p_errno)); 1265cb5caa98Sdjl 1266cb5caa98Sdjl /* clear the TSD key used by the generic initf */ 1267cb5caa98Sdjl clear_initf_key(); 1268cb5caa98Sdjl pbuf->nscdpriv = 0; 1269cb5caa98Sdjl } 1270cb5caa98Sdjl 1271cb5caa98Sdjl static void 1272cb5caa98Sdjl nscd_map_contextp(void *buffer, nss_getent_t *contextp, 1273cb5caa98Sdjl nssuint_t **cookie_p, nssuint_t **seqnum_p, int setent) 1274cb5caa98Sdjl { 1275cb5caa98Sdjl nss_pheader_t *pbuf = (nss_pheader_t *)buffer; 1276cb5caa98Sdjl nssuint_t off; 1277cb5caa98Sdjl nscd_getent_context_t *ctx; 1278cb5caa98Sdjl char *me = "nscd_map_contextp"; 1279cb5caa98Sdjl 1280cb5caa98Sdjl struct cookie_seqnum { 1281cb5caa98Sdjl nssuint_t cookie; 1282cb5caa98Sdjl nssuint_t seqnum; 1283cb5caa98Sdjl } *csp; 1284cb5caa98Sdjl 1285cb5caa98Sdjl if (buffer == NULL) { 1286cb5caa98Sdjl NSCD_RETURN_STATUS(pbuf, NSS_ERROR, EFAULT); 1287cb5caa98Sdjl } 1288cb5caa98Sdjl 1289cb5caa98Sdjl off = pbuf->key_off; 1290cb5caa98Sdjl csp = (struct cookie_seqnum *)((void *)((char *)buffer + off)); 1291cb5caa98Sdjl if (seqnum_p != NULL) 1292cb5caa98Sdjl *seqnum_p = &csp->seqnum; 1293cb5caa98Sdjl 1294cb5caa98Sdjl /* 1295cb5caa98Sdjl * if called by nss_psetent, and the passed in cookie is 1296cb5caa98Sdjl * NSCD_NEW_COOKIE, then there is no cookie yet, return 1297cb5caa98Sdjl * a pointer pointing to where the cookie will be stored. 1298cb5caa98Sdjl * Also because there is no cookie to validate, just 1299cb5caa98Sdjl * return success. 1300cb5caa98Sdjl * 1301cb5caa98Sdjl * On the other hand, if a cookie is passed in, we need 1302cb5caa98Sdjl * to validate the cookie before returning. 1303cb5caa98Sdjl */ 1304cb5caa98Sdjl if (cookie_p != NULL) 1305cb5caa98Sdjl *cookie_p = &csp->cookie; 1306cb5caa98Sdjl if (setent == 1 && csp->cookie == NSCD_NEW_COOKIE) { 1307cb5caa98Sdjl NSCD_RETURN_STATUS_SUCCESS(pbuf); 1308cb5caa98Sdjl } 1309cb5caa98Sdjl 1310cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG) 1311cb5caa98Sdjl (me, "cookie = %lld, sequence number = %lld\n", 1312cb5caa98Sdjl csp->cookie, csp->seqnum); 1313cb5caa98Sdjl 1314cb5caa98Sdjl ctx = _nscd_is_getent_ctx(csp->cookie); 1315cb5caa98Sdjl 1316cb5caa98Sdjl if (ctx == NULL) { 1317cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG) 1318cb5caa98Sdjl (me, "invalid cookie (%lld)\n", csp->cookie); 1319cb5caa98Sdjl 1320cb5caa98Sdjl NSCD_RETURN_STATUS(pbuf, NSS_ERROR, EFAULT); 1321cb5caa98Sdjl } 1322cb5caa98Sdjl 1323cb5caa98Sdjl if (setent == 1) { 1324cb5caa98Sdjl /* if called by nss_psetent, reset the seq number */ 1325cb5caa98Sdjl ctx->seq_num = 1; 1326cb5caa98Sdjl } else if (ctx->seq_num != (nscd_seq_num_t)csp->seqnum) { 1327cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG) 1328cb5caa98Sdjl (me, "invalid sequence number (%lld)\n", csp->seqnum); 1329cb5caa98Sdjl 1330cb5caa98Sdjl NSCD_RETURN_STATUS(pbuf, NSS_ERROR, EFAULT); 1331cb5caa98Sdjl } 1332cb5caa98Sdjl 1333cb5caa98Sdjl contextp->ctx = (struct nss_getent_context *)ctx; 1334cb5caa98Sdjl 1335cb5caa98Sdjl NSCD_RETURN_STATUS_SUCCESS(pbuf); 1336cb5caa98Sdjl } 1337cb5caa98Sdjl 1338cb5caa98Sdjl void 1339cb5caa98Sdjl nss_psetent(void *buffer, size_t length, pid_t pid) 1340cb5caa98Sdjl { 1341cb5caa98Sdjl /* inputs */ 1342cb5caa98Sdjl nss_db_initf_t initf; 1343cb5caa98Sdjl nss_getent_t context = { 0 }; 1344cb5caa98Sdjl nss_getent_t *contextp = &context; 1345cb5caa98Sdjl nss_status_t status; 1346cb5caa98Sdjl nssuint_t *cookiep; 1347cb5caa98Sdjl nssuint_t *seqnump; 1348cb5caa98Sdjl nscd_getent_context_t *ctx; 1349cb5caa98Sdjl int rc; 1350cb5caa98Sdjl nss_pheader_t *pbuf = (nss_pheader_t *)buffer; 1351cb5caa98Sdjl nscd_sw_return_t swret = { 0 }, *swrp = &swret; 1352cb5caa98Sdjl char *me = "nss_psetent"; 1353cb5caa98Sdjl 1354cb5caa98Sdjl if (buffer == NULL || length == 0) { 1355cb5caa98Sdjl NSCD_RETURN_STATUS(pbuf, NSS_ERROR, EFAULT); 1356cb5caa98Sdjl } 1357cb5caa98Sdjl 1358cb5caa98Sdjl /* 1359cb5caa98Sdjl * If this is a per-user nscd, and the user does not have 1360cb5caa98Sdjl * the necessary credential, return NSS_TRYLOCAL, so the 1361cb5caa98Sdjl * setent/getent can be done locally in the process of the 1362cb5caa98Sdjl * setent call 1363cb5caa98Sdjl */ 1364cb5caa98Sdjl if (_whoami == NSCD_CHILD) { 1365cb5caa98Sdjl OM_uint32 stat; 1366cb5caa98Sdjl 1367cb5caa98Sdjl if (gss_inquire_cred(&stat, GSS_C_NO_CREDENTIAL, 1368cb5caa98Sdjl NULL, NULL, NULL, NULL) != GSS_S_COMPLETE) { 1369cb5caa98Sdjl 1370cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, 1371cb5caa98Sdjl NSCD_LOG_LEVEL_DEBUG) 1372cb5caa98Sdjl (me, "NSS_TRYLOCAL: fallback to caller process\n"); 1373cb5caa98Sdjl NSCD_RETURN_STATUS(pbuf, NSS_TRYLOCAL, 0); 1374cb5caa98Sdjl } 1375cb5caa98Sdjl } 1376cb5caa98Sdjl 1377cb5caa98Sdjl status = nss_packed_context_init(buffer, length, 1378cb5caa98Sdjl NULL, &initf, &contextp, (nss_XbyY_args_t *)NULL); 1379cb5caa98Sdjl if (status != NSS_SUCCESS) { 1380cb5caa98Sdjl NSCD_RETURN_STATUS(pbuf, status, -1); 1381cb5caa98Sdjl } 1382cb5caa98Sdjl 1383cb5caa98Sdjl /* 1384cb5caa98Sdjl * use the generic nscd_initf for all the setent requests 1385cb5caa98Sdjl * (the TSD key is the pointer to the packed header) 1386cb5caa98Sdjl */ 1387cb5caa98Sdjl rc = set_initf_key(pbuf); 1388cb5caa98Sdjl if (rc != 0) { 1389cb5caa98Sdjl NSCD_RETURN_STATUS(pbuf, NSS_UNAVAIL, EINVAL); 1390cb5caa98Sdjl } 1391cb5caa98Sdjl initf = nscd_initf; 1392cb5caa98Sdjl 1393cb5caa98Sdjl /* get address of cookie and seqnum for later updates */ 1394cb5caa98Sdjl nscd_map_contextp(buffer, contextp, &cookiep, &seqnump, 1); 1395cb5caa98Sdjl if (NSCD_STATUS_IS_NOT_OK(pbuf)) 1396cb5caa98Sdjl return; 1397cb5caa98Sdjl /* 1398cb5caa98Sdjl * pass the packed header buffer pointer to nss_setent 1399cb5caa98Sdjl */ 1400cb5caa98Sdjl (void) memcpy(&pbuf->nscdpriv, &swrp, sizeof (swrp)); 1401cb5caa98Sdjl swret.pbuf = buffer; 1402cb5caa98Sdjl 1403cb5caa98Sdjl /* Perform local setent and set context */ 1404cb5caa98Sdjl nss_setent(NULL, initf, contextp); 1405cb5caa98Sdjl 1406cb5caa98Sdjl /* insert cookie info into buffer and return */ 1407cb5caa98Sdjl ctx = (nscd_getent_context_t *)contextp->ctx; 1408cb5caa98Sdjl if (ctx != NULL) { 1409cb5caa98Sdjl *cookiep = ctx->cookie; 1410cb5caa98Sdjl *seqnump = (nssuint_t)ctx->seq_num; 1411cb5caa98Sdjl ctx->pid = pid; 1412cb5caa98Sdjl } else { 1413cb5caa98Sdjl /* 1414cb5caa98Sdjl * not able to allocate a getent context, the 1415cb5caa98Sdjl * client should try the enumeration locally 1416cb5caa98Sdjl */ 1417cb5caa98Sdjl *cookiep = NSCD_LOCAL_COOKIE; 1418cb5caa98Sdjl *seqnump = 0; 1419cb5caa98Sdjl } 1420cb5caa98Sdjl 1421cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG) 1422cb5caa98Sdjl (me, "cookie = %lld, sequence number = %lld\n", 1423cb5caa98Sdjl *cookiep, *seqnump); 1424cb5caa98Sdjl 1425cb5caa98Sdjl if (ctx != NULL) { 1426cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG) 1427cb5caa98Sdjl (me, "cookie = %lld, sequence number = %lld\n", 1428cb5caa98Sdjl ctx->cookie, ctx->seq_num); 1429cb5caa98Sdjl } 1430cb5caa98Sdjl 1431cb5caa98Sdjl /* clear the TSD key used by the generic initf */ 1432cb5caa98Sdjl clear_initf_key(); 1433cb5caa98Sdjl 1434cb5caa98Sdjl if (*cookiep == NSCD_LOCAL_COOKIE) { 1435cb5caa98Sdjl NSCD_RETURN_STATUS(pbuf, NSS_TRYLOCAL, 0); 1436cb5caa98Sdjl } else { 1437cb5caa98Sdjl NSCD_RETURN_STATUS(pbuf, NSS_SUCCESS, 0); 1438cb5caa98Sdjl } 1439cb5caa98Sdjl } 1440cb5caa98Sdjl 1441cb5caa98Sdjl void 1442cb5caa98Sdjl nss_pgetent(void *buffer, size_t length) 1443cb5caa98Sdjl { 1444cb5caa98Sdjl /* inputs */ 1445cb5caa98Sdjl nss_db_initf_t initf; 1446cb5caa98Sdjl nss_getent_t context; 1447cb5caa98Sdjl nss_getent_t *contextp = &context; 1448cb5caa98Sdjl nss_XbyY_args_t arg; 1449cb5caa98Sdjl nss_status_t status; 1450cb5caa98Sdjl nssuint_t *cookiep; 1451cb5caa98Sdjl nssuint_t *seqnump; 1452cb5caa98Sdjl nscd_getent_context_t *ctx; 1453cb5caa98Sdjl int rc; 1454cb5caa98Sdjl nss_pheader_t *pbuf = (nss_pheader_t *)buffer; 1455cb5caa98Sdjl char *me = "nss_pgetent"; 1456cb5caa98Sdjl 1457cb5caa98Sdjl if (buffer == NULL || length == 0) { 1458cb5caa98Sdjl NSCD_RETURN_STATUS(pbuf, NSS_ERROR, EFAULT); 1459cb5caa98Sdjl } 1460cb5caa98Sdjl 1461cb5caa98Sdjl status = nss_packed_context_init(buffer, length, 1462cb5caa98Sdjl NULL, &initf, &contextp, &arg); 1463cb5caa98Sdjl if (status != NSS_SUCCESS) { 1464cb5caa98Sdjl NSCD_RETURN_STATUS(pbuf, status, -1); 1465cb5caa98Sdjl } 1466cb5caa98Sdjl 1467cb5caa98Sdjl /* 1468cb5caa98Sdjl * use the generic nscd_initf for all the getent requests 1469cb5caa98Sdjl * (the TSD key is the pointer to the packed header) 1470cb5caa98Sdjl */ 1471cb5caa98Sdjl rc = set_initf_key(pbuf); 1472cb5caa98Sdjl if (rc != 0) { 1473cb5caa98Sdjl NSCD_RETURN_STATUS(pbuf, NSS_UNAVAIL, EINVAL); 1474cb5caa98Sdjl } 1475cb5caa98Sdjl initf = nscd_initf; 1476cb5caa98Sdjl 1477cb5caa98Sdjl 1478cb5caa98Sdjl /* verify the cookie passed in */ 1479cb5caa98Sdjl nscd_map_contextp(buffer, contextp, &cookiep, &seqnump, 0); 1480cb5caa98Sdjl if (NSCD_STATUS_IS_NOT_OK(pbuf)) 1481cb5caa98Sdjl return; 1482cb5caa98Sdjl 1483cb5caa98Sdjl /* Perform local search and pack results into return buffer */ 1484cb5caa98Sdjl status = nss_getent(NULL, initf, contextp, &arg); 1485cb5caa98Sdjl NSCD_SET_STATUS(pbuf, status, -1); 1486cb5caa98Sdjl nss_packed_set_status(buffer, length, status, &arg); 1487cb5caa98Sdjl 1488cb5caa98Sdjl /* increment sequence number in the buffer and nscd context */ 1489cb5caa98Sdjl if (status == NSS_SUCCESS) { 1490cb5caa98Sdjl ctx = (nscd_getent_context_t *)contextp->ctx; 1491cb5caa98Sdjl ctx->seq_num++; 1492cb5caa98Sdjl *seqnump = ctx->seq_num; 1493cb5caa98Sdjl *cookiep = ctx->cookie; 1494cb5caa98Sdjl 1495cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG) 1496cb5caa98Sdjl (me, "getent OK, new sequence number = %lld, len = %lld," 1497cb5caa98Sdjl " data = [ %s ]\n", *seqnump, 1498cb5caa98Sdjl pbuf->data_len, (char *)buffer + pbuf->data_off); 1499cb5caa98Sdjl } else { 1500*124771bbSmichen /* release the resources used */ 1501cb5caa98Sdjl ctx = (nscd_getent_context_t *)contextp->ctx; 1502*124771bbSmichen if (ctx != NULL) { 1503*124771bbSmichen _nscd_put_getent_ctx(ctx); 1504*124771bbSmichen contextp->ctx = NULL; 1505*124771bbSmichen } 1506cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG) 1507cb5caa98Sdjl (me, "getent failed, status = %d, sequence number = %lld\n", 1508cb5caa98Sdjl status, *seqnump); 1509cb5caa98Sdjl } 1510cb5caa98Sdjl 1511cb5caa98Sdjl /* clear the TSD key used by the generic initf */ 1512cb5caa98Sdjl clear_initf_key(); 1513cb5caa98Sdjl } 1514cb5caa98Sdjl 1515cb5caa98Sdjl void 1516cb5caa98Sdjl nss_pendent(void *buffer, size_t length) 1517cb5caa98Sdjl { 1518cb5caa98Sdjl nss_getent_t context; 1519cb5caa98Sdjl nss_getent_t *contextp = &context; 1520cb5caa98Sdjl nssuint_t *seqnump; 1521cb5caa98Sdjl nssuint_t *cookiep; 1522cb5caa98Sdjl nss_pheader_t *pbuf = (nss_pheader_t *)buffer; 1523cb5caa98Sdjl char *me = "nss_pendent"; 1524cb5caa98Sdjl 1525cb5caa98Sdjl if (buffer == NULL || length == 0) { 1526cb5caa98Sdjl NSCD_RETURN_STATUS(pbuf, NSS_ERROR, EFAULT); 1527cb5caa98Sdjl } 1528cb5caa98Sdjl 1529cb5caa98Sdjl /* map the contextp from the cookie information */ 1530cb5caa98Sdjl nscd_map_contextp(buffer, contextp, &cookiep, &seqnump, 0); 1531cb5caa98Sdjl if (NSCD_STATUS_IS_NOT_OK(pbuf)) 1532cb5caa98Sdjl return; 1533cb5caa98Sdjl 1534cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG) 1535cb5caa98Sdjl (me, "endent, cookie = %lld, sequence number = %lld\n", 1536cb5caa98Sdjl *cookiep, *seqnump); 1537cb5caa98Sdjl 1538cb5caa98Sdjl /* Perform local endent and reset context */ 1539cb5caa98Sdjl nss_endent(NULL, NULL, contextp); 1540cb5caa98Sdjl NSCD_RETURN_STATUS(pbuf, NSS_SUCCESS, 0); 1541cb5caa98Sdjl } 1542cb5caa98Sdjl 1543cb5caa98Sdjl /*ARGSUSED*/ 1544cb5caa98Sdjl void 1545cb5caa98Sdjl nss_pdelete(void *buffer, size_t length) 1546cb5caa98Sdjl { 1547cb5caa98Sdjl nss_pheader_t *pbuf = (nss_pheader_t *)buffer; 1548cb5caa98Sdjl 1549cb5caa98Sdjl /* unnecessary, kept for completeness */ 1550cb5caa98Sdjl NSCD_RETURN_STATUS_SUCCESS(pbuf); 1551cb5caa98Sdjl } 1552