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 */ 21cb620785Sraf 22cb5caa98Sdjl /* 23b57459abSJulian Pullen * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24cb5caa98Sdjl * Use is subject to license terms. 25*7d7551bcSMilan Jurik * Copyright 2012 Milan Jurik. All rights reserved. 26cb5caa98Sdjl */ 27cb5caa98Sdjl 28cb5caa98Sdjl #include <stdlib.h> /* getenv() */ 29cb5caa98Sdjl #include <assert.h> 30cb5caa98Sdjl #include <unistd.h> 31cb5caa98Sdjl #include <string.h> 32cb620785Sraf #include <pthread.h> 33cb5caa98Sdjl #include <dlfcn.h> 34cb5caa98Sdjl #include <nss_dbdefs.h> 35cb5caa98Sdjl #include <exec_attr.h> 36cb5caa98Sdjl #include <gssapi/gssapi.h> 37cb5caa98Sdjl #include "nscd_door.h" 38cb5caa98Sdjl #include "nscd_switch.h" 39cb5caa98Sdjl #include "nscd_log.h" 40cb5caa98Sdjl #include "nscd_frontend.h" 41cb5caa98Sdjl 42cb5caa98Sdjl #pragma weak nss_search = _nss_search 43cb5caa98Sdjl #define nss_search _nss_search 44cb5caa98Sdjl 45cb5caa98Sdjl extern rwlock_t nscd_smf_service_state_lock; 46cb5caa98Sdjl 47cb5caa98Sdjl /* nscd id: main, forker, or child */ 48cb5caa98Sdjl extern int _whoami; 49cb5caa98Sdjl 50cb5caa98Sdjl static int 51cb5caa98Sdjl retry_test(nss_status_t res, int n, struct __nsw_lookup_v1 *lkp) 52cb5caa98Sdjl { 53cb5caa98Sdjl if (res != NSS_TRYAGAIN && res != NSS_NISSERVDNS_TRYAGAIN) { 54cb5caa98Sdjl if (res == NSS_SUCCESS) { 55cb5caa98Sdjl __NSW_UNPAUSE_ACTION(lkp->actions[__NSW_TRYAGAIN]); 56cb5caa98Sdjl __NSW_UNPAUSE_ACTION( 57cb5caa98Sdjl lkp->actions[__NSW_NISSERVDNS_TRYAGAIN]); 58cb5caa98Sdjl } 59cb5caa98Sdjl return (0); 60cb5caa98Sdjl } 61cb5caa98Sdjl 62cb5caa98Sdjl if ((res == NSS_TRYAGAIN && 63cb5caa98Sdjl lkp->actions[__NSW_TRYAGAIN] == __NSW_TRYAGAIN_FOREVER) || 64cb5caa98Sdjl (res == NSS_NISSERVDNS_TRYAGAIN && 65cb5caa98Sdjl lkp->actions[__NSW_NISSERVDNS_TRYAGAIN] == __NSW_TRYAGAIN_FOREVER)) 66cb5caa98Sdjl return (1); 67cb5caa98Sdjl 68cb5caa98Sdjl if (res == NSS_TRYAGAIN && 69cb5caa98Sdjl lkp->actions[__NSW_TRYAGAIN] == __NSW_TRYAGAIN_NTIMES) 70cb5caa98Sdjl if (n <= lkp->max_retries) 71cb5caa98Sdjl return (1); 72cb5caa98Sdjl else { 73cb5caa98Sdjl lkp->actions[__NSW_TRYAGAIN] = __NSW_TRYAGAIN_PAUSED; 74cb5caa98Sdjl return (0); 75cb5caa98Sdjl } 76cb5caa98Sdjl 77cb5caa98Sdjl if (res == NSS_NISSERVDNS_TRYAGAIN && 78cb5caa98Sdjl lkp->actions[__NSW_NISSERVDNS_TRYAGAIN] == __NSW_TRYAGAIN_NTIMES) 79cb5caa98Sdjl if (n <= lkp->max_retries) 80cb5caa98Sdjl return (1); 81cb5caa98Sdjl else { 82cb5caa98Sdjl lkp->actions[__NSW_NISSERVDNS_TRYAGAIN] = 83cb5caa98Sdjl __NSW_TRYAGAIN_PAUSED; 84cb5caa98Sdjl return (0); 85cb5caa98Sdjl } 86cb5caa98Sdjl 87cb5caa98Sdjl return (0); 88cb5caa98Sdjl } 89cb5caa98Sdjl 90cb620785Sraf static thread_key_t loopback_key = THR_ONCE_KEY; 91cb5caa98Sdjl typedef struct lb_key { 92cb5caa98Sdjl int srci; 93cb5caa98Sdjl int dbi; 94cb5caa98Sdjl int fnum; 95cb5caa98Sdjl int *lb_flagp; 96cb5caa98Sdjl } lb_key_t; 97cb5caa98Sdjl 98cb5caa98Sdjl static int 99cb5caa98Sdjl set_loopback_key(lb_key_t *key) { 100cb5caa98Sdjl 101cb620785Sraf int rc; 102cb5caa98Sdjl 103cb620785Sraf rc = thr_keycreate_once(&loopback_key, NULL); 104cb5caa98Sdjl /* set key if not already set */ 105cb620785Sraf if (rc == 0 && pthread_getspecific(loopback_key) == NULL) 106cb5caa98Sdjl rc = thr_setspecific(loopback_key, key); 107cb5caa98Sdjl 108cb5caa98Sdjl return (rc); 109cb5caa98Sdjl } 110cb5caa98Sdjl 111cb5caa98Sdjl static lb_key_t * 112cb5caa98Sdjl get_loopback_key(void) { 113cb5caa98Sdjl 114cb5caa98Sdjl char *me = "get_loopback_key"; 115cb5caa98Sdjl lb_key_t *k = NULL; 116cb5caa98Sdjl 117cb620785Sraf k = pthread_getspecific(loopback_key); 118cb5caa98Sdjl 119cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG) 120cb620785Sraf (me, "get loopback key, key = %p\n", k); 121cb5caa98Sdjl 122cb5caa98Sdjl return (k); 123cb5caa98Sdjl } 124cb5caa98Sdjl 125cb5caa98Sdjl static void 126cb5caa98Sdjl clear_loopback_key(lb_key_t *key) { 127cb5caa98Sdjl 128cb5caa98Sdjl char *me = "clear_loopback_key"; 129cb5caa98Sdjl 130cb620785Sraf if (loopback_key != THR_ONCE_KEY && key != NULL) { 131cb5caa98Sdjl /* 132cb5caa98Sdjl * key->lb_flagp points to the location of the 133cb5caa98Sdjl * flag, check_flag, in the stack where it was 134cb5caa98Sdjl * first set; clearing the flag tells that 135cb5caa98Sdjl * stack the loopback error has been resolved 136cb5caa98Sdjl */ 137cb5caa98Sdjl *key->lb_flagp = 0; 138cb5caa98Sdjl (void) thr_setspecific(loopback_key, NULL); 139cb5caa98Sdjl } 140cb5caa98Sdjl 141cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG) 142cb5caa98Sdjl (me, "key %p cleared\n", key); 143cb5caa98Sdjl } 144cb5caa98Sdjl 145cb620785Sraf static thread_key_t initf_key = THR_ONCE_KEY; 146cb5caa98Sdjl 147cb5caa98Sdjl static int 148cb5caa98Sdjl set_initf_key(void *pbuf) { 149cb5caa98Sdjl 150cb620785Sraf int rc; 151cb5caa98Sdjl 152cb620785Sraf rc = thr_keycreate_once(&initf_key, NULL); 153cb5caa98Sdjl if (rc == 0) 154cb5caa98Sdjl rc = thr_setspecific(initf_key, pbuf); 155cb5caa98Sdjl 156cb5caa98Sdjl return (rc); 157cb5caa98Sdjl } 158cb5caa98Sdjl 159cb5caa98Sdjl static void * 160cb5caa98Sdjl get_initf_key(void) { 161cb5caa98Sdjl 162cb5caa98Sdjl char *me = "get_initf_key"; 163cb5caa98Sdjl void *pbuf; 164cb5caa98Sdjl 165cb620785Sraf pbuf = pthread_getspecific(initf_key); 166cb5caa98Sdjl 167cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG) 168cb620785Sraf (me, "got initf pbuf, key = %p\n", pbuf); 169cb5caa98Sdjl 170cb5caa98Sdjl return (pbuf); 171cb5caa98Sdjl } 172cb5caa98Sdjl 173cb5caa98Sdjl static void 174cb5caa98Sdjl clear_initf_key(void) { 175cb5caa98Sdjl 176cb5caa98Sdjl char *me = "clear_initf_key"; 177cb5caa98Sdjl 178cb5caa98Sdjl (void) thr_setspecific(initf_key, NULL); 179cb5caa98Sdjl 180cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG) 181cb5caa98Sdjl (me, "initf pbuf cleared\n"); 182cb5caa98Sdjl } 183cb5caa98Sdjl 184cb5caa98Sdjl /* 185cb5caa98Sdjl * Call the input initf function to extract the 186cb5caa98Sdjl * NSS front end parameters and examine them to 187cb5caa98Sdjl * determine if an NSS lookup is to be performed 188cb5caa98Sdjl * on a regular or a pseudo (called from compat 189cb5caa98Sdjl * backend) database. Then set the necessary 190cb5caa98Sdjl * parameters for later data structures creation 191cb5caa98Sdjl * and processing. 192cb5caa98Sdjl */ 193cb5caa98Sdjl static nscd_rc_t 194cb5caa98Sdjl getparams( 195cb5caa98Sdjl int search_fnum, 196cb5caa98Sdjl nss_db_initf_t initf, 197cb5caa98Sdjl nscd_nsw_params_t *params) 198cb5caa98Sdjl { 199cb5caa98Sdjl 200cb5caa98Sdjl nscd_rc_t rc = NSCD_SUCCESS; 201cb5caa98Sdjl nss_db_params_t *p; 202cb5caa98Sdjl int j; 203cb5caa98Sdjl char *dbn; 204cb5caa98Sdjl const char *n; 205bee2e9ddSmichen char *me = "getparams"; 206cb5caa98Sdjl 207cb5caa98Sdjl p = ¶ms->p; 208cb5caa98Sdjl (void) memset(p, 0, sizeof (*p)); 209cb5caa98Sdjl (*initf)(p); 210cb5caa98Sdjl params->dbi = -1; 211cb5caa98Sdjl params->cfgdbi = -1; 212cb5caa98Sdjl params->compati = -1; 213cb5caa98Sdjl params->dnsi = -1; 214cb5caa98Sdjl 215cb5caa98Sdjl /* map database name to index */ 216cb5caa98Sdjl n = p->name; 217cb5caa98Sdjl for (j = 0; j < NSCD_NUM_DB; j++) { 218cb5caa98Sdjl dbn = NSCD_NSW_DB_NAME(j); 219cb5caa98Sdjl if (*n != *dbn) 220cb5caa98Sdjl continue; 221cb5caa98Sdjl if (strcmp(n, dbn) == 0) { 222cb5caa98Sdjl params->dbi = j; 223cb5caa98Sdjl if (*n != 'h' && *n != 'i' && *n != 's' && *n != 'a') 224cb5caa98Sdjl break; 225cb5caa98Sdjl if (strcmp(n, NSS_DBNAM_HOSTS) == 0 && 226cb5caa98Sdjl search_fnum == NSS_DBOP_HOSTS_BYNAME) 227cb5caa98Sdjl params->dnsi = 0; 228cb5caa98Sdjl else if (strcmp(n, NSS_DBNAM_IPNODES) == 0 && 229cb5caa98Sdjl search_fnum == NSS_DBOP_IPNODES_BYNAME) 230cb5caa98Sdjl params->dnsi = 1; 231cb5caa98Sdjl else if (strcmp(n, NSS_DBNAM_SHADOW) == 0) 232cb5caa98Sdjl params->privdb = 1; 233cb5caa98Sdjl break; 234cb5caa98Sdjl } 235cb5caa98Sdjl } 236cb5caa98Sdjl 237cb5caa98Sdjl /* 238cb5caa98Sdjl * use the switch policy for passwd_compat or 239cb5caa98Sdjl * group_compat? 240cb5caa98Sdjl */ 241cb5caa98Sdjl if (p->config_name != NULL) { 242cb5caa98Sdjl 243cb5caa98Sdjl n = p->config_name; 244cb5caa98Sdjl for (j = 0; j < NSCD_NUM_DB; j++) { 245cb5caa98Sdjl dbn = NSCD_NSW_DB_NAME(j); 246cb5caa98Sdjl if (*n == *dbn) { 247cb5caa98Sdjl if (strcmp(n, dbn) == 0) { 248cb5caa98Sdjl params->cfgdbi = j; 249cb5caa98Sdjl break; 250cb5caa98Sdjl } 251cb5caa98Sdjl } 252cb5caa98Sdjl } 253cb5caa98Sdjl } 254cb5caa98Sdjl 255cb5caa98Sdjl /* map the database name to the pseudo database index */ 256cb5caa98Sdjl if (params->cfgdbi != -1) { 257cb5caa98Sdjl if (strstr(p->config_name, "_compat") != NULL) { 258cb5caa98Sdjl n = p->name; 259cb5caa98Sdjl for (j = params->cfgdbi; j < NSCD_NUM_DB; j++) { 260cb5caa98Sdjl dbn = NSCD_NSW_DB_NAME(j); 261cb5caa98Sdjl if (*n == *dbn) { 262cb5caa98Sdjl if (strcmp(n, dbn) == 0) { 263cb5caa98Sdjl params->compati = j; 264cb5caa98Sdjl break; 265cb5caa98Sdjl } 266cb5caa98Sdjl } 267cb5caa98Sdjl } 268cb5caa98Sdjl } 269cb5caa98Sdjl } 270cb5caa98Sdjl 271bee2e9ddSmichen /* 272bee2e9ddSmichen * if unsupported database, let caller determine what to do next 273bee2e9ddSmichen */ 274bee2e9ddSmichen if (params->dbi == -1) { 275bee2e9ddSmichen _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG) 276bee2e9ddSmichen (me, "unsupported database: %s\n", p->name); 277bee2e9ddSmichen return (NSCD_CFG_UNSUPPORTED_SWITCH_DB); 278bee2e9ddSmichen } 279bee2e9ddSmichen 280cb5caa98Sdjl return (rc); 281cb5caa98Sdjl } 282cb5caa98Sdjl 283cb5caa98Sdjl static void 284cb5caa98Sdjl nscd_initf(nss_db_params_t *p) 285cb5caa98Sdjl { 286cb5caa98Sdjl nss_pheader_t *pbuf; 287cb5caa98Sdjl nssuint_t off; 288cb5caa98Sdjl nss_dbd_t *pdbd; 289cb5caa98Sdjl char *me = "nscd_initf"; 290cb5caa98Sdjl 291cb5caa98Sdjl pbuf = (nss_pheader_t *)get_initf_key(); 292cb5caa98Sdjl if (pbuf == NULL) { 293cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG) 294cb5caa98Sdjl (me, "ERROR: initf key not set\n"); 295cb5caa98Sdjl return; 296cb5caa98Sdjl } 297cb5caa98Sdjl 298cb5caa98Sdjl if (pbuf->dbd_len <= sizeof (nss_dbd_t)) { 299cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG) 300cb5caa98Sdjl (me, "invalid db front params data ? dbd_len = %d\n", 301cb5caa98Sdjl pbuf->dbd_len); 302cb5caa98Sdjl return; 303cb5caa98Sdjl } 304cb5caa98Sdjl 305cb5caa98Sdjl off = pbuf->dbd_off; 306cb5caa98Sdjl pdbd = (nss_dbd_t *)((void *)((char *)pbuf + off)); 307cb5caa98Sdjl 308cb5caa98Sdjl p->name = (char *)pdbd + pdbd->o_name; 309cb5caa98Sdjl p->config_name = (char *)pdbd + pdbd->o_config_name; 310cb5caa98Sdjl p->default_config = (char *)pdbd + pdbd->o_default_config; 311cb5caa98Sdjl p->flags = (enum nss_dbp_flags)pdbd->flags; 312cb5caa98Sdjl (void) memcpy(&p->private, &pbuf->nscdpriv, sizeof (p->private)); 313cb5caa98Sdjl 314cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG) 315cb5caa98Sdjl (me, "db frontend params: name =%s, config_name = %s, " 316cb5caa98Sdjl "default_config = %s, flags = %x\n", p->name, 317cb5caa98Sdjl (p->config_name && *p->config_name != '\0' ? 318cb5caa98Sdjl p->config_name : "<NOT SPECIFIED>"), 319cb5caa98Sdjl (p->default_config && *p->default_config != '\0' ? 320cb5caa98Sdjl p->default_config : "<NOT SPECIFIED>"), 321cb5caa98Sdjl p->flags); 322cb5caa98Sdjl } 323cb5caa98Sdjl 324cb5caa98Sdjl 325cb5caa98Sdjl static void 326cb5caa98Sdjl trace_result( 327cb5caa98Sdjl int dbi, 328cb5caa98Sdjl int srci, 329cb5caa98Sdjl int op, 330cb5caa98Sdjl nss_status_t res, 331cb5caa98Sdjl nss_XbyY_args_t *arg) 332cb5caa98Sdjl { 333cb5caa98Sdjl char *res_str; 334cb5caa98Sdjl char *src = "?"; 335cb5caa98Sdjl char *db = "?"; 33618bdb8a7Smichen char *data_str = "<NOT STRING FORMAT>"; 33718bdb8a7Smichen int data_len = 0; 33818bdb8a7Smichen char *me = "trace_result"; 339cb5caa98Sdjl 340cb5caa98Sdjl switch (res) { 341cb5caa98Sdjl case NSS_SUCCESS: 342cb5caa98Sdjl res_str = "NSS_SUCCESS"; 343cb5caa98Sdjl break; 344cb5caa98Sdjl case NSS_NOTFOUND: 345cb5caa98Sdjl res_str = "NSS_NOTFOUND"; 346cb5caa98Sdjl break; 347cb5caa98Sdjl case NSS_UNAVAIL: 348cb5caa98Sdjl res_str = "NSS_UNAVAIL"; 349cb5caa98Sdjl break; 350cb5caa98Sdjl case NSS_TRYAGAIN: 351cb5caa98Sdjl res_str = "NSS_TRYAGAIN"; 352cb5caa98Sdjl break; 353cb5caa98Sdjl case NSS_NISSERVDNS_TRYAGAIN: 354cb5caa98Sdjl res_str = "NSS_NISSERVDNS_TRYAGAIN"; 355cb5caa98Sdjl break; 356cb5caa98Sdjl default: 357cb5caa98Sdjl res_str = "UNKNOWN STATUS"; 358cb5caa98Sdjl break; 359cb5caa98Sdjl } 360cb5caa98Sdjl 361cb5caa98Sdjl if (dbi != -1) 362cb5caa98Sdjl db = NSCD_NSW_DB_NAME(dbi); 363cb5caa98Sdjl if (srci != -1) 364cb5caa98Sdjl src = NSCD_NSW_SRC_NAME(srci); 365cb5caa98Sdjl 36618bdb8a7Smichen if (arg->buf.result == NULL) { 36718bdb8a7Smichen data_str = arg->buf.buffer; 36818bdb8a7Smichen data_len = arg->returnlen; 36918bdb8a7Smichen } 37018bdb8a7Smichen 371cb5caa98Sdjl if (res == NSS_SUCCESS) { 372bf1e3beeSmichen _nscd_logit(me, "%s: database: %s, operation: %d, " 373bf1e3beeSmichen "source: %s returned >>%s<<, length = %d\n", 37418bdb8a7Smichen res_str, db, op, src, data_str, data_len); 375cb5caa98Sdjl return; 376cb5caa98Sdjl } 377cb5caa98Sdjl 378bf1e3beeSmichen _nscd_logit(me, "%s: database: %s, operation: %d, source: %s, " 379940a40eaSsm26363 "erange= %d, herrno: %s (%d)\n", 380940a40eaSsm26363 res_str, db, op, src, arg->erange, hstrerror(arg->h_errno), 381940a40eaSsm26363 arg->h_errno); 382cb5caa98Sdjl } 383cb5caa98Sdjl 384cb5caa98Sdjl /* 385cb5caa98Sdjl * Determine if a request should be done locally in the getXbyY caller's 3860dfdd7f3Smichen * process. Return none zero if yes, 0 otherwise. This should be called 3870dfdd7f3Smichen * before the switch engine steps through the backends/sources. 388bf1e3beeSmichen * This function returns 1 if: 389cb5caa98Sdjl * -- the database is exec_attr and the search_flag is GET_ALL 390cb5caa98Sdjl */ 391cb5caa98Sdjl static int 392cb5caa98Sdjl try_local( 393cb5caa98Sdjl int dbi, 394cb5caa98Sdjl void *arg) 395cb5caa98Sdjl { 396cb5caa98Sdjl struct nss_XbyY_args *ap = (struct nss_XbyY_args *)arg; 397cb5caa98Sdjl _priv_execattr *ep; 398cb5caa98Sdjl int rc = 0; 399cb5caa98Sdjl char *me = "try_local"; 400cb5caa98Sdjl 401cb5caa98Sdjl if (strcmp(NSCD_NSW_DB_NAME(dbi), NSS_DBNAM_EXECATTR) == 0) { 40201ef659dSJoep Vesseur if ((ep = ap->key.attrp) != NULL && IS_GET_ALL(ep->search_flag)) 403cb5caa98Sdjl rc = 1; 404cb5caa98Sdjl } 405cb5caa98Sdjl 406cb5caa98Sdjl if (rc != 0) { 407cb5caa98Sdjl 408cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG) 409cb5caa98Sdjl (me, "TRYLOCAL: exec_attr:GET_ALL\n"); 410cb5caa98Sdjl } 411cb5caa98Sdjl 412cb5caa98Sdjl return (rc); 413cb5caa98Sdjl } 414cb5caa98Sdjl 4150dfdd7f3Smichen /* 4160dfdd7f3Smichen * Determine if a request should be done locally in the getXbyY caller's 4170dfdd7f3Smichen * process. Return none zero if yes, 0 otherwise. This should be called 4180dfdd7f3Smichen * before the switch engine invokes any backend. 419bf1e3beeSmichen * This function returns 1 if: 420a3dd7914SMichen Chang * -- the database is shadow and the source is compat 4210dfdd7f3Smichen */ 4220dfdd7f3Smichen static int 4230dfdd7f3Smichen try_local2( 4240dfdd7f3Smichen int dbi, 4250dfdd7f3Smichen int srci) 4260dfdd7f3Smichen { 4270dfdd7f3Smichen int rc = 0; 4280dfdd7f3Smichen char *me = "try_local2"; 4290dfdd7f3Smichen 4300dfdd7f3Smichen if (*NSCD_NSW_DB_NAME(dbi) == 's' && 4310dfdd7f3Smichen strcmp(NSCD_NSW_DB_NAME(dbi), NSS_DBNAM_SHADOW) == 0) { 43236e852a1SRaja Andra if (strcmp(NSCD_NSW_SRC_NAME(srci), "compat") == 0) 4330dfdd7f3Smichen rc = 1; 4340dfdd7f3Smichen } 4350dfdd7f3Smichen 4360dfdd7f3Smichen if (rc != 0) { 4370dfdd7f3Smichen _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG) 438a3dd7914SMichen Chang (me, "TRYLOCAL: database: shadow, source: %s\n", 439a3dd7914SMichen Chang NSCD_NSW_SRC_NAME(srci)); 4400dfdd7f3Smichen } 4410dfdd7f3Smichen 4420dfdd7f3Smichen return (rc); 4430dfdd7f3Smichen } 4440dfdd7f3Smichen 445cb5caa98Sdjl static nscd_rc_t 44618bdb8a7Smichen get_lib_func(void **handle, void **func, mutex_t *lock, 44718bdb8a7Smichen char *lib, char *name, void **func_p) 448c70a8a3bSmichen { 44918bdb8a7Smichen char *me = "get_lib_func"; 450c70a8a3bSmichen void *sym; 451c70a8a3bSmichen 45218bdb8a7Smichen if (func_p != NULL && *handle != NULL && *func != NULL) { 45318bdb8a7Smichen *func_p = *func; 454c70a8a3bSmichen return (NSCD_SUCCESS); 455c70a8a3bSmichen } 456c70a8a3bSmichen 45718bdb8a7Smichen (void) mutex_lock(lock); 458c70a8a3bSmichen 459c70a8a3bSmichen /* close the handle if requested */ 460c70a8a3bSmichen if (func_p == NULL) { 46118bdb8a7Smichen if (*handle != NULL) { 46218bdb8a7Smichen (void) dlclose(*handle); 46318bdb8a7Smichen *handle = NULL; 46418bdb8a7Smichen *func = NULL; 465c70a8a3bSmichen } 46618bdb8a7Smichen (void) mutex_unlock(lock); 467c70a8a3bSmichen return (NSCD_SUCCESS); 468c70a8a3bSmichen } 469c70a8a3bSmichen 47018bdb8a7Smichen if (*handle != NULL && *func != NULL) { 47118bdb8a7Smichen *func_p = *func; 47218bdb8a7Smichen (void) mutex_unlock(lock); 473c70a8a3bSmichen return (NSCD_SUCCESS); 474c70a8a3bSmichen } 475c70a8a3bSmichen 47618bdb8a7Smichen if (*handle == NULL) { 47718bdb8a7Smichen *handle = dlopen(lib, RTLD_LAZY); 47818bdb8a7Smichen if (*handle == NULL) { 479bf1e3beeSmichen _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_ERROR) 48018bdb8a7Smichen (me, "unable to dlopen %s\n", lib); 48118bdb8a7Smichen (void) mutex_unlock(lock); 482c70a8a3bSmichen return (NSCD_CFG_DLOPEN_ERROR); 483c70a8a3bSmichen } 484c70a8a3bSmichen } 485c70a8a3bSmichen 48618bdb8a7Smichen if ((sym = dlsym(*handle, name)) == NULL) { 487c70a8a3bSmichen 488c70a8a3bSmichen _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_ERROR) 48918bdb8a7Smichen (me, "unable to find symbol %s:%s\n", lib, name); 49018bdb8a7Smichen (void) mutex_unlock(lock); 491c70a8a3bSmichen return (NSCD_CFG_DLSYM_ERROR); 492c70a8a3bSmichen } else { 49318bdb8a7Smichen *func_p = sym; 49418bdb8a7Smichen *func = sym; 495c70a8a3bSmichen } 496c70a8a3bSmichen 49718bdb8a7Smichen (void) mutex_unlock(lock); 498c70a8a3bSmichen return (NSCD_SUCCESS); 499c70a8a3bSmichen } 500c70a8a3bSmichen 50118bdb8a7Smichen static nscd_rc_t 50218bdb8a7Smichen get_libc_nss_search(void **func_p) 50318bdb8a7Smichen { 50418bdb8a7Smichen static void *handle = NULL; 50518bdb8a7Smichen static void *func = NULL; 50618bdb8a7Smichen static mutex_t lock = DEFAULTMUTEX; 50718bdb8a7Smichen 50818bdb8a7Smichen return (get_lib_func(&handle, &func, &lock, 50918bdb8a7Smichen "libc.so", "nss_search", func_p)); 51018bdb8a7Smichen } 51118bdb8a7Smichen 51218bdb8a7Smichen static nscd_rc_t 51318bdb8a7Smichen get_gss_func(void **func_p) 51418bdb8a7Smichen { 51518bdb8a7Smichen static void *handle = NULL; 51618bdb8a7Smichen static void *func = NULL; 51718bdb8a7Smichen static mutex_t lock = DEFAULTMUTEX; 51818bdb8a7Smichen 51918bdb8a7Smichen return (get_lib_func(&handle, &func, &lock, 52018bdb8a7Smichen "libgss.so", "gss_inquire_cred", func_p)); 52118bdb8a7Smichen } 52218bdb8a7Smichen 523b57459abSJulian Pullen static nscd_rc_t 524b57459abSJulian Pullen get_sldap_shadow_func(void **func_p) 525b57459abSJulian Pullen { 526b57459abSJulian Pullen static void *handle = NULL; 527b57459abSJulian Pullen static void *func = NULL; 528b57459abSJulian Pullen static mutex_t lock = DEFAULTMUTEX; 529b57459abSJulian Pullen 530b57459abSJulian Pullen return (get_lib_func(&handle, &func, &lock, 531b57459abSJulian Pullen "libsldap.so", "__ns_ldap_is_shadow_update_enabled", 532b57459abSJulian Pullen func_p)); 533b57459abSJulian Pullen } 534b57459abSJulian Pullen 5354b22b933Srs200217 /* 5364b22b933Srs200217 * get_dns_funcs returns pointers to gethostbyname functions in the 5374b22b933Srs200217 * dynamically loaded nss_dns & nss_mdns modules that return host 5384b22b933Srs200217 * lookup results along with the TTL value in the DNS resource 5394b22b933Srs200217 * records. The dnsi parameter indicates whether the lookup database 5404b22b933Srs200217 * is hosts(0) or ipnodes(1). The srcname parameter identifies the DNS 5414b22b933Srs200217 * module: dns/mdns and the function returns the address of the specific 5424b22b933Srs200217 * gethostbyname function in func_p variable. 5434b22b933Srs200217 */ 544c70a8a3bSmichen static nscd_rc_t 5454b22b933Srs200217 get_dns_funcs(int dnsi, nss_status_t (**func_p)(), const char *srcname) 546cb5caa98Sdjl { 5474b22b933Srs200217 int si; 54818bdb8a7Smichen void **funcpp; 5494b22b933Srs200217 static void *handle[2] = { NULL, NULL }; 5504b22b933Srs200217 static mutex_t func_lock[2] = { DEFAULTMUTEX, DEFAULTMUTEX }; 5514b22b933Srs200217 static void *func[2][2] = {{NULL, NULL}, {NULL, NULL}}; 5524b22b933Srs200217 static const char *lib[2] = { "nss_dns.so.1", "nss_mdns.so.1" }; 5534b22b933Srs200217 static const char *func_name[2][2] = 5544b22b933Srs200217 {{ "_nss_get_dns_hosts_name", "_nss_get_dns_ipnodes_name" }, 5554b22b933Srs200217 { "_nss_get_mdns_hosts_name", "_nss_get_mdns_ipnodes_name" }}; 556cb5caa98Sdjl 5574b22b933Srs200217 /* source index: 0 = dns, 1 = mdns */ 5584b22b933Srs200217 if (strcmp(srcname, "dns") == 0) 5594b22b933Srs200217 si = 0; 5604b22b933Srs200217 else 5614b22b933Srs200217 si = 1; 5624b22b933Srs200217 5634b22b933Srs200217 /* 5644b22b933Srs200217 * function index (func[si][dnsi]): 5654b22b933Srs200217 * [0,0] = dns/hosts, [0,1] = dns/ipnodes, 5664b22b933Srs200217 * [1,0] = mdns/hosts, [1,1] = mdns/ipnodes 5674b22b933Srs200217 */ 5684b22b933Srs200217 56918bdb8a7Smichen if (dnsi < 0) { /* close handle */ 57018bdb8a7Smichen funcpp = NULL; 5714b22b933Srs200217 (void) mutex_lock(&func_lock[si]); 5724b22b933Srs200217 func[si][0] = NULL; 5734b22b933Srs200217 func[si][1] = NULL; 5744b22b933Srs200217 (void) mutex_unlock(&func_lock[si]); 57518bdb8a7Smichen } else 57618bdb8a7Smichen funcpp = (void **)func_p; 577cb5caa98Sdjl 57818bdb8a7Smichen return (get_lib_func(&handle[si], &func[si][dnsi], &func_lock[si], 57918bdb8a7Smichen (char *)lib[si], (char *)func_name[si][dnsi], funcpp)); 580cb5caa98Sdjl } 581cb5caa98Sdjl 582cb5caa98Sdjl static nss_status_t 5834b22b933Srs200217 search_dns_withttl(nscd_sw_return_t *swret, const char *srcname, int dnsi) 584cb5caa98Sdjl { 585cb5caa98Sdjl nss_status_t (*func)(); 586cb5caa98Sdjl nss_status_t res = NSS_UNAVAIL; 587cb5caa98Sdjl nscd_rc_t rc; 588cb5caa98Sdjl 589cb5caa98Sdjl swret->noarg = 0; 5904b22b933Srs200217 if (strcmp(srcname, "dns") != 0 && strcmp(srcname, "mdns") != 0) 591cb5caa98Sdjl return (NSS_ERROR); 592cb5caa98Sdjl 5934b22b933Srs200217 rc = get_dns_funcs(dnsi, &func, srcname); 5944b22b933Srs200217 if (rc == NSCD_SUCCESS) { 5954b22b933Srs200217 /* 5964b22b933Srs200217 * data_len in the packed buf header may be changed 5974b22b933Srs200217 * by the dns or mdns backend, reset it just in 5984b22b933Srs200217 * case 5994b22b933Srs200217 */ 6004b22b933Srs200217 ((nss_pheader_t *)swret->pbuf)->data_len = 6014b22b933Srs200217 swret->datalen; 602cb5caa98Sdjl res = (func)(NULL, &swret->pbuf, &swret->pbufsiz); 6034b22b933Srs200217 } 604cb5caa98Sdjl return (res); 605cb5caa98Sdjl } 606cb5caa98Sdjl 607cb5caa98Sdjl /* 608cb5caa98Sdjl * Returns a flag to indicate if needs to fall back to the 609cb5caa98Sdjl * main nscd when a per-user lookup failed with rc NSS_NOTFOUND. 610cb5caa98Sdjl */ 611cb5caa98Sdjl static int 612cb5caa98Sdjl set_fallback_flag(char *srcname, nss_status_t rc) 613cb5caa98Sdjl { 614cb5caa98Sdjl char *me = "set_fallback_flag"; 615cb5caa98Sdjl if (strcmp(srcname, "ldap") == 0 && rc == NSS_NOTFOUND) { 616cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG) 617cb5caa98Sdjl (me, "NSS_NOTFOUND (ldap): fallback to main nscd " 618cb5caa98Sdjl "may be needed\n"); 619cb5caa98Sdjl return (1); 620cb5caa98Sdjl } 621cb5caa98Sdjl return (0); 622cb5caa98Sdjl } 623cb5caa98Sdjl 624cb5caa98Sdjl nss_status_t 625cb5caa98Sdjl nss_search(nss_db_root_t *rootp, nss_db_initf_t initf, int search_fnum, 626cb5caa98Sdjl void *search_args) 627cb5caa98Sdjl { 628cb5caa98Sdjl char *me = "nss_search"; 629cb5caa98Sdjl nss_status_t res = NSS_UNAVAIL; 630cb5caa98Sdjl nscd_nsw_state_t *s = NULL; 631cb5caa98Sdjl int n_src; 632cb5caa98Sdjl unsigned int status_vec = 0; 633cb5caa98Sdjl int dbi, srci = -1; 634cb5caa98Sdjl int check_loopback = 0; 635cb5caa98Sdjl int state_thr = 0; 636cb5caa98Sdjl lb_key_t key, *k = NULL; 637cb5caa98Sdjl nss_db_root_t root_db; 638cb5caa98Sdjl nscd_nsw_params_t params; 639cb5caa98Sdjl nscd_sw_return_t *swret; 640cb5caa98Sdjl 641cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG) 642cb5caa98Sdjl (me, "rootp = %p, initf = %p, search_fnum = %d, " 643cb5caa98Sdjl "search_args = %p\n", rootp, initf, 644cb5caa98Sdjl search_fnum, search_args); 645cb5caa98Sdjl 646cb5caa98Sdjl NSCD_SW_STATS_G.lookup_request_received_g++; 647cb5caa98Sdjl NSCD_SW_STATS_G.lookup_request_in_progress_g++; 648cb5caa98Sdjl NSCD_SW_STATS_G.lookup_request_queued_g++; 649cb5caa98Sdjl 650cb5caa98Sdjl /* determine db index, cfg db index, etc */ 651bee2e9ddSmichen if (getparams(search_fnum, initf, ¶ms) == 652bee2e9ddSmichen NSCD_CFG_UNSUPPORTED_SWITCH_DB) { 653bee2e9ddSmichen /* 654bee2e9ddSmichen * if unsupported database and the request is from the 655bee2e9ddSmichen * the door, tell the door client to try it locally 656bee2e9ddSmichen */ 65718bdb8a7Smichen if (initf == nscd_initf) { 658bee2e9ddSmichen res = NSS_TRYLOCAL; 659bee2e9ddSmichen goto error_exit; 66018bdb8a7Smichen } else { /* otherwise, let libc:nss_search() handle it */ 66118bdb8a7Smichen nss_status_t (*func)(); 66218bdb8a7Smichen 66318bdb8a7Smichen if (get_libc_nss_search((void **)&func) == 66418bdb8a7Smichen NSCD_SUCCESS) 66518bdb8a7Smichen return ((func)(rootp, initf, search_fnum, 66618bdb8a7Smichen search_args)); 66718bdb8a7Smichen else 66818bdb8a7Smichen goto error_exit; 66918bdb8a7Smichen } 670bee2e9ddSmichen } 671cb5caa98Sdjl dbi = params.dbi; 672cb5caa98Sdjl 673cb5caa98Sdjl /* get address of the switch engine return data area */ 674cb5caa98Sdjl if (initf == nscd_initf) { 675cb5caa98Sdjl swret = (nscd_sw_return_t *)params.p.private; 676cb5caa98Sdjl swret->srci = -1; 677cb5caa98Sdjl } else { 678cb5caa98Sdjl swret = NULL; 679cb5caa98Sdjl params.dnsi = -1; 680cb5caa98Sdjl } 681cb5caa98Sdjl 682cb5caa98Sdjl /* 68318bdb8a7Smichen * for door request that should be processed by the client, 684cb5caa98Sdjl * send it back with status NSS_TRYLOCAL 685cb5caa98Sdjl */ 68618bdb8a7Smichen if (initf == nscd_initf && try_local(dbi, search_args) == 1) { 687cb5caa98Sdjl res = NSS_TRYLOCAL; 688cb5caa98Sdjl goto error_exit; 689cb5caa98Sdjl } 690cb5caa98Sdjl 691cb5caa98Sdjl NSCD_SW_STATS(dbi).lookup_request_received++; 692cb5caa98Sdjl NSCD_SW_STATS(dbi).lookup_request_in_progress++; 693cb5caa98Sdjl NSCD_SW_STATS(dbi).lookup_request_queued++; 694cb5caa98Sdjl 695cb5caa98Sdjl /* if lookup not enabled, return NSS_UNAVAIL */ 696cb5caa98Sdjl if (!(NSCD_SW_CFG_G.enable_lookup_g == nscd_true && 697cb5caa98Sdjl NSCD_SW_CFG(dbi).enable_lookup == nscd_true)) { 698cb5caa98Sdjl 699cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG) 700cb5caa98Sdjl (me, "lookup not enabled for %s\n", NSCD_NSW_DB_NAME(dbi)); 701cb5caa98Sdjl 702cb5caa98Sdjl goto error_exit; 703cb5caa98Sdjl } 704cb5caa98Sdjl 705cb5caa98Sdjl /* determine if loopback checking is configured */ 706cb5caa98Sdjl if (NSCD_SW_CFG_G.enable_loopback_checking_g == nscd_true && 707cb5caa98Sdjl NSCD_SW_CFG(dbi).enable_loopback_checking == nscd_true) { 708cb5caa98Sdjl check_loopback = 1; 709cb5caa98Sdjl 710cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG) 711cb5caa98Sdjl (me, "loopback checking enabled for %s\n", 712cb5caa98Sdjl NSCD_NSW_DB_NAME(dbi)); 713cb5caa98Sdjl } 714cb5caa98Sdjl 715cb5caa98Sdjl if (check_loopback) { 716cb5caa98Sdjl k = get_loopback_key(); 717cb5caa98Sdjl if (k != NULL) { 718cb5caa98Sdjl if (k->dbi != dbi || k->fnum != search_fnum) { 719cb5caa98Sdjl clear_loopback_key(k); 720cb5caa98Sdjl k = NULL; 721cb5caa98Sdjl } 722cb5caa98Sdjl } 723cb5caa98Sdjl } 724cb5caa98Sdjl 725cb5caa98Sdjl if (s == 0) { 726cb5caa98Sdjl nscd_rc_t rc; 727cb5caa98Sdjl 728cb5caa98Sdjl if (check_loopback) { 729cb5caa98Sdjl rc = _nscd_get_nsw_state_thread(&root_db, ¶ms); 730cb5caa98Sdjl state_thr = 1; 731cb5caa98Sdjl } else 732cb5caa98Sdjl rc = _nscd_get_nsw_state(&root_db, ¶ms); 733cb5caa98Sdjl 734cb5caa98Sdjl NSCD_SW_STATS_G.lookup_request_queued_g--; 735cb5caa98Sdjl NSCD_SW_STATS(dbi).lookup_request_queued--; 736cb5caa98Sdjl 737cb5caa98Sdjl if (rc != NSCD_SUCCESS) 738cb5caa98Sdjl goto error_exit; 739cb5caa98Sdjl 740cb5caa98Sdjl s = (nscd_nsw_state_t *)root_db.s; 741cb5caa98Sdjl } 742cb5caa98Sdjl 743cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG) 744e37190e5Smichen (me, "database = %s, config = >>%s<<\n", NSCD_NSW_DB_NAME(dbi), 745cb5caa98Sdjl (*s->nsw_cfg_p)->nsw_cfg_str); 746cb5caa98Sdjl 747cb5caa98Sdjl for (n_src = 0; n_src < s->max_src; n_src++) { 74818bdb8a7Smichen nss_backend_t *be = NULL; 74918bdb8a7Smichen nss_backend_op_t funcp = NULL; 750cb5caa98Sdjl struct __nsw_lookup_v1 *lkp; 751cb5caa98Sdjl int smf_state; 752cb5caa98Sdjl int n_loop = 0; 753cb5caa98Sdjl int max_retry = 10; 754cb5caa98Sdjl 755cb5caa98Sdjl res = NSS_UNAVAIL; 756cb5caa98Sdjl 757cb5caa98Sdjl if (n_src == 0) 758cb5caa98Sdjl lkp = s->config->lookups; 759cb5caa98Sdjl else 760cb5caa98Sdjl lkp = lkp->next; 761cb5caa98Sdjl 762cb5caa98Sdjl /* set the number of max. retries */ 763cb5caa98Sdjl if (lkp->actions[__NSW_TRYAGAIN] == __NSW_TRYAGAIN_NTIMES) 764cb5caa98Sdjl max_retry = lkp->max_retries; 765cb5caa98Sdjl 766cb5caa98Sdjl srci = (*s->nsw_cfg_p)->src_idx[n_src]; 767cb5caa98Sdjl if (swret != NULL) 768cb5caa98Sdjl swret->srci = srci; 769cb5caa98Sdjl 770cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG) 771cb5caa98Sdjl (me, "nsw source = %s\n", NSCD_NSW_SRC_NAME(srci)); 772cb5caa98Sdjl 773b57459abSJulian Pullen /* 774b57459abSJulian Pullen * If no privilege to look up, skip. 775b57459abSJulian Pullen * 'files' requires PRIV_FILE_DAC_READ to read shadow(4) data, 776b57459abSJulian Pullen * 'ldap' requires all zones privilege. 777b57459abSJulian Pullen */ 778b57459abSJulian Pullen if (params.privdb == 1 && swret != NULL) { 779b57459abSJulian Pullen boolean_t (*is_shadow_update_enabled)(); 780b57459abSJulian Pullen boolean_t check_ldap_priv = B_FALSE; 781b57459abSJulian Pullen 782b57459abSJulian Pullen if (strcmp(NSCD_NSW_SRC_NAME(srci), "ldap") == 0) { 783b57459abSJulian Pullen if (get_sldap_shadow_func( 784b57459abSJulian Pullen (void **)&is_shadow_update_enabled) == 785b57459abSJulian Pullen NSCD_SUCCESS && 786b57459abSJulian Pullen is_shadow_update_enabled()) { 787b57459abSJulian Pullen check_ldap_priv = B_TRUE; 788b57459abSJulian Pullen 789b57459abSJulian Pullen /* 790b57459abSJulian Pullen * A peruser nscd doesn't have 791b57459abSJulian Pullen * the privileges to lookup a 792b57459abSJulian Pullen * private database, such as shadow, 793b57459abSJulian Pullen * returns NSS_ALTRETRY to have the 794b57459abSJulian Pullen * main nscd do the job. 795b57459abSJulian Pullen */ 796b57459abSJulian Pullen if (_whoami == NSCD_CHILD) { 797b57459abSJulian Pullen res = NSS_ALTRETRY; 798b57459abSJulian Pullen goto free_nsw_state; 799b57459abSJulian Pullen } 800b57459abSJulian Pullen } 801b57459abSJulian Pullen } 802b57459abSJulian Pullen 803b57459abSJulian Pullen if ((strcmp(NSCD_NSW_SRC_NAME(srci), "files") == 0 && 804b57459abSJulian Pullen _nscd_check_client_priv(NSCD_READ_PRIV) != 0) || 805b57459abSJulian Pullen (check_ldap_priv && 806b57459abSJulian Pullen _nscd_check_client_priv(NSCD_ALL_PRIV) != 0)) { 807b57459abSJulian Pullen _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, 808b57459abSJulian Pullen NSCD_LOG_LEVEL_DEBUG) 809cb5caa98Sdjl (me, "no privilege to look up, skip source\n"); 810cb5caa98Sdjl 811cb5caa98Sdjl goto next_src; 812cb5caa98Sdjl } 813b57459abSJulian Pullen } 814cb5caa98Sdjl 815cb5caa98Sdjl /* get state of the (backend) client service */ 816cb5caa98Sdjl smf_state = _nscd_get_smf_state(srci, dbi, 0); 817cb5caa98Sdjl 818cb5caa98Sdjl /* stop if the source is one that should be TRYLOCAL */ 819d2ba247cSmichen if (initf == nscd_initf && /* request is from the door */ 820d2ba247cSmichen (smf_state == NSCD_SVC_STATE_UNSUPPORTED_SRC || 821d2ba247cSmichen (smf_state == NSCD_SVC_STATE_FOREIGN_SRC && 822d2ba247cSmichen s->be_version_p[n_src] == NULL) || 82318bdb8a7Smichen (params.privdb && try_local2(dbi, srci) == 1))) { 824bf1e3beeSmichen _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG) 825cb5caa98Sdjl (me, "returning TRYLOCAL ... \n"); 826cb5caa98Sdjl res = NSS_TRYLOCAL; 827cb5caa98Sdjl goto free_nsw_state; 828cb5caa98Sdjl } 829cb5caa98Sdjl 830cb5caa98Sdjl if (check_loopback && k != NULL) { 831cb5caa98Sdjl 832cb5caa98Sdjl if (k->srci == srci && k->dbi == dbi) 833cb5caa98Sdjl if (k->fnum == search_fnum) { 834cb5caa98Sdjl 835cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, 836cb5caa98Sdjl NSCD_LOG_LEVEL_DEBUG) 837cb5caa98Sdjl (me, "loopback detected: " 838cb5caa98Sdjl "source = %s, database = %s " 839cb5caa98Sdjl "search fnum = %d\n", 840cb5caa98Sdjl NSCD_NSW_SRC_NAME(srci), 841cb5caa98Sdjl NSCD_NSW_DB_NAME(dbi), search_fnum); 842cb5caa98Sdjl 843cb5caa98Sdjl NSCD_SW_STATS_G.loopback_nsw_db_skipped_g++; 844cb5caa98Sdjl NSCD_SW_STATS(dbi).loopback_nsw_db_skipped++; 845cb5caa98Sdjl continue; 846cb5caa98Sdjl } 847cb5caa98Sdjl } 848cb5caa98Sdjl 849cb5caa98Sdjl be = s->be[n_src]; 850cb5caa98Sdjl if (be != NULL) 851cb5caa98Sdjl funcp = NSS_LOOKUP_DBOP(be, search_fnum); 852cb5caa98Sdjl 853d2ba247cSmichen /* request could be from within nscd so check states again */ 85418bdb8a7Smichen if (be == NULL || (params.dnsi < 0 && (funcp == NULL || 85518bdb8a7Smichen (smf_state != NSCD_SVC_STATE_UNINITED && 856d2ba247cSmichen smf_state != NSCD_SVC_STATE_UNSUPPORTED_SRC && 857d2ba247cSmichen smf_state != NSCD_SVC_STATE_FOREIGN_SRC && 85818bdb8a7Smichen smf_state < SCF_STATE_ONLINE)))) { 859cb5caa98Sdjl 860cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, 861cb5caa98Sdjl NSCD_LOG_LEVEL_DEBUG) 862cb5caa98Sdjl (me, "unable to look up source %s: be = %p, " 863cb5caa98Sdjl "smf state = %d, funcp = %p\n", 864cb5caa98Sdjl NSCD_NSW_SRC_NAME(srci), be, smf_state, funcp); 865cb5caa98Sdjl 866cb5caa98Sdjl goto next_src; 867cb5caa98Sdjl } 868cb5caa98Sdjl 869cb5caa98Sdjl do { 870cb5caa98Sdjl /* 871cb5caa98Sdjl * we can only retry max_retry times, 872cb5caa98Sdjl * otherwise threads may get stuck in this 873cb5caa98Sdjl * do-while loop forever 874cb5caa98Sdjl */ 875cb5caa98Sdjl if (n_loop > max_retry) { 876cb5caa98Sdjl if (swret != NULL) 877cb5caa98Sdjl res = NSS_TRYLOCAL; 878cb5caa98Sdjl goto free_nsw_state; 879cb5caa98Sdjl } 880cb5caa98Sdjl 881cb5caa98Sdjl /* 882cb5caa98Sdjl * set up to prevent loopback 883cb5caa98Sdjl */ 884cb5caa98Sdjl if (check_loopback && k == NULL) { 885cb5caa98Sdjl key.srci = srci; 886cb5caa98Sdjl key.dbi = dbi; 887cb5caa98Sdjl key.fnum = search_fnum; 888cb5caa98Sdjl key.lb_flagp = &check_loopback; 889cb5caa98Sdjl (void) set_loopback_key(&key); 890cb5caa98Sdjl k = &key; 891cb5caa98Sdjl } 892cb5caa98Sdjl 893cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, 894cb5caa98Sdjl NSCD_LOG_LEVEL_DEBUG) 895cb5caa98Sdjl (me, "looking up source = %s, loop# = %d \n", 896cb5caa98Sdjl NSCD_NSW_SRC_NAME(srci), n_loop); 897cb5caa98Sdjl 898cb5caa98Sdjl /* 899cb5caa98Sdjl * search the backend, if hosts lookups, 900cb5caa98Sdjl * try to get the hosts data with ttl first 901cb5caa98Sdjl */ 902cb5caa98Sdjl if (params.dnsi >= 0) { 903cb5caa98Sdjl res = search_dns_withttl(swret, 904bf1e3beeSmichen NSCD_NSW_SRC_NAME(srci), params.dnsi); 905cb5caa98Sdjl /* 906cb5caa98Sdjl * if not able to get ttl, fall back 907cb5caa98Sdjl * to the regular backend call 908cb5caa98Sdjl */ 909cb5caa98Sdjl if (res == NSS_ERROR) 910cb5caa98Sdjl res = (*funcp)(be, search_args); 911cb5caa98Sdjl else { 912cb5caa98Sdjl /* 913cb5caa98Sdjl * status/result are in the 914cb5caa98Sdjl * packed buffer, not 915cb5caa98Sdjl * search_args 916cb5caa98Sdjl */ 917cb5caa98Sdjl swret->noarg = 1; 918cb5caa98Sdjl } 919cb5caa98Sdjl } else 920cb5caa98Sdjl res = (*funcp)(be, search_args); 921cb5caa98Sdjl if (swret != NULL) 922cb5caa98Sdjl swret->errnum = errno; 923cb5caa98Sdjl 924cb5caa98Sdjl /* 925cb5caa98Sdjl * backend is not up, check and update the 926cb5caa98Sdjl * smf state table 927cb5caa98Sdjl */ 928cb5caa98Sdjl if (res == NSS_UNAVAIL) 929cb5caa98Sdjl (void) _nscd_get_smf_state(srci, dbi, 1); 930cb5caa98Sdjl 931cb5caa98Sdjl /* 932cb5caa98Sdjl * may need to fall back to use the main nscd 933cb5caa98Sdjl * if per-user lookup 934cb5caa98Sdjl */ 935cb5caa98Sdjl if (_whoami == NSCD_CHILD && swret != NULL) 936cb5caa98Sdjl swret->fallback = set_fallback_flag( 937cb5caa98Sdjl NSCD_NSW_SRC_NAME(srci), res); 938cb5caa98Sdjl 939cb5caa98Sdjl _NSCD_LOG_IF(NSCD_LOG_SWITCH_ENGINE, 940cb5caa98Sdjl NSCD_LOG_LEVEL_DEBUG) { 941cb5caa98Sdjl 942cb5caa98Sdjl /* 943cb5caa98Sdjl * set up to trace the result/status 944cb5caa98Sdjl * of the dns/ttl lookup 945cb5caa98Sdjl */ 946cb5caa98Sdjl if (swret != NULL && swret->noarg == 1) { 947cb5caa98Sdjl nss_pheader_t *phdr; 948cb5caa98Sdjl struct nss_XbyY_args *arg; 949cb5caa98Sdjl arg = (struct nss_XbyY_args *) 950cb5caa98Sdjl search_args; 951cb5caa98Sdjl phdr = (nss_pheader_t *)swret->pbuf; 952cb5caa98Sdjl arg->buf.buffer = (char *)phdr + 953cb5caa98Sdjl phdr->data_off; 954cb5caa98Sdjl arg->returnlen = phdr->data_len; 955cb5caa98Sdjl if (phdr->p_errno == ERANGE) 956cb5caa98Sdjl arg->erange = 1; 957cb5caa98Sdjl arg->h_errno = phdr->p_herrno; 958cb5caa98Sdjl } 959cb5caa98Sdjl 960cb5caa98Sdjl trace_result(dbi, srci, search_fnum, res, 961cb5caa98Sdjl (nss_XbyY_args_t *)search_args); 962cb5caa98Sdjl } 963cb5caa98Sdjl 964cb5caa98Sdjl n_loop++; 965cb5caa98Sdjl } while (retry_test(res, n_loop, lkp)); 966cb5caa98Sdjl 967cb5caa98Sdjl next_src: 968cb5caa98Sdjl 969cb5caa98Sdjl status_vec |= (1 << res); 970cb5caa98Sdjl 971cb5caa98Sdjl if (__NSW_ACTION_V1(lkp, res) == __NSW_RETURN) { 972cb5caa98Sdjl break; 973cb5caa98Sdjl } 974cb5caa98Sdjl } 975cb5caa98Sdjl 976cb5caa98Sdjl free_nsw_state: 977cb5caa98Sdjl 978cb5caa98Sdjl if (state_thr == 1) 979cb5caa98Sdjl _nscd_put_nsw_state_thread(s); 980cb5caa98Sdjl else 981cb5caa98Sdjl _nscd_put_nsw_state(s); 982cb5caa98Sdjl if (check_loopback && k != NULL) 983cb5caa98Sdjl clear_loopback_key(k); 984cb5caa98Sdjl 985cb5caa98Sdjl if (res != NSS_SUCCESS) 986cb5caa98Sdjl goto error_exit; 987cb5caa98Sdjl 988cb5caa98Sdjl NSCD_SW_STATS_G.lookup_request_succeeded_g++; 989cb5caa98Sdjl NSCD_SW_STATS(dbi).lookup_request_succeeded++; 990cb5caa98Sdjl NSCD_SW_STATS_G.lookup_request_in_progress_g--; 991cb5caa98Sdjl NSCD_SW_STATS(dbi).lookup_request_in_progress--; 992cb5caa98Sdjl 993cb5caa98Sdjl return (NSS_SUCCESS); 994cb5caa98Sdjl 995cb5caa98Sdjl error_exit: 996cb5caa98Sdjl 997cb5caa98Sdjl NSCD_SW_STATS_G.lookup_request_failed_g++; 998cb5caa98Sdjl NSCD_SW_STATS_G.lookup_request_in_progress_g--; 999cb5caa98Sdjl NSCD_SW_STATS(dbi).lookup_request_failed++; 1000cb5caa98Sdjl NSCD_SW_STATS(dbi).lookup_request_in_progress--; 1001cb5caa98Sdjl 1002cb5caa98Sdjl return (res); 1003cb5caa98Sdjl } 1004cb5caa98Sdjl 1005cb5caa98Sdjl 1006cb5caa98Sdjl /* ===> get/set/endent */ 1007cb5caa98Sdjl 1008cb5caa98Sdjl static void nss_setent_u(nss_db_root_t *, 1009cb5caa98Sdjl nss_db_initf_t, 1010cb5caa98Sdjl nss_getent_t *); 1011cb5caa98Sdjl static nss_status_t nss_getent_u(nss_db_root_t *, 1012cb5caa98Sdjl nss_db_initf_t, 1013cb5caa98Sdjl nss_getent_t *, 1014cb5caa98Sdjl void *); 1015cb5caa98Sdjl static void nss_endent_u(nss_db_root_t *, 1016cb5caa98Sdjl nss_db_initf_t, 1017cb5caa98Sdjl nss_getent_t *); 1018cb5caa98Sdjl 1019cb5caa98Sdjl void 1020cb5caa98Sdjl nss_setent(nss_db_root_t *rootp, nss_db_initf_t initf, 1021cb5caa98Sdjl nss_getent_t *contextpp) 1022cb5caa98Sdjl { 1023cb5caa98Sdjl if (contextpp == 0) 1024cb5caa98Sdjl return; 1025cb5caa98Sdjl nss_setent_u(rootp, initf, contextpp); 1026cb5caa98Sdjl } 1027cb5caa98Sdjl 1028cb5caa98Sdjl nss_status_t 1029cb5caa98Sdjl nss_getent(nss_db_root_t *rootp, nss_db_initf_t initf, nss_getent_t *contextpp, 1030cb5caa98Sdjl void *args) 1031cb5caa98Sdjl { 1032cb5caa98Sdjl nss_status_t status; 1033cb5caa98Sdjl 1034cb5caa98Sdjl if (contextpp == 0) { 1035cb5caa98Sdjl return (NSS_UNAVAIL); 1036cb5caa98Sdjl } 1037cb5caa98Sdjl status = nss_getent_u(rootp, initf, contextpp, args); 1038cb5caa98Sdjl return (status); 1039cb5caa98Sdjl } 1040cb5caa98Sdjl 1041cb5caa98Sdjl void 1042cb5caa98Sdjl nss_endent(nss_db_root_t *rootp, nss_db_initf_t initf, 1043cb5caa98Sdjl nss_getent_t *contextpp) 1044cb5caa98Sdjl { 1045cb5caa98Sdjl if (contextpp == 0) 1046cb5caa98Sdjl return; 1047cb5caa98Sdjl nss_endent_u(rootp, initf, contextpp); 1048cb5caa98Sdjl } 1049cb5caa98Sdjl 1050cb5caa98Sdjl /*ARGSUSED*/ 1051cb5caa98Sdjl static void 1052cb5caa98Sdjl end_iter_u(nss_db_root_t *rootp, struct nss_getent_context *contextp) 1053cb5caa98Sdjl { 1054cb5caa98Sdjl nscd_getent_context_t *ctx; 1055cb5caa98Sdjl nscd_nsw_state_t *s; 1056cb5caa98Sdjl nss_backend_t *be; 1057cb5caa98Sdjl int n_src; 1058cb5caa98Sdjl 1059cb5caa98Sdjl ctx = (nscd_getent_context_t *)contextp; 1060cb5caa98Sdjl s = ctx->nsw_state; 1061cb5caa98Sdjl n_src = ctx->n_src; 1062cb5caa98Sdjl be = ctx->be; 1063cb5caa98Sdjl 1064cb5caa98Sdjl if (s != 0) { 1065cb5caa98Sdjl if (n_src < s->max_src && be != 0) { 1066cb5caa98Sdjl (void) NSS_INVOKE_DBOP(be, NSS_DBOP_ENDENT, 0); 1067cb5caa98Sdjl ctx->be = 0; /* Should be unnecessary, but hey */ 1068cb5caa98Sdjl } 1069cb5caa98Sdjl } 1070cb5caa98Sdjl ctx->n_src = 0; 1071cb5caa98Sdjl } 1072cb5caa98Sdjl 1073cb5caa98Sdjl static void 1074cb5caa98Sdjl nss_setent_u(nss_db_root_t *rootp, nss_db_initf_t initf, 1075cb5caa98Sdjl nss_getent_t *contextpp) 1076cb5caa98Sdjl { 1077cb5caa98Sdjl char *me = "nss_setent_u"; 1078cb5caa98Sdjl nscd_nsw_state_t *s; 1079cb5caa98Sdjl nscd_getent_context_t *contextp; 1080cb5caa98Sdjl nscd_nsw_params_t params; 1081cb5caa98Sdjl nss_db_root_t root; 1082cb5caa98Sdjl nss_backend_t *be; 1083cb5caa98Sdjl int n_src, i; 1084cb5caa98Sdjl nscd_sw_return_t *swret = NULL; 1085cb5caa98Sdjl 1086cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG) 1087cb5caa98Sdjl (me, "rootp = %p, initf = %p, contextpp = %p \n", 1088cb5caa98Sdjl rootp, initf, contextpp); 1089cb5caa98Sdjl 1090bee2e9ddSmichen /* 1091bee2e9ddSmichen * Get the nsw db index via the initf function. If unsupported 1092bee2e9ddSmichen * database, no need to continue 1093bee2e9ddSmichen */ 1094bee2e9ddSmichen if (getparams(-1, initf, ¶ms) == NSCD_CFG_UNSUPPORTED_SWITCH_DB) 1095bee2e9ddSmichen return; 1096cb5caa98Sdjl 1097cb5caa98Sdjl /* get address of the switch engine return data area */ 1098cb5caa98Sdjl if (initf == nscd_initf) 1099cb5caa98Sdjl swret = (nscd_sw_return_t *)params.p.private; 1100cb5caa98Sdjl 1101cb5caa98Sdjl /* if no privilege to look up, return */ 1102cb5caa98Sdjl if (params.privdb == 1 && swret != NULL && 1103b57459abSJulian Pullen _nscd_check_client_priv(NSCD_READ_PRIV) != 0) { 1104cb5caa98Sdjl 1105cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG) 1106cb5caa98Sdjl (me, "no privilege \n"); 1107cb5caa98Sdjl return; 1108cb5caa98Sdjl } 1109cb5caa98Sdjl 1110cb5caa98Sdjl if ((contextp = (nscd_getent_context_t *)contextpp->ctx) == 0) { 1111cb5caa98Sdjl if ((_nscd_get_getent_ctx(contextpp, ¶ms)) != 1112cb5caa98Sdjl NSCD_SUCCESS) { 1113cb5caa98Sdjl return; 1114cb5caa98Sdjl } 1115cb5caa98Sdjl contextp = (nscd_getent_context_t *)contextpp->ctx; 1116cb5caa98Sdjl } 1117cb5caa98Sdjl s = contextp->nsw_state; 1118cb5caa98Sdjl 1119cb5caa98Sdjl if (s == 0) { 1120cb5caa98Sdjl if (_nscd_get_nsw_state(&root, ¶ms) != 1121cb5caa98Sdjl NSCD_SUCCESS) { 1122cb5caa98Sdjl return; 1123cb5caa98Sdjl } 1124cb5caa98Sdjl s = (nscd_nsw_state_t *)root.s; 1125cb5caa98Sdjl contextp->nsw_state = s; 1126cb5caa98Sdjl 1127cb5caa98Sdjl } else { 1128cb5caa98Sdjl s = contextp->nsw_state; 1129cb5caa98Sdjl n_src = contextp->n_src; 1130cb5caa98Sdjl be = contextp->be; 1131cb5caa98Sdjl if (n_src == 0 && be != 0) { 1132cb5caa98Sdjl /* 1133cb5caa98Sdjl * Optimization: don't do endent, don't change 1134cb5caa98Sdjl * backends, just do the setent. Look Ma, no locks 1135cb5caa98Sdjl * (nor any context that needs updating). 1136cb5caa98Sdjl */ 1137cb5caa98Sdjl (void) NSS_INVOKE_DBOP(be, NSS_DBOP_SETENT, 0); 1138cb5caa98Sdjl return; 1139cb5caa98Sdjl } 1140cb5caa98Sdjl if (n_src < s->max_src && be != 0) { 1141cb5caa98Sdjl (void) NSS_INVOKE_DBOP(be, NSS_DBOP_ENDENT, 0); 1142cb5caa98Sdjl contextp->be = 0; /* Play it safe */ 1143cb5caa98Sdjl } 1144cb5caa98Sdjl } 1145cb5caa98Sdjl for (n_src = 0, be = 0; n_src < s->max_src && 1146cb5caa98Sdjl (be = s->be[n_src]) == 0; n_src++) { 1147cb5caa98Sdjl ; 1148cb5caa98Sdjl } 1149cb5caa98Sdjl 1150cb5caa98Sdjl contextp->n_src = n_src; 1151cb5caa98Sdjl contextp->be = be; 1152cb5caa98Sdjl 1153cb5caa98Sdjl if (be == 0) { 1154cb5caa98Sdjl /* Things are broken enough that we can't do setent/getent */ 1155cb5caa98Sdjl nss_endent_u(rootp, initf, contextpp); 1156cb5caa98Sdjl return; 1157cb5caa98Sdjl } 1158cb5caa98Sdjl 1159cb5caa98Sdjl /* 1160cb5caa98Sdjl * make sure all the backends are supported 1161cb5caa98Sdjl */ 1162cb5caa98Sdjl for (i = 0; i < s->max_src; i++) { 1163cb5caa98Sdjl int st, srci; 1164cb5caa98Sdjl 1165d2ba247cSmichen if (s->be[i] == NULL) 1166d2ba247cSmichen continue; 1167d2ba247cSmichen 1168cb5caa98Sdjl srci = (*s->nsw_cfg_p)->src_idx[i]; 1169cb5caa98Sdjl st = _nscd_get_smf_state(srci, params.dbi, 1); 1170d2ba247cSmichen if (st == NSCD_SVC_STATE_UNSUPPORTED_SRC || 1171d2ba247cSmichen (st == NSCD_SVC_STATE_FOREIGN_SRC && 11726392794bSMichen Chang s->be_version_p[i] == NULL && initf == nscd_initf) || 1173d2ba247cSmichen st == NSCD_SVC_STATE_UNINITED || 1174d2ba247cSmichen (params.privdb && 11750dfdd7f3Smichen try_local2(params.dbi, srci) == 1)) { 1176cb5caa98Sdjl nss_endent_u(rootp, initf, contextpp); 1177cb5caa98Sdjl 1178cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, 1179cb5caa98Sdjl NSCD_LOG_LEVEL_DEBUG) 1180cb5caa98Sdjl (me, "backend (%s) not available (state = %d)\n", 1181cb5caa98Sdjl NSCD_NSW_SRC_NAME(srci), st); 1182cb5caa98Sdjl 1183cb5caa98Sdjl return; 1184cb5caa98Sdjl } 1185cb5caa98Sdjl } 1186cb5caa98Sdjl 1187cb5caa98Sdjl (void) NSS_INVOKE_DBOP(be, NSS_DBOP_SETENT, 0); 1188cb5caa98Sdjl } 1189cb5caa98Sdjl 1190cb5caa98Sdjl nss_status_t 1191cb5caa98Sdjl nss_getent_u(nss_db_root_t *rootp, nss_db_initf_t initf, 1192cb5caa98Sdjl nss_getent_t *contextpp, void *args) 1193cb5caa98Sdjl { 1194cb5caa98Sdjl char *me = "nss_getent_u"; 1195cb5caa98Sdjl nscd_nsw_state_t *s; 1196cb5caa98Sdjl nscd_getent_context_t *contextp; 1197cb5caa98Sdjl int n_src; 1198cb5caa98Sdjl nss_backend_t *be; 1199cb5caa98Sdjl 1200cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG) 1201cb5caa98Sdjl (me, "rootp = %p, initf = %p, contextpp = %p, args = %p\n", 1202cb5caa98Sdjl rootp, initf, contextpp, args); 1203cb5caa98Sdjl 1204cb5caa98Sdjl if ((contextp = (nscd_getent_context_t *)contextpp->ctx) == 0) { 1205cb5caa98Sdjl nss_setent_u(rootp, initf, contextpp); 1206cb5caa98Sdjl if ((contextp = (nscd_getent_context_t *)contextpp->ctx) == 0) { 1207cb5caa98Sdjl /* Give up */ 1208cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, 1209cb5caa98Sdjl NSCD_LOG_LEVEL_ERROR) 1210cb5caa98Sdjl (me, "not able to obtain getent context ... give up\n"); 1211cb5caa98Sdjl 1212cb5caa98Sdjl return (NSS_UNAVAIL); 1213cb5caa98Sdjl } 1214cb5caa98Sdjl } 1215cb5caa98Sdjl 1216cb5caa98Sdjl s = contextp->nsw_state; 1217cb5caa98Sdjl n_src = contextp->n_src; 1218cb5caa98Sdjl be = contextp->be; 1219cb5caa98Sdjl 1220cb5caa98Sdjl if (s == 0) { 1221cb5caa98Sdjl /* 1222cb5caa98Sdjl * We've done an end_iter() and haven't done nss_setent() 1223cb5caa98Sdjl * or nss_endent() since; we should stick in this state 1224cb5caa98Sdjl * until the caller invokes one of those two routines. 1225cb5caa98Sdjl */ 1226cb5caa98Sdjl return (NSS_SUCCESS); 1227cb5caa98Sdjl } 1228cb5caa98Sdjl 1229cb5caa98Sdjl while (n_src < s->max_src) { 1230cb5caa98Sdjl nss_status_t res; 1231cb5caa98Sdjl struct __nsw_lookup_v1 *lkp = NULL; 1232cb5caa98Sdjl int n; 1233cb5caa98Sdjl 1234cb5caa98Sdjl /* get the nsw config for the current source */ 1235cb5caa98Sdjl lkp = s->config->lookups; 1236cb5caa98Sdjl for (n = 0; n < n_src; n++) 1237cb5caa98Sdjl lkp = lkp->next; 1238cb5caa98Sdjl 1239cb5caa98Sdjl if (be == 0) { 1240cb5caa98Sdjl /* If it's null it's a bug, but let's play safe */ 1241cb5caa98Sdjl res = NSS_UNAVAIL; 1242cb5caa98Sdjl } else { 1243cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, 1244cb5caa98Sdjl NSCD_LOG_LEVEL_DEBUG) 1245cb5caa98Sdjl (me, "database: %s, backend: %s, nsswitch config: %s\n", 1246cb5caa98Sdjl NSCD_NSW_DB_NAME(s->dbi), 1247cb5caa98Sdjl lkp->service_name, 1248cb5caa98Sdjl (*s->nsw_cfg_p)->nsw_cfg_str); 1249cb5caa98Sdjl 1250cb5caa98Sdjl res = NSS_INVOKE_DBOP(be, NSS_DBOP_GETENT, args); 1251cb5caa98Sdjl } 1252cb5caa98Sdjl 1253cb5caa98Sdjl if (__NSW_ACTION_V1(lkp, res) == __NSW_RETURN) { 1254cb5caa98Sdjl if (res != __NSW_SUCCESS) { 1255cb5caa98Sdjl end_iter_u(rootp, 1256cb5caa98Sdjl (struct nss_getent_context *)contextp); 1257cb5caa98Sdjl } 1258cb5caa98Sdjl return (res); 1259cb5caa98Sdjl } 1260cb5caa98Sdjl (void) NSS_INVOKE_DBOP(be, NSS_DBOP_ENDENT, 0); 1261cb5caa98Sdjl do { 1262cb5caa98Sdjl n_src++; 1263cb5caa98Sdjl } while (n_src < s->max_src && 1264cb5caa98Sdjl (be = s->be[n_src]) == 0); 1265cb5caa98Sdjl if (be == 0) { 1266cb5caa98Sdjl /* 1267cb5caa98Sdjl * This is the case where we failed to get the backend 1268cb5caa98Sdjl * for the last source. We exhausted all sources. 1269cb5caa98Sdjl */ 1270cb5caa98Sdjl nss_endent_u(rootp, initf, contextpp); 12712802e980Smichen return (NSS_NOTFOUND); 1272cb5caa98Sdjl } 1273cb5caa98Sdjl contextp->n_src = n_src; 1274cb5caa98Sdjl contextp->be = be; 1275cb5caa98Sdjl (void) NSS_INVOKE_DBOP(be, NSS_DBOP_SETENT, 0); 1276cb5caa98Sdjl } 1277cb5caa98Sdjl /* Got to the end of the sources without finding another entry */ 1278cb5caa98Sdjl end_iter_u(rootp, (struct nss_getent_context *)contextp); 1279cb5caa98Sdjl return (NSS_SUCCESS); 1280cb5caa98Sdjl /* success is either a successful entry or end of the sources */ 1281cb5caa98Sdjl } 1282cb5caa98Sdjl 1283cb5caa98Sdjl /*ARGSUSED*/ 1284cb5caa98Sdjl void 1285cb5caa98Sdjl nss_endent_u(nss_db_root_t *rootp, nss_db_initf_t initf, 1286cb5caa98Sdjl nss_getent_t *contextpp) 1287cb5caa98Sdjl { 1288cb5caa98Sdjl char *me = "nss_endent_u"; 1289cb5caa98Sdjl nscd_getent_context_t *contextp; 1290cb5caa98Sdjl 1291cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG) 1292cb5caa98Sdjl (me, "rootp = %p, initf = %p, contextpp = %p \n", 1293cb5caa98Sdjl rootp, initf, contextpp); 1294cb5caa98Sdjl 1295cb5caa98Sdjl if ((contextp = (nscd_getent_context_t *)contextpp->ctx) == 0) { 1296cb5caa98Sdjl /* nss_endent() on an unused context is a no-op */ 1297cb5caa98Sdjl return; 1298cb5caa98Sdjl } 12996392794bSMichen Chang 13006392794bSMichen Chang if (_nscd_is_getent_ctx_in_use(contextp) == 0) { 1301cb5caa98Sdjl end_iter_u(rootp, (struct nss_getent_context *)contextp); 1302cb5caa98Sdjl _nscd_put_getent_ctx(contextp); 1303cb5caa98Sdjl contextpp->ctx = NULL; 1304cb5caa98Sdjl } 13056392794bSMichen Chang } 1306cb5caa98Sdjl 1307cb5caa98Sdjl /* 1308cb5caa98Sdjl * _nss_db_state_destr() and nss_delete() do nothing in nscd 1309cb5caa98Sdjl * but is needed to make the caller (below nscd) happy 1310cb5caa98Sdjl */ 1311cb5caa98Sdjl /*ARGSUSED*/ 1312cb5caa98Sdjl void 1313cb5caa98Sdjl _nss_db_state_destr(struct nss_db_state *s) 1314cb5caa98Sdjl { 1315cb5caa98Sdjl /* nsw state in nscd is always reused, so do nothing here */ 1316cb5caa98Sdjl } 1317cb5caa98Sdjl 1318cb5caa98Sdjl /*ARGSUSED*/ 1319cb5caa98Sdjl void 1320cb5caa98Sdjl nss_delete(nss_db_root_t *rootp) 1321cb5caa98Sdjl { 1322cb5caa98Sdjl /* 1323cb5caa98Sdjl * the only resource kept tracked by the nss_db_root_t 1324cb5caa98Sdjl * is the nsw state which is always reused and no need 1325cb5caa98Sdjl * to be freed. So just return. 1326cb5caa98Sdjl */ 1327cb5caa98Sdjl } 1328cb5caa98Sdjl 1329cb5caa98Sdjl /* 1330cb5caa98Sdjl * Start of nss_psearch/nss_psetent()/nss_pgetent()/nss_pendent() 1331cb5caa98Sdjl * buffers switch entry points 1332cb5caa98Sdjl */ 1333cb5caa98Sdjl 1334cb5caa98Sdjl /* 1335cb5caa98Sdjl * nss_psearch opens a packed structure header, assembles a local 1336cb5caa98Sdjl * nss_XbyY_args_t structure and calls the local copy of nss_search. 1337cb5caa98Sdjl * The return data is assembled in "files native format" in the 1338cb5caa98Sdjl * return buffer location. Status if packed back up with the buffer 1339cb5caa98Sdjl * and the whole wad is returned to the cache or the client. 1340cb5caa98Sdjl */ 1341cb5caa98Sdjl 1342cb5caa98Sdjl void 1343cb5caa98Sdjl nss_psearch(void *buffer, size_t length) 1344cb5caa98Sdjl { 1345cb5caa98Sdjl /* inputs */ 1346cb5caa98Sdjl nss_db_initf_t initf; 1347cb5caa98Sdjl int dbop; 1348cb5caa98Sdjl int rc; 1349cb5caa98Sdjl nss_XbyY_args_t arg; 1350cb5caa98Sdjl nss_status_t status; 1351cb5caa98Sdjl nscd_sw_return_t swret = { 0 }, *swrp = &swret; 1352cb5caa98Sdjl nss_pheader_t *pbuf = (nss_pheader_t *)buffer; 1353cb5caa98Sdjl char *me = "nss_psearch"; 1354cb5caa98Sdjl 1355cb5caa98Sdjl if (buffer == NULL || length == 0) { 1356*7d7551bcSMilan Jurik NSCD_SET_STATUS(pbuf, NSS_ERROR, EFAULT); 1357*7d7551bcSMilan Jurik return; 1358cb5caa98Sdjl } 1359cb5caa98Sdjl 1360cb5caa98Sdjl status = nss_packed_arg_init(buffer, length, 1361cb5caa98Sdjl NULL, &initf, &dbop, &arg); 1362cb5caa98Sdjl if (status != NSS_SUCCESS) { 1363*7d7551bcSMilan Jurik NSCD_SET_STATUS(pbuf, status, -1); 1364*7d7551bcSMilan Jurik return; 1365cb5caa98Sdjl } 1366cb5caa98Sdjl 1367cb5caa98Sdjl /* 1368cb5caa98Sdjl * pass the address of the return data area 1369cb5caa98Sdjl * for the switch engine to return its own data 1370cb5caa98Sdjl */ 1371cb5caa98Sdjl (void) memcpy(&pbuf->nscdpriv, &swrp, sizeof (swrp)); 1372cb5caa98Sdjl swret.pbuf = buffer; 1373cb5caa98Sdjl swret.pbufsiz = length; 13744b22b933Srs200217 swret.datalen = pbuf->data_len; 1375cb5caa98Sdjl 1376cb5caa98Sdjl /* 1377cb5caa98Sdjl * use the generic nscd_initf for all database lookups 1378cb5caa98Sdjl * (the TSD key is the pointer to the packed header) 1379cb5caa98Sdjl */ 1380cb5caa98Sdjl rc = set_initf_key(pbuf); 1381cb5caa98Sdjl if (rc != 0) { 1382*7d7551bcSMilan Jurik NSCD_SET_STATUS(pbuf, NSS_UNAVAIL, EINVAL); 1383*7d7551bcSMilan Jurik return; 1384cb5caa98Sdjl } 1385cb5caa98Sdjl initf = nscd_initf; 1386cb5caa98Sdjl 1387cb5caa98Sdjl /* Perform local search and pack results into return buffer */ 1388cb5caa98Sdjl /* nscd's search ignores db_root */ 1389cb5caa98Sdjl status = nss_search(NULL, initf, dbop, &arg); 1390cb5caa98Sdjl 1391cb5caa98Sdjl /* 1392cb5caa98Sdjl * If status is NSS_NOTFOUND and ldap also returned 1393cb5caa98Sdjl * NSS_NOTFOUND, it is possible that the user does 1394cb5caa98Sdjl * not have a credential, so check and see if 1395cb5caa98Sdjl * needs to return NSS_ALTRETRY to let the main 1396cb5caa98Sdjl * nscd get a chance to process the lookup 1397cb5caa98Sdjl */ 1398cb5caa98Sdjl if (swret.fallback == 1 && status == NSS_NOTFOUND) { 1399c70a8a3bSmichen OM_uint32 (*func)(); 1400cb5caa98Sdjl OM_uint32 stat; 1401c70a8a3bSmichen nscd_rc_t rc; 1402cb5caa98Sdjl 1403c70a8a3bSmichen rc = get_gss_func((void **)&func); 1404c70a8a3bSmichen if (rc == NSCD_SUCCESS) { 1405c70a8a3bSmichen if (func(&stat, GSS_C_NO_CREDENTIAL, 1406cb5caa98Sdjl NULL, NULL, NULL, NULL) != GSS_S_COMPLETE) { 1407cb5caa98Sdjl 1408cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, 1409cb5caa98Sdjl NSCD_LOG_LEVEL_DEBUG) 1410cb5caa98Sdjl (me, "NSS_ALTRETRY: fallback to main nscd needed\n"); 1411cb5caa98Sdjl 1412cb5caa98Sdjl status = NSS_ALTRETRY; 1413cb5caa98Sdjl } 1414cb5caa98Sdjl } 1415c70a8a3bSmichen } 1416cb5caa98Sdjl 1417cb5caa98Sdjl NSCD_SET_STATUS(pbuf, status, -1); 1418cb5caa98Sdjl errno = swret.errnum; 1419cb5caa98Sdjl 1420cb5caa98Sdjl /* 1421d2ba247cSmichen * Move result/status from args to packed buffer only if 1422d2ba247cSmichen * arg was being used and rc from the switch engine is not 1423d2ba247cSmichen * NSS_TRYLOCAL. 1424cb5caa98Sdjl */ 1425d2ba247cSmichen if (!swret.noarg && status != NSS_TRYLOCAL) 1426cb5caa98Sdjl nss_packed_set_status(buffer, length, status, &arg); 1427cb5caa98Sdjl 1428cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG) 1429cb5caa98Sdjl (me, "switch engine result: source is %s, status %d, " 1430cb5caa98Sdjl "herrno is %d, errno is %s\n", 1431cb5caa98Sdjl (swret.srci != -1) ? NSCD_NSW_SRC_NAME(swret.srci) : "<NOTSET>", 1432cb5caa98Sdjl pbuf->p_status, pbuf->p_herrno, strerror(pbuf->p_errno)); 1433cb5caa98Sdjl 1434cb5caa98Sdjl /* clear the TSD key used by the generic initf */ 1435cb5caa98Sdjl clear_initf_key(); 1436cb5caa98Sdjl pbuf->nscdpriv = 0; 1437cb5caa98Sdjl } 1438cb5caa98Sdjl 1439cb5caa98Sdjl static void 1440cb5caa98Sdjl nscd_map_contextp(void *buffer, nss_getent_t *contextp, 1441e37190e5Smichen nssuint_t **cookie_num_p, nssuint_t **seqnum_p, int setent) 1442cb5caa98Sdjl { 1443cb5caa98Sdjl nss_pheader_t *pbuf = (nss_pheader_t *)buffer; 1444cb5caa98Sdjl nssuint_t off; 1445cb5caa98Sdjl nscd_getent_context_t *ctx; 1446cb5caa98Sdjl char *me = "nscd_map_contextp"; 1447e37190e5Smichen nscd_getent_p1_cookie_t *cookie; 1448cb5caa98Sdjl 1449cb5caa98Sdjl if (buffer == NULL) { 1450*7d7551bcSMilan Jurik NSCD_SET_STATUS(pbuf, NSS_ERROR, EFAULT); 1451*7d7551bcSMilan Jurik return; 1452cb5caa98Sdjl } 1453cb5caa98Sdjl 1454cb5caa98Sdjl off = pbuf->key_off; 1455e37190e5Smichen cookie = (nscd_getent_p1_cookie_t *)((void *)((char *)buffer + off)); 1456cb5caa98Sdjl if (seqnum_p != NULL) 1457e37190e5Smichen *seqnum_p = &cookie->p1_seqnum; 1458cb5caa98Sdjl 1459cb5caa98Sdjl /* 1460e37190e5Smichen * if called by nss_psetent, and the passed in cookie number 1461e37190e5Smichen * is NSCD_NEW_COOKIE, then there is no cookie yet, return a 1462e37190e5Smichen * pointer pointing to where the cookie number will be stored. 1463e37190e5Smichen * Also because there is no cookie to validate, just return 1464e37190e5Smichen * success. 1465cb5caa98Sdjl * 1466e37190e5Smichen * On the other hand, if a cookie number is passed in, we need 1467e37190e5Smichen * to validate the cookie number before returning. 1468cb5caa98Sdjl */ 1469e37190e5Smichen if (cookie_num_p != NULL) 1470e37190e5Smichen *cookie_num_p = &cookie->p1_cookie_num; 1471e37190e5Smichen if (setent == 1 && cookie->p1_cookie_num == NSCD_NEW_COOKIE) { 1472*7d7551bcSMilan Jurik NSCD_SET_STATUS_SUCCESS(pbuf); 1473*7d7551bcSMilan Jurik return; 1474e37190e5Smichen } 1475e37190e5Smichen 1476e37190e5Smichen /* 1477e37190e5Smichen * If the sequence number and start time match nscd's p0 cookie, 1478e37190e5Smichen * then either setent was done twice in a row or this is the 1479e37190e5Smichen * first getent after the setent, return success as well. 1480e37190e5Smichen */ 1481e37190e5Smichen if (cookie->p1_seqnum == NSCD_P0_COOKIE_SEQNUM) { 1482e37190e5Smichen nscd_getent_p0_cookie_t *p0c = 1483e37190e5Smichen (nscd_getent_p0_cookie_t *)cookie; 1484*7d7551bcSMilan Jurik if (p0c->p0_time == _nscd_get_start_time()) { 1485*7d7551bcSMilan Jurik NSCD_SET_STATUS_SUCCESS(pbuf); 1486*7d7551bcSMilan Jurik return; 1487*7d7551bcSMilan Jurik } 1488cb5caa98Sdjl } 1489cb5caa98Sdjl 1490cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG) 1491e37190e5Smichen (me, "cookie # = %lld, sequence # = %lld\n", 1492e37190e5Smichen cookie->p1_cookie_num, cookie->p1_seqnum); 1493cb5caa98Sdjl 1494e37190e5Smichen ctx = _nscd_is_getent_ctx(cookie->p1_cookie_num); 1495cb5caa98Sdjl 1496cb5caa98Sdjl if (ctx == NULL) { 1497cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG) 149829836b19Smichen (me, "No matching context found (cookie number: %lld)\n", 149929836b19Smichen cookie->p1_cookie_num); 1500cb5caa98Sdjl 1501*7d7551bcSMilan Jurik NSCD_SET_STATUS(pbuf, NSS_ERROR, EFAULT); 1502*7d7551bcSMilan Jurik return; 1503cb5caa98Sdjl } 1504cb5caa98Sdjl 1505e37190e5Smichen /* if not called by nss_psetent, verify sequence number */ 1506e37190e5Smichen if (setent != 1 && ctx->seq_num != 1507e37190e5Smichen (nscd_seq_num_t)cookie->p1_seqnum) { 1508cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG) 1509e37190e5Smichen (me, "invalid sequence # (%lld)\n", cookie->p1_seqnum); 1510cb5caa98Sdjl 151129836b19Smichen _nscd_free_ctx_if_aborted(ctx); 1512*7d7551bcSMilan Jurik NSCD_SET_STATUS(pbuf, NSS_ERROR, EFAULT); 1513*7d7551bcSMilan Jurik return; 1514cb5caa98Sdjl } 1515cb5caa98Sdjl 1516cb5caa98Sdjl contextp->ctx = (struct nss_getent_context *)ctx; 1517cb5caa98Sdjl 1518*7d7551bcSMilan Jurik NSCD_SET_STATUS_SUCCESS(pbuf); 1519cb5caa98Sdjl } 1520cb5caa98Sdjl 1521cb5caa98Sdjl void 1522cb5caa98Sdjl nss_psetent(void *buffer, size_t length, pid_t pid) 1523cb5caa98Sdjl { 1524cb5caa98Sdjl nss_getent_t context = { 0 }; 1525cb5caa98Sdjl nss_getent_t *contextp = &context; 1526e37190e5Smichen nssuint_t *cookie_num_p; 1527e37190e5Smichen nssuint_t *seqnum_p; 1528cb5caa98Sdjl nss_pheader_t *pbuf = (nss_pheader_t *)buffer; 1529e37190e5Smichen nscd_getent_p0_cookie_t *p0c; 1530cb5caa98Sdjl char *me = "nss_psetent"; 1531cb5caa98Sdjl 1532cb5caa98Sdjl if (buffer == NULL || length == 0) { 1533*7d7551bcSMilan Jurik NSCD_SET_STATUS(pbuf, NSS_ERROR, EFAULT); 1534*7d7551bcSMilan Jurik return; 1535cb5caa98Sdjl } 1536cb5caa98Sdjl 1537cb5caa98Sdjl /* 1538cb5caa98Sdjl * If this is a per-user nscd, and the user does not have 1539cb5caa98Sdjl * the necessary credential, return NSS_TRYLOCAL, so the 1540cb5caa98Sdjl * setent/getent can be done locally in the process of the 1541cb5caa98Sdjl * setent call 1542cb5caa98Sdjl */ 1543cb5caa98Sdjl if (_whoami == NSCD_CHILD) { 1544c70a8a3bSmichen OM_uint32 (*func)(); 1545cb5caa98Sdjl OM_uint32 stat; 1546c70a8a3bSmichen nscd_rc_t rc; 1547cb5caa98Sdjl 1548c70a8a3bSmichen rc = get_gss_func((void **)&func); 1549c70a8a3bSmichen if (rc == NSCD_SUCCESS) { 1550c70a8a3bSmichen if (func(&stat, GSS_C_NO_CREDENTIAL, 1551cb5caa98Sdjl NULL, NULL, NULL, NULL) != GSS_S_COMPLETE) { 1552cb5caa98Sdjl 1553cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, 1554cb5caa98Sdjl NSCD_LOG_LEVEL_DEBUG) 1555cb5caa98Sdjl (me, "NSS_TRYLOCAL: fallback to caller process\n"); 1556*7d7551bcSMilan Jurik NSCD_SET_STATUS(pbuf, NSS_TRYLOCAL, 0); 1557*7d7551bcSMilan Jurik return; 1558cb5caa98Sdjl } 1559cb5caa98Sdjl } 1560c70a8a3bSmichen } 1561cb5caa98Sdjl 1562e37190e5Smichen /* check cookie number */ 1563e37190e5Smichen nscd_map_contextp(buffer, contextp, &cookie_num_p, &seqnum_p, 1); 1564cb5caa98Sdjl if (NSCD_STATUS_IS_NOT_OK(pbuf)) 1565cb5caa98Sdjl return; 1566e37190e5Smichen 1567e37190e5Smichen /* set cookie number and sequence number */ 1568e37190e5Smichen p0c = (nscd_getent_p0_cookie_t *)cookie_num_p; 1569e37190e5Smichen if (contextp->ctx == NULL) { 1570e37190e5Smichen /* 1571e37190e5Smichen * first setent (no existing getent context), 1572e37190e5Smichen * return a p0 cookie 1573e37190e5Smichen */ 1574e37190e5Smichen _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG) 1575e37190e5Smichen (me, "first setent, no getent context yet\n"); 1576e37190e5Smichen } else { 1577e37190e5Smichen /* 1578e37190e5Smichen * doing setent on an existing getent context, 1579e37190e5Smichen * release resources allocated and return a 1580e37190e5Smichen * p0 cookie 1581e37190e5Smichen */ 1582e37190e5Smichen _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG) 1583e37190e5Smichen (me, "setent resetting sequence number = %lld\n", *seqnum_p); 1584e37190e5Smichen 15856392794bSMichen Chang if (_nscd_is_getent_ctx_in_use((nscd_getent_context_t *) 15866392794bSMichen Chang contextp->ctx) == 0) { 15876392794bSMichen Chang /* 15886392794bSMichen Chang * context not in use, release the backend and 15896392794bSMichen Chang * return the context to the pool 15906392794bSMichen Chang */ 15916392794bSMichen Chang end_iter_u(NULL, contextp->ctx); 15926392794bSMichen Chang _nscd_put_getent_ctx( 15936392794bSMichen Chang (nscd_getent_context_t *)contextp->ctx); 1594e37190e5Smichen contextp->ctx = NULL; 1595e37190e5Smichen } 15966392794bSMichen Chang } 1597e37190e5Smichen 1598e37190e5Smichen p0c->p0_pid = pid; 1599e37190e5Smichen p0c->p0_time = _nscd_get_start_time(); 1600e37190e5Smichen p0c->p0_seqnum = NSCD_P0_COOKIE_SEQNUM; 1601e37190e5Smichen _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG) 1602e37190e5Smichen (me, "returning a p0 cookie: pid = %ld, time = %ld, seq #= %llx\n", 1603e37190e5Smichen p0c->p0_pid, p0c->p0_time, p0c->p0_seqnum); 1604e37190e5Smichen 1605*7d7551bcSMilan Jurik NSCD_SET_STATUS(pbuf, NSS_SUCCESS, 0); 1606e37190e5Smichen } 1607e37190e5Smichen 1608e37190e5Smichen static void 1609e37190e5Smichen delayed_setent(nss_pheader_t *pbuf, nss_db_initf_t initf, 1610e37190e5Smichen nss_getent_t *contextp, nssuint_t *cookie_num_p, 1611e37190e5Smichen nssuint_t *seqnum_p, pid_t pid) 1612e37190e5Smichen { 1613e37190e5Smichen nscd_getent_context_t *ctx; 1614e37190e5Smichen nscd_sw_return_t swret = { 0 }, *swrp = &swret; 1615e37190e5Smichen char *me = "delayed_setent"; 1616e37190e5Smichen 1617e37190e5Smichen /* 1618e37190e5Smichen * check credential 1619e37190e5Smichen */ 1620e37190e5Smichen _nscd_APP_check_cred(pbuf, &pid, "NSCD_DELAYED_SETENT", 1621e37190e5Smichen NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_ERROR); 1622e37190e5Smichen if (NSCD_STATUS_IS_NOT_OK(pbuf)) { 1623e37190e5Smichen _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG) 1624e37190e5Smichen (me, "invalid credential\n"); 1625e37190e5Smichen return; 1626e37190e5Smichen } 1627e37190e5Smichen 1628cb5caa98Sdjl /* 1629cb5caa98Sdjl * pass the packed header buffer pointer to nss_setent 1630cb5caa98Sdjl */ 1631cb5caa98Sdjl (void) memcpy(&pbuf->nscdpriv, &swrp, sizeof (swrp)); 1632e37190e5Smichen swret.pbuf = pbuf; 1633cb5caa98Sdjl 1634cb5caa98Sdjl /* Perform local setent and set context */ 1635cb5caa98Sdjl nss_setent(NULL, initf, contextp); 1636cb5caa98Sdjl 1637e37190e5Smichen /* insert cookie info into packed buffer header */ 1638cb5caa98Sdjl ctx = (nscd_getent_context_t *)contextp->ctx; 1639cb5caa98Sdjl if (ctx != NULL) { 1640e37190e5Smichen *cookie_num_p = ctx->cookie_num; 1641e37190e5Smichen *seqnum_p = ctx->seq_num; 1642cb5caa98Sdjl ctx->pid = pid; 1643cb5caa98Sdjl } else { 1644cb5caa98Sdjl /* 1645cb5caa98Sdjl * not able to allocate a getent context, the 1646cb5caa98Sdjl * client should try the enumeration locally 1647cb5caa98Sdjl */ 1648e37190e5Smichen *cookie_num_p = NSCD_LOCAL_COOKIE; 1649e37190e5Smichen *seqnum_p = 0; 1650cb5caa98Sdjl 1651cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG) 1652e37190e5Smichen (me, "NSS_TRYLOCAL: cookie # = %lld, sequence # = %lld\n", 1653e37190e5Smichen *cookie_num_p, *seqnum_p); 1654*7d7551bcSMilan Jurik NSCD_SET_STATUS(pbuf, NSS_TRYLOCAL, 0); 1655*7d7551bcSMilan Jurik return; 1656cb5caa98Sdjl } 1657e37190e5Smichen 1658e37190e5Smichen _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG) 1659e37190e5Smichen (me, "NSS_SUCCESS: cookie # = %lld, sequence # = %lld\n", 1660e37190e5Smichen ctx->cookie_num, ctx->seq_num); 1661e37190e5Smichen 1662*7d7551bcSMilan Jurik NSCD_SET_STATUS(pbuf, NSS_SUCCESS, 0); 1663cb5caa98Sdjl } 1664cb5caa98Sdjl 1665cb5caa98Sdjl void 1666cb5caa98Sdjl nss_pgetent(void *buffer, size_t length) 1667cb5caa98Sdjl { 1668cb5caa98Sdjl /* inputs */ 1669cb5caa98Sdjl nss_db_initf_t initf; 1670e37190e5Smichen nss_getent_t context = { 0 }; 1671cb5caa98Sdjl nss_getent_t *contextp = &context; 1672e37190e5Smichen nss_XbyY_args_t arg = { 0}; 1673cb5caa98Sdjl nss_status_t status; 1674e37190e5Smichen nssuint_t *cookie_num_p; 1675e37190e5Smichen nssuint_t *seqnum_p; 1676cb5caa98Sdjl nscd_getent_context_t *ctx; 1677cb5caa98Sdjl int rc; 1678cb5caa98Sdjl nss_pheader_t *pbuf = (nss_pheader_t *)buffer; 1679cb5caa98Sdjl char *me = "nss_pgetent"; 1680cb5caa98Sdjl 1681cb5caa98Sdjl if (buffer == NULL || length == 0) { 1682*7d7551bcSMilan Jurik NSCD_SET_STATUS(pbuf, NSS_ERROR, EFAULT); 1683*7d7551bcSMilan Jurik return; 1684cb5caa98Sdjl } 1685cb5caa98Sdjl 1686e37190e5Smichen /* verify the cookie passed in */ 1687e37190e5Smichen nscd_map_contextp(buffer, contextp, &cookie_num_p, &seqnum_p, 0); 1688e37190e5Smichen if (NSCD_STATUS_IS_NOT_OK(pbuf)) 1689e37190e5Smichen return; 16906392794bSMichen Chang 1691cb5caa98Sdjl /* 1692cb5caa98Sdjl * use the generic nscd_initf for all the getent requests 1693cb5caa98Sdjl * (the TSD key is the pointer to the packed header) 1694cb5caa98Sdjl */ 1695cb5caa98Sdjl rc = set_initf_key(pbuf); 1696cb5caa98Sdjl if (rc != 0) { 1697*7d7551bcSMilan Jurik NSCD_SET_STATUS(pbuf, NSS_UNAVAIL, EINVAL); 1698*7d7551bcSMilan Jurik return; 1699cb5caa98Sdjl } 1700cb5caa98Sdjl initf = nscd_initf; 1701cb5caa98Sdjl 1702e37190e5Smichen /* if no context yet, get one */ 1703e37190e5Smichen if (contextp->ctx == NULL) { 1704e37190e5Smichen nscd_getent_p0_cookie_t *p0c = 1705e37190e5Smichen (nscd_getent_p0_cookie_t *)cookie_num_p; 1706cb5caa98Sdjl 1707e37190e5Smichen delayed_setent(pbuf, initf, contextp, cookie_num_p, 1708e37190e5Smichen seqnum_p, p0c->p0_pid); 1709e37190e5Smichen if (NSCD_STATUS_IS_NOT_OK(pbuf)) { 1710e37190e5Smichen clear_initf_key(); 1711cb5caa98Sdjl return; 1712e37190e5Smichen } 1713e37190e5Smichen } 1714e37190e5Smichen 1715e37190e5Smichen status = nss_packed_context_init(buffer, length, 1716e37190e5Smichen NULL, &initf, &contextp, &arg); 1717e37190e5Smichen if (status != NSS_SUCCESS) { 171829836b19Smichen clear_initf_key(); 171929836b19Smichen _nscd_free_ctx_if_aborted( 172029836b19Smichen (nscd_getent_context_t *)contextp->ctx); 1721*7d7551bcSMilan Jurik NSCD_SET_STATUS(pbuf, status, -1); 1722*7d7551bcSMilan Jurik return; 1723e37190e5Smichen } 1724cb5caa98Sdjl 1725cb5caa98Sdjl /* Perform local search and pack results into return buffer */ 1726cb5caa98Sdjl status = nss_getent(NULL, initf, contextp, &arg); 1727cb5caa98Sdjl NSCD_SET_STATUS(pbuf, status, -1); 1728cb5caa98Sdjl nss_packed_set_status(buffer, length, status, &arg); 1729cb5caa98Sdjl 1730cb5caa98Sdjl /* increment sequence number in the buffer and nscd context */ 1731cb5caa98Sdjl if (status == NSS_SUCCESS) { 1732cb5caa98Sdjl ctx = (nscd_getent_context_t *)contextp->ctx; 1733cb5caa98Sdjl ctx->seq_num++; 1734e37190e5Smichen *seqnum_p = ctx->seq_num; 1735e37190e5Smichen *cookie_num_p = ctx->cookie_num; 1736cb5caa98Sdjl 1737cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG) 1738e37190e5Smichen (me, "getent OK, new sequence # = %lld, len = %lld," 1739e37190e5Smichen " data = >>%s<<\n", *seqnum_p, 1740cb5caa98Sdjl pbuf->data_len, (char *)buffer + pbuf->data_off); 174129836b19Smichen 174229836b19Smichen _nscd_free_ctx_if_aborted(ctx); 1743cb5caa98Sdjl } else { 1744124771bbSmichen /* release the resources used */ 1745cb5caa98Sdjl ctx = (nscd_getent_context_t *)contextp->ctx; 17466392794bSMichen Chang if (ctx != NULL && _nscd_is_getent_ctx_in_use(ctx) == 0) { 1747124771bbSmichen _nscd_put_getent_ctx(ctx); 1748124771bbSmichen contextp->ctx = NULL; 1749124771bbSmichen } 1750cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG) 1751e37190e5Smichen (me, "getent failed, status = %d, sequence # = %lld\n", 1752e37190e5Smichen status, *seqnum_p); 1753cb5caa98Sdjl } 1754cb5caa98Sdjl 1755cb5caa98Sdjl /* clear the TSD key used by the generic initf */ 1756cb5caa98Sdjl clear_initf_key(); 1757cb5caa98Sdjl } 1758cb5caa98Sdjl 1759cb5caa98Sdjl void 1760cb5caa98Sdjl nss_pendent(void *buffer, size_t length) 1761cb5caa98Sdjl { 1762e37190e5Smichen nss_getent_t context = { 0 }; 1763cb5caa98Sdjl nss_getent_t *contextp = &context; 1764e37190e5Smichen nssuint_t *seqnum_p; 1765e37190e5Smichen nssuint_t *cookie_num_p; 1766cb5caa98Sdjl nss_pheader_t *pbuf = (nss_pheader_t *)buffer; 1767cb5caa98Sdjl char *me = "nss_pendent"; 1768cb5caa98Sdjl 1769cb5caa98Sdjl if (buffer == NULL || length == 0) { 1770*7d7551bcSMilan Jurik NSCD_SET_STATUS(pbuf, NSS_ERROR, EFAULT); 1771*7d7551bcSMilan Jurik return; 1772cb5caa98Sdjl } 1773cb5caa98Sdjl 1774cb5caa98Sdjl /* map the contextp from the cookie information */ 1775e37190e5Smichen nscd_map_contextp(buffer, contextp, &cookie_num_p, &seqnum_p, 0); 1776cb5caa98Sdjl if (NSCD_STATUS_IS_NOT_OK(pbuf)) 1777cb5caa98Sdjl return; 1778cb5caa98Sdjl 1779e37190e5Smichen if (contextp->ctx == NULL) 1780e37190e5Smichen return; 1781e37190e5Smichen 1782cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG) 1783e37190e5Smichen (me, "endent, cookie = %lld, sequence # = %lld\n", 1784e37190e5Smichen *cookie_num_p, *seqnum_p); 1785cb5caa98Sdjl 1786cb5caa98Sdjl /* Perform local endent and reset context */ 1787cb5caa98Sdjl nss_endent(NULL, NULL, contextp); 17886392794bSMichen Chang 1789*7d7551bcSMilan Jurik NSCD_SET_STATUS(pbuf, NSS_SUCCESS, 0); 1790cb5caa98Sdjl } 1791cb5caa98Sdjl 1792cb5caa98Sdjl /*ARGSUSED*/ 1793cb5caa98Sdjl void 1794cb5caa98Sdjl nss_pdelete(void *buffer, size_t length) 1795cb5caa98Sdjl { 1796cb5caa98Sdjl nss_pheader_t *pbuf = (nss_pheader_t *)buffer; 1797cb5caa98Sdjl 1798cb5caa98Sdjl /* unnecessary, kept for completeness */ 1799*7d7551bcSMilan Jurik NSCD_SET_STATUS_SUCCESS(pbuf); 1800cb5caa98Sdjl } 1801