LCOV - code coverage report
Current view: top level - source3/smbd - ntquotas.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 84 135 62.2 %
Date: 2024-04-21 15:09:00 Functions: 8 8 100.0 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             :    NT QUOTA support
       4             :    Copyright (C) Stefan (metze) Metzmacher      2003
       5             : 
       6             :    This program is free software; you can redistribute it and/or modify
       7             :    it under the terms of the GNU General Public License as published by
       8             :    the Free Software Foundation; either version 3 of the License, or
       9             :    (at your option) any later version.
      10             : 
      11             :    This program is distributed in the hope that it will be useful,
      12             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14             :    GNU General Public License for more details.
      15             : 
      16             :    You should have received a copy of the GNU General Public License
      17             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      18             : */
      19             : 
      20             : #include "includes.h"
      21             : #include "smbd/smbd.h"
      22             : #include "../lib/util/util_pw.h"
      23             : #include "system/passwd.h"
      24             : #include "passdb/lookup_sid.h"
      25             : #include "libsmb/libsmb.h"
      26             : #include "libcli/security/dom_sid.h"
      27             : 
      28             : #undef DBGC_CLASS
      29             : #define DBGC_CLASS DBGC_QUOTA
      30             : 
      31           8 : static uint64_t limit_nt2unix(uint64_t in, uint64_t bsize)
      32             : {
      33           8 :         uint64_t ret = (uint64_t)0;
      34             : 
      35           8 :         ret =   (uint64_t)(in/bsize);
      36           8 :         if (in>0 && ret==0) {
      37             :                 /* we have to make sure that a overflow didn't set NO_LIMIT */
      38           0 :                 ret = (uint64_t)1;
      39             :         }
      40             : 
      41           8 :         if (in == SMB_NTQUOTAS_NO_LIMIT)
      42           0 :                 ret = SMB_QUOTAS_NO_LIMIT;
      43           8 :         else if (in == SMB_NTQUOTAS_NO_SPACE)
      44           0 :                 ret = SMB_QUOTAS_NO_SPACE;
      45           8 :         else if (in == SMB_NTQUOTAS_NO_ENTRY)
      46           0 :                 ret = SMB_QUOTAS_NO_LIMIT;
      47             : 
      48           8 :         return ret;
      49             : }
      50             : 
      51         168 : static uint64_t limit_unix2nt(uint64_t in, uint64_t bsize)
      52             : {
      53         168 :         uint64_t ret = (uint64_t)0;
      54             : 
      55         168 :         ret = (uint64_t)(in*bsize);
      56             : 
      57         168 :         return ret;
      58             : }
      59             : 
      60          84 : NTSTATUS vfs_get_ntquota(files_struct *fsp, enum SMB_QUOTA_TYPE qtype,
      61             :                          struct dom_sid *psid, SMB_NTQUOTA_STRUCT *qt)
      62             : {
      63           0 :         int ret;
      64           0 :         SMB_DISK_QUOTA D;
      65           0 :         unid_t id;
      66          84 :         struct smb_filename *smb_fname_cwd = NULL;
      67          84 :         int saved_errno = 0;
      68             : 
      69          84 :         ZERO_STRUCT(D);
      70             : 
      71          84 :         if (!fsp || !fsp->conn || !qt) {
      72           0 :                 return NT_STATUS_INTERNAL_ERROR;
      73             :         }
      74             : 
      75          84 :         ZERO_STRUCT(*qt);
      76             : 
      77          84 :         id.uid = -1;
      78             : 
      79          84 :         if (psid && !sid_to_uid(psid, &id.uid)) {
      80           0 :                 struct dom_sid_buf buf;
      81           0 :                 DEBUG(0,("sid_to_uid: failed, SID[%s]\n",
      82             :                          dom_sid_str_buf(psid, &buf)));
      83           0 :                 return NT_STATUS_NO_SUCH_USER;
      84             :         }
      85             : 
      86          84 :         smb_fname_cwd = synthetic_smb_fname(talloc_tos(),
      87             :                                 ".",
      88             :                                 NULL,
      89             :                                 NULL,
      90             :                                 0,
      91             :                                 0);
      92          84 :         if (smb_fname_cwd == NULL) {
      93           0 :                 return NT_STATUS_NO_MEMORY;
      94             :         }
      95             : 
      96          84 :         ret = SMB_VFS_GET_QUOTA(fsp->conn, smb_fname_cwd, qtype, id, &D);
      97          84 :         if (ret == -1) {
      98           0 :                 saved_errno = errno;
      99             :         }
     100          84 :         TALLOC_FREE(smb_fname_cwd);
     101          84 :         if (saved_errno != 0) {
     102           0 :                 errno = saved_errno;
     103             :         }
     104             : 
     105          84 :         if (psid)
     106          84 :                 qt->sid    = *psid;
     107             : 
     108          84 :         if (ret!=0) {
     109           0 :                 return map_nt_error_from_unix(errno);
     110             :         }
     111             : 
     112          84 :         qt->usedspace = (uint64_t)D.curblocks*D.bsize;
     113          84 :         qt->softlim = limit_unix2nt(D.softlimit, D.bsize);
     114          84 :         qt->hardlim = limit_unix2nt(D.hardlimit, D.bsize);
     115          84 :         qt->qflags = D.qflags;
     116             : 
     117          84 :         return NT_STATUS_OK;
     118             : }
     119             : 
     120           4 : int vfs_set_ntquota(files_struct *fsp, enum SMB_QUOTA_TYPE qtype, struct dom_sid *psid, SMB_NTQUOTA_STRUCT *qt)
     121             : {
     122           0 :         int ret;
     123           0 :         SMB_DISK_QUOTA D;
     124           0 :         unid_t id;
     125           4 :         ZERO_STRUCT(D);
     126             : 
     127           4 :         if (!fsp||!fsp->conn||!qt)
     128           0 :                 return (-1);
     129             : 
     130           4 :         id.uid = -1;
     131             : 
     132           4 :         D.bsize     = (uint64_t)QUOTABLOCK_SIZE;
     133             : 
     134           4 :         D.softlimit = limit_nt2unix(qt->softlim,D.bsize);
     135           4 :         D.hardlimit = limit_nt2unix(qt->hardlim,D.bsize);
     136           4 :         D.qflags     = qt->qflags;
     137             : 
     138           4 :         if (psid && !sid_to_uid(psid, &id.uid)) {
     139           0 :                 struct dom_sid_buf buf;
     140           0 :                 DEBUG(0,("sid_to_uid: failed, SID[%s]\n",
     141             :                          dom_sid_str_buf(psid, &buf)));
     142             :         }
     143             : 
     144           4 :         ret = SMB_VFS_SET_QUOTA(fsp->conn, qtype, id, &D);
     145             : 
     146           4 :         return ret;
     147             : }
     148             : 
     149          72 : static bool already_in_quota_list(SMB_NTQUOTA_LIST *qt_list, uid_t uid)
     150             : {
     151          72 :         SMB_NTQUOTA_LIST *tmp_list = NULL;
     152             : 
     153          72 :         if (!qt_list)
     154           4 :                 return False;
     155             : 
     156         680 :         for (tmp_list=qt_list;tmp_list!=NULL;tmp_list=tmp_list->next) {
     157         612 :                 if (tmp_list->uid == uid) {
     158           0 :                         return True;
     159             :                 }
     160             :         }
     161             : 
     162          68 :         return False;
     163             : }
     164             : 
     165           4 : int vfs_get_user_ntquota_list(files_struct *fsp, SMB_NTQUOTA_LIST **qt_list)
     166             : {
     167           0 :         struct passwd *usr;
     168           4 :         TALLOC_CTX *mem_ctx = NULL;
     169             : 
     170           4 :         if (!fsp||!fsp->conn||!qt_list)
     171           0 :                 return (-1);
     172             : 
     173           4 :         *qt_list = NULL;
     174             : 
     175           4 :         if ((mem_ctx=talloc_init("SMB_USER_QUOTA_LIST"))==NULL) {
     176           0 :                 DEBUG(0,("talloc_init() failed\n"));
     177           0 :                 return (-1);
     178             :         }
     179             : 
     180           4 :         setpwent();
     181          76 :         while ((usr = getpwent()) != NULL) {
     182           0 :                 SMB_NTQUOTA_STRUCT tmp_qt;
     183           0 :                 SMB_NTQUOTA_LIST *tmp_list_ent;
     184           0 :                 struct dom_sid  sid;
     185           0 :                 struct dom_sid_buf buf;
     186           0 :                 NTSTATUS status;
     187             : 
     188          72 :                 ZERO_STRUCT(tmp_qt);
     189             : 
     190          72 :                 if (already_in_quota_list((*qt_list),usr->pw_uid)) {
     191           0 :                         DEBUG(5,("record for uid[%ld] already in the list\n",(long)usr->pw_uid));
     192           0 :                         continue;
     193             :                 }
     194             : 
     195          72 :                 uid_to_sid(&sid, usr->pw_uid);
     196             : 
     197           0 :                 status =
     198          72 :                     vfs_get_ntquota(fsp, SMB_USER_QUOTA_TYPE, &sid, &tmp_qt);
     199          72 :                 if (!NT_STATUS_IS_OK(status)) {
     200           0 :                         DEBUG(5, ("failed getting quota for uid[%ld] - %s\n",
     201             :                                   (long)usr->pw_uid, nt_errstr(status)));
     202           0 :                         continue;
     203             :                 }
     204          72 :                 if (tmp_qt.softlim == 0 && tmp_qt.hardlim == 0) {
     205           0 :                         DEBUG(5,("no quota entry for sid[%s] path[%s]\n",
     206             :                                  dom_sid_str_buf(&sid, &buf),
     207             :                                  fsp->conn->connectpath));
     208           0 :                         continue;
     209             :                 }
     210             : 
     211          72 :                 DEBUG(15,("quota entry for id[%s] path[%s]\n",
     212             :                           dom_sid_str_buf(&sid, &buf),
     213             :                           fsp->conn->connectpath));
     214             : 
     215          72 :                 if ((tmp_list_ent=talloc_zero(mem_ctx,SMB_NTQUOTA_LIST))==NULL) {
     216           0 :                         DEBUG(0,("TALLOC_ZERO() failed\n"));
     217           0 :                         *qt_list = NULL;
     218           0 :                         talloc_destroy(mem_ctx);
     219           0 :                         return (-1);
     220             :                 }
     221             : 
     222          72 :                 if ((tmp_list_ent->quotas=talloc_zero(mem_ctx,SMB_NTQUOTA_STRUCT))==NULL) {
     223           0 :                         DEBUG(0,("TALLOC_ZERO() failed\n"));
     224           0 :                         *qt_list = NULL;
     225           0 :                         talloc_destroy(mem_ctx);
     226           0 :                         return (-1);
     227             :                 }
     228             : 
     229          72 :                 tmp_list_ent->uid = usr->pw_uid;
     230          72 :                 memcpy(tmp_list_ent->quotas,&tmp_qt,sizeof(tmp_qt));
     231          72 :                 tmp_list_ent->mem_ctx = mem_ctx;
     232             : 
     233          72 :                 DLIST_ADD((*qt_list),tmp_list_ent);
     234             : 
     235             :         }
     236           4 :         endpwent();
     237             : 
     238           4 :         if (*qt_list == NULL) {
     239           0 :                 TALLOC_FREE(mem_ctx);
     240             :         }
     241           4 :         return 0;
     242             : }
     243             : 
     244          21 : static int quota_handle_destructor(SMB_NTQUOTA_HANDLE *handle)
     245             : {
     246          21 :         free_ntquota_list(&handle->quota_list);
     247          21 :         return 0;
     248             : }
     249             : 
     250          21 : void *init_quota_handle(TALLOC_CTX *mem_ctx)
     251             : {
     252           0 :         SMB_NTQUOTA_HANDLE *qt_handle;
     253             : 
     254          21 :         if (!mem_ctx)
     255           0 :                 return NULL;
     256             : 
     257          21 :         qt_handle = talloc_zero(mem_ctx,SMB_NTQUOTA_HANDLE);
     258          21 :         if (qt_handle==NULL) {
     259           0 :                 DEBUG(0,("TALLOC_ZERO() failed\n"));
     260           0 :                 return NULL;
     261             :         }
     262             : 
     263          21 :         talloc_set_destructor(qt_handle, quota_handle_destructor);
     264          21 :         return (void *)qt_handle;
     265             : }

Generated by: LCOV version 1.14