]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
su: log failed logins to btmp
authorKarel Zak <kzak@redhat.com>
Thu, 22 Nov 2012 14:23:14 +0000 (15:23 +0100)
committerKarel Zak <kzak@redhat.com>
Thu, 22 Nov 2012 14:23:14 +0000 (15:23 +0100)
Signed-off-by: Karel Zak <kzak@redhat.com>
Documentation/TODO
login-utils/su-common.c

index e9faa55063ef3771968a93f4f09de6707e3ae19e..04d83eb2123dd887f5430b0a88b1264b4e942fba 100644 (file)
@@ -3,7 +3,7 @@
 
 su
 --
- - log failed attempts to btmp and all attempts to lastlog if authentication by
+ - log all attempts to lastlog if authentication by
    password is required (pam_authenticate()).  See login.c for more details.
    https://bugzilla.redhat.com/show_bug.cgi?id=866682
 
index c5e288d15778aa2e5c09cbf09db026c4f2f2e32d..9daae721ab9003e5b34170086febac2d788e6216 100644 (file)
@@ -54,6 +54,7 @@ enum
 #include <signal.h>
 #include <sys/wait.h>
 #include <syslog.h>
+#include <utmp.h>
 
 #include "err.h"
 
@@ -64,6 +65,7 @@ enum
 #include "pathnames.h"
 #include "env.h"
 #include "closestream.h"
+#include "strutils.h"
 #include "ttyutils.h"
 
 /* name of the pam configuration files. separate configs for su and su -  */
@@ -167,6 +169,45 @@ log_syslog(struct passwd const *pw, bool successful)
   closelog ();
 }
 
+
+/*
+ * Log failed login attempts in _PATH_BTMP if that exists.
+ */
+static void log_btmp(struct passwd const *pw)
+{
+       struct utmp ut;
+       struct timeval tv;
+       const char *tty_name, *tty_num;
+
+       memset(&ut, 0, sizeof(ut));
+
+       strncpy(ut.ut_user,
+               pw && pw->pw_name ? pw->pw_name : "(unknown)",
+               sizeof(ut.ut_user));
+
+       get_terminal_name(NULL, &tty_name, &tty_num);
+       if (tty_num)
+               xstrncpy(ut.ut_id, tty_num, sizeof(ut.ut_id));
+       if (tty_name)
+               xstrncpy(ut.ut_line, tty_name, sizeof(ut.ut_line));
+
+#if defined(_HAVE_UT_TV)       /* in <utmpbits.h> included by <utmp.h> */
+       gettimeofday(&tv, NULL);
+       ut.ut_tv.tv_sec = tv.tv_sec;
+       ut.ut_tv.tv_usec = tv.tv_usec;
+#else
+       {
+               time_t t;
+               time(&t);
+               ut.ut_time = t; /* ut_time is not always a time_t */
+       }
+#endif
+       ut.ut_type = LOGIN_PROCESS;     /* XXX doesn't matter */
+       ut.ut_pid = getpid();
+
+       updwtmp(_PATH_BTMP, &ut);
+}
+
 static struct pam_conv conv =
 {
   misc_conv,
@@ -335,7 +376,7 @@ create_watching_parent (void)
 static void
 authenticate (const struct passwd *pw)
 {
-  const struct passwd *lpw;
+  const struct passwd *lpw = NULL;
   const char *cp, *srvname = NULL;
   int retval;
 
@@ -397,11 +438,18 @@ authenticate (const struct passwd *pw)
 
 done:
 
+  if (lpw && lpw->pw_name)
+     pw = lpw;
+
   log_syslog(pw, !is_pam_failure(retval));
 
   if (is_pam_failure(retval))
     {
-      const char *msg = pam_strerror(pamh, retval);
+      const char *msg;
+
+      log_btmp(pw);
+
+      msg  = pam_strerror(pamh, retval);
       pam_end(pamh, retval);
       sleep (getlogindefs_num ("FAIL_DELAY", 1));
       errx (EXIT_FAILURE, "%s", msg?msg:_("incorrect password"));