mirror of
https://github.com/samba-team/samba.git
synced 2025-01-06 13:18:07 +03:00
9e1c2fedb8
- create file with ARCHIVE - open file with ARCHIVE+HIDDEN+... - check DOS attrs are still only ARCHIVE from the initial create Signed-off-by: Ralph Boehme <slow@samba.org> Reviewed-by: Jeremy Allison <jra@samba.org>
711 lines
25 KiB
C
711 lines
25 KiB
C
/*
|
|
Unix SMB/CIFS implementation.
|
|
|
|
openattr tester
|
|
|
|
Copyright (C) Andrew Tridgell 2003
|
|
Copyright (C) David Mulder 2019
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "includes.h"
|
|
#include "libcli/smb2/smb2.h"
|
|
#include "libcli/smb2/smb2_calls.h"
|
|
#include "torture/torture.h"
|
|
#include "libcli/security/security_descriptor.h"
|
|
#include "torture/smb2/proto.h"
|
|
|
|
static const uint32_t open_attrs_table[] = {
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
FILE_ATTRIBUTE_ARCHIVE,
|
|
FILE_ATTRIBUTE_READONLY,
|
|
FILE_ATTRIBUTE_HIDDEN,
|
|
FILE_ATTRIBUTE_SYSTEM,
|
|
|
|
FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY,
|
|
FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN,
|
|
FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM,
|
|
FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
|
|
FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
|
|
FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
|
|
|
|
FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
|
|
FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
|
|
FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
|
|
FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_SYSTEM,
|
|
};
|
|
|
|
struct trunc_open_results {
|
|
unsigned int num;
|
|
uint32_t init_attr;
|
|
uint32_t trunc_attr;
|
|
uint32_t result_attr;
|
|
};
|
|
|
|
static const struct trunc_open_results attr_results[] = {
|
|
{ 0, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
|
|
{ 1, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
|
|
{ 2, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
|
|
{ 16, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
|
|
{ 17, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
|
|
{ 18, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
|
|
{ 51, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
|
|
{ 54, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
|
|
{ 56, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
|
|
{ 68, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
|
|
{ 71, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
|
|
{ 73, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM },
|
|
{ 99, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
|
|
{ 102, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
|
|
{ 104, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
|
|
{ 116, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
|
|
{ 119, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
|
|
{ 121, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM },
|
|
{ 170, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM|FILE_ATTRIBUTE_HIDDEN },
|
|
{ 173, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM },
|
|
{ 227, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
|
|
{ 230, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
|
|
{ 232, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
|
|
{ 244, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
|
|
{ 247, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
|
|
{ 249, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM }
|
|
};
|
|
|
|
static NTSTATUS smb2_setatr(struct smb2_tree *tree, const char *name,
|
|
uint32_t attrib)
|
|
{
|
|
NTSTATUS status;
|
|
struct smb2_create create_io = {0};
|
|
union smb_setfileinfo io;
|
|
|
|
create_io.in.desired_access = SEC_FILE_READ_DATA |
|
|
SEC_FILE_WRITE_ATTRIBUTE;
|
|
create_io.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
|
|
create_io.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
|
|
create_io.in.create_disposition = NTCREATEX_DISP_OPEN;
|
|
create_io.in.fname = name;
|
|
status = smb2_create(tree, tree, &create_io);
|
|
if (!NT_STATUS_IS_OK(status)) {
|
|
return status;
|
|
}
|
|
|
|
ZERO_STRUCT(io);
|
|
io.basic_info.level = RAW_SFILEINFO_BASIC_INFORMATION;
|
|
io.basic_info.in.file.handle = create_io.out.file.handle;
|
|
io.basic_info.in.attrib = attrib;
|
|
status = smb2_setinfo_file(tree, &io);
|
|
if (!NT_STATUS_IS_OK(status)) {
|
|
return status;
|
|
}
|
|
|
|
status = smb2_util_close(tree, create_io.out.file.handle);
|
|
if (!NT_STATUS_IS_OK(status)) {
|
|
return status;
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
bool torture_smb2_openattrtest(struct torture_context *tctx,
|
|
struct smb2_tree *tree)
|
|
{
|
|
NTSTATUS status;
|
|
const char *fname = "openattr.file";
|
|
uint16_t attr;
|
|
unsigned int i, j, k, l;
|
|
int ret = true;
|
|
|
|
for (k = 0, i = 0; i < sizeof(open_attrs_table)/sizeof(uint32_t); i++) {
|
|
struct smb2_create create_io = {0};
|
|
smb2_setatr(tree, fname, FILE_ATTRIBUTE_NORMAL);
|
|
smb2_util_unlink(tree, fname);
|
|
create_io.in.create_flags = 0;
|
|
create_io.in.desired_access = SEC_FILE_WRITE_DATA;
|
|
create_io.in.file_attributes = open_attrs_table[i];
|
|
create_io.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
|
|
create_io.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
|
|
create_io.in.create_options = 0;
|
|
create_io.in.security_flags = 0;
|
|
create_io.in.fname = fname;
|
|
status = smb2_create(tree, tctx, &create_io);
|
|
torture_assert_ntstatus_ok_goto(tctx, status, ret, error_exit,
|
|
talloc_asprintf(tctx, "open %d (1) of %s failed (%s)",
|
|
i, fname, nt_errstr(status)));
|
|
|
|
status = smb2_util_close(tree, create_io.out.file.handle);
|
|
torture_assert_ntstatus_ok_goto(tctx, status, ret, error_exit,
|
|
talloc_asprintf(tctx, "close %d (1) of %s failed (%s)",
|
|
i, fname, nt_errstr(status)));
|
|
|
|
for (j = 0; j < ARRAY_SIZE(open_attrs_table); j++) {
|
|
create_io = (struct smb2_create){0};
|
|
create_io.in.create_flags = 0;
|
|
create_io.in.desired_access = SEC_FILE_READ_DATA|
|
|
SEC_FILE_WRITE_DATA;
|
|
create_io.in.file_attributes = open_attrs_table[j];
|
|
create_io.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
|
|
create_io.in.create_disposition = NTCREATEX_DISP_OVERWRITE;
|
|
create_io.in.create_options = 0;
|
|
create_io.in.security_flags = 0;
|
|
create_io.in.fname = fname;
|
|
status = smb2_create(tree, tctx, &create_io);
|
|
|
|
if (!NT_STATUS_IS_OK(status)) {
|
|
for (l = 0; l < ARRAY_SIZE(attr_results); l++) {
|
|
torture_assert_goto(tctx,
|
|
attr_results[l].num != k,
|
|
ret, error_exit,
|
|
talloc_asprintf(tctx,
|
|
"[%d] trunc open 0x%x "
|
|
"-> 0x%x of %s failed "
|
|
"- should have "
|
|
"succeeded !(%s)",
|
|
k, open_attrs_table[i],
|
|
open_attrs_table[j],
|
|
fname,
|
|
nt_errstr(status)));
|
|
}
|
|
torture_assert_ntstatus_equal_goto(tctx,
|
|
status, NT_STATUS_ACCESS_DENIED,
|
|
ret, error_exit,
|
|
talloc_asprintf(tctx,
|
|
"[%d] trunc open 0x%x "
|
|
"-> 0x%x failed with "
|
|
"wrong error code %s",
|
|
k, open_attrs_table[i],
|
|
open_attrs_table[j],
|
|
nt_errstr(status)));
|
|
k++;
|
|
continue;
|
|
}
|
|
|
|
status = smb2_util_close(tree, create_io.out.file.handle);
|
|
torture_assert_ntstatus_ok_goto(tctx, status, ret,
|
|
error_exit, talloc_asprintf(tctx,
|
|
"close %d (2) of %s failed (%s)", j,
|
|
fname, nt_errstr(status)));
|
|
|
|
status = smb2_util_getatr(tree, fname, &attr, NULL, NULL);
|
|
torture_assert_ntstatus_ok_goto(tctx, status, ret,
|
|
error_exit, talloc_asprintf(tctx,
|
|
"getatr(2) failed (%s)",
|
|
nt_errstr(status)));
|
|
|
|
for (l = 0; l < ARRAY_SIZE(attr_results); l++) {
|
|
if (attr_results[l].num == k) {
|
|
if (attr != attr_results[l].result_attr ||
|
|
open_attrs_table[i] != attr_results[l].init_attr ||
|
|
open_attrs_table[j] != attr_results[l].trunc_attr) {
|
|
ret = false;
|
|
torture_fail_goto(tctx, error_exit,
|
|
talloc_asprintf(tctx,
|
|
"[%d] getatr check "
|
|
"failed. [0x%x] trunc "
|
|
"[0x%x] got attr 0x%x,"
|
|
" should be 0x%x",
|
|
k, open_attrs_table[i],
|
|
open_attrs_table[j],
|
|
(unsigned int)attr,
|
|
attr_results[l].result_attr));
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
k++;
|
|
}
|
|
}
|
|
error_exit:
|
|
smb2_setatr(tree, fname, FILE_ATTRIBUTE_NORMAL);
|
|
smb2_util_unlink(tree, fname);
|
|
|
|
|
|
return ret;
|
|
}
|
|
|
|
bool torture_smb2_winattrtest(struct torture_context *tctx,
|
|
struct smb2_tree *tree)
|
|
{
|
|
const char *fname = "winattr1.file";
|
|
const char *dname = "winattr1.dir";
|
|
uint16_t attr;
|
|
uint16_t j;
|
|
uint32_t aceno;
|
|
bool ret = true;
|
|
union smb_fileinfo query, query_org;
|
|
NTSTATUS status;
|
|
struct security_descriptor *sd1 = NULL, *sd2 = NULL;
|
|
struct smb2_create create_io = {0};
|
|
ZERO_STRUCT(query);
|
|
ZERO_STRUCT(query_org);
|
|
|
|
/* Test winattrs for file */
|
|
smb2_util_unlink(tree, fname);
|
|
|
|
/* Open a file*/
|
|
create_io.in.create_flags = 0;
|
|
create_io.in.desired_access = SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA |
|
|
SEC_STD_READ_CONTROL;
|
|
create_io.in.file_attributes = 0;
|
|
create_io.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
|
|
create_io.in.create_disposition = FILE_SUPERSEDE;
|
|
create_io.in.create_options = 0;
|
|
create_io.in.security_flags = 0;
|
|
create_io.in.fname = fname;
|
|
status = smb2_create(tree, tctx, &create_io);
|
|
torture_assert_ntstatus_ok_goto(tctx, status, ret, error_exit,
|
|
talloc_asprintf(tctx, "open(1) of %s failed (%s)\n",
|
|
fname, nt_errstr(status)));
|
|
|
|
/* Get security descriptor and store it*/
|
|
query_org.generic.level = RAW_FILEINFO_SEC_DESC;
|
|
query_org.generic.in.file.handle = create_io.out.file.handle;
|
|
query_org.query_secdesc.in.secinfo_flags = SECINFO_OWNER|
|
|
SECINFO_GROUP|
|
|
SECINFO_DACL;
|
|
status = smb2_getinfo_file(tree, tctx, &query_org);
|
|
if(!NT_STATUS_IS_OK(status)){
|
|
NTSTATUS s = smb2_util_close(tree, create_io.out.file.handle);
|
|
torture_assert_ntstatus_ok_goto(tctx, s, ret, error_exit,
|
|
talloc_asprintf(tctx,
|
|
"close(1) of %s failed (%s)\n",
|
|
fname, nt_errstr(s)));
|
|
ret = false;
|
|
torture_fail_goto(tctx, error_exit, talloc_asprintf(tctx,
|
|
"smb2_getinfo_file(1) of %s failed (%s)\n",
|
|
fname, nt_errstr(status)));
|
|
}
|
|
sd1 = query_org.query_secdesc.out.sd;
|
|
|
|
status = smb2_util_close(tree, create_io.out.file.handle);
|
|
torture_assert_ntstatus_ok_goto(tctx, status, ret, error_exit,
|
|
talloc_asprintf(tctx, "close(1) of %s failed (%s)\n",
|
|
fname, nt_errstr(status)));
|
|
|
|
/*Set and get attributes*/
|
|
for (j = 0; j < ARRAY_SIZE(open_attrs_table); j++) {
|
|
status = smb2_setatr(tree, fname, open_attrs_table[j]);
|
|
torture_assert_ntstatus_ok_goto(tctx, status, ret,
|
|
error_exit,
|
|
talloc_asprintf(tctx, "setatr(2) failed (%s)",
|
|
nt_errstr(status)));
|
|
|
|
status = smb2_util_getatr(tree, fname, &attr, NULL, NULL);
|
|
torture_assert_ntstatus_ok_goto(tctx, status, ret,
|
|
error_exit,
|
|
talloc_asprintf(tctx, "getatr(2) failed (%s)",
|
|
nt_errstr(status)));
|
|
|
|
/* Check the result */
|
|
torture_assert_goto(tctx, attr == open_attrs_table[j], ret,
|
|
error_exit, talloc_asprintf(tctx,
|
|
"getatr check failed. \
|
|
Attr applied [0x%x],got attr 0x%x, \
|
|
should be 0x%x ", open_attrs_table[j],
|
|
(uint16_t)attr, open_attrs_table[j]));
|
|
|
|
create_io = (struct smb2_create){0};
|
|
create_io.in.create_flags = 0;
|
|
create_io.in.desired_access = SEC_FILE_READ_ATTRIBUTE|
|
|
SEC_STD_READ_CONTROL;
|
|
create_io.in.file_attributes = 0;
|
|
create_io.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
|
|
create_io.in.create_disposition = FILE_OPEN_IF;
|
|
create_io.in.create_options = 0;
|
|
create_io.in.security_flags = 0;
|
|
create_io.in.fname = fname;
|
|
status = smb2_create(tree, tctx, &create_io);
|
|
torture_assert_ntstatus_ok_goto(tctx, status, ret,
|
|
error_exit,
|
|
talloc_asprintf(tctx, "open(2) of %s failed (%s)\n",
|
|
fname, nt_errstr(status)));
|
|
/*Get security descriptor */
|
|
query.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
|
|
query.query_secdesc.in.file.handle = create_io.out.file.handle;
|
|
query.query_secdesc.in.secinfo_flags = SECINFO_OWNER|
|
|
SECINFO_GROUP|
|
|
SECINFO_DACL;
|
|
status = smb2_getinfo_file(tree, tctx, &query);
|
|
if(!NT_STATUS_IS_OK(status)){
|
|
NTSTATUS s = smb2_util_close(tree, create_io.out.file.handle);
|
|
torture_assert_ntstatus_ok_goto(tctx, s, ret,
|
|
error_exit,
|
|
talloc_asprintf(tctx,
|
|
"close(2) of %s failed (%s)\n",
|
|
fname, nt_errstr(s)));
|
|
ret = false;
|
|
torture_fail_goto(tctx, error_exit,
|
|
talloc_asprintf(tctx,
|
|
"smb2_getinfo_file(2) of %s failed (%s)\n",
|
|
fname, nt_errstr(status)));
|
|
}
|
|
sd2 = query.query_secdesc.out.sd;
|
|
|
|
status = smb2_util_close(tree, create_io.out.file.handle);
|
|
torture_assert_ntstatus_ok_goto(tctx, status, ret, error_exit,
|
|
talloc_asprintf(tctx, "close(2) of %s failed (%s)\n",
|
|
fname, nt_errstr(status)));
|
|
|
|
/*Compare security descriptors -- Must be same*/
|
|
for (aceno=0;(sd1->dacl&&aceno < sd1->dacl->num_aces);aceno++){
|
|
struct security_ace *ace1 = &sd1->dacl->aces[aceno];
|
|
struct security_ace *ace2 = &sd2->dacl->aces[aceno];
|
|
|
|
torture_assert_goto(tctx, security_ace_equal(ace1, ace2),
|
|
ret, error_exit,
|
|
"ACLs changed! Not expected!\n");
|
|
}
|
|
|
|
torture_comment(tctx, "[%d] setattr = [0x%x] got attr 0x%x\n",
|
|
j, open_attrs_table[j], attr );
|
|
|
|
}
|
|
|
|
|
|
/* Check for Directory. */
|
|
|
|
smb2_deltree(tree, dname);
|
|
smb2_util_rmdir(tree, dname);
|
|
|
|
/* Open a directory */
|
|
create_io = (struct smb2_create){0};
|
|
create_io.in.create_flags = 0;
|
|
create_io.in.desired_access = SEC_RIGHTS_DIR_ALL;
|
|
create_io.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
|
|
create_io.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
|
|
create_io.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
|
|
create_io.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
|
|
create_io.in.security_flags = 0;
|
|
create_io.in.fname = dname;
|
|
status = smb2_create(tree, tctx, &create_io);
|
|
|
|
torture_assert_ntstatus_ok_goto(tctx, status, ret, error_exit,
|
|
talloc_asprintf(tctx,
|
|
"open (1) of %s failed (%s)",
|
|
dname, nt_errstr(status)));
|
|
|
|
|
|
/* Get Security Descriptor */
|
|
query_org.generic.level = RAW_FILEINFO_SEC_DESC;
|
|
query_org.generic.in.file.handle = create_io.out.file.handle;
|
|
status = smb2_getinfo_file(tree, tctx, &query_org);
|
|
if(!NT_STATUS_IS_OK(status)){
|
|
NTSTATUS s = smb2_util_close(tree, create_io.out.file.handle);
|
|
torture_assert_ntstatus_ok_goto(tctx, s, ret, error_exit,
|
|
talloc_asprintf(tctx,
|
|
"close(1) of %s failed (%s)\n",
|
|
dname, nt_errstr(s)));
|
|
ret = false;
|
|
torture_fail_goto(tctx, error_exit, talloc_asprintf(tctx,
|
|
"smb2_getinfo_file(1) of %s failed (%s)\n", dname,
|
|
nt_errstr(status)));
|
|
}
|
|
sd1 = query_org.query_secdesc.out.sd;
|
|
|
|
status = smb2_util_close(tree, create_io.out.file.handle);
|
|
torture_assert_ntstatus_ok_goto(tctx, status, ret, error_exit,
|
|
talloc_asprintf(tctx,
|
|
"close (1) of %s failed (%s)", dname,
|
|
nt_errstr(status)));
|
|
|
|
/* Set and get win attributes*/
|
|
for (j = 1; j < ARRAY_SIZE(open_attrs_table); j++) {
|
|
|
|
status = smb2_setatr(tree, dname, open_attrs_table[j]);
|
|
torture_assert_ntstatus_ok_goto(tctx, status, ret, error_exit,
|
|
talloc_asprintf(tctx, "setatr(2) failed (%s)",
|
|
nt_errstr(status)));
|
|
|
|
status = smb2_util_getatr(tree, dname, &attr, NULL, NULL);
|
|
torture_assert_ntstatus_ok_goto(tctx, status, ret, error_exit,
|
|
talloc_asprintf(tctx, "getatr(2) failed (%s)",
|
|
nt_errstr(status)));
|
|
|
|
torture_comment(tctx, "[%d] setatt = [0x%x] got attr 0x%x\n",
|
|
j, open_attrs_table[j], attr );
|
|
|
|
/* Check the result */
|
|
torture_assert_goto(tctx,
|
|
attr == (open_attrs_table[j]|FILE_ATTRIBUTE_DIRECTORY),
|
|
ret, error_exit, talloc_asprintf(tctx,
|
|
"getatr check failed. set attr "
|
|
"[0x%x], got attr 0x%x, should be 0x%x\n",
|
|
open_attrs_table[j], (uint16_t)attr,
|
|
(unsigned int)(open_attrs_table[j]|FILE_ATTRIBUTE_DIRECTORY)));
|
|
|
|
create_io = (struct smb2_create){0};
|
|
create_io.in.create_flags = 0;
|
|
create_io.in.desired_access = SEC_RIGHTS_DIR_READ;
|
|
create_io.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
|
|
create_io.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
|
|
create_io.in.create_disposition = NTCREATEX_DISP_OPEN;
|
|
create_io.in.create_options = 0;
|
|
create_io.in.security_flags = 0;
|
|
create_io.in.fname = dname;
|
|
status = smb2_create(tree, tctx, &create_io);
|
|
|
|
torture_assert_ntstatus_ok_goto(tctx, status, ret, error_exit,
|
|
talloc_asprintf(tctx,
|
|
"open (2) of %s failed (%s)",
|
|
dname, nt_errstr(status)));
|
|
/* Get security descriptor */
|
|
query.generic.level = RAW_FILEINFO_SEC_DESC;
|
|
query.generic.in.file.handle = create_io.out.file.handle;
|
|
status = smb2_getinfo_file(tree, tctx, &query);
|
|
if(!NT_STATUS_IS_OK(status)){
|
|
NTSTATUS s = smb2_util_close(tree, create_io.out.file.handle);
|
|
torture_assert_ntstatus_ok_goto(tctx, s, ret, error_exit,
|
|
talloc_asprintf(tctx,
|
|
"close (2) of %s failed (%s)", dname,
|
|
nt_errstr(s)));
|
|
ret = false;
|
|
torture_fail_goto(tctx, error_exit,
|
|
talloc_asprintf(tctx,
|
|
"smb2_getinfo_file(2) of %s failed(%s)\n",
|
|
dname, nt_errstr(status)));
|
|
}
|
|
sd2 = query.query_secdesc.out.sd;
|
|
status = smb2_util_close(tree, create_io.out.file.handle);
|
|
torture_assert_ntstatus_ok_goto(tctx, status, ret, error_exit,
|
|
talloc_asprintf(tctx,
|
|
"close (2) of %s failed (%s)", dname,
|
|
nt_errstr(status)));
|
|
|
|
/* Security descriptor must be same*/
|
|
for (aceno=0;(sd1->dacl&&aceno < sd1->dacl->num_aces);aceno++){
|
|
struct security_ace *ace1 = &sd1->dacl->aces[aceno];
|
|
struct security_ace *ace2 = &sd2->dacl->aces[aceno];
|
|
|
|
torture_assert_goto(tctx, security_ace_equal(ace1, ace2),
|
|
ret, error_exit,
|
|
"ACLs changed! Not expected!\n");
|
|
}
|
|
|
|
}
|
|
|
|
error_exit:
|
|
smb2_setatr(tree, fname, FILE_ATTRIBUTE_NORMAL);
|
|
smb2_util_unlink(tree, fname);
|
|
smb2_deltree(tree, dname);
|
|
smb2_util_rmdir(tree, dname);
|
|
|
|
return ret;
|
|
}
|
|
|
|
bool torture_smb2_winattr2(struct torture_context *tctx,
|
|
struct smb2_tree *tree)
|
|
{
|
|
const char *fname = "winattr2.file";
|
|
struct smb2_create c = {0};
|
|
NTSTATUS status;
|
|
bool ret = true;
|
|
|
|
smb2_util_unlink(tree, fname);
|
|
|
|
/* Create a file with FILE_ATTRIBUTE_ARCHIVE */
|
|
c = (struct smb2_create) {
|
|
.in.desired_access = SEC_FILE_READ_DATA,
|
|
.in.file_attributes = FILE_ATTRIBUTE_ARCHIVE,
|
|
.in.share_access = NTCREATEX_SHARE_ACCESS_NONE,
|
|
.in.create_disposition = NTCREATEX_DISP_OPEN_IF,
|
|
.in.fname = fname,
|
|
};
|
|
|
|
status = smb2_create(tree, tctx, &c);
|
|
torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
|
|
"smb2_create failed\n");
|
|
|
|
status = smb2_util_close(tree, c.out.file.handle);
|
|
torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
|
|
"smb2_util_close failed\n");
|
|
|
|
/* Reopen file with different attributes */
|
|
c = (struct smb2_create) {
|
|
.in.desired_access = SEC_FILE_READ_DATA,
|
|
.in.file_attributes = FILE_ATTRIBUTE_ARCHIVE |
|
|
FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN |
|
|
FILE_ATTRIBUTE_READONLY,
|
|
.in.share_access = NTCREATEX_SHARE_ACCESS_NONE,
|
|
.in.create_disposition = NTCREATEX_DISP_OPEN_IF,
|
|
.in.fname = fname,
|
|
};
|
|
|
|
status = smb2_create(tree, tctx, &c);
|
|
torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
|
|
"smb2_create failed\n");
|
|
|
|
status = smb2_util_close(tree, c.out.file.handle);
|
|
torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
|
|
"smb2_util_close failed\n");
|
|
|
|
torture_assert_int_equal_goto(tctx,
|
|
c.out.file_attr,
|
|
FILE_ATTRIBUTE_ARCHIVE,
|
|
ret, done,
|
|
"Wrong attributes\n");
|
|
|
|
done:
|
|
smb2_util_unlink(tree, fname);
|
|
return ret;
|
|
}
|
|
|
|
bool torture_smb2_sdreadtest(struct torture_context *tctx,
|
|
struct smb2_tree *tree)
|
|
{
|
|
const char *fname = "sdread.file";
|
|
bool ret = true;
|
|
union smb_fileinfo query;
|
|
NTSTATUS status;
|
|
struct security_descriptor *sd = NULL;
|
|
struct smb2_create create_io = {0};
|
|
uint32_t sd_bits[] = { SECINFO_OWNER,
|
|
SECINFO_GROUP,
|
|
SECINFO_DACL };
|
|
size_t i;
|
|
|
|
ZERO_STRUCT(query);
|
|
|
|
smb2_util_unlink(tree, fname);
|
|
|
|
/* Create then close a file*/
|
|
create_io.in.create_flags = 0;
|
|
create_io.in.desired_access = SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA;
|
|
create_io.in.file_attributes = 0;
|
|
create_io.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
|
|
create_io.in.create_disposition = FILE_SUPERSEDE;
|
|
create_io.in.create_options = 0;
|
|
create_io.in.security_flags = 0;
|
|
create_io.in.fname = fname;
|
|
status = smb2_create(tree, tctx, &create_io);
|
|
torture_assert_ntstatus_ok_goto(tctx, status, ret, error_exit,
|
|
talloc_asprintf(tctx, "open(1) of %s failed (%s)\n",
|
|
fname, nt_errstr(status)));
|
|
status = smb2_util_close(tree, create_io.out.file.handle);
|
|
torture_assert_ntstatus_ok_goto(tctx, status, ret, error_exit,
|
|
talloc_asprintf(tctx, "close(1) of %s failed (%s)\n",
|
|
fname, nt_errstr(status)));
|
|
|
|
/*
|
|
* Open the file with READ_ATTRIBUTES *only*,
|
|
* no READ_CONTROL.
|
|
*
|
|
* This should deny access for any attempt to
|
|
* get a security descriptor if we ask for
|
|
* any of OWNER|GROUP|DACL, but if
|
|
* we ask for *NO* info but still ask for
|
|
* the security descriptor, then Windows
|
|
* returns an ACL but with zero entries
|
|
* for OWNER|GROUP|DACL.
|
|
*/
|
|
|
|
create_io = (struct smb2_create){0};
|
|
create_io.in.create_flags = 0;
|
|
create_io.in.desired_access = SEC_FILE_READ_ATTRIBUTE;
|
|
create_io.in.file_attributes = 0;
|
|
create_io.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
|
|
create_io.in.create_disposition = FILE_OPEN;
|
|
create_io.in.create_options = 0;
|
|
create_io.in.security_flags = 0;
|
|
create_io.in.fname = fname;
|
|
status = smb2_create(tree, tctx, &create_io);
|
|
torture_assert_ntstatus_ok_goto(tctx, status, ret,
|
|
error_exit,
|
|
talloc_asprintf(tctx, "open(2) of %s failed (%s)\n",
|
|
fname, nt_errstr(status)));
|
|
|
|
/* Check asking for SD fails ACCESS_DENIED with actual bits set. */
|
|
for (i = 0; i < ARRAY_SIZE(sd_bits); i++) {
|
|
query.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
|
|
query.query_secdesc.in.file.handle = create_io.out.file.handle;
|
|
query.query_secdesc.in.secinfo_flags = sd_bits[i];
|
|
|
|
status = smb2_getinfo_file(tree, tctx, &query);
|
|
|
|
/* Must return ACESS_DENIED. */
|
|
if(!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)){
|
|
NTSTATUS s = smb2_util_close(tree,
|
|
create_io.out.file.handle);
|
|
torture_assert_ntstatus_ok_goto(tctx, s, ret,
|
|
error_exit,
|
|
talloc_asprintf(tctx,
|
|
"close(2) of %s failed (%s)\n",
|
|
fname, nt_errstr(s)));
|
|
ret = false;
|
|
torture_fail_goto(tctx, error_exit,
|
|
talloc_asprintf(tctx,
|
|
"smb2_getinfo_file(2) of %s failed (%s)\n",
|
|
fname, nt_errstr(status)));
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Get security descriptor whilst asking for *NO* bits.
|
|
* This succeeds even though we don't have READ_CONTROL
|
|
* access but returns an SD with zero data.
|
|
*/
|
|
query.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
|
|
query.query_secdesc.in.file.handle = create_io.out.file.handle;
|
|
query.query_secdesc.in.secinfo_flags = 0;
|
|
|
|
status = smb2_getinfo_file(tree, tctx, &query);
|
|
if(!NT_STATUS_IS_OK(status)){
|
|
NTSTATUS s = smb2_util_close(tree, create_io.out.file.handle);
|
|
torture_assert_ntstatus_ok_goto(tctx, s, ret, error_exit,
|
|
talloc_asprintf(tctx,
|
|
"close(3) of %s failed (%s)\n",
|
|
fname, nt_errstr(s)));
|
|
ret = false;
|
|
torture_fail_goto(tctx, error_exit, talloc_asprintf(tctx,
|
|
"smb2_getinfo_file(3) of %s failed (%s)\n",
|
|
fname, nt_errstr(status)));
|
|
}
|
|
|
|
sd = query.query_secdesc.out.sd;
|
|
|
|
/* Check it's empty. */
|
|
torture_assert_goto(tctx,
|
|
(sd->owner_sid == NULL),
|
|
ret,
|
|
error_exit,
|
|
"sd->owner_sid != NULL\n");
|
|
|
|
torture_assert_goto(tctx,
|
|
(sd->group_sid == NULL),
|
|
ret,
|
|
error_exit,
|
|
"sd->group_sid != NULL\n");
|
|
|
|
torture_assert_goto(tctx,
|
|
(sd->dacl == NULL),
|
|
ret,
|
|
error_exit,
|
|
"sd->dacl != NULL\n");
|
|
|
|
status = smb2_util_close(tree, create_io.out.file.handle);
|
|
torture_assert_ntstatus_ok_goto(tctx,
|
|
status,
|
|
ret,
|
|
error_exit,
|
|
talloc_asprintf(tctx, "close(4) of %s failed (%s)\n",
|
|
fname,
|
|
nt_errstr(status)));
|
|
|
|
error_exit:
|
|
|
|
smb2_setatr(tree, fname, FILE_ATTRIBUTE_NORMAL);
|
|
smb2_util_unlink(tree, fname);
|
|
|
|
return ret;
|
|
}
|