Ejemplo n.º 1
0
size_t clistr_push_fn(struct cli_state *cli,
			void *dest,
			const char *src,
			int dest_len,
			int flags)
{
	size_t buf_used = PTR_DIFF(dest, cli->outbuf);
	if (dest_len == -1) {
		if (((ptrdiff_t)dest < (ptrdiff_t)cli->outbuf) || (buf_used > cli->bufsize)) {
			DEBUG(0, ("Pushing string of 'unlimited' length into non-SMB buffer!\n"));
			return push_string_base(cli->outbuf,
						(uint16_t)(cli_ucs2(cli) ? FLAGS2_UNICODE_STRINGS : 0),
						dest, src, -1, flags);
		}
		return push_string_base(cli->outbuf,
					(uint16_t)(cli_ucs2(cli) ? FLAGS2_UNICODE_STRINGS : 0),
					dest, src, cli->bufsize - buf_used,
					flags);
	}

	/* 'normal' push into size-specified buffer */
	return push_string_base(cli->outbuf,
				(uint16_t)(cli_ucs2(cli) ? FLAGS2_UNICODE_STRINGS : 0),
				dest, src, dest_len, flags);
}
Ejemplo n.º 2
0
Archivo: clidfs.c Proyecto: ekohl/samba
NTSTATUS cli_dfs_get_referral(TALLOC_CTX *ctx,
			struct cli_state *cli,
			const char *path,
			struct client_dfs_referral **refs,
			size_t *num_refs,
			size_t *consumed)
{
	unsigned int data_len = 0;
	unsigned int param_len = 0;
	uint16_t setup[1];
	uint16_t recv_flags2;
	uint8_t *param = NULL;
	uint8_t *rdata = NULL;
	char *p;
	char *endp;
	smb_ucs2_t *path_ucs;
	char *consumed_path = NULL;
	uint16_t consumed_ucs;
	uint16 num_referrals;
	struct client_dfs_referral *referrals = NULL;
	NTSTATUS status;
	TALLOC_CTX *frame = talloc_stackframe();

	*num_refs = 0;
	*refs = NULL;

	SSVAL(setup, 0, TRANSACT2_GET_DFS_REFERRAL);

	param = talloc_array(talloc_tos(), uint8_t, 2);
	if (!param) {
		status = NT_STATUS_NO_MEMORY;
		goto out;
	}
	SSVAL(param, 0, 0x03);	/* max referral level */

	param = trans2_bytes_push_str(param, cli_ucs2(cli),
				      path, strlen(path)+1,
				      NULL);
	if (!param) {
		status = NT_STATUS_NO_MEMORY;
		goto out;
	}
	param_len = talloc_get_size(param);
	path_ucs = (smb_ucs2_t *)&param[2];

	status = cli_trans(talloc_tos(), cli, SMBtrans2,
			   NULL, 0xffff, 0, 0,
			   setup, 1, 0,
			   param, param_len, 2,
			   NULL, 0, CLI_BUFFER_SIZE,
			   &recv_flags2,
			   NULL, 0, NULL, /* rsetup */
			   NULL, 0, NULL,
			   &rdata, 4, &data_len);
	if (!NT_STATUS_IS_OK(status)) {
		goto out;
	}

	endp = (char *)rdata + data_len;

	consumed_ucs  = SVAL(rdata, 0);
	num_referrals = SVAL(rdata, 2);

	/* consumed_ucs is the number of bytes
	 * of the UCS2 path consumed not counting any
	 * terminating null. We need to convert
	 * back to unix charset and count again
	 * to get the number of bytes consumed from
	 * the incoming path. */

	errno = 0;
	if (pull_string_talloc(talloc_tos(),
			NULL,
			0,
			&consumed_path,
			path_ucs,
			consumed_ucs,
			STR_UNICODE) == 0) {
		if (errno != 0) {
			status = map_nt_error_from_unix(errno);
		} else {
			status = NT_STATUS_INVALID_NETWORK_RESPONSE;
		}
		goto out;
	}
	if (consumed_path == NULL) {
		status = map_nt_error_from_unix(errno);
		goto out;
	}
	*consumed = strlen(consumed_path);

	if (num_referrals != 0) {
		uint16 ref_version;
		uint16 ref_size;
		int i;
		uint16 node_offset;

		referrals = talloc_array(ctx, struct client_dfs_referral,
					 num_referrals);

		if (!referrals) {
			status = NT_STATUS_NO_MEMORY;
			goto out;
		}
		/* start at the referrals array */

		p = (char *)rdata+8;
		for (i=0; i<num_referrals && p < endp; i++) {
			if (p + 18 > endp) {
				goto out;
			}
			ref_version = SVAL(p, 0);
			ref_size    = SVAL(p, 2);
			node_offset = SVAL(p, 16);

			if (ref_version != 3) {
				p += ref_size;
				continue;
			}

			referrals[i].proximity = SVAL(p, 8);
			referrals[i].ttl       = SVAL(p, 10);

			if (p + node_offset > endp) {
				status = NT_STATUS_INVALID_NETWORK_RESPONSE;
				goto out;
			}
			clistr_pull_talloc(referrals,
					   (const char *)rdata,
					   recv_flags2,
					   &referrals[i].dfspath,
					   p+node_offset,
					   PTR_DIFF(endp, p+node_offset),
					   STR_TERMINATE|STR_UNICODE);

			if (!referrals[i].dfspath) {
				status = map_nt_error_from_unix(errno);
				goto out;
			}
			p += ref_size;
		}
		if (i < num_referrals) {
			status = NT_STATUS_INVALID_NETWORK_RESPONSE;
			goto out;
		}
	}
Ejemplo n.º 3
0
struct tevent_req *cli_trans_send(
	TALLOC_CTX *mem_ctx, struct event_context *ev,
	struct cli_state *cli, uint8_t cmd,
	const char *pipe_name, uint16_t fid, uint16_t function, int flags,
	uint16_t *setup, uint8_t num_setup, uint8_t max_setup,
	uint8_t *param, uint32_t num_param, uint32_t max_param,
	uint8_t *data, uint32_t num_data, uint32_t max_data)
{
	struct tevent_req *req, *subreq;
	struct cli_trans_state *state;
	int iov_count;
	uint8_t wct;

	req = tevent_req_create(mem_ctx, &state, struct cli_trans_state);
	if (req == NULL) {
		return NULL;
	}

	if ((cmd == SMBtrans) || (cmd == SMBtrans2)) {
		if ((num_param > 0xffff) || (max_param > 0xffff)
		    || (num_data > 0xffff) || (max_data > 0xffff)) {
			DEBUG(3, ("Attempt to send invalid trans2 request "
				  "(setup %u, params %u/%u, data %u/%u)\n",
				  (unsigned)num_setup,
				  (unsigned)num_param, (unsigned)max_param,
				  (unsigned)num_data, (unsigned)max_data));
			tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
			return tevent_req_post(req, ev);
		}
	}

	/*
	 * The largest wct will be for nttrans (19+num_setup). Make sure we
	 * don't overflow state->vwv in cli_trans_format.
	 */

	if ((num_setup + 19) > ARRAY_SIZE(state->vwv)) {
		tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
		return tevent_req_post(req, ev);
	}

	state->cli = cli;
	state->ev = ev;
	state->cmd = cmd;
	state->flags = flags;
	state->num_rsetup = 0;
	state->rsetup = NULL;
	ZERO_STRUCT(state->rparam);
	ZERO_STRUCT(state->rdata);

	if ((pipe_name != NULL)
	    && (!convert_string_talloc(state, CH_UNIX,
				       cli_ucs2(cli) ? CH_UTF16LE : CH_DOS,
				       pipe_name, strlen(pipe_name) + 1,
				       &state->pipe_name_conv,
				       &state->pipe_name_conv_len, true))) {
		tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
		return tevent_req_post(req, ev);
	}
	state->fid = fid;	/* trans2 */
	state->function = function; /* nttrans */

	state->setup = setup;
	state->num_setup = num_setup;
	state->max_setup = max_setup;

	state->param = param;
	state->num_param = num_param;
	state->param_sent = 0;
	state->rparam.max = max_param;

	state->data = data;
	state->num_data = num_data;
	state->data_sent = 0;
	state->rdata.max = max_data;

	cli_trans_format(state, &wct, &iov_count);

	subreq = cli_smb_req_create(state, ev, cli, cmd, 0, wct, state->vwv,
				    iov_count, state->iov);
	if (tevent_req_nomem(subreq, req)) {
		return tevent_req_post(req, ev);
	}
	state->mid = cli_smb_req_mid(subreq);
	if (!cli_smb_req_send(subreq)) {
		tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
		return tevent_req_post(req, state->ev);
	}
	cli_state_seqnum_persistent(cli, state->mid);
	tevent_req_set_callback(subreq, cli_trans_done, req);
	return req;
}
Ejemplo n.º 4
0
/****************************************************************************
check for existance of a nttrans call
****************************************************************************/
static bool scan_nttrans(struct cli_state *cli, int op, int level, 
			int fnum, int dnum, const char *fname)
{
	uint32_t data_len = 0;
	uint32_t param_len = 0;
	uint32_t rparam_len, rdata_len;
	uint8_t *param = NULL;
	uint8_t data[DATA_SIZE];
	NTSTATUS status;
	const char *newfname;
	const char *dname;

	memset(data, 0, sizeof(data));
	data_len = 4;

	/* try with a info level only */
	TALLOC_FREE(param);
	param = talloc_array(talloc_tos(), uint8_t, 2);
	if (param == NULL) return True;

	SSVAL(param, 0, level);

	param_len = talloc_get_size(param);
	status = try_nttrans_len(cli, "void", op, level, param, data, param_len, &data_len, 
			    &rparam_len, &rdata_len);
	if (NT_STATUS_IS_OK(status)) return True;

	/* try with a file descriptor */
	TALLOC_FREE(param);
	param = talloc_array(talloc_tos(), uint8_t, 6);
	if (param == NULL) return True;

	SSVAL(param, 0, fnum);
	SSVAL(param, 2, level);
	SSVAL(param, 4, 0);

	param_len = talloc_get_size(param);
	status = try_nttrans_len(cli, "fnum", op, level, param, data, param_len, &data_len, 
				&rparam_len, &rdata_len);
	if (NT_STATUS_IS_OK(status)) return True;


	/* try with a notify style */
	TALLOC_FREE(param);
	param = talloc_array(talloc_tos(), uint8_t, 6);
	if (param == NULL) return True;

	SSVAL(param, 0, dnum);
	SSVAL(param, 2, dnum);
	SSVAL(param, 4, level);

	param_len = talloc_get_size(param);
	status = try_nttrans_len(cli, "notify", op, level, param, data, param_len, &data_len, 
				&rparam_len, &rdata_len);
	if (NT_STATUS_IS_OK(status)) return True;

	/* try with a file name */
	TALLOC_FREE(param);
	param = talloc_array(talloc_tos(), uint8_t, 6);
	if (param == NULL) return True;

	SSVAL(param, 0, level);
	SSVAL(param, 2, 0);
	SSVAL(param, 4, 0);
	param = trans2_bytes_push_str(param, cli_ucs2(cli),
				      fname, strlen(fname)+1, NULL);
	if (param == NULL) return True;

	param_len = talloc_get_size(param);
	status = try_nttrans_len(cli, "fname", op, level, param, data, param_len, &data_len, 
				&rparam_len, &rdata_len);
	if (NT_STATUS_IS_OK(status)) return True;

	/* try with a new file name */
	newfname = "\\newfile.dat";
	TALLOC_FREE(param);
	param = talloc_array(talloc_tos(), uint8_t, 6);
	if (param == NULL) return True;

	SSVAL(param, 0, level);
	SSVAL(param, 2, 0);
	SSVAL(param, 4, 0);
	param = trans2_bytes_push_str(param, cli_ucs2(cli),
				      newfname, strlen(newfname)+1, NULL);
	if (param == NULL) return True;

	param_len = talloc_get_size(param);
	status = try_nttrans_len(cli, "newfile", op, level, param, data, param_len, &data_len, 
				&rparam_len, &rdata_len);
	cli_unlink(cli, newfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
	cli_rmdir(cli, newfname);
	if (NT_STATUS_IS_OK(status)) return True;

	/* try dfs style  */
	dname = "\\testdir";
	cli_mkdir(cli, dname);
	TALLOC_FREE(param);
	param = talloc_array(talloc_tos(), uint8_t, 2);
	if (param == NULL) return True;

	SSVAL(param, 0, level);
	param = trans2_bytes_push_str(param, cli_ucs2(cli),
				      dname, strlen(dname)+1, NULL);
	if (param == NULL) return True;

	param_len = talloc_get_size(param);
	status = try_nttrans_len(cli, "dfs", op, level, param, data, param_len, &data_len, 
				&rparam_len, &rdata_len);
	cli_rmdir(cli, dname);
	if (NT_STATUS_IS_OK(status)) return True;

	return False;
}