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