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