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 enum smbacl4_mode_enum
{e_simple
=0, e_special
=1};
58 enum smbacl4_acedup_enum
{e_dontcare
=0, e_reject
=1, e_ignore
=2, e_merge
=3};
60 typedef struct _smbacl4_vfs_params
{
61 enum smbacl4_mode_enum mode
;
63 enum smbacl4_acedup_enum acedup
;
64 bool map_full_control
;
68 * Gather special parameters for NFS4 ACL handling
70 static int smbacl4_get_vfs_params(
71 const char *type_name
,
72 struct connection_struct
*conn
,
73 smbacl4_vfs_params
*params
76 static const struct enum_list enum_smbacl4_modes
[] = {
77 { e_simple
, "simple" },
78 { e_special
, "special" },
81 static const struct enum_list enum_smbacl4_acedups
[] = {
82 { e_dontcare
, "dontcare" },
83 { e_reject
, "reject" },
84 { e_ignore
, "ignore" },
90 memset(params
, 0, sizeof(smbacl4_vfs_params
));
92 enumval
= lp_parm_enum(SNUM(conn
), type_name
, "mode",
93 enum_smbacl4_modes
, e_simple
);
95 DEBUG(10, ("value for %s:mode unknown\n", type_name
));
98 params
->mode
= (enum smbacl4_mode_enum
)enumval
;
100 params
->do_chown
= lp_parm_bool(SNUM(conn
), type_name
,
103 enumval
= lp_parm_enum(SNUM(conn
), type_name
, "acedup",
104 enum_smbacl4_acedups
, e_dontcare
);
106 DEBUG(10, ("value for %s:acedup unknown\n", type_name
));
109 params
->acedup
= (enum smbacl4_acedup_enum
)enumval
;
111 params
->map_full_control
= lp_acl_map_full_control(SNUM(conn
));
113 DEBUG(10, ("mode:%s, do_chown:%s, acedup: %s map full control:%s\n",
114 enum_smbacl4_modes
[params
->mode
].name
,
115 params
->do_chown
? "true" : "false",
116 enum_smbacl4_acedups
[params
->acedup
].name
,
117 params
->map_full_control
? "true" : "false"));
122 /************************************************
123 Split the ACE flag mapping between nfs4 and Windows
124 into two separate functions rather than trying to do
125 it inline. Allows us to carefully control what flags
126 are mapped to what in one place.
127 ************************************************/
129 static uint32_t map_nfs4_ace_flags_to_windows_ace_flags(
130 uint32_t nfs4_ace_flags
)
132 uint32_t win_ace_flags
= 0;
134 /* The nfs4 flags <= 0xf map perfectly. */
135 win_ace_flags
= nfs4_ace_flags
& (SEC_ACE_FLAG_OBJECT_INHERIT
|
136 SEC_ACE_FLAG_CONTAINER_INHERIT
|
137 SEC_ACE_FLAG_NO_PROPAGATE_INHERIT
|
138 SEC_ACE_FLAG_INHERIT_ONLY
);
140 /* flags greater than 0xf have diverged :-(. */
141 /* See the nfs4 ace flag definitions here:
142 http://www.ietf.org/rfc/rfc3530.txt.
143 And the Windows ace flag definitions here:
144 librpc/idl/security.idl. */
145 if (nfs4_ace_flags
& SMB_ACE4_INHERITED_ACE
) {
146 win_ace_flags
|= SEC_ACE_FLAG_INHERITED_ACE
;
149 return win_ace_flags
;
152 static uint32_t map_windows_ace_flags_to_nfs4_ace_flags(uint32_t win_ace_flags
)
154 uint32_t nfs4_ace_flags
= 0;
156 /* The windows flags <= 0xf map perfectly. */
157 nfs4_ace_flags
= win_ace_flags
& (SMB_ACE4_FILE_INHERIT_ACE
|
158 SMB_ACE4_DIRECTORY_INHERIT_ACE
|
159 SMB_ACE4_NO_PROPAGATE_INHERIT_ACE
|
160 SMB_ACE4_INHERIT_ONLY_ACE
);
162 /* flags greater than 0xf have diverged :-(. */
163 /* See the nfs4 ace flag definitions here:
164 http://www.ietf.org/rfc/rfc3530.txt.
165 And the Windows ace flag definitions here:
166 librpc/idl/security.idl. */
167 if (win_ace_flags
& SEC_ACE_FLAG_INHERITED_ACE
) {
168 nfs4_ace_flags
|= SMB_ACE4_INHERITED_ACE
;
171 return nfs4_ace_flags
;
174 static SMB_ACL4_INT_T
*get_validated_aclint(SMB4ACL_T
*theacl
)
176 SMB_ACL4_INT_T
*aclint
= (SMB_ACL4_INT_T
*)theacl
;
179 DEBUG(2, ("acl is NULL\n"));
183 if (aclint
->magic
!=SMB_ACL4_INT_MAGIC
)
185 DEBUG(2, ("aclint bad magic 0x%x\n", aclint
->magic
));
192 static SMB_ACE4_INT_T
*get_validated_aceint(SMB4ACE_T
*ace
)
194 SMB_ACE4_INT_T
*aceint
= (SMB_ACE4_INT_T
*)ace
;
197 DEBUG(2, ("ace is NULL\n"));
201 if (aceint
->magic
!=SMB_ACE4_INT_MAGIC
)
203 DEBUG(2, ("aceint bad magic 0x%x\n", aceint
->magic
));
210 SMB4ACL_T
*smb_create_smb4acl(TALLOC_CTX
*mem_ctx
)
212 SMB_ACL4_INT_T
*theacl
= (SMB_ACL4_INT_T
*)TALLOC_ZERO_SIZE(
213 mem_ctx
, sizeof(SMB_ACL4_INT_T
));
216 DEBUG(0, ("TALLOC_SIZE failed\n"));
220 theacl
->magic
= SMB_ACL4_INT_MAGIC
;
221 /* theacl->first, last = NULL not needed */
222 return (SMB4ACL_T
*)theacl
;
225 SMB4ACE_T
*smb_add_ace4(SMB4ACL_T
*theacl
, SMB_ACE4PROP_T
*prop
)
227 SMB_ACL4_INT_T
*aclint
= get_validated_aclint(theacl
);
230 ace
= (SMB_ACE4_INT_T
*)TALLOC_ZERO_SIZE(
231 theacl
, sizeof(SMB_ACE4_INT_T
));
234 DEBUG(0, ("TALLOC_SIZE failed\n"));
238 ace
->magic
= SMB_ACE4_INT_MAGIC
;
239 /* ace->next = NULL not needed */
240 memcpy(&ace
->prop
, prop
, sizeof(SMB_ACE4PROP_T
));
242 if (aclint
->first
==NULL
)
247 aclint
->last
->next
= (void *)ace
;
252 return (SMB4ACE_T
*)ace
;
255 SMB_ACE4PROP_T
*smb_get_ace4(SMB4ACE_T
*ace
)
257 SMB_ACE4_INT_T
*aceint
= get_validated_aceint(ace
);
261 return &aceint
->prop
;
264 SMB4ACE_T
*smb_next_ace4(SMB4ACE_T
*ace
)
266 SMB_ACE4_INT_T
*aceint
= get_validated_aceint(ace
);
270 return (SMB4ACE_T
*)aceint
->next
;
273 SMB4ACE_T
*smb_first_ace4(SMB4ACL_T
*theacl
)
275 SMB_ACL4_INT_T
*aclint
= get_validated_aclint(theacl
);
279 return (SMB4ACE_T
*)aclint
->first
;
282 uint32
smb_get_naces(SMB4ACL_T
*theacl
)
284 SMB_ACL4_INT_T
*aclint
= get_validated_aclint(theacl
);
288 return aclint
->naces
;
291 static int smbacl4_GetFileOwner(struct connection_struct
*conn
,
292 const char *filename
,
293 SMB_STRUCT_STAT
*psbuf
)
295 memset(psbuf
, 0, sizeof(SMB_STRUCT_STAT
));
297 /* Get the stat struct for the owner info. */
298 if (vfs_stat_smb_fname(conn
, filename
, psbuf
) != 0)
300 DEBUG(8, ("vfs_stat_smb_fname failed with error %s\n",
308 static int smbacl4_fGetFileOwner(files_struct
*fsp
, SMB_STRUCT_STAT
*psbuf
)
310 memset(psbuf
, 0, sizeof(SMB_STRUCT_STAT
));
312 if (fsp
->fh
->fd
== -1) {
313 return smbacl4_GetFileOwner(fsp
->conn
,
314 fsp
->fsp_name
->base_name
, psbuf
);
316 if (SMB_VFS_FSTAT(fsp
, psbuf
) != 0)
318 DEBUG(8, ("SMB_VFS_FSTAT failed with error %s\n",
326 static bool smbacl4_nfs42win(TALLOC_CTX
*mem_ctx
,
327 smbacl4_vfs_params
*params
,
328 SMB4ACL_T
*theacl
, /* in */
329 struct dom_sid
*psid_owner
, /* in */
330 struct dom_sid
*psid_group
, /* in */
331 bool is_directory
, /* in */
332 struct security_ace
**ppnt_ace_list
, /* out */
333 int *pgood_aces
/* out */
336 SMB_ACL4_INT_T
*aclint
= (SMB_ACL4_INT_T
*)theacl
;
337 SMB_ACE4_INT_T
*aceint
;
338 struct security_ace
*nt_ace_list
= NULL
;
341 DEBUG(10, ("smbacl_nfs42win entered\n"));
343 aclint
= get_validated_aclint(theacl
);
344 /* We do not check for theacl being NULL here
345 because this is already checked in smb_get_nt_acl_nfs4().
346 We reserve twice the number of input aces because one nfs4
347 ace might result in 2 nt aces.*/
348 nt_ace_list
= (struct security_ace
*)TALLOC_ZERO_SIZE(
349 mem_ctx
, 2 * aclint
->naces
* sizeof(struct security_ace
));
350 if (nt_ace_list
==NULL
)
352 DEBUG(10, ("talloc error with %d aces", aclint
->naces
));
357 for (aceint
=aclint
->first
;
359 aceint
=(SMB_ACE4_INT_T
*)aceint
->next
) {
362 SMB_ACE4PROP_T
*ace
= &aceint
->prop
;
363 uint32_t win_ace_flags
;
365 DEBUG(10, ("magic: 0x%x, type: %d, iflags: %x, flags: %x, "
366 "mask: %x, who: %d\n",
367 aceint
->magic
, ace
->aceType
, ace
->flags
,
368 ace
->aceFlags
, ace
->aceMask
, ace
->who
.id
));
370 SMB_ASSERT(aceint
->magic
==SMB_ACE4_INT_MAGIC
);
372 if (ace
->flags
& SMB_ACE4_ID_SPECIAL
) {
373 switch (ace
->who
.special_id
) {
374 case SMB_ACE4_WHO_OWNER
:
375 sid_copy(&sid
, psid_owner
);
377 case SMB_ACE4_WHO_GROUP
:
378 sid_copy(&sid
, psid_group
);
380 case SMB_ACE4_WHO_EVERYONE
:
381 sid_copy(&sid
, &global_sid_World
);
384 DEBUG(8, ("invalid special who id %d "
385 "ignored\n", ace
->who
.special_id
));
389 if (ace
->aceFlags
& SMB_ACE4_IDENTIFIER_GROUP
) {
390 gid_to_sid(&sid
, ace
->who
.gid
);
392 uid_to_sid(&sid
, ace
->who
.uid
);
395 DEBUG(10, ("mapped %d to %s\n", ace
->who
.id
,
396 sid_string_dbg(&sid
)));
398 if (is_directory
&& (ace
->aceMask
& SMB_ACE4_ADD_FILE
)) {
399 ace
->aceMask
|= SMB_ACE4_DELETE_CHILD
;
402 if (!is_directory
&& params
->map_full_control
) {
404 * Do we have all access except DELETE_CHILD
405 * (not caring about the delete bit).
407 uint32_t test_mask
= ((ace
->aceMask
|SMB_ACE4_DELETE
|SMB_ACE4_DELETE_CHILD
) &
409 if (test_mask
== SMB_ACE4_ALL_MASKS
) {
410 ace
->aceMask
|= SMB_ACE4_DELETE_CHILD
;
414 win_ace_flags
= map_nfs4_ace_flags_to_windows_ace_flags(
417 (win_ace_flags
& (SEC_ACE_FLAG_OBJECT_INHERIT
|
418 SEC_ACE_FLAG_CONTAINER_INHERIT
))) {
420 * GPFS sets inherits dir_inhert and file_inherit flags
421 * to files, too, which confuses windows, and seems to
422 * be wrong anyways. ==> Map these bits away for files.
424 DEBUG(10, ("removing inherit flags from nfs4 ace\n"));
425 win_ace_flags
&= ~(SEC_ACE_FLAG_OBJECT_INHERIT
|
426 SEC_ACE_FLAG_CONTAINER_INHERIT
);
428 DEBUG(10, ("Windows mapped ace flags: 0x%x => 0x%x\n",
429 ace
->aceFlags
, win_ace_flags
));
432 /* Windows clients expect SYNC on acls to
433 correctly allow rename. See bug #7909. */
434 /* But not on DENY ace entries. See
436 if(ace
->aceType
== SMB_ACE4_ACCESS_ALLOWED_ACE_TYPE
) {
437 mask
= ace
->aceMask
| SMB_ACE4_SYNCHRONIZE
;
440 /* Mapping of owner@ and group@ to creator owner and
441 creator group. Keep old behavior in mode special. */
442 if (params
->mode
!= e_special
&&
443 ace
->flags
& SMB_ACE4_ID_SPECIAL
&&
444 (ace
->who
.special_id
== SMB_ACE4_WHO_OWNER
||
445 ace
->who
.special_id
== SMB_ACE4_WHO_GROUP
)) {
446 DEBUG(10, ("Map special entry\n"));
447 if (!(win_ace_flags
& SEC_ACE_FLAG_INHERIT_ONLY
)) {
448 uint32_t win_ace_flags_current
;
449 DEBUG(10, ("Map current sid\n"));
450 win_ace_flags_current
= win_ace_flags
&
451 ~(SEC_ACE_FLAG_OBJECT_INHERIT
|
452 SEC_ACE_FLAG_CONTAINER_INHERIT
);
453 init_sec_ace(&nt_ace_list
[good_aces
++], &sid
,
455 win_ace_flags_current
);
457 if (ace
->who
.special_id
== SMB_ACE4_WHO_OWNER
&&
458 win_ace_flags
& (SEC_ACE_FLAG_OBJECT_INHERIT
|
459 SEC_ACE_FLAG_CONTAINER_INHERIT
)) {
460 uint32_t win_ace_flags_creator
;
461 DEBUG(10, ("Map creator owner\n"));
462 win_ace_flags_creator
= win_ace_flags
|
463 SMB_ACE4_INHERIT_ONLY_ACE
;
464 init_sec_ace(&nt_ace_list
[good_aces
++],
465 &global_sid_Creator_Owner
,
467 win_ace_flags_creator
);
469 if (ace
->who
.special_id
== SMB_ACE4_WHO_GROUP
&&
470 win_ace_flags
& (SEC_ACE_FLAG_OBJECT_INHERIT
|
471 SEC_ACE_FLAG_CONTAINER_INHERIT
)) {
472 uint32_t win_ace_flags_creator
;
473 DEBUG(10, ("Map creator owner group\n"));
474 win_ace_flags_creator
= win_ace_flags
|
475 SMB_ACE4_INHERIT_ONLY_ACE
;
476 init_sec_ace(&nt_ace_list
[good_aces
++],
477 &global_sid_Creator_Group
,
479 win_ace_flags_creator
);
482 DEBUG(10, ("Map normal sid\n"));
483 init_sec_ace(&nt_ace_list
[good_aces
++], &sid
,
489 nt_ace_list
= (struct security_ace
*)
490 TALLOC_REALLOC(mem_ctx
, nt_ace_list
,
491 good_aces
* sizeof(struct security_ace
));
492 /* returns a NULL ace list when good_aces is zero. */
493 if (good_aces
&& nt_ace_list
== NULL
) {
494 DEBUG(10, ("realloc error with %d aces", good_aces
));
499 *ppnt_ace_list
= nt_ace_list
;
500 *pgood_aces
= good_aces
;
505 static NTSTATUS
smb_get_nt_acl_nfs4_common(const SMB_STRUCT_STAT
*sbuf
,
506 smbacl4_vfs_params
*params
,
507 uint32 security_info
,
509 struct security_descriptor
**ppdesc
,
513 struct dom_sid sid_owner
, sid_group
;
515 struct security_ace
*nt_ace_list
= NULL
;
516 struct security_acl
*psa
= NULL
;
517 TALLOC_CTX
*frame
= talloc_stackframe();
521 return NT_STATUS_ACCESS_DENIED
; /* special because we
522 * need to think through
526 uid_to_sid(&sid_owner
, sbuf
->st_ex_uid
);
527 gid_to_sid(&sid_group
, sbuf
->st_ex_gid
);
529 if (smbacl4_nfs42win(mem_ctx
, params
, theacl
, &sid_owner
, &sid_group
,
530 S_ISDIR(sbuf
->st_ex_mode
),
531 &nt_ace_list
, &good_aces
)==false) {
532 DEBUG(8,("smbacl4_nfs42win failed\n"));
534 return map_nt_error_from_unix(errno
);
537 psa
= make_sec_acl(frame
, NT4_ACL_REVISION
, good_aces
, nt_ace_list
);
539 DEBUG(2,("make_sec_acl failed\n"));
541 return NT_STATUS_NO_MEMORY
;
544 DEBUG(10,("after make sec_acl\n"));
545 *ppdesc
= make_sec_desc(
546 mem_ctx
, SD_REVISION
, SEC_DESC_SELF_RELATIVE
,
547 (security_info
& SECINFO_OWNER
) ? &sid_owner
: NULL
,
548 (security_info
& SECINFO_GROUP
) ? &sid_group
: NULL
,
549 NULL
, psa
, &sd_size
);
551 DEBUG(2,("make_sec_desc failed\n"));
553 return NT_STATUS_NO_MEMORY
;
556 DEBUG(10, ("smb_get_nt_acl_nfs4_common successfully exited with "
558 (int)ndr_size_security_descriptor(*ppdesc
, 0)));
564 NTSTATUS
smb_fget_nt_acl_nfs4(files_struct
*fsp
,
565 uint32 security_info
,
567 struct security_descriptor
**ppdesc
,
570 SMB_STRUCT_STAT sbuf
;
571 smbacl4_vfs_params params
;
573 DEBUG(10, ("smb_fget_nt_acl_nfs4 invoked for %s\n", fsp_str_dbg(fsp
)));
575 if (smbacl4_fGetFileOwner(fsp
, &sbuf
)) {
576 return map_nt_error_from_unix(errno
);
579 /* Special behaviours */
580 if (smbacl4_get_vfs_params(SMBACL4_PARAM_TYPE_NAME
, fsp
->conn
, ¶ms
)) {
581 return NT_STATUS_NO_MEMORY
;
584 return smb_get_nt_acl_nfs4_common(&sbuf
, ¶ms
, security_info
,
585 mem_ctx
, ppdesc
, theacl
);
588 NTSTATUS
smb_get_nt_acl_nfs4(struct connection_struct
*conn
,
590 uint32 security_info
,
592 struct security_descriptor
**ppdesc
,
595 SMB_STRUCT_STAT sbuf
;
596 smbacl4_vfs_params params
;
598 DEBUG(10, ("smb_get_nt_acl_nfs4 invoked for %s\n", name
));
600 if (smbacl4_GetFileOwner(conn
, name
, &sbuf
)) {
601 return map_nt_error_from_unix(errno
);
604 /* Special behaviours */
605 if (smbacl4_get_vfs_params(SMBACL4_PARAM_TYPE_NAME
, conn
, ¶ms
)) {
606 return NT_STATUS_NO_MEMORY
;
609 return smb_get_nt_acl_nfs4_common(&sbuf
, ¶ms
, security_info
,
610 mem_ctx
, ppdesc
, theacl
);
613 static void smbacl4_dump_nfs4acl(int level
, SMB4ACL_T
*theacl
)
615 SMB_ACL4_INT_T
*aclint
= get_validated_aclint(theacl
);
616 SMB_ACE4_INT_T
*aceint
;
618 DEBUG(level
, ("NFS4ACL: size=%d\n", aclint
->naces
));
620 for (aceint
= aclint
->first
;
622 aceint
=(SMB_ACE4_INT_T
*)aceint
->next
) {
623 SMB_ACE4PROP_T
*ace
= &aceint
->prop
;
625 DEBUG(level
, ("\tACE: type=%d, flags=0x%x, fflags=0x%x, "
626 "mask=0x%x, id=%d\n",
628 ace
->aceFlags
, ace
->flags
,
635 * Find 2 NFS4 who-special ACE property (non-copy!!!)
636 * match nonzero if "special" and who is equal
637 * return ace if found matching; otherwise NULL
639 static SMB_ACE4PROP_T
*smbacl4_find_equal_special(
641 SMB_ACE4PROP_T
*aceNew
)
643 SMB_ACL4_INT_T
*aclint
= get_validated_aclint(theacl
);
644 SMB_ACE4_INT_T
*aceint
;
646 for (aceint
= aclint
->first
; aceint
!= NULL
;
647 aceint
=(SMB_ACE4_INT_T
*)aceint
->next
) {
648 SMB_ACE4PROP_T
*ace
= &aceint
->prop
;
650 DEBUG(10,("ace type:0x%x flags:0x%x aceFlags:0x%x "
651 "new type:0x%x flags:0x%x aceFlags:0x%x\n",
652 ace
->aceType
, ace
->flags
, ace
->aceFlags
,
653 aceNew
->aceType
, aceNew
->flags
,aceNew
->aceFlags
));
655 if (ace
->flags
== aceNew
->flags
&&
656 ace
->aceType
==aceNew
->aceType
&&
657 ace
->aceFlags
==aceNew
->aceFlags
)
659 /* keep type safety; e.g. gid is an u.short */
660 if (ace
->flags
& SMB_ACE4_ID_SPECIAL
)
662 if (ace
->who
.special_id
==
663 aceNew
->who
.special_id
)
666 if (ace
->aceFlags
& SMB_ACE4_IDENTIFIER_GROUP
)
668 if (ace
->who
.gid
==aceNew
->who
.gid
)
671 if (ace
->who
.uid
==aceNew
->who
.uid
)
682 static bool smbacl4_fill_ace4(
683 const struct smb_filename
*filename
,
684 smbacl4_vfs_params
*params
,
687 const struct security_ace
*ace_nt
, /* input */
688 SMB_ACE4PROP_T
*ace_v4
/* output */
691 DEBUG(10, ("got ace for %s\n", sid_string_dbg(&ace_nt
->trustee
)));
693 memset(ace_v4
, 0, sizeof(SMB_ACE4PROP_T
));
695 /* only ACCESS|DENY supported right now */
696 ace_v4
->aceType
= ace_nt
->type
;
698 ace_v4
->aceFlags
= map_windows_ace_flags_to_nfs4_ace_flags(
701 /* remove inheritance flags on files */
702 if (VALID_STAT(filename
->st
) &&
703 !S_ISDIR(filename
->st
.st_ex_mode
)) {
704 DEBUG(10, ("Removing inheritance flags from a file\n"));
705 ace_v4
->aceFlags
&= ~(SMB_ACE4_FILE_INHERIT_ACE
|
706 SMB_ACE4_DIRECTORY_INHERIT_ACE
|
707 SMB_ACE4_NO_PROPAGATE_INHERIT_ACE
|
708 SMB_ACE4_INHERIT_ONLY_ACE
);
711 ace_v4
->aceMask
= ace_nt
->access_mask
&
712 (SEC_STD_ALL
| SEC_FILE_ALL
);
714 se_map_generic(&ace_v4
->aceMask
, &file_generic_mapping
);
716 if (ace_v4
->aceFlags
!=ace_nt
->flags
)
717 DEBUG(9, ("ace_v4->aceFlags(0x%x)!=ace_nt->flags(0x%x)\n",
718 ace_v4
->aceFlags
, ace_nt
->flags
));
720 if (ace_v4
->aceMask
!=ace_nt
->access_mask
)
721 DEBUG(9, ("ace_v4->aceMask(0x%x)!=ace_nt->access_mask(0x%x)\n",
722 ace_v4
->aceMask
, ace_nt
->access_mask
));
724 if (dom_sid_equal(&ace_nt
->trustee
, &global_sid_World
)) {
725 ace_v4
->who
.special_id
= SMB_ACE4_WHO_EVERYONE
;
726 ace_v4
->flags
|= SMB_ACE4_ID_SPECIAL
;
727 } else if (params
->mode
!=e_special
&&
728 dom_sid_equal(&ace_nt
->trustee
,
729 &global_sid_Creator_Owner
)) {
730 DEBUG(10, ("Map creator owner\n"));
731 ace_v4
->who
.special_id
= SMB_ACE4_WHO_OWNER
;
732 ace_v4
->flags
|= SMB_ACE4_ID_SPECIAL
;
733 /* A non inheriting creator owner entry has no effect. */
734 ace_v4
->aceFlags
|= SMB_ACE4_INHERIT_ONLY_ACE
;
735 if (!(ace_v4
->aceFlags
& SMB_ACE4_DIRECTORY_INHERIT_ACE
)
736 && !(ace_v4
->aceFlags
& SMB_ACE4_FILE_INHERIT_ACE
)) {
739 } else if (params
->mode
!=e_special
&&
740 dom_sid_equal(&ace_nt
->trustee
,
741 &global_sid_Creator_Group
)) {
742 DEBUG(10, ("Map creator owner group\n"));
743 ace_v4
->who
.special_id
= SMB_ACE4_WHO_GROUP
;
744 ace_v4
->flags
|= SMB_ACE4_ID_SPECIAL
;
745 /* A non inheriting creator group entry has no effect. */
746 ace_v4
->aceFlags
|= SMB_ACE4_INHERIT_ONLY_ACE
;
747 if (!(ace_v4
->aceFlags
& SMB_ACE4_DIRECTORY_INHERIT_ACE
)
748 && !(ace_v4
->aceFlags
& SMB_ACE4_FILE_INHERIT_ACE
)) {
755 if (sid_to_gid(&ace_nt
->trustee
, &gid
)) {
756 ace_v4
->aceFlags
|= SMB_ACE4_IDENTIFIER_GROUP
;
757 ace_v4
->who
.gid
= gid
;
758 } else if (sid_to_uid(&ace_nt
->trustee
, &uid
)) {
759 ace_v4
->who
.uid
= uid
;
761 DEBUG(1, ("nfs4_acls.c: file [%s]: could not "
762 "convert %s to uid or gid\n",
764 sid_string_dbg(&ace_nt
->trustee
)));
769 return true; /* OK */
772 static int smbacl4_MergeIgnoreReject(
773 enum smbacl4_acedup_enum acedup
,
774 SMB4ACL_T
*theacl
, /* may modify it */
775 SMB_ACE4PROP_T
*ace
, /* the "new" ACE */
781 SMB_ACE4PROP_T
*ace4found
= smbacl4_find_equal_special(theacl
, ace
);
786 case e_merge
: /* "merge" flags */
788 ace4found
->aceFlags
|= ace
->aceFlags
;
789 ace4found
->aceMask
|= ace
->aceMask
;
791 case e_ignore
: /* leave out this record */
794 case e_reject
: /* do an error */
795 DEBUG(8, ("ACL rejected by duplicate nt ace#%d\n", i
));
796 errno
= EINVAL
; /* SHOULD be set on any _real_ error */
806 static int smbacl4_substitute_special(
812 SMB_ACL4_INT_T
*aclint
= get_validated_aclint(theacl
);
813 SMB_ACE4_INT_T
*aceint
;
815 for(aceint
= aclint
->first
; aceint
!=NULL
; aceint
=(SMB_ACE4_INT_T
*)aceint
->next
) {
816 SMB_ACE4PROP_T
*ace
= &aceint
->prop
;
818 DEBUG(10,("ace type: %d, iflags: %x, flags: %x, "
819 "mask: %x, who: %d\n",
820 ace
->aceType
, ace
->flags
, ace
->aceFlags
,
821 ace
->aceMask
, ace
->who
.id
));
823 if (!(ace
->flags
& SMB_ACE4_ID_SPECIAL
) &&
824 !(ace
->aceFlags
& SMB_ACE4_IDENTIFIER_GROUP
) &&
825 ace
->who
.uid
== ownerUID
) {
826 ace
->flags
|= SMB_ACE4_ID_SPECIAL
;
827 ace
->who
.special_id
= SMB_ACE4_WHO_OWNER
;
828 DEBUG(10,("replaced with special owner ace\n"));
831 if (!(ace
->flags
& SMB_ACE4_ID_SPECIAL
) &&
832 ace
->aceFlags
& SMB_ACE4_IDENTIFIER_GROUP
&&
833 ace
->who
.uid
== ownerGID
) {
834 ace
->flags
|= SMB_ACE4_ID_SPECIAL
;
835 ace
->who
.special_id
= SMB_ACE4_WHO_GROUP
;
836 DEBUG(10,("replaced with special group ace\n"));
839 return true; /* OK */
842 static int smbacl4_substitute_simple(
848 SMB_ACL4_INT_T
*aclint
= get_validated_aclint(theacl
);
849 SMB_ACE4_INT_T
*aceint
;
851 for(aceint
= aclint
->first
; aceint
!=NULL
; aceint
=(SMB_ACE4_INT_T
*)aceint
->next
) {
852 SMB_ACE4PROP_T
*ace
= &aceint
->prop
;
854 DEBUG(10,("ace type: %d, iflags: %x, flags: %x, "
855 "mask: %x, who: %d\n",
856 ace
->aceType
, ace
->flags
, ace
->aceFlags
,
857 ace
->aceMask
, ace
->who
.id
));
859 if (!(ace
->flags
& SMB_ACE4_ID_SPECIAL
) &&
860 !(ace
->aceFlags
& SMB_ACE4_IDENTIFIER_GROUP
) &&
861 ace
->who
.uid
== ownerUID
&&
862 !(ace
->aceFlags
& SMB_ACE4_INHERIT_ONLY_ACE
) &&
863 !(ace
->aceFlags
& SMB_ACE4_FILE_INHERIT_ACE
) &&
864 !(ace
->aceFlags
& SMB_ACE4_DIRECTORY_INHERIT_ACE
)) {
865 ace
->flags
|= SMB_ACE4_ID_SPECIAL
;
866 ace
->who
.special_id
= SMB_ACE4_WHO_OWNER
;
867 DEBUG(10,("replaced with special owner ace\n"));
870 if (!(ace
->flags
& SMB_ACE4_ID_SPECIAL
) &&
871 ace
->aceFlags
& SMB_ACE4_IDENTIFIER_GROUP
&&
872 ace
->who
.uid
== ownerGID
&&
873 !(ace
->aceFlags
& SMB_ACE4_INHERIT_ONLY_ACE
) &&
874 !(ace
->aceFlags
& SMB_ACE4_FILE_INHERIT_ACE
) &&
875 !(ace
->aceFlags
& SMB_ACE4_DIRECTORY_INHERIT_ACE
)) {
876 ace
->flags
|= SMB_ACE4_ID_SPECIAL
;
877 ace
->who
.special_id
= SMB_ACE4_WHO_GROUP
;
878 DEBUG(10,("replaced with special group ace\n"));
881 return true; /* OK */
884 static SMB4ACL_T
*smbacl4_win2nfs4(
886 const files_struct
*fsp
,
887 const struct security_acl
*dacl
,
888 smbacl4_vfs_params
*pparams
,
895 const char *filename
= fsp
->fsp_name
->base_name
;
897 DEBUG(10, ("smbacl4_win2nfs4 invoked\n"));
899 theacl
= smb_create_smb4acl(mem_ctx
);
903 for(i
=0; i
<dacl
->num_aces
; i
++) {
904 SMB_ACE4PROP_T ace_v4
;
905 bool addNewACE
= true;
907 if (!smbacl4_fill_ace4(fsp
->fsp_name
, pparams
,
909 dacl
->aces
+ i
, &ace_v4
)) {
910 DEBUG(3, ("Could not fill ace for file %s, SID %s\n",
912 sid_string_dbg(&((dacl
->aces
+i
)->trustee
))));
916 if (pparams
->acedup
!=e_dontcare
) {
917 if (smbacl4_MergeIgnoreReject(pparams
->acedup
, theacl
,
918 &ace_v4
, &addNewACE
, i
))
923 smb_add_ace4(theacl
, &ace_v4
);
926 if (pparams
->mode
==e_simple
) {
927 smbacl4_substitute_simple(theacl
, ownerUID
, ownerGID
);
930 if (pparams
->mode
==e_special
) {
931 smbacl4_substitute_special(theacl
, ownerUID
, ownerGID
);
937 NTSTATUS
smb_set_nt_acl_nfs4(vfs_handle_struct
*handle
, files_struct
*fsp
,
938 uint32 security_info_sent
,
939 const struct security_descriptor
*psd
,
940 set_nfs4acl_native_fn_t set_nfs4_native
)
942 smbacl4_vfs_params params
;
943 SMB4ACL_T
*theacl
= NULL
;
946 SMB_STRUCT_STAT sbuf
;
947 bool set_acl_as_root
= false;
948 uid_t newUID
= (uid_t
)-1;
949 gid_t newGID
= (gid_t
)-1;
951 TALLOC_CTX
*frame
= talloc_stackframe();
953 DEBUG(10, ("smb_set_nt_acl_nfs4 invoked for %s\n", fsp_str_dbg(fsp
)));
955 if ((security_info_sent
& (SECINFO_DACL
|
956 SECINFO_GROUP
| SECINFO_OWNER
)) == 0)
958 DEBUG(9, ("security_info_sent (0x%x) ignored\n",
959 security_info_sent
));
961 return NT_STATUS_OK
; /* won't show error - later to be
965 /* Special behaviours */
966 if (smbacl4_get_vfs_params(SMBACL4_PARAM_TYPE_NAME
,
967 fsp
->conn
, ¶ms
)) {
969 return NT_STATUS_NO_MEMORY
;
972 if (smbacl4_fGetFileOwner(fsp
, &sbuf
)) {
974 return map_nt_error_from_unix(errno
);
977 if (params
.do_chown
) {
978 /* chown logic is a copy/paste from posix_acl.c:set_nt_acl */
979 NTSTATUS status
= unpack_nt_owners(fsp
->conn
, &newUID
, &newGID
,
980 security_info_sent
, psd
);
981 if (!NT_STATUS_IS_OK(status
)) {
982 DEBUG(8, ("unpack_nt_owners failed"));
986 if (((newUID
!= (uid_t
)-1) && (sbuf
.st_ex_uid
!= newUID
)) ||
987 ((newGID
!= (gid_t
)-1) && (sbuf
.st_ex_gid
!= newGID
))) {
989 status
= try_chown(fsp
, newUID
, newGID
);
990 if (!NT_STATUS_IS_OK(status
)) {
991 DEBUG(3,("chown %s, %u, %u failed. Error = "
992 "%s.\n", fsp_str_dbg(fsp
),
993 (unsigned int)newUID
,
994 (unsigned int)newGID
,
1000 DEBUG(10,("chown %s, %u, %u succeeded.\n",
1001 fsp_str_dbg(fsp
), (unsigned int)newUID
,
1002 (unsigned int)newGID
));
1003 if (smbacl4_GetFileOwner(fsp
->conn
,
1004 fsp
->fsp_name
->base_name
,
1007 return map_nt_error_from_unix(errno
);
1010 /* If we successfully chowned, we know we must
1011 * be able to set the acl, so do it as root.
1013 set_acl_as_root
= true;
1017 if (!(security_info_sent
& SECINFO_DACL
) || psd
->dacl
==NULL
) {
1018 DEBUG(10, ("no dacl found; security_info_sent = 0x%x\n",
1019 security_info_sent
));
1021 return NT_STATUS_OK
;
1024 theacl
= smbacl4_win2nfs4(frame
, fsp
, psd
->dacl
, ¶ms
,
1025 sbuf
.st_ex_uid
, sbuf
.st_ex_gid
);
1028 return map_nt_error_from_unix(errno
);
1031 smbacl4_dump_nfs4acl(10, theacl
);
1033 if (set_acl_as_root
) {
1036 result
= set_nfs4_native(handle
, fsp
, theacl
);
1037 saved_errno
= errno
;
1038 if (set_acl_as_root
) {
1045 errno
= saved_errno
;
1046 DEBUG(10, ("set_nfs4_native failed with %s\n",
1048 return map_nt_error_from_unix(errno
);
1051 DEBUG(10, ("smb_set_nt_acl_nfs4 succeeded\n"));
1052 return NT_STATUS_OK
;