4 * Copyright (C) Jim McDonough, 2006
5 * Copyright (C) Christof Schmitt 2019
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.
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.
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/>.
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"
33 #include "lib/param/loadparm.h"
36 #define DBGC_CLASS DBGC_ACLS
38 #define SMBACL4_PARAM_TYPE_NAME "nfs4"
40 extern const struct generic_mapping file_generic_mapping
;
45 struct SMB4ACE_T
*next
;
50 uint16_t controlflags
;
52 struct SMB4ACE_T
*first
;
53 struct SMB4ACE_T
*last
;
57 * Gather special parameters for NFS4 ACL handling
59 int smbacl4_get_vfs_params(struct connection_struct
*conn
,
60 struct smbacl4_vfs_params
*params
)
62 static const struct enum_list enum_smbacl4_modes
[] = {
63 { e_simple
, "simple" },
64 { e_special
, "special" },
67 static const struct enum_list enum_smbacl4_acedups
[] = {
68 { e_dontcare
, "dontcare" },
69 { e_reject
, "reject" },
70 { e_ignore
, "ignore" },
76 *params
= (struct smbacl4_vfs_params
) { 0 };
78 enumval
= lp_parm_enum(SNUM(conn
), SMBACL4_PARAM_TYPE_NAME
, "mode",
79 enum_smbacl4_modes
, e_simple
);
81 DEBUG(10, ("value for %s:mode unknown\n",
82 SMBACL4_PARAM_TYPE_NAME
));
85 params
->mode
= (enum smbacl4_mode_enum
)enumval
;
86 if (params
->mode
== e_special
) {
87 DBG_WARNING("nfs4:mode special is deprecated.\n");
90 params
->do_chown
= lp_parm_bool(SNUM(conn
), SMBACL4_PARAM_TYPE_NAME
,
93 enumval
= lp_parm_enum(SNUM(conn
), SMBACL4_PARAM_TYPE_NAME
, "acedup",
94 enum_smbacl4_acedups
, e_merge
);
96 DEBUG(10, ("value for %s:acedup unknown\n",
97 SMBACL4_PARAM_TYPE_NAME
));
100 params
->acedup
= (enum smbacl4_acedup_enum
)enumval
;
101 if (params
->acedup
== e_ignore
) {
102 DBG_WARNING("nfs4:acedup ignore is deprecated.\n");
104 if (params
->acedup
== e_reject
) {
105 DBG_WARNING("nfs4:acedup ignore is deprecated.\n");
108 params
->map_full_control
= lp_acl_map_full_control(SNUM(conn
));
110 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"));
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 ************************************************/
126 static uint32_t map_nfs4_ace_flags_to_windows_ace_flags(
127 uint32_t nfs4_ace_flags
)
129 uint32_t win_ace_flags
= 0;
131 /* The nfs4 flags <= 0xf map perfectly. */
132 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
);
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 if (nfs4_ace_flags
& SMB_ACE4_INHERITED_ACE
) {
143 win_ace_flags
|= SEC_ACE_FLAG_INHERITED_ACE
;
146 return win_ace_flags
;
149 static uint32_t map_windows_ace_flags_to_nfs4_ace_flags(uint32_t win_ace_flags
)
151 uint32_t nfs4_ace_flags
= 0;
153 /* The windows flags <= 0xf map perfectly. */
154 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
);
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 if (win_ace_flags
& SEC_ACE_FLAG_INHERITED_ACE
) {
165 nfs4_ace_flags
|= SMB_ACE4_INHERITED_ACE
;
168 return nfs4_ace_flags
;
171 struct SMB4ACL_T
*smb_create_smb4acl(TALLOC_CTX
*mem_ctx
)
173 struct SMB4ACL_T
*theacl
;
175 theacl
= talloc_zero(mem_ctx
, struct SMB4ACL_T
);
178 DEBUG(0, ("TALLOC_SIZE failed\n"));
182 theacl
->controlflags
= SEC_DESC_SELF_RELATIVE
;
183 /* theacl->first, last = NULL not needed */
187 struct SMB4ACE_T
*smb_add_ace4(struct SMB4ACL_T
*acl
, SMB_ACE4PROP_T
*prop
)
189 struct SMB4ACE_T
*ace
;
191 ace
= talloc_zero(acl
, struct SMB4ACE_T
);
194 DBG_ERR("talloc_zero failed\n");
200 if (acl
->first
==NULL
)
205 acl
->last
->next
= ace
;
213 SMB_ACE4PROP_T
*smb_get_ace4(struct SMB4ACE_T
*ace
)
222 struct SMB4ACE_T
*smb_next_ace4(struct SMB4ACE_T
*ace
)
231 struct SMB4ACE_T
*smb_first_ace4(struct SMB4ACL_T
*acl
)
240 uint32_t smb_get_naces(struct SMB4ACL_T
*acl
)
249 uint16_t smbacl4_get_controlflags(struct SMB4ACL_T
*acl
)
255 return acl
->controlflags
;
258 bool smbacl4_set_controlflags(struct SMB4ACL_T
*acl
, uint16_t controlflags
)
264 acl
->controlflags
= controlflags
;
268 bool nfs_ace_is_inherit(SMB_ACE4PROP_T
*ace
)
270 return ace
->aceFlags
& (SMB_ACE4_INHERIT_ONLY_ACE
|
271 SMB_ACE4_FILE_INHERIT_ACE
|
272 SMB_ACE4_DIRECTORY_INHERIT_ACE
);
275 static int smbacl4_GetFileOwner(struct connection_struct
*conn
,
276 const struct smb_filename
*smb_fname
,
277 SMB_STRUCT_STAT
*psbuf
)
281 /* Get the stat struct for the owner info. */
282 if (vfs_stat_smb_basename(conn
, smb_fname
, psbuf
) != 0)
284 DEBUG(8, ("vfs_stat_smb_basename failed with error %s\n",
292 static void check_for_duplicate_sec_ace(struct security_ace
*nt_ace_list
,
295 struct security_ace
*last
= NULL
;
298 if (*good_aces
< 2) {
302 last
= &nt_ace_list
[(*good_aces
) - 1];
304 for (i
= 0; i
< (*good_aces
) - 1; i
++) {
305 struct security_ace
*cur
= &nt_ace_list
[i
];
307 if (cur
->type
== last
->type
&&
308 cur
->flags
== last
->flags
&&
309 cur
->access_mask
== last
->access_mask
&&
310 dom_sid_equal(&cur
->trustee
, &last
->trustee
))
312 struct dom_sid_buf sid_buf
;
314 DBG_INFO("Removing duplicate entry for SID %s.\n",
315 dom_sid_str_buf(&last
->trustee
, &sid_buf
));
321 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 */
331 struct SMB4ACE_T
*aceint
;
332 struct security_ace
*nt_ace_list
= NULL
;
335 DEBUG(10, ("%s entered\n", __func__
));
337 nt_ace_list
= talloc_zero_array(mem_ctx
, struct security_ace
,
339 if (nt_ace_list
==NULL
)
341 DEBUG(10, ("talloc error with %d aces", acl
->naces
));
346 for (aceint
= acl
->first
; aceint
!= NULL
; aceint
= aceint
->next
) {
349 struct dom_sid_buf buf
;
350 SMB_ACE4PROP_T
*ace
= &aceint
->prop
;
351 uint32_t win_ace_flags
;
353 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
));
358 if (ace
->flags
& SMB_ACE4_ID_SPECIAL
) {
359 switch (ace
->who
.special_id
) {
360 case SMB_ACE4_WHO_OWNER
:
361 sid_copy(&sid
, psid_owner
);
363 case SMB_ACE4_WHO_GROUP
:
364 sid_copy(&sid
, psid_group
);
366 case SMB_ACE4_WHO_EVERYONE
:
367 sid_copy(&sid
, &global_sid_World
);
370 DEBUG(8, ("invalid special who id %d "
371 "ignored\n", ace
->who
.special_id
));
375 if (ace
->aceFlags
& SMB_ACE4_IDENTIFIER_GROUP
) {
376 gid_to_sid(&sid
, ace
->who
.gid
);
378 uid_to_sid(&sid
, ace
->who
.uid
);
381 DEBUG(10, ("mapped %d to %s\n", ace
->who
.id
,
382 dom_sid_str_buf(&sid
, &buf
)));
384 if (!is_directory
&& params
->map_full_control
) {
386 * Do we have all access except DELETE_CHILD
387 * (not caring about the delete bit).
389 uint32_t test_mask
= ((ace
->aceMask
|SMB_ACE4_DELETE
|SMB_ACE4_DELETE_CHILD
) &
391 if (test_mask
== SMB_ACE4_ALL_MASKS
) {
392 ace
->aceMask
|= SMB_ACE4_DELETE_CHILD
;
396 win_ace_flags
= map_nfs4_ace_flags_to_windows_ace_flags(
399 (win_ace_flags
& (SEC_ACE_FLAG_OBJECT_INHERIT
|
400 SEC_ACE_FLAG_CONTAINER_INHERIT
))) {
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.
406 DEBUG(10, ("removing inherit flags from nfs4 ace\n"));
407 win_ace_flags
&= ~(SEC_ACE_FLAG_OBJECT_INHERIT
|
408 SEC_ACE_FLAG_CONTAINER_INHERIT
);
410 DEBUG(10, ("Windows mapped ace flags: 0x%x => 0x%x\n",
411 ace
->aceFlags
, win_ace_flags
));
415 /* Mapping of owner@ and group@ to creator owner and
416 creator group. Keep old behavior in mode special. */
417 if (params
->mode
!= e_special
&&
418 ace
->flags
& SMB_ACE4_ID_SPECIAL
&&
419 (ace
->who
.special_id
== SMB_ACE4_WHO_OWNER
||
420 ace
->who
.special_id
== SMB_ACE4_WHO_GROUP
)) {
421 DEBUG(10, ("Map special entry\n"));
422 if (!(win_ace_flags
& SEC_ACE_FLAG_INHERIT_ONLY
)) {
423 uint32_t win_ace_flags_current
;
424 DEBUG(10, ("Map current sid\n"));
425 win_ace_flags_current
= win_ace_flags
&
426 ~(SEC_ACE_FLAG_OBJECT_INHERIT
|
427 SEC_ACE_FLAG_CONTAINER_INHERIT
);
428 init_sec_ace(&nt_ace_list
[good_aces
++], &sid
,
430 win_ace_flags_current
);
432 if (ace
->who
.special_id
== SMB_ACE4_WHO_OWNER
&&
433 win_ace_flags
& (SEC_ACE_FLAG_OBJECT_INHERIT
|
434 SEC_ACE_FLAG_CONTAINER_INHERIT
)) {
435 uint32_t win_ace_flags_creator
;
436 DEBUG(10, ("Map creator owner\n"));
437 win_ace_flags_creator
= win_ace_flags
|
438 SMB_ACE4_INHERIT_ONLY_ACE
;
439 init_sec_ace(&nt_ace_list
[good_aces
++],
440 &global_sid_Creator_Owner
,
442 win_ace_flags_creator
);
444 if (ace
->who
.special_id
== SMB_ACE4_WHO_GROUP
&&
445 win_ace_flags
& (SEC_ACE_FLAG_OBJECT_INHERIT
|
446 SEC_ACE_FLAG_CONTAINER_INHERIT
)) {
447 uint32_t win_ace_flags_creator
;
448 DEBUG(10, ("Map creator owner group\n"));
449 win_ace_flags_creator
= win_ace_flags
|
450 SMB_ACE4_INHERIT_ONLY_ACE
;
451 init_sec_ace(&nt_ace_list
[good_aces
++],
452 &global_sid_Creator_Group
,
454 win_ace_flags_creator
);
457 DEBUG(10, ("Map normal sid\n"));
458 init_sec_ace(&nt_ace_list
[good_aces
++], &sid
,
463 check_for_duplicate_sec_ace(nt_ace_list
, &good_aces
);
466 nt_ace_list
= talloc_realloc(mem_ctx
, nt_ace_list
, struct security_ace
,
469 /* returns a NULL ace list when good_aces is zero. */
470 if (good_aces
&& nt_ace_list
== NULL
) {
471 DEBUG(10, ("realloc error with %d aces", good_aces
));
476 *ppnt_ace_list
= nt_ace_list
;
477 *pgood_aces
= good_aces
;
482 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
,
486 struct security_descriptor
**ppdesc
,
487 struct SMB4ACL_T
*theacl
)
490 struct dom_sid sid_owner
, sid_group
;
492 struct security_ace
*nt_ace_list
= NULL
;
493 struct security_acl
*psa
= NULL
;
494 TALLOC_CTX
*frame
= talloc_stackframe();
499 return NT_STATUS_ACCESS_DENIED
; /* special because we
500 * need to think through
504 uid_to_sid(&sid_owner
, sbuf
->st_ex_uid
);
505 gid_to_sid(&sid_group
, sbuf
->st_ex_gid
);
507 ok
= smbacl4_nfs42win(frame
, params
, theacl
, &sid_owner
, &sid_group
,
508 S_ISDIR(sbuf
->st_ex_mode
),
509 &nt_ace_list
, &good_aces
);
511 DEBUG(8,("smbacl4_nfs42win failed\n"));
513 return map_nt_error_from_unix(errno
);
516 psa
= make_sec_acl(frame
, NT4_ACL_REVISION
, good_aces
, nt_ace_list
);
518 DEBUG(2,("make_sec_acl failed\n"));
520 return NT_STATUS_NO_MEMORY
;
523 DEBUG(10,("after make sec_acl\n"));
524 *ppdesc
= make_sec_desc(
525 mem_ctx
, SD_REVISION
, smbacl4_get_controlflags(theacl
),
526 (security_info
& SECINFO_OWNER
) ? &sid_owner
: NULL
,
527 (security_info
& SECINFO_GROUP
) ? &sid_group
: NULL
,
528 NULL
, psa
, &sd_size
);
530 DEBUG(2,("make_sec_desc failed\n"));
532 return NT_STATUS_NO_MEMORY
;
535 DEBUG(10, ("smb_get_nt_acl_nfs4_common successfully exited with "
537 (int)ndr_size_security_descriptor(*ppdesc
, 0)));
543 NTSTATUS
smb_fget_nt_acl_nfs4(files_struct
*fsp
,
544 const struct smbacl4_vfs_params
*pparams
,
545 uint32_t security_info
,
547 struct security_descriptor
**ppdesc
,
548 struct SMB4ACL_T
*theacl
)
550 struct smbacl4_vfs_params params
;
552 DEBUG(10, ("smb_fget_nt_acl_nfs4 invoked for %s\n", fsp_str_dbg(fsp
)));
554 if (!VALID_STAT(fsp
->fsp_name
->st
)) {
557 status
= vfs_stat_fsp(fsp
);
558 if (!NT_STATUS_IS_OK(status
)) {
563 if (pparams
== NULL
) {
564 /* Special behaviours */
565 if (smbacl4_get_vfs_params(fsp
->conn
, ¶ms
)) {
566 return NT_STATUS_NO_MEMORY
;
571 return smb_get_nt_acl_nfs4_common(&fsp
->fsp_name
->st
, pparams
,
573 mem_ctx
, ppdesc
, theacl
);
576 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
,
581 struct security_descriptor
**ppdesc
,
582 struct SMB4ACL_T
*theacl
)
584 SMB_STRUCT_STAT sbuf
;
585 struct smbacl4_vfs_params params
;
586 const SMB_STRUCT_STAT
*psbuf
= NULL
;
588 DEBUG(10, ("smb_get_nt_acl_nfs4 invoked for %s\n",
589 smb_fname
->base_name
));
591 if (VALID_STAT(smb_fname
->st
)) {
592 psbuf
= &smb_fname
->st
;
596 if (smbacl4_GetFileOwner(conn
, smb_fname
, &sbuf
)) {
597 return map_nt_error_from_unix(errno
);
602 if (pparams
== NULL
) {
603 /* Special behaviours */
604 if (smbacl4_get_vfs_params(conn
, ¶ms
)) {
605 return NT_STATUS_NO_MEMORY
;
610 return smb_get_nt_acl_nfs4_common(psbuf
, pparams
, security_info
,
611 mem_ctx
, ppdesc
, theacl
);
614 static void smbacl4_dump_nfs4acl(int level
, struct SMB4ACL_T
*acl
)
616 struct SMB4ACE_T
*aceint
;
618 DEBUG(level
, ("NFS4ACL: size=%d\n", acl
->naces
));
620 for (aceint
= acl
->first
; aceint
!= NULL
; aceint
= aceint
->next
) {
621 SMB_ACE4PROP_T
*ace
= &aceint
->prop
;
623 DEBUG(level
, ("\tACE: type=%d, flags=0x%x, fflags=0x%x, "
624 "mask=0x%x, id=%d\n",
626 ace
->aceFlags
, ace
->flags
,
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
637 static SMB_ACE4PROP_T
*smbacl4_find_equal_special(
638 struct SMB4ACL_T
*acl
,
639 SMB_ACE4PROP_T
*aceNew
)
641 struct SMB4ACE_T
*aceint
;
643 for (aceint
= acl
->first
; aceint
!= NULL
; aceint
= aceint
->next
) {
644 SMB_ACE4PROP_T
*ace
= &aceint
->prop
;
646 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
));
651 if (ace
->flags
== aceNew
->flags
&&
652 ace
->aceType
==aceNew
->aceType
&&
653 ace
->aceFlags
==aceNew
->aceFlags
)
655 /* keep type safety; e.g. gid is an u.short */
656 if (ace
->flags
& SMB_ACE4_ID_SPECIAL
)
658 if (ace
->who
.special_id
==
659 aceNew
->who
.special_id
)
662 if (ace
->aceFlags
& SMB_ACE4_IDENTIFIER_GROUP
)
664 if (ace
->who
.gid
==aceNew
->who
.gid
)
667 if (ace
->who
.uid
==aceNew
->who
.uid
)
677 static int smbacl4_MergeIgnoreReject(enum smbacl4_acedup_enum acedup
,
678 struct SMB4ACL_T
*theacl
,
683 SMB_ACE4PROP_T
*ace4found
= smbacl4_find_equal_special(theacl
, ace
);
688 case e_merge
: /* "merge" flags */
690 ace4found
->aceFlags
|= ace
->aceFlags
;
691 ace4found
->aceMask
|= ace
->aceMask
;
693 case e_ignore
: /* leave out this record */
696 case e_reject
: /* do an error */
697 DBG_INFO("ACL rejected by duplicate nt ace.\n");
698 errno
= EINVAL
; /* SHOULD be set on any _real_ error */
708 static int nfs4_acl_add_ace(enum smbacl4_acedup_enum acedup
,
709 struct SMB4ACL_T
*nfs4_acl
,
710 SMB_ACE4PROP_T
*nfs4_ace
)
714 if (acedup
!= e_dontcare
) {
717 ret
= smbacl4_MergeIgnoreReject(acedup
, nfs4_acl
,
725 smb_add_ace4(nfs4_acl
, nfs4_ace
);
731 static int nfs4_acl_add_sec_ace(bool is_directory
,
732 const struct smbacl4_vfs_params
*params
,
735 const struct security_ace
*ace_nt
,
736 struct SMB4ACL_T
*nfs4_acl
)
738 struct dom_sid_buf buf
;
739 SMB_ACE4PROP_T nfs4_ace
= { 0 };
740 SMB_ACE4PROP_T nfs4_ace_2
= { 0 };
741 bool add_ace2
= false;
744 DEBUG(10, ("got ace for %s\n",
745 dom_sid_str_buf(&ace_nt
->trustee
, &buf
)));
747 /* only ACCESS|DENY supported right now */
748 nfs4_ace
.aceType
= ace_nt
->type
;
751 map_windows_ace_flags_to_nfs4_ace_flags(ace_nt
->flags
);
753 /* remove inheritance flags on files */
755 DEBUG(10, ("Removing inheritance flags from a file\n"));
756 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
);
762 nfs4_ace
.aceMask
= ace_nt
->access_mask
& (SEC_STD_ALL
| SEC_FILE_ALL
);
764 se_map_generic(&nfs4_ace
.aceMask
, &file_generic_mapping
);
766 if (dom_sid_equal(&ace_nt
->trustee
, &global_sid_World
)) {
767 nfs4_ace
.who
.special_id
= SMB_ACE4_WHO_EVERYONE
;
768 nfs4_ace
.flags
|= SMB_ACE4_ID_SPECIAL
;
769 } else if (params
->mode
!=e_special
&&
770 dom_sid_equal(&ace_nt
->trustee
,
771 &global_sid_Creator_Owner
)) {
772 DEBUG(10, ("Map creator owner\n"));
773 nfs4_ace
.who
.special_id
= SMB_ACE4_WHO_OWNER
;
774 nfs4_ace
.flags
|= SMB_ACE4_ID_SPECIAL
;
775 /* A non inheriting creator owner entry has no effect. */
776 nfs4_ace
.aceFlags
|= SMB_ACE4_INHERIT_ONLY_ACE
;
777 if (!(nfs4_ace
.aceFlags
& SMB_ACE4_DIRECTORY_INHERIT_ACE
)
778 && !(nfs4_ace
.aceFlags
& SMB_ACE4_FILE_INHERIT_ACE
)) {
781 } else if (params
->mode
!=e_special
&&
782 dom_sid_equal(&ace_nt
->trustee
,
783 &global_sid_Creator_Group
)) {
784 DEBUG(10, ("Map creator owner group\n"));
785 nfs4_ace
.who
.special_id
= SMB_ACE4_WHO_GROUP
;
786 nfs4_ace
.flags
|= SMB_ACE4_ID_SPECIAL
;
787 /* A non inheriting creator group entry has no effect. */
788 nfs4_ace
.aceFlags
|= SMB_ACE4_INHERIT_ONLY_ACE
;
789 if (!(nfs4_ace
.aceFlags
& SMB_ACE4_DIRECTORY_INHERIT_ACE
)
790 && !(nfs4_ace
.aceFlags
& SMB_ACE4_FILE_INHERIT_ACE
)) {
794 struct unixid unixid
;
797 ok
= sids_to_unixids(&ace_nt
->trustee
, 1, &unixid
);
799 DBG_WARNING("Could not convert %s to uid or gid.\n",
800 dom_sid_str_buf(&ace_nt
->trustee
, &buf
));
804 if (dom_sid_compare_domain(&ace_nt
->trustee
,
805 &global_sid_Unix_NFS
) == 0) {
809 switch (unixid
.type
) {
811 nfs4_ace
.aceFlags
|= SMB_ACE4_IDENTIFIER_GROUP
;
812 nfs4_ace
.who
.gid
= unixid
.id
;
814 if (ownerUID
== unixid
.id
&&
815 !nfs_ace_is_inherit(&nfs4_ace
))
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.
823 * This only applies to non-inheriting
824 * entries as only these are replaced
825 * with SPECIAL_OWNER in nfs4:mode=simple.
827 nfs4_ace_2
= (SMB_ACE4PROP_T
) {
828 .who
.uid
= unixid
.id
,
829 .aceFlags
= (nfs4_ace
.aceFlags
&
830 ~SMB_ACE4_IDENTIFIER_GROUP
),
831 .aceMask
= nfs4_ace
.aceMask
,
832 .aceType
= nfs4_ace
.aceType
,
838 nfs4_ace
.aceFlags
|= SMB_ACE4_IDENTIFIER_GROUP
;
839 nfs4_ace
.who
.gid
= unixid
.id
;
842 nfs4_ace
.who
.uid
= unixid
.id
;
844 case ID_TYPE_NOT_SPECIFIED
:
846 DBG_WARNING("Could not convert %s to uid or gid.\n",
847 dom_sid_str_buf(&ace_nt
->trustee
, &buf
));
852 ret
= nfs4_acl_add_ace(params
->acedup
, nfs4_acl
, &nfs4_ace
);
861 return nfs4_acl_add_ace(params
->acedup
, nfs4_acl
, &nfs4_ace_2
);
864 static void smbacl4_substitute_special(struct SMB4ACL_T
*acl
,
868 struct SMB4ACE_T
*aceint
;
870 for (aceint
= acl
->first
; aceint
!= NULL
; aceint
= aceint
->next
) {
871 SMB_ACE4PROP_T
*ace
= &aceint
->prop
;
873 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
));
878 if (!(ace
->flags
& SMB_ACE4_ID_SPECIAL
) &&
879 !(ace
->aceFlags
& SMB_ACE4_IDENTIFIER_GROUP
) &&
880 ace
->who
.uid
== ownerUID
) {
881 ace
->flags
|= SMB_ACE4_ID_SPECIAL
;
882 ace
->who
.special_id
= SMB_ACE4_WHO_OWNER
;
883 DEBUG(10,("replaced with special owner ace\n"));
886 if (!(ace
->flags
& SMB_ACE4_ID_SPECIAL
) &&
887 ace
->aceFlags
& SMB_ACE4_IDENTIFIER_GROUP
&&
888 ace
->who
.uid
== ownerGID
) {
889 ace
->flags
|= SMB_ACE4_ID_SPECIAL
;
890 ace
->who
.special_id
= SMB_ACE4_WHO_GROUP
;
891 DEBUG(10,("replaced with special group ace\n"));
896 static void smbacl4_substitute_simple(struct SMB4ACL_T
*acl
,
900 struct SMB4ACE_T
*aceint
;
902 for (aceint
= acl
->first
; aceint
!= NULL
; aceint
= aceint
->next
) {
903 SMB_ACE4PROP_T
*ace
= &aceint
->prop
;
905 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
));
910 if (!(ace
->flags
& SMB_ACE4_ID_SPECIAL
) &&
911 !(ace
->aceFlags
& SMB_ACE4_IDENTIFIER_GROUP
) &&
912 ace
->who
.uid
== ownerUID
&&
913 !nfs_ace_is_inherit(ace
)) {
914 ace
->flags
|= SMB_ACE4_ID_SPECIAL
;
915 ace
->who
.special_id
= SMB_ACE4_WHO_OWNER
;
916 DEBUG(10,("replaced with special owner ace\n"));
919 if (!(ace
->flags
& SMB_ACE4_ID_SPECIAL
) &&
920 ace
->aceFlags
& SMB_ACE4_IDENTIFIER_GROUP
&&
921 ace
->who
.gid
== ownerGID
&&
922 !nfs_ace_is_inherit(ace
)) {
923 ace
->flags
|= SMB_ACE4_ID_SPECIAL
;
924 ace
->who
.special_id
= SMB_ACE4_WHO_GROUP
;
925 DEBUG(10,("replaced with special group ace\n"));
930 static struct SMB4ACL_T
*smbacl4_win2nfs4(
933 const struct security_acl
*dacl
,
934 const struct smbacl4_vfs_params
*pparams
,
939 struct SMB4ACL_T
*theacl
;
942 DEBUG(10, ("smbacl4_win2nfs4 invoked\n"));
944 theacl
= smb_create_smb4acl(mem_ctx
);
948 for(i
=0; i
<dacl
->num_aces
; i
++) {
951 ret
= nfs4_acl_add_sec_ace(is_directory
, pparams
,
953 dacl
->aces
+ i
, theacl
);
959 if (pparams
->mode
==e_simple
) {
960 smbacl4_substitute_simple(theacl
, ownerUID
, ownerGID
);
963 if (pparams
->mode
==e_special
) {
964 smbacl4_substitute_special(theacl
, ownerUID
, ownerGID
);
970 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
)
976 struct smbacl4_vfs_params params
;
977 struct SMB4ACL_T
*theacl
= NULL
;
978 bool result
, is_directory
;
980 bool set_acl_as_root
= false;
981 uid_t newUID
= (uid_t
)-1;
982 gid_t newGID
= (gid_t
)-1;
985 TALLOC_CTX
*frame
= talloc_stackframe();
987 DEBUG(10, ("smb_set_nt_acl_nfs4 invoked for %s\n", fsp_str_dbg(fsp
)));
989 if ((security_info_sent
& (SECINFO_DACL
|
990 SECINFO_GROUP
| SECINFO_OWNER
)) == 0)
992 DEBUG(9, ("security_info_sent (0x%x) ignored\n",
993 security_info_sent
));
995 return NT_STATUS_OK
; /* won't show error - later to be
999 if (security_descriptor_with_ms_nfs(psd
)) {
1000 return NT_STATUS_OK
;
1003 if (pparams
== NULL
) {
1004 /* Special behaviours */
1005 if (smbacl4_get_vfs_params(fsp
->conn
, ¶ms
)) {
1007 return NT_STATUS_NO_MEMORY
;
1012 status
= vfs_stat_fsp(fsp
);
1013 if (!NT_STATUS_IS_OK(status
)) {
1018 is_directory
= S_ISDIR(fsp
->fsp_name
->st
.st_ex_mode
);
1020 if (pparams
->do_chown
) {
1021 /* chown logic is a copy/paste from posix_acl.c:set_nt_acl */
1023 uid_t old_uid
= fsp
->fsp_name
->st
.st_ex_uid
;
1024 uid_t old_gid
= fsp
->fsp_name
->st
.st_ex_uid
;
1025 status
= unpack_nt_owners(fsp
->conn
, &newUID
, &newGID
,
1026 security_info_sent
, psd
);
1027 if (!NT_STATUS_IS_OK(status
)) {
1028 DEBUG(8, ("unpack_nt_owners failed"));
1032 if (((newUID
!= (uid_t
)-1) && (old_uid
!= newUID
)) ||
1033 ((newGID
!= (gid_t
)-1) && (old_gid
!= newGID
)))
1035 status
= try_chown(fsp
, newUID
, newGID
);
1036 if (!NT_STATUS_IS_OK(status
)) {
1037 DEBUG(3,("chown %s, %u, %u failed. Error = "
1038 "%s.\n", fsp_str_dbg(fsp
),
1039 (unsigned int)newUID
,
1040 (unsigned int)newGID
,
1041 nt_errstr(status
)));
1046 DEBUG(10,("chown %s, %u, %u succeeded.\n",
1047 fsp_str_dbg(fsp
), (unsigned int)newUID
,
1048 (unsigned int)newGID
));
1051 * Owner change, need to update stat info.
1053 status
= vfs_stat_fsp(fsp
);
1054 if (!NT_STATUS_IS_OK(status
)) {
1059 /* If we successfully chowned, we know we must
1060 * be able to set the acl, so do it as root.
1062 set_acl_as_root
= true;
1066 if (!(security_info_sent
& SECINFO_DACL
) || psd
->dacl
==NULL
) {
1067 DEBUG(10, ("no dacl found; security_info_sent = 0x%x\n",
1068 security_info_sent
));
1070 return NT_STATUS_OK
;
1073 theacl
= smbacl4_win2nfs4(frame
, is_directory
, psd
->dacl
, pparams
,
1074 fsp
->fsp_name
->st
.st_ex_uid
,
1075 fsp
->fsp_name
->st
.st_ex_gid
);
1078 return map_nt_error_from_unix(errno
);
1081 smbacl4_set_controlflags(theacl
, psd
->type
);
1082 smbacl4_dump_nfs4acl(10, theacl
);
1084 if (set_acl_as_root
) {
1087 result
= set_nfs4_native(handle
, fsp
, theacl
);
1088 saved_errno
= errno
;
1089 if (set_acl_as_root
) {
1096 errno
= saved_errno
;
1097 DEBUG(10, ("set_nfs4_native failed with %s\n",
1099 return map_nt_error_from_unix(errno
);
1102 DEBUG(10, ("smb_set_nt_acl_nfs4 succeeded\n"));
1103 return NT_STATUS_OK
;