1
0
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:
Andrew Tridgell 2004-12-13 10:48:21 +00:00 committed by Gerald (Jerry) Carter
parent e08e2645de
commit fbd8c61ff7
11 changed files with 302 additions and 339 deletions

View File

@ -1133,6 +1133,7 @@ union smb_open {
struct { struct {
uint16_t flags; uint16_t flags;
uint16_t open_mode; uint16_t open_mode;
uint16_t search_attrs;
uint16_t file_attrs; uint16_t file_attrs;
time_t write_time; time_t write_time;
uint16_t open_func; uint16_t open_func;
@ -1152,7 +1153,7 @@ union smb_open {
uint16_t ftype; uint16_t ftype;
uint16_t devstate; uint16_t devstate;
uint16_t action; uint16_t action;
uint32_t unknown; uint32_t file_id;
} out; } out;
} t2open; } t2open;
@ -1161,7 +1162,7 @@ union smb_open {
enum smb_open_level level; enum smb_open_level level;
struct { struct {
uint16_t flags; uint16_t open_mode;
uint16_t search_attrs; uint16_t search_attrs;
const char *fname; const char *fname;
} in; } in;

View File

@ -51,7 +51,7 @@ struct smbcli_session *smbcli_session_init(struct smbcli_transport *transport)
capabilities = transport->negotiate.capabilities; capabilities = transport->negotiate.capabilities;
flags2 = FLAGS2_LONG_PATH_COMPONENTS; flags2 = FLAGS2_LONG_PATH_COMPONENTS | FLAGS2_EXTENDED_ATTRIBUTES;
if (capabilities & CAP_UNICODE) { if (capabilities & CAP_UNICODE) {
flags2 |= FLAGS2_UNICODE_STRINGS; flags2 |= FLAGS2_UNICODE_STRINGS;

View File

@ -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(0), parms->t2open.in.flags);
SSVAL(t2.in.params.data, VWV(1), parms->t2open.in.open_mode); 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); SSVAL(t2.in.params.data, VWV(3), parms->t2open.in.file_attrs);
raw_push_dos_date(tree->session->transport, 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); 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(7), parms->t2open.in.size);
SIVAL(t2.in.params.data, VWV(9), parms->t2open.in.timeout); 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); SSVAL(t2.in.params.data, VWV(13), 0);
smbcli_blob_append_string(tree->session, mem_ctx, smbcli_blob_append_string(tree->session, mem_ctx,
&t2.in.params, parms->t2open.in.fname, &t2.in.params, parms->t2open.in.fname,
STR_TERMINATE); STR_TERMINATE);
ea_put_list(t2.in.data.data, parms->t2open.in.num_eas, parms->t2open.in.eas); 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.ftype = SVAL(t2.out.params.data, VWV(7));
parms->t2open.out.devstate = SVAL(t2.out.params.data, VWV(8)); 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.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; 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: case RAW_OPEN_OPEN:
SETUP_REQUEST(SMBopen, 2, 0); 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); SSVAL(req->out.vwv, VWV(1), parms->openold.in.search_attrs);
smbcli_req_append_ascii4(req, parms->openold.in.fname, STR_TERMINATE); smbcli_req_append_ascii4(req, parms->openold.in.fname, STR_TERMINATE);
break; break;

View File

