2012-02-07 02:06:41 +04:00
/*
Unix SMB / CIFS implementation .
Copyright ( C ) Stefan Metzmacher 2012
Copyright ( C ) Michael Adam 2012
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
the Free Software Foundation ; either version 3 of the License , or
( at your option ) any later version .
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 .
You should have received a copy of the GNU General Public License
along with this program . If not , see < http : //www.gnu.org/licenses/>.
*/
2021-10-26 14:48:28 +03:00
# include "smbXsrv_open.h"
2012-02-07 02:06:41 +04:00
# include "includes.h"
# include "system/filesys.h"
2017-01-01 23:00:55 +03:00
# include "lib/util/server_id.h"
2012-02-07 02:06:41 +04:00
# include "smbd/smbd.h"
# include "smbd/globals.h"
# include "dbwrap/dbwrap.h"
# include "dbwrap/dbwrap_rbt.h"
# include "dbwrap/dbwrap_open.h"
# include "../libcli/security/security.h"
# include "messages.h"
# include "lib/util/util_tdb.h"
# include "librpc/gen_ndr/ndr_smbXsrv.h"
# include "serverid.h"
2023-01-04 11:52:50 +03:00
# include "source3/include/util_tdb.h"
2023-01-04 14:18:44 +03:00
# include "lib/util/idtree_random.h"
2023-01-10 14:29:18 +03:00
# include "lib/util/time_basic.h"
2012-02-07 02:06:41 +04:00
struct smbXsrv_open_table {
struct {
2023-01-04 14:18:44 +03:00
struct idr_context * idr ;
2016-02-24 02:23:15 +03:00
struct db_context * replay_cache_db_ctx ;
2012-02-07 02:06:41 +04:00
uint32_t lowest_id ;
uint32_t highest_id ;
uint32_t max_opens ;
uint32_t num_opens ;
} local ;
struct {
struct db_context * db_ctx ;
} global ;
} ;
static struct db_context * smbXsrv_open_global_db_ctx = NULL ;
NTSTATUS smbXsrv_open_global_init ( void )
{
2014-11-02 22:21:48 +03:00
char * global_path = NULL ;
2012-02-07 02:06:41 +04:00
struct db_context * db_ctx = NULL ;
if ( smbXsrv_open_global_db_ctx ! = NULL ) {
return NT_STATUS_OK ;
}
2018-08-16 11:51:44 +03:00
global_path = lock_path ( talloc_tos ( ) , " smbXsrv_open_global.tdb " ) ;
2014-11-02 22:21:48 +03:00
if ( global_path = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
2012-02-07 02:06:41 +04:00
db_ctx = db_open ( NULL , global_path ,
2019-06-17 17:36:01 +03:00
SMBD_VOLATILE_TDB_HASH_SIZE ,
SMBD_VOLATILE_TDB_FLAGS ,
2012-02-07 02:06:41 +04:00
O_RDWR | O_CREAT , 0600 ,
2014-01-27 17:49:12 +04:00
DBWRAP_LOCK_ORDER_1 ,
DBWRAP_FLAG_NONE ) ;
2014-11-02 22:21:48 +03:00
TALLOC_FREE ( global_path ) ;
2012-02-07 02:06:41 +04:00
if ( db_ctx = = NULL ) {
2024-02-09 14:47:48 +03:00
NTSTATUS status = map_nt_error_from_unix_common ( errno ) ;
2012-02-07 02:06:41 +04:00
return status ;
}
smbXsrv_open_global_db_ctx = db_ctx ;
return NT_STATUS_OK ;
}
/*
* NOTE :
* We need to store the keys in big endian so that dbwrap_rbt ' s memcmp
* has the same result as integer comparison between the uint32_t
* values .
*
* TODO : implement string based key
*/
2023-01-04 22:09:32 +03:00
struct smbXsrv_open_global_key_buf { uint8_t buf [ sizeof ( uint32_t ) ] ; } ;
2012-02-07 02:06:41 +04:00
2023-01-04 22:09:32 +03:00
static TDB_DATA smbXsrv_open_global_id_to_key (
uint32_t id , struct smbXsrv_open_global_key_buf * key_buf )
2012-02-07 02:06:41 +04:00
{
2023-01-04 22:09:32 +03:00
RSIVAL ( key_buf - > buf , 0 , id ) ;
2012-02-07 02:06:41 +04:00
2023-01-04 22:09:32 +03:00
return ( TDB_DATA ) {
. dptr = key_buf - > buf ,
. dsize = sizeof ( key_buf - > buf ) ,
} ;
2012-02-07 02:06:41 +04:00
}
static NTSTATUS smbXsrv_open_table_init ( struct smbXsrv_connection * conn ,
uint32_t lowest_id ,
uint32_t highest_id ,
uint32_t max_opens )
{
2014-06-12 22:22:54 +04:00
struct smbXsrv_client * client = conn - > client ;
2012-02-07 02:06:41 +04:00
struct smbXsrv_open_table * table ;
NTSTATUS status ;
uint64_t max_range ;
if ( lowest_id > highest_id ) {
return NT_STATUS_INTERNAL_ERROR ;
}
max_range = highest_id ;
max_range - = lowest_id ;
max_range + = 1 ;
if ( max_opens > max_range ) {
return NT_STATUS_INTERNAL_ERROR ;
}
2014-06-12 22:22:54 +04:00
table = talloc_zero ( client , struct smbXsrv_open_table ) ;
2012-02-07 02:06:41 +04:00
if ( table = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
2023-01-04 14:18:44 +03:00
table - > local . idr = idr_init ( table ) ;
if ( table - > local . idr = = NULL ) {
2012-02-07 02:06:41 +04:00
TALLOC_FREE ( table ) ;
return NT_STATUS_NO_MEMORY ;
}
2016-02-24 02:23:15 +03:00
table - > local . replay_cache_db_ctx = db_open_rbt ( table ) ;
if ( table - > local . replay_cache_db_ctx = = NULL ) {
TALLOC_FREE ( table ) ;
return NT_STATUS_NO_MEMORY ;
}
2012-02-07 02:06:41 +04:00
table - > local . lowest_id = lowest_id ;
table - > local . highest_id = highest_id ;
table - > local . max_opens = max_opens ;
status = smbXsrv_open_global_init ( ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
TALLOC_FREE ( table ) ;
return status ;
}
table - > global . db_ctx = smbXsrv_open_global_db_ctx ;
2014-06-12 22:22:54 +04:00
client - > open_table = table ;
2012-02-07 02:06:41 +04:00
return NT_STATUS_OK ;
}
static NTSTATUS smbXsrv_open_local_lookup ( struct smbXsrv_open_table * table ,
uint32_t open_local_id ,
uint32_t open_global_id ,
NTTIME now ,
struct smbXsrv_open * * _open )
{
2023-01-04 14:18:44 +03:00
struct smbXsrv_open * op = NULL ;
2012-02-07 02:06:41 +04:00
* _open = NULL ;
if ( open_local_id = = 0 ) {
return NT_STATUS_FILE_CLOSED ;
}
if ( table = = NULL ) {
/* this might happen before the end of negprot */
return NT_STATUS_FILE_CLOSED ;
}
2023-01-04 14:18:44 +03:00
if ( table - > local . idr = = NULL ) {
2012-02-07 02:06:41 +04:00
return NT_STATUS_INTERNAL_ERROR ;
}
2023-01-04 14:18:44 +03:00
op = idr_find ( table - > local . idr , open_local_id ) ;
if ( op = = NULL ) {
2012-02-07 02:06:41 +04:00
return NT_STATUS_FILE_CLOSED ;
}
if ( open_global_id = = 0 ) {
/* make the global check a no-op for SMB1 */
2023-01-04 14:18:44 +03:00
open_global_id = op - > global - > open_global_id ;
2012-02-07 02:06:41 +04:00
}
2023-01-04 14:18:44 +03:00
if ( op - > global - > open_global_id ! = open_global_id ) {
2012-02-07 02:06:41 +04:00
return NT_STATUS_FILE_CLOSED ;
}
2014-04-11 02:29:48 +04:00
if ( now ! = 0 ) {
2023-01-04 14:18:44 +03:00
op - > idle_time = now ;
2014-04-11 02:29:48 +04:00
}
2012-02-07 02:06:41 +04:00
2023-01-04 14:18:44 +03:00
* _open = op ;
return NT_STATUS_OK ;
2012-02-07 02:06:41 +04:00
}
2023-01-19 14:22:33 +03:00
static NTSTATUS smbXsrv_open_global_parse_record (
TALLOC_CTX * mem_ctx ,
2023-01-19 14:25:21 +03:00
TDB_DATA key ,
TDB_DATA val ,
2023-01-19 14:22:33 +03:00
struct smbXsrv_open_global0 * * global )
{
DATA_BLOB blob = data_blob_const ( val . dptr , val . dsize ) ;
struct smbXsrv_open_globalB global_blob ;
enum ndr_err_code ndr_err ;
NTSTATUS status ;
TALLOC_CTX * frame = talloc_stackframe ( ) ;
ndr_err = ndr_pull_struct_blob ( & blob , frame , & global_blob ,
( ndr_pull_flags_fn_t ) ndr_pull_smbXsrv_open_globalB ) ;
if ( ! NDR_ERR_CODE_IS_SUCCESS ( ndr_err ) ) {
DEBUG ( 1 , ( " Invalid record in smbXsrv_open_global.tdb: "
" key '%s' ndr_pull_struct_blob - %s \n " ,
tdb_data_dbg ( key ) ,
ndr_errstr ( ndr_err ) ) ) ;
status = ndr_map_error2ntstatus ( ndr_err ) ;
goto done ;
}
2023-01-19 14:29:20 +03:00
DBG_DEBUG ( " \n " ) ;
if ( CHECK_DEBUGLVL ( 10 ) ) {
NDR_PRINT_DEBUG ( smbXsrv_open_globalB , & global_blob ) ;
}
2023-01-19 14:22:33 +03:00
if ( global_blob . version ! = SMBXSRV_VERSION_0 ) {
status = NT_STATUS_INTERNAL_DB_CORRUPTION ;
DEBUG ( 1 , ( " Invalid record in smbXsrv_open_global.tdb: "
" key '%s' unsupported version - %d - %s \n " ,
tdb_data_dbg ( key ) ,
( int ) global_blob . version ,
nt_errstr ( status ) ) ) ;
goto done ;
}
if ( global_blob . info . info0 = = NULL ) {
status = NT_STATUS_INTERNAL_DB_CORRUPTION ;
2023-02-13 14:36:38 +03:00
DEBUG ( 1 , ( " Invalid record in smbXsrv_open_global.tdb: "
2023-01-19 14:22:33 +03:00
" key '%s' info0 NULL pointer - %s \n " ,
tdb_data_dbg ( key ) ,
nt_errstr ( status ) ) ) ;
goto done ;
}
* global = talloc_move ( mem_ctx , & global_blob . info . info0 ) ;
status = NT_STATUS_OK ;
done :
talloc_free ( frame ) ;
return status ;
}
2023-01-06 18:25:03 +03:00
static NTSTATUS smbXsrv_open_global_verify_record (
TDB_DATA key ,
TDB_DATA val ,
TALLOC_CTX * mem_ctx ,
struct smbXsrv_open_global0 * * _global0 )
2012-02-07 02:06:41 +04:00
{
2023-01-06 18:25:03 +03:00
struct smbXsrv_open_global0 * global0 = NULL ;
struct server_id_buf buf ;
2023-01-19 14:29:20 +03:00
NTSTATUS status ;
2012-02-07 02:06:41 +04:00
if ( val . dsize = = 0 ) {
2023-01-06 18:25:03 +03:00
return NT_STATUS_NOT_FOUND ;
2012-02-07 02:06:41 +04:00
}
2023-01-19 14:29:20 +03:00
status = smbXsrv_open_global_parse_record ( mem_ctx , key , val , & global0 ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DBG_WARNING ( " smbXsrv_open_global_parse_record for %s failed: "
" %s \n " ,
2023-01-06 18:25:03 +03:00
tdb_data_dbg ( key ) ,
2023-01-19 14:29:20 +03:00
nt_errstr ( status ) ) ;
return status ;
2012-02-07 02:06:41 +04:00
}
2023-01-06 18:25:03 +03:00
* _global0 = global0 ;
2012-02-07 02:06:41 +04:00
2023-01-06 18:25:03 +03:00
if ( server_id_is_disconnected ( & global0 - > server_id ) ) {
return NT_STATUS_OK ;
2012-06-18 14:46:15 +04:00
}
2023-01-06 18:25:03 +03:00
if ( serverid_exists ( & global0 - > server_id ) ) {
return NT_STATUS_OK ;
2012-02-07 02:06:41 +04:00
}
2023-01-06 18:25:03 +03:00
DBG_WARNING ( " smbd %s did not clean up record %s \n " ,
server_id_str_buf ( global0 - > server_id , & buf ) ,
tdb_data_dbg ( key ) ) ;
return NT_STATUS_FATAL_APP_EXIT ;
2012-02-07 02:06:41 +04:00
}
2023-01-05 18:18:37 +03:00
static NTSTATUS smbXsrv_open_global_store (
struct db_record * rec ,
TDB_DATA key ,
TDB_DATA oldval ,
struct smbXsrv_open_global0 * global )
2012-02-07 02:06:41 +04:00
{
struct smbXsrv_open_globalB global_blob ;
DATA_BLOB blob = data_blob_null ;
2023-01-05 18:18:37 +03:00
TDB_DATA val = { . dptr = NULL , } ;
2012-02-07 02:06:41 +04:00
NTSTATUS status ;
enum ndr_err_code ndr_err ;
/*
* TODO : if we use other versions than ' 0 '
* we would add glue code here , that would be able to
* store the information in the old format .
*/
2023-01-04 10:50:28 +03:00
global_blob = ( struct smbXsrv_open_globalB ) {
. version = smbXsrv_version_global_current ( ) ,
} ;
2023-01-05 18:18:37 +03:00
if ( oldval . dsize > = 8 ) {
global_blob . seqnum = IVAL ( oldval . dptr , 4 ) ;
2012-02-07 02:06:41 +04:00
}
global_blob . seqnum + = 1 ;
global_blob . info . info0 = global ;
2023-01-04 12:12:22 +03:00
ndr_err = ndr_push_struct_blob ( & blob , talloc_tos ( ) , & global_blob ,
2012-02-07 02:06:41 +04:00
( ndr_push_flags_fn_t ) ndr_push_smbXsrv_open_globalB ) ;
if ( ! NDR_ERR_CODE_IS_SUCCESS ( ndr_err ) ) {
2023-01-05 18:06:40 +03:00
DBG_WARNING ( " key '%s' ndr_push - %s \n " ,
tdb_data_dbg ( key ) ,
ndr_map_error2string ( ndr_err ) ) ;
return ndr_map_error2ntstatus ( ndr_err ) ;
2012-02-07 02:06:41 +04:00
}
val = make_tdb_data ( blob . data , blob . length ) ;
2023-01-05 18:18:37 +03:00
status = dbwrap_record_store ( rec , val , TDB_REPLACE ) ;
2023-01-04 12:12:22 +03:00
TALLOC_FREE ( blob . data ) ;
2012-02-07 02:06:41 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2023-01-05 18:06:40 +03:00
DBG_WARNING ( " key '%s' store - %s \n " ,
tdb_data_dbg ( key ) ,
nt_errstr ( status ) ) ;
2012-02-07 02:06:41 +04:00
return status ;
}
smbd: Avoid duplicate debug header lines
This is what gets created in log.smbd: DEBUGLVL generates an empty
header line, CHECK_DEBUGLVL avoids this.
[2014/01/10 12:58:24.971658, 10, pid=2329, effective(1001, 1001), real(0, 0)] ../source3/smbd/smbXsrv_open.c:696(smbXsrv_open_global_store)
[2014/01/10 12:58:24.971690, 10, pid=2329, effective(1001, 1001), real(0, 0)] ../source3/smbd/smbXsrv_open.c:698(smbXsrv_open_global_store)
Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
Autobuild-User(master): Jeremy Allison <jra@samba.org>
Autobuild-Date(master): Wed Jan 15 04:02:58 CET 2014 on sn-devel-104
2014-01-10 16:02:59 +04:00
if ( CHECK_DEBUGLVL ( 10 ) ) {
2023-01-05 18:06:40 +03:00
DBG_DEBUG ( " key '%s' stored \n " , tdb_data_dbg ( key ) ) ;
2012-02-07 02:06:41 +04:00
NDR_PRINT_DEBUG ( smbXsrv_open_globalB , & global_blob ) ;
}
return NT_STATUS_OK ;
}
2023-01-26 11:08:27 +03:00
struct smbXsrv_open_global_allocate_state {
uint32_t id ;
struct smbXsrv_open_global0 * global ;
NTSTATUS status ;
} ;
static void smbXsrv_open_global_allocate_fn (
struct db_record * rec , TDB_DATA oldval , void * private_data )
{
struct smbXsrv_open_global_allocate_state * state = private_data ;
struct smbXsrv_open_global0 * global = state - > global ;
struct smbXsrv_open_global0 * tmp_global0 = NULL ;
TDB_DATA key = dbwrap_record_get_key ( rec ) ;
state - > status = smbXsrv_open_global_verify_record (
key , oldval , talloc_tos ( ) , & tmp_global0 ) ;
if ( NT_STATUS_IS_OK ( state - > status ) ) {
/*
* Found an existing record
*/
TALLOC_FREE ( tmp_global0 ) ;
state - > status = NT_STATUS_RETRY ;
return ;
}
if ( NT_STATUS_EQUAL ( state - > status , NT_STATUS_NOT_FOUND ) ) {
/*
* Found an empty slot
*/
global - > open_global_id = state - > id ;
global - > open_persistent_id = state - > id ;
state - > status = smbXsrv_open_global_store (
rec , key , ( TDB_DATA ) { . dsize = 0 , } , state - > global ) ;
if ( ! NT_STATUS_IS_OK ( state - > status ) ) {
DBG_WARNING ( " smbXsrv_open_global_store() for "
" id % " PRIu32 " failed: %s \n " ,
state - > id ,
nt_errstr ( state - > status ) ) ;
}
return ;
}
if ( NT_STATUS_EQUAL ( state - > status , NT_STATUS_FATAL_APP_EXIT ) ) {
NTSTATUS status ;
TALLOC_FREE ( tmp_global0 ) ;
/*
* smbd crashed
*/
status = dbwrap_record_delete ( rec ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DBG_WARNING ( " dbwrap_record_delete() failed "
" for record % " PRIu32 " : %s \n " ,
state - > id ,
nt_errstr ( status ) ) ;
state - > status = NT_STATUS_INTERNAL_DB_CORRUPTION ;
return ;
}
return ;
}
}
2023-01-26 10:46:31 +03:00
static NTSTATUS smbXsrv_open_global_allocate (
struct db_context * db , struct smbXsrv_open_global0 * global )
{
2023-01-26 11:08:27 +03:00
struct smbXsrv_open_global_allocate_state state = {
. global = global ,
} ;
2023-01-26 10:46:31 +03:00
uint32_t i ;
uint32_t last_free = 0 ;
const uint32_t min_tries = 3 ;
/*
* Here we just randomly try the whole 32 - bit space
*
* We use just 32 - bit , because we want to reuse the
* ID for SRVSVC .
*/
for ( i = 0 ; i < UINT32_MAX ; i + + ) {
struct smbXsrv_open_global_key_buf key_buf ;
2023-01-26 11:08:27 +03:00
TDB_DATA key ;
2023-01-26 10:46:31 +03:00
NTSTATUS status ;
if ( i > = min_tries & & last_free ! = 0 ) {
2023-01-26 11:08:27 +03:00
state . id = last_free ;
2023-01-26 10:46:31 +03:00
} else {
2023-01-26 11:08:27 +03:00
generate_nonce_buffer (
( uint8_t * ) & state . id , sizeof ( state . id ) ) ;
state . id = MAX ( state . id , 1 ) ;
state . id = MIN ( state . id , UINT32_MAX - 1 ) ;
2023-01-26 10:46:31 +03:00
}
2023-01-26 11:08:27 +03:00
key = smbXsrv_open_global_id_to_key ( state . id , & key_buf ) ;
2023-01-26 10:46:31 +03:00
2023-01-26 11:08:27 +03:00
status = dbwrap_do_locked (
db , key , smbXsrv_open_global_allocate_fn , & state ) ;
2023-01-26 10:46:31 +03:00
2023-01-26 11:08:27 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
DBG_WARNING ( " dbwrap_do_locked() failed: %s \n " ,
nt_errstr ( status ) ) ;
return NT_STATUS_INTERNAL_DB_ERROR ;
}
2023-01-26 10:46:31 +03:00
2023-01-26 11:08:27 +03:00
if ( NT_STATUS_IS_OK ( state . status ) ) {
2023-01-26 10:46:31 +03:00
/*
2023-01-26 11:08:27 +03:00
* Found an empty slot , done .
2023-01-26 10:46:31 +03:00
*/
2023-01-26 11:08:27 +03:00
DBG_DEBUG ( " Found slot % " PRIu32 " \n " , state . id ) ;
return NT_STATUS_OK ;
2023-01-26 10:46:31 +03:00
}
2023-01-26 11:08:27 +03:00
if ( NT_STATUS_EQUAL ( state . status , NT_STATUS_FATAL_APP_EXIT ) ) {
2023-01-26 10:46:31 +03:00
if ( ( i < min_tries ) & & ( last_free = = 0 ) ) {
/*
* Remember " id " as free but also try
* others to not recycle ids too
* quickly .
*/
2023-01-26 11:08:27 +03:00
last_free = state . id ;
2023-01-26 10:46:31 +03:00
}
2023-01-26 11:08:27 +03:00
continue ;
2023-01-26 10:46:31 +03:00
}
2023-01-26 11:08:27 +03:00
if ( NT_STATUS_EQUAL ( state . status , NT_STATUS_RETRY ) ) {
/*
* Normal collision , try next
*/
DBG_DEBUG ( " Found record for id % " PRIu32 " \n " ,
state . id ) ;
continue ;
2023-01-26 10:46:31 +03:00
}
2023-01-26 11:08:27 +03:00
DBG_WARNING ( " smbXsrv_open_global_allocate_fn() failed: %s \n " ,
nt_errstr ( state . status ) ) ;
return state . status ;
2023-01-26 10:46:31 +03:00
}
/* should not be reached */
return NT_STATUS_INTERNAL_ERROR ;
}
2012-02-07 02:06:41 +04:00
static int smbXsrv_open_destructor ( struct smbXsrv_open * op )
{
NTSTATUS status ;
status = smbXsrv_open_close ( op , 0 ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " smbXsrv_open_destructor: "
" smbXsrv_open_close() failed - %s \n " ,
nt_errstr ( status ) ) ) ;
}
TALLOC_FREE ( op - > global ) ;
return 0 ;
}
NTSTATUS smbXsrv_open_create ( struct smbXsrv_connection * conn ,
struct auth_session_info * session_info ,
NTTIME now ,
struct smbXsrv_open * * _open )
{
2014-06-12 22:22:54 +04:00
struct smbXsrv_open_table * table = conn - > client - > open_table ;
2012-02-07 02:06:41 +04:00
struct smbXsrv_open * op = NULL ;
struct smbXsrv_open_global0 * global = NULL ;
NTSTATUS status ;
struct dom_sid * current_sid = NULL ;
struct security_token * current_token = NULL ;
2023-01-04 14:18:44 +03:00
int local_id ;
2012-02-07 02:06:41 +04:00
if ( session_info = = NULL ) {
return NT_STATUS_INVALID_HANDLE ;
}
current_token = session_info - > security_token ;
2024-02-09 14:37:53 +03:00
if ( ( current_token = = NULL ) | |
( current_token - > num_sids < = PRIMARY_USER_SID_INDEX ) ) {
2012-02-07 02:06:41 +04:00
return NT_STATUS_INVALID_HANDLE ;
}
2024-02-09 14:37:53 +03:00
current_sid = & current_token - > sids [ PRIMARY_USER_SID_INDEX ] ;
2012-02-07 02:06:41 +04:00
if ( table - > local . num_opens > = table - > local . max_opens ) {
return NT_STATUS_INSUFFICIENT_RESOURCES ;
}
op = talloc_zero ( table , struct smbXsrv_open ) ;
if ( op = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
op - > table = table ;
op - > status = NT_STATUS_OK ; /* TODO: start with INTERNAL_ERROR */
op - > idle_time = now ;
2023-01-04 16:30:28 +03:00
global = talloc_zero ( op , struct smbXsrv_open_global0 ) ;
if ( global = = NULL ) {
TALLOC_FREE ( op ) ;
return NT_STATUS_NO_MEMORY ;
}
op - > global = global ;
/*
* We mark every slot as invalid using 0xFF .
* Valid values are masked with 0xF .
*/
memset ( global - > lock_sequence_array , 0xFF ,
sizeof ( global - > lock_sequence_array ) ) ;
2023-01-04 14:18:44 +03:00
local_id = idr_get_new_random (
table - > local . idr ,
op ,
table - > local . lowest_id ,
table - > local . highest_id ) ;
if ( local_id = = - 1 ) {
2012-02-07 02:06:41 +04:00
TALLOC_FREE ( op ) ;
2023-01-04 14:18:44 +03:00
return NT_STATUS_INSUFFICIENT_RESOURCES ;
2012-02-07 02:06:41 +04:00
}
2023-01-04 14:18:44 +03:00
op - > local_id = local_id ;
2012-02-07 02:06:41 +04:00
global - > open_volatile_id = op - > local_id ;
2018-03-22 12:54:41 +03:00
global - > server_id = messaging_server_id ( conn - > client - > msg_ctx ) ;
2012-02-07 02:06:41 +04:00
global - > open_time = now ;
global - > open_owner = * current_sid ;
2012-06-18 14:46:15 +04:00
if ( conn - > protocol > = PROTOCOL_SMB2_10 ) {
global - > client_guid = conn - > smb2 . client . guid ;
}
2012-02-07 02:06:41 +04:00
2023-01-06 19:12:23 +03:00
status = smbXsrv_open_global_allocate ( table - > global . db_ctx ,
global ) ;
2012-02-07 02:06:41 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2023-01-06 19:12:23 +03:00
int ret = idr_remove ( table - > local . idr , local_id ) ;
SMB_ASSERT ( ret = = 0 ) ;
DBG_WARNING ( " smbXsrv_open_global_allocate() failed: %s \n " ,
nt_errstr ( status ) ) ;
2012-02-07 02:06:41 +04:00
TALLOC_FREE ( op ) ;
return status ;
}
2023-01-06 19:12:23 +03:00
table - > local . num_opens + = 1 ;
talloc_set_destructor ( op , smbXsrv_open_destructor ) ;
smbd: Avoid duplicate debug header lines
This is what gets created in log.smbd: DEBUGLVL generates an empty
header line, CHECK_DEBUGLVL avoids this.
[2014/01/10 12:58:24.971658, 10, pid=2329, effective(1001, 1001), real(0, 0)] ../source3/smbd/smbXsrv_open.c:696(smbXsrv_open_global_store)
[2014/01/10 12:58:24.971690, 10, pid=2329, effective(1001, 1001), real(0, 0)] ../source3/smbd/smbXsrv_open.c:698(smbXsrv_open_global_store)
Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
Autobuild-User(master): Jeremy Allison <jra@samba.org>
Autobuild-Date(master): Wed Jan 15 04:02:58 CET 2014 on sn-devel-104
2014-01-10 16:02:59 +04:00
if ( CHECK_DEBUGLVL ( 10 ) ) {
2019-09-16 15:26:05 +03:00
struct smbXsrv_openB open_blob = {
. version = SMBXSRV_VERSION_0 ,
. info . info0 = op ,
} ;
2012-02-07 02:06:41 +04:00
DEBUG ( 10 , ( " smbXsrv_open_create: global_id (0x%08x) stored \n " ,
op - > global - > open_global_id ) ) ;
NDR_PRINT_DEBUG ( smbXsrv_openB , & open_blob ) ;
}
* _open = op ;
return NT_STATUS_OK ;
}
2016-02-24 02:23:15 +03:00
static NTSTATUS smbXsrv_open_set_replay_cache ( struct smbXsrv_open * op )
{
struct GUID * create_guid ;
struct GUID_txt_buf buf ;
char * guid_string ;
struct db_context * db = op - > table - > local . replay_cache_db_ctx ;
2021-03-12 17:10:46 +03:00
struct smbXsrv_open_replay_cache rc = {
. idle_time = op - > idle_time ,
. local_id = op - > local_id ,
} ;
Fix gcc11 compiler issue "-Werror=maybe-uninitialized"
BUG: https://bugzilla.samba.org/show_bug.cgi?id=14699
../../source4/dsdb/common/util_links.c: In function ‘ndr_guid_compare’:
../../source4/dsdb/common/util_links.c:38:29: error: ‘v1_data’ may be used uninitialized [-Werror=maybe-uninitialized]
38 | struct ldb_val v1 = data_blob_const(v1_data, sizeof(v1_data));
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from ../../source4/../lib/util/samba_util.h:48,
from ../../source4/include/includes.h:62,
from ../../source4/dsdb/common/util_links.c:22:
../../lib/util/data_blob.h:116:20: note: by argument 1 of type ‘const void *’ to ‘data_blob_const’ declared here
116 | _PUBLIC_ DATA_BLOB data_blob_const(const void *p, size_t length);
| ^~~~~~~~~~~~~~~
../../source4/dsdb/common/util_links.c:37:17: note: ‘v1_data’ declared here
37 | uint8_t v1_data[16];
| ^~~~~~~
cc1: all warnings being treated as errors
[1729/3991] Compiling source3/smbd/smbXsrv_open.c
../../libcli/auth/smbencrypt.c: In function ‘decode_wkssvc_join_password_buffer’:
../../libcli/auth/smbencrypt.c:1045:32: error: ‘_confounder’ may be used uninitialized [-Werror=maybe-uninitialized]
1045 | DATA_BLOB confounder = data_blob_const(_confounder, 8);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from ../../source4/../lib/util/samba_util.h:48,
from ../../source4/include/includes.h:62,
from ../../libcli/auth/smbencrypt.c:24:
../../lib/util/data_blob.h:116:20: note: by argument 1 of type ‘const void *’ to ‘data_blob_const’ declared here
116 | _PUBLIC_ DATA_BLOB data_blob_const(const void *p, size_t length);
| ^~~~~~~~~~~~~~~
../../libcli/auth/smbencrypt.c:1044:17: note: ‘_confounder’ declared here
1044 | uint8_t _confounder[8];
| ^~~~~~~~~~~
cc1: all warnings being treated as errors
[2624/3991] Compiling source4/torture/rpc/samr.c
../../source3/rpc_client/cli_samr.c: In function ‘dcerpc_samr_chgpasswd_user2’:
../../source3/rpc_client/cli_samr.c:158:33: error: ‘old_nt_hash’ may be used uninitialized [-Werror=maybe-uninitialized]
158 | DATA_BLOB session_key = data_blob_const(old_nt_hash, 16);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from ../../source3/../lib/util/samba_util.h:48,
from ../../source3/include/includes.h:256,
from ../../source3/rpc_client/cli_samr.c:24:
../../lib/util/data_blob.h:116:20: note: by argument 1 of type ‘const void *’ to ‘data_blob_const’ declared here
116 | _PUBLIC_ DATA_BLOB data_blob_const(const void *p, size_t length);
| ^~~~~~~~~~~~~~~
../../source3/rpc_client/cli_samr.c:152:17: note: ‘old_nt_hash’ declared here
152 | uint8_t old_nt_hash[16];
| ^~~~~~~~~~~
../../source3/rpc_client/cli_samr.c: In function ‘dcerpc_samr_chgpasswd_user3’:
../../source3/rpc_client/cli_samr.c:365:33: error: ‘old_nt_hash’ may be used uninitialized [-Werror=maybe-uninitialized]
365 | DATA_BLOB session_key = data_blob_const(old_nt_hash, 16);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from ../../source3/../lib/util/samba_util.h:48,
from ../../source3/include/includes.h:256,
from ../../source3/rpc_client/cli_samr.c:24:
../../lib/util/data_blob.h:116:20: note: by argument 1 of type ‘const void *’ to ‘data_blob_const’ declared here
116 | _PUBLIC_ DATA_BLOB data_blob_const(const void *p, size_t length);
| ^~~~~~~~~~~~~~~
../../source3/rpc_client/cli_samr.c:358:17: note: ‘old_nt_hash’ declared here
358 | uint8_t old_nt_hash[16];
| ^~~~~~~~~~~
cc1: all warnings being treated as errors
[3399/3991] Compiling source3/rpcclient/cmd_spotlight.c
../../source3/smbd/smbXsrv_open.c: In function ‘smbXsrv_open_set_replay_cache’:
../../source3/smbd/smbXsrv_open.c:936:26: error: ‘data’ may be used uninitialized [-Werror=maybe-uninitialized]
936 | DATA_BLOB blob = data_blob_const(data, ARRAY_SIZE(data));
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from ../../source3/../lib/util/samba_util.h:48,
from ../../source3/include/includes.h:256,
from ../../source3/smbd/smbXsrv_open.c:21:
../../lib/util/data_blob.h:116:20: note: by argument 1 of type ‘const void *’ to ‘data_blob_const’ declared here
116 | _PUBLIC_ DATA_BLOB data_blob_const(const void *p, size_t length);
| ^~~~~~~~~~~~~~~
../../source3/smbd/smbXsrv_open.c:935:17: note: ‘data’ declared here
935 | uint8_t data[SMBXSRV_OPEN_REPLAY_CACHE_FIXED_SIZE];
| ^~~~
cc1: all warnings being treated as errors
../../source3/rpcclient/cmd_spotlight.c: In function ‘cmd_mdssvc_fetch_properties’:
../../source3/rpcclient/cmd_spotlight.c:60:18: error: ‘share_path’ may be used uninitialized [-Werror=maybe-uninitialized]
60 | status = dcerpc_mdssvc_open(b, mem_ctx,
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
61 | &device_id,
| ~~~~~~~~~~~
62 | &unkn1,
| ~~~~~~~
63 | &unkn2,
| ~~~~~~~
64 | argv[2],
| ~~~~~~~~
65 | argv[1],
| ~~~~~~~~
66 | share_path,
| ~~~~~~~~~~~
67 | &share_handle);
| ~~~~~~~~~~~~~~
In file included from ../../source3/rpcclient/cmd_spotlight.c:24:
source3/../librpc/gen_ndr/ndr_mdssvc_c.h:26:10: note: by argument 8 of type ‘const char *’ to ‘dcerpc_mdssvc_open’ declared here
26 | NTSTATUS dcerpc_mdssvc_open(struct dcerpc_binding_handle *h,
| ^~~~~~~~~~~~~~~~~~
../../source3/rpcclient/cmd_spotlight.c:40:14: note: ‘share_path’ declared here
40 | char share_path[1025];
| ^~~~~~~~~~
cc1: all warnings being treated as errors
../../source4/torture/rpc/samr.c: In function ‘test_ChangePasswordUser2’:
../../source4/torture/rpc/samr.c:2266:19: error: ‘old_nt_hash’ may be used uninitialized [-Werror=maybe-uninitialized]
2266 | = data_blob_const(old_nt_hash, sizeof(old_nt_hash));
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from ../../source4/../lib/util/samba_util.h:48,
from ../../source4/include/includes.h:62,
from ../../source4/torture/rpc/samr.c:24:
../../lib/util/data_blob.h:116:20: note: by argument 1 of type ‘const void *’ to ‘data_blob_const’ declared here
116 | _PUBLIC_ DATA_BLOB data_blob_const(const void *p, size_t length);
| ^~~~~~~~~~~~~~~
../../source4/torture/rpc/samr.c:2263:17: note: ‘old_nt_hash’ declared here
2263 | uint8_t old_nt_hash[16], new_nt_hash[16];
| ^~~~~~~~~~~
../../source4/torture/rpc/samr.c: In function ‘test_ChangePasswordUser2_ntstatus’:
../../source4/torture/rpc/samr.c:2371:19: error: ‘old_nt_hash’ may be used uninitialized [-Werror=maybe-uninitialized]
2371 | = data_blob_const(old_nt_hash, sizeof(old_nt_hash));
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from ../../source4/../lib/util/samba_util.h:48,
from ../../source4/include/includes.h:62,
from ../../source4/torture/rpc/samr.c:24:
../../lib/util/data_blob.h:116:20: note: by argument 1 of type ‘const void *’ to ‘data_blob_const’ declared here
116 | _PUBLIC_ DATA_BLOB data_blob_const(const void *p, size_t length);
| ^~~~~~~~~~~~~~~
../../source4/torture/rpc/samr.c:2368:17: note: ‘old_nt_hash’ declared here
2368 | uint8_t old_nt_hash[16], new_nt_hash[16];
| ^~~~~~~~~~~
../../source4/torture/rpc/samr.c: In function ‘test_ChangePasswordUser3’:
../../source4/torture/rpc/samr.c:2478:38: error: ‘old_nt_hash’ may be used uninitialized [-Werror=maybe-uninitialized]
2478 | DATA_BLOB old_nt_hash_blob = data_blob_const(old_nt_hash, 16);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from ../../source4/../lib/util/samba_util.h:48,
from ../../source4/include/includes.h:62,
from ../../source4/torture/rpc/samr.c:24:
../../lib/util/data_blob.h:116:20: note: by argument 1 of type ‘const void *’ to ‘data_blob_const’ declared here
116 | _PUBLIC_ DATA_BLOB data_blob_const(const void *p, size_t length);
| ^~~~~~~~~~~~~~~
../../source4/torture/rpc/samr.c:2473:17: note: ‘old_nt_hash’ declared here
2473 | uint8_t old_nt_hash[16], new_nt_hash[16];
| ^~~~~~~~~~~
../../source4/torture/rpc/samr.c: In function ‘test_ChangePasswordRandomBytes’:
../../source4/torture/rpc/samr.c:2794:19: error: ‘old_nt_hash’ may be used uninitialized [-Werror=maybe-uninitialized]
2794 | = data_blob_const(old_nt_hash,
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
2795 | sizeof(old_nt_hash));
| ~~~~~~~~~~~~~~~~~~~~
In file included from ../../source4/../lib/util/samba_util.h:48,
from ../../source4/include/includes.h:62,
from ../../source4/torture/rpc/samr.c:24:
../../lib/util/data_blob.h:116:20: note: by argument 1 of type ‘const void *’ to ‘data_blob_const’ declared here
116 | _PUBLIC_ DATA_BLOB data_blob_const(const void *p, size_t length);
| ^~~~~~~~~~~~~~~
../../source4/torture/rpc/samr.c:2792:17: note: ‘old_nt_hash’ declared here
2792 | uint8_t old_nt_hash[16], new_nt_hash[16];
| ^~~~~~~~~~~
cc1: all warnings being treated as errors
Guenther
Signed-off-by: Guenther Deschner <gd@samba.org>
Reviewed-by: Andreas Schneider <asn@samba.org>
2021-05-03 22:27:43 +03:00
uint8_t data [ SMBXSRV_OPEN_REPLAY_CACHE_FIXED_SIZE ] = { 0 } ;
2023-01-04 14:31:26 +03:00
DATA_BLOB blob = { . data = data , . length = sizeof ( data ) , } ;
2021-03-12 17:10:46 +03:00
enum ndr_err_code ndr_err ;
2016-02-24 02:23:15 +03:00
NTSTATUS status ;
2021-03-12 17:10:46 +03:00
TDB_DATA val ;
2016-02-24 02:23:15 +03:00
if ( ! ( op - > flags & SMBXSRV_OPEN_NEED_REPLAY_CACHE ) ) {
return NT_STATUS_OK ;
}
if ( op - > flags & SMBXSRV_OPEN_HAVE_REPLAY_CACHE ) {
return NT_STATUS_OK ;
}
create_guid = & op - > global - > create_guid ;
guid_string = GUID_buf_string ( create_guid , & buf ) ;
2021-03-12 17:10:46 +03:00
ndr_err = ndr_push_struct_into_fixed_blob ( & blob , & rc ,
( ndr_push_flags_fn_t ) ndr_push_smbXsrv_open_replay_cache ) ;
if ( ! NDR_ERR_CODE_IS_SUCCESS ( ndr_err ) ) {
status = ndr_map_error2ntstatus ( ndr_err ) ;
return status ;
2016-02-24 02:23:15 +03:00
}
2021-03-12 17:10:46 +03:00
val = make_tdb_data ( blob . data , blob . length ) ;
2016-02-24 02:23:15 +03:00
2023-01-04 14:34:43 +03:00
status = dbwrap_store_bystring ( db , guid_string , val , TDB_REPLACE ) ;
2016-02-24 02:23:15 +03:00
if ( NT_STATUS_IS_OK ( status ) ) {
op - > flags | = SMBXSRV_OPEN_HAVE_REPLAY_CACHE ;
op - > flags & = ~ SMBXSRV_OPEN_NEED_REPLAY_CACHE ;
}
return status ;
}
2021-03-12 17:10:46 +03:00
NTSTATUS smbXsrv_open_purge_replay_cache ( struct smbXsrv_client * client ,
const struct GUID * create_guid )
{
struct GUID_txt_buf buf ;
2024-02-09 15:02:25 +03:00
NTSTATUS status ;
2021-03-12 17:10:46 +03:00
if ( client - > open_table = = NULL ) {
return NT_STATUS_OK ;
}
2024-02-09 15:02:25 +03:00
status = dbwrap_purge_bystring (
client - > open_table - > local . replay_cache_db_ctx ,
GUID_buf_string ( create_guid , & buf ) ) ;
return status ;
2021-03-12 17:10:46 +03:00
}
2016-02-24 02:23:15 +03:00
static NTSTATUS smbXsrv_open_clear_replay_cache ( struct smbXsrv_open * op )
{
struct GUID * create_guid ;
struct GUID_txt_buf buf ;
struct db_context * db ;
NTSTATUS status ;
if ( op - > table = = NULL ) {
return NT_STATUS_OK ;
}
db = op - > table - > local . replay_cache_db_ctx ;
if ( ! ( op - > flags & SMBXSRV_OPEN_HAVE_REPLAY_CACHE ) ) {
return NT_STATUS_OK ;
}
create_guid = & op - > global - > create_guid ;
if ( GUID_all_zero ( create_guid ) ) {
return NT_STATUS_OK ;
}
2024-02-09 15:05:28 +03:00
status = dbwrap_purge_bystring ( db , GUID_buf_string ( create_guid , & buf ) ) ;
2016-02-24 02:23:15 +03:00
if ( NT_STATUS_IS_OK ( status ) ) {
op - > flags & = ~ SMBXSRV_OPEN_HAVE_REPLAY_CACHE ;
}
return status ;
}
2023-01-08 23:04:25 +03:00
struct smbXsrv_open_update_state {
struct smbXsrv_open_global0 * global ;
NTSTATUS status ;
} ;
static void smbXsrv_open_update_fn (
struct db_record * rec , TDB_DATA oldval , void * private_data )
{
struct smbXsrv_open_update_state * state = private_data ;
TDB_DATA key = dbwrap_record_get_key ( rec ) ;
state - > status = smbXsrv_open_global_store (
rec , key , oldval , state - > global ) ;
}
2012-02-07 02:06:41 +04:00
NTSTATUS smbXsrv_open_update ( struct smbXsrv_open * op )
{
2023-01-08 23:04:25 +03:00
struct smbXsrv_open_update_state state = { . global = op - > global , } ;
2012-02-07 02:06:41 +04:00
struct smbXsrv_open_table * table = op - > table ;
2023-01-08 23:04:25 +03:00
struct smbXsrv_open_global_key_buf key_buf ;
TDB_DATA key = smbXsrv_open_global_id_to_key (
op - > global - > open_global_id , & key_buf ) ;
2012-02-07 02:06:41 +04:00
NTSTATUS status ;
2023-01-08 23:04:25 +03:00
status = dbwrap_do_locked (
table - > global . db_ctx , key , smbXsrv_open_update_fn , & state ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DBG_WARNING ( " global_id (0x%08x) dbwrap_do_locked failed: %s \n " ,
op - > global - > open_global_id ,
nt_errstr ( status ) ) ;
2012-02-07 02:06:41 +04:00
return NT_STATUS_INTERNAL_DB_ERROR ;
}
2023-01-08 23:04:25 +03:00
if ( ! NT_STATUS_IS_OK ( state . status ) ) {
DBG_WARNING ( " global_id (0x%08x) smbXsrv_open_global_store "
" failed: %s \n " ,
op - > global - > open_global_id ,
nt_errstr ( state . status ) ) ;
return state . status ;
2012-02-07 02:06:41 +04:00
}
2016-02-24 02:23:15 +03:00
status = smbXsrv_open_set_replay_cache ( op ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DBG_ERR ( " smbXsrv_open_set_replay_cache failed: %s \n " ,
nt_errstr ( status ) ) ;
return status ;
}
smbd: Avoid duplicate debug header lines
This is what gets created in log.smbd: DEBUGLVL generates an empty
header line, CHECK_DEBUGLVL avoids this.
[2014/01/10 12:58:24.971658, 10, pid=2329, effective(1001, 1001), real(0, 0)] ../source3/smbd/smbXsrv_open.c:696(smbXsrv_open_global_store)
[2014/01/10 12:58:24.971690, 10, pid=2329, effective(1001, 1001), real(0, 0)] ../source3/smbd/smbXsrv_open.c:698(smbXsrv_open_global_store)
Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
Autobuild-User(master): Jeremy Allison <jra@samba.org>
Autobuild-Date(master): Wed Jan 15 04:02:58 CET 2014 on sn-devel-104
2014-01-10 16:02:59 +04:00
if ( CHECK_DEBUGLVL ( 10 ) ) {
2019-09-16 15:26:05 +03:00
struct smbXsrv_openB open_blob = {
. version = SMBXSRV_VERSION_0 ,
. info . info0 = op ,
} ;
2012-02-07 02:06:41 +04:00
DEBUG ( 10 , ( " smbXsrv_open_update: global_id (0x%08x) stored \n " ,
op - > global - > open_global_id ) ) ;
NDR_PRINT_DEBUG ( smbXsrv_openB , & open_blob ) ;
}
return NT_STATUS_OK ;
}
2023-01-10 13:59:07 +03:00
struct smbXsrv_open_close_state {
struct smbXsrv_open * op ;
NTSTATUS status ;
} ;
static void smbXsrv_open_close_fn (
struct db_record * rec , TDB_DATA oldval , void * private_data )
{
struct smbXsrv_open_close_state * state = private_data ;
struct smbXsrv_open_global0 * global = state - > op - > global ;
TDB_DATA key = dbwrap_record_get_key ( rec ) ;
if ( global - > durable ) {
/*
* Durable open - - we need to update the global part
* instead of deleting it
*/
state - > status = smbXsrv_open_global_store (
rec , key , oldval , global ) ;
if ( ! NT_STATUS_IS_OK ( state - > status ) ) {
DBG_WARNING ( " failed to store global key '%s': %s \n " ,
tdb_data_dbg ( key ) ,
nt_errstr ( state - > status ) ) ;
return ;
}
if ( CHECK_DEBUGLVL ( 10 ) ) {
struct smbXsrv_openB open_blob = {
. version = SMBXSRV_VERSION_0 ,
. info . info0 = state - > op ,
} ;
DBG_DEBUG ( " (0x%08x) stored disconnect \n " ,
global - > open_global_id ) ;
NDR_PRINT_DEBUG ( smbXsrv_openB , & open_blob ) ;
}
return ;
}
state - > status = dbwrap_record_delete ( rec ) ;
if ( ! NT_STATUS_IS_OK ( state - > status ) ) {
DBG_WARNING ( " failed to delete global key '%s': %s \n " ,
tdb_data_dbg ( key ) ,
nt_errstr ( state - > status ) ) ;
}
}
2012-02-07 02:06:41 +04:00
NTSTATUS smbXsrv_open_close ( struct smbXsrv_open * op , NTTIME now )
{
2023-01-10 13:59:07 +03:00
struct smbXsrv_open_close_state state = { . op = op , } ;
struct smbXsrv_open_global0 * global = op - > global ;
2012-02-07 02:06:41 +04:00
struct smbXsrv_open_table * table ;
NTSTATUS status ;
NTSTATUS error = NT_STATUS_OK ;
2023-01-10 13:59:07 +03:00
struct smbXsrv_open_global_key_buf key_buf ;
TDB_DATA key = smbXsrv_open_global_id_to_key (
global - > open_global_id , & key_buf ) ;
2023-01-04 14:18:44 +03:00
int ret ;
2012-02-07 02:06:41 +04:00
2016-02-24 02:23:15 +03:00
error = smbXsrv_open_clear_replay_cache ( op ) ;
if ( ! NT_STATUS_IS_OK ( error ) ) {
DBG_ERR ( " smbXsrv_open_clear_replay_cache failed: %s \n " ,
nt_errstr ( error ) ) ;
}
2012-02-07 02:06:41 +04:00
if ( op - > table = = NULL ) {
2016-02-24 02:23:15 +03:00
return error ;
2012-02-07 02:06:41 +04:00
}
table = op - > table ;
op - > table = NULL ;
op - > status = NT_STATUS_FILE_CLOSED ;
2023-01-10 13:59:07 +03:00
global - > disconnect_time = now ;
server_id_set_disconnected ( & global - > server_id ) ;
2012-06-18 14:46:15 +04:00
2023-01-10 13:59:07 +03:00
status = dbwrap_do_locked (
table - > global . db_ctx , key , smbXsrv_open_close_fn , & state ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DBG_WARNING ( " dbwrap_do_locked() for %s failed: %s \n " ,
tdb_data_dbg ( key ) ,
nt_errstr ( status ) ) ;
error = status ;
} else if ( ! NT_STATUS_IS_OK ( state . status ) ) {
DBG_WARNING ( " smbXsrv_open_close_fn() for %s failed: %s \n " ,
tdb_data_dbg ( key ) ,
nt_errstr ( state . status ) ) ;
error = state . status ;
2012-02-07 02:06:41 +04:00
}
2023-01-04 14:18:44 +03:00
ret = idr_remove ( table - > local . idr , op - > local_id ) ;
SMB_ASSERT ( ret = = 0 ) ;
2012-02-07 02:06:41 +04:00
2023-01-04 13:29:51 +03:00
table - > local . num_opens - = 1 ;
2012-02-07 02:06:41 +04:00
if ( op - > compat ) {
2013-02-19 02:21:24 +04:00
op - > compat - > op = NULL ;
2012-02-07 02:06:41 +04:00
file_free ( NULL , op - > compat ) ;
op - > compat = NULL ;
}
return error ;
}
NTSTATUS smb1srv_open_table_init ( struct smbXsrv_connection * conn )
{
uint32_t max_opens ;
/*
* Allow a range from 1. .65534 .
*
* With real_max_open_files possible ids ,
* truncated to the SMB1 limit of 16 - bit .
*
* 0 and 0xFFFF are no valid ids .
*/
2014-06-12 10:57:22 +04:00
max_opens = conn - > client - > sconn - > real_max_open_files ;
2012-02-07 02:06:41 +04:00
max_opens = MIN ( max_opens , UINT16_MAX - 1 ) ;
return smbXsrv_open_table_init ( conn , 1 , UINT16_MAX - 1 , max_opens ) ;
}
NTSTATUS smb1srv_open_lookup ( struct smbXsrv_connection * conn ,
uint16_t fnum , NTTIME now ,
struct smbXsrv_open * * _open )
{
2014-06-12 22:22:54 +04:00
struct smbXsrv_open_table * table = conn - > client - > open_table ;
2012-02-07 02:06:41 +04:00
uint32_t local_id = fnum ;
uint32_t global_id = 0 ;
return smbXsrv_open_local_lookup ( table , local_id , global_id , now , _open ) ;
}
NTSTATUS smb2srv_open_table_init ( struct smbXsrv_connection * conn )
{
uint32_t max_opens ;
2023-01-04 14:18:44 +03:00
uint32_t highest_id ;
2012-02-07 02:06:41 +04:00
/*
* Allow a range from 1. .4294967294 .
*
* With real_max_open_files possible ids ,
* truncated to 16 - bit ( the same as SMB1 for now ) .
*
* 0 and 0xFFFFFFFF are no valid ids .
*
* The usage of conn - > sconn - > real_max_open_files
* is the reason that we use one open table per
* transport connection ( as we still have a 1 : 1 mapping
* between process and transport connection ) .
*/
2014-06-12 10:57:22 +04:00
max_opens = conn - > client - > sconn - > real_max_open_files ;
2012-02-07 02:06:41 +04:00
max_opens = MIN ( max_opens , UINT16_MAX - 1 ) ;
2023-01-04 14:18:44 +03:00
/*
* idtree uses " int " for local IDs . Limit the maximum ID to
* what " int " can hold .
*/
highest_id = UINT32_MAX - 1 ;
highest_id = MIN ( highest_id , INT_MAX ) ;
return smbXsrv_open_table_init ( conn , 1 , highest_id , max_opens ) ;
2012-02-07 02:06:41 +04:00
}
NTSTATUS smb2srv_open_lookup ( struct smbXsrv_connection * conn ,
uint64_t persistent_id ,
uint64_t volatile_id ,
NTTIME now ,
struct smbXsrv_open * * _open )
{
2014-06-12 22:22:54 +04:00
struct smbXsrv_open_table * table = conn - > client - > open_table ;
2012-02-07 02:06:41 +04:00
uint32_t local_id = volatile_id & UINT32_MAX ;
uint64_t local_zeros = volatile_id & 0xFFFFFFFF00000000LLU ;
uint32_t global_id = persistent_id & UINT32_MAX ;
uint64_t global_zeros = persistent_id & 0xFFFFFFFF00000000LLU ;
2016-02-24 02:23:15 +03:00
NTSTATUS status ;
2012-02-07 02:06:41 +04:00
if ( local_zeros ! = 0 ) {
return NT_STATUS_FILE_CLOSED ;
}
if ( global_zeros ! = 0 ) {
return NT_STATUS_FILE_CLOSED ;
}
if ( global_id = = 0 ) {
return NT_STATUS_FILE_CLOSED ;
}
2016-02-24 02:23:15 +03:00
status = smbXsrv_open_local_lookup ( table , local_id , global_id , now ,
_open ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
/*
* Clear the replay cache for this create_guid if it exists :
* This is based on the assumption that this lookup will be
* triggered by a client request using the file - id for lookup .
* Hence the client has proven that it has in fact seen the
* reply to its initial create call . So subsequent create replays
* should be treated as invalid . Hence the index for create_guid
* lookup needs to be removed .
*/
status = smbXsrv_open_clear_replay_cache ( * _open ) ;
return status ;
2012-02-07 02:06:41 +04:00
}
2012-06-18 14:46:15 +04:00
2021-03-12 17:10:46 +03:00
/*
* This checks or marks the replay cache , we have the following
* cases :
*
* 1. There is no record in the cache
* = > we add the passes caller_req_guid as holder_req_guid
* together with local_id as 0.
* = > We return STATUS_FWP_RESERVED in order to indicate
* that the caller holds the current reservation
*
* 2. There is a record in the cache and holder_req_guid
* is already the same as caller_req_guid and local_id is 0
* = > We return STATUS_FWP_RESERVED in order to indicate
* that the caller holds the current reservation
*
* 3. There is a record in the cache with a holder_req_guid
* other than caller_req_guid ( and local_id is 0 ) :
* = > We return NT_STATUS_FILE_NOT_AVAILABLE to indicate
* the original request is still pending
*
* 4. There is a record in the cache with a zero holder_req_guid
* and a valid local_id :
* = > We lookup the existing open by local_id
* = > We return NT_STATUS_OK together with the smbXsrv_open
*
*
* With NT_STATUS_OK the caller can continue the replay processing .
*
* With STATUS_FWP_RESERVED the caller should continue the normal
* open processing :
* - On success :
* - smbXsrv_open_update ( ) / smbXsrv_open_set_replay_cache ( )
* will convert the record to a zero holder_req_guid
* with a valid local_id .
* - On failure :
* - smbXsrv_open_purge_replay_cache ( ) should cleanup
* the reservation .
*
* All other values should be returned to the client ,
* while NT_STATUS_FILE_NOT_AVAILABLE will trigger the
* retry loop on the client .
*/
2016-02-27 05:23:27 +03:00
NTSTATUS smb2srv_open_lookup_replay_cache ( struct smbXsrv_connection * conn ,
2021-03-12 17:10:46 +03:00
struct GUID caller_req_guid ,
struct GUID create_guid ,
const char * name ,
NTTIME now ,
2016-02-27 05:23:27 +03:00
struct smbXsrv_open * * _open )
{
2021-03-12 17:10:46 +03:00
TALLOC_CTX * frame = talloc_stackframe ( ) ;
2016-02-27 05:23:27 +03:00
NTSTATUS status ;
struct smbXsrv_open_table * table = conn - > client - > open_table ;
struct db_context * db = table - > local . replay_cache_db_ctx ;
2021-03-12 17:10:46 +03:00
struct GUID_txt_buf tmp_guid_buf ;
2023-01-11 13:44:29 +03:00
struct GUID_txt_buf _create_guid_buf ;
const char * create_guid_str = GUID_buf_string ( & create_guid , & _create_guid_buf ) ;
TDB_DATA create_guid_key = string_term_tdb_data ( create_guid_str ) ;
2021-03-12 17:10:46 +03:00
struct db_record * db_rec = NULL ;
struct smbXsrv_open * op = NULL ;
struct smbXsrv_open_replay_cache rc = {
. holder_req_guid = caller_req_guid ,
. idle_time = now ,
. local_id = 0 ,
} ;
enum ndr_err_code ndr_err ;
DATA_BLOB blob = data_blob_null ;
TDB_DATA val ;
2016-02-27 05:23:27 +03:00
2021-03-12 17:10:46 +03:00
* _open = NULL ;
db_rec = dbwrap_fetch_locked ( db , frame , create_guid_key ) ;
if ( db_rec = = NULL ) {
TALLOC_FREE ( frame ) ;
return NT_STATUS_INTERNAL_DB_ERROR ;
2016-02-27 05:23:27 +03:00
}
2021-03-12 17:10:46 +03:00
val = dbwrap_record_get_value ( db_rec ) ;
if ( val . dsize = = 0 ) {
uint8_t data [ SMBXSRV_OPEN_REPLAY_CACHE_FIXED_SIZE ] ;
blob = data_blob_const ( data , ARRAY_SIZE ( data ) ) ;
ndr_err = ndr_push_struct_into_fixed_blob ( & blob , & rc ,
( ndr_push_flags_fn_t ) ndr_push_smbXsrv_open_replay_cache ) ;
if ( ! NDR_ERR_CODE_IS_SUCCESS ( ndr_err ) ) {
status = ndr_map_error2ntstatus ( ndr_err ) ;
TALLOC_FREE ( frame ) ;
return status ;
}
val = make_tdb_data ( blob . data , blob . length ) ;
status = dbwrap_record_store ( db_rec , val , TDB_REPLACE ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
TALLOC_FREE ( frame ) ;
return status ;
}
/*
* We ' re the new holder
*/
* _open = NULL ;
TALLOC_FREE ( frame ) ;
return NT_STATUS_FWP_RESERVED ;
2016-02-27 05:23:27 +03:00
}
2021-03-12 17:10:46 +03:00
if ( val . dsize ! = SMBXSRV_OPEN_REPLAY_CACHE_FIXED_SIZE ) {
TALLOC_FREE ( frame ) ;
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
2016-02-27 05:23:27 +03:00
}
2021-03-12 17:10:46 +03:00
blob = data_blob_const ( val . dptr , val . dsize ) ;
ndr_err = ndr_pull_struct_blob_all_noalloc ( & blob , & rc ,
( ndr_pull_flags_fn_t ) ndr_pull_smbXsrv_open_replay_cache ) ;
if ( ! NDR_ERR_CODE_IS_SUCCESS ( ndr_err ) ) {
status = ndr_map_error2ntstatus ( ndr_err ) ;
TALLOC_FREE ( frame ) ;
2016-02-27 05:23:27 +03:00
return status ;
}
2021-03-12 17:10:46 +03:00
if ( rc . local_id ! = 0 ) {
if ( GUID_equal ( & rc . holder_req_guid , & caller_req_guid ) ) {
/*
* This should not happen
*/
status = NT_STATUS_INTERNAL_ERROR ;
DBG_ERR ( " caller %s already holds local_id %u for create %s [%s] - %s \n " ,
GUID_buf_string ( & caller_req_guid , & tmp_guid_buf ) ,
( unsigned ) rc . local_id ,
create_guid_str ,
name ,
nt_errstr ( status ) ) ;
TALLOC_FREE ( frame ) ;
return status ;
}
2016-02-27 05:23:27 +03:00
2021-03-12 17:10:46 +03:00
status = smbXsrv_open_local_lookup ( table ,
rc . local_id ,
0 , /* global_id */
now ,
& op ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DBG_ERR ( " holder %s stale for local_id %u for create %s [%s] - %s \n " ,
GUID_buf_string ( & rc . holder_req_guid , & tmp_guid_buf ) ,
( unsigned ) rc . local_id ,
create_guid_str ,
name ,
nt_errstr ( status ) ) ;
TALLOC_FREE ( frame ) ;
return status ;
}
/*
* We found an open the caller can reuse .
*/
SMB_ASSERT ( op ! = NULL ) ;
* _open = op ;
TALLOC_FREE ( frame ) ;
return NT_STATUS_OK ;
}
if ( GUID_equal ( & rc . holder_req_guid , & caller_req_guid ) ) {
/*
* We ' re still the holder
*/
* _open = NULL ;
TALLOC_FREE ( frame ) ;
return NT_STATUS_FWP_RESERVED ;
2016-02-27 05:23:27 +03:00
}
2021-03-12 17:10:46 +03:00
/*
* The original request ( or a former replay ) is still
* pending , ask the client to retry by sending FILE_NOT_AVAILABLE .
*/
status = NT_STATUS_FILE_NOT_AVAILABLE ;
DBG_DEBUG ( " holder %s still pending for create %s [%s] - %s \n " ,
GUID_buf_string ( & rc . holder_req_guid , & tmp_guid_buf ) ,
create_guid_str ,
name ,
nt_errstr ( status ) ) ;
TALLOC_FREE ( frame ) ;
2016-02-27 05:23:27 +03:00
return status ;
}
2023-01-11 12:54:37 +03:00
struct smb2srv_open_recreate_state {
struct smbXsrv_open * op ;
const struct GUID * create_guid ;
struct security_token * current_token ;
struct server_id me ;
NTSTATUS status ;
} ;
static void smb2srv_open_recreate_fn (
struct db_record * rec , TDB_DATA oldval , void * private_data )
{
struct smb2srv_open_recreate_state * state = private_data ;
TDB_DATA key = dbwrap_record_get_key ( rec ) ;
struct smbXsrv_open_global0 * global = NULL ;
state - > status = smbXsrv_open_global_verify_record (
key , oldval , state - > op , & state - > op - > global ) ;
if ( ! NT_STATUS_IS_OK ( state - > status ) ) {
DBG_WARNING ( " smbXsrv_open_global_verify_record for %s "
" failed: %s \n " ,
tdb_data_dbg ( key ) ,
nt_errstr ( state - > status ) ) ;
goto not_found ;
}
global = state - > op - > global ;
/*
* If the provided create_guid is NULL , this means that
* the reconnect request was a v1 request . In that case
* we should skip the create GUID verification , since
* it is valid to v1 - reconnect a v2 - opened handle .
*/
if ( ( state - > create_guid ! = NULL ) & &
! GUID_equal ( & global - > create_guid , state - > create_guid ) ) {
struct GUID_txt_buf buf1 , buf2 ;
DBG_NOTICE ( " %s != %s in %s \n " ,
GUID_buf_string ( & global - > create_guid , & buf1 ) ,
GUID_buf_string ( state - > create_guid , & buf2 ) ,
tdb_data_dbg ( key ) ) ;
goto not_found ;
}
if ( ! security_token_is_sid (
state - > current_token , & global - > open_owner ) ) {
struct dom_sid_buf buf ;
DBG_NOTICE ( " global owner %s not in our token in %s \n " ,
dom_sid_str_buf ( & global - > open_owner , & buf ) ,
tdb_data_dbg ( key ) ) ;
goto not_found ;
}
if ( ! global - > durable ) {
DBG_NOTICE ( " % " PRIu64 " /% " PRIu64 " not durable in %s \n " ,
global - > open_persistent_id ,
global - > open_volatile_id ,
tdb_data_dbg ( key ) ) ;
goto not_found ;
}
global - > open_volatile_id = state - > op - > local_id ;
global - > server_id = state - > me ;
state - > status = smbXsrv_open_global_store ( rec , key , oldval , global ) ;
if ( ! NT_STATUS_IS_OK ( state - > status ) ) {
DBG_WARNING ( " smbXsrv_open_global_store for %s failed: %s \n " ,
tdb_data_dbg ( key ) ,
nt_errstr ( state - > status ) ) ;
return ;
}
return ;
not_found :
state - > status = NT_STATUS_OBJECT_NAME_NOT_FOUND ;
}
2012-06-18 14:46:15 +04:00
NTSTATUS smb2srv_open_recreate ( struct smbXsrv_connection * conn ,
struct auth_session_info * session_info ,
uint64_t persistent_id ,
2013-09-26 01:20:18 +04:00
const struct GUID * create_guid ,
2012-06-18 14:46:15 +04:00
NTTIME now ,
struct smbXsrv_open * * _open )
{
2014-06-12 22:22:54 +04:00
struct smbXsrv_open_table * table = conn - > client - > open_table ;
2023-01-11 12:54:37 +03:00
struct smb2srv_open_recreate_state state = {
. create_guid = create_guid ,
. me = messaging_server_id ( conn - > client - > msg_ctx ) ,
} ;
struct smbXsrv_open_global_key_buf key_buf ;
TDB_DATA key = smbXsrv_open_global_id_to_key (
persistent_id & UINT32_MAX , & key_buf ) ;
int ret , local_id ;
2012-06-18 14:46:15 +04:00
NTSTATUS status ;
if ( session_info = = NULL ) {
2014-07-07 15:49:49 +04:00
DEBUG ( 10 , ( " session_info=NULL \n " ) ) ;
2012-06-18 14:46:15 +04:00
return NT_STATUS_INVALID_HANDLE ;
}
2023-01-11 12:54:37 +03:00
state . current_token = session_info - > security_token ;
2012-06-18 14:46:15 +04:00
2023-01-11 12:54:37 +03:00
if ( state . current_token = = NULL ) {
2014-07-07 15:49:49 +04:00
DEBUG ( 10 , ( " current_token=NULL \n " ) ) ;
2012-06-18 14:46:15 +04:00
return NT_STATUS_INVALID_HANDLE ;
}
2023-01-04 16:05:55 +03:00
if ( ( persistent_id & 0xFFFFFFFF00000000LLU ) ! = 0 ) {
/*
* We only use 32 bit for the persistent ID
*/
DBG_DEBUG ( " persistent_id=% " PRIx64 " \n " , persistent_id ) ;
2012-06-18 14:46:15 +04:00
return NT_STATUS_OBJECT_NAME_NOT_FOUND ;
}
if ( table - > local . num_opens > = table - > local . max_opens ) {
return NT_STATUS_INSUFFICIENT_RESOURCES ;
}
2023-01-11 12:54:37 +03:00
state . op = talloc_zero ( table , struct smbXsrv_open ) ;
if ( state . op = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
state . op - > table = table ;
local_id = idr_get_new_random (
2023-01-04 14:18:44 +03:00
table - > local . idr ,
2023-01-11 12:54:37 +03:00
state . op ,
2023-01-04 14:18:44 +03:00
table - > local . lowest_id ,
table - > local . highest_id ) ;
if ( local_id = = - 1 ) {
2023-01-11 12:54:37 +03:00
TALLOC_FREE ( state . op ) ;
2023-01-04 14:18:44 +03:00
return NT_STATUS_INSUFFICIENT_RESOURCES ;
2012-06-18 14:46:15 +04:00
}
2023-01-11 12:54:37 +03:00
state . op - > local_id = local_id ;
SMB_ASSERT ( state . op - > local_id = = local_id ) ; /* No coercion loss */
2012-06-18 14:46:15 +04:00
table - > local . num_opens + = 1 ;
2023-01-11 12:54:37 +03:00
state . op - > idle_time = now ;
state . op - > status = NT_STATUS_FILE_CLOSED ;
2012-06-18 14:46:15 +04:00
2023-01-11 12:54:37 +03:00
status = dbwrap_do_locked (
table - > global . db_ctx , key , smb2srv_open_recreate_fn , & state ) ;
2012-06-18 14:46:15 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2023-01-11 12:54:37 +03:00
DBG_DEBUG ( " dbwrap_do_locked() for %s failed: %s \n " ,
tdb_data_dbg ( key ) ,
nt_errstr ( status ) ) ;
goto fail ;
}
if ( ! NT_STATUS_IS_OK ( state . status ) ) {
status = state . status ;
DBG_DEBUG ( " smb2srv_open_recreate_fn for %s failed: %s \n " ,
tdb_data_dbg ( key ) ,
nt_errstr ( status ) ) ;
goto fail ;
2012-06-18 14:46:15 +04:00
}
2023-01-11 12:54:37 +03:00
talloc_set_destructor ( state . op , smbXsrv_open_destructor ) ;
smbd: Avoid duplicate debug header lines
This is what gets created in log.smbd: DEBUGLVL generates an empty
header line, CHECK_DEBUGLVL avoids this.
[2014/01/10 12:58:24.971658, 10, pid=2329, effective(1001, 1001), real(0, 0)] ../source3/smbd/smbXsrv_open.c:696(smbXsrv_open_global_store)
[2014/01/10 12:58:24.971690, 10, pid=2329, effective(1001, 1001), real(0, 0)] ../source3/smbd/smbXsrv_open.c:698(smbXsrv_open_global_store)
Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
Autobuild-User(master): Jeremy Allison <jra@samba.org>
Autobuild-Date(master): Wed Jan 15 04:02:58 CET 2014 on sn-devel-104
2014-01-10 16:02:59 +04:00
if ( CHECK_DEBUGLVL ( 10 ) ) {
2019-09-16 15:26:05 +03:00
struct smbXsrv_openB open_blob = {
2023-01-11 12:54:37 +03:00
. info . info0 = state . op ,
2019-09-16 15:26:05 +03:00
} ;
2023-01-11 12:54:37 +03:00
DBG_DEBUG ( " global_id (0x%08x) stored \n " ,
state . op - > global - > open_global_id ) ;
2012-06-18 14:46:15 +04:00
NDR_PRINT_DEBUG ( smbXsrv_openB , & open_blob ) ;
}
2023-01-11 12:54:37 +03:00
* _open = state . op ;
2012-06-18 14:46:15 +04:00
return NT_STATUS_OK ;
2023-01-11 12:54:37 +03:00
fail :
table - > local . num_opens - = 1 ;
2012-12-12 19:06:50 +04:00
2023-01-11 12:54:37 +03:00
ret = idr_remove ( table - > local . idr , state . op - > local_id ) ;
SMB_ASSERT ( ret = = 0 ) ;
TALLOC_FREE ( state . op ) ;
return status ;
}
2012-12-12 19:06:50 +04:00
2013-03-12 16:43:30 +04:00
struct smbXsrv_open_global_traverse_state {
2023-01-11 13:02:11 +03:00
int ( * fn ) ( struct db_record * rec , struct smbXsrv_open_global0 * , void * ) ;
2013-03-12 16:43:30 +04:00
void * private_data ;
} ;
static int smbXsrv_open_global_traverse_fn ( struct db_record * rec , void * data )
{
struct smbXsrv_open_global_traverse_state * state =
( struct smbXsrv_open_global_traverse_state * ) data ;
struct smbXsrv_open_global0 * global = NULL ;
2023-01-19 14:25:21 +03:00
TDB_DATA key = dbwrap_record_get_key ( rec ) ;
TDB_DATA val = dbwrap_record_get_value ( rec ) ;
2013-03-12 16:43:30 +04:00
NTSTATUS status ;
int ret = - 1 ;
2023-01-19 14:25:21 +03:00
status = smbXsrv_open_global_parse_record (
talloc_tos ( ) , key , val , & global ) ;
2013-03-12 16:43:30 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
return - 1 ;
}
2023-01-11 13:02:11 +03:00
ret = state - > fn ( rec , global , state - > private_data ) ;
2013-03-12 16:43:30 +04:00
talloc_free ( global ) ;
2012-12-12 19:06:50 +04:00
return ret ;
}
NTSTATUS smbXsrv_open_global_traverse (
2023-01-11 13:02:11 +03:00
int ( * fn ) ( struct db_record * rec , struct smbXsrv_open_global0 * , void * ) ,
void * private_data )
2012-12-12 19:06:50 +04:00
{
NTSTATUS status ;
int count = 0 ;
struct smbXsrv_open_global_traverse_state state = {
. fn = fn ,
. private_data = private_data ,
} ;
become_root ( ) ;
status = smbXsrv_open_global_init ( ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
unbecome_root ( ) ;
DEBUG ( 0 , ( " Failed to initialize open_global: %s \n " ,
nt_errstr ( status ) ) ) ;
return status ;
}
status = dbwrap_traverse_read ( smbXsrv_open_global_db_ctx ,
smbXsrv_open_global_traverse_fn ,
& state ,
& count ) ;
unbecome_root ( ) ;
return status ;
}
2013-03-12 17:36:32 +04:00
2023-01-10 14:29:18 +03:00
struct smbXsrv_open_cleanup_state {
uint32_t global_id ;
NTSTATUS status ;
} ;
static void smbXsrv_open_cleanup_fn (
struct db_record * rec , TDB_DATA oldval , void * private_data )
2013-03-12 17:36:32 +04:00
{
2023-01-10 14:29:18 +03:00
struct smbXsrv_open_cleanup_state * state = private_data ;
2023-01-31 14:39:06 +03:00
struct smbXsrv_open_global0 * global = NULL ;
2023-01-10 14:29:18 +03:00
TDB_DATA key = dbwrap_record_get_key ( rec ) ;
2013-03-12 17:36:32 +04:00
bool delete_open = false ;
2023-01-19 14:25:21 +03:00
2023-01-10 14:29:18 +03:00
if ( oldval . dsize = = 0 ) {
DBG_DEBUG ( " [global: 0x%08x] "
2013-12-24 12:00:01 +04:00
" empty record in %s, skipping... \n " ,
2023-01-10 14:29:18 +03:00
state - > global_id ,
dbwrap_name ( dbwrap_record_get_db ( rec ) ) ) ;
state - > status = NT_STATUS_OK ;
return ;
2013-12-24 12:00:01 +04:00
}
2023-01-10 14:29:18 +03:00
state - > status = smbXsrv_open_global_parse_record (
2023-01-31 14:39:06 +03:00
talloc_tos ( ) , key , oldval , & global ) ;
2023-01-10 14:29:18 +03:00
if ( ! NT_STATUS_IS_OK ( state - > status ) ) {
DBG_WARNING ( " [global: %x08x] "
" smbXsrv_open_global_parse_record() in %s "
2023-01-10 14:29:18 +03:00
" failed: %s, deleting record \n " ,
2023-01-10 14:29:18 +03:00
state - > global_id ,
dbwrap_name ( dbwrap_record_get_db ( rec ) ) ,
nt_errstr ( state - > status ) ) ;
2023-01-10 14:29:18 +03:00
delete_open = true ;
goto do_delete ;
2013-03-12 17:36:32 +04:00
}
2023-01-31 14:39:06 +03:00
if ( server_id_is_disconnected ( & global - > server_id ) ) {
2023-01-10 14:29:18 +03:00
struct timeval now = timeval_current ( ) ;
struct timeval disconnect_time ;
struct timeval_buf buf ;
2013-03-12 17:36:32 +04:00
int64_t tdiff ;
2023-01-10 14:29:18 +03:00
2023-01-31 14:39:06 +03:00
nttime_to_timeval ( & disconnect_time , global - > disconnect_time ) ;
2013-03-12 17:36:32 +04:00
tdiff = usec_time_diff ( & now , & disconnect_time ) ;
2023-01-31 14:39:06 +03:00
delete_open = ( tdiff > = 1000 * global - > durable_timeout_msec ) ;
2013-03-12 17:36:32 +04:00
2023-01-10 14:29:18 +03:00
DBG_DEBUG ( " [global: 0x%08x] "
" disconnected at [%s] % " PRIi64 " s ago with "
" timeout of % " PRIu32 " s -%s reached \n " ,
state - > global_id ,
timeval_str_buf ( & disconnect_time ,
false ,
false ,
& buf ) ,
tdiff / 1000000 ,
2023-01-31 14:39:06 +03:00
global - > durable_timeout_msec / 1000 ,
2023-01-10 14:29:18 +03:00
delete_open ? " " : " not " ) ;
2023-01-31 14:39:06 +03:00
} else if ( ! serverid_exists ( & global - > server_id ) ) {
2015-04-28 14:30:58 +03:00
struct server_id_buf idbuf ;
2023-01-10 14:29:18 +03:00
DBG_DEBUG ( " [global: 0x%08x] "
" server[%s] does not exist \n " ,
state - > global_id ,
2023-01-31 14:39:06 +03:00
server_id_str_buf ( global - > server_id , & idbuf ) ) ;
2013-03-12 17:36:32 +04:00
delete_open = true ;
}
if ( ! delete_open ) {
2023-01-10 14:29:18 +03:00
state - > status = NT_STATUS_OK ;
return ;
2013-03-12 17:36:32 +04:00
}
2023-01-10 14:29:18 +03:00
do_delete :
2023-01-10 14:29:18 +03:00
state - > status = dbwrap_record_delete ( rec ) ;
if ( ! NT_STATUS_IS_OK ( state - > status ) ) {
DBG_WARNING ( " [global: 0x%08x] "
2023-08-02 00:44:51 +03:00
" failed to delete record "
2023-01-10 14:29:18 +03:00
" from %s: %s \n " ,
state - > global_id ,
dbwrap_name ( dbwrap_record_get_db ( rec ) ) ,
nt_errstr ( state - > status ) ) ;
return ;
2013-03-12 17:36:32 +04:00
}
2023-01-10 14:29:18 +03:00
DBG_DEBUG ( " [global: 0x%08x] "
" deleted record from %s \n " ,
state - > global_id ,
dbwrap_name ( dbwrap_record_get_db ( rec ) ) ) ;
}
2013-03-12 17:36:32 +04:00
2023-01-10 14:29:18 +03:00
NTSTATUS smbXsrv_open_cleanup ( uint64_t persistent_id )
{
struct smbXsrv_open_cleanup_state state = {
. global_id = persistent_id & UINT32_MAX ,
} ;
struct smbXsrv_open_global_key_buf key_buf ;
TDB_DATA key = smbXsrv_open_global_id_to_key (
state . global_id , & key_buf ) ;
NTSTATUS status ;
status = dbwrap_do_locked (
smbXsrv_open_global_db_ctx ,
key ,
smbXsrv_open_cleanup_fn ,
& state ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DBG_DEBUG ( " [global: 0x%08x] dbwrap_do_locked failed: %s \n " ,
state . global_id ,
nt_errstr ( status ) ) ;
return status ;
}
return state . status ;
2013-03-12 17:36:32 +04:00
}