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(void)
147 TALLOC_CTX
*mem_ctx
= talloc_tos();
148 SMB_ACL4_INT_T
*theacl
= (SMB_ACL4_INT_T
*)TALLOC_ZERO_SIZE(
149 mem_ctx
, sizeof(SMB_ACL4_INT_T
));
152 DEBUG(0, ("TALLOC_SIZE failed\n"));
156 theacl
->magic
= SMB_ACL4_INT_MAGIC
;
157 /* theacl->first, last = NULL not needed */
158 return (SMB4ACL_T
*)theacl
;
161 SMB4ACE_T
*smb_add_ace4(SMB4ACL_T
*theacl
, SMB_ACE4PROP_T
*prop
)
163 SMB_ACL4_INT_T
*aclint
= get_validated_aclint(theacl
);
164 TALLOC_CTX
*mem_ctx
= talloc_tos();
167 ace
= (SMB_ACE4_INT_T
*)TALLOC_ZERO_SIZE(
168 mem_ctx
, sizeof(SMB_ACE4_INT_T
));
171 DEBUG(0, ("TALLOC_SIZE failed\n"));
175 ace
->magic
= SMB_ACE4_INT_MAGIC
;
176 /* ace->next = NULL not needed */
177 memcpy(&ace
->prop
, prop
, sizeof(SMB_ACE4PROP_T
));
179 if (aclint
->first
==NULL
)
184 aclint
->last
->next
= (void *)ace
;
189 return (SMB4ACE_T
*)ace
;
192 SMB_ACE4PROP_T
*smb_get_ace4(SMB4ACE_T
*ace
)
194 SMB_ACE4_INT_T
*aceint
= get_validated_aceint(ace
);
198 return &aceint
->prop
;
201 SMB4ACE_T
*smb_next_ace4(SMB4ACE_T
*ace
)
203 SMB_ACE4_INT_T
*aceint
= get_validated_aceint(ace
);
207 return (SMB4ACE_T
*)aceint
->next
;
210 SMB4ACE_T
*smb_first_ace4(SMB4ACL_T
*theacl
)
212 SMB_ACL4_INT_T
*aclint
= get_validated_aclint(theacl
);
216 return (SMB4ACE_T
*)aclint
->first
;
219 uint32
smb_get_naces(SMB4ACL_T
*theacl
)
221 SMB_ACL4_INT_T
*aclint
= get_validated_aclint(theacl
);
225 return aclint
->naces
;
228 static int smbacl4_GetFileOwner(struct connection_struct
*conn
,
229 const char *filename
,
230 SMB_STRUCT_STAT
*psbuf
)
232 memset(psbuf
, 0, sizeof(SMB_STRUCT_STAT
));
234 /* Get the stat struct for the owner info. */
235 if (vfs_stat_smb_fname(conn
, filename
, psbuf
) != 0)
237 DEBUG(8, ("vfs_stat_smb_fname failed with error %s\n",
245 static int smbacl4_fGetFileOwner(files_struct
*fsp
, SMB_STRUCT_STAT
*psbuf
)
247 memset(psbuf
, 0, sizeof(SMB_STRUCT_STAT
));
249 if (fsp
->fh
->fd
== -1) {
250 return smbacl4_GetFileOwner(fsp
->conn
,
251 fsp
->fsp_name
->base_name
, psbuf
);
253 if (SMB_VFS_FSTAT(fsp
, psbuf
) != 0)
255 DEBUG(8, ("SMB_VFS_FSTAT failed with error %s\n",
263 static bool smbacl4_nfs42win(TALLOC_CTX
*mem_ctx
, SMB4ACL_T
*theacl
, /* in */
264 struct dom_sid
*psid_owner
, /* in */
265 struct dom_sid
*psid_group
, /* in */
266 bool is_directory
, /* in */
267 struct security_ace
**ppnt_ace_list
, /* out */
268 int *pgood_aces
/* out */
271 SMB_ACL4_INT_T
*aclint
= (SMB_ACL4_INT_T
*)theacl
;
272 SMB_ACE4_INT_T
*aceint
;
273 struct security_ace
*nt_ace_list
= NULL
;
276 DEBUG(10, ("smbacl_nfs42win entered\n"));
278 aclint
= get_validated_aclint(theacl
);
279 /* We do not check for naces being 0 or theacl being NULL here
280 * because it is done upstream */
281 /* in smb_get_nt_acl_nfs4(). */
282 nt_ace_list
= (struct security_ace
*)TALLOC_ZERO_SIZE(
283 mem_ctx
, aclint
->naces
* sizeof(struct security_ace
));
284 if (nt_ace_list
==NULL
)
286 DEBUG(10, ("talloc error"));
291 for (aceint
=aclint
->first
;
293 aceint
=(SMB_ACE4_INT_T
*)aceint
->next
) {
296 SMB_ACE4PROP_T
*ace
= &aceint
->prop
;
297 uint32_t win_ace_flags
;
299 DEBUG(10, ("magic: 0x%x, type: %d, iflags: %x, flags: %x, "
300 "mask: %x, who: %d\n",
301 aceint
->magic
, ace
->aceType
, ace
->flags
,
302 ace
->aceFlags
, ace
->aceMask
, ace
->who
.id
));
304 SMB_ASSERT(aceint
->magic
==SMB_ACE4_INT_MAGIC
);
306 if (ace
->flags
& SMB_ACE4_ID_SPECIAL
) {
307 switch (ace
->who
.special_id
) {
308 case SMB_ACE4_WHO_OWNER
:
309 sid_copy(&sid
, psid_owner
);
311 case SMB_ACE4_WHO_GROUP
:
312 sid_copy(&sid
, psid_group
);
314 case SMB_ACE4_WHO_EVERYONE
:
315 sid_copy(&sid
, &global_sid_World
);
318 DEBUG(8, ("invalid special who id %d "
319 "ignored\n", ace
->who
.special_id
));
323 if (ace
->aceFlags
& SMB_ACE4_IDENTIFIER_GROUP
) {
324 gid_to_sid(&sid
, ace
->who
.gid
);
326 uid_to_sid(&sid
, ace
->who
.uid
);
329 DEBUG(10, ("mapped %d to %s\n", ace
->who
.id
,
330 sid_string_dbg(&sid
)));
332 if (is_directory
&& (ace
->aceMask
& SMB_ACE4_ADD_FILE
)) {
333 ace
->aceMask
|= SMB_ACE4_DELETE_CHILD
;
336 win_ace_flags
= map_nfs4_ace_flags_to_windows_ace_flags(
339 (win_ace_flags
& (SEC_ACE_FLAG_OBJECT_INHERIT
|
340 SEC_ACE_FLAG_CONTAINER_INHERIT
))) {
342 * GPFS sets inherits dir_inhert and file_inherit flags
343 * to files, too, which confuses windows, and seems to
344 * be wrong anyways. ==> Map these bits away for files.
346 DEBUG(10, ("removing inherit flags from nfs4 ace\n"));
347 win_ace_flags
&= ~(SEC_ACE_FLAG_OBJECT_INHERIT
|
348 SEC_ACE_FLAG_CONTAINER_INHERIT
);
350 DEBUG(10, ("Windows mapped ace flags: 0x%x => 0x%x\n",
351 ace
->aceFlags
, win_ace_flags
));
354 /* Windows clients expect SYNC on acls to
355 correctly allow rename. See bug #7909. */
356 /* But not on DENY ace entries. See
358 if(ace
->aceType
== SMB_ACE4_ACCESS_ALLOWED_ACE_TYPE
) {
359 mask
= ace
->aceMask
| SMB_ACE4_SYNCHRONIZE
;
361 init_sec_ace(&nt_ace_list
[good_aces
++], &sid
,
366 *ppnt_ace_list
= nt_ace_list
;
367 *pgood_aces
= good_aces
;
372 static NTSTATUS
smb_get_nt_acl_nfs4_common(const SMB_STRUCT_STAT
*sbuf
,
373 uint32 security_info
,
374 struct security_descriptor
**ppdesc
, SMB4ACL_T
*theacl
)
377 struct dom_sid sid_owner
, sid_group
;
379 struct security_ace
*nt_ace_list
= NULL
;
380 struct security_acl
*psa
= NULL
;
381 TALLOC_CTX
*mem_ctx
= talloc_tos();
383 if (theacl
==NULL
|| smb_get_naces(theacl
)==0)
384 return NT_STATUS_ACCESS_DENIED
; /* special because we
385 * 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"));
395 return map_nt_error_from_unix(errno
);
398 psa
= make_sec_acl(mem_ctx
, NT4_ACL_REVISION
, good_aces
, nt_ace_list
);
400 DEBUG(2,("make_sec_acl failed\n"));
401 return NT_STATUS_NO_MEMORY
;
404 DEBUG(10,("after make sec_acl\n"));
405 *ppdesc
= make_sec_desc(
406 mem_ctx
, SD_REVISION
, SEC_DESC_SELF_RELATIVE
,
407 (security_info
& SECINFO_OWNER
) ? &sid_owner
: NULL
,
408 (security_info
& SECINFO_GROUP
) ? &sid_group
: NULL
,
409 NULL
, psa
, &sd_size
);
411 DEBUG(2,("make_sec_desc failed\n"));
412 return NT_STATUS_NO_MEMORY
;
415 DEBUG(10, ("smb_get_nt_acl_nfs4_common successfully exited with "
417 (int)ndr_size_security_descriptor(*ppdesc
, 0)));
422 NTSTATUS
smb_fget_nt_acl_nfs4(files_struct
*fsp
,
423 uint32 security_info
,
424 struct security_descriptor
**ppdesc
,
427 SMB_STRUCT_STAT sbuf
;
429 DEBUG(10, ("smb_fget_nt_acl_nfs4 invoked for %s\n", fsp_str_dbg(fsp
)));
431 if (smbacl4_fGetFileOwner(fsp
, &sbuf
)) {
432 return map_nt_error_from_unix(errno
);
435 return smb_get_nt_acl_nfs4_common(&sbuf
, security_info
, ppdesc
,
439 NTSTATUS
smb_get_nt_acl_nfs4(struct connection_struct
*conn
,
441 uint32 security_info
,
442 struct security_descriptor
**ppdesc
,
445 SMB_STRUCT_STAT sbuf
;
447 DEBUG(10, ("smb_get_nt_acl_nfs4 invoked for %s\n", name
));
449 if (smbacl4_GetFileOwner(conn
, name
, &sbuf
)) {
450 return map_nt_error_from_unix(errno
);
453 return smb_get_nt_acl_nfs4_common(&sbuf
, security_info
, ppdesc
,
457 enum smbacl4_mode_enum
{e_simple
=0, e_special
=1};
458 enum smbacl4_acedup_enum
{e_dontcare
=0, e_reject
=1, e_ignore
=2, e_merge
=3};
460 typedef struct _smbacl4_vfs_params
{
461 enum smbacl4_mode_enum mode
;
463 enum smbacl4_acedup_enum acedup
;
464 } smbacl4_vfs_params
;
467 * Gather special parameters for NFS4 ACL handling
469 static int smbacl4_get_vfs_params(
470 const char *type_name
,
472 smbacl4_vfs_params
*params
475 static const struct enum_list enum_smbacl4_modes
[] = {
476 { e_simple
, "simple" },
477 { e_special
, "special" },
480 static const struct enum_list enum_smbacl4_acedups
[] = {
481 { e_dontcare
, "dontcare" },
482 { e_reject
, "reject" },
483 { e_ignore
, "ignore" },
484 { e_merge
, "merge" },
488 memset(params
, 0, sizeof(smbacl4_vfs_params
));
489 params
->mode
= (enum smbacl4_mode_enum
)lp_parm_enum(
490 SNUM(fsp
->conn
), type_name
,
491 "mode", enum_smbacl4_modes
, e_simple
);
492 params
->do_chown
= lp_parm_bool(SNUM(fsp
->conn
), type_name
,
494 params
->acedup
= (enum smbacl4_acedup_enum
)lp_parm_enum(
495 SNUM(fsp
->conn
), type_name
,
496 "acedup", enum_smbacl4_acedups
, e_dontcare
);
498 DEBUG(10, ("mode:%s, do_chown:%s, acedup: %s\n",
499 enum_smbacl4_modes
[params
->mode
].name
,
500 params
->do_chown
? "true" : "false",
501 enum_smbacl4_acedups
[params
->acedup
].name
));
506 static void smbacl4_dump_nfs4acl(int level
, SMB4ACL_T
*theacl
)
508 SMB_ACL4_INT_T
*aclint
= get_validated_aclint(theacl
);
509 SMB_ACE4_INT_T
*aceint
;
511 DEBUG(level
, ("NFS4ACL: size=%d\n", aclint
->naces
));
513 for (aceint
= aclint
->first
;
515 aceint
=(SMB_ACE4_INT_T
*)aceint
->next
) {
516 SMB_ACE4PROP_T
*ace
= &aceint
->prop
;
518 DEBUG(level
, ("\tACE: type=%d, flags=0x%x, fflags=0x%x, "
519 "mask=0x%x, id=%d\n",
521 ace
->aceFlags
, ace
->flags
,
528 * Find 2 NFS4 who-special ACE property (non-copy!!!)
529 * match nonzero if "special" and who is equal
530 * return ace if found matching; otherwise NULL
532 static SMB_ACE4PROP_T
*smbacl4_find_equal_special(
534 SMB_ACE4PROP_T
*aceNew
)
536 SMB_ACL4_INT_T
*aclint
= get_validated_aclint(theacl
);
537 SMB_ACE4_INT_T
*aceint
;
539 for (aceint
= aclint
->first
; aceint
!= NULL
;
540 aceint
=(SMB_ACE4_INT_T
*)aceint
->next
) {
541 SMB_ACE4PROP_T
*ace
= &aceint
->prop
;
543 DEBUG(10,("ace type:0x%x flags:0x%x aceFlags:0x%x "
544 "new type:0x%x flags:0x%x aceFlags:0x%x\n",
545 ace
->aceType
, ace
->flags
, ace
->aceFlags
,
546 aceNew
->aceType
, aceNew
->flags
,aceNew
->aceFlags
));
548 if (ace
->flags
== aceNew
->flags
&&
549 ace
->aceType
==aceNew
->aceType
&&
550 ace
->aceFlags
==aceNew
->aceFlags
)
552 /* keep type safety; e.g. gid is an u.short */
553 if (ace
->flags
& SMB_ACE4_ID_SPECIAL
)
555 if (ace
->who
.special_id
==
556 aceNew
->who
.special_id
)
559 if (ace
->aceFlags
& SMB_ACE4_IDENTIFIER_GROUP
)
561 if (ace
->who
.gid
==aceNew
->who
.gid
)
564 if (ace
->who
.uid
==aceNew
->who
.uid
)
575 static bool smbacl4_fill_ace4(
577 const struct smb_filename
*filename
,
578 smbacl4_vfs_params
*params
,
581 const struct security_ace
*ace_nt
, /* input */
582 SMB_ACE4PROP_T
*ace_v4
/* output */
585 DEBUG(10, ("got ace for %s\n", sid_string_dbg(&ace_nt
->trustee
)));
587 memset(ace_v4
, 0, sizeof(SMB_ACE4PROP_T
));
589 /* only ACCESS|DENY supported right now */
590 ace_v4
->aceType
= ace_nt
->type
;
592 ace_v4
->aceFlags
= map_windows_ace_flags_to_nfs4_ace_flags(
595 /* remove inheritance flags on files */
596 if (VALID_STAT(filename
->st
) &&
597 !S_ISDIR(filename
->st
.st_ex_mode
)) {
598 DEBUG(10, ("Removing inheritance flags from a file\n"));
599 ace_v4
->aceFlags
&= ~(SMB_ACE4_FILE_INHERIT_ACE
|
600 SMB_ACE4_DIRECTORY_INHERIT_ACE
|
601 SMB_ACE4_NO_PROPAGATE_INHERIT_ACE
|
602 SMB_ACE4_INHERIT_ONLY_ACE
);
605 ace_v4
->aceMask
= ace_nt
->access_mask
&
606 (SEC_STD_ALL
| SEC_FILE_ALL
);
608 se_map_generic(&ace_v4
->aceMask
, &file_generic_mapping
);
610 if (ace_v4
->aceFlags
!=ace_nt
->flags
)
611 DEBUG(9, ("ace_v4->aceFlags(0x%x)!=ace_nt->flags(0x%x)\n",
612 ace_v4
->aceFlags
, ace_nt
->flags
));
614 if (ace_v4
->aceMask
!=ace_nt
->access_mask
)
615 DEBUG(9, ("ace_v4->aceMask(0x%x)!=ace_nt->access_mask(0x%x)\n",
616 ace_v4
->aceMask
, ace_nt
->access_mask
));
618 if (dom_sid_equal(&ace_nt
->trustee
, &global_sid_World
)) {
619 ace_v4
->who
.special_id
= SMB_ACE4_WHO_EVERYONE
;
620 ace_v4
->flags
|= SMB_ACE4_ID_SPECIAL
;
625 if (sid_to_gid(&ace_nt
->trustee
, &gid
)) {
626 ace_v4
->aceFlags
|= SMB_ACE4_IDENTIFIER_GROUP
;
628 if (params
->mode
==e_special
&& gid
==ownerGID
) {
629 ace_v4
->flags
|= SMB_ACE4_ID_SPECIAL
;
630 ace_v4
->who
.special_id
= SMB_ACE4_WHO_GROUP
;
632 ace_v4
->who
.gid
= gid
;
634 } else if (sid_to_uid(&ace_nt
->trustee
, &uid
)) {
635 if (params
->mode
==e_special
&& uid
==ownerUID
) {
636 ace_v4
->flags
|= SMB_ACE4_ID_SPECIAL
;
637 ace_v4
->who
.special_id
= SMB_ACE4_WHO_OWNER
;
639 ace_v4
->who
.uid
= uid
;
642 DEBUG(1, ("nfs4_acls.c: file [%s]: could not "
643 "convert %s to uid or gid\n",
645 sid_string_dbg(&ace_nt
->trustee
)));
650 return True
; /* OK */
653 static int smbacl4_MergeIgnoreReject(
654 enum smbacl4_acedup_enum acedup
,
655 SMB4ACL_T
*theacl
, /* may modify it */
656 SMB_ACE4PROP_T
*ace
, /* the "new" ACE */
662 SMB_ACE4PROP_T
*ace4found
= smbacl4_find_equal_special(theacl
, ace
);
667 case e_merge
: /* "merge" flags */
669 ace4found
->aceFlags
|= ace
->aceFlags
;
670 ace4found
->aceMask
|= ace
->aceMask
;
672 case e_ignore
: /* leave out this record */
675 case e_reject
: /* do an error */
676 DEBUG(8, ("ACL rejected by duplicate nt ace#%d\n", i
));
677 errno
= EINVAL
; /* SHOULD be set on any _real_ error */
687 static SMB4ACL_T
*smbacl4_win2nfs4(
688 const files_struct
*fsp
,
689 const struct security_acl
*dacl
,
690 smbacl4_vfs_params
*pparams
,
697 TALLOC_CTX
*mem_ctx
= talloc_tos();
698 const char *filename
= fsp
->fsp_name
->base_name
;
700 DEBUG(10, ("smbacl4_win2nfs4 invoked\n"));
702 theacl
= smb_create_smb4acl();
706 for(i
=0; i
<dacl
->num_aces
; i
++) {
707 SMB_ACE4PROP_T ace_v4
;
708 bool addNewACE
= True
;
710 if (!smbacl4_fill_ace4(mem_ctx
, fsp
->fsp_name
, pparams
,
712 dacl
->aces
+ i
, &ace_v4
)) {
713 DEBUG(3, ("Could not fill ace for file %s, SID %s\n",
715 sid_string_dbg(&((dacl
->aces
+i
)->trustee
))));
719 if (pparams
->acedup
!=e_dontcare
) {
720 if (smbacl4_MergeIgnoreReject(pparams
->acedup
, theacl
,
721 &ace_v4
, &addNewACE
, i
))
726 smb_add_ace4(theacl
, &ace_v4
);
732 NTSTATUS
smb_set_nt_acl_nfs4(files_struct
*fsp
,
733 uint32 security_info_sent
,
734 const struct security_descriptor
*psd
,
735 set_nfs4acl_native_fn_t set_nfs4_native
)
737 smbacl4_vfs_params params
;
738 SMB4ACL_T
*theacl
= NULL
;
741 SMB_STRUCT_STAT sbuf
;
742 bool set_acl_as_root
= false;
743 uid_t newUID
= (uid_t
)-1;
744 gid_t newGID
= (gid_t
)-1;
747 DEBUG(10, ("smb_set_nt_acl_nfs4 invoked for %s\n", fsp_str_dbg(fsp
)));
749 if ((security_info_sent
& (SECINFO_DACL
|
750 SECINFO_GROUP
| SECINFO_OWNER
)) == 0)
752 DEBUG(9, ("security_info_sent (0x%x) ignored\n",
753 security_info_sent
));
754 return NT_STATUS_OK
; /* won't show error - later to be
758 /* Special behaviours */
759 if (smbacl4_get_vfs_params(SMBACL4_PARAM_TYPE_NAME
, fsp
, ¶ms
))
760 return NT_STATUS_NO_MEMORY
;
762 if (smbacl4_fGetFileOwner(fsp
, &sbuf
))
763 return map_nt_error_from_unix(errno
);
765 if (params
.do_chown
) {
766 /* chown logic is a copy/paste from posix_acl.c:set_nt_acl */
767 NTSTATUS status
= unpack_nt_owners(fsp
->conn
, &newUID
, &newGID
,
768 security_info_sent
, psd
);
769 if (!NT_STATUS_IS_OK(status
)) {
770 DEBUG(8, ("unpack_nt_owners failed"));
773 if (((newUID
!= (uid_t
)-1) && (sbuf
.st_ex_uid
!= newUID
)) ||
774 ((newGID
!= (gid_t
)-1) && (sbuf
.st_ex_gid
!= newGID
))) {
776 status
= try_chown(fsp
, newUID
, newGID
);
777 if (!NT_STATUS_IS_OK(status
)) {
778 DEBUG(3,("chown %s, %u, %u failed. Error = "
779 "%s.\n", fsp_str_dbg(fsp
),
780 (unsigned int)newUID
,
781 (unsigned int)newGID
,
786 DEBUG(10,("chown %s, %u, %u succeeded.\n",
787 fsp_str_dbg(fsp
), (unsigned int)newUID
,
788 (unsigned int)newGID
));
789 if (smbacl4_GetFileOwner(fsp
->conn
,
790 fsp
->fsp_name
->base_name
,
792 return map_nt_error_from_unix(errno
);
794 /* If we successfully chowned, we know we must
795 * be able to set the acl, so do it as root.
797 set_acl_as_root
= true;
801 if (!(security_info_sent
& SECINFO_DACL
) || psd
->dacl
==NULL
) {
802 DEBUG(10, ("no dacl found; security_info_sent = 0x%x\n",
803 security_info_sent
));
807 theacl
= smbacl4_win2nfs4(fsp
, psd
->dacl
, ¶ms
,
808 sbuf
.st_ex_uid
, sbuf
.st_ex_gid
);
810 return map_nt_error_from_unix(errno
);
812 smbacl4_dump_nfs4acl(10, theacl
);
814 if (set_acl_as_root
) {
817 result
= set_nfs4_native(fsp
, theacl
);
819 if (set_acl_as_root
) {
824 DEBUG(10, ("set_nfs4_native failed with %s\n",
826 return map_nt_error_from_unix(errno
);
829 DEBUG(10, ("smb_set_nt_acl_nfs4 succeeded\n"));