8158 Want named threads API
[unleashed.git] / usr / src / cmd / nscd / nscd_selfcred.c
blobb6cdba8c7a477112e170151717ab267392833568
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.
25 * Copyright 2018 Joyent Inc.
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <synch.h>
31 #include <thread.h>
32 #include <string.h>
33 #include <errno.h>
34 #include <dlfcn.h>
35 #include <door.h>
36 #include <libscf.h>
37 #include <ucred.h>
38 #include <sys/varargs.h>
39 #include <signal.h>
40 #include <unistd.h>
41 #include <sys/types.h>
42 #include <dirent.h>
43 #include <sys/proc.h>
44 #include <procfs.h>
45 #include <sys/stat.h>
46 #include <fcntl.h>
47 #include <libscf.h>
48 #include "nscd_door.h"
49 #include "nscd_config.h"
50 #include "nscd_log.h"
51 #include "nscd_frontend.h"
52 #include "nscd_selfcred.h"
53 #include "nscd_admin.h"
54 #include "nscd_common.h"
55 #include "ns_sldap.h"
57 extern int _logfd;
58 static char *execpath;
59 static char **execargv;
60 static char *selfcred_dbs = NULL;
62 static void *get_smf_prop(const char *var, char type, void *def_val);
64 /* current self-cred configuration data being used */
65 static nscd_cfg_global_selfcred_t nscd_selfcred_cfg_g;
67 #define _NSCD_PUN_BLOCK 1024
68 static uint8_t pu_nscd_enabled;
69 static int max_pu_nscd = _NSCD_PUN_BLOCK;
70 static int pu_nscd_ttl;
72 static nscd_rc_t setup_ldap_backend();
73 static nscd_rc_t init_user_proc_monitor();
76 * clild state
78 typedef enum {
79 CHILD_STATE_NONE = 0,
80 CHILD_STATE_UIDKNOWN,
81 CHILD_STATE_FORKSENT,
82 CHILD_STATE_PIDKNOWN
83 } child_state_t;
86 typedef struct _child {
87 int child_slot;
88 int child_door;
89 pid_t child_pid;
90 uid_t child_uid;
91 gid_t child_gid;
92 child_state_t child_state;
93 int next_open;
94 mutex_t *mutex;
95 cond_t *cond;
96 } child_t;
98 static child_t **child = NULL;
99 static mutex_t child_lock = DEFAULTMUTEX;
100 static int open_head;
101 static int open_tail;
102 static int used_slot;
104 /* nscd door id */
105 extern int _doorfd;
106 static pid_t main_uid = 0;
108 /* nscd id: main, forker, or child */
109 extern int _whoami;
111 /* forker nscd pid */
112 static pid_t forker_pid = 0;
113 static pid_t forker_uid = 0;
115 long activity = 0;
116 mutex_t activity_lock = DEFAULTMUTEX;
118 static int forking_door = -1;
119 static mutex_t forking_lock = DEFAULTMUTEX;
121 static void
122 free_slot(int s)
124 if (child[s] == NULL)
125 return;
126 free(child[s]->mutex);
127 free(child[s]->cond);
128 free(child[s]);
129 child[s] = NULL;
132 void
133 _nscd_free_cslots()
136 int i;
138 (void) mutex_lock(&child_lock);
140 for (i = 0; i < max_pu_nscd; i++)
141 free_slot(i);
143 open_head = -1;
144 open_tail = -1;
145 used_slot = -1;
147 (void) mutex_unlock(&child_lock);
151 static int
152 init_slot(int s)
154 child_t *ch;
155 char *me = "init_slot";
157 if (child[s] == NULL) {
158 child[s] = (child_t *)calloc(1, sizeof (child_t));
159 if (child[s] == NULL)
160 return (-1);
161 ch = child[s];
163 if ((ch->mutex = (mutex_t *)calloc(1,
164 sizeof (mutex_t))) == NULL) {
165 free(ch);
166 return (-1);
168 (void) mutex_init(ch->mutex, USYNC_THREAD, NULL);
170 if ((ch->cond = (cond_t *)calloc(1,
171 sizeof (cond_t))) == NULL) {
172 free(ch->mutex);
173 free(ch);
174 return (-1);
176 (void) cond_init(ch->cond, USYNC_THREAD, NULL);
178 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
179 (me, "slot %d allocated\n", s);
180 } else
181 ch = child[s];
183 ch->child_slot = s;
184 ch->child_door = 0;
185 ch->child_state = CHILD_STATE_NONE;
186 ch->child_pid = 0;
187 ch->child_uid = 0;
188 ch->child_gid = 0;
189 ch->next_open = -1;
191 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
192 (me, "slot %d initialized\n", s);
194 return (0);
197 static int
198 _nscd_init_cslots()
200 (void) mutex_lock(&child_lock);
202 child = (child_t **)calloc(max_pu_nscd, sizeof (child_t *));
203 if (child == NULL)
204 return (-1);
206 open_head = -1;
207 open_tail = -1;
208 used_slot = -1;
210 (void) mutex_unlock(&child_lock);
212 return (0);
215 static child_t *
216 get_cslot(
217 uid_t uid,
218 int no_alloc)
220 int i;
221 child_t *ch, *ret = NULL;
222 char *me = "get_cslot";
224 (void) mutex_lock(&child_lock);
226 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
227 (me, "looking for uid %d (slot used = %d)\n", uid, used_slot);
229 /* first find the slot with a matching uid */
230 for (i = 0; i <= used_slot; i++) {
231 ch = child[i];
232 if (ch->child_state >= CHILD_STATE_UIDKNOWN &&
233 ch->child_uid == uid) {
234 ret = ch;
235 (void) mutex_unlock(&child_lock);
237 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
238 (me, "slot %d found with uid %d\n",
239 ret->child_slot, ret->child_uid);
241 return (ret);
245 /* if no need to allocate a new slot, return NULL */
246 if (no_alloc == 1) {
247 (void) mutex_unlock(&child_lock);
248 return (ret);
251 /* no open slot ? get a new one */
252 if (open_head == -1) {
253 /* if no slot available, allocate more */
254 if (used_slot >= max_pu_nscd - 1) {
255 child_t **tmp;
256 int newmax = max_pu_nscd + _NSCD_PUN_BLOCK;
258 tmp = (child_t **)calloc(newmax, sizeof (child_t *));
259 if (tmp == NULL) {
260 (void) mutex_unlock(&child_lock);
261 return (ret);
263 (void) memcpy(tmp, child, sizeof (child_t) *
264 max_pu_nscd);
265 free(child);
266 child = tmp;
267 max_pu_nscd = newmax;
269 used_slot++;
270 if (init_slot(used_slot) == -1) {
271 used_slot--;
272 (void) mutex_unlock(&child_lock);
273 return (ret);
275 ch = child[used_slot];
276 } else {
277 ch = child[open_head];
278 open_head = ch->next_open;
279 /* got last one ? reset tail */
280 if (open_head == -1)
281 open_tail = -1;
282 ch->next_open = -1;
285 ch->child_uid = uid;
286 ch->child_state = CHILD_STATE_UIDKNOWN;
287 ret = ch;
289 (void) mutex_unlock(&child_lock);
291 return (ret);
294 static void
295 return_cslot_nolock(child_t *ch)
298 int slot = ch->child_slot;
300 /* have open slot ? add to and reset tail */
301 if (open_tail != -1) {
302 child[open_tail]->next_open = slot;
303 open_tail = slot;
304 } else {
305 /* no open slot ? make one */
306 open_head = open_tail = slot;
309 (void) init_slot(ch->child_slot);
312 static void
313 return_cslot(child_t *ch)
316 char *me = "return_cslot";
318 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
319 (me, "returning slot %d\n", ch->child_slot);
321 /* return if the slot has been returned by another thread */
322 if (ch->child_state == CHILD_STATE_NONE)
323 return;
325 (void) mutex_lock(&child_lock);
327 /* check one more time */
328 if (ch->child_state == CHILD_STATE_NONE) {
329 (void) mutex_unlock(&child_lock);
330 return;
333 return_cslot_nolock(ch);
335 (void) mutex_unlock(&child_lock);
338 static int
339 selfcred_kill(
340 int fd)
342 int ret;
343 char *me = "selfcred_kill";
345 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
346 (me, "sending kill to door %d\n", fd);
348 if (fd != -1)
349 ret = _nscd_doorcall_fd(fd, NSCD_KILL, NULL, 0,
350 NULL, 0, NULL);
351 else
352 ret = _nscd_doorcall(NSCD_KILL);
354 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
355 (me, "kill request sent to door %d (rc = %d)\n", fd, ret);
357 return (ret);
361 void
362 _nscd_kill_forker()
364 (void) mutex_lock(&forking_lock);
365 if (forking_door != -1)
366 (void) selfcred_kill(forking_door);
367 forking_door = -1;
368 (void) mutex_unlock(&forking_lock);
371 void
372 _nscd_kill_all_children()
374 int i;
375 int ret;
376 char *me = "_nscd_kill_all_children";
378 (void) mutex_lock(&child_lock);
379 for (i = 0; i <= used_slot; i++) {
380 if (child[i] == NULL)
381 continue;
383 if (child[i]->child_state >= CHILD_STATE_PIDKNOWN) {
384 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
385 (me, "killing child process %d (doorfd %d)\n",
386 child[i]->child_pid, child[i]->child_door);
388 ret = selfcred_kill(child[i]->child_door);
390 if (ret != -1)
391 (void) kill(child[i]->child_pid, SIGTERM);
393 if (child[i]->child_state != CHILD_STATE_NONE)
394 (void) return_cslot_nolock(child[i]);
396 (void) mutex_unlock(&child_lock);
398 static int
399 selfcred_pulse(
400 int fd)
402 int ret;
403 char *me = "selfcred_pulse";
405 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
406 (me, "start monitoring door %d\n", fd);
408 ret = _nscd_doorcall_fd(fd, NSCD_PULSE |(_whoami & NSCD_WHOAMI),
409 NULL, 0, NULL, 0, NULL);
411 /* Close door because the other side exited. */
412 (void) close(fd);
414 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
415 (me, "door (%d) monitor exited (rc = %d)\n", fd, ret);
417 return (ret);
420 /*ARGSUSED*/
421 static void *
422 forker_monitor(
423 void *arg)
425 pid_t fpid;
426 char *fmri;
427 char *me = "forker_monitor";
429 (void) thr_setname(thr_self(), me);
431 /* wait until forker exits */
432 fpid = forker_pid;
433 (void) selfcred_pulse(forking_door);
435 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
436 (me, "forker (pid = %d) exited or crashed, "
437 "killing all child processes\n", fpid);
439 (void) mutex_lock(&forking_lock);
440 forking_door = -1;
441 forker_pid = -1;
442 (void) mutex_unlock(&forking_lock);
444 /* forker exited/crashed, kill all the child processes */
445 _nscd_kill_all_children();
447 /* restart forker */
448 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
449 (me, "restarting the forker ...\n");
451 switch (fpid = fork1()) {
452 case (pid_t)-1:
453 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
454 (me, "unable to fork and start the forker ...\n");
456 /* enter the maintenance mode */
457 if ((fmri = getenv("SMF_FMRI")) != NULL) {
458 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
459 (me, "entering maintenance mode ...\n");
460 (void) smf_maintain_instance(fmri, SMF_TEMPORARY);
462 return ((void *)1);
463 case 0:
464 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
465 (me, "execv path = %s\n", execpath);
467 (void) execv(execpath, execargv);
468 exit(0);
469 default:
470 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
471 (me, "new forker's pid is %d\n", fpid);
472 forker_pid = fpid;
473 break;
476 return (NULL);
479 static void *
480 child_monitor(
481 void *arg)
483 child_t *ch = (child_t *)arg;
484 pid_t cpid;
485 char *me = "child_monitor";
487 /* wait until child exits */
488 cpid = ch->child_pid;
489 (void) selfcred_pulse(ch->child_door);
491 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
492 (me, "child (pid = %d) exited or crashed ...\n", cpid);
494 /* return the slot used by the child */
495 return_cslot(ch);
497 return (NULL);
501 void
502 _nscd_proc_iamhere(
503 void *buf,
504 door_desc_t *dp,
505 uint_t n_desc,
506 int iam)
508 int cslot;
509 child_t *ch;
510 int errnum;
511 ucred_t *uc = NULL;
512 uid_t uid;
513 nscd_imhere_t *ih;
514 nss_pheader_t *phdr = (nss_pheader_t *)buf;
515 char *me = "_nscd_proc_iamhere";
518 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
519 (me, "%d receives iamhere from %d\n", _whoami, iam);
521 if (door_ucred(&uc) != 0) {
522 errnum = errno;
523 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
524 (me, "door_ucred failed: %s\n", strerror(errnum));
526 NSCD_SET_N2N_STATUS(phdr, NSS_NSCD_PRIV, errnum,
527 NSCD_DOOR_UCRED_ERROR);
528 return;
530 uid = ucred_geteuid(uc);
532 switch (iam) {
534 case NSCD_MAIN:
535 if (_whoami == NSCD_MAIN || uid != main_uid) {
537 * I'm main, or uid from door is not correct,
538 * this must be an imposter
540 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
541 (me, "MAIN IMPOSTER CAUGHT!\n");
544 NSCD_SET_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0,
545 NSCD_SELF_CRED_MAIN_IMPOSTER);
547 break;
549 case NSCD_FORKER:
550 if (_whoami == NSCD_FORKER || uid != forker_uid) {
552 * I'm forker, or uid from door is not correct,
553 * this must be an imposter
555 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
556 (me, "FORKER IMPOSTER CAUGHT!\n");
559 NSCD_SET_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0,
560 NSCD_SELF_CRED_FORKER_IMPOSTER);
561 break;
564 /* only main needs to know the forker */
565 if (_whoami != NSCD_MAIN) {
567 NSCD_SET_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0,
568 NSCD_SELF_CRED_WRONG_NSCD);
569 break;
572 if (ucred_getpid(uc) != forker_pid) {
573 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
574 (me, "FORKER IMPOSTER CAUGHT: pid = %d should be %d\n",
575 ucred_getpid(uc), forker_pid);
578 NSCD_SET_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0,
579 NSCD_SELF_CRED_FORKER_IMPOSTER);
580 break;
583 if (n_desc < 1) {
584 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
585 (me, "BAD FORKER, NO DOOR!\n");
588 NSCD_SET_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0,
589 NSCD_SELF_CRED_NO_DOOR);
590 break;
593 if ((dp->d_attributes & DOOR_DESCRIPTOR) &&
594 dp->d_data.d_desc.d_descriptor > 0 &&
595 dp->d_data.d_desc.d_id != 0) {
596 (void) mutex_lock(&forking_lock);
597 if (forking_door != -1)
598 (void) close(forking_door);
599 forking_door = dp->d_data.d_desc.d_descriptor;
600 (void) mutex_unlock(&forking_lock);
602 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
603 (me, "forking door is %d\n", forking_door);
605 NSCD_SET_STATUS_SUCCESS(phdr);
606 } else {
607 NSCD_SET_STATUS(phdr, NSS_ALTRETRY, 0);
608 break;
611 /* monitor the forker nscd */
612 (void) thr_create(NULL, 0, forker_monitor, NULL,
613 THR_DETACHED, NULL);
615 break;
617 case NSCD_CHILD:
618 if (_whoami != NSCD_MAIN) {
619 /* child nscd can only talk to the main nscd */
620 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
621 (me, "CHILD IMPOSTER CAUGHT!\n");
623 NSCD_SET_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0,
624 NSCD_SELF_CRED_CHILD_IMPOSTER);
625 break;
628 /* get the main nscd assigned slot number */
629 ih = NSCD_N2N_DOOR_DATA(nscd_imhere_t, buf);
630 cslot = ih->slot;
631 (void) mutex_lock(&child_lock);
632 if (cslot < 0 || cslot >= max_pu_nscd)
633 ch = NULL;
634 else
635 ch = child[cslot];
636 (void) mutex_unlock(&child_lock);
638 if (ch == NULL) {
639 /* Bad slot number */
640 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
641 (me, "bad slot number %d\n", cslot);
643 NSCD_SET_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0,
644 NSCD_SELF_CRED_INVALID_SLOT_NUMBER);
645 break;
648 if (uid != ch->child_uid) {
649 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
650 (me, "CHILD IMPOSTER CAUGHT: uid = %d should be %d\n",
651 uid, ch->child_uid);
653 NSCD_SET_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0,
654 NSCD_SELF_CRED_CHILD_IMPOSTER);
655 break;
658 if (ch->child_state != CHILD_STATE_UIDKNOWN &&
659 ch->child_state != CHILD_STATE_FORKSENT) {
660 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
661 (me, "invalid slot/child state (%d) for uid %d\n",
662 ch->child_state, uid);
664 NSCD_SET_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0,
665 NSCD_SELF_CRED_INVALID_SLOT_STATE);
666 break;
669 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
670 (me, "d_descriptor = %d, d_id = %lld\n",
671 dp->d_data.d_desc.d_descriptor, dp->d_data.d_desc.d_id);
673 if ((dp->d_attributes & DOOR_DESCRIPTOR) &&
674 dp->d_data.d_desc.d_descriptor > 0 &&
675 dp->d_data.d_desc.d_id != 0) {
676 (void) mutex_lock(ch->mutex);
677 if (ch->child_door != -1)
678 (void) close(ch->child_door);
679 ch->child_door = dp->d_data.d_desc.d_descriptor;
680 ch->child_pid = ucred_getpid(uc);
681 ch->child_state = CHILD_STATE_PIDKNOWN;
682 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
683 (me, "child in slot %d has door %d\n",
684 cslot, ch->child_door);
687 * let waiters know that the child is ready to
688 * serve
690 (void) cond_broadcast(ch->cond);
691 (void) mutex_unlock(ch->mutex);
693 /* monitor the child nscd */
694 (void) thr_create(NULL, 0, child_monitor,
695 ch, THR_DETACHED, NULL);
696 NSCD_SET_STATUS_SUCCESS(phdr);
697 break;
698 } else {
699 NSCD_SET_STATUS(phdr, NSS_ALTRETRY, 0);
701 break;
704 ucred_free(uc);
705 uc = NULL;
708 void
709 _nscd_proc_pulse(
710 void *buf,
711 int iam)
713 long last_active;
714 int done = 0;
715 nss_pheader_t *phdr = (nss_pheader_t *)buf;
716 char *me = "_nscd_proc_pulse";
718 /* only main nscd sends pulse */
719 if (iam != NSCD_MAIN) {
720 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
721 (me, "MAIN IMPOSTER CAUGHT! i am %d not NSCD_MAIN\n", iam);
723 NSCD_SET_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0,
724 NSCD_SELF_CRED_MAIN_IMPOSTER);
725 return;
728 /* forker doesn't return stats, it just pauses */
729 if (_whoami == NSCD_FORKER) {
730 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
731 (me, "forker ready to pause ...\n");
733 for (;;)
734 (void) pause();
737 /* remember the current activity sequence number */
738 (void) mutex_lock(&activity_lock);
739 last_active = activity;
740 (void) mutex_unlock(&activity_lock);
742 while (!done) {
744 /* allow per_user_nscd_ttl seconds of inactivity */
745 (void) sleep(pu_nscd_ttl);
747 (void) mutex_lock(&activity_lock);
748 if (last_active == activity)
749 done = 1;
750 else {
751 last_active = activity;
752 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
753 (me, "active, sleep again for %d seconds\n",
754 pu_nscd_ttl);
756 (void) mutex_unlock(&activity_lock);
759 /* no activity in the specified seconds, exit and disconnect */
760 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
761 (me, "no activity in the last %d seconds, exit\n", pu_nscd_ttl);
762 exit(0);
765 void
766 _nscd_proc_fork(
767 void *buf,
768 int iam)
770 int slot;
771 int ret;
772 char *fmri;
773 pid_t cid;
774 uid_t set2uid;
775 gid_t set2gid;
776 nss_pheader_t *phdr = (nss_pheader_t *)buf;
777 char *me = "_nscd_proc_fork";
778 nscd_fork_t *f;
779 nscd_imhere_t ih;
781 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
782 (me, "%d receives fork request from %d\n", _whoami, iam);
784 /* only main nscd sends fork requests */
785 if (iam != NSCD_MAIN) {
786 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
787 (me, "MAIN IMPOSTER CAUGHT! i am %d not NSCD_MAIN\n", iam);
789 NSCD_SET_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0,
790 NSCD_SELF_CRED_MAIN_IMPOSTER);
791 return;
794 /* only forker handles fork requests */
795 if (_whoami != NSCD_FORKER) {
796 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
797 (me, "MAIN IMPOSTER CAUGHT! I AM NOT FORKER!\n");
799 NSCD_SET_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0,
800 NSCD_SELF_CRED_WRONG_NSCD);
801 return;
804 /* fork a child for the slot assigned by the main nscd */
805 f = NSCD_N2N_DOOR_DATA(nscd_fork_t, buf);
806 slot = f->slot;
807 /* set the uid/gid as assigned by the main nscd */
808 set2uid = f->uid;
809 set2gid = f->gid;
811 /* ignore bad slot number */
812 if (slot < 0 || slot >= max_pu_nscd) {
813 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
814 (me, "bas slot number\n");
816 NSCD_SET_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0,
817 NSCD_SELF_CRED_INVALID_SLOT_NUMBER);
818 return;
821 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
822 (me, "before fork1() ...\n");
824 if ((cid = fork1()) == 0) {
825 _whoami = NSCD_CHILD;
828 * remember when this child nscd starts
829 * (replace the forker start time)
831 _nscd_set_start_time(1);
833 /* close all except the log file */
834 if (_logfd > 0) {
835 int i;
836 for (i = 0; i < _logfd; i++)
837 (void) close(i);
838 closefrom(_logfd + 1);
839 } else
840 closefrom(0);
842 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
843 (me, "child %d\n", getpid());
845 (void) setgid(set2gid);
846 (void) setuid(set2uid);
848 /* set up the door and server thread pool */
849 if ((_doorfd = _nscd_setup_child_server(_doorfd)) == -1)
850 exit(-1);
852 /* tell libsldap to do self cred only */
853 (void) setup_ldap_backend();
855 /* notify main that child is active */
856 ih.slot = slot;
857 for (ret = NSS_ALTRETRY; ret == NSS_ALTRETRY; )
858 ret = _nscd_doorcall_sendfd(_doorfd,
859 NSCD_IMHERE | (NSCD_CHILD & NSCD_WHOAMI),
860 &ih, sizeof (ih), NULL);
862 NSCD_SET_STATUS_SUCCESS(phdr);
863 return;
864 } if (cid == (pid_t)-1) {
865 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
866 (me, "forker unable to fork ...\n");
868 /* enter the maintenance mode */
869 if ((fmri = getenv("SMF_FMRI")) != NULL) {
870 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
871 (me, "entering maintenance mode ...\n");
872 (void) smf_maintain_instance(fmri, SMF_TEMPORARY);
874 exit(0);
875 } else {
877 * start the monitor so as to exit as early as
878 * possible if no other processes are running
879 * with the same PUN uid (i.e., this PUN is
880 * not needed any more)
882 (void) init_user_proc_monitor();
884 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
885 (me, "child forked: parent pid = %d, child pid = %d\n",
886 getpid(), cid);
888 NSCD_SET_STATUS_SUCCESS(phdr);
891 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
892 (me, "after fork\n");
895 static void
896 selfcred_fork(
897 void *buf,
898 int doorfd,
899 int cslot,
900 uid_t uid,
901 gid_t gid)
903 int ret;
904 nscd_fork_t f;
905 nss_pheader_t *phdr = (nss_pheader_t *)buf;
906 char *me = "selfcred_fork";
908 /* if no door fd, do nothing */
909 if (doorfd == -1) {
910 NSCD_SET_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0,
911 NSCD_SELF_CRED_NO_DOOR);
914 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
915 (me, "sending fork request to door %d for slot %d "
916 "(uid = %d, gid = %d)\n", doorfd, cslot, uid, gid);
918 f.slot = cslot;
919 f.uid = uid;
920 f.gid = gid;
922 ret = _nscd_doorcall_fd(doorfd, NSCD_FORK|(_whoami&NSCD_WHOAMI),
923 &f, sizeof (f), NULL, 0, phdr);
925 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
926 (me, "fork request sent to door %d for slot %d (rc = %d)\n",
927 doorfd, cslot, ret);
929 if (NSCD_STATUS_IS_NOT_OK(phdr)) {
931 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
932 (me, "fork request sent to door %d for slot %d failed: "
933 "status = %d, errno = %s, nscd status = %d\n", doorfd,
934 cslot, NSCD_GET_STATUS(phdr),
935 strerror(NSCD_GET_ERRNO(phdr)),
936 NSCD_GET_NSCD_STATUS(phdr));
941 void
942 _nscd_proc_alt_get(
943 void *buf,
944 int *door)
946 int errnum;
947 uid_t set2uid;
948 gid_t set2gid;
949 nss_pheader_t *phdr = (nss_pheader_t *)buf;
950 char *me = "_nscd_proc_alt_get";
951 ucred_t *uc = NULL;
952 child_t *ch;
954 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
955 (me, "getting an alternate door ...\n");
957 /* make sure there is a door to talk to the forker */
958 if (forking_door == -1) {
959 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_ERROR)
960 (me, "no door to talk to the forker\n");
962 NSCD_SET_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0,
963 NSCD_SELF_CRED_NO_FORKER);
964 return;
967 /* get door client's credential information */
968 if (door_ucred(&uc) != 0) {
969 errnum = errno;
970 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
971 (me, "door_ucred failed: %s\n", strerror(errnum));
973 NSCD_SET_N2N_STATUS(phdr, NSS_NSCD_PRIV, errnum,
974 NSCD_DOOR_UCRED_ERROR);
975 return;
978 /* get door client's effective uid and effective gid */
979 set2uid = ucred_geteuid(uc);
980 set2gid = ucred_getegid(uc);
981 ucred_free(uc);
982 uc = NULL;
984 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
985 (me, "child uid = %d, gid = %d\n", set2uid, set2gid);
987 /* is a slot available ? if not, no one to serve */
988 if (child == NULL || (ch = get_cslot(set2uid, 0)) == NULL) {
990 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
991 (me, "no child slot available (child array = %p, slot = %d)\n",
992 child, ch->child_slot);
994 NSCD_SET_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0,
995 NSCD_SELF_CRED_NO_CHILD_SLOT);
996 return;
999 /* create the per user nscd if necessary */
1000 if (ch->child_state != CHILD_STATE_PIDKNOWN) {
1002 nss_pheader_t phdr1;
1003 NSCD_CLEAR_STATUS(&phdr1);
1005 (void) mutex_lock(ch->mutex);
1006 if (ch->child_state == CHILD_STATE_UIDKNOWN) {
1008 /* ask forker to fork a new child */
1009 selfcred_fork(&phdr1, forking_door, ch->child_slot,
1010 set2uid, set2gid);
1011 if (NSCD_STATUS_IS_NOT_OK(&phdr1)) {
1012 (void) mutex_unlock(ch->mutex);
1013 NSCD_COPY_STATUS(phdr, &phdr1);
1014 return;
1016 ch->child_state = CHILD_STATE_FORKSENT;
1019 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
1020 (me, "waiting for door (slot = %d, uid = %d, gid = %d)\n",
1021 ch->child_slot, set2uid, set2gid);
1023 /* wait for the per user nscd to become available */
1024 while (ch->child_state == CHILD_STATE_FORKSENT) {
1025 timestruc_t to;
1026 int err;
1027 int ttl = 5;
1029 to.tv_sec = ttl;
1030 to.tv_nsec = 0;
1031 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
1032 (me, "cond_reltimedwait %d seconds\n", ttl);
1033 err = cond_reltimedwait(ch->cond, ch->mutex, &to);
1034 if (err == ETIME) {
1035 ch->child_state = CHILD_STATE_UIDKNOWN;
1036 _NSCD_LOG(NSCD_LOG_SELF_CRED,
1037 NSCD_LOG_LEVEL_DEBUG)
1038 (me, "door wait timedout (slot = %d)\n",
1039 ch->child_slot);
1040 break;
1043 (void) mutex_unlock(ch->mutex);
1046 if (ch->child_state != CHILD_STATE_PIDKNOWN) {
1048 NSCD_SET_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0,
1049 NSCD_SELF_CRED_INVALID_SLOT_STATE);
1050 return;
1053 *door = ch->child_door;
1055 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
1056 (me, "returning door %d for slot %d, uid %d, gid = %d\n",
1057 *door, ch->child_slot, set2uid, set2gid);
1059 NSCD_SET_STATUS(phdr, NSS_ALTRETRY, 0);
1062 static char **
1063 cpargv(
1064 int argc,
1065 char **inargv)
1067 char **newargv;
1068 int c = 4;
1069 int i = 0, j, k = 0, n = 0;
1071 newargv = (char **)calloc(c + 1, sizeof (char *));
1072 if (newargv == NULL)
1073 return (NULL);
1075 newargv[n] = strdup(inargv[0]);
1076 if (newargv[n++] == NULL) {
1077 free(newargv);
1078 return (NULL);
1081 newargv[n] = strdup("-F");
1082 if (newargv[n++] == NULL) {
1083 free(newargv[0]);
1084 free(newargv);
1085 return (NULL);
1088 for (i = 1; i < argc; i++) {
1089 if (strcmp(inargv[i], "-f") == 0)
1090 k = 2;
1091 if (k == 0)
1092 continue;
1094 newargv[n] = strdup(inargv[i]);
1095 if (newargv[n] == NULL) {
1096 for (j = 0; j < n; j++)
1097 free(newargv[j]);
1098 free(newargv);
1099 return (NULL);
1102 k--;
1103 n++;
1105 return (newargv);
1109 void
1110 _nscd_start_forker(
1111 char *path,
1112 int argc,
1113 char **argv)
1115 pid_t cid;
1117 /* if self cred is not configured, do nothing */
1118 if (!_nscd_is_self_cred_on(1, NULL))
1119 return;
1121 /* save pathname and generate the new argv for the forker */
1122 execpath = strdup(path);
1123 execargv = cpargv(argc, argv);
1124 if (execpath == NULL || execargv == NULL)
1125 exit(1);
1127 switch (cid = fork1()) {
1128 case (pid_t)-1:
1129 exit(1);
1130 break;
1131 case 0:
1132 /* start the forker nscd */
1133 (void) execv(path, execargv);
1134 exit(0);
1135 break;
1136 default:
1137 /* main nscd */
1138 /* remember process id of the forker */
1139 forker_pid = cid;
1141 /* enable child nscd management */
1142 (void) _nscd_init_cslots();
1143 break;
1147 static nscd_rc_t
1148 get_ldap_funcs(
1149 char *name,
1150 void **func_p)
1152 char *me = "get_ldap_funcs";
1153 static void *handle = NULL;
1154 void *sym;
1156 if (name == NULL && handle != NULL) {
1157 (void) dlclose(handle);
1158 return (NSCD_SUCCESS);
1160 /* no handle to close, it's OK */
1161 if (name == NULL)
1162 return (NSCD_SUCCESS);
1164 if (handle == NULL) {
1165 handle = dlopen("libsldap.so.1", RTLD_LAZY);
1166 if (handle == NULL) {
1168 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_ERROR)
1169 (me, "unable to dlopen libsldap.so.1");
1170 return (NSCD_CFG_DLOPEN_ERROR);
1174 if ((sym = dlsym(handle, name)) == NULL) {
1176 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_ERROR)
1177 (me, "unable to find symbol %s", name);
1178 return (NSCD_CFG_DLSYM_ERROR);
1179 } else
1180 (void) memcpy(func_p, &sym, sizeof (void *));
1182 return (NSCD_SUCCESS);
1187 _nscd_is_self_cred_on(int recheck, char **dblist)
1189 static int checked = 0;
1190 static int is_on = 0;
1191 static int (*ldap_func)();
1192 char *srcs = "ldap"; /* only ldap support self cred */
1193 int ldap_on = 0;
1195 char *ldap_sc_func = "__ns_ldap_self_gssapi_config";
1196 ns_ldap_self_gssapi_config_t ldap_config;
1198 if (checked && !recheck) {
1199 if (is_on && dblist != NULL)
1200 *dblist = selfcred_dbs;
1201 return (is_on);
1204 if (selfcred_dbs != NULL)
1205 free(selfcred_dbs);
1206 selfcred_dbs = _nscd_srcs_in_db_nsw_policy(1, &srcs);
1208 if (selfcred_dbs == NULL) {
1209 is_on = 0;
1210 checked = 1;
1211 return (0);
1215 * also check the ldap backend to see if
1216 * the configuration there is good for
1217 * doing self credentialing
1219 if (ldap_func == NULL)
1220 (void) get_ldap_funcs(ldap_sc_func, (void **)&ldap_func);
1221 if (ldap_func != NULL) {
1222 if (ldap_func(&ldap_config) == NS_LDAP_SUCCESS &&
1223 ldap_config != NS_LDAP_SELF_GSSAPI_CONFIG_NONE)
1224 ldap_on = 1;
1227 is_on = (pu_nscd_enabled == nscd_true) && ldap_on;
1229 checked = 1;
1231 if (is_on && dblist != NULL)
1232 *dblist = selfcred_dbs;
1234 return (is_on);
1237 static nscd_rc_t
1238 setup_ldap_backend()
1240 nscd_rc_t rc;
1241 static void (*ldap_func)();
1242 char *ldap_sc_func = "__ns_ldap_self_gssapi_only_set";
1243 if (ldap_func == NULL)
1244 rc = get_ldap_funcs(ldap_sc_func, (void **)&ldap_func);
1245 if (ldap_func != NULL) {
1246 ldap_func(1);
1247 return (NSCD_SUCCESS);
1249 return (rc);
1252 /*ARGSUSED*/
1253 void
1254 _nscd_peruser_getadmin(
1255 void *buf,
1256 int buf_size)
1258 void *result_mn = NSCD_N2N_DOOR_DATA(void, buf);
1259 int errnum = 0;
1260 int ret;
1261 uid_t uid;
1262 nss_pheader_t *phdr = (nss_pheader_t *)buf;
1263 char *me = "_nscd_peruser_getadmin";
1264 ucred_t *uc = NULL;
1265 child_t *ch;
1267 /* get door client's credential information */
1268 if (door_ucred(&uc) != 0) {
1269 errnum = errno;
1270 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
1271 (me, "door_ucred failed: %s\n", strerror(errnum));
1273 NSCD_SET_N2N_STATUS(phdr, NSS_NSCD_PRIV, errnum,
1274 NSCD_DOOR_UCRED_ERROR);
1275 return;
1278 /* get door client's effective uid */
1279 uid = ucred_geteuid(uc);
1280 ucred_free(uc);
1281 uc = NULL;
1283 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
1284 (me, "per user get admin ... (uid = %d)\n", uid);
1286 /* is the per-user nscd running ? if not, no one to serve */
1287 ch = get_cslot(uid, 1);
1288 if (ch == NULL) {
1289 NSCD_SET_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0,
1290 NSCD_SELF_CRED_NO_CHILD_SLOT);
1291 return;
1294 ret = _nscd_doorcall_fd(ch->child_door, NSCD_GETADMIN,
1295 NULL, sizeof (nscd_admin_t), result_mn,
1296 sizeof (nscd_admin_t), phdr);
1298 if (ret == NSS_SUCCESS) {
1299 phdr->data_len = sizeof (nscd_admin_t);
1300 return;
1304 static void
1305 set_selfcred_cfg(
1306 char param,
1307 void *data)
1309 int64_t prop_int;
1310 uint8_t prop_boolean;
1311 char *me = "set_selfcred_cfg";
1313 if (param == 'e') {
1314 prop_boolean = *(uint8_t *)data;
1315 pu_nscd_enabled = *(uint8_t *)get_smf_prop(
1316 "enable_per_user_lookup", 'b', &prop_boolean);
1318 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
1319 (me, "self cred config: enabled = %d\n", pu_nscd_enabled);
1322 if (param == 't') {
1323 prop_int = *(int *)data;
1324 pu_nscd_ttl = *(int64_t *)get_smf_prop(
1325 "per_user_nscd_time_to_live", 'i', &prop_int);
1327 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
1328 (me, "self cred config: PUN TTL = %d\n", pu_nscd_ttl);
1332 /* ARGSUSED */
1333 nscd_rc_t
1334 _nscd_cfg_selfcred_notify(
1335 void *data,
1336 struct nscd_cfg_param_desc *pdesc,
1337 nscd_cfg_id_t *nswdb,
1338 nscd_cfg_flag_t dflag,
1339 nscd_cfg_error_t **errorp,
1340 void *cookie)
1343 nscd_cfg_global_selfcred_t *sc_cfg = &nscd_selfcred_cfg_g;
1344 int off;
1347 * At init time, the whole group of config params are received.
1348 * At update time, group or individual parameter value could
1349 * be received.
1352 if (_nscd_cfg_flag_is_set(dflag, NSCD_CFG_DFLAG_GROUP)) {
1354 *sc_cfg = *(nscd_cfg_global_selfcred_t *)data;
1356 off = offsetof(nscd_cfg_global_selfcred_t,
1357 enable_selfcred);
1358 set_selfcred_cfg('e', (char *)data + off);
1360 off = offsetof(nscd_cfg_global_selfcred_t,
1361 per_user_nscd_ttl);
1362 set_selfcred_cfg('t', (char *)data + off);
1364 return (NSCD_SUCCESS);
1368 * individual config parameter
1370 off = offsetof(nscd_cfg_global_selfcred_t, enable_selfcred);
1371 if (pdesc->p_offset == off) {
1372 sc_cfg->enable_selfcred = *(nscd_bool_t *)data;
1373 set_selfcred_cfg('e', data);
1374 return (NSCD_SUCCESS);
1377 off = offsetof(nscd_cfg_global_selfcred_t, per_user_nscd_ttl);
1378 if (pdesc->p_offset == off) {
1379 sc_cfg->per_user_nscd_ttl = *(int *)data;
1380 set_selfcred_cfg('t', data);
1381 return (NSCD_SUCCESS);
1384 return (NSCD_SUCCESS);
1387 /* ARGSUSED */
1388 nscd_rc_t
1389 _nscd_cfg_selfcred_verify(
1390 void *data,
1391 struct nscd_cfg_param_desc *pdesc,
1392 nscd_cfg_id_t *nswdb,
1393 nscd_cfg_flag_t dflag,
1394 nscd_cfg_error_t **errorp,
1395 void **cookie)
1398 return (NSCD_SUCCESS);
1401 /* ARGSUSED */
1402 nscd_rc_t
1403 _nscd_cfg_selfcred_get_stat(
1404 void **stat,
1405 struct nscd_cfg_stat_desc *sdesc,
1406 nscd_cfg_id_t *nswdb,
1407 nscd_cfg_flag_t *dflag,
1408 void (**free_stat)(void *stat),
1409 nscd_cfg_error_t **errorp)
1411 return (NSCD_SUCCESS);
1414 static int
1415 check_uid(char *pid_name)
1417 char pname[PATH_MAX];
1418 static pid_t pid = 0;
1419 static uid_t uid = 0;
1420 static uid_t euid = 0;
1421 int pfd; /* file descriptor for /proc/<pid>/psinfo */
1422 psinfo_t info; /* process information from /proc */
1424 if (uid == 0) {
1425 pid = getpid();
1426 uid = getuid();
1427 euid = geteuid();
1430 (void) snprintf(pname, sizeof (pname), "/proc/%s/psinfo", pid_name);
1431 retry:
1432 if ((pfd = open(pname, O_RDONLY)) == -1) {
1433 /* Process may have exited */
1434 return (1);
1438 * Get the info structure for the process and close quickly.
1440 if (read(pfd, (char *)&info, sizeof (info)) < 0) {
1441 int saverr = errno;
1443 (void) close(pfd);
1444 if (saverr == EAGAIN)
1445 goto retry;
1446 if (saverr != ENOENT)
1447 return (1);
1449 (void) close(pfd);
1451 if (info.pr_pid != pid &&
1452 info.pr_uid == uid && info.pr_euid == euid)
1453 return (0);
1454 else
1455 return (1);
1460 * FUNCTION: check_user_process
1462 /*ARGSUSED*/
1463 static void *
1464 check_user_process(void *arg)
1467 DIR *dp;
1468 struct dirent *ep;
1469 int found;
1470 char *me = "check_user_process";
1472 (void) thr_setname(thr_self(), me);
1474 for (;;) {
1475 (void) sleep(60);
1477 found = 0;
1480 * search the /proc directory and look at each process
1482 if ((dp = opendir("/proc")) == NULL) {
1483 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_ERROR)
1484 (me, "unable to open the /proc directory\n");
1485 continue;
1488 /* for each active process */
1489 while (ep = readdir(dp)) {
1490 if (ep->d_name[0] == '.') /* skip . and .. */
1491 continue;
1492 if (check_uid(ep->d_name) == 0) {
1493 found = 1;
1494 break;
1499 * if no process running as the PUN uid found, exit
1500 * to kill this PUN
1502 if (found == 0) {
1503 (void) closedir(dp);
1504 exit(1);
1506 (void) closedir(dp);
1508 /*LINTED E_FUNC_HAS_NO_RETURN_STMT*/
1511 static nscd_rc_t
1512 init_user_proc_monitor() {
1514 int errnum;
1515 char *me = "init_user_proc_monitor";
1517 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
1518 (me, "initializing the user process monitor\n");
1521 * start a thread to make sure there is at least a process
1522 * running as the PUN user. If not, terminate this PUN.
1524 if (thr_create(NULL, NULL, check_user_process,
1525 NULL, THR_DETACHED, NULL) != 0) {
1526 errnum = errno;
1527 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_ERROR)
1528 (me, "thr_create: %s\n", strerror(errnum));
1529 return (NSCD_THREAD_CREATE_ERROR);
1532 return (NSCD_SUCCESS);
1535 static void *
1536 get_smf_prop(const char *var, char type, void *def_val)
1538 scf_simple_prop_t *prop;
1539 void *val;
1540 char *me = "get_smf_prop";
1542 prop = scf_simple_prop_get(NULL, NULL, "config", var);
1543 if (prop) {
1544 switch (type) {
1545 case 'b':
1546 val = scf_simple_prop_next_boolean(prop);
1547 if (val != NULL)
1548 (void) memcpy(def_val, val, sizeof (uint8_t));
1549 break;
1551 case 'i':
1552 val = scf_simple_prop_next_integer(prop);
1553 if (val != NULL)
1554 (void) memcpy(def_val, val, sizeof (int64_t));
1555 break;
1557 scf_simple_prop_free(prop);
1560 if (prop == NULL || val == NULL) {
1561 char vs[64];
1563 switch (type) {
1564 case 'b':
1565 if (*(uint8_t *)def_val)
1566 (void) strcpy(vs, "yes");
1567 else
1568 (void) strcpy(vs, "no");
1570 break;
1572 case 'i':
1573 (void) sprintf(vs, "%lld", *(int64_t *)def_val);
1574 break;
1577 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_ALERT)
1578 (me, "no value for config/%s (%s). "
1579 "Using default \"%s\"\n", var,
1580 scf_strerror(scf_error()), vs);
1583 return (def_val);