]> git.ipfire.org Git - thirdparty/shadow.git/commitdiff
lib/, src/, configure.ac: Use utmpx instead of utmp
authorAlejandro Colomar <alx@kernel.org>
Sat, 17 Feb 2024 14:15:38 +0000 (15:15 +0100)
committerAlejandro Colomar <alx@kernel.org>
Tue, 20 Feb 2024 21:53:54 +0000 (22:53 +0100)
utmpx is specified by POSIX as an XSI extension.  That's more portable
than utmp, which is unavailable for example in musl libc.  The manual
page specifies that in Linux (but it probably means in glibc), utmp and
utmpx (and the functions that use them) are identical, so this commit
shouldn't affect glibc systems.

Assume utmpx is always present.

Also, if utmpx is present, POSIX guarantees that some members exist:

-  ut_user
-  ut_id
-  ut_line
-  ut_pid
-  ut_type
-  ut_tv

So, rely on them unconditionally.

Fixes: 170b76cdd1a9 ("Disable utmpx permanently")
Closes: <https://github.com/shadow-maint/shadow/issues/945>
Reported-by: Firas Khalil Khana <firasuke@gmail.com>
Reported-by: "A. Wilfox" <https://github.com/awilfox>
Tested-by: Firas Khalil Khana <firasuke@gmail.com>
Reviewed-by: Iker Pedrosa <ipedrosa@redhat.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
Cherry-picked-from: 64bcb54fa962 ("lib/, src/, configure.ac: Use utmpx instead of utmp")
Signed-off-by: Alejandro Colomar <alx@kernel.org>
configure.ac
lib/log.c
lib/user_busy.c
lib/utmp.c
src/logoutd.c

index 724dec87ae7256ada3776c58dfe5c6f39453e442..8445e5a184aa7a88479b93dec90ccb6a9a7fc641 100644 (file)
@@ -49,7 +49,7 @@ AC_CHECK_HEADER([shadow.h],,[AC_MSG_ERROR([You need a libc with shadow.h])])
 AC_CHECK_FUNCS(arc4random_buf futimes \
        getentropy getrandom getspnam getusershell \
        initgroups lckpwdf lutimes mempcpy \
-       setgroups updwtmp updwtmpx innetgr \
+       setgroups updwtmpx innetgr \
        getspnam_r \
        rpmatch \
        memset_explicit explicit_bzero stpecpy stpeprintf)
@@ -57,17 +57,13 @@ AC_SYS_LARGEFILE
 
 dnl Checks for typedefs, structures, and compiler characteristics.
 
