summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source4/libcli/raw/interfaces.h9
-rw-r--r--source4/ntvfs/ntvfs_generic.c2
-rw-r--r--source4/ntvfs/posix/pvfs_acl.c12
-rw-r--r--source4/ntvfs/posix/pvfs_open.c24
-rw-r--r--source4/smb_server/smb2/fileio.c12
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));