X-Git-Url: http://andersk.mit.edu/gitweb/openssh.git/blobdiff_plain/5ccf88cba8cd9efaf0a9f41cb49d386905a0b64d..HEAD:/loginrec.c diff --git a/loginrec.c b/loginrec.c index aefca100..bca95970 100644 --- a/loginrec.c +++ b/loginrec.c @@ -147,14 +147,34 @@ #include "includes.h" -#include "ssh.h" +#include +#include +#include + +#include + +#include +#include +#ifdef HAVE_PATHS_H +# include +#endif +#include +#include +#include +#include +#include + #include "xmalloc.h" +#include "key.h" +#include "hostfile.h" +#include "ssh.h" #include "loginrec.h" #include "log.h" #include "atomicio.h" #include "packet.h" #include "canohost.h" #include "auth.h" +#include "buffer.h" #ifdef HAVE_UTIL_H # include @@ -164,8 +184,6 @@ # include #endif -RCSID("$Id$"); - /** ** prototypes for helper functions in this file **/ @@ -361,7 +379,7 @@ login_init_entry(struct logininfo *li, int pid, const char *username, strlcpy(li->username, username, sizeof(li->username)); pw = getpwnam(li->username); if (pw == NULL) { - fatal("%s: Cannot find user \"%s\"", __func__, + fatal("%s: Cannot find user \"%s\"", __func__, li->username); } li->uid = pw->pw_uid; @@ -373,7 +391,7 @@ login_init_entry(struct logininfo *li, int pid, const char *username, return (1); } -/* +/* * login_set_current_time(struct logininfo *) - set the current time * * Set the current time in a logininfo structure. This function is @@ -442,8 +460,9 @@ login_write(struct logininfo *li) wtmpx_write_entry(li); #endif #ifdef CUSTOM_SYS_AUTH_RECORD_LOGIN - if (li->type == LTYPE_LOGIN && - !sys_auth_record_login(li->username,li->hostname,li->line, &loginmsg)) + if (li->type == LTYPE_LOGIN && + !sys_auth_record_login(li->username,li->hostname,li->line, + &loginmsg)) logit("Writing login record failed for %s", li->username); #endif #ifdef SSH_AUDIT_EVENTS @@ -533,7 +552,7 @@ getlast_entry(struct logininfo *li) * sure dst has enough space, if not just copy src (ugh) */ char * -line_fullname(char *dst, const char *src, int dstsize) +line_fullname(char *dst, const char *src, u_int dstsize) { memset(dst, '\0', dstsize); if ((strncmp(src, "/dev/", 5) == 0) || (dstsize < (strlen(src) + 5))) @@ -557,7 +576,7 @@ line_stripname(char *dst, const char *src, int dstsize) return (dst); } -/* +/* * line_abbrevname(): Return the abbreviated (usually four-character) * form of the line (Just use the last characters of the * full name.) @@ -739,8 +758,8 @@ construct_utmpx(struct logininfo *li, struct utmpx *utx) utx->ut_pid = li->pid; /* strncpy(): Don't necessarily want null termination */ - strncpy(utx->ut_name, li->username, - MIN_SIZEOF(utx->ut_name, li->username)); + strncpy(utx->ut_user, li->username, + MIN_SIZEOF(utx->ut_user, li->username)); if (li->type == LTYPE_LOGOUT) return; @@ -807,7 +826,7 @@ utmp_write_library(struct logininfo *li, struct utmp *ut) } # else /* UTMP_USE_LIBRARY */ -/* +/* * Write a utmp entry direct to the file * This is a slightly modification of code in OpenBSD's login.c */ @@ -851,7 +870,7 @@ utmp_write_direct(struct logininfo *li, struct utmp *ut) return (0); } if (ret != pos) { - logit("%s: Couldn't seek to tty %d slot in %s", + logit("%s: Couldn't seek to tty %d slot in %s", __func__, tty, UTMP_FILE); return (0); } @@ -1051,7 +1070,7 @@ utmpx_write_entry(struct logininfo *li) #ifdef USE_WTMP -/* +/* * Write a wtmp entry direct to the end of the file * This is a slight modification of code in OpenBSD's logwtmp.c */ @@ -1112,7 +1131,7 @@ wtmp_write_entry(struct logininfo *li) } -/* +/* * Notes on fetching login data from wtmp/wtmpx * * Logouts are usually recorded with (amongst other things) a blank @@ -1156,12 +1175,12 @@ wtmp_get_entry(struct logininfo *li) li->tv_sec = li->tv_usec = 0; if ((fd = open(WTMP_FILE, O_RDONLY)) < 0) { - logit("%s: problem opening %s: %s", __func__, + logit("%s: problem opening %s: %s", __func__, WTMP_FILE, strerror(errno)); return (0); } if (fstat(fd, &st) != 0) { - logit("%s: couldn't stat %s: %s", __func__, + logit("%s: couldn't stat %s: %s", __func__, WTMP_FILE, strerror(errno)); close(fd); return (0); @@ -1176,7 +1195,7 @@ wtmp_get_entry(struct logininfo *li) while (!found) { if (atomicio(read, fd, &ut, sizeof(ut)) != sizeof(ut)) { - logit("%s: read of %s failed: %s", __func__, + logit("%s: read of %s failed: %s", __func__, WTMP_FILE, strerror(errno)); close (fd); return (0); @@ -1234,7 +1253,7 @@ wtmpx_write(struct logininfo *li, struct utmpx *utx) int fd, ret = 1; if ((fd = open(WTMPX_FILE, O_WRONLY|O_APPEND, 0)) < 0) { - logit("%s: problem opening %s: %s", __func__, + logit("%s: problem opening %s: %s", __func__, WTMPX_FILE, strerror(errno)); return (0); } @@ -1297,8 +1316,8 @@ wtmpx_write_entry(struct logininfo *li) static int wtmpx_islogin(struct logininfo *li, struct utmpx *utx) { - if (strncmp(li->username, utx->ut_name, - MIN_SIZEOF(li->username, utx->ut_name)) == 0 ) { + if (strncmp(li->username, utx->ut_user, + MIN_SIZEOF(li->username, utx->ut_user)) == 0 ) { # ifdef HAVE_TYPE_IN_UTMPX if (utx->ut_type == USER_PROCESS) return (1); @@ -1321,12 +1340,12 @@ wtmpx_get_entry(struct logininfo *li) li->tv_sec = li->tv_usec = 0; if ((fd = open(WTMPX_FILE, O_RDONLY)) < 0) { - logit("%s: problem opening %s: %s", __func__, + logit("%s: problem opening %s: %s", __func__, WTMPX_FILE, strerror(errno)); return (0); } if (fstat(fd, &st) != 0) { - logit("%s: couldn't stat %s: %s", __func__, + logit("%s: couldn't stat %s: %s", __func__, WTMPX_FILE, strerror(errno)); close(fd); return (0); @@ -1341,13 +1360,13 @@ wtmpx_get_entry(struct logininfo *li) while (!found) { if (atomicio(read, fd, &utx, sizeof(utx)) != sizeof(utx)) { - logit("%s: read of %s failed: %s", __func__, + logit("%s: read of %s failed: %s", __func__, WTMPX_FILE, strerror(errno)); close (fd); return (0); } /* - * Logouts are recorded as a blank username on a particular + * Logouts are recorded as a blank username on a particular * line. So, we just need to find the username in struct utmpx */ if (wtmpx_islogin(li, &utx)) { @@ -1437,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) { @@ -1463,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); @@ -1503,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)); @@ -1516,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) { @@ -1579,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__, @@ -1587,13 +1598,14 @@ lastlog_get_entry(struct logininfo *li) return (0); default: error("%s: Error reading from %s: Expecting %d, got %d", - __func__, LASTLOG_FILE, sizeof(last), ret); + __func__, LASTLOG_FILE, (int)sizeof(last), ret); return (0); } /* NOTREACHED */ return (0); } +#endif /* HAVE_GETLASTLOGXBYNAME */ #endif /* USE_LASTLOG */ #ifdef USE_BTMP @@ -1611,7 +1623,7 @@ record_failed_login(const char *username, const char *hostname, int fd; struct utmp ut; struct sockaddr_storage from; - size_t fromlen = sizeof(from); + socklen_t fromlen = sizeof(from); struct sockaddr_in *a4; struct sockaddr_in6 *a6; time_t t;