2 * acls.c - General function to process NTFS ACLs
4 * This module is part of ntfs-3g library, but may also be
5 * integrated in tools running over Linux or Windows
7 * Copyright (c) 2007-2012 Jean-Pierre Andre
9 * This program/include file is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as published
11 * by the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program/include file is distributed in the hope that it will be
15 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
16 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program (in the main directory of the NTFS-3G
21 * distribution in the file COPYING); if not, write to the Free Software
22 * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 * integration into ntfs-3g
43 #ifdef HAVE_SYS_STAT_H
64 * integration into secaudit, check whether Win32,
65 * may have to be adapted to compiler or something else
69 #if defined(__WIN32) | defined(__WIN32__) | defined(WNSC)
79 #include <sys/types.h>
83 * integration into secaudit/Win32
88 #define __LITTLE_ENDIAN 1234
89 #define __BYTE_ORDER __LITTLE_ENDIAN
92 * integration into secaudit/STSC
97 #define __BYTE_ORDER __BIG_ENDIAN
100 * integration into secaudit/Linux
102 #include <sys/stat.h>
108 #include "secaudit.h"
109 #endif /* HAVE_CONFIG_H */
112 * A few useful constants
119 static const char nullsidbytes
[] = {
122 0, 0, 0, 0, 0, 0, /* base */
123 0, 0, 0, 0 /* 1st level */
126 static const SID
*nullsid
= (const SID
*)nullsidbytes
;
129 * SID for world (S-1-1-0)
132 static const char worldsidbytes
[] = {
135 0, 0, 0, 0, 0, 1, /* base */
136 0, 0, 0, 0 /* 1st level */
140 * SID for authenticated user (S-1-5-11)
143 static const char authsidbytes
[] = {
146 0, 0, 0, 0, 0, 5, /* base */
147 11, 0, 0, 0 /* 1st level */
150 static const SID
*authsid
= (const SID
*)authsidbytes
;
152 const SID
*worldsid
= (const SID
*)worldsidbytes
;
155 * SID for administrator
158 static const char adminsidbytes
[] = {
161 0, 0, 0, 0, 0, 5, /* base */
162 32, 0, 0, 0, /* 1st level */
163 32, 2, 0, 0 /* 2nd level */
166 const SID
*adminsid
= (const SID
*)adminsidbytes
;
172 static const char systemsidbytes
[] = {
175 0, 0, 0, 0, 0, 5, /* base */
176 18, 0, 0, 0 /* 1st level */
179 static const SID
*systemsid
= (const SID
*)systemsidbytes
;
182 * SID for generic creator-owner
186 static const char ownersidbytes
[] = {
189 0, 0, 0, 0, 0, 3, /* base */
190 0, 0, 0, 0 /* 1st level */
193 static const SID
*ownersid
= (const SID
*)ownersidbytes
;
196 * SID for generic creator-group
200 static const char groupsidbytes
[] = {
203 0, 0, 0, 0, 0, 3, /* base */
204 1, 0, 0, 0 /* 1st level */
207 static const SID
*groupsid
= (const SID
*)groupsidbytes
;
210 * Determine the size of a SID
213 int ntfs_sid_size(const SID
* sid
)
215 return (sid
->sub_authority_count
* 4 + 8);
219 * Test whether two SID are equal
222 BOOL
ntfs_same_sid(const SID
*first
, const SID
*second
)
226 size
= ntfs_sid_size(first
);
227 return ((ntfs_sid_size(second
) == size
)
228 && !memcmp(first
, second
, size
));
232 * Test whether a SID means "world user"
233 * Local users group also recognized as world
236 static int is_world_sid(const SID
* usid
)
239 /* check whether S-1-1-0 : world */
240 ((usid
->sub_authority_count
== 1)
241 && (usid
->identifier_authority
.high_part
== const_cpu_to_be16(0))
242 && (usid
->identifier_authority
.low_part
== const_cpu_to_be32(1))
243 && (usid
->sub_authority
[0] == const_cpu_to_le32(0)))
245 /* check whether S-1-5-32-545 : local user */
246 || ((usid
->sub_authority_count
== 2)
247 && (usid
->identifier_authority
.high_part
== const_cpu_to_be16(0))
248 && (usid
->identifier_authority
.low_part
== const_cpu_to_be32(5))
249 && (usid
->sub_authority
[0] == const_cpu_to_le32(32))
250 && (usid
->sub_authority
[1] == const_cpu_to_le32(545)))
252 /* check whether S-1-5-11 : authenticated user */
253 || ((usid
->sub_authority_count
== 1)
254 && (usid
->identifier_authority
.high_part
== const_cpu_to_be16(0))
255 && (usid
->identifier_authority
.low_part
== const_cpu_to_be32(5))
256 && (usid
->sub_authority
[0] == const_cpu_to_le32(11)))
261 * Test whether a SID means "some user (or group)"
262 * Currently we only check for S-1-5-21... but we should
263 * probably test for other configurations
266 BOOL
ntfs_is_user_sid(const SID
*usid
)
268 return ((usid
->sub_authority_count
== 5)
269 && (usid
->identifier_authority
.high_part
== const_cpu_to_be16(0))
270 && (usid
->identifier_authority
.low_part
== const_cpu_to_be32(5))
271 && (usid
->sub_authority
[0] == const_cpu_to_le32(21)));
275 * Determine the size of a security attribute
276 * whatever the order of fields
279 unsigned int ntfs_attr_size(const char *attr
)
281 const SECURITY_DESCRIPTOR_RELATIVE
*phead
;
285 unsigned int offdacl
;
286 unsigned int offsacl
;
287 unsigned int offowner
;
288 unsigned int offgroup
;
293 phead
= (const SECURITY_DESCRIPTOR_RELATIVE
*)attr
;
295 * First check group, which is the last field in all descriptors
296 * we build, and in most descriptors built by Windows
298 attrsz
= sizeof(SECURITY_DESCRIPTOR_RELATIVE
);
299 offgroup
= le32_to_cpu(phead
->group
);
300 if (offgroup
>= attrsz
) {
301 /* find end of GSID */
302 psid
= (const SID
*)&attr
[offgroup
];
303 endsid
= offgroup
+ ntfs_sid_size(psid
);
304 if (endsid
> attrsz
) attrsz
= endsid
;
306 offowner
= le32_to_cpu(phead
->owner
);
307 if (offowner
>= attrsz
) {
308 /* find end of USID */
309 psid
= (const SID
*)&attr
[offowner
];
310 endsid
= offowner
+ ntfs_sid_size(psid
);
313 offsacl
= le32_to_cpu(phead
->sacl
);
314 if (offsacl
>= attrsz
) {
315 /* find end of SACL */
316 psacl
= (const ACL
*)&attr
[offsacl
];
317 endacl
= offsacl
+ le16_to_cpu(psacl
->size
);
323 /* find end of DACL */
324 offdacl
= le32_to_cpu(phead
->dacl
);
325 if (offdacl
>= attrsz
) {
326 pdacl
= (const ACL
*)&attr
[offdacl
];
327 endacl
= offdacl
+ le16_to_cpu(pdacl
->size
);
335 * Do sanity checks on a SID read from storage
336 * (just check revision and number of authorities)
339 BOOL
ntfs_valid_sid(const SID
*sid
)
341 return ((sid
->revision
== SID_REVISION
)
342 && (sid
->sub_authority_count
>= 1)
343 && (sid
->sub_authority_count
<= 8));
347 * Check whether a SID is acceptable for an implicit
349 * It should have been already checked it is a valid user SID.
351 * The last authority reference has to be >= 1000 (Windows usage)
352 * and <= 0x7fffffff, so that 30 bits from a uid and 30 more bits
353 * from a gid an be inserted with no overflow.
356 BOOL
ntfs_valid_pattern(const SID
*sid
)
362 cnt
= sid
->sub_authority_count
;
363 leauth
= sid
->sub_authority
[cnt
-1];
364 auth
= le32_to_cpu(leauth
);
365 return ((auth
>= 1000) && (auth
<= 0x7fffffff));
369 * Compute the uid or gid associated to a SID
370 * through an implicit mapping
372 * Returns 0 (root) if it does not match pattern
375 static u32
findimplicit(const SID
*xsid
, const SID
*pattern
, int parity
)
379 u32 xid
; /* uid or gid */
387 memcpy(&defsid
,pattern
,ntfs_sid_size(pattern
));
388 psid
= (SID
*)&defsid
;
389 cnt
= psid
->sub_authority_count
;
391 if (xsid
->sub_authority_count
== cnt
) {
392 psid
->sub_authority
[cnt
-1] = xsid
->sub_authority
[cnt
-1];
393 leauth
= xsid
->sub_authority
[cnt
-1];
394 xlast
= le32_to_cpu(leauth
);
395 leauth
= pattern
->sub_authority
[cnt
-1];
396 rlast
= le32_to_cpu(leauth
);
398 if ((xlast
> rlast
) && !((xlast
^ rlast
^ parity
) & 1)) {
399 /* direct check for basic situation */
400 if (ntfs_same_sid(psid
,xsid
))
401 xid
= ((xlast
- rlast
) >> 1) & 0x3fffffff;
404 * check whether part of mapping had to be
405 * recorded in a higher level authority
409 leauth
= psid
->sub_authority
[cnt
-2];
410 uauth
= le32_to_cpu(leauth
) + 1;
411 psid
->sub_authority
[cnt
-2]
412 = cpu_to_le32(uauth
);
413 } while (!ntfs_same_sid(psid
,xsid
)
416 xid
= (((xlast
- rlast
) >> 1)
417 & 0x3fffffff) | (carry
<< 30);
425 * Find usid mapped to a Linux user
426 * Returns NULL if not found
429 const SID
*ntfs_find_usid(const struct MAPPING
* usermapping
,
430 uid_t uid
, SID
*defusid
)
432 const struct MAPPING
*p
;
442 while (p
&& p
->xid
&& ((uid_t
)p
->xid
!= uid
))
446 * default pattern has been reached :
447 * build an implicit SID according to pattern
448 * (the pattern format was checked while reading
451 memcpy(defusid
, p
->sid
, ntfs_sid_size(p
->sid
));
452 cnt
= defusid
->sub_authority_count
;
453 leauth
= defusid
->sub_authority
[cnt
-1];
454 uauth
= le32_to_cpu(leauth
) + 2*(uid
& 0x3fffffff);
455 defusid
->sub_authority
[cnt
-1] = cpu_to_le32(uauth
);
456 if (uid
& 0xc0000000) {
457 leauth
= defusid
->sub_authority
[cnt
-2];
458 uauth
= le32_to_cpu(leauth
) + ((uid
>> 30) & 3);
459 defusid
->sub_authority
[cnt
-2] = cpu_to_le32(uauth
);
463 sid
= (p
? p
->sid
: (const SID
*)NULL
);
469 * Find Linux group mapped to a gsid
470 * Returns 0 (root) if not found
473 const SID
*ntfs_find_gsid(const struct MAPPING
* groupmapping
,
474 gid_t gid
, SID
*defgsid
)
476 const struct MAPPING
*p
;
486 while (p
&& p
->xid
&& ((gid_t
)p
->xid
!= gid
))
490 * default pattern has been reached :
491 * build an implicit SID according to pattern
492 * (the pattern format was checked while reading
495 memcpy(defgsid
, p
->sid
, ntfs_sid_size(p
->sid
));
496 cnt
= defgsid
->sub_authority_count
;
497 leauth
= defgsid
->sub_authority
[cnt
-1];
498 uauth
= le32_to_cpu(leauth
) + 2*(gid
& 0x3fffffff) + 1;
499 defgsid
->sub_authority
[cnt
-1] = cpu_to_le32(uauth
);
500 if (gid
& 0xc0000000) {
501 leauth
= defgsid
->sub_authority
[cnt
-2];
502 uauth
= le32_to_cpu(leauth
) + ((gid
>> 30) & 3);
503 defgsid
->sub_authority
[cnt
-2] = cpu_to_le32(uauth
);
507 sid
= (p
? p
->sid
: (const SID
*)NULL
);
513 * Find Linux owner mapped to a usid
514 * Returns 0 (root) if not found
517 uid_t
ntfs_find_user(const struct MAPPING
* usermapping
, const SID
*usid
)
520 const struct MAPPING
*p
;
523 while (p
&& p
->xid
&& !ntfs_same_sid(usid
, p
->sid
))
527 * No explicit mapping found, try implicit mapping
529 uid
= findimplicit(usid
,p
->sid
,0);
531 uid
= (p
? p
->xid
: 0);
536 * Find Linux group mapped to a gsid
537 * Returns 0 (root) if not found
540 gid_t
ntfs_find_group(const struct MAPPING
* groupmapping
, const SID
* gsid
)
543 const struct MAPPING
*p
;
546 while (p
&& p
->xid
&& !ntfs_same_sid(gsid
, p
->sid
))
550 * No explicit mapping found, try implicit mapping
552 gid
= findimplicit(gsid
,p
->sid
,1);
554 gid
= (p
? p
->xid
: 0);
559 * Check the validity of the ACEs in a DACL or SACL
562 static BOOL
valid_acl(const ACL
*pacl
, unsigned int end
)
564 const ACCESS_ALLOWED_ACE
*pace
;
572 acecnt
= le16_to_cpu(pacl
->ace_count
);
573 offace
= sizeof(ACL
);
574 for (nace
= 0; (nace
< acecnt
) && ok
; nace
++) {
575 /* be sure the beginning is within range */
576 if ((offace
+ sizeof(ACCESS_ALLOWED_ACE
)) > end
)
579 pace
= (const ACCESS_ALLOWED_ACE
*)
580 &((const char*)pacl
)[offace
];
581 acesz
= le16_to_cpu(pace
->size
);
582 if (((offace
+ acesz
) > end
)
583 || !ntfs_valid_sid(&pace
->sid
)
584 || ((ntfs_sid_size(&pace
->sid
) + 8) != (int)acesz
))
593 * Do sanity checks on security descriptors read from storage
594 * basically, we make sure that every field holds within
596 * Should not be called with a NULL argument
597 * returns TRUE if considered safe
598 * if not, error should be logged by caller
601 BOOL
ntfs_valid_descr(const char *securattr
, unsigned int attrsz
)
603 const SECURITY_DESCRIPTOR_RELATIVE
*phead
;
606 unsigned int offdacl
;
607 unsigned int offsacl
;
608 unsigned int offowner
;
609 unsigned int offgroup
;
615 * first check overall size if within allocation range
616 * and a DACL is present
617 * and owner and group SID are valid
620 phead
= (const SECURITY_DESCRIPTOR_RELATIVE
*)securattr
;
621 offdacl
= le32_to_cpu(phead
->dacl
);
622 offsacl
= le32_to_cpu(phead
->sacl
);
623 offowner
= le32_to_cpu(phead
->owner
);
624 offgroup
= le32_to_cpu(phead
->group
);
625 pdacl
= (const ACL
*)&securattr
[offdacl
];
626 psacl
= (const ACL
*)&securattr
[offsacl
];
629 * size check occurs before the above pointers are used
631 * "DR Watson" standard directory on WinXP has an
632 * old revision and no DACL though SE_DACL_PRESENT is set
634 if ((attrsz
>= sizeof(SECURITY_DESCRIPTOR_RELATIVE
))
635 && (phead
->revision
== SECURITY_DESCRIPTOR_REVISION
)
636 && (offowner
>= sizeof(SECURITY_DESCRIPTOR_RELATIVE
))
637 && ((offowner
+ 2) < attrsz
)
638 && (offgroup
>= sizeof(SECURITY_DESCRIPTOR_RELATIVE
))
639 && ((offgroup
+ 2) < attrsz
)
641 || ((offdacl
>= sizeof(SECURITY_DESCRIPTOR_RELATIVE
))
642 && (offdacl
+sizeof(ACL
) < attrsz
)))
644 || ((offsacl
>= sizeof(SECURITY_DESCRIPTOR_RELATIVE
))
645 && (offsacl
+sizeof(ACL
) <= attrsz
)))
646 && !(phead
->owner
& const_cpu_to_le32(3))
647 && !(phead
->group
& const_cpu_to_le32(3))
648 && !(phead
->dacl
& const_cpu_to_le32(3))
649 && !(phead
->sacl
& const_cpu_to_le32(3))
650 && (ntfs_attr_size(securattr
) <= attrsz
)
651 && ntfs_valid_sid((const SID
*)&securattr
[offowner
])
652 && ntfs_valid_sid((const SID
*)&securattr
[offgroup
])
654 * if there is an ACL, as indicated by offdacl,
655 * require SE_DACL_PRESENT
656 * but "Dr Watson" has SE_DACL_PRESENT though no DACL
659 || ((phead
->control
& SE_DACL_PRESENT
)
660 && ((pdacl
->revision
== ACL_REVISION
)
661 || (pdacl
->revision
== ACL_REVISION_DS
))))
664 || ((phead
->control
& SE_SACL_PRESENT
)
665 && ((psacl
->revision
== ACL_REVISION
)
666 || (psacl
->revision
== ACL_REVISION_DS
))))) {
668 * Check the DACL and SACL if present
670 if ((offdacl
&& !valid_acl(pdacl
,attrsz
- offdacl
))
671 || (offsacl
&& !valid_acl(psacl
,attrsz
- offsacl
)))
679 * Copy the inheritable parts of an ACL
681 * Returns the size of the new ACL
682 * or zero if nothing is inheritable
685 int ntfs_inherit_acl(const ACL
*oldacl
, ACL
*newacl
,
686 const SID
*usid
, const SID
*gsid
, BOOL fordir
,
693 unsigned int selection
;
698 const ACCESS_ALLOWED_ACE
*poldace
;
699 ACCESS_ALLOWED_ACE
*pnewace
;
700 ACCESS_ALLOWED_ACE
*pauthace
;
702 pauthace
= (ACCESS_ALLOWED_ACE
*)NULL
;
703 usidsz
= ntfs_sid_size(usid
);
704 gsidsz
= ntfs_sid_size(gsid
);
708 newacl
->revision
= ACL_REVISION
;
709 newacl
->alignment1
= 0;
710 newacl
->alignment2
= const_cpu_to_le16(0);
711 src
= dst
= sizeof(ACL
);
713 selection
= (fordir
? CONTAINER_INHERIT_ACE
: OBJECT_INHERIT_ACE
);
715 oldcnt
= le16_to_cpu(oldacl
->ace_count
);
716 for (nace
= 0; nace
< oldcnt
; nace
++) {
717 poldace
= (const ACCESS_ALLOWED_ACE
*)((const char*)oldacl
+ src
);
718 acesz
= le16_to_cpu(poldace
->size
);
721 * Inheritance for access, unless this is inheriting
722 * an inherited ACL to a directory.
724 if ((poldace
->flags
& selection
)
725 && !(fordir
&& inherited
)
726 && !ntfs_same_sid(&poldace
->sid
, ownersid
)
727 && !ntfs_same_sid(&poldace
->sid
, groupsid
)) {
728 pnewace
= (ACCESS_ALLOWED_ACE
*)
729 ((char*)newacl
+ dst
);
730 memcpy(pnewace
,poldace
,acesz
);
731 /* reencode GENERIC_ALL */
732 if (pnewace
->mask
& GENERIC_ALL
) {
733 pnewace
->mask
&= ~GENERIC_ALL
;
735 pnewace
->mask
|= OWNER_RIGHTS
741 * The last flag is not defined for a file,
742 * however Windows sets it, so do the same
744 pnewace
->mask
|= OWNER_RIGHTS
750 /* reencode GENERIC_READ (+ EXECUTE) */
751 if (pnewace
->mask
& GENERIC_READ
) {
753 pnewace
->mask
|= OWNER_RIGHTS
757 pnewace
->mask
|= OWNER_RIGHTS
760 pnewace
->mask
&= ~(GENERIC_READ
764 | DELETE
| FILE_WRITE_EA
765 | FILE_WRITE_ATTRIBUTES
);
767 /* reencode GENERIC_WRITE */
768 if (pnewace
->mask
& GENERIC_WRITE
) {
770 pnewace
->mask
|= OWNER_RIGHTS
773 pnewace
->mask
|= OWNER_RIGHTS
775 pnewace
->mask
&= ~(GENERIC_WRITE
778 | FILE_DELETE_CHILD
);
780 /* remove inheritance flags */
781 pnewace
->flags
&= ~(OBJECT_INHERIT_ACE
782 | CONTAINER_INHERIT_ACE
785 * Group similar ACE for authenticated users
786 * (should probably be done for other SIDs)
789 && (poldace
->type
== ACCESS_ALLOWED_ACE_TYPE
)
790 && ntfs_same_sid(&poldace
->sid
, authsid
)) {
792 pauthace
->flags
|= pnewace
->flags
;
793 pauthace
->mask
|= pnewace
->mask
;
797 pnewace
->flags
|= INHERITED_ACE
;
803 pnewace
->flags
|= INHERITED_ACE
;
809 * Inheritance for access, specific to
810 * creator-owner (and creator-group)
812 if (fordir
|| !inherited
814 & (CONTAINER_INHERIT_ACE
| OBJECT_INHERIT_ACE
))) {
815 pnewace
= (ACCESS_ALLOWED_ACE
*)
816 ((char*)newacl
+ dst
);
817 memcpy(pnewace
,poldace
,acesz
);
819 * Replace generic creator-owner and
820 * creator-group by owner and group
821 * (but keep for further inheritance)
823 if (ntfs_same_sid(&pnewace
->sid
, ownersid
)) {
824 memcpy(&pnewace
->sid
, usid
, usidsz
);
825 pnewace
->size
= cpu_to_le16(usidsz
+ 8);
826 /* remove inheritance flags */
827 pnewace
->flags
&= ~(OBJECT_INHERIT_ACE
828 | CONTAINER_INHERIT_ACE
831 pnewace
->flags
|= INHERITED_ACE
;
835 if (ntfs_same_sid(&pnewace
->sid
, groupsid
)) {
836 memcpy(&pnewace
->sid
, gsid
, gsidsz
);
837 pnewace
->size
= cpu_to_le16(gsidsz
+ 8);
838 /* remove inheritance flags */
839 pnewace
->flags
&= ~(OBJECT_INHERIT_ACE
840 | CONTAINER_INHERIT_ACE
843 pnewace
->flags
|= INHERITED_ACE
;
849 /* inheritance for further inheritance */
852 & (CONTAINER_INHERIT_ACE
| OBJECT_INHERIT_ACE
))) {
853 pnewace
= (ACCESS_ALLOWED_ACE
*)
854 ((char*)newacl
+ dst
);
855 memcpy(pnewace
,poldace
,acesz
);
857 pnewace
->flags
|= INHERITED_ACE
;
863 * Adjust header if something was inherited
865 if (dst
> sizeof(ACL
)) {
866 newacl
->ace_count
= cpu_to_le16(newcnt
);
867 newacl
->size
= cpu_to_le16(dst
);
876 * Do sanity checks on a Posix descriptor
877 * Should not be called with a NULL argument
878 * returns TRUE if considered safe
879 * if not, error should be logged by caller
882 BOOL
ntfs_valid_posix(const struct POSIX_SECURITY
*pxdesc
)
884 const struct POSIX_ACL
*pacl
;
900 for (i
=0; i
<2; i
++) {
902 checks
[i
].tagsset
= 0;
903 checks
[i
].owners
= 0;
904 checks
[i
].groups
= 0;
905 checks
[i
].others
= 0;
906 checks
[i
].previous
= 0;
907 checks
[i
].previousid
= 0;
912 * header (strict for now)
914 if ((pacl
->version
!= POSIX_VERSION
)
915 || (pacl
->flags
!= 0)
916 || (pacl
->filler
!= 0))
919 * Reject multiple owner, group or other
920 * but do not require them to be present
921 * Also check the ACEs are in correct order
922 * which implies there is no duplicates
924 for (i
=0; i
<pxdesc
->acccnt
+ pxdesc
->defcnt
; i
++) {
925 if (i
>= pxdesc
->firstdef
)
929 perms
= pacl
->ace
[i
].perms
;
930 tag
= pacl
->ace
[i
].tag
;
931 pchk
->tagsset
|= tag
;
932 id
= pacl
->ace
[i
].id
;
933 if (perms
& ~7) ok
= FALSE
;
934 if ((tag
< pchk
->previous
)
935 || ((tag
== pchk
->previous
)
936 && (id
<= pchk
->previousid
)))
938 pchk
->previous
= tag
;
939 pchk
->previousid
= id
;
941 case POSIX_ACL_USER_OBJ
:
946 pchk
->mode
|= perms
<< 6;
948 case POSIX_ACL_GROUP_OBJ
:
953 pchk
->mode
= (pchk
->mode
& 07707) | (perms
<< 3);
955 case POSIX_ACL_OTHER
:
962 case POSIX_ACL_USER
:
963 case POSIX_ACL_GROUP
:
967 case POSIX_ACL_MASK
:
970 pchk
->mode
= (pchk
->mode
& 07707) | (perms
<< 3);
977 if ((pxdesc
->acccnt
> 0)
978 && ((checks
[0].owners
!= 1) || (checks
[0].groups
!= 1)
979 || (checks
[0].others
!= 1)))
981 /* do not check owner, group or other are present in */
982 /* the default ACL, Windows does not necessarily set them */
984 if (pxdesc
->defcnt
&& (pxdesc
->acccnt
> pxdesc
->firstdef
))
986 if ((pxdesc
->acccnt
< 0) || (pxdesc
->defcnt
< 0))
988 /* check mode, unless null or no tag set */
991 && (checks
[0].mode
!= (pxdesc
->mode
& 0777)))
994 if (pxdesc
->tagsset
!= checks
[0].tagsset
)
1000 * Set standard header data into a Posix ACL
1001 * The mode argument should provide the 3 upper bits of target mode
1004 static mode_t
posix_header(struct POSIX_SECURITY
*pxdesc
, mode_t basemode
)
1008 struct POSIX_ACE
*pace
;
1011 mode
= basemode
& 07000;
1013 for (i
=0; i
<pxdesc
->acccnt
; i
++) {
1014 pace
= &pxdesc
->acl
.ace
[i
];
1015 tagsset
|= pace
->tag
;
1017 case POSIX_ACL_USER_OBJ
:
1018 mode
|= (pace
->perms
& 7) << 6;
1020 case POSIX_ACL_GROUP_OBJ
:
1021 case POSIX_ACL_MASK
:
1022 mode
= (mode
& 07707) | ((pace
->perms
& 7) << 3);
1024 case POSIX_ACL_OTHER
:
1025 mode
|= pace
->perms
& 7;
1031 pxdesc
->tagsset
= tagsset
;
1032 pxdesc
->mode
= mode
;
1033 pxdesc
->acl
.version
= POSIX_VERSION
;
1034 pxdesc
->acl
.flags
= 0;
1035 pxdesc
->acl
.filler
= 0;
1040 * Sort ACEs in a Posix ACL
1041 * This is useful for always getting reusable converted ACLs,
1042 * it also helps in merging ACEs.
1043 * Repeated tag+id are allowed and not merged here.
1045 * Tags should be in ascending sequence and for a repeatable tag
1046 * ids should be in ascending sequence.
1049 void ntfs_sort_posix(struct POSIX_SECURITY
*pxdesc
)
1051 struct POSIX_ACL
*pacl
;
1052 struct POSIX_ACE ace
;
1063 * Check sequencing of tag+id in access ACE's
1065 pacl
= &pxdesc
->acl
;
1068 previous
= pacl
->ace
[0].tag
;
1069 previousid
= pacl
->ace
[0].id
;
1070 for (i
=1; i
<pxdesc
->acccnt
; i
++) {
1071 tag
= pacl
->ace
[i
].tag
;
1072 id
= pacl
->ace
[i
].id
;
1074 if ((tag
< previous
)
1075 || ((tag
== previous
) && (id
< previousid
))) {
1077 memcpy(&ace
,&pacl
->ace
[i
-1],sizeof(struct POSIX_ACE
));
1078 memcpy(&pacl
->ace
[i
-1],&pacl
->ace
[i
],sizeof(struct POSIX_ACE
));
1079 memcpy(&pacl
->ace
[i
],&ace
,sizeof(struct POSIX_ACE
));
1087 * Same for default ACEs
1091 if ((pxdesc
->defcnt
) > 1) {
1092 offs
= pxdesc
->firstdef
;
1093 previous
= pacl
->ace
[offs
].tag
;
1094 previousid
= pacl
->ace
[offs
].id
;
1095 for (i
=offs
+1; i
<offs
+pxdesc
->defcnt
; i
++) {
1096 tag
= pacl
->ace
[i
].tag
;
1097 id
= pacl
->ace
[i
].id
;
1099 if ((tag
< previous
)
1100 || ((tag
== previous
) && (id
< previousid
))) {
1102 memcpy(&ace
,&pacl
->ace
[i
-1],sizeof(struct POSIX_ACE
));
1103 memcpy(&pacl
->ace
[i
-1],&pacl
->ace
[i
],sizeof(struct POSIX_ACE
));
1104 memcpy(&pacl
->ace
[i
],&ace
,sizeof(struct POSIX_ACE
));
1115 * Merge a new mode into a Posix descriptor
1116 * The Posix descriptor is not reallocated, its size is unchanged
1121 int ntfs_merge_mode_posix(struct POSIX_SECURITY
*pxdesc
, mode_t mode
)
1125 struct POSIX_ACE
*pace
;
1129 todo
= POSIX_ACL_USER_OBJ
| POSIX_ACL_GROUP_OBJ
| POSIX_ACL_OTHER
;
1130 for (i
=pxdesc
->acccnt
-1; i
>=0; i
--) {
1131 pace
= &pxdesc
->acl
.ace
[i
];
1133 case POSIX_ACL_USER_OBJ
:
1134 pace
->perms
= (mode
>> 6) & 7;
1135 todo
&= ~POSIX_ACL_USER_OBJ
;
1137 case POSIX_ACL_GROUP_OBJ
:
1139 pace
->perms
= (mode
>> 3) & 7;
1140 todo
&= ~POSIX_ACL_GROUP_OBJ
;
1142 case POSIX_ACL_MASK
:
1143 pace
->perms
= (mode
>> 3) & 7;
1146 case POSIX_ACL_OTHER
:
1147 pace
->perms
= mode
& 7;
1148 todo
&= ~POSIX_ACL_OTHER
;
1154 pxdesc
->mode
= mode
;
1155 return (todo
? -1 : 0);
1159 * Replace an access or default Posix ACL
1160 * The resulting ACL is checked for validity
1162 * Returns a new ACL or NULL if there is a problem
1165 struct POSIX_SECURITY
*ntfs_replace_acl(const struct POSIX_SECURITY
*oldpxdesc
,
1166 const struct POSIX_ACL
*newacl
, int count
, BOOL deflt
)
1168 struct POSIX_SECURITY
*newpxdesc
;
1175 newsize
= sizeof(struct POSIX_SECURITY
)
1176 + (oldpxdesc
->acccnt
+ count
)*sizeof(struct POSIX_ACE
);
1178 newsize
= sizeof(struct POSIX_SECURITY
)
1179 + (oldpxdesc
->defcnt
+ count
)*sizeof(struct POSIX_ACE
);
1180 newpxdesc
= (struct POSIX_SECURITY
*)malloc(newsize
);
1183 offset
= oldpxdesc
->acccnt
;
1184 newpxdesc
->acccnt
= oldpxdesc
->acccnt
;
1185 newpxdesc
->defcnt
= count
;
1186 newpxdesc
->firstdef
= offset
;
1187 /* copy access ACEs */
1188 for (i
=0; i
<newpxdesc
->acccnt
; i
++)
1189 newpxdesc
->acl
.ace
[i
] = oldpxdesc
->acl
.ace
[i
];
1190 /* copy default ACEs */
1191 for (i
=0; i
<count
; i
++)
1192 newpxdesc
->acl
.ace
[i
+ offset
] = newacl
->ace
[i
];
1195 newpxdesc
->acccnt
= count
;
1196 newpxdesc
->defcnt
= oldpxdesc
->defcnt
;
1197 newpxdesc
->firstdef
= count
;
1198 /* copy access ACEs */
1199 for (i
=0; i
<count
; i
++)
1200 newpxdesc
->acl
.ace
[i
] = newacl
->ace
[i
];
1201 /* copy default ACEs */
1202 oldoffset
= oldpxdesc
->firstdef
;
1203 for (i
=0; i
<newpxdesc
->defcnt
; i
++)
1204 newpxdesc
->acl
.ace
[i
+ offset
] = oldpxdesc
->acl
.ace
[i
+ oldoffset
];
1206 /* assume special flags unchanged */
1207 posix_header(newpxdesc
, oldpxdesc
->mode
);
1208 if (!ntfs_valid_posix(newpxdesc
)) {
1209 /* do not log, this is an application error */
1211 newpxdesc
= (struct POSIX_SECURITY
*)NULL
;
1220 * Build an inherited Posix descriptor from parent
1221 * descriptor (if any) restricted to creation mode
1223 * Returns the inherited descriptor or NULL if there is a problem
1226 struct POSIX_SECURITY
*ntfs_build_inherited_posix(
1227 const struct POSIX_SECURITY
*pxdesc
, mode_t mode
,
1228 mode_t mask
, BOOL isdir
)
1230 struct POSIX_SECURITY
*pydesc
;
1231 struct POSIX_ACE
*pyace
;
1238 if (pxdesc
&& pxdesc
->defcnt
) {
1240 count
= 2*pxdesc
->defcnt
+ 3;
1242 count
= pxdesc
->defcnt
+ 3;
1245 pydesc
= (struct POSIX_SECURITY
*)malloc(
1246 sizeof(struct POSIX_SECURITY
) + count
*sizeof(struct POSIX_ACE
));
1249 * Copy inherited tags and adapt perms
1250 * Use requested mode, ignoring umask
1251 * (not possible with older versions of fuse)
1254 defcnt
= (pxdesc
? pxdesc
->defcnt
: 0);
1255 for (i
=defcnt
-1; i
>=0; i
--) {
1256 pyace
= &pydesc
->acl
.ace
[i
];
1257 *pyace
= pxdesc
->acl
.ace
[pxdesc
->firstdef
+ i
];
1258 switch (pyace
->tag
) {
1259 case POSIX_ACL_USER_OBJ
:
1260 pyace
->perms
&= (mode
>> 6) & 7;
1262 case POSIX_ACL_GROUP_OBJ
:
1263 if (!(tagsset
& POSIX_ACL_MASK
))
1264 pyace
->perms
&= (mode
>> 3) & 7;
1266 case POSIX_ACL_OTHER
:
1267 pyace
->perms
&= mode
& 7;
1269 case POSIX_ACL_MASK
:
1270 pyace
->perms
&= (mode
>> 3) & 7;
1275 tagsset
|= pyace
->tag
;
1277 pydesc
->acccnt
= defcnt
;
1279 * If some standard tags were missing, append them from mode
1281 * Here we have to use the umask'ed mode
1283 if (~tagsset
& (POSIX_ACL_USER_OBJ
1284 | POSIX_ACL_GROUP_OBJ
| POSIX_ACL_OTHER
)) {
1286 /* owner was missing */
1287 if (!(tagsset
& POSIX_ACL_USER_OBJ
)) {
1288 pyace
= &pydesc
->acl
.ace
[i
];
1289 pyace
->tag
= POSIX_ACL_USER_OBJ
;
1291 pyace
->perms
= ((mode
& ~mask
) >> 6) & 7;
1292 tagsset
|= POSIX_ACL_USER_OBJ
;
1295 /* owning group was missing */
1296 if (!(tagsset
& POSIX_ACL_GROUP_OBJ
)) {
1297 pyace
= &pydesc
->acl
.ace
[i
];
1298 pyace
->tag
= POSIX_ACL_GROUP_OBJ
;
1300 pyace
->perms
= ((mode
& ~mask
) >> 3) & 7;
1301 tagsset
|= POSIX_ACL_GROUP_OBJ
;
1304 /* other was missing */
1305 if (!(tagsset
& POSIX_ACL_OTHER
)) {
1306 pyace
= &pydesc
->acl
.ace
[i
];
1307 pyace
->tag
= POSIX_ACL_OTHER
;
1309 pyace
->perms
= mode
& ~mask
& 7;
1310 tagsset
|= POSIX_ACL_OTHER
;
1314 pydesc
->firstdef
= i
;
1316 ntfs_sort_posix(pydesc
);
1320 * append as a default ACL if a directory
1322 pydesc
->firstdef
= pydesc
->acccnt
;
1323 if (defcnt
&& isdir
) {
1324 size
= sizeof(struct POSIX_ACE
)*defcnt
;
1325 memcpy(&pydesc
->acl
.ace
[pydesc
->firstdef
],
1326 &pxdesc
->acl
.ace
[pxdesc
->firstdef
],size
);
1327 pydesc
->defcnt
= defcnt
;
1331 /* assume special bits are not inherited */
1332 posix_header(pydesc
, mode
& 07000);
1333 if (!ntfs_valid_posix(pydesc
)) {
1334 ntfs_log_error("Error building an inherited Posix desc\n");
1337 pydesc
= (struct POSIX_SECURITY
*)NULL
;
1344 static int merge_lists_posix(struct POSIX_ACE
*targetace
,
1345 const struct POSIX_ACE
*firstace
,
1346 const struct POSIX_ACE
*secondace
,
1347 int firstcnt
, int secondcnt
)
1353 * No list is exhausted :
1354 * if same tag+id in both list :
1355 * ignore ACE from second list
1356 * else take the one with smaller tag+id
1358 while ((firstcnt
> 0) && (secondcnt
> 0))
1359 if ((firstace
->tag
== secondace
->tag
)
1360 && (firstace
->id
== secondace
->id
)) {
1364 if ((firstace
->tag
< secondace
->tag
)
1365 || ((firstace
->tag
== secondace
->tag
)
1366 && (firstace
->id
< secondace
->id
))) {
1367 targetace
->tag
= firstace
->tag
;
1368 targetace
->id
= firstace
->id
;
1369 targetace
->perms
= firstace
->perms
;
1375 targetace
->tag
= secondace
->tag
;
1376 targetace
->id
= secondace
->id
;
1377 targetace
->perms
= secondace
->perms
;
1384 * One list is exhausted, copy the other one
1386 while (firstcnt
> 0) {
1387 targetace
->tag
= firstace
->tag
;
1388 targetace
->id
= firstace
->id
;
1389 targetace
->perms
= firstace
->perms
;
1395 while (secondcnt
> 0) {
1396 targetace
->tag
= secondace
->tag
;
1397 targetace
->id
= secondace
->id
;
1398 targetace
->perms
= secondace
->perms
;
1408 * Merge two Posix ACLs
1409 * The input ACLs have to be adequately sorted
1411 * Returns the merged ACL, which is allocated and has to be freed by caller,
1415 struct POSIX_SECURITY
*ntfs_merge_descr_posix(const struct POSIX_SECURITY
*first
,
1416 const struct POSIX_SECURITY
*second
)
1418 struct POSIX_SECURITY
*pxdesc
;
1419 struct POSIX_ACE
*targetace
;
1420 const struct POSIX_ACE
*firstace
;
1421 const struct POSIX_ACE
*secondace
;
1425 size
= sizeof(struct POSIX_SECURITY
)
1426 + (first
->acccnt
+ first
->defcnt
1427 + second
->acccnt
+ second
->defcnt
)*sizeof(struct POSIX_ACE
);
1428 pxdesc
= (struct POSIX_SECURITY
*)malloc(size
);
1433 firstace
= first
->acl
.ace
;
1434 secondace
= second
->acl
.ace
;
1435 targetace
= pxdesc
->acl
.ace
;
1436 k
= merge_lists_posix(targetace
,firstace
,secondace
,
1437 first
->acccnt
,second
->acccnt
);
1440 * merge default ACEs
1442 pxdesc
->firstdef
= k
;
1443 firstace
= &first
->acl
.ace
[first
->firstdef
];
1444 secondace
= &second
->acl
.ace
[second
->firstdef
];
1445 targetace
= &pxdesc
->acl
.ace
[k
];
1446 k
= merge_lists_posix(targetace
,firstace
,secondace
,
1447 first
->defcnt
,second
->defcnt
);
1452 pxdesc
->acl
.version
= POSIX_VERSION
;
1453 pxdesc
->acl
.flags
= 0;
1454 pxdesc
->acl
.filler
= 0;
1456 pxdesc
->tagsset
= 0;
1462 struct BUILD_CONTEXT
{
1478 static BOOL
build_user_denials(ACL
*pacl
,
1479 const SID
*usid
, struct MAPPING
* const mapping
[],
1480 ACE_FLAGS flags
, const struct POSIX_ACE
*pxace
,
1481 struct BUILD_CONTEXT
*pset
)
1484 ACCESS_ALLOWED_ACE
*pdace
;
1500 perms
= pxace
->perms
;
1502 pos
= le16_to_cpu(pacl
->size
);
1503 acecnt
= le16_to_cpu(pacl
->ace_count
);
1504 avoidmask
= (pset
->mask
== (POSIX_PERM_R
| POSIX_PERM_W
| POSIX_PERM_X
))
1505 && ((pset
->designates
&& pset
->withmask
)
1506 || (!pset
->designates
&& !pset
->withmask
));
1507 if (tag
== POSIX_ACL_USER_OBJ
) {
1509 sidsz
= ntfs_sid_size(sid
);
1510 grants
= OWNER_RIGHTS
;
1513 sid
= NTFS_FIND_USID(mapping
[MAPUSERS
],
1514 pxace
->id
, (SID
*)&defsid
);
1515 grants
= WORLD_RIGHTS
;
1519 grants
= WORLD_RIGHTS
& ~ROOT_OWNER_UNMARK
;
1522 sidsz
= ntfs_sid_size(sid
);
1524 * Insert denial of complement of mask for
1525 * each designated user (except root)
1526 * WRITE_OWNER is inserted so that
1527 * the mask can be identified
1529 if (!avoidmask
&& !rootuser
) {
1530 denials
= WRITE_OWNER
;
1531 pdace
= (ACCESS_DENIED_ACE
*)&((char*)pacl
)[pos
];
1533 if (!(pset
->mask
& POSIX_PERM_X
))
1534 denials
|= DIR_EXEC
;
1535 if (!(pset
->mask
& POSIX_PERM_W
))
1536 denials
|= DIR_WRITE
;
1537 if (!(pset
->mask
& POSIX_PERM_R
))
1538 denials
|= DIR_READ
;
1540 if (!(pset
->mask
& POSIX_PERM_X
))
1541 denials
|= FILE_EXEC
;
1542 if (!(pset
->mask
& POSIX_PERM_W
))
1543 denials
|= FILE_WRITE
;
1544 if (!(pset
->mask
& POSIX_PERM_R
))
1545 denials
|= FILE_READ
;
1548 grants
&= ~ROOT_OWNER_UNMARK
;
1549 pdace
->type
= ACCESS_DENIED_ACE_TYPE
;
1550 pdace
->flags
= flags
;
1551 pdace
->size
= cpu_to_le16(sidsz
+ 8);
1552 pdace
->mask
= denials
;
1553 memcpy((char*)&pdace
->sid
, sid
, sidsz
);
1562 if (perms
& POSIX_PERM_X
)
1564 if (perms
& POSIX_PERM_W
)
1565 grants
|= DIR_WRITE
;
1566 if (perms
& POSIX_PERM_R
)
1569 if (perms
& POSIX_PERM_X
)
1570 grants
|= FILE_EXEC
;
1571 if (perms
& POSIX_PERM_W
)
1572 grants
|= FILE_WRITE
;
1573 if (perms
& POSIX_PERM_R
)
1574 grants
|= FILE_READ
;
1577 /* a possible ACE to deny owner what he/she would */
1578 /* induely get from administrator, group or world */
1579 /* unless owner is administrator or group */
1581 denials
= const_cpu_to_le32(0);
1582 pdace
= (ACCESS_DENIED_ACE
*)&((char*)pacl
)[pos
];
1583 if (!pset
->adminowns
&& !rootuser
) {
1584 if (!pset
->groupowns
) {
1585 mixperms
= pset
->grpperms
| pset
->othperms
;
1586 if (tag
== POSIX_ACL_USER_OBJ
)
1587 mixperms
|= pset
->selfuserperms
;
1589 if (mixperms
& POSIX_PERM_X
)
1590 denials
|= DIR_EXEC
;
1591 if (mixperms
& POSIX_PERM_W
)
1592 denials
|= DIR_WRITE
;
1593 if (mixperms
& POSIX_PERM_R
)
1594 denials
|= DIR_READ
;
1596 if (mixperms
& POSIX_PERM_X
)
1597 denials
|= FILE_EXEC
;
1598 if (mixperms
& POSIX_PERM_W
)
1599 denials
|= FILE_WRITE
;
1600 if (mixperms
& POSIX_PERM_R
)
1601 denials
|= FILE_READ
;
1604 mixperms
= ~pset
->grpperms
& pset
->othperms
;
1605 if (tag
== POSIX_ACL_USER_OBJ
)
1606 mixperms
|= pset
->selfuserperms
;
1608 if (mixperms
& POSIX_PERM_X
)
1609 denials
|= DIR_EXEC
;
1610 if (mixperms
& POSIX_PERM_W
)
1611 denials
|= DIR_WRITE
;
1612 if (mixperms
& POSIX_PERM_R
)
1613 denials
|= DIR_READ
;
1615 if (mixperms
& POSIX_PERM_X
)
1616 denials
|= FILE_EXEC
;
1617 if (mixperms
& POSIX_PERM_W
)
1618 denials
|= FILE_WRITE
;
1619 if (mixperms
& POSIX_PERM_R
)
1620 denials
|= FILE_READ
;
1625 pdace
->type
= ACCESS_DENIED_ACE_TYPE
;
1626 pdace
->flags
= flags
;
1627 pdace
->size
= cpu_to_le16(sidsz
+ 8);
1628 pdace
->mask
= denials
;
1629 memcpy((char*)&pdace
->sid
, sid
, sidsz
);
1635 pacl
->size
= cpu_to_le16(pos
);
1636 pacl
->ace_count
= cpu_to_le16(acecnt
);
1640 static BOOL
build_user_grants(ACL
*pacl
,
1641 const SID
*usid
, struct MAPPING
* const mapping
[],
1642 ACE_FLAGS flags
, const struct POSIX_ACE
*pxace
,
1643 struct BUILD_CONTEXT
*pset
)
1646 ACCESS_ALLOWED_ACE
*pgace
;
1659 perms
= pxace
->perms
;
1661 pos
= le16_to_cpu(pacl
->size
);
1662 acecnt
= le16_to_cpu(pacl
->ace_count
);
1663 if (tag
== POSIX_ACL_USER_OBJ
) {
1665 sidsz
= ntfs_sid_size(sid
);
1666 grants
= OWNER_RIGHTS
;
1669 sid
= NTFS_FIND_USID(mapping
[MAPUSERS
],
1670 pxace
->id
, (SID
*)&defsid
);
1672 sidsz
= ntfs_sid_size(sid
);
1675 grants
= WORLD_RIGHTS
;
1678 sidsz
= ntfs_sid_size(sid
);
1680 grants
= WORLD_RIGHTS
& ~ROOT_OWNER_UNMARK
;
1685 if (perms
& POSIX_PERM_X
)
1687 if (perms
& POSIX_PERM_W
)
1688 grants
|= DIR_WRITE
;
1689 if (perms
& POSIX_PERM_R
)
1692 if (perms
& POSIX_PERM_X
)
1693 grants
|= FILE_EXEC
;
1694 if (perms
& POSIX_PERM_W
)
1695 grants
|= FILE_WRITE
;
1696 if (perms
& POSIX_PERM_R
)
1697 grants
|= FILE_READ
;
1700 grants
&= ~ROOT_OWNER_UNMARK
;
1701 pgace
= (ACCESS_DENIED_ACE
*)&((char*)pacl
)[pos
];
1702 pgace
->type
= ACCESS_ALLOWED_ACE_TYPE
;
1703 pgace
->size
= cpu_to_le16(sidsz
+ 8);
1704 pgace
->flags
= flags
;
1705 pgace
->mask
= grants
;
1706 memcpy((char*)&pgace
->sid
, sid
, sidsz
);
1708 acecnt
= le16_to_cpu(pacl
->ace_count
) + 1;
1709 pacl
->ace_count
= cpu_to_le16(acecnt
);
1710 pacl
->size
= cpu_to_le16(pos
);
1716 /* a grant ACE for group */
1717 /* unless group-obj has the same rights as world */
1718 /* but present if group is owner or owner is administrator */
1719 /* this ACE will be inserted after denials for group */
1721 static BOOL
build_group_denials_grant(ACL
*pacl
,
1722 const SID
*gsid
, struct MAPPING
* const mapping
[],
1723 ACE_FLAGS flags
, const struct POSIX_ACE
*pxace
,
1724 struct BUILD_CONTEXT
*pset
)
1727 ACCESS_ALLOWED_ACE
*pdace
;
1728 ACCESS_ALLOWED_ACE
*pgace
;
1744 perms
= pxace
->perms
;
1745 pos
= le16_to_cpu(pacl
->size
);
1746 acecnt
= le16_to_cpu(pacl
->ace_count
);
1748 avoidmask
= (pset
->mask
== (POSIX_PERM_R
| POSIX_PERM_W
| POSIX_PERM_X
))
1749 && ((pset
->designates
&& pset
->withmask
)
1750 || (!pset
->designates
&& !pset
->withmask
));
1751 if (tag
== POSIX_ACL_GROUP_OBJ
)
1755 sid
= NTFS_FIND_GSID(mapping
[MAPGROUPS
],
1756 pxace
->id
, (SID
*)&defsid
);
1762 sidsz
= ntfs_sid_size(sid
);
1764 * Insert denial of complement of mask for
1766 * WRITE_OWNER is inserted so that
1767 * the mask can be identified
1768 * Note : this mask may lead on Windows to
1769 * deny rights to administrators belonging
1770 * to some user group
1772 if ((!avoidmask
&& !rootgroup
)
1773 || (pset
->rootspecial
1774 && (tag
== POSIX_ACL_GROUP_OBJ
))) {
1775 denials
= WRITE_OWNER
;
1776 pdace
= (ACCESS_DENIED_ACE
*)&((char*)pacl
)[pos
];
1778 if (!(pset
->mask
& POSIX_PERM_X
))
1779 denials
|= DIR_EXEC
;
1780 if (!(pset
->mask
& POSIX_PERM_W
))
1781 denials
|= DIR_WRITE
;
1782 if (!(pset
->mask
& POSIX_PERM_R
))
1783 denials
|= DIR_READ
;
1785 if (!(pset
->mask
& POSIX_PERM_X
))
1786 denials
|= FILE_EXEC
;
1787 if (!(pset
->mask
& POSIX_PERM_W
))
1788 denials
|= FILE_WRITE
;
1789 if (!(pset
->mask
& POSIX_PERM_R
))
1790 denials
|= FILE_READ
;
1792 pdace
->type
= ACCESS_DENIED_ACE_TYPE
;
1793 pdace
->flags
= flags
;
1794 pdace
->size
= cpu_to_le16(sidsz
+ 8);
1795 pdace
->mask
= denials
;
1796 memcpy((char*)&pdace
->sid
, sid
, sidsz
);
1807 || (perms
!= pset
->othperms
))) {
1808 grants
= WORLD_RIGHTS
;
1810 grants
&= ~ROOT_GROUP_UNMARK
;
1812 if (perms
& POSIX_PERM_X
)
1814 if (perms
& POSIX_PERM_W
)
1815 grants
|= DIR_WRITE
;
1816 if (perms
& POSIX_PERM_R
)
1819 if (perms
& POSIX_PERM_X
)
1820 grants
|= FILE_EXEC
;
1821 if (perms
& POSIX_PERM_W
)
1822 grants
|= FILE_WRITE
;
1823 if (perms
& POSIX_PERM_R
)
1824 grants
|= FILE_READ
;
1827 /* a possible ACE to deny group what it would get from world */
1828 /* or administrator, unless owner is administrator or group */
1830 denials
= const_cpu_to_le32(0);
1831 pdace
= (ACCESS_DENIED_ACE
*)&((char*)pacl
)[pos
];
1832 if (!pset
->adminowns
1835 mixperms
= pset
->othperms
;
1836 if (tag
== POSIX_ACL_GROUP_OBJ
)
1837 mixperms
|= pset
->selfgrpperms
;
1839 if (mixperms
& POSIX_PERM_X
)
1840 denials
|= DIR_EXEC
;
1841 if (mixperms
& POSIX_PERM_W
)
1842 denials
|= DIR_WRITE
;
1843 if (mixperms
& POSIX_PERM_R
)
1844 denials
|= DIR_READ
;
1846 if (mixperms
& POSIX_PERM_X
)
1847 denials
|= FILE_EXEC
;
1848 if (mixperms
& POSIX_PERM_W
)
1849 denials
|= FILE_WRITE
;
1850 if (mixperms
& POSIX_PERM_R
)
1851 denials
|= FILE_READ
;
1853 denials
&= ~(grants
| OWNER_RIGHTS
);
1855 pdace
->type
= ACCESS_DENIED_ACE_TYPE
;
1856 pdace
->flags
= flags
;
1857 pdace
->size
= cpu_to_le16(sidsz
+ 8);
1858 pdace
->mask
= denials
;
1859 memcpy((char*)&pdace
->sid
, sid
, sidsz
);
1865 /* now insert grants to group if more than world */
1868 || (avoidmask
&& (pset
->designates
|| pset
->withmask
))
1869 || (perms
& ~pset
->othperms
)
1870 || (pset
->rootspecial
1871 && (tag
== POSIX_ACL_GROUP_OBJ
))
1872 || (tag
== POSIX_ACL_GROUP
)) {
1874 grants
&= ~ROOT_GROUP_UNMARK
;
1875 pgace
= (ACCESS_DENIED_ACE
*)&((char*)pacl
)[pos
];
1876 pgace
->type
= ACCESS_ALLOWED_ACE_TYPE
;
1877 pgace
->flags
= flags
;
1878 pgace
->size
= cpu_to_le16(sidsz
+ 8);
1879 pgace
->mask
= grants
;
1880 memcpy((char*)&pgace
->sid
, sid
, sidsz
);
1885 pacl
->size
= cpu_to_le16(pos
);
1886 pacl
->ace_count
= cpu_to_le16(acecnt
);
1892 * Build an ACL composed of several ACE's
1893 * returns size of ACL or zero if failed
1895 * Three schemes are defined :
1897 * 1) if root is neither owner nor group up to 7 ACE's are set up :
1898 * - denials to owner (preventing grants to world or group to apply)
1899 * + mask denials to designated user (unless mask allows all)
1900 * + denials to designated user
1901 * - grants to owner (always present - first grant)
1902 * + grants to designated user
1903 * + mask denial to group (unless mask allows all)
1904 * - denials to group (preventing grants to world to apply)
1905 * - grants to group (unless group has no more than world rights)
1906 * + mask denials to designated group (unless mask allows all)
1907 * + grants to designated group
1908 * + denials to designated group
1909 * - grants to world (unless none)
1910 * - full privileges to administrator, always present
1911 * - full privileges to system, always present
1913 * The same scheme is applied for Posix ACLs, with the mask represented
1914 * as denials prepended to grants for designated users and groups
1916 * This is inspired by an Internet Draft from Marius Aamodt Eriksen
1917 * for mapping NFSv4 ACLs to Posix ACLs (draft-ietf-nfsv4-acl-mapping-00.txt)
1918 * More recent versions of the draft (draft-ietf-nfsv4-acl-mapping-05.txt)
1919 * are not followed, as they ignore the Posix mask and lead to
1920 * loss of compatibility with Linux implementations on other fs.
1922 * Note that denials to group are located after grants to owner.
1923 * This only occurs in the unfrequent situation where world
1924 * has more rights than group and cannot be avoided if owner and other
1925 * have some common right which is denied to group (eg for mode 745
1926 * executing has to be denied to group, but not to owner or world).
1927 * This rare situation is processed by Windows correctly, but
1928 * Windows utilities may want to change the order, with a
1929 * consequence of applying the group denials to the Windows owner.
1930 * The interpretation on Linux is not affected by the order change.
1932 * 2) if root is either owner or group, two problems arise :
1933 * - granting full rights to administrator (as needed to transpose
1934 * to Windows rights bypassing granting to root) would imply
1935 * Linux permissions to always be seen as rwx, no matter the chmod
1936 * - there is no different SID to separate an administrator owner
1937 * from an administrator group. Hence Linux permissions for owner
1938 * would always be similar to permissions to group.
1940 * as a work-around, up to 5 ACE's are set up if owner or group :
1941 * - grants to owner, always present at first position
1942 * - grants to group, always present
1943 * - grants to world, unless none
1944 * - full privileges to administrator, always present
1945 * - full privileges to system, always present
1947 * On Windows, these ACE's are processed normally, though they
1948 * are redundant (owner, group and administrator are the same,
1949 * as a consequence any denials would damage administrator rights)
1950 * but on Linux, privileges to administrator are ignored (they
1951 * are not needed as root has always full privileges), and
1952 * neither grants to group are applied to owner, nor grants to
1953 * world are applied to owner or group.
1955 * 3) finally a similar situation arises when group is owner (they
1956 * have the same SID), but is not root.
1957 * In this situation up to 6 ACE's are set up :
1959 * - denials to owner (preventing grants to world to apply)
1960 * - grants to owner (always present)
1961 * - grants to group (unless groups has same rights as world)
1962 * - grants to world (unless none)
1963 * - full privileges to administrator, always present
1964 * - full privileges to system, always present
1966 * On Windows, these ACE's are processed normally, though they
1967 * are redundant (as owner and group are the same), but this has
1968 * no impact on administrator rights
1970 * Special flags (S_ISVTX, S_ISGID, S_ISUID) :
1971 * an extra null ACE is inserted to hold these flags, using
1972 * the same conventions as cygwin.
1976 static int buildacls_posix(struct MAPPING
* const mapping
[],
1977 char *secattr
, int offs
, const struct POSIX_SECURITY
*pxdesc
,
1978 int isdir
, const SID
*usid
, const SID
*gsid
)
1980 struct BUILD_CONTEXT aceset
[2], *pset
;
1984 ACCESS_ALLOWED_ACE
*pgace
;
1985 ACCESS_ALLOWED_ACE
*pdace
;
1986 const struct POSIX_ACE
*pxace
;
2005 usidsz
= ntfs_sid_size(usid
);
2006 wsidsz
= ntfs_sid_size(worldsid
);
2007 asidsz
= ntfs_sid_size(adminsid
);
2008 ssidsz
= ntfs_sid_size(systemsid
);
2009 mode
= pxdesc
->mode
;
2010 /* adminowns and groupowns are used for both lists */
2011 adminowns
= ntfs_same_sid(usid
, adminsid
)
2012 || ntfs_same_sid(gsid
, adminsid
);
2013 groupowns
= !adminowns
&& ntfs_same_sid(usid
, gsid
);
2018 pacl
= (ACL
*)&secattr
[offs
];
2019 pacl
->revision
= ACL_REVISION
;
2020 pacl
->alignment1
= 0;
2021 pacl
->size
= cpu_to_le16(sizeof(ACL
) + usidsz
+ 8);
2022 pacl
->ace_count
= const_cpu_to_le16(0);
2023 pacl
->alignment2
= const_cpu_to_le16(0);
2026 * Determine what is allowed to some group or world
2027 * to prevent designated users or other groups to get
2028 * rights from groups or world
2029 * Do the same if owner and group appear as designated
2031 * Also get global mask
2033 for (k
=0; k
<2; k
++) {
2035 pset
->selfuserperms
= 0;
2036 pset
->selfgrpperms
= 0;
2039 pset
->mask
= (POSIX_PERM_R
| POSIX_PERM_W
| POSIX_PERM_X
);
2040 pset
->designates
= 0;
2042 pset
->rootspecial
= 0;
2043 pset
->adminowns
= adminowns
;
2044 pset
->groupowns
= groupowns
;
2045 pset
->isdir
= isdir
;
2048 for (i
=pxdesc
->acccnt
+pxdesc
->defcnt
-1; i
>=0; i
--) {
2049 if (i
>= pxdesc
->acccnt
) {
2051 pxace
= &pxdesc
->acl
.ace
[i
+ pxdesc
->firstdef
- pxdesc
->acccnt
];
2054 pxace
= &pxdesc
->acl
.ace
[i
];
2056 switch (pxace
->tag
) {
2057 case POSIX_ACL_USER
:
2060 sid
= NTFS_FIND_USID(mapping
[MAPUSERS
],
2061 pxace
->id
, (SID
*)&defsid
);
2062 if (sid
&& ntfs_same_sid(sid
,usid
))
2063 pset
->selfuserperms
|= pxace
->perms
;
2065 /* root as designated user is processed apart */
2066 pset
->rootspecial
= TRUE
;
2068 case POSIX_ACL_GROUP
:
2071 sid
= NTFS_FIND_GSID(mapping
[MAPUSERS
],
2072 pxace
->id
, (SID
*)&defsid
);
2073 if (sid
&& ntfs_same_sid(sid
,gsid
))
2074 pset
->selfgrpperms
|= pxace
->perms
;
2076 /* root as designated group is processed apart */
2077 pset
->rootspecial
= TRUE
;
2079 case POSIX_ACL_GROUP_OBJ
:
2080 pset
->grpperms
|= pxace
->perms
;
2082 case POSIX_ACL_OTHER
:
2083 pset
->othperms
= pxace
->perms
;
2085 case POSIX_ACL_MASK
:
2087 pset
->mask
= pxace
->perms
;
2093 if (pxdesc
->defcnt
&& (pxdesc
->firstdef
!= pxdesc
->acccnt
)) {
2094 ntfs_log_error("** error : access and default not consecutive\n");
2098 * First insert all denials for owner and each
2099 * designated user (with mask if needed)
2102 pacl
->ace_count
= const_cpu_to_le16(0);
2103 pacl
->size
= const_cpu_to_le16(sizeof(ACL
));
2104 for (i
=0; (i
<(pxdesc
->acccnt
+ pxdesc
->defcnt
)) && ok
; i
++) {
2105 if (i
>= pxdesc
->acccnt
) {
2106 flags
= INHERIT_ONLY_ACE
2107 | OBJECT_INHERIT_ACE
| CONTAINER_INHERIT_ACE
;
2109 pxace
= &pxdesc
->acl
.ace
[i
+ pxdesc
->firstdef
- pxdesc
->acccnt
];
2112 flags
= NO_PROPAGATE_INHERIT_ACE
;
2114 flags
= (isdir
? DIR_INHERITANCE
2115 : FILE_INHERITANCE
);
2117 pxace
= &pxdesc
->acl
.ace
[i
];
2120 perms
= pxace
->perms
;
2123 /* insert denial ACEs for each owner or allowed user */
2125 case POSIX_ACL_USER
:
2126 case POSIX_ACL_USER_OBJ
:
2128 ok
= build_user_denials(pacl
,
2129 usid
, mapping
, flags
, pxace
, pset
);
2137 * for directories, insert a world execution denial
2138 * inherited to plain files.
2139 * This is to prevent Windows from granting execution
2140 * of files through inheritance from parent directory
2144 pos
= le16_to_cpu(pacl
->size
);
2145 pdace
= (ACCESS_DENIED_ACE
*) &secattr
[offs
+ pos
];
2146 pdace
->type
= ACCESS_DENIED_ACE_TYPE
;
2147 pdace
->flags
= INHERIT_ONLY_ACE
| OBJECT_INHERIT_ACE
;
2148 pdace
->size
= cpu_to_le16(wsidsz
+ 8);
2149 pdace
->mask
= FILE_EXEC
;
2150 memcpy((char*)&pdace
->sid
, worldsid
, wsidsz
);
2152 acecnt
= le16_to_cpu(pacl
->ace_count
) + 1;
2153 pacl
->ace_count
= cpu_to_le16(acecnt
);
2154 pacl
->size
= cpu_to_le16(pos
);
2158 * now insert (if needed)
2159 * - grants to owner and designated users
2160 * - mask and denials for all groups
2164 for (i
=0; (i
<(pxdesc
->acccnt
+ pxdesc
->defcnt
)) && ok
; i
++) {
2165 if (i
>= pxdesc
->acccnt
) {
2166 flags
= INHERIT_ONLY_ACE
2167 | OBJECT_INHERIT_ACE
| CONTAINER_INHERIT_ACE
;
2169 pxace
= &pxdesc
->acl
.ace
[i
+ pxdesc
->firstdef
- pxdesc
->acccnt
];
2172 flags
= NO_PROPAGATE_INHERIT_ACE
;
2174 flags
= (isdir
? DIR_INHERITANCE
2175 : FILE_INHERITANCE
);
2177 pxace
= &pxdesc
->acl
.ace
[i
];
2180 perms
= pxace
->perms
;
2183 /* ACE for each owner or allowed user */
2185 case POSIX_ACL_USER
:
2186 case POSIX_ACL_USER_OBJ
:
2187 ok
= build_user_grants(pacl
,usid
,
2188 mapping
,flags
,pxace
,pset
);
2191 case POSIX_ACL_GROUP
:
2192 case POSIX_ACL_GROUP_OBJ
:
2194 /* denials and grants for groups */
2196 ok
= build_group_denials_grant(pacl
,gsid
,
2197 mapping
,flags
,pxace
,pset
);
2200 case POSIX_ACL_OTHER
:
2202 /* grants for other users */
2204 pos
= le16_to_cpu(pacl
->size
);
2205 pgace
= (ACCESS_ALLOWED_ACE
*)&secattr
[offs
+ pos
];
2206 grants
= WORLD_RIGHTS
;
2208 if (perms
& POSIX_PERM_X
)
2210 if (perms
& POSIX_PERM_W
)
2211 grants
|= DIR_WRITE
;
2212 if (perms
& POSIX_PERM_R
)
2215 if (perms
& POSIX_PERM_X
)
2216 grants
|= FILE_EXEC
;
2217 if (perms
& POSIX_PERM_W
)
2218 grants
|= FILE_WRITE
;
2219 if (perms
& POSIX_PERM_R
)
2220 grants
|= FILE_READ
;
2222 pgace
->type
= ACCESS_ALLOWED_ACE_TYPE
;
2223 pgace
->flags
= flags
;
2224 pgace
->size
= cpu_to_le16(wsidsz
+ 8);
2225 pgace
->mask
= grants
;
2226 memcpy((char*)&pgace
->sid
, worldsid
, wsidsz
);
2228 acecnt
= le16_to_cpu(pacl
->ace_count
) + 1;
2229 pacl
->ace_count
= cpu_to_le16(acecnt
);
2230 pacl
->size
= cpu_to_le16(pos
);
2239 /* an ACE for administrators */
2240 /* always full access */
2242 pos
= le16_to_cpu(pacl
->size
);
2243 acecnt
= le16_to_cpu(pacl
->ace_count
);
2245 flags
= OBJECT_INHERIT_ACE
2246 | CONTAINER_INHERIT_ACE
;
2248 flags
= NO_PROPAGATE_INHERIT_ACE
;
2249 pgace
= (ACCESS_ALLOWED_ACE
*)&secattr
[offs
+ pos
];
2250 pgace
->type
= ACCESS_ALLOWED_ACE_TYPE
;
2251 pgace
->flags
= flags
;
2252 pgace
->size
= cpu_to_le16(asidsz
+ 8);
2253 grants
= OWNER_RIGHTS
| FILE_READ
| FILE_WRITE
| FILE_EXEC
;
2254 pgace
->mask
= grants
;
2255 memcpy((char*)&pgace
->sid
, adminsid
, asidsz
);
2259 /* an ACE for system (needed ?) */
2260 /* always full access */
2262 pgace
= (ACCESS_ALLOWED_ACE
*)&secattr
[offs
+ pos
];
2263 pgace
->type
= ACCESS_ALLOWED_ACE_TYPE
;
2264 pgace
->flags
= flags
;
2265 pgace
->size
= cpu_to_le16(ssidsz
+ 8);
2266 grants
= OWNER_RIGHTS
| FILE_READ
| FILE_WRITE
| FILE_EXEC
;
2267 pgace
->mask
= grants
;
2268 memcpy((char*)&pgace
->sid
, systemsid
, ssidsz
);
2272 /* a null ACE to hold special flags */
2273 /* using the same representation as cygwin */
2275 if (mode
& (S_ISVTX
| S_ISGID
| S_ISUID
)) {
2276 nsidsz
= ntfs_sid_size(nullsid
);
2277 pgace
= (ACCESS_ALLOWED_ACE
*)&secattr
[offs
+ pos
];
2278 pgace
->type
= ACCESS_ALLOWED_ACE_TYPE
;
2279 pgace
->flags
= NO_PROPAGATE_INHERIT_ACE
;
2280 pgace
->size
= cpu_to_le16(nsidsz
+ 8);
2281 grants
= const_cpu_to_le32(0);
2283 grants
|= FILE_APPEND_DATA
;
2285 grants
|= FILE_WRITE_DATA
;
2287 grants
|= FILE_READ_DATA
;
2288 pgace
->mask
= grants
;
2289 memcpy((char*)&pgace
->sid
, nullsid
, nsidsz
);
2294 /* fix ACL header */
2295 pacl
->size
= cpu_to_le16(pos
);
2296 pacl
->ace_count
= cpu_to_le16(acecnt
);
2298 return (ok
? pos
: 0);
2301 #endif /* POSIXACLS */
2303 static int buildacls(char *secattr
, int offs
, mode_t mode
, int isdir
,
2304 const SID
* usid
, const SID
* gsid
)
2307 ACCESS_ALLOWED_ACE
*pgace
;
2308 ACCESS_ALLOWED_ACE
*pdace
;
2323 usidsz
= ntfs_sid_size(usid
);
2324 gsidsz
= ntfs_sid_size(gsid
);
2325 wsidsz
= ntfs_sid_size(worldsid
);
2326 asidsz
= ntfs_sid_size(adminsid
);
2327 ssidsz
= ntfs_sid_size(systemsid
);
2328 adminowns
= ntfs_same_sid(usid
, adminsid
)
2329 || ntfs_same_sid(gsid
, adminsid
);
2330 groupowns
= !adminowns
&& ntfs_same_sid(usid
, gsid
);
2333 pacl
= (ACL
*)&secattr
[offs
];
2334 pacl
->revision
= ACL_REVISION
;
2335 pacl
->alignment1
= 0;
2336 pacl
->size
= cpu_to_le16(sizeof(ACL
) + usidsz
+ 8);
2337 pacl
->ace_count
= const_cpu_to_le16(1);
2338 pacl
->alignment2
= const_cpu_to_le16(0);
2342 /* compute a grant ACE for owner */
2343 /* this ACE will be inserted after denial for owner */
2345 grants
= OWNER_RIGHTS
;
2347 gflags
= DIR_INHERITANCE
;
2351 grants
|= DIR_WRITE
;
2355 gflags
= FILE_INHERITANCE
;
2357 grants
|= FILE_EXEC
;
2359 grants
|= FILE_WRITE
;
2361 grants
|= FILE_READ
;
2364 /* a possible ACE to deny owner what he/she would */
2365 /* induely get from administrator, group or world */
2366 /* unless owner is administrator or group */
2368 denials
= const_cpu_to_le32(0);
2369 pdace
= (ACCESS_DENIED_ACE
*) &secattr
[offs
+ pos
];
2373 pdace
->flags
= DIR_INHERITANCE
;
2374 if (mode
& (S_IXGRP
| S_IXOTH
))
2375 denials
|= DIR_EXEC
;
2376 if (mode
& (S_IWGRP
| S_IWOTH
))
2377 denials
|= DIR_WRITE
;
2378 if (mode
& (S_IRGRP
| S_IROTH
))
2379 denials
|= DIR_READ
;
2381 pdace
->flags
= FILE_INHERITANCE
;
2382 if (mode
& (S_IXGRP
| S_IXOTH
))
2383 denials
|= FILE_EXEC
;
2384 if (mode
& (S_IWGRP
| S_IWOTH
))
2385 denials
|= FILE_WRITE
;
2386 if (mode
& (S_IRGRP
| S_IROTH
))
2387 denials
|= FILE_READ
;
2391 pdace
->flags
= DIR_INHERITANCE
;
2392 if ((mode
& S_IXOTH
) && !(mode
& S_IXGRP
))
2393 denials
|= DIR_EXEC
;
2394 if ((mode
& S_IWOTH
) && !(mode
& S_IWGRP
))
2395 denials
|= DIR_WRITE
;
2396 if ((mode
& S_IROTH
) && !(mode
& S_IRGRP
))
2397 denials
|= DIR_READ
;
2399 pdace
->flags
= FILE_INHERITANCE
;
2400 if ((mode
& S_IXOTH
) && !(mode
& S_IXGRP
))
2401 denials
|= FILE_EXEC
;
2402 if ((mode
& S_IWOTH
) && !(mode
& S_IWGRP
))
2403 denials
|= FILE_WRITE
;
2404 if ((mode
& S_IROTH
) && !(mode
& S_IRGRP
))
2405 denials
|= FILE_READ
;
2410 pdace
->type
= ACCESS_DENIED_ACE_TYPE
;
2411 pdace
->size
= cpu_to_le16(usidsz
+ 8);
2412 pdace
->mask
= denials
;
2413 memcpy((char*)&pdace
->sid
, usid
, usidsz
);
2419 * for directories, a world execution denial
2420 * inherited to plain files
2424 pdace
= (ACCESS_DENIED_ACE
*) &secattr
[offs
+ pos
];
2425 pdace
->type
= ACCESS_DENIED_ACE_TYPE
;
2426 pdace
->flags
= INHERIT_ONLY_ACE
| OBJECT_INHERIT_ACE
;
2427 pdace
->size
= cpu_to_le16(wsidsz
+ 8);
2428 pdace
->mask
= FILE_EXEC
;
2429 memcpy((char*)&pdace
->sid
, worldsid
, wsidsz
);
2435 /* now insert grants to owner */
2436 pgace
= (ACCESS_ALLOWED_ACE
*) &secattr
[offs
+ pos
];
2437 pgace
->type
= ACCESS_ALLOWED_ACE_TYPE
;
2438 pgace
->size
= cpu_to_le16(usidsz
+ 8);
2439 pgace
->flags
= gflags
;
2440 pgace
->mask
= grants
;
2441 memcpy((char*)&pgace
->sid
, usid
, usidsz
);
2445 /* a grant ACE for group */
2446 /* unless group has the same rights as world */
2447 /* but present if group is owner or owner is administrator */
2448 /* this ACE will be inserted after denials for group */
2452 || (((mode
>> 3) ^ mode
) & 7)) {
2453 grants
= WORLD_RIGHTS
;
2455 gflags
= DIR_INHERITANCE
;
2459 grants
|= DIR_WRITE
;
2463 gflags
= FILE_INHERITANCE
;
2465 grants
|= FILE_EXEC
;
2467 grants
|= FILE_WRITE
;
2469 grants
|= FILE_READ
;
2472 /* a possible ACE to deny group what it would get from world */
2473 /* or administrator, unless owner is administrator or group */
2475 denials
= const_cpu_to_le32(0);
2476 pdace
= (ACCESS_ALLOWED_ACE
*)&secattr
[offs
+ pos
];
2477 if (!adminowns
&& !groupowns
) {
2479 pdace
->flags
= DIR_INHERITANCE
;
2481 denials
|= DIR_EXEC
;
2483 denials
|= DIR_WRITE
;
2485 denials
|= DIR_READ
;
2487 pdace
->flags
= FILE_INHERITANCE
;
2489 denials
|= FILE_EXEC
;
2491 denials
|= FILE_WRITE
;
2493 denials
|= FILE_READ
;
2495 denials
&= ~(grants
| OWNER_RIGHTS
);
2497 pdace
->type
= ACCESS_DENIED_ACE_TYPE
;
2498 pdace
->size
= cpu_to_le16(gsidsz
+ 8);
2499 pdace
->mask
= denials
;
2500 memcpy((char*)&pdace
->sid
, gsid
, gsidsz
);
2508 || ((mode
>> 3) & ~mode
& 7)) {
2509 /* now insert grants to group */
2510 /* if more rights than other */
2511 pgace
= (ACCESS_ALLOWED_ACE
*)&secattr
[offs
+ pos
];
2512 pgace
->type
= ACCESS_ALLOWED_ACE_TYPE
;
2513 pgace
->flags
= gflags
;
2514 pgace
->size
= cpu_to_le16(gsidsz
+ 8);
2515 pgace
->mask
= grants
;
2516 memcpy((char*)&pgace
->sid
, gsid
, gsidsz
);
2522 /* an ACE for world users */
2524 pgace
= (ACCESS_ALLOWED_ACE
*)&secattr
[offs
+ pos
];
2525 pgace
->type
= ACCESS_ALLOWED_ACE_TYPE
;
2526 grants
= WORLD_RIGHTS
;
2528 pgace
->flags
= DIR_INHERITANCE
;
2532 grants
|= DIR_WRITE
;
2536 pgace
->flags
= FILE_INHERITANCE
;
2538 grants
|= FILE_EXEC
;
2540 grants
|= FILE_WRITE
;
2542 grants
|= FILE_READ
;
2544 pgace
->size
= cpu_to_le16(wsidsz
+ 8);
2545 pgace
->mask
= grants
;
2546 memcpy((char*)&pgace
->sid
, worldsid
, wsidsz
);
2550 /* an ACE for administrators */
2551 /* always full access */
2553 pgace
= (ACCESS_ALLOWED_ACE
*)&secattr
[offs
+ pos
];
2554 pgace
->type
= ACCESS_ALLOWED_ACE_TYPE
;
2556 pgace
->flags
= DIR_INHERITANCE
;
2558 pgace
->flags
= FILE_INHERITANCE
;
2559 pgace
->size
= cpu_to_le16(asidsz
+ 8);
2560 grants
= OWNER_RIGHTS
| FILE_READ
| FILE_WRITE
| FILE_EXEC
;
2561 pgace
->mask
= grants
;
2562 memcpy((char*)&pgace
->sid
, adminsid
, asidsz
);
2566 /* an ACE for system (needed ?) */
2567 /* always full access */
2569 pgace
= (ACCESS_ALLOWED_ACE
*)&secattr
[offs
+ pos
];
2570 pgace
->type
= ACCESS_ALLOWED_ACE_TYPE
;
2572 pgace
->flags
= DIR_INHERITANCE
;
2574 pgace
->flags
= FILE_INHERITANCE
;
2575 pgace
->size
= cpu_to_le16(ssidsz
+ 8);
2576 grants
= OWNER_RIGHTS
| FILE_READ
| FILE_WRITE
| FILE_EXEC
;
2577 pgace
->mask
= grants
;
2578 memcpy((char*)&pgace
->sid
, systemsid
, ssidsz
);
2582 /* a null ACE to hold special flags */
2583 /* using the same representation as cygwin */
2585 if (mode
& (S_ISVTX
| S_ISGID
| S_ISUID
)) {
2586 nsidsz
= ntfs_sid_size(nullsid
);
2587 pgace
= (ACCESS_ALLOWED_ACE
*)&secattr
[offs
+ pos
];
2588 pgace
->type
= ACCESS_ALLOWED_ACE_TYPE
;
2589 pgace
->flags
= NO_PROPAGATE_INHERIT_ACE
;
2590 pgace
->size
= cpu_to_le16(nsidsz
+ 8);
2591 grants
= const_cpu_to_le32(0);
2593 grants
|= FILE_APPEND_DATA
;
2595 grants
|= FILE_WRITE_DATA
;
2597 grants
|= FILE_READ_DATA
;
2598 pgace
->mask
= grants
;
2599 memcpy((char*)&pgace
->sid
, nullsid
, nsidsz
);
2604 /* fix ACL header */
2605 pacl
->size
= cpu_to_le16(pos
);
2606 pacl
->ace_count
= cpu_to_le16(acecnt
);
2613 * Build a full security descriptor from a Posix ACL
2614 * returns descriptor in allocated memory, must free() after use
2617 char *ntfs_build_descr_posix(struct MAPPING
* const mapping
[],
2618 struct POSIX_SECURITY
*pxdesc
,
2619 int isdir
, const SID
*usid
, const SID
*gsid
)
2622 SECURITY_DESCRIPTOR_RELATIVE
*pnhead
;
2632 usidsz
= ntfs_sid_size(usid
);
2633 gsidsz
= ntfs_sid_size(gsid
);
2634 wsidsz
= ntfs_sid_size(worldsid
);
2635 asidsz
= ntfs_sid_size(adminsid
);
2636 ssidsz
= ntfs_sid_size(systemsid
);
2638 /* allocate enough space for the new security attribute */
2639 newattrsz
= sizeof(SECURITY_DESCRIPTOR_RELATIVE
) /* header */
2640 + usidsz
+ gsidsz
/* usid and gsid */
2641 + sizeof(ACL
) /* acl header */
2642 + 2*(8 + usidsz
) /* two possible ACE for user */
2643 + 3*(8 + gsidsz
) /* three possible ACE for group and mask */
2644 + 8 + wsidsz
/* one ACE for world */
2645 + 8 + asidsz
/* one ACE for admin */
2646 + 8 + ssidsz
; /* one ACE for system */
2647 if (isdir
) /* a world denial for directories */
2648 newattrsz
+= 8 + wsidsz
;
2649 if (pxdesc
->mode
& 07000) /* a NULL ACE for special modes */
2650 newattrsz
+= 8 + ntfs_sid_size(nullsid
);
2651 /* account for non-owning users and groups */
2652 for (k
=0; k
<pxdesc
->acccnt
; k
++) {
2653 if ((pxdesc
->acl
.ace
[k
].tag
== POSIX_ACL_USER
)
2654 || (pxdesc
->acl
.ace
[k
].tag
== POSIX_ACL_GROUP
))
2655 newattrsz
+= 3*40; /* fixme : maximum size */
2657 /* account for default ACE's */
2658 newattrsz
+= 2*40*pxdesc
->defcnt
; /* fixme : maximum size */
2659 newattr
= (char*)ntfs_malloc(newattrsz
);
2661 /* build the main header part */
2662 pnhead
= (SECURITY_DESCRIPTOR_RELATIVE
*)newattr
;
2663 pnhead
->revision
= SECURITY_DESCRIPTOR_REVISION
;
2664 pnhead
->alignment
= 0;
2666 * The flag SE_DACL_PROTECTED prevents the ACL
2667 * to be changed in an inheritance after creation
2669 pnhead
->control
= SE_DACL_PRESENT
| SE_DACL_PROTECTED
2672 * Windows prefers ACL first, do the same to
2673 * get the same hash value and avoid duplication
2675 /* build permissions */
2676 aclsz
= buildacls_posix(mapping
,newattr
,
2677 sizeof(SECURITY_DESCRIPTOR_RELATIVE
),
2678 pxdesc
, isdir
, usid
, gsid
);
2679 if (aclsz
&& ((int)(sizeof(SECURITY_DESCRIPTOR_RELATIVE
)
2680 + aclsz
+ usidsz
+ gsidsz
) <= newattrsz
)) {
2681 /* append usid and gsid */
2682 memcpy(&newattr
[sizeof(SECURITY_DESCRIPTOR_RELATIVE
)
2683 + aclsz
], usid
, usidsz
);
2684 memcpy(&newattr
[sizeof(SECURITY_DESCRIPTOR_RELATIVE
)
2685 + aclsz
+ usidsz
], gsid
, gsidsz
);
2686 /* positions of ACL, USID and GSID into header */
2688 cpu_to_le32(sizeof(SECURITY_DESCRIPTOR_RELATIVE
)
2691 cpu_to_le32(sizeof(SECURITY_DESCRIPTOR_RELATIVE
)
2693 pnhead
->sacl
= const_cpu_to_le32(0);
2695 const_cpu_to_le32(sizeof(SECURITY_DESCRIPTOR_RELATIVE
));
2697 /* ACL failure (errno set) or overflow */
2699 newattr
= (char*)NULL
;
2701 /* hope error was detected before overflowing */
2702 ntfs_log_error("Security descriptor is longer than expected\n");
2711 #endif /* POSIXACLS */
2714 * Build a full security descriptor
2715 * returns descriptor in allocated memory, must free() after use
2718 char *ntfs_build_descr(mode_t mode
,
2719 int isdir
, const SID
* usid
, const SID
* gsid
)
2722 SECURITY_DESCRIPTOR_RELATIVE
*pnhead
;
2731 usidsz
= ntfs_sid_size(usid
);
2732 gsidsz
= ntfs_sid_size(gsid
);
2733 wsidsz
= ntfs_sid_size(worldsid
);
2734 asidsz
= ntfs_sid_size(adminsid
);
2735 ssidsz
= ntfs_sid_size(systemsid
);
2737 /* allocate enough space for the new security attribute */
2738 newattrsz
= sizeof(SECURITY_DESCRIPTOR_RELATIVE
) /* header */
2739 + usidsz
+ gsidsz
/* usid and gsid */
2740 + sizeof(ACL
) /* acl header */
2741 + 2*(8 + usidsz
) /* two possible ACE for user */
2742 + 2*(8 + gsidsz
) /* two possible ACE for group */
2743 + 8 + wsidsz
/* one ACE for world */
2744 + 8 + asidsz
/* one ACE for admin */
2745 + 8 + ssidsz
; /* one ACE for system */
2746 if (isdir
) /* a world denial for directories */
2747 newattrsz
+= 8 + wsidsz
;
2748 if (mode
& 07000) /* a NULL ACE for special modes */
2749 newattrsz
+= 8 + ntfs_sid_size(nullsid
);
2750 newattr
= (char*)ntfs_malloc(newattrsz
);
2752 /* build the main header part */
2753 pnhead
= (SECURITY_DESCRIPTOR_RELATIVE
*) newattr
;
2754 pnhead
->revision
= SECURITY_DESCRIPTOR_REVISION
;
2755 pnhead
->alignment
= 0;
2757 * The flag SE_DACL_PROTECTED prevents the ACL
2758 * to be changed in an inheritance after creation
2760 pnhead
->control
= SE_DACL_PRESENT
| SE_DACL_PROTECTED
2763 * Windows prefers ACL first, do the same to
2764 * get the same hash value and avoid duplication
2766 /* build permissions */
2767 aclsz
= buildacls(newattr
,
2768 sizeof(SECURITY_DESCRIPTOR_RELATIVE
),
2769 mode
, isdir
, usid
, gsid
);
2770 if (((int)sizeof(SECURITY_DESCRIPTOR_RELATIVE
)
2771 + aclsz
+ usidsz
+ gsidsz
) <= newattrsz
) {
2772 /* append usid and gsid */
2773 memcpy(&newattr
[sizeof(SECURITY_DESCRIPTOR_RELATIVE
)
2774 + aclsz
], usid
, usidsz
);
2775 memcpy(&newattr
[sizeof(SECURITY_DESCRIPTOR_RELATIVE
)
2776 + aclsz
+ usidsz
], gsid
, gsidsz
);
2777 /* positions of ACL, USID and GSID into header */
2779 cpu_to_le32(sizeof(SECURITY_DESCRIPTOR_RELATIVE
)
2782 cpu_to_le32(sizeof(SECURITY_DESCRIPTOR_RELATIVE
)
2784 pnhead
->sacl
= const_cpu_to_le32(0);
2786 const_cpu_to_le32(sizeof(SECURITY_DESCRIPTOR_RELATIVE
));
2788 /* hope error was detected before overflowing */
2790 newattr
= (char*)NULL
;
2791 ntfs_log_error("Security descriptor is longer than expected\n");
2800 * Create a mode_t permission set
2801 * from owner, group and world grants as represented in ACEs
2804 static int merge_permissions(BOOL isdir
,
2805 le32 owner
, le32 group
, le32 world
, le32 special
)
2811 /* build owner permission */
2814 /* exec if any of list, traverse */
2815 if (owner
& DIR_GEXEC
)
2817 /* write if any of addfile, adddir, delchild */
2818 if (owner
& DIR_GWRITE
)
2820 /* read if any of list */
2821 if (owner
& DIR_GREAD
)
2824 /* exec if execute or generic execute */
2825 if (owner
& FILE_GEXEC
)
2827 /* write if any of writedata or generic write */
2828 if (owner
& FILE_GWRITE
)
2830 /* read if any of readdata or generic read */
2831 if (owner
& FILE_GREAD
)
2835 /* build group permission */
2838 /* exec if any of list, traverse */
2839 if (group
& DIR_GEXEC
)
2841 /* write if any of addfile, adddir, delchild */
2842 if (group
& DIR_GWRITE
)
2844 /* read if any of list */
2845 if (group
& DIR_GREAD
)
2848 /* exec if execute */
2849 if (group
& FILE_GEXEC
)
2851 /* write if any of writedata, appenddata */
2852 if (group
& FILE_GWRITE
)
2854 /* read if any of readdata */
2855 if (group
& FILE_GREAD
)
2859 /* build world permission */
2862 /* exec if any of list, traverse */
2863 if (world
& DIR_GEXEC
)
2865 /* write if any of addfile, adddir, delchild */
2866 if (world
& DIR_GWRITE
)
2868 /* read if any of list */
2869 if (world
& DIR_GREAD
)
2872 /* exec if execute */
2873 if (world
& FILE_GEXEC
)
2875 /* write if any of writedata, appenddata */
2876 if (world
& FILE_GWRITE
)
2878 /* read if any of readdata */
2879 if (world
& FILE_GREAD
)
2883 /* build special permission flags */
2885 if (special
& FILE_APPEND_DATA
)
2887 if (special
& FILE_WRITE_DATA
)
2889 if (special
& FILE_READ_DATA
)
2898 * Normalize a Posix ACL either from a sorted raw set of
2899 * access ACEs or default ACEs
2900 * (standard case : different owner, group and administrator)
2903 static int norm_std_permissions_posix(struct POSIX_SECURITY
*posix_desc
,
2904 BOOL groupowns
, int start
, int count
, int target
)
2910 struct POSIX_ACE
*pxace
;
2922 * Determine what is granted to some group or world
2923 * Also get denials to world which are meant to prevent
2924 * execution flags to be inherited by plain files
2926 pxace
= posix_desc
->acl
.ace
;
2930 for (j
=start
; j
<(start
+ count
); j
++) {
2931 if (pxace
[j
].perms
& POSIX_PERM_DENIAL
) {
2932 /* deny world exec unless for default */
2933 if ((pxace
[j
].tag
== POSIX_ACL_OTHER
)
2935 denywrld
= pxace
[j
].perms
;
2937 switch (pxace
[j
].tag
) {
2938 case POSIX_ACL_GROUP_OBJ
:
2939 grantgrps
|= pxace
[j
].perms
;
2941 case POSIX_ACL_GROUP
:
2943 grantgrps
|= pxace
[j
].perms
;
2945 case POSIX_ACL_OTHER
:
2946 grantwrld
= pxace
[j
].perms
;
2954 * Collect groups of ACEs related to the same id
2955 * and determine what is granted and what is denied.
2956 * It is important the ACEs have been sorted
2960 while (j
< (start
+ count
)) {
2963 if (pxace
[j
].perms
& POSIX_PERM_DENIAL
) {
2964 deny
= pxace
[j
].perms
| denywrld
;
2968 allow
= pxace
[j
].perms
;
2971 while ((j
< (start
+ count
))
2972 && (pxace
[j
].tag
== tag
)
2973 && (pxace
[j
].id
== id
)) {
2974 if (pxace
[j
].perms
& POSIX_PERM_DENIAL
)
2975 deny
|= pxace
[j
].perms
;
2977 allow
|= pxace
[j
].perms
;
2981 * Build the permissions equivalent to grants and denials
2984 if (tag
== POSIX_ACL_MASK
)
2987 perms
= allow
& ~deny
;
2990 case POSIX_ACL_USER_OBJ
:
2991 perms
= (allow
| grantgrps
| grantwrld
) & ~deny
;
2993 case POSIX_ACL_USER
:
2995 perms
= (allow
| grantgrps
| grantwrld
)
3000 case POSIX_ACL_GROUP_OBJ
:
3001 perms
= (allow
| grantwrld
) & ~deny
;
3003 case POSIX_ACL_GROUP
:
3005 perms
= (allow
| grantwrld
) & ~deny
;
3009 case POSIX_ACL_MASK
:
3013 perms
= allow
& ~deny
;
3017 * Store into a Posix ACE
3019 if (tag
!= POSIX_ACL_SPECIAL
) {
3022 pxace
[k
].perms
= perms
3023 & (POSIX_PERM_R
| POSIX_PERM_W
| POSIX_PERM_X
);
3028 case POSIX_ACL_USER_OBJ
:
3029 mode
|= ((perms
& 7) << 6);
3031 case POSIX_ACL_GROUP_OBJ
:
3032 case POSIX_ACL_MASK
:
3033 mode
= (mode
& 07707) | ((perms
& 7) << 3);
3035 case POSIX_ACL_OTHER
:
3038 case POSIX_ACL_SPECIAL
:
3039 mode
|= (perms
& (S_ISVTX
| S_ISUID
| S_ISGID
));
3045 if (!start
) { /* not satisfactory */
3046 posix_desc
->mode
= mode
;
3047 posix_desc
->tagsset
= tagsset
;
3049 return (k
- target
);
3052 #endif /* POSIXACLS */
3055 * Interpret an ACL and extract meaningful grants
3056 * (standard case : different owner, group and administrator)
3059 static int build_std_permissions(const char *securattr
,
3060 const SID
*usid
, const SID
*gsid
, BOOL isdir
)
3062 const SECURITY_DESCRIPTOR_RELATIVE
*phead
;
3064 const ACCESS_ALLOWED_ACE
*pace
;
3071 le32 allowown
, allowgrp
, allowall
;
3072 le32 denyown
, denygrp
, denyall
;
3074 phead
= (const SECURITY_DESCRIPTOR_RELATIVE
*)securattr
;
3075 offdacl
= le32_to_cpu(phead
->dacl
);
3076 pacl
= (const ACL
*)&securattr
[offdacl
];
3077 special
= const_cpu_to_le32(0);
3078 allowown
= allowgrp
= allowall
= const_cpu_to_le32(0);
3079 denyown
= denygrp
= denyall
= const_cpu_to_le32(0);
3082 acecnt
= le16_to_cpu(pacl
->ace_count
);
3083 offace
= offdacl
+ sizeof(ACL
);
3088 for (nace
= 0; nace
< acecnt
; nace
++) {
3089 pace
= (const ACCESS_ALLOWED_ACE
*)&securattr
[offace
];
3090 if (!(pace
->flags
& INHERIT_ONLY_ACE
)) {
3091 if (ntfs_same_sid(usid
, &pace
->sid
)
3092 || ntfs_same_sid(ownersid
, &pace
->sid
)) {
3094 if (pace
->type
== ACCESS_ALLOWED_ACE_TYPE
)
3095 allowown
|= pace
->mask
;
3096 else if (pace
->type
== ACCESS_DENIED_ACE_TYPE
)
3097 denyown
|= pace
->mask
;
3099 if (ntfs_same_sid(gsid
, &pace
->sid
)
3100 && !(pace
->mask
& WRITE_OWNER
)) {
3101 if (pace
->type
== ACCESS_ALLOWED_ACE_TYPE
)
3102 allowgrp
|= pace
->mask
;
3103 else if (pace
->type
== ACCESS_DENIED_ACE_TYPE
)
3104 denygrp
|= pace
->mask
;
3106 if (is_world_sid((const SID
*)&pace
->sid
)) {
3107 if (pace
->type
== ACCESS_ALLOWED_ACE_TYPE
)
3108 allowall
|= pace
->mask
;
3110 if (pace
->type
== ACCESS_DENIED_ACE_TYPE
)
3111 denyall
|= pace
->mask
;
3113 if ((ntfs_same_sid((const SID
*)&pace
->sid
,nullsid
))
3114 && (pace
->type
== ACCESS_ALLOWED_ACE_TYPE
))
3115 special
|= pace
->mask
;
3117 offace
+= le16_to_cpu(pace
->size
);
3120 * No indication about owner's rights : grant basic rights
3121 * This happens for files created by Windows in directories
3122 * created by Linux and owned by root, because Windows
3123 * merges the admin ACEs
3126 allowown
= (FILE_READ_DATA
| FILE_WRITE_DATA
| FILE_EXECUTE
);
3128 * Add to owner rights granted to group or world
3129 * unless denied personaly, and add to group rights
3130 * granted to world unless denied specifically
3132 allowown
|= (allowgrp
| allowall
);
3133 allowgrp
|= allowall
;
3134 return (merge_permissions(isdir
,
3135 allowown
& ~(denyown
| denyall
),
3136 allowgrp
& ~(denygrp
| denyall
),
3137 allowall
& ~denyall
,
3142 * Interpret an ACL and extract meaningful grants
3143 * (special case : owner and group are the same,
3144 * and not administrator)
3147 static int build_owngrp_permissions(const char *securattr
,
3148 const SID
*usid
, BOOL isdir
)
3150 const SECURITY_DESCRIPTOR_RELATIVE
*phead
;
3152 const ACCESS_ALLOWED_ACE
*pace
;
3160 le32 allowown
, allowgrp
, allowall
;
3161 le32 denyown
, denygrp
, denyall
;
3163 phead
= (const SECURITY_DESCRIPTOR_RELATIVE
*)securattr
;
3164 offdacl
= le32_to_cpu(phead
->dacl
);
3165 pacl
= (const ACL
*)&securattr
[offdacl
];
3166 special
= const_cpu_to_le32(0);
3167 allowown
= allowgrp
= allowall
= const_cpu_to_le32(0);
3168 denyown
= denygrp
= denyall
= const_cpu_to_le32(0);
3172 acecnt
= le16_to_cpu(pacl
->ace_count
);
3173 offace
= offdacl
+ sizeof(ACL
);
3178 for (nace
= 0; nace
< acecnt
; nace
++) {
3179 pace
= (const ACCESS_ALLOWED_ACE
*)&securattr
[offace
];
3180 if (!(pace
->flags
& INHERIT_ONLY_ACE
)) {
3181 if ((ntfs_same_sid(usid
, &pace
->sid
)
3182 || ntfs_same_sid(ownersid
, &pace
->sid
))
3183 && (pace
->mask
& WRITE_OWNER
)) {
3184 if (pace
->type
== ACCESS_ALLOWED_ACE_TYPE
) {
3185 allowown
|= pace
->mask
;
3189 if (ntfs_same_sid(usid
, &pace
->sid
)
3190 && (!(pace
->mask
& WRITE_OWNER
))) {
3191 if (pace
->type
== ACCESS_ALLOWED_ACE_TYPE
) {
3192 allowgrp
|= pace
->mask
;
3196 if (is_world_sid((const SID
*)&pace
->sid
)) {
3197 if (pace
->type
== ACCESS_ALLOWED_ACE_TYPE
)
3198 allowall
|= pace
->mask
;
3200 if (pace
->type
== ACCESS_DENIED_ACE_TYPE
)
3201 denyall
|= pace
->mask
;
3203 if ((ntfs_same_sid((const SID
*)&pace
->sid
,nullsid
))
3204 && (pace
->type
== ACCESS_ALLOWED_ACE_TYPE
))
3205 special
|= pace
->mask
;
3207 offace
+= le16_to_cpu(pace
->size
);
3210 allowown
= allowall
;
3212 allowgrp
= allowall
;
3213 return (merge_permissions(isdir
,
3214 allowown
& ~(denyown
| denyall
),
3215 allowgrp
& ~(denygrp
| denyall
),
3216 allowall
& ~denyall
,
3223 * Normalize a Posix ACL either from a sorted raw set of
3224 * access ACEs or default ACEs
3225 * (special case : owner or/and group is administrator)
3228 static int norm_ownadmin_permissions_posix(struct POSIX_SECURITY
*posix_desc
,
3229 int start
, int count
, int target
)
3235 struct POSIX_ACE
*pxace
;
3243 pxace
= posix_desc
->acl
.ace
;
3247 * Get denials to world which are meant to prevent
3248 * execution flags to be inherited by plain files
3250 for (j
=start
; j
<(start
+ count
); j
++) {
3251 if (pxace
[j
].perms
& POSIX_PERM_DENIAL
) {
3252 /* deny world exec not for default */
3253 if ((pxace
[j
].tag
== POSIX_ACL_OTHER
)
3255 denywrld
= pxace
[j
].perms
;
3259 * Collect groups of ACEs related to the same id
3260 * and determine what is granted (denials are ignored)
3261 * It is important the ACEs have been sorted
3266 while (j
< (start
+ count
)) {
3270 if (tag
== POSIX_ACL_MASK
) {
3271 deny
= pxace
[j
].perms
;
3273 while ((j
< (start
+ count
))
3274 && (pxace
[j
].tag
== POSIX_ACL_MASK
))
3277 if (!(pxace
[j
].perms
& POSIX_PERM_DENIAL
))
3278 allow
= pxace
[j
].perms
;
3280 while ((j
< (start
+ count
))
3281 && (pxace
[j
].tag
== tag
)
3282 && (pxace
[j
].id
== id
)) {
3283 if (!(pxace
[j
].perms
& POSIX_PERM_DENIAL
))
3284 allow
|= pxace
[j
].perms
;
3290 * Store the grants into a Posix ACE
3292 if (tag
== POSIX_ACL_MASK
)
3295 perms
= allow
& ~denywrld
;
3296 if (tag
!= POSIX_ACL_SPECIAL
) {
3299 pxace
[k
].perms
= perms
3300 & (POSIX_PERM_R
| POSIX_PERM_W
| POSIX_PERM_X
);
3305 case POSIX_ACL_USER_OBJ
:
3306 mode
|= ((perms
& 7) << 6);
3308 case POSIX_ACL_GROUP_OBJ
:
3309 case POSIX_ACL_MASK
:
3310 mode
= (mode
& 07707) | ((perms
& 7) << 3);
3312 case POSIX_ACL_OTHER
:
3315 case POSIX_ACL_SPECIAL
:
3316 mode
|= perms
& (S_ISVTX
| S_ISUID
| S_ISGID
);
3322 if (!start
) { /* not satisfactory */
3323 posix_desc
->mode
= mode
;
3324 posix_desc
->tagsset
= tagsset
;
3326 return (k
- target
);
3329 #endif /* POSIXACLS */
3332 * Interpret an ACL and extract meaningful grants
3333 * (special case : owner or/and group is administrator)
3337 static int build_ownadmin_permissions(const char *securattr
,
3338 const SID
*usid
, const SID
*gsid
, BOOL isdir
)
3340 const SECURITY_DESCRIPTOR_RELATIVE
*phead
;
3342 const ACCESS_ALLOWED_ACE
*pace
;
3350 le32 allowown
, allowgrp
, allowall
;
3351 le32 denyown
, denygrp
, denyall
;
3353 phead
= (const SECURITY_DESCRIPTOR_RELATIVE
*)securattr
;
3354 offdacl
= le32_to_cpu(phead
->dacl
);
3355 pacl
= (const ACL
*)&securattr
[offdacl
];
3356 special
= const_cpu_to_le32(0);
3357 allowown
= allowgrp
= allowall
= const_cpu_to_le32(0);
3358 denyown
= denygrp
= denyall
= const_cpu_to_le32(0);
3360 acecnt
= le16_to_cpu(pacl
->ace_count
);
3361 offace
= offdacl
+ sizeof(ACL
);
3368 for (nace
= 0; nace
< acecnt
; nace
++) {
3369 pace
= (const ACCESS_ALLOWED_ACE
*)&securattr
[offace
];
3370 if (!(pace
->flags
& INHERIT_ONLY_ACE
)
3371 && !(~pace
->mask
& (ROOT_OWNER_UNMARK
| ROOT_GROUP_UNMARK
))) {
3372 if ((ntfs_same_sid(usid
, &pace
->sid
)
3373 || ntfs_same_sid(ownersid
, &pace
->sid
))
3374 && (((pace
->mask
& WRITE_OWNER
) && firstapply
))) {
3375 if (pace
->type
== ACCESS_ALLOWED_ACE_TYPE
) {
3376 allowown
|= pace
->mask
;
3379 if (pace
->type
== ACCESS_DENIED_ACE_TYPE
)
3380 denyown
|= pace
->mask
;
3382 if (ntfs_same_sid(gsid
, &pace
->sid
)
3383 && (!(pace
->mask
& WRITE_OWNER
))) {
3384 if (pace
->type
== ACCESS_ALLOWED_ACE_TYPE
) {
3385 allowgrp
|= pace
->mask
;
3388 if (pace
->type
== ACCESS_DENIED_ACE_TYPE
)
3389 denygrp
|= pace
->mask
;
3390 } else if (is_world_sid((const SID
*)&pace
->sid
)) {
3391 if (pace
->type
== ACCESS_ALLOWED_ACE_TYPE
)
3392 allowall
|= pace
->mask
;
3394 if (pace
->type
== ACCESS_DENIED_ACE_TYPE
)
3395 denyall
|= pace
->mask
;
3399 if (!(pace
->flags
& INHERIT_ONLY_ACE
))
3400 if ((ntfs_same_sid((const SID
*)&pace
->sid
,nullsid
))
3401 && (pace
->type
== ACCESS_ALLOWED_ACE_TYPE
))
3402 special
|= pace
->mask
;
3403 offace
+= le16_to_cpu(pace
->size
);
3406 allowown
|= (allowgrp
| allowall
);
3407 allowgrp
|= allowall
;
3409 return (merge_permissions(isdir
,
3410 allowown
& ~(denyown
| denyall
),
3411 allowgrp
& ~(denygrp
| denyall
),
3412 allowall
& ~denyall
,
3419 * Define the owner of a file as the first user allowed
3420 * to change the owner, instead of the user defined as owner.
3422 * This produces better approximations for files written by a
3423 * Windows user in an inheritable directory owned by another user,
3424 * as the access rights are inheritable but the ownership is not.
3426 * An important case is the directories "Documents and Settings/user"
3427 * which the users must have access to, though Windows considers them
3428 * as owned by administrator.
3431 const SID
*ntfs_acl_owner(const char *securattr
)
3433 const SECURITY_DESCRIPTOR_RELATIVE
*phead
;
3436 const ACCESS_ALLOWED_ACE
*pace
;
3444 phead
= (const SECURITY_DESCRIPTOR_RELATIVE
*)securattr
;
3445 offdacl
= le32_to_cpu(phead
->dacl
);
3447 pacl
= (const ACL
*)&securattr
[offdacl
];
3448 acecnt
= le16_to_cpu(pacl
->ace_count
);
3449 offace
= offdacl
+ sizeof(ACL
);
3452 pace
= (const ACCESS_ALLOWED_ACE
*)&securattr
[offace
];
3453 if ((pace
->mask
& WRITE_OWNER
)
3454 && (pace
->type
== ACCESS_ALLOWED_ACE_TYPE
)
3455 && ntfs_is_user_sid(&pace
->sid
))
3457 offace
+= le16_to_cpu(pace
->size
);
3458 } while (!found
&& (++nace
< acecnt
));
3463 usid
= (const SID
*)&securattr
[le32_to_cpu(phead
->owner
)];
3470 * Special case for files owned by administrator with full
3471 * access granted to a mapped user : consider this user as the tenant
3474 * This situation cannot be represented with Linux concepts and can
3475 * only be found for files or directories created by Windows.
3476 * Typical situation : directory "Documents and Settings/user" which
3477 * is on the path to user's files and must be given access to user
3480 * Check file is owned by administrator and no user has rights before
3482 * Returns the uid of tenant or zero if none
3486 static uid_t
find_tenant(struct MAPPING
*const mapping
[],
3487 const char *securattr
)
3489 const SECURITY_DESCRIPTOR_RELATIVE
*phead
;
3491 const ACCESS_ALLOWED_ACE
*pace
;
3499 phead
= (const SECURITY_DESCRIPTOR_RELATIVE
*)securattr
;
3500 offdacl
= le32_to_cpu(phead
->dacl
);
3501 pacl
= (const ACL
*)&securattr
[offdacl
];
3504 acecnt
= le16_to_cpu(pacl
->ace_count
);
3505 offace
= offdacl
+ sizeof(ACL
);
3508 for (nace
= 0; nace
< acecnt
; nace
++) {
3509 pace
= (const ACCESS_ALLOWED_ACE
*)&securattr
[offace
];
3510 if ((pace
->type
== ACCESS_ALLOWED_ACE_TYPE
)
3511 && (pace
->mask
& DIR_WRITE
)) {
3512 xid
= NTFS_FIND_USER(mapping
[MAPUSERS
], &pace
->sid
);
3515 offace
+= le16_to_cpu(pace
->size
);
3520 #endif /* OWNERFROMACL */
3525 * Build Posix permissions from an ACL
3526 * returns a pointer to the requested permissions
3527 * or a null pointer (with errno set) if there is a problem
3529 * If the NTFS ACL was created according to our rules, the retrieved
3530 * Posix ACL should be the exact ACL which was set. However if
3531 * the NTFS ACL was built by a different tool, the result could
3532 * be a a poor approximation of what was expected
3535 struct POSIX_SECURITY
*ntfs_build_permissions_posix(
3536 struct MAPPING
*const mapping
[],
3537 const char *securattr
,
3538 const SID
*usid
, const SID
*gsid
, BOOL isdir
)
3540 const SECURITY_DESCRIPTOR_RELATIVE
*phead
;
3541 struct POSIX_SECURITY
*pxdesc
;
3543 const ACCESS_ALLOWED_ACE
*pace
;
3544 struct POSIX_ACE
*pxace
;
3569 phead
= (const SECURITY_DESCRIPTOR_RELATIVE
*)securattr
;
3570 offdacl
= le32_to_cpu(phead
->dacl
);
3572 pacl
= (const ACL
*)&securattr
[offdacl
];
3573 acecnt
= le16_to_cpu(pacl
->ace_count
);
3574 offace
= offdacl
+ sizeof(ACL
);
3580 groupowns
= ntfs_same_sid(gsid
,usid
);
3584 * Build a raw posix security descriptor
3585 * by just translating permissions and ids
3586 * Add 2 to the count of ACE to be able to insert
3587 * a group ACE later in access and default ACLs
3588 * and add 2 more to be able to insert ACEs for owner
3589 * and 2 more for other
3591 alloccnt
= acecnt
+ 6;
3592 pxdesc
= (struct POSIX_SECURITY
*)malloc(
3593 sizeof(struct POSIX_SECURITY
)
3594 + alloccnt
*sizeof(struct POSIX_ACE
));
3597 for (i
=0; i
<2; i
++) {
3599 pctx
->permswrld
= 0;
3602 pctx
->groupmasks
= 0;
3604 pctx
->gotowner
= FALSE
;
3605 pctx
->gotgroup
= FALSE
;
3606 pctx
->gotownermask
= FALSE
;
3608 for (j
=0; j
<acecnt
; j
++) {
3609 pace
= (const ACCESS_ALLOWED_ACE
*)&securattr
[offace
];
3610 if (pace
->flags
& INHERIT_ONLY_ACE
) {
3611 pxace
= &pxdesc
->acl
.ace
[l
- 1];
3614 pxace
= &pxdesc
->acl
.ace
[k
];
3619 * grants for root as a designated user or group
3621 if ((~pace
->mask
& (ROOT_OWNER_UNMARK
| ROOT_GROUP_UNMARK
))
3622 && (pace
->type
== ACCESS_ALLOWED_ACE_TYPE
)
3623 && ntfs_same_sid(&pace
->sid
, adminsid
)) {
3624 pxace
->tag
= (pace
->mask
& ROOT_OWNER_UNMARK
? POSIX_ACL_GROUP
: POSIX_ACL_USER
);
3626 if ((pace
->mask
& (GENERIC_ALL
| WRITE_OWNER
))
3627 && (pace
->flags
& INHERIT_ONLY_ACE
))
3628 ignore
= genericinh
= TRUE
;
3630 if (ntfs_same_sid(usid
, &pace
->sid
)) {
3633 * Owner has no write-owner right :
3634 * a group was defined same as owner
3635 * or admin was owner or group :
3636 * denials are meant to owner
3637 * and grants are meant to group
3639 if (!(pace
->mask
& (WRITE_OWNER
| GENERIC_ALL
))
3640 && (pace
->type
== ACCESS_ALLOWED_ACE_TYPE
)) {
3641 if (ntfs_same_sid(gsid
,usid
)) {
3642 pxace
->tag
= POSIX_ACL_GROUP_OBJ
;
3645 if (ntfs_same_sid(&pace
->sid
,usid
))
3647 gid
= NTFS_FIND_GROUP(mapping
[MAPGROUPS
],&pace
->sid
);
3649 pxace
->tag
= POSIX_ACL_GROUP
;
3651 pctx
->prevgid
= gid
;
3653 uid
= NTFS_FIND_USER(mapping
[MAPUSERS
],&pace
->sid
);
3655 pxace
->tag
= POSIX_ACL_USER
;
3663 * when group owns, late denials for owner
3666 if ((pace
->type
== ACCESS_DENIED_ACE_TYPE
)
3667 && (pace
->mask
& WRITE_OWNER
)) {
3668 pxace
->tag
= POSIX_ACL_MASK
;
3669 pctx
->gotownermask
= TRUE
;
3673 if (pace
->type
== ACCESS_ALLOWED_ACE_TYPE
)
3674 pctx
->gotowner
= TRUE
;
3675 if (pctx
->gotownermask
&& !pctx
->gotowner
) {
3676 uid
= NTFS_FIND_USER(mapping
[MAPUSERS
],&pace
->sid
);
3678 pxace
->tag
= POSIX_ACL_USER
;
3680 pxace
->tag
= POSIX_ACL_USER_OBJ
;
3681 /* system ignored, and admin */
3682 /* ignored at first position */
3683 if (pace
->flags
& INHERIT_ONLY_ACE
) {
3684 if ((firstinh
&& ntfs_same_sid(&pace
->sid
,adminsid
))
3685 || ntfs_same_sid(&pace
->sid
,systemsid
))
3691 if ((adminowns
&& ntfs_same_sid(&pace
->sid
,adminsid
))
3692 || ntfs_same_sid(&pace
->sid
,systemsid
))
3694 if (ntfs_same_sid(usid
,adminsid
))
3699 } else if (ntfs_same_sid(gsid
, &pace
->sid
)) {
3700 if ((pace
->type
== ACCESS_DENIED_ACE_TYPE
)
3701 && (pace
->mask
& WRITE_OWNER
)) {
3702 pxace
->tag
= POSIX_ACL_MASK
;
3707 if (pctx
->gotgroup
|| (pctx
->groupmasks
> 1)) {
3708 gid
= NTFS_FIND_GROUP(mapping
[MAPGROUPS
],&pace
->sid
);
3711 pxace
->tag
= POSIX_ACL_GROUP
;
3712 pctx
->prevgid
= gid
;
3717 pxace
->tag
= POSIX_ACL_GROUP_OBJ
;
3718 if (pace
->type
== ACCESS_ALLOWED_ACE_TYPE
)
3719 pctx
->gotgroup
= TRUE
;
3722 if (ntfs_same_sid(gsid
,adminsid
)
3723 || ntfs_same_sid(gsid
,systemsid
)) {
3724 if (pace
->mask
& (WRITE_OWNER
| GENERIC_ALL
))
3726 if (ntfs_same_sid(gsid
,adminsid
))
3729 genericinh
= ignore
;
3732 } else if (is_world_sid((const SID
*)&pace
->sid
)) {
3734 pxace
->tag
= POSIX_ACL_OTHER
;
3735 if ((pace
->type
== ACCESS_DENIED_ACE_TYPE
)
3736 && (pace
->flags
& INHERIT_ONLY_ACE
))
3738 } else if (ntfs_same_sid((const SID
*)&pace
->sid
,nullsid
)) {
3740 pxace
->tag
= POSIX_ACL_SPECIAL
;
3742 uid
= NTFS_FIND_USER(mapping
[MAPUSERS
],&pace
->sid
);
3744 if ((pace
->type
== ACCESS_DENIED_ACE_TYPE
)
3745 && (pace
->mask
& WRITE_OWNER
)
3746 && (pctx
->prevuid
!= uid
)) {
3748 pxace
->tag
= POSIX_ACL_MASK
;
3751 pxace
->tag
= POSIX_ACL_USER
;
3753 pctx
->prevuid
= uid
;
3755 gid
= NTFS_FIND_GROUP(mapping
[MAPGROUPS
],&pace
->sid
);
3757 if ((pace
->type
== ACCESS_DENIED_ACE_TYPE
)
3758 && (pace
->mask
& WRITE_OWNER
)
3759 && (pctx
->prevgid
!= gid
)) {
3760 pxace
->tag
= POSIX_ACL_MASK
;
3763 pxace
->tag
= POSIX_ACL_GROUP
;
3766 pctx
->prevgid
= gid
;
3769 * do not grant rights to unknown
3770 * people and do not define root as a
3771 * designated user or group
3779 /* specific decoding for vtx/uid/gid */
3780 if (pxace
->tag
== POSIX_ACL_SPECIAL
) {
3781 if (pace
->mask
& FILE_APPEND_DATA
)
3782 pxace
->perms
|= S_ISUID
;
3783 if (pace
->mask
& FILE_WRITE_DATA
)
3784 pxace
->perms
|= S_ISGID
;
3785 if (pace
->mask
& FILE_READ_DATA
)
3786 pxace
->perms
|= S_ISVTX
;
3789 if (pace
->mask
& DIR_GEXEC
)
3790 pxace
->perms
|= POSIX_PERM_X
;
3791 if (pace
->mask
& DIR_GWRITE
)
3792 pxace
->perms
|= POSIX_PERM_W
;
3793 if (pace
->mask
& DIR_GREAD
)
3794 pxace
->perms
|= POSIX_PERM_R
;
3795 if ((pace
->mask
& GENERIC_ALL
)
3796 && (pace
->flags
& INHERIT_ONLY_ACE
))
3797 pxace
->perms
|= POSIX_PERM_X
3801 if (pace
->mask
& FILE_GEXEC
)
3802 pxace
->perms
|= POSIX_PERM_X
;
3803 if (pace
->mask
& FILE_GWRITE
)
3804 pxace
->perms
|= POSIX_PERM_W
;
3805 if (pace
->mask
& FILE_GREAD
)
3806 pxace
->perms
|= POSIX_PERM_R
;
3809 if (pace
->type
!= ACCESS_ALLOWED_ACE_TYPE
)
3810 pxace
->perms
|= POSIX_PERM_DENIAL
;
3812 if (pxace
->tag
== POSIX_ACL_OTHER
)
3813 pctx
->permswrld
|= pxace
->perms
;
3814 pctx
->tagsset
|= pxace
->tag
;
3815 if (pace
->flags
& INHERIT_ONLY_ACE
) {
3821 offace
+= le16_to_cpu(pace
->size
);
3824 * Create world perms if none (both lists)
3827 if ((genericinh
|| !i
)
3828 && !(ctx
[i
].tagsset
& POSIX_ACL_OTHER
)) {
3830 pxace
= &pxdesc
->acl
.ace
[--l
];
3832 pxace
= &pxdesc
->acl
.ace
[k
++];
3833 pxace
->tag
= POSIX_ACL_OTHER
;
3836 ctx
[i
].tagsset
|= POSIX_ACL_OTHER
;
3837 ctx
[i
].permswrld
= 0;
3840 * Set basic owner perms if none (both lists)
3841 * This happens for files created by Windows in directories
3842 * created by Linux and owned by root, because Windows
3843 * merges the admin ACEs
3846 if (!(ctx
[i
].tagsset
& POSIX_ACL_USER_OBJ
)
3847 && (ctx
[i
].tagsset
& POSIX_ACL_OTHER
)) {
3849 pxace
= &pxdesc
->acl
.ace
[--l
];
3851 pxace
= &pxdesc
->acl
.ace
[k
++];
3852 pxace
->tag
= POSIX_ACL_USER_OBJ
;
3854 pxace
->perms
= POSIX_PERM_R
| POSIX_PERM_W
| POSIX_PERM_X
;
3855 ctx
[i
].tagsset
|= POSIX_ACL_USER_OBJ
;
3858 * Duplicate world perms as group_obj perms if none
3861 if ((ctx
[i
].tagsset
& POSIX_ACL_OTHER
)
3862 && !(ctx
[i
].tagsset
& POSIX_ACL_GROUP_OBJ
)) {
3864 pxace
= &pxdesc
->acl
.ace
[--l
];
3866 pxace
= &pxdesc
->acl
.ace
[k
++];
3867 pxace
->tag
= POSIX_ACL_GROUP_OBJ
;
3869 pxace
->perms
= ctx
[i
].permswrld
;
3870 ctx
[i
].tagsset
|= POSIX_ACL_GROUP_OBJ
;
3873 * Also duplicate world perms as group perms if they
3874 * were converted to mask and not followed by a group entry
3876 if (ctx
[0].groupmasks
) {
3877 for (j
=k
-2; j
>=0; j
--) {
3878 if ((pxdesc
->acl
.ace
[j
].tag
== POSIX_ACL_MASK
)
3879 && (pxdesc
->acl
.ace
[j
].id
!= -1)
3880 && ((pxdesc
->acl
.ace
[j
+1].tag
!= POSIX_ACL_GROUP
)
3881 || (pxdesc
->acl
.ace
[j
+1].id
3882 != pxdesc
->acl
.ace
[j
].id
))) {
3883 pxace
= &pxdesc
->acl
.ace
[k
];
3884 pxace
->tag
= POSIX_ACL_GROUP
;
3885 pxace
->id
= pxdesc
->acl
.ace
[j
].id
;
3886 pxace
->perms
= ctx
[0].permswrld
;
3887 ctx
[0].tagsset
|= POSIX_ACL_GROUP
;
3890 if (pxdesc
->acl
.ace
[j
].tag
== POSIX_ACL_MASK
)
3891 pxdesc
->acl
.ace
[j
].id
= -1;
3894 if (ctx
[1].groupmasks
) {
3895 for (j
=l
; j
<(alloccnt
-1); j
++) {
3896 if ((pxdesc
->acl
.ace
[j
].tag
== POSIX_ACL_MASK
)
3897 && (pxdesc
->acl
.ace
[j
].id
!= -1)
3898 && ((pxdesc
->acl
.ace
[j
+1].tag
!= POSIX_ACL_GROUP
)
3899 || (pxdesc
->acl
.ace
[j
+1].id
3900 != pxdesc
->acl
.ace
[j
].id
))) {
3901 pxace
= &pxdesc
->acl
.ace
[l
- 1];
3902 pxace
->tag
= POSIX_ACL_GROUP
;
3903 pxace
->id
= pxdesc
->acl
.ace
[j
].id
;
3904 pxace
->perms
= ctx
[1].permswrld
;
3905 ctx
[1].tagsset
|= POSIX_ACL_GROUP
;
3908 if (pxdesc
->acl
.ace
[j
].tag
== POSIX_ACL_MASK
)
3909 pxdesc
->acl
.ace
[j
].id
= -1;
3914 * Insert default mask if none present and
3915 * there are designated users or groups
3916 * (the space for it has not beed used)
3919 if ((ctx
[i
].tagsset
& (POSIX_ACL_USER
| POSIX_ACL_GROUP
))
3920 && !(ctx
[i
].tagsset
& POSIX_ACL_MASK
)) {
3922 pxace
= &pxdesc
->acl
.ace
[--l
];
3924 pxace
= &pxdesc
->acl
.ace
[k
++];
3925 pxace
->tag
= POSIX_ACL_MASK
;
3927 pxace
->perms
= POSIX_PERM_DENIAL
;
3928 ctx
[i
].tagsset
|= POSIX_ACL_MASK
;
3932 ntfs_log_error("Posix descriptor is longer than expected\n");
3935 pxdesc
= (struct POSIX_SECURITY
*)NULL
;
3938 pxdesc
->defcnt
= alloccnt
- l
;
3939 pxdesc
->firstdef
= l
;
3940 pxdesc
->tagsset
= ctx
[0].tagsset
;
3941 pxdesc
->acl
.version
= POSIX_VERSION
;
3942 pxdesc
->acl
.flags
= 0;
3943 pxdesc
->acl
.filler
= 0;
3944 ntfs_sort_posix(pxdesc
);
3946 k
= norm_ownadmin_permissions_posix(pxdesc
,
3947 0, pxdesc
->acccnt
, 0);
3949 l
= norm_ownadmin_permissions_posix(pxdesc
,
3950 pxdesc
->firstdef
, pxdesc
->defcnt
, k
);
3951 pxdesc
->firstdef
= k
;
3954 k
= norm_std_permissions_posix(pxdesc
,groupowns
,
3955 0, pxdesc
->acccnt
, 0);
3957 l
= norm_std_permissions_posix(pxdesc
,groupowns
,
3958 pxdesc
->firstdef
, pxdesc
->defcnt
, k
);
3959 pxdesc
->firstdef
= k
;
3963 if (pxdesc
&& !ntfs_valid_posix(pxdesc
)) {
3964 ntfs_log_error("Invalid Posix descriptor built\n");
3967 pxdesc
= (struct POSIX_SECURITY
*)NULL
;
3972 #endif /* POSIXACLS */
3975 * Build unix-style (mode_t) permissions from an ACL
3976 * returns the requested permissions
3977 * or a negative result (with errno set) if there is a problem
3980 int ntfs_build_permissions(const char *securattr
,
3981 const SID
*usid
, const SID
*gsid
, BOOL isdir
)
3987 adminowns
= ntfs_same_sid(usid
,adminsid
)
3988 || ntfs_same_sid(gsid
,adminsid
);
3989 groupowns
= !adminowns
&& ntfs_same_sid(gsid
,usid
);
3991 perm
= build_ownadmin_permissions(securattr
, usid
, gsid
, isdir
);
3994 perm
= build_owngrp_permissions(securattr
, usid
, isdir
);
3996 perm
= build_std_permissions(securattr
, usid
, gsid
, isdir
);
4001 * The following must be in some library...
4004 static unsigned long atoul(const char *p
)
4005 { /* must be somewhere ! */
4009 while ((*p
>= '0') && (*p
<= '9'))
4010 v
= v
* 10 + (*p
++) - '0';
4015 * Build an internal representation of a SID
4016 * Returns a copy in allocated memory if it succeeds
4017 * The SID is checked to be a valid user one.
4020 static SID
*encodesid(const char *sidstr
)
4030 if (!strncmp(sidstr
, "S-1-", 4)) {
4031 bsid
= (SID
*)&bigsid
;
4032 bsid
->revision
= SID_REVISION
;
4035 bsid
->identifier_authority
.high_part
= const_cpu_to_be16(0);
4036 bsid
->identifier_authority
.low_part
= cpu_to_be32(auth
);
4039 while (p
&& (cnt
< 8)) {
4042 bsid
->sub_authority
[cnt
] = cpu_to_le32(auth
);
4046 bsid
->sub_authority_count
= cnt
;
4047 if ((cnt
> 0) && ntfs_valid_sid(bsid
) && ntfs_is_user_sid(bsid
)) {
4048 sid
= (SID
*) ntfs_malloc(4 * cnt
+ 8);
4050 memcpy(sid
, bsid
, 4 * cnt
+ 8);
4057 * Get a single mapping item from buffer
4059 * Always reads a full line, truncating long lines
4060 * Refills buffer when exhausted
4061 * Returns pointer to item, or NULL when there is no more
4064 static struct MAPLIST
*getmappingitem(FILEREADER reader
, void *fileid
,
4065 off_t
*poffs
, char *buf
, int *psrc
, s64
*psize
)
4073 struct MAPLIST
*item
;
4077 /* allocate and get a full line */
4078 item
= (struct MAPLIST
*)ntfs_malloc(sizeof(struct MAPLIST
));
4082 while ((src
< *psize
)
4083 && (buf
[src
] != '\n')) {
4085 item
->maptext
[dst
++] = buf
[src
];
4088 if (src
>= *psize
) {
4090 *psize
= reader(fileid
, buf
, (size_t)BUFSZ
, *poffs
);
4095 item
->maptext
[dst
] = '\0';
4098 } while (*psize
&& ((item
->maptext
[0] == '#') || !gotend
));
4100 pu
= pg
= (char*)NULL
;
4101 /* decompose into uid, gid and sid */
4102 item
->uidstr
= item
->maptext
;
4103 item
->gidstr
= strchr(item
->uidstr
, ':');
4105 pu
= item
->gidstr
++;
4106 item
->sidstr
= strchr(item
->gidstr
, ':');
4108 pg
= item
->sidstr
++;
4109 q
= strchr(item
->sidstr
, ':');
4116 ntfs_log_early_error("Bad mapping item \"%s\"\n",
4119 item
= (struct MAPLIST
*)NULL
;
4122 free(item
); /* free unused item */
4123 item
= (struct MAPLIST
*)NULL
;
4131 * Read user mapping file and split into their attribute.
4132 * Parameters are kept as text in a chained list until logins
4133 * are converted to uid.
4134 * Returns the head of list, if any
4136 * If an absolute path is provided, the mapping file is assumed
4137 * to be located in another mounted file system, and plain read()
4138 * are used to get its contents.
4139 * If a relative path is provided, the mapping file is assumed
4140 * to be located on the current file system, and internal IO
4141 * have to be used since we are still mounting and we have not
4142 * entered the fuse loop yet.
4145 struct MAPLIST
*ntfs_read_mapping(FILEREADER reader
, void *fileid
)
4148 struct MAPLIST
*item
;
4149 struct MAPLIST
*firstitem
;
4150 struct MAPLIST
*lastitem
;
4155 firstitem
= (struct MAPLIST
*)NULL
;
4156 lastitem
= (struct MAPLIST
*)NULL
;
4158 size
= reader(fileid
, buf
, (size_t)BUFSZ
, (off_t
)0);
4162 item
= getmappingitem(reader
, fileid
, &offs
,
4165 item
->next
= (struct MAPLIST
*)NULL
;
4167 lastitem
->next
= item
;
4178 * Free memory used to store the user mapping
4179 * The only purpose is to facilitate the detection of memory leaks
4182 void ntfs_free_mapping(struct MAPPING
*mapping
[])
4184 struct MAPPING
*user
;
4185 struct MAPPING
*group
;
4187 /* free user mappings */
4188 while (mapping
[MAPUSERS
]) {
4189 user
= mapping
[MAPUSERS
];
4190 /* do not free SIDs used for group mappings */
4191 group
= mapping
[MAPGROUPS
];
4192 while (group
&& (group
->sid
!= user
->sid
))
4193 group
= group
->next
;
4196 /* free group list if any */
4199 /* unchain item and free */
4200 mapping
[MAPUSERS
] = user
->next
;
4203 /* free group mappings */
4204 while (mapping
[MAPGROUPS
]) {
4205 group
= mapping
[MAPGROUPS
];
4207 /* unchain item and free */
4208 mapping
[MAPGROUPS
] = group
->next
;
4215 * Build the user mapping list
4216 * user identification may be given in symbolic or numeric format
4218 * ! Note ! : does getpwnam() read /etc/passwd or some other file ?
4219 * if so there is a possible recursion into fuse if this
4220 * file is on NTFS, and fuse is not recursion safe.
4223 struct MAPPING
*ntfs_do_user_mapping(struct MAPLIST
*firstitem
)
4225 struct MAPLIST
*item
;
4226 struct MAPPING
*firstmapping
;
4227 struct MAPPING
*lastmapping
;
4228 struct MAPPING
*mapping
;
4233 firstmapping
= (struct MAPPING
*)NULL
;
4234 lastmapping
= (struct MAPPING
*)NULL
;
4235 for (item
= firstitem
; item
; item
= item
->next
) {
4236 if ((item
->uidstr
[0] >= '0') && (item
->uidstr
[0] <= '9'))
4237 uid
= atoi(item
->uidstr
);
4240 if (item
->uidstr
[0]) {
4241 pwd
= getpwnam(item
->uidstr
);
4245 ntfs_log_early_error("Invalid user \"%s\"\n",
4250 * Records with no uid and no gid are inserted
4251 * to define the implicit mapping pattern
4254 || (!item
->uidstr
[0] && !item
->gidstr
[0])) {
4255 sid
= encodesid(item
->sidstr
);
4256 if (sid
&& !item
->uidstr
[0] && !item
->gidstr
[0]
4257 && !ntfs_valid_pattern(sid
)) {
4258 ntfs_log_error("Bad implicit SID pattern %s\n",
4265 ntfs_malloc(sizeof(struct MAPPING
));
4270 mapping
->next
= (struct MAPPING
*)NULL
;
4272 lastmapping
->next
= mapping
;
4274 firstmapping
= mapping
;
4275 lastmapping
= mapping
;
4280 return (firstmapping
);
4284 * Build the group mapping list
4285 * group identification may be given in symbolic or numeric format
4287 * gid not associated to a uid are processed first in order
4288 * to favour real groups
4290 * ! Note ! : does getgrnam() read /etc/group or some other file ?
4291 * if so there is a possible recursion into fuse if this
4292 * file is on NTFS, and fuse is not recursion safe.
4295 struct MAPPING
*ntfs_do_group_mapping(struct MAPLIST
*firstitem
)
4297 struct MAPLIST
*item
;
4298 struct MAPPING
*firstmapping
;
4299 struct MAPPING
*lastmapping
;
4300 struct MAPPING
*mapping
;
4308 firstmapping
= (struct MAPPING
*)NULL
;
4309 lastmapping
= (struct MAPPING
*)NULL
;
4310 for (step
=1; step
<=2; step
++) {
4311 for (item
= firstitem
; item
; item
= item
->next
) {
4312 secondstep
= (item
->uidstr
[0] != '\0')
4313 || !item
->gidstr
[0];
4314 ok
= (step
== 1 ? !secondstep
: secondstep
);
4315 if ((item
->gidstr
[0] >= '0')
4316 && (item
->gidstr
[0] <= '9'))
4317 gid
= atoi(item
->gidstr
);
4320 if (item
->gidstr
[0]) {
4321 grp
= getgrnam(item
->gidstr
);
4325 ntfs_log_early_error("Invalid group \"%s\"\n",
4330 * Records with no uid and no gid are inserted in the
4331 * second step to define the implicit mapping pattern
4335 || (!item
->uidstr
[0] && !item
->gidstr
[0]))) {
4336 sid
= encodesid(item
->sidstr
);
4337 if (sid
&& !item
->uidstr
[0] && !item
->gidstr
[0]
4338 && !ntfs_valid_pattern(sid
)) {
4339 /* error already logged */
4343 mapping
= (struct MAPPING
*)
4344 ntfs_malloc(sizeof(struct MAPPING
));
4349 mapping
->next
= (struct MAPPING
*)NULL
;
4351 lastmapping
->next
= mapping
;
4353 firstmapping
= mapping
;
4354 lastmapping
= mapping
;
4360 return (firstmapping
);