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 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 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 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 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 * 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 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 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 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 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 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 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 * 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 * 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 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 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 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 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 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 ** 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 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 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 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 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 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 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 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 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 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 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 * 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 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 * 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