2003-05-12 01:20:17 +00:00
/*
Unix SMB / CIFS implementation .
NT QUOTA suppport
Copyright ( C ) Stefan ( metze ) Metzmacher 2003
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 19:25:36 +00:00
the Free Software Foundation ; either version 3 of the License , or
2003-05-12 01:20:17 +00:00
( at your option ) any later version .
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 .
You should have received a copy of the GNU General Public License
2007-07-10 00:52:41 +00:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2003-05-12 01:20:17 +00:00
*/
# include "includes.h"
2011-03-22 16:57:01 +01:00
# include "smbd/smbd.h"
2011-03-02 16:06:32 +01:00
# include "../lib/util/util_pw.h"
2011-02-25 17:14:22 +01:00
# include "system/passwd.h"
2011-03-22 16:50:02 +01:00
# include "passdb/lookup_sid.h"
2011-05-06 11:47:43 +02:00
# include "libsmb/libsmb.h"
2018-12-10 13:04:11 +01:00
# include "libcli/security/dom_sid.h"
2003-05-12 01:20:17 +00:00
2004-01-15 08:49:30 +00:00
# undef DBGC_CLASS
# define DBGC_CLASS DBGC_QUOTA
2008-10-14 01:59:36 +02:00
static uint64_t limit_nt2unix ( uint64_t in , uint64_t bsize )
2003-05-12 01:20:17 +00:00
{
2008-10-14 01:59:36 +02:00
uint64_t ret = ( uint64_t ) 0 ;
2003-05-12 01:20:17 +00:00
2008-10-14 01:59:36 +02:00
ret = ( uint64_t ) ( in / bsize ) ;
2003-05-12 01:20:17 +00:00
if ( in > 0 & & ret = = 0 ) {
/* we have to make sure that a overflow didn't set NO_LIMIT */
2008-10-14 01:59:36 +02:00
ret = ( uint64_t ) 1 ;
2003-05-12 01:20:17 +00:00
}
if ( in = = SMB_NTQUOTAS_NO_LIMIT )
ret = SMB_QUOTAS_NO_LIMIT ;
else if ( in = = SMB_NTQUOTAS_NO_SPACE )
ret = SMB_QUOTAS_NO_SPACE ;
else if ( in = = SMB_NTQUOTAS_NO_ENTRY )
ret = SMB_QUOTAS_NO_LIMIT ;
return ret ;
}
2008-10-14 01:59:36 +02:00
static uint64_t limit_unix2nt ( uint64_t in , uint64_t bsize )
2003-05-12 01:20:17 +00:00
{
2008-10-14 01:59:36 +02:00
uint64_t ret = ( uint64_t ) 0 ;
2003-05-12 01:20:17 +00:00
2008-10-14 01:59:36 +02:00
ret = ( uint64_t ) ( in * bsize ) ;
2003-05-12 01:20:17 +00:00
return ret ;
}
2016-03-29 23:30:23 +03:00
NTSTATUS vfs_get_ntquota ( files_struct * fsp , enum SMB_QUOTA_TYPE qtype ,
struct dom_sid * psid , SMB_NTQUOTA_STRUCT * qt )
2003-05-12 01:20:17 +00:00
{
int ret ;
SMB_DISK_QUOTA D ;
unid_t id ;
2017-06-01 11:45:25 -07:00
struct smb_filename * smb_fname_cwd = NULL ;
int saved_errno = 0 ;
2003-05-12 01:20:17 +00:00
ZERO_STRUCT ( D ) ;
2016-03-29 23:30:23 +03:00
if ( ! fsp | | ! fsp - > conn | | ! qt ) {
return NT_STATUS_INTERNAL_ERROR ;
}
2003-05-12 01:20:17 +00:00
ZERO_STRUCT ( * qt ) ;
id . uid = - 1 ;
2006-02-03 22:19:41 +00:00
if ( psid & & ! sid_to_uid ( psid , & id . uid ) ) {
2018-12-10 13:04:11 +01:00
struct dom_sid_buf buf ;
2003-05-12 01:20:17 +00:00
DEBUG ( 0 , ( " sid_to_uid: failed, SID[%s] \n " ,
2018-12-10 13:04:11 +01:00
dom_sid_str_buf ( psid , & buf ) ) ) ;
2016-03-29 23:30:23 +03:00
return NT_STATUS_NO_SUCH_USER ;
2003-05-12 01:20:17 +00:00
}
2017-06-01 11:45:25 -07:00
smb_fname_cwd = synthetic_smb_fname ( talloc_tos ( ) ,
" . " ,
NULL ,
NULL ,
2020-04-30 11:48:32 +02:00
0 ,
2017-06-01 11:45:25 -07:00
0 ) ;
if ( smb_fname_cwd = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
ret = SMB_VFS_GET_QUOTA ( fsp - > conn , smb_fname_cwd , qtype , id , & D ) ;
if ( ret = = - 1 ) {
saved_errno = errno ;
}
TALLOC_FREE ( smb_fname_cwd ) ;
if ( saved_errno ! = 0 ) {
errno = saved_errno ;
}
2003-05-12 01:20:17 +00:00
if ( psid )
qt - > sid = * psid ;
if ( ret ! = 0 ) {
2016-03-29 23:30:23 +03:00
return map_nt_error_from_unix ( errno ) ;
2003-05-12 01:20:17 +00:00
}
2008-10-14 01:59:36 +02:00
qt - > usedspace = ( uint64_t ) D . curblocks * D . bsize ;
2003-05-12 01:20:17 +00:00
qt - > softlim = limit_unix2nt ( D . softlimit , D . bsize ) ;
qt - > hardlim = limit_unix2nt ( D . hardlimit , D . bsize ) ;
qt - > qflags = D . qflags ;
2016-03-29 23:30:23 +03:00
return NT_STATUS_OK ;
2003-05-12 01:20:17 +00:00
}
2010-05-21 11:25:01 +10:00
int vfs_set_ntquota ( files_struct * fsp , enum SMB_QUOTA_TYPE qtype , struct dom_sid * psid , SMB_NTQUOTA_STRUCT * qt )
2003-05-12 01:20:17 +00:00
{
int ret ;
SMB_DISK_QUOTA D ;
unid_t id ;
ZERO_STRUCT ( D ) ;
if ( ! fsp | | ! fsp - > conn | | ! qt )
return ( - 1 ) ;
id . uid = - 1 ;
2008-10-14 01:59:36 +02:00
D . bsize = ( uint64_t ) QUOTABLOCK_SIZE ;
2003-05-14 14:38:11 +00:00
2003-05-12 01:20:17 +00:00
D . softlimit = limit_nt2unix ( qt - > softlim , D . bsize ) ;
D . hardlimit = limit_nt2unix ( qt - > hardlim , D . bsize ) ;
D . qflags = qt - > qflags ;
2006-02-03 22:19:41 +00:00
if ( psid & & ! sid_to_uid ( psid , & id . uid ) ) {
2018-12-10 13:04:11 +01:00
struct dom_sid_buf buf ;
2003-05-12 01:20:17 +00:00
DEBUG ( 0 , ( " sid_to_uid: failed, SID[%s] \n " ,
2018-12-10 13:04:11 +01:00
dom_sid_str_buf ( psid , & buf ) ) ) ;
2003-05-12 01:20:17 +00:00
}
2003-05-14 10:59:01 +00:00
ret = SMB_VFS_SET_QUOTA ( fsp - > conn , qtype , id , & D ) ;
2003-05-12 01:20:17 +00:00
return ret ;
}
2017-02-18 09:02:09 +13:00
static bool already_in_quota_list ( SMB_NTQUOTA_LIST * qt_list , uid_t uid )
2003-05-12 01:20:17 +00:00
{
SMB_NTQUOTA_LIST * tmp_list = NULL ;
if ( ! qt_list )
return False ;
for ( tmp_list = qt_list ; tmp_list ! = NULL ; tmp_list = tmp_list - > next ) {
if ( tmp_list - > uid = = uid ) {
return True ;
}
}
return False ;
}
int vfs_get_user_ntquota_list ( files_struct * fsp , SMB_NTQUOTA_LIST * * qt_list )
{
struct passwd * usr ;
TALLOC_CTX * mem_ctx = NULL ;
if ( ! fsp | | ! fsp - > conn | | ! qt_list )
return ( - 1 ) ;
* qt_list = NULL ;
if ( ( mem_ctx = talloc_init ( " SMB_USER_QUOTA_LIST " ) ) = = NULL ) {
DEBUG ( 0 , ( " talloc_init() failed \n " ) ) ;
return ( - 1 ) ;
}
2012-03-24 15:23:02 +01:00
setpwent ( ) ;
while ( ( usr = getpwent ( ) ) ! = NULL ) {
2003-05-12 01:20:17 +00:00
SMB_NTQUOTA_STRUCT tmp_qt ;
SMB_NTQUOTA_LIST * tmp_list_ent ;
2010-05-21 11:25:01 +10:00
struct dom_sid sid ;
2018-12-10 13:04:11 +01:00
struct dom_sid_buf buf ;
2016-03-29 23:30:23 +03:00
NTSTATUS status ;
2003-05-12 01:20:17 +00:00
ZERO_STRUCT ( tmp_qt ) ;
2017-02-18 09:02:09 +13:00
if ( already_in_quota_list ( ( * qt_list ) , usr - > pw_uid ) ) {
DEBUG ( 5 , ( " record for uid[%ld] already in the list \n " , ( long ) usr - > pw_uid ) ) ;
2003-05-12 01:20:17 +00:00
continue ;
}
2006-02-03 22:19:41 +00:00
uid_to_sid ( & sid , usr - > pw_uid ) ;
2003-05-12 01:20:17 +00:00
2016-03-29 23:30:23 +03:00
status =
vfs_get_ntquota ( fsp , SMB_USER_QUOTA_TYPE , & sid , & tmp_qt ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2016-03-30 13:59:39 +03:00
DEBUG ( 5 , ( " failed getting quota for uid[%ld] - %s \n " ,
( long ) usr - > pw_uid , nt_errstr ( status ) ) ) ;
continue ;
}
if ( tmp_qt . softlim = = 0 & & tmp_qt . hardlim = = 0 ) {
2003-07-24 11:37:11 +00:00
DEBUG ( 5 , ( " no quota entry for sid[%s] path[%s] \n " ,
2018-12-10 13:04:11 +01:00
dom_sid_str_buf ( & sid , & buf ) ,
2007-12-15 21:11:36 +01:00
fsp - > conn - > connectpath ) ) ;
2003-05-12 01:20:17 +00:00
continue ;
}
DEBUG ( 15 , ( " quota entry for id[%s] path[%s] \n " ,
2018-12-10 13:04:11 +01:00
dom_sid_str_buf ( & sid , & buf ) ,
fsp - > conn - > connectpath ) ) ;
2003-05-12 01:20:17 +00:00
2011-06-07 11:44:43 +10:00
if ( ( tmp_list_ent = talloc_zero ( mem_ctx , SMB_NTQUOTA_LIST ) ) = = NULL ) {
2007-04-27 23:18:41 +00:00
DEBUG ( 0 , ( " TALLOC_ZERO() failed \n " ) ) ;
2003-05-12 01:20:17 +00:00
* qt_list = NULL ;
talloc_destroy ( mem_ctx ) ;
return ( - 1 ) ;
}
2011-06-07 11:44:43 +10:00
if ( ( tmp_list_ent - > quotas = talloc_zero ( mem_ctx , SMB_NTQUOTA_STRUCT ) ) = = NULL ) {
2007-04-27 23:18:41 +00:00
DEBUG ( 0 , ( " TALLOC_ZERO() failed \n " ) ) ;
2003-05-12 01:20:17 +00:00
* qt_list = NULL ;
talloc_destroy ( mem_ctx ) ;
return ( - 1 ) ;
}
tmp_list_ent - > uid = usr - > pw_uid ;
memcpy ( tmp_list_ent - > quotas , & tmp_qt , sizeof ( tmp_qt ) ) ;
tmp_list_ent - > mem_ctx = mem_ctx ;
DLIST_ADD ( ( * qt_list ) , tmp_list_ent ) ;
}
2012-03-24 15:23:02 +01:00
endpwent ( ) ;
2003-05-12 01:20:17 +00:00
2016-09-18 11:05:23 +03:00
if ( * qt_list = = NULL ) {
TALLOC_FREE ( mem_ctx ) ;
}
2003-05-12 01:20:17 +00:00
return 0 ;
}
2008-03-29 18:19:31 +01:00
static int quota_handle_destructor ( SMB_NTQUOTA_HANDLE * handle )
{
2016-09-18 11:09:54 +03:00
free_ntquota_list ( & handle - > quota_list ) ;
2008-03-29 18:19:31 +01:00
return 0 ;
}
2003-05-12 01:20:17 +00:00
void * init_quota_handle ( TALLOC_CTX * mem_ctx )
{
SMB_NTQUOTA_HANDLE * qt_handle ;
if ( ! mem_ctx )
2011-12-20 10:25:05 +01:00
return NULL ;
2003-05-12 01:20:17 +00:00
2011-06-07 11:44:43 +10:00
qt_handle = talloc_zero ( mem_ctx , SMB_NTQUOTA_HANDLE ) ;
2003-05-12 01:20:17 +00:00
if ( qt_handle = = NULL ) {
2007-04-27 23:18:41 +00:00
DEBUG ( 0 , ( " TALLOC_ZERO() failed \n " ) ) ;
2003-05-12 01:20:17 +00:00
return NULL ;
}
2008-03-29 18:19:31 +01:00
talloc_set_destructor ( qt_handle , quota_handle_destructor ) ;
return ( void * ) qt_handle ;
2003-05-12 01:20:17 +00:00
}