From: Alejandro Colomar Date: Sat, 17 Feb 2024 14:15:38 +0000 (+0100) Subject: lib/, src/, configure.ac: Use utmpx instead of utmp X-Git-Tag: 4.15.0-rc3~9 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=64bcb54fa9621a73075249c75081b056512baa52;p=thirdparty%2Fshadow.git lib/, src/, configure.ac: Use utmpx instead of utmp 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: Reported-by: Firas Khalil Khana Reported-by: "A. Wilfox" Tested-by: Firas Khalil Khana Reviewed-by: Iker Pedrosa Signed-off-by: Alejandro Colomar --- diff --git a/configure.ac b/configure.ac index 279b649d3..569ed3590 100644 --- a/configure.ac +++ b/configure.ac @@ -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 ]]) +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 ]]) dnl Checks for library functions. AC_TYPE_GETGROUPS diff --git a/lib/log.c b/lib/log.c index fd7ee1309..9f54d4547 100644 --- 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, diff --git a/lib/user_busy.c b/lib/user_busy.c index 3ab26f6f2..a622376a8 100644 --- a/lib/user_busy.c +++ b/lib/user_busy.c @@ -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 utmpx *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) diff --git a/lib/utmp.c b/lib/utmp.c index e7c33a2b2..528b7d53e 100644 --- a/lib/utmp.c +++ b/lib/utmp.c @@ -13,7 +13,7 @@ #include "prototypes.h" #include "getdef.h" -#include +#include #include #include #include @@ -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 utmpx *ut; + struct utmpx *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 utmpx *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 utmpx *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; } diff --git a/src/logoutd.c b/src/logoutd.c index 11ccf05f6..cc7c2013b 100644 --- a/src/logoutd.c +++ b/src/logoutd.c @@ -15,7 +15,7 @@ #include #include #include -#include +#include #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 utmpx *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);