]> 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 17:53:53 +0000 (18: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>
configure.ac
lib/log.c
lib/user_busy.c
lib/utmp.c
src/logoutd.c

index 279b649d3685e4ebbddb920e7c7dfac647b8064d..569ed3590b4ed16e57eb95a1045d489bcdd942ed 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 \
-       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 fd7ee13098e0670bf584cf8c828f7df1d6968291..9f54d454743331a1f25815f2f6e617a3875baa18 100644 (file)
--- a/lib/log.c
+++ b/lib/log.c
@@ -28,7 +28,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 3ab26f6f2c61722b399f32adde8f9a08a1f6f3e1..a622376a8abd44682de84bdce51bbbf82c188160 100644 (file)
@@ -51,13 +51,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;
@@ -79,6 +81,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 e7c33a2b2b4c69f106099efab6e01c5f98b94390..528b7d53ef45173fd8277e8be8b0d602171d454a 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>
@@ -59,13 +59,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;
@@ -121,6 +123,7 @@ err_close:
                 username, ftmp));
 }
 
+
 /*
  * get_current_utmp - return the most probable utmp entry for the current
  *                    session
@@ -129,52 +132,51 @@ err_close:
  *     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();
 
@@ -196,13 +198,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;
 
@@ -212,8 +216,7 @@ static void updwtmp (const char *filename, const struct utmp *ut)
                close (fd);
        }
 }
-#endif                         /* ! HAVE_UPDWTMP */
-
+#endif                         /* ! HAVE_UPDWTMPX */
 #endif                         /* ! USE_PAM */
 
 
@@ -235,15 +238,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);
@@ -267,28 +268,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);
-#ifdef HAVE_STRUCT_UTMP_UT_ID
        if (NULL != ut) {
                STRNCPY(utent->ut_id, ut->ut_id);
        } else {
                /* XXX - assumes /dev/tty?? */
                STRNCPY(utent->ut_id, line + 3);
        }
-#endif                         /* HAVE_STRUCT_UTMP_UT_ID */
 #ifdef HAVE_STRUCT_UTMP_UT_NAME
        STRNCPY(utent->ut_name, name);
 #endif                         /* HAVE_STRUCT_UTMP_UT_NAME */
-#ifdef HAVE_STRUCT_UTMP_UT_USER
        STRNCPY(utent->ut_user, name);
-#endif                         /* HAVE_STRUCT_UTMP_UT_USER */
        if (NULL != hostname) {
                struct addrinfo *info = NULL;
 #ifdef HAVE_STRUCT_UTMP_UT_HOST
@@ -340,45 +335,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);
@@ -391,11 +386,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 ();
@@ -406,13 +401,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;
@@ -428,7 +425,7 @@ unsigned long active_sessions_count(const char *name, unsigned long limit)
                        break;
                }
        }
-       endutent ();
+       endutxent();
 
        return count;
 }
index 11ccf05f691dc64a11e298074cd98efadbf829bc..cc7c2013bb43e23bc2e8c3fec6ca85d574b3cfde 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"
@@ -34,14 +34,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];
        char    line[sizeof(ut->ut_line) + 1];
@@ -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;
                        }
@@ -238,7 +242,7 @@ int main (int argc, char **argv)
                        exit (EXIT_SUCCESS);
                }
 
-               endutent ();
+               endutxent();
 
 #ifndef DEBUG
                sleep (60);