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-2009 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
61 * integration into secaudit, check whether Win32,
62 * may have to be adapted to compiler or something else
66 #if defined(__WIN32) | defined(__WIN32__) | defined(WNSC)
76 #include <sys/types.h>
80 * integration into secaudit/Win32
85 #define __LITTLE_ENDIAN 1234
86 #define __BYTE_ORDER __LITTLE_ENDIAN
89 * integration into secaudit/STSC
94 #define __BYTE_ORDER __BIG_ENDIAN
97 * integration into secaudit/Linux
105 #include "secaudit.h"
106 #endif /* HAVE_CONFIG_H */
109 * A few useful constants
116 static const char nullsidbytes
[] = {
119 0, 0, 0, 0, 0, 0, /* base */
120 0, 0, 0, 0 /* 1st level */
123 static const SID
*nullsid
= (const SID
*)nullsidbytes
;
126 * SID for world (S-1-1-0)
129 static const char worldsidbytes
[] = {
132 0, 0, 0, 0, 0, 1, /* base */
133 0, 0, 0, 0 /* 1st level */
136 const SID
*worldsid
= (const SID
*)worldsidbytes
;
139 * SID for administrator
142 static const char adminsidbytes
[] = {
145 0, 0, 0, 0, 0, 5, /* base */
146 32, 0, 0, 0, /* 1st level */
147 32, 2, 0, 0 /* 2nd level */
150 const SID
*adminsid
= (const SID
*)adminsidbytes
;
156 static const char systemsidbytes
[] = {
159 0, 0, 0, 0, 0, 5, /* base */
160 18, 0, 0, 0 /* 1st level */
163 static const SID
*systemsid
= (const SID
*)systemsidbytes
;
166 * SID for generic creator-owner
170 static const char ownersidbytes
[] = {
173 0, 0, 0, 0, 0, 3, /* base */
174 0, 0, 0, 0 /* 1st level */
177 static const SID
*ownersid
= (const SID
*)ownersidbytes
;
180 * SID for generic creator-group
184 static const char groupsidbytes
[] = {
187 0, 0, 0, 0, 0, 3, /* base */
188 1, 0, 0, 0 /* 1st level */
191 static const SID
*groupsid
= (const SID
*)groupsidbytes
;
194 * Determine the size of a SID
197 int ntfs_sid_size(const SID
* sid
)
199 return (sid
->sub_authority_count
* 4 + 8);
203 * Test whether two SID are equal
206 BOOL
ntfs_same_sid(const SID
*first
, const SID
*second
)
210 size
= ntfs_sid_size(first
);
211 return ((ntfs_sid_size(second
) == size
)
212 && !memcmp(first
, second
, size
));
216 * Test whether a SID means "world user"
217 * Local users group also recognized as world
220 static int is_world_sid(const SID
* usid
)
223 /* check whether S-1-1-0 : world */
224 ((usid
->sub_authority_count
== 1)
225 && (usid
->identifier_authority
.high_part
== const_cpu_to_be16(0))
226 && (usid
->identifier_authority
.low_part
== const_cpu_to_be32(1))
227 && (usid
->sub_authority
[0] == const_cpu_to_le32(0)))
229 /* check whether S-1-5-32-545 : local user */
230 || ((usid
->sub_authority_count
== 2)
231 && (usid
->identifier_authority
.high_part
== const_cpu_to_be16(0))
232 && (usid
->identifier_authority
.low_part
== const_cpu_to_be32(5))
233 && (usid
->sub_authority
[0] == const_cpu_to_le32(32))
234 && (usid
->sub_authority
[1] == const_cpu_to_le32(545)))
239 * Test whether a SID means "some user (or group)"
240 * Currently we only check for S-1-5-21... but we should
241 * probably test for other configurations
244 BOOL
ntfs_is_user_sid(const SID
*usid
)
246 return ((usid
->sub_authority_count
== 5)
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(21)));
253 * Determine the size of a security attribute
254 * whatever the order of fields
257 unsigned int ntfs_attr_size(const char *attr
)
259 const SECURITY_DESCRIPTOR_RELATIVE
*phead
;
263 unsigned int offdacl
;
264 unsigned int offsacl
;
265 unsigned int offowner
;
266 unsigned int offgroup
;
271 phead
= (const SECURITY_DESCRIPTOR_RELATIVE
*)attr
;
273 * First check group, which is the last field in all descriptors
274 * we build, and in most descriptors built by Windows
276 attrsz
= sizeof(SECURITY_DESCRIPTOR_RELATIVE
);
277 offgroup
= le32_to_cpu(phead
->group
);
278 if (offgroup
>= attrsz
) {
279 /* find end of GSID */
280 psid
= (const SID
*)&attr
[offgroup
];
281 endsid
= offgroup
+ ntfs_sid_size(psid
);
282 if (endsid
> attrsz
) attrsz
= endsid
;
284 offowner
= le32_to_cpu(phead
->owner
);
285 if (offowner
>= attrsz
) {
286 /* find end of USID */
287 psid
= (const SID
*)&attr
[offowner
];
288 endsid
= offowner
+ ntfs_sid_size(psid
);
291 offsacl
= le32_to_cpu(phead
->sacl
);
292 if (offsacl
>= attrsz
) {
293 /* find end of SACL */
294 psacl
= (const ACL
*)&attr
[offsacl
];
295 endacl
= offsacl
+ le16_to_cpu(psacl
->size
);
301 /* find end of DACL */
302 offdacl
= le32_to_cpu(phead
->dacl
);
303 if (offdacl
>= attrsz
) {
304 pdacl
= (const ACL
*)&attr
[offdacl
];
305 endacl
= offdacl
+ le16_to_cpu(pdacl
->size
);
313 * Do sanity checks on a SID read from storage
314 * (just check revision and number of authorities)
317 BOOL
ntfs_valid_sid(const SID
*sid
)
319 return ((sid
->revision
== SID_REVISION
)
320 && (sid
->sub_authority_count
>= 1)
321 && (sid
->sub_authority_count
<= 8));
325 * Check whether a SID is acceptable for an implicit
327 * It should have been already checked it is a valid user SID.
329 * The last authority reference has to be >= 1000 (Windows usage)
330 * and <= 0x7fffffff, so that 30 bits from a uid and 30 more bits
331 * from a gid an be inserted with no overflow.
334 BOOL
ntfs_valid_pattern(const SID
*sid
)
340 cnt
= sid
->sub_authority_count
;
341 leauth
= sid
->sub_authority
[cnt
-1];
342 auth
= le32_to_cpu(leauth
);
343 return ((auth
>= 1000) && (auth
<= 0x7fffffff));
347 * Compute the uid or gid associated to a SID
348 * through an implicit mapping
350 * Returns 0 (root) if it does not match pattern
353 static u32
findimplicit(const SID
*xsid
, const SID
*pattern
, int parity
)
357 u32 xid
; /* uid or gid */
365 memcpy(&defsid
,pattern
,ntfs_sid_size(pattern
));
366 psid
= (SID
*)&defsid
;
367 cnt
= psid
->sub_authority_count
;
369 if (xsid
->sub_authority_count
== cnt
) {
370 psid
->sub_authority
[cnt
-1] = xsid
->sub_authority
[cnt
-1];
371 leauth
= xsid
->sub_authority
[cnt
-1];
372 xlast
= le32_to_cpu(leauth
);
373 leauth
= pattern
->sub_authority
[cnt
-1];
374 rlast
= le32_to_cpu(leauth
);
376 if ((xlast
> rlast
) && !((xlast
^ rlast
^ parity
) & 1)) {
377 /* direct check for basic situation */
378 if (ntfs_same_sid(psid
,xsid
))
379 xid
= ((xlast
- rlast
) >> 1) & 0x3fffffff;
382 * check whether part of mapping had to be
383 * recorded in a higher level authority
387 leauth
= psid
->sub_authority
[cnt
-2];
388 uauth
= le32_to_cpu(leauth
) + 1;
389 psid
->sub_authority
[cnt
-2]
390 = cpu_to_le32(uauth
);
391 } while (!ntfs_same_sid(psid
,xsid
)
394 xid
= (((xlast
- rlast
) >> 1)
395 & 0x3fffffff) | (carry
<< 30);
403 * Find usid mapped to a Linux user
404 * Returns NULL if not found
407 const SID
*ntfs_find_usid(const struct MAPPING
* usermapping
,
408 uid_t uid
, SID
*defusid
)
410 const struct MAPPING
*p
;
420 while (p
&& p
->xid
&& ((uid_t
)p
->xid
!= uid
))
424 * default pattern has been reached :
425 * build an implicit SID according to pattern
426 * (the pattern format was checked while reading
429 memcpy(defusid
, p
->sid
, ntfs_sid_size(p
->sid
));
430 cnt
= defusid
->sub_authority_count
;
431 leauth
= defusid
->sub_authority
[cnt
-1];
432 uauth
= le32_to_cpu(leauth
) + 2*(uid
& 0x3fffffff);
433 defusid
->sub_authority
[cnt
-1] = cpu_to_le32(uauth
);
434 if (uid
& 0xc0000000) {
435 leauth
= defusid
->sub_authority
[cnt
-2];
436 uauth
= le32_to_cpu(leauth
) + ((uid
>> 30) & 3);
437 defusid
->sub_authority
[cnt
-2] = cpu_to_le32(uauth
);
441 sid
= (p
? p
->sid
: (const SID
*)NULL
);
447 * Find Linux group mapped to a gsid
448 * Returns 0 (root) if not found
451 const SID
*ntfs_find_gsid(const struct MAPPING
* groupmapping
,
452 gid_t gid
, SID
*defgsid
)
454 const struct MAPPING
*p
;
464 while (p
&& p
->xid
&& ((gid_t
)p
->xid
!= gid
))
468 * default pattern has been reached :
469 * build an implicit SID according to pattern
470 * (the pattern format was checked while reading
473 memcpy(defgsid
, p
->sid
, ntfs_sid_size(p
->sid
));
474 cnt
= defgsid
->sub_authority_count
;
475 leauth
= defgsid
->sub_authority
[cnt
-1];
476 uauth
= le32_to_cpu(leauth
) + 2*(gid
& 0x3fffffff) + 1;
477 defgsid
->sub_authority
[cnt
-1] = cpu_to_le32(uauth
);
478 if (gid
& 0xc0000000) {
479 leauth
= defgsid
->sub_authority
[cnt
-2];
480 uauth
= le32_to_cpu(leauth
) + ((gid
>> 30) & 3);
481 defgsid
->sub_authority
[cnt
-2] = cpu_to_le32(uauth
);
485 sid
= (p
? p
->sid
: (const SID
*)NULL
);
491 * Find Linux owner mapped to a usid
492 * Returns 0 (root) if not found
495 uid_t
ntfs_find_user(const struct MAPPING
* usermapping
, const SID
*usid
)
498 const struct MAPPING
*p
;
501 while (p
&& p
->xid
&& !ntfs_same_sid(usid
, p
->sid
))
505 * No explicit mapping found, try implicit mapping
507 uid
= findimplicit(usid
,p
->sid
,0);
509 uid
= (p
? p
->xid
: 0);
514 * Find Linux group mapped to a gsid
515 * Returns 0 (root) if not found
518 gid_t
ntfs_find_group(const struct MAPPING
* groupmapping
, const SID
* gsid
)
521 const struct MAPPING
*p
;
524 gsidsz
= ntfs_sid_size(gsid
);
526 while (p
&& p
->xid
&& !ntfs_same_sid(gsid
, p
->sid
))
530 * No explicit mapping found, try implicit mapping
532 gid
= findimplicit(gsid
,p
->sid
,1);
534 gid
= (p
? p
->xid
: 0);
539 * Check the validity of the ACEs in a DACL or SACL
542 static BOOL
valid_acl(const ACL
*pacl
, unsigned int end
)
544 const ACCESS_ALLOWED_ACE
*pace
;
552 acecnt
= le16_to_cpu(pacl
->ace_count
);
553 offace
= sizeof(ACL
);
554 for (nace
= 0; (nace
< acecnt
) && ok
; nace
++) {
555 /* be sure the beginning is within range */
556 if ((offace
+ sizeof(ACCESS_ALLOWED_ACE
)) > end
)
559 pace
= (const ACCESS_ALLOWED_ACE
*)
560 &((const char*)pacl
)[offace
];
561 acesz
= le16_to_cpu(pace
->size
);
562 if (((offace
+ acesz
) > end
)
563 || !ntfs_valid_sid(&pace
->sid
))
572 * Do sanity checks on security descriptors read from storage
573 * basically, we make sure that every field holds within
575 * Should not be called with a NULL argument
576 * returns TRUE if considered safe
577 * if not, error should be logged by caller
580 BOOL
ntfs_valid_descr(const char *securattr
, unsigned int attrsz
)
582 const SECURITY_DESCRIPTOR_RELATIVE
*phead
;
585 unsigned int offdacl
;
586 unsigned int offsacl
;
587 unsigned int offowner
;
588 unsigned int offgroup
;
594 * first check overall size if within allocation range
595 * and a DACL is present
596 * and owner and group SID are valid
599 phead
= (const SECURITY_DESCRIPTOR_RELATIVE
*)securattr
;
600 offdacl
= le32_to_cpu(phead
->dacl
);
601 offsacl
= le32_to_cpu(phead
->sacl
);
602 offowner
= le32_to_cpu(phead
->owner
);
603 offgroup
= le32_to_cpu(phead
->group
);
604 pdacl
= (const ACL
*)&securattr
[offdacl
];
605 psacl
= (const ACL
*)&securattr
[offsacl
];
608 * size check occurs before the above pointers are used
610 * "DR Watson" standard directory on WinXP has an
611 * old revision and no DACL though SE_DACL_PRESENT is set
613 if ((attrsz
>= sizeof(SECURITY_DESCRIPTOR_RELATIVE
))
614 && (ntfs_attr_size(securattr
) <= attrsz
)
615 && (phead
->revision
== SECURITY_DESCRIPTOR_REVISION
)
616 && (offowner
>= sizeof(SECURITY_DESCRIPTOR_RELATIVE
))
617 && ((offowner
+ 2) < attrsz
)
618 && (offgroup
>= sizeof(SECURITY_DESCRIPTOR_RELATIVE
))
619 && ((offgroup
+ 2) < attrsz
)
621 || ((offdacl
>= sizeof(SECURITY_DESCRIPTOR_RELATIVE
))
622 && (offdacl
< attrsz
)))
624 || ((offsacl
>= sizeof(SECURITY_DESCRIPTOR_RELATIVE
))
625 && (offsacl
< attrsz
)))
626 && !(phead
->owner
& const_cpu_to_le32(3))
627 && !(phead
->group
& const_cpu_to_le32(3))
628 && !(phead
->dacl
& const_cpu_to_le32(3))
629 && !(phead
->sacl
& const_cpu_to_le32(3))
630 && ntfs_valid_sid((const SID
*)&securattr
[offowner
])
631 && ntfs_valid_sid((const SID
*)&securattr
[offgroup
])
633 * if there is an ACL, as indicated by offdacl,
634 * require SE_DACL_PRESENT
635 * but "Dr Watson" has SE_DACL_PRESENT though no DACL
638 || ((phead
->control
& SE_DACL_PRESENT
)
639 && ((pdacl
->revision
== ACL_REVISION
)
640 || (pdacl
->revision
== ACL_REVISION_DS
))))
643 || ((phead
->control
& SE_SACL_PRESENT
)
644 && ((psacl
->revision
== ACL_REVISION
)
645 || (psacl
->revision
== ACL_REVISION_DS
))))) {
647 * Check the DACL and SACL if present
649 if ((offdacl
&& !valid_acl(pdacl
,attrsz
- offdacl
))
650 || (offsacl
&& !valid_acl(psacl
,attrsz
- offsacl
)))
658 * Copy the inheritable parts of an ACL
660 * Returns the size of the new ACL
661 * or zero if nothing is inheritable
664 int ntfs_inherit_acl(const ACL
*oldacl
, ACL
*newacl
,
665 const SID
*usid
, const SID
*gsid
, BOOL fordir
)
671 unsigned int selection
;
676 const ACCESS_ALLOWED_ACE
*poldace
;
677 ACCESS_ALLOWED_ACE
*pnewace
;
679 usidsz
= ntfs_sid_size(usid
);
680 gsidsz
= ntfs_sid_size(gsid
);
684 newacl
->revision
= ACL_REVISION
;
685 newacl
->alignment1
= 0;
686 newacl
->alignment2
= const_cpu_to_le16(0);
687 src
= dst
= sizeof(ACL
);
689 selection
= (fordir
? CONTAINER_INHERIT_ACE
: OBJECT_INHERIT_ACE
);
691 oldcnt
= le16_to_cpu(oldacl
->ace_count
);
692 for (nace
= 0; nace
< oldcnt
; nace
++) {
693 poldace
= (const ACCESS_ALLOWED_ACE
*)((const char*)oldacl
+ src
);
694 acesz
= le16_to_cpu(poldace
->size
);
695 /* inheritance for access */
696 if (poldace
->flags
& selection
) {
697 pnewace
= (ACCESS_ALLOWED_ACE
*)
698 ((char*)newacl
+ dst
);
699 memcpy(pnewace
,poldace
,acesz
);
701 * Replace generic creator-owner and
702 * creator-group by owner and group
704 if (ntfs_same_sid(&pnewace
->sid
, ownersid
)) {
705 memcpy(&pnewace
->sid
, usid
, usidsz
);
708 if (ntfs_same_sid(&pnewace
->sid
, groupsid
)) {
709 memcpy(&pnewace
->sid
, gsid
, gsidsz
);
712 if (pnewace
->mask
& GENERIC_ALL
) {
713 pnewace
->mask
&= ~GENERIC_ALL
;
715 pnewace
->mask
|= OWNER_RIGHTS
721 * The last flag is not defined for a file,
722 * however Windows sets it, so do the same
724 pnewace
->mask
|= OWNER_RIGHTS
730 /* remove inheritance flags */
731 pnewace
->flags
&= ~(OBJECT_INHERIT_ACE
732 | CONTAINER_INHERIT_ACE
737 /* inheritance for further inheritance */
740 & (CONTAINER_INHERIT_ACE
| OBJECT_INHERIT_ACE
))) {
741 pnewace
= (ACCESS_ALLOWED_ACE
*)
742 ((char*)newacl
+ dst
);
743 memcpy(pnewace
,poldace
,acesz
);
745 * Replace generic creator-owner and
746 * creator-group by owner and group
748 if (ntfs_same_sid(&pnewace
->sid
, ownersid
)) {
749 memcpy(&pnewace
->sid
, usid
, usidsz
);
752 if (ntfs_same_sid(&pnewace
->sid
, groupsid
)) {
753 memcpy(&pnewace
->sid
, gsid
, gsidsz
);
762 * Adjust header if something was inherited
764 if (dst
> sizeof(ACL
)) {
765 newacl
->ace_count
= cpu_to_le16(newcnt
);
766 newacl
->size
= cpu_to_le16(dst
);
775 * Do sanity checks on a Posix descriptor
776 * Should not be called with a NULL argument
777 * returns TRUE if considered safe
778 * if not, error should be logged by caller
781 BOOL
ntfs_valid_posix(const struct POSIX_SECURITY
*pxdesc
)
783 const struct POSIX_ACL
*pacl
;
799 for (i
=0; i
<2; i
++) {
801 checks
[i
].tagsset
= 0;
802 checks
[i
].owners
= 0;
803 checks
[i
].groups
= 0;
804 checks
[i
].others
= 0;
805 checks
[i
].previous
= 0;
806 checks
[i
].previousid
= 0;
811 * header (strict for now)
813 if ((pacl
->version
!= POSIX_VERSION
)
814 || (pacl
->flags
!= 0)
815 || (pacl
->filler
!= 0))
818 * Reject multiple owner, group or other
819 * but do not require them to be present
820 * Also check the ACEs are in correct order
821 * which implies there is no duplicates
823 for (i
=0; i
<pxdesc
->acccnt
+ pxdesc
->defcnt
; i
++) {
824 if (i
>= pxdesc
->firstdef
)
828 perms
= pacl
->ace
[i
].perms
;
829 tag
= pacl
->ace
[i
].tag
;
830 pchk
->tagsset
|= tag
;
831 id
= pacl
->ace
[i
].id
;
832 if (perms
& ~7) ok
= FALSE
;
833 if ((tag
< pchk
->previous
)
834 || ((tag
== pchk
->previous
)
835 && (id
<= pchk
->previousid
)))
837 pchk
->previous
= tag
;
838 pchk
->previousid
= id
;
840 case POSIX_ACL_USER_OBJ
:
845 pchk
->mode
|= perms
<< 6;
847 case POSIX_ACL_GROUP_OBJ
:
852 pchk
->mode
= (pchk
->mode
& 07707) | (perms
<< 3);
854 case POSIX_ACL_OTHER
:
861 case POSIX_ACL_USER
:
862 case POSIX_ACL_GROUP
:
866 case POSIX_ACL_MASK
:
869 pchk
->mode
= (pchk
->mode
& 07707) | (perms
<< 3);
876 if ((pxdesc
->acccnt
> 0)
877 && ((checks
[0].owners
!= 1) || (checks
[0].groups
!= 1)
878 || (checks
[0].others
!= 1)))
880 /* do not check owner, group or other are present in */
881 /* the default ACL, Windows does not necessarily set them */
883 if (pxdesc
->defcnt
&& (pxdesc
->acccnt
> pxdesc
->firstdef
))
885 if ((pxdesc
->acccnt
< 0) || (pxdesc
->defcnt
< 0))
887 /* check mode, unless null or no tag set */
890 && (checks
[0].mode
!= (pxdesc
->mode
& 0777)))
893 if (pxdesc
->tagsset
!= checks
[0].tagsset
)
899 * Set standard header data into a Posix ACL
900 * The mode argument should provide the 3 upper bits of target mode
903 static mode_t
posix_header(struct POSIX_SECURITY
*pxdesc
, mode_t basemode
)
907 struct POSIX_ACE
*pace
;
910 mode
= basemode
& 07000;
912 for (i
=0; i
<pxdesc
->acccnt
; i
++) {
913 pace
= &pxdesc
->acl
.ace
[i
];
914 tagsset
|= pace
->tag
;
916 case POSIX_ACL_USER_OBJ
:
917 mode
|= (pace
->perms
& 7) << 6;
919 case POSIX_ACL_GROUP_OBJ
:
920 case POSIX_ACL_MASK
:
921 mode
= (mode
& 07707) | ((pace
->perms
& 7) << 3);
923 case POSIX_ACL_OTHER
:
924 mode
|= pace
->perms
& 7;
930 pxdesc
->tagsset
= tagsset
;
932 pxdesc
->acl
.version
= POSIX_VERSION
;
933 pxdesc
->acl
.flags
= 0;
934 pxdesc
->acl
.filler
= 0;
939 * Sort ACEs in a Posix ACL
940 * This is useful for always getting reusable converted ACLs,
941 * it also helps in merging ACEs.
942 * Repeated tag+id are allowed and not merged here.
944 * Tags should be in ascending sequence and for a repeatable tag
945 * ids should be in ascending sequence.
948 void ntfs_sort_posix(struct POSIX_SECURITY
*pxdesc
)
950 struct POSIX_ACL
*pacl
;
951 struct POSIX_ACE ace
;
962 * Check sequencing of tag+id in access ACE's
967 previous
= pacl
->ace
[0].tag
;
968 previousid
= pacl
->ace
[0].id
;
969 for (i
=1; i
<pxdesc
->acccnt
; i
++) {
970 tag
= pacl
->ace
[i
].tag
;
971 id
= pacl
->ace
[i
].id
;
974 || ((tag
== previous
) && (id
< previousid
))) {
976 memcpy(&ace
,&pacl
->ace
[i
-1],sizeof(struct POSIX_ACE
));
977 memcpy(&pacl
->ace
[i
-1],&pacl
->ace
[i
],sizeof(struct POSIX_ACE
));
978 memcpy(&pacl
->ace
[i
],&ace
,sizeof(struct POSIX_ACE
));
986 * Same for default ACEs
990 if ((pxdesc
->defcnt
) > 1) {
991 offs
= pxdesc
->firstdef
;
992 previous
= pacl
->ace
[offs
].tag
;
993 previousid
= pacl
->ace
[offs
].id
;
994 for (i
=offs
+1; i
<offs
+pxdesc
->defcnt
; i
++) {
995 tag
= pacl
->ace
[i
].tag
;
996 id
= pacl
->ace
[i
].id
;
999 || ((tag
== previous
) && (id
< previousid
))) {
1001 memcpy(&ace
,&pacl
->ace
[i
-1],sizeof(struct POSIX_ACE
));
1002 memcpy(&pacl
->ace
[i
-1],&pacl
->ace
[i
],sizeof(struct POSIX_ACE
));
1003 memcpy(&pacl
->ace
[i
],&ace
,sizeof(struct POSIX_ACE
));
1014 * Merge a new mode into a Posix descriptor
1015 * The Posix descriptor is not reallocated, its size is unchanged
1020 int ntfs_merge_mode_posix(struct POSIX_SECURITY
*pxdesc
, mode_t mode
)
1024 struct POSIX_ACE
*pace
;
1028 todo
= POSIX_ACL_USER_OBJ
| POSIX_ACL_GROUP_OBJ
| POSIX_ACL_OTHER
;
1029 for (i
=pxdesc
->acccnt
-1; i
>=0; i
--) {
1030 pace
= &pxdesc
->acl
.ace
[i
];
1032 case POSIX_ACL_USER_OBJ
:
1033 pace
->perms
= (mode
>> 6) & 7;
1034 todo
&= ~POSIX_ACL_USER_OBJ
;
1036 case POSIX_ACL_GROUP_OBJ
:
1038 pace
->perms
= (mode
>> 3) & 7;
1039 todo
&= ~POSIX_ACL_GROUP_OBJ
;
1041 case POSIX_ACL_MASK
:
1042 pace
->perms
= (mode
>> 3) & 7;
1045 case POSIX_ACL_OTHER
:
1046 pace
->perms
= mode
& 7;
1047 todo
&= ~POSIX_ACL_OTHER
;
1053 pxdesc
->mode
= mode
;
1054 return (todo
? -1 : 0);
1058 * Replace an access or default Posix ACL
1059 * The resulting ACL is checked for validity
1061 * Returns a new ACL or NULL if there is a problem
1064 struct POSIX_SECURITY
*ntfs_replace_acl(const struct POSIX_SECURITY
*oldpxdesc
,
1065 const struct POSIX_ACL
*newacl
, int count
, BOOL deflt
)
1067 struct POSIX_SECURITY
*newpxdesc
;
1074 newsize
= sizeof(struct POSIX_SECURITY
)
1075 + (oldpxdesc
->acccnt
+ count
)*sizeof(struct POSIX_ACE
);
1077 newsize
= sizeof(struct POSIX_SECURITY
)
1078 + (oldpxdesc
->defcnt
+ count
)*sizeof(struct POSIX_ACE
);
1079 newpxdesc
= (struct POSIX_SECURITY
*)malloc(newsize
);
1082 offset
= oldpxdesc
->acccnt
;
1083 newpxdesc
->acccnt
= oldpxdesc
->acccnt
;
1084 newpxdesc
->defcnt
= count
;
1085 newpxdesc
->firstdef
= offset
;
1086 /* copy access ACEs */
1087 for (i
=0; i
<newpxdesc
->acccnt
; i
++)
1088 newpxdesc
->acl
.ace
[i
] = oldpxdesc
->acl
.ace
[i
];
1089 /* copy default ACEs */
1090 for (i
=0; i
<count
; i
++)
1091 newpxdesc
->acl
.ace
[i
+ offset
] = newacl
->ace
[i
];
1094 newpxdesc
->acccnt
= count
;
1095 newpxdesc
->defcnt
= oldpxdesc
->defcnt
;
1096 newpxdesc
->firstdef
= count
;
1097 /* copy access ACEs */
1098 for (i
=0; i
<count
; i
++)
1099 newpxdesc
->acl
.ace
[i
] = newacl
->ace
[i
];
1100 /* copy default ACEs */
1101 oldoffset
= oldpxdesc
->firstdef
;
1102 for (i
=0; i
<newpxdesc
->defcnt
; i
++)
1103 newpxdesc
->acl
.ace
[i
+ offset
] = oldpxdesc
->acl
.ace
[i
+ oldoffset
];
1105 /* assume special flags unchanged */
1106 posix_header(newpxdesc
, oldpxdesc
->mode
);
1107 if (!ntfs_valid_posix(newpxdesc
)) {
1108 /* do not log, this is an application error */
1110 newpxdesc
= (struct POSIX_SECURITY
*)NULL
;
1119 * Build an inherited Posix descriptor from parent
1120 * descriptor (if any) restricted to creation mode
1122 * Returns the inherited descriptor or NULL if there is a problem
1125 struct POSIX_SECURITY
*ntfs_build_inherited_posix(
1126 const struct POSIX_SECURITY
*pxdesc
, mode_t mode
,
1127 mode_t mask
, BOOL isdir
)
1129 struct POSIX_SECURITY
*pydesc
;
1130 struct POSIX_ACE
*pyace
;
1137 if (pxdesc
&& pxdesc
->defcnt
) {
1139 count
= 2*pxdesc
->defcnt
+ 3;
1141 count
= pxdesc
->defcnt
+ 3;
1144 pydesc
= (struct POSIX_SECURITY
*)malloc(
1145 sizeof(struct POSIX_SECURITY
) + count
*sizeof(struct POSIX_ACE
));
1148 * Copy inherited tags and adapt perms
1149 * Use requested mode, ignoring umask
1150 * (not possible with older versions of fuse)
1153 defcnt
= (pxdesc
? pxdesc
->defcnt
: 0);
1154 for (i
=defcnt
-1; i
>=0; i
--) {
1155 pyace
= &pydesc
->acl
.ace
[i
];
1156 *pyace
= pxdesc
->acl
.ace
[pxdesc
->firstdef
+ i
];
1157 switch (pyace
->tag
) {
1158 case POSIX_ACL_USER_OBJ
:
1159 pyace
->perms
&= (mode
>> 6) & 7;
1161 case POSIX_ACL_GROUP_OBJ
:
1162 if (!(tagsset
& POSIX_ACL_MASK
))
1163 pyace
->perms
&= (mode
>> 3) & 7;
1165 case POSIX_ACL_OTHER
:
1166 pyace
->perms
&= mode
& 7;
1168 case POSIX_ACL_MASK
:
1169 pyace
->perms
&= (mode
>> 3) & 7;
1174 tagsset
|= pyace
->tag
;
1176 pydesc
->acccnt
= defcnt
;
1178 * If some standard tags were missing, append them from mode
1180 * Here we have to use the umask'ed mode
1182 if (~tagsset
& (POSIX_ACL_USER_OBJ
1183 | POSIX_ACL_GROUP_OBJ
| POSIX_ACL_OTHER
)) {
1185 /* owner was missing */
1186 if (!(tagsset
& POSIX_ACL_USER_OBJ
)) {
1187 pyace
= &pydesc
->acl
.ace
[i
];
1188 pyace
->tag
= POSIX_ACL_USER_OBJ
;
1190 pyace
->perms
= ((mode
& ~mask
) >> 6) & 7;
1191 tagsset
|= POSIX_ACL_USER_OBJ
;
1194 /* owning group was missing */
1195 if (!(tagsset
& POSIX_ACL_GROUP_OBJ
)) {
1196 pyace
= &pydesc
->acl
.ace
[i
];
1197 pyace
->tag
= POSIX_ACL_GROUP_OBJ
;
1199 pyace
->perms
= ((mode
& ~mask
) >> 3) & 7;
1200 tagsset
|= POSIX_ACL_GROUP_OBJ
;
1203 /* other was missing */
1204 if (!(tagsset
& POSIX_ACL_OTHER
)) {
1205 pyace
= &pydesc
->acl
.ace
[i
];
1206 pyace
->tag
= POSIX_ACL_OTHER
;
1208 pyace
->perms
= mode
& ~mask
& 7;
1209 tagsset
|= POSIX_ACL_OTHER
;
1213 pydesc
->firstdef
= i
;
1215 ntfs_sort_posix(pydesc
);
1219 * append as a default ACL if a directory
1221 pydesc
->firstdef
= pydesc
->acccnt
;
1222 if (defcnt
&& isdir
) {
1223 size
= sizeof(struct POSIX_ACE
)*defcnt
;
1224 memcpy(&pydesc
->acl
.ace
[pydesc
->firstdef
],
1225 &pxdesc
->acl
.ace
[pxdesc
->firstdef
],size
);
1226 pydesc
->defcnt
= defcnt
;
1230 /* assume special bits are not inherited */
1231 posix_header(pydesc
, mode
& 07000);
1232 if (!ntfs_valid_posix(pydesc
)) {
1233 ntfs_log_error("Error building an inherited Posix desc\n");
1236 pydesc
= (struct POSIX_SECURITY
*)NULL
;
1243 static int merge_lists_posix(struct POSIX_ACE
*targetace
,
1244 const struct POSIX_ACE
*firstace
,
1245 const struct POSIX_ACE
*secondace
,
1246 int firstcnt
, int secondcnt
)
1252 * No list is exhausted :
1253 * if same tag+id in both list :
1254 * ignore ACE from second list
1255 * else take the one with smaller tag+id
1257 while ((firstcnt
> 0) && (secondcnt
> 0))
1258 if ((firstace
->tag
== secondace
->tag
)
1259 && (firstace
->id
== secondace
->id
)) {
1263 if ((firstace
->tag
< secondace
->tag
)
1264 || ((firstace
->tag
== secondace
->tag
)
1265 && (firstace
->id
< secondace
->id
))) {
1266 targetace
->tag
= firstace
->tag
;
1267 targetace
->id
= firstace
->id
;
1268 targetace
->perms
= firstace
->perms
;
1274 targetace
->tag
= secondace
->tag
;
1275 targetace
->id
= secondace
->id
;
1276 targetace
->perms
= secondace
->perms
;
1283 * One list is exhausted, copy the other one
1285 while (firstcnt
> 0) {
1286 targetace
->tag
= firstace
->tag
;
1287 targetace
->id
= firstace
->id
;
1288 targetace
->perms
= firstace
->perms
;
1294 while (secondcnt
> 0) {
1295 targetace
->tag
= secondace
->tag
;
1296 targetace
->id
= secondace
->id
;
1297 targetace
->perms
= secondace
->perms
;
1307 * Merge two Posix ACLs
1308 * The input ACLs have to be adequately sorted
1310 * Returns the merged ACL, which is allocated and has to be freed by caller,
1314 struct POSIX_SECURITY
*ntfs_merge_descr_posix(const struct POSIX_SECURITY
*first
,
1315 const struct POSIX_SECURITY
*second
)
1317 struct POSIX_SECURITY
*pxdesc
;
1318 struct POSIX_ACE
*targetace
;
1319 const struct POSIX_ACE
*firstace
;
1320 const struct POSIX_ACE
*secondace
;
1324 size
= sizeof(struct POSIX_SECURITY
)
1325 + (first
->acccnt
+ first
->defcnt
1326 + second
->acccnt
+ second
->defcnt
)*sizeof(struct POSIX_ACE
);
1327 pxdesc
= (struct POSIX_SECURITY
*)malloc(size
);
1332 firstace
= first
->acl
.ace
;
1333 secondace
= second
->acl
.ace
;
1334 targetace
= pxdesc
->acl
.ace
;
1335 k
= merge_lists_posix(targetace
,firstace
,secondace
,
1336 first
->acccnt
,second
->acccnt
);
1339 * merge default ACEs
1341 pxdesc
->firstdef
= k
;
1342 firstace
= &first
->acl
.ace
[first
->firstdef
];
1343 secondace
= &second
->acl
.ace
[second
->firstdef
];
1344 targetace
= &pxdesc
->acl
.ace
[k
];
1345 k
= merge_lists_posix(targetace
,firstace
,secondace
,
1346 first
->defcnt
,second
->defcnt
);
1351 pxdesc
->acl
.version
= POSIX_VERSION
;
1352 pxdesc
->acl
.flags
= 0;
1353 pxdesc
->acl
.filler
= 0;
1355 pxdesc
->tagsset
= 0;
1361 struct BUILD_CONTEXT
{
1377 static BOOL
build_user_denials(ACL
*pacl
,
1378 const SID
*usid
, struct MAPPING
* const mapping
[],
1379 ACE_FLAGS flags
, const struct POSIX_ACE
*pxace
,
1380 struct BUILD_CONTEXT
*pset
)
1383 ACCESS_ALLOWED_ACE
*pdace
;
1399 perms
= pxace
->perms
;
1401 pos
= le16_to_cpu(pacl
->size
);
1402 acecnt
= le16_to_cpu(pacl
->ace_count
);
1403 avoidmask
= (pset
->mask
== (POSIX_PERM_R
| POSIX_PERM_W
| POSIX_PERM_X
))
1404 && ((pset
->designates
&& pset
->withmask
)
1405 || (!pset
->designates
&& !pset
->withmask
));
1406 if (tag
== POSIX_ACL_USER_OBJ
) {
1408 sidsz
= ntfs_sid_size(sid
);
1409 grants
= OWNER_RIGHTS
;
1412 sid
= NTFS_FIND_USID(mapping
[MAPUSERS
],
1413 pxace
->id
, (SID
*)&defsid
);
1414 grants
= WORLD_RIGHTS
;
1418 grants
= WORLD_RIGHTS
& ~ROOT_OWNER_UNMARK
;
1421 sidsz
= ntfs_sid_size(sid
);
1423 * Insert denial of complement of mask for
1424 * each designated user (except root)
1425 * WRITE_OWNER is inserted so that
1426 * the mask can be identified
1428 if (!avoidmask
&& !rootuser
) {
1429 denials
= WRITE_OWNER
;
1430 pdace
= (ACCESS_DENIED_ACE
*)&((char*)pacl
)[pos
];
1432 if (!(pset
->mask
& POSIX_PERM_X
))
1433 denials
|= DIR_EXEC
;
1434 if (!(pset
->mask
& POSIX_PERM_W
))
1435 denials
|= DIR_WRITE
;
1436 if (!(pset
->mask
& POSIX_PERM_R
))
1437 denials
|= DIR_READ
;
1439 if (!(pset
->mask
& POSIX_PERM_X
))
1440 denials
|= FILE_EXEC
;
1441 if (!(pset
->mask
& POSIX_PERM_W
))
1442 denials
|= FILE_WRITE
;
1443 if (!(pset
->mask
& POSIX_PERM_R
))
1444 denials
|= FILE_READ
;
1447 grants
&= ~ROOT_OWNER_UNMARK
;
1448 pdace
->type
= ACCESS_DENIED_ACE_TYPE
;
1449 pdace
->flags
= flags
;
1450 pdace
->size
= cpu_to_le16(sidsz
+ 8);
1451 pdace
->mask
= denials
;
1452 memcpy((char*)&pdace
->sid
, sid
, sidsz
);
1461 if (perms
& POSIX_PERM_X
)
1463 if (perms
& POSIX_PERM_W
)
1464 grants
|= DIR_WRITE
;
1465 if (perms
& POSIX_PERM_R
)
1468 if (perms
& POSIX_PERM_X
)
1469 grants
|= FILE_EXEC
;
1470 if (perms
& POSIX_PERM_W
)
1471 grants
|= FILE_WRITE
;
1472 if (perms
& POSIX_PERM_R
)
1473 grants
|= FILE_READ
;
1476 /* a possible ACE to deny owner what he/she would */
1477 /* induely get from administrator, group or world */
1478 /* unless owner is administrator or group */
1480 denials
= const_cpu_to_le32(0);
1481 pdace
= (ACCESS_DENIED_ACE
*)&((char*)pacl
)[pos
];
1482 if (!pset
->adminowns
&& !rootuser
) {
1483 if (!pset
->groupowns
) {
1484 mixperms
= pset
->grpperms
| pset
->othperms
;
1485 if (tag
== POSIX_ACL_USER_OBJ
)
1486 mixperms
|= pset
->selfuserperms
;
1488 if (mixperms
& POSIX_PERM_X
)
1489 denials
|= DIR_EXEC
;
1490 if (mixperms
& POSIX_PERM_W
)
1491 denials
|= DIR_WRITE
;
1492 if (mixperms
& POSIX_PERM_R
)
1493 denials
|= DIR_READ
;
1495 if (mixperms
& POSIX_PERM_X
)
1496 denials
|= FILE_EXEC
;
1497 if (mixperms
& POSIX_PERM_W
)
1498 denials
|= FILE_WRITE
;
1499 if (mixperms
& POSIX_PERM_R
)
1500 denials
|= FILE_READ
;
1503 mixperms
= ~pset
->grpperms
& pset
->othperms
;
1504 if (tag
== POSIX_ACL_USER_OBJ
)
1505 mixperms
|= pset
->selfuserperms
;
1507 if (mixperms
& POSIX_PERM_X
)
1508 denials
|= DIR_EXEC
;
1509 if (mixperms
& POSIX_PERM_W
)
1510 denials
|= DIR_WRITE
;
1511 if (mixperms
& POSIX_PERM_R
)
1512 denials
|= DIR_READ
;
1514 if (mixperms
& POSIX_PERM_X
)
1515 denials
|= FILE_EXEC
;
1516 if (mixperms
& POSIX_PERM_W
)
1517 denials
|= FILE_WRITE
;
1518 if (mixperms
& POSIX_PERM_R
)
1519 denials
|= FILE_READ
;
1524 pdace
->type
= ACCESS_DENIED_ACE_TYPE
;
1525 pdace
->flags
= flags
;
1526 pdace
->size
= cpu_to_le16(sidsz
+ 8);
1527 pdace
->mask
= denials
;
1528 memcpy((char*)&pdace
->sid
, sid
, sidsz
);
1534 pacl
->size
= cpu_to_le16(pos
);
1535 pacl
->ace_count
= cpu_to_le16(acecnt
);
1539 static BOOL
build_user_grants(ACL
*pacl
,
1540 const SID
*usid
, struct MAPPING
* const mapping
[],
1541 ACE_FLAGS flags
, const struct POSIX_ACE
*pxace
,
1542 struct BUILD_CONTEXT
*pset
)
1545 ACCESS_ALLOWED_ACE
*pgace
;
1558 perms
= pxace
->perms
;
1560 pos
= le16_to_cpu(pacl
->size
);
1561 acecnt
= le16_to_cpu(pacl
->ace_count
);
1562 if (tag
== POSIX_ACL_USER_OBJ
) {
1564 sidsz
= ntfs_sid_size(sid
);
1565 grants
= OWNER_RIGHTS
;
1568 sid
= NTFS_FIND_USID(mapping
[MAPUSERS
],
1569 pxace
->id
, (SID
*)&defsid
);
1571 sidsz
= ntfs_sid_size(sid
);
1574 grants
= WORLD_RIGHTS
;
1577 sidsz
= ntfs_sid_size(sid
);
1579 grants
= WORLD_RIGHTS
& ~ROOT_OWNER_UNMARK
;
1584 if (perms
& POSIX_PERM_X
)
1586 if (perms
& POSIX_PERM_W
)
1587 grants
|= DIR_WRITE
;
1588 if (perms
& POSIX_PERM_R
)
1591 if (perms
& POSIX_PERM_X
)
1592 grants
|= FILE_EXEC
;
1593 if (perms
& POSIX_PERM_W
)
1594 grants
|= FILE_WRITE
;
1595 if (perms
& POSIX_PERM_R
)
1596 grants
|= FILE_READ
;
1599 grants
&= ~ROOT_OWNER_UNMARK
;
1600 pgace
= (ACCESS_DENIED_ACE
*)&((char*)pacl
)[pos
];
1601 pgace
->type
= ACCESS_ALLOWED_ACE_TYPE
;
1602 pgace
->size
= cpu_to_le16(sidsz
+ 8);
1603 pgace
->flags
= flags
;
1604 pgace
->mask
= grants
;
1605 memcpy((char*)&pgace
->sid
, sid
, sidsz
);
1607 acecnt
= le16_to_cpu(pacl
->ace_count
) + 1;
1608 pacl
->ace_count
= cpu_to_le16(acecnt
);
1609 pacl
->size
= cpu_to_le16(pos
);
1615 /* a grant ACE for group */
1616 /* unless group-obj has the same rights as world */
1617 /* but present if group is owner or owner is administrator */
1618 /* this ACE will be inserted after denials for group */
1620 static BOOL
build_group_denials_grant(ACL
*pacl
,
1621 const SID
*gsid
, struct MAPPING
* const mapping
[],
1622 ACE_FLAGS flags
, const struct POSIX_ACE
*pxace
,
1623 struct BUILD_CONTEXT
*pset
)
1626 ACCESS_ALLOWED_ACE
*pdace
;
1627 ACCESS_ALLOWED_ACE
*pgace
;
1643 perms
= pxace
->perms
;
1644 pos
= le16_to_cpu(pacl
->size
);
1645 acecnt
= le16_to_cpu(pacl
->ace_count
);
1647 avoidmask
= (pset
->mask
== (POSIX_PERM_R
| POSIX_PERM_W
| POSIX_PERM_X
))
1648 && ((pset
->designates
&& pset
->withmask
)
1649 || (!pset
->designates
&& !pset
->withmask
));
1650 if (tag
== POSIX_ACL_GROUP_OBJ
)
1654 sid
= NTFS_FIND_GSID(mapping
[MAPGROUPS
],
1655 pxace
->id
, (SID
*)&defsid
);
1661 sidsz
= ntfs_sid_size(sid
);
1663 * Insert denial of complement of mask for
1665 * WRITE_OWNER is inserted so that
1666 * the mask can be identified
1667 * Note : this mask may lead on Windows to
1668 * deny rights to administrators belonging
1669 * to some user group
1671 if ((!avoidmask
&& !rootgroup
)
1672 || (pset
->rootspecial
1673 && (tag
== POSIX_ACL_GROUP_OBJ
))) {
1674 denials
= WRITE_OWNER
;
1675 pdace
= (ACCESS_DENIED_ACE
*)&((char*)pacl
)[pos
];
1677 if (!(pset
->mask
& POSIX_PERM_X
))
1678 denials
|= DIR_EXEC
;
1679 if (!(pset
->mask
& POSIX_PERM_W
))
1680 denials
|= DIR_WRITE
;
1681 if (!(pset
->mask
& POSIX_PERM_R
))
1682 denials
|= DIR_READ
;
1684 if (!(pset
->mask
& POSIX_PERM_X
))
1685 denials
|= FILE_EXEC
;
1686 if (!(pset
->mask
& POSIX_PERM_W
))
1687 denials
|= FILE_WRITE
;
1688 if (!(pset
->mask
& POSIX_PERM_R
))
1689 denials
|= FILE_READ
;
1691 pdace
->type
= ACCESS_DENIED_ACE_TYPE
;
1692 pdace
->flags
= flags
;
1693 pdace
->size
= cpu_to_le16(sidsz
+ 8);
1694 pdace
->mask
= denials
;
1695 memcpy((char*)&pdace
->sid
, sid
, sidsz
);
1706 || (perms
!= pset
->othperms
))) {
1707 grants
= WORLD_RIGHTS
;
1709 grants
&= ~ROOT_GROUP_UNMARK
;
1711 if (perms
& POSIX_PERM_X
)
1713 if (perms
& POSIX_PERM_W
)
1714 grants
|= DIR_WRITE
;
1715 if (perms
& POSIX_PERM_R
)
1718 if (perms
& POSIX_PERM_X
)
1719 grants
|= FILE_EXEC
;
1720 if (perms
& POSIX_PERM_W
)
1721 grants
|= FILE_WRITE
;
1722 if (perms
& POSIX_PERM_R
)
1723 grants
|= FILE_READ
;
1726 /* a possible ACE to deny group what it would get from world */
1727 /* or administrator, unless owner is administrator or group */
1729 denials
= const_cpu_to_le32(0);
1730 pdace
= (ACCESS_DENIED_ACE
*)&((char*)pacl
)[pos
];
1731 if (!pset
->adminowns
1734 mixperms
= pset
->othperms
;
1735 if (tag
== POSIX_ACL_GROUP_OBJ
)
1736 mixperms
|= pset
->selfgrpperms
;
1738 if (mixperms
& POSIX_PERM_X
)
1739 denials
|= DIR_EXEC
;
1740 if (mixperms
& POSIX_PERM_W
)
1741 denials
|= DIR_WRITE
;
1742 if (mixperms
& POSIX_PERM_R
)
1743 denials
|= DIR_READ
;
1745 if (mixperms
& POSIX_PERM_X
)
1746 denials
|= FILE_EXEC
;
1747 if (mixperms
& POSIX_PERM_W
)
1748 denials
|= FILE_WRITE
;
1749 if (mixperms
& POSIX_PERM_R
)
1750 denials
|= FILE_READ
;
1752 denials
&= ~(grants
| OWNER_RIGHTS
);
1754 pdace
->type
= ACCESS_DENIED_ACE_TYPE
;
1755 pdace
->flags
= flags
;
1756 pdace
->size
= cpu_to_le16(sidsz
+ 8);
1757 pdace
->mask
= denials
;
1758 memcpy((char*)&pdace
->sid
, sid
, sidsz
);
1764 /* now insert grants to group if more than world */
1767 || (avoidmask
&& (pset
->designates
|| pset
->withmask
))
1768 || (perms
& ~pset
->othperms
)
1769 || (pset
->rootspecial
1770 && (tag
== POSIX_ACL_GROUP_OBJ
))
1771 || (tag
== POSIX_ACL_GROUP
)) {
1773 grants
&= ~ROOT_GROUP_UNMARK
;
1774 pgace
= (ACCESS_DENIED_ACE
*)&((char*)pacl
)[pos
];
1775 pgace
->type
= ACCESS_ALLOWED_ACE_TYPE
;
1776 pgace
->flags
= flags
;
1777 pgace
->size
= cpu_to_le16(sidsz
+ 8);
1778 pgace
->mask
= grants
;
1779 memcpy((char*)&pgace
->sid
, sid
, sidsz
);
1784 pacl
->size
= cpu_to_le16(pos
);
1785 pacl
->ace_count
= cpu_to_le16(acecnt
);
1791 * Build an ACL composed of several ACE's
1792 * returns size of ACL or zero if failed
1794 * Three schemes are defined :
1796 * 1) if root is neither owner nor group up to 7 ACE's are set up :
1797 * - denials to owner (preventing grants to world or group to apply)
1798 * + mask denials to designated user (unless mask allows all)
1799 * + denials to designated user
1800 * - grants to owner (always present - first grant)
1801 * + grants to designated user
1802 * + mask denial to group (unless mask allows all)
1803 * - denials to group (preventing grants to world to apply)
1804 * - grants to group (unless group has no more than world rights)
1805 * + mask denials to designated group (unless mask allows all)
1806 * + grants to designated group
1807 * + denials to designated group
1808 * - grants to world (unless none)
1809 * - full privileges to administrator, always present
1810 * - full privileges to system, always present
1812 * The same scheme is applied for Posix ACLs, with the mask represented
1813 * as denials prepended to grants for designated users and groups
1815 * This is inspired by an Internet Draft from Marius Aamodt Eriksen
1816 * for mapping NFSv4 ACLs to Posix ACLs (draft-ietf-nfsv4-acl-mapping-00.txt)
1817 * More recent versions of the draft (draft-ietf-nfsv4-acl-mapping-05.txt)
1818 * are not followed, as they ignore the Posix mask and lead to
1819 * loss of compatibility with Linux implementations on other fs.
1821 * Note that denials to group are located after grants to owner.
1822 * This only occurs in the unfrequent situation where world
1823 * has more rights than group and cannot be avoided if owner and other
1824 * have some common right which is denied to group (eg for mode 745
1825 * executing has to be denied to group, but not to owner or world).
1826 * This rare situation is processed by Windows correctly, but
1827 * Windows utilities may want to change the order, with a
1828 * consequence of applying the group denials to the Windows owner.
1829 * The interpretation on Linux is not affected by the order change.
1831 * 2) if root is either owner or group, two problems arise :
1832 * - granting full rights to administrator (as needed to transpose
1833 * to Windows rights bypassing granting to root) would imply
1834 * Linux permissions to always be seen as rwx, no matter the chmod
1835 * - there is no different SID to separate an administrator owner
1836 * from an administrator group. Hence Linux permissions for owner
1837 * would always be similar to permissions to group.
1839 * as a work-around, up to 5 ACE's are set up if owner or group :
1840 * - grants to owner, always present at first position
1841 * - grants to group, always present
1842 * - grants to world, unless none
1843 * - full privileges to administrator, always present
1844 * - full privileges to system, always present
1846 * On Windows, these ACE's are processed normally, though they
1847 * are redundant (owner, group and administrator are the same,
1848 * as a consequence any denials would damage administrator rights)
1849 * but on Linux, privileges to administrator are ignored (they
1850 * are not needed as root has always full privileges), and
1851 * neither grants to group are applied to owner, nor grants to
1852 * world are applied to owner or group.
1854 * 3) finally a similar situation arises when group is owner (they
1855 * have the same SID), but is not root.
1856 * In this situation up to 6 ACE's are set up :
1858 * - denials to owner (preventing grants to world to apply)
1859 * - grants to owner (always present)
1860 * - grants to group (unless groups has same rights as world)
1861 * - grants to world (unless none)
1862 * - full privileges to administrator, always present
1863 * - full privileges to system, always present
1865 * On Windows, these ACE's are processed normally, though they
1866 * are redundant (as owner and group are the same), but this has
1867 * no impact on administrator rights
1869 * Special flags (S_ISVTX, S_ISGID, S_ISUID) :
1870 * an extra null ACE is inserted to hold these flags, using
1871 * the same conventions as cygwin.
1875 static int buildacls_posix(struct MAPPING
* const mapping
[],
1876 char *secattr
, int offs
, const struct POSIX_SECURITY
*pxdesc
,
1877 int isdir
, const SID
*usid
, const SID
*gsid
)
1879 struct BUILD_CONTEXT aceset
[2], *pset
;
1883 ACCESS_ALLOWED_ACE
*pgace
;
1884 ACCESS_ALLOWED_ACE
*pdace
;
1885 const struct POSIX_ACE
*pxace
;
1905 usidsz
= ntfs_sid_size(usid
);
1906 gsidsz
= ntfs_sid_size(gsid
);
1907 wsidsz
= ntfs_sid_size(worldsid
);
1908 asidsz
= ntfs_sid_size(adminsid
);
1909 ssidsz
= ntfs_sid_size(systemsid
);
1910 mode
= pxdesc
->mode
;
1911 /* adminowns and groupowns are used for both lists */
1912 adminowns
= ntfs_same_sid(usid
, adminsid
)
1913 || ntfs_same_sid(gsid
, adminsid
);
1914 groupowns
= !adminowns
&& ntfs_same_sid(usid
, gsid
);
1919 pacl
= (ACL
*)&secattr
[offs
];
1920 pacl
->revision
= ACL_REVISION
;
1921 pacl
->alignment1
= 0;
1922 pacl
->size
= cpu_to_le16(sizeof(ACL
) + usidsz
+ 8);
1923 pacl
->ace_count
= const_cpu_to_le16(0);
1924 pacl
->alignment2
= const_cpu_to_le16(0);
1927 * Determine what is allowed to some group or world
1928 * to prevent designated users or other groups to get
1929 * rights from groups or world
1930 * Do the same if owner and group appear as designated
1932 * Also get global mask
1934 for (k
=0; k
<2; k
++) {
1936 pset
->selfuserperms
= 0;
1937 pset
->selfgrpperms
= 0;
1940 pset
->mask
= (POSIX_PERM_R
| POSIX_PERM_W
| POSIX_PERM_X
);
1941 pset
->designates
= 0;
1943 pset
->rootspecial
= 0;
1944 pset
->adminowns
= adminowns
;
1945 pset
->groupowns
= groupowns
;
1946 pset
->isdir
= isdir
;
1949 for (i
=pxdesc
->acccnt
+pxdesc
->defcnt
-1; i
>=0; i
--) {
1950 if (i
>= pxdesc
->acccnt
) {
1952 pxace
= &pxdesc
->acl
.ace
[i
+ pxdesc
->firstdef
- pxdesc
->acccnt
];
1955 pxace
= &pxdesc
->acl
.ace
[i
];
1957 switch (pxace
->tag
) {
1958 case POSIX_ACL_USER
:
1961 sid
= NTFS_FIND_USID(mapping
[MAPUSERS
],
1962 pxace
->id
, (SID
*)&defsid
);
1963 if (sid
&& ntfs_same_sid(sid
,usid
))
1964 pset
->selfuserperms
|= pxace
->perms
;
1966 /* root as designated user is processed apart */
1967 pset
->rootspecial
= TRUE
;
1969 case POSIX_ACL_GROUP
:
1972 sid
= NTFS_FIND_GSID(mapping
[MAPUSERS
],
1973 pxace
->id
, (SID
*)&defsid
);
1974 if (sid
&& ntfs_same_sid(sid
,gsid
))
1975 pset
->selfgrpperms
|= pxace
->perms
;
1977 /* root as designated group is processed apart */
1978 pset
->rootspecial
= TRUE
;
1980 case POSIX_ACL_GROUP_OBJ
:
1981 pset
->grpperms
|= pxace
->perms
;
1983 case POSIX_ACL_OTHER
:
1984 pset
->othperms
= pxace
->perms
;
1986 case POSIX_ACL_MASK
:
1988 pset
->mask
= pxace
->perms
;
1994 if (pxdesc
->defcnt
&& (pxdesc
->firstdef
!= pxdesc
->acccnt
)) {
1995 ntfs_log_error("** error : access and default not consecutive\n");
1999 * First insert all denials for owner and each
2000 * designated user (with mask if needed)
2003 pacl
->ace_count
= const_cpu_to_le16(0);
2004 pacl
->size
= const_cpu_to_le16(sizeof(ACL
));
2005 for (i
=0; (i
<(pxdesc
->acccnt
+ pxdesc
->defcnt
)) && ok
; i
++) {
2006 if (i
>= pxdesc
->acccnt
) {
2007 flags
= INHERIT_ONLY_ACE
2008 | OBJECT_INHERIT_ACE
| CONTAINER_INHERIT_ACE
;
2010 pxace
= &pxdesc
->acl
.ace
[i
+ pxdesc
->firstdef
- pxdesc
->acccnt
];
2013 flags
= NO_PROPAGATE_INHERIT_ACE
;
2015 flags
= (isdir
? DIR_INHERITANCE
2016 : FILE_INHERITANCE
);
2018 pxace
= &pxdesc
->acl
.ace
[i
];
2021 perms
= pxace
->perms
;
2024 /* insert denial ACEs for each owner or allowed user */
2026 case POSIX_ACL_USER
:
2027 case POSIX_ACL_USER_OBJ
:
2029 ok
= build_user_denials(pacl
,
2030 usid
, mapping
, flags
, pxace
, pset
);
2038 * for directories, insert a world execution denial
2039 * inherited to plain files.
2040 * This is to prevent Windows from granting execution
2041 * of files through inheritance from parent directory
2045 pos
= le16_to_cpu(pacl
->size
);
2046 pdace
= (ACCESS_DENIED_ACE
*) &secattr
[offs
+ pos
];
2047 pdace
->type
= ACCESS_DENIED_ACE_TYPE
;
2048 pdace
->flags
= INHERIT_ONLY_ACE
| OBJECT_INHERIT_ACE
;
2049 pdace
->size
= cpu_to_le16(wsidsz
+ 8);
2050 pdace
->mask
= FILE_EXEC
;
2051 memcpy((char*)&pdace
->sid
, worldsid
, wsidsz
);
2053 acecnt
= le16_to_cpu(pacl
->ace_count
) + 1;
2054 pacl
->ace_count
= cpu_to_le16(acecnt
);
2055 pacl
->size
= cpu_to_le16(pos
);
2059 * now insert (if needed)
2060 * - grants to owner and designated users
2061 * - mask and denials for all groups
2065 for (i
=0; (i
<(pxdesc
->acccnt
+ pxdesc
->defcnt
)) && ok
; i
++) {
2066 if (i
>= pxdesc
->acccnt
) {
2067 flags
= INHERIT_ONLY_ACE
2068 | OBJECT_INHERIT_ACE
| CONTAINER_INHERIT_ACE
;
2070 pxace
= &pxdesc
->acl
.ace
[i
+ pxdesc
->firstdef
- pxdesc
->acccnt
];
2073 flags
= NO_PROPAGATE_INHERIT_ACE
;
2075 flags
= (isdir
? DIR_INHERITANCE
2076 : FILE_INHERITANCE
);
2078 pxace
= &pxdesc
->acl
.ace
[i
];
2081 perms
= pxace
->perms
;
2084 /* ACE for each owner or allowed user */
2086 case POSIX_ACL_USER
:
2087 case POSIX_ACL_USER_OBJ
:
2088 ok
= build_user_grants(pacl
,usid
,
2089 mapping
,flags
,pxace
,pset
);
2092 case POSIX_ACL_GROUP
:
2093 case POSIX_ACL_GROUP_OBJ
:
2095 /* denials and grants for groups */
2097 ok
= build_group_denials_grant(pacl
,gsid
,
2098 mapping
,flags
,pxace
,pset
);
2101 case POSIX_ACL_OTHER
:
2103 /* grants for other users */
2105 pos
= le16_to_cpu(pacl
->size
);
2106 pgace
= (ACCESS_ALLOWED_ACE
*)&secattr
[offs
+ pos
];
2107 grants
= WORLD_RIGHTS
;
2109 if (perms
& POSIX_PERM_X
)
2111 if (perms
& POSIX_PERM_W
)
2112 grants
|= DIR_WRITE
;
2113 if (perms
& POSIX_PERM_R
)
2116 if (perms
& POSIX_PERM_X
)
2117 grants
|= FILE_EXEC
;
2118 if (perms
& POSIX_PERM_W
)
2119 grants
|= FILE_WRITE
;
2120 if (perms
& POSIX_PERM_R
)
2121 grants
|= FILE_READ
;
2123 pgace
->type
= ACCESS_ALLOWED_ACE_TYPE
;
2124 pgace
->flags
= flags
;
2125 pgace
->size
= cpu_to_le16(wsidsz
+ 8);
2126 pgace
->mask
= grants
;
2127 memcpy((char*)&pgace
->sid
, worldsid
, wsidsz
);
2129 acecnt
= le16_to_cpu(pacl
->ace_count
) + 1;
2130 pacl
->ace_count
= cpu_to_le16(acecnt
);
2131 pacl
->size
= cpu_to_le16(pos
);
2140 /* an ACE for administrators */
2141 /* always full access */
2143 pos
= le16_to_cpu(pacl
->size
);
2144 acecnt
= le16_to_cpu(pacl
->ace_count
);
2146 flags
= OBJECT_INHERIT_ACE
2147 | CONTAINER_INHERIT_ACE
;
2149 flags
= NO_PROPAGATE_INHERIT_ACE
;
2150 pgace
= (ACCESS_ALLOWED_ACE
*)&secattr
[offs
+ pos
];
2151 pgace
->type
= ACCESS_ALLOWED_ACE_TYPE
;
2152 pgace
->flags
= flags
;
2153 pgace
->size
= cpu_to_le16(asidsz
+ 8);
2154 grants
= OWNER_RIGHTS
| FILE_READ
| FILE_WRITE
| FILE_EXEC
;
2155 pgace
->mask
= grants
;
2156 memcpy((char*)&pgace
->sid
, adminsid
, asidsz
);
2160 /* an ACE for system (needed ?) */
2161 /* always full access */
2163 pgace
= (ACCESS_ALLOWED_ACE
*)&secattr
[offs
+ pos
];
2164 pgace
->type
= ACCESS_ALLOWED_ACE_TYPE
;
2165 pgace
->flags
= flags
;
2166 pgace
->size
= cpu_to_le16(ssidsz
+ 8);
2167 grants
= OWNER_RIGHTS
| FILE_READ
| FILE_WRITE
| FILE_EXEC
;
2168 pgace
->mask
= grants
;
2169 memcpy((char*)&pgace
->sid
, systemsid
, ssidsz
);
2173 /* a null ACE to hold special flags */
2174 /* using the same representation as cygwin */
2176 if (mode
& (S_ISVTX
| S_ISGID
| S_ISUID
)) {
2177 nsidsz
= ntfs_sid_size(nullsid
);
2178 pgace
= (ACCESS_ALLOWED_ACE
*)&secattr
[offs
+ pos
];
2179 pgace
->type
= ACCESS_ALLOWED_ACE_TYPE
;
2180 pgace
->flags
= NO_PROPAGATE_INHERIT_ACE
;
2181 pgace
->size
= cpu_to_le16(nsidsz
+ 8);
2182 grants
= const_cpu_to_le32(0);
2184 grants
|= FILE_APPEND_DATA
;
2186 grants
|= FILE_WRITE_DATA
;
2188 grants
|= FILE_READ_DATA
;
2189 pgace
->mask
= grants
;
2190 memcpy((char*)&pgace
->sid
, nullsid
, nsidsz
);
2195 /* fix ACL header */
2196 pacl
->size
= cpu_to_le16(pos
);
2197 pacl
->ace_count
= cpu_to_le16(acecnt
);
2199 return (ok
? pos
: 0);
2202 #endif /* POSIXACLS */
2204 static int buildacls(char *secattr
, int offs
, mode_t mode
, int isdir
,
2205 const SID
* usid
, const SID
* gsid
)
2208 ACCESS_ALLOWED_ACE
*pgace
;
2209 ACCESS_ALLOWED_ACE
*pdace
;
2224 usidsz
= ntfs_sid_size(usid
);
2225 gsidsz
= ntfs_sid_size(gsid
);
2226 wsidsz
= ntfs_sid_size(worldsid
);
2227 asidsz
= ntfs_sid_size(adminsid
);
2228 ssidsz
= ntfs_sid_size(systemsid
);
2229 adminowns
= ntfs_same_sid(usid
, adminsid
)
2230 || ntfs_same_sid(gsid
, adminsid
);
2231 groupowns
= !adminowns
&& ntfs_same_sid(usid
, gsid
);
2234 pacl
= (ACL
*)&secattr
[offs
];
2235 pacl
->revision
= ACL_REVISION
;
2236 pacl
->alignment1
= 0;
2237 pacl
->size
= cpu_to_le16(sizeof(ACL
) + usidsz
+ 8);
2238 pacl
->ace_count
= const_cpu_to_le16(1);
2239 pacl
->alignment2
= const_cpu_to_le16(0);
2243 /* compute a grant ACE for owner */
2244 /* this ACE will be inserted after denial for owner */
2246 grants
= OWNER_RIGHTS
;
2248 gflags
= DIR_INHERITANCE
;
2252 grants
|= DIR_WRITE
;
2256 gflags
= FILE_INHERITANCE
;
2258 grants
|= FILE_EXEC
;
2260 grants
|= FILE_WRITE
;
2262 grants
|= FILE_READ
;
2265 /* a possible ACE to deny owner what he/she would */
2266 /* induely get from administrator, group or world */
2267 /* unless owner is administrator or group */
2269 denials
= const_cpu_to_le32(0);
2270 pdace
= (ACCESS_DENIED_ACE
*) &secattr
[offs
+ pos
];
2274 pdace
->flags
= DIR_INHERITANCE
;
2275 if (mode
& (S_IXGRP
| S_IXOTH
))
2276 denials
|= DIR_EXEC
;
2277 if (mode
& (S_IWGRP
| S_IWOTH
))
2278 denials
|= DIR_WRITE
;
2279 if (mode
& (S_IRGRP
| S_IROTH
))
2280 denials
|= DIR_READ
;
2282 pdace
->flags
= FILE_INHERITANCE
;
2283 if (mode
& (S_IXGRP
| S_IXOTH
))
2284 denials
|= FILE_EXEC
;
2285 if (mode
& (S_IWGRP
| S_IWOTH
))
2286 denials
|= FILE_WRITE
;
2287 if (mode
& (S_IRGRP
| S_IROTH
))
2288 denials
|= FILE_READ
;
2292 pdace
->flags
= DIR_INHERITANCE
;
2293 if ((mode
& S_IXOTH
) && !(mode
& S_IXGRP
))
2294 denials
|= DIR_EXEC
;
2295 if ((mode
& S_IWOTH
) && !(mode
& S_IWGRP
))
2296 denials
|= DIR_WRITE
;
2297 if ((mode
& S_IROTH
) && !(mode
& S_IRGRP
))
2298 denials
|= DIR_READ
;
2300 pdace
->flags
= FILE_INHERITANCE
;
2301 if ((mode
& S_IXOTH
) && !(mode
& S_IXGRP
))
2302 denials
|= FILE_EXEC
;
2303 if ((mode
& S_IWOTH
) && !(mode
& S_IWGRP
))
2304 denials
|= FILE_WRITE
;
2305 if ((mode
& S_IROTH
) && !(mode
& S_IRGRP
))
2306 denials
|= FILE_READ
;
2311 pdace
->type
= ACCESS_DENIED_ACE_TYPE
;
2312 pdace
->size
= cpu_to_le16(usidsz
+ 8);
2313 pdace
->mask
= denials
;
2314 memcpy((char*)&pdace
->sid
, usid
, usidsz
);
2320 * for directories, a world execution denial
2321 * inherited to plain files
2325 pdace
= (ACCESS_DENIED_ACE
*) &secattr
[offs
+ pos
];
2326 pdace
->type
= ACCESS_DENIED_ACE_TYPE
;
2327 pdace
->flags
= INHERIT_ONLY_ACE
| OBJECT_INHERIT_ACE
;
2328 pdace
->size
= cpu_to_le16(wsidsz
+ 8);
2329 pdace
->mask
= FILE_EXEC
;
2330 memcpy((char*)&pdace
->sid
, worldsid
, wsidsz
);
2336 /* now insert grants to owner */
2337 pgace
= (ACCESS_ALLOWED_ACE
*) &secattr
[offs
+ pos
];
2338 pgace
->type
= ACCESS_ALLOWED_ACE_TYPE
;
2339 pgace
->size
= cpu_to_le16(usidsz
+ 8);
2340 pgace
->flags
= gflags
;
2341 pgace
->mask
= grants
;
2342 memcpy((char*)&pgace
->sid
, usid
, usidsz
);
2346 /* a grant ACE for group */
2347 /* unless group has the same rights as world */
2348 /* but present if group is owner or owner is administrator */
2349 /* this ACE will be inserted after denials for group */
2353 || (((mode
>> 3) ^ mode
) & 7)) {
2354 grants
= WORLD_RIGHTS
;
2356 gflags
= DIR_INHERITANCE
;
2360 grants
|= DIR_WRITE
;
2364 gflags
= FILE_INHERITANCE
;
2366 grants
|= FILE_EXEC
;
2368 grants
|= FILE_WRITE
;
2370 grants
|= FILE_READ
;
2373 /* a possible ACE to deny group what it would get from world */
2374 /* or administrator, unless owner is administrator or group */
2376 denials
= const_cpu_to_le32(0);
2377 pdace
= (ACCESS_ALLOWED_ACE
*)&secattr
[offs
+ pos
];
2378 if (!adminowns
&& !groupowns
) {
2380 pdace
->flags
= DIR_INHERITANCE
;
2382 denials
|= DIR_EXEC
;
2384 denials
|= DIR_WRITE
;
2386 denials
|= DIR_READ
;
2388 pdace
->flags
= FILE_INHERITANCE
;
2390 denials
|= FILE_EXEC
;
2392 denials
|= FILE_WRITE
;
2394 denials
|= FILE_READ
;
2396 denials
&= ~(grants
| OWNER_RIGHTS
);
2398 pdace
->type
= ACCESS_DENIED_ACE_TYPE
;
2399 pdace
->size
= cpu_to_le16(gsidsz
+ 8);
2400 pdace
->mask
= denials
;
2401 memcpy((char*)&pdace
->sid
, gsid
, gsidsz
);
2409 || ((mode
>> 3) & ~mode
& 7)) {
2410 /* now insert grants to group */
2411 /* if more rights than other */
2412 pgace
= (ACCESS_ALLOWED_ACE
*)&secattr
[offs
+ pos
];
2413 pgace
->type
= ACCESS_ALLOWED_ACE_TYPE
;
2414 pgace
->flags
= gflags
;
2415 pgace
->size
= cpu_to_le16(gsidsz
+ 8);
2416 pgace
->mask
= grants
;
2417 memcpy((char*)&pgace
->sid
, gsid
, gsidsz
);
2423 /* an ACE for world users */
2425 pgace
= (ACCESS_ALLOWED_ACE
*)&secattr
[offs
+ pos
];
2426 pgace
->type
= ACCESS_ALLOWED_ACE_TYPE
;
2427 grants
= WORLD_RIGHTS
;
2429 pgace
->flags
= DIR_INHERITANCE
;
2433 grants
|= DIR_WRITE
;
2437 pgace
->flags
= FILE_INHERITANCE
;
2439 grants
|= FILE_EXEC
;
2441 grants
|= FILE_WRITE
;
2443 grants
|= FILE_READ
;
2445 pgace
->size
= cpu_to_le16(wsidsz
+ 8);
2446 pgace
->mask
= grants
;
2447 memcpy((char*)&pgace
->sid
, worldsid
, wsidsz
);
2451 /* an ACE for administrators */
2452 /* always full access */
2454 pgace
= (ACCESS_ALLOWED_ACE
*)&secattr
[offs
+ pos
];
2455 pgace
->type
= ACCESS_ALLOWED_ACE_TYPE
;
2457 pgace
->flags
= DIR_INHERITANCE
;
2459 pgace
->flags
= FILE_INHERITANCE
;
2460 pgace
->size
= cpu_to_le16(asidsz
+ 8);
2461 grants
= OWNER_RIGHTS
| FILE_READ
| FILE_WRITE
| FILE_EXEC
;
2462 pgace
->mask
= grants
;
2463 memcpy((char*)&pgace
->sid
, adminsid
, asidsz
);
2467 /* an ACE for system (needed ?) */
2468 /* always full access */
2470 pgace
= (ACCESS_ALLOWED_ACE
*)&secattr
[offs
+ pos
];
2471 pgace
->type
= ACCESS_ALLOWED_ACE_TYPE
;
2473 pgace
->flags
= DIR_INHERITANCE
;
2475 pgace
->flags
= FILE_INHERITANCE
;
2476 pgace
->size
= cpu_to_le16(ssidsz
+ 8);
2477 grants
= OWNER_RIGHTS
| FILE_READ
| FILE_WRITE
| FILE_EXEC
;
2478 pgace
->mask
= grants
;
2479 memcpy((char*)&pgace
->sid
, systemsid
, ssidsz
);
2483 /* a null ACE to hold special flags */
2484 /* using the same representation as cygwin */
2486 if (mode
& (S_ISVTX
| S_ISGID
| S_ISUID
)) {
2487 nsidsz
= ntfs_sid_size(nullsid
);
2488 pgace
= (ACCESS_ALLOWED_ACE
*)&secattr
[offs
+ pos
];
2489 pgace
->type
= ACCESS_ALLOWED_ACE_TYPE
;
2490 pgace
->flags
= NO_PROPAGATE_INHERIT_ACE
;
2491 pgace
->size
= cpu_to_le16(nsidsz
+ 8);
2492 grants
= const_cpu_to_le32(0);
2494 grants
|= FILE_APPEND_DATA
;
2496 grants
|= FILE_WRITE_DATA
;
2498 grants
|= FILE_READ_DATA
;
2499 pgace
->mask
= grants
;
2500 memcpy((char*)&pgace
->sid
, nullsid
, nsidsz
);
2505 /* fix ACL header */
2506 pacl
->size
= cpu_to_le16(pos
);
2507 pacl
->ace_count
= cpu_to_le16(acecnt
);
2514 * Build a full security descriptor from a Posix ACL
2515 * returns descriptor in allocated memory, must free() after use
2518 char *ntfs_build_descr_posix(struct MAPPING
* const mapping
[],
2519 struct POSIX_SECURITY
*pxdesc
,
2520 int isdir
, const SID
*usid
, const SID
*gsid
)
2523 SECURITY_DESCRIPTOR_RELATIVE
*pnhead
;
2533 usidsz
= ntfs_sid_size(usid
);
2534 gsidsz
= ntfs_sid_size(gsid
);
2535 wsidsz
= ntfs_sid_size(worldsid
);
2536 asidsz
= ntfs_sid_size(adminsid
);
2537 ssidsz
= ntfs_sid_size(systemsid
);
2539 /* allocate enough space for the new security attribute */
2540 newattrsz
= sizeof(SECURITY_DESCRIPTOR_RELATIVE
) /* header */
2541 + usidsz
+ gsidsz
/* usid and gsid */
2542 + sizeof(ACL
) /* acl header */
2543 + 2*(8 + usidsz
) /* two possible ACE for user */
2544 + 3*(8 + gsidsz
) /* three possible ACE for group and mask */
2545 + 8 + wsidsz
/* one ACE for world */
2546 + 8 + asidsz
/* one ACE for admin */
2547 + 8 + ssidsz
; /* one ACE for system */
2548 if (isdir
) /* a world denial for directories */
2549 newattrsz
+= 8 + wsidsz
;
2550 if (pxdesc
->mode
& 07000) /* a NULL ACE for special modes */
2551 newattrsz
+= 8 + ntfs_sid_size(nullsid
);
2552 /* account for non-owning users and groups */
2553 for (k
=0; k
<pxdesc
->acccnt
; k
++) {
2554 if ((pxdesc
->acl
.ace
[k
].tag
== POSIX_ACL_USER
)
2555 || (pxdesc
->acl
.ace
[k
].tag
== POSIX_ACL_GROUP
))
2556 newattrsz
+= 3*40; /* fixme : maximum size */
2558 /* account for default ACE's */
2559 newattrsz
+= 2*40*pxdesc
->defcnt
; /* fixme : maximum size */
2560 newattr
= (char*)ntfs_malloc(newattrsz
);
2562 /* build the main header part */
2563 pnhead
= (SECURITY_DESCRIPTOR_RELATIVE
*)newattr
;
2564 pnhead
->revision
= SECURITY_DESCRIPTOR_REVISION
;
2565 pnhead
->alignment
= 0;
2567 * The flag SE_DACL_PROTECTED prevents the ACL
2568 * to be changed in an inheritance after creation
2570 pnhead
->control
= SE_DACL_PRESENT
| SE_DACL_PROTECTED
2573 * Windows prefers ACL first, do the same to
2574 * get the same hash value and avoid duplication
2576 /* build permissions */
2577 aclsz
= buildacls_posix(mapping
,newattr
,
2578 sizeof(SECURITY_DESCRIPTOR_RELATIVE
),
2579 pxdesc
, isdir
, usid
, gsid
);
2580 if (aclsz
&& ((int)(sizeof(SECURITY_DESCRIPTOR_RELATIVE
)
2581 + aclsz
+ usidsz
+ gsidsz
) <= newattrsz
)) {
2582 /* append usid and gsid */
2583 memcpy(&newattr
[sizeof(SECURITY_DESCRIPTOR_RELATIVE
)
2584 + aclsz
], usid
, usidsz
);
2585 memcpy(&newattr
[sizeof(SECURITY_DESCRIPTOR_RELATIVE
)
2586 + aclsz
+ usidsz
], gsid
, gsidsz
);
2587 /* positions of ACL, USID and GSID into header */
2589 cpu_to_le32(sizeof(SECURITY_DESCRIPTOR_RELATIVE
)
2592 cpu_to_le32(sizeof(SECURITY_DESCRIPTOR_RELATIVE
)
2594 pnhead
->sacl
= const_cpu_to_le32(0);
2596 const_cpu_to_le32(sizeof(SECURITY_DESCRIPTOR_RELATIVE
));
2598 /* ACL failure (errno set) or overflow */
2600 newattr
= (char*)NULL
;
2602 /* hope error was detected before overflowing */
2603 ntfs_log_error("Security descriptor is longer than expected\n");
2612 #endif /* POSIXACLS */
2615 * Build a full security descriptor
2616 * returns descriptor in allocated memory, must free() after use
2619 char *ntfs_build_descr(mode_t mode
,
2620 int isdir
, const SID
* usid
, const SID
* gsid
)
2623 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 + 2*(8 + gsidsz
) /* two possible ACE for group */
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 (mode
& 07000) /* a NULL ACE for special modes */
2650 newattrsz
+= 8 + ntfs_sid_size(nullsid
);
2651 newattr
= (char*)ntfs_malloc(newattrsz
);
2653 /* build the main header part */
2654 pnhead
= (SECURITY_DESCRIPTOR_RELATIVE
*) newattr
;
2655 pnhead
->revision
= SECURITY_DESCRIPTOR_REVISION
;
2656 pnhead
->alignment
= 0;
2658 * The flag SE_DACL_PROTECTED prevents the ACL
2659 * to be changed in an inheritance after creation
2661 pnhead
->control
= SE_DACL_PRESENT
| SE_DACL_PROTECTED
2664 * Windows prefers ACL first, do the same to
2665 * get the same hash value and avoid duplication
2667 /* build permissions */
2668 aclsz
= buildacls(newattr
,
2669 sizeof(SECURITY_DESCRIPTOR_RELATIVE
),
2670 mode
, isdir
, usid
, gsid
);
2671 if (((int)sizeof(SECURITY_DESCRIPTOR_RELATIVE
)
2672 + aclsz
+ usidsz
+ gsidsz
) <= newattrsz
) {
2673 /* append usid and gsid */
2674 memcpy(&newattr
[sizeof(SECURITY_DESCRIPTOR_RELATIVE
)
2675 + aclsz
], usid
, usidsz
);
2676 memcpy(&newattr
[sizeof(SECURITY_DESCRIPTOR_RELATIVE
)
2677 + aclsz
+ usidsz
], gsid
, gsidsz
);
2678 /* positions of ACL, USID and GSID into header */
2680 cpu_to_le32(sizeof(SECURITY_DESCRIPTOR_RELATIVE
)
2683 cpu_to_le32(sizeof(SECURITY_DESCRIPTOR_RELATIVE
)
2685 pnhead
->sacl
= const_cpu_to_le32(0);
2687 const_cpu_to_le32(sizeof(SECURITY_DESCRIPTOR_RELATIVE
));
2689 /* hope error was detected before overflowing */
2691 newattr
= (char*)NULL
;
2692 ntfs_log_error("Security descriptor is longer than expected\n");
2701 * Create a mode_t permission set
2702 * from owner, group and world grants as represented in ACEs
2705 static int merge_permissions(BOOL isdir
,
2706 le32 owner
, le32 group
, le32 world
, le32 special
)
2712 /* build owner permission */
2715 /* exec if any of list, traverse */
2716 if (owner
& DIR_GEXEC
)
2718 /* write if any of addfile, adddir, delchild */
2719 if (owner
& DIR_GWRITE
)
2721 /* read if any of list */
2722 if (owner
& DIR_GREAD
)
2725 /* exec if execute or generic execute */
2726 if (owner
& FILE_GEXEC
)
2728 /* write if any of writedata or generic write */
2729 if (owner
& FILE_GWRITE
)
2731 /* read if any of readdata or generic read */
2732 if (owner
& FILE_GREAD
)
2736 /* build group permission */
2739 /* exec if any of list, traverse */
2740 if (group
& DIR_GEXEC
)
2742 /* write if any of addfile, adddir, delchild */
2743 if (group
& DIR_GWRITE
)
2745 /* read if any of list */
2746 if (group
& DIR_GREAD
)
2749 /* exec if execute */
2750 if (group
& FILE_GEXEC
)
2752 /* write if any of writedata, appenddata */
2753 if (group
& FILE_GWRITE
)
2755 /* read if any of readdata */
2756 if (group
& FILE_GREAD
)
2760 /* build world permission */
2763 /* exec if any of list, traverse */
2764 if (world
& DIR_GEXEC
)
2766 /* write if any of addfile, adddir, delchild */
2767 if (world
& DIR_GWRITE
)
2769 /* read if any of list */
2770 if (world
& DIR_GREAD
)
2773 /* exec if execute */
2774 if (world
& FILE_GEXEC
)
2776 /* write if any of writedata, appenddata */
2777 if (world
& FILE_GWRITE
)
2779 /* read if any of readdata */
2780 if (world
& FILE_GREAD
)
2784 /* build special permission flags */
2786 if (special
& FILE_APPEND_DATA
)
2788 if (special
& FILE_WRITE_DATA
)
2790 if (special
& FILE_READ_DATA
)
2799 * Normalize a Posix ACL either from a sorted raw set of
2800 * access ACEs or default ACEs
2801 * (standard case : different owner, group and administrator)
2804 static int norm_std_permissions_posix(struct POSIX_SECURITY
*posix_desc
,
2805 BOOL groupowns
, int start
, int count
, int target
)
2811 struct POSIX_ACE
*pxace
;
2823 * Determine what is granted to some group or world
2824 * Also get denials to world which are meant to prevent
2825 * execution flags to be inherited by plain files
2827 pxace
= posix_desc
->acl
.ace
;
2831 for (j
=start
; j
<(start
+ count
); j
++) {
2832 if (pxace
[j
].perms
& POSIX_PERM_DENIAL
) {
2833 /* deny world exec unless for default */
2834 if ((pxace
[j
].tag
== POSIX_ACL_OTHER
)
2836 denywrld
= pxace
[j
].perms
;
2838 switch (pxace
[j
].tag
) {
2839 case POSIX_ACL_GROUP_OBJ
:
2840 grantgrps
|= pxace
[j
].perms
;
2842 case POSIX_ACL_GROUP
:
2844 grantgrps
|= pxace
[j
].perms
;
2846 case POSIX_ACL_OTHER
:
2847 grantwrld
= pxace
[j
].perms
;
2855 * Collect groups of ACEs related to the same id
2856 * and determine what is granted and what is denied.
2857 * It is important the ACEs have been sorted
2861 while (j
< (start
+ count
)) {
2864 if (pxace
[j
].perms
& POSIX_PERM_DENIAL
) {
2865 deny
= pxace
[j
].perms
| denywrld
;
2869 allow
= pxace
[j
].perms
;
2872 while ((j
< (start
+ count
))
2873 && (pxace
[j
].tag
== tag
)
2874 && (pxace
[j
].id
== id
)) {
2875 if (pxace
[j
].perms
& POSIX_PERM_DENIAL
)
2876 deny
|= pxace
[j
].perms
;
2878 allow
|= pxace
[j
].perms
;
2882 * Build the permissions equivalent to grants and denials
2885 if (tag
== POSIX_ACL_MASK
)
2888 perms
= allow
& ~deny
;
2891 case POSIX_ACL_USER_OBJ
:
2892 perms
= (allow
| grantgrps
| grantwrld
) & ~deny
;
2894 case POSIX_ACL_USER
:
2896 perms
= (allow
| grantgrps
| grantwrld
)
2901 case POSIX_ACL_GROUP_OBJ
:
2902 perms
= (allow
| grantwrld
) & ~deny
;
2904 case POSIX_ACL_GROUP
:
2906 perms
= (allow
| grantwrld
) & ~deny
;
2910 case POSIX_ACL_MASK
:
2914 perms
= allow
& ~deny
;
2918 * Store into a Posix ACE
2920 if (tag
!= POSIX_ACL_SPECIAL
) {
2923 pxace
[k
].perms
= perms
2924 & (POSIX_PERM_R
| POSIX_PERM_W
| POSIX_PERM_X
);
2929 case POSIX_ACL_USER_OBJ
:
2930 mode
|= ((perms
& 7) << 6);
2932 case POSIX_ACL_GROUP_OBJ
:
2933 case POSIX_ACL_MASK
:
2934 mode
= (mode
& 07707) | ((perms
& 7) << 3);
2936 case POSIX_ACL_OTHER
:
2939 case POSIX_ACL_SPECIAL
:
2940 mode
|= (perms
& (S_ISVTX
| S_ISUID
| S_ISGID
));
2946 if (!start
) { /* not satisfactory */
2947 posix_desc
->mode
= mode
;
2948 posix_desc
->tagsset
= tagsset
;
2950 return (k
- target
);
2953 #endif /* POSIXACLS */
2956 * Interpret an ACL and extract meaningful grants
2957 * (standard case : different owner, group and administrator)
2960 static int build_std_permissions(const char *securattr
,
2961 const SID
*usid
, const SID
*gsid
, BOOL isdir
)
2963 const SECURITY_DESCRIPTOR_RELATIVE
*phead
;
2965 const ACCESS_ALLOWED_ACE
*pace
;
2972 le32 allowown
, allowgrp
, allowall
;
2973 le32 denyown
, denygrp
, denyall
;
2975 phead
= (const SECURITY_DESCRIPTOR_RELATIVE
*)securattr
;
2976 offdacl
= le32_to_cpu(phead
->dacl
);
2977 pacl
= (const ACL
*)&securattr
[offdacl
];
2978 special
= const_cpu_to_le32(0);
2979 allowown
= allowgrp
= allowall
= const_cpu_to_le32(0);
2980 denyown
= denygrp
= denyall
= const_cpu_to_le32(0);
2983 acecnt
= le16_to_cpu(pacl
->ace_count
);
2984 offace
= offdacl
+ sizeof(ACL
);
2987 for (nace
= 0; nace
< acecnt
; nace
++) {
2988 pace
= (const ACCESS_ALLOWED_ACE
*)&securattr
[offace
];
2989 if (!(pace
->flags
& INHERIT_ONLY_ACE
)) {
2990 if (ntfs_same_sid(usid
, &pace
->sid
)
2991 || ntfs_same_sid(ownersid
, &pace
->sid
)) {
2993 if (pace
->type
== ACCESS_ALLOWED_ACE_TYPE
)
2994 allowown
|= pace
->mask
;
2995 else if (pace
->type
== ACCESS_DENIED_ACE_TYPE
)
2996 denyown
|= pace
->mask
;
2998 if (ntfs_same_sid(gsid
, &pace
->sid
)
2999 && !(pace
->mask
& WRITE_OWNER
)) {
3000 if (pace
->type
== ACCESS_ALLOWED_ACE_TYPE
)
3001 allowgrp
|= pace
->mask
;
3002 else if (pace
->type
== ACCESS_DENIED_ACE_TYPE
)
3003 denygrp
|= pace
->mask
;
3005 if (is_world_sid((const SID
*)&pace
->sid
)) {
3006 if (pace
->type
== ACCESS_ALLOWED_ACE_TYPE
)
3007 allowall
|= pace
->mask
;
3009 if (pace
->type
== ACCESS_DENIED_ACE_TYPE
)
3010 denyall
|= pace
->mask
;
3012 if ((ntfs_same_sid((const SID
*)&pace
->sid
,nullsid
))
3013 && (pace
->type
== ACCESS_ALLOWED_ACE_TYPE
))
3014 special
|= pace
->mask
;
3016 offace
+= le16_to_cpu(pace
->size
);
3019 * No indication about owner's rights : grant basic rights
3020 * This happens for files created by Windows in directories
3021 * created by Linux and owned by root, because Windows
3022 * merges the admin ACEs
3025 allowown
= (FILE_READ_DATA
| FILE_WRITE_DATA
| FILE_EXECUTE
);
3027 * Add to owner rights granted to group or world
3028 * unless denied personaly, and add to group rights
3029 * granted to world unless denied specifically
3031 allowown
|= (allowgrp
| allowall
);
3032 allowgrp
|= allowall
;
3033 return (merge_permissions(isdir
,
3034 allowown
& ~(denyown
| denyall
),
3035 allowgrp
& ~(denygrp
| denyall
),
3036 allowall
& ~denyall
,
3041 * Interpret an ACL and extract meaningful grants
3042 * (special case : owner and group are the same,
3043 * and not administrator)
3046 static int build_owngrp_permissions(const char *securattr
,
3047 const SID
*usid
, BOOL isdir
)
3049 const SECURITY_DESCRIPTOR_RELATIVE
*phead
;
3051 const ACCESS_ALLOWED_ACE
*pace
;
3058 le32 allowown
, allowgrp
, allowall
;
3059 le32 denyown
, denygrp
, denyall
;
3061 phead
= (const SECURITY_DESCRIPTOR_RELATIVE
*)securattr
;
3062 offdacl
= le32_to_cpu(phead
->dacl
);
3063 pacl
= (const ACL
*)&securattr
[offdacl
];
3064 special
= const_cpu_to_le32(0);
3065 allowown
= allowgrp
= allowall
= const_cpu_to_le32(0);
3066 denyown
= denygrp
= denyall
= const_cpu_to_le32(0);
3069 acecnt
= le16_to_cpu(pacl
->ace_count
);
3070 offace
= offdacl
+ sizeof(ACL
);
3073 for (nace
= 0; nace
< acecnt
; nace
++) {
3074 pace
= (const ACCESS_ALLOWED_ACE
*)&securattr
[offace
];
3075 if (!(pace
->flags
& INHERIT_ONLY_ACE
)) {
3076 if ((ntfs_same_sid(usid
, &pace
->sid
)
3077 || ntfs_same_sid(ownersid
, &pace
->sid
))
3078 && (pace
->mask
& WRITE_OWNER
)) {
3079 if (pace
->type
== ACCESS_ALLOWED_ACE_TYPE
)
3080 allowown
|= pace
->mask
;
3082 if (ntfs_same_sid(usid
, &pace
->sid
)
3083 && (!(pace
->mask
& WRITE_OWNER
))) {
3084 if (pace
->type
== ACCESS_ALLOWED_ACE_TYPE
) {
3085 allowgrp
|= pace
->mask
;
3089 if (is_world_sid((const SID
*)&pace
->sid
)) {
3090 if (pace
->type
== ACCESS_ALLOWED_ACE_TYPE
)
3091 allowall
|= pace
->mask
;
3093 if (pace
->type
== ACCESS_DENIED_ACE_TYPE
)
3094 denyall
|= pace
->mask
;
3096 if ((ntfs_same_sid((const SID
*)&pace
->sid
,nullsid
))
3097 && (pace
->type
== ACCESS_ALLOWED_ACE_TYPE
))
3098 special
|= pace
->mask
;
3100 offace
+= le16_to_cpu(pace
->size
);
3103 allowgrp
= allowall
;
3104 return (merge_permissions(isdir
,
3105 allowown
& ~(denyown
| denyall
),
3106 allowgrp
& ~(denygrp
| denyall
),
3107 allowall
& ~denyall
,
3114 * Normalize a Posix ACL either from a sorted raw set of
3115 * access ACEs or default ACEs
3116 * (special case : owner or/and group is administrator)
3119 static int norm_ownadmin_permissions_posix(struct POSIX_SECURITY
*posix_desc
,
3120 int start
, int count
, int target
)
3126 struct POSIX_ACE
*pxace
;
3135 pxace
= posix_desc
->acl
.ace
;
3136 acccnt
= posix_desc
->acccnt
;
3140 * Get denials to world which are meant to prevent
3141 * execution flags to be inherited by plain files
3143 for (j
=start
; j
<(start
+ count
); j
++) {
3144 if (pxace
[j
].perms
& POSIX_PERM_DENIAL
) {
3145 /* deny world exec not for default */
3146 if ((pxace
[j
].tag
== POSIX_ACL_OTHER
)
3148 denywrld
= pxace
[j
].perms
;
3152 * Collect groups of ACEs related to the same id
3153 * and determine what is granted (denials are ignored)
3154 * It is important the ACEs have been sorted
3159 while (j
< (start
+ count
)) {
3163 if (tag
== POSIX_ACL_MASK
) {
3164 deny
= pxace
[j
].perms
;
3166 while ((j
< (start
+ count
))
3167 && (pxace
[j
].tag
== POSIX_ACL_MASK
))
3170 if (!(pxace
[j
].perms
& POSIX_PERM_DENIAL
))
3171 allow
= pxace
[j
].perms
;
3173 while ((j
< (start
+ count
))
3174 && (pxace
[j
].tag
== tag
)
3175 && (pxace
[j
].id
== id
)) {
3176 if (!(pxace
[j
].perms
& POSIX_PERM_DENIAL
))
3177 allow
|= pxace
[j
].perms
;
3183 * Store the grants into a Posix ACE
3185 if (tag
== POSIX_ACL_MASK
)
3188 perms
= allow
& ~denywrld
;
3189 if (tag
!= POSIX_ACL_SPECIAL
) {
3192 pxace
[k
].perms
= perms
3193 & (POSIX_PERM_R
| POSIX_PERM_W
| POSIX_PERM_X
);
3198 case POSIX_ACL_USER_OBJ
:
3199 mode
|= ((perms
& 7) << 6);
3201 case POSIX_ACL_GROUP_OBJ
:
3202 case POSIX_ACL_MASK
:
3203 mode
= (mode
& 07707) | ((perms
& 7) << 3);
3205 case POSIX_ACL_OTHER
:
3208 case POSIX_ACL_SPECIAL
:
3209 mode
|= perms
& (S_ISVTX
| S_ISUID
| S_ISGID
);
3215 if (!start
) { /* not satisfactory */
3216 posix_desc
->mode
= mode
;
3217 posix_desc
->tagsset
= tagsset
;
3219 return (k
- target
);
3222 #endif /* POSIXACLS */
3225 * Interpret an ACL and extract meaningful grants
3226 * (special case : owner or/and group is administrator)
3230 static int build_ownadmin_permissions(const char *securattr
,
3231 const SID
*usid
, const SID
*gsid
, BOOL isdir
)
3233 const SECURITY_DESCRIPTOR_RELATIVE
*phead
;
3235 const ACCESS_ALLOWED_ACE
*pace
;
3243 le32 allowown
, allowgrp
, allowall
;
3244 le32 denyown
, denygrp
, denyall
;
3246 phead
= (const SECURITY_DESCRIPTOR_RELATIVE
*)securattr
;
3247 offdacl
= le32_to_cpu(phead
->dacl
);
3248 pacl
= (const ACL
*)&securattr
[offdacl
];
3249 special
= const_cpu_to_le32(0);
3250 allowown
= allowgrp
= allowall
= const_cpu_to_le32(0);
3251 denyown
= denygrp
= denyall
= const_cpu_to_le32(0);
3253 acecnt
= le16_to_cpu(pacl
->ace_count
);
3254 offace
= offdacl
+ sizeof(ACL
);
3259 for (nace
= 0; nace
< acecnt
; nace
++) {
3260 pace
= (const ACCESS_ALLOWED_ACE
*)&securattr
[offace
];
3261 if (!(pace
->flags
& INHERIT_ONLY_ACE
)
3262 && !(~pace
->mask
& (ROOT_OWNER_UNMARK
| ROOT_GROUP_UNMARK
))) {
3263 if ((ntfs_same_sid(usid
, &pace
->sid
)
3264 || ntfs_same_sid(ownersid
, &pace
->sid
))
3265 && (((pace
->mask
& WRITE_OWNER
) && firstapply
))) {
3266 if (pace
->type
== ACCESS_ALLOWED_ACE_TYPE
) {
3267 allowown
|= pace
->mask
;
3270 if (pace
->type
== ACCESS_DENIED_ACE_TYPE
)
3271 denyown
|= pace
->mask
;
3273 if (ntfs_same_sid(gsid
, &pace
->sid
)
3274 && (!(pace
->mask
& WRITE_OWNER
))) {
3275 if (pace
->type
== ACCESS_ALLOWED_ACE_TYPE
) {
3276 allowgrp
|= pace
->mask
;
3279 if (pace
->type
== ACCESS_DENIED_ACE_TYPE
)
3280 denygrp
|= pace
->mask
;
3281 } else if (is_world_sid((const SID
*)&pace
->sid
)) {
3282 if (pace
->type
== ACCESS_ALLOWED_ACE_TYPE
)
3283 allowall
|= pace
->mask
;
3285 if (pace
->type
== ACCESS_DENIED_ACE_TYPE
)
3286 denyall
|= pace
->mask
;
3290 if (!(pace
->flags
& INHERIT_ONLY_ACE
))
3291 if ((ntfs_same_sid((const SID
*)&pace
->sid
,nullsid
))
3292 && (pace
->type
== ACCESS_ALLOWED_ACE_TYPE
))
3293 special
|= pace
->mask
;
3294 offace
+= le16_to_cpu(pace
->size
);
3297 allowown
|= (allowgrp
| allowall
);
3298 allowgrp
|= allowall
;
3300 return (merge_permissions(isdir
,
3301 allowown
& ~(denyown
| denyall
),
3302 allowgrp
& ~(denygrp
| denyall
),
3303 allowall
& ~denyall
,
3310 * Define the owner of a file as the first user allowed
3311 * to change the owner, instead of the user defined as owner.
3313 * This produces better approximations for files written by a
3314 * Windows user in an inheritable directory owned by another user,
3315 * as the access rights are inheritable but the ownership is not.
3317 * An important case is the directories "Documents and Settings/user"
3318 * which the users must have access to, though Windows considers them
3319 * as owned by administrator.
3322 const SID
*ntfs_acl_owner(const char *securattr
)
3324 const SECURITY_DESCRIPTOR_RELATIVE
*phead
;
3327 const ACCESS_ALLOWED_ACE
*pace
;
3335 phead
= (const SECURITY_DESCRIPTOR_RELATIVE
*)securattr
;
3336 offdacl
= le32_to_cpu(phead
->dacl
);
3338 pacl
= (const ACL
*)&securattr
[offdacl
];
3339 acecnt
= le16_to_cpu(pacl
->ace_count
);
3340 offace
= offdacl
+ sizeof(ACL
);
3343 pace
= (const ACCESS_ALLOWED_ACE
*)&securattr
[offace
];
3344 if ((pace
->mask
& WRITE_OWNER
)
3345 && (pace
->type
== ACCESS_ALLOWED_ACE_TYPE
)
3346 && ntfs_is_user_sid(&pace
->sid
))
3348 offace
+= le16_to_cpu(pace
->size
);
3349 } while (!found
&& (++nace
< acecnt
));
3354 usid
= (const SID
*)&securattr
[le32_to_cpu(phead
->owner
)];
3361 * Special case for files owned by administrator with full
3362 * access granted to a mapped user : consider this user as the tenant
3365 * This situation cannot be represented with Linux concepts and can
3366 * only be found for files or directories created by Windows.
3367 * Typical situation : directory "Documents and Settings/user" which
3368 * is on the path to user's files and must be given access to user
3371 * Check file is owned by administrator and no user has rights before
3373 * Returns the uid of tenant or zero if none
3377 static uid_t
find_tenant(struct MAPPING
*const mapping
[],
3378 const char *securattr
)
3380 const SECURITY_DESCRIPTOR_RELATIVE
*phead
;
3382 const ACCESS_ALLOWED_ACE
*pace
;
3390 phead
= (const SECURITY_DESCRIPTOR_RELATIVE
*)securattr
;
3391 offdacl
= le32_to_cpu(phead
->dacl
);
3392 pacl
= (const ACL
*)&securattr
[offdacl
];
3395 acecnt
= le16_to_cpu(pacl
->ace_count
);
3396 offace
= offdacl
+ sizeof(ACL
);
3399 for (nace
= 0; nace
< acecnt
; nace
++) {
3400 pace
= (const ACCESS_ALLOWED_ACE
*)&securattr
[offace
];
3401 if ((pace
->type
== ACCESS_ALLOWED_ACE_TYPE
)
3402 && (pace
->mask
& DIR_WRITE
)) {
3403 xid
= NTFS_FIND_USER(mapping
[MAPUSERS
], &pace
->sid
);
3406 offace
+= le16_to_cpu(pace
->size
);
3411 #endif /* OWNERFROMACL */
3416 * Build Posix permissions from an ACL
3417 * returns a pointer to the requested permissions
3418 * or a null pointer (with errno set) if there is a problem
3420 * If the NTFS ACL was created according to our rules, the retrieved
3421 * Posix ACL should be the exact ACL which was set. However if
3422 * the NTFS ACL was built by a different tool, the result could
3423 * be a a poor approximation of what was expected
3426 struct POSIX_SECURITY
*ntfs_build_permissions_posix(
3427 struct MAPPING
*const mapping
[],
3428 const char *securattr
,
3429 const SID
*usid
, const SID
*gsid
, BOOL isdir
)
3431 const SECURITY_DESCRIPTOR_RELATIVE
*phead
;
3432 struct POSIX_SECURITY
*pxdesc
;
3434 const ACCESS_ALLOWED_ACE
*pace
;
3435 struct POSIX_ACE
*pxace
;
3460 phead
= (const SECURITY_DESCRIPTOR_RELATIVE
*)securattr
;
3461 offdacl
= le32_to_cpu(phead
->dacl
);
3463 pacl
= (const ACL
*)&securattr
[offdacl
];
3464 acecnt
= le16_to_cpu(pacl
->ace_count
);
3465 offace
= offdacl
+ sizeof(ACL
);
3471 groupowns
= ntfs_same_sid(gsid
,usid
);
3475 * Build a raw posix security descriptor
3476 * by just translating permissions and ids
3477 * Add 2 to the count of ACE to be able to insert
3478 * a group ACE later in access and default ACLs
3479 * and add 2 more to be able to insert ACEs for owner
3480 * and 2 more for other
3482 alloccnt
= acecnt
+ 6;
3483 pxdesc
= (struct POSIX_SECURITY
*)malloc(
3484 sizeof(struct POSIX_SECURITY
)
3485 + alloccnt
*sizeof(struct POSIX_ACE
));
3488 for (i
=0; i
<2; i
++) {
3490 pctx
->permswrld
= 0;
3493 pctx
->groupmasks
= 0;
3495 pctx
->gotowner
= FALSE
;
3496 pctx
->gotgroup
= FALSE
;
3497 pctx
->gotownermask
= FALSE
;
3499 for (j
=0; j
<acecnt
; j
++) {
3500 pace
= (const ACCESS_ALLOWED_ACE
*)&securattr
[offace
];
3501 if (pace
->flags
& INHERIT_ONLY_ACE
) {
3502 pxace
= &pxdesc
->acl
.ace
[l
- 1];
3505 pxace
= &pxdesc
->acl
.ace
[k
];
3510 * grants for root as a designated user or group
3512 if ((~pace
->mask
& (ROOT_OWNER_UNMARK
| ROOT_GROUP_UNMARK
))
3513 && (pace
->type
== ACCESS_ALLOWED_ACE_TYPE
)
3514 && ntfs_same_sid(&pace
->sid
, adminsid
)) {
3515 pxace
->tag
= (pace
->mask
& ROOT_OWNER_UNMARK
? POSIX_ACL_GROUP
: POSIX_ACL_USER
);
3517 if ((pace
->mask
& (GENERIC_ALL
| WRITE_OWNER
))
3518 && (pace
->flags
& INHERIT_ONLY_ACE
))
3519 ignore
= genericinh
= TRUE
;
3521 if (ntfs_same_sid(usid
, &pace
->sid
)) {
3524 * Owner has no write-owner right :
3525 * a group was defined same as owner
3526 * or admin was owner or group :
3527 * denials are meant to owner
3528 * and grants are meant to group
3530 if (!(pace
->mask
& (WRITE_OWNER
| GENERIC_ALL
))
3531 && (pace
->type
== ACCESS_ALLOWED_ACE_TYPE
)) {
3532 if (ntfs_same_sid(gsid
,usid
)) {
3533 pxace
->tag
= POSIX_ACL_GROUP_OBJ
;
3536 if (ntfs_same_sid(&pace
->sid
,usid
))
3538 gid
= NTFS_FIND_GROUP(mapping
[MAPGROUPS
],&pace
->sid
);
3540 pxace
->tag
= POSIX_ACL_GROUP
;
3542 pctx
->prevgid
= gid
;
3544 uid
= NTFS_FIND_USER(mapping
[MAPUSERS
],&pace
->sid
);
3546 pxace
->tag
= POSIX_ACL_USER
;
3554 * when group owns, late denials for owner
3557 if ((pace
->type
== ACCESS_DENIED_ACE_TYPE
)
3558 && (pace
->mask
& WRITE_OWNER
)) {
3559 pxace
->tag
= POSIX_ACL_MASK
;
3560 pctx
->gotownermask
= TRUE
;
3564 if (pace
->type
== ACCESS_ALLOWED_ACE_TYPE
)
3565 pctx
->gotowner
= TRUE
;
3566 if (pctx
->gotownermask
&& !pctx
->gotowner
) {
3567 uid
= NTFS_FIND_USER(mapping
[MAPUSERS
],&pace
->sid
);
3569 pxace
->tag
= POSIX_ACL_USER
;
3571 pxace
->tag
= POSIX_ACL_USER_OBJ
;
3572 /* system ignored, and admin */
3573 /* ignored at first position */
3574 if (pace
->flags
& INHERIT_ONLY_ACE
) {
3575 if ((firstinh
&& ntfs_same_sid(&pace
->sid
,adminsid
))
3576 || ntfs_same_sid(&pace
->sid
,systemsid
))
3582 if ((adminowns
&& ntfs_same_sid(&pace
->sid
,adminsid
))
3583 || ntfs_same_sid(&pace
->sid
,systemsid
))
3585 if (ntfs_same_sid(usid
,adminsid
))
3590 } else if (ntfs_same_sid(gsid
, &pace
->sid
)) {
3591 if ((pace
->type
== ACCESS_DENIED_ACE_TYPE
)
3592 && (pace
->mask
& WRITE_OWNER
)) {
3593 pxace
->tag
= POSIX_ACL_MASK
;
3598 if (pctx
->gotgroup
|| (pctx
->groupmasks
> 1)) {
3599 gid
= NTFS_FIND_GROUP(mapping
[MAPGROUPS
],&pace
->sid
);
3602 pxace
->tag
= POSIX_ACL_GROUP
;
3603 pctx
->prevgid
= gid
;
3608 pxace
->tag
= POSIX_ACL_GROUP_OBJ
;
3609 if (pace
->type
== ACCESS_ALLOWED_ACE_TYPE
)
3610 pctx
->gotgroup
= TRUE
;
3613 if (ntfs_same_sid(gsid
,adminsid
)
3614 || ntfs_same_sid(gsid
,systemsid
)) {
3615 if (pace
->mask
& (WRITE_OWNER
| GENERIC_ALL
))
3617 if (ntfs_same_sid(gsid
,adminsid
))
3620 genericinh
= ignore
;
3623 } else if (is_world_sid((const SID
*)&pace
->sid
)) {
3625 pxace
->tag
= POSIX_ACL_OTHER
;
3626 if ((pace
->type
== ACCESS_DENIED_ACE_TYPE
)
3627 && (pace
->flags
& INHERIT_ONLY_ACE
))
3629 } else if (ntfs_same_sid((const SID
*)&pace
->sid
,nullsid
)) {
3631 pxace
->tag
= POSIX_ACL_SPECIAL
;
3633 uid
= NTFS_FIND_USER(mapping
[MAPUSERS
],&pace
->sid
);
3635 if ((pace
->type
== ACCESS_DENIED_ACE_TYPE
)
3636 && (pace
->mask
& WRITE_OWNER
)
3637 && (pctx
->prevuid
!= uid
)) {
3639 pxace
->tag
= POSIX_ACL_MASK
;
3642 pxace
->tag
= POSIX_ACL_USER
;
3644 pctx
->prevuid
= uid
;
3646 gid
= NTFS_FIND_GROUP(mapping
[MAPGROUPS
],&pace
->sid
);
3648 if ((pace
->type
== ACCESS_DENIED_ACE_TYPE
)
3649 && (pace
->mask
& WRITE_OWNER
)
3650 && (pctx
->prevgid
!= gid
)) {
3651 pxace
->tag
= POSIX_ACL_MASK
;
3654 pxace
->tag
= POSIX_ACL_GROUP
;
3657 pctx
->prevgid
= gid
;
3660 * do not grant rights to unknown
3661 * people and do not define root as a
3662 * designated user or group
3670 /* specific decoding for vtx/uid/gid */
3671 if (pxace
->tag
== POSIX_ACL_SPECIAL
) {
3672 if (pace
->mask
& FILE_APPEND_DATA
)
3673 pxace
->perms
|= S_ISUID
;
3674 if (pace
->mask
& FILE_WRITE_DATA
)
3675 pxace
->perms
|= S_ISGID
;
3676 if (pace
->mask
& FILE_READ_DATA
)
3677 pxace
->perms
|= S_ISVTX
;
3680 if (pace
->mask
& DIR_GEXEC
)
3681 pxace
->perms
|= POSIX_PERM_X
;
3682 if (pace
->mask
& DIR_GWRITE
)
3683 pxace
->perms
|= POSIX_PERM_W
;
3684 if (pace
->mask
& DIR_GREAD
)
3685 pxace
->perms
|= POSIX_PERM_R
;
3686 if ((pace
->mask
& GENERIC_ALL
)
3687 && (pace
->flags
& INHERIT_ONLY_ACE
))
3688 pxace
->perms
|= POSIX_PERM_X
3692 if (pace
->mask
& FILE_GEXEC
)
3693 pxace
->perms
|= POSIX_PERM_X
;
3694 if (pace
->mask
& FILE_GWRITE
)
3695 pxace
->perms
|= POSIX_PERM_W
;
3696 if (pace
->mask
& FILE_GREAD
)
3697 pxace
->perms
|= POSIX_PERM_R
;
3700 if (pace
->type
!= ACCESS_ALLOWED_ACE_TYPE
)
3701 pxace
->perms
|= POSIX_PERM_DENIAL
;
3703 if (pxace
->tag
== POSIX_ACL_OTHER
)
3704 pctx
->permswrld
= pxace
->perms
;
3705 pctx
->tagsset
|= pxace
->tag
;
3706 if (pace
->flags
& INHERIT_ONLY_ACE
) {
3712 offace
+= le16_to_cpu(pace
->size
);
3715 * Create world perms if none (both lists)
3718 if ((genericinh
|| !i
)
3719 && !(ctx
[i
].tagsset
& POSIX_ACL_OTHER
)) {
3721 pxace
= &pxdesc
->acl
.ace
[--l
];
3723 pxace
= &pxdesc
->acl
.ace
[k
++];
3724 pxace
->tag
= POSIX_ACL_OTHER
;
3727 ctx
[i
].tagsset
|= POSIX_ACL_OTHER
;
3728 ctx
[i
].permswrld
= 0;
3731 * Set basic owner perms if none (both lists)
3732 * This happens for files created by Windows in directories
3733 * created by Linux and owned by root, because Windows
3734 * merges the admin ACEs
3737 if (!(ctx
[i
].tagsset
& POSIX_ACL_USER_OBJ
)
3738 && (ctx
[i
].tagsset
& POSIX_ACL_OTHER
)) {
3740 pxace
= &pxdesc
->acl
.ace
[--l
];
3742 pxace
= &pxdesc
->acl
.ace
[k
++];
3743 pxace
->tag
= POSIX_ACL_USER_OBJ
;
3745 pxace
->perms
= POSIX_PERM_R
| POSIX_PERM_W
| POSIX_PERM_X
;
3746 ctx
[i
].tagsset
|= POSIX_ACL_USER_OBJ
;
3749 * Duplicate world perms as group_obj perms if none
3752 if ((ctx
[i
].tagsset
& POSIX_ACL_OTHER
)
3753 && !(ctx
[i
].tagsset
& POSIX_ACL_GROUP_OBJ
)) {
3755 pxace
= &pxdesc
->acl
.ace
[--l
];
3757 pxace
= &pxdesc
->acl
.ace
[k
++];
3758 pxace
->tag
= POSIX_ACL_GROUP_OBJ
;
3760 pxace
->perms
= ctx
[i
].permswrld
;
3761 ctx
[i
].tagsset
|= POSIX_ACL_GROUP_OBJ
;
3764 * Also duplicate world perms as group perms if they
3765 * were converted to mask and not followed by a group entry
3767 if (ctx
[0].groupmasks
) {
3768 for (j
=k
-2; j
>=0; j
--) {
3769 if ((pxdesc
->acl
.ace
[j
].tag
== POSIX_ACL_MASK
)
3770 && (pxdesc
->acl
.ace
[j
].id
!= -1)
3771 && ((pxdesc
->acl
.ace
[j
+1].tag
!= POSIX_ACL_GROUP
)
3772 || (pxdesc
->acl
.ace
[j
+1].id
3773 != pxdesc
->acl
.ace
[j
].id
))) {
3774 pxace
= &pxdesc
->acl
.ace
[k
];
3775 pxace
->tag
= POSIX_ACL_GROUP
;
3776 pxace
->id
= pxdesc
->acl
.ace
[j
].id
;
3777 pxace
->perms
= ctx
[0].permswrld
;
3778 ctx
[0].tagsset
|= POSIX_ACL_GROUP
;
3781 if (pxdesc
->acl
.ace
[j
].tag
== POSIX_ACL_MASK
)
3782 pxdesc
->acl
.ace
[j
].id
= -1;
3785 if (ctx
[1].groupmasks
) {
3786 for (j
=l
; j
<(alloccnt
-1); j
++) {
3787 if ((pxdesc
->acl
.ace
[j
].tag
== POSIX_ACL_MASK
)
3788 && (pxdesc
->acl
.ace
[j
].id
!= -1)
3789 && ((pxdesc
->acl
.ace
[j
+1].tag
!= POSIX_ACL_GROUP
)
3790 || (pxdesc
->acl
.ace
[j
+1].id
3791 != pxdesc
->acl
.ace
[j
].id
))) {
3792 pxace
= &pxdesc
->acl
.ace
[l
- 1];
3793 pxace
->tag
= POSIX_ACL_GROUP
;
3794 pxace
->id
= pxdesc
->acl
.ace
[j
].id
;
3795 pxace
->perms
= ctx
[1].permswrld
;
3796 ctx
[1].tagsset
|= POSIX_ACL_GROUP
;
3799 if (pxdesc
->acl
.ace
[j
].tag
== POSIX_ACL_MASK
)
3800 pxdesc
->acl
.ace
[j
].id
= -1;
3805 * Insert default mask if none present and
3806 * there are designated users or groups
3807 * (the space for it has not beed used)
3810 if ((ctx
[i
].tagsset
& (POSIX_ACL_USER
| POSIX_ACL_GROUP
))
3811 && !(ctx
[i
].tagsset
& POSIX_ACL_MASK
)) {
3813 pxace
= &pxdesc
->acl
.ace
[--l
];
3815 pxace
= &pxdesc
->acl
.ace
[k
++];
3816 pxace
->tag
= POSIX_ACL_MASK
;
3818 pxace
->perms
= POSIX_PERM_DENIAL
;
3819 ctx
[i
].tagsset
|= POSIX_ACL_MASK
;
3823 ntfs_log_error("Posix descriptor is longer than expected\n");
3826 pxdesc
= (struct POSIX_SECURITY
*)NULL
;
3829 pxdesc
->defcnt
= alloccnt
- l
;
3830 pxdesc
->firstdef
= l
;
3831 pxdesc
->tagsset
= ctx
[0].tagsset
;
3832 pxdesc
->acl
.version
= POSIX_VERSION
;
3833 pxdesc
->acl
.flags
= 0;
3834 pxdesc
->acl
.filler
= 0;
3835 ntfs_sort_posix(pxdesc
);
3837 k
= norm_ownadmin_permissions_posix(pxdesc
,
3838 0, pxdesc
->acccnt
, 0);
3840 l
= norm_ownadmin_permissions_posix(pxdesc
,
3841 pxdesc
->firstdef
, pxdesc
->defcnt
, k
);
3842 pxdesc
->firstdef
= k
;
3845 k
= norm_std_permissions_posix(pxdesc
,groupowns
,
3846 0, pxdesc
->acccnt
, 0);
3848 l
= norm_std_permissions_posix(pxdesc
,groupowns
,
3849 pxdesc
->firstdef
, pxdesc
->defcnt
, k
);
3850 pxdesc
->firstdef
= k
;
3854 if (pxdesc
&& !ntfs_valid_posix(pxdesc
)) {
3855 ntfs_log_error("Invalid Posix descriptor built\n");
3858 pxdesc
= (struct POSIX_SECURITY
*)NULL
;
3863 #endif /* POSIXACLS */
3866 * Build unix-style (mode_t) permissions from an ACL
3867 * returns the requested permissions
3868 * or a negative result (with errno set) if there is a problem
3871 int ntfs_build_permissions(const char *securattr
,
3872 const SID
*usid
, const SID
*gsid
, BOOL isdir
)
3874 const SECURITY_DESCRIPTOR_RELATIVE
*phead
;
3879 phead
= (const SECURITY_DESCRIPTOR_RELATIVE
*)securattr
;
3880 adminowns
= ntfs_same_sid(usid
,adminsid
)
3881 || ntfs_same_sid(gsid
,adminsid
);
3882 groupowns
= !adminowns
&& ntfs_same_sid(gsid
,usid
);
3884 perm
= build_ownadmin_permissions(securattr
, usid
, gsid
, isdir
);
3887 perm
= build_owngrp_permissions(securattr
, usid
, isdir
);
3889 perm
= build_std_permissions(securattr
, usid
, gsid
, isdir
);
3894 * The following must be in some library...
3897 static unsigned long atoul(const char *p
)
3898 { /* must be somewhere ! */
3902 while ((*p
>= '0') && (*p
<= '9'))
3903 v
= v
* 10 + (*p
++) - '0';
3908 * Build an internal representation of a SID
3909 * Returns a copy in allocated memory if it succeeds
3910 * The SID is checked to be a valid user one.
3913 static SID
*encodesid(const char *sidstr
)
3923 if (!strncmp(sidstr
, "S-1-", 4)) {
3924 bsid
= (SID
*)&bigsid
;
3925 bsid
->revision
= SID_REVISION
;
3928 bsid
->identifier_authority
.high_part
= const_cpu_to_be16(0);
3929 bsid
->identifier_authority
.low_part
= cpu_to_be32(auth
);
3932 while (p
&& (cnt
< 8)) {
3935 bsid
->sub_authority
[cnt
] = cpu_to_le32(auth
);
3939 bsid
->sub_authority_count
= cnt
;
3940 if ((cnt
> 0) && ntfs_valid_sid(bsid
) && ntfs_is_user_sid(bsid
)) {
3941 sid
= (SID
*) ntfs_malloc(4 * cnt
+ 8);
3943 memcpy(sid
, bsid
, 4 * cnt
+ 8);
3950 * Early logging before the logs are redirected
3952 * (not quite satisfactory : this appears before the ntfs-g banner,
3953 * and with a different pid)
3956 static void log_early_error(const char *format
, ...)
3957 __attribute__((format(printf
, 1, 2)));
3959 static void log_early_error(const char *format
, ...)
3963 va_start(args
, format
);
3964 #ifdef HAVE_SYSLOG_H
3965 openlog("ntfs-3g", LOG_PID
, LOG_USER
);
3966 ntfs_log_handler_syslog(NULL
, NULL
, 0,
3967 NTFS_LOG_LEVEL_ERROR
, NULL
,
3970 vfprintf(stderr
,format
,args
);
3977 * Get a single mapping item from buffer
3979 * Always reads a full line, truncating long lines
3980 * Refills buffer when exhausted
3981 * Returns pointer to item, or NULL when there is no more
3984 static struct MAPLIST
*getmappingitem(FILEREADER reader
, void *fileid
,
3985 off_t
*poffs
, char *buf
, int *psrc
, s64
*psize
)
3994 struct MAPLIST
*item
;
3998 /* allocate and get a full line */
3999 item
= (struct MAPLIST
*)ntfs_malloc(sizeof(struct MAPLIST
));
4003 while ((src
< *psize
)
4004 && (buf
[src
] != '\n')) {
4006 item
->maptext
[dst
++] = buf
[src
];
4009 if (src
>= *psize
) {
4011 *psize
= reader(fileid
, buf
, (size_t)BUFSZ
, *poffs
);
4016 item
->maptext
[dst
] = '\0';
4019 } while (*psize
&& ((item
->maptext
[0] == '#') || !gotend
));
4021 pu
= pg
= (char*)NULL
;
4022 /* decompose into uid, gid and sid */
4024 item
->uidstr
= item
->maptext
;
4025 item
->gidstr
= strchr(item
->uidstr
, ':');
4027 pu
= item
->gidstr
++;
4028 item
->sidstr
= strchr(item
->gidstr
, ':');
4030 pg
= item
->sidstr
++;
4031 q
= strchr(item
->sidstr
, ':');
4038 log_early_error("Bad mapping item \"%s\"\n",
4041 item
= (struct MAPLIST
*)NULL
;
4044 free(item
); /* free unused item */
4045 item
= (struct MAPLIST
*)NULL
;
4053 * Read user mapping file and split into their attribute.
4054 * Parameters are kept as text in a chained list until logins
4055 * are converted to uid.
4056 * Returns the head of list, if any
4058 * If an absolute path is provided, the mapping file is assumed
4059 * to be located in another mounted file system, and plain read()
4060 * are used to get its contents.
4061 * If a relative path is provided, the mapping file is assumed
4062 * to be located on the current file system, and internal IO
4063 * have to be used since we are still mounting and we have not
4064 * entered the fuse loop yet.
4067 struct MAPLIST
*ntfs_read_mapping(FILEREADER reader
, void *fileid
)
4070 struct MAPLIST
*item
;
4071 struct MAPLIST
*firstitem
;
4072 struct MAPLIST
*lastitem
;
4077 firstitem
= (struct MAPLIST
*)NULL
;
4078 lastitem
= (struct MAPLIST
*)NULL
;
4080 size
= reader(fileid
, buf
, (size_t)BUFSZ
, (off_t
)0);
4084 item
= getmappingitem(reader
, fileid
, &offs
,
4087 item
->next
= (struct MAPLIST
*)NULL
;
4089 lastitem
->next
= item
;
4100 * Free memory used to store the user mapping
4101 * The only purpose is to facilitate the detection of memory leaks
4104 void ntfs_free_mapping(struct MAPPING
*mapping
[])
4106 struct MAPPING
*user
;
4107 struct MAPPING
*group
;
4109 /* free user mappings */
4110 while (mapping
[MAPUSERS
]) {
4111 user
= mapping
[MAPUSERS
];
4112 /* do not free SIDs used for group mappings */
4113 group
= mapping
[MAPGROUPS
];
4114 while (group
&& (group
->sid
!= user
->sid
))
4115 group
= group
->next
;
4118 /* free group list if any */
4121 /* unchain item and free */
4122 mapping
[MAPUSERS
] = user
->next
;
4125 /* free group mappings */
4126 while (mapping
[MAPGROUPS
]) {
4127 group
= mapping
[MAPGROUPS
];
4129 /* unchain item and free */
4130 mapping
[MAPGROUPS
] = group
->next
;
4137 * Build the user mapping list
4138 * user identification may be given in symbolic or numeric format
4140 * ! Note ! : does getpwnam() read /etc/passwd or some other file ?
4141 * if so there is a possible recursion into fuse if this
4142 * file is on NTFS, and fuse is not recursion safe.
4145 struct MAPPING
*ntfs_do_user_mapping(struct MAPLIST
*firstitem
)
4147 struct MAPLIST
*item
;
4148 struct MAPPING
*firstmapping
;
4149 struct MAPPING
*lastmapping
;
4150 struct MAPPING
*mapping
;
4155 firstmapping
= (struct MAPPING
*)NULL
;
4156 lastmapping
= (struct MAPPING
*)NULL
;
4157 for (item
= firstitem
; item
; item
= item
->next
) {
4158 if ((item
->uidstr
[0] >= '0') && (item
->uidstr
[0] <= '9'))
4159 uid
= atoi(item
->uidstr
);
4162 if (item
->uidstr
[0]) {
4163 pwd
= getpwnam(item
->uidstr
);
4167 log_early_error("Invalid user \"%s\"\n",
4172 * Records with no uid and no gid are inserted
4173 * to define the implicit mapping pattern
4176 || (!item
->uidstr
[0] && !item
->gidstr
[0])) {
4177 sid
= encodesid(item
->sidstr
);
4178 if (sid
&& !item
->uidstr
[0] && !item
->gidstr
[0]
4179 && !ntfs_valid_pattern(sid
)) {
4180 ntfs_log_error("Bad implicit SID pattern %s\n",
4187 ntfs_malloc(sizeof(struct MAPPING
));
4192 mapping
->next
= (struct MAPPING
*)NULL
;
4194 lastmapping
->next
= mapping
;
4196 firstmapping
= mapping
;
4197 lastmapping
= mapping
;
4202 return (firstmapping
);
4206 * Build the group mapping list
4207 * group identification may be given in symbolic or numeric format
4209 * gid not associated to a uid are processed first in order
4210 * to favour real groups
4212 * ! Note ! : does getgrnam() read /etc/group or some other file ?
4213 * if so there is a possible recursion into fuse if this
4214 * file is on NTFS, and fuse is not recursion safe.
4217 struct MAPPING
*ntfs_do_group_mapping(struct MAPLIST
*firstitem
)
4219 struct MAPLIST
*item
;
4220 struct MAPPING
*firstmapping
;
4221 struct MAPPING
*lastmapping
;
4222 struct MAPPING
*mapping
;
4230 firstmapping
= (struct MAPPING
*)NULL
;
4231 lastmapping
= (struct MAPPING
*)NULL
;
4232 for (step
=1; step
<=2; step
++) {
4233 for (item
= firstitem
; item
; item
= item
->next
) {
4234 secondstep
= (item
->uidstr
[0] != '\0')
4235 || !item
->gidstr
[0];
4236 ok
= (step
== 1 ? !secondstep
: secondstep
);
4237 if ((item
->gidstr
[0] >= '0')
4238 && (item
->gidstr
[0] <= '9'))
4239 gid
= atoi(item
->gidstr
);
4242 if (item
->gidstr
[0]) {
4243 grp
= getgrnam(item
->gidstr
);
4247 log_early_error("Invalid group \"%s\"\n",
4252 * Records with no uid and no gid are inserted in the
4253 * second step to define the implicit mapping pattern
4257 || (!item
->uidstr
[0] && !item
->gidstr
[0]))) {
4258 sid
= encodesid(item
->sidstr
);
4259 if (sid
&& !item
->uidstr
[0] && !item
->gidstr
[0]
4260 && !ntfs_valid_pattern(sid
)) {
4261 /* error already logged */
4265 mapping
= (struct MAPPING
*)
4266 ntfs_malloc(sizeof(struct MAPPING
));
4271 mapping
->next
= (struct MAPPING
*)NULL
;
4273 lastmapping
->next
= mapping
;
4275 firstmapping
= mapping
;
4276 lastmapping
= mapping
;
4282 return (firstmapping
);