aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--loginutils/login.c80
1 files changed, 44 insertions, 36 deletions
diff --git a/loginutils/login.c b/loginutils/login.c
index 861382f12..70e3b1333 100644
--- a/loginutils/login.c
+++ b/loginutils/login.c
@@ -52,7 +52,7 @@ static char* short_tty;
* command line flags.
*/
-static void read_or_build_utent(struct utmp *utptr, int picky)
+static void read_or_build_utent(struct utmp *utptr, int run_by_root)
{
struct utmp *ut;
pid_t pid = getpid();
@@ -60,30 +60,33 @@ static void read_or_build_utent(struct utmp *utptr, int picky)
setutent();
/* First, try to find a valid utmp entry for this process. */
- while ((ut = getutent()))
- if (ut->ut_pid == pid && ut->ut_line[0] && ut->ut_id[0] &&
- (ut->ut_type == LOGIN_PROCESS || ut->ut_type == USER_PROCESS))
- break;
+ /* If there is one, just use it. */
+ while ((ut = getutent()) != NULL)
+ if (ut->ut_pid == pid && ut->ut_line[0] && ut->ut_id[0]
+ && (ut->ut_type == LOGIN_PROCESS || ut->ut_type == USER_PROCESS)
+ ) {
+ *utptr = *ut; /* struct copy */
+ if (run_by_root) /* why only for root? */
+ memset(utptr->ut_host, 0, sizeof(utptr->ut_host));
+ return;
+ }
- /* If there is one, just use it, otherwise create a new one. */
- if (ut) {
- *utptr = *ut;
- } else {
- if (picky)
- bb_error_msg_and_die("no utmp entry found");
-
- memset(utptr, 0, sizeof(*utptr));
- utptr->ut_type = LOGIN_PROCESS;
- utptr->ut_pid = pid;
- strncpy(utptr->ut_line, short_tty, sizeof(utptr->ut_line));
- /* This one is only 4 chars wide. Try to fit something
- * remotely meaningful by skipping "tty"... */
- strncpy(utptr->ut_id, short_tty + 3, sizeof(utptr->ut_id));
- strncpy(utptr->ut_user, "LOGIN", sizeof(utptr->ut_user));
- utptr->ut_tv.tv_sec = time(NULL);
- }
- if (!picky) /* root login */
- memset(utptr->ut_host, 0, sizeof(utptr->ut_host));
+// Why? Do we require non-root to exec login from another
+// former login process (e.g. login shell)? Some login's have
+// login shells as children, so it won't work...
+// if (!run_by_root)
+// bb_error_msg_and_die("no utmp entry found");
+
+ /* Otherwise create a new one. */
+ memset(utptr, 0, sizeof(*utptr));
+ utptr->ut_type = LOGIN_PROCESS;
+ utptr->ut_pid = pid;
+ strncpy(utptr->ut_line, short_tty, sizeof(utptr->ut_line));
+ /* This one is only 4 chars wide. Try to fit something
+ * remotely meaningful by skipping "tty"... */
+ strncpy(utptr->ut_id, short_tty + 3, sizeof(utptr->ut_id));
+ strncpy(utptr->ut_user, "LOGIN", sizeof(utptr->ut_user));
+ utptr->ut_tv.tv_sec = time(NULL);
}
/*
@@ -109,7 +112,7 @@ static void write_utent(struct utmp *utptr, const char *username)
#endif
}
#else /* !ENABLE_FEATURE_UTMP */
-#define read_or_build_utent(utptr, picky) ((void)0)
+#define read_or_build_utent(utptr, run_by_root) ((void)0)
#define write_utent(utptr, username) ((void)0)
#endif /* !ENABLE_FEATURE_UTMP */
@@ -225,7 +228,7 @@ int login_main(int argc UNUSED_PARAM, char **argv)
char *fromhost;
char username[USERNAME_SIZE];
const char *tmp;
- int amroot;
+ int run_by_root;
unsigned opt;
int count = 0;
struct passwd *pw;
@@ -248,8 +251,9 @@ int login_main(int argc UNUSED_PARAM, char **argv)
signal(SIGALRM, alarm_handler);
alarm(TIMEOUT);
- /* More of suid paranoia if called by non-root */
- amroot = !sanitize_env_if_suid(); /* Clear dangerous stuff, set PATH */
+ /* More of suid paranoia if called by non-root: */
+ /* Clear dangerous stuff, set PATH */
+ run_by_root = !sanitize_env_if_suid();
/* Mandatory paranoia for suid applet:
* ensure that fd# 0,1,2 are opened (at least to /dev/null)
@@ -259,7 +263,7 @@ int login_main(int argc UNUSED_PARAM, char **argv)
opt = getopt32(argv, "f:h:p", &opt_user, &opt_host);
if (opt & LOGIN_OPT_f) {
- if (!amroot)
+ if (!run_by_root)
bb_error_msg_and_die("-f is for root only");
safe_strncpy(username, opt_user, sizeof(username));
}
@@ -278,7 +282,7 @@ int login_main(int argc UNUSED_PARAM, char **argv)
short_tty = full_tty + 5;
}
- read_or_build_utent(&utent, !amroot);
+ read_or_build_utent(&utent, run_by_root);
if (opt & LOGIN_OPT_h) {
USE_FEATURE_UTMP(
@@ -396,10 +400,12 @@ int login_main(int argc UNUSED_PARAM, char **argv)
return EXIT_FAILURE;
}
username[0] = '\0';
- }
+ } /* while (1) */
alarm(0);
- if (!amroot)
+ /* We can ignore /etc/nologin if we are logging in as root,
+ * it doesn't matter whether we are run by root or not */
+ if (pw->pw_uid != 0)
die_if_nologin();
write_utent(&utent, username);
@@ -433,7 +439,7 @@ int login_main(int argc UNUSED_PARAM, char **argv)
fchmod(0, 0600);
/* We trust environment only if we run by root */
- if (ENABLE_LOGIN_SCRIPTS && amroot) {
+ if (ENABLE_LOGIN_SCRIPTS && run_by_root) {
char *t_argv[2];
t_argv[0] = getenv("LOGIN_PRE_SUID_SCRIPT");
@@ -479,14 +485,16 @@ int login_main(int argc UNUSED_PARAM, char **argv)
// bb_setpgrp();
// If this stuff is really needed, add it and explain why!
- /* set signals to defaults */
- signal(SIGALRM, SIG_DFL);
+ /* Set signals to defaults */
+ /*signal(SIGALRM, SIG_DFL); - not needed, we already set it
+ * to non-SIG_IGN, and on exec such signals are reset to SIG_DFL */
+
/* Is this correct? This way user can ctrl-c out of /etc/profile,
* potentially creating security breach (tested with bash 3.0).
* But without this, bash 3.0 will not enable ctrl-c either.
* Maybe bash is buggy?
* Need to find out what standards say about /bin/login -
- * should it leave SIGINT etc enabled or disabled? */
+ * should we leave SIGINT etc enabled or disabled? */
signal(SIGINT, SIG_DFL);
/* Exec login shell with no additional parameters */