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