2023-12-18 23:13:56 +03:00
/*
2003-04-12 03:32:00 +04:00
Unix SMB / CIFS implementation .
client quota functions
Copyright ( C ) Stefan ( metze ) Metzmacher 2003
2008-10-05 18:14:27 +04:00
2003-04-12 03:32:00 +04:00
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
2007-07-09 23:25:36 +04:00
the Free Software Foundation ; either version 3 of the License , or
2003-04-12 03:32:00 +04:00
( at your option ) any later version .
2008-10-05 18:14:27 +04:00
2003-04-12 03:32:00 +04:00
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
2008-10-05 18:14:27 +04:00
2003-04-12 03:32:00 +04:00
You should have received a copy of the GNU General Public License
2007-07-10 04:52:41 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2003-04-12 03:32:00 +04:00
*/
# include "includes.h"
2011-05-06 13:47:43 +04:00
# include "libsmb/libsmb.h"
2010-05-28 04:19:32 +04:00
# include "../librpc/gen_ndr/ndr_security.h"
2010-08-18 18:44:47 +04:00
# include "fake_file.h"
2010-10-12 08:27:50 +04:00
# include "../libcli/security/security.h"
2011-02-25 02:03:01 +03:00
# include "trans2.h"
2016-09-12 22:38:15 +03:00
# include "../libcli/smb/smbXcli_base.h"
2017-05-26 17:01:17 +03:00
# include "librpc/gen_ndr/ndr_quota.h"
2003-04-12 03:32:00 +04:00
2009-05-01 02:26:43 +04:00
NTSTATUS cli_get_quota_handle ( struct cli_state * cli , uint16_t * quota_fnum )
2003-04-12 03:32:00 +04:00
{
2009-05-01 02:26:43 +04:00
return cli_ntcreate ( cli , FAKE_FILE_NAME_QUOTA_WIN32 ,
2003-04-12 03:32:00 +04:00
0x00000016 , DESIRED_ACCESS_PIPE ,
0x00000000 , FILE_SHARE_READ | FILE_SHARE_WRITE ,
2014-05-09 07:55:57 +04:00
FILE_OPEN , 0x00000000 , 0x03 , quota_fnum , NULL ) ;
2003-04-12 03:32:00 +04:00
}
void free_ntquota_list ( SMB_NTQUOTA_LIST * * qt_list )
{
2016-09-18 11:09:54 +03:00
if ( ! qt_list | | ! * qt_list ) {
2003-04-12 03:32:00 +04:00
return ;
2016-09-18 11:09:54 +03:00
}
2008-10-05 18:14:27 +04:00
2003-04-12 03:32:00 +04:00
if ( ( * qt_list ) - > mem_ctx )
talloc_destroy ( ( * qt_list ) - > mem_ctx ) ;
( * qt_list ) = NULL ;
2023-12-18 23:13:56 +03:00
return ;
2003-04-12 03:32:00 +04:00
}
2016-09-21 18:37:40 +03:00
bool add_record_to_ntquota_list ( TALLOC_CTX * mem_ctx ,
SMB_NTQUOTA_STRUCT * pqt ,
SMB_NTQUOTA_LIST * * pqt_list )
{
SMB_NTQUOTA_LIST * tmp_list_ent ;
if ( ( tmp_list_ent = talloc_zero ( mem_ctx , SMB_NTQUOTA_LIST ) ) = = NULL ) {
return false ;
}
if ( ( tmp_list_ent - > quotas = talloc_zero ( mem_ctx , SMB_NTQUOTA_STRUCT ) ) = =
NULL ) {
return false ;
}
* tmp_list_ent - > quotas = * pqt ;
tmp_list_ent - > mem_ctx = mem_ctx ;
DLIST_ADD ( ( * pqt_list ) , tmp_list_ent ) ;
return true ;
}
2016-09-12 22:33:12 +03:00
bool parse_user_quota_record ( const uint8_t * rdata ,
unsigned int rdata_count ,
unsigned int * offset ,
SMB_NTQUOTA_STRUCT * pqt )
2003-04-12 03:32:00 +04:00
{
2017-05-26 17:01:17 +03:00
struct file_quota_information info = { 0 } ;
TALLOC_CTX * frame = talloc_stackframe ( ) ;
DATA_BLOB blob ;
enum ndr_err_code err ;
bool result = false ;
2008-10-05 18:14:27 +04:00
2017-05-26 17:01:17 +03:00
blob . data = discard_const_p ( uint8_t , rdata ) ;
blob . length = rdata_count ;
err = ndr_pull_struct_blob (
& blob ,
frame ,
& info ,
( ndr_pull_flags_fn_t ) ndr_pull_file_quota_information ) ;
2003-04-12 03:32:00 +04:00
2017-05-26 17:01:17 +03:00
if ( ! NDR_ERR_CODE_IS_SUCCESS ( err ) ) {
goto out ;
2016-09-19 18:24:58 +03:00
}
2003-04-12 03:32:00 +04:00
2017-05-26 17:01:17 +03:00
* offset = info . next_entry_offset ;
2003-04-12 03:32:00 +04:00
2017-05-26 17:01:17 +03:00
ZERO_STRUCTP ( pqt ) ;
pqt - > usedspace = info . quota_used ;
2016-09-19 18:24:58 +03:00
2017-05-26 17:01:17 +03:00
pqt - > softlim = info . quota_threshold ;
2003-04-12 03:32:00 +04:00
2017-05-26 17:01:17 +03:00
pqt - > hardlim = info . quota_limit ;
2003-04-12 03:32:00 +04:00
2017-05-26 17:01:17 +03:00
pqt - > qtype = SMB_USER_QUOTA_TYPE ;
pqt - > sid = info . sid ;
result = true ;
out :
TALLOC_FREE ( frame ) ;
return result ;
2003-04-12 03:32:00 +04:00
}
2016-09-19 21:14:01 +03:00
NTSTATUS parse_user_quota_list ( const uint8_t * curdata ,
uint32_t curdata_count ,
TALLOC_CTX * mem_ctx ,
SMB_NTQUOTA_LIST * * pqt_list )
{
NTSTATUS status = NT_STATUS_OK ;
unsigned offset ;
SMB_NTQUOTA_STRUCT qt ;
while ( true ) {
ZERO_STRUCT ( qt ) ;
if ( ! parse_user_quota_record ( curdata , curdata_count , & offset ,
& qt ) ) {
DEBUG ( 1 , ( " Failed to parse the quota record \n " ) ) ;
status = NT_STATUS_INVALID_NETWORK_RESPONSE ;
break ;
}
if ( offset > curdata_count ) {
DEBUG ( 1 , ( " out of bounds offset in quota record \n " ) ) ;
status = NT_STATUS_INVALID_NETWORK_RESPONSE ;
break ;
}
if ( curdata + offset < curdata ) {
DEBUG ( 1 , ( " Pointer overflow in quota record \n " ) ) ;
status = NT_STATUS_INVALID_NETWORK_RESPONSE ;
break ;
}
2016-09-21 18:37:40 +03:00
if ( ! add_record_to_ntquota_list ( mem_ctx , & qt , pqt_list ) ) {
status = NT_STATUS_NO_MEMORY ;
break ;
}
2016-09-19 21:14:01 +03:00
curdata + = offset ;
curdata_count - = offset ;
if ( offset = = 0 ) {
break ;
}
}
return status ;
}
2016-09-20 06:45:03 +03:00
NTSTATUS parse_fs_quota_buffer ( const uint8_t * rdata ,
unsigned int rdata_count ,
SMB_NTQUOTA_STRUCT * pqt )
{
SMB_NTQUOTA_STRUCT qt ;
ZERO_STRUCT ( qt ) ;
if ( rdata_count < 48 ) {
/* minimum length is not enforced by SMB2 client.
*/
DEBUG ( 1 , ( " small returned fs quota buffer \n " ) ) ;
return NT_STATUS_INVALID_NETWORK_RESPONSE ;
}
/* 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 ;
return NT_STATUS_OK ;
}
2016-09-21 18:37:40 +03:00
NTSTATUS build_user_quota_buffer ( SMB_NTQUOTA_LIST * qt_list ,
uint32_t maxlen ,
TALLOC_CTX * mem_ctx ,
DATA_BLOB * outbuf ,
SMB_NTQUOTA_LIST * * end_ptr )
{
2017-05-26 17:01:17 +03:00
return fill_quota_buffer ( mem_ctx ,
qt_list ,
false ,
maxlen ,
outbuf ,
end_ptr ) ;
2016-09-21 18:37:40 +03:00
}
2016-09-21 23:58:33 +03:00
NTSTATUS build_fs_quota_buffer ( TALLOC_CTX * mem_ctx ,
const SMB_NTQUOTA_STRUCT * pqt ,
DATA_BLOB * blob ,
uint32_t maxlen )
{
uint8_t * buf ;
if ( maxlen > 0 & & maxlen < 48 ) {
return NT_STATUS_BUFFER_TOO_SMALL ;
}
* blob = data_blob_talloc_zero ( mem_ctx , 48 ) ;
if ( ! blob - > data ) {
return NT_STATUS_NO_MEMORY ;
}
buf = blob - > data ;
/* Unknown1 24 NULL bytes*/
SBIG_UINT ( buf , 0 , ( uint64_t ) 0 ) ;
SBIG_UINT ( buf , 8 , ( uint64_t ) 0 ) ;
SBIG_UINT ( buf , 16 , ( uint64_t ) 0 ) ;
/* Default Soft Quota 8 bytes */
SBIG_UINT ( buf , 24 , pqt - > softlim ) ;
/* Default Hard Quota 8 bytes */
SBIG_UINT ( buf , 32 , pqt - > hardlim ) ;
/* Quota flag 4 bytes */
SIVAL ( buf , 40 , pqt - > qflags ) ;
/* 4 padding bytes */
SIVAL ( buf , 44 , 0 ) ;
return NT_STATUS_OK ;
}
2011-01-16 10:34:58 +03:00
NTSTATUS cli_get_user_quota ( struct cli_state * cli , int quota_fnum ,
SMB_NTQUOTA_STRUCT * pqt )
2003-04-12 03:32:00 +04:00
{
2011-01-16 10:34:58 +03:00
uint16_t setup [ 1 ] ;
2017-05-26 17:01:17 +03:00
uint8_t * rparam = NULL , * rdata = NULL ;
2011-01-16 10:34:58 +03:00
uint32_t rparam_count , rdata_count ;
2003-04-12 03:32:00 +04:00
unsigned int sid_len ;
unsigned int offset ;
2017-05-26 17:01:17 +03:00
struct nttrans_query_quota_params get_quota = { 0 } ;
struct file_get_quota_info info = { 0 } ;
enum ndr_err_code err ;
2011-01-16 10:34:58 +03:00
NTSTATUS status ;
2017-05-26 17:01:17 +03:00
TALLOC_CTX * frame = talloc_stackframe ( ) ;
DATA_BLOB data_blob = data_blob_null ;
2017-05-26 18:01:53 +03:00
DATA_BLOB param_blob = data_blob_null ;
2003-04-12 03:32:00 +04:00
2007-06-16 01:58:49 +04:00
if ( ! cli | | ! pqt ) {
2003-04-12 03:32:00 +04:00
smb_panic ( " cli_get_user_quota() called with NULL Pointer! " ) ;
2007-06-16 01:58:49 +04:00
}
2003-04-12 03:32:00 +04:00
2016-09-12 22:38:15 +03:00
if ( smbXcli_conn_protocol ( cli - > conn ) > = PROTOCOL_SMB2_02 ) {
2017-05-26 17:01:17 +03:00
TALLOC_FREE ( frame ) ;
2016-09-12 22:38:15 +03:00
return cli_smb2_get_user_quota ( cli , quota_fnum , pqt ) ;
}
2017-05-26 17:01:17 +03:00
get_quota . fid = quota_fnum ;
get_quota . return_single_entry = 1 ;
get_quota . restart_scan = 0 ;
2008-10-05 18:14:27 +04:00
2010-05-10 02:42:06 +04:00
sid_len = ndr_size_dom_sid ( & pqt - > sid , 0 ) ;
2017-05-26 17:01:17 +03:00
info . next_entry_offset = 0 ;
info . sid_length = sid_len ;
info . sid = pqt - > sid ;
err = ndr_push_struct_blob (
& data_blob ,
frame ,
& info ,
( ndr_push_flags_fn_t ) ndr_push_file_get_quota_info ) ;
if ( ! NDR_ERR_CODE_IS_SUCCESS ( err ) ) {
status = NT_STATUS_INTERNAL_ERROR ;
goto out ;
}
get_quota . sid_list_length = data_blob . length ;
get_quota . start_sid_offset = data_blob . length ;
2017-05-26 18:01:53 +03:00
err = ndr_push_struct_blob (
& param_blob ,
frame ,
& get_quota ,
( ndr_push_flags_fn_t ) ndr_push_nttrans_query_quota_params ) ;
2017-05-26 17:01:17 +03:00
if ( ! NDR_ERR_CODE_IS_SUCCESS ( err ) ) {
status = NT_STATUS_INTERNAL_ERROR ;
goto out ;
}
2011-01-16 10:34:58 +03:00
status = cli_trans ( talloc_tos ( ) , cli , SMBnttrans ,
NULL , - 1 , /* name, fid */
NT_TRANSACT_GET_USER_QUOTA , 0 ,
setup , 1 , 0 , /* setup */
2017-05-26 18:01:53 +03:00
param_blob . data , param_blob . length , 4 , /* params */
2017-05-26 17:01:17 +03:00
data_blob . data , data_blob . length , 112 , /* data */
2011-01-16 10:34:58 +03:00
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 ) ) ) ;
2017-05-26 17:01:17 +03:00
goto out ;
2003-04-12 03:32:00 +04:00
}
2011-01-16 10:34:58 +03:00
if ( ! parse_user_quota_record ( rdata , rdata_count , & offset , pqt ) ) {
status = NT_STATUS_INVALID_NETWORK_RESPONSE ;
2003-04-12 03:32:00 +04:00
DEBUG ( 0 , ( " Got INVALID NT_TRANSACT_GET_USER_QUOTA reply. \n " ) ) ;
}
2017-05-26 17:01:17 +03:00
out :
2011-01-16 10:34:58 +03:00
TALLOC_FREE ( rparam ) ;
TALLOC_FREE ( rdata ) ;
2017-05-26 17:01:17 +03:00
TALLOC_FREE ( frame ) ;
2011-01-16 10:34:58 +03:00
return status ;
2003-04-12 03:32:00 +04:00
}
2016-09-21 18:37:40 +03:00
NTSTATUS
cli_set_user_quota ( struct cli_state * cli , int quota_fnum , SMB_NTQUOTA_LIST * qtl )
2003-04-12 03:32:00 +04:00
{
2011-01-16 13:33:35 +03:00
uint16_t setup [ 1 ] ;
uint8_t params [ 2 ] ;
2016-09-21 18:37:40 +03:00
DATA_BLOB data = data_blob_null ;
2019-08-09 18:02:18 +03:00
NTSTATUS status ;
2008-10-05 18:14:27 +04:00
2016-09-21 18:37:40 +03:00
if ( ! cli | | ! qtl ) {
2003-04-12 03:32:00 +04:00
smb_panic ( " cli_set_user_quota() called with NULL Pointer! " ) ;
2007-06-16 01:58:49 +04:00
}
2003-04-12 03:32:00 +04:00
2016-09-21 19:35:39 +03:00
if ( smbXcli_conn_protocol ( cli - > conn ) > = PROTOCOL_SMB2_02 ) {
return cli_smb2_set_user_quota ( cli , quota_fnum , qtl ) ;
}
2016-09-21 18:37:40 +03:00
status = build_user_quota_buffer ( qtl , 0 , talloc_tos ( ) , & data , NULL ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2017-05-26 17:01:17 +03:00
/*
* smb1 doesn ' t send NT_STATUS_NO_MORE_ENTRIES so swallow
* this status .
*/
2019-08-09 18:06:20 +03:00
if ( ! NT_STATUS_EQUAL ( status , NT_STATUS_NO_MORE_ENTRIES ) ) {
2017-05-26 17:01:17 +03:00
goto cleanup ;
}
2016-09-21 18:37:40 +03:00
}
2011-01-16 13:33:35 +03:00
SSVAL ( setup + 0 , 0 , NT_TRANSACT_SET_USER_QUOTA ) ;
2003-04-12 03:32:00 +04:00
SSVAL ( params , 0 , quota_fnum ) ;
2011-01-16 13:33:35 +03:00
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 */
2016-09-21 18:37:40 +03:00
data . data , data . length , 0 , /* data */
2011-01-16 13:33:35 +03:00
NULL , /* recv_flags2 */
NULL , 0 , NULL , /* rsetup */
NULL , 0 , NULL , /* rparams */
NULL , 0 , NULL ) ; /* rdata */
2003-04-12 03:32:00 +04:00
2011-01-16 13:33:35 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 1 , ( " NT_TRANSACT_SET_USER_QUOTA failed: %s \n " ,
nt_errstr ( status ) ) ) ;
2003-04-12 03:32:00 +04:00
}
2016-09-21 18:37:40 +03:00
cleanup :
data_blob_free ( & data ) ;
2011-01-16 13:33:35 +03:00
return status ;
2003-04-12 03:32:00 +04:00
}
2016-09-18 11:13:16 +03:00
static NTSTATUS cli_list_user_quota_step ( struct cli_state * cli ,
TALLOC_CTX * mem_ctx ,
int quota_fnum ,
SMB_NTQUOTA_LIST * * pqt_list ,
bool first )
2003-04-12 03:32:00 +04:00
{
2011-01-16 13:53:03 +03:00
uint16_t setup [ 1 ] ;
2017-05-26 17:01:17 +03:00
DATA_BLOB params_blob = data_blob_null ;
2011-01-16 13:53:03 +03:00
uint8_t * rparam = NULL , * rdata = NULL ;
uint32_t rparam_count = 0 , rdata_count = 0 ;
NTSTATUS status ;
2017-05-26 17:01:17 +03:00
struct nttrans_query_quota_params quota_params = { 0 } ;
enum ndr_err_code err ;
2003-04-12 03:32:00 +04:00
2017-05-26 17:01:17 +03:00
TALLOC_CTX * frame = NULL ;
2016-09-19 22:17:10 +03:00
if ( smbXcli_conn_protocol ( cli - > conn ) > = PROTOCOL_SMB2_02 ) {
return cli_smb2_list_user_quota_step ( cli , mem_ctx , quota_fnum ,
pqt_list , first ) ;
}
2017-05-26 17:01:17 +03:00
frame = talloc_stackframe ( ) ;
2016-09-19 22:17:10 +03:00
2011-01-16 13:53:03 +03:00
SSVAL ( setup + 0 , 0 , NT_TRANSACT_GET_USER_QUOTA ) ;
2003-04-12 03:32:00 +04:00
2017-05-26 17:01:17 +03:00
quota_params . fid = quota_fnum ;
if ( first ) {
quota_params . restart_scan = 1 ;
}
err = ndr_push_struct_blob (
& params_blob ,
frame ,
& quota_params ,
( ndr_push_flags_fn_t ) ndr_push_nttrans_query_quota_params ) ;
if ( ! NDR_ERR_CODE_IS_SUCCESS ( err ) ) {
status = NT_STATUS_INVALID_PARAMETER ;
goto cleanup ;
}
2008-10-05 18:14:27 +04:00
2011-01-16 13:53:03 +03:00
status = cli_trans ( talloc_tos ( ) , cli , SMBnttrans ,
NULL , - 1 , /* name, fid */
NT_TRANSACT_GET_USER_QUOTA , 0 ,
setup , 1 , 0 , /* setup */
2017-05-26 17:01:17 +03:00
params_blob . data , params_blob . length , 4 , /* params */
2011-01-16 13:53:03 +03:00
NULL , 0 , 2048 , /* data */
NULL , /* recv_flags2 */
NULL , 0 , NULL , /* rsetup */
& rparam , 0 , & rparam_count ,
& rdata , 0 , & rdata_count ) ;
2003-04-12 03:32:00 +04:00
2016-09-18 11:13:16 +03:00
/* compat. with smbd + safeguard against
* endless loop
*/
2016-09-19 21:14:01 +03:00
if ( NT_STATUS_IS_OK ( status ) & & rdata_count = = 0 ) {
2016-09-18 11:13:16 +03:00
status = NT_STATUS_NO_MORE_ENTRIES ;
2003-04-12 03:32:00 +04:00
}
2016-09-19 21:14:01 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto cleanup ;
2003-04-12 03:32:00 +04:00
}
2016-09-19 21:14:01 +03:00
status = parse_user_quota_list ( rdata , rdata_count , mem_ctx , pqt_list ) ;
2016-09-18 11:13:16 +03:00
cleanup :
TALLOC_FREE ( rparam ) ;
TALLOC_FREE ( rdata ) ;
2017-05-26 17:01:17 +03:00
TALLOC_FREE ( frame ) ;
2008-10-05 18:14:27 +04:00
2016-09-18 11:13:16 +03:00
return status ;
}
2003-04-12 03:32:00 +04:00
2016-09-18 11:13:16 +03:00
NTSTATUS cli_list_user_quota ( struct cli_state * cli ,
int quota_fnum ,
SMB_NTQUOTA_LIST * * pqt_list )
{
NTSTATUS status ;
TALLOC_CTX * mem_ctx = NULL ;
bool first = true ;
if ( ! cli | | ! pqt_list ) {
smb_panic ( " cli_list_user_quota() called with NULL Pointer! " ) ;
2003-04-12 03:32:00 +04:00
}
2016-09-18 11:13:16 +03:00
* pqt_list = NULL ;
if ( ( mem_ctx = talloc_init ( " SMB_USER_QUOTA_LIST " ) ) = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
do {
status = cli_list_user_quota_step ( cli , mem_ctx , quota_fnum ,
pqt_list , first ) ;
first = false ;
} while ( NT_STATUS_IS_OK ( status ) ) ;
if ( NT_STATUS_EQUAL ( status , NT_STATUS_NO_MORE_ENTRIES ) ) {
status = NT_STATUS_OK ;
}
if ( ! NT_STATUS_IS_OK ( status ) | | * pqt_list = = NULL ) {
TALLOC_FREE ( mem_ctx ) ;
}
2008-10-05 18:14:27 +04:00
2011-01-16 13:53:03 +03:00
return status ;
2003-04-12 03:32:00 +04:00
}
2011-01-16 14:03:07 +03:00
NTSTATUS cli_get_fs_quota_info ( struct cli_state * cli , int quota_fnum ,
SMB_NTQUOTA_STRUCT * pqt )
2003-04-12 03:32:00 +04:00
{
2011-01-16 14:03:07 +03:00
uint16_t setup [ 1 ] ;
uint8_t param [ 2 ] ;
uint8_t * rdata = NULL ;
uint32_t rdata_count = 0 ;
NTSTATUS status ;
2007-06-16 01:58:49 +04:00
if ( ! cli | | ! pqt ) {
2003-04-12 03:32:00 +04:00
smb_panic ( " cli_get_fs_quota_info() called with NULL Pointer! " ) ;
2007-06-16 01:58:49 +04:00
}
2003-04-12 03:32:00 +04:00
2016-09-20 06:46:28 +03:00
if ( smbXcli_conn_protocol ( cli - > conn ) > = PROTOCOL_SMB2_02 ) {
return cli_smb2_get_fs_quota_info ( cli , quota_fnum , pqt ) ;
}
2011-01-16 14:03:07 +03:00
SSVAL ( setup + 0 , 0 , TRANSACT2_QFSINFO ) ;
2008-10-05 18:14:27 +04:00
2003-04-12 03:32:00 +04:00
SSVAL ( param , 0 , SMB_FS_QUOTA_INFORMATION ) ;
2008-10-05 18:14:27 +04:00
2011-01-16 14:03:07 +03:00
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 ) ;
2003-04-12 03:32:00 +04:00
2011-01-16 14:03:07 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 1 , ( " SMB_FS_QUOTA_INFORMATION failed: %s \n " ,
nt_errstr ( status ) ) ) ;
return status ;
2003-04-12 03:32:00 +04:00
}
2008-10-05 18:14:27 +04:00
2016-09-20 06:45:03 +03:00
status = parse_fs_quota_buffer ( rdata , rdata_count , pqt ) ;
2003-04-12 03:32:00 +04:00
2011-01-16 14:03:07 +03:00
TALLOC_FREE ( rdata ) ;
return status ;
2003-04-12 03:32:00 +04:00
}
2011-01-16 14:14:26 +03:00
NTSTATUS cli_set_fs_quota_info ( struct cli_state * cli , int quota_fnum ,
SMB_NTQUOTA_STRUCT * pqt )
2003-04-12 03:32:00 +04:00
{
2011-01-16 14:14:26 +03:00
uint16_t setup [ 1 ] ;
uint8_t param [ 4 ] ;
2016-09-21 23:58:33 +03:00
DATA_BLOB data = data_blob_null ;
2011-01-16 14:14:26 +03:00
NTSTATUS status ;
2003-04-12 03:32:00 +04:00
2007-06-16 01:58:49 +04:00
if ( ! cli | | ! pqt ) {
2003-04-12 03:32:00 +04:00
smb_panic ( " cli_set_fs_quota_info() called with NULL Pointer! " ) ;
2007-06-16 01:58:49 +04:00
}
2003-04-12 03:32:00 +04:00
2016-09-22 01:03:41 +03:00
if ( smbXcli_conn_protocol ( cli - > conn ) > = PROTOCOL_SMB2_02 ) {
return cli_smb2_set_fs_quota_info ( cli , quota_fnum , pqt ) ;
}
2016-09-21 23:58:33 +03:00
status = build_fs_quota_buffer ( talloc_tos ( ) , pqt , & data , 0 ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
2011-01-16 14:14:26 +03:00
SSVAL ( setup + 0 , 0 , TRANSACT2_SETFSINFO ) ;
2003-04-12 03:32:00 +04:00
SSVAL ( param , 0 , quota_fnum ) ;
SSVAL ( param , 2 , SMB_FS_QUOTA_INFORMATION ) ;
2011-01-16 14:14:26 +03:00
status = cli_trans ( talloc_tos ( ) , cli , SMBtrans2 ,
NULL , - 1 , /* name, fid */
0 , 0 , /* function, flags */
setup , 1 , 0 , /* setup */
2016-09-22 16:06:12 +03:00
param , 4 , 0 , /* param */
2016-09-21 23:58:33 +03:00
data . data , data . length , 0 , /* data */
2011-01-16 14:14:26 +03:00
NULL , /* recv_flags2 */
NULL , 0 , NULL , /* rsetup */
NULL , 0 , NULL , /* rparam */
NULL , 0 , NULL ) ; /* rdata */
2003-04-12 03:32:00 +04:00
2011-01-16 14:14:26 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 1 , ( " SMB_FS_QUOTA_INFORMATION failed: %s \n " ,
nt_errstr ( status ) ) ) ;
2003-04-12 03:32:00 +04:00
}
2011-01-16 14:14:26 +03:00
return status ;
2003-04-12 03:32:00 +04:00
}
2017-05-26 17:01:17 +03:00
NTSTATUS fill_quota_buffer ( TALLOC_CTX * mem_ctx ,
SMB_NTQUOTA_LIST * qlist ,
bool return_single ,
uint32_t max_data ,
DATA_BLOB * blob ,
SMB_NTQUOTA_LIST * * end_ptr )
{
2023-10-27 04:41:17 +03:00
ndr_flags_type ndr_flags = NDR_SCALARS | NDR_BUFFERS ;
2019-05-14 13:48:14 +03:00
struct ndr_push * qndr = NULL ;
2017-05-26 17:01:17 +03:00
uint32_t start_offset = 0 ;
uint32_t padding = 0 ;
if ( qlist = = NULL ) {
/* We must push at least one. */
return NT_STATUS_NO_MORE_ENTRIES ;
}
2019-05-14 13:48:14 +03:00
qndr = ndr_push_init_ctx ( mem_ctx ) ;
if ( qndr = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
2017-05-26 17:01:17 +03:00
for ( ; qlist ! = NULL ; qlist = qlist - > next ) {
struct file_quota_information info = { 0 } ;
enum ndr_err_code err ;
uint32_t dsize = sizeof ( info . next_entry_offset )
+ sizeof ( info . sid_length )
+ sizeof ( info . change_time )
+ sizeof ( info . quota_used )
+ sizeof ( info . quota_threshold )
+ sizeof ( info . quota_limit ) ;
info . sid_length = ndr_size_dom_sid ( & qlist - > quotas - > sid , 0 ) ;
if ( max_data ) {
uint32_t curr_pos_no_padding = qndr - > offset - padding ;
uint32_t payload = dsize + info . sid_length ;
uint32_t new_pos = ( curr_pos_no_padding + payload ) ;
if ( new_pos < curr_pos_no_padding ) {
/* Detect unlikely integer wrap */
DBG_ERR ( " Integer wrap while adjusting pos "
" 0x%x by offset 0x%x \n " ,
curr_pos_no_padding , payload ) ;
return NT_STATUS_INTERNAL_ERROR ;
}
if ( new_pos > max_data ) {
DBG_WARNING ( " Max data will be exceeded "
" writing next query info. "
" cur_pos 0x%x, sid_length 0x%x, "
" dsize 0x%x, max_data 0x%x \n " ,
curr_pos_no_padding ,
info . sid_length ,
dsize ,
max_data ) ;
break ;
}
}
start_offset = qndr - > offset ;
info . sid = qlist - > quotas - > sid ;
info . quota_used = qlist - > quotas - > usedspace ;
info . quota_threshold = qlist - > quotas - > softlim ;
info . quota_limit = qlist - > quotas - > hardlim ;
err = ndr_push_file_quota_information ( qndr ,
ndr_flags ,
& info ) ;
if ( ! NDR_ERR_CODE_IS_SUCCESS ( err ) ) {
DBG_DEBUG ( " Failed to push the quota sid \n " ) ;
return NT_STATUS_INTERNAL_ERROR ;
}
/* pidl will align to 8 bytes due to 8 byte members*/
/* Remember how much align padding we've used. */
padding = qndr - > offset ;
2018-08-08 11:14:26 +03:00
err = ndr_push_align ( qndr , 8 ) ;
if ( ! NDR_ERR_CODE_IS_SUCCESS ( err ) ) {
DBG_DEBUG ( " ndr_push_align returned %s \n " ,
ndr_map_error2string ( err ) ) ;
return ndr_map_error2ntstatus ( err ) ;
}
2017-05-26 17:01:17 +03:00
padding = qndr - > offset - padding ;
/*
* Overwrite next_entry_offset for this entry now
* we know what it should be . We know we ' re using
* LIBNDR_FLAG_LITTLE_ENDIAN here so we can use
* SIVAL .
*/
info . next_entry_offset = qndr - > offset - start_offset ;
SIVAL ( qndr - > data , start_offset , info . next_entry_offset ) ;
if ( return_single ) {
break ;
}
}
if ( end_ptr ! = NULL ) {
* end_ptr = qlist ;
}
/* Remove the padding alignment on the last element pushed. */
blob - > length = qndr - > offset - padding ;
blob - > data = qndr - > data ;
/*
* Terminate the pushed array by setting next_entry_offset
* for the last element to zero .
*/
if ( blob - > length > = sizeof ( uint32_t ) ) {
SIVAL ( qndr - > data , start_offset , 0 ) ;
}
return NT_STATUS_OK ;
}