From fbd8c61ff7a7c41d16c400ddb87ad290f4af167d Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 13 Dec 2004 10:48:21 +0000 Subject: 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) --- source4/include/smb_interfaces.h | 5 +- source4/libcli/raw/clisession.c | 2 +- source4/libcli/raw/rawfile.c | 12 +- source4/ntvfs/ntvfs_generic.c | 332 +++++++++++++++++---------------------- source4/ntvfs/posix/pvfs_open.c | 36 ----- source4/smb_server/reply.c | 2 +- source4/torture/gentest.c | 6 +- source4/torture/raw/eas.c | 97 ++++-------- source4/torture/raw/open.c | 89 +++++++---- source4/torture/raw/search.c | 2 +- source4/torture/torture_util.c | 56 +++++++ 11 files changed, 301 insertions(+), 338 deletions(-) diff --git a/source4/include/smb_interfaces.h b/source4/include/smb_interfaces.h index 4b767c8d70..4ba8ea3442 100644 --- a/source4/include/smb_interfaces.h +++ b/source4/include/smb_interfaces.h @@ -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; diff --git a/source4/libcli/raw/clisession.c b/source4/libcli/raw/clisession.c index 4f77145d4d..519f112ceb 100644 --- a/source4/libcli/raw/clisession.c +++ b/source4/libcli/raw/clisession.c @@ -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; diff --git a/source4/libcli/raw/rawfile.c b/source4/libcli/raw/rawfile.c index 028d8734e1..bfd96bd360 100644 --- a/source4/libcli/raw/rawfile.c +++ b/source4/libcli/raw/rawfile.c @@ -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; diff --git a/source4/ntvfs/ntvfs_generic.c b/source4/ntvfs/ntvfs_generic.c index 49de8944ff..407bd38f74 100644 --- a/source4/ntvfs/ntvfs_generic.c +++ b/source4/ntvfs/ntvfs_generic.c @@ -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; - 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; + 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; } - 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; + + status = ntvfs->ops->openfile(ntvfs, req, io2); + break; + + case RAW_OPEN_T2OPEN: + io2->generic.level = RAW_OPEN_NTTRANS_CREATE; + + if (io->t2open.in.open_func == 0) { + status = NT_STATUS_OBJECT_NAME_COLLISION; 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; + + 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; } - status = ntvfs->ops->openfile(ntvfs, req, io2); - break; + 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; - 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; 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); } diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index a53deda270..af0858f639 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -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 && diff --git a/source4/smb_server/reply.c b/source4/smb_server/reply.c index 9fba5063b8..91423b05f8 100644 --- a/source4/smb_server/reply.c +++ b/source4/smb_server/reply.c @@ -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); diff --git a/source4/torture/gentest.c b/source4/torture/gentest.c index e49267e162..6c2f9d37fa 100644 --- a/source4/torture/gentest.c +++ b/source4/torture/gentest.c @@ -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; diff --git a/source4/torture/raw/eas.c b/source4/torture/raw/eas.c index 044fe9ebb4..00c2fac74a 100644 --- a/source4/torture/raw/eas.c +++ b/source4/torture/raw/eas.c @@ -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;itree, &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); diff --git a/source4/torture/raw/open.c b/source4/torture/raw/open.c index a1cc76ebd8..f3d5daeade 100644 --- a/source4/torture/raw/open.c +++ b/source4/torture/raw/open.c @@ -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; itree, 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); diff --git a/source4/torture/raw/search.c b/source4/torture/raw/search.c index f159c4e154..395b9ff559 100644 --- a/source4/torture/raw/search.c +++ b/source4/torture/raw/search.c @@ -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); diff --git a/source4/torture/torture_util.c b/source4/torture/torture_util.c index 6370086838..05b06c6d0e 100644 --- a/source4/torture/torture_util.c +++ b/source4/torture/torture_util.c @@ -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