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.
257d7551bcSMilan 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
retry_test(nss_status_t res,int n,struct __nsw_lookup_v1 * lkp)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
set_loopback_key(lb_key_t * key)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 *
get_loopback_key(void)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
clear_loopback_key(lb_key_t * key)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
set_initf_key(void * pbuf)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 *
get_initf_key(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
clear_initf_key(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
getparams(int search_fnum,nss_db_initf_t initf,nscd_nsw_params_t * params)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;
208*03d446dbSRichard Lowe (void) memset(params, 0, sizeof (nscd_nsw_params_t));
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 n = p->config_name;
243cb5caa98Sdjl for (j = 0; j < NSCD_NUM_DB; j++) {
244cb5caa98Sdjl dbn = NSCD_NSW_DB_NAME(j);
245cb5caa98Sdjl if (*n == *dbn) {
246cb5caa98Sdjl if (strcmp(n, dbn) == 0) {
247cb5caa98Sdjl params->cfgdbi = j;
248cb5caa98Sdjl break;
249cb5caa98Sdjl }
250cb5caa98Sdjl }
251cb5caa98Sdjl }
252cb5caa98Sdjl }
253cb5caa98Sdjl
254cb5caa98Sdjl /* map the database name to the pseudo database index */
255cb5caa98Sdjl if (params->cfgdbi != -1) {
256cb5caa98Sdjl if (strstr(p->config_name, "_compat") != NULL) {
257cb5caa98Sdjl n = p->name;
258cb5caa98Sdjl for (j = params->cfgdbi; j < NSCD_NUM_DB; j++) {
259cb5caa98Sdjl dbn = NSCD_NSW_DB_NAME(j);
260cb5caa98Sdjl if (*n == *dbn) {
261cb5caa98Sdjl if (strcmp(n, dbn) == 0) {
262cb5caa98Sdjl params->compati = j;
263cb5caa98Sdjl break;
264cb5caa98Sdjl }
265cb5caa98Sdjl }
266cb5caa98Sdjl }
267cb5caa98Sdjl }
268cb5caa98Sdjl }
269cb5caa98Sdjl
270bee2e9ddSmichen /*
271bee2e9ddSmichen * if unsupported database, let caller determine what to do next
272bee2e9ddSmichen */
273bee2e9ddSmichen if (params->dbi == -1) {
274bee2e9ddSmichen _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG)
275bee2e9ddSmichen (me, "unsupported database: %s\n", p->name);
276bee2e9ddSmichen return (NSCD_CFG_UNSUPPORTED_SWITCH_DB);
277bee2e9ddSmichen }
278bee2e9ddSmichen
279cb5caa98Sdjl return (rc);
280cb5caa98Sdjl }
281cb5caa98Sdjl
282cb5caa98Sdjl static void
nscd_initf(nss_db_params_t * p)283cb5caa98Sdjl nscd_initf(nss_db_params_t *p)
284cb5caa98Sdjl {
285cb5caa98Sdjl nss_pheader_t *pbuf;
286cb5caa98Sdjl nssuint_t off;
287cb5caa98Sdjl nss_dbd_t *pdbd;
288cb5caa98Sdjl char *me = "nscd_initf";
289cb5caa98Sdjl
290cb5caa98Sdjl pbuf = (nss_pheader_t *)get_initf_key();
291cb5caa98Sdjl if (pbuf == NULL) {
292cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG)
293cb5caa98Sdjl (me, "ERROR: initf key not set\n");
294cb5caa98Sdjl return;
295cb5caa98Sdjl }
296cb5caa98Sdjl
297cb5caa98Sdjl if (pbuf->dbd_len <= sizeof (nss_dbd_t)) {
298cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG)
299cb5caa98Sdjl (me, "invalid db front params data ? dbd_len = %d\n",
300cb5caa98Sdjl pbuf->dbd_len);
301cb5caa98Sdjl return;
302cb5caa98Sdjl }
303cb5caa98Sdjl
304cb5caa98Sdjl off = pbuf->dbd_off;
305cb5caa98Sdjl pdbd = (nss_dbd_t *)((void *)((char *)pbuf + off));
306cb5caa98Sdjl
307cb5caa98Sdjl p->name = (char *)pdbd + pdbd->o_name;
308cb5caa98Sdjl p->config_name = (char *)pdbd + pdbd->o_config_name;
309cb5caa98Sdjl p->default_config = (char *)pdbd + pdbd->o_default_config;
310cb5caa98Sdjl p->flags = (enum nss_dbp_flags)pdbd->flags;
311cb5caa98Sdjl (void) memcpy(&p->private, &pbuf->nscdpriv, sizeof (p->private));
312cb5caa98Sdjl
313cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG)
314cb5caa98Sdjl (me, "db frontend params: name =%s, config_name = %s, "
315cb5caa98Sdjl "default_config = %s, flags = %x\n", p->name,
316cb5caa98Sdjl (p->config_name && *p->config_name != '\0' ?
317cb5caa98Sdjl p->config_name : "<NOT SPECIFIED>"),
318cb5caa98Sdjl (p->default_config && *p->default_config != '\0' ?
319cb5caa98Sdjl p->default_config : "<NOT SPECIFIED>"),
320cb5caa98Sdjl p->flags);
321cb5caa98Sdjl }
322cb5caa98Sdjl
323cb5caa98Sdjl
324cb5caa98Sdjl static void
trace_result(int dbi,int srci,int op,nss_status_t res,nss_XbyY_args_t * arg)325cb5caa98Sdjl trace_result(
326cb5caa98Sdjl int dbi,
327cb5caa98Sdjl int srci,
328cb5caa98Sdjl int op,
329cb5caa98Sdjl nss_status_t res,
330cb5caa98Sdjl nss_XbyY_args_t *arg)
331cb5caa98Sdjl {
332cb5caa98Sdjl char *res_str;
333cb5caa98Sdjl char *src = "?";
334cb5caa98Sdjl char *db = "?";
33518bdb8a7Smichen char *data_str = "<NOT STRING FORMAT>";
33618bdb8a7Smichen int data_len = 0;
33718bdb8a7Smichen char *me = "trace_result";
338cb5caa98Sdjl
339cb5caa98Sdjl switch (res) {
340cb5caa98Sdjl case NSS_SUCCESS:
341cb5caa98Sdjl res_str = "NSS_SUCCESS";
342cb5caa98Sdjl break;
343cb5caa98Sdjl case NSS_NOTFOUND:
344cb5caa98Sdjl res_str = "NSS_NOTFOUND";
345cb5caa98Sdjl break;
346cb5caa98Sdjl case NSS_UNAVAIL:
347cb5caa98Sdjl res_str = "NSS_UNAVAIL";
348cb5caa98Sdjl break;
349cb5caa98Sdjl case NSS_TRYAGAIN:
350cb5caa98Sdjl res_str = "NSS_TRYAGAIN";
351cb5caa98Sdjl break;
352cb5caa98Sdjl case NSS_NISSERVDNS_TRYAGAIN:
353cb5caa98Sdjl res_str = "NSS_NISSERVDNS_TRYAGAIN";
354cb5caa98Sdjl break;
355cb5caa98Sdjl default:
356cb5caa98Sdjl res_str = "UNKNOWN STATUS";
357cb5caa98Sdjl break;
358cb5caa98Sdjl }
359cb5caa98Sdjl
360cb5caa98Sdjl if (dbi != -1)
361cb5caa98Sdjl db = NSCD_NSW_DB_NAME(dbi);
362cb5caa98Sdjl if (srci != -1)
363cb5caa98Sdjl src = NSCD_NSW_SRC_NAME(srci);
364cb5caa98Sdjl
36518bdb8a7Smichen if (arg->buf.result == NULL) {
36618bdb8a7Smichen data_str = arg->buf.buffer;
36718bdb8a7Smichen data_len = arg->returnlen;
36818bdb8a7Smichen }
36918bdb8a7Smichen
370cb5caa98Sdjl if (res == NSS_SUCCESS) {
371bf1e3beeSmichen _nscd_logit(me, "%s: database: %s, operation: %d, "
372bf1e3beeSmichen "source: %s returned >>%s<<, length = %d\n",
37318bdb8a7Smichen res_str, db, op, src, data_str, data_len);
374cb5caa98Sdjl return;
375cb5caa98Sdjl }
376cb5caa98Sdjl
377bf1e3beeSmichen _nscd_logit(me, "%s: database: %s, operation: %d, source: %s, "
378940a40eaSsm26363 "erange= %d, herrno: %s (%d)\n",
379940a40eaSsm26363 res_str, db, op, src, arg->erange, hstrerror(arg->h_errno),
380940a40eaSsm26363 arg->h_errno);
381cb5caa98Sdjl }
382cb5caa98Sdjl
383cb5caa98Sdjl /*
384cb5caa98Sdjl * Determine if a request should be done locally in the getXbyY caller's
3850dfdd7f3Smichen * process. Return none zero if yes, 0 otherwise. This should be called
3860dfdd7f3Smichen * before the switch engine steps through the backends/sources.
387bf1e3beeSmichen * This function returns 1 if:
388cb5caa98Sdjl * -- the database is exec_attr and the search_flag is GET_ALL
389cb5caa98Sdjl */
390cb5caa98Sdjl static int
try_local(int dbi,void * arg)391cb5caa98Sdjl try_local(
392cb5caa98Sdjl int dbi,
393cb5caa98Sdjl void *arg)
394cb5caa98Sdjl {
395cb5caa98Sdjl struct nss_XbyY_args *ap = (struct nss_XbyY_args *)arg;
396cb5caa98Sdjl _priv_execattr *ep;
397cb5caa98Sdjl int rc = 0;
398cb5caa98Sdjl char *me = "try_local";
399cb5caa98Sdjl
400cb5caa98Sdjl if (strcmp(NSCD_NSW_DB_NAME(dbi), NSS_DBNAM_EXECATTR) == 0) {
40101ef659dSJoep Vesseur if ((ep = ap->key.attrp) != NULL && IS_GET_ALL(ep->search_flag))
402cb5caa98Sdjl rc = 1;
403cb5caa98Sdjl }
404cb5caa98Sdjl
405cb5caa98Sdjl if (rc != 0) {
406cb5caa98Sdjl
407cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG)
408cb5caa98Sdjl (me, "TRYLOCAL: exec_attr:GET_ALL\n");
409cb5caa98Sdjl }
410cb5caa98Sdjl
411cb5caa98Sdjl return (rc);
412cb5caa98Sdjl }
413cb5caa98Sdjl
4140dfdd7f3Smichen /*
4150dfdd7f3Smichen * Determine if a request should be done locally in the getXbyY caller's
4160dfdd7f3Smichen * process. Return none zero if yes, 0 otherwise. This should be called
4170dfdd7f3Smichen * before the switch engine invokes any backend.
418bf1e3beeSmichen * This function returns 1 if:
419a3dd7914SMichen Chang * -- the database is shadow and the source is compat
4200dfdd7f3Smichen */
4210dfdd7f3Smichen static int
try_local2(int dbi,int srci)4220dfdd7f3Smichen try_local2(
4230dfdd7f3Smichen int dbi,
4240dfdd7f3Smichen int srci)
4250dfdd7f3Smichen {
4260dfdd7f3Smichen int rc = 0;
4270dfdd7f3Smichen char *me = "try_local2";
4280dfdd7f3Smichen
4290dfdd7f3Smichen if (*NSCD_NSW_DB_NAME(dbi) == 's' &&
4300dfdd7f3Smichen strcmp(NSCD_NSW_DB_NAME(dbi), NSS_DBNAM_SHADOW) == 0) {
43136e852a1SRaja Andra if (strcmp(NSCD_NSW_SRC_NAME(srci), "compat") == 0)
4320dfdd7f3Smichen rc = 1;
4330dfdd7f3Smichen }
4340dfdd7f3Smichen
4350dfdd7f3Smichen if (rc != 0) {
4360dfdd7f3Smichen _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG)
437a3dd7914SMichen Chang (me, "TRYLOCAL: database: shadow, source: %s\n",
438a3dd7914SMichen Chang NSCD_NSW_SRC_NAME(srci));
4390dfdd7f3Smichen }
4400dfdd7f3Smichen
4410dfdd7f3Smichen return (rc);
4420dfdd7f3Smichen }
4430dfdd7f3Smichen
444cb5caa98Sdjl static nscd_rc_t
get_lib_func(void ** handle,void ** func,mutex_t * lock,char * lib,char * name,void ** func_p)44518bdb8a7Smichen get_lib_func(void **handle, void **func, mutex_t *lock,
44618bdb8a7Smichen char *lib, char *name, void **func_p)
447c70a8a3bSmichen {
44818bdb8a7Smichen char *me = "get_lib_func";
449c70a8a3bSmichen void *sym;
450c70a8a3bSmichen
45118bdb8a7Smichen if (func_p != NULL && *handle != NULL && *func != NULL) {
45218bdb8a7Smichen *func_p = *func;
453c70a8a3bSmichen return (NSCD_SUCCESS);
454c70a8a3bSmichen }
455c70a8a3bSmichen
45618bdb8a7Smichen (void) mutex_lock(lock);
457c70a8a3bSmichen
458c70a8a3bSmichen /* close the handle if requested */
459c70a8a3bSmichen if (func_p == NULL) {
46018bdb8a7Smichen if (*handle != NULL) {
46118bdb8a7Smichen (void) dlclose(*handle);
46218bdb8a7Smichen *handle = NULL;
46318bdb8a7Smichen *func = NULL;
464c70a8a3bSmichen }
46518bdb8a7Smichen (void) mutex_unlock(lock);
466c70a8a3bSmichen return (NSCD_SUCCESS);
467c70a8a3bSmichen }
468c70a8a3bSmichen
46918bdb8a7Smichen if (*handle != NULL && *func != NULL) {
47018bdb8a7Smichen *func_p = *func;
47118bdb8a7Smichen (void) mutex_unlock(lock);
472c70a8a3bSmichen return (NSCD_SUCCESS);
473c70a8a3bSmichen }
474c70a8a3bSmichen
47518bdb8a7Smichen if (*handle == NULL) {
47618bdb8a7Smichen *handle = dlopen(lib, RTLD_LAZY);
47718bdb8a7Smichen if (*handle == NULL) {
478bf1e3beeSmichen _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_ERROR)
47918bdb8a7Smichen (me, "unable to dlopen %s\n", lib);
48018bdb8a7Smichen (void) mutex_unlock(lock);
481c70a8a3bSmichen return (NSCD_CFG_DLOPEN_ERROR);
482c70a8a3bSmichen }
483c70a8a3bSmichen }
484c70a8a3bSmichen
48518bdb8a7Smichen if ((sym = dlsym(*handle, name)) == NULL) {
486c70a8a3bSmichen
487c70a8a3bSmichen _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_ERROR)
48818bdb8a7Smichen (me, "unable to find symbol %s:%s\n", lib, name);
48918bdb8a7Smichen (void) mutex_unlock(lock);
490c70a8a3bSmichen return (NSCD_CFG_DLSYM_ERROR);
491c70a8a3bSmichen } else {
49218bdb8a7Smichen *func_p = sym;
49318bdb8a7Smichen *func = sym;
494c70a8a3bSmichen }
495c70a8a3bSmichen
49618bdb8a7Smichen (void) mutex_unlock(lock);
497c70a8a3bSmichen return (NSCD_SUCCESS);
498c70a8a3bSmichen }
499c70a8a3bSmichen
50018bdb8a7Smichen static nscd_rc_t
get_libc_nss_search(void ** func_p)50118bdb8a7Smichen get_libc_nss_search(void **func_p)
50218bdb8a7Smichen {
50318bdb8a7Smichen static void *handle = NULL;
50418bdb8a7Smichen static void *func = NULL;
50518bdb8a7Smichen static mutex_t lock = DEFAULTMUTEX;
50618bdb8a7Smichen
50718bdb8a7Smichen return (get_lib_func(&handle, &func, &lock,
50818bdb8a7Smichen "libc.so", "nss_search", func_p));
50918bdb8a7Smichen }
51018bdb8a7Smichen
51118bdb8a7Smichen static nscd_rc_t
get_gss_func(void ** func_p)51218bdb8a7Smichen get_gss_func(void **func_p)
51318bdb8a7Smichen {
51418bdb8a7Smichen static void *handle = NULL;
51518bdb8a7Smichen static void *func = NULL;
51618bdb8a7Smichen static mutex_t lock = DEFAULTMUTEX;
51718bdb8a7Smichen
51818bdb8a7Smichen return (get_lib_func(&handle, &func, &lock,
51918bdb8a7Smichen "libgss.so", "gss_inquire_cred", func_p));
52018bdb8a7Smichen }
52118bdb8a7Smichen
522b57459abSJulian Pullen static nscd_rc_t
get_sldap_shadow_func(void ** func_p)523b57459abSJulian Pullen get_sldap_shadow_func(void **func_p)
524b57459abSJulian Pullen {
525b57459abSJulian Pullen static void *handle = NULL;
526b57459abSJulian Pullen static void *func = NULL;
527b57459abSJulian Pullen static mutex_t lock = DEFAULTMUTEX;
528b57459abSJulian Pullen
529b57459abSJulian Pullen return (get_lib_func(&handle, &func, &lock,
530b57459abSJulian Pullen "libsldap.so", "__ns_ldap_is_shadow_update_enabled",
531b57459abSJulian Pullen func_p));
532b57459abSJulian Pullen }
533b57459abSJulian Pullen
5344b22b933Srs200217 /*
5354b22b933Srs200217 * get_dns_funcs returns pointers to gethostbyname functions in the
5364b22b933Srs200217 * dynamically loaded nss_dns & nss_mdns modules that return host
5374b22b933Srs200217 * lookup results along with the TTL value in the DNS resource
5384b22b933Srs200217 * records. The dnsi parameter indicates whether the lookup database
5394b22b933Srs200217 * is hosts(0) or ipnodes(1). The srcname parameter identifies the DNS
5404b22b933Srs200217 * module: dns/mdns and the function returns the address of the specific
5414b22b933Srs200217 * gethostbyname function in func_p variable.
5424b22b933Srs200217 */
543c70a8a3bSmichen static nscd_rc_t
get_dns_funcs(int dnsi,nss_status_t (** func_p)(),const char * srcname)5444b22b933Srs200217 get_dns_funcs(int dnsi, nss_status_t (**func_p)(), const char *srcname)
545cb5caa98Sdjl {
5464b22b933Srs200217 int si;
54718bdb8a7Smichen void **funcpp;
5484b22b933Srs200217 static void *handle[2] = { NULL, NULL };
5494b22b933Srs200217 static mutex_t func_lock[2] = { DEFAULTMUTEX, DEFAULTMUTEX };
5504b22b933Srs200217 static void *func[2][2] = {{NULL, NULL}, {NULL, NULL}};
5514b22b933Srs200217 static const char *lib[2] = { "nss_dns.so.1", "nss_mdns.so.1" };
5524b22b933Srs200217 static const char *func_name[2][2] =
5534b22b933Srs200217 {{ "_nss_get_dns_hosts_name", "_nss_get_dns_ipnodes_name" },
5544b22b933Srs200217 { "_nss_get_mdns_hosts_name", "_nss_get_mdns_ipnodes_name" }};
555cb5caa98Sdjl
5564b22b933Srs200217 /* source index: 0 = dns, 1 = mdns */
5574b22b933Srs200217 if (strcmp(srcname, "dns") == 0)
5584b22b933Srs200217 si = 0;
5594b22b933Srs200217 else
5604b22b933Srs200217 si = 1;
5614b22b933Srs200217
5624b22b933Srs200217 /*
5634b22b933Srs200217 * function index (func[si][dnsi]):
5644b22b933Srs200217 * [0,0] = dns/hosts, [0,1] = dns/ipnodes,
5654b22b933Srs200217 * [1,0] = mdns/hosts, [1,1] = mdns/ipnodes
5664b22b933Srs200217 */
5674b22b933Srs200217
56818bdb8a7Smichen if (dnsi < 0) { /* close handle */
56918bdb8a7Smichen funcpp = NULL;
5704b22b933Srs200217 (void) mutex_lock(&func_lock[si]);
5714b22b933Srs200217 func[si][0] = NULL;
5724b22b933Srs200217 func[si][1] = NULL;
5734b22b933Srs200217 (void) mutex_unlock(&func_lock[si]);
57418bdb8a7Smichen } else
57518bdb8a7Smichen funcpp = (void **)func_p;
576cb5caa98Sdjl
57718bdb8a7Smichen return (get_lib_func(&handle[si], &func[si][dnsi], &func_lock[si],
57818bdb8a7Smichen (char *)lib[si], (char *)func_name[si][dnsi], funcpp));
579cb5caa98Sdjl }
580cb5caa98Sdjl
581cb5caa98Sdjl static nss_status_t
search_dns_withttl(nscd_sw_return_t * swret,const char * srcname,int dnsi)5824b22b933Srs200217 search_dns_withttl(nscd_sw_return_t *swret, const char *srcname, int dnsi)
583cb5caa98Sdjl {
584cb5caa98Sdjl nss_status_t (*func)();
585cb5caa98Sdjl nss_status_t res = NSS_UNAVAIL;
586cb5caa98Sdjl nscd_rc_t rc;
587cb5caa98Sdjl
588cb5caa98Sdjl swret->noarg = 0;
5894b22b933Srs200217 if (strcmp(srcname, "dns") != 0 && strcmp(srcname, "mdns") != 0)
590cb5caa98Sdjl return (NSS_ERROR);
591cb5caa98Sdjl
5924b22b933Srs200217 rc = get_dns_funcs(dnsi, &func, srcname);
5934b22b933Srs200217 if (rc == NSCD_SUCCESS) {
5944b22b933Srs200217 /*
5954b22b933Srs200217 * data_len in the packed buf header may be changed
5964b22b933Srs200217 * by the dns or mdns backend, reset it just in
5974b22b933Srs200217 * case
5984b22b933Srs200217 */
5994b22b933Srs200217 ((nss_pheader_t *)swret->pbuf)->data_len =
6004b22b933Srs200217 swret->datalen;
601cb5caa98Sdjl res = (func)(NULL, &swret->pbuf, &swret->pbufsiz);
6024b22b933Srs200217 }
603cb5caa98Sdjl return (res);
604cb5caa98Sdjl }
605cb5caa98Sdjl
606cb5caa98Sdjl /*
607cb5caa98Sdjl * Returns a flag to indicate if needs to fall back to the
608cb5caa98Sdjl * main nscd when a per-user lookup failed with rc NSS_NOTFOUND.
609cb5caa98Sdjl */
610cb5caa98Sdjl static int
set_fallback_flag(char * srcname,nss_status_t rc)611cb5caa98Sdjl set_fallback_flag(char *srcname, nss_status_t rc)
612cb5caa98Sdjl {
613cb5caa98Sdjl char *me = "set_fallback_flag";
614cb5caa98Sdjl if (strcmp(srcname, "ldap") == 0 && rc == NSS_NOTFOUND) {
615cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG)
616cb5caa98Sdjl (me, "NSS_NOTFOUND (ldap): fallback to main nscd "
617cb5caa98Sdjl "may be needed\n");
618cb5caa98Sdjl return (1);
619cb5caa98Sdjl }
620cb5caa98Sdjl return (0);
621cb5caa98Sdjl }
622cb5caa98Sdjl
623cb5caa98Sdjl nss_status_t
nss_search(nss_db_root_t * rootp,nss_db_initf_t initf,int search_fnum,void * search_args)624cb5caa98Sdjl nss_search(nss_db_root_t *rootp, nss_db_initf_t initf, int search_fnum,
625cb5caa98Sdjl void *search_args)
626cb5caa98Sdjl {
627cb5caa98Sdjl char *me = "nss_search";
628cb5caa98Sdjl nss_status_t res = NSS_UNAVAIL;
629cb5caa98Sdjl nscd_nsw_state_t *s = NULL;
630cb5caa98Sdjl int n_src;
631cb5caa98Sdjl unsigned int status_vec = 0;
632cb5caa98Sdjl int dbi, srci = -1;
633cb5caa98Sdjl int check_loopback = 0;
634cb5caa98Sdjl int state_thr = 0;
635cb5caa98Sdjl lb_key_t key, *k = NULL;
636cb5caa98Sdjl nss_db_root_t root_db;
637cb5caa98Sdjl nscd_nsw_params_t params;
638cb5caa98Sdjl nscd_sw_return_t *swret;
639cb5caa98Sdjl
640cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG)
641cb5caa98Sdjl (me, "rootp = %p, initf = %p, search_fnum = %d, "
642cb5caa98Sdjl "search_args = %p\n", rootp, initf,
643cb5caa98Sdjl search_fnum, search_args);
644cb5caa98Sdjl
645cb5caa98Sdjl NSCD_SW_STATS_G.lookup_request_received_g++;
646cb5caa98Sdjl NSCD_SW_STATS_G.lookup_request_in_progress_g++;
647cb5caa98Sdjl NSCD_SW_STATS_G.lookup_request_queued_g++;
648cb5caa98Sdjl
649cb5caa98Sdjl /* determine db index, cfg db index, etc */
650bee2e9ddSmichen if (getparams(search_fnum, initf, ¶ms) ==
651bee2e9ddSmichen NSCD_CFG_UNSUPPORTED_SWITCH_DB) {
652bee2e9ddSmichen /*
653bee2e9ddSmichen * if unsupported database and the request is from the
654bee2e9ddSmichen * the door, tell the door client to try it locally
655bee2e9ddSmichen */
65618bdb8a7Smichen if (initf == nscd_initf) {
657bee2e9ddSmichen res = NSS_TRYLOCAL;
658bee2e9ddSmichen goto error_exit;
65918bdb8a7Smichen } else { /* otherwise, let libc:nss_search() handle it */
66018bdb8a7Smichen nss_status_t (*func)();
66118bdb8a7Smichen
66218bdb8a7Smichen if (get_libc_nss_search((void **)&func) ==
66318bdb8a7Smichen NSCD_SUCCESS)
66418bdb8a7Smichen return ((func)(rootp, initf, search_fnum,
66518bdb8a7Smichen search_args));
66618bdb8a7Smichen else
66718bdb8a7Smichen goto error_exit;
66818bdb8a7Smichen }
669bee2e9ddSmichen }
670cb5caa98Sdjl dbi = params.dbi;
671cb5caa98Sdjl
672cb5caa98Sdjl /* get address of the switch engine return data area */
673cb5caa98Sdjl if (initf == nscd_initf) {
674cb5caa98Sdjl swret = (nscd_sw_return_t *)params.p.private;
675cb5caa98Sdjl swret->srci = -1;
676cb5caa98Sdjl } else {
677cb5caa98Sdjl swret = NULL;
678cb5caa98Sdjl params.dnsi = -1;
679cb5caa98Sdjl }
680cb5caa98Sdjl
681cb5caa98Sdjl /*
68218bdb8a7Smichen * for door request that should be processed by the client,
683cb5caa98Sdjl * send it back with status NSS_TRYLOCAL
684cb5caa98Sdjl */
68518bdb8a7Smichen if (initf == nscd_initf && try_local(dbi, search_args) == 1) {
686cb5caa98Sdjl res = NSS_TRYLOCAL;
687cb5caa98Sdjl goto error_exit;
688cb5caa98Sdjl }
689cb5caa98Sdjl
690cb5caa98Sdjl NSCD_SW_STATS(dbi).lookup_request_received++;
691cb5caa98Sdjl NSCD_SW_STATS(dbi).lookup_request_in_progress++;
692cb5caa98Sdjl NSCD_SW_STATS(dbi).lookup_request_queued++;
693cb5caa98Sdjl
694cb5caa98Sdjl /* if lookup not enabled, return NSS_UNAVAIL */
695cb5caa98Sdjl if (!(NSCD_SW_CFG_G.enable_lookup_g == nscd_true &&
696cb5caa98Sdjl NSCD_SW_CFG(dbi).enable_lookup == nscd_true)) {
697cb5caa98Sdjl
698cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG)
699cb5caa98Sdjl (me, "lookup not enabled for %s\n", NSCD_NSW_DB_NAME(dbi));
700cb5caa98Sdjl
701cb5caa98Sdjl goto error_exit;
702cb5caa98Sdjl }
703cb5caa98Sdjl
704cb5caa98Sdjl /* determine if loopback checking is configured */
705cb5caa98Sdjl if (NSCD_SW_CFG_G.enable_loopback_checking_g == nscd_true &&
706cb5caa98Sdjl NSCD_SW_CFG(dbi).enable_loopback_checking == nscd_true) {
707cb5caa98Sdjl check_loopback = 1;
708cb5caa98Sdjl
709cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG)
710cb5caa98Sdjl (me, "loopback checking enabled for %s\n",
711cb5caa98Sdjl NSCD_NSW_DB_NAME(dbi));
712cb5caa98Sdjl }
713cb5caa98Sdjl
714cb5caa98Sdjl if (check_loopback) {
715cb5caa98Sdjl k = get_loopback_key();
716cb5caa98Sdjl if (k != NULL) {
717cb5caa98Sdjl if (k->dbi != dbi || k->fnum != search_fnum) {
718cb5caa98Sdjl clear_loopback_key(k);
719cb5caa98Sdjl k = NULL;
720cb5caa98Sdjl }
721cb5caa98Sdjl }
722cb5caa98Sdjl }
723cb5caa98Sdjl
724cb5caa98Sdjl if (s == 0) {
725cb5caa98Sdjl nscd_rc_t rc;
726cb5caa98Sdjl
727cb5caa98Sdjl if (check_loopback) {
728cb5caa98Sdjl rc = _nscd_get_nsw_state_thread(&root_db, ¶ms);
729cb5caa98Sdjl state_thr = 1;
730cb5caa98Sdjl } else
731cb5caa98Sdjl rc = _nscd_get_nsw_state(&root_db, ¶ms);
732cb5caa98Sdjl
733cb5caa98Sdjl NSCD_SW_STATS_G.lookup_request_queued_g--;
734cb5caa98Sdjl NSCD_SW_STATS(dbi).lookup_request_queued--;
735cb5caa98Sdjl
736cb5caa98Sdjl if (rc != NSCD_SUCCESS)
737cb5caa98Sdjl goto error_exit;
738cb5caa98Sdjl
739cb5caa98Sdjl s = (nscd_nsw_state_t *)root_db.s;
740cb5caa98Sdjl }
741cb5caa98Sdjl
742cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG)
743e37190e5Smichen (me, "database = %s, config = >>%s<<\n", NSCD_NSW_DB_NAME(dbi),
744cb5caa98Sdjl (*s->nsw_cfg_p)->nsw_cfg_str);
745cb5caa98Sdjl
746cb5caa98Sdjl for (n_src = 0; n_src < s->max_src; n_src++) {
74718bdb8a7Smichen nss_backend_t *be = NULL;
74818bdb8a7Smichen nss_backend_op_t funcp = NULL;
749cb5caa98Sdjl struct __nsw_lookup_v1 *lkp;
750cb5caa98Sdjl int smf_state;
751cb5caa98Sdjl int n_loop = 0;
752cb5caa98Sdjl int max_retry = 10;
753cb5caa98Sdjl
754cb5caa98Sdjl res = NSS_UNAVAIL;
755cb5caa98Sdjl
756cb5caa98Sdjl if (n_src == 0)
757cb5caa98Sdjl lkp = s->config->lookups;
758cb5caa98Sdjl else
759cb5caa98Sdjl lkp = lkp->next;
760cb5caa98Sdjl
761cb5caa98Sdjl /* set the number of max. retries */
762cb5caa98Sdjl if (lkp->actions[__NSW_TRYAGAIN] == __NSW_TRYAGAIN_NTIMES)
763cb5caa98Sdjl max_retry = lkp->max_retries;
764cb5caa98Sdjl
765cb5caa98Sdjl srci = (*s->nsw_cfg_p)->src_idx[n_src];
766cb5caa98Sdjl if (swret != NULL)
767cb5caa98Sdjl swret->srci = srci;
768cb5caa98Sdjl
769cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG)
770cb5caa98Sdjl (me, "nsw source = %s\n", NSCD_NSW_SRC_NAME(srci));
771cb5caa98Sdjl
772b57459abSJulian Pullen /*
773b57459abSJulian Pullen * If no privilege to look up, skip.
774b57459abSJulian Pullen * 'files' requires PRIV_FILE_DAC_READ to read shadow(4) data,
775b57459abSJulian Pullen * 'ldap' requires all zones privilege.
776b57459abSJulian Pullen */
777b57459abSJulian Pullen if (params.privdb == 1 && swret != NULL) {
778b57459abSJulian Pullen boolean_t (*is_shadow_update_enabled)();
779b57459abSJulian Pullen boolean_t check_ldap_priv = B_FALSE;
780b57459abSJulian Pullen
781b57459abSJulian Pullen if (strcmp(NSCD_NSW_SRC_NAME(srci), "ldap") == 0) {
782b57459abSJulian Pullen if (get_sldap_shadow_func(
783b57459abSJulian Pullen (void **)&is_shadow_update_enabled) ==
784b57459abSJulian Pullen NSCD_SUCCESS &&
785b57459abSJulian Pullen is_shadow_update_enabled()) {
786b57459abSJulian Pullen check_ldap_priv = B_TRUE;
787b57459abSJulian Pullen
788b57459abSJulian Pullen /*
789b57459abSJulian Pullen * A peruser nscd doesn't have
790b57459abSJulian Pullen * the privileges to lookup a
791b57459abSJulian Pullen * private database, such as shadow,
792b57459abSJulian Pullen * returns NSS_ALTRETRY to have the
793b57459abSJulian Pullen * main nscd do the job.
794b57459abSJulian Pullen */
795b57459abSJulian Pullen if (_whoami == NSCD_CHILD) {
796b57459abSJulian Pullen res = NSS_ALTRETRY;
797b57459abSJulian Pullen goto free_nsw_state;
798b57459abSJulian Pullen }
799b57459abSJulian Pullen }
800b57459abSJulian Pullen }
801b57459abSJulian Pullen
802b57459abSJulian Pullen if ((strcmp(NSCD_NSW_SRC_NAME(srci), "files") == 0 &&
803b57459abSJulian Pullen _nscd_check_client_priv(NSCD_READ_PRIV) != 0) ||
804b57459abSJulian Pullen (check_ldap_priv &&
805b57459abSJulian Pullen _nscd_check_client_priv(NSCD_ALL_PRIV) != 0)) {
806b57459abSJulian Pullen _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE,
807b57459abSJulian Pullen NSCD_LOG_LEVEL_DEBUG)
808cb5caa98Sdjl (me, "no privilege to look up, skip source\n");
809cb5caa98Sdjl
810cb5caa98Sdjl goto next_src;
811cb5caa98Sdjl }
812b57459abSJulian Pullen }
813cb5caa98Sdjl
814cb5caa98Sdjl /* get state of the (backend) client service */
815cb5caa98Sdjl smf_state = _nscd_get_smf_state(srci, dbi, 0);
816cb5caa98Sdjl
817cb5caa98Sdjl /* stop if the source is one that should be TRYLOCAL */
818d2ba247cSmichen if (initf == nscd_initf && /* request is from the door */
819d2ba247cSmichen (smf_state == NSCD_SVC_STATE_UNSUPPORTED_SRC ||
820d2ba247cSmichen (smf_state == NSCD_SVC_STATE_FOREIGN_SRC &&
821d2ba247cSmichen s->be_version_p[n_src] == NULL) ||
82218bdb8a7Smichen (params.privdb && try_local2(dbi, srci) == 1))) {
823bf1e3beeSmichen _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG)
824cb5caa98Sdjl (me, "returning TRYLOCAL ... \n");
825cb5caa98Sdjl res = NSS_TRYLOCAL;
826cb5caa98Sdjl goto free_nsw_state;
827cb5caa98Sdjl }
828cb5caa98Sdjl
829cb5caa98Sdjl if (check_loopback && k != NULL) {
830cb5caa98Sdjl
831cb5caa98Sdjl if (k->srci == srci && k->dbi == dbi)
832cb5caa98Sdjl if (k->fnum == search_fnum) {
833cb5caa98Sdjl
834cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE,
835cb5caa98Sdjl NSCD_LOG_LEVEL_DEBUG)
836cb5caa98Sdjl (me, "loopback detected: "
837cb5caa98Sdjl "source = %s, database = %s "
838cb5caa98Sdjl "search fnum = %d\n",
839cb5caa98Sdjl NSCD_NSW_SRC_NAME(srci),
840cb5caa98Sdjl NSCD_NSW_DB_NAME(dbi), search_fnum);
841cb5caa98Sdjl
842cb5caa98Sdjl NSCD_SW_STATS_G.loopback_nsw_db_skipped_g++;
843cb5caa98Sdjl NSCD_SW_STATS(dbi).loopback_nsw_db_skipped++;
844cb5caa98Sdjl continue;
845cb5caa98Sdjl }
846cb5caa98Sdjl }
847cb5caa98Sdjl
848cb5caa98Sdjl be = s->be[n_src];
849cb5caa98Sdjl if (be != NULL)
850cb5caa98Sdjl funcp = NSS_LOOKUP_DBOP(be, search_fnum);
851cb5caa98Sdjl
852d2ba247cSmichen /* request could be from within nscd so check states again */
85318bdb8a7Smichen if (be == NULL || (params.dnsi < 0 && (funcp == NULL ||
85418bdb8a7Smichen (smf_state != NSCD_SVC_STATE_UNINITED &&
855d2ba247cSmichen smf_state != NSCD_SVC_STATE_UNSUPPORTED_SRC &&
856d2ba247cSmichen smf_state != NSCD_SVC_STATE_FOREIGN_SRC &&
85718bdb8a7Smichen smf_state < SCF_STATE_ONLINE)))) {
858cb5caa98Sdjl
859cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE,
860cb5caa98Sdjl NSCD_LOG_LEVEL_DEBUG)
861cb5caa98Sdjl (me, "unable to look up source %s: be = %p, "
862cb5caa98Sdjl "smf state = %d, funcp = %p\n",
863cb5caa98Sdjl NSCD_NSW_SRC_NAME(srci), be, smf_state, funcp);
864cb5caa98Sdjl
865cb5caa98Sdjl goto next_src;
866cb5caa98Sdjl }
867cb5caa98Sdjl
868cb5caa98Sdjl do {
869cb5caa98Sdjl /*
870cb5caa98Sdjl * we can only retry max_retry times,
871cb5caa98Sdjl * otherwise threads may get stuck in this
872cb5caa98Sdjl * do-while loop forever
873cb5caa98Sdjl */
874cb5caa98Sdjl if (n_loop > max_retry) {
875cb5caa98Sdjl if (swret != NULL)
876cb5caa98Sdjl res = NSS_TRYLOCAL;
877cb5caa98Sdjl goto free_nsw_state;
878cb5caa98Sdjl }
879cb5caa98Sdjl
880cb5caa98Sdjl /*
881cb5caa98Sdjl * set up to prevent loopback
882cb5caa98Sdjl */
883cb5caa98Sdjl if (check_loopback && k == NULL) {
884cb5caa98Sdjl key.srci = srci;
885cb5caa98Sdjl key.dbi = dbi;
886cb5caa98Sdjl key.fnum = search_fnum;
887cb5caa98Sdjl key.lb_flagp = &check_loopback;
888cb5caa98Sdjl (void) set_loopback_key(&key);
889cb5caa98Sdjl k = &key;
890cb5caa98Sdjl }
891cb5caa98Sdjl
892cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE,
893cb5caa98Sdjl NSCD_LOG_LEVEL_DEBUG)
894cb5caa98Sdjl (me, "looking up source = %s, loop# = %d \n",
895cb5caa98Sdjl NSCD_NSW_SRC_NAME(srci), n_loop);
896cb5caa98Sdjl
897cb5caa98Sdjl /*
898cb5caa98Sdjl * search the backend, if hosts lookups,
899cb5caa98Sdjl * try to get the hosts data with ttl first
900cb5caa98Sdjl */
901cb5caa98Sdjl if (params.dnsi >= 0) {
902cb5caa98Sdjl res = search_dns_withttl(swret,
903bf1e3beeSmichen NSCD_NSW_SRC_NAME(srci), params.dnsi);
904cb5caa98Sdjl /*
905cb5caa98Sdjl * if not able to get ttl, fall back
906cb5caa98Sdjl * to the regular backend call
907cb5caa98Sdjl */
908cb5caa98Sdjl if (res == NSS_ERROR)
909cb5caa98Sdjl res = (*funcp)(be, search_args);
910cb5caa98Sdjl else {
911cb5caa98Sdjl /*
912cb5caa98Sdjl * status/result are in the
913cb5caa98Sdjl * packed buffer, not
914cb5caa98Sdjl * search_args
915cb5caa98Sdjl */
916cb5caa98Sdjl swret->noarg = 1;
917cb5caa98Sdjl }
918cb5caa98Sdjl } else
919cb5caa98Sdjl res = (*funcp)(be, search_args);
920cb5caa98Sdjl if (swret != NULL)
921cb5caa98Sdjl swret->errnum = errno;
922cb5caa98Sdjl
923cb5caa98Sdjl /*
924cb5caa98Sdjl * backend is not up, check and update the
925cb5caa98Sdjl * smf state table
926cb5caa98Sdjl */
927cb5caa98Sdjl if (res == NSS_UNAVAIL)
928cb5caa98Sdjl (void) _nscd_get_smf_state(srci, dbi, 1);
929cb5caa98Sdjl
930cb5caa98Sdjl /*
931cb5caa98Sdjl * may need to fall back to use the main nscd
932cb5caa98Sdjl * if per-user lookup
933cb5caa98Sdjl */
934cb5caa98Sdjl if (_whoami == NSCD_CHILD && swret != NULL)
935cb5caa98Sdjl swret->fallback = set_fallback_flag(
936cb5caa98Sdjl NSCD_NSW_SRC_NAME(srci), res);
937cb5caa98Sdjl
938cb5caa98Sdjl _NSCD_LOG_IF(NSCD_LOG_SWITCH_ENGINE,
939cb5caa98Sdjl NSCD_LOG_LEVEL_DEBUG) {
940cb5caa98Sdjl
941cb5caa98Sdjl /*
942cb5caa98Sdjl * set up to trace the result/status
943cb5caa98Sdjl * of the dns/ttl lookup
944cb5caa98Sdjl */
945cb5caa98Sdjl if (swret != NULL && swret->noarg == 1) {
946cb5caa98Sdjl nss_pheader_t *phdr;
947cb5caa98Sdjl struct nss_XbyY_args *arg;
948cb5caa98Sdjl arg = (struct nss_XbyY_args *)
949cb5caa98Sdjl search_args;
950cb5caa98Sdjl phdr = (nss_pheader_t *)swret->pbuf;
951cb5caa98Sdjl arg->buf.buffer = (char *)phdr +
952cb5caa98Sdjl phdr->data_off;
953cb5caa98Sdjl arg->returnlen = phdr->data_len;
954cb5caa98Sdjl if (phdr->p_errno == ERANGE)
955cb5caa98Sdjl arg->erange = 1;
956cb5caa98Sdjl arg->h_errno = phdr->p_herrno;
957cb5caa98Sdjl }
958cb5caa98Sdjl
959cb5caa98Sdjl trace_result(dbi, srci, search_fnum, res,
960cb5caa98Sdjl (nss_XbyY_args_t *)search_args);
961cb5caa98Sdjl }
962cb5caa98Sdjl
963cb5caa98Sdjl n_loop++;
964cb5caa98Sdjl } while (retry_test(res, n_loop, lkp));
965cb5caa98Sdjl
966cb5caa98Sdjl next_src:
967cb5caa98Sdjl
968cb5caa98Sdjl status_vec |= (1 << res);
969cb5caa98Sdjl
970cb5caa98Sdjl if (__NSW_ACTION_V1(lkp, res) == __NSW_RETURN) {
971cb5caa98Sdjl break;
972cb5caa98Sdjl }
973cb5caa98Sdjl }
974cb5caa98Sdjl
975cb5caa98Sdjl free_nsw_state:
976cb5caa98Sdjl
977cb5caa98Sdjl if (state_thr == 1)
978cb5caa98Sdjl _nscd_put_nsw_state_thread(s);
979cb5caa98Sdjl else
980cb5caa98Sdjl _nscd_put_nsw_state(s);
981cb5caa98Sdjl if (check_loopback && k != NULL)
982cb5caa98Sdjl clear_loopback_key(k);
983cb5caa98Sdjl
984cb5caa98Sdjl if (res != NSS_SUCCESS)
985cb5caa98Sdjl goto error_exit;
986cb5caa98Sdjl
987cb5caa98Sdjl NSCD_SW_STATS_G.lookup_request_succeeded_g++;
988cb5caa98Sdjl NSCD_SW_STATS(dbi).lookup_request_succeeded++;
989cb5caa98Sdjl NSCD_SW_STATS_G.lookup_request_in_progress_g--;
990cb5caa98Sdjl NSCD_SW_STATS(dbi).lookup_request_in_progress--;
991cb5caa98Sdjl
992cb5caa98Sdjl return (NSS_SUCCESS);
993cb5caa98Sdjl
994cb5caa98Sdjl error_exit:
995cb5caa98Sdjl
996cb5caa98Sdjl NSCD_SW_STATS_G.lookup_request_failed_g++;
997cb5caa98Sdjl NSCD_SW_STATS_G.lookup_request_in_progress_g--;
998cb5caa98Sdjl NSCD_SW_STATS(dbi).lookup_request_failed++;
999cb5caa98Sdjl NSCD_SW_STATS(dbi).lookup_request_in_progress--;
1000cb5caa98Sdjl
1001cb5caa98Sdjl return (res);
1002cb5caa98Sdjl }
1003cb5caa98Sdjl
1004cb5caa98Sdjl
1005cb5caa98Sdjl /* ===> get/set/endent */
1006cb5caa98Sdjl
1007cb5caa98Sdjl static void nss_setent_u(nss_db_root_t *,
1008cb5caa98Sdjl nss_db_initf_t,
1009cb5caa98Sdjl nss_getent_t *);
1010cb5caa98Sdjl static nss_status_t nss_getent_u(nss_db_root_t *,
1011cb5caa98Sdjl nss_db_initf_t,
1012cb5caa98Sdjl nss_getent_t *,
1013cb5caa98Sdjl void *);
1014cb5caa98Sdjl static void nss_endent_u(nss_db_root_t *,
1015cb5caa98Sdjl nss_db_initf_t,
1016cb5caa98Sdjl nss_getent_t *);
1017cb5caa98Sdjl
1018cb5caa98Sdjl void
nss_setent(nss_db_root_t * rootp,nss_db_initf_t initf,nss_getent_t * contextpp)1019cb5caa98Sdjl nss_setent(nss_db_root_t *rootp, nss_db_initf_t initf,
1020cb5caa98Sdjl nss_getent_t *contextpp)
1021cb5caa98Sdjl {
1022cb5caa98Sdjl if (contextpp == 0)
1023cb5caa98Sdjl return;
1024cb5caa98Sdjl nss_setent_u(rootp, initf, contextpp);
1025cb5caa98Sdjl }
1026cb5caa98Sdjl
1027cb5caa98Sdjl nss_status_t
nss_getent(nss_db_root_t * rootp,nss_db_initf_t initf,nss_getent_t * contextpp,void * args)1028cb5caa98Sdjl nss_getent(nss_db_root_t *rootp, nss_db_initf_t initf, nss_getent_t *contextpp,
1029cb5caa98Sdjl void *args)
1030cb5caa98Sdjl {
1031cb5caa98Sdjl nss_status_t status;
1032cb5caa98Sdjl
1033cb5caa98Sdjl if (contextpp == 0) {
1034cb5caa98Sdjl return (NSS_UNAVAIL);
1035cb5caa98Sdjl }
1036cb5caa98Sdjl status = nss_getent_u(rootp, initf, contextpp, args);
1037cb5caa98Sdjl return (status);
1038cb5caa98Sdjl }
1039cb5caa98Sdjl
1040cb5caa98Sdjl void
nss_endent(nss_db_root_t * rootp,nss_db_initf_t initf,nss_getent_t * contextpp)1041cb5caa98Sdjl nss_endent(nss_db_root_t *rootp, nss_db_initf_t initf,
1042cb5caa98Sdjl nss_getent_t *contextpp)
1043cb5caa98Sdjl {
1044cb5caa98Sdjl if (contextpp == 0)
1045cb5caa98Sdjl return;
1046cb5caa98Sdjl nss_endent_u(rootp, initf, contextpp);
1047cb5caa98Sdjl }
1048cb5caa98Sdjl
1049cb5caa98Sdjl /*ARGSUSED*/
1050cb5caa98Sdjl static void
end_iter_u(nss_db_root_t * rootp,struct nss_getent_context * contextp)1051cb5caa98Sdjl end_iter_u(nss_db_root_t *rootp, struct nss_getent_context *contextp)
1052cb5caa98Sdjl {
1053cb5caa98Sdjl nscd_getent_context_t *ctx;
1054cb5caa98Sdjl nscd_nsw_state_t *s;
1055cb5caa98Sdjl nss_backend_t *be;
1056cb5caa98Sdjl int n_src;
1057cb5caa98Sdjl
1058cb5caa98Sdjl ctx = (nscd_getent_context_t *)contextp;
1059cb5caa98Sdjl s = ctx->nsw_state;
1060cb5caa98Sdjl n_src = ctx->n_src;
1061cb5caa98Sdjl be = ctx->be;
1062cb5caa98Sdjl
1063cb5caa98Sdjl if (s != 0) {
1064cb5caa98Sdjl if (n_src < s->max_src && be != 0) {
1065cb5caa98Sdjl (void) NSS_INVOKE_DBOP(be, NSS_DBOP_ENDENT, 0);
1066cb5caa98Sdjl ctx->be = 0; /* Should be unnecessary, but hey */
1067cb5caa98Sdjl }
1068cb5caa98Sdjl }
1069cb5caa98Sdjl ctx->n_src = 0;
1070cb5caa98Sdjl }
1071cb5caa98Sdjl
1072cb5caa98Sdjl static void
nss_setent_u(nss_db_root_t * rootp,nss_db_initf_t initf,nss_getent_t * contextpp)1073cb5caa98Sdjl nss_setent_u(nss_db_root_t *rootp, nss_db_initf_t initf,
1074cb5caa98Sdjl nss_getent_t *contextpp)
1075cb5caa98Sdjl {
1076cb5caa98Sdjl char *me = "nss_setent_u";
1077cb5caa98Sdjl nscd_nsw_state_t *s;
1078cb5caa98Sdjl nscd_getent_context_t *contextp;
1079cb5caa98Sdjl nscd_nsw_params_t params;
1080cb5caa98Sdjl nss_db_root_t root;
1081cb5caa98Sdjl nss_backend_t *be;
1082cb5caa98Sdjl int n_src, i;
1083cb5caa98Sdjl nscd_sw_return_t *swret = NULL;
1084cb5caa98Sdjl
1085cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG)
1086cb5caa98Sdjl (me, "rootp = %p, initf = %p, contextpp = %p \n",
1087cb5caa98Sdjl rootp, initf, contextpp);
1088cb5caa98Sdjl
1089bee2e9ddSmichen /*
1090bee2e9ddSmichen * Get the nsw db index via the initf function. If unsupported
1091bee2e9ddSmichen * database, no need to continue
1092bee2e9ddSmichen */
1093bee2e9ddSmichen if (getparams(-1, initf, ¶ms) == NSCD_CFG_UNSUPPORTED_SWITCH_DB)
1094bee2e9ddSmichen return;
1095cb5caa98Sdjl
1096cb5caa98Sdjl /* get address of the switch engine return data area */
1097cb5caa98Sdjl if (initf == nscd_initf)
1098cb5caa98Sdjl swret = (nscd_sw_return_t *)params.p.private;
1099cb5caa98Sdjl
1100cb5caa98Sdjl /* if no privilege to look up, return */
1101cb5caa98Sdjl if (params.privdb == 1 && swret != NULL &&
1102b57459abSJulian Pullen _nscd_check_client_priv(NSCD_READ_PRIV) != 0) {
1103cb5caa98Sdjl
1104cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG)
1105cb5caa98Sdjl (me, "no privilege \n");
1106cb5caa98Sdjl return;
1107cb5caa98Sdjl }
1108cb5caa98Sdjl
1109cb5caa98Sdjl if ((contextp = (nscd_getent_context_t *)contextpp->ctx) == 0) {
1110cb5caa98Sdjl if ((_nscd_get_getent_ctx(contextpp, ¶ms)) !=
1111cb5caa98Sdjl NSCD_SUCCESS) {
1112cb5caa98Sdjl return;
1113cb5caa98Sdjl }
1114cb5caa98Sdjl contextp = (nscd_getent_context_t *)contextpp->ctx;
1115cb5caa98Sdjl }
1116cb5caa98Sdjl s = contextp->nsw_state;
1117cb5caa98Sdjl
1118cb5caa98Sdjl if (s == 0) {
1119cb5caa98Sdjl if (_nscd_get_nsw_state(&root, ¶ms) !=
1120cb5caa98Sdjl NSCD_SUCCESS) {
1121cb5caa98Sdjl return;
1122cb5caa98Sdjl }
1123cb5caa98Sdjl s = (nscd_nsw_state_t *)root.s;
1124cb5caa98Sdjl contextp->nsw_state = s;
1125cb5caa98Sdjl
1126cb5caa98Sdjl } else {
1127cb5caa98Sdjl s = contextp->nsw_state;
1128cb5caa98Sdjl n_src = contextp->n_src;
1129cb5caa98Sdjl be = contextp->be;
1130cb5caa98Sdjl if (n_src == 0 && be != 0) {
1131cb5caa98Sdjl /*
1132cb5caa98Sdjl * Optimization: don't do endent, don't change
1133cb5caa98Sdjl * backends, just do the setent. Look Ma, no locks
1134cb5caa98Sdjl * (nor any context that needs updating).
1135cb5caa98Sdjl */
1136cb5caa98Sdjl (void) NSS_INVOKE_DBOP(be, NSS_DBOP_SETENT, 0);
1137cb5caa98Sdjl return;
1138cb5caa98Sdjl }
1139cb5caa98Sdjl if (n_src < s->max_src && be != 0) {
1140cb5caa98Sdjl (void) NSS_INVOKE_DBOP(be, NSS_DBOP_ENDENT, 0);
1141cb5caa98Sdjl contextp->be = 0; /* Play it safe */
1142cb5caa98Sdjl }
1143cb5caa98Sdjl }
1144cb5caa98Sdjl for (n_src = 0, be = 0; n_src < s->max_src &&
1145cb5caa98Sdjl (be = s->be[n_src]) == 0; n_src++) {
1146cb5caa98Sdjl ;
1147cb5caa98Sdjl }
1148cb5caa98Sdjl
1149cb5caa98Sdjl contextp->n_src = n_src;
1150cb5caa98Sdjl contextp->be = be;
1151cb5caa98Sdjl
1152cb5caa98Sdjl if (be == 0) {
1153cb5caa98Sdjl /* Things are broken enough that we can't do setent/getent */
1154cb5caa98Sdjl nss_endent_u(rootp, initf, contextpp);
1155cb5caa98Sdjl return;
1156cb5caa98Sdjl }
1157cb5caa98Sdjl
1158cb5caa98Sdjl /*
1159cb5caa98Sdjl * make sure all the backends are supported
1160cb5caa98Sdjl */
1161cb5caa98Sdjl for (i = 0; i < s->max_src; i++) {
1162cb5caa98Sdjl int st, srci;
1163cb5caa98Sdjl
1164d2ba247cSmichen if (s->be[i] == NULL)
1165d2ba247cSmichen continue;
1166d2ba247cSmichen
1167cb5caa98Sdjl srci = (*s->nsw_cfg_p)->src_idx[i];
1168cb5caa98Sdjl st = _nscd_get_smf_state(srci, params.dbi, 1);
1169d2ba247cSmichen if (st == NSCD_SVC_STATE_UNSUPPORTED_SRC ||
1170d2ba247cSmichen (st == NSCD_SVC_STATE_FOREIGN_SRC &&
11716392794bSMichen Chang s->be_version_p[i] == NULL && initf == nscd_initf) ||
1172d2ba247cSmichen st == NSCD_SVC_STATE_UNINITED ||
1173d2ba247cSmichen (params.privdb &&
11740dfdd7f3Smichen try_local2(params.dbi, srci) == 1)) {
1175cb5caa98Sdjl nss_endent_u(rootp, initf, contextpp);
1176cb5caa98Sdjl
1177cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE,
1178cb5caa98Sdjl NSCD_LOG_LEVEL_DEBUG)
1179cb5caa98Sdjl (me, "backend (%s) not available (state = %d)\n",
1180cb5caa98Sdjl NSCD_NSW_SRC_NAME(srci), st);
1181cb5caa98Sdjl
1182cb5caa98Sdjl return;
1183cb5caa98Sdjl }
1184cb5caa98Sdjl }
1185cb5caa98Sdjl
1186cb5caa98Sdjl (void) NSS_INVOKE_DBOP(be, NSS_DBOP_SETENT, 0);
1187cb5caa98Sdjl }
1188cb5caa98Sdjl
1189cb5caa98Sdjl nss_status_t
nss_getent_u(nss_db_root_t * rootp,nss_db_initf_t initf,nss_getent_t * contextpp,void * args)1190cb5caa98Sdjl nss_getent_u(nss_db_root_t *rootp, nss_db_initf_t initf,
1191cb5caa98Sdjl nss_getent_t *contextpp, void *args)
1192cb5caa98Sdjl {
1193cb5caa98Sdjl char *me = "nss_getent_u";
1194cb5caa98Sdjl nscd_nsw_state_t *s;
1195cb5caa98Sdjl nscd_getent_context_t *contextp;
1196cb5caa98Sdjl int n_src;
1197cb5caa98Sdjl nss_backend_t *be;
1198cb5caa98Sdjl
1199cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG)
1200cb5caa98Sdjl (me, "rootp = %p, initf = %p, contextpp = %p, args = %p\n",
1201cb5caa98Sdjl rootp, initf, contextpp, args);
1202cb5caa98Sdjl
1203cb5caa98Sdjl if ((contextp = (nscd_getent_context_t *)contextpp->ctx) == 0) {
1204cb5caa98Sdjl nss_setent_u(rootp, initf, contextpp);
1205cb5caa98Sdjl if ((contextp = (nscd_getent_context_t *)contextpp->ctx) == 0) {
1206cb5caa98Sdjl /* Give up */
1207cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE,
1208cb5caa98Sdjl NSCD_LOG_LEVEL_ERROR)
1209cb5caa98Sdjl (me, "not able to obtain getent context ... give up\n");
1210cb5caa98Sdjl
1211cb5caa98Sdjl return (NSS_UNAVAIL);
1212cb5caa98Sdjl }
1213cb5caa98Sdjl }
1214cb5caa98Sdjl
1215cb5caa98Sdjl s = contextp->nsw_state;
1216cb5caa98Sdjl n_src = contextp->n_src;
1217cb5caa98Sdjl be = contextp->be;
1218cb5caa98Sdjl
1219cb5caa98Sdjl if (s == 0) {
1220cb5caa98Sdjl /*
1221cb5caa98Sdjl * We've done an end_iter() and haven't done nss_setent()
1222cb5caa98Sdjl * or nss_endent() since; we should stick in this state
1223cb5caa98Sdjl * until the caller invokes one of those two routines.
1224cb5caa98Sdjl */
1225cb5caa98Sdjl return (NSS_SUCCESS);
1226cb5caa98Sdjl }
1227cb5caa98Sdjl
1228cb5caa98Sdjl while (n_src < s->max_src) {
1229cb5caa98Sdjl nss_status_t res;
1230cb5caa98Sdjl struct __nsw_lookup_v1 *lkp = NULL;
1231cb5caa98Sdjl int n;
1232cb5caa98Sdjl
1233cb5caa98Sdjl /* get the nsw config for the current source */
1234cb5caa98Sdjl lkp = s->config->lookups;
1235cb5caa98Sdjl for (n = 0; n < n_src; n++)
1236cb5caa98Sdjl lkp = lkp->next;
1237cb5caa98Sdjl
1238cb5caa98Sdjl if (be == 0) {
1239cb5caa98Sdjl /* If it's null it's a bug, but let's play safe */
1240cb5caa98Sdjl res = NSS_UNAVAIL;
1241cb5caa98Sdjl } else {
1242cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE,
1243cb5caa98Sdjl NSCD_LOG_LEVEL_DEBUG)
1244cb5caa98Sdjl (me, "database: %s, backend: %s, nsswitch config: %s\n",
1245cb5caa98Sdjl NSCD_NSW_DB_NAME(s->dbi),
1246cb5caa98Sdjl lkp->service_name,
1247cb5caa98Sdjl (*s->nsw_cfg_p)->nsw_cfg_str);
1248cb5caa98Sdjl
1249cb5caa98Sdjl res = NSS_INVOKE_DBOP(be, NSS_DBOP_GETENT, args);
1250cb5caa98Sdjl }
1251cb5caa98Sdjl
1252cb5caa98Sdjl if (__NSW_ACTION_V1(lkp, res) == __NSW_RETURN) {
1253cb5caa98Sdjl if (res != __NSW_SUCCESS) {
1254cb5caa98Sdjl end_iter_u(rootp,
1255cb5caa98Sdjl (struct nss_getent_context *)contextp);
1256cb5caa98Sdjl }
1257cb5caa98Sdjl return (res);
1258cb5caa98Sdjl }
1259cb5caa98Sdjl (void) NSS_INVOKE_DBOP(be, NSS_DBOP_ENDENT, 0);
1260cb5caa98Sdjl do {
1261cb5caa98Sdjl n_src++;
1262cb5caa98Sdjl } while (n_src < s->max_src &&
1263cb5caa98Sdjl (be = s->be[n_src]) == 0);
1264cb5caa98Sdjl if (be == 0) {
1265cb5caa98Sdjl /*
1266cb5caa98Sdjl * This is the case where we failed to get the backend
1267cb5caa98Sdjl * for the last source. We exhausted all sources.
1268cb5caa98Sdjl */
1269cb5caa98Sdjl nss_endent_u(rootp, initf, contextpp);
12702802e980Smichen return (NSS_NOTFOUND);
1271cb5caa98Sdjl }
1272cb5caa98Sdjl contextp->n_src = n_src;
1273cb5caa98Sdjl contextp->be = be;
1274cb5caa98Sdjl (void) NSS_INVOKE_DBOP(be, NSS_DBOP_SETENT, 0);
1275cb5caa98Sdjl }
1276cb5caa98Sdjl /* Got to the end of the sources without finding another entry */
1277cb5caa98Sdjl end_iter_u(rootp, (struct nss_getent_context *)contextp);
1278cb5caa98Sdjl return (NSS_SUCCESS);
1279cb5caa98Sdjl /* success is either a successful entry or end of the sources */
1280cb5caa98Sdjl }
1281cb5caa98Sdjl
1282cb5caa98Sdjl /*ARGSUSED*/
1283cb5caa98Sdjl void
nss_endent_u(nss_db_root_t * rootp,nss_db_initf_t initf,nss_getent_t * contextpp)1284cb5caa98Sdjl nss_endent_u(nss_db_root_t *rootp, nss_db_initf_t initf,
1285cb5caa98Sdjl nss_getent_t *contextpp)
1286cb5caa98Sdjl {
1287cb5caa98Sdjl char *me = "nss_endent_u";
1288cb5caa98Sdjl nscd_getent_context_t *contextp;
1289cb5caa98Sdjl
1290cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG)
1291cb5caa98Sdjl (me, "rootp = %p, initf = %p, contextpp = %p \n",
1292cb5caa98Sdjl rootp, initf, contextpp);
1293cb5caa98Sdjl
1294cb5caa98Sdjl if ((contextp = (nscd_getent_context_t *)contextpp->ctx) == 0) {
1295cb5caa98Sdjl /* nss_endent() on an unused context is a no-op */
1296cb5caa98Sdjl return;
1297cb5caa98Sdjl }
12986392794bSMichen Chang
12996392794bSMichen Chang if (_nscd_is_getent_ctx_in_use(contextp) == 0) {
1300cb5caa98Sdjl end_iter_u(rootp, (struct nss_getent_context *)contextp);
1301cb5caa98Sdjl _nscd_put_getent_ctx(contextp);
1302cb5caa98Sdjl contextpp->ctx = NULL;
1303cb5caa98Sdjl }
13046392794bSMichen Chang }
1305cb5caa98Sdjl
1306cb5caa98Sdjl /*
1307cb5caa98Sdjl * _nss_db_state_destr() and nss_delete() do nothing in nscd
1308cb5caa98Sdjl * but is needed to make the caller (below nscd) happy
1309cb5caa98Sdjl */
1310cb5caa98Sdjl /*ARGSUSED*/
1311cb5caa98Sdjl void
_nss_db_state_destr(struct nss_db_state * s)1312cb5caa98Sdjl _nss_db_state_destr(struct nss_db_state *s)
1313cb5caa98Sdjl {
1314cb5caa98Sdjl /* nsw state in nscd is always reused, so do nothing here */
1315cb5caa98Sdjl }
1316cb5caa98Sdjl
1317cb5caa98Sdjl /*ARGSUSED*/
1318cb5caa98Sdjl void
nss_delete(nss_db_root_t * rootp)1319cb5caa98Sdjl nss_delete(nss_db_root_t *rootp)
1320cb5caa98Sdjl {
1321cb5caa98Sdjl /*
1322cb5caa98Sdjl * the only resource kept tracked by the nss_db_root_t
1323cb5caa98Sdjl * is the nsw state which is always reused and no need
1324cb5caa98Sdjl * to be freed. So just return.
1325cb5caa98Sdjl */
1326cb5caa98Sdjl }
1327cb5caa98Sdjl
1328cb5caa98Sdjl /*
1329cb5caa98Sdjl * Start of nss_psearch/nss_psetent()/nss_pgetent()/nss_pendent()
1330cb5caa98Sdjl * buffers switch entry points
1331cb5caa98Sdjl */
1332cb5caa98Sdjl
1333cb5caa98Sdjl /*
1334cb5caa98Sdjl * nss_psearch opens a packed structure header, assembles a local
1335cb5caa98Sdjl * nss_XbyY_args_t structure and calls the local copy of nss_search.
1336cb5caa98Sdjl * The return data is assembled in "files native format" in the
1337cb5caa98Sdjl * return buffer location. Status if packed back up with the buffer
1338cb5caa98Sdjl * and the whole wad is returned to the cache or the client.
1339cb5caa98Sdjl */
1340cb5caa98Sdjl
1341cb5caa98Sdjl void
nss_psearch(void * buffer,size_t length)1342cb5caa98Sdjl nss_psearch(void *buffer, size_t length)
1343cb5caa98Sdjl {
1344cb5caa98Sdjl /* inputs */
1345cb5caa98Sdjl nss_db_initf_t initf;
1346cb5caa98Sdjl int dbop;
1347cb5caa98Sdjl int rc;
1348cb5caa98Sdjl nss_XbyY_args_t arg;
1349cb5caa98Sdjl nss_status_t status;
1350cb5caa98Sdjl nscd_sw_return_t swret = { 0 }, *swrp = &swret;
1351cb5caa98Sdjl nss_pheader_t *pbuf = (nss_pheader_t *)buffer;
1352cb5caa98Sdjl char *me = "nss_psearch";
1353cb5caa98Sdjl
1354cb5caa98Sdjl if (buffer == NULL || length == 0) {
13557d7551bcSMilan Jurik NSCD_SET_STATUS(pbuf, NSS_ERROR, EFAULT);
13567d7551bcSMilan Jurik return;
1357cb5caa98Sdjl }
1358cb5caa98Sdjl
1359cb5caa98Sdjl status = nss_packed_arg_init(buffer, length,
1360cb5caa98Sdjl NULL, &initf, &dbop, &arg);
1361cb5caa98Sdjl if (status != NSS_SUCCESS) {
13627d7551bcSMilan Jurik NSCD_SET_STATUS(pbuf, status, -1);
13637d7551bcSMilan Jurik return;
1364cb5caa98Sdjl }
1365cb5caa98Sdjl
1366cb5caa98Sdjl /*
1367cb5caa98Sdjl * pass the address of the return data area
1368cb5caa98Sdjl * for the switch engine to return its own data
1369cb5caa98Sdjl */
1370cb5caa98Sdjl (void) memcpy(&pbuf->nscdpriv, &swrp, sizeof (swrp));
1371cb5caa98Sdjl swret.pbuf = buffer;
1372cb5caa98Sdjl swret.pbufsiz = length;
13734b22b933Srs200217 swret.datalen = pbuf->data_len;
1374cb5caa98Sdjl
1375cb5caa98Sdjl /*
1376cb5caa98Sdjl * use the generic nscd_initf for all database lookups
1377cb5caa98Sdjl * (the TSD key is the pointer to the packed header)
1378cb5caa98Sdjl */
1379cb5caa98Sdjl rc = set_initf_key(pbuf);
1380cb5caa98Sdjl if (rc != 0) {
13817d7551bcSMilan Jurik NSCD_SET_STATUS(pbuf, NSS_UNAVAIL, EINVAL);
13827d7551bcSMilan Jurik return;
1383cb5caa98Sdjl }
1384cb5caa98Sdjl initf = nscd_initf;
1385cb5caa98Sdjl
1386cb5caa98Sdjl /* Perform local search and pack results into return buffer */
1387cb5caa98Sdjl /* nscd's search ignores db_root */
1388cb5caa98Sdjl status = nss_search(NULL, initf, dbop, &arg);
1389cb5caa98Sdjl
1390cb5caa98Sdjl /*
1391cb5caa98Sdjl * If status is NSS_NOTFOUND and ldap also returned
1392cb5caa98Sdjl * NSS_NOTFOUND, it is possible that the user does
1393cb5caa98Sdjl * not have a credential, so check and see if
1394cb5caa98Sdjl * needs to return NSS_ALTRETRY to let the main
1395cb5caa98Sdjl * nscd get a chance to process the lookup
1396cb5caa98Sdjl */
1397cb5caa98Sdjl if (swret.fallback == 1 && status == NSS_NOTFOUND) {
1398c70a8a3bSmichen OM_uint32 (*func)();
1399cb5caa98Sdjl OM_uint32 stat;
1400c70a8a3bSmichen nscd_rc_t rc;
1401cb5caa98Sdjl
1402c70a8a3bSmichen rc = get_gss_func((void **)&func);
1403c70a8a3bSmichen if (rc == NSCD_SUCCESS) {
1404c70a8a3bSmichen if (func(&stat, GSS_C_NO_CREDENTIAL,
1405cb5caa98Sdjl NULL, NULL, NULL, NULL) != GSS_S_COMPLETE) {
1406cb5caa98Sdjl
1407cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE,
1408cb5caa98Sdjl NSCD_LOG_LEVEL_DEBUG)
1409cb5caa98Sdjl (me, "NSS_ALTRETRY: fallback to main nscd needed\n");
1410cb5caa98Sdjl
1411cb5caa98Sdjl status = NSS_ALTRETRY;
1412cb5caa98Sdjl }
1413cb5caa98Sdjl }
1414c70a8a3bSmichen }
1415cb5caa98Sdjl
1416cb5caa98Sdjl NSCD_SET_STATUS(pbuf, status, -1);
1417cb5caa98Sdjl errno = swret.errnum;
1418cb5caa98Sdjl
1419cb5caa98Sdjl /*
1420d2ba247cSmichen * Move result/status from args to packed buffer only if
1421d2ba247cSmichen * arg was being used and rc from the switch engine is not
1422d2ba247cSmichen * NSS_TRYLOCAL.
1423cb5caa98Sdjl */
1424d2ba247cSmichen if (!swret.noarg && status != NSS_TRYLOCAL)
1425cb5caa98Sdjl nss_packed_set_status(buffer, length, status, &arg);
1426cb5caa98Sdjl
1427cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG)
1428cb5caa98Sdjl (me, "switch engine result: source is %s, status %d, "
1429cb5caa98Sdjl "herrno is %d, errno is %s\n",
1430cb5caa98Sdjl (swret.srci != -1) ? NSCD_NSW_SRC_NAME(swret.srci) : "<NOTSET>",
1431cb5caa98Sdjl pbuf->p_status, pbuf->p_herrno, strerror(pbuf->p_errno));
1432cb5caa98Sdjl
1433cb5caa98Sdjl /* clear the TSD key used by the generic initf */
1434cb5caa98Sdjl clear_initf_key();
1435cb5caa98Sdjl pbuf->nscdpriv = 0;
1436cb5caa98Sdjl }
1437cb5caa98Sdjl
1438cb5caa98Sdjl static void
nscd_map_contextp(void * buffer,nss_getent_t * contextp,nssuint_t ** cookie_num_p,nssuint_t ** seqnum_p,int setent)1439cb5caa98Sdjl nscd_map_contextp(void *buffer, nss_getent_t *contextp,
1440e37190e5Smichen nssuint_t **cookie_num_p, nssuint_t **seqnum_p, int setent)
1441cb5caa98Sdjl {
1442cb5caa98Sdjl nss_pheader_t *pbuf = (nss_pheader_t *)buffer;
1443cb5caa98Sdjl nssuint_t off;
1444cb5caa98Sdjl nscd_getent_context_t *ctx;
1445cb5caa98Sdjl char *me = "nscd_map_contextp";
1446e37190e5Smichen nscd_getent_p1_cookie_t *cookie;
1447cb5caa98Sdjl
1448cb5caa98Sdjl if (buffer == NULL) {
14497d7551bcSMilan Jurik NSCD_SET_STATUS(pbuf, NSS_ERROR, EFAULT);
14507d7551bcSMilan Jurik return;
1451cb5caa98Sdjl }
1452cb5caa98Sdjl
1453cb5caa98Sdjl off = pbuf->key_off;
1454e37190e5Smichen cookie = (nscd_getent_p1_cookie_t *)((void *)((char *)buffer + off));
1455cb5caa98Sdjl if (seqnum_p != NULL)
1456e37190e5Smichen *seqnum_p = &cookie->p1_seqnum;
1457cb5caa98Sdjl
1458cb5caa98Sdjl /*
1459e37190e5Smichen * if called by nss_psetent, and the passed in cookie number
1460e37190e5Smichen * is NSCD_NEW_COOKIE, then there is no cookie yet, return a
1461e37190e5Smichen * pointer pointing to where the cookie number will be stored.
1462e37190e5Smichen * Also because there is no cookie to validate, just return
1463e37190e5Smichen * success.
1464cb5caa98Sdjl *
1465e37190e5Smichen * On the other hand, if a cookie number is passed in, we need
1466e37190e5Smichen * to validate the cookie number before returning.
1467cb5caa98Sdjl */
1468e37190e5Smichen if (cookie_num_p != NULL)
1469e37190e5Smichen *cookie_num_p = &cookie->p1_cookie_num;
1470e37190e5Smichen if (setent == 1 && cookie->p1_cookie_num == NSCD_NEW_COOKIE) {
14717d7551bcSMilan Jurik NSCD_SET_STATUS_SUCCESS(pbuf);
14727d7551bcSMilan Jurik return;
1473e37190e5Smichen }
1474e37190e5Smichen
1475e37190e5Smichen /*
1476e37190e5Smichen * If the sequence number and start time match nscd's p0 cookie,
1477e37190e5Smichen * then either setent was done twice in a row or this is the
1478e37190e5Smichen * first getent after the setent, return success as well.
1479e37190e5Smichen */
1480e37190e5Smichen if (cookie->p1_seqnum == NSCD_P0_COOKIE_SEQNUM) {
1481e37190e5Smichen nscd_getent_p0_cookie_t *p0c =
1482e37190e5Smichen (nscd_getent_p0_cookie_t *)cookie;
14837d7551bcSMilan Jurik if (p0c->p0_time == _nscd_get_start_time()) {
14847d7551bcSMilan Jurik NSCD_SET_STATUS_SUCCESS(pbuf);
14857d7551bcSMilan Jurik return;
14867d7551bcSMilan Jurik }
1487cb5caa98Sdjl }
1488cb5caa98Sdjl
1489cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG)
1490e37190e5Smichen (me, "cookie # = %lld, sequence # = %lld\n",
1491e37190e5Smichen cookie->p1_cookie_num, cookie->p1_seqnum);
1492cb5caa98Sdjl
1493e37190e5Smichen ctx = _nscd_is_getent_ctx(cookie->p1_cookie_num);
1494cb5caa98Sdjl
1495cb5caa98Sdjl if (ctx == NULL) {
1496cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG)
149729836b19Smichen (me, "No matching context found (cookie number: %lld)\n",
149829836b19Smichen cookie->p1_cookie_num);
1499cb5caa98Sdjl
15007d7551bcSMilan Jurik NSCD_SET_STATUS(pbuf, NSS_ERROR, EFAULT);
15017d7551bcSMilan Jurik return;
1502cb5caa98Sdjl }
1503cb5caa98Sdjl
1504e37190e5Smichen /* if not called by nss_psetent, verify sequence number */
1505e37190e5Smichen if (setent != 1 && ctx->seq_num !=
1506e37190e5Smichen (nscd_seq_num_t)cookie->p1_seqnum) {
1507cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG)
1508e37190e5Smichen (me, "invalid sequence # (%lld)\n", cookie->p1_seqnum);
1509cb5caa98Sdjl
151029836b19Smichen _nscd_free_ctx_if_aborted(ctx);
15117d7551bcSMilan Jurik NSCD_SET_STATUS(pbuf, NSS_ERROR, EFAULT);
15127d7551bcSMilan Jurik return;
1513cb5caa98Sdjl }
1514cb5caa98Sdjl
1515cb5caa98Sdjl contextp->ctx = (struct nss_getent_context *)ctx;
1516cb5caa98Sdjl
15177d7551bcSMilan Jurik NSCD_SET_STATUS_SUCCESS(pbuf);
1518cb5caa98Sdjl }
1519cb5caa98Sdjl
1520cb5caa98Sdjl void
nss_psetent(void * buffer,size_t length,pid_t pid)1521cb5caa98Sdjl nss_psetent(void *buffer, size_t length, pid_t pid)
1522cb5caa98Sdjl {
1523cb5caa98Sdjl nss_getent_t context = { 0 };
1524cb5caa98Sdjl nss_getent_t *contextp = &context;
1525e37190e5Smichen nssuint_t *cookie_num_p;
1526e37190e5Smichen nssuint_t *seqnum_p;
1527cb5caa98Sdjl nss_pheader_t *pbuf = (nss_pheader_t *)buffer;
1528e37190e5Smichen nscd_getent_p0_cookie_t *p0c;
1529cb5caa98Sdjl char *me = "nss_psetent";
1530cb5caa98Sdjl
1531cb5caa98Sdjl if (buffer == NULL || length == 0) {
15327d7551bcSMilan Jurik NSCD_SET_STATUS(pbuf, NSS_ERROR, EFAULT);
15337d7551bcSMilan Jurik return;
1534cb5caa98Sdjl }
1535cb5caa98Sdjl
1536cb5caa98Sdjl /*
1537cb5caa98Sdjl * If this is a per-user nscd, and the user does not have
1538cb5caa98Sdjl * the necessary credential, return NSS_TRYLOCAL, so the
1539cb5caa98Sdjl * setent/getent can be done locally in the process of the
1540cb5caa98Sdjl * setent call
1541cb5caa98Sdjl */
1542cb5caa98Sdjl if (_whoami == NSCD_CHILD) {
1543c70a8a3bSmichen OM_uint32 (*func)();
1544cb5caa98Sdjl OM_uint32 stat;
1545c70a8a3bSmichen nscd_rc_t rc;
1546cb5caa98Sdjl
1547c70a8a3bSmichen rc = get_gss_func((void **)&func);
1548c70a8a3bSmichen if (rc == NSCD_SUCCESS) {
1549c70a8a3bSmichen if (func(&stat, GSS_C_NO_CREDENTIAL,
1550cb5caa98Sdjl NULL, NULL, NULL, NULL) != GSS_S_COMPLETE) {
1551cb5caa98Sdjl
1552cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE,
1553cb5caa98Sdjl NSCD_LOG_LEVEL_DEBUG)
1554cb5caa98Sdjl (me, "NSS_TRYLOCAL: fallback to caller process\n");
15557d7551bcSMilan Jurik NSCD_SET_STATUS(pbuf, NSS_TRYLOCAL, 0);
15567d7551bcSMilan Jurik return;
1557cb5caa98Sdjl }
1558cb5caa98Sdjl }
1559c70a8a3bSmichen }
1560cb5caa98Sdjl
1561e37190e5Smichen /* check cookie number */
1562e37190e5Smichen nscd_map_contextp(buffer, contextp, &cookie_num_p, &seqnum_p, 1);
1563cb5caa98Sdjl if (NSCD_STATUS_IS_NOT_OK(pbuf))
1564cb5caa98Sdjl return;
1565e37190e5Smichen
1566e37190e5Smichen /* set cookie number and sequence number */
1567e37190e5Smichen p0c = (nscd_getent_p0_cookie_t *)cookie_num_p;
1568e37190e5Smichen if (contextp->ctx == NULL) {
1569e37190e5Smichen /*
1570e37190e5Smichen * first setent (no existing getent context),
1571e37190e5Smichen * return a p0 cookie
1572e37190e5Smichen */
1573e37190e5Smichen _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG)
1574e37190e5Smichen (me, "first setent, no getent context yet\n");
1575e37190e5Smichen } else {
1576e37190e5Smichen /*
1577e37190e5Smichen * doing setent on an existing getent context,
1578e37190e5Smichen * release resources allocated and return a
1579e37190e5Smichen * p0 cookie
1580e37190e5Smichen */
1581e37190e5Smichen _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG)
1582e37190e5Smichen (me, "setent resetting sequence number = %lld\n", *seqnum_p);
1583e37190e5Smichen
15846392794bSMichen Chang if (_nscd_is_getent_ctx_in_use((nscd_getent_context_t *)
15856392794bSMichen Chang contextp->ctx) == 0) {
15866392794bSMichen Chang /*
15876392794bSMichen Chang * context not in use, release the backend and
15886392794bSMichen Chang * return the context to the pool
15896392794bSMichen Chang */
15906392794bSMichen Chang end_iter_u(NULL, contextp->ctx);
15916392794bSMichen Chang _nscd_put_getent_ctx(
15926392794bSMichen Chang (nscd_getent_context_t *)contextp->ctx);
1593e37190e5Smichen contextp->ctx = NULL;
1594e37190e5Smichen }
15956392794bSMichen Chang }
1596e37190e5Smichen
1597e37190e5Smichen p0c->p0_pid = pid;
1598e37190e5Smichen p0c->p0_time = _nscd_get_start_time();
1599e37190e5Smichen p0c->p0_seqnum = NSCD_P0_COOKIE_SEQNUM;
1600e37190e5Smichen _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG)
1601e37190e5Smichen (me, "returning a p0 cookie: pid = %ld, time = %ld, seq #= %llx\n",
1602e37190e5Smichen p0c->p0_pid, p0c->p0_time, p0c->p0_seqnum);
1603e37190e5Smichen
16047d7551bcSMilan Jurik NSCD_SET_STATUS(pbuf, NSS_SUCCESS, 0);
1605e37190e5Smichen }
1606e37190e5Smichen
1607e37190e5Smichen static void
delayed_setent(nss_pheader_t * pbuf,nss_db_initf_t initf,nss_getent_t * contextp,nssuint_t * cookie_num_p,nssuint_t * seqnum_p,pid_t pid)1608e37190e5Smichen delayed_setent(nss_pheader_t *pbuf, nss_db_initf_t initf,
1609e37190e5Smichen nss_getent_t *contextp, nssuint_t *cookie_num_p,
1610e37190e5Smichen nssuint_t *seqnum_p, pid_t pid)
1611e37190e5Smichen {
1612e37190e5Smichen nscd_getent_context_t *ctx;
1613e37190e5Smichen nscd_sw_return_t swret = { 0 }, *swrp = &swret;
1614e37190e5Smichen char *me = "delayed_setent";
1615e37190e5Smichen
1616e37190e5Smichen /*
1617e37190e5Smichen * check credential
1618e37190e5Smichen */
1619e37190e5Smichen _nscd_APP_check_cred(pbuf, &pid, "NSCD_DELAYED_SETENT",
1620e37190e5Smichen NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_ERROR);
1621e37190e5Smichen if (NSCD_STATUS_IS_NOT_OK(pbuf)) {
1622e37190e5Smichen _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG)
1623e37190e5Smichen (me, "invalid credential\n");
1624e37190e5Smichen return;
1625e37190e5Smichen }
1626e37190e5Smichen
1627cb5caa98Sdjl /*
1628cb5caa98Sdjl * pass the packed header buffer pointer to nss_setent
1629cb5caa98Sdjl */
1630cb5caa98Sdjl (void) memcpy(&pbuf->nscdpriv, &swrp, sizeof (swrp));
1631e37190e5Smichen swret.pbuf = pbuf;
1632cb5caa98Sdjl
1633cb5caa98Sdjl /* Perform local setent and set context */
1634cb5caa98Sdjl nss_setent(NULL, initf, contextp);
1635cb5caa98Sdjl
1636e37190e5Smichen /* insert cookie info into packed buffer header */
1637cb5caa98Sdjl ctx = (nscd_getent_context_t *)contextp->ctx;
1638cb5caa98Sdjl if (ctx != NULL) {
1639e37190e5Smichen *cookie_num_p = ctx->cookie_num;
1640e37190e5Smichen *seqnum_p = ctx->seq_num;
1641cb5caa98Sdjl ctx->pid = pid;
1642cb5caa98Sdjl } else {
1643cb5caa98Sdjl /*
1644cb5caa98Sdjl * not able to allocate a getent context, the
1645cb5caa98Sdjl * client should try the enumeration locally
1646cb5caa98Sdjl */
1647e37190e5Smichen *cookie_num_p = NSCD_LOCAL_COOKIE;
1648e37190e5Smichen *seqnum_p = 0;
1649cb5caa98Sdjl
1650cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG)
1651e37190e5Smichen (me, "NSS_TRYLOCAL: cookie # = %lld, sequence # = %lld\n",
1652e37190e5Smichen *cookie_num_p, *seqnum_p);
16537d7551bcSMilan Jurik NSCD_SET_STATUS(pbuf, NSS_TRYLOCAL, 0);
16547d7551bcSMilan Jurik return;
1655cb5caa98Sdjl }
1656e37190e5Smichen
1657e37190e5Smichen _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG)
1658e37190e5Smichen (me, "NSS_SUCCESS: cookie # = %lld, sequence # = %lld\n",
1659e37190e5Smichen ctx->cookie_num, ctx->seq_num);
1660e37190e5Smichen
16617d7551bcSMilan Jurik NSCD_SET_STATUS(pbuf, NSS_SUCCESS, 0);
1662cb5caa98Sdjl }
1663cb5caa98Sdjl
1664cb5caa98Sdjl void
nss_pgetent(void * buffer,size_t length)1665cb5caa98Sdjl nss_pgetent(void *buffer, size_t length)
1666cb5caa98Sdjl {
1667cb5caa98Sdjl /* inputs */
1668cb5caa98Sdjl nss_db_initf_t initf;
1669e37190e5Smichen nss_getent_t context = { 0 };
1670cb5caa98Sdjl nss_getent_t *contextp = &context;
1671e37190e5Smichen nss_XbyY_args_t arg = { 0};
1672cb5caa98Sdjl nss_status_t status;
1673e37190e5Smichen nssuint_t *cookie_num_p;
1674e37190e5Smichen nssuint_t *seqnum_p;
1675cb5caa98Sdjl nscd_getent_context_t *ctx;
1676cb5caa98Sdjl int rc;
1677cb5caa98Sdjl nss_pheader_t *pbuf = (nss_pheader_t *)buffer;
1678cb5caa98Sdjl char *me = "nss_pgetent";
1679cb5caa98Sdjl
1680cb5caa98Sdjl if (buffer == NULL || length == 0) {
16817d7551bcSMilan Jurik NSCD_SET_STATUS(pbuf, NSS_ERROR, EFAULT);
16827d7551bcSMilan Jurik return;
1683cb5caa98Sdjl }
1684cb5caa98Sdjl
1685e37190e5Smichen /* verify the cookie passed in */
1686e37190e5Smichen nscd_map_contextp(buffer, contextp, &cookie_num_p, &seqnum_p, 0);
1687e37190e5Smichen if (NSCD_STATUS_IS_NOT_OK(pbuf))
1688e37190e5Smichen return;
16896392794bSMichen Chang
1690cb5caa98Sdjl /*
1691cb5caa98Sdjl * use the generic nscd_initf for all the getent requests
1692cb5caa98Sdjl * (the TSD key is the pointer to the packed header)
1693cb5caa98Sdjl */
1694cb5caa98Sdjl rc = set_initf_key(pbuf);
1695cb5caa98Sdjl if (rc != 0) {
16967d7551bcSMilan Jurik NSCD_SET_STATUS(pbuf, NSS_UNAVAIL, EINVAL);
16977d7551bcSMilan Jurik return;
1698cb5caa98Sdjl }
1699cb5caa98Sdjl initf = nscd_initf;
1700cb5caa98Sdjl
1701e37190e5Smichen /* if no context yet, get one */
1702e37190e5Smichen if (contextp->ctx == NULL) {
1703e37190e5Smichen nscd_getent_p0_cookie_t *p0c =
1704e37190e5Smichen (nscd_getent_p0_cookie_t *)cookie_num_p;
1705cb5caa98Sdjl
1706e37190e5Smichen delayed_setent(pbuf, initf, contextp, cookie_num_p,
1707e37190e5Smichen seqnum_p, p0c->p0_pid);
1708e37190e5Smichen if (NSCD_STATUS_IS_NOT_OK(pbuf)) {
1709e37190e5Smichen clear_initf_key();
1710cb5caa98Sdjl return;
1711e37190e5Smichen }
1712e37190e5Smichen }
1713e37190e5Smichen
1714e37190e5Smichen status = nss_packed_context_init(buffer, length,
1715e37190e5Smichen NULL, &initf, &contextp, &arg);
1716e37190e5Smichen if (status != NSS_SUCCESS) {
171729836b19Smichen clear_initf_key();
171829836b19Smichen _nscd_free_ctx_if_aborted(
171929836b19Smichen (nscd_getent_context_t *)contextp->ctx);
17207d7551bcSMilan Jurik NSCD_SET_STATUS(pbuf, status, -1);
17217d7551bcSMilan Jurik return;
1722e37190e5Smichen }
1723cb5caa98Sdjl
1724cb5caa98Sdjl /* Perform local search and pack results into return buffer */
1725cb5caa98Sdjl status = nss_getent(NULL, initf, contextp, &arg);
1726cb5caa98Sdjl NSCD_SET_STATUS(pbuf, status, -1);
1727cb5caa98Sdjl nss_packed_set_status(buffer, length, status, &arg);
1728cb5caa98Sdjl
1729cb5caa98Sdjl /* increment sequence number in the buffer and nscd context */
1730cb5caa98Sdjl if (status == NSS_SUCCESS) {
1731cb5caa98Sdjl ctx = (nscd_getent_context_t *)contextp->ctx;
1732cb5caa98Sdjl ctx->seq_num++;
1733e37190e5Smichen *seqnum_p = ctx->seq_num;
1734e37190e5Smichen *cookie_num_p = ctx->cookie_num;
1735cb5caa98Sdjl
1736cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG)
1737e37190e5Smichen (me, "getent OK, new sequence # = %lld, len = %lld,"
1738e37190e5Smichen " data = >>%s<<\n", *seqnum_p,
1739cb5caa98Sdjl pbuf->data_len, (char *)buffer + pbuf->data_off);
174029836b19Smichen
174129836b19Smichen _nscd_free_ctx_if_aborted(ctx);
1742cb5caa98Sdjl } else {
1743124771bbSmichen /* release the resources used */
1744cb5caa98Sdjl ctx = (nscd_getent_context_t *)contextp->ctx;
17456392794bSMichen Chang if (ctx != NULL && _nscd_is_getent_ctx_in_use(ctx) == 0) {
1746124771bbSmichen _nscd_put_getent_ctx(ctx);
1747124771bbSmichen contextp->ctx = NULL;
1748124771bbSmichen }
1749cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG)
1750e37190e5Smichen (me, "getent failed, status = %d, sequence # = %lld\n",
1751e37190e5Smichen status, *seqnum_p);
1752cb5caa98Sdjl }
1753cb5caa98Sdjl
1754cb5caa98Sdjl /* clear the TSD key used by the generic initf */
1755cb5caa98Sdjl clear_initf_key();
1756cb5caa98Sdjl }
1757cb5caa98Sdjl
1758cb5caa98Sdjl void
nss_pendent(void * buffer,size_t length)1759cb5caa98Sdjl nss_pendent(void *buffer, size_t length)
1760cb5caa98Sdjl {
1761e37190e5Smichen nss_getent_t context = { 0 };
1762cb5caa98Sdjl nss_getent_t *contextp = &context;
1763e37190e5Smichen nssuint_t *seqnum_p;
1764e37190e5Smichen nssuint_t *cookie_num_p;
1765cb5caa98Sdjl nss_pheader_t *pbuf = (nss_pheader_t *)buffer;
1766cb5caa98Sdjl char *me = "nss_pendent";
1767cb5caa98Sdjl
1768cb5caa98Sdjl if (buffer == NULL || length == 0) {
17697d7551bcSMilan Jurik NSCD_SET_STATUS(pbuf, NSS_ERROR, EFAULT);
17707d7551bcSMilan Jurik return;
1771cb5caa98Sdjl }
1772cb5caa98Sdjl
1773cb5caa98Sdjl /* map the contextp from the cookie information */
1774e37190e5Smichen nscd_map_contextp(buffer, contextp, &cookie_num_p, &seqnum_p, 0);
1775cb5caa98Sdjl if (NSCD_STATUS_IS_NOT_OK(pbuf))
1776cb5caa98Sdjl return;
1777cb5caa98Sdjl
1778e37190e5Smichen if (contextp->ctx == NULL)
1779e37190e5Smichen return;
1780e37190e5Smichen
1781cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG)
1782e37190e5Smichen (me, "endent, cookie = %lld, sequence # = %lld\n",
1783e37190e5Smichen *cookie_num_p, *seqnum_p);
1784cb5caa98Sdjl
1785cb5caa98Sdjl /* Perform local endent and reset context */
1786cb5caa98Sdjl nss_endent(NULL, NULL, contextp);
17876392794bSMichen Chang
17887d7551bcSMilan Jurik NSCD_SET_STATUS(pbuf, NSS_SUCCESS, 0);
1789cb5caa98Sdjl }
1790cb5caa98Sdjl
1791cb5caa98Sdjl /*ARGSUSED*/
1792cb5caa98Sdjl void
nss_pdelete(void * buffer,size_t length)1793cb5caa98Sdjl nss_pdelete(void *buffer, size_t length)
1794cb5caa98Sdjl {
1795cb5caa98Sdjl nss_pheader_t *pbuf = (nss_pheader_t *)buffer;
1796cb5caa98Sdjl
1797cb5caa98Sdjl /* unnecessary, kept for completeness */
17987d7551bcSMilan Jurik NSCD_SET_STATUS_SUCCESS(pbuf);
1799cb5caa98Sdjl }
1800