1
0
mirror of https://github.com/samba-team/samba.git synced 2025-01-11 05:18:09 +03:00

s3/smbd: adjust smb1 server to use idl structs and generated ndr push/pull funcs

BUG: https://bugzilla.samba.org/show_bug.cgi?id=13553

Signed-off-by: Noel Power <noel.power@suse.com>
Reviewed-by: Jeremy Allison <jra@samba.org>
This commit is contained in:
Noel Power 2017-05-26 16:01:53 +01:00 committed by Noel Power
parent dd21b4fcfe
commit b8802e2713
3 changed files with 407 additions and 296 deletions

View File

@ -254,10 +254,10 @@ NTSTATUS cli_get_user_quota(struct cli_state *cli, int quota_fnum,
struct nttrans_query_quota_params get_quota = {0};
struct file_get_quota_info info = {0};
enum ndr_err_code err;
struct ndr_push *ndr_push = NULL;
NTSTATUS status;
TALLOC_CTX *frame = talloc_stackframe();
DATA_BLOB data_blob = data_blob_null;
DATA_BLOB param_blob = data_blob_null;
if (!cli||!pqt) {
smb_panic("cli_get_user_quota() called with NULL Pointer!");
@ -292,16 +292,11 @@ NTSTATUS cli_get_user_quota(struct cli_state *cli, int quota_fnum,
get_quota.sid_list_length = data_blob.length;
get_quota.start_sid_offset = data_blob.length;
ndr_push = ndr_push_init_ctx(frame);
if (!ndr_push) {
status = NT_STATUS_NO_MEMORY;
goto out;
}
err = ndr_push_nttrans_query_quota_params(ndr_push,
NDR_SCALARS | NDR_BUFFERS,
&get_quota);
err = ndr_push_struct_blob(
&param_blob,
frame,
&get_quota,
(ndr_push_flags_fn_t)ndr_push_nttrans_query_quota_params);
if (!NDR_ERR_CODE_IS_SUCCESS(err)) {
status = NT_STATUS_INTERNAL_ERROR;
@ -312,7 +307,7 @@ NTSTATUS cli_get_user_quota(struct cli_state *cli, int quota_fnum,
NULL, -1, /* name, fid */
NT_TRANSACT_GET_USER_QUOTA, 0,
setup, 1, 0, /* setup */
ndr_push->data, ndr_push->offset, 4, /* params */
param_blob.data, param_blob.length, 4, /* params */
data_blob.data, data_blob.length, 112, /* data */
NULL, /* recv_flags2 */
NULL, 0, NULL, /* rsetup */

View File

@ -30,6 +30,8 @@
#include "smbprofile.h"
#include "libsmb/libsmb.h"
#include "lib/util_ea.h"
#include "librpc/gen_ndr/ndr_quota.h"
#include "librpc/gen_ndr/ndr_security.h"
extern const struct generic_mapping file_generic_mapping;
@ -2293,6 +2295,263 @@ static void call_nt_transact_ioctl(connection_struct *conn,
#ifdef HAVE_SYS_QUOTAS
static enum ndr_err_code fill_qtlist_from_sids(TALLOC_CTX *mem_ctx,
struct files_struct *fsp,
SMB_NTQUOTA_HANDLE *qt_handle,
struct dom_sid *sids,
uint32_t elems)
{
int i;
TALLOC_CTX *list_ctx = NULL;
list_ctx = talloc_init("quota_sid_list");
if (list_ctx == NULL) {
DBG_ERR("failed to allocate\n");
return NDR_ERR_ALLOC;
}
if (qt_handle->quota_list!=NULL) {
free_ntquota_list(&(qt_handle->quota_list));
}
for (i = 0; i < elems; i++) {
SMB_NTQUOTA_STRUCT qt;
SMB_NTQUOTA_LIST *list_item;
if (!NT_STATUS_IS_OK(vfs_get_ntquota(fsp,
SMB_USER_QUOTA_TYPE,
&sids[i], &qt))) {
/* non fatal error, return empty item in result */
ZERO_STRUCT(qt);
continue;
}
list_item = talloc_zero(list_ctx, SMB_NTQUOTA_LIST);
if (list_item == NULL) {
DBG_ERR("failed to allocate\n");
return NDR_ERR_ALLOC;
}
sid_to_uid(&sids[i], &list_item->uid);
list_item->quotas = talloc_zero(list_item, SMB_NTQUOTA_STRUCT);
if (list_item->quotas == NULL) {
DBG_ERR("failed to allocate\n");
return NDR_ERR_ALLOC;
}
*list_item->quotas = qt;
list_item->mem_ctx = list_ctx;
DLIST_ADD(qt_handle->quota_list, list_item);
}
qt_handle->tmp_list = qt_handle->quota_list;
return NDR_ERR_SUCCESS;
}
static enum ndr_err_code extract_sids_from_buf(TALLOC_CTX *mem_ctx,
uint32_t sidlistlength,
DATA_BLOB *sid_buf,
struct dom_sid **sids,
uint32_t *num)
{
DATA_BLOB blob;
uint32_t i = 0;
enum ndr_err_code err;
struct sid_list_elem {
struct sid_list_elem *prev, *next;
struct dom_sid sid;
};
struct sid_list_elem *sid_list = NULL;
struct sid_list_elem *iter = NULL;
TALLOC_CTX *list_ctx = talloc_init("sid_list");
if (!list_ctx) {
DBG_ERR("OOM\n");
err = NDR_ERR_ALLOC;
goto done;
}
*num = 0;
*sids = NULL;
if (sidlistlength) {
uint32_t offset = 0;
struct ndr_pull *ndr_pull = NULL;
if (sidlistlength > sid_buf->length) {
DBG_ERR("sid_list_length 0x%x exceeds "
"available bytes %zx\n",
sidlistlength,
sid_buf->length);
err = NDR_ERR_OFFSET;
goto done;
}
while (true) {
struct file_get_quota_info info;
struct sid_list_elem *item = NULL;
uint32_t new_offset = 0;
blob.data = sid_buf->data + offset;
blob.length = sidlistlength - offset;
ndr_pull = ndr_pull_init_blob(&blob, list_ctx);
if (!ndr_pull) {
DBG_ERR("OOM\n");
err = NDR_ERR_ALLOC;
goto done;
}
err = ndr_pull_file_get_quota_info(ndr_pull,
NDR_SCALARS | NDR_BUFFERS, &info);
if (!NDR_ERR_CODE_IS_SUCCESS(err)) {
DBG_ERR("Failed to pull file_get_quota_info "
"from sidlist buffer\n");
goto done;
}
item = talloc_zero(list_ctx, struct sid_list_elem);
if (!item) {
DBG_ERR("OOM\n");
err = NDR_ERR_ALLOC;
goto done;
}
item->sid = info.sid;
DLIST_ADD(sid_list, item);
i++;
if (i == UINT32_MAX) {
DBG_ERR("Integer overflow\n");
err = NDR_ERR_ARRAY_SIZE;
goto done;
}
new_offset = info.next_entry_offset;
/* if new_offset == 0 no more sid(s) to read. */
if (new_offset == 0) {
break;
}
/* Integer wrap? */
if ((offset + new_offset) < offset) {
DBG_ERR("Integer wrap while adding "
"new_offset 0x%x to current "
"buffer offset 0x%x\n",
new_offset, offset);
err = NDR_ERR_OFFSET;
goto done;
}
offset += new_offset;
/* check if new offset is outside buffer boundry. */
if (offset >= sidlistlength) {
DBG_ERR("bufsize 0x%x exceeded by "
"new offset 0x%x)\n",
sidlistlength,
offset);
err = NDR_ERR_OFFSET;
goto done;
}
}
*sids = talloc_zero_array(mem_ctx, struct dom_sid, i);
if (!sids) {
DBG_ERR("OOM\n");
err = NDR_ERR_ALLOC;
goto done;
}
*num = i;
for (iter = sid_list, i = 0; iter; iter = iter->next, i++) {
(*sids)[i] = iter->sid;
DBG_DEBUG("quota SID[%u] %s\n",
(unsigned int)i,
sid_string_dbg(&iter->sid));
}
}
err = NDR_ERR_SUCCESS;
done:
TALLOC_FREE(list_ctx);
return err;
}
NTSTATUS smbd_do_query_getinfo_quota(TALLOC_CTX *mem_ctx,
files_struct *fsp,
bool restart_scan,
bool return_single,
uint32_t sid_list_length,
DATA_BLOB *sid_buf,
uint32_t max_data_count,
uint8_t **p_data,
uint32_t *p_data_size)
{
NTSTATUS status;
SMB_NTQUOTA_HANDLE *qt_handle = NULL;
SMB_NTQUOTA_LIST *qt_list = NULL;
DATA_BLOB blob = data_blob_null;
enum ndr_err_code err;
qt_handle =
(SMB_NTQUOTA_HANDLE *)fsp->fake_file_handle->private_data;
if (sid_list_length ) {
struct dom_sid *sids;
uint32_t elems = 0;
/*
* error check pulled offsets and lengths for wrap and
* exceeding available bytes.
*/
if (sid_list_length > sid_buf->length) {
DBG_ERR("sid_list_length 0x%x exceeds "
"available bytes %zx\n",
sid_list_length,
sid_buf->length);
return NT_STATUS_INVALID_PARAMETER;
}
err = extract_sids_from_buf(mem_ctx, sid_list_length,
sid_buf, &sids, &elems);
if (!NDR_ERR_CODE_IS_SUCCESS(err) || elems == 0) {
return NT_STATUS_INVALID_PARAMETER;
}
err = fill_qtlist_from_sids(mem_ctx,
fsp,
qt_handle,
sids,
elems);
if (!NDR_ERR_CODE_IS_SUCCESS(err)) {
return NT_STATUS_INVALID_PARAMETER;
}
} else if (restart_scan) {
if (vfs_get_user_ntquota_list(fsp,
&(qt_handle->quota_list))!=0) {
return NT_STATUS_INTERNAL_ERROR;
}
} else {
if (qt_handle->quota_list!=NULL &&
qt_handle->tmp_list==NULL) {
free_ntquota_list(&(qt_handle->quota_list));
}
}
if (restart_scan !=0 ) {
qt_list = qt_handle->quota_list;
} else {
qt_list = qt_handle->tmp_list;
}
status = fill_quota_buffer(mem_ctx, qt_list,
return_single != 0,
max_data_count,
&blob,
&qt_handle->tmp_list);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
if (blob.length > max_data_count) {
return NT_STATUS_BUFFER_TOO_SMALL;
}
*p_data = blob.data;
*p_data_size = blob.length;
return NT_STATUS_OK;
}
/****************************************************************************
Reply to get user quota
****************************************************************************/
@ -2310,268 +2569,117 @@ static void call_nt_transact_get_user_quota(connection_struct *conn,
NTSTATUS nt_status = NT_STATUS_OK;
char *params = *ppparams;
char *pdata = *ppdata;
char *entry;
int data_len=0,param_len=0;
int qt_len=0;
int entry_len = 0;
int data_len = 0;
int param_len = 0;
files_struct *fsp = NULL;
uint16_t level = 0;
size_t sid_len;
struct dom_sid sid;
bool start_enum = True;
SMB_NTQUOTA_STRUCT qt;
SMB_NTQUOTA_LIST *tmp_list;
SMB_NTQUOTA_HANDLE *qt_handle = NULL;
DATA_BLOB blob = data_blob_null;
struct nttrans_query_quota_params info = {0};
enum ndr_err_code err;
TALLOC_CTX *tmp_ctx = NULL;
uint32_t resp_len = 0;
uint8_t *resp_data = 0;
ZERO_STRUCT(qt);
tmp_ctx = talloc_init("ntquota_list");
if (!tmp_ctx) {
nt_status = NT_STATUS_NO_MEMORY;
goto error;
}
/* access check */
if (get_current_uid(conn) != sec_initial_uid()) {
DEBUG(1,("get_user_quota: access_denied service [%s] user "
"[%s]\n", lp_servicename(talloc_tos(), SNUM(conn)),
conn->session_info->unix_info->unix_name));
reply_nterror(req, NT_STATUS_ACCESS_DENIED);
return;
nt_status = NT_STATUS_ACCESS_DENIED;
goto error;
}
/*
* Ensure minimum number of parameters sent.
*/
blob.data = (uint8_t*)params;
blob.length = parameter_count;
if (parameter_count < 4) {
DEBUG(0,("TRANSACT_GET_USER_QUOTA: requires %d >= 4 bytes parameters\n",parameter_count));
reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
return;
err = ndr_pull_struct_blob(&blob, tmp_ctx, &info,
(ndr_pull_flags_fn_t)ndr_pull_nttrans_query_quota_params);
if (!NDR_ERR_CODE_IS_SUCCESS(err)) {
DEBUG(0,("TRANSACT_GET_USER_QUOTA: failed to pull "
"query_quota_params."));
nt_status = NT_STATUS_INVALID_PARAMETER;
goto error;
}
DBG_DEBUG("info.return_single_entry = %u, info.restart_scan = %u, "
"info.sid_list_length = %u, info.start_sid_length = %u, "
"info.start_sid_offset = %u\n",
(unsigned int)info.return_single_entry,
(unsigned int)info.restart_scan,
(unsigned int)info.sid_list_length,
(unsigned int)info.start_sid_length,
(unsigned int)info.start_sid_offset);
/* set blob to point at data for further parsing */
blob.data = (uint8_t*)pdata;
blob.length = data_count;
/*
* Although MS-SMB ref is ambiguous here, a microsoft client will
* only ever send a start sid (as part of a list) with
* sid_list_length & start_sid_offset both set to the actual list
* length. Note: Only a single result is returned in this case
* In the case where either start_sid_offset or start_sid_length
* are set alone or if both set (but have different values) then
* it seems windows will return a number of entries from the start
* of the list of users with quotas set. This behaviour is undocumented
* and windows clients do not send messages of that type. As such we
* currently will reject these requests.
*/
if (info.start_sid_length
|| (info.sid_list_length != info.start_sid_offset)) {
DBG_ERR("TRANSACT_GET_USER_QUOTA: unsupported single or "
"compound sid format\n");
nt_status = NT_STATUS_INVALID_PARAMETER;
goto error;
}
/* maybe we can check the quota_fnum */
fsp = file_fsp(req, SVAL(params,0));
fsp = file_fsp(req, info.fid);
if (!check_fsp_ntquota_handle(conn, req, fsp)) {
DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
reply_nterror(req, NT_STATUS_INVALID_HANDLE);
return;
nt_status = NT_STATUS_INVALID_HANDLE;
goto error;
}
nt_status = smbd_do_query_getinfo_quota(tmp_ctx,
fsp,
info.restart_scan,
info.return_single_entry,
info.sid_list_length,
&blob,
max_data_count,
&resp_data,
&resp_len);
if (!NT_STATUS_IS_OK(nt_status)) {
if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_NO_MORE_ENTRIES)) {
goto error;
}
nt_status = NT_STATUS_OK;
}
/* the NULL pointer checking for fsp->fake_file_handle->pd
* is done by CHECK_NTQUOTA_HANDLE_OK()
*/
qt_handle = (SMB_NTQUOTA_HANDLE *)fsp->fake_file_handle->private_data;
level = SVAL(params,2);
/* unknown 12 bytes leading in params */
switch (level) {
case TRANSACT_GET_USER_QUOTA_LIST_CONTINUE:
/* seems that we should continue with the enum here --metze */
if (qt_handle->quota_list!=NULL &&
qt_handle->tmp_list==NULL) {
/* free the list */
free_ntquota_list(&(qt_handle->quota_list));
/* Realloc the size of parameters and data we will return */
param_len = 4;
params = nttrans_realloc(ppparams, param_len);
if(params == NULL) {
reply_nterror(req, NT_STATUS_NO_MEMORY);
return;
}
data_len = 0;
SIVAL(params,0,data_len);
break;
}
start_enum = False;
FALL_THROUGH;
case TRANSACT_GET_USER_QUOTA_LIST_START:
if (qt_handle->quota_list==NULL &&
qt_handle->tmp_list==NULL) {
start_enum = True;
}
if (start_enum && vfs_get_user_ntquota_list(fsp,&(qt_handle->quota_list))!=0) {
reply_nterror(req, NT_STATUS_INTERNAL_ERROR);
return;
}
/* Realloc the size of parameters and data we will return */
param_len = 4;
params = nttrans_realloc(ppparams, param_len);
if(params == NULL) {
reply_nterror(req, NT_STATUS_NO_MEMORY);
return;
}
/* we should not trust the value in max_data_count*/
max_data_count = MIN(max_data_count,2048);
pdata = nttrans_realloc(ppdata, max_data_count);/* should be max data count from client*/
if(pdata == NULL) {
reply_nterror(req, NT_STATUS_NO_MEMORY);
return;
}
entry = pdata;
/* set params Size of returned Quota Data 4 bytes*/
/* but set it later when we know it */
/* for each entry push the data */
if (start_enum) {
qt_handle->tmp_list = qt_handle->quota_list;
}
tmp_list = qt_handle->tmp_list;
for (;((tmp_list!=NULL)&&((qt_len +40+SID_MAX_SIZE)<max_data_count));
tmp_list=tmp_list->next,entry+=entry_len,qt_len+=entry_len) {
sid_len = ndr_size_dom_sid(
&tmp_list->quotas->sid, 0);
entry_len = 40 + sid_len;
/* nextoffset entry 4 bytes */
SIVAL(entry,0,entry_len);
/* then the len of the SID 4 bytes */
SIVAL(entry,4,sid_len);
/* unknown data 8 bytes uint64_t */
SBIG_UINT(entry,8,(uint64_t)0); /* this is not 0 in windows...-metze*/
/* the used disk space 8 bytes uint64_t */
SBIG_UINT(entry,16,tmp_list->quotas->usedspace);
/* the soft quotas 8 bytes uint64_t */
SBIG_UINT(entry,24,tmp_list->quotas->softlim);
/* the hard quotas 8 bytes uint64_t */
SBIG_UINT(entry,32,tmp_list->quotas->hardlim);
/* and now the SID */
sid_linearize((uint8_t *)(entry+40), sid_len,
&tmp_list->quotas->sid);
}
qt_handle->tmp_list = tmp_list;
/* overwrite the offset of the last entry */
SIVAL(entry-entry_len,0,0);
data_len = 4+qt_len;
/* overwrite the params quota_data_len */
SIVAL(params,0,data_len);
break;
case TRANSACT_GET_USER_QUOTA_FOR_SID:
/* unknown 4 bytes IVAL(pdata,0) */
if (data_count < 8) {
DEBUG(0,("TRANSACT_GET_USER_QUOTA_FOR_SID: requires %d >= %d bytes data\n",data_count,8));
reply_nterror(req, NT_STATUS_INVALID_LEVEL);
return;
}
sid_len = IVAL(pdata,4);
/* Ensure this is less than 1mb. */
if (sid_len > (1024*1024)) {
reply_nterror(req, NT_STATUS_NO_MEMORY);
return;
}
if (data_count < 8+sid_len) {
DEBUG(0,("TRANSACT_GET_USER_QUOTA_FOR_SID: requires %d >= %lu bytes data\n",data_count,(unsigned long)(8+sid_len)));
reply_nterror(req, NT_STATUS_INVALID_LEVEL);
return;
}
data_len = 4+40+sid_len;
if (max_data_count < data_len) {
DEBUG(0,("TRANSACT_GET_USER_QUOTA_FOR_SID: max_data_count(%d) < data_len(%d)\n",
max_data_count, data_len));
param_len = 4;
SIVAL(params,0,data_len);
data_len = 0;
nt_status = NT_STATUS_BUFFER_TOO_SMALL;
break;
}
if (!sid_parse((const uint8_t *)(pdata+8), sid_len,
&sid)) {
reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
return;
}
nt_status = vfs_get_ntquota(fsp, SMB_USER_QUOTA_TYPE,
&sid, &qt);
if (!NT_STATUS_IS_OK(nt_status)) {
reply_nterror(req, nt_status);
return;
}
/* Realloc the size of parameters and data we will return */
param_len = 4;
params = nttrans_realloc(ppparams, param_len);
if(params == NULL) {
reply_nterror(req, NT_STATUS_NO_MEMORY);
return;
}
pdata = nttrans_realloc(ppdata, data_len);
if(pdata == NULL) {
reply_nterror(req, NT_STATUS_NO_MEMORY);
return;
}
entry = pdata;
/* set params Size of returned Quota Data 4 bytes*/
SIVAL(params,0,data_len);
/* nextoffset entry 4 bytes */
SIVAL(entry,0,0);
/* then the len of the SID 4 bytes */
SIVAL(entry,4,sid_len);
/* unknown data 8 bytes uint64_t */
SBIG_UINT(entry,8,(uint64_t)0); /* this is not 0 in windows...-mezte*/
/* the used disk space 8 bytes uint64_t */
SBIG_UINT(entry,16,qt.usedspace);
/* the soft quotas 8 bytes uint64_t */
SBIG_UINT(entry,24,qt.softlim);
/* the hard quotas 8 bytes uint64_t */
SBIG_UINT(entry,32,qt.hardlim);
/* and now the SID */
sid_linearize((uint8_t *)(entry+40), sid_len, &sid);
break;
default:
DEBUG(0, ("do_nt_transact_get_user_quota: %s: unknown "
"level 0x%04hX\n",
fsp_fnum_dbg(fsp), level));
reply_nterror(req, NT_STATUS_INVALID_LEVEL);
return;
break;
param_len = 4;
params = nttrans_realloc(ppparams, param_len);
if(params == NULL) {
nt_status = NT_STATUS_NO_MEMORY;
goto error;
}
data_len = resp_len;
SIVAL(params, 0, data_len);
pdata = nttrans_realloc(ppdata, data_len);
memcpy(pdata, resp_data, data_len);
TALLOC_FREE(tmp_ctx);
send_nt_replies(conn, req, nt_status, params, param_len,
pdata, data_len);
return;
error:
TALLOC_FREE(tmp_ctx);
reply_nterror(req, nt_status);
}
/****************************************************************************
@ -2592,10 +2700,13 @@ static void call_nt_transact_set_user_quota(connection_struct *conn,
char *pdata = *ppdata;
int data_len=0,param_len=0;
SMB_NTQUOTA_STRUCT qt;
size_t sid_len;
struct file_quota_information info = {0};
enum ndr_err_code err;
struct dom_sid sid;
DATA_BLOB inblob;
files_struct *fsp = NULL;
TALLOC_CTX *ctx = NULL;
NTSTATUS status = NT_STATUS_OK;
ZERO_STRUCT(qt);
/* access check */
@ -2603,8 +2714,8 @@ static void call_nt_transact_set_user_quota(connection_struct *conn,
DEBUG(1,("set_user_quota: access_denied service [%s] user "
"[%s]\n", lp_servicename(talloc_tos(), SNUM(conn)),
conn->session_info->unix_info->unix_name));
reply_nterror(req, NT_STATUS_ACCESS_DENIED);
return;
status = NT_STATUS_ACCESS_DENIED;
goto error;
}
/*
@ -2613,67 +2724,58 @@ static void call_nt_transact_set_user_quota(connection_struct *conn,
if (parameter_count < 2) {
DEBUG(0,("TRANSACT_SET_USER_QUOTA: requires %d >= 2 bytes parameters\n",parameter_count));
reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
return;
status = NT_STATUS_INVALID_PARAMETER;
goto error;
}
/* maybe we can check the quota_fnum */
fsp = file_fsp(req, SVAL(params,0));
if (!check_fsp_ntquota_handle(conn, req, fsp)) {
DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
reply_nterror(req, NT_STATUS_INVALID_HANDLE);
return;
status = NT_STATUS_INVALID_HANDLE;
goto error;
}
if (data_count < 40) {
DEBUG(0,("TRANSACT_SET_USER_QUOTA: requires %d >= %d bytes data\n",data_count,40));
reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
return;
ctx = talloc_init("set_user_quota");
if (!ctx) {
status = NT_STATUS_NO_MEMORY;
goto error;
}
inblob.data = (uint8_t*)pdata;
inblob.length = data_count;
/* offset to next quota record.
* 4 bytes IVAL(pdata,0)
* unused here...
*/
err = ndr_pull_struct_blob(
&inblob,
ctx,
&info,
(ndr_pull_flags_fn_t)ndr_pull_file_quota_information);
/* sid len */
sid_len = IVAL(pdata,4);
if (data_count < 40+sid_len || (40+sid_len < sid_len)) {
DEBUG(0,("TRANSACT_SET_USER_QUOTA: requires %d >= %lu bytes data\n",data_count,(unsigned long)40+sid_len));
reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
return;
if (!NDR_ERR_CODE_IS_SUCCESS(err)) {
DEBUG(0,("TRANSACT_SET_USER_QUOTA: failed to pull "
"file_quota_information\n"));
status = NT_STATUS_INVALID_PARAMETER;
goto error;
}
qt.usedspace = info.quota_used;
/* unknown 8 bytes in pdata
* maybe its the change time in NTTIME
*/
qt.softlim = info.quota_threshold;
/* the used space 8 bytes (uint64_t)*/
qt.usedspace = BVAL(pdata,16);
qt.hardlim = info.quota_limit;
/* the soft quotas 8 bytes (uint64_t)*/
qt.softlim = BVAL(pdata,24);
/* the hard quotas 8 bytes (uint64_t)*/
qt.hardlim = BVAL(pdata,32);
if (!sid_parse((const uint8_t *)(pdata+40), sid_len, &sid)) {
reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
return;
}
DEBUGADD(8,("SID: %s\n", sid_string_dbg(&sid)));
/* 44 unknown bytes left... */
sid = info.sid;
if (vfs_set_ntquota(fsp, SMB_USER_QUOTA_TYPE, &sid, &qt)!=0) {
reply_nterror(req, NT_STATUS_INTERNAL_ERROR);
return;
status = NT_STATUS_INTERNAL_ERROR;
goto error;
}
send_nt_replies(conn, req, NT_STATUS_OK, params, param_len,
pdata, data_len);
TALLOC_FREE(ctx);
return;
error:
TALLOC_FREE(ctx);
reply_nterror(req, status);
}
#endif /* HAVE_SYS_QUOTAS */

View File

@ -640,6 +640,20 @@ NTSTATUS smbd_do_query_security_desc(connection_struct *conn,
uint32_t max_data_count,
uint8_t **ppmarshalled_sd,
size_t *psd_size);
#ifdef HAVE_SYS_QUOTAS
struct smb2_query_quota_info;
NTSTATUS smbd_do_query_getinfo_quota(TALLOC_CTX *mem_ctx,
files_struct *fsp,
bool restart_scan,
bool return_single,
uint32_t sid_list_length,
DATA_BLOB *sidbuffer,
uint32_t max_data_count,
uint8_t **p_data,
uint32_t *p_data_size);
#endif
void reply_nttrans(struct smb_request *req);
void reply_nttranss(struct smb_request *req);