示例#1
0
文件: request.c 项目: AIdrifter/samba
/*
  pull a uint32_t length/ uint16_t ofs/blob triple from a data blob
  the ptr points to the start of the offset/length pair
*/
NTSTATUS smb2_pull_s32o16_blob(struct smb2_request_buffer *buf, TALLOC_CTX *mem_ctx, uint8_t *ptr, DATA_BLOB *blob)
{
	uint32_t ofs, size;
	if (smb2_oob(buf, ptr, 8)) {
		return NT_STATUS_INVALID_PARAMETER;
	}
	size = IVAL(ptr, 0);
	ofs  = SVAL(ptr, 4);
	if (ofs == 0) {
		*blob = data_blob(NULL, 0);
		return NT_STATUS_OK;
	}
	if (smb2_oob(buf, buf->hdr + ofs, size)) {
		return NT_STATUS_INVALID_PARAMETER;
	}
	*blob = data_blob_talloc(mem_ctx, buf->hdr + ofs, size);
	NT_STATUS_HAVE_NO_MEMORY(blob->data);
	return NT_STATUS_OK;
}
示例#2
0
/*
  pull a uint32_t ofs/ uint32_t length/blob triple from a data blob
  the ptr points to the start of the offset/length pair
*/
NTSTATUS smb2_pull_o32s32_blob(struct smb2_request_buffer *buf, TALLOC_CTX *mem_ctx, uint8_t *ptr, DATA_BLOB *blob)
{
	uint32_t ofs, size;
	if (smb2_oob(buf, ptr, 8)) {
		return NT_STATUS_BUFFER_TOO_SMALL;
	}
	ofs  = IVAL(ptr, 0);
	size = IVAL(ptr, 4);
	if (ofs == 0 || size == 0) {
		*blob = data_blob(NULL, 0);
		return NT_STATUS_OK;
	}
	if (smb2_oob(buf, buf->hdr + ofs, size)) {
		return NT_STATUS_BUFFER_TOO_SMALL;
	}
	*blob = data_blob_talloc(mem_ctx, buf->hdr + ofs, size);
	NT_STATUS_HAVE_NO_MEMORY(blob->data);
	return NT_STATUS_OK;
}
示例#3
0
文件: request.c 项目: AIdrifter/samba
/*
  push a uint16_t ofs/ uint16_t length/blob triple into a data blob
  the ofs points to the start of the offset/length pair, and is relative
  to the body start
*/
NTSTATUS smb2_push_o16s16_blob(struct smb2_request_buffer *buf, 
			       uint16_t ofs, DATA_BLOB blob)
{
	NTSTATUS status;
	size_t offset;
	size_t padding_length;
	size_t padding_fix;
	uint8_t *ptr = buf->body+ofs;

	if (buf->dynamic == NULL) {
		return NT_STATUS_INVALID_PARAMETER;
	}

	/* we have only 16 bit for the size */
	if (blob.length > 0xFFFF) {
		return NT_STATUS_INVALID_PARAMETER;
	}

	/* check if there're enough room for ofs and size */
	if (smb2_oob(buf, ptr, 4)) {
		return NT_STATUS_INVALID_PARAMETER;
	}

	if (blob.data == NULL) {
		if (blob.length != 0) {
			return NT_STATUS_INTERNAL_ERROR;
		}
		SSVAL(ptr, 0, 0);
		SSVAL(ptr, 2, 0);
		return NT_STATUS_OK;
	}

	offset = buf->dynamic - buf->hdr;
	padding_length = smb2_padding_size(offset, 2);
	offset += padding_length;
	padding_fix = smb2_padding_fix(buf);

	SSVAL(ptr, 0, offset);
	SSVAL(ptr, 2, blob.length);

	status = smb2_grow_buffer(buf, blob.length + padding_length - padding_fix);
	NT_STATUS_NOT_OK_RETURN(status);

	memset(buf->dynamic, 0, padding_length);
	buf->dynamic += padding_length;

	memcpy(buf->dynamic, blob.data, blob.length);
	buf->dynamic += blob.length;

	buf->size += blob.length + padding_length - padding_fix;
	buf->body_size += blob.length + padding_length;

	return NT_STATUS_OK;
}
示例#4
0
/*
  push a uint32_t length/ uint32_t ofs/blob triple into a data blob
  the ofs points to the start of the length/offset pair, and is relative
  to the body start
*/
NTSTATUS smb2_push_s32o32_blob(struct smb2_request_buffer *buf, 
			       uint32_t ofs, DATA_BLOB blob)
{
	NTSTATUS status;
	size_t offset;
	size_t padding_length;
	size_t padding_fix;
	uint8_t *ptr = buf->body+ofs;

	if (buf->dynamic == NULL) {
		return NT_STATUS_INVALID_PARAMETER;
	}

	/* check if there're enough room for ofs and size */
	if (smb2_oob(buf, ptr, 8)) {
		return NT_STATUS_BUFFER_TOO_SMALL;
	}

	if (blob.length == 0) {
		SIVAL(ptr, 0, 0);
		SIVAL(ptr, 4, 0);
		return NT_STATUS_OK;
	}

	offset = buf->dynamic - buf->hdr;
	padding_length = smb2_padding_size(offset, 8);
	offset += padding_length;
	padding_fix = smb2_padding_fix(buf);

	SIVAL(ptr, 0, blob.length);
	SIVAL(ptr, 4, offset);

	status = smb2_grow_buffer(buf, blob.length + padding_length - padding_fix);
	NT_STATUS_NOT_OK_RETURN(status);

	memset(buf->dynamic, 0, padding_length);
	buf->dynamic += padding_length;

	memcpy(buf->dynamic, blob.data, blob.length);
	buf->dynamic += blob.length;

	buf->size += blob.length + padding_length - padding_fix;
	buf->body_size += blob.length + padding_length;

	return NT_STATUS_OK;
}
示例#5
0
文件: receive.c 项目: srimalik/samba
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);
}
示例#6
0
文件: receive.c 项目: srimalik/samba
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;
	}
}