335 lines
7.5 KiB
Diff
335 lines
7.5 KiB
Diff
|
--- src/sulogin.c
|
||
|
+++ src/sulogin.c 2005-10-19 11:56:43.000000000 +0200
|
||
|
@@ -23,13 +23,16 @@
|
||
|
#include <pwd.h>
|
||
|
#include <shadow.h>
|
||
|
#include <termios.h>
|
||
|
+#include <sys/ttydefaults.h>
|
||
|
#include <sys/ioctl.h>
|
||
|
+#include <errno.h>
|
||
|
#if defined(__GLIBC__)
|
||
|
# include <crypt.h>
|
||
|
#endif
|
||
|
|
||
|
#define CHECK_DES 1
|
||
|
#define CHECK_MD5 1
|
||
|
+#define FIXTTY 1
|
||
|
|
||
|
#define F_PASSWD "/etc/passwd"
|
||
|
#define F_SHADOW "/etc/shadow"
|
||
|
@@ -37,49 +40,80 @@
|
||
|
|
||
|
char *Version = "@(#)sulogin 2.85-3 23-Apr-2003 miquels@cistron.nl";
|
||
|
|
||
|
-int timeout = 0;
|
||
|
-int profile = 0;
|
||
|
+static int timeout;
|
||
|
+static int profile;
|
||
|
+
|
||
|
+static void (*saved_sigint) = SIG_DFL;
|
||
|
+static void (*saved_sigtstp) = SIG_DFL;
|
||
|
+static void (*saved_sigquit) = SIG_DFL;
|
||
|
|
||
|
#ifndef IUCLC
|
||
|
# define IUCLC 0
|
||
|
#endif
|
||
|
|
||
|
-#if 0
|
||
|
+#if FIXTTY
|
||
|
/*
|
||
|
* Fix the tty modes and set reasonable defaults.
|
||
|
* (I'm not sure if this is needed under Linux, but..)
|
||
|
*/
|
||
|
+static
|
||
|
void fixtty(void)
|
||
|
{
|
||
|
struct termios tty;
|
||
|
+ int serial;
|
||
|
+
|
||
|
+ /* Skip serial console */
|
||
|
+ if (ioctl (0, TIOCMGET, (char*)&serial) == 0)
|
||
|
+ goto out;
|
||
|
+ /* Expected error */
|
||
|
+ serial = errno = 0;
|
||
|
|
||
|
tcgetattr(0, &tty);
|
||
|
|
||
|
- /*
|
||
|
- * Set or adjust tty modes.
|
||
|
- */
|
||
|
- tty.c_iflag &= ~(INLCR|IGNCR|IUCLC);
|
||
|
- tty.c_iflag |= ICRNL;
|
||
|
- tty.c_oflag &= ~(OCRNL|OLCUC|ONOCR|ONLRET|OFILL);
|
||
|
- tty.c_oflag |= OPOST|ONLCR;
|
||
|
- tty.c_cflag |= CLOCAL;
|
||
|
- tty.c_lflag = ISIG|ICANON|ECHO|ECHOE|ECHOK|ECHOCTL|ECHOKE;
|
||
|
-
|
||
|
- /*
|
||
|
- * Set the most important characters */
|
||
|
- */
|
||
|
- tty.c_cc[VINTR] = 3;
|
||
|
- tty.c_cc[VQUIT] = 28;
|
||
|
- tty.c_cc[VERASE] = 127;
|
||
|
- tty.c_cc[VKILL] = 24;
|
||
|
- tty.c_cc[VEOF] = 4;
|
||
|
- tty.c_cc[VTIME] = 0;
|
||
|
- tty.c_cc[VMIN] = 1;
|
||
|
- tty.c_cc[VSTART] = 17;
|
||
|
- tty.c_cc[VSTOP] = 19;
|
||
|
- tty.c_cc[VSUSP] = 26;
|
||
|
+ /* Use defaults of <sys/ttydefaults.h> for base settings */
|
||
|
+ tty.c_iflag |= TTYDEF_IFLAG;
|
||
|
+ tty.c_oflag |= TTYDEF_OFLAG;
|
||
|
+ tty.c_lflag |= TTYDEF_LFLAG;
|
||
|
+ tty.c_cflag |= (TTYDEF_SPEED | TTYDEF_CFLAG);
|
||
|
+
|
||
|
+ /* Sane setting, allow eight bit characters, no carriage return delay
|
||
|
+ * the same result as `stty sane cr0 pass8'
|
||
|
+ */
|
||
|
+ tty.c_iflag |= (BRKINT | ICRNL | IMAXBEL);
|
||
|
+ tty.c_iflag &= ~(IGNBRK | INLCR | IGNCR | IXOFF | IUCLC | IXANY | ISTRIP);
|
||
|
+ tty.c_oflag |= (OPOST | ONLCR | NL0 | CR0 | TAB0 | BS0 | VT0 | FF0);
|
||
|
+ tty.c_oflag &= ~(OLCUC | OCRNL | ONOCR | ONLRET | OFILL | OFDEL |\
|
||
|
+ NLDLY|CRDLY|TABDLY|BSDLY|VTDLY|FFDLY);
|
||
|
+ tty.c_lflag |= (ISIG | ICANON | IEXTEN | ECHO|ECHOE|ECHOK|ECHOCTL|ECHOKE);
|
||
|
+ tty.c_lflag &= ~(ECHONL | NOFLSH | XCASE | TOSTOP | ECHOPRT);
|
||
|
+ tty.c_cflag |= (CREAD | CS8 | B9600);
|
||
|
+ tty.c_cflag &= ~(PARENB);
|
||
|
+
|
||
|
+ /* VTIME and VMIN can overlap with VEOF and VEOL since they are
|
||
|
+ * only used for non-canonical mode. We just set the at the
|
||
|
+ * beginning, so nothing bad should happen.
|
||
|
+ */
|
||
|
+ tty.c_cc[VTIME] = 0;
|
||
|
+ tty.c_cc[VMIN] = 1;
|
||
|
+ tty.c_cc[VINTR] = CINTR;
|
||
|
+ tty.c_cc[VQUIT] = CQUIT;
|
||
|
+ tty.c_cc[VERASE] = CERASE; /* ASCII DEL (0177) */
|
||
|
+ tty.c_cc[VKILL] = CKILL;
|
||
|
+ tty.c_cc[VEOF] = CEOF;
|
||
|
+ tty.c_cc[VSWTC] = _POSIX_VDISABLE;
|
||
|
+ tty.c_cc[VSTART] = CSTART;
|
||
|
+ tty.c_cc[VSTOP] = CSTOP;
|
||
|
+ tty.c_cc[VSUSP] = CSUSP;
|
||
|
+ tty.c_cc[VEOL] = _POSIX_VDISABLE;
|
||
|
+ tty.c_cc[VREPRINT] = CREPRINT;
|
||
|
+ tty.c_cc[VDISCARD] = CDISCARD;
|
||
|
+ tty.c_cc[VWERASE] = CWERASE;
|
||
|
+ tty.c_cc[VLNEXT] = CLNEXT;
|
||
|
+ tty.c_cc[VEOL2] = _POSIX_VDISABLE;
|
||
|
|
||
|
tcsetattr(0, TCSANOW, &tty);
|
||
|
+out:
|
||
|
+ return;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
@@ -87,7 +121,8 @@
|
||
|
/*
|
||
|
* Called at timeout.
|
||
|
*/
|
||
|
-void alrm_handler()
|
||
|
+static
|
||
|
+void alrm_handler(int sig)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
@@ -96,6 +131,7 @@
|
||
|
* password is checked for traditional-style DES and
|
||
|
* FreeBSD-style MD5 encryption.
|
||
|
*/
|
||
|
+static
|
||
|
int valid(char *pass)
|
||
|
{
|
||
|
char *s;
|
||
|
@@ -134,6 +170,7 @@
|
||
|
/*
|
||
|
* Set a variable if the value is not NULL.
|
||
|
*/
|
||
|
+static
|
||
|
void set(char **var, char *val)
|
||
|
{
|
||
|
if (val) *var = val;
|
||
|
@@ -142,6 +179,7 @@
|
||
|
/*
|
||
|
* Get the root password entry.
|
||
|
*/
|
||
|
+static
|
||
|
struct passwd *getrootpwent(int try_manually)
|
||
|
{
|
||
|
static struct passwd pwd;
|
||
|
@@ -244,6 +282,7 @@
|
||
|
* Ask for the password. Note that there is no
|
||
|
* default timeout as we normally skip this during boot.
|
||
|
*/
|
||
|
+static
|
||
|
char *getpasswd(char *crypted)
|
||
|
{
|
||
|
struct sigaction sa;
|
||
|
@@ -252,11 +291,10 @@
|
||
|
char *ret = pass;
|
||
|
int i;
|
||
|
|
||
|
- if (crypted[0])
|
||
|
- printf("Give root password for maintenance\n");
|
||
|
- else
|
||
|
- printf("Press enter for maintenance\n");
|
||
|
- printf("(or type Control-D to continue): ");
|
||
|
+ if (crypted[0]) {
|
||
|
+ printf("Give root password for login: ");
|
||
|
+ } else
|
||
|
+ printf("Press enter for login: ");
|
||
|
fflush(stdout);
|
||
|
|
||
|
tcgetattr(0, &old);
|
||
|
@@ -291,6 +329,7 @@
|
||
|
/*
|
||
|
* Password was OK, execute a shell.
|
||
|
*/
|
||
|
+static
|
||
|
void sushell(struct passwd *pwd)
|
||
|
{
|
||
|
char shell[128];
|
||
|
@@ -332,9 +371,9 @@
|
||
|
* Try to execute a shell.
|
||
|
*/
|
||
|
setenv("SHELL", sushell, 1);
|
||
|
- signal(SIGINT, SIG_DFL);
|
||
|
- signal(SIGTSTP, SIG_DFL);
|
||
|
- signal(SIGQUIT, SIG_DFL);
|
||
|
+ signal(SIGINT, saved_sigint);
|
||
|
+ signal(SIGTSTP, saved_sigtstp);
|
||
|
+ signal(SIGQUIT, saved_sigquit);
|
||
|
execl(sushell, shell, NULL);
|
||
|
perror(sushell);
|
||
|
|
||
|
@@ -343,6 +382,7 @@
|
||
|
perror(BINSH);
|
||
|
}
|
||
|
|
||
|
+static
|
||
|
void usage(void)
|
||
|
{
|
||
|
fprintf(stderr, "Usage: sulogin [-e] [-p] [-t timeout] [tty device]\n");
|
||
|
@@ -385,50 +425,69 @@
|
||
|
/*
|
||
|
* See if we need to open an other tty device.
|
||
|
*/
|
||
|
- signal(SIGINT, SIG_IGN);
|
||
|
- signal(SIGQUIT, SIG_IGN);
|
||
|
- signal(SIGTSTP, SIG_IGN);
|
||
|
+ saved_sigint = signal(SIGINT, SIG_IGN);
|
||
|
+ saved_sigtstp = signal(SIGQUIT, SIG_IGN);
|
||
|
+ saved_sigquit = signal(SIGTSTP, SIG_IGN);
|
||
|
if (optind < argc) tty = argv[optind];
|
||
|
- if (tty) {
|
||
|
- if ((fd = open(tty, O_RDWR)) < 0) {
|
||
|
- perror(tty);
|
||
|
- } else if (!isatty(fd)) {
|
||
|
- fprintf(stderr, "%s: not a tty\n", tty);
|
||
|
- close(fd);
|
||
|
- } else {
|
||
|
-
|
||
|
- /*
|
||
|
- * Only go through this trouble if the new
|
||
|
- * tty doesn't fall in this process group.
|
||
|
- */
|
||
|
- pid = getpid();
|
||
|
- pgrp = getpgid(0);
|
||
|
- ppgrp = getpgid(getppid());
|
||
|
- ioctl(fd, TIOCGPGRP, &ttypgrp);
|
||
|
-
|
||
|
- if (pgrp != ttypgrp && ppgrp != ttypgrp) {
|
||
|
- if (pid != getsid(0)) {
|
||
|
- if (pid == getpgid(0))
|
||
|
- setpgid(0, getpgid(getppid()));
|
||
|
- setsid();
|
||
|
- }
|
||
|
|
||
|
- signal(SIGHUP, SIG_IGN);
|
||
|
+ if (!tty && !(tty = getenv("CONSOLE")))
|
||
|
+ tty = "/dev/console";
|
||
|
+
|
||
|
+ if ((fd = open(tty, O_RDWR)) < 0) {
|
||
|
+ perror(tty);
|
||
|
+ fd = dup(0);
|
||
|
+ }
|
||
|
+
|
||
|
+ if (!isatty(fd)) {
|
||
|
+ fprintf(stderr, "%s: not a tty\n", tty);
|
||
|
+ close(fd);
|
||
|
+ } else {
|
||
|
+
|
||
|
+ /*
|
||
|
+ * Only go through this trouble if the new
|
||
|
+ * tty doesn't fall in this process group.
|
||
|
+ */
|
||
|
+ pid = getpid();
|
||
|
+ pgrp = getpgid(0);
|
||
|
+ ppgrp = getpgid(getppid());
|
||
|
+ ttypgrp = tcgetpgrp(fd);
|
||
|
+
|
||
|
+ if (pgrp != ttypgrp && ppgrp != ttypgrp) {
|
||
|
+ if (pid != getsid(0)) {
|
||
|
+ if (pid == getpgid(0))
|
||
|
+ setpgid(0, getpgid(getppid()));
|
||
|
+ setsid();
|
||
|
+ }
|
||
|
+
|
||
|
+ signal(SIGHUP, SIG_IGN);
|
||
|
+ if (ttypgrp > 0)
|
||
|
ioctl(0, TIOCNOTTY, (char *)1);
|
||
|
- signal(SIGHUP, SIG_DFL);
|
||
|
- close(0);
|
||
|
- close(1);
|
||
|
- close(2);
|
||
|
+ signal(SIGHUP, SIG_DFL);
|
||
|
+ close(0);
|
||
|
+ close(1);
|
||
|
+ close(2);
|
||
|
+ if (fd > 2)
|
||
|
close(fd);
|
||
|
- fd = open(tty, O_RDWR);
|
||
|
+ if ((fd = open(tty, O_RDWR)) < 0) {
|
||
|
+ perror(tty);
|
||
|
+ } else {
|
||
|
+ tcsetpgrp(fd, ppgrp);
|
||
|
ioctl(0, TIOCSCTTY, (char *)1);
|
||
|
- dup(fd);
|
||
|
- dup(fd);
|
||
|
- } else
|
||
|
+ dup2(fd, 0);
|
||
|
+ dup2(fd, 1);
|
||
|
+ dup2(fd, 2);
|
||
|
+ if (fd > 2)
|
||
|
+ close(fd);
|
||
|
+ }
|
||
|
+ } else
|
||
|
+ if (fd > 2)
|
||
|
close(fd);
|
||
|
- }
|
||
|
}
|
||
|
|
||
|
+#if FIXTTY
|
||
|
+ fixtty();
|
||
|
+#endif
|
||
|
+
|
||
|
/*
|
||
|
* Get the root password.
|
||
|
*/
|
||
|
@@ -445,6 +504,9 @@
|
||
|
if (pwd->pw_passwd[0] == 0 ||
|
||
|
strcmp(crypt(p, pwd->pw_passwd), pwd->pw_passwd) == 0)
|
||
|
sushell(pwd);
|
||
|
+ saved_sigquit = signal(SIGQUIT, SIG_IGN);
|
||
|
+ saved_sigtstp = signal(SIGTSTP, SIG_IGN);
|
||
|
+ saved_sigint = signal(SIGINT, SIG_IGN);
|
||
|
printf("Login incorrect.\n");
|
||
|
}
|
||
|
|
||
|
@@ -453,4 +515,3 @@
|
||
|
*/
|
||
|
return 0;
|
||
|
}
|
||
|
-
|