Spelling fixes for lib/compression.
[sfrench/samba-autobuild/.git] / source3 / smbd / utmp.c
index cc52db8462fd48c8aa6e9e8b4c1cc828f99bb307..74774054e855d8ce04add9edb5f386ada7377e84 100644 (file)
@@ -1,13 +1,12 @@
 /* 
-   Unix SMB/Netbios implementation.
-   Version 2.0
+   Unix SMB/CIFS implementation.
    utmp routines
    Copyright (C) T.D.Lee@durham.ac.uk 1999
    Heavily modified by Andrew Bartlett and Tridge, April 2001
    
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
    
    This program is distributed in the hope that it will be useful,
    GNU General Public License for more details.
    
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
 #include "includes.h"
 
-#ifdef WITH_UTMP
-
 /****************************************************************************
 Reflect connection status in utmp/wtmp files.
        T.D.Lee@durham.ac.uk  September 1999
@@ -82,11 +78,11 @@ lastlog:
 
 Notes:
        Each connection requires a small number (starting at 0, working up)
-       to represent the line (unum).  This must be unique within and across
-       all smbd processes.
+       to represent the line.  This must be unique within and across all
+       smbd processes.  It is the 'id_num' from Samba's session.c code.
 
        The 4 byte 'ut_id' component is vital to distinguish connections,
-       of which there could be several hundered or even thousand.
+       of which there could be several hundred or even thousand.
        Entries seem to be printable characters, with optional NULL pads.
 
        We need to be distinct from other entries in utmp/wtmp.
@@ -106,14 +102,28 @@ Notes:
        Arbitrarily I have chosen to use a distinctive 'SM' for the
        first two bytes.
 
-       The remaining two encode the "unum" (see above).
-
-       For "utmp consolidate" the suggestion was made to encode the pid into
-       those remaining two bytes (16 bits).  But recent UNIX (e.g Solaris 8)
-       is migrating to pids > 16 bits, so we ought not to do this.
+       The remaining two bytes encode the session 'id_num' (see above).
+       Our caller (session.c) should note our 16-bit limitation.
 
 ****************************************************************************/
 
+#ifndef WITH_UTMP
+/*
+ * Not WITH_UTMP?  Simply supply dummy routines.
+ */
+
+void sys_utmp_claim(const char *username, const char *hostname,
+                       const char *ip_addr_str,
+                       const char *id_str, int id_num)
+{}
+
+void sys_utmp_yield(const char *username, const char *hostname,
+                       const char *ip_addr_str,
+                       const char *id_str, int id_num)
+{}
+
+#else /* WITH_UTMP */
+
 #include <utmp.h>
 
 #ifdef HAVE_UTMPX_H
@@ -126,40 +136,13 @@ Notes:
 #include <lastlog.h>
 #endif
 
-/****************************************************************************
- Obtain/release a small number (0 upwards) unique within and across smbds.
-****************************************************************************/
-/*
- * Need a "small" number to represent this connection, unique within this
- * smbd and across all smbds.
- *
- * claim:
- *     Start at 0, hunt up for free, unique number "unum" by attempting to
- *     store it as a key in a tdb database:
- *             key: unum               data: pid+conn  
- *     Also store its inverse, ready for yield function:
- *             key: pid+conn           data: unum
- *
- * yield:
- *     Find key: pid+conn; data is unum;  delete record
- *     Find key: unum ; delete record.
- *
- * Comment:
- *     The claim algorithm (a "for" loop attempting to store numbers in a tdb
- *     database) will be increasingly inefficient with larger numbers of
- *     connections.  Is it possible to write a suitable primitive within tdb?
- *
- *     However, by also storing the inverse key/data pair, we at least make
- *     the yield algorithm efficient.
- */
-
 /****************************************************************************
  Default paths to various {u,w}tmp{,x} files.
 ****************************************************************************/
 
 #ifdef HAVE_UTMPX_H
 
-static const char *ux_pathname =
+static const char * const ux_pathname =
 # if defined (UTMPX_FILE)
        UTMPX_FILE ;
 # elif defined (_UTMPX_FILE)
@@ -170,7 +153,7 @@ static const char *ux_pathname =
        "" ;
 # endif
 
