LCOV - code coverage report
Current view: top level - source3/modules - vfs_acl_common.c (source / functions) Hit Total Coverage
Test: coverage report for abartlet/fix-coverage dd10fb34 Lines: 305 468 65.2 %
Date: 2021-09-23 10:06:22 Functions: 17 18 94.4 %

          Line data    Source code
       1             : /*
       2             :  * Store Windows ACLs in data store - common functions.
       3             :  * #included into modules/vfs_acl_xattr.c and modules/vfs_acl_tdb.c
       4             :  *
       5             :  * Copyright (C) Volker Lendecke, 2008
       6             :  * Copyright (C) Jeremy Allison, 2009
       7             :  * Copyright (C) Ralph Böhme, 2016
       8             :  *
       9             :  * This program is free software; you can redistribute it and/or modify
      10             :  * it under the terms of the GNU General Public License as published by
      11             :  * the Free Software Foundation; either version 3 of the License, or
      12             :  * (at your option) any later version.
      13             :  *
      14             :  * This program is distributed in the hope that it will be useful,
      15             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      16             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      17             :  * GNU General Public License for more details.
      18             :  *
      19             :  * You should have received a copy of the GNU General Public License
      20             :  * along with this program; if not, see <http://www.gnu.org/licenses/>.
      21             :  */
      22             : 
      23             : #include "includes.h"
      24             : #include "vfs_acl_common.h"
      25             : #include "smbd/smbd.h"
      26             : #include "system/filesys.h"
      27             : #include "librpc/gen_ndr/ndr_xattr.h"
      28             : #include "../libcli/security/security.h"
      29             : #include "../librpc/gen_ndr/ndr_security.h"
      30             : #include "../lib/util/bitmap.h"
      31             : #include "passdb/lookup_sid.h"
      32             : 
      33             : #include <gnutls/gnutls.h>
      34             : #include <gnutls/crypto.h>
      35             : 
      36             : static NTSTATUS create_acl_blob(const struct security_descriptor *psd,
      37             :                         DATA_BLOB *pblob,
      38             :                         uint16_t hash_type,
      39             :                         uint8_t hash[XATTR_SD_HASH_SIZE]);
      40             : 
      41             : #define HASH_SECURITY_INFO (SECINFO_OWNER | \
      42             :                                 SECINFO_GROUP | \
      43             :                                 SECINFO_DACL | \
      44             :                                 SECINFO_SACL)
      45             : 
      46       43164 : bool init_acl_common_config(vfs_handle_struct *handle,
      47             :                             const char *module_name)
      48             : {
      49       43164 :         struct acl_common_config *config = NULL;
      50       43164 :         const struct enum_list *default_acl_style_list = NULL;
      51             : 
      52       43164 :         default_acl_style_list = get_default_acl_style_list();
      53             : 
      54       43164 :         config = talloc_zero(handle->conn, struct acl_common_config);
      55       43164 :         if (config == NULL) {
      56           0 :                 DBG_ERR("talloc_zero() failed\n");
      57           0 :                 errno = ENOMEM;
      58           0 :                 return false;
      59             :         }
      60             : 
      61       43164 :         config->ignore_system_acls = lp_parm_bool(SNUM(handle->conn),
      62             :                                                   module_name,
      63             :                                                   "ignore system acls",
      64             :                                                   false);
      65       43164 :         config->default_acl_style = lp_parm_enum(SNUM(handle->conn),
      66             :                                                  module_name,
      67             :                                                  "default acl style",
      68             :                                                  default_acl_style_list,
      69             :                                                  DEFAULT_ACL_POSIX);
      70             : 
      71       43164 :         SMB_VFS_HANDLE_SET_DATA(handle, config, NULL,
      72             :                                 struct acl_common_config,
      73             :                                 return false);
      74             : 
      75       43164 :         return true;
      76             : }
      77             : 
      78             : 
      79             : /*******************************************************************
      80             :  Hash a security descriptor.
      81             : *******************************************************************/
      82             : 
      83      931515 : static NTSTATUS hash_blob_sha256(DATA_BLOB blob,
      84             :                                  uint8_t *hash)
      85             : {
      86             :         int rc;
      87             : 
      88      931515 :         ZERO_ARRAY_LEN(hash, XATTR_SD_HASH_SIZE);
      89             : 
      90     1686151 :         rc = gnutls_hash_fast(GNUTLS_DIG_SHA256,
      91      931515 :                               blob.data,
      92             :                               blob.length,
      93             :                               hash);
      94      931515 :         if (rc < 0) {
      95           0 :                 return NT_STATUS_INTERNAL_ERROR;
      96             :         }
      97             : 
      98      931515 :         return NT_STATUS_OK;
      99             : }
     100             : 
     101             : /*******************************************************************
     102             :  Hash a security descriptor.
     103             : *******************************************************************/
     104             : 
     105      152088 : static NTSTATUS hash_sd_sha256(struct security_descriptor *psd,
     106             :                         uint8_t *hash)
     107             : {
     108             :         DATA_BLOB blob;
     109             :         NTSTATUS status;
     110             : 
     111      152088 :         memset(hash, '\0', XATTR_SD_HASH_SIZE);
     112      152088 :         status = create_acl_blob(psd, &blob, XATTR_SD_HASH_TYPE_SHA256, hash);
     113      152088 :         if (!NT_STATUS_IS_OK(status)) {
     114           0 :                 return status;
     115             :         }
     116      152088 :         return hash_blob_sha256(blob, hash);
     117             : }
     118             : 
     119             : /*******************************************************************
     120             :  Parse out a struct security_descriptor from a DATA_BLOB.
     121             : *******************************************************************/
     122             : 
     123      627797 : static NTSTATUS parse_acl_blob(const DATA_BLOB *pblob,
     124             :                                TALLOC_CTX *mem_ctx,
     125             :                                struct security_descriptor **ppdesc,
     126             :                                uint16_t *p_hash_type,
     127             :                                uint16_t *p_version,
     128             :                                uint8_t hash[XATTR_SD_HASH_SIZE],
     129             :                                uint8_t sys_acl_hash[XATTR_SD_HASH_SIZE])
     130             : {
     131             :         struct xattr_NTACL xacl;
     132             :         enum ndr_err_code ndr_err;
     133             :         size_t sd_size;
     134      627797 :         TALLOC_CTX *frame = talloc_stackframe();
     135             : 
     136      627797 :         ndr_err = ndr_pull_struct_blob(pblob, frame, &xacl,
     137             :                         (ndr_pull_flags_fn_t)ndr_pull_xattr_NTACL);
     138             : 
     139      627797 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     140           0 :                 DBG_INFO("ndr_pull_xattr_NTACL failed: %s\n",
     141             :                          ndr_errstr(ndr_err));
     142           0 :                 TALLOC_FREE(frame);
     143           0 :                 return ndr_map_error2ntstatus(ndr_err);
     144             :         }
     145             : 
     146      627797 :         *p_version = xacl.version;
     147             : 
     148      627797 :         switch (xacl.version) {
     149          74 :                 case 1:
     150         185 :                         *ppdesc = make_sec_desc(mem_ctx, SD_REVISION,
     151          74 :                                         xacl.info.sd->type | SEC_DESC_SELF_RELATIVE,
     152          74 :                                         xacl.info.sd->owner_sid,
     153          74 :                                         xacl.info.sd->group_sid,
     154          74 :                                         xacl.info.sd->sacl,
     155          74 :                                         xacl.info.sd->dacl,
     156             :                                         &sd_size);
     157             :                         /* No hash - null out. */
     158          74 :                         *p_hash_type = XATTR_SD_HASH_TYPE_NONE;
     159          74 :                         memset(hash, '\0', XATTR_SD_HASH_SIZE);
     160          74 :                         break;
     161           0 :                 case 2:
     162           0 :                         *ppdesc = make_sec_desc(mem_ctx, SD_REVISION,
     163           0 :                                         xacl.info.sd_hs2->sd->type | SEC_DESC_SELF_RELATIVE,
     164           0 :                                         xacl.info.sd_hs2->sd->owner_sid,
     165           0 :                                         xacl.info.sd_hs2->sd->group_sid,
     166           0 :                                         xacl.info.sd_hs2->sd->sacl,
     167           0 :                                         xacl.info.sd_hs2->sd->dacl,
     168             :                                         &sd_size);
     169             :                         /* No hash - null out. */
     170           0 :                         *p_hash_type = XATTR_SD_HASH_TYPE_NONE;
     171           0 :                         memset(hash, '\0', XATTR_SD_HASH_SIZE);
     172           0 :                         break;
     173         134 :                 case 3:
     174         402 :                         *ppdesc = make_sec_desc(mem_ctx, SD_REVISION,
     175         134 :                                         xacl.info.sd_hs3->sd->type | SEC_DESC_SELF_RELATIVE,
     176         134 :                                         xacl.info.sd_hs3->sd->owner_sid,
     177         134 :                                         xacl.info.sd_hs3->sd->group_sid,
     178         134 :                                         xacl.info.sd_hs3->sd->sacl,
     179         134 :                                         xacl.info.sd_hs3->sd->dacl,
     180             :                                         &sd_size);
     181         134 :                         *p_hash_type = xacl.info.sd_hs3->hash_type;
     182             :                         /* Current version 3 (if no sys acl hash available). */
     183         134 :                         memcpy(hash, xacl.info.sd_hs3->hash, XATTR_SD_HASH_SIZE);
     184         134 :                         break;
     185      627589 :                 case 4:
     186     1764444 :                         *ppdesc = make_sec_desc(mem_ctx, SD_REVISION,
     187      627589 :                                         xacl.info.sd_hs4->sd->type | SEC_DESC_SELF_RELATIVE,
     188      627589 :                                         xacl.info.sd_hs4->sd->owner_sid,
     189      627589 :                                         xacl.info.sd_hs4->sd->group_sid,
     190      626631 :                                         xacl.info.sd_hs4->sd->sacl,
     191      627589 :                                         xacl.info.sd_hs4->sd->dacl,
     192             :                                         &sd_size);
     193      627589 :                         *p_hash_type = xacl.info.sd_hs4->hash_type;
     194             :                         /* Current version 4. */
     195      628547 :                         memcpy(hash, xacl.info.sd_hs4->hash, XATTR_SD_HASH_SIZE);
     196      627589 :                         memcpy(sys_acl_hash, xacl.info.sd_hs4->sys_acl_hash, XATTR_SD_HASH_SIZE);
     197      626631 :                         break;
     198           0 :                 default:
     199           0 :                         TALLOC_FREE(frame);
     200           0 :                         return NT_STATUS_REVISION_MISMATCH;
     201             :         }
     202             : 
     203      627797 :         TALLOC_FREE(frame);
     204             : 
     205      627797 :         return (*ppdesc != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
     206             : }
     207             : 
     208             : /*******************************************************************
     209             :  Create a DATA_BLOB from a hash of the security descriptor storead at
     210             :  the system layer and the NT ACL we wish to preserve
     211             : *******************************************************************/
     212             : 
     213      152124 : static NTSTATUS create_acl_blob(const struct security_descriptor *psd,
     214             :                         DATA_BLOB *pblob,
     215             :                         uint16_t hash_type,
     216             :                         uint8_t hash[XATTR_SD_HASH_SIZE])
     217             : {
     218             :         struct xattr_NTACL xacl;
     219             :         struct security_descriptor_hash_v3 sd_hs3;
     220             :         enum ndr_err_code ndr_err;
     221      152124 :         TALLOC_CTX *ctx = talloc_tos();
     222             : 
     223      152124 :         ZERO_STRUCT(xacl);
     224      152124 :         ZERO_STRUCT(sd_hs3);
     225             : 
     226      152124 :         xacl.version = 3;
     227      152124 :         xacl.info.sd_hs3 = &sd_hs3;
     228      152124 :         xacl.info.sd_hs3->sd = discard_const_p(struct security_descriptor, psd);
     229      152124 :         xacl.info.sd_hs3->hash_type = hash_type;
     230      152425 :         memcpy(&xacl.info.sd_hs3->hash[0], hash, XATTR_SD_HASH_SIZE);
     231             : 
     232      152124 :         ndr_err = ndr_push_struct_blob(
     233             :                         pblob, ctx, &xacl,
     234             :                         (ndr_push_flags_fn_t)ndr_push_xattr_NTACL);
     235             : 
     236      152124 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     237           0 :                 DBG_INFO("ndr_push_xattr_NTACL failed: %s\n",
     238             :                          ndr_errstr(ndr_err));
     239           0 :                 return ndr_map_error2ntstatus(ndr_err);
     240             :         }
     241             : 
     242      152124 :         return NT_STATUS_OK;
     243             : }
     244             : 
     245             : /*******************************************************************
     246             :  Create a DATA_BLOB from a hash of the security descriptors 
     247             :  (system and NT) stored at the system layer and the NT ACL we wish 
     248             :  to preserve.
     249             : *******************************************************************/
     250             : 
     251      151890 : static NTSTATUS create_sys_acl_blob(const struct security_descriptor *psd,
     252             :                                     DATA_BLOB *pblob,
     253             :                                     uint16_t hash_type,
     254             :                                     uint8_t hash[XATTR_SD_HASH_SIZE],
     255             :                                     const char *description,
     256             :                                     uint8_t sys_acl_hash[XATTR_SD_HASH_SIZE])
     257             : {
     258             :         struct xattr_NTACL xacl;
     259             :         struct security_descriptor_hash_v4 sd_hs4;
     260             :         enum ndr_err_code ndr_err;
     261      151890 :         TALLOC_CTX *ctx = talloc_tos();
     262             :         NTTIME nttime_now;
     263      151890 :         struct timeval now = timeval_current();
     264      151890 :         nttime_now = timeval_to_nttime(&now);
     265             : 
     266      151890 :         ZERO_STRUCT(xacl);
     267      151890 :         ZERO_STRUCT(sd_hs4);
     268             : 
     269      151890 :         xacl.version = 4;
     270      151890 :         xacl.info.sd_hs4 = &sd_hs4;
     271      151890 :         xacl.info.sd_hs4->sd = discard_const_p(struct security_descriptor, psd);
     272      151890 :         xacl.info.sd_hs4->hash_type = hash_type;
     273      152191 :         memcpy(&xacl.info.sd_hs4->hash[0], hash, XATTR_SD_HASH_SIZE);
     274      151890 :         xacl.info.sd_hs4->description = description;
     275      151890 :         xacl.info.sd_hs4->time = nttime_now;
     276      152191 :         memcpy(&xacl.info.sd_hs4->sys_acl_hash[0], sys_acl_hash, XATTR_SD_HASH_SIZE);
     277             : 
     278      151890 :         ndr_err = ndr_push_struct_blob(
     279             :                         pblob, ctx, &xacl,
     280             :                         (ndr_push_flags_fn_t)ndr_push_xattr_NTACL);
     281             : 
     282      151890 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     283           0 :                 DBG_INFO("ndr_push_xattr_NTACL failed: %s\n",
     284             :                          ndr_errstr(ndr_err));
     285           0 :                 return ndr_map_error2ntstatus(ndr_err);
     286             :         }
     287             : 
     288      151890 :         return NT_STATUS_OK;
     289             : }
     290             : 
     291             : /*******************************************************************
     292             :  Add in 3 inheritable components for a non-inheritable directory ACL.
     293             :  CREATOR_OWNER/CREATOR_GROUP/WORLD.
     294             : *******************************************************************/
     295             : 
     296       48521 : static NTSTATUS add_directory_inheritable_components(vfs_handle_struct *handle,
     297             :                                 const char *name,
     298             :                                 SMB_STRUCT_STAT *psbuf,
     299             :                                 struct security_descriptor *psd)
     300             : {
     301       48521 :         struct connection_struct *conn = handle->conn;
     302       48521 :         int num_aces = (psd->dacl ? psd->dacl->num_aces : 0);
     303             :         struct smb_filename smb_fname;
     304             :         enum security_ace_type acltype;
     305             :         uint32_t access_mask;
     306             :         mode_t dir_mode;
     307             :         mode_t file_mode;
     308             :         mode_t mode;
     309             :         struct security_ace *new_ace_list;
     310             : 
     311       48521 :         if (psd->dacl) {
     312       48521 :                 new_ace_list = talloc_zero_array(psd->dacl,
     313             :                                                  struct security_ace,
     314             :                                                  num_aces + 3);
     315             :         } else {
     316             :                 /*
     317             :                  * make_sec_acl() at the bottom of this function
     318             :                  * dupliates new_ace_list
     319             :                  */
     320           0 :                 new_ace_list = talloc_zero_array(talloc_tos(),
     321             :                                                  struct security_ace,
     322             :                                                  num_aces + 3);
     323             :         }
     324             : 
     325       48521 :         if (new_ace_list == NULL) {
     326           0 :                 return NT_STATUS_NO_MEMORY;
     327             :         }
     328             : 
     329             :         /* Fake a quick smb_filename. */
     330       48521 :         ZERO_STRUCT(smb_fname);
     331       48521 :         smb_fname.st = *psbuf;
     332       48521 :         smb_fname.base_name = discard_const_p(char, name);
     333             : 
     334       48521 :         dir_mode = unix_mode(conn,
     335             :                         FILE_ATTRIBUTE_DIRECTORY, &smb_fname, NULL);
     336       48521 :         file_mode = unix_mode(conn,
     337             :                         FILE_ATTRIBUTE_ARCHIVE, &smb_fname, NULL);
     338             : 
     339       48521 :         mode = dir_mode | file_mode;
     340             : 
     341       48521 :         DBG_DEBUG("directory %s, mode = 0%o\n", name, (unsigned int)mode);
     342             : 
     343       48521 :         if (num_aces) {
     344       48521 :                 memcpy(new_ace_list, psd->dacl->aces,
     345             :                         num_aces * sizeof(struct security_ace));
     346             :         }
     347       48521 :         access_mask = map_canon_ace_perms(SNUM(conn), &acltype,
     348             :                                 mode & 0700, false);
     349             : 
     350       48521 :         init_sec_ace(&new_ace_list[num_aces],
     351             :                         &global_sid_Creator_Owner,
     352             :                         acltype,
     353             :                         access_mask,
     354             :                         SEC_ACE_FLAG_CONTAINER_INHERIT|
     355             :                                 SEC_ACE_FLAG_OBJECT_INHERIT|
     356             :                                 SEC_ACE_FLAG_INHERIT_ONLY);
     357       48521 :         access_mask = map_canon_ace_perms(SNUM(conn), &acltype,
     358       48521 :                                 (mode << 3) & 0700, false);
     359       48521 :         init_sec_ace(&new_ace_list[num_aces+1],
     360             :                         &global_sid_Creator_Group,
     361             :                         acltype,
     362             :                         access_mask,
     363             :                         SEC_ACE_FLAG_CONTAINER_INHERIT|
     364             :                                 SEC_ACE_FLAG_OBJECT_INHERIT|
     365             :                                 SEC_ACE_FLAG_INHERIT_ONLY);
     366       48521 :         access_mask = map_canon_ace_perms(SNUM(conn), &acltype,
     367       48521 :                                 (mode << 6) & 0700, false);
     368       48521 :         init_sec_ace(&new_ace_list[num_aces+2],
     369             :                         &global_sid_World,
     370             :                         acltype,
     371             :                         access_mask,
     372             :                         SEC_ACE_FLAG_CONTAINER_INHERIT|
     373             :                                 SEC_ACE_FLAG_OBJECT_INHERIT|
     374             :                                 SEC_ACE_FLAG_INHERIT_ONLY);
     375       48521 :         if (psd->dacl) {
     376       48521 :                 psd->dacl->aces = new_ace_list;
     377       48521 :                 psd->dacl->num_aces += 3;
     378      130221 :                 psd->dacl->size += new_ace_list[num_aces].size +
     379       89371 :                         new_ace_list[num_aces+1].size +
     380       48521 :                         new_ace_list[num_aces+2].size;
     381             :         } else {
     382           0 :                 psd->dacl = make_sec_acl(psd,
     383             :                                 NT4_ACL_REVISION,
     384             :                                 3,
     385             :                                 new_ace_list);
     386           0 :                 if (psd->dacl == NULL) {
     387           0 :                         return NT_STATUS_NO_MEMORY;
     388             :                 }
     389             :         }
     390       48521 :         return NT_STATUS_OK;
     391             : }
     392             : 
     393             : /**
     394             :  * Validate an ACL blob
     395             :  *
     396             :  * This validates an ACL blob against the underlying filesystem ACL. If this
     397             :  * function returns NT_STATUS_OK ppsd can be
     398             :  *
     399             :  * 1. the ACL from the blob (psd_from_fs=false), or
     400             :  * 2. the ACL from the fs (psd_from_fs=true), or
     401             :  * 3. NULL (!)
     402             :  *
     403             :  * If the return value is anything else then NT_STATUS_OK, ppsd is set to NULL
     404             :  * and psd_from_fs set to false.
     405             :  *
     406             :  * Returning the underlying filesystem ACL in case no. 2 is really just an
     407             :  * optimisation, because some validations have to fetch the filesytem ACL as
     408             :  * part of the validation, so we already have it available and callers might
     409             :  * need it as well.
     410             :  **/
     411      627797 : static NTSTATUS validate_nt_acl_blob(TALLOC_CTX *mem_ctx,
     412             :                                 vfs_handle_struct *handle,
     413             :                                 struct files_struct *fsp,
     414             :                                 const struct smb_filename *smb_fname,
     415             :                                 const DATA_BLOB *blob,
     416             :                                 struct security_descriptor **ppsd,
     417             :                                 bool *psd_is_from_fs)
     418             : {
     419             :         NTSTATUS status;
     420      627797 :         uint16_t hash_type = XATTR_SD_HASH_TYPE_NONE;
     421      627797 :         uint16_t xattr_version = 0;
     422             :         uint8_t hash[XATTR_SD_HASH_SIZE];
     423             :         uint8_t sys_acl_hash[XATTR_SD_HASH_SIZE];
     424             :         uint8_t hash_tmp[XATTR_SD_HASH_SIZE];
     425             :         uint8_t sys_acl_hash_tmp[XATTR_SD_HASH_SIZE];
     426      627797 :         struct security_descriptor *psd = NULL;
     427      627797 :         struct security_descriptor *psd_blob = NULL;
     428      627797 :         struct security_descriptor *psd_fs = NULL;
     429      627797 :         char *sys_acl_blob_description = NULL;
     430      627797 :         DATA_BLOB sys_acl_blob = { 0 };
     431      627797 :         struct acl_common_config *config = NULL;
     432             : 
     433      627797 :         *ppsd = NULL;
     434      627797 :         *psd_is_from_fs = false;
     435             : 
     436      627797 :         SMB_VFS_HANDLE_GET_DATA(handle, config,
     437             :                                 struct acl_common_config,
     438             :                                 return NT_STATUS_UNSUCCESSFUL);
     439             : 
     440      627797 :         status = parse_acl_blob(blob,
     441             :                                 mem_ctx,
     442             :                                 &psd_blob,
     443             :                                 &hash_type,
     444             :                                 &xattr_version,
     445             :                                 &hash[0],
     446             :                                 &sys_acl_hash[0]);
     447      627797 :         if (!NT_STATUS_IS_OK(status)) {
     448           0 :                 DBG_DEBUG("parse_acl_blob returned %s\n", nt_errstr(status));
     449           0 :                 goto fail;
     450             :         }
     451             : 
     452             :         /* determine which type of xattr we got */
     453      627797 :         switch (xattr_version) {
     454          74 :         case 1:
     455             :         case 2:
     456             :                 /* These xattr types are unilatteral, they do not
     457             :                  * require confirmation of the hash.  In particular,
     458             :                  * the NTVFS file server uses version 1, but
     459             :                  * 'samba-tool ntacl' can set these as well */
     460          74 :                 *ppsd = psd_blob;
     461          74 :                 return NT_STATUS_OK;
     462      627723 :         case 3:
     463             :         case 4:
     464      627723 :                 if (config->ignore_system_acls) {
     465         180 :                         *ppsd = psd_blob;
     466         180 :                         return NT_STATUS_OK;
     467             :                 }
     468             : 
     469      626585 :                 break;
     470           0 :         default:
     471           0 :                 DBG_DEBUG("ACL blob revision mismatch (%u) for file %s\n",
     472             :                           (unsigned int)hash_type, smb_fname->base_name);
     473           0 :                 TALLOC_FREE(psd_blob);
     474           0 :                 return NT_STATUS_OK;
     475             :         }
     476             : 
     477             :         /* determine which type of xattr we got */
     478      627543 :         if (hash_type != XATTR_SD_HASH_TYPE_SHA256) {
     479           0 :                 DBG_DEBUG("ACL blob hash type (%u) unexpected for file %s\n",
     480             :                           (unsigned int)hash_type, smb_fname->base_name);
     481           0 :                 TALLOC_FREE(psd_blob);
     482           0 :                 return NT_STATUS_OK;
     483             :         }
     484             : 
     485             :         /* determine which type of xattr we got */
     486      627543 :         switch (xattr_version) {
     487      627537 :         case 4:
     488             :         {
     489             :                 int ret;
     490             :                 /* Get the full underlying sd, then hash. */
     491      627537 :                 ret = SMB_VFS_NEXT_SYS_ACL_BLOB_GET_FD(handle,
     492             :                                                        fsp,
     493             :                                                        mem_ctx,
     494             :                                                        &sys_acl_blob_description,
     495             :                                                        &sys_acl_blob);
     496             :                 /* If we fail to get the ACL blob (for some reason) then this
     497             :                  * is not fatal, we just work based on the NT ACL only */
     498      627537 :                 if (ret == 0) {
     499      627537 :                         status = hash_blob_sha256(sys_acl_blob, sys_acl_hash_tmp);
     500      627537 :                         if (!NT_STATUS_IS_OK(status)) {
     501           0 :                                 goto fail;
     502             :                         }
     503             : 
     504      627537 :                         TALLOC_FREE(sys_acl_blob_description);
     505      627537 :                         TALLOC_FREE(sys_acl_blob.data);
     506             : 
     507      627537 :                         if (memcmp(&sys_acl_hash[0], &sys_acl_hash_tmp[0], 
     508             :                                    XATTR_SD_HASH_SIZE) == 0) {
     509             :                                 /* Hash matches, return blob sd. */
     510      627345 :                                 DBG_DEBUG("blob hash matches for file %s\n",
     511             :                                           smb_fname->base_name);
     512      627345 :                                 *ppsd = psd_blob;
     513      627345 :                                 return NT_STATUS_OK;
     514             :                         }
     515             :                 }
     516             : 
     517             :                 /* Otherwise, fall though and see if the NT ACL hash matches */
     518             :                 FALL_THROUGH;
     519             :         }
     520             :         case 3:
     521             :                 /* Get the full underlying sd for the hash
     522             :                    or to return as backup. */
     523         198 :                 status = SMB_VFS_NEXT_FGET_NT_ACL(handle,
     524             :                                                   fsp,
     525             :                                                   HASH_SECURITY_INFO,
     526             :                                                   mem_ctx,
     527             :                                                   &psd_fs);
     528         198 :                 if (!NT_STATUS_IS_OK(status)) {
     529           0 :                         DBG_DEBUG("get_next_acl for file %s returned %s\n",
     530             :                                   smb_fname->base_name, nt_errstr(status));
     531           0 :                         goto fail;
     532             :                 }
     533             : 
     534         198 :                 status = hash_sd_sha256(psd_fs, hash_tmp);
     535         198 :                 if (!NT_STATUS_IS_OK(status)) {
     536           0 :                         TALLOC_FREE(psd_blob);
     537           0 :                         *ppsd = psd_fs;
     538           0 :                         *psd_is_from_fs = true;
     539           0 :                         return NT_STATUS_OK;
     540             :                 }
     541             : 
     542         198 :                 if (memcmp(&hash[0], &hash_tmp[0], XATTR_SD_HASH_SIZE) == 0) {
     543             :                         /* Hash matches, return blob sd. */
     544          15 :                         DBG_DEBUG("blob hash matches for file %s\n",
     545             :                                   smb_fname->base_name);
     546          15 :                         *ppsd = psd_blob;
     547          15 :                         return NT_STATUS_OK;
     548             :                 }
     549             : 
     550             :                 /* Hash doesn't match, return underlying sd. */
     551         183 :                 DBG_DEBUG("blob hash does not match for file %s - returning "
     552             :                           "file system SD mapping.\n",
     553             :                           smb_fname->base_name);
     554             : 
     555         183 :                 if (DEBUGLEVEL >= 10) {
     556           0 :                         DBG_DEBUG("acl for blob hash for %s is:\n",
     557             :                                   smb_fname->base_name);
     558           0 :                         NDR_PRINT_DEBUG(security_descriptor, psd_fs);
     559             :                 }
     560             : 
     561         183 :                 TALLOC_FREE(psd_blob);
     562         183 :                 *ppsd = psd_fs;
     563         183 :                 *psd_is_from_fs = true;
     564             :         }
     565             : 
     566         183 :         return NT_STATUS_OK;
     567             : 
     568           0 : fail:
     569           0 :         TALLOC_FREE(psd);
     570           0 :         TALLOC_FREE(psd_blob);
     571           0 :         TALLOC_FREE(psd_fs);
     572           0 :         TALLOC_FREE(sys_acl_blob_description);
     573           0 :         TALLOC_FREE(sys_acl_blob.data);
     574           0 :         return status;
     575             : }
     576             : 
     577             : /*******************************************************************
     578             :  Pull a DATA_BLOB from an xattr given an fsp.
     579             :  If the hash doesn't match, or doesn't exist - return the underlying
     580             :  filesystem sd.
     581             : *******************************************************************/
     582             : 
     583      816180 : NTSTATUS fget_nt_acl_common(
     584             :         NTSTATUS (*fget_acl_blob_fn)(TALLOC_CTX *ctx,
     585             :                                     vfs_handle_struct *handle,
     586             :                                     files_struct *fsp,
     587             :                                     DATA_BLOB *pblob),
     588             :         vfs_handle_struct *handle,
     589             :         files_struct *fsp,
     590             :         uint32_t security_info,
     591             :         TALLOC_CTX *mem_ctx,
     592             :         struct security_descriptor **ppdesc)
     593             : {
     594      816180 :         DATA_BLOB blob = data_blob_null;
     595             :         NTSTATUS status;
     596      816180 :         struct security_descriptor *psd = NULL;
     597      816180 :         const struct smb_filename *smb_fname = fsp->fsp_name;
     598      816180 :         bool psd_is_from_fs = false;
     599      816180 :         struct acl_common_config *config = NULL;
     600             : 
     601      816180 :         SMB_VFS_HANDLE_GET_DATA(handle, config,
     602             :                                 struct acl_common_config,
     603             :                                 return NT_STATUS_UNSUCCESSFUL);
     604             : 
     605      816180 :         DBG_DEBUG("name=%s\n", smb_fname->base_name);
     606             : 
     607      816180 :         status = fget_acl_blob_fn(mem_ctx, handle, fsp, &blob);
     608      816180 :         if (NT_STATUS_IS_OK(status)) {
     609      627797 :                 status = validate_nt_acl_blob(mem_ctx,
     610             :                                         handle,
     611             :                                         fsp,
     612             :                                         smb_fname,
     613             :                                         &blob,
     614             :                                         &psd,
     615             :                                         &psd_is_from_fs);
     616      627797 :                 TALLOC_FREE(blob.data);
     617      627797 :                 if (!NT_STATUS_IS_OK(status)) {
     618           0 :                         DBG_DEBUG("ACL validation for [%s] failed\n",
     619             :                                   smb_fname->base_name);
     620           0 :                         goto fail;
     621             :                 }
     622             :         }
     623             : 
     624      816180 :         if (psd == NULL) {
     625             :                 /* Get the full underlying sd, as we failed to get the
     626             :                  * blob for the hash, or the revision/hash type wasn't
     627             :                  * known */
     628             : 
     629      188383 :                 if (config->ignore_system_acls) {
     630         244 :                         status = vfs_stat_fsp(fsp);
     631         244 :                         if (!NT_STATUS_IS_OK(status)) {
     632           0 :                                 goto fail;
     633             :                         }
     634             : 
     635         244 :                         status = make_default_filesystem_acl(
     636             :                                 mem_ctx,
     637             :                                 config->default_acl_style,
     638         244 :                                 smb_fname->base_name,
     639         244 :                                 &fsp->fsp_name->st,
     640             :                                 &psd);
     641         244 :                         if (!NT_STATUS_IS_OK(status)) {
     642           0 :                                 goto fail;
     643             :                         }
     644             :                 } else {
     645      188139 :                         status = SMB_VFS_NEXT_FGET_NT_ACL(handle,
     646             :                                                           fsp,
     647             :                                                           security_info,
     648             :                                                           mem_ctx,
     649             :                                                           &psd);
     650             : 
     651      188139 :                         if (!NT_STATUS_IS_OK(status)) {
     652           0 :                                 DBG_DEBUG("get_next_acl for file %s "
     653             :                                           "returned %s\n",
     654             :                                           smb_fname->base_name,
     655             :                                           nt_errstr(status));
     656           0 :                                 goto fail;
     657             :                         }
     658             : 
     659      188139 :                         psd_is_from_fs = true;
     660             :                 }
     661             :         }
     662             : 
     663      816180 :         if (psd_is_from_fs) {
     664      188322 :                 status = vfs_stat_fsp(fsp);
     665      188322 :                 if (!NT_STATUS_IS_OK(status)) {
     666           0 :                         goto fail;
     667             :                 }
     668             : 
     669             :                 /*
     670             :                  * We're returning the underlying ACL from the
     671             :                  * filesystem. If it's a directory, and has no
     672             :                  * inheritable ACE entries we have to fake them.
     673             :                  */
     674             : 
     675      229276 :                 if (fsp->fsp_flags.is_directory &&
     676       48625 :                                 !sd_has_inheritable_components(psd, true)) {
     677      130221 :                         status = add_directory_inheritable_components(
     678             :                                 handle,
     679       48521 :                                 smb_fname->base_name,
     680       48521 :                                 &fsp->fsp_name->st,
     681             :                                 psd);
     682       48521 :                         if (!NT_STATUS_IS_OK(status)) {
     683           0 :                                 goto fail;
     684             :                         }
     685             :                 }
     686             : 
     687             :                 /*
     688             :                  * The underlying POSIX module always sets the
     689             :                  * ~SEC_DESC_DACL_PROTECTED bit, as ACLs can't be inherited in
     690             :                  * this way under POSIX. Remove it for Windows-style ACLs.
     691             :                  */
     692      188322 :                 psd->type &= ~SEC_DESC_DACL_PROTECTED;
     693             :         }
     694             : 
     695      816180 :         if (!(security_info & SECINFO_OWNER)) {
     696      295319 :                 psd->owner_sid = NULL;
     697             :         }
     698      816180 :         if (!(security_info & SECINFO_GROUP)) {
     699      300179 :                 psd->group_sid = NULL;
     700             :         }
     701      816180 :         if (!(security_info & SECINFO_DACL)) {
     702           6 :                 psd->type &= ~SEC_DESC_DACL_PRESENT;
     703           6 :                 psd->dacl = NULL;
     704             :         }
     705      816180 :         if (!(security_info & SECINFO_SACL)) {
     706      663436 :                 psd->type &= ~SEC_DESC_SACL_PRESENT;
     707      663436 :                 psd->sacl = NULL;
     708             :         }
     709             : 
     710      816180 :         if (DEBUGLEVEL >= 10) {
     711           0 :                 DBG_DEBUG("returning acl for %s is:\n",
     712             :                           smb_fname->base_name);
     713           0 :                 NDR_PRINT_DEBUG(security_descriptor, psd);
     714             :         }
     715             : 
     716      816180 :         *ppdesc = psd;
     717             : 
     718      816180 :         return NT_STATUS_OK;
     719             : 
     720           0 : fail:
     721           0 :         TALLOC_FREE(psd);
     722           0 :         return status;
     723             : }
     724             : 
     725             : /*********************************************************************
     726             :  Set the underlying ACL (e.g. POSIX ACLS, POSIX owner, etc)
     727             : *********************************************************************/
     728      151912 : static NTSTATUS set_underlying_acl(vfs_handle_struct *handle, files_struct *fsp,
     729             :                                    struct security_descriptor *psd,
     730             :                                    uint32_t security_info_sent,
     731             :                                    bool chown_needed)
     732             : {
     733             :         NTSTATUS status;
     734      151912 :         const struct security_token *token = NULL;
     735             :         struct dom_sid_buf buf;
     736             : 
     737      151912 :         status = SMB_VFS_NEXT_FSET_NT_ACL(handle, fsp, security_info_sent, psd);
     738      151912 :         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
     739      151912 :                 return status;
     740             :         }
     741             : 
     742             :         /* We got access denied here. If we're already root,
     743             :            or we didn't need to do a chown, or the fsp isn't
     744             :            open with WRITE_OWNER access, just return. */
     745           0 :         if (get_current_uid(handle->conn) == 0 || chown_needed == false ||
     746           0 :             !(fsp->access_mask & SEC_STD_WRITE_OWNER)) {
     747           0 :                 return NT_STATUS_ACCESS_DENIED;
     748             :         }
     749             : 
     750             :         /*
     751             :          * Only allow take-ownership, not give-ownership. That's the way Windows
     752             :          * implements SEC_STD_WRITE_OWNER. MS-FSA 2.1.5.16 just states: If
     753             :          * InputBuffer.OwnerSid is not a valid owner SID for a file in the
     754             :          * objectstore, as determined in an implementation specific manner, the
     755             :          * object store MUST return STATUS_INVALID_OWNER.
     756             :          */
     757           0 :         token = get_current_nttok(fsp->conn);
     758           0 :         if (!security_token_is_sid(token, psd->owner_sid)) {
     759           0 :                 return NT_STATUS_INVALID_OWNER;
     760             :         }
     761             : 
     762           0 :         DBG_DEBUG("overriding chown on file %s for sid %s\n",
     763             :                   fsp_str_dbg(fsp),
     764             :                   dom_sid_str_buf(psd->owner_sid, &buf));
     765             : 
     766             :         /* Ok, we failed to chown and we have
     767             :            SEC_STD_WRITE_OWNER access - override. */
     768           0 :         become_root();
     769           0 :         status = SMB_VFS_NEXT_FSET_NT_ACL(handle, fsp, security_info_sent, psd);
     770           0 :         unbecome_root();
     771             : 
     772           0 :         return status;
     773             : }
     774             : 
     775             : /*********************************************************************
     776             :  Store a v3 security descriptor
     777             : *********************************************************************/
     778          36 : static NTSTATUS store_v3_blob(
     779             :         NTSTATUS (*store_acl_blob_fsp_fn)(vfs_handle_struct *handle,
     780             :                                           files_struct *fsp,
     781             :                                           DATA_BLOB *pblob),
     782             :         vfs_handle_struct *handle, files_struct *fsp,
     783             :         struct security_descriptor *psd,
     784             :         struct security_descriptor *pdesc_next,
     785             :         uint8_t hash[XATTR_SD_HASH_SIZE])
     786             : {
     787             :         NTSTATUS status;
     788             :         DATA_BLOB blob;
     789             : 
     790          36 :         if (DEBUGLEVEL >= 10) {
     791           0 :                 DBG_DEBUG("storing xattr sd for file %s\n",
     792             :                           fsp_str_dbg(fsp));
     793           0 :                 NDR_PRINT_DEBUG(
     794             :                     security_descriptor,
     795             :                     discard_const_p(struct security_descriptor, psd));
     796             : 
     797           0 :                 if (pdesc_next != NULL) {
     798           0 :                         DBG_DEBUG("storing xattr sd based on \n");
     799           0 :                         NDR_PRINT_DEBUG(
     800             :                             security_descriptor,
     801             :                             discard_const_p(struct security_descriptor,
     802             :                                             pdesc_next));
     803             :                 } else {
     804           0 :                         DBG_DEBUG("ignoring underlying sd\n");
     805             :                 }
     806             :         }
     807          36 :         status = create_acl_blob(psd, &blob, XATTR_SD_HASH_TYPE_SHA256, hash);
     808          36 :         if (!NT_STATUS_IS_OK(status)) {
     809           0 :                 DBG_DEBUG("create_acl_blob failed\n");
     810           0 :                 return status;
     811             :         }
     812             : 
     813          36 :         status = store_acl_blob_fsp_fn(handle, fsp, &blob);
     814          36 :         return status;
     815             : }
     816             : 
     817             : /*********************************************************************
     818             :  Store a security descriptor given an fsp.
     819             : *********************************************************************/
     820             : 
     821      151928 : NTSTATUS fset_nt_acl_common(
     822             :         NTSTATUS (*fget_acl_blob_fn)(TALLOC_CTX *ctx,
     823             :                                     vfs_handle_struct *handle,
     824             :                                     files_struct *fsp,
     825             :                                     DATA_BLOB *pblob),
     826             :         NTSTATUS (*store_acl_blob_fsp_fn)(vfs_handle_struct *handle,
     827             :                                           files_struct *fsp,
     828             :                                           DATA_BLOB *pblob),
     829             :         const char *module_name,
     830             :         vfs_handle_struct *handle, files_struct *fsp,
     831             :         uint32_t security_info_sent,
     832             :         const struct security_descriptor *orig_psd)
     833             : {
     834             :         NTSTATUS status;
     835             :         int ret;
     836             :         DATA_BLOB blob, sys_acl_blob;
     837      151928 :         struct security_descriptor *pdesc_next = NULL;
     838      151928 :         struct security_descriptor *psd = NULL;
     839             :         uint8_t hash[XATTR_SD_HASH_SIZE];
     840             :         uint8_t sys_acl_hash[XATTR_SD_HASH_SIZE];
     841      151928 :         bool chown_needed = false;
     842             :         char *sys_acl_description;
     843      151928 :         TALLOC_CTX *frame = talloc_stackframe();
     844      274102 :         bool ignore_file_system_acl = lp_parm_bool(
     845      274102 :             SNUM(handle->conn), module_name, "ignore system acls", false);
     846      151928 :         struct acl_common_fsp_ext *ext = NULL;
     847             : 
     848      151928 :         if (DEBUGLEVEL >= 10) {
     849           0 :                 DBG_DEBUG("incoming sd for file %s\n", fsp_str_dbg(fsp));
     850           0 :                 NDR_PRINT_DEBUG(security_descriptor,
     851             :                         discard_const_p(struct security_descriptor, orig_psd));
     852             :         }
     853             : 
     854      151928 :         status = fget_nt_acl_common(fget_acl_blob_fn, handle, fsp,
     855             :                         SECINFO_OWNER|SECINFO_GROUP|SECINFO_DACL|SECINFO_SACL,
     856             :                                      frame,
     857             :                         &psd);
     858             : 
     859      151928 :         if (!NT_STATUS_IS_OK(status)) {
     860           0 :                 TALLOC_FREE(frame);
     861           0 :                 return status;
     862             :         }
     863             : 
     864      151928 :         psd->revision = orig_psd->revision;
     865      151928 :         if (security_info_sent & SECINFO_DACL) {
     866      149842 :                 psd->type = orig_psd->type;
     867             :                 /* All our SD's are self relative. */
     868      149842 :                 psd->type |= SEC_DESC_SELF_RELATIVE;
     869             :         }
     870             : 
     871      151928 :         if ((security_info_sent & SECINFO_OWNER) && (orig_psd->owner_sid != NULL)) {
     872      147457 :                 if (!dom_sid_equal(orig_psd->owner_sid, psd->owner_sid)) {
     873             :                         /* We're changing the owner. */
     874       59533 :                         chown_needed = true;
     875             :                 }
     876      147457 :                 psd->owner_sid = orig_psd->owner_sid;
     877             :         }
     878      151928 :         if ((security_info_sent & SECINFO_GROUP) && (orig_psd->group_sid != NULL)) {
     879      145167 :                 if (!dom_sid_equal(orig_psd->group_sid, psd->group_sid)) {
     880             :                         /* We're changing the group. */
     881      143332 :                         chown_needed = true;
     882             :                 }
     883      145167 :                 psd->group_sid = orig_psd->group_sid;
     884             :         }
     885      151928 :         if (security_info_sent & SECINFO_DACL) {
     886      149842 :                 if (security_descriptor_with_ms_nfs(orig_psd)) {
     887             :                         /*
     888             :                          * If the sd contains a MS NFS SID, do
     889             :                          * nothing, it's a chmod() request from OS X
     890             :                          * with AAPL context.
     891             :                          */
     892           0 :                         TALLOC_FREE(frame);
     893           0 :                         return NT_STATUS_OK;
     894             :                 }
     895      149842 :                 psd->dacl = orig_psd->dacl;
     896      149842 :                 psd->type |= SEC_DESC_DACL_PRESENT;
     897             :         }
     898      151928 :         if (security_info_sent & SECINFO_SACL) {
     899        1855 :                 psd->sacl = orig_psd->sacl;
     900        1855 :                 psd->type |= SEC_DESC_SACL_PRESENT;
     901             :         }
     902             : 
     903      151928 :         ext = VFS_ADD_FSP_EXTENSION(handle,
     904             :                                     fsp,
     905             :                                     struct acl_common_fsp_ext,
     906             :                                     NULL);
     907      151928 :         ext->setting_nt_acl = true;
     908             : 
     909      151928 :         if (ignore_file_system_acl) {
     910          36 :                 if (chown_needed) {
     911             :                         /* send only ownership stuff to lower layer */
     912          20 :                         security_info_sent &= (SECINFO_OWNER | SECINFO_GROUP);
     913          20 :                         status = set_underlying_acl(handle, fsp, psd,
     914             :                                                     security_info_sent, true);
     915          20 :                         if (!NT_STATUS_IS_OK(status)) {
     916           0 :                                 goto done;
     917             :                         }
     918             :                 }
     919          36 :                 ZERO_ARRAY(hash);
     920          36 :                 status = store_v3_blob(store_acl_blob_fsp_fn, handle, fsp, psd,
     921             :                                        NULL, hash);
     922          36 :                 goto done;
     923             :         }
     924             : 
     925      151892 :         status = set_underlying_acl(handle, fsp, psd, security_info_sent,
     926             :                                     chown_needed);
     927      151892 :         if (!NT_STATUS_IS_OK(status)) {
     928           2 :                 goto done;
     929             :         }
     930             : 
     931             :         /* Get the full underlying sd, then hash. */
     932      151890 :         status = SMB_VFS_NEXT_FGET_NT_ACL(handle,
     933             :                                           fsp,
     934             :                                           HASH_SECURITY_INFO,
     935             :                                           frame,
     936             :                                           &pdesc_next);
     937             : 
     938      151890 :         if (!NT_STATUS_IS_OK(status)) {
     939           0 :                 goto done;
     940             :         }
     941             : 
     942      151890 :         status = hash_sd_sha256(pdesc_next, hash);
     943      151890 :         if (!NT_STATUS_IS_OK(status)) {
     944           0 :                 goto done;
     945             :         }
     946             : 
     947             :         /* Get the full underlying sd, then hash. */
     948      151890 :         ret = SMB_VFS_NEXT_SYS_ACL_BLOB_GET_FD(handle,
     949             :                                                fsp,
     950             :                                                frame,
     951             :                                                &sys_acl_description,
     952             :                                                &sys_acl_blob);
     953             : 
     954             :         /* If we fail to get the ACL blob (for some reason) then this
     955             :          * is not fatal, we just work based on the NT ACL only */
     956      151890 :         if (ret != 0) {
     957           0 :                 status = store_v3_blob(store_acl_blob_fsp_fn, handle, fsp, psd,
     958             :                                        pdesc_next, hash);
     959             : 
     960           0 :                 goto done;
     961             :         }
     962             : 
     963      151890 :         status = hash_blob_sha256(sys_acl_blob, sys_acl_hash);
     964      151890 :         if (!NT_STATUS_IS_OK(status)) {
     965           0 :                 goto done;
     966             :         }
     967             : 
     968      151890 :         if (DEBUGLEVEL >= 10) {
     969           0 :                 DBG_DEBUG("storing xattr sd for file %s based on system ACL\n",
     970             :                           fsp_str_dbg(fsp));
     971           0 :                 NDR_PRINT_DEBUG(security_descriptor,
     972             :                                 discard_const_p(struct security_descriptor, psd));
     973             : 
     974           0 :                 DBG_DEBUG("storing hash in xattr sd based on system ACL and:\n");
     975           0 :                 NDR_PRINT_DEBUG(security_descriptor,
     976             :                                 discard_const_p(struct security_descriptor, pdesc_next));
     977             :         }
     978             : 
     979             :         /* We store hashes of both the sys ACL blob and the NT
     980             :          * security desciptor mapped from that ACL so as to improve
     981             :          * our chances against some inadvertant change breaking the
     982             :          * hash used */
     983      151890 :         status = create_sys_acl_blob(psd, &blob, XATTR_SD_HASH_TYPE_SHA256, hash, 
     984             :                                      sys_acl_description, sys_acl_hash);
     985      151890 :         if (!NT_STATUS_IS_OK(status)) {
     986           0 :                 DBG_DEBUG("create_sys_acl_blob failed\n");
     987           0 :                 goto done;
     988             :         }
     989             : 
     990      151890 :         status = store_acl_blob_fsp_fn(handle, fsp, &blob);
     991             : 
     992      151928 : done:
     993      151928 :         VFS_REMOVE_FSP_EXTENSION(handle, fsp);
     994      151928 :         TALLOC_FREE(frame);
     995      151928 :         return status;
     996             : }
     997             : 
     998           0 : static int acl_common_remove_object(vfs_handle_struct *handle,
     999             :                                         struct files_struct *dirfsp,
    1000             :                                         const struct smb_filename *smb_fname,
    1001             :                                         bool is_directory)
    1002             : {
    1003           0 :         connection_struct *conn = handle->conn;
    1004             :         struct file_id id;
    1005           0 :         files_struct *fsp = NULL;
    1006           0 :         int ret = 0;
    1007           0 :         struct smb_filename *full_fname = NULL;
    1008           0 :         struct smb_filename *local_fname = NULL;
    1009           0 :         struct smb_filename *parent_dir_fname = NULL;
    1010           0 :         int saved_errno = 0;
    1011           0 :         struct smb_filename *saved_dir_fname = NULL;
    1012             :         NTSTATUS status;
    1013             : 
    1014           0 :         saved_dir_fname = vfs_GetWd(talloc_tos(),conn);
    1015           0 :         if (saved_dir_fname == NULL) {
    1016           0 :                 saved_errno = errno;
    1017           0 :                 goto out;
    1018             :         }
    1019             : 
    1020           0 :         full_fname = full_path_from_dirfsp_atname(talloc_tos(),
    1021             :                                                   dirfsp,
    1022             :                                                   smb_fname);
    1023           0 :         if (full_fname == NULL) {
    1024           0 :                 goto out;
    1025             :         }
    1026             : 
    1027           0 :         status = SMB_VFS_PARENT_PATHNAME(conn,
    1028             :                                          talloc_tos(),
    1029             :                                          full_fname,
    1030             :                                          &parent_dir_fname,
    1031             :                                          &local_fname);
    1032           0 :         if (!NT_STATUS_IS_OK(status)) {
    1033           0 :                 saved_errno = map_errno_from_nt_status(status);
    1034           0 :                 goto out;
    1035             :         }
    1036             : 
    1037           0 :         DBG_DEBUG("removing %s %s\n", is_directory ? "directory" : "file",
    1038             :                   smb_fname_str_dbg(full_fname));
    1039             : 
    1040             :         /* cd into the parent dir to pin it. */
    1041           0 :         ret = vfs_ChDir(conn, parent_dir_fname);
    1042           0 :         if (ret == -1) {
    1043           0 :                 saved_errno = errno;
    1044           0 :                 goto out;
    1045             :         }
    1046             : 
    1047             :         /* Must use lstat here. */
    1048           0 :         ret = SMB_VFS_LSTAT(conn, local_fname);
    1049           0 :         if (ret == -1) {
    1050           0 :                 saved_errno = errno;
    1051           0 :                 goto out;
    1052             :         }
    1053             : 
    1054             :         /* Ensure we have this file open with DELETE access. */
    1055           0 :         id = vfs_file_id_from_sbuf(conn, &local_fname->st);
    1056           0 :         for (fsp = file_find_di_first(conn->sconn, id, true); fsp;
    1057           0 :                      fsp = file_find_di_next(fsp, true)) {
    1058           0 :                 if (fsp->access_mask & DELETE_ACCESS &&
    1059             :                     fsp->fsp_flags.delete_on_close)
    1060             :                 {
    1061             :                         /* We did open this for delete,
    1062             :                          * allow the delete as root.
    1063             :                          */
    1064           0 :                         break;
    1065             :                 }
    1066             :         }
    1067             : 
    1068           0 :         if (!fsp) {
    1069           0 :                 DBG_DEBUG("%s %s not an open file\n",
    1070             :                           is_directory ? "directory" : "file",
    1071             :                           smb_fname_str_dbg(full_fname));
    1072           0 :                 saved_errno = EACCES;
    1073           0 :                 goto out;
    1074             :         }
    1075             : 
    1076           0 :         become_root();
    1077           0 :         if (is_directory) {
    1078           0 :                 ret = SMB_VFS_NEXT_UNLINKAT(handle,
    1079             :                                 dirfsp,
    1080             :                                 smb_fname,
    1081             :                                 AT_REMOVEDIR);
    1082             :         } else {
    1083           0 :                 ret = SMB_VFS_NEXT_UNLINKAT(handle,
    1084             :                                 dirfsp,
    1085             :                                 smb_fname,
    1086             :                                 0);
    1087             :         }
    1088           0 :         unbecome_root();
    1089             : 
    1090           0 :         if (ret == -1) {
    1091           0 :                 saved_errno = errno;
    1092             :         }
    1093             : 
    1094           0 :   out:
    1095             : 
    1096           0 :         TALLOC_FREE(parent_dir_fname);
    1097           0 :         TALLOC_FREE(full_fname);
    1098             : 
    1099           0 :         if (saved_dir_fname) {
    1100           0 :                 vfs_ChDir(conn, saved_dir_fname);
    1101           0 :                 TALLOC_FREE(saved_dir_fname);
    1102             :         }
    1103           0 :         if (saved_errno) {
    1104           0 :                 errno = saved_errno;
    1105             :         }
    1106           0 :         return ret;
    1107             : }
    1108             : 
    1109        9637 : int rmdir_acl_common(struct vfs_handle_struct *handle,
    1110             :                 struct files_struct *dirfsp,
    1111             :                 const struct smb_filename *smb_fname)
    1112             : {
    1113             :         int ret;
    1114             : 
    1115             :         /* Try the normal rmdir first. */
    1116        9637 :         ret = SMB_VFS_NEXT_UNLINKAT(handle,
    1117             :                         dirfsp,
    1118             :                         smb_fname,
    1119             :                         AT_REMOVEDIR);
    1120        9637 :         if (ret == 0) {
    1121        9566 :                 return 0;
    1122             :         }
    1123           8 :         if (errno == EACCES || errno == EPERM) {
    1124             :                 /* Failed due to access denied,
    1125             :                    see if we need to root override. */
    1126           0 :                 return acl_common_remove_object(handle,
    1127             :                                                 dirfsp,
    1128             :                                                 smb_fname,
    1129             :                                                 true);
    1130             :         }
    1131             : 
    1132           8 :         DBG_DEBUG("unlink of %s failed %s\n",
    1133             :                   smb_fname->base_name,
    1134             :                   strerror(errno));
    1135           8 :         return -1;
    1136             : }
    1137             : 
    1138      133351 : int unlink_acl_common(struct vfs_handle_struct *handle,
    1139             :                         struct files_struct *dirfsp,
    1140             :                         const struct smb_filename *smb_fname,
    1141             :                         int flags)
    1142             : {
    1143             :         int ret;
    1144             : 
    1145             :         /* Try the normal unlink first. */
    1146      133351 :         ret = SMB_VFS_NEXT_UNLINKAT(handle,
    1147             :                                 dirfsp,
    1148             :                                 smb_fname,
    1149             :                                 flags);
    1150      133351 :         if (ret == 0) {
    1151      132895 :                 return 0;
    1152             :         }
    1153         306 :         if (errno == EACCES || errno == EPERM) {
    1154             :                 /* Failed due to access denied,
    1155             :                    see if we need to root override. */
    1156             : 
    1157             :                 /* Don't do anything fancy for streams. */
    1158           0 :                 if (smb_fname->stream_name) {
    1159           0 :                         return -1;
    1160             :                 }
    1161           0 :                 return acl_common_remove_object(handle,
    1162             :                                         dirfsp,
    1163             :                                         smb_fname,
    1164             :                                         false);
    1165             :         }
    1166             : 
    1167         306 :         DBG_DEBUG("unlink of %s failed %s\n",
    1168             :                   smb_fname->base_name,
    1169             :                   strerror(errno));
    1170         306 :         return -1;
    1171             : }
    1172             : 
    1173         230 : int fchmod_acl_module_common(struct vfs_handle_struct *handle,
    1174             :                              struct files_struct *fsp, mode_t mode)
    1175             : {
    1176         230 :         if (fsp->posix_flags & FSP_POSIX_FLAGS_PATHNAMES
    1177         230 :             || fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH) {
    1178             :                 /* Only allow this on POSIX opens. */
    1179          12 :                 return SMB_VFS_NEXT_FCHMOD(handle, fsp, mode);
    1180             :         }
    1181         196 :         return 0;
    1182             : }

Generated by: LCOV version 1.13