1
0
mirror of https://github.com/samba-team/samba.git synced 2025-12-21 20:23:50 +03:00

Added utmp fix from David Lee <T.D.Lee@durham.ac.uk>.

Jeremy.
This commit is contained in:
Jeremy Allison
-
parent b0a5ba9e01
commit 95d37a1d25
9 changed files with 951 additions and 576 deletions

View File

@@ -5,4 +5,4 @@ The Samba Consultants List
==========================
This list has now moved to the support page of the
Samba web pages at http://samba.org.au/samba/
Samba web pages at http://samba.org/samba/

View File

@@ -762,6 +762,10 @@ it() link(bf(username level))(usernamelevel)
it() link(bf(username map))(usernamemap)
it() link(bf(utmp))(utmp)
it() link(bf(utmp directory))(utmpdirectory)
it() link(bf(valid chars))(validchars)
it() link(bf(wins proxy))(winsproxy)
@@ -6357,6 +6361,39 @@ tt( no username map)
bf(Example:)
tt( username map = /usr/local/samba/lib/users.map)
label(utmp)
dit(bf(utmp (G)))
This boolean parameter is only available if Samba has been configured and compiled
with the option tt(--with-utmp). If set to True then Samba will attempt
to add utmp or utmpx records (depending on the UNIX system) whenever a
connection is made to a Samba server. Sites may use this to record the
user connecting to a Samba share.
See also the link(bf("utmp directory"))(utmpdirectory) parameter.
bf(Default:)
tt(utmp = False)
bf(Example:)
tt(utmp = True)
label(utmpdirectory)
dit(bf(utmp directory(G)))
This parameter is only available if Samba has been configured and compiled
with the option tt(--with-utmp). It specifies a directory pathname that is
used to store the utmp or utmpx files (depending on the UNIX system) that
record user connections to a Samba server. See also the link(bf("utmp"))(utmp)
parameter. By default this is not set, meaning the system will use whatever
utmp file the native system is set to use (usually /var/run/utmp on Linux).
bf(Default:)
tt(no utmp directory)
bf(Example:)
tt(utmp directory = /var/adm/)
label(validchars)
dit(bf(valid chars (G)))

View File

@@ -74,6 +74,7 @@
#undef HAVE_SETRESUID_DECL
#undef HAVE_SETRESUID
#undef WITH_NETATALK
#undef WITH_UTMP
#undef HAVE_INO64_T
#undef HAVE_STRUCT_FLOCK64
#undef SIZEOF_INO_T

1221
source/configure vendored

File diff suppressed because it is too large Load Diff

View File

