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_RETURN_N2N_STATUS(phdr, NSS_NSCD_PRIV, errnum, 524 NSCD_DOOR_UCRED_ERROR); 525 } 526 uid = ucred_geteuid(uc); 527 528 switch (iam) { 529 530 case NSCD_MAIN: 531 if (_whoami == NSCD_MAIN || uid != main_uid) { 532 /* 533 * I'm main, or uid from door is not correct, 534 * this must be an imposter 535 */ 536 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG) 537 (me, "MAIN IMPOSTER CAUGHT!\n"); 538 539 540 NSCD_SET_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0, 541 NSCD_SELF_CRED_MAIN_IMPOSTER); 542 } 543 break; 544 545 case NSCD_FORKER: 546 if (_whoami == NSCD_FORKER || uid != forker_uid) { 547 /* 548 * I'm forker, or uid from door is not correct, 549 * this must be an imposter 550 */ 551 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG) 552 (me, "FORKER IMPOSTER CAUGHT!\n"); 553 554 555 NSCD_SET_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0, 556 NSCD_SELF_CRED_FORKER_IMPOSTER); 557 break; 558 } 559 560 /* only main needs to know the forker */ 561 if (_whoami != NSCD_MAIN) { 562 563 NSCD_SET_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0, 564 NSCD_SELF_CRED_WRONG_NSCD); 565 break; 566 } 567 568 if (ucred_getpid(uc) != forker_pid) { 569 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG) 570 (me, "FORKER IMPOSTER CAUGHT: pid = %d should be %d\n", 571 ucred_getpid(uc), forker_pid); 572 573 574 NSCD_SET_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0, 575 NSCD_SELF_CRED_FORKER_IMPOSTER); 576 break; 577 } 578 579 if (n_desc < 1) { 580 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG) 581 (me, "BAD FORKER, NO DOOR!\n"); 582 583 584 NSCD_SET_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0, 585 NSCD_SELF_CRED_NO_DOOR); 586 break; 587 } 588 589 if ((dp->d_attributes & DOOR_DESCRIPTOR) && 590 dp->d_data.d_desc.d_descriptor > 0 && 591 dp->d_data.d_desc.d_id != 0) { 592 (void) mutex_lock(&forking_lock); 593 if (forking_door != -1) 594 (void) close(forking_door); 595 forking_door = dp->d_data.d_desc.d_descriptor; 596 (void) mutex_unlock(&forking_lock); 597 598 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG) 599 (me, "forking door is %d\n", forking_door); 600 601 NSCD_SET_STATUS_SUCCESS(phdr); 602 } else { 603 NSCD_SET_STATUS(phdr, NSS_ALTRETRY, 0); 604 break; 605 } 606 607 /* monitor the forker nscd */ 608 (void) thr_create(NULL, 0, forker_monitor, NULL, 609 THR_DETACHED, NULL); 610 611 break; 612 613 case NSCD_CHILD: 614 if (_whoami != NSCD_MAIN) { 615 /* child nscd can only talk to the main nscd */ 616 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG) 617 (me, "CHILD IMPOSTER CAUGHT!\n"); 618 619 NSCD_SET_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0, 620 NSCD_SELF_CRED_CHILD_IMPOSTER); 621 break; 622 } 623 624 /* get the main nscd assigned slot number */ 625 ih = NSCD_N2N_DOOR_DATA(nscd_imhere_t, buf); 626 cslot = ih->slot; 627 (void) mutex_lock(&child_lock); 628 if (cslot < 0 || cslot >= max_pu_nscd) 629 ch = NULL; 630 else 631 ch = child[cslot]; 632 (void) mutex_unlock(&child_lock); 633 634 if (ch == NULL) { 635 /* Bad slot number */ 636 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG) 637 (me, "bad slot number %d\n", cslot); 638 639 NSCD_SET_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0, 640 NSCD_SELF_CRED_INVALID_SLOT_NUMBER); 641 break; 642 } 643 644 if (uid != ch->child_uid) { 645 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG) 646 (me, "CHILD IMPOSTER CAUGHT: uid = %d should be %d\n", 647 uid, ch->child_uid); 648 649 NSCD_SET_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0, 650 NSCD_SELF_CRED_CHILD_IMPOSTER); 651 break; 652 } 653 654 if (ch->child_state != CHILD_STATE_UIDKNOWN && 655 ch->child_state != CHILD_STATE_FORKSENT) { 656 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG) 657 (me, "invalid slot/child state (%d) for uid %d\n", 658 ch->child_state, uid); 659 660 NSCD_SET_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0, 661 NSCD_SELF_CRED_INVALID_SLOT_STATE); 662 break; 663 } 664 665 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG) 666 (me, "d_descriptor = %d, d_id = %lld\n", 667 dp->d_data.d_desc.d_descriptor, dp->d_data.d_desc.d_id); 668 669 if ((dp->d_attributes & DOOR_DESCRIPTOR) && 670 dp->d_data.d_desc.d_descriptor > 0 && 671 dp->d_data.d_desc.d_id != 0) { 672 (void) mutex_lock(ch->mutex); 673 if (ch->child_door != -1) 674 (void) close(ch->child_door); 675 ch->child_door = dp->d_data.d_desc.d_descriptor; 676 ch->child_pid = ucred_getpid(uc); 677 ch->child_state = CHILD_STATE_PIDKNOWN; 678 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG) 679 (me, "child in slot %d has door %d\n", 680 cslot, ch->child_door); 681 682 /* 683 * let waiters know that the child is ready to 684 * serve 685 */ 686 (void) cond_broadcast(ch->cond); 687 (void) mutex_unlock(ch->mutex); 688 689 /* monitor the child nscd */ 690 (void) thr_create(NULL, 0, child_monitor, 691 ch, THR_DETACHED, NULL); 692 NSCD_SET_STATUS_SUCCESS(phdr); 693 break; 694 } else { 695 NSCD_SET_STATUS(phdr, NSS_ALTRETRY, 0); 696 } 697 break; 698 } 699 700 ucred_free(uc); 701 uc = NULL; 702 } 703 704 void 705 _nscd_proc_pulse( 706 void *buf, 707 int iam) 708 { 709 long last_active; 710 int done = 0; 711 nss_pheader_t *phdr = (nss_pheader_t *)buf; 712 char *me = "_nscd_proc_pulse"; 713 714 /* only main nscd sends pulse */ 715 if (iam != NSCD_MAIN) { 716 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG) 717 (me, "MAIN IMPOSTER CAUGHT! i am %d not NSCD_MAIN\n", iam); 718 719 NSCD_RETURN_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0, 720 NSCD_SELF_CRED_MAIN_IMPOSTER); 721 } 722 723 /* forker doesn't return stats, it just pauses */ 724 if (_whoami == NSCD_FORKER) { 725 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG) 726 (me, "forker ready to pause ...\n"); 727 728 /*CONSTCOND*/ 729 while (1) 730 (void) pause(); 731 732 NSCD_RETURN_STATUS_SUCCESS(phdr); 733 } 734 735 /* remember the current activity sequence number */ 736 (void) mutex_lock(&activity_lock); 737 last_active = activity; 738 (void) mutex_unlock(&activity_lock); 739 740 while (!done) { 741 742 /* allow per_user_nscd_ttl seconds of inactivity */ 743 (void) sleep(pu_nscd_ttl); 744 745 (void) mutex_lock(&activity_lock); 746 if (last_active == activity) 747 done = 1; 748 else { 749 last_active = activity; 750 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG) 751 (me, "active, sleep again for %d seconds\n", 752 pu_nscd_ttl); 753 } 754 (void) mutex_unlock(&activity_lock); 755 } 756 757 /* no activity in the specified seconds, exit and disconnect */ 758 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG) 759 (me, "no activity in the last %d seconds, exit\n", pu_nscd_ttl); 760 exit(0); 761 } 762 763 void 764 _nscd_proc_fork( 765 void *buf, 766 int iam) 767 { 768 int slot; 769 int ret; 770 char *fmri; 771 pid_t cid; 772 uid_t set2uid; 773 gid_t set2gid; 774 nss_pheader_t *phdr = (nss_pheader_t *)buf; 775 char *me = "_nscd_proc_fork"; 776 nscd_fork_t *f; 777 nscd_imhere_t ih; 778 779 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG) 780 (me, "%d receives fork request from %d\n", _whoami, iam); 781 782 /* only main nscd sends fork requests */ 783 if (iam != NSCD_MAIN) { 784 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG) 785 (me, "MAIN IMPOSTER CAUGHT! i am %d not NSCD_MAIN\n", iam); 786 787 NSCD_RETURN_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0, 788 NSCD_SELF_CRED_MAIN_IMPOSTER); 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_RETURN_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0, 797 NSCD_SELF_CRED_WRONG_NSCD); 798 } 799 800 /* fork a child for the slot assigned by the main nscd */ 801 f = NSCD_N2N_DOOR_DATA(nscd_fork_t, buf); 802 slot = f->slot; 803 /* set the uid/gid as assigned by the main nscd */ 804 set2uid = f->uid; 805 set2gid = f->gid; 806 807 /* ignore bad slot number */ 808 if (slot < 0 || slot >= max_pu_nscd) { 809 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG) 810 (me, "bas slot number\n"); 811 812 NSCD_RETURN_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0, 813 NSCD_SELF_CRED_INVALID_SLOT_NUMBER); 814 } 815 816 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG) 817 (me, "before fork1() ...\n"); 818 819 if ((cid = fork1()) == 0) { 820 _whoami = NSCD_CHILD; 821 822 /* 823 * remember when this child nscd starts 824 * (replace the forker start time) 825 */ 826 _nscd_set_start_time(1); 827 828 /* close all except the log file */ 829 if (_logfd > 0) { 830 int i; 831 for (i = 0; i < _logfd; i++) 832 (void) close(i); 833 closefrom(_logfd + 1); 834 } else 835 closefrom(0); 836 837 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG) 838 (me, "child %d\n", getpid()); 839 840 (void) setgid(set2gid); 841 (void) setuid(set2uid); 842 843 /* set up the door and server thread pool */ 844 if ((_doorfd = _nscd_setup_child_server(_doorfd)) == -1) 845 exit(-1); 846 847 /* tell libsldap to do self cred only */ 848 (void) setup_ldap_backend(); 849 850 /* notify main that child is active */ 851 ih.slot = slot; 852 for (ret = NSS_ALTRETRY; ret == NSS_ALTRETRY; ) 853 ret = _nscd_doorcall_sendfd(_doorfd, 854 NSCD_IMHERE | (NSCD_CHILD & NSCD_WHOAMI), 855 &ih, sizeof (ih), NULL); 856 857 NSCD_RETURN_STATUS_SUCCESS(phdr); 858 } if (cid == (pid_t)-1) { 859 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG) 860 (me, "forker unable to fork ...\n"); 861 862 /* enter the maintenance mode */ 863 if ((fmri = getenv("SMF_FMRI")) != NULL) { 864 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG) 865 (me, "entering maintenance mode ...\n"); 866 (void) smf_maintain_instance(fmri, SMF_TEMPORARY); 867 } 868 exit(0); 869 } else { 870 /* 871 * start the monitor so as to exit as early as 872 * possible if no other processes are running 873 * with the same PUN uid (i.e., this PUN is 874 * not needed any more) 875 */ 876 (void) init_user_proc_monitor(); 877 878 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG) 879 (me, "child forked: parent pid = %d, child pid = %d\n", 880 getpid(), cid); 881 882 NSCD_SET_STATUS_SUCCESS(phdr); 883 } 884 885 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG) 886 (me, "after fork\n"); 887 } 888 889 static void 890 selfcred_fork( 891 void *buf, 892 int doorfd, 893 int cslot, 894 uid_t uid, 895 gid_t gid) 896 { 897 int ret; 898 nscd_fork_t f; 899 nss_pheader_t *phdr = (nss_pheader_t *)buf; 900 char *me = "selfcred_fork"; 901 902 /* if no door fd, do nothing */ 903 if (doorfd == -1) { 904 NSCD_SET_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0, 905 NSCD_SELF_CRED_NO_DOOR); 906 } 907 908 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG) 909 (me, "sending fork request to door %d for slot %d " 910 "(uid = %d, gid = %d)\n", doorfd, cslot, uid, gid); 911 912 f.slot = cslot; 913 f.uid = uid; 914 f.gid = gid; 915 916 ret = _nscd_doorcall_fd(doorfd, NSCD_FORK|(_whoami&NSCD_WHOAMI), 917 &f, sizeof (f), NULL, 0, phdr); 918 919 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG) 920 (me, "fork request sent to door %d for slot %d (rc = %d)\n", 921 doorfd, cslot, ret); 922 923 if (NSCD_STATUS_IS_NOT_OK(phdr)) { 924 925 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG) 926 (me, "fork request sent to door %d for slot %d failed: " 927 "status = %d, errno = %s, nscd status = %d\n", doorfd, 928 cslot, NSCD_GET_STATUS(phdr), 929 strerror(NSCD_GET_ERRNO(phdr)), 930 NSCD_GET_NSCD_STATUS(phdr)); 931 932 } 933 } 934 935 void 936 _nscd_proc_alt_get( 937 void *buf, 938 int *door) 939 { 940 int errnum; 941 uid_t set2uid; 942 gid_t set2gid; 943 nss_pheader_t *phdr = (nss_pheader_t *)buf; 944 char *me = "_nscd_proc_alt_get"; 945 ucred_t *uc = NULL; 946 child_t *ch; 947 948 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG) 949 (me, "getting an alternate door ...\n"); 950 951 /* make sure there is a door to talk to the forker */ 952 if (forking_door == -1) { 953 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_ERROR) 954 (me, "no door to talk to the forker\n"); 955 956 NSCD_RETURN_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0, 957 NSCD_SELF_CRED_NO_FORKER); 958 } 959 960 /* get door client's credential information */ 961 if (door_ucred(&uc) != 0) { 962 errnum = errno; 963 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG) 964 (me, "door_ucred failed: %s\n", strerror(errnum)); 965 966 NSCD_RETURN_N2N_STATUS(phdr, NSS_NSCD_PRIV, errnum, 967 NSCD_DOOR_UCRED_ERROR); 968 } 969 970 /* get door client's effective uid and effective gid */ 971 set2uid = ucred_geteuid(uc); 972 set2gid = ucred_getegid(uc); 973 ucred_free(uc); 974 uc = NULL; 975 976 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG) 977 (me, "child uid = %d, gid = %d\n", set2uid, set2gid); 978 979 /* is a slot available ? if not, no one to serve */ 980 if (child == NULL || (ch = get_cslot(set2uid, 0)) == NULL) { 981 982 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG) 983 (me, "no child slot available (child array = %p, slot = %d)\n", 984 child, ch->child_slot); 985 986 NSCD_RETURN_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0, 987 NSCD_SELF_CRED_NO_CHILD_SLOT); 988 } 989 990 /* create the per user nscd if necessary */ 991 if (ch->child_state != CHILD_STATE_PIDKNOWN) { 992 993 nss_pheader_t phdr1; 994 NSCD_CLEAR_STATUS(&phdr1); 995 996 (void) mutex_lock(ch->mutex); 997 if (ch->child_state == CHILD_STATE_UIDKNOWN) { 998 999 /* ask forker to fork a new child */ 1000 selfcred_fork(&phdr1, forking_door, ch->child_slot, 1001 set2uid, set2gid); 1002 if (NSCD_STATUS_IS_NOT_OK(&phdr1)) { 1003 (void) mutex_unlock(ch->mutex); 1004 NSCD_COPY_STATUS(phdr, &phdr1); 1005 return; 1006 } 1007 ch->child_state = CHILD_STATE_FORKSENT; 1008 } 1009 1010 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG) 1011 (me, "waiting for door (slot = %d, uid = %d, gid = %d)\n", 1012 ch->child_slot, set2uid, set2gid); 1013 1014 /* wait for the per user nscd to become available */ 1015 while (ch->child_state == CHILD_STATE_FORKSENT) { 1016 timestruc_t to; 1017 int err; 1018 int ttl = 5; 1019 1020 to.tv_sec = ttl; 1021 to.tv_nsec = 0; 1022 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG) 1023 (me, "cond_reltimedwait %d seconds\n", ttl); 1024 err = cond_reltimedwait(ch->cond, ch->mutex, &to); 1025 if (err == ETIME) { 1026 ch->child_state = CHILD_STATE_UIDKNOWN; 1027 _NSCD_LOG(NSCD_LOG_SELF_CRED, 1028 NSCD_LOG_LEVEL_DEBUG) 1029 (me, "door wait timedout (slot = %d)\n", 1030 ch->child_slot); 1031 break; 1032 } 1033 } 1034 (void) mutex_unlock(ch->mutex); 1035 } 1036 1037 if (ch->child_state != CHILD_STATE_PIDKNOWN) { 1038 1039 NSCD_RETURN_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0, 1040 NSCD_SELF_CRED_INVALID_SLOT_STATE); 1041 } 1042 1043 *door = ch->child_door; 1044 1045 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG) 1046 (me, "returning door %d for slot %d, uid %d, gid = %d\n", 1047 *door, ch->child_slot, set2uid, set2gid); 1048 1049 NSCD_RETURN_STATUS(phdr, NSS_ALTRETRY, 0); 1050 } 1051 1052 static char ** 1053 cpargv( 1054 int argc, 1055 char **inargv) 1056 { 1057 char **newargv; 1058 int c = 4; 1059 int i = 0, j, k = 0, n = 0; 1060 1061 newargv = (char **)calloc(c + 1, sizeof (char *)); 1062 if (newargv == NULL) 1063 return (NULL); 1064 1065 newargv[n] = strdup(inargv[0]); 1066 if (newargv[n++] == NULL) { 1067 free(newargv); 1068 return (NULL); 1069 } 1070 1071 newargv[n] = strdup("-F"); 1072 if (newargv[n++] == NULL) { 1073 free(newargv[0]); 1074 free(newargv); 1075 return (NULL); 1076 } 1077 1078 for (i = 1; i < argc; i++) { 1079 if (strcmp(inargv[i], "-f") == 0) 1080 k = 2; 1081 if (k == 0) 1082 continue; 1083 1084 newargv[n] = strdup(inargv[i]); 1085 if (newargv[n] == NULL) { 1086 for (j = 0; j < n; j++) 1087 free(newargv[j]); 1088 free(newargv); 1089 return (NULL); 1090 } 1091 1092 k--; 1093 n++; 1094 } 1095 return (newargv); 1096 } 1097 1098 1099 void 1100 _nscd_start_forker( 1101 char *path, 1102 int argc, 1103 char **argv) 1104 { 1105 pid_t cid; 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 /* enable child nscd management */ 1132 (void) _nscd_init_cslots(); 1133 break; 1134 } 1135 } 1136 1137 static nscd_rc_t 1138 get_ldap_funcs( 1139 char *name, 1140 void **func_p) 1141 { 1142 char *me = "get_ldap_funcs"; 1143 static void *handle = NULL; 1144 void *sym; 1145 1146 if (name == NULL && handle != NULL) { 1147 (void) dlclose(handle); 1148 return (NSCD_SUCCESS); 1149 } 1150 /* no handle to close, it's OK */ 1151 if (name == NULL) 1152 return (NSCD_SUCCESS); 1153 1154 if (handle == NULL) { 1155 handle = dlopen("libsldap.so.1", RTLD_LAZY); 1156 if (handle == NULL) { 1157 1158 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_ERROR) 1159 (me, "unable to dlopen libsldap.so.1"); 1160 return (NSCD_CFG_DLOPEN_ERROR); 1161 } 1162 } 1163 1164 if ((sym = dlsym(handle, name)) == NULL) { 1165 1166 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_ERROR) 1167 (me, "unable to find symbol %s", name); 1168 return (NSCD_CFG_DLSYM_ERROR); 1169 } else 1170 (void) memcpy(func_p, &sym, sizeof (void *)); 1171 1172 return (NSCD_SUCCESS); 1173 } 1174 1175 1176 int 1177 _nscd_is_self_cred_on(int recheck, char **dblist) 1178 { 1179 static int checked = 0; 1180 static int is_on = 0; 1181 static int (*ldap_func)(); 1182 char *srcs = "ldap"; /* only ldap support self cred */ 1183 int ldap_on = 0; 1184 1185 char *ldap_sc_func = "__ns_ldap_self_gssapi_config"; 1186 ns_ldap_self_gssapi_config_t ldap_config; 1187 1188 if (checked && !recheck) { 1189 if (is_on && dblist != NULL) 1190 *dblist = selfcred_dbs; 1191 return (is_on); 1192 } 1193 1194 if (selfcred_dbs != NULL) 1195 free(selfcred_dbs); 1196 selfcred_dbs = _nscd_srcs_in_db_nsw_policy(1, &srcs); 1197 1198 if (selfcred_dbs == NULL) { 1199 is_on = 0; 1200 checked = 1; 1201 return (0); 1202 } 1203 1204 /* 1205 * also check the ldap backend to see if 1206 * the configuration there is good for 1207 * doing self credentialing 1208 */ 1209 if (ldap_func == NULL) 1210 (void) get_ldap_funcs(ldap_sc_func, (void **)&ldap_func); 1211 if (ldap_func != NULL) { 1212 if (ldap_func(&ldap_config) == NS_LDAP_SUCCESS && 1213 ldap_config != NS_LDAP_SELF_GSSAPI_CONFIG_NONE) 1214 ldap_on = 1; 1215 } 1216 1217 is_on = (pu_nscd_enabled == nscd_true) && ldap_on; 1218 1219 checked = 1; 1220 1221 if (is_on && dblist != NULL) 1222 *dblist = selfcred_dbs; 1223 1224 return (is_on); 1225 } 1226 1227 static nscd_rc_t 1228 setup_ldap_backend() 1229 { 1230 nscd_rc_t rc; 1231 static void (*ldap_func)(); 1232 char *ldap_sc_func = "__ns_ldap_self_gssapi_only_set"; 1233 if (ldap_func == NULL) 1234 rc = get_ldap_funcs(ldap_sc_func, (void **)&ldap_func); 1235 if (ldap_func != NULL) { 1236 ldap_func(1); 1237 return (NSCD_SUCCESS); 1238 } 1239 return (rc); 1240 } 1241 1242 /*ARGSUSED*/ 1243 void 1244 _nscd_peruser_getadmin( 1245 void *buf, 1246 int buf_size) 1247 { 1248 void *result_mn = NSCD_N2N_DOOR_DATA(void, buf); 1249 int errnum = 0; 1250 int ret; 1251 uid_t uid; 1252 nss_pheader_t *phdr = (nss_pheader_t *)buf; 1253 char *me = "_nscd_peruser_getadmin"; 1254 ucred_t *uc = NULL; 1255 child_t *ch; 1256 1257 /* get door client's credential information */ 1258 if (door_ucred(&uc) != 0) { 1259 errnum = errno; 1260 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG) 1261 (me, "door_ucred failed: %s\n", strerror(errnum)); 1262 1263 NSCD_RETURN_N2N_STATUS(phdr, NSS_NSCD_PRIV, errnum, 1264 NSCD_DOOR_UCRED_ERROR); 1265 } 1266 1267 /* get door client's effective uid */ 1268 uid = ucred_geteuid(uc); 1269 ucred_free(uc); 1270 uc = NULL; 1271 1272 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG) 1273 (me, "per user get admin ... (uid = %d)\n", uid); 1274 1275 /* is the per-user nscd running ? if not, no one to serve */ 1276 ch = get_cslot(uid, 1); 1277 if (ch == NULL) { 1278 NSCD_RETURN_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0, 1279 NSCD_SELF_CRED_NO_CHILD_SLOT); 1280 } 1281 1282 ret = _nscd_doorcall_fd(ch->child_door, NSCD_GETADMIN, 1283 NULL, sizeof (nscd_admin_t), result_mn, 1284 sizeof (nscd_admin_t), phdr); 1285 1286 if (ret == NSS_SUCCESS) { 1287 phdr->data_len = sizeof (nscd_admin_t); 1288 return; 1289 } 1290 } 1291 1292 static void 1293 set_selfcred_cfg( 1294 char param, 1295 void *data) 1296 { 1297 int64_t prop_int; 1298 uint8_t prop_boolean; 1299 char *me = "set_selfcred_cfg"; 1300 1301 if (param == 'e') { 1302 prop_boolean = *(uint8_t *)data; 1303 pu_nscd_enabled = *(uint8_t *)get_smf_prop( 1304 "enable_per_user_lookup", 'b', &prop_boolean); 1305 1306 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG) 1307 (me, "self cred config: enabled = %d\n", pu_nscd_enabled); 1308 } 1309 1310 if (param == 't') { 1311 prop_int = *(int *)data; 1312 pu_nscd_ttl = *(int64_t *)get_smf_prop( 1313 "per_user_nscd_time_to_live", 'i', &prop_int); 1314 1315 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG) 1316 (me, "self cred config: PUN TTL = %d\n", pu_nscd_ttl); 1317 } 1318 } 1319 1320 /* ARGSUSED */ 1321 nscd_rc_t 1322 _nscd_cfg_selfcred_notify( 1323 void *data, 1324 struct nscd_cfg_param_desc *pdesc, 1325 nscd_cfg_id_t *nswdb, 1326 nscd_cfg_flag_t dflag, 1327 nscd_cfg_error_t **errorp, 1328 void *cookie) 1329 { 1330 1331 nscd_cfg_global_selfcred_t *sc_cfg = &nscd_selfcred_cfg_g; 1332 int off; 1333 1334 /* 1335 * At init time, the whole group of config params are received. 1336 * At update time, group or individual parameter value could 1337 * be received. 1338 */ 1339 1340 if (_nscd_cfg_flag_is_set(dflag, NSCD_CFG_DFLAG_GROUP)) { 1341 1342 *sc_cfg = *(nscd_cfg_global_selfcred_t *)data; 1343 1344 off = offsetof(nscd_cfg_global_selfcred_t, 1345 enable_selfcred); 1346 set_selfcred_cfg('e', (char *)data + off); 1347 1348 off = offsetof(nscd_cfg_global_selfcred_t, 1349 per_user_nscd_ttl); 1350 set_selfcred_cfg('t', (char *)data + off); 1351 1352 return (NSCD_SUCCESS); 1353 } 1354 1355 /* 1356 * individual config parameter 1357 */ 1358 off = offsetof(nscd_cfg_global_selfcred_t, enable_selfcred); 1359 if (pdesc->p_offset == off) { 1360 sc_cfg->enable_selfcred = *(nscd_bool_t *)data; 1361 set_selfcred_cfg('e', data); 1362 return (NSCD_SUCCESS); 1363 } 1364 1365 off = offsetof(nscd_cfg_global_selfcred_t, per_user_nscd_ttl); 1366 if (pdesc->p_offset == off) { 1367 sc_cfg->per_user_nscd_ttl = *(int *)data; 1368 set_selfcred_cfg('t', data); 1369 return (NSCD_SUCCESS); 1370 } 1371 1372 return (NSCD_SUCCESS); 1373 } 1374 1375 /* ARGSUSED */ 1376 nscd_rc_t 1377 _nscd_cfg_selfcred_verify( 1378 void *data, 1379 struct nscd_cfg_param_desc *pdesc, 1380 nscd_cfg_id_t *nswdb, 1381 nscd_cfg_flag_t dflag, 1382 nscd_cfg_error_t **errorp, 1383 void **cookie) 1384 { 1385 1386 return (NSCD_SUCCESS); 1387 } 1388 1389 /* ARGSUSED */ 1390 nscd_rc_t 1391 _nscd_cfg_selfcred_get_stat( 1392 void **stat, 1393 struct nscd_cfg_stat_desc *sdesc, 1394 nscd_cfg_id_t *nswdb, 1395 nscd_cfg_flag_t *dflag, 1396 void (**free_stat)(void *stat), 1397 nscd_cfg_error_t **errorp) 1398 { 1399 return (NSCD_SUCCESS); 1400 } 1401 1402 static int 1403 check_uid(char *pid_name) 1404 { 1405 char pname[PATH_MAX]; 1406 static pid_t pid = 0; 1407 static uid_t uid = 0; 1408 static uid_t euid = 0; 1409 int pfd; /* file descriptor for /proc/<pid>/psinfo */ 1410 psinfo_t info; /* process information from /proc */ 1411 1412 if (uid == 0) { 1413 pid = getpid(); 1414 uid = getuid(); 1415 euid = geteuid(); 1416 } 1417 1418 (void) snprintf(pname, sizeof (pname), "/proc/%s/psinfo", pid_name); 1419 retry: 1420 if ((pfd = open(pname, O_RDONLY)) == -1) { 1421 /* Process may have exited */ 1422 return (1); 1423 } 1424 1425 /* 1426 * Get the info structure for the process and close quickly. 1427 */ 1428 if (read(pfd, (char *)&info, sizeof (info)) < 0) { 1429 int saverr = errno; 1430 1431 (void) close(pfd); 1432 if (saverr == EAGAIN) 1433 goto retry; 1434 if (saverr != ENOENT) 1435 return (1); 1436 } 1437 (void) close(pfd); 1438 1439 if (info.pr_pid != pid && 1440 info.pr_uid == uid && info.pr_euid == euid) 1441 return (0); 1442 else 1443 return (1); 1444 } 1445 1446 1447 /* 1448 * FUNCTION: check_user_process 1449 */ 1450 /*ARGSUSED*/ 1451 static void * 1452 check_user_process(void *arg) 1453 { 1454 1455 DIR *dp; 1456 struct dirent *ep; 1457 int found; 1458 char *me = "check_user_process"; 1459 1460 /*CONSTCOND*/ 1461 while (1) { 1462 (void) sleep(60); 1463 1464 found = 0; 1465 1466 /* 1467 * search the /proc directory and look at each process 1468 */ 1469 if ((dp = opendir("/proc")) == NULL) { 1470 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_ERROR) 1471 (me, "unable to open the /proc directory\n"); 1472 continue; 1473 } 1474 1475 /* for each active process */ 1476 while (ep = readdir(dp)) { 1477 if (ep->d_name[0] == '.') /* skip . and .. */ 1478 continue; 1479 if (check_uid(ep->d_name) == 0) { 1480 found = 1; 1481 break; 1482 } 1483 } 1484 1485 /* 1486 * if no process running as the PUN uid found, exit 1487 * to kill this PUN 1488 */ 1489 if (found == 0) { 1490 (void) closedir(dp); 1491 exit(1); 1492 } 1493 (void) closedir(dp); 1494 } 1495 /* NOTREACHED */ 1496 /*LINTED E_FUNC_HAS_NO_RETURN_STMT*/ 1497 } 1498 1499 static nscd_rc_t 1500 init_user_proc_monitor() { 1501 1502 int errnum; 1503 char *me = "init_user_proc_monitor"; 1504 1505 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG) 1506 (me, "initializing the user process monitor\n"); 1507 1508 /* 1509 * start a thread to make sure there is at least a process 1510 * running as the PUN user. If not, terminate this PUN. 1511 */ 1512 if (thr_create(NULL, NULL, check_user_process, 1513 NULL, THR_DETACHED, NULL) != 0) { 1514 errnum = errno; 1515 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_ERROR) 1516 (me, "thr_create: %s\n", strerror(errnum)); 1517 return (NSCD_THREAD_CREATE_ERROR); 1518 } 1519 1520 return (NSCD_SUCCESS); 1521 } 1522 1523 static void * 1524 get_smf_prop(const char *var, char type, void *def_val) 1525 { 1526 scf_simple_prop_t *prop; 1527 void *val; 1528 char *me = "get_smf_prop"; 1529 1530 prop = scf_simple_prop_get(NULL, NULL, "config", var); 1531 if (prop) { 1532 switch (type) { 1533 case 'b': 1534 val = scf_simple_prop_next_boolean(prop); 1535 if (val != NULL) 1536 (void) memcpy(def_val, val, sizeof (uint8_t)); 1537 break; 1538 1539 case 'i': 1540 val = scf_simple_prop_next_integer(prop); 1541 if (val != NULL) 1542 (void) memcpy(def_val, val, sizeof (int64_t)); 1543 break; 1544 } 1545 scf_simple_prop_free(prop); 1546 } 1547 1548 if (prop == NULL || val == NULL) { 1549 char vs[64]; 1550 1551 switch (type) { 1552 case 'b': 1553 if (*(uint8_t *)def_val) 1554 (void) strcpy(vs, "yes"); 1555 else 1556 (void) strcpy(vs, "no"); 1557 1558 break; 1559 1560 case 'i': 1561 (void) sprintf(vs, "%lld", *(int64_t *)def_val); 1562 break; 1563 1564 } 1565 _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_ALERT) 1566 (me, "no value for config/%s (%s). " 1567 "Using default \"%s\"\n", var, 1568 scf_strerror(scf_error()), vs); 1569 } 1570 1571 return (def_val); 1572 } 1573