mirror of
https://github.com/samba-team/samba.git
synced 2025-01-22 22:04:08 +03:00
r4173: - new t2open code, that can cope with "create with EAs". Many thanks
to kukks on #samba-technical for the sniffs that allowed me to work this out - much simpler ntvfs open generic mapping code - added t2open create with EA torture test to RAW-OPEN test (This used to be commit a56d95ad89b4f32a05974c4fe9a816d67aa369e3)
This commit is contained in:
parent
e08e2645de
commit
fbd8c61ff7
@ -1133,6 +1133,7 @@ union smb_open {
|
||||
struct {
|
||||
uint16_t flags;
|
||||
uint16_t open_mode;
|
||||
uint16_t search_attrs;
|
||||
uint16_t file_attrs;
|
||||
time_t write_time;
|
||||
uint16_t open_func;
|
||||
@ -1152,7 +1153,7 @@ union smb_open {
|
||||
uint16_t ftype;
|
||||
uint16_t devstate;
|
||||
uint16_t action;
|
||||
uint32_t unknown;
|
||||
uint32_t file_id;
|
||||
} out;
|
||||
} t2open;
|
||||
|
||||
@ -1161,7 +1162,7 @@ union smb_open {
|
||||
enum smb_open_level level;
|
||||
|
||||
struct {
|
||||
uint16_t flags;
|
||||
uint16_t open_mode;
|
||||
uint16_t search_attrs;
|
||||
const char *fname;
|
||||
} in;
|
||||
|
@ -51,7 +51,7 @@ struct smbcli_session *smbcli_session_init(struct smbcli_transport *transport)
|
||||
|
||||
capabilities = transport->negotiate.capabilities;
|
||||
|
||||
flags2 = FLAGS2_LONG_PATH_COMPONENTS;
|
||||
flags2 = FLAGS2_LONG_PATH_COMPONENTS | FLAGS2_EXTENDED_ATTRIBUTES;
|
||||
|
||||
if (capabilities & CAP_UNICODE) {
|
||||
flags2 |= FLAGS2_UNICODE_STRINGS;
|
||||
|
@ -366,10 +366,10 @@ static struct smbcli_request *smb_raw_t2open_send(struct smbcli_tree *tree,
|
||||
|
||||
SSVAL(t2.in.params.data, VWV(0), parms->t2open.in.flags);
|
||||
SSVAL(t2.in.params.data, VWV(1), parms->t2open.in.open_mode);
|
||||
SSVAL(t2.in.params.data, VWV(2), 0); /* reserved */
|
||||
SSVAL(t2.in.params.data, VWV(2), parms->t2open.in.search_attrs);
|
||||
SSVAL(t2.in.params.data, VWV(3), parms->t2open.in.file_attrs);
|
||||
raw_push_dos_date(tree->session->transport,
|
||||
t2.in.params.data, VWV(4), parms->t2open.in.write_time);
|
||||
t2.in.params.data, VWV(4), parms->t2open.in.write_time);
|
||||
SSVAL(t2.in.params.data, VWV(6), parms->t2open.in.open_func);
|
||||
SIVAL(t2.in.params.data, VWV(7), parms->t2open.in.size);
|
||||
SIVAL(t2.in.params.data, VWV(9), parms->t2open.in.timeout);
|
||||
@ -377,8 +377,8 @@ static struct smbcli_request *smb_raw_t2open_send(struct smbcli_tree *tree,
|
||||
SSVAL(t2.in.params.data, VWV(13), 0);
|
||||
|
||||
smbcli_blob_append_string(tree->session, mem_ctx,
|
||||
&t2.in.params, parms->t2open.in.fname,
|
||||
STR_TERMINATE);
|
||||
&t2.in.params, parms->t2open.in.fname,
|
||||
STR_TERMINATE);
|
||||
|
||||
ea_put_list(t2.in.data.data, parms->t2open.in.num_eas, parms->t2open.in.eas);
|
||||
|
||||
@ -414,7 +414,7 @@ static NTSTATUS smb_raw_t2open_recv(struct smbcli_request *req, TALLOC_CTX *mem_
|
||||
parms->t2open.out.ftype = SVAL(t2.out.params.data, VWV(7));
|
||||
parms->t2open.out.devstate = SVAL(t2.out.params.data, VWV(8));
|
||||
parms->t2open.out.action = SVAL(t2.out.params.data, VWV(9));
|
||||
parms->t2open.out.unknown = SVAL(t2.out.params.data, VWV(10));
|
||||
parms->t2open.out.file_id = SVAL(t2.out.params.data, VWV(10));
|
||||
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
@ -433,7 +433,7 @@ struct smbcli_request *smb_raw_open_send(struct smbcli_tree *tree, union smb_ope
|
||||
|
||||
case RAW_OPEN_OPEN:
|
||||
SETUP_REQUEST(SMBopen, 2, 0);
|
||||
SSVAL(req->out.vwv, VWV(0), parms->openold.in.flags);
|
||||
SSVAL(req->out.vwv, VWV(0), parms->openold.in.open_mode);
|
||||
SSVAL(req->out.vwv, VWV(1), parms->openold.in.search_attrs);
|
||||
smbcli_req_append_ascii4(req, parms->openold.in.fname, STR_TERMINATE);
|
||||
break;
|
||||
|
@ -150,13 +150,6 @@ static NTSTATUS ntvfs_map_open_finish(struct smbsrv_request *req,
|
||||
union smb_setfileinfo *sf;
|
||||
uint_t state;
|
||||
|
||||
/* this is really strange, but matches w2k3 */
|
||||
if (io->generic.level == RAW_OPEN_T2OPEN &&
|
||||
io->t2open.in.open_func != OPENX_OPEN_FUNC_OPEN &&
|
||||
NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
|
||||
return NT_STATUS_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
return status;
|
||||
}
|
||||
@ -167,7 +160,7 @@ static NTSTATUS ntvfs_map_open_finish(struct smbsrv_request *req,
|
||||
io->openold.out.attrib = io2->generic.out.attrib;
|
||||
io->openold.out.write_time = nt_time_to_unix(io2->generic.out.write_time);
|
||||
io->openold.out.size = io2->generic.out.size;
|
||||
io->openold.out.rmode = io->openold.in.flags;
|
||||
io->openold.out.rmode = io->openold.in.open_mode;
|
||||
break;
|
||||
|
||||
case RAW_OPEN_OPENX:
|
||||
@ -175,6 +168,7 @@ static NTSTATUS ntvfs_map_open_finish(struct smbsrv_request *req,
|
||||
io->openx.out.attrib = io2->generic.out.attrib;
|
||||
io->openx.out.write_time = nt_time_to_unix(io2->generic.out.write_time);
|
||||
io->openx.out.size = io2->generic.out.size;
|
||||
io->openx.out.access = (io->openx.in.open_mode & OPENX_MODE_ACCESS_MASK);
|
||||
io->openx.out.ftype = 0;
|
||||
io->openx.out.devstate = 0;
|
||||
io->openx.out.action = io2->generic.out.create_action;
|
||||
@ -190,15 +184,15 @@ static NTSTATUS ntvfs_map_open_finish(struct smbsrv_request *req,
|
||||
break;
|
||||
|
||||
case RAW_OPEN_T2OPEN:
|
||||
io->t2open.out.fnum = io2->openx.out.fnum;
|
||||
io->t2open.out.attrib = io2->openx.out.attrib;
|
||||
io->t2open.out.write_time = 0;
|
||||
io->t2open.out.size = io2->openx.out.size;
|
||||
io->t2open.out.access = io->t2open.in.open_mode;
|
||||
io->t2open.out.ftype = io2->openx.out.ftype;
|
||||
io->t2open.out.devstate = io2->openx.out.devstate;
|
||||
io->t2open.out.action = io2->openx.out.action;
|
||||
io->t2open.out.unknown = 0;
|
||||
io->t2open.out.fnum = io2->generic.out.fnum;
|
||||
io->t2open.out.attrib = io2->generic.out.attrib;
|
||||
io->t2open.out.write_time = nt_time_to_unix(io2->generic.out.write_time);
|
||||
io->t2open.out.size = io2->generic.out.size;
|
||||
io->t2open.out.access = io->t2open.in.open_mode;
|
||||
io->t2open.out.ftype = 0;
|
||||
io->t2open.out.devstate = 0;
|
||||
io->t2open.out.action = io2->generic.out.create_action;
|
||||
io->t2open.out.file_id = 0;
|
||||
break;
|
||||
|
||||
case RAW_OPEN_MKNEW:
|
||||
@ -248,6 +242,106 @@ static NTSTATUS ntvfs_map_open_finish(struct smbsrv_request *req,
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
the core of the mapping between openx style parameters and ntcreatex
|
||||
parameters
|
||||
*/
|
||||
static NTSTATUS map_openx_open(uint16_t flags, uint16_t open_mode,
|
||||
uint16_t open_func, const char *fname,
|
||||
union smb_open *io2)
|
||||
{
|
||||
if (flags & OPENX_FLAGS_REQUEST_OPLOCK) {
|
||||
io2->generic.in.flags |= NTCREATEX_FLAGS_REQUEST_OPLOCK;
|
||||
}
|
||||
if (flags & OPENX_FLAGS_REQUEST_BATCH_OPLOCK) {
|
||||
io2->generic.in.flags |= NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
|
||||
}
|
||||
|
||||
switch (open_mode & OPENX_MODE_ACCESS_MASK) {
|
||||
case OPENX_MODE_ACCESS_READ:
|
||||
io2->generic.in.access_mask = SEC_RIGHTS_FILE_READ;
|
||||
break;
|
||||
case OPENX_MODE_ACCESS_WRITE:
|
||||
io2->generic.in.access_mask = SEC_RIGHTS_FILE_WRITE;
|
||||
break;
|
||||
case OPENX_MODE_ACCESS_RDWR:
|
||||
case OPENX_MODE_ACCESS_FCB:
|
||||
case OPENX_MODE_ACCESS_EXEC:
|
||||
io2->generic.in.access_mask =
|
||||
SEC_RIGHTS_FILE_READ |
|
||||
SEC_RIGHTS_FILE_WRITE;
|
||||
break;
|
||||
default:
|
||||
return NT_STATUS_INVALID_LOCK_SEQUENCE;
|
||||
}
|
||||
|
||||
switch (open_mode & OPENX_MODE_DENY_MASK) {
|
||||
case OPENX_MODE_DENY_READ:
|
||||
io2->generic.in.share_access = NTCREATEX_SHARE_ACCESS_WRITE;
|
||||
break;
|
||||
case OPENX_MODE_DENY_WRITE:
|
||||
io2->generic.in.share_access = NTCREATEX_SHARE_ACCESS_READ;
|
||||
break;
|
||||
case OPENX_MODE_DENY_ALL:
|
||||
io2->generic.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
|
||||
break;
|
||||
case OPENX_MODE_DENY_NONE:
|
||||
io2->generic.in.share_access =
|
||||
NTCREATEX_SHARE_ACCESS_READ |
|
||||
NTCREATEX_SHARE_ACCESS_WRITE;
|
||||
break;
|
||||
case OPENX_MODE_DENY_DOS:
|
||||
/* DENY_DOS is quite strange - it depends on the filename! */
|
||||
io2->generic.in.create_options |=
|
||||
NTCREATEX_OPTIONS_PRIVATE_DENY_DOS;
|
||||
if (is_exe_filename(fname)) {
|
||||
io2->generic.in.share_access =
|
||||
NTCREATEX_SHARE_ACCESS_READ |
|
||||
NTCREATEX_SHARE_ACCESS_WRITE;
|
||||
} else {
|
||||
if ((open_mode & OPENX_MODE_ACCESS_MASK) == OPENX_MODE_ACCESS_READ) {
|
||||
io2->generic.in.share_access = NTCREATEX_SHARE_ACCESS_READ;
|
||||
} else {
|
||||
io2->generic.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case OPENX_MODE_DENY_FCB:
|
||||
io2->generic.in.create_options |= NTCREATEX_OPTIONS_PRIVATE_DENY_FCB;
|
||||
io2->generic.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
|
||||
break;
|
||||
default:
|
||||
return NT_STATUS_INVALID_LOCK_SEQUENCE;
|
||||
}
|
||||
|
||||
switch (open_func) {
|
||||
case (OPENX_OPEN_FUNC_OPEN):
|
||||
io2->generic.in.open_disposition = NTCREATEX_DISP_OPEN;
|
||||
break;
|
||||
case (OPENX_OPEN_FUNC_TRUNC):
|
||||
io2->generic.in.open_disposition = NTCREATEX_DISP_OVERWRITE;
|
||||
break;
|
||||
case (OPENX_OPEN_FUNC_FAIL | OPENX_OPEN_FUNC_CREATE):
|
||||
io2->generic.in.open_disposition = NTCREATEX_DISP_CREATE;
|
||||
break;
|
||||
case (OPENX_OPEN_FUNC_OPEN | OPENX_OPEN_FUNC_CREATE):
|
||||
io2->generic.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
|
||||
break;
|
||||
case (OPENX_OPEN_FUNC_TRUNC | OPENX_OPEN_FUNC_CREATE):
|
||||
io2->generic.in.open_disposition = NTCREATEX_DISP_OVERWRITE_IF;
|
||||
break;
|
||||
default:
|
||||
/* this one is very strange */
|
||||
if ((open_mode & OPENX_MODE_ACCESS_MASK) == OPENX_MODE_ACCESS_EXEC) {
|
||||
io2->generic.in.open_disposition = NTCREATEX_DISP_CREATE;
|
||||
break;
|
||||
}
|
||||
return NT_STATUS_INVALID_LOCK_SEQUENCE;
|
||||
}
|
||||
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
NTVFS open generic to any mapper
|
||||
*/
|
||||
@ -272,105 +366,15 @@ NTSTATUS ntvfs_map_open(struct smbsrv_request *req, union smb_open *io,
|
||||
|
||||
switch (io->generic.level) {
|
||||
case RAW_OPEN_OPENX:
|
||||
if (io->openx.in.flags & OPENX_FLAGS_REQUEST_OPLOCK) {
|
||||
io2->generic.in.flags |= NTCREATEX_FLAGS_REQUEST_OPLOCK;
|
||||
}
|
||||
if (io->openx.in.flags & OPENX_FLAGS_REQUEST_BATCH_OPLOCK) {
|
||||
io2->generic.in.flags |= NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
|
||||
}
|
||||
|
||||
switch (io->openx.in.open_mode & OPENX_MODE_ACCESS_MASK) {
|
||||
case OPENX_MODE_ACCESS_READ:
|
||||
io2->generic.in.access_mask = SEC_RIGHTS_FILE_READ;
|
||||
io->openx.out.access = OPENX_MODE_ACCESS_READ;
|
||||
break;
|
||||
case OPENX_MODE_ACCESS_WRITE:
|
||||
io2->generic.in.access_mask = SEC_RIGHTS_FILE_WRITE;
|
||||
io->openx.out.access = OPENX_MODE_ACCESS_WRITE;
|
||||
break;
|
||||
case OPENX_MODE_ACCESS_RDWR:
|
||||
case OPENX_MODE_ACCESS_FCB:
|
||||
case OPENX_MODE_ACCESS_EXEC:
|
||||
io2->generic.in.access_mask =
|
||||
SEC_RIGHTS_FILE_READ |
|
||||
SEC_RIGHTS_FILE_WRITE;
|
||||
io->openx.out.access = OPENX_MODE_ACCESS_RDWR;
|
||||
break;
|
||||
default:
|
||||
status = NT_STATUS_INVALID_LOCK_SEQUENCE;
|
||||
status = map_openx_open(io->openx.in.flags,
|
||||
io->openx.in.open_mode,
|
||||
io->openx.in.open_func,
|
||||
io->openx.in.fname,
|
||||
io2);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
switch (io->openx.in.open_mode & OPENX_MODE_DENY_MASK) {
|
||||
case OPENX_MODE_DENY_READ:
|
||||
io2->generic.in.share_access = NTCREATEX_SHARE_ACCESS_WRITE;
|
||||
break;
|
||||
case OPENX_MODE_DENY_WRITE:
|
||||
io2->generic.in.share_access = NTCREATEX_SHARE_ACCESS_READ;
|
||||
break;
|
||||
case OPENX_MODE_DENY_ALL:
|
||||
io2->generic.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
|
||||
break;
|
||||
case OPENX_MODE_DENY_NONE:
|
||||
io2->generic.in.share_access =
|
||||
NTCREATEX_SHARE_ACCESS_READ |
|
||||
NTCREATEX_SHARE_ACCESS_WRITE;
|
||||
break;
|
||||
case OPENX_MODE_DENY_DOS:
|
||||
/* DENY_DOS is quite strange - it depends on the filename! */
|
||||
io2->generic.in.create_options |=
|
||||
NTCREATEX_OPTIONS_PRIVATE_DENY_DOS;
|
||||
if (is_exe_filename(io->openx.in.fname)) {
|
||||
io2->generic.in.share_access =
|
||||
NTCREATEX_SHARE_ACCESS_READ |
|
||||
NTCREATEX_SHARE_ACCESS_WRITE;
|
||||
} else {
|
||||
if ((io->openx.in.open_mode & OPENX_MODE_ACCESS_MASK) ==
|
||||
OPENX_MODE_ACCESS_READ) {
|
||||
io2->generic.in.share_access = NTCREATEX_SHARE_ACCESS_READ;
|
||||
} else {
|
||||
io2->generic.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case OPENX_MODE_DENY_FCB:
|
||||
io2->generic.in.create_options |=
|
||||
NTCREATEX_OPTIONS_PRIVATE_DENY_FCB;
|
||||
io2->generic.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
|
||||
break;
|
||||
default:
|
||||
status = NT_STATUS_INVALID_LOCK_SEQUENCE;
|
||||
goto done;
|
||||
}
|
||||
|
||||
switch (io->openx.in.open_func) {
|
||||
case (OPENX_OPEN_FUNC_OPEN):
|
||||
io2->generic.in.open_disposition = NTCREATEX_DISP_OPEN;
|
||||
break;
|
||||
case (OPENX_OPEN_FUNC_TRUNC):
|
||||
io2->generic.in.open_disposition = NTCREATEX_DISP_OVERWRITE;
|
||||
break;
|
||||
case (OPENX_OPEN_FUNC_FAIL | OPENX_OPEN_FUNC_CREATE):
|
||||
io2->generic.in.open_disposition = NTCREATEX_DISP_CREATE;
|
||||
break;
|
||||
case (OPENX_OPEN_FUNC_OPEN | OPENX_OPEN_FUNC_CREATE):
|
||||
io2->generic.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
|
||||
break;
|
||||
case (OPENX_OPEN_FUNC_TRUNC | OPENX_OPEN_FUNC_CREATE):
|
||||
io2->generic.in.open_disposition = NTCREATEX_DISP_OVERWRITE_IF;
|
||||
break;
|
||||
default:
|
||||
/* this one is very strange */
|
||||
if ((io->openx.in.open_mode & OPENX_MODE_ACCESS_MASK) ==
|
||||
OPENX_MODE_ACCESS_EXEC) {
|
||||
io2->generic.in.open_disposition = NTCREATEX_DISP_CREATE;
|
||||
break;
|
||||
}
|
||||
status = NT_STATUS_INVALID_LOCK_SEQUENCE;
|
||||
goto done;
|
||||
}
|
||||
|
||||
io2->generic.in.alloc_size = 0;
|
||||
io2->generic.in.file_attr = io->openx.in.file_attrs;
|
||||
io2->generic.in.fname = io->openx.in.fname;
|
||||
|
||||
@ -379,85 +383,44 @@ NTSTATUS ntvfs_map_open(struct smbsrv_request *req, union smb_open *io,
|
||||
|
||||
|
||||
case RAW_OPEN_OPEN:
|
||||
status = map_openx_open(0,
|
||||
io->openold.in.open_mode,
|
||||
OPENX_OPEN_FUNC_OPEN,
|
||||
io->openold.in.fname,
|
||||
io2);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
io2->generic.in.file_attr = io->openold.in.search_attrs;
|
||||
io2->generic.in.fname = io->openold.in.fname;
|
||||
io2->generic.in.open_disposition = NTCREATEX_DISP_OPEN;
|
||||
switch (io->openold.in.flags & OPEN_FLAGS_MODE_MASK) {
|
||||
case OPEN_FLAGS_OPEN_READ:
|
||||
io2->generic.in.access_mask = SEC_RIGHTS_FILE_READ;
|
||||
io->openold.out.rmode = DOS_OPEN_RDONLY;
|
||||
break;
|
||||
case OPEN_FLAGS_OPEN_WRITE:
|
||||
io2->generic.in.access_mask = SEC_RIGHTS_FILE_WRITE;
|
||||
io->openold.out.rmode = DOS_OPEN_WRONLY;
|
||||
break;
|
||||
case OPEN_FLAGS_OPEN_RDWR:
|
||||
case 0xf: /* FCB mode */
|
||||
io2->generic.in.access_mask = SEC_RIGHTS_FILE_READ |
|
||||
SEC_RIGHTS_FILE_WRITE;
|
||||
io->openold.out.rmode = DOS_OPEN_RDWR; /* assume we got r/w */
|
||||
break;
|
||||
default:
|
||||
DEBUG(2,("ntvfs_map_open(OPEN): invalid mode 0x%x\n",
|
||||
io->openold.in.flags & OPEN_FLAGS_MODE_MASK));
|
||||
status = NT_STATUS_INVALID_PARAMETER;
|
||||
goto done;
|
||||
}
|
||||
|
||||
switch (io->openold.in.flags & OPEN_FLAGS_DENY_MASK) {
|
||||
case OPEN_FLAGS_DENY_DOS:
|
||||
/* DENY_DOS is quite strange - it depends on the filename! */
|
||||
if (is_exe_filename(io->openold.in.fname)) {
|
||||
io2->generic.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
|
||||
} else {
|
||||
if ((io->openold.in.flags & OPEN_FLAGS_MODE_MASK) ==
|
||||
OPEN_FLAGS_OPEN_READ) {
|
||||
io2->generic.in.share_access = NTCREATEX_SHARE_ACCESS_READ;
|
||||
} else {
|
||||
io2->generic.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case OPEN_FLAGS_DENY_ALL:
|
||||
io2->generic.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
|
||||
break;
|
||||
case OPEN_FLAGS_DENY_WRITE:
|
||||
io2->generic.in.share_access = NTCREATEX_SHARE_ACCESS_READ;
|
||||
break;
|
||||
case OPEN_FLAGS_DENY_READ:
|
||||
io2->generic.in.share_access = NTCREATEX_SHARE_ACCESS_WRITE;
|
||||
break;
|
||||
case OPEN_FLAGS_DENY_NONE:
|
||||
io2->generic.in.share_access =
|
||||
NTCREATEX_SHARE_ACCESS_WRITE |
|
||||
NTCREATEX_SHARE_ACCESS_READ;
|
||||
break;
|
||||
case OPEN_FLAGS_DENY_MASK:
|
||||
io2->generic.in.share_access =
|
||||
NTCREATEX_SHARE_ACCESS_READ|
|
||||
NTCREATEX_SHARE_ACCESS_WRITE;
|
||||
break;
|
||||
default:
|
||||
DEBUG(2,("ntvfs_map_open(OPEN): invalid DENY 0x%x\n",
|
||||
io->openold.in.flags & OPEN_FLAGS_DENY_MASK));
|
||||
status = NT_STATUS_INVALID_PARAMETER;
|
||||
goto done;
|
||||
}
|
||||
|
||||
status = ntvfs->ops->openfile(ntvfs, req, io2);
|
||||
break;
|
||||
|
||||
case RAW_OPEN_T2OPEN:
|
||||
io2->generic.level = RAW_OPEN_OPENX;
|
||||
io2->openx.in.flags = io->t2open.in.flags;
|
||||
io2->openx.in.open_mode = io->t2open.in.open_mode;
|
||||
io2->openx.in.search_attrs = 0;
|
||||
io2->openx.in.file_attrs = io->t2open.in.file_attrs;
|
||||
io2->openx.in.write_time = io->t2open.in.write_time;
|
||||
io2->openx.in.open_func = OPENX_OPEN_FUNC_OPEN;
|
||||
io2->openx.in.size = io->t2open.in.size;
|
||||
io2->openx.in.timeout = io->t2open.in.timeout;
|
||||
io2->openx.in.fname = io->t2open.in.fname;
|
||||
io2->generic.level = RAW_OPEN_NTTRANS_CREATE;
|
||||
|
||||
if (io->t2open.in.open_func == 0) {
|
||||
status = NT_STATUS_OBJECT_NAME_COLLISION;
|
||||
goto done;
|
||||
}
|
||||
|
||||
status = map_openx_open(io->t2open.in.flags,
|
||||
io->t2open.in.open_mode,
|
||||
io->t2open.in.open_func,
|
||||
io->t2open.in.fname,
|
||||
io2);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
io2->generic.in.file_attr = io->t2open.in.file_attrs;
|
||||
io2->generic.in.fname = io->t2open.in.fname;
|
||||
io2->generic.in.ea_list = talloc_p(io2, struct smb_ea_list);
|
||||
io2->generic.in.ea_list->num_eas = io->t2open.in.num_eas;
|
||||
io2->generic.in.ea_list->eas = io->t2open.in.eas;
|
||||
|
||||
status = ntvfs->ops->openfile(ntvfs, req, io2);
|
||||
break;
|
||||
|
||||
@ -508,7 +471,6 @@ NTSTATUS ntvfs_map_open(struct smbsrv_request *req, union smb_open *io,
|
||||
status = NT_STATUS_INVALID_LEVEL;
|
||||
break;
|
||||
}
|
||||
|
||||
done:
|
||||
return ntvfs_map_async_finish(req, status);
|
||||
}
|
||||
|
@ -794,38 +794,6 @@ static NTSTATUS pvfs_open_setup_retry(struct ntvfs_module_context *ntvfs,
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
special handling for t2open
|
||||
*/
|
||||
static NTSTATUS pvfs_open_t2open(struct ntvfs_module_context *ntvfs,
|
||||
struct smbsrv_request *req, union smb_open *io)
|
||||
{
|
||||
struct pvfs_state *pvfs = ntvfs->private_data;
|
||||
struct pvfs_filename *name;
|
||||
NTSTATUS status;
|
||||
|
||||
status = pvfs_resolve_name(pvfs, req, io->t2open.in.fname, 0, &name);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
return status;
|
||||
}
|
||||
|
||||
if (io->t2open.in.open_func & OPENX_OPEN_FUNC_CREATE) {
|
||||
if (!name->stream_exists) return NT_STATUS_ACCESS_DENIED;
|
||||
}
|
||||
if (io->t2open.in.open_func & OPENX_OPEN_FUNC_TRUNC) {
|
||||
if (name->stream_exists) return NT_STATUS_ACCESS_DENIED;
|
||||
return NT_STATUS_OBJECT_NAME_NOT_FOUND;
|
||||
}
|
||||
if ((io->t2open.in.open_func & 0xF) == OPENX_OPEN_FUNC_FAIL) {
|
||||
if (!name->stream_exists) return NT_STATUS_ACCESS_DENIED;
|
||||
return NT_STATUS_OBJECT_NAME_COLLISION;
|
||||
}
|
||||
|
||||
talloc_free(name);
|
||||
|
||||
return ntvfs_map_open(req, io, ntvfs);
|
||||
}
|
||||
|
||||
/*
|
||||
open a file
|
||||
*/
|
||||
@ -844,10 +812,6 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs,
|
||||
uint32_t access_mask;
|
||||
BOOL stream_existed;
|
||||
|
||||
if (io->generic.level == RAW_OPEN_T2OPEN) {
|
||||
return pvfs_open_t2open(ntvfs, req, io);
|
||||
}
|
||||
|
||||
/* use the generic mapping code to avoid implementing all the
|
||||
different open calls. */
|
||||
if (io->generic.level != RAW_OPEN_GENERIC &&
|
||||
|
@ -430,7 +430,7 @@ void reply_open(struct smbsrv_request *req)
|
||||
REQ_TALLOC(oi, sizeof(*oi));
|
||||
|
||||
oi->openold.level = RAW_OPEN_OPEN;
|
||||
oi->openold.in.flags = SVAL(req->in.vwv, VWV(0));
|
||||
oi->openold.in.open_mode = SVAL(req->in.vwv, VWV(0));
|
||||
oi->openold.in.search_attrs = SVAL(req->in.vwv, VWV(1));
|
||||
|
||||
req_pull_ascii4(req, &oi->openold.in.fname, req->in.data, STR_TERMINATE);
|
||||
|
@ -1089,14 +1089,14 @@ static BOOL handler_open(int instance)
|
||||
NTSTATUS status[NSERVERS];
|
||||
|
||||
parm[0].openold.level = RAW_OPEN_OPEN;
|
||||
parm[0].openold.in.flags = gen_bits_mask2(0xF, 0xFFFF);
|
||||
parm[0].openold.in.open_mode = gen_bits_mask2(0xF, 0xFFFF);
|
||||
parm[0].openold.in.search_attrs = gen_attrib();
|
||||
parm[0].openold.in.fname = gen_fname_open(instance);
|
||||
|
||||
if (!options.use_oplocks) {
|
||||
/* mask out oplocks */
|
||||
parm[0].openold.in.flags &= ~(OPENX_FLAGS_REQUEST_OPLOCK|
|
||||
OPENX_FLAGS_REQUEST_BATCH_OPLOCK);
|
||||
parm[0].openold.in.open_mode &= ~(OPENX_FLAGS_REQUEST_OPLOCK|
|
||||
OPENX_FLAGS_REQUEST_BATCH_OPLOCK);
|
||||
}
|
||||
|
||||
GEN_COPY_PARM;
|
||||
|
@ -34,55 +34,6 @@
|
||||
goto done; \
|
||||
}} while (0)
|
||||
|
||||
/*
|
||||
check that an EA has the right value
|
||||
*/
|
||||
static BOOL check_ea(struct smbcli_state *cli, TALLOC_CTX *mem_ctx,
|
||||
const char *fname, const char *eaname, const char *value)
|
||||
{
|
||||
union smb_fileinfo info;
|
||||
NTSTATUS status;
|
||||
BOOL ret = True;
|
||||
int i;
|
||||
|
||||
info.all_eas.level = RAW_FILEINFO_ALL_EAS;
|
||||
info.all_eas.in.fname = fname;
|
||||
|
||||
status = smb_raw_pathinfo(cli->tree, mem_ctx, &info);
|
||||
CHECK_STATUS(status, NT_STATUS_OK);
|
||||
|
||||
for (i=0;i<info.all_eas.out.num_eas;i++) {
|
||||
if (StrCaseCmp(eaname, info.all_eas.out.eas[i].name.s) == 0) {
|
||||
if (value == NULL) {
|
||||
printf("attr '%s' should not be present\n", eaname);
|
||||
return False;
|
||||
}
|
||||
if (strlen(value) == info.all_eas.out.eas[i].value.length &&
|
||||
memcmp(value,
|
||||
info.all_eas.out.eas[i].value.data,
|
||||
info.all_eas.out.eas[i].value.length) == 0) {
|
||||
return True;
|
||||
} else {
|
||||
printf("attr '%s' has wrong value '%*.*s'\n",
|
||||
eaname,
|
||||
info.all_eas.out.eas[i].value.length,
|
||||
info.all_eas.out.eas[i].value.length,
|
||||
info.all_eas.out.eas[i].value.data);
|
||||
ret = False;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (value != NULL) {
|
||||
printf("attr '%s' not found\n", eaname);
|
||||
ret = False;
|
||||
}
|
||||
|
||||
done:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static DATA_BLOB data_blob_string_const(const char *str)
|
||||
{
|
||||
DATA_BLOB blob;
|
||||
@ -91,6 +42,12 @@ static DATA_BLOB data_blob_string_const(const char *str)
|
||||
return blob;
|
||||
}
|
||||
|
||||
static BOOL check_ea(struct smbcli_state *cli,
|
||||
const char *fname, const char *eaname, const char *value)
|
||||
{
|
||||
NTSTATUS status = torture_check_ea(cli, fname, eaname, value);
|
||||
return NT_STATUS_IS_OK(status);
|
||||
}
|
||||
|
||||
static BOOL test_eas(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
|
||||
{
|
||||
@ -121,7 +78,7 @@ static BOOL test_eas(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
|
||||
CHECK_STATUS(status, NT_STATUS_OK);
|
||||
fnum = io.ntcreatex.out.fnum;
|
||||
|
||||
ret &= check_ea(cli, mem_ctx, fname, "EAONE", NULL);
|
||||
ret &= check_ea(cli, fname, "EAONE", NULL);
|
||||
|
||||
printf("Adding first EA\n");
|
||||
setfile.generic.level = RAW_SFILEINFO_EA_SET;
|
||||
@ -133,7 +90,7 @@ static BOOL test_eas(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
|
||||
status = smb_raw_setfileinfo(cli->tree, &setfile);
|
||||
CHECK_STATUS(status, NT_STATUS_OK);
|
||||
|
||||
ret &= check_ea(cli, mem_ctx, fname, "EAONE", "VALUE1");
|
||||
ret &= check_ea(cli, fname, "EAONE", "VALUE1");
|
||||
|
||||
setfile.ea_set.in.ea.name.s = "SECONDEA";
|
||||
setfile.ea_set.in.ea.value = data_blob_string_const("ValueTwo");
|
||||
@ -142,16 +99,16 @@ static BOOL test_eas(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
|
||||
status = smb_raw_setfileinfo(cli->tree, &setfile);
|
||||
CHECK_STATUS(status, NT_STATUS_OK);
|
||||
|
||||
ret &= check_ea(cli, mem_ctx, fname, "EAONE", "VALUE1");
|
||||
ret &= check_ea(cli, mem_ctx, fname, "SECONDEA", "ValueTwo");
|
||||
ret &= check_ea(cli, fname, "EAONE", "VALUE1");
|
||||
ret &= check_ea(cli, fname, "SECONDEA", "ValueTwo");
|
||||
|
||||
printf("Modifying 2nd EA\n");
|
||||
setfile.ea_set.in.ea.value = data_blob_string_const(" Changed Value");
|
||||
status = smb_raw_setfileinfo(cli->tree, &setfile);
|
||||
CHECK_STATUS(status, NT_STATUS_OK);
|
||||
|
||||
ret &= check_ea(cli, mem_ctx, fname, "EAONE", "VALUE1");
|
||||
ret &= check_ea(cli, mem_ctx, fname, "SECONDEA", " Changed Value");
|
||||
ret &= check_ea(cli, fname, "EAONE", "VALUE1");
|
||||
ret &= check_ea(cli, fname, "SECONDEA", " Changed Value");
|
||||
|
||||
printf("Setting a NULL EA\n");
|
||||
setfile.ea_set.in.ea.value = data_blob(NULL, 0);
|
||||
@ -159,9 +116,9 @@ static BOOL test_eas(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
|
||||
status = smb_raw_setfileinfo(cli->tree, &setfile);
|
||||
CHECK_STATUS(status, NT_STATUS_OK);
|
||||
|
||||
ret &= check_ea(cli, mem_ctx, fname, "EAONE", "VALUE1");
|
||||
ret &= check_ea(cli, mem_ctx, fname, "SECONDEA", " Changed Value");
|
||||
ret &= check_ea(cli, mem_ctx, fname, "NULLEA", NULL);
|
||||
ret &= check_ea(cli, fname, "EAONE", "VALUE1");
|
||||
ret &= check_ea(cli, fname, "SECONDEA", " Changed Value");
|
||||
ret &= check_ea(cli, fname, "NULLEA", NULL);
|
||||
|
||||
printf("Deleting first EA\n");
|
||||
setfile.ea_set.in.ea.flags = 0;
|
||||
@ -170,8 +127,8 @@ static BOOL test_eas(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
|
||||
status = smb_raw_setfileinfo(cli->tree, &setfile);
|
||||
CHECK_STATUS(status, NT_STATUS_OK);
|
||||
|
||||
ret &= check_ea(cli, mem_ctx, fname, "EAONE", NULL);
|
||||
ret &= check_ea(cli, mem_ctx, fname, "SECONDEA", " Changed Value");
|
||||
ret &= check_ea(cli, fname, "EAONE", NULL);
|
||||
ret &= check_ea(cli, fname, "SECONDEA", " Changed Value");
|
||||
|
||||
printf("Deleting second EA\n");
|
||||
setfile.ea_set.in.ea.flags = 0;
|
||||
@ -180,8 +137,8 @@ static BOOL test_eas(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
|
||||
status = smb_raw_setfileinfo(cli->tree, &setfile);
|
||||
CHECK_STATUS(status, NT_STATUS_OK);
|
||||
|
||||
ret &= check_ea(cli, mem_ctx, fname, "EAONE", NULL);
|
||||
ret &= check_ea(cli, mem_ctx, fname, "SECONDEA", NULL);
|
||||
ret &= check_ea(cli, fname, "EAONE", NULL);
|
||||
ret &= check_ea(cli, fname, "SECONDEA", NULL);
|
||||
|
||||
done:
|
||||
smbcli_close(cli->tree, fnum);
|
||||
@ -241,10 +198,10 @@ static BOOL test_nttrans_create(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
|
||||
CHECK_STATUS(status, NT_STATUS_OK);
|
||||
fnum = io.ntcreatex.out.fnum;
|
||||
|
||||
ret &= check_ea(cli, mem_ctx, fname, "EAONE", NULL);
|
||||
ret &= check_ea(cli, mem_ctx, fname, "1st EA", "Value One");
|
||||
ret &= check_ea(cli, mem_ctx, fname, "2nd EA", "Second Value");
|
||||
ret &= check_ea(cli, mem_ctx, fname, "and 3rd", "final value");
|
||||
ret &= check_ea(cli, fname, "EAONE", NULL);
|
||||
ret &= check_ea(cli, fname, "1st EA", "Value One");
|
||||
ret &= check_ea(cli, fname, "2nd EA", "Second Value");
|
||||
ret &= check_ea(cli, fname, "and 3rd", "final value");
|
||||
|
||||
smbcli_close(cli->tree, fnum);
|
||||
|
||||
@ -261,10 +218,10 @@ static BOOL test_nttrans_create(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
|
||||
CHECK_STATUS(status, NT_STATUS_OK);
|
||||
fnum = io.ntcreatex.out.fnum;
|
||||
|
||||
ret &= check_ea(cli, mem_ctx, fname, "1st EA", "Value One");
|
||||
ret &= check_ea(cli, mem_ctx, fname, "2nd EA", "Second Value");
|
||||
ret &= check_ea(cli, mem_ctx, fname, "and 3rd", "final value");
|
||||
ret &= check_ea(cli, mem_ctx, fname, "Fourth EA", NULL);
|
||||
ret &= check_ea(cli, fname, "1st EA", "Value One");
|
||||
ret &= check_ea(cli, fname, "2nd EA", "Second Value");
|
||||
ret &= check_ea(cli, fname, "and 3rd", "final value");
|
||||
ret &= check_ea(cli, fname, "Fourth EA", NULL);
|
||||
|
||||
done:
|
||||
smbcli_close(cli->tree, fnum);
|
||||
|
@ -160,7 +160,7 @@ static BOOL test_open(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
|
||||
|
||||
io.openold.level = RAW_OPEN_OPEN;
|
||||
io.openold.in.fname = fname;
|
||||
io.openold.in.flags = OPEN_FLAGS_FCB;
|
||||
io.openold.in.open_mode = OPEN_FLAGS_FCB;
|
||||
io.openold.in.search_attrs = 0;
|
||||
status = smb_raw_open(cli->tree, mem_ctx, &io);
|
||||
CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
|
||||
@ -187,21 +187,21 @@ static BOOL test_open(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
|
||||
io.openold.in.fname = fname;
|
||||
io.openold.in.search_attrs = 0;
|
||||
|
||||
io.openold.in.flags = OPEN_FLAGS_OPEN_READ;
|
||||
io.openold.in.open_mode = OPEN_FLAGS_OPEN_READ;
|
||||
status = smb_raw_open(cli->tree, mem_ctx, &io);
|
||||
CHECK_STATUS(status, NT_STATUS_OK);
|
||||
fnum = io.openold.out.fnum;
|
||||
CHECK_RDWR(fnum, RDWR_RDONLY);
|
||||
smbcli_close(cli->tree, fnum);
|
||||
|
||||
io.openold.in.flags = OPEN_FLAGS_OPEN_WRITE;
|
||||
io.openold.in.open_mode = OPEN_FLAGS_OPEN_WRITE;
|
||||
status = smb_raw_open(cli->tree, mem_ctx, &io);
|
||||
CHECK_STATUS(status, NT_STATUS_OK);
|
||||
fnum = io.openold.out.fnum;
|
||||
CHECK_RDWR(fnum, RDWR_WRONLY);
|
||||
smbcli_close(cli->tree, fnum);
|
||||
|
||||
io.openold.in.flags = OPEN_FLAGS_OPEN_RDWR;
|
||||
io.openold.in.open_mode = OPEN_FLAGS_OPEN_RDWR;
|
||||
status = smb_raw_open(cli->tree, mem_ctx, &io);
|
||||
CHECK_STATUS(status, NT_STATUS_OK);
|
||||
fnum = io.openold.out.fnum;
|
||||
@ -209,22 +209,22 @@ static BOOL test_open(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
|
||||
smbcli_close(cli->tree, fnum);
|
||||
|
||||
/* check the share modes roughly - not a complete matrix */
|
||||
io.openold.in.flags = OPEN_FLAGS_OPEN_RDWR | OPEN_FLAGS_DENY_WRITE;
|
||||
io.openold.in.open_mode = OPEN_FLAGS_OPEN_RDWR | OPEN_FLAGS_DENY_WRITE;
|
||||
status = smb_raw_open(cli->tree, mem_ctx, &io);
|
||||
CHECK_STATUS(status, NT_STATUS_OK);
|
||||
fnum = io.openold.out.fnum;
|
||||
CHECK_RDWR(fnum, RDWR_RDWR);
|
||||
|
||||
if (io.openold.in.flags != io.openold.out.rmode) {
|
||||
printf("(%s) rmode should equal flags - 0x%x 0x%x\n",
|
||||
__location__, io.openold.out.rmode, io.openold.in.flags);
|
||||
if (io.openold.in.open_mode != io.openold.out.rmode) {
|
||||
printf("(%s) rmode should equal open_mode - 0x%x 0x%x\n",
|
||||
__location__, io.openold.out.rmode, io.openold.in.open_mode);
|
||||
}
|
||||
|
||||
io.openold.in.flags = OPEN_FLAGS_OPEN_RDWR | OPEN_FLAGS_DENY_NONE;
|
||||
io.openold.in.open_mode = OPEN_FLAGS_OPEN_RDWR | OPEN_FLAGS_DENY_NONE;
|
||||
status = smb_raw_open(cli->tree, mem_ctx, &io);
|
||||
CHECK_STATUS(status, NT_STATUS_SHARING_VIOLATION);
|
||||
|
||||
io.openold.in.flags = OPEN_FLAGS_OPEN_READ | OPEN_FLAGS_DENY_NONE;
|
||||
io.openold.in.open_mode = OPEN_FLAGS_OPEN_READ | OPEN_FLAGS_DENY_NONE;
|
||||
status = smb_raw_open(cli->tree, mem_ctx, &io);
|
||||
CHECK_STATUS(status, NT_STATUS_OK);
|
||||
fnum2 = io.openold.out.fnum;
|
||||
@ -237,7 +237,7 @@ static BOOL test_open(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
|
||||
io.openold.level = RAW_OPEN_OPEN;
|
||||
io.openold.in.fname = fname;
|
||||
io.openold.in.search_attrs = 0;
|
||||
io.openold.in.flags = OPEN_FLAGS_OPEN_READ;
|
||||
io.openold.in.open_mode = OPEN_FLAGS_OPEN_READ;
|
||||
status = smb_raw_open(cli->tree, mem_ctx, &io);
|
||||
CHECK_STATUS(status, NT_STATUS_OK);
|
||||
fnum = io.openold.out.fnum;
|
||||
@ -319,12 +319,16 @@ static BOOL test_openx(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
|
||||
i, (int)open_funcs[i].with_file, (int)open_funcs[i].open_func);
|
||||
ret = False;
|
||||
}
|
||||
if (NT_STATUS_IS_OK(status) || open_funcs[i].with_file) {
|
||||
if (NT_STATUS_IS_OK(status)) {
|
||||
smbcli_close(cli->tree, io.openx.out.fnum);
|
||||
}
|
||||
if (open_funcs[i].with_file) {
|
||||
smbcli_unlink(cli->tree, fname);
|
||||
}
|
||||
}
|
||||
|
||||
smbcli_unlink(cli->tree, fname);
|
||||
|
||||
/* check the basic return fields */
|
||||
io.openx.in.open_func = OPENX_OPEN_FUNC_OPEN | OPENX_OPEN_FUNC_CREATE;
|
||||
status = smb_raw_open(cli->tree, mem_ctx, &io);
|
||||
@ -434,6 +438,10 @@ static BOOL test_openx(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
|
||||
CHECK_VAL(io.openx.out.access_mask, SEC_STD_ALL);
|
||||
smbcli_close(cli->tree, io.openx.out.fnum);
|
||||
|
||||
io.openx.in.fname = "\\A.+,;=[].B";
|
||||
status = smb_raw_open(cli->tree, mem_ctx, &io);
|
||||
CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
|
||||
|
||||
done:
|
||||
smbcli_close(cli->tree, fnum);
|
||||
smbcli_unlink(cli->tree, fname);
|
||||
@ -445,9 +453,7 @@ done:
|
||||
/*
|
||||
test RAW_OPEN_T2OPEN
|
||||
|
||||
I can't work out how to get win2003 to accept a create file via TRANS2_OPEN, which
|
||||
is why you see all the ACCESS_DENIED results below. When we finally work this out then this
|
||||
test will make more sense
|
||||
many thanks to kukks for a sniff showing how this works with os2->w2k
|
||||
*/
|
||||
static BOOL test_t2open(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
|
||||
{
|
||||
@ -468,15 +474,15 @@ static BOOL test_t2open(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
|
||||
{ OPENX_OPEN_FUNC_OPEN, True, NT_STATUS_OK },
|
||||
{ OPENX_OPEN_FUNC_OPEN, False, NT_STATUS_OBJECT_NAME_NOT_FOUND },
|
||||
{ OPENX_OPEN_FUNC_OPEN | OPENX_OPEN_FUNC_CREATE, True, NT_STATUS_OK },
|
||||
{ OPENX_OPEN_FUNC_OPEN | OPENX_OPEN_FUNC_CREATE, False, NT_STATUS_ACCESS_DENIED },
|
||||
{ OPENX_OPEN_FUNC_OPEN | OPENX_OPEN_FUNC_CREATE, False, NT_STATUS_OK },
|
||||
{ OPENX_OPEN_FUNC_FAIL, True, NT_STATUS_OBJECT_NAME_COLLISION },
|
||||
{ OPENX_OPEN_FUNC_FAIL, False, NT_STATUS_ACCESS_DENIED },
|
||||
{ OPENX_OPEN_FUNC_FAIL, False, NT_STATUS_OBJECT_NAME_COLLISION },
|
||||
{ OPENX_OPEN_FUNC_FAIL | OPENX_OPEN_FUNC_CREATE, True, NT_STATUS_OBJECT_NAME_COLLISION },
|
||||
{ OPENX_OPEN_FUNC_FAIL | OPENX_OPEN_FUNC_CREATE, False, NT_STATUS_ACCESS_DENIED },
|
||||
{ OPENX_OPEN_FUNC_TRUNC, True, NT_STATUS_ACCESS_DENIED },
|
||||
{ OPENX_OPEN_FUNC_TRUNC, False, NT_STATUS_OBJECT_NAME_NOT_FOUND },
|
||||
{ OPENX_OPEN_FUNC_TRUNC | OPENX_OPEN_FUNC_CREATE, True, NT_STATUS_ACCESS_DENIED },
|
||||
{ OPENX_OPEN_FUNC_TRUNC | OPENX_OPEN_FUNC_CREATE, False, NT_STATUS_ACCESS_DENIED },
|
||||
{ OPENX_OPEN_FUNC_FAIL | OPENX_OPEN_FUNC_CREATE, False, NT_STATUS_OBJECT_NAME_COLLISION },
|
||||
{ OPENX_OPEN_FUNC_TRUNC, True, NT_STATUS_OK },
|
||||
{ OPENX_OPEN_FUNC_TRUNC, False, NT_STATUS_OK },
|
||||
{ OPENX_OPEN_FUNC_TRUNC | OPENX_OPEN_FUNC_CREATE, True, NT_STATUS_OK },
|
||||
{ OPENX_OPEN_FUNC_TRUNC | OPENX_OPEN_FUNC_CREATE, False, NT_STATUS_OK },
|
||||
};
|
||||
|
||||
fnum = create_complex_file(cli, mem_ctx, fname1);
|
||||
@ -490,20 +496,26 @@ static BOOL test_t2open(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
|
||||
printf("Checking RAW_OPEN_T2OPEN\n");
|
||||
|
||||
io.t2open.level = RAW_OPEN_T2OPEN;
|
||||
io.t2open.in.flags = OPENX_FLAGS_ADDITIONAL_INFO |
|
||||
OPENX_FLAGS_EA_LEN | OPENX_FLAGS_EXTENDED_RETURN;
|
||||
io.t2open.in.flags = OPENX_FLAGS_ADDITIONAL_INFO;
|
||||
io.t2open.in.open_mode = OPENX_MODE_DENY_NONE | OPENX_MODE_ACCESS_RDWR;
|
||||
io.t2open.in.open_func = OPENX_OPEN_FUNC_OPEN | OPENX_OPEN_FUNC_CREATE;
|
||||
io.t2open.in.search_attrs = 0;
|
||||
io.t2open.in.file_attrs = 0;
|
||||
io.t2open.in.write_time = 0;
|
||||
io.t2open.in.size = 0;
|
||||
io.t2open.in.timeout = 0;
|
||||
|
||||
io.t2open.in.eas = talloc_p(mem_ctx, struct ea_struct);
|
||||
io.t2open.in.num_eas = 1;
|
||||
io.t2open.in.num_eas = 3;
|
||||
io.t2open.in.eas = talloc_array_p(mem_ctx, struct ea_struct, io.t2open.in.num_eas);
|
||||
io.t2open.in.eas[0].flags = 0;
|
||||
io.t2open.in.eas[0].name.s = "EAONE";
|
||||
io.t2open.in.eas[0].value = data_blob_talloc(mem_ctx, "1", 1);
|
||||
io.t2open.in.eas[0].name.s = ".CLASSINFO";
|
||||
io.t2open.in.eas[0].value = data_blob_talloc(mem_ctx, "first value", 11);
|
||||
io.t2open.in.eas[1].flags = 0;
|
||||
io.t2open.in.eas[1].name.s = "EA TWO";
|
||||
io.t2open.in.eas[1].value = data_blob_talloc(mem_ctx, "foo", 3);
|
||||
io.t2open.in.eas[2].flags = 0;
|
||||
io.t2open.in.eas[2].name.s = "X THIRD";
|
||||
io.t2open.in.eas[2].value = data_blob_talloc(mem_ctx, "xy", 2);
|
||||
|
||||
/* check all combinations of open_func */
|
||||
for (i=0; i<ARRAY_SIZE(open_funcs); i++) {
|
||||
@ -526,25 +538,35 @@ static BOOL test_t2open(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
|
||||
}
|
||||
|
||||
smbcli_unlink(cli->tree, fname1);
|
||||
smbcli_unlink(cli->tree, fname2);
|
||||
|
||||
/* check the basic return fields */
|
||||
fnum = create_complex_file(cli, mem_ctx, fname);
|
||||
smbcli_close(cli->tree, fnum);
|
||||
io.t2open.in.open_func = OPENX_OPEN_FUNC_OPEN | OPENX_OPEN_FUNC_CREATE;
|
||||
io.t2open.in.write_time = 0;
|
||||
io.t2open.in.fname = fname;
|
||||
status = smb_raw_open(cli->tree, mem_ctx, &io);
|
||||
CHECK_STATUS(status, NT_STATUS_OK);
|
||||
fnum = io.t2open.out.fnum;
|
||||
|
||||
CHECK_ALL_INFO(io.t2open.out.size, size);
|
||||
#if 0
|
||||
/* windows appears to leak uninitialised memory here */
|
||||
CHECK_VAL(io.t2open.out.write_time, 0);
|
||||
#endif
|
||||
CHECK_ALL_INFO(io.t2open.out.attrib, attrib & ~FILE_ATTRIBUTE_NONINDEXED);
|
||||
CHECK_VAL(io.t2open.out.access, OPENX_MODE_DENY_NONE | OPENX_MODE_ACCESS_RDWR);
|
||||
CHECK_VAL(io.t2open.out.ftype, 0);
|
||||
CHECK_VAL(io.t2open.out.devstate, 0);
|
||||
CHECK_VAL(io.t2open.out.action, OPENX_ACTION_EXISTED);
|
||||
CHECK_VAL(io.t2open.out.action, OPENX_ACTION_CREATED);
|
||||
smbcli_close(cli->tree, fnum);
|
||||
|
||||
status = torture_check_ea(cli, fname, ".CLASSINFO", "first value");
|
||||
CHECK_STATUS(status, NT_STATUS_OK);
|
||||
status = torture_check_ea(cli, fname, "EA TWO", "foo");
|
||||
CHECK_STATUS(status, NT_STATUS_OK);
|
||||
status = torture_check_ea(cli, fname, "X THIRD", "xy");
|
||||
CHECK_STATUS(status, NT_STATUS_OK);
|
||||
|
||||
/* now check the search attrib for hidden files - win2003 ignores this? */
|
||||
SET_ATTRIB(FILE_ATTRIBUTE_HIDDEN);
|
||||
CHECK_ALL_INFO(FILE_ATTRIBUTE_HIDDEN, attrib);
|
||||
@ -564,14 +586,15 @@ static BOOL test_t2open(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
|
||||
io.t2open.in.open_func = OPENX_OPEN_FUNC_FAIL | OPENX_OPEN_FUNC_CREATE;
|
||||
io.t2open.in.file_attrs = FILE_ATTRIBUTE_SYSTEM;
|
||||
status = smb_raw_open(cli->tree, mem_ctx, &io);
|
||||
CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
|
||||
CHECK_STATUS(status, NT_STATUS_OK);
|
||||
|
||||
/* check timeout on create - win2003 ignores the timeout! */
|
||||
io.t2open.in.open_func = OPENX_OPEN_FUNC_OPEN | OPENX_OPEN_FUNC_CREATE;
|
||||
io.t2open.in.file_attrs = 0;
|
||||
io.t2open.in.timeout = 20000;
|
||||
io.t2open.in.open_mode = OPENX_MODE_ACCESS_RDWR | OPENX_MODE_DENY_ALL;
|
||||
status = smb_raw_open(cli->tree, mem_ctx, &io);
|
||||
CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
|
||||
CHECK_STATUS(status, NT_STATUS_SHARING_VIOLATION);
|
||||
|
||||
done:
|
||||
smbcli_close(cli->tree, fnum);
|
||||
|
@ -1150,7 +1150,7 @@ static BOOL test_os2_delete(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
|
||||
}
|
||||
|
||||
if (i>0) {
|
||||
io2.t2fnext.in.resume_key = 0;
|
||||
io2.t2fnext.in.resume_key = result.list[i-1].ea_size.resume_key;
|
||||
io2.t2fnext.in.last_name = result.list[i-1].ea_size.name.s;
|
||||
}
|
||||
} while (NT_STATUS_IS_OK(status) && result.count != 0);
|
||||
|
@ -356,3 +356,59 @@ NTSTATUS torture_set_sparse(struct smbcli_tree *tree, int fnum)
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
check that an EA has the right value
|
||||
*/
|
||||
NTSTATUS torture_check_ea(struct smbcli_state *cli,
|
||||
const char *fname, const char *eaname, const char *value)
|
||||
{
|
||||
union smb_fileinfo info;
|
||||
NTSTATUS status;
|
||||
int i;
|
||||
TALLOC_CTX *mem_ctx = talloc(cli, 0);
|
||||
|
||||
info.all_eas.level = RAW_FILEINFO_ALL_EAS;
|
||||
info.all_eas.in.fname = fname;
|
||||
|
||||
status = smb_raw_pathinfo(cli->tree, mem_ctx, &info);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
talloc_free(mem_ctx);
|
||||
return status;
|
||||
}
|
||||
|
||||
for (i=0;i<info.all_eas.out.num_eas;i++) {
|
||||
if (StrCaseCmp(eaname, info.all_eas.out.eas[i].name.s) == 0) {
|
||||
if (value == NULL) {
|
||||
printf("attr '%s' should not be present\n", eaname);
|
||||
talloc_free(mem_ctx);
|
||||
return NT_STATUS_EA_CORRUPT_ERROR;
|
||||
}
|
||||
if (strlen(value) == info.all_eas.out.eas[i].value.length &&
|
||||
memcmp(value,
|
||||
info.all_eas.out.eas[i].value.data,
|
||||
info.all_eas.out.eas[i].value.length) == 0) {
|
||||
talloc_free(mem_ctx);
|
||||
return NT_STATUS_OK;
|
||||
} else {
|
||||
printf("attr '%s' has wrong value '%*.*s'\n",
|
||||
eaname,
|
||||
info.all_eas.out.eas[i].value.length,
|
||||
info.all_eas.out.eas[i].value.length,
|
||||
info.all_eas.out.eas[i].value.data);
|
||||
talloc_free(mem_ctx);
|
||||
return NT_STATUS_EA_CORRUPT_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
talloc_free(mem_ctx);
|
||||
|
||||
if (value != NULL) {
|
||||
printf("attr '%s' not found\n", eaname);
|
||||
return NT_STATUS_NONEXISTENT_EA_ENTRY;
|
||||
}
|
||||
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user