* src/login.c: Get rid of pwent. pwd is sufficient as long as it
is always coming from xgetpwnam. There is no need to copy pwd to pwent, this was not a good idea anyway as the strings from pwd were not duplicated. * src/login.c: Always free the pwd and spwd structure when we retrieve a new one. This will clear the password of the previous user from the memory. * src/login.c: user_passwd is used to keep point to the password of the user being authenticated. * src/login.c: (non PAM) Fail if the user's entry cannot be found after the user updated her password (if expire() requested an update). * src/login.c: If the user does not exist on the system, there is no need to build a pwd structure (with shell).
This commit is contained in:
parent
a6ac4dda75
commit
18fdfee274
17
ChangeLog
17
ChangeLog
@ -1,3 +1,20 @@
|
|||||||
|
2009-04-20 Nicolas François <nicolas.francois@centraliens.net>
|
||||||
|
|
||||||
|
* src/login.c: Get rid of pwent. pwd is sufficient as long as it
|
||||||
|
is always coming from xgetpwnam. There is no need to copy pwd to
|
||||||
|
pwent, this was not a good idea anyway as the strings from pwd
|
||||||
|
were not duplicated.
|
||||||
|
* src/login.c: Always free the pwd and spwd structure when we
|
||||||
|
retrieve a new one. This will clear the password of the previous
|
||||||
|
user from the memory.
|
||||||
|
* src/login.c: user_passwd is used to keep point to the password
|
||||||
|
of the user being authenticated.
|
||||||
|
* src/login.c: (non PAM) Fail if the user's entry cannot be found
|
||||||
|
after the user updated her password (if expire() requested an
|
||||||
|
update).
|
||||||
|
* src/login.c: If the user does not exist on the system, there is
|
||||||
|
no need to build a pwd structure (with shell).
|
||||||
|
|
||||||
2009-04-20 Nicolas François <nicolas.francois@centraliens.net>
|
2009-04-20 Nicolas François <nicolas.francois@centraliens.net>
|
||||||
|
|
||||||
* src/login.c: ttytype already checks for TTYTYPE_FILE and TERM.
|
* src/login.c: ttytype already checks for TTYTYPE_FILE and TERM.
|
||||||
|
138
src/login.c
138
src/login.c
@ -85,8 +85,6 @@ static const char *hostname = "";
|
|||||||
static char *username = NULL;
|
static char *username = NULL;
|
||||||
static int reason = PW_LOGIN;
|
static int reason = PW_LOGIN;
|
||||||
|
|
||||||
static struct passwd pwent;
|
|
||||||
|
|
||||||
#if HAVE_UTMPX_H
|
#if HAVE_UTMPX_H
|
||||||
extern struct utmpx utxent;
|
extern struct utmpx utxent;
|
||||||
struct utmpx failent;
|
struct utmpx failent;
|
||||||
@ -490,10 +488,9 @@ int main (int argc, char **argv)
|
|||||||
const char *cp;
|
const char *cp;
|
||||||
char *tmp;
|
char *tmp;
|
||||||
char fromhost[512];
|
char fromhost[512];
|
||||||
struct passwd *pwd;
|
struct passwd *pwd = NULL;
|
||||||
char **envp = environ;
|
char **envp = environ;
|
||||||
#ifndef USE_PAM
|
#ifndef USE_PAM
|
||||||
static char temp_pw[2];
|
|
||||||
static char temp_shell[] = "/bin/sh";
|
static char temp_shell[] = "/bin/sh";
|
||||||
#endif
|
#endif
|
||||||
const char *failent_user;
|
const char *failent_user;
|
||||||
@ -881,8 +878,6 @@ int main (int argc, char **argv)
|
|||||||
exit (1);
|
exit (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
pwent = *pwd;
|
|
||||||
|
|
||||||
retcode = pam_setcred (pamh, PAM_ESTABLISH_CRED);
|
retcode = pam_setcred (pamh, PAM_ESTABLISH_CRED);
|
||||||
PAM_FAIL_CHECK;
|
PAM_FAIL_CHECK;
|
||||||
/* NOTE: If pam_setcred changes PAM_USER, this will not be taken
|
/* NOTE: If pam_setcred changes PAM_USER, this will not be taken
|
||||||
@ -891,6 +886,22 @@ int main (int argc, char **argv)
|
|||||||
|
|
||||||
#else /* ! USE_PAM */
|
#else /* ! USE_PAM */
|
||||||
while (true) { /* repeatedly get login/password pairs */
|
while (true) { /* repeatedly get login/password pairs */
|
||||||
|
/* user_passwd is always a pointer to this constant string
|
||||||
|
* or a passwd or shadow password that will be memzero by
|
||||||
|
* passwd_free / shadow_free.
|
||||||
|
* Do not free() user_passwd. */
|
||||||
|
const char *user_passwd = "!";
|
||||||
|
|
||||||
|
/* Do some cleanup to avoid keeping entries we do not need
|
||||||
|
* anymore. */
|
||||||
|
if (NULL != pwd) {
|
||||||
|
passwd_free (pwd);
|
||||||
|
}
|
||||||
|
if (NULL != spwd) {
|
||||||
|
shadow_free (spwd);
|
||||||
|
spwd = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
failed = false; /* haven't failed authentication yet */
|
failed = false; /* haven't failed authentication yet */
|
||||||
if (NULL == username) { /* need to get a login id */
|
if (NULL == username) { /* need to get a login id */
|
||||||
if (subroot) {
|
if (subroot) {
|
||||||
@ -913,41 +924,37 @@ int main (int argc, char **argv)
|
|||||||
|
|
||||||
pwd = xgetpwnam (username);
|
pwd = xgetpwnam (username);
|
||||||
if (NULL == pwd) {
|
if (NULL == pwd) {
|
||||||
pwent.pw_name = username;
|
|
||||||
strcpy (temp_pw, "!");
|
|
||||||
pwent.pw_passwd = temp_pw;
|
|
||||||
pwent.pw_shell = temp_shell;
|
|
||||||
|
|
||||||
preauth_flag = false;
|
preauth_flag = false;
|
||||||
failed = true;
|
failed = true;
|
||||||
} else {
|
} else {
|
||||||
pwent = *pwd;
|
user_passwd = pwd->pw_passwd;
|
||||||
|
/*
|
||||||
|
* If the encrypted password begins with a "!",
|
||||||
|
* the account is locked and the user cannot
|
||||||
|
* login, even if they have been
|
||||||
|
* "pre-authenticated."
|
||||||
|
*/
|
||||||
|
if ( ('!' == user_passwd[0])
|
||||||
|
|| ('*' == user_passwd[0])) {
|
||||||
|
failed = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
spwd = NULL;
|
if (strcmp (user_passwd, SHADOW_PASSWD_STRING) == 0) {
|
||||||
if ( (NULL != pwd)
|
spwd = xgetspnam (username);
|
||||||
&& (strcmp (pwd->pw_passwd, SHADOW_PASSWD_STRING) == 0)) {
|
|
||||||
/* !USE_PAM, no need for xgetspnam */
|
|
||||||
spwd = getspnam (username);
|
|
||||||
if (NULL != spwd) {
|
if (NULL != spwd) {
|
||||||
pwent.pw_passwd = spwd->sp_pwdp;
|
user_passwd = spwd->sp_pwdp;
|
||||||
} else {
|
} else {
|
||||||
|
/* The user exists in passwd, but not in
|
||||||
|
* shadow. SHADOW_PASSWD_STRING indicates
|
||||||
|
* that the password shall be in shadow.
|
||||||
|
*/
|
||||||
SYSLOG ((LOG_WARN,
|
SYSLOG ((LOG_WARN,
|
||||||
"no shadow password for '%s'%s",
|
"no shadow password for '%s'%s",
|
||||||
username, fromhost));
|
username, fromhost));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* If the encrypted password begins with a "!", the account
|
|
||||||
* is locked and the user cannot login, even if they have
|
|
||||||
* been "pre-authenticated."
|
|
||||||
*/
|
|
||||||
if ( ('!' == pwent.pw_passwd[0])
|
|
||||||
|| ('*' == pwent.pw_passwd[0])) {
|
|
||||||
failed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The -r and -f flags provide a name which has already
|
* The -r and -f flags provide a name which has already
|
||||||
* been authenticated by some server.
|
* been authenticated by some server.
|
||||||
@ -956,8 +963,7 @@ int main (int argc, char **argv)
|
|||||||
goto auth_ok;
|
goto auth_ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pw_auth (pwent.pw_passwd, username,
|
if (pw_auth (user_passwd, username, reason, (char *) 0) == 0) {
|
||||||
reason, (char *) 0) == 0) {
|
|
||||||
goto auth_ok;
|
goto auth_ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -972,8 +978,8 @@ int main (int argc, char **argv)
|
|||||||
* authenticated and so on.
|
* authenticated and so on.
|
||||||
*/
|
*/
|
||||||
if ( !failed
|
if ( !failed
|
||||||
&& (NULL != pwent.pw_name)
|
&& (NULL != pwd)
|
||||||
&& (0 == pwent.pw_uid)
|
&& (0 == pwd->pw_uid)
|
||||||
&& !is_console) {
|
&& !is_console) {
|
||||||
SYSLOG ((LOG_CRIT, "ILLEGAL ROOT LOGIN %s", fromhost));
|
SYSLOG ((LOG_CRIT, "ILLEGAL ROOT LOGIN %s", fromhost));
|
||||||
failed = true;
|
failed = true;
|
||||||
@ -986,7 +992,7 @@ int main (int argc, char **argv)
|
|||||||
}
|
}
|
||||||
if ( (NULL != pwd)
|
if ( (NULL != pwd)
|
||||||
&& getdef_bool ("FAILLOG_ENAB")
|
&& getdef_bool ("FAILLOG_ENAB")
|
||||||
&& !failcheck (pwent.pw_uid, &faillog, failed)) {
|
&& !failcheck (pwd->pw_uid, &faillog, failed)) {
|
||||||
SYSLOG ((LOG_CRIT,
|
SYSLOG ((LOG_CRIT,
|
||||||
"exceeded failure limit for '%s' %s",
|
"exceeded failure limit for '%s' %s",
|
||||||
username, fromhost));
|
username, fromhost));
|
||||||
@ -998,7 +1004,7 @@ int main (int argc, char **argv)
|
|||||||
|
|
||||||
/* don't log non-existent users */
|
/* don't log non-existent users */
|
||||||
if ((NULL != pwd) && getdef_bool ("FAILLOG_ENAB")) {
|
if ((NULL != pwd) && getdef_bool ("FAILLOG_ENAB")) {
|
||||||
failure (pwent.pw_uid, tty, &faillog);
|
failure (pwd->pw_uid, tty, &faillog);
|
||||||
}
|
}
|
||||||
if (getdef_str ("FTMP_FILE") != NULL) {
|
if (getdef_str ("FTMP_FILE") != NULL) {
|
||||||
#if HAVE_UTMPX_H
|
#if HAVE_UTMPX_H
|
||||||
@ -1036,7 +1042,7 @@ int main (int argc, char **argv)
|
|||||||
* guys won't see that the passwordless account exists at
|
* guys won't see that the passwordless account exists at
|
||||||
* all). --marekm
|
* all). --marekm
|
||||||
*/
|
*/
|
||||||
if (pwent.pw_passwd[0] == '\0') {
|
if (user_passwd[0] == '\0') {
|
||||||
pw_auth ("!", username, reason, (char *) 0);
|
pw_auth ("!", username, reason, (char *) 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1075,7 +1081,7 @@ int main (int argc, char **argv)
|
|||||||
* by Ivan Nejgebauer <ian@unsux.ns.ac.yu>. --marekm
|
* by Ivan Nejgebauer <ian@unsux.ns.ac.yu>. --marekm
|
||||||
*/
|
*/
|
||||||
if ( getdef_bool ("PORTTIME_CHECKS_ENAB")
|
if ( getdef_bool ("PORTTIME_CHECKS_ENAB")
|
||||||
&& !isttytime (pwent.pw_name, tty, time ((time_t *) 0))) {
|
&& !isttytime (username, tty, time ((time_t *) 0))) {
|
||||||
SYSLOG ((LOG_WARN, "invalid login time for '%s'%s",
|
SYSLOG ((LOG_WARN, "invalid login time for '%s'%s",
|
||||||
username, fromhost));
|
username, fromhost));
|
||||||
closelog ();
|
closelog ();
|
||||||
@ -1083,7 +1089,7 @@ int main (int argc, char **argv)
|
|||||||
exit (1);
|
exit (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
check_nologin (pwent.pw_uid == 0);
|
check_nologin (pwd->pw_uid == 0);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (getenv ("IFS")) { /* don't export user IFS ... */
|
if (getenv ("IFS")) { /* don't export user IFS ... */
|
||||||
@ -1091,9 +1097,9 @@ int main (int argc, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
setutmp (username, tty, hostname); /* make entry in utmp & wtmp files */
|
setutmp (username, tty, hostname); /* make entry in utmp & wtmp files */
|
||||||
if (pwent.pw_shell[0] == '*') { /* subsystem root */
|
if (pwd->pw_shell[0] == '*') { /* subsystem root */
|
||||||
pwent.pw_shell++; /* skip the '*' */
|
pwd->pw_shell++; /* skip the '*' */
|
||||||
subsystem (&pwent); /* figure out what to execute */
|
subsystem (pwd); /* figure out what to execute */
|
||||||
subroot = true; /* say I was here again */
|
subroot = true; /* say I was here again */
|
||||||
endpwent (); /* close all of the file which were */
|
endpwent (); /* close all of the file which were */
|
||||||
endgrent (); /* open in the original rooted file */
|
endgrent (); /* open in the original rooted file */
|
||||||
@ -1110,7 +1116,7 @@ int main (int argc, char **argv)
|
|||||||
AUDIT_USER_LOGIN,
|
AUDIT_USER_LOGIN,
|
||||||
NULL, /* Prog. name */
|
NULL, /* Prog. name */
|
||||||
"login",
|
"login",
|
||||||
pwd->pw_name,
|
username,
|
||||||
AUDIT_NO_ID,
|
AUDIT_NO_ID,
|
||||||
hostname,
|
hostname,
|
||||||
NULL, /* addr */
|
NULL, /* addr */
|
||||||
@ -1121,31 +1127,38 @@ int main (int argc, char **argv)
|
|||||||
|
|
||||||
#ifndef USE_PAM /* pam_lastlog handles this */
|
#ifndef USE_PAM /* pam_lastlog handles this */
|
||||||
if (getdef_bool ("LASTLOG_ENAB")) { /* give last login and log this one */
|
if (getdef_bool ("LASTLOG_ENAB")) { /* give last login and log this one */
|
||||||
dolastlog (&lastlog, &pwent, tty, hostname);
|
dolastlog (&lastlog, pwd, tty, hostname);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef USE_PAM /* PAM handles this as well */
|
#ifndef USE_PAM /* PAM handles this as well */
|
||||||
/*
|
/*
|
||||||
* Have to do this while we still have root privileges, otherwise we
|
* Have to do this while we still have root privileges, otherwise we
|
||||||
* don't have access to /etc/shadow. expire() closes password files,
|
* don't have access to /etc/shadow.
|
||||||
* and changes to the user in the child before executing the passwd
|
|
||||||
* program. --marekm
|
|
||||||
*/
|
*/
|
||||||
if (spwd) { /* check for age of password */
|
if (NULL != spwd) { /* check for age of password */
|
||||||
if (expire (&pwent, spwd)) {
|
if (expire (pwd, spwd)) {
|
||||||
/* !USE_PAM, no need for xgetpwnam */
|
/* The user updated her password, get the new
|
||||||
pwd = getpwnam (username);
|
* entries.
|
||||||
/* !USE_PAM, no need for xgetspnam */
|
* Use the x variants because we need to keep the
|
||||||
spwd = getspnam (username);
|
* entry for a long time, and there might be other
|
||||||
if (pwd) {
|
* getxxyy in between.
|
||||||
pwent = *pwd;
|
*/
|
||||||
|
passwd_free (pwd);
|
||||||
|
pwd = xgetpwnam (username);
|
||||||
|
if (NULL == pwd) {
|
||||||
|
SYSLOG ((LOG_ERR,
|
||||||
|
"cannot find user %s after update of expired password",
|
||||||
|
username));
|
||||||
|
exit (1);
|
||||||
}
|
}
|
||||||
|
shadow_free (spwd);
|
||||||
|
spwd = xgetspnam (username);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
setup_limits (&pwent); /* nice, ulimit etc. */
|
setup_limits (pwd); /* nice, ulimit etc. */
|
||||||
#endif /* ! USE_PAM */
|
#endif /* ! USE_PAM */
|
||||||
chown_tty (&pwent);
|
chown_tty (pwd);
|
||||||
|
|
||||||
#ifdef USE_PAM
|
#ifdef USE_PAM
|
||||||
/*
|
/*
|
||||||
@ -1180,7 +1193,8 @@ int main (int argc, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/* The pwd and spwd entries for the user have been copied.
|
||||||
|
*
|
||||||
* Close all the files so that unauthorized access won't occur.
|
* Close all the files so that unauthorized access won't occur.
|
||||||
*/
|
*/
|
||||||
endpwent (); /* stop access to password file */
|
endpwent (); /* stop access to password file */
|
||||||
@ -1192,18 +1206,18 @@ int main (int argc, char **argv)
|
|||||||
|
|
||||||
/* Drop root privileges */
|
/* Drop root privileges */
|
||||||
#ifndef USE_PAM
|
#ifndef USE_PAM
|
||||||
if (setup_uid_gid (&pwent, is_console))
|
if (setup_uid_gid (pwd, is_console))
|
||||||
#else
|
#else
|
||||||
/* The group privileges were already dropped.
|
/* The group privileges were already dropped.
|
||||||
* See setup_groups() above.
|
* See setup_groups() above.
|
||||||
*/
|
*/
|
||||||
if (change_uid (&pwent))
|
if (change_uid (pwd))
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
exit (1);
|
exit (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
setup_env (&pwent); /* set env vars, cd to the home dir */
|
setup_env (pwd); /* set env vars, cd to the home dir */
|
||||||
|
|
||||||
#ifdef USE_PAM
|
#ifdef USE_PAM
|
||||||
{
|
{
|
||||||
@ -1280,7 +1294,7 @@ int main (int argc, char **argv)
|
|||||||
(void) signal (SIGHUP, SIG_DFL); /* added this. --marekm */
|
(void) signal (SIGHUP, SIG_DFL); /* added this. --marekm */
|
||||||
(void) signal (SIGINT, SIG_DFL); /* default interrupt signal */
|
(void) signal (SIGINT, SIG_DFL); /* default interrupt signal */
|
||||||
|
|
||||||
if (0 == pwent.pw_uid) {
|
if (0 == pwd->pw_uid) {
|
||||||
SYSLOG ((LOG_NOTICE, "ROOT LOGIN %s", fromhost));
|
SYSLOG ((LOG_NOTICE, "ROOT LOGIN %s", fromhost));
|
||||||
} else if (getdef_bool ("LOG_OK_LOGINS")) {
|
} else if (getdef_bool ("LOG_OK_LOGINS")) {
|
||||||
SYSLOG ((LOG_INFO, "'%s' logged in %s", username, fromhost));
|
SYSLOG ((LOG_INFO, "'%s' logged in %s", username, fromhost));
|
||||||
@ -1288,10 +1302,10 @@ int main (int argc, char **argv)
|
|||||||
closelog ();
|
closelog ();
|
||||||
tmp = getdef_str ("FAKE_SHELL");
|
tmp = getdef_str ("FAKE_SHELL");
|
||||||
if (NULL != tmp) {
|
if (NULL != tmp) {
|
||||||
err = shell (tmp, pwent.pw_shell, newenvp); /* fake shell */
|
err = shell (tmp, pwd->pw_shell, newenvp); /* fake shell */
|
||||||
} else {
|
} else {
|
||||||
/* exec the shell finally */
|
/* exec the shell finally */
|
||||||
err = shell (pwent.pw_shell, (char *) 0, newenvp);
|
err = shell (pwd->pw_shell, (char *) 0, newenvp);
|
||||||
}
|
}
|
||||||
exit (err == ENOENT ? E_CMD_NOTFOUND : E_CMD_NOEXEC);
|
exit (err == ENOENT ? E_CMD_NOTFOUND : E_CMD_NOEXEC);
|
||||||
/* NOT REACHED */
|
/* NOT REACHED */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user