diff options
-rw-r--r-- | source4/libcli/raw/interfaces.h | 1 | ||||
-rw-r--r-- | source4/libcli/raw/smb.h | 9 | ||||
-rw-r--r-- | source4/librpc/idl/xattr.idl | 3 | ||||
-rw-r--r-- | source4/ntvfs/ntvfs_generic.c | 18 | ||||
-rw-r--r-- | source4/ntvfs/posix/pvfs_flush.c | 1 | ||||
-rw-r--r-- | source4/ntvfs/posix/pvfs_open.c | 38 | ||||
-rw-r--r-- | source4/ntvfs/posix/pvfs_streams.c | 13 | ||||
-rw-r--r-- | source4/scripting/python/samba/tests/dcerpc/rpcecho.py | 2 | ||||
-rw-r--r-- | source4/smb_server/smb/reply.c | 5 | ||||
-rw-r--r-- | source4/torture/gentest_smb2.c | 2 | ||||
-rw-r--r-- | source4/torture/raw/read.c | 17 |
11 files changed, 87 insertions, 22 deletions
diff --git a/source4/libcli/raw/interfaces.h b/source4/libcli/raw/interfaces.h index bae0e67b02..36d8c3abb0 100644 --- a/source4/libcli/raw/interfaces.h +++ b/source4/libcli/raw/interfaces.h @@ -1919,6 +1919,7 @@ union smb_lock { #define SMB2_LOCK_FLAG_EXCLUSIVE 0x00000002 #define SMB2_LOCK_FLAG_UNLOCK 0x00000004 #define SMB2_LOCK_FLAG_FAIL_IMMEDIATELY 0x00000010 +#define SMB2_LOCK_FLAG_ALL_MASK 0x00000017 uint32_t flags; uint32_t reserved; } *locks; diff --git a/source4/libcli/raw/smb.h b/source4/libcli/raw/smb.h index 74869e8a45..5a92b99757 100644 --- a/source4/libcli/raw/smb.h +++ b/source4/libcli/raw/smb.h @@ -133,6 +133,7 @@ #define NTCREATEX_SHARE_ACCESS_READ 1 #define NTCREATEX_SHARE_ACCESS_WRITE 2 #define NTCREATEX_SHARE_ACCESS_DELETE 4 +#define NTCREATEX_SHARE_ACCESS_MASK 7 /* ntcreatex open_disposition field */ #define NTCREATEX_DISP_SUPERSEDE 0 /* supersede existing file (if it exists) */ @@ -154,14 +155,18 @@ #define NTCREATEX_OPTIONS_RANDOM_ACCESS 0x0800 #define NTCREATEX_OPTIONS_DELETE_ON_CLOSE 0x1000 #define NTCREATEX_OPTIONS_OPEN_BY_FILE_ID 0x2000 -#define NTCREATEX_OPTIONS_UNKNOWN_400000 0x400000 - +#define NTCREATEX_OPTIONS_BACKUP_INTENT 0x4000 +#define NTCREATEX_OPTIONS_REPARSE_POINT 0x200000 +#define NTCREATEX_OPTIONS_UNKNOWN_400000 0x400000 /* create options these bits are for private use by backends, they are not valid on the wire */ #define NTCREATEX_OPTIONS_PRIVATE_MASK 0xFF000000 #define NTCREATEX_OPTIONS_PRIVATE_DENY_DOS 0x01000000 #define NTCREATEX_OPTIONS_PRIVATE_DENY_FCB 0x02000000 +#define NTCREATEX_OPTIONS_NOT_SUPPORTED_MASK 0x00DFA188 + + /* ntcreatex impersonation field */ #define NTCREATEX_IMPERSONATION_ANONYMOUS 0 diff --git a/source4/librpc/idl/xattr.idl b/source4/librpc/idl/xattr.idl index 2010d51ce1..520341e6aa 100644 --- a/source4/librpc/idl/xattr.idl +++ b/source4/librpc/idl/xattr.idl @@ -86,7 +86,8 @@ interface xattr /* stream data is stored in attributes with the given prefix */ const char *XATTR_DOSSTREAM_PREFIX = "user.DosStream."; - const int XATTR_MAX_STREAM_SIZE = 0x4000; + const int XATTR_MAX_STREAM_SIZE = 0x4000; + const int XATTR_MAX_STREAM_SIZE_TDB = 0x100000; typedef struct { uint32 flags; 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;i<lck->smb2.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_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: 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) { 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 */ diff --git a/source4/scripting/python/samba/tests/dcerpc/rpcecho.py b/source4/scripting/python/samba/tests/dcerpc/rpcecho.py index 68b7a42d52..bbbd0d76ec 100644 --- a/source4/scripting/python/samba/tests/dcerpc/rpcecho.py +++ b/source4/scripting/python/samba/tests/dcerpc/rpcecho.py @@ -27,7 +27,7 @@ class RpcEchoTests(RpcInterfaceTestCase): self.conn = echo.rpcecho("ncalrpc:", self.get_loadparm()) def test_two_contexts(self): - self.conn2 = echo.rpcecho("ncalrpc", basis_connection=self.conn) + self.conn2 = echo.rpcecho("ncalrpc:", basis_connection=self.conn) self.assertEquals(3, self.conn2.AddOne(2)) def test_abstract_syntax(self): diff --git a/source4/smb_server/smb/reply.c b/source4/smb_server/smb/reply.c index 40cad91062..d28f4b6072 100644 --- a/source4/smb_server/smb/reply.c +++ b/source4/smb_server/smb/reply.c @@ -2193,6 +2193,11 @@ void smbsrv_reply_ntcreate_and_X(struct smbsrv_request *req) io->ntcreatex.in.ea_list = NULL; io->ntcreatex.in.sec_desc = NULL; + /* we use a couple of bits of the create options internally */ + if (io->ntcreatex.in.create_options & NTCREATEX_OPTIONS_PRIVATE_MASK) { + return NT_STATUS_INVALID_PARAMETER; + } + /* we need a neater way to handle this alignment */ if ((req->flags2 & FLAGS2_UNICODE_STRINGS) && ucs2_align(req->in.buffer, req->in.data, STR_TERMINATE|STR_UNICODE)) { diff --git a/source4/torture/gentest_smb2.c b/source4/torture/gentest_smb2.c index 6546ba6768..46545699d0 100644 --- a/source4/torture/gentest_smb2.c +++ b/source4/torture/gentest_smb2.c @@ -1026,7 +1026,7 @@ static bool handler_create(int instance) /* mask out oplocks */ parm[0].in.oplock_level = 0; } - + GEN_COPY_PARM; GEN_CALL(smb2_create(tree, current_op.mem_ctx, &parm[i])); diff --git a/source4/torture/raw/read.c b/source4/torture/raw/read.c index c8420c279e..ada9b1f432 100644 --- a/source4/torture/raw/read.c +++ b/source4/torture/raw/read.c @@ -460,6 +460,23 @@ static bool test_readx(struct torture_context *tctx, struct smbcli_state *cli) CHECK_VALUE(io.readx.out.compaction_mode, 0); } + printf("Trying mincnt past EOF\n"); + memset(buf, 0, maxsize); + io.readx.in.offset = 0; + io.readx.in.mincnt = 100; + io.readx.in.maxcnt = 110; + status = smb_raw_read(cli->tree, &io); + CHECK_STATUS(status, NT_STATUS_OK); + CHECK_VALUE(io.readx.out.remaining, 0xFFFF); + CHECK_VALUE(io.readx.out.compaction_mode, 0); + CHECK_VALUE(io.readx.out.nread, strlen(test_data)); + if (memcmp(buf, test_data, strlen(test_data)) != 0) { + ret = false; + printf("incorrect data at %d!? (%s:%s)\n", __LINE__, test_data, buf); + goto done; + } + + setup_buffer(buf, seed, maxsize); smbcli_write(cli->tree, fnum, 0, buf, 0, maxsize); memset(buf, 0, maxsize); |