Ejemplo n.º 1
0
/*
 * reply to a SMB negprot request with dialect "SMB 2.002"
 */
void smb2srv_reply_smb_negprot(struct smbsrv_request *smb_req)
{
	struct smb2srv_request *req;
	uint32_t body_fixed_size = 0x26;

	req = talloc_zero(smb_req->smb_conn, struct smb2srv_request);
	if (!req) goto nomem;
	req->smb_conn		= smb_req->smb_conn;
	req->request_time	= smb_req->request_time;
	talloc_steal(req, smb_req);

	req->in.size      = NBT_HDR_SIZE+SMB2_HDR_BODY+body_fixed_size;
	req->in.allocated = req->in.size;
	req->in.buffer    = talloc_array(req, uint8_t, req->in.allocated);
	if (!req->in.buffer) goto nomem;
	req->in.hdr       = req->in.buffer + NBT_HDR_SIZE;
	req->in.body      = req->in.hdr + SMB2_HDR_BODY;
	req->in.body_size = body_fixed_size;
	req->in.dynamic   = NULL;

	smb2srv_setup_bufinfo(req);

	SIVAL(req->in.hdr, 0,				SMB2_MAGIC);
	SSVAL(req->in.hdr, SMB2_HDR_LENGTH,		SMB2_HDR_BODY);
	SSVAL(req->in.hdr, SMB2_HDR_EPOCH,		0);
	SIVAL(req->in.hdr, SMB2_HDR_STATUS,		0);
	SSVAL(req->in.hdr, SMB2_HDR_OPCODE,		SMB2_OP_NEGPROT);
	SSVAL(req->in.hdr, SMB2_HDR_CREDIT,		0);
	SIVAL(req->in.hdr, SMB2_HDR_FLAGS,		0);
	SIVAL(req->in.hdr, SMB2_HDR_NEXT_COMMAND,	0);
	SBVAL(req->in.hdr, SMB2_HDR_MESSAGE_ID,		0);
	SIVAL(req->in.hdr, SMB2_HDR_PID,		0);
	SIVAL(req->in.hdr, SMB2_HDR_TID,		0);
	SBVAL(req->in.hdr, SMB2_HDR_SESSION_ID,		0);
	memset(req->in.hdr+SMB2_HDR_SIGNATURE, 0, 16);

	/* this seems to be a bug, they use 0x24 but the length is 0x26 */
	SSVAL(req->in.body, 0x00, 0x24);

	SSVAL(req->in.body, 0x02, 1);
	memset(req->in.body+0x04, 0, 32);
	SSVAL(req->in.body, 0x24, SMB2_DIALECT_REVISION_202);

	smb2srv_negprot_recv(req);
	return;
nomem:
	smbsrv_terminate_connection(smb_req->smb_conn, nt_errstr(NT_STATUS_NO_MEMORY));
	talloc_free(req);
	return;
}
Ejemplo n.º 2
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);
}
Ejemplo n.º 3
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;
	}
}