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