mirror of
https://github.com/samba-team/samba.git
synced 2025-12-10 04:23:50 +03:00
Defensive brlock and locking database cleaning code.
Jeremy.
This commit is contained in:
@@ -1242,6 +1242,7 @@ struct packet_struct *receive_unexpected(enum packet_type packet_type, int id,
|
|||||||
/* The following definitions come from locking/brlock.c */
|
/* The following definitions come from locking/brlock.c */
|
||||||
|
|
||||||
void brl_init(int read_only);
|
void brl_init(int read_only);
|
||||||
|
void brl_shutdown(int read_only);
|
||||||
BOOL brl_lock(SMB_DEV_T dev, SMB_INO_T ino, int fnum,
|
BOOL brl_lock(SMB_DEV_T dev, SMB_INO_T ino, int fnum,
|
||||||
uint16 smbpid, pid_t pid, uint16 tid,
|
uint16 smbpid, pid_t pid, uint16 tid,
|
||||||
br_off start, br_off size,
|
br_off start, br_off size,
|
||||||
|
|||||||
@@ -113,12 +113,16 @@ static BOOL brl_conflict(struct lock_struct *lck1,
|
|||||||
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
delete a record if it is for a dead process
|
Delete a record if it is for a dead process, if check_self is true, then
|
||||||
|
delete any records belonging to this pid also (there shouldn't be any).
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static int delete_fn(TDB_CONTEXT *ttdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state)
|
static int delete_fn(TDB_CONTEXT *ttdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state)
|
||||||
{
|
{
|
||||||
struct lock_struct *locks;
|
struct lock_struct *locks;
|
||||||
int count, i;
|
int count, i;
|
||||||
|
BOOL check_self = *(BOOL *)state;
|
||||||
|
pid_t mypid = sys_getpid();
|
||||||
|
|
||||||
tdb_chainlock(tdb, kbuf);
|
tdb_chainlock(tdb, kbuf);
|
||||||
|
|
||||||
@@ -128,7 +132,20 @@ static int delete_fn(TDB_CONTEXT *ttdb, TDB_DATA kbuf, TDB_DATA dbuf, void *stat
|
|||||||
for (i=0; i<count; i++) {
|
for (i=0; i<count; i++) {
|
||||||
struct lock_struct *lock = &locks[i];
|
struct lock_struct *lock = &locks[i];
|
||||||
|
|
||||||
if (process_exists(lock->context.pid)) continue;
|
/* If check_self is true we want to remove our own records. */
|
||||||
|
if (check_self && (mypid == lock->context.pid)) {
|
||||||
|
|
||||||
|
DEBUG(0,("brlock : delete_fn. LOGIC ERROR ! Shutting down and a record for my pid (%u) exists !\n",
|
||||||
|
(unsigned int)lock->context.pid ));
|
||||||
|
|
||||||
|
} else if (process_exists(lock->context.pid)) {
|
||||||
|
|
||||||
|
DEBUG(10,("brlock : delete_fn. pid %u exists.\n", (unsigned int)lock->context.pid ));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEBUG(10,("brlock : delete_fn. Deleting record for process %u\n",
|
||||||
|
(unsigned int)lock->context.pid ));
|
||||||
|
|
||||||
if (count > 1 && i < count-1) {
|
if (count > 1 && i < count-1) {
|
||||||
memmove(&locks[i], &locks[i+1],
|
memmove(&locks[i], &locks[i+1],
|
||||||
@@ -152,9 +169,13 @@ static int delete_fn(TDB_CONTEXT *ttdb, TDB_DATA kbuf, TDB_DATA dbuf, void *stat
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
Open up the brlock.tdb database.
|
Open up the brlock.tdb database.
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
void brl_init(int read_only)
|
void brl_init(int read_only)
|
||||||
{
|
{
|
||||||
if (tdb) return;
|
BOOL check_self = False;
|
||||||
|
|
||||||
|
if (tdb)
|
||||||
|
return;
|
||||||
tdb = tdb_open(lock_path("brlock.tdb"), 0, TDB_CLEAR_IF_FIRST,
|
tdb = tdb_open(lock_path("brlock.tdb"), 0, TDB_CLEAR_IF_FIRST,
|
||||||
read_only?O_RDONLY:(O_RDWR|O_CREAT), 0644);
|
read_only?O_RDONLY:(O_RDWR|O_CREAT), 0644);
|
||||||
if (!tdb) {
|
if (!tdb) {
|
||||||
@@ -163,11 +184,27 @@ void brl_init(int read_only)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* delete any dead locks */
|
/* delete any dead locks */
|
||||||
if (!read_only) {
|
if (!read_only)
|
||||||
tdb_traverse(tdb, delete_fn, NULL);
|
tdb_traverse(tdb, delete_fn, &check_self);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
Close down the brlock.tdb database.
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
void brl_shutdown(int read_only)
|
||||||
|
{
|
||||||
|
BOOL check_self = True;
|
||||||
|
|
||||||
|
if (tdb)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* delete any dead locks */
|
||||||
|
if (!read_only)
|
||||||
|
tdb_traverse(tdb, delete_fn, &check_self);
|
||||||
|
|
||||||
|
tdb_close(tdb);
|
||||||
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
Lock a range of bytes.
|
Lock a range of bytes.
|
||||||
|
|||||||
@@ -214,14 +214,73 @@ void locking_close_file(files_struct *fsp)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
Delete a record if it is for a dead process, if check_self is true, then
|
||||||
|
delete any records belonging to this pid also (there shouldn't be any).
|
||||||
|
This function is only called on locking startup and shutdown.
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static int delete_fn(TDB_CONTEXT *ttdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state)
|
||||||
|
{
|
||||||
|
struct locking_data *data;
|
||||||
|
share_mode_entry *shares;
|
||||||
|
int i, del_count=0;
|
||||||
|
pid_t mypid = sys_getpid();
|
||||||
|
BOOL check_self = *(BOOL *)state;
|
||||||
|
|
||||||
|
tdb_chainlock(tdb, kbuf);
|
||||||
|
|
||||||
|
data = (struct locking_data *)dbuf.dptr;
|
||||||
|
shares = (share_mode_entry *)(dbuf.dptr + sizeof(*data));
|
||||||
|
|
||||||
|
for (i=0;i<data->num_share_mode_entries;) {
|
||||||
|
|
||||||
|
if (check_self && (shares[i].pid == mypid)) {
|
||||||
|
DEBUG(0,("locking : delete_fn. LOGIC ERROR ! Shutting down and a record for my pid (%u) exists !\n",
|
||||||
|
(unsigned int)shares[i].pid ));
|
||||||
|
} else if (!process_exists(shares[i].pid)) {
|
||||||
|
DEBUG(0,("locking : delete_fn. LOGIC ERROR ! Entry for pid %u and it no longer exists !\n",
|
||||||
|
(unsigned int)shares[i].pid ));
|
||||||
|
} else {
|
||||||
|
/* Process exists, leave this record alone. */
|
||||||
|
i++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
data->num_share_mode_entries--;
|
||||||
|
memmove(&shares[i], &shares[i+1],
|
||||||
|
dbuf.dsize - (sizeof(*data) + (i+1)*sizeof(*shares)));
|
||||||
|
del_count++;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* the record has shrunk a bit */
|
||||||
|
dbuf.dsize -= del_count * sizeof(*shares);
|
||||||
|
|
||||||
|
/* store it back in the database */
|
||||||
|
if (data->num_share_mode_entries == 0)
|
||||||
|
tdb_delete(ttdb, kbuf);
|
||||||
|
else
|
||||||
|
tdb_store(ttdb, kbuf, dbuf, TDB_REPLACE);
|
||||||
|
|
||||||
|
tdb_chainunlock(tdb, kbuf);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
Initialise the locking functions.
|
Initialise the locking functions.
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
|
static int open_read_only;
|
||||||
|
|
||||||
BOOL locking_init(int read_only)
|
BOOL locking_init(int read_only)
|
||||||
{
|
{
|
||||||
|
BOOL check_self = False;
|
||||||
|
|
||||||
brl_init(read_only);
|
brl_init(read_only);
|
||||||
|
|
||||||
if (tdb) return True;
|
if (tdb)
|
||||||
|
return True;
|
||||||
|
|
||||||
tdb = tdb_open(lock_path("locking.tdb"),
|
tdb = tdb_open(lock_path("locking.tdb"),
|
||||||
0, TDB_CLEAR_IF_FIRST,
|
0, TDB_CLEAR_IF_FIRST,
|
||||||
@@ -236,15 +295,35 @@ BOOL locking_init(int read_only)
|
|||||||
if (!posix_locking_init(read_only))
|
if (!posix_locking_init(read_only))
|
||||||
return False;
|
return False;
|
||||||
|
|
||||||
|
/* delete any dead locks */
|
||||||
|
if (!read_only)
|
||||||
|
tdb_traverse(tdb, delete_fn, &check_self);
|
||||||
|
|
||||||
|
open_read_only = read_only;
|
||||||
|
|
||||||
return True;
|
return True;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*******************************************************************
|
/*******************************************************************
|
||||||
Deinitialize the share_mode management.
|
Deinitialize the share_mode management.
|
||||||
******************************************************************/
|
******************************************************************/
|
||||||
|
|
||||||
BOOL locking_end(void)
|
BOOL locking_end(void)
|
||||||
{
|
{
|
||||||
if (tdb && tdb_close(tdb) != 0) return False;
|
BOOL check_self = True;
|
||||||
|
|
||||||
|
brl_shutdown(open_read_only);
|
||||||
|
if (tdb) {
|
||||||
|
|
||||||
|
/* delete any dead locks */
|
||||||
|
|
||||||
|
if (!open_read_only)
|
||||||
|
tdb_traverse(tdb, delete_fn, &check_self);
|
||||||
|
|
||||||
|
if (tdb_close(tdb) != 0)
|
||||||
|
return False;
|
||||||
|
}
|
||||||
|
|
||||||
return True;
|
return True;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -603,57 +603,55 @@ static BOOL check_domain_security(char *orig_user, char *domain, char *unix_user
|
|||||||
char *smb_apasswd, int smb_apasslen,
|
char *smb_apasswd, int smb_apasslen,
|
||||||
char *smb_ntpasswd, int smb_ntpasslen)
|
char *smb_ntpasswd, int smb_ntpasslen)
|
||||||
{
|
{
|
||||||
BOOL ret = False;
|
BOOL ret = False;
|
||||||
BOOL user_exists = True;
|
BOOL user_exists = True;
|
||||||
struct passwd *pwd=NULL;
|
struct passwd *pwd=NULL;
|
||||||
|
|
||||||
if(lp_security() != SEC_DOMAIN)
|
if(lp_security() != SEC_DOMAIN)
|
||||||
return False;
|
return False;
|
||||||
|
|
||||||
if (!check_domain_match(orig_user, domain))
|
if (!check_domain_match(orig_user, domain))
|
||||||
return False;
|
return False;
|
||||||
|
|
||||||
ret = domain_client_validate(orig_user, domain,
|
ret = domain_client_validate(orig_user, domain,
|
||||||
smb_apasswd, smb_apasslen,
|
smb_apasswd, smb_apasslen,
|
||||||
smb_ntpasswd, smb_ntpasslen,
|
smb_ntpasswd, smb_ntpasslen,
|
||||||
&user_exists, NULL);
|
&user_exists, NULL);
|
||||||
|
|
||||||
if(ret) {
|
if(ret) {
|
||||||
/*
|
/*
|
||||||
* User validated ok against Domain controller.
|
* User validated ok against Domain controller.
|
||||||
* If the admin wants us to try and create a UNIX
|
* If the admin wants us to try and create a UNIX
|
||||||
* user on the fly, do so.
|
* user on the fly, do so.
|
||||||
*/
|
*/
|
||||||
if(user_exists && lp_adduser_script() && !(pwd = smb_getpwnam(unix_user,True))) {
|
if(user_exists && lp_adduser_script() && !(pwd = smb_getpwnam(unix_user,True)))
|
||||||
smb_create_user(unix_user, NULL);
|
smb_create_user(unix_user, NULL);
|
||||||
}
|
|
||||||
|
|
||||||
if(lp_adduser_script() && pwd) {
|
if(lp_adduser_script() && pwd) {
|
||||||
SMB_STRUCT_STAT st;
|
SMB_STRUCT_STAT st;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Also call smb_create_user if the users home directory
|
* Also call smb_create_user if the users home directory
|
||||||
* doesn't exist. Used with winbindd to allow the script to
|
* doesn't exist. Used with winbindd to allow the script to
|
||||||
* create the home directory for a user mapped with winbindd.
|
* create the home directory for a user mapped with winbindd.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (pwd->pw_shell && (sys_stat(pwd->pw_dir, &st) == -1) && (errno == ENOENT))
|
if (pwd->pw_dir && (sys_stat(pwd->pw_dir, &st) == -1) && (errno == ENOENT))
|
||||||
smb_create_user(unix_user, pwd->pw_dir);
|
smb_create_user(unix_user, pwd->pw_dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
/*
|
/*
|
||||||
* User failed to validate ok against Domain controller.
|
* User failed to validate ok against Domain controller.
|
||||||
* If the failure was "user doesn't exist" and admin
|
* If the failure was "user doesn't exist" and admin
|
||||||
* wants us to try and delete that UNIX user on the fly,
|
* wants us to try and delete that UNIX user on the fly,
|
||||||
* do so.
|
* do so.
|
||||||
*/
|
*/
|
||||||
if(!user_exists && lp_deluser_script() && smb_getpwnam(unix_user,True)) {
|
if(!user_exists && lp_deluser_script() && smb_getpwnam(unix_user,True))
|
||||||
smb_delete_user(unix_user);
|
smb_delete_user(unix_user);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
|
|||||||
Reference in New Issue
Block a user