vlock.c 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. /*++
  2. Copyright (c) 2015 Minoca Corp. All Rights Reserved
  3. Module Name:
  4. vlock.c
  5. Abstract:
  6. This module implements the vlock command, which locks a terminal until a
  7. password unlocks it.
  8. Author:
  9. Evan Green 12-Mar-2015
  10. Environment:
  11. POSIX
  12. --*/
  13. //
  14. // ------------------------------------------------------------------- Includes
  15. //
  16. #include <minoca/lib/types.h>
  17. #include <assert.h>
  18. #include <errno.h>
  19. #include <getopt.h>
  20. #include <grp.h>
  21. #include <pwd.h>
  22. #include <shadow.h>
  23. #include <signal.h>
  24. #include <stdlib.h>
  25. #include <string.h>
  26. #include <termios.h>
  27. #include <unistd.h>
  28. #include "../swlib.h"
  29. #include "lutil.h"
  30. //
  31. // ---------------------------------------------------------------- Definitions
  32. //
  33. #define VLOCK_VERSION_MAJOR 1
  34. #define VLOCK_VERSION_MINOR 0
  35. #define VLOCK_USAGE \
  36. "usage: vlock\n" \
  37. "The vlock utility locks a terminal, requiring the user's password to \n" \
  38. "unlock it. Options are:\n" \
  39. " --help -- Displays this help text and exits.\n" \
  40. " --version -- Displays the application version and exits.\n"
  41. #define VLOCK_OPTIONS_STRING "HV"
  42. //
  43. // ------------------------------------------------------ Data Type Definitions
  44. //
  45. //
  46. // ----------------------------------------------- Internal Function Prototypes
  47. //
  48. //
  49. // -------------------------------------------------------------------- Globals
  50. //
  51. struct option VlockLongOptions[] = {
  52. {"help", no_argument, 0, 'H'},
  53. {"version", no_argument, 0, 'V'},
  54. {NULL, 0, 0, 0},
  55. };
  56. //
  57. // ------------------------------------------------------------------ Functions
  58. //
  59. INT
  60. VlockMain (
  61. INT ArgumentCount,
  62. CHAR **Arguments
  63. )
  64. /*++
  65. Routine Description:
  66. This routine is the main entry point for the vlock utility.
  67. Arguments:
  68. ArgumentCount - Supplies the number of command line arguments the program
  69. was invoked with.
  70. Arguments - Supplies a tokenized array of command line arguments.
  71. Return Value:
  72. Returns an integer exit code. 0 for success, nonzero otherwise.
  73. --*/
  74. {
  75. ULONG ArgumentIndex;
  76. struct sigaction NewAction;
  77. struct termios NewSettings;
  78. INT Option;
  79. struct termios OriginalSettings;
  80. struct sigaction SaveAlarm;
  81. struct sigaction SaveHup;
  82. struct sigaction SaveInt;
  83. struct sigaction SavePipe;
  84. struct sigaction SaveQuit;
  85. struct sigaction SaveTerm;
  86. struct sigaction SaveTstop;
  87. struct sigaction SaveTtin;
  88. struct sigaction SaveTtou;
  89. int Status;
  90. struct passwd *User;
  91. uid_t UserId;
  92. UserId = getuid();
  93. User = getpwuid(UserId);
  94. if (User == NULL) {
  95. SwPrintError(0,
  96. NULL,
  97. "Cannot get user information for user ID %d.\n",
  98. UserId);
  99. Status = 1;
  100. goto MainEnd;
  101. }
  102. //
  103. // Process the control arguments.
  104. //
  105. while (TRUE) {
  106. Option = getopt_long(ArgumentCount,
  107. Arguments,
  108. VLOCK_OPTIONS_STRING,
  109. VlockLongOptions,
  110. NULL);
  111. if (Option == -1) {
  112. break;
  113. }
  114. if ((Option == '?') || (Option == ':')) {
  115. Status = 1;
  116. goto MainEnd;
  117. }
  118. switch (Option) {
  119. case 'V':
  120. SwPrintVersion(VLOCK_VERSION_MAJOR, VLOCK_VERSION_MINOR);
  121. return 1;
  122. case 'H':
  123. printf(VLOCK_USAGE);
  124. return 1;
  125. default:
  126. assert(FALSE);
  127. Status = 1;
  128. goto MainEnd;
  129. }
  130. }
  131. ArgumentIndex = optind;
  132. if (ArgumentIndex > ArgumentCount) {
  133. ArgumentIndex = ArgumentCount;
  134. }
  135. if (ArgumentIndex != ArgumentCount) {
  136. SwPrintError(0, NULL, "Unexpected argument");
  137. Status = 1;
  138. goto MainEnd;
  139. }
  140. if (SwCheckAccount(User) != 0) {
  141. SwPrintError(0, User->pw_name, "Not locking terminal for account");
  142. Status = 1;
  143. goto MainEnd;
  144. }
  145. //
  146. // Turn off echoing, signals and breaks.
  147. //
  148. if (tcgetattr(STDIN_FILENO, &OriginalSettings) != 0) {
  149. Status = 1;
  150. goto MainEnd;
  151. }
  152. memcpy(&NewSettings, &OriginalSettings, sizeof(struct termios));
  153. NewSettings.c_iflag &= ~(BRKINT | ISIG | ECHO);
  154. NewSettings.c_iflag |= IGNBRK;
  155. if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &NewSettings) != 0) {
  156. Status = 1;
  157. goto MainEnd;
  158. }
  159. //
  160. // Handle all signals so that the terminal settings can be put back.
  161. //
  162. sigemptyset(&(NewAction.sa_mask));
  163. NewAction.sa_flags = 0;
  164. NewAction.sa_handler = SIG_IGN;
  165. sigaction(SIGALRM, &NewAction, &SaveAlarm);
  166. sigaction(SIGHUP, &NewAction, &SaveHup);
  167. sigaction(SIGINT, &NewAction, &SaveInt);
  168. sigaction(SIGPIPE, &NewAction, &SavePipe);
  169. sigaction(SIGQUIT, &NewAction, &SaveQuit);
  170. sigaction(SIGTERM, &NewAction, &SaveTerm);
  171. sigaction(SIGTSTP, &NewAction, &SaveTstop);
  172. sigaction(SIGTTIN, &NewAction, &SaveTtin);
  173. sigaction(SIGTTOU, &NewAction, &SaveTtou);
  174. while (TRUE) {
  175. printf("Console locked by %s.\n", User->pw_name);
  176. Status = SwGetAndCheckPassword(User, NULL);
  177. if (Status == 0) {
  178. break;
  179. }
  180. sleep(LOGIN_FAIL_DELAY);
  181. printf("vlock: Incorrect password.\n");
  182. }
  183. //
  184. // Restore the original terminal settings.
  185. //
  186. tcsetattr(STDIN_FILENO, TCSAFLUSH, &OriginalSettings);
  187. //
  188. // Restore the original signal handlers.
  189. //
  190. sigaction(SIGALRM, &SaveAlarm, NULL);
  191. sigaction(SIGHUP, &SaveHup, NULL);
  192. sigaction(SIGINT, &SaveInt, NULL);
  193. sigaction(SIGPIPE, &SavePipe, NULL);
  194. sigaction(SIGQUIT, &SaveQuit, NULL);
  195. sigaction(SIGTERM, &SaveTerm, NULL);
  196. sigaction(SIGTSTP, &SaveTstop, NULL);
  197. sigaction(SIGTTIN, &SaveTtin, NULL);
  198. sigaction(SIGTTOU, &SaveTtou, NULL);
  199. Status = 0;
  200. MainEnd:
  201. return Status;
  202. }
  203. //
  204. // --------------------------------------------------------- Internal Functions
  205. //