@ -150,13 +150,6 @@ static NTSTATUS ntvfs_map_open_finish(struct smbsrv_request *req,
union smb_setfileinfo *sf; union smb_setfileinfo *sf;
uint_t state; 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)) { if (!NT_STATUS_IS_OK(status)) {
return 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.attrib = io2->generic.out.attrib;
io->openold.out.write_time = nt_time_to_unix(io2->generic.out.write_time); 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.size = io2->generic.out.size;
io->openold.out.rmode = io->openold.in.flags; io->openold.out.rmode = io->openold.in.open_mode;
break; break;
case RAW_OPEN_OPENX: 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.attrib = io2->generic.out.attrib;
io->openx.out.write_time = nt_time_to_unix(io2->generic.out.write_time); 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.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.ftype = 0;
io->openx.out.devstate = 0; io->openx.out.devstate = 0;
io->openx.out.action = io2->generic.out.create_action; io->openx.out.action = io2->generic.out.create_action;
@ -190,15 +184,15 @@ static NTSTATUS ntvfs_map_open_finish(struct smbsrv_request *req,
break; break;
case RAW_OPEN_T2OPEN: case RAW_OPEN_T2OPEN:
io->t2open.out.fnum = io2->openx.out.fnum; io->t2open.out.fnum = io2->generic.out.fnum;
io->t2open.out.attrib = io2->openx.out.attrib; io->t2open.out.attrib = io2->generic.out.attrib;
io->t2open.out.write_time = 0; io->t2open.out.write_time = nt_time_to_unix(io2->generic.out.write_time);
io->t2open.out.size = io2->openx.out.size; io->t2open.out.size = io2->generic.out.size;
io->t2open.out.access = io->t2open.in.open_mode; io->t2open.out.access = io->t2open.in.open_mode;
io->t2open.out.ftype = io2->openx.out.ftype; io->t2open.out.ftype = 0;
io->t2open.out.devstate = io2->openx.out.devstate; io->t2open.out.devstate = 0;
io->t2open.out.action = io2->openx.out.action; io->t2open.out.action = io2->generic.out.create_action;
io->t2open.out.unknown = 0; io->t2open.out.file_id = 0;
break; break;
case RAW_OPEN_MKNEW: case RAW_OPEN_MKNEW:
@ -248,6 +242,106 @@ static NTSTATUS ntvfs_map_open_finish(struct smbsrv_request *req,
return NT_STATUS_OK; 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 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) { switch (io->generic.level) {
case RAW_OPEN_OPENX: case RAW_OPEN_OPENX:
if (io->openx.in.flags & OPENX_FLAGS_REQUEST_OPLOCK) { status = map_openx_open(io->openx.in.flags,
io2->generic.in.flags |= NTCREATEX_FLAGS_REQUEST_OPLOCK; io->openx.in.open_mode,
} io->openx.in.open_func,
if (io->openx.in.flags & OPENX_FLAGS_REQUEST_BATCH_OPLOCK) { io->openx.in.fname,
io2->generic.in.flags |= NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK; io2);
} if (!NT_STATUS_IS_OK(status)) {
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;
goto done; 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.file_attr = io->openx.in.file_attrs;
io2->generic.in.fname = io->openx.in.fname; 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: 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.file_attr = io->openold.in.search_attrs;
io2->generic.in.fname = io->openold.in.fname; 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); status = ntvfs->ops->openfile(ntvfs, req, io2);
break; break;
case RAW_OPEN_T2OPEN: case RAW_OPEN_T2OPEN:
io2->generic.level = RAW_OPEN_OPENX; io2->generic.level = RAW_OPEN_NTTRANS_CREATE;
io2->openx.in.flags = io->t2open.in.flags;
io2->openx.in.open_mode = io->t2open.in.open_mode; if (io->t2open.in.open_func == 0) {
io2->openx.in.search_attrs = 0; status = NT_STATUS_OBJECT_NAME_COLLISION;
io2->openx.in.file_attrs = io->t2open.in.file_attrs; goto done;
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; status = map_openx_open(io->t2open.in.flags,
io2->openx.in.timeout = io->t2open.in.timeout; io->t2open.in.open_mode,
io2->openx.in.fname = io->t2open.in.fname; 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); status = ntvfs->ops->openfile(ntvfs, req, io2);
break; break;
@ -508,7 +471,6 @@ NTSTATUS ntvfs_map_open(struct smbsrv_request *req, union smb_open *io,
status = NT_STATUS_INVALID_LEVEL; status = NT_STATUS_INVALID_LEVEL;
break; break;
} }
done: done:
return ntvfs_map_async_finish(req, status); return ntvfs_map_async_finish(req, status);
} }

View File

@ -794,38 +794,6 @@ static NTSTATUS pvfs_open_setup_retry(struct ntvfs_module_context *ntvfs,
return NT_STATUS_OK; 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 open a file
*/ */
@ -844,10 +812,6 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs,
uint32_t access_mask; uint32_t access_mask;
BOOL stream_existed; 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 /* use the generic mapping code to avoid implementing all the
different open calls. */ different open calls. */
if (io->generic.level != RAW_OPEN_GENERIC && if (io->generic.level != RAW_OPEN_GENERIC &&

View File

@ -430,7 +430,7 @@ void reply_open(struct smbsrv_request *req)
REQ_TALLOC(oi, sizeof(*oi)); REQ_TALLOC(oi, sizeof(*oi));
oi->openold.level = RAW_OPEN_OPEN; 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)); oi->openold.in.search_attrs = SVAL(req->in.vwv, VWV(1));
req_pull_ascii4(req, &oi->openold.in.fname, req->in.data, STR_TERMINATE); req_pull_ascii4(req, &oi->openold.in.fname, req->in.data, STR_TERMINATE);

View File

@ -1089,14 +1089,14 @@ static BOOL handler_open(int instance)
NTSTATUS status[NSERVERS]; NTSTATUS status[NSERVERS];
parm[0].openold.level = RAW_OPEN_OPEN; 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.search_attrs = gen_attrib();
parm[0].openold.in.fname = gen_fname_open(instance); parm[0].openold.in.fname = gen_fname_open(instance);
if (!options.use_oplocks) { if (!options.use_oplocks) {
/* mask out oplocks */ /* mask out oplocks */
parm[0].openold.in.flags &= ~(OPENX_FLAGS_REQUEST_OPLOCK| parm[0].openold.in.open_mode &= ~(OPENX_FLAGS_REQUEST_OPLOCK|
OPENX_FLAGS_REQUEST_BATCH_OPLOCK); OPENX_FLAGS_REQUEST_BATCH_OPLOCK);
} }
GEN_COPY_PARM; GEN_COPY_PARM;

View File

@ -34,55 +34,6 @@
goto done; \ goto done; \
}} while (0) }} 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) static DATA_BLOB data_blob_string_const(const char *str)
{ {
DATA_BLOB blob; DATA_BLOB blob;
@ -91,6 +42,12 @@ static DATA_BLOB data_blob_string_const(const char *str)
return blob; 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) 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); CHECK_STATUS(status, NT_STATUS_OK);
fnum = io.ntcreatex.out.fnum; 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"); printf("Adding first EA\n");
setfile.generic.level = RAW_SFILEINFO_EA_SET; 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); status = smb_raw_setfileinfo(cli->tree, &setfile);
CHECK_STATUS(status, NT_STATUS_OK); 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.name.s = "SECONDEA";
setfile.ea_set.in.ea.value = data_blob_string_const("ValueTwo"); 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); status = smb_raw_setfileinfo(cli->tree, &setfile);
CHECK_STATUS(status, NT_STATUS_OK); CHECK_STATUS(status, NT_STATUS_OK);
ret &= check_ea(cli, mem_ctx, fname, "EAONE", "VALUE1"); ret &= check_ea(cli, fname, "EAONE", "VALUE1");
ret &= check_ea(cli, mem_ctx, fname, "SECONDEA", "ValueTwo"); ret &= check_ea(cli, fname, "SECONDEA", "ValueTwo");
printf("Modifying 2nd EA\n"); printf("Modifying 2nd EA\n");
setfile.ea_set.in.ea.value = data_blob_string_const(" Changed Value"); setfile.ea_set.in.ea.value = data_blob_string_const(" Changed Value");
status = smb_raw_setfileinfo(cli->tree, &setfile); status = smb_raw_setfileinfo(cli->tree, &setfile);
CHECK_STATUS(status, NT_STATUS_OK); CHECK_STATUS(status, NT_STATUS_OK);
ret &= check_ea(cli, mem_ctx, fname, "EAONE", "VALUE1"); ret &= check_ea(cli, fname, "EAONE", "VALUE1");
ret &= check_ea(cli, mem_ctx, fname, "SECONDEA", " Changed Value"); ret &= check_ea(cli, fname, "SECONDEA", " Changed Value");
printf("Setting a NULL EA\n"); printf("Setting a NULL EA\n");
setfile.ea_set.in.ea.value = data_blob(NULL, 0); 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); status = smb_raw_setfileinfo(cli->tree, &setfile);
CHECK_STATUS(status, NT_STATUS_OK); CHECK_STATUS(status, NT_STATUS_OK);
ret &= check_ea(cli, mem_ctx, fname, "EAONE", "VALUE1"); ret &= check_ea(cli, fname, "EAONE", "VALUE1");
ret &= check_ea(cli, mem_ctx, fname, "SECONDEA", " Changed Value"); ret &= check_ea(cli, fname, "SECONDEA", " Changed Value");
ret &= check_ea(cli, mem_ctx, fname, "NULLEA", NULL); ret &= check_ea(cli, fname, "NULLEA", NULL);
printf("Deleting first EA\n"); printf("Deleting first EA\n");
setfile.ea_set.in.ea.flags = 0; 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); status = smb_raw_setfileinfo(cli->tree, &setfile);
CHECK_STATUS(status, NT_STATUS_OK); CHECK_STATUS(status, NT_STATUS_OK);
ret &= check_ea(cli, mem_ctx, fname, "EAONE", NULL); ret &= check_ea(cli, fname, "EAONE", NULL);
ret &= check_ea(cli, mem_ctx, fname, "SECONDEA", " Changed Value"); ret &= check_ea(cli, fname, "SECONDEA", " Changed Value");
printf("Deleting second EA\n"); printf("Deleting second EA\n");
setfile.ea_set.in.ea.flags = 0; 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); status = smb_raw_setfileinfo(cli->tree, &setfile);
CHECK_STATUS(status, NT_STATUS_OK); CHECK_STATUS(status, NT_STATUS_OK);
ret &= check_ea(cli, mem_ctx, fname, "EAONE", NULL); ret &= check_ea(cli, fname, "EAONE", NULL);
ret &= check_ea(cli, mem_ctx, fname, "SECONDEA", NULL); ret &= check_ea(cli, fname, "SECONDEA", NULL);
done: done:
smbcli_close(cli->tree, fnum); 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); CHECK_STATUS(status, NT_STATUS_OK);
fnum = io.ntcreatex.out.fnum; fnum = io.ntcreatex.out.fnum;
ret &= check_ea(cli, mem_ctx, fname, "EAONE", NULL); ret &= check_ea(cli, fname, "EAONE", NULL);
ret &= check_ea(cli, mem_ctx, fname, "1st EA", "Value One"); ret &= check_ea(cli, fname, "1st EA", "Value One");
ret &= check_ea(cli, mem_ctx, fname, "2nd EA", "Second Value"); ret &= check_ea(cli, fname, "2nd EA", "Second Value");
ret &= check_ea(cli, mem_ctx, fname, "and 3rd", "final value"); ret &= check_ea(cli, fname, "and 3rd", "final value");
smbcli_close(cli->tree, fnum); 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); CHECK_STATUS(status, NT_STATUS_OK);
fnum = io.ntcreatex.out.fnum; fnum = io.ntcreatex.out.fnum;
ret &= check_ea(cli, mem_ctx, fname, "1st EA", "Value One"); ret &= check_ea(cli, fname, "1st EA", "Value One");
ret &= check_ea(cli, mem_ctx, fname, "2nd EA", "Second Value"); ret &= check_ea(cli, fname, "2nd EA", "Second Value");
ret &= check_ea(cli, mem_ctx, fname, "and 3rd", "final value"); ret &= check_ea(cli, fname, "and 3rd", "final value");
ret &= check_ea(cli, mem_ctx, fname, "Fourth EA", NULL); ret &= check_ea(cli, fname, "Fourth EA", NULL);
done: done:
smbcli_close(cli->tree, fnum); smbcli_close(cli->tree, fnum);