-static const char *wx_pathname =
+static const char * const wx_pathname =
 # if defined (WTMPX_FILE)
        WTMPX_FILE ;
 # elif defined (_WTMPX_FILE)
@@ -183,7 +166,7 @@ static const char *wx_pathname =
 
 #endif /* HAVE_UTMPX_H */
 
-static const char *ut_pathname =
+static const char * const ut_pathname =
 # if defined (UTMP_FILE)
        UTMP_FILE ;
 # elif defined (_UTMP_FILE)
@@ -194,7 +177,7 @@ static const char *ut_pathname =
        "" ;
 # endif
 
-static const char *wt_pathname =
+static const char * const wt_pathname =
 # if defined (WTMP_FILE)
        WTMP_FILE ;
 # elif defined (_WTMP_FILE)
@@ -206,7 +189,7 @@ static const char *wt_pathname =
 # endif
 
 /* BSD-like systems might want "lastlog" support. */
-/* *** Not yet implemented */
+#if 0 /* *** Not yet implemented */
 #ifndef HAVE_PUTUTLINE         /* see "pututline_my()" */
 static const char *ll_pathname =
 # if defined (_PATH_LASTLOG)   /* what other names (if any?) */
@@ -215,6 +198,7 @@ static const char *ll_pathname =
        "" ;
 # endif        /* _PATH_LASTLOG */
 #endif /* HAVE_PUTUTLINE */
+#endif
 
 /*
  * Get name of {u,w}tmp{,x} file.
@@ -224,30 +208,36 @@ static const char *ll_pathname =
  * utmp{,x}:  try "utmp dir", then default (a define)
  * wtmp{,x}:  try "wtmp dir", then "utmp dir", then default (a define)
  */
