]> git.ipfire.org Git - thirdparty/openssh-portable.git/commitdiff
Add wtmpdb support as Y2038 safe wtmp replacement
authorThorsten Kukuk <kukuk@suse.com>
Tue, 19 Nov 2024 09:53:28 +0000 (10:53 +0100)
committerDamien Miller <djm@mindrot.org>
Mon, 2 Dec 2024 15:55:36 +0000 (02:55 +1100)
Makefile.in
configure.ac
loginrec.c
loginrec.h

index 389e5d9cb7aa3ae15ef9c3f335b5b11b91f1033a..2fcd8aa1ffd32abac93511e03c09a9829c8b1267 100644 (file)
@@ -60,6 +60,7 @@ GSSLIBS=@GSSLIBS@
 SSHDLIBS=@SSHDLIBS@
 LIBEDIT=@LIBEDIT@
 LIBFIDO2=@LIBFIDO2@
+LIBWTMPDB=@LIBWTMPDB@
 AR=@AR@
 AWK=@AWK@
 RANLIB=@RANLIB@
@@ -234,10 +235,10 @@ sshd$(EXEEXT): libssh.a   $(LIBCOMPAT) $(SSHDOBJS)
        $(LD) -o $@ $(SSHDOBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(SSHDLIBS) $(LIBS) $(CHANNELLIBS)
 
 sshd-session$(EXEEXT): libssh.a        $(LIBCOMPAT) $(SSHD_SESSION_OBJS)
-       $(LD) -o $@ $(SSHD_SESSION_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(SSHDLIBS) $(LIBS) $(GSSLIBS) $(K5LIBS) $(CHANNELLIBS)
+       $(LD) -o $@ $(SSHD_SESSION_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(SSHDLIBS) $(LIBS) $(GSSLIBS) $(K5LIBS) $(CHANNELLIBS) $(LIBWTMPDB)
 
 sshd-auth$(EXEEXT): libssh.a $(LIBCOMPAT) $(SSHD_AUTH_OBJS)
-       $(LD) -o $@ $(SSHD_AUTH_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(SSHDLIBS) $(LIBS) $(GSSLIBS) $(K5LIBS) $(CHANNELLIBS)
+       $(LD) -o $@ $(SSHD_AUTH_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(SSHDLIBS) $(LIBS) $(GSSLIBS) $(K5LIBS) $(CHANNELLIBS) $(LIBWTMPDB)
 
 scp$(EXEEXT): $(LIBCOMPAT) libssh.a $(SCP_OBJS)
        $(LD) -o $@ $(SCP_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
index 3728187c433572fbafad57a4eb828d25df1f82c5..018277287bdbc68cf42f85a62065b4164ae85a3a 100644 (file)
@@ -1772,6 +1772,48 @@ AC_ARG_WITH([libedit],
        fi ]
 )
 
+# Check whether user wants wtmpdb support
+WTMPDB_MSG="no"
+AC_ARG_WITH([wtmpdb],
+       [  --with-wtmpdb[[=PATH]]   Enable wtmpdb support for sshd],
+       [ if test "x$withval" != "xno" ; then
+               if test "x$withval" = "xyes" ; then
+                       if test "x$PKGCONFIG" != "xno"; then
+                               AC_MSG_CHECKING([if $PKGCONFIG knows about wtmpdb])
+                               if "$PKGCONFIG" libwtmpdb; then
+                                       AC_MSG_RESULT([yes])
+                                       use_pkgconfig_for_libwtmpdb=yes
+                               else
+                                       AC_MSG_RESULT([no])
+                               fi
+                       fi
+               else
+                       CPPFLAGS="$CPPFLAGS -I${withval}/include"
+                       if test -n "${rpath_opt}"; then
+                               LDFLAGS="-L${withval}/lib ${rpath_opt}${withval}/lib ${LDFLAGS}"
+                       else
+                               LDFLAGS="-L${withval}/lib ${LDFLAGS}"
+                       fi
+               fi
+               if test "x$use_pkgconfig_for_libwtmpdb" = "xyes"; then
+                       LIBWTMPDB=`$PKGCONFIG --libs libwtmpdb`
+                       CPPFLAGS="$CPPFLAGS `$PKGCONFIG --cflags libwtmpdb`"
+               else
+                       LIBWTMPDB="-lwtmpdb"
+               fi
+               OTHERLIBS=`echo $LIBWTMPDB | sed 's/-lwtmpdb//'`
+               AC_CHECK_LIB([wtmpdb], [wtmpdb_login],
+                       [ AC_DEFINE([USE_WTMPDB], [1], [Use libwtmpdb for sshd])
+                         WTMPDB_MSG="yes"
+                         AC_SUBST([LIBWTMPDB])
+                       ],
+                       [ AC_MSG_ERROR([libwtmpdb not found]) ],
+                       [ $OTHERLIBS ]
+               )
+       fi ]
+)
+
+
 AUDIT_MODULE=none
 AC_ARG_WITH([audit],
        [  --with-audit=module     Enable audit support (modules=debug,bsm,linux)],
index 4afe136f45a483f2cbf15dbc7cdd36fca20ba383..c4a9bd4853e3be5372ea2b75564bea5ff2c37d6a 100644 (file)
 # include <util.h>
 #endif
 
+#ifdef USE_WTMPDB
+# include <wtmpdb.h>
+#endif
+
 /**
  ** prototypes for helper functions in this file
  **/
@@ -186,6 +190,9 @@ int wtmp_write_entry(struct logininfo *li);
 int wtmpx_write_entry(struct logininfo *li);
 int lastlog_write_entry(struct logininfo *li);
 int syslogin_write_entry(struct logininfo *li);
+#ifdef USE_WTMPDB
+int wtmpdb_write_entry(struct logininfo *li);
+#endif
 
 int getlast_entry(struct logininfo *li);
 int lastlog_get_entry(struct logininfo *li);
@@ -446,6 +453,9 @@ login_write(struct logininfo *li)
 #ifdef USE_WTMPX
        wtmpx_write_entry(li);
 #endif
+#ifdef USE_WTMPDB
+       wtmpdb_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,
@@ -1391,6 +1401,64 @@ wtmpx_get_entry(struct logininfo *li)
 }
 #endif /* USE_WTMPX */
 
+#ifdef USE_WTMPDB
+static int
+wtmpdb_perform_login(struct logininfo *li)
+{
+       uint64_t login_time = li->tv_sec * ((uint64_t) 1000000ULL) +
+           li->tv_usec;
+       const char *tty;
+
+       if (strncmp(li->line, "/dev/", 5) == 0)
+               tty = &(li->line[5]);
+       else
+               tty = li->line;
+
+       li->wtmpdb_id = wtmpdb_login(NULL, USER_PROCESS, li->username,
+           login_time, tty, li->hostname, 0, 0);
+
+       if (li->wtmpdb_id < 0)
+               return (0);
+
+       return (1);
+}
+
+static int
+wtmpdb_perform_logout(struct logininfo *li)
+{
+       uint64_t logout_time = li->tv_sec * ((uint64_t) 1000000ULL) +
+          li->tv_usec;
+
+       if (li->wtmpdb_id == 0) {
+               const char *tty;
+
+               if (strncmp(li->line, "/dev/", 5) == 0)
+                       tty = &(li->line[5]);
+               else
+                       tty = li->line;
+
+               li->wtmpdb_id = wtmpdb_get_id(NULL, tty, NULL);
+       }
+       wtmpdb_logout(NULL, li->wtmpdb_id, logout_time, NULL);
+
+       return (1);
+}
+
+int
+wtmpdb_write_entry(struct logininfo *li)
+{
+       switch(li->type) {
+       case LTYPE_LOGIN:
+               return (wtmpdb_perform_login(li));
+       case LTYPE_LOGOUT:
+               return (wtmpdb_perform_logout(li));
+       default:
+               logit("%s: invalid type field", __func__);
+               return (0);
+       }
+}
+#endif
+
 /**
  ** Low-level libutil login() functions
  **/
@@ -1529,10 +1597,10 @@ lastlog_write_entry(struct logininfo *li)
                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);
@@ -1540,7 +1608,7 @@ lastlog_write_entry(struct logininfo *li)
                            LASTLOG_FILE, strerror(errno));
                        return (0);
                }
-       
+
                close(fd);
                return (1);
        default:
index 02bceb604c7faa3af940b029ae2444e9239889b8..62ddd01d515a652c00f190320f0e53475063aaab 100644 (file)
@@ -79,6 +79,9 @@ struct logininfo {
        unsigned int tv_sec;
        unsigned int tv_usec;
        union login_netinfo hostaddr;       /* caller's host address(es) */
+#ifdef USE_WTMPDB
+       int64_t wtmpdb_id;                  /* ID for wtmpdb_logout */
+#endif
 }; /* struct logininfo */
 
 /*