diff options
-rw-r--r-- | source4/ntvfs/ipc/vfs_ipc.c | 2 | ||||
-rw-r--r-- | source4/ntvfs/ntvfs_generic.c | 14 | ||||
-rw-r--r-- | source4/ntvfs/posix/pvfs_open.c | 3 | ||||
-rw-r--r-- | source4/smb_server/smb2/fileio.c | 76 |
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 = ""; |