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