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