mirror of
https://github.com/samba-team/samba.git
synced 2024-12-23 17:34:34 +03:00
parent
6f78636a56
commit
9ce5a03ccb
@ -185,6 +185,7 @@ OPLOCK_OBJ = smbd/oplock.o smbd/oplock_irix.o smbd/oplock_linux.o
|
||||
NOTIFY_OBJ = smbd/notify.o smbd/notify_hash.o smbd/notify_kernel.o
|
||||
|
||||
SMBD_OBJ1 = smbd/server.o smbd/files.o smbd/chgpasswd.o smbd/connection.o \
|
||||
smbd/utmp.o smbd/session.o \
|
||||
smbd/dfree.o smbd/dir.o smbd/password.o smbd/conn.o smbd/fileio.o \
|
||||
smbd/ipc.o smbd/lanman.o smbd/mangle.o smbd/negprot.o \
|
||||
smbd/message.o smbd/nttrans.o smbd/pipes.o \
|
||||
|
@ -337,12 +337,12 @@ static BOOL proc_pam_session(pam_handle_t *pamh, char *user, char *tty, BOOL fla
|
||||
/*
|
||||
* PAM Externally accessible Session handler
|
||||
*/
|
||||
BOOL pam_session(BOOL flag, const connection_struct *conn, char *tty)
|
||||
BOOL pam_session(BOOL flag, const char *in_user, char *tty)
|
||||
{
|
||||
pam_handle_t *pamh = NULL;
|
||||
char * user;
|
||||
|
||||
user = malloc(strlen(conn->user)+1);
|
||||
user = malloc(strlen(in_user)+1);
|
||||
if ( user == NULL )
|
||||
{
|
||||
DEBUG(0, ("PAM: PAM_session Malloc Failed!\n"));
|
||||
@ -350,7 +350,7 @@ BOOL pam_session(BOOL flag, const connection_struct *conn, char *tty)
|
||||
}
|
||||
|
||||
/* This is freed by PAM */
|
||||
StrnCpy(user, conn->user, strlen(conn->user)+1);
|
||||
StrnCpy(user, in_user, strlen(in_user)+1);
|
||||
|
||||
if (!proc_pam_start(&pamh, user))
|
||||
{
|
||||
|
@ -173,4 +173,12 @@
|
||||
/* Minimum length of allowed password when changing UNIX password. */
|
||||
#define MINPASSWDLENGTH 5
|
||||
|
||||
/* maximum ID number used for session control. This cannot be larger
|
||||
than 62*62 for the current code */
|
||||
#define MAX_SESSION_ID 3000
|
||||
|
||||
#ifndef SESSION_TEMPLATE
|
||||
#define SESSION_TEMPLATE "smb/%d"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -1627,7 +1627,7 @@ char *lp_lockdir(void);
|
||||
char *lp_utmpdir(void);
|
||||
char *lp_wtmpdir(void);
|
||||
char *lp_utmp_hostname(void);
|
||||
BOOL lp_utmp_consolidate(void);
|
||||
BOOL lp_utmp(void);
|
||||
char *lp_rootdir(void);
|
||||
char *lp_source_environment(void);
|
||||
char *lp_defaultservice(void);
|
||||
@ -1717,7 +1717,6 @@ BOOL lp_debug_hires_timestamp(void);
|
||||
BOOL lp_debug_pid(void);
|
||||
BOOL lp_debug_uid(void);
|
||||
BOOL lp_browse_list(void);
|
||||
BOOL lp_unix_realname(void);
|
||||
BOOL lp_nis_home_map(void);
|
||||
BOOL lp_bind_interfaces_only(void);
|
||||
BOOL lp_unix_password_sync(void);
|
||||
@ -1824,7 +1823,6 @@ BOOL lp_map_archive(int );
|
||||
BOOL lp_locking(int );
|
||||
BOOL lp_strict_locking(int );
|
||||
BOOL lp_posix_locking(int );
|
||||
BOOL lp_utmp(int );
|
||||
BOOL lp_share_modes(int );
|
||||
BOOL lp_oplocks(int );
|
||||
BOOL lp_level2_oplocks(int );
|
||||
@ -1911,7 +1909,7 @@ BOOL pdb_generate_sam_sid(void);
|
||||
|
||||
/*The following definitions come from passdb/pampass.c */
|
||||
|
||||
BOOL pam_session(BOOL flag, const connection_struct *conn, char *tty);
|
||||
BOOL pam_session(BOOL flag, const char *in_user, char *tty);
|
||||
BOOL pam_accountcheck(char * user);
|
||||
BOOL pam_passcheck(char * user, char * password);
|
||||
|
||||
@ -4105,11 +4103,12 @@ void generate_next_challenge(char *challenge);
|
||||
BOOL set_challenge(unsigned char *challenge);
|
||||
user_struct *get_valid_user_struct(uint16 vuid);
|
||||
void invalidate_vuid(uint16 vuid);
|
||||
void invalidate_all_vuids(void);
|
||||
char *validated_username(uint16 vuid);
|
||||
char *validated_domain(uint16 vuid);
|
||||
NT_USER_TOKEN *create_nt_token(uid_t uid, gid_t gid, int ngroups, gid_t *groups, BOOL is_guest);
|
||||
uint16 register_vuid(uid_t uid,gid_t gid, char *unix_name, char *requested_name,
|
||||
char *domain,BOOL guest);
|
||||
int register_vuid(uid_t uid,gid_t gid, char *unix_name, char *requested_name,
|
||||
char *domain,BOOL guest);
|
||||
void add_session_user(char *user);
|
||||
BOOL smb_password_check(char *password, unsigned char *part_passwd, unsigned char *c8);
|
||||
BOOL smb_password_ok(SAM_ACCOUNT *sampass, uchar chal[8],
|
||||
@ -4260,6 +4259,11 @@ int find_service(char *service);
|
||||
connection_struct *make_connection(char *service,char *user,char *password, int pwlen, char *dev,uint16 vuid, int *ecode);
|
||||
void close_cnum(connection_struct *conn, uint16 vuid);
|
||||
|
||||
/*The following definitions come from smbd/session.c */
|
||||
|
||||
BOOL session_claim(uint16 vuid);
|
||||
void session_yield(uint16 vuid);
|
||||
|
||||
/*The following definitions come from smbd/srvstr.c */
|
||||
|
||||
int srvstr_push(void *outbuf, void *dest, const char *src, int dest_len, int flags);
|
||||
@ -4311,6 +4315,13 @@ DOM_SID *gid_to_sid(DOM_SID *psid, gid_t gid);
|
||||
BOOL sid_to_uid(DOM_SID *psid, uid_t *puid, enum SID_NAME_USE *sidtype);
|
||||
BOOL sid_to_gid(DOM_SID *psid, gid_t *pgid, enum SID_NAME_USE *sidtype);
|
||||
|
||||
/*The following definitions come from smbd/utmp.c */
|
||||
|
||||
void sys_utmp_yield(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 *id_str, int id_num);
|
||||
|
||||
/*The following definitions come from smbd/vfs-wrap.c */
|
||||
|
||||
int vfswrap_dummy_connect(connection_struct *conn, char *service, char *user);
|
||||
|
@ -1629,6 +1629,8 @@ typedef struct user_struct
|
||||
gid_t *groups;
|
||||
|
||||
NT_USER_TOKEN *nt_user_token;
|
||||
|
||||
int session_id; /* used by utmp and pam session code */
|
||||
} user_struct;
|
||||
|
||||
#include "ntdomain.h"
|
||||
|
@ -173,8 +173,8 @@ typedef struct
|
||||
char *szUtmpDir;
|
||||
char *szWtmpDir;
|
||||
char *szUtmpHostname;
|
||||
BOOL bUtmpConsolidate;
|
||||
#endif /* WITH_UTMP */
|
||||
BOOL bUtmp;
|
||||
#endif
|
||||
char *szSourceEnv;
|
||||
char *szWinbindUID;
|
||||
char *szWinbindGID;
|
||||
@ -257,7 +257,6 @@ typedef struct
|
||||
BOOL bReadbmpx;
|
||||
BOOL bSyslogOnly;
|
||||
BOOL bBrowseList;
|
||||
BOOL bUnixRealname;
|
||||
BOOL bNISHomeMap;
|
||||
BOOL bTimeServer;
|
||||
BOOL bBindInterfacesOnly;
|
||||
@ -374,9 +373,6 @@ typedef struct
|
||||
BOOL bLocking;
|
||||
BOOL bStrictLocking;
|
||||
BOOL bPosixLocking;
|
||||
#ifdef WITH_UTMP
|
||||
BOOL bUtmp;
|
||||
#endif
|
||||
BOOL bShareModes;
|
||||
BOOL bOpLocks;
|
||||
BOOL bLevel2OpLocks;
|
||||
@ -490,9 +486,6 @@ static service sDefault = {
|
||||
True, /* bLocking */
|
||||
False, /* bStrictLocking */
|
||||
True, /* bPosixLocking */
|
||||
#ifdef WITH_UTMP
|
||||
False, /* bUtmp */
|
||||
#endif
|
||||
True, /* bShareModes */
|
||||
True, /* bOpLocks */
|
||||
True, /* bLevel2OpLocks */
|
||||
@ -942,9 +935,6 @@ 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
|
||||
|
||||
{"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},
|
||||
@ -976,16 +966,13 @@ static struct parm_struct parm_table[] = {
|
||||
{"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},
|
||||
{"wtmp dir", P_STRING, P_GLOBAL, &Globals.szWtmpDir, NULL, NULL, 0},
|
||||
{"wtmp directory", P_STRING, P_GLOBAL, &Globals.szWtmpDir, NULL, NULL, 0},
|
||||
{"utmp hostname", P_STRING, P_GLOBAL, &Globals.szUtmpHostname, NULL, NULL, 0},
|
||||
{"utmp consolidate", P_BOOL, P_GLOBAL, &Globals.bUtmpConsolidate, NULL, NULL, 0},
|
||||
#endif /* WITH_UTMP */
|
||||
{"utmp", P_BOOL, P_GLOBAL, &Globals.bUtmp, NULL, NULL, 0},
|
||||
#endif
|
||||
|
||||
{"default service", P_STRING, P_GLOBAL,
|
||||
&Globals.szDefaultService, NULL, NULL, 0},
|
||||
{"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},
|
||||
{"dfree command", P_STRING, P_GLOBAL, &Globals.szDfree, NULL, NULL, 0},
|
||||
@ -995,7 +982,6 @@ static struct parm_struct parm_table[] = {
|
||||
{"socket address", P_STRING, P_GLOBAL, &Globals.szSocketAddress, NULL, NULL, 0},
|
||||
{"homedir map", P_STRING, P_GLOBAL, &Globals.szNISHomeMapName, NULL, NULL, 0},
|
||||
{"time offset", P_INTEGER, P_GLOBAL, &extra_time_offset, NULL, NULL, 0},
|
||||
{"unix realname", P_BOOL, P_GLOBAL, &Globals.bUnixRealname, NULL, NULL, 0},
|
||||
{"NIS homedir", P_BOOL, P_GLOBAL, &Globals.bNISHomeMap, NULL, NULL, 0},
|
||||
{"-valid", P_BOOL, P_LOCAL, &sDefault.valid, NULL, NULL, FLAG_HIDE},
|
||||
|
||||
@ -1215,8 +1201,8 @@ static void init_globals(void)
|
||||
string_set(&Globals.szUtmpDir, "");
|
||||
string_set(&Globals.szWtmpDir, "");
|
||||
string_set(&Globals.szUtmpHostname, "%m");
|
||||
Globals.bUtmpConsolidate = False;
|
||||
#endif /* WITH_UTMP */
|
||||
Globals.bUtmp = False;
|
||||
#endif
|
||||
string_set(&Globals.szSmbrun, SMBRUN);
|
||||
string_set(&Globals.szSocketAddress, "0.0.0.0");
|
||||
pstrcpy(s, "Samba ");
|
||||
@ -1277,7 +1263,6 @@ static void init_globals(void)
|
||||
Globals.lm_interval = 60;
|
||||
Globals.stat_cache_size = 50; /* Number of stat translations we'll keep */
|
||||
Globals.announce_as = ANNOUNCE_AS_NT_SERVER;
|
||||
Globals.bUnixRealname = True;
|
||||
#if (defined(HAVE_NETGROUP) && defined(WITH_AUTOMOUNT))
|
||||
Globals.bNISHomeMap = False;
|
||||
#ifdef WITH_NISPLUS_HOME
|
||||
@ -1450,8 +1435,8 @@ FN_GLOBAL_STRING(lp_lockdir, &Globals.szLockDir)
|
||||
FN_GLOBAL_STRING(lp_utmpdir, &Globals.szUtmpDir)
|
||||
FN_GLOBAL_STRING(lp_wtmpdir, &Globals.szWtmpDir)
|
||||
FN_GLOBAL_STRING(lp_utmp_hostname, &Globals.szUtmpHostname)
|
||||
FN_GLOBAL_BOOL(lp_utmp_consolidate, &Globals.bUtmpConsolidate)
|
||||
#endif /* WITH_UTMP */
|
||||
FN_GLOBAL_BOOL(lp_utmp, &Globals.bUtmp)
|
||||
#endif
|
||||
FN_GLOBAL_STRING(lp_rootdir, &Globals.szRootdir)
|
||||
FN_GLOBAL_STRING(lp_source_environment, &Globals.szSourceEnv)
|
||||
FN_GLOBAL_STRING(lp_defaultservice, &Globals.szDefaultService)
|
||||
@ -1552,7 +1537,6 @@ FN_GLOBAL_BOOL(lp_debug_hires_timestamp, &Globals.bDebugHiresTimestamp)
|
||||
FN_GLOBAL_BOOL(lp_debug_pid, &Globals.bDebugPid)
|
||||
FN_GLOBAL_BOOL(lp_debug_uid, &Globals.bDebugUid)
|
||||
FN_GLOBAL_BOOL(lp_browse_list, &Globals.bBrowseList)
|
||||
FN_GLOBAL_BOOL(lp_unix_realname, &Globals.bUnixRealname)
|
||||
FN_GLOBAL_BOOL(lp_nis_home_map, &Globals.bNISHomeMap)
|
||||
static FN_GLOBAL_BOOL(lp_time_server, &Globals.bTimeServer)
|
||||
FN_GLOBAL_BOOL(lp_bind_interfaces_only, &Globals.bBindInterfacesOnly)
|
||||
@ -1665,9 +1649,6 @@ FN_LOCAL_BOOL(lp_map_archive, bMap_archive)
|
||||
FN_LOCAL_BOOL(lp_locking, bLocking)
|
||||
FN_LOCAL_BOOL(lp_strict_locking, bStrictLocking)
|
||||
FN_LOCAL_BOOL(lp_posix_locking, bPosixLocking)
|
||||
#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)
|
||||
|
@ -337,12 +337,12 @@ static BOOL proc_pam_session(pam_handle_t *pamh, char *user, char *tty, BOOL fla
|
||||
/*
|
||||
* PAM Externally accessible Session handler
|
||||
*/
|
||||
BOOL pam_session(BOOL flag, const connection_struct *conn, char *tty)
|
||||
BOOL pam_session(BOOL flag, const char *in_user, char *tty)
|
||||
{
|
||||
pam_handle_t *pamh = NULL;
|
||||
char * user;
|
||||
|
||||
user = malloc(strlen(conn->user)+1);
|
||||
user = malloc(strlen(in_user)+1);
|
||||
if ( user == NULL )
|
||||
{
|
||||
DEBUG(0, ("PAM: PAM_session Malloc Failed!\n"));
|
||||
@ -350,7 +350,7 @@ BOOL pam_session(BOOL flag, const connection_struct *conn, char *tty)
|
||||
}
|
||||
|
||||
/* This is freed by PAM */
|
||||
StrnCpy(user, conn->user, strlen(conn->user)+1);
|
||||
StrnCpy(user, in_user, strlen(in_user)+1);
|
||||
|
||||
if (!proc_pam_start(&pamh, user))
|
||||
{
|
||||
|
@ -1285,11 +1285,7 @@ static BOOL build_sam_account (SAM_ACCOUNT *sam_pass,
|
||||
standard_sub_advanced(-1, pw_buf->smb_name, "", gid, str);
|
||||
pdb_set_homedir(sam_pass, str);
|
||||
|
||||
if (lp_unix_realname())
|
||||
pdb_set_fullname(sam_pass, pwfile->pw_gecos);
|
||||
else
|
||||
pdb_set_fullname(sam_pass, "<Full Name>");
|
||||
|
||||
pdb_set_fullname(sam_pass, pwfile->pw_gecos);
|
||||
|
||||
/* set other user information that we have */
|
||||
pdb_set_group_rid (sam_pass, pdb_gid_to_group_rid(pdb_get_gid(&global_sam_pass)) );
|
||||
|
@ -27,11 +27,6 @@ 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
|
||||
|
||||
/****************************************************************************
|
||||
Return the connection tdb context (used for message send all).
|
||||
****************************************************************************/
|
||||
@ -64,11 +59,6 @@ BOOL yield_connection(connection_struct *conn,char *name,int max_connections)
|
||||
|
||||
tdb_delete(tdb, kbuf);
|
||||
|
||||
#ifdef WITH_UTMP
|
||||
if(conn)
|
||||
utmp_yield(key.pid, conn);
|
||||
#endif
|
||||
|
||||
return(True);
|
||||
}
|
||||
|
||||
@ -120,769 +110,6 @@ 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
|
||||
|
||||
With grateful thanks since then to many who have helped port it to
|
||||
different operating systems. The variety of OS quirks thereby
|
||||
uncovered is amazing...
|
||||
|
||||
Hints for porting:
|
||||
o Always attempt to use programmatic interface (pututline() etc.)
|
||||
Indeed, at present only programmatic use is supported.
|
||||
o The only currently supported programmatic interface to "wtmp{,x}"
|
||||
is through "updwtmp*()" routines.
|
||||
o The "x" (utmpx/wtmpx; HAVE_UTMPX_H) seems preferable.
|
||||
o The HAVE_* items should identify supported features.
|
||||
o If at all possible, avoid "if defined(MY-OS)" constructions.
|
||||
|
||||
OS observations and status:
|
||||
Almost every OS seems to have its own quirks.
|
||||
|
||||
Solaris 2.x:
|
||||
Tested on 2.6 and 2.7; should be OK on other flavours.
|
||||
AIX:
|
||||
Apparently has utmpx.h but doesn't implement.
|
||||
OSF:
|
||||
Has utmpx.h, but (e.g.) no "getutmpx()". (Is this like AIX ?)
|
||||
Redhat 6:
|
||||
utmpx.h seems not to set default filenames. non-x better.
|
||||
IRIX 6.5:
|
||||
Not tested. Appears to have "x".
|
||||
HP-UX 9.x:
|
||||
Not tested. Appears to lack "x".
|
||||
HP-UX 10.x:
|
||||
Not tested.
|
||||
"updwtmp*()" routines seem absent, so no current wtmp* support.
|
||||
Has "ut_addr": probably trivial to implement (although remember
|
||||
that IPv6 is coming...).
|
||||
|
||||
FreeBSD:
|
||||
No "putut*()" type of interface.
|
||||
No "ut_type" and associated defines.
|
||||
Write files directly. Alternatively use its login(3)/logout(3).
|
||||
SunOS 4:
|
||||
Not tested. Resembles FreeBSD, but no login()/logout().
|
||||
|
||||
lastlog:
|
||||
Should "lastlog" files, if any, be updated?
|
||||
BSD systems (SunOS 4, FreeBSD):
|
||||
o Prominent mention on man pages.
|
||||
System-V (e.g. Solaris 2):
|
||||
o No mention on man pages, even under "man -k".
|
||||
o Has a "/var/adm/lastlog" file, but pututxline() etc. seem
|
||||
not to touch it.
|
||||
o Despite downplaying (above), nevertheless has <lastlog.h>.
|
||||
So perhaps UN*X "lastlog" facility is intended for tty/terminal only?
|
||||
|
||||
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.
|
||||
|
||||
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 "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.
|
||||
|
||||
****************************************************************************/
|
||||
|
||||
#include <utmp.h>
|
||||
|
||||
#ifdef HAVE_UTMPX_H
|
||||
#include <utmpx.h>
|
||||
#endif
|
||||
|
||||
/* BSD systems: some may need lastlog.h (SunOS 4), some may not (FreeBSD) */
|
||||
/* Some System-V systems (e.g. Solaris 2) declare this too. */
|
||||
#ifdef HAVE_LASTLOG_H
|
||||
#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.
|
||||
*/
|
||||
|
||||
static TDB_CONTEXT *tdb_utmp;
|
||||
|
||||
struct utmp_tdb_data {
|
||||
pid_t pid;
|
||||
int cnum;
|
||||
};
|
||||
|
||||
static int utmp_claim_tdb(const connection_struct *conn)
|
||||
{
|
||||
struct utmp_tdb_data udata;
|
||||
int i, slotnum;
|
||||
TDB_DATA kbuf, dbuf;
|
||||
|
||||
if (!tdb_utmp) {
|
||||
tdb_utmp = tdb_open(lock_path("utmp.tdb"), 0,
|
||||
TDB_CLEAR_IF_FIRST, O_RDWR | O_CREAT, 0644);
|
||||
}
|
||||
if (!tdb_utmp) return(-1);
|
||||
|
||||
DEBUG(2,("utmp_claim_tdb: entered\n"));
|
||||
|
||||
ZERO_STRUCT(udata);
|
||||
udata.pid = sys_getpid();
|
||||
udata.cnum = conn ? conn->cnum : -1;
|
||||
|
||||
dbuf.dptr = (char *) &udata;
|
||||
dbuf.dsize = sizeof(udata);
|
||||
|
||||
/* The key is simply a number as close as possible to zero: find it */
|
||||
slotnum = -1;
|
||||
/* stop loop when overflow +ve integers (a huge, busy machine!) */
|
||||
for (i = 0; i >= 0 ; i++) {
|
||||
kbuf.dptr = (char *) &i;
|
||||
kbuf.dsize = sizeof(i);
|
||||
|
||||
if (tdb_store(tdb_utmp, kbuf, dbuf, TDB_INSERT) == 0) {
|
||||
/* have successfully grabbed a free slot */
|
||||
slotnum = i;
|
||||
|
||||
/* store the inverse for faster utmp_yield_tdb() */
|
||||
tdb_store(tdb_utmp, dbuf, kbuf, TDB_INSERT);
|
||||
|
||||
break; /* Got it; escape */
|
||||
}
|
||||
}
|
||||
if (slotnum < 0) { /* more connections than positive integers! */
|
||||
DEBUG(2,("utmp_claim_tdb: failed\n"));
|
||||
return(-1);
|
||||
}
|
||||
|
||||
DEBUG(2,("utmp_claim_tdb: leaving with %d\n", slotnum));
|
||||
|
||||
return(slotnum);
|
||||
}
|
||||
|
||||
static int utmp_yield_tdb(const connection_struct *conn)
|
||||
{
|
||||
struct utmp_tdb_data revkey;
|
||||
int i, slotnum;
|
||||
TDB_DATA kbuf, dbuf;
|
||||
|
||||
if (!tdb_utmp) {
|
||||
return(-1);
|
||||
}
|
||||
|
||||
DEBUG(2,("utmp_yield_tdb: entered\n"));
|
||||
|
||||
ZERO_STRUCT(revkey);
|
||||
revkey.pid = sys_getpid();
|
||||
revkey.cnum = conn ? conn->cnum : -1;
|
||||
|
||||
kbuf.dptr = (char *) &revkey;
|
||||
kbuf.dsize = sizeof(revkey);
|
||||
|
||||
dbuf = tdb_fetch(tdb_utmp, kbuf);
|
||||
if (dbuf.dptr == NULL) {
|
||||
DEBUG(2,("utmp_yield_tdb: failed\n"));
|
||||
return(-1); /* shouldn't happen */
|
||||
}
|
||||
|
||||
/* Save our result */
|
||||
slotnum = (int) dbuf.dptr;
|
||||
|
||||
/* Tidy up */
|
||||
tdb_delete(tdb_utmp, kbuf);
|
||||
tdb_delete(tdb_utmp, dbuf);
|
||||
|
||||
free(dbuf.dptr);
|
||||
DEBUG(2,("utmp_yield_tdb: leaving with %d\n", slotnum));
|
||||
|
||||
return(slotnum);
|
||||
}
|
||||
|
||||
#if defined(HAVE_UT_UT_ID)
|
||||
/****************************************************************************
|
||||
encode the unique connection number into "ut_id"
|
||||
****************************************************************************/
|
||||
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 */
|
||||
}
|
||||
#endif /* defined(HAVE_UT_UT_ID) */
|
||||
|
||||
/*
|
||||
* ut_line:
|
||||
* size small, e.g. Solaris: 12; FreeBSD: 8
|
||||
* pattern conventions differ across systems.
|
||||
* So take care in tweaking the template below.
|
||||
* Arguably, this could be yet another smb.conf parameter.
|
||||
*/
|
||||
static const char *ut_line_template =
|
||||
#if defined(__FreeBSD__)
|
||||
"smb%d" ;
|
||||
#else
|
||||
"smb/%d" ;
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
Fill in a utmp (not utmpx) template
|
||||
****************************************************************************/
|
||||
static int utmp_fill(struct utmp *u, const connection_struct *conn, pid_t pid,
|
||||
int i, pstring host)
|
||||
{
|
||||
#if defined(HAVE_UT_UT_TIME)
|
||||
struct timeval timeval;
|
||||
#endif /* defined(HAVE_UT_UT_TIME) */
|
||||
char line_tmp[1024]; /* plenty big enough for slprintf() */
|
||||
int line_len;
|
||||
int rc = 0;
|
||||
|
||||
/*
|
||||
* ut_name, ut_user:
|
||||
* Several (all?) systems seems to define one as the other.
|
||||
* It is easier and clearer simply to let the following take its course,
|
||||
* rather than to try to detect and optimise.
|
||||
*/
|
||||
#if defined(HAVE_UT_UT_USER)
|
||||
pstrcpy(u->ut_user, conn->user);
|
||||
#endif /* defined(HAVE_UT_UT_USER) */
|
||||
|
||||
#if defined(HAVE_UT_UT_NAME)
|
||||
pstrcpy(u->ut_name, conn->user);
|
||||
#endif /* defined(HAVE_UT_UT_NAME) */
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
memset(line_tmp, '\0', sizeof(line_tmp));
|
||||
slprintf(line_tmp, sizeof(line_tmp)-1, (char *) ut_line_template, i);
|
||||
line_len = strlen(line_tmp);
|
||||
if (line_len <= sizeof(u->ut_line)) {
|
||||
memcpy(u->ut_line, line_tmp, sizeof(u->ut_line));
|
||||
}
|
||||
else {
|
||||
DEBUG(1,("utmp_fill: ut_line exceeds field length(%d > %d)\n",
|
||||
line_len, sizeof(u->ut_line)));
|
||||
return(1);
|
||||
}
|
||||
|
||||
#if defined(HAVE_UT_UT_PID)
|
||||
u->ut_pid = pid;
|
||||
#endif /* defined(HAVE_UT_UT_PID) */
|
||||
|
||||
/*
|
||||
* 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);
|
||||
u->ut_time = timeval.tv_sec;
|
||||
#endif /* defined(HAVE_UT_UT_TIME) */
|
||||
|
||||
#if defined(HAVE_UT_UT_TV)
|
||||
gettimeofday(&timeval, NULL);
|
||||
u->ut_tv = timeval;
|
||||
#endif /* defined(HAVE_UT_UT_TV) */
|
||||
|
||||
#if defined(HAVE_UT_UT_HOST)
|
||||
if (host) {
|
||||
pstrcpy(u->ut_host, host);
|
||||
}
|
||||
#endif /* defined(HAVE_UT_UT_HOST) */
|
||||
|
||||
#if defined(HAVE_UT_UT_ADDR)
|
||||
/*
|
||||
* "(unsigned long) ut_addr" apparently exists on at least HP-UX 10.20.
|
||||
* Volunteer to implement, please ...
|
||||
*/
|
||||
#endif /* defined(HAVE_UT_UT_ADDR) */
|
||||
|
||||
#if defined(HAVE_UT_UT_ID)
|
||||
rc = ut_id_encode(i, u->ut_id);
|
||||
#endif /* defined(HAVE_UT_UT_ID) */
|
||||
|
||||
return(rc);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
Default paths to various {u,w}tmp{,x} files
|
||||
****************************************************************************/
|
||||
#ifdef HAVE_UTMPX_H
|
||||
|
||||
static const char *ux_pathname =
|
||||
# if defined (UTMPX_FILE)
|
||||
UTMPX_FILE ;
|
||||
# elif defined (_UTMPX_FILE)
|
||||
_UTMPX_FILE ;
|
||||
# elif defined (_PATH_UTMPX)
|
||||
_PATH_UTMPX ;
|
||||
# else
|
||||
"" ;
|
||||
# endif
|
||||
|
||||
static const char *wx_pathname =
|
||||
# if defined (WTMPX_FILE)
|
||||
WTMPX_FILE ;
|
||||
# elif defined (_WTMPX_FILE)
|
||||
_WTMPX_FILE ;
|
||||
# elif defined (_PATH_WTMPX)
|
||||
_PATH_WTMPX ;
|
||||
# else
|
||||
"" ;
|
||||
# endif
|
||||
|
||||
#endif /* HAVE_UTMPX_H */
|
||||
|
||||
static const char *ut_pathname =
|
||||
# if defined (UTMP_FILE)
|
||||
UTMP_FILE ;
|
||||
# elif defined (_UTMP_FILE)
|
||||
_UTMP_FILE ;
|
||||
# elif defined (_PATH_UTMP)
|
||||
_PATH_UTMP ;
|
||||
# else
|
||||
"" ;
|
||||
# endif
|
||||
|
||||
static const char *wt_pathname =
|
||||
# if defined (WTMP_FILE)
|
||||
WTMP_FILE ;
|
||||
# elif defined (_WTMP_FILE)
|
||||
_WTMP_FILE ;
|
||||
# elif defined (_PATH_WTMP)
|
||||
_PATH_WTMP ;
|
||||
# else
|
||||
"" ;
|
||||
# endif
|
||||
|
||||
/* BSD-like systems might want "lastlog" support. */
|
||||
/* *** Not yet implemented */
|
||||
#ifndef HAVE_PUTUTLINE /* see "pututline_my()" */
|
||||
static const char *ll_pathname =
|
||||
# if defined (_PATH_LASTLOG) /* what other names (if any?) */
|
||||
_PATH_LASTLOG ;
|
||||
# else
|
||||
"" ;
|
||||
# endif /* _PATH_LASTLOG */
|
||||
#endif /* HAVE_PUTUTLINE */
|
||||
|
||||
/*
|
||||
* Get name of {u,w}tmp{,x} file.
|
||||
* return: fname contains filename
|
||||
* Possibly empty if this code not yet ported to this system.
|
||||
*
|
||||
* 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)
|
||||
{
|
||||
pstring dirname;
|
||||
|
||||
pstrcpy(dirname, "");
|
||||
|
||||
/* For w-files, first look for explicit "wtmp dir" */
|
||||
if (uw_name[0] == 'w') {
|
||||
pstrcpy(dirname,lp_wtmpdir());
|
||||
trim_string(dirname,"","/");
|
||||
}
|
||||
|
||||
/* 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 explicit directory above, use it */
|
||||
if (dirname != 0 && strlen(dirname) != 0) {
|
||||
pstrcpy(fname, dirname);
|
||||
pstrcat(fname, "/");
|
||||
pstrcat(fname, uw_name);
|
||||
return;
|
||||
}
|
||||
|
||||
/* No explicit directory: attempt to use default paths */
|
||||
if (strlen(uw_default) == 0) {
|
||||
/* No explicit setting, no known default.
|
||||
* Has it yet been ported to this OS?
|
||||
*/
|
||||
DEBUG(2,("uw_pathname: unable to determine pathname\n"));
|
||||
}
|
||||
pstrcpy(fname, 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)
|
||||
{
|
||||
DEBUG(1,("pututline_my: not yet implemented\n"));
|
||||
/* BSD implementor: may want to consider (or not) adjusting "lastlog" */
|
||||
}
|
||||
#endif /* HAVE_PUTUTLINE */
|
||||
|
||||
#ifndef HAVE_UPDWTMP
|
||||
/****************************************************************************
|
||||
Update wtmp file directly. No subroutine interface: probably a BSD system.
|
||||
Credit: Michail Vidiassov <master@iaas.msu.ru>
|
||||
****************************************************************************/
|
||||
static void updwtmp_my(pstring wname, struct utmp *u, BOOL claim)
|
||||
{
|
||||
int fd;
|
||||
struct stat buf;
|
||||
|
||||
if (! claim) {
|
||||
/*
|
||||
* BSD-like systems:
|
||||
* may use empty ut_name to distinguish a logout record.
|
||||
*
|
||||
* May need "if defined(SUNOS4)" etc. around some of these,
|
||||
* but try to avoid if possible.
|
||||
*
|
||||
* SunOS 4:
|
||||
* man page indicates ut_name and ut_host both NULL
|
||||
* FreeBSD 4.0:
|
||||
* 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));
|
||||
}
|
||||
/* Stolen from logwtmp function in libutil.
|
||||
* May be more locking/blocking is needed?
|
||||
*/
|
||||
if ((fd = open(wname, O_WRONLY|O_APPEND, 0)) < 0)
|
||||
return;
|
||||
if (fstat(fd, &buf) == 0) {
|
||||
if (write(fd, (char *)u, sizeof(struct utmp)) != sizeof(struct utmp))
|
||||
(void) ftruncate(fd, buf.st_size);
|
||||
}
|
||||
(void) close(fd);
|
||||
}
|
||||
#endif /* HAVE_UPDWTMP */
|
||||
|
||||
/****************************************************************************
|
||||
Update via utmp/wtmp (not utmpx/wtmpx)
|
||||
****************************************************************************/
|
||||
static void utmp_nox_update(struct utmp *u, pstring host, BOOL claim)
|
||||
{
|
||||
pstring uname, wname;
|
||||
#if defined(PUTUTLINE_RETURNS_UTMP)
|
||||
struct utmp *urc;
|
||||
#endif /* PUTUTLINE_RETURNS_UTMP */
|
||||
|
||||
uw_pathname(uname, "utmp", ut_pathname);
|
||||
DEBUG(2,("utmp_nox_update: uname:%s\n", uname));
|
||||
|
||||
#ifdef HAVE_PUTUTLINE
|
||||
if (strlen(uname) != 0) {
|
||||
utmpname(uname);
|
||||
}
|
||||
|
||||
# if defined(PUTUTLINE_RETURNS_UTMP)
|
||||
setutent();
|
||||
urc = pututline(u);
|
||||
endutent();
|
||||
if (urc == NULL) {
|
||||
DEBUG(2,("utmp_nox_update: pututline() failed\n"));
|
||||
return;
|
||||
}
|
||||
# else /* PUTUTLINE_RETURNS_UTMP */
|
||||
setutent();
|
||||
pututline(u);
|
||||
endutent();
|
||||
# endif /* PUTUTLINE_RETURNS_UTMP */
|
||||
|
||||
#else /* HAVE_PUTUTLINE */
|
||||
if (strlen(uname) != 0) {
|
||||
pututline_my(uname, u, claim);
|
||||
}
|
||||
#endif /* HAVE_PUTUTLINE */
|
||||
|
||||
uw_pathname(wname, "wtmp", wt_pathname);
|
||||
DEBUG(2,("utmp_nox_update: wname:%s\n", wname));
|
||||
if (strlen(wname) != 0) {
|
||||
#ifdef HAVE_UPDWTMP
|
||||
updwtmp(wname, u);
|
||||
/*
|
||||
* updwtmp() and the newer updwtmpx() may be unsymmetrical.
|
||||
* At least one OS, Solaris 2.x declares the former in the
|
||||
* "utmpx" (latter) file and context.
|
||||
* In the Solaris case this is irrelevant: it has both and
|
||||
* we always prefer the "x" case, so doesn't come here.
|
||||
* But are there other systems, with no "x", which lack
|
||||
* updwtmp() perhaps?
|
||||
*/
|
||||
#else
|
||||
updwtmp_my(wname, u, claim);
|
||||
#endif /* HAVE_UPDWTMP */
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
Update via utmpx/wtmpx (preferred) or via utmp/wtmp
|
||||
****************************************************************************/
|
||||
static void utmp_update(struct utmp *u, pstring host, BOOL claim)
|
||||
{
|
||||
#if !defined(HAVE_UTMPX_H)
|
||||
/* No utmpx stuff. Drop to non-x stuff */
|
||||
utmp_nox_update(u, host, 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, host, 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, host, claim);
|
||||
#else
|
||||
pstring uname, wname;
|
||||
struct utmpx ux, *uxrc;
|
||||
|
||||
getutmpx(u, &ux);
|
||||
if (host) {
|
||||
#if defined(HAVE_UX_UT_SYSLEN)
|
||||
ux.ut_syslen = strlen(host) + 1; /* include end NULL */
|
||||
#endif /* defined(HAVE_UX_UT_SYSLEN) */
|
||||
pstrcpy(ux.ut_host, host);
|
||||
}
|
||||
|
||||
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
|
||||
* define default filenames.
|
||||
* 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, host, claim);
|
||||
}
|
||||
else {
|
||||
utmpxname(uname);
|
||||
setutxent();
|
||||
uxrc = pututxline(&ux);
|
||||
endutxent();
|
||||
if (uxrc == NULL) {
|
||||
DEBUG(2,("utmp_update: pututxline() failed\n"));
|
||||
return;
|
||||
}
|
||||
#ifdef HAVE_UPDWTMPX
|
||||
updwtmpx(wname, &ux);
|
||||
#else
|
||||
/* Have utmpx.h but no "updwtmpx()". */
|
||||
DEBUG(1,("utmp_update: no updwtmpx() function\n"));
|
||||
#endif /* HAVE_UPDWTMPX */
|
||||
}
|
||||
#endif /* HAVE_UTMPX_H */
|
||||
}
|
||||
|
||||
/*
|
||||
* "utmp consolidate": some background:
|
||||
* False (default):
|
||||
* In "utmp" files note every connection via this process.
|
||||
* Argument "i" is simply a tty-like number we can use as-is.
|
||||
* True:
|
||||
* In "utmp" files, only note first open and final close. Keep:
|
||||
* o count of open processes;
|
||||
* o record value of first "i", to use as "i" in final close.
|
||||
*/
|
||||
static int utmp_count = 0;
|
||||
static int utmp_consolidate_conn_num;
|
||||
|
||||
/****************************************************************************
|
||||
close a connection
|
||||
****************************************************************************/
|
||||
static void utmp_yield(pid_t pid, const connection_struct *conn)
|
||||
{
|
||||
struct utmp u;
|
||||
int conn_num, i;
|
||||
|
||||
if (! lp_utmp(SNUM(conn))) {
|
||||
DEBUG(2,("utmp_yield: lp_utmp() NULL\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
i = utmp_yield_tdb(conn);
|
||||
if (i < 0) {
|
||||
DEBUG(2,("utmp_yield: utmp_yield_tdb() failed\n"));
|
||||
return;
|
||||
}
|
||||
conn_num = i;
|
||||
DEBUG(2,("utmp_yield: conn: user:%s cnum:%d i:%d (utmp_count:%d)\n",
|
||||
conn->user, conn->cnum, i, utmp_count));
|
||||
|
||||
utmp_count -= 1;
|
||||
if (lp_utmp_consolidate()) {
|
||||
if (utmp_count > 0) {
|
||||
DEBUG(2,("utmp_yield: utmp consolidate: %d entries still open\n", utmp_count));
|
||||
return;
|
||||
}
|
||||
else {
|
||||
/* consolidate; final close: override conn_num */
|
||||
conn_num = utmp_consolidate_conn_num;
|
||||
}
|
||||
}
|
||||
|
||||
memset((char *)&u, '\0', sizeof(struct utmp));
|
||||
|
||||
#if defined(HAVE_UT_UT_EXIT)
|
||||
u.ut_exit.e_termination = 0;
|
||||
u.ut_exit.e_exit = 0;
|
||||
#endif /* defined(HAVE_UT_UT_EXIT) */
|
||||
|
||||
#if defined(HAVE_UT_UT_TYPE)
|
||||
u.ut_type = DEAD_PROCESS;
|
||||
#endif /* defined(HAVE_UT_UT_TYPE) */
|
||||
|
||||
if (utmp_fill(&u, conn, pid, conn_num, NULL) == 0) {
|
||||
utmp_update(&u, NULL, False);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
open a connection
|
||||
****************************************************************************/
|
||||
static void utmp_claim(const struct connections_data *crec, const connection_struct *conn)
|
||||
{
|
||||
struct utmp u;
|
||||
pstring host;
|
||||
int i;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
i = utmp_claim_tdb(conn);
|
||||
if (i < 0) {
|
||||
DEBUG(2,("utmp_claim: utmp_claim_tdb() failed\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
pstrcpy(host, lp_utmp_hostname());
|
||||
if (host == 0 || strlen(host) == 0) {
|
||||
pstrcpy(host, crec->machine);
|
||||
}
|
||||
else {
|
||||
/* explicit "utmp host": expand for any "%" variables */
|
||||
standard_sub_basic(host);
|
||||
}
|
||||
|
||||
DEBUG(2,("utmp_claim: conn: user:%s cnum:%d i:%d (utmp_count:%d)\n",
|
||||
conn->user, conn->cnum, i, utmp_count));
|
||||
DEBUG(2,("utmp_claim: crec: pid:%d, cnum:%d name:%s addr:%s mach:%s DNS:%s host:%s\n",
|
||||
crec->pid, crec->cnum, crec->name, crec->addr, crec->machine, client_name(), host));
|
||||
|
||||
utmp_count += 1;
|
||||
if (lp_utmp_consolidate()) {
|
||||
if (utmp_count > 1) {
|
||||
DEBUG(2,("utmp_claim: utmp consolidate: %d entries already open\n", (utmp_count-1)));
|
||||
return;
|
||||
}
|
||||
else {
|
||||
/* consolidate; first open: keep record of "i" */
|
||||
utmp_consolidate_conn_num = i;
|
||||
}
|
||||
}
|
||||
|
||||
memset((char *)&u, '\0', sizeof(struct utmp));
|
||||
|
||||
#if defined(HAVE_UT_UT_TYPE)
|
||||
u.ut_type = USER_PROCESS;
|
||||
#endif /* defined(HAVE_UT_UT_TYPE) */
|
||||
|
||||
if (utmp_fill(&u, conn, crec->pid, i, host) == 0) {
|
||||
utmp_update(&u, host, True);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* WITH_UTMP */
|
||||
|
@ -110,8 +110,9 @@ user_struct *get_valid_user_struct(uint16 vuid)
|
||||
|
||||
for (usp=validated_users;usp;usp=usp->next,count++) {
|
||||
if (vuid == usp->vuid) {
|
||||
if (count > 10)
|
||||
DLIST_PROMOTE(validated_users, usp);
|
||||
if (count > 10) {
|
||||
DLIST_PROMOTE(validated_users, usp);
|
||||
}
|
||||
return usp;
|
||||
}
|
||||
}
|
||||
@ -129,6 +130,8 @@ void invalidate_vuid(uint16 vuid)
|
||||
if (vuser == NULL)
|
||||
return;
|
||||
|
||||
session_yield(vuid);
|
||||
|
||||
DLIST_REMOVE(validated_users, vuser);
|
||||
|
||||
safe_free(vuser->groups);
|
||||
@ -137,6 +140,20 @@ void invalidate_vuid(uint16 vuid)
|
||||
num_validated_vuids--;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
invalidate all vuid entries for this process
|
||||
****************************************************************************/
|
||||
void invalidate_all_vuids(void)
|
||||
{
|
||||
user_struct *usp, *next=NULL;
|
||||
|
||||
for (usp=validated_users;usp;usp=next) {
|
||||
next = usp->next;
|
||||
|
||||
invalidate_vuid(usp->vuid);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
return a validated username
|
||||
****************************************************************************/
|
||||
@ -244,8 +261,8 @@ has been given. vuid is biased by an offset. This allows us to
|
||||
tell random client vuid's (normally zero) from valid vuids.
|
||||
****************************************************************************/
|
||||
|
||||
uint16 register_vuid(uid_t uid,gid_t gid, char *unix_name, char *requested_name,
|
||||
char *domain,BOOL guest)
|
||||
int register_vuid(uid_t uid,gid_t gid, char *unix_name, char *requested_name,
|
||||
char *domain,BOOL guest)
|
||||
{
|
||||
user_struct *vuser = NULL;
|
||||
struct passwd *pwfile; /* for getting real name from passwd file */
|
||||
@ -305,12 +322,15 @@ uint16 register_vuid(uid_t uid,gid_t gid, char *unix_name, char *requested_name,
|
||||
DEBUG(3,("uid %d registered to name %s\n",(int)uid,unix_name));
|
||||
|
||||
DEBUG(3, ("Clearing default real name\n"));
|
||||
fstrcpy(vuser->user.full_name, "<Full Name>");
|
||||
if (lp_unix_realname()) {
|
||||
if ((pwfile=sys_getpwnam(vuser->user.unix_name))!= NULL) {
|
||||
DEBUG(3, ("User name: %s\tReal name: %s\n",vuser->user.unix_name,pwfile->pw_gecos));
|
||||
fstrcpy(vuser->user.full_name, pwfile->pw_gecos);
|
||||
}
|
||||
if ((pwfile=sys_getpwnam(vuser->user.unix_name))!= NULL) {
|
||||
DEBUG(3, ("User name: %s\tReal name: %s\n",vuser->user.unix_name,pwfile->pw_gecos));
|
||||
fstrcpy(vuser->user.full_name, pwfile->pw_gecos);
|
||||
}
|
||||
|
||||
if (!session_claim(vuser->vuid)) {
|
||||
DEBUG(1,("Failed to claim session for vuid=%d\n", vuser->vuid));
|
||||
invalidate_vuid(vuser->vuid);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return vuser->vuid;
|
||||
@ -737,6 +757,13 @@ BOOL authorise_login(int snum,char *user,char *password, int pwlen,
|
||||
BOOL *guest,BOOL *force,uint16 vuid)
|
||||
{
|
||||
BOOL ok = False;
|
||||
user_struct *vuser = get_valid_user_struct(vuid);
|
||||
|
||||
if (lp_security() > SEC_SHARE && !vuser) {
|
||||
DEBUG(1,("authorise_login: refusing user %s with no session setup\n",
|
||||
user));
|
||||
return False;
|
||||
}
|
||||
|
||||
*guest = False;
|
||||
|
||||
@ -760,9 +787,6 @@ BOOL authorise_login(int snum,char *user,char *password, int pwlen,
|
||||
|
||||
if (!(GUEST_ONLY(snum) && GUEST_OK(snum)))
|
||||
{
|
||||
|
||||
user_struct *vuser = get_valid_user_struct(vuid);
|
||||
|
||||
/* check the given username and password */
|
||||
if (!ok && (*user) && user_ok(user,snum)) {
|
||||
ok = password_ok(user,password, pwlen, NULL);
|
||||
|
@ -671,7 +671,7 @@ reply to a session setup command
|
||||
|
||||
int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
|
||||
{
|
||||
uint16 sess_vuid;
|
||||
int sess_vuid;
|
||||
gid_t gid;
|
||||
uid_t uid;
|
||||
int smb_bufsize;
|
||||
@ -1037,6 +1037,11 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int
|
||||
to a uid can get through without a password, on the same VC */
|
||||
|
||||
sess_vuid = register_vuid(uid,gid,user,current_user_info.smb_name,domain,guest);
|
||||
|
||||
if (sess_vuid == -1) {
|
||||
return(ERROR(ERRDOS,ERRnoaccess));
|
||||
}
|
||||
|
||||
|
||||
SSVAL(outbuf,smb_uid,sess_vuid);
|
||||
SSVAL(inbuf,smb_uid,sess_vuid);
|
||||
|
@ -441,12 +441,14 @@ void exit_server(char *reason)
|
||||
|
||||
conn_close_all();
|
||||
|
||||
invalidate_all_vuids();
|
||||
|
||||
/* delete our entry in the connections database. */
|
||||
if (lp_status(-1)) {
|
||||
yield_connection(NULL,"",MAXSTATUS);
|
||||
}
|
||||
|
||||
respond_to_all_remaining_local_messages();
|
||||
respond_to_all_remaining_local_messages();
|
||||
decrement_smbd_process_count();
|
||||
|
||||
#ifdef WITH_DFS
|
||||
|
@ -207,6 +207,7 @@ size_t tdb_pack(char *buf, int bufsize, char *fmt, ...)
|
||||
|
||||
/* useful pair of routines for packing/unpacking data consisting of
|
||||
integers and strings */
|
||||
|
||||
int tdb_unpack(char *buf, int bufsize, char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
Loading…
Reference in New Issue
Block a user