aboutsummaryrefslogtreecommitdiff
path: root/loginutils
diff options
context:
space:
mode:
Diffstat (limited to 'loginutils')
-rw-r--r--loginutils/Makefile.in9
-rw-r--r--loginutils/addgroup.c9
-rw-r--r--loginutils/adduser.c56
-rw-r--r--loginutils/config.in17
-rw-r--r--loginutils/deluser.c28
-rw-r--r--loginutils/login.c43
-rw-r--r--loginutils/passwd.c408
-rw-r--r--loginutils/su.c9
-rw-r--r--loginutils/sulogin.c184
-rw-r--r--loginutils/tinylogin.c209
-rw-r--r--loginutils/tinylogin.h10
-rw-r--r--loginutils/vlock.c229
12 files changed, 866 insertions, 345 deletions
diff --git a/loginutils/Makefile.in b/loginutils/Makefile.in
index adee35baa..cb6452c39 100644
--- a/loginutils/Makefile.in
+++ b/loginutils/Makefile.in
@@ -26,9 +26,12 @@ LOGINUTILS-y:=
LOGINUTILS-$(CONFIG_ADDGROUP) += addgroup.o
LOGINUTILS-$(CONFIG_ADDUSER) += adduser.o
LOGINUTILS-$(CONFIG_DELUSER) += deluser.o
-LOGINUTILS-$(CONFIG_GETTY) += getty.o
-LOGINUTILS-$(CONFIG_LOGIN) += login.o tinylogin.o
-LOGINUTILS-$(CONFIG_SU) += su.o tinylogin.o
+LOGINUTILS-$(CONFIG_GETTY) += getty.o
+LOGINUTILS-$(CONFIG_LOGIN) += login.o
+LOGINUTILS-$(CONFIG_PASSWD) += passwd.o
+LOGINUTILS-$(CONFIG_SU) += su.o
+LOGINUTILS-$(CONFIG_SULOGIN) += sulogin.o
+LOGINUTILS-$(CONFIG_VLOCK) += vlock.o
libraries-y+=$(LOGINUTILS_DIR)$(LOGINUTILS_AR)
diff --git a/loginutils/addgroup.c b/loginutils/addgroup.c
index e04a8d784..87e98fb18 100644
--- a/loginutils/addgroup.c
+++ b/loginutils/addgroup.c
@@ -35,9 +35,6 @@
#include "pwd.h"
#include "grp.h"
-#define GROUP_FILE "/etc/group"
-#define SHADOW_FILE "/etc/gshadow"
-
/* structs __________________________ */
@@ -92,7 +89,7 @@ static int addgroup(const char *filename, char *group, gid_t gid)
#ifdef CONFIG_FEATURE_SHADOWPASSWDS
FILE *etc_gshadow;
- char *gshadow = SHADOW_FILE;
+ char *gshadow = shadow_file;
#endif
struct group gr;
@@ -162,7 +159,7 @@ int addgroup_main(int argc, char **argv)
}
/* werk */
- return addgroup(GROUP_FILE, group, gid);
+ return addgroup(group_file, group, gid);
}
-/* $Id: addgroup.c,v 1.1 2002/06/04 20:45:05 sandman Exp $ */
+/* $Id: addgroup.c,v 1.2 2002/06/23 04:24:24 andersen Exp $ */
diff --git a/loginutils/adduser.c b/loginutils/adduser.c
index 66fcaa23f..7aa7fcfd3 100644
--- a/loginutils/adduser.c
+++ b/loginutils/adduser.c
@@ -33,11 +33,7 @@
#include <sys/stat.h>
#include <sys/types.h>
#include "busybox.h"
-#include "pwd.h"
-#include "grp.h"
-#define PASSWD_FILE "/etc/passwd"
-#define SHADOW_FILE "/etc/shadow"
/* structs __________________________ */
@@ -56,9 +52,6 @@ static const char default_home_prefix[] = "/home";
static const char default_shell[] = "/bin/sh";
#ifdef CONFIG_FEATURE_SHADOWPASSWDS
-
-#include "shadow.h"
-
/* shadow in use? */
static int shadow_enabled = 0;
#endif
@@ -138,47 +131,6 @@ static void passwd_wrapper(const char *login)
error_msg_and_die("Failed to execute 'passwd', you must set the password for '%s' manually", login);
}
-#ifdef CONFIG_FEATURE_SHADOWPASSWDS
-/*
- * pwd_to_spwd - create entries for new spwd structure
- *
- * pwd_to_spwd() creates a new (struct spwd) containing the
- * information in the pointed-to (struct passwd).
- */
-#define DAY (24L*3600L)
-#define WEEK (7*DAY)
-#define SCALE DAY
-static struct spwd *pwd_to_spwd(const struct passwd *pw)
-{
- static struct spwd sp;
-
- /*
- * Nice, easy parts first. The name and passwd map directly
- * from the old password structure to the new one.
- */
- sp.sp_namp = pw->pw_name;
- sp.sp_pwdp = pw->pw_passwd;
-
- /*
- * Defaults used if there is no pw_age information.
- */
- sp.sp_min = 0;
- sp.sp_max = (10000L * DAY) / SCALE;
- sp.sp_lstchg = time((time_t *) 0) / SCALE;
-
- /*
- * These fields have no corresponding information in the password
- * file. They are set to uninitialized values.
- */
- sp.sp_warn = -1;
- sp.sp_expire = -1;
- sp.sp_inact = -1;
- sp.sp_flag = -1;
-
- return &sp;
-}
-#endif
-
/* putpwent(3) remix */
static int adduser(const char *filename, struct passwd *p)
{
@@ -222,7 +174,7 @@ static int adduser(const char *filename, struct passwd *p)
#ifdef CONFIG_FEATURE_SHADOWPASSWDS
/* add to shadow if necessary */
if (shadow_enabled) {
- shadow = wfopen(SHADOW_FILE, "a");
+ shadow = wfopen(shadow_file, "a");
if (shadow == NULL) {
/* return -1; */
return 1;
@@ -333,7 +285,7 @@ int adduser_main(int argc, char **argv)
}
#ifdef CONFIG_FEATURE_SHADOWPASSWDS
/* is /etc/shadow in use? */
- shadow_enabled = (0 == access(SHADOW_FILE, F_OK));
+ shadow_enabled = (0 == access(shadow_file, F_OK));
#endif
/* create a passwd struct */
@@ -346,7 +298,7 @@ int adduser_main(int argc, char **argv)
pw.pw_shell = (char *)shell;
/* grand finale */
- return adduser(PASSWD_FILE, &pw);
+ return adduser(passwd_file, &pw);
}
-/* $Id: adduser.c,v 1.1 2002/06/04 20:45:05 sandman Exp $ */
+/* $Id: adduser.c,v 1.2 2002/06/23 04:24:24 andersen Exp $ */
diff --git a/loginutils/config.in b/loginutils/config.in
index 265d45ab4..b3880aa3d 100644
--- a/loginutils/config.in
+++ b/loginutils/config.in
@@ -7,19 +7,22 @@ mainmenu_option next_comment
comment 'Login/Password Management Utilities'
-bool 'addgroup' CONFIG_ADDGROUP
-bool 'adduser' CONFIG_ADDUSER
-bool 'deluser' CONFIG_DELUSER
-bool 'delgroup' CONFIG_DELUSER
-bool 'getty' CONFIG_GETTY
+bool 'addgroup' CONFIG_ADDGROUP
+bool 'adduser' CONFIG_ADDUSER
+bool 'deluser' CONFIG_DELUSER
+bool 'delgroup' CONFIG_DELUSER
+bool 'getty' CONFIG_GETTY
bool 'login' CONFIG_LOGIN
if [ "$CONFIG_LOGIN" = "y" ]; then
bool ' Support for /etc/securetty' CONFIG_FEATURE_SECURETTY
fi
-bool 'su' CONFIG_SU
+bool 'passwd' CONFIG_PASSWD
+bool 'su' CONFIG_SU
if [ "$CONFIG_ADDUSER" = "y" -o "$CONFIG_DELUSER" = "y" -o "$CONFIG_LOGIN" = "y" -o "$CONFIG_SU" = "y" ]; then
- bool 'Support for shadow passwords' CONFIG_FEATURE_SHADOWPASSWDS
+ bool ' Support for shadow passwords' CONFIG_FEATURE_SHADOWPASSWDS
fi
+bool 'sulogin' CONFIG_SULOGIN
+bool 'vlock' CONFIG_VLOCK
endmenu
diff --git a/loginutils/deluser.c b/loginutils/deluser.c
index 481a716e7..c7d6ece64 100644
--- a/loginutils/deluser.c
+++ b/loginutils/deluser.c
@@ -28,10 +28,6 @@
#include <string.h>
#include "busybox.h"
-#define PASSWD_FILE "/etc/passwd"
-#define GROUP_FILE "/etc/group"
-#define SHADOW_FILE "/etc/shadow"
-#define GSHADOW_FILE "/etc/gshadow"
/* where to start and stop deletion */
@@ -123,11 +119,11 @@ int delgroup_main(int argc, char **argv)
show_usage();
} else {
- failure = del_line_matching(argv[1], GROUP_FILE);
+ failure = del_line_matching(argv[1], group_file);
#ifdef CONFIG_FEATURE_SHADOWPASSWDS
- if (access(GSHADOW_FILE, W_OK) == 0) {
+ if (access(gshadow_file, W_OK) == 0) {
/* EDR the |= works if the error is not 0, so he had it wrong */
- failure |= del_line_matching(argv[1], GSHADOW_FILE);
+ failure |= del_line_matching(argv[1], gshadow_file);
}
#endif /* CONFIG_FEATURE_SHADOWPASSWDS */
/* if (!successful) { */
@@ -149,35 +145,35 @@ int deluser_main(int argc, char **argv)
show_usage();
} else {
- failure = del_line_matching(argv[1], PASSWD_FILE);
+ failure = del_line_matching(argv[1], passwd_file);
/* if (!successful) { */
if (failure) {
error_msg_and_die("%s: User could not be removed from %s\n",
- argv[1], PASSWD_FILE);
+ argv[1], passwd_file);
}
#ifdef CONFIG_FEATURE_SHADOWPASSWDS
- failure = del_line_matching(argv[1], SHADOW_FILE);
+ failure = del_line_matching(argv[1], shadow_file);
/* if (!successful) { */
if (failure) {
error_msg_and_die("%s: User could not be removed from %s\n",
- argv[1], SHADOW_FILE);
+ argv[1], shadow_file);
}
- failure = del_line_matching(argv[1], GSHADOW_FILE);
+ failure = del_line_matching(argv[1], gshadow_file);
/* if (!successful) { */
if (failure) {
error_msg_and_die("%s: User could not be removed from %s\n",
- argv[1], GSHADOW_FILE);
+ argv[1], gshadow_file);
}
#endif /* CONFIG_FEATURE_SHADOWPASSWDS */
- failure = del_line_matching(argv[1], GROUP_FILE);
+ failure = del_line_matching(argv[1], group_file);
/* if (!successful) { */
if (failure) {
error_msg_and_die("%s: User could not be removed from %s\n",
- argv[1], GROUP_FILE);
+ argv[1], group_file);
}
}
return (EXIT_SUCCESS);
}
-/* $Id: deluser.c,v 1.1 2002/06/04 20:45:05 sandman Exp $ */
+/* $Id: deluser.c,v 1.2 2002/06/23 04:24:24 andersen Exp $ */
diff --git a/loginutils/login.c b/loginutils/login.c
index 8ccc5bc8a..7687556ba 100644
--- a/loginutils/login.c
+++ b/loginutils/login.c
@@ -14,16 +14,9 @@
#include <sys/types.h>
#include <ctype.h>
#include <time.h>
-#include "busybox.h"
-
-#include "pwd.h"
-#include "grp.h"
-#ifdef CONFIG_FEATURE_SHADOWPASSWDS
-#include "shadow.h"
-#endif
+#include "busybox.h"
-#include "tinylogin.h"
// import from utmp.c
static void checkutmp(int picky);
@@ -35,12 +28,7 @@ extern char *pw_encrypt(const char *clear, const char *salt);
// login defines
#define TIMEOUT 60
-#define FAIL_DELAY 3
#define EMPTY_USERNAME_COUNT 10
-#define MOTD_FILE "/etc/motd"
-#define NOLOGIN_FILE "/etc/nologin"
-#define SECURETTY_FILE "/etc/securetty"
-
#define USERNAME_SIZE 32
/* Stuff global to this file */
@@ -81,7 +69,9 @@ extern int login_main(int argc, char **argv)
int failed;
int count=0;
struct passwd *pw, pw_copy;
-
+#ifdef CONFIG_WHEEL_GROUP
+ struct group *grp;
+#endif
int opt_preserve = 0;
int opt_fflag = 0;
char *opt_host = 0;
@@ -283,11 +273,11 @@ static int login_prompt ( char *buf_name )
static int check_nologin ( int amroot )
{
- if ( access ( NOLOGIN_FILE, F_OK ) == 0 ) {
+ if ( access ( nologin_file, F_OK ) == 0 ) {
FILE *fp;
int c;
- if (( fp = fopen ( NOLOGIN_FILE, "r" ))) {
+ if (( fp = fopen ( nologin_file, "r" ))) {
while (( c = getc ( fp )) != EOF )
putchar (( c == '\n' ) ? '\r' : c );
@@ -312,7 +302,7 @@ static int check_tty ( const char *tty )
int i;
char buf[BUFSIZ];
- if (( fp = fopen ( SECURETTY_FILE, "r" ))) {
+ if (( fp = fopen ( securetty_file, "r" ))) {
while ( fgets ( buf, sizeof( buf ) - 1, fp )) {
for ( i = xstrlen( buf ) - 1; i >= 0; --i ) {
if ( !isspace ( buf[i] ))
@@ -358,7 +348,7 @@ static void motd ( )
FILE *fp;
register int c;
- if (( fp = fopen ( MOTD_FILE, "r" ))) {
+ if (( fp = fopen ( motd_file, "r" ))) {
while (( c = getc ( fp )) != EOF )
putchar ( c );
fclose ( fp );
@@ -429,23 +419,6 @@ static void checkutmp(int picky)
}
}
-#if __GNU_LIBRARY__ < 5
-/*
- * Some systems already have updwtmp() and possibly updwtmpx(). Others
- * don't, so we re-implement these functions if necessary. --marekm
- */
-static void updwtmp(const char *filename, const struct utmp *ut)
-{
- int fd;
-
- fd = open(filename, O_APPEND | O_WRONLY, 0);
- if (fd >= 0) {
- write(fd, (const char *) ut, sizeof(*ut));
- close(fd);
- }
-}
-#endif
-
/*
* setutmp - put a USER_PROCESS entry in the utmp file
*
diff --git a/loginutils/passwd.c b/loginutils/passwd.c
new file mode 100644
index 000000000..9c84c167c
--- /dev/null
+++ b/loginutils/passwd.c
@@ -0,0 +1,408 @@
+/* vi: set sw=4 ts=4: */
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <signal.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <utime.h>
+#include <syslog.h>
+#include <time.h>
+#include <sys/resource.h>
+#include <errno.h>
+
+#include "busybox.h"
+
+static char crypt_passwd[128];
+
+static int create_backup(const char *backup, FILE * fp);
+static int new_password(const struct passwd *pw, int amroot, int algo);
+static void set_filesize_limit(int blocks);
+
+
+int get_algo(char *a)
+{
+ int x = 0; /* standart: DES */
+
+ if (strcasecmp(a, "md5") == 0)
+ x = 1;
+ return x;
+}
+
+
+extern int update_passwd(const struct passwd *pw, char *crypt_pw)
+{
+ char filename[1024];
+ char buf[1025];
+ char buffer[80];
+ char username[32];
+ char *pw_rest;
+ int has_shadow = 0;
+ int mask;
+ int continued;
+ FILE *fp;
+ FILE *out_fp;
+ struct stat sb;
+ struct flock lock;
+
+ if (access(shadow_file, F_OK) == 0) {
+ has_shadow = 1;
+ }
+ if (has_shadow) {
+ snprintf(filename, sizeof filename, "%s", shadow_file);
+ } else {
+ snprintf(filename, sizeof filename, "%s", passwd_file);
+ }
+
+ if (((fp = fopen(filename, "r+")) == 0) || (fstat(fileno(fp), &sb))) {
+ /* return 0; */
+ return 1;
+ }
+
+ /* Lock the password file before updating */
+ lock.l_type = F_WRLCK;
+ lock.l_whence = SEEK_SET;
+ lock.l_start = 0;
+ lock.l_len = 0;
+ if (fcntl(fileno(fp), F_SETLK, &lock) < 0) {
+ fprintf(stderr, "%s: %s\n", filename, strerror(errno));
+ return 1;
+ }
+ lock.l_type = F_UNLCK;
+
+ snprintf(buf, sizeof buf, "%s-", filename);
+ if (create_backup(buf, fp)) {
+ fcntl(fileno(fp), F_SETLK, &lock);
+ fclose(fp);
+ return 1;
+ }
+ snprintf(buf, sizeof buf, "%s+", filename);
+ mask = umask(0777);
+ out_fp = fopen(buf, "w");
+ umask(mask);
+ if ((!out_fp) || (fchmod(fileno(out_fp), sb.st_mode & 0777))
+ || (fchown(fileno(out_fp), sb.st_uid, sb.st_gid))) {
+ fcntl(fileno(fp), F_SETLK, &lock);
+ fclose(fp);
+ fclose(out_fp);
+ return 1;
+ }
+
+ continued = 0;
+ snprintf(username, sizeof username, "%s:", pw->pw_name);
+ rewind(fp);
+ while (!feof(fp)) {
+ fgets(buffer, sizeof buffer, fp);
+ if (!continued) { // Check to see if we're updating this line.
+ if (strncmp(username, buffer, strlen(username)) == 0) { // we have a match.
+ pw_rest = strchr(buffer, ':');
+ *pw_rest++ = '\0';
+ pw_rest = strchr(pw_rest, ':');
+ fprintf(out_fp, "%s:%s%s", buffer, crypt_pw, pw_rest);
+ } else {
+ fputs(buffer, out_fp);
+ }
+ } else {
+ fputs(buffer, out_fp);
+ }
+ if (buffer[strlen(buffer) - 1] == '\n') {
+ continued = 0;
+ } else {
+ continued = 1;
+ }
+ bzero(buffer, sizeof buffer);
+ }
+
+ if (fflush(out_fp) || fsync(fileno(out_fp)) || fclose(out_fp)) {
+ unlink(buf);
+ fcntl(fileno(fp), F_SETLK, &lock);
+ fclose(fp);
+ return 1;
+ }
+ if (rename(buf, filename) < 0) {
+ fcntl(fileno(fp), F_SETLK, &lock);
+ fclose(fp);
+ return 1;
+ } else {
+ fcntl(fileno(fp), F_SETLK, &lock);
+ fclose(fp);
+ return 0;
+ }
+}
+
+
+extern int passwd_main(int argc, char **argv)
+{
+ int amroot;
+ char *cp;
+ char *np;
+ char *name;
+ char *myname;
+ int flag;
+ int algo = 0; /* -a - password algorithm */
+ int lflg = 0; /* -l - lock account */
+ int uflg = 0; /* -u - unlock account */
+ int dflg = 0; /* -d - delete password */
+ const struct passwd *pw;
+ unsigned short ruid;
+
+#ifdef CONFIG_FEATURE_SHADOWPASSWDS
+ const struct spwd *sp;
+#endif /* CONFIG_FEATURE_SHADOWPASSWDS */
+ amroot = (getuid() == 0);
+ openlog("passwd", LOG_PID | LOG_CONS | LOG_NOWAIT, LOG_AUTH);
+ while ((flag = getopt(argc, argv, "a:dlu")) != EOF) {
+ switch (flag) {
+ case 'a':
+ algo = get_algo(optarg);
+ break;
+ case 'd':
+ dflg++;
+ break;
+ case 'l':
+ lflg++;
+ break;
+ case 'u':
+ uflg++;
+ break;
+ default:
+ show_usage();
+ }
+ }
+ ruid = getuid();
+ pw = (struct passwd *) getpwuid(ruid);
+ if (!pw) {
+ error_msg_and_die("Cannot determine your user name.\n");
+ }
+ myname = (char *) xstrdup(pw->pw_name);
+ if (optind < argc) {
+ name = argv[optind];
+ } else {
+ name = myname;
+ }
+ if ((lflg || uflg || dflg) && (optind >= argc || !amroot)) {
+ show_usage();
+ }
+ pw = getpwnam(name);
+ if (!pw) {
+ error_msg_and_die("Unknown user %s\n", name);
+ }
+ if (!amroot && pw->pw_uid != getuid()) {
+ syslog(LOG_WARNING, "can't change pwd for `%s'", name);
+ error_msg_and_die("Permission denied.\n");
+ }
+#ifdef CONFIG_FEATURE_SHADOWPASSWDS
+ sp = getspnam(name);
+ if (!sp) {
+ sp = (struct spwd *) pwd_to_spwd(pw);
+ }
+ cp = sp->sp_pwdp;
+ np = sp->sp_namp;
+#else
+ cp = pw->pw_passwd;
+ np = name;
+#endif /* CONFIG_FEATURE_SHADOWPASSWDS */
+
+ safe_strncpy(crypt_passwd, cp, sizeof(crypt_passwd));
+ if (!(dflg || lflg || uflg)) {
+ if (!amroot) {
+ if (cp[0] == '!') {
+ syslog(LOG_WARNING, "password locked for `%s'", np);
+ error_msg_and_die( "The password for `%s' cannot be changed.\n", np);
+ }
+ }
+ printf("Changing password for %s\n", name);
+ if (new_password(pw, amroot, algo)) {
+ error_msg_and_die( "The password for %s is unchanged.\n", name);
+ }
+ } else if (lflg) {
+ if (crypt_passwd[0] != '!') {
+ memmove(&crypt_passwd[1], crypt_passwd,
+ sizeof crypt_passwd - 1);
+ crypt_passwd[sizeof crypt_passwd - 1] = '\0';
+ crypt_passwd[0] = '!';
+ }
+ } else if (uflg) {
+ if (crypt_passwd[0] == '!') {
+ memmove(crypt_passwd, &crypt_passwd[1],
+ sizeof crypt_passwd - 1);
+ }
+ } else if (dflg) {
+ crypt_passwd[0] = '\0';
+ }
+ set_filesize_limit(30000);
+ signal(SIGHUP, SIG_IGN);
+ signal(SIGINT, SIG_IGN);
+ signal(SIGQUIT, SIG_IGN);
+ umask(077);
+ if (setuid(0)) {
+ syslog(LOG_ERR, "can't setuid(0)");
+ error_msg_and_die( "Cannot change ID to root.\n");
+ }
+ if (!update_passwd(pw, crypt_passwd)) {
+ syslog(LOG_INFO, "password for `%s' changed by user `%s'", name,
+ myname);
+ printf("Password changed.\n");
+ } else {
+ syslog(LOG_WARNING,
+ "an error occurred updating the password file");
+ error_msg_and_die("An error occurred updating the password file.\n");
+ }
+ return (0);
+}
+
+
+
+static int create_backup(const char *backup, FILE * fp)
+{
+ struct stat sb;
+ struct utimbuf ub;
+ FILE *bkfp;
+ int c, mask;
+
+ if (fstat(fileno(fp), &sb))
+ /* return -1; */
+ return 1;
+
+ mask = umask(077);
+ bkfp = fopen(backup, "w");
+ umask(mask);
+ if (!bkfp)
+ /* return -1; */
+ return 1;
+
+ /* TODO: faster copy, not one-char-at-a-time. --marekm */
+ rewind(fp);
+ while ((c = getc(fp)) != EOF) {
+ if (putc(c, bkfp) == EOF)
+ break;
+ }
+ if (c != EOF || fflush(bkfp)) {
+ fclose(bkfp);
+ /* return -1; */
+ return 1;
+ }
+ if (fclose(bkfp))
+ /* return -1; */
+ return 1;
+
+ ub.actime = sb.st_atime;
+ ub.modtime = sb.st_mtime;
+ utime(backup, &ub);
+ return 0;
+}
+
+static int i64c(int i)
+{
+ if (i <= 0)
+ return ('.');
+ if (i == 1)
+ return ('/');
+ if (i >= 2 && i < 12)
+ return ('0' - 2 + i);
+ if (i >= 12 && i < 38)
+ return ('A' - 12 + i);
+ if (i >= 38 && i < 63)
+ return ('a' - 38 + i);
+ return ('z');
+}
+
+static char *crypt_make_salt(void)
+{
+ time_t now;
+ static unsigned long x;
+ static char result[3];
+
+ time(&now);
+ x += now + getpid() + clock();
+ result[0] = i64c(((x >> 18) ^ (x >> 6)) & 077);
+ result[1] = i64c(((x >> 12) ^ x) & 077);
+ result[2] = '\0';
+ return result;
+}
+
+
+static int new_password(const struct passwd *pw, int amroot, int algo)
+{
+ char *clear;
+ char *cipher;
+ char *cp;
+ char orig[200];
+ char pass[200];
+ time_t start, now;
+
+ if (!amroot && crypt_passwd[0]) {
+ if (!(clear = getpass("Old password:"))) {
+ /* return -1; */
+ return 1;
+ }
+ cipher = pw_encrypt(clear, crypt_passwd);
+ if (strcmp(cipher, crypt_passwd) != 0) {
+ syslog(LOG_WARNING, "incorrect password for `%s'",
+ pw->pw_name);
+ time(&start);
+ now = start;
+ while (difftime(now, start) < FAIL_DELAY) {
+ sleep(FAIL_DELAY);
+ time(&now);
+ }
+ fprintf(stderr, "Incorrect password.\n");
+ /* return -1; */
+ return 1;
+ }
+ safe_strncpy(orig, clear, sizeof(orig));
+ bzero(clear, strlen(clear));
+ bzero(cipher, strlen(cipher));
+ } else {
+ orig[0] = '\0';
+ }
+ if (!
+ (cp =
+ getpass ("Enter the new password (minimum of 5, maximum of 8 characters)\n""
+ Please use a combination of upper and lower case letters and numbers.\nEnter new password: ")))
+ {
+ bzero(orig, sizeof orig);
+ /* return -1; */
+ return 1;
+ }
+ safe_strncpy(pass, cp, sizeof(pass));
+ bzero(cp, strlen(cp));
+ /* if (!obscure(orig, pass, pw)) { */
+ if (obscure(orig, pass, pw)) {
+ if (amroot) {
+ printf("\nWarning: weak password (continuing).\n");
+ } else {
+ /* return -1; */
+ return 1;
+ }
+ }
+ if (!(cp = getpass("Re-enter new password: "))) {
+ bzero(orig, sizeof orig);
+ /* return -1; */
+ return 1;
+ }
+ if (strcmp(cp, pass)) {
+ fprintf(stderr, "Passwords do not match.\n");
+ /* return -1; */
+ return 1;
+ }
+ bzero(cp, strlen(cp));
+ bzero(orig, sizeof(orig));
+
+ if (algo == 1) {
+ cp = pw_encrypt(pass, "$1$");
+ } else
+ cp = pw_encrypt(pass, crypt_make_salt());
+ bzero(pass, sizeof pass);
+ safe_strncpy(crypt_passwd, cp, sizeof(crypt_passwd));
+ return 0;
+}
+
+static void set_filesize_limit(int blocks)
+{
+ struct rlimit rlimit_fsize;
+
+ rlimit_fsize.rlim_cur = rlimit_fsize.rlim_max = 512L * blocks;
+ setrlimit(RLIMIT_FSIZE, &rlimit_fsize);
+}
diff --git a/loginutils/su.c b/loginutils/su.c
index 33e62e837..6d427262e 100644
--- a/loginutils/su.c
+++ b/loginutils/su.c
@@ -1,7 +1,5 @@
/* vi: set sw=4 ts=4: */
-#include "busybox.h"
-
#include <fcntl.h>
#include <signal.h>
#include <stdio.h>
@@ -18,10 +16,7 @@
#include <ctype.h>
#include <time.h>
-#include "pwd.h"
-#include "grp.h"
-
-#include "tinylogin.h"
+#include "busybox.h"
@@ -161,7 +156,7 @@ int su_main ( int argc, char **argv )
change_identity ( pw );
setup_environment ( opt_shell, opt_loginshell, !opt_preserve, pw );
- run_shell ( opt_shell, opt_loginshell, opt_command, opt_args );
+ run_shell ( opt_shell, opt_loginshell, opt_command, (const char**)opt_args );
return EXIT_FAILURE;
}
diff --git a/loginutils/sulogin.c b/loginutils/sulogin.c
new file mode 100644
index 000000000..a654ffb89
--- /dev/null
+++ b/loginutils/sulogin.c
@@ -0,0 +1,184 @@
+/* vi: set sw=4 ts=4: */
+#include <fcntl.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include <termios.h>
+#include <unistd.h>
+#include <utmp.h>
+#include <sys/resource.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <ctype.h>
+#include <time.h>
+
+#include "busybox.h"
+
+
+// sulogin defines
+#define SULOGIN_PROMPT "\nGive root password for system maintenance\n" \
+ "(or type Control-D for normal startup):"
+
+static const char *forbid[] = {
+ "ENV",
+ "BASH_ENV",
+ "HOME",
+ "IFS",
+ "PATH",
+ "SHELL",
+ "LD_LIBRARY_PATH",
+ "LD_PRELOAD",
+ "LD_TRACE_LOADED_OBJECTS",
+ "LD_BIND_NOW",
+ "LD_AOUT_LIBRARY_PATH",
+ "LD_AOUT_PRELOAD",
+ "LD_NOWARN",
+ "LD_KEEPDIR",
+ (char *) 0
+};
+
+
+
+static void catchalarm(int junk)
+{
+ exit(EXIT_FAILURE);
+}
+
+
+extern int sulogin_main(int argc, char **argv)
+{
+ char *cp;
+ char *device = (char *) 0;
+ const char *name = "root";
+ int timeout = 0;
+ static char pass[BUFSIZ];
+ struct termios termio;
+ struct passwd pwent;
+ struct passwd *pwd;
+ time_t start, now;
+ const char **p;
+#ifdef CONFIG_FEATURE_SHADOWPASSWDS
+ struct spwd *spwd = NULL;
+#endif /* CONFIG_FEATURE_SHADOWPASSWDS */
+
+ tcgetattr(0, &termio);
+ /* set control chars */
+ termio.c_cc[VINTR] = 3; /* C-c */
+ termio.c_cc[VQUIT] = 28; /* C-\ */
+ termio.c_cc[VERASE] = 127; /* C-? */
+ termio.c_cc[VKILL] = 21; /* C-u */
+ termio.c_cc[VEOF] = 4; /* C-d */
+ termio.c_cc[VSTART] = 17; /* C-q */
+ termio.c_cc[VSTOP] = 19; /* C-s */
+ termio.c_cc[VSUSP] = 26; /* C-z */
+ /* use line dicipline 0 */
+ termio.c_line = 0;
+ /* Make it be sane */
+ termio.c_cflag &= CBAUD|CBAUDEX|CSIZE|CSTOPB|PARENB|PARODD;
+ termio.c_cflag |= CREAD|HUPCL|CLOCAL;
+ /* input modes */
+ termio.c_iflag = ICRNL | IXON | IXOFF;
+ /* output modes */
+ termio.c_oflag = OPOST | ONLCR;
+ /* local modes */
+ termio.c_lflag = ISIG | ICANON | ECHO | ECHOE | ECHOK | ECHOCTL | ECHOKE | IEXTEN;
+ tcsetattr(0, TCSANOW, &termio);
+ openlog("sulogin", LOG_PID | LOG_CONS | LOG_NOWAIT, LOG_AUTH);
+ if (argc > 1) {
+ if (strncmp(argv[1], "-t", 2) == 0) {
+ if (strcmp(argv[1], "-t") == 0) {
+ if (argc > 2) {
+ timeout = atoi(argv[2]);
+ if (argc > 3) {
+ device = argv[3];
+ }
+ }
+ } else {
+ if (argc > 2) {
+ device = argv[2];
+ }
+ }
+ } else {
+ device = argv[1];
+ }
+ if (device) {
+ close(0);
+ close(1);
+ close(2);
+ if (open(device, O_RDWR) >= 0) {
+ dup(0);
+ dup(0);
+ } else {
+ syslog(LOG_WARNING, "cannot open %s\n", device);
+ exit(EXIT_FAILURE);
+ }
+ }
+ }
+ if (access(passwd_file, 0) == -1) {
+ syslog(LOG_WARNING, "No password file\n");
+ error_msg_and_die("No password file\n");
+ }
+ if (!isatty(0) || !isatty(1) || !isatty(2)) {
+ exit(EXIT_FAILURE);
+ }
+
+
+ /* Clear out anything dangerous from the environment */
+ for (p = forbid; *p; p++)
+ unsetenv(*p);
+
+
+ signal(SIGALRM, catchalarm);
+ alarm(timeout);
+ if (!(pwd = getpwnam(name))) {
+ syslog(LOG_WARNING, "No password entry for `root'\n");
+ error_msg_and_die("No password entry for `root'\n");
+ }
+ pwent = *pwd;
+#ifdef CONFIG_FEATURE_SHADOWPASSWDS
+ spwd = NULL;
+ if (pwd && ((strcmp(pwd->pw_passwd, "x") == 0)
+ || (strcmp(pwd->pw_passwd, "*") == 0))) {
+ endspent();
+ spwd = getspnam(name);
+ if (spwd) {
+ pwent.pw_passwd = spwd->sp_pwdp;
+ }
+ }
+#endif /* CONFIG_FEATURE_SHADOWPASSWDS */
+ while (1) {
+ cp = getpass(SULOGIN_PROMPT);
+ if (!cp || !*cp) {
+ puts("\n");
+ fflush(stdout);
+ syslog(LOG_INFO, "Normal startup\n");
+ exit(EXIT_SUCCESS);
+ } else {
+ safe_strncpy(pass, cp, sizeof(pass));
+ bzero(cp, strlen(cp));
+ }
+ if (strcmp(pw_encrypt(pass, pwent.pw_passwd), pwent.pw_passwd) == 0) {
+ break;
+ }
+ time(&start);
+ now = start;
+ while (difftime(now, start) < FAIL_DELAY) {
+ sleep(FAIL_DELAY);
+ time(&now);
+ }
+ puts("Login incorrect");
+ fflush(stdout);
+ syslog(LOG_WARNING, "Incorrect root password\n");
+ }
+ bzero(pass, strlen(pass));
+ alarm(0);
+ signal(SIGALRM, SIG_DFL);
+ puts("Entering System Maintenance Mode\n");
+ fflush(stdout);
+ syslog(LOG_INFO, "System Maintenance Mode\n");
+ run_shell(pwent.pw_shell, 1, 0, 0);
+ return (0);
+}
diff --git a/loginutils/tinylogin.c b/loginutils/tinylogin.c
deleted file mode 100644
index bd611fd70..000000000
--- a/loginutils/tinylogin.c
+++ /dev/null
@@ -1,209 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * Copyright 1989 - 1991, Julianne Frances Haugh <jockgrrl@austin.rr.com>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of Julianne F. Haugh nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include "busybox.h"
-
-#include <stdio.h>
-#include <errno.h>
-#include <unistd.h>
-#include <string.h>
-#include <stdlib.h>
-#include <syslog.h>
-#include <ctype.h>
-
-#include "pwd.h"
-#include "grp.h"
-
-#ifdef CONFIG_FEATURE_SHADOWPASSWDS
-#include "shadow.h"
-#endif
-
-#define DEFAULT_LOGIN_PATH "/bin:/usr/bin"
-#define DEFAULT_ROOT_LOGIN_PATH "/usr/sbin:/bin:/usr/bin:/sbin"
-
-
-static void xsetenv ( const char *key, const char *value )
-{
- if ( setenv ( key, value, 1 ))
- error_msg_and_die ( "out of memory" );
-}
-
-/* Become the user and group(s) specified by PW. */
-
-void change_identity ( const struct passwd *pw )
-{
- if ( initgroups ( pw-> pw_name, pw-> pw_gid ) == -1 )
- perror_msg_and_die ( "cannot set groups" );
- endgrent ( );
-
- if ( setgid ( pw-> pw_gid ))
- perror_msg_and_die ( "cannot set group id" );
- if ( setuid ( pw->pw_uid ))
- perror_msg_and_die ( "cannot set user id" );
-}
-
-/* Run SHELL, or DEFAULT_SHELL if SHELL is empty.
- If COMMAND is nonzero, pass it to the shell with the -c option.
- If ADDITIONAL_ARGS is nonzero, pass it to the shell as more
- arguments. */
-
-void run_shell ( const char *shell, int loginshell, const char *command, const char **additional_args )
-{
- const char **args;
- int argno = 1;
- int additional_args_cnt = 0;
-
- for ( args = additional_args; args && *args; args++ )
- additional_args_cnt++;
-
- if ( additional_args )
- args = (const char **) xmalloc (sizeof (char *) * ( 4 + additional_args_cnt ));
- else
- args = (const char **) xmalloc (sizeof (char *) * 4 );
-
- args [0] = get_last_path_component ( xstrdup ( shell ));
-
- if ( loginshell ) {
- char *args0 = xmalloc ( xstrlen ( args [0] ) + 2 );
- args0 [0] = '-';
- strcpy ( args0 + 1, args [0] );
- args [0] = args0;
- }
-
- if ( command ) {
- args [argno++] = "-c";
- args [argno++] = command;
- }
- if ( additional_args ) {
- for ( ; *additional_args; ++additional_args )
- args [argno++] = *additional_args;
- }
- args [argno] = 0;
- execv ( shell, (char **) args );
- perror_msg_and_die ( "cannot run %s", shell );
-}
-
-/* Return 1 if SHELL is a restricted shell (one not returned by
- getusershell), else 0, meaning it is a standard shell. */
-
-int restricted_shell ( const char *shell )
-{
- char *line;
-
- setusershell ( );
- while (( line = getusershell ( ))) {
- if (( *line != '#' ) && ( strcmp ( line, shell ) == 0 ))
- break;
- }
- endusershell ( );
- return line ? 0 : 1;
-}
-
-/* Update `environ' for the new shell based on PW, with SHELL being
- the value for the SHELL environment variable. */
-
-void setup_environment ( const char *shell, int loginshell, int changeenv, const struct passwd *pw )
-{
- if ( loginshell ) {
- char *term;
-
- /* Change the current working directory to be the home directory
- * of the user. It is a fatal error for this process to be unable
- * to change to that directory. There is no "default" home
- * directory.
- * Some systems default to HOME=/
- */
- if ( chdir ( pw-> pw_dir )) {
- if ( chdir ( "/" )) {
- syslog ( LOG_WARNING, "unable to cd to %s' for user %s'\n", pw-> pw_dir, pw-> pw_name );
- error_msg_and_die ( "cannot cd to home directory or /" );
- }
- fputs ( "warning: cannot change to home directory\n", stderr );
- }
-
- /* Leave TERM unchanged. Set HOME, SHELL, USER, LOGNAME, PATH.
- Unset all other environment variables. */
- term = getenv ("TERM");
- clearenv ( );
- if ( term )
- xsetenv ( "TERM", term );
- xsetenv ( "HOME", pw-> pw_dir );
- xsetenv ( "SHELL", shell );
- xsetenv ( "USER", pw-> pw_name );
- xsetenv ( "LOGNAME", pw-> pw_name );
- xsetenv ( "PATH", ( pw-> pw_uid ? DEFAULT_LOGIN_PATH : DEFAULT_ROOT_LOGIN_PATH ));
- }
- else if ( changeenv ) {
- /* Set HOME, SHELL, and if not becoming a super-user,
- USER and LOGNAME. */
- xsetenv ( "HOME", pw-> pw_dir );
- xsetenv ( "SHELL", shell );
- if ( pw-> pw_uid ) {
- xsetenv ( "USER", pw-> pw_name );
- xsetenv ( "LOGNAME", pw-> pw_name );
- }
- }
-}
-
-/* Ask the user for a password.
- Return 1 if the user gives the correct password for entry PW,
- 0 if not. Return 1 without asking for a password if run by UID 0
- or if PW has an empty password. */
-
-int correct_password ( const struct passwd *pw )
-{
- char *unencrypted, *encrypted, *correct;
-
-#ifdef CONFIG_FEATURE_SHADOWPASSWDS
- if (( strcmp ( pw-> pw_passwd, "x" ) == 0 ) || ( strcmp ( pw-> pw_passwd, "*" ) == 0 )) {
- struct spwd *sp = getspnam ( pw-> pw_name );
-
- if ( !sp )
- error_msg_and_die ( "no valid shadow password" );
-
- correct = sp-> sp_pwdp;
- }
- else
-#endif
- correct = pw-> pw_passwd;
-
- if ( correct == 0 || correct[0] == '\0' )
- return 1;
-
- unencrypted = getpass ( "Password: " );
- if ( !unencrypted )
- {
- fputs ( "getpass: cannot open /dev/tty\n", stderr );
- return 0;
- }
- encrypted = crypt ( unencrypted, correct );
- memset ( unencrypted, 0, xstrlen ( unencrypted ));
- return ( strcmp ( encrypted, correct ) == 0 ) ? 1 : 0;
-}
diff --git a/loginutils/tinylogin.h b/loginutils/tinylogin.h
deleted file mode 100644
index 5e56a2c7f..000000000
--- a/loginutils/tinylogin.h
+++ /dev/null
@@ -1,10 +0,0 @@
-#ifndef BB_LOGINUTILS_SHELL_H
-#define BB_LOGINUTILS_SHELL_H
-
-extern void change_identity ( const struct passwd *pw );
-extern void run_shell ( const char *shell, int loginshell, const char *command, char **additional_args );
-extern int restricted_shell ( const char *shell );
-extern void setup_environment ( const char *shell, int loginshell, int changeenv, const struct passwd *pw );
-extern int correct_password ( const struct passwd *pw );
-
-#endif
diff --git a/loginutils/vlock.c b/loginutils/vlock.c
new file mode 100644
index 000000000..a26999f89
--- /dev/null
+++ b/loginutils/vlock.c
@@ -0,0 +1,229 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * vlock implementation for busybox
+ *
+ * Copyright (C) 2000 by spoon <spoon@ix.netcom.com>
+ * Written by spoon <spon@ix.netcom.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+/* Shoutz to Michael K. Johnson <johnsonm@redhat.com>, author of the
+ * original vlock. I snagged a bunch of his code to write this
+ * minimalistic vlock.
+ */
+/* Fixed by Erik Andersen to do passwords the tinylogin way...
+ * It now works with md5, sha1, etc passwords. */
+
+#include <stdio.h>
+#include <sys/vt.h>
+#include <signal.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/ioctl.h>
+#include <termios.h>
+
+#include "busybox.h"
+
+static struct passwd *pw;
+static struct spwd *spw;
+static struct vt_mode ovtm;
+static struct termios oterm;
+static int vfd;
+static int o_lock_all = 0;
+
+/* getspuid - get a shadow entry by uid */
+struct spwd *getspuid(uid_t uid)
+{
+ struct spwd *sp;
+ struct passwd *mypw;
+
+ if ((mypw = getpwuid(getuid())) == NULL) {
+ return (NULL);
+ }
+ setspent();
+ while ((sp = getspent()) != NULL) {
+ if (strcmp(mypw->pw_name, sp->sp_namp) == 0)
+ break;
+ }
+ endspent();
+ return (sp);
+}
+
+static void release_vt(int signo)
+{
+ if (!o_lock_all)
+ ioctl(vfd, VT_RELDISP, 1);
+ else
+ ioctl(vfd, VT_RELDISP, 0);
+}
+
+static void acquire_vt(int signo)
+{
+ ioctl(vfd, VT_RELDISP, VT_ACKACQ);
+}
+
+static void restore_terminal(void)
+{
+ ioctl(vfd, VT_SETMODE, &ovtm);
+ tcsetattr(STDIN_FILENO, TCSANOW, &oterm);
+}
+
+extern int vlock_main(int argc, char **argv)
+{
+ sigset_t sig;
+ struct sigaction sa;
+ struct vt_mode vtm;
+ int times = 0;
+ struct termios term;
+
+ if (argc > 2) {
+ show_usage();
+ }
+
+ if (argc == 2) {
+ if (strncmp(argv[1], "-a", 2)) {
+ show_usage();
+ } else {
+ o_lock_all = 1;
+ }
+ }
+
+ if ((pw = getpwuid(getuid())) == NULL) {
+ error_msg_and_die("no password for uid %d\n", getuid());
+ }
+#ifdef CONFIG_FEATURE_SHADOWPASSWDS
+ if ((strcmp(pw->pw_passwd, "x") == 0)
+ || (strcmp(pw->pw_passwd, "*") == 0)) {
+
+ if ((spw = getspuid(getuid())) == NULL) {
+ error_msg_and_die("could not read shadow password for uid %d: %s\n",
+ getuid(), strerror(errno));
+ }
+ if (spw->sp_pwdp) {
+ pw->pw_passwd = spw->sp_pwdp;
+ }
+ }
+#endif /* CONFIG_FEATURE_SHADOWPASSWDS */
+ if (pw->pw_passwd[0] == '!' || pw->pw_passwd[0] == '*') {
+ error_msg_and_die("Account disabled for uid %d\n", getuid());
+ }
+
+ /* we no longer need root privs */
+ setuid(getuid());
+ setgid(getgid());
+
+ if ((vfd = open("/dev/tty", O_RDWR)) < 0) {
+ error_msg_and_die("/dev/tty");
+ };
+
+ if (ioctl(vfd, VT_GETMODE, &vtm) < 0) {
+ error_msg_and_die("/dev/tty");
+ };
+
+ /* mask a bunch of signals */
+ sigprocmask(SIG_SETMASK, NULL, &sig);
+ sigdelset(&sig, SIGUSR1);
+ sigdelset(&sig, SIGUSR2);
+ sigaddset(&sig, SIGTSTP);
+ sigaddset(&sig, SIGTTIN);
+ sigaddset(&sig, SIGTTOU);
+ sigaddset(&sig, SIGHUP);
+ sigaddset(&sig, SIGCHLD);
+ sigaddset(&sig, SIGQUIT);
+ sigaddset(&sig, SIGINT);
+
+ sigemptyset(&(sa.sa_mask));
+ sa.sa_flags = SA_RESTART;
+ sa.sa_handler = release_vt;
+ sigaction(SIGUSR1, &sa, NULL);
+ sa.sa_handler = acquire_vt;
+ sigaction(SIGUSR2, &sa, NULL);
+
+ /* need to handle some signals so that we don't get killed by them */
+ sa.sa_handler = SIG_IGN;
+ sigaction(SIGHUP, &sa, NULL);
+ sigaction(SIGQUIT, &sa, NULL);
+ sigaction(SIGINT, &sa, NULL);
+ sigaction(SIGTSTP, &sa, NULL);
+
+ ovtm = vtm;
+ vtm.mode = VT_PROCESS;
+ vtm.relsig = SIGUSR1;
+ vtm.acqsig = SIGUSR2;
+ ioctl(vfd, VT_SETMODE, &vtm);
+
+ tcgetattr(STDIN_FILENO, &oterm);
+ term = oterm;
+ term.c_iflag &= ~BRKINT;
+ term.c_iflag |= IGNBRK;
+ term.c_lflag &= ~ISIG;
+ term.c_lflag &= ~(ECHO | ECHOCTL);
+ tcsetattr(STDIN_FILENO, TCSANOW, &term);
+
+ do {
+ char *pass, *crypt_pass;
+ char prompt[100];
+
+ if (o_lock_all) {
+ printf("All Virtual Consoles locked.\n");
+ } else {
+ printf("This Virtual Console locked.\n");
+ }
+ fflush(stdout);
+
+ snprintf(prompt, 100, "%s's password: ", pw->pw_name);
+
+ if ((pass = getpass(prompt)) == NULL) {
+ perror("getpass");
+ restore_terminal();
+ exit(1);
+ }
+
+ crypt_pass = pw_encrypt(pass, pw->pw_passwd);
+ if (strncmp(crypt_pass, pw->pw_passwd, sizeof(crypt_pass)) == 0) {
+ memset(pass, 0, strlen(pass));
+ memset(crypt_pass, 0, strlen(crypt_pass));
+ restore_terminal();
+ return 0;
+ }
+ memset(pass, 0, strlen(pass));
+ memset(crypt_pass, 0, strlen(crypt_pass));
+
+ if (isatty(STDIN_FILENO) == 0) {
+ perror("isatty");
+ restore_terminal();
+ exit(1);
+ }
+
+ sleep(++times);
+ printf("Password incorrect.\n");
+ if (times >= 3) {
+ sleep(15);
+ times = 2;
+ }
+ } while (1);
+}
+
+/*
+Local Variables:
+c-file-style: "linux"
+c-basic-offset: 4
+tab-width: 4
+End:
+*/