xref: /titanic_52/usr/src/cmd/vt/vtdaemon.c (revision 876b86efac620aaabc70ad2ed4bfb715ce714875)
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) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
24  */
25 
26 /*
27  * vtdaemon is responsible for the session secure switch via hotkeys.
28  *
29  * vtdaemon itself, like ttymon(1M), is also running on a virtual
30  * console device (/dev/vt/1), and provides a text console session
31  * for password input and authentication. The /dev/vt/1 special text
32  * console is reserved and end users cannot switch to it via hotkeys.
33  *
34  *
35  * The hotkey event request can come from either kernel or Xserver,
36  * and a door server is setup to handle the request:
37  *
38  *   1) All text console hotkeys (e.g. "Alt + F#") are intercepted by
39  *      the kernel console driver which sends a door upcall to the
40  *      vtdaemon via door_upcall (target_vt).
41  *
42  *   2) All Xserver hotkeys ("Alt + Ctrl + F#") are intercepted by
43  *      Xserver which sends a door call to the vtdaemon via
44  *      door_call (target_vt).
45  *
46  *
47  * server_for_door receives and handles any door server requests:
48  *
49  *   Firstly, check source session:
50  *
51  *      . If it's from kernel for a text console source session,
52  *        then directly go to check the target session.
53  *
54  *      . If it's from Xserver for a graphical source session and the vt
55  *        associated with the Xserver is currently active:
56  *          check if a user has logged in, if true, issue an internal
57  *          VT_EV_LOCK event to the main thread to request lock for
58  *          the graphical source session; else, directly go to check
59  *          the target session.
60  *
61  *      . otherwise, discard this request.
62  *
63  *
64  *    Secondly, check the target session
65  *
66  *      . if the target session is a text one that no one has logged in
67  *        or a graphical one, issue an internal VT_EV_ACTIVATE event to
68  *        the main thread to request the actual VT switch.
69  *
70  *      . otherwise, the target session is a text one that someone has
71  *        logged in, issue an internal VT_EV_AUTH event to the main
72  *        thread to request authentication for the target session.
73  *
74  *
75  * The main thread of vtdaemon is a loop waiting for internal events
76  * which come from door call threads:
77  *
78  *   1)  VT_EV_AUTH      to authenticate for target session:
79  *
80  *                       firstly switch to the vtdaemon special text console;
81  *                       then prompt for password (target_owner on target_vt),
82  *                       e.g. "User Bob's password on vt/#: ".
83  *
84  *                       if the password is correct (authentication succeeds),
85  *                       then actually issue the VT switch; otherwise, ignore
86  *                       the request.
87  *
88  *   2)  VT_EV_LOCK      to lock the graphical source session:
89  *
90  *                       activate screenlock for this graphical session.
91  *                       vtdaemon just invokes existing front-end command line
92  *                       tools (e.g. xscreensaver-command -lock for JDS) to
93  *                       lock the display.
94  *
95  *   3)  VT_EV_ACTIVATE  to directly switch to the target session
96  *
97  *
98  * There is a system/vtdaemon:default SMF service for vtdaemon.
99  *
100  *	There's a "hotkeys" property (BOOLEAN) in the
101  *	system/vtdaemon:default SMF service, which allows authorized
102  *	users to dynamically enable or disable VT switch via hotkeys.
103  *      Its default value is TRUE (enabled).
104  *
105  *	There's a "secure" property (BOOLEAN) in the
106  *	system/vtdaemon:default SMF service, which allows authorized
107  *	users to dynamically enable or disable hotkeys are secure.
108  *	If disabled, the user can freely switch to any session without
109  *	authentication. Its default value is TRUE (enabled).
110  *
111  *
112  *  By default, there's only 16 virtual console device nodes (from
113  *  /dev/vt/0 to /dev/vt/15). There's a property "nodecount"
114  *  (default value is 16) in the system/vtdaemon:default SMF
115  *  service, so authorized users can configure it to have more
116  *  or less virtual console device nodes.
117  *
118  *  Xserver needs to switch back to previous active vt via VT_EV_X_EXIT
119  *  door event request when it's exiting, so vtdaemon always needs to
120  *  be there even if the hotkeys switch is disabled, otherwise the screen
121  *  will be just blank when Xserver exits.
122  */
123 
124 #include <sys/param.h>
125 #include <sys/mman.h>
126 #include <sys/types.h>
127 #include <sys/wait.h>
128 #include <sys/stat.h>
129 #include <sys/sysmacros.h>
130 #include <syslog.h>
131 #include <deflt.h>
132 
133 #include <bsm/adt.h>
134 #include <bsm/adt_event.h>
135 
136 #include <alloca.h>
137 #include <assert.h>
138 #include <errno.h>
139 #include <door.h>
140 #include <fcntl.h>
141 #include <signal.h>
142 #include <stdarg.h>
143 #include <stdio.h>
144 #include <stdlib.h>
145 #include <string.h>
146 #include <strings.h>
147 #include <synch.h>
148 #include <thread.h>
149 #include <unistd.h>
150 #include <wait.h>
151 #include <limits.h>
152 #include <zone.h>
153 #include <priv.h>
154 #include <pwd.h>
155 #include <utmpx.h>
156 #include <procfs.h>
157 #include <poll.h>
158 #include <termio.h>
159 #include <security/pam_appl.h>
160 #include <time.h>
161 #include <sys/console.h>
162 #include <assert.h>
163 #include <syslog.h>
164 
165 #include <sys/vt.h>
166 #include <sys/vtdaemon.h>
167 
168 /*
169  * The door file /var/run/vt/vtdaemon_door
170  */
171 #define	VT_TMPDIR "/var/run/vt"
172 
173 #define	VT_DAEMON_ARG	0
174 #define	VT_DAEMON_CONSOLE_FILE	"/dev/vt/1"
175 
176 #define	VT_IS_SYSTEM_CONSOLE(vtno)	((vtno) == 1)
177 
178 /* Defaults for updating expired passwords */
179 #define	DEF_ATTEMPTS	3
180 
181 int daemonfd;
182 
183 static boolean_t vt_hotkeys = B_TRUE;		/* '-k' option to disable */
184 static boolean_t vt_secure = B_TRUE;		/* '-s' option to disable */
185 
186 static char	vt_door_path[MAXPATHLEN];
187 static int	vt_door = -1;
188 
189 /* protecting vt_hotkeys_pending and vt_auth_doing */
190 static mutex_t	vt_mutex = DEFAULTMUTEX;
191 
192 static boolean_t vt_hotkeys_pending = B_FALSE;
193 static boolean_t vt_auth_doing = B_FALSE;
194 
195 static adt_session_data_t **vt_ah_array = NULL;
196 static int vtnodecount = 0;
197 
198 static int vt_audit_start(adt_session_data_t **, pid_t);
199 static void vt_audit_event(adt_session_data_t *, au_event_t, int);
200 static void vt_check_source_audit(void);
201 
202 static int
203 vt_setup_signal(int signo, int mask)
204 {
205 	sigset_t set;
206 
207 	(void) sigemptyset(&set);
208 	(void) sigaddset(&set, signo);
209 
210 	if (mask)
211 		return (sigprocmask(SIG_BLOCK, &set, NULL));
212 	else
213 		return (sigprocmask(SIG_UNBLOCK, &set, NULL));
214 }
215 
216 static void
217 do_activate_screenlock(int display_num)
218 {
219 	char dpy[16];
220 
221 	(void) snprintf(dpy, sizeof (dpy), "%d", display_num);
222 	(void) execl("/usr/lib/vtxlock", "vtxlock", dpy, NULL);
223 }
224 
225 static void
226 vt_activate_screenlock(int display)
227 {
228 	pid_t pid;
229 
230 	if ((pid = fork()) == -1)
231 		return;
232 
233 	if (pid == 0) { /* child */
234 		do_activate_screenlock(display);
235 		exit(0);
236 	}
237 
238 	/* parent */
239 	while (waitpid(pid, (int *)0, 0) != pid)
240 		continue;
241 }
242 
243 /*
244  * Find the login process and user logged in on the target vt.
245  */
246 static void
247 vt_read_utx(int target_vt, pid_t *pid, char name[])
248 {
249 	struct utmpx  *u;
250 	char ttyntail[sizeof (u->ut_line)];
251 
252 	*pid = (pid_t)-1;
253 
254 	if (VT_IS_SYSTEM_CONSOLE(target_vt)) /* system console */
255 		(void) snprintf(ttyntail, sizeof (ttyntail),
256 		    "%s", "console");
257 	else
258 		(void) snprintf(ttyntail, sizeof (ttyntail),
259 		    "%s%d", "vt/", target_vt);
260 
261 	setutxent();
262 	while ((u = getutxent()) != NULL)
263 		/* see if this is the entry we want */
264 		if ((u->ut_type == USER_PROCESS) &&
265 		    (!nonuserx(*u)) &&
266 		    (u->ut_host[0] == '\0') &&
267 		    (strncmp(u->ut_line, ttyntail, sizeof (u->ut_line)) == 0)) {
268 
269 			*pid = u->ut_pid;
270 			if (name != NULL) {
271 				(void) strncpy(name, u->ut_user,
272 				    sizeof (u->ut_user));
273 				name[sizeof (u->ut_user)] = '\0';
274 			}
275 			break;
276 		}
277 
278 	endutxent();
279 }
280 
281 static boolean_t
282 vt_is_tipline(void)
283 {
284 	static int is_tipline = 0;
285 	int fd;
286 	static char termbuf[MAX_TERM_TYPE_LEN];
287 	static struct cons_getterm cons_term = { sizeof (termbuf), termbuf};
288 
289 	if (is_tipline != 0)
290 		return (is_tipline == 1);
291 
292 	if ((fd = open("/dev/console", O_RDONLY)) < 0)
293 		return (B_FALSE);
294 
295 	if (ioctl(fd, CONS_GETTERM, &cons_term) != 0 &&
296 	    errno == ENODEV) {
297 		is_tipline = 1;
298 	} else {
299 		is_tipline = -1;
300 	}
301 
302 	(void) close(fd);
303 	return (is_tipline == 1);
304 }
305 
306 static int
307 validate_target_vt(int target_vt)
308 {
309 	int fd;
310 	struct vt_stat state;
311 
312 	if (target_vt < 1)
313 		return (-1);
314 
315 	if ((fd = open(VT_DAEMON_CONSOLE_FILE, O_WRONLY)) < 0)
316 		return (-1);
317 
318 	if (ioctl(fd, VT_GETSTATE, &state) != 0) {
319 		(void) close(fd);
320 		return (-1);
321 	}
322 
323 	(void) close(fd);
324 
325 	if (state.v_active == target_vt) {
326 		return (1);	/* it's current active vt */
327 	}
328 
329 	if (target_vt == 1) {
330 		/*
331 		 * In tipline case, the system console is always
332 		 * available, so ignore this request.
333 		 */
334 		if (vt_is_tipline())
335 			return (-1);
336 
337 		target_vt = 0;
338 	}
339 
340 	/*
341 	 * The hotkey request and corresponding target_vt number can come
342 	 * from either kernel or Xserver (or other user applications).
343 	 * In kernel we've validated the hotkey request, but Xserver (or
344 	 * other user applications) cannot do it, so here we still try
345 	 * to validate it.
346 	 *
347 	 * VT_GETSTATE is only valid for first 16 VTs for historical reasons.
348 	 * Fortunately, in practice, Xserver can only send the hotkey
349 	 * request of target_vt number from 1 to 12 (Ctrl + Alt + F1 to F2).
350 	 */
351 	if (target_vt < 8 * sizeof (state.v_state)) {
352 		if ((state.v_state & (1 << target_vt)) != 0) {
353 			return (0);
354 		} else {
355 			return (-1);
356 		}
357 	}
358 
359 	return (0);
360 }
361 
362 static void
363 vt_do_activate(int target_vt)
364 {
365 	(void) ioctl(daemonfd, VT_ACTIVATE, target_vt);
366 	(void) mutex_lock(&vt_mutex);
367 	vt_hotkeys_pending = B_FALSE;
368 	(void) mutex_unlock(&vt_mutex);
369 }
370 
371 /* events written to fd 0 and read from fd 1 */
372 #define	VT_EV_AUTH	1
373 #define	VT_EV_LOCK	2
374 #define	VT_EV_ACTIVATE	3
375 
376 /* events written to fd 1 and read from fd 0 */
377 #define	VT_EV_TERMINATE_AUTH	4
378 
379 typedef struct vt_evt {
380 	int	ve_cmd;
381 	int	ve_info;	/* vtno or display num */
382 } vt_evt_t;
383 
384 static int eventstream[2];
385 
386 boolean_t
387 eventstream_init(void)
388 {
389 	if (pipe(eventstream) == -1)
390 		return (B_FALSE);
391 	return (B_TRUE);
392 }
393 
394 void
395 eventstream_write(int channel, vt_evt_t *pevt)
396 {
397 	(void) write(eventstream[channel], pevt, sizeof (vt_evt_t));
398 }
399 
400 static boolean_t
401 eventstream_read(int channel, vt_evt_t *pevt)
402 {
403 	ssize_t rval;
404 
405 	rval = read(eventstream[channel], pevt, sizeof (vt_evt_t));
406 	return (rval > 0);
407 }
408 
409 static void
410 vt_ev_request(int cmd, int info)
411 {
412 	int channel;
413 	vt_evt_t ve;
414 
415 	ve.ve_cmd = cmd;
416 	ve.ve_info = info;
417 
418 	channel = (cmd == VT_EV_TERMINATE_AUTH) ? 1 : 0;
419 	eventstream_write(channel, &ve);
420 }
421 
422 static void
423 vt_clear_events(void)
424 {
425 	int rval = 0;
426 	struct stat buf;
427 	vt_evt_t evt;
428 
429 	while (rval == 0) {
430 		rval = fstat(eventstream[0], &buf);
431 		if (rval != -1 && buf.st_size > 0)
432 			(void) eventstream_read(0, &evt);
433 		else
434 			break;
435 	}
436 }
437 
438 static int vt_conv(int, struct pam_message **,
439     struct pam_response **, void *);
440 
441 /*ARGSUSED*/
442 static void
443 catch(int x)
444 {
445 	(void) signal(SIGINT, catch);
446 }
447 
448 /*
449  * The SIGINT (ctl_c) will restart the authentication, and re-prompt
450  * the end user to input the password.
451  */
452 static int
453 vt_poll()
454 {
455 	struct pollfd pollfds[2];
456 	vt_evt_t ve;
457 	int ret;
458 
459 	pollfds[0].fd = eventstream[0];
460 	pollfds[1].fd = daemonfd;
461 	pollfds[0].events = pollfds[1].events =
462 	    POLLIN | POLLRDNORM | POLLRDBAND | POLLPRI;
463 
464 	for (;;) {
465 		pollfds[0].revents = pollfds[1].revents = 0;
466 
467 		ret = poll(pollfds,
468 		    sizeof (pollfds) / sizeof (struct pollfd), -1);
469 		if (ret == -1 && errno != EINTR) {
470 			continue;
471 		}
472 
473 		if (ret == -1 && errno == EINTR)
474 			return (-1);
475 
476 		if (pollfds[0].revents) {
477 			(void) eventstream_read(0, &ve);
478 			return (0);
479 		}
480 
481 		if (pollfds[1].revents)
482 			return (1);
483 
484 		return (0);
485 
486 	}
487 }
488 
489 static char
490 vt_getchar(int fd)
491 {
492 	char c;
493 	int cnt;
494 
495 	cnt = read(fd, &c, 1);
496 	if (cnt > 0) {
497 		return (c);
498 	}
499 
500 	return (EOF);
501 }
502 
503 static char *
504 vt_getinput(int noecho)
505 {
506 	int c;
507 	int i = 0;
508 	struct termio tty;
509 	tcflag_t tty_flags;
510 	char input[PAM_MAX_RESP_SIZE];
511 
512 	if (noecho) {
513 		(void) ioctl(daemonfd, TCGETA, &tty);
514 		tty_flags = tty.c_lflag;
515 		tty.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL);
516 		(void) ioctl(daemonfd, TCSETAF, &tty);
517 	}
518 
519 	while ((vt_poll()) == 1) {
520 		if ((c = vt_getchar(daemonfd)) != '\n' && c != '\r' &&
521 		    c != EOF && (i < PAM_MAX_RESP_SIZE - 1))
522 			input[i++] = (char)c;
523 		else
524 			break;
525 	}
526 
527 	input[i] = '\0';
528 
529 	if (noecho) {
530 		tty.c_lflag = tty_flags;
531 		(void) ioctl(daemonfd, TCSETAW, &tty);
532 		(void) fputc('\n', stdout);
533 	}
534 
535 	return (strdup(input));
536 }
537 
538 /*
539  * vt_conv: vtdaemon PAM conversation function.
540  * SIGINT/EINTR is handled in vt_getinput()/vt_poll().
541  */
542 
543 /*ARGSUSED*/
544 static int
545 vt_conv(int num_msg, struct pam_message **msg,
546     struct pam_response **response, void *appdata_ptr)
547 {
548 	struct pam_message	*m;
549 	struct pam_response	*r;
550 	int			i, k;
551 
552 	if (num_msg >= PAM_MAX_NUM_MSG) {
553 		syslog(LOG_ERR, "too many messages %d >= %d",
554 		    num_msg, PAM_MAX_NUM_MSG);
555 		*response = NULL;
556 		return (PAM_CONV_ERR);
557 	}
558 
559 	*response = calloc(num_msg, sizeof (struct pam_response));
560 	if (*response == NULL)
561 		return (PAM_BUF_ERR);
562 
563 	m = *msg;
564 	r = *response;
565 	for (i = 0; i < num_msg; i++) {
566 		int echo_off = 0;
567 
568 		/* Bad message */
569 		if (m->msg == NULL) {
570 			syslog(LOG_ERR, "message[%d]: %d/NULL\n",
571 			    i, m->msg_style);
572 			goto err;
573 		}
574 
575 		/*
576 		 * Fix up final newline:
577 		 * remove from prompts, add back for messages.
578 		 */
579 		if (m->msg[strlen(m->msg)] == '\n')
580 			m->msg[strlen(m->msg)] = '\0';
581 
582 		r->resp = NULL;
583 		r->resp_retcode = 0;
584 
585 		switch (m->msg_style) {
586 
587 		case PAM_PROMPT_ECHO_OFF:
588 			echo_off = 1;
589 			/* FALLTHROUGH */
590 
591 		case PAM_PROMPT_ECHO_ON:
592 			(void) fputs(m->msg, stdout);
593 
594 			r->resp = vt_getinput(echo_off);
595 			break;
596 
597 		case PAM_ERROR_MSG:
598 			/* the user may want to see this */
599 			(void) fputs(m->msg, stdout);
600 			(void) fputs("\n", stdout);
601 			break;
602 
603 		case PAM_TEXT_INFO:
604 			(void) fputs(m->msg, stdout);
605 			(void) fputs("\n", stdout);
606 			break;
607 
608 		default:
609 			syslog(LOG_ERR, "message[%d]: unknown type"
610 			    "%d/val=\"%s\"", i, m->msg_style, m->msg);
611 
612 			/* error, service module won't clean up */
613 			goto err;
614 		}
615 
616 		/* Next message/response */
617 		m++;
618 		r++;
619 
620 	}
621 	return (PAM_SUCCESS);
622 
623 err:
624 	/*
625 	 * Service modules don't clean up responses if an error is returned.
626 	 * Free responses here.
627 	 */
628 	r = *response;
629 	for (k = 0; k < i; k++, r++) {
630 		if (r->resp) {
631 			/* Clear before freeing -- maybe a password */
632 			bzero(r->resp, strlen(r->resp));
633 			free(r->resp);
634 			r->resp = NULL;
635 		}
636 	}
637 
638 	free(*response);
639 	*response = NULL;
640 	return (PAM_CONV_ERR);
641 }
642 
643 #define	DEF_FILE	"/etc/default/login"
644 
645 /* Get PASSREQ from default file */
646 static boolean_t
647 vt_default(void)
648 {
649 	int flags;
650 	char *ptr;
651 	boolean_t retval = B_FALSE;
652 
653 	if ((defopen(DEF_FILE)) == 0) {
654 		/* ignore case */
655 		flags = defcntl(DC_GETFLAGS, 0);
656 		TURNOFF(flags, DC_CASE);
657 		(void) defcntl(DC_SETFLAGS, flags);
658 
659 		if ((ptr = defread("PASSREQ=")) != NULL &&
660 		    strcasecmp("YES", ptr) == 0)
661 			retval = B_TRUE;
662 
663 		(void) defopen(NULL);
664 	}
665 
666 	return (retval);
667 }
668 
669 /*
670  * VT_CLEAR_SCREEN_STR is the console terminal escape sequence used to
671  * clear the current screen.  The vt special console (/dev/vt/1) is
672  * just reserved for vtdaemon, and the TERM/termcap of it is always
673  * the local sun-color, which is always supported by our kernel terminal
674  * emulator.
675  */
676 #define	VT_CLEAR_SCREEN_STR	"\033[2J\033[1;1H"
677 
678 static void
679 vt_do_auth(int target_vt)
680 {
681 	char	user_name[sizeof (((struct utmpx *)0)->ut_line) + 1] = {'\0'};
682 	pam_handle_t	*vt_pamh;
683 	int		err;
684 	int		pam_flag = 0;
685 	int		chpasswd_tries;
686 	struct pam_conv pam_conv = {vt_conv, NULL};
687 	pid_t		pid;
688 	adt_session_data_t	*ah;
689 
690 	vt_read_utx(target_vt, &pid, user_name);
691 
692 	if (pid == (pid_t)-1 || user_name[0] == '\0')
693 		return;
694 
695 	if ((err = pam_start("vtdaemon", user_name, &pam_conv,
696 	    &vt_pamh)) != PAM_SUCCESS)
697 		return;
698 
699 	/*
700 	 * firstly switch to the vtdaemon special console
701 	 * and clear the current screen
702 	 */
703 	(void) ioctl(daemonfd, VT_ACTIVATE, VT_DAEMON_ARG);
704 	(void) write(daemonfd, VT_CLEAR_SCREEN_STR,
705 	    strlen(VT_CLEAR_SCREEN_STR));
706 	(void) ioctl(daemonfd, VT_SET_TARGET, target_vt);
707 
708 	(void) mutex_lock(&vt_mutex);
709 	vt_auth_doing = B_TRUE;
710 	vt_hotkeys_pending = B_FALSE;
711 	(void) mutex_unlock(&vt_mutex);
712 
713 	/*
714 	 * Fetch audit handle.
715 	 */
716 	ah = vt_ah_array[target_vt - 1];
717 
718 	if (vt_default())
719 		pam_flag = PAM_DISALLOW_NULL_AUTHTOK;
720 
721 	do {
722 		if (VT_IS_SYSTEM_CONSOLE(target_vt))
723 			(void) fprintf(stdout,
724 			    "\nUnlock user %s on the system console\n",
725 			    user_name);
726 		else
727 			(void) fprintf(stdout,
728 			    "\nUnlock user %s on vt/%d\n", user_name,
729 			    target_vt);
730 
731 		err = pam_authenticate(vt_pamh, pam_flag);
732 
733 		(void) mutex_lock(&vt_mutex);
734 		if (vt_hotkeys_pending) {
735 			(void) mutex_unlock(&vt_mutex);
736 			break;
737 		}
738 		(void) mutex_unlock(&vt_mutex);
739 
740 		if (err == PAM_SUCCESS) {
741 			err = pam_acct_mgmt(vt_pamh, pam_flag);
742 
743 			(void) mutex_lock(&vt_mutex);
744 			if (vt_hotkeys_pending) {
745 				(void) mutex_unlock(&vt_mutex);
746 				break;
747 			}
748 			(void) mutex_unlock(&vt_mutex);
749 
750 			if (err == PAM_NEW_AUTHTOK_REQD) {
751 				chpasswd_tries = 0;
752 
753 				do {
754 					err = pam_chauthtok(vt_pamh,
755 					    PAM_CHANGE_EXPIRED_AUTHTOK);
756 					chpasswd_tries++;
757 
758 					(void) mutex_lock(&vt_mutex);
759 					if (vt_hotkeys_pending) {
760 						(void) mutex_unlock(&vt_mutex);
761 						break;
762 					}
763 					(void) mutex_unlock(&vt_mutex);
764 
765 				} while ((err == PAM_AUTHTOK_ERR ||
766 				    err == PAM_TRY_AGAIN) &&
767 				    chpasswd_tries < DEF_ATTEMPTS);
768 
769 				(void) mutex_lock(&vt_mutex);
770 				if (vt_hotkeys_pending) {
771 					(void) mutex_unlock(&vt_mutex);
772 					break;
773 				}
774 				(void) mutex_unlock(&vt_mutex);
775 
776 				vt_audit_event(ah, ADT_passwd, err);
777 			}
778 		}
779 
780 		/*
781 		 * Only audit failed unlock here, successful unlock
782 		 * will be audited after switching to target vt.
783 		 */
784 		if (err != PAM_SUCCESS) {
785 			(void) fprintf(stdout, "%s",
786 			    pam_strerror(vt_pamh, err));
787 
788 			vt_audit_event(ah, ADT_screenunlock, err);
789 		}
790 
791 		(void) mutex_lock(&vt_mutex);
792 		if (vt_hotkeys_pending) {
793 			(void) mutex_unlock(&vt_mutex);
794 			break;
795 		}
796 		(void) mutex_unlock(&vt_mutex);
797 
798 	} while (err != PAM_SUCCESS);
799 
800 	(void) mutex_lock(&vt_mutex);
801 	if (!vt_hotkeys_pending) {
802 		/*
803 		 * Should be PAM_SUCCESS to reach here.
804 		 */
805 		(void) ioctl(daemonfd, VT_ACTIVATE, target_vt);
806 
807 		vt_audit_event(ah, ADT_screenunlock, err);
808 
809 		/*
810 		 * Free audit handle.
811 		 */
812 		(void) adt_end_session(ah);
813 		vt_ah_array[target_vt - 1] = NULL;
814 	}
815 	(void) mutex_unlock(&vt_mutex);
816 
817 	(void) pam_end(vt_pamh, err);
818 
819 	(void) mutex_lock(&vt_mutex);
820 	vt_auth_doing = B_FALSE;
821 	vt_clear_events();
822 	(void) mutex_unlock(&vt_mutex);
823 }
824 
825 /* main thread (lock and auth) */
826 static void __NORETURN
827 vt_serve_events(void)
828 {
829 	struct pollfd pollfds[1];
830 	int ret;
831 	vt_evt_t ve;
832 
833 	pollfds[0].fd = eventstream[1];
834 	pollfds[0].events = POLLIN | POLLRDNORM | POLLRDBAND | POLLPRI;
835 
836 	for (;;) {
837 		pollfds[0].revents = 0;
838 		ret = poll(pollfds,
839 		    sizeof (pollfds) / sizeof (struct pollfd), -1);
840 		if (ret == -1 && errno == EINTR) {
841 			continue;
842 		}
843 
844 		if (pollfds[0].revents && eventstream_read(1, &ve)) {
845 			/* new request */
846 			switch (ve.ve_cmd) {
847 			case VT_EV_AUTH:
848 				vt_do_auth(ve.ve_info);
849 				break;
850 
851 			case VT_EV_LOCK:
852 				vt_activate_screenlock(ve.ve_info);
853 				break;
854 
855 			case VT_EV_ACTIVATE:
856 				/* directly activate target vt */
857 				vt_do_activate(ve.ve_info);
858 				break;
859 			}
860 		}
861 	}
862 }
863 
864 static void
865 vt_check_target_session(uint32_t target_vt)
866 {
867 	pid_t	pid = (pid_t)-1;
868 
869 	if (!vt_secure) {
870 		vt_ev_request(VT_EV_ACTIVATE, target_vt);
871 		return;
872 	}
873 
874 	/* check the target session */
875 	vt_read_utx(target_vt, &pid, NULL);
876 	if (pid  == (pid_t)-1) {
877 		vt_ev_request(VT_EV_ACTIVATE, target_vt);
878 		return;
879 	}
880 
881 	vt_ev_request(VT_EV_AUTH, target_vt);
882 }
883 
884 static boolean_t
885 vt_get_active_disp_info(struct vt_dispinfo *vd)
886 {
887 	int fd;
888 	struct vt_stat state;
889 	char vtname[16];
890 
891 	if ((fd = open(VT_DAEMON_CONSOLE_FILE, O_RDONLY)) < 0)
892 		return (B_FALSE);
893 
894 	if (ioctl(fd, VT_GETSTATE, &state) != 0) {
895 		(void) close(fd);
896 		return (B_FALSE);
897 	}
898 	(void) close(fd);
899 
900 	(void) snprintf(vtname, sizeof (vtname), "/dev/vt/%d", state.v_active);
901 	if ((fd = open(vtname, O_RDONLY)) < 0)
902 		return (B_FALSE);
903 
904 	if (ioctl(fd, VT_GETDISPINFO, vd) != 0) {
905 		(void) close(fd);
906 		return (B_FALSE);
907 	}
908 
909 	(void) close(fd);
910 	return (B_TRUE);
911 }
912 
913 /*
914  * Xserver registers its pid into kernel to associate it with
915  * its vt upon startup for each graphical display. So here we can
916  * check if the pid is of the Xserver for the current active
917  * display when we receive a special VT_EV_X_EXIT request from
918  * a process. If the request does not come from the current
919  * active Xserver, it is discarded.
920  */
921 static boolean_t
922 vt_check_disp_active(pid_t x_pid)
923 {
924 	struct vt_dispinfo vd;
925 
926 	if (vt_get_active_disp_info(&vd) &&
927 	    vd.v_pid == x_pid)
928 		return (B_TRUE);
929 
930 	return (B_FALSE);
931 }
932 
933 /*
934  * check if the pid is of the Xserver for the current active display,
935  * return true when it is, and then also return other associated
936  * information with the Xserver.
937  */
938 static boolean_t
939 vt_get_disp_info(pid_t x_pid, int *logged_in, int *display_num)
940 {
941 	struct vt_dispinfo vd;
942 
943 	if (!vt_get_active_disp_info(&vd) ||
944 	    vd.v_pid != x_pid)
945 		return (B_FALSE);
946 
947 	*logged_in = vd.v_login;
948 	*display_num = vd.v_dispnum;
949 	return (B_TRUE);
950 }
951 
952 static void
953 vt_terminate_auth(void)
954 {
955 	struct timespec sleeptime;
956 
957 	sleeptime.tv_sec = 0;
958 	sleeptime.tv_nsec = 1000000; /* 1ms */
959 
960 	(void) mutex_lock(&vt_mutex);
961 	while (vt_auth_doing) {
962 		vt_ev_request(VT_EV_TERMINATE_AUTH, 0);
963 
964 		if (vt_auth_doing) {
965 			(void) mutex_unlock(&vt_mutex);
966 			(void) nanosleep(&sleeptime, NULL);
967 			sleeptime.tv_nsec *= 2;
968 			(void) mutex_lock(&vt_mutex);
969 		}
970 	}
971 	(void) mutex_unlock(&vt_mutex);
972 }
973 
974 static void
975 vt_do_hotkeys(pid_t pid, uint32_t target_vt)
976 {
977 	int		logged_in;
978 	int		display_num;
979 
980 	if (validate_target_vt(target_vt) != 0)
981 		return;
982 
983 	/*
984 	 * Maybe last switch action is being taken and the lock is ongoing,
985 	 * here we must reject the newly request.
986 	 */
987 	(void) mutex_lock(&vt_mutex);
988 	if (vt_hotkeys_pending) {
989 		(void) mutex_unlock(&vt_mutex);
990 		return;
991 	}
992 
993 	/* cleared in vt_do_active and vt_do_auth */
994 	vt_hotkeys_pending = B_TRUE;
995 	(void) mutex_unlock(&vt_mutex);
996 
997 	vt_terminate_auth();
998 
999 	/* check source session for this hotkeys request */
1000 	if (pid == 0) {
1001 		/* ok, it comes from kernel. */
1002 		if (vt_secure)
1003 			vt_check_source_audit();
1004 
1005 		/* then only need to check target session */
1006 		vt_check_target_session(target_vt);
1007 		return;
1008 	}
1009 
1010 	/*
1011 	 * check if it comes from current active X graphical session,
1012 	 * if not, ignore this request.
1013 	 */
1014 	if (!vt_get_disp_info(pid, &logged_in, &display_num)) {
1015 		(void) mutex_lock(&vt_mutex);
1016 		vt_hotkeys_pending = B_FALSE;
1017 		(void) mutex_unlock(&vt_mutex);
1018 		return;
1019 	}
1020 
1021 	if (logged_in && vt_secure)
1022 		vt_ev_request(VT_EV_LOCK, display_num);
1023 
1024 	vt_check_target_session(target_vt);
1025 }
1026 
1027 /*
1028  * The main routine for the door server that deals with secure hotkeys
1029  */
1030 /* ARGSUSED */
1031 static void
1032 server_for_door(void *cookie, char *args, size_t alen, door_desc_t *dp,
1033     uint_t n_desc)
1034 {
1035 	ucred_t *uc = NULL;
1036 	vt_cmd_arg_t *vtargp;
1037 
1038 	/* LINTED E_BAD_PTR_CAST_ALIGN */
1039 	vtargp = (vt_cmd_arg_t *)args;
1040 
1041 	if (vtargp == NULL ||
1042 	    alen != sizeof (vt_cmd_arg_t) ||
1043 	    door_ucred(&uc) != 0) {
1044 		(void) door_return(NULL, 0, NULL, 0);
1045 		return;
1046 	}
1047 
1048 	switch (vtargp->vt_ev) {
1049 	case VT_EV_X_EXIT:
1050 		/*
1051 		 * Xserver will issue this event requesting to switch back
1052 		 * to previous active vt when it's exiting and the associated
1053 		 * vt is currently active.
1054 		 */
1055 		if (vt_check_disp_active(ucred_getpid(uc)))
1056 			vt_do_hotkeys(0, vtargp->vt_num);
1057 		break;
1058 
1059 	case VT_EV_HOTKEYS:
1060 		if (!vt_hotkeys)	/* hotkeys are disabled? */
1061 			break;
1062 
1063 		vt_do_hotkeys(ucred_getpid(uc), vtargp->vt_num);
1064 		break;
1065 
1066 	default:
1067 		break;
1068 	}
1069 
1070 	ucred_free(uc);
1071 	(void) door_return(NULL, 0, NULL, 0);
1072 }
1073 
1074 static boolean_t
1075 setup_door(void)
1076 {
1077 	if ((vt_door = door_create(server_for_door, NULL,
1078 	    DOOR_UNREF | DOOR_REFUSE_DESC | DOOR_NO_CANCEL)) < 0) {
1079 		syslog(LOG_ERR, "door_create failed: %s", strerror(errno));
1080 		return (B_FALSE);
1081 	}
1082 
1083 	(void) fdetach(vt_door_path);
1084 
1085 	if (fattach(vt_door, vt_door_path) != 0) {
1086 		syslog(LOG_ERR, "fattach to %s failed: %s",
1087 		    vt_door_path, strerror(errno));
1088 		(void) door_revoke(vt_door);
1089 		(void) fdetach(vt_door_path);
1090 		vt_door = -1;
1091 		return (B_FALSE);
1092 	}
1093 
1094 	return (B_TRUE);
1095 }
1096 
1097 /*
1098  * check to see if vtdaemon is already running.
1099  *
1100  * The idea here is that we want to open the path to which we will
1101  * attach our door, lock it, and then make sure that no-one has beat us
1102  * to fattach(3c)ing onto it.
1103  *
1104  * fattach(3c) is really a mount, so there are actually two possible
1105  * vnodes we could be dealing with.  Our strategy is as follows:
1106  *
1107  * - If the file we opened is a regular file (common case):
1108  * 	There is no fattach(3c)ed door, so we have a chance of becoming
1109  * 	the running vtdaemon. We attempt to lock the file: if it is
1110  * 	already locked, that means someone else raced us here, so we
1111  * 	lose and give up.
1112  *
1113  * - If the file we opened is a namefs file:
1114  * 	This means there is already an established door fattach(3c)'ed
1115  * 	to the rendezvous path.  We've lost the race, so we give up.
1116  * 	Note that in this case we also try to grab the file lock, and
1117  * 	will succeed in acquiring it since the vnode locked by the
1118  * 	"winning" vtdaemon was a regular one, and the one we locked was
1119  * 	the fattach(3c)'ed door node.  At any rate, no harm is done.
1120  */
1121 static boolean_t
1122 make_daemon_exclusive(void)
1123 {
1124 	int doorfd = -1;
1125 	boolean_t ret = B_FALSE;
1126 	struct stat st;
1127 	struct flock flock;
1128 
1129 top:
1130 	if ((doorfd = open(vt_door_path, O_CREAT|O_RDWR,
1131 	    S_IREAD|S_IWRITE|S_IRGRP|S_IROTH)) < 0) {
1132 		syslog(LOG_ERR, "failed to open %s", vt_door_path);
1133 		goto out;
1134 	}
1135 	if (fstat(doorfd, &st) < 0) {
1136 		syslog(LOG_ERR, "failed to stat %s", vt_door_path);
1137 		goto out;
1138 	}
1139 	/*
1140 	 * Lock the file to synchronize
1141 	 */
1142 	flock.l_type = F_WRLCK;
1143 	flock.l_whence = SEEK_SET;
1144 	flock.l_start = (off_t)0;
1145 	flock.l_len = (off_t)0;
1146 	if (fcntl(doorfd, F_SETLK, &flock) < 0) {
1147 		/*
1148 		 * Someone else raced us here and grabbed the lock file
1149 		 * first.  A warning here and exit.
1150 		 */
1151 		syslog(LOG_ERR, "vtdaemon is already running!");
1152 		goto out;
1153 	}
1154 
1155 	if (strcmp(st.st_fstype, "namefs") == 0) {
1156 		struct door_info info;
1157 
1158 		/*
1159 		 * There is already something fattach()'ed to this file.
1160 		 * Lets see what the door is up to.
1161 		 */
1162 		if (door_info(doorfd, &info) == 0 && info.di_target != -1) {
1163 			syslog(LOG_ERR, "vtdaemon is already running!");
1164 			goto out;
1165 		}
1166 
1167 		(void) fdetach(vt_door_path);
1168 		(void) close(doorfd);
1169 		goto top;
1170 	}
1171 
1172 	ret = setup_door();
1173 
1174 out:
1175 	(void) close(doorfd);
1176 	return (ret);
1177 }
1178 
1179 static boolean_t
1180 mkvtdir(void)
1181 {
1182 	struct stat st;
1183 	/*
1184 	 * We must create and lock everyone but root out of VT_TMPDIR
1185 	 * since anyone can open any UNIX domain socket, regardless of
1186 	 * its file system permissions.
1187 	 */
1188 	if (mkdir(VT_TMPDIR, S_IRWXU|S_IROTH|S_IXOTH|S_IRGRP|S_IXGRP) < 0 &&
1189 	    errno != EEXIST) {
1190 		syslog(LOG_ERR, "could not mkdir '%s'", VT_TMPDIR);
1191 		return (B_FALSE);
1192 	}
1193 	/* paranoia */
1194 	if ((stat(VT_TMPDIR, &st) < 0) || !S_ISDIR(st.st_mode)) {
1195 		syslog(LOG_ERR, "'%s' is not a directory", VT_TMPDIR);
1196 		return (B_FALSE);
1197 	}
1198 	(void) chmod(VT_TMPDIR, S_IRWXU|S_IROTH|S_IXOTH|S_IRGRP|S_IXGRP);
1199 	return (B_TRUE);
1200 }
1201 
1202 int
1203 main(int argc, char *argv[])
1204 {
1205 	int i;
1206 	int opt;
1207 	priv_set_t *privset;
1208 	int active;
1209 
1210 	openlog("vtdaemon", LOG_PID | LOG_CONS, 0);
1211 
1212 	/*
1213 	 * Check that we have all privileges.  It would be nice to pare
1214 	 * this down, but this is at least a first cut.
1215 	 */
1216 	if ((privset = priv_allocset()) == NULL) {
1217 		syslog(LOG_ERR, "priv_allocset failed");
1218 		return (1);
1219 	}
1220 
1221 	if (getppriv(PRIV_EFFECTIVE, privset) != 0) {
1222 		syslog(LOG_ERR, "getppriv failed", "getppriv");
1223 		priv_freeset(privset);
1224 		return (1);
1225 	}
1226 
1227 	if (priv_isfullset(privset) == B_FALSE) {
1228 		syslog(LOG_ERR, "You lack sufficient privilege "
1229 		    "to run this command (all privs required)");
1230 		priv_freeset(privset);
1231 		return (1);
1232 	}
1233 	priv_freeset(privset);
1234 
1235 	while ((opt = getopt(argc, argv, "ksrc:")) != EOF) {
1236 		switch (opt) {
1237 		case 'k':
1238 			vt_hotkeys = B_FALSE;
1239 			break;
1240 		case 's':
1241 			vt_secure = B_FALSE;
1242 			break;
1243 		case 'c':
1244 			vtnodecount = atoi(optarg);
1245 			break;
1246 		default:
1247 			break;
1248 		}
1249 	}
1250 
1251 	(void) vt_setup_signal(SIGINT, 1);
1252 
1253 	if (!mkvtdir())
1254 		return (1);
1255 
1256 	if (!eventstream_init())
1257 		return (1);
1258 
1259 	(void) snprintf(vt_door_path, sizeof (vt_door_path),
1260 	    VT_TMPDIR "/vtdaemon_door");
1261 
1262 	if (!make_daemon_exclusive())
1263 		return (1);
1264 
1265 	/* only the main thread accepts SIGINT */
1266 	(void) vt_setup_signal(SIGINT, 0);
1267 	(void) sigset(SIGPIPE, SIG_IGN);
1268 	(void) signal(SIGQUIT, SIG_IGN);
1269 	(void) signal(SIGINT, catch);
1270 
1271 	for (i = 0; i < 3; i++)
1272 		(void) close(i);
1273 	(void) setsid();
1274 
1275 	if ((daemonfd = open(VT_DAEMON_CONSOLE_FILE, O_RDWR)) < 0) {
1276 		return (1);
1277 	}
1278 
1279 	if (daemonfd != 0)
1280 		(void) dup2(daemonfd, STDIN_FILENO);
1281 	if (daemonfd != 1)
1282 		(void) dup2(daemonfd, STDOUT_FILENO);
1283 
1284 	if (vtnodecount >= 2)
1285 		(void) ioctl(daemonfd, VT_CONFIG, vtnodecount);
1286 
1287 	if ((vt_ah_array = calloc(vtnodecount - 1,
1288 	    sizeof (adt_session_data_t *))) == NULL)
1289 		return (1);
1290 
1291 	(void) ioctl(daemonfd, VT_GETACTIVE, &active);
1292 
1293 	if (active == 1) {
1294 		/*
1295 		 * This is for someone who restarts vtdaemon while vtdaemon
1296 		 * is doing authentication on /dev/vt/1.
1297 		 * A better way is to continue the authentication, but there
1298 		 * are chances that the status of the target VT has changed.
1299 		 * So we just clear the screen here.
1300 		 */
1301 		(void) write(daemonfd, VT_CLEAR_SCREEN_STR,
1302 		    strlen(VT_CLEAR_SCREEN_STR));
1303 	}
1304 
1305 	vt_serve_events();
1306 	/*NOTREACHED*/
1307 }
1308 
1309 static int
1310 vt_audit_start(adt_session_data_t **ah, pid_t pid)
1311 {
1312 	ucred_t *uc;
1313 
1314 	if (adt_start_session(ah, NULL, 0))
1315 		return (-1);
1316 
1317 	if ((uc = ucred_get(pid)) == NULL) {
1318 		(void) adt_end_session(*ah);
1319 		return (-1);
1320 	}
1321 
1322 	if (adt_set_from_ucred(*ah, uc, ADT_NEW)) {
1323 		ucred_free(uc);
1324 		(void) adt_end_session(*ah);
1325 		return (-1);
1326 	}
1327 
1328 	ucred_free(uc);
1329 	return (0);
1330 }
1331 
1332 /*
1333  * Write audit event
1334  */
1335 static void
1336 vt_audit_event(adt_session_data_t *ah, au_event_t event_id, int status)
1337 {
1338 	adt_event_data_t	*event;
1339 
1340 
1341 	if ((event = adt_alloc_event(ah, event_id)) == NULL) {
1342 		return;
1343 	}
1344 
1345 	(void) adt_put_event(event,
1346 	    status == PAM_SUCCESS ? ADT_SUCCESS : ADT_FAILURE,
1347 	    status == PAM_SUCCESS ? ADT_SUCCESS : ADT_FAIL_PAM + status);
1348 
1349 	adt_free_event(event);
1350 }
1351 
1352 static void
1353 vt_check_source_audit(void)
1354 {
1355 	int	fd;
1356 	int	source_vt;
1357 	int	real_vt;
1358 	struct vt_stat state;
1359 	pid_t	pid;
1360 	adt_session_data_t *ah;
1361 
1362 	if ((fd = open(VT_DAEMON_CONSOLE_FILE, O_WRONLY)) < 0)
1363 		return;
1364 
1365 	if (ioctl(fd, VT_GETSTATE, &state) != 0 ||
1366 	    ioctl(fd, VT_GETACTIVE, &real_vt) != 0) {
1367 		(void) close(fd);
1368 		return;
1369 	}
1370 
1371 	source_vt = state.v_active;	/* 1..n */
1372 	(void) close(fd);
1373 
1374 	/* check if it's already locked */
1375 	if (real_vt == 1)	/* vtdaemon is taking over the screen */
1376 		return;
1377 
1378 	vt_read_utx(source_vt, &pid, NULL);
1379 	if (pid == (pid_t)-1)
1380 		return;
1381 
1382 	if (vt_audit_start(&ah, pid) != 0) {
1383 		syslog(LOG_ERR, "audit start failed ");
1384 		return;
1385 	}
1386 
1387 	/*
1388 	 * In case the previous session terminated abnormally.
1389 	 */
1390 	if (vt_ah_array[source_vt - 1] != NULL)
1391 		(void) adt_end_session(vt_ah_array[source_vt - 1]);
1392 
1393 	vt_ah_array[source_vt - 1] = ah;
1394 
1395 	vt_audit_event(ah, ADT_screenlock, PAM_SUCCESS);
1396 }
1397