vlock.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. /* vi: set sw=4 ts=4: */
  2. /*
  3. * vlock implementation for busybox
  4. *
  5. * Copyright (C) 2000 by spoon <spoon@ix.netcom.com>
  6. * Written by spoon <spon@ix.netcom.com>
  7. *
  8. * Licensed under GPLv2 or later, see file LICENSE in this source tree.
  9. */
  10. /* Shoutz to Michael K. Johnson <johnsonm@redhat.com>, author of the
  11. * original vlock. I snagged a bunch of his code to write this
  12. * minimalistic vlock.
  13. */
  14. /* Fixed by Erik Andersen to do passwords the tinylogin way...
  15. * It now works with md5, sha1, etc passwords.
  16. */
  17. //config:config VLOCK
  18. //config: bool "vlock"
  19. //config: default y
  20. //config: help
  21. //config: Build the "vlock" applet which allows you to lock (virtual) terminals.
  22. //config:
  23. //config: Note that Busybox binary must be setuid root for this applet to
  24. //config: work properly.
  25. //applet:/* Needs to be run by root or be suid root - needs to change uid and gid: */
  26. //applet:IF_VLOCK(APPLET(vlock, BB_DIR_USR_BIN, BB_SUID_REQUIRE))
  27. //kbuild:lib-$(CONFIG_VLOCK) += vlock.o
  28. //usage:#define vlock_trivial_usage
  29. //usage: "[-a]"
  30. //usage:#define vlock_full_usage "\n\n"
  31. //usage: "Lock a virtual terminal. A password is required to unlock.\n"
  32. //usage: "\n -a Lock all VTs"
  33. #include "libbb.h"
  34. #ifdef __linux__
  35. #include <sys/vt.h>
  36. static void release_vt(int signo UNUSED_PARAM)
  37. {
  38. /* If -a, param is 0, which means:
  39. * "no, kernel, we don't allow console switch away from us!" */
  40. ioctl(STDIN_FILENO, VT_RELDISP, (unsigned long) !option_mask32);
  41. }
  42. static void acquire_vt(int signo UNUSED_PARAM)
  43. {
  44. /* ACK to kernel that switch to console is successful */
  45. ioctl(STDIN_FILENO, VT_RELDISP, VT_ACKACQ);
  46. }
  47. #endif
  48. int vlock_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
  49. int vlock_main(int argc UNUSED_PARAM, char **argv)
  50. {
  51. #ifdef __linux__
  52. struct vt_mode vtm;
  53. struct vt_mode ovtm;
  54. #endif
  55. struct termios term;
  56. struct termios oterm;
  57. struct passwd *pw;
  58. pw = xgetpwuid(getuid());
  59. opt_complementary = "=0"; /* no params! */
  60. getopt32(argv, "a");
  61. /* Ignore some signals so that we don't get killed by them */
  62. bb_signals(0
  63. + (1 << SIGTSTP)
  64. + (1 << SIGTTIN)
  65. + (1 << SIGTTOU)
  66. + (1 << SIGHUP )
  67. + (1 << SIGCHLD) /* paranoia :) */
  68. + (1 << SIGQUIT)
  69. + (1 << SIGINT )
  70. , SIG_IGN);
  71. #ifdef __linux__
  72. /* We will use SIGUSRx for console switch control: */
  73. /* 1: set handlers */
  74. signal_SA_RESTART_empty_mask(SIGUSR1, release_vt);
  75. signal_SA_RESTART_empty_mask(SIGUSR2, acquire_vt);
  76. /* 2: unmask them */
  77. sig_unblock(SIGUSR1);
  78. sig_unblock(SIGUSR2);
  79. #endif
  80. /* Revert stdin/out to our controlling tty
  81. * (or die if we have none) */
  82. xmove_fd(xopen(CURRENT_TTY, O_RDWR), STDIN_FILENO);
  83. xdup2(STDIN_FILENO, STDOUT_FILENO);
  84. #ifdef __linux__
  85. xioctl(STDIN_FILENO, VT_GETMODE, &vtm);
  86. ovtm = vtm;
  87. /* "console switches are controlled by us, not kernel!" */
  88. vtm.mode = VT_PROCESS;
  89. vtm.relsig = SIGUSR1;
  90. vtm.acqsig = SIGUSR2;
  91. ioctl(STDIN_FILENO, VT_SETMODE, &vtm);
  92. #endif
  93. tcgetattr(STDIN_FILENO, &oterm);
  94. term = oterm;
  95. term.c_iflag &= ~BRKINT;
  96. term.c_iflag |= IGNBRK;
  97. term.c_lflag &= ~ISIG;
  98. term.c_lflag &= ~(ECHO | ECHOCTL);
  99. tcsetattr_stdin_TCSANOW(&term);
  100. while (1) {
  101. printf("Virtual console%s locked by %s.\n",
  102. /* "s" if -a, else "": */ "s" + !option_mask32,
  103. pw->pw_name
  104. );
  105. if (ask_and_check_password(pw) > 0) {
  106. break;
  107. }
  108. bb_do_delay(LOGIN_FAIL_DELAY);
  109. puts("Incorrect password");
  110. }
  111. #ifdef __linux__
  112. ioctl(STDIN_FILENO, VT_SETMODE, &ovtm);
  113. #endif
  114. tcsetattr_stdin_TCSANOW(&oterm);
  115. fflush_stdout_and_exit(EXIT_SUCCESS);
  116. }