X-Git-Url: http://andersk.mit.edu/gitweb/openssh.git/blobdiff_plain/2a81eb9fb5d5b19f763cf83ca117bb8f78eddb3d..6a2c4cd8b3908e0d7e28789e83b4dc2b69aaf6d4:/loginrec.c diff --git a/loginrec.c b/loginrec.c index 2aff6d2b..897921c6 100644 --- a/loginrec.c +++ b/loginrec.c @@ -12,11 +12,6 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Markus Friedl. - * 4. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES @@ -123,7 +118,7 @@ symbols for the platform. Use logintest to check which symbols are defined before modifying - configure.in and loginrec.c. (You have to build logintest yourself + configure.ac and loginrec.c. (You have to build logintest yourself with 'make logintest' as it's not built by default.) Otherwise, patches to the specific method(s) are very helpful! @@ -413,7 +408,7 @@ login_write (struct logininfo *li) { #ifndef HAVE_CYGWIN if ((int)geteuid() != 0) { - log("Attempt to write login records by non-root user (aborting)"); + logit("Attempt to write login records by non-root user (aborting)"); return 1; } #endif @@ -443,6 +438,28 @@ login_write (struct logininfo *li) return 0; } +#ifdef LOGIN_NEEDS_UTMPX +int +login_utmp_only(struct logininfo *li) +{ + li->type = LTYPE_LOGIN; + login_set_current_time(li); +# ifdef USE_UTMP + utmp_write_entry(li); +# endif +# ifdef USE_WTMP + wtmp_write_entry(li); +# endif +# ifdef USE_UTMPX + utmpx_write_entry(li); +# endif +# ifdef USE_WTMPX + wtmpx_write_entry(li); +# endif + return 0; +} +#endif + /** ** getlast_entry: Call low-level functions to retrieve the last login ** time. @@ -542,6 +559,11 @@ line_abbrevname(char *dst, const char *src, int dstsize) if (strncmp(src, "/dev/", 5) == 0) src += 5; +#ifdef WITH_ABBREV_NO_TTY + if (strncmp(src, "tty", 3) == 0) + src += 3; +#endif + len = strlen(src); if (len > 0) { @@ -582,6 +604,9 @@ void construct_utmp(struct logininfo *li, struct utmp *ut) { +# ifdef HAVE_ADDR_V6_IN_UTMP + struct sockaddr_in6 *sa6; +# endif memset(ut, '\0', sizeof(*ut)); /* First fill out fields used for both logins and logouts */ @@ -595,9 +620,15 @@ construct_utmp(struct logininfo *li, switch (li->type) { case LTYPE_LOGIN: ut->ut_type = USER_PROCESS; +#ifdef _UNICOS + cray_set_tmpdir(ut); +#endif break; case LTYPE_LOGOUT: ut->ut_type = DEAD_PROCESS; +#ifdef _UNICOS + cray_retain_utmp(ut, li->pid); +#endif break; } # endif @@ -628,6 +659,19 @@ construct_utmp(struct logininfo *li, if (li->hostaddr.sa.sa_family == AF_INET) ut->ut_addr = li->hostaddr.sa_in.sin_addr.s_addr; # endif +# ifdef HAVE_ADDR_V6_IN_UTMP + /* this is just a 128-bit IPv6 address */ + if (li->hostaddr.sa.sa_family == AF_INET6) { + sa6 = ((struct sockaddr_in6 *)&li->hostaddr.sa); + memcpy(ut->ut_addr_v6, sa6->sin6_addr.s6_addr, 16); + if (IN6_IS_ADDR_V4MAPPED(&sa6->sin6_addr)) { + ut->ut_addr_v6[0] = ut->ut_addr_v6[3]; + ut->ut_addr_v6[1] = 0; + ut->ut_addr_v6[2] = 0; + ut->ut_addr_v6[3] = 0; + } + } +# endif } #endif /* USE_UTMP || USE_WTMP || USE_LOGIN */ @@ -656,6 +700,9 @@ set_utmpx_time(struct logininfo *li, struct utmpx *utx) void construct_utmpx(struct logininfo *li, struct utmpx *utx) { +# ifdef HAVE_ADDR_V6_IN_UTMP + struct sockaddr_in6 *sa6; +# endif memset(utx, '\0', sizeof(*utx)); # ifdef HAVE_ID_IN_UTMPX line_abbrevname(utx->ut_id, li->line, sizeof(utx->ut_id)); @@ -673,6 +720,8 @@ construct_utmpx(struct logininfo *li, struct utmpx *utx) line_stripname(utx->ut_line, li->line, sizeof(utx->ut_line)); set_utmpx_time(li, 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)); if (li->type == LTYPE_LOGOUT) return; @@ -682,8 +731,6 @@ construct_utmpx(struct logininfo *li, struct utmpx *utx) * for logouts. */ - /* strncpy(): Don't necessarily want null termination */ - strncpy(utx->ut_name, li->username, MIN_SIZEOF(utx->ut_name, li->username)); # ifdef HAVE_HOST_IN_UTMPX strncpy(utx->ut_host, li->hostname, MIN_SIZEOF(utx->ut_host, li->hostname)); # endif @@ -692,6 +739,19 @@ construct_utmpx(struct logininfo *li, struct utmpx *utx) if (li->hostaddr.sa.sa_family == AF_INET) utx->ut_addr = li->hostaddr.sa_in.sin_addr.s_addr; # endif +# ifdef HAVE_ADDR_V6_IN_UTMP + /* this is just a 128-bit IPv6 address */ + if (li->hostaddr.sa.sa_family == AF_INET6) { + sa6 = ((struct sockaddr_in6 *)&li->hostaddr.sa); + memcpy(ut->ut_addr_v6, sa6->sin6_addr.s6_addr, 16); + if (IN6_IS_ADDR_V4MAPPED(&sa6->sin6_addr)) { + ut->ut_addr_v6[0] = ut->ut_addr_v6[3]; + ut->ut_addr_v6[1] = 0; + ut->ut_addr_v6[2] = 0; + ut->ut_addr_v6[3] = 0; + } + } +# endif # ifdef HAVE_SYSLEN_IN_UTMPX /* ut_syslen is the length of the utx_host string */ utx->ut_syslen = MIN(strlen(li->hostname), sizeof(utx->ut_host)); @@ -753,7 +813,7 @@ utmp_write_direct(struct logininfo *li, struct utmp *ut) endttyent(); if((struct ttyent *)0 == ty) { - log("utmp_write_entry: tty not found"); + logit("utmp_write_entry: tty not found"); return(1); } #else /* FIXME */ @@ -777,8 +837,8 @@ utmp_write_direct(struct logininfo *li, struct utmp *ut) } (void)lseek(fd, (off_t)(tty * sizeof(struct utmp)), SEEK_SET); - if (atomicio(write, fd, ut, sizeof(*ut)) != sizeof(*ut)) - log("utmp_write_direct: error writing %s: %s", + if (atomicio(vwrite, fd, ut, sizeof(*ut)) != sizeof(*ut)) + logit("utmp_write_direct: error writing %s: %s", UTMP_FILE, strerror(errno)); (void)close(fd); @@ -797,12 +857,12 @@ utmp_perform_login(struct logininfo *li) construct_utmp(li, &ut); # ifdef UTMP_USE_LIBRARY if (!utmp_write_library(li, &ut)) { - log("utmp_perform_login: utmp_write_library() failed"); + logit("utmp_perform_login: utmp_write_library() failed"); return 0; } # else if (!utmp_write_direct(li, &ut)) { - log("utmp_perform_login: utmp_write_direct() failed"); + logit("utmp_perform_login: utmp_write_direct() failed"); return 0; } # endif @@ -818,12 +878,12 @@ utmp_perform_logout(struct logininfo *li) construct_utmp(li, &ut); # ifdef UTMP_USE_LIBRARY if (!utmp_write_library(li, &ut)) { - log("utmp_perform_logout: utmp_write_library() failed"); + logit("utmp_perform_logout: utmp_write_library() failed"); return 0; } # else if (!utmp_write_direct(li, &ut)) { - log("utmp_perform_logout: utmp_write_direct() failed"); + logit("utmp_perform_logout: utmp_write_direct() failed"); return 0; } # endif @@ -842,7 +902,7 @@ utmp_write_entry(struct logininfo *li) return utmp_perform_logout(li); default: - log("utmp_write_entry: invalid type field"); + logit("utmp_write_entry: invalid type field"); return 0; } } @@ -883,7 +943,7 @@ utmpx_write_library(struct logininfo *li, struct utmpx *utx) static int utmpx_write_direct(struct logininfo *li, struct utmpx *utx) { - log("utmpx_write_direct: not implemented!"); + logit("utmpx_write_direct: not implemented!"); return 0; } # endif /* UTMPX_USE_LIBRARY */ @@ -896,12 +956,12 @@ utmpx_perform_login(struct logininfo *li) construct_utmpx(li, &utx); # ifdef UTMPX_USE_LIBRARY if (!utmpx_write_library(li, &utx)) { - log("utmpx_perform_login: utmp_write_library() failed"); + logit("utmpx_perform_login: utmp_write_library() failed"); return 0; } # else if (!utmpx_write_direct(li, &ut)) { - log("utmpx_perform_login: utmp_write_direct() failed"); + logit("utmpx_perform_login: utmp_write_direct() failed"); return 0; } # endif @@ -914,9 +974,7 @@ utmpx_perform_logout(struct logininfo *li) { struct utmpx utx; - memset(&utx, '\0', sizeof(utx)); - set_utmpx_time(li, &utx); - line_stripname(utx.ut_line, li->line, sizeof(utx.ut_line)); + construct_utmpx(li, &utx); # ifdef HAVE_ID_IN_UTMPX line_abbrevname(utx.ut_id, li->line, sizeof(utx.ut_id)); # endif @@ -941,7 +999,7 @@ utmpx_write_entry(struct logininfo *li) case LTYPE_LOGOUT: return utmpx_perform_logout(li); default: - log("utmpx_write_entry: invalid type field"); + logit("utmpx_write_entry: invalid type field"); return 0; } } @@ -963,14 +1021,14 @@ wtmp_write(struct logininfo *li, struct utmp *ut) int fd, ret = 1; if ((fd = open(WTMP_FILE, O_WRONLY|O_APPEND, 0)) < 0) { - log("wtmp_write: problem writing %s: %s", + logit("wtmp_write: problem writing %s: %s", WTMP_FILE, strerror(errno)); return 0; } if (fstat(fd, &buf) == 0) - if (atomicio(write, fd, ut, sizeof(*ut)) != sizeof(*ut)) { + if (atomicio(vwrite, fd, ut, sizeof(*ut)) != sizeof(*ut)) { ftruncate(fd, buf.st_size); - log("wtmp_write: problem writing %s: %s", + logit("wtmp_write: problem writing %s: %s", WTMP_FILE, strerror(errno)); ret = 0; } @@ -1007,7 +1065,7 @@ wtmp_write_entry(struct logininfo *li) case LTYPE_LOGOUT: return wtmp_perform_logout(li); default: - log("wtmp_write_entry: invalid type field"); + logit("wtmp_write_entry: invalid type field"); return 0; } } @@ -1056,19 +1114,19 @@ wtmp_get_entry(struct logininfo *li) li->tv_sec = li->tv_usec = 0; if ((fd = open(WTMP_FILE, O_RDONLY)) < 0) { - log("wtmp_get_entry: problem opening %s: %s", + logit("wtmp_get_entry: problem opening %s: %s", WTMP_FILE, strerror(errno)); return 0; } if (fstat(fd, &st) != 0) { - log("wtmp_get_entry: couldn't stat %s: %s", + logit("wtmp_get_entry: couldn't stat %s: %s", WTMP_FILE, strerror(errno)); close(fd); return 0; } /* Seek to the start of the last struct utmp */ - if (lseek(fd, (off_t)(0 - sizeof(struct utmp)), SEEK_END) == -1) { + if (lseek(fd, -(off_t)sizeof(struct utmp), SEEK_END) == -1) { /* Looks like we've got a fresh wtmp file */ close(fd); return 0; @@ -1076,7 +1134,7 @@ wtmp_get_entry(struct logininfo *li) while (!found) { if (atomicio(read, fd, &ut, sizeof(ut)) != sizeof(ut)) { - log("wtmp_get_entry: read of %s failed: %s", + logit("wtmp_get_entry: read of %s failed: %s", WTMP_FILE, strerror(errno)); close (fd); return 0; @@ -1101,7 +1159,7 @@ wtmp_get_entry(struct logininfo *li) continue; } /* Seek back 2 x struct utmp */ - if (lseek(fd, (off_t)(0-2*sizeof(struct utmp)), SEEK_CUR) == -1) { + if (lseek(fd, -(off_t)(2 * sizeof(struct utmp)), SEEK_CUR) == -1) { /* We've found the start of the file, so quit */ close (fd); return 0; @@ -1125,25 +1183,30 @@ wtmp_get_entry(struct logininfo *li) static int wtmpx_write(struct logininfo *li, struct utmpx *utx) { +#ifndef HAVE_UPDWTMPX struct stat buf; int fd, ret = 1; if ((fd = open(WTMPX_FILE, O_WRONLY|O_APPEND, 0)) < 0) { - log("wtmpx_write: problem opening %s: %s", + logit("wtmpx_write: problem opening %s: %s", WTMPX_FILE, strerror(errno)); return 0; } if (fstat(fd, &buf) == 0) - if (atomicio(write, fd, utx, sizeof(*utx)) != sizeof(*utx)) { + if (atomicio(vwrite, fd, utx, sizeof(*utx)) != sizeof(*utx)) { ftruncate(fd, buf.st_size); - log("wtmpx_write: problem writing %s: %s", + logit("wtmpx_write: problem writing %s: %s", WTMPX_FILE, strerror(errno)); ret = 0; } (void)close(fd); return ret; +#else + updwtmpx(WTMPX_FILE, utx); + return 1; +#endif } @@ -1176,7 +1239,7 @@ wtmpx_write_entry(struct logininfo *li) case LTYPE_LOGOUT: return wtmpx_perform_logout(li); default: - log("wtmpx_write_entry: invalid type field"); + logit("wtmpx_write_entry: invalid type field"); return 0; } } @@ -1212,19 +1275,19 @@ wtmpx_get_entry(struct logininfo *li) li->tv_sec = li->tv_usec = 0; if ((fd = open(WTMPX_FILE, O_RDONLY)) < 0) { - log("wtmpx_get_entry: problem opening %s: %s", + logit("wtmpx_get_entry: problem opening %s: %s", WTMPX_FILE, strerror(errno)); return 0; } if (fstat(fd, &st) != 0) { - log("wtmpx_get_entry: couldn't stat %s: %s", - WTMP_FILE, strerror(errno)); + logit("wtmpx_get_entry: couldn't stat %s: %s", + WTMPX_FILE, strerror(errno)); close(fd); return 0; } /* Seek to the start of the last struct utmpx */ - if (lseek(fd, (off_t)(0-sizeof(struct utmpx)), SEEK_END) == -1 ) { + if (lseek(fd, -(off_t)sizeof(struct utmpx), SEEK_END) == -1 ) { /* probably a newly rotated wtmpx file */ close(fd); return 0; @@ -1232,7 +1295,7 @@ wtmpx_get_entry(struct logininfo *li) while (!found) { if (atomicio(read, fd, &utx, sizeof(utx)) != sizeof(utx)) { - log("wtmpx_get_entry: read of %s failed: %s", + logit("wtmpx_get_entry: read of %s failed: %s", WTMPX_FILE, strerror(errno)); close (fd); return 0; @@ -1240,6 +1303,7 @@ wtmpx_get_entry(struct logininfo *li) /* 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) ) { + found = 1; # ifdef HAVE_TV_IN_UTMPX li->tv_sec = utx.ut_tv.tv_sec; # else @@ -1254,7 +1318,7 @@ wtmpx_get_entry(struct logininfo *li) # endif continue; } - if (lseek(fd, (off_t)(0-2*sizeof(struct utmpx)), SEEK_CUR) == -1) { + if (lseek(fd, -(off_t)(2 * sizeof(struct utmpx)), SEEK_CUR) == -1) { close (fd); return 0; } @@ -1276,11 +1340,12 @@ syslogin_perform_login(struct logininfo *li) struct utmp *ut; if (! (ut = (struct utmp *)malloc(sizeof(*ut)))) { - log("syslogin_perform_login: couldn't malloc()"); + logit("syslogin_perform_login: couldn't malloc()"); return 0; } construct_utmp(li, ut); login(ut); + free(ut); return 1; } @@ -1289,12 +1354,12 @@ static int syslogin_perform_logout(struct logininfo *li) { # ifdef HAVE_LOGOUT - char line[8]; + char line[UT_LINESIZE]; (void)line_stripname(line, li->line, sizeof(line)); if (!logout(line)) { - log("syslogin_perform_logout: logout() returned an error"); + logit("syslogin_perform_logout: logout() returned an error"); # ifdef HAVE_LOGWTMP } else { logwtmp(line, "", ""); @@ -1317,7 +1382,7 @@ syslogin_write_entry(struct logininfo *li) case LTYPE_LOGOUT: return syslogin_perform_logout(li); default: - log("syslogin_write_entry: Invalid type field"); + logit("syslogin_write_entry: Invalid type field"); return 0; } } @@ -1352,7 +1417,7 @@ lastlog_filetype(char *filename) struct stat st; if (stat(LASTLOG_FILE, &st) != 0) { - log("lastlog_perform_login: Couldn't stat %s: %s", LASTLOG_FILE, + logit("lastlog_perform_login: Couldn't stat %s: %s", LASTLOG_FILE, strerror(errno)); return 0; } @@ -1383,12 +1448,12 @@ lastlog_openseek(struct logininfo *li, int *fd, int filemode) LASTLOG_FILE, li->username); break; default: - log("lastlog_openseek: %.100s is not a file or directory!", + logit("lastlog_openseek: %.100s is not a file or directory!", LASTLOG_FILE); return 0; } - *fd = open(lastlog_file, filemode); + *fd = open(lastlog_file, filemode, 0600); if ( *fd < 0) { debug("lastlog_openseek: Couldn't open %s: %s", lastlog_file, strerror(errno)); @@ -1397,10 +1462,10 @@ lastlog_openseek(struct logininfo *li, int *fd, int filemode) if (type == LL_FILE) { /* find this uid's offset in the lastlog file */ - offset = (off_t) ( (long)li->uid * sizeof(struct lastlog)); + offset = (off_t) ((long)li->uid * sizeof(struct lastlog)); if ( lseek(*fd, offset, SEEK_SET) != offset ) { - log("lastlog_openseek: %s->lseek(): %s", + logit("lastlog_openseek: %s->lseek(): %s", lastlog_file, strerror(errno)); return 0; } @@ -1422,9 +1487,9 @@ lastlog_perform_login(struct logininfo *li) return(0); /* write the entry */ - if (atomicio(write, fd, &last, sizeof(last)) != sizeof(last)) { + if (atomicio(vwrite, fd, &last, sizeof(last)) != sizeof(last)) { close(fd); - log("lastlog_write_filemode: Error writing to %s: %s", + logit("lastlog_write_filemode: Error writing to %s: %s", LASTLOG_FILE, strerror(errno)); return 0; } @@ -1440,7 +1505,7 @@ lastlog_write_entry(struct logininfo *li) case LTYPE_LOGIN: return lastlog_perform_login(li); default: - log("lastlog_write_entry: Invalid type field"); + logit("lastlog_write_entry: Invalid type field"); return 0; } } @@ -1458,19 +1523,32 @@ int lastlog_get_entry(struct logininfo *li) { struct lastlog last; - int fd; + int fd, ret; - if (lastlog_openseek(li, &fd, O_RDONLY)) { - if (atomicio(read, fd, &last, sizeof(last)) != sizeof(last)) { - log("lastlog_get_entry: Error reading from %s: %s", - LASTLOG_FILE, strerror(errno)); - return 0; - } else { - lastlog_populate_entry(li, &last); - return 1; - } - } else { - return 0; + if (!lastlog_openseek(li, &fd, O_RDONLY)) + return (0); + + ret = atomicio(read, fd, &last, sizeof(last)); + close(fd); + + switch (ret) { + case 0: + memset(&last, '\0', sizeof(last)); + /* FALLTHRU */ + case sizeof(last): + lastlog_populate_entry(li, &last); + return (1); + case -1: + error("%s: Error reading from %s: %s", __func__, + LASTLOG_FILE, strerror(errno)); + return (0); + default: + error("%s: Error reading from %s: Expecting %d, got %d", + __func__, LASTLOG_FILE, sizeof(last), ret); + return (0); } + + /* NOTREACHED */ + return (0); } #endif /* USE_LASTLOG */