@@ -198,6 +198,9 @@ AC_CHECK_HEADERS(stropts.h poll.h readline.h history.h readline/readline.h)
AC_CHECK_HEADERS(readline/history.h sys/capability.h syscall.h sys/syscall.h)
AC_CHECK_HEADERS(sys/acl.h sys/cdefs.h glob.h)
# For experimental utmp support
AC_CHECK_HEADERS(utmp.h utmpx.h)
AC_CHECK_SIZEOF(int,cross)
AC_CHECK_SIZEOF(long,cross)
AC_CHECK_SIZEOF(short,cross)
@@ -1385,6 +1388,25 @@ AC_ARG_WITH(quotas,
)
AC_SUBST(QUOTAOBJS)
#################################################
# check for experimental utmp accounting
AC_MSG_CHECKING(whether to support utmp accounting)
AC_ARG_WITH(utmp,
[ --with-utmp Include experimental utmp accounting
--without-utmp Don't include experimental utmp accounting (default)],
[ case "$withval" in
yes)
AC_MSG_RESULT(yes)
AC_DEFINE(WITH_UTMP)
;;
*)
AC_MSG_RESULT(no)
;;
esac ],
AC_MSG_RESULT(no)
)
#################################################
# set private directory location
AC_ARG_WITH(privatedir,

View File

@@ -140,6 +140,7 @@
#undef HAVE_SETRESUID_DECL
#undef HAVE_SETRESUID
#undef WITH_NETATALK
#undef WITH_UTMP
#undef HAVE_INO64_T
#undef HAVE_STRUCT_FLOCK64
#undef SIZEOF_INO_T
@@ -870,6 +871,12 @@
/* Define if you have the <utime.h> header file. */
#undef HAVE_UTIME_H
/* Define if you have the <utmp.h> header file. */
#undef HAVE_UTMP_H
/* Define if you have the <utmpx.h> header file. */
#undef HAVE_UTMPX_H
/* Define if you have the cups library (-lcups). */
#undef HAVE_LIBCUPS

View File

@@ -1127,6 +1127,7 @@ char *lp_smb_passwd_file(void);
char *lp_serverstring(void);
char *lp_printcapname(void);
char *lp_lockdir(void);
char *lp_utmpdir(void);
char *lp_rootdir(void);
char *lp_defaultservice(void);
char *lp_msg_command(void);
@@ -1300,6 +1301,7 @@ BOOL lp_map_hidden(int );
BOOL lp_map_archive(int );
BOOL lp_locking(int );
BOOL lp_strict_locking(int );
BOOL lp_utmp(int );
BOOL lp_share_modes(int );
BOOL lp_oplocks(int );
BOOL lp_level2_oplocks(int );

View File

@@ -159,6 +159,9 @@ typedef struct
char *szAddUserScript;
char *szDelUserScript;
char *szWINSHook;
#ifdef WITH_UTMP
char *szUtmpDir;
#endif /* WITH_UTMP */
int max_log_size;
int mangled_stack;
int max_xmit;
@@ -333,6 +336,9 @@ typedef struct
BOOL bMap_archive;
BOOL bLocking;
BOOL bStrictLocking;
#ifdef WITH_UTMP
BOOL bUtmp;
#endif
BOOL bShareModes;
BOOL bOpLocks;
BOOL bLevel2OpLocks;
@@ -435,6 +441,9 @@ static service sDefault =
True, /* bMap_archive */
True, /* bLocking */
False, /* bStrictLocking */
#ifdef WITH_UTMP
False, /* bUtmp */
#endif
True, /* bShareModes */
True, /* bOpLocks */
True, /* bLevel2OpLocks */
@@ -773,6 +782,9 @@ static struct parm_struct parm_table[] =
{"fake oplocks", P_BOOL, P_LOCAL, &sDefault.bFakeOplocks, NULL, NULL, FLAG_SHARE},
{"kernel oplocks", P_BOOL, P_GLOBAL, &Globals.bKernelOplocks, NULL, NULL, FLAG_GLOBAL},
{"locking", P_BOOL, P_LOCAL, &sDefault.bLocking, NULL, NULL, FLAG_SHARE|FLAG_GLOBAL},
#ifdef WITH_UTMP
{"utmp", P_BOOL, P_LOCAL, &sDefault.bUtmp, NULL, NULL, FLAG_SHARE|FLAG_GLOBAL},
#endif
{"ole locking compatibility", P_BOOL, P_GLOBAL, &Globals.bOleLockingCompat, NULL, NULL, FLAG_GLOBAL},
{"oplocks", P_BOOL, P_LOCAL, &sDefault.bOpLocks, NULL, NULL, FLAG_SHARE|FLAG_GLOBAL},
{"level2 oplocks", P_BOOL, P_LOCAL, &sDefault.bLevel2OpLocks, NULL, NULL, FLAG_SHARE|FLAG_GLOBAL},
@@ -799,6 +811,10 @@ static struct parm_struct parm_table[] =
{"auto services", P_STRING, P_GLOBAL, &Globals.szAutoServices, NULL, NULL, 0},
{"lock dir", P_STRING, P_GLOBAL, &Globals.szLockDir, NULL, NULL, 0},
{"lock directory", P_STRING, P_GLOBAL, &Globals.szLockDir, NULL, NULL, 0},
#ifdef WITH_UTMP
{"utmp dir", P_STRING, P_GLOBAL, &Globals.szUtmpDir, NULL, NULL, 0},
{"utmp directory", P_STRING, P_GLOBAL, &Globals.szUtmpDir, NULL, NULL, 0},
#endif /* WITH_UTMP */
{"default service", P_STRING, P_GLOBAL, &Globals.szDefaultService, NULL, NULL, 0},
{"default", P_STRING, P_GLOBAL, &Globals.szDefaultService, NULL, NULL, 0},
{"message command", P_STRING, P_GLOBAL, &Globals.szMsgCommand, NULL, NULL, 0},
@@ -882,6 +898,7 @@ static void init_globals(void)
string_set(&Globals.szDriverFile, DRIVERFILE);
string_set(&Globals.szLockDir, LOCKDIR);
string_set(&Globals.szRootdir, "/");
string_set(&Globals.szUtmpDir, "");
string_set(&Globals.szSmbrun, SMBRUN);
string_set(&Globals.szSocketAddress, "0.0.0.0");
pstrcpy(s, "Samba ");
@@ -1162,6 +1179,9 @@ FN_GLOBAL_STRING(lp_smb_passwd_file,&Globals.szSMBPasswdFile)
FN_GLOBAL_STRING(lp_serverstring,&Globals.szServerString)
FN_GLOBAL_STRING(lp_printcapname,&Globals.szPrintcapname)
FN_GLOBAL_STRING(lp_lockdir,&Globals.szLockDir)
#ifdef WITH_UTMP
FN_GLOBAL_STRING(lp_utmpdir,&Globals.szUtmpDir)
#endif /* WITH_UTMP */
FN_GLOBAL_STRING(lp_rootdir,&Globals.szRootdir)
FN_GLOBAL_STRING(lp_defaultservice,&Globals.szDefaultService)
FN_GLOBAL_STRING(lp_msg_command,&Globals.szMsgCommand)
@@ -1355,6 +1375,9 @@ FN_LOCAL_BOOL(lp_map_hidden,bMap_hidden)
FN_LOCAL_BOOL(lp_map_archive,bMap_archive)
FN_LOCAL_BOOL(lp_locking,bLocking)
FN_LOCAL_BOOL(lp_strict_locking,bStrictLocking)
#ifdef WITH_UTMP
FN_LOCAL_BOOL(lp_utmp,bUtmp)
#endif
FN_LOCAL_BOOL(lp_share_modes,bShareModes)
FN_LOCAL_BOOL(lp_oplocks,bOpLocks)
FN_LOCAL_BOOL(lp_level2_oplocks,bLevel2OpLocks)

View File

@@ -27,6 +27,11 @@ static TDB_CONTEXT *tdb;
extern int DEBUGLEVEL;
#ifdef WITH_UTMP
static void utmp_yield(pid_t pid, const connection_struct *conn);
static void utmp_claim(const struct connections_data *crec, const connection_struct *conn);
#endif
/****************************************************************************
delete a connection record
****************************************************************************/
@@ -48,6 +53,12 @@ BOOL yield_connection(connection_struct *conn,char *name,int max_connections)
kbuf.dsize = sizeof(key);
tdb_delete(tdb, kbuf);
#ifdef WITH_UTMP
if(conn)
utmp_yield(key.pid, conn);
#endif
return(True);
}
@@ -102,5 +113,206 @@ BOOL claim_connection(connection_struct *conn,char *name,int max_connections,BOO
if (tdb_store(tdb, kbuf, dbuf, TDB_REPLACE) != 0) return False;
#ifdef WITH_UTMP
if (conn)
utmp_claim(&crec, conn);
#endif
return True;
}
#ifdef WITH_UTMP
/****************************************************************************
Reflect connection status in utmp/wtmp files.
T.D.Lee@durham.ac.uk September 1999
Hints for porting:
o Always attempt to use programmatic interface (pututline() etc.)
o The "x" (utmpx/wtmpx; HAVE_UTMPX_H) seems preferable.
OS status:
Solaris 2.x: Tested on 2.6 and 2.7; should be OK on other flavours.
T.D.Lee@durham.ac.uk
HPUX 9.x: Not tested. Appears not to have "x".
IRIX 6.5: Not tested. Appears to have "x".
Notes:
The 4 byte 'ut_id' component is vital to distinguish connections,
of which there could be several hundered or even thousand.
Entries seem to be printable characters, with optional NULL pads.
We need to be distinct from other entries in utmp/wtmp.
Observed things: therefore avoid them. Add to this list please.
From Solaris 2.x (because that's what I have):
'sN' : run-levels; N: [0-9]
'co' : console
'CC' : arbitrary things; C: [a-z]
'rXNN' : rlogin; N: [0-9]; X: [0-9a-z]
'tXNN' : rlogin; N: [0-9]; X: [0-9a-z]
'/NNN' : Solaris CDE
'ftpZ' : ftp (Z is the number 255, aka 0377, aka 0xff)
Mostly a record uses the same 'ut_id' in both "utmp" and "wtmp",
but differences have been seen.
Arbitrarily I have chosen to use a distinctive 'SM' for the
first two bytes.
The remaining two encode the connection number used in samba locking
functions "claim_connection() and "yield_connection()". This seems
to be a "nicely behaved" number: starting from 0 then working up
looking for an available slot.
****************************************************************************/
#include <utmp.h>
#ifdef HAVE_UTMPX_H
#include <utmpx.h>
#endif
static const char *ut_id_encstr =
"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
static
int
ut_id_encode(int i, char *fourbyte)
{
int nbase;
fourbyte[0] = 'S';
fourbyte[1] = 'M';
/*
* Encode remaining 2 bytes from 'i'.
* 'ut_id_encstr' is the character set on which modulo arithmetic is done.
* Example: digits would produce the base-10 numbers from '001'.
*/
nbase = strlen(ut_id_encstr);
fourbyte[3] = ut_id_encstr[i % nbase];
i /= nbase;
fourbyte[2] = ut_id_encstr[i % nbase];
i /= nbase;
return(i); /* 0: good; else overflow */
}
static int utmp_fill(struct utmp *u, const connection_struct *conn, pid_t pid, int i)
{
struct timeval timeval;
int rc;
pstrcpy(u->ut_user, conn->user);
rc = ut_id_encode(i, u->ut_id);
slprintf(u->ut_line, 12, "smb/%d", i);
u->ut_pid = pid;
gettimeofday(&timeval, NULL);
u->ut_time = timeval.tv_sec;
return(rc);
}
static void utmp_update(const pstring dirname, const struct utmp *u, const char *host)
{
pstring fname;
#ifdef HAVE_UTMPX_H
struct utmpx ux, *uxrc;
getutmpx(u, &ux);
if (host) {
ux.ut_syslen = strlen(host);
pstrcpy(ux.ut_host, host);
}
pstrcpy(fname, dirname);
pstrcat(fname, "utmpx");
utmpxname(fname);
uxrc = pututxline(&ux);
if (uxrc == NULL) {
DEBUG(2,("utmp_update: pututxline() failed\n"));
return;
}
pstrcpy(fname, dirname);
pstrcat(fname, "wtmpx");
updwtmpx(fname, &ux);
#else
pstrcpy(fname, dirname);
pstrcat(fname, "utmp");
utmpname(fname);
pututline(u);
pstrcpy(fname, dirname);
pstrcat(fname, "wtmp");
/* *** OK. Appending wtmp (as distinct from overwriting utmp) has
me baffled. How is it to be done? *** */
#endif
}
static void utmp_yield(int pid, const connection_struct *conn)
{
struct utmp u;
pstring dirname;
if (! lp_utmp(SNUM(conn))) {
DEBUG(2,("utmp_yield: lp_utmp() NULL\n"));
return;
}
pstrcpy(dirname,lp_utmpdir());
trim_string(dirname,"","/");
pstrcat(dirname,"/");
DEBUG(2,("utmp_yield: dir:%s conn: user:%s cnum:%d i:%d\n",
dirname, conn->user, conn->cnum, conn->cnum));
memset((char *)&u, '\0', sizeof(struct utmp));
u.ut_type = DEAD_PROCESS;
u.ut_exit.e_termination = 0;
u.ut_exit.e_exit = 0;
if (utmp_fill(&u, conn, pid, conn->cnum) == 0) {
utmp_update(dirname, &u, NULL);
}
}
static void utmp_claim(const struct connections_data *crec, const connection_struct *conn)
{
extern int Client;
struct utmp u;
pstring dirname;
if (conn == NULL) {
DEBUG(2,("utmp_claim: conn NULL\n"));
return;
}
if (! lp_utmp(SNUM(conn))) {
DEBUG(2,("utmp_claim: lp_utmp() NULL\n"));
return;
}
pstrcpy(dirname,lp_utmpdir());
trim_string(dirname,"","/");
pstrcat(dirname,"/");
DEBUG(2,("utmp_claim: dir:%s conn: user:%s cnum:%d i:%d\n",
dirname, conn->user, conn->cnum, conn->cnum));
DEBUG(2,("utmp_claim: crec: pid:%d, cnum:%d name:%s addr:%s mach:%s DNS:%s\n",
crec->pid, crec->cnum, crec->name, crec->addr, crec->machine, client_name(Client)));
memset((char *)&u, '\0', sizeof(struct utmp));
u.ut_type = USER_PROCESS;
if (utmp_fill(&u, conn, crec->pid, conn->cnum) == 0) {
utmp_update(dirname, &u, crec->machine);
}
}
#endif