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 /* close all except the log file */ 827 if (_logfd > 0) { 828 int i; 829 for (i = 0; i < _logfd; i++) 830 (void) close(i); 831 closefrom(_logfd + 1); 832 } else 833 closefrom(0); 834 835 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG) 836 (me, "child %d\n", getpid()); 837 838 (void) setgid(set2gid); 839 (void) setuid(set2uid); 840 841 /* set up the door and server thread pool */ 842 if ((_doorfd = _nscd_setup_child_server(_doorfd)) == -1) 843 exit(-1); 844 845 /* tell libsldap to do self cred only */ 846 (void) setup_ldap_backend(); 847 848 /* notify main that child is active */ 849 ih.slot = slot; 850 for (ret = NSS_ALTRETRY; ret == NSS_ALTRETRY; ) 851 ret = _nscd_doorcall_sendfd(_doorfd, 852 NSCD_IMHERE | (NSCD_CHILD & NSCD_WHOAMI), 853 &ih, sizeof (ih), NULL); 854 855 NSCD_RETURN_STATUS_SUCCESS(phdr); 856 } if (cid == (pid_t)-1) { 857 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG) 858 (me, "forker unable to fork ...\n"); 859 860 /* enter the maintenance mode */ 861 if ((fmri = getenv("SMF_FMRI")) != NULL) { 862 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG) 863 (me, "entering maintenance mode ...\n"); 864 (void) smf_maintain_instance(fmri, SMF_TEMPORARY); 865 } 866 exit(0); 867 } else { 868 /* 869 * start the monitor so as to exit as early as 870 * possible if no other processes are running 871 * with the same PUN uid (i.e., this PUN is 872 * not needed any more) 873 */ 874 (void) init_user_proc_monitor(); 875 876 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG) 877 (me, "child forked: parent pid = %d, child pid = %d\n", 878 getpid(), cid); 879 880 NSCD_SET_STATUS_SUCCESS(phdr); 881 } 882 883 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG) 884 (me, "after fork\n"); 885 } 886 887 static void 888 selfcred_fork( 889 void *buf, 890 int doorfd, 891 int cslot, 892 uid_t uid, 893 gid_t gid) 894 { 895 int ret; 896 nscd_fork_t f; 897 nss_pheader_t *phdr = (nss_pheader_t *)buf; 898 char *me = "selfcred_fork"; 899 900 /* if no door fd, do nothing */ 901 if (doorfd == -1) { 902 NSCD_SET_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0, 903 NSCD_SELF_CRED_NO_DOOR); 904 } 905 906 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG) 907 (me, "sending fork request to door %d for slot %d " 908 "(uid = %d, gid = %d)\n", doorfd, cslot, uid, gid); 909 910 f.slot = cslot; 911 f.uid = uid; 912 f.gid = gid; 913 914 ret = _nscd_doorcall_fd(doorfd, NSCD_FORK|(_whoami&NSCD_WHOAMI), 915 &f, sizeof (f), NULL, 0, phdr); 916 917 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG) 918 (me, "fork request sent to door %d for slot %d (rc = %d)\n", 919 doorfd, cslot, ret); 920 921 if (NSCD_STATUS_IS_NOT_OK(phdr)) { 922 923 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG) 924 (me, "fork request sent to door %d for slot %d failed: " 925 "status = %d, errno = %s, nscd status = %d\n", doorfd, 926 cslot, NSCD_GET_STATUS(phdr), strerror(NSCD_GET_ERRNO(phdr)), 927 NSCD_GET_NSCD_STATUS(phdr)); 928 929 } 930 } 931 932 void 933 _nscd_proc_alt_get( 934 void *buf, 935 int *door) 936 { 937 int errnum; 938 uid_t set2uid; 939 gid_t set2gid; 940 nss_pheader_t *phdr = (nss_pheader_t *)buf; 941 char *me = "_nscd_proc_alt_get"; 942 ucred_t *uc = NULL; 943 child_t *ch; 944 945 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG) 946 (me, "getting an alternate door ...\n"); 947 948 /* make sure there is a door to talk to the forker */ 949 if (forking_door == -1) { 950 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_ERROR) 951 (me, "no door to talk to the forker\n"); 952 953 NSCD_RETURN_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0, 954 NSCD_SELF_CRED_NO_FORKER); 955 } 956 957 /* get door client's credential information */ 958 if (door_ucred(&uc) != 0) { 959 errnum = errno; 960 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG) 961 (me, "door_ucred failed: %s\n", strerror(errnum)); 962 963 NSCD_RETURN_N2N_STATUS(phdr, NSS_NSCD_PRIV, errnum, 964 NSCD_DOOR_UCRED_ERROR); 965 } 966 967 /* get door client's effective uid and effective gid */ 968 set2uid = ucred_geteuid(uc); 969 set2gid = ucred_getegid(uc); 970 ucred_free(uc); 971 uc = NULL; 972 973 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG) 974 (me, "child uid = %d, gid = %d\n", set2uid, set2gid); 975 976 /* is a slot available ? if not, no one to serve */ 977 if (child == NULL || (ch = get_cslot(set2uid, 0)) == NULL) { 978 979 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG) 980 (me, "no child slot available (child array = %p, slot = %d)\n", 981 child, ch->child_slot); 982 983 NSCD_RETURN_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0, 984 NSCD_SELF_CRED_NO_CHILD_SLOT); 985 } 986 987 /* create the per user nscd if necessary */ 988 if (ch->child_state != CHILD_STATE_PIDKNOWN) { 989 990 nss_pheader_t phdr1; 991 NSCD_CLEAR_STATUS(&phdr1); 992 993 (void) mutex_lock(ch->mutex); 994 if (ch->child_state == CHILD_STATE_UIDKNOWN) { 995 996 /* ask forker to fork a new child */ 997 selfcred_fork(&phdr1, forking_door, ch->child_slot, 998 set2uid, set2gid); 999 if (NSCD_STATUS_IS_NOT_OK(&phdr1)) { 1000 (void) mutex_unlock(ch->mutex); 1001 NSCD_COPY_STATUS(phdr, &phdr1); 1002 return; 1003 } 1004 ch->child_state = CHILD_STATE_FORKSENT; 1005 } 1006 1007 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG) 1008 (me, "waiting for door (slot = %d, uid = %d, gid = %d)\n", 1009 ch->child_slot, set2uid, set2gid); 1010 1011 /* wait for the per user nscd to become available */ 1012 while (ch->child_state == CHILD_STATE_FORKSENT) { 1013 timestruc_t to; 1014 int err; 1015 int ttl = 5; 1016 1017 to.tv_sec = ttl; 1018 to.tv_nsec = 0; 1019 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG) 1020 (me, "cond_reltimedwait %d seconds\n", ttl); 1021 err = cond_reltimedwait(ch->cond, ch->mutex, &to); 1022 if (err == ETIME) { 1023 ch->child_state = 1024 CHILD_STATE_UIDKNOWN; 1025 _NSCD_LOG(NSCD_LOG_SELF_CRED, 1026 NSCD_LOG_LEVEL_DEBUG) 1027 (me, "door wait timedout (slot = %d)\n", 1028 ch->child_slot); 1029 break; 1030 } 1031 } 1032 (void) mutex_unlock(ch->mutex); 1033 } 1034 1035 if (ch->child_state != CHILD_STATE_PIDKNOWN) { 1036 1037 NSCD_RETURN_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0, 1038 NSCD_SELF_CRED_INVALID_SLOT_STATE); 1039 } 1040 1041 *door = ch->child_door; 1042 1043 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG) 1044 (me, "returning door %d for slot %d, uid %d, gid = %d\n", 1045 *door, ch->child_slot, set2uid, set2gid); 1046 1047 NSCD_RETURN_STATUS(phdr, NSS_ALTRETRY, 0); 1048 } 1049 1050 static char ** 1051 cpargv( 1052 int argc, 1053 char **inargv) 1054 { 1055 char **newargv; 1056 int c = 4; 1057 int i = 0, j, k = 0, n = 0; 1058 1059 newargv = (char **)calloc(c + 1, sizeof (char *)); 1060 if (newargv == NULL) 1061 return (NULL); 1062 1063 newargv[n] = strdup(inargv[0]); 1064 if (newargv[n++] == NULL) { 1065 free(newargv); 1066 return (NULL); 1067 } 1068 1069 newargv[n] = strdup("-F"); 1070 if (newargv[n++] == NULL) { 1071 free(newargv[0]); 1072 free(newargv); 1073 return (NULL); 1074 } 1075 1076 for (i = 1; i < argc; i++) { 1077 if (strcmp(inargv[i], "-f") == 0) 1078 k = 2; 1079 if (k == 0) 1080 continue; 1081 1082 newargv[n] = strdup(inargv[i]); 1083 if (newargv[n] == NULL) { 1084 for (j = 0; j < n; j++) 1085 free(newargv[j]); 1086 free(newargv); 1087 return (NULL); 1088 } 1089 1090 k--; 1091 n++; 1092 } 1093 return (newargv); 1094 } 1095 1096 1097 void 1098 _nscd_start_forker( 1099 char *path, 1100 int argc, 1101 char **argv) 1102 { 1103 pid_t cid; 1104 struct rlimit rl; 1105 char *me = "_nscd_start_forker"; 1106 1107 /* if self cred is not configured, do nothing */ 1108 if (!_nscd_is_self_cred_on(1, NULL)) 1109 return; 1110 1111 /* save pathname and generate the new argv for the forker */ 1112 execpath = strdup(path); 1113 execargv = cpargv(argc, argv); 1114 if (execpath == NULL || execargv == NULL) 1115 exit(1); 1116 1117 switch (cid = fork1()) { 1118 case (pid_t)-1: 1119 exit(1); 1120 break; 1121 case 0: 1122 /* start the forker nscd */ 1123 (void) execv(path, execargv); 1124 exit(0); 1125 break; 1126 default: 1127 /* main nscd */ 1128 /* remember process id of the forker */ 1129 forker_pid = cid; 1130 1131 /* set NOFILE to unlimited */ 1132 rl.rlim_cur = rl.rlim_max = RLIM_INFINITY; 1133 if (setrlimit(RLIMIT_NOFILE, &rl) < 0) { 1134 _NSCD_LOG(NSCD_LOG_SELF_CRED, 1135 NSCD_LOG_LEVEL_ERROR) 1136 (me, "Cannot set open file limit: %s\n", 1137 strerror(errno)); 1138 exit(1); 1139 } 1140 1141 /* enable child nscd management */ 1142 (void) _nscd_init_cslots(); 1143 break; 1144 } 1145 } 1146 1147 static nscd_rc_t 1148 get_ldap_funcs( 1149 char *name, 1150 void **func_p) 1151 { 1152 char *me = "get_ldap_funcs"; 1153 static void *handle = NULL; 1154 void *sym; 1155 1156 if (name == NULL && handle != NULL) { 1157 (void) dlclose(handle); 1158 return (NSCD_SUCCESS); 1159 } 1160 /* no handle to close, it's OK */ 1161 if (name == NULL) 1162 return (NSCD_SUCCESS); 1163 1164 if (handle == NULL) { 1165 handle = dlopen("libsldap.so.1", RTLD_LAZY); 1166 if (handle == NULL) { 1167 1168 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_ERROR) 1169 (me, "unable to dlopen libsldap.so.1"); 1170 return (NSCD_CFG_DLOPEN_ERROR); 1171 } 1172 } 1173 1174 if ((sym = dlsym(handle, name)) == NULL) { 1175 1176 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_ERROR) 1177 (me, "unable to find symbol %s", name); 1178 return (NSCD_CFG_DLSYM_ERROR); 1179 } else 1180 (void) memcpy(func_p, &sym, sizeof (void *)); 1181 1182 return (NSCD_SUCCESS); 1183 } 1184 1185 1186 int 1187 _nscd_is_self_cred_on(int recheck, char **dblist) 1188 { 1189 static int checked = 0; 1190 static int is_on = 0; 1191 static int (*ldap_func)(); 1192 char *srcs = "ldap"; /* only ldap support self cred */ 1193 int ldap_on = 0; 1194 1195 char *ldap_sc_func = "__ns_ldap_self_gssapi_config"; 1196 ns_ldap_self_gssapi_config_t ldap_config; 1197 1198 if (checked && !recheck) { 1199 if (is_on && dblist != NULL) 1200 *dblist = selfcred_dbs; 1201 return (is_on); 1202 } 1203 1204 if (selfcred_dbs != NULL) 1205 free(selfcred_dbs); 1206 selfcred_dbs = _nscd_srcs_in_db_nsw_policy(1, &srcs); 1207 1208 /* 1209 * also check the ldap backend to see if 1210 * the configuration there is good for 1211 * doing self credentialing 1212 */ 1213 if (ldap_func == NULL) 1214 (void) get_ldap_funcs(ldap_sc_func, (void **)&ldap_func); 1215 if (ldap_func != NULL) { 1216 if (ldap_func(&ldap_config) == NS_LDAP_SUCCESS && 1217 ldap_config != NS_LDAP_SELF_GSSAPI_CONFIG_NONE) 1218 ldap_on = 1; 1219 } 1220 1221 is_on = pu_nscd_enabled == nscd_true && 1222 ldap_on && selfcred_dbs != NULL; 1223 1224 checked = 1; 1225 1226 if (is_on && dblist != NULL) 1227 *dblist = selfcred_dbs; 1228 1229 return (is_on); 1230 } 1231 1232 static nscd_rc_t 1233 setup_ldap_backend() 1234 { 1235 nscd_rc_t rc; 1236 static void (*ldap_func)(); 1237 char *ldap_sc_func = "__ns_ldap_self_gssapi_only_set"; 1238 if (ldap_func == NULL) 1239 rc = get_ldap_funcs(ldap_sc_func, (void **)&ldap_func); 1240 if (ldap_func != NULL) { 1241 ldap_func(1); 1242 return (NSCD_SUCCESS); 1243 } 1244 return (rc); 1245 } 1246 1247 /*ARGSUSED*/ 1248 void 1249 _nscd_peruser_getadmin( 1250 void *buf, 1251 int buf_size) 1252 { 1253 void *result_mn = NSCD_N2N_DOOR_DATA(void, buf); 1254 int errnum = 0; 1255 int ret; 1256 uid_t uid; 1257 nss_pheader_t *phdr = (nss_pheader_t *)buf; 1258 char *me = "_nscd_peruser_getadmin"; 1259 ucred_t *uc = NULL; 1260 child_t *ch; 1261 1262 /* get door client's credential information */ 1263 if (door_ucred(&uc) != 0) { 1264 errnum = errno; 1265 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG) 1266 (me, "door_ucred failed: %s\n", strerror(errnum)); 1267 1268 NSCD_RETURN_N2N_STATUS(phdr, NSS_NSCD_PRIV, errnum, 1269 NSCD_DOOR_UCRED_ERROR); 1270 } 1271 1272 /* get door client's effective uid */ 1273 uid = ucred_geteuid(uc); 1274 ucred_free(uc); 1275 uc = NULL; 1276 1277 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG) 1278 (me, "per user get admin ... (uid = %d)\n", uid); 1279 1280 /* is the per-user nscd running ? if not, no one to serve */ 1281 ch = get_cslot(uid, 1); 1282 if (ch == NULL) { 1283 NSCD_RETURN_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0, 1284 NSCD_SELF_CRED_NO_CHILD_SLOT); 1285 } 1286 1287 ret = _nscd_doorcall_fd(ch->child_door, NSCD_GETADMIN, 1288 NULL, sizeof (nscd_admin_t), result_mn, 1289 sizeof (nscd_admin_t), phdr); 1290 1291 if (ret == NSS_SUCCESS) { 1292 phdr->data_len = sizeof (nscd_admin_t); 1293 return; 1294 } 1295 } 1296 1297 static void 1298 set_selfcred_cfg( 1299 char param, 1300 void *data) 1301 { 1302 int64_t prop_int; 1303 char *me = "set_selfcred_cfg"; 1304 1305 if (param == 'a' || param == 'e') { 1306 pu_nscd_enabled = *(uint8_t *)get_smf_prop( 1307 "enable_per_user_lookup", 'b', data); 1308 1309 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG) 1310 (me, "self cred config: enabled = %d\n", pu_nscd_enabled); 1311 } 1312 1313 if (param == 'a' || param == 't') { 1314 prop_int = *(int *)data; 1315 pu_nscd_ttl = *(int64_t *)get_smf_prop( 1316 "per_user_nscd_time_to_live", 'i', &prop_int); 1317 1318 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG) 1319 (me, "self cred config: PUN TTL = %d\n", pu_nscd_ttl); 1320 } 1321 } 1322 1323 /* ARGSUSED */ 1324 nscd_rc_t 1325 _nscd_cfg_selfcred_notify( 1326 void *data, 1327 struct nscd_cfg_param_desc *pdesc, 1328 nscd_cfg_id_t *nswdb, 1329 nscd_cfg_flag_t dflag, 1330 nscd_cfg_error_t **errorp, 1331 void *cookie) 1332 { 1333 1334 nscd_cfg_global_selfcred_t *sc_cfg = &nscd_selfcred_cfg_g; 1335 int off; 1336 1337 /* 1338 * At init time, the whole group of config params are received. 1339 * At update time, group or individual parameter value could 1340 * be received. 1341 */ 1342 1343 if (_nscd_cfg_flag_is_set(dflag, NSCD_CFG_DFLAG_GROUP)) { 1344 1345 *sc_cfg = *(nscd_cfg_global_selfcred_t *)data; 1346 1347 off = offsetof(nscd_cfg_global_selfcred_t, 1348 enable_selfcred); 1349 set_selfcred_cfg('e', (char *)data + off); 1350 1351 off = offsetof(nscd_cfg_global_selfcred_t, 1352 max_per_user_nscd); 1353 set_selfcred_cfg('n', (char *)data + off); 1354 1355 off = offsetof(nscd_cfg_global_selfcred_t, 1356 per_user_nscd_ttl); 1357 set_selfcred_cfg('t', (char *)data + off); 1358 1359 return (NSCD_SUCCESS); 1360 } 1361 1362 /* 1363 * individual config parameter 1364 */ 1365 off = offsetof(nscd_cfg_global_selfcred_t, enable_selfcred); 1366 if (pdesc->p_offset == off) { 1367 sc_cfg->enable_selfcred = *(nscd_bool_t *)data; 1368 set_selfcred_cfg('e', data); 1369 return (NSCD_SUCCESS); 1370 } 1371 1372 off = offsetof(nscd_cfg_global_selfcred_t, max_per_user_nscd); 1373 if (pdesc->p_offset == off) { 1374 sc_cfg->max_per_user_nscd = *(int *)data; 1375 set_selfcred_cfg('n', data); 1376 return (NSCD_SUCCESS); 1377 } 1378 1379 off = offsetof(nscd_cfg_global_selfcred_t, per_user_nscd_ttl); 1380 if (pdesc->p_offset == off) { 1381 sc_cfg->per_user_nscd_ttl = *(int *)data; 1382 set_selfcred_cfg('t', data); 1383 return (NSCD_SUCCESS); 1384 } 1385 1386 return (NSCD_SUCCESS); 1387 } 1388 1389 /* ARGSUSED */ 1390 nscd_rc_t 1391 _nscd_cfg_selfcred_verify( 1392 void *data, 1393 struct nscd_cfg_param_desc *pdesc, 1394 nscd_cfg_id_t *nswdb, 1395 nscd_cfg_flag_t dflag, 1396 nscd_cfg_error_t **errorp, 1397 void **cookie) 1398 { 1399 1400 return (NSCD_SUCCESS); 1401 } 1402 1403 /* ARGSUSED */ 1404 nscd_rc_t 1405 _nscd_cfg_selfcred_get_stat( 1406 void **stat, 1407 struct nscd_cfg_stat_desc *sdesc, 1408 nscd_cfg_id_t *nswdb, 1409 nscd_cfg_flag_t *dflag, 1410 void (**free_stat)(void *stat), 1411 nscd_cfg_error_t **errorp) 1412 { 1413 return (NSCD_SUCCESS); 1414 } 1415 1416 static int 1417 check_uid(char *pid_name) 1418 { 1419 char pname[PATH_MAX]; 1420 static pid_t pid = 0; 1421 static uid_t uid = 0; 1422 static uid_t euid = 0; 1423 int pfd; /* file descriptor for /proc/<pid>/psinfo */ 1424 psinfo_t info; /* process information from /proc */ 1425 1426 if (uid == 0) { 1427 pid = getpid(); 1428 uid = getuid(); 1429 euid = geteuid(); 1430 } 1431 1432 (void) snprintf(pname, sizeof (pname), "/proc/%s/psinfo", pid_name); 1433 retry: 1434 if ((pfd = open(pname, O_RDONLY)) == -1) { 1435 /* Process may have exited */ 1436 return (1); 1437 } 1438 1439 /* 1440 * Get the info structure for the process and close quickly. 1441 */ 1442 if (read(pfd, (char *)&info, sizeof (info)) < 0) { 1443 int saverr = errno; 1444 1445 (void) close(pfd); 1446 if (saverr == EAGAIN) 1447 goto retry; 1448 if (saverr != ENOENT) 1449 return (1); 1450 } 1451 (void) close(pfd); 1452 1453 if (info.pr_pid != pid && 1454 info.pr_uid == uid && info.pr_euid == euid) 1455 return (0); 1456 else 1457 return (1); 1458 } 1459 1460 1461 /* 1462 * FUNCTION: check_user_process 1463 */ 1464 /*ARGSUSED*/ 1465 static void * 1466 check_user_process(void *arg) 1467 { 1468 1469 DIR *dp; 1470 struct dirent *ep; 1471 int found; 1472 char *me = "check_user_process"; 1473 1474 /*CONSTCOND*/ 1475 while (1) { 1476 (void) sleep(60); 1477 1478 found = 0; 1479 1480 /* 1481 * search the /proc directory and look at each process 1482 */ 1483 if ((dp = opendir("/proc")) == NULL) { 1484 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_ERROR) 1485 (me, "unable to open the /proc directory\n"); 1486 continue; 1487 } 1488 1489 /* for each active process */ 1490 while (ep = readdir(dp)) { 1491 if (ep->d_name[0] == '.') /* skip . and .. */ 1492 continue; 1493 if (check_uid(ep->d_name) == 0) { 1494 found = 1; 1495 break; 1496 } 1497 } 1498 1499 /* 1500 * if no process running as the PUN uid found, exit 1501 * to kill this PUN 1502 */ 1503 if (found == 0) { 1504 (void) closedir(dp); 1505 exit(1); 1506 } 1507 (void) closedir(dp); 1508 } 1509 /* NOTREACHED */ 1510 /*LINTED E_FUNC_HAS_NO_RETURN_STMT*/ 1511 } 1512 1513 static nscd_rc_t 1514 init_user_proc_monitor() { 1515 1516 int errnum; 1517 char *me = "init_user_proc_monitor"; 1518 1519 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG) 1520 (me, "initializing the user process monitor\n"); 1521 1522 /* 1523 * start a thread to make sure there is at least a process 1524 * running as the PUN user. If not, terminate this PUN. 1525 */ 1526 if (thr_create(NULL, NULL, check_user_process, 1527 NULL, THR_DETACHED, NULL) != 0) { 1528 errnum = errno; 1529 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_ERROR) 1530 (me, "thr_create: %s\n", strerror(errnum)); 1531 return (NSCD_THREAD_CREATE_ERROR); 1532 } 1533 1534 return (NSCD_SUCCESS); 1535 } 1536 1537 static void * 1538 get_smf_prop(const char *var, char type, void *def_val) 1539 { 1540 scf_simple_prop_t *prop; 1541 void *val = def_val; 1542 char *me = "get_smf_prop"; 1543 1544 prop = scf_simple_prop_get(NULL, NULL, "config", var); 1545 if (prop) { 1546 switch (type) { 1547 case 'b': 1548 val = scf_simple_prop_next_boolean(prop); 1549 break; 1550 1551 case 'i': 1552 val = scf_simple_prop_next_integer(prop); 1553 break; 1554 1555 case 'c': 1556 val = scf_simple_prop_next_count(prop); 1557 break; 1558 } 1559 scf_simple_prop_free(prop); 1560 } 1561 1562 if (prop == NULL || val == NULL) { 1563 char vs[64]; 1564 1565 switch (type) { 1566 case 'b': 1567 if (*(uint8_t *)def_val) 1568 (void) strcpy(vs, "yes"); 1569 else 1570 (void) strcpy(vs, "no"); 1571 1572 break; 1573 1574 case 'i': 1575 case 'c': 1576 (void) sprintf(vs, "%lld", *(int64_t *)def_val); 1577 break; 1578 1579 } 1580 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_ALERT) 1581 (me, "no value for config/%s (%s). " 1582 "Using default \"%s\"\n", var, 1583 scf_strerror(scf_error()), vs); 1584 } 1585 1586 return (val); 1587 } 1588