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