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