login: fix /etc/nologin handling (should prohibit non-root LOGINS,
not running login by non-root). minor code shrink. function old new delta login_main 1669 1602 -67
This commit is contained in:
parent
b0150d299f
commit
2ec94a7ee8
@ -52,7 +52,7 @@ static char* short_tty;
|
|||||||
* command line flags.
|
* 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;
|
struct utmp *ut;
|
||||||
pid_t pid = getpid();
|
pid_t pid = getpid();
|
||||||
@ -60,30 +60,33 @@ static void read_or_build_utent(struct utmp *utptr, int picky)
|
|||||||
setutent();
|
setutent();
|
||||||
|
|
||||||
/* First, try to find a valid utmp entry for this process. */
|
/* First, try to find a valid utmp entry for this process. */
|
||||||
while ((ut = getutent()))
|
/* If there is one, just use it. */
|
||||||
if (ut->ut_pid == pid && ut->ut_line[0] && ut->ut_id[0] &&
|
while ((ut = getutent()) != NULL)
|
||||||
(ut->ut_type == LOGIN_PROCESS || ut->ut_type == USER_PROCESS))
|
if (ut->ut_pid == pid && ut->ut_line[0] && ut->ut_id[0]
|
||||||
break;
|
&& (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. */
|
// Why? Do we require non-root to exec login from another
|
||||||
if (ut) {
|
// former login process (e.g. login shell)? Some login's have
|
||||||
*utptr = *ut;
|
// login shells as children, so it won't work...
|
||||||
} else {
|
// if (!run_by_root)
|
||||||
if (picky)
|
// bb_error_msg_and_die("no utmp entry found");
|
||||||
bb_error_msg_and_die("no utmp entry found");
|
|
||||||
|
|
||||||
memset(utptr, 0, sizeof(*utptr));
|
/* Otherwise create a new one. */
|
||||||
utptr->ut_type = LOGIN_PROCESS;
|
memset(utptr, 0, sizeof(*utptr));
|
||||||
utptr->ut_pid = pid;
|
utptr->ut_type = LOGIN_PROCESS;
|
||||||
strncpy(utptr->ut_line, short_tty, sizeof(utptr->ut_line));
|
utptr->ut_pid = pid;
|
||||||
/* This one is only 4 chars wide. Try to fit something
|
strncpy(utptr->ut_line, short_tty, sizeof(utptr->ut_line));
|
||||||
* remotely meaningful by skipping "tty"... */
|
/* This one is only 4 chars wide. Try to fit something
|
||||||
strncpy(utptr->ut_id, short_tty + 3, sizeof(utptr->ut_id));
|
* remotely meaningful by skipping "tty"... */
|
||||||
strncpy(utptr->ut_user, "LOGIN", sizeof(utptr->ut_user));
|
strncpy(utptr->ut_id, short_tty + 3, sizeof(utptr->ut_id));
|
||||||
utptr->ut_tv.tv_sec = time(NULL);
|
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));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -109,7 +112,7 @@ static void write_utent(struct utmp *utptr, const char *username)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#else /* !ENABLE_FEATURE_UTMP */
|
#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)
|
#define write_utent(utptr, username) ((void)0)
|
||||||
#endif /* !ENABLE_FEATURE_UTMP */
|
#endif /* !ENABLE_FEATURE_UTMP */
|
||||||
|
|
||||||
@ -225,7 +228,7 @@ int login_main(int argc UNUSED_PARAM, char **argv)
|
|||||||
char *fromhost;
|
char *fromhost;
|
||||||
char username[USERNAME_SIZE];
|
char username[USERNAME_SIZE];
|
||||||
const char *tmp;
|
const char *tmp;
|
||||||
int amroot;
|
int run_by_root;
|
||||||
unsigned opt;
|
unsigned opt;
|
||||||
int count = 0;
|
int count = 0;
|
||||||
struct passwd *pw;
|
struct passwd *pw;
|
||||||
@ -248,8 +251,9 @@ int login_main(int argc UNUSED_PARAM, char **argv)
|
|||||||
signal(SIGALRM, alarm_handler);
|
signal(SIGALRM, alarm_handler);
|
||||||
alarm(TIMEOUT);
|
alarm(TIMEOUT);
|
||||||
|
|
||||||
/* More of suid paranoia if called by non-root */
|
/* More of suid paranoia if called by non-root: */
|
||||||
amroot = !sanitize_env_if_suid(); /* Clear dangerous stuff, set PATH */
|
/* Clear dangerous stuff, set PATH */
|
||||||
|
run_by_root = !sanitize_env_if_suid();
|
||||||
|
|
||||||
/* Mandatory paranoia for suid applet:
|
/* Mandatory paranoia for suid applet:
|
||||||
* ensure that fd# 0,1,2 are opened (at least to /dev/null)
|
* 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);
|
opt = getopt32(argv, "f:h:p", &opt_user, &opt_host);
|
||||||
if (opt & LOGIN_OPT_f) {
|
if (opt & LOGIN_OPT_f) {
|
||||||
if (!amroot)
|
if (!run_by_root)
|
||||||
bb_error_msg_and_die("-f is for root only");
|
bb_error_msg_and_die("-f is for root only");
|
||||||
safe_strncpy(username, opt_user, sizeof(username));
|
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;
|
short_tty = full_tty + 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
read_or_build_utent(&utent, !amroot);
|
read_or_build_utent(&utent, run_by_root);
|
||||||
|
|
||||||
if (opt & LOGIN_OPT_h) {
|
if (opt & LOGIN_OPT_h) {
|
||||||
USE_FEATURE_UTMP(
|
USE_FEATURE_UTMP(
|
||||||
@ -396,10 +400,12 @@ int login_main(int argc UNUSED_PARAM, char **argv)
|
|||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
username[0] = '\0';
|
username[0] = '\0';
|
||||||
}
|
} /* while (1) */
|
||||||
|
|
||||||
alarm(0);
|
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();
|
die_if_nologin();
|
||||||
|
|
||||||
write_utent(&utent, username);
|
write_utent(&utent, username);
|
||||||
@ -433,7 +439,7 @@ int login_main(int argc UNUSED_PARAM, char **argv)
|
|||||||
fchmod(0, 0600);
|
fchmod(0, 0600);
|
||||||
|
|
||||||
/* We trust environment only if we run by root */
|
/* 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];
|
char *t_argv[2];
|
||||||
|
|
||||||
t_argv[0] = getenv("LOGIN_PRE_SUID_SCRIPT");
|
t_argv[0] = getenv("LOGIN_PRE_SUID_SCRIPT");
|
||||||
@ -479,14 +485,16 @@ int login_main(int argc UNUSED_PARAM, char **argv)
|
|||||||
// bb_setpgrp();
|
// bb_setpgrp();
|
||||||
// If this stuff is really needed, add it and explain why!
|
// If this stuff is really needed, add it and explain why!
|
||||||
|
|
||||||
/* set signals to defaults */
|
/* Set signals to defaults */
|
||||||
signal(SIGALRM, SIG_DFL);
|
/*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,
|
/* Is this correct? This way user can ctrl-c out of /etc/profile,
|
||||||
* potentially creating security breach (tested with bash 3.0).
|
* potentially creating security breach (tested with bash 3.0).
|
||||||
* But without this, bash 3.0 will not enable ctrl-c either.
|
* But without this, bash 3.0 will not enable ctrl-c either.
|
||||||
* Maybe bash is buggy?
|
* Maybe bash is buggy?
|
||||||
* Need to find out what standards say about /bin/login -
|
* 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);
|
signal(SIGINT, SIG_DFL);
|
||||||
|
|
||||||
/* Exec login shell with no additional parameters */
|
/* Exec login shell with no additional parameters */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user