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(uint32_t nfs4_ace_flags)
66 uint32_t win_ace_flags = 0;
68 /* The nfs4 flags <= 0xf map perfectly. */
69 win_ace_flags = nfs4_ace_flags & (SEC_ACE_FLAG_OBJECT_INHERIT|
70 SEC_ACE_FLAG_CONTAINER_INHERIT|
71 SEC_ACE_FLAG_NO_PROPAGATE_INHERIT|
72 SEC_ACE_FLAG_INHERIT_ONLY);
74 /* flags greater than 0xf have diverged :-(. */
75 /* See the nfs4 ace flag definitions here:
76 http://www.ietf.org/rfc/rfc3530.txt.
77 And the Windows ace flag definitions here:
78 librpc/idl/security.idl. */
79 if (nfs4_ace_flags & SMB_ACE4_INHERITED_ACE) {
80 win_ace_flags |= SEC_ACE_FLAG_INHERITED_ACE;
86 static uint32_t map_windows_ace_flags_to_nfs4_ace_flags(uint32_t win_ace_flags)
88 uint32_t nfs4_ace_flags = 0;
90 /* The windows flags <= 0xf map perfectly. */
91 nfs4_ace_flags = win_ace_flags & (SMB_ACE4_FILE_INHERIT_ACE|
92 SMB_ACE4_DIRECTORY_INHERIT_ACE|
93 SMB_ACE4_NO_PROPAGATE_INHERIT_ACE|
94 SMB_ACE4_INHERIT_ONLY_ACE);
96 /* flags greater than 0xf have diverged :-(. */
97 /* See the nfs4 ace flag definitions here:
98 http://www.ietf.org/rfc/rfc3530.txt.
99 And the Windows ace flag definitions here:
100 librpc/idl/security.idl. */
101 if (win_ace_flags & SEC_ACE_FLAG_INHERITED_ACE) {
102 nfs4_ace_flags |= SMB_ACE4_INHERITED_ACE;
105 return nfs4_ace_flags;
108 static SMB_ACL4_INT_T *get_validated_aclint(SMB4ACL_T *theacl)
110 SMB_ACL4_INT_T *aclint = (SMB_ACL4_INT_T *)theacl;
113 DEBUG(2, ("acl is NULL\n"));
117 if (aclint->magic!=SMB_ACL4_INT_MAGIC)
119 DEBUG(2, ("aclint bad magic 0x%x\n", aclint->magic));
126 static SMB_ACE4_INT_T *get_validated_aceint(SMB4ACE_T *ace)
128 SMB_ACE4_INT_T *aceint = (SMB_ACE4_INT_T *)ace;
131 DEBUG(2, ("ace is NULL\n"));
135 if (aceint->magic!=SMB_ACE4_INT_MAGIC)
137 DEBUG(2, ("aceint bad magic 0x%x\n", aceint->magic));
144 SMB4ACL_T *smb_create_smb4acl(void)
146 TALLOC_CTX *mem_ctx = talloc_tos();
147 SMB_ACL4_INT_T *theacl = (SMB_ACL4_INT_T *)TALLOC_ZERO_SIZE(mem_ctx, sizeof(SMB_ACL4_INT_T));
150 DEBUG(0, ("TALLOC_SIZE failed\n"));
154 theacl->magic = SMB_ACL4_INT_MAGIC;
155 /* theacl->first, last = NULL not needed */
156 return (SMB4ACL_T *)theacl;
159 SMB4ACE_T *smb_add_ace4(SMB4ACL_T *theacl, SMB_ACE4PROP_T *prop)
161 SMB_ACL4_INT_T *aclint = get_validated_aclint(theacl);
162 TALLOC_CTX *mem_ctx = talloc_tos();
165 ace = (SMB_ACE4_INT_T *)TALLOC_ZERO_SIZE(mem_ctx, sizeof(SMB_ACE4_INT_T));
168 DEBUG(0, ("TALLOC_SIZE failed\n"));
172 ace->magic = SMB_ACE4_INT_MAGIC;
173 /* ace->next = NULL not needed */
174 memcpy(&ace->prop, prop, sizeof(SMB_ACE4PROP_T));
176 if (aclint->first==NULL)
181 aclint->last->next = (void *)ace;
186 return (SMB4ACE_T *)ace;
189 SMB_ACE4PROP_T *smb_get_ace4(SMB4ACE_T *ace)
191 SMB_ACE4_INT_T *aceint = get_validated_aceint(ace);
195 return &aceint->prop;
198 SMB4ACE_T *smb_next_ace4(SMB4ACE_T *ace)
200 SMB_ACE4_INT_T *aceint = get_validated_aceint(ace);
204 return (SMB4ACE_T *)aceint->next;
207 SMB4ACE_T *smb_first_ace4(SMB4ACL_T *theacl)
209 SMB_ACL4_INT_T *aclint = get_validated_aclint(theacl);
213 return (SMB4ACE_T *)aclint->first;
216 uint32 smb_get_naces(SMB4ACL_T *theacl)
218 SMB_ACL4_INT_T *aclint = get_validated_aclint(theacl);
222 return aclint->naces;
225 static int smbacl4_GetFileOwner(struct connection_struct *conn,
226 const char *filename,
227 SMB_STRUCT_STAT *psbuf)
229 memset(psbuf, 0, sizeof(SMB_STRUCT_STAT));
231 /* Get the stat struct for the owner info. */
232 if (vfs_stat_smb_fname(conn, filename, psbuf) != 0)
234 DEBUG(8, ("vfs_stat_smb_fname failed with error %s\n",
242 static int smbacl4_fGetFileOwner(files_struct *fsp, SMB_STRUCT_STAT *psbuf)
244 memset(psbuf, 0, sizeof(SMB_STRUCT_STAT));
246 if (fsp->fh->fd == -1) {
247 return smbacl4_GetFileOwner(fsp->conn,
248 fsp->fsp_name->base_name, psbuf);
250 if (SMB_VFS_FSTAT(fsp, psbuf) != 0)
252 DEBUG(8, ("SMB_VFS_FSTAT failed with error %s\n",
260 static bool smbacl4_nfs42win(TALLOC_CTX *mem_ctx, SMB4ACL_T *theacl, /* in */
261 struct dom_sid *psid_owner, /* in */
262 struct dom_sid *psid_group, /* in */
263 bool is_directory, /* in */
264 struct security_ace **ppnt_ace_list, /* out */
265 int *pgood_aces /* out */
268 SMB_ACL4_INT_T *aclint = (SMB_ACL4_INT_T *)theacl;
269 SMB_ACE4_INT_T *aceint;
270 struct security_ace *nt_ace_list = NULL;
273 DEBUG(10, ("smbacl_nfs42win entered\n"));
275 aclint = get_validated_aclint(theacl);
276 /* We do not check for naces being 0 or theacl being NULL here because it is done upstream */
277 /* in smb_get_nt_acl_nfs4(). */
278 nt_ace_list = (struct security_ace *)TALLOC_ZERO_SIZE(mem_ctx, aclint->naces * sizeof(struct security_ace));
279 if (nt_ace_list==NULL)
281 DEBUG(10, ("talloc error"));
286 for (aceint=aclint->first; aceint!=NULL; aceint=(SMB_ACE4_INT_T *)aceint->next) {
289 SMB_ACE4PROP_T *ace = &aceint->prop;
290 uint32_t win_ace_flags;
292 DEBUG(10, ("magic: 0x%x, type: %d, iflags: %x, flags: %x, mask: %x, "
293 "who: %d\n", aceint->magic, ace->aceType, ace->flags,
294 ace->aceFlags, ace->aceMask, ace->who.id));
296 SMB_ASSERT(aceint->magic==SMB_ACE4_INT_MAGIC);
298 if (ace->flags & SMB_ACE4_ID_SPECIAL) {
299 switch (ace->who.special_id) {
300 case SMB_ACE4_WHO_OWNER:
301 sid_copy(&sid, psid_owner);
303 case SMB_ACE4_WHO_GROUP:
304 sid_copy(&sid, psid_group);
306 case SMB_ACE4_WHO_EVERYONE:
307 sid_copy(&sid, &global_sid_World);
310 DEBUG(8, ("invalid special who id %d "
311 "ignored\n", ace->who.special_id));
314 if (ace->aceFlags & SMB_ACE4_IDENTIFIER_GROUP) {
315 gid_to_sid(&sid, ace->who.gid);
317 uid_to_sid(&sid, ace->who.uid);
320 DEBUG(10, ("mapped %d to %s\n", ace->who.id,
321 sid_string_dbg(&sid)));
323 if (is_directory && (ace->aceMask & SMB_ACE4_ADD_FILE)) {
324 ace->aceMask |= SMB_ACE4_DELETE_CHILD;
327 win_ace_flags = map_nfs4_ace_flags_to_windows_ace_flags(ace->aceFlags);
328 if (!is_directory && (win_ace_flags & (SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_CONTAINER_INHERIT))) {
330 * GPFS sets inherits dir_inhert and file_inherit flags
331 * to files, too, which confuses windows, and seems to
332 * be wrong anyways. ==> Map these bits away for files.
334 DEBUG(10, ("removing inherit flags from nfs4 ace\n"));
335 win_ace_flags &= ~(SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_CONTAINER_INHERIT);
337 DEBUG(10, ("Windows mapped ace flags: 0x%x => 0x%x\n",
338 ace->aceFlags, win_ace_flags));
340 /* Windows clients expect SYNC on acls to
341 correctly allow rename. See bug #7909. */
342 mask = ace->aceMask | SMB_ACE4_SYNCHRONIZE;
343 init_sec_ace(&nt_ace_list[good_aces++], &sid,
348 *ppnt_ace_list = nt_ace_list;
349 *pgood_aces = good_aces;
354 static NTSTATUS smb_get_nt_acl_nfs4_common(const SMB_STRUCT_STAT *sbuf,
355 uint32 security_info,
356 struct security_descriptor **ppdesc, SMB4ACL_T *theacl)
359 struct dom_sid sid_owner, sid_group;
361 struct security_ace *nt_ace_list = NULL;
362 struct security_acl *psa = NULL;
363 TALLOC_CTX *mem_ctx = talloc_tos();
365 if (theacl==NULL || smb_get_naces(theacl)==0)
366 return NT_STATUS_ACCESS_DENIED; /* special because we
367 * shouldn't alloc 0 for
370 uid_to_sid(&sid_owner, sbuf->st_ex_uid);
371 gid_to_sid(&sid_group, sbuf->st_ex_gid);
373 if (smbacl4_nfs42win(mem_ctx, theacl, &sid_owner, &sid_group,
374 S_ISDIR(sbuf->st_ex_mode),
375 &nt_ace_list, &good_aces)==False) {
376 DEBUG(8,("smbacl4_nfs42win failed\n"));
377 return map_nt_error_from_unix(errno);
380 psa = make_sec_acl(mem_ctx, NT4_ACL_REVISION, good_aces, nt_ace_list);
382 DEBUG(2,("make_sec_acl failed\n"));
383 return NT_STATUS_NO_MEMORY;
386 DEBUG(10,("after make sec_acl\n"));
387 *ppdesc = make_sec_desc(mem_ctx, SD_REVISION, SEC_DESC_SELF_RELATIVE,
388 (security_info & SECINFO_OWNER) ? &sid_owner : NULL,
389 (security_info & SECINFO_GROUP) ? &sid_group : NULL,
390 NULL, psa, &sd_size);
392 DEBUG(2,("make_sec_desc failed\n"));
393 return NT_STATUS_NO_MEMORY;
396 DEBUG(10, ("smb_get_nt_acl_nfs4_common successfully exited with sd_size %d\n",
397 (int)ndr_size_security_descriptor(*ppdesc, 0)));
402 NTSTATUS smb_fget_nt_acl_nfs4(files_struct *fsp,
403 uint32 security_info,
404 struct security_descriptor **ppdesc, SMB4ACL_T *theacl)
406 SMB_STRUCT_STAT sbuf;
408 DEBUG(10, ("smb_fget_nt_acl_nfs4 invoked for %s\n", fsp_str_dbg(fsp)));
410 if (smbacl4_fGetFileOwner(fsp, &sbuf)) {
411 return map_nt_error_from_unix(errno);
414 return smb_get_nt_acl_nfs4_common(&sbuf, security_info, ppdesc, theacl);
417 NTSTATUS smb_get_nt_acl_nfs4(struct connection_struct *conn,
419 uint32 security_info,
420 struct security_descriptor **ppdesc, SMB4ACL_T *theacl)
422 SMB_STRUCT_STAT sbuf;
424 DEBUG(10, ("smb_get_nt_acl_nfs4 invoked for %s\n", name));
426 if (smbacl4_GetFileOwner(conn, name, &sbuf)) {
427 return map_nt_error_from_unix(errno);
430 return smb_get_nt_acl_nfs4_common(&sbuf, security_info, ppdesc, theacl);
433 enum smbacl4_mode_enum {e_simple=0, e_special=1};
434 enum smbacl4_acedup_enum {e_dontcare=0, e_reject=1, e_ignore=2, e_merge=3};
436 typedef struct _smbacl4_vfs_params {
437 enum smbacl4_mode_enum mode;
439 enum smbacl4_acedup_enum acedup;
440 struct db_context *sid_mapping_table;
441 } smbacl4_vfs_params;
444 * Gather special parameters for NFS4 ACL handling
446 static int smbacl4_get_vfs_params(
447 const char *type_name,
449 smbacl4_vfs_params *params
452 static const struct enum_list enum_smbacl4_modes[] = {
453 { e_simple, "simple" },
454 { e_special, "special" },
457 static const struct enum_list enum_smbacl4_acedups[] = {
458 { e_dontcare, "dontcare" },
459 { e_reject, "reject" },
460 { e_ignore, "ignore" },
461 { e_merge, "merge" },
465 memset(params, 0, sizeof(smbacl4_vfs_params));
466 params->mode = (enum smbacl4_mode_enum)lp_parm_enum(
467 SNUM(fsp->conn), type_name,
468 "mode", enum_smbacl4_modes, e_simple);
469 params->do_chown = lp_parm_bool(SNUM(fsp->conn), type_name,
471 params->acedup = (enum smbacl4_acedup_enum)lp_parm_enum(
472 SNUM(fsp->conn), type_name,
473 "acedup", enum_smbacl4_acedups, e_dontcare);
475 DEBUG(10, ("mode:%s, do_chown:%s, acedup: %s\n",
476 enum_smbacl4_modes[params->mode].name,
477 params->do_chown ? "true" : "false",
478 enum_smbacl4_acedups[params->acedup].name));
483 static void smbacl4_dump_nfs4acl(int level, SMB4ACL_T *theacl)
485 SMB_ACL4_INT_T *aclint = get_validated_aclint(theacl);
486 SMB_ACE4_INT_T *aceint;
488 DEBUG(level, ("NFS4ACL: size=%d\n", aclint->naces));
490 for(aceint = aclint->first; aceint!=NULL; aceint=(SMB_ACE4_INT_T *)aceint->next) {
491 SMB_ACE4PROP_T *ace = &aceint->prop;
493 DEBUG(level, ("\tACE: type=%d, flags=0x%x, fflags=0x%x, mask=0x%x, id=%d\n",
495 ace->aceFlags, ace->flags,
502 * Find 2 NFS4 who-special ACE property (non-copy!!!)
503 * match nonzero if "special" and who is equal
504 * return ace if found matching; otherwise NULL
506 static SMB_ACE4PROP_T *smbacl4_find_equal_special(
508 SMB_ACE4PROP_T *aceNew)
510 SMB_ACL4_INT_T *aclint = get_validated_aclint(theacl);
511 SMB_ACE4_INT_T *aceint;
513 for(aceint = aclint->first; aceint!=NULL; aceint=(SMB_ACE4_INT_T *)aceint->next) {
514 SMB_ACE4PROP_T *ace = &aceint->prop;
516 DEBUG(10,("ace type:0x%x flags:0x%x aceFlags:0x%x "
517 "new type:0x%x flags:0x%x aceFlags:0x%x\n",
518 ace->aceType, ace->flags, ace->aceFlags,
519 aceNew->aceType, aceNew->flags,aceNew->aceFlags));
521 if (ace->flags == aceNew->flags &&
522 ace->aceType==aceNew->aceType &&
523 ace->aceFlags==aceNew->aceFlags)
525 /* keep type safety; e.g. gid is an u.short */
526 if (ace->flags & SMB_ACE4_ID_SPECIAL)
528 if (ace->who.special_id==aceNew->who.special_id)
531 if (ace->aceFlags & SMB_ACE4_IDENTIFIER_GROUP)
533 if (ace->who.gid==aceNew->who.gid)
536 if (ace->who.uid==aceNew->who.uid)
546 static bool nfs4_map_sid(smbacl4_vfs_params *params, const struct dom_sid *src,
549 static struct db_context *mapping_db = NULL;
552 if (mapping_db == NULL) {
553 const char *dbname = lp_parm_const_string(
554 -1, SMBACL4_PARAM_TYPE_NAME, "sidmap", NULL);
556 if (dbname == NULL) {
557 DEBUG(10, ("%s:sidmap not defined\n",
558 SMBACL4_PARAM_TYPE_NAME));
563 mapping_db = db_open(NULL, dbname, 0, TDB_DEFAULT,
567 if (mapping_db == NULL) {
568 DEBUG(1, ("could not open sidmap: %s\n",
574 if (mapping_db->fetch(mapping_db, NULL,
575 string_term_tdb_data(sid_string_tos(src)),
577 DEBUG(10, ("could not find mapping for SID %s\n",
578 sid_string_dbg(src)));
582 if ((data.dptr == NULL) || (data.dsize <= 0)
583 || (data.dptr[data.dsize-1] != '\0')) {
584 DEBUG(5, ("invalid mapping for SID %s\n",
585 sid_string_dbg(src)));
586 TALLOC_FREE(data.dptr);
590 if (!string_to_sid(dst, (char *)data.dptr)) {
591 DEBUG(1, ("invalid mapping %s for SID %s\n",
592 (char *)data.dptr, sid_string_dbg(src)));
593 TALLOC_FREE(data.dptr);
597 TALLOC_FREE(data.dptr);
602 static bool smbacl4_fill_ace4(
604 const char *filename,
605 smbacl4_vfs_params *params,
608 const struct security_ace *ace_nt, /* input */
609 SMB_ACE4PROP_T *ace_v4 /* output */
612 DEBUG(10, ("got ace for %s\n", sid_string_dbg(&ace_nt->trustee)));
614 memset(ace_v4, 0, sizeof(SMB_ACE4PROP_T));
615 ace_v4->aceType = ace_nt->type; /* only ACCESS|DENY supported right now */
616 ace_v4->aceFlags = map_windows_ace_flags_to_nfs4_ace_flags(ace_nt->flags);
617 ace_v4->aceMask = ace_nt->access_mask &
618 (SEC_STD_ALL | SEC_FILE_ALL);
620 se_map_generic(&ace_v4->aceMask, &file_generic_mapping);
622 if (ace_v4->aceFlags!=ace_nt->flags)
623 DEBUG(9, ("ace_v4->aceFlags(0x%x)!=ace_nt->flags(0x%x)\n",
624 ace_v4->aceFlags, ace_nt->flags));
626 if (ace_v4->aceMask!=ace_nt->access_mask)
627 DEBUG(9, ("ace_v4->aceMask(0x%x)!=ace_nt->access_mask(0x%x)\n",
628 ace_v4->aceMask, ace_nt->access_mask));
630 if (dom_sid_equal(&ace_nt->trustee, &global_sid_World)) {
631 ace_v4->who.special_id = SMB_ACE4_WHO_EVERYONE;
632 ace_v4->flags |= SMB_ACE4_ID_SPECIAL;
634 const char *dom, *name;
635 enum lsa_SidType type;
640 sid_copy(&sid, &ace_nt->trustee);
642 if (!lookup_sid(mem_ctx, &sid, &dom, &name, &type)) {
644 struct dom_sid mapped;
646 if (!nfs4_map_sid(params, &sid, &mapped)) {
647 DEBUG(1, ("nfs4_acls.c: file [%s]: SID %s "
648 "unknown\n", filename, sid_string_dbg(&sid)));
653 DEBUG(2, ("nfs4_acls.c: file [%s]: mapped SID %s "
654 "to %s\n", filename, sid_string_dbg(&sid), sid_string_dbg(&mapped)));
656 if (!lookup_sid(mem_ctx, &mapped, &dom,
658 DEBUG(1, ("nfs4_acls.c: file [%s]: SID %s "
659 "mapped from %s is unknown\n",
660 filename, sid_string_dbg(&mapped), sid_string_dbg(&sid)));
665 sid_copy(&sid, &mapped);
668 if (type == SID_NAME_USER) {
669 if (!sid_to_uid(&sid, &uid)) {
670 DEBUG(1, ("nfs4_acls.c: file [%s]: could not "
671 "convert %s to uid\n", filename,
672 sid_string_dbg(&sid)));
676 if (params->mode==e_special && uid==ownerUID) {
677 ace_v4->flags |= SMB_ACE4_ID_SPECIAL;
678 ace_v4->who.special_id = SMB_ACE4_WHO_OWNER;
680 ace_v4->who.uid = uid;
682 } else { /* else group? - TODO check it... */
683 if (!sid_to_gid(&sid, &gid)) {
684 DEBUG(1, ("nfs4_acls.c: file [%s]: could not "
685 "convert %s to gid\n", filename,
686 sid_string_dbg(&sid)));
690 ace_v4->aceFlags |= SMB_ACE4_IDENTIFIER_GROUP;
692 if (params->mode==e_special && gid==ownerGID) {
693 ace_v4->flags |= SMB_ACE4_ID_SPECIAL;
694 ace_v4->who.special_id = SMB_ACE4_WHO_GROUP;
696 ace_v4->who.gid = gid;
701 return True; /* OK */
704 static int smbacl4_MergeIgnoreReject(
705 enum smbacl4_acedup_enum acedup,
706 SMB4ACL_T *theacl, /* may modify it */
707 SMB_ACE4PROP_T *ace, /* the "new" ACE */
713 SMB_ACE4PROP_T *ace4found = smbacl4_find_equal_special(theacl, ace);
718 case e_merge: /* "merge" flags */
720 ace4found->aceFlags |= ace->aceFlags;
721 ace4found->aceMask |= ace->aceMask;
723 case e_ignore: /* leave out this record */
726 case e_reject: /* do an error */
727 DEBUG(8, ("ACL rejected by duplicate nt ace#%d\n", i));
728 errno = EINVAL; /* SHOULD be set on any _real_ error */
738 static SMB4ACL_T *smbacl4_win2nfs4(
739 const char *filename,
740 const struct security_acl *dacl,
741 smbacl4_vfs_params *pparams,
748 TALLOC_CTX *mem_ctx = talloc_tos();
750 DEBUG(10, ("smbacl4_win2nfs4 invoked\n"));
752 theacl = smb_create_smb4acl();
756 for(i=0; i<dacl->num_aces; i++) {
757 SMB_ACE4PROP_T ace_v4;
758 bool addNewACE = True;
760 if (!smbacl4_fill_ace4(mem_ctx, filename, pparams,
762 dacl->aces + i, &ace_v4)) {
763 DEBUG(3, ("Could not fill ace for file %s, SID %s\n",
765 sid_string_dbg(&((dacl->aces+i)->trustee))));
769 if (pparams->acedup!=e_dontcare) {
770 if (smbacl4_MergeIgnoreReject(pparams->acedup, theacl,
771 &ace_v4, &addNewACE, i))
776 smb_add_ace4(theacl, &ace_v4);
782 NTSTATUS smb_set_nt_acl_nfs4(files_struct *fsp,
783 uint32 security_info_sent,
784 const struct security_descriptor *psd,
785 set_nfs4acl_native_fn_t set_nfs4_native)
787 smbacl4_vfs_params params;
788 SMB4ACL_T *theacl = NULL;
791 SMB_STRUCT_STAT sbuf;
792 bool set_acl_as_root = false;
793 uid_t newUID = (uid_t)-1;
794 gid_t newGID = (gid_t)-1;
797 DEBUG(10, ("smb_set_nt_acl_nfs4 invoked for %s\n", fsp_str_dbg(fsp)));
799 if ((security_info_sent & (SECINFO_DACL |
800 SECINFO_GROUP | SECINFO_OWNER)) == 0)
802 DEBUG(9, ("security_info_sent (0x%x) ignored\n",
803 security_info_sent));
804 return NT_STATUS_OK; /* won't show error - later to be refined... */
807 /* Special behaviours */
808 if (smbacl4_get_vfs_params(SMBACL4_PARAM_TYPE_NAME, fsp, ¶ms))
809 return NT_STATUS_NO_MEMORY;
811 if (smbacl4_fGetFileOwner(fsp, &sbuf))
812 return map_nt_error_from_unix(errno);
814 if (params.do_chown) {
815 /* chown logic is a copy/paste from posix_acl.c:set_nt_acl */
816 NTSTATUS status = unpack_nt_owners(fsp->conn, &newUID, &newGID, security_info_sent, psd);
817 if (!NT_STATUS_IS_OK(status)) {
818 DEBUG(8, ("unpack_nt_owners failed"));
821 if (((newUID != (uid_t)-1) && (sbuf.st_ex_uid != newUID)) ||
822 ((newGID != (gid_t)-1) && (sbuf.st_ex_gid != newGID))) {
824 status = try_chown(fsp, newUID, newGID);
825 if (!NT_STATUS_IS_OK(status)) {
826 DEBUG(3,("chown %s, %u, %u failed. Error = "
827 "%s.\n", fsp_str_dbg(fsp),
828 (unsigned int)newUID,
829 (unsigned int)newGID,
834 DEBUG(10,("chown %s, %u, %u succeeded.\n",
835 fsp_str_dbg(fsp), (unsigned int)newUID,
836 (unsigned int)newGID));
837 if (smbacl4_GetFileOwner(fsp->conn,
838 fsp->fsp_name->base_name,
840 return map_nt_error_from_unix(errno);
842 /* If we successfully chowned, we know we must
843 * be able to set the acl, so do it as root.
845 set_acl_as_root = true;
849 if (!(security_info_sent & SECINFO_DACL) || psd->dacl ==NULL) {
850 DEBUG(10, ("no dacl found; security_info_sent = 0x%x\n", security_info_sent));
854 theacl = smbacl4_win2nfs4(fsp->fsp_name->base_name, psd->dacl, ¶ms,
855 sbuf.st_ex_uid, sbuf.st_ex_gid);
857 return map_nt_error_from_unix(errno);
859 smbacl4_dump_nfs4acl(10, theacl);
861 if (set_acl_as_root) {
864 result = set_nfs4_native(fsp, theacl);
866 if (set_acl_as_root) {
871 DEBUG(10, ("set_nfs4_native failed with %s\n", strerror(errno)));
872 return map_nt_error_from_unix(errno);
875 DEBUG(10, ("smb_set_nt_acl_nfs4 succeeded\n"));