LCOV - code coverage report
Current view: top level - source3/modules - nfs4_acls.c (source / functions) Hit Total Coverage
Test: coverage report for fix-15632 9995c5c2 Lines: 391 565 69.2 %
Date: 2024-04-13 12:30:31 Functions: 25 34 73.5 %

          Line data    Source code
       1             : /*
       2             :  * NFS4 ACL handling
       3             :  *
       4             :  * Copyright (C) Jim McDonough, 2006
       5             :  * Copyright (C) Christof Schmitt 2019
       6             :  *
       7             :  * This program is free software; you can redistribute it and/or modify
       8             :  * it under the terms of the GNU General Public License as published by
       9             :  * the Free Software Foundation; either version 3 of the License, or
      10             :  * (at your option) any later version.
      11             :  *
      12             :  * This program is distributed in the hope that it will be useful,
      13             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      15             :  * GNU General Public License for more details.
      16             :  *
      17             :  * You should have received a copy of the GNU General Public License
      18             :  * along with this program; if not, see <http://www.gnu.org/licenses/>.
      19             :  */
      20             : 
      21             : #include "includes.h"
      22             : #include "smbd/smbd.h"
      23             : #include "nfs4_acls.h"
      24             : #include "librpc/gen_ndr/ndr_security.h"
      25             : #include "librpc/gen_ndr/idmap.h"
      26             : #include "../libcli/security/dom_sid.h"
      27             : #include "../libcli/security/security.h"
      28             : #include "dbwrap/dbwrap.h"
      29             : #include "dbwrap/dbwrap_open.h"
      30             : #include "system/filesys.h"
      31             : #include "passdb/lookup_sid.h"
      32             : #include "util_tdb.h"
      33             : #include "lib/param/loadparm.h"
      34             : 
      35             : #undef DBGC_CLASS
      36             : #define DBGC_CLASS DBGC_ACLS
      37             : 
      38             : #define SMBACL4_PARAM_TYPE_NAME "nfs4"
      39             : 
      40             : extern const struct generic_mapping file_generic_mapping;
      41             : 
      42             : struct SMB4ACE_T
      43             : {
      44             :         SMB_ACE4PROP_T  prop;
      45             :         struct SMB4ACE_T *next;
      46             : };
      47             : 
      48             : struct SMB4ACL_T
      49             : {
      50             :         uint16_t controlflags;
      51             :         uint32_t naces;
      52             :         struct SMB4ACE_T        *first;
      53             :         struct SMB4ACE_T        *last;
      54             : };
      55             : 
      56             : /*
      57             :  * Gather special parameters for NFS4 ACL handling
      58             :  */
      59        8976 : int smbacl4_get_vfs_params(struct connection_struct *conn,
      60             :                            struct smbacl4_vfs_params *params)
      61             : {
      62           0 :         static const struct enum_list enum_smbacl4_modes[] = {
      63             :                 { e_simple, "simple" },
      64             :                 { e_special, "special" },
      65             :                 { -1 , NULL }
      66             :         };
      67           0 :         static const struct enum_list enum_smbacl4_acedups[] = {
      68             :                 { e_dontcare, "dontcare" },
      69             :                 { e_reject, "reject" },
      70             :                 { e_ignore, "ignore" },
      71             :                 { e_merge, "merge" },
      72             :                 { -1 , NULL }
      73             :         };
      74           0 :         int enumval;
      75             : 
      76        8976 :         *params = (struct smbacl4_vfs_params) { 0 };
      77             : 
      78        8976 :         enumval = lp_parm_enum(SNUM(conn), SMBACL4_PARAM_TYPE_NAME, "mode",
      79             :                                enum_smbacl4_modes, e_simple);
      80        8976 :         if (enumval == -1) {
      81           0 :                 DEBUG(10, ("value for %s:mode unknown\n",
      82             :                            SMBACL4_PARAM_TYPE_NAME));
      83           0 :                 return -1;
      84             :         }
      85        8976 :         params->mode = (enum smbacl4_mode_enum)enumval;
      86        8976 :         if (params->mode == e_special) {
      87        1282 :                 DBG_WARNING("nfs4:mode special is deprecated.\n");
      88             :         }
      89             : 
      90        8976 :         params->do_chown = lp_parm_bool(SNUM(conn), SMBACL4_PARAM_TYPE_NAME,
      91             :                 "chown", true);
      92             : 
      93        8976 :         enumval = lp_parm_enum(SNUM(conn), SMBACL4_PARAM_TYPE_NAME, "acedup",
      94             :                                enum_smbacl4_acedups, e_merge);
      95        8976 :         if (enumval == -1) {
      96           0 :                 DEBUG(10, ("value for %s:acedup unknown\n",
      97             :                            SMBACL4_PARAM_TYPE_NAME));
      98           0 :                 return -1;
      99             :         }
     100        8976 :         params->acedup = (enum smbacl4_acedup_enum)enumval;
     101        8976 :         if (params->acedup == e_ignore) {
     102           0 :                 DBG_WARNING("nfs4:acedup ignore is deprecated.\n");
     103             :         }
     104        8976 :         if (params->acedup == e_reject) {
     105           0 :                 DBG_WARNING("nfs4:acedup ignore is deprecated.\n");
     106             :         }
     107             : 
     108        8976 :         params->map_full_control = lp_acl_map_full_control(SNUM(conn));
     109             : 
     110        8976 :         DEBUG(10, ("mode:%s, do_chown:%s, acedup: %s map full control:%s\n",
     111             :                 enum_smbacl4_modes[params->mode].name,
     112             :                 params->do_chown ? "true" : "false",
     113             :                 enum_smbacl4_acedups[params->acedup].name,
     114             :                 params->map_full_control ? "true" : "false"));
     115             : 
     116        8976 :         return 0;
     117             : }
     118             : 
     119           0 : static int fstatat_with_cap_dac_override(int fd,
     120             :                                          const char *pathname,
     121             :                                          SMB_STRUCT_STAT *sbuf,
     122             :                                          int flags,
     123             :                                          bool fake_dir_create_times)
     124             : {
     125           0 :         int ret;
     126             : 
     127           0 :         set_effective_capability(DAC_OVERRIDE_CAPABILITY);
     128           0 :         ret = sys_fstatat(fd,
     129             :                           pathname,
     130             :                           sbuf,
     131             :                           flags,
     132             :                           fake_dir_create_times);
     133           0 :         drop_effective_capability(DAC_OVERRIDE_CAPABILITY);
     134             : 
     135           0 :         return ret;
     136             : }
     137             : 
     138           0 : static int stat_with_cap_dac_override(struct vfs_handle_struct *handle,
     139             :                                       struct smb_filename *smb_fname, int flag)
     140             : {
     141           0 :         bool fake_dctime = lp_fake_directory_create_times(SNUM(handle->conn));
     142           0 :         int fd = -1;
     143           0 :         NTSTATUS status;
     144           0 :         struct smb_filename *dir_name = NULL;
     145           0 :         struct smb_filename *rel_name = NULL;
     146           0 :         int ret = -1;
     147             : #ifdef O_PATH
     148           0 :         int open_flags = O_PATH;
     149             : #else
     150           0 :         int open_flags = O_RDONLY;
     151             : #endif
     152             : 
     153           0 :         status = SMB_VFS_PARENT_PATHNAME(handle->conn,
     154             :                                          talloc_tos(),
     155             :                                          smb_fname,
     156             :                                          &dir_name,
     157             :                                          &rel_name);
     158           0 :         if (!NT_STATUS_IS_OK(status)) {
     159           0 :                 errno = map_errno_from_nt_status(status);
     160           0 :                 return -1;
     161             :         }
     162             : 
     163           0 :         fd = open(dir_name->base_name, open_flags, 0);
     164           0 :         if (fd == -1) {
     165           0 :                 TALLOC_FREE(dir_name);
     166           0 :                 return -1;
     167             :         }
     168             : 
     169           0 :         ret = fstatat_with_cap_dac_override(fd,
     170           0 :                                             rel_name->base_name,
     171             :                                             &smb_fname->st,
     172             :                                             flag,
     173             :                                             fake_dctime);
     174             : 
     175           0 :         TALLOC_FREE(dir_name);
     176           0 :         close(fd);
     177             : 
     178           0 :         return ret;
     179             : }
     180             : 
     181           0 : int nfs4_acl_stat(struct vfs_handle_struct *handle,
     182             :                   struct smb_filename *smb_fname)
     183             : {
     184           0 :         int ret;
     185             : 
     186           0 :         ret = SMB_VFS_NEXT_STAT(handle, smb_fname);
     187           0 :         if (ret == -1 && errno == EACCES) {
     188           0 :                 DEBUG(10, ("Trying stat with capability for %s\n",
     189             :                            smb_fname->base_name));
     190           0 :                 ret = stat_with_cap_dac_override(handle, smb_fname, 0);
     191             :         }
     192           0 :         return ret;
     193             : }
     194             : 
     195           0 : static int fstat_with_cap_dac_override(int fd, SMB_STRUCT_STAT *sbuf,
     196             :                                        bool fake_dir_create_times)
     197             : {
     198           0 :         int ret;
     199             : 
     200           0 :         set_effective_capability(DAC_OVERRIDE_CAPABILITY);
     201           0 :         ret = sys_fstat(fd, sbuf, fake_dir_create_times);
     202           0 :         drop_effective_capability(DAC_OVERRIDE_CAPABILITY);
     203             : 
     204           0 :         return ret;
     205             : }
     206             : 
     207           0 : int nfs4_acl_fstat(struct vfs_handle_struct *handle,
     208             :                    struct files_struct *fsp,
     209             :                    SMB_STRUCT_STAT *sbuf)
     210             : {
     211           0 :         int ret;
     212             : 
     213           0 :         ret = SMB_VFS_NEXT_FSTAT(handle, fsp, sbuf);
     214           0 :         if (ret == -1 && errno == EACCES) {
     215           0 :                 bool fake_dctime =
     216           0 :                         lp_fake_directory_create_times(SNUM(handle->conn));
     217             : 
     218           0 :                 DBG_DEBUG("fstat for %s failed with EACCES. Trying with "
     219             :                           "CAP_DAC_OVERRIDE.\n", fsp->fsp_name->base_name);
     220           0 :                 ret = fstat_with_cap_dac_override(fsp_get_pathref_fd(fsp),
     221             :                                                   sbuf,
     222             :                                                   fake_dctime);
     223             :         }
     224             : 
     225           0 :         return ret;
     226             : }
     227             : 
     228           0 : int nfs4_acl_lstat(struct vfs_handle_struct *handle,
     229             :                    struct smb_filename *smb_fname)
     230             : {
     231           0 :         int ret;
     232             : 
     233           0 :         ret = SMB_VFS_NEXT_LSTAT(handle, smb_fname);
     234           0 :         if (ret == -1 && errno == EACCES) {
     235           0 :                 DEBUG(10, ("Trying lstat with capability for %s\n",
     236             :                            smb_fname->base_name));
     237           0 :                 ret = stat_with_cap_dac_override(handle, smb_fname,
     238             :                                                  AT_SYMLINK_NOFOLLOW);
     239             :         }
     240           0 :         return ret;
     241             : }
     242             : 
     243           0 : int nfs4_acl_fstatat(struct vfs_handle_struct *handle,
     244             :                      const struct files_struct *dirfsp,
     245             :                      const struct smb_filename *smb_fname,
     246             :                      SMB_STRUCT_STAT *sbuf,
     247             :                      int flags)
     248             : {
     249           0 :         int ret;
     250             : 
     251           0 :         ret = SMB_VFS_NEXT_FSTATAT(handle, dirfsp, smb_fname, sbuf, flags);
     252           0 :         if (ret == -1 && errno == EACCES) {
     253           0 :                 bool fake_dctime =
     254           0 :                         lp_fake_directory_create_times(SNUM(handle->conn));
     255             : 
     256           0 :                 DBG_DEBUG("fstatat for %s failed with EACCES. Trying with "
     257             :                           "CAP_DAC_OVERRIDE.\n", dirfsp->fsp_name->base_name);
     258           0 :                 ret = fstatat_with_cap_dac_override(fsp_get_pathref_fd(dirfsp),
     259           0 :                                                     smb_fname->base_name,
     260             :                                                     sbuf,
     261             :                                                     flags,
     262             :                                                     fake_dctime);
     263             :         }
     264             : 
     265           0 :         return ret;
     266             : }
     267             : 
     268             : /************************************************
     269             :  Split the ACE flag mapping between nfs4 and Windows
     270             :  into two separate functions rather than trying to do
     271             :  it inline. Allows us to carefully control what flags
     272             :  are mapped to what in one place.
     273             : ************************************************/
     274             : 
     275       11569 : static uint32_t map_nfs4_ace_flags_to_windows_ace_flags(
     276             :         uint32_t nfs4_ace_flags)
     277             : {
     278       11569 :         uint32_t win_ace_flags = 0;
     279             : 
     280             :         /* The nfs4 flags <= 0xf map perfectly. */
     281       11569 :         win_ace_flags = nfs4_ace_flags & (SEC_ACE_FLAG_OBJECT_INHERIT|
     282             :                                       SEC_ACE_FLAG_CONTAINER_INHERIT|
     283             :                                       SEC_ACE_FLAG_NO_PROPAGATE_INHERIT|
     284             :                                       SEC_ACE_FLAG_INHERIT_ONLY);
     285             : 
     286             :         /* flags greater than 0xf have diverged :-(. */
     287             :         /* See the nfs4 ace flag definitions here:
     288             :            http://www.ietf.org/rfc/rfc3530.txt.
     289             :            And the Windows ace flag definitions here:
     290             :            librpc/idl/security.idl. */
     291       11569 :         if (nfs4_ace_flags & SMB_ACE4_INHERITED_ACE) {
     292        2112 :                 win_ace_flags |= SEC_ACE_FLAG_INHERITED_ACE;
     293             :         }
     294             : 
     295       11569 :         return win_ace_flags;
     296             : }
     297             : 
     298        5676 : static uint32_t map_windows_ace_flags_to_nfs4_ace_flags(uint32_t win_ace_flags)
     299             : {
     300        5676 :         uint32_t nfs4_ace_flags = 0;
     301             : 
     302             :         /* The windows flags <= 0xf map perfectly. */
     303        5676 :         nfs4_ace_flags = win_ace_flags & (SMB_ACE4_FILE_INHERIT_ACE|
     304             :                                       SMB_ACE4_DIRECTORY_INHERIT_ACE|
     305             :                                       SMB_ACE4_NO_PROPAGATE_INHERIT_ACE|
     306             :                                       SMB_ACE4_INHERIT_ONLY_ACE);
     307             : 
     308             :         /* flags greater than 0xf have diverged :-(. */
     309             :         /* See the nfs4 ace flag definitions here:
     310             :            http://www.ietf.org/rfc/rfc3530.txt.
     311             :            And the Windows ace flag definitions here:
     312             :            librpc/idl/security.idl. */
     313        5676 :         if (win_ace_flags & SEC_ACE_FLAG_INHERITED_ACE) {
     314        1692 :                 nfs4_ace_flags |= SMB_ACE4_INHERITED_ACE;
     315             :         }
     316             : 
     317        5676 :         return nfs4_ace_flags;
     318             : }
     319             : 
     320       13881 : struct SMB4ACL_T *smb_create_smb4acl(TALLOC_CTX *mem_ctx)
     321             : {
     322         119 :         struct SMB4ACL_T *theacl;
     323             : 
     324       13881 :         theacl = talloc_zero(mem_ctx, struct SMB4ACL_T);
     325       13881 :         if (theacl==NULL)
     326             :         {
     327           0 :                 DEBUG(0, ("TALLOC_SIZE failed\n"));
     328           0 :                 errno = ENOMEM;
     329           0 :                 return NULL;
     330             :         }
     331       13881 :         theacl->controlflags = SEC_DESC_SELF_RELATIVE;
     332             :         /* theacl->first, last = NULL not needed */
     333       13881 :         return theacl;
     334             : }
     335             : 
     336       17183 : struct SMB4ACE_T *smb_add_ace4(struct SMB4ACL_T *acl, SMB_ACE4PROP_T *prop)
     337             : {
     338         149 :         struct SMB4ACE_T *ace;
     339             : 
     340       17183 :         ace = talloc_zero(acl, struct SMB4ACE_T);
     341       17183 :         if (ace==NULL)
     342             :         {
     343           0 :                 DBG_ERR("talloc_zero failed\n");
     344           0 :                 errno = ENOMEM;
     345           0 :                 return NULL;
     346             :         }
     347       17183 :         ace->prop = *prop;
     348             : 
     349       17183 :         if (acl->first==NULL)
     350             :         {
     351       13817 :                 acl->first = ace;
     352       13817 :                 acl->last = ace;
     353             :         } else {
     354        3366 :                 acl->last->next = ace;
     355        3366 :                 acl->last = ace;
     356             :         }
     357       17183 :         acl->naces++;
     358             : 
     359       17183 :         return ace;
     360             : }
     361             : 
     362        5606 : SMB_ACE4PROP_T *smb_get_ace4(struct SMB4ACE_T *ace)
     363             : {
     364        5606 :         if (ace == NULL) {
     365           0 :                 return NULL;
     366             :         }
     367             : 
     368        5606 :         return &ace->prop;
     369             : }
     370             : 
     371        5602 : struct SMB4ACE_T *smb_next_ace4(struct SMB4ACE_T *ace)
     372             : {
     373        5602 :         if (ace == NULL) {
     374           0 :                 return NULL;
     375             :         }
     376             : 
     377        5602 :         return ace->next;
     378             : }
     379             : 
     380        5060 : struct SMB4ACE_T *smb_first_ace4(struct SMB4ACL_T *acl)
     381             : {
     382        5060 :         if (acl == NULL) {
     383           0 :                 return NULL;
     384             :         }
     385             : 
     386        5060 :         return acl->first;
     387             : }
     388             : 
     389        5058 : uint32_t smb_get_naces(struct SMB4ACL_T *acl)
     390             : {
     391        5058 :         if (acl == NULL) {
     392           0 :                 return 0;
     393             :         }
     394             : 
     395        5058 :         return acl->naces;
     396             : }
     397             : 
     398       10968 : uint16_t smbacl4_get_controlflags(struct SMB4ACL_T *acl)
     399             : {
     400       10968 :         if (acl == NULL) {
     401           0 :                 return 0;
     402             :         }
     403             : 
     404       10968 :         return acl->controlflags;
     405             : }
     406             : 
     407        8754 : bool smbacl4_set_controlflags(struct SMB4ACL_T *acl, uint16_t controlflags)
     408             : {
     409        8754 :         if (acl == NULL) {
     410           0 :                 return false;
     411             :         }
     412             : 
     413        8754 :         acl->controlflags = controlflags;
     414        8754 :         return true;
     415             : }
     416             : 
     417        3897 : bool nfs_ace_is_inherit(SMB_ACE4PROP_T *ace)
     418             : {
     419        3897 :         return ace->aceFlags & (SMB_ACE4_INHERIT_ONLY_ACE|
     420             :                                 SMB_ACE4_FILE_INHERIT_ACE|
     421             :                                 SMB_ACE4_DIRECTORY_INHERIT_ACE);
     422             : }
     423             : 
     424           0 : static int smbacl4_GetFileOwner(struct connection_struct *conn,
     425             :                                 const struct smb_filename *smb_fname,
     426             :                                 SMB_STRUCT_STAT *psbuf)
     427             : {
     428           0 :         ZERO_STRUCTP(psbuf);
     429             : 
     430             :         /* Get the stat struct for the owner info. */
     431           0 :         if (vfs_stat_smb_basename(conn, smb_fname, psbuf) != 0)
     432             :         {
     433           0 :                 DEBUG(8, ("vfs_stat_smb_basename failed with error %s\n",
     434             :                         strerror(errno)));
     435           0 :                 return -1;
     436             :         }
     437             : 
     438           0 :         return 0;
     439             : }
     440             : 
     441       11569 : static void check_for_duplicate_sec_ace(struct security_ace *nt_ace_list,
     442             :                                         int *good_aces)
     443             : {
     444       11569 :         struct security_ace *last = NULL;
     445          61 :         int i;
     446             : 
     447       11569 :         if (*good_aces < 2) {
     448        8716 :                 return;
     449             :         }
     450             : 
     451        2804 :         last = &nt_ace_list[(*good_aces) - 1];
     452             : 
     453        5609 :         for (i = 0; i < (*good_aces) - 1; i++) {
     454        2805 :                 struct security_ace *cur = &nt_ace_list[i];
     455             : 
     456        2805 :                 if (cur->type == last->type &&
     457        2797 :                     cur->flags == last->flags &&
     458         145 :                     cur->access_mask == last->access_mask &&
     459           2 :                     dom_sid_equal(&cur->trustee, &last->trustee))
     460             :                 {
     461           2 :                         struct dom_sid_buf sid_buf;
     462             : 
     463           2 :                         DBG_INFO("Removing duplicate entry for SID %s.\n",
     464             :                                  dom_sid_str_buf(&last->trustee, &sid_buf));
     465           2 :                         (*good_aces)--;
     466             :                 }
     467             :         }
     468             : }
     469             : 
     470        8820 : static bool smbacl4_nfs42win(TALLOC_CTX *mem_ctx,
     471             :         const struct smbacl4_vfs_params *params,
     472             :         struct SMB4ACL_T *acl, /* in */
     473             :         struct dom_sid *psid_owner, /* in */
     474             :         struct dom_sid *psid_group, /* in */
     475             :         bool is_directory, /* in */
     476             :         struct security_ace **ppnt_ace_list, /* out */
     477             :         int *pgood_aces /* out */
     478             : )
     479             : {
     480          56 :         struct SMB4ACE_T *aceint;
     481        8820 :         struct security_ace *nt_ace_list = NULL;
     482        8820 :         int good_aces = 0;
     483             : 
     484        8820 :         DEBUG(10, ("%s entered\n", __func__));
     485             : 
     486        8820 :         nt_ace_list = talloc_zero_array(mem_ctx, struct security_ace,
     487             :                                         2 * acl->naces);
     488        8820 :         if (nt_ace_list==NULL)
     489             :         {
     490           0 :                 DEBUG(10, ("talloc error with %d aces\n", acl->naces));
     491           0 :                 errno = ENOMEM;
     492           0 :                 return false;
     493             :         }
     494             : 
     495       20396 :         for (aceint = acl->first; aceint != NULL; aceint = aceint->next) {
     496          68 :                 uint32_t mask;
     497          68 :                 struct dom_sid sid;
     498          68 :                 struct dom_sid_buf buf;
     499       11576 :                 SMB_ACE4PROP_T  *ace = &aceint->prop;
     500          68 :                 uint32_t win_ace_flags;
     501             : 
     502       11576 :                 DEBUG(10, ("type: %d, iflags: %x, flags: %x, "
     503             :                            "mask: %x, who: %d\n",
     504             :                            ace->aceType, ace->flags,
     505             :                            ace->aceFlags, ace->aceMask, ace->who.id));
     506             : 
     507       11576 :                 if (ace->flags & SMB_ACE4_ID_SPECIAL) {
     508       10036 :                         switch (ace->who.special_id) {
     509        6831 :                         case SMB_ACE4_WHO_OWNER:
     510        6831 :                                 sid_copy(&sid, psid_owner);
     511        6831 :                                 break;
     512           5 :                         case SMB_ACE4_WHO_GROUP:
     513           5 :                                 sid_copy(&sid, psid_group);
     514           5 :                                 break;
     515        3193 :                         case SMB_ACE4_WHO_EVERYONE:
     516        3193 :                                 sid_copy(&sid, &global_sid_World);
     517        3193 :                                 break;
     518           7 :                         default:
     519           7 :                                 DEBUG(8, ("invalid special who id %d "
     520             :                                         "ignored\n", ace->who.special_id));
     521           7 :                                 continue;
     522             :                         }
     523             :                 } else {
     524        1540 :                         if (ace->aceFlags & SMB_ACE4_IDENTIFIER_GROUP) {
     525         391 :                                 gid_to_sid(&sid, ace->who.gid);
     526             :                         } else {
     527        1149 :                                 uid_to_sid(&sid, ace->who.uid);
     528             :                         }
     529             :                 }
     530       11569 :                 DEBUG(10, ("mapped %d to %s\n", ace->who.id,
     531             :                            dom_sid_str_buf(&sid, &buf)));
     532             : 
     533       11569 :                 if (!is_directory && params->map_full_control) {
     534             :                         /*
     535             :                          * Do we have all access except DELETE_CHILD
     536             :                          * (not caring about the delete bit).
     537             :                          */
     538        5269 :                         uint32_t test_mask = ((ace->aceMask|SMB_ACE4_DELETE|SMB_ACE4_DELETE_CHILD) &
     539             :                                                 SMB_ACE4_ALL_MASKS);
     540        5269 :                         if (test_mask == SMB_ACE4_ALL_MASKS) {
     541         183 :                                 ace->aceMask |= SMB_ACE4_DELETE_CHILD;
     542             :                         }
     543             :                 }
     544             : 
     545       11569 :                 win_ace_flags = map_nfs4_ace_flags_to_windows_ace_flags(
     546             :                         ace->aceFlags);
     547       11569 :                 if (!is_directory &&
     548        5270 :                     (win_ace_flags & (SEC_ACE_FLAG_OBJECT_INHERIT|
     549             :                                       SEC_ACE_FLAG_CONTAINER_INHERIT))) {
     550             :                         /*
     551             :                          * GPFS sets inherits dir_inherit and file_inherit flags
     552             :                          * to files, too, which confuses windows, and seems to
     553             :                          * be wrong anyways. ==> Map these bits away for files.
     554             :                          */
     555           2 :                         DEBUG(10, ("removing inherit flags from nfs4 ace\n"));
     556           2 :                         win_ace_flags &= ~(SEC_ACE_FLAG_OBJECT_INHERIT|
     557             :                                            SEC_ACE_FLAG_CONTAINER_INHERIT);
     558             :                 }
     559       11569 :                 DEBUG(10, ("Windows mapped ace flags: 0x%x => 0x%x\n",
     560             :                       ace->aceFlags, win_ace_flags));
     561             : 
     562       11569 :                 mask = ace->aceMask;
     563             : 
     564             :                 /* Mapping of owner@ and group@ to creator owner and
     565             :                    creator group. Keep old behavior in mode special. */
     566       11569 :                 if (params->mode != e_special &&
     567        9875 :                     ace->flags & SMB_ACE4_ID_SPECIAL &&
     568        8613 :                     (ace->who.special_id == SMB_ACE4_WHO_OWNER ||
     569        2736 :                      ace->who.special_id == SMB_ACE4_WHO_GROUP)) {
     570        5876 :                         DEBUG(10, ("Map special entry\n"));
     571        5876 :                         if (!(win_ace_flags & SEC_ACE_FLAG_INHERIT_ONLY)) {
     572           8 :                                 uint32_t win_ace_flags_current;
     573        4652 :                                 DEBUG(10, ("Map current sid\n"));
     574        4652 :                                 win_ace_flags_current = win_ace_flags &
     575             :                                         ~(SEC_ACE_FLAG_OBJECT_INHERIT |
     576             :                                           SEC_ACE_FLAG_CONTAINER_INHERIT);
     577        4652 :                                 init_sec_ace(&nt_ace_list[good_aces++], &sid,
     578        4652 :                                              ace->aceType, mask,
     579             :                                              win_ace_flags_current);
     580             :                         }
     581        5876 :                         if (ace->who.special_id == SMB_ACE4_WHO_OWNER &&
     582        5872 :                             win_ace_flags & (SEC_ACE_FLAG_OBJECT_INHERIT |
     583             :                                              SEC_ACE_FLAG_CONTAINER_INHERIT)) {
     584           3 :                                 uint32_t win_ace_flags_creator;
     585        1227 :                                 DEBUG(10, ("Map creator owner\n"));
     586        1227 :                                 win_ace_flags_creator = win_ace_flags |
     587             :                                         SMB_ACE4_INHERIT_ONLY_ACE;
     588        1227 :                                 init_sec_ace(&nt_ace_list[good_aces++],
     589             :                                              &global_sid_Creator_Owner,
     590        1227 :                                              ace->aceType, mask,
     591             :                                              win_ace_flags_creator);
     592             :                         }
     593        5876 :                         if (ace->who.special_id == SMB_ACE4_WHO_GROUP &&
     594           4 :                             win_ace_flags & (SEC_ACE_FLAG_OBJECT_INHERIT |
     595             :                                              SEC_ACE_FLAG_CONTAINER_INHERIT)) {
     596           3 :                                 uint32_t win_ace_flags_creator;
     597           3 :                                 DEBUG(10, ("Map creator owner group\n"));
     598           3 :                                 win_ace_flags_creator = win_ace_flags |
     599             :                                         SMB_ACE4_INHERIT_ONLY_ACE;
     600           3 :                                 init_sec_ace(&nt_ace_list[good_aces++],
     601             :                                              &global_sid_Creator_Group,
     602           3 :                                              ace->aceType, mask,
     603             :                                              win_ace_flags_creator);
     604             :                         }
     605             :                 } else {
     606        5693 :                         DEBUG(10, ("Map normal sid\n"));
     607        5693 :                         init_sec_ace(&nt_ace_list[good_aces++], &sid,
     608        5693 :                                      ace->aceType, mask,
     609             :                                      win_ace_flags);
     610             :                 }
     611             : 
     612       11569 :                 check_for_duplicate_sec_ace(nt_ace_list, &good_aces);
     613             :         }
     614             : 
     615        8820 :         nt_ace_list = talloc_realloc(mem_ctx, nt_ace_list, struct security_ace,
     616             :                                      good_aces);
     617             : 
     618             :         /* returns a NULL ace list when good_aces is zero. */
     619        8820 :         if (good_aces && nt_ace_list == NULL) {
     620           0 :                 DEBUG(10, ("realloc error with %d aces\n", good_aces));
     621           0 :                 errno = ENOMEM;
     622           0 :                 return false;
     623             :         }
     624             : 
     625        8820 :         *ppnt_ace_list = nt_ace_list;
     626        8820 :         *pgood_aces = good_aces;
     627             : 
     628        8820 :         return true;
     629             : }
     630             : 
     631        8764 : static NTSTATUS smb_get_nt_acl_nfs4_common(const SMB_STRUCT_STAT *sbuf,
     632             :                                            const struct smbacl4_vfs_params *params,
     633             :                                            uint32_t security_info,
     634             :                                            TALLOC_CTX *mem_ctx,
     635             :                                            struct security_descriptor **ppdesc,
     636             :                                            struct SMB4ACL_T *theacl)
     637             : {
     638        8764 :         int good_aces = 0;
     639           0 :         struct dom_sid sid_owner, sid_group;
     640        8764 :         size_t sd_size = 0;
     641        8764 :         struct security_ace *nt_ace_list = NULL;
     642        8764 :         struct security_acl *psa = NULL;
     643        8764 :         TALLOC_CTX *frame = talloc_stackframe();
     644           0 :         bool ok;
     645             : 
     646        8764 :         if (theacl==NULL) {
     647           0 :                 TALLOC_FREE(frame);
     648           0 :                 return NT_STATUS_ACCESS_DENIED; /* special because we
     649             :                                                  * need to think through
     650             :                                                  * the null case.*/
     651             :         }
     652             : 
     653        8764 :         uid_to_sid(&sid_owner, sbuf->st_ex_uid);
     654        8764 :         gid_to_sid(&sid_group, sbuf->st_ex_gid);
     655             : 
     656        8764 :         ok = smbacl4_nfs42win(frame, params, theacl, &sid_owner, &sid_group,
     657        8764 :                               S_ISDIR(sbuf->st_ex_mode),
     658             :                               &nt_ace_list, &good_aces);
     659        8764 :         if (!ok) {
     660           0 :                 DEBUG(8,("smbacl4_nfs42win failed\n"));
     661           0 :                 TALLOC_FREE(frame);
     662           0 :                 return map_nt_error_from_unix(errno);
     663             :         }
     664             : 
     665        8764 :         psa = make_sec_acl(frame, NT4_ACL_REVISION, good_aces, nt_ace_list);
     666        8764 :         if (psa == NULL) {
     667           0 :                 DEBUG(2,("make_sec_acl failed\n"));
     668           0 :                 TALLOC_FREE(frame);
     669           0 :                 return NT_STATUS_NO_MEMORY;
     670             :         }
     671             : 
     672        8764 :         DEBUG(10,("after make sec_acl\n"));
     673       26292 :         *ppdesc = make_sec_desc(
     674        8764 :                 mem_ctx, SD_REVISION, smbacl4_get_controlflags(theacl),
     675        8764 :                 (security_info & SECINFO_OWNER) ? &sid_owner : NULL,
     676        8764 :                 (security_info & SECINFO_GROUP) ? &sid_group : NULL,
     677             :                 NULL, psa, &sd_size);
     678        8764 :         if (*ppdesc==NULL) {
     679           0 :                 DEBUG(2,("make_sec_desc failed\n"));
     680           0 :                 TALLOC_FREE(frame);
     681           0 :                 return NT_STATUS_NO_MEMORY;
     682             :         }
     683             : 
     684        8764 :         DEBUG(10, ("smb_get_nt_acl_nfs4_common successfully exited with "
     685             :                    "sd_size %d\n",
     686             :                    (int)ndr_size_security_descriptor(*ppdesc, 0)));
     687             : 
     688        8764 :         TALLOC_FREE(frame);
     689        8764 :         return NT_STATUS_OK;
     690             : }
     691             : 
     692        8764 : NTSTATUS smb_fget_nt_acl_nfs4(files_struct *fsp,
     693             :                               const struct smbacl4_vfs_params *pparams,
     694             :                               uint32_t security_info,
     695             :                               TALLOC_CTX *mem_ctx,
     696             :                               struct security_descriptor **ppdesc,
     697             :                               struct SMB4ACL_T *theacl)
     698             : {
     699           0 :         struct smbacl4_vfs_params params;
     700             : 
     701        8764 :         DEBUG(10, ("smb_fget_nt_acl_nfs4 invoked for %s\n", fsp_str_dbg(fsp)));
     702             : 
     703        8764 :         if (!VALID_STAT(fsp->fsp_name->st)) {
     704           0 :                 NTSTATUS status;
     705             : 
     706           0 :                 status = vfs_stat_fsp(fsp);
     707           0 :                 if (!NT_STATUS_IS_OK(status)) {
     708           0 :                         return status;
     709             :                 }
     710             :         }
     711             : 
     712        8764 :         if (pparams == NULL) {
     713             :                 /* Special behaviours */
     714        8764 :                 if (smbacl4_get_vfs_params(fsp->conn, &params)) {
     715           0 :                         return NT_STATUS_NO_MEMORY;
     716             :                 }
     717        8764 :                 pparams = &params;
     718             :         }
     719             : 
     720        8764 :         return smb_get_nt_acl_nfs4_common(&fsp->fsp_name->st, pparams,
     721             :                                           security_info,
     722             :                                           mem_ctx, ppdesc, theacl);
     723             : }
     724             : 
     725           0 : NTSTATUS smb_get_nt_acl_nfs4(struct connection_struct *conn,
     726             :                              const struct smb_filename *smb_fname,
     727             :                              const struct smbacl4_vfs_params *pparams,
     728             :                              uint32_t security_info,
     729             :                              TALLOC_CTX *mem_ctx,
     730             :                              struct security_descriptor **ppdesc,
     731             :                              struct SMB4ACL_T *theacl)
     732             : {
     733           0 :         SMB_STRUCT_STAT sbuf;
     734           0 :         struct smbacl4_vfs_params params;
     735           0 :         const SMB_STRUCT_STAT *psbuf = NULL;
     736             : 
     737           0 :         DEBUG(10, ("smb_get_nt_acl_nfs4 invoked for %s\n",
     738             :                 smb_fname->base_name));
     739             : 
     740           0 :         if (VALID_STAT(smb_fname->st)) {
     741           0 :                 psbuf = &smb_fname->st;
     742             :         }
     743             : 
     744           0 :         if (psbuf == NULL) {
     745           0 :                 if (smbacl4_GetFileOwner(conn, smb_fname, &sbuf)) {
     746           0 :                         return map_nt_error_from_unix(errno);
     747             :                 }
     748           0 :                 psbuf = &sbuf;
     749             :         }
     750             : 
     751           0 :         if (pparams == NULL) {
     752             :                 /* Special behaviours */
     753           0 :                 if (smbacl4_get_vfs_params(conn, &params)) {
     754           0 :                         return NT_STATUS_NO_MEMORY;
     755             :                 }
     756           0 :                 pparams = &params;
     757             :         }
     758             : 
     759           0 :         return smb_get_nt_acl_nfs4_common(psbuf, pparams, security_info,
     760             :                                           mem_ctx, ppdesc, theacl);
     761             : }
     762             : 
     763        4998 : static void smbacl4_dump_nfs4acl(int level, struct SMB4ACL_T *acl)
     764             : {
     765           0 :         struct SMB4ACE_T *aceint;
     766             : 
     767        4998 :         DEBUG(level, ("NFS4ACL: size=%d\n", acl->naces));
     768             : 
     769       10524 :         for (aceint = acl->first; aceint != NULL; aceint = aceint->next) {
     770        5526 :                 SMB_ACE4PROP_T *ace = &aceint->prop;
     771             : 
     772        5526 :                 DEBUG(level, ("\tACE: type=%d, flags=0x%x, fflags=0x%x, "
     773             :                               "mask=0x%x, id=%d\n",
     774             :                               ace->aceType,
     775             :                               ace->aceFlags, ace->flags,
     776             :                               ace->aceMask,
     777             :                               ace->who.id));
     778             :         }
     779        4998 : }
     780             : 
     781             : /*
     782             :  * Find 2 NFS4 who-special ACE property (non-copy!!!)
     783             :  * match nonzero if "special" and who is equal
     784             :  * return ace if found matching; otherwise NULL
     785             :  */
     786        5599 : static SMB_ACE4PROP_T *smbacl4_find_equal_special(
     787             :         struct SMB4ACL_T *acl,
     788             :         SMB_ACE4PROP_T *aceNew)
     789             : {
     790          73 :         struct SMB4ACE_T *aceint;
     791             : 
     792        6150 :         for (aceint = acl->first; aceint != NULL; aceint = aceint->next) {
     793         556 :                 SMB_ACE4PROP_T *ace = &aceint->prop;
     794             : 
     795         556 :                 DEBUG(10,("ace type:0x%x flags:0x%x aceFlags:0x%x "
     796             :                           "new type:0x%x flags:0x%x aceFlags:0x%x\n",
     797             :                           ace->aceType, ace->flags, ace->aceFlags,
     798             :                           aceNew->aceType, aceNew->flags,aceNew->aceFlags));
     799             : 
     800         556 :                 if (ace->flags == aceNew->flags &&
     801         168 :                         ace->aceType==aceNew->aceType &&
     802         167 :                         ace->aceFlags==aceNew->aceFlags)
     803             :                 {
     804             :                         /* keep type safety; e.g. gid is an u.short */
     805          11 :                         if (ace->flags & SMB_ACE4_ID_SPECIAL)
     806             :                         {
     807           6 :                                 if (ace->who.special_id ==
     808           6 :                                     aceNew->who.special_id)
     809           0 :                                         return ace;
     810             :                         } else {
     811           5 :                                 if (ace->aceFlags & SMB_ACE4_IDENTIFIER_GROUP)
     812             :                                 {
     813           0 :                                         if (ace->who.gid==aceNew->who.gid)
     814           0 :                                                 return ace;
     815             :                                 } else {
     816           5 :                                         if (ace->who.uid==aceNew->who.uid)
     817           5 :                                                 return ace;
     818             :                                 }
     819             :                         }
     820             :                 }
     821             :         }
     822             : 
     823        5526 :         return NULL;
     824             : }
     825             : 
     826        5599 : static int smbacl4_MergeIgnoreReject(enum smbacl4_acedup_enum acedup,
     827             :                                      struct SMB4ACL_T *theacl,
     828             :                                      SMB_ACE4PROP_T *ace,
     829             :                                      bool *paddNewACE)
     830             : {
     831        5599 :         int     result = 0;
     832        5599 :         SMB_ACE4PROP_T *ace4found = smbacl4_find_equal_special(theacl, ace);
     833        5599 :         if (ace4found)
     834             :         {
     835           5 :                 switch(acedup)
     836             :                 {
     837           1 :                 case e_merge: /* "merge" flags */
     838           1 :                         *paddNewACE = false;
     839           1 :                         ace4found->aceFlags |= ace->aceFlags;
     840           1 :                         ace4found->aceMask |= ace->aceMask;
     841           1 :                         break;
     842           3 :                 case e_ignore: /* leave out this record */
     843           3 :                         *paddNewACE = false;
     844           3 :                         break;
     845           1 :                 case e_reject: /* do an error */
     846           1 :                         DBG_INFO("ACL rejected by duplicate nt ace.\n");
     847           1 :                         errno = EINVAL; /* SHOULD be set on any _real_ error */
     848           1 :                         result = -1;
     849           1 :                         break;
     850           0 :                 default:
     851           0 :                         break;
     852             :                 }
     853             :         }
     854        5599 :         return result;
     855             : }
     856             : 
     857        5612 : static int nfs4_acl_add_ace(enum smbacl4_acedup_enum acedup,
     858             :                             struct SMB4ACL_T *nfs4_acl,
     859             :                             SMB_ACE4PROP_T *nfs4_ace)
     860             : {
     861        5612 :         bool add_ace = true;
     862             : 
     863        5612 :         if (acedup != e_dontcare) {
     864          73 :                 int ret;
     865             : 
     866        5599 :                 ret = smbacl4_MergeIgnoreReject(acedup, nfs4_acl,
     867             :                                                 nfs4_ace, &add_ace);
     868        5599 :                 if (ret == -1) {
     869           0 :                         return -1;
     870             :                 }
     871             :         }
     872             : 
     873        5611 :         if (add_ace) {
     874        5607 :                 smb_add_ace4(nfs4_acl, nfs4_ace);
     875             :         }
     876             : 
     877        5526 :         return 0;
     878             : }
     879             : 
     880        5676 : static int nfs4_acl_add_sec_ace(bool is_directory,
     881             :                                 const struct smbacl4_vfs_params *params,
     882             :                                 uid_t ownerUID,
     883             :                                 gid_t ownerGID,
     884             :                                 const struct security_ace *ace_nt,
     885             :                                 struct SMB4ACL_T *nfs4_acl)
     886             : {
     887          90 :         struct dom_sid_buf buf;
     888        5676 :         SMB_ACE4PROP_T nfs4_ace = { 0 };
     889        5676 :         SMB_ACE4PROP_T nfs4_ace_2 = { 0 };
     890        5676 :         bool add_ace2 = false;
     891          90 :         int ret;
     892             : 
     893        5676 :         DEBUG(10, ("got ace for %s\n",
     894             :                    dom_sid_str_buf(&ace_nt->trustee, &buf)));
     895             : 
     896             :         /* only ACCESS|DENY supported right now */
     897        5676 :         nfs4_ace.aceType = ace_nt->type;
     898             : 
     899        5766 :         nfs4_ace.aceFlags =
     900        5676 :                 map_windows_ace_flags_to_nfs4_ace_flags(ace_nt->flags);
     901             : 
     902             :         /* remove inheritance flags on files */
     903        5676 :         if (!is_directory) {
     904        4287 :                 DEBUG(10, ("Removing inheritance flags from a file\n"));
     905        4287 :                 nfs4_ace.aceFlags &= ~(SMB_ACE4_FILE_INHERIT_ACE|
     906             :                                        SMB_ACE4_DIRECTORY_INHERIT_ACE|
     907             :                                        SMB_ACE4_NO_PROPAGATE_INHERIT_ACE|
     908             :                                        SMB_ACE4_INHERIT_ONLY_ACE);
     909             :         }
     910             : 
     911        5676 :         nfs4_ace.aceMask = ace_nt->access_mask & (SEC_STD_ALL | SEC_FILE_ALL);
     912             : 
     913        5676 :         se_map_generic(&nfs4_ace.aceMask, &file_generic_mapping);
     914             : 
     915        5676 :         if (dom_sid_equal(&ace_nt->trustee, &global_sid_World)) {
     916         659 :                 nfs4_ace.who.special_id = SMB_ACE4_WHO_EVERYONE;
     917         659 :                 nfs4_ace.flags |= SMB_ACE4_ID_SPECIAL;
     918        9324 :         } else if (params->mode!=e_special &&
     919        4307 :                    dom_sid_equal(&ace_nt->trustee,
     920             :                                  &global_sid_Creator_Owner)) {
     921         284 :                 DEBUG(10, ("Map creator owner\n"));
     922         284 :                 nfs4_ace.who.special_id = SMB_ACE4_WHO_OWNER;
     923         284 :                 nfs4_ace.flags |= SMB_ACE4_ID_SPECIAL;
     924             :                 /* A non inheriting creator owner entry has no effect. */
     925         284 :                 nfs4_ace.aceFlags |= SMB_ACE4_INHERIT_ONLY_ACE;
     926         284 :                 if (!(nfs4_ace.aceFlags & SMB_ACE4_DIRECTORY_INHERIT_ACE)
     927         140 :                     && !(nfs4_ace.aceFlags & SMB_ACE4_FILE_INHERIT_ACE)) {
     928          60 :                         return 0;
     929             :                 }
     930        8756 :         } else if (params->mode!=e_special &&
     931        4023 :                    dom_sid_equal(&ace_nt->trustee,
     932             :                                  &global_sid_Creator_Group)) {
     933           8 :                 DEBUG(10, ("Map creator owner group\n"));
     934           8 :                 nfs4_ace.who.special_id = SMB_ACE4_WHO_GROUP;
     935           8 :                 nfs4_ace.flags |= SMB_ACE4_ID_SPECIAL;
     936             :                 /* A non inheriting creator group entry has no effect. */
     937           8 :                 nfs4_ace.aceFlags |= SMB_ACE4_INHERIT_ONLY_ACE;
     938           8 :                 if (!(nfs4_ace.aceFlags & SMB_ACE4_DIRECTORY_INHERIT_ACE)
     939           8 :                     && !(nfs4_ace.aceFlags & SMB_ACE4_FILE_INHERIT_ACE)) {
     940           0 :                         return 0;
     941             :                 }
     942             :         } else {
     943          73 :                 struct unixid unixid;
     944          73 :                 bool ok;
     945             : 
     946        4725 :                 ok = sids_to_unixids(&ace_nt->trustee, 1, &unixid);
     947        4725 :                 if (!ok) {
     948           0 :                         DBG_WARNING("Could not convert %s to uid or gid.\n",
     949             :                                     dom_sid_str_buf(&ace_nt->trustee, &buf));
     950           1 :                         return 0;
     951             :                 }
     952             : 
     953        4725 :                 if (dom_sid_compare_domain(&ace_nt->trustee,
     954             :                                            &global_sid_Unix_NFS) == 0) {
     955           0 :                         return 0;
     956             :                 }
     957             : 
     958        4724 :                 switch (unixid.type) {
     959           4 :                 case ID_TYPE_BOTH:
     960           4 :                         nfs4_ace.aceFlags |= SMB_ACE4_IDENTIFIER_GROUP;
     961           4 :                         nfs4_ace.who.gid = unixid.id;
     962             : 
     963           6 :                         if (ownerUID == unixid.id &&
     964           2 :                             !nfs_ace_is_inherit(&nfs4_ace))
     965             :                         {
     966             :                                 /*
     967             :                                  * IDMAP_TYPE_BOTH for owner. Add
     968             :                                  * additional user entry, which can be
     969             :                                  * mapped to special:owner to reflect
     970             :                                  * the permissions in the modebits.
     971             :                                  *
     972             :                                  * This only applies to non-inheriting
     973             :                                  * entries as only these are replaced
     974             :                                  * with SPECIAL_OWNER in nfs4:mode=simple.
     975             :                                  */
     976           1 :                                 nfs4_ace_2 = (SMB_ACE4PROP_T) {
     977           1 :                                         .who.uid = unixid.id,
     978           1 :                                         .aceFlags = (nfs4_ace.aceFlags &
     979             :                                                     ~SMB_ACE4_IDENTIFIER_GROUP),
     980           1 :                                         .aceMask = nfs4_ace.aceMask,
     981           1 :                                         .aceType = nfs4_ace.aceType,
     982             :                                 };
     983           1 :                                 add_ace2 = true;
     984             :                         }
     985           0 :                         break;
     986         123 :                 case ID_TYPE_GID:
     987         123 :                         nfs4_ace.aceFlags |= SMB_ACE4_IDENTIFIER_GROUP;
     988         123 :                         nfs4_ace.who.gid = unixid.id;
     989         123 :                         break;
     990        4597 :                 case ID_TYPE_UID:
     991        4597 :                         nfs4_ace.who.uid = unixid.id;
     992        4597 :                         break;
     993           0 :                 case ID_TYPE_NOT_SPECIFIED:
     994             :                 default:
     995           0 :                         DBG_WARNING("Could not convert %s to uid or gid.\n",
     996             :                                     dom_sid_str_buf(&ace_nt->trustee, &buf));
     997           0 :                         return 0;
     998             :                 }
     999             :         }
    1000             : 
    1001        5611 :         ret = nfs4_acl_add_ace(params->acedup, nfs4_acl, &nfs4_ace);
    1002        5611 :         if (ret != 0) {
    1003           0 :                 return -1;
    1004             :         }
    1005             : 
    1006        5610 :         if (!add_ace2) {
    1007        5526 :                 return 0;
    1008             :         }
    1009             : 
    1010           1 :         return nfs4_acl_add_ace(params->acedup, nfs4_acl, &nfs4_ace_2);
    1011             : }
    1012             : 
    1013         715 : static void smbacl4_substitute_special(struct SMB4ACL_T *acl,
    1014             :                                        uid_t ownerUID,
    1015             :                                        gid_t ownerGID)
    1016             : {
    1017           1 :         struct SMB4ACE_T *aceint;
    1018             : 
    1019        1519 :         for (aceint = acl->first; aceint != NULL; aceint = aceint->next) {
    1020         804 :                 SMB_ACE4PROP_T *ace = &aceint->prop;
    1021             : 
    1022         804 :                 DEBUG(10,("ace type: %d, iflags: %x, flags: %x, "
    1023             :                           "mask: %x, who: %d\n",
    1024             :                           ace->aceType, ace->flags, ace->aceFlags,
    1025             :                           ace->aceMask, ace->who.id));
    1026             : 
    1027         804 :                 if (!(ace->flags & SMB_ACE4_ID_SPECIAL) &&
    1028         710 :                     !(ace->aceFlags & SMB_ACE4_IDENTIFIER_GROUP) &&
    1029         651 :                     ace->who.uid == ownerUID) {
    1030         650 :                         ace->flags |= SMB_ACE4_ID_SPECIAL;
    1031         650 :                         ace->who.special_id = SMB_ACE4_WHO_OWNER;
    1032         650 :                         DEBUG(10,("replaced with special owner ace\n"));
    1033             :                 }
    1034             : 
    1035         804 :                 if (!(ace->flags & SMB_ACE4_ID_SPECIAL) &&
    1036          60 :                     ace->aceFlags & SMB_ACE4_IDENTIFIER_GROUP &&
    1037          59 :                     ace->who.uid == ownerGID) {
    1038           2 :                         ace->flags |= SMB_ACE4_ID_SPECIAL;
    1039           2 :                         ace->who.special_id = SMB_ACE4_WHO_GROUP;
    1040           2 :                         DEBUG(10,("replaced with special group ace\n"));
    1041             :                 }
    1042             :         }
    1043         715 : }
    1044             : 
    1045        4345 : static void smbacl4_substitute_simple(struct SMB4ACL_T *acl,
    1046             :                                       uid_t ownerUID,
    1047             :                                       gid_t ownerGID)
    1048             : {
    1049          61 :         struct SMB4ACE_T *aceint;
    1050             : 
    1051        9147 :         for (aceint = acl->first; aceint != NULL; aceint = aceint->next) {
    1052        4802 :                 SMB_ACE4PROP_T *ace = &aceint->prop;
    1053             : 
    1054        4802 :                 DEBUG(10,("ace type: %d, iflags: %x, flags: %x, "
    1055             :                           "mask: %x, who: %d\n",
    1056             :                           ace->aceType, ace->flags, ace->aceFlags,
    1057             :                           ace->aceMask, ace->who.id));
    1058             : 
    1059        4802 :                 if (!(ace->flags & SMB_ACE4_ID_SPECIAL) &&
    1060        4009 :                     !(ace->aceFlags & SMB_ACE4_IDENTIFIER_GROUP) &&
    1061        3944 :                     ace->who.uid == ownerUID &&
    1062        3891 :                     !nfs_ace_is_inherit(ace)) {
    1063        3661 :                         ace->flags |= SMB_ACE4_ID_SPECIAL;
    1064        3661 :                         ace->who.special_id = SMB_ACE4_WHO_OWNER;
    1065        3661 :                         DEBUG(10,("replaced with special owner ace\n"));
    1066             :                 }
    1067             : 
    1068        4802 :                 if (!(ace->flags & SMB_ACE4_ID_SPECIAL) &&
    1069         348 :                     ace->aceFlags & SMB_ACE4_IDENTIFIER_GROUP &&
    1070          72 :                     ace->who.gid == ownerGID &&
    1071           4 :                     !nfs_ace_is_inherit(ace)) {
    1072           1 :                         ace->flags |= SMB_ACE4_ID_SPECIAL;
    1073           1 :                         ace->who.special_id = SMB_ACE4_WHO_GROUP;
    1074           1 :                         DEBUG(10,("replaced with special group ace\n"));
    1075             :                 }
    1076             :         }
    1077        4345 : }
    1078             : 
    1079        5061 : static struct SMB4ACL_T *smbacl4_win2nfs4(
    1080             :         TALLOC_CTX *mem_ctx,
    1081             :         bool is_directory,
    1082             :         const struct security_acl *dacl,
    1083             :         const struct smbacl4_vfs_params *pparams,
    1084             :         uid_t ownerUID,
    1085             :         gid_t ownerGID
    1086             : )
    1087             : {
    1088          63 :         struct SMB4ACL_T *theacl;
    1089          63 :         uint32_t i;
    1090             : 
    1091        5061 :         DEBUG(10, ("smbacl4_win2nfs4 invoked\n"));
    1092             : 
    1093        5061 :         theacl = smb_create_smb4acl(mem_ctx);
    1094        5061 :         if (theacl==NULL)
    1095           0 :                 return NULL;
    1096             : 
    1097       10736 :         for(i=0; i<dacl->num_aces; i++) {
    1098          90 :                 int ret;
    1099             : 
    1100        5766 :                 ret = nfs4_acl_add_sec_ace(is_directory, pparams,
    1101             :                                            ownerUID, ownerGID,
    1102        5676 :                                            dacl->aces + i, theacl);
    1103        5676 :                 if (ret == -1) {
    1104           0 :                         return NULL;
    1105             :                 }
    1106             :         }
    1107             : 
    1108        5060 :         if (pparams->mode==e_simple) {
    1109        4345 :                 smbacl4_substitute_simple(theacl, ownerUID, ownerGID);
    1110             :         }
    1111             : 
    1112        5060 :         if (pparams->mode==e_special) {
    1113         715 :                 smbacl4_substitute_special(theacl, ownerUID, ownerGID);
    1114             :         }
    1115             : 
    1116        4998 :         return theacl;
    1117             : }
    1118             : 
    1119        5012 : NTSTATUS smb_set_nt_acl_nfs4(vfs_handle_struct *handle, files_struct *fsp,
    1120             :         const struct smbacl4_vfs_params *pparams,
    1121             :         uint32_t security_info_sent,
    1122             :         const struct security_descriptor *psd,
    1123             :         set_nfs4acl_native_fn_t set_nfs4_native)
    1124             : {
    1125           0 :         struct smbacl4_vfs_params params;
    1126        5012 :         struct SMB4ACL_T *theacl = NULL;
    1127           0 :         bool    result, is_directory;
    1128             : 
    1129        5012 :         bool set_acl_as_root = false;
    1130           0 :         int saved_errno;
    1131           0 :         NTSTATUS status;
    1132        5012 :         TALLOC_CTX *frame = talloc_stackframe();
    1133             : 
    1134        5012 :         DEBUG(10, ("smb_set_nt_acl_nfs4 invoked for %s\n", fsp_str_dbg(fsp)));
    1135             : 
    1136        5012 :         if ((security_info_sent & (SECINFO_DACL |
    1137             :                 SECINFO_GROUP | SECINFO_OWNER)) == 0)
    1138             :         {
    1139           0 :                 DEBUG(9, ("security_info_sent (0x%x) ignored\n",
    1140             :                         security_info_sent));
    1141           0 :                 TALLOC_FREE(frame);
    1142           0 :                 return NT_STATUS_OK; /* won't show error - later to be
    1143             :                                       * refined... */
    1144             :         }
    1145             : 
    1146        5012 :         if (security_descriptor_with_ms_nfs(psd)) {
    1147           0 :                 TALLOC_FREE(frame);
    1148           0 :                 return NT_STATUS_OK;
    1149             :         }
    1150             : 
    1151        5012 :         if (pparams == NULL) {
    1152             :                 /* Special behaviours */
    1153           0 :                 if (smbacl4_get_vfs_params(fsp->conn, &params)) {
    1154           0 :                         TALLOC_FREE(frame);
    1155           0 :                         return NT_STATUS_NO_MEMORY;
    1156             :                 }
    1157           0 :                 pparams = &params;
    1158             :         }
    1159             : 
    1160        5012 :         status = vfs_stat_fsp(fsp);
    1161        5012 :         if (!NT_STATUS_IS_OK(status)) {
    1162           0 :                 TALLOC_FREE(frame);
    1163           0 :                 return status;
    1164             :         }
    1165             : 
    1166        5012 :         is_directory = S_ISDIR(fsp->fsp_name->st.st_ex_mode);
    1167             : 
    1168        5012 :         if (pparams->do_chown) {
    1169             :                 /*
    1170             :                  * When the chown succeeds, the special entries in the
    1171             :                  * file system ACL refer to the new owner. In order to
    1172             :                  * apply the complete information from the DACL,
    1173             :                  * setting the ACL then has to succeed. Track this
    1174             :                  * case with set_acl_as_root and set the ACL as root
    1175             :                  * accordingly.
    1176             :                  */
    1177        5012 :                 status = chown_if_needed(fsp, security_info_sent, psd,
    1178             :                                          &set_acl_as_root);
    1179        5012 :                 if (!NT_STATUS_IS_OK(status)) {
    1180           0 :                         TALLOC_FREE(frame);
    1181           0 :                         return status;
    1182             :                 }
    1183             :         }
    1184             : 
    1185        5012 :         if (!(security_info_sent & SECINFO_DACL) || psd->dacl ==NULL) {
    1186          14 :                 DEBUG(10, ("no dacl found; security_info_sent = 0x%x\n",
    1187             :                            security_info_sent));
    1188          14 :                 TALLOC_FREE(frame);
    1189          14 :                 return NT_STATUS_OK;
    1190             :         }
    1191             : 
    1192        4998 :         theacl = smbacl4_win2nfs4(frame, is_directory, psd->dacl, pparams,
    1193        4998 :                                   fsp->fsp_name->st.st_ex_uid,
    1194        4998 :                                   fsp->fsp_name->st.st_ex_gid);
    1195        4998 :         if (!theacl) {
    1196           0 :                 TALLOC_FREE(frame);
    1197           0 :                 return map_nt_error_from_unix(errno);
    1198             :         }
    1199             : 
    1200        4998 :         smbacl4_set_controlflags(theacl, psd->type);
    1201        4998 :         smbacl4_dump_nfs4acl(10, theacl);
    1202             : 
    1203        4998 :         if (set_acl_as_root) {
    1204         532 :                 set_effective_capability(DAC_OVERRIDE_CAPABILITY);
    1205             :         }
    1206        4998 :         result = set_nfs4_native(handle, fsp, theacl);
    1207        4998 :         saved_errno = errno;
    1208        4998 :         if (set_acl_as_root) {
    1209         532 :                 drop_effective_capability(DAC_OVERRIDE_CAPABILITY);
    1210             :         }
    1211             : 
    1212        4998 :         TALLOC_FREE(frame);
    1213             : 
    1214        4998 :         if (result!=true) {
    1215           0 :                 errno = saved_errno;
    1216           0 :                 DEBUG(10, ("set_nfs4_native failed with %s\n",
    1217             :                            strerror(errno)));
    1218           0 :                 return map_nt_error_from_unix(errno);
    1219             :         }
    1220             : 
    1221        4998 :         DEBUG(10, ("smb_set_nt_acl_nfs4 succeeded\n"));
    1222        4998 :         return NT_STATUS_OK;
    1223             : }

Generated by: LCOV version 1.14