Unleashed v1.4
[unleashed.git] / usr / src / cmd / nscd / nscd_selfcred.c
blob5583ecab1b32dc5412cacf33331f3cc29120dd22
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
23 * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright 2012 Milan Jurik. All rights reserved.
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <synch.h>
30 #include <thread.h>
31 #include <string.h>
32 #include <errno.h>
33 #include <dlfcn.h>
34 #include <door.h>
35 #include <libscf.h>
36 #include <ucred.h>
37 #include <sys/varargs.h>
38 #include <signal.h>
39 #include <unistd.h>
40 #include <sys/types.h>
41 #include <dirent.h>
42 #include <sys/proc.h>
43 #include <procfs.h>
44 #include <sys/stat.h>
45 #include <fcntl.h>
46 #include <libscf.h>
47 #include "nscd_door.h"
48 #include "nscd_config.h"
49 #include "nscd_log.h"
50 #include "nscd_frontend.h"
51 #include "nscd_selfcred.h"
52 #include "nscd_admin.h"
53 #include "nscd_common.h"
54 #include "ns_sldap.h"
56 extern int _logfd;
57 static char *execpath;
58 static char **execargv;
59 static char *selfcred_dbs = NULL;
61 static void *get_smf_prop(const char *var, char type, void *def_val);
63 /* current self-cred configuration data being used */
64 static nscd_cfg_global_selfcred_t nscd_selfcred_cfg_g;
66 #define _NSCD_PUN_BLOCK 1024
67 static uint8_t pu_nscd_enabled;
68 static int max_pu_nscd = _NSCD_PUN_BLOCK;
69 static int pu_nscd_ttl;
71 static nscd_rc_t setup_ldap_backend();
72 static nscd_rc_t init_user_proc_monitor();
75 * clild state
77 typedef enum {
78 CHILD_STATE_NONE = 0,
79 CHILD_STATE_UIDKNOWN,
80 CHILD_STATE_FORKSENT,
81 CHILD_STATE_PIDKNOWN
82 } child_state_t;
85 typedef struct _child {
86 int child_slot;
87 int child_door;
88 pid_t child_pid;
89 uid_t child_uid;
90 gid_t child_gid;
91 child_state_t child_state;
92 int next_open;
93 mutex_t *mutex;
94 cond_t *cond;
95 } child_t;
97 static child_t **child = NULL;
98 static mutex_t child_lock = DEFAULTMUTEX;
99 static int open_head;
100 static int open_tail;
101 static int used_slot;
103 /* nscd door id */
104 extern int _doorfd;
105 static pid_t main_uid = 0;
107 /* nscd id: main, forker, or child */
108 extern int _whoami;
110 /* forker nscd pid */
111 static pid_t forker_pid = 0;
112 static pid_t forker_uid = 0;
114 long activity = 0;
115 mutex_t activity_lock = DEFAULTMUTEX;
117 static int forking_door = -1;
118 static mutex_t forking_lock = DEFAULTMUTEX;
120 static void
121 free_slot(int s)
123 if (child[s] == NULL)
124 return;
125 free(child[s]->mutex);
126 free(child[s]->cond);
127 free(child[s]);
128 child[s] = NULL;
131 void
132 _nscd_free_cslots()
135 int i;
137 (void) mutex_lock(&child_lock);
139 for (i = 0; i < max_pu_nscd; i++)
140 free_slot(i);
142 open_head = -1;
143 open_tail = -1;
144 used_slot = -1;
146 (void) mutex_unlock(&child_lock);
150 static int
151 init_slot(int s)
153 child_t *ch;
154 char *me = "init_slot";
156 if (child[s] == NULL) {
157 child[s] = (child_t *)calloc(1, sizeof (child_t));
158 if (child[s] == NULL)
159 return (-1);
160 ch = child[s];
162 if ((ch->mutex = (mutex_t *)calloc(1,
163 sizeof (mutex_t))) == NULL) {
164 free(ch);
165 return (-1);
167 (void) mutex_init(ch->mutex, USYNC_THREAD, NULL);
169 if ((ch->cond = (cond_t *)calloc(1,
170 sizeof (cond_t))) == NULL) {
171 free(ch->mutex);
172 free(ch);
173 return (-1);
175 (void) cond_init(ch->cond, USYNC_THREAD, NULL);
177 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
178 (me, "slot %d allocated\n", s);
179 } else
180 ch = child[s];
182 ch->child_slot = s;
183 ch->child_door = 0;
184 ch->child_state = CHILD_STATE_NONE;
185 ch->child_pid = 0;
186 ch->child_uid = 0;
187 ch->child_gid = 0;
188 ch->next_open = -1;
190 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
191 (me, "slot %d initialized\n", s);
193 return (0);
196 static int
197 _nscd_init_cslots()
199 (void) mutex_lock(&child_lock);
201 child = (child_t **)calloc(max_pu_nscd, sizeof (child_t *));
202 if (child == NULL)
203 return (-1);
205 open_head = -1;
206 open_tail = -1;
207 used_slot = -1;
209 (void) mutex_unlock(&child_lock);
211 return (0);
214 static child_t *
215 get_cslot(
216 uid_t uid,
217 int no_alloc)
219 int i;
220 child_t *ch, *ret = NULL;
221 char *me = "get_cslot";
223 (void) mutex_lock(&child_lock);
225 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
226 (me, "looking for uid %d (slot used = %d)\n", uid, used_slot);
228 /* first find the slot with a matching uid */
229 for (i = 0; i <= used_slot; i++) {
230 ch = child[i];
231 if (ch->child_state >= CHILD_STATE_UIDKNOWN &&
232 ch->child_uid == uid) {
233 ret = ch;
234 (void) mutex_unlock(&child_lock);
236 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
237 (me, "slot %d found with uid %d\n",
238 ret->child_slot, ret->child_uid);
240 return (ret);
244 /* if no need to allocate a new slot, return NULL */
245 if (no_alloc == 1) {
246 (void) mutex_unlock(&child_lock);
247 return (ret);
250 /* no open slot ? get a new one */
251 if (open_head == -1) {
252 /* if no slot available, allocate more */
253 if (used_slot >= max_pu_nscd - 1) {
254 child_t **tmp;
255 int newmax = max_pu_nscd + _NSCD_PUN_BLOCK;
257 tmp = (child_t **)calloc(newmax, sizeof (child_t *));
258 if (tmp == NULL) {
259 (void) mutex_unlock(&child_lock);
260 return (ret);
262 (void) memcpy(tmp, child, sizeof (child_t) *
263 max_pu_nscd);
264 free(child);
265 child = tmp;
266 max_pu_nscd = newmax;
268 used_slot++;
269 if (init_slot(used_slot) == -1) {
270 used_slot--;
271 (void) mutex_unlock(&child_lock);
272 return (ret);
274 ch = child[used_slot];
275 } else {
276 ch = child[open_head];
277 open_head = ch->next_open;
278 /* got last one ? reset tail */
279 if (open_head == -1)
280 open_tail = -1;
281 ch->next_open = -1;
284 ch->child_uid = uid;
285 ch->child_state = CHILD_STATE_UIDKNOWN;
286 ret = ch;
288 (void) mutex_unlock(&child_lock);
290 return (ret);
293 static void
294 return_cslot_nolock(child_t *ch)
297 int slot = ch->child_slot;
299 /* have open slot ? add to and reset tail */
300 if (open_tail != -1) {
301 child[open_tail]->next_open = slot;
302 open_tail = slot;
303 } else {
304 /* no open slot ? make one */
305 open_head = open_tail = slot;
308 (void) init_slot(ch->child_slot);
311 static void
312 return_cslot(child_t *ch)
315 char *me = "return_cslot";
317 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
318 (me, "returning slot %d\n", ch->child_slot);
320 /* return if the slot has been returned by another thread */
321 if (ch->child_state == CHILD_STATE_NONE)
322 return;
324 (void) mutex_lock(&child_lock);
326 /* check one more time */
327 if (ch->child_state == CHILD_STATE_NONE) {
328 (void) mutex_unlock(&child_lock);
329 return;
332 return_cslot_nolock(ch);
334 (void) mutex_unlock(&child_lock);
337 static int
338 selfcred_kill(
339 int fd)
341 int ret;
342 char *me = "selfcred_kill";
344 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
345 (me, "sending kill to door %d\n", fd);
347 if (fd != -1)
348 ret = _nscd_doorcall_fd(fd, NSCD_KILL, NULL, 0,
349 NULL, 0, NULL);
350 else
351 ret = _nscd_doorcall(NSCD_KILL);
353 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
354 (me, "kill request sent to door %d (rc = %d)\n", fd, ret);
356 return (ret);
360 void
361 _nscd_kill_forker()
363 (void) mutex_lock(&forking_lock);
364 if (forking_door != -1)
365 (void) selfcred_kill(forking_door);
366 forking_door = -1;
367 (void) mutex_unlock(&forking_lock);
370 void
371 _nscd_kill_all_children()
373 int i;
374 int ret;
375 char *me = "_nscd_kill_all_children";
377 (void) mutex_lock(&child_lock);
378 for (i = 0; i <= used_slot; i++) {
379 if (child[i] == NULL)
380 continue;
382 if (child[i]->child_state >= CHILD_STATE_PIDKNOWN) {
383 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
384 (me, "killing child process %d (doorfd %d)\n",
385 child[i]->child_pid, child[i]->child_door);
387 ret = selfcred_kill(child[i]->child_door);
389 if (ret != -1)
390 (void) kill(child[i]->child_pid, SIGTERM);
392 if (child[i]->child_state != CHILD_STATE_NONE)
393 (void) return_cslot_nolock(child[i]);
395 (void) mutex_unlock(&child_lock);
397 static int
398 selfcred_pulse(
399 int fd)
401 int ret;
402 char *me = "selfcred_pulse";
404 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
405 (me, "start monitoring door %d\n", fd);
407 ret = _nscd_doorcall_fd(fd, NSCD_PULSE |(_whoami & NSCD_WHOAMI),
408 NULL, 0, NULL, 0, NULL);
410 /* Close door because the other side exited. */
411 (void) close(fd);
413 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
414 (me, "door (%d) monitor exited (rc = %d)\n", fd, ret);
416 return (ret);
419 /*ARGSUSED*/
420 static void *
421 forker_monitor(
422 void *arg)
424 pid_t fpid;
425 char *fmri;
426 char *me = "forker_monitor";
428 /* wait until forker exits */
429 fpid = forker_pid;
430 (void) selfcred_pulse(forking_door);
432 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
433 (me, "forker (pid = %d) exited or crashed, "
434 "killing all child processes\n", fpid);
436 (void) mutex_lock(&forking_lock);
437 forking_door = -1;
438 forker_pid = -1;
439 (void) mutex_unlock(&forking_lock);
441 /* forker exited/crashed, kill all the child processes */
442 _nscd_kill_all_children();
444 /* restart forker */
445 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
446 (me, "restarting the forker ...\n");
448 switch (fpid = fork1()) {
449 case (pid_t)-1:
450 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
451 (me, "unable to fork and start the forker ...\n");
453 /* enter the maintenance mode */
454 if ((fmri = getenv("SMF_FMRI")) != NULL) {
455 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
456 (me, "entering maintenance mode ...\n");
457 (void) smf_maintain_instance(fmri, SMF_TEMPORARY);
459 return ((void *)1);
460 case 0:
461 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
462 (me, "execv path = %s\n", execpath);
464 (void) execv(execpath, execargv);
465 exit(0);
466 default:
467 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
468 (me, "new forker's pid is %d\n", fpid);
469 forker_pid = fpid;
470 break;
473 return (NULL);
476 static void *
477 child_monitor(
478 void *arg)
480 child_t *ch = (child_t *)arg;
481 pid_t cpid;
482 char *me = "child_monitor";
484 /* wait until child exits */
485 cpid = ch->child_pid;
486 (void) selfcred_pulse(ch->child_door);
488 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
489 (me, "child (pid = %d) exited or crashed ...\n", cpid);
491 /* return the slot used by the child */
492 return_cslot(ch);
494 return (NULL);
498 void
499 _nscd_proc_iamhere(
500 void *buf,
501 door_desc_t *dp,
502 uint_t n_desc,
503 int iam)
505 int cslot;
506 child_t *ch;
507 int errnum;
508 ucred_t *uc = NULL;
509 uid_t uid;
510 nscd_imhere_t *ih;
511 nss_pheader_t *phdr = (nss_pheader_t *)buf;
512 char *me = "_nscd_proc_iamhere";
515 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
516 (me, "%d receives iamhere from %d\n", _whoami, iam);
518 if (door_ucred(&uc) != 0) {
519 errnum = errno;
520 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
521 (me, "door_ucred failed: %s\n", strerror(errnum));
523 NSCD_SET_N2N_STATUS(phdr, NSS_NSCD_PRIV, errnum,
524 NSCD_DOOR_UCRED_ERROR);
525 return;
527 uid = ucred_geteuid(uc);
529 switch (iam) {
531 case NSCD_MAIN:
532 if (_whoami == NSCD_MAIN || uid != main_uid) {
534 * I'm main, or uid from door is not correct,
535 * this must be an imposter
537 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
538 (me, "MAIN IMPOSTER CAUGHT!\n");
541 NSCD_SET_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0,
542 NSCD_SELF_CRED_MAIN_IMPOSTER);
544 break;
546 case NSCD_FORKER:
547 if (_whoami == NSCD_FORKER || uid != forker_uid) {
549 * I'm forker, or uid from door is not correct,
550 * this must be an imposter
552 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
553 (me, "FORKER IMPOSTER CAUGHT!\n");
556 NSCD_SET_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0,
557 NSCD_SELF_CRED_FORKER_IMPOSTER);
558 break;
561 /* only main needs to know the forker */
562 if (_whoami != NSCD_MAIN) {
564 NSCD_SET_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0,
565 NSCD_SELF_CRED_WRONG_NSCD);
566 break;
569 if (ucred_getpid(uc) != forker_pid) {
570 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
571 (me, "FORKER IMPOSTER CAUGHT: pid = %d should be %d\n",
572 ucred_getpid(uc), forker_pid);
575 NSCD_SET_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0,
576 NSCD_SELF_CRED_FORKER_IMPOSTER);
577 break;
580 if (n_desc < 1) {
581 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
582 (me, "BAD FORKER, NO DOOR!\n");
585 NSCD_SET_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0,
586 NSCD_SELF_CRED_NO_DOOR);
587 break;
590 if ((dp->d_attributes & DOOR_DESCRIPTOR) &&
591 dp->d_data.d_desc.d_descriptor > 0 &&
592 dp->d_data.d_desc.d_id != 0) {
593 (void) mutex_lock(&forking_lock);
594 if (forking_door != -1)
595 (void) close(forking_door);
596 forking_door = dp->d_data.d_desc.d_descriptor;
597 (void) mutex_unlock(&forking_lock);
599 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
600 (me, "forking door is %d\n", forking_door);
602 NSCD_SET_STATUS_SUCCESS(phdr);
603 } else {
604 NSCD_SET_STATUS(phdr, NSS_ALTRETRY, 0);
605 break;
608 /* monitor the forker nscd */
609 (void) thr_create(NULL, 0, forker_monitor, NULL,
610 THR_DETACHED, NULL);
612 break;
614 case NSCD_CHILD:
615 if (_whoami != NSCD_MAIN) {
616 /* child nscd can only talk to the main nscd */
617 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
618 (me, "CHILD IMPOSTER CAUGHT!\n");
620 NSCD_SET_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0,
621 NSCD_SELF_CRED_CHILD_IMPOSTER);
622 break;
625 /* get the main nscd assigned slot number */
626 ih = NSCD_N2N_DOOR_DATA(nscd_imhere_t, buf);
627 cslot = ih->slot;
628 (void) mutex_lock(&child_lock);
629 if (cslot < 0 || cslot >= max_pu_nscd)
630 ch = NULL;
631 else
632 ch = child[cslot];
633 (void) mutex_unlock(&child_lock);
635 if (ch == NULL) {
636 /* Bad slot number */
637 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
638 (me, "bad slot number %d\n", cslot);
640 NSCD_SET_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0,
641 NSCD_SELF_CRED_INVALID_SLOT_NUMBER);
642 break;
645 if (uid != ch->child_uid) {
646 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
647 (me, "CHILD IMPOSTER CAUGHT: uid = %d should be %d\n",
648 uid, ch->child_uid);
650 NSCD_SET_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0,
651 NSCD_SELF_CRED_CHILD_IMPOSTER);
652 break;
655 if (ch->child_state != CHILD_STATE_UIDKNOWN &&
656 ch->child_state != CHILD_STATE_FORKSENT) {
657 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
658 (me, "invalid slot/child state (%d) for uid %d\n",
659 ch->child_state, uid);
661 NSCD_SET_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0,
662 NSCD_SELF_CRED_INVALID_SLOT_STATE);
663 break;
666 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
667 (me, "d_descriptor = %d, d_id = %lld\n",
668 dp->d_data.d_desc.d_descriptor, dp->d_data.d_desc.d_id);
670 if ((dp->d_attributes & DOOR_DESCRIPTOR) &&
671 dp->d_data.d_desc.d_descriptor > 0 &&
672 dp->d_data.d_desc.d_id != 0) {
673 (void) mutex_lock(ch->mutex);
674 if (ch->child_door != -1)
675 (void) close(ch->child_door);
676 ch->child_door = dp->d_data.d_desc.d_descriptor;
677 ch->child_pid = ucred_getpid(uc);
678 ch->child_state = CHILD_STATE_PIDKNOWN;
679 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
680 (me, "child in slot %d has door %d\n",
681 cslot, ch->child_door);
684 * let waiters know that the child is ready to
685 * serve
687 (void) cond_broadcast(ch->cond);
688 (void) mutex_unlock(ch->mutex);
690 /* monitor the child nscd */
691 (void) thr_create(NULL, 0, child_monitor,
692 ch, THR_DETACHED, NULL);
693 NSCD_SET_STATUS_SUCCESS(phdr);
694 break;
695 } else {
696 NSCD_SET_STATUS(phdr, NSS_ALTRETRY, 0);
698 break;
701 ucred_free(uc);
702 uc = NULL;
705 void
706 _nscd_proc_pulse(
707 void *buf,
708 int iam)
710 long last_active;
711 int done = 0;
712 nss_pheader_t *phdr = (nss_pheader_t *)buf;
713 char *me = "_nscd_proc_pulse";
715 /* only main nscd sends pulse */
716 if (iam != NSCD_MAIN) {
717 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
718 (me, "MAIN IMPOSTER CAUGHT! i am %d not NSCD_MAIN\n", iam);
720 NSCD_SET_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0,
721 NSCD_SELF_CRED_MAIN_IMPOSTER);
722 return;
725 /* forker doesn't return stats, it just pauses */
726 if (_whoami == NSCD_FORKER) {
727 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
728 (me, "forker ready to pause ...\n");
730 for (;;)
731 (void) pause();
734 /* remember the current activity sequence number */
735 (void) mutex_lock(&activity_lock);
736 last_active = activity;
737 (void) mutex_unlock(&activity_lock);
739 while (!done) {
741 /* allow per_user_nscd_ttl seconds of inactivity */
742 (void) sleep(pu_nscd_ttl);
744 (void) mutex_lock(&activity_lock);
745 if (last_active == activity)
746 done = 1;
747 else {
748 last_active = activity;
749 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
750 (me, "active, sleep again for %d seconds\n",
751 pu_nscd_ttl);
753 (void) mutex_unlock(&activity_lock);
756 /* no activity in the specified seconds, exit and disconnect */
757 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
758 (me, "no activity in the last %d seconds, exit\n", pu_nscd_ttl);
759 exit(0);
762 void
763 _nscd_proc_fork(
764 void *buf,
765 int iam)
767 int slot;
768 int ret;
769 char *fmri;
770 pid_t cid;
771 uid_t set2uid;
772 gid_t set2gid;
773 nss_pheader_t *phdr = (nss_pheader_t *)buf;
774 char *me = "_nscd_proc_fork";
775 nscd_fork_t *f;
776 nscd_imhere_t ih;
778 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
779 (me, "%d receives fork request from %d\n", _whoami, iam);
781 /* only main nscd sends fork requests */
782 if (iam != NSCD_MAIN) {
783 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
784 (me, "MAIN IMPOSTER CAUGHT! i am %d not NSCD_MAIN\n", iam);
786 NSCD_SET_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0,
787 NSCD_SELF_CRED_MAIN_IMPOSTER);
788 return;
791 /* only forker handles fork requests */
792 if (_whoami != NSCD_FORKER) {
793 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
794 (me, "MAIN IMPOSTER CAUGHT! I AM NOT FORKER!\n");
796 NSCD_SET_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0,
797 NSCD_SELF_CRED_WRONG_NSCD);
798 return;
801 /* fork a child for the slot assigned by the main nscd */
802 f = NSCD_N2N_DOOR_DATA(nscd_fork_t, buf);
803 slot = f->slot;
804 /* set the uid/gid as assigned by the main nscd */
805 set2uid = f->uid;
806 set2gid = f->gid;
808 /* ignore bad slot number */
809 if (slot < 0 || slot >= max_pu_nscd) {
810 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
811 (me, "bas slot number\n");
813 NSCD_SET_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0,
814 NSCD_SELF_CRED_INVALID_SLOT_NUMBER);
815 return;
818 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
819 (me, "before fork1() ...\n");
821 if ((cid = fork1()) == 0) {
822 _whoami = NSCD_CHILD;
825 * remember when this child nscd starts
826 * (replace the forker start time)
828 _nscd_set_start_time(1);
830 /* close all except the log file */
831 if (_logfd > 0) {
832 int i;
833 for (i = 0; i < _logfd; i++)
834 (void) close(i);
835 closefrom(_logfd + 1);
836 } else
837 closefrom(0);
839 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
840 (me, "child %d\n", getpid());
842 (void) setgid(set2gid);
843 (void) setuid(set2uid);
845 /* set up the door and server thread pool */
846 if ((_doorfd = _nscd_setup_child_server(_doorfd)) == -1)
847 exit(-1);
849 /* tell libsldap to do self cred only */
850 (void) setup_ldap_backend();
852 /* notify main that child is active */
853 ih.slot = slot;
854 for (ret = NSS_ALTRETRY; ret == NSS_ALTRETRY; )
855 ret = _nscd_doorcall_sendfd(_doorfd,
856 NSCD_IMHERE | (NSCD_CHILD & NSCD_WHOAMI),
857 &ih, sizeof (ih), NULL);
859 NSCD_SET_STATUS_SUCCESS(phdr);
860 return;
861 } if (cid == (pid_t)-1) {
862 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
863 (me, "forker unable to fork ...\n");
865 /* enter the maintenance mode */
866 if ((fmri = getenv("SMF_FMRI")) != NULL) {
867 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
868 (me, "entering maintenance mode ...\n");
869 (void) smf_maintain_instance(fmri, SMF_TEMPORARY);
871 exit(0);
872 } else {
874 * start the monitor so as to exit as early as
875 * possible if no other processes are running
876 * with the same PUN uid (i.e., this PUN is
877 * not needed any more)
879 (void) init_user_proc_monitor();
881 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
882 (me, "child forked: parent pid = %d, child pid = %d\n",
883 getpid(), cid);
885 NSCD_SET_STATUS_SUCCESS(phdr);
888 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
889 (me, "after fork\n");
892 static void
893 selfcred_fork(
894 void *buf,
895 int doorfd,
896 int cslot,
897 uid_t uid,
898 gid_t gid)
900 int ret;
901 nscd_fork_t f;
902 nss_pheader_t *phdr = (nss_pheader_t *)buf;
903 char *me = "selfcred_fork";
905 /* if no door fd, do nothing */
906 if (doorfd == -1) {
907 NSCD_SET_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0,
908 NSCD_SELF_CRED_NO_DOOR);
911 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
912 (me, "sending fork request to door %d for slot %d "
913 "(uid = %d, gid = %d)\n", doorfd, cslot, uid, gid);
915 f.slot = cslot;
916 f.uid = uid;
917 f.gid = gid;
919 ret = _nscd_doorcall_fd(doorfd, NSCD_FORK|(_whoami&NSCD_WHOAMI),
920 &f, sizeof (f), NULL, 0, phdr);
922 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
923 (me, "fork request sent to door %d for slot %d (rc = %d)\n",
924 doorfd, cslot, ret);
926 if (NSCD_STATUS_IS_NOT_OK(phdr)) {
928 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
929 (me, "fork request sent to door %d for slot %d failed: "
930 "status = %d, errno = %s, nscd status = %d\n", doorfd,
931 cslot, NSCD_GET_STATUS(phdr),
932 strerror(NSCD_GET_ERRNO(phdr)),
933 NSCD_GET_NSCD_STATUS(phdr));
938 void
939 _nscd_proc_alt_get(
940 void *buf,
941 int *door)
943 int errnum;
944 uid_t set2uid;
945 gid_t set2gid;
946 nss_pheader_t *phdr = (nss_pheader_t *)buf;
947 char *me = "_nscd_proc_alt_get";
948 ucred_t *uc = NULL;
949 child_t *ch;
951 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
952 (me, "getting an alternate door ...\n");
954 /* make sure there is a door to talk to the forker */
955 if (forking_door == -1) {
956 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_ERROR)
957 (me, "no door to talk to the forker\n");
959 NSCD_SET_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0,
960 NSCD_SELF_CRED_NO_FORKER);
961 return;
964 /* get door client's credential information */
965 if (door_ucred(&uc) != 0) {
966 errnum = errno;
967 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
968 (me, "door_ucred failed: %s\n", strerror(errnum));
970 NSCD_SET_N2N_STATUS(phdr, NSS_NSCD_PRIV, errnum,
971 NSCD_DOOR_UCRED_ERROR);
972 return;
975 /* get door client's effective uid and effective gid */
976 set2uid = ucred_geteuid(uc);
977 set2gid = ucred_getegid(uc);
978 ucred_free(uc);
979 uc = NULL;
981 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
982 (me, "child uid = %d, gid = %d\n", set2uid, set2gid);
984 /* is a slot available ? if not, no one to serve */
985 if (child == NULL || (ch = get_cslot(set2uid, 0)) == NULL) {
987 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
988 (me, "no child slot available (child array = %p, slot = %d)\n",
989 child, ch->child_slot);
991 NSCD_SET_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0,
992 NSCD_SELF_CRED_NO_CHILD_SLOT);
993 return;
996 /* create the per user nscd if necessary */
997 if (ch->child_state != CHILD_STATE_PIDKNOWN) {
999 nss_pheader_t phdr1;
1000 NSCD_CLEAR_STATUS(&phdr1);
1002 (void) mutex_lock(ch->mutex);
1003 if (ch->child_state == CHILD_STATE_UIDKNOWN) {
1005 /* ask forker to fork a new child */
1006 selfcred_fork(&phdr1, forking_door, ch->child_slot,
1007 set2uid, set2gid);
1008 if (NSCD_STATUS_IS_NOT_OK(&phdr1)) {
1009 (void) mutex_unlock(ch->mutex);
1010 NSCD_COPY_STATUS(phdr, &phdr1);
1011 return;
1013 ch->child_state = CHILD_STATE_FORKSENT;
1016 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
1017 (me, "waiting for door (slot = %d, uid = %d, gid = %d)\n",
1018 ch->child_slot, set2uid, set2gid);
1020 /* wait for the per user nscd to become available */
1021 while (ch->child_state == CHILD_STATE_FORKSENT) {
1022 timestruc_t to;
1023 int err;
1024 int ttl = 5;
1026 to.tv_sec = ttl;
1027 to.tv_nsec = 0;
1028 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
1029 (me, "cond_reltimedwait %d seconds\n", ttl);
1030 err = cond_reltimedwait(ch->cond, ch->mutex, &to);
1031 if (err == ETIME) {
1032 ch->child_state = CHILD_STATE_UIDKNOWN;
1033 _NSCD_LOG(NSCD_LOG_SELF_CRED,
1034 NSCD_LOG_LEVEL_DEBUG)
1035 (me, "door wait timedout (slot = %d)\n",
1036 ch->child_slot);
1037 break;
1040 (void) mutex_unlock(ch->mutex);
1043 if (ch->child_state != CHILD_STATE_PIDKNOWN) {
1045 NSCD_SET_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0,
1046 NSCD_SELF_CRED_INVALID_SLOT_STATE);
1047 return;
1050 *door = ch->child_door;
1052 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
1053 (me, "returning door %d for slot %d, uid %d, gid = %d\n",
1054 *door, ch->child_slot, set2uid, set2gid);
1056 NSCD_SET_STATUS(phdr, NSS_ALTRETRY, 0);
1059 static char **
1060 cpargv(
1061 int argc,
1062 char **inargv)
1064 char **newargv;
1065 int c = 4;
1066 int i = 0, j, k = 0, n = 0;
1068 newargv = (char **)calloc(c + 1, sizeof (char *));
1069 if (newargv == NULL)
1070 return (NULL);
1072 newargv[n] = strdup(inargv[0]);
1073 if (newargv[n++] == NULL) {
1074 free(newargv);
1075 return (NULL);
1078 newargv[n] = strdup("-F");
1079 if (newargv[n++] == NULL) {
1080 free(newargv[0]);
1081 free(newargv);
1082 return (NULL);
1085 for (i = 1; i < argc; i++) {
1086 if (strcmp(inargv[i], "-f") == 0)
1087 k = 2;
1088 if (k == 0)
1089 continue;
1091 newargv[n] = strdup(inargv[i]);
1092 if (newargv[n] == NULL) {
1093 for (j = 0; j < n; j++)
1094 free(newargv[j]);
1095 free(newargv);
1096 return (NULL);
1099 k--;
1100 n++;
1102 return (newargv);
1106 void
1107 _nscd_start_forker(
1108 char *path,
1109 int argc,
1110 char **argv)
1112 pid_t cid;
1114 /* if self cred is not configured, do nothing */
1115 if (!_nscd_is_self_cred_on(1, NULL))
1116 return;
1118 /* save pathname and generate the new argv for the forker */
1119 execpath = strdup(path);
1120 execargv = cpargv(argc, argv);
1121 if (execpath == NULL || execargv == NULL)
1122 exit(1);
1124 switch (cid = fork1()) {
1125 case (pid_t)-1:
1126 exit(1);
1127 break;
1128 case 0:
1129 /* start the forker nscd */
1130 (void) execv(path, execargv);
1131 exit(0);
1132 break;
1133 default:
1134 /* main nscd */
1135 /* remember process id of the forker */
1136 forker_pid = cid;
1138 /* enable child nscd management */
1139 (void) _nscd_init_cslots();
1140 break;
1144 static nscd_rc_t
1145 get_ldap_funcs(
1146 char *name,
1147 void **func_p)
1149 char *me = "get_ldap_funcs";
1150 static void *handle = NULL;
1151 void *sym;
1153 if (name == NULL && handle != NULL) {
1154 (void) dlclose(handle);
1155 return (NSCD_SUCCESS);
1157 /* no handle to close, it's OK */
1158 if (name == NULL)
1159 return (NSCD_SUCCESS);
1161 if (handle == NULL) {
1162 handle = dlopen("libsldap.so.1", RTLD_LAZY);
1163 if (handle == NULL) {
1165 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_ERROR)
1166 (me, "unable to dlopen libsldap.so.1");
1167 return (NSCD_CFG_DLOPEN_ERROR);
1171 if ((sym = dlsym(handle, name)) == NULL) {
1173 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_ERROR)
1174 (me, "unable to find symbol %s", name);
1175 return (NSCD_CFG_DLSYM_ERROR);
1176 } else
1177 (void) memcpy(func_p, &sym, sizeof (void *));
1179 return (NSCD_SUCCESS);
1184 _nscd_is_self_cred_on(int recheck, char **dblist)
1186 static int checked = 0;
1187 static int is_on = 0;
1188 static int (*ldap_func)();
1189 char *srcs = "ldap"; /* only ldap support self cred */
1190 int ldap_on = 0;
1192 char *ldap_sc_func = "__ns_ldap_self_gssapi_config";
1193 ns_ldap_self_gssapi_config_t ldap_config;
1195 if (checked && !recheck) {
1196 if (is_on && dblist != NULL)
1197 *dblist = selfcred_dbs;
1198 return (is_on);
1201 free(selfcred_dbs);
1202 selfcred_dbs = _nscd_srcs_in_db_nsw_policy(1, &srcs);
1204 if (selfcred_dbs == NULL) {
1205 is_on = 0;
1206 checked = 1;
1207 return (0);
1211 * also check the ldap backend to see if
1212 * the configuration there is good for
1213 * doing self credentialing
1215 if (ldap_func == NULL)
1216 (void) get_ldap_funcs(ldap_sc_func, (void **)&ldap_func);
1217 if (ldap_func != NULL) {
1218 if (ldap_func(&ldap_config) == NS_LDAP_SUCCESS &&
1219 ldap_config != NS_LDAP_SELF_GSSAPI_CONFIG_NONE)
1220 ldap_on = 1;
1223 is_on = (pu_nscd_enabled == nscd_true) && ldap_on;
1225 checked = 1;
1227 if (is_on && dblist != NULL)
1228 *dblist = selfcred_dbs;
1230 return (is_on);
1233 static nscd_rc_t
1234 setup_ldap_backend()
1236 nscd_rc_t rc;
1237 static void (*ldap_func)();
1238 char *ldap_sc_func = "__ns_ldap_self_gssapi_only_set";
1239 if (ldap_func == NULL)
1240 rc = get_ldap_funcs(ldap_sc_func, (void **)&ldap_func);
1241 if (ldap_func != NULL) {
1242 ldap_func(1);
1243 return (NSCD_SUCCESS);
1245 return (rc);
1248 /*ARGSUSED*/
1249 void
1250 _nscd_peruser_getadmin(
1251 void *buf,
1252 int buf_size)
1254 void *result_mn = NSCD_N2N_DOOR_DATA(void, buf);
1255 int errnum = 0;
1256 int ret;
1257 uid_t uid;
1258 nss_pheader_t *phdr = (nss_pheader_t *)buf;
1259 char *me = "_nscd_peruser_getadmin";
1260 ucred_t *uc = NULL;
1261 child_t *ch;
1263 /* get door client's credential information */
1264 if (door_ucred(&uc) != 0) {
1265 errnum = errno;
1266 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
1267 (me, "door_ucred failed: %s\n", strerror(errnum));
1269 NSCD_SET_N2N_STATUS(phdr, NSS_NSCD_PRIV, errnum,
1270 NSCD_DOOR_UCRED_ERROR);
1271 return;
1274 /* get door client's effective uid */
1275 uid = ucred_geteuid(uc);
1276 ucred_free(uc);
1277 uc = NULL;
1279 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
1280 (me, "per user get admin ... (uid = %d)\n", uid);
1282 /* is the per-user nscd running ? if not, no one to serve */
1283 ch = get_cslot(uid, 1);
1284 if (ch == NULL) {
1285 NSCD_SET_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0,
1286 NSCD_SELF_CRED_NO_CHILD_SLOT);
1287 return;
1290 ret = _nscd_doorcall_fd(ch->child_door, NSCD_GETADMIN,
1291 NULL, sizeof (nscd_admin_t), result_mn,
1292 sizeof (nscd_admin_t), phdr);
1294 if (ret == NSS_SUCCESS) {
1295 phdr->data_len = sizeof (nscd_admin_t);
1296 return;
1300 static void
1301 set_selfcred_cfg(
1302 char param,
1303 void *data)
1305 int64_t prop_int;
1306 uint8_t prop_boolean;
1307 char *me = "set_selfcred_cfg";
1309 if (param == 'e') {
1310 prop_boolean = *(uint8_t *)data;
1311 pu_nscd_enabled = *(uint8_t *)get_smf_prop(
1312 "enable_per_user_lookup", 'b', &prop_boolean);
1314 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
1315 (me, "self cred config: enabled = %d\n", pu_nscd_enabled);
1318 if (param == 't') {
1319 prop_int = *(int *)data;
1320 pu_nscd_ttl = *(int64_t *)get_smf_prop(
1321 "per_user_nscd_time_to_live", 'i', &prop_int);
1323 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
1324 (me, "self cred config: PUN TTL = %d\n", pu_nscd_ttl);
1328 /* ARGSUSED */
1329 nscd_rc_t
1330 _nscd_cfg_selfcred_notify(
1331 void *data,
1332 struct nscd_cfg_param_desc *pdesc,
1333 nscd_cfg_id_t *nswdb,
1334 nscd_cfg_flag_t dflag,
1335 nscd_cfg_error_t **errorp,
1336 void *cookie)
1339 nscd_cfg_global_selfcred_t *sc_cfg = &nscd_selfcred_cfg_g;
1340 int off;
1343 * At init time, the whole group of config params are received.
1344 * At update time, group or individual parameter value could
1345 * be received.
1348 if (_nscd_cfg_flag_is_set(dflag, NSCD_CFG_DFLAG_GROUP)) {
1350 *sc_cfg = *(nscd_cfg_global_selfcred_t *)data;
1352 off = offsetof(nscd_cfg_global_selfcred_t,
1353 enable_selfcred);
1354 set_selfcred_cfg('e', (char *)data + off);
1356 off = offsetof(nscd_cfg_global_selfcred_t,
1357 per_user_nscd_ttl);
1358 set_selfcred_cfg('t', (char *)data + off);
1360 return (NSCD_SUCCESS);
1364 * individual config parameter
1366 off = offsetof(nscd_cfg_global_selfcred_t, enable_selfcred);
1367 if (pdesc->p_offset == off) {
1368 sc_cfg->enable_selfcred = *(nscd_bool_t *)data;
1369 set_selfcred_cfg('e', data);
1370 return (NSCD_SUCCESS);
1373 off = offsetof(nscd_cfg_global_selfcred_t, per_user_nscd_ttl);
1374 if (pdesc->p_offset == off) {
1375 sc_cfg->per_user_nscd_ttl = *(int *)data;
1376 set_selfcred_cfg('t', data);
1377 return (NSCD_SUCCESS);
1380 return (NSCD_SUCCESS);
1383 /* ARGSUSED */
1384 nscd_rc_t
1385 _nscd_cfg_selfcred_verify(
1386 void *data,
1387 struct nscd_cfg_param_desc *pdesc,
1388 nscd_cfg_id_t *nswdb,
1389 nscd_cfg_flag_t dflag,
1390 nscd_cfg_error_t **errorp,
1391 void **cookie)
1394 return (NSCD_SUCCESS);
1397 /* ARGSUSED */
1398 nscd_rc_t
1399 _nscd_cfg_selfcred_get_stat(
1400 void **stat,
1401 struct nscd_cfg_stat_desc *sdesc,
1402 nscd_cfg_id_t *nswdb,
1403 nscd_cfg_flag_t *dflag,
1404 void (**free_stat)(void *stat),
1405 nscd_cfg_error_t **errorp)
1407 return (NSCD_SUCCESS);
1410 static int
1411 check_uid(char *pid_name)
1413 char pname[PATH_MAX];
1414 static pid_t pid = 0;
1415 static uid_t uid = 0;
1416 static uid_t euid = 0;
1417 int pfd; /* file descriptor for /proc/<pid>/psinfo */
1418 psinfo_t info; /* process information from /proc */
1420 if (uid == 0) {
1421 pid = getpid();
1422 uid = getuid();
1423 euid = geteuid();
1426 (void) snprintf(pname, sizeof (pname), "/proc/%s/psinfo", pid_name);
1427 retry:
1428 if ((pfd = open(pname, O_RDONLY)) == -1) {
1429 /* Process may have exited */
1430 return (1);
1434 * Get the info structure for the process and close quickly.
1436 if (read(pfd, (char *)&info, sizeof (info)) < 0) {
1437 int saverr = errno;
1439 (void) close(pfd);
1440 if (saverr == EAGAIN)
1441 goto retry;
1442 if (saverr != ENOENT)
1443 return (1);
1445 (void) close(pfd);
1447 if (info.pr_pid != pid &&
1448 info.pr_uid == uid && info.pr_euid == euid)
1449 return (0);
1450 else
1451 return (1);
1456 * FUNCTION: check_user_process
1458 /*ARGSUSED*/
1459 static void *
1460 check_user_process(void *arg)
1463 DIR *dp;
1464 struct dirent *ep;
1465 int found;
1466 char *me = "check_user_process";
1468 for (;;) {
1469 (void) sleep(60);
1471 found = 0;
1474 * search the /proc directory and look at each process
1476 if ((dp = opendir("/proc")) == NULL) {
1477 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_ERROR)
1478 (me, "unable to open the /proc directory\n");
1479 continue;
1482 /* for each active process */
1483 while (ep = readdir(dp)) {
1484 if (ep->d_name[0] == '.') /* skip . and .. */
1485 continue;
1486 if (check_uid(ep->d_name) == 0) {
1487 found = 1;
1488 break;
1493 * if no process running as the PUN uid found, exit
1494 * to kill this PUN
1496 if (found == 0) {
1497 (void) closedir(dp);
1498 exit(1);
1500 (void) closedir(dp);
1502 /*LINTED E_FUNC_HAS_NO_RETURN_STMT*/
1505 static nscd_rc_t
1506 init_user_proc_monitor() {
1508 int errnum;
1509 char *me = "init_user_proc_monitor";
1511 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
1512 (me, "initializing the user process monitor\n");
1515 * start a thread to make sure there is at least a process
1516 * running as the PUN user. If not, terminate this PUN.
1518 if (thr_create(NULL, 0, check_user_process,
1519 NULL, THR_DETACHED, NULL) != 0) {
1520 errnum = errno;
1521 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_ERROR)
1522 (me, "thr_create: %s\n", strerror(errnum));
1523 return (NSCD_THREAD_CREATE_ERROR);
1526 return (NSCD_SUCCESS);
1529 static void *
1530 get_smf_prop(const char *var, char type, void *def_val)
1532 scf_simple_prop_t *prop;
1533 void *val;
1534 char *me = "get_smf_prop";
1536 prop = scf_simple_prop_get(NULL, NULL, "config", var);
1537 if (prop) {
1538 switch (type) {
1539 case 'b':
1540 val = scf_simple_prop_next_boolean(prop);
1541 if (val != NULL)
1542 (void) memcpy(def_val, val, sizeof (uint8_t));
1543 break;
1545 case 'i':
1546 val = scf_simple_prop_next_integer(prop);
1547 if (val != NULL)
1548 (void) memcpy(def_val, val, sizeof (int64_t));
1549 break;
1551 scf_simple_prop_free(prop);
1554 if (prop == NULL || val == NULL) {
1555 char vs[64];
1557 switch (type) {
1558 case 'b':
1559 if (*(uint8_t *)def_val)
1560 (void) strcpy(vs, "yes");
1561 else
1562 (void) strcpy(vs, "no");
1564 break;
1566 case 'i':
1567 (void) sprintf(vs, "%lld", *(int64_t *)def_val);
1568 break;
1571 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_ALERT)
1572 (me, "no value for config/%s (%s). "
1573 "Using default \"%s\"\n", var,
1574 scf_strerror(scf_error()), vs);
1577 return (def_val);