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