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