4 * Copyright (C) Jim McDonough, 2006
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
21 #include "smbd/smbd.h"
22 #include "nfs4_acls.h"
23 #include "librpc/gen_ndr/ndr_security.h"
24 #include "../libcli/security/dom_sid.h"
25 #include "../libcli/security/security.h"
26 #include "dbwrap/dbwrap.h"
27 #include "dbwrap/dbwrap_open.h"
28 #include "system/filesys.h"
29 #include "passdb/lookup_sid.h"
31 #include "lib/param/loadparm.h"
34 #define DBGC_CLASS DBGC_ACLS
36 #define SMBACL4_PARAM_TYPE_NAME "nfs4"
38 extern const struct generic_mapping file_generic_mapping;
40 #define SMB_ACE4_INT_MAGIC 0x76F8A967
41 typedef struct _SMB_ACE4_INT_T
48 #define SMB_ACL4_INT_MAGIC 0x29A3E792
49 typedef struct _SMB_ACL4_INT_T
53 SMB_ACE4_INT_T *first;
57 /************************************************
58 Split the ACE flag mapping between nfs4 and Windows
59 into two separate functions rather than trying to do
60 it inline. Allows us to carefully control what flags
61 are mapped to what in one place.
62 ************************************************/
64 static uint32_t map_nfs4_ace_flags_to_windows_ace_flags(
65 uint32_t nfs4_ace_flags)
67 uint32_t win_ace_flags = 0;
69 /* The nfs4 flags <= 0xf map perfectly. */
70 win_ace_flags = nfs4_ace_flags & (SEC_ACE_FLAG_OBJECT_INHERIT|
71 SEC_ACE_FLAG_CONTAINER_INHERIT|
72 SEC_ACE_FLAG_NO_PROPAGATE_INHERIT|
73 SEC_ACE_FLAG_INHERIT_ONLY);
75 /* flags greater than 0xf have diverged :-(. */
76 /* See the nfs4 ace flag definitions here:
77 http://www.ietf.org/rfc/rfc3530.txt.
78 And the Windows ace flag definitions here:
79 librpc/idl/security.idl. */
80 if (nfs4_ace_flags & SMB_ACE4_INHERITED_ACE) {
81 win_ace_flags |= SEC_ACE_FLAG_INHERITED_ACE;
87 static uint32_t map_windows_ace_flags_to_nfs4_ace_flags(uint32_t win_ace_flags)
89 uint32_t nfs4_ace_flags = 0;
91 /* The windows flags <= 0xf map perfectly. */
92 nfs4_ace_flags = win_ace_flags & (SMB_ACE4_FILE_INHERIT_ACE|
93 SMB_ACE4_DIRECTORY_INHERIT_ACE|
94 SMB_ACE4_NO_PROPAGATE_INHERIT_ACE|
95 SMB_ACE4_INHERIT_ONLY_ACE);
97 /* flags greater than 0xf have diverged :-(. */
98 /* See the nfs4 ace flag definitions here:
99 http://www.ietf.org/rfc/rfc3530.txt.
100 And the Windows ace flag definitions here:
101 librpc/idl/security.idl. */
102 if (win_ace_flags & SEC_ACE_FLAG_INHERITED_ACE) {
103 nfs4_ace_flags |= SMB_ACE4_INHERITED_ACE;
106 return nfs4_ace_flags;
109 static SMB_ACL4_INT_T *get_validated_aclint(SMB4ACL_T *theacl)
111 SMB_ACL4_INT_T *aclint = (SMB_ACL4_INT_T *)theacl;
114 DEBUG(2, ("acl is NULL\n"));
118 if (aclint->magic!=SMB_ACL4_INT_MAGIC)
120 DEBUG(2, ("aclint bad magic 0x%x\n", aclint->magic));
127 static SMB_ACE4_INT_T *get_validated_aceint(SMB4ACE_T *ace)
129 SMB_ACE4_INT_T *aceint = (SMB_ACE4_INT_T *)ace;
132 DEBUG(2, ("ace is NULL\n"));
136 if (aceint->magic!=SMB_ACE4_INT_MAGIC)
138 DEBUG(2, ("aceint bad magic 0x%x\n", aceint->magic));
145 SMB4ACL_T *smb_create_smb4acl(TALLOC_CTX *mem_ctx)
147 SMB_ACL4_INT_T *theacl = (SMB_ACL4_INT_T *)TALLOC_ZERO_SIZE(
148 mem_ctx, sizeof(SMB_ACL4_INT_T));
151 DEBUG(0, ("TALLOC_SIZE failed\n"));
155 theacl->magic = SMB_ACL4_INT_MAGIC;
156 /* theacl->first, last = NULL not needed */
157 return (SMB4ACL_T *)theacl;
160 SMB4ACE_T *smb_add_ace4(SMB4ACL_T *theacl, SMB_ACE4PROP_T *prop)
162 SMB_ACL4_INT_T *aclint = get_validated_aclint(theacl);
165 ace = (SMB_ACE4_INT_T *)TALLOC_ZERO_SIZE(
166 theacl, sizeof(SMB_ACE4_INT_T));
169 DEBUG(0, ("TALLOC_SIZE failed\n"));
173 ace->magic = SMB_ACE4_INT_MAGIC;
174 /* ace->next = NULL not needed */
175 memcpy(&ace->prop, prop, sizeof(SMB_ACE4PROP_T));
177 if (aclint->first==NULL)
182 aclint->last->next = (void *)ace;
187 return (SMB4ACE_T *)ace;
190 SMB_ACE4PROP_T *smb_get_ace4(SMB4ACE_T *ace)
192 SMB_ACE4_INT_T *aceint = get_validated_aceint(ace);
196 return &aceint->prop;
199 SMB4ACE_T *smb_next_ace4(SMB4ACE_T *ace)
201 SMB_ACE4_INT_T *aceint = get_validated_aceint(ace);
205 return (SMB4ACE_T *)aceint->next;
208 SMB4ACE_T *smb_first_ace4(SMB4ACL_T *theacl)
210 SMB_ACL4_INT_T *aclint = get_validated_aclint(theacl);
214 return (SMB4ACE_T *)aclint->first;
217 uint32 smb_get_naces(SMB4ACL_T *theacl)
219 SMB_ACL4_INT_T *aclint = get_validated_aclint(theacl);
223 return aclint->naces;
226 static int smbacl4_GetFileOwner(struct connection_struct *conn,
227 const char *filename,
228 SMB_STRUCT_STAT *psbuf)
230 memset(psbuf, 0, sizeof(SMB_STRUCT_STAT));
232 /* Get the stat struct for the owner info. */
233 if (vfs_stat_smb_fname(conn, filename, psbuf) != 0)
235 DEBUG(8, ("vfs_stat_smb_fname failed with error %s\n",
243 static int smbacl4_fGetFileOwner(files_struct *fsp, SMB_STRUCT_STAT *psbuf)
245 memset(psbuf, 0, sizeof(SMB_STRUCT_STAT));
247 if (fsp->fh->fd == -1) {
248 return smbacl4_GetFileOwner(fsp->conn,
249 fsp->fsp_name->base_name, psbuf);
251 if (SMB_VFS_FSTAT(fsp, psbuf) != 0)
253 DEBUG(8, ("SMB_VFS_FSTAT failed with error %s\n",
261 static bool smbacl4_nfs42win(TALLOC_CTX *mem_ctx, SMB4ACL_T *theacl, /* in */
262 struct dom_sid *psid_owner, /* in */
263 struct dom_sid *psid_group, /* in */
264 bool is_directory, /* in */
265 struct security_ace **ppnt_ace_list, /* out */
266 int *pgood_aces /* out */
269 SMB_ACL4_INT_T *aclint = (SMB_ACL4_INT_T *)theacl;
270 SMB_ACE4_INT_T *aceint;
271 struct security_ace *nt_ace_list = NULL;
274 DEBUG(10, ("smbacl_nfs42win entered\n"));
276 aclint = get_validated_aclint(theacl);
277 /* We do not check for naces being 0 or theacl being NULL here
278 * because it is done upstream */
279 /* in smb_get_nt_acl_nfs4(). */
280 nt_ace_list = (struct security_ace *)TALLOC_ZERO_SIZE(
281 mem_ctx, aclint->naces * sizeof(struct security_ace));
282 if (nt_ace_list==NULL)
284 DEBUG(10, ("talloc error"));
289 for (aceint=aclint->first;
291 aceint=(SMB_ACE4_INT_T *)aceint->next) {
294 SMB_ACE4PROP_T *ace = &aceint->prop;
295 uint32_t win_ace_flags;
297 DEBUG(10, ("magic: 0x%x, type: %d, iflags: %x, flags: %x, "
298 "mask: %x, who: %d\n",
299 aceint->magic, ace->aceType, ace->flags,
300 ace->aceFlags, ace->aceMask, ace->who.id));
302 SMB_ASSERT(aceint->magic==SMB_ACE4_INT_MAGIC);
304 if (ace->flags & SMB_ACE4_ID_SPECIAL) {
305 switch (ace->who.special_id) {
306 case SMB_ACE4_WHO_OWNER:
307 sid_copy(&sid, psid_owner);
309 case SMB_ACE4_WHO_GROUP:
310 sid_copy(&sid, psid_group);
312 case SMB_ACE4_WHO_EVERYONE:
313 sid_copy(&sid, &global_sid_World);
316 DEBUG(8, ("invalid special who id %d "
317 "ignored\n", ace->who.special_id));
321 if (ace->aceFlags & SMB_ACE4_IDENTIFIER_GROUP) {
322 gid_to_sid(&sid, ace->who.gid);
324 uid_to_sid(&sid, ace->who.uid);
327 DEBUG(10, ("mapped %d to %s\n", ace->who.id,
328 sid_string_dbg(&sid)));
330 if (is_directory && (ace->aceMask & SMB_ACE4_ADD_FILE)) {
331 ace->aceMask |= SMB_ACE4_DELETE_CHILD;
334 win_ace_flags = map_nfs4_ace_flags_to_windows_ace_flags(
337 (win_ace_flags & (SEC_ACE_FLAG_OBJECT_INHERIT|
338 SEC_ACE_FLAG_CONTAINER_INHERIT))) {
340 * GPFS sets inherits dir_inhert and file_inherit flags
341 * to files, too, which confuses windows, and seems to
342 * be wrong anyways. ==> Map these bits away for files.
344 DEBUG(10, ("removing inherit flags from nfs4 ace\n"));
345 win_ace_flags &= ~(SEC_ACE_FLAG_OBJECT_INHERIT|
346 SEC_ACE_FLAG_CONTAINER_INHERIT);
348 DEBUG(10, ("Windows mapped ace flags: 0x%x => 0x%x\n",
349 ace->aceFlags, win_ace_flags));
352 /* Windows clients expect SYNC on acls to
353 correctly allow rename. See bug #7909. */
354 /* But not on DENY ace entries. See
356 if(ace->aceType == SMB_ACE4_ACCESS_ALLOWED_ACE_TYPE) {
357 mask = ace->aceMask | SMB_ACE4_SYNCHRONIZE;
359 init_sec_ace(&nt_ace_list[good_aces++], &sid,
364 *ppnt_ace_list = nt_ace_list;
365 *pgood_aces = good_aces;
370 static NTSTATUS smb_get_nt_acl_nfs4_common(const SMB_STRUCT_STAT *sbuf,
371 uint32 security_info, TALLOC_CTX *mem_ctx,
372 struct security_descriptor **ppdesc, SMB4ACL_T *theacl)
375 struct dom_sid sid_owner, sid_group;
377 struct security_ace *nt_ace_list = NULL;
378 struct security_acl *psa = NULL;
379 TALLOC_CTX *frame = talloc_stackframe();
381 if (theacl==NULL || smb_get_naces(theacl)==0) {
383 return NT_STATUS_ACCESS_DENIED; /* special because we
384 * shouldn't alloc 0 for
388 uid_to_sid(&sid_owner, sbuf->st_ex_uid);
389 gid_to_sid(&sid_group, sbuf->st_ex_gid);
391 if (smbacl4_nfs42win(mem_ctx, theacl, &sid_owner, &sid_group,
392 S_ISDIR(sbuf->st_ex_mode),
393 &nt_ace_list, &good_aces)==False) {
394 DEBUG(8,("smbacl4_nfs42win failed\n"));
396 return map_nt_error_from_unix(errno);
399 psa = make_sec_acl(frame, NT4_ACL_REVISION, good_aces, nt_ace_list);
401 DEBUG(2,("make_sec_acl failed\n"));
403 return NT_STATUS_NO_MEMORY;
406 DEBUG(10,("after make sec_acl\n"));
407 *ppdesc = make_sec_desc(
408 mem_ctx, SD_REVISION, SEC_DESC_SELF_RELATIVE,
409 (security_info & SECINFO_OWNER) ? &sid_owner : NULL,
410 (security_info & SECINFO_GROUP) ? &sid_group : NULL,
411 NULL, psa, &sd_size);
413 DEBUG(2,("make_sec_desc failed\n"));
415 return NT_STATUS_NO_MEMORY;
418 DEBUG(10, ("smb_get_nt_acl_nfs4_common successfully exited with "
420 (int)ndr_size_security_descriptor(*ppdesc, 0)));
426 NTSTATUS smb_fget_nt_acl_nfs4(files_struct *fsp,
427 uint32 security_info,
429 struct security_descriptor **ppdesc,
432 SMB_STRUCT_STAT sbuf;
434 DEBUG(10, ("smb_fget_nt_acl_nfs4 invoked for %s\n", fsp_str_dbg(fsp)));
436 if (smbacl4_fGetFileOwner(fsp, &sbuf)) {
437 return map_nt_error_from_unix(errno);
440 return smb_get_nt_acl_nfs4_common(&sbuf, security_info,
445 NTSTATUS smb_get_nt_acl_nfs4(struct connection_struct *conn,
447 uint32 security_info,
449 struct security_descriptor **ppdesc,
452 SMB_STRUCT_STAT sbuf;
454 DEBUG(10, ("smb_get_nt_acl_nfs4 invoked for %s\n", name));
456 if (smbacl4_GetFileOwner(conn, name, &sbuf)) {
457 return map_nt_error_from_unix(errno);
460 return smb_get_nt_acl_nfs4_common(&sbuf, security_info,
465 enum smbacl4_mode_enum {e_simple=0, e_special=1};
466 enum smbacl4_acedup_enum {e_dontcare=0, e_reject=1, e_ignore=2, e_merge=3};
468 typedef struct _smbacl4_vfs_params {
469 enum smbacl4_mode_enum mode;
471 enum smbacl4_acedup_enum acedup;
472 } smbacl4_vfs_params;
475 * Gather special parameters for NFS4 ACL handling
477 static int smbacl4_get_vfs_params(
478 const char *type_name,
480 smbacl4_vfs_params *params
483 static const struct enum_list enum_smbacl4_modes[] = {
484 { e_simple, "simple" },
485 { e_special, "special" },
488 static const struct enum_list enum_smbacl4_acedups[] = {
489 { e_dontcare, "dontcare" },
490 { e_reject, "reject" },
491 { e_ignore, "ignore" },
492 { e_merge, "merge" },
496 memset(params, 0, sizeof(smbacl4_vfs_params));
497 params->mode = (enum smbacl4_mode_enum)lp_parm_enum(
498 SNUM(fsp->conn), type_name,
499 "mode", enum_smbacl4_modes, e_simple);
500 params->do_chown = lp_parm_bool(SNUM(fsp->conn), type_name,
502 params->acedup = (enum smbacl4_acedup_enum)lp_parm_enum(
503 SNUM(fsp->conn), type_name,
504 "acedup", enum_smbacl4_acedups, e_dontcare);
506 DEBUG(10, ("mode:%s, do_chown:%s, acedup: %s\n",
507 enum_smbacl4_modes[params->mode].name,
508 params->do_chown ? "true" : "false",
509 enum_smbacl4_acedups[params->acedup].name));
514 static void smbacl4_dump_nfs4acl(int level, SMB4ACL_T *theacl)
516 SMB_ACL4_INT_T *aclint = get_validated_aclint(theacl);
517 SMB_ACE4_INT_T *aceint;
519 DEBUG(level, ("NFS4ACL: size=%d\n", aclint->naces));
521 for (aceint = aclint->first;
523 aceint=(SMB_ACE4_INT_T *)aceint->next) {
524 SMB_ACE4PROP_T *ace = &aceint->prop;
526 DEBUG(level, ("\tACE: type=%d, flags=0x%x, fflags=0x%x, "
527 "mask=0x%x, id=%d\n",
529 ace->aceFlags, ace->flags,
536 * Find 2 NFS4 who-special ACE property (non-copy!!!)
537 * match nonzero if "special" and who is equal
538 * return ace if found matching; otherwise NULL
540 static SMB_ACE4PROP_T *smbacl4_find_equal_special(
542 SMB_ACE4PROP_T *aceNew)
544 SMB_ACL4_INT_T *aclint = get_validated_aclint(theacl);
545 SMB_ACE4_INT_T *aceint;
547 for (aceint = aclint->first; aceint != NULL;
548 aceint=(SMB_ACE4_INT_T *)aceint->next) {
549 SMB_ACE4PROP_T *ace = &aceint->prop;
551 DEBUG(10,("ace type:0x%x flags:0x%x aceFlags:0x%x "
552 "new type:0x%x flags:0x%x aceFlags:0x%x\n",
553 ace->aceType, ace->flags, ace->aceFlags,
554 aceNew->aceType, aceNew->flags,aceNew->aceFlags));
556 if (ace->flags == aceNew->flags &&
557 ace->aceType==aceNew->aceType &&
558 ace->aceFlags==aceNew->aceFlags)
560 /* keep type safety; e.g. gid is an u.short */
561 if (ace->flags & SMB_ACE4_ID_SPECIAL)
563 if (ace->who.special_id ==
564 aceNew->who.special_id)
567 if (ace->aceFlags & SMB_ACE4_IDENTIFIER_GROUP)
569 if (ace->who.gid==aceNew->who.gid)
572 if (ace->who.uid==aceNew->who.uid)
583 static bool smbacl4_fill_ace4(
584 const struct smb_filename *filename,
585 smbacl4_vfs_params *params,
588 const struct security_ace *ace_nt, /* input */
589 SMB_ACE4PROP_T *ace_v4 /* output */
592 DEBUG(10, ("got ace for %s\n", sid_string_dbg(&ace_nt->trustee)));
594 memset(ace_v4, 0, sizeof(SMB_ACE4PROP_T));
596 /* only ACCESS|DENY supported right now */
597 ace_v4->aceType = ace_nt->type;
599 ace_v4->aceFlags = map_windows_ace_flags_to_nfs4_ace_flags(
602 /* remove inheritance flags on files */
603 if (VALID_STAT(filename->st) &&
604 !S_ISDIR(filename->st.st_ex_mode)) {
605 DEBUG(10, ("Removing inheritance flags from a file\n"));
606 ace_v4->aceFlags &= ~(SMB_ACE4_FILE_INHERIT_ACE|
607 SMB_ACE4_DIRECTORY_INHERIT_ACE|
608 SMB_ACE4_NO_PROPAGATE_INHERIT_ACE|
609 SMB_ACE4_INHERIT_ONLY_ACE);
612 ace_v4->aceMask = ace_nt->access_mask &
613 (SEC_STD_ALL | SEC_FILE_ALL);
615 se_map_generic(&ace_v4->aceMask, &file_generic_mapping);
617 if (ace_v4->aceFlags!=ace_nt->flags)
618 DEBUG(9, ("ace_v4->aceFlags(0x%x)!=ace_nt->flags(0x%x)\n",
619 ace_v4->aceFlags, ace_nt->flags));
621 if (ace_v4->aceMask!=ace_nt->access_mask)
622 DEBUG(9, ("ace_v4->aceMask(0x%x)!=ace_nt->access_mask(0x%x)\n",
623 ace_v4->aceMask, ace_nt->access_mask));
625 if (dom_sid_equal(&ace_nt->trustee, &global_sid_World)) {
626 ace_v4->who.special_id = SMB_ACE4_WHO_EVERYONE;
627 ace_v4->flags |= SMB_ACE4_ID_SPECIAL;
632 if (sid_to_gid(&ace_nt->trustee, &gid)) {
633 ace_v4->aceFlags |= SMB_ACE4_IDENTIFIER_GROUP;
635 if (params->mode==e_special && gid==ownerGID) {
636 ace_v4->flags |= SMB_ACE4_ID_SPECIAL;
637 ace_v4->who.special_id = SMB_ACE4_WHO_GROUP;
639 ace_v4->who.gid = gid;
641 } else if (sid_to_uid(&ace_nt->trustee, &uid)) {
642 if (params->mode==e_special && uid==ownerUID) {
643 ace_v4->flags |= SMB_ACE4_ID_SPECIAL;
644 ace_v4->who.special_id = SMB_ACE4_WHO_OWNER;
646 ace_v4->who.uid = uid;
649 DEBUG(1, ("nfs4_acls.c: file [%s]: could not "
650 "convert %s to uid or gid\n",
652 sid_string_dbg(&ace_nt->trustee)));
657 return True; /* OK */
660 static int smbacl4_MergeIgnoreReject(
661 enum smbacl4_acedup_enum acedup,
662 SMB4ACL_T *theacl, /* may modify it */
663 SMB_ACE4PROP_T *ace, /* the "new" ACE */
669 SMB_ACE4PROP_T *ace4found = smbacl4_find_equal_special(theacl, ace);
674 case e_merge: /* "merge" flags */
676 ace4found->aceFlags |= ace->aceFlags;
677 ace4found->aceMask |= ace->aceMask;
679 case e_ignore: /* leave out this record */
682 case e_reject: /* do an error */
683 DEBUG(8, ("ACL rejected by duplicate nt ace#%d\n", i));
684 errno = EINVAL; /* SHOULD be set on any _real_ error */
694 static SMB4ACL_T *smbacl4_win2nfs4(
696 const files_struct *fsp,
697 const struct security_acl *dacl,
698 smbacl4_vfs_params *pparams,
705 const char *filename = fsp->fsp_name->base_name;
707 DEBUG(10, ("smbacl4_win2nfs4 invoked\n"));
709 theacl = smb_create_smb4acl(mem_ctx);
713 for(i=0; i<dacl->num_aces; i++) {
714 SMB_ACE4PROP_T ace_v4;
715 bool addNewACE = True;
717 if (!smbacl4_fill_ace4(fsp->fsp_name, pparams,
719 dacl->aces + i, &ace_v4)) {
720 DEBUG(3, ("Could not fill ace for file %s, SID %s\n",
722 sid_string_dbg(&((dacl->aces+i)->trustee))));
726 if (pparams->acedup!=e_dontcare) {
727 if (smbacl4_MergeIgnoreReject(pparams->acedup, theacl,
728 &ace_v4, &addNewACE, i))
733 smb_add_ace4(theacl, &ace_v4);
739 NTSTATUS smb_set_nt_acl_nfs4(vfs_handle_struct *handle, files_struct *fsp,
740 uint32 security_info_sent,
741 const struct security_descriptor *psd,
742 set_nfs4acl_native_fn_t set_nfs4_native)
744 smbacl4_vfs_params params;
745 SMB4ACL_T *theacl = NULL;
748 SMB_STRUCT_STAT sbuf;
749 bool set_acl_as_root = false;
750 uid_t newUID = (uid_t)-1;
751 gid_t newGID = (gid_t)-1;
753 TALLOC_CTX *frame = talloc_stackframe();
755 DEBUG(10, ("smb_set_nt_acl_nfs4 invoked for %s\n", fsp_str_dbg(fsp)));
757 if ((security_info_sent & (SECINFO_DACL |
758 SECINFO_GROUP | SECINFO_OWNER)) == 0)
760 DEBUG(9, ("security_info_sent (0x%x) ignored\n",
761 security_info_sent));
763 return NT_STATUS_OK; /* won't show error - later to be
767 /* Special behaviours */
768 if (smbacl4_get_vfs_params(SMBACL4_PARAM_TYPE_NAME, fsp, ¶ms)) {
770 return NT_STATUS_NO_MEMORY;
773 if (smbacl4_fGetFileOwner(fsp, &sbuf)) {
775 return map_nt_error_from_unix(errno);
778 if (params.do_chown) {
779 /* chown logic is a copy/paste from posix_acl.c:set_nt_acl */
780 NTSTATUS status = unpack_nt_owners(fsp->conn, &newUID, &newGID,
781 security_info_sent, psd);
782 if (!NT_STATUS_IS_OK(status)) {
783 DEBUG(8, ("unpack_nt_owners failed"));
787 if (((newUID != (uid_t)-1) && (sbuf.st_ex_uid != newUID)) ||
788 ((newGID != (gid_t)-1) && (sbuf.st_ex_gid != newGID))) {
790 status = try_chown(fsp, newUID, newGID);
791 if (!NT_STATUS_IS_OK(status)) {
792 DEBUG(3,("chown %s, %u, %u failed. Error = "
793 "%s.\n", fsp_str_dbg(fsp),
794 (unsigned int)newUID,
795 (unsigned int)newGID,
801 DEBUG(10,("chown %s, %u, %u succeeded.\n",
802 fsp_str_dbg(fsp), (unsigned int)newUID,
803 (unsigned int)newGID));
804 if (smbacl4_GetFileOwner(fsp->conn,
805 fsp->fsp_name->base_name,
808 return map_nt_error_from_unix(errno);
810 /* If we successfully chowned, we know we must
811 * be able to set the acl, so do it as root.
813 set_acl_as_root = true;
817 if (!(security_info_sent & SECINFO_DACL) || psd->dacl ==NULL) {
818 DEBUG(10, ("no dacl found; security_info_sent = 0x%x\n",
819 security_info_sent));
824 theacl = smbacl4_win2nfs4(frame, fsp, psd->dacl, ¶ms,
825 sbuf.st_ex_uid, sbuf.st_ex_gid);
828 return map_nt_error_from_unix(errno);
831 smbacl4_dump_nfs4acl(10, theacl);
833 if (set_acl_as_root) {
836 result = set_nfs4_native(handle, fsp, theacl);
838 if (set_acl_as_root) {
846 DEBUG(10, ("set_nfs4_native failed with %s\n",
848 return map_nt_error_from_unix(errno);
851 DEBUG(10, ("smb_set_nt_acl_nfs4 succeeded\n"));