vlock.c 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  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. * This program is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation; either version 2 of the License, or
  11. * (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  16. * General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program; if not, write to the Free Software
  20. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  21. *
  22. */
  23. /* Shoutz to Michael K. Johnson <johnsonm@redhat.com>, author of the
  24. * original vlock. I snagged a bunch of his code to write this
  25. * minimalistic vlock.
  26. */
  27. /* Fixed by Erik Andersen to do passwords the tinylogin way...
  28. * It now works with md5, sha1, etc passwords. */
  29. #include <stdio.h>
  30. #include <stdlib.h>
  31. #include <sys/vt.h>
  32. #include <signal.h>
  33. #include <string.h>
  34. #include <unistd.h>
  35. #include <fcntl.h>
  36. #include <errno.h>
  37. #include <sys/ioctl.h>
  38. #include <termios.h>
  39. #include "busybox.h"
  40. static struct passwd *pw;
  41. static struct vt_mode ovtm;
  42. static struct termios oterm;
  43. static int vfd;
  44. static int o_lock_all = 0;
  45. #ifdef CONFIG_FEATURE_SHADOWPASSWDS
  46. static struct spwd *spw;
  47. /* getspuid - get a shadow entry by uid */
  48. static struct spwd *getspuid(uid_t uid)
  49. {
  50. struct spwd *sp;
  51. struct passwd *mypw;
  52. if ((mypw = getpwuid(getuid())) == NULL) {
  53. return (NULL);
  54. }
  55. setspent();
  56. while ((sp = getspent()) != NULL) {
  57. if (strcmp(mypw->pw_name, sp->sp_namp) == 0)
  58. break;
  59. }
  60. endspent();
  61. return (sp);
  62. }
  63. #endif
  64. static void release_vt(int signo)
  65. {
  66. if (!o_lock_all)
  67. ioctl(vfd, VT_RELDISP, 1);
  68. else
  69. ioctl(vfd, VT_RELDISP, 0);
  70. }
  71. static void acquire_vt(int signo)
  72. {
  73. ioctl(vfd, VT_RELDISP, VT_ACKACQ);
  74. }
  75. static void restore_terminal(void)
  76. {
  77. ioctl(vfd, VT_SETMODE, &ovtm);
  78. tcsetattr(STDIN_FILENO, TCSANOW, &oterm);
  79. }
  80. extern int vlock_main(int argc, char **argv)
  81. {
  82. sigset_t sig;
  83. struct sigaction sa;
  84. struct vt_mode vtm;
  85. int times = 0;
  86. struct termios term;
  87. if (argc > 2) {
  88. bb_show_usage();
  89. }
  90. if (argc == 2) {
  91. if (strncmp(argv[1], "-a", 2)) {
  92. bb_show_usage();
  93. } else {
  94. o_lock_all = 1;
  95. }
  96. }
  97. if ((pw = getpwuid(getuid())) == NULL) {
  98. bb_error_msg_and_die("no password for uid %d\n", getuid());
  99. }
  100. #ifdef CONFIG_FEATURE_SHADOWPASSWDS
  101. if ((strcmp(pw->pw_passwd, "x") == 0)
  102. || (strcmp(pw->pw_passwd, "*") == 0)) {
  103. if ((spw = getspuid(getuid())) == NULL) {
  104. bb_error_msg_and_die("could not read shadow password for uid %d: %s\n",
  105. getuid(), strerror(errno));
  106. }
  107. if (spw->sp_pwdp) {
  108. pw->pw_passwd = spw->sp_pwdp;
  109. }
  110. }
  111. #endif /* CONFIG_FEATURE_SHADOWPASSWDS */
  112. if (pw->pw_passwd[0] == '!' || pw->pw_passwd[0] == '*') {
  113. bb_error_msg_and_die("Account disabled for uid %d\n", getuid());
  114. }
  115. /* we no longer need root privs */
  116. setuid(getuid());
  117. setgid(getgid());
  118. if ((vfd = open("/dev/tty", O_RDWR)) < 0) {
  119. bb_error_msg_and_die("/dev/tty");
  120. };
  121. if (ioctl(vfd, VT_GETMODE, &vtm) < 0) {
  122. bb_error_msg_and_die("/dev/tty");
  123. };
  124. /* mask a bunch of signals */
  125. sigprocmask(SIG_SETMASK, NULL, &sig);
  126. sigdelset(&sig, SIGUSR1);
  127. sigdelset(&sig, SIGUSR2);
  128. sigaddset(&sig, SIGTSTP);
  129. sigaddset(&sig, SIGTTIN);
  130. sigaddset(&sig, SIGTTOU);
  131. sigaddset(&sig, SIGHUP);
  132. sigaddset(&sig, SIGCHLD);
  133. sigaddset(&sig, SIGQUIT);
  134. sigaddset(&sig, SIGINT);
  135. sigemptyset(&(sa.sa_mask));
  136. sa.sa_flags = SA_RESTART;
  137. sa.sa_handler = release_vt;
  138. sigaction(SIGUSR1, &sa, NULL);
  139. sa.sa_handler = acquire_vt;
  140. sigaction(SIGUSR2, &sa, NULL);
  141. /* need to handle some signals so that we don't get killed by them */
  142. sa.sa_handler = SIG_IGN;
  143. sigaction(SIGHUP, &sa, NULL);
  144. sigaction(SIGQUIT, &sa, NULL);
  145. sigaction(SIGINT, &sa, NULL);
  146. sigaction(SIGTSTP, &sa, NULL);
  147. ovtm = vtm;
  148. vtm.mode = VT_PROCESS;
  149. vtm.relsig = SIGUSR1;
  150. vtm.acqsig = SIGUSR2;
  151. ioctl(vfd, VT_SETMODE, &vtm);
  152. tcgetattr(STDIN_FILENO, &oterm);
  153. term = oterm;
  154. term.c_iflag &= ~BRKINT;
  155. term.c_iflag |= IGNBRK;
  156. term.c_lflag &= ~ISIG;
  157. term.c_lflag &= ~(ECHO | ECHOCTL);
  158. tcsetattr(STDIN_FILENO, TCSANOW, &term);
  159. do {
  160. char *pass, *crypt_pass;
  161. char prompt[100];
  162. if (o_lock_all) {
  163. printf("All Virtual Consoles locked.\n");
  164. } else {
  165. printf("This Virtual Console locked.\n");
  166. }
  167. fflush(stdout);
  168. snprintf(prompt, 100, "%s's password: ", pw->pw_name);
  169. if ((pass = bb_askpass(0, prompt)) == NULL) {
  170. restore_terminal();
  171. bb_perror_msg_and_die("password");
  172. }
  173. crypt_pass = pw_encrypt(pass, pw->pw_passwd);
  174. if (strncmp(crypt_pass, pw->pw_passwd, sizeof(crypt_pass)) == 0) {
  175. memset(pass, 0, strlen(pass));
  176. memset(crypt_pass, 0, strlen(crypt_pass));
  177. restore_terminal();
  178. return 0;
  179. }
  180. memset(pass, 0, strlen(pass));
  181. memset(crypt_pass, 0, strlen(crypt_pass));
  182. if (isatty(STDIN_FILENO) == 0) {
  183. restore_terminal();
  184. bb_perror_msg_and_die("isatty");
  185. }
  186. sleep(++times);
  187. printf("Password incorrect.\n");
  188. if (times >= 3) {
  189. sleep(15);
  190. times = 2;
  191. }
  192. } while (1);
  193. }
  194. /*
  195. Local Variables:
  196. c-file-style: "linux"
  197. c-basic-offset: 4
  198. tab-width: 4
  199. End:
  200. */