1 /* vi: set sw=4 ts=4: */
3 * vlock implementation for busybox
5 * Copyright (C) 2000 by spoon <spoon@ix.netcom.com>
6 * Written by spoon <spon@ix.netcom.com>
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.
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.
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
24 /* Shoutz to Michael K. Johnson <johnsonm@redhat.com>, author of the
25 * original vlock. I snagged a bunch of his code to write this
28 /* Fixed by Erik Andersen to do passwords the tinylogin way...
29 * It now works with md5, sha1, etc passwords. */
38 #include <sys/ioctl.h>
43 static struct passwd *pw;
44 static struct vt_mode ovtm;
45 static struct termios oterm;
47 static int o_lock_all = 0;
49 #ifdef CONFIG_FEATURE_SHADOWPASSWDS
50 static struct spwd *spw;
52 /* getspuid - get a shadow entry by uid */
53 struct spwd *getspuid(uid_t uid)
58 if ((mypw = getpwuid(getuid())) == NULL) {
62 while ((sp = getspent()) != NULL) {
63 if (strcmp(mypw->pw_name, sp->sp_namp) == 0)
71 static void release_vt(int signo)
74 ioctl(vfd, VT_RELDISP, 1);
76 ioctl(vfd, VT_RELDISP, 0);
79 static void acquire_vt(int signo)
81 ioctl(vfd, VT_RELDISP, VT_ACKACQ);
84 static void restore_terminal(void)
86 ioctl(vfd, VT_SETMODE, &ovtm);
87 tcsetattr(STDIN_FILENO, TCSANOW, &oterm);
90 extern int vlock_main(int argc, char **argv)
103 if (strncmp(argv[1], "-a", 2)) {
110 if ((pw = getpwuid(getuid())) == NULL) {
111 error_msg_and_die("no password for uid %d\n", getuid());
113 #ifdef CONFIG_FEATURE_SHADOWPASSWDS
114 if ((strcmp(pw->pw_passwd, "x") == 0)
115 || (strcmp(pw->pw_passwd, "*") == 0)) {
117 if ((spw = getspuid(getuid())) == NULL) {
118 error_msg_and_die("could not read shadow password for uid %d: %s\n",
119 getuid(), strerror(errno));
122 pw->pw_passwd = spw->sp_pwdp;
125 #endif /* CONFIG_FEATURE_SHADOWPASSWDS */
126 if (pw->pw_passwd[0] == '!' || pw->pw_passwd[0] == '*') {
127 error_msg_and_die("Account disabled for uid %d\n", getuid());
130 /* we no longer need root privs */
134 if ((vfd = open("/dev/tty", O_RDWR)) < 0) {
135 error_msg_and_die("/dev/tty");
138 if (ioctl(vfd, VT_GETMODE, &vtm) < 0) {
139 error_msg_and_die("/dev/tty");
142 /* mask a bunch of signals */
143 sigprocmask(SIG_SETMASK, NULL, &sig);
144 sigdelset(&sig, SIGUSR1);
145 sigdelset(&sig, SIGUSR2);
146 sigaddset(&sig, SIGTSTP);
147 sigaddset(&sig, SIGTTIN);
148 sigaddset(&sig, SIGTTOU);
149 sigaddset(&sig, SIGHUP);
150 sigaddset(&sig, SIGCHLD);
151 sigaddset(&sig, SIGQUIT);
152 sigaddset(&sig, SIGINT);
154 sigemptyset(&(sa.sa_mask));
155 sa.sa_flags = SA_RESTART;
156 sa.sa_handler = release_vt;
157 sigaction(SIGUSR1, &sa, NULL);
158 sa.sa_handler = acquire_vt;
159 sigaction(SIGUSR2, &sa, NULL);
161 /* need to handle some signals so that we don't get killed by them */
162 sa.sa_handler = SIG_IGN;
163 sigaction(SIGHUP, &sa, NULL);
164 sigaction(SIGQUIT, &sa, NULL);
165 sigaction(SIGINT, &sa, NULL);
166 sigaction(SIGTSTP, &sa, NULL);
169 vtm.mode = VT_PROCESS;
170 vtm.relsig = SIGUSR1;
171 vtm.acqsig = SIGUSR2;
172 ioctl(vfd, VT_SETMODE, &vtm);
174 tcgetattr(STDIN_FILENO, &oterm);
176 term.c_iflag &= ~BRKINT;
177 term.c_iflag |= IGNBRK;
178 term.c_lflag &= ~ISIG;
179 term.c_lflag &= ~(ECHO | ECHOCTL);
180 tcsetattr(STDIN_FILENO, TCSANOW, &term);
183 char *pass, *crypt_pass;
187 printf("All Virtual Consoles locked.\n");
189 printf("This Virtual Console locked.\n");
193 snprintf(prompt, 100, "%s's password: ", pw->pw_name);
195 if ((pass = getpass(prompt)) == NULL) {
201 crypt_pass = pw_encrypt(pass, pw->pw_passwd);
202 if (strncmp(crypt_pass, pw->pw_passwd, sizeof(crypt_pass)) == 0) {
203 memset(pass, 0, strlen(pass));
204 memset(crypt_pass, 0, strlen(crypt_pass));
208 memset(pass, 0, strlen(pass));
209 memset(crypt_pass, 0, strlen(crypt_pass));
211 if (isatty(STDIN_FILENO) == 0) {
218 printf("Password incorrect.\n");
228 c-file-style: "linux"