xref: /titanic_53/usr/src/cmd/nscd/nscd_selfcred.c (revision cb5caa98562cf06753163f558cbcfe30b8f4673a)
1*cb5caa98Sdjl /*
2*cb5caa98Sdjl  * CDDL HEADER START
3*cb5caa98Sdjl  *
4*cb5caa98Sdjl  * The contents of this file are subject to the terms of the
5*cb5caa98Sdjl  * Common Development and Distribution License (the "License").
6*cb5caa98Sdjl  * You may not use this file except in compliance with the License.
7*cb5caa98Sdjl  *
8*cb5caa98Sdjl  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*cb5caa98Sdjl  * or http://www.opensolaris.org/os/licensing.
10*cb5caa98Sdjl  * See the License for the specific language governing permissions
11*cb5caa98Sdjl  * and limitations under the License.
12*cb5caa98Sdjl  *
13*cb5caa98Sdjl  * When distributing Covered Code, include this CDDL HEADER in each
14*cb5caa98Sdjl  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*cb5caa98Sdjl  * If applicable, add the following below this CDDL HEADER, with the
16*cb5caa98Sdjl  * fields enclosed by brackets "[]" replaced with your own identifying
17*cb5caa98Sdjl  * information: Portions Copyright [yyyy] [name of copyright owner]
18*cb5caa98Sdjl  *
19*cb5caa98Sdjl  * CDDL HEADER END
20*cb5caa98Sdjl  */
21*cb5caa98Sdjl /*
22*cb5caa98Sdjl  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
23*cb5caa98Sdjl  * Use is subject to license terms.
24*cb5caa98Sdjl  */
25*cb5caa98Sdjl 
26*cb5caa98Sdjl #pragma ident	"%Z%%M%	%I%	%E% SMI"
27*cb5caa98Sdjl 
28*cb5caa98Sdjl #include <stdio.h>
29*cb5caa98Sdjl #include <stdlib.h>
30*cb5caa98Sdjl #include <synch.h>
31*cb5caa98Sdjl #include <thread.h>
32*cb5caa98Sdjl #include <string.h>
33*cb5caa98Sdjl #include <errno.h>
34*cb5caa98Sdjl #include <dlfcn.h>
35*cb5caa98Sdjl #include <door.h>
36*cb5caa98Sdjl #include <libscf.h>
37*cb5caa98Sdjl #include <ucred.h>
38*cb5caa98Sdjl #include <sys/varargs.h>
39*cb5caa98Sdjl #include <signal.h>
40*cb5caa98Sdjl #include <unistd.h>
41*cb5caa98Sdjl #include <sys/types.h>
42*cb5caa98Sdjl #include <dirent.h>
43*cb5caa98Sdjl #include <sys/proc.h>
44*cb5caa98Sdjl #include <procfs.h>
45*cb5caa98Sdjl #include <sys/stat.h>
46*cb5caa98Sdjl #include <fcntl.h>
47*cb5caa98Sdjl #include <limits.h>
48*cb5caa98Sdjl #include <sys/resource.h>
49*cb5caa98Sdjl #include <libscf.h>
50*cb5caa98Sdjl #include "nscd_door.h"
51*cb5caa98Sdjl #include "nscd_config.h"
52*cb5caa98Sdjl #include "nscd_log.h"
53*cb5caa98Sdjl #include "nscd_frontend.h"
54*cb5caa98Sdjl #include "nscd_selfcred.h"
55*cb5caa98Sdjl #include "nscd_admin.h"
56*cb5caa98Sdjl #include "nscd_common.h"
57*cb5caa98Sdjl #include "ns_sldap.h"
58*cb5caa98Sdjl 
59*cb5caa98Sdjl extern int	_logfd;
60*cb5caa98Sdjl static char	*execpath;
61*cb5caa98Sdjl static char	**execargv;
62*cb5caa98Sdjl static char	*selfcred_dbs = NULL;
63*cb5caa98Sdjl 
64*cb5caa98Sdjl static void *get_smf_prop(const char *var, char type, void *def_val);
65*cb5caa98Sdjl 
66*cb5caa98Sdjl /* current self-cred configuration data being used */
67*cb5caa98Sdjl static nscd_cfg_global_selfcred_t	nscd_selfcred_cfg_g;
68*cb5caa98Sdjl 
69*cb5caa98Sdjl #define	_NSCD_PUN_BLOCK	1024
70*cb5caa98Sdjl static uint8_t  pu_nscd_enabled;
71*cb5caa98Sdjl static int	max_pu_nscd = _NSCD_PUN_BLOCK;
72*cb5caa98Sdjl static int	pu_nscd_ttl;
73*cb5caa98Sdjl 
74*cb5caa98Sdjl static nscd_rc_t setup_ldap_backend();
75*cb5caa98Sdjl static nscd_rc_t init_user_proc_monitor();
76*cb5caa98Sdjl 
77*cb5caa98Sdjl /*
78*cb5caa98Sdjl  * clild state
79*cb5caa98Sdjl  */
80*cb5caa98Sdjl typedef enum {
81*cb5caa98Sdjl 	CHILD_STATE_NONE	= 0,
82*cb5caa98Sdjl 	CHILD_STATE_UIDKNOWN,
83*cb5caa98Sdjl 	CHILD_STATE_FORKSENT,
84*cb5caa98Sdjl 	CHILD_STATE_PIDKNOWN
85*cb5caa98Sdjl } child_state_t;
86*cb5caa98Sdjl 
87*cb5caa98Sdjl 
88*cb5caa98Sdjl typedef struct _child {
89*cb5caa98Sdjl 	int		child_slot;
90*cb5caa98Sdjl 	int		child_door;
91*cb5caa98Sdjl 	pid_t		child_pid;
92*cb5caa98Sdjl 	uid_t		child_uid;
93*cb5caa98Sdjl 	gid_t		child_gid;
94*cb5caa98Sdjl 	child_state_t	child_state;
95*cb5caa98Sdjl 	int		next_open;
96*cb5caa98Sdjl 	mutex_t		*mutex;
97*cb5caa98Sdjl 	cond_t		*cond;
98*cb5caa98Sdjl } child_t;
99*cb5caa98Sdjl 
100*cb5caa98Sdjl static child_t	**child = NULL;
101*cb5caa98Sdjl static mutex_t	child_lock = DEFAULTMUTEX;
102*cb5caa98Sdjl static int	open_head;
103*cb5caa98Sdjl static int	open_tail;
104*cb5caa98Sdjl static int	used_slot;
105*cb5caa98Sdjl 
106*cb5caa98Sdjl /* nscd door id */
107*cb5caa98Sdjl extern int _doorfd;
108*cb5caa98Sdjl static pid_t main_uid = 0;
109*cb5caa98Sdjl 
110*cb5caa98Sdjl /* nscd id: main, forker, or child */
111*cb5caa98Sdjl extern int _whoami;
112*cb5caa98Sdjl 
113*cb5caa98Sdjl /* forker nscd pid */
114*cb5caa98Sdjl static pid_t forker_pid = 0;
115*cb5caa98Sdjl static pid_t forker_uid = 0;
116*cb5caa98Sdjl 
117*cb5caa98Sdjl long		activity = 0;
118*cb5caa98Sdjl mutex_t		activity_lock = DEFAULTMUTEX;
119*cb5caa98Sdjl 
120*cb5caa98Sdjl static int	forking_door = -1;
121*cb5caa98Sdjl static mutex_t	forking_lock = DEFAULTMUTEX;
122*cb5caa98Sdjl 
123*cb5caa98Sdjl static void
124*cb5caa98Sdjl free_slot(int	s)
125*cb5caa98Sdjl {
126*cb5caa98Sdjl 	if (child[s] == NULL)
127*cb5caa98Sdjl 		return;
128*cb5caa98Sdjl 	free(child[s]->mutex);
129*cb5caa98Sdjl 	free(child[s]->cond);
130*cb5caa98Sdjl 	free(child[s]);
131*cb5caa98Sdjl 	child[s] = NULL;
132*cb5caa98Sdjl }
133*cb5caa98Sdjl 
134*cb5caa98Sdjl void
135*cb5caa98Sdjl _nscd_free_cslots()
136*cb5caa98Sdjl {
137*cb5caa98Sdjl 
138*cb5caa98Sdjl 	int i;
139*cb5caa98Sdjl 
140*cb5caa98Sdjl 	(void) mutex_lock(&child_lock);
141*cb5caa98Sdjl 
142*cb5caa98Sdjl 	for (i = 0; i < max_pu_nscd; i++)
143*cb5caa98Sdjl 		free_slot(i);
144*cb5caa98Sdjl 
145*cb5caa98Sdjl 	open_head = -1;
146*cb5caa98Sdjl 	open_tail = -1;
147*cb5caa98Sdjl 	used_slot = -1;
148*cb5caa98Sdjl 
149*cb5caa98Sdjl 	(void) mutex_unlock(&child_lock);
150*cb5caa98Sdjl 
151*cb5caa98Sdjl }
152*cb5caa98Sdjl 
153*cb5caa98Sdjl static int
154*cb5caa98Sdjl init_slot(int	s)
155*cb5caa98Sdjl {
156*cb5caa98Sdjl 	child_t	*ch;
157*cb5caa98Sdjl 	char	*me = "init_slot";
158*cb5caa98Sdjl 
159*cb5caa98Sdjl 	if (child[s] == NULL) {
160*cb5caa98Sdjl 		child[s] = (child_t *)calloc(1, sizeof (child_t));
161*cb5caa98Sdjl 		if (child[s] == NULL)
162*cb5caa98Sdjl 			return (-1);
163*cb5caa98Sdjl 		ch = child[s];
164*cb5caa98Sdjl 
165*cb5caa98Sdjl 		if ((ch->mutex = (mutex_t *)calloc(1,
166*cb5caa98Sdjl 			sizeof (mutex_t))) == NULL) {
167*cb5caa98Sdjl 			free(ch);
168*cb5caa98Sdjl 			return (-1);
169*cb5caa98Sdjl 		}
170*cb5caa98Sdjl 		(void) mutex_init(ch->mutex, USYNC_THREAD, NULL);
171*cb5caa98Sdjl 
172*cb5caa98Sdjl 		if ((ch->cond = (cond_t *)calloc(1,
173*cb5caa98Sdjl 			sizeof (cond_t))) == NULL) {
174*cb5caa98Sdjl 			free(ch->mutex);
175*cb5caa98Sdjl 			free(ch);
176*cb5caa98Sdjl 			return (-1);
177*cb5caa98Sdjl 		}
178*cb5caa98Sdjl 		(void) cond_init(ch->cond, USYNC_THREAD, NULL);
179*cb5caa98Sdjl 
180*cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
181*cb5caa98Sdjl 		(me, "slot %d allocated\n", s);
182*cb5caa98Sdjl 	} else
183*cb5caa98Sdjl 		ch = child[s];
184*cb5caa98Sdjl 
185*cb5caa98Sdjl 	ch->child_slot = s;
186*cb5caa98Sdjl 	ch->child_door = 0;
187*cb5caa98Sdjl 	ch->child_state = CHILD_STATE_NONE;
188*cb5caa98Sdjl 	ch->child_pid = 0;
189*cb5caa98Sdjl 	ch->child_uid = 0;
190*cb5caa98Sdjl 	ch->child_gid = 0;
191*cb5caa98Sdjl 	ch->next_open = -1;
192*cb5caa98Sdjl 
193*cb5caa98Sdjl 	_NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
194*cb5caa98Sdjl 	(me, "slot %d initialized\n", s);
195*cb5caa98Sdjl 
196*cb5caa98Sdjl 	return (0);
197*cb5caa98Sdjl }
198*cb5caa98Sdjl 
199*cb5caa98Sdjl static int
200*cb5caa98Sdjl _nscd_init_cslots()
201*cb5caa98Sdjl {
202*cb5caa98Sdjl 	(void) mutex_lock(&child_lock);
203*cb5caa98Sdjl 
204*cb5caa98Sdjl 	child = (child_t **)calloc(max_pu_nscd, sizeof (child_t *));
205*cb5caa98Sdjl 	if (child == NULL)
206*cb5caa98Sdjl 		return (-1);
207*cb5caa98Sdjl 
208*cb5caa98Sdjl 	open_head = -1;
209*cb5caa98Sdjl 	open_tail = -1;
210*cb5caa98Sdjl 	used_slot = -1;
211*cb5caa98Sdjl 
212*cb5caa98Sdjl 	(void) mutex_unlock(&child_lock);
213*cb5caa98Sdjl 
214*cb5caa98Sdjl 	return (0);
215*cb5caa98Sdjl }
216*cb5caa98Sdjl 
217*cb5caa98Sdjl static child_t *
218*cb5caa98Sdjl get_cslot(
219*cb5caa98Sdjl 	uid_t		uid,
220*cb5caa98Sdjl 	int		no_alloc)
221*cb5caa98Sdjl {
222*cb5caa98Sdjl 	int		i;
223*cb5caa98Sdjl 	child_t		*ch, *ret = NULL;
224*cb5caa98Sdjl 	char		*me = "get_cslot";
225*cb5caa98Sdjl 
226*cb5caa98Sdjl 	(void) mutex_lock(&child_lock);
227*cb5caa98Sdjl 
228*cb5caa98Sdjl 	_NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
229*cb5caa98Sdjl 	(me, "looking for uid %d (slot used = %d)\n", uid, used_slot);
230*cb5caa98Sdjl 
231*cb5caa98Sdjl 	/* first find the slot with a matching uid */
232*cb5caa98Sdjl 	for (i = 0; i <= used_slot; i++) {
233*cb5caa98Sdjl 		ch = child[i];
234*cb5caa98Sdjl 		if (ch->child_state >= CHILD_STATE_UIDKNOWN &&
235*cb5caa98Sdjl 			ch->child_uid == uid) {
236*cb5caa98Sdjl 			ret = ch;
237*cb5caa98Sdjl 			(void) mutex_unlock(&child_lock);
238*cb5caa98Sdjl 
239*cb5caa98Sdjl 			_NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
240*cb5caa98Sdjl 			(me, "slot %d found with uid %d\n",
241*cb5caa98Sdjl 				ret->child_slot, ret->child_uid);
242*cb5caa98Sdjl 
243*cb5caa98Sdjl 			return (ret);
244*cb5caa98Sdjl 		}
245*cb5caa98Sdjl 	}
246*cb5caa98Sdjl 
247*cb5caa98Sdjl 	/* if no need to allocate a new slot, return NULL */
248*cb5caa98Sdjl 	if (no_alloc == 1) {
249*cb5caa98Sdjl 		(void) mutex_unlock(&child_lock);
250*cb5caa98Sdjl 		return (ret);
251*cb5caa98Sdjl 	}
252*cb5caa98Sdjl 
253*cb5caa98Sdjl 	/* no open slot ? get a new one */
254*cb5caa98Sdjl 	if (open_head == -1) {
255*cb5caa98Sdjl 		/* if no slot available, allocate more */
256*cb5caa98Sdjl 		if (used_slot >= max_pu_nscd - 1) {
257*cb5caa98Sdjl 			child_t	**tmp;
258*cb5caa98Sdjl 			int	newmax = max_pu_nscd + _NSCD_PUN_BLOCK;
259*cb5caa98Sdjl 
260*cb5caa98Sdjl 			tmp = (child_t **)calloc(newmax, sizeof (child_t *));
261*cb5caa98Sdjl 			if (tmp == NULL) {
262*cb5caa98Sdjl 				(void) mutex_unlock(&child_lock);
263*cb5caa98Sdjl 				return (ret);
264*cb5caa98Sdjl 			}
265*cb5caa98Sdjl 			(void) memcpy(tmp, child, sizeof (child_t) *
266*cb5caa98Sdjl 				max_pu_nscd);
267*cb5caa98Sdjl 			free(child);
268*cb5caa98Sdjl 			child = tmp;
269*cb5caa98Sdjl 			max_pu_nscd = newmax;
270*cb5caa98Sdjl 		}
271*cb5caa98Sdjl 		used_slot++;
272*cb5caa98Sdjl 		if (init_slot(used_slot) == -1) {
273*cb5caa98Sdjl 			used_slot--;
274*cb5caa98Sdjl 			(void) mutex_unlock(&child_lock);
275*cb5caa98Sdjl 			return (ret);
276*cb5caa98Sdjl 		}
277*cb5caa98Sdjl 		ch = child[used_slot];
278*cb5caa98Sdjl 	} else {
279*cb5caa98Sdjl 		ch = child[open_head];
280*cb5caa98Sdjl 		open_head = ch->next_open;
281*cb5caa98Sdjl 		/* got last one ? reset tail */
282*cb5caa98Sdjl 		if (open_head == -1)
283*cb5caa98Sdjl 			open_tail = -1;
284*cb5caa98Sdjl 		ch->next_open = -1;
285*cb5caa98Sdjl 	}
286*cb5caa98Sdjl 
287*cb5caa98Sdjl 	ch->child_uid = uid;
288*cb5caa98Sdjl 	ch->child_state = CHILD_STATE_UIDKNOWN;
289*cb5caa98Sdjl 	ret = ch;
290*cb5caa98Sdjl 
291*cb5caa98Sdjl 	(void) mutex_unlock(&child_lock);
292*cb5caa98Sdjl 
293*cb5caa98Sdjl 	return (ret);
294*cb5caa98Sdjl }
295*cb5caa98Sdjl 
296*cb5caa98Sdjl static void
297*cb5caa98Sdjl return_cslot_nolock(child_t *ch)
298*cb5caa98Sdjl {
299*cb5caa98Sdjl 
300*cb5caa98Sdjl 	int	slot = ch->child_slot;
301*cb5caa98Sdjl 
302*cb5caa98Sdjl 	/* have open slot ? add to and reset tail */
303*cb5caa98Sdjl 	if (open_tail != -1) {
304*cb5caa98Sdjl 		child[open_tail]->next_open = slot;
305*cb5caa98Sdjl 		open_tail = slot;
306*cb5caa98Sdjl 	} else {
307*cb5caa98Sdjl 		/* no open slot ? make one */
308*cb5caa98Sdjl 		open_head = open_tail = slot;
309*cb5caa98Sdjl 	}
310*cb5caa98Sdjl 
311*cb5caa98Sdjl 	(void) init_slot(ch->child_slot);
312*cb5caa98Sdjl }
313*cb5caa98Sdjl 
314*cb5caa98Sdjl static void
315*cb5caa98Sdjl return_cslot(child_t *ch)
316*cb5caa98Sdjl {
317*cb5caa98Sdjl 
318*cb5caa98Sdjl 	char *me = "return_cslot";
319*cb5caa98Sdjl 
320*cb5caa98Sdjl 	_NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
321*cb5caa98Sdjl 	(me, "returning slot %d\n", ch->child_slot);
322*cb5caa98Sdjl 
323*cb5caa98Sdjl 	/* return if the slot has been returned by another thread */
324*cb5caa98Sdjl 	if (ch->child_state == CHILD_STATE_NONE)
325*cb5caa98Sdjl 		return;
326*cb5caa98Sdjl 
327*cb5caa98Sdjl 	(void) mutex_lock(&child_lock);
328*cb5caa98Sdjl 
329*cb5caa98Sdjl 	/* check one more time */
330*cb5caa98Sdjl 	if (ch->child_state == CHILD_STATE_NONE) {
331*cb5caa98Sdjl 		(void) mutex_unlock(&child_lock);
332*cb5caa98Sdjl 		return;
333*cb5caa98Sdjl 	}
334*cb5caa98Sdjl 
335*cb5caa98Sdjl 	return_cslot_nolock(ch);
336*cb5caa98Sdjl 
337*cb5caa98Sdjl 	(void) mutex_unlock(&child_lock);
338*cb5caa98Sdjl }
339*cb5caa98Sdjl 
340*cb5caa98Sdjl static int
341*cb5caa98Sdjl selfcred_kill(
342*cb5caa98Sdjl 	int	fd)
343*cb5caa98Sdjl {
344*cb5caa98Sdjl 	int	ret;
345*cb5caa98Sdjl 	char	*me = "selfcred_kill";
346*cb5caa98Sdjl 
347*cb5caa98Sdjl 	_NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
348*cb5caa98Sdjl 	(me, "sending kill to door %d\n", fd);
349*cb5caa98Sdjl 
350*cb5caa98Sdjl 	if (fd != -1)
351*cb5caa98Sdjl 		ret = _nscd_doorcall_fd(fd, NSCD_KILL, NULL, 0,
352*cb5caa98Sdjl 			NULL, 0, NULL);
353*cb5caa98Sdjl 	else
354*cb5caa98Sdjl 		ret = _nscd_doorcall(NSCD_KILL);
355*cb5caa98Sdjl 
356*cb5caa98Sdjl 	_NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
357*cb5caa98Sdjl 	(me, "kill request sent to door %d (rc = %d)\n", fd, ret);
358*cb5caa98Sdjl 
359*cb5caa98Sdjl 	return (ret);
360*cb5caa98Sdjl }
361*cb5caa98Sdjl 
362*cb5caa98Sdjl 
363*cb5caa98Sdjl void
364*cb5caa98Sdjl _nscd_kill_forker()
365*cb5caa98Sdjl {
366*cb5caa98Sdjl 	(void) mutex_lock(&forking_lock);
367*cb5caa98Sdjl 	if (forking_door != -1)
368*cb5caa98Sdjl 		(void) selfcred_kill(forking_door);
369*cb5caa98Sdjl 	forking_door = -1;
370*cb5caa98Sdjl 	(void) mutex_unlock(&forking_lock);
371*cb5caa98Sdjl }
372*cb5caa98Sdjl 
373*cb5caa98Sdjl void
374*cb5caa98Sdjl _nscd_kill_all_children()
375*cb5caa98Sdjl {
376*cb5caa98Sdjl 	int	i;
377*cb5caa98Sdjl 	int	ret;
378*cb5caa98Sdjl 	char	*me = "_nscd_kill_all_children";
379*cb5caa98Sdjl 
380*cb5caa98Sdjl 	(void) mutex_lock(&child_lock);
381*cb5caa98Sdjl 	for (i = 0; i <= used_slot; i++) {
382*cb5caa98Sdjl 		if (child[i] == NULL)
383*cb5caa98Sdjl 			continue;
384*cb5caa98Sdjl 
385*cb5caa98Sdjl 		if (child[i]->child_state >= CHILD_STATE_PIDKNOWN) {
386*cb5caa98Sdjl 			_NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
387*cb5caa98Sdjl 			(me, "killing child process %d (doorfd %d)\n",
388*cb5caa98Sdjl 			child[i]->child_pid, child[i]->child_door);
389*cb5caa98Sdjl 
390*cb5caa98Sdjl 			ret = selfcred_kill(child[i]->child_door);
391*cb5caa98Sdjl 
392*cb5caa98Sdjl 			if (ret != -1)
393*cb5caa98Sdjl 				(void) kill(child[i]->child_pid, SIGTERM);
394*cb5caa98Sdjl 		}
395*cb5caa98Sdjl 		if (child[i]->child_state != CHILD_STATE_NONE)
396*cb5caa98Sdjl 			(void) return_cslot_nolock(child[i]);
397*cb5caa98Sdjl 	}
398*cb5caa98Sdjl 	(void) mutex_unlock(&child_lock);
399*cb5caa98Sdjl }
400*cb5caa98Sdjl static int
401*cb5caa98Sdjl selfcred_pulse(
402*cb5caa98Sdjl 	int		fd)
403*cb5caa98Sdjl {
404*cb5caa98Sdjl 	int		ret;
405*cb5caa98Sdjl 	char		*me = "selfcred_pulse";
406*cb5caa98Sdjl 
407*cb5caa98Sdjl 	_NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
408*cb5caa98Sdjl 	(me, "start monitoring door %d\n", fd);
409*cb5caa98Sdjl 
410*cb5caa98Sdjl 	ret = _nscd_doorcall_fd(fd, NSCD_PULSE |(_whoami & NSCD_WHOAMI),
411*cb5caa98Sdjl 		NULL, 0, NULL, 0, NULL);
412*cb5caa98Sdjl 
413*cb5caa98Sdjl 	_NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
414*cb5caa98Sdjl 	(me, "door (%d) monitor exited (rc = %d)\n", fd, ret);
415*cb5caa98Sdjl 
416*cb5caa98Sdjl 	return (ret);
417*cb5caa98Sdjl }
418*cb5caa98Sdjl 
419*cb5caa98Sdjl /*ARGSUSED*/
420*cb5caa98Sdjl static void *
421*cb5caa98Sdjl forker_monitor(
422*cb5caa98Sdjl 	void		*arg)
423*cb5caa98Sdjl {
424*cb5caa98Sdjl 	pid_t		fpid;
425*cb5caa98Sdjl 	char		*fmri;
426*cb5caa98Sdjl 	char		*me = "forker_monitor";
427*cb5caa98Sdjl 
428*cb5caa98Sdjl 	/* wait until forker exits */
429*cb5caa98Sdjl 	fpid = forker_pid;
430*cb5caa98Sdjl 	(void) selfcred_pulse(forking_door);
431*cb5caa98Sdjl 
432*cb5caa98Sdjl 	_NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
433*cb5caa98Sdjl (me, "forker (pid = %d) exited or crashed, killing all child processes\n",
434*cb5caa98Sdjl 		fpid);
435*cb5caa98Sdjl 
436*cb5caa98Sdjl 	(void) mutex_lock(&forking_lock);
437*cb5caa98Sdjl 	forking_door = -1;
438*cb5caa98Sdjl 	forker_pid = -1;
439*cb5caa98Sdjl 	(void) mutex_unlock(&forking_lock);
440*cb5caa98Sdjl 
441*cb5caa98Sdjl 	/* forker exited/crashed, kill all the child processes */
442*cb5caa98Sdjl 	_nscd_kill_all_children();
443*cb5caa98Sdjl 
444*cb5caa98Sdjl 	/* restart forker */
445*cb5caa98Sdjl 	_NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
446*cb5caa98Sdjl 	(me, "restarting the forker ...\n");
447*cb5caa98Sdjl 
448*cb5caa98Sdjl 	switch (fpid = fork1()) {
449*cb5caa98Sdjl 	case (pid_t)-1:
450*cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
451*cb5caa98Sdjl 		(me, "unable to fork and start the forker ...\n");
452*cb5caa98Sdjl 
453*cb5caa98Sdjl 		/* enter the maintenance mode */
454*cb5caa98Sdjl 		if ((fmri = getenv("SMF_FMRI")) != NULL) {
455*cb5caa98Sdjl 			_NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
456*cb5caa98Sdjl 			(me, "entering maintenance mode ...\n");
457*cb5caa98Sdjl 			smf_maintain_instance(fmri, SMF_TEMPORARY);
458*cb5caa98Sdjl 		}
459*cb5caa98Sdjl 		thr_exit((void *)1);
460*cb5caa98Sdjl 		break;
461*cb5caa98Sdjl 	case 0:
462*cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
463*cb5caa98Sdjl 		(me, "execv path = %s\n", execpath);
464*cb5caa98Sdjl 
465*cb5caa98Sdjl 		(void) execv(execpath, execargv);
466*cb5caa98Sdjl 		exit(0);
467*cb5caa98Sdjl 		break;
468*cb5caa98Sdjl 	default:
469*cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
470*cb5caa98Sdjl 		(me, "new forker's pid is %d\n", fpid);
471*cb5caa98Sdjl 		forker_pid = fpid;
472*cb5caa98Sdjl 		break;
473*cb5caa98Sdjl 	}
474*cb5caa98Sdjl 
475*cb5caa98Sdjl 	thr_exit((void *)0);
476*cb5caa98Sdjl 
477*cb5caa98Sdjl 	/*LINTED E_FUNC_HAS_NO_RETURN_STMT*/
478*cb5caa98Sdjl }
479*cb5caa98Sdjl 
480*cb5caa98Sdjl static void *
481*cb5caa98Sdjl child_monitor(
482*cb5caa98Sdjl 	void		*arg)
483*cb5caa98Sdjl {
484*cb5caa98Sdjl 	child_t		*ch = (child_t *)arg;
485*cb5caa98Sdjl 	pid_t		cpid;
486*cb5caa98Sdjl 	char		*me = "child_monitor";
487*cb5caa98Sdjl 
488*cb5caa98Sdjl 	/* wait until child exits */
489*cb5caa98Sdjl 	cpid = ch->child_pid;
490*cb5caa98Sdjl 	(void) selfcred_pulse(ch->child_door);
491*cb5caa98Sdjl 
492*cb5caa98Sdjl 	_NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
493*cb5caa98Sdjl 		(me, "child (pid = %d) exited or crashed ...\n", cpid);
494*cb5caa98Sdjl 
495*cb5caa98Sdjl 	/* return the slot used by the child */
496*cb5caa98Sdjl 	return_cslot(ch);
497*cb5caa98Sdjl 
498*cb5caa98Sdjl 	thr_exit((void *)0);
499*cb5caa98Sdjl 	/*LINTED E_FUNC_HAS_NO_RETURN_STMT*/
500*cb5caa98Sdjl }
501*cb5caa98Sdjl 
502*cb5caa98Sdjl 
503*cb5caa98Sdjl void
504*cb5caa98Sdjl _nscd_proc_iamhere(
505*cb5caa98Sdjl 	void		*buf,
506*cb5caa98Sdjl 	door_desc_t	*dp,
507*cb5caa98Sdjl 	uint_t		n_desc,
508*cb5caa98Sdjl 	int		iam)
509*cb5caa98Sdjl {
510*cb5caa98Sdjl 	int		cslot;
511*cb5caa98Sdjl 	child_t		*ch;
512*cb5caa98Sdjl 	int		errnum;
513*cb5caa98Sdjl 	ucred_t		*uc = NULL;
514*cb5caa98Sdjl 	uid_t		uid;
515*cb5caa98Sdjl 	nscd_imhere_t	*ih;
516*cb5caa98Sdjl 	nss_pheader_t	*phdr = (nss_pheader_t *)buf;
517*cb5caa98Sdjl 	char		*me = "_nscd_proc_iamhere";
518*cb5caa98Sdjl 
519*cb5caa98Sdjl 
520*cb5caa98Sdjl 	_NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
521*cb5caa98Sdjl 	(me, "%d receives iamhere from %d\n", _whoami, iam);
522*cb5caa98Sdjl 
523*cb5caa98Sdjl 	if (door_ucred(&uc) != 0) {
524*cb5caa98Sdjl 		errnum = errno;
525*cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
526*cb5caa98Sdjl 		(me, "door_ucred failed: %s\n", strerror(errnum));
527*cb5caa98Sdjl 
528*cb5caa98Sdjl 		NSCD_RETURN_N2N_STATUS(phdr, NSS_NSCD_PRIV, errnum,
529*cb5caa98Sdjl 			NSCD_DOOR_UCRED_ERROR);
530*cb5caa98Sdjl 	}
531*cb5caa98Sdjl 	uid = ucred_geteuid(uc);
532*cb5caa98Sdjl 
533*cb5caa98Sdjl 	switch (iam) {
534*cb5caa98Sdjl 
535*cb5caa98Sdjl 	case NSCD_MAIN:
536*cb5caa98Sdjl 		if (_whoami == NSCD_MAIN || uid != main_uid) {
537*cb5caa98Sdjl 			/*
538*cb5caa98Sdjl 			 * I'm main, or uid from door is not correct,
539*cb5caa98Sdjl 			 * this must be an imposter
540*cb5caa98Sdjl 			 */
541*cb5caa98Sdjl 			_NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
542*cb5caa98Sdjl 			(me, "MAIN IMPOSTER CAUGHT!\n");
543*cb5caa98Sdjl 
544*cb5caa98Sdjl 
545*cb5caa98Sdjl 			NSCD_SET_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0,
546*cb5caa98Sdjl 			NSCD_SELF_CRED_MAIN_IMPOSTER);
547*cb5caa98Sdjl 		}
548*cb5caa98Sdjl 		break;
549*cb5caa98Sdjl 
550*cb5caa98Sdjl 	case NSCD_FORKER:
551*cb5caa98Sdjl 		if (_whoami == NSCD_FORKER || uid != forker_uid) {
552*cb5caa98Sdjl 			/*
553*cb5caa98Sdjl 			 * I'm forker, or uid from door is not correct,
554*cb5caa98Sdjl 			 * this must be an imposter
555*cb5caa98Sdjl 			 */
556*cb5caa98Sdjl 			_NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
557*cb5caa98Sdjl 			(me, "FORKER IMPOSTER CAUGHT!\n");
558*cb5caa98Sdjl 
559*cb5caa98Sdjl 
560*cb5caa98Sdjl 			NSCD_SET_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0,
561*cb5caa98Sdjl 			NSCD_SELF_CRED_FORKER_IMPOSTER);
562*cb5caa98Sdjl 			break;
563*cb5caa98Sdjl 		}
564*cb5caa98Sdjl 
565*cb5caa98Sdjl 		/* only main needs to know the forker */
566*cb5caa98Sdjl 		if (_whoami != NSCD_MAIN) {
567*cb5caa98Sdjl 
568*cb5caa98Sdjl 			NSCD_SET_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0,
569*cb5caa98Sdjl 			NSCD_SELF_CRED_WRONG_NSCD);
570*cb5caa98Sdjl 			break;
571*cb5caa98Sdjl 		}
572*cb5caa98Sdjl 
573*cb5caa98Sdjl 		if (ucred_getpid(uc) != forker_pid) {
574*cb5caa98Sdjl 			_NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
575*cb5caa98Sdjl 		(me, "FORKER IMPOSTER CAUGHT: pid = %d should be %d\n",
576*cb5caa98Sdjl 			ucred_getpid(uc), forker_pid);
577*cb5caa98Sdjl 
578*cb5caa98Sdjl 
579*cb5caa98Sdjl 			NSCD_SET_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0,
580*cb5caa98Sdjl 			NSCD_SELF_CRED_FORKER_IMPOSTER);
581*cb5caa98Sdjl 			break;
582*cb5caa98Sdjl 		}
583*cb5caa98Sdjl 
584*cb5caa98Sdjl 		if (n_desc < 1) {
585*cb5caa98Sdjl 			_NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
586*cb5caa98Sdjl 			(me, "BAD FORKER, NO DOOR!\n");
587*cb5caa98Sdjl 
588*cb5caa98Sdjl 
589*cb5caa98Sdjl 			NSCD_SET_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0,
590*cb5caa98Sdjl 			NSCD_SELF_CRED_NO_DOOR);
591*cb5caa98Sdjl 			break;
592*cb5caa98Sdjl 		}
593*cb5caa98Sdjl 
594*cb5caa98Sdjl 		if ((dp->d_attributes & DOOR_DESCRIPTOR) &&
595*cb5caa98Sdjl 			dp->d_data.d_desc.d_descriptor > 0 &&
596*cb5caa98Sdjl 			dp->d_data.d_desc.d_id != 0) {
597*cb5caa98Sdjl 			(void) mutex_lock(&forking_lock);
598*cb5caa98Sdjl 			if (forking_door != -1)
599*cb5caa98Sdjl 				(void) close(forking_door);
600*cb5caa98Sdjl 			forking_door = dp->d_data.d_desc.d_descriptor;
601*cb5caa98Sdjl 			(void) mutex_unlock(&forking_lock);
602*cb5caa98Sdjl 
603*cb5caa98Sdjl 			_NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
604*cb5caa98Sdjl 			(me, "forking door is %d\n", forking_door);
605*cb5caa98Sdjl 
606*cb5caa98Sdjl 			NSCD_SET_STATUS_SUCCESS(phdr);
607*cb5caa98Sdjl 		} else {
608*cb5caa98Sdjl 			NSCD_SET_STATUS(phdr, NSS_ALTRETRY, 0);
609*cb5caa98Sdjl 			break;
610*cb5caa98Sdjl 		}
611*cb5caa98Sdjl 
612*cb5caa98Sdjl 		/* monitor the forker nscd */
613*cb5caa98Sdjl 		(void) thr_create(NULL, 0, forker_monitor, NULL,
614*cb5caa98Sdjl 			THR_DETACHED, NULL);
615*cb5caa98Sdjl 
616*cb5caa98Sdjl 		break;
617*cb5caa98Sdjl 
618*cb5caa98Sdjl 	case NSCD_CHILD:
619*cb5caa98Sdjl 		if (_whoami != NSCD_MAIN) {
620*cb5caa98Sdjl 			/* child nscd can only talk to the main nscd */
621*cb5caa98Sdjl 			_NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
622*cb5caa98Sdjl 			(me, "CHILD IMPOSTER CAUGHT!\n");
623*cb5caa98Sdjl 
624*cb5caa98Sdjl 			NSCD_SET_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0,
625*cb5caa98Sdjl 			NSCD_SELF_CRED_CHILD_IMPOSTER);
626*cb5caa98Sdjl 			break;
627*cb5caa98Sdjl 		}
628*cb5caa98Sdjl 
629*cb5caa98Sdjl 		/* get the main nscd assigned slot number */
630*cb5caa98Sdjl 		ih = NSCD_N2N_DOOR_DATA(nscd_imhere_t, buf);
631*cb5caa98Sdjl 		cslot = ih->slot;
632*cb5caa98Sdjl 		(void) mutex_lock(&child_lock);
633*cb5caa98Sdjl 		if (cslot < 0 || cslot >= max_pu_nscd)
634*cb5caa98Sdjl 			ch = NULL;
635*cb5caa98Sdjl 		else
636*cb5caa98Sdjl 			ch = child[cslot];
637*cb5caa98Sdjl 		(void) mutex_unlock(&child_lock);
638*cb5caa98Sdjl 
639*cb5caa98Sdjl 		if (ch == NULL) {
640*cb5caa98Sdjl 			/* Bad slot number */
641*cb5caa98Sdjl 			_NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
642*cb5caa98Sdjl 			(me, "bad slot number %d\n", cslot);
643*cb5caa98Sdjl 
644*cb5caa98Sdjl 			NSCD_SET_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0,
645*cb5caa98Sdjl 			NSCD_SELF_CRED_INVALID_SLOT_NUMBER);
646*cb5caa98Sdjl 			break;
647*cb5caa98Sdjl 		}
648*cb5caa98Sdjl 
649*cb5caa98Sdjl 		if (uid != ch->child_uid) {
650*cb5caa98Sdjl 			_NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
651*cb5caa98Sdjl 		(me, "CHILD IMPOSTER CAUGHT: uid = %d should be %d\n",
652*cb5caa98Sdjl 			uid, ch->child_uid);
653*cb5caa98Sdjl 
654*cb5caa98Sdjl 			NSCD_SET_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0,
655*cb5caa98Sdjl 			NSCD_SELF_CRED_CHILD_IMPOSTER);
656*cb5caa98Sdjl 			break;
657*cb5caa98Sdjl 		}
658*cb5caa98Sdjl 
659*cb5caa98Sdjl 		if (ch->child_state != CHILD_STATE_UIDKNOWN &&
660*cb5caa98Sdjl 			ch->child_state != CHILD_STATE_FORKSENT) {
661*cb5caa98Sdjl 			_NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
662*cb5caa98Sdjl 			(me, "invalid slot/child state (%d) for uid %d\n",
663*cb5caa98Sdjl 			ch->child_state, uid);
664*cb5caa98Sdjl 
665*cb5caa98Sdjl 			NSCD_SET_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0,
666*cb5caa98Sdjl 			NSCD_SELF_CRED_INVALID_SLOT_STATE);
667*cb5caa98Sdjl 			break;
668*cb5caa98Sdjl 		}
669*cb5caa98Sdjl 
670*cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
671*cb5caa98Sdjl 		(me, "d_descriptor = %d, d_id = %lld\n",
672*cb5caa98Sdjl 		dp->d_data.d_desc.d_descriptor, dp->d_data.d_desc.d_id);
673*cb5caa98Sdjl 
674*cb5caa98Sdjl 		if ((dp->d_attributes & DOOR_DESCRIPTOR) &&
675*cb5caa98Sdjl 			dp->d_data.d_desc.d_descriptor > 0 &&
676*cb5caa98Sdjl 			dp->d_data.d_desc.d_id != 0) {
677*cb5caa98Sdjl 			(void) mutex_lock(ch->mutex);
678*cb5caa98Sdjl 			if (ch->child_door != -1)
679*cb5caa98Sdjl 				(void) close(ch->child_door);
680*cb5caa98Sdjl 			ch->child_door = dp->d_data.d_desc.d_descriptor;
681*cb5caa98Sdjl 			ch->child_pid  = ucred_getpid(uc);
682*cb5caa98Sdjl 			ch->child_state  = CHILD_STATE_PIDKNOWN;
683*cb5caa98Sdjl 			_NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
684*cb5caa98Sdjl 			(me, "child in slot %d has door %d\n",
685*cb5caa98Sdjl 				cslot, ch->child_door);
686*cb5caa98Sdjl 
687*cb5caa98Sdjl 			/*
688*cb5caa98Sdjl 			 * let waiters know that the child is ready to
689*cb5caa98Sdjl 			 * serve
690*cb5caa98Sdjl 			 */
691*cb5caa98Sdjl 			(void) cond_broadcast(ch->cond);
692*cb5caa98Sdjl 			(void) mutex_unlock(ch->mutex);
693*cb5caa98Sdjl 
694*cb5caa98Sdjl 			/* monitor the child nscd */
695*cb5caa98Sdjl 			(void) thr_create(NULL, 0, child_monitor,
696*cb5caa98Sdjl 				ch, THR_DETACHED, NULL);
697*cb5caa98Sdjl 			NSCD_SET_STATUS_SUCCESS(phdr);
698*cb5caa98Sdjl 			break;
699*cb5caa98Sdjl 		} else {
700*cb5caa98Sdjl 			NSCD_SET_STATUS(phdr, NSS_ALTRETRY, 0);
701*cb5caa98Sdjl 		}
702*cb5caa98Sdjl 		break;
703*cb5caa98Sdjl 	}
704*cb5caa98Sdjl 
705*cb5caa98Sdjl 	ucred_free(uc);
706*cb5caa98Sdjl 	uc = NULL;
707*cb5caa98Sdjl }
708*cb5caa98Sdjl 
709*cb5caa98Sdjl void
710*cb5caa98Sdjl _nscd_proc_pulse(
711*cb5caa98Sdjl 	void		*buf,
712*cb5caa98Sdjl 	int		iam)
713*cb5caa98Sdjl {
714*cb5caa98Sdjl 	long		last_active;
715*cb5caa98Sdjl 	int		done = 0;
716*cb5caa98Sdjl 	nss_pheader_t	*phdr = (nss_pheader_t *)buf;
717*cb5caa98Sdjl 	char		*me = "_nscd_proc_pulse";
718*cb5caa98Sdjl 
719*cb5caa98Sdjl 	/* only main nscd sends pulse */
720*cb5caa98Sdjl 	if (iam != NSCD_MAIN) {
721*cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
722*cb5caa98Sdjl 		(me, "MAIN IMPOSTER CAUGHT! i am %d not NSCD_MAIN\n", iam);
723*cb5caa98Sdjl 
724*cb5caa98Sdjl 		NSCD_RETURN_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0,
725*cb5caa98Sdjl 			NSCD_SELF_CRED_MAIN_IMPOSTER);
726*cb5caa98Sdjl 	}
727*cb5caa98Sdjl 
728*cb5caa98Sdjl 	/* forker doesn't return stats, it just pauses */
729*cb5caa98Sdjl 	if (_whoami == NSCD_FORKER) {
730*cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
731*cb5caa98Sdjl 		(me, "forker ready to pause ...\n");
732*cb5caa98Sdjl 
733*cb5caa98Sdjl 		/*CONSTCOND*/
734*cb5caa98Sdjl 		while (1)
735*cb5caa98Sdjl 			(void) pause();
736*cb5caa98Sdjl 
737*cb5caa98Sdjl 		NSCD_RETURN_STATUS_SUCCESS(phdr);
738*cb5caa98Sdjl 	}
739*cb5caa98Sdjl 
740*cb5caa98Sdjl 	/* remember the current activity sequence number */
741*cb5caa98Sdjl 	(void) mutex_lock(&activity_lock);
742*cb5caa98Sdjl 	last_active = activity;
743*cb5caa98Sdjl 	(void) mutex_unlock(&activity_lock);
744*cb5caa98Sdjl 
745*cb5caa98Sdjl 	while (!done) {
746*cb5caa98Sdjl 
747*cb5caa98Sdjl 		/* allow per_user_nscd_ttl seconds of inactivity */
748*cb5caa98Sdjl 		(void) sleep(pu_nscd_ttl);
749*cb5caa98Sdjl 
750*cb5caa98Sdjl 		(void) mutex_lock(&activity_lock);
751*cb5caa98Sdjl 		if (last_active == activity)
752*cb5caa98Sdjl 			done = 1;
753*cb5caa98Sdjl 		else {
754*cb5caa98Sdjl 			last_active = activity;
755*cb5caa98Sdjl 			_NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
756*cb5caa98Sdjl 			(me, "active, sleep again for %d seconds\n",
757*cb5caa98Sdjl 				pu_nscd_ttl);
758*cb5caa98Sdjl 		}
759*cb5caa98Sdjl 		(void) mutex_unlock(&activity_lock);
760*cb5caa98Sdjl 	}
761*cb5caa98Sdjl 
762*cb5caa98Sdjl 	/* no activity in the specified seconds, exit and disconnect */
763*cb5caa98Sdjl 	_NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
764*cb5caa98Sdjl 	(me, "no activity in the last %d seconds, exit\n", pu_nscd_ttl);
765*cb5caa98Sdjl 	exit(0);
766*cb5caa98Sdjl }
767*cb5caa98Sdjl 
768*cb5caa98Sdjl void
769*cb5caa98Sdjl _nscd_proc_fork(
770*cb5caa98Sdjl 	void		*buf,
771*cb5caa98Sdjl 	int		iam)
772*cb5caa98Sdjl {
773*cb5caa98Sdjl 	int		slot;
774*cb5caa98Sdjl 	int		ret;
775*cb5caa98Sdjl 	char		*fmri;
776*cb5caa98Sdjl 	pid_t		cid;
777*cb5caa98Sdjl 	uid_t		set2uid;
778*cb5caa98Sdjl 	gid_t		set2gid;
779*cb5caa98Sdjl 	nss_pheader_t	*phdr = (nss_pheader_t *)buf;
780*cb5caa98Sdjl 	char		*me = "_nscd_proc_fork";
781*cb5caa98Sdjl 	nscd_fork_t	*f;
782*cb5caa98Sdjl 	nscd_imhere_t	ih;
783*cb5caa98Sdjl 
784*cb5caa98Sdjl 	_NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
785*cb5caa98Sdjl 	(me, "%d receives fork request from %d\n", _whoami, iam);
786*cb5caa98Sdjl 
787*cb5caa98Sdjl 	/* only main nscd sends fork requests */
788*cb5caa98Sdjl 	if (iam != NSCD_MAIN) {
789*cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
790*cb5caa98Sdjl 		(me, "MAIN IMPOSTER CAUGHT! i am %d not NSCD_MAIN\n",
791*cb5caa98Sdjl 			iam);
792*cb5caa98Sdjl 
793*cb5caa98Sdjl 		NSCD_RETURN_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0,
794*cb5caa98Sdjl 			NSCD_SELF_CRED_MAIN_IMPOSTER);
795*cb5caa98Sdjl 	}
796*cb5caa98Sdjl 
797*cb5caa98Sdjl 	/* only forker handles fork requests */
798*cb5caa98Sdjl 	if (_whoami != NSCD_FORKER) {
799*cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
800*cb5caa98Sdjl 		(me, "MAIN IMPOSTER CAUGHT! I AM NOT FORKER!\n");
801*cb5caa98Sdjl 
802*cb5caa98Sdjl 		NSCD_RETURN_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0,
803*cb5caa98Sdjl 			NSCD_SELF_CRED_WRONG_NSCD);
804*cb5caa98Sdjl 	}
805*cb5caa98Sdjl 
806*cb5caa98Sdjl 	/* fork a child for the slot assigned by the main nscd */
807*cb5caa98Sdjl 	f = NSCD_N2N_DOOR_DATA(nscd_fork_t, buf);
808*cb5caa98Sdjl 	slot = f->slot;
809*cb5caa98Sdjl 	/* set the uid/gid as assigned by the main nscd */
810*cb5caa98Sdjl 	set2uid = f->uid;
811*cb5caa98Sdjl 	set2gid = f->gid;
812*cb5caa98Sdjl 
813*cb5caa98Sdjl 	/* ignore bad slot number */
814*cb5caa98Sdjl 	if (slot < 0 || slot >= max_pu_nscd) {
815*cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
816*cb5caa98Sdjl 		(me, "bas slot number\n");
817*cb5caa98Sdjl 
818*cb5caa98Sdjl 		NSCD_RETURN_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0,
819*cb5caa98Sdjl 		NSCD_SELF_CRED_INVALID_SLOT_NUMBER);
820*cb5caa98Sdjl 	}
821*cb5caa98Sdjl 
822*cb5caa98Sdjl 	_NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
823*cb5caa98Sdjl 	(me, "before fork1() ...\n");
824*cb5caa98Sdjl 
825*cb5caa98Sdjl 	if ((cid = fork1()) == 0) {
826*cb5caa98Sdjl 		_whoami = NSCD_CHILD;
827*cb5caa98Sdjl 
828*cb5caa98Sdjl 		/* close all except the log file */
829*cb5caa98Sdjl 		if (_logfd > 0) {
830*cb5caa98Sdjl 			int i;
831*cb5caa98Sdjl 			for (i = 0; i < _logfd; i++)
832*cb5caa98Sdjl 				(void) close(i);
833*cb5caa98Sdjl 			closefrom(_logfd + 1);
834*cb5caa98Sdjl 		} else
835*cb5caa98Sdjl 			closefrom(0);
836*cb5caa98Sdjl 
837*cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
838*cb5caa98Sdjl 		(me, "child %d\n", getpid());
839*cb5caa98Sdjl 
840*cb5caa98Sdjl 		(void) setgid(set2gid);
841*cb5caa98Sdjl 		(void) setuid(set2uid);
842*cb5caa98Sdjl 
843*cb5caa98Sdjl 		/* set up the door and server thread pool */
844*cb5caa98Sdjl 		if ((_doorfd = _nscd_setup_child_server(_doorfd)) == -1)
845*cb5caa98Sdjl 			exit(-1);
846*cb5caa98Sdjl 
847*cb5caa98Sdjl 		/* tell libsldap to do self cred only */
848*cb5caa98Sdjl 		(void) setup_ldap_backend();
849*cb5caa98Sdjl 
850*cb5caa98Sdjl 		/* notify main that child is active */
851*cb5caa98Sdjl 		ih.slot = slot;
852*cb5caa98Sdjl 		for (ret = NSS_ALTRETRY; ret == NSS_ALTRETRY; )
853*cb5caa98Sdjl 			ret = _nscd_doorcall_sendfd(_doorfd,
854*cb5caa98Sdjl 				NSCD_IMHERE | (NSCD_CHILD & NSCD_WHOAMI),
855*cb5caa98Sdjl 				&ih, sizeof (ih), NULL);
856*cb5caa98Sdjl 
857*cb5caa98Sdjl 			NSCD_RETURN_STATUS_SUCCESS(phdr);
858*cb5caa98Sdjl 	} if (cid  == (pid_t)-1) {
859*cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
860*cb5caa98Sdjl 		(me, "forker unable to fork ...\n");
861*cb5caa98Sdjl 
862*cb5caa98Sdjl 		/* enter the maintenance mode */
863*cb5caa98Sdjl 		if ((fmri = getenv("SMF_FMRI")) != NULL) {
864*cb5caa98Sdjl 			_NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
865*cb5caa98Sdjl 			(me, "entering maintenance mode ...\n");
866*cb5caa98Sdjl 			smf_maintain_instance(fmri, SMF_TEMPORARY);
867*cb5caa98Sdjl 		}
868*cb5caa98Sdjl 		exit(0);
869*cb5caa98Sdjl 	} else {
870*cb5caa98Sdjl 		/*
871*cb5caa98Sdjl 		 * start the monitor so as to exit as early as
872*cb5caa98Sdjl 		 * possible if no other processes are running
873*cb5caa98Sdjl 		 * with the same PUN uid (i.e., this PUN is
874*cb5caa98Sdjl 		 * not needed any more)
875*cb5caa98Sdjl 		 */
876*cb5caa98Sdjl 		(void) init_user_proc_monitor();
877*cb5caa98Sdjl 
878*cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
879*cb5caa98Sdjl 		(me, "child forked:  parent pid = %d, child pid = %d\n",
880*cb5caa98Sdjl 		getpid(), cid);
881*cb5caa98Sdjl 
882*cb5caa98Sdjl 		NSCD_SET_STATUS_SUCCESS(phdr);
883*cb5caa98Sdjl 	}
884*cb5caa98Sdjl 
885*cb5caa98Sdjl 	_NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
886*cb5caa98Sdjl 	(me, "after fork\n");
887*cb5caa98Sdjl }
888*cb5caa98Sdjl 
889*cb5caa98Sdjl static void
890*cb5caa98Sdjl selfcred_fork(
891*cb5caa98Sdjl 	void		*buf,
892*cb5caa98Sdjl 	int		doorfd,
893*cb5caa98Sdjl 	int		cslot,
894*cb5caa98Sdjl 	uid_t		uid,
895*cb5caa98Sdjl 	gid_t		gid)
896*cb5caa98Sdjl {
897*cb5caa98Sdjl 	int		ret;
898*cb5caa98Sdjl 	nscd_fork_t	f;
899*cb5caa98Sdjl 	nss_pheader_t	*phdr = (nss_pheader_t *)buf;
900*cb5caa98Sdjl 	char		*me = "selfcred_fork";
901*cb5caa98Sdjl 
902*cb5caa98Sdjl 	/* if no door fd, do nothing */
903*cb5caa98Sdjl 	if (doorfd == -1) {
904*cb5caa98Sdjl 		NSCD_SET_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0,
905*cb5caa98Sdjl 			NSCD_SELF_CRED_NO_DOOR);
906*cb5caa98Sdjl 	}
907*cb5caa98Sdjl 
908*cb5caa98Sdjl 	_NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
909*cb5caa98Sdjl 	(me, "sending fork request to door %d for slot %d "
910*cb5caa98Sdjl 		"(uid = %d, gid = %d)\n", doorfd, cslot, uid, gid);
911*cb5caa98Sdjl 
912*cb5caa98Sdjl 	f.slot = cslot;
913*cb5caa98Sdjl 	f.uid = uid;
914*cb5caa98Sdjl 	f.gid = gid;
915*cb5caa98Sdjl 
916*cb5caa98Sdjl 	ret = _nscd_doorcall_fd(doorfd, NSCD_FORK|(_whoami&NSCD_WHOAMI),
917*cb5caa98Sdjl 		&f, sizeof (f), NULL, 0, phdr);
918*cb5caa98Sdjl 
919*cb5caa98Sdjl 	_NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
920*cb5caa98Sdjl 	(me, "fork request sent to door %d for slot %d (rc = %d)\n",
921*cb5caa98Sdjl 		doorfd, cslot, ret);
922*cb5caa98Sdjl 
923*cb5caa98Sdjl 	if (NSCD_STATUS_IS_NOT_OK(phdr)) {
924*cb5caa98Sdjl 
925*cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
926*cb5caa98Sdjl 		(me, "fork request sent to door %d for slot %d failed: "
927*cb5caa98Sdjl 		"status = %d, errno = %s, nscd status = %d\n", doorfd,
928*cb5caa98Sdjl 		cslot, NSCD_GET_STATUS(phdr), strerror(NSCD_GET_ERRNO(phdr)),
929*cb5caa98Sdjl 		NSCD_GET_NSCD_STATUS(phdr));
930*cb5caa98Sdjl 
931*cb5caa98Sdjl 	}
932*cb5caa98Sdjl }
933*cb5caa98Sdjl 
934*cb5caa98Sdjl void
935*cb5caa98Sdjl _nscd_proc_alt_get(
936*cb5caa98Sdjl 	void		*buf,
937*cb5caa98Sdjl 	int		*door)
938*cb5caa98Sdjl {
939*cb5caa98Sdjl 	int		errnum;
940*cb5caa98Sdjl 	uid_t		set2uid;
941*cb5caa98Sdjl 	gid_t		set2gid;
942*cb5caa98Sdjl 	nss_pheader_t	*phdr = (nss_pheader_t *)buf;
943*cb5caa98Sdjl 	char		*me = "_nscd_proc_alt_get";
944*cb5caa98Sdjl 	ucred_t		*uc = NULL;
945*cb5caa98Sdjl 	child_t		*ch;
946*cb5caa98Sdjl 
947*cb5caa98Sdjl 	_NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
948*cb5caa98Sdjl 	(me, "getting an alternate door ...\n");
949*cb5caa98Sdjl 
950*cb5caa98Sdjl 	/* make sure there is a door to talk to the forker */
951*cb5caa98Sdjl 	if (forking_door == -1) {
952*cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_ERROR)
953*cb5caa98Sdjl 		(me, "no door to talk to the forker\n");
954*cb5caa98Sdjl 
955*cb5caa98Sdjl 		NSCD_RETURN_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0,
956*cb5caa98Sdjl 		NSCD_SELF_CRED_NO_FORKER);
957*cb5caa98Sdjl 	}
958*cb5caa98Sdjl 
959*cb5caa98Sdjl 	/* get door client's credential information */
960*cb5caa98Sdjl 	if (door_ucred(&uc) != 0) {
961*cb5caa98Sdjl 		errnum = errno;
962*cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
963*cb5caa98Sdjl 		(me, "door_ucred failed: %s\n", strerror(errnum));
964*cb5caa98Sdjl 
965*cb5caa98Sdjl 		NSCD_RETURN_N2N_STATUS(phdr, NSS_NSCD_PRIV, errnum,
966*cb5caa98Sdjl 			NSCD_DOOR_UCRED_ERROR);
967*cb5caa98Sdjl 	}
968*cb5caa98Sdjl 
969*cb5caa98Sdjl 	/* get door client's effective uid and effective gid */
970*cb5caa98Sdjl 	set2uid = ucred_geteuid(uc);
971*cb5caa98Sdjl 	set2gid = ucred_getegid(uc);
972*cb5caa98Sdjl 	ucred_free(uc);
973*cb5caa98Sdjl 	uc = NULL;
974*cb5caa98Sdjl 
975*cb5caa98Sdjl 	_NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
976*cb5caa98Sdjl 	(me, "child uid = %d, gid = %d\n", set2uid, set2gid);
977*cb5caa98Sdjl 
978*cb5caa98Sdjl 	/* is a slot available ? if not, no one to serve */
979*cb5caa98Sdjl 	if (child == NULL || (ch = get_cslot(set2uid, 0)) == NULL) {
980*cb5caa98Sdjl 
981*cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
982*cb5caa98Sdjl 		(me, "no child slot available (child array = %p, slot = %d)\n",
983*cb5caa98Sdjl 			child, ch->child_slot);
984*cb5caa98Sdjl 
985*cb5caa98Sdjl 		NSCD_RETURN_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0,
986*cb5caa98Sdjl 			NSCD_SELF_CRED_NO_CHILD_SLOT);
987*cb5caa98Sdjl 	}
988*cb5caa98Sdjl 
989*cb5caa98Sdjl 	/* create the per user nscd if necessary */
990*cb5caa98Sdjl 	if (ch->child_state != CHILD_STATE_PIDKNOWN) {
991*cb5caa98Sdjl 
992*cb5caa98Sdjl 		nss_pheader_t	phdr1;
993*cb5caa98Sdjl 		NSCD_CLEAR_STATUS(&phdr1);
994*cb5caa98Sdjl 
995*cb5caa98Sdjl 		(void) mutex_lock(ch->mutex);
996*cb5caa98Sdjl 		if (ch->child_state == CHILD_STATE_UIDKNOWN) {
997*cb5caa98Sdjl 
998*cb5caa98Sdjl 			/* ask forker to fork a new child */
999*cb5caa98Sdjl 			selfcred_fork(&phdr1, forking_door, ch->child_slot,
1000*cb5caa98Sdjl 				set2uid, set2gid);
1001*cb5caa98Sdjl 			if (NSCD_STATUS_IS_NOT_OK(&phdr1)) {
1002*cb5caa98Sdjl 				(void) mutex_unlock(ch->mutex);
1003*cb5caa98Sdjl 				NSCD_COPY_STATUS(phdr, &phdr1);
1004*cb5caa98Sdjl 				return;
1005*cb5caa98Sdjl 			}
1006*cb5caa98Sdjl 			ch->child_state = CHILD_STATE_FORKSENT;
1007*cb5caa98Sdjl 		}
1008*cb5caa98Sdjl 
1009*cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
1010*cb5caa98Sdjl 		(me, "waiting for door (slot = %d, uid = %d, gid = %d)\n",
1011*cb5caa98Sdjl 				ch->child_slot, set2uid, set2gid);
1012*cb5caa98Sdjl 
1013*cb5caa98Sdjl 		/* wait for the per user nscd to become available */
1014*cb5caa98Sdjl 		while (ch->child_state == CHILD_STATE_FORKSENT) {
1015*cb5caa98Sdjl 			timestruc_t to;
1016*cb5caa98Sdjl 			int err;
1017*cb5caa98Sdjl 			int ttl = 5;
1018*cb5caa98Sdjl 
1019*cb5caa98Sdjl 			to.tv_sec = ttl;
1020*cb5caa98Sdjl 			to.tv_nsec = 0;
1021*cb5caa98Sdjl 			_NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
1022*cb5caa98Sdjl 				(me, "cond_reltimedwait %d seconds\n", ttl);
1023*cb5caa98Sdjl 			err = cond_reltimedwait(ch->cond, ch->mutex, &to);
1024*cb5caa98Sdjl 			if (err == ETIME) {
1025*cb5caa98Sdjl 				ch->child_state =
1026*cb5caa98Sdjl 					CHILD_STATE_UIDKNOWN;
1027*cb5caa98Sdjl 				_NSCD_LOG(NSCD_LOG_SELF_CRED,
1028*cb5caa98Sdjl 					NSCD_LOG_LEVEL_DEBUG)
1029*cb5caa98Sdjl 				(me, "door wait timedout (slot = %d)\n",
1030*cb5caa98Sdjl 					ch->child_slot);
1031*cb5caa98Sdjl 				break;
1032*cb5caa98Sdjl 			}
1033*cb5caa98Sdjl 		}
1034*cb5caa98Sdjl 		(void) mutex_unlock(ch->mutex);
1035*cb5caa98Sdjl 	}
1036*cb5caa98Sdjl 
1037*cb5caa98Sdjl 	if (ch->child_state != CHILD_STATE_PIDKNOWN) {
1038*cb5caa98Sdjl 
1039*cb5caa98Sdjl 		NSCD_RETURN_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0,
1040*cb5caa98Sdjl 			NSCD_SELF_CRED_INVALID_SLOT_STATE);
1041*cb5caa98Sdjl 	}
1042*cb5caa98Sdjl 
1043*cb5caa98Sdjl 	*door = ch->child_door;
1044*cb5caa98Sdjl 
1045*cb5caa98Sdjl 	_NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
1046*cb5caa98Sdjl 	(me, "returning door %d for slot %d, uid %d, gid = %d\n",
1047*cb5caa98Sdjl 		*door, ch->child_slot, set2uid, set2gid);
1048*cb5caa98Sdjl 
1049*cb5caa98Sdjl 	NSCD_RETURN_STATUS(phdr, NSS_ALTRETRY, 0);
1050*cb5caa98Sdjl }
1051*cb5caa98Sdjl 
1052*cb5caa98Sdjl static char **
1053*cb5caa98Sdjl cpargv(
1054*cb5caa98Sdjl 	int	argc,
1055*cb5caa98Sdjl 	char	**inargv)
1056*cb5caa98Sdjl {
1057*cb5caa98Sdjl 	char	**newargv;
1058*cb5caa98Sdjl 	int	c = 4;
1059*cb5caa98Sdjl 	int	i = 0, j, k = 0, n = 0;
1060*cb5caa98Sdjl 
1061*cb5caa98Sdjl 	newargv = (char **)calloc(c + 1, sizeof (char *));
1062*cb5caa98Sdjl 	if (newargv == NULL)
1063*cb5caa98Sdjl 		return (NULL);
1064*cb5caa98Sdjl 
1065*cb5caa98Sdjl 	newargv[n] = strdup(inargv[0]);
1066*cb5caa98Sdjl 	if (newargv[n++] == NULL) {
1067*cb5caa98Sdjl 		free(newargv);
1068*cb5caa98Sdjl 		return (NULL);
1069*cb5caa98Sdjl 	}
1070*cb5caa98Sdjl 
1071*cb5caa98Sdjl 	newargv[n] = strdup("-F");
1072*cb5caa98Sdjl 	if (newargv[n++] == NULL) {
1073*cb5caa98Sdjl 		free(newargv[0]);
1074*cb5caa98Sdjl 		free(newargv);
1075*cb5caa98Sdjl 		return (NULL);
1076*cb5caa98Sdjl 	}
1077*cb5caa98Sdjl 
1078*cb5caa98Sdjl 	for (i = 1; i < argc; i++) {
1079*cb5caa98Sdjl 		if (strcmp(inargv[i], "-f") == 0)
1080*cb5caa98Sdjl 			k = 2;
1081*cb5caa98Sdjl 		if (k  == 0)
1082*cb5caa98Sdjl 			continue;
1083*cb5caa98Sdjl 
1084*cb5caa98Sdjl 		newargv[n] = strdup(inargv[i]);
1085*cb5caa98Sdjl 		if (newargv[n] == NULL) {
1086*cb5caa98Sdjl 			for (j = 0; j < n; j++)
1087*cb5caa98Sdjl 				free(newargv[j]);
1088*cb5caa98Sdjl 			free(newargv);
1089*cb5caa98Sdjl 			return (NULL);
1090*cb5caa98Sdjl 		}
1091*cb5caa98Sdjl 
1092*cb5caa98Sdjl 		k--;
1093*cb5caa98Sdjl 		n++;
1094*cb5caa98Sdjl 	}
1095*cb5caa98Sdjl 	return (newargv);
1096*cb5caa98Sdjl }
1097*cb5caa98Sdjl 
1098*cb5caa98Sdjl 
1099*cb5caa98Sdjl void
1100*cb5caa98Sdjl _nscd_start_forker(
1101*cb5caa98Sdjl 	char	*path,
1102*cb5caa98Sdjl 	int	argc,
1103*cb5caa98Sdjl 	char	**argv)
1104*cb5caa98Sdjl {
1105*cb5caa98Sdjl 	pid_t	cid;
1106*cb5caa98Sdjl 	struct	rlimit rl;
1107*cb5caa98Sdjl 	char	*me = "_nscd_start_forker";
1108*cb5caa98Sdjl 
1109*cb5caa98Sdjl 	/* if self cred is not configured, do nothing */
1110*cb5caa98Sdjl 	if (!_nscd_is_self_cred_on(1, NULL))
1111*cb5caa98Sdjl 		return;
1112*cb5caa98Sdjl 
1113*cb5caa98Sdjl 	/* save pathname and generate the new argv for the forker */
1114*cb5caa98Sdjl 	execpath = strdup(path);
1115*cb5caa98Sdjl 	execargv = cpargv(argc, argv);
1116*cb5caa98Sdjl 	if (execpath == NULL || execargv == NULL)
1117*cb5caa98Sdjl 		exit(1);
1118*cb5caa98Sdjl 
1119*cb5caa98Sdjl 	switch (cid = fork1()) {
1120*cb5caa98Sdjl 		case (pid_t)-1:
1121*cb5caa98Sdjl 			exit(1);
1122*cb5caa98Sdjl 			break;
1123*cb5caa98Sdjl 		case 0:
1124*cb5caa98Sdjl 			/* start the forker nscd */
1125*cb5caa98Sdjl 			(void) execv(path, execargv);
1126*cb5caa98Sdjl 			exit(0);
1127*cb5caa98Sdjl 			break;
1128*cb5caa98Sdjl 		default:
1129*cb5caa98Sdjl 			/* main nscd */
1130*cb5caa98Sdjl 			/* remember process id of the forker */
1131*cb5caa98Sdjl 			forker_pid = cid;
1132*cb5caa98Sdjl 
1133*cb5caa98Sdjl 			/* set NOFILE to unlimited */
1134*cb5caa98Sdjl 			rl.rlim_cur = rl.rlim_max = RLIM_INFINITY;
1135*cb5caa98Sdjl 			if (setrlimit(RLIMIT_NOFILE, &rl) < 0) {
1136*cb5caa98Sdjl 				_NSCD_LOG(NSCD_LOG_SELF_CRED,
1137*cb5caa98Sdjl 					NSCD_LOG_LEVEL_ERROR)
1138*cb5caa98Sdjl 				(me, "Cannot set open file limit: %s\n",
1139*cb5caa98Sdjl 					strerror(errno));
1140*cb5caa98Sdjl 				exit(1);
1141*cb5caa98Sdjl 			}
1142*cb5caa98Sdjl 
1143*cb5caa98Sdjl 			/* enable child nscd management */
1144*cb5caa98Sdjl 			(void) _nscd_init_cslots();
1145*cb5caa98Sdjl 			break;
1146*cb5caa98Sdjl 	}
1147*cb5caa98Sdjl }
1148*cb5caa98Sdjl 
1149*cb5caa98Sdjl static nscd_rc_t
1150*cb5caa98Sdjl get_ldap_funcs(
1151*cb5caa98Sdjl 	char			*name,
1152*cb5caa98Sdjl 	void			**func_p)
1153*cb5caa98Sdjl {
1154*cb5caa98Sdjl 	char			*me = "get_ldap_funcs";
1155*cb5caa98Sdjl 	static void		*handle = NULL;
1156*cb5caa98Sdjl 	void			*sym;
1157*cb5caa98Sdjl 
1158*cb5caa98Sdjl 	if (name == NULL && handle != NULL) {
1159*cb5caa98Sdjl 		(void) dlclose(handle);
1160*cb5caa98Sdjl 		return (NSCD_SUCCESS);
1161*cb5caa98Sdjl 	}
1162*cb5caa98Sdjl 	/* no handle to close, it's OK */
1163*cb5caa98Sdjl 	if (name == NULL)
1164*cb5caa98Sdjl 		return (NSCD_SUCCESS);
1165*cb5caa98Sdjl 
1166*cb5caa98Sdjl 	if (handle == NULL) {
1167*cb5caa98Sdjl 		handle = dlopen("libsldap.so.1", RTLD_LAZY);
1168*cb5caa98Sdjl 		if (handle == NULL) {
1169*cb5caa98Sdjl 
1170*cb5caa98Sdjl 			_NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_ERROR)
1171*cb5caa98Sdjl 			(me, "unable to dlopen libsldap.so.1");
1172*cb5caa98Sdjl 			return (NSCD_CFG_DLOPEN_ERROR);
1173*cb5caa98Sdjl 		}
1174*cb5caa98Sdjl 	}
1175*cb5caa98Sdjl 
1176*cb5caa98Sdjl 	if ((sym = dlsym(handle, name)) == NULL) {
1177*cb5caa98Sdjl 
1178*cb5caa98Sdjl 			_NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_ERROR)
1179*cb5caa98Sdjl 			(me, "unable to find symbol %s", name);
1180*cb5caa98Sdjl 			return (NSCD_CFG_DLSYM_ERROR);
1181*cb5caa98Sdjl 	} else
1182*cb5caa98Sdjl 		(void) memcpy(func_p, &sym, sizeof (void *));
1183*cb5caa98Sdjl 
1184*cb5caa98Sdjl 	return (NSCD_SUCCESS);
1185*cb5caa98Sdjl }
1186*cb5caa98Sdjl 
1187*cb5caa98Sdjl 
1188*cb5caa98Sdjl int
1189*cb5caa98Sdjl _nscd_is_self_cred_on(int recheck, char **dblist)
1190*cb5caa98Sdjl {
1191*cb5caa98Sdjl 	static int	checked = 0;
1192*cb5caa98Sdjl 	static int	is_on = 0;
1193*cb5caa98Sdjl 	static int	(*ldap_func)();
1194*cb5caa98Sdjl 	char		*srcs = "ldap"; /* only ldap support self cred */
1195*cb5caa98Sdjl 	int		ldap_on = 0;
1196*cb5caa98Sdjl 
1197*cb5caa98Sdjl 	char		*ldap_sc_func = "__ns_ldap_self_gssapi_config";
1198*cb5caa98Sdjl 	ns_ldap_self_gssapi_config_t ldap_config;
1199*cb5caa98Sdjl 
1200*cb5caa98Sdjl 	if (checked && !recheck) {
1201*cb5caa98Sdjl 		if (is_on && dblist != NULL)
1202*cb5caa98Sdjl 			*dblist = selfcred_dbs;
1203*cb5caa98Sdjl 		return (is_on);
1204*cb5caa98Sdjl 	}
1205*cb5caa98Sdjl 
1206*cb5caa98Sdjl 	if (selfcred_dbs != NULL)
1207*cb5caa98Sdjl 		free(selfcred_dbs);
1208*cb5caa98Sdjl 	selfcred_dbs = _nscd_srcs_in_db_nsw_policy(1, &srcs);
1209*cb5caa98Sdjl 
1210*cb5caa98Sdjl 	/*
1211*cb5caa98Sdjl 	 * also check the ldap backend to see if
1212*cb5caa98Sdjl 	 * the configuration there is good for
1213*cb5caa98Sdjl 	 * doing self credentialing
1214*cb5caa98Sdjl 	 */
1215*cb5caa98Sdjl 	if (ldap_func == NULL)
1216*cb5caa98Sdjl 		(void) get_ldap_funcs(ldap_sc_func, (void **)&ldap_func);
1217*cb5caa98Sdjl 	if (ldap_func != NULL) {
1218*cb5caa98Sdjl 		if (ldap_func(&ldap_config) == NS_LDAP_SUCCESS &&
1219*cb5caa98Sdjl 			ldap_config != NS_LDAP_SELF_GSSAPI_CONFIG_NONE)
1220*cb5caa98Sdjl 			ldap_on = 1;
1221*cb5caa98Sdjl 	}
1222*cb5caa98Sdjl 
1223*cb5caa98Sdjl 	is_on = pu_nscd_enabled == nscd_true &&
1224*cb5caa98Sdjl 			ldap_on && selfcred_dbs != NULL;
1225*cb5caa98Sdjl 
1226*cb5caa98Sdjl 	checked = 1;
1227*cb5caa98Sdjl 
1228*cb5caa98Sdjl 	if (is_on && dblist != NULL)
1229*cb5caa98Sdjl 		*dblist = selfcred_dbs;
1230*cb5caa98Sdjl 
1231*cb5caa98Sdjl 	return (is_on);
1232*cb5caa98Sdjl }
1233*cb5caa98Sdjl 
1234*cb5caa98Sdjl static nscd_rc_t
1235*cb5caa98Sdjl setup_ldap_backend()
1236*cb5caa98Sdjl {
1237*cb5caa98Sdjl 	nscd_rc_t	rc;
1238*cb5caa98Sdjl 	static void	(*ldap_func)();
1239*cb5caa98Sdjl 	char		*ldap_sc_func = "__ns_ldap_self_gssapi_only_set";
1240*cb5caa98Sdjl 	if (ldap_func == NULL)
1241*cb5caa98Sdjl 		rc = get_ldap_funcs(ldap_sc_func, (void **)&ldap_func);
1242*cb5caa98Sdjl 	if (ldap_func != NULL) {
1243*cb5caa98Sdjl 		ldap_func(1);
1244*cb5caa98Sdjl 		return (NSCD_SUCCESS);
1245*cb5caa98Sdjl 	}
1246*cb5caa98Sdjl 	return (rc);
1247*cb5caa98Sdjl }
1248*cb5caa98Sdjl 
1249*cb5caa98Sdjl /*ARGSUSED*/
1250*cb5caa98Sdjl void
1251*cb5caa98Sdjl _nscd_peruser_getadmin(
1252*cb5caa98Sdjl 	void		*buf,
1253*cb5caa98Sdjl 	int		buf_size)
1254*cb5caa98Sdjl {
1255*cb5caa98Sdjl 	void		*result_mn = NSCD_N2N_DOOR_DATA(void, buf);
1256*cb5caa98Sdjl 	int		errnum = 0;
1257*cb5caa98Sdjl 	int		ret;
1258*cb5caa98Sdjl 	uid_t		uid;
1259*cb5caa98Sdjl 	nss_pheader_t	*phdr = (nss_pheader_t *)buf;
1260*cb5caa98Sdjl 	char		*me = "_nscd_peruser_getadmin";
1261*cb5caa98Sdjl 	ucred_t		*uc = NULL;
1262*cb5caa98Sdjl 	child_t		*ch;
1263*cb5caa98Sdjl 
1264*cb5caa98Sdjl 	/* get door client's credential information */
1265*cb5caa98Sdjl 	if (door_ucred(&uc) != 0) {
1266*cb5caa98Sdjl 		errnum = errno;
1267*cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
1268*cb5caa98Sdjl 		(me, "door_ucred failed: %s\n", strerror(errnum));
1269*cb5caa98Sdjl 
1270*cb5caa98Sdjl 		NSCD_RETURN_N2N_STATUS(phdr, NSS_NSCD_PRIV, errnum,
1271*cb5caa98Sdjl 			NSCD_DOOR_UCRED_ERROR);
1272*cb5caa98Sdjl 	}
1273*cb5caa98Sdjl 
1274*cb5caa98Sdjl 	/* get door client's effective uid */
1275*cb5caa98Sdjl 	uid = ucred_geteuid(uc);
1276*cb5caa98Sdjl 	ucred_free(uc);
1277*cb5caa98Sdjl 	uc = NULL;
1278*cb5caa98Sdjl 
1279*cb5caa98Sdjl 	_NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
1280*cb5caa98Sdjl 	(me, "per user get admin ... (uid = %d)\n", uid);
1281*cb5caa98Sdjl 
1282*cb5caa98Sdjl 	/* is the per-user nscd running ? if not, no one to serve */
1283*cb5caa98Sdjl 	ch = get_cslot(uid, 1);
1284*cb5caa98Sdjl 	if (ch == NULL) {
1285*cb5caa98Sdjl 		NSCD_RETURN_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0,
1286*cb5caa98Sdjl 			NSCD_SELF_CRED_NO_CHILD_SLOT);
1287*cb5caa98Sdjl 	}
1288*cb5caa98Sdjl 
1289*cb5caa98Sdjl 	ret = _nscd_doorcall_fd(ch->child_door, NSCD_GETADMIN,
1290*cb5caa98Sdjl 		NULL, sizeof (nscd_admin_t), result_mn,
1291*cb5caa98Sdjl 		sizeof (nscd_admin_t), phdr);
1292*cb5caa98Sdjl 
1293*cb5caa98Sdjl 	if (ret == NSS_SUCCESS) {
1294*cb5caa98Sdjl 		phdr->data_len = sizeof (nscd_admin_t);
1295*cb5caa98Sdjl 		return;
1296*cb5caa98Sdjl 	}
1297*cb5caa98Sdjl }
1298*cb5caa98Sdjl 
1299*cb5caa98Sdjl static void
1300*cb5caa98Sdjl set_selfcred_cfg(
1301*cb5caa98Sdjl 	char	param,
1302*cb5caa98Sdjl 	void	*data)
1303*cb5caa98Sdjl {
1304*cb5caa98Sdjl 	int64_t	prop_int;
1305*cb5caa98Sdjl 	char	*me = "set_selfcred_cfg";
1306*cb5caa98Sdjl 
1307*cb5caa98Sdjl 	if (param == 'a' || param == 'e') {
1308*cb5caa98Sdjl 		pu_nscd_enabled = *(uint8_t *)get_smf_prop(
1309*cb5caa98Sdjl 			"enable_per_user_lookup", 'b', data);
1310*cb5caa98Sdjl 
1311*cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
1312*cb5caa98Sdjl 		(me, "self cred config: enabled = %d\n", pu_nscd_enabled);
1313*cb5caa98Sdjl 	}
1314*cb5caa98Sdjl 
1315*cb5caa98Sdjl 	if (param == 'a' || param == 't') {
1316*cb5caa98Sdjl 		prop_int = *(int *)data;
1317*cb5caa98Sdjl 		pu_nscd_ttl = *(int64_t *)get_smf_prop(
1318*cb5caa98Sdjl 			"per_user_nscd_time_to_live", 'i', &prop_int);
1319*cb5caa98Sdjl 
1320*cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
1321*cb5caa98Sdjl 		(me, "self cred config: PUN TTL = %d\n", pu_nscd_ttl);
1322*cb5caa98Sdjl 	}
1323*cb5caa98Sdjl }
1324*cb5caa98Sdjl 
1325*cb5caa98Sdjl /* ARGSUSED */
1326*cb5caa98Sdjl nscd_rc_t
1327*cb5caa98Sdjl _nscd_cfg_selfcred_notify(
1328*cb5caa98Sdjl 	void				*data,
1329*cb5caa98Sdjl 	struct nscd_cfg_param_desc	*pdesc,
1330*cb5caa98Sdjl 	nscd_cfg_id_t			*nswdb,
1331*cb5caa98Sdjl 	nscd_cfg_flag_t			dflag,
1332*cb5caa98Sdjl 	nscd_cfg_error_t		**errorp,
1333*cb5caa98Sdjl 	void				*cookie)
1334*cb5caa98Sdjl {
1335*cb5caa98Sdjl 
1336*cb5caa98Sdjl 	nscd_cfg_global_selfcred_t	*sc_cfg = &nscd_selfcred_cfg_g;
1337*cb5caa98Sdjl 	int				off;
1338*cb5caa98Sdjl 
1339*cb5caa98Sdjl 	/*
1340*cb5caa98Sdjl 	 * At init time, the whole group of config params are received.
1341*cb5caa98Sdjl 	 * At update time, group or individual parameter value could
1342*cb5caa98Sdjl 	 * be received.
1343*cb5caa98Sdjl 	 */
1344*cb5caa98Sdjl 
1345*cb5caa98Sdjl 	if (_nscd_cfg_flag_is_set(dflag, NSCD_CFG_DFLAG_GROUP)) {
1346*cb5caa98Sdjl 
1347*cb5caa98Sdjl 		*sc_cfg = *(nscd_cfg_global_selfcred_t *)data;
1348*cb5caa98Sdjl 
1349*cb5caa98Sdjl 		off = offsetof(nscd_cfg_global_selfcred_t,
1350*cb5caa98Sdjl 			enable_selfcred);
1351*cb5caa98Sdjl 		set_selfcred_cfg('e', (char *)data + off);
1352*cb5caa98Sdjl 
1353*cb5caa98Sdjl 		off = offsetof(nscd_cfg_global_selfcred_t,
1354*cb5caa98Sdjl 			max_per_user_nscd);
1355*cb5caa98Sdjl 		set_selfcred_cfg('n', (char *)data + off);
1356*cb5caa98Sdjl 
1357*cb5caa98Sdjl 		off = offsetof(nscd_cfg_global_selfcred_t,
1358*cb5caa98Sdjl 			per_user_nscd_ttl);
1359*cb5caa98Sdjl 		set_selfcred_cfg('t', (char *)data + off);
1360*cb5caa98Sdjl 
1361*cb5caa98Sdjl 		return (NSCD_SUCCESS);
1362*cb5caa98Sdjl 	}
1363*cb5caa98Sdjl 
1364*cb5caa98Sdjl 	/*
1365*cb5caa98Sdjl 	 * individual config parameter
1366*cb5caa98Sdjl 	 */
1367*cb5caa98Sdjl 	off = offsetof(nscd_cfg_global_selfcred_t, enable_selfcred);
1368*cb5caa98Sdjl 	if (pdesc->p_offset == off) {
1369*cb5caa98Sdjl 		sc_cfg->enable_selfcred = *(nscd_bool_t *)data;
1370*cb5caa98Sdjl 		set_selfcred_cfg('e', data);
1371*cb5caa98Sdjl 		return (NSCD_SUCCESS);
1372*cb5caa98Sdjl 	}
1373*cb5caa98Sdjl 
1374*cb5caa98Sdjl 	off = offsetof(nscd_cfg_global_selfcred_t, max_per_user_nscd);
1375*cb5caa98Sdjl 	if (pdesc->p_offset == off) {
1376*cb5caa98Sdjl 		sc_cfg->max_per_user_nscd = *(int *)data;
1377*cb5caa98Sdjl 		set_selfcred_cfg('n', data);
1378*cb5caa98Sdjl 		return (NSCD_SUCCESS);
1379*cb5caa98Sdjl 	}
1380*cb5caa98Sdjl 
1381*cb5caa98Sdjl 	off = offsetof(nscd_cfg_global_selfcred_t, per_user_nscd_ttl);
1382*cb5caa98Sdjl 	if (pdesc->p_offset == off) {
1383*cb5caa98Sdjl 		sc_cfg->per_user_nscd_ttl = *(int *)data;
1384*cb5caa98Sdjl 		set_selfcred_cfg('t', data);
1385*cb5caa98Sdjl 		return (NSCD_SUCCESS);
1386*cb5caa98Sdjl 	}
1387*cb5caa98Sdjl 
1388*cb5caa98Sdjl 	return (NSCD_SUCCESS);
1389*cb5caa98Sdjl }
1390*cb5caa98Sdjl 
1391*cb5caa98Sdjl /* ARGSUSED */
1392*cb5caa98Sdjl nscd_rc_t
1393*cb5caa98Sdjl _nscd_cfg_selfcred_verify(
1394*cb5caa98Sdjl 	void				*data,
1395*cb5caa98Sdjl 	struct	nscd_cfg_param_desc	*pdesc,
1396*cb5caa98Sdjl 	nscd_cfg_id_t			*nswdb,
1397*cb5caa98Sdjl 	nscd_cfg_flag_t			dflag,
1398*cb5caa98Sdjl 	nscd_cfg_error_t		**errorp,
1399*cb5caa98Sdjl 	void				**cookie)
1400*cb5caa98Sdjl {
1401*cb5caa98Sdjl 
1402*cb5caa98Sdjl 	return (NSCD_SUCCESS);
1403*cb5caa98Sdjl }
1404*cb5caa98Sdjl 
1405*cb5caa98Sdjl /* ARGSUSED */
1406*cb5caa98Sdjl nscd_rc_t
1407*cb5caa98Sdjl _nscd_cfg_selfcred_get_stat(
1408*cb5caa98Sdjl 	void				**stat,
1409*cb5caa98Sdjl 	struct nscd_cfg_stat_desc	*sdesc,
1410*cb5caa98Sdjl 	nscd_cfg_id_t			*nswdb,
1411*cb5caa98Sdjl 	nscd_cfg_flag_t			*dflag,
1412*cb5caa98Sdjl 	void				(**free_stat)(void *stat),
1413*cb5caa98Sdjl 	nscd_cfg_error_t		**errorp)
1414*cb5caa98Sdjl {
1415*cb5caa98Sdjl 	return (NSCD_SUCCESS);
1416*cb5caa98Sdjl }
1417*cb5caa98Sdjl 
1418*cb5caa98Sdjl static int
1419*cb5caa98Sdjl check_uid(char *pid_name)
1420*cb5caa98Sdjl {
1421*cb5caa98Sdjl 	char		pname[PATH_MAX];
1422*cb5caa98Sdjl 	static pid_t	pid = 0;
1423*cb5caa98Sdjl 	static uid_t	uid = 0;
1424*cb5caa98Sdjl 	static uid_t	euid = 0;
1425*cb5caa98Sdjl 	int		pfd; /* file descriptor for /proc/<pid>/psinfo */
1426*cb5caa98Sdjl 	psinfo_t 	info;  /* process information from /proc */
1427*cb5caa98Sdjl 
1428*cb5caa98Sdjl 	if (uid == 0)  {
1429*cb5caa98Sdjl 		pid = getpid();
1430*cb5caa98Sdjl 		uid = getuid();
1431*cb5caa98Sdjl 		euid = geteuid();
1432*cb5caa98Sdjl 	}
1433*cb5caa98Sdjl 
1434*cb5caa98Sdjl 	(void) snprintf(pname, sizeof (pname), "/proc/%s/psinfo", pid_name);
1435*cb5caa98Sdjl retry:
1436*cb5caa98Sdjl 	if ((pfd = open(pname, O_RDONLY)) == -1) {
1437*cb5caa98Sdjl 		/* Process may have exited */
1438*cb5caa98Sdjl 			return (1);
1439*cb5caa98Sdjl 	}
1440*cb5caa98Sdjl 
1441*cb5caa98Sdjl 	/*
1442*cb5caa98Sdjl 	 * Get the info structure for the process and close quickly.
1443*cb5caa98Sdjl 	 */
1444*cb5caa98Sdjl 	if (read(pfd, (char *)&info, sizeof (info)) < 0) {
1445*cb5caa98Sdjl 		int	saverr = errno;
1446*cb5caa98Sdjl 
1447*cb5caa98Sdjl 		(void) close(pfd);
1448*cb5caa98Sdjl 		if (saverr == EAGAIN)
1449*cb5caa98Sdjl 			goto retry;
1450*cb5caa98Sdjl 		if (saverr != ENOENT)
1451*cb5caa98Sdjl 			return (1);
1452*cb5caa98Sdjl 	}
1453*cb5caa98Sdjl 	(void) close(pfd);
1454*cb5caa98Sdjl 
1455*cb5caa98Sdjl 	if (info.pr_pid != pid &&
1456*cb5caa98Sdjl 		info.pr_uid == uid && info.pr_euid == euid)
1457*cb5caa98Sdjl 		return (0);
1458*cb5caa98Sdjl 	else
1459*cb5caa98Sdjl 		return (1);
1460*cb5caa98Sdjl }
1461*cb5caa98Sdjl 
1462*cb5caa98Sdjl 
1463*cb5caa98Sdjl /*
1464*cb5caa98Sdjl  * FUNCTION: check_user_process
1465*cb5caa98Sdjl  */
1466*cb5caa98Sdjl /*ARGSUSED*/
1467*cb5caa98Sdjl static void *
1468*cb5caa98Sdjl check_user_process(void *arg)
1469*cb5caa98Sdjl {
1470*cb5caa98Sdjl 
1471*cb5caa98Sdjl 	DIR		*dp;
1472*cb5caa98Sdjl 	struct dirent	*ep;
1473*cb5caa98Sdjl 	int		found;
1474*cb5caa98Sdjl 	char		*me = "check_user_process";
1475*cb5caa98Sdjl 
1476*cb5caa98Sdjl 	/*CONSTCOND*/
1477*cb5caa98Sdjl 	while (1) {
1478*cb5caa98Sdjl 		(void) sleep(60);
1479*cb5caa98Sdjl 
1480*cb5caa98Sdjl 		found = 0;
1481*cb5caa98Sdjl 
1482*cb5caa98Sdjl 		/*
1483*cb5caa98Sdjl 		 * search the /proc directory and look at each process
1484*cb5caa98Sdjl 		 */
1485*cb5caa98Sdjl 		if ((dp = opendir("/proc")) == NULL) {
1486*cb5caa98Sdjl 			_NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_ERROR)
1487*cb5caa98Sdjl 			(me, "unable to open the /proc directory\n");
1488*cb5caa98Sdjl 			continue;
1489*cb5caa98Sdjl 		}
1490*cb5caa98Sdjl 
1491*cb5caa98Sdjl 		/* for each active process */
1492*cb5caa98Sdjl 		while (ep = readdir(dp)) {
1493*cb5caa98Sdjl 			if (ep->d_name[0] == '.')    /* skip . and .. */
1494*cb5caa98Sdjl 				continue;
1495*cb5caa98Sdjl 			if (check_uid(ep->d_name) == 0) {
1496*cb5caa98Sdjl 				found = 1;
1497*cb5caa98Sdjl 				break;
1498*cb5caa98Sdjl 			}
1499*cb5caa98Sdjl 		}
1500*cb5caa98Sdjl 
1501*cb5caa98Sdjl 		/*
1502*cb5caa98Sdjl 		 * if no process running as the PUN uid found, exit
1503*cb5caa98Sdjl 		 * to kill this PUN
1504*cb5caa98Sdjl 		 */
1505*cb5caa98Sdjl 		if (found == 0) {
1506*cb5caa98Sdjl 			(void) closedir(dp);
1507*cb5caa98Sdjl 			exit(1);
1508*cb5caa98Sdjl 		}
1509*cb5caa98Sdjl 		(void) closedir(dp);
1510*cb5caa98Sdjl 	}
1511*cb5caa98Sdjl 	/* NOTREACHED */
1512*cb5caa98Sdjl 	/*LINTED E_FUNC_HAS_NO_RETURN_STMT*/
1513*cb5caa98Sdjl }
1514*cb5caa98Sdjl 
1515*cb5caa98Sdjl static nscd_rc_t
1516*cb5caa98Sdjl init_user_proc_monitor() {
1517*cb5caa98Sdjl 
1518*cb5caa98Sdjl 	int	errnum;
1519*cb5caa98Sdjl 	char	*me = "init_user_proc_monitor";
1520*cb5caa98Sdjl 
1521*cb5caa98Sdjl 	_NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
1522*cb5caa98Sdjl 	(me, "initializing the user process monitor\n");
1523*cb5caa98Sdjl 
1524*cb5caa98Sdjl 	/*
1525*cb5caa98Sdjl 	 * start a thread to make sure there is at least a process
1526*cb5caa98Sdjl 	 * running as the PUN user. If not, terminate this PUN.
1527*cb5caa98Sdjl 	 */
1528*cb5caa98Sdjl 	if (thr_create(NULL, NULL, check_user_process,
1529*cb5caa98Sdjl 		NULL, THR_DETACHED, NULL) != 0) {
1530*cb5caa98Sdjl 		errnum = errno;
1531*cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_ERROR)
1532*cb5caa98Sdjl 		(me, "thr_create: %s\n", strerror(errnum));
1533*cb5caa98Sdjl 		return (NSCD_THREAD_CREATE_ERROR);
1534*cb5caa98Sdjl 	}
1535*cb5caa98Sdjl 
1536*cb5caa98Sdjl 	return (NSCD_SUCCESS);
1537*cb5caa98Sdjl }
1538*cb5caa98Sdjl 
1539*cb5caa98Sdjl static void *
1540*cb5caa98Sdjl get_smf_prop(const char *var, char type, void *def_val)
1541*cb5caa98Sdjl {
1542*cb5caa98Sdjl 	scf_simple_prop_t	*prop;
1543*cb5caa98Sdjl 	void			*val = def_val;
1544*cb5caa98Sdjl 	char			*me = "get_smf_prop";
1545*cb5caa98Sdjl 
1546*cb5caa98Sdjl 	prop = scf_simple_prop_get(NULL, NULL, "config", var);
1547*cb5caa98Sdjl 	if (prop) {
1548*cb5caa98Sdjl 		switch (type) {
1549*cb5caa98Sdjl 		case 'b':
1550*cb5caa98Sdjl 			val = scf_simple_prop_next_boolean(prop);
1551*cb5caa98Sdjl 			break;
1552*cb5caa98Sdjl 
1553*cb5caa98Sdjl 		case 'i':
1554*cb5caa98Sdjl 			val = scf_simple_prop_next_integer(prop);
1555*cb5caa98Sdjl 			break;
1556*cb5caa98Sdjl 
1557*cb5caa98Sdjl 		case 'c':
1558*cb5caa98Sdjl 			val = scf_simple_prop_next_count(prop);
1559*cb5caa98Sdjl 			break;
1560*cb5caa98Sdjl 		}
1561*cb5caa98Sdjl 		scf_simple_prop_free(prop);
1562*cb5caa98Sdjl 	}
1563*cb5caa98Sdjl 
1564*cb5caa98Sdjl 	if (prop == NULL || val == NULL) {
1565*cb5caa98Sdjl 		char	vs[64];
1566*cb5caa98Sdjl 
1567*cb5caa98Sdjl 		switch (type) {
1568*cb5caa98Sdjl 		case 'b':
1569*cb5caa98Sdjl 			if (*(uint8_t *)def_val)
1570*cb5caa98Sdjl 				(void) strcpy(vs, "yes");
1571*cb5caa98Sdjl 			else
1572*cb5caa98Sdjl 				(void) strcpy(vs, "no");
1573*cb5caa98Sdjl 
1574*cb5caa98Sdjl 			break;
1575*cb5caa98Sdjl 
1576*cb5caa98Sdjl 		case 'i':
1577*cb5caa98Sdjl 		case 'c':
1578*cb5caa98Sdjl 			(void) sprintf(vs, "%lld", *(int64_t *)def_val);
1579*cb5caa98Sdjl 			break;
1580*cb5caa98Sdjl 
1581*cb5caa98Sdjl 		}
1582*cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_ALERT)
1583*cb5caa98Sdjl 		(me, "no value for config/%s (%s). "
1584*cb5caa98Sdjl 			"Using default \"%s\"\n", var,
1585*cb5caa98Sdjl 			scf_strerror(scf_error()), vs);
1586*cb5caa98Sdjl 	}
1587*cb5caa98Sdjl 
1588*cb5caa98Sdjl 	return (val);
1589*cb5caa98Sdjl }
1590