Exemplo n.º 1
0
static void smb2srv_ioctl_send(struct ntvfs_request *ntvfs)
{
	struct smb2srv_request *req;
	union smb_ioctl *io;

	SMB2SRV_CHECK_ASYNC_STATUS_ERR(io, union smb_ioctl);
	SMB2SRV_CHECK(smb2srv_setup_reply(req, 0x30, True, 0));

	SSVAL(req->out.body,	0x02,	io->smb2.out._pad);
	SIVAL(req->out.body,	0x04,	io->smb2.out.function);
	if (io->smb2.level == RAW_IOCTL_SMB2_NO_HANDLE) {
		struct smb2_handle h;
		h.data[0] = UINT64_MAX;
		h.data[1] = UINT64_MAX;
		smb2_push_handle(req->out.body + 0x08, &h);
	} else {
		smb2srv_push_handle(req->out.body, 0x08,io->smb2.in.file.ntvfs);
	}
	SMB2SRV_CHECK(smb2_push_o32s32_blob(&req->out, 0x18, io->smb2.out.in));
	SMB2SRV_CHECK(smb2_push_o32s32_blob(&req->out, 0x20, io->smb2.out.out));
	SIVAL(req->out.body,	0x28,	io->smb2.out.unknown2);
	SIVAL(req->out.body,	0x2C,	io->smb2.out.unknown3);

	smb2srv_send_reply(req);
}
Exemplo n.º 2
0
void smb2srv_ioctl_recv(struct smb2srv_request *req)
{
	union smb_ioctl *io;
	struct smb2_handle h;

	SMB2SRV_CHECK_BODY_SIZE(req, 0x38, True);
	SMB2SRV_TALLOC_IO_PTR(io, union smb_ioctl);
	SMB2SRV_SETUP_NTVFS_REQUEST(smb2srv_ioctl_send, NTVFS_ASYNC_STATE_MAY_ASYNC);

	/* TODO: avoid the memcpy */
	io->smb2.in._pad		= SVAL(req->in.body, 0x02);
	io->smb2.in.function		= IVAL(req->in.body, 0x04);
	/* file handle ... */
	SMB2SRV_CHECK(smb2_pull_o32s32_blob(&req->in, io, req->in.body+0x18, &io->smb2.in.out));
	io->smb2.in.unknown2		= IVAL(req->in.body, 0x20);
	SMB2SRV_CHECK(smb2_pull_o32s32_blob(&req->in, io, req->in.body+0x24, &io->smb2.in.in));
	io->smb2.in.max_response_size	= IVAL(req->in.body, 0x2C);
	io->smb2.in.flags		= BVAL(req->in.body, 0x30);

	smb2_pull_handle(req->in.body + 0x08, &h);
	if (h.data[0] == UINT64_MAX && h.data[1] == UINT64_MAX) {
		io->smb2.level		= RAW_IOCTL_SMB2_NO_HANDLE;
	} else {
		io->smb2.level		= RAW_IOCTL_SMB2;
		io->smb2.in.file.ntvfs	= smb2srv_pull_handle(req, req->in.body, 0x08);
		SMB2SRV_CHECK_FILE_HANDLE(io->smb2.in.file.ntvfs);
	}

	SMB2SRV_CALL_NTVFS_BACKEND(ntvfs_ioctl(req->ntvfs, io));
}
Exemplo n.º 3
0
static void smb2srv_create_send(struct ntvfs_request *ntvfs)
{
	struct smb2srv_request *req;
	union smb_open *io;

	SMB2SRV_CHECK_ASYNC_STATUS(io, union smb_open);
	SMB2SRV_CHECK(smb2srv_setup_reply(req, 0x58, True, io->smb2.out.blob.length));

	SSVAL(req->out.body,	0x02,	io->smb2.out.oplock_flags);
	SIVAL(req->out.body,	0x04,	io->smb2.out.create_action);
	SBVAL(req->out.body,	0x08,	io->smb2.out.create_time);
	SBVAL(req->out.body,	0x10,	io->smb2.out.access_time);
	SBVAL(req->out.body,	0x18,	io->smb2.out.write_time);
	SBVAL(req->out.body,	0x20,	io->smb2.out.change_time);
	SBVAL(req->out.body,	0x28,	io->smb2.out.alloc_size);
	SBVAL(req->out.body,	0x30,	io->smb2.out.size);
	SIVAL(req->out.body,	0x38,	io->smb2.out.file_attr);
	SIVAL(req->out.body,	0x3C,	io->smb2.out._pad);
	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));

	/* also setup the chained file handle */
	req->chained_file_handle = req->_chained_file_handle;
	smb2srv_push_handle(req->chained_file_handle, 0, io->smb2.out.file.ntvfs);

	smb2srv_send_reply(req);
}
Exemplo n.º 4
0
void smb2srv_create_recv(struct smb2srv_request *req)
{
	union smb_open *io;
	DATA_BLOB blob;

	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);

	io->smb2.level			= RAW_OPEN_SMB2;
	io->smb2.in.oplock_flags	= SVAL(req->in.body, 0x02);
	io->smb2.in.impersonation	= IVAL(req->in.body, 0x04);
	io->smb2.in.unknown3[0]		= IVAL(req->in.body, 0x08);
	io->smb2.in.unknown3[1]		= IVAL(req->in.body, 0x0C);
	io->smb2.in.unknown3[2]		= IVAL(req->in.body, 0x10);
	io->smb2.in.unknown3[3]		= IVAL(req->in.body, 0x14);
	io->smb2.in.access_mask		= IVAL(req->in.body, 0x18);
	io->smb2.in.file_attr		= IVAL(req->in.body, 0x1C);
	io->smb2.in.share_access	= IVAL(req->in.body, 0x20);
	io->smb2.in.open_disposition	= IVAL(req->in.body, 0x24);
	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);

	SMB2SRV_CALL_NTVFS_BACKEND(ntvfs_open(req->ntvfs, io));
}
Exemplo n.º 5
0
static void smb2srv_notify_send(struct ntvfs_request *ntvfs)
{
	struct smb2srv_request *req;
	union smb_notify *io;
	size_t size = 0;
	int i;
	uint8_t *p;
	DATA_BLOB blob = data_blob(NULL, 0);

	SMB2SRV_CHECK_ASYNC_STATUS(io, union smb_notify);
	SMB2SRV_CHECK(smb2srv_setup_reply(req, 0x08, True, 0));

#define MAX_BYTES_PER_CHAR 3
	
	/* work out how big the reply buffer could be */
	for (i=0;i<io->smb2.out.num_changes;i++) {
		size += 12 + 3 + (1+strlen(io->smb2.out.changes[i].name.s)) * MAX_BYTES_PER_CHAR;
	}

	blob = data_blob_talloc(req, NULL, size);
	if (size > 0 && !blob.data) {
		SMB2SRV_CHECK(NT_STATUS_NO_MEMORY);
	}

	p = blob.data;

	/* construct the changes buffer */
	for (i=0;i<io->smb2.out.num_changes;i++) {
		uint32_t ofs;
		ssize_t len;

		SIVAL(p, 4, io->smb2.out.changes[i].action);
		len = push_string(p + 12, io->smb2.out.changes[i].name.s, 
				  blob.length - (p+12 - blob.data), STR_UNICODE);
		SIVAL(p, 8, len);

		ofs = len + 12;

		if (ofs & 3) {
			int pad = 4 - (ofs & 3);
			memset(p+ofs, 0, pad);
			ofs += pad;
		}

		if (i == io->smb2.out.num_changes-1) {
			SIVAL(p, 0, 0);
		} else {
			SIVAL(p, 0, ofs);
		}

		p += ofs;
	}

	blob.length = p - blob.data;

	SMB2SRV_CHECK(smb2_push_o16s32_blob(&req->out, 0x02, blob));

	smb2srv_send_reply(req);
}
Exemplo n.º 6
0
static void smb2srv_read_send(struct ntvfs_request *ntvfs)
{
	struct smb2srv_request *req;
	union smb_read *io;

	SMB2SRV_CHECK_ASYNC_STATUS(io, union smb_read);
	SMB2SRV_CHECK(smb2srv_setup_reply(req, 0x10, True, io->smb2.out.data.length));

	/* TODO: avoid the memcpy */
	SMB2SRV_CHECK(smb2_push_o16s32_blob(&req->out, 0x02, io->smb2.out.data));
	SBVAL(req->out.body,	0x08,	io->smb2.out.unknown1);

	smb2srv_send_reply(req);
}
Exemplo n.º 7
0
void smb2srv_read_recv(struct smb2srv_request *req)
{
	union smb_read *io;

	SMB2SRV_CHECK_BODY_SIZE(req, 0x30, true);

	/* MS-SMB2 2.2.19 read must have a single byte of zero */
	if (req->in.body_size - req->in.body_fixed < 1) {
		smb2srv_send_error(req,  NT_STATUS_INVALID_PARAMETER);
		return;
	}
	SMB2SRV_TALLOC_IO_PTR(io, union smb_read);
	SMB2SRV_SETUP_NTVFS_REQUEST(smb2srv_read_send, NTVFS_ASYNC_STATE_MAY_ASYNC);

	io->smb2.level			= RAW_READ_SMB2;
	io->smb2.in._pad		= SVAL(req->in.body, 0x02);
	io->smb2.in.length		= IVAL(req->in.body, 0x04);
	io->smb2.in.offset		= BVAL(req->in.body, 0x08);
	io->smb2.in.file.ntvfs		= smb2srv_pull_handle(req, req->in.body, 0x10);
	io->smb2.in.min_count		= IVAL(req->in.body, 0x20);
	io->smb2.in.channel		= IVAL(req->in.body, 0x24);
	io->smb2.in.remaining		= IVAL(req->in.body, 0x28);
	io->smb2.in.channel_offset      = SVAL(req->in.body, 0x2C);
	io->smb2.in.channel_length      = SVAL(req->in.body, 0x2E);

	SMB2SRV_CHECK_FILE_HANDLE(io->smb2.in.file.ntvfs);

	/* preallocate the buffer for the backends */
	io->smb2.out.data = data_blob_talloc(io, NULL, io->smb2.in.length);
	if (io->smb2.out.data.length != io->smb2.in.length) {
		SMB2SRV_CHECK(NT_STATUS_NO_MEMORY);
	}

	SMB2SRV_CALL_NTVFS_BACKEND(ntvfs_read(req->ntvfs, io));
}
Exemplo n.º 8
0
static void smb2srv_tcon_send(struct smb2srv_request *req, union smb_tcon *io)
{
	uint16_t unknown1;

	if (!NT_STATUS_IS_OK(req->status)) {
		smb2srv_send_error(req, req->status);
		return;
	}
	if (io->smb2.out.unknown1 == 0x0002) {
		/* if it's an IPC share vista returns 0x0005 */
		unknown1 = 0x0005;
	} else {
		unknown1 = 0x0001;
	}

	SMB2SRV_CHECK(smb2srv_setup_reply(req, 0x10, False, 0));

	SIVAL(req->out.hdr,	SMB2_HDR_TID,	io->smb2.out.tid);
	SSVAL(req->out.hdr,	SMB2_HDR_UNKNOWN1,unknown1);

	SSVAL(req->out.body,	0x02,		io->smb2.out.unknown1);
	SIVAL(req->out.body,	0x04,		io->smb2.out.unknown2);
	SIVAL(req->out.body,	0x08,		io->smb2.out.unknown3);
	SIVAL(req->out.body,	0x0C,		io->smb2.out.access_mask);

	smb2srv_send_reply(req);
}
Exemplo n.º 9
0
void smb2srv_read_recv(struct smb2srv_request *req)
{
	union smb_read *io;

	SMB2SRV_CHECK_BODY_SIZE(req, 0x30, True);
	SMB2SRV_TALLOC_IO_PTR(io, union smb_read);
	SMB2SRV_SETUP_NTVFS_REQUEST(smb2srv_read_send, NTVFS_ASYNC_STATE_MAY_ASYNC);

	io->smb2.level			= RAW_READ_SMB2;
	io->smb2.in._pad		= SVAL(req->in.body, 0x02);
	io->smb2.in.length		= IVAL(req->in.body, 0x04);
	io->smb2.in.offset		= BVAL(req->in.body, 0x08);
	io->smb2.in.file.ntvfs		= smb2srv_pull_handle(req, req->in.body, 0x10);
	io->smb2.in.unknown1		= BVAL(req->in.body, 0x20);
	io->smb2.in.unknown2		= BVAL(req->in.body, 0x28);

	SMB2SRV_CHECK_FILE_HANDLE(io->smb2.in.file.ntvfs);

	/* preallocate the buffer for the backends */
	io->smb2.out.data = data_blob_talloc(io, NULL, io->smb2.in.length);
	if (io->smb2.out.data.length != io->smb2.in.length) {
		SMB2SRV_CHECK(NT_STATUS_NO_MEMORY);
	}

	SMB2SRV_CALL_NTVFS_BACKEND(ntvfs_read(req->ntvfs, io));
}
Exemplo n.º 10
0
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);

	/* 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));

	SCVAL(req->out.body,	0x02,	io->smb2.out.oplock_level);
	SCVAL(req->out.body,	0x03,	io->smb2.out.reserved);
	SIVAL(req->out.body,	0x04,	io->smb2.out.create_action);
	SBVAL(req->out.body,	0x08,	io->smb2.out.create_time);
	SBVAL(req->out.body,	0x10,	io->smb2.out.access_time);
	SBVAL(req->out.body,	0x18,	io->smb2.out.write_time);
	SBVAL(req->out.body,	0x20,	io->smb2.out.change_time);
	SBVAL(req->out.body,	0x28,	io->smb2.out.alloc_size);
	SBVAL(req->out.body,	0x30,	io->smb2.out.size);
	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, blob));

	/* also setup the chained file handle */
	req->chained_file_handle = req->_chained_file_handle;
	smb2srv_push_handle(req->chained_file_handle, 0, io->smb2.out.file.ntvfs);

	smb2srv_send_reply(req);
}
Exemplo n.º 11
0
static void smb2srv_sesssetup_send(struct smb2srv_request *req, union smb_sesssetup *io)
{
	if (NT_STATUS_IS_OK(req->status)) {
		/* nothing */
	} else if (NT_STATUS_EQUAL(req->status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
		/* nothing */
	} else {
		smb2srv_send_error(req, req->status);
		return;
	}

	SMB2SRV_CHECK(smb2srv_setup_reply(req, 0x08, true, io->smb2.out.secblob.length));

	SBVAL(req->out.hdr, SMB2_HDR_SESSION_ID,	io->smb2.out.uid);

	SSVAL(req->out.body, 0x02, io->smb2.out.session_flags);
	SMB2SRV_CHECK(smb2_push_o16s16_blob(&req->out, 0x04, io->smb2.out.secblob));

	smb2srv_send_reply(req);
}
Exemplo n.º 12
0
static void smb2srv_flush_send(struct ntvfs_request *ntvfs)
{
	struct smb2srv_request *req;
	union smb_flush *io;

	SMB2SRV_CHECK_ASYNC_STATUS(io, union smb_flush);
	SMB2SRV_CHECK(smb2srv_setup_reply(req, 0x04, False, 0));

	SSVAL(req->out.body,	0x02,	0);

	smb2srv_send_reply(req);
}
Exemplo n.º 13
0
static void smb2srv_lock_send(struct ntvfs_request *ntvfs)
{
	struct smb2srv_request *req;
	union smb_lock *io;

	SMB2SRV_CHECK_ASYNC_STATUS_ERR(io, union smb_lock);
	SMB2SRV_CHECK(smb2srv_setup_reply(req, 0x04, False, 0));

	SSVAL(req->out.body,	0x02,	io->smb2.out.unknown1);

	smb2srv_send_reply(req);
}
Exemplo n.º 14
0
static void smb2srv_write_send(struct ntvfs_request *ntvfs)
{
	struct smb2srv_request *req;
	union smb_write *io;

	SMB2SRV_CHECK_ASYNC_STATUS(io, union smb_write);
	SMB2SRV_CHECK(smb2srv_setup_reply(req, 0x10, True, 0));

	SSVAL(req->out.body,	0x02,	io->smb2.out._pad);
	SIVAL(req->out.body,	0x04,	io->smb2.out.nwritten);
	SBVAL(req->out.body,	0x08,	io->smb2.out.unknown1);

	smb2srv_send_reply(req);
}
Exemplo n.º 15
0
static void smb2srv_sesssetup_send(struct smb2srv_request *req, union smb_sesssetup *io)
{
	uint16_t unknown1;

	if (NT_STATUS_IS_OK(req->status)) {
		unknown1 = 0x0003;
	} else if (NT_STATUS_EQUAL(req->status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
		unknown1 = 0x0002;
	} else {
		smb2srv_send_error(req, req->status);
		return;
	}

	SMB2SRV_CHECK(smb2srv_setup_reply(req, 0x08, True, io->smb2.out.secblob.length));

	SSVAL(req->out.hdr, SMB2_HDR_UNKNOWN1,	unknown1);
	SBVAL(req->out.hdr, SMB2_HDR_UID,	io->smb2.out.uid);

	SSVAL(req->out.body, 0x02, io->smb2.out._pad);
	SMB2SRV_CHECK(smb2_push_o16s16_blob(&req->out, 0x04, io->smb2.out.secblob));

	smb2srv_send_reply(req);
}
Exemplo n.º 16
0
static void smb2srv_break_send(struct ntvfs_request *ntvfs)
{
	struct smb2srv_request *req;
	union smb_lock *io;

	SMB2SRV_CHECK_ASYNC_STATUS_ERR(io, union smb_lock);
	SMB2SRV_CHECK(smb2srv_setup_reply(req, 0x18, false, 0));

	SCVAL(req->out.body,	0x02,	io->smb2_break.out.oplock_level);
	SCVAL(req->out.body,	0x03,	io->smb2_break.out.reserved);
	SIVAL(req->out.body,	0x04,	io->smb2_break.out.reserved2);
	smb2srv_push_handle(req->out.body, 0x08,io->smb2_break.out.file.ntvfs);

	smb2srv_send_reply(req);
}
Exemplo n.º 17
0
void smb2srv_tcon_recv(struct smb2srv_request *req)
{
	union smb_tcon *io;

	SMB2SRV_CHECK_BODY_SIZE(req, 0x08, True);
	SMB2SRV_TALLOC_IO_PTR(io, union smb_tcon);

	io->smb2.level		= RAW_TCON_SMB2;
	io->smb2.in.unknown1	= SVAL(req->in.body, 0x02);
	SMB2SRV_CHECK(smb2_pull_o16s16_string(&req->in, io, req->in.body+0x04, &io->smb2.in.path));

	req->status = smb2srv_tcon_backend(req, io);

	if (req->control_flags & SMB2SRV_REQ_CTRL_FLAG_NOT_REPLY) {
		talloc_free(req);
		return;
	}
	smb2srv_tcon_send(req, io);
}
Exemplo n.º 18
0
void smb2srv_write_recv(struct smb2srv_request *req)
{
	union smb_write *io;

	SMB2SRV_CHECK_BODY_SIZE(req, 0x30, True);
	SMB2SRV_TALLOC_IO_PTR(io, union smb_write);
	SMB2SRV_SETUP_NTVFS_REQUEST(smb2srv_write_send, NTVFS_ASYNC_STATE_MAY_ASYNC);

	/* TODO: avoid the memcpy */
	io->smb2.level			= RAW_WRITE_SMB2;
	SMB2SRV_CHECK(smb2_pull_o16s32_blob(&req->in, io, req->in.body+0x02, &io->smb2.in.data));
	io->smb2.in.offset		= BVAL(req->in.body, 0x08);
	io->smb2.in.file.ntvfs		= smb2srv_pull_handle(req, req->in.body, 0x10);
	io->smb2.in.unknown1		= BVAL(req->in.body, 0x20);
	io->smb2.in.unknown2		= BVAL(req->in.body, 0x28);

	SMB2SRV_CHECK_FILE_HANDLE(io->smb2.in.file.ntvfs);
	SMB2SRV_CALL_NTVFS_BACKEND(ntvfs_write(req->ntvfs, io));
}
Exemplo n.º 19
0
static void smb2srv_close_send(struct ntvfs_request *ntvfs)
{
	struct smb2srv_request *req;
	union smb_close *io;

	SMB2SRV_CHECK_ASYNC_STATUS(io, union smb_close);
	SMB2SRV_CHECK(smb2srv_setup_reply(req, 0x3C, False, 0));

	SSVAL(req->out.body,	0x02,	io->smb2.out.flags);
	SIVAL(req->out.body,	0x04,	io->smb2.out._pad);
	SBVAL(req->out.body,	0x08,	io->smb2.out.create_time);
	SBVAL(req->out.body,	0x10,	io->smb2.out.access_time);
	SBVAL(req->out.body,	0x18,	io->smb2.out.write_time);
	SBVAL(req->out.body,	0x20,	io->smb2.out.change_time);
	SBVAL(req->out.body,	0x28,	io->smb2.out.alloc_size);
	SBVAL(req->out.body,	0x30,	io->smb2.out.size);
	SIVAL(req->out.body,	0x38,	io->smb2.out.file_attr);

	smb2srv_send_reply(req);
}
Exemplo n.º 20
0
static void smb2srv_close_send(struct ntvfs_request *ntvfs)
{
	struct smb2srv_request *req;
	union smb_close *io;

	SMB2SRV_CHECK_ASYNC_STATUS(io, union smb_close);
	SMB2SRV_CHECK(smb2srv_setup_reply(req, 0x3C, false, 0));

	SSVAL(req->out.body,	0x02,	io->smb2.out.flags);
	SIVAL(req->out.body,	0x04,	io->smb2.out._pad);
	SBVAL(req->out.body,	0x08,	io->smb2.out.create_time);
	SBVAL(req->out.body,	0x10,	io->smb2.out.access_time);
	SBVAL(req->out.body,	0x18,	io->smb2.out.write_time);
	SBVAL(req->out.body,	0x20,	io->smb2.out.change_time);
	SBVAL(req->out.body,	0x28,	io->smb2.out.alloc_size);
	SBVAL(req->out.body,	0x30,	io->smb2.out.size);
	SIVAL(req->out.body,	0x38,	io->smb2.out.file_attr);

	/* also destroy the chained file handle */
	req->chained_file_handle = NULL;
	memset(req->_chained_file_handle, 0, sizeof(req->_chained_file_handle));

	smb2srv_send_reply(req);
}
Exemplo n.º 21
0
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);
	io->smb2.in.impersonation_level	= IVAL(req->in.body, 0x04);
	io->smb2.in.create_flags	= BVAL(req->in.body, 0x08);
	io->smb2.in.reserved		= BVAL(req->in.body, 0x10);
	io->smb2.in.desired_access	= IVAL(req->in.body, 0x18);
	io->smb2.in.file_attributes	= IVAL(req->in.body, 0x1C);
	io->smb2.in.share_access	= IVAL(req->in.body, 0x20);
	io->smb2.in.create_disposition	= IVAL(req->in.body, 0x24);
	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));
	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 = "";
	}

	SMB2SRV_CALL_NTVFS_BACKEND(ntvfs_open(req->ntvfs, io));
}