summaryrefslogtreecommitdiffstats
path: root/src/login.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/login.c')
-rw-r--r--src/login.c267
1 files changed, 116 insertions, 151 deletions
diff --git a/src/login.c b/src/login.c
index 0048281..9fed7b3 100644
--- a/src/login.c
+++ b/src/login.c
@@ -14,7 +14,9 @@
#include <errno.h>
#include <grp.h>
#ifndef USE_PAM
+#ifdef ENABLE_LASTLOG
#include <lastlog.h>
+#endif /* ENABLE_LASTLOG */
#endif /* !USE_PAM */
#include <pwd.h>
#include <signal.h>
@@ -22,15 +24,24 @@
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <assert.h>
+
+#include "alloc.h"
+#include "attr.h"
+#include "chkname.h"
#include "defines.h"
#include "faillog.h"
#include "failure.h"
#include "getdef.h"
+#include "memzero.h"
#include "prototypes.h"
#include "pwauth.h"
/*@-exitarg@*/
#include "exitcodes.h"
#include "shadowlog.h"
+#include "string/sprintf.h"
+#include "string/strftime.h"
+#include "string/strtcpy.h"
+
#ifdef USE_PAM
#include "pam_defs.h"
@@ -60,14 +71,16 @@ static pam_handle_t *pamh = NULL;
/*
* Global variables
*/
-const char *Prog;
+static const char Prog[] = "login";
static const char *hostname = "";
static /*@null@*/ /*@only@*/char *username = NULL;
static int reason = PW_LOGIN;
#ifndef USE_PAM
+#ifdef ENABLE_LASTLOG
static struct lastlog ll;
+#endif /* ENABLE_LASTLOG */
#endif /* !USE_PAM */
static bool pflg = false;
static bool fflg = false;
@@ -89,7 +102,6 @@ static char tmsg[256];
extern char **newenvp;
extern size_t newenvc;
-extern char **environ;
#ifndef ALARM
#define ALARM 60
@@ -104,15 +116,6 @@ static void usage (void);
static void setup_tty (void);
static void process_flags (int argc, char *const *argv);
static /*@observer@*/const char *get_failent_user (/*@returned@*/const char *user);
-static void update_utmp (const char *user,
- const char *tty,
- const char *host,
-#ifdef USE_UTMPX
- /*@null@*/const struct utmpx *utent
-#else
- /*@null@*/const struct utmp *utent
-#endif
- );
#ifndef USE_PAM
static struct faillog faillog;
@@ -125,6 +128,7 @@ static void get_pam_user (char **ptr_pam_user);
static void init_env (void);
static void alarm_handler (int);
+static void exit_handler (int);
/*
* usage - print login command usage and exit
@@ -172,10 +176,10 @@ static void setup_tty (void)
#endif
/* leave these values unchanged if not specified in login.defs */
- erasechar = getdef_num ("ERASECHAR", (int) termio.c_cc[VERASE]);
- killchar = getdef_num ("KILLCHAR", (int) termio.c_cc[VKILL]);
- termio.c_cc[VERASE] = (cc_t) erasechar;
- termio.c_cc[VKILL] = (cc_t) killchar;
+ erasechar = getdef_num ("ERASECHAR", termio.c_cc[VERASE]);
+ killchar = getdef_num ("KILLCHAR", termio.c_cc[VKILL]);
+ termio.c_cc[VERASE] = erasechar;
+ termio.c_cc[VKILL] = killchar;
/* Make sure the values were valid.
* getdef_num cannot validate this.
*/
@@ -396,13 +400,18 @@ static void init_env (void)
#endif /* !USE_PAM */
}
-
-static void alarm_handler (unused int sig)
+static void exit_handler (MAYBE_UNUSED int sig)
{
- write (STDERR_FILENO, tmsg, strlen (tmsg));
_exit (0);
}
+static void alarm_handler (MAYBE_UNUSED int sig)
+{
+ write_full(STDERR_FILENO, tmsg, strlen(tmsg));
+ signal(SIGALRM, exit_handler);
+ alarm(2);
+}
+
#ifdef USE_PAM
/*
* get_pam_user - Get the username according to PAM
@@ -411,17 +420,17 @@ static void alarm_handler (unused int sig)
*/
static void get_pam_user (char **ptr_pam_user)
{
- int retcode;
- void *ptr_user;
+ int retcode;
+ const void *ptr_user;
assert (NULL != ptr_pam_user);
- retcode = pam_get_item (pamh, PAM_USER, (const void **)&ptr_user);
+ retcode = pam_get_item (pamh, PAM_USER, &ptr_user);
PAM_FAIL_CHECK;
free (*ptr_pam_user);
if (NULL != ptr_user) {
- *ptr_pam_user = xstrdup ((const char *)ptr_user);
+ *ptr_pam_user = xstrdup (ptr_user);
} else {
*ptr_pam_user = NULL;
}
@@ -430,7 +439,7 @@ static void get_pam_user (char **ptr_pam_user)
/*
* get_failent_user - Return a string that can be used to log failure
- * from an user.
+ * from a user.
*
* This will be either the user argument, or "UNKNOWN".
*
@@ -453,38 +462,6 @@ static /*@observer@*/const char *get_failent_user (/*@returned@*/const char *use
}
/*
- * update_utmp - Update or create an utmp entry in utmp, wtmp, utmpw, and
- * wtmpx
- *
- * utent should be the utmp entry returned by get_current_utmp (or
- * NULL).
- */
-static void update_utmp (const char *user,
- const char *tty,
- const char *host,
-#ifdef USE_UTMPX
- /*@null@*/const struct utmpx *utent
-#else
- /*@null@*/const struct utmp *utent
-#endif
- )
-{
-#ifdef USE_UTMPX
- struct utmpx *utx = prepare_utmpx (user, tty, host, utent);
-#else
- struct utmp *ut = prepare_utmp (user, tty, host, utent);
-#endif /* USE_UTMPX */
-
-#ifndef USE_UTMPX
- (void) setutmp (ut); /* make entry in the utmp & wtmp files */
- free (ut);
-#else
- (void) setutmpx (utx); /* make entry in the utmpx & wtmpx files */
- free (utx);
-#endif /* USE_UTMPX */
-}
-
-/*
* login - create a new login session for a user
*
* login is typically called by getty as the second step of a
@@ -503,42 +480,36 @@ static void update_utmp (const char *user,
*/
int main (int argc, char **argv)
{
- const char *tmptty;
- char tty[BUFSIZ];
-
-#ifdef RLOGIN
- char term[128] = "";
-#endif /* RLOGIN */
-#if !defined(USE_PAM)
- char ptime[80];
-#endif
- unsigned int delay;
- unsigned int retries;
- bool subroot = false;
-#ifndef USE_PAM
+ int err;
+ bool subroot = false;
+ char **envp = environ;
+ char *host = NULL;
+ char tty[BUFSIZ];
+ char fromhost[512];
+ const char *failent_user;
+ const char *tmptty;
+ const char *cp;
+ const char *tmp;
+ unsigned int delay;
+ unsigned int retries;
+ unsigned int timeout;
+ struct passwd *pwd = NULL;
+
+#if defined(USE_PAM)
+ int retcode;
+ char *pam_user = NULL;
+ pid_t child;
+#else
bool is_console;
+ struct spwd *spwd = NULL;
+# if defined(ENABLE_LASTLOG)
+ char ptime[80];
+# endif
#endif
- int err;
- unsigned int timeout;
- const char *cp;
- const char *tmp;
- char fromhost[512];
- struct passwd *pwd = NULL;
- char **envp = environ;
- const char *failent_user;
-#ifdef USE_UTMPX
- /*@null@*/struct utmpx *utent;
-#else
- /*@null@*/struct utmp *utent;
+#if defined(RLOGIN)
+ char term[128] = "";
#endif
-#ifdef USE_PAM
- int retcode;
- pid_t child;
- char *pam_user = NULL;
-#else
- struct spwd *spwd = NULL;
-#endif
/*
* Some quick initialization.
*/
@@ -552,7 +523,6 @@ int main (int argc, char **argv)
initenv ();
amroot = (getuid () == 0);
- Prog = Basename (argv[0]);
log_set_progname(Prog);
log_set_logfd(stderr);
@@ -567,25 +537,23 @@ int main (int argc, char **argv)
exit (1); /* must be a terminal */
}
- utent = get_current_utmp ();
+ err = get_session_host(&host);
/*
* Be picky if run by normal users (possible if installed setuid
- * root), but not if run by root. This way it still allows logins
- * even if your getty is broken, or if something corrupts utmp,
- * but users must "exec login" which will use the existing utmp
- * entry (will not overwrite remote hostname). --marekm
+ * root), but not if run by root.
*/
- if (!amroot && (NULL == utent)) {
- (void) puts (_("No utmp entry. You must exec \"login\" from the lowest level \"sh\""));
+ if (!amroot && (err != 0)) {
+ SYSLOG ((LOG_ERR,
+ "No session entry, error %d. You must exec \"login\" from the lowest level \"sh\"",
+ err));
exit (1);
}
- /* NOTE: utent might be NULL afterwards */
tmptty = ttyname (0);
if (NULL == tmptty) {
tmptty = "UNKNOWN";
}
- STRFCPY (tty, tmptty);
+ STRTCPY(tty, tmptty);
#ifndef USE_PAM
is_console = console (tty);
@@ -606,10 +574,14 @@ int main (int argc, char **argv)
}
#ifdef RLOGIN
if (rflg) {
+ size_t max_size;
+
+ max_size = login_name_max_size();
assert (NULL == username);
- username = xmalloc (USER_NAME_MAX_LENGTH + 1);
- username[USER_NAME_MAX_LENGTH] = '\0';
- if (do_rlogin (hostname, username, USER_NAME_MAX_LENGTH, term, sizeof term)) {
+ username = XMALLOC(max_size, char);
+ username[max_size - 1] = '\0';
+ if (do_rlogin(hostname, username, max_size, term, sizeof(term)))
+ {
preauth_flag = true;
} else {
free (username);
@@ -618,7 +590,7 @@ int main (int argc, char **argv)
}
#endif /* RLOGIN */
- OPENLOG ("login");
+ OPENLOG (Prog);
setup_tty ();
@@ -674,27 +646,23 @@ int main (int argc, char **argv)
if (rflg || hflg) {
cp = hostname;
-#if defined(HAVE_STRUCT_UTMP_UT_HOST) || defined(USE_UTMPX)
- } else if ((NULL != utent) && ('\0' != utent->ut_host[0])) {
- cp = utent->ut_host;
-#endif /* HAVE_STRUCT_UTMP_UT_HOST */
+ } else if ((host != NULL) && (host[0] != '\0')) {
+ cp = host;
} else {
cp = "";
}
if ('\0' != *cp) {
- snprintf (fromhost, sizeof fromhost,
- " on '%.100s' from '%.200s'", tty, cp);
+ SNPRINTF(fromhost, " on '%.100s' from '%.200s'", tty, cp);
} else {
- snprintf (fromhost, sizeof fromhost,
- " on '%.100s'", tty);
+ SNPRINTF(fromhost, " on '%.100s'", tty);
}
+ free(host);
top:
/* only allow ALARM sec. for login */
timeout = getdef_unum ("LOGIN_TIMEOUT", ALARM);
- snprintf (tmsg, sizeof tmsg,
- _("\nLogin timed out after %u seconds.\n"), timeout);
+ SNPRINTF(tmsg, _("\nLogin timed out after %u seconds.\n"), timeout);
(void) signal (SIGALRM, alarm_handler);
if (timeout > 0) {
(void) alarm (timeout);
@@ -705,7 +673,7 @@ int main (int argc, char **argv)
retries = getdef_unum ("LOGIN_RETRIES", RETRIES);
#ifdef USE_PAM
- retcode = pam_start ("login", username, &conv, &pamh);
+ retcode = pam_start (Prog, username, &conv, &pamh);
if (retcode != PAM_SUCCESS) {
fprintf (stderr,
_("login: PAM Failure, aborting: %s\n"),
@@ -733,18 +701,15 @@ int main (int argc, char **argv)
#endif
/* if fflg, then the user has already been authenticated */
if (!fflg) {
- unsigned int failcount = 0;
- char hostn[256];
- char loginprompt[256]; /* That's one hell of a prompt :) */
+ char hostn[256];
+ char loginprompt[256]; //That's one hell of a prompt :)
+ unsigned int failcount = 0;
/* Make the login prompt look like we want it */
if (gethostname (hostn, sizeof (hostn)) == 0) {
- snprintf (loginprompt,
- sizeof (loginprompt),
- _("%s login: "), hostn);
+ SNPRINTF(loginprompt, _("%s login: "), hostn);
} else {
- strncpy (loginprompt, _("login: "),
- sizeof (loginprompt));
+ STRTCPY(loginprompt, _("login: "));
}
retcode = pam_set_item (pamh, PAM_USER_PROMPT, loginprompt);
@@ -919,14 +884,17 @@ int main (int argc, char **argv)
failed = false; /* haven't failed authentication yet */
if (NULL == username) { /* need to get a login id */
+ size_t max_size;
+
+ max_size = login_name_max_size();
if (subroot) {
closelog ();
exit (1);
}
preauth_flag = false;
- username = xmalloc (USER_NAME_MAX_LENGTH + 1);
- username[USER_NAME_MAX_LENGTH] = '\0';
- login_prompt (_("\n%s login: "), username, USER_NAME_MAX_LENGTH);
+ username = XMALLOC(max_size, char);
+ username[max_size - 1] = '\0';
+ login_prompt(username, max_size);
if ('\0' == username[0]) {
/* Prompt for a new login */
@@ -956,7 +924,8 @@ int main (int argc, char **argv)
}
if (strcmp (user_passwd, "") == 0) {
- char *prevent_no_auth = getdef_str("PREVENT_NO_AUTH");
+ const char *prevent_no_auth = getdef_str("PREVENT_NO_AUTH");
+
if (prevent_no_auth == NULL) {
prevent_no_auth = "superuser";
}
@@ -992,7 +961,7 @@ int main (int argc, char **argv)
goto auth_ok;
}
- if (pw_auth (user_passwd, username, reason, (char *) 0) == 0) {
+ if (pw_auth (user_passwd, username, reason, NULL) == 0) {
goto auth_ok;
}
@@ -1035,23 +1004,9 @@ int main (int argc, char **argv)
if ((NULL != pwd) && getdef_bool ("FAILLOG_ENAB")) {
failure (pwd->pw_uid, tty, &faillog);
}
- if (getdef_str ("FTMP_FILE") != NULL) {
-#ifdef USE_UTMPX
- struct utmpx *failent =
- prepare_utmpx (failent_user,
- tty,
- /* FIXME: or fromhost? */hostname,
- utent);
-#else /* !USE_UTMPX */
- struct utmp *failent =
- prepare_utmp (failent_user,
- tty,
- hostname,
- utent);
-#endif /* !USE_UTMPX */
- failtmp (failent_user, failent);
- free (failent);
- }
+#ifndef ENABLE_LOGIND
+ record_failure(failent_user, tty, hostname);
+#endif /* ENABLE_LOGIND */
retries--;
if (retries <= 0) {
@@ -1067,7 +1022,7 @@ int main (int argc, char **argv)
* all). --marekm
*/
if (user_passwd[0] == '\0') {
- pw_auth ("!", username, reason, (char *) 0);
+ pw_auth ("!", username, reason, NULL);
}
/*
@@ -1107,7 +1062,7 @@ int main (int argc, char **argv)
* by Ivan Nejgebauer <ian@unsux.ns.ac.yu>. --marekm
*/
if ( getdef_bool ("PORTTIME_CHECKS_ENAB")
- && !isttytime (username, tty, time ((time_t *) 0))) {
+ && !isttytime (username, tty, time (NULL))) {
SYSLOG ((LOG_WARN, "invalid login time for '%s'%s",
username, fromhost));
closelog ();
@@ -1151,11 +1106,13 @@ int main (int argc, char **argv)
#endif /* WITH_AUDIT */
#ifndef USE_PAM /* pam_lastlog handles this */
+#ifdef ENABLE_LASTLOG
if ( getdef_bool ("LASTLOG_ENAB")
&& pwd->pw_uid <= (uid_t) getdef_ulong ("LASTLOG_UID_MAX", 0xFFFFFFFFUL)) {
/* give last login and log this one */
dolastlog (&ll, pwd, tty, hostname);
}
+#endif /* ENABLE_LASTLOG */
#endif
#ifndef USE_PAM /* PAM handles this as well */
@@ -1220,11 +1177,16 @@ int main (int argc, char **argv)
}
}
+#ifndef ENABLE_LOGIND
/*
* The utmp entry needs to be updated to indicate the new status
* of the session, the new PID and SID.
*/
- update_utmp (username, tty, hostname, utent);
+ err = update_utmp (username, tty, hostname);
+ if (err != 0) {
+ SYSLOG ((LOG_WARN, "Unable to update utmp entry for %s", username));
+ }
+#endif /* ENABLE_LOGIND */
/* The pwd and spwd entries for the user have been copied.
*
@@ -1289,14 +1251,16 @@ int main (int argc, char **argv)
username, (int) faillog.fail_cnt));
}
}
+#ifdef ENABLE_LASTLOG
if ( getdef_bool ("LASTLOG_ENAB")
&& pwd->pw_uid <= (uid_t) getdef_ulong ("LASTLOG_UID_MAX", 0xFFFFFFFFUL)
- && (ll.ll_time != 0)) {
- time_t ll_time = ll.ll_time;
+ && (ll.ll_time != 0))
+ {
+ time_t ll_time = ll.ll_time;
+ struct tm tm;
- (void) strftime (ptime, sizeof (ptime),
- "%a %b %e %H:%M:%S %z %Y",
- localtime (&ll_time));
+ localtime_r(&ll_time, &tm);
+ STRFTIME(ptime, "%a %b %e %H:%M:%S %z %Y", &tm);
printf (_("Last login: %s on %s"),
ptime, ll.ll_line);
#ifdef HAVE_LL_HOST /* __linux__ || SUN4 */
@@ -1307,6 +1271,7 @@ int main (int argc, char **argv)
#endif
printf (".\n");
}
+#endif /* ENABLE_LASTLOG */
agecheck (spwd);
mailcheck (); /* report on the status of mail */
@@ -1334,7 +1299,7 @@ int main (int argc, char **argv)
err = shell (tmp, pwd->pw_shell, newenvp); /* fake shell */
} else {
/* exec the shell finally */
- err = shell (pwd->pw_shell, (char *) 0, newenvp);
+ err = shell (pwd->pw_shell, NULL, newenvp);
}
return ((err == ENOENT) ? E_CMD_NOTFOUND : E_CMD_NOEXEC);