summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source4/ntvfs/ipc/vfs_ipc.c2
-rw-r--r--source4/ntvfs/ntvfs_generic.c14
-rw-r--r--source4/ntvfs/posix/pvfs_open.c3
-rw-r--r--source4/smb_server/smb2/fileio.c76
4 files changed, 84 insertions, 11 deletions
diff --git a/source4/ntvfs/ipc/vfs_ipc.c b/source4/ntvfs/ipc/vfs_ipc.c
index ea7b54ae6a..8ac7ac7d03 100644
--- a/source4/ntvfs/ipc/vfs_ipc.c
+++ b/source4/ntvfs/ipc/vfs_ipc.c
@@ -321,6 +321,7 @@ static NTSTATUS ipc_open_smb2(struct ntvfs_module_context *ntvfs,
status = ipc_open_generic(ntvfs, req, oi->smb2.in.fname, &p);
NT_STATUS_NOT_OK_RETURN(status);
+ ZERO_STRUCT(oi->smb2.out);
oi->smb2.out.file.ntvfs = p->handle;
oi->smb2.out.oplock_level = oi->smb2.in.oplock_level;
oi->smb2.out.create_action = NTCREATEX_ACTION_EXISTED;
@@ -332,7 +333,6 @@ static NTSTATUS ipc_open_smb2(struct ntvfs_module_context *ntvfs,
oi->smb2.out.size = 0;
oi->smb2.out.file_attr = FILE_ATTRIBUTE_NORMAL;
oi->smb2.out.reserved2 = 0;
- oi->smb2.out.blob = data_blob(NULL, 0);
return status;
}
diff --git a/source4/ntvfs/ntvfs_generic.c b/source4/ntvfs/ntvfs_generic.c
index 06d89a717b..9227295696 100644
--- a/source4/ntvfs/ntvfs_generic.c
+++ b/source4/ntvfs/ntvfs_generic.c
@@ -207,6 +207,7 @@ static NTSTATUS ntvfs_map_open_finish(struct ntvfs_module_context *ntvfs,
break;
case RAW_OPEN_SMB2:
+ ZERO_STRUCT(io->smb2.out);
io->smb2.out.file.ntvfs = io2->generic.out.file.ntvfs;
switch (io2->generic.out.oplock_level) {
case BATCH_OPLOCK_RETURN:
@@ -232,7 +233,6 @@ 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.blob = data_blob(NULL, 0);
break;
default:
@@ -512,7 +512,7 @@ NTSTATUS ntvfs_map_open(struct ntvfs_module_context *ntvfs,
}
io2->generic.in.root_fid = 0;
io2->generic.in.access_mask = io->smb2.in.desired_access;
- io2->generic.in.alloc_size = 0;
+ io2->generic.in.alloc_size = io->smb2.in.alloc_size;
io2->generic.in.file_attr = io->smb2.in.file_attributes;
io2->generic.in.share_access = io->smb2.in.share_access;
io2->generic.in.open_disposition= io->smb2.in.create_disposition;
@@ -520,8 +520,14 @@ NTSTATUS ntvfs_map_open(struct ntvfs_module_context *ntvfs,
io2->generic.in.impersonation = io->smb2.in.impersonation_level;
io2->generic.in.security_flags = 0;
io2->generic.in.fname = io->smb2.in.fname;
- io2->generic.in.sec_desc = NULL;
- io2->generic.in.ea_list = NULL;
+ io2->generic.in.sec_desc = io->smb2.in.sec_desc;
+ io2->generic.in.ea_list = &io->smb2.in.eas;
+
+ /* we don't support timewarp yet */
+ if (io->smb2.in.timewarp != 0) {
+ status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
+ break;
+ }
/* we need to check these bits before we check the private mask */
if (io2->generic.in.create_options & NTCREATEX_OPTIONS_NOT_SUPPORTED_MASK) {
diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c
index 49710806c7..0f08136a79 100644
--- a/source4/ntvfs/posix/pvfs_open.c
+++ b/source4/ntvfs/posix/pvfs_open.c
@@ -634,6 +634,8 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs,
return status;
}
+ /* support initial alloc sizes */
+ name->dos.alloc_size = io->ntcreatex.in.alloc_size;
name->dos.attrib = attrib;
status = pvfs_dosattrib_save(pvfs, name, fd);
if (!NT_STATUS_IS_OK(status)) {
@@ -1464,6 +1466,7 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs,
talloc_free(lck);
return pvfs_map_errno(pvfs, errno);
}
+ name->dos.alloc_size = io->ntcreatex.in.alloc_size;
name->dos.attrib = attrib;
status = pvfs_dosattrib_save(pvfs, name, fd);
if (!NT_STATUS_IS_OK(status)) {
diff --git a/source4/smb_server/smb2/fileio.c b/source4/smb_server/smb2/fileio.c
index 5ab217bbfd..086ddc690e 100644
--- a/source4/smb_server/smb2/fileio.c
+++ b/source4/smb_server/smb2/fileio.c
@@ -25,14 +25,19 @@
#include "smb_server/smb2/smb2_server.h"
#include "ntvfs/ntvfs.h"
#include "param/param.h"
+#include "libcli/raw/libcliraw.h"
+#include "libcli/raw/raw_proto.h"
+#include "librpc/gen_ndr/ndr_security.h"
static void smb2srv_create_send(struct ntvfs_request *ntvfs)
{
struct smb2srv_request *req;
union smb_open *io;
+ DATA_BLOB blob;
SMB2SRV_CHECK_ASYNC_STATUS(io, union smb_open);
- SMB2SRV_CHECK(smb2srv_setup_reply(req, 0x58, true, io->smb2.out.blob.length));
+ SMB2SRV_CHECK(smb2_create_blob_push(req, &blob, io->smb2.out.blobs));
+ SMB2SRV_CHECK(smb2srv_setup_reply(req, 0x58, true, blob.length));
SCVAL(req->out.body, 0x02, io->smb2.out.oplock_level);
SCVAL(req->out.body, 0x03, io->smb2.out.reserved);
@@ -46,7 +51,7 @@ static void smb2srv_create_send(struct ntvfs_request *ntvfs)
SIVAL(req->out.body, 0x38, io->smb2.out.file_attr);
SIVAL(req->out.body, 0x3C, io->smb2.out.reserved2);
smb2srv_push_handle(req->out.body, 0x40, io->smb2.out.file.ntvfs);
- SMB2SRV_CHECK(smb2_push_o32s32_blob(&req->out, 0x50, io->smb2.out.blob));
+ SMB2SRV_CHECK(smb2_push_o32s32_blob(&req->out, 0x50, blob));
/* also setup the chained file handle */
req->chained_file_handle = req->_chained_file_handle;
@@ -59,11 +64,13 @@ void smb2srv_create_recv(struct smb2srv_request *req)
{
union smb_open *io;
DATA_BLOB blob;
+ int i;
SMB2SRV_CHECK_BODY_SIZE(req, 0x38, true);
SMB2SRV_TALLOC_IO_PTR(io, union smb_open);
SMB2SRV_SETUP_NTVFS_REQUEST(smb2srv_create_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
+ ZERO_STRUCT(io->smb2.in);
io->smb2.level = RAW_OPEN_SMB2;
io->smb2.in.security_flags = CVAL(req->in.body, 0x02);
io->smb2.in.oplock_level = CVAL(req->in.body, 0x03);
@@ -77,10 +84,67 @@ void smb2srv_create_recv(struct smb2srv_request *req)
io->smb2.in.create_options = IVAL(req->in.body, 0x28);
SMB2SRV_CHECK(smb2_pull_o16s16_string(&req->in, io, req->in.body+0x2C, &io->smb2.in.fname));
SMB2SRV_CHECK(smb2_pull_o32s32_blob(&req->in, io, req->in.body+0x30, &blob));
- /* TODO: parse the blob */
- ZERO_STRUCT(io->smb2.in.eas);
- ZERO_STRUCT(io->smb2.in.blobs);
-
+ SMB2SRV_CHECK(smb2_create_blob_parse(io, blob, &io->smb2.in.blobs));
+
+ /* interpret the parsed tags that a server needs to respond to */
+ for (i=0;i<io->smb2.in.blobs.num_blobs;i++) {
+ if (strcmp(io->smb2.in.blobs.blobs[i].tag, SMB2_CREATE_TAG_EXTA) == 0) {
+ SMB2SRV_CHECK(ea_pull_list_chained(&io->smb2.in.blobs.blobs[i].data, io,
+ &io->smb2.in.eas.num_eas,
+ &io->smb2.in.eas.eas));
+ }
+ if (strcmp(io->smb2.in.blobs.blobs[i].tag, SMB2_CREATE_TAG_SECD) == 0) {
+ enum ndr_err_code ndr_err;
+ io->smb2.in.sec_desc = talloc(io, struct security_descriptor);
+ if (io->smb2.in.sec_desc == NULL) {
+ smb2srv_send_error(req, NT_STATUS_NO_MEMORY);
+ return;
+ }
+ ndr_err = ndr_pull_struct_blob(&io->smb2.in.blobs.blobs[i].data, io, NULL,
+ io->smb2.in.sec_desc,
+ (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ smb2srv_send_error(req, ndr_map_error2ntstatus(ndr_err));
+ return;
+ }
+ }
+ if (strcmp(io->smb2.in.blobs.blobs[i].tag, SMB2_CREATE_TAG_DHNQ) == 0) {
+ io->smb2.in.durable_open = true;
+ }
+ if (strcmp(io->smb2.in.blobs.blobs[i].tag, SMB2_CREATE_TAG_DHNC) == 0) {
+ if (io->smb2.in.blobs.blobs[i].data.length != 16) {
+ smb2srv_send_error(req, NT_STATUS_INVALID_PARAMETER);
+ return;
+ }
+ io->smb2.in.durable_handle = talloc(io, struct smb2_handle);
+ if (io->smb2.in.durable_handle == NULL) {
+ smb2srv_send_error(req, NT_STATUS_NO_MEMORY);
+ return;
+ }
+ smb2_pull_handle(io->smb2.in.blobs.blobs[i].data.data, io->smb2.in.durable_handle);
+ }
+ if (strcmp(io->smb2.in.blobs.blobs[i].tag, SMB2_CREATE_TAG_ALSI) == 0) {
+ if (io->smb2.in.blobs.blobs[i].data.length != 8) {
+ smb2srv_send_error(req, NT_STATUS_INVALID_PARAMETER);
+ return;
+ }
+ io->smb2.in.alloc_size = BVAL(io->smb2.in.blobs.blobs[i].data.data, 0);
+ }
+ if (strcmp(io->smb2.in.blobs.blobs[i].tag, SMB2_CREATE_TAG_MXAC) == 0) {
+ io->smb2.in.query_maximal_access = true;
+ }
+ if (strcmp(io->smb2.in.blobs.blobs[i].tag, SMB2_CREATE_TAG_TWRP) == 0) {
+ if (io->smb2.in.blobs.blobs[i].data.length != 8) {
+ smb2srv_send_error(req, NT_STATUS_INVALID_PARAMETER);
+ return;
+ }
+ io->smb2.in.timewarp = BVAL(io->smb2.in.blobs.blobs[i].data.data, 0);
+ }
+ if (strcmp(io->smb2.in.blobs.blobs[i].tag, SMB2_CREATE_TAG_QFID) == 0) {
+ io->smb2.in.query_on_disk_id = true;
+ }
+ }
+
/* the VFS backend does not yet handle NULL filenames */
if (io->smb2.in.fname == NULL) {
io->smb2.in.fname = "";