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