-static void uw_pathname(pstring fname, const char *uw_name, const char *uw_default)
+static char *uw_pathname(TALLOC_CTX *ctx,
+               const char *uw_name,
+               const char *uw_default)
 {
-       pstring dirname;
-
-       pstrcpy(dirname, "");
+       char *dirname = NULL;
 
        /* For w-files, first look for explicit "wtmp dir" */
        if (uw_name[0] == 'w') {
-               pstrcpy(dirname,lp_wtmpdir());
-               trim_string(dirname,"","/");
+               dirname = talloc_strdup(ctx, lp_wtmpdir());
+               if (!dirname) {
+                       return NULL;
+               }
+               trim_char(dirname,'\0','/');
        }
 
        /* For u-files and non-explicit w-dir, look for "utmp dir" */
-       if (dirname == 0 || strlen(dirname) == 0) {
-               pstrcpy(dirname,lp_utmpdir());
-               trim_string(dirname,"","/");
+       if ((dirname == NULL) || (strlen(dirname) == 0)) {
+               dirname = talloc_strdup(ctx, lp_utmpdir());
+               if (!dirname) {
+                       return NULL;
+               }
+               trim_char(dirname,'\0','/');
        }
 
        /* If explicit directory above, use it */
-       if (dirname != 0 && strlen(dirname) != 0) {
-               pstrcpy(fname, dirname);
-               pstrcat(fname, "/");
-               pstrcat(fname, uw_name);
-               return;
+       if (dirname && strlen(dirname) != 0) {
+               return talloc_asprintf(ctx,
+                               "%s/%s",
+                               dirname,
+                               uw_name);
        }
 
        /* No explicit directory: attempt to use default paths */
@@ -257,16 +247,15 @@ static void uw_pathname(pstring fname, const char *uw_name, const char *uw_defau
                 */
                DEBUG(2,("uw_pathname: unable to determine pathname\n"));
        }
-       pstrcpy(fname, uw_default);
+       return talloc_strdup(ctx, uw_default);
 }
 
 #ifndef HAVE_PUTUTLINE
-
 /****************************************************************************
  Update utmp file directly.  No subroutine interface: probably a BSD system.
 ****************************************************************************/
 
-static void pututline_my(pstring uname, struct utmp *u, BOOL claim)
+static void pututline_my(const char *uname, struct utmp *u, bool claim)
 {
        DEBUG(1,("pututline_my: not yet implemented\n"));
        /* BSD implementor: may want to consider (or not) adjusting "lastlog" */
@@ -280,7 +269,7 @@ static void pututline_my(pstring uname, struct utmp *u, BOOL claim)
  Credit: Michail Vidiassov <master@iaas.msu.ru>
 ****************************************************************************/
 
-static void updwtmp_my(pstring wname, struct utmp *u, BOOL claim)
+static void updwtmp_my(const char *wname, struct utmp *u, bool claim)
 {
        int fd;
        struct stat buf;
@@ -299,8 +288,12 @@ static void updwtmp_my(pstring wname, struct utmp *u, BOOL claim)
                 *      man page appears not to specify (hints non-NULL)
                 *      A correspondent suggest at least ut_name should be NULL
                 */
-               memset((char *)&(u->ut_name), '\0', sizeof(u->ut_name));
-               memset((char *)&(u->ut_host), '\0', sizeof(u->ut_host));
+#if defined(HAVE_UT_UT_NAME)
+               memset((char *)&u->ut_name, '\0', sizeof(u->ut_name));
+#endif
+#if defined(HAVE_UT_UT_HOST)
+               memset((char *)&u->ut_host, '\0', sizeof(u->ut_host));
+#endif
        }
        /* Stolen from logwtmp function in libutil.
         * May be more locking/blocking is needed?
@@ -319,14 +312,18 @@ static void updwtmp_my(pstring wname, struct utmp *u, BOOL claim)
  Update via utmp/wtmp (not utmpx/wtmpx).
 ****************************************************************************/
 
-static void utmp_nox_update(struct utmp *u, const char *host, BOOL claim)
+static void utmp_nox_update(struct utmp *u, bool claim)
 {
-       pstring uname, wname;
+       char *uname = NULL;
+       char *wname = NULL;
 #if defined(PUTUTLINE_RETURNS_UTMP)
        struct utmp *urc;
 #endif /* PUTUTLINE_RETURNS_UTMP */
 
-       uw_pathname(uname, "utmp", ut_pathname);
+       uname = uw_pathname(talloc_tos(), "utmp", ut_pathname);
+       if (!uname) {
+               return;
+       }
        DEBUG(2,("utmp_nox_update: uname:%s\n", uname));
 
 #ifdef HAVE_PUTUTLINE
@@ -354,7 +351,10 @@ static void utmp_nox_update(struct utmp *u, const char *host, BOOL claim)
        }
 #endif /* HAVE_PUTUTLINE */
 
-       uw_pathname(wname, "wtmp", wt_pathname);
+       wname = uw_pathname(talloc_tos(), "wtmp", wt_pathname);
+       if (!wname) {
+               return;
+       }
        DEBUG(2,("utmp_nox_update: wname:%s\n", wname));
        if (strlen(wname) != 0) {
 #ifdef HAVE_UPDWTMP
@@ -380,14 +380,16 @@ static void utmp_nox_update(struct utmp *u, const char *host, BOOL claim)
 
 static void utmp_strcpy(char *dest, const char *src, size_t n)
 {
-       size_t len;
+       size_t len = 0;
 
-       len = strlen(src);
+       memset(dest, '\0', n);
+       if (src)
+               len = strlen(src);
        if (len >= n) {
                memcpy(dest, src, n);
        } else {
-               memcpy(dest, src, len);
-               memset(dest + len, '\0', n - len);
+               if (len)
+                       memcpy(dest, src, len);
        }
 }
 
@@ -395,21 +397,26 @@ static void utmp_strcpy(char *dest, const char *src, size_t n)
  Update via utmpx/wtmpx (preferred) or via utmp/wtmp.
 ****************************************************************************/
 
-static void sys_utmp_update(struct utmp *u, const char *hostname, BOOL claim)
+static void sys_utmp_update(struct utmp *u, const char *hostname, bool claim)
 {
 #if !defined(HAVE_UTMPX_H)
        /* No utmpx stuff.  Drop to non-x stuff */
-       utmp_nox_update(u, hostname, claim);
+       utmp_nox_update(u, claim);
 #elif !defined(HAVE_PUTUTXLINE)
        /* Odd.  Have utmpx.h but no "pututxline()".  Drop to non-x stuff */
        DEBUG(1,("utmp_update: have utmpx.h but no pututxline() function\n"));
-       utmp_nox_update(u, hostname, claim);
+       utmp_nox_update(u, claim);
 #elif !defined(HAVE_GETUTMPX)
        /* Odd.  Have utmpx.h but no "getutmpx()".  Drop to non-x stuff */
        DEBUG(1,("utmp_update: have utmpx.h but no getutmpx() function\n"));
-       utmp_nox_update(u, hostname, claim);
+       utmp_nox_update(u, claim);
+#elif !defined(HAVE_UPDWTMPX)
+       /* Have utmpx.h but no "updwtmpx()".  Drop to non-x stuff */
+       DEBUG(1,("utmp_update: have utmpx.h but no updwtmpx() function\n"));
+       utmp_nox_update(u, claim);
 #else
-       pstring uname, wname;
+       char *uname = NULL;
+       char *wname = NULL;
        struct utmpx ux, *uxrc;
 
        getutmpx(u, &ux);
@@ -420,11 +427,16 @@ static void sys_utmp_update(struct utmp *u, const char *hostname, BOOL claim)
        else
                ux.ut_syslen = 0;
 #endif
+#if defined(HAVE_UT_UT_HOST)
        utmp_strcpy(ux.ut_host, hostname, sizeof(ux.ut_host));
+#endif
+
+       uname = uw_pathname(talloc_tos(), "utmpx", ux_pathname);
+       wname = uw_pathname(talloc_tos(), "wtmpx", wx_pathname);
+       if (uname && wname) {
+               DEBUG(2,("utmp_update: uname:%s wname:%s\n", uname, wname));
+       }
 
-       uw_pathname(uname, "utmpx", ux_pathname);
-       uw_pathname(wname, "wtmpx", wx_pathname);
-       DEBUG(2,("utmp_update: uname:%s wname:%s\n", uname, wname));
        /*
         * Check for either uname or wname being empty.
         * Some systems, such as Redhat 6, have a "utmpx.h" which doesn't
@@ -432,8 +444,8 @@ static void sys_utmp_update(struct utmp *u, const char *hostname, BOOL claim)
         * Also, our local installation has not provided an override.
         * Drop to non-x method.  (E.g. RH6 has good defaults in "utmp.h".)
         */
-       if ((strlen(uname) == 0) || (strlen(wname) == 0)) {
-               utmp_nox_update(u, hostname, claim);
+       if (!uname || !wname || (strlen(uname) == 0) || (strlen(wname) == 0)) {
+               utmp_nox_update(u, claim);
        } else {
                utmpxname(uname);
                setutxent();
@@ -456,8 +468,8 @@ static void sys_utmp_update(struct utmp *u, const char *hostname, BOOL claim)
 static int ut_id_encode(int i, char *fourbyte)
 {
        int nbase;
-       char *ut_id_encstr = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
-       
+       const char *ut_id_encstr = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
+
        fourbyte[0] = 'S';
        fourbyte[1] = 'M';
 
@@ -479,12 +491,13 @@ static int ut_id_encode(int i, char *fourbyte)
 
 
 /*
-  fill a system utmp structure given all the info we can gather 
+  fill a system utmp structure given all the info we can gather
 */
-static BOOL sys_utmp_fill(struct utmp *u,
-                         const char *username, const char *hostname,
-                         const char *id_str, int id_num)
-{                        
+static bool sys_utmp_fill(struct utmp *u,
+                       const char *username, const char *hostname,
+                       const char *ip_addr_str,
+                       const char *id_str, int id_num)
+{
        struct timeval timeval;
 
        /*
@@ -502,14 +515,10 @@ static BOOL sys_utmp_fill(struct utmp *u,
        /*
         * ut_line:
         *      If size limit proves troublesome, then perhaps use "ut_id_encode()".
-        *
-        * Temporary variable "line_tmp" avoids trouble:
-        * o  with unwanted trailing NULL if ut_line full;
-        * o  with overflow if ut_line would be more than full.
         */
        if (strlen(id_str) > sizeof(u->ut_line)) {
-               DEBUG(1,("id_str [%s] is too long for %d char utmp field\n",
-                        id_str, sizeof(u->ut_line)));
+               DEBUG(1,("id_str [%s] is too long for %lu char utmp field\n",
+                        id_str, (unsigned long)sizeof(u->ut_line)));
                return False;
        }
        utmp_strcpy(u->ut_line, id_str, sizeof(u->ut_line));
@@ -519,16 +528,16 @@ static BOOL sys_utmp_fill(struct utmp *u,
 #endif
 
 /*
- * ut_time, ut_tv: 
+ * ut_time, ut_tv:
  *     Some have one, some the other.  Many have both, but defined (aliased).
  *     It is easier and clearer simply to let the following take its course.
  *     But note that we do the more precise ut_tv as the final assignment.
  */
 #if defined(HAVE_UT_UT_TIME)
-       gettimeofday(&timeval, NULL);
+       GetTimeOfDay(&timeval);
        u->ut_time = timeval.tv_sec;
 #elif defined(HAVE_UT_UT_TV)
-       gettimeofday(&timeval, NULL);
+       GetTimeOfDay(&timeval);
        u->ut_tv = timeval;
 #else
 #error "with-utmp must have UT_TIME or UT_TV"
@@ -537,8 +546,22 @@ static BOOL sys_utmp_fill(struct utmp *u,
 #if defined(HAVE_UT_UT_HOST)
        utmp_strcpy(u->ut_host, hostname, sizeof(u->ut_host));
 #endif
-
-#if defined(HAVE_UT_UT_ADDR)
+#if defined(HAVE_IPV6) && defined(HAVE_UT_UT_ADDR_V6)
+       memset(&u->ut_addr_v6, '\0', sizeof(u->ut_addr_v6));
+       if (ip_addr_str) {
+               struct in6_addr addr;
+               if (inet_pton(AF_INET6, ip_addr_str, &addr) > 0) {
+                       memcpy(&u->ut_addr_v6, &addr, sizeof(addr));
+               }
+       }
+#elif defined(HAVE_UT_UT_ADDR)
+       memset(&u->ut_addr, '\0', sizeof(u->ut_addr));
+       if (ip_addr_str) {
+               struct in_addr addr;
+               if (inet_pton(AF_INET, ip_addr_str, &addr) > 0) {
+                       memcpy(&u->ut_addr, &addr, sizeof(addr));
+               }
+       }
        /*
         * "(unsigned long) ut_addr" apparently exists on at least HP-UX 10.20.
         * Volunteer to implement, please ...
@@ -559,8 +582,9 @@ static BOOL sys_utmp_fill(struct utmp *u,
  Close a connection.
 ****************************************************************************/
 
-void sys_utmp_yield(const char *username, const char *hostname, 
-                   const char *id_str, int id_num)
+void sys_utmp_yield(const char *username, const char *hostname,
+                       const char *ip_addr_str,
+                       const char *id_str, int id_num)
 {
        struct utmp u;
 
@@ -575,7 +599,8 @@ void sys_utmp_yield(const char *username, const char *hostname,
        u.ut_type = DEAD_PROCESS;
 #endif
 
-       if (!sys_utmp_fill(&u, username, hostname, id_str, id_num)) return;
+       if (!sys_utmp_fill(&u, username, hostname, ip_addr_str, id_str, id_num))
+               return;
 
        sys_utmp_update(&u, NULL, False);
 }
@@ -584,8 +609,9 @@ void sys_utmp_yield(const char *username, const char *hostname,
  Claim a entry in whatever utmp system the OS uses.
 ****************************************************************************/
 
-void sys_utmp_claim(const char *username, const char *hostname, 
-                   const char *id_str, int id_num)
+void sys_utmp_claim(const char *username, const char *hostname,
+                       const char *ip_addr_str,
+                       const char *id_str, int id_num)
 {
        struct utmp u;
 
@@ -595,11 +621,10 @@ void sys_utmp_claim(const char *username, const char *hostname,
        u.ut_type = USER_PROCESS;
 #endif
 
-       if (!sys_utmp_fill(&u, username, hostname, id_str, id_num)) return;
+       if (!sys_utmp_fill(&u, username, hostname, ip_addr_str, id_str, id_num))
+               return;
 
        sys_utmp_update(&u, hostname, True);
 }
 
-#else /* WITH_UTMP */
- void dummy_utmp(void) {}
-#endif
+#endif /* WITH_UTMP */