4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
27 * vtdaemon is responsible for the session secure switch via hotkeys.
29 * vtdaemon itself, like ttymon(1M), is also running on a virtual
30 * console device (/dev/vt/1), and provides a text console session
31 * for password input and authentication. The /dev/vt/1 special text
32 * console is reserved and end users cannot switch to it via hotkeys.
35 * The hotkey event request can come from either kernel or Xserver,
36 * and a door server is setup to handle the request:
38 * 1) All text console hotkeys (e.g. "Alt + F#") are intercepted by
39 * the kernel console driver which sends a door upcall to the
40 * vtdaemon via door_upcall (target_vt).
42 * 2) All Xserver hotkeys ("Alt + Ctrl + F#") are intercepted by
43 * Xserver which sends a door call to the vtdaemon via
44 * door_call (target_vt).
47 * server_for_door receives and handles any door server requests:
49 * Firstly, check source session:
51 * . If it's from kernel for a text console source session,
52 * then directly go to check the target session.
54 * . If it's from Xserver for a graphical source session and the vt
55 * associated with the Xserver is currently active:
56 * check if a user has logged in, if true, issue an internal
57 * VT_EV_LOCK event to the main thread to request lock for
58 * the graphical source session; else, directly go to check
61 * . otherwise, discard this request.
64 * Secondly, check the target session
66 * . if the target session is a text one that no one has logged in
67 * or a graphical one, issue an internal VT_EV_ACTIVATE event to
68 * the main thread to request the actual VT switch.
70 * . otherwise, the target session is a text one that someone has
71 * logged in, issue an internal VT_EV_AUTH event to the main
72 * thread to request authentication for the target session.
75 * The main thread of vtdaemon is a loop waiting for internal events
76 * which come from door call threads:
78 * 1) VT_EV_AUTH to authenticate for target session:
80 * firstly switch to the vtdaemon special text console;
81 * then prompt for password (target_owner on target_vt),
82 * e.g. "User Bob's password on vt/#: ".
84 * if the password is correct (authentication succeeds),
85 * then actually issue the VT switch; otherwise, ignore
88 * 2) VT_EV_LOCK to lock the graphical source session:
90 * activate screenlock for this graphical session.
91 * vtdaemon just invokes existing front-end command line
92 * tools (e.g. xscreensaver-command -lock for JDS) to
95 * 3) VT_EV_ACTIVATE to directly switch to the target session
98 * There is a system/vtdaemon:default SMF service for vtdaemon.
100 * There's a "hotkeys" property (BOOLEAN) in the
101 * system/vtdaemon:default SMF service, which allows authorized
102 * users to dynamically enable or disable VT switch via hotkeys.
103 * Its default value is TRUE (enabled).
105 * There's a "secure" property (BOOLEAN) in the
106 * system/vtdaemon:default SMF service, which allows authorized
107 * users to dynamically enable or disable hotkeys are secure.
108 * If disabled, the user can freely switch to any session without
109 * authentication. Its default value is TRUE (enabled).
112 * By default, there's only 16 virtual console device nodes (from
113 * /dev/vt/0 to /dev/vt/15). There's a property "nodecount"
114 * (default value is 16) in the system/vtdaemon:default SMF
115 * service, so authorized users can configure it to have more
116 * or less virtual console device nodes.
118 * Xserver needs to switch back to previous active vt via VT_EV_X_EXIT
119 * door event request when it's exiting, so vtdaemon always needs to
120 * be there even if the hotkeys switch is disabled, otherwise the screen
121 * will be just blank when Xserver exits.
124 #include <sys/param.h>
125 #include <sys/mman.h>
126 #include <sys/types.h>
127 #include <sys/wait.h>
128 #include <sys/stat.h>
129 #include <sys/sysmacros.h>
134 #include <bsm/adt_event.h>
159 #include <security/pam_appl.h>
161 #include <sys/console.h>
166 #include <sys/vtdaemon.h>
169 * The door file /var/run/vt/vtdaemon_door
171 #define VT_TMPDIR "/var/run/vt"
173 #define VT_DAEMON_ARG 0
174 #define VT_DAEMON_CONSOLE_FILE "/dev/vt/1"
176 #define VT_IS_SYSTEM_CONSOLE(vtno) ((vtno) == 1)
178 /* Defaults for updating expired passwords */
179 #define DEF_ATTEMPTS 3
183 static boolean_t vt_hotkeys
= B_TRUE
; /* '-k' option to disable */
184 static boolean_t vt_secure
= B_TRUE
; /* '-s' option to disable */
186 static char vt_door_path
[MAXPATHLEN
];
187 static int vt_door
= -1;
189 /* protecting vt_hotkeys_pending and vt_auth_doing */
190 static mutex_t vt_mutex
= DEFAULTMUTEX
;
192 static boolean_t vt_hotkeys_pending
= B_FALSE
;
193 static boolean_t vt_auth_doing
= B_FALSE
;
195 static adt_session_data_t
**vt_ah_array
= NULL
;
196 static int vtnodecount
= 0;
198 static int vt_audit_start(adt_session_data_t
**, pid_t
);
199 static void vt_audit_event(adt_session_data_t
*, au_event_t
, int);
200 static void vt_check_source_audit(void);
203 vt_setup_signal(int signo
, int mask
)
207 (void) sigemptyset(&set
);
208 (void) sigaddset(&set
, signo
);
211 return (sigprocmask(SIG_BLOCK
, &set
, NULL
));
213 return (sigprocmask(SIG_UNBLOCK
, &set
, NULL
));
217 do_activate_screenlock(int display_num
)
221 (void) snprintf(dpy
, sizeof (dpy
), "%d", display_num
);
222 (void) execl("/usr/lib/vtxlock", "vtxlock", dpy
, NULL
);
226 vt_activate_screenlock(int display
)
230 if ((pid
= fork()) == -1)
233 if (pid
== 0) { /* child */
234 do_activate_screenlock(display
);
239 while (waitpid(pid
, (int *)0, 0) != pid
)
244 * Find the login process and user logged in on the target vt.
247 vt_read_utx(int target_vt
, pid_t
*pid
, char name
[])
250 char ttyntail
[sizeof (u
->ut_line
)];
254 if (VT_IS_SYSTEM_CONSOLE(target_vt
)) /* system console */
255 (void) snprintf(ttyntail
, sizeof (ttyntail
),
258 (void) snprintf(ttyntail
, sizeof (ttyntail
),
259 "%s%d", "vt/", target_vt
);
262 while ((u
= getutxent()) != NULL
)
263 /* see if this is the entry we want */
264 if ((u
->ut_type
== USER_PROCESS
) &&
266 (u
->ut_host
[0] == '\0') &&
267 (strncmp(u
->ut_line
, ttyntail
, sizeof (u
->ut_line
)) == 0)) {
271 (void) strncpy(name
, u
->ut_user
,
272 sizeof (u
->ut_user
));
273 name
[sizeof (u
->ut_user
)] = '\0';
284 static int is_tipline
= 0;
286 static char termbuf
[MAX_TERM_TYPE_LEN
];
287 static struct cons_getterm cons_term
= { sizeof (termbuf
), termbuf
};
290 return (is_tipline
== 1);
292 if ((fd
= open("/dev/console", O_RDONLY
)) < 0)
295 if (ioctl(fd
, CONS_GETTERM
, &cons_term
) != 0 &&
303 return (is_tipline
== 1);
307 validate_target_vt(int target_vt
)
310 struct vt_stat state
;
315 if ((fd
= open(VT_DAEMON_CONSOLE_FILE
, O_WRONLY
)) < 0)
318 if (ioctl(fd
, VT_GETSTATE
, &state
) != 0) {
325 if (state
.v_active
== target_vt
) {
326 return (1); /* it's current active vt */
329 if (target_vt
== 1) {
331 * In tipline case, the system console is always
332 * available, so ignore this request.
341 * The hotkey request and corresponding target_vt number can come
342 * from either kernel or Xserver (or other user applications).
343 * In kernel we've validated the hotkey request, but Xserver (or
344 * other user applications) cannot do it, so here we still try
347 * VT_GETSTATE is only valid for first 16 VTs for historical reasons.
348 * Fortunately, in practice, Xserver can only send the hotkey
349 * request of target_vt number from 1 to 12 (Ctrl + Alt + F1 to F2).
351 if (target_vt
< 8 * sizeof (state
.v_state
)) {
352 if ((state
.v_state
& (1 << target_vt
)) != 0) {
363 vt_do_activate(int target_vt
)
365 (void) ioctl(daemonfd
, VT_ACTIVATE
, target_vt
);
366 (void) mutex_lock(&vt_mutex
);
367 vt_hotkeys_pending
= B_FALSE
;
368 (void) mutex_unlock(&vt_mutex
);
371 /* events written to fd 0 and read from fd 1 */
374 #define VT_EV_ACTIVATE 3
376 /* events written to fd 1 and read from fd 0 */
377 #define VT_EV_TERMINATE_AUTH 4
379 typedef struct vt_evt
{
381 int ve_info
; /* vtno or display num */
384 static int eventstream
[2];
387 eventstream_init(void)
389 if (pipe(eventstream
) == -1)
395 eventstream_write(int channel
, vt_evt_t
*pevt
)
397 (void) write(eventstream
[channel
], pevt
, sizeof (vt_evt_t
));
401 eventstream_read(int channel
, vt_evt_t
*pevt
)
405 rval
= read(eventstream
[channel
], pevt
, sizeof (vt_evt_t
));
410 vt_ev_request(int cmd
, int info
)
418 channel
= (cmd
== VT_EV_TERMINATE_AUTH
) ? 1 : 0;
419 eventstream_write(channel
, &ve
);
423 vt_clear_events(void)
430 rval
= fstat(eventstream
[0], &buf
);
431 if (rval
!= -1 && buf
.st_size
> 0)
432 (void) eventstream_read(0, &evt
);
438 static int vt_conv(int, struct pam_message
**,
439 struct pam_response
**, void *);
445 (void) signal(SIGINT
, catch);
449 * The SIGINT (ctl_c) will restart the authentication, and re-prompt
450 * the end user to input the password.
455 struct pollfd pollfds
[2];
459 pollfds
[0].fd
= eventstream
[0];
460 pollfds
[1].fd
= daemonfd
;
461 pollfds
[0].events
= pollfds
[1].events
=
462 POLLIN
| POLLRDNORM
| POLLRDBAND
| POLLPRI
;
465 pollfds
[0].revents
= pollfds
[1].revents
= 0;
468 sizeof (pollfds
) / sizeof (struct pollfd
), -1);
469 if (ret
== -1 && errno
!= EINTR
) {
473 if (ret
== -1 && errno
== EINTR
)
476 if (pollfds
[0].revents
) {
477 (void) eventstream_read(0, &ve
);
481 if (pollfds
[1].revents
)
495 cnt
= read(fd
, &c
, 1);
504 vt_getinput(int noecho
)
510 char input
[PAM_MAX_RESP_SIZE
];
513 (void) ioctl(daemonfd
, TCGETA
, &tty
);
514 tty_flags
= tty
.c_lflag
;
515 tty
.c_lflag
&= ~(ECHO
| ECHOE
| ECHOK
| ECHONL
);
516 (void) ioctl(daemonfd
, TCSETAF
, &tty
);
519 while ((vt_poll()) == 1) {
520 if ((c
= vt_getchar(daemonfd
)) != '\n' && c
!= '\r' &&
521 c
!= EOF
&& (i
< PAM_MAX_RESP_SIZE
- 1))
522 input
[i
++] = (char)c
;
530 tty
.c_lflag
= tty_flags
;
531 (void) ioctl(daemonfd
, TCSETAW
, &tty
);
532 (void) fputc('\n', stdout
);
535 return (strdup(input
));
539 * vt_conv: vtdaemon PAM conversation function.
540 * SIGINT/EINTR is handled in vt_getinput()/vt_poll().
545 vt_conv(int num_msg
, struct pam_message
**msg
,
546 struct pam_response
**response
, void *appdata_ptr
)
548 struct pam_message
*m
;
549 struct pam_response
*r
;
552 if (num_msg
>= PAM_MAX_NUM_MSG
) {
553 syslog(LOG_ERR
, "too many messages %d >= %d",
554 num_msg
, PAM_MAX_NUM_MSG
);
556 return (PAM_CONV_ERR
);
559 *response
= calloc(num_msg
, sizeof (struct pam_response
));
560 if (*response
== NULL
)
561 return (PAM_BUF_ERR
);
565 for (i
= 0; i
< num_msg
; i
++) {
569 if (m
->msg
== NULL
) {
570 syslog(LOG_ERR
, "message[%d]: %d/NULL\n",
576 * Fix up final newline:
577 * remove from prompts, add back for messages.
579 if (m
->msg
[strlen(m
->msg
)] == '\n')
580 m
->msg
[strlen(m
->msg
)] = '\0';
585 switch (m
->msg_style
) {
587 case PAM_PROMPT_ECHO_OFF
:
591 case PAM_PROMPT_ECHO_ON
:
592 (void) fputs(m
->msg
, stdout
);
594 r
->resp
= vt_getinput(echo_off
);
598 /* the user may want to see this */
599 (void) fputs(m
->msg
, stdout
);
600 (void) fputs("\n", stdout
);
604 (void) fputs(m
->msg
, stdout
);
605 (void) fputs("\n", stdout
);
609 syslog(LOG_ERR
, "message[%d]: unknown type"
610 "%d/val=\"%s\"", i
, m
->msg_style
, m
->msg
);
612 /* error, service module won't clean up */
616 /* Next message/response */
621 return (PAM_SUCCESS
);
625 * Service modules don't clean up responses if an error is returned.
626 * Free responses here.
629 for (k
= 0; k
< i
; k
++, r
++) {
631 /* Clear before freeing -- maybe a password */
632 bzero(r
->resp
, strlen(r
->resp
));
640 return (PAM_CONV_ERR
);
643 #define DEF_FILE "/etc/default/login"
645 /* Get PASSREQ from default file */
651 boolean_t retval
= B_FALSE
;
653 if ((defopen(DEF_FILE
)) == 0) {
655 flags
= defcntl(DC_GETFLAGS
, 0);
656 TURNOFF(flags
, DC_CASE
);
657 (void) defcntl(DC_SETFLAGS
, flags
);
659 if ((ptr
= defread("PASSREQ=")) != NULL
&&
660 strcasecmp("YES", ptr
) == 0)
663 (void) defopen(NULL
);
670 * VT_CLEAR_SCREEN_STR is the console terminal escape sequence used to
671 * clear the current screen. The vt special console (/dev/vt/1) is
672 * just reserved for vtdaemon, and the TERM/termcap of it is always
673 * the local sun-color, which is always supported by our kernel terminal
676 #define VT_CLEAR_SCREEN_STR "\033[2J\033[1;1H"
679 vt_do_auth(int target_vt
)
681 char user_name
[sizeof (((struct utmpx
*)0)->ut_line
) + 1] = {'\0'};
682 pam_handle_t
*vt_pamh
;
686 struct pam_conv pam_conv
= {vt_conv
, NULL
};
688 adt_session_data_t
*ah
;
690 vt_read_utx(target_vt
, &pid
, user_name
);
692 if (pid
== (pid_t
)-1 || user_name
[0] == '\0')
695 if ((err
= pam_start("vtdaemon", user_name
, &pam_conv
,
696 &vt_pamh
)) != PAM_SUCCESS
)
700 * firstly switch to the vtdaemon special console
701 * and clear the current screen
703 (void) ioctl(daemonfd
, VT_ACTIVATE
, VT_DAEMON_ARG
);
704 (void) write(daemonfd
, VT_CLEAR_SCREEN_STR
,
705 strlen(VT_CLEAR_SCREEN_STR
));
706 (void) ioctl(daemonfd
, VT_SET_TARGET
, target_vt
);
708 (void) mutex_lock(&vt_mutex
);
709 vt_auth_doing
= B_TRUE
;
710 vt_hotkeys_pending
= B_FALSE
;
711 (void) mutex_unlock(&vt_mutex
);
714 * Fetch audit handle.
716 ah
= vt_ah_array
[target_vt
- 1];
719 pam_flag
= PAM_DISALLOW_NULL_AUTHTOK
;
722 if (VT_IS_SYSTEM_CONSOLE(target_vt
))
723 (void) fprintf(stdout
,
724 "\nUnlock user %s on the system console\n",
727 (void) fprintf(stdout
,
728 "\nUnlock user %s on vt/%d\n", user_name
,
731 err
= pam_authenticate(vt_pamh
, pam_flag
);
733 (void) mutex_lock(&vt_mutex
);
734 if (vt_hotkeys_pending
) {
735 (void) mutex_unlock(&vt_mutex
);
738 (void) mutex_unlock(&vt_mutex
);
740 if (err
== PAM_SUCCESS
) {
741 err
= pam_acct_mgmt(vt_pamh
, pam_flag
);
743 (void) mutex_lock(&vt_mutex
);
744 if (vt_hotkeys_pending
) {
745 (void) mutex_unlock(&vt_mutex
);
748 (void) mutex_unlock(&vt_mutex
);
750 if (err
== PAM_NEW_AUTHTOK_REQD
) {
754 err
= pam_chauthtok(vt_pamh
,
755 PAM_CHANGE_EXPIRED_AUTHTOK
);
758 (void) mutex_lock(&vt_mutex
);
759 if (vt_hotkeys_pending
) {
760 (void) mutex_unlock(&vt_mutex
);
763 (void) mutex_unlock(&vt_mutex
);
765 } while ((err
== PAM_AUTHTOK_ERR
||
766 err
== PAM_TRY_AGAIN
) &&
767 chpasswd_tries
< DEF_ATTEMPTS
);
769 (void) mutex_lock(&vt_mutex
);
770 if (vt_hotkeys_pending
) {
771 (void) mutex_unlock(&vt_mutex
);
774 (void) mutex_unlock(&vt_mutex
);
776 vt_audit_event(ah
, ADT_passwd
, err
);
781 * Only audit failed unlock here, successful unlock
782 * will be audited after switching to target vt.
784 if (err
!= PAM_SUCCESS
) {
785 (void) fprintf(stdout
, "%s",
786 pam_strerror(vt_pamh
, err
));
788 vt_audit_event(ah
, ADT_screenunlock
, err
);
791 (void) mutex_lock(&vt_mutex
);
792 if (vt_hotkeys_pending
) {
793 (void) mutex_unlock(&vt_mutex
);
796 (void) mutex_unlock(&vt_mutex
);
798 } while (err
!= PAM_SUCCESS
);
800 (void) mutex_lock(&vt_mutex
);
801 if (!vt_hotkeys_pending
) {
803 * Should be PAM_SUCCESS to reach here.
805 (void) ioctl(daemonfd
, VT_ACTIVATE
, target_vt
);
807 vt_audit_event(ah
, ADT_screenunlock
, err
);
812 (void) adt_end_session(ah
);
813 vt_ah_array
[target_vt
- 1] = NULL
;
815 (void) mutex_unlock(&vt_mutex
);
817 (void) pam_end(vt_pamh
, err
);
819 (void) mutex_lock(&vt_mutex
);
820 vt_auth_doing
= B_FALSE
;
822 (void) mutex_unlock(&vt_mutex
);
825 /* main thread (lock and auth) */
826 static void __NORETURN
827 vt_serve_events(void)
829 struct pollfd pollfds
[1];
833 pollfds
[0].fd
= eventstream
[1];
834 pollfds
[0].events
= POLLIN
| POLLRDNORM
| POLLRDBAND
| POLLPRI
;
837 pollfds
[0].revents
= 0;
839 sizeof (pollfds
) / sizeof (struct pollfd
), -1);
840 if (ret
== -1 && errno
== EINTR
) {
844 if (pollfds
[0].revents
&& eventstream_read(1, &ve
)) {
848 vt_do_auth(ve
.ve_info
);
852 vt_activate_screenlock(ve
.ve_info
);
856 /* directly activate target vt */
857 vt_do_activate(ve
.ve_info
);
865 vt_check_target_session(uint32_t target_vt
)
867 pid_t pid
= (pid_t
)-1;
870 vt_ev_request(VT_EV_ACTIVATE
, target_vt
);
874 /* check the target session */
875 vt_read_utx(target_vt
, &pid
, NULL
);
876 if (pid
== (pid_t
)-1) {
877 vt_ev_request(VT_EV_ACTIVATE
, target_vt
);
881 vt_ev_request(VT_EV_AUTH
, target_vt
);
885 vt_get_active_disp_info(struct vt_dispinfo
*vd
)
888 struct vt_stat state
;
891 if ((fd
= open(VT_DAEMON_CONSOLE_FILE
, O_RDONLY
)) < 0)
894 if (ioctl(fd
, VT_GETSTATE
, &state
) != 0) {
900 (void) snprintf(vtname
, sizeof (vtname
), "/dev/vt/%d", state
.v_active
);
901 if ((fd
= open(vtname
, O_RDONLY
)) < 0)
904 if (ioctl(fd
, VT_GETDISPINFO
, vd
) != 0) {
914 * Xserver registers its pid into kernel to associate it with
915 * its vt upon startup for each graphical display. So here we can
916 * check if the pid is of the Xserver for the current active
917 * display when we receive a special VT_EV_X_EXIT request from
918 * a process. If the request does not come from the current
919 * active Xserver, it is discarded.
922 vt_check_disp_active(pid_t x_pid
)
924 struct vt_dispinfo vd
;
926 if (vt_get_active_disp_info(&vd
) &&
934 * check if the pid is of the Xserver for the current active display,
935 * return true when it is, and then also return other associated
936 * information with the Xserver.
939 vt_get_disp_info(pid_t x_pid
, int *logged_in
, int *display_num
)
941 struct vt_dispinfo vd
;
943 if (!vt_get_active_disp_info(&vd
) ||
947 *logged_in
= vd
.v_login
;
948 *display_num
= vd
.v_dispnum
;
953 vt_terminate_auth(void)
955 struct timespec sleeptime
;
957 sleeptime
.tv_sec
= 0;
958 sleeptime
.tv_nsec
= 1000000; /* 1ms */
960 (void) mutex_lock(&vt_mutex
);
961 while (vt_auth_doing
) {
962 vt_ev_request(VT_EV_TERMINATE_AUTH
, 0);
965 (void) mutex_unlock(&vt_mutex
);
966 (void) nanosleep(&sleeptime
, NULL
);
967 sleeptime
.tv_nsec
*= 2;
968 (void) mutex_lock(&vt_mutex
);
971 (void) mutex_unlock(&vt_mutex
);
975 vt_do_hotkeys(pid_t pid
, uint32_t target_vt
)
980 if (validate_target_vt(target_vt
) != 0)
984 * Maybe last switch action is being taken and the lock is ongoing,
985 * here we must reject the newly request.
987 (void) mutex_lock(&vt_mutex
);
988 if (vt_hotkeys_pending
) {
989 (void) mutex_unlock(&vt_mutex
);
993 /* cleared in vt_do_active and vt_do_auth */
994 vt_hotkeys_pending
= B_TRUE
;
995 (void) mutex_unlock(&vt_mutex
);
999 /* check source session for this hotkeys request */
1001 /* ok, it comes from kernel. */
1003 vt_check_source_audit();
1005 /* then only need to check target session */
1006 vt_check_target_session(target_vt
);
1011 * check if it comes from current active X graphical session,
1012 * if not, ignore this request.
1014 if (!vt_get_disp_info(pid
, &logged_in
, &display_num
)) {
1015 (void) mutex_lock(&vt_mutex
);
1016 vt_hotkeys_pending
= B_FALSE
;
1017 (void) mutex_unlock(&vt_mutex
);
1021 if (logged_in
&& vt_secure
)
1022 vt_ev_request(VT_EV_LOCK
, display_num
);
1024 vt_check_target_session(target_vt
);
1028 * The main routine for the door server that deals with secure hotkeys
1032 server_for_door(void *cookie
, char *args
, size_t alen
, door_desc_t
*dp
,
1036 vt_cmd_arg_t
*vtargp
;
1038 /* LINTED E_BAD_PTR_CAST_ALIGN */
1039 vtargp
= (vt_cmd_arg_t
*)args
;
1041 if (vtargp
== NULL
||
1042 alen
!= sizeof (vt_cmd_arg_t
) ||
1043 door_ucred(&uc
) != 0) {
1044 (void) door_return(NULL
, 0, NULL
, 0);
1048 switch (vtargp
->vt_ev
) {
1051 * Xserver will issue this event requesting to switch back
1052 * to previous active vt when it's exiting and the associated
1053 * vt is currently active.
1055 if (vt_check_disp_active(ucred_getpid(uc
)))
1056 vt_do_hotkeys(0, vtargp
->vt_num
);
1060 if (!vt_hotkeys
) /* hotkeys are disabled? */
1063 vt_do_hotkeys(ucred_getpid(uc
), vtargp
->vt_num
);
1071 (void) door_return(NULL
, 0, NULL
, 0);
1077 if ((vt_door
= door_create(server_for_door
, NULL
,
1078 DOOR_UNREF
| DOOR_REFUSE_DESC
| DOOR_NO_CANCEL
)) < 0) {
1079 syslog(LOG_ERR
, "door_create failed: %s", strerror(errno
));
1083 (void) fdetach(vt_door_path
);
1085 if (fattach(vt_door
, vt_door_path
) != 0) {
1086 syslog(LOG_ERR
, "fattach to %s failed: %s",
1087 vt_door_path
, strerror(errno
));
1088 (void) door_revoke(vt_door
);
1089 (void) fdetach(vt_door_path
);
1098 * check to see if vtdaemon is already running.
1100 * The idea here is that we want to open the path to which we will
1101 * attach our door, lock it, and then make sure that no-one has beat us
1102 * to fattach(3c)ing onto it.
1104 * fattach(3c) is really a mount, so there are actually two possible
1105 * vnodes we could be dealing with. Our strategy is as follows:
1107 * - If the file we opened is a regular file (common case):
1108 * There is no fattach(3c)ed door, so we have a chance of becoming
1109 * the running vtdaemon. We attempt to lock the file: if it is
1110 * already locked, that means someone else raced us here, so we
1113 * - If the file we opened is a namefs file:
1114 * This means there is already an established door fattach(3c)'ed
1115 * to the rendezvous path. We've lost the race, so we give up.
1116 * Note that in this case we also try to grab the file lock, and
1117 * will succeed in acquiring it since the vnode locked by the
1118 * "winning" vtdaemon was a regular one, and the one we locked was
1119 * the fattach(3c)'ed door node. At any rate, no harm is done.
1122 make_daemon_exclusive(void)
1125 boolean_t ret
= B_FALSE
;
1130 if ((doorfd
= open(vt_door_path
, O_CREAT
|O_RDWR
,
1131 S_IREAD
|S_IWRITE
|S_IRGRP
|S_IROTH
)) < 0) {
1132 syslog(LOG_ERR
, "failed to open %s", vt_door_path
);
1135 if (fstat(doorfd
, &st
) < 0) {
1136 syslog(LOG_ERR
, "failed to stat %s", vt_door_path
);
1140 * Lock the file to synchronize
1142 flock
.l_type
= F_WRLCK
;
1143 flock
.l_whence
= SEEK_SET
;
1144 flock
.l_start
= (off_t
)0;
1145 flock
.l_len
= (off_t
)0;
1146 if (fcntl(doorfd
, F_SETLK
, &flock
) < 0) {
1148 * Someone else raced us here and grabbed the lock file
1149 * first. A warning here and exit.
1151 syslog(LOG_ERR
, "vtdaemon is already running!");
1155 if (strcmp(st
.st_fstype
, "namefs") == 0) {
1156 struct door_info info
;
1159 * There is already something fattach()'ed to this file.
1160 * Lets see what the door is up to.
1162 if (door_info(doorfd
, &info
) == 0 && info
.di_target
!= -1) {
1163 syslog(LOG_ERR
, "vtdaemon is already running!");
1167 (void) fdetach(vt_door_path
);
1168 (void) close(doorfd
);
1175 (void) close(doorfd
);
1184 * We must create and lock everyone but root out of VT_TMPDIR
1185 * since anyone can open any UNIX domain socket, regardless of
1186 * its file system permissions.
1188 if (mkdir(VT_TMPDIR
, S_IRWXU
|S_IROTH
|S_IXOTH
|S_IRGRP
|S_IXGRP
) < 0 &&
1190 syslog(LOG_ERR
, "could not mkdir '%s'", VT_TMPDIR
);
1194 if ((stat(VT_TMPDIR
, &st
) < 0) || !S_ISDIR(st
.st_mode
)) {
1195 syslog(LOG_ERR
, "'%s' is not a directory", VT_TMPDIR
);
1198 (void) chmod(VT_TMPDIR
, S_IRWXU
|S_IROTH
|S_IXOTH
|S_IRGRP
|S_IXGRP
);
1203 main(int argc
, char *argv
[])
1207 priv_set_t
*privset
;
1210 openlog("vtdaemon", LOG_PID
| LOG_CONS
, 0);
1213 * Check that we have all privileges. It would be nice to pare
1214 * this down, but this is at least a first cut.
1216 if ((privset
= priv_allocset()) == NULL
) {
1217 syslog(LOG_ERR
, "priv_allocset failed");
1221 if (getppriv(PRIV_EFFECTIVE
, privset
) != 0) {
1222 syslog(LOG_ERR
, "getppriv failed", "getppriv");
1223 priv_freeset(privset
);
1227 if (priv_isfullset(privset
) == B_FALSE
) {
1228 syslog(LOG_ERR
, "You lack sufficient privilege "
1229 "to run this command (all privs required)");
1230 priv_freeset(privset
);
1233 priv_freeset(privset
);
1235 while ((opt
= getopt(argc
, argv
, "ksrc:")) != EOF
) {
1238 vt_hotkeys
= B_FALSE
;
1241 vt_secure
= B_FALSE
;
1244 vtnodecount
= atoi(optarg
);
1251 (void) vt_setup_signal(SIGINT
, 1);
1256 if (!eventstream_init())
1259 (void) snprintf(vt_door_path
, sizeof (vt_door_path
),
1260 VT_TMPDIR
"/vtdaemon_door");
1262 if (!make_daemon_exclusive())
1265 /* only the main thread accepts SIGINT */
1266 (void) vt_setup_signal(SIGINT
, 0);
1267 (void) sigset(SIGPIPE
, SIG_IGN
);
1268 (void) signal(SIGQUIT
, SIG_IGN
);
1269 (void) signal(SIGINT
, catch);
1271 for (i
= 0; i
< 3; i
++)
1275 if ((daemonfd
= open(VT_DAEMON_CONSOLE_FILE
, O_RDWR
)) < 0) {
1280 (void) dup2(daemonfd
, STDIN_FILENO
);
1282 (void) dup2(daemonfd
, STDOUT_FILENO
);
1284 if (vtnodecount
>= 2)
1285 (void) ioctl(daemonfd
, VT_CONFIG
, vtnodecount
);
1287 if ((vt_ah_array
= calloc(vtnodecount
- 1,
1288 sizeof (adt_session_data_t
*))) == NULL
)
1291 (void) ioctl(daemonfd
, VT_GETACTIVE
, &active
);
1295 * This is for someone who restarts vtdaemon while vtdaemon
1296 * is doing authentication on /dev/vt/1.
1297 * A better way is to continue the authentication, but there
1298 * are chances that the status of the target VT has changed.
1299 * So we just clear the screen here.
1301 (void) write(daemonfd
, VT_CLEAR_SCREEN_STR
,
1302 strlen(VT_CLEAR_SCREEN_STR
));
1310 vt_audit_start(adt_session_data_t
**ah
, pid_t pid
)
1314 if (adt_start_session(ah
, NULL
, 0))
1317 if ((uc
= ucred_get(pid
)) == NULL
) {
1318 (void) adt_end_session(*ah
);
1322 if (adt_set_from_ucred(*ah
, uc
, ADT_NEW
)) {
1324 (void) adt_end_session(*ah
);
1336 vt_audit_event(adt_session_data_t
*ah
, au_event_t event_id
, int status
)
1338 adt_event_data_t
*event
;
1341 if ((event
= adt_alloc_event(ah
, event_id
)) == NULL
) {
1345 (void) adt_put_event(event
,
1346 status
== PAM_SUCCESS
? ADT_SUCCESS
: ADT_FAILURE
,
1347 status
== PAM_SUCCESS
? ADT_SUCCESS
: ADT_FAIL_PAM
+ status
);
1349 adt_free_event(event
);
1353 vt_check_source_audit(void)
1358 struct vt_stat state
;
1360 adt_session_data_t
*ah
;
1362 if ((fd
= open(VT_DAEMON_CONSOLE_FILE
, O_WRONLY
)) < 0)
1365 if (ioctl(fd
, VT_GETSTATE
, &state
) != 0 ||
1366 ioctl(fd
, VT_GETACTIVE
, &real_vt
) != 0) {
1371 source_vt
= state
.v_active
; /* 1..n */
1374 /* check if it's already locked */
1375 if (real_vt
== 1) /* vtdaemon is taking over the screen */
1378 vt_read_utx(source_vt
, &pid
, NULL
);
1379 if (pid
== (pid_t
)-1)
1382 if (vt_audit_start(&ah
, pid
) != 0) {
1383 syslog(LOG_ERR
, "audit start failed ");
1388 * In case the previous session terminated abnormally.
1390 if (vt_ah_array
[source_vt
- 1] != NULL
)
1391 (void) adt_end_session(vt_ah_array
[source_vt
- 1]);
1393 vt_ah_array
[source_vt
- 1] = ah
;
1395 vt_audit_event(ah
, ADT_screenlock
, PAM_SUCCESS
);