2005-11-18 09:31:33 +03:00
/*
Unix SMB / CIFS implementation .
SMB2 setinfo individual test suite
Copyright ( C ) Andrew Tridgell 2005
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation ; either version 2 of the License , or
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program ; if not , write to the Free Software
Foundation , Inc . , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
*/
# include "includes.h"
# include "system/time.h"
2005-12-28 18:38:36 +03:00
# include "libcli/smb2/smb2.h"
2006-01-03 20:27:33 +03:00
# include "libcli/smb2/smb2_calls.h"
2005-11-18 09:31:33 +03:00
2006-03-25 19:01:28 +03:00
# include "torture/torture.h"
2006-02-04 17:08:24 +03:00
# include "torture/smb2/proto.h"
2006-06-29 11:03:09 +04:00
# include "libcli/security/security.h"
# include "librpc/gen_ndr/ndr_security.h"
2005-11-18 09:31:33 +03:00
# define BASEDIR ""
/* basic testing of all SMB2 setinfo calls
for each call we test that it succeeds , and where possible test
for consistency between the calls .
*/
2006-03-25 19:01:28 +03:00
BOOL torture_smb2_setinfo ( struct torture_context * torture )
2005-11-18 09:31:33 +03:00
{
struct smb2_tree * tree ;
BOOL ret = True ;
TALLOC_CTX * mem_ctx = talloc_new ( NULL ) ;
struct smb2_handle handle ;
char * fname ;
char * fname_new ;
2005-11-19 08:55:08 +03:00
union smb_fileinfo finfo2 ;
2005-11-18 09:31:33 +03:00
union smb_setfileinfo sfinfo ;
2006-06-29 11:03:09 +04:00
struct security_ace ace ;
struct security_descriptor * sd ;
struct dom_sid * test_sid ;
2005-11-18 09:31:33 +03:00
NTSTATUS status , status2 ;
const char * call_name ;
time_t basetime = ( time ( NULL ) - 86400 ) & ~ 1 ;
int n = time ( NULL ) % 100 ;
2005-12-02 06:18:34 +03:00
ZERO_STRUCT ( handle ) ;
2005-11-18 09:31:33 +03:00
fname = talloc_asprintf ( mem_ctx , BASEDIR " fnum_test_%d.txt " , n ) ;
fname_new = talloc_asprintf ( mem_ctx , BASEDIR " fnum_test_new_%d.txt " , n ) ;
if ( ! torture_smb2_connection ( mem_ctx , & tree ) ) {
return False ;
}
# define RECREATE_FILE(fname) do { \
smb2_util_close ( tree , handle ) ; \
status = smb2_create_complex_file ( tree , fname , & handle ) ; \
if ( ! NT_STATUS_IS_OK ( status ) ) { \
printf ( " (%s) ERROR: open of %s failed (%s) \n " , \
__location__ , fname , nt_errstr ( status ) ) ; \
ret = False ; \
goto done ; \
} } while ( 0 )
# define RECREATE_BOTH do { \
RECREATE_FILE ( fname ) ; \
} while ( 0 )
RECREATE_BOTH ;
# define CHECK_CALL(call, rightstatus) do { \
call_name = # call ; \
sfinfo . generic . level = RAW_SFILEINFO_ # # call ; \
2006-03-13 01:48:25 +03:00
sfinfo . generic . in . file . handle = handle ; \
2005-11-18 09:31:33 +03:00
status = smb2_setinfo_file ( tree , & sfinfo ) ; \
if ( ! NT_STATUS_EQUAL ( status , rightstatus ) ) { \
printf ( " (%s) %s - %s (should be %s) \n " , __location__ , # call , \
nt_errstr ( status ) , nt_errstr ( rightstatus ) ) ; \
ret = False ; \
} \
2005-11-19 08:55:08 +03:00
} while ( 0 )
2005-11-18 09:31:33 +03:00
# define CHECK1(call) \
do { if ( NT_STATUS_IS_OK ( status ) ) { \
finfo2 . generic . level = RAW_FILEINFO_ # # call ; \
2006-03-13 01:48:25 +03:00
finfo2 . generic . in . file . handle = handle ; \
2005-11-18 09:31:33 +03:00
status2 = smb2_getinfo_file ( tree , mem_ctx , & finfo2 ) ; \
if ( ! NT_STATUS_IS_OK ( status2 ) ) { \
2006-06-29 11:03:09 +04:00
printf ( " (%s) %s - %s \n " , __location__ , # call , nt_errstr ( status2 ) ) ; \
2005-11-18 09:31:33 +03:00
} \
} } while ( 0 )
# define CHECK_VALUE(call, stype, field, value) do { \
CHECK1 ( call ) ; \
if ( NT_STATUS_IS_OK ( status ) & & NT_STATUS_IS_OK ( status2 ) & & finfo2 . stype . out . field ! = value ) { \
printf ( " (%s) %s - %s/%s should be 0x%x - 0x%x \n " , __location__ , \
call_name , # stype , # field , \
( uint_t ) value , ( uint_t ) finfo2 . stype . out . field ) ; \
2005-11-19 08:55:08 +03:00
torture_smb2_all_info ( tree , handle ) ; \
2005-11-18 09:31:33 +03:00
} } while ( 0 )
# define CHECK_TIME(call, stype, field, value) do { \
CHECK1 ( call ) ; \
if ( NT_STATUS_IS_OK ( status ) & & NT_STATUS_IS_OK ( status2 ) & & nt_time_to_unix ( finfo2 . stype . out . field ) ! = value ) { \
printf ( " (%s) %s - %s/%s should be 0x%x - 0x%x \n " , __location__ , \
call_name , # stype , # field , \
( uint_t ) value , \
( uint_t ) nt_time_to_unix ( finfo2 . stype . out . field ) ) ; \
printf ( " \t %s " , timestring ( mem_ctx , value ) ) ; \
printf ( " \t %s \n " , nt_time_string ( mem_ctx , finfo2 . stype . out . field ) ) ; \
2005-11-19 08:55:08 +03:00
torture_smb2_all_info ( tree , handle ) ; \
2005-11-18 09:31:33 +03:00
} } while ( 0 )
# define CHECK_STR(call, stype, field, value) do { \
CHECK1 ( call ) ; \
if ( NT_STATUS_IS_OK ( status ) & & NT_STATUS_IS_OK ( status2 ) & & strcmp ( finfo2 . stype . out . field , value ) ! = 0 ) { \
printf ( " (%s) %s - %s/%s should be '%s' - '%s' \n " , __location__ , \
call_name , # stype , # field , \
value , \
finfo2 . stype . out . field ) ; \
2005-11-19 08:55:08 +03:00
torture_smb2_all_info ( tree , handle ) ; \
2005-11-18 09:31:33 +03:00
} } while ( 0 )
# define CHECK_STATUS(status, correct) do { \
if ( ! NT_STATUS_EQUAL ( status , correct ) ) { \
printf ( " (%s) Incorrect status %s - should be %s \n " , \
__location__ , nt_errstr ( status ) , nt_errstr ( correct ) ) ; \
ret = False ; \
goto done ; \
} } while ( 0 )
2005-11-18 12:25:25 +03:00
torture_smb2_all_info ( tree , handle ) ;
2005-11-18 09:31:33 +03:00
printf ( " test basic_information level \n " ) ;
basetime + = 86400 ;
unix_to_nt_time ( & sfinfo . basic_info . in . create_time , basetime + 100 ) ;
unix_to_nt_time ( & sfinfo . basic_info . in . access_time , basetime + 200 ) ;
unix_to_nt_time ( & sfinfo . basic_info . in . write_time , basetime + 300 ) ;
unix_to_nt_time ( & sfinfo . basic_info . in . change_time , basetime + 400 ) ;
sfinfo . basic_info . in . attrib = FILE_ATTRIBUTE_READONLY ;
CHECK_CALL ( BASIC_INFORMATION , NT_STATUS_OK ) ;
CHECK_TIME ( SMB2_ALL_INFORMATION , all_info2 , create_time , basetime + 100 ) ;
CHECK_TIME ( SMB2_ALL_INFORMATION , all_info2 , access_time , basetime + 200 ) ;
CHECK_TIME ( SMB2_ALL_INFORMATION , all_info2 , write_time , basetime + 300 ) ;
CHECK_TIME ( SMB2_ALL_INFORMATION , all_info2 , change_time , basetime + 400 ) ;
CHECK_VALUE ( SMB2_ALL_INFORMATION , all_info2 , attrib , FILE_ATTRIBUTE_READONLY ) ;
printf ( " a zero time means don't change \n " ) ;
unix_to_nt_time ( & sfinfo . basic_info . in . create_time , 0 ) ;
unix_to_nt_time ( & sfinfo . basic_info . in . access_time , 0 ) ;
unix_to_nt_time ( & sfinfo . basic_info . in . write_time , 0 ) ;
unix_to_nt_time ( & sfinfo . basic_info . in . change_time , 0 ) ;
sfinfo . basic_info . in . attrib = FILE_ATTRIBUTE_NORMAL ;
CHECK_CALL ( BASIC_INFORMATION , NT_STATUS_OK ) ;
CHECK_TIME ( SMB2_ALL_INFORMATION , all_info2 , create_time , basetime + 100 ) ;
CHECK_TIME ( SMB2_ALL_INFORMATION , all_info2 , access_time , basetime + 200 ) ;
CHECK_TIME ( SMB2_ALL_INFORMATION , all_info2 , write_time , basetime + 300 ) ;
CHECK_TIME ( SMB2_ALL_INFORMATION , all_info2 , change_time , basetime + 400 ) ;
CHECK_VALUE ( SMB2_ALL_INFORMATION , all_info2 , attrib , FILE_ATTRIBUTE_NORMAL ) ;
2005-11-19 08:55:08 +03:00
printf ( " change the attribute \n " ) ;
sfinfo . basic_info . in . attrib = FILE_ATTRIBUTE_HIDDEN ;
CHECK_CALL ( BASIC_INFORMATION , NT_STATUS_OK ) ;
CHECK_VALUE ( SMB2_ALL_INFORMATION , all_info2 , attrib , FILE_ATTRIBUTE_HIDDEN ) ;
printf ( " zero attrib means don't change \n " ) ;
sfinfo . basic_info . in . attrib = 0 ;
CHECK_CALL ( BASIC_INFORMATION , NT_STATUS_OK ) ;
CHECK_VALUE ( SMB2_ALL_INFORMATION , all_info2 , attrib , FILE_ATTRIBUTE_HIDDEN ) ;
printf ( " restore attribute \n " ) ;
sfinfo . basic_info . in . attrib = FILE_ATTRIBUTE_NORMAL ;
CHECK_CALL ( BASIC_INFORMATION , NT_STATUS_OK ) ;
CHECK_VALUE ( SMB2_ALL_INFORMATION , all_info2 , attrib , FILE_ATTRIBUTE_NORMAL ) ;
2005-11-18 09:31:33 +03:00
printf ( " test disposition_information level \n " ) ;
sfinfo . disposition_info . in . delete_on_close = 1 ;
CHECK_CALL ( DISPOSITION_INFORMATION , NT_STATUS_OK ) ;
CHECK_VALUE ( SMB2_ALL_INFORMATION , all_info2 , delete_pending , 1 ) ;
CHECK_VALUE ( SMB2_ALL_INFORMATION , all_info2 , nlink , 0 ) ;
sfinfo . disposition_info . in . delete_on_close = 0 ;
CHECK_CALL ( DISPOSITION_INFORMATION , NT_STATUS_OK ) ;
CHECK_VALUE ( SMB2_ALL_INFORMATION , all_info2 , delete_pending , 0 ) ;
CHECK_VALUE ( SMB2_ALL_INFORMATION , all_info2 , nlink , 1 ) ;
printf ( " test allocation_information level \n " ) ;
sfinfo . allocation_info . in . alloc_size = 0 ;
CHECK_CALL ( ALLOCATION_INFORMATION , NT_STATUS_OK ) ;
CHECK_VALUE ( SMB2_ALL_INFORMATION , all_info2 , size , 0 ) ;
CHECK_VALUE ( SMB2_ALL_INFORMATION , all_info2 , alloc_size , 0 ) ;
sfinfo . allocation_info . in . alloc_size = 4096 ;
CHECK_CALL ( ALLOCATION_INFORMATION , NT_STATUS_OK ) ;
CHECK_VALUE ( SMB2_ALL_INFORMATION , all_info2 , alloc_size , 4096 ) ;
CHECK_VALUE ( SMB2_ALL_INFORMATION , all_info2 , size , 0 ) ;
printf ( " test end_of_file_info level \n " ) ;
sfinfo . end_of_file_info . in . size = 37 ;
CHECK_CALL ( END_OF_FILE_INFORMATION , NT_STATUS_OK ) ;
CHECK_VALUE ( SMB2_ALL_INFORMATION , all_info2 , size , 37 ) ;
sfinfo . end_of_file_info . in . size = 7 ;
CHECK_CALL ( END_OF_FILE_INFORMATION , NT_STATUS_OK ) ;
CHECK_VALUE ( SMB2_ALL_INFORMATION , all_info2 , size , 7 ) ;
printf ( " test position_information level \n " ) ;
sfinfo . position_information . in . position = 123456 ;
CHECK_CALL ( POSITION_INFORMATION , NT_STATUS_OK ) ;
CHECK_VALUE ( POSITION_INFORMATION , position_information , position , 123456 ) ;
2005-11-19 08:55:08 +03:00
CHECK_VALUE ( SMB2_ALL_INFORMATION , all_info2 , position , 123456 ) ;
2005-11-18 09:31:33 +03:00
printf ( " test mode_information level \n " ) ;
sfinfo . mode_information . in . mode = 2 ;
CHECK_CALL ( MODE_INFORMATION , NT_STATUS_OK ) ;
CHECK_VALUE ( MODE_INFORMATION , mode_information , mode , 2 ) ;
2005-11-19 08:55:08 +03:00
CHECK_VALUE ( SMB2_ALL_INFORMATION , all_info2 , mode , 2 ) ;
2005-11-18 09:31:33 +03:00
sfinfo . mode_information . in . mode = 1 ;
CHECK_CALL ( MODE_INFORMATION , NT_STATUS_INVALID_PARAMETER ) ;
sfinfo . mode_information . in . mode = 0 ;
CHECK_CALL ( MODE_INFORMATION , NT_STATUS_OK ) ;
CHECK_VALUE ( MODE_INFORMATION , mode_information , mode , 0 ) ;
2006-06-29 11:03:09 +04:00
printf ( " test sec_desc level \n " ) ;
ZERO_STRUCT ( finfo2 ) ;
finfo2 . query_secdesc . in . secinfo_flags =
SECINFO_OWNER |
SECINFO_GROUP |
SECINFO_DACL ;
CHECK1 ( SEC_DESC ) ;
sd = finfo2 . query_secdesc . out . sd ;
test_sid = dom_sid_parse_talloc ( mem_ctx , " S-1-5-32-1234-5432 " ) ;
2006-06-29 18:00:57 +04:00
ZERO_STRUCT ( ace ) ;
2006-06-29 11:03:09 +04:00
ace . type = SEC_ACE_TYPE_ACCESS_ALLOWED ;
ace . flags = 0 ;
ace . access_mask = SEC_STD_ALL ;
ace . trustee = * test_sid ;
status = security_descriptor_dacl_add ( sd , & ace ) ;
CHECK_STATUS ( status , NT_STATUS_OK ) ;
printf ( " add a new ACE to the DACL \n " ) ;
sfinfo . set_secdesc . in . secinfo_flags = finfo2 . query_secdesc . in . secinfo_flags ;
sfinfo . set_secdesc . in . sd = sd ;
CHECK_CALL ( SEC_DESC , NT_STATUS_OK ) ;
CHECK1 ( SEC_DESC ) ;
if ( ! security_acl_equal ( finfo2 . query_secdesc . out . sd - > dacl , sd - > dacl ) ) {
printf ( " %s: security descriptors don't match! \n " , __location__ ) ;
printf ( " got: \n " ) ;
NDR_PRINT_DEBUG ( security_descriptor , finfo2 . query_secdesc . out . sd ) ;
printf ( " expected: \n " ) ;
NDR_PRINT_DEBUG ( security_descriptor , sd ) ;
ret = False ;
}
printf ( " remove it again \n " ) ;
status = security_descriptor_dacl_del ( sd , test_sid ) ;
CHECK_STATUS ( status , NT_STATUS_OK ) ;
sfinfo . set_secdesc . in . secinfo_flags = finfo2 . query_secdesc . in . secinfo_flags ;
sfinfo . set_secdesc . in . sd = sd ;
CHECK_CALL ( SEC_DESC , NT_STATUS_OK ) ;
CHECK1 ( SEC_DESC ) ;
if ( ! security_acl_equal ( finfo2 . query_secdesc . out . sd - > dacl , sd - > dacl ) ) {
printf ( " %s: security descriptors don't match! \n " , __location__ ) ;
printf ( " got: \n " ) ;
NDR_PRINT_DEBUG ( security_descriptor , finfo2 . query_secdesc . out . sd ) ;
printf ( " expected: \n " ) ;
NDR_PRINT_DEBUG ( security_descriptor , sd ) ;
ret = False ;
}
2005-11-18 09:31:33 +03:00
done :
status = smb2_util_close ( tree , handle ) ;
if ( NT_STATUS_IS_ERR ( status ) ) {
printf ( " Failed to delete %s - %s \n " , fname , nt_errstr ( status ) ) ;
}
smb2_util_unlink ( tree , fname ) ;
talloc_free ( mem_ctx ) ;
return ret ;
}