ntfs-3g ver. 2009.11.14
[tomato.git] / release / src / router / ntfs-3g / libntfs-3g / acls.c
blob887d75ae9dac55c52798fec4ddb0281c9a81264a
1 /**
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
25 #ifdef HAVE_CONFIG_H
27 * integration into ntfs-3g
29 #include "config.h"
31 #ifdef HAVE_STDIO_H
32 #include <stdio.h>
33 #endif
34 #ifdef HAVE_STDLIB_H
35 #include <stdlib.h>
36 #endif
37 #ifdef HAVE_STRING_H
38 #include <string.h>
39 #endif
40 #ifdef HAVE_ERRNO_H
41 #include <errno.h>
42 #endif
43 #ifdef HAVE_FCNTL_H
44 #include <fcntl.h>
45 #endif
46 #ifdef HAVE_SYSLOG_H
47 #include <syslog.h>
48 #endif
49 #include <unistd.h>
50 #include <pwd.h>
51 #include <grp.h>
53 #include "types.h"
54 #include "layout.h"
55 #include "security.h"
56 #include "acls.h"
57 #include "misc.h"
58 #else
61 * integration into secaudit, check whether Win32,
62 * may have to be adapted to compiler or something else
65 #ifndef WIN32
66 #if defined(__WIN32) | defined(__WIN32__) | defined(WNSC)
67 #define WIN32 1
68 #endif
69 #endif
71 #include <stdio.h>
72 #include <time.h>
73 #include <string.h>
74 #include <stdlib.h>
75 #include <stdarg.h>
76 #include <sys/types.h>
77 #include <errno.h>
80 * integration into secaudit/Win32
82 #ifdef WIN32
83 #include <fcntl.h>
84 #include <windows.h>
85 #define __LITTLE_ENDIAN 1234
86 #define __BYTE_ORDER __LITTLE_ENDIAN
87 #else
89 * integration into secaudit/STSC
91 #ifdef STSC
92 #include <stat.h>
93 #undef __BYTE_ORDER
94 #define __BYTE_ORDER __BIG_ENDIAN
95 #else
97 * integration into secaudit/Linux
99 #include <sys/stat.h>
100 #include <endian.h>
101 #include <unistd.h>
102 #include <dlfcn.h>
103 #endif /* STSC */
104 #endif /* WIN32 */
105 #include "secaudit.h"
106 #endif /* HAVE_CONFIG_H */
109 * A few useful constants
113 * null SID (S-1-0-0)
116 static const char nullsidbytes[] = {
117 1, /* revision */
118 1, /* auth count */
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[] = {
130 1, /* revision */
131 1, /* auth count */
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[] = {
143 1, /* revision */
144 2, /* auth count */
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;
153 * SID for system
156 static const char systemsidbytes[] = {
157 1, /* revision */
158 1, /* auth count */
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
167 * S-1-3-0
170 static const char ownersidbytes[] = {
171 1, /* revision */
172 1, /* auth count */
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
181 * S-1-3-1
184 static const char groupsidbytes[] = {
185 1, /* revision */
186 1, /* auth count */
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)
208 int size;
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)
222 return (
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;
260 const ACL *pdacl;
261 const ACL *psacl;
262 const SID *psid;
263 unsigned int offdacl;
264 unsigned int offsacl;
265 unsigned int offowner;
266 unsigned int offgroup;
267 unsigned int endsid;
268 unsigned int endacl;
269 unsigned int attrsz;
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);
289 attrsz = endsid;
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);
296 if (endacl > attrsz)
297 attrsz = endacl;
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);
306 if (endacl > attrsz)
307 attrsz = endacl;
309 return (attrsz);
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
326 * mapping pattern.
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)
336 int cnt;
337 u32 auth;
338 le32 leauth;
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)
355 BIGSID defsid;
356 SID *psid;
357 u32 xid; /* uid or gid */
358 int cnt;
359 u32 carry;
360 le32 leauth;
361 u32 uauth;
362 u32 xlast;
363 u32 rlast;
365 memcpy(&defsid,pattern,ntfs_sid_size(pattern));
366 psid = (SID*)&defsid;
367 cnt = psid->sub_authority_count;
368 xid = 0;
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;
380 else {
382 * check whether part of mapping had to be
383 * recorded in a higher level authority
385 carry = 1;
386 do {
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)
392 && (++carry < 4));
393 if (carry < 4)
394 xid = (((xlast - rlast) >> 1)
395 & 0x3fffffff) | (carry << 30);
399 return (xid);
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;
411 const SID *sid;
412 le32 leauth;
413 u32 uauth;
414 int cnt;
416 if (!uid)
417 sid = adminsid;
418 else {
419 p = usermapping;
420 while (p && p->xid && ((uid_t)p->xid != uid))
421 p = p->next;
422 if (p && !p->xid) {
424 * default pattern has been reached :
425 * build an implicit SID according to pattern
426 * (the pattern format was checked while reading
427 * the mapping file)
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);
439 sid = defusid;
440 } else
441 sid = (p ? p->sid : (const SID*)NULL);
443 return (sid);
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;
455 const SID *sid;
456 le32 leauth;
457 u32 uauth;
458 int cnt;
460 if (!gid)
461 sid = adminsid;
462 else {
463 p = groupmapping;
464 while (p && p->xid && ((gid_t)p->xid != gid))
465 p = p->next;
466 if (p && !p->xid) {
468 * default pattern has been reached :
469 * build an implicit SID according to pattern
470 * (the pattern format was checked while reading
471 * the mapping file)
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);
483 sid = defgsid;
484 } else
485 sid = (p ? p->sid : (const SID*)NULL);
487 return (sid);
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)
497 uid_t uid;
498 const struct MAPPING *p;
500 p = usermapping;
501 while (p && p->xid && !ntfs_same_sid(usid, p->sid))
502 p = p->next;
503 if (p && !p->xid)
505 * No explicit mapping found, try implicit mapping
507 uid = findimplicit(usid,p->sid,0);
508 else
509 uid = (p ? p->xid : 0);
510 return (uid);
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)
520 gid_t gid;
521 const struct MAPPING *p;
522 int gsidsz;
524 gsidsz = ntfs_sid_size(gsid);
525 p = groupmapping;
526 while (p && p->xid && !ntfs_same_sid(gsid, p->sid))
527 p = p->next;
528 if (p && !p->xid)
530 * No explicit mapping found, try implicit mapping
532 gid = findimplicit(gsid,p->sid,1);
533 else
534 gid = (p ? p->xid : 0);
535 return (gid);
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;
545 unsigned int offace;
546 unsigned int acecnt;
547 unsigned int acesz;
548 unsigned int nace;
549 BOOL ok;
551 ok = TRUE;
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)
557 ok = FALSE;
558 else {
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))
564 ok = FALSE;
565 offace += acesz;
568 return (ok);
572 * Do sanity checks on security descriptors read from storage
573 * basically, we make sure that every field holds within
574 * allocated storage
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;
583 const ACL *pdacl;
584 const ACL *psacl;
585 unsigned int offdacl;
586 unsigned int offsacl;
587 unsigned int offowner;
588 unsigned int offgroup;
589 BOOL ok;
591 ok = TRUE;
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)
620 && (!offdacl
621 || ((offdacl >= sizeof(SECURITY_DESCRIPTOR_RELATIVE))
622 && (offdacl < attrsz)))
623 && (!offsacl
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
637 && (!offdacl
638 || ((phead->control & SE_DACL_PRESENT)
639 && ((pdacl->revision == ACL_REVISION)
640 || (pdacl->revision == ACL_REVISION_DS))))
641 /* same for SACL */
642 && (!offsacl
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)))
651 ok = FALSE;
652 } else
653 ok = FALSE;
654 return (ok);
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)
667 unsigned int src;
668 unsigned int dst;
669 int oldcnt;
670 int newcnt;
671 unsigned int selection;
672 int nace;
673 int acesz;
674 int usidsz;
675 int gsidsz;
676 const ACCESS_ALLOWED_ACE *poldace;
677 ACCESS_ALLOWED_ACE *pnewace;
679 usidsz = ntfs_sid_size(usid);
680 gsidsz = ntfs_sid_size(gsid);
682 /* ACL header */
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);
690 newcnt = 0;
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);
706 acesz = usidsz + 8;
708 if (ntfs_same_sid(&pnewace->sid, groupsid)) {
709 memcpy(&pnewace->sid, gsid, gsidsz);
710 acesz = gsidsz + 8;
712 if (pnewace->mask & GENERIC_ALL) {
713 pnewace->mask &= ~GENERIC_ALL;
714 if (fordir)
715 pnewace->mask |= OWNER_RIGHTS
716 | DIR_READ
717 | DIR_WRITE
718 | DIR_EXEC;
719 else
721 * The last flag is not defined for a file,
722 * however Windows sets it, so do the same
724 pnewace->mask |= OWNER_RIGHTS
725 | FILE_READ
726 | FILE_WRITE
727 | FILE_EXEC
728 | cpu_to_le32(0x40);
730 /* remove inheritance flags */
731 pnewace->flags &= ~(OBJECT_INHERIT_ACE
732 | CONTAINER_INHERIT_ACE
733 | INHERIT_ONLY_ACE);
734 dst += acesz;
735 newcnt++;
737 /* inheritance for further inheritance */
738 if (fordir
739 && (poldace->flags
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);
750 acesz = usidsz + 8;
752 if (ntfs_same_sid(&pnewace->sid, groupsid)) {
753 memcpy(&pnewace->sid, gsid, gsidsz);
754 acesz = gsidsz + 8;
756 dst += acesz;
757 newcnt++;
759 src += acesz;
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);
767 } else
768 dst = 0;
769 return (dst);
772 #if POSIXACLS
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;
784 int i;
785 BOOL ok;
786 u16 tag;
787 u32 id;
788 int perms;
789 struct {
790 u16 previous;
791 u32 previousid;
792 u16 tagsset;
793 mode_t mode;
794 int owners;
795 int groups;
796 int others;
797 } checks[2], *pchk;
799 for (i=0; i<2; i++) {
800 checks[i].mode = 0;
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;
808 ok = TRUE;
809 pacl = &pxdesc->acl;
811 * header (strict for now)
813 if ((pacl->version != POSIX_VERSION)
814 || (pacl->flags != 0)
815 || (pacl->filler != 0))
816 ok = FALSE;
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)
825 pchk = &checks[1];
826 else
827 pchk = &checks[0];
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)))
836 ok = FALSE;
837 pchk->previous = tag;
838 pchk->previousid = id;
839 switch (tag) {
840 case POSIX_ACL_USER_OBJ :
841 if (pchk->owners++)
842 ok = FALSE;
843 if (id != (u32)-1)
844 ok = FALSE;
845 pchk->mode |= perms << 6;
846 break;
847 case POSIX_ACL_GROUP_OBJ :
848 if (pchk->groups++)
849 ok = FALSE;
850 if (id != (u32)-1)
851 ok = FALSE;
852 pchk->mode = (pchk->mode & 07707) | (perms << 3);
853 break;
854 case POSIX_ACL_OTHER :
855 if (pchk->others++)
856 ok = FALSE;
857 if (id != (u32)-1)
858 ok = FALSE;
859 pchk->mode |= perms;
860 break;
861 case POSIX_ACL_USER :
862 case POSIX_ACL_GROUP :
863 if (id == (u32)-1)
864 ok = FALSE;
865 break;
866 case POSIX_ACL_MASK :
867 if (id != (u32)-1)
868 ok = FALSE;
869 pchk->mode = (pchk->mode & 07707) | (perms << 3);
870 break;
871 default :
872 ok = FALSE;
873 break;
876 if ((pxdesc->acccnt > 0)
877 && ((checks[0].owners != 1) || (checks[0].groups != 1)
878 || (checks[0].others != 1)))
879 ok = FALSE;
880 /* do not check owner, group or other are present in */
881 /* the default ACL, Windows does not necessarily set them */
882 /* descriptor */
883 if (pxdesc->defcnt && (pxdesc->acccnt > pxdesc->firstdef))
884 ok = FALSE;
885 if ((pxdesc->acccnt < 0) || (pxdesc->defcnt < 0))
886 ok = FALSE;
887 /* check mode, unless null or no tag set */
888 if (pxdesc->mode
889 && checks[0].tagsset
890 && (checks[0].mode != (pxdesc->mode & 0777)))
891 ok = FALSE;
892 /* check tagsset */
893 if (pxdesc->tagsset != checks[0].tagsset)
894 ok = FALSE;
895 return (ok);
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)
905 mode_t mode;
906 u16 tagsset;
907 struct POSIX_ACE *pace;
908 int i;
910 mode = basemode & 07000;
911 tagsset = 0;
912 for (i=0; i<pxdesc->acccnt; i++) {
913 pace = &pxdesc->acl.ace[i];
914 tagsset |= pace->tag;
915 switch(pace->tag) {
916 case POSIX_ACL_USER_OBJ :
917 mode |= (pace->perms & 7) << 6;
918 break;
919 case POSIX_ACL_GROUP_OBJ :
920 case POSIX_ACL_MASK :
921 mode = (mode & 07707) | ((pace->perms & 7) << 3);
922 break;
923 case POSIX_ACL_OTHER :
924 mode |= pace->perms & 7;
925 break;
926 default :
927 break;
930 pxdesc->tagsset = tagsset;
931 pxdesc->mode = mode;
932 pxdesc->acl.version = POSIX_VERSION;
933 pxdesc->acl.flags = 0;
934 pxdesc->acl.filler = 0;
935 return (mode);
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;
952 int i;
953 int offs;
954 BOOL done;
955 u16 tag;
956 u16 previous;
957 u32 id;
958 u32 previousid;
962 * Check sequencing of tag+id in access ACE's
964 pacl = &pxdesc->acl;
965 do {
966 done = TRUE;
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;
973 if ((tag < previous)
974 || ((tag == previous) && (id < previousid))) {
975 done = FALSE;
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));
979 } else {
980 previous = tag;
981 previousid = id;
984 } while (!done);
986 * Same for default ACEs
988 do {
989 done = TRUE;
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;
998 if ((tag < previous)
999 || ((tag == previous) && (id < previousid))) {
1000 done = FALSE;
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));
1004 } else {
1005 previous = tag;
1006 previousid = id;
1010 } while (!done);
1014 * Merge a new mode into a Posix descriptor
1015 * The Posix descriptor is not reallocated, its size is unchanged
1017 * returns 0 if ok
1020 int ntfs_merge_mode_posix(struct POSIX_SECURITY *pxdesc, mode_t mode)
1022 int i;
1023 BOOL maskfound;
1024 struct POSIX_ACE *pace;
1025 int todo;
1027 maskfound = FALSE;
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];
1031 switch(pace->tag) {
1032 case POSIX_ACL_USER_OBJ :
1033 pace->perms = (mode >> 6) & 7;
1034 todo &= ~POSIX_ACL_USER_OBJ;
1035 break;
1036 case POSIX_ACL_GROUP_OBJ :
1037 if (!maskfound)
1038 pace->perms = (mode >> 3) & 7;
1039 todo &= ~POSIX_ACL_GROUP_OBJ;
1040 break;
1041 case POSIX_ACL_MASK :
1042 pace->perms = (mode >> 3) & 7;
1043 maskfound = TRUE;
1044 break;
1045 case POSIX_ACL_OTHER :
1046 pace->perms = mode & 7;
1047 todo &= ~POSIX_ACL_OTHER;
1048 break;
1049 default :
1050 break;
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;
1068 size_t newsize;
1069 int offset;
1070 int oldoffset;
1071 int i;
1073 if (deflt)
1074 newsize = sizeof(struct POSIX_SECURITY)
1075 + (oldpxdesc->acccnt + count)*sizeof(struct POSIX_ACE);
1076 else
1077 newsize = sizeof(struct POSIX_SECURITY)
1078 + (oldpxdesc->defcnt + count)*sizeof(struct POSIX_ACE);
1079 newpxdesc = (struct POSIX_SECURITY*)malloc(newsize);
1080 if (newpxdesc) {
1081 if (deflt) {
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];
1092 } else {
1093 offset = count;
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 */
1109 free(newpxdesc);
1110 newpxdesc = (struct POSIX_SECURITY*)NULL;
1111 errno = EINVAL;
1113 } else
1114 errno = ENOMEM;
1115 return (newpxdesc);
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;
1131 int count;
1132 int defcnt;
1133 int size;
1134 int i;
1135 s16 tagsset;
1137 if (pxdesc && pxdesc->defcnt) {
1138 if (isdir)
1139 count = 2*pxdesc->defcnt + 3;
1140 else
1141 count = pxdesc->defcnt + 3;
1142 } else
1143 count = 3;
1144 pydesc = (struct POSIX_SECURITY*)malloc(
1145 sizeof(struct POSIX_SECURITY) + count*sizeof(struct POSIX_ACE));
1146 if (pydesc) {
1148 * Copy inherited tags and adapt perms
1149 * Use requested mode, ignoring umask
1150 * (not possible with older versions of fuse)
1152 tagsset = 0;
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;
1160 break;
1161 case POSIX_ACL_GROUP_OBJ :
1162 if (!(tagsset & POSIX_ACL_MASK))
1163 pyace->perms &= (mode >> 3) & 7;
1164 break;
1165 case POSIX_ACL_OTHER :
1166 pyace->perms &= mode & 7;
1167 break;
1168 case POSIX_ACL_MASK :
1169 pyace->perms &= (mode >> 3) & 7;
1170 break;
1171 default :
1172 break;
1174 tagsset |= pyace->tag;
1176 pydesc->acccnt = defcnt;
1178 * If some standard tags were missing, append them from mode
1179 * and sort the list
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)) {
1184 i = defcnt;
1185 /* owner was missing */
1186 if (!(tagsset & POSIX_ACL_USER_OBJ)) {
1187 pyace = &pydesc->acl.ace[i];
1188 pyace->tag = POSIX_ACL_USER_OBJ;
1189 pyace->id = -1;
1190 pyace->perms = ((mode & ~mask) >> 6) & 7;
1191 tagsset |= POSIX_ACL_USER_OBJ;
1192 i++;
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;
1198 pyace->id = -1;
1199 pyace->perms = ((mode & ~mask) >> 3) & 7;
1200 tagsset |= POSIX_ACL_GROUP_OBJ;
1201 i++;
1203 /* other was missing */
1204 if (!(tagsset & POSIX_ACL_OTHER)) {
1205 pyace = &pydesc->acl.ace[i];
1206 pyace->tag = POSIX_ACL_OTHER;
1207 pyace->id = -1;
1208 pyace->perms = mode & ~mask & 7;
1209 tagsset |= POSIX_ACL_OTHER;
1210 i++;
1212 pydesc->acccnt = i;
1213 pydesc->firstdef = i;
1214 pydesc->defcnt = 0;
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;
1227 } else {
1228 pydesc->defcnt = 0;
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");
1234 errno = EIO;
1235 free(pydesc);
1236 pydesc = (struct POSIX_SECURITY*)NULL;
1238 } else
1239 errno = ENOMEM;
1240 return (pydesc);
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)
1248 int k;
1250 k = 0;
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)) {
1260 secondace++;
1261 secondcnt--;
1262 } else
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;
1269 firstace++;
1270 targetace++;
1271 firstcnt--;
1272 k++;
1273 } else {
1274 targetace->tag = secondace->tag;
1275 targetace->id = secondace->id;
1276 targetace->perms = secondace->perms;
1277 secondace++;
1278 targetace++;
1279 secondcnt--;
1280 k++;
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;
1289 firstace++;
1290 targetace++;
1291 firstcnt--;
1292 k++;
1294 while (secondcnt > 0) {
1295 targetace->tag = secondace->tag;
1296 targetace->id = secondace->id;
1297 targetace->perms = secondace->perms;
1298 secondace++;
1299 targetace++;
1300 secondcnt--;
1301 k++;
1303 return (k);
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,
1311 * or NULL if failed
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;
1321 size_t size;
1322 int k;
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);
1328 if (pxdesc) {
1330 * merge access ACEs
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);
1337 pxdesc->acccnt = k;
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);
1347 pxdesc->defcnt = k;
1349 * build header
1351 pxdesc->acl.version = POSIX_VERSION;
1352 pxdesc->acl.flags = 0;
1353 pxdesc->acl.filler = 0;
1354 pxdesc->mode = 0;
1355 pxdesc->tagsset = 0;
1356 } else
1357 errno = ENOMEM;
1358 return (pxdesc);
1361 struct BUILD_CONTEXT {
1362 BOOL isdir;
1363 BOOL adminowns;
1364 BOOL groupowns;
1365 u16 selfuserperms;
1366 u16 selfgrpperms;
1367 u16 grpperms;
1368 u16 othperms;
1369 u16 mask;
1370 u16 designates;
1371 u16 withmask;
1372 u16 rootspecial;
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)
1382 BIGSID defsid;
1383 ACCESS_ALLOWED_ACE *pdace;
1384 const SID *sid;
1385 int sidsz;
1386 int pos;
1387 int acecnt;
1388 le32 grants;
1389 le32 denials;
1390 u16 perms;
1391 u16 mixperms;
1392 u16 tag;
1393 BOOL rejected;
1394 BOOL rootuser;
1395 BOOL avoidmask;
1397 rejected = FALSE;
1398 tag = pxace->tag;
1399 perms = pxace->perms;
1400 rootuser = FALSE;
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) {
1407 sid = usid;
1408 sidsz = ntfs_sid_size(sid);
1409 grants = OWNER_RIGHTS;
1410 } else {
1411 if (pxace->id) {
1412 sid = NTFS_FIND_USID(mapping[MAPUSERS],
1413 pxace->id, (SID*)&defsid);
1414 grants = WORLD_RIGHTS;
1415 } else {
1416 sid = adminsid;
1417 rootuser = TRUE;
1418 grants = WORLD_RIGHTS & ~ROOT_OWNER_UNMARK;
1420 if (sid) {
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];
1431 if (pset->isdir) {
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;
1438 } else {
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;
1446 if (rootuser)
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);
1453 pos += sidsz + 8;
1454 acecnt++;
1456 } else
1457 rejected = TRUE;
1459 if (!rejected) {
1460 if (pset->isdir) {
1461 if (perms & POSIX_PERM_X)
1462 grants |= DIR_EXEC;
1463 if (perms & POSIX_PERM_W)
1464 grants |= DIR_WRITE;
1465 if (perms & POSIX_PERM_R)
1466 grants |= DIR_READ;
1467 } else {
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;
1487 if (pset->isdir) {
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;
1494 } else {
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;
1502 } else {
1503 mixperms = ~pset->grpperms & pset->othperms;
1504 if (tag == POSIX_ACL_USER_OBJ)
1505 mixperms |= pset->selfuserperms;
1506 if (pset->isdir) {
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;
1513 } else {
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;
1522 denials &= ~grants;
1523 if (denials) {
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);
1529 pos += sidsz + 8;
1530 acecnt++;
1534 pacl->size = cpu_to_le16(pos);
1535 pacl->ace_count = cpu_to_le16(acecnt);
1536 return (!rejected);
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)
1544 BIGSID defsid;
1545 ACCESS_ALLOWED_ACE *pgace;
1546 const SID *sid;
1547 int sidsz;
1548 int pos;
1549 int acecnt;
1550 le32 grants;
1551 u16 perms;
1552 u16 tag;
1553 BOOL rejected;
1554 BOOL rootuser;
1556 rejected = FALSE;
1557 tag = pxace->tag;
1558 perms = pxace->perms;
1559 rootuser = FALSE;
1560 pos = le16_to_cpu(pacl->size);
1561 acecnt = le16_to_cpu(pacl->ace_count);
1562 if (tag == POSIX_ACL_USER_OBJ) {
1563 sid = usid;
1564 sidsz = ntfs_sid_size(sid);
1565 grants = OWNER_RIGHTS;
1566 } else {
1567 if (pxace->id) {
1568 sid = NTFS_FIND_USID(mapping[MAPUSERS],
1569 pxace->id, (SID*)&defsid);
1570 if (sid)
1571 sidsz = ntfs_sid_size(sid);
1572 else
1573 rejected = TRUE;
1574 grants = WORLD_RIGHTS;
1575 } else {
1576 sid = adminsid;
1577 sidsz = ntfs_sid_size(sid);
1578 rootuser = TRUE;
1579 grants = WORLD_RIGHTS & ~ROOT_OWNER_UNMARK;
1582 if (!rejected) {
1583 if (pset->isdir) {
1584 if (perms & POSIX_PERM_X)
1585 grants |= DIR_EXEC;
1586 if (perms & POSIX_PERM_W)
1587 grants |= DIR_WRITE;
1588 if (perms & POSIX_PERM_R)
1589 grants |= DIR_READ;
1590 } else {
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;
1598 if (rootuser)
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);
1606 pos += sidsz + 8;
1607 acecnt = le16_to_cpu(pacl->ace_count) + 1;
1608 pacl->ace_count = cpu_to_le16(acecnt);
1609 pacl->size = cpu_to_le16(pos);
1611 return (!rejected);
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)
1625 BIGSID defsid;
1626 ACCESS_ALLOWED_ACE *pdace;
1627 ACCESS_ALLOWED_ACE *pgace;
1628 const SID *sid;
1629 int sidsz;
1630 int pos;
1631 int acecnt;
1632 le32 grants;
1633 le32 denials;
1634 u16 perms;
1635 u16 mixperms;
1636 u16 tag;
1637 BOOL avoidmask;
1638 BOOL rootgroup;
1639 BOOL rejected;
1641 rejected = FALSE;
1642 tag = pxace->tag;
1643 perms = pxace->perms;
1644 pos = le16_to_cpu(pacl->size);
1645 acecnt = le16_to_cpu(pacl->ace_count);
1646 rootgroup = FALSE;
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)
1651 sid = gsid;
1652 else
1653 if (pxace->id)
1654 sid = NTFS_FIND_GSID(mapping[MAPGROUPS],
1655 pxace->id, (SID*)&defsid);
1656 else {
1657 sid = adminsid;
1658 rootgroup = TRUE;
1660 if (sid) {
1661 sidsz = ntfs_sid_size(sid);
1663 * Insert denial of complement of mask for
1664 * each group
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];
1676 if (pset->isdir) {
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;
1683 } else {
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);
1696 pos += sidsz + 8;
1697 acecnt++;
1699 } else
1700 rejected = TRUE;
1701 if (!rejected
1702 && (pset->adminowns
1703 || pset->groupowns
1704 || avoidmask
1705 || rootgroup
1706 || (perms != pset->othperms))) {
1707 grants = WORLD_RIGHTS;
1708 if (rootgroup)
1709 grants &= ~ROOT_GROUP_UNMARK;
1710 if (pset->isdir) {
1711 if (perms & POSIX_PERM_X)
1712 grants |= DIR_EXEC;
1713 if (perms & POSIX_PERM_W)
1714 grants |= DIR_WRITE;
1715 if (perms & POSIX_PERM_R)
1716 grants |= DIR_READ;
1717 } else {
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
1732 && !pset->groupowns
1733 && !rootgroup) {
1734 mixperms = pset->othperms;
1735 if (tag == POSIX_ACL_GROUP_OBJ)
1736 mixperms |= pset->selfgrpperms;
1737 if (pset->isdir) {
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;
1744 } else {
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);
1753 if (denials) {
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);
1759 pos += sidsz + 8;
1760 acecnt++;
1764 /* now insert grants to group if more than world */
1765 if (pset->adminowns
1766 || pset->groupowns
1767 || (avoidmask && (pset->designates || pset->withmask))
1768 || (perms & ~pset->othperms)
1769 || (pset->rootspecial
1770 && (tag == POSIX_ACL_GROUP_OBJ))
1771 || (tag == POSIX_ACL_GROUP)) {
1772 if (rootgroup)
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);
1780 pos += sidsz + 8;
1781 acecnt++;
1784 pacl->size = cpu_to_le16(pos);
1785 pacl->ace_count = cpu_to_le16(acecnt);
1786 return (!rejected);
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;
1880 BOOL adminowns;
1881 BOOL groupowns;
1882 ACL *pacl;
1883 ACCESS_ALLOWED_ACE *pgace;
1884 ACCESS_ALLOWED_ACE *pdace;
1885 const struct POSIX_ACE *pxace;
1886 BOOL ok;
1887 mode_t mode;
1888 u16 tag;
1889 u16 perms;
1890 ACE_FLAGS flags;
1891 int pos;
1892 int i;
1893 int k;
1894 BIGSID defsid;
1895 const SID *sid;
1896 int acecnt;
1897 int usidsz;
1898 int gsidsz;
1899 int wsidsz;
1900 int asidsz;
1901 int ssidsz;
1902 int nsidsz;
1903 le32 grants;
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);
1916 ok = TRUE;
1918 /* ACL header */
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
1931 * user or group
1932 * Also get global mask
1934 for (k=0; k<2; k++) {
1935 pset = &aceset[k];
1936 pset->selfuserperms = 0;
1937 pset->selfgrpperms = 0;
1938 pset->grpperms = 0;
1939 pset->othperms = 0;
1940 pset->mask = (POSIX_PERM_R | POSIX_PERM_W | POSIX_PERM_X);
1941 pset->designates = 0;
1942 pset->withmask = 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) {
1951 pset = &aceset[1];
1952 pxace = &pxdesc->acl.ace[i + pxdesc->firstdef - pxdesc->acccnt];
1953 } else {
1954 pset = &aceset[0];
1955 pxace = &pxdesc->acl.ace[i];
1957 switch (pxace->tag) {
1958 case POSIX_ACL_USER :
1959 pset->designates++;
1960 if (pxace->id) {
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;
1965 } else
1966 /* root as designated user is processed apart */
1967 pset->rootspecial = TRUE;
1968 break;
1969 case POSIX_ACL_GROUP :
1970 pset->designates++;
1971 if (pxace->id) {
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;
1976 } else
1977 /* root as designated group is processed apart */
1978 pset->rootspecial = TRUE;
1979 /* fall through */
1980 case POSIX_ACL_GROUP_OBJ :
1981 pset->grpperms |= pxace->perms;
1982 break;
1983 case POSIX_ACL_OTHER :
1984 pset->othperms = pxace->perms;
1985 break;
1986 case POSIX_ACL_MASK :
1987 pset->withmask++;
1988 pset->mask = pxace->perms;
1989 default :
1990 break;
1994 if (pxdesc->defcnt && (pxdesc->firstdef != pxdesc->acccnt)) {
1995 ntfs_log_error("** error : access and default not consecutive\n");
1996 return (0);
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;
2009 pset = &aceset[1];
2010 pxace = &pxdesc->acl.ace[i + pxdesc->firstdef - pxdesc->acccnt];
2011 } else {
2012 if (pxdesc->defcnt)
2013 flags = NO_PROPAGATE_INHERIT_ACE;
2014 else
2015 flags = (isdir ? DIR_INHERITANCE
2016 : FILE_INHERITANCE);
2017 pset = &aceset[0];
2018 pxace = &pxdesc->acl.ace[i];
2020 tag = pxace->tag;
2021 perms = pxace->perms;
2022 switch (tag) {
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);
2031 break;
2032 default :
2033 break;
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
2044 if (isdir && ok) {
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);
2052 pos += wsidsz + 8;
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
2062 * - grants to other
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;
2069 pset = &aceset[1];
2070 pxace = &pxdesc->acl.ace[i + pxdesc->firstdef - pxdesc->acccnt];
2071 } else {
2072 if (pxdesc->defcnt)
2073 flags = NO_PROPAGATE_INHERIT_ACE;
2074 else
2075 flags = (isdir ? DIR_INHERITANCE
2076 : FILE_INHERITANCE);
2077 pset = &aceset[0];
2078 pxace = &pxdesc->acl.ace[i];
2080 tag = pxace->tag;
2081 perms = pxace->perms;
2082 switch (tag) {
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);
2090 break;
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);
2099 break;
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;
2108 if (isdir) {
2109 if (perms & POSIX_PERM_X)
2110 grants |= DIR_EXEC;
2111 if (perms & POSIX_PERM_W)
2112 grants |= DIR_WRITE;
2113 if (perms & POSIX_PERM_R)
2114 grants |= DIR_READ;
2115 } else {
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);
2128 pos += wsidsz + 8;
2129 acecnt = le16_to_cpu(pacl->ace_count) + 1;
2130 pacl->ace_count = cpu_to_le16(acecnt);
2131 pacl->size = cpu_to_le16(pos);
2132 break;
2136 if (!ok) {
2137 errno = EINVAL;
2138 pos = 0;
2139 } else {
2140 /* an ACE for administrators */
2141 /* always full access */
2143 pos = le16_to_cpu(pacl->size);
2144 acecnt = le16_to_cpu(pacl->ace_count);
2145 if (isdir)
2146 flags = OBJECT_INHERIT_ACE
2147 | CONTAINER_INHERIT_ACE;
2148 else
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);
2157 pos += asidsz + 8;
2158 acecnt++;
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);
2170 pos += ssidsz + 8;
2171 acecnt++;
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);
2183 if (mode & S_ISUID)
2184 grants |= FILE_APPEND_DATA;
2185 if (mode & S_ISGID)
2186 grants |= FILE_WRITE_DATA;
2187 if (mode & S_ISVTX)
2188 grants |= FILE_READ_DATA;
2189 pgace->mask = grants;
2190 memcpy((char*)&pgace->sid, nullsid, nsidsz);
2191 pos += nsidsz + 8;
2192 acecnt++;
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)
2207 ACL *pacl;
2208 ACCESS_ALLOWED_ACE *pgace;
2209 ACCESS_ALLOWED_ACE *pdace;
2210 BOOL adminowns;
2211 BOOL groupowns;
2212 ACE_FLAGS gflags;
2213 int pos;
2214 int acecnt;
2215 int usidsz;
2216 int gsidsz;
2217 int wsidsz;
2218 int asidsz;
2219 int ssidsz;
2220 int nsidsz;
2221 le32 grants;
2222 le32 denials;
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);
2233 /* ACL header */
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);
2240 pos = sizeof(ACL);
2241 acecnt = 0;
2243 /* compute a grant ACE for owner */
2244 /* this ACE will be inserted after denial for owner */
2246 grants = OWNER_RIGHTS;
2247 if (isdir) {
2248 gflags = DIR_INHERITANCE;
2249 if (mode & S_IXUSR)
2250 grants |= DIR_EXEC;
2251 if (mode & S_IWUSR)
2252 grants |= DIR_WRITE;
2253 if (mode & S_IRUSR)
2254 grants |= DIR_READ;
2255 } else {
2256 gflags = FILE_INHERITANCE;
2257 if (mode & S_IXUSR)
2258 grants |= FILE_EXEC;
2259 if (mode & S_IWUSR)
2260 grants |= FILE_WRITE;
2261 if (mode & S_IRUSR)
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];
2271 if (!adminowns) {
2272 if (!groupowns) {
2273 if (isdir) {
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;
2281 } else {
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;
2290 } else {
2291 if (isdir) {
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;
2299 } else {
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;
2309 denials &= ~grants;
2310 if (denials) {
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);
2315 pos += usidsz + 8;
2316 acecnt++;
2320 * for directories, a world execution denial
2321 * inherited to plain files
2324 if (isdir) {
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);
2331 pos += wsidsz + 8;
2332 acecnt++;
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);
2343 pos += usidsz + 8;
2344 acecnt++;
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 */
2351 if (adminowns
2352 || groupowns
2353 || (((mode >> 3) ^ mode) & 7)) {
2354 grants = WORLD_RIGHTS;
2355 if (isdir) {
2356 gflags = DIR_INHERITANCE;
2357 if (mode & S_IXGRP)
2358 grants |= DIR_EXEC;
2359 if (mode & S_IWGRP)
2360 grants |= DIR_WRITE;
2361 if (mode & S_IRGRP)
2362 grants |= DIR_READ;
2363 } else {
2364 gflags = FILE_INHERITANCE;
2365 if (mode & S_IXGRP)
2366 grants |= FILE_EXEC;
2367 if (mode & S_IWGRP)
2368 grants |= FILE_WRITE;
2369 if (mode & S_IRGRP)
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) {
2379 if (isdir) {
2380 pdace->flags = DIR_INHERITANCE;
2381 if (mode & S_IXOTH)
2382 denials |= DIR_EXEC;
2383 if (mode & S_IWOTH)
2384 denials |= DIR_WRITE;
2385 if (mode & S_IROTH)
2386 denials |= DIR_READ;
2387 } else {
2388 pdace->flags = FILE_INHERITANCE;
2389 if (mode & S_IXOTH)
2390 denials |= FILE_EXEC;
2391 if (mode & S_IWOTH)
2392 denials |= FILE_WRITE;
2393 if (mode & S_IROTH)
2394 denials |= FILE_READ;
2396 denials &= ~(grants | OWNER_RIGHTS);
2397 if (denials) {
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);
2402 pos += gsidsz + 8;
2403 acecnt++;
2407 if (adminowns
2408 || groupowns
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);
2418 pos += gsidsz + 8;
2419 acecnt++;
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;
2428 if (isdir) {
2429 pgace->flags = DIR_INHERITANCE;
2430 if (mode & S_IXOTH)
2431 grants |= DIR_EXEC;
2432 if (mode & S_IWOTH)
2433 grants |= DIR_WRITE;
2434 if (mode & S_IROTH)
2435 grants |= DIR_READ;
2436 } else {
2437 pgace->flags = FILE_INHERITANCE;
2438 if (mode & S_IXOTH)
2439 grants |= FILE_EXEC;
2440 if (mode & S_IWOTH)
2441 grants |= FILE_WRITE;
2442 if (mode & S_IROTH)
2443 grants |= FILE_READ;
2445 pgace->size = cpu_to_le16(wsidsz + 8);
2446 pgace->mask = grants;
2447 memcpy((char*)&pgace->sid, worldsid, wsidsz);
2448 pos += wsidsz + 8;
2449 acecnt++;
2451 /* an ACE for administrators */
2452 /* always full access */
2454 pgace = (ACCESS_ALLOWED_ACE*)&secattr[offs + pos];
2455 pgace->type = ACCESS_ALLOWED_ACE_TYPE;
2456 if (isdir)
2457 pgace->flags = DIR_INHERITANCE;
2458 else
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);
2464 pos += asidsz + 8;
2465 acecnt++;
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;
2472 if (isdir)
2473 pgace->flags = DIR_INHERITANCE;
2474 else
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);
2480 pos += ssidsz + 8;
2481 acecnt++;
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);
2493 if (mode & S_ISUID)
2494 grants |= FILE_APPEND_DATA;
2495 if (mode & S_ISGID)
2496 grants |= FILE_WRITE_DATA;
2497 if (mode & S_ISVTX)
2498 grants |= FILE_READ_DATA;
2499 pgace->mask = grants;
2500 memcpy((char*)&pgace->sid, nullsid, nsidsz);
2501 pos += nsidsz + 8;
2502 acecnt++;
2505 /* fix ACL header */
2506 pacl->size = cpu_to_le16(pos);
2507 pacl->ace_count = cpu_to_le16(acecnt);
2508 return (pos);
2511 #if POSIXACLS
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)
2522 int newattrsz;
2523 SECURITY_DESCRIPTOR_RELATIVE *pnhead;
2524 char *newattr;
2525 int aclsz;
2526 int usidsz;
2527 int gsidsz;
2528 int wsidsz;
2529 int asidsz;
2530 int ssidsz;
2531 int k;
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);
2561 if (newattr) {
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
2571 | SE_SELF_RELATIVE;
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 */
2588 pnhead->owner =
2589 cpu_to_le32(sizeof(SECURITY_DESCRIPTOR_RELATIVE)
2590 + aclsz);
2591 pnhead->group =
2592 cpu_to_le32(sizeof(SECURITY_DESCRIPTOR_RELATIVE)
2593 + aclsz + usidsz);
2594 pnhead->sacl = const_cpu_to_le32(0);
2595 pnhead->dacl =
2596 const_cpu_to_le32(sizeof(SECURITY_DESCRIPTOR_RELATIVE));
2597 } else {
2598 /* ACL failure (errno set) or overflow */
2599 free(newattr);
2600 newattr = (char*)NULL;
2601 if (aclsz) {
2602 /* hope error was detected before overflowing */
2603 ntfs_log_error("Security descriptor is longer than expected\n");
2604 errno = EIO;
2607 } else
2608 errno = ENOMEM;
2609 return (newattr);
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)
2622 int newattrsz;
2623 SECURITY_DESCRIPTOR_RELATIVE *pnhead;
2624 char *newattr;
2625 int aclsz;
2626 int usidsz;
2627 int gsidsz;
2628 int wsidsz;
2629 int asidsz;
2630 int ssidsz;
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);
2652 if (newattr) {
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
2662 | SE_SELF_RELATIVE;
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 */
2679 pnhead->owner =
2680 cpu_to_le32(sizeof(SECURITY_DESCRIPTOR_RELATIVE)
2681 + aclsz);
2682 pnhead->group =
2683 cpu_to_le32(sizeof(SECURITY_DESCRIPTOR_RELATIVE)
2684 + aclsz + usidsz);
2685 pnhead->sacl = const_cpu_to_le32(0);
2686 pnhead->dacl =
2687 const_cpu_to_le32(sizeof(SECURITY_DESCRIPTOR_RELATIVE));
2688 } else {
2689 /* hope error was detected before overflowing */
2690 free(newattr);
2691 newattr = (char*)NULL;
2692 ntfs_log_error("Security descriptor is longer than expected\n");
2693 errno = EIO;
2695 } else
2696 errno = ENOMEM;
2697 return (newattr);
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)
2709 int perm;
2711 perm = 0;
2712 /* build owner permission */
2713 if (owner) {
2714 if (isdir) {
2715 /* exec if any of list, traverse */
2716 if (owner & DIR_GEXEC)
2717 perm |= S_IXUSR;
2718 /* write if any of addfile, adddir, delchild */
2719 if (owner & DIR_GWRITE)
2720 perm |= S_IWUSR;
2721 /* read if any of list */
2722 if (owner & DIR_GREAD)
2723 perm |= S_IRUSR;
2724 } else {
2725 /* exec if execute or generic execute */
2726 if (owner & FILE_GEXEC)
2727 perm |= S_IXUSR;
2728 /* write if any of writedata or generic write */
2729 if (owner & FILE_GWRITE)
2730 perm |= S_IWUSR;
2731 /* read if any of readdata or generic read */
2732 if (owner & FILE_GREAD)
2733 perm |= S_IRUSR;
2736 /* build group permission */
2737 if (group) {
2738 if (isdir) {
2739 /* exec if any of list, traverse */
2740 if (group & DIR_GEXEC)
2741 perm |= S_IXGRP;
2742 /* write if any of addfile, adddir, delchild */
2743 if (group & DIR_GWRITE)
2744 perm |= S_IWGRP;
2745 /* read if any of list */
2746 if (group & DIR_GREAD)
2747 perm |= S_IRGRP;
2748 } else {
2749 /* exec if execute */
2750 if (group & FILE_GEXEC)
2751 perm |= S_IXGRP;
2752 /* write if any of writedata, appenddata */
2753 if (group & FILE_GWRITE)
2754 perm |= S_IWGRP;
2755 /* read if any of readdata */
2756 if (group & FILE_GREAD)
2757 perm |= S_IRGRP;
2760 /* build world permission */
2761 if (world) {
2762 if (isdir) {
2763 /* exec if any of list, traverse */
2764 if (world & DIR_GEXEC)
2765 perm |= S_IXOTH;
2766 /* write if any of addfile, adddir, delchild */
2767 if (world & DIR_GWRITE)
2768 perm |= S_IWOTH;
2769 /* read if any of list */
2770 if (world & DIR_GREAD)
2771 perm |= S_IROTH;
2772 } else {
2773 /* exec if execute */
2774 if (world & FILE_GEXEC)
2775 perm |= S_IXOTH;
2776 /* write if any of writedata, appenddata */
2777 if (world & FILE_GWRITE)
2778 perm |= S_IWOTH;
2779 /* read if any of readdata */
2780 if (world & FILE_GREAD)
2781 perm |= S_IROTH;
2784 /* build special permission flags */
2785 if (special) {
2786 if (special & FILE_APPEND_DATA)
2787 perm |= S_ISUID;
2788 if (special & FILE_WRITE_DATA)
2789 perm |= S_ISGID;
2790 if (special & FILE_READ_DATA)
2791 perm |= S_ISVTX;
2793 return (perm);
2796 #if POSIXACLS
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)
2807 int j,k;
2808 s32 id;
2809 u16 tag;
2810 u16 tagsset;
2811 struct POSIX_ACE *pxace;
2812 mode_t grantgrps;
2813 mode_t grantwrld;
2814 mode_t denywrld;
2815 mode_t allow;
2816 mode_t deny;
2817 mode_t perms;
2818 mode_t mode;
2820 mode = 0;
2821 tagsset = 0;
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;
2828 grantgrps = 0;
2829 grantwrld = 0;
2830 denywrld = 0;
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)
2835 && !start)
2836 denywrld = pxace[j].perms;
2837 } else {
2838 switch (pxace[j].tag) {
2839 case POSIX_ACL_GROUP_OBJ :
2840 grantgrps |= pxace[j].perms;
2841 break;
2842 case POSIX_ACL_GROUP :
2843 if (pxace[j].id)
2844 grantgrps |= pxace[j].perms;
2845 break;
2846 case POSIX_ACL_OTHER :
2847 grantwrld = pxace[j].perms;
2848 break;
2849 default :
2850 break;
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
2859 j = start;
2860 k = target;
2861 while (j < (start + count)) {
2862 tag = pxace[j].tag;
2863 id = pxace[j].id;
2864 if (pxace[j].perms & POSIX_PERM_DENIAL) {
2865 deny = pxace[j].perms | denywrld;
2866 allow = 0;
2867 } else {
2868 deny = denywrld;
2869 allow = pxace[j].perms;
2871 j++;
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;
2877 else
2878 allow |= pxace[j].perms;
2879 j++;
2882 * Build the permissions equivalent to grants and denials
2884 if (groupowns) {
2885 if (tag == POSIX_ACL_MASK)
2886 perms = ~deny;
2887 else
2888 perms = allow & ~deny;
2889 } else
2890 switch (tag) {
2891 case POSIX_ACL_USER_OBJ :
2892 perms = (allow | grantgrps | grantwrld) & ~deny;
2893 break;
2894 case POSIX_ACL_USER :
2895 if (id)
2896 perms = (allow | grantgrps | grantwrld)
2897 & ~deny;
2898 else
2899 perms = allow;
2900 break;
2901 case POSIX_ACL_GROUP_OBJ :
2902 perms = (allow | grantwrld) & ~deny;
2903 break;
2904 case POSIX_ACL_GROUP :
2905 if (id)
2906 perms = (allow | grantwrld) & ~deny;
2907 else
2908 perms = allow;
2909 break;
2910 case POSIX_ACL_MASK :
2911 perms = ~deny;
2912 break;
2913 default :
2914 perms = allow & ~deny;
2915 break;
2918 * Store into a Posix ACE
2920 if (tag != POSIX_ACL_SPECIAL) {
2921 pxace[k].tag = tag;
2922 pxace[k].id = id;
2923 pxace[k].perms = perms
2924 & (POSIX_PERM_R | POSIX_PERM_W | POSIX_PERM_X);
2925 tagsset |= tag;
2926 k++;
2928 switch (tag) {
2929 case POSIX_ACL_USER_OBJ :
2930 mode |= ((perms & 7) << 6);
2931 break;
2932 case POSIX_ACL_GROUP_OBJ :
2933 case POSIX_ACL_MASK :
2934 mode = (mode & 07707) | ((perms & 7) << 3);
2935 break;
2936 case POSIX_ACL_OTHER :
2937 mode |= perms & 7;
2938 break;
2939 case POSIX_ACL_SPECIAL :
2940 mode |= (perms & (S_ISVTX | S_ISUID | S_ISGID));
2941 break;
2942 default :
2943 break;
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;
2964 const ACL *pacl;
2965 const ACCESS_ALLOWED_ACE *pace;
2966 int offdacl;
2967 int offace;
2968 int acecnt;
2969 int nace;
2970 BOOL noown;
2971 le32 special;
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);
2981 noown = TRUE;
2982 if (offdacl) {
2983 acecnt = le16_to_cpu(pacl->ace_count);
2984 offace = offdacl + sizeof(ACL);
2985 } else
2986 acecnt = 0;
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)) {
2992 noown = FALSE;
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;
2997 } else
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;
3004 } else
3005 if (is_world_sid((const SID*)&pace->sid)) {
3006 if (pace->type == ACCESS_ALLOWED_ACE_TYPE)
3007 allowall |= pace->mask;
3008 else
3009 if (pace->type == ACCESS_DENIED_ACE_TYPE)
3010 denyall |= pace->mask;
3011 } else
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
3024 if (noown)
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,
3037 special));
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;
3050 const ACL *pacl;
3051 const ACCESS_ALLOWED_ACE *pace;
3052 int offdacl;
3053 int offace;
3054 int acecnt;
3055 int nace;
3056 le32 special;
3057 BOOL grppresent;
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);
3067 grppresent = FALSE;
3068 if (offdacl) {
3069 acecnt = le16_to_cpu(pacl->ace_count);
3070 offace = offdacl + sizeof(ACL);
3071 } else
3072 acecnt = 0;
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;
3081 } else
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;
3086 grppresent = TRUE;
3088 } else
3089 if (is_world_sid((const SID*)&pace->sid)) {
3090 if (pace->type == ACCESS_ALLOWED_ACE_TYPE)
3091 allowall |= pace->mask;
3092 else
3093 if (pace->type == ACCESS_DENIED_ACE_TYPE)
3094 denyall |= pace->mask;
3095 } else
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);
3102 if (!grppresent)
3103 allowgrp = allowall;
3104 return (merge_permissions(isdir,
3105 allowown & ~(denyown | denyall),
3106 allowgrp & ~(denygrp | denyall),
3107 allowall & ~denyall,
3108 special));
3111 #if POSIXACLS
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)
3122 int j,k;
3123 s32 id;
3124 u16 tag;
3125 u16 tagsset;
3126 struct POSIX_ACE *pxace;
3127 int acccnt;
3128 mode_t denywrld;
3129 mode_t allow;
3130 mode_t deny;
3131 mode_t perms;
3132 mode_t mode;
3134 mode = 0;
3135 pxace = posix_desc->acl.ace;
3136 acccnt = posix_desc->acccnt;
3137 tagsset = 0;
3138 denywrld = 0;
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)
3147 && !start)
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
3156 j = start;
3157 k = target;
3158 deny = 0;
3159 while (j < (start + count)) {
3160 allow = 0;
3161 tag = pxace[j].tag;
3162 id = pxace[j].id;
3163 if (tag == POSIX_ACL_MASK) {
3164 deny = pxace[j].perms;
3165 j++;
3166 while ((j < (start + count))
3167 && (pxace[j].tag == POSIX_ACL_MASK))
3168 j++;
3169 } else {
3170 if (!(pxace[j].perms & POSIX_PERM_DENIAL))
3171 allow = pxace[j].perms;
3172 j++;
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;
3178 j++;
3183 * Store the grants into a Posix ACE
3185 if (tag == POSIX_ACL_MASK)
3186 perms = ~deny;
3187 else
3188 perms = allow & ~denywrld;
3189 if (tag != POSIX_ACL_SPECIAL) {
3190 pxace[k].tag = tag;
3191 pxace[k].id = id;
3192 pxace[k].perms = perms
3193 & (POSIX_PERM_R | POSIX_PERM_W | POSIX_PERM_X);
3194 tagsset |= tag;
3195 k++;
3197 switch (tag) {
3198 case POSIX_ACL_USER_OBJ :
3199 mode |= ((perms & 7) << 6);
3200 break;
3201 case POSIX_ACL_GROUP_OBJ :
3202 case POSIX_ACL_MASK :
3203 mode = (mode & 07707) | ((perms & 7) << 3);
3204 break;
3205 case POSIX_ACL_OTHER :
3206 mode |= perms & 7;
3207 break;
3208 case POSIX_ACL_SPECIAL :
3209 mode |= perms & (S_ISVTX | S_ISUID | S_ISGID);
3210 break;
3211 default :
3212 break;
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;
3234 const ACL *pacl;
3235 const ACCESS_ALLOWED_ACE *pace;
3236 int offdacl;
3237 int offace;
3238 int acecnt;
3239 int nace;
3240 BOOL firstapply;
3241 int isforeign;
3242 le32 special;
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);
3252 if (offdacl) {
3253 acecnt = le16_to_cpu(pacl->ace_count);
3254 offace = offdacl + sizeof(ACL);
3255 } else
3256 acecnt = 0;
3257 firstapply = TRUE;
3258 isforeign = 3;
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;
3268 isforeign &= ~1;
3269 } else
3270 if (pace->type == ACCESS_DENIED_ACE_TYPE)
3271 denyown |= pace->mask;
3272 } else
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;
3277 isforeign &= ~2;
3278 } else
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;
3284 else
3285 if (pace->type == ACCESS_DENIED_ACE_TYPE)
3286 denyall |= pace->mask;
3288 firstapply = FALSE;
3289 } else
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);
3296 if (isforeign) {
3297 allowown |= (allowgrp | allowall);
3298 allowgrp |= allowall;
3300 return (merge_permissions(isdir,
3301 allowown & ~(denyown | denyall),
3302 allowgrp & ~(denygrp | denyall),
3303 allowall & ~denyall,
3304 special));
3307 #if OWNERFROMACL
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;
3325 const SID *usid;
3326 const ACL *pacl;
3327 const ACCESS_ALLOWED_ACE *pace;
3328 int offdacl;
3329 int offace;
3330 int acecnt;
3331 int nace;
3332 BOOL found;
3334 found = FALSE;
3335 phead = (const SECURITY_DESCRIPTOR_RELATIVE*)securattr;
3336 offdacl = le32_to_cpu(phead->dacl);
3337 if (offdacl) {
3338 pacl = (const ACL*)&securattr[offdacl];
3339 acecnt = le16_to_cpu(pacl->ace_count);
3340 offace = offdacl + sizeof(ACL);
3341 nace = 0;
3342 do {
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))
3347 found = TRUE;
3348 offace += le16_to_cpu(pace->size);
3349 } while (!found && (++nace < acecnt));
3351 if (found)
3352 usid = &pace->sid;
3353 else
3354 usid = (const SID*)&securattr[le32_to_cpu(phead->owner)];
3355 return (usid);
3358 #else
3361 * Special case for files owned by administrator with full
3362 * access granted to a mapped user : consider this user as the tenant
3363 * of the file.
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
3369 * only.
3371 * Check file is owned by administrator and no user has rights before
3372 * calling.
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;
3381 const ACL *pacl;
3382 const ACCESS_ALLOWED_ACE *pace;
3383 int offdacl;
3384 int offace;
3385 int acecnt;
3386 int nace;
3387 uid_t tid;
3388 uid_t xid;
3390 phead = (const SECURITY_DESCRIPTOR_RELATIVE*)securattr;
3391 offdacl = le32_to_cpu(phead->dacl);
3392 pacl = (const ACL*)&securattr[offdacl];
3393 tid = 0;
3394 if (offdacl) {
3395 acecnt = le16_to_cpu(pacl->ace_count);
3396 offace = offdacl + sizeof(ACL);
3397 } else
3398 acecnt = 0;
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);
3404 if (xid) tid = xid;
3406 offace += le16_to_cpu(pace->size);
3408 return (tid);
3411 #endif /* OWNERFROMACL */
3413 #if POSIXACLS
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;
3433 const ACL *pacl;
3434 const ACCESS_ALLOWED_ACE *pace;
3435 struct POSIX_ACE *pxace;
3436 struct {
3437 uid_t prevuid;
3438 gid_t prevgid;
3439 int groupmasks;
3440 s16 tagsset;
3441 BOOL gotowner;
3442 BOOL gotownermask;
3443 BOOL gotgroup;
3444 mode_t permswrld;
3445 } ctx[2], *pctx;
3446 int offdacl;
3447 int offace;
3448 int alloccnt;
3449 int acecnt;
3450 uid_t uid;
3451 gid_t gid;
3452 int i,j;
3453 int k,l;
3454 BOOL ignore;
3455 BOOL adminowns;
3456 BOOL groupowns;
3457 BOOL firstinh;
3458 BOOL genericinh;
3460 phead = (const SECURITY_DESCRIPTOR_RELATIVE*)securattr;
3461 offdacl = le32_to_cpu(phead->dacl);
3462 if (offdacl) {
3463 pacl = (const ACL*)&securattr[offdacl];
3464 acecnt = le16_to_cpu(pacl->ace_count);
3465 offace = offdacl + sizeof(ACL);
3466 } else {
3467 acecnt = 0;
3468 offace = 0;
3470 adminowns = FALSE;
3471 groupowns = ntfs_same_sid(gsid,usid);
3472 firstinh = FALSE;
3473 genericinh = FALSE;
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));
3486 k = 0;
3487 l = alloccnt;
3488 for (i=0; i<2; i++) {
3489 pctx = &ctx[i];
3490 pctx->permswrld = 0;
3491 pctx->prevuid = -1;
3492 pctx->prevgid = -1;
3493 pctx->groupmasks = 0;
3494 pctx->tagsset = 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];
3503 pctx = &ctx[1];
3504 } else {
3505 pxace = &pxdesc->acl.ace[k];
3506 pctx = &ctx[0];
3508 ignore = FALSE;
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);
3516 pxace->id = 0;
3517 if ((pace->mask & (GENERIC_ALL | WRITE_OWNER))
3518 && (pace->flags & INHERIT_ONLY_ACE))
3519 ignore = genericinh = TRUE;
3520 } else
3521 if (ntfs_same_sid(usid, &pace->sid)) {
3522 pxace->id = -1;
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;
3534 pxace->id = -1;
3535 } else {
3536 if (ntfs_same_sid(&pace->sid,usid))
3537 groupowns = TRUE;
3538 gid = NTFS_FIND_GROUP(mapping[MAPGROUPS],&pace->sid);
3539 if (gid) {
3540 pxace->tag = POSIX_ACL_GROUP;
3541 pxace->id = gid;
3542 pctx->prevgid = gid;
3543 } else {
3544 uid = NTFS_FIND_USER(mapping[MAPUSERS],&pace->sid);
3545 if (uid) {
3546 pxace->tag = POSIX_ACL_USER;
3547 pxace->id = uid;
3548 } else
3549 ignore = TRUE;
3552 } else {
3554 * when group owns, late denials for owner
3555 * mean group mask
3557 if ((pace->type == ACCESS_DENIED_ACE_TYPE)
3558 && (pace->mask & WRITE_OWNER)) {
3559 pxace->tag = POSIX_ACL_MASK;
3560 pctx->gotownermask = TRUE;
3561 if (pctx->gotowner)
3562 pctx->groupmasks++;
3563 } else {
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);
3568 pxace->id = uid;
3569 pxace->tag = POSIX_ACL_USER;
3570 } else
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))
3577 ignore = TRUE;
3578 if (!firstinh) {
3579 firstinh = TRUE;
3581 } else {
3582 if ((adminowns && ntfs_same_sid(&pace->sid,adminsid))
3583 || ntfs_same_sid(&pace->sid,systemsid))
3584 ignore = TRUE;
3585 if (ntfs_same_sid(usid,adminsid))
3586 adminowns = TRUE;
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;
3594 pxace->id = -1;
3595 if (pctx->gotowner)
3596 pctx->groupmasks++;
3597 } else {
3598 if (pctx->gotgroup || (pctx->groupmasks > 1)) {
3599 gid = NTFS_FIND_GROUP(mapping[MAPGROUPS],&pace->sid);
3600 if (gid) {
3601 pxace->id = gid;
3602 pxace->tag = POSIX_ACL_GROUP;
3603 pctx->prevgid = gid;
3604 } else
3605 ignore = TRUE;
3606 } else {
3607 pxace->id = -1;
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))
3616 ignore = TRUE;
3617 if (ntfs_same_sid(gsid,adminsid))
3618 adminowns = TRUE;
3619 else
3620 genericinh = ignore;
3623 } else if (is_world_sid((const SID*)&pace->sid)) {
3624 pxace->id = -1;
3625 pxace->tag = POSIX_ACL_OTHER;
3626 if ((pace->type == ACCESS_DENIED_ACE_TYPE)
3627 && (pace->flags & INHERIT_ONLY_ACE))
3628 ignore = TRUE;
3629 } else if (ntfs_same_sid((const SID*)&pace->sid,nullsid)) {
3630 pxace->id = -1;
3631 pxace->tag = POSIX_ACL_SPECIAL;
3632 } else {
3633 uid = NTFS_FIND_USER(mapping[MAPUSERS],&pace->sid);
3634 if (uid) {
3635 if ((pace->type == ACCESS_DENIED_ACE_TYPE)
3636 && (pace->mask & WRITE_OWNER)
3637 && (pctx->prevuid != uid)) {
3638 pxace->id = -1;
3639 pxace->tag = POSIX_ACL_MASK;
3640 } else {
3641 pxace->id = uid;
3642 pxace->tag = POSIX_ACL_USER;
3644 pctx->prevuid = uid;
3645 } else {
3646 gid = NTFS_FIND_GROUP(mapping[MAPGROUPS],&pace->sid);
3647 if (gid) {
3648 if ((pace->type == ACCESS_DENIED_ACE_TYPE)
3649 && (pace->mask & WRITE_OWNER)
3650 && (pctx->prevgid != gid)) {
3651 pxace->tag = POSIX_ACL_MASK;
3652 pctx->groupmasks++;
3653 } else {
3654 pxace->tag = POSIX_ACL_GROUP;
3656 pxace->id = gid;
3657 pctx->prevgid = gid;
3658 } else {
3660 * do not grant rights to unknown
3661 * people and do not define root as a
3662 * designated user or group
3664 ignore = TRUE;
3668 if (!ignore) {
3669 pxace->perms = 0;
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;
3678 } else
3679 if (isdir) {
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
3689 | POSIX_PERM_W
3690 | POSIX_PERM_R;
3691 } else {
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;
3702 else
3703 if (pxace->tag == POSIX_ACL_OTHER)
3704 pctx->permswrld = pxace->perms;
3705 pctx->tagsset |= pxace->tag;
3706 if (pace->flags & INHERIT_ONLY_ACE) {
3707 l--;
3708 } else {
3709 k++;
3712 offace += le16_to_cpu(pace->size);
3715 * Create world perms if none (both lists)
3717 for (i=0; i<2; i++)
3718 if ((genericinh || !i)
3719 && !(ctx[i].tagsset & POSIX_ACL_OTHER)) {
3720 if (i)
3721 pxace = &pxdesc->acl.ace[--l];
3722 else
3723 pxace = &pxdesc->acl.ace[k++];
3724 pxace->tag = POSIX_ACL_OTHER;
3725 pxace->id = -1;
3726 pxace->perms = 0;
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
3736 for (i=0; i<2; i++)
3737 if (!(ctx[i].tagsset & POSIX_ACL_USER_OBJ)
3738 && (ctx[i].tagsset & POSIX_ACL_OTHER)) {
3739 if (i)
3740 pxace = &pxdesc->acl.ace[--l];
3741 else
3742 pxace = &pxdesc->acl.ace[k++];
3743 pxace->tag = POSIX_ACL_USER_OBJ;
3744 pxace->id = -1;
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
3751 for (i=0; i<2; i++)
3752 if ((ctx[i].tagsset & POSIX_ACL_OTHER)
3753 && !(ctx[i].tagsset & POSIX_ACL_GROUP_OBJ)) {
3754 if (i)
3755 pxace = &pxdesc->acl.ace[--l];
3756 else
3757 pxace = &pxdesc->acl.ace[k++];
3758 pxace->tag = POSIX_ACL_GROUP_OBJ;
3759 pxace->id = -1;
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;
3779 k++;
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;
3797 l--;
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)
3809 for (i=0; i<2; i++)
3810 if ((ctx[i].tagsset & (POSIX_ACL_USER | POSIX_ACL_GROUP))
3811 && !(ctx[i].tagsset & POSIX_ACL_MASK)) {
3812 if (i)
3813 pxace = &pxdesc->acl.ace[--l];
3814 else
3815 pxace = &pxdesc->acl.ace[k++];
3816 pxace->tag = POSIX_ACL_MASK;
3817 pxace->id = -1;
3818 pxace->perms = POSIX_PERM_DENIAL;
3819 ctx[i].tagsset |= POSIX_ACL_MASK;
3822 if (k > l) {
3823 ntfs_log_error("Posix descriptor is longer than expected\n");
3824 errno = EIO;
3825 free(pxdesc);
3826 pxdesc = (struct POSIX_SECURITY*)NULL;
3827 } else {
3828 pxdesc->acccnt = k;
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);
3836 if (adminowns) {
3837 k = norm_ownadmin_permissions_posix(pxdesc,
3838 0, pxdesc->acccnt, 0);
3839 pxdesc->acccnt = k;
3840 l = norm_ownadmin_permissions_posix(pxdesc,
3841 pxdesc->firstdef, pxdesc->defcnt, k);
3842 pxdesc->firstdef = k;
3843 pxdesc->defcnt = l;
3844 } else {
3845 k = norm_std_permissions_posix(pxdesc,groupowns,
3846 0, pxdesc->acccnt, 0);
3847 pxdesc->acccnt = k;
3848 l = norm_std_permissions_posix(pxdesc,groupowns,
3849 pxdesc->firstdef, pxdesc->defcnt, k);
3850 pxdesc->firstdef = k;
3851 pxdesc->defcnt = l;
3854 if (pxdesc && !ntfs_valid_posix(pxdesc)) {
3855 ntfs_log_error("Invalid Posix descriptor built\n");
3856 errno = EIO;
3857 free(pxdesc);
3858 pxdesc = (struct POSIX_SECURITY*)NULL;
3860 return (pxdesc);
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;
3875 int perm;
3876 BOOL adminowns;
3877 BOOL groupowns;
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);
3883 if (adminowns)
3884 perm = build_ownadmin_permissions(securattr, usid, gsid, isdir);
3885 else
3886 if (groupowns)
3887 perm = build_owngrp_permissions(securattr, usid, isdir);
3888 else
3889 perm = build_std_permissions(securattr, usid, gsid, isdir);
3890 return (perm);
3894 * The following must be in some library...
3897 static unsigned long atoul(const char *p)
3898 { /* must be somewhere ! */
3899 unsigned long v;
3901 v = 0;
3902 while ((*p >= '0') && (*p <= '9'))
3903 v = v * 10 + (*p++) - '0';
3904 return (v);
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)
3915 SID *sid;
3916 int cnt;
3917 BIGSID bigsid;
3918 SID *bsid;
3919 u32 auth;
3920 const char *p;
3922 sid = (SID*) NULL;
3923 if (!strncmp(sidstr, "S-1-", 4)) {
3924 bsid = (SID*)&bigsid;
3925 bsid->revision = SID_REVISION;
3926 p = &sidstr[4];
3927 auth = atoul(p);
3928 bsid->identifier_authority.high_part = const_cpu_to_be16(0);
3929 bsid->identifier_authority.low_part = cpu_to_be32(auth);
3930 cnt = 0;
3931 p = strchr(p, '-');
3932 while (p && (cnt < 8)) {
3933 p++;
3934 auth = atoul(p);
3935 bsid->sub_authority[cnt] = cpu_to_le32(auth);
3936 p = strchr(p, '-');
3937 cnt++;
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);
3942 if (sid)
3943 memcpy(sid, bsid, 4 * cnt + 8);
3946 return (sid);
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, ...)
3961 va_list args;
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,
3968 format, args);
3969 #else
3970 vfprintf(stderr,format,args);
3971 #endif
3972 va_end(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)
3987 int src;
3988 int dst;
3989 char *p;
3990 char *q;
3991 char *pu;
3992 char *pg;
3993 int gotend;
3994 struct MAPLIST *item;
3996 src = *psrc;
3997 dst = 0;
3998 /* allocate and get a full line */
3999 item = (struct MAPLIST*)ntfs_malloc(sizeof(struct MAPLIST));
4000 if (item) {
4001 do {
4002 gotend = 0;
4003 while ((src < *psize)
4004 && (buf[src] != '\n')) {
4005 if (dst < LINESZ)
4006 item->maptext[dst++] = buf[src];
4007 src++;
4009 if (src >= *psize) {
4010 *poffs += *psize;
4011 *psize = reader(fileid, buf, (size_t)BUFSZ, *poffs);
4012 src = 0;
4013 } else {
4014 gotend = 1;
4015 src++;
4016 item->maptext[dst] = '\0';
4017 dst = 0;
4019 } while (*psize && ((item->maptext[0] == '#') || !gotend));
4020 if (gotend) {
4021 pu = pg = (char*)NULL;
4022 /* decompose into uid, gid and sid */
4023 p = item->maptext;
4024 item->uidstr = item->maptext;
4025 item->gidstr = strchr(item->uidstr, ':');
4026 if (item->gidstr) {
4027 pu = item->gidstr++;
4028 item->sidstr = strchr(item->gidstr, ':');
4029 if (item->sidstr) {
4030 pg = item->sidstr++;
4031 q = strchr(item->sidstr, ':');
4032 if (q) *q = 0;
4035 if (pu && pg)
4036 *pu = *pg = '\0';
4037 else {
4038 log_early_error("Bad mapping item \"%s\"\n",
4039 item->maptext);
4040 free(item);
4041 item = (struct MAPLIST*)NULL;
4043 } else {
4044 free(item); /* free unused item */
4045 item = (struct MAPLIST*)NULL;
4048 *psrc = src;
4049 return (item);
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)
4069 char buf[BUFSZ];
4070 struct MAPLIST *item;
4071 struct MAPLIST *firstitem;
4072 struct MAPLIST *lastitem;
4073 int src;
4074 off_t offs;
4075 s64 size;
4077 firstitem = (struct MAPLIST*)NULL;
4078 lastitem = (struct MAPLIST*)NULL;
4079 offs = 0;
4080 size = reader(fileid, buf, (size_t)BUFSZ, (off_t)0);
4081 if (size > 0) {
4082 src = 0;
4083 do {
4084 item = getmappingitem(reader, fileid, &offs,
4085 buf, &src, &size);
4086 if (item) {
4087 item->next = (struct MAPLIST*)NULL;
4088 if (lastitem)
4089 lastitem->next = item;
4090 else
4091 firstitem = item;
4092 lastitem = item;
4094 } while (item);
4096 return (firstitem);
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;
4116 if (!group)
4117 free(user->sid);
4118 /* free group list if any */
4119 if (user->grcnt)
4120 free(user->groups);
4121 /* unchain item and free */
4122 mapping[MAPUSERS] = user->next;
4123 free(user);
4125 /* free group mappings */
4126 while (mapping[MAPGROUPS]) {
4127 group = mapping[MAPGROUPS];
4128 free(group->sid);
4129 /* unchain item and free */
4130 mapping[MAPGROUPS] = group->next;
4131 free(group);
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;
4151 struct passwd *pwd;
4152 SID *sid;
4153 int uid;
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);
4160 else {
4161 uid = 0;
4162 if (item->uidstr[0]) {
4163 pwd = getpwnam(item->uidstr);
4164 if (pwd)
4165 uid = pwd->pw_uid;
4166 else
4167 log_early_error("Invalid user \"%s\"\n",
4168 item->uidstr);
4172 * Records with no uid and no gid are inserted
4173 * to define the implicit mapping pattern
4175 if (uid
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",
4181 item->sidstr);
4182 sid = (SID*)NULL;
4184 if (sid) {
4185 mapping =
4186 (struct MAPPING*)
4187 ntfs_malloc(sizeof(struct MAPPING));
4188 if (mapping) {
4189 mapping->sid = sid;
4190 mapping->xid = uid;
4191 mapping->grcnt = 0;
4192 mapping->next = (struct MAPPING*)NULL;
4193 if (lastmapping)
4194 lastmapping->next = mapping;
4195 else
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;
4223 struct group *grp;
4224 BOOL secondstep;
4225 BOOL ok;
4226 int step;
4227 SID *sid;
4228 int gid;
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);
4240 else {
4241 gid = 0;
4242 if (item->gidstr[0]) {
4243 grp = getgrnam(item->gidstr);
4244 if (grp)
4245 gid = grp->gr_gid;
4246 else
4247 log_early_error("Invalid group \"%s\"\n",
4248 item->gidstr);
4252 * Records with no uid and no gid are inserted in the
4253 * second step to define the implicit mapping pattern
4255 if (ok
4256 && (gid
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 */
4262 sid = (SID*)NULL;
4264 if (sid) {
4265 mapping = (struct MAPPING*)
4266 ntfs_malloc(sizeof(struct MAPPING));
4267 if (mapping) {
4268 mapping->sid = sid;
4269 mapping->xid = gid;
4270 mapping->grcnt = 0;
4271 mapping->next = (struct MAPPING*)NULL;
4272 if (lastmapping)
4273 lastmapping->next = mapping;
4274 else
4275 firstmapping = mapping;
4276 lastmapping = mapping;
4282 return (firstmapping);