*/
#include "includes.h"
-#include "torture/torture.h"
#include "system/filesys.h"
-#include "libcli/raw/libcliraw.h"
#include "libcli/libcli.h"
#include "libcli/security/security.h"
#include "torture/util.h"
-#include "torture/smbtorture.h"
#include "cxd_known.h"
extern int torture_failures;
};
-static void progress_bar(struct torture_context *tctx, uint_t i, uint_t total)
+static void progress_bar(struct torture_context *tctx, unsigned int i, unsigned int total)
{
if (torture_setting_bool(tctx, "progress", true)) {
torture_comment(tctx, "%5d/%5d\r", i, total);
progress_bar(tctx, i, ARRAY_SIZE(denytable1));
+ if (!torture_setting_bool(tctx, "deny_fcb_support", true) &&
+ (denytable1[i].deny1 == DENY_FCB ||
+ denytable1[i].deny2 == DENY_FCB))
+ continue;
+
+ if (!torture_setting_bool(tctx, "deny_dos_support", true) &&
+ (denytable1[i].deny1 == DENY_DOS ||
+ denytable1[i].deny2 == DENY_DOS))
+ continue;
+
fnum1 = smbcli_open(cli1->tree, fname,
denytable1[i].mode1,
denytable1[i].deny1);
progress_bar(tctx, i, ARRAY_SIZE(denytable1));
+ if (!torture_setting_bool(tctx, "deny_fcb_support", true) &&
+ (denytable1[i].deny1 == DENY_FCB ||
+ denytable1[i].deny2 == DENY_FCB))
+ continue;
+
+ if (!torture_setting_bool(tctx, "deny_dos_support", true) &&
+ (denytable1[i].deny1 == DENY_DOS ||
+ denytable1[i].deny2 == DENY_DOS))
+ continue;
+
fnum1 = smbcli_open(cli1->tree, fname,
denytable2[i].mode1,
denytable2[i].deny1);
a denytest for ntcreatex
*/
static bool torture_ntdenytest(struct torture_context *tctx,
- struct smbcli_state *cli1, struct smbcli_state *cli2, int client)
+ struct smbcli_state *cli1,
+ struct smbcli_state *cli2, int client)
{
const struct bit_value share_access_bits[] = {
{ NTCREATEX_SHARE_ACCESS_READ, "S_R" },
GetTimeOfDay(&tv_start);
io1.ntcreatex.level = RAW_OPEN_NTCREATEX;
- io1.ntcreatex.in.root_fid = 0;
+ io1.ntcreatex.in.root_fid.fnum = 0;
io1.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
io1.ntcreatex.in.create_options = NTCREATEX_OPTIONS_NON_DIRECTORY_FILE;
io1.ntcreatex.in.file_attr = 0;
return -1;
}
-#define FILL_NTCREATEX(_struct, _init...) \
- do { \
- (_struct)->generic.level = RAW_OPEN_NTCREATEX; \
- (_struct)->ntcreatex.in \
- = (typeof((_struct)->ntcreatex.in)) {_init};\
- } while (0)
-
#define CREATEX_NAME "\\createx_dir"
static bool createx_make_dir(struct torture_context *tctx,
bool ret = true;
NTSTATUS status;
- FILL_NTCREATEX(&open_parms,
- .flags = 0,
- .access_mask = SEC_RIGHTS_FILE_ALL,
- .file_attr = FILE_ATTRIBUTE_NORMAL,
- .share_access = 0,
- .open_disposition = NTCREATEX_DISP_CREATE,
- .create_options = 0,
- .fname = fname,
- );
+ ZERO_STRUCT(open_parms);
+ open_parms.generic.level = RAW_OPEN_NTCREATEX;
+ open_parms.ntcreatex.in.flags = 0;
+ open_parms.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
+ open_parms.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
+ open_parms.ntcreatex.in.share_access = 0;
+ open_parms.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
+ open_parms.ntcreatex.in.create_options = 0;
+ open_parms.ntcreatex.in.fname = fname;
+
status = smb_raw_open(tree, mem_ctx, &open_parms);
CHECK_STATUS(status, NT_STATUS_OK);
static void createx_fill_dir(union smb_open *open_parms, int accessmode,
int sharemode, const char *fname)
{
- FILL_NTCREATEX(open_parms,
- .flags = 0,
- .access_mask = accessmode,
- .file_attr = FILE_ATTRIBUTE_DIRECTORY,
- .share_access = sharemode,
- .open_disposition = NTCREATEX_DISP_OPEN_IF,
- .create_options = NTCREATEX_OPTIONS_DIRECTORY,
- .fname = fname,
- );
+ ZERO_STRUCTP(open_parms);
+ open_parms->generic.level = RAW_OPEN_NTCREATEX;
+ open_parms->ntcreatex.in.flags = 0;
+ open_parms->ntcreatex.in.access_mask = accessmode;
+ open_parms->ntcreatex.in.file_attr = FILE_ATTRIBUTE_DIRECTORY;
+ open_parms->ntcreatex.in.share_access = sharemode;
+ open_parms->ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
+ open_parms->ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
+ open_parms->ntcreatex.in.fname = fname;
}
static void createx_fill_file(union smb_open *open_parms, int accessmode,
int sharemode, const char *fname)
{
- FILL_NTCREATEX(open_parms,
- .flags = 0,
- .access_mask = accessmode,
- .file_attr = FILE_ATTRIBUTE_NORMAL,
- .share_access = sharemode,
- .open_disposition = NTCREATEX_DISP_OPEN_IF,
- .create_options = 0,
- .fname = fname,
- );
+ ZERO_STRUCTP(open_parms);
+ open_parms->generic.level = RAW_OPEN_NTCREATEX;
+ open_parms->ntcreatex.in.flags = 0;
+ open_parms->ntcreatex.in.access_mask = accessmode;
+ open_parms->ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
+ open_parms->ntcreatex.in.share_access = sharemode;
+ open_parms->ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
+ open_parms->ntcreatex.in.create_options = 0;
+ open_parms->ntcreatex.in.fname = fname;
+ open_parms->ntcreatex.in.root_fid.fnum = 0;
}
static int data_file_fd = -1;
union smb_open open_parms;
/* bypass original handle to guarantee creation */
- FILL_NTCREATEX(&open_parms,
- .flags = 0,
- .access_mask = SEC_RIGHTS_FILE_ALL,
- .file_attr = FILE_ATTRIBUTE_NORMAL,
- .share_access = 0,
- .open_disposition = NTCREATEX_DISP_CREATE,
- .create_options = 0,
- .fname = CREATEX_NAME "\\" KNOWN,
- );
+ ZERO_STRUCT(open_parms);
+ open_parms.generic.level = RAW_OPEN_NTCREATEX;
+ open_parms.ntcreatex.in.flags = 0;
+ open_parms.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
+ open_parms.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
+ open_parms.ntcreatex.in.share_access = 0;
+ open_parms.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
+ open_parms.ntcreatex.in.create_options = 0;
+ open_parms.ntcreatex.in.fname = CREATEX_NAME "\\" KNOWN;
+
status = smb_raw_open(tree, mem_ctx, &open_parms);
CHECK_STATUS(status, NT_STATUS_OK);
smbcli_close(tree, open_parms.ntcreatex.out.file.fnum);
result[CXD_DIR_ENUMERATE] = NT_STATUS_OK;
/* try to create a child */
- FILL_NTCREATEX(&open_parms,
- .flags = 0,
- .access_mask = SEC_RIGHTS_FILE_ALL,
- .file_attr = FILE_ATTRIBUTE_NORMAL,
- .share_access = 0,
- .open_disposition = NTCREATEX_DISP_CREATE,
- .create_options = 0,
- .fname = CHILD,
- .root_fid = fnum,
- );
+ ZERO_STRUCT(open_parms);
+ open_parms.generic.level = RAW_OPEN_NTCREATEX;
+ open_parms.ntcreatex.in.flags = 0;
+ open_parms.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
+ open_parms.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
+ open_parms.ntcreatex.in.share_access = 0;
+ open_parms.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
+ open_parms.ntcreatex.in.create_options = 0;
+ open_parms.ntcreatex.in.fname = CHILD;
+ open_parms.ntcreatex.in.root_fid.fnum = fnum;
result[CXD_DIR_CREATE_CHILD] =
smb_raw_open(tree, mem_ctx, &open_parms);
smbcli_close(tree, open_parms.ntcreatex.out.file.fnum);
/* try to traverse dir to known good file */
- FILL_NTCREATEX(&open_parms,
- .flags = 0,
- .access_mask = SEC_RIGHTS_FILE_ALL,
- .file_attr = FILE_ATTRIBUTE_NORMAL,
- .share_access = 0,
- .open_disposition = NTCREATEX_DISP_OPEN,
- .create_options = 0,
- .fname = KNOWN,
- .root_fid = fnum,
- );
+ ZERO_STRUCT(open_parms);
+ open_parms.generic.level = RAW_OPEN_NTCREATEX;
+ open_parms.ntcreatex.in.flags = 0;
+ open_parms.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
+ open_parms.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
+ open_parms.ntcreatex.in.share_access = 0;
+ open_parms.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
+ open_parms.ntcreatex.in.create_options = 0;
+ open_parms.ntcreatex.in.fname = KNOWN;
+ open_parms.ntcreatex.in.root_fid.fnum = fnum;
result[CXD_DIR_TRAVERSE] =
smb_raw_open(tree, mem_ctx, &open_parms);
static bool createx_test_file(struct torture_context *tctx,
struct smbcli_tree *tree, int fnum, TALLOC_CTX *mem_ctx, NTSTATUS *result)
{
- union smb_read rd = {};
- union smb_write wr = {};
+ union smb_read rd;
+ union smb_write wr;
char buf[256] = "";
+ memset(&rd, 0, sizeof(rd));
rd.readx.level = RAW_READ_READX;
rd.readx.in.file.fnum = fnum;
rd.readx.in.mincnt = sizeof(buf);
rd.readx.in.maxcnt = sizeof(buf);
- rd.readx.out.data = buf;
+ rd.readx.out.data = (uint8_t *)buf;
result[CXD_FILE_READ] = smb_raw_read(tree, &rd);
+ memset(&wr, 0, sizeof(wr));
wr.writex.level = RAW_WRITE_WRITEX;
wr.writex.in.file.fnum = fnum;
wr.writex.in.count = sizeof(buf);
- wr.writex.in.data = buf;
+ wr.writex.in.data = (uint8_t *)buf;
result[CXD_FILE_WRITE] = smb_raw_write(tree, &wr);
rd.readx.in.mincnt = sizeof(buf);
rd.readx.in.maxcnt = sizeof(buf);
rd.readx.in.read_for_execute = 1;
- rd.readx.out.data = buf;
+ rd.readx.out.data = (uint8_t *)buf;
result[CXD_FILE_EXECUTE] = smb_raw_read(tree, &rd);
/* TODO When redirecting stdout to a file, the progress bar really screws up
* the output. Could use a switch "--noprogress", or direct the progress bar to
* stderr? No other solution? */
-static void createx_progress_bar(struct torture_context *tctx, uint_t i,
- uint_t total, uint_t skipped)
+static void createx_progress_bar(struct torture_context *tctx, unsigned int i,
+ unsigned int total, unsigned int skipped)
{
if (torture_setting_bool(tctx, "progress", true)) {
torture_comment(tctx, "%5d/%5d (%d skipped)\r", i, total,
destroy_func = smbcli_unlink;
}
+ /* Skip all SACL related tests. */
+ if ((!torture_setting_bool(tctx, "sacl_support", true)) &&
+ ((cxd->cxd_access1 & SEC_FLAG_SYSTEM_SECURITY) ||
+ (cxd->cxd_access2 & SEC_FLAG_SYSTEM_SECURITY)))
+ goto done;
+
if (cxd->cxd_flags & CXD_FLAGS_MAKE_BEFORE_CREATEX) {
ret = make_func(tctx, cli->tree, mem_ctx, fname);
if (!ret) {
if (!mem_ctx)
return false;
+ if (!torture_setting_bool(tctx, "sacl_support", true))
+ torture_warning(tctx, "Skipping SACL related tests!\n");
+
cxd.cxd_test = extended ? CXD_TEST_CREATEX_SHAREMODE_EXTENDED :
CXD_TEST_CREATEX_SHAREMODE;
cxd.cxd_flags = dir ? CXD_FLAGS_DIRECTORY: 0;
if (!mem_ctx)
return false;
+ if (!torture_setting_bool(tctx, "sacl_support", true))
+ torture_warning(tctx, "Skipping SACL related tests!\n");
+
cxd.cxd_test = CXD_TEST_CREATEX_ACCESS;
/* HACK for progress bar: figure out estimated count. */
torture_createx_specific(tctx, cli, NULL, mem_ctx,
&cxd, est);
}
-
for (i = 0; i < num_access_bits; i++) {
/* And now run through the single access bits. */
cxd.cxd_access1 = 1 << i;
if (!mem_ctx)
return false;
+ if (!torture_setting_bool(tctx, "sacl_support", true))
+ torture_warning(tctx, "Skipping SACL related tests!\n");
+
data_file = getenv("CREATEX_DATA");
if (data_file) {
data_file_fd = open(data_file, O_WRONLY|O_CREAT|O_TRUNC, 0666);
bool torture_maximum_allowed(struct torture_context *tctx,
struct smbcli_state *cli)
{
- struct security_descriptor *sd;
- union smb_open io = {};
+ struct security_descriptor *sd, *sd_orig;
+ union smb_open io;
static TALLOC_CTX *mem_ctx;
int fnum, i;
bool ret = true;
NTSTATUS status;
+ union smb_fileinfo q;
+ const char *owner_sid;
+ bool has_restore_privilege, has_backup_privilege;
mem_ctx = talloc_init("torture_maximum_allowed");
+ if (!torture_setting_bool(tctx, "sacl_support", true))
+ torture_warning(tctx, "Skipping SACL related tests!\n");
+
sd = security_descriptor_dacl_create(mem_ctx,
0, NULL, NULL,
SID_NT_AUTHENTICATED_USERS,
smbcli_unlink(cli->tree, MAXIMUM_ALLOWED_FILE);
/* create initial file with restrictive SD */
+ memset(&io, 0, sizeof(io));
io.generic.level = RAW_OPEN_NTTRANS_CREATE;
io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
CHECK_STATUS(status, NT_STATUS_OK);
fnum = io.ntcreatex.out.file.fnum;
+ /* the correct answers for this test depends on whether the
+ user has restore privileges. To find that out we first need
+ to know our SID - get it from the owner_sid of the file we
+ just created */
+ q.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
+ q.query_secdesc.in.file.fnum = fnum;
+ q.query_secdesc.in.secinfo_flags = SECINFO_DACL | SECINFO_OWNER;
+ status = smb_raw_fileinfo(cli->tree, tctx, &q);
+ CHECK_STATUS(status, NT_STATUS_OK);
+ sd_orig = q.query_secdesc.out.sd;
+
+ owner_sid = dom_sid_string(tctx, sd_orig->owner_sid);
+
+ status = torture_check_privilege(cli,
+ owner_sid,
+ sec_privilege_name(SEC_PRIV_RESTORE));
+ has_restore_privilege = NT_STATUS_IS_OK(status);
+ torture_comment(tctx, "Checked SEC_PRIV_RESTORE for %s - %s\n",
+ owner_sid,
+ has_restore_privilege?"Yes":"No");
+
+ status = torture_check_privilege(cli,
+ owner_sid,
+ sec_privilege_name(SEC_PRIV_BACKUP));
+ has_backup_privilege = NT_STATUS_IS_OK(status);
+ torture_comment(tctx, "Checked SEC_PRIV_BACKUP for %s - %s\n",
+ owner_sid,
+ has_backup_privilege?"Yes":"No");
+
smbcli_close(cli->tree, fnum);
for (i = 0; i < 32; i++) {
uint32_t mask = SEC_FLAG_MAXIMUM_ALLOWED | (1u << i);
+ uint32_t ok_mask = SEC_RIGHTS_FILE_READ | SEC_GENERIC_READ |
+ SEC_STD_DELETE | SEC_STD_WRITE_DAC;
+
+ if (has_restore_privilege) {
+ ok_mask |= SEC_RIGHTS_PRIV_RESTORE;
+ }
+ if (has_backup_privilege) {
+ ok_mask |= SEC_RIGHTS_PRIV_BACKUP;
+ }
+
+ /* Skip all SACL related tests. */
+ if ((!torture_setting_bool(tctx, "sacl_support", true)) &&
+ (mask & SEC_FLAG_SYSTEM_SECURITY))
+ continue;
memset(&io, 0, sizeof(io));
io.generic.level = RAW_OPEN_NTTRANS_CREATE;
io.ntcreatex.in.fname = MAXIMUM_ALLOWED_FILE;
status = smb_raw_open(cli->tree, mem_ctx, &io);
- if (mask & SEC_RIGHTS_FILE_READ ||
- mask & SEC_GENERIC_READ ||
- mask & SEC_STD_DELETE || /* owner gets delete */
- mask & SEC_STD_WRITE_DAC || /* and write_dac */
- mask & SEC_STD_WRITE_OWNER ||
- mask & SEC_FLAG_SYSTEM_SECURITY ||
- mask == SEC_FLAG_MAXIMUM_ALLOWED)
+ if (mask & ok_mask ||
+ mask == SEC_FLAG_MAXIMUM_ALLOWED) {
CHECK_STATUS(status, NT_STATUS_OK);
- else
- CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
+ } else {
+ if (mask & SEC_FLAG_SYSTEM_SECURITY) {
+ CHECK_STATUS(status, NT_STATUS_PRIVILEGE_NOT_HELD);
+ } else {
+ CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
+ }
+ }
fnum = io.ntcreatex.out.file.fnum;
}
done:
+ smbcli_unlink(cli->tree, MAXIMUM_ALLOWED_FILE);
return ret;
}