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