Beispiel #1
0
NTSTATUS cli_query_security_descriptor(struct cli_state *cli,
				       uint16_t fnum,
				       uint32_t sec_info,
				       TALLOC_CTX *mem_ctx,
				       struct security_descriptor **sd)
{
	uint8_t param[8];
	uint8_t *rdata=NULL;
	uint32_t rdata_count=0;
	NTSTATUS status;
	struct security_descriptor *lsd;

	if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
		return cli_smb2_query_security_descriptor(cli,
							fnum,
							sec_info,
							mem_ctx,
							sd);
	}

	SIVAL(param, 0, fnum);
	SIVAL(param, 4, sec_info);

	status = cli_trans(talloc_tos(), cli, SMBnttrans,
			   NULL, -1, /* name, fid */
			   NT_TRANSACT_QUERY_SECURITY_DESC, 0, /* function, flags */
			   NULL, 0, 0, /* setup, length, max */
			   param, 8, 4, /* param, length, max */
			   NULL, 0, 0x10000, /* data, length, max */
			   NULL,	     /* recv_flags2 */
			   NULL, 0, NULL, /* rsetup, length */
			   NULL, 0, NULL,
			   &rdata, 0, &rdata_count);

	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(1, ("NT_TRANSACT_QUERY_SECURITY_DESC failed: %s\n",
			  nt_errstr(status)));
		goto cleanup;
	}

	status = unmarshall_sec_desc(mem_ctx, (uint8 *)rdata, rdata_count,
				     &lsd);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(10, ("unmarshall_sec_desc failed: %s\n",
			   nt_errstr(status)));
		goto cleanup;
	}

	if (sd != NULL) {
		*sd = lsd;
	} else {
		TALLOC_FREE(lsd);
	}

 cleanup:

	TALLOC_FREE(rdata);

	return status;
}
Beispiel #2
0
/****************************************************************************
check for existance of a trans2 call
****************************************************************************/
static NTSTATUS try_trans2(struct cli_state *cli, 
			 int op,
			 uint8_t *param, uint8_t *data,
			 uint32_t param_len, uint32_t data_len,
			 uint32_t *rparam_len, uint32_t *rdata_len)
{
	uint16_t setup[1];
	uint8_t *rparam=NULL, *rdata=NULL;
	NTSTATUS status;

	SSVAL(setup+0, 0, op);

	status = cli_trans(talloc_tos(), cli, SMBtrans2,
			   NULL, -1, /* name, fid */
			   op, 0,
			   NULL, 0, 0, /* setup */
			   param, param_len, 2,
			   data, data_len, CLI_BUFFER_SIZE,
			   NULL,		/* recv_flags2 */
			   NULL, 0, NULL,	/* rsetup */
			   &rparam, 0, rparam_len,
			   &rdata, 0, rdata_len);

	TALLOC_FREE(rdata);
	TALLOC_FREE(rparam);

	return status;
}
Beispiel #3
0
/****************************************************************************
check for existance of a nttrans call
****************************************************************************/
static NTSTATUS try_nttrans(struct cli_state *cli, 
			    int op,
			    uint8_t *param, uint8_t *data,
			    int32_t param_len, uint32_t data_len,
			    uint32_t *rparam_len,
			    uint32_t *rdata_len)
{
	uint8_t *rparam=NULL, *rdata=NULL;
	NTSTATUS status;

	status = cli_trans(talloc_tos(), cli, SMBnttrans,
			   NULL, -1, /* name, fid */
			   op, 0,
			   NULL, 0, 0, /* setup */
			   param, param_len, 2,
			   data, data_len, CLI_BUFFER_SIZE,
			   NULL,		/* recv_flags2 */
			   NULL, 0, NULL,	/* rsetup */
			   &rparam, 0, rparam_len,
			   &rdata, 0, rdata_len);
	SAFE_FREE(rdata);
	SAFE_FREE(rparam);

	return status;
}
Beispiel #4
0
NTSTATUS cli_get_user_quota(struct cli_state *cli, int quota_fnum,
			    SMB_NTQUOTA_STRUCT *pqt)
{
	uint16_t setup[1];
	uint8_t params[16];
	unsigned int data_len;
	uint8_t data[SID_MAX_SIZE+8];
	uint8_t *rparam, *rdata;
	uint32_t rparam_count, rdata_count;
	unsigned int sid_len;
	unsigned int offset;
	NTSTATUS status;

	if (!cli||!pqt) {
		smb_panic("cli_get_user_quota() called with NULL Pointer!");
	}

	SSVAL(setup + 0, 0, NT_TRANSACT_GET_USER_QUOTA);

	SSVAL(params, 0,quota_fnum);
	SSVAL(params, 2,TRANSACT_GET_USER_QUOTA_FOR_SID);
	SIVAL(params, 4,0x00000024);
	SIVAL(params, 8,0x00000000);
	SIVAL(params,12,0x00000024);

	sid_len = ndr_size_dom_sid(&pqt->sid, 0);
	data_len = sid_len+8;
	SIVAL(data, 0, 0x00000000);
	SIVAL(data, 4, sid_len);
	sid_linearize((char *)data+8, sid_len, &pqt->sid);

	status = cli_trans(talloc_tos(), cli, SMBnttrans,
			   NULL, -1, /* name, fid */
			   NT_TRANSACT_GET_USER_QUOTA, 0,
			   setup, 1, 0, /* setup */
			   params, 16, 4, /* params */
			   data, data_len, 112, /* data */
			   NULL,		/* recv_flags2 */
			   NULL, 0, NULL,	/* rsetup */
			   &rparam, 4, &rparam_count,
			   &rdata, 8, &rdata_count);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(1, ("NT_TRANSACT_GET_USER_QUOTA failed: %s\n",
			  nt_errstr(status)));
		return status;
	}

	if (!parse_user_quota_record(rdata, rdata_count, &offset, pqt)) {
		status = NT_STATUS_INVALID_NETWORK_RESPONSE;
		DEBUG(0,("Got INVALID NT_TRANSACT_GET_USER_QUOTA reply.\n"));
	}

	TALLOC_FREE(rparam);
	TALLOC_FREE(rdata);
	return status;
}
Beispiel #5
0
bool cli_api(struct cli_state *cli,
	     char *param, int prcnt, int mprcnt,
	     char *data, int drcnt, int mdrcnt,
	     char **rparam, unsigned int *rprcnt,
	     char **rdata, unsigned int *rdrcnt)
{
	NTSTATUS status;

	uint8_t *my_rparam, *my_rdata;
	uint32_t num_my_rparam, num_my_rdata;

	status = cli_trans(talloc_tos(), cli, SMBtrans,
			   PIPE_LANMAN, 0, /* name, fid */
			   0, 0,	   /* function, flags */
			   NULL, 0, 0,	   /* setup */
			   (uint8_t *)param, prcnt, mprcnt, /* Params, length, max */
			   (uint8_t *)data, drcnt, mdrcnt,  /* Data, length, max */
			   NULL,		 /* recv_flags2 */
			   NULL, 0, NULL,	 /* rsetup */
			   &my_rparam, 0, &num_my_rparam,
			   &my_rdata, 0, &num_my_rdata);
	if (!NT_STATUS_IS_OK(status)) {
		return false;
	}

	/*
	 * I know this memcpy massively hurts, but there are just tons
	 * of callers of cli_api that eventually need changing to
	 * talloc
	 */

	*rparam = (char *)smb_memdup(my_rparam, num_my_rparam);
	if (*rparam == NULL) {
		goto fail;
	}
	*rprcnt = num_my_rparam;
	TALLOC_FREE(my_rparam);

	*rdata = (char *)smb_memdup(my_rdata, num_my_rdata);
	if (*rdata == NULL) {
		goto fail;
	}
	*rdrcnt = num_my_rdata;
	TALLOC_FREE(my_rdata);

	return true;
fail:
	TALLOC_FREE(my_rdata);
	TALLOC_FREE(my_rparam);
	*rparam = NULL;
	*rprcnt = 0;
	*rdata = NULL;
	*rdrcnt = 0;
	return false;
}
Beispiel #6
0
NTSTATUS cli_get_fs_quota_info(struct cli_state *cli, int quota_fnum,
			       SMB_NTQUOTA_STRUCT *pqt)
{
	uint16_t setup[1];
	uint8_t param[2];
	uint8_t *rdata=NULL;
	uint32_t rdata_count=0;
	SMB_NTQUOTA_STRUCT qt;
	NTSTATUS status;

	ZERO_STRUCT(qt);

	if (!cli||!pqt) {
		smb_panic("cli_get_fs_quota_info() called with NULL Pointer!");
	}

	SSVAL(setup + 0, 0, TRANSACT2_QFSINFO);

	SSVAL(param,0,SMB_FS_QUOTA_INFORMATION);

	status = cli_trans(talloc_tos(), cli, SMBtrans2,
			   NULL, -1, /* name, fid */
			   0, 0,     /* function, flags */
			   setup, 1, 0, /* setup */
			   param, 2, 0, /* param */
			   NULL, 0, 560, /* data */
			   NULL,	 /* recv_flags2 */
			   NULL, 0, NULL, /* rsetup */
			   NULL, 0, NULL, /* rparam */
			   &rdata, 48, &rdata_count);

	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(1, ("SMB_FS_QUOTA_INFORMATION failed: %s\n",
			  nt_errstr(status)));
		return status;
	}

	/* unknown_1 24 NULL bytes in pdata*/

	/* the soft quotas 8 bytes (uint64_t)*/
	qt.softlim = BVAL(rdata,24);

	/* the hard quotas 8 bytes (uint64_t)*/
	qt.hardlim = BVAL(rdata,32);

	/* quota_flags 2 bytes **/
	qt.qflags = SVAL(rdata,40);

	qt.qtype = SMB_USER_FS_QUOTA_TYPE;

	*pqt = qt;

	TALLOC_FREE(rdata);
	return status;
}
Beispiel #7
0
NTSTATUS cli_set_fs_quota_info(struct cli_state *cli, int quota_fnum,
			       SMB_NTQUOTA_STRUCT *pqt)
{
	uint16_t setup[1];
	uint8_t param[4];
	uint8_t data[48];
	SMB_NTQUOTA_STRUCT qt;
	NTSTATUS status;
	ZERO_STRUCT(qt);
	memset(data,'\0',48);

	if (!cli||!pqt) {
		smb_panic("cli_set_fs_quota_info() called with NULL Pointer!");
	}

	SSVAL(setup + 0, 0,TRANSACT2_SETFSINFO);

	SSVAL(param,0,quota_fnum);
	SSVAL(param,2,SMB_FS_QUOTA_INFORMATION);

	/* Unknown1 24 NULL bytes*/

	/* Default Soft Quota 8 bytes */
	SBIG_UINT(data,24,pqt->softlim);

	/* Default Hard Quota 8 bytes */
	SBIG_UINT(data,32,pqt->hardlim);

	/* Quota flag 2 bytes */
	SSVAL(data,40,pqt->qflags);

	/* Unknown3 6 NULL bytes */

	status = cli_trans(talloc_tos(), cli, SMBtrans2,
			   NULL, -1, /* name, fid */
			   0, 0,     /* function, flags */
			   setup, 1, 0, /* setup */
			   param, 8, 0, /* param */
			   data, 48, 0, /* data */
			   NULL,	 /* recv_flags2 */
			   NULL, 0, NULL, /* rsetup */
			   NULL, 0, NULL, /* rparam */
			   NULL, 0, NULL); /* rdata */

	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(1, ("SMB_FS_QUOTA_INFORMATION failed: %s\n",
			  nt_errstr(status)));
	}

	return status;
}
Beispiel #8
0
NTSTATUS cli_set_user_quota(struct cli_state *cli, int quota_fnum,
			    SMB_NTQUOTA_STRUCT *pqt)
{
	uint16_t setup[1];
	uint8_t params[2];
	uint8_t data[112];
	unsigned int sid_len;	
	NTSTATUS status;

	memset(data,'\0',112);

	if (!cli||!pqt) {
		smb_panic("cli_set_user_quota() called with NULL Pointer!");
	}

	SSVAL(setup + 0, 0, NT_TRANSACT_SET_USER_QUOTA);

	SSVAL(params,0,quota_fnum);

	sid_len = ndr_size_dom_sid(&pqt->sid, 0);
	SIVAL(data,0,0);
	SIVAL(data,4,sid_len);
	SBIG_UINT(data, 8,(uint64_t)0);
	SBIG_UINT(data,16,pqt->usedspace);
	SBIG_UINT(data,24,pqt->softlim);
	SBIG_UINT(data,32,pqt->hardlim);
	sid_linearize((char *)data+40, sid_len, &pqt->sid);

	status = cli_trans(talloc_tos(), cli, SMBnttrans,
			   NULL, -1, /* name, fid */
			   NT_TRANSACT_SET_USER_QUOTA, 0,
			   setup, 1, 0, /* setup */
			   params, 2, 0, /* params */
			   data, 112, 0, /* data */
			   NULL,		/* recv_flags2 */
			   NULL, 0, NULL,	/* rsetup */
			   NULL, 0, NULL,	/* rparams */
			   NULL, 0, NULL);	/* rdata */

	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(1, ("NT_TRANSACT_SET_USER_QUOTA failed: %s\n",
			  nt_errstr(status)));
	}

	return status;
}
Beispiel #9
0
/****************************************************************************
  query the security descriptor for a open file
 ****************************************************************************/
