LCOV - code coverage report
Current view: top level - source3/modules - vfs_acl_common.c (source / functions) Hit Total Coverage
Test: coverage report for recycleplus df22b230 Lines: 241 470 51.3 %
Date: 2024-02-14 10:14:15 Functions: 13 16 81.2 %

          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        7956 : bool init_acl_common_config(vfs_handle_struct *handle,
      47             :                             const char *module_name)
      48             : {
      49        7956 :         struct acl_common_config *config = NULL;
      50        7956 :         const struct enum_list *default_acl_style_list = NULL;
      51             : 
      52        7956 :         default_acl_style_list = get_default_acl_style_list();
      53             : 
      54        7956 :         config = talloc_zero(handle->conn, struct acl_common_config);
      55        7956 :         if (config == NULL) {
      56           0 :                 DBG_ERR("talloc_zero() failed\n");
      57           0 :                 errno = ENOMEM;
      58           0 :                 return false;
      59             :         }
      60             : 
      61        7956 :         config->ignore_system_acls = lp_parm_bool(SNUM(handle->conn),
      62             :                                                   module_name,
      63             :                                                   "ignore system acls",
      64             :                                                   false);
      65        7956 :         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        7956 :         SMB_VFS_HANDLE_SET_DATA(handle, config, NULL,
      72             :                                 struct acl_common_config,
      73             :                                 return false);
      74             : 
      75        7956 :         return true;
      76             : }
      77             : 
      78             : 
      79             : /*******************************************************************
      80             :  Hash a security descriptor.
      81             : *******************************************************************/
      82             : 
      83       10259 : static NTSTATUS hash_blob_sha256(DATA_BLOB blob,
      84             :                                  uint8_t *hash)
      85             : {
      86             :         int rc;
      87             : 
      88       10259 :         ZERO_ARRAY_LEN(hash, XATTR_SD_HASH_SIZE);
      89             : 
      90       10259 :         rc = gnutls_hash_fast(GNUTLS_DIG_SHA256,
      91       10259 :                               blob.data,
      92             :                               blob.length,
      93             :                               hash);
      94       10259 :         if (rc < 0) {
      95           0 :                 return NT_STATUS_INTERNAL_ERROR;
      96             :         }
      97             : 
      98       10259 :         return NT_STATUS_OK;
      99             : }
     100             : 
     101             : /*******************************************************************
     102             :  Hash a security descriptor.
     103             : *******************************************************************/
     104             : 
     105        2384 : static NTSTATUS hash_sd_sha256(struct security_descriptor *psd,
     106             :                         uint8_t *hash)
     107             : {
     108             :         DATA_BLOB blob;
     109             :         NTSTATUS status;
     110             : 
     111        2384 :         memset(hash, '\0', XATTR_SD_HASH_SIZE);
     112        2384 :         status = create_acl_blob(psd, &blob, XATTR_SD_HASH_TYPE_SHA256, hash);
     113        2384 :         if (!NT_STATUS_IS_OK(status)) {
     114           0 :                 return status;
     115             :         }
     116        2384 :         return hash_blob_sha256(blob, hash);
     117             : }
     118             : 
     119             : /*******************************************************************
     120             :  Parse out a struct security_descriptor from a DATA_BLOB.
     121             : *******************************************************************/
     122             : 
     123        5493 : 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        5493 :         TALLOC_CTX *frame = talloc_stackframe();
     135             : 
     136        5493 :         ndr_err = ndr_pull_struct_blob(pblob, frame, &xacl,
     137             :                         (ndr_pull_flags_fn_t)ndr_pull_xattr_NTACL);
     138             : 
     139        5493 :         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        5493 :         *p_version = xacl.version;
     147             : 
     148        5493 :         switch (xacl.version) {
     149           0 :                 case 1:
     150           0 :                         *ppdesc = make_sec_desc(mem_ctx, SD_REVISION,
     151           0 :                                         xacl.info.sd->type | SEC_DESC_SELF_RELATIVE,
     152           0 :                                         xacl.info.sd->owner_sid,
     153           0 :                                         xacl.info.sd->group_sid,
     154           0 :                                         xacl.info.sd->sacl,
     155           0 :                                         xacl.info.sd->dacl,
     156             :                                         &sd_size);
     157             :                         /* No hash - null out. */
     158           0 :                         *p_hash_type = XATTR_SD_HASH_TYPE_NONE;
     159           0 :                         memset(hash, '\0', XATTR_SD_HASH_SIZE);
     160           0 :                         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           0 :                 case 3:
     174           0 :                         *ppdesc = make_sec_desc(mem_ctx, SD_REVISION,
     175           0 :                                         xacl.info.sd_hs3->sd->type | SEC_DESC_SELF_RELATIVE,
     176           0 :                                         xacl.info.sd_hs3->sd->owner_sid,
     177           0 :                                         xacl.info.sd_hs3->sd->group_sid,
     178           0 :                                         xacl.info.sd_hs3->sd->sacl,
     179           0 :                                         xacl.info.sd_hs3->sd->dacl,
     180             :                                         &sd_size);
     181           0 :                         *p_hash_type = xacl.info.sd_hs3->hash_type;
     182             :                         /* Current version 3 (if no sys acl hash available). */
     183           0 :                         memcpy(hash, xacl.info.sd_hs3->hash, XATTR_SD_HASH_SIZE);
     184           0 :                         break;
     185        5493 :                 case 4:
     186       10986 :                         *ppdesc = make_sec_desc(mem_ctx, SD_REVISION,
     187        5493 :                                         xacl.info.sd_hs4->sd->type | SEC_DESC_SELF_RELATIVE,
     188        5493 :                                         xacl.info.sd_hs4->sd->owner_sid,
     189        5493 :                                         xacl.info.sd_hs4->sd->group_sid,
     190        5493 :                                         xacl.info.sd_hs4->sd->sacl,
     191        5493 :                                         xacl.info.sd_hs4->sd->dacl,
     192             :                                         &sd_size);
     193        5493 :                         *p_hash_type = xacl.info.sd_hs4->hash_type;
     194             :                         /* Current version 4. */
     195        5493 :                         memcpy(hash, xacl.info.sd_hs4->hash, XATTR_SD_HASH_SIZE);
     196        5493 :                         memcpy(sys_acl_hash, xacl.info.sd_hs4->sys_acl_hash, XATTR_SD_HASH_SIZE);
     197        5493 :                         break;
     198           0 :                 default:
     199           0 :                         TALLOC_FREE(frame);
     200           0 :                         return NT_STATUS_REVISION_MISMATCH;
     201             :         }
     202             : 
     203        5493 :         TALLOC_FREE(frame);
     204             : 
     205        5493 :         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        2384 : 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        2384 :         TALLOC_CTX *ctx = talloc_tos();
     222             : 
     223        2384 :         ZERO_STRUCT(xacl);
     224        2384 :         ZERO_STRUCT(sd_hs3);
     225             : 
     226        2384 :         xacl.version = 3;
     227        2384 :         xacl.info.sd_hs3 = &sd_hs3;
     228        2384 :         xacl.info.sd_hs3->sd = discard_const_p(struct security_descriptor, psd);
     229        2384 :         xacl.info.sd_hs3->hash_type = hash_type;
     230        2384 :         memcpy(&xacl.info.sd_hs3->hash[0], hash, XATTR_SD_HASH_SIZE);
     231             : 
     232        2384 :         ndr_err = ndr_push_struct_blob(
     233             :                         pblob, ctx, &xacl,
     234             :                         (ndr_push_flags_fn_t)ndr_push_xattr_NTACL);
     235             : 
     236        2384 :         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        2384 :         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        2382 : 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        2382 :         TALLOC_CTX *ctx = talloc_tos();
     262             :         NTTIME nttime_now;
     263        2382 :         struct timeval now = timeval_current();
     264        2382 :         nttime_now = timeval_to_nttime(&now);
     265             : 
     266        2382 :         ZERO_STRUCT(xacl);
     267        2382 :         ZERO_STRUCT(sd_hs4);
     268             : 
     269        2382 :         xacl.version = 4;
     270        2382 :         xacl.info.sd_hs4 = &sd_hs4;
     271        2382 :         xacl.info.sd_hs4->sd = discard_const_p(struct security_descriptor, psd);
     272        2382 :         xacl.info.sd_hs4->hash_type = hash_type;
     273        2382 :         memcpy(&xacl.info.sd_hs4->hash[0], hash, XATTR_SD_HASH_SIZE);
     274        2382 :         xacl.info.sd_hs4->description = description;
     275        2382 :         xacl.info.sd_hs4->time = nttime_now;
     276        2382 :         memcpy(&xacl.info.sd_hs4->sys_acl_hash[0], sys_acl_hash, XATTR_SD_HASH_SIZE);
     277             : 
     278        2382 :         ndr_err = ndr_push_struct_blob(
     279             :                         pblob, ctx, &xacl,
     280             :                         (ndr_push_flags_fn_t)ndr_push_xattr_NTACL);
     281             : 
     282        2382 :         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        2382 :         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        3049 : 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        3049 :         struct connection_struct *conn = handle->conn;
     302        3049 :         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        3049 :         if (psd->dacl) {
     312        3049 :                 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        3049 :         if (new_ace_list == NULL) {
     326           0 :                 return NT_STATUS_NO_MEMORY;
     327             :         }
     328             : 
     329             :         /* Fake a quick smb_filename. */
     330        3049 :         ZERO_STRUCT(smb_fname);
     331        3049 :         smb_fname.st = *psbuf;
     332        3049 :         smb_fname.base_name = discard_const_p(char, name);
     333             : 
     334        3049 :         dir_mode = unix_mode(conn,
     335             :                         FILE_ATTRIBUTE_DIRECTORY, &smb_fname, NULL);
     336        3049 :         file_mode = unix_mode(conn,
     337             :                         FILE_ATTRIBUTE_ARCHIVE, &smb_fname, NULL);
     338             : 
     339        3049 :         mode = dir_mode | file_mode;
     340             : 
     341        3049 :         DBG_DEBUG("directory %s, mode = 0%o\n", name, (unsigned int)mode);
     342             : 
     343        3049 :         if (num_aces) {
     344        3049 :                 memcpy(new_ace_list, psd->dacl->aces,
     345             :                         num_aces * sizeof(struct security_ace));
     346             :         }
     347        3049 :         access_mask = map_canon_ace_perms(SNUM(conn), &acltype,
     348             :                                 mode & 0700, false);
     349             : 
     350        3049 :         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        3049 :         access_mask = map_canon_ace_perms(SNUM(conn), &acltype,
     358        3049 :                                 (mode << 3) & 0700, false);
     359        3049 :         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        3049 :         access_mask = map_canon_ace_perms(SNUM(conn), &acltype,
     367        3049 :                                 (mode << 6) & 0700, false);
     368        3049 :         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        3049 :         if (psd->dacl) {
     376        3049 :                 psd->dacl->aces = new_ace_list;
     377        3049 :                 psd->dacl->num_aces += 3;
     378        3049 :                 psd->dacl->size += new_ace_list[num_aces].size +
     379        3049 :                         new_ace_list[num_aces+1].size +
     380        3049 :                         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        3049 :         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        5493 : 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        5493 :         uint16_t hash_type = XATTR_SD_HASH_TYPE_NONE;
     421        5493 :         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        5493 :         struct security_descriptor *psd = NULL;
     427        5493 :         struct security_descriptor *psd_blob = NULL;
     428        5493 :         struct security_descriptor *psd_fs = NULL;
     429        5493 :         char *sys_acl_blob_description = NULL;
     430        5493 :         DATA_BLOB sys_acl_blob = { 0 };
     431        5493 :         struct acl_common_config *config = NULL;
     432             : 
     433        5493 :         *ppsd = NULL;
     434        5493 :         *psd_is_from_fs = false;
     435             : 
     436        5493 :         SMB_VFS_HANDLE_GET_DATA(handle, config,
     437             :                                 struct acl_common_config,
     438             :                                 return NT_STATUS_UNSUCCESSFUL);
     439             : 
     440        5493 :         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        5493 :         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        5493 :         switch (xattr_version) {
     454           0 :         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           0 :                 *ppsd = psd_blob;
     461           0 :                 return NT_STATUS_OK;
     462        5493 :         case 3:
     463             :         case 4:
     464        5493 :                 if (config->ignore_system_acls) {
     465           0 :                         *ppsd = psd_blob;
     466           0 :                         return NT_STATUS_OK;
     467             :                 }
     468             : 
     469        5493 :                 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        5493 :         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        5493 :         switch (xattr_version) {
     487        5493 :         case 4:
     488             :         {
     489             :                 int ret;
     490             :                 /* Get the full underlying sd, then hash. */
     491        5493 :                 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        5493 :                 if (ret == 0) {
     499        5493 :                         status = hash_blob_sha256(sys_acl_blob, sys_acl_hash_tmp);
     500        5493 :                         if (!NT_STATUS_IS_OK(status)) {
     501           0 :                                 goto fail;
     502             :                         }
     503             : 
     504        5493 :                         TALLOC_FREE(sys_acl_blob_description);
     505        5493 :                         TALLOC_FREE(sys_acl_blob.data);
     506             : 
     507        5493 :                         if (memcmp(&sys_acl_hash[0], &sys_acl_hash_tmp[0], 
     508             :                                    XATTR_SD_HASH_SIZE) == 0) {
     509             :                                 /* Hash matches, return blob sd. */
     510        5491 :                                 DBG_DEBUG("blob hash matches for file %s\n",
     511             :                                           smb_fname->base_name);
     512        5491 :                                 *ppsd = psd_blob;
     513        5491 :                                 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           2 :                 status = SMB_VFS_NEXT_FGET_NT_ACL(handle,
     524             :                                                   fsp,
     525             :                                                   HASH_SECURITY_INFO,
     526             :                                                   mem_ctx,
     527             :                                                   &psd_fs);
     528           2 :                 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           2 :                 status = hash_sd_sha256(psd_fs, hash_tmp);
     535           2 :                 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           2 :                 if (memcmp(&hash[0], &hash_tmp[0], XATTR_SD_HASH_SIZE) == 0) {
     543             :                         /* Hash matches, return blob sd. */
     544           2 :                         DBG_DEBUG("blob hash matches for file %s\n",
     545             :                                   smb_fname->base_name);
     546           2 :                         *ppsd = psd_blob;
     547           2 :                         return NT_STATUS_OK;
     548             :                 }
     549             : 
     550             :                 /* Hash doesn't match, return underlying sd. */
     551           0 :                 DBG_DEBUG("blob hash does not match for file %s - returning "
     552             :                           "file system SD mapping.\n",
     553             :                           smb_fname->base_name);
     554             : 
     555           0 :                 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           0 :                 TALLOC_FREE(psd_blob);
     562           0 :                 *ppsd = psd_fs;
     563           0 :                 *psd_is_from_fs = true;
     564             :         }
     565             : 
     566           0 :         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        9281 : 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        9281 :         DATA_BLOB blob = data_blob_null;
     595             :         NTSTATUS status;
     596        9281 :         struct security_descriptor *psd = NULL;
     597        9281 :         const struct smb_filename *smb_fname = fsp->fsp_name;
     598        9281 :         bool psd_is_from_fs = false;
     599        9281 :         struct acl_common_config *config = NULL;
     600             : 
     601        9281 :         SMB_VFS_HANDLE_GET_DATA(handle, config,
     602             :                                 struct acl_common_config,
     603             :                                 return NT_STATUS_UNSUCCESSFUL);
     604             : 
     605        9281 :         DBG_DEBUG("name=%s\n", smb_fname->base_name);
     606             : 
     607        9281 :         status = fget_acl_blob_fn(mem_ctx, handle, fsp, &blob);
     608        9281 :         if (NT_STATUS_IS_OK(status)) {
     609        5493 :                 status = validate_nt_acl_blob(mem_ctx,
     610             :                                         handle,
     611             :                                         fsp,
     612             :                                         smb_fname,
     613             :                                         &blob,
     614             :                                         &psd,
     615             :                                         &psd_is_from_fs);
     616        5493 :                 TALLOC_FREE(blob.data);
     617        5493 :                 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        9281 :         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        3788 :                 if (config->ignore_system_acls) {
     630           0 :                         status = vfs_stat_fsp(fsp);
     631           0 :                         if (!NT_STATUS_IS_OK(status)) {
     632           0 :                                 goto fail;
     633             :                         }
     634             : 
     635           0 :                         status = make_default_filesystem_acl(
     636             :                                 mem_ctx,
     637             :                                 config->default_acl_style,
     638           0 :                                 smb_fname->base_name,
     639           0 :                                 &fsp->fsp_name->st,
     640             :                                 &psd);
     641           0 :                         if (!NT_STATUS_IS_OK(status)) {
     642           0 :                                 goto fail;
     643             :                         }
     644             :                 } else {
     645        3788 :                         status = SMB_VFS_NEXT_FGET_NT_ACL(handle,
     646             :                                                           fsp,
     647             :                                                           security_info,
     648             :                                                           mem_ctx,
     649             :                                                           &psd);
     650             : 
     651        3788 :                         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        3788 :                         psd_is_from_fs = true;
     660             :                 }
     661             :         }
     662             : 
     663        9281 :         if (psd_is_from_fs) {
     664        3788 :                 status = vfs_stat_fsp(fsp);
     665        3788 :                 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        3788 :                 if (fsp->fsp_flags.is_directory &&
     676        3049 :                                 !sd_has_inheritable_components(psd, true)) {
     677        3049 :                         status = add_directory_inheritable_components(
     678             :                                 handle,
     679        3049 :                                 smb_fname->base_name,
     680        3049 :                                 &fsp->fsp_name->st,
     681             :                                 psd);
     682        3049 :                         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        3788 :                 psd->type &= ~SEC_DESC_DACL_PROTECTED;
     693             :         }
     694             : 
     695        9281 :         if (!(security_info & SECINFO_OWNER)) {
     696        2125 :                 psd->owner_sid = NULL;
     697             :         }
     698        9281 :         if (!(security_info & SECINFO_GROUP)) {
     699        2125 :                 psd->group_sid = NULL;
     700             :         }
     701        9281 :         if (!(security_info & SECINFO_DACL)) {
     702           0 :                 psd->type &= ~SEC_DESC_DACL_PRESENT;
     703           0 :                 psd->dacl = NULL;
     704             :         }
     705        9281 :         if (!(security_info & SECINFO_SACL)) {
     706        6491 :                 psd->type &= ~SEC_DESC_SACL_PRESENT;
     707        6491 :                 psd->sacl = NULL;
     708             :         }
     709             : 
     710        9281 :         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        9281 :         *ppdesc = psd;
     717             : 
     718        9281 :         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        2382 : 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        2382 :         const struct security_token *token = NULL;
     735             :         struct dom_sid_buf buf;
     736             : 
     737        2382 :         status = SMB_VFS_NEXT_FSET_NT_ACL(handle, fsp, security_info_sent, psd);
     738        2382 :         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
     739        2382 :                 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 :                 return NT_STATUS_ACCESS_DENIED;
     747             :         }
     748           0 :         status = check_any_access_fsp(fsp, SEC_STD_WRITE_OWNER);
     749           0 :         if (!NT_STATUS_IS_OK(status)) {
     750           0 :                 return status;
     751             :         }
     752             : 
     753             :         /*
     754             :          * Only allow take-ownership, not give-ownership. That's the way Windows
     755             :          * implements SEC_STD_WRITE_OWNER. MS-FSA 2.1.5.16 just states: If
     756             :          * InputBuffer.OwnerSid is not a valid owner SID for a file in the
     757             :          * objectstore, as determined in an implementation specific manner, the
     758             :          * object store MUST return STATUS_INVALID_OWNER.
     759             :          */
     760           0 :         token = get_current_nttok(fsp->conn);
     761           0 :         if (!security_token_is_sid(token, psd->owner_sid)) {
     762           0 :                 return NT_STATUS_INVALID_OWNER;
     763             :         }
     764             : 
     765           0 :         DBG_DEBUG("overriding chown on file %s for sid %s\n",
     766             :                   fsp_str_dbg(fsp),
     767             :                   dom_sid_str_buf(psd->owner_sid, &buf));
     768             : 
     769             :         /* Ok, we failed to chown and we have
     770             :            SEC_STD_WRITE_OWNER access - override. */
     771           0 :         become_root();
     772           0 :         status = SMB_VFS_NEXT_FSET_NT_ACL(handle, fsp, security_info_sent, psd);
     773           0 :         unbecome_root();
     774             : 
     775           0 :         return status;
     776             : }
     777             : 
     778             : /*********************************************************************
     779             :  Store a v3 security descriptor
     780             : *********************************************************************/
     781           0 : static NTSTATUS store_v3_blob(
     782             :         NTSTATUS (*store_acl_blob_fsp_fn)(vfs_handle_struct *handle,
     783             :                                           files_struct *fsp,
     784             :                                           DATA_BLOB *pblob),
     785             :         vfs_handle_struct *handle, files_struct *fsp,
     786             :         struct security_descriptor *psd,
     787             :         struct security_descriptor *pdesc_next,
     788             :         uint8_t hash[XATTR_SD_HASH_SIZE])
     789             : {
     790             :         NTSTATUS status;
     791             :         DATA_BLOB blob;
     792             : 
     793           0 :         if (DEBUGLEVEL >= 10) {
     794           0 :                 DBG_DEBUG("storing xattr sd for file %s\n",
     795             :                           fsp_str_dbg(fsp));
     796           0 :                 NDR_PRINT_DEBUG(
     797             :                     security_descriptor,
     798             :                     discard_const_p(struct security_descriptor, psd));
     799             : 
     800           0 :                 if (pdesc_next != NULL) {
     801           0 :                         DBG_DEBUG("storing xattr sd based on \n");
     802           0 :                         NDR_PRINT_DEBUG(
     803             :                             security_descriptor,
     804             :                             discard_const_p(struct security_descriptor,
     805             :                                             pdesc_next));
     806             :                 } else {
     807           0 :                         DBG_DEBUG("ignoring underlying sd\n");
     808             :                 }
     809             :         }
     810           0 :         status = create_acl_blob(psd, &blob, XATTR_SD_HASH_TYPE_SHA256, hash);
     811           0 :         if (!NT_STATUS_IS_OK(status)) {
     812           0 :                 DBG_DEBUG("create_acl_blob failed\n");
     813           0 :                 return status;
     814             :         }
     815             : 
     816           0 :         status = store_acl_blob_fsp_fn(handle, fsp, &blob);
     817           0 :         return status;
     818             : }
     819             : 
     820             : /*********************************************************************
     821             :  Store a security descriptor given an fsp.
     822             : *********************************************************************/
     823             : 
     824        2382 : NTSTATUS fset_nt_acl_common(
     825             :         NTSTATUS (*fget_acl_blob_fn)(TALLOC_CTX *ctx,
     826             :                                     vfs_handle_struct *handle,
     827             :                                     files_struct *fsp,
     828             :                                     DATA_BLOB *pblob),
     829             :         NTSTATUS (*store_acl_blob_fsp_fn)(vfs_handle_struct *handle,
     830             :                                           files_struct *fsp,
     831             :                                           DATA_BLOB *pblob),
     832             :         const char *module_name,
     833             :         vfs_handle_struct *handle, files_struct *fsp,
     834             :         uint32_t security_info_sent,
     835             :         const struct security_descriptor *orig_psd)
     836             : {
     837             :         NTSTATUS status;
     838             :         int ret;
     839             :         DATA_BLOB blob, sys_acl_blob;
     840        2382 :         struct security_descriptor *pdesc_next = NULL;
     841        2382 :         struct security_descriptor *psd = NULL;
     842             :         uint8_t hash[XATTR_SD_HASH_SIZE];
     843             :         uint8_t sys_acl_hash[XATTR_SD_HASH_SIZE];
     844        2382 :         bool chown_needed = false;
     845             :         char *sys_acl_description;
     846        2382 :         TALLOC_CTX *frame = talloc_stackframe();
     847        2382 :         bool ignore_file_system_acl = lp_parm_bool(
     848        2382 :             SNUM(handle->conn), module_name, "ignore system acls", false);
     849        2382 :         struct acl_common_fsp_ext *ext = NULL;
     850             : 
     851        2382 :         if (DEBUGLEVEL >= 10) {
     852           0 :                 DBG_DEBUG("incoming sd for file %s\n", fsp_str_dbg(fsp));
     853           0 :                 NDR_PRINT_DEBUG(security_descriptor,
     854             :                         discard_const_p(struct security_descriptor, orig_psd));
     855             :         }
     856             : 
     857        2382 :         status = fget_nt_acl_common(fget_acl_blob_fn, handle, fsp,
     858             :                         SECINFO_OWNER|SECINFO_GROUP|SECINFO_DACL|SECINFO_SACL,
     859             :                                      frame,
     860             :                         &psd);
     861             : 
     862        2382 :         if (!NT_STATUS_IS_OK(status)) {
     863           0 :                 TALLOC_FREE(frame);
     864           0 :                 return status;
     865             :         }
     866             : 
     867        2382 :         psd->revision = orig_psd->revision;
     868        2382 :         if (security_info_sent & SECINFO_DACL) {
     869        2382 :                 psd->type = orig_psd->type;
     870             :                 /* All our SD's are self relative. */
     871        2382 :                 psd->type |= SEC_DESC_SELF_RELATIVE;
     872             :         }
     873             : 
     874        2382 :         if ((security_info_sent & SECINFO_OWNER) && (orig_psd->owner_sid != NULL)) {
     875        2373 :                 if (!dom_sid_equal(orig_psd->owner_sid, psd->owner_sid)) {
     876             :                         /* We're changing the owner. */
     877        1769 :                         chown_needed = true;
     878             :                 }
     879        2373 :                 psd->owner_sid = orig_psd->owner_sid;
     880             :         }
     881        2382 :         if ((security_info_sent & SECINFO_GROUP) && (orig_psd->group_sid != NULL)) {
     882        2377 :                 if (!dom_sid_equal(orig_psd->group_sid, psd->group_sid)) {
     883             :                         /* We're changing the group. */
     884        2348 :                         chown_needed = true;
     885             :                 }
     886        2377 :                 psd->group_sid = orig_psd->group_sid;
     887             :         }
     888        2382 :         if (security_info_sent & SECINFO_DACL) {
     889        2382 :                 if (security_descriptor_with_ms_nfs(orig_psd)) {
     890             :                         /*
     891             :                          * If the sd contains a MS NFS SID, do
     892             :                          * nothing, it's a chmod() request from OS X
     893             :                          * with AAPL context.
     894             :                          */
     895           0 :                         TALLOC_FREE(frame);
     896           0 :                         return NT_STATUS_OK;
     897             :                 }
     898        2382 :                 psd->dacl = orig_psd->dacl;
     899        2382 :                 psd->type |= SEC_DESC_DACL_PRESENT;
     900             :         }
     901        2382 :         if (security_info_sent & SECINFO_SACL) {
     902         929 :                 psd->sacl = orig_psd->sacl;
     903         929 :                 psd->type |= SEC_DESC_SACL_PRESENT;
     904             :         }
     905             : 
     906        2382 :         ext = VFS_ADD_FSP_EXTENSION(handle,
     907             :                                     fsp,
     908             :                                     struct acl_common_fsp_ext,
     909             :                                     NULL);
     910        2382 :         ext->setting_nt_acl = true;
     911             : 
     912        2382 :         if (ignore_file_system_acl) {
     913           0 :                 if (chown_needed) {
     914             :                         /* send only ownership stuff to lower layer */
     915           0 :                         security_info_sent &= (SECINFO_OWNER | SECINFO_GROUP);
     916           0 :                         status = set_underlying_acl(handle, fsp, psd,
     917             :                                                     security_info_sent, true);
     918           0 :                         if (!NT_STATUS_IS_OK(status)) {
     919           0 :                                 goto done;
     920             :                         }
     921             :                 }
     922           0 :                 ZERO_ARRAY(hash);
     923           0 :                 status = store_v3_blob(store_acl_blob_fsp_fn, handle, fsp, psd,
     924             :                                        NULL, hash);
     925           0 :                 goto done;
     926             :         }
     927             : 
     928        2382 :         status = set_underlying_acl(handle, fsp, psd, security_info_sent,
     929             :                                     chown_needed);
     930        2382 :         if (!NT_STATUS_IS_OK(status)) {
     931           0 :                 goto done;
     932             :         }
     933             : 
     934             :         /* Get the full underlying sd, then hash. */
     935        2382 :         status = SMB_VFS_NEXT_FGET_NT_ACL(handle,
     936             :                                           fsp,
     937             :                                           HASH_SECURITY_INFO,
     938             :                                           frame,
     939             :                                           &pdesc_next);
     940             : 
     941        2382 :         if (!NT_STATUS_IS_OK(status)) {
     942           0 :                 goto done;
     943             :         }
     944             : 
     945        2382 :         status = hash_sd_sha256(pdesc_next, hash);
     946        2382 :         if (!NT_STATUS_IS_OK(status)) {
     947           0 :                 goto done;
     948             :         }
     949             : 
     950             :         /* Get the full underlying sd, then hash. */
     951        2382 :         ret = SMB_VFS_NEXT_SYS_ACL_BLOB_GET_FD(handle,
     952             :                                                fsp,
     953             :                                                frame,
     954             :                                                &sys_acl_description,
     955             :                                                &sys_acl_blob);
     956             : 
     957             :         /* If we fail to get the ACL blob (for some reason) then this
     958             :          * is not fatal, we just work based on the NT ACL only */
     959        2382 :         if (ret != 0) {
     960           0 :                 status = store_v3_blob(store_acl_blob_fsp_fn, handle, fsp, psd,
     961             :                                        pdesc_next, hash);
     962             : 
     963           0 :                 goto done;
     964             :         }
     965             : 
     966        2382 :         status = hash_blob_sha256(sys_acl_blob, sys_acl_hash);
     967        2382 :         if (!NT_STATUS_IS_OK(status)) {
     968           0 :                 goto done;
     969             :         }
     970             : 
     971        2382 :         if (DEBUGLEVEL >= 10) {
     972           0 :                 DBG_DEBUG("storing xattr sd for file %s based on system ACL\n",
     973             :                           fsp_str_dbg(fsp));
     974           0 :                 NDR_PRINT_DEBUG(security_descriptor,
     975             :                                 discard_const_p(struct security_descriptor, psd));
     976             : 
     977           0 :                 DBG_DEBUG("storing hash in xattr sd based on system ACL and:\n");
     978           0 :                 NDR_PRINT_DEBUG(security_descriptor,
     979             :                                 discard_const_p(struct security_descriptor, pdesc_next));
     980             :         }
     981             : 
     982             :         /* We store hashes of both the sys ACL blob and the NT
     983             :          * security desciptor mapped from that ACL so as to improve
     984             :          * our chances against some inadvertant change breaking the
     985             :          * hash used */
     986        2382 :         status = create_sys_acl_blob(psd, &blob, XATTR_SD_HASH_TYPE_SHA256, hash, 
     987             :                                      sys_acl_description, sys_acl_hash);
     988        2382 :         if (!NT_STATUS_IS_OK(status)) {
     989           0 :                 DBG_DEBUG("create_sys_acl_blob failed\n");
     990           0 :                 goto done;
     991             :         }
     992             : 
     993        2382 :         status = store_acl_blob_fsp_fn(handle, fsp, &blob);
     994             : 
     995        2382 : done:
     996        2382 :         VFS_REMOVE_FSP_EXTENSION(handle, fsp);
     997        2382 :         TALLOC_FREE(frame);
     998        2382 :         return status;
     999             : }
    1000             : 
    1001           0 : static int acl_common_remove_object(vfs_handle_struct *handle,
    1002             :                                         struct files_struct *dirfsp,
    1003             :                                         const struct smb_filename *smb_fname,
    1004             :                                         bool is_directory)
    1005             : {
    1006           0 :         connection_struct *conn = handle->conn;
    1007             :         struct file_id id;
    1008           0 :         files_struct *fsp = NULL;
    1009           0 :         int ret = 0;
    1010           0 :         struct smb_filename *full_fname = NULL;
    1011           0 :         struct smb_filename *local_fname = NULL;
    1012           0 :         struct smb_filename *parent_dir_fname = NULL;
    1013           0 :         int saved_errno = 0;
    1014           0 :         struct smb_filename *saved_dir_fname = NULL;
    1015             :         NTSTATUS status;
    1016             : 
    1017           0 :         saved_dir_fname = vfs_GetWd(talloc_tos(),conn);
    1018           0 :         if (saved_dir_fname == NULL) {
    1019           0 :                 saved_errno = errno;
    1020           0 :                 goto out;
    1021             :         }
    1022             : 
    1023           0 :         full_fname = full_path_from_dirfsp_atname(talloc_tos(),
    1024             :                                                   dirfsp,
    1025             :                                                   smb_fname);
    1026           0 :         if (full_fname == NULL) {
    1027           0 :                 goto out;
    1028             :         }
    1029             : 
    1030           0 :         status = SMB_VFS_PARENT_PATHNAME(conn,
    1031             :                                          talloc_tos(),
    1032             :                                          full_fname,
    1033             :                                          &parent_dir_fname,
    1034             :                                          &local_fname);
    1035           0 :         if (!NT_STATUS_IS_OK(status)) {
    1036           0 :                 saved_errno = map_errno_from_nt_status(status);
    1037           0 :                 goto out;
    1038             :         }
    1039             : 
    1040           0 :         DBG_DEBUG("removing %s %s\n", is_directory ? "directory" : "file",
    1041             :                   smb_fname_str_dbg(full_fname));
    1042             : 
    1043             :         /* cd into the parent dir to pin it. */
    1044           0 :         ret = vfs_ChDir(conn, parent_dir_fname);
    1045           0 :         if (ret == -1) {
    1046           0 :                 saved_errno = errno;
    1047           0 :                 goto out;
    1048             :         }
    1049             : 
    1050             :         /* Must use lstat here. */
    1051           0 :         ret = SMB_VFS_LSTAT(conn, local_fname);
    1052           0 :         if (ret == -1) {
    1053           0 :                 saved_errno = errno;
    1054           0 :                 goto out;
    1055             :         }
    1056             : 
    1057             :         /* Ensure we have this file open with DELETE access. */
    1058           0 :         id = vfs_file_id_from_sbuf(conn, &local_fname->st);
    1059           0 :         for (fsp = file_find_di_first(conn->sconn, id, true); fsp;
    1060           0 :                      fsp = file_find_di_next(fsp, true)) {
    1061           0 :                 if (fsp->access_mask & DELETE_ACCESS &&
    1062             :                     fsp->fsp_flags.delete_on_close)
    1063             :                 {
    1064             :                         /* We did open this for delete,
    1065             :                          * allow the delete as root.
    1066             :                          */
    1067           0 :                         break;
    1068             :                 }
    1069             :         }
    1070             : 
    1071           0 :         if (!fsp) {
    1072           0 :                 DBG_DEBUG("%s %s not an open file\n",
    1073             :                           is_directory ? "directory" : "file",
    1074             :                           smb_fname_str_dbg(full_fname));
    1075           0 :                 saved_errno = EACCES;
    1076           0 :                 goto out;
    1077             :         }
    1078             : 
    1079           0 :         become_root();
    1080           0 :         if (is_directory) {
    1081           0 :                 ret = SMB_VFS_NEXT_UNLINKAT(handle,
    1082             :                                 dirfsp,
    1083             :                                 smb_fname,
    1084             :                                 AT_REMOVEDIR);
    1085             :         } else {
    1086           0 :                 ret = SMB_VFS_NEXT_UNLINKAT(handle,
    1087             :                                 dirfsp,
    1088             :                                 smb_fname,
    1089             :                                 0);
    1090             :         }
    1091           0 :         unbecome_root();
    1092             : 
    1093           0 :         if (ret == -1) {
    1094           0 :                 saved_errno = errno;
    1095             :         }
    1096             : 
    1097           0 :   out:
    1098             : 
    1099           0 :         TALLOC_FREE(parent_dir_fname);
    1100           0 :         TALLOC_FREE(full_fname);
    1101             : 
    1102           0 :         if (saved_dir_fname) {
    1103           0 :                 vfs_ChDir(conn, saved_dir_fname);
    1104           0 :                 TALLOC_FREE(saved_dir_fname);
    1105             :         }
    1106           0 :         if (saved_errno) {
    1107           0 :                 errno = saved_errno;
    1108             :         }
    1109           0 :         return ret;
    1110             : }
    1111             : 
    1112         804 : int rmdir_acl_common(struct vfs_handle_struct *handle,
    1113             :                 struct files_struct *dirfsp,
    1114             :                 const struct smb_filename *smb_fname)
    1115             : {
    1116             :         int ret;
    1117             : 
    1118             :         /* Try the normal rmdir first. */
    1119         804 :         ret = SMB_VFS_NEXT_UNLINKAT(handle,
    1120             :                         dirfsp,
    1121             :                         smb_fname,
    1122             :                         AT_REMOVEDIR);
    1123         804 :         if (ret == 0) {
    1124         804 :                 return 0;
    1125             :         }
    1126           0 :         if (errno == EACCES || errno == EPERM) {
    1127             :                 /* Failed due to access denied,
    1128             :                    see if we need to root override. */
    1129           0 :                 return acl_common_remove_object(handle,
    1130             :                                                 dirfsp,
    1131             :                                                 smb_fname,
    1132             :                                                 true);
    1133             :         }
    1134             : 
    1135           0 :         DBG_DEBUG("unlink of %s failed %s\n",
    1136             :                   smb_fname->base_name,
    1137             :                   strerror(errno));
    1138           0 :         return -1;
    1139             : }
    1140             : 
    1141         573 : int unlink_acl_common(struct vfs_handle_struct *handle,
    1142             :                         struct files_struct *dirfsp,
    1143             :                         const struct smb_filename *smb_fname,
    1144             :                         int flags)
    1145             : {
    1146             :         int ret;
    1147             : 
    1148             :         /* Try the normal unlink first. */
    1149         573 :         ret = SMB_VFS_NEXT_UNLINKAT(handle,
    1150             :                                 dirfsp,
    1151             :                                 smb_fname,
    1152             :                                 flags);
    1153         573 :         if (ret == 0) {
    1154         573 :                 return 0;
    1155             :         }
    1156           0 :         if (errno == EACCES || errno == EPERM) {
    1157             :                 /* Failed due to access denied,
    1158             :                    see if we need to root override. */
    1159             : 
    1160             :                 /* Don't do anything fancy for streams. */
    1161           0 :                 if (smb_fname->stream_name) {
    1162           0 :                         return -1;
    1163             :                 }
    1164           0 :                 return acl_common_remove_object(handle,
    1165             :                                         dirfsp,
    1166             :                                         smb_fname,
    1167             :                                         false);
    1168             :         }
    1169             : 
    1170           0 :         DBG_DEBUG("unlink of %s failed %s\n",
    1171             :                   smb_fname->base_name,
    1172             :                   strerror(errno));
    1173           0 :         return -1;
    1174             : }
    1175             : 
    1176           0 : int fchmod_acl_module_common(struct vfs_handle_struct *handle,
    1177             :                              struct files_struct *fsp, mode_t mode)
    1178             : {
    1179           0 :         if (fsp->posix_flags & FSP_POSIX_FLAGS_PATHNAMES
    1180           0 :             || fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH) {
    1181             :                 /* Only allow this on POSIX opens. */
    1182           0 :                 return SMB_VFS_NEXT_FCHMOD(handle, fsp, mode);
    1183             :         }
    1184           0 :         return 0;
    1185             : }

Generated by: LCOV version 1.14