From 9ce5a03ccbcc21c60a3dbc39b1dbd06b30655852 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 18 Apr 2001 16:41:04 +0000 Subject: merge from 2.2 (This used to be commit f52a5014ee325f9d91f266f88eac51b6136a75b9) --- source3/Makefile.in | 1 + source3/auth/pampass.c | 6 +- source3/include/local.h | 8 + source3/include/proto.h | 23 +- source3/include/smb.h | 2 + source3/param/loadparm.c | 37 +- source3/passdb/pampass.c | 6 +- source3/passdb/pdb_smbpasswd.c | 6 +- source3/smbd/connection.c | 773 ----------------------------------------- source3/smbd/password.c | 50 ++- source3/smbd/reply.c | 7 +- source3/smbd/server.c | 4 +- source3/tdb/tdbutil.c | 1 + 13 files changed, 91 insertions(+), 833 deletions(-) (limited to 'source3') diff --git a/source3/Makefile.in b/source3/Makefile.in index 5c9e817776..a639f9d3dc 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -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 \ diff --git a/source3/auth/pampass.c b/source3/auth/pampass.c index 271c46045b..d9137045e2 100644 --- a/source3/auth/pampass.c +++ b/source3/auth/pampass.c @@ -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)) { diff --git a/source3/include/local.h b/source3/include/local.h index f693d18623..e534f39306 100644 --- a/source3/include/local.h +++ b/source3/include/local.h @@ -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 diff --git a/source3/include/proto.h b/source3/include/proto.h index 2497169677..a02349a075 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -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); diff --git a/source3/include/smb.h b/source3/include/smb.h index eae19921f8..aa1356d821 100644 --- a/source3/include/smb.h +++ b/source3/include/smb.h @@ -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" diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c index 11697b5044..c29418ee87 100644 --- a/source3/param/loadparm.c +++ b/source3/param/loadparm.c @@ -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) diff --git a/source3/passdb/pampass.c b/source3/passdb/pampass.c index 271c46045b..d9137045e2 100644 --- a/source3/passdb/pampass.c +++ b/source3/passdb/pampass.c @@ -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)) { diff --git a/source3/passdb/pdb_smbpasswd.c b/source3/passdb/pdb_smbpasswd.c index 2449eec1f0..a814c8da8e 100644 --- a/source3/passdb/pdb_smbpasswd.c +++ b/source3/passdb/pdb_smbpasswd.c @@ -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, ""); - + 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)) ); diff --git a/source3/smbd/connection.c b/source3/smbd/connection.c index 125b2fbbe5..43e89abfbf 100644 --- a/source3/smbd/connection.c +++ b/source3/smbd/connection.c @@ -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 . - 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 - -#ifdef HAVE_UTMPX_H -#include -#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 -#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 -****************************************************************************/ -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 */ diff --git a/source3/smbd/password.c b/source3/smbd/password.c index fa973dd720..6c0fe79845 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -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, ""); - 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); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 82ac230764..15e8e9537e 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -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); diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 84b7109294..d2a9a64966 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -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 diff --git a/source3/tdb/tdbutil.c b/source3/tdb/tdbutil.c index 95c90efeed..c387644efc 100644 --- a/source3/tdb/tdbutil.c +++ b/source3/tdb/tdbutil.c @@ -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; -- cgit