]> andersk Git - openssh.git/blobdiff - loginrec.c
- (tim) [contrib/cygwin/README] add minires-devel requirement. Patch from
[openssh.git] / loginrec.c
index 2aff6d2b53cd90f17052d7196c16777db7dcd5bc..897921c633d5c00e45a764a427189cffde8ac913 100644 (file)
  * 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
   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 */
This page took 0.075631 seconds and 4 git commands to generate.