LCOV - code coverage report
Current view: top level - source3/modules - nfs4_acls.c (source / functions) Hit Total Coverage
Test: coverage report for abartlet/fix-coverage dd10fb34 Lines: 380 480 79.2 %
Date: 2021-09-23 10:06:22 Functions: 28 31 90.3 %

          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        8988 : int smbacl4_get_vfs_params(struct connection_struct *conn,
      60             :                            struct smbacl4_vfs_params *params)
      61             : {
      62             :         static const struct enum_list enum_smbacl4_modes[] = {
      63             :                 { e_simple, "simple" },
      64             :                 { e_special, "special" },
      65             :                 { -1 , NULL }
      66             :         };
      67             :         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             :         int enumval;
      75             : 
      76        8988 :         *params = (struct smbacl4_vfs_params) { 0 };
      77             : 
      78        8988 :         enumval = lp_parm_enum(SNUM(conn), SMBACL4_PARAM_TYPE_NAME, "mode",
      79             :                                enum_smbacl4_modes, e_simple);
      80        8988 :         if (enumval == -1) {
      81           0 :                 DEBUG(10, ("value for %s:mode unknown\n",
      82             :                            SMBACL4_PARAM_TYPE_NAME));
      83           0 :                 return -1;
      84             :         }
      85        8988 :         params->mode = (enum smbacl4_mode_enum)enumval;
      86        8988 :         if (params->mode == e_special) {
      87        1284 :                 DBG_WARNING("nfs4:mode special is deprecated.\n");
      88             :         }
      89             : 
      90        8988 :         params->do_chown = lp_parm_bool(SNUM(conn), SMBACL4_PARAM_TYPE_NAME,
      91             :                 "chown", true);
      92             : 
      93        8988 :         enumval = lp_parm_enum(SNUM(conn), SMBACL4_PARAM_TYPE_NAME, "acedup",
      94             :                                enum_smbacl4_acedups, e_merge);
      95        8988 :         if (enumval == -1) {
      96           0 :                 DEBUG(10, ("value for %s:acedup unknown\n",
      97             :                            SMBACL4_PARAM_TYPE_NAME));
      98           0 :                 return -1;
      99             :         }
     100        8988 :         params->acedup = (enum smbacl4_acedup_enum)enumval;
     101        8988 :         if (params->acedup == e_ignore) {
     102           0 :                 DBG_WARNING("nfs4:acedup ignore is deprecated.\n");
     103             :         }
     104        8988 :         if (params->acedup == e_reject) {
     105           0 :                 DBG_WARNING("nfs4:acedup ignore is deprecated.\n");
     106             :         }
     107             : 
     108        8988 :         params->map_full_control = lp_acl_map_full_control(SNUM(conn));
     109             : 
     110        8988 :         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        8988 :         return 0;
     117             : }
     118             : 
     119             : /************************************************
     120             :  Split the ACE flag mapping between nfs4 and Windows
     121             :  into two separate functions rather than trying to do
     122             :  it inline. Allows us to carefully control what flags
     123             :  are mapped to what in one place.
     124             : ************************************************/
     125             : 
     126       11522 : static uint32_t map_nfs4_ace_flags_to_windows_ace_flags(
     127             :         uint32_t nfs4_ace_flags)
     128             : {
     129       11583 :         uint32_t win_ace_flags = 0;
     130             : 
     131             :         /* The nfs4 flags <= 0xf map perfectly. */
     132       11583 :         win_ace_flags = nfs4_ace_flags & (SEC_ACE_FLAG_OBJECT_INHERIT|
     133             :                                       SEC_ACE_FLAG_CONTAINER_INHERIT|
     134             :                                       SEC_ACE_FLAG_NO_PROPAGATE_INHERIT|
     135             :                                       SEC_ACE_FLAG_INHERIT_ONLY);
     136             : 
     137             :         /* flags greater than 0xf have diverged :-(. */
     138             :         /* See the nfs4 ace flag definitions here:
     139             :            http://www.ietf.org/rfc/rfc3530.txt.
     140             :            And the Windows ace flag definitions here:
     141             :            librpc/idl/security.idl. */
     142       11583 :         if (nfs4_ace_flags & SMB_ACE4_INHERITED_ACE) {
     143        2112 :                 win_ace_flags |= SEC_ACE_FLAG_INHERITED_ACE;
     144             :         }
     145             : 
     146       11522 :         return win_ace_flags;
     147             : }
     148             : 
     149        5586 : static uint32_t map_windows_ace_flags_to_nfs4_ace_flags(uint32_t win_ace_flags)
     150             : {
     151        5676 :         uint32_t nfs4_ace_flags = 0;
     152             : 
     153             :         /* The windows flags <= 0xf map perfectly. */
     154        5676 :         nfs4_ace_flags = win_ace_flags & (SMB_ACE4_FILE_INHERIT_ACE|
     155             :                                       SMB_ACE4_DIRECTORY_INHERIT_ACE|
     156             :                                       SMB_ACE4_NO_PROPAGATE_INHERIT_ACE|
     157             :                                       SMB_ACE4_INHERIT_ONLY_ACE);
     158             : 
     159             :         /* flags greater than 0xf have diverged :-(. */
     160             :         /* See the nfs4 ace flag definitions here:
     161             :            http://www.ietf.org/rfc/rfc3530.txt.
     162             :            And the Windows ace flag definitions here:
     163             :            librpc/idl/security.idl. */
     164        5676 :         if (win_ace_flags & SEC_ACE_FLAG_INHERITED_ACE) {
     165        1692 :                 nfs4_ace_flags |= SMB_ACE4_INHERITED_ACE;
     166             :         }
     167             : 
     168        5586 :         return nfs4_ace_flags;
     169             : }
     170             : 
     171       13895 : struct SMB4ACL_T *smb_create_smb4acl(TALLOC_CTX *mem_ctx)
     172             : {
     173             :         struct SMB4ACL_T *theacl;
     174             : 
     175       13895 :         theacl = talloc_zero(mem_ctx, struct SMB4ACL_T);
     176       13895 :         if (theacl==NULL)
     177             :         {
     178           0 :                 DEBUG(0, ("TALLOC_SIZE failed\n"));
     179           0 :                 errno = ENOMEM;
     180           0 :                 return NULL;
     181             :         }
     182       13895 :         theacl->controlflags = SEC_DESC_SELF_RELATIVE;
     183             :         /* theacl->first, last = NULL not needed */
     184       13895 :         return theacl;
     185             : }
     186             : 
     187       17197 : struct SMB4ACE_T *smb_add_ace4(struct SMB4ACL_T *acl, SMB_ACE4PROP_T *prop)
     188             : {
     189             :         struct SMB4ACE_T *ace;
     190             : 
     191       17197 :         ace = talloc_zero(acl, struct SMB4ACE_T);
     192       17197 :         if (ace==NULL)
     193             :         {
     194           0 :                 DBG_ERR("talloc_zero failed\n");
     195           0 :                 errno = ENOMEM;
     196           0 :                 return NULL;
     197             :         }
     198       17197 :         ace->prop = *prop;
     199             : 
     200       17197 :         if (acl->first==NULL)
     201             :         {
     202       13831 :                 acl->first = ace;
     203       13831 :                 acl->last = ace;
     204             :         } else {
     205        3366 :                 acl->last->next = ace;
     206        3366 :                 acl->last = ace;
     207             :         }
     208       17197 :         acl->naces++;
     209             : 
     210       17197 :         return ace;
     211             : }
     212             : 
     213        5606 : SMB_ACE4PROP_T *smb_get_ace4(struct SMB4ACE_T *ace)
     214             : {
     215        5606 :         if (ace == NULL) {
     216           0 :                 return NULL;
     217             :         }
     218             : 
     219        5606 :         return &ace->prop;
     220             : }
     221             : 
     222        5602 : struct SMB4ACE_T *smb_next_ace4(struct SMB4ACE_T *ace)
     223             : {
     224        5602 :         if (ace == NULL) {
     225           0 :                 return NULL;
     226             :         }
     227             : 
     228        5602 :         return ace->next;
     229             : }
     230             : 
     231        5060 : struct SMB4ACE_T *smb_first_ace4(struct SMB4ACL_T *acl)
     232             : {
     233        5060 :         if (acl == NULL) {
     234           0 :                 return NULL;
     235             :         }
     236             : 
     237        5060 :         return acl->first;
     238             : }
     239             : 
     240        5058 : uint32_t smb_get_naces(struct SMB4ACL_T *acl)
     241             : {
     242        5058 :         if (acl == NULL) {
     243           0 :                 return 0;
     244             :         }
     245             : 
     246        5058 :         return acl->naces;
     247             : }
     248             : 
     249       10982 : uint16_t smbacl4_get_controlflags(struct SMB4ACL_T *acl)
     250             : {
     251       10982 :         if (acl == NULL) {
     252           0 :                 return 0;
     253             :         }
     254             : 
     255       10982 :         return acl->controlflags;
     256             : }
     257             : 
     258        8760 : bool smbacl4_set_controlflags(struct SMB4ACL_T *acl, uint16_t controlflags)
     259             : {
     260        8760 :         if (acl == NULL) {
     261           0 :                 return false;
     262             :         }
     263             : 
     264        8760 :         acl->controlflags = controlflags;
     265        8760 :         return true;
     266             : }
     267             : 
     268        3897 : bool nfs_ace_is_inherit(SMB_ACE4PROP_T *ace)
     269             : {
     270        3897 :         return ace->aceFlags & (SMB_ACE4_INHERIT_ONLY_ACE|
     271             :                                 SMB_ACE4_FILE_INHERIT_ACE|
     272             :                                 SMB_ACE4_DIRECTORY_INHERIT_ACE);
     273             : }
     274             : 
     275           0 : static int smbacl4_GetFileOwner(struct connection_struct *conn,
     276             :                                 const struct smb_filename *smb_fname,
     277             :                                 SMB_STRUCT_STAT *psbuf)
     278             : {
     279           0 :         ZERO_STRUCTP(psbuf);
     280             : 
     281             :         /* Get the stat struct for the owner info. */
     282           0 :         if (vfs_stat_smb_basename(conn, smb_fname, psbuf) != 0)
     283             :         {
     284           0 :                 DEBUG(8, ("vfs_stat_smb_basename failed with error %s\n",
     285             :                         strerror(errno)));
     286           0 :                 return -1;
     287             :         }
     288             : 
     289           0 :         return 0;
     290             : }
     291             : 
     292       11583 : static void check_for_duplicate_sec_ace(struct security_ace *nt_ace_list,
     293             :                                         int *good_aces)
     294             : {
     295       11583 :         struct security_ace *last = NULL;
     296             :         int i;
     297             : 
     298       11583 :         if (*good_aces < 2) {
     299        8730 :                 return;
     300             :         }
     301             : 
     302        2804 :         last = &nt_ace_list[(*good_aces) - 1];
     303             : 
     304        5609 :         for (i = 0; i < (*good_aces) - 1; i++) {
     305        2805 :                 struct security_ace *cur = &nt_ace_list[i];
     306             : 
     307        5609 :                 if (cur->type == last->type &&
     308        2947 :                     cur->flags == last->flags &&
     309         145 :                     cur->access_mask == last->access_mask &&
     310           2 :                     dom_sid_equal(&cur->trustee, &last->trustee))
     311             :                 {
     312             :                         struct dom_sid_buf sid_buf;
     313             : 
     314           2 :                         DBG_INFO("Removing duplicate entry for SID %s.\n",
     315             :                                  dom_sid_str_buf(&last->trustee, &sid_buf));
     316           2 :                         (*good_aces)--;
     317             :                 }
     318             :         }
     319             : }
     320             : 
     321        8834 : static bool smbacl4_nfs42win(TALLOC_CTX *mem_ctx,
     322             :         const struct smbacl4_vfs_params *params,
     323             :         struct SMB4ACL_T *acl, /* in */
     324             :         struct dom_sid *psid_owner, /* in */
     325             :         struct dom_sid *psid_group, /* in */
     326             :         bool is_directory, /* in */
     327             :         struct security_ace **ppnt_ace_list, /* out */
     328             :         int *pgood_aces /* out */
     329             : )
     330             : {
     331             :         struct SMB4ACE_T *aceint;
     332        8834 :         struct security_ace *nt_ace_list = NULL;
     333        8834 :         int good_aces = 0;
     334             : 
     335        8834 :         DEBUG(10, ("%s entered\n", __func__));
     336             : 
     337        8834 :         nt_ace_list = talloc_zero_array(mem_ctx, struct security_ace,
     338             :                                         2 * acl->naces);
     339        8834 :         if (nt_ace_list==NULL)
     340             :         {
     341           0 :                 DEBUG(10, ("talloc error with %d aces", acl->naces));
     342           0 :                 errno = ENOMEM;
     343           0 :                 return false;
     344             :         }
     345             : 
     346       20424 :         for (aceint = acl->first; aceint != NULL; aceint = aceint->next) {
     347             :                 uint32_t mask;
     348             :                 struct dom_sid sid;
     349             :                 struct dom_sid_buf buf;
     350       11590 :                 SMB_ACE4PROP_T  *ace = &aceint->prop;
     351             :                 uint32_t win_ace_flags;
     352             : 
     353       11590 :                 DEBUG(10, ("type: %d, iflags: %x, flags: %x, "
     354             :                            "mask: %x, who: %d\n",
     355             :                            ace->aceType, ace->flags,
     356             :                            ace->aceFlags, ace->aceMask, ace->who.id));
     357             : 
     358       11590 :                 if (ace->flags & SMB_ACE4_ID_SPECIAL) {
     359       10050 :                         switch (ace->who.special_id) {
     360        6845 :                         case SMB_ACE4_WHO_OWNER:
     361        6845 :                                 sid_copy(&sid, psid_owner);
     362        6845 :                                 break;
     363           5 :                         case SMB_ACE4_WHO_GROUP:
     364           5 :                                 sid_copy(&sid, psid_group);
     365           5 :                                 break;
     366        3193 :                         case SMB_ACE4_WHO_EVERYONE:
     367        3193 :                                 sid_copy(&sid, &global_sid_World);
     368        3193 :                                 break;
     369           7 :                         default:
     370           7 :                                 DEBUG(8, ("invalid special who id %d "
     371             :                                         "ignored\n", ace->who.special_id));
     372           7 :                                 continue;
     373             :                         }
     374             :                 } else {
     375        1540 :                         if (ace->aceFlags & SMB_ACE4_IDENTIFIER_GROUP) {
     376         391 :                                 gid_to_sid(&sid, ace->who.gid);
     377             :                         } else {
     378        1149 :                                 uid_to_sid(&sid, ace->who.uid);
     379             :                         }
     380             :                 }
     381       11583 :                 DEBUG(10, ("mapped %d to %s\n", ace->who.id,
     382             :                            dom_sid_str_buf(&sid, &buf)));
     383             : 
     384       11583 :                 if (!is_directory && params->map_full_control) {
     385             :                         /*
     386             :                          * Do we have all access except DELETE_CHILD
     387             :                          * (not caring about the delete bit).
     388             :                          */
     389        5283 :                         uint32_t test_mask = ((ace->aceMask|SMB_ACE4_DELETE|SMB_ACE4_DELETE_CHILD) &
     390             :                                                 SMB_ACE4_ALL_MASKS);
     391        5283 :                         if (test_mask == SMB_ACE4_ALL_MASKS) {
     392         183 :                                 ace->aceMask |= SMB_ACE4_DELETE_CHILD;
     393             :                         }
     394             :                 }
     395             : 
     396       11644 :                 win_ace_flags = map_nfs4_ace_flags_to_windows_ace_flags(
     397             :                         ace->aceFlags);
     398       16867 :                 if (!is_directory &&
     399        5284 :                     (win_ace_flags & (SEC_ACE_FLAG_OBJECT_INHERIT|
     400             :                                       SEC_ACE_FLAG_CONTAINER_INHERIT))) {
     401             :                         /*
     402             :                          * GPFS sets inherits dir_inhert and file_inherit flags
     403             :                          * to files, too, which confuses windows, and seems to
     404             :                          * be wrong anyways. ==> Map these bits away for files.
     405             :                          */
     406           2 :                         DEBUG(10, ("removing inherit flags from nfs4 ace\n"));
     407           2 :                         win_ace_flags &= ~(SEC_ACE_FLAG_OBJECT_INHERIT|
     408             :                                            SEC_ACE_FLAG_CONTAINER_INHERIT);
     409             :                 }
     410       11583 :                 DEBUG(10, ("Windows mapped ace flags: 0x%x => 0x%x\n",
     411             :                       ace->aceFlags, win_ace_flags));
     412             : 
     413       11583 :                 mask = ace->aceMask;
     414             : 
     415             :                 /* Mapping of owner@ and group@ to creator owner and
     416             :                    creator group. Keep old behavior in mode special. */
     417       21470 :                 if (params->mode != e_special &&
     418       18512 :                     ace->flags & SMB_ACE4_ID_SPECIAL &&
     419       11361 :                     (ace->who.special_id == SMB_ACE4_WHO_OWNER ||
     420        2736 :                      ace->who.special_id == SMB_ACE4_WHO_GROUP)) {
     421        5888 :                         DEBUG(10, ("Map special entry\n"));
     422        5888 :                         if (!(win_ace_flags & SEC_ACE_FLAG_INHERIT_ONLY)) {
     423             :                                 uint32_t win_ace_flags_current;
     424        4664 :                                 DEBUG(10, ("Map current sid\n"));
     425        4664 :                                 win_ace_flags_current = win_ace_flags &
     426             :                                         ~(SEC_ACE_FLAG_OBJECT_INHERIT |
     427             :                                           SEC_ACE_FLAG_CONTAINER_INHERIT);
     428        9328 :                                 init_sec_ace(&nt_ace_list[good_aces++], &sid,
     429        4664 :                                              ace->aceType, mask,
     430             :                                              win_ace_flags_current);
     431             :                         }
     432       11772 :                         if (ace->who.special_id == SMB_ACE4_WHO_OWNER &&
     433        5884 :                             win_ace_flags & (SEC_ACE_FLAG_OBJECT_INHERIT |
     434             :                                              SEC_ACE_FLAG_CONTAINER_INHERIT)) {
     435             :                                 uint32_t win_ace_flags_creator;
     436        1227 :                                 DEBUG(10, ("Map creator owner\n"));
     437        1227 :                                 win_ace_flags_creator = win_ace_flags |
     438             :                                         SMB_ACE4_INHERIT_ONLY_ACE;
     439        2454 :                                 init_sec_ace(&nt_ace_list[good_aces++],
     440             :                                              &global_sid_Creator_Owner,
     441        1227 :                                              ace->aceType, mask,
     442             :                                              win_ace_flags_creator);
     443             :                         }
     444       11772 :                         if (ace->who.special_id == SMB_ACE4_WHO_GROUP &&
     445           4 :                             win_ace_flags & (SEC_ACE_FLAG_OBJECT_INHERIT |
     446             :                                              SEC_ACE_FLAG_CONTAINER_INHERIT)) {
     447             :                                 uint32_t win_ace_flags_creator;
     448           3 :                                 DEBUG(10, ("Map creator owner group\n"));
     449           3 :                                 win_ace_flags_creator = win_ace_flags |
     450             :                                         SMB_ACE4_INHERIT_ONLY_ACE;
     451           6 :                                 init_sec_ace(&nt_ace_list[good_aces++],
     452             :                                              &global_sid_Creator_Group,
     453           3 :                                              ace->aceType, mask,
     454             :                                              win_ace_flags_creator);
     455             :                         }
     456             :                 } else {
     457        5695 :                         DEBUG(10, ("Map normal sid\n"));
     458       11390 :                         init_sec_ace(&nt_ace_list[good_aces++], &sid,
     459        5695 :                                      ace->aceType, mask,
     460             :                                      win_ace_flags);
     461             :                 }
     462             : 
     463       11583 :                 check_for_duplicate_sec_ace(nt_ace_list, &good_aces);
     464             :         }
     465             : 
     466        8834 :         nt_ace_list = talloc_realloc(mem_ctx, nt_ace_list, struct security_ace,
     467             :                                      good_aces);
     468             : 
     469             :         /* returns a NULL ace list when good_aces is zero. */
     470        8834 :         if (good_aces && nt_ace_list == NULL) {
     471           0 :                 DEBUG(10, ("realloc error with %d aces", good_aces));
     472           0 :                 errno = ENOMEM;
     473           0 :                 return false;
     474             :         }
     475             : 
     476        8834 :         *ppnt_ace_list = nt_ace_list;
     477        8834 :         *pgood_aces = good_aces;
     478             : 
     479        8834 :         return true;
     480             : }
     481             : 
     482        8778 : static NTSTATUS smb_get_nt_acl_nfs4_common(const SMB_STRUCT_STAT *sbuf,
     483             :                                            const struct smbacl4_vfs_params *params,
     484             :                                            uint32_t security_info,
     485             :                                            TALLOC_CTX *mem_ctx,
     486             :                                            struct security_descriptor **ppdesc,
     487             :                                            struct SMB4ACL_T *theacl)
     488             : {
     489        8778 :         int good_aces = 0;
     490             :         struct dom_sid sid_owner, sid_group;
     491        8778 :         size_t sd_size = 0;
     492        8778 :         struct security_ace *nt_ace_list = NULL;
     493        8778 :         struct security_acl *psa = NULL;
     494        8778 :         TALLOC_CTX *frame = talloc_stackframe();
     495             :         bool ok;
     496             : 
     497        8778 :         if (theacl==NULL) {
     498           0 :                 TALLOC_FREE(frame);
     499           0 :                 return NT_STATUS_ACCESS_DENIED; /* special because we
     500             :                                                  * need to think through
     501             :                                                  * the null case.*/
     502             :         }
     503             : 
     504        8778 :         uid_to_sid(&sid_owner, sbuf->st_ex_uid);
     505        8778 :         gid_to_sid(&sid_group, sbuf->st_ex_gid);
     506             : 
     507        8778 :         ok = smbacl4_nfs42win(frame, params, theacl, &sid_owner, &sid_group,
     508        8778 :                               S_ISDIR(sbuf->st_ex_mode),
     509             :                               &nt_ace_list, &good_aces);
     510        8778 :         if (!ok) {
     511           0 :                 DEBUG(8,("smbacl4_nfs42win failed\n"));
     512           0 :                 TALLOC_FREE(frame);
     513           0 :                 return map_nt_error_from_unix(errno);
     514             :         }
     515             : 
     516        8778 :         psa = make_sec_acl(frame, NT4_ACL_REVISION, good_aces, nt_ace_list);
     517        8778 :         if (psa == NULL) {
     518           0 :                 DEBUG(2,("make_sec_acl failed\n"));
     519           0 :                 TALLOC_FREE(frame);
     520           0 :                 return NT_STATUS_NO_MEMORY;
     521             :         }
     522             : 
     523        8778 :         DEBUG(10,("after make sec_acl\n"));
     524       26334 :         *ppdesc = make_sec_desc(
     525        8778 :                 mem_ctx, SD_REVISION, smbacl4_get_controlflags(theacl),
     526        8778 :                 (security_info & SECINFO_OWNER) ? &sid_owner : NULL,
     527        8778 :                 (security_info & SECINFO_GROUP) ? &sid_group : NULL,
     528             :                 NULL, psa, &sd_size);
     529        8778 :         if (*ppdesc==NULL) {
     530           0 :                 DEBUG(2,("make_sec_desc failed\n"));
     531           0 :                 TALLOC_FREE(frame);
     532           0 :                 return NT_STATUS_NO_MEMORY;
     533             :         }
     534             : 
     535        8778 :         DEBUG(10, ("smb_get_nt_acl_nfs4_common successfully exited with "
     536             :                    "sd_size %d\n",
     537             :                    (int)ndr_size_security_descriptor(*ppdesc, 0)));
     538             : 
     539        8778 :         TALLOC_FREE(frame);
     540        8778 :         return NT_STATUS_OK;
     541             : }
     542             : 
     543        8778 : NTSTATUS smb_fget_nt_acl_nfs4(files_struct *fsp,
     544             :                               const struct smbacl4_vfs_params *pparams,
     545             :                               uint32_t security_info,
     546             :                               TALLOC_CTX *mem_ctx,
     547             :                               struct security_descriptor **ppdesc,
     548             :                               struct SMB4ACL_T *theacl)
     549             : {
     550             :         struct smbacl4_vfs_params params;
     551             : 
     552        8778 :         DEBUG(10, ("smb_fget_nt_acl_nfs4 invoked for %s\n", fsp_str_dbg(fsp)));
     553             : 
     554        8778 :         if (!VALID_STAT(fsp->fsp_name->st)) {
     555             :                 NTSTATUS status;
     556             : 
     557           0 :                 status = vfs_stat_fsp(fsp);
     558           0 :                 if (!NT_STATUS_IS_OK(status)) {
     559           0 :                         return status;
     560             :                 }
     561             :         }
     562             : 
     563        8778 :         if (pparams == NULL) {
     564             :                 /* Special behaviours */
     565        8778 :                 if (smbacl4_get_vfs_params(fsp->conn, &params)) {
     566           0 :                         return NT_STATUS_NO_MEMORY;
     567             :                 }
     568        8778 :                 pparams = &params;
     569             :         }
     570             : 
     571        8778 :         return smb_get_nt_acl_nfs4_common(&fsp->fsp_name->st, pparams,
     572             :                                           security_info,
     573             :                                           mem_ctx, ppdesc, theacl);
     574             : }
     575             : 
     576           0 : NTSTATUS smb_get_nt_acl_nfs4(struct connection_struct *conn,
     577             :                              const struct smb_filename *smb_fname,
     578             :                              const struct smbacl4_vfs_params *pparams,
     579             :                              uint32_t security_info,
     580             :                              TALLOC_CTX *mem_ctx,
     581             :                              struct security_descriptor **ppdesc,
     582             :                              struct SMB4ACL_T *theacl)
     583             : {
     584             :         SMB_STRUCT_STAT sbuf;
     585             :         struct smbacl4_vfs_params params;
     586           0 :         const SMB_STRUCT_STAT *psbuf = NULL;
     587             : 
     588           0 :         DEBUG(10, ("smb_get_nt_acl_nfs4 invoked for %s\n",
     589             :                 smb_fname->base_name));
     590             : 
     591           0 :         if (VALID_STAT(smb_fname->st)) {
     592           0 :                 psbuf = &smb_fname->st;
     593             :         }
     594             : 
     595           0 :         if (psbuf == NULL) {
     596           0 :                 if (smbacl4_GetFileOwner(conn, smb_fname, &sbuf)) {
     597           0 :                         return map_nt_error_from_unix(errno);
     598             :                 }
     599           0 :                 psbuf = &sbuf;
     600             :         }
     601             : 
     602           0 :         if (pparams == NULL) {
     603             :                 /* Special behaviours */
     604           0 :                 if (smbacl4_get_vfs_params(conn, &params)) {
     605           0 :                         return NT_STATUS_NO_MEMORY;
     606             :                 }
     607           0 :                 pparams = &params;
     608             :         }
     609             : 
     610           0 :         return smb_get_nt_acl_nfs4_common(psbuf, pparams, security_info,
     611             :                                           mem_ctx, ppdesc, theacl);
     612             : }
     613             : 
     614        4998 : static void smbacl4_dump_nfs4acl(int level, struct SMB4ACL_T *acl)
     615             : {
     616             :         struct SMB4ACE_T *aceint;
     617             : 
     618        4998 :         DEBUG(level, ("NFS4ACL: size=%d\n", acl->naces));
     619             : 
     620       10524 :         for (aceint = acl->first; aceint != NULL; aceint = aceint->next) {
     621        5526 :                 SMB_ACE4PROP_T *ace = &aceint->prop;
     622             : 
     623        5526 :                 DEBUG(level, ("\tACE: type=%d, flags=0x%x, fflags=0x%x, "
     624             :                               "mask=0x%x, id=%d\n",
     625             :                               ace->aceType,
     626             :                               ace->aceFlags, ace->flags,
     627             :                               ace->aceMask,
     628             :                               ace->who.id));
     629             :         }
     630        4998 : }
     631             : 
     632             : /*
     633             :  * Find 2 NFS4 who-special ACE property (non-copy!!!)
     634             :  * match nonzero if "special" and who is equal
     635             :  * return ace if found matching; otherwise NULL
     636             :  */
     637        5599 : static SMB_ACE4PROP_T *smbacl4_find_equal_special(
     638             :         struct SMB4ACL_T *acl,
     639             :         SMB_ACE4PROP_T *aceNew)
     640             : {
     641             :         struct SMB4ACE_T *aceint;
     642             : 
     643        6150 :         for (aceint = acl->first; aceint != NULL; aceint = aceint->next) {
     644         556 :                 SMB_ACE4PROP_T *ace = &aceint->prop;
     645             : 
     646         556 :                 DEBUG(10,("ace type:0x%x flags:0x%x aceFlags:0x%x "
     647             :                           "new type:0x%x flags:0x%x aceFlags:0x%x\n",
     648             :                           ace->aceType, ace->flags, ace->aceFlags,
     649             :                           aceNew->aceType, aceNew->flags,aceNew->aceFlags));
     650             : 
     651         724 :                 if (ace->flags == aceNew->flags &&
     652         335 :                         ace->aceType==aceNew->aceType &&
     653         167 :                         ace->aceFlags==aceNew->aceFlags)
     654             :                 {
     655             :                         /* keep type safety; e.g. gid is an u.short */
     656          11 :                         if (ace->flags & SMB_ACE4_ID_SPECIAL)
     657             :                         {
     658          12 :                                 if (ace->who.special_id ==
     659           6 :                                     aceNew->who.special_id)
     660           0 :                                         return ace;
     661             :                         } else {
     662           5 :                                 if (ace->aceFlags & SMB_ACE4_IDENTIFIER_GROUP)
     663             :                                 {
     664           0 :                                         if (ace->who.gid==aceNew->who.gid)
     665           0 :                                                 return ace;
     666             :                                 } else {
     667           5 :                                         if (ace->who.uid==aceNew->who.uid)
     668           0 :                                                 return ace;
     669             :                                 }
     670             :                         }
     671             :                 }
     672             :         }
     673             : 
     674        5526 :         return NULL;
     675             : }
     676             : 
     677        5599 : static int smbacl4_MergeIgnoreReject(enum smbacl4_acedup_enum acedup,
     678             :                                      struct SMB4ACL_T *theacl,
     679             :                                      SMB_ACE4PROP_T *ace,
     680             :                                      bool *paddNewACE)
     681             : {
     682        5599 :         int     result = 0;
     683        5599 :         SMB_ACE4PROP_T *ace4found = smbacl4_find_equal_special(theacl, ace);
     684        5599 :         if (ace4found)
     685             :         {
     686           5 :                 switch(acedup)
     687             :                 {
     688           1 :                 case e_merge: /* "merge" flags */
     689           1 :                         *paddNewACE = false;
     690           1 :                         ace4found->aceFlags |= ace->aceFlags;
     691           1 :                         ace4found->aceMask |= ace->aceMask;
     692           1 :                         break;
     693           3 :                 case e_ignore: /* leave out this record */
     694           3 :                         *paddNewACE = false;
     695           3 :                         break;
     696           1 :                 case e_reject: /* do an error */
     697           1 :                         DBG_INFO("ACL rejected by duplicate nt ace.\n");
     698           1 :                         errno = EINVAL; /* SHOULD be set on any _real_ error */
     699           1 :                         result = -1;
     700           1 :                         break;
     701           0 :                 default:
     702           0 :                         break;
     703             :                 }
     704        5594 :         }
     705        5599 :         return result;
     706             : }
     707             : 
     708        5612 : static int nfs4_acl_add_ace(enum smbacl4_acedup_enum acedup,
     709             :                             struct SMB4ACL_T *nfs4_acl,
     710             :                             SMB_ACE4PROP_T *nfs4_ace)
     711             : {
     712        5612 :         bool add_ace = true;
     713             : 
     714        5612 :         if (acedup != e_dontcare) {
     715             :                 int ret;
     716             : 
     717        5599 :                 ret = smbacl4_MergeIgnoreReject(acedup, nfs4_acl,
     718             :                                                 nfs4_ace, &add_ace);
     719        5599 :                 if (ret == -1) {
     720           0 :                         return -1;
     721             :                 }
     722             :         }
     723             : 
     724        5611 :         if (add_ace) {
     725        5607 :                 smb_add_ace4(nfs4_acl, nfs4_ace);
     726             :         }
     727             : 
     728        5526 :         return 0;
     729             : }
     730             : 
     731        5676 : static int nfs4_acl_add_sec_ace(bool is_directory,
     732             :                                 const struct smbacl4_vfs_params *params,
     733             :                                 uid_t ownerUID,
     734             :                                 gid_t ownerGID,
     735             :                                 const struct security_ace *ace_nt,
     736             :                                 struct SMB4ACL_T *nfs4_acl)
     737             : {
     738             :         struct dom_sid_buf buf;
     739        5676 :         SMB_ACE4PROP_T nfs4_ace = { 0 };
     740        5676 :         SMB_ACE4PROP_T nfs4_ace_2 = { 0 };
     741        5676 :         bool add_ace2 = false;
     742             :         int ret;
     743             : 
     744        5676 :         DEBUG(10, ("got ace for %s\n",
     745             :                    dom_sid_str_buf(&ace_nt->trustee, &buf)));
     746             : 
     747             :         /* only ACCESS|DENY supported right now */
     748        5676 :         nfs4_ace.aceType = ace_nt->type;
     749             : 
     750        5676 :         nfs4_ace.aceFlags =
     751        5766 :                 map_windows_ace_flags_to_nfs4_ace_flags(ace_nt->flags);
     752             : 
     753             :         /* remove inheritance flags on files */
     754        5676 :         if (!is_directory) {
     755        4287 :                 DEBUG(10, ("Removing inheritance flags from a file\n"));
     756        4287 :                 nfs4_ace.aceFlags &= ~(SMB_ACE4_FILE_INHERIT_ACE|
     757             :                                        SMB_ACE4_DIRECTORY_INHERIT_ACE|
     758             :                                        SMB_ACE4_NO_PROPAGATE_INHERIT_ACE|
     759             :                                        SMB_ACE4_INHERIT_ONLY_ACE);
     760             :         }
     761             : 
     762        5676 :         nfs4_ace.aceMask = ace_nt->access_mask & (SEC_STD_ALL | SEC_FILE_ALL);
     763             : 
     764        5676 :         se_map_generic(&nfs4_ace.aceMask, &file_generic_mapping);
     765             : 
     766        5676 :         if (dom_sid_equal(&ace_nt->trustee, &global_sid_World)) {
     767         659 :                 nfs4_ace.who.special_id = SMB_ACE4_WHO_EVERYONE;
     768         659 :                 nfs4_ace.flags |= SMB_ACE4_ID_SPECIAL;
     769        9324 :         } else if (params->mode!=e_special &&
     770        4307 :                    dom_sid_equal(&ace_nt->trustee,
     771             :                                  &global_sid_Creator_Owner)) {
     772         284 :                 DEBUG(10, ("Map creator owner\n"));
     773         284 :                 nfs4_ace.who.special_id = SMB_ACE4_WHO_OWNER;
     774         284 :                 nfs4_ace.flags |= SMB_ACE4_ID_SPECIAL;
     775             :                 /* A non inheriting creator owner entry has no effect. */
     776         284 :                 nfs4_ace.aceFlags |= SMB_ACE4_INHERIT_ONLY_ACE;
     777         500 :                 if (!(nfs4_ace.aceFlags & SMB_ACE4_DIRECTORY_INHERIT_ACE)
     778         140 :                     && !(nfs4_ace.aceFlags & SMB_ACE4_FILE_INHERIT_ACE)) {
     779          60 :                         return 0;
     780             :                 }
     781        8756 :         } else if (params->mode!=e_special &&
     782        4023 :                    dom_sid_equal(&ace_nt->trustee,
     783             :                                  &global_sid_Creator_Group)) {
     784           8 :                 DEBUG(10, ("Map creator owner group\n"));
     785           8 :                 nfs4_ace.who.special_id = SMB_ACE4_WHO_GROUP;
     786           8 :                 nfs4_ace.flags |= SMB_ACE4_ID_SPECIAL;
     787             :                 /* A non inheriting creator group entry has no effect. */
     788           8 :                 nfs4_ace.aceFlags |= SMB_ACE4_INHERIT_ONLY_ACE;
     789           8 :                 if (!(nfs4_ace.aceFlags & SMB_ACE4_DIRECTORY_INHERIT_ACE)
     790           8 :                     && !(nfs4_ace.aceFlags & SMB_ACE4_FILE_INHERIT_ACE)) {
     791           0 :                         return 0;
     792             :                 }
     793             :         } else {
     794             :                 struct unixid unixid;
     795             :                 bool ok;
     796             : 
     797        4725 :                 ok = sids_to_unixids(&ace_nt->trustee, 1, &unixid);
     798        4725 :                 if (!ok) {
     799           0 :                         DBG_WARNING("Could not convert %s to uid or gid.\n",
     800             :                                     dom_sid_str_buf(&ace_nt->trustee, &buf));
     801           1 :                         return 0;
     802             :                 }
     803             : 
     804        4725 :                 if (dom_sid_compare_domain(&ace_nt->trustee,
     805             :                                            &global_sid_Unix_NFS) == 0) {
     806           0 :                         return 0;
     807             :                 }
     808             : 
     809        4724 :                 switch (unixid.type) {
     810           4 :                 case ID_TYPE_BOTH:
     811           4 :                         nfs4_ace.aceFlags |= SMB_ACE4_IDENTIFIER_GROUP;
     812           4 :                         nfs4_ace.who.gid = unixid.id;
     813             : 
     814           6 :                         if (ownerUID == unixid.id &&
     815           2 :                             !nfs_ace_is_inherit(&nfs4_ace))
     816             :                         {
     817             :                                 /*
     818             :                                  * IDMAP_TYPE_BOTH for owner. Add
     819             :                                  * additional user entry, which can be
     820             :                                  * mapped to special:owner to reflect
     821             :                                  * the permissions in the modebits.
     822             :                                  *
     823             :                                  * This only applies to non-inheriting
     824             :                                  * entries as only these are replaced
     825             :                                  * with SPECIAL_OWNER in nfs4:mode=simple.
     826             :                                  */
     827           1 :                                 nfs4_ace_2 = (SMB_ACE4PROP_T) {
     828           1 :                                         .who.uid = unixid.id,
     829           1 :                                         .aceFlags = (nfs4_ace.aceFlags &
     830             :                                                     ~SMB_ACE4_IDENTIFIER_GROUP),
     831           1 :                                         .aceMask = nfs4_ace.aceMask,
     832           1 :                                         .aceType = nfs4_ace.aceType,
     833             :                                 };
     834           1 :                                 add_ace2 = true;
     835             :                         }
     836           0 :                         break;
     837         123 :                 case ID_TYPE_GID:
     838         123 :                         nfs4_ace.aceFlags |= SMB_ACE4_IDENTIFIER_GROUP;
     839         123 :                         nfs4_ace.who.gid = unixid.id;
     840         123 :                         break;
     841        4597 :                 case ID_TYPE_UID:
     842        4597 :                         nfs4_ace.who.uid = unixid.id;
     843        4597 :                         break;
     844           0 :                 case ID_TYPE_NOT_SPECIFIED:
     845             :                 default:
     846           0 :                         DBG_WARNING("Could not convert %s to uid or gid.\n",
     847             :                                     dom_sid_str_buf(&ace_nt->trustee, &buf));
     848           0 :                         return 0;
     849             :                 }
     850             :         }
     851             : 
     852        5611 :         ret = nfs4_acl_add_ace(params->acedup, nfs4_acl, &nfs4_ace);
     853        5611 :         if (ret != 0) {
     854           0 :                 return -1;
     855             :         }
     856             : 
     857        5610 :         if (!add_ace2) {
     858        5526 :                 return 0;
     859             :         }
     860             : 
     861           1 :         return nfs4_acl_add_ace(params->acedup, nfs4_acl, &nfs4_ace_2);
     862             : }
     863             : 
     864         715 : static void smbacl4_substitute_special(struct SMB4ACL_T *acl,
     865             :                                        uid_t ownerUID,
     866             :                                        gid_t ownerGID)
     867             : {
     868             :         struct SMB4ACE_T *aceint;
     869             : 
     870        1519 :         for (aceint = acl->first; aceint != NULL; aceint = aceint->next) {
     871         804 :                 SMB_ACE4PROP_T *ace = &aceint->prop;
     872             : 
     873         804 :                 DEBUG(10,("ace type: %d, iflags: %x, flags: %x, "
     874             :                           "mask: %x, who: %d\n",
     875             :                           ace->aceType, ace->flags, ace->aceFlags,
     876             :                           ace->aceMask, ace->who.id));
     877             : 
     878        1514 :                 if (!(ace->flags & SMB_ACE4_ID_SPECIAL) &&
     879        1361 :                     !(ace->aceFlags & SMB_ACE4_IDENTIFIER_GROUP) &&
     880         651 :                     ace->who.uid == ownerUID) {
     881         650 :                         ace->flags |= SMB_ACE4_ID_SPECIAL;
     882         650 :                         ace->who.special_id = SMB_ACE4_WHO_OWNER;
     883         650 :                         DEBUG(10,("replaced with special owner ace\n"));
     884             :                 }
     885             : 
     886         864 :                 if (!(ace->flags & SMB_ACE4_ID_SPECIAL) &&
     887         119 :                     ace->aceFlags & SMB_ACE4_IDENTIFIER_GROUP &&
     888          59 :                     ace->who.uid == ownerGID) {
     889           2 :                         ace->flags |= SMB_ACE4_ID_SPECIAL;
     890           2 :                         ace->who.special_id = SMB_ACE4_WHO_GROUP;
     891           2 :                         DEBUG(10,("replaced with special group ace\n"));
     892             :                 }
     893             :         }
     894         715 : }
     895             : 
     896        4345 : static void smbacl4_substitute_simple(struct SMB4ACL_T *acl,
     897             :                                       uid_t ownerUID,
     898             :                                       gid_t ownerGID)
     899             : {
     900             :         struct SMB4ACE_T *aceint;
     901             : 
     902        9147 :         for (aceint = acl->first; aceint != NULL; aceint = aceint->next) {
     903        4802 :                 SMB_ACE4PROP_T *ace = &aceint->prop;
     904             : 
     905        4802 :                 DEBUG(10,("ace type: %d, iflags: %x, flags: %x, "
     906             :                           "mask: %x, who: %d\n",
     907             :                           ace->aceType, ace->flags, ace->aceFlags,
     908             :                           ace->aceMask, ace->who.id));
     909             : 
     910        8811 :                 if (!(ace->flags & SMB_ACE4_ID_SPECIAL) &&
     911        7950 :                     !(ace->aceFlags & SMB_ACE4_IDENTIFIER_GROUP) &&
     912        7832 :                     ace->who.uid == ownerUID &&
     913        3891 :                     !nfs_ace_is_inherit(ace)) {
     914        3661 :                         ace->flags |= SMB_ACE4_ID_SPECIAL;
     915        3661 :                         ace->who.special_id = SMB_ACE4_WHO_OWNER;
     916        3661 :                         DEBUG(10,("replaced with special owner ace\n"));
     917             :                 }
     918             : 
     919        5150 :                 if (!(ace->flags & SMB_ACE4_ID_SPECIAL) &&
     920         416 :                     ace->aceFlags & SMB_ACE4_IDENTIFIER_GROUP &&
     921          72 :                     ace->who.gid == ownerGID &&
     922           4 :                     !nfs_ace_is_inherit(ace)) {
     923           1 :                         ace->flags |= SMB_ACE4_ID_SPECIAL;
     924           1 :                         ace->who.special_id = SMB_ACE4_WHO_GROUP;
     925           1 :                         DEBUG(10,("replaced with special group ace\n"));
     926             :                 }
     927             :         }
     928        4345 : }
     929             : 
     930        5061 : static struct SMB4ACL_T *smbacl4_win2nfs4(
     931             :         TALLOC_CTX *mem_ctx,
     932             :         bool is_directory,
     933             :         const struct security_acl *dacl,
     934             :         const struct smbacl4_vfs_params *pparams,
     935             :         uid_t ownerUID,
     936             :         gid_t ownerGID
     937             : )
     938             : {
     939             :         struct SMB4ACL_T *theacl;
     940             :         uint32_t i;
     941             : 
     942        5061 :         DEBUG(10, ("smbacl4_win2nfs4 invoked\n"));
     943             : 
     944        5061 :         theacl = smb_create_smb4acl(mem_ctx);
     945        5061 :         if (theacl==NULL)
     946           0 :                 return NULL;
     947             : 
     948       10673 :         for(i=0; i<dacl->num_aces; i++) {
     949             :                 int ret;
     950             : 
     951        5676 :                 ret = nfs4_acl_add_sec_ace(is_directory, pparams,
     952             :                                            ownerUID, ownerGID,
     953        5676 :                                            dacl->aces + i, theacl);
     954        5676 :                 if (ret == -1) {
     955           0 :                         return NULL;
     956             :                 }
     957             :         }
     958             : 
     959        5060 :         if (pparams->mode==e_simple) {
     960        4345 :                 smbacl4_substitute_simple(theacl, ownerUID, ownerGID);
     961             :         }
     962             : 
     963        5060 :         if (pparams->mode==e_special) {
     964         715 :                 smbacl4_substitute_special(theacl, ownerUID, ownerGID);
     965             :         }
     966             : 
     967        4998 :         return theacl;
     968             : }
     969             : 
     970        5012 : NTSTATUS smb_set_nt_acl_nfs4(vfs_handle_struct *handle, files_struct *fsp,
     971             :         const struct smbacl4_vfs_params *pparams,
     972             :         uint32_t security_info_sent,
     973             :         const struct security_descriptor *psd,
     974             :         set_nfs4acl_native_fn_t set_nfs4_native)
     975             : {
     976             :         struct smbacl4_vfs_params params;
     977        5012 :         struct SMB4ACL_T *theacl = NULL;
     978             :         bool    result, is_directory;
     979             : 
     980        5012 :         bool set_acl_as_root = false;
     981        5012 :         uid_t newUID = (uid_t)-1;
     982        5012 :         gid_t newGID = (gid_t)-1;
     983             :         int saved_errno;
     984             :         NTSTATUS status;
     985        5012 :         TALLOC_CTX *frame = talloc_stackframe();
     986             : 
     987        5012 :         DEBUG(10, ("smb_set_nt_acl_nfs4 invoked for %s\n", fsp_str_dbg(fsp)));
     988             : 
     989        5012 :         if ((security_info_sent & (SECINFO_DACL |
     990             :                 SECINFO_GROUP | SECINFO_OWNER)) == 0)
     991             :         {
     992           0 :                 DEBUG(9, ("security_info_sent (0x%x) ignored\n",
     993             :                         security_info_sent));
     994           0 :                 TALLOC_FREE(frame);
     995           0 :                 return NT_STATUS_OK; /* won't show error - later to be
     996             :                                       * refined... */
     997             :         }
     998             : 
     999        5012 :         if (security_descriptor_with_ms_nfs(psd)) {
    1000           0 :                 TALLOC_FREE(frame);
    1001           0 :                 return NT_STATUS_OK;
    1002             :         }
    1003             : 
    1004        5012 :         if (pparams == NULL) {
    1005             :                 /* Special behaviours */
    1006           0 :                 if (smbacl4_get_vfs_params(fsp->conn, &params)) {
    1007           0 :                         TALLOC_FREE(frame);
    1008           0 :                         return NT_STATUS_NO_MEMORY;
    1009             :                 }
    1010           0 :                 pparams = &params;
    1011             :         }
    1012             : 
    1013        5012 :         status = vfs_stat_fsp(fsp);
    1014        5012 :         if (!NT_STATUS_IS_OK(status)) {
    1015           0 :                 TALLOC_FREE(frame);
    1016           0 :                 return status;
    1017             :         }
    1018             : 
    1019        5012 :         is_directory = S_ISDIR(fsp->fsp_name->st.st_ex_mode);
    1020             : 
    1021        5012 :         if (pparams->do_chown) {
    1022             :                 /* chown logic is a copy/paste from posix_acl.c:set_nt_acl */
    1023             : 
    1024        5012 :                 uid_t old_uid = fsp->fsp_name->st.st_ex_uid;
    1025        5012 :                 uid_t old_gid = fsp->fsp_name->st.st_ex_uid;
    1026        5012 :                 status = unpack_nt_owners(fsp->conn, &newUID, &newGID,
    1027             :                                           security_info_sent, psd);
    1028        5012 :                 if (!NT_STATUS_IS_OK(status)) {
    1029           0 :                         DEBUG(8, ("unpack_nt_owners failed"));
    1030           0 :                         TALLOC_FREE(frame);
    1031           0 :                         return status;
    1032             :                 }
    1033       10024 :                 if (((newUID != (uid_t)-1) && (old_uid != newUID)) ||
    1034        5628 :                     ((newGID != (gid_t)-1) && (old_gid != newGID)))
    1035             :                 {
    1036         532 :                         status = try_chown(fsp, newUID, newGID);
    1037         532 :                         if (!NT_STATUS_IS_OK(status)) {
    1038           0 :                                 DEBUG(3,("chown %s, %u, %u failed. Error = "
    1039             :                                          "%s.\n", fsp_str_dbg(fsp),
    1040             :                                          (unsigned int)newUID,
    1041             :                                          (unsigned int)newGID,
    1042             :                                          nt_errstr(status)));
    1043           0 :                                 TALLOC_FREE(frame);
    1044           0 :                                 return status;
    1045             :                         }
    1046             : 
    1047         532 :                         DEBUG(10,("chown %s, %u, %u succeeded.\n",
    1048             :                                   fsp_str_dbg(fsp), (unsigned int)newUID,
    1049             :                                   (unsigned int)newGID));
    1050             : 
    1051             :                         /*
    1052             :                          * Owner change, need to update stat info.
    1053             :                          */
    1054         532 :                         status = vfs_stat_fsp(fsp);
    1055         532 :                         if (!NT_STATUS_IS_OK(status)) {
    1056           0 :                                 TALLOC_FREE(frame);
    1057           0 :                                 return status;
    1058             :                         }
    1059             : 
    1060             :                         /* If we successfully chowned, we know we must
    1061             :                          * be able to set the acl, so do it as root.
    1062             :                          */
    1063         532 :                         set_acl_as_root = true;
    1064             :                 }
    1065             :         }
    1066             : 
    1067        5012 :         if (!(security_info_sent & SECINFO_DACL) || psd->dacl ==NULL) {
    1068          14 :                 DEBUG(10, ("no dacl found; security_info_sent = 0x%x\n",
    1069             :                            security_info_sent));
    1070          14 :                 TALLOC_FREE(frame);
    1071          14 :                 return NT_STATUS_OK;
    1072             :         }
    1073             : 
    1074        9996 :         theacl = smbacl4_win2nfs4(frame, is_directory, psd->dacl, pparams,
    1075        4998 :                                   fsp->fsp_name->st.st_ex_uid,
    1076        4998 :                                   fsp->fsp_name->st.st_ex_gid);
    1077        4998 :         if (!theacl) {
    1078           0 :                 TALLOC_FREE(frame);
    1079           0 :                 return map_nt_error_from_unix(errno);
    1080             :         }
    1081             : 
    1082        4998 :         smbacl4_set_controlflags(theacl, psd->type);
    1083        4998 :         smbacl4_dump_nfs4acl(10, theacl);
    1084             : 
    1085        4998 :         if (set_acl_as_root) {
    1086         532 :                 become_root();
    1087             :         }
    1088        4998 :         result = set_nfs4_native(handle, fsp, theacl);
    1089        4998 :         saved_errno = errno;
    1090        4998 :         if (set_acl_as_root) {
    1091         532 :                 unbecome_root();
    1092             :         }
    1093             : 
    1094        4998 :         TALLOC_FREE(frame);
    1095             : 
    1096        4998 :         if (result!=true) {
    1097           0 :                 errno = saved_errno;
    1098           0 :                 DEBUG(10, ("set_nfs4_native failed with %s\n",
    1099             :                            strerror(errno)));
    1100           0 :                 return map_nt_error_from_unix(errno);
    1101             :         }
    1102             : 
    1103        4998 :         DEBUG(10, ("smb_set_nt_acl_nfs4 succeeded\n"));
    1104        4998 :         return NT_STATUS_OK;
    1105             : }

Generated by: LCOV version 1.13