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