View File

@ -160,7 +160,7 @@ static BOOL test_open(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
io.openold.level = RAW_OPEN_OPEN; io.openold.level = RAW_OPEN_OPEN;
io.openold.in.fname = fname; 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; io.openold.in.search_attrs = 0;
status = smb_raw_open(cli->tree, mem_ctx, &io); status = smb_raw_open(cli->tree, mem_ctx, &io);
CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND); 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.fname = fname;
io.openold.in.search_attrs = 0; 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); status = smb_raw_open(cli->tree, mem_ctx, &io);
CHECK_STATUS(status, NT_STATUS_OK); CHECK_STATUS(status, NT_STATUS_OK);
fnum = io.openold.out.fnum; fnum = io.openold.out.fnum;
CHECK_RDWR(fnum, RDWR_RDONLY); CHECK_RDWR(fnum, RDWR_RDONLY);
smbcli_close(cli->tree, fnum); 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); status = smb_raw_open(cli->tree, mem_ctx, &io);
CHECK_STATUS(status, NT_STATUS_OK); CHECK_STATUS(status, NT_STATUS_OK);
fnum = io.openold.out.fnum; fnum = io.openold.out.fnum;
CHECK_RDWR(fnum, RDWR_WRONLY); CHECK_RDWR(fnum, RDWR_WRONLY);
smbcli_close(cli->tree, fnum); 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); status = smb_raw_open(cli->tree, mem_ctx, &io);
CHECK_STATUS(status, NT_STATUS_OK); CHECK_STATUS(status, NT_STATUS_OK);
fnum = io.openold.out.fnum; 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); smbcli_close(cli->tree, fnum);
/* check the share modes roughly - not a complete matrix */ /* 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); status = smb_raw_open(cli->tree, mem_ctx, &io);
CHECK_STATUS(status, NT_STATUS_OK); CHECK_STATUS(status, NT_STATUS_OK);
fnum = io.openold.out.fnum; fnum = io.openold.out.fnum;
CHECK_RDWR(fnum, RDWR_RDWR); CHECK_RDWR(fnum, RDWR_RDWR);
if (io.openold.in.flags != io.openold.out.rmode) { if (io.openold.in.open_mode != io.openold.out.rmode) {
printf("(%s) rmode should equal flags - 0x%x 0x%x\n", printf("(%s) rmode should equal open_mode - 0x%x 0x%x\n",
__location__, io.openold.out.rmode, io.openold.in.flags); __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); status = smb_raw_open(cli->tree, mem_ctx, &io);
CHECK_STATUS(status, NT_STATUS_SHARING_VIOLATION); 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); status = smb_raw_open(cli->tree, mem_ctx, &io);
CHECK_STATUS(status, NT_STATUS_OK); CHECK_STATUS(status, NT_STATUS_OK);
fnum2 = io.openold.out.fnum; 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.level = RAW_OPEN_OPEN;
io.openold.in.fname = fname; io.openold.in.fname = fname;
io.openold.in.search_attrs = 0; 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); status = smb_raw_open(cli->tree, mem_ctx, &io);
CHECK_STATUS(status, NT_STATUS_OK); CHECK_STATUS(status, NT_STATUS_OK);
fnum = io.openold.out.fnum; 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); i, (int)open_funcs[i].with_file, (int)open_funcs[i].open_func);
ret = False; 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); smbcli_close(cli->tree, io.openx.out.fnum);
}
if (open_funcs[i].with_file) {
smbcli_unlink(cli->tree, fname); smbcli_unlink(cli->tree, fname);
} }
} }
smbcli_unlink(cli->tree, fname);
/* check the basic return fields */ /* check the basic return fields */
io.openx.in.open_func = OPENX_OPEN_FUNC_OPEN | OPENX_OPEN_FUNC_CREATE; io.openx.in.open_func = OPENX_OPEN_FUNC_OPEN | OPENX_OPEN_FUNC_CREATE;
status = smb_raw_open(cli->tree, mem_ctx, &io); 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); CHECK_VAL(io.openx.out.access_mask, SEC_STD_ALL);
smbcli_close(cli->tree, io.openx.out.fnum); 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: done:
smbcli_close(cli->tree, fnum); smbcli_close(cli->tree, fnum);
smbcli_unlink(cli->tree, fname); smbcli_unlink(cli->tree, fname);
@ -445,9 +453,7 @@ done:
/* /*
test RAW_OPEN_T2OPEN test RAW_OPEN_T2OPEN
I can't work out how to get win2003 to accept a create file via TRANS2_OPEN, which many thanks to kukks for a sniff showing how this works with os2->w2k
is why you see all the ACCESS_DENIED results below. When we finally work this out then this
test will make more sense
*/ */
static BOOL test_t2open(struct smbcli_state *cli, TALLOC_CTX *mem_ctx) 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, True, NT_STATUS_OK },
{ OPENX_OPEN_FUNC_OPEN, False, NT_STATUS_OBJECT_NAME_NOT_FOUND }, { 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, 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, 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, True, NT_STATUS_OBJECT_NAME_COLLISION },
{ OPENX_OPEN_FUNC_FAIL | 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_ACCESS_DENIED }, { OPENX_OPEN_FUNC_TRUNC, True, NT_STATUS_OK },
{ OPENX_OPEN_FUNC_TRUNC, False, NT_STATUS_OBJECT_NAME_NOT_FOUND }, { OPENX_OPEN_FUNC_TRUNC, False, NT_STATUS_OK },
{ OPENX_OPEN_FUNC_TRUNC | OPENX_OPEN_FUNC_CREATE, True, NT_STATUS_ACCESS_DENIED }, { OPENX_OPEN_FUNC_TRUNC | OPENX_OPEN_FUNC_CREATE, True, NT_STATUS_OK },
{ OPENX_OPEN_FUNC_TRUNC | OPENX_OPEN_FUNC_CREATE, False, NT_STATUS_ACCESS_DENIED }, { OPENX_OPEN_FUNC_TRUNC | OPENX_OPEN_FUNC_CREATE, False, NT_STATUS_OK },
}; };
fnum = create_complex_file(cli, mem_ctx, fname1); 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"); printf("Checking RAW_OPEN_T2OPEN\n");
io.t2open.level = RAW_OPEN_T2OPEN; io.t2open.level = RAW_OPEN_T2OPEN;
io.t2open.in.flags = OPENX_FLAGS_ADDITIONAL_INFO | io.t2open.in.flags = OPENX_FLAGS_ADDITIONAL_INFO;
OPENX_FLAGS_EA_LEN | OPENX_FLAGS_EXTENDED_RETURN;
io.t2open.in.open_mode = OPENX_MODE_DENY_NONE | OPENX_MODE_ACCESS_RDWR; 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.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.file_attrs = 0;
io.t2open.in.write_time = 0; io.t2open.in.write_time = 0;
io.t2open.in.size = 0; io.t2open.in.size = 0;
io.t2open.in.timeout = 0; io.t2open.in.timeout = 0;
io.t2open.in.eas = talloc_p(mem_ctx, struct ea_struct); io.t2open.in.num_eas = 3;
io.t2open.in.num_eas = 1; 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].flags = 0;
io.t2open.in.eas[0].name.s = "EAONE"; io.t2open.in.eas[0].name.s = ".CLASSINFO";
io.t2open.in.eas[0].value = data_blob_talloc(mem_ctx, "1", 1); 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 */ /* check all combinations of open_func */
for (i=0; i<ARRAY_SIZE(open_funcs); i++) { 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, fname1);
smbcli_unlink(cli->tree, fname2);
/* check the basic return fields */ /* 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.open_func = OPENX_OPEN_FUNC_OPEN | OPENX_OPEN_FUNC_CREATE;
io.t2open.in.write_time = 0;
io.t2open.in.fname = fname; io.t2open.in.fname = fname;
status = smb_raw_open(cli->tree, mem_ctx, &io); status = smb_raw_open(cli->tree, mem_ctx, &io);
CHECK_STATUS(status, NT_STATUS_OK); CHECK_STATUS(status, NT_STATUS_OK);
fnum = io.t2open.out.fnum; fnum = io.t2open.out.fnum;
CHECK_ALL_INFO(io.t2open.out.size, size); 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); CHECK_VAL(io.t2open.out.write_time, 0);
#endif
CHECK_ALL_INFO(io.t2open.out.attrib, attrib & ~FILE_ATTRIBUTE_NONINDEXED); 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.access, OPENX_MODE_DENY_NONE | OPENX_MODE_ACCESS_RDWR);
CHECK_VAL(io.t2open.out.ftype, 0); CHECK_VAL(io.t2open.out.ftype, 0);
CHECK_VAL(io.t2open.out.devstate, 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); 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? */ /* now check the search attrib for hidden files - win2003 ignores this? */
SET_ATTRIB(FILE_ATTRIBUTE_HIDDEN); SET_ATTRIB(FILE_ATTRIBUTE_HIDDEN);
CHECK_ALL_INFO(FILE_ATTRIBUTE_HIDDEN, attrib); 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.open_func = OPENX_OPEN_FUNC_FAIL | OPENX_OPEN_FUNC_CREATE;
io.t2open.in.file_attrs = FILE_ATTRIBUTE_SYSTEM; io.t2open.in.file_attrs = FILE_ATTRIBUTE_SYSTEM;
status = smb_raw_open(cli->tree, mem_ctx, &io); 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! */ /* check timeout on create - win2003 ignores the timeout! */
io.t2open.in.open_func = OPENX_OPEN_FUNC_OPEN | OPENX_OPEN_FUNC_CREATE; io.t2open.in.open_func = OPENX_OPEN_FUNC_OPEN | OPENX_OPEN_FUNC_CREATE;
io.t2open.in.file_attrs = 0; io.t2open.in.file_attrs = 0;
io.t2open.in.timeout = 20000;
io.t2open.in.open_mode = OPENX_MODE_ACCESS_RDWR | OPENX_MODE_DENY_ALL; io.t2open.in.open_mode = OPENX_MODE_ACCESS_RDWR | OPENX_MODE_DENY_ALL;
status = smb_raw_open(cli->tree, mem_ctx, &io); status = smb_raw_open(cli->tree, mem_ctx, &io);
CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED); CHECK_STATUS(status, NT_STATUS_SHARING_VIOLATION);
done: done:
smbcli_close(cli->tree, fnum); smbcli_close(cli->tree, fnum);

View File

@ -1150,7 +1150,7 @@ static BOOL test_os2_delete(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
} }
if (i>0) { 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; io2.t2fnext.in.last_name = result.list[i-1].ea_size.name.s;
} }
} while (NT_STATUS_IS_OK(status) && result.count != 0); } while (NT_STATUS_IS_OK(status) && result.count != 0);

View File

@ -356,3 +356,59 @@ NTSTATUS torture_set_sparse(struct smbcli_tree *tree, int fnum)
return status; 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;
}