Пример #1
0
void smb2srv_lock_recv(struct smb2srv_request *req)
{
	union smb_lock *io;
	int i;

	SMB2SRV_CHECK_BODY_SIZE(req, 0x30, false);
	SMB2SRV_TALLOC_IO_PTR(io, union smb_lock);
	SMB2SRV_SETUP_NTVFS_REQUEST(smb2srv_lock_send, NTVFS_ASYNC_STATE_MAY_ASYNC);

	io->smb2.level			= RAW_LOCK_SMB2;
	io->smb2.in.lock_count		= SVAL(req->in.body, 0x02);
	io->smb2.in.reserved		= IVAL(req->in.body, 0x04);
	io->smb2.in.file.ntvfs		= smb2srv_pull_handle(req, req->in.body, 0x08);
	if (req->in.body_size < 24 + 24*(uint64_t)io->smb2.in.lock_count) {
		DEBUG(0,("%s: lock buffer too small\n", __location__));
		smb2srv_send_error(req,  NT_STATUS_FOOBAR);
		return;
	}
	io->smb2.in.locks = talloc_array(io, struct smb2_lock_element, 
					 io->smb2.in.lock_count);
	if (io->smb2.in.locks == NULL) {
		smb2srv_send_error(req, NT_STATUS_NO_MEMORY);
		return;
	}

	for (i=0;i<io->smb2.in.lock_count;i++) {
		io->smb2.in.locks[i].offset	= BVAL(req->in.body, 24 + i*24);
		io->smb2.in.locks[i].length	= BVAL(req->in.body, 32 + i*24);
		io->smb2.in.locks[i].flags	= IVAL(req->in.body, 40 + i*24);
		io->smb2.in.locks[i].reserved	= IVAL(req->in.body, 44 + i*24);
	}

	SMB2SRV_CHECK_FILE_HANDLE(io->smb2.in.file.ntvfs);
	SMB2SRV_CALL_NTVFS_BACKEND(ntvfs_lock(req->ntvfs, io));
}
Пример #2
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);
}
Пример #3
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));
}
Пример #4
0
void smb2srv_negprot_recv(struct smb2srv_request *req)
{
	struct smb2_negprot *io;

	if (req->in.body_size < 0x26) {
		smb2srv_send_error(req,  NT_STATUS_FOOBAR);
		return;
	}

	io = talloc(req, struct smb2_negprot);
	if (!io) {
		smbsrv_terminate_connection(req->smb_conn, nt_errstr(NT_STATUS_NO_MEMORY));
		talloc_free(req);
		return;
	}

	io->in.unknown1	= SVAL(req->in.body, 0x02);
	memcpy(io->in.unknown2, req->in.body + 0x04, 0x20);
	io->in.unknown3 = SVAL(req->in.body, 0x24);

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

	if (req->control_flags & SMB2SRV_REQ_CTRL_FLAG_NOT_REPLY) {
		talloc_free(req);
		return;
	}
	smb2srv_negprot_send(req, io);
}
Пример #5
0
void smb2srv_keepalive_recv(struct smb2srv_request *req)
{
	uint16_t _pad;

	if (req->in.body_size != 0x04) {
		smb2srv_send_error(req,  NT_STATUS_INVALID_PARAMETER);
		return;
	}

	if (SVAL(req->in.body, 0x00) != 0x04) {
		smb2srv_send_error(req,  NT_STATUS_INVALID_PARAMETER);
		return;
	}

	_pad	= SVAL(req->in.body, 0x02);

	req->status = smb2srv_keepalive_backend(req);

	if (req->control_flags & SMB2SRV_REQ_CTRL_FLAG_NOT_REPLY) {
		talloc_free(req);
		return;
	}
	smb2srv_keepalive_send(req);
}
Пример #6
0
static void smb2srv_keepalive_send(struct smb2srv_request *req)
{
	NTSTATUS status;

	if (NT_STATUS_IS_ERR(req->status)) {
		smb2srv_send_error(req, req->status);
		return;
	}

	status = smb2srv_setup_reply(req, 0x04, false, 0);
	if (!NT_STATUS_IS_OK(status)) {
		smbsrv_terminate_connection(req->smb_conn, nt_errstr(status));
		talloc_free(req);
		return;
	}

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

	smb2srv_send_reply(req);
}
Пример #7
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);
}
Пример #8
0
static void smb2srv_negprot_send(struct smb2srv_request *req, struct smb2_negprot *io)
{
	NTSTATUS status;

	if (NT_STATUS_IS_ERR(req->status)) {
		smb2srv_send_error(req, req->status); /* TODO: is this correct? */
		return;
	}

	status = smb2srv_setup_reply(req, 0x40, true, io->out.secblob.length);
	if (!NT_STATUS_IS_OK(status)) {
		smbsrv_terminate_connection(req->smb_conn, nt_errstr(status));
		talloc_free(req);
		return;
	}

	SSVAL(req->out.body, 0x02, io->out.security_mode);
	SIVAL(req->out.body, 0x04, io->out.dialect_revision);
	SIVAL(req->out.body, 0x06, io->out.reserved);
	status = smbcli_push_guid(req->out.body, 0x08, &io->out.server_guid);
	if (!NT_STATUS_IS_OK(status)) {
		smbsrv_terminate_connection(req->smb_conn, nt_errstr(status));
		talloc_free(req);
		return;
	}
	SIVAL(req->out.body, 0x18, io->out.capabilities);
	SIVAL(req->out.body, 0x1C, io->out.max_transact_size);
	SIVAL(req->out.body, 0x20, io->out.max_read_size);
	SIVAL(req->out.body, 0x24, io->out.max_write_size);
	push_nttime(req->out.body, 0x28, io->out.system_time);
	push_nttime(req->out.body, 0x30, io->out.server_start_time);
	SIVAL(req->out.body, 0x3C, io->out.reserved2);
	status = smb2_push_o16s16_blob(&req->out, 0x38, io->out.secblob);
	if (!NT_STATUS_IS_OK(status)) {
		smbsrv_terminate_connection(req->smb_conn, nt_errstr(status));
		talloc_free(req);
		return;
	}

	smb2srv_send_reply(req);
}
Пример #9
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);
}
Пример #10
0
static void smb2srv_negprot_send(struct smb2srv_request *req, struct smb2_negprot *io)
{
	NTSTATUS status;

	if (NT_STATUS_IS_ERR(req->status)) {
		smb2srv_send_error(req, req->status); /* TODO: is this correct? */
		return;
	}

	status = smb2srv_setup_reply(req, 0x40, True, io->out.secblob.length);
	if (!NT_STATUS_IS_OK(status)) {
		smbsrv_terminate_connection(req->smb_conn, nt_errstr(status));
		talloc_free(req);
		return;
	}

	SSVAL(req->out.body, 0x02, io->out._pad);
	SIVAL(req->out.body, 0x04, io->out.unknown2);
	memcpy(req->out.body+0x08, io->out.sessid, 16);
	SIVAL(req->out.body, 0x18, io->out.unknown3);
	SSVAL(req->out.body, 0x1C, io->out.unknown4);
	SIVAL(req->out.body, 0x1E, io->out.unknown5);
	SIVAL(req->out.body, 0x22, io->out.unknown6);
	SSVAL(req->out.body, 0x26, io->out.unknown7);
	push_nttime(req->out.body, 0x28, io->out.current_time);
	push_nttime(req->out.body, 0x30, io->out.boot_time);
	status = smb2_push_o16s16_blob(&req->out, 0x38, io->out.secblob);
	if (!NT_STATUS_IS_OK(status)) {
		smbsrv_terminate_connection(req->smb_conn, nt_errstr(status));
		talloc_free(req);
		return;
	}

	SIVAL(req->out.body, 0x3C, io->out.unknown9);

	smb2srv_send_reply(req);
}
Пример #11
0
void smb2srv_break_recv(struct smb2srv_request *req)
{
	smb2srv_send_error(req, NT_STATUS_NOT_IMPLEMENTED);
}
Пример #12
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));
}
Пример #13
0
NTSTATUS smbsrv_recv_smb2_request(void *private_data, DATA_BLOB blob)
{
	struct smbsrv_connection *smb_conn = talloc_get_type(private_data, struct smbsrv_connection);
	struct smb2srv_request *req;
	struct timeval cur_time = timeval_current();
	uint32_t protocol_version;
	uint16_t buffer_code;
	uint32_t dynamic_size;
	uint32_t flags;

	smb_conn->statistics.last_request_time = cur_time;

	/* see if its a special NBT packet */
	if (CVAL(blob.data,0) != 0) {
		DEBUG(2,("Special NBT packet on SMB2 connection"));
		smbsrv_terminate_connection(smb_conn, "Special NBT packet on SMB2 connection");
		return NT_STATUS_OK;
	}

	if (blob.length < (NBT_HDR_SIZE + SMB2_MIN_SIZE_NO_BODY)) {
		DEBUG(2,("Invalid SMB2 packet length count %ld\n", (long)blob.length));
		smbsrv_terminate_connection(smb_conn, "Invalid SMB2 packet");
		return NT_STATUS_OK;
	}

	protocol_version = IVAL(blob.data, NBT_HDR_SIZE);
	if (protocol_version != SMB2_MAGIC) {
		DEBUG(2,("Invalid SMB packet: protocol prefix: 0x%08X\n",
			 protocol_version));
		smbsrv_terminate_connection(smb_conn, "NON-SMB2 packet");
		return NT_STATUS_OK;
	}

	req = smb2srv_init_request(smb_conn);
	NT_STATUS_HAVE_NO_MEMORY(req);

	req->in.buffer		= talloc_steal(req, blob.data);
	req->in.size		= blob.length;
	req->request_time	= cur_time;
	req->in.allocated	= req->in.size;

	req->in.hdr		= req->in.buffer+ NBT_HDR_SIZE;
	req->in.body		= req->in.hdr	+ SMB2_HDR_BODY;
	req->in.body_size	= req->in.size	- (SMB2_HDR_BODY+NBT_HDR_SIZE);
	req->in.dynamic 	= NULL;

	req->seqnum		= BVAL(req->in.hdr, SMB2_HDR_MESSAGE_ID);

	if (req->in.body_size < 2) {
		/* error handling for this is different for negprot to 
		   other packet types */
		uint16_t opcode	= SVAL(req->in.hdr, SMB2_HDR_OPCODE);
		if (opcode == SMB2_OP_NEGPROT) {
			smbsrv_terminate_connection(req->smb_conn, "Bad body size in SMB2 negprot");			
			return NT_STATUS_OK;
		} else {
			smb2srv_send_error(req, NT_STATUS_INVALID_PARAMETER);
			return NT_STATUS_OK;
		}
	}

	buffer_code		= SVAL(req->in.body, 0);
	req->in.body_fixed	= (buffer_code & ~1);
	dynamic_size		= req->in.body_size - req->in.body_fixed;

	if (dynamic_size != 0 && (buffer_code & 1)) {
		req->in.dynamic = req->in.body + req->in.body_fixed;
		if (smb2_oob(&req->in, req->in.dynamic, dynamic_size)) {
			DEBUG(1,("SMB2 request invalid dynamic size 0x%x\n", 
				 dynamic_size));
			smb2srv_send_error(req, NT_STATUS_INVALID_PARAMETER);
			return NT_STATUS_OK;
		}
	}

	smb2srv_setup_bufinfo(req);

	/* 
	 * TODO: - make sure the length field is 64
	 *       - make sure it's a request
	 */

	flags = IVAL(req->in.hdr, SMB2_HDR_FLAGS);
	/* the first request should never have the related flag set */
	if (flags & SMB2_HDR_FLAG_CHAINED) {
		req->chain_status = NT_STATUS_INVALID_PARAMETER;
	}

	return smb2srv_reply(req);
}
Пример #14
0
static NTSTATUS smb2srv_reply(struct smb2srv_request *req)
{
	uint16_t opcode;
	uint32_t tid;
	uint64_t uid;
	uint32_t flags;

	if (SVAL(req->in.hdr, SMB2_HDR_LENGTH) != SMB2_HDR_BODY) {
		smbsrv_terminate_connection(req->smb_conn, "Invalid SMB2 header length");
		return NT_STATUS_INVALID_PARAMETER;
	}
	opcode			= SVAL(req->in.hdr, SMB2_HDR_OPCODE);
	req->chain_offset	= IVAL(req->in.hdr, SMB2_HDR_NEXT_COMMAND);
	req->seqnum		= BVAL(req->in.hdr, SMB2_HDR_MESSAGE_ID);
	tid			= IVAL(req->in.hdr, SMB2_HDR_TID);
	uid			= BVAL(req->in.hdr, SMB2_HDR_SESSION_ID);
	flags			= IVAL(req->in.hdr, SMB2_HDR_FLAGS);

	if (opcode != SMB2_OP_CANCEL &&
	    req->smb_conn->highest_smb2_seqnum != 0 &&
	    req->seqnum <= req->smb_conn->highest_smb2_seqnum) {
		smbsrv_terminate_connection(req->smb_conn, "Invalid SMB2 sequence number");
		return NT_STATUS_INVALID_PARAMETER;
	}
	if (opcode != SMB2_OP_CANCEL) {
		req->smb_conn->highest_smb2_seqnum = req->seqnum;
	}

	if (flags & SMB2_HDR_FLAG_CHAINED) {
		uid = req->chained_session_id;
		tid = req->chained_tree_id;
	}

	req->session	= smbsrv_session_find(req->smb_conn, uid, req->request_time);
	req->tcon	= smbsrv_smb2_tcon_find(req->session, tid, req->request_time);

	req->chained_session_id = uid;
	req->chained_tree_id = tid;

	errno = 0;

	/* supporting signing is mandatory in SMB2, and is per-packet. So we 
	   should check the signature on any incoming packet that is signed, and 
	   should give a signed reply to any signed request */
	if (flags & SMB2_HDR_FLAG_SIGNED) {
		NTSTATUS status;

		if (!req->session) goto nosession;

		req->is_signed = true;
		status = smb2_check_signature(&req->in, 
					      req->session->session_info->session_key);
		if (!NT_STATUS_IS_OK(status)) {
			smb2srv_send_error(req, status);
			return NT_STATUS_OK;			
		}
	} else if (req->session && req->session->smb2_signing.active) {
		/* we require signing and this request was not signed */
		smb2srv_send_error(req, NT_STATUS_ACCESS_DENIED);
		return NT_STATUS_OK;					
	}

	if (!NT_STATUS_IS_OK(req->chain_status)) {
		smb2srv_send_error(req, req->chain_status);
		return NT_STATUS_OK;
	}

	switch (opcode) {
	case SMB2_OP_NEGPROT:
		smb2srv_negprot_recv(req);
		return NT_STATUS_OK;
	case SMB2_OP_SESSSETUP:
		smb2srv_sesssetup_recv(req);
		return NT_STATUS_OK;
	case SMB2_OP_LOGOFF:
		if (!req->session) goto nosession;
		smb2srv_logoff_recv(req);
		return NT_STATUS_OK;
	case SMB2_OP_TCON:
		if (!req->session) goto nosession;
		smb2srv_tcon_recv(req);
		return NT_STATUS_OK;
	case SMB2_OP_TDIS:
		if (!req->session) goto nosession;
		if (!req->tcon)	goto notcon;
		smb2srv_tdis_recv(req);
		return NT_STATUS_OK;
	case SMB2_OP_CREATE:
		if (!req->session) goto nosession;
		if (!req->tcon)	goto notcon;
		smb2srv_create_recv(req);
		return NT_STATUS_OK;
	case SMB2_OP_CLOSE:
		if (!req->session) goto nosession;
		if (!req->tcon)	goto notcon;
		smb2srv_close_recv(req);
		return NT_STATUS_OK;
	case SMB2_OP_FLUSH:
		if (!req->session) goto nosession;
		if (!req->tcon)	goto notcon;
		smb2srv_flush_recv(req);
		return NT_STATUS_OK;
	case SMB2_OP_READ:
		if (!req->session) goto nosession;
		if (!req->tcon)	goto notcon;
		smb2srv_read_recv(req);
		return NT_STATUS_OK;
	case SMB2_OP_WRITE:
		if (!req->session) goto nosession;
		if (!req->tcon)	goto notcon;
		smb2srv_write_recv(req);
		return NT_STATUS_OK;
	case SMB2_OP_LOCK:
		if (!req->session) goto nosession;
		if (!req->tcon)	goto notcon;
		smb2srv_lock_recv(req);
		return NT_STATUS_OK;
	case SMB2_OP_IOCTL:
		if (!req->session) goto nosession;
		if (!req->tcon)	goto notcon;
		smb2srv_ioctl_recv(req);
		return NT_STATUS_OK;
	case SMB2_OP_CANCEL:
		smb2srv_cancel_recv(req);
		return NT_STATUS_OK;
	case SMB2_OP_KEEPALIVE:
		smb2srv_keepalive_recv(req);
		return NT_STATUS_OK;
	case SMB2_OP_FIND:
		if (!req->session) goto nosession;
		if (!req->tcon)	goto notcon;
		smb2srv_find_recv(req);
		return NT_STATUS_OK;
	case SMB2_OP_NOTIFY:
		if (!req->session) goto nosession;
		if (!req->tcon)	goto notcon;
		smb2srv_notify_recv(req);
		return NT_STATUS_OK;
	case SMB2_OP_GETINFO:
		if (!req->session) goto nosession;
		if (!req->tcon)	goto notcon;
		smb2srv_getinfo_recv(req);
		return NT_STATUS_OK;
	case SMB2_OP_SETINFO:
		if (!req->session) goto nosession;
		if (!req->tcon)	goto notcon;
		smb2srv_setinfo_recv(req);
		return NT_STATUS_OK;
	case SMB2_OP_BREAK:
		if (!req->session) goto nosession;
		if (!req->tcon)	goto notcon;
		smb2srv_break_recv(req);
		return NT_STATUS_OK;
	}

	DEBUG(1,("Invalid SMB2 opcode: 0x%04X\n", opcode));
	smbsrv_terminate_connection(req->smb_conn, "Invalid SMB2 opcode");
	return NT_STATUS_OK;

nosession:
	smb2srv_send_error(req, NT_STATUS_USER_SESSION_DELETED);
	return NT_STATUS_OK;
notcon:
	smb2srv_send_error(req, NT_STATUS_NETWORK_NAME_DELETED);
	return NT_STATUS_OK;
}
Пример #15
0
static void smb2srv_chain_reply(struct smb2srv_request *p_req)
{
	NTSTATUS status;
	struct smb2srv_request *req;
	uint32_t chain_offset;
	uint32_t protocol_version;
	uint16_t buffer_code;
	uint32_t dynamic_size;
	uint32_t flags;
	uint32_t last_hdr_offset;

	last_hdr_offset = p_req->in.hdr - p_req->in.buffer;

	chain_offset = p_req->chain_offset;
	p_req->chain_offset = 0;

	if (p_req->in.size < (last_hdr_offset + chain_offset + SMB2_MIN_SIZE_NO_BODY)) {
		DEBUG(2,("Invalid SMB2 chained packet at offset 0x%X from last hdr 0x%X\n",
			chain_offset, last_hdr_offset));
		smbsrv_terminate_connection(p_req->smb_conn, "Invalid SMB2 chained packet");
		return;
	}

	protocol_version = IVAL(p_req->in.buffer, last_hdr_offset + chain_offset);
	if (protocol_version != SMB2_MAGIC) {
		DEBUG(2,("Invalid SMB chained packet: protocol prefix: 0x%08X\n",
			 protocol_version));
		smbsrv_terminate_connection(p_req->smb_conn, "NON-SMB2 chained packet");
		return;
	}

	req = smb2srv_init_request(p_req->smb_conn);
	if (!req) {
		smbsrv_terminate_connection(p_req->smb_conn, "SMB2 chained packet - no memory");
		return;
	}

	req->in.buffer		= talloc_steal(req, p_req->in.buffer);
	req->in.size		= p_req->in.size;
	req->request_time	= p_req->request_time;
	req->in.allocated	= req->in.size;

	req->in.hdr		= req->in.buffer+ last_hdr_offset + chain_offset;
	req->in.body		= req->in.hdr	+ SMB2_HDR_BODY;
	req->in.body_size	= req->in.size	- (last_hdr_offset+ chain_offset + SMB2_HDR_BODY);
	req->in.dynamic 	= NULL;

	req->seqnum		= BVAL(req->in.hdr, SMB2_HDR_MESSAGE_ID);

	if (req->in.body_size < 2) {
		/* error handling for this is different for negprot to 
		   other packet types */
		uint16_t opcode	= SVAL(req->in.hdr, SMB2_HDR_OPCODE);
		if (opcode == SMB2_OP_NEGPROT) {
			smbsrv_terminate_connection(req->smb_conn, "Bad body size in SMB2 negprot");			
		} else {
			smb2srv_send_error(req, NT_STATUS_INVALID_PARAMETER);
		}
	}

	buffer_code		= SVAL(req->in.body, 0);
	req->in.body_fixed	= (buffer_code & ~1);
	dynamic_size		= req->in.body_size - req->in.body_fixed;

	if (dynamic_size != 0 && (buffer_code & 1)) {
		req->in.dynamic = req->in.body + req->in.body_fixed;
		if (smb2_oob(&req->in, req->in.dynamic, dynamic_size)) {
			DEBUG(1,("SMB2 chained request invalid dynamic size 0x%x\n", 
				 dynamic_size));
			smb2srv_send_error(req, NT_STATUS_INVALID_PARAMETER);
			return;
		}
	}

	smb2srv_setup_bufinfo(req);

	flags = IVAL(req->in.hdr, SMB2_HDR_FLAGS);
	if (flags & SMB2_HDR_FLAG_CHAINED) {
		if (p_req->chained_file_handle) {
			memcpy(req->_chained_file_handle,
			       p_req->_chained_file_handle,
			       sizeof(req->_chained_file_handle));
			req->chained_file_handle = req->_chained_file_handle;
		}
		req->chained_session_id = p_req->chained_session_id;
		req->chained_tree_id = p_req->chained_tree_id;
		req->chain_status = p_req->chain_status;
	}

	/* 
	 * TODO: - make sure the length field is 64
	 *       - make sure it's a request
	 */

	status = smb2srv_reply(req);
	if (!NT_STATUS_IS_OK(status)) {
		smbsrv_terminate_connection(req->smb_conn, nt_errstr(status));
		talloc_free(req);
		return;
	}
}