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