-AC_CHECK_MEMBERS([struct utmp.ut_type,
-                  struct utmp.ut_id,
-                  struct utmp.ut_name,
-                  struct utmp.ut_user,
-                  struct utmp.ut_host,
-                  struct utmp.ut_syslen,
-                  struct utmp.ut_addr,
-                  struct utmp.ut_addr_v6,
-                  struct utmp.ut_time,
-                  struct utmp.ut_xtime,
-                  struct utmp.ut_tv],,,[[#include <utmp.h>]])
+AC_CHECK_MEMBERS([struct utmpx.ut_name,
+                  struct utmpx.ut_host,
+                  struct utmpx.ut_syslen,
+                  struct utmpx.ut_addr,
+                  struct utmpx.ut_addr_v6,
+                  struct utmpx.ut_time,
+                  struct utmpx.ut_xtime],,,[[#include <utmpx.h>]])
 
 dnl Checks for library functions.
 AC_TYPE_GETGROUPS
index cc38d6dc5fbe506520c769fca2c7e8f42a9026e8..e1fa4daf6eb03c6e1cfdb9c753a48bf08fd0aa2e 100644 (file)
--- a/lib/log.c
+++ b/lib/log.c
@@ -24,7 +24,7 @@
  *
  *     A "last login" entry is created for the user being logged in.  The
  *     UID is extracted from the global (struct passwd) entry and the
- *     TTY information is gotten from the (struct utmp).
+ *     TTY information is gotten from the (struct utmpx).
  */
 void dolastlog (
        struct lastlog *ll,
index eef645636bee8cf93d63c8bb72caf5a6a7579cd1..47e9c4834f5646be9f1447a026c80b682c41805b 100644 (file)
@@ -49,13 +49,15 @@ int user_busy (const char *name, uid_t uid)
 #endif                         /* !__linux__ */
 }
 
+
 #ifndef __linux__
-static int user_busy_utmp (const char *name)
+static int
+user_busy_utmp(const char *name)
 {
-       struct utmp *utent;
+       struct utmp *utent;
 
-       setutent ();
-       while ((utent = getutent ()) != NULL)
+       setutxent();
+       while ((utent = getutxent()) != NULL)
        {
                if (utent->ut_type != USER_PROCESS) {
                        continue;
@@ -77,6 +79,7 @@ static int user_busy_utmp (const char *name)
 }
 #endif                         /* !__linux__ */
 
+
 #ifdef __linux__
 #ifdef ENABLE_SUBIDS
 #define in_parentuid_range(uid) ((uid) >= parentuid && (uid) < parentuid + range)
index 99833c4f3bf4a7589b891478cd641961b6848795..95ff1dbbaa3551107b79a3b7b6c224489747f6aa 100644 (file)
@@ -13,7 +13,7 @@
 #include "prototypes.h"
 #include "getdef.h"
 
-#include <utmp.h>
+#include <utmpx.h>
 #include <assert.h>
 #include <sys/param.h>
 #include <sys/types.h>
@@ -55,13 +55,15 @@ static bool is_my_tty (const char tty[UT_LINESIZE])
        return strcmp (full_tty, tmptty) == 0;
 }
 
+
 /*
  * failtmp - update the cumulative failure log
  *
- *     failtmp updates the (struct utmp) formatted failure log which
+ *     failtmp updates the (struct utmpx) formatted failure log which
  *     maintains a record of all login failures.
  */
-static void failtmp (const char *username, const struct utmp *failent)
+static void
+failtmp(const char *username, const struct utmpx *failent)
 {
        const char *ftmp;
        int fd;
@@ -106,6 +108,7 @@ static void failtmp (const char *username, const struct utmp *failent)
        }
 }
 
+
 /*
  * get_current_utmp - return the most probable utmp entry for the current
  *                    session
@@ -114,52 +117,51 @@ static void failtmp (const char *username, const struct utmp *failent)
  *     The line entered by the *getty / telnetd, etc. should also match
  *     the current terminal.
  *
- *     When an entry is returned by get_current_utmp, and if the utmp
+ *     When an entry is returned by get_current_utmp, and if the utmpx
  *     structure has a ut_id field, this field should be used to update
  *     the entry information.
  *
  *     Return NULL if no entries exist in utmp for the current process.
  */
-static
-/*@null@*/ /*@only@*/struct utmp *get_current_utmp (void)
+static /*@null@*/ /*@only@*/struct utmpx *
+get_current_utmp(void)
 {
-       struct utmp *ut;
-       struct utmp *ret = NULL;
+       struct utmp *ut;
+       struct utmp *ret = NULL;
 
-       setutent ();
+       setutxent();
 
        /* First, try to find a valid utmp entry for this process.  */
-       while ((ut = getutent ()) != NULL) {
+       while ((ut = getutxent()) != NULL) {
                if (   (ut->ut_pid == getpid ())
-#ifdef HAVE_STRUCT_UTMP_UT_ID
                    && ('\0' != ut->ut_id[0])
-#endif
-#ifdef HAVE_STRUCT_UTMP_UT_TYPE
                    && (   (LOGIN_PROCESS == ut->ut_type)
                        || (USER_PROCESS  == ut->ut_type))
-#endif
                    /* A process may have failed to close an entry
                     * Check if this entry refers to the current tty */
-                   && is_my_tty (ut->ut_line)) {
+                   && is_my_tty(ut->ut_line))
+               {
                        break;
                }
        }
 
        if (NULL != ut) {
-               ret = XMALLOC(1, struct utmp);
+               ret = XMALLOC(1, struct utmpx);
                memcpy (ret, ut, sizeof (*ret));
        }
 
-       endutent ();
+       endutxent();
 
        return ret;
 }
 
-int get_session_host (char **out)
+
+int
+get_session_host(char **out)
 {
-       char *hostname = NULL;
-       struct utmp *ut = NULL;
-       int ret = 0;
+       int           ret = 0;
+       char          *hostname;
+       struct utmpx  *ut;
 
        ut = get_current_utmp();
 
@@ -182,13 +184,15 @@ int get_session_host (char **out)
        return ret;
 }
 
+
 #ifndef USE_PAM
 /*
- * Some systems already have updwtmp() and possibly updwtmpx().  Others
+ * Some systems already have updwtmpx().  Others
  * don't, so we re-implement these functions if necessary.
  */
-#ifndef HAVE_UPDWTMP
-static void updwtmp (const char *filename, const struct utmp *ut)
+#ifndef HAVE_UPDWTMPX
+static void
+updwtmpx(const char *filename, const struct utmpx *ut)
 {
        int fd;
 
@@ -198,8 +202,7 @@ static void updwtmp (const char *filename, const struct utmp *ut)
                close (fd);
        }
 }
-#endif                         /* ! HAVE_UPDWTMP */
-
+#endif                         /* ! HAVE_UPDWTMPX */
 #endif                         /* ! USE_PAM */
 
 
@@ -221,15 +224,13 @@ static void updwtmp (const char *filename, const struct utmp *ut)
  *
  *     The returned structure shall be freed by the caller.
  */
-static
-/*@only@*/struct utmp *prepare_utmp (const char *name,
-                                     const char *line,
-                                     const char *host,
-                                     /*@null@*/const struct utmp *ut)
+static /*@only@*/struct utmpx *
+prepare_utmp(const char *name, const char *line, const char *host,
+             /*@null@*/const struct utmpx *ut)
 {
-       struct timeval tv;
-       char *hostname = NULL;
-       struct utmp *utent;
+       char            *hostname = NULL;
+       struct utmpx    *utent;
+       struct timeval  tv;
 
        assert (NULL != name);
        assert (NULL != line);
@@ -254,28 +255,22 @@ static
        }
 
 
-       utent = XCALLOC (1, struct utmp);
+       utent = XCALLOC(1, struct utmpx);
 
 
-#ifdef HAVE_STRUCT_UTMP_UT_TYPE
        utent->ut_type = USER_PROCESS;
-#endif                         /* HAVE_STRUCT_UTMP_UT_TYPE */
        utent->ut_pid = getpid ();
        strncpy (utent->ut_line, line,      sizeof (utent->ut_line) - 1);
-#ifdef HAVE_STRUCT_UTMP_UT_ID
        if (NULL != ut) {
                strncpy (utent->ut_id, ut->ut_id, sizeof (utent->ut_id));
        } else {
                /* XXX - assumes /dev/tty?? */
                strncpy (utent->ut_id, line + 3, sizeof (utent->ut_id) - 1);
        }
-#endif                         /* HAVE_STRUCT_UTMP_UT_ID */
 #ifdef HAVE_STRUCT_UTMP_UT_NAME
        strncpy (utent->ut_name, name,      sizeof (utent->ut_name));
 #endif                         /* HAVE_STRUCT_UTMP_UT_NAME */
-#ifdef HAVE_STRUCT_UTMP_UT_USER
        strncpy (utent->ut_user, name,      sizeof (utent->ut_user) - 1);
-#endif                         /* HAVE_STRUCT_UTMP_UT_USER */
        if (NULL != hostname) {
                struct addrinfo *info = NULL;
 #ifdef HAVE_STRUCT_UTMP_UT_HOST
@@ -327,45 +322,45 @@ static
 #ifdef HAVE_STRUCT_UTMP_UT_XTIME
                utent->ut_xtime = tv.tv_usec;
 #endif                         /* HAVE_STRUCT_UTMP_UT_XTIME */
-#ifdef HAVE_STRUCT_UTMP_UT_TV
                utent->ut_tv.tv_sec  = tv.tv_sec;
                utent->ut_tv.tv_usec = tv.tv_usec;
-#endif                         /* HAVE_STRUCT_UTMP_UT_TV */
        }
 
        return utent;
 }
 
+
 /*
  * setutmp - Update an entry in utmp and log an entry in wtmp
  *
  *     Return 1 on failure and 0 on success.
  */
-static int setutmp (struct utmp *ut)
+static int
+setutmp(struct utmpx *ut)
 {
        int err = 0;
 
        assert (NULL != ut);
 
-       setutent ();
-       if (pututline (ut) == NULL) {
+       setutxent();
+       if (pututxline(ut) == NULL) {
                err = 1;
        }
-       endutent ();
+       endutxent();
 
 #ifndef USE_PAM
        /* This is done by pam_lastlog */
-       updwtmp (_WTMP_FILE, ut);
+       updwtmpx(_WTMP_FILE, ut);
 #endif                         /* ! USE_PAM */
 
        return err;
 }
 
-int update_utmp (const char *user,
-                 const char *tty,
-                 const char *host)
+
+int
+update_utmp(const char *user, const char *tty, const char *host)
 {
-       struct utmp *utent, *ut;
+       struct utmp *utent, *ut;
 
        utent = get_current_utmp ();
        ut = prepare_utmp  (user, tty, host, utent);
@@ -380,11 +375,11 @@ int update_utmp (const char *user,
        return 0;
 }
 
-void record_failure(const char *failent_user,
-                    const char *tty,
-                    const char *hostname)
+
+void
+record_failure(const char *failent_user, const char *tty, const char *hostname)
 {
-       struct utmp *utent, *failent;
+       struct utmp *utent, *failent;
 
        if (getdef_str ("FTMP_FILE") != NULL) {
                utent = get_current_utmp ();
@@ -395,13 +390,15 @@ void record_failure(const char *failent_user,
        }
 }
 
-unsigned long active_sessions_count(const char *name, unsigned long limit)
+
+unsigned long
+active_sessions_count(const char *name, unsigned long limit)
 {
-       struct utmp *ut;
-       unsigned long count = 0;
+       struct utmpx   *ut;
+       unsigned long  count = 0;
 
-       setutent ();
-       while ((ut = getutent ()))
+       setutxent();
+       while ((ut = getutxent()))
        {
                if (USER_PROCESS != ut->ut_type) {
                        continue;
@@ -417,7 +414,7 @@ unsigned long active_sessions_count(const char *name, unsigned long limit)
                        break;
                }
        }
-       endutent ();
+       endutxent();
 
        return count;
 }
index 3a833d88b455b63db3dd21836dfcb852084f28b9..9a5d11e8658e5c5b755ee045710e061c65f0eea1 100644 (file)
@@ -15,7 +15,7 @@
 #include <stdio.h>
 #include <sys/stat.h>
 #include <sys/types.h>
-#include <utmp.h>
+#include <utmpx.h>
 #include "defines.h"
 #include "prototypes.h"
 #include "shadowlog.h"
@@ -32,14 +32,17 @@ const char *Prog;
 #define HUP_MESG_FILE "/etc/logoutd.mesg"
 #endif
 
+
 /* local function prototypes */
-static int check_login (const struct utmp *ut);
+static int check_login (const struct utmpx *ut);
 static void send_mesg_to_tty (int tty_fd);
 
+
 /*
- * check_login - check if user (struct utmp) allowed to stay logged in
+ * check_login - check if user (struct utmpx) allowed to stay logged in
  */
-static int check_login (const struct utmp *ut)
+static int
+check_login(const struct utmpx *ut)
 {
        char user[sizeof (ut->ut_user) + 1];
        time_t now;
@@ -112,16 +115,17 @@ static void send_mesg_to_tty (int tty_fd)
  *     utmp file is periodically scanned and offending users are logged
  *     off from the system.
  */
-int main (int argc, char **argv)
+int
+main(int argc, char **argv)
 {
-       int i;
-       int status;
-       pid_t pid;
+       int    i;
+       int    status;
+       pid_t  pid;
 
-       struct utmp *ut;
-       char user[sizeof (ut->ut_user) + 1];    /* terminating NUL */
-       char tty_name[sizeof (ut->ut_line) + 6];        /* /dev/ + NUL */
-       int tty_fd;
+       struct utmp *ut;
+       char          user[sizeof (ut->ut_user) + 1];   /* terminating NUL */
+       char          tty_name[sizeof (ut->ut_line) + 6];       /* /dev/ + NUL */
+       int           tty_fd;
 
        if (1 != argc) {
                (void) fputs (_("Usage: logoutd\n"), stderr);
@@ -169,14 +173,14 @@ int main (int argc, char **argv)
                 * Attempt to re-open the utmp file. The file is only
                 * open while it is being used.
                 */
-               setutent ();
+               setutxent();
 
                /*
                 * Read all of the entries in the utmp file. The entries
                 * for login sessions will be checked to see if the user
                 * is permitted to be signed on at this time.
                 */
-               while ((ut = getutent ()) != NULL) {
+               while ((ut = getutxent()) != NULL) {
                        if (ut->ut_type != USER_PROCESS) {
                                continue;
                        }
@@ -239,7 +243,7 @@ int main (int argc, char **argv)
                        exit (EXIT_SUCCESS);
                }
 
-               endutent ();
+               endutxent();
 
 #ifndef DEBUG
                sleep (60);