diff options
-rw-r--r-- | source4/libcli/raw/interfaces.h | 9 | ||||
-rw-r--r-- | source4/ntvfs/ntvfs_generic.c | 2 | ||||
-rw-r--r-- | source4/ntvfs/posix/pvfs_acl.c | 12 | ||||
-rw-r--r-- | source4/ntvfs/posix/pvfs_open.c | 24 | ||||
-rw-r--r-- | source4/smb_server/smb2/fileio.c | 12 |
5 files changed, 54 insertions, 5 deletions
diff --git a/source4/libcli/raw/interfaces.h b/source4/libcli/raw/interfaces.h index d170006d3b..19d51893a6 100644 --- a/source4/libcli/raw/interfaces.h +++ b/source4/libcli/raw/interfaces.h @@ -1354,7 +1354,7 @@ union smb_open { break; \ } \ } while (0) - /* SMBNTCreateX interface */ + /* SMBNTCreateX, nttrans and generic interface */ struct { enum smb_open_level level; struct { @@ -1377,6 +1377,9 @@ union smb_open { NTTRANS varient of the call */ struct security_descriptor *sec_desc; struct smb_ea_list *ea_list; + + /* some optional parameters from the SMB2 varient */ + bool query_maximal_access; } in; struct { union smb_handle file; @@ -1392,6 +1395,10 @@ union smb_open { uint16_t file_type; uint16_t ipc_state; uint8_t is_directory; + + /* optional return values matching SMB2 tagged + values in the call */ + uint32_t maximal_access; } out; } ntcreatex, nttrans, generic; diff --git a/source4/ntvfs/ntvfs_generic.c b/source4/ntvfs/ntvfs_generic.c index 9227295696..d705758475 100644 --- a/source4/ntvfs/ntvfs_generic.c +++ b/source4/ntvfs/ntvfs_generic.c @@ -233,6 +233,7 @@ static NTSTATUS ntvfs_map_open_finish(struct ntvfs_module_context *ntvfs, io->smb2.out.size = io2->generic.out.size; io->smb2.out.file_attr = io2->generic.out.attrib; io->smb2.out.reserved2 = 0; + io->smb2.out.maximal_access = io2->generic.out.maximal_access; break; default: @@ -522,6 +523,7 @@ NTSTATUS ntvfs_map_open(struct ntvfs_module_context *ntvfs, io2->generic.in.fname = io->smb2.in.fname; io2->generic.in.sec_desc = io->smb2.in.sec_desc; io2->generic.in.ea_list = &io->smb2.in.eas; + io2->generic.in.query_maximal_access = io->smb2.in.query_maximal_access; /* we don't support timewarp yet */ if (io->smb2.in.timewarp != 0) { diff --git a/source4/ntvfs/posix/pvfs_acl.c b/source4/ntvfs/posix/pvfs_acl.c index 089631a307..623b1ae5e9 100644 --- a/source4/ntvfs/posix/pvfs_acl.c +++ b/source4/ntvfs/posix/pvfs_acl.c @@ -807,3 +807,15 @@ NTSTATUS pvfs_acl_inherit(struct pvfs_state *pvfs, return status; } + +/* + return the maximum allowed access mask +*/ +NTSTATUS pvfs_access_maximal_allowed(struct pvfs_state *pvfs, + struct ntvfs_request *req, + struct pvfs_filename *name, + uint32_t *maximal_access) +{ + *maximal_access = SEC_FLAG_MAXIMUM_ALLOWED; + return pvfs_access_check(pvfs, req, name, maximal_access); +} diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index a1c5571258..dada9f503f 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -252,8 +252,12 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, } else { status = pvfs_access_check_create(pvfs, req, name, &access_mask); } - if (!NT_STATUS_IS_OK(status)) { - return status; + NT_STATUS_NOT_OK_RETURN(status); + + if (io->generic.in.query_maximal_access) { + status = pvfs_access_maximal_allowed(pvfs, req, name, + &io->generic.out.maximal_access); + NT_STATUS_NOT_OK_RETURN(status); } f->ntvfs = h; @@ -578,6 +582,12 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, status = pvfs_access_check_create(pvfs, req, name, &access_mask); NT_STATUS_NOT_OK_RETURN(status); + if (io->generic.in.query_maximal_access) { + status = pvfs_access_maximal_allowed(pvfs, req, name, + &io->generic.out.maximal_access); + NT_STATUS_NOT_OK_RETURN(status); + } + /* check that the parent isn't opened with delete on close set */ status = pvfs_resolve_parent(pvfs, req, name, &parent); if (NT_STATUS_IS_OK(status)) { @@ -1135,6 +1145,8 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, return ntvfs_map_open(ntvfs, req, io); } + ZERO_STRUCT(io->generic.out); + create_options = io->generic.in.create_options; share_access = io->generic.in.share_access; access_mask = io->generic.in.access_mask; @@ -1282,8 +1294,12 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, /* check the security descriptor */ status = pvfs_access_check(pvfs, req, name, &access_mask); - if (!NT_STATUS_IS_OK(status)) { - return status; + NT_STATUS_NOT_OK_RETURN(status); + + if (io->generic.in.query_maximal_access) { + status = pvfs_access_maximal_allowed(pvfs, req, name, + &io->generic.out.maximal_access); + NT_STATUS_NOT_OK_RETURN(status); } status = ntvfs_handle_new(pvfs->ntvfs, req, &h); diff --git a/source4/smb_server/smb2/fileio.c b/source4/smb_server/smb2/fileio.c index 086ddc690e..2c322ea587 100644 --- a/source4/smb_server/smb2/fileio.c +++ b/source4/smb_server/smb2/fileio.c @@ -36,6 +36,18 @@ static void smb2srv_create_send(struct ntvfs_request *ntvfs) DATA_BLOB blob; SMB2SRV_CHECK_ASYNC_STATUS(io, union smb_open); + + /* setup the blobs we should give in the reply */ + if (io->smb2.out.maximal_access != 0) { + uint32_t data[2]; + SIVAL(data, 0, 0); + SIVAL(data, 4, io->smb2.out.maximal_access); + SMB2SRV_CHECK(smb2_create_blob_add(req, &io->smb2.out.blobs, + SMB2_CREATE_TAG_MXAC, + data_blob_const(data, 8))); + } + + SMB2SRV_CHECK(smb2_create_blob_push(req, &blob, io->smb2.out.blobs)); SMB2SRV_CHECK(smb2srv_setup_reply(req, 0x58, true, blob.length)); |