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