From 7a9ffeca21666935ba08cd909b63fc063f7607f7 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 22 May 2008 17:53:50 +1000 Subject: check for invalid file attribute values in create (This used to be commit dd21e3d9d788a67d4673625ed4892a875f4600dc) --- source4/ntvfs/posix/pvfs_open.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source4/ntvfs') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 67937324cc..cc4f0add27 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -548,6 +548,10 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, uint32_t oplock_level = OPLOCK_NONE, oplock_granted; bool allow_level_II_oplock = false; + if (io->ntcreatex.in.file_attr & ~FILE_ATTRIBUTE_ALL_MASK) { + return NT_STATUS_INVALID_PARAMETER; + } + if ((io->ntcreatex.in.file_attr & FILE_ATTRIBUTE_READONLY) && (create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE)) { return NT_STATUS_CANNOT_DELETE; -- cgit From ac185ae0c5bca7fdf82e90a7d925c77e9cbe1888 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 22 May 2008 23:00:08 +1000 Subject: fixes for EAs and filename in gentest_smb2 results - SMB2 returns 0 for a null EA - return the share qualified name for the filename in SMB2 ALL_INFO level (This used to be commit f9708184a2037f83ebb97c847414326a42436154) --- source4/ntvfs/posix/pvfs_qfileinfo.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'source4/ntvfs') diff --git a/source4/ntvfs/posix/pvfs_qfileinfo.c b/source4/ntvfs/posix/pvfs_qfileinfo.c index 6bc21e5e3e..102660a0bf 100644 --- a/source4/ntvfs/posix/pvfs_qfileinfo.c +++ b/source4/ntvfs/posix/pvfs_qfileinfo.c @@ -298,10 +298,21 @@ static NTSTATUS pvfs_map_fileinfo(struct pvfs_state *pvfs, (name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY)? 1 : 0; info->all_info2.out.file_id = name->dos.file_id; info->all_info2.out.ea_size = name->dos.ea_size; + if (info->all_info2.out.ea_size == 4) { + /* SMB2 uses zero for a empty EA set */ + info->all_info2.out.ea_size = 0; + } info->all_info2.out.access_mask = 0; /* only set by qfileinfo */ info->all_info2.out.position = 0; /* only set by qfileinfo */ info->all_info2.out.mode = 0; /* only set by qfileinfo */ - info->all_info2.out.fname.s = name->original_name; + /* windows wants the full path on disk for this + result, but I really don't want to expose that on + the wire, so I'll give the path with a share + prefix, which is a good approximation */ + info->all_info2.out.fname.s = talloc_asprintf(req, "\\%s\\%s", + pvfs->share_name, + name->original_name); + NT_STATUS_HAVE_NO_MEMORY(info->all_info2.out.fname.s); return NT_STATUS_OK; } -- cgit From 2e0f61a18ab002a90faa06477fa258e36b8a5fc0 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 22 May 2008 23:07:16 +1000 Subject: SMB2 read returns NT_STATUS_END_OF_FILE on read past end of file (This used to be commit 1590494daf5abe43e43402e7602f92267bcda34b) --- source4/ntvfs/ntvfs_generic.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'source4/ntvfs') diff --git a/source4/ntvfs/ntvfs_generic.c b/source4/ntvfs/ntvfs_generic.c index a706e621c9..62a1427405 100644 --- a/source4/ntvfs/ntvfs_generic.c +++ b/source4/ntvfs/ntvfs_generic.c @@ -1276,6 +1276,11 @@ static NTSTATUS ntvfs_map_read_finish(struct ntvfs_module_context *ntvfs, rd->smb2.out.data.length= rd2->generic.out.nread; rd->smb2.out.remaining = 0; rd->smb2.out.reserved = 0; + if (NT_STATUS_IS_OK(status) && + rd->smb2.out.data.length == 0 && + rd->smb2.in.length != 0) { + status = NT_STATUS_END_OF_FILE; + } break; default: return NT_STATUS_INVALID_LEVEL; -- cgit From ec7a6ee8ab25f4550a68b286d9eba32b955a73a1 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 23 May 2008 00:07:12 +1000 Subject: fix make test for EAs again - go back to 4 byte alignment until I work out the rules that Vista wants more exactly - add the zero sized EA handling for SMB2 more generically (This used to be commit 326b69bc8064cbea357864cecd6bd27b50c57184) --- source4/ntvfs/posix/pvfs_fileinfo.c | 5 +++++ source4/ntvfs/posix/pvfs_qfileinfo.c | 4 ---- 2 files changed, 5 insertions(+), 4 deletions(-) (limited to 'source4/ntvfs') diff --git a/source4/ntvfs/posix/pvfs_fileinfo.c b/source4/ntvfs/posix/pvfs_fileinfo.c index 4c383ed45d..e35f42e955 100644 --- a/source4/ntvfs/posix/pvfs_fileinfo.c +++ b/source4/ntvfs/posix/pvfs_fileinfo.c @@ -75,6 +75,11 @@ NTSTATUS pvfs_fill_dos_info(struct pvfs_state *pvfs, struct pvfs_filename *name, name->dos.alloc_size = pvfs_round_alloc_size(pvfs, name->st.st_size); name->dos.nlink = name->st.st_nlink; name->dos.ea_size = 4; + if (pvfs->ntvfs->ctx->protocol == PROTOCOL_SMB2) { + /* SMB2 represents a null EA with zero bytes */ + name->dos.ea_size = 0; + } + name->dos.file_id = (((uint64_t)name->st.st_dev)<<32) | name->st.st_ino; name->dos.flags = 0; diff --git a/source4/ntvfs/posix/pvfs_qfileinfo.c b/source4/ntvfs/posix/pvfs_qfileinfo.c index 102660a0bf..6e3092b744 100644 --- a/source4/ntvfs/posix/pvfs_qfileinfo.c +++ b/source4/ntvfs/posix/pvfs_qfileinfo.c @@ -298,10 +298,6 @@ static NTSTATUS pvfs_map_fileinfo(struct pvfs_state *pvfs, (name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY)? 1 : 0; info->all_info2.out.file_id = name->dos.file_id; info->all_info2.out.ea_size = name->dos.ea_size; - if (info->all_info2.out.ea_size == 4) { - /* SMB2 uses zero for a empty EA set */ - info->all_info2.out.ea_size = 0; - } info->all_info2.out.access_mask = 0; /* only set by qfileinfo */ info->all_info2.out.position = 0; /* only set by qfileinfo */ info->all_info2.out.mode = 0; /* only set by qfileinfo */ -- cgit From c78bf3c2c925060df3362625bbd1c3e96751c087 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 23 May 2008 09:45:46 +0200 Subject: pvfs_streams: directories don't have streams metze (This used to be commit 9ed7bb5afe6a73206bcba85f25305eb6630a5571) --- source4/ntvfs/posix/pvfs_streams.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'source4/ntvfs') diff --git a/source4/ntvfs/posix/pvfs_streams.c b/source4/ntvfs/posix/pvfs_streams.c index 7e6173ef2f..3cd9952fd5 100644 --- a/source4/ntvfs/posix/pvfs_streams.c +++ b/source4/ntvfs/posix/pvfs_streams.c @@ -36,6 +36,13 @@ NTSTATUS pvfs_stream_information(struct pvfs_state *pvfs, int i; NTSTATUS status; + /* directories don't have streams */ + if (name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY) { + info->num_streams = 0; + info->streams = NULL; + return NT_STATUS_OK; + } + streams = talloc(mem_ctx, struct xattr_DosStreams); if (streams == NULL) { return NT_STATUS_NO_MEMORY; -- cgit From 391b746430ad3d0b371930933e0a77e6a70a9ac0 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 23 May 2008 09:46:50 +0200 Subject: pvfs_resolve: stream_name = "" is only the same as NULL for files metze (This used to be commit 47756129fdf01075bac06cdd24107d7dc8ba34af) --- source4/ntvfs/posix/pvfs_fileinfo.c | 2 ++ source4/ntvfs/posix/pvfs_resolve.c | 8 +++++++- 2 files changed, 9 insertions(+), 1 deletion(-) (limited to 'source4/ntvfs') diff --git a/source4/ntvfs/posix/pvfs_fileinfo.c b/source4/ntvfs/posix/pvfs_fileinfo.c index e35f42e955..04f6ad78d0 100644 --- a/source4/ntvfs/posix/pvfs_fileinfo.c +++ b/source4/ntvfs/posix/pvfs_fileinfo.c @@ -58,6 +58,8 @@ NTSTATUS pvfs_fill_dos_info(struct pvfs_state *pvfs, struct pvfs_filename *name, if (S_ISDIR(name->st.st_mode)) { name->st.st_size = 0; name->st.st_nlink = 1; + } else if (name->stream_id == 0) { + name->stream_name = NULL; } /* for now just use the simple samba mapping */ diff --git a/source4/ntvfs/posix/pvfs_resolve.c b/source4/ntvfs/posix/pvfs_resolve.c index 325bc74f8f..2e97925c49 100644 --- a/source4/ntvfs/posix/pvfs_resolve.c +++ b/source4/ntvfs/posix/pvfs_resolve.c @@ -202,7 +202,13 @@ static NTSTATUS parse_stream_name(struct pvfs_filename *name, const char *s) } *p = 0; if (strcmp(name->stream_name, "") == 0) { - name->stream_name = NULL; + /* + * we don't set stream_name to NULL, here + * as this would be wrong for directories + * + * pvfs_fill_dos_info() will set it to NULL + * if it's not a directory. + */ name->stream_id = 0; } else { name->stream_id = pvfs_name_hash(name->stream_name, -- cgit From 5d648b4aa5540e91fa7ea77668965eefd8926b1a Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 23 May 2008 09:47:59 +0200 Subject: pvfs_open: return FILE_IS_A_DIRECTORY when opening a stream on a directory metze (This used to be commit 1421b1cc0c442be839be702647009ed5295f34a3) --- source4/ntvfs/posix/pvfs_open.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'source4/ntvfs') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index cc4f0add27..926c99d37e 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -182,12 +182,19 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, bool del_on_close; uint32_t create_options; uint32_t share_access; + bool forced; create_options = io->generic.in.create_options; share_access = io->generic.in.share_access; + forced = (io->generic.in.create_options & NTCREATEX_OPTIONS_DIRECTORY)?true:false; + if (name->stream_name) { - return NT_STATUS_NOT_A_DIRECTORY; + if (forced) { + return NT_STATUS_NOT_A_DIRECTORY; + } else { + return NT_STATUS_FILE_IS_A_DIRECTORY; + } } /* if the client says it must be a directory, and it isn't, -- cgit From c5c1b3706af13fe729f435e7bf4ec1e73b719eef Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 26 May 2008 14:59:58 +1000 Subject: allow larger streams using the TDB backend (This used to be commit 8c0d756eb887477da867e069dbde3a7ad98d4ae0) --- source4/ntvfs/posix/pvfs_streams.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'source4/ntvfs') diff --git a/source4/ntvfs/posix/pvfs_streams.c b/source4/ntvfs/posix/pvfs_streams.c index 3cd9952fd5..30d7ce2477 100644 --- a/source4/ntvfs/posix/pvfs_streams.c +++ b/source4/ntvfs/posix/pvfs_streams.c @@ -276,9 +276,12 @@ ssize_t pvfs_stream_write(struct pvfs_state *pvfs, if (count == 0) { return 0; } - if (offset > XATTR_MAX_STREAM_SIZE) { - errno = ENOSPC; - return -1; + + if (count+offset > XATTR_MAX_STREAM_SIZE) { + if (!pvfs->ea_db || count+offset > XATTR_MAX_STREAM_SIZE_TDB) { + errno = ENOSPC; + return -1; + } } /* we have to load the existing stream, then modify, then save */ @@ -332,7 +335,9 @@ NTSTATUS pvfs_stream_truncate(struct pvfs_state *pvfs, DATA_BLOB blob; if (length > XATTR_MAX_STREAM_SIZE) { - return NT_STATUS_DISK_FULL; + if (!pvfs->ea_db || length > XATTR_MAX_STREAM_SIZE_TDB) { + return NT_STATUS_DISK_FULL; + } } /* we have to load the existing stream, then modify, then save */ -- cgit From bf8d9e180e1e908e891e3755bbb70eab550f0638 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 26 May 2008 15:00:27 +1000 Subject: fill in reserved field on SMB2 flush (This used to be commit 400a3b39d5c151cf43e307af2fa702208d7cd472) --- source4/ntvfs/posix/pvfs_flush.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source4/ntvfs') diff --git a/source4/ntvfs/posix/pvfs_flush.c b/source4/ntvfs/posix/pvfs_flush.c index 61e73cedba..6e09c1f34a 100644 --- a/source4/ntvfs/posix/pvfs_flush.c +++ b/source4/ntvfs/posix/pvfs_flush.c @@ -54,6 +54,7 @@ NTSTATUS pvfs_flush(struct ntvfs_module_context *ntvfs, return NT_STATUS_INVALID_HANDLE; } pvfs_flush_file(pvfs, f); + io->smb2.out.reserved = 0; return NT_STATUS_OK; case RAW_FLUSH_ALL: -- cgit From 2ad2bdda89c07c0b8ce754c3b0cd4664eefc697d Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 26 May 2008 15:02:43 +1000 Subject: stricter checks for valid inputs in SMB2 open and lock (This used to be commit a7b5689a73adde59de28770aa3949660441291ea) --- source4/ntvfs/ntvfs_generic.c | 18 ++++++++++++++++-- source4/ntvfs/posix/pvfs_open.c | 38 +++++++++++++++++++++++++++----------- 2 files changed, 43 insertions(+), 13 deletions(-) (limited to 'source4/ntvfs') diff --git a/source4/ntvfs/ntvfs_generic.c b/source4/ntvfs/ntvfs_generic.c index 62a1427405..9b4f235cde 100644 --- a/source4/ntvfs/ntvfs_generic.c +++ b/source4/ntvfs/ntvfs_generic.c @@ -522,6 +522,12 @@ NTSTATUS ntvfs_map_open(struct ntvfs_module_context *ntvfs, io2->generic.in.fname = io->smb2.in.fname; io2->generic.in.sec_desc = NULL; io2->generic.in.ea_list = NULL; + + /* we use a couple of bits of the create options internally */ + if (io2->generic.in.create_options & NTCREATEX_OPTIONS_PRIVATE_MASK) { + return NT_STATUS_INVALID_PARAMETER; + } + status = ntvfs->ops->open(ntvfs, req, io2); break; @@ -1031,6 +1037,9 @@ NTSTATUS ntvfs_map_lock(struct ntvfs_module_context *ntvfs, return NT_STATUS_NO_MEMORY; } for (i=0;ismb2.in.lock_count;i++) { + if (lck->smb2.in.locks[i].flags & ~SMB2_LOCK_FLAG_ALL_MASK) { + return NT_STATUS_INVALID_PARAMETER; + } if (lck->smb2.in.locks[i].flags & SMB2_LOCK_FLAG_UNLOCK) { int j = lck2->generic.in.ulock_cnt; lck2->generic.in.ulock_cnt++; @@ -1277,10 +1286,15 @@ static NTSTATUS ntvfs_map_read_finish(struct ntvfs_module_context *ntvfs, rd->smb2.out.remaining = 0; rd->smb2.out.reserved = 0; if (NT_STATUS_IS_OK(status) && - rd->smb2.out.data.length == 0 && - rd->smb2.in.length != 0) { + rd->smb2.out.data.length == 0) { status = NT_STATUS_END_OF_FILE; } + /* SMB2 does honor the min_count field, SMB does not */ + if (NT_STATUS_IS_OK(status) && + rd->smb2.in.min_count > rd->smb2.out.data.length) { + rd->smb2.out.data.length = 0; + status = NT_STATUS_END_OF_FILE; + } break; default: return NT_STATUS_INVALID_LEVEL; diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 926c99d37e..59b42fe751 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -203,6 +203,13 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, return NT_STATUS_NOT_A_DIRECTORY; } + /* found with gentest */ + if (io->ntcreatex.in.access_mask == SEC_FLAG_MAXIMUM_ALLOWED && + (io->ntcreatex.in.create_options & NTCREATEX_OPTIONS_DIRECTORY) && + (io->ntcreatex.in.create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE)) { + return NT_STATUS_INVALID_PARAMETER; + } + switch (io->generic.in.open_disposition) { case NTCREATEX_DISP_OPEN_IF: break; @@ -563,7 +570,7 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, (create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE)) { return NT_STATUS_CANNOT_DELETE; } - + status = pvfs_access_check_create(pvfs, req, name, &access_mask); NT_STATUS_NOT_OK_RETURN(status); @@ -1121,6 +1128,25 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, return ntvfs_map_open(ntvfs, req, io); } + create_options = io->generic.in.create_options; + share_access = io->generic.in.share_access; + access_mask = io->generic.in.access_mask; + + if (share_access & ~NTCREATEX_SHARE_ACCESS_MASK) { + return NT_STATUS_INVALID_PARAMETER; + } + + /* some create options are not supported */ + if (create_options & NTCREATEX_OPTIONS_NOT_SUPPORTED_MASK) { + return NT_STATUS_NOT_SUPPORTED; + } + + /* other create options are not allowed */ + if ((create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE) && + !(access_mask & SEC_STD_DELETE)) { + return NT_STATUS_INVALID_PARAMETER; + } + /* resolve the cifs name to a posix name */ status = pvfs_resolve_name(pvfs, req, io->ntcreatex.in.fname, PVFS_RESOLVE_STREAMS, &name); @@ -1152,16 +1178,6 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, open doesn't match */ io->generic.in.file_attr &= ~FILE_ATTRIBUTE_DIRECTORY; - create_options = io->generic.in.create_options; - share_access = io->generic.in.share_access; - access_mask = io->generic.in.access_mask; - - /* certain create options are not allowed */ - if ((create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE) && - !(access_mask & SEC_STD_DELETE)) { - return NT_STATUS_INVALID_PARAMETER; - } - flags = 0; switch (io->generic.in.open_disposition) { -- cgit From 506849f6008386dad5baa287e7e81a73af031622 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 27 May 2008 12:42:43 +1000 Subject: check invalid create options in the right order (This used to be commit 73dbfb9b4148dbfdc30518c08db4658d189f4160) --- source4/ntvfs/ntvfs_generic.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'source4/ntvfs') diff --git a/source4/ntvfs/ntvfs_generic.c b/source4/ntvfs/ntvfs_generic.c index 9b4f235cde..c5b88da3d1 100644 --- a/source4/ntvfs/ntvfs_generic.c +++ b/source4/ntvfs/ntvfs_generic.c @@ -523,9 +523,16 @@ NTSTATUS ntvfs_map_open(struct ntvfs_module_context *ntvfs, io2->generic.in.sec_desc = NULL; io2->generic.in.ea_list = NULL; + /* we need to check these bits before we check the private mask */ + if (io2->generic.in.create_options & NTCREATEX_OPTIONS_NOT_SUPPORTED_MASK) { + status = NT_STATUS_NOT_SUPPORTED; + break; + } + /* we use a couple of bits of the create options internally */ if (io2->generic.in.create_options & NTCREATEX_OPTIONS_PRIVATE_MASK) { - return NT_STATUS_INVALID_PARAMETER; + status = NT_STATUS_INVALID_PARAMETER; + break; } status = ntvfs->ops->open(ntvfs, req, io2); -- cgit From 9a37e7ed93dabd1880513d10afc1135049f1fb4a Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 27 May 2008 14:06:51 +1000 Subject: Vista returns ACCESS_DENIED here (This used to be commit f5068c6e50215f6ea7108d58d783394a315ff14f) --- source4/ntvfs/posix/pvfs_acl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/ntvfs') diff --git a/source4/ntvfs/posix/pvfs_acl.c b/source4/ntvfs/posix/pvfs_acl.c index f1e469f790..507c22f050 100644 --- a/source4/ntvfs/posix/pvfs_acl.c +++ b/source4/ntvfs/posix/pvfs_acl.c @@ -457,7 +457,7 @@ NTSTATUS pvfs_access_check_unix(struct pvfs_state *pvfs, } if (uid != 0 && (*access_mask & SEC_FLAG_SYSTEM_SECURITY)) { - return NT_STATUS_PRIVILEGE_NOT_HELD; + return NT_STATUS_ACCESS_DENIED; } if (*access_mask & ~max_bits) { -- cgit From f0b4b15f64259fcdb18f21657434f592bb2f157e Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 27 May 2008 14:07:11 +1000 Subject: check for some more invalid bits in smb2 create (This used to be commit dcdaa9f5fd9150b16fb277213e864e5c39d831d6) --- source4/ntvfs/posix/pvfs_open.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'source4/ntvfs') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 59b42fe751..328f064a57 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -1147,6 +1147,15 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, return NT_STATUS_INVALID_PARAMETER; } + if (access_mask & (SEC_MASK_INVALID | SEC_STD_SYNCHRONIZE)) { + return NT_STATUS_ACCESS_DENIED; + } + + if (io->ntcreatex.in.file_attr & (FILE_ATTRIBUTE_DEVICE| + FILE_ATTRIBUTE_VOLUME)) { + return NT_STATUS_INVALID_PARAMETER; + } + /* resolve the cifs name to a posix name */ status = pvfs_resolve_name(pvfs, req, io->ntcreatex.in.fname, PVFS_RESOLVE_STREAMS, &name); -- cgit From 6e265867ff8869254820e8af954c8f1316b05d39 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 27 May 2008 14:30:42 +1000 Subject: SEC_STD_SYNCHRONIZE is only invalid on SMB2 (This used to be commit 067f1271adaa13d537bbc92b19fe8d633cbaaf50) --- source4/ntvfs/posix/pvfs_open.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'source4/ntvfs') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 328f064a57..739c127b98 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -565,6 +565,10 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, if (io->ntcreatex.in.file_attr & ~FILE_ATTRIBUTE_ALL_MASK) { return NT_STATUS_INVALID_PARAMETER; } + + if (io->ntcreatex.in.file_attr & FILE_ATTRIBUTE_ENCRYPTED) { + return NT_STATUS_ACCESS_DENIED; + } if ((io->ntcreatex.in.file_attr & FILE_ATTRIBUTE_READONLY) && (create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE)) { @@ -1147,7 +1151,12 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, return NT_STATUS_INVALID_PARAMETER; } - if (access_mask & (SEC_MASK_INVALID | SEC_STD_SYNCHRONIZE)) { + if (access_mask & SEC_MASK_INVALID) { + return NT_STATUS_ACCESS_DENIED; + } + + if (req->ctx->protocol == PROTOCOL_SMB2 && + (access_mask & SEC_STD_SYNCHRONIZE)) { return NT_STATUS_ACCESS_DENIED; } -- cgit From 65e31a965ee6514610ec0d4ca52a5cd8772c5254 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 27 May 2008 14:59:55 +1000 Subject: make the SEC_STD_SYNCHRONIZE test more specific (This used to be commit 8c263f91bda97eb910c8589b6cd987ec4a62d770) --- source4/ntvfs/posix/pvfs_open.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'source4/ntvfs') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 739c127b98..cfa88b6baa 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -1155,13 +1155,16 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, return NT_STATUS_ACCESS_DENIED; } + /* what does this bit really mean?? */ if (req->ctx->protocol == PROTOCOL_SMB2 && - (access_mask & SEC_STD_SYNCHRONIZE)) { + (access_mask & SEC_STD_SYNCHRONIZE) && + !(access_mask & SEC_STD_READ_CONTROL)) { return NT_STATUS_ACCESS_DENIED; } if (io->ntcreatex.in.file_attr & (FILE_ATTRIBUTE_DEVICE| - FILE_ATTRIBUTE_VOLUME)) { + FILE_ATTRIBUTE_VOLUME| + (~FILE_ATTRIBUTE_ALL_MASK))) { return NT_STATUS_INVALID_PARAMETER; } -- cgit From cf274201b4e987faa822a137bb67fa191dabc5e8 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 27 May 2008 15:27:25 +1000 Subject: disable the SEC_STD_SYNCHRONIZE test until we know what it means (This used to be commit 897f4582bee72e319874e8a2d064ba442415571d) --- source4/ntvfs/posix/pvfs_open.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source4/ntvfs') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index cfa88b6baa..adcdeb1f2b 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -1155,12 +1155,14 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, return NT_STATUS_ACCESS_DENIED; } +#if 0 /* what does this bit really mean?? */ if (req->ctx->protocol == PROTOCOL_SMB2 && (access_mask & SEC_STD_SYNCHRONIZE) && !(access_mask & SEC_STD_READ_CONTROL)) { return NT_STATUS_ACCESS_DENIED; } +#endif if (io->ntcreatex.in.file_attr & (FILE_ATTRIBUTE_DEVICE| FILE_ATTRIBUTE_VOLUME| -- cgit From 848e7c5830a869d86d7fe236acc1e6a1949252d3 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 27 May 2008 16:02:10 +1000 Subject: it seems that lock flags are only validated when UNLOCK is set (This used to be commit d1bde5830cd56042236d72598e5cfe9c7abc4c47) --- source4/ntvfs/ntvfs_generic.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'source4/ntvfs') diff --git a/source4/ntvfs/ntvfs_generic.c b/source4/ntvfs/ntvfs_generic.c index c5b88da3d1..e449e61b34 100644 --- a/source4/ntvfs/ntvfs_generic.c +++ b/source4/ntvfs/ntvfs_generic.c @@ -1044,11 +1044,12 @@ NTSTATUS ntvfs_map_lock(struct ntvfs_module_context *ntvfs, return NT_STATUS_NO_MEMORY; } for (i=0;ismb2.in.lock_count;i++) { - if (lck->smb2.in.locks[i].flags & ~SMB2_LOCK_FLAG_ALL_MASK) { - return NT_STATUS_INVALID_PARAMETER; - } if (lck->smb2.in.locks[i].flags & SMB2_LOCK_FLAG_UNLOCK) { int j = lck2->generic.in.ulock_cnt; + if (lck->smb2.in.locks[i].flags & + (SMB2_LOCK_FLAG_SHARED|SMB2_LOCK_FLAG_EXCLUSIVE)) { + return NT_STATUS_INVALID_PARAMETER; + } lck2->generic.in.ulock_cnt++; lck2->generic.in.locks[j].pid = 0; lck2->generic.in.locks[j].offset = lck->smb2.in.locks[i].offset; -- cgit From 46e64417a3b14d1c33ca7e97080c64f8e67efec2 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 27 May 2008 16:02:27 +1000 Subject: another attempt at the damn SEC_STD_SYNCHRONIZE flag (This used to be commit 2ac27bfffa557d6c0f71c443b43a8d1967edb177) --- source4/ntvfs/posix/pvfs_open.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'source4/ntvfs') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index adcdeb1f2b..908dd449af 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -1155,14 +1155,11 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, return NT_STATUS_ACCESS_DENIED; } -#if 0 /* what does this bit really mean?? */ if (req->ctx->protocol == PROTOCOL_SMB2 && - (access_mask & SEC_STD_SYNCHRONIZE) && - !(access_mask & SEC_STD_READ_CONTROL)) { + access_mask == SEC_STD_SYNCHRONIZE) { return NT_STATUS_ACCESS_DENIED; } -#endif if (io->ntcreatex.in.file_attr & (FILE_ATTRIBUTE_DEVICE| FILE_ATTRIBUTE_VOLUME| -- cgit From cb36437db2d75e7facc91cf0089f2caa20bf0ca0 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 27 May 2008 16:43:36 +1000 Subject: added support for the output fields of SMB2 close (This used to be commit 2633bc749792c224acc73a2e4ca723404331c19c) --- source4/ntvfs/cifs/vfs_cifs.c | 10 +++++++ source4/ntvfs/ntvfs_generic.c | 63 +++++++++++++++++++++++++++++++++-------- source4/ntvfs/posix/pvfs_open.c | 29 +++++++++++++++++-- 3 files changed, 87 insertions(+), 15 deletions(-) (limited to 'source4/ntvfs') diff --git a/source4/ntvfs/cifs/vfs_cifs.c b/source4/ntvfs/cifs/vfs_cifs.c index 2b61268733..844fa11cc5 100644 --- a/source4/ntvfs/cifs/vfs_cifs.c +++ b/source4/ntvfs/cifs/vfs_cifs.c @@ -769,6 +769,7 @@ static NTSTATUS cvfs_close(struct ntvfs_module_context *ntvfs, struct cvfs_private *private = ntvfs->private_data; struct smbcli_request *c_req; struct cvfs_file *f; + union smb_close io2; SETUP_PID; @@ -776,6 +777,15 @@ static NTSTATUS cvfs_close(struct ntvfs_module_context *ntvfs, private->map_generic) { return ntvfs_map_close(ntvfs, req, io); } + + if (io->generic.level == RAW_CLOSE_GENERIC) { + ZERO_STRUCT(io2); + io2.close.level = RAW_CLOSE_CLOSE; + io2.close.in.file = io->generic.in.file; + io2.close.in.write_time = io->generic.in.write_time; + io = &io2; + } + SETUP_FILE_HERE(f); /* Note, we aren't free-ing f, or it's h here. Should we? even if file-close fails, we'll remove it from the list, diff --git a/source4/ntvfs/ntvfs_generic.c b/source4/ntvfs/ntvfs_generic.c index e449e61b34..a1c89e7df4 100644 --- a/source4/ntvfs/ntvfs_generic.c +++ b/source4/ntvfs/ntvfs_generic.c @@ -1407,6 +1407,36 @@ done: } +/* + NTVFS close generic to any mapper +*/ +static NTSTATUS ntvfs_map_close_finish(struct ntvfs_module_context *ntvfs, + struct ntvfs_request *req, + union smb_close *cl, + union smb_close *cl2, + NTSTATUS status) +{ + NT_STATUS_NOT_OK_RETURN(status); + + switch (cl->generic.level) { + case RAW_CLOSE_SMB2: + cl->smb2.out.flags = cl2->generic.out.flags; + cl->smb2.out._pad = 0; + cl->smb2.out.create_time = cl2->generic.out.create_time; + cl->smb2.out.access_time = cl2->generic.out.access_time; + cl->smb2.out.write_time = cl2->generic.out.write_time; + cl->smb2.out.change_time = cl2->generic.out.change_time; + cl->smb2.out.alloc_size = cl2->generic.out.alloc_size; + cl->smb2.out.size = cl2->generic.out.size; + cl->smb2.out.file_attr = cl2->generic.out.file_attr; + break; + default: + break; + } + + return status; +} + /* NTVFS close generic to any mapper */ @@ -1415,6 +1445,7 @@ NTSTATUS ntvfs_map_close(struct ntvfs_module_context *ntvfs, union smb_close *cl) { union smb_close *cl2; + NTSTATUS status; cl2 = talloc(req, union smb_close); if (cl2 == NULL) { @@ -1422,30 +1453,38 @@ NTSTATUS ntvfs_map_close(struct ntvfs_module_context *ntvfs, } switch (cl->generic.level) { - case RAW_CLOSE_CLOSE: + case RAW_CLOSE_GENERIC: return NT_STATUS_INVALID_LEVEL; + case RAW_CLOSE_CLOSE: + cl2->generic.level = RAW_CLOSE_GENERIC; + cl2->generic.in.file = cl->close.in.file; + cl2->generic.in.write_time = cl->close.in.write_time; + cl2->generic.in.flags = 0; + break; + case RAW_CLOSE_SPLCLOSE: - cl2->generic.level = RAW_CLOSE_CLOSE; - cl2->generic.in.file.ntvfs = cl->splclose.in.file.ntvfs; + cl2->generic.level = RAW_CLOSE_GENERIC; + cl2->generic.in.file = cl->splclose.in.file; cl2->generic.in.write_time = 0; + cl2->generic.in.flags = 0; break; case RAW_CLOSE_SMB2: - cl2->generic.level = RAW_CLOSE_CLOSE; - cl2->generic.in.file.ntvfs = cl->smb2.in.file.ntvfs; + cl2->generic.level = RAW_CLOSE_GENERIC; + cl2->generic.in.file = cl->smb2.in.file; cl2->generic.in.write_time = 0; - /* SMB2 Close has output parameter, but we just zero them */ - ZERO_STRUCT(cl->smb2.out); + cl2->generic.in.flags = cl->smb2.in.flags; break; } - /* - * we don't need to call ntvfs_map_async_setup() here, - * as close() doesn't have any output fields - */ + status = ntvfs_map_async_setup(ntvfs, req, cl, cl2, + (second_stage_t)ntvfs_map_close_finish); + NT_STATUS_NOT_OK_RETURN(status); + + status = ntvfs->ops->close(ntvfs, req, cl2); - return ntvfs->ops->close(ntvfs, req, cl2); + return ntvfs_map_async_finish(req, status); } /* diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 908dd449af..49710806c7 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -1514,21 +1514,44 @@ NTSTATUS pvfs_close(struct ntvfs_module_context *ntvfs, return NT_STATUS_DOS(ERRSRV, ERRerror); } - if (io->generic.level != RAW_CLOSE_CLOSE) { + if (io->generic.level != RAW_CLOSE_GENERIC) { return ntvfs_map_close(ntvfs, req, io); } - f = pvfs_find_fd(pvfs, req, io->close.in.file.ntvfs); + f = pvfs_find_fd(pvfs, req, io->generic.in.file.ntvfs); if (!f) { return NT_STATUS_INVALID_HANDLE; } - if (!null_time(io->close.in.write_time)) { + if (!null_time(io->generic.in.write_time)) { unix_times.actime = 0; unix_times.modtime = io->close.in.write_time; utime(f->handle->name->full_name, &unix_times); } + if (io->generic.in.flags & SMB2_CLOSE_FLAGS_FULL_INFORMATION) { + struct pvfs_filename *name; + NTSTATUS status; + struct pvfs_file_handle *h = f->handle; + + status = pvfs_resolve_name_handle(pvfs, h); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + name = h->name; + + io->generic.out.flags = SMB2_CLOSE_FLAGS_FULL_INFORMATION; + io->generic.out.create_time = name->dos.create_time; + io->generic.out.access_time = name->dos.access_time; + io->generic.out.write_time = name->dos.write_time; + io->generic.out.change_time = name->dos.change_time; + io->generic.out.alloc_size = name->dos.alloc_size; + io->generic.out.size = name->st.st_size; + io->generic.out.file_attr = name->dos.attrib; + } else { + ZERO_STRUCT(io->generic.out); + } + talloc_free(f); return NT_STATUS_OK; -- cgit From beac55a88fd28b6003ba163f32539a7bdc2df1a6 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 27 May 2008 17:22:02 +1000 Subject: enforce lock ordering in SMB2 (This used to be commit 3bec932a89006521ba74bde7943b8cd5b4a660d8) --- source4/ntvfs/ntvfs_generic.c | 56 ++++++++++++++++++++++--------------------- 1 file changed, 29 insertions(+), 27 deletions(-) (limited to 'source4/ntvfs') diff --git a/source4/ntvfs/ntvfs_generic.c b/source4/ntvfs/ntvfs_generic.c index a1c89e7df4..3d92c0be33 100644 --- a/source4/ntvfs/ntvfs_generic.c +++ b/source4/ntvfs/ntvfs_generic.c @@ -1027,7 +1027,7 @@ NTSTATUS ntvfs_map_lock(struct ntvfs_module_context *ntvfs, case RAW_LOCK_SMB2: { /* this is only approximate! We need to change the generic structure to fix this properly */ - int i; + int i, j; if (lck->smb2.in.lock_count < 1) { return NT_STATUS_INVALID_PARAMETER; } @@ -1044,34 +1044,36 @@ NTSTATUS ntvfs_map_lock(struct ntvfs_module_context *ntvfs, return NT_STATUS_NO_MEMORY; } for (i=0;ismb2.in.lock_count;i++) { - if (lck->smb2.in.locks[i].flags & SMB2_LOCK_FLAG_UNLOCK) { - int j = lck2->generic.in.ulock_cnt; - if (lck->smb2.in.locks[i].flags & - (SMB2_LOCK_FLAG_SHARED|SMB2_LOCK_FLAG_EXCLUSIVE)) { - return NT_STATUS_INVALID_PARAMETER; - } - lck2->generic.in.ulock_cnt++; - lck2->generic.in.locks[j].pid = 0; - lck2->generic.in.locks[j].offset = lck->smb2.in.locks[i].offset; - lck2->generic.in.locks[j].count = lck->smb2.in.locks[i].length; - lck2->generic.in.locks[j].pid = 0; + if (!(lck->smb2.in.locks[i].flags & SMB2_LOCK_FLAG_UNLOCK)) { + break; + } + j = lck2->generic.in.ulock_cnt; + if (lck->smb2.in.locks[i].flags & + (SMB2_LOCK_FLAG_SHARED|SMB2_LOCK_FLAG_EXCLUSIVE)) { + return NT_STATUS_INVALID_PARAMETER; } + lck2->generic.in.ulock_cnt++; + lck2->generic.in.locks[j].pid = 0; + lck2->generic.in.locks[j].offset = lck->smb2.in.locks[i].offset; + lck2->generic.in.locks[j].count = lck->smb2.in.locks[i].length; + lck2->generic.in.locks[j].pid = 0; } - for (i=0;ismb2.in.lock_count;i++) { - if (!(lck->smb2.in.locks[i].flags & SMB2_LOCK_FLAG_UNLOCK)) { - int j = lck2->generic.in.ulock_cnt + - lck2->generic.in.lock_cnt; - lck2->generic.in.lock_cnt++; - lck2->generic.in.locks[j].pid = 0; - lck2->generic.in.locks[j].offset = lck->smb2.in.locks[i].offset; - lck2->generic.in.locks[j].count = lck->smb2.in.locks[i].length; - lck2->generic.in.locks[j].pid = 0; - if (!(lck->smb2.in.locks[i].flags & SMB2_LOCK_FLAG_EXCLUSIVE)) { - lck2->generic.in.mode = LOCKING_ANDX_SHARED_LOCK; - } - if (lck->smb2.in.locks[i].flags & SMB2_LOCK_FLAG_FAIL_IMMEDIATELY) { - lck2->generic.in.timeout = 0; - } + for (;ismb2.in.lock_count;i++) { + if (lck->smb2.in.locks[i].flags & SMB2_LOCK_FLAG_UNLOCK) { + /* w2008 requires unlocks to come first */ + return NT_STATUS_INVALID_PARAMETER; + } + j = lck2->generic.in.ulock_cnt + lck2->generic.in.lock_cnt; + lck2->generic.in.lock_cnt++; + lck2->generic.in.locks[j].pid = 0; + lck2->generic.in.locks[j].offset = lck->smb2.in.locks[i].offset; + lck2->generic.in.locks[j].count = lck->smb2.in.locks[i].length; + lck2->generic.in.locks[j].pid = 0; + if (!(lck->smb2.in.locks[i].flags & SMB2_LOCK_FLAG_EXCLUSIVE)) { + lck2->generic.in.mode = LOCKING_ANDX_SHARED_LOCK; + } + if (lck->smb2.in.locks[i].flags & SMB2_LOCK_FLAG_FAIL_IMMEDIATELY) { + lck2->generic.in.timeout = 0; } } /* initialize output value */ -- cgit From 8daeee5c5d7d5851677089cceaf26a0e32675a96 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 27 May 2008 18:20:23 +1000 Subject: ensure that we honor SMB2 read min_count properly (This used to be commit 318038d6f670efffa96d8b0db63f46b3752e1cd3) --- source4/ntvfs/ntvfs_generic.c | 12 +----------- source4/ntvfs/posix/pvfs_read.c | 8 ++++++++ 2 files changed, 9 insertions(+), 11 deletions(-) (limited to 'source4/ntvfs') diff --git a/source4/ntvfs/ntvfs_generic.c b/source4/ntvfs/ntvfs_generic.c index 3d92c0be33..06d89a717b 100644 --- a/source4/ntvfs/ntvfs_generic.c +++ b/source4/ntvfs/ntvfs_generic.c @@ -1295,16 +1295,6 @@ static NTSTATUS ntvfs_map_read_finish(struct ntvfs_module_context *ntvfs, rd->smb2.out.data.length= rd2->generic.out.nread; rd->smb2.out.remaining = 0; rd->smb2.out.reserved = 0; - if (NT_STATUS_IS_OK(status) && - rd->smb2.out.data.length == 0) { - status = NT_STATUS_END_OF_FILE; - } - /* SMB2 does honor the min_count field, SMB does not */ - if (NT_STATUS_IS_OK(status) && - rd->smb2.in.min_count > rd->smb2.out.data.length) { - rd->smb2.out.data.length = 0; - status = NT_STATUS_END_OF_FILE; - } break; default: return NT_STATUS_INVALID_LEVEL; @@ -1396,7 +1386,7 @@ NTSTATUS ntvfs_map_read(struct ntvfs_module_context *ntvfs, case RAW_READ_SMB2: rd2->readx.in.file.ntvfs= rd->smb2.in.file.ntvfs; rd2->readx.in.offset = rd->smb2.in.offset; - rd2->readx.in.mincnt = rd->smb2.in.length; + rd2->readx.in.mincnt = rd->smb2.in.min_count; rd2->readx.in.maxcnt = rd->smb2.in.length; rd2->readx.in.remaining = 0; rd2->readx.out.data = rd->smb2.out.data.data; diff --git a/source4/ntvfs/posix/pvfs_read.c b/source4/ntvfs/posix/pvfs_read.c index 418b7e09fb..a01a8a57e3 100644 --- a/source4/ntvfs/posix/pvfs_read.c +++ b/source4/ntvfs/posix/pvfs_read.c @@ -93,6 +93,14 @@ NTSTATUS pvfs_read(struct ntvfs_module_context *ntvfs, return pvfs_map_errno(pvfs, errno); } + /* only SMB2 honors mincnt */ + if (req->ctx->protocol == PROTOCOL_SMB2) { + if (rd->readx.in.mincnt > ret || + (ret == 0 && maxcnt > 0)) { + return NT_STATUS_END_OF_FILE; + } + } + f->handle->position = f->handle->seek_offset = rd->readx.in.offset + ret; rd->readx.out.nread = ret; -- cgit