From 9b70b047ad199d6ba6002e616da115177ecb7ac6 Mon Sep 17 00:00:00 2001 From: Dan Cross Date: Mon, 11 Jan 2021 02:58:58 +0000 Subject: [PATCH] finger: Fix `lastlogx` logic. Use of `lastlogx` in finger to retrieve last login times was incorrectly trying to make use of `utmpx` and `wtmpx` interfaces. Change it to use `getlastlogx` interfaces. Note that had this code ever succeeded (which, admittedly it couldn't have since it used the interface incorrectly), it would have lead to a NULL pointer dereference. Signed-off-by: Dan Cross --- usr.bin/finger/finger.h | 6 ++++-- usr.bin/finger/util.c | 26 +++++++++++++------------- 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/usr.bin/finger/finger.h b/usr.bin/finger/finger.h index 8ebec5cacc..72feb3e0fd 100644 --- a/usr.bin/finger/finger.h +++ b/usr.bin/finger/finger.h @@ -34,6 +34,8 @@ * $DragonFly: src/usr.bin/finger/finger.h,v 1.2 2003/06/17 04:29:26 dillon Exp $ */ +#include + typedef struct person { uid_t uid; /* user id */ char *dir; /* user's home directory */ @@ -56,8 +58,8 @@ typedef struct where { short writable; /* tty is writable */ time_t loginat; /* time of (last) login */ time_t idletime; /* how long idle (if logged in) */ - char *tty; /* null terminated tty line */ - char *host; /* null terminated remote host name */ + char tty[_UTX_LINESIZE + 1]; /* null terminated tty line */ + char host[_UTX_HOSTSIZE + 1]; /* null terminated remote host name */ } WHERE; #define UNPRIV_NAME "nobody" /* Preferred privilege level */ diff --git a/usr.bin/finger/util.c b/usr.bin/finger/util.c index 49fd69cb77..a308f1aafb 100644 --- a/usr.bin/finger/util.c +++ b/usr.bin/finger/util.c @@ -100,18 +100,18 @@ void enter_lastlog(PERSON *pn) { WHERE *w; - struct utmpx *ut = NULL; char doit = 0; + struct lastlogx ll; - if (setutxdb(UTX_DB_LASTLOGX, NULL) == 0) - ut = getutxuser(pn->name); + memset(&ll, 0, sizeof(ll)); + getlastlogx(_PATH_LASTLOGX, pn->uid, &ll); if ((w = pn->whead) == NULL) doit = 1; - else if (ut != NULL && ut->ut_type == USER_PROCESS) { + else { /* if last login is earlier than some current login */ for (; !doit && w != NULL; w = w->next) if (w->info == LOGGEDIN && - w->loginat < ut->ut_tv.tv_sec) + w->loginat < ll.ll_tv.tv_sec) doit = 1; /* * and if it's not any of the current logins @@ -120,17 +120,17 @@ enter_lastlog(PERSON *pn) */ for (w = pn->whead; doit && w != NULL; w = w->next) if (w->info == LOGGEDIN && - strcmp(w->tty, ut->ut_line) == 0) + strcmp(w->tty, ll.ll_line) == 0) doit = 0; } - if (ut != NULL && doit) { + if (doit) { w = walloc(pn); w->info = LASTLOG; - strcpy(w->tty, ut->ut_line); - strcpy(w->host, ut->ut_host); - w->loginat = ut->ut_tv.tv_sec; + strlcpy(w->tty, ll.ll_line, sizeof(w->tty)); + strlcpy(w->host, ll.ll_host, sizeof(w->host)); + w->host[_UTX_HOSTSIZE] = '\0'; + w->loginat = ll.ll_tv.tv_sec; } - endutxent(); } void @@ -140,8 +140,8 @@ enter_where(struct utmpentry *ep, PERSON *pn) w = walloc(pn); w->info = LOGGEDIN; - w->tty = ep->line; - w->host = ep->host; + strlcpy(w->tty, ep->line, sizeof(w->tty)); + strlcpy(w->host, ep->host, sizeof(w->host)); w->loginat = (time_t)ep->tv.tv_sec; find_idle_and_ttywrite(w); } -- 2.28.0