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