From 295dd642e96e5d3fea22b1a45f3a2cfd6e354f09 Mon Sep 17 00:00:00 2001 From: djm Date: Thu, 12 Feb 2009 02:12:21 +0000 Subject: [PATCH] - (djm) [configure.ac loginrec.c] bz#1421: fix lastlog support for OSX. OSX provides a getlastlogxbyname function that automates the reading of a lastlog file. Also, the pututxline function will update lastlog so there is no need for loginrec.c to do it explicitly. Collapse some overly verbose code while I'm in there. --- ChangeLog | 7 ++- configure.ac | 4 ++ loginrec.c | 139 ++++++++++++++++++++++++--------------------------- 3 files changed, 76 insertions(+), 74 deletions(-) diff --git a/ChangeLog b/ChangeLog index 0a6b99c7..cbacdeda 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,11 @@ -20090212 +20090205 - (djm) [sshpty.c] bz#1419: OSX uses cloning ptys that automagically set ownership and modes, so avoid explicitly setting them + - (djm) [configure.ac loginrec.c] bz#1421: fix lastlog support for OSX. + OSX provides a getlastlogxbyname function that automates the reading of + a lastlog file. Also, the pututxline function will update lastlog so + there is no need for loginrec.c to do it explicitly. Collapse some + overly verbose code while I'm in there. 20090201 - (dtucker) [defines.h sshconnect.c] INET6_ADDRSTRLEN is now needed in diff --git a/configure.ac b/configure.ac index a15d065c..517ddb68 100644 --- a/configure.ac +++ b/configure.ac @@ -477,6 +477,8 @@ main() { if (NSVersionOfRunTimeLibrary("System") >= (60 << 16)) AC_CHECK_DECL(AU_IPv4, [], AC_DEFINE(AU_IPv4, 0, [System only supports IPv4 audit records]) [#include ] + AC_DEFINE(LASTLOG_WRITE_PUTUTXLINE, 1, + [Define if pututxline updates lastlog too]) ) ;; *-*-dragonfly*) @@ -1508,6 +1510,8 @@ AC_CHECK_FUNCS(utmpname) dnl Checks for utmpx functions AC_CHECK_FUNCS(endutxent getutxent getutxid getutxline pututxline ) AC_CHECK_FUNCS(setutxent utmpxname) +dnl Checks for lastlog functions +AC_CHECK_FUNCS(getlastlogxbyname) AC_CHECK_FUNC(daemon, [AC_DEFINE(HAVE_DAEMON, 1, [Define if your libraries define daemon()])], diff --git a/loginrec.c b/loginrec.c index b4111419..f4af0673 100644 --- a/loginrec.c +++ b/loginrec.c @@ -1456,25 +1456,14 @@ syslogin_write_entry(struct logininfo *li) **/ #ifdef USE_LASTLOG -#define LL_FILE 1 -#define LL_DIR 2 -#define LL_OTHER 3 - -static void -lastlog_construct(struct logininfo *li, struct lastlog *last) -{ - /* clear the structure */ - memset(last, '\0', sizeof(*last)); - - line_stripname(last->ll_line, li->line, sizeof(last->ll_line)); - strlcpy(last->ll_host, li->hostname, - MIN_SIZEOF(last->ll_host, li->hostname)); - last->ll_time = li->tv_sec; -} +#if !defined(LASTLOG_WRITE_PUTUTXLINE) || !defined(HAVE_GETLASTLOGXBYNAME) +/* open the file (using filemode) and seek to the login entry */ static int -lastlog_filetype(char *filename) +lastlog_openseek(struct logininfo *li, int *fd, int filemode) { + off_t offset; + char lastlog_file[1024]; struct stat st; if (stat(LASTLOG_FILE, &st) != 0) { @@ -1482,34 +1471,12 @@ lastlog_filetype(char *filename) LASTLOG_FILE, strerror(errno)); return (0); } - if (S_ISDIR(st.st_mode)) - return (LL_DIR); - else if (S_ISREG(st.st_mode)) - return (LL_FILE); - else - return (LL_OTHER); -} - - -/* open the file (using filemode) and seek to the login entry */ -static int -lastlog_openseek(struct logininfo *li, int *fd, int filemode) -{ - off_t offset; - int type; - char lastlog_file[1024]; - - type = lastlog_filetype(LASTLOG_FILE); - switch (type) { - case LL_FILE: - strlcpy(lastlog_file, LASTLOG_FILE, - sizeof(lastlog_file)); - break; - case LL_DIR: + if (S_ISDIR(st.st_mode)) { snprintf(lastlog_file, sizeof(lastlog_file), "%s/%s", LASTLOG_FILE, li->username); - break; - default: + } else if (S_ISREG(st.st_mode)) { + strlcpy(lastlog_file, LASTLOG_FILE, sizeof(lastlog_file)); + } else { logit("%s: %.100s is not a file or directory!", __func__, LASTLOG_FILE); return (0); @@ -1522,7 +1489,7 @@ lastlog_openseek(struct logininfo *li, int *fd, int filemode) return (0); } - if (type == LL_FILE) { + if (S_ISREG(st.st_mode)) { /* find this uid's offset in the lastlog file */ offset = (off_t) ((long)li->uid * sizeof(struct lastlog)); @@ -1535,52 +1502,74 @@ lastlog_openseek(struct logininfo *li, int *fd, int filemode) return (1); } +#endif /* !LASTLOG_WRITE_PUTUTXLINE || !HAVE_GETLASTLOGXBYNAME */ -static int -lastlog_perform_login(struct logininfo *li) +#ifdef LASTLOG_WRITE_PUTUTXLINE +int +lastlog_write_entry(struct logininfo *li) { - struct lastlog last; - int fd; - - /* create our struct lastlog */ - lastlog_construct(li, &last); - - if (!lastlog_openseek(li, &fd, O_RDWR|O_CREAT)) - return (0); - - /* write the entry */ - if (atomicio(vwrite, fd, &last, sizeof(last)) != sizeof(last)) { - close(fd); - logit("%s: Error writing to %s: %s", __func__, - LASTLOG_FILE, strerror(errno)); - return (0); + switch(li->type) { + case LTYPE_LOGIN: + return 1; /* lastlog written by pututxline */ + default: + logit("lastlog_write_entry: Invalid type field"); + return 0; } - - close(fd); - return (1); } - +#else /* LASTLOG_WRITE_PUTUTXLINE */ int lastlog_write_entry(struct logininfo *li) { + struct lastlog last; + int fd; + switch(li->type) { case LTYPE_LOGIN: - return (lastlog_perform_login(li)); + /* create our struct lastlog */ + memset(&last, '\0', sizeof(last)); + line_stripname(last.ll_line, li->line, sizeof(last.ll_line)); + strlcpy(last.ll_host, li->hostname, + MIN_SIZEOF(last.ll_host, li->hostname)); + last.ll_time = li->tv_sec; + + if (!lastlog_openseek(li, &fd, O_RDWR|O_CREAT)) + return (0); + + /* write the entry */ + if (atomicio(vwrite, fd, &last, sizeof(last)) != sizeof(last)) { + close(fd); + logit("%s: Error writing to %s: %s", __func__, + LASTLOG_FILE, strerror(errno)); + return (0); + } + + close(fd); + return (1); default: logit("%s: Invalid type field", __func__); return (0); } } +#endif /* LASTLOG_WRITE_PUTUTXLINE */ -static void -lastlog_populate_entry(struct logininfo *li, struct lastlog *last) +#ifdef HAVE_GETLASTLOGXBYNAME +int +lastlog_get_entry(struct logininfo *li) { - line_fullname(li->line, last->ll_line, sizeof(li->line)); - strlcpy(li->hostname, last->ll_host, - MIN_SIZEOF(li->hostname, last->ll_host)); - li->tv_sec = last->ll_time; -} + struct lastlogx l, *ll; + if ((ll = getlastlogxbyname(li->username, &l)) == NULL) { + memset(&l, '\0', sizeof(l)); + ll = &l; + } + line_fullname(li->line, ll->ll_line, sizeof(li->line)); + strlcpy(li->hostname, ll->ll_host, + MIN_SIZEOF(li->hostname, ll->ll_host)); + li->tv_sec = ll->ll_tv.tv_sec; + li->tv_usec = ll->ll_tv.tv_usec; + return (1); +} +#else /* HAVE_GETLASTLOGXBYNAME */ int lastlog_get_entry(struct logininfo *li) { @@ -1598,7 +1587,10 @@ lastlog_get_entry(struct logininfo *li) memset(&last, '\0', sizeof(last)); /* FALLTHRU */ case sizeof(last): - lastlog_populate_entry(li, &last); + line_fullname(li->line, last.ll_line, sizeof(li->line)); + strlcpy(li->hostname, last.ll_host, + MIN_SIZEOF(li->hostname, last.ll_host)); + li->tv_sec = last.ll_time; return (1); case -1: error("%s: Error reading from %s: %s", __func__, @@ -1613,6 +1605,7 @@ lastlog_get_entry(struct logininfo *li) /* NOTREACHED */ return (0); } +#endif /* HAVE_GETLASTLOGXBYNAME */ #endif /* USE_LASTLOG */ #ifdef USE_BTMP -- 2.45.2