LCOV - code coverage report
Current view: top level - source3/smbd - smb2_nttrans.c (source / functions) Hit Total Coverage
Test: coverage report for support-claim-type-attributes 6b5c566e Lines: 234 344 68.0 %
Date: 2023-11-21 12:31:41 Functions: 11 11 100.0 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             :    SMB NT transaction handling
       4             :    Copyright (C) Jeremy Allison                 1994-2007
       5             :    Copyright (C) Stefan (metze) Metzmacher      2003
       6             : 
       7             :    This program is free software; you can redistribute it and/or modify
       8             :    it under the terms of the GNU General Public License as published by
       9             :    the Free Software Foundation; either version 3 of the License, or
      10             :    (at your option) any later version.
      11             : 
      12             :    This program is distributed in the hope that it will be useful,
      13             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      15             :    GNU General Public License for more details.
      16             : 
      17             :    You should have received a copy of the GNU General Public License
      18             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      19             : */
      20             : 
      21             : #include "includes.h"
      22             : #include "system/filesys.h"
      23             : #include "smbd/smbd.h"
      24             : #include "smbd/globals.h"
      25             : #include "fake_file.h"
      26             : #include "../libcli/security/security.h"
      27             : #include "../librpc/gen_ndr/ndr_security.h"
      28             : #include "passdb/lookup_sid.h"
      29             : #include "auth.h"
      30             : #include "smbprofile.h"
      31             : #include "libsmb/libsmb.h"
      32             : #include "lib/util_ea.h"
      33             : #include "librpc/gen_ndr/ndr_quota.h"
      34             : #include "librpc/gen_ndr/ndr_security.h"
      35             : 
      36             : extern const struct generic_mapping file_generic_mapping;
      37             : 
      38             : /*********************************************************************
      39             :  Windows seems to do canonicalization of inheritance bits. Do the
      40             :  same.
      41             : *********************************************************************/
      42             : 
      43       13661 : static void canonicalize_inheritance_bits(struct files_struct *fsp,
      44             :                                           struct security_descriptor *psd)
      45             : {
      46       13661 :         bool set_auto_inherited = false;
      47             : 
      48             :         /*
      49             :          * We need to filter out the
      50             :          * SEC_DESC_DACL_AUTO_INHERITED|SEC_DESC_DACL_AUTO_INHERIT_REQ
      51             :          * bits. If both are set we store SEC_DESC_DACL_AUTO_INHERITED
      52             :          * as this alters whether SEC_ACE_FLAG_INHERITED_ACE is set
      53             :          * when an ACE is inherited. Otherwise we zero these bits out.
      54             :          * See:
      55             :          *
      56             :          * http://social.msdn.microsoft.com/Forums/eu/os_fileservices/thread/11f77b68-731e-407d-b1b3-064750716531
      57             :          *
      58             :          * for details.
      59             :          */
      60             : 
      61       13661 :         if (!lp_acl_flag_inherited_canonicalization(SNUM(fsp->conn))) {
      62           4 :                 psd->type &= ~SEC_DESC_DACL_AUTO_INHERIT_REQ;
      63           4 :                 return;
      64             :         }
      65             : 
      66       13657 :         if ((psd->type & (SEC_DESC_DACL_AUTO_INHERITED|SEC_DESC_DACL_AUTO_INHERIT_REQ))
      67             :                         == (SEC_DESC_DACL_AUTO_INHERITED|SEC_DESC_DACL_AUTO_INHERIT_REQ)) {
      68        1370 :                 set_auto_inherited = true;
      69             :         }
      70             : 
      71       13657 :         psd->type &= ~(SEC_DESC_DACL_AUTO_INHERITED|SEC_DESC_DACL_AUTO_INHERIT_REQ);
      72       13657 :         if (set_auto_inherited) {
      73        1370 :                 psd->type |= SEC_DESC_DACL_AUTO_INHERITED;
      74             :         }
      75             : }
      76             : 
      77             : /****************************************************************************
      78             :  Internal fn to set security descriptors.
      79             : ****************************************************************************/
      80             : 
      81       13663 : NTSTATUS set_sd(files_struct *fsp, struct security_descriptor *psd,
      82             :                        uint32_t security_info_sent)
      83             : {
      84       13663 :         files_struct *sd_fsp = NULL;
      85           2 :         NTSTATUS status;
      86             : 
      87       13663 :         if (!CAN_WRITE(fsp->conn)) {
      88           0 :                 return NT_STATUS_ACCESS_DENIED;
      89             :         }
      90             : 
      91       13663 :         if (!lp_nt_acl_support(SNUM(fsp->conn))) {
      92           0 :                 return NT_STATUS_OK;
      93             :         }
      94             : 
      95       13663 :         status = refuse_symlink_fsp(fsp);
      96       13663 :         if (!NT_STATUS_IS_OK(status)) {
      97           0 :                 DBG_DEBUG("ACL set on symlink %s denied.\n",
      98             :                         fsp_str_dbg(fsp));
      99           0 :                 return status;
     100             :         }
     101             : 
     102       13663 :         if (psd->owner_sid == NULL) {
     103        1921 :                 security_info_sent &= ~SECINFO_OWNER;
     104             :         }
     105       13663 :         if (psd->group_sid == NULL) {
     106       11165 :                 security_info_sent &= ~SECINFO_GROUP;
     107             :         }
     108             : 
     109             :         /* Ensure we have at least one thing set. */
     110       13663 :         if ((security_info_sent & (SECINFO_OWNER|SECINFO_GROUP|SECINFO_DACL|SECINFO_SACL)) == 0) {
     111             :                 /* Just like W2K3 */
     112           0 :                 return NT_STATUS_OK;
     113             :         }
     114             : 
     115             :         /* Ensure we have the rights to do this. */
     116       13663 :         if (security_info_sent & SECINFO_OWNER) {
     117        4948 :                 if (!(fsp->access_mask & SEC_STD_WRITE_OWNER)) {
     118           0 :                         return NT_STATUS_ACCESS_DENIED;
     119             :                 }
     120             :         }
     121             : 
     122       13663 :         if (security_info_sent & SECINFO_GROUP) {
     123        2456 :                 if (!(fsp->access_mask & SEC_STD_WRITE_OWNER)) {
     124           0 :                         return NT_STATUS_ACCESS_DENIED;
     125             :                 }
     126             :         }
     127             : 
     128       13663 :         if (security_info_sent & SECINFO_DACL) {
     129       11575 :                 if (!(fsp->access_mask & SEC_STD_WRITE_DAC)) {
     130           2 :                         return NT_STATUS_ACCESS_DENIED;
     131             :                 }
     132             :                 /* Convert all the generic bits. */
     133       11573 :                 if (psd->dacl) {
     134       11539 :                         security_acl_map_generic(psd->dacl, &file_generic_mapping);
     135             :                 }
     136             :         }
     137             : 
     138       13661 :         if (security_info_sent & SECINFO_SACL) {
     139         165 :                 if (!(fsp->access_mask & SEC_FLAG_SYSTEM_SECURITY)) {
     140           0 :                         return NT_STATUS_ACCESS_DENIED;
     141             :                 }
     142             :                 /*
     143             :                  * Setting a SACL also requires WRITE_DAC.
     144             :                  * See the smbtorture3 SMB2-SACL test.
     145             :                  */
     146         165 :                 if (!(fsp->access_mask & SEC_STD_WRITE_DAC)) {
     147           0 :                         return NT_STATUS_ACCESS_DENIED;
     148             :                 }
     149             :                 /* Convert all the generic bits. */
     150         165 :                 if (psd->sacl) {
     151           2 :                         security_acl_map_generic(psd->sacl, &file_generic_mapping);
     152             :                 }
     153             :         }
     154             : 
     155       13661 :         canonicalize_inheritance_bits(fsp, psd);
     156             : 
     157       13661 :         if (DEBUGLEVEL >= 10) {
     158           0 :                 DEBUG(10,("set_sd for file %s\n", fsp_str_dbg(fsp)));
     159           0 :                 NDR_PRINT_DEBUG(security_descriptor, psd);
     160             :         }
     161             : 
     162       13661 :         sd_fsp = metadata_fsp(fsp);
     163       13661 :         status = SMB_VFS_FSET_NT_ACL(sd_fsp, security_info_sent, psd);
     164             : 
     165       13661 :         TALLOC_FREE(psd);
     166             : 
     167       13661 :         return status;
     168             : }
     169             : 
     170             : /****************************************************************************
     171             :  Internal fn to set security descriptors from a data blob.
     172             : ****************************************************************************/
     173             : 
     174       13521 : NTSTATUS set_sd_blob(files_struct *fsp, uint8_t *data, uint32_t sd_len,
     175             :                        uint32_t security_info_sent)
     176             : {
     177       13521 :         struct security_descriptor *psd = NULL;
     178           2 :         NTSTATUS status;
     179             : 
     180       13521 :         if (sd_len == 0) {
     181           0 :                 return NT_STATUS_INVALID_PARAMETER;
     182             :         }
     183             : 
     184       13521 :         status = unmarshall_sec_desc(talloc_tos(), data, sd_len, &psd);
     185             : 
     186       13521 :         if (!NT_STATUS_IS_OK(status)) {
     187           0 :                 return status;
     188             :         }
     189             : 
     190       13521 :         return set_sd(fsp, psd, security_info_sent);
     191             : }
     192             : 
     193             : /****************************************************************************
     194             :  Copy a file.
     195             : ****************************************************************************/
     196             : 
     197          10 : NTSTATUS copy_internals(TALLOC_CTX *ctx,
     198             :                         connection_struct *conn,
     199             :                         struct smb_request *req,
     200             :                         struct files_struct *src_dirfsp,
     201             :                         struct smb_filename *smb_fname_src,
     202             :                         struct files_struct *dst_dirfsp,
     203             :                         struct smb_filename *smb_fname_dst,
     204             :                         uint32_t attrs)
     205             : {
     206           2 :         files_struct *fsp1,*fsp2;
     207           2 :         uint32_t fattr;
     208           2 :         int info;
     209          10 :         off_t ret=-1;
     210          10 :         NTSTATUS status = NT_STATUS_OK;
     211          10 :         struct smb_filename *parent = NULL;
     212          10 :         struct smb_filename *pathref = NULL;
     213             : 
     214          10 :         if (!CAN_WRITE(conn)) {
     215           0 :                 status = NT_STATUS_MEDIA_WRITE_PROTECTED;
     216           0 :                 goto out;
     217             :         }
     218             : 
     219             :         /* Source must already exist. */
     220          10 :         if (!VALID_STAT(smb_fname_src->st)) {
     221           0 :                 status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
     222           0 :                 goto out;
     223             :         }
     224             : 
     225             :         /* Ensure attributes match. */
     226          10 :         fattr = fdos_mode(smb_fname_src->fsp);
     227          10 :         if ((fattr & ~attrs) & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
     228           0 :                 status = NT_STATUS_NO_SUCH_FILE;
     229           0 :                 goto out;
     230             :         }
     231             : 
     232             :         /* Disallow if dst file already exists. */
     233          10 :         if (VALID_STAT(smb_fname_dst->st)) {
     234           0 :                 status = NT_STATUS_OBJECT_NAME_COLLISION;
     235           0 :                 goto out;
     236             :         }
     237             : 
     238             :         /* No links from a directory. */
     239          10 :         if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
     240           0 :                 status = NT_STATUS_FILE_IS_A_DIRECTORY;
     241           0 :                 goto out;
     242             :         }
     243             : 
     244          10 :         DEBUG(10,("copy_internals: doing file copy %s to %s\n",
     245             :                   smb_fname_str_dbg(smb_fname_src),
     246             :                   smb_fname_str_dbg(smb_fname_dst)));
     247             : 
     248          10 :         status = SMB_VFS_CREATE_FILE(
     249             :                 conn,                                   /* conn */
     250             :                 req,                                    /* req */
     251             :                 src_dirfsp,                             /* dirfsp */
     252             :                 smb_fname_src,                          /* fname */
     253             :                 FILE_READ_DATA|FILE_READ_ATTRIBUTES|
     254             :                         FILE_READ_EA,                   /* access_mask */
     255             :                 (FILE_SHARE_READ | FILE_SHARE_WRITE |   /* share_access */
     256             :                     FILE_SHARE_DELETE),
     257             :                 FILE_OPEN,                              /* create_disposition*/
     258             :                 0,                                      /* create_options */
     259             :                 FILE_ATTRIBUTE_NORMAL,                  /* file_attributes */
     260             :                 NO_OPLOCK,                              /* oplock_request */
     261             :                 NULL,                                   /* lease */
     262             :                 0,                                      /* allocation_size */
     263             :                 0,                                      /* private_flags */
     264             :                 NULL,                                   /* sd */
     265             :                 NULL,                                   /* ea_list */
     266             :                 &fsp1,                                      /* result */
     267             :                 &info,                                      /* pinfo */
     268             :                 NULL, NULL);                            /* create context */
     269             : 
     270          10 :         if (!NT_STATUS_IS_OK(status)) {
     271           0 :                 goto out;
     272             :         }
     273             : 
     274          10 :         status = SMB_VFS_CREATE_FILE(
     275             :                 conn,                                   /* conn */
     276             :                 req,                                    /* req */
     277             :                 dst_dirfsp,                             /* dirfsp */
     278             :                 smb_fname_dst,                          /* fname */
     279             :                 FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|
     280             :                         FILE_WRITE_EA,                  /* access_mask */
     281             :                 (FILE_SHARE_READ | FILE_SHARE_WRITE |   /* share_access */
     282             :                     FILE_SHARE_DELETE),
     283             :                 FILE_CREATE,                            /* create_disposition*/
     284             :                 0,                                      /* create_options */
     285             :                 fattr,                                  /* file_attributes */
     286             :                 NO_OPLOCK,                              /* oplock_request */
     287             :                 NULL,                                   /* lease */
     288             :                 0,                                      /* allocation_size */
     289             :                 0,                                      /* private_flags */
     290             :                 NULL,                                   /* sd */
     291             :                 NULL,                                   /* ea_list */
     292             :                 &fsp2,                                      /* result */
     293             :                 &info,                                      /* pinfo */
     294             :                 NULL, NULL);                            /* create context */
     295             : 
     296          10 :         if (!NT_STATUS_IS_OK(status)) {
     297           0 :                 close_file_free(NULL, &fsp1, ERROR_CLOSE);
     298           0 :                 goto out;
     299             :         }
     300             : 
     301          10 :         if (smb_fname_src->st.st_ex_size) {
     302          10 :                 ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
     303             :         }
     304             : 
     305             :         /*
     306             :          * As we are opening fsp1 read-only we only expect
     307             :          * an error on close on fsp2 if we are out of space.
     308             :          * Thus we don't look at the error return from the
     309             :          * close of fsp1.
     310             :          */
     311          10 :         close_file_free(NULL, &fsp1, NORMAL_CLOSE);
     312             : 
     313             :         /* Ensure the modtime is set correctly on the destination file. */
     314          10 :         set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
     315             : 
     316          10 :         status = close_file_free(NULL, &fsp2, NORMAL_CLOSE);
     317          10 :         if (!NT_STATUS_IS_OK(status)) {
     318           0 :                 DBG_WARNING("close_file_free() failed: %s\n",
     319             :                             nt_errstr(status));
     320             :                 /*
     321             :                  * We can't do much but leak the fsp
     322             :                  */
     323           0 :                 goto out;
     324             :         }
     325             : 
     326             :         /* Grrr. We have to do this as open_file_ntcreate adds FILE_ATTRIBUTE_ARCHIVE when it
     327             :            creates the file. This isn't the correct thing to do in the copy
     328             :            case. JRA */
     329             : 
     330          10 :         status = SMB_VFS_PARENT_PATHNAME(conn,
     331             :                                          talloc_tos(),
     332             :                                          smb_fname_dst,
     333             :                                          &parent,
     334             :                                          NULL);
     335          10 :         if (!NT_STATUS_IS_OK(status)) {
     336           0 :                 goto out;
     337             :         }
     338          10 :         if (smb_fname_dst->fsp == NULL) {
     339          12 :                 status = synthetic_pathref(parent,
     340             :                                         conn->cwd_fsp,
     341          10 :                                         smb_fname_dst->base_name,
     342          10 :                                         smb_fname_dst->stream_name,
     343             :                                         NULL,
     344             :                                         smb_fname_dst->twrp,
     345             :                                         smb_fname_dst->flags,
     346             :                                         &pathref);
     347             : 
     348             :                 /* should we handle NT_STATUS_OBJECT_NAME_NOT_FOUND specially here ???? */
     349          10 :                 if (!NT_STATUS_IS_OK(status)) {
     350           0 :                         TALLOC_FREE(parent);
     351           0 :                         goto out;
     352             :                 }
     353          10 :                 file_set_dosmode(conn, pathref, fattr, parent, false);
     354          10 :                 smb_fname_dst->st.st_ex_mode = pathref->st.st_ex_mode;
     355             :         } else {
     356           0 :                 file_set_dosmode(conn, smb_fname_dst, fattr, parent, false);
     357             :         }
     358          10 :         TALLOC_FREE(parent);
     359             : 
     360          10 :         if (ret < (off_t)smb_fname_src->st.st_ex_size) {
     361           0 :                 status = NT_STATUS_DISK_FULL;
     362           0 :                 goto out;
     363             :         }
     364          10 :  out:
     365          10 :         if (!NT_STATUS_IS_OK(status)) {
     366           0 :                 DEBUG(3,("copy_internals: Error %s copy file %s to %s\n",
     367             :                         nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
     368             :                         smb_fname_str_dbg(smb_fname_dst)));
     369             :         }
     370             : 
     371          10 :         return status;
     372             : }
     373             : 
     374             : /******************************************************************************
     375             :  Fake up a completely empty SD.
     376             : *******************************************************************************/
     377             : 
     378          12 : static NTSTATUS get_null_nt_acl(TALLOC_CTX *mem_ctx, struct security_descriptor **ppsd)
     379             : {
     380           0 :         size_t sd_size;
     381             : 
     382          12 :         *ppsd = make_standard_sec_desc( mem_ctx, &global_sid_World, &global_sid_World, NULL, &sd_size);
     383          12 :         if(!*ppsd) {
     384           0 :                 DEBUG(0,("get_null_nt_acl: Unable to malloc space for security descriptor.\n"));
     385           0 :                 return NT_STATUS_NO_MEMORY;
     386             :         }
     387             : 
     388          12 :         return NT_STATUS_OK;
     389             : }
     390             : 
     391             : /****************************************************************************
     392             :  Get a security descriptor from the file system, normalize for components
     393             :  requested.
     394             : ****************************************************************************/
     395             : 
     396       14767 : static NTSTATUS smbd_fetch_security_desc(connection_struct *conn,
     397             :                                 TALLOC_CTX *mem_ctx,
     398             :                                 files_struct *fsp,
     399             :                                 uint32_t security_info_wanted,
     400             :                                 struct security_descriptor **ppsd)
     401             : {
     402          12 :         NTSTATUS status;
     403       14767 :         struct security_descriptor *psd = NULL;
     404       14767 :         bool need_to_read_sd = false;
     405             : 
     406             :         /*
     407             :          * Get the permissions to return.
     408             :          */
     409             : 
     410       14767 :         if ((security_info_wanted & SECINFO_SACL) &&
     411         338 :                         !(fsp->access_mask & SEC_FLAG_SYSTEM_SECURITY)) {
     412           0 :                 DEBUG(10, ("Access to SACL denied.\n"));
     413           0 :                 return NT_STATUS_ACCESS_DENIED;
     414             :         }
     415             : 
     416       14767 :         if ((security_info_wanted & (SECINFO_DACL|SECINFO_OWNER|SECINFO_GROUP)) &&
     417       14753 :                         !(fsp->access_mask & SEC_STD_READ_CONTROL)) {
     418          22 :                 DEBUG(10, ("Access to DACL, OWNER, or GROUP denied.\n"));
     419          22 :                 return NT_STATUS_ACCESS_DENIED;
     420             :         }
     421             : 
     422       14745 :         status = refuse_symlink_fsp(fsp);
     423       14745 :         if (!NT_STATUS_IS_OK(status)) {
     424           0 :                 DBG_DEBUG("ACL get on symlink %s denied.\n",
     425             :                         fsp_str_dbg(fsp));
     426           0 :                 return status;
     427             :         }
     428             : 
     429       14745 :         if (security_info_wanted & (SECINFO_DACL|SECINFO_OWNER|
     430             :                         SECINFO_GROUP|SECINFO_SACL)) {
     431             :                 /* Don't return SECINFO_LABEL if anything else was
     432             :                    requested. See bug #8458. */
     433       14733 :                 security_info_wanted &= ~SECINFO_LABEL;
     434             : 
     435             :                 /*
     436             :                  * Only query the file system SD if the caller asks
     437             :                  * for any bits. This allows a caller to open without
     438             :                  * READ_CONTROL but still issue a query sd. See
     439             :                  * smb2.sdread test.
     440             :                  */
     441       14733 :                 need_to_read_sd = true;
     442             :         }
     443             : 
     444       14745 :         if (lp_nt_acl_support(SNUM(conn)) &&
     445       14745 :             ((security_info_wanted & SECINFO_LABEL) == 0) &&
     446             :             need_to_read_sd)
     447       14733 :         {
     448       14733 :                 files_struct *sd_fsp = metadata_fsp(fsp);
     449       14733 :                 status = SMB_VFS_FGET_NT_ACL(
     450             :                         sd_fsp, security_info_wanted, mem_ctx, &psd);
     451             :         } else {
     452          12 :                 status = get_null_nt_acl(mem_ctx, &psd);
     453             :         }
     454             : 
     455       14745 :         if (!NT_STATUS_IS_OK(status)) {
     456           0 :                 return status;
     457             :         }
     458             : 
     459       14745 :         if (!(security_info_wanted & SECINFO_OWNER)) {
     460        1270 :                 psd->owner_sid = NULL;
     461             :         }
     462       14745 :         if (!(security_info_wanted & SECINFO_GROUP)) {
     463       10690 :                 psd->group_sid = NULL;
     464             :         }
     465       14745 :         if (!(security_info_wanted & SECINFO_DACL)) {
     466          24 :                 psd->type &= ~SEC_DESC_DACL_PRESENT;
     467          24 :                 psd->dacl = NULL;
     468             :         }
     469       14745 :         if (!(security_info_wanted & SECINFO_SACL)) {
     470       14407 :                 psd->type &= ~SEC_DESC_SACL_PRESENT;
     471       14407 :                 psd->sacl = NULL;
     472             :         }
     473             : 
     474             :         /* If the SACL/DACL is NULL, but was requested, we mark that it is
     475             :          * present in the reply to match Windows behavior */
     476       14745 :         if (psd->sacl == NULL &&
     477       14731 :             security_info_wanted & SECINFO_SACL)
     478         336 :                 psd->type |= SEC_DESC_SACL_PRESENT;
     479       14745 :         if (psd->dacl == NULL &&
     480          42 :             security_info_wanted & SECINFO_DACL)
     481          18 :                 psd->type |= SEC_DESC_DACL_PRESENT;
     482             : 
     483       14745 :         if (security_info_wanted & SECINFO_LABEL) {
     484             :                 /* Like W2K3 return a null object. */
     485           0 :                 psd->owner_sid = NULL;
     486           0 :                 psd->group_sid = NULL;
     487           0 :                 psd->dacl = NULL;
     488           0 :                 psd->sacl = NULL;
     489           0 :                 psd->type &= ~(SEC_DESC_DACL_PRESENT|SEC_DESC_SACL_PRESENT);
     490             :         }
     491             : 
     492       14745 :         *ppsd = psd;
     493       14745 :         return NT_STATUS_OK;
     494             : }
     495             : 
     496             : /****************************************************************************
     497             :  Write a security descriptor into marshalled format.
     498             : ****************************************************************************/
     499             : 
     500       14745 : static NTSTATUS smbd_marshall_security_desc(TALLOC_CTX *mem_ctx,
     501             :                                         files_struct *fsp,
     502             :                                         struct security_descriptor *psd,
     503             :                                         uint32_t max_data_count,
     504             :                                         uint8_t **ppmarshalled_sd,
     505             :                                         size_t *psd_size)
     506             : {
     507       14745 :         *psd_size = ndr_size_security_descriptor(psd, 0);
     508             : 
     509       14745 :         DBG_NOTICE("sd_size = %zu.\n", *psd_size);
     510             : 
     511       14745 :         if (DEBUGLEVEL >= 10) {
     512           0 :                 DBG_DEBUG("security desc for file %s\n",
     513             :                         fsp_str_dbg(fsp));
     514           0 :                 NDR_PRINT_DEBUG(security_descriptor, psd);
     515             :         }
     516             : 
     517       14745 :         if (max_data_count < *psd_size) {
     518           8 :                 return NT_STATUS_BUFFER_TOO_SMALL;
     519             :         }
     520             : 
     521       14737 :         return marshall_sec_desc(mem_ctx,
     522             :                                  psd,
     523             :                                  ppmarshalled_sd,
     524             :                                  psd_size);
     525             : }
     526             : 
     527             : /****************************************************************************
     528             :  Reply to query a security descriptor.
     529             :  Callable from SMB1 and SMB2.
     530             :  If it returns NT_STATUS_BUFFER_TOO_SMALL, psd_size is initialized with
     531             :  the required size.
     532             : ****************************************************************************/
     533             : 
     534       14767 : NTSTATUS smbd_do_query_security_desc(connection_struct *conn,
     535             :                                         TALLOC_CTX *mem_ctx,
     536             :                                         files_struct *fsp,
     537             :                                         uint32_t security_info_wanted,
     538             :                                         uint32_t max_data_count,
     539             :                                         uint8_t **ppmarshalled_sd,
     540             :                                         size_t *psd_size)
     541             : {
     542          12 :         NTSTATUS status;
     543       14767 :         struct security_descriptor *psd = NULL;
     544             : 
     545             :         /*
     546             :          * Get the permissions to return.
     547             :          */
     548             : 
     549       14767 :         status = smbd_fetch_security_desc(conn,
     550             :                                         mem_ctx,
     551             :                                         fsp,
     552             :                                         security_info_wanted,
     553             :                                         &psd);
     554       14767 :         if (!NT_STATUS_IS_OK(status)) {
     555          22 :                 return status;
     556             :         }
     557             : 
     558       14745 :         status = smbd_marshall_security_desc(mem_ctx,
     559             :                                         fsp,
     560             :                                         psd,
     561             :                                         max_data_count,
     562             :                                         ppmarshalled_sd,
     563             :                                         psd_size);
     564       14745 :         TALLOC_FREE(psd);
     565       14745 :         return status;
     566             : }
     567             : 
     568             : #ifdef HAVE_SYS_QUOTAS
     569          12 : static enum ndr_err_code fill_qtlist_from_sids(TALLOC_CTX *mem_ctx,
     570             :                                                struct files_struct *fsp,
     571             :                                                SMB_NTQUOTA_HANDLE *qt_handle,
     572             :                                                struct dom_sid *sids,
     573             :                                                uint32_t elems)
     574             : {
     575           0 :         uint32_t i;
     576          12 :         TALLOC_CTX *list_ctx = NULL;
     577             : 
     578          12 :         list_ctx = talloc_init("quota_sid_list");
     579             : 
     580          12 :         if (list_ctx == NULL) {
     581           0 :                 DBG_ERR("failed to allocate\n");
     582           0 :                 return NDR_ERR_ALLOC;
     583             :         }
     584             : 
     585          12 :         if (qt_handle->quota_list!=NULL) {
     586           0 :                 free_ntquota_list(&(qt_handle->quota_list));
     587             :         }
     588          24 :         for (i = 0; i < elems; i++) {
     589           0 :                 SMB_NTQUOTA_STRUCT qt;
     590           0 :                 SMB_NTQUOTA_LIST *list_item;
     591           0 :                 bool ok;
     592             : 
     593          12 :                 if (!NT_STATUS_IS_OK(vfs_get_ntquota(fsp,
     594             :                                                      SMB_USER_QUOTA_TYPE,
     595             :                                                      &sids[i], &qt))) {
     596             :                         /* non fatal error, return empty item in result */
     597           0 :                         ZERO_STRUCT(qt);
     598           0 :                         continue;
     599             :                 }
     600             : 
     601             : 
     602          12 :                 list_item = talloc_zero(list_ctx, SMB_NTQUOTA_LIST);
     603          12 :                 if (list_item == NULL) {
     604           0 :                         DBG_ERR("failed to allocate\n");
     605           0 :                         return NDR_ERR_ALLOC;
     606             :                 }
     607             : 
     608          12 :                 ok = sid_to_uid(&sids[i], &list_item->uid);
     609          12 :                 if (!ok) {
     610           0 :                         struct dom_sid_buf buf;
     611           0 :                         DBG_WARNING("Could not convert SID %s to uid\n",
     612             :                                     dom_sid_str_buf(&sids[i], &buf));
     613             :                         /* No idea what to return here... */
     614           0 :                         return NDR_ERR_INVALID_POINTER;
     615             :                 }
     616             : 
     617          12 :                 list_item->quotas = talloc_zero(list_item, SMB_NTQUOTA_STRUCT);
     618          12 :                 if (list_item->quotas == NULL) {
     619           0 :                         DBG_ERR("failed to allocate\n");
     620           0 :                         return NDR_ERR_ALLOC;
     621             :                 }
     622             : 
     623          12 :                 *list_item->quotas = qt;
     624          12 :                 list_item->mem_ctx = list_ctx;
     625          12 :                 DLIST_ADD(qt_handle->quota_list, list_item);
     626             :         }
     627          12 :         qt_handle->tmp_list = qt_handle->quota_list;
     628          12 :         return NDR_ERR_SUCCESS;
     629             : }
     630             : 
     631          12 : static enum ndr_err_code extract_sids_from_buf(TALLOC_CTX *mem_ctx,
     632             :                                   uint32_t sidlistlength,
     633             :                                   DATA_BLOB *sid_buf,
     634             :                                   struct dom_sid **sids,
     635             :                                   uint32_t *num)
     636             : {
     637           0 :         DATA_BLOB blob;
     638          12 :         uint32_t i = 0;
     639           0 :         enum ndr_err_code err;
     640             : 
     641           0 :         struct sid_list_elem {
     642             :                 struct sid_list_elem *prev, *next;
     643             :                 struct dom_sid sid;
     644             :         };
     645             : 
     646          12 :         struct sid_list_elem *sid_list = NULL;
     647          12 :         struct sid_list_elem *iter = NULL;
     648          12 :         TALLOC_CTX *list_ctx = talloc_init("sid_list");
     649          12 :         if (!list_ctx) {
     650           0 :                 DBG_ERR("OOM\n");
     651           0 :                 err = NDR_ERR_ALLOC;
     652           0 :                 goto done;
     653             :         }
     654             : 
     655          12 :         *num = 0;
     656          12 :         *sids = NULL;
     657             : 
     658          12 :         if (sidlistlength) {
     659          12 :                 uint32_t offset = 0;
     660          12 :                 struct ndr_pull *ndr_pull = NULL;
     661             : 
     662          12 :                 if (sidlistlength > sid_buf->length) {
     663           0 :                         DBG_ERR("sid_list_length 0x%x exceeds "
     664             :                                 "available bytes %zx\n",
     665             :                                 sidlistlength,
     666             :                                 sid_buf->length);
     667           0 :                         err = NDR_ERR_OFFSET;
     668           0 :                         goto done;
     669             :                 }
     670           0 :                 while (true) {
     671           0 :                         struct file_get_quota_info info;
     672          12 :                         struct sid_list_elem *item = NULL;
     673          12 :                         uint32_t new_offset = 0;
     674          12 :                         blob.data = sid_buf->data + offset;
     675          12 :                         blob.length = sidlistlength - offset;
     676          12 :                         ndr_pull = ndr_pull_init_blob(&blob, list_ctx);
     677          12 :                         if (!ndr_pull) {
     678           0 :                                 DBG_ERR("OOM\n");
     679           0 :                                 err = NDR_ERR_ALLOC;
     680           0 :                                 goto done;
     681             :                         }
     682          12 :                         err = ndr_pull_file_get_quota_info(ndr_pull,
     683             :                                            NDR_SCALARS | NDR_BUFFERS, &info);
     684          12 :                         if (!NDR_ERR_CODE_IS_SUCCESS(err)) {
     685           0 :                                 DBG_ERR("Failed to pull file_get_quota_info "
     686             :                                         "from sidlist buffer\n");
     687           0 :                                 goto done;
     688             :                         }
     689          12 :                         item = talloc_zero(list_ctx, struct sid_list_elem);
     690          12 :                         if (!item) {
     691           0 :                                 DBG_ERR("OOM\n");
     692           0 :                                 err = NDR_ERR_ALLOC;
     693           0 :                                 goto done;
     694             :                         }
     695          12 :                         item->sid = info.sid;
     696          12 :                         DLIST_ADD(sid_list, item);
     697          12 :                         i++;
     698          12 :                         if (i == UINT32_MAX) {
     699           0 :                                 DBG_ERR("Integer overflow\n");
     700           0 :                                 err = NDR_ERR_ARRAY_SIZE;
     701           0 :                                 goto done;
     702             :                         }
     703          12 :                         new_offset = info.next_entry_offset;
     704             : 
     705             :                         /* if new_offset == 0 no more sid(s) to read. */
     706          12 :                         if (new_offset == 0) {
     707          12 :                                 break;
     708             :                         }
     709             : 
     710             :                         /* Integer wrap? */
     711           0 :                         if ((offset + new_offset) < offset) {
     712           0 :                                 DBG_ERR("Integer wrap while adding "
     713             :                                         "new_offset 0x%x to current "
     714             :                                         "buffer offset 0x%x\n",
     715             :                                         new_offset, offset);
     716           0 :                                 err = NDR_ERR_OFFSET;
     717           0 :                                 goto done;
     718             :                         }
     719             : 
     720           0 :                         offset += new_offset;
     721             : 
     722             :                         /* check if new offset is outside buffer boundary. */
     723           0 :                         if (offset >= sidlistlength) {
     724           0 :                                 DBG_ERR("bufsize 0x%x exceeded by "
     725             :                                         "new offset 0x%x)\n",
     726             :                                         sidlistlength,
     727             :                                         offset);
     728           0 :                                 err = NDR_ERR_OFFSET;
     729           0 :                                 goto done;
     730             :                         }
     731             :                 }
     732          12 :                 *sids = talloc_zero_array(mem_ctx, struct dom_sid, i);
     733          12 :                 if (*sids == NULL) {
     734           0 :                         DBG_ERR("OOM\n");
     735           0 :                         err = NDR_ERR_ALLOC;
     736           0 :                         goto done;
     737             :                 }
     738             : 
     739          12 :                 *num = i;
     740             : 
     741          24 :                 for (iter = sid_list, i = 0; iter; iter = iter->next, i++) {
     742           0 :                         struct dom_sid_buf buf;
     743          12 :                         (*sids)[i] = iter->sid;
     744          12 :                         DBG_DEBUG("quota SID[%u] %s\n",
     745             :                                 (unsigned int)i,
     746             :                                 dom_sid_str_buf(&iter->sid, &buf));
     747             :                 }
     748             :         }
     749          12 :         err = NDR_ERR_SUCCESS;
     750          12 : done:
     751          12 :         TALLOC_FREE(list_ctx);
     752          12 :         return err;
     753             : }
     754             : 
     755          20 : NTSTATUS smbd_do_query_getinfo_quota(TALLOC_CTX *mem_ctx,
     756             :                                      files_struct *fsp,
     757             :                                      bool restart_scan,
     758             :                                      bool return_single,
     759             :                                      uint32_t sid_list_length,
     760             :                                      DATA_BLOB *sid_buf,
     761             :                                      uint32_t max_data_count,
     762             :                                      uint8_t **p_data,
     763             :                                      uint32_t *p_data_size)
     764             : {
     765           0 :         NTSTATUS status;
     766          20 :         SMB_NTQUOTA_HANDLE *qt_handle = NULL;
     767          20 :         SMB_NTQUOTA_LIST *qt_list = NULL;
     768          20 :         DATA_BLOB blob = data_blob_null;
     769           0 :         enum ndr_err_code err;
     770             : 
     771          20 :         qt_handle =
     772          20 :                 (SMB_NTQUOTA_HANDLE *)fsp->fake_file_handle->private_data;
     773             : 
     774          20 :         if (sid_list_length ) {
     775           0 :                 struct dom_sid *sids;
     776          12 :                 uint32_t elems = 0;
     777             :                 /*
     778             :                  * error check pulled offsets and lengths for wrap and
     779             :                  * exceeding available bytes.
     780             :                  */
     781          12 :                 if (sid_list_length > sid_buf->length) {
     782           0 :                         DBG_ERR("sid_list_length 0x%x exceeds "
     783             :                                 "available bytes %zx\n",
     784             :                                 sid_list_length,
     785             :                                 sid_buf->length);
     786           0 :                         return NT_STATUS_INVALID_PARAMETER;
     787             :                 }
     788             : 
     789          12 :                 err = extract_sids_from_buf(mem_ctx, sid_list_length,
     790             :                                             sid_buf, &sids, &elems);
     791          12 :                 if (!NDR_ERR_CODE_IS_SUCCESS(err) || elems == 0) {
     792           0 :                         return NT_STATUS_INVALID_PARAMETER;
     793             :                 }
     794          12 :                 err = fill_qtlist_from_sids(mem_ctx,
     795             :                                             fsp,
     796             :                                             qt_handle,
     797             :                                             sids,
     798             :                                             elems);
     799          12 :                 if (!NDR_ERR_CODE_IS_SUCCESS(err)) {
     800           0 :                         return NT_STATUS_INVALID_PARAMETER;
     801             :                 }
     802           8 :         } else if (restart_scan) {
     803           4 :                 if (vfs_get_user_ntquota_list(fsp,
     804             :                                               &(qt_handle->quota_list))!=0) {
     805           0 :                         return NT_STATUS_INTERNAL_ERROR;
     806             :                 }
     807             :         } else {
     808           4 :                 if (qt_handle->quota_list!=NULL &&
     809           4 :                         qt_handle->tmp_list==NULL) {
     810           4 :                         free_ntquota_list(&(qt_handle->quota_list));
     811             :                 }
     812             :         }
     813             : 
     814          20 :         if (restart_scan !=0 ) {
     815           4 :                 qt_list = qt_handle->quota_list;
     816             :         } else {
     817          16 :                 qt_list = qt_handle->tmp_list;
     818             :         }
     819          20 :         status = fill_quota_buffer(mem_ctx, qt_list,
     820             :                                    return_single != 0,
     821             :                                    max_data_count,
     822             :                                    &blob,
     823             :                                    &qt_handle->tmp_list);
     824          20 :         if (!NT_STATUS_IS_OK(status)) {
     825           4 :                 return status;
     826             :         }
     827          16 :         if (blob.length > max_data_count) {
     828           0 :                 return NT_STATUS_BUFFER_TOO_SMALL;
     829             :         }
     830             : 
     831          16 :         *p_data = blob.data;
     832          16 :         *p_data_size = blob.length;
     833          16 :         return NT_STATUS_OK;
     834             : }
     835             : #endif /* HAVE_SYS_QUOTAS */

Generated by: LCOV version 1.14