Esempio n. 1
0
/*
  add a blob to a smb2_create attribute blob
*/
NTSTATUS smb2_create_blob_add(TALLOC_CTX *mem_ctx, DATA_BLOB *blob, 
			      uint32_t tag,
			      DATA_BLOB add, BOOL last)
{
	NTSTATUS status;
	uint32_t ofs = blob->length;
	uint8_t pad = smb2_padding_size(add.length, 8);
	status = data_blob_realloc(mem_ctx, blob, blob->length + 0x18 + add.length + pad);
	NT_STATUS_NOT_OK_RETURN(status);
	
	if (last) {
		SIVAL(blob->data, ofs+0x00, 0);
	} else {
		SIVAL(blob->data, ofs+0x00, 0x18 + add.length + pad);
	}
	SSVAL(blob->data, ofs+0x04, 0x10); /* offset of tag */
	SIVAL(blob->data, ofs+0x06, 0x04); /* tag length */
	SSVAL(blob->data, ofs+0x0A, 0x18); /* offset of data */
	SIVAL(blob->data, ofs+0x0C, add.length);
	SIVAL(blob->data, ofs+0x10, tag);
	SIVAL(blob->data, ofs+0x14, 0); /* pad? */
	memcpy(blob->data+ofs+0x18, add.data, add.length);
	memset(blob->data+ofs+0x18+add.length, 0, pad);

	return NT_STATUS_OK;
}
Esempio n. 2
0
/*
  add a blob to a smb2_create attribute blob
*/
static NTSTATUS smb2_create_blob_push_one(TALLOC_CTX *mem_ctx, DATA_BLOB *buffer,
					  const struct smb2_create_blob *blob,
					  bool last)
{
	uint32_t ofs = buffer->length;
	size_t tag_length = strlen(blob->tag);
	size_t blob_offset = 0;
	size_t blob_pad = 0;
	size_t next_offset = 0;
	size_t next_pad = 0;
	bool ok;

	blob_offset = 0x10 + tag_length;
	blob_pad = smb2_create_blob_padding(blob_offset, 8);
	next_offset = blob_offset + blob_pad + blob->data.length;
	if (!last) {
		next_pad = smb2_create_blob_padding(next_offset, 8);
	}

	ok = data_blob_realloc(mem_ctx, buffer,
			       buffer->length + next_offset + next_pad);
	if (!ok) {
		return NT_STATUS_NO_MEMORY;
	}

	if (last) {
		SIVAL(buffer->data, ofs+0x00, 0);
	} else {
		SIVAL(buffer->data, ofs+0x00, next_offset + next_pad);
	}
	SSVAL(buffer->data, ofs+0x04, 0x10); /* offset of tag */
	SIVAL(buffer->data, ofs+0x06, tag_length); /* tag length */
	SSVAL(buffer->data, ofs+0x0A, blob_offset + blob_pad); /* offset of data */
	SIVAL(buffer->data, ofs+0x0C, blob->data.length);
	memcpy(buffer->data+ofs+0x10, blob->tag, tag_length);
	if (blob_pad > 0) {
		memset(buffer->data+ofs+blob_offset, 0, blob_pad);
		blob_offset += blob_pad;
	}
	memcpy(buffer->data+ofs+blob_offset, blob->data.data, blob->data.length);
	if (next_pad > 0) {
		memset(buffer->data+ofs+next_offset, 0, next_pad);
		next_offset += next_pad;
	}

	return NT_STATUS_OK;
}
Esempio n. 3
0
/*
  call this when the socket becomes readable to kick off the whole
  stream parsing process
*/
_PUBLIC_ void packet_recv(struct packet_context *pc)
{
	size_t npending;
	NTSTATUS status;
	size_t nread = 0;
	DATA_BLOB blob;
	bool recv_retry = false;

	if (pc->processing) {
		TEVENT_FD_NOT_READABLE(pc->fde);
		pc->processing++;
		return;
	}

	if (pc->recv_disable) {
		pc->recv_need_enable = true;
		TEVENT_FD_NOT_READABLE(pc->fde);
		return;
	}

	if (pc->packet_size != 0 && pc->num_read >= pc->packet_size) {
		goto next_partial;
	}

	if (pc->packet_size != 0) {
		/* we've already worked out how long this next packet is, so skip the
		   socket_pending() call */
		npending = pc->packet_size - pc->num_read;
	} else if (pc->initial_read != 0) {
		npending = pc->initial_read - pc->num_read;
	} else {
		if (pc->sock) {
			status = socket_pending(pc->sock, &npending);
		} else {
			status = NT_STATUS_CONNECTION_DISCONNECTED;
		}
		if (!NT_STATUS_IS_OK(status)) {
			packet_error(pc, status);
			return;
		}
	}

	if (npending == 0) {
		packet_eof(pc);
		return;
	}

again:

	if (npending + pc->num_read < npending) {
		packet_error(pc, NT_STATUS_INVALID_PARAMETER);
		return;
	}

	if (npending + pc->num_read < pc->num_read) {
		packet_error(pc, NT_STATUS_INVALID_PARAMETER);
		return;
	}

	/* possibly expand the partial packet buffer */
	if (npending + pc->num_read > pc->partial.length) {
		if (!data_blob_realloc(pc, &pc->partial, npending+pc->num_read)) {
			packet_error(pc, NT_STATUS_NO_MEMORY);
			return;
		}
	}

	if (pc->partial.length < pc->num_read + npending) {
		packet_error(pc, NT_STATUS_INVALID_PARAMETER);
		return;
	}

	if ((uint8_t *)pc->partial.data + pc->num_read < (uint8_t *)pc->partial.data) {
		packet_error(pc, NT_STATUS_INVALID_PARAMETER);
		return;
	}
	if ((uint8_t *)pc->partial.data + pc->num_read + npending < (uint8_t *)pc->partial.data) {
		packet_error(pc, NT_STATUS_INVALID_PARAMETER);
		return;
	}

	status = socket_recv(pc->sock, pc->partial.data + pc->num_read, 
			     npending, &nread);

	if (NT_STATUS_IS_ERR(status)) {
		packet_error(pc, status);
		return;
	}
	if (recv_retry && NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
		nread = 0;
		status = NT_STATUS_OK;
	}
	if (!NT_STATUS_IS_OK(status)) {
		return;
	}

	if (nread == 0 && !recv_retry) {
		packet_eof(pc);
		return;
	}

	pc->num_read += nread;

	if (pc->unreliable_select && nread != 0) {
		recv_retry = true;
		status = socket_pending(pc->sock, &npending);
		if (!NT_STATUS_IS_OK(status)) {
			packet_error(pc, status);
			return;
		}
		if (npending != 0) {
			goto again;
		}
	}

next_partial:
	if (pc->partial.length != pc->num_read) {
		if (!data_blob_realloc(pc, &pc->partial, pc->num_read)) {
			packet_error(pc, NT_STATUS_NO_MEMORY);
			return;
		}
	}

	/* see if its a full request */
	blob = pc->partial;
	blob.length = pc->num_read;
	status = pc->full_request(pc->private_data, blob, &pc->packet_size);
	if (NT_STATUS_IS_ERR(status)) {
		packet_error(pc, status);
		return;
	}
	if (!NT_STATUS_IS_OK(status)) {
		return;
	}

	if (pc->packet_size > pc->num_read) {
		/* the caller made an error */
		DEBUG(0,("Invalid packet_size %lu greater than num_read %lu\n",
			 (long)pc->packet_size, (long)pc->num_read));
		packet_error(pc, NT_STATUS_INVALID_PARAMETER);
		return;
	}

	/* it is a full request - give it to the caller */
	blob = pc->partial;
	blob.length = pc->num_read;

	if (pc->packet_size < pc->num_read) {
		pc->partial = data_blob_talloc(pc, blob.data + pc->packet_size, 
					       pc->num_read - pc->packet_size);
		if (pc->partial.data == NULL) {
			packet_error(pc, NT_STATUS_NO_MEMORY);
			return;
		}
		/* Trunate the blob sent to the caller to only the packet length */
		if (!data_blob_realloc(pc, &blob, pc->packet_size)) {
			packet_error(pc, NT_STATUS_NO_MEMORY);
			return;
		}
	} else {
		pc->partial = data_blob(NULL, 0);
	}
	pc->num_read -= pc->packet_size;
	pc->packet_size = 0;
	
	if (pc->serialise) {
		pc->processing = 1;
	}

	pc->busy = true;

	status = pc->callback(pc->private_data, blob);

	pc->busy = false;

	if (pc->destructor_called) {
		talloc_free(pc);
		return;
	}

	if (pc->processing) {
		if (pc->processing > 1) {
			TEVENT_FD_READABLE(pc->fde);
		}
		pc->processing = 0;
	}

	if (!NT_STATUS_IS_OK(status)) {
		packet_error(pc, status);
		return;
	}

	/* Have we consumed the whole buffer yet? */
	if (pc->partial.length == 0) {
		return;
	}

	/* we got multiple packets in one tcp read */
	if (pc->ev == NULL) {
		goto next_partial;
	}

	blob = pc->partial;
	blob.length = pc->num_read;

	status = pc->full_request(pc->private_data, blob, &pc->packet_size);
	if (NT_STATUS_IS_ERR(status)) {
		packet_error(pc, status);
		return;
	}

	if (!NT_STATUS_IS_OK(status)) {
		return;
	}

	tevent_add_timer(pc->ev, pc, timeval_zero(), packet_next_event, pc);
}
Esempio n. 4
0
static NTSTATUS nfs4acl_get_blob(struct vfs_handle_struct *handle,
				 files_struct *fsp,
				 const struct smb_filename *smb_fname_in,
				 TALLOC_CTX *mem_ctx,
				 DATA_BLOB *blob)
{
	struct nfs4acl_config *config = NULL;
	const struct smb_filename *smb_fname = NULL;
	size_t allocsize = 256;
	ssize_t length;
	bool ok;

	SMB_VFS_HANDLE_GET_DATA(handle, config,
				struct nfs4acl_config,
				return NT_STATUS_INTERNAL_ERROR);

	*blob = data_blob_null;

	if (fsp == NULL && smb_fname_in == NULL) {
		return NT_STATUS_INTERNAL_ERROR;
	}
	smb_fname = smb_fname_in;
	if (smb_fname == NULL) {
		smb_fname = fsp->fsp_name;
	}
	if (smb_fname == NULL) {
		return NT_STATUS_INTERNAL_ERROR;
	}

	ok = nfs4acl_validate_blob(handle, smb_fname);
	if (!ok) {
		return NT_STATUS_INTERNAL_ERROR;
	}

	do {
		int saved_errno = 0;

		allocsize *= 4;
		ok = data_blob_realloc(mem_ctx, blob, allocsize);
		if (!ok) {
			return NT_STATUS_NO_MEMORY;
		}

		become_root();
		if (fsp != NULL && fsp->fh->fd != -1) {
			length = SMB_VFS_NEXT_FGETXATTR(handle,
							fsp,
							config->xattr_name,
							blob->data,
							blob->length);
		} else {
			length = SMB_VFS_NEXT_GETXATTR(handle,
						       smb_fname,
						       config->xattr_name,
						       blob->data,
						       blob->length);
		}
		if (length == -1) {
			saved_errno = errno;
		}
		unbecome_root();
		if (saved_errno != 0) {
			errno = saved_errno;
		}
	} while (length == -1 && errno == ERANGE && allocsize <= 65536);

	if (length == -1) {
		return map_nt_error_from_unix(errno);
	}

	return NT_STATUS_OK;
}