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