1996-05-04 11:50:46 +04:00
/*
2002-01-30 09:08:46 +03:00
Unix SMB / CIFS implementation .
1996-05-04 11:50:46 +04:00
Locking functions
2000-04-28 01:12:33 +04:00
Copyright ( C ) Andrew Tridgell 1992 - 2000
2006-04-10 19:33:04 +04:00
Copyright ( C ) Jeremy Allison 1992 - 2006
2005-07-08 08:51:27 +04:00
Copyright ( C ) Volker Lendecke 2005
2011-05-28 12:24:20 +04:00
1996-05-04 11:50:46 +04:00
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
2007-07-09 23:25:36 +04:00
the Free Software Foundation ; either version 3 of the License , or
1996-05-04 11:50:46 +04:00
( at your option ) any later version .
2011-05-28 12:24:20 +04:00
1996-05-04 11:50:46 +04:00
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
2011-05-28 12:24:20 +04:00
1996-05-04 11:50:46 +04:00
You should have received a copy of the GNU General Public License
2007-07-10 04:52:41 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
1996-08-15 19:11:34 +04:00
Revision History :
12 aug 96 : Erik . Devriendt @ te6 . siemens . be
added support for shared memory implementation of share mode locking
1997-05-20 04:32:51 +04:00
May 1997. Jeremy Allison ( jallison @ whistle . com ) . Modified share mode
locking to deal with multiple share modes per open file .
1997-10-07 22:46:19 +04:00
September 1997. Jeremy Allison ( jallison @ whistle . com ) . Added oplock
support .
2011-12-15 18:48:33 +04:00
rewritten completely to use new tdb code . Tridge , Dec ' 99
2000-04-28 01:12:33 +04:00
Added POSIX locking support . Jeremy Allison ( jeremy @ valinux . com ) , Apr . 2000.
2006-04-10 19:33:04 +04:00
Added Unix Extensions POSIX locking support . Jeremy Allison Mar 2006.
1996-05-04 11:50:46 +04:00
*/
# include "includes.h"
2019-12-02 18:30:50 +03:00
# include "lib/util/time_basic.h"
2011-02-26 01:20:06 +03:00
# include "system/filesys.h"
2017-01-01 23:00:55 +03:00
# include "lib/util/server_id.h"
2020-10-28 14:09:39 +03:00
# include "share_mode_lock.h"
2020-11-04 14:39:48 +03:00
# include "share_mode_lock_private.h"
2011-03-23 14:43:17 +03:00
# include "locking/proto.h"
2010-07-04 20:18:58 +04:00
# include "smbd/globals.h"
2011-07-07 19:42:08 +04:00
# include "dbwrap/dbwrap.h"
2011-07-06 18:40:21 +04:00
# include "dbwrap/dbwrap_open.h"
2010-10-12 08:27:50 +04:00
# include "../libcli/security/security.h"
2011-02-25 01:05:57 +03:00
# include "serverid.h"
2011-03-24 17:31:06 +03:00
# include "messages.h"
2011-05-05 13:25:29 +04:00
# include "util_tdb.h"
2011-11-24 17:11:28 +04:00
# include "../librpc/gen_ndr/ndr_open_files.h"
2015-04-21 11:16:16 +03:00
# include "librpc/gen_ndr/ndr_file_id.h"
2019-08-26 23:05:14 +03:00
# include "librpc/gen_ndr/ndr_leases_db.h"
2014-10-11 01:32:19 +04:00
# include "locking/leases_db.h"
1996-05-04 11:50:46 +04:00
2005-04-27 22:32:37 +04:00
# undef DBGC_CLASS
# define DBGC_CLASS DBGC_LOCKING
2007-07-17 04:50:48 +04:00
# define NO_LOCKING_COUNT (-1)
2000-04-12 21:59:09 +04:00
/****************************************************************************
2006-04-10 19:33:04 +04:00
Debugging aids : - ) .
2000-04-12 21:59:09 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-04-10 19:33:04 +04:00
const char * lock_type_name ( enum brl_type lock_type )
2000-04-12 21:59:09 +04:00
{
2006-04-10 19:33:04 +04:00
switch ( lock_type ) {
case READ_LOCK :
return " READ " ;
case WRITE_LOCK :
return " WRITE " ;
default :
return " other " ;
}
}
const char * lock_flav_name ( enum brl_flavour lock_flav )
{
return ( lock_flav = = WINDOWS_LOCK ) ? " WINDOWS_LOCK " : " POSIX_LOCK " ;
2000-04-12 21:59:09 +04:00
}
1996-05-04 11:50:46 +04:00
/****************************************************************************
1998-07-23 04:10:26 +04:00
Utility function called to see if a file region is locked .
2006-04-10 19:33:04 +04:00
Called in the read / write codepath .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2000-04-12 21:59:09 +04:00
2009-03-14 00:15:28 +03:00
void init_strict_lock_struct ( files_struct * fsp ,
2010-05-07 17:20:50 +04:00
uint64_t smblctx ,
2009-03-14 00:15:28 +03:00
br_off start ,
br_off size ,
enum brl_type lock_type ,
2021-11-17 02:00:03 +03:00
enum brl_flavour lock_flav ,
2009-03-14 00:15:28 +03:00
struct lock_struct * plock )
{
SMB_ASSERT ( lock_type = = READ_LOCK | | lock_type = = WRITE_LOCK ) ;
2010-05-07 17:20:50 +04:00
plock - > context . smblctx = smblctx ;
2009-03-14 00:15:28 +03:00
plock - > context . tid = fsp - > conn - > cnum ;
2011-12-15 14:50:43 +04:00
plock - > context . pid = messaging_server_id ( fsp - > conn - > sconn - > msg_ctx ) ;
2009-03-14 00:15:28 +03:00
plock - > start = start ;
plock - > size = size ;
plock - > fnum = fsp - > fnum ;
plock - > lock_type = lock_type ;
plock - > lock_flav = lp_posix_cifsu_locktype ( fsp ) ;
}
2017-07-09 15:34:10 +03:00
bool strict_lock_check_default ( files_struct * fsp , struct lock_struct * plock )
1996-05-04 11:50:46 +04:00
{
2014-07-11 00:23:37 +04:00
struct byte_range_lock * br_lck ;
2006-11-11 20:05:11 +03:00
int strict_locking = lp_strict_locking ( fsp - > conn - > params ) ;
2009-03-14 00:15:28 +03:00
bool ret = False ;
if ( plock - > size = = 0 ) {
return True ;
2006-04-10 19:33:04 +04:00
}
1996-05-04 11:50:46 +04:00
2006-11-11 20:05:11 +03:00
if ( ! lp_locking ( fsp - > conn - > params ) | | ! strict_locking ) {
2009-03-14 00:15:28 +03:00
return True ;
2006-04-10 19:33:04 +04:00
}
1998-07-28 22:26:47 +04:00
2004-12-11 03:30:28 +03:00
if ( strict_locking = = Auto ) {
2017-03-14 23:34:07 +03:00
uint32_t lease_type = fsp_lease_type ( fsp ) ;
if ( ( lease_type & SMB2_LEASE_READ ) & &
( plock - > lock_type = = READ_LOCK ) )
{
DBG_DEBUG ( " optimisation - read lease on file %s \n " ,
fsp_str_dbg ( fsp ) ) ;
2014-07-11 00:23:37 +04:00
return true ;
2004-12-11 03:30:28 +03:00
}
2017-03-14 23:34:07 +03:00
if ( ( lease_type & SMB2_LEASE_WRITE ) & &
( plock - > lock_type = = WRITE_LOCK ) )
{
DBG_DEBUG ( " optimisation - write lease on file %s \n " ,
fsp_str_dbg ( fsp ) ) ;
2014-07-11 00:23:37 +04:00
return true ;
2006-04-10 19:33:04 +04:00
}
2004-12-10 01:10:40 +03:00
}
2001-06-30 05:59:48 +04:00
2014-07-11 00:23:37 +04:00
br_lck = brl_get_locks_readonly ( fsp ) ;
if ( ! br_lck ) {
return true ;
}
2014-07-11 17:35:45 +04:00
ret = brl_locktest ( br_lck , plock ) ;
2014-07-11 00:23:37 +04:00
2014-08-19 16:36:55 +04:00
if ( ! ret ) {
/*
* We got a lock conflict . Retry with rw locks to enable
* autocleanup . This is the slow path anyway .
*/
br_lck = brl_get_locks ( talloc_tos ( ) , fsp ) ;
2019-02-04 19:19:55 +03:00
if ( br_lck = = NULL ) {
return true ;
}
2014-08-19 16:36:55 +04:00
ret = brl_locktest ( br_lck , plock ) ;
TALLOC_FREE ( br_lck ) ;
}
2024-05-14 17:20:03 +03:00
DBG_DEBUG ( " flavour = %s brl start=% " PRIu64 " "
" len=% " PRIu64 " %s for fnum % " PRIu64 " file %s \n " ,
lock_flav_name ( plock - > lock_flav ) ,
plock - > start ,
plock - > size ,
ret ? " unlocked " : " locked " ,
plock - > fnum ,
fsp_str_dbg ( fsp ) ) ;
1996-05-04 11:50:46 +04:00
2006-04-10 19:33:04 +04:00
return ret ;
}
/****************************************************************************
Find out if a lock could be granted - return who is blocking us if we can ' t .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2000-04-12 21:59:09 +04:00
2006-04-10 19:33:04 +04:00
NTSTATUS query_lock ( files_struct * fsp ,
2010-05-07 17:20:50 +04:00
uint64_t * psmblctx ,
2008-10-14 03:59:36 +04:00
uint64_t * pcount ,
uint64_t * poffset ,
2006-04-10 19:33:04 +04:00
enum brl_type * plock_type ,
enum brl_flavour lock_flav )
{
struct byte_range_lock * br_lck = NULL ;
2000-04-12 21:59:09 +04:00
2020-04-02 18:09:36 +03:00
if ( ! fsp - > fsp_flags . can_lock ) {
2020-04-02 19:21:11 +03:00
return fsp - > fsp_flags . is_directory ?
NT_STATUS_INVALID_DEVICE_REQUEST :
NT_STATUS_INVALID_HANDLE ;
2001-06-30 05:59:48 +04:00
}
2006-11-11 20:05:11 +03:00
if ( ! lp_locking ( fsp - > conn - > params ) ) {
2006-04-10 19:33:04 +04:00
return NT_STATUS_OK ;
}
2009-11-16 11:40:47 +03:00
br_lck = brl_get_locks_readonly ( fsp ) ;
2006-04-10 19:33:04 +04:00
if ( ! br_lck ) {
return NT_STATUS_NO_MEMORY ;
}
2009-11-16 11:40:47 +03:00
return brl_lockquery ( br_lck ,
2010-05-07 17:20:50 +04:00
psmblctx ,
2011-12-15 14:50:43 +04:00
messaging_server_id ( fsp - > conn - > sconn - > msg_ctx ) ,
2006-04-10 19:33:04 +04:00
poffset ,
pcount ,
plock_type ,
lock_flav ) ;
2000-04-12 21:59:09 +04:00
}
1996-05-04 11:50:46 +04:00
2009-02-10 08:51:29 +03:00
static void increment_current_lock_count ( files_struct * fsp ,
enum brl_flavour lock_flav )
{
if ( lock_flav = = WINDOWS_LOCK & &
fsp - > current_lock_count ! = NO_LOCKING_COUNT ) {
/* blocking ie. pending, locks also count here,
* as this is an efficiency counter to avoid checking
* the lock db . on close . JRA . */
fsp - > current_lock_count + + ;
} else {
/* Notice that this has had a POSIX lock request.
* We can ' t count locks after this so forget them .
*/
fsp - > current_lock_count = NO_LOCKING_COUNT ;
}
}
static void decrement_current_lock_count ( files_struct * fsp ,
enum brl_flavour lock_flav )
{
if ( lock_flav = = WINDOWS_LOCK & &
fsp - > current_lock_count ! = NO_LOCKING_COUNT ) {
SMB_ASSERT ( fsp - > current_lock_count > 0 ) ;
fsp - > current_lock_count - - ;
}
}
1996-05-04 11:50:46 +04:00
/****************************************************************************
1998-07-23 04:10:26 +04:00
Utility function called by locking requests .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2000-04-12 21:59:09 +04:00
2019-07-01 16:56:27 +03:00
struct do_lock_state {
struct files_struct * fsp ;
2019-08-08 20:26:28 +03:00
TALLOC_CTX * req_mem_ctx ;
const struct GUID * req_guid ;
2019-07-01 16:56:27 +03:00
uint64_t smblctx ;
uint64_t count ;
uint64_t offset ;
enum brl_type lock_type ;
enum brl_flavour lock_flav ;
struct server_id blocker_pid ;
uint64_t blocker_smblctx ;
NTSTATUS status ;
} ;
static void do_lock_fn (
2022-08-18 14:57:56 +03:00
struct share_mode_lock * lck ,
2019-07-01 16:56:27 +03:00
void * private_data )
{
struct do_lock_state * state = private_data ;
struct byte_range_lock * br_lck = NULL ;
2019-08-08 20:26:28 +03:00
br_lck = brl_get_locks_for_locking ( talloc_tos ( ) ,
state - > fsp ,
state - > req_mem_ctx ,
state - > req_guid ) ;
2019-07-01 16:56:27 +03:00
if ( br_lck = = NULL ) {
state - > status = NT_STATUS_NO_MEMORY ;
return ;
}
state - > status = brl_lock (
br_lck ,
state - > smblctx ,
messaging_server_id ( state - > fsp - > conn - > sconn - > msg_ctx ) ,
state - > offset ,
state - > count ,
state - > lock_type ,
state - > lock_flav ,
& state - > blocker_pid ,
& state - > blocker_smblctx ) ;
TALLOC_FREE ( br_lck ) ;
}
2019-07-01 16:17:27 +03:00
NTSTATUS do_lock ( files_struct * fsp ,
2019-08-08 20:26:28 +03:00
TALLOC_CTX * req_mem_ctx ,
const struct GUID * req_guid ,
2019-07-01 15:30:15 +03:00
uint64_t smblctx ,
uint64_t count ,
uint64_t offset ,
enum brl_type lock_type ,
enum brl_flavour lock_flav ,
struct server_id * pblocker_pid ,
uint64_t * psmblctx )
1996-05-04 11:50:46 +04:00
{
2019-07-01 16:56:27 +03:00
struct do_lock_state state = {
. fsp = fsp ,
2019-08-08 20:26:28 +03:00
. req_mem_ctx = req_mem_ctx ,
. req_guid = req_guid ,
2019-07-01 16:56:27 +03:00
. smblctx = smblctx ,
. count = count ,
. offset = offset ,
. lock_type = lock_type ,
. lock_flav = lock_flav ,
} ;
2019-07-01 15:30:15 +03:00
NTSTATUS status ;
1999-12-21 12:25:59 +03:00
2010-04-29 03:42:04 +04:00
/* silently return ok on print files as we don't do locking there */
if ( fsp - > print_file ) {
2019-07-01 15:30:15 +03:00
return NT_STATUS_OK ;
2010-04-29 03:42:04 +04:00
}
2020-04-02 18:09:36 +03:00
if ( ! fsp - > fsp_flags . can_lock ) {
2020-04-02 19:21:11 +03:00
if ( fsp - > fsp_flags . is_directory ) {
2019-07-01 15:30:15 +03:00
return NT_STATUS_INVALID_DEVICE_REQUEST ;
}
return NT_STATUS_INVALID_HANDLE ;
2006-04-10 19:33:04 +04:00
}
2006-11-11 20:05:11 +03:00
if ( ! lp_locking ( fsp - > conn - > params ) ) {
2019-07-01 15:30:15 +03:00
return NT_STATUS_OK ;
2006-04-10 19:33:04 +04:00
}
1999-12-21 12:25:59 +03:00
2001-08-24 08:55:28 +04:00
/* NOTE! 0 byte long ranges ARE allowed and should be stored */
2019-07-01 15:23:27 +03:00
DBG_DEBUG ( " lock flavour %s lock type %s start=% " PRIu64 " len=% " PRIu64 " "
2019-07-01 15:42:50 +03:00
" requested for %s file %s \n " ,
2019-07-01 15:23:27 +03:00
lock_flav_name ( lock_flav ) ,
lock_type_name ( lock_type ) ,
offset ,
count ,
fsp_fnum_dbg ( fsp ) ,
fsp_str_dbg ( fsp ) ) ;
2006-04-10 19:33:04 +04:00
2022-08-18 14:57:56 +03:00
status = share_mode_do_locked_vfs_allowed ( fsp - > file_id ,
do_lock_fn ,
& state ) ;
2019-07-01 16:56:27 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
DBG_DEBUG ( " share_mode_do_locked returned %s \n " ,
nt_errstr ( status ) ) ;
return status ;
2000-01-13 15:09:36 +03:00
}
1999-12-21 12:25:59 +03:00
2019-06-20 13:42:23 +03:00
if ( psmblctx ! = NULL ) {
2019-07-01 16:56:27 +03:00
* psmblctx = state . blocker_smblctx ;
2019-06-20 13:42:23 +03:00
}
2019-06-20 13:20:39 +03:00
if ( pblocker_pid ! = NULL ) {
2019-07-01 16:56:27 +03:00
* pblocker_pid = state . blocker_pid ;
2019-06-20 13:20:39 +03:00
}
2006-04-10 19:33:04 +04:00
2019-07-01 16:56:27 +03:00
DBG_DEBUG ( " returning status=%s \n " , nt_errstr ( state . status ) ) ;
2007-03-07 00:59:51 +03:00
2009-02-10 08:51:29 +03:00
increment_current_lock_count ( fsp , lock_flav ) ;
2019-07-01 15:30:15 +03:00
2019-07-01 16:56:27 +03:00
return state . status ;
1996-05-04 11:50:46 +04:00
}
2002-03-13 23:28:19 +03:00
/****************************************************************************
2006-07-18 01:09:02 +04:00
Utility function called by unlocking requests .
2002-03-13 23:28:19 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2019-07-01 16:33:58 +03:00
NTSTATUS do_unlock ( files_struct * fsp ,
uint64_t smblctx ,
uint64_t count ,
uint64_t offset ,
enum brl_flavour lock_flav )
2002-03-13 23:28:19 +03:00
{
2007-10-19 04:40:25 +04:00
bool ok = False ;
2006-07-18 01:09:02 +04:00
struct byte_range_lock * br_lck = NULL ;
2011-05-28 12:24:20 +04:00
2020-04-02 18:09:36 +03:00
if ( ! fsp - > fsp_flags . can_lock ) {
2020-04-02 19:21:11 +03:00
return fsp - > fsp_flags . is_directory ?
NT_STATUS_INVALID_DEVICE_REQUEST :
NT_STATUS_INVALID_HANDLE ;
2006-04-10 19:33:04 +04:00
}
2011-05-28 12:24:20 +04:00
2006-11-11 20:05:11 +03:00
if ( ! lp_locking ( fsp - > conn - > params ) ) {
2006-07-18 01:09:02 +04:00
return NT_STATUS_OK ;
}
2011-05-28 12:24:20 +04:00
2019-05-27 14:49:34 +03:00
DBG_DEBUG ( " unlock start=% " PRIu64 " len=% " PRIu64 " requested for %s file "
" %s \n " ,
offset ,
count ,
fsp_fnum_dbg ( fsp ) ,
fsp_str_dbg ( fsp ) ) ;
2002-03-13 23:49:57 +03:00
2008-01-06 18:15:45 +03:00
br_lck = brl_get_locks ( talloc_tos ( ) , fsp ) ;
2006-07-18 01:09:02 +04:00
if ( ! br_lck ) {
return NT_STATUS_NO_MEMORY ;
}
2006-04-10 19:33:04 +04:00
2019-07-01 16:28:10 +03:00
ok = brl_unlock ( br_lck ,
2010-05-07 17:20:50 +04:00
smblctx ,
2011-12-15 14:50:43 +04:00
messaging_server_id ( fsp - > conn - > sconn - > msg_ctx ) ,
2006-07-18 01:09:02 +04:00
offset ,
count ,
lock_flav ) ;
2011-05-28 12:24:20 +04:00
2006-07-18 01:09:02 +04:00
TALLOC_FREE ( br_lck ) ;
2006-04-10 19:33:04 +04:00
2006-07-18 01:09:02 +04:00
if ( ! ok ) {
DEBUG ( 10 , ( " do_unlock: returning ERRlock. \n " ) ) ;
return NT_STATUS_RANGE_NOT_LOCKED ;
2002-03-13 23:28:19 +03:00
}
2006-07-18 01:09:02 +04:00
2009-02-10 08:51:29 +03:00
decrement_current_lock_count ( fsp , lock_flav ) ;
2006-07-18 01:09:02 +04:00
return NT_STATUS_OK ;
2002-03-13 23:28:19 +03:00
}
2000-04-26 00:30:58 +04:00
/****************************************************************************
Remove any locks on this fd . Called from file_close ( ) .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2019-07-01 16:35:19 +03:00
void locking_close_file ( files_struct * fsp ,
2010-05-07 12:20:26 +04:00
enum file_close_type close_type )
2000-04-26 00:30:58 +04:00
{
2006-04-10 19:33:04 +04:00
struct byte_range_lock * br_lck ;
2000-04-26 00:30:58 +04:00
2006-11-11 20:05:11 +03:00
if ( ! lp_locking ( fsp - > conn - > params ) ) {
2000-04-26 00:30:58 +04:00
return ;
2006-04-10 19:33:04 +04:00
}
2000-04-26 00:30:58 +04:00
2013-09-10 16:01:58 +04:00
/* If we have no outstanding locks or pending
2007-03-07 00:59:51 +03:00
* locks then we don ' t need to look in the lock db .
*/
if ( fsp - > current_lock_count = = 0 ) {
return ;
}
2008-01-06 18:15:45 +03:00
br_lck = brl_get_locks ( talloc_tos ( ) , fsp ) ;
2006-07-18 01:09:02 +04:00
2006-07-11 22:01:26 +04:00
if ( br_lck ) {
2019-06-19 17:08:49 +03:00
/*
* Unlocks must trigger dbwrap_watch watchers ,
* normally in smbd_do_unlocking . Here it ' s done
2023-07-13 09:50:21 +03:00
* implicitly , we ' re closing the file and thus remove a
2019-06-19 17:08:49 +03:00
* share mode . This will wake the waiters .
*/
2019-07-01 16:31:04 +03:00
brl_close_fnum ( br_lck ) ;
2006-07-11 22:01:26 +04:00
TALLOC_FREE ( br_lck ) ;
2000-04-26 00:30:58 +04:00
}
}
2002-01-08 03:52:36 +03:00
/*******************************************************************
Print out a share mode .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2018-02-07 13:05:33 +03:00
char * share_mode_str ( TALLOC_CTX * ctx , int num ,
const struct file_id * id ,
const struct share_mode_entry * e )
2002-01-08 03:52:36 +03:00
{
2015-04-23 19:06:17 +03:00
struct server_id_buf tmp ;
2019-09-06 08:29:10 +03:00
struct file_id_buf ftmp ;
2015-04-23 19:06:17 +03:00
2011-12-14 13:35:56 +04:00
return talloc_asprintf ( ctx , " share_mode_entry[%d]: "
2005-09-30 21:13:37 +04:00
" pid = %s, share_access = 0x%x, private_options = 0x%x, "
2011-12-25 14:35:07 +04:00
" access_mask = 0x%x, mid = 0x%llx, type= 0x%x, gen_id = %llu, "
2011-01-26 01:01:52 +03:00
" uid = %u, flags = %u, file_id %s, name_hash = 0x%x " ,
2006-01-27 22:54:39 +03:00
num ,
2015-04-23 19:06:17 +03:00
server_id_str_buf ( e - > pid , & tmp ) ,
2005-07-08 08:51:27 +04:00
e - > share_access , e - > private_options ,
2010-04-13 08:40:28 +04:00
e - > access_mask , ( unsigned long long ) e - > op_mid ,
2012-01-07 02:25:06 +04:00
e - > op_type , ( unsigned long long ) e - > share_file_id ,
2007-02-07 00:05:34 +03:00
( unsigned int ) e - > uid , ( unsigned int ) e - > flags ,
2019-09-06 08:29:10 +03:00
file_id_str_buf ( * id , & ftmp ) ,
2011-01-26 01:01:52 +03:00
( unsigned int ) e - > name_hash ) ;
2002-01-08 03:52:36 +03:00
}
2019-09-10 22:12:23 +03:00
struct rename_share_filename_state {
2022-08-26 11:21:25 +03:00
struct share_mode_data * data ;
2019-09-10 22:12:23 +03:00
struct messaging_context * msg_ctx ;
struct server_id self ;
uint32_t orig_name_hash ;
uint32_t new_name_hash ;
struct file_rename_message msg ;
} ;
2019-09-10 22:21:01 +03:00
static bool rename_lease_fn ( struct share_mode_entry * e ,
2018-09-17 14:24:56 +03:00
void * private_data )
{
2019-09-10 22:12:23 +03:00
struct rename_share_filename_state * state = private_data ;
2022-08-26 11:21:25 +03:00
struct share_mode_data * d = state - > data ;
2018-09-17 14:24:56 +03:00
NTSTATUS status ;
status = leases_db_rename ( & e - > client_guid ,
& e - > lease_key ,
& d - > id ,
d - > servicepath ,
d - > base_name ,
d - > stream_name ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
/* Any error recovery possible here ? */
DBG_WARNING ( " Failed to rename lease key for "
" renamed file %s:%s. %s \n " ,
d - > base_name ,
d - > stream_name ,
nt_errstr ( status ) ) ;
}
return false ;
}
2005-12-13 01:07:36 +03:00
/*******************************************************************
Sets the service name and filename for rename .
2005-12-13 21:11:50 +03:00
At this point we emit " file renamed " messages to all
process id ' s that have this file open .
Based on an initial code idea from SATOH Fumiyasu < fumiya @ samba . gr . jp >
2005-12-13 01:07:36 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2019-08-16 16:40:55 +03:00
static bool rename_share_filename_fn (
struct share_mode_entry * e ,
bool * modified ,
void * private_data )
{
struct rename_share_filename_state * state = private_data ;
DATA_BLOB blob ;
enum ndr_err_code ndr_err ;
bool ok ;
/*
* If this is a hardlink to the inode with a different name ,
* skip this .
*/
if ( e - > name_hash ! = state - > orig_name_hash ) {
return false ;
}
e - > name_hash = state - > new_name_hash ;
* modified = true ;
2019-10-09 22:38:04 +03:00
ok = server_id_equal ( & e - > pid , & state - > self ) ;
2019-08-16 16:40:55 +03:00
if ( ok ) {
return false ;
}
state - > msg . share_file_id = e - > share_file_id ;
ndr_err = ndr_push_struct_blob (
& blob ,
talloc_tos ( ) ,
& state - > msg ,
( ndr_push_flags_fn_t ) ndr_push_file_rename_message ) ;
if ( ! NDR_ERR_CODE_IS_SUCCESS ( ndr_err ) ) {
DBG_DEBUG ( " ndr_push_file_rename_message failed: %s \n " ,
ndr_errstr ( ndr_err ) ) ;
return false ;
}
if ( DEBUGLEVEL > = 10 ) {
struct server_id_buf tmp ;
DBG_DEBUG ( " sending rename message to %s \n " ,
server_id_str_buf ( e - > pid , & tmp ) ) ;
NDR_PRINT_DEBUG ( file_rename_message , & state - > msg ) ;
}
messaging_send ( state - > msg_ctx , e - > pid , MSG_SMB_FILE_RENAME , & blob ) ;
TALLOC_FREE ( blob . data ) ;
return false ;
}
2007-10-19 04:40:25 +04:00
bool rename_share_filename ( struct messaging_context * msg_ctx ,
2007-05-14 17:01:28 +04:00
struct share_mode_lock * lck ,
2014-03-20 17:36:11 +04:00
struct file_id id ,
2005-12-13 01:07:36 +03:00
const char * servicepath ,
2011-01-26 01:01:52 +03:00
uint32_t orig_name_hash ,
uint32_t new_name_hash ,
2009-07-09 03:22:44 +04:00
const struct smb_filename * smb_fname_dst )
2005-12-13 01:07:36 +03:00
{
2019-08-16 16:40:55 +03:00
struct rename_share_filename_state state = {
. msg_ctx = msg_ctx ,
. self = messaging_server_id ( msg_ctx ) ,
. orig_name_hash = orig_name_hash ,
. new_name_hash = new_name_hash ,
. msg . id = id ,
. msg . servicepath = servicepath ,
. msg . base_name = smb_fname_dst - > base_name ,
. msg . stream_name = smb_fname_dst - > stream_name ,
2019-05-17 11:41:25 +03:00
} ;
2022-08-26 11:24:52 +03:00
struct share_mode_data * d = NULL ;
NTSTATUS status ;
2018-09-17 14:24:56 +03:00
bool ok ;
2005-12-13 21:11:50 +03:00
2024-05-14 17:20:03 +03:00
DBG_DEBUG ( " servicepath %s newname %s \n " ,
servicepath ,
smb_fname_dst - > base_name ) ;
2005-12-13 21:11:50 +03:00
2022-08-26 11:24:52 +03:00
status = share_mode_lock_access_private_data ( lck , & d ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
/* Any error recovery possible here ? */
DBG_ERR ( " share_mode_lock_access_private_data() failed for "
" servicepath %s newname %s - %s \n " ,
servicepath , smb_fname_dst - > base_name ,
nt_errstr ( status ) ) ;
return false ;
}
state . data = d ;
2005-12-13 01:07:36 +03:00
/*
* rename_internal_fsp ( ) and rename_internals ( ) add ' . / ' to
* head of newname if newname does not contain a ' / ' .
*/
2005-12-13 21:11:50 +03:00
2019-08-16 16:40:55 +03:00
if ( strncmp ( state . msg . base_name , " ./ " , 2 ) = = 0 ) {
state . msg . base_name + = 2 ;
2005-12-13 21:11:50 +03:00
}
2006-01-13 01:17:54 +03:00
2019-08-16 16:40:55 +03:00
d - > servicepath = talloc_strdup ( d , state . msg . servicepath ) ;
d - > base_name = talloc_strdup ( d , state . msg . base_name ) ;
d - > stream_name = talloc_strdup ( d , state . msg . stream_name ) ;
2019-05-17 11:41:25 +03:00
if ( ( d - > servicepath = = NULL ) | |
( d - > base_name = = NULL ) | |
2019-08-16 16:40:55 +03:00
( ( state . msg . stream_name ! = NULL ) & & ( d - > stream_name = = NULL ) ) ) {
2019-05-17 11:41:25 +03:00
DBG_WARNING ( " talloc failed \n " ) ;
return false ;
}
d - > modified = True ;
2005-12-13 21:11:50 +03:00
2019-08-16 16:40:55 +03:00
ok = share_mode_forall_entries (
lck , rename_share_filename_fn , & state ) ;
if ( ! ok ) {
DBG_WARNING ( " share_mode_forall_entries failed \n " ) ;
2019-05-17 11:44:23 +03:00
}
2019-05-17 11:41:25 +03:00
2019-09-10 22:12:23 +03:00
ok = share_mode_forall_leases ( lck , rename_lease_fn , & state ) ;
2018-09-17 14:24:56 +03:00
if ( ! ok ) {
/*
* Ignore error here . Not sure what to do . .
*/
DBG_WARNING ( " share_mode_forall_leases failed \n " ) ;
2014-12-04 21:14:23 +03:00
}
2005-12-13 01:07:36 +03:00
return True ;
}
2008-04-01 13:40:23 +04:00
void get_file_infos ( struct file_id id ,
2011-01-26 00:57:38 +03:00
uint32_t name_hash ,
2008-04-01 13:40:23 +04:00
bool * delete_on_close ,
struct timespec * write_time )
2008-03-12 17:32:47 +03:00
{
struct share_mode_lock * lck ;
2008-04-01 13:40:23 +04:00
if ( delete_on_close ) {
* delete_on_close = false ;
}
if ( write_time ) {
2019-12-02 18:30:50 +03:00
* write_time = make_omit_timespec ( ) ;
2008-04-01 13:40:23 +04:00
}
2008-03-12 17:32:47 +03:00
2009-07-09 03:22:44 +04:00
if ( ! ( lck = fetch_share_mode_unlocked ( talloc_tos ( ) , id ) ) ) {
2008-04-01 13:40:23 +04:00
return ;
2008-03-12 17:32:47 +03:00
}
2008-04-01 13:40:23 +04:00
if ( delete_on_close ) {
2011-01-26 01:23:19 +03:00
* delete_on_close = is_delete_on_close_set ( lck , name_hash ) ;
2008-03-12 17:32:47 +03:00
}
2008-04-01 13:40:23 +04:00
if ( write_time ) {
2013-11-22 18:36:49 +04:00
* write_time = get_share_mode_write_time ( lck ) ;
2007-05-27 13:57:05 +04:00
}
2008-04-01 13:40:23 +04:00
2007-05-27 13:57:05 +04:00
TALLOC_FREE ( lck ) ;
1998-10-23 07:34:50 +04:00
}
2007-10-19 04:40:25 +04:00
bool is_valid_share_mode_entry ( const struct share_mode_entry * e )
1998-10-23 07:34:50 +04:00
{
2005-09-30 21:13:37 +04:00
int num_props = 0 ;
2013-08-30 16:49:43 +04:00
if ( e - > stale ) {
return false ;
}
2005-09-30 21:13:37 +04:00
num_props + = ( ( e - > op_type = = NO_OPLOCK ) ? 1 : 0 ) ;
num_props + = ( EXCLUSIVE_OPLOCK_TYPE ( e - > op_type ) ? 1 : 0 ) ;
num_props + = ( LEVEL_II_OPLOCK_TYPE ( e - > op_type ) ? 1 : 0 ) ;
2014-11-27 20:34:56 +03:00
num_props + = ( e - > op_type = = LEASE_OPLOCK ) ;
2005-09-30 21:13:37 +04:00
2012-06-01 17:15:07 +04:00
if ( ( num_props > 1 ) & & serverid_exists ( & e - > pid ) ) {
2012-05-14 16:57:34 +04:00
smb_panic ( " Invalid share mode entry " ) ;
}
2005-09-30 21:13:37 +04:00
return ( num_props ! = 0 ) ;
1998-10-23 07:34:50 +04:00
}
2019-08-26 18:09:57 +03:00
struct find_lease_ref_state {
const struct GUID * client_guid ;
const struct smb2_lease_key * lease_key ;
bool found_same ;
} ;
static bool find_lease_ref_fn (
struct share_mode_entry * e ,
bool * modified ,
void * private_data )
{
struct find_lease_ref_state * state = private_data ;
if ( e - > stale ) {
return false ;
}
if ( e - > op_type ! = LEASE_OPLOCK ) {
return false ;
}
state - > found_same = smb2_lease_equal (
& e - > client_guid ,
& e - > lease_key ,
state - > client_guid ,
state - > lease_key ) ;
/*
* If we found a lease reference , look no further ( i . e . return true )
*/
return state - > found_same ;
}
2019-08-26 17:51:56 +03:00
NTSTATUS remove_lease_if_stale ( struct share_mode_lock * lck ,
2019-08-05 19:50:08 +03:00
const struct GUID * client_guid ,
const struct smb2_lease_key * lease_key )
{
2019-08-26 18:09:57 +03:00
struct find_lease_ref_state state = {
. client_guid = client_guid , . lease_key = lease_key ,
} ;
2022-08-26 11:43:12 +03:00
struct file_id id = share_mode_lock_file_id ( lck ) ;
2019-08-05 19:50:08 +03:00
NTSTATUS status ;
2019-08-26 18:09:57 +03:00
bool ok ;
2019-08-05 19:50:08 +03:00
2019-08-26 18:09:57 +03:00
ok = share_mode_forall_entries ( lck , find_lease_ref_fn , & state ) ;
if ( ! ok ) {
2022-09-10 21:39:19 +03:00
DBG_ERR ( " share_mode_forall_entries failed \n " ) ;
2019-08-26 18:09:57 +03:00
return NT_STATUS_INTERNAL_ERROR ;
}
2019-08-05 19:50:08 +03:00
2019-08-26 18:09:57 +03:00
if ( state . found_same ) {
return NT_STATUS_RESOURCE_IN_USE ;
2019-08-05 19:50:08 +03:00
}
2022-08-26 11:43:12 +03:00
status = leases_db_del ( client_guid , lease_key , & id ) ;
2019-08-05 19:50:08 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2020-07-02 15:09:15 +03:00
int level = DBGLVL_DEBUG ;
if ( ! NT_STATUS_EQUAL ( status , NT_STATUS_NOT_FOUND ) ) {
level = DBGLVL_ERR ;
}
DBG_PREFIX ( level , ( " leases_db_del failed: %s \n " ,
nt_errstr ( status ) ) ) ;
2019-08-05 19:50:08 +03:00
}
return status ;
}
2019-08-13 17:00:09 +03:00
bool share_entry_stale_pid ( struct share_mode_entry * e )
{
struct server_id_buf buf ;
bool exists ;
if ( e - > stale ) {
return true ;
}
exists = serverid_exists ( & e - > pid ) ;
if ( exists ) {
DBG_DEBUG ( " PID %s still exists \n " ,
server_id_str_buf ( e - > pid , & buf ) ) ;
return false ;
}
DBG_DEBUG ( " PID %s does not exist anymore \n " ,
server_id_str_buf ( e - > pid , & buf ) ) ;
e - > stale = true ;
return true ;
}
2006-02-02 23:44:50 +03:00
/****************************************************************************
2011-01-26 01:23:19 +03:00
Adds a delete on close token .
2006-02-02 23:44:50 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2012-01-10 16:56:37 +04:00
static bool add_delete_on_close_token ( struct share_mode_data * d ,
2011-01-26 01:23:19 +03:00
uint32_t name_hash ,
2012-04-05 01:54:02 +04:00
const struct security_token * nt_tok ,
2011-02-11 10:49:15 +03:00
const struct security_unix_token * tok )
2006-02-02 23:44:50 +03:00
{
2011-11-21 20:12:00 +04:00
struct delete_token * tmp , * dtl ;
2006-02-02 23:44:50 +03:00
2012-01-10 16:56:37 +04:00
tmp = talloc_realloc ( d , d - > delete_tokens , struct delete_token ,
d - > num_delete_tokens + 1 ) ;
2011-11-21 20:12:00 +04:00
if ( tmp = = NULL ) {
2011-01-26 01:23:19 +03:00
return false ;
}
2012-01-10 16:56:37 +04:00
d - > delete_tokens = tmp ;
dtl = & d - > delete_tokens [ d - > num_delete_tokens ] ;
2011-01-26 01:23:19 +03:00
dtl - > name_hash = name_hash ;
2023-09-15 01:08:01 +03:00
dtl - > delete_nt_token = security_token_duplicate ( d - > delete_tokens , nt_tok ) ;
2012-04-05 01:54:02 +04:00
if ( dtl - > delete_nt_token = = NULL ) {
return false ;
}
2012-01-10 16:56:37 +04:00
dtl - > delete_token = copy_unix_token ( d - > delete_tokens , tok ) ;
2011-01-26 01:23:19 +03:00
if ( dtl - > delete_token = = NULL ) {
return false ;
}
2012-01-10 16:56:37 +04:00
d - > num_delete_tokens + = 1 ;
d - > modified = true ;
2011-01-26 01:23:19 +03:00
return true ;
2006-02-02 23:44:50 +03:00
}
2015-04-21 12:36:30 +03:00
void reset_delete_on_close_lck ( files_struct * fsp ,
struct share_mode_lock * lck )
{
2022-08-26 12:17:51 +03:00
struct share_mode_data * d = NULL ;
NTSTATUS status ;
2015-04-21 12:36:30 +03:00
uint32_t i ;
2022-08-26 12:17:51 +03:00
status = share_mode_lock_access_private_data ( lck , & d ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
/* Any error recovery possible here ? */
DBG_ERR ( " share_mode_lock_access_private_data() failed for "
" %s - %s \n " , fsp_str_dbg ( fsp ) , nt_errstr ( status ) ) ;
smb_panic ( __location__ ) ;
return ;
}
2015-04-21 12:36:30 +03:00
for ( i = 0 ; i < d - > num_delete_tokens ; i + + ) {
struct delete_token * dt = & d - > delete_tokens [ i ] ;
if ( dt - > name_hash = = fsp - > name_hash ) {
d - > modified = true ;
/* Delete this entry. */
TALLOC_FREE ( dt - > delete_nt_token ) ;
TALLOC_FREE ( dt - > delete_token ) ;
* dt = d - > delete_tokens [ d - > num_delete_tokens - 1 ] ;
d - > num_delete_tokens - = 1 ;
}
}
}
2019-08-14 18:29:19 +03:00
struct set_delete_on_close_state {
struct messaging_context * msg_ctx ;
DATA_BLOB blob ;
} ;
static bool set_delete_on_close_fn (
struct share_mode_entry * e ,
bool * modified ,
void * private_data )
{
struct set_delete_on_close_state * state = private_data ;
NTSTATUS status ;
status = messaging_send (
state - > msg_ctx ,
e - > pid ,
MSG_SMB_NOTIFY_CANCEL_DELETED ,
& state - > blob ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
struct server_id_buf tmp ;
DBG_DEBUG ( " messaging_send to %s returned %s \n " ,
server_id_str_buf ( e - > pid , & tmp ) ,
nt_errstr ( status ) ) ;
}
return false ;
}
2005-09-30 21:13:37 +04:00
/****************************************************************************
Sets the delete on close flag over all share modes on this file .
Modify the share mode entry for all files open
on this device and inode to tell other smbds we have
changed the delete on close flag . This will be noticed
in the close code , the last closer will delete the file
if flag is set .
2011-02-11 10:49:15 +03:00
This makes a copy of any struct security_unix_token into the
2007-01-19 00:51:52 +03:00
lck entry . This function is used when the lock is already granted .
2005-09-30 21:13:37 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2004-06-08 20:14:31 +04:00
2011-01-26 01:23:19 +03:00
void set_delete_on_close_lck ( files_struct * fsp ,
struct share_mode_lock * lck ,
2012-04-05 01:54:02 +04:00
const struct security_token * nt_tok ,
2011-02-11 10:49:15 +03:00
const struct security_unix_token * tok )
2007-01-19 00:51:52 +03:00
{
2022-08-26 12:17:51 +03:00
struct share_mode_data * d = NULL ;
2019-08-14 18:29:19 +03:00
struct set_delete_on_close_state state = {
. msg_ctx = fsp - > conn - > sconn - > msg_ctx
} ;
2015-04-21 11:16:16 +03:00
uint32_t i ;
2011-01-26 01:23:19 +03:00
bool ret ;
2015-04-21 11:16:16 +03:00
enum ndr_err_code ndr_err ;
2022-08-26 12:17:51 +03:00
NTSTATUS status ;
status = share_mode_lock_access_private_data ( lck , & d ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
/* Any error recovery possible here ? */
DBG_ERR ( " share_mode_lock_access_private_data() failed for "
" %s - %s \n " , fsp_str_dbg ( fsp ) , nt_errstr ( status ) ) ;
smb_panic ( __location__ ) ;
return ;
}
2011-01-26 01:23:19 +03:00
2015-04-21 12:36:30 +03:00
SMB_ASSERT ( nt_tok ! = NULL ) ;
SMB_ASSERT ( tok ! = NULL ) ;
2012-01-10 16:56:37 +04:00
for ( i = 0 ; i < d - > num_delete_tokens ; i + + ) {
struct delete_token * dt = & d - > delete_tokens [ i ] ;
2011-11-21 20:12:00 +04:00
if ( dt - > name_hash = = fsp - > name_hash ) {
2012-01-10 16:56:37 +04:00
d - > modified = true ;
2015-04-21 12:36:30 +03:00
/* Replace this token with the given tok. */
TALLOC_FREE ( dt - > delete_nt_token ) ;
2023-09-15 01:08:01 +03:00
dt - > delete_nt_token = security_token_duplicate ( dt , nt_tok ) ;
2015-04-21 12:36:30 +03:00
SMB_ASSERT ( dt - > delete_nt_token ! = NULL ) ;
TALLOC_FREE ( dt - > delete_token ) ;
dt - > delete_token = copy_unix_token ( dt , tok ) ;
SMB_ASSERT ( dt - > delete_token ! = NULL ) ;
2012-04-07 02:35:55 +04:00
return ;
2007-01-19 00:51:52 +03:00
}
}
2011-01-26 01:23:19 +03:00
2022-08-26 12:17:51 +03:00
ret = add_delete_on_close_token ( d , fsp - > name_hash , nt_tok , tok ) ;
2011-01-26 01:23:19 +03:00
SMB_ASSERT ( ret ) ;
2015-04-21 11:16:16 +03:00
2019-08-14 18:29:19 +03:00
ndr_err = ndr_push_struct_blob (
& state . blob ,
talloc_tos ( ) ,
& fsp - > file_id ,
( ndr_push_flags_fn_t ) ndr_push_file_id ) ;
2015-04-21 11:16:16 +03:00
if ( ! NDR_ERR_CODE_IS_SUCCESS ( ndr_err ) ) {
2022-09-12 10:18:00 +03:00
DBG_ERR ( " ndr_push_file_id failed: %s \n " ,
ndr_errstr ( ndr_err ) ) ;
smb_panic ( __location__ ) ;
2015-04-21 11:16:16 +03:00
}
2019-08-14 18:29:19 +03:00
ret = share_mode_forall_entries (
lck , set_delete_on_close_fn , & state ) ;
if ( ! ret ) {
2022-09-12 10:18:00 +03:00
DBG_ERR ( " share_mode_forall_entries failed \n " ) ;
smb_panic ( __location__ ) ;
2015-04-21 11:16:16 +03:00
}
2019-08-14 18:29:19 +03:00
TALLOC_FREE ( state . blob . data ) ;
2007-01-19 00:51:52 +03:00
}
2022-08-31 17:34:40 +03:00
struct set_delete_on_close_locked_state {
struct files_struct * fsp ;
bool delete_on_close ;
const struct security_token * nt_tok ;
const struct security_unix_token * tok ;
} ;
static void set_delete_on_close_locked ( struct share_mode_lock * lck ,
void * private_data )
{
struct set_delete_on_close_locked_state * state =
( struct set_delete_on_close_locked_state * ) private_data ;
if ( state - > delete_on_close ) {
set_delete_on_close_lck ( state - > fsp ,
lck ,
state - > nt_tok ,
state - > tok ) ;
} else {
reset_delete_on_close_lck ( state - > fsp , lck ) ;
}
state - > fsp - > fsp_flags . delete_on_close = state - > delete_on_close ;
}
2012-04-05 01:54:02 +04:00
bool set_delete_on_close ( files_struct * fsp , bool delete_on_close ,
const struct security_token * nt_tok ,
const struct security_unix_token * tok )
2004-06-08 20:14:31 +04:00
{
2022-08-31 17:34:40 +03:00
struct set_delete_on_close_locked_state state = {
. fsp = fsp ,
. delete_on_close = delete_on_close ,
. nt_tok = nt_tok ,
. tok = tok ,
} ;
NTSTATUS status ;
2011-05-28 12:24:20 +04:00
2005-09-30 21:13:37 +04:00
DEBUG ( 10 , ( " set_delete_on_close: %s delete on close flag for "
2012-06-14 14:25:43 +04:00
" %s, file %s \n " ,
delete_on_close ? " Adding " : " Removing " , fsp_fnum_dbg ( fsp ) ,
2009-07-11 01:50:37 +04:00
fsp_str_dbg ( fsp ) ) ) ;
2004-06-08 20:14:31 +04:00
2020-04-02 19:21:11 +03:00
if ( fsp - > fsp_flags . is_directory ) {
2009-07-11 01:50:37 +04:00
SMB_ASSERT ( ! is_ntfs_stream_smb_fname ( fsp - > fsp_name ) ) ;
2007-01-20 00:46:12 +03:00
}
2022-08-31 17:34:40 +03:00
status = share_mode_do_locked_vfs_denied ( fsp - > file_id ,
set_delete_on_close_locked ,
& state ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return false ;
}
2010-01-13 03:04:44 +03:00
2005-09-30 21:13:37 +04:00
return True ;
}
2001-08-21 05:25:45 +04:00
2012-06-01 17:50:39 +04:00
static struct delete_token * find_delete_on_close_token (
struct share_mode_data * d , uint32_t name_hash )
{
uint32_t i ;
2019-09-03 17:40:00 +03:00
DBG_DEBUG ( " name_hash = 0x% " PRIx32 " \n " , name_hash ) ;
2012-06-01 17:50:39 +04:00
for ( i = 0 ; i < d - > num_delete_tokens ; i + + ) {
struct delete_token * dt = & d - > delete_tokens [ i ] ;
2019-09-03 17:40:00 +03:00
DBG_DEBUG ( " dt->name_hash = 0x% " PRIx32 " \n " ,
dt - > name_hash ) ;
2012-06-01 17:50:39 +04:00
if ( dt - > name_hash = = name_hash ) {
return dt ;
}
}
return NULL ;
}
2012-04-05 01:54:02 +04:00
/****************************************************************************
Return the NT token and UNIX token if there ' s a match . Return true if
found , false if not .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
bool get_delete_on_close_token ( struct share_mode_lock * lck ,
uint32_t name_hash ,
const struct security_token * * pp_nt_tok ,
const struct security_unix_token * * pp_tok )
2011-01-26 01:23:19 +03:00
{
2022-08-26 12:17:51 +03:00
struct share_mode_data * d = NULL ;
2012-06-01 17:50:39 +04:00
struct delete_token * dt ;
2022-08-26 12:17:51 +03:00
NTSTATUS status ;
status = share_mode_lock_access_private_data ( lck , & d ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
struct file_id id = share_mode_lock_file_id ( lck ) ;
struct file_id_buf id_buf ;
/* Any error recovery possible here ? */
DBG_ERR ( " share_mode_lock_access_private_data() failed for "
" %s name_hash=% " PRIu32 " - %s \n " ,
file_id_str_buf ( id , & id_buf ) , name_hash ,
nt_errstr ( status ) ) ;
return false ;
}
2011-01-26 01:23:19 +03:00
2022-08-26 12:17:51 +03:00
dt = find_delete_on_close_token ( d , name_hash ) ;
2012-06-01 17:50:39 +04:00
if ( dt = = NULL ) {
return false ;
}
2012-06-01 17:52:14 +04:00
* pp_nt_tok = dt - > delete_nt_token ;
* pp_tok = dt - > delete_token ;
2012-06-01 17:50:39 +04:00
return true ;
2011-01-26 01:23:19 +03:00
}
bool is_delete_on_close_set ( struct share_mode_lock * lck , uint32_t name_hash )
{
2022-08-26 12:17:51 +03:00
struct share_mode_data * d = NULL ;
NTSTATUS status ;
status = share_mode_lock_access_private_data ( lck , & d ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
struct file_id id = share_mode_lock_file_id ( lck ) ;
struct file_id_buf id_buf ;
/* Any error recovery possible here ? */
DBG_ERR ( " share_mode_lock_access_private_data() failed for "
" %s name_hash=% " PRIu32 " - %s \n " ,
file_id_str_buf ( id , & id_buf ) , name_hash ,
nt_errstr ( status ) ) ;
return false ;
}
return find_delete_on_close_token ( d , name_hash ) ! = NULL ;
2011-01-26 01:23:19 +03:00
}
2022-09-01 13:54:35 +03:00
struct set_sticky_write_time_state {
struct file_id fileid ;
struct timespec write_time ;
bool ok ;
} ;
static void set_sticky_write_time_fn ( struct share_mode_lock * lck ,
void * private_data )
2008-03-12 17:32:47 +03:00
{
2022-09-01 13:54:35 +03:00
struct set_sticky_write_time_state * state = private_data ;
2022-08-26 12:17:51 +03:00
struct share_mode_data * d = NULL ;
2019-09-06 08:31:22 +03:00
struct file_id_buf ftmp ;
2019-12-02 18:30:50 +03:00
struct timeval_buf tbuf ;
2022-08-26 12:17:51 +03:00
NTSTATUS status ;
2008-03-12 17:32:47 +03:00
2022-08-26 12:17:51 +03:00
status = share_mode_lock_access_private_data ( lck , & d ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
/* Any error recovery possible here ? */
DBG_ERR ( " share_mode_lock_access_private_data() failed for "
2022-09-01 13:54:35 +03:00
" %s id=%s - %s \n " ,
timespec_string_buf ( & state - > write_time , true , & tbuf ) ,
file_id_str_buf ( state - > fileid , & ftmp ) ,
nt_errstr ( status ) ) ;
return ;
}
share_mode_set_changed_write_time ( lck , state - > write_time ) ;
state - > ok = true ;
}
bool set_sticky_write_time ( struct file_id fileid , struct timespec write_time )
{
struct set_sticky_write_time_state state = {
. fileid = fileid ,
. write_time = write_time ,
} ;
struct file_id_buf ftmp ;
struct timeval_buf tbuf ;
NTSTATUS status ;
status = share_mode_do_locked_vfs_denied ( fileid ,
set_sticky_write_time_fn ,
& state ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
/* Any error recovery possible here ? */
DBG_ERR ( " share_mode_do_locked_vfs_denied() failed for "
2022-08-26 12:17:51 +03:00
" %s id=%s - %s \n " ,
timespec_string_buf ( & write_time , true , & tbuf ) ,
file_id_str_buf ( fileid , & ftmp ) ,
nt_errstr ( status ) ) ;
return false ;
}
2022-09-01 13:54:35 +03:00
return state . ok ;
2008-03-12 17:32:47 +03:00
}
2022-09-01 13:49:51 +03:00
struct set_write_time_state {
struct file_id fileid ;
struct timespec write_time ;
bool ok ;
} ;
static void set_write_time_fn ( struct share_mode_lock * lck ,
void * private_data )
2008-09-06 06:00:48 +04:00
{
2022-09-01 13:49:51 +03:00
struct set_write_time_state * state = private_data ;
2022-08-26 12:17:51 +03:00
struct share_mode_data * d = NULL ;
2019-11-04 09:39:48 +03:00
struct file_id_buf idbuf ;
2019-12-02 18:30:50 +03:00
struct timeval_buf tbuf ;
2022-08-26 12:17:51 +03:00
NTSTATUS status ;
2008-09-06 06:00:48 +04:00
2022-08-26 12:17:51 +03:00
status = share_mode_lock_access_private_data ( lck , & d ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
/* Any error recovery possible here ? */
DBG_ERR ( " share_mode_lock_access_private_data() failed for "
2022-09-01 13:49:51 +03:00
" %s id=%s - %s \n " ,
timespec_string_buf ( & state - > write_time , true , & tbuf ) ,
file_id_str_buf ( state - > fileid , & idbuf ) ,
nt_errstr ( status ) ) ;
return ;
}
share_mode_set_old_write_time ( lck , state - > write_time ) ;
state - > ok = true ;
}
bool set_write_time ( struct file_id fileid , struct timespec write_time )
{
struct set_write_time_state state = {
. fileid = fileid ,
. write_time = write_time ,
} ;
struct file_id_buf idbuf ;
struct timeval_buf tbuf ;
NTSTATUS status ;
status = share_mode_do_locked_vfs_denied ( fileid ,
set_write_time_fn ,
& state ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DBG_ERR ( " share_mode_do_locked_vfs_denied() failed for "
2022-08-26 12:17:51 +03:00
" %s id=%s - %s \n " ,
timespec_string_buf ( & write_time , true , & tbuf ) ,
file_id_str_buf ( fileid , & idbuf ) ,
nt_errstr ( status ) ) ;
return false ;
}
2022-09-01 13:49:51 +03:00
return state . ok ;
2008-09-06 06:00:48 +04:00
}
2013-11-22 18:36:49 +04:00
struct timespec get_share_mode_write_time ( struct share_mode_lock * lck )
{
2022-08-26 12:17:51 +03:00
struct share_mode_data * d = NULL ;
NTSTATUS status ;
status = share_mode_lock_access_private_data ( lck , & d ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
struct file_id id = share_mode_lock_file_id ( lck ) ;
struct file_id_buf id_buf ;
struct timespec ts_zero = { } ;
/* Any error recovery possible here ? */
DBG_ERR ( " share_mode_lock_access_private_data() failed for "
" %s - %s \n " ,
file_id_str_buf ( id , & id_buf ) ,
nt_errstr ( status ) ) ;
smb_panic ( __location__ ) ;
return ts_zero ;
}
2013-11-22 18:36:49 +04:00
2019-12-02 18:30:50 +03:00
if ( ! null_nttime ( d - > changed_write_time ) ) {
return nt_time_to_full_timespec ( d - > changed_write_time ) ;
2013-11-22 18:36:49 +04:00
}
2019-12-02 18:30:50 +03:00
return nt_time_to_full_timespec ( d - > old_write_time ) ;
2013-11-22 18:36:49 +04:00
}
2018-05-27 14:03:25 +03:00
2019-08-16 16:56:23 +03:00
struct file_has_open_streams_state {
bool found_one ;
2022-09-01 13:34:16 +03:00
bool ok ;
2019-08-16 16:56:23 +03:00
} ;
static bool file_has_open_streams_fn (
struct share_mode_entry * e ,
bool * modified ,
void * private_data )
{
struct file_has_open_streams_state * state = private_data ;
if ( ( e - > private_options &
2020-10-23 14:08:50 +03:00
NTCREATEX_FLAG_STREAM_BASEOPEN ) = = 0 ) {
2019-08-16 16:56:23 +03:00
return false ;
}
if ( share_entry_stale_pid ( e ) ) {
return false ;
}
state - > found_one = true ;
return true ;
}
2022-09-01 13:34:16 +03:00
static void file_has_open_streams_locked ( struct share_mode_lock * lck ,
void * private_data )
{
struct file_has_open_streams_state * state = private_data ;
state - > ok = share_mode_forall_entries ( lck ,
file_has_open_streams_fn ,
private_data ) ;
}
2018-05-27 14:03:25 +03:00
bool file_has_open_streams ( files_struct * fsp )
{
2019-08-16 16:56:23 +03:00
struct file_has_open_streams_state state = { . found_one = false } ;
2022-09-01 13:34:16 +03:00
NTSTATUS status ;
2018-05-27 14:03:25 +03:00
2022-09-01 13:34:16 +03:00
status = share_mode_do_locked_vfs_denied ( fsp - > file_id ,
file_has_open_streams_locked ,
& state ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DBG_DEBUG ( " share_mode_do_locked_vfs_denied() failed - %s \n " ,
nt_errstr ( status ) ) ;
2018-05-27 14:03:25 +03:00
return false ;
}
2022-09-01 13:34:16 +03:00
if ( ! state . ok ) {
2019-08-16 16:56:23 +03:00
DBG_DEBUG ( " share_mode_forall_entries failed \n " ) ;
return false ;
2018-05-27 14:03:25 +03:00
}
2022-09-01 13:34:16 +03:00
2019-08-16 16:56:23 +03:00
return state . found_one ;
2018-05-27 14:03:25 +03:00
}
2018-09-17 14:14:22 +03:00
/*
* Walk share mode entries , looking at every lease only once
*/
2019-08-26 23:05:14 +03:00
struct share_mode_forall_leases_state {
TALLOC_CTX * mem_ctx ;
struct leases_db_key * leases ;
2019-09-10 22:21:01 +03:00
bool ( * fn ) ( struct share_mode_entry * e ,
2019-08-26 23:05:14 +03:00
void * private_data ) ;
void * private_data ;
NTSTATUS status ;
} ;
static bool share_mode_forall_leases_fn (
struct share_mode_entry * e ,
bool * modified ,
2018-09-17 14:14:22 +03:00
void * private_data )
{
2019-08-26 23:05:14 +03:00
struct share_mode_forall_leases_state * state = private_data ;
struct leases_db_key * leases = state - > leases ;
size_t i , num_leases ;
bool stop ;
2018-09-17 14:14:22 +03:00
2019-08-26 23:05:14 +03:00
if ( e - > op_type ! = LEASE_OPLOCK ) {
2018-09-17 14:14:22 +03:00
return false ;
}
2019-08-26 23:05:14 +03:00
num_leases = talloc_array_length ( leases ) ;
2018-09-17 14:14:22 +03:00
2019-08-26 23:05:14 +03:00
for ( i = 0 ; i < num_leases ; i + + ) {
struct leases_db_key * l = & leases [ i ] ;
bool same = smb2_lease_equal (
& e - > client_guid ,
& e - > lease_key ,
& l - > client_guid ,
& l - > lease_key ) ;
if ( same ) {
return false ;
2018-09-17 14:14:22 +03:00
}
2019-08-26 23:05:14 +03:00
}
2018-09-17 14:14:22 +03:00
2019-08-26 23:05:14 +03:00
leases = talloc_realloc (
state - > mem_ctx ,
leases ,
struct leases_db_key ,
num_leases + 1 ) ;
if ( leases = = NULL ) {
state - > status = NT_STATUS_NO_MEMORY ;
return true ;
}
leases [ num_leases ] = ( struct leases_db_key ) {
. client_guid = e - > client_guid ,
. lease_key = e - > lease_key ,
} ;
state - > leases = leases ;
2018-09-17 14:14:22 +03:00
2019-08-26 23:05:14 +03:00
stop = state - > fn ( e , state - > private_data ) ;
return stop ;
}
2018-09-17 14:14:22 +03:00
2019-08-26 23:05:14 +03:00
bool share_mode_forall_leases (
struct share_mode_lock * lck ,
bool ( * fn ) ( struct share_mode_entry * e ,
void * private_data ) ,
void * private_data )
{
struct share_mode_forall_leases_state state = {
. mem_ctx = talloc_tos ( ) ,
. fn = fn ,
. private_data = private_data
} ;
bool ok ;
2018-09-17 14:14:22 +03:00
2019-08-26 23:05:14 +03:00
ok = share_mode_forall_entries (
lck , share_mode_forall_leases_fn , & state ) ;
TALLOC_FREE ( state . leases ) ;
if ( ! ok ) {
2022-09-10 21:39:19 +03:00
DBG_ERR ( " share_mode_forall_entries failed \n " ) ;
2019-08-26 23:05:14 +03:00
return false ;
}
2018-09-17 14:14:22 +03:00
2019-08-26 23:05:14 +03:00
if ( ! NT_STATUS_IS_OK ( state . status ) ) {
2022-09-10 21:39:19 +03:00
DBG_ERR ( " share_mode_forall_leases_fn returned %s \n " ,
nt_errstr ( state . status ) ) ;
2019-08-26 23:05:14 +03:00
return false ;
2018-09-17 14:14:22 +03:00
}
return true ;
}