break; \
} \
} while (0)
- /* SMBNTCreateX interface */
+ /* SMBNTCreateX, nttrans and generic interface */
struct {
enum smb_open_level level;
struct {
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;
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;
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:
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) {
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);
+}
} 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;
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)) {
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;
/* 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);
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));