1 #pragma ident   "%Z%%M% %I%     %E% SMI"
   2 
   3 /****************************************************************************    
   4   Copyright (c) 1999,2000 WU-FTPD Development Group.  
   5   All rights reserved.
   6   
   7   Portions Copyright (c) 1980, 1985, 1988, 1989, 1990, 1991, 1993, 1994 
   8     The Regents of the University of California.
   9   Portions Copyright (c) 1993, 1994 Washington University in Saint Louis. 
  10   Portions Copyright (c) 1996, 1998 Berkeley Software Design, Inc. 
  11   Portions Copyright (c) 1989 Massachusetts Institute of Technology. 
  12   Portions Copyright (c) 1998 Sendmail, Inc. 
  13   Portions Copyright (c) 1983, 1995, 1996, 1997 Eric P.  Allman. 
  14   Portions Copyright (c) 1997 by Stan Barber. 
  15   Portions Copyright (c) 1997 by Kent Landfield. 
  16   Portions Copyright (c) 1991, 1992, 1993, 1994, 1995, 1996, 1997 
  17     Free Software Foundation, Inc.   
  18   
  19   Use and distribution of this software and its source code are governed  
  20   by the terms and conditions of the WU-FTPD Software License ("LICENSE"). 
  21   
  22   If you did not receive a copy of the license, it may be obtained online 
  23   at http://www.wu-ftpd.org/license.html. 
  24   
  25   $Id: logwtmp.c,v 1.16 2000/07/01 18:17:39 wuftpd Exp $ 
  26   
  27 ****************************************************************************/
  28 #include "config.h"
  29 
  30 #include <sys/types.h>
  31 #ifdef TIME_WITH_SYS_TIME
  32 #include <time.h>
  33 #include <sys/time.h>
  34 #else
  35 #ifdef HAVE_SYS_TIME_H
  36 #include <sys/time.h>
  37 #else
  38 #include <time.h>
  39 #endif
  40 #endif
  41 #include <sys/stat.h>
  42 #if defined(HAVE_FCNTL_H)
  43 #include <fcntl.h>
  44 #endif
  45 #include <utmp.h>
  46 #ifdef SVR4
  47 #ifndef NO_UTMPX
  48 #include <utmpx.h>
  49 #ifndef _SCO_DS
  50 #include <sac.h>
  51 #endif
  52 #endif
  53 #endif
  54 #ifdef BSD
  55 #include <strings.h>
  56 #else
  57 #include <string.h>
  58 #endif
  59 #ifdef HAVE_SYS_SYSLOG_H
  60 #include <sys/syslog.h>
  61 #endif
  62 #if defined(HAVE_SYSLOG_H) || (!defined(AUTOCONF) && !defined(HAVE_SYS_SYSLOG_H))
  63 #include <syslog.h>
  64 #endif
  65 #ifdef __FreeBSD__
  66 #include <netinet/in.h>
  67 #include <arpa/inet.h>
  68 #include <netdb.h>
  69 #endif
  70 
  71 #include "pathnames.h"
  72 #include "proto.h"
  73 
  74 #ifndef NO_UTMP
  75 static int fd = -1;
  76 #endif
  77 #if defined(SVR4) && !defined(NO_UTMPX)
  78 static int fdx = -1;
  79 #endif
  80 
  81 /* Modified version of logwtmp that holds wtmp file open after first call,
  82  * for use with ftp (which may chroot after login, but before logout). */
  83 
  84 void wu_logwtmp(char *line, char *name, char *host, int login)
  85 {
  86     struct stat buf;
  87 #ifndef NO_UTMP
  88     struct utmp ut;
  89 #endif
  90 
  91 #if defined(SVR4) && !defined(NO_UTMPX)
  92     /*
  93      * Date: Tue, 09 Mar 1999 14:59:42 -0600
  94      * From: Chad Price <cprice@molbio.unmc.edu>
  95      * To: wu-ftpd@wugate.wustl.edu
  96      * Subject: Re: Problem w/ Solaris /var/adm/wtmpx and /usr/bin/last(1)
  97      * 
  98      * I've been running Sol 2.4 since it came out, and the 'last' command
  99      * has never worked correctly, for ftpd or logins either one.  wtmpx
 100      * often fails to close out sessions when the user logs out.  As a
 101      * result, I only use last to see who logged in, not who/when the
 102      * logout occurred.
 103      * 
 104      * When I first installed it, it was even worse, and they immediately
 105      * told me to patch the system.  This fixed it to semi-compus mentis,
 106      * but not to working order.  So I guess my conclusion is: ignore the
 107      * wtmpx / last log stuff on Solaris 2.4 (and other releases of Solaris
 108      * too from what I see in the comments), it's broken and always has
 109      * been.  I do of course stand ready to be corrected (in this case,
 110      * pointed to a patch which really does fix it.)
 111      *
 112      */
 113     struct utmpx utx;
 114 
 115     if (fdx < 0 && (fdx = open(WTMPX_FILE, O_WRONLY | O_APPEND, 0)) < 0) {
 116         syslog(LOG_ERR, "wtmpx %s %m", WTMPX_FILE);
 117         return;
 118     }
 119 
 120     if (fstat(fdx, &buf) == 0) {
 121         memset((void *) &utx, '\0', sizeof(utx));
 122         (void) strncpy(utx.ut_user, name, sizeof(utx.ut_user));
 123         (void) strncpy(utx.ut_host, host, sizeof(utx.ut_host));
 124         (void) strncpy(utx.ut_id, "ftp", sizeof(utx.ut_id));
 125         (void) strncpy(utx.ut_line, line, sizeof(utx.ut_line));
 126         utx.ut_syslen = strlen(utx.ut_host) + 1;
 127         utx.ut_pid = getpid();
 128         (void) time(&utx.ut_tv.tv_sec);
 129         if (login /* name && *name */ ) {
 130             utx.ut_type = USER_PROCESS;
 131         }
 132         else {
 133             utx.ut_type = DEAD_PROCESS;
 134         }
 135         utx.ut_exit.e_termination = 0;
 136         utx.ut_exit.e_exit = 0;
 137         if (write(fdx, (char *) &utx, sizeof(struct utmpx)) !=
 138             sizeof(struct utmpx))
 139                   (void) ftruncate(fdx, buf.st_size);
 140     }
 141 #endif /* defined(SVR4) && !defined(NO_UTMPX) */
 142 
 143 #ifndef NO_UTMP
 144 #ifdef __FreeBSD__
 145     if (strlen(host) > UT_HOSTSIZE) {
 146         if ((host = inet_htop(host)) == NULL)
 147             host = "invalid hostname";
 148     }
 149 #endif
 150 
 151     if (fd < 0 && (fd = open(_PATH_WTMP, O_WRONLY | O_APPEND, 0)) < 0) {
 152         syslog(LOG_ERR, "wtmp %s %m", _PATH_WTMP);
 153         return;
 154     }
 155     if (fstat(fd, &buf) == 0) {
 156 #ifdef UTMAXTYPE
 157         memset((void *) &ut, 0, sizeof(ut));
 158 #ifdef LINUX
 159         (void) strncpy(ut.ut_id, "", sizeof(ut.ut_id));
 160 #else
 161         (void) strncpy(ut.ut_id, "ftp", sizeof(ut.ut_id));
 162 #endif
 163         (void) strncpy(ut.ut_line, line, sizeof(ut.ut_line));
 164         ut.ut_pid = getpid();
 165         if (login /* name && *name */ ) {
 166             (void) strncpy(ut.ut_user, name, sizeof(ut.ut_user));
 167             ut.ut_type = USER_PROCESS;
 168         }
 169         else
 170             ut.ut_type = DEAD_PROCESS;
 171 #if defined(HAVE_UT_UT_EXIT_E_TERMINATION) || (!defined(AUTOCONF) && !defined(LINUX))
 172         ut.ut_exit.e_termination = 0;
 173         ut.ut_exit.e_exit = 0;
 174 #endif
 175 #else
 176         (void) strncpy(ut.ut_line, line, sizeof(ut.ut_line));
 177         if (login) {
 178             (void) strncpy(ut.ut_name, name, sizeof(ut.ut_name));
 179         }
 180         else {
 181             (void) strncpy(ut.ut_name, "", sizeof(ut.ut_name));
 182         }
 183 #endif /* UTMAXTYPE */
 184 #ifdef HAVE_UT_UT_HOST          /* does have host in utmp */
 185         if (login) {
 186             (void) strncpy(ut.ut_host, host, sizeof(ut.ut_host));
 187         }
 188         else {
 189             (void) strncpy(ut.ut_host, "", sizeof(ut.ut_host));
 190         }
 191 #endif
 192         (void) time(&ut.ut_time);
 193         if (write(fd, (char *) &ut, sizeof(struct utmp)) !=
 194             sizeof(struct utmp))
 195                  (void) ftruncate(fd, buf.st_size);
 196     }
 197 #endif /* NO_UTMP */
 198 }