struct security_descriptor *cli_query_secdesc(struct cli_state *cli, uint16_t fnum,
			    TALLOC_CTX *mem_ctx)
{
	uint8_t param[8];
	uint8_t *rdata=NULL;
	uint32_t rdata_count=0;
	struct security_descriptor *psd = NULL;
	NTSTATUS status;

	SIVAL(param, 0, fnum);
	SIVAL(param, 4, 0x7);

	status = cli_trans(talloc_tos(), cli, SMBnttrans,
			   NULL, -1, /* name, fid */
			   NT_TRANSACT_QUERY_SECURITY_DESC, 0, /* function, flags */
			   NULL, 0, 0, /* setup, length, max */
			   param, 8, 4, /* param, length, max */
			   NULL, 0, 0x10000, /* data, length, max */
			   NULL,	     /* recv_flags2 */
			   NULL, 0, NULL, /* rsetup, length */
			   NULL, 0, NULL,
			   &rdata, 0, &rdata_count);

	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(1, ("NT_TRANSACT_QUERY_SECURITY_DESC failed: %s\n",
			  nt_errstr(status)));
		goto cleanup;
	}

	status = unmarshall_sec_desc(mem_ctx, (uint8 *)rdata, rdata_count,
				     &psd);

	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(10, ("unmarshall_sec_desc failed: %s\n",
			   nt_errstr(status)));
		goto cleanup;
	}

 cleanup:

	TALLOC_FREE(rdata);

	return psd;
}
Beispiel #10
0
/****************************************************************************
  set the security descriptor for a open file
 ****************************************************************************/
NTSTATUS cli_set_security_descriptor(struct cli_state *cli,
				     uint16_t fnum,
				     uint32_t sec_info,
				     const struct security_descriptor *sd)
{
	uint8_t param[8];
	uint8 *data;
	size_t len;
	NTSTATUS status;

	if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
		return cli_smb2_set_security_descriptor(cli,
							fnum,
							sec_info,
							sd);
	}

	status = marshall_sec_desc(talloc_tos(), sd, &data, &len);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(10, ("marshall_sec_desc failed: %s\n",
			   nt_errstr(status)));
		return status;
	}

	SIVAL(param, 0, fnum);
	SIVAL(param, 4, sec_info);

	status = cli_trans(talloc_tos(), cli, SMBnttrans,
			   NULL, -1, /* name, fid */
			   NT_TRANSACT_SET_SECURITY_DESC, 0,
			   NULL, 0, 0, /* setup */
			   param, 8, 0, /* param */
			   data, len, 0, /* data */
			   NULL,	 /* recv_flags2 */
			   NULL, 0, NULL, /* rsetup */
			   NULL, 0, NULL, /* rparam */
			   NULL, 0, NULL); /* rdata */
	TALLOC_FREE(data);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(1, ("Failed to send NT_TRANSACT_SET_SECURITY_DESC: %s\n",
			  nt_errstr(status)));
	}
	return status;
}
Beispiel #11
0
/****************************************************************************
  set the security descriptor for a open file
 ****************************************************************************/
NTSTATUS cli_set_secdesc(struct cli_state *cli, uint16_t fnum,
			 struct security_descriptor *sd)
{
	uint8_t param[8];
	uint32 sec_info = 0;
	uint8 *data;
	size_t len;
	NTSTATUS status;

	status = marshall_sec_desc(talloc_tos(), sd, &data, &len);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(10, ("marshall_sec_desc failed: %s\n",
			   nt_errstr(status)));
		return status;
	}

	SIVAL(param, 0, fnum);

	if (sd->dacl)
		sec_info |= SECINFO_DACL;
	if (sd->owner_sid)
		sec_info |= SECINFO_OWNER;
	if (sd->group_sid)
		sec_info |= SECINFO_GROUP;
	SSVAL(param, 4, sec_info);

	status = cli_trans(talloc_tos(), cli, SMBnttrans,
			   NULL, -1, /* name, fid */
			   NT_TRANSACT_SET_SECURITY_DESC, 0,
			   NULL, 0, 0, /* setup */
			   param, 8, 0, /* param */
			   data, len, 0, /* data */
			   NULL,	 /* recv_flags2 */
			   NULL, 0, NULL, /* rsetup */
			   NULL, 0, NULL, /* rparam */
			   NULL, 0, NULL); /* rdata */
	TALLOC_FREE(data);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(1, ("Failed to send NT_TRANSACT_SET_SECURITY_DESC: %s\n",
			  nt_errstr(status)));
	}
	return status;
}
Beispiel #12
0
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;
		}
	}
Beispiel #13
0
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 param_len = 0;
	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_t num_referrals;
	struct client_dfs_referral *referrals = NULL;
	NTSTATUS status;
	TALLOC_CTX *frame = talloc_stackframe();

	*num_refs = 0;
	*refs = NULL;

	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, smbXcli_conn_use_unicode(cli->conn),
				      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];

	if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
		DATA_BLOB in_input_buffer;
		DATA_BLOB in_output_buffer = data_blob_null;
		DATA_BLOB out_input_buffer = data_blob_null;
		DATA_BLOB out_output_buffer = data_blob_null;

		in_input_buffer.data = param;
		in_input_buffer.length = param_len;

		status = smb2cli_ioctl(cli->conn,
				       cli->timeout,
				       cli->smb2.session,
				       cli->smb2.tcon,
				       UINT64_MAX, /* in_fid_persistent */
				       UINT64_MAX, /* in_fid_volatile */
				       FSCTL_DFS_GET_REFERRALS,
				       0, /* in_max_input_length */
				       &in_input_buffer,
				       CLI_BUFFER_SIZE, /* in_max_output_length */
				       &in_output_buffer,
				       SMB2_IOCTL_FLAG_IS_FSCTL,
				       talloc_tos(),
				       &out_input_buffer,
				       &out_output_buffer);
		if (!NT_STATUS_IS_OK(status)) {
			goto out;
		}

		if (out_output_buffer.length < 4) {
			status = NT_STATUS_INVALID_NETWORK_RESPONSE;
			goto out;
		}

		recv_flags2 = FLAGS2_UNICODE_STRINGS;
		rdata = out_output_buffer.data;
		endp = (char *)rdata + out_output_buffer.length;
	} else {
		unsigned int data_len = 0;
		uint16_t setup[1];

		SSVAL(setup, 0, TRANSACT2_GET_DFS_REFERRAL);

		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_t ref_version;
		uint16_t ref_size;
		int i;
		uint16_t 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;
		}
	}
Beispiel #14
0
NTSTATUS cli_list_user_quota(struct cli_state *cli, int quota_fnum,
			     SMB_NTQUOTA_LIST **pqt_list)
{
	uint16_t setup[1];
	uint8_t params[16];
	uint8_t *rparam=NULL, *rdata=NULL;
	uint32_t rparam_count=0, rdata_count=0;
	unsigned int offset;
	const uint8_t *curdata = NULL;
	unsigned int curdata_count = 0;
	TALLOC_CTX *mem_ctx = NULL;
	SMB_NTQUOTA_STRUCT qt;
	SMB_NTQUOTA_LIST *tmp_list_ent;
	NTSTATUS status;

	if (!cli||!pqt_list) {
		smb_panic("cli_list_user_quota() called with NULL Pointer!");
	}

	SSVAL(setup + 0, 0, NT_TRANSACT_GET_USER_QUOTA);

	SSVAL(params, 0,quota_fnum);
	SSVAL(params, 2,TRANSACT_GET_USER_QUOTA_LIST_START);
	SIVAL(params, 4,0x00000000);
	SIVAL(params, 8,0x00000000);
	SIVAL(params,12,0x00000000);

	status = cli_trans(talloc_tos(), cli, SMBnttrans,
			   NULL, -1, /* name, fid */
			   NT_TRANSACT_GET_USER_QUOTA, 0,
			   setup, 1, 0, /* setup */
			   params, 16, 4, /* params */
			   NULL, 0, 2048, /* data */
			   NULL,		/* recv_flags2 */
			   NULL, 0, NULL,	/* rsetup */
			   &rparam, 0, &rparam_count,
			   &rdata, 0, &rdata_count);

	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(1, ("NT_TRANSACT_GET_USER_QUOTA failed: %s\n",
			  nt_errstr(status)));
		goto cleanup;
	}

	if (rdata_count == 0) {
		*pqt_list = NULL;
		return NT_STATUS_OK;
	}

	if ((mem_ctx=talloc_init("SMB_USER_QUOTA_LIST"))==NULL) {
		DEBUG(0,("talloc_init() failed\n"));
		return NT_STATUS_NO_MEMORY;
	}

	offset = 1;
	for (curdata=rdata,curdata_count=rdata_count;
		((curdata)&&(curdata_count>=8)&&(offset>0));
		curdata +=offset,curdata_count -= offset) {
		ZERO_STRUCT(qt);
		if (!parse_user_quota_record((const uint8_t *)curdata, curdata_count,
					     &offset, &qt)) {
			DEBUG(1,("Failed to parse the quota record\n"));
			goto cleanup;
		}

		if ((tmp_list_ent=talloc_zero(mem_ctx,SMB_NTQUOTA_LIST))==NULL) {
			DEBUG(0,("TALLOC_ZERO() failed\n"));
			talloc_destroy(mem_ctx);
			return NT_STATUS_NO_MEMORY;
		}

		if ((tmp_list_ent->quotas=talloc_zero(mem_ctx,SMB_NTQUOTA_STRUCT))==NULL) {
			DEBUG(0,("TALLOC_ZERO() failed\n"));
			talloc_destroy(mem_ctx);
			return NT_STATUS_NO_MEMORY;
		}

		memcpy(tmp_list_ent->quotas,&qt,sizeof(qt));
		tmp_list_ent->mem_ctx = mem_ctx;		

		DLIST_ADD((*pqt_list),tmp_list_ent);
	}

	SSVAL(params, 2,TRANSACT_GET_USER_QUOTA_LIST_CONTINUE);	
	while(1) {

		TALLOC_FREE(rparam);
		TALLOC_FREE(rdata);

		status = cli_trans(talloc_tos(), cli, SMBnttrans,
				   NULL, -1, /* name, fid */
				   NT_TRANSACT_GET_USER_QUOTA, 0,
				   setup, 1, 0, /* setup */
				   params, 16, 4, /* params */
				   NULL, 0, 2048, /* data */
				   NULL,		/* recv_flags2 */
				   NULL, 0, NULL,	/* rsetup */
				   &rparam, 0, &rparam_count,
				   &rdata, 0, &rdata_count);

		if (!NT_STATUS_IS_OK(status)) {
			DEBUG(1, ("NT_TRANSACT_GET_USER_QUOTA failed: %s\n",
				  nt_errstr(status)));
			goto cleanup;
		}

		if (rdata_count == 0) {
			break;
		}

		offset = 1;
		for (curdata=rdata,curdata_count=rdata_count;
			((curdata)&&(curdata_count>=8)&&(offset>0));
			curdata +=offset,curdata_count -= offset) {
			ZERO_STRUCT(qt);
			if (!parse_user_quota_record((const uint8_t *)curdata,
						     curdata_count, &offset,
						     &qt)) {
				DEBUG(1,("Failed to parse the quota record\n"));
				goto cleanup;
			}

			if ((tmp_list_ent=talloc_zero(mem_ctx,SMB_NTQUOTA_LIST))==NULL) {
				DEBUG(0,("TALLOC_ZERO() failed\n"));
				talloc_destroy(mem_ctx);
				goto cleanup;
			}

			if ((tmp_list_ent->quotas=talloc_zero(mem_ctx,SMB_NTQUOTA_STRUCT))==NULL) {
				DEBUG(0,("TALLOC_ZERO() failed\n"));
				talloc_destroy(mem_ctx);
				goto cleanup;
			}

			memcpy(tmp_list_ent->quotas,&qt,sizeof(qt));
			tmp_list_ent->mem_ctx = mem_ctx;		

			DLIST_ADD((*pqt_list),tmp_list_ent);
		}
	}

 cleanup:
	TALLOC_FREE(rparam);
	TALLOC_FREE(rdata);

	return status;
}