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