2007-09-12 21:48:20 +00:00
/*
2002-01-30 06:08:46 +00:00
Unix SMB / CIFS implementation .
1996-05-04 07:50:46 +00:00
SMB transaction2 handling
2007-01-30 19:54:28 +00:00
Copyright ( C ) Jeremy Allison 1994 - 2007
2003-05-12 01:20:17 +00:00
Copyright ( C ) Stefan ( metze ) Metzmacher 2003
2007-08-02 18:28:41 +00:00
Copyright ( C ) Volker Lendecke 2005 - 2007
2005-10-20 17:33:17 +00:00
Copyright ( C ) Steve French 2005
2008-01-19 20:41:15 +01:00
Copyright ( C ) James Peach 2006 - 2007
1996-05-04 07:50:46 +00:00
Extensively modified by Andrew Tridgell , 1995
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 19:25:36 +00:00
the Free Software Foundation ; either version 3 of the License , or
1996-05-04 07:50:46 +00:00
( at your option ) any later version .
2007-09-12 21:48:20 +00:00
1996-05-04 07:50:46 +00: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 .
2007-09-12 21:48:20 +00:00
1996-05-04 07:50:46 +00:00
You should have received a copy of the GNU General Public License
2007-07-10 00:52:41 +00:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
1996-05-04 07:50:46 +00:00
*/
# include "includes.h"
2013-08-18 07:34:31 -07:00
# include "ntioctl.h"
2011-02-25 23:20:06 +01:00
# include "system/filesys.h"
2019-12-02 16:30:50 +01:00
# include "lib/util/time_basic.h"
2009-01-15 22:27:52 +01:00
# include "version.h"
2011-03-22 16:57:01 +01:00
# include "smbd/smbd.h"
2009-01-08 12:03:45 +01:00
# include "smbd/globals.h"
2009-03-16 21:27:58 +11:00
# include "../libcli/auth/libcli_auth.h"
2010-05-05 01:39:16 +02:00
# include "../librpc/gen_ndr/xattr.h"
2010-05-28 02:19:32 +02:00
# include "../librpc/gen_ndr/ndr_security.h"
2023-09-27 10:48:35 +02:00
# include "../librpc/gen_ndr/ndr_smb3posix.h"
2010-10-12 15:27:50 +11:00
# include "libcli/security/security.h"
2011-02-25 00:03:01 +01:00
# include "trans2.h"
2011-03-24 13:46:20 +01:00
# include "auth.h"
2011-04-14 00:36:23 +02:00
# include "smbprofile.h"
2011-04-29 23:32:28 +02:00
# include "rpc_server/srv_pipe_hnd.h"
2012-06-05 08:42:53 +02:00
# include "printing.h"
2013-08-07 13:48:55 -07:00
# include "lib/util_ea.h"
2014-11-26 15:21:36 +01:00
# include "lib/readdir_attr.h"
2018-09-08 18:05:57 +02:00
# include "messages.h"
2020-02-04 14:58:02 +02:00
# include "libcli/smb/smb2_posix.h"
2020-08-07 11:17:34 -07:00
# include "lib/util/string_wrappers.h"
2021-11-10 20:18:07 +01:00
# include "source3/lib/substitute.h"
2021-11-20 16:36:42 +01:00
# include "source3/lib/adouble.h"
1996-05-04 07:50:46 +00:00
2004-09-25 22:18:46 +00:00
# define DIR_ENTRY_SAFETY_MARGIN 4096
2022-04-27 19:27:15 +02:00
static uint32_t generate_volume_serial_number (
const struct loadparm_substitution * lp_sub ,
int snum ) ;
2016-01-05 11:18:12 -08:00
/****************************************************************************
2021-05-20 12:02:22 -07:00
Check if an open file handle is a symlink .
2016-01-05 11:18:12 -08:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2021-05-20 12:13:19 -07:00
NTSTATUS refuse_symlink_fsp ( const files_struct * fsp )
2016-01-05 11:18:12 -08:00
{
2021-05-20 12:02:22 -07:00
if ( ! VALID_STAT ( fsp - > fsp_name - > st ) ) {
return NT_STATUS_ACCESS_DENIED ;
2016-09-10 14:43:07 +02:00
}
2021-05-20 12:02:22 -07:00
if ( S_ISLNK ( fsp - > fsp_name - > st . st_ex_mode ) ) {
return NT_STATUS_ACCESS_DENIED ;
2016-01-05 11:18:12 -08:00
}
2021-05-20 12:02:22 -07:00
if ( fsp_get_pathref_fd ( fsp ) = = - 1 ) {
2016-01-05 11:18:12 -08:00
return NT_STATUS_ACCESS_DENIED ;
}
return NT_STATUS_OK ;
}
2020-11-17 12:08:48 +01:00
NTSTATUS check_access_fsp ( struct files_struct * fsp ,
2015-11-17 15:10:42 +01:00
uint32_t access_mask )
{
2020-11-17 12:09:05 +01:00
if ( ! fsp - > fsp_flags . is_fsa ) {
2021-06-08 12:24:17 -07:00
return smbd_check_access_rights_fsp ( fsp - > conn - > cwd_fsp ,
fsp ,
2020-11-17 12:09:05 +01:00
false ,
access_mask ) ;
}
2015-11-17 15:10:42 +01:00
if ( ! ( fsp - > access_mask & access_mask ) ) {
return NT_STATUS_ACCESS_DENIED ;
}
return NT_STATUS_OK ;
}
2005-03-03 03:43:57 +00:00
/********************************************************************
Roundup a value to the nearest allocation roundup size boundary .
Only do this for Windows clients .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-10-14 01:59:36 +02:00
uint64_t smb_roundup ( connection_struct * conn , uint64_t val )
2005-03-03 03:43:57 +00:00
{
2008-10-14 01:59:36 +02:00
uint64_t rval = lp_allocation_roundup_size ( SNUM ( conn ) ) ;
2005-03-03 03:43:57 +00:00
/* Only roundup for Windows clients. */
enum remote_arch_types ra_type = get_remote_arch ( ) ;
if ( rval & & ( ra_type ! = RA_SAMBA ) & & ( ra_type ! = RA_CIFSFS ) ) {
val = SMB_ROUNDUP ( val , rval ) ;
}
return val ;
}
2004-03-31 02:20:16 +00:00
/****************************************************************************
Utility functions for dealing with extended attributes .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/****************************************************************************
Refuse to allow clients to overwrite our private xattrs .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2014-05-21 11:52:27 +02:00
bool samba_private_attr_name ( const char * unix_ea_name )
2004-03-31 02:20:16 +00:00
{
2023-01-04 06:22:55 +01:00
bool prohibited = false ;
prohibited | = strequal ( unix_ea_name , SAMBA_POSIX_INHERITANCE_EA_NAME ) ;
prohibited | = strequal ( unix_ea_name , SAMBA_XATTR_DOS_ATTRIB ) ;
prohibited | = strequal ( unix_ea_name , SAMBA_XATTR_MARKER ) ;
prohibited | = strequal ( unix_ea_name , XATTR_NTACL_NAME ) ;
prohibited | = strequal ( unix_ea_name , AFPINFO_EA_NETATALK ) ;
if ( prohibited ) {
return true ;
2004-03-31 02:20:16 +00:00
}
2023-01-04 06:22:55 +01:00
2011-05-13 20:23:36 +02:00
if ( strncasecmp_m ( unix_ea_name , SAMBA_XATTR_DOSSTREAM_PREFIX ,
2008-01-21 20:24:23 +01:00
strlen ( SAMBA_XATTR_DOSSTREAM_PREFIX ) ) = = 0 ) {
return true ;
}
return false ;
2004-03-31 02:20:16 +00:00
}
/****************************************************************************
Get one EA value . Fill in a struct ea_struct .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2021-06-22 17:53:29 -07:00
NTSTATUS get_ea_value_fsp ( TALLOC_CTX * mem_ctx ,
files_struct * fsp ,
const char * ea_name ,
struct ea_struct * pea )
2004-03-31 02:20:16 +00:00
{
/* Get the value of this xattr. Max size is 64k. */
size_t attr_size = 256 ;
char * val = NULL ;
ssize_t sizeret ;
2021-06-22 17:53:29 -07:00
size_t max_xattr_size = 0 ;
2023-10-31 15:38:46 +01:00
NTSTATUS status ;
2021-06-22 17:53:29 -07:00
if ( fsp = = NULL ) {
return NT_STATUS_INVALID_HANDLE ;
}
2023-10-31 15:38:46 +01:00
status = refuse_symlink_fsp ( fsp ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
2021-06-22 17:53:29 -07:00
max_xattr_size = lp_smbd_max_xattr_size ( SNUM ( fsp - > conn ) ) ;
2004-03-31 02:20:16 +00:00
again :
2011-06-07 11:10:15 +10:00
val = talloc_realloc ( mem_ctx , val , char , attr_size ) ;
2004-03-31 02:20:16 +00:00
if ( ! val ) {
2008-01-15 13:22:39 +01:00
return NT_STATUS_NO_MEMORY ;
2004-03-31 02:20:16 +00:00
}
2021-06-22 17:53:29 -07:00
sizeret = SMB_VFS_FGETXATTR ( fsp , ea_name , val , attr_size ) ;
2021-05-07 06:37:25 -04:00
if ( sizeret = = - 1 & & errno = = ERANGE & & attr_size < max_xattr_size ) {
attr_size = max_xattr_size ;
2004-03-31 02:20:16 +00:00
goto again ;
}
if ( sizeret = = - 1 ) {
2008-01-15 13:22:39 +01:00
return map_nt_error_from_unix ( errno ) ;
2004-03-31 02:20:16 +00:00
}
2007-10-30 22:58:09 +01:00
DEBUG ( 10 , ( " get_ea_value: EA %s is of length %u \n " , ea_name , ( unsigned int ) sizeret ) ) ;
2015-04-26 16:02:55 -07:00
dump_data ( 10 , ( uint8_t * ) val , sizeret ) ;
2004-03-31 02:20:16 +00:00
pea - > flags = 0 ;
if ( strnequal ( ea_name , " user. " , 5 ) ) {
2008-01-15 13:22:39 +01:00
pea - > name = talloc_strdup ( mem_ctx , & ea_name [ 5 ] ) ;
2004-03-31 02:20:16 +00:00
} else {
2008-01-15 13:22:39 +01:00
pea - > name = talloc_strdup ( mem_ctx , ea_name ) ;
}
if ( pea - > name = = NULL ) {
TALLOC_FREE ( val ) ;
return NT_STATUS_NO_MEMORY ;
2004-03-31 02:20:16 +00:00
}
2005-03-17 01:19:49 +00:00
pea - > value . data = ( unsigned char * ) val ;
2004-03-31 02:20:16 +00:00
pea - > value . length = ( size_t ) sizeret ;
2008-01-15 13:22:39 +01:00
return NT_STATUS_OK ;
2004-03-31 02:20:16 +00:00
}
2021-06-23 12:12:30 -07:00
NTSTATUS get_ea_names_from_fsp ( TALLOC_CTX * mem_ctx ,
2016-03-11 15:34:58 -08:00
files_struct * fsp ,
char * * * pnames ,
size_t * pnum_names )
2004-03-31 02:20:16 +00:00
{
2016-10-20 16:33:55 +02:00
char smallbuf [ 1024 ] ;
2004-03-31 02:20:16 +00:00
/* Get a list of all xattrs. Max namesize is 64k. */
size_t ea_namelist_size = 1024 ;
2016-10-20 16:33:55 +02:00
char * ea_namelist = smallbuf ;
char * to_free = NULL ;
2008-01-19 16:07:56 +01:00
2004-03-31 02:20:16 +00:00
char * p ;
2016-10-20 16:33:55 +02:00
char * * names ;
2008-01-19 16:07:56 +01:00
size_t num_names ;
2008-04-29 14:36:24 -07:00
ssize_t sizeret = - 1 ;
2016-01-05 11:29:38 -08:00
NTSTATUS status ;
2004-03-31 02:20:16 +00:00
2016-01-05 11:05:48 -08:00
if ( pnames ) {
* pnames = NULL ;
}
* pnum_names = 0 ;
2023-10-31 15:38:46 +01:00
if ( ( fsp = = NULL ) | | ! NT_STATUS_IS_OK ( refuse_symlink_fsp ( fsp ) ) ) {
2016-01-05 11:29:38 -08:00
/*
2021-01-31 19:18:03 +00:00
* Callers may pass fsp = = NULL when passing smb_fname - > fsp of a
* symlink . This is ok , handle it here , by just return no EA ' s
* on a symlink .
2016-01-05 11:29:38 -08:00
*/
return NT_STATUS_OK ;
}
2021-01-29 14:53:43 +00:00
sizeret = SMB_VFS_FLISTXATTR ( fsp , ea_namelist ,
ea_namelist_size ) ;
2008-01-19 16:07:56 +01:00
2016-10-20 16:33:55 +02:00
if ( ( sizeret = = - 1 ) & & ( errno = = ERANGE ) ) {
ea_namelist_size = 65536 ;
ea_namelist = talloc_array ( mem_ctx , char , ea_namelist_size ) ;
2008-01-19 16:07:56 +01:00
if ( ea_namelist = = NULL ) {
return NT_STATUS_NO_MEMORY ;
2006-06-16 22:36:12 +00:00
}
2016-10-20 16:33:55 +02:00
to_free = ea_namelist ;
2006-06-16 22:36:12 +00:00
2021-01-29 14:53:43 +00:00
sizeret = SMB_VFS_FLISTXATTR ( fsp , ea_namelist ,
ea_namelist_size ) ;
2004-03-31 02:20:16 +00:00
}
2008-01-19 16:07:56 +01:00
if ( sizeret = = - 1 ) {
2016-10-20 16:33:55 +02:00
status = map_nt_error_from_unix ( errno ) ;
TALLOC_FREE ( to_free ) ;
return status ;
2008-01-19 16:07:56 +01:00
}
2016-10-20 16:33:55 +02:00
DBG_DEBUG ( " ea_namelist size = %zd \n " , sizeret ) ;
2008-01-19 16:07:56 +01:00
if ( sizeret = = 0 ) {
2016-10-20 16:33:55 +02:00
TALLOC_FREE ( to_free ) ;
2008-01-19 16:07:56 +01:00
return NT_STATUS_OK ;
}
/*
* Ensure the result is 0 - terminated
*/
if ( ea_namelist [ sizeret - 1 ] ! = ' \0 ' ) {
2016-10-20 16:33:55 +02:00
TALLOC_FREE ( to_free ) ;
2008-01-19 16:07:56 +01:00
return NT_STATUS_INTERNAL_ERROR ;
}
/*
* count the names
*/
num_names = 0 ;
for ( p = ea_namelist ; p - ea_namelist < sizeret ; p + = strlen ( p ) + 1 ) {
num_names + = 1 ;
}
2016-10-20 16:33:55 +02:00
* pnum_names = num_names ;
if ( pnames = = NULL ) {
TALLOC_FREE ( to_free ) ;
return NT_STATUS_OK ;
}
names = talloc_array ( mem_ctx , char * , num_names ) ;
if ( names = = NULL ) {
2008-01-19 16:07:56 +01:00
DEBUG ( 0 , ( " talloc failed \n " ) ) ;
2016-10-20 16:33:55 +02:00
TALLOC_FREE ( to_free ) ;
2008-01-19 16:07:56 +01:00
return NT_STATUS_NO_MEMORY ;
}
2016-10-20 16:33:55 +02:00
if ( ea_namelist = = smallbuf ) {
ea_namelist = talloc_memdup ( names , smallbuf , sizeret ) ;
if ( ea_namelist = = NULL ) {
TALLOC_FREE ( names ) ;
return NT_STATUS_NO_MEMORY ;
}
} else {
talloc_steal ( names , ea_namelist ) ;
ea_namelist = talloc_realloc ( names , ea_namelist , char ,
sizeret ) ;
if ( ea_namelist = = NULL ) {
TALLOC_FREE ( names ) ;
return NT_STATUS_NO_MEMORY ;
}
}
2008-01-19 16:07:56 +01:00
num_names = 0 ;
for ( p = ea_namelist ; p - ea_namelist < sizeret ; p + = strlen ( p ) + 1 ) {
names [ num_names + + ] = p ;
}
2016-10-20 16:33:55 +02:00
* pnames = names ;
2008-01-19 16:07:56 +01:00
return NT_STATUS_OK ;
}
/****************************************************************************
Return a linked list of the total EA ' s . Plus the total size
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2021-02-10 10:07:51 +00:00
static NTSTATUS get_ea_list_from_fsp ( TALLOC_CTX * mem_ctx ,
2021-02-10 09:53:23 +00:00
files_struct * fsp ,
size_t * pea_total_len ,
struct ea_list * * ea_list )
{
/* Get a list of all xattrs. Max namesize is 64k. */
size_t i , num_names ;
char * * names ;
struct ea_list * ea_list_head = NULL ;
bool posix_pathnames = false ;
NTSTATUS status ;
* pea_total_len = 0 ;
* ea_list = NULL ;
/* symlink */
if ( fsp = = NULL ) {
return NT_STATUS_OK ;
}
if ( ! lp_ea_support ( SNUM ( fsp - > conn ) ) ) {
return NT_STATUS_OK ;
}
2022-02-11 09:59:16 +01:00
if ( fsp_is_alternate_stream ( fsp ) ) {
2021-02-10 10:07:51 +00:00
return NT_STATUS_INVALID_PARAMETER ;
}
2021-02-10 09:53:23 +00:00
posix_pathnames = ( fsp - > fsp_name - > flags & SMB_FILENAME_POSIX_PATH ) ;
2021-06-23 12:12:30 -07:00
status = get_ea_names_from_fsp ( talloc_tos ( ) ,
2021-02-10 09:53:23 +00:00
fsp ,
& names ,
& num_names ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
if ( num_names = = 0 ) {
return NT_STATUS_OK ;
}
for ( i = 0 ; i < num_names ; i + + ) {
struct ea_list * listp ;
fstring dos_ea_name ;
2022-09-26 10:27:19 +02:00
/*
* POSIX EA names are divided into several namespaces by
* means of string prefixes . Usually , the system controls
* semantics for each namespace , but the ' user ' namespace is
* available for arbitrary use , which comes closest to
* Windows EA semantics . Hence , we map POSIX EAs from the
* ' user ' namespace to Windows EAs , and just ignore all the
* other namespaces . Also , a few specific names in the ' user '
* namespace are used by Samba internally . Filter them out as
* well , and only present the EAs that are available for
* arbitrary use .
*/
if ( ! strnequal ( names [ i ] , " user. " , 5 )
2021-02-10 09:53:23 +00:00
| | samba_private_attr_name ( names [ i ] ) )
continue ;
/*
* Filter out any underlying POSIX EA names
* that a Windows client can ' t handle .
*/
if ( ! posix_pathnames & &
is_invalid_windows_ea_name ( names [ i ] ) ) {
continue ;
}
listp = talloc ( mem_ctx , struct ea_list ) ;
if ( listp = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
2021-06-22 17:53:29 -07:00
status = get_ea_value_fsp ( listp ,
fsp ,
names [ i ] ,
& listp - > ea ) ;
2021-02-10 09:53:23 +00:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
TALLOC_FREE ( listp ) ;
return status ;
}
if ( listp - > ea . value . length = = 0 ) {
/*
* We can never return a zero length EA .
* Windows reports the EA ' s as corrupted .
*/
TALLOC_FREE ( listp ) ;
continue ;
2021-05-07 06:37:25 -04:00
} else if ( listp - > ea . value . length > 65536 ) {
/*
* SMB clients may report error with file
* if large EA is presented to them .
*/
DBG_ERR ( " EA [%s] on file [%s] exceeds "
" maximum permitted EA size of 64KiB: %zu \n . " ,
listp - > ea . name , fsp_str_dbg ( fsp ) ,
listp - > ea . value . length ) ;
TALLOC_FREE ( listp ) ;
continue ;
2021-02-10 09:53:23 +00:00
}
push_ascii_fstring ( dos_ea_name , listp - > ea . name ) ;
* pea_total_len + =
4 + strlen ( dos_ea_name ) + 1 + listp - > ea . value . length ;
DEBUG ( 10 , ( " get_ea_list_from_file: total_len = %u, %s, val len "
" = %u \n " , ( unsigned int ) * pea_total_len , dos_ea_name ,
( unsigned int ) listp - > ea . value . length ) ) ;
DLIST_ADD_END ( ea_list_head , listp ) ;
}
/* Add on 4 for total length. */
if ( * pea_total_len ) {
* pea_total_len + = 4 ;
}
DEBUG ( 10 , ( " get_ea_list_from_file: total_len = %u \n " ,
( unsigned int ) * pea_total_len ) ) ;
* ea_list = ea_list_head ;
return NT_STATUS_OK ;
}
2004-03-31 02:20:16 +00:00
/****************************************************************************
2004-04-10 20:02:46 +00:00
Fill a qfilepathinfo buffer with EA ' s . Returns the length of the buffer
that was filled .
2004-03-31 02:20:16 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-03-18 01:55:30 +00:00
static unsigned int fill_ea_buffer ( TALLOC_CTX * mem_ctx , char * pdata , unsigned int total_data_size ,
connection_struct * conn , struct ea_list * ea_list )
2004-03-31 02:20:16 +00:00
{
unsigned int ret_data_size = 4 ;
char * p = pdata ;
SMB_ASSERT ( total_data_size > = 4 ) ;
2004-04-10 20:02:46 +00:00
if ( ! lp_ea_support ( SNUM ( conn ) ) ) {
2005-03-26 00:44:46 +00:00
SIVAL ( pdata , 4 , 0 ) ;
2004-04-10 20:02:46 +00:00
return 4 ;
}
2004-03-31 02:20:16 +00:00
for ( p = pdata + 4 ; ea_list ; ea_list = ea_list - > next ) {
size_t dos_namelen ;
fstring dos_ea_name ;
push_ascii_fstring ( dos_ea_name , ea_list - > ea . name ) ;
dos_namelen = strlen ( dos_ea_name ) ;
if ( dos_namelen > 255 | | dos_namelen = = 0 ) {
break ;
}
if ( ea_list - > ea . value . length > 65535 ) {
break ;
}
if ( 4 + dos_namelen + 1 + ea_list - > ea . value . length > total_data_size ) {
break ;
}
/* We know we have room. */
SCVAL ( p , 0 , ea_list - > ea . flags ) ;
SCVAL ( p , 1 , dos_namelen ) ;
SSVAL ( p , 2 , ea_list - > ea . value . length ) ;
2011-05-04 11:38:26 -07:00
strlcpy ( p + 4 , dos_ea_name , dos_namelen + 1 ) ;
2019-05-24 11:00:05 +12:00
if ( ea_list - > ea . value . length > 0 ) {
memcpy ( p + 4 + dos_namelen + 1 ,
ea_list - > ea . value . data ,
ea_list - > ea . value . length ) ;
}
2004-03-31 02:20:16 +00:00
total_data_size - = 4 + dos_namelen + 1 + ea_list - > ea . value . length ;
p + = 4 + dos_namelen + 1 + ea_list - > ea . value . length ;
}
ret_data_size = PTR_DIFF ( p , pdata ) ;
2005-03-18 01:55:30 +00:00
DEBUG ( 10 , ( " fill_ea_buffer: data_size = %u \n " , ret_data_size ) ) ;
2004-03-31 02:20:16 +00:00
SIVAL ( pdata , 0 , ret_data_size ) ;
return ret_data_size ;
}
2009-07-12 16:40:58 +02:00
static NTSTATUS fill_ea_chained_buffer ( TALLOC_CTX * mem_ctx ,
char * pdata ,
unsigned int total_data_size ,
unsigned int * ret_data_size ,
connection_struct * conn ,
struct ea_list * ea_list )
{
uint8_t * p = ( uint8_t * ) pdata ;
uint8_t * last_start = NULL ;
2013-03-26 15:46:06 -07:00
bool do_store_data = ( pdata ! = NULL ) ;
2009-07-12 16:40:58 +02:00
* ret_data_size = 0 ;
if ( ! lp_ea_support ( SNUM ( conn ) ) ) {
return NT_STATUS_NO_EAS_ON_FILE ;
}
for ( ; ea_list ; ea_list = ea_list - > next ) {
size_t dos_namelen ;
fstring dos_ea_name ;
size_t this_size ;
2013-03-26 16:46:51 -07:00
size_t pad = 0 ;
2009-07-12 16:40:58 +02:00
2013-03-26 15:46:06 -07:00
if ( last_start ! = NULL & & do_store_data ) {
2009-07-12 16:40:58 +02:00
SIVAL ( last_start , 0 , PTR_DIFF ( p , last_start ) ) ;
}
last_start = p ;
push_ascii_fstring ( dos_ea_name , ea_list - > ea . name ) ;
dos_namelen = strlen ( dos_ea_name ) ;
if ( dos_namelen > 255 | | dos_namelen = = 0 ) {
return NT_STATUS_INTERNAL_ERROR ;
}
if ( ea_list - > ea . value . length > 65535 ) {
return NT_STATUS_INTERNAL_ERROR ;
}
this_size = 0x08 + dos_namelen + 1 + ea_list - > ea . value . length ;
if ( ea_list - > next ) {
2013-03-27 11:54:34 -07:00
pad = ( 4 - ( this_size % 4 ) ) % 4 ;
2009-07-12 16:40:58 +02:00
this_size + = pad ;
}
2013-03-26 15:46:06 -07:00
if ( do_store_data ) {
if ( this_size > total_data_size ) {
return NT_STATUS_INFO_LENGTH_MISMATCH ;
}
/* We know we have room. */
SIVAL ( p , 0x00 , 0 ) ; /* next offset */
SCVAL ( p , 0x04 , ea_list - > ea . flags ) ;
SCVAL ( p , 0x05 , dos_namelen ) ;
SSVAL ( p , 0x06 , ea_list - > ea . value . length ) ;
strlcpy ( ( char * ) ( p + 0x08 ) , dos_ea_name , dos_namelen + 1 ) ;
memcpy ( p + 0x08 + dos_namelen + 1 , ea_list - > ea . value . data , ea_list - > ea . value . length ) ;
2013-03-26 16:46:51 -07:00
if ( pad ) {
memset ( p + 0x08 + dos_namelen + 1 + ea_list - > ea . value . length ,
' \0 ' ,
pad ) ;
}
2013-03-26 15:46:06 -07:00
total_data_size - = this_size ;
2009-07-12 16:40:58 +02:00
}
p + = this_size ;
}
* ret_data_size = PTR_DIFF ( p , pdata ) ;
DEBUG ( 10 , ( " fill_ea_chained_buffer: data_size = %u \n " , * ret_data_size ) ) ;
return NT_STATUS_OK ;
}
2022-03-21 12:29:26 -06:00
unsigned int estimate_ea_size ( files_struct * fsp )
2004-03-31 02:20:16 +00:00
{
size_t total_ea_len = 0 ;
2012-08-19 15:24:04 +10:00
TALLOC_CTX * mem_ctx ;
2013-03-29 10:07:20 -07:00
struct ea_list * ea_list = NULL ;
2021-01-29 14:54:47 +00:00
NTSTATUS status ;
2004-03-31 02:20:16 +00:00
2021-02-01 21:09:08 +00:00
/* symlink */
if ( fsp = = NULL ) {
return 0 ;
}
2021-02-10 11:54:29 +00:00
if ( ! lp_ea_support ( SNUM ( fsp - > conn ) ) ) {
return 0 ;
}
2012-08-19 21:58:56 +10:00
2021-09-11 12:33:37 +02:00
mem_ctx = talloc_stackframe ( ) ;
2012-08-19 21:58:56 +10:00
/* If this is a stream fsp, then we need to instead find the
* estimated ea len from the main file , not the stream
2012-08-19 22:46:58 +10:00
* ( streams cannot have EAs ) , but the estimate isn ' t just 0 in
* this case ! */
2022-02-11 09:45:30 +01:00
fsp = metadata_fsp ( fsp ) ;
2021-02-10 10:13:46 +00:00
( void ) get_ea_list_from_fsp ( mem_ctx ,
fsp ,
& total_ea_len ,
& ea_list ) ;
2021-02-01 21:09:08 +00:00
2021-02-10 11:54:29 +00:00
if ( fsp - > conn - > sconn - > using_smb2 ) {
2013-03-26 15:54:31 -07:00
unsigned int ret_data_size ;
/*
* We ' re going to be using fill_ea_chained_buffer ( ) to
* marshall EA ' s - this size is significantly larger
* than the SMB1 buffer . Re - calculate the size without
* marshalling .
*/
status = fill_ea_chained_buffer ( mem_ctx ,
NULL ,
0 ,
& ret_data_size ,
2021-02-10 11:54:29 +00:00
fsp - > conn ,
2013-03-26 15:54:31 -07:00
ea_list ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
ret_data_size = 0 ;
}
total_ea_len = ret_data_size ;
}
2012-08-19 15:24:04 +10:00
TALLOC_FREE ( mem_ctx ) ;
2004-03-31 02:20:16 +00:00
return total_ea_len ;
}
2004-04-06 14:24:13 +00:00
/****************************************************************************
Ensure the EA name is case insensitive by matching any existing EA name .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2021-02-10 10:26:53 +00:00
static void canonicalize_ea_name ( files_struct * fsp ,
2016-03-11 15:25:54 -08:00
fstring unix_ea_name )
2004-04-06 14:24:13 +00:00
{
size_t total_ea_len ;
2008-01-09 17:11:04 -08:00
TALLOC_CTX * mem_ctx = talloc_tos ( ) ;
2012-08-19 22:46:58 +10:00
struct ea_list * ea_list ;
2021-02-10 10:13:46 +00:00
NTSTATUS status = get_ea_list_from_fsp ( mem_ctx ,
2021-02-10 10:26:53 +00:00
fsp ,
2021-02-10 10:13:46 +00:00
& total_ea_len ,
& ea_list ) ;
2012-08-19 22:46:58 +10:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
return ;
}
2004-04-06 14:24:13 +00:00
for ( ; ea_list ; ea_list = ea_list - > next ) {
if ( strequal ( & unix_ea_name [ 5 ] , ea_list - > ea . name ) ) {
DEBUG ( 10 , ( " canonicalize_ea_name: %s -> %s \n " ,
& unix_ea_name [ 5 ] , ea_list - > ea . name ) ) ;
2011-05-03 13:52:06 -07:00
strlcpy ( & unix_ea_name [ 5 ] , ea_list - > ea . name , sizeof ( fstring ) - 5 ) ;
2004-04-06 14:24:13 +00:00
break ;
}
}
}
2004-03-31 02:20:16 +00:00
/****************************************************************************
Set or delete an extended attribute .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2009-06-25 14:16:46 -07:00
NTSTATUS set_ea ( connection_struct * conn , files_struct * fsp ,
2020-12-14 12:15:48 -08:00
struct ea_list * ea_list )
2004-03-31 02:20:16 +00:00
{
2011-11-15 17:29:59 -08:00
NTSTATUS status ;
2016-03-18 21:58:20 -07:00
bool posix_pathnames = false ;
2009-06-25 14:16:46 -07:00
2004-03-31 02:20:16 +00:00
if ( ! lp_ea_support ( SNUM ( conn ) ) ) {
return NT_STATUS_EAS_NOT_SUPPORTED ;
}
2021-06-15 15:42:33 -07:00
if ( fsp = = NULL ) {
return NT_STATUS_INVALID_HANDLE ;
}
2020-12-14 10:14:46 -08:00
posix_pathnames = ( fsp - > fsp_name - > flags & SMB_FILENAME_POSIX_PATH ) ;
2016-03-18 21:58:20 -07:00
2021-05-20 12:02:22 -07:00
status = refuse_symlink_fsp ( fsp ) ;
2016-01-05 11:33:48 -08:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
2020-10-27 21:12:22 +01:00
status = check_access_fsp ( fsp , FILE_WRITE_EA ) ;
2011-11-15 17:29:59 -08:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
2010-11-23 15:59:33 -08:00
}
2012-08-19 22:46:58 +10:00
/* Setting EAs on streams isn't supported. */
2022-02-11 09:59:16 +01:00
if ( fsp_is_alternate_stream ( fsp ) ) {
2012-08-19 22:46:58 +10:00
return NT_STATUS_INVALID_PARAMETER ;
}
2013-07-09 15:52:47 -07:00
/*
* Filter out invalid Windows EA names - before
* we set * any * of them .
*/
2016-03-18 21:58:20 -07:00
if ( ! posix_pathnames & & ea_list_has_invalid_name ( ea_list ) ) {
2013-07-09 15:52:47 -07:00
return STATUS_INVALID_EA_NAME ;
}
2005-03-22 02:23:52 +00:00
for ( ; ea_list ; ea_list = ea_list - > next ) {
2005-03-22 02:14:38 +00:00
int ret ;
fstring unix_ea_name ;
2004-03-31 02:20:16 +00:00
2022-09-26 10:27:19 +02:00
/*
* Complementing the forward mapping from POSIX EAs to
* Windows EAs in get_ea_list_from_fsp ( ) , here we map in the
* opposite direction from Windows EAs to the ' user ' namespace
* of POSIX EAs . Hence , all POSIX EA names the we set here must
* start with a ' user . ' prefix .
*/
fstrcpy ( unix_ea_name , " user. " ) ;
2005-03-22 02:14:38 +00:00
fstrcat ( unix_ea_name , ea_list - > ea . name ) ;
2004-04-06 14:24:13 +00:00
2021-02-10 10:26:53 +00:00
canonicalize_ea_name ( fsp , unix_ea_name ) ;
2004-03-31 02:20:16 +00:00
2005-09-12 21:27:48 +00:00
DEBUG ( 10 , ( " set_ea: ea_name %s ealen = %u \n " , unix_ea_name , ( unsigned int ) ea_list - > ea . value . length ) ) ;
2004-03-31 02:20:16 +00:00
2005-03-22 02:14:38 +00:00
if ( samba_private_attr_name ( unix_ea_name ) ) {
DEBUG ( 10 , ( " set_ea: ea name %s is a private Samba name. \n " , unix_ea_name ) ) ;
return NT_STATUS_ACCESS_DENIED ;
2004-03-31 02:20:16 +00:00
}
2005-03-22 02:14:38 +00:00
if ( ea_list - > ea . value . length = = 0 ) {
/* Remove the attribute. */
2021-03-11 13:42:31 -08:00
DBG_DEBUG ( " deleting ea name %s on "
" file %s by file descriptor. \n " ,
unix_ea_name , fsp_str_dbg ( fsp ) ) ;
ret = SMB_VFS_FREMOVEXATTR ( fsp , unix_ea_name ) ;
2004-03-31 02:20:16 +00:00
# ifdef ENOATTR
2005-03-22 02:14:38 +00:00
/* Removing a non existent attribute always succeeds. */
if ( ret = = - 1 & & errno = = ENOATTR ) {
DEBUG ( 10 , ( " set_ea: deleting ea name %s didn't exist - succeeding by default. \n " ,
unix_ea_name ) ) ;
ret = 0 ;
}
2004-03-31 02:20:16 +00:00
# endif
} else {
2021-02-16 18:49:19 +00:00
DEBUG ( 10 , ( " set_ea: setting ea name %s on file "
" %s by file descriptor. \n " ,
unix_ea_name , fsp_str_dbg ( fsp ) ) ) ;
ret = SMB_VFS_FSETXATTR ( fsp , unix_ea_name ,
ea_list - > ea . value . data , ea_list - > ea . value . length , 0 ) ;
2004-03-31 02:20:16 +00:00
}
2005-03-22 02:14:38 +00:00
if ( ret = = - 1 ) {
2004-04-30 07:53:52 +00:00
# ifdef ENOTSUP
2005-03-22 02:14:38 +00:00
if ( errno = = ENOTSUP ) {
return NT_STATUS_EAS_NOT_SUPPORTED ;
}
2004-04-30 07:53:52 +00:00
# endif
2005-03-22 02:14:38 +00:00
return map_nt_error_from_unix ( errno ) ;
}
2004-03-31 02:20:16 +00:00
2005-03-22 02:14:38 +00:00
}
2004-03-31 02:20:16 +00:00
return NT_STATUS_OK ;
}
2005-03-22 02:14:38 +00:00
2005-03-31 00:36:22 +00:00
/****************************************************************************
Read a list of EA names and data from an incoming data buffer . Create an ea_list with them .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2022-03-21 12:29:26 -06:00
struct ea_list * read_ea_list ( TALLOC_CTX * ctx , const char * pdata , size_t data_size )
2005-03-31 00:36:22 +00:00
{
struct ea_list * ea_list_head = NULL ;
size_t offset = 0 ;
size_t bytes_used = 0 ;
while ( offset < data_size ) {
struct ea_list * eal = read_ea_list_entry ( ctx , pdata + offset , data_size - offset , & bytes_used ) ;
if ( ! eal ) {
return NULL ;
}
2016-02-05 11:32:18 +01:00
DLIST_ADD_END ( ea_list_head , eal ) ;
2005-03-31 00:36:22 +00:00
offset + = bytes_used ;
2005-03-18 01:55:30 +00:00
}
return ea_list_head ;
}
2005-03-18 02:32:35 +00:00
/****************************************************************************
Count the total EA size needed .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static size_t ea_list_size ( struct ea_list * ealist )
{
fstring dos_ea_name ;
struct ea_list * listp ;
size_t ret = 0 ;
for ( listp = ealist ; listp ; listp = listp - > next ) {
push_ascii_fstring ( dos_ea_name , listp - > ea . name ) ;
ret + = 4 + strlen ( dos_ea_name ) + 1 + listp - > ea . value . length ;
}
/* Add on 4 for total length. */
if ( ret ) {
ret + = 4 ;
}
return ret ;
}
/****************************************************************************
Return a union of EA ' s from a file list and a list of names .
2005-03-22 02:14:38 +00:00
The TALLOC context for the two lists * MUST * be identical as we steal
2005-03-22 17:48:41 +00:00
memory from one list to add to another . JRA .
2005-03-18 02:32:35 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static struct ea_list * ea_list_union ( struct ea_list * name_list , struct ea_list * file_list , size_t * total_ea_len )
{
struct ea_list * nlistp , * flistp ;
2005-03-22 02:14:38 +00:00
for ( nlistp = name_list ; nlistp ; nlistp = nlistp - > next ) {
for ( flistp = file_list ; flistp ; flistp = flistp - > next ) {
2005-03-18 02:32:35 +00:00
if ( strequal ( nlistp - > ea . name , flistp - > ea . name ) ) {
break ;
}
}
2005-03-22 02:14:38 +00:00
if ( flistp ) {
/* Copy the data from this entry. */
nlistp - > ea . flags = flistp - > ea . flags ;
nlistp - > ea . value = flistp - > ea . value ;
} else {
/* Null entry. */
nlistp - > ea . flags = 0 ;
ZERO_STRUCT ( nlistp - > ea . value ) ;
2005-03-18 02:32:35 +00:00
}
}
2005-03-22 02:14:38 +00:00
* total_ea_len = ea_list_size ( name_list ) ;
return name_list ;
2005-03-18 02:32:35 +00:00
}
2002-01-10 02:41:15 +00:00
/****************************************************************************
Return the filetype for UNIX extensions .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2015-04-26 16:02:55 -07:00
static uint32_t unix_filetype ( mode_t mode )
2002-01-10 02:41:15 +00:00
{
if ( S_ISREG ( mode ) )
return UNIX_TYPE_FILE ;
else if ( S_ISDIR ( mode ) )
return UNIX_TYPE_DIR ;
# ifdef S_ISLNK
else if ( S_ISLNK ( mode ) )
return UNIX_TYPE_SYMLINK ;
# endif
# ifdef S_ISCHR
else if ( S_ISCHR ( mode ) )
return UNIX_TYPE_CHARDEV ;
# endif
# ifdef S_ISBLK
else if ( S_ISBLK ( mode ) )
return UNIX_TYPE_BLKDEV ;
# endif
# ifdef S_ISFIFO
else if ( S_ISFIFO ( mode ) )
return UNIX_TYPE_FIFO ;
# endif
# ifdef S_ISSOCK
else if ( S_ISSOCK ( mode ) )
return UNIX_TYPE_SOCKET ;
# endif
2008-12-01 17:35:19 +01:00
DEBUG ( 0 , ( " unix_filetype: unknown filetype %u \n " , ( unsigned ) mode ) ) ;
2002-01-10 02:41:15 +00:00
return UNIX_TYPE_UNKNOWN ;
}
/****************************************************************************
2002-07-15 10:35:28 +00:00
Map wire perms onto standard UNIX permissions . Obey share restrictions .
2002-01-10 02:41:15 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2020-02-04 15:28:16 +02:00
NTSTATUS unix_perms_from_wire ( connection_struct * conn ,
const SMB_STRUCT_STAT * psbuf ,
uint32_t perms ,
enum perm_type ptype ,
mode_t * ret_perms )
2002-01-10 02:41:15 +00:00
{
2002-07-15 10:35:28 +00:00
mode_t ret = 0 ;
2007-01-31 19:26:46 +00:00
if ( perms = = SMB_MODE_NO_CHANGE ) {
if ( ! VALID_STAT ( * psbuf ) ) {
return NT_STATUS_INVALID_PARAMETER ;
} else {
2009-05-14 15:34:42 +02:00
* ret_perms = psbuf - > st_ex_mode ;
2007-01-31 19:26:46 +00:00
return NT_STATUS_OK ;
}
}
2002-07-15 10:35:28 +00:00
2018-11-09 07:55:40 +01:00
ret = wire_perms_to_unix ( perms ) ;
2002-07-15 10:35:28 +00:00
2013-08-21 12:03:25 -07:00
if ( ptype = = PERM_NEW_FILE ) {
/*
* " create mask " / " force create mode " are
* only applied to new files , not existing ones .
*/
2007-01-31 19:26:46 +00:00
ret & = lp_create_mask ( SNUM ( conn ) ) ;
/* Add in force bits */
ret | = lp_force_create_mode ( SNUM ( conn ) ) ;
2013-08-21 12:03:25 -07:00
} else if ( ptype = = PERM_NEW_DIR ) {
/*
* " directory mask " / " force directory mode " are
* only applied to new directories , not existing ones .
*/
2014-02-02 14:59:30 +01:00
ret & = lp_directory_mask ( SNUM ( conn ) ) ;
2002-07-15 10:35:28 +00:00
/* Add in force bits */
2014-02-03 14:48:28 +13:00
ret | = lp_force_directory_mode ( SNUM ( conn ) ) ;
2002-07-15 10:35:28 +00:00
}
2007-01-31 19:26:46 +00:00
* ret_perms = ret ;
return NT_STATUS_OK ;
2002-01-10 02:41:15 +00:00
}
1996-05-04 07:50:46 +00:00
/****************************************************************************
2001-11-12 01:00:54 +00:00
Get a level dependent lanman2 dir entry .
1996-05-04 07:50:46 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-11-12 01:00:54 +00:00
2009-08-07 08:55:35 +02:00
struct smbd_dirptr_lanman2_state {
connection_struct * conn ;
uint32_t info_level ;
bool check_mangled_names ;
2021-11-05 16:53:26 -07:00
bool case_sensitive ;
2009-08-07 08:55:35 +02:00
} ;
static bool smbd_dirptr_lanman2_match_fn ( TALLOC_CTX * ctx ,
void * private_data ,
const char * dname ,
const char * mask ,
char * * _fname )
{
struct smbd_dirptr_lanman2_state * state =
( struct smbd_dirptr_lanman2_state * ) private_data ;
bool ok ;
char mangled_name [ 13 ] ; /* mangled 8.3 name. */
bool got_match ;
const char * fname ;
/* Mangle fname if it's an illegal name. */
if ( mangle_must_mangle ( dname , state - > conn - > params ) ) {
2014-08-26 16:39:56 -07:00
/*
* Slow path - ensure we can push the original name as UCS2 . If
* not , then just don ' t return this name .
*/
NTSTATUS status ;
size_t ret_len = 0 ;
size_t len = ( strlen ( dname ) + 2 ) * 4 ; /* Allow enough space. */
uint8_t * tmp = talloc_array ( talloc_tos ( ) ,
2015-05-02 21:01:14 -07:00
uint8_t ,
2014-08-26 16:39:56 -07:00
len ) ;
status = srvstr_push ( NULL ,
FLAGS2_UNICODE_STRINGS ,
tmp ,
dname ,
len ,
STR_TERMINATE ,
& ret_len ) ;
TALLOC_FREE ( tmp ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return false ;
}
2009-08-07 08:55:35 +02:00
ok = name_to_8_3 ( dname , mangled_name ,
true , state - > conn - > params ) ;
if ( ! ok ) {
return false ;
}
fname = mangled_name ;
} else {
fname = dname ;
}
2023-06-16 13:53:25 +02:00
got_match = mask_match ( fname , mask ,
state - > case_sensitive ) ;
2009-08-07 08:55:35 +02:00
if ( ! got_match & & state - > check_mangled_names & &
! mangle_is_8_3 ( fname , false , state - > conn - > params ) ) {
/*
* It turns out that NT matches wildcards against
* both long * and * short names . This may explain some
2023-07-18 11:30:18 +02:00
* of the wildcard weirdness from old DOS clients
2009-08-07 08:55:35 +02:00
* that some people have been seeing . . . . JRA .
*/
/* Force the mangling into 8.3. */
ok = name_to_8_3 ( fname , mangled_name ,
false , state - > conn - > params ) ;
if ( ! ok ) {
return false ;
}
2023-06-16 13:53:25 +02:00
got_match = mask_match ( mangled_name , mask ,
state - > case_sensitive ) ;
2009-08-07 08:55:35 +02:00
}
if ( ! got_match ) {
return false ;
}
* _fname = talloc_strdup ( ctx , fname ) ;
if ( * _fname = = NULL ) {
return false ;
}
return true ;
}
2023-01-02 16:19:12 +01:00
static uint32_t get_dirent_ea_size ( uint32_t mode , files_struct * fsp )
{
if ( ! ( mode & FILE_ATTRIBUTE_REPARSE_POINT ) ) {
unsigned ea_size = estimate_ea_size ( fsp ) ;
return ea_size ;
}
return IO_REPARSE_TAG_DFS ;
}
2014-08-26 11:36:41 -07:00
static NTSTATUS smbd_marshall_dir_entry ( TALLOC_CTX * ctx ,
2009-08-06 12:15:51 +02:00
connection_struct * conn ,
uint16_t flags2 ,
uint32_t info_level ,
struct ea_list * name_list ,
bool check_mangled_names ,
bool requires_resume_key ,
uint32_t mode ,
const char * fname ,
const struct smb_filename * smb_fname ,
2010-04-29 13:40:25 -07:00
int space_remaining ,
2009-08-14 13:23:19 +02:00
uint8_t align ,
bool do_pad ,
2009-08-06 12:15:51 +02:00
char * base_data ,
char * * ppdata ,
char * end_data ,
uint64_t * last_entry_off )
1996-05-04 07:50:46 +00:00
{
2001-11-12 01:00:54 +00:00
char * p , * q , * pdata = * ppdata ;
2009-08-06 12:15:51 +02:00
uint32_t reskey = 0 ;
uint64_t file_size = 0 ;
2008-10-14 01:59:36 +02:00
uint64_t allocation_size = 0 ;
2019-06-28 10:12:44 +02:00
uint64_t file_id = 0 ;
2014-08-25 17:05:47 -07:00
size_t len = 0 ;
2015-02-23 11:17:59 +00:00
struct timespec mdate_ts = { 0 } ;
struct timespec adate_ts = { 0 } ;
struct timespec cdate_ts = { 0 } ;
struct timespec create_date_ts = { 0 } ;
2006-08-24 16:44:00 +00:00
time_t mdate = ( time_t ) 0 , adate = ( time_t ) 0 , create_date = ( time_t ) 0 ;
2001-11-12 01:00:54 +00:00
char * nameptr ;
2005-03-08 23:03:38 +00:00
char * last_entry_ptr ;
2007-10-18 17:40:25 -07:00
bool was_8_3 ;
2010-04-29 13:40:25 -07:00
int off ;
int pad = 0 ;
2014-08-25 17:11:58 -07:00
NTSTATUS status ;
2014-11-26 15:21:36 +01:00
struct readdir_attr_data * readdir_attr_data = NULL ;
2023-01-02 16:19:12 +01:00
uint32_t ea_size ;
2009-08-07 08:55:35 +02:00
2011-04-29 11:57:02 +10:00
if ( ! ( mode & FILE_ATTRIBUTE_DIRECTORY ) ) {
2009-08-07 08:55:35 +02:00
file_size = get_file_size_stat ( & smb_fname - > st ) ;
}
allocation_size = SMB_VFS_GET_ALLOC_SIZE ( conn , NULL , & smb_fname - > st ) ;
2006-04-08 05:00:04 +00:00
2021-05-13 17:01:47 +02:00
/*
* Skip SMB_VFS_FREADDIR_ATTR if the directory entry is a symlink or
* a DFS symlink .
*/
if ( smb_fname - > fsp ! = NULL & &
! ( mode & FILE_ATTRIBUTE_REPARSE_POINT ) ) {
status = SMB_VFS_FREADDIR_ATTR ( smb_fname - > fsp ,
ctx ,
& readdir_attr_data ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
if ( ! NT_STATUS_EQUAL ( NT_STATUS_NOT_SUPPORTED ,
status ) ) {
return status ;
}
2014-11-26 15:21:36 +01:00
}
}
2019-06-29 14:18:13 +02:00
file_id = SMB_VFS_FS_FILE_ID ( conn , & smb_fname - > st ) ;
2010-05-20 11:36:47 -07:00
2009-08-07 08:55:35 +02:00
mdate_ts = smb_fname - > st . st_ex_mtime ;
adate_ts = smb_fname - > st . st_ex_atime ;
2009-08-12 13:00:54 -07:00
create_date_ts = get_create_timespec ( conn , NULL , smb_fname ) ;
cdate_ts = get_change_timespec ( conn , NULL , smb_fname ) ;
2009-07-08 12:24:03 -07:00
2009-08-07 08:55:35 +02:00
if ( lp_dos_filetime_resolution ( SNUM ( conn ) ) ) {
dos_filetime_timespec ( & create_date_ts ) ;
dos_filetime_timespec ( & mdate_ts ) ;
dos_filetime_timespec ( & adate_ts ) ;
2009-08-10 15:07:53 -07:00
dos_filetime_timespec ( & cdate_ts ) ;
2001-11-12 01:00:54 +00:00
}
1996-05-04 07:50:46 +00:00
2009-08-07 08:55:35 +02:00
create_date = convert_timespec_to_time_t ( create_date_ts ) ;
mdate = convert_timespec_to_time_t ( mdate_ts ) ;
adate = convert_timespec_to_time_t ( adate_ts ) ;
2009-08-14 13:23:19 +02:00
/* align the record */
2010-04-29 13:40:25 -07:00
SMB_ASSERT ( align > = 1 ) ;
off = ( int ) PTR_DIFF ( pdata , base_data ) ;
2009-08-14 13:23:19 +02:00
pad = ( off + ( align - 1 ) ) & ~ ( align - 1 ) ;
pad - = off ;
2010-05-13 15:59:09 -07:00
if ( pad & & pad > space_remaining ) {
DEBUG ( 9 , ( " smbd_marshall_dir_entry: out of space "
" for padding (wanted %u, had %d) \n " ,
( unsigned int ) pad ,
space_remaining ) ) ;
2014-08-26 11:36:41 -07:00
return STATUS_MORE_ENTRIES ; /* Not finished - just out of space */
2010-05-13 15:59:09 -07:00
}
2009-08-14 13:23:19 +02:00
off + = pad ;
/* initialize padding to 0 */
2009-11-03 11:19:24 -08:00
if ( pad ) {
memset ( pdata , 0 , pad ) ;
}
2009-08-14 13:23:19 +02:00
space_remaining - = pad ;
2010-04-29 13:40:25 -07:00
DEBUG ( 10 , ( " smbd_marshall_dir_entry: space_remaining = %d \n " ,
space_remaining ) ) ;
2009-08-14 13:23:19 +02:00
pdata + = pad ;
2001-11-12 01:00:54 +00:00
p = pdata ;
2005-03-08 23:03:38 +00:00
last_entry_ptr = p ;
1996-05-04 07:50:46 +00:00
2009-08-14 13:23:19 +02:00
pad = 0 ;
off = 0 ;
2001-11-12 01:00:54 +00:00
switch ( info_level ) {
2009-08-06 12:15:51 +02:00
case SMB_FIND_INFO_STANDARD :
2009-11-03 11:22:19 -08:00
DEBUG ( 10 , ( " smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD \n " ) ) ;
2009-08-06 12:15:51 +02:00
if ( requires_resume_key ) {
SIVAL ( p , 0 , reskey ) ;
p + = 4 ;
}
srv_put_dos_date2 ( p , 0 , create_date ) ;
srv_put_dos_date2 ( p , 4 , adate ) ;
srv_put_dos_date2 ( p , 8 , mdate ) ;
2015-05-02 21:01:14 -07:00
SIVAL ( p , 12 , ( uint32_t ) file_size ) ;
SIVAL ( p , 16 , ( uint32_t ) allocation_size ) ;
2009-08-06 12:15:51 +02:00
SSVAL ( p , 20 , mode ) ;
p + = 23 ;
nameptr = p ;
if ( flags2 & FLAGS2_UNICODE_STRINGS ) {
p + = ucs2_align ( base_data , p , 0 ) ;
}
2014-08-25 17:11:58 -07:00
status = srvstr_push ( base_data , flags2 , p ,
2009-08-06 12:15:51 +02:00
fname , PTR_DIFF ( end_data , p ) ,
2014-08-25 17:11:58 -07:00
STR_TERMINATE , & len ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2014-08-26 11:36:41 -07:00
return status ;
2014-08-25 17:11:58 -07:00
}
2009-08-06 12:15:51 +02:00
if ( flags2 & FLAGS2_UNICODE_STRINGS ) {
if ( len > 2 ) {
SCVAL ( nameptr , - 1 , len - 2 ) ;
2004-04-10 20:02:46 +00:00
} else {
2009-08-06 12:15:51 +02:00
SCVAL ( nameptr , - 1 , 0 ) ;
2004-04-10 20:02:46 +00:00
}
2009-08-06 12:15:51 +02:00
} else {
if ( len > 1 ) {
SCVAL ( nameptr , - 1 , len - 1 ) ;
2004-04-10 20:02:46 +00:00
} else {
2009-08-06 12:15:51 +02:00
SCVAL ( nameptr , - 1 , 0 ) ;
2004-04-10 20:02:46 +00:00
}
2009-08-06 12:15:51 +02:00
}
p + = len ;
break ;
1996-05-04 07:50:46 +00:00
2009-08-06 12:15:51 +02:00
case SMB_FIND_EA_SIZE :
2009-11-03 11:22:19 -08:00
DEBUG ( 10 , ( " smbd_marshall_dir_entry: SMB_FIND_EA_SIZE \n " ) ) ;
2009-08-06 12:15:51 +02:00
if ( requires_resume_key ) {
SIVAL ( p , 0 , reskey ) ;
p + = 4 ;
}
srv_put_dos_date2 ( p , 0 , create_date ) ;
srv_put_dos_date2 ( p , 4 , adate ) ;
srv_put_dos_date2 ( p , 8 , mdate ) ;
2015-05-02 21:01:14 -07:00
SIVAL ( p , 12 , ( uint32_t ) file_size ) ;
SIVAL ( p , 16 , ( uint32_t ) allocation_size ) ;
2009-08-06 12:15:51 +02:00
SSVAL ( p , 20 , mode ) ;
2005-03-22 02:14:38 +00:00
{
2023-01-02 16:19:12 +01:00
ea_size = estimate_ea_size ( smb_fname - > fsp ) ;
2009-08-06 12:15:51 +02:00
SIVAL ( p , 22 , ea_size ) ; /* Extended attributes */
}
p + = 27 ;
nameptr = p - 1 ;
2014-08-25 17:11:58 -07:00
status = srvstr_push ( base_data , flags2 ,
2009-08-06 12:15:51 +02:00
p , fname , PTR_DIFF ( end_data , p ) ,
2014-08-25 17:11:58 -07:00
STR_TERMINATE | STR_NOALIGN , & len ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2014-08-26 11:36:41 -07:00
return status ;
2014-08-25 17:11:58 -07:00
}
2009-08-06 12:15:51 +02:00
if ( flags2 & FLAGS2_UNICODE_STRINGS ) {
if ( len > 2 ) {
len - = 2 ;
} else {
len = 0 ;
2005-03-22 02:14:38 +00:00
}
2009-08-06 12:15:51 +02:00
} else {
if ( len > 1 ) {
len - = 1 ;
2005-03-22 02:14:38 +00:00
} else {
2009-08-06 12:15:51 +02:00
len = 0 ;
2005-03-22 02:14:38 +00:00
}
}
2009-08-06 12:15:51 +02:00
SCVAL ( nameptr , 0 , len ) ;
p + = len ;
SCVAL ( p , 0 , 0 ) ; p + = 1 ; /* Extra zero byte ? - why.. */
break ;
case SMB_FIND_EA_LIST :
{
struct ea_list * file_list = NULL ;
size_t ea_len = 0 ;
2005-03-18 01:55:30 +00:00
2009-11-03 11:22:19 -08:00
DEBUG ( 10 , ( " smbd_marshall_dir_entry: SMB_FIND_EA_LIST \n " ) ) ;
2009-08-06 12:15:51 +02:00
if ( ! name_list ) {
2014-08-26 11:36:41 -07:00
return NT_STATUS_INVALID_PARAMETER ;
2009-08-06 12:15:51 +02:00
}
if ( requires_resume_key ) {
SIVAL ( p , 0 , reskey ) ;
2001-11-12 01:00:54 +00:00
p + = 4 ;
2009-08-06 12:15:51 +02:00
}
srv_put_dos_date2 ( p , 0 , create_date ) ;
srv_put_dos_date2 ( p , 4 , adate ) ;
srv_put_dos_date2 ( p , 8 , mdate ) ;
2015-05-02 21:01:14 -07:00
SIVAL ( p , 12 , ( uint32_t ) file_size ) ;
SIVAL ( p , 16 , ( uint32_t ) allocation_size ) ;
2009-08-06 12:15:51 +02:00
SSVAL ( p , 20 , mode ) ;
p + = 22 ; /* p now points to the EA area. */
2021-02-08 17:38:54 +00:00
status = get_ea_list_from_fsp ( ctx ,
2021-01-29 18:54:20 +00:00
smb_fname - > fsp ,
2012-08-19 22:46:58 +10:00
& ea_len , & file_list ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
file_list = NULL ;
}
2009-08-06 12:15:51 +02:00
name_list = ea_list_union ( name_list , file_list , & ea_len ) ;
/* We need to determine if this entry will fit in the space available. */
/* Max string size is 255 bytes. */
if ( PTR_DIFF ( p + 255 + ea_len , pdata ) > space_remaining ) {
2010-04-29 13:40:25 -07:00
DEBUG ( 9 , ( " smbd_marshall_dir_entry: out of space "
" (wanted %u, had %d) \n " ,
( unsigned int ) PTR_DIFF ( p + 255 + ea_len , pdata ) ,
space_remaining ) ) ;
2014-08-26 11:36:41 -07:00
return STATUS_MORE_ENTRIES ; /* Not finished - just out of space */
2009-08-06 12:15:51 +02:00
}
/* Push the ea_data followed by the name. */
p + = fill_ea_buffer ( ctx , p , space_remaining , conn , name_list ) ;
nameptr = p ;
2014-08-25 17:11:58 -07:00
status = srvstr_push ( base_data , flags2 ,
2009-08-06 12:15:51 +02:00
p + 1 , fname , PTR_DIFF ( end_data , p + 1 ) ,
2014-08-25 17:11:58 -07:00
STR_TERMINATE | STR_NOALIGN , & len ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2014-08-26 11:36:41 -07:00
return status ;
2014-08-25 17:11:58 -07:00
}
2009-08-06 12:15:51 +02:00
if ( flags2 & FLAGS2_UNICODE_STRINGS ) {
if ( len > 2 ) {
len - = 2 ;
} else {
len = 0 ;
2004-04-10 20:02:46 +00:00
}
2009-08-06 12:15:51 +02:00
} else {
if ( len > 1 ) {
len - = 1 ;
2005-06-02 06:19:02 +00:00
} else {
2009-08-06 12:15:51 +02:00
len = 0 ;
2001-11-12 01:00:54 +00:00
}
2009-08-06 12:15:51 +02:00
}
SCVAL ( nameptr , 0 , len ) ;
p + = len + 1 ;
SCVAL ( p , 0 , 0 ) ; p + = 1 ; /* Extra zero byte ? - why.. */
break ;
}
1996-05-04 07:50:46 +00:00
2009-08-06 12:15:51 +02:00
case SMB_FIND_FILE_BOTH_DIRECTORY_INFO :
2009-11-03 11:22:19 -08:00
DEBUG ( 10 , ( " smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO \n " ) ) ;
2009-08-06 12:15:51 +02:00
was_8_3 = mangle_is_8_3 ( fname , True , conn - > params ) ;
p + = 4 ;
SIVAL ( p , 0 , reskey ) ; p + = 4 ;
2019-11-30 21:29:07 +01:00
put_long_date_full_timespec ( conn - > ts_res , p , & create_date_ts ) ; p + = 8 ;
put_long_date_full_timespec ( conn - > ts_res , p , & adate_ts ) ; p + = 8 ;
put_long_date_full_timespec ( conn - > ts_res , p , & mdate_ts ) ; p + = 8 ;
put_long_date_full_timespec ( conn - > ts_res , p , & cdate_ts ) ; p + = 8 ;
2009-08-06 12:15:51 +02:00
SOFF_T ( p , 0 , file_size ) ; p + = 8 ;
SOFF_T ( p , 0 , allocation_size ) ; p + = 8 ;
2009-12-15 18:03:47 -08:00
SIVAL ( p , 0 , mode ) ; p + = 4 ;
2009-08-06 12:15:51 +02:00
q = p ; p + = 4 ; /* q is placeholder for name length. */
2023-01-02 16:19:12 +01:00
ea_size = get_dirent_ea_size ( mode , smb_fname - > fsp ) ;
SIVAL ( p , 0 , ea_size ) ;
2013-08-18 07:34:31 -07:00
p + = 4 ;
2009-08-06 12:15:51 +02:00
/* Clear the short name buffer. This is
* IMPORTANT as not doing so will trigger
* a Win2k client bug . JRA .
*/
if ( ! was_8_3 & & check_mangled_names ) {
char mangled_name [ 13 ] ; /* mangled 8.3 name. */
if ( ! name_to_8_3 ( fname , mangled_name , True ,
conn - > params ) ) {
/* Error - mangle failed ! */
memset ( mangled_name , ' \0 ' , 12 ) ;
}
mangled_name [ 12 ] = 0 ;
2014-08-25 17:11:58 -07:00
status = srvstr_push ( base_data , flags2 ,
2009-08-06 12:15:51 +02:00
p + 2 , mangled_name , 24 ,
2014-08-25 17:11:58 -07:00
STR_UPPER | STR_UNICODE , & len ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2014-08-26 11:36:41 -07:00
return status ;
2014-08-25 17:11:58 -07:00
}
2009-08-06 12:15:51 +02:00
if ( len < 24 ) {
memset ( p + 2 + len , ' \0 ' , 24 - len ) ;
2004-04-10 20:02:46 +00:00
}
2009-08-06 12:15:51 +02:00
SSVAL ( p , 0 , len ) ;
} else {
memset ( p , ' \0 ' , 26 ) ;
}
p + = 2 + 24 ;
2014-08-25 17:11:58 -07:00
status = srvstr_push ( base_data , flags2 , p ,
2009-08-06 12:15:51 +02:00
fname , PTR_DIFF ( end_data , p ) ,
2014-08-25 17:11:58 -07:00
STR_TERMINATE_ASCII , & len ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2014-08-26 11:36:41 -07:00
return status ;
2014-08-25 17:11:58 -07:00
}
2009-08-06 12:15:51 +02:00
SIVAL ( q , 0 , len ) ;
p + = len ;
2009-08-14 13:23:19 +02:00
2009-08-06 12:15:51 +02:00
len = PTR_DIFF ( p , pdata ) ;
2009-08-14 13:23:19 +02:00
pad = ( len + ( align - 1 ) ) & ~ ( align - 1 ) ;
/*
* offset to the next entry , the caller
* will overwrite it for the last entry
* that ' s why we always include the padding
*/
SIVAL ( pdata , 0 , pad ) ;
/*
* set padding to zero
*/
if ( do_pad ) {
memset ( p , 0 , pad - len ) ;
p = pdata + pad ;
} else {
p = pdata + len ;
}
2009-08-06 12:15:51 +02:00
break ;
1996-05-04 07:50:46 +00:00
2009-08-06 12:15:51 +02:00
case SMB_FIND_FILE_DIRECTORY_INFO :
2009-11-03 11:22:19 -08:00
DEBUG ( 10 , ( " smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO \n " ) ) ;
2009-08-06 12:15:51 +02:00
p + = 4 ;
SIVAL ( p , 0 , reskey ) ; p + = 4 ;
2019-11-30 21:29:07 +01:00
put_long_date_full_timespec ( conn - > ts_res , p , & create_date_ts ) ; p + = 8 ;
put_long_date_full_timespec ( conn - > ts_res , p , & adate_ts ) ; p + = 8 ;
put_long_date_full_timespec ( conn - > ts_res , p , & mdate_ts ) ; p + = 8 ;
put_long_date_full_timespec ( conn - > ts_res , p , & cdate_ts ) ; p + = 8 ;
2009-08-06 12:15:51 +02:00
SOFF_T ( p , 0 , file_size ) ; p + = 8 ;
SOFF_T ( p , 0 , allocation_size ) ; p + = 8 ;
2009-12-15 18:03:47 -08:00
SIVAL ( p , 0 , mode ) ; p + = 4 ;
2014-08-25 17:11:58 -07:00
status = srvstr_push ( base_data , flags2 ,
2009-08-06 12:15:51 +02:00
p + 4 , fname , PTR_DIFF ( end_data , p + 4 ) ,
2014-08-25 17:11:58 -07:00
STR_TERMINATE_ASCII , & len ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2014-08-26 11:36:41 -07:00
return status ;
2014-08-25 17:11:58 -07:00
}
2009-08-06 12:15:51 +02:00
SIVAL ( p , 0 , len ) ;
p + = 4 + len ;
2009-08-14 13:23:19 +02:00
2009-08-06 12:15:51 +02:00
len = PTR_DIFF ( p , pdata ) ;
2009-08-14 13:23:19 +02:00
pad = ( len + ( align - 1 ) ) & ~ ( align - 1 ) ;
/*
* offset to the next entry , the caller
* will overwrite it for the last entry
* that ' s why we always include the padding
*/
SIVAL ( pdata , 0 , pad ) ;
/*
* set padding to zero
*/
if ( do_pad ) {
memset ( p , 0 , pad - len ) ;
p = pdata + pad ;
} else {
p = pdata + len ;
}
2009-08-06 12:15:51 +02:00
break ;
1996-05-04 07:50:46 +00:00
2009-08-06 12:15:51 +02:00
case SMB_FIND_FILE_FULL_DIRECTORY_INFO :
2009-11-03 11:22:19 -08:00
DEBUG ( 10 , ( " smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO \n " ) ) ;
2009-08-06 12:15:51 +02:00
p + = 4 ;
SIVAL ( p , 0 , reskey ) ; p + = 4 ;
2019-11-30 21:29:07 +01:00
put_long_date_full_timespec ( conn - > ts_res , p , & create_date_ts ) ; p + = 8 ;
put_long_date_full_timespec ( conn - > ts_res , p , & adate_ts ) ; p + = 8 ;
put_long_date_full_timespec ( conn - > ts_res , p , & mdate_ts ) ; p + = 8 ;
put_long_date_full_timespec ( conn - > ts_res , p , & cdate_ts ) ; p + = 8 ;
2009-08-06 12:15:51 +02:00
SOFF_T ( p , 0 , file_size ) ; p + = 8 ;
SOFF_T ( p , 0 , allocation_size ) ; p + = 8 ;
2009-12-15 18:03:47 -08:00
SIVAL ( p , 0 , mode ) ; p + = 4 ;
2009-08-06 12:15:51 +02:00
q = p ; p + = 4 ; /* q is placeholder for name length. */
2023-01-02 16:19:12 +01:00
ea_size = get_dirent_ea_size ( mode , smb_fname - > fsp ) ;
SIVAL ( p , 0 , ea_size ) ;
2017-10-09 12:06:29 +02:00
p + = 4 ;
2014-08-25 17:11:58 -07:00
status = srvstr_push ( base_data , flags2 , p ,
2009-08-06 12:15:51 +02:00
fname , PTR_DIFF ( end_data , p ) ,
2014-08-25 17:11:58 -07:00
STR_TERMINATE_ASCII , & len ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2014-08-26 11:36:41 -07:00
return status ;
2014-08-25 17:11:58 -07:00
}
2009-08-06 12:15:51 +02:00
SIVAL ( q , 0 , len ) ;
p + = len ;
len = PTR_DIFF ( p , pdata ) ;
2009-08-14 13:23:19 +02:00
pad = ( len + ( align - 1 ) ) & ~ ( align - 1 ) ;
/*
* offset to the next entry , the caller
* will overwrite it for the last entry
* that ' s why we always include the padding
*/
SIVAL ( pdata , 0 , pad ) ;
/*
* set padding to zero
*/
if ( do_pad ) {
memset ( p , 0 , pad - len ) ;
p = pdata + pad ;
} else {
p = pdata + len ;
}
2009-08-06 12:15:51 +02:00
break ;
2003-08-18 21:38:33 +00:00
2009-08-06 12:15:51 +02:00
case SMB_FIND_FILE_NAMES_INFO :
2009-11-03 11:22:19 -08:00
DEBUG ( 10 , ( " smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO \n " ) ) ;
2009-08-06 12:15:51 +02:00
p + = 4 ;
SIVAL ( p , 0 , reskey ) ; p + = 4 ;
p + = 4 ;
/* this must *not* be null terminated or w2k gets in a loop trying to set an
acl on a dir ( tridge ) */
2014-08-25 17:11:58 -07:00
status = srvstr_push ( base_data , flags2 , p ,
2009-08-06 12:15:51 +02:00
fname , PTR_DIFF ( end_data , p ) ,
2014-08-25 17:11:58 -07:00
STR_TERMINATE_ASCII , & len ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2014-08-26 11:36:41 -07:00
return status ;
2014-08-25 17:11:58 -07:00
}
2009-08-06 12:15:51 +02:00
SIVAL ( p , - 4 , len ) ;
p + = len ;
2009-08-14 13:23:19 +02:00
2009-08-06 12:15:51 +02:00
len = PTR_DIFF ( p , pdata ) ;
2009-08-14 13:23:19 +02:00
pad = ( len + ( align - 1 ) ) & ~ ( align - 1 ) ;
/*
* offset to the next entry , the caller
* will overwrite it for the last entry
* that ' s why we always include the padding
*/
SIVAL ( pdata , 0 , pad ) ;
/*
* set padding to zero
*/
if ( do_pad ) {
memset ( p , 0 , pad - len ) ;
p = pdata + pad ;
} else {
p = pdata + len ;
}
2009-08-06 12:15:51 +02:00
break ;
case SMB_FIND_ID_FULL_DIRECTORY_INFO :
2009-11-03 11:22:19 -08:00
DEBUG ( 10 , ( " smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO \n " ) ) ;
2009-08-06 12:15:51 +02:00
p + = 4 ;
SIVAL ( p , 0 , reskey ) ; p + = 4 ;
2019-11-30 21:29:07 +01:00
put_long_date_full_timespec ( conn - > ts_res , p , & create_date_ts ) ; p + = 8 ;
put_long_date_full_timespec ( conn - > ts_res , p , & adate_ts ) ; p + = 8 ;
put_long_date_full_timespec ( conn - > ts_res , p , & mdate_ts ) ; p + = 8 ;
put_long_date_full_timespec ( conn - > ts_res , p , & cdate_ts ) ; p + = 8 ;
2009-08-06 12:15:51 +02:00
SOFF_T ( p , 0 , file_size ) ; p + = 8 ;
SOFF_T ( p , 0 , allocation_size ) ; p + = 8 ;
2009-12-15 18:03:47 -08:00
SIVAL ( p , 0 , mode ) ; p + = 4 ;
2009-08-06 12:15:51 +02:00
q = p ; p + = 4 ; /* q is placeholder for name length. */
2023-01-02 16:19:12 +01:00
ea_size = get_dirent_ea_size ( mode , smb_fname - > fsp ) ;
SIVAL ( p , 0 , ea_size ) ;
2013-08-18 07:34:31 -07:00
p + = 4 ;
2009-08-06 12:15:51 +02:00
SIVAL ( p , 0 , 0 ) ; p + = 4 ; /* Unknown - reserved ? */
2019-06-28 10:12:44 +02:00
SBVAL ( p , 0 , file_id ) ; p + = 8 ;
2014-08-25 17:11:58 -07:00
status = srvstr_push ( base_data , flags2 , p ,
2009-08-06 12:15:51 +02:00
fname , PTR_DIFF ( end_data , p ) ,
2014-08-25 17:11:58 -07:00
STR_TERMINATE_ASCII , & len ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2014-08-26 11:36:41 -07:00
return status ;
2014-08-25 17:11:58 -07:00
}
2009-08-06 12:15:51 +02:00
SIVAL ( q , 0 , len ) ;
p + = len ;
2009-08-14 13:23:19 +02:00
2009-08-06 12:15:51 +02:00
len = PTR_DIFF ( p , pdata ) ;
2009-08-14 13:23:19 +02:00
pad = ( len + ( align - 1 ) ) & ~ ( align - 1 ) ;
/*
* offset to the next entry , the caller
* will overwrite it for the last entry
* that ' s why we always include the padding
*/
SIVAL ( pdata , 0 , pad ) ;
/*
* set padding to zero
*/
if ( do_pad ) {
memset ( p , 0 , pad - len ) ;
p = pdata + pad ;
} else {
p = pdata + len ;
}
2009-08-06 12:15:51 +02:00
break ;
case SMB_FIND_ID_BOTH_DIRECTORY_INFO :
2009-11-03 11:22:19 -08:00
DEBUG ( 10 , ( " smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO \n " ) ) ;
2009-08-06 12:15:51 +02:00
was_8_3 = mangle_is_8_3 ( fname , True , conn - > params ) ;
p + = 4 ;
SIVAL ( p , 0 , reskey ) ; p + = 4 ;
2019-11-30 21:29:07 +01:00
put_long_date_full_timespec ( conn - > ts_res , p , & create_date_ts ) ; p + = 8 ;
put_long_date_full_timespec ( conn - > ts_res , p , & adate_ts ) ; p + = 8 ;
put_long_date_full_timespec ( conn - > ts_res , p , & mdate_ts ) ; p + = 8 ;
put_long_date_full_timespec ( conn - > ts_res , p , & cdate_ts ) ; p + = 8 ;
2009-08-06 12:15:51 +02:00
SOFF_T ( p , 0 , file_size ) ; p + = 8 ;
SOFF_T ( p , 0 , allocation_size ) ; p + = 8 ;
2009-12-15 18:03:47 -08:00
SIVAL ( p , 0 , mode ) ; p + = 4 ;
2009-08-06 12:15:51 +02:00
q = p ; p + = 4 ; /* q is placeholder for name length */
2023-01-02 16:21:50 +01:00
if ( readdir_attr_data & &
readdir_attr_data - > type = = RDATTR_AAPL ) {
2014-11-26 15:21:36 +01:00
/*
* OS X specific SMB2 extension negotiated via
* AAPL create context : return max_access in
* ea_size field .
*/
2023-01-02 16:21:50 +01:00
ea_size = readdir_attr_data - > attr_data . aapl . max_access ;
2013-08-18 07:34:31 -07:00
} else {
2023-01-02 16:21:50 +01:00
ea_size = get_dirent_ea_size ( mode , smb_fname - > fsp ) ;
2009-08-06 12:15:51 +02:00
}
2023-01-02 16:21:50 +01:00
SIVAL ( p , 0 , ea_size ) ; /* Extended attributes */
2013-08-18 07:34:31 -07:00
p + = 4 ;
2014-11-26 15:21:36 +01:00
if ( readdir_attr_data & &
readdir_attr_data - > type = = RDATTR_AAPL ) {
/*
* OS X specific SMB2 extension negotiated via
* AAPL create context : return resource fork
* length and compressed FinderInfo in
* shortname field .
*
* According to documentation short_name_len
* should be 0 , but on the wire behaviour
* shows its set to 24 by clients .
*/
SSVAL ( p , 0 , 24 ) ;
/* Resourefork length */
SBVAL ( p , 2 , readdir_attr_data - > attr_data . aapl . rfork_size ) ;
/* Compressed FinderInfo */
memcpy ( p + 10 , & readdir_attr_data - > attr_data . aapl . finder_info , 16 ) ;
} else if ( ! was_8_3 & & check_mangled_names ) {
2009-08-06 12:15:51 +02:00
char mangled_name [ 13 ] ; /* mangled 8.3 name. */
if ( ! name_to_8_3 ( fname , mangled_name , True ,
conn - > params ) ) {
/* Error - mangle failed ! */
memset ( mangled_name , ' \0 ' , 12 ) ;
2004-04-10 20:02:46 +00:00
}
2009-08-06 12:15:51 +02:00
mangled_name [ 12 ] = 0 ;
2014-08-25 17:11:58 -07:00
status = srvstr_push ( base_data , flags2 ,
2009-08-06 12:15:51 +02:00
p + 2 , mangled_name , 24 ,
2014-08-25 17:11:58 -07:00
STR_UPPER | STR_UNICODE , & len ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2014-08-26 11:36:41 -07:00
return status ;
2014-08-25 17:11:58 -07:00
}
2009-08-06 12:15:51 +02:00
SSVAL ( p , 0 , len ) ;
if ( len < 24 ) {
memset ( p + 2 + len , ' \0 ' , 24 - len ) ;
2003-08-18 21:54:42 +00:00
}
2009-08-06 12:15:51 +02:00
SSVAL ( p , 0 , len ) ;
} else {
2014-11-26 15:21:36 +01:00
/* Clear the short name buffer. This is
* IMPORTANT as not doing so will trigger
* a Win2k client bug . JRA .
*/
2009-08-06 12:15:51 +02:00
memset ( p , ' \0 ' , 26 ) ;
}
p + = 26 ;
2014-11-26 15:21:36 +01:00
/* Reserved ? */
if ( readdir_attr_data & &
readdir_attr_data - > type = = RDATTR_AAPL ) {
/*
* OS X specific SMB2 extension negotiated via
* AAPL create context : return UNIX mode in
* reserved field .
*/
uint16_t aapl_mode = ( uint16_t ) readdir_attr_data - > attr_data . aapl . unix_mode ;
SSVAL ( p , 0 , aapl_mode ) ;
} else {
SSVAL ( p , 0 , 0 ) ;
}
p + = 2 ;
2019-06-28 10:12:44 +02:00
SBVAL ( p , 0 , file_id ) ; p + = 8 ;
2014-08-25 17:11:58 -07:00
status = srvstr_push ( base_data , flags2 , p ,
2009-08-06 12:15:51 +02:00
fname , PTR_DIFF ( end_data , p ) ,
2014-08-25 17:11:58 -07:00
STR_TERMINATE_ASCII , & len ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2014-08-26 11:36:41 -07:00
return status ;
2014-08-25 17:11:58 -07:00
}
2009-08-06 12:15:51 +02:00
SIVAL ( q , 0 , len ) ;
p + = len ;
2009-08-14 13:23:19 +02:00
2009-08-06 12:15:51 +02:00
len = PTR_DIFF ( p , pdata ) ;
2009-08-14 13:23:19 +02:00
pad = ( len + ( align - 1 ) ) & ~ ( align - 1 ) ;
/*
* offset to the next entry , the caller
* will overwrite it for the last entry
* that ' s why we always include the padding
*/
SIVAL ( pdata , 0 , pad ) ;
/*
* set padding to zero
*/
if ( do_pad ) {
memset ( p , 0 , pad - len ) ;
p = pdata + pad ;
} else {
p = pdata + len ;
}
2009-08-06 12:15:51 +02:00
break ;
2003-08-18 21:54:42 +00:00
2009-08-06 12:15:51 +02:00
/* CIFS UNIX Extension. */
2002-01-10 02:41:15 +00:00
2009-08-06 12:15:51 +02:00
case SMB_FIND_FILE_UNIX :
case SMB_FIND_FILE_UNIX_INFO2 :
p + = 4 ;
SIVAL ( p , 0 , reskey ) ; p + = 4 ; /* Used for continuing search. */
2002-01-10 02:41:15 +00:00
2009-08-06 12:15:51 +02:00
/* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2002-01-10 02:41:15 +00:00
2009-08-06 12:15:51 +02:00
if ( info_level = = SMB_FIND_FILE_UNIX ) {
2009-11-03 11:22:19 -08:00
DEBUG ( 10 , ( " smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX \n " ) ) ;
2009-08-06 12:15:51 +02:00
p = store_file_unix_basic ( conn , p ,
NULL , & smb_fname - > st ) ;
2014-08-25 17:11:58 -07:00
status = srvstr_push ( base_data , flags2 , p ,
2009-08-06 12:15:51 +02:00
fname , PTR_DIFF ( end_data , p ) ,
2014-08-25 17:11:58 -07:00
STR_TERMINATE , & len ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2014-08-26 11:36:41 -07:00
return status ;
2014-08-25 17:11:58 -07:00
}
2009-08-06 12:15:51 +02:00
} else {
2009-11-03 11:22:19 -08:00
DEBUG ( 10 , ( " smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2 \n " ) ) ;
2009-08-06 12:15:51 +02:00
p = store_file_unix_basic_info2 ( conn , p ,
NULL , & smb_fname - > st ) ;
nameptr = p ;
p + = 4 ;
2014-08-25 17:11:58 -07:00
status = srvstr_push ( base_data , flags2 , p , fname ,
PTR_DIFF ( end_data , p ) , 0 , & len ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2014-08-26 11:36:41 -07:00
return status ;
2014-08-25 17:11:58 -07:00
}
2009-08-06 12:15:51 +02:00
SIVAL ( nameptr , 0 , len ) ;
}
2002-01-10 02:41:15 +00:00
2009-08-06 12:15:51 +02:00
p + = len ;
2002-07-15 10:35:28 +00:00
2009-08-06 12:15:51 +02:00
len = PTR_DIFF ( p , pdata ) ;
2009-08-14 13:23:19 +02:00
pad = ( len + ( align - 1 ) ) & ~ ( align - 1 ) ;
/*
* offset to the next entry , the caller
* will overwrite it for the last entry
* that ' s why we always include the padding
*/
SIVAL ( pdata , 0 , pad ) ;
/*
* set padding to zero
*/
if ( do_pad ) {
memset ( p , 0 , pad - len ) ;
p = pdata + pad ;
} else {
p = pdata + len ;
}
2009-08-06 12:15:51 +02:00
/* End of SMB_QUERY_FILE_UNIX_BASIC */
2002-01-10 02:41:15 +00:00
2009-08-06 12:15:51 +02:00
break ;
2002-01-10 02:41:15 +00:00
2022-06-17 15:06:29 -06:00
/* SMB2 UNIX Extension. */
case SMB2_FILE_POSIX_INFORMATION :
{
2023-09-27 10:48:35 +02:00
struct smb3_file_posix_information info = { } ;
uint8_t buf [ sizeof ( info ) ] ;
struct ndr_push ndr = {
. data = buf ,
. alloc_size = sizeof ( buf ) ,
. fixed_buf_size = true ,
} ;
enum ndr_err_code ndr_err ;
2022-06-17 15:06:29 -06:00
p + = 4 ;
SIVAL ( p , 0 , reskey ) ; p + = 4 ;
2023-09-27 17:43:33 +02:00
DBG_DEBUG ( " SMB2_FILE_POSIX_INFORMATION \n " ) ;
2022-06-17 15:06:29 -06:00
if ( ! ( conn - > sconn - > using_smb2 ) ) {
return NT_STATUS_INVALID_LEVEL ;
}
2023-09-27 10:48:35 +02:00
smb3_file_posix_information_init (
conn , & smb_fname - > st , 0 , mode , & info ) ;
ndr_err = ndr_push_smb3_file_posix_information (
& ndr , NDR_SCALARS | NDR_BUFFERS , & info ) ;
if ( ! NDR_ERR_CODE_IS_SUCCESS ( ndr_err ) ) {
return NT_STATUS_INSUFFICIENT_RESOURCES ;
2022-06-17 15:06:29 -06:00
}
2023-09-27 10:48:35 +02:00
memcpy ( p , buf , ndr . offset ) ;
p + = ndr . offset ;
2022-06-17 15:06:29 -06:00
nameptr = p ;
p + = 4 ;
status = srvstr_push ( base_data , flags2 , p , fname ,
PTR_DIFF ( end_data , p ) , 0 , & len ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
SIVAL ( nameptr , 0 , len ) ;
p + = len ;
len = PTR_DIFF ( p , pdata ) ;
pad = ( len + ( align - 1 ) ) & ~ ( align - 1 ) ;
/*
* offset to the next entry , the caller
* will overwrite it for the last entry
* that ' s why we always include the padding
*/
SIVAL ( pdata , 0 , pad ) ;
break ;
}
2009-08-06 12:15:51 +02:00
default :
2014-08-26 11:36:41 -07:00
return NT_STATUS_INVALID_LEVEL ;
2001-11-12 01:00:54 +00:00
}
1996-05-04 07:50:46 +00:00
2001-11-12 01:00:54 +00:00
if ( PTR_DIFF ( p , pdata ) > space_remaining ) {
2010-04-29 13:40:25 -07:00
DEBUG ( 9 , ( " smbd_marshall_dir_entry: out of space "
" (wanted %u, had %d) \n " ,
( unsigned int ) PTR_DIFF ( p , pdata ) ,
space_remaining ) ) ;
2014-08-26 11:36:41 -07:00
return STATUS_MORE_ENTRIES ; /* Not finished - just out of space */
2001-11-12 01:00:54 +00:00
}
1996-05-04 07:50:46 +00:00
2005-03-08 23:03:38 +00:00
/* Setup the last entry pointer, as an offset from base_data */
* last_entry_off = PTR_DIFF ( last_entry_ptr , base_data ) ;
2001-11-12 01:00:54 +00:00
/* Advance the data pointer to the next slot */
* ppdata = p ;
1999-12-13 13:27:58 +00:00
2014-08-26 11:36:41 -07:00
return NT_STATUS_OK ;
1996-05-04 07:50:46 +00:00
}
1998-07-29 00:27:23 +00:00
2014-08-26 14:49:37 -07:00
NTSTATUS smbd_dirptr_lanman2_entry ( TALLOC_CTX * ctx ,
2009-08-14 13:23:19 +02:00
connection_struct * conn ,
struct dptr_struct * dirptr ,
2015-04-26 16:02:55 -07:00
uint16_t flags2 ,
2009-08-14 13:23:19 +02:00
const char * path_mask ,
2015-04-26 16:02:55 -07:00
uint32_t dirtype ,
2009-08-14 13:23:19 +02:00
int info_level ,
int requires_resume_key ,
bool dont_descend ,
bool ask_sharemode ,
2018-03-15 15:50:41 +01:00
bool get_dosmode ,
2009-08-14 13:23:19 +02:00
uint8_t align ,
bool do_pad ,
char * * ppdata ,
char * base_data ,
char * end_data ,
int space_remaining ,
2018-03-15 19:03:59 +01:00
struct smb_filename * * _smb_fname ,
2009-08-14 13:23:19 +02:00
int * _last_entry_off ,
2016-12-22 14:53:17 +01:00
struct ea_list * name_list ,
struct file_id * file_id )
2009-08-06 12:15:51 +02:00
{
const char * p ;
const char * mask = NULL ;
uint32_t mode = 0 ;
char * fname = NULL ;
struct smb_filename * smb_fname = NULL ;
struct smbd_dirptr_lanman2_state state ;
bool ok ;
uint64_t last_entry_off = 0 ;
2014-08-26 11:36:41 -07:00
NTSTATUS status ;
2016-11-17 14:22:41 +01:00
enum mangled_names_options mangled_names ;
bool marshall_with_83_names ;
mangled_names = lp_mangled_names ( conn - > params ) ;
2009-08-06 12:15:51 +02:00
ZERO_STRUCT ( state ) ;
state . conn = conn ;
state . info_level = info_level ;
2016-11-17 14:22:41 +01:00
if ( mangled_names ! = MANGLED_NAMES_NO ) {
state . check_mangled_names = true ;
}
2021-11-08 11:25:26 -08:00
state . case_sensitive = dptr_case_sensitive ( dirptr ) ;
2009-08-06 12:15:51 +02:00
p = strrchr_m ( path_mask , ' / ' ) ;
if ( p ! = NULL ) {
if ( p [ 1 ] = = ' \0 ' ) {
mask = " *.* " ;
} else {
mask = p + 1 ;
}
} else {
mask = path_mask ;
}
ok = smbd_dirptr_get_entry ( ctx ,
dirptr ,
mask ,
dirtype ,
dont_descend ,
ask_sharemode ,
2018-03-15 16:08:11 +01:00
get_dosmode ,
2009-08-06 12:15:51 +02:00
smbd_dirptr_lanman2_match_fn ,
& state ,
& fname ,
& smb_fname ,
2023-06-09 15:05:07 +02:00
& mode ) ;
2009-08-06 12:15:51 +02:00
if ( ! ok ) {
2014-08-26 14:49:37 -07:00
return NT_STATUS_END_OF_FILE ;
2009-08-06 12:15:51 +02:00
}
2016-11-17 14:22:41 +01:00
marshall_with_83_names = ( mangled_names = = MANGLED_NAMES_YES ) ;
2014-08-26 11:36:41 -07:00
status = smbd_marshall_dir_entry ( ctx ,
2009-08-06 12:15:51 +02:00
conn ,
flags2 ,
info_level ,
name_list ,
2016-11-17 14:22:41 +01:00
marshall_with_83_names ,
2009-08-06 12:15:51 +02:00
requires_resume_key ,
mode ,
fname ,
smb_fname ,
space_remaining ,
2009-08-14 13:23:19 +02:00
align ,
do_pad ,
2009-08-06 12:15:51 +02:00
base_data ,
ppdata ,
end_data ,
& last_entry_off ) ;
2015-06-03 17:07:46 +02:00
if ( NT_STATUS_EQUAL ( status , NT_STATUS_ILLEGAL_CHARACTER ) ) {
DEBUG ( 1 , ( " Conversion error: illegal character: %s \n " ,
smb_fname_str_dbg ( smb_fname ) ) ) ;
}
2016-12-22 14:53:17 +01:00
if ( file_id ! = NULL ) {
* file_id = vfs_file_id_from_sbuf ( conn , & smb_fname - > st ) ;
}
2023-06-09 14:44:58 +02:00
if ( NT_STATUS_EQUAL ( status , STATUS_MORE_ENTRIES ) ) {
2023-06-09 14:52:11 +02:00
smbd_dirptr_push_overflow ( dirptr , & fname , & smb_fname , mode ) ;
2023-06-09 14:44:58 +02:00
}
if ( ! NT_STATUS_IS_OK ( status ) ) {
2018-03-15 19:03:59 +01:00
TALLOC_FREE ( smb_fname ) ;
TALLOC_FREE ( fname ) ;
2014-08-26 14:49:37 -07:00
return status ;
2009-08-06 12:15:51 +02:00
}
2018-03-15 18:57:50 +01:00
2023-06-09 15:22:31 +02:00
smbd_dirptr_set_last_name_sent ( dirptr , & smb_fname - > base_name ) ;
2018-03-15 19:03:59 +01:00
if ( _smb_fname ! = NULL ) {
2021-07-14 15:00:13 -07:00
/*
* smb_fname is already talloc ' ed off ctx .
* We just need to make sure we don ' t return
* any stream_name , and replace base_name
* with fname in case base_name got mangled .
* This allows us to preserve any smb_fname - > fsp
* for asynchronous handle lookups .
*/
TALLOC_FREE ( smb_fname - > stream_name ) ;
2023-06-09 15:22:31 +02:00
/*
* smbd_dirptr_set_last_name_sent ( ) above consumed
* base_name
*/
2021-07-14 15:00:13 -07:00
smb_fname - > base_name = talloc_strdup ( smb_fname , fname ) ;
if ( smb_fname - > base_name = = NULL ) {
2018-03-15 19:03:59 +01:00
TALLOC_FREE ( smb_fname ) ;
TALLOC_FREE ( fname ) ;
return NT_STATUS_NO_MEMORY ;
}
2021-07-14 15:00:13 -07:00
* _smb_fname = smb_fname ;
} else {
TALLOC_FREE ( smb_fname ) ;
2018-03-15 19:03:59 +01:00
}
TALLOC_FREE ( fname ) ;
2009-08-06 12:15:51 +02:00
* _last_entry_off = last_entry_off ;
2014-08-26 14:49:37 -07:00
return NT_STATUS_OK ;
2009-08-06 12:15:51 +02:00
}
2022-03-21 12:29:26 -06:00
unsigned char * create_volume_objectid ( connection_struct * conn , unsigned char objid [ 16 ] )
2009-08-14 13:23:19 +02:00
{
2022-03-21 12:29:26 -06:00
const struct loadparm_substitution * lp_sub =
loadparm_s3_global_substitution ( ) ;
E_md4hash ( lp_servicename ( talloc_tos ( ) , lp_sub , SNUM ( conn ) ) , objid ) ;
return objid ;
2009-08-14 13:23:19 +02:00
}
2022-03-21 12:29:26 -06:00
static void samba_extended_info_version ( struct smb_extended_info * extended_info )
{
SMB_ASSERT ( extended_info ! = NULL ) ;
1999-12-13 13:27:58 +00:00
2022-03-21 12:29:26 -06:00
extended_info - > samba_magic = SAMBA_EXTENDED_INFO_MAGIC ;
extended_info - > samba_version = ( ( SAMBA_VERSION_MAJOR & 0xff ) < < 24 )
| ( ( SAMBA_VERSION_MINOR & 0xff ) < < 16 )
| ( ( SAMBA_VERSION_RELEASE & 0xff ) < < 8 ) ;
# ifdef SAMBA_VERSION_REVISION
extended_info - > samba_version | = ( tolower ( * SAMBA_VERSION_REVISION ) - ' a ' + 1 ) & 0xff ;
# endif
extended_info - > samba_subversion = 0 ;
# ifdef SAMBA_VERSION_RC_RELEASE
extended_info - > samba_subversion | = ( SAMBA_VERSION_RC_RELEASE & 0xff ) < < 24 ;
# else
# ifdef SAMBA_VERSION_PRE_RELEASE
extended_info - > samba_subversion | = ( SAMBA_VERSION_PRE_RELEASE & 0xff ) < < 16 ;
# endif
# endif
# ifdef SAMBA_VERSION_VENDOR_PATCH
extended_info - > samba_subversion | = ( SAMBA_VERSION_VENDOR_PATCH & 0xffff ) ;
# endif
extended_info - > samba_gitcommitdate = 0 ;
# ifdef SAMBA_VERSION_COMMIT_TIME
unix_to_nt_time ( & extended_info - > samba_gitcommitdate , SAMBA_VERSION_COMMIT_TIME ) ;
# endif
memset ( extended_info - > samba_version_string , 0 ,
sizeof ( extended_info - > samba_version_string ) ) ;
snprintf ( extended_info - > samba_version_string ,
sizeof ( extended_info - > samba_version_string ) ,
" %s " , samba_version_string ( ) ) ;
}
2022-09-12 16:09:50 -07:00
static bool fsinfo_unix_valid_level ( connection_struct * conn ,
2023-11-13 08:04:33 +01:00
struct files_struct * fsp ,
2022-09-12 16:09:50 -07:00
uint16_t info_level )
{
if ( conn - > sconn - > using_smb2 & &
2023-09-18 16:54:05 -07:00
info_level = = SMB2_FS_POSIX_INFORMATION_INTERNAL ) {
2022-09-12 16:09:50 -07:00
return true ;
}
# if defined(SMB1SERVER)
if ( lp_smb1_unix_extensions ( ) & &
info_level = = SMB_QUERY_POSIX_FS_INFO ) {
return true ;
}
# endif
return false ;
}
2023-11-13 07:43:11 +01:00
/*
* fsp is only valid for SMB2 .
*/
2022-03-21 12:29:26 -06:00
NTSTATUS smbd_do_qfsinfo ( struct smbXsrv_connection * xconn ,
connection_struct * conn ,
TALLOC_CTX * mem_ctx ,
uint16_t info_level ,
uint16_t flags2 ,
unsigned int max_data_bytes ,
size_t * fixed_portion ,
2023-11-13 07:43:11 +01:00
struct files_struct * fsp ,
2022-03-21 12:29:26 -06:00
struct smb_filename * fname ,
char * * ppdata ,
int * ret_data_len )
1996-05-04 07:50:46 +00:00
{
2019-10-31 17:51:06 +01:00
const struct loadparm_substitution * lp_sub =
loadparm_s3_global_substitution ( ) ;
2022-03-21 12:29:26 -06:00
char * pdata , * end_data ;
int data_len = 0 ;
size_t len = 0 ;
const char * vname = volume_label ( talloc_tos ( ) , SNUM ( conn ) ) ;
int snum = SNUM ( conn ) ;
const char * fstype = lp_fstype ( SNUM ( conn ) ) ;
const char * filename = NULL ;
const uint64_t bytes_per_sector = 512 ;
uint32_t additional_flags = 0 ;
struct smb_filename smb_fname ;
SMB_STRUCT_STAT st ;
NTSTATUS status = NT_STATUS_OK ;
uint64_t df_ret ;
2022-04-27 19:27:15 +02:00
uint32_t serial ;
2002-07-15 10:35:28 +00:00
2022-03-21 12:29:26 -06:00
if ( fname = = NULL | | fname - > base_name = = NULL ) {
filename = " . " ;
} else {
filename = fname - > base_name ;
2005-03-19 00:31:45 +00:00
}
2002-07-15 10:35:28 +00:00
2022-03-21 12:29:26 -06:00
if ( IS_IPC ( conn ) ) {
if ( info_level ! = SMB_QUERY_CIFS_UNIX_INFO ) {
DEBUG ( 0 , ( " smbd_do_qfsinfo: not an allowed "
" info level (0x%x) on IPC$. \n " ,
( unsigned int ) info_level ) ) ;
return NT_STATUS_ACCESS_DENIED ;
}
2004-09-28 05:33:30 +00:00
}
2009-02-02 21:37:51 -08:00
2022-03-21 12:29:26 -06:00
DEBUG ( 3 , ( " smbd_do_qfsinfo: level = %d \n " , info_level ) ) ;
1997-10-03 20:36:06 +00:00
2022-03-21 12:29:26 -06:00
smb_fname = ( struct smb_filename ) {
. base_name = discard_const_p ( char , filename ) ,
. flags = fname ? fname - > flags : 0 ,
. twrp = fname ? fname - > twrp : 0 ,
} ;
2020-10-15 10:27:23 +02:00
2022-03-21 12:29:26 -06:00
if ( info_level ! = SMB_FS_QUOTA_INFORMATION
& & SMB_VFS_STAT ( conn , & smb_fname ) ! = 0 ) {
DEBUG ( 2 , ( " stat of . failed (%s) \n " , strerror ( errno ) ) ) ;
return map_nt_error_from_unix ( errno ) ;
2007-03-07 22:12:58 +00:00
}
2002-07-15 10:35:28 +00:00
2022-03-21 12:29:26 -06:00
st = smb_fname . st ;
2005-03-22 02:14:38 +00:00
2013-08-02 17:05:58 -07:00
if ( max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes ) {
2022-03-21 12:29:26 -06:00
return NT_STATUS_INVALID_PARAMETER ;
2013-08-02 17:05:58 -07:00
}
2006-07-31 21:11:03 +00:00
* ppdata = ( char * ) SMB_REALLOC (
* ppdata , max_data_bytes + DIR_ENTRY_SAFETY_MARGIN ) ;
2022-03-21 12:29:26 -06:00
if ( * ppdata = = NULL ) {
return NT_STATUS_NO_MEMORY ;
2012-02-29 12:15:12 -08:00
}
2022-03-21 12:29:26 -06:00
pdata = * ppdata ;
memset ( ( char * ) pdata , ' \0 ' , max_data_bytes + DIR_ENTRY_SAFETY_MARGIN ) ;
end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1 ;
2007-09-12 21:48:20 +00:00
2022-03-21 12:29:26 -06:00
* fixed_portion = 0 ;
2002-07-15 10:35:28 +00:00
2022-03-21 12:29:26 -06:00
switch ( info_level ) {
case SMB_INFO_ALLOCATION :
{
uint64_t dfree , dsize , bsize , block_size , sectors_per_unit ;
data_len = 18 ;
df_ret = get_dfree_info ( conn , & smb_fname , & bsize ,
& dfree , & dsize ) ;
if ( df_ret = = ( uint64_t ) - 1 ) {
return map_nt_error_from_unix ( errno ) ;
}
2002-07-15 10:35:28 +00:00
2022-03-21 12:29:26 -06:00
block_size = lp_block_size ( snum ) ;
if ( bsize < block_size ) {
uint64_t factor = block_size / bsize ;
bsize = block_size ;
dsize / = factor ;
dfree / = factor ;
2014-08-26 15:05:24 -07:00
}
2022-03-21 12:29:26 -06:00
if ( bsize > block_size ) {
uint64_t factor = bsize / block_size ;
bsize = block_size ;
dsize * = factor ;
dfree * = factor ;
2014-08-26 15:05:24 -07:00
}
2022-03-21 12:29:26 -06:00
sectors_per_unit = bsize / bytes_per_sector ;
2002-07-15 10:35:28 +00:00
2022-03-21 12:29:26 -06:00
DEBUG ( 5 , ( " smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
cBytesSector = % u , cUnitTotal = % u , cUnitAvail = % d \ n " , (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
( unsigned int ) bytes_per_sector , ( unsigned int ) dsize , ( unsigned int ) dfree ) ) ;
2002-07-15 10:35:28 +00:00
2022-03-21 12:29:26 -06:00
/*
* For large drives , return max values and not modulo .
*/
dsize = MIN ( dsize , UINT32_MAX ) ;
dfree = MIN ( dfree , UINT32_MAX ) ;
2002-07-15 10:35:28 +00:00
2022-03-21 12:29:26 -06:00
SIVAL ( pdata , l1_idFileSystem , st . st_ex_dev ) ;
SIVAL ( pdata , l1_cSectorUnit , sectors_per_unit ) ;
SIVAL ( pdata , l1_cUnit , dsize ) ;
SIVAL ( pdata , l1_cUnitAvail , dfree ) ;
SSVAL ( pdata , l1_cbSector , bytes_per_sector ) ;
break ;
2007-09-07 20:57:01 +00:00
}
1996-05-04 07:50:46 +00:00
2022-03-21 12:29:26 -06:00
case SMB_INFO_VOLUME :
/* Return volume name */
2022-12-12 12:53:22 +01:00
/*
2022-03-21 12:29:26 -06:00
* Add volume serial number - hash of a combination of
* the called hostname and the service name .
*/
2022-04-27 19:27:15 +02:00
serial = generate_volume_serial_number ( lp_sub , snum ) ;
SIVAL ( pdata , 0 , serial ) ;
2022-03-21 12:29:26 -06:00
/*
* Win2k3 and previous mess this up by sending a name length
* one byte short . I believe only older clients ( OS / 2 Win9x ) use
* this call so try fixing this by adding a terminating null to
* the pushed string . The change here was adding the STR_TERMINATE . JRA .
*/
status = srvstr_push (
pdata , flags2 ,
pdata + l2_vol_szVolLabel , vname ,
PTR_DIFF ( end_data , pdata + l2_vol_szVolLabel ) ,
STR_NOALIGN | STR_TERMINATE , & len ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
SCVAL ( pdata , l2_vol_cch , len ) ;
data_len = l2_vol_szVolLabel + len ;
2022-04-27 19:27:15 +02:00
DEBUG ( 5 , ( " smbd_do_qfsinfo : time = %x, namelen = %u, "
" name = %s serial = 0x%04 " PRIx32 " \n " ,
2022-03-21 12:29:26 -06:00
( unsigned ) convert_timespec_to_time_t ( st . st_ex_ctime ) ,
2022-04-27 19:27:15 +02:00
( unsigned ) len , vname , serial ) ) ;
2022-03-21 12:29:26 -06:00
break ;
2001-11-12 01:00:54 +00:00
2022-03-21 12:29:26 -06:00
case SMB_QUERY_FS_ATTRIBUTE_INFO :
case SMB_FS_ATTRIBUTE_INFORMATION :
2002-07-15 10:35:28 +00:00
2022-03-21 12:29:26 -06:00
additional_flags = 0 ;
# if defined(HAVE_SYS_QUOTAS)
additional_flags | = FILE_VOLUME_QUOTAS ;
# endif
2002-07-15 10:35:28 +00:00
2022-03-21 12:29:26 -06:00
if ( lp_nt_acl_support ( SNUM ( conn ) ) ) {
additional_flags | = FILE_PERSISTENT_ACLS ;
2009-11-02 12:15:25 -08:00
}
2002-07-15 10:35:28 +00:00
2022-03-21 12:29:26 -06:00
/* Capabilities are filled in at connection time through STATVFS call */
additional_flags | = conn - > fs_capabilities ;
additional_flags | = lp_parm_int ( conn - > params - > service ,
" share " , " fake_fscaps " ,
0 ) ;
2002-07-15 10:35:28 +00:00
2022-03-21 12:29:26 -06:00
SIVAL ( pdata , 0 , FILE_CASE_PRESERVED_NAMES | FILE_CASE_SENSITIVE_SEARCH |
FILE_SUPPORTS_OBJECT_IDS | FILE_UNICODE_ON_DISK |
additional_flags ) ; /* FS ATTRIBUTES */
2004-09-28 05:33:30 +00:00
2022-03-21 12:29:26 -06:00
SIVAL ( pdata , 4 , 255 ) ; /* Max filename component length */
/* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
and will think we can ' t do long filenames */
status = srvstr_push ( pdata , flags2 , pdata + 12 , fstype ,
PTR_DIFF ( end_data , pdata + 12 ) ,
STR_UNICODE , & len ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
2006-04-10 15:33:04 +00:00
}
2022-03-21 12:29:26 -06:00
SIVAL ( pdata , 8 , len ) ;
data_len = 12 + len ;
if ( max_data_bytes > = 16 & & data_len > max_data_bytes ) {
/* the client only requested a portion of the
file system name */
data_len = max_data_bytes ;
status = STATUS_BUFFER_OVERFLOW ;
2021-11-18 11:48:42 -08:00
}
2022-03-21 12:29:26 -06:00
* fixed_portion = 16 ;
2002-07-15 10:35:28 +00:00
break ;
2005-03-22 02:14:38 +00:00
2022-03-21 12:29:26 -06:00
case SMB_QUERY_FS_LABEL_INFO :
case SMB_FS_LABEL_INFORMATION :
status = srvstr_push ( pdata , flags2 , pdata + 4 , vname ,
PTR_DIFF ( end_data , pdata + 4 ) , 0 , & len ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
data_len = 4 + len ;
SIVAL ( pdata , 0 , len ) ;
break ;
2007-09-12 21:48:20 +00:00
2022-12-12 12:53:22 +01:00
case SMB_QUERY_FS_VOLUME_INFO :
2022-03-21 12:29:26 -06:00
case SMB_FS_VOLUME_INFORMATION :
2022-05-07 20:37:34 +02:00
put_long_date_full_timespec ( TIMESTAMP_SET_NT_OR_BETTER ,
pdata , & st . st_ex_btime ) ;
2022-12-12 12:53:22 +01:00
/*
2022-03-21 12:29:26 -06:00
* Add volume serial number - hash of a combination of
* the called hostname and the service name .
*/
2022-04-27 19:27:15 +02:00
serial = generate_volume_serial_number ( lp_sub , snum ) ;
SIVAL ( pdata , 8 , serial ) ;
2005-01-28 21:01:58 +00:00
2022-03-21 12:29:26 -06:00
/* Max label len is 32 characters. */
status = srvstr_push ( pdata , flags2 , pdata + 18 , vname ,
PTR_DIFF ( end_data , pdata + 18 ) ,
STR_UNICODE , & len ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
2007-09-07 20:57:01 +00:00
}
2022-03-21 12:29:26 -06:00
SIVAL ( pdata , 12 , len ) ;
data_len = 18 + len ;
2002-07-15 10:35:28 +00:00
2022-04-27 19:27:15 +02:00
DEBUG ( 5 , ( " smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO "
" namelen = %d, vol=%s serv=%s "
" serial=0x%04 " PRIx32 " \n " ,
( int ) strlen ( vname ) , vname ,
lp_servicename ( talloc_tos ( ) , lp_sub , snum ) ,
serial ) ) ;
2022-03-21 12:29:26 -06:00
if ( max_data_bytes > = 24 & & data_len > max_data_bytes ) {
/* the client only requested a portion of the
volume label */
data_len = max_data_bytes ;
status = STATUS_BUFFER_OVERFLOW ;
2014-08-26 15:05:24 -07:00
}
2022-03-21 12:29:26 -06:00
* fixed_portion = 24 ;
break ;
2013-08-27 09:06:27 +00:00
2022-03-21 12:29:26 -06:00
case SMB_QUERY_FS_SIZE_INFO :
case SMB_FS_SIZE_INFORMATION :
2002-07-15 10:35:28 +00:00
{
2015-03-12 17:02:56 +01:00
uint64_t dfree , dsize , bsize , block_size , sectors_per_unit ;
2022-03-21 12:29:26 -06:00
data_len = 24 ;
2016-01-14 00:09:36 +02:00
df_ret = get_dfree_info ( conn , & smb_fname , & bsize ,
& dfree , & dsize ) ;
2015-02-16 19:26:24 +01:00
if ( df_ret = = ( uint64_t ) - 1 ) {
2009-07-13 11:54:20 +02:00
return map_nt_error_from_unix ( errno ) ;
2005-03-16 01:41:21 +00:00
}
2003-10-07 00:06:01 +00:00
block_size = lp_block_size ( snum ) ;
if ( bsize < block_size ) {
2008-10-14 01:59:36 +02:00
uint64_t factor = block_size / bsize ;
2003-10-07 00:06:01 +00:00
bsize = block_size ;
dsize / = factor ;
dfree / = factor ;
}
if ( bsize > block_size ) {
2008-10-14 01:59:36 +02:00
uint64_t factor = bsize / block_size ;
2003-10-07 00:06:01 +00:00
bsize = block_size ;
dsize * = factor ;
dfree * = factor ;
}
sectors_per_unit = bsize / bytes_per_sector ;
2022-03-21 12:29:26 -06:00
DEBUG ( 5 , ( " smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
cBytesSector = % u , cUnitTotal = % u , cUnitAvail = % d \ n " , (unsigned int)bsize, (unsigned int)sectors_per_unit,
2003-10-07 00:06:01 +00:00
( unsigned int ) bytes_per_sector , ( unsigned int ) dsize , ( unsigned int ) dfree ) ) ;
2022-03-21 12:29:26 -06:00
SBIG_UINT ( pdata , 0 , dsize ) ;
SBIG_UINT ( pdata , 8 , dfree ) ;
SIVAL ( pdata , 16 , sectors_per_unit ) ;
SIVAL ( pdata , 20 , bytes_per_sector ) ;
* fixed_portion = 24 ;
2002-07-15 10:35:28 +00:00
break ;
}
case SMB_FS_FULL_SIZE_INFORMATION :
{
2015-03-12 17:02:56 +01:00
uint64_t dfree , dsize , bsize , block_size , sectors_per_unit ;
2002-07-15 10:35:28 +00:00
data_len = 32 ;
2016-01-14 00:09:36 +02:00
df_ret = get_dfree_info ( conn , & smb_fname , & bsize ,
& dfree , & dsize ) ;
2015-02-16 19:26:24 +01:00
if ( df_ret = = ( uint64_t ) - 1 ) {
2009-07-13 11:54:20 +02:00
return map_nt_error_from_unix ( errno ) ;
2005-03-16 01:41:21 +00:00
}
2002-07-15 10:35:28 +00:00
block_size = lp_block_size ( snum ) ;
if ( bsize < block_size ) {
2008-10-14 01:59:36 +02:00
uint64_t factor = block_size / bsize ;
2002-07-15 10:35:28 +00:00
bsize = block_size ;
dsize / = factor ;
dfree / = factor ;
}
if ( bsize > block_size ) {
2008-10-14 01:59:36 +02:00
uint64_t factor = bsize / block_size ;
2002-07-15 10:35:28 +00:00
bsize = block_size ;
dsize * = factor ;
dfree * = factor ;
}
sectors_per_unit = bsize / bytes_per_sector ;
2009-07-13 11:54:20 +02:00
DEBUG ( 5 , ( " smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2002-07-15 10:35:28 +00:00
cBytesSector = % u , cUnitTotal = % u , cUnitAvail = % d \ n " , (unsigned int)bsize, (unsigned int)sectors_per_unit,
( unsigned int ) bytes_per_sector , ( unsigned int ) dsize , ( unsigned int ) dfree ) ) ;
SBIG_UINT ( pdata , 0 , dsize ) ; /* Total Allocation units. */
SBIG_UINT ( pdata , 8 , dfree ) ; /* Caller available allocation units. */
SBIG_UINT ( pdata , 16 , dfree ) ; /* Actual available allocation units. */
SIVAL ( pdata , 24 , sectors_per_unit ) ; /* Sectors per allocation unit. */
SIVAL ( pdata , 28 , bytes_per_sector ) ; /* Bytes per sector. */
2013-08-27 09:06:27 +00:00
* fixed_portion = 32 ;
2002-07-15 10:35:28 +00:00
break ;
}
case SMB_QUERY_FS_DEVICE_INFO :
case SMB_FS_DEVICE_INFORMATION :
2010-05-19 21:28:08 -07:00
{
uint32_t characteristics = FILE_DEVICE_IS_MOUNTED ;
if ( ! CAN_WRITE ( conn ) ) {
characteristics | = FILE_READ_ONLY_DEVICE ;
}
2002-07-15 10:35:28 +00:00
data_len = 8 ;
2010-05-19 21:28:08 -07:00
SIVAL ( pdata , 0 , FILE_DEVICE_DISK ) ; /* dev type */
SIVAL ( pdata , 4 , characteristics ) ;
2013-08-27 09:06:27 +00:00
* fixed_portion = 8 ;
2002-07-15 10:35:28 +00:00
break ;
2010-05-19 21:28:08 -07:00
}
2002-07-15 10:35:28 +00:00
2003-05-14 14:38:11 +00:00
# ifdef HAVE_SYS_QUOTAS
2003-05-12 01:20:17 +00:00
case SMB_FS_QUOTA_INFORMATION :
2022-12-12 12:53:22 +01:00
/*
2003-05-12 01:20:17 +00:00
* what we have to send - - metze :
*
* Unknown1 : 24 NULL bytes
2023-07-18 11:30:18 +02:00
* Soft Quota Threshold : 8 bytes seems like uint64_t or so
2008-10-14 01:59:36 +02:00
* Hard Quota Limit : 8 bytes seems like uint64_t or so
2003-05-12 01:20:17 +00:00
* Quota Flags : 2 byte :
* Unknown3 : 6 NULL bytes
*
* 48 bytes total
2022-12-12 12:53:22 +01:00
*
2003-05-12 01:20:17 +00:00
* details for Quota Flags :
2022-12-12 12:53:22 +01:00
*
2003-05-12 01:20:17 +00:00
* 0x0020 Log Limit : log if the user exceeds his Hard Quota
* 0x0010 Log Warn : log if the user exceeds his Soft Quota
* 0x0002 Deny Disk : deny disk access when the user exceeds his Hard Quota
* 0x0001 Enable Quotas : enable quota for this fs
*
*/
{
/* we need to fake up a fsp here,
* because its not send in this call
*/
2023-11-13 07:43:11 +01:00
files_struct tmpfsp ;
2003-05-12 01:20:17 +00:00
SMB_NTQUOTA_STRUCT quotas ;
2009-05-26 21:07:08 +02:00
2023-11-13 07:43:11 +01:00
ZERO_STRUCT ( tmpfsp ) ;
2003-05-12 01:20:17 +00:00
ZERO_STRUCT ( quotas ) ;
2009-05-26 21:07:08 +02:00
2023-11-13 07:43:11 +01:00
tmpfsp . conn = conn ;
tmpfsp . fnum = FNUM_FIELD_INVALID ;
2009-05-26 21:07:08 +02:00
2003-05-12 01:20:17 +00:00
/* access check */
2011-04-05 11:24:39 -07:00
if ( get_current_uid ( conn ) ! = 0 ) {
2013-08-22 15:19:32 +00:00
DEBUG ( 0 , ( " get_user_quota: access_denied "
2008-05-08 16:06:42 +02:00
" service [%s] user [%s] \n " ,
2019-11-07 11:01:05 +01:00
lp_servicename ( talloc_tos ( ) , lp_sub , SNUM ( conn ) ) ,
2011-07-15 15:55:31 +10:00
conn - > session_info - > unix_info - > unix_name ) ) ;
2009-07-14 09:47:46 +02:00
return NT_STATUS_ACCESS_DENIED ;
2003-05-12 01:20:17 +00:00
}
2009-05-26 21:07:08 +02:00
2023-11-13 07:43:11 +01:00
status = vfs_get_ntquota ( & tmpfsp , SMB_USER_FS_QUOTA_TYPE ,
2016-03-29 23:30:23 +03:00
NULL , & quotas ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2019-11-07 11:01:05 +01:00
DEBUG ( 0 , ( " vfs_get_ntquota() failed for service [%s] \n " , lp_servicename ( talloc_tos ( ) , lp_sub , SNUM ( conn ) ) ) ) ;
2016-03-29 23:30:23 +03:00
return status ;
2003-05-12 01:20:17 +00:00
}
data_len = 48 ;
2009-07-13 11:54:20 +02:00
DEBUG ( 10 , ( " SMB_FS_QUOTA_INFORMATION: for service [%s] \n " ,
2019-11-07 11:01:05 +01:00
lp_servicename ( talloc_tos ( ) , lp_sub , SNUM ( conn ) ) ) ) ;
2009-05-26 21:07:08 +02:00
2003-05-12 01:20:17 +00:00
/* Unknown1 24 NULL bytes*/
2008-10-14 01:59:36 +02:00
SBIG_UINT ( pdata , 0 , ( uint64_t ) 0 ) ;
SBIG_UINT ( pdata , 8 , ( uint64_t ) 0 ) ;
SBIG_UINT ( pdata , 16 , ( uint64_t ) 0 ) ;
2009-05-26 21:07:08 +02:00
2003-05-12 01:20:17 +00:00
/* Default Soft Quota 8 bytes */
SBIG_UINT ( pdata , 24 , quotas . softlim ) ;
/* Default Hard Quota 8 bytes */
SBIG_UINT ( pdata , 32 , quotas . hardlim ) ;
2009-05-26 21:07:08 +02:00
2003-05-12 01:20:17 +00:00
/* Quota flag 2 bytes */
SSVAL ( pdata , 40 , quotas . qflags ) ;
2009-05-26 21:07:08 +02:00
2003-05-12 01:20:17 +00:00
/* Unknown3 6 NULL bytes */
SSVAL ( pdata , 42 , 0 ) ;
SIVAL ( pdata , 44 , 0 ) ;
2009-05-26 21:07:08 +02:00
2003-05-12 01:20:17 +00:00
break ;
}
2003-05-14 14:38:11 +00:00
# endif /* HAVE_SYS_QUOTAS */
2002-07-15 10:35:28 +00:00
case SMB_FS_OBJECTID_INFORMATION :
2007-04-23 16:32:24 +00:00
{
unsigned char objid [ 16 ] ;
2008-01-22 11:33:17 +01:00
struct smb_extended_info extended_info ;
2007-04-23 16:32:24 +00:00
memcpy ( pdata , create_volume_objectid ( conn , objid ) , 16 ) ;
2008-01-22 11:33:17 +01:00
samba_extended_info_version ( & extended_info ) ;
SIVAL ( pdata , 16 , extended_info . samba_magic ) ;
SIVAL ( pdata , 20 , extended_info . samba_version ) ;
SIVAL ( pdata , 24 , extended_info . samba_subversion ) ;
SBIG_UINT ( pdata , 28 , extended_info . samba_gitcommitdate ) ;
memcpy ( pdata + 36 , extended_info . samba_version_string , 28 ) ;
2002-07-15 10:35:28 +00:00
data_len = 64 ;
break ;
2007-04-23 16:32:24 +00:00
}
2002-07-15 10:35:28 +00:00
2015-03-13 00:34:58 +01:00
case SMB_FS_SECTOR_SIZE_INFORMATION :
{
data_len = 28 ;
/*
* These values match a physical Windows Server 2012
* share backed by NTFS atop spinning rust .
*/
DEBUG ( 5 , ( " SMB_FS_SECTOR_SIZE_INFORMATION: " ) ) ;
/* logical_bytes_per_sector */
SIVAL ( pdata , 0 , bytes_per_sector ) ;
/* phys_bytes_per_sector_atomic */
SIVAL ( pdata , 4 , bytes_per_sector ) ;
/* phys_bytes_per_sector_perf */
SIVAL ( pdata , 8 , bytes_per_sector ) ;
/* fs_effective_phys_bytes_per_sector_atomic */
SIVAL ( pdata , 12 , bytes_per_sector ) ;
/* flags */
SIVAL ( pdata , 16 , SSINFO_FLAGS_ALIGNED_DEVICE
| SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE ) ;
/* byte_off_sector_align */
SIVAL ( pdata , 20 , 0 ) ;
/* byte_off_partition_align */
SIVAL ( pdata , 24 , 0 ) ;
* fixed_portion = 28 ;
break ;
}
2022-03-21 14:10:24 -06:00
# if defined(WITH_SMB1SERVER)
2002-07-15 10:35:28 +00:00
/*
* Query the version and capabilities of the CIFS UNIX extensions
* in use .
*/
case SMB_QUERY_CIFS_UNIX_INFO :
2007-10-31 14:01:35 -07:00
{
bool large_write = lp_min_receive_file_size ( ) & &
2022-03-07 19:51:06 -08:00
! smb1_srv_is_signing_active ( xconn ) ;
bool large_read = ! smb1_srv_is_signing_active ( xconn ) ;
2007-12-27 16:54:07 -08:00
int encrypt_caps = 0 ;
2007-10-31 14:01:35 -07:00
2022-01-21 14:49:11 -08:00
if ( ! lp_smb1_unix_extensions ( ) ) {
2009-07-13 11:54:20 +02:00
return NT_STATUS_INVALID_LEVEL ;
2006-04-10 15:33:04 +00:00
}
2007-12-27 16:54:07 -08:00
2007-12-27 23:51:03 -08:00
switch ( conn - > encrypt_level ) {
2012-08-17 09:40:52 +02:00
case SMB_SIGNING_OFF :
2007-12-27 16:54:07 -08:00
encrypt_caps = 0 ;
break ;
2015-07-07 17:15:00 +02:00
case SMB_SIGNING_DESIRED :
2012-08-17 09:40:52 +02:00
case SMB_SIGNING_IF_REQUIRED :
case SMB_SIGNING_DEFAULT :
2007-12-27 16:54:07 -08:00
encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP ;
break ;
2012-08-17 09:40:52 +02:00
case SMB_SIGNING_REQUIRED :
2007-12-27 16:54:07 -08:00
encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP |
CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP ;
2007-12-28 00:02:13 -08:00
large_write = false ;
large_read = false ;
2007-12-27 16:54:07 -08:00
break ;
}
2002-07-15 10:35:28 +00:00
data_len = 12 ;
SSVAL ( pdata , 0 , CIFS_UNIX_MAJOR_VERSION ) ;
SSVAL ( pdata , 2 , CIFS_UNIX_MINOR_VERSION ) ;
2007-12-27 10:18:22 -08:00
2022-12-12 12:53:22 +01:00
/* We have POSIX ACLs, pathname, encryption,
2007-12-27 10:18:22 -08:00
* large read / write , and locking capability . */
2008-10-14 01:59:36 +02:00
SBIG_UINT ( pdata , 4 , ( ( uint64_t ) (
2006-04-10 15:33:04 +00:00
CIFS_UNIX_POSIX_ACLS_CAP |
CIFS_UNIX_POSIX_PATHNAMES_CAP |
2007-02-06 21:05:34 +00:00
CIFS_UNIX_FCNTL_LOCKS_CAP |
2007-03-08 18:05:55 +00:00
CIFS_UNIX_EXTATTR_CAP |
2007-05-16 00:07:38 +00:00
CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP |
2007-12-27 16:54:07 -08:00
encrypt_caps |
2007-12-28 00:02:13 -08:00
( large_read ? CIFS_UNIX_LARGE_READ_CAP : 0 ) |
2007-11-01 18:30:02 -07:00
( large_write ?
CIFS_UNIX_LARGE_WRITE_CAP : 0 ) ) ) ) ;
2002-07-15 10:35:28 +00:00
break ;
2007-10-31 14:01:35 -07:00
}
2022-03-21 14:10:24 -06:00
# endif
2002-07-15 10:35:28 +00:00
2005-10-20 17:33:17 +00:00
case SMB_QUERY_POSIX_FS_INFO :
2022-09-12 16:09:50 -07:00
case SMB2_FS_POSIX_INFORMATION_INTERNAL :
2005-10-20 17:33:17 +00:00
{
int rc ;
2022-06-03 14:47:30 +02:00
struct vfs_statvfs_struct svfs ;
2005-10-20 17:33:17 +00:00
2023-11-13 08:04:33 +01:00
if ( ! fsinfo_unix_valid_level ( conn , fsp , info_level ) ) {
2009-07-13 11:54:20 +02:00
return NT_STATUS_INVALID_LEVEL ;
2006-04-10 15:33:04 +00:00
}
2017-06-02 15:26:06 -07:00
rc = SMB_VFS_STATVFS ( conn , & smb_fname , & svfs ) ;
2005-10-20 17:33:17 +00:00
if ( ! rc ) {
data_len = 56 ;
SIVAL ( pdata , 0 , svfs . OptimalTransferSize ) ;
SIVAL ( pdata , 4 , svfs . BlockSize ) ;
SBIG_UINT ( pdata , 8 , svfs . TotalBlocks ) ;
SBIG_UINT ( pdata , 16 , svfs . BlocksAvail ) ;
SBIG_UINT ( pdata , 24 , svfs . UserBlocksAvail ) ;
SBIG_UINT ( pdata , 32 , svfs . TotalFileNodes ) ;
SBIG_UINT ( pdata , 40 , svfs . FreeFileNodes ) ;
SBIG_UINT ( pdata , 48 , svfs . FsIdentifier ) ;
2023-09-07 16:09:38 +12:00
DEBUG ( 5 , ( " smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO successful \n " ) ) ;
2005-10-20 17:33:17 +00:00
# ifdef EOPNOTSUPP
} else if ( rc = = EOPNOTSUPP ) {
2009-07-13 11:54:20 +02:00
return NT_STATUS_INVALID_LEVEL ;
2005-10-20 17:33:17 +00:00
# endif /* EOPNOTSUPP */
} else {
2019-11-07 11:01:05 +01:00
DEBUG ( 0 , ( " vfs_statvfs() failed for service [%s] \n " , lp_servicename ( talloc_tos ( ) , lp_sub , SNUM ( conn ) ) ) ) ;
2009-07-13 11:54:20 +02:00
return NT_STATUS_DOS ( ERRSRV , ERRerror ) ;
2005-10-20 17:33:17 +00:00
}
break ;
}
2007-03-06 00:54:05 +00:00
case SMB_QUERY_POSIX_WHOAMI :
{
uint32_t flags = 0 ;
uint32_t sid_bytes ;
2022-01-02 19:33:07 +01:00
uint32_t i ;
2007-03-06 00:54:05 +00:00
2022-01-21 14:49:11 -08:00
if ( ! lp_smb1_unix_extensions ( ) ) {
2009-07-13 11:54:20 +02:00
return NT_STATUS_INVALID_LEVEL ;
2007-03-06 00:54:05 +00:00
}
if ( max_data_bytes < 40 ) {
2009-07-13 11:54:20 +02:00
return NT_STATUS_BUFFER_TOO_SMALL ;
2007-03-06 00:54:05 +00:00
}
2012-05-01 17:13:34 +10:00
if ( security_session_user_level ( conn - > session_info , NULL ) < SECURITY_USER ) {
2007-03-06 00:54:05 +00:00
flags | = SMB_WHOAMI_GUEST ;
}
/* NOTE: 8 bytes for UID/GID, irrespective of native
* platform size . This matches
* SMB_QUERY_FILE_UNIX_BASIC and friends .
*/
data_len = 4 /* flags */
+ 4 /* flag mask */
+ 8 /* uid */
+ 8 /* gid */
+ 4 /* ngroups */
+ 4 /* num_sids */
+ 4 /* SID bytes */
+ 4 /* pad/reserved */
2011-07-15 14:59:14 +10:00
+ ( conn - > session_info - > unix_token - > ngroups * 8 )
2007-03-06 00:54:05 +00:00
/* groups list */
2011-02-21 10:25:52 +01:00
+ ( conn - > session_info - > security_token - > num_sids *
2007-03-06 00:54:05 +00:00
SID_MAX_SIZE )
/* SID list */ ;
SIVAL ( pdata , 0 , flags ) ;
SIVAL ( pdata , 4 , SMB_WHOAMI_MASK ) ;
2008-06-19 18:36:54 +02:00
SBIG_UINT ( pdata , 8 ,
2011-07-15 14:59:14 +10:00
( uint64_t ) conn - > session_info - > unix_token - > uid ) ;
2008-06-19 18:36:54 +02:00
SBIG_UINT ( pdata , 16 ,
2011-07-15 14:59:14 +10:00
( uint64_t ) conn - > session_info - > unix_token - > gid ) ;
2007-03-06 00:54:05 +00:00
if ( data_len > = max_data_bytes ) {
/* Potential overflow, skip the GIDs and SIDs. */
SIVAL ( pdata , 24 , 0 ) ; /* num_groups */
SIVAL ( pdata , 28 , 0 ) ; /* num_sids */
SIVAL ( pdata , 32 , 0 ) ; /* num_sid_bytes */
SIVAL ( pdata , 36 , 0 ) ; /* reserved */
data_len = 40 ;
break ;
}
2011-07-15 14:59:14 +10:00
SIVAL ( pdata , 24 , conn - > session_info - > unix_token - > ngroups ) ;
2011-02-21 10:25:52 +01:00
SIVAL ( pdata , 28 , conn - > session_info - > security_token - > num_sids ) ;
2007-03-06 00:54:05 +00:00
/* We walk the SID list twice, but this call is fairly
* infrequent , and I don ' t expect that it ' s performance
* sensitive - - jpeach
*/
for ( i = 0 , sid_bytes = 0 ;
2011-02-21 10:25:52 +01:00
i < conn - > session_info - > security_token - > num_sids ; + + i ) {
2007-12-29 22:16:31 +01:00
sid_bytes + = ndr_size_dom_sid (
2011-02-21 10:25:52 +01:00
& conn - > session_info - > security_token - > sids [ i ] ,
2008-06-19 18:36:54 +02:00
0 ) ;
2007-03-06 00:54:05 +00:00
}
/* SID list byte count */
SIVAL ( pdata , 32 , sid_bytes ) ;
/* 4 bytes pad/reserved - must be zero */
SIVAL ( pdata , 36 , 0 ) ;
data_len = 40 ;
/* GID list */
2011-07-15 14:59:14 +10:00
for ( i = 0 ; i < conn - > session_info - > unix_token - > ngroups ; + + i ) {
2007-03-06 00:54:05 +00:00
SBIG_UINT ( pdata , data_len ,
2011-07-15 14:59:14 +10:00
( uint64_t ) conn - > session_info - > unix_token - > groups [ i ] ) ;
2007-03-06 00:54:05 +00:00
data_len + = 8 ;
}
/* SID list */
for ( i = 0 ;
2011-02-21 10:25:52 +01:00
i < conn - > session_info - > security_token - > num_sids ; + + i ) {
2007-12-29 22:16:31 +01:00
int sid_len = ndr_size_dom_sid (
2011-02-21 10:25:52 +01:00
& conn - > session_info - > security_token - > sids [ i ] ,
2008-06-19 18:36:54 +02:00
0 ) ;
2007-03-06 00:54:05 +00:00
2015-08-26 10:52:44 +02:00
sid_linearize ( ( uint8_t * ) ( pdata + data_len ) ,
sid_len ,
2011-02-21 10:25:52 +01:00
& conn - > session_info - > security_token - > sids [ i ] ) ;
2007-03-06 00:54:05 +00:00
data_len + = sid_len ;
}
break ;
}
2002-07-15 10:35:28 +00:00
case SMB_MAC_QUERY_FS_INFO :
/*
* Thursby MAC extension . . . ONLY on NTFS filesystems
* once we do streams then we don ' t need this
*/
2014-01-16 15:58:31 +13:00
if ( strequal ( lp_fstype ( SNUM ( conn ) ) , " NTFS " ) ) {
2002-07-15 10:35:28 +00:00
data_len = 88 ;
SIVAL ( pdata , 84 , 0x100 ) ; /* Don't support mac... */
break ;
}
2017-07-26 17:52:06 +02:00
FALL_THROUGH ;
2002-07-15 10:35:28 +00:00
default :
2009-07-13 11:54:20 +02:00
return NT_STATUS_INVALID_LEVEL ;
}
* ret_data_len = data_len ;
2013-07-05 11:32:27 +02:00
return status ;
2009-07-13 11:54:20 +02:00
}
2022-03-21 12:29:26 -06:00
NTSTATUS smb_set_fsquota ( connection_struct * conn ,
struct smb_request * req ,
files_struct * fsp ,
const DATA_BLOB * qdata )
2016-04-14 12:39:05 +00:00
{
2019-11-07 11:01:05 +01:00
const struct loadparm_substitution * lp_sub =
loadparm_s3_global_substitution ( ) ;
2016-04-14 12:39:05 +00:00
NTSTATUS status ;
SMB_NTQUOTA_STRUCT quotas ;
ZERO_STRUCT ( quotas ) ;
/* access check */
if ( ( get_current_uid ( conn ) ! = 0 ) | | ! CAN_WRITE ( conn ) ) {
2023-08-23 16:36:06 +02:00
DBG_NOTICE ( " access_denied service [%s] user [%s] \n " ,
lp_servicename ( talloc_tos ( ) , lp_sub , SNUM ( conn ) ) ,
conn - > session_info - > unix_info - > unix_name ) ;
2016-04-14 12:39:05 +00:00
return NT_STATUS_ACCESS_DENIED ;
}
if ( ! check_fsp_ntquota_handle ( conn , req ,
fsp ) ) {
2023-08-23 16:36:06 +02:00
DBG_WARNING ( " no valid QUOTA HANDLE \n " ) ;
2016-04-14 12:39:05 +00:00
return NT_STATUS_INVALID_HANDLE ;
}
/* note: normally there're 48 bytes,
* but we didn ' t use the last 6 bytes for now
* - - metze
*/
if ( qdata - > length < 42 ) {
2023-08-23 16:36:06 +02:00
DBG_ERR ( " requires total_data(%zu) >= 42 bytes! \n " ,
qdata - > length ) ;
2016-04-14 12:39:05 +00:00
return NT_STATUS_INVALID_PARAMETER ;
}
/* unknown_1 24 NULL bytes in pdata*/
/* the soft quotas 8 bytes (uint64_t)*/
quotas . softlim = BVAL ( qdata - > data , 24 ) ;
/* the hard quotas 8 bytes (uint64_t)*/
quotas . hardlim = BVAL ( qdata - > data , 32 ) ;
/* quota_flags 2 bytes **/
quotas . qflags = SVAL ( qdata - > data , 40 ) ;
/* unknown_2 6 NULL bytes follow*/
/* now set the quotas */
if ( vfs_set_ntquota ( fsp , SMB_USER_FS_QUOTA_TYPE , NULL , & quotas ) ! = 0 ) {
2023-08-23 16:36:06 +02:00
DBG_WARNING ( " vfs_set_ntquota() failed for service [%s] \n " ,
lp_servicename ( talloc_tos ( ) , lp_sub , SNUM ( conn ) ) ) ;
2016-04-14 12:39:05 +00:00
status = map_nt_error_from_unix ( errno ) ;
} else {
status = NT_STATUS_OK ;
}
return status ;
}
NTSTATUS smbd_do_setfsinfo ( connection_struct * conn ,
struct smb_request * req ,
TALLOC_CTX * mem_ctx ,
uint16_t info_level ,
files_struct * fsp ,
const DATA_BLOB * pdata )
{
switch ( info_level ) {
case SMB_FS_QUOTA_INFORMATION :
{
return smb_set_fsquota ( conn ,
req ,
fsp ,
pdata ) ;
}
default :
break ;
}
return NT_STATUS_INVALID_LEVEL ;
}
2007-02-07 02:39:43 +00:00
/****************************************************************************
Store the FILE_UNIX_BASIC info .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2022-12-28 23:47:42 +01:00
char * store_file_unix_basic ( connection_struct * conn ,
char * pdata ,
files_struct * fsp ,
const SMB_STRUCT_STAT * psbuf )
2007-02-07 02:39:43 +00:00
{
2012-05-11 13:31:36 +02:00
dev_t devno ;
2010-05-20 11:36:47 -07:00
2023-08-23 16:36:06 +02:00
DBG_DEBUG ( " SMB_QUERY_FILE_UNIX_BASIC \n " ) ;
DBG_NOTICE ( " st_mode=%o \n " , ( int ) psbuf - > st_ex_mode ) ;
2007-02-07 02:39:43 +00:00
2009-01-26 15:39:40 -08:00
SOFF_T ( pdata , 0 , get_file_size_stat ( psbuf ) ) ; /* File size 64 Bit */
2007-02-07 02:39:43 +00:00
pdata + = 8 ;
2009-01-26 15:39:40 -08:00
SOFF_T ( pdata , 0 , SMB_VFS_GET_ALLOC_SIZE ( conn , fsp , psbuf ) ) ; /* Number of bytes used on disk - 64 Bit */
2007-02-07 02:39:43 +00:00
pdata + = 8 ;
2019-11-30 21:29:07 +01:00
put_long_date_full_timespec ( TIMESTAMP_SET_NT_OR_BETTER , pdata , & psbuf - > st_ex_ctime ) ; /* Change Time 64 Bit */
put_long_date_full_timespec ( TIMESTAMP_SET_NT_OR_BETTER , pdata + 8 , & psbuf - > st_ex_atime ) ; /* Last access time 64 Bit */
put_long_date_full_timespec ( TIMESTAMP_SET_NT_OR_BETTER , pdata + 16 , & psbuf - > st_ex_mtime ) ; /* Last modification time 64 Bit */
2007-02-07 02:39:43 +00:00
pdata + = 24 ;
2009-05-14 15:34:42 +02:00
SIVAL ( pdata , 0 , psbuf - > st_ex_uid ) ; /* user id for the owner */
2007-02-07 02:39:43 +00:00
SIVAL ( pdata , 4 , 0 ) ;
pdata + = 8 ;
2009-05-14 15:34:42 +02:00
SIVAL ( pdata , 0 , psbuf - > st_ex_gid ) ; /* group id of owner */
2007-02-07 02:39:43 +00:00
SIVAL ( pdata , 4 , 0 ) ;
pdata + = 8 ;
2009-05-14 15:34:42 +02:00
SIVAL ( pdata , 0 , unix_filetype ( psbuf - > st_ex_mode ) ) ;
2007-02-07 02:39:43 +00:00
pdata + = 4 ;
2012-05-11 13:31:36 +02:00
if ( S_ISBLK ( psbuf - > st_ex_mode ) | | S_ISCHR ( psbuf - > st_ex_mode ) ) {
devno = psbuf - > st_ex_rdev ;
} else {
devno = psbuf - > st_ex_dev ;
}
SIVAL ( pdata , 0 , unix_dev_major ( devno ) ) ; /* Major device number if type is device */
2007-02-07 02:39:43 +00:00
SIVAL ( pdata , 4 , 0 ) ;
pdata + = 8 ;
2012-05-11 13:31:36 +02:00
SIVAL ( pdata , 0 , unix_dev_minor ( devno ) ) ; /* Minor device number if type is device */
2007-02-07 02:39:43 +00:00
SIVAL ( pdata , 4 , 0 ) ;
pdata + = 8 ;
2019-06-25 12:07:59 +02:00
SINO_T_VAL ( pdata , 0 , psbuf - > st_ex_ino ) ; /* inode number */
2007-02-07 02:39:43 +00:00
pdata + = 8 ;
2009-05-26 21:07:08 +02:00
2009-05-14 15:34:42 +02:00
SIVAL ( pdata , 0 , unix_perms_to_wire ( psbuf - > st_ex_mode ) ) ; /* Standard UNIX file permissions */
2007-02-07 02:39:43 +00:00
SIVAL ( pdata , 4 , 0 ) ;
pdata + = 8 ;
2009-05-14 15:34:42 +02:00
SIVAL ( pdata , 0 , psbuf - > st_ex_nlink ) ; /* number of hard links */
2007-02-07 02:39:43 +00:00
SIVAL ( pdata , 4 , 0 ) ;
pdata + = 8 ;
return pdata ;
}
2007-03-08 18:05:55 +00:00
/* Forward and reverse mappings from the UNIX_INFO2 file flags field and
* the chflags ( 2 ) ( or equivalent ) flags .
*
* XXX : this really should be behind the VFS interface . To do this , we would
* need to alter SMB_STRUCT_STAT so that it included a flags and a mask field .
2007-11-26 15:28:13 +01:00
* Each VFS module could then implement its own mapping as appropriate for the
2007-03-08 18:05:55 +00:00
* platform . We would then pass the SMB flags into SMB_VFS_CHFLAGS .
*/
static const struct { unsigned stat_fflag ; unsigned smb_fflag ; }
info2_flags_map [ ] =
{
# ifdef UF_NODUMP
{ UF_NODUMP , EXT_DO_NOT_BACKUP } ,
# endif
# ifdef UF_IMMUTABLE
{ UF_IMMUTABLE , EXT_IMMUTABLE } ,
# endif
# ifdef UF_APPEND
{ UF_APPEND , EXT_OPEN_APPEND_ONLY } ,
# endif
# ifdef UF_HIDDEN
2007-03-08 18:45:44 +00:00
{ UF_HIDDEN , EXT_HIDDEN } ,
2007-03-08 18:05:55 +00:00
# endif
2007-03-08 18:45:44 +00:00
/* Do not remove. We need to guarantee that this array has at least one
* entry to build on HP - UX .
*/
{ 0 , 0 }
2007-03-08 18:05:55 +00:00
} ;
static void map_info2_flags_from_sbuf ( const SMB_STRUCT_STAT * psbuf ,
2015-04-26 16:02:55 -07:00
uint32_t * smb_fflags , uint32_t * smb_fmask )
2007-03-08 18:05:55 +00:00
{
2022-01-02 19:33:07 +01:00
size_t i ;
2007-03-08 18:05:55 +00:00
for ( i = 0 ; i < ARRAY_SIZE ( info2_flags_map ) ; + + i ) {
* smb_fmask | = info2_flags_map [ i ] . smb_fflag ;
2009-05-14 15:34:42 +02:00
if ( psbuf - > st_ex_flags & info2_flags_map [ i ] . stat_fflag ) {
2007-03-08 18:05:55 +00:00
* smb_fflags | = info2_flags_map [ i ] . smb_fflag ;
}
}
}
2022-12-30 16:23:52 +01:00
bool map_info2_flags_to_sbuf ( const SMB_STRUCT_STAT * psbuf ,
const uint32_t smb_fflags ,
const uint32_t smb_fmask ,
int * stat_fflags )
2007-03-08 18:05:55 +00:00
{
2015-04-26 16:02:55 -07:00
uint32_t max_fmask = 0 ;
2022-01-02 19:33:07 +01:00
size_t i ;
2007-03-08 18:05:55 +00:00
2009-05-14 15:34:42 +02:00
* stat_fflags = psbuf - > st_ex_flags ;
2007-03-08 18:05:55 +00:00
/* For each flags requested in smb_fmask, check the state of the
* corresponding flag in smb_fflags and set or clear the matching
* stat flag .
*/
for ( i = 0 ; i < ARRAY_SIZE ( info2_flags_map ) ; + + i ) {
max_fmask | = info2_flags_map [ i ] . smb_fflag ;
if ( smb_fmask & info2_flags_map [ i ] . smb_fflag ) {
if ( smb_fflags & info2_flags_map [ i ] . smb_fflag ) {
* stat_fflags | = info2_flags_map [ i ] . stat_fflag ;
} else {
* stat_fflags & = ~ info2_flags_map [ i ] . stat_fflag ;
}
}
}
/* If smb_fmask is asking to set any bits that are not supported by
* our flag mappings , we should fail .
*/
if ( ( smb_fmask & max_fmask ) ! = smb_fmask ) {
return False ;
}
return True ;
}
/* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
* of file flags and birth ( create ) time .
*/
2022-12-28 23:47:42 +01:00
char * store_file_unix_basic_info2 ( connection_struct * conn ,
char * pdata ,
files_struct * fsp ,
const SMB_STRUCT_STAT * psbuf )
2007-03-08 18:05:55 +00:00
{
2015-04-26 16:02:55 -07:00
uint32_t file_flags = 0 ;
uint32_t flags_mask = 0 ;
2007-03-08 18:05:55 +00:00
pdata = store_file_unix_basic ( conn , pdata , fsp , psbuf ) ;
/* Create (birth) time 64 bit */
2019-11-30 21:29:07 +01:00
put_long_date_full_timespec ( TIMESTAMP_SET_NT_OR_BETTER , pdata , & psbuf - > st_ex_btime ) ;
2007-03-08 18:05:55 +00:00
pdata + = 8 ;
map_info2_flags_from_sbuf ( psbuf , & file_flags , & flags_mask ) ;
SIVAL ( pdata , 0 , file_flags ) ; /* flags */
SIVAL ( pdata , 4 , flags_mask ) ; /* mask */
pdata + = 8 ;
return pdata ;
}
2008-01-19 20:41:15 +01:00
static NTSTATUS marshall_stream_info ( unsigned int num_streams ,
const struct stream_struct * streams ,
char * data ,
unsigned int max_data_bytes ,
unsigned int * data_size )
{
unsigned int i ;
unsigned int ofs = 0 ;
2013-08-27 09:39:17 +00:00
if ( max_data_bytes < 32 ) {
return NT_STATUS_INFO_LENGTH_MISMATCH ;
}
2012-12-04 17:21:29 -08:00
for ( i = 0 ; i < num_streams ; i + + ) {
2008-01-19 20:41:15 +01:00
unsigned int next_offset ;
size_t namelen ;
smb_ucs2_t * namebuf ;
2008-04-29 14:36:24 -07:00
if ( ! push_ucs2_talloc ( talloc_tos ( ) , & namebuf ,
streams [ i ] . name , & namelen ) | |
namelen < = 2 )
{
2008-01-19 20:41:15 +01:00
return NT_STATUS_INVALID_PARAMETER ;
}
/*
* name_buf is now null - terminated , we need to marshall as not
* terminated
*/
namelen - = 2 ;
2012-12-04 17:21:29 -08:00
/*
* We cannot overflow . . .
*/
if ( ( ofs + 24 + namelen ) > max_data_bytes ) {
DEBUG ( 10 , ( " refusing to overflow reply at stream %u \n " ,
i ) ) ;
TALLOC_FREE ( namebuf ) ;
return STATUS_BUFFER_OVERFLOW ;
}
2008-01-19 20:41:15 +01:00
SIVAL ( data , ofs + 4 , namelen ) ;
SOFF_T ( data , ofs + 8 , streams [ i ] . size ) ;
SOFF_T ( data , ofs + 16 , streams [ i ] . alloc_size ) ;
memcpy ( data + ofs + 24 , namebuf , namelen ) ;
TALLOC_FREE ( namebuf ) ;
next_offset = ofs + 24 + namelen ;
if ( i = = num_streams - 1 ) {
SIVAL ( data , ofs , 0 ) ;
}
else {
unsigned int align = ndr_align_size ( next_offset , 8 ) ;
2012-12-04 17:21:29 -08:00
if ( ( next_offset + align ) > max_data_bytes ) {
DEBUG ( 10 , ( " refusing to overflow align "
" reply at stream %u \n " ,
i ) ) ;
TALLOC_FREE ( namebuf ) ;
return STATUS_BUFFER_OVERFLOW ;
}
2008-01-19 20:41:15 +01:00
memset ( data + next_offset , 0 , align ) ;
next_offset + = align ;
SIVAL ( data , ofs , next_offset - ofs ) ;
ofs = next_offset ;
}
ofs = next_offset ;
}
2012-12-04 17:21:29 -08:00
DEBUG ( 10 , ( " max_data: %u, data_size: %u \n " , max_data_bytes , ofs ) ) ;
2008-01-19 20:41:15 +01:00
* data_size = ofs ;
return NT_STATUS_OK ;
}
2009-07-10 20:02:44 +02:00
NTSTATUS smbd_do_qfilepathinfo ( connection_struct * conn ,
TALLOC_CTX * mem_ctx ,
2019-06-18 13:11:51 -07:00
struct smb_request * req ,
2009-07-10 20:02:44 +02:00
uint16_t info_level ,
files_struct * fsp ,
2009-08-12 15:08:23 -07:00
struct smb_filename * smb_fname ,
2009-07-10 20:02:44 +02:00
bool delete_pending ,
struct timespec write_time_ts ,
struct ea_list * ea_list ,
uint16_t flags2 ,
unsigned int max_data_bytes ,
2013-08-27 09:06:27 +00:00
size_t * fixed_portion ,
2009-07-10 20:02:44 +02:00
char * * ppdata ,
unsigned int * pdata_size )
1996-05-04 07:50:46 +00:00
{
2001-11-08 02:17:03 +00:00
char * pdata = * ppdata ;
2007-08-02 20:19:27 +00:00
char * dstart , * dend ;
2009-07-10 19:04:58 +02:00
unsigned int data_size ;
2009-08-10 15:07:53 -07:00
struct timespec create_time_ts , mtime_ts , atime_ts , ctime_ts ;
time_t create_time , mtime , atime , c_time ;
2020-10-19 21:07:35 +02:00
SMB_STRUCT_STAT * psbuf = NULL ;
2022-03-28 11:48:37 +02:00
SMB_STRUCT_STAT * base_sp = NULL ;
2001-11-08 02:17:03 +00:00
char * p ;
2009-07-10 19:04:58 +02:00
char * base_name ;
char * dos_fname ;
int mode ;
int nlink ;
NTSTATUS status ;
uint64_t file_size = 0 ;
uint64_t pos = 0 ;
uint64_t allocation_size = 0 ;
2019-06-28 10:12:44 +02:00
uint64_t file_id = 0 ;
2009-07-12 16:37:49 +02:00
uint32_t access_mask = 0 ;
2014-08-25 17:05:47 -07:00
size_t len = 0 ;
2001-11-08 02:17:03 +00:00
2021-11-18 11:48:42 -08:00
if ( INFO_LEVEL_IS_UNIX ( info_level ) ) {
2022-11-22 16:00:53 +01:00
bool ok = false ;
if ( lp_smb1_unix_extensions ( ) & & req - > posix_pathnames ) {
DBG_DEBUG ( " SMB1 unix extensions activated \n " ) ;
ok = true ;
}
2023-09-18 16:54:05 -07:00
if ( ( fsp ! = NULL ) & &
2022-11-22 16:00:53 +01:00
( fsp - > posix_flags & FSP_POSIX_FLAGS_OPEN ) ) {
DBG_DEBUG ( " SMB2 posix open \n " ) ;
ok = true ;
2021-11-18 11:48:42 -08:00
}
2022-11-22 16:00:53 +01:00
if ( ! ok ) {
2021-11-18 11:48:42 -08:00
return NT_STATUS_INVALID_LEVEL ;
}
2007-08-02 20:19:27 +00:00
}
2002-02-05 01:31:16 +00:00
2012-06-14 13:31:43 +02:00
DEBUG ( 5 , ( " smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u \n " ,
2012-06-12 17:56:43 +02:00
smb_fname_str_dbg ( smb_fname ) ,
2012-06-14 13:31:43 +02:00
fsp_fnum_dbg ( fsp ) ,
2009-07-21 11:37:51 -07:00
info_level , max_data_bytes ) ) ;
2002-09-25 15:19:00 +00:00
2020-10-19 21:07:35 +02:00
/*
* In case of querying a symlink in POSIX context ,
* fsp will be NULL . fdos_mode ( ) deals with it .
*/
if ( fsp ! = NULL ) {
smb_fname = fsp - > fsp_name ;
}
mode = fdos_mode ( fsp ) ;
psbuf = & smb_fname - > st ;
2022-03-28 11:48:37 +02:00
if ( fsp ! = NULL ) {
base_sp = fsp - > base_fsp ?
& fsp - > base_fsp - > fsp_name - > st :
& fsp - > fsp_name - > st ;
} else {
base_sp = & smb_fname - > st ;
}
2009-08-12 15:08:23 -07:00
nlink = psbuf - > st_ex_nlink ;
2001-11-08 02:17:03 +00:00
2011-04-29 11:57:02 +10:00
if ( nlink & & ( mode & FILE_ATTRIBUTE_DIRECTORY ) ) {
2009-07-10 19:04:58 +02:00
nlink = 1 ;
}
2001-11-08 02:17:03 +00:00
2009-07-10 19:04:58 +02:00
if ( ( nlink > 0 ) & & delete_pending ) {
nlink - = 1 ;
}
2007-03-08 18:05:55 +00:00
2013-08-02 17:05:58 -07:00
if ( max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes ) {
return NT_STATUS_INVALID_PARAMETER ;
}
2009-07-10 19:04:58 +02:00
data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN ;
2022-12-12 12:53:22 +01:00
* ppdata = ( char * ) SMB_REALLOC ( * ppdata , data_size ) ;
2009-07-10 19:04:58 +02:00
if ( * ppdata = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
pdata = * ppdata ;
dstart = pdata ;
dend = dstart + data_size - 1 ;
2007-09-07 20:57:01 +00:00
2019-12-02 16:30:50 +01:00
if ( ! is_omit_timespec ( & write_time_ts ) & &
! INFO_LEVEL_IS_UNIX ( info_level ) )
{
2009-08-12 15:08:23 -07:00
update_stat_ex_mtime ( psbuf , write_time_ts ) ;
2009-07-10 19:04:58 +02:00
}
2009-08-12 13:00:54 -07:00
create_time_ts = get_create_timespec ( conn , fsp , smb_fname ) ;
2009-08-12 15:08:23 -07:00
mtime_ts = psbuf - > st_ex_mtime ;
atime_ts = psbuf - > st_ex_atime ;
2009-08-12 13:00:54 -07:00
ctime_ts = get_change_timespec ( conn , fsp , smb_fname ) ;
2009-07-10 19:04:58 +02:00
if ( lp_dos_filetime_resolution ( SNUM ( conn ) ) ) {
dos_filetime_timespec ( & create_time_ts ) ;
dos_filetime_timespec ( & mtime_ts ) ;
dos_filetime_timespec ( & atime_ts ) ;
2009-08-10 15:07:53 -07:00
dos_filetime_timespec ( & ctime_ts ) ;
2009-07-10 19:04:58 +02:00
}
create_time = convert_timespec_to_time_t ( create_time_ts ) ;
mtime = convert_timespec_to_time_t ( mtime_ts ) ;
atime = convert_timespec_to_time_t ( atime_ts ) ;
2009-08-10 15:07:53 -07:00
c_time = convert_timespec_to_time_t ( ctime_ts ) ;
2009-07-10 19:04:58 +02:00
p = strrchr_m ( smb_fname - > base_name , ' / ' ) ;
if ( ! p )
base_name = smb_fname - > base_name ;
else
base_name = p + 1 ;
/* NT expects the name to be in an exact form of the *full*
filename . See the trans2 torture test */
if ( ISDOT ( base_name ) ) {
dos_fname = talloc_strdup ( mem_ctx , " \\ " ) ;
if ( ! dos_fname ) {
return NT_STATUS_NO_MEMORY ;
}
} else {
dos_fname = talloc_asprintf ( mem_ctx ,
" \\ %s " ,
2009-07-24 16:05:44 -07:00
smb_fname - > base_name ) ;
2009-07-10 19:04:58 +02:00
if ( ! dos_fname ) {
return NT_STATUS_NO_MEMORY ;
2007-09-07 20:57:01 +00:00
}
2022-02-11 18:09:56 +01:00
if ( is_named_stream ( smb_fname ) ) {
2009-07-24 16:05:44 -07:00
dos_fname = talloc_asprintf ( dos_fname , " %s " ,
smb_fname - > stream_name ) ;
if ( ! dos_fname ) {
return NT_STATUS_NO_MEMORY ;
}
}
2009-07-10 19:04:58 +02:00
string_replace ( dos_fname , ' / ' , ' \\ ' ) ;
}
2007-09-07 20:57:01 +00:00
2009-08-12 15:08:23 -07:00
allocation_size = SMB_VFS_GET_ALLOC_SIZE ( conn , fsp , psbuf ) ;
2009-07-10 19:04:58 +02:00
2020-11-17 07:59:13 +01:00
if ( fsp = = NULL | | ! fsp - > fsp_flags . is_fsa ) {
2009-07-10 19:04:58 +02:00
/* Do we have this path open ? */
2009-08-12 15:08:23 -07:00
struct file_id fileid = vfs_file_id_from_sbuf ( conn , psbuf ) ;
2023-02-13 15:18:50 +01:00
files_struct * fsp1 = file_find_di_first (
conn - > sconn , fileid , true ) ;
2009-07-10 19:04:58 +02:00
if ( fsp1 & & fsp1 - > initial_allocation_size ) {
2009-08-12 15:08:23 -07:00
allocation_size = SMB_VFS_GET_ALLOC_SIZE ( conn , fsp1 , psbuf ) ;
2009-06-22 15:26:56 -07:00
}
2009-07-10 19:04:58 +02:00
}
2009-06-22 15:26:56 -07:00
2011-04-29 11:57:02 +10:00
if ( ! ( mode & FILE_ATTRIBUTE_DIRECTORY ) ) {
2009-08-12 15:08:23 -07:00
file_size = get_file_size_stat ( psbuf ) ;
2009-07-10 19:04:58 +02:00
}
2007-09-07 20:57:01 +00:00
2009-07-17 21:40:23 -07:00
if ( fsp ) {
2020-09-28 10:32:29 +02:00
pos = fh_get_position_information ( fsp - > fh ) ;
2009-07-10 19:04:58 +02:00
}
2007-09-07 20:57:01 +00:00
2009-07-12 16:37:49 +02:00
if ( fsp ) {
access_mask = fsp - > access_mask ;
} else {
/* GENERIC_EXECUTE mapping from Windows */
access_mask = 0x12019F ;
}
/* This should be an index number - looks like
dev / ino to me : - )
I think this causes us to fail the IFSKIT
BasicFileInformationTest . - tpot */
2022-03-28 11:48:37 +02:00
file_id = SMB_VFS_FS_FILE_ID ( conn , base_sp ) ;
2009-07-12 16:37:49 +02:00
2013-08-27 09:06:27 +00:00
* fixed_portion = 0 ;
2009-07-10 19:04:58 +02:00
switch ( info_level ) {
case SMB_INFO_STANDARD :
DEBUG ( 10 , ( " smbd_do_qfilepathinfo: SMB_INFO_STANDARD \n " ) ) ;
data_size = 22 ;
srv_put_dos_date2 ( pdata , l1_fdateCreation , create_time ) ;
srv_put_dos_date2 ( pdata , l1_fdateLastAccess , atime ) ;
srv_put_dos_date2 ( pdata , l1_fdateLastWrite , mtime ) ; /* write time */
2015-05-02 21:01:14 -07:00
SIVAL ( pdata , l1_cbFile , ( uint32_t ) file_size ) ;
SIVAL ( pdata , l1_cbFileAlloc , ( uint32_t ) allocation_size ) ;
2009-07-10 19:04:58 +02:00
SSVAL ( pdata , l1_attrFile , mode ) ;
break ;
2007-09-07 20:57:01 +00:00
2009-07-10 19:04:58 +02:00
case SMB_INFO_QUERY_EA_SIZE :
{
2009-07-24 16:05:44 -07:00
unsigned int ea_size =
2021-02-10 11:54:29 +00:00
estimate_ea_size ( smb_fname - > fsp ) ;
2009-07-10 19:04:58 +02:00
DEBUG ( 10 , ( " smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE \n " ) ) ;
data_size = 26 ;
srv_put_dos_date2 ( pdata , 0 , create_time ) ;
srv_put_dos_date2 ( pdata , 4 , atime ) ;
srv_put_dos_date2 ( pdata , 8 , mtime ) ; /* write time */
2015-05-02 21:01:14 -07:00
SIVAL ( pdata , 12 , ( uint32_t ) file_size ) ;
SIVAL ( pdata , 16 , ( uint32_t ) allocation_size ) ;
2009-07-10 19:04:58 +02:00
SSVAL ( pdata , 20 , mode ) ;
SIVAL ( pdata , 22 , ea_size ) ;
break ;
}
2002-07-15 10:35:28 +00:00
2009-07-10 19:04:58 +02:00
case SMB_INFO_IS_NAME_VALID :
DEBUG ( 10 , ( " smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID \n " ) ) ;
if ( fsp ) {
/* os/2 needs this ? really ?*/
return NT_STATUS_DOS ( ERRDOS , ERRbadfunc ) ;
2007-08-02 20:19:27 +00:00
}
2009-07-10 19:04:58 +02:00
/* This is only reached for qpathinfo */
data_size = 0 ;
break ;
1996-05-04 07:50:46 +00:00
2009-07-10 19:04:58 +02:00
case SMB_INFO_QUERY_EAS_FROM_LIST :
{
size_t total_ea_len = 0 ;
struct ea_list * ea_file_list = NULL ;
DEBUG ( 10 , ( " smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST \n " ) ) ;
2012-08-19 22:46:58 +10:00
status =
2021-02-08 17:38:54 +00:00
get_ea_list_from_fsp ( mem_ctx ,
2021-02-02 17:05:49 +00:00
smb_fname - > fsp ,
2012-08-19 22:46:58 +10:00
& total_ea_len , & ea_file_list ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
2009-07-10 19:04:58 +02:00
ea_list = ea_list_union ( ea_list , ea_file_list , & total_ea_len ) ;
if ( ! ea_list | | ( total_ea_len > data_size ) ) {
data_size = 4 ;
SIVAL ( pdata , 0 , 4 ) ; /* EA List Length must be set to 4 if no EA's. */
break ;
2001-11-12 01:00:54 +00:00
}
2007-09-07 20:57:01 +00:00
2009-07-10 19:04:58 +02:00
data_size = fill_ea_buffer ( mem_ctx , pdata , data_size , conn , ea_list ) ;
break ;
2005-03-19 00:31:45 +00:00
}
2002-07-15 10:35:28 +00:00
2009-07-10 19:04:58 +02:00
case SMB_INFO_QUERY_ALL_EAS :
{
/* We have data_size bytes to put EA's into. */
size_t total_ea_len = 0 ;
DEBUG ( 10 , ( " smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS \n " ) ) ;
2001-03-14 07:29:53 +00:00
2021-02-08 17:38:54 +00:00
status = get_ea_list_from_fsp ( mem_ctx ,
2021-02-02 17:05:49 +00:00
smb_fname - > fsp ,
2012-08-19 22:46:58 +10:00
& total_ea_len , & ea_list ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
2009-07-10 19:04:58 +02:00
if ( ! ea_list | | ( total_ea_len > data_size ) ) {
data_size = 4 ;
SIVAL ( pdata , 0 , 4 ) ; /* EA List Length must be set to 4 if no EA's. */
break ;
}
data_size = fill_ea_buffer ( mem_ctx , pdata , data_size , conn , ea_list ) ;
break ;
2007-03-08 18:05:55 +00:00
}
2020-10-23 16:24:08 +02:00
case SMB2_FILE_FULL_EA_INFORMATION :
2009-07-12 16:40:58 +02:00
{
/* We have data_size bytes to put EA's into. */
size_t total_ea_len = 0 ;
struct ea_list * ea_file_list = NULL ;
DEBUG ( 10 , ( " smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS \n " ) ) ;
/*TODO: add filtering and index handling */
2012-08-19 22:46:58 +10:00
status =
2021-02-08 17:38:54 +00:00
get_ea_list_from_fsp ( mem_ctx ,
2021-02-02 17:05:49 +00:00
smb_fname - > fsp ,
2012-08-19 22:46:58 +10:00
& total_ea_len , & ea_file_list ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
2009-07-12 16:40:58 +02:00
if ( ! ea_file_list ) {
return NT_STATUS_NO_EAS_ON_FILE ;
}
status = fill_ea_chained_buffer ( mem_ctx ,
pdata ,
data_size ,
& data_size ,
conn , ea_file_list ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
break ;
}
2009-07-10 19:04:58 +02:00
case SMB_FILE_BASIC_INFORMATION :
case SMB_QUERY_FILE_BASIC_INFO :
1998-08-21 05:58:57 +00:00
2009-07-10 19:04:58 +02:00
if ( info_level = = SMB_QUERY_FILE_BASIC_INFO ) {
DEBUG ( 10 , ( " smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO \n " ) ) ;
data_size = 36 ; /* w95 returns 40 bytes not 36 - why ?. */
} else {
DEBUG ( 10 , ( " smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION \n " ) ) ;
data_size = 40 ;
SIVAL ( pdata , 36 , 0 ) ;
2007-03-12 17:55:24 +00:00
}
2019-11-30 21:29:07 +01:00
put_long_date_full_timespec ( conn - > ts_res , pdata , & create_time_ts ) ;
put_long_date_full_timespec ( conn - > ts_res , pdata + 8 , & atime_ts ) ;
put_long_date_full_timespec ( conn - > ts_res , pdata + 16 , & mtime_ts ) ; /* write time */
put_long_date_full_timespec ( conn - > ts_res , pdata + 24 , & ctime_ts ) ; /* change time */
2009-07-10 19:04:58 +02:00
SIVAL ( pdata , 32 , mode ) ;
1996-05-04 07:50:46 +00:00
2009-07-10 19:04:58 +02:00
DEBUG ( 5 , ( " SMB_QFBI - " ) ) ;
DEBUG ( 5 , ( " create: %s " , ctime ( & create_time ) ) ) ;
DEBUG ( 5 , ( " access: %s " , ctime ( & atime ) ) ) ;
DEBUG ( 5 , ( " write: %s " , ctime ( & mtime ) ) ) ;
2009-08-10 15:07:53 -07:00
DEBUG ( 5 , ( " change: %s " , ctime ( & c_time ) ) ) ;
2009-07-10 19:04:58 +02:00
DEBUG ( 5 , ( " mode: %x \n " , mode ) ) ;
2013-08-27 09:06:27 +00:00
* fixed_portion = data_size ;
2009-07-10 19:04:58 +02:00
break ;
2009-06-22 15:26:56 -07:00
2009-07-10 19:04:58 +02:00
case SMB_FILE_STANDARD_INFORMATION :
case SMB_QUERY_FILE_STANDARD_INFO :
2008-12-01 13:35:28 -08:00
2009-07-10 19:04:58 +02:00
DEBUG ( 10 , ( " smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION \n " ) ) ;
data_size = 24 ;
SOFF_T ( pdata , 0 , allocation_size ) ;
SOFF_T ( pdata , 8 , file_size ) ;
SIVAL ( pdata , 16 , nlink ) ;
SCVAL ( pdata , 20 , delete_pending ? 1 : 0 ) ;
2011-04-29 11:57:02 +10:00
SCVAL ( pdata , 21 , ( mode & FILE_ATTRIBUTE_DIRECTORY ) ? 1 : 0 ) ;
2009-07-10 19:04:58 +02:00
SSVAL ( pdata , 22 , 0 ) ; /* Padding. */
2013-08-27 09:06:27 +00:00
* fixed_portion = 24 ;
2009-07-10 19:04:58 +02:00
break ;
2008-12-01 13:35:28 -08:00
2009-07-10 19:04:58 +02:00
case SMB_FILE_EA_INFORMATION :
case SMB_QUERY_FILE_EA_INFO :
{
2009-07-24 16:05:44 -07:00
unsigned int ea_size =
2021-02-10 11:54:29 +00:00
estimate_ea_size ( smb_fname - > fsp ) ;
2009-07-10 19:04:58 +02:00
DEBUG ( 10 , ( " smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION \n " ) ) ;
data_size = 4 ;
2013-08-27 09:06:27 +00:00
* fixed_portion = 4 ;
2009-07-10 19:04:58 +02:00
SIVAL ( pdata , 0 , ea_size ) ;
break ;
2008-12-01 13:35:28 -08:00
}
2009-07-10 19:04:58 +02:00
/* Get the 8.3 name - used if NT SMB was negotiated. */
case SMB_QUERY_FILE_ALT_NAME_INFO :
case SMB_FILE_ALTERNATE_NAME_INFORMATION :
{
char mangled_name [ 13 ] ;
DEBUG ( 10 , ( " smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION \n " ) ) ;
if ( ! name_to_8_3 ( base_name , mangled_name ,
True , conn - > params ) ) {
return NT_STATUS_NO_MEMORY ;
2001-11-12 01:00:54 +00:00
}
2014-08-25 17:11:58 -07:00
status = srvstr_push ( dstart , flags2 ,
2009-07-10 19:04:58 +02:00
pdata + 4 , mangled_name ,
PTR_DIFF ( dend , pdata + 4 ) ,
2014-08-25 17:11:58 -07:00
STR_UNICODE , & len ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
2009-07-10 19:04:58 +02:00
data_size = 4 + len ;
SIVAL ( pdata , 0 , len ) ;
2013-08-27 09:06:27 +00:00
* fixed_portion = 8 ;
2009-07-10 19:04:58 +02:00
break ;
}
2008-04-28 15:06:08 -07:00
2009-07-10 19:04:58 +02:00
case SMB_QUERY_FILE_NAME_INFO :
{
/*
this must be * exactly * right for ACLs on mapped drives to work
*/
2014-08-25 17:11:58 -07:00
status = srvstr_push ( dstart , flags2 ,
2009-07-10 19:04:58 +02:00
pdata + 4 , dos_fname ,
PTR_DIFF ( dend , pdata + 4 ) ,
2014-08-25 17:11:58 -07:00
STR_UNICODE , & len ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
2009-07-10 19:04:58 +02:00
DEBUG ( 10 , ( " smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO \n " ) ) ;
data_size = 4 + len ;
SIVAL ( pdata , 0 , len ) ;
break ;
2001-11-12 01:00:54 +00:00
}
2005-07-08 04:51:27 +00:00
2019-04-25 14:57:33 +02:00
case SMB_FILE_NORMALIZED_NAME_INFORMATION :
{
char * nfname = NULL ;
2019-12-09 10:45:31 +01:00
if ( fsp = = NULL | | ! fsp - > conn - > sconn - > using_smb2 ) {
2019-04-25 14:57:33 +02:00
return NT_STATUS_INVALID_LEVEL ;
}
nfname = talloc_strdup ( mem_ctx , smb_fname - > base_name ) ;
if ( nfname = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
if ( ISDOT ( nfname ) ) {
nfname [ 0 ] = ' \0 ' ;
}
string_replace ( nfname , ' / ' , ' \\ ' ) ;
2022-02-11 15:59:06 +01:00
if ( fsp_is_alternate_stream ( fsp ) ) {
2019-04-25 14:57:33 +02:00
const char * s = smb_fname - > stream_name ;
const char * e = NULL ;
size_t n ;
SMB_ASSERT ( s [ 0 ] ! = ' \0 ' ) ;
/*
* smb_fname - > stream_name is in form
* of ' : StrEam : $ DATA ' , but we should only
* append ' : StrEam ' here .
*/
e = strchr ( & s [ 1 ] , ' : ' ) ;
if ( e = = NULL ) {
n = strlen ( s ) ;
} else {
n = PTR_DIFF ( e , s ) ;
}
nfname = talloc_strndup_append ( nfname , s , n ) ;
if ( nfname = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
}
status = srvstr_push ( dstart , flags2 ,
pdata + 4 , nfname ,
PTR_DIFF ( dend , pdata + 4 ) ,
STR_UNICODE , & len ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
DEBUG ( 10 , ( " smbd_do_qfilepathinfo: SMB_FILE_NORMALIZED_NAME_INFORMATION \n " ) ) ;
data_size = 4 + len ;
SIVAL ( pdata , 0 , len ) ;
* fixed_portion = 8 ;
break ;
}
2009-07-10 19:04:58 +02:00
case SMB_FILE_ALLOCATION_INFORMATION :
case SMB_QUERY_FILE_ALLOCATION_INFO :
DEBUG ( 10 , ( " smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION \n " ) ) ;
data_size = 8 ;
SOFF_T ( pdata , 0 , allocation_size ) ;
break ;
case SMB_FILE_END_OF_FILE_INFORMATION :
case SMB_QUERY_FILE_END_OF_FILEINFO :
DEBUG ( 10 , ( " smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION \n " ) ) ;
data_size = 8 ;
SOFF_T ( pdata , 0 , file_size ) ;
break ;
case SMB_QUERY_FILE_ALL_INFO :
case SMB_FILE_ALL_INFORMATION :
{
2009-07-24 16:05:44 -07:00
unsigned int ea_size =
2021-02-10 11:54:29 +00:00
estimate_ea_size ( smb_fname - > fsp ) ;
2009-07-10 19:04:58 +02:00
DEBUG ( 10 , ( " smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION \n " ) ) ;
2019-11-30 21:29:07 +01:00
put_long_date_full_timespec ( conn - > ts_res , pdata , & create_time_ts ) ;
put_long_date_full_timespec ( conn - > ts_res , pdata + 8 , & atime_ts ) ;
put_long_date_full_timespec ( conn - > ts_res , pdata + 16 , & mtime_ts ) ; /* write time */
put_long_date_full_timespec ( conn - > ts_res , pdata + 24 , & ctime_ts ) ; /* change time */
2009-07-10 19:04:58 +02:00
SIVAL ( pdata , 32 , mode ) ;
SIVAL ( pdata , 36 , 0 ) ; /* padding. */
pdata + = 40 ;
SOFF_T ( pdata , 0 , allocation_size ) ;
SOFF_T ( pdata , 8 , file_size ) ;
SIVAL ( pdata , 16 , nlink ) ;
SCVAL ( pdata , 20 , delete_pending ) ;
2011-04-29 11:57:02 +10:00
SCVAL ( pdata , 21 , ( mode & FILE_ATTRIBUTE_DIRECTORY ) ? 1 : 0 ) ;
2009-07-10 19:04:58 +02:00
SSVAL ( pdata , 22 , 0 ) ;
pdata + = 24 ;
SIVAL ( pdata , 0 , ea_size ) ;
pdata + = 4 ; /* EA info */
2014-08-25 17:11:58 -07:00
status = srvstr_push ( dstart , flags2 ,
2009-07-12 17:08:18 +02:00
pdata + 4 , dos_fname ,
PTR_DIFF ( dend , pdata + 4 ) ,
2014-08-25 17:11:58 -07:00
STR_UNICODE , & len ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
2009-07-12 17:08:18 +02:00
SIVAL ( pdata , 0 , len ) ;
pdata + = 4 + len ;
data_size = PTR_DIFF ( pdata , ( * ppdata ) ) ;
2013-08-27 09:06:27 +00:00
* fixed_portion = 10 ;
2009-07-12 17:08:18 +02:00
break ;
}
2020-10-23 16:25:06 +02:00
case SMB2_FILE_ALL_INFORMATION :
2009-07-12 17:08:18 +02:00
{
2009-07-24 16:05:44 -07:00
unsigned int ea_size =
2021-02-10 11:54:29 +00:00
estimate_ea_size ( smb_fname - > fsp ) ;
2009-07-12 17:08:18 +02:00
DEBUG ( 10 , ( " smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION \n " ) ) ;
2019-11-30 21:29:07 +01:00
put_long_date_full_timespec ( conn - > ts_res , pdata + 0x00 , & create_time_ts ) ;
put_long_date_full_timespec ( conn - > ts_res , pdata + 0x08 , & atime_ts ) ;
put_long_date_full_timespec ( conn - > ts_res , pdata + 0x10 , & mtime_ts ) ; /* write time */
put_long_date_full_timespec ( conn - > ts_res , pdata + 0x18 , & ctime_ts ) ; /* change time */
2009-07-12 17:08:18 +02:00
SIVAL ( pdata , 0x20 , mode ) ;
SIVAL ( pdata , 0x24 , 0 ) ; /* padding. */
SBVAL ( pdata , 0x28 , allocation_size ) ;
SBVAL ( pdata , 0x30 , file_size ) ;
SIVAL ( pdata , 0x38 , nlink ) ;
SCVAL ( pdata , 0x3C , delete_pending ) ;
2011-04-29 11:57:02 +10:00
SCVAL ( pdata , 0x3D , ( mode & FILE_ATTRIBUTE_DIRECTORY ) ? 1 : 0 ) ;
2009-07-12 17:08:18 +02:00
SSVAL ( pdata , 0x3E , 0 ) ; /* padding */
2019-06-28 10:12:44 +02:00
SBVAL ( pdata , 0x40 , file_id ) ;
2009-07-12 17:08:18 +02:00
SIVAL ( pdata , 0x48 , ea_size ) ;
SIVAL ( pdata , 0x4C , access_mask ) ;
SBVAL ( pdata , 0x50 , pos ) ;
SIVAL ( pdata , 0x58 , mode ) ; /*TODO: mode != mode fix this!!! */
SIVAL ( pdata , 0x5C , 0 ) ; /* No alignment needed. */
pdata + = 0x60 ;
2014-08-25 17:11:58 -07:00
status = srvstr_push ( dstart , flags2 ,
2009-07-10 19:04:58 +02:00
pdata + 4 , dos_fname ,
PTR_DIFF ( dend , pdata + 4 ) ,
2014-08-25 17:11:58 -07:00
STR_UNICODE , & len ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
2009-07-10 19:04:58 +02:00
SIVAL ( pdata , 0 , len ) ;
pdata + = 4 + len ;
data_size = PTR_DIFF ( pdata , ( * ppdata ) ) ;
2013-08-27 09:06:27 +00:00
* fixed_portion = 104 ;
2009-07-10 19:04:58 +02:00
break ;
2005-07-08 04:51:27 +00:00
}
2009-07-10 19:04:58 +02:00
case SMB_FILE_INTERNAL_INFORMATION :
2009-06-22 15:26:56 -07:00
2009-07-10 19:04:58 +02:00
DEBUG ( 10 , ( " smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION \n " ) ) ;
2019-06-28 10:12:44 +02:00
SBVAL ( pdata , 0 , file_id ) ;
2009-07-10 19:04:58 +02:00
data_size = 8 ;
2013-08-27 09:06:27 +00:00
* fixed_portion = 8 ;
2009-07-10 19:04:58 +02:00
break ;
1996-05-04 07:50:46 +00:00
2009-07-10 19:04:58 +02:00
case SMB_FILE_ACCESS_INFORMATION :
DEBUG ( 10 , ( " smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION \n " ) ) ;
2009-07-12 16:37:49 +02:00
SIVAL ( pdata , 0 , access_mask ) ;
2009-07-10 19:04:58 +02:00
data_size = 4 ;
2013-08-27 09:06:27 +00:00
* fixed_portion = 4 ;
2009-07-10 19:04:58 +02:00
break ;
2001-07-04 01:01:02 +00:00
2009-07-10 19:04:58 +02:00
case SMB_FILE_NAME_INFORMATION :
/* Pathname with leading '\'. */
{
size_t byte_len ;
byte_len = dos_PutUniCode ( pdata + 4 , dos_fname , ( size_t ) max_data_bytes , False ) ;
DEBUG ( 10 , ( " smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION \n " ) ) ;
SIVAL ( pdata , 0 , byte_len ) ;
data_size = 4 + byte_len ;
break ;
}
2001-07-04 01:01:02 +00:00
2009-07-10 19:04:58 +02:00
case SMB_FILE_DISPOSITION_INFORMATION :
DEBUG ( 10 , ( " smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION \n " ) ) ;
data_size = 1 ;
SCVAL ( pdata , 0 , delete_pending ) ;
2013-08-27 09:06:27 +00:00
* fixed_portion = 1 ;
2009-07-10 19:04:58 +02:00
break ;
2003-08-14 23:15:02 +00:00
2009-07-10 19:04:58 +02:00
case SMB_FILE_POSITION_INFORMATION :
DEBUG ( 10 , ( " smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION \n " ) ) ;
data_size = 8 ;
SOFF_T ( pdata , 0 , pos ) ;
2013-08-27 09:06:27 +00:00
* fixed_portion = 8 ;
2009-07-10 19:04:58 +02:00
break ;
2008-01-18 18:39:27 -08:00
2009-07-10 19:04:58 +02:00
case SMB_FILE_MODE_INFORMATION :
DEBUG ( 10 , ( " smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION \n " ) ) ;
SIVAL ( pdata , 0 , mode ) ;
data_size = 4 ;
2013-08-27 09:06:27 +00:00
* fixed_portion = 4 ;
2009-07-10 19:04:58 +02:00
break ;
2008-01-18 18:39:27 -08:00
2009-07-10 19:04:58 +02:00
case SMB_FILE_ALIGNMENT_INFORMATION :
DEBUG ( 10 , ( " smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION \n " ) ) ;
SIVAL ( pdata , 0 , 0 ) ; /* No alignment needed. */
data_size = 4 ;
2013-08-27 09:06:27 +00:00
* fixed_portion = 4 ;
2009-07-10 19:04:58 +02:00
break ;
/*
* NT4 server just returns " invalid query " to this - if we try
* to answer it then NTws gets a BSOD ! ( tridge ) . W2K seems to
* want this . JRA .
*/
/* The first statement above is false - verified using Thursby
* client against NT4 - - gcolley .
*/
case SMB_QUERY_FILE_STREAM_INFO :
case SMB_FILE_STREAM_INFORMATION : {
2011-10-13 15:41:53 -07:00
unsigned int num_streams = 0 ;
struct stream_struct * streams = NULL ;
2008-01-18 18:39:27 -08:00
2009-07-10 19:04:58 +02:00
DEBUG ( 10 , ( " smbd_do_qfilepathinfo: "
" SMB_FILE_STREAM_INFORMATION \n " ) ) ;
1996-05-04 07:50:46 +00:00
2009-07-24 16:05:44 -07:00
if ( is_ntfs_stream_smb_fname ( smb_fname ) ) {
return NT_STATUS_INVALID_PARAMETER ;
}
2021-04-28 13:59:22 +01:00
status = vfs_fstreaminfo ( fsp ,
mem_ctx ,
2016-03-04 14:16:13 -08:00
& num_streams ,
& streams ) ;
2005-03-22 17:48:41 +00:00
2009-07-10 19:04:58 +02:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 10 , ( " could not get stream info: %s \n " ,
nt_errstr ( status ) ) ) ;
return status ;
2006-04-10 15:33:04 +00:00
}
2005-03-18 01:55:30 +00:00
2009-07-10 19:04:58 +02:00
status = marshall_stream_info ( num_streams , streams ,
pdata , max_data_bytes ,
& data_size ) ;
2005-03-18 01:55:30 +00:00
2009-07-10 19:04:58 +02:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 10 , ( " marshall_stream_info failed: %s \n " ,
nt_errstr ( status ) ) ) ;
2012-12-04 17:21:29 -08:00
TALLOC_FREE ( streams ) ;
2009-07-10 19:04:58 +02:00
return status ;
2006-04-10 15:33:04 +00:00
}
2005-03-18 01:55:30 +00:00
2009-07-10 19:04:58 +02:00
TALLOC_FREE ( streams ) ;
2013-08-27 09:06:27 +00:00
* fixed_portion = 32 ;
2006-04-10 15:33:04 +00:00
break ;
2005-03-18 01:55:30 +00:00
}
2009-07-10 19:04:58 +02:00
case SMB_QUERY_COMPRESSION_INFO :
case SMB_FILE_COMPRESSION_INFORMATION :
DEBUG ( 10 , ( " smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION \n " ) ) ;
SOFF_T ( pdata , 0 , file_size ) ;
SIVAL ( pdata , 8 , 0 ) ; /* ??? */
SIVAL ( pdata , 12 , 0 ) ; /* ??? */
data_size = 16 ;
2013-08-27 09:06:27 +00:00
* fixed_portion = 16 ;
2009-07-10 19:04:58 +02:00
break ;
2006-07-11 18:01:26 +00:00
2009-07-10 19:04:58 +02:00
case SMB_FILE_NETWORK_OPEN_INFORMATION :
DEBUG ( 10 , ( " smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION \n " ) ) ;
2019-11-30 21:29:07 +01:00
put_long_date_full_timespec ( conn - > ts_res , pdata , & create_time_ts ) ;
put_long_date_full_timespec ( conn - > ts_res , pdata + 8 , & atime_ts ) ;
put_long_date_full_timespec ( conn - > ts_res , pdata + 16 , & mtime_ts ) ; /* write time */
put_long_date_full_timespec ( conn - > ts_res , pdata + 24 , & ctime_ts ) ; /* change time */
2009-07-10 19:04:58 +02:00
SOFF_T ( pdata , 32 , allocation_size ) ;
SOFF_T ( pdata , 40 , file_size ) ;
SIVAL ( pdata , 48 , mode ) ;
SIVAL ( pdata , 52 , 0 ) ; /* ??? */
data_size = 56 ;
2013-08-27 09:06:27 +00:00
* fixed_portion = 56 ;
2009-07-10 19:04:58 +02:00
break ;
2006-04-10 15:33:04 +00:00
2009-07-10 19:04:58 +02:00
case SMB_FILE_ATTRIBUTE_TAG_INFORMATION :
DEBUG ( 10 , ( " smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION \n " ) ) ;
SIVAL ( pdata , 0 , mode ) ;
SIVAL ( pdata , 4 , 0 ) ;
data_size = 8 ;
2013-08-27 09:06:27 +00:00
* fixed_portion = 8 ;
2006-04-10 15:33:04 +00:00
break ;
2005-03-18 01:55:30 +00:00
2017-12-14 15:18:21 -08:00
/*
* SMB2 UNIX Extensions .
*/
case SMB2_FILE_POSIX_INFORMATION_INTERNAL :
{
2023-09-27 10:51:37 +02:00
struct smb3_file_posix_information info = { } ;
uint8_t buf [ sizeof ( info ) ] ;
struct ndr_push ndr = {
. data = buf ,
. alloc_size = sizeof ( buf ) ,
. fixed_buf_size = true ,
} ;
enum ndr_err_code ndr_err ;
2017-12-14 15:18:21 -08:00
if ( ! ( conn - > sconn - > using_smb2 ) ) {
return NT_STATUS_INVALID_LEVEL ;
}
if ( fsp = = NULL ) {
return NT_STATUS_INVALID_HANDLE ;
}
if ( ! ( fsp - > posix_flags & FSP_POSIX_FLAGS_OPEN ) ) {
return NT_STATUS_INVALID_LEVEL ;
}
2023-09-27 10:51:37 +02:00
smb3_file_posix_information_init (
conn , & smb_fname - > st , 0 , mode , & info ) ;
ndr_err = ndr_push_smb3_file_posix_information (
& ndr , NDR_SCALARS | NDR_BUFFERS , & info ) ;
if ( ! NDR_ERR_CODE_IS_SUCCESS ( ndr_err ) ) {
return NT_STATUS_INSUFFICIENT_RESOURCES ;
2017-12-14 15:18:21 -08:00
}
2023-09-27 10:51:37 +02:00
memcpy ( pdata , buf , ndr . offset ) ;
data_size = ndr . offset ;
2017-12-14 15:18:21 -08:00
break ;
}
2009-07-10 19:04:58 +02:00
default :
return NT_STATUS_INVALID_LEVEL ;
}
2001-11-12 01:00:54 +00:00
2009-07-10 19:04:58 +02:00
* pdata_size = data_size ;
return NT_STATUS_OK ;
}
2001-06-18 23:42:41 +00:00
2004-03-03 23:14:23 +00:00
/****************************************************************************
Set a hard link ( called by UNIX extensions and by NT rename with HARD link
code .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-09-13 22:08:59 +00:00
NTSTATUS hardlink_internals ( TALLOC_CTX * ctx ,
connection_struct * conn ,
2010-05-18 18:34:54 -07:00
struct smb_request * req ,
bool overwrite_if_exists ,
2009-06-18 13:13:38 -07:00
const struct smb_filename * smb_fname_old ,
2010-05-18 18:34:54 -07:00
struct smb_filename * smb_fname_new )
2004-03-03 23:14:23 +00:00
{
NTSTATUS status = NT_STATUS_OK ;
2019-08-16 16:16:48 -07:00
int ret ;
2019-03-18 12:24:25 +01:00
bool ok ;
2021-01-19 12:57:51 -08:00
struct smb_filename * parent_fname_old = NULL ;
struct smb_filename * base_name_old = NULL ;
struct smb_filename * parent_fname_new = NULL ;
struct smb_filename * base_name_new = NULL ;
2004-03-03 23:14:23 +00:00
/* source must already exist. */
2009-06-18 13:13:38 -07:00
if ( ! VALID_STAT ( smb_fname_old - > st ) ) {
2021-01-19 12:49:40 -08:00
status = NT_STATUS_OBJECT_NAME_NOT_FOUND ;
goto out ;
2004-03-03 23:14:23 +00:00
}
2021-01-19 12:57:51 -08:00
/* No links from a directory. */
if ( S_ISDIR ( smb_fname_old - > st . st_ex_mode ) ) {
status = NT_STATUS_FILE_IS_A_DIRECTORY ;
goto out ;
}
/* Setting a hardlink to/from a stream isn't currently supported. */
ok = is_ntfs_stream_smb_fname ( smb_fname_old ) ;
if ( ok ) {
DBG_DEBUG ( " Old name has streams \n " ) ;
status = NT_STATUS_INVALID_PARAMETER ;
goto out ;
}
ok = is_ntfs_stream_smb_fname ( smb_fname_new ) ;
if ( ok ) {
DBG_DEBUG ( " New name has streams \n " ) ;
status = NT_STATUS_INVALID_PARAMETER ;
goto out ;
}
status = parent_pathref ( talloc_tos ( ) ,
conn - > cwd_fsp ,
smb_fname_old ,
& parent_fname_old ,
& base_name_old ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto out ;
}
status = parent_pathref ( talloc_tos ( ) ,
conn - > cwd_fsp ,
smb_fname_new ,
& parent_fname_new ,
& base_name_new ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto out ;
}
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-07 13:39:57 -07:00
if ( VALID_STAT ( smb_fname_new - > st ) ) {
2010-05-18 18:34:54 -07:00
if ( overwrite_if_exists ) {
if ( S_ISDIR ( smb_fname_new - > st . st_ex_mode ) ) {
2021-01-19 12:49:40 -08:00
status = NT_STATUS_FILE_IS_A_DIRECTORY ;
goto out ;
2010-05-18 18:34:54 -07:00
}
status = unlink_internals ( conn ,
req ,
FILE_ATTRIBUTE_NORMAL ,
2022-07-28 11:17:47 -07:00
NULL , /* new_dirfsp */
2021-12-01 13:03:03 -08:00
smb_fname_new ) ;
2010-05-18 18:34:54 -07:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2021-01-19 12:49:40 -08:00
goto out ;
2010-05-18 18:34:54 -07:00
}
} else {
/* Disallow if newname already exists. */
2021-01-19 12:49:40 -08:00
status = NT_STATUS_OBJECT_NAME_COLLISION ;
goto out ;
2010-05-18 18:34:54 -07:00
}
2004-03-03 23:14:23 +00:00
}
2009-07-21 11:35:17 -07:00
DEBUG ( 10 , ( " hardlink_internals: doing hard link %s -> %s \n " ,
smb_fname_old - > base_name , smb_fname_new - > base_name ) ) ;
2004-03-03 23:14:23 +00:00
2019-08-16 16:16:48 -07:00
ret = SMB_VFS_LINKAT ( conn ,
2021-01-19 12:57:51 -08:00
parent_fname_old - > fsp ,
base_name_old ,
parent_fname_new - > fsp ,
base_name_new ,
2019-08-16 16:16:48 -07:00
0 ) ;
if ( ret ! = 0 ) {
2004-03-03 23:14:23 +00:00
status = map_nt_error_from_unix ( errno ) ;
2004-04-06 23:01:09 +00:00
DEBUG ( 3 , ( " hardlink_internals: Error %s hard link %s -> %s \n " ,
2009-07-21 11:35:17 -07:00
nt_errstr ( status ) , smb_fname_old - > base_name ,
smb_fname_new - > base_name ) ) ;
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-07 13:39:57 -07:00
}
2021-01-19 12:49:40 -08:00
out :
2021-01-19 12:57:51 -08:00
TALLOC_FREE ( parent_fname_old ) ;
TALLOC_FREE ( parent_fname_new ) ;
2004-03-03 23:14:23 +00:00
return status ;
}
2007-01-31 00:49:49 +00:00
/****************************************************************************
Deal with setting the time from any of the setfilepathinfo functions .
2011-11-15 17:41:48 -08:00
NOTE ! ! ! ! The check for FILE_WRITE_ATTRIBUTES access must be done * before *
calling this function .
2007-01-31 00:49:49 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-03-12 15:39:38 +01:00
NTSTATUS smb_set_file_time ( connection_struct * conn ,
files_struct * fsp ,
2020-11-12 16:28:41 +01:00
struct smb_filename * smb_fname ,
2009-01-23 14:40:19 -08:00
struct smb_file_time * ft ,
2008-03-12 15:39:38 +01:00
bool setting_write_time )
2007-01-31 00:49:49 +00:00
{
2020-10-28 12:24:14 +01:00
struct files_struct * set_fsp = NULL ;
2019-12-02 16:30:50 +01:00
struct timeval_buf tbuf [ 4 ] ;
2015-04-26 16:02:55 -07:00
uint32_t action =
2007-02-03 16:53:52 +00:00
FILE_NOTIFY_CHANGE_LAST_ACCESS
2009-08-07 12:38:31 -07:00
| FILE_NOTIFY_CHANGE_LAST_WRITE
| FILE_NOTIFY_CHANGE_CREATION ;
2020-10-28 12:24:14 +01:00
int ret ;
2007-02-03 16:53:52 +00:00
2009-07-02 13:39:20 -07:00
if ( ! VALID_STAT ( smb_fname - > st ) ) {
2007-01-31 00:49:49 +00:00
return NT_STATUS_OBJECT_NAME_NOT_FOUND ;
}
2020-10-28 12:24:14 +01:00
if ( fsp = = NULL ) {
/* A symlink */
return NT_STATUS_OK ;
}
2022-02-11 09:45:30 +01:00
set_fsp = metadata_fsp ( fsp ) ;
2020-10-28 12:24:14 +01:00
2007-01-31 00:49:49 +00:00
/* get some defaults (no modifications) if any info is zero or -1. */
2019-12-02 16:30:50 +01:00
if ( is_omit_timespec ( & ft - > create_time ) ) {
2009-08-07 12:38:31 -07:00
action & = ~ FILE_NOTIFY_CHANGE_CREATION ;
2009-07-30 13:19:26 -07:00
}
2019-12-02 16:30:50 +01:00
if ( is_omit_timespec ( & ft - > atime ) ) {
2007-02-03 16:53:52 +00:00
action & = ~ FILE_NOTIFY_CHANGE_LAST_ACCESS ;
2007-01-31 00:49:49 +00:00
}
2019-12-02 16:30:50 +01:00
if ( is_omit_timespec ( & ft - > mtime ) ) {
2007-02-03 16:53:52 +00:00
action & = ~ FILE_NOTIFY_CHANGE_LAST_WRITE ;
2007-01-31 00:49:49 +00:00
}
2007-10-31 16:32:48 -07:00
if ( ! setting_write_time ) {
2009-01-23 14:40:19 -08:00
/* ft->mtime comes from change time, not write time. */
2007-10-31 16:32:48 -07:00
action & = ~ FILE_NOTIFY_CHANGE_LAST_WRITE ;
}
2009-08-24 20:57:37 -07:00
/* Ensure the resolution is the correct for
* what we can store on this filesystem . */
round_timespec ( conn - > ts_res , & ft - > create_time ) ;
round_timespec ( conn - > ts_res , & ft - > ctime ) ;
round_timespec ( conn - > ts_res , & ft - > atime ) ;
round_timespec ( conn - > ts_res , & ft - > mtime ) ;
2009-08-21 21:44:21 -07:00
2019-12-02 16:30:50 +01:00
DBG_DEBUG ( " smb_set_filetime: actime: %s \n " ,
timespec_string_buf ( & ft - > atime , true , & tbuf [ 0 ] ) ) ;
DBG_DEBUG ( " smb_set_filetime: modtime: %s \n " ,
timespec_string_buf ( & ft - > mtime , true , & tbuf [ 1 ] ) ) ;
DBG_DEBUG ( " smb_set_filetime: ctime: %s \n " ,
timespec_string_buf ( & ft - > ctime , true , & tbuf [ 2 ] ) ) ;
DBG_DEBUG ( " smb_set_file_time: createtime: %s \n " ,
timespec_string_buf ( & ft - > create_time , true , & tbuf [ 3 ] ) ) ;
2007-01-31 00:49:49 +00:00
2008-03-12 15:39:38 +01:00
if ( setting_write_time ) {
2007-01-31 00:49:49 +00:00
/*
2009-07-01 16:58:14 -07:00
* This was a Windows setfileinfo on an open file .
2022-12-12 12:53:22 +01:00
* NT does this a lot . We also need to
* set the time here , as it can be read by
2007-01-31 00:49:49 +00:00
* FindFirst / FindNext and with the patch for bug # 2045
* in smbd / fileio . c it ensures that this timestamp is
* kept sticky even after a write . We save the request
* away and will set it on file close and after a write . JRA .
*/
2019-12-02 16:30:50 +01:00
DBG_DEBUG ( " setting pending modtime to %s \n " ,
timespec_string_buf ( & ft - > mtime , true , & tbuf [ 0 ] ) ) ;
2007-01-31 00:49:49 +00:00
2020-10-28 12:24:14 +01:00
if ( set_fsp ! = NULL ) {
set_sticky_write_time_fsp ( set_fsp , ft - > mtime ) ;
2008-03-12 15:39:38 +01:00
} else {
2009-07-02 10:27:01 -07:00
set_sticky_write_time_path (
2009-07-02 13:39:20 -07:00
vfs_file_id_from_sbuf ( conn , & smb_fname - > st ) ,
ft - > mtime ) ;
2008-03-12 15:39:38 +01:00
}
2007-01-31 00:49:49 +00:00
}
2008-03-12 15:39:38 +01:00
2007-01-31 00:49:49 +00:00
DEBUG ( 10 , ( " smb_set_file_time: setting utimes to modified values. \n " ) ) ;
2021-04-13 17:05:57 +02:00
ret = file_ntimes ( conn , set_fsp , ft ) ;
2020-10-28 12:24:14 +01:00
if ( ret ! = 0 ) {
2007-01-31 00:49:49 +00:00
return map_nt_error_from_unix ( errno ) ;
}
2007-10-31 16:32:48 -07:00
2009-07-02 13:39:20 -07:00
notify_fname ( conn , NOTIFY_ACTION_MODIFIED , action ,
smb_fname - > base_name ) ;
2007-01-31 00:49:49 +00:00
return NT_STATUS_OK ;
}
/****************************************************************************
Deal with setting the dosmode from any of the setfilepathinfo functions .
2011-11-15 17:29:59 -08:00
NB . The check for FILE_WRITE_ATTRIBUTES access on this path must have been
done before calling this function .
2007-01-31 00:49:49 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static NTSTATUS smb_set_file_dosmode ( connection_struct * conn ,
2020-10-30 22:00:17 +01:00
struct files_struct * fsp ,
2015-04-26 16:02:55 -07:00
uint32_t dosmode )
2007-01-31 00:49:49 +00:00
{
2021-07-30 15:17:44 +02:00
struct files_struct * dos_fsp = NULL ;
uint32_t current_dosmode ;
int ret ;
2009-07-02 13:39:20 -07:00
2021-07-30 15:17:44 +02:00
if ( ! VALID_STAT ( fsp - > fsp_name - > st ) ) {
2007-01-31 00:49:49 +00:00
return NT_STATUS_OBJECT_NAME_NOT_FOUND ;
}
2022-02-11 09:45:30 +01:00
dos_fsp = metadata_fsp ( fsp ) ;
2021-02-18 11:01:10 +00:00
2021-07-30 15:17:44 +02:00
if ( dosmode ! = 0 ) {
if ( S_ISDIR ( fsp - > fsp_name - > st . st_ex_mode ) ) {
2011-04-29 11:57:02 +10:00
dosmode | = FILE_ATTRIBUTE_DIRECTORY ;
2007-01-31 00:49:49 +00:00
} else {
2011-04-29 11:57:02 +10:00
dosmode & = ~ FILE_ATTRIBUTE_DIRECTORY ;
2007-01-31 00:49:49 +00:00
}
}
2021-07-30 15:17:44 +02:00
DBG_DEBUG ( " dosmode: 0x% " PRIx32 " \n " , dosmode ) ;
2007-01-31 00:49:49 +00:00
/* check the mode isn't different, before changing it */
2021-07-30 15:17:44 +02:00
if ( dosmode = = 0 ) {
return NT_STATUS_OK ;
2007-01-31 00:49:49 +00:00
}
2021-07-30 15:17:44 +02:00
current_dosmode = fdos_mode ( dos_fsp ) ;
if ( dosmode = = current_dosmode ) {
return NT_STATUS_OK ;
}
DBG_DEBUG ( " file %s : setting dos mode 0x% " PRIx32 " \n " ,
fsp_str_dbg ( dos_fsp ) , dosmode ) ;
ret = file_set_dosmode ( conn , dos_fsp - > fsp_name , dosmode , NULL , false ) ;
if ( ret ! = 0 ) {
DBG_WARNING ( " file_set_dosmode of %s failed: %s \n " ,
fsp_str_dbg ( dos_fsp ) , strerror ( errno ) ) ;
return map_nt_error_from_unix ( errno ) ;
}
return NT_STATUS_OK ;
2007-01-31 00:49:49 +00:00
}
/****************************************************************************
Deal with setting the size from any of the setfilepathinfo functions .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2022-12-30 16:23:27 +01:00
NTSTATUS smb_set_file_size ( connection_struct * conn ,
struct smb_request * req ,
files_struct * fsp ,
struct smb_filename * smb_fname ,
const SMB_STRUCT_STAT * psbuf ,
off_t size ,
bool fail_after_createfile )
2007-01-31 00:49:49 +00:00
{
NTSTATUS status = NT_STATUS_OK ;
files_struct * new_fsp = NULL ;
if ( ! VALID_STAT ( * psbuf ) ) {
return NT_STATUS_OBJECT_NAME_NOT_FOUND ;
}
2018-08-07 15:09:04 +02:00
DBG_INFO ( " size: % " PRIu64 " , file_size_stat=% " PRIu64 " \n " ,
( uint64_t ) size ,
get_file_size_stat ( psbuf ) ) ;
2007-01-31 00:49:49 +00:00
2009-01-26 15:39:40 -08:00
if ( size = = get_file_size_stat ( psbuf ) ) {
2020-03-12 16:52:34 +01:00
if ( fsp = = NULL ) {
return NT_STATUS_OK ;
}
2020-04-02 17:37:02 +02:00
if ( ! fsp - > fsp_flags . modified ) {
2020-03-12 16:52:34 +01:00
return NT_STATUS_OK ;
}
trigger_write_time_update_immediate ( fsp ) ;
2007-01-31 00:49:49 +00:00
return NT_STATUS_OK ;
}
2007-02-08 19:42:27 +00:00
DEBUG ( 10 , ( " smb_set_file_size: file %s : setting new size to %.0f \n " ,
2009-07-02 09:27:44 -07:00
smb_fname_str_dbg ( smb_fname ) , ( double ) size ) ) ;
2007-01-31 00:49:49 +00:00
2020-09-26 21:52:52 +02:00
if ( fsp & &
! fsp - > fsp_flags . is_pathref & &
fsp_get_io_fd ( fsp ) ! = - 1 )
{
2007-01-31 00:49:49 +00:00
/* Handle based call. */
2011-11-15 16:22:09 -08:00
if ( ! ( fsp - > access_mask & FILE_WRITE_DATA ) ) {
return NT_STATUS_ACCESS_DENIED ;
}
2007-01-31 00:49:49 +00:00
if ( vfs_set_filelen ( fsp , size ) = = - 1 ) {
return map_nt_error_from_unix ( errno ) ;
}
2008-09-05 19:00:48 -07:00
trigger_write_time_update_immediate ( fsp ) ;
2007-01-31 00:49:49 +00:00
return NT_STATUS_OK ;
}
2008-11-20 18:55:24 -08:00
status = SMB_VFS_CREATE_FILE (
conn , /* conn */
req , /* req */
2021-11-23 12:29:17 +01:00
NULL , /* dirfsp */
2020-11-12 16:51:26 +01:00
smb_fname , /* fname */
2009-11-24 16:48:16 -08:00
FILE_WRITE_DATA , /* access_mask */
2008-11-20 18:55:24 -08:00
( FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
FILE_SHARE_DELETE ) ,
FILE_OPEN , /* create_disposition*/
0 , /* create_options */
FILE_ATTRIBUTE_NORMAL , /* file_attributes */
2013-09-04 17:26:30 +02:00
0 , /* oplock_request */
2013-08-21 13:56:14 +00:00
NULL , /* lease */
2008-11-20 18:55:24 -08:00
0 , /* allocation_size */
2010-03-05 15:10:30 -08:00
0 , /* private_flags */
2008-11-20 18:55:24 -08:00
NULL , /* sd */
NULL , /* ea_list */
& new_fsp , /* result */
2014-11-26 14:12:51 +01:00
NULL , /* pinfo */
NULL , NULL ) ; /* create context */
2009-06-12 12:54:11 -07:00
2007-01-31 00:49:49 +00:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
/* NB. We check for open_was_deferred in the caller. */
return status ;
}
2009-12-01 10:47:08 -08:00
/* See RAW-SFILEINFO-END-OF-FILE */
if ( fail_after_createfile ) {
2022-02-01 17:47:29 +01:00
close_file_free ( req , & new_fsp , NORMAL_CLOSE ) ;
2009-12-01 10:47:08 -08:00
return NT_STATUS_INVALID_LEVEL ;
}
2007-01-31 00:49:49 +00:00
if ( vfs_set_filelen ( new_fsp , size ) = = - 1 ) {
status = map_nt_error_from_unix ( errno ) ;
2022-02-01 17:47:29 +01:00
close_file_free ( req , & new_fsp , NORMAL_CLOSE ) ;
2007-01-31 00:49:49 +00:00
return status ;
}
2008-09-05 19:00:48 -07:00
trigger_write_time_update_immediate ( new_fsp ) ;
2022-02-01 17:47:29 +01:00
close_file_free ( req , & new_fsp , NORMAL_CLOSE ) ;
2007-01-31 00:49:49 +00:00
return NT_STATUS_OK ;
}
1996-05-04 07:50:46 +00:00
/****************************************************************************
2007-01-30 01:14:48 +00:00
Deal with SMB_INFO_SET_EA .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-01-30 20:49:37 +00:00
static NTSTATUS smb_info_set_ea ( connection_struct * conn ,
2007-01-30 18:45:19 +00:00
const char * pdata ,
2007-01-30 01:14:48 +00:00
int total_data ,
files_struct * fsp ,
2020-11-12 16:28:41 +01:00
struct smb_filename * smb_fname )
2007-01-30 01:14:48 +00:00
{
struct ea_list * ea_list = NULL ;
TALLOC_CTX * ctx = NULL ;
NTSTATUS status = NT_STATUS_OK ;
if ( total_data < 10 ) {
/* OS/2 workplace shell seems to send SET_EA requests of "null"
length . They seem to have no effect . Bug # 3212. JRA */
if ( ( total_data = = 4 ) & & ( IVAL ( pdata , 0 ) = = 4 ) ) {
/* We're done. We only get EA info in this call. */
2007-01-30 20:49:37 +00:00
return NT_STATUS_OK ;
2007-01-30 01:14:48 +00:00
}
2007-01-30 20:49:37 +00:00
return NT_STATUS_INVALID_PARAMETER ;
2007-01-30 01:14:48 +00:00
}
if ( IVAL ( pdata , 0 ) > total_data ) {
DEBUG ( 10 , ( " smb_info_set_ea: bad total data size (%u) > %u \n " ,
IVAL ( pdata , 0 ) , ( unsigned int ) total_data ) ) ;
2007-01-30 20:49:37 +00:00
return NT_STATUS_INVALID_PARAMETER ;
2007-01-30 01:14:48 +00:00
}
2008-01-09 17:11:04 -08:00
ctx = talloc_tos ( ) ;
2007-01-30 01:14:48 +00:00
ea_list = read_ea_list ( ctx , pdata + 4 , total_data - 4 ) ;
if ( ! ea_list ) {
2007-01-30 20:49:37 +00:00
return NT_STATUS_INVALID_PARAMETER ;
2007-01-30 01:14:48 +00:00
}
2010-11-23 15:59:33 -08:00
2020-12-14 12:07:48 -08:00
if ( fsp = = NULL ) {
/*
* The only way fsp can be NULL here is if
* smb_fname points at a symlink and
* and we ' re in POSIX context .
* Ensure this is the case .
*
2021-05-20 11:55:45 -07:00
* In this case we cannot set the EA .
2020-12-14 12:07:48 -08:00
*/
SMB_ASSERT ( smb_fname - > flags & SMB_FILENAME_POSIX_PATH ) ;
return NT_STATUS_ACCESS_DENIED ;
}
2020-12-14 12:15:48 -08:00
status = set_ea ( conn , fsp , ea_list ) ;
2007-01-30 01:14:48 +00:00
2007-01-30 20:49:37 +00:00
return status ;
2007-01-30 01:14:48 +00:00
}
2009-09-17 09:29:07 -07:00
/****************************************************************************
Deal with SMB_FILE_FULL_EA_INFORMATION set .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static NTSTATUS smb_set_file_full_ea_info ( connection_struct * conn ,
const char * pdata ,
int total_data ,
files_struct * fsp )
{
struct ea_list * ea_list = NULL ;
NTSTATUS status ;
2021-06-15 15:42:33 -07:00
if ( fsp = = NULL ) {
2009-09-17 09:29:07 -07:00
return NT_STATUS_INVALID_HANDLE ;
}
if ( ! lp_ea_support ( SNUM ( conn ) ) ) {
DEBUG ( 10 , ( " smb_set_file_full_ea_info - ea_len = %u but "
" EA's not supported. \n " ,
( unsigned int ) total_data ) ) ;
return NT_STATUS_EAS_NOT_SUPPORTED ;
}
if ( total_data < 10 ) {
DEBUG ( 10 , ( " smb_set_file_full_ea_info - ea_len = %u "
" too small. \n " ,
( unsigned int ) total_data ) ) ;
return NT_STATUS_INVALID_PARAMETER ;
}
ea_list = read_nttrans_ea_list ( talloc_tos ( ) ,
pdata ,
total_data ) ;
if ( ! ea_list ) {
return NT_STATUS_INVALID_PARAMETER ;
}
2010-11-23 15:59:33 -08:00
2020-12-14 12:15:48 -08:00
status = set_ea ( conn , fsp , ea_list ) ;
2009-09-17 09:29:07 -07:00
DEBUG ( 10 , ( " smb_set_file_full_ea_info on file %s returned %s \n " ,
smb_fname_str_dbg ( fsp - > fsp_name ) ,
nt_errstr ( status ) ) ) ;
return status ;
}
2007-01-30 01:36:45 +00:00
/****************************************************************************
Deal with SMB_SET_FILE_DISPOSITION_INFO .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2022-12-29 00:06:58 +01:00
NTSTATUS smb_set_file_disposition_info ( connection_struct * conn ,
const char * pdata ,
int total_data ,
files_struct * fsp ,
struct smb_filename * smb_fname )
2007-01-30 01:36:45 +00:00
{
NTSTATUS status = NT_STATUS_OK ;
2007-10-18 17:40:25 -07:00
bool delete_on_close ;
2015-04-26 16:02:55 -07:00
uint32_t dosmode = 0 ;
2007-01-30 01:36:45 +00:00
if ( total_data < 1 ) {
2007-01-30 20:49:37 +00:00
return NT_STATUS_INVALID_PARAMETER ;
2007-01-30 01:36:45 +00:00
}
if ( fsp = = NULL ) {
2007-01-30 20:49:37 +00:00
return NT_STATUS_INVALID_HANDLE ;
2007-01-30 01:36:45 +00:00
}
2007-01-30 01:46:14 +00:00
delete_on_close = ( CVAL ( pdata , 0 ) ? True : False ) ;
2020-10-19 21:09:00 +02:00
dosmode = fdos_mode ( fsp ) ;
2007-01-30 01:46:14 +00:00
2007-03-01 23:03:46 +00:00
DEBUG ( 10 , ( " smb_set_file_disposition_info: file %s, dosmode = %u, "
" delete_on_close = %u \n " ,
2009-07-08 12:24:03 -07:00
smb_fname_str_dbg ( smb_fname ) ,
2007-03-01 23:03:46 +00:00
( unsigned int ) dosmode ,
( unsigned int ) delete_on_close ) ) ;
2009-12-02 18:06:40 -08:00
if ( delete_on_close ) {
status = can_set_delete_on_close ( fsp , dosmode ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
2007-01-30 01:36:45 +00:00
}
/* The set is across all open files on this dev/inode pair. */
2008-06-19 18:36:54 +02:00
if ( ! set_delete_on_close ( fsp , delete_on_close ,
2012-04-04 14:54:02 -07:00
conn - > session_info - > security_token ,
2011-07-15 14:59:14 +10:00
conn - > session_info - > unix_token ) ) {
2007-01-30 20:49:37 +00:00
return NT_STATUS_ACCESS_DENIED ;
2007-01-30 01:36:45 +00:00
}
2007-01-30 20:49:37 +00:00
return NT_STATUS_OK ;
2007-01-30 01:36:45 +00:00
}
2007-01-30 01:46:14 +00:00
/****************************************************************************
Deal with SMB_FILE_POSITION_INFORMATION .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-01-30 20:49:37 +00:00
static NTSTATUS smb_file_position_information ( connection_struct * conn ,
2007-01-30 18:45:19 +00:00
const char * pdata ,
2007-01-30 01:46:14 +00:00
int total_data ,
files_struct * fsp )
{
2008-10-14 01:59:36 +02:00
uint64_t position_information ;
2007-01-30 01:46:14 +00:00
if ( total_data < 8 ) {
2007-01-30 20:49:37 +00:00
return NT_STATUS_INVALID_PARAMETER ;
2007-01-30 01:46:14 +00:00
}
2007-01-30 20:49:37 +00:00
if ( fsp = = NULL ) {
2007-01-30 02:13:58 +00:00
/* Ignore on pathname based set. */
2007-01-30 20:49:37 +00:00
return NT_STATUS_OK ;
2007-01-30 01:54:07 +00:00
}
2008-10-14 01:59:36 +02:00
position_information = ( uint64_t ) IVAL ( pdata , 0 ) ;
position_information | = ( ( ( uint64_t ) IVAL ( pdata , 4 ) ) < < 32 ) ;
2007-01-30 01:54:07 +00:00
2009-07-10 14:50:37 -07:00
DEBUG ( 10 , ( " smb_file_position_information: Set file position "
" information for file %s to %.0f \n " , fsp_str_dbg ( fsp ) ,
( double ) position_information ) ) ;
2020-09-28 10:32:29 +02:00
fh_set_position_information ( fsp - > fh , position_information ) ;
2007-01-30 20:49:37 +00:00
return NT_STATUS_OK ;
2007-01-30 01:46:14 +00:00
}
2007-01-30 01:54:07 +00:00
/****************************************************************************
Deal with SMB_FILE_MODE_INFORMATION .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-01-30 20:49:37 +00:00
static NTSTATUS smb_file_mode_information ( connection_struct * conn ,
2007-01-30 18:45:19 +00:00
const char * pdata ,
2007-01-30 20:49:37 +00:00
int total_data )
2007-01-30 01:54:07 +00:00
{
2015-04-26 16:02:55 -07:00
uint32_t mode ;
2007-01-30 01:54:07 +00:00
if ( total_data < 4 ) {
2007-01-30 20:49:37 +00:00
return NT_STATUS_INVALID_PARAMETER ;
2007-01-30 01:54:07 +00:00
}
mode = IVAL ( pdata , 0 ) ;
if ( mode ! = 0 & & mode ! = 2 & & mode ! = 4 & & mode ! = 6 ) {
2007-01-30 20:49:37 +00:00
return NT_STATUS_INVALID_PARAMETER ;
2007-01-30 01:54:07 +00:00
}
2007-01-30 20:49:37 +00:00
return NT_STATUS_OK ;
2007-01-30 01:54:07 +00:00
}
2010-02-25 11:15:16 -08:00
/****************************************************************************
Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static NTSTATUS smb2_file_rename_information ( connection_struct * conn ,
struct smb_request * req ,
const char * pdata ,
int total_data ,
files_struct * fsp ,
struct smb_filename * smb_fname_src )
{
bool overwrite ;
uint32_t len ;
char * newname = NULL ;
2022-07-28 12:29:22 -07:00
struct files_struct * dst_dirfsp = NULL ;
2010-02-25 11:15:16 -08:00
struct smb_filename * smb_fname_dst = NULL ;
2020-03-26 15:59:51 -07:00
const char * dst_original_lcomp = NULL ;
2020-03-26 16:27:25 -07:00
uint32_t ucf_flags = ucf_flags_from_smb_request ( req ) ;
2010-02-25 11:15:16 -08:00
NTSTATUS status = NT_STATUS_OK ;
TALLOC_CTX * ctx = talloc_tos ( ) ;
if ( ! fsp ) {
return NT_STATUS_INVALID_HANDLE ;
}
if ( total_data < 20 ) {
return NT_STATUS_INVALID_PARAMETER ;
}
overwrite = ( CVAL ( pdata , 0 ) ? True : False ) ;
len = IVAL ( pdata , 16 ) ;
if ( len > ( total_data - 20 ) | | ( len = = 0 ) ) {
return NT_STATUS_INVALID_PARAMETER ;
}
2022-08-09 10:43:45 -07:00
( void ) srvstr_pull_talloc ( ctx ,
pdata ,
req - > flags2 ,
& newname ,
& pdata [ 20 ] ,
len ,
STR_TERMINATE ) ;
if ( newname = = NULL ) {
return NT_STATUS_INVALID_PARAMETER ;
2015-12-22 13:26:49 -08:00
}
2023-03-27 12:01:56 -07:00
/* SMB2 rename paths are never DFS. */
req - > flags2 & = ~ FLAGS2_DFS_PATHNAMES ;
ucf_flags & = ~ UCF_DFS_PATHNAME ;
2023-03-31 11:44:00 +02:00
status = check_path_syntax ( newname ,
fsp - > fsp_name - > flags & SMB_FILENAME_POSIX_PATH ) ;
2010-02-25 11:15:16 -08:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
2010-02-25 11:57:54 -08:00
DEBUG ( 10 , ( " smb2_file_rename_information: got name |%s| \n " ,
2010-02-25 11:15:16 -08:00
newname ) ) ;
2022-07-29 14:38:17 -07:00
if ( newname [ 0 ] = = ' : ' ) {
2010-02-25 11:15:16 -08:00
/* Create an smb_fname to call rename_internals_fsp() with. */
2016-03-18 21:19:38 -07:00
smb_fname_dst = synthetic_smb_fname ( talloc_tos ( ) ,
fsp - > base_fsp - > fsp_name - > base_name ,
newname ,
NULL ,
2020-04-30 11:48:32 +02:00
fsp - > base_fsp - > fsp_name - > twrp ,
2016-03-18 21:19:38 -07:00
fsp - > base_fsp - > fsp_name - > flags ) ;
2013-04-15 10:53:16 +02:00
if ( smb_fname_dst = = NULL ) {
status = NT_STATUS_NO_MEMORY ;
2010-02-25 11:15:16 -08:00
goto out ;
}
2022-07-29 14:38:17 -07:00
} else {
2022-07-28 12:29:22 -07:00
status = filename_convert_dirfsp ( ctx ,
conn ,
newname ,
ucf_flags ,
2023-03-27 10:43:55 -07:00
0 , /* Never a TWRP. */
2022-07-28 12:29:22 -07:00
& dst_dirfsp ,
& smb_fname_dst ) ;
2022-07-29 14:38:17 -07:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto out ;
}
2020-03-26 15:59:51 -07:00
}
2010-02-25 11:15:16 -08:00
2020-03-26 15:59:51 -07:00
/*
* Set the original last component , since
* rename_internals_fsp ( ) requires it .
*/
dst_original_lcomp = get_original_lcomp ( smb_fname_dst ,
conn ,
newname ,
ucf_flags ) ;
if ( dst_original_lcomp = = NULL ) {
status = NT_STATUS_NO_MEMORY ;
goto out ;
2010-02-25 11:15:16 -08:00
}
2010-02-25 11:57:54 -08:00
DEBUG ( 10 , ( " smb2_file_rename_information: "
2012-06-14 13:31:43 +02:00
" SMB_FILE_RENAME_INFORMATION (%s) %s -> %s \n " ,
fsp_fnum_dbg ( fsp ) , fsp_str_dbg ( fsp ) ,
2010-02-25 11:15:16 -08:00
smb_fname_str_dbg ( smb_fname_dst ) ) ) ;
2020-03-25 13:42:34 -07:00
status = rename_internals_fsp ( conn ,
fsp ,
smb_fname_dst ,
2020-03-26 15:59:51 -07:00
dst_original_lcomp ,
2011-05-19 16:39:18 -07:00
( FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM ) ,
overwrite ) ;
2010-02-25 11:15:16 -08:00
out :
TALLOC_FREE ( smb_fname_dst ) ;
return status ;
}
2023-03-27 11:07:07 -07:00
static NTSTATUS smb2_file_link_information ( connection_struct * conn ,
struct smb_request * req ,
const char * pdata ,
int total_data ,
files_struct * fsp ,
struct smb_filename * smb_fname_src )
{
bool overwrite ;
uint32_t len ;
char * newname = NULL ;
struct files_struct * dst_dirfsp = NULL ;
struct smb_filename * smb_fname_dst = NULL ;
NTSTATUS status = NT_STATUS_OK ;
uint32_t ucf_flags = ucf_flags_from_smb_request ( req ) ;
2023-03-27 11:25:59 -07:00
size_t ret ;
2023-03-27 11:07:07 -07:00
TALLOC_CTX * ctx = talloc_tos ( ) ;
if ( ! fsp ) {
return NT_STATUS_INVALID_HANDLE ;
}
if ( total_data < 20 ) {
return NT_STATUS_INVALID_PARAMETER ;
}
overwrite = ( CVAL ( pdata , 0 ) ? true : false ) ;
len = IVAL ( pdata , 16 ) ;
if ( len > ( total_data - 20 ) | | ( len = = 0 ) ) {
return NT_STATUS_INVALID_PARAMETER ;
}
2023-03-27 11:25:59 -07:00
ret = srvstr_pull_talloc ( ctx ,
pdata ,
req - > flags2 ,
& newname ,
& pdata [ 20 ] ,
len ,
STR_TERMINATE ) ;
if ( ret = = ( size_t ) - 1 | | newname = = NULL ) {
return NT_STATUS_INVALID_PARAMETER ;
2023-03-27 11:07:07 -07:00
}
2023-03-27 11:25:59 -07:00
2023-03-27 12:01:56 -07:00
/* SMB2 hardlink paths are never DFS. */
req - > flags2 & = ~ FLAGS2_DFS_PATHNAMES ;
ucf_flags & = ~ UCF_DFS_PATHNAME ;
2023-03-31 11:44:00 +02:00
status = check_path_syntax ( newname ,
fsp - > fsp_name - > flags & SMB_FILENAME_POSIX_PATH ) ;
2023-03-27 11:07:07 -07:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
DBG_DEBUG ( " got name |%s| \n " , newname ) ;
status = filename_convert_dirfsp ( ctx ,
conn ,
newname ,
ucf_flags ,
2023-03-27 11:14:59 -07:00
0 , /* No TWRP. */
2023-03-27 11:07:07 -07:00
& dst_dirfsp ,
& smb_fname_dst ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
if ( fsp - > base_fsp ) {
/* No stream names. */
return NT_STATUS_NOT_SUPPORTED ;
}
DBG_DEBUG ( " SMB_FILE_LINK_INFORMATION (%s) %s -> %s \n " ,
fsp_fnum_dbg ( fsp ) , fsp_str_dbg ( fsp ) ,
smb_fname_str_dbg ( smb_fname_dst ) ) ;
status = hardlink_internals ( ctx ,
conn ,
req ,
overwrite ,
fsp - > fsp_name ,
smb_fname_dst ) ;
TALLOC_FREE ( smb_fname_dst ) ;
return status ;
}
2010-05-18 18:34:54 -07:00
static NTSTATUS smb_file_link_information ( connection_struct * conn ,
struct smb_request * req ,
const char * pdata ,
int total_data ,
files_struct * fsp ,
struct smb_filename * smb_fname_src )
{
bool overwrite ;
uint32_t len ;
char * newname = NULL ;
2022-07-28 12:32:07 -07:00
struct files_struct * dst_dirfsp = NULL ;
2010-05-18 18:34:54 -07:00
struct smb_filename * smb_fname_dst = NULL ;
NTSTATUS status = NT_STATUS_OK ;
2020-03-26 16:27:25 -07:00
uint32_t ucf_flags = ucf_flags_from_smb_request ( req ) ;
2022-07-28 12:32:07 -07:00
NTTIME dst_twrp = 0 ;
2010-05-18 18:34:54 -07:00
TALLOC_CTX * ctx = talloc_tos ( ) ;
if ( ! fsp ) {
return NT_STATUS_INVALID_HANDLE ;
}
if ( total_data < 20 ) {
return NT_STATUS_INVALID_PARAMETER ;
}
overwrite = ( CVAL ( pdata , 0 ) ? true : false ) ;
len = IVAL ( pdata , 16 ) ;
if ( len > ( total_data - 20 ) | | ( len = = 0 ) ) {
return NT_STATUS_INVALID_PARAMETER ;
}
2019-03-18 12:40:06 +01:00
if ( smb_fname_src - > flags & SMB_FILENAME_POSIX_PATH ) {
2015-12-22 13:26:49 -08:00
srvstr_get_path_posix ( ctx ,
pdata ,
req - > flags2 ,
& newname ,
& pdata [ 20 ] ,
len ,
STR_TERMINATE ,
2010-05-18 18:34:54 -07:00
& status ) ;
2019-03-18 12:40:06 +01:00
ucf_flags | = UCF_POSIX_PATHNAMES ;
2015-12-22 13:26:49 -08:00
} else {
srvstr_get_path ( ctx ,
pdata ,
req - > flags2 ,
& newname ,
& pdata [ 20 ] ,
len ,
STR_TERMINATE ,
& status ) ;
}
2010-05-18 18:34:54 -07:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
DEBUG ( 10 , ( " smb_file_link_information: got name |%s| \n " ,
newname ) ) ;
2022-07-28 12:32:07 -07:00
if ( ucf_flags & UCF_GMT_PATHNAME ) {
2022-08-04 10:02:15 -07:00
extract_snapshot_token ( newname , & dst_twrp ) ;
2022-07-28 12:32:07 -07:00
}
2023-03-30 13:02:01 -07:00
/* hardlink paths are never DFS. */
ucf_flags & = ~ UCF_DFS_PATHNAME ;
2022-07-28 12:32:07 -07:00
status = filename_convert_dirfsp ( ctx ,
conn ,
newname ,
ucf_flags ,
dst_twrp ,
& dst_dirfsp ,
& smb_fname_dst ) ;
2010-05-18 18:34:54 -07:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
if ( fsp - > base_fsp ) {
/* No stream names. */
return NT_STATUS_NOT_SUPPORTED ;
}
DEBUG ( 10 , ( " smb_file_link_information: "
2012-06-14 13:31:43 +02:00
" SMB_FILE_LINK_INFORMATION (%s) %s -> %s \n " ,
fsp_fnum_dbg ( fsp ) , fsp_str_dbg ( fsp ) ,
2010-05-18 18:34:54 -07:00
smb_fname_str_dbg ( smb_fname_dst ) ) ) ;
status = hardlink_internals ( ctx ,
conn ,
req ,
overwrite ,
fsp - > fsp_name ,
smb_fname_dst ) ;
TALLOC_FREE ( smb_fname_dst ) ;
return status ;
}
2010-02-25 11:15:16 -08:00
2023-03-27 11:07:07 -07:00
2007-01-30 18:16:51 +00:00
/****************************************************************************
Deal with SMB_FILE_RENAME_INFORMATION .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-01-30 20:49:37 +00:00
static NTSTATUS smb_file_rename_information ( connection_struct * conn ,
2007-07-05 16:26:27 +00:00
struct smb_request * req ,
2007-09-07 20:57:01 +00:00
const char * pdata ,
int total_data ,
files_struct * fsp ,
2009-07-24 11:39:56 -07:00
struct smb_filename * smb_fname_src )
2007-01-30 18:16:51 +00:00
{
2007-10-18 17:40:25 -07:00
bool overwrite ;
2015-04-26 16:02:55 -07:00
uint32_t root_fid ;
uint32_t len ;
2007-09-11 18:31:29 +00:00
char * newname = NULL ;
2022-07-28 12:38:47 -07:00
struct files_struct * dst_dirfsp = NULL ;
2009-07-24 11:39:56 -07:00
struct smb_filename * smb_fname_dst = NULL ;
2020-03-26 16:18:53 -07:00
const char * dst_original_lcomp = NULL ;
2007-01-30 18:16:51 +00:00
NTSTATUS status = NT_STATUS_OK ;
char * p ;
2007-09-11 18:31:29 +00:00
TALLOC_CTX * ctx = talloc_tos ( ) ;
2007-01-30 18:16:51 +00:00
if ( total_data < 13 ) {
2007-01-30 20:49:37 +00:00
return NT_STATUS_INVALID_PARAMETER ;
2007-01-30 18:16:51 +00:00
}
2022-06-17 09:38:24 +02:00
overwrite = ( CVAL ( pdata , 0 ) ! = 0 ) ;
2007-06-14 14:45:37 +00:00
root_fid = IVAL ( pdata , 4 ) ;
2007-01-30 18:16:51 +00:00
len = IVAL ( pdata , 8 ) ;
2007-06-14 14:45:37 +00:00
if ( len > ( total_data - 12 ) | | ( len = = 0 ) | | ( root_fid ! = 0 ) ) {
2007-01-30 20:49:37 +00:00
return NT_STATUS_INVALID_PARAMETER ;
2007-01-30 18:16:51 +00:00
}
2015-12-22 13:49:55 -08:00
if ( req - > posix_pathnames ) {
2020-09-29 13:47:08 -07:00
srvstr_get_path_posix ( ctx ,
2015-12-22 13:13:44 -08:00
pdata ,
req - > flags2 ,
& newname ,
& pdata [ 12 ] ,
len ,
0 ,
2020-09-29 13:47:08 -07:00
& status ) ;
2015-12-22 13:13:44 -08:00
} else {
2020-09-29 13:47:08 -07:00
srvstr_get_path ( ctx ,
2015-12-22 13:13:44 -08:00
pdata ,
req - > flags2 ,
& newname ,
& pdata [ 12 ] ,
len ,
0 ,
2020-09-29 13:47:08 -07:00
& status ) ;
2015-12-22 13:13:44 -08:00
}
2007-01-30 18:16:51 +00:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-01-30 20:49:37 +00:00
return status ;
2007-01-30 18:16:51 +00:00
}
2007-09-11 23:57:59 +00:00
DEBUG ( 10 , ( " smb_file_rename_information: got name |%s| \n " ,
newname ) ) ;
2007-01-30 18:16:51 +00:00
/* Check the new name has no '/' characters. */
2007-09-11 18:31:29 +00:00
if ( strchr_m ( newname , ' / ' ) ) {
2007-01-30 20:49:37 +00:00
return NT_STATUS_NOT_SUPPORTED ;
2007-01-30 18:16:51 +00:00
}
2008-12-01 13:31:43 -08:00
if ( fsp & & fsp - > base_fsp ) {
2008-12-19 13:59:12 -08:00
/* newname must be a stream name. */
2008-12-01 13:31:43 -08:00
if ( newname [ 0 ] ! = ' : ' ) {
return NT_STATUS_NOT_SUPPORTED ;
}
2009-06-30 17:04:38 -07:00
/* Create an smb_fname to call rename_internals_fsp() with. */
2016-03-18 21:19:38 -07:00
smb_fname_dst = synthetic_smb_fname ( talloc_tos ( ) ,
fsp - > base_fsp - > fsp_name - > base_name ,
newname ,
NULL ,
2020-04-30 11:48:32 +02:00
fsp - > base_fsp - > fsp_name - > twrp ,
2016-03-18 21:19:38 -07:00
fsp - > base_fsp - > fsp_name - > flags ) ;
2013-04-15 10:54:22 +02:00
if ( smb_fname_dst = = NULL ) {
status = NT_STATUS_NO_MEMORY ;
2009-06-30 17:04:38 -07:00
goto out ;
}
/*
2020-03-26 16:18:53 -07:00
* Get the original last component , since
2009-06-30 17:04:38 -07:00
* rename_internals_fsp ( ) requires it .
*/
2020-03-26 16:18:53 -07:00
dst_original_lcomp = get_original_lcomp ( smb_fname_dst ,
conn ,
newname ,
0 ) ;
if ( dst_original_lcomp = = NULL ) {
2009-06-30 17:04:38 -07:00
status = NT_STATUS_NO_MEMORY ;
goto out ;
}
2007-05-23 21:32:10 +00:00
} else {
2009-07-24 11:39:56 -07:00
/*
* Build up an smb_fname_dst based on the filename passed in .
* We basically just strip off the last component , and put on
* the newname instead .
*/
char * base_name = NULL ;
2021-12-01 16:07:07 -08:00
uint32_t ucf_flags = ucf_flags_from_smb_request ( req ) ;
2022-07-28 12:38:47 -07:00
NTTIME dst_twrp = 0 ;
2009-07-24 11:39:56 -07:00
2008-12-19 13:59:12 -08:00
/* newname must *not* be a stream name. */
2009-07-08 14:08:04 -07:00
if ( newname [ 0 ] = = ' : ' ) {
2008-12-01 13:31:43 -08:00
return NT_STATUS_NOT_SUPPORTED ;
}
2009-07-24 11:39:56 -07:00
/*
* Strip off the last component ( filename ) of the path passed
* in .
*/
base_name = talloc_strdup ( ctx , smb_fname_src - > base_name ) ;
2008-12-01 13:31:43 -08:00
if ( ! base_name ) {
return NT_STATUS_NO_MEMORY ;
}
p = strrchr_m ( base_name , ' / ' ) ;
if ( p ) {
p [ 1 ] = ' \0 ' ;
} else {
2011-01-20 16:30:28 -08:00
base_name = talloc_strdup ( ctx , " " ) ;
2008-12-01 13:31:43 -08:00
if ( ! base_name ) {
return NT_STATUS_NO_MEMORY ;
}
}
/* Append the new name. */
base_name = talloc_asprintf_append ( base_name ,
" %s " ,
newname ) ;
2007-09-12 21:48:20 +00:00
if ( ! base_name ) {
return NT_STATUS_NO_MEMORY ;
}
2007-08-19 19:57:55 +00:00
2022-07-28 12:38:47 -07:00
if ( ucf_flags & UCF_GMT_PATHNAME ) {
2022-08-04 10:02:15 -07:00
extract_snapshot_token ( base_name , & dst_twrp ) ;
2022-07-28 12:38:47 -07:00
}
2023-03-30 13:02:01 -07:00
/* The newname is *not* a DFS path. */
ucf_flags & = ~ UCF_DFS_PATHNAME ;
2022-07-28 12:38:47 -07:00
status = filename_convert_dirfsp ( ctx ,
conn ,
base_name ,
ucf_flags ,
dst_twrp ,
& dst_dirfsp ,
& smb_fname_dst ) ;
2007-08-19 19:57:55 +00:00
2009-06-30 17:04:38 -07:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2021-12-09 16:35:17 -08:00
goto out ;
2007-08-19 19:57:55 +00:00
}
2020-03-26 16:18:53 -07:00
dst_original_lcomp = get_original_lcomp ( smb_fname_dst ,
conn ,
newname ,
ucf_flags ) ;
if ( dst_original_lcomp = = NULL ) {
status = NT_STATUS_NO_MEMORY ;
goto out ;
}
2008-12-19 13:59:12 -08:00
}
2007-08-19 19:57:55 +00:00
2020-11-17 12:11:13 +01:00
if ( fsp ! = NULL & & fsp - > fsp_flags . is_fsa ) {
2009-07-10 14:50:37 -07:00
DEBUG ( 10 , ( " smb_file_rename_information: "
2012-06-14 13:31:43 +02:00
" SMB_FILE_RENAME_INFORMATION (%s) %s -> %s \n " ,
fsp_fnum_dbg ( fsp ) , fsp_str_dbg ( fsp ) ,
2009-07-24 11:39:56 -07:00
smb_fname_str_dbg ( smb_fname_dst ) ) ) ;
2020-03-25 13:42:34 -07:00
status = rename_internals_fsp ( conn ,
fsp ,
smb_fname_dst ,
2020-03-26 16:18:53 -07:00
dst_original_lcomp ,
2020-03-25 13:42:34 -07:00
0 ,
overwrite ) ;
2007-01-30 18:16:51 +00:00
} else {
2009-07-10 14:50:37 -07:00
DEBUG ( 10 , ( " smb_file_rename_information: "
" SMB_FILE_RENAME_INFORMATION %s -> %s \n " ,
2009-07-24 11:39:56 -07:00
smb_fname_str_dbg ( smb_fname_src ) ,
smb_fname_str_dbg ( smb_fname_dst ) ) ) ;
2020-03-25 13:42:34 -07:00
status = rename_internals ( ctx ,
conn ,
req ,
2022-07-28 11:08:17 -07:00
NULL , /* src_dirfsp */
2020-03-25 13:42:34 -07:00
smb_fname_src ,
smb_fname_dst ,
2020-03-26 16:18:53 -07:00
dst_original_lcomp ,
2020-03-25 13:42:34 -07:00
0 ,
overwrite ,
FILE_WRITE_ATTRIBUTES ) ;
2007-01-30 18:16:51 +00:00
}
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-07 13:39:57 -07:00
out :
2009-07-24 11:39:56 -07:00
TALLOC_FREE ( smb_fname_dst ) ;
2007-01-30 20:49:37 +00:00
return status ;
2007-01-30 18:16:51 +00:00
}
2007-01-30 19:26:01 +00:00
/****************************************************************************
Deal with SMB_SET_FILE_BASIC_INFO .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-01-31 00:49:49 +00:00
static NTSTATUS smb_set_file_basic_info ( connection_struct * conn ,
const char * pdata ,
2007-01-30 22:20:55 +00:00
int total_data ,
2007-01-31 00:49:49 +00:00
files_struct * fsp ,
2020-11-12 16:28:41 +01:00
struct smb_filename * smb_fname )
2007-01-30 19:26:01 +00:00
{
/* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
2009-01-23 14:40:19 -08:00
struct smb_file_time ft ;
2015-04-26 16:02:55 -07:00
uint32_t dosmode = 0 ;
2007-01-31 00:49:49 +00:00
NTSTATUS status = NT_STATUS_OK ;
2007-01-30 19:26:01 +00:00
2019-12-02 16:30:50 +01:00
init_smb_file_time ( & ft ) ;
2009-01-23 14:40:19 -08:00
2007-01-30 19:26:01 +00:00
if ( total_data < 36 ) {
return NT_STATUS_INVALID_PARAMETER ;
}
2021-06-15 15:42:33 -07:00
if ( fsp = = NULL ) {
return NT_STATUS_INVALID_HANDLE ;
}
2020-10-27 21:13:12 +01:00
status = check_access_fsp ( fsp , FILE_WRITE_ATTRIBUTES ) ;
2011-11-15 17:29:59 -08:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
2010-11-23 15:59:33 -08:00
}
2007-01-31 00:49:49 +00:00
/* Set the attributes */
dosmode = IVAL ( pdata , 32 ) ;
2021-07-30 15:17:44 +02:00
status = smb_set_file_dosmode ( conn , fsp , dosmode ) ;
2007-01-31 00:49:49 +00:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
2009-01-23 14:40:19 -08:00
/* create time */
2019-12-03 09:55:47 +01:00
ft . create_time = pull_long_date_full_timespec ( pdata ) ;
2007-01-30 19:26:01 +00:00
2009-07-30 13:16:40 -07:00
/* access time */
2019-12-03 09:55:47 +01:00
ft . atime = pull_long_date_full_timespec ( pdata + 8 ) ;
2007-03-05 23:40:03 +00:00
2009-07-30 13:16:40 -07:00
/* write time. */
2019-12-03 09:55:47 +01:00
ft . mtime = pull_long_date_full_timespec ( pdata + 16 ) ;
2009-07-30 13:16:40 -07:00
/* change time. */
2019-12-03 09:55:47 +01:00
ft . ctime = pull_long_date_full_timespec ( pdata + 24 ) ;
2007-01-30 19:26:01 +00:00
2009-07-02 13:39:20 -07:00
DEBUG ( 10 , ( " smb_set_file_basic_info: file %s \n " ,
smb_fname_str_dbg ( smb_fname ) ) ) ;
2007-03-01 22:44:02 +00:00
2020-03-12 19:23:40 +01:00
status = smb_set_file_time ( conn , fsp , smb_fname , & ft , true ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
2021-06-10 09:05:53 +02:00
if ( fsp - > fsp_flags . modified ) {
2020-03-12 19:23:40 +01:00
trigger_write_time_update_immediate ( fsp ) ;
}
return NT_STATUS_OK ;
2007-01-30 19:26:01 +00:00
}
2009-08-06 12:50:16 -07:00
/****************************************************************************
Deal with SMB_INFO_STANDARD .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static NTSTATUS smb_set_info_standard ( connection_struct * conn ,
const char * pdata ,
int total_data ,
files_struct * fsp ,
2020-11-12 16:28:41 +01:00
struct smb_filename * smb_fname )
2009-08-06 12:50:16 -07:00
{
2011-11-15 17:29:59 -08:00
NTSTATUS status ;
2009-08-06 12:50:16 -07:00
struct smb_file_time ft ;
2019-12-02 16:30:50 +01:00
init_smb_file_time ( & ft ) ;
2009-08-06 12:50:16 -07:00
if ( total_data < 12 ) {
return NT_STATUS_INVALID_PARAMETER ;
}
2021-06-15 15:42:33 -07:00
if ( fsp = = NULL ) {
return NT_STATUS_INVALID_HANDLE ;
}
2009-08-06 12:50:16 -07:00
/* create time */
2019-12-02 16:30:50 +01:00
ft . create_time = time_t_to_full_timespec ( srv_make_unix_date2 ( pdata ) ) ;
2009-08-06 12:50:16 -07:00
/* access time */
2019-12-02 16:30:50 +01:00
ft . atime = time_t_to_full_timespec ( srv_make_unix_date2 ( pdata + 4 ) ) ;
2009-08-06 12:50:16 -07:00
/* write time */
2019-12-02 16:30:50 +01:00
ft . mtime = time_t_to_full_timespec ( srv_make_unix_date2 ( pdata + 8 ) ) ;
2009-08-06 12:50:16 -07:00
DEBUG ( 10 , ( " smb_set_info_standard: file %s \n " ,
smb_fname_str_dbg ( smb_fname ) ) ) ;
2020-10-27 21:13:36 +01:00
status = check_access_fsp ( fsp , FILE_WRITE_ATTRIBUTES ) ;
2011-11-15 17:29:59 -08:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
2011-11-15 17:41:48 -08:00
}
2020-03-12 19:23:40 +01:00
status = smb_set_file_time ( conn , fsp , smb_fname , & ft , true ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
2021-06-10 09:05:53 +02:00
if ( fsp - > fsp_flags . modified ) {
2020-03-12 19:23:40 +01:00
trigger_write_time_update_immediate ( fsp ) ;
}
return NT_STATUS_OK ;
2009-08-06 12:50:16 -07:00
}
2007-01-30 19:54:28 +00:00
/****************************************************************************
Deal with SMB_SET_FILE_ALLOCATION_INFO .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static NTSTATUS smb_set_file_allocation_info ( connection_struct * conn ,
2007-07-05 16:26:27 +00:00
struct smb_request * req ,
2007-01-30 19:54:28 +00:00
const char * pdata ,
int total_data ,
files_struct * fsp ,
2009-07-08 17:53:05 -07:00
struct smb_filename * smb_fname )
2007-01-30 19:54:28 +00:00
{
2008-10-14 01:59:36 +02:00
uint64_t allocation_size = 0 ;
2007-01-31 00:49:49 +00:00
NTSTATUS status = NT_STATUS_OK ;
files_struct * new_fsp = NULL ;
2009-07-08 17:53:05 -07:00
if ( ! VALID_STAT ( smb_fname - > st ) ) {
2007-01-31 00:49:49 +00:00
return NT_STATUS_OBJECT_NAME_NOT_FOUND ;
}
2007-01-30 19:54:28 +00:00
if ( total_data < 8 ) {
return NT_STATUS_INVALID_PARAMETER ;
}
2008-10-14 01:59:36 +02:00
allocation_size = ( uint64_t ) IVAL ( pdata , 0 ) ;
allocation_size | = ( ( ( uint64_t ) IVAL ( pdata , 4 ) ) < < 32 ) ;
2009-07-08 17:53:05 -07:00
DEBUG ( 10 , ( " smb_set_file_allocation_info: Set file allocation info for "
" file %s to %.0f \n " , smb_fname_str_dbg ( smb_fname ) ,
( double ) allocation_size ) ) ;
2007-01-30 19:54:28 +00:00
if ( allocation_size ) {
allocation_size = smb_roundup ( conn , allocation_size ) ;
}
2009-07-08 17:53:05 -07:00
DEBUG ( 10 , ( " smb_set_file_allocation_info: file %s : setting new "
" allocation size to %.0f \n " , smb_fname_str_dbg ( smb_fname ) ,
( double ) allocation_size ) ) ;
2007-07-12 18:11:41 +00:00
2020-09-26 21:52:52 +02:00
if ( fsp & &
! fsp - > fsp_flags . is_pathref & &
fsp_get_io_fd ( fsp ) ! = - 1 )
{
2007-01-31 00:49:49 +00:00
/* Open file handle. */
2011-11-15 16:14:16 -08:00
if ( ! ( fsp - > access_mask & FILE_WRITE_DATA ) ) {
return NT_STATUS_ACCESS_DENIED ;
}
2007-07-12 18:11:41 +00:00
/* Only change if needed. */
2009-07-08 17:53:05 -07:00
if ( allocation_size ! = get_file_size_stat ( & smb_fname - > st ) ) {
2007-07-12 18:11:41 +00:00
if ( vfs_allocate_file_space ( fsp , allocation_size ) = = - 1 ) {
return map_nt_error_from_unix ( errno ) ;
}
}
/* But always update the time. */
2008-03-12 15:39:38 +01:00
/*
* This is equivalent to a write . Ensure it ' s seen immediately
* if there are no pending writes .
*/
2008-09-05 19:00:48 -07:00
trigger_write_time_update_immediate ( fsp ) ;
2007-01-31 00:49:49 +00:00
return NT_STATUS_OK ;
}
/* Pathname or stat or directory file. */
2009-07-08 17:53:05 -07:00
status = SMB_VFS_CREATE_FILE (
2008-11-20 18:55:24 -08:00
conn , /* conn */
req , /* req */
2021-11-23 12:29:17 +01:00
NULL , /* dirfsp */
2009-06-12 12:54:11 -07:00
smb_fname , /* fname */
2008-11-20 18:55:24 -08:00
FILE_WRITE_DATA , /* access_mask */
( FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
FILE_SHARE_DELETE ) ,
FILE_OPEN , /* create_disposition*/
0 , /* create_options */
FILE_ATTRIBUTE_NORMAL , /* file_attributes */
2013-09-04 17:26:30 +02:00
0 , /* oplock_request */
2013-08-21 13:56:14 +00:00
NULL , /* lease */
2008-11-20 18:55:24 -08:00
0 , /* allocation_size */
2010-03-05 15:10:30 -08:00
0 , /* private_flags */
2008-11-20 18:55:24 -08:00
NULL , /* sd */
NULL , /* ea_list */
& new_fsp , /* result */
2014-11-26 14:12:51 +01:00
NULL , /* pinfo */
NULL , NULL ) ; /* create context */
2009-06-12 12:54:11 -07:00
2007-01-31 00:49:49 +00:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
/* NB. We check for open_was_deferred in the caller. */
return status ;
2007-01-30 19:54:28 +00:00
}
2007-07-12 18:11:41 +00:00
/* Only change if needed. */
2009-07-08 17:53:05 -07:00
if ( allocation_size ! = get_file_size_stat ( & smb_fname - > st ) ) {
2007-07-12 18:11:41 +00:00
if ( vfs_allocate_file_space ( new_fsp , allocation_size ) = = - 1 ) {
status = map_nt_error_from_unix ( errno ) ;
2022-02-01 17:47:29 +01:00
close_file_free ( req , & new_fsp , NORMAL_CLOSE ) ;
2007-07-12 18:11:41 +00:00
return status ;
}
2007-01-31 00:49:49 +00:00
}
2007-07-12 18:11:41 +00:00
/* Changing the allocation size should set the last mod time. */
2008-03-12 15:39:38 +01:00
/*
* This is equivalent to a write . Ensure it ' s seen immediately
* if there are no pending writes .
*/
2008-09-05 19:00:48 -07:00
trigger_write_time_update_immediate ( new_fsp ) ;
2022-02-01 17:47:29 +01:00
close_file_free ( req , & new_fsp , NORMAL_CLOSE ) ;
2007-01-30 19:54:28 +00:00
return NT_STATUS_OK ;
}
2007-01-30 20:49:37 +00:00
/****************************************************************************
Deal with SMB_SET_FILE_END_OF_FILE_INFO .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static NTSTATUS smb_set_file_end_of_file_info ( connection_struct * conn ,
2007-07-05 16:26:27 +00:00
struct smb_request * req ,
2007-01-30 20:49:37 +00:00
const char * pdata ,
int total_data ,
2007-01-31 00:49:49 +00:00
files_struct * fsp ,
2020-11-12 16:28:41 +01:00
struct smb_filename * smb_fname ,
2009-12-01 10:47:08 -08:00
bool fail_after_createfile )
2007-01-30 20:49:37 +00:00
{
2012-04-05 14:53:08 +10:00
off_t size ;
2007-01-31 00:49:49 +00:00
2007-01-30 20:49:37 +00:00
if ( total_data < 8 ) {
return NT_STATUS_INVALID_PARAMETER ;
}
2007-01-31 00:49:49 +00:00
size = IVAL ( pdata , 0 ) ;
2012-04-05 14:53:08 +10:00
size | = ( ( ( off_t ) IVAL ( pdata , 4 ) ) < < 32 ) ;
2007-01-30 20:49:37 +00:00
DEBUG ( 10 , ( " smb_set_file_end_of_file_info: Set end of file info for "
2009-07-02 09:27:44 -07:00
" file %s to %.0f \n " , smb_fname_str_dbg ( smb_fname ) ,
( double ) size ) ) ;
2007-01-31 00:49:49 +00:00
2007-07-05 16:26:27 +00:00
return smb_set_file_size ( conn , req ,
2007-01-31 00:49:49 +00:00
fsp ,
2009-07-02 09:27:44 -07:00
smb_fname ,
& smb_fname - > st ,
2009-12-01 10:47:08 -08:00
size ,
fail_after_createfile ) ;
2007-01-31 00:49:49 +00:00
}
2022-03-21 12:29:26 -06:00
NTSTATUS smbd_do_setfilepathinfo ( connection_struct * conn ,
struct smb_request * req ,
TALLOC_CTX * mem_ctx ,
uint16_t info_level ,
files_struct * fsp ,
struct smb_filename * smb_fname ,
char * * ppdata , int total_data ,
int * ret_data_size )
2000-03-08 22:14:30 +00:00
{
2022-03-21 12:29:26 -06:00
char * pdata = * ppdata ;
2007-04-03 22:59:55 +00:00
NTSTATUS status = NT_STATUS_OK ;
2022-03-21 12:29:26 -06:00
int data_return_size = 0 ;
2000-03-13 17:38:13 +00:00
2022-03-21 12:29:26 -06:00
* ret_data_size = 0 ;
DEBUG ( 3 , ( " smbd_do_setfilepathinfo: %s (%s) info_level=%d "
" totdata=%d \n " , smb_fname_str_dbg ( smb_fname ) ,
fsp_fnum_dbg ( fsp ) ,
info_level , total_data ) ) ;
switch ( info_level ) {
case SMB_INFO_STANDARD :
{
status = smb_set_info_standard ( conn ,
pdata ,
total_data ,
fsp ,
smb_fname ) ;
break ;
}
case SMB_INFO_SET_EA :
{
status = smb_info_set_ea ( conn ,
pdata ,
total_data ,
fsp ,
smb_fname ) ;
break ;
}
case SMB_SET_FILE_BASIC_INFO :
case SMB_FILE_BASIC_INFORMATION :
{
status = smb_set_file_basic_info ( conn ,
pdata ,
total_data ,
fsp ,
smb_fname ) ;
break ;
}
case SMB_FILE_ALLOCATION_INFORMATION :
case SMB_SET_FILE_ALLOCATION_INFO :
{
status = smb_set_file_allocation_info ( conn , req ,
pdata ,
total_data ,
fsp ,
smb_fname ) ;
break ;
}
2000-03-08 22:14:30 +00:00
2022-03-21 12:29:26 -06:00
case SMB_FILE_END_OF_FILE_INFORMATION :
case SMB_SET_FILE_END_OF_FILE_INFO :
{
/*
* XP / Win7 both fail after the createfile with
* SMB_SET_FILE_END_OF_FILE_INFO but not
* SMB_FILE_END_OF_FILE_INFORMATION ( pass - through ) .
* The level is known here , so pass it down
* appropriately .
*/
bool should_fail =
( info_level = = SMB_SET_FILE_END_OF_FILE_INFO ) ;
2000-03-08 22:14:30 +00:00
2022-03-21 12:29:26 -06:00
status = smb_set_file_end_of_file_info ( conn , req ,
pdata ,
total_data ,
fsp ,
smb_fname ,
should_fail ) ;
break ;
}
2007-09-11 23:57:59 +00:00
2022-03-21 12:29:26 -06:00
case SMB_FILE_DISPOSITION_INFORMATION :
case SMB_SET_FILE_DISPOSITION_INFO : /* Set delete on close for open file. */
{
#if 0
2022-12-12 12:53:22 +01:00
/* JRA - We used to just ignore this on a path ?
2022-03-21 12:29:26 -06:00
* Shouldn ' t this be invalid level on a pathname
* based call ?
*/
if ( tran_call ! = TRANSACT2_SETFILEINFO ) {
return ERROR_NT ( NT_STATUS_INVALID_LEVEL ) ;
}
# endif
status = smb_set_file_disposition_info ( conn ,
pdata ,
total_data ,
fsp ,
smb_fname ) ;
break ;
}
2000-03-10 22:53:36 +00:00
2022-03-21 12:29:26 -06:00
case SMB_FILE_POSITION_INFORMATION :
{
status = smb_file_position_information ( conn ,
pdata ,
total_data ,
fsp ) ;
break ;
}
2000-03-08 22:14:30 +00:00
2022-03-21 12:29:26 -06:00
case SMB_FILE_FULL_EA_INFORMATION :
{
status = smb_set_file_full_ea_info ( conn ,
pdata ,
total_data ,
fsp ) ;
break ;
}
2001-03-23 03:12:58 +00:00
2022-12-12 12:53:22 +01:00
/* From tridge Samba4 :
2022-03-21 12:29:26 -06:00
* MODE_INFORMATION in setfileinfo ( I have no
* idea what " mode information " on a file is - it takes a value of 0 ,
* 2 , 4 or 6. What could it be ? ) .
*/
2001-03-23 03:12:58 +00:00
2022-03-21 12:29:26 -06:00
case SMB_FILE_MODE_INFORMATION :
{
status = smb_file_mode_information ( conn ,
pdata ,
total_data ) ;
break ;
}
2003-10-30 15:57:52 +00:00
2022-03-21 12:29:26 -06:00
/* [MS-SMB2] 3.3.5.21.1 states we MUST fail with STATUS_NOT_SUPPORTED. */
case SMB_FILE_VALID_DATA_LENGTH_INFORMATION :
case SMB_FILE_SHORT_NAME_INFORMATION :
return NT_STATUS_NOT_SUPPORTED ;
2007-09-11 23:57:59 +00:00
2022-03-21 12:29:26 -06:00
case SMB_FILE_RENAME_INFORMATION :
{
status = smb_file_rename_information ( conn , req ,
pdata , total_data ,
fsp , smb_fname ) ;
break ;
}
2003-10-30 15:57:52 +00:00
2022-03-21 12:29:26 -06:00
case SMB2_FILE_RENAME_INFORMATION_INTERNAL :
{
/* SMB2 rename information. */
status = smb2_file_rename_information ( conn , req ,
pdata , total_data ,
fsp , smb_fname ) ;
break ;
2005-03-22 02:14:38 +00:00
}
2002-07-15 10:35:28 +00:00
2022-03-21 12:29:26 -06:00
case SMB_FILE_LINK_INFORMATION :
{
2023-03-27 11:07:07 -07:00
if ( conn - > sconn - > using_smb2 ) {
status = smb2_file_link_information ( conn ,
req ,
pdata ,
total_data ,
fsp ,
smb_fname ) ;
} else {
status = smb_file_link_information ( conn ,
req ,
pdata ,
total_data ,
fsp ,
smb_fname ) ;
}
2022-03-21 12:29:26 -06:00
break ;
}
2002-07-15 10:35:28 +00:00
2022-03-21 12:29:26 -06:00
default :
return NT_STATUS_INVALID_LEVEL ;
}
2012-06-05 08:42:53 +02:00
2022-03-21 12:29:26 -06:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
2002-07-15 10:35:28 +00:00
}
2007-08-03 11:57:39 +00:00
2022-03-21 12:29:26 -06:00
* ret_data_size = data_return_size ;
return NT_STATUS_OK ;
2001-03-23 03:12:58 +00:00
}
2022-04-27 19:27:15 +02:00
static uint32_t generate_volume_serial_number (
const struct loadparm_substitution * lp_sub ,
int snum )
{
2022-05-31 21:13:25 +02:00
int serial = lp_volume_serial_number ( snum ) ;
return serial ! = - 1 ? serial :
str_checksum ( lp_servicename ( talloc_tos ( ) , lp_sub , snum ) ) ^
2022-04-27 19:27:15 +02:00
( str_checksum ( get_local_machine_name ( ) ) < < 16 ) ;
}