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