Allow IPv6 address entry in tools>ping - Loosens valid character check
[tomato/davidwu.git] / release / src / router / ntfs-3g / libntfs-3g / acls.c
blob7d162105e50946dd3ae461979ee1d9b9faf3575a
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-2012 Jean-Pierre Andre
9 * This program/include file is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as published
11 * by the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program/include file is distributed in the hope that it will be
15 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
16 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program (in the main directory of the NTFS-3G
21 * distribution in the file COPYING); if not, write to the Free Software
22 * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
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_SYS_STAT_H
44 #include <sys/stat.h>
45 #endif
46 #ifdef HAVE_FCNTL_H
47 #include <fcntl.h>
48 #endif
49 #ifdef HAVE_SYSLOG_H
50 #include <syslog.h>
51 #endif
52 #include <unistd.h>
53 #include <pwd.h>
54 #include <grp.h>
56 #include "types.h"
57 #include "layout.h"
58 #include "security.h"
59 #include "acls.h"
60 #include "misc.h"
61 #else
64 * integration into secaudit, check whether Win32,
65 * may have to be adapted to compiler or something else
68 #ifndef WIN32
69 #if defined(__WIN32) | defined(__WIN32__) | defined(WNSC)
70 #define WIN32 1
71 #endif
72 #endif
74 #include <stdio.h>
75 #include <time.h>
76 #include <string.h>
77 #include <stdlib.h>
78 #include <stdarg.h>
79 #include <sys/types.h>
80 #include <errno.h>
83 * integration into secaudit/Win32
85 #ifdef WIN32
86 #include <fcntl.h>
87 #include <windows.h>
88 #define __LITTLE_ENDIAN 1234
89 #define __BYTE_ORDER __LITTLE_ENDIAN
90 #else
92 * integration into secaudit/STSC
94 #ifdef STSC
95 #include <stat.h>
96 #undef __BYTE_ORDER
97 #define __BYTE_ORDER __BIG_ENDIAN
98 #else
100 * integration into secaudit/Linux
102 #include <sys/stat.h>
103 #include <endian.h>
104 #include <unistd.h>
105 #include <dlfcn.h>
106 #endif /* STSC */
107 #endif /* WIN32 */
108 #include "secaudit.h"
109 #endif /* HAVE_CONFIG_H */
112 * A few useful constants
116 * null SID (S-1-0-0)
119 static const char nullsidbytes[] = {
120 1, /* revision */
121 1, /* auth count */
122 0, 0, 0, 0, 0, 0, /* base */
123 0, 0, 0, 0 /* 1st level */
126 static const SID *nullsid = (const SID*)nullsidbytes;
129 * SID for world (S-1-1-0)
132 static const char worldsidbytes[] = {
133 1, /* revision */
134 1, /* auth count */
135 0, 0, 0, 0, 0, 1, /* base */
136 0, 0, 0, 0 /* 1st level */
140 * SID for authenticated user (S-1-5-11)
143 static const char authsidbytes[] = {
144 1, /* revision */
145 1, /* auth count */
146 0, 0, 0, 0, 0, 5, /* base */
147 11, 0, 0, 0 /* 1st level */
150 static const SID *authsid = (const SID*)authsidbytes;
152 const SID *worldsid = (const SID*)worldsidbytes;
155 * SID for administrator
158 static const char adminsidbytes[] = {
159 1, /* revision */
160 2, /* auth count */
161 0, 0, 0, 0, 0, 5, /* base */
162 32, 0, 0, 0, /* 1st level */
163 32, 2, 0, 0 /* 2nd level */
166 const SID *adminsid = (const SID*)adminsidbytes;
169 * SID for system
172 static const char systemsidbytes[] = {
173 1, /* revision */
174 1, /* auth count */
175 0, 0, 0, 0, 0, 5, /* base */
176 18, 0, 0, 0 /* 1st level */
179 static const SID *systemsid = (const SID*)systemsidbytes;
182 * SID for generic creator-owner
183 * S-1-3-0
186 static const char ownersidbytes[] = {
187 1, /* revision */
188 1, /* auth count */
189 0, 0, 0, 0, 0, 3, /* base */
190 0, 0, 0, 0 /* 1st level */
193 static const SID *ownersid = (const SID*)ownersidbytes;
196 * SID for generic creator-group
197 * S-1-3-1
200 static const char groupsidbytes[] = {
201 1, /* revision */
202 1, /* auth count */
203 0, 0, 0, 0, 0, 3, /* base */
204 1, 0, 0, 0 /* 1st level */
207 static const SID *groupsid = (const SID*)groupsidbytes;
210 * Determine the size of a SID
213 int ntfs_sid_size(const SID * sid)
215 return (sid->sub_authority_count * 4 + 8);
219 * Test whether two SID are equal
222 BOOL ntfs_same_sid(const SID *first, const SID *second)
224 int size;
226 size = ntfs_sid_size(first);
227 return ((ntfs_sid_size(second) == size)
228 && !memcmp(first, second, size));
232 * Test whether a SID means "world user"
233 * Local users group also recognized as world
236 static int is_world_sid(const SID * usid)
238 return (
239 /* check whether S-1-1-0 : world */
240 ((usid->sub_authority_count == 1)
241 && (usid->identifier_authority.high_part == const_cpu_to_be16(0))
242 && (usid->identifier_authority.low_part == const_cpu_to_be32(1))
243 && (usid->sub_authority[0] == const_cpu_to_le32(0)))
245 /* check whether S-1-5-32-545 : local user */
246 || ((usid->sub_authority_count == 2)
247 && (usid->identifier_authority.high_part == const_cpu_to_be16(0))
248 && (usid->identifier_authority.low_part == const_cpu_to_be32(5))
249 && (usid->sub_authority[0] == const_cpu_to_le32(32))
250 && (usid->sub_authority[1] == const_cpu_to_le32(545)))
252 /* check whether S-1-5-11 : authenticated user */
253 || ((usid->sub_authority_count == 1)
254 && (usid->identifier_authority.high_part == const_cpu_to_be16(0))
255 && (usid->identifier_authority.low_part == const_cpu_to_be32(5))
256 && (usid->sub_authority[0] == const_cpu_to_le32(11)))
261 * Test whether a SID means "some user (or group)"
262 * Currently we only check for S-1-5-21... but we should
263 * probably test for other configurations
266 BOOL ntfs_is_user_sid(const SID *usid)
268 return ((usid->sub_authority_count == 5)
269 && (usid->identifier_authority.high_part == const_cpu_to_be16(0))
270 && (usid->identifier_authority.low_part == const_cpu_to_be32(5))
271 && (usid->sub_authority[0] == const_cpu_to_le32(21)));
275 * Determine the size of a security attribute
276 * whatever the order of fields
279 unsigned int ntfs_attr_size(const char *attr)
281 const SECURITY_DESCRIPTOR_RELATIVE *phead;
282 const ACL *pdacl;
283 const ACL *psacl;
284 const SID *psid;
285 unsigned int offdacl;
286 unsigned int offsacl;
287 unsigned int offowner;
288 unsigned int offgroup;
289 unsigned int endsid;
290 unsigned int endacl;
291 unsigned int attrsz;
293 phead = (const SECURITY_DESCRIPTOR_RELATIVE*)attr;
295 * First check group, which is the last field in all descriptors
296 * we build, and in most descriptors built by Windows
298 attrsz = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
299 offgroup = le32_to_cpu(phead->group);
300 if (offgroup >= attrsz) {
301 /* find end of GSID */
302 psid = (const SID*)&attr[offgroup];
303 endsid = offgroup + ntfs_sid_size(psid);
304 if (endsid > attrsz) attrsz = endsid;
306 offowner = le32_to_cpu(phead->owner);
307 if (offowner >= attrsz) {
308 /* find end of USID */
309 psid = (const SID*)&attr[offowner];
310 endsid = offowner + ntfs_sid_size(psid);
311 attrsz = endsid;
313 offsacl = le32_to_cpu(phead->sacl);
314 if (offsacl >= attrsz) {
315 /* find end of SACL */
316 psacl = (const ACL*)&attr[offsacl];
317 endacl = offsacl + le16_to_cpu(psacl->size);
318 if (endacl > attrsz)
319 attrsz = endacl;
323 /* find end of DACL */
324 offdacl = le32_to_cpu(phead->dacl);
325 if (offdacl >= attrsz) {
326 pdacl = (const ACL*)&attr[offdacl];
327 endacl = offdacl + le16_to_cpu(pdacl->size);
328 if (endacl > attrsz)
329 attrsz = endacl;
331 return (attrsz);
335 * Do sanity checks on a SID read from storage
336 * (just check revision and number of authorities)
339 BOOL ntfs_valid_sid(const SID *sid)
341 return ((sid->revision == SID_REVISION)
342 && (sid->sub_authority_count >= 1)
343 && (sid->sub_authority_count <= 8));
347 * Check whether a SID is acceptable for an implicit
348 * mapping pattern.
349 * It should have been already checked it is a valid user SID.
351 * The last authority reference has to be >= 1000 (Windows usage)
352 * and <= 0x7fffffff, so that 30 bits from a uid and 30 more bits
353 * from a gid an be inserted with no overflow.
356 BOOL ntfs_valid_pattern(const SID *sid)
358 int cnt;
359 u32 auth;
360 le32 leauth;
362 cnt = sid->sub_authority_count;
363 leauth = sid->sub_authority[cnt-1];
364 auth = le32_to_cpu(leauth);
365 return ((auth >= 1000) && (auth <= 0x7fffffff));
369 * Compute the uid or gid associated to a SID
370 * through an implicit mapping
372 * Returns 0 (root) if it does not match pattern
375 static u32 findimplicit(const SID *xsid, const SID *pattern, int parity)
377 BIGSID defsid;
378 SID *psid;
379 u32 xid; /* uid or gid */
380 int cnt;
381 u32 carry;
382 le32 leauth;
383 u32 uauth;
384 u32 xlast;
385 u32 rlast;
387 memcpy(&defsid,pattern,ntfs_sid_size(pattern));
388 psid = (SID*)&defsid;
389 cnt = psid->sub_authority_count;
390 xid = 0;
391 if (xsid->sub_authority_count == cnt) {
392 psid->sub_authority[cnt-1] = xsid->sub_authority[cnt-1];
393 leauth = xsid->sub_authority[cnt-1];
394 xlast = le32_to_cpu(leauth);
395 leauth = pattern->sub_authority[cnt-1];
396 rlast = le32_to_cpu(leauth);
398 if ((xlast > rlast) && !((xlast ^ rlast ^ parity) & 1)) {
399 /* direct check for basic situation */
400 if (ntfs_same_sid(psid,xsid))
401 xid = ((xlast - rlast) >> 1) & 0x3fffffff;
402 else {
404 * check whether part of mapping had to be
405 * recorded in a higher level authority
407 carry = 1;
408 do {
409 leauth = psid->sub_authority[cnt-2];
410 uauth = le32_to_cpu(leauth) + 1;
411 psid->sub_authority[cnt-2]
412 = cpu_to_le32(uauth);
413 } while (!ntfs_same_sid(psid,xsid)
414 && (++carry < 4));
415 if (carry < 4)
416 xid = (((xlast - rlast) >> 1)
417 & 0x3fffffff) | (carry << 30);
421 return (xid);
425 * Find usid mapped to a Linux user
426 * Returns NULL if not found
429 const SID *ntfs_find_usid(const struct MAPPING* usermapping,
430 uid_t uid, SID *defusid)
432 const struct MAPPING *p;
433 const SID *sid;
434 le32 leauth;
435 u32 uauth;
436 int cnt;
438 if (!uid)
439 sid = adminsid;
440 else {
441 p = usermapping;
442 while (p && p->xid && ((uid_t)p->xid != uid))
443 p = p->next;
444 if (p && !p->xid) {
446 * default pattern has been reached :
447 * build an implicit SID according to pattern
448 * (the pattern format was checked while reading
449 * the mapping file)
451 memcpy(defusid, p->sid, ntfs_sid_size(p->sid));
452 cnt = defusid->sub_authority_count;
453 leauth = defusid->sub_authority[cnt-1];
454 uauth = le32_to_cpu(leauth) + 2*(uid & 0x3fffffff);
455 defusid->sub_authority[cnt-1] = cpu_to_le32(uauth);
456 if (uid & 0xc0000000) {
457 leauth = defusid->sub_authority[cnt-2];
458 uauth = le32_to_cpu(leauth) + ((uid >> 30) & 3);
459 defusid->sub_authority[cnt-2] = cpu_to_le32(uauth);
461 sid = defusid;
462 } else
463 sid = (p ? p->sid : (const SID*)NULL);
465 return (sid);
469 * Find Linux group mapped to a gsid
470 * Returns 0 (root) if not found
473 const SID *ntfs_find_gsid(const struct MAPPING* groupmapping,
474 gid_t gid, SID *defgsid)
476 const struct MAPPING *p;
477 const SID *sid;
478 le32 leauth;
479 u32 uauth;
480 int cnt;
482 if (!gid)
483 sid = adminsid;
484 else {
485 p = groupmapping;
486 while (p && p->xid && ((gid_t)p->xid != gid))
487 p = p->next;
488 if (p && !p->xid) {
490 * default pattern has been reached :
491 * build an implicit SID according to pattern
492 * (the pattern format was checked while reading
493 * the mapping file)
495 memcpy(defgsid, p->sid, ntfs_sid_size(p->sid));
496 cnt = defgsid->sub_authority_count;
497 leauth = defgsid->sub_authority[cnt-1];
498 uauth = le32_to_cpu(leauth) + 2*(gid & 0x3fffffff) + 1;
499 defgsid->sub_authority[cnt-1] = cpu_to_le32(uauth);
500 if (gid & 0xc0000000) {
501 leauth = defgsid->sub_authority[cnt-2];
502 uauth = le32_to_cpu(leauth) + ((gid >> 30) & 3);
503 defgsid->sub_authority[cnt-2] = cpu_to_le32(uauth);
505 sid = defgsid;
506 } else
507 sid = (p ? p->sid : (const SID*)NULL);
509 return (sid);
513 * Find Linux owner mapped to a usid
514 * Returns 0 (root) if not found
517 uid_t ntfs_find_user(const struct MAPPING* usermapping, const SID *usid)
519 uid_t uid;
520 const struct MAPPING *p;
522 p = usermapping;
523 while (p && p->xid && !ntfs_same_sid(usid, p->sid))
524 p = p->next;
525 if (p && !p->xid)
527 * No explicit mapping found, try implicit mapping
529 uid = findimplicit(usid,p->sid,0);
530 else
531 uid = (p ? p->xid : 0);
532 return (uid);
536 * Find Linux group mapped to a gsid
537 * Returns 0 (root) if not found
540 gid_t ntfs_find_group(const struct MAPPING* groupmapping, const SID * gsid)
542 gid_t gid;
543 const struct MAPPING *p;
545 p = groupmapping;
546 while (p && p->xid && !ntfs_same_sid(gsid, p->sid))
547 p = p->next;
548 if (p && !p->xid)
550 * No explicit mapping found, try implicit mapping
552 gid = findimplicit(gsid,p->sid,1);
553 else
554 gid = (p ? p->xid : 0);
555 return (gid);
559 * Check the validity of the ACEs in a DACL or SACL
562 static BOOL valid_acl(const ACL *pacl, unsigned int end)
564 const ACCESS_ALLOWED_ACE *pace;
565 unsigned int offace;
566 unsigned int acecnt;
567 unsigned int acesz;
568 unsigned int nace;
569 BOOL ok;
571 ok = TRUE;
572 acecnt = le16_to_cpu(pacl->ace_count);
573 offace = sizeof(ACL);
574 for (nace = 0; (nace < acecnt) && ok; nace++) {
575 /* be sure the beginning is within range */
576 if ((offace + sizeof(ACCESS_ALLOWED_ACE)) > end)
577 ok = FALSE;
578 else {
579 pace = (const ACCESS_ALLOWED_ACE*)
580 &((const char*)pacl)[offace];
581 acesz = le16_to_cpu(pace->size);
582 if (((offace + acesz) > end)
583 || !ntfs_valid_sid(&pace->sid)
584 || ((ntfs_sid_size(&pace->sid) + 8) != (int)acesz))
585 ok = FALSE;
586 offace += acesz;
589 return (ok);
593 * Do sanity checks on security descriptors read from storage
594 * basically, we make sure that every field holds within
595 * allocated storage
596 * Should not be called with a NULL argument
597 * returns TRUE if considered safe
598 * if not, error should be logged by caller
601 BOOL ntfs_valid_descr(const char *securattr, unsigned int attrsz)
603 const SECURITY_DESCRIPTOR_RELATIVE *phead;
604 const ACL *pdacl;
605 const ACL *psacl;
606 unsigned int offdacl;
607 unsigned int offsacl;
608 unsigned int offowner;
609 unsigned int offgroup;
610 BOOL ok;
612 ok = TRUE;
615 * first check overall size if within allocation range
616 * and a DACL is present
617 * and owner and group SID are valid
620 phead = (const SECURITY_DESCRIPTOR_RELATIVE*)securattr;
621 offdacl = le32_to_cpu(phead->dacl);
622 offsacl = le32_to_cpu(phead->sacl);
623 offowner = le32_to_cpu(phead->owner);
624 offgroup = le32_to_cpu(phead->group);
625 pdacl = (const ACL*)&securattr[offdacl];
626 psacl = (const ACL*)&securattr[offsacl];
629 * size check occurs before the above pointers are used
631 * "DR Watson" standard directory on WinXP has an
632 * old revision and no DACL though SE_DACL_PRESENT is set
634 if ((attrsz >= sizeof(SECURITY_DESCRIPTOR_RELATIVE))
635 && (phead->revision == SECURITY_DESCRIPTOR_REVISION)
636 && (offowner >= sizeof(SECURITY_DESCRIPTOR_RELATIVE))
637 && ((offowner + 2) < attrsz)
638 && (offgroup >= sizeof(SECURITY_DESCRIPTOR_RELATIVE))
639 && ((offgroup + 2) < attrsz)
640 && (!offdacl
641 || ((offdacl >= sizeof(SECURITY_DESCRIPTOR_RELATIVE))
642 && (offdacl+sizeof(ACL) < attrsz)))
643 && (!offsacl
644 || ((offsacl >= sizeof(SECURITY_DESCRIPTOR_RELATIVE))
645 && (offsacl+sizeof(ACL) <= attrsz)))
646 && !(phead->owner & const_cpu_to_le32(3))
647 && !(phead->group & const_cpu_to_le32(3))
648 && !(phead->dacl & const_cpu_to_le32(3))
649 && !(phead->sacl & const_cpu_to_le32(3))
650 && (ntfs_attr_size(securattr) <= attrsz)
651 && ntfs_valid_sid((const SID*)&securattr[offowner])
652 && ntfs_valid_sid((const SID*)&securattr[offgroup])
654 * if there is an ACL, as indicated by offdacl,
655 * require SE_DACL_PRESENT
656 * but "Dr Watson" has SE_DACL_PRESENT though no DACL
658 && (!offdacl
659 || ((phead->control & SE_DACL_PRESENT)
660 && ((pdacl->revision == ACL_REVISION)
661 || (pdacl->revision == ACL_REVISION_DS))))
662 /* same for SACL */
663 && (!offsacl
664 || ((phead->control & SE_SACL_PRESENT)
665 && ((psacl->revision == ACL_REVISION)
666 || (psacl->revision == ACL_REVISION_DS))))) {
668 * Check the DACL and SACL if present
670 if ((offdacl && !valid_acl(pdacl,attrsz - offdacl))
671 || (offsacl && !valid_acl(psacl,attrsz - offsacl)))
672 ok = FALSE;
673 } else
674 ok = FALSE;
675 return (ok);
679 * Copy the inheritable parts of an ACL
681 * Returns the size of the new ACL
682 * or zero if nothing is inheritable
685 int ntfs_inherit_acl(const ACL *oldacl, ACL *newacl,
686 const SID *usid, const SID *gsid, BOOL fordir,
687 le16 inherited)
689 unsigned int src;
690 unsigned int dst;
691 int oldcnt;
692 int newcnt;
693 unsigned int selection;
694 int nace;
695 int acesz;
696 int usidsz;
697 int gsidsz;
698 const ACCESS_ALLOWED_ACE *poldace;
699 ACCESS_ALLOWED_ACE *pnewace;
700 ACCESS_ALLOWED_ACE *pauthace;
702 pauthace = (ACCESS_ALLOWED_ACE*)NULL;
703 usidsz = ntfs_sid_size(usid);
704 gsidsz = ntfs_sid_size(gsid);
706 /* ACL header */
708 newacl->revision = ACL_REVISION;
709 newacl->alignment1 = 0;
710 newacl->alignment2 = const_cpu_to_le16(0);
711 src = dst = sizeof(ACL);
713 selection = (fordir ? CONTAINER_INHERIT_ACE : OBJECT_INHERIT_ACE);
714 newcnt = 0;
715 oldcnt = le16_to_cpu(oldacl->ace_count);
716 for (nace = 0; nace < oldcnt; nace++) {
717 poldace = (const ACCESS_ALLOWED_ACE*)((const char*)oldacl + src);
718 acesz = le16_to_cpu(poldace->size);
719 src += acesz;
721 * Inheritance for access, unless this is inheriting
722 * an inherited ACL to a directory.
724 if ((poldace->flags & selection)
725 && !(fordir && inherited)
726 && !ntfs_same_sid(&poldace->sid, ownersid)
727 && !ntfs_same_sid(&poldace->sid, groupsid)) {
728 pnewace = (ACCESS_ALLOWED_ACE*)
729 ((char*)newacl + dst);
730 memcpy(pnewace,poldace,acesz);
731 /* reencode GENERIC_ALL */
732 if (pnewace->mask & GENERIC_ALL) {
733 pnewace->mask &= ~GENERIC_ALL;
734 if (fordir)
735 pnewace->mask |= OWNER_RIGHTS
736 | DIR_READ
737 | DIR_WRITE
738 | DIR_EXEC;
739 else
741 * The last flag is not defined for a file,
742 * however Windows sets it, so do the same
744 pnewace->mask |= OWNER_RIGHTS
745 | FILE_READ
746 | FILE_WRITE
747 | FILE_EXEC
748 | cpu_to_le32(0x40);
750 /* reencode GENERIC_READ (+ EXECUTE) */
751 if (pnewace->mask & GENERIC_READ) {
752 if (fordir)
753 pnewace->mask |= OWNER_RIGHTS
754 | DIR_READ
755 | DIR_EXEC;
756 else
757 pnewace->mask |= OWNER_RIGHTS
758 | FILE_READ
759 | FILE_EXEC;
760 pnewace->mask &= ~(GENERIC_READ
761 | GENERIC_EXECUTE
762 | WRITE_DAC
763 | WRITE_OWNER
764 | DELETE | FILE_WRITE_EA
765 | FILE_WRITE_ATTRIBUTES);
767 /* reencode GENERIC_WRITE */
768 if (pnewace->mask & GENERIC_WRITE) {
769 if (fordir)
770 pnewace->mask |= OWNER_RIGHTS
771 | DIR_WRITE;
772 else
773 pnewace->mask |= OWNER_RIGHTS
774 | FILE_WRITE;
775 pnewace->mask &= ~(GENERIC_WRITE
776 | WRITE_DAC
777 | WRITE_OWNER
778 | FILE_DELETE_CHILD);
780 /* remove inheritance flags */
781 pnewace->flags &= ~(OBJECT_INHERIT_ACE
782 | CONTAINER_INHERIT_ACE
783 | INHERIT_ONLY_ACE);
785 * Group similar ACE for authenticated users
786 * (should probably be done for other SIDs)
788 if (!fordir
789 && (poldace->type == ACCESS_ALLOWED_ACE_TYPE)
790 && ntfs_same_sid(&poldace->sid, authsid)) {
791 if (pauthace) {
792 pauthace->flags |= pnewace->flags;
793 pauthace->mask |= pnewace->mask;
794 } else {
795 pauthace = pnewace;
796 if (inherited)
797 pnewace->flags |= INHERITED_ACE;
798 dst += acesz;
799 newcnt++;
801 } else {
802 if (inherited)
803 pnewace->flags |= INHERITED_ACE;
804 dst += acesz;
805 newcnt++;
809 * Inheritance for access, specific to
810 * creator-owner (and creator-group)
812 if (fordir || !inherited
813 || (poldace->flags
814 & (CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE))) {
815 pnewace = (ACCESS_ALLOWED_ACE*)
816 ((char*)newacl + dst);
817 memcpy(pnewace,poldace,acesz);
819 * Replace generic creator-owner and
820 * creator-group by owner and group
821 * (but keep for further inheritance)
823 if (ntfs_same_sid(&pnewace->sid, ownersid)) {
824 memcpy(&pnewace->sid, usid, usidsz);
825 pnewace->size = cpu_to_le16(usidsz + 8);
826 /* remove inheritance flags */
827 pnewace->flags &= ~(OBJECT_INHERIT_ACE
828 | CONTAINER_INHERIT_ACE
829 | INHERIT_ONLY_ACE);
830 if (inherited)
831 pnewace->flags |= INHERITED_ACE;
832 dst += usidsz + 8;
833 newcnt++;
835 if (ntfs_same_sid(&pnewace->sid, groupsid)) {
836 memcpy(&pnewace->sid, gsid, gsidsz);
837 pnewace->size = cpu_to_le16(gsidsz + 8);
838 /* remove inheritance flags */
839 pnewace->flags &= ~(OBJECT_INHERIT_ACE
840 | CONTAINER_INHERIT_ACE
841 | INHERIT_ONLY_ACE);
842 if (inherited)
843 pnewace->flags |= INHERITED_ACE;
844 dst += gsidsz + 8;
845 newcnt++;
849 /* inheritance for further inheritance */
850 if (fordir
851 && (poldace->flags
852 & (CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE))) {
853 pnewace = (ACCESS_ALLOWED_ACE*)
854 ((char*)newacl + dst);
855 memcpy(pnewace,poldace,acesz);
856 if (inherited)
857 pnewace->flags |= INHERITED_ACE;
858 dst += acesz;
859 newcnt++;
863 * Adjust header if something was inherited
865 if (dst > sizeof(ACL)) {
866 newacl->ace_count = cpu_to_le16(newcnt);
867 newacl->size = cpu_to_le16(dst);
868 } else
869 dst = 0;
870 return (dst);
873 #if POSIXACLS
876 * Do sanity checks on a Posix descriptor
877 * Should not be called with a NULL argument
878 * returns TRUE if considered safe
879 * if not, error should be logged by caller
882 BOOL ntfs_valid_posix(const struct POSIX_SECURITY *pxdesc)
884 const struct POSIX_ACL *pacl;
885 int i;
886 BOOL ok;
887 u16 tag;
888 u32 id;
889 int perms;
890 struct {
891 u16 previous;
892 u32 previousid;
893 u16 tagsset;
894 mode_t mode;
895 int owners;
896 int groups;
897 int others;
898 } checks[2], *pchk;
900 for (i=0; i<2; i++) {
901 checks[i].mode = 0;
902 checks[i].tagsset = 0;
903 checks[i].owners = 0;
904 checks[i].groups = 0;
905 checks[i].others = 0;
906 checks[i].previous = 0;
907 checks[i].previousid = 0;
909 ok = TRUE;
910 pacl = &pxdesc->acl;
912 * header (strict for now)
914 if ((pacl->version != POSIX_VERSION)
915 || (pacl->flags != 0)
916 || (pacl->filler != 0))
917 ok = FALSE;
919 * Reject multiple owner, group or other
920 * but do not require them to be present
921 * Also check the ACEs are in correct order
922 * which implies there is no duplicates
924 for (i=0; i<pxdesc->acccnt + pxdesc->defcnt; i++) {
925 if (i >= pxdesc->firstdef)
926 pchk = &checks[1];
927 else
928 pchk = &checks[0];
929 perms = pacl->ace[i].perms;
930 tag = pacl->ace[i].tag;
931 pchk->tagsset |= tag;
932 id = pacl->ace[i].id;
933 if (perms & ~7) ok = FALSE;
934 if ((tag < pchk->previous)
935 || ((tag == pchk->previous)
936 && (id <= pchk->previousid)))
937 ok = FALSE;
938 pchk->previous = tag;
939 pchk->previousid = id;
940 switch (tag) {
941 case POSIX_ACL_USER_OBJ :
942 if (pchk->owners++)
943 ok = FALSE;
944 if (id != (u32)-1)
945 ok = FALSE;
946 pchk->mode |= perms << 6;
947 break;
948 case POSIX_ACL_GROUP_OBJ :
949 if (pchk->groups++)
950 ok = FALSE;
951 if (id != (u32)-1)
952 ok = FALSE;
953 pchk->mode = (pchk->mode & 07707) | (perms << 3);
954 break;
955 case POSIX_ACL_OTHER :
956 if (pchk->others++)
957 ok = FALSE;
958 if (id != (u32)-1)
959 ok = FALSE;
960 pchk->mode |= perms;
961 break;
962 case POSIX_ACL_USER :
963 case POSIX_ACL_GROUP :
964 if (id == (u32)-1)
965 ok = FALSE;
966 break;
967 case POSIX_ACL_MASK :
968 if (id != (u32)-1)
969 ok = FALSE;
970 pchk->mode = (pchk->mode & 07707) | (perms << 3);
971 break;
972 default :
973 ok = FALSE;
974 break;
977 if ((pxdesc->acccnt > 0)
978 && ((checks[0].owners != 1) || (checks[0].groups != 1)
979 || (checks[0].others != 1)))
980 ok = FALSE;
981 /* do not check owner, group or other are present in */
982 /* the default ACL, Windows does not necessarily set them */
983 /* descriptor */
984 if (pxdesc->defcnt && (pxdesc->acccnt > pxdesc->firstdef))
985 ok = FALSE;
986 if ((pxdesc->acccnt < 0) || (pxdesc->defcnt < 0))
987 ok = FALSE;
988 /* check mode, unless null or no tag set */
989 if (pxdesc->mode
990 && checks[0].tagsset
991 && (checks[0].mode != (pxdesc->mode & 0777)))
992 ok = FALSE;
993 /* check tagsset */
994 if (pxdesc->tagsset != checks[0].tagsset)
995 ok = FALSE;
996 return (ok);
1000 * Set standard header data into a Posix ACL
1001 * The mode argument should provide the 3 upper bits of target mode
1004 static mode_t posix_header(struct POSIX_SECURITY *pxdesc, mode_t basemode)
1006 mode_t mode;
1007 u16 tagsset;
1008 struct POSIX_ACE *pace;
1009 int i;
1011 mode = basemode & 07000;
1012 tagsset = 0;
1013 for (i=0; i<pxdesc->acccnt; i++) {
1014 pace = &pxdesc->acl.ace[i];
1015 tagsset |= pace->tag;
1016 switch(pace->tag) {
1017 case POSIX_ACL_USER_OBJ :
1018 mode |= (pace->perms & 7) << 6;
1019 break;
1020 case POSIX_ACL_GROUP_OBJ :
1021 case POSIX_ACL_MASK :
1022 mode = (mode & 07707) | ((pace->perms & 7) << 3);
1023 break;
1024 case POSIX_ACL_OTHER :
1025 mode |= pace->perms & 7;
1026 break;
1027 default :
1028 break;
1031 pxdesc->tagsset = tagsset;
1032 pxdesc->mode = mode;
1033 pxdesc->acl.version = POSIX_VERSION;
1034 pxdesc->acl.flags = 0;
1035 pxdesc->acl.filler = 0;
1036 return (mode);
1040 * Sort ACEs in a Posix ACL
1041 * This is useful for always getting reusable converted ACLs,
1042 * it also helps in merging ACEs.
1043 * Repeated tag+id are allowed and not merged here.
1045 * Tags should be in ascending sequence and for a repeatable tag
1046 * ids should be in ascending sequence.
1049 void ntfs_sort_posix(struct POSIX_SECURITY *pxdesc)
1051 struct POSIX_ACL *pacl;
1052 struct POSIX_ACE ace;
1053 int i;
1054 int offs;
1055 BOOL done;
1056 u16 tag;
1057 u16 previous;
1058 u32 id;
1059 u32 previousid;
1063 * Check sequencing of tag+id in access ACE's
1065 pacl = &pxdesc->acl;
1066 do {
1067 done = TRUE;
1068 previous = pacl->ace[0].tag;
1069 previousid = pacl->ace[0].id;
1070 for (i=1; i<pxdesc->acccnt; i++) {
1071 tag = pacl->ace[i].tag;
1072 id = pacl->ace[i].id;
1074 if ((tag < previous)
1075 || ((tag == previous) && (id < previousid))) {
1076 done = FALSE;
1077 memcpy(&ace,&pacl->ace[i-1],sizeof(struct POSIX_ACE));
1078 memcpy(&pacl->ace[i-1],&pacl->ace[i],sizeof(struct POSIX_ACE));
1079 memcpy(&pacl->ace[i],&ace,sizeof(struct POSIX_ACE));
1080 } else {
1081 previous = tag;
1082 previousid = id;
1085 } while (!done);
1087 * Same for default ACEs
1089 do {
1090 done = TRUE;
1091 if ((pxdesc->defcnt) > 1) {
1092 offs = pxdesc->firstdef;
1093 previous = pacl->ace[offs].tag;
1094 previousid = pacl->ace[offs].id;
1095 for (i=offs+1; i<offs+pxdesc->defcnt; i++) {
1096 tag = pacl->ace[i].tag;
1097 id = pacl->ace[i].id;
1099 if ((tag < previous)
1100 || ((tag == previous) && (id < previousid))) {
1101 done = FALSE;
1102 memcpy(&ace,&pacl->ace[i-1],sizeof(struct POSIX_ACE));
1103 memcpy(&pacl->ace[i-1],&pacl->ace[i],sizeof(struct POSIX_ACE));
1104 memcpy(&pacl->ace[i],&ace,sizeof(struct POSIX_ACE));
1105 } else {
1106 previous = tag;
1107 previousid = id;
1111 } while (!done);
1115 * Merge a new mode into a Posix descriptor
1116 * The Posix descriptor is not reallocated, its size is unchanged
1118 * returns 0 if ok
1121 int ntfs_merge_mode_posix(struct POSIX_SECURITY *pxdesc, mode_t mode)
1123 int i;
1124 BOOL maskfound;
1125 struct POSIX_ACE *pace;
1126 int todo;
1128 maskfound = FALSE;
1129 todo = POSIX_ACL_USER_OBJ | POSIX_ACL_GROUP_OBJ | POSIX_ACL_OTHER;
1130 for (i=pxdesc->acccnt-1; i>=0; i--) {
1131 pace = &pxdesc->acl.ace[i];
1132 switch(pace->tag) {
1133 case POSIX_ACL_USER_OBJ :
1134 pace->perms = (mode >> 6) & 7;
1135 todo &= ~POSIX_ACL_USER_OBJ;
1136 break;
1137 case POSIX_ACL_GROUP_OBJ :
1138 if (!maskfound)
1139 pace->perms = (mode >> 3) & 7;
1140 todo &= ~POSIX_ACL_GROUP_OBJ;
1141 break;
1142 case POSIX_ACL_MASK :
1143 pace->perms = (mode >> 3) & 7;
1144 maskfound = TRUE;
1145 break;
1146 case POSIX_ACL_OTHER :
1147 pace->perms = mode & 7;
1148 todo &= ~POSIX_ACL_OTHER;
1149 break;
1150 default :
1151 break;
1154 pxdesc->mode = mode;
1155 return (todo ? -1 : 0);
1159 * Replace an access or default Posix ACL
1160 * The resulting ACL is checked for validity
1162 * Returns a new ACL or NULL if there is a problem
1165 struct POSIX_SECURITY *ntfs_replace_acl(const struct POSIX_SECURITY *oldpxdesc,
1166 const struct POSIX_ACL *newacl, int count, BOOL deflt)
1168 struct POSIX_SECURITY *newpxdesc;
1169 size_t newsize;
1170 int offset;
1171 int oldoffset;
1172 int i;
1174 if (deflt)
1175 newsize = sizeof(struct POSIX_SECURITY)
1176 + (oldpxdesc->acccnt + count)*sizeof(struct POSIX_ACE);
1177 else
1178 newsize = sizeof(struct POSIX_SECURITY)
1179 + (oldpxdesc->defcnt + count)*sizeof(struct POSIX_ACE);
1180 newpxdesc = (struct POSIX_SECURITY*)malloc(newsize);
1181 if (newpxdesc) {
1182 if (deflt) {
1183 offset = oldpxdesc->acccnt;
1184 newpxdesc->acccnt = oldpxdesc->acccnt;
1185 newpxdesc->defcnt = count;
1186 newpxdesc->firstdef = offset;
1187 /* copy access ACEs */
1188 for (i=0; i<newpxdesc->acccnt; i++)
1189 newpxdesc->acl.ace[i] = oldpxdesc->acl.ace[i];
1190 /* copy default ACEs */
1191 for (i=0; i<count; i++)
1192 newpxdesc->acl.ace[i + offset] = newacl->ace[i];
1193 } else {
1194 offset = count;
1195 newpxdesc->acccnt = count;
1196 newpxdesc->defcnt = oldpxdesc->defcnt;
1197 newpxdesc->firstdef = count;
1198 /* copy access ACEs */
1199 for (i=0; i<count; i++)
1200 newpxdesc->acl.ace[i] = newacl->ace[i];
1201 /* copy default ACEs */
1202 oldoffset = oldpxdesc->firstdef;
1203 for (i=0; i<newpxdesc->defcnt; i++)
1204 newpxdesc->acl.ace[i + offset] = oldpxdesc->acl.ace[i + oldoffset];
1206 /* assume special flags unchanged */
1207 posix_header(newpxdesc, oldpxdesc->mode);
1208 if (!ntfs_valid_posix(newpxdesc)) {
1209 /* do not log, this is an application error */
1210 free(newpxdesc);
1211 newpxdesc = (struct POSIX_SECURITY*)NULL;
1212 errno = EINVAL;
1214 } else
1215 errno = ENOMEM;
1216 return (newpxdesc);
1220 * Build an inherited Posix descriptor from parent
1221 * descriptor (if any) restricted to creation mode
1223 * Returns the inherited descriptor or NULL if there is a problem
1226 struct POSIX_SECURITY *ntfs_build_inherited_posix(
1227 const struct POSIX_SECURITY *pxdesc, mode_t mode,
1228 mode_t mask, BOOL isdir)
1230 struct POSIX_SECURITY *pydesc;
1231 struct POSIX_ACE *pyace;
1232 int count;
1233 int defcnt;
1234 int size;
1235 int i;
1236 s16 tagsset;
1238 if (pxdesc && pxdesc->defcnt) {
1239 if (isdir)
1240 count = 2*pxdesc->defcnt + 3;
1241 else
1242 count = pxdesc->defcnt + 3;
1243 } else
1244 count = 3;
1245 pydesc = (struct POSIX_SECURITY*)malloc(
1246 sizeof(struct POSIX_SECURITY) + count*sizeof(struct POSIX_ACE));
1247 if (pydesc) {
1249 * Copy inherited tags and adapt perms
1250 * Use requested mode, ignoring umask
1251 * (not possible with older versions of fuse)
1253 tagsset = 0;
1254 defcnt = (pxdesc ? pxdesc->defcnt : 0);
1255 for (i=defcnt-1; i>=0; i--) {
1256 pyace = &pydesc->acl.ace[i];
1257 *pyace = pxdesc->acl.ace[pxdesc->firstdef + i];
1258 switch (pyace->tag) {
1259 case POSIX_ACL_USER_OBJ :
1260 pyace->perms &= (mode >> 6) & 7;
1261 break;
1262 case POSIX_ACL_GROUP_OBJ :
1263 if (!(tagsset & POSIX_ACL_MASK))
1264 pyace->perms &= (mode >> 3) & 7;
1265 break;
1266 case POSIX_ACL_OTHER :
1267 pyace->perms &= mode & 7;
1268 break;
1269 case POSIX_ACL_MASK :
1270 pyace->perms &= (mode >> 3) & 7;
1271 break;
1272 default :
1273 break;
1275 tagsset |= pyace->tag;
1277 pydesc->acccnt = defcnt;
1279 * If some standard tags were missing, append them from mode
1280 * and sort the list
1281 * Here we have to use the umask'ed mode
1283 if (~tagsset & (POSIX_ACL_USER_OBJ
1284 | POSIX_ACL_GROUP_OBJ | POSIX_ACL_OTHER)) {
1285 i = defcnt;
1286 /* owner was missing */
1287 if (!(tagsset & POSIX_ACL_USER_OBJ)) {
1288 pyace = &pydesc->acl.ace[i];
1289 pyace->tag = POSIX_ACL_USER_OBJ;
1290 pyace->id = -1;
1291 pyace->perms = ((mode & ~mask) >> 6) & 7;
1292 tagsset |= POSIX_ACL_USER_OBJ;
1293 i++;
1295 /* owning group was missing */
1296 if (!(tagsset & POSIX_ACL_GROUP_OBJ)) {
1297 pyace = &pydesc->acl.ace[i];
1298 pyace->tag = POSIX_ACL_GROUP_OBJ;
1299 pyace->id = -1;
1300 pyace->perms = ((mode & ~mask) >> 3) & 7;
1301 tagsset |= POSIX_ACL_GROUP_OBJ;
1302 i++;
1304 /* other was missing */
1305 if (!(tagsset & POSIX_ACL_OTHER)) {
1306 pyace = &pydesc->acl.ace[i];
1307 pyace->tag = POSIX_ACL_OTHER;
1308 pyace->id = -1;
1309 pyace->perms = mode & ~mask & 7;
1310 tagsset |= POSIX_ACL_OTHER;
1311 i++;
1313 pydesc->acccnt = i;
1314 pydesc->firstdef = i;
1315 pydesc->defcnt = 0;
1316 ntfs_sort_posix(pydesc);
1320 * append as a default ACL if a directory
1322 pydesc->firstdef = pydesc->acccnt;
1323 if (defcnt && isdir) {
1324 size = sizeof(struct POSIX_ACE)*defcnt;
1325 memcpy(&pydesc->acl.ace[pydesc->firstdef],
1326 &pxdesc->acl.ace[pxdesc->firstdef],size);
1327 pydesc->defcnt = defcnt;
1328 } else {
1329 pydesc->defcnt = 0;
1331 /* assume special bits are not inherited */
1332 posix_header(pydesc, mode & 07000);
1333 if (!ntfs_valid_posix(pydesc)) {
1334 ntfs_log_error("Error building an inherited Posix desc\n");
1335 errno = EIO;
1336 free(pydesc);
1337 pydesc = (struct POSIX_SECURITY*)NULL;
1339 } else
1340 errno = ENOMEM;
1341 return (pydesc);
1344 static int merge_lists_posix(struct POSIX_ACE *targetace,
1345 const struct POSIX_ACE *firstace,
1346 const struct POSIX_ACE *secondace,
1347 int firstcnt, int secondcnt)
1349 int k;
1351 k = 0;
1353 * No list is exhausted :
1354 * if same tag+id in both list :
1355 * ignore ACE from second list
1356 * else take the one with smaller tag+id
1358 while ((firstcnt > 0) && (secondcnt > 0))
1359 if ((firstace->tag == secondace->tag)
1360 && (firstace->id == secondace->id)) {
1361 secondace++;
1362 secondcnt--;
1363 } else
1364 if ((firstace->tag < secondace->tag)
1365 || ((firstace->tag == secondace->tag)
1366 && (firstace->id < secondace->id))) {
1367 targetace->tag = firstace->tag;
1368 targetace->id = firstace->id;
1369 targetace->perms = firstace->perms;
1370 firstace++;
1371 targetace++;
1372 firstcnt--;
1373 k++;
1374 } else {
1375 targetace->tag = secondace->tag;
1376 targetace->id = secondace->id;
1377 targetace->perms = secondace->perms;
1378 secondace++;
1379 targetace++;
1380 secondcnt--;
1381 k++;
1384 * One list is exhausted, copy the other one
1386 while (firstcnt > 0) {
1387 targetace->tag = firstace->tag;
1388 targetace->id = firstace->id;
1389 targetace->perms = firstace->perms;
1390 firstace++;
1391 targetace++;
1392 firstcnt--;
1393 k++;
1395 while (secondcnt > 0) {
1396 targetace->tag = secondace->tag;
1397 targetace->id = secondace->id;
1398 targetace->perms = secondace->perms;
1399 secondace++;
1400 targetace++;
1401 secondcnt--;
1402 k++;
1404 return (k);
1408 * Merge two Posix ACLs
1409 * The input ACLs have to be adequately sorted
1411 * Returns the merged ACL, which is allocated and has to be freed by caller,
1412 * or NULL if failed
1415 struct POSIX_SECURITY *ntfs_merge_descr_posix(const struct POSIX_SECURITY *first,
1416 const struct POSIX_SECURITY *second)
1418 struct POSIX_SECURITY *pxdesc;
1419 struct POSIX_ACE *targetace;
1420 const struct POSIX_ACE *firstace;
1421 const struct POSIX_ACE *secondace;
1422 size_t size;
1423 int k;
1425 size = sizeof(struct POSIX_SECURITY)
1426 + (first->acccnt + first->defcnt
1427 + second->acccnt + second->defcnt)*sizeof(struct POSIX_ACE);
1428 pxdesc = (struct POSIX_SECURITY*)malloc(size);
1429 if (pxdesc) {
1431 * merge access ACEs
1433 firstace = first->acl.ace;
1434 secondace = second->acl.ace;
1435 targetace = pxdesc->acl.ace;
1436 k = merge_lists_posix(targetace,firstace,secondace,
1437 first->acccnt,second->acccnt);
1438 pxdesc->acccnt = k;
1440 * merge default ACEs
1442 pxdesc->firstdef = k;
1443 firstace = &first->acl.ace[first->firstdef];
1444 secondace = &second->acl.ace[second->firstdef];
1445 targetace = &pxdesc->acl.ace[k];
1446 k = merge_lists_posix(targetace,firstace,secondace,
1447 first->defcnt,second->defcnt);
1448 pxdesc->defcnt = k;
1450 * build header
1452 pxdesc->acl.version = POSIX_VERSION;
1453 pxdesc->acl.flags = 0;
1454 pxdesc->acl.filler = 0;
1455 pxdesc->mode = 0;
1456 pxdesc->tagsset = 0;
1457 } else
1458 errno = ENOMEM;
1459 return (pxdesc);
1462 struct BUILD_CONTEXT {
1463 BOOL isdir;
1464 BOOL adminowns;
1465 BOOL groupowns;
1466 u16 selfuserperms;
1467 u16 selfgrpperms;
1468 u16 grpperms;
1469 u16 othperms;
1470 u16 mask;
1471 u16 designates;
1472 u16 withmask;
1473 u16 rootspecial;
1478 static BOOL build_user_denials(ACL *pacl,
1479 const SID *usid, struct MAPPING* const mapping[],
1480 ACE_FLAGS flags, const struct POSIX_ACE *pxace,
1481 struct BUILD_CONTEXT *pset)
1483 BIGSID defsid;
1484 ACCESS_ALLOWED_ACE *pdace;
1485 const SID *sid;
1486 int sidsz;
1487 int pos;
1488 int acecnt;
1489 le32 grants;
1490 le32 denials;
1491 u16 perms;
1492 u16 mixperms;
1493 u16 tag;
1494 BOOL rejected;
1495 BOOL rootuser;
1496 BOOL avoidmask;
1498 rejected = FALSE;
1499 tag = pxace->tag;
1500 perms = pxace->perms;
1501 rootuser = FALSE;
1502 pos = le16_to_cpu(pacl->size);
1503 acecnt = le16_to_cpu(pacl->ace_count);
1504 avoidmask = (pset->mask == (POSIX_PERM_R | POSIX_PERM_W | POSIX_PERM_X))
1505 && ((pset->designates && pset->withmask)
1506 || (!pset->designates && !pset->withmask));
1507 if (tag == POSIX_ACL_USER_OBJ) {
1508 sid = usid;
1509 sidsz = ntfs_sid_size(sid);
1510 grants = OWNER_RIGHTS;
1511 } else {
1512 if (pxace->id) {
1513 sid = NTFS_FIND_USID(mapping[MAPUSERS],
1514 pxace->id, (SID*)&defsid);
1515 grants = WORLD_RIGHTS;
1516 } else {
1517 sid = adminsid;
1518 rootuser = TRUE;
1519 grants = WORLD_RIGHTS & ~ROOT_OWNER_UNMARK;
1521 if (sid) {
1522 sidsz = ntfs_sid_size(sid);
1524 * Insert denial of complement of mask for
1525 * each designated user (except root)
1526 * WRITE_OWNER is inserted so that
1527 * the mask can be identified
1529 if (!avoidmask && !rootuser) {
1530 denials = WRITE_OWNER;
1531 pdace = (ACCESS_DENIED_ACE*)&((char*)pacl)[pos];
1532 if (pset->isdir) {
1533 if (!(pset->mask & POSIX_PERM_X))
1534 denials |= DIR_EXEC;
1535 if (!(pset->mask & POSIX_PERM_W))
1536 denials |= DIR_WRITE;
1537 if (!(pset->mask & POSIX_PERM_R))
1538 denials |= DIR_READ;
1539 } else {
1540 if (!(pset->mask & POSIX_PERM_X))
1541 denials |= FILE_EXEC;
1542 if (!(pset->mask & POSIX_PERM_W))
1543 denials |= FILE_WRITE;
1544 if (!(pset->mask & POSIX_PERM_R))
1545 denials |= FILE_READ;
1547 if (rootuser)
1548 grants &= ~ROOT_OWNER_UNMARK;
1549 pdace->type = ACCESS_DENIED_ACE_TYPE;
1550 pdace->flags = flags;
1551 pdace->size = cpu_to_le16(sidsz + 8);
1552 pdace->mask = denials;
1553 memcpy((char*)&pdace->sid, sid, sidsz);
1554 pos += sidsz + 8;
1555 acecnt++;
1557 } else
1558 rejected = TRUE;
1560 if (!rejected) {
1561 if (pset->isdir) {
1562 if (perms & POSIX_PERM_X)
1563 grants |= DIR_EXEC;
1564 if (perms & POSIX_PERM_W)
1565 grants |= DIR_WRITE;
1566 if (perms & POSIX_PERM_R)
1567 grants |= DIR_READ;
1568 } else {
1569 if (perms & POSIX_PERM_X)
1570 grants |= FILE_EXEC;
1571 if (perms & POSIX_PERM_W)
1572 grants |= FILE_WRITE;
1573 if (perms & POSIX_PERM_R)
1574 grants |= FILE_READ;
1577 /* a possible ACE to deny owner what he/she would */
1578 /* induely get from administrator, group or world */
1579 /* unless owner is administrator or group */
1581 denials = const_cpu_to_le32(0);
1582 pdace = (ACCESS_DENIED_ACE*)&((char*)pacl)[pos];
1583 if (!pset->adminowns && !rootuser) {
1584 if (!pset->groupowns) {
1585 mixperms = pset->grpperms | pset->othperms;
1586 if (tag == POSIX_ACL_USER_OBJ)
1587 mixperms |= pset->selfuserperms;
1588 if (pset->isdir) {
1589 if (mixperms & POSIX_PERM_X)
1590 denials |= DIR_EXEC;
1591 if (mixperms & POSIX_PERM_W)
1592 denials |= DIR_WRITE;
1593 if (mixperms & POSIX_PERM_R)
1594 denials |= DIR_READ;
1595 } else {
1596 if (mixperms & POSIX_PERM_X)
1597 denials |= FILE_EXEC;
1598 if (mixperms & POSIX_PERM_W)
1599 denials |= FILE_WRITE;
1600 if (mixperms & POSIX_PERM_R)
1601 denials |= FILE_READ;
1603 } else {
1604 mixperms = ~pset->grpperms & pset->othperms;
1605 if (tag == POSIX_ACL_USER_OBJ)
1606 mixperms |= pset->selfuserperms;
1607 if (pset->isdir) {
1608 if (mixperms & POSIX_PERM_X)
1609 denials |= DIR_EXEC;
1610 if (mixperms & POSIX_PERM_W)
1611 denials |= DIR_WRITE;
1612 if (mixperms & POSIX_PERM_R)
1613 denials |= DIR_READ;
1614 } else {
1615 if (mixperms & POSIX_PERM_X)
1616 denials |= FILE_EXEC;
1617 if (mixperms & POSIX_PERM_W)
1618 denials |= FILE_WRITE;
1619 if (mixperms & POSIX_PERM_R)
1620 denials |= FILE_READ;
1623 denials &= ~grants;
1624 if (denials) {
1625 pdace->type = ACCESS_DENIED_ACE_TYPE;
1626 pdace->flags = flags;
1627 pdace->size = cpu_to_le16(sidsz + 8);
1628 pdace->mask = denials;
1629 memcpy((char*)&pdace->sid, sid, sidsz);
1630 pos += sidsz + 8;
1631 acecnt++;
1635 pacl->size = cpu_to_le16(pos);
1636 pacl->ace_count = cpu_to_le16(acecnt);
1637 return (!rejected);
1640 static BOOL build_user_grants(ACL *pacl,
1641 const SID *usid, struct MAPPING* const mapping[],
1642 ACE_FLAGS flags, const struct POSIX_ACE *pxace,
1643 struct BUILD_CONTEXT *pset)
1645 BIGSID defsid;
1646 ACCESS_ALLOWED_ACE *pgace;
1647 const SID *sid;
1648 int sidsz;
1649 int pos;
1650 int acecnt;
1651 le32 grants;
1652 u16 perms;
1653 u16 tag;
1654 BOOL rejected;
1655 BOOL rootuser;
1657 rejected = FALSE;
1658 tag = pxace->tag;
1659 perms = pxace->perms;
1660 rootuser = FALSE;
1661 pos = le16_to_cpu(pacl->size);
1662 acecnt = le16_to_cpu(pacl->ace_count);
1663 if (tag == POSIX_ACL_USER_OBJ) {
1664 sid = usid;
1665 sidsz = ntfs_sid_size(sid);
1666 grants = OWNER_RIGHTS;
1667 } else {
1668 if (pxace->id) {
1669 sid = NTFS_FIND_USID(mapping[MAPUSERS],
1670 pxace->id, (SID*)&defsid);
1671 if (sid)
1672 sidsz = ntfs_sid_size(sid);
1673 else
1674 rejected = TRUE;
1675 grants = WORLD_RIGHTS;
1676 } else {
1677 sid = adminsid;
1678 sidsz = ntfs_sid_size(sid);
1679 rootuser = TRUE;
1680 grants = WORLD_RIGHTS & ~ROOT_OWNER_UNMARK;
1683 if (!rejected) {
1684 if (pset->isdir) {
1685 if (perms & POSIX_PERM_X)
1686 grants |= DIR_EXEC;
1687 if (perms & POSIX_PERM_W)
1688 grants |= DIR_WRITE;
1689 if (perms & POSIX_PERM_R)
1690 grants |= DIR_READ;
1691 } else {
1692 if (perms & POSIX_PERM_X)
1693 grants |= FILE_EXEC;
1694 if (perms & POSIX_PERM_W)
1695 grants |= FILE_WRITE;
1696 if (perms & POSIX_PERM_R)
1697 grants |= FILE_READ;
1699 if (rootuser)
1700 grants &= ~ROOT_OWNER_UNMARK;
1701 pgace = (ACCESS_DENIED_ACE*)&((char*)pacl)[pos];
1702 pgace->type = ACCESS_ALLOWED_ACE_TYPE;
1703 pgace->size = cpu_to_le16(sidsz + 8);
1704 pgace->flags = flags;
1705 pgace->mask = grants;
1706 memcpy((char*)&pgace->sid, sid, sidsz);
1707 pos += sidsz + 8;
1708 acecnt = le16_to_cpu(pacl->ace_count) + 1;
1709 pacl->ace_count = cpu_to_le16(acecnt);
1710 pacl->size = cpu_to_le16(pos);
1712 return (!rejected);
1716 /* a grant ACE for group */
1717 /* unless group-obj has the same rights as world */
1718 /* but present if group is owner or owner is administrator */
1719 /* this ACE will be inserted after denials for group */
1721 static BOOL build_group_denials_grant(ACL *pacl,
1722 const SID *gsid, struct MAPPING* const mapping[],
1723 ACE_FLAGS flags, const struct POSIX_ACE *pxace,
1724 struct BUILD_CONTEXT *pset)
1726 BIGSID defsid;
1727 ACCESS_ALLOWED_ACE *pdace;
1728 ACCESS_ALLOWED_ACE *pgace;
1729 const SID *sid;
1730 int sidsz;
1731 int pos;
1732 int acecnt;
1733 le32 grants;
1734 le32 denials;
1735 u16 perms;
1736 u16 mixperms;
1737 u16 tag;
1738 BOOL avoidmask;
1739 BOOL rootgroup;
1740 BOOL rejected;
1742 rejected = FALSE;
1743 tag = pxace->tag;
1744 perms = pxace->perms;
1745 pos = le16_to_cpu(pacl->size);
1746 acecnt = le16_to_cpu(pacl->ace_count);
1747 rootgroup = FALSE;
1748 avoidmask = (pset->mask == (POSIX_PERM_R | POSIX_PERM_W | POSIX_PERM_X))
1749 && ((pset->designates && pset->withmask)
1750 || (!pset->designates && !pset->withmask));
1751 if (tag == POSIX_ACL_GROUP_OBJ)
1752 sid = gsid;
1753 else
1754 if (pxace->id)
1755 sid = NTFS_FIND_GSID(mapping[MAPGROUPS],
1756 pxace->id, (SID*)&defsid);
1757 else {
1758 sid = adminsid;
1759 rootgroup = TRUE;
1761 if (sid) {
1762 sidsz = ntfs_sid_size(sid);
1764 * Insert denial of complement of mask for
1765 * each group
1766 * WRITE_OWNER is inserted so that
1767 * the mask can be identified
1768 * Note : this mask may lead on Windows to
1769 * deny rights to administrators belonging
1770 * to some user group
1772 if ((!avoidmask && !rootgroup)
1773 || (pset->rootspecial
1774 && (tag == POSIX_ACL_GROUP_OBJ))) {
1775 denials = WRITE_OWNER;
1776 pdace = (ACCESS_DENIED_ACE*)&((char*)pacl)[pos];
1777 if (pset->isdir) {
1778 if (!(pset->mask & POSIX_PERM_X))
1779 denials |= DIR_EXEC;
1780 if (!(pset->mask & POSIX_PERM_W))
1781 denials |= DIR_WRITE;
1782 if (!(pset->mask & POSIX_PERM_R))
1783 denials |= DIR_READ;
1784 } else {
1785 if (!(pset->mask & POSIX_PERM_X))
1786 denials |= FILE_EXEC;
1787 if (!(pset->mask & POSIX_PERM_W))
1788 denials |= FILE_WRITE;
1789 if (!(pset->mask & POSIX_PERM_R))
1790 denials |= FILE_READ;
1792 pdace->type = ACCESS_DENIED_ACE_TYPE;
1793 pdace->flags = flags;
1794 pdace->size = cpu_to_le16(sidsz + 8);
1795 pdace->mask = denials;
1796 memcpy((char*)&pdace->sid, sid, sidsz);
1797 pos += sidsz + 8;
1798 acecnt++;
1800 } else
1801 rejected = TRUE;
1802 if (!rejected
1803 && (pset->adminowns
1804 || pset->groupowns
1805 || avoidmask
1806 || rootgroup
1807 || (perms != pset->othperms))) {
1808 grants = WORLD_RIGHTS;
1809 if (rootgroup)
1810 grants &= ~ROOT_GROUP_UNMARK;
1811 if (pset->isdir) {
1812 if (perms & POSIX_PERM_X)
1813 grants |= DIR_EXEC;
1814 if (perms & POSIX_PERM_W)
1815 grants |= DIR_WRITE;
1816 if (perms & POSIX_PERM_R)
1817 grants |= DIR_READ;
1818 } else {
1819 if (perms & POSIX_PERM_X)
1820 grants |= FILE_EXEC;
1821 if (perms & POSIX_PERM_W)
1822 grants |= FILE_WRITE;
1823 if (perms & POSIX_PERM_R)
1824 grants |= FILE_READ;
1827 /* a possible ACE to deny group what it would get from world */
1828 /* or administrator, unless owner is administrator or group */
1830 denials = const_cpu_to_le32(0);
1831 pdace = (ACCESS_DENIED_ACE*)&((char*)pacl)[pos];
1832 if (!pset->adminowns
1833 && !pset->groupowns
1834 && !rootgroup) {
1835 mixperms = pset->othperms;
1836 if (tag == POSIX_ACL_GROUP_OBJ)
1837 mixperms |= pset->selfgrpperms;
1838 if (pset->isdir) {
1839 if (mixperms & POSIX_PERM_X)
1840 denials |= DIR_EXEC;
1841 if (mixperms & POSIX_PERM_W)
1842 denials |= DIR_WRITE;
1843 if (mixperms & POSIX_PERM_R)
1844 denials |= DIR_READ;
1845 } else {
1846 if (mixperms & POSIX_PERM_X)
1847 denials |= FILE_EXEC;
1848 if (mixperms & POSIX_PERM_W)
1849 denials |= FILE_WRITE;
1850 if (mixperms & POSIX_PERM_R)
1851 denials |= FILE_READ;
1853 denials &= ~(grants | OWNER_RIGHTS);
1854 if (denials) {
1855 pdace->type = ACCESS_DENIED_ACE_TYPE;
1856 pdace->flags = flags;
1857 pdace->size = cpu_to_le16(sidsz + 8);
1858 pdace->mask = denials;
1859 memcpy((char*)&pdace->sid, sid, sidsz);
1860 pos += sidsz + 8;
1861 acecnt++;
1865 /* now insert grants to group if more than world */
1866 if (pset->adminowns
1867 || pset->groupowns
1868 || (avoidmask && (pset->designates || pset->withmask))
1869 || (perms & ~pset->othperms)
1870 || (pset->rootspecial
1871 && (tag == POSIX_ACL_GROUP_OBJ))
1872 || (tag == POSIX_ACL_GROUP)) {
1873 if (rootgroup)
1874 grants &= ~ROOT_GROUP_UNMARK;
1875 pgace = (ACCESS_DENIED_ACE*)&((char*)pacl)[pos];
1876 pgace->type = ACCESS_ALLOWED_ACE_TYPE;
1877 pgace->flags = flags;
1878 pgace->size = cpu_to_le16(sidsz + 8);
1879 pgace->mask = grants;
1880 memcpy((char*)&pgace->sid, sid, sidsz);
1881 pos += sidsz + 8;
1882 acecnt++;
1885 pacl->size = cpu_to_le16(pos);
1886 pacl->ace_count = cpu_to_le16(acecnt);
1887 return (!rejected);
1892 * Build an ACL composed of several ACE's
1893 * returns size of ACL or zero if failed
1895 * Three schemes are defined :
1897 * 1) if root is neither owner nor group up to 7 ACE's are set up :
1898 * - denials to owner (preventing grants to world or group to apply)
1899 * + mask denials to designated user (unless mask allows all)
1900 * + denials to designated user
1901 * - grants to owner (always present - first grant)
1902 * + grants to designated user
1903 * + mask denial to group (unless mask allows all)
1904 * - denials to group (preventing grants to world to apply)
1905 * - grants to group (unless group has no more than world rights)
1906 * + mask denials to designated group (unless mask allows all)
1907 * + grants to designated group
1908 * + denials to designated group
1909 * - grants to world (unless none)
1910 * - full privileges to administrator, always present
1911 * - full privileges to system, always present
1913 * The same scheme is applied for Posix ACLs, with the mask represented
1914 * as denials prepended to grants for designated users and groups
1916 * This is inspired by an Internet Draft from Marius Aamodt Eriksen
1917 * for mapping NFSv4 ACLs to Posix ACLs (draft-ietf-nfsv4-acl-mapping-00.txt)
1918 * More recent versions of the draft (draft-ietf-nfsv4-acl-mapping-05.txt)
1919 * are not followed, as they ignore the Posix mask and lead to
1920 * loss of compatibility with Linux implementations on other fs.
1922 * Note that denials to group are located after grants to owner.
1923 * This only occurs in the unfrequent situation where world
1924 * has more rights than group and cannot be avoided if owner and other
1925 * have some common right which is denied to group (eg for mode 745
1926 * executing has to be denied to group, but not to owner or world).
1927 * This rare situation is processed by Windows correctly, but
1928 * Windows utilities may want to change the order, with a
1929 * consequence of applying the group denials to the Windows owner.
1930 * The interpretation on Linux is not affected by the order change.
1932 * 2) if root is either owner or group, two problems arise :
1933 * - granting full rights to administrator (as needed to transpose
1934 * to Windows rights bypassing granting to root) would imply
1935 * Linux permissions to always be seen as rwx, no matter the chmod
1936 * - there is no different SID to separate an administrator owner
1937 * from an administrator group. Hence Linux permissions for owner
1938 * would always be similar to permissions to group.
1940 * as a work-around, up to 5 ACE's are set up if owner or group :
1941 * - grants to owner, always present at first position
1942 * - grants to group, always present
1943 * - grants to world, unless none
1944 * - full privileges to administrator, always present
1945 * - full privileges to system, always present
1947 * On Windows, these ACE's are processed normally, though they
1948 * are redundant (owner, group and administrator are the same,
1949 * as a consequence any denials would damage administrator rights)
1950 * but on Linux, privileges to administrator are ignored (they
1951 * are not needed as root has always full privileges), and
1952 * neither grants to group are applied to owner, nor grants to
1953 * world are applied to owner or group.
1955 * 3) finally a similar situation arises when group is owner (they
1956 * have the same SID), but is not root.
1957 * In this situation up to 6 ACE's are set up :
1959 * - denials to owner (preventing grants to world to apply)
1960 * - grants to owner (always present)
1961 * - grants to group (unless groups has same rights as world)
1962 * - grants to world (unless none)
1963 * - full privileges to administrator, always present
1964 * - full privileges to system, always present
1966 * On Windows, these ACE's are processed normally, though they
1967 * are redundant (as owner and group are the same), but this has
1968 * no impact on administrator rights
1970 * Special flags (S_ISVTX, S_ISGID, S_ISUID) :
1971 * an extra null ACE is inserted to hold these flags, using
1972 * the same conventions as cygwin.
1976 static int buildacls_posix(struct MAPPING* const mapping[],
1977 char *secattr, int offs, const struct POSIX_SECURITY *pxdesc,
1978 int isdir, const SID *usid, const SID *gsid)
1980 struct BUILD_CONTEXT aceset[2], *pset;
1981 BOOL adminowns;
1982 BOOL groupowns;
1983 ACL *pacl;
1984 ACCESS_ALLOWED_ACE *pgace;
1985 ACCESS_ALLOWED_ACE *pdace;
1986 const struct POSIX_ACE *pxace;
1987 BOOL ok;
1988 mode_t mode;
1989 u16 tag;
1990 u16 perms;
1991 ACE_FLAGS flags;
1992 int pos;
1993 int i;
1994 int k;
1995 BIGSID defsid;
1996 const SID *sid;
1997 int acecnt;
1998 int usidsz;
1999 int wsidsz;
2000 int asidsz;
2001 int ssidsz;
2002 int nsidsz;
2003 le32 grants;
2005 usidsz = ntfs_sid_size(usid);
2006 wsidsz = ntfs_sid_size(worldsid);
2007 asidsz = ntfs_sid_size(adminsid);
2008 ssidsz = ntfs_sid_size(systemsid);
2009 mode = pxdesc->mode;
2010 /* adminowns and groupowns are used for both lists */
2011 adminowns = ntfs_same_sid(usid, adminsid)
2012 || ntfs_same_sid(gsid, adminsid);
2013 groupowns = !adminowns && ntfs_same_sid(usid, gsid);
2015 ok = TRUE;
2017 /* ACL header */
2018 pacl = (ACL*)&secattr[offs];
2019 pacl->revision = ACL_REVISION;
2020 pacl->alignment1 = 0;
2021 pacl->size = cpu_to_le16(sizeof(ACL) + usidsz + 8);
2022 pacl->ace_count = const_cpu_to_le16(0);
2023 pacl->alignment2 = const_cpu_to_le16(0);
2026 * Determine what is allowed to some group or world
2027 * to prevent designated users or other groups to get
2028 * rights from groups or world
2029 * Do the same if owner and group appear as designated
2030 * user or group
2031 * Also get global mask
2033 for (k=0; k<2; k++) {
2034 pset = &aceset[k];
2035 pset->selfuserperms = 0;
2036 pset->selfgrpperms = 0;
2037 pset->grpperms = 0;
2038 pset->othperms = 0;
2039 pset->mask = (POSIX_PERM_R | POSIX_PERM_W | POSIX_PERM_X);
2040 pset->designates = 0;
2041 pset->withmask = 0;
2042 pset->rootspecial = 0;
2043 pset->adminowns = adminowns;
2044 pset->groupowns = groupowns;
2045 pset->isdir = isdir;
2048 for (i=pxdesc->acccnt+pxdesc->defcnt-1; i>=0; i--) {
2049 if (i >= pxdesc->acccnt) {
2050 pset = &aceset[1];
2051 pxace = &pxdesc->acl.ace[i + pxdesc->firstdef - pxdesc->acccnt];
2052 } else {
2053 pset = &aceset[0];
2054 pxace = &pxdesc->acl.ace[i];
2056 switch (pxace->tag) {
2057 case POSIX_ACL_USER :
2058 pset->designates++;
2059 if (pxace->id) {
2060 sid = NTFS_FIND_USID(mapping[MAPUSERS],
2061 pxace->id, (SID*)&defsid);
2062 if (sid && ntfs_same_sid(sid,usid))
2063 pset->selfuserperms |= pxace->perms;
2064 } else
2065 /* root as designated user is processed apart */
2066 pset->rootspecial = TRUE;
2067 break;
2068 case POSIX_ACL_GROUP :
2069 pset->designates++;
2070 if (pxace->id) {
2071 sid = NTFS_FIND_GSID(mapping[MAPUSERS],
2072 pxace->id, (SID*)&defsid);
2073 if (sid && ntfs_same_sid(sid,gsid))
2074 pset->selfgrpperms |= pxace->perms;
2075 } else
2076 /* root as designated group is processed apart */
2077 pset->rootspecial = TRUE;
2078 /* fall through */
2079 case POSIX_ACL_GROUP_OBJ :
2080 pset->grpperms |= pxace->perms;
2081 break;
2082 case POSIX_ACL_OTHER :
2083 pset->othperms = pxace->perms;
2084 break;
2085 case POSIX_ACL_MASK :
2086 pset->withmask++;
2087 pset->mask = pxace->perms;
2088 default :
2089 break;
2093 if (pxdesc->defcnt && (pxdesc->firstdef != pxdesc->acccnt)) {
2094 ntfs_log_error("** error : access and default not consecutive\n");
2095 return (0);
2098 * First insert all denials for owner and each
2099 * designated user (with mask if needed)
2102 pacl->ace_count = const_cpu_to_le16(0);
2103 pacl->size = const_cpu_to_le16(sizeof(ACL));
2104 for (i=0; (i<(pxdesc->acccnt + pxdesc->defcnt)) && ok; i++) {
2105 if (i >= pxdesc->acccnt) {
2106 flags = INHERIT_ONLY_ACE
2107 | OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE;
2108 pset = &aceset[1];
2109 pxace = &pxdesc->acl.ace[i + pxdesc->firstdef - pxdesc->acccnt];
2110 } else {
2111 if (pxdesc->defcnt)
2112 flags = NO_PROPAGATE_INHERIT_ACE;
2113 else
2114 flags = (isdir ? DIR_INHERITANCE
2115 : FILE_INHERITANCE);
2116 pset = &aceset[0];
2117 pxace = &pxdesc->acl.ace[i];
2119 tag = pxace->tag;
2120 perms = pxace->perms;
2121 switch (tag) {
2123 /* insert denial ACEs for each owner or allowed user */
2125 case POSIX_ACL_USER :
2126 case POSIX_ACL_USER_OBJ :
2128 ok = build_user_denials(pacl,
2129 usid, mapping, flags, pxace, pset);
2130 break;
2131 default :
2132 break;
2137 * for directories, insert a world execution denial
2138 * inherited to plain files.
2139 * This is to prevent Windows from granting execution
2140 * of files through inheritance from parent directory
2143 if (isdir && ok) {
2144 pos = le16_to_cpu(pacl->size);
2145 pdace = (ACCESS_DENIED_ACE*) &secattr[offs + pos];
2146 pdace->type = ACCESS_DENIED_ACE_TYPE;
2147 pdace->flags = INHERIT_ONLY_ACE | OBJECT_INHERIT_ACE;
2148 pdace->size = cpu_to_le16(wsidsz + 8);
2149 pdace->mask = FILE_EXEC;
2150 memcpy((char*)&pdace->sid, worldsid, wsidsz);
2151 pos += wsidsz + 8;
2152 acecnt = le16_to_cpu(pacl->ace_count) + 1;
2153 pacl->ace_count = cpu_to_le16(acecnt);
2154 pacl->size = cpu_to_le16(pos);
2158 * now insert (if needed)
2159 * - grants to owner and designated users
2160 * - mask and denials for all groups
2161 * - grants to other
2164 for (i=0; (i<(pxdesc->acccnt + pxdesc->defcnt)) && ok; i++) {
2165 if (i >= pxdesc->acccnt) {
2166 flags = INHERIT_ONLY_ACE
2167 | OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE;
2168 pset = &aceset[1];
2169 pxace = &pxdesc->acl.ace[i + pxdesc->firstdef - pxdesc->acccnt];
2170 } else {
2171 if (pxdesc->defcnt)
2172 flags = NO_PROPAGATE_INHERIT_ACE;
2173 else
2174 flags = (isdir ? DIR_INHERITANCE
2175 : FILE_INHERITANCE);
2176 pset = &aceset[0];
2177 pxace = &pxdesc->acl.ace[i];
2179 tag = pxace->tag;
2180 perms = pxace->perms;
2181 switch (tag) {
2183 /* ACE for each owner or allowed user */
2185 case POSIX_ACL_USER :
2186 case POSIX_ACL_USER_OBJ :
2187 ok = build_user_grants(pacl,usid,
2188 mapping,flags,pxace,pset);
2189 break;
2191 case POSIX_ACL_GROUP :
2192 case POSIX_ACL_GROUP_OBJ :
2194 /* denials and grants for groups */
2196 ok = build_group_denials_grant(pacl,gsid,
2197 mapping,flags,pxace,pset);
2198 break;
2200 case POSIX_ACL_OTHER :
2202 /* grants for other users */
2204 pos = le16_to_cpu(pacl->size);
2205 pgace = (ACCESS_ALLOWED_ACE*)&secattr[offs + pos];
2206 grants = WORLD_RIGHTS;
2207 if (isdir) {
2208 if (perms & POSIX_PERM_X)
2209 grants |= DIR_EXEC;
2210 if (perms & POSIX_PERM_W)
2211 grants |= DIR_WRITE;
2212 if (perms & POSIX_PERM_R)
2213 grants |= DIR_READ;
2214 } else {
2215 if (perms & POSIX_PERM_X)
2216 grants |= FILE_EXEC;
2217 if (perms & POSIX_PERM_W)
2218 grants |= FILE_WRITE;
2219 if (perms & POSIX_PERM_R)
2220 grants |= FILE_READ;
2222 pgace->type = ACCESS_ALLOWED_ACE_TYPE;
2223 pgace->flags = flags;
2224 pgace->size = cpu_to_le16(wsidsz + 8);
2225 pgace->mask = grants;
2226 memcpy((char*)&pgace->sid, worldsid, wsidsz);
2227 pos += wsidsz + 8;
2228 acecnt = le16_to_cpu(pacl->ace_count) + 1;
2229 pacl->ace_count = cpu_to_le16(acecnt);
2230 pacl->size = cpu_to_le16(pos);
2231 break;
2235 if (!ok) {
2236 errno = EINVAL;
2237 pos = 0;
2238 } else {
2239 /* an ACE for administrators */
2240 /* always full access */
2242 pos = le16_to_cpu(pacl->size);
2243 acecnt = le16_to_cpu(pacl->ace_count);
2244 if (isdir)
2245 flags = OBJECT_INHERIT_ACE
2246 | CONTAINER_INHERIT_ACE;
2247 else
2248 flags = NO_PROPAGATE_INHERIT_ACE;
2249 pgace = (ACCESS_ALLOWED_ACE*)&secattr[offs + pos];
2250 pgace->type = ACCESS_ALLOWED_ACE_TYPE;
2251 pgace->flags = flags;
2252 pgace->size = cpu_to_le16(asidsz + 8);
2253 grants = OWNER_RIGHTS | FILE_READ | FILE_WRITE | FILE_EXEC;
2254 pgace->mask = grants;
2255 memcpy((char*)&pgace->sid, adminsid, asidsz);
2256 pos += asidsz + 8;
2257 acecnt++;
2259 /* an ACE for system (needed ?) */
2260 /* always full access */
2262 pgace = (ACCESS_ALLOWED_ACE*)&secattr[offs + pos];
2263 pgace->type = ACCESS_ALLOWED_ACE_TYPE;
2264 pgace->flags = flags;
2265 pgace->size = cpu_to_le16(ssidsz + 8);
2266 grants = OWNER_RIGHTS | FILE_READ | FILE_WRITE | FILE_EXEC;
2267 pgace->mask = grants;
2268 memcpy((char*)&pgace->sid, systemsid, ssidsz);
2269 pos += ssidsz + 8;
2270 acecnt++;
2272 /* a null ACE to hold special flags */
2273 /* using the same representation as cygwin */
2275 if (mode & (S_ISVTX | S_ISGID | S_ISUID)) {
2276 nsidsz = ntfs_sid_size(nullsid);
2277 pgace = (ACCESS_ALLOWED_ACE*)&secattr[offs + pos];
2278 pgace->type = ACCESS_ALLOWED_ACE_TYPE;
2279 pgace->flags = NO_PROPAGATE_INHERIT_ACE;
2280 pgace->size = cpu_to_le16(nsidsz + 8);
2281 grants = const_cpu_to_le32(0);
2282 if (mode & S_ISUID)
2283 grants |= FILE_APPEND_DATA;
2284 if (mode & S_ISGID)
2285 grants |= FILE_WRITE_DATA;
2286 if (mode & S_ISVTX)
2287 grants |= FILE_READ_DATA;
2288 pgace->mask = grants;
2289 memcpy((char*)&pgace->sid, nullsid, nsidsz);
2290 pos += nsidsz + 8;
2291 acecnt++;
2294 /* fix ACL header */
2295 pacl->size = cpu_to_le16(pos);
2296 pacl->ace_count = cpu_to_le16(acecnt);
2298 return (ok ? pos : 0);
2301 #endif /* POSIXACLS */
2303 static int buildacls(char *secattr, int offs, mode_t mode, int isdir,
2304 const SID * usid, const SID * gsid)
2306 ACL *pacl;
2307 ACCESS_ALLOWED_ACE *pgace;
2308 ACCESS_ALLOWED_ACE *pdace;
2309 BOOL adminowns;
2310 BOOL groupowns;
2311 ACE_FLAGS gflags;
2312 int pos;
2313 int acecnt;
2314 int usidsz;
2315 int gsidsz;
2316 int wsidsz;
2317 int asidsz;
2318 int ssidsz;
2319 int nsidsz;
2320 le32 grants;
2321 le32 denials;
2323 usidsz = ntfs_sid_size(usid);
2324 gsidsz = ntfs_sid_size(gsid);
2325 wsidsz = ntfs_sid_size(worldsid);
2326 asidsz = ntfs_sid_size(adminsid);
2327 ssidsz = ntfs_sid_size(systemsid);
2328 adminowns = ntfs_same_sid(usid, adminsid)
2329 || ntfs_same_sid(gsid, adminsid);
2330 groupowns = !adminowns && ntfs_same_sid(usid, gsid);
2332 /* ACL header */
2333 pacl = (ACL*)&secattr[offs];
2334 pacl->revision = ACL_REVISION;
2335 pacl->alignment1 = 0;
2336 pacl->size = cpu_to_le16(sizeof(ACL) + usidsz + 8);
2337 pacl->ace_count = const_cpu_to_le16(1);
2338 pacl->alignment2 = const_cpu_to_le16(0);
2339 pos = sizeof(ACL);
2340 acecnt = 0;
2342 /* compute a grant ACE for owner */
2343 /* this ACE will be inserted after denial for owner */
2345 grants = OWNER_RIGHTS;
2346 if (isdir) {
2347 gflags = DIR_INHERITANCE;
2348 if (mode & S_IXUSR)
2349 grants |= DIR_EXEC;
2350 if (mode & S_IWUSR)
2351 grants |= DIR_WRITE;
2352 if (mode & S_IRUSR)
2353 grants |= DIR_READ;
2354 } else {
2355 gflags = FILE_INHERITANCE;
2356 if (mode & S_IXUSR)
2357 grants |= FILE_EXEC;
2358 if (mode & S_IWUSR)
2359 grants |= FILE_WRITE;
2360 if (mode & S_IRUSR)
2361 grants |= FILE_READ;
2364 /* a possible ACE to deny owner what he/she would */
2365 /* induely get from administrator, group or world */
2366 /* unless owner is administrator or group */
2368 denials = const_cpu_to_le32(0);
2369 pdace = (ACCESS_DENIED_ACE*) &secattr[offs + pos];
2370 if (!adminowns) {
2371 if (!groupowns) {
2372 if (isdir) {
2373 pdace->flags = DIR_INHERITANCE;
2374 if (mode & (S_IXGRP | S_IXOTH))
2375 denials |= DIR_EXEC;
2376 if (mode & (S_IWGRP | S_IWOTH))
2377 denials |= DIR_WRITE;
2378 if (mode & (S_IRGRP | S_IROTH))
2379 denials |= DIR_READ;
2380 } else {
2381 pdace->flags = FILE_INHERITANCE;
2382 if (mode & (S_IXGRP | S_IXOTH))
2383 denials |= FILE_EXEC;
2384 if (mode & (S_IWGRP | S_IWOTH))
2385 denials |= FILE_WRITE;
2386 if (mode & (S_IRGRP | S_IROTH))
2387 denials |= FILE_READ;
2389 } else {
2390 if (isdir) {
2391 pdace->flags = DIR_INHERITANCE;
2392 if ((mode & S_IXOTH) && !(mode & S_IXGRP))
2393 denials |= DIR_EXEC;
2394 if ((mode & S_IWOTH) && !(mode & S_IWGRP))
2395 denials |= DIR_WRITE;
2396 if ((mode & S_IROTH) && !(mode & S_IRGRP))
2397 denials |= DIR_READ;
2398 } else {
2399 pdace->flags = FILE_INHERITANCE;
2400 if ((mode & S_IXOTH) && !(mode & S_IXGRP))
2401 denials |= FILE_EXEC;
2402 if ((mode & S_IWOTH) && !(mode & S_IWGRP))
2403 denials |= FILE_WRITE;
2404 if ((mode & S_IROTH) && !(mode & S_IRGRP))
2405 denials |= FILE_READ;
2408 denials &= ~grants;
2409 if (denials) {
2410 pdace->type = ACCESS_DENIED_ACE_TYPE;
2411 pdace->size = cpu_to_le16(usidsz + 8);
2412 pdace->mask = denials;
2413 memcpy((char*)&pdace->sid, usid, usidsz);
2414 pos += usidsz + 8;
2415 acecnt++;
2419 * for directories, a world execution denial
2420 * inherited to plain files
2423 if (isdir) {
2424 pdace = (ACCESS_DENIED_ACE*) &secattr[offs + pos];
2425 pdace->type = ACCESS_DENIED_ACE_TYPE;
2426 pdace->flags = INHERIT_ONLY_ACE | OBJECT_INHERIT_ACE;
2427 pdace->size = cpu_to_le16(wsidsz + 8);
2428 pdace->mask = FILE_EXEC;
2429 memcpy((char*)&pdace->sid, worldsid, wsidsz);
2430 pos += wsidsz + 8;
2431 acecnt++;
2435 /* now insert grants to owner */
2436 pgace = (ACCESS_ALLOWED_ACE*) &secattr[offs + pos];
2437 pgace->type = ACCESS_ALLOWED_ACE_TYPE;
2438 pgace->size = cpu_to_le16(usidsz + 8);
2439 pgace->flags = gflags;
2440 pgace->mask = grants;
2441 memcpy((char*)&pgace->sid, usid, usidsz);
2442 pos += usidsz + 8;
2443 acecnt++;
2445 /* a grant ACE for group */
2446 /* unless group has the same rights as world */
2447 /* but present if group is owner or owner is administrator */
2448 /* this ACE will be inserted after denials for group */
2450 if (adminowns
2451 || groupowns
2452 || (((mode >> 3) ^ mode) & 7)) {
2453 grants = WORLD_RIGHTS;
2454 if (isdir) {
2455 gflags = DIR_INHERITANCE;
2456 if (mode & S_IXGRP)
2457 grants |= DIR_EXEC;
2458 if (mode & S_IWGRP)
2459 grants |= DIR_WRITE;
2460 if (mode & S_IRGRP)
2461 grants |= DIR_READ;
2462 } else {
2463 gflags = FILE_INHERITANCE;
2464 if (mode & S_IXGRP)
2465 grants |= FILE_EXEC;
2466 if (mode & S_IWGRP)
2467 grants |= FILE_WRITE;
2468 if (mode & S_IRGRP)
2469 grants |= FILE_READ;
2472 /* a possible ACE to deny group what it would get from world */
2473 /* or administrator, unless owner is administrator or group */
2475 denials = const_cpu_to_le32(0);
2476 pdace = (ACCESS_ALLOWED_ACE*)&secattr[offs + pos];
2477 if (!adminowns && !groupowns) {
2478 if (isdir) {
2479 pdace->flags = DIR_INHERITANCE;
2480 if (mode & S_IXOTH)
2481 denials |= DIR_EXEC;
2482 if (mode & S_IWOTH)
2483 denials |= DIR_WRITE;
2484 if (mode & S_IROTH)
2485 denials |= DIR_READ;
2486 } else {
2487 pdace->flags = FILE_INHERITANCE;
2488 if (mode & S_IXOTH)
2489 denials |= FILE_EXEC;
2490 if (mode & S_IWOTH)
2491 denials |= FILE_WRITE;
2492 if (mode & S_IROTH)
2493 denials |= FILE_READ;
2495 denials &= ~(grants | OWNER_RIGHTS);
2496 if (denials) {
2497 pdace->type = ACCESS_DENIED_ACE_TYPE;
2498 pdace->size = cpu_to_le16(gsidsz + 8);
2499 pdace->mask = denials;
2500 memcpy((char*)&pdace->sid, gsid, gsidsz);
2501 pos += gsidsz + 8;
2502 acecnt++;
2506 if (adminowns
2507 || groupowns
2508 || ((mode >> 3) & ~mode & 7)) {
2509 /* now insert grants to group */
2510 /* if more rights than other */
2511 pgace = (ACCESS_ALLOWED_ACE*)&secattr[offs + pos];
2512 pgace->type = ACCESS_ALLOWED_ACE_TYPE;
2513 pgace->flags = gflags;
2514 pgace->size = cpu_to_le16(gsidsz + 8);
2515 pgace->mask = grants;
2516 memcpy((char*)&pgace->sid, gsid, gsidsz);
2517 pos += gsidsz + 8;
2518 acecnt++;
2522 /* an ACE for world users */
2524 pgace = (ACCESS_ALLOWED_ACE*)&secattr[offs + pos];
2525 pgace->type = ACCESS_ALLOWED_ACE_TYPE;
2526 grants = WORLD_RIGHTS;
2527 if (isdir) {
2528 pgace->flags = DIR_INHERITANCE;
2529 if (mode & S_IXOTH)
2530 grants |= DIR_EXEC;
2531 if (mode & S_IWOTH)
2532 grants |= DIR_WRITE;
2533 if (mode & S_IROTH)
2534 grants |= DIR_READ;
2535 } else {
2536 pgace->flags = FILE_INHERITANCE;
2537 if (mode & S_IXOTH)
2538 grants |= FILE_EXEC;
2539 if (mode & S_IWOTH)
2540 grants |= FILE_WRITE;
2541 if (mode & S_IROTH)
2542 grants |= FILE_READ;
2544 pgace->size = cpu_to_le16(wsidsz + 8);
2545 pgace->mask = grants;
2546 memcpy((char*)&pgace->sid, worldsid, wsidsz);
2547 pos += wsidsz + 8;
2548 acecnt++;
2550 /* an ACE for administrators */
2551 /* always full access */
2553 pgace = (ACCESS_ALLOWED_ACE*)&secattr[offs + pos];
2554 pgace->type = ACCESS_ALLOWED_ACE_TYPE;
2555 if (isdir)
2556 pgace->flags = DIR_INHERITANCE;
2557 else
2558 pgace->flags = FILE_INHERITANCE;
2559 pgace->size = cpu_to_le16(asidsz + 8);
2560 grants = OWNER_RIGHTS | FILE_READ | FILE_WRITE | FILE_EXEC;
2561 pgace->mask = grants;
2562 memcpy((char*)&pgace->sid, adminsid, asidsz);
2563 pos += asidsz + 8;
2564 acecnt++;
2566 /* an ACE for system (needed ?) */
2567 /* always full access */
2569 pgace = (ACCESS_ALLOWED_ACE*)&secattr[offs + pos];
2570 pgace->type = ACCESS_ALLOWED_ACE_TYPE;
2571 if (isdir)
2572 pgace->flags = DIR_INHERITANCE;
2573 else
2574 pgace->flags = FILE_INHERITANCE;
2575 pgace->size = cpu_to_le16(ssidsz + 8);
2576 grants = OWNER_RIGHTS | FILE_READ | FILE_WRITE | FILE_EXEC;
2577 pgace->mask = grants;
2578 memcpy((char*)&pgace->sid, systemsid, ssidsz);
2579 pos += ssidsz + 8;
2580 acecnt++;
2582 /* a null ACE to hold special flags */
2583 /* using the same representation as cygwin */
2585 if (mode & (S_ISVTX | S_ISGID | S_ISUID)) {
2586 nsidsz = ntfs_sid_size(nullsid);
2587 pgace = (ACCESS_ALLOWED_ACE*)&secattr[offs + pos];
2588 pgace->type = ACCESS_ALLOWED_ACE_TYPE;
2589 pgace->flags = NO_PROPAGATE_INHERIT_ACE;
2590 pgace->size = cpu_to_le16(nsidsz + 8);
2591 grants = const_cpu_to_le32(0);
2592 if (mode & S_ISUID)
2593 grants |= FILE_APPEND_DATA;
2594 if (mode & S_ISGID)
2595 grants |= FILE_WRITE_DATA;
2596 if (mode & S_ISVTX)
2597 grants |= FILE_READ_DATA;
2598 pgace->mask = grants;
2599 memcpy((char*)&pgace->sid, nullsid, nsidsz);
2600 pos += nsidsz + 8;
2601 acecnt++;
2604 /* fix ACL header */
2605 pacl->size = cpu_to_le16(pos);
2606 pacl->ace_count = cpu_to_le16(acecnt);
2607 return (pos);
2610 #if POSIXACLS
2613 * Build a full security descriptor from a Posix ACL
2614 * returns descriptor in allocated memory, must free() after use
2617 char *ntfs_build_descr_posix(struct MAPPING* const mapping[],
2618 struct POSIX_SECURITY *pxdesc,
2619 int isdir, const SID *usid, const SID *gsid)
2621 int newattrsz;
2622 SECURITY_DESCRIPTOR_RELATIVE *pnhead;
2623 char *newattr;
2624 int aclsz;
2625 int usidsz;
2626 int gsidsz;
2627 int wsidsz;
2628 int asidsz;
2629 int ssidsz;
2630 int k;
2632 usidsz = ntfs_sid_size(usid);
2633 gsidsz = ntfs_sid_size(gsid);
2634 wsidsz = ntfs_sid_size(worldsid);
2635 asidsz = ntfs_sid_size(adminsid);
2636 ssidsz = ntfs_sid_size(systemsid);
2638 /* allocate enough space for the new security attribute */
2639 newattrsz = sizeof(SECURITY_DESCRIPTOR_RELATIVE) /* header */
2640 + usidsz + gsidsz /* usid and gsid */
2641 + sizeof(ACL) /* acl header */
2642 + 2*(8 + usidsz) /* two possible ACE for user */
2643 + 3*(8 + gsidsz) /* three possible ACE for group and mask */
2644 + 8 + wsidsz /* one ACE for world */
2645 + 8 + asidsz /* one ACE for admin */
2646 + 8 + ssidsz; /* one ACE for system */
2647 if (isdir) /* a world denial for directories */
2648 newattrsz += 8 + wsidsz;
2649 if (pxdesc->mode & 07000) /* a NULL ACE for special modes */
2650 newattrsz += 8 + ntfs_sid_size(nullsid);
2651 /* account for non-owning users and groups */
2652 for (k=0; k<pxdesc->acccnt; k++) {
2653 if ((pxdesc->acl.ace[k].tag == POSIX_ACL_USER)
2654 || (pxdesc->acl.ace[k].tag == POSIX_ACL_GROUP))
2655 newattrsz += 3*40; /* fixme : maximum size */
2657 /* account for default ACE's */
2658 newattrsz += 2*40*pxdesc->defcnt; /* fixme : maximum size */
2659 newattr = (char*)ntfs_malloc(newattrsz);
2660 if (newattr) {
2661 /* build the main header part */
2662 pnhead = (SECURITY_DESCRIPTOR_RELATIVE*)newattr;
2663 pnhead->revision = SECURITY_DESCRIPTOR_REVISION;
2664 pnhead->alignment = 0;
2666 * The flag SE_DACL_PROTECTED prevents the ACL
2667 * to be changed in an inheritance after creation
2669 pnhead->control = SE_DACL_PRESENT | SE_DACL_PROTECTED
2670 | SE_SELF_RELATIVE;
2672 * Windows prefers ACL first, do the same to
2673 * get the same hash value and avoid duplication
2675 /* build permissions */
2676 aclsz = buildacls_posix(mapping,newattr,
2677 sizeof(SECURITY_DESCRIPTOR_RELATIVE),
2678 pxdesc, isdir, usid, gsid);
2679 if (aclsz && ((int)(sizeof(SECURITY_DESCRIPTOR_RELATIVE)
2680 + aclsz + usidsz + gsidsz) <= newattrsz)) {
2681 /* append usid and gsid */
2682 memcpy(&newattr[sizeof(SECURITY_DESCRIPTOR_RELATIVE)
2683 + aclsz], usid, usidsz);
2684 memcpy(&newattr[sizeof(SECURITY_DESCRIPTOR_RELATIVE)
2685 + aclsz + usidsz], gsid, gsidsz);
2686 /* positions of ACL, USID and GSID into header */
2687 pnhead->owner =
2688 cpu_to_le32(sizeof(SECURITY_DESCRIPTOR_RELATIVE)
2689 + aclsz);
2690 pnhead->group =
2691 cpu_to_le32(sizeof(SECURITY_DESCRIPTOR_RELATIVE)
2692 + aclsz + usidsz);
2693 pnhead->sacl = const_cpu_to_le32(0);
2694 pnhead->dacl =
2695 const_cpu_to_le32(sizeof(SECURITY_DESCRIPTOR_RELATIVE));
2696 } else {
2697 /* ACL failure (errno set) or overflow */
2698 free(newattr);
2699 newattr = (char*)NULL;
2700 if (aclsz) {
2701 /* hope error was detected before overflowing */
2702 ntfs_log_error("Security descriptor is longer than expected\n");
2703 errno = EIO;
2706 } else
2707 errno = ENOMEM;
2708 return (newattr);
2711 #endif /* POSIXACLS */
2714 * Build a full security descriptor
2715 * returns descriptor in allocated memory, must free() after use
2718 char *ntfs_build_descr(mode_t mode,
2719 int isdir, const SID * usid, const SID * gsid)
2721 int newattrsz;
2722 SECURITY_DESCRIPTOR_RELATIVE *pnhead;
2723 char *newattr;
2724 int aclsz;
2725 int usidsz;
2726 int gsidsz;
2727 int wsidsz;
2728 int asidsz;
2729 int ssidsz;
2731 usidsz = ntfs_sid_size(usid);
2732 gsidsz = ntfs_sid_size(gsid);
2733 wsidsz = ntfs_sid_size(worldsid);
2734 asidsz = ntfs_sid_size(adminsid);
2735 ssidsz = ntfs_sid_size(systemsid);
2737 /* allocate enough space for the new security attribute */
2738 newattrsz = sizeof(SECURITY_DESCRIPTOR_RELATIVE) /* header */
2739 + usidsz + gsidsz /* usid and gsid */
2740 + sizeof(ACL) /* acl header */
2741 + 2*(8 + usidsz) /* two possible ACE for user */
2742 + 2*(8 + gsidsz) /* two possible ACE for group */
2743 + 8 + wsidsz /* one ACE for world */
2744 + 8 + asidsz /* one ACE for admin */
2745 + 8 + ssidsz; /* one ACE for system */
2746 if (isdir) /* a world denial for directories */
2747 newattrsz += 8 + wsidsz;
2748 if (mode & 07000) /* a NULL ACE for special modes */
2749 newattrsz += 8 + ntfs_sid_size(nullsid);
2750 newattr = (char*)ntfs_malloc(newattrsz);
2751 if (newattr) {
2752 /* build the main header part */
2753 pnhead = (SECURITY_DESCRIPTOR_RELATIVE*) newattr;
2754 pnhead->revision = SECURITY_DESCRIPTOR_REVISION;
2755 pnhead->alignment = 0;
2757 * The flag SE_DACL_PROTECTED prevents the ACL
2758 * to be changed in an inheritance after creation
2760 pnhead->control = SE_DACL_PRESENT | SE_DACL_PROTECTED
2761 | SE_SELF_RELATIVE;
2763 * Windows prefers ACL first, do the same to
2764 * get the same hash value and avoid duplication
2766 /* build permissions */
2767 aclsz = buildacls(newattr,
2768 sizeof(SECURITY_DESCRIPTOR_RELATIVE),
2769 mode, isdir, usid, gsid);
2770 if (((int)sizeof(SECURITY_DESCRIPTOR_RELATIVE)
2771 + aclsz + usidsz + gsidsz) <= newattrsz) {
2772 /* append usid and gsid */
2773 memcpy(&newattr[sizeof(SECURITY_DESCRIPTOR_RELATIVE)
2774 + aclsz], usid, usidsz);
2775 memcpy(&newattr[sizeof(SECURITY_DESCRIPTOR_RELATIVE)
2776 + aclsz + usidsz], gsid, gsidsz);
2777 /* positions of ACL, USID and GSID into header */
2778 pnhead->owner =
2779 cpu_to_le32(sizeof(SECURITY_DESCRIPTOR_RELATIVE)
2780 + aclsz);
2781 pnhead->group =
2782 cpu_to_le32(sizeof(SECURITY_DESCRIPTOR_RELATIVE)
2783 + aclsz + usidsz);
2784 pnhead->sacl = const_cpu_to_le32(0);
2785 pnhead->dacl =
2786 const_cpu_to_le32(sizeof(SECURITY_DESCRIPTOR_RELATIVE));
2787 } else {
2788 /* hope error was detected before overflowing */
2789 free(newattr);
2790 newattr = (char*)NULL;
2791 ntfs_log_error("Security descriptor is longer than expected\n");
2792 errno = EIO;
2794 } else
2795 errno = ENOMEM;
2796 return (newattr);
2800 * Create a mode_t permission set
2801 * from owner, group and world grants as represented in ACEs
2804 static int merge_permissions(BOOL isdir,
2805 le32 owner, le32 group, le32 world, le32 special)
2808 int perm;
2810 perm = 0;
2811 /* build owner permission */
2812 if (owner) {
2813 if (isdir) {
2814 /* exec if any of list, traverse */
2815 if (owner & DIR_GEXEC)
2816 perm |= S_IXUSR;
2817 /* write if any of addfile, adddir, delchild */
2818 if (owner & DIR_GWRITE)
2819 perm |= S_IWUSR;
2820 /* read if any of list */
2821 if (owner & DIR_GREAD)
2822 perm |= S_IRUSR;
2823 } else {
2824 /* exec if execute or generic execute */
2825 if (owner & FILE_GEXEC)
2826 perm |= S_IXUSR;
2827 /* write if any of writedata or generic write */
2828 if (owner & FILE_GWRITE)
2829 perm |= S_IWUSR;
2830 /* read if any of readdata or generic read */
2831 if (owner & FILE_GREAD)
2832 perm |= S_IRUSR;
2835 /* build group permission */
2836 if (group) {
2837 if (isdir) {
2838 /* exec if any of list, traverse */
2839 if (group & DIR_GEXEC)
2840 perm |= S_IXGRP;
2841 /* write if any of addfile, adddir, delchild */
2842 if (group & DIR_GWRITE)
2843 perm |= S_IWGRP;
2844 /* read if any of list */
2845 if (group & DIR_GREAD)
2846 perm |= S_IRGRP;
2847 } else {
2848 /* exec if execute */
2849 if (group & FILE_GEXEC)
2850 perm |= S_IXGRP;
2851 /* write if any of writedata, appenddata */
2852 if (group & FILE_GWRITE)
2853 perm |= S_IWGRP;
2854 /* read if any of readdata */
2855 if (group & FILE_GREAD)
2856 perm |= S_IRGRP;
2859 /* build world permission */
2860 if (world) {
2861 if (isdir) {
2862 /* exec if any of list, traverse */
2863 if (world & DIR_GEXEC)
2864 perm |= S_IXOTH;
2865 /* write if any of addfile, adddir, delchild */
2866 if (world & DIR_GWRITE)
2867 perm |= S_IWOTH;
2868 /* read if any of list */
2869 if (world & DIR_GREAD)
2870 perm |= S_IROTH;
2871 } else {
2872 /* exec if execute */
2873 if (world & FILE_GEXEC)
2874 perm |= S_IXOTH;
2875 /* write if any of writedata, appenddata */
2876 if (world & FILE_GWRITE)
2877 perm |= S_IWOTH;
2878 /* read if any of readdata */
2879 if (world & FILE_GREAD)
2880 perm |= S_IROTH;
2883 /* build special permission flags */
2884 if (special) {
2885 if (special & FILE_APPEND_DATA)
2886 perm |= S_ISUID;
2887 if (special & FILE_WRITE_DATA)
2888 perm |= S_ISGID;
2889 if (special & FILE_READ_DATA)
2890 perm |= S_ISVTX;
2892 return (perm);
2895 #if POSIXACLS
2898 * Normalize a Posix ACL either from a sorted raw set of
2899 * access ACEs or default ACEs
2900 * (standard case : different owner, group and administrator)
2903 static int norm_std_permissions_posix(struct POSIX_SECURITY *posix_desc,
2904 BOOL groupowns, int start, int count, int target)
2906 int j,k;
2907 s32 id;
2908 u16 tag;
2909 u16 tagsset;
2910 struct POSIX_ACE *pxace;
2911 mode_t grantgrps;
2912 mode_t grantwrld;
2913 mode_t denywrld;
2914 mode_t allow;
2915 mode_t deny;
2916 mode_t perms;
2917 mode_t mode;
2919 mode = 0;
2920 tagsset = 0;
2922 * Determine what is granted to some group or world
2923 * Also get denials to world which are meant to prevent
2924 * execution flags to be inherited by plain files
2926 pxace = posix_desc->acl.ace;
2927 grantgrps = 0;
2928 grantwrld = 0;
2929 denywrld = 0;
2930 for (j=start; j<(start + count); j++) {
2931 if (pxace[j].perms & POSIX_PERM_DENIAL) {
2932 /* deny world exec unless for default */
2933 if ((pxace[j].tag == POSIX_ACL_OTHER)
2934 && !start)
2935 denywrld = pxace[j].perms;
2936 } else {
2937 switch (pxace[j].tag) {
2938 case POSIX_ACL_GROUP_OBJ :
2939 grantgrps |= pxace[j].perms;
2940 break;
2941 case POSIX_ACL_GROUP :
2942 if (pxace[j].id)
2943 grantgrps |= pxace[j].perms;
2944 break;
2945 case POSIX_ACL_OTHER :
2946 grantwrld = pxace[j].perms;
2947 break;
2948 default :
2949 break;
2954 * Collect groups of ACEs related to the same id
2955 * and determine what is granted and what is denied.
2956 * It is important the ACEs have been sorted
2958 j = start;
2959 k = target;
2960 while (j < (start + count)) {
2961 tag = pxace[j].tag;
2962 id = pxace[j].id;
2963 if (pxace[j].perms & POSIX_PERM_DENIAL) {
2964 deny = pxace[j].perms | denywrld;
2965 allow = 0;
2966 } else {
2967 deny = denywrld;
2968 allow = pxace[j].perms;
2970 j++;
2971 while ((j < (start + count))
2972 && (pxace[j].tag == tag)
2973 && (pxace[j].id == id)) {
2974 if (pxace[j].perms & POSIX_PERM_DENIAL)
2975 deny |= pxace[j].perms;
2976 else
2977 allow |= pxace[j].perms;
2978 j++;
2981 * Build the permissions equivalent to grants and denials
2983 if (groupowns) {
2984 if (tag == POSIX_ACL_MASK)
2985 perms = ~deny;
2986 else
2987 perms = allow & ~deny;
2988 } else
2989 switch (tag) {
2990 case POSIX_ACL_USER_OBJ :
2991 perms = (allow | grantgrps | grantwrld) & ~deny;
2992 break;
2993 case POSIX_ACL_USER :
2994 if (id)
2995 perms = (allow | grantgrps | grantwrld)
2996 & ~deny;
2997 else
2998 perms = allow;
2999 break;
3000 case POSIX_ACL_GROUP_OBJ :
3001 perms = (allow | grantwrld) & ~deny;
3002 break;
3003 case POSIX_ACL_GROUP :
3004 if (id)
3005 perms = (allow | grantwrld) & ~deny;
3006 else
3007 perms = allow;
3008 break;
3009 case POSIX_ACL_MASK :
3010 perms = ~deny;
3011 break;
3012 default :
3013 perms = allow & ~deny;
3014 break;
3017 * Store into a Posix ACE
3019 if (tag != POSIX_ACL_SPECIAL) {
3020 pxace[k].tag = tag;
3021 pxace[k].id = id;
3022 pxace[k].perms = perms
3023 & (POSIX_PERM_R | POSIX_PERM_W | POSIX_PERM_X);
3024 tagsset |= tag;
3025 k++;
3027 switch (tag) {
3028 case POSIX_ACL_USER_OBJ :
3029 mode |= ((perms & 7) << 6);
3030 break;
3031 case POSIX_ACL_GROUP_OBJ :
3032 case POSIX_ACL_MASK :
3033 mode = (mode & 07707) | ((perms & 7) << 3);
3034 break;
3035 case POSIX_ACL_OTHER :
3036 mode |= perms & 7;
3037 break;
3038 case POSIX_ACL_SPECIAL :
3039 mode |= (perms & (S_ISVTX | S_ISUID | S_ISGID));
3040 break;
3041 default :
3042 break;
3045 if (!start) { /* not satisfactory */
3046 posix_desc->mode = mode;
3047 posix_desc->tagsset = tagsset;
3049 return (k - target);
3052 #endif /* POSIXACLS */
3055 * Interpret an ACL and extract meaningful grants
3056 * (standard case : different owner, group and administrator)
3059 static int build_std_permissions(const char *securattr,
3060 const SID *usid, const SID *gsid, BOOL isdir)
3062 const SECURITY_DESCRIPTOR_RELATIVE *phead;
3063 const ACL *pacl;
3064 const ACCESS_ALLOWED_ACE *pace;
3065 int offdacl;
3066 int offace;
3067 int acecnt;
3068 int nace;
3069 BOOL noown;
3070 le32 special;
3071 le32 allowown, allowgrp, allowall;
3072 le32 denyown, denygrp, denyall;
3074 phead = (const SECURITY_DESCRIPTOR_RELATIVE*)securattr;
3075 offdacl = le32_to_cpu(phead->dacl);
3076 pacl = (const ACL*)&securattr[offdacl];
3077 special = const_cpu_to_le32(0);
3078 allowown = allowgrp = allowall = const_cpu_to_le32(0);
3079 denyown = denygrp = denyall = const_cpu_to_le32(0);
3080 noown = TRUE;
3081 if (offdacl) {
3082 acecnt = le16_to_cpu(pacl->ace_count);
3083 offace = offdacl + sizeof(ACL);
3084 } else {
3085 acecnt = 0;
3086 offace = 0;
3088 for (nace = 0; nace < acecnt; nace++) {
3089 pace = (const ACCESS_ALLOWED_ACE*)&securattr[offace];
3090 if (!(pace->flags & INHERIT_ONLY_ACE)) {
3091 if (ntfs_same_sid(usid, &pace->sid)
3092 || ntfs_same_sid(ownersid, &pace->sid)) {
3093 noown = FALSE;
3094 if (pace->type == ACCESS_ALLOWED_ACE_TYPE)
3095 allowown |= pace->mask;
3096 else if (pace->type == ACCESS_DENIED_ACE_TYPE)
3097 denyown |= pace->mask;
3098 } else
3099 if (ntfs_same_sid(gsid, &pace->sid)
3100 && !(pace->mask & WRITE_OWNER)) {
3101 if (pace->type == ACCESS_ALLOWED_ACE_TYPE)
3102 allowgrp |= pace->mask;
3103 else if (pace->type == ACCESS_DENIED_ACE_TYPE)
3104 denygrp |= pace->mask;
3105 } else
3106 if (is_world_sid((const SID*)&pace->sid)) {
3107 if (pace->type == ACCESS_ALLOWED_ACE_TYPE)
3108 allowall |= pace->mask;
3109 else
3110 if (pace->type == ACCESS_DENIED_ACE_TYPE)
3111 denyall |= pace->mask;
3112 } else
3113 if ((ntfs_same_sid((const SID*)&pace->sid,nullsid))
3114 && (pace->type == ACCESS_ALLOWED_ACE_TYPE))
3115 special |= pace->mask;
3117 offace += le16_to_cpu(pace->size);
3120 * No indication about owner's rights : grant basic rights
3121 * This happens for files created by Windows in directories
3122 * created by Linux and owned by root, because Windows
3123 * merges the admin ACEs
3125 if (noown)
3126 allowown = (FILE_READ_DATA | FILE_WRITE_DATA | FILE_EXECUTE);
3128 * Add to owner rights granted to group or world
3129 * unless denied personaly, and add to group rights
3130 * granted to world unless denied specifically
3132 allowown |= (allowgrp | allowall);
3133 allowgrp |= allowall;
3134 return (merge_permissions(isdir,
3135 allowown & ~(denyown | denyall),
3136 allowgrp & ~(denygrp | denyall),
3137 allowall & ~denyall,
3138 special));
3142 * Interpret an ACL and extract meaningful grants
3143 * (special case : owner and group are the same,
3144 * and not administrator)
3147 static int build_owngrp_permissions(const char *securattr,
3148 const SID *usid, BOOL isdir)
3150 const SECURITY_DESCRIPTOR_RELATIVE *phead;
3151 const ACL *pacl;
3152 const ACCESS_ALLOWED_ACE *pace;
3153 int offdacl;
3154 int offace;
3155 int acecnt;
3156 int nace;
3157 le32 special;
3158 BOOL grppresent;
3159 BOOL ownpresent;
3160 le32 allowown, allowgrp, allowall;
3161 le32 denyown, denygrp, denyall;
3163 phead = (const SECURITY_DESCRIPTOR_RELATIVE*)securattr;
3164 offdacl = le32_to_cpu(phead->dacl);
3165 pacl = (const ACL*)&securattr[offdacl];
3166 special = const_cpu_to_le32(0);
3167 allowown = allowgrp = allowall = const_cpu_to_le32(0);
3168 denyown = denygrp = denyall = const_cpu_to_le32(0);
3169 ownpresent = FALSE;
3170 grppresent = FALSE;
3171 if (offdacl) {
3172 acecnt = le16_to_cpu(pacl->ace_count);
3173 offace = offdacl + sizeof(ACL);
3174 } else {
3175 acecnt = 0;
3176 offace = 0;
3178 for (nace = 0; nace < acecnt; nace++) {
3179 pace = (const ACCESS_ALLOWED_ACE*)&securattr[offace];
3180 if (!(pace->flags & INHERIT_ONLY_ACE)) {
3181 if ((ntfs_same_sid(usid, &pace->sid)
3182 || ntfs_same_sid(ownersid, &pace->sid))
3183 && (pace->mask & WRITE_OWNER)) {
3184 if (pace->type == ACCESS_ALLOWED_ACE_TYPE) {
3185 allowown |= pace->mask;
3186 ownpresent = TRUE;
3188 } else
3189 if (ntfs_same_sid(usid, &pace->sid)
3190 && (!(pace->mask & WRITE_OWNER))) {
3191 if (pace->type == ACCESS_ALLOWED_ACE_TYPE) {
3192 allowgrp |= pace->mask;
3193 grppresent = TRUE;
3195 } else
3196 if (is_world_sid((const SID*)&pace->sid)) {
3197 if (pace->type == ACCESS_ALLOWED_ACE_TYPE)
3198 allowall |= pace->mask;
3199 else
3200 if (pace->type == ACCESS_DENIED_ACE_TYPE)
3201 denyall |= pace->mask;
3202 } else
3203 if ((ntfs_same_sid((const SID*)&pace->sid,nullsid))
3204 && (pace->type == ACCESS_ALLOWED_ACE_TYPE))
3205 special |= pace->mask;
3207 offace += le16_to_cpu(pace->size);
3209 if (!ownpresent)
3210 allowown = allowall;
3211 if (!grppresent)
3212 allowgrp = allowall;
3213 return (merge_permissions(isdir,
3214 allowown & ~(denyown | denyall),
3215 allowgrp & ~(denygrp | denyall),
3216 allowall & ~denyall,
3217 special));
3220 #if POSIXACLS
3223 * Normalize a Posix ACL either from a sorted raw set of
3224 * access ACEs or default ACEs
3225 * (special case : owner or/and group is administrator)
3228 static int norm_ownadmin_permissions_posix(struct POSIX_SECURITY *posix_desc,
3229 int start, int count, int target)
3231 int j,k;
3232 s32 id;
3233 u16 tag;
3234 u16 tagsset;
3235 struct POSIX_ACE *pxace;
3236 mode_t denywrld;
3237 mode_t allow;
3238 mode_t deny;
3239 mode_t perms;
3240 mode_t mode;
3242 mode = 0;
3243 pxace = posix_desc->acl.ace;
3244 tagsset = 0;
3245 denywrld = 0;
3247 * Get denials to world which are meant to prevent
3248 * execution flags to be inherited by plain files
3250 for (j=start; j<(start + count); j++) {
3251 if (pxace[j].perms & POSIX_PERM_DENIAL) {
3252 /* deny world exec not for default */
3253 if ((pxace[j].tag == POSIX_ACL_OTHER)
3254 && !start)
3255 denywrld = pxace[j].perms;
3259 * Collect groups of ACEs related to the same id
3260 * and determine what is granted (denials are ignored)
3261 * It is important the ACEs have been sorted
3263 j = start;
3264 k = target;
3265 deny = 0;
3266 while (j < (start + count)) {
3267 allow = 0;
3268 tag = pxace[j].tag;
3269 id = pxace[j].id;
3270 if (tag == POSIX_ACL_MASK) {
3271 deny = pxace[j].perms;
3272 j++;
3273 while ((j < (start + count))
3274 && (pxace[j].tag == POSIX_ACL_MASK))
3275 j++;
3276 } else {
3277 if (!(pxace[j].perms & POSIX_PERM_DENIAL))
3278 allow = pxace[j].perms;
3279 j++;
3280 while ((j < (start + count))
3281 && (pxace[j].tag == tag)
3282 && (pxace[j].id == id)) {
3283 if (!(pxace[j].perms & POSIX_PERM_DENIAL))
3284 allow |= pxace[j].perms;
3285 j++;
3290 * Store the grants into a Posix ACE
3292 if (tag == POSIX_ACL_MASK)
3293 perms = ~deny;
3294 else
3295 perms = allow & ~denywrld;
3296 if (tag != POSIX_ACL_SPECIAL) {
3297 pxace[k].tag = tag;
3298 pxace[k].id = id;
3299 pxace[k].perms = perms
3300 & (POSIX_PERM_R | POSIX_PERM_W | POSIX_PERM_X);
3301 tagsset |= tag;
3302 k++;
3304 switch (tag) {
3305 case POSIX_ACL_USER_OBJ :
3306 mode |= ((perms & 7) << 6);
3307 break;
3308 case POSIX_ACL_GROUP_OBJ :
3309 case POSIX_ACL_MASK :
3310 mode = (mode & 07707) | ((perms & 7) << 3);
3311 break;
3312 case POSIX_ACL_OTHER :
3313 mode |= perms & 7;
3314 break;
3315 case POSIX_ACL_SPECIAL :
3316 mode |= perms & (S_ISVTX | S_ISUID | S_ISGID);
3317 break;
3318 default :
3319 break;
3322 if (!start) { /* not satisfactory */
3323 posix_desc->mode = mode;
3324 posix_desc->tagsset = tagsset;
3326 return (k - target);
3329 #endif /* POSIXACLS */
3332 * Interpret an ACL and extract meaningful grants
3333 * (special case : owner or/and group is administrator)
3337 static int build_ownadmin_permissions(const char *securattr,
3338 const SID *usid, const SID *gsid, BOOL isdir)
3340 const SECURITY_DESCRIPTOR_RELATIVE *phead;
3341 const ACL *pacl;
3342 const ACCESS_ALLOWED_ACE *pace;
3343 int offdacl;
3344 int offace;
3345 int acecnt;
3346 int nace;
3347 BOOL firstapply;
3348 int isforeign;
3349 le32 special;
3350 le32 allowown, allowgrp, allowall;
3351 le32 denyown, denygrp, denyall;
3353 phead = (const SECURITY_DESCRIPTOR_RELATIVE*)securattr;
3354 offdacl = le32_to_cpu(phead->dacl);
3355 pacl = (const ACL*)&securattr[offdacl];
3356 special = const_cpu_to_le32(0);
3357 allowown = allowgrp = allowall = const_cpu_to_le32(0);
3358 denyown = denygrp = denyall = const_cpu_to_le32(0);
3359 if (offdacl) {
3360 acecnt = le16_to_cpu(pacl->ace_count);
3361 offace = offdacl + sizeof(ACL);
3362 } else {
3363 acecnt = 0;
3364 offace = 0;
3366 firstapply = TRUE;
3367 isforeign = 3;
3368 for (nace = 0; nace < acecnt; nace++) {
3369 pace = (const ACCESS_ALLOWED_ACE*)&securattr[offace];
3370 if (!(pace->flags & INHERIT_ONLY_ACE)
3371 && !(~pace->mask & (ROOT_OWNER_UNMARK | ROOT_GROUP_UNMARK))) {
3372 if ((ntfs_same_sid(usid, &pace->sid)
3373 || ntfs_same_sid(ownersid, &pace->sid))
3374 && (((pace->mask & WRITE_OWNER) && firstapply))) {
3375 if (pace->type == ACCESS_ALLOWED_ACE_TYPE) {
3376 allowown |= pace->mask;
3377 isforeign &= ~1;
3378 } else
3379 if (pace->type == ACCESS_DENIED_ACE_TYPE)
3380 denyown |= pace->mask;
3381 } else
3382 if (ntfs_same_sid(gsid, &pace->sid)
3383 && (!(pace->mask & WRITE_OWNER))) {
3384 if (pace->type == ACCESS_ALLOWED_ACE_TYPE) {
3385 allowgrp |= pace->mask;
3386 isforeign &= ~2;
3387 } else
3388 if (pace->type == ACCESS_DENIED_ACE_TYPE)
3389 denygrp |= pace->mask;
3390 } else if (is_world_sid((const SID*)&pace->sid)) {
3391 if (pace->type == ACCESS_ALLOWED_ACE_TYPE)
3392 allowall |= pace->mask;
3393 else
3394 if (pace->type == ACCESS_DENIED_ACE_TYPE)
3395 denyall |= pace->mask;
3397 firstapply = FALSE;
3398 } else
3399 if (!(pace->flags & INHERIT_ONLY_ACE))
3400 if ((ntfs_same_sid((const SID*)&pace->sid,nullsid))
3401 && (pace->type == ACCESS_ALLOWED_ACE_TYPE))
3402 special |= pace->mask;
3403 offace += le16_to_cpu(pace->size);
3405 if (isforeign) {
3406 allowown |= (allowgrp | allowall);
3407 allowgrp |= allowall;
3409 return (merge_permissions(isdir,
3410 allowown & ~(denyown | denyall),
3411 allowgrp & ~(denygrp | denyall),
3412 allowall & ~denyall,
3413 special));
3416 #if OWNERFROMACL
3419 * Define the owner of a file as the first user allowed
3420 * to change the owner, instead of the user defined as owner.
3422 * This produces better approximations for files written by a
3423 * Windows user in an inheritable directory owned by another user,
3424 * as the access rights are inheritable but the ownership is not.
3426 * An important case is the directories "Documents and Settings/user"
3427 * which the users must have access to, though Windows considers them
3428 * as owned by administrator.
3431 const SID *ntfs_acl_owner(const char *securattr)
3433 const SECURITY_DESCRIPTOR_RELATIVE *phead;
3434 const SID *usid;
3435 const ACL *pacl;
3436 const ACCESS_ALLOWED_ACE *pace;
3437 int offdacl;
3438 int offace;
3439 int acecnt;
3440 int nace;
3441 BOOL found;
3443 found = FALSE;
3444 phead = (const SECURITY_DESCRIPTOR_RELATIVE*)securattr;
3445 offdacl = le32_to_cpu(phead->dacl);
3446 if (offdacl) {
3447 pacl = (const ACL*)&securattr[offdacl];
3448 acecnt = le16_to_cpu(pacl->ace_count);
3449 offace = offdacl + sizeof(ACL);
3450 nace = 0;
3451 do {
3452 pace = (const ACCESS_ALLOWED_ACE*)&securattr[offace];
3453 if ((pace->mask & WRITE_OWNER)
3454 && (pace->type == ACCESS_ALLOWED_ACE_TYPE)
3455 && ntfs_is_user_sid(&pace->sid))
3456 found = TRUE;
3457 offace += le16_to_cpu(pace->size);
3458 } while (!found && (++nace < acecnt));
3460 if (found)
3461 usid = &pace->sid;
3462 else
3463 usid = (const SID*)&securattr[le32_to_cpu(phead->owner)];
3464 return (usid);
3467 #else
3470 * Special case for files owned by administrator with full
3471 * access granted to a mapped user : consider this user as the tenant
3472 * of the file.
3474 * This situation cannot be represented with Linux concepts and can
3475 * only be found for files or directories created by Windows.
3476 * Typical situation : directory "Documents and Settings/user" which
3477 * is on the path to user's files and must be given access to user
3478 * only.
3480 * Check file is owned by administrator and no user has rights before
3481 * calling.
3482 * Returns the uid of tenant or zero if none
3486 static uid_t find_tenant(struct MAPPING *const mapping[],
3487 const char *securattr)
3489 const SECURITY_DESCRIPTOR_RELATIVE *phead;
3490 const ACL *pacl;
3491 const ACCESS_ALLOWED_ACE *pace;
3492 int offdacl;
3493 int offace;
3494 int acecnt;
3495 int nace;
3496 uid_t tid;
3497 uid_t xid;
3499 phead = (const SECURITY_DESCRIPTOR_RELATIVE*)securattr;
3500 offdacl = le32_to_cpu(phead->dacl);
3501 pacl = (const ACL*)&securattr[offdacl];
3502 tid = 0;
3503 if (offdacl) {
3504 acecnt = le16_to_cpu(pacl->ace_count);
3505 offace = offdacl + sizeof(ACL);
3506 } else
3507 acecnt = 0;
3508 for (nace = 0; nace < acecnt; nace++) {
3509 pace = (const ACCESS_ALLOWED_ACE*)&securattr[offace];
3510 if ((pace->type == ACCESS_ALLOWED_ACE_TYPE)
3511 && (pace->mask & DIR_WRITE)) {
3512 xid = NTFS_FIND_USER(mapping[MAPUSERS], &pace->sid);
3513 if (xid) tid = xid;
3515 offace += le16_to_cpu(pace->size);
3517 return (tid);
3520 #endif /* OWNERFROMACL */
3522 #if POSIXACLS
3525 * Build Posix permissions from an ACL
3526 * returns a pointer to the requested permissions
3527 * or a null pointer (with errno set) if there is a problem
3529 * If the NTFS ACL was created according to our rules, the retrieved
3530 * Posix ACL should be the exact ACL which was set. However if
3531 * the NTFS ACL was built by a different tool, the result could
3532 * be a a poor approximation of what was expected
3535 struct POSIX_SECURITY *ntfs_build_permissions_posix(
3536 struct MAPPING *const mapping[],
3537 const char *securattr,
3538 const SID *usid, const SID *gsid, BOOL isdir)
3540 const SECURITY_DESCRIPTOR_RELATIVE *phead;
3541 struct POSIX_SECURITY *pxdesc;
3542 const ACL *pacl;
3543 const ACCESS_ALLOWED_ACE *pace;
3544 struct POSIX_ACE *pxace;
3545 struct {
3546 uid_t prevuid;
3547 gid_t prevgid;
3548 int groupmasks;
3549 s16 tagsset;
3550 BOOL gotowner;
3551 BOOL gotownermask;
3552 BOOL gotgroup;
3553 mode_t permswrld;
3554 } ctx[2], *pctx;
3555 int offdacl;
3556 int offace;
3557 int alloccnt;
3558 int acecnt;
3559 uid_t uid;
3560 gid_t gid;
3561 int i,j;
3562 int k,l;
3563 BOOL ignore;
3564 BOOL adminowns;
3565 BOOL groupowns;
3566 BOOL firstinh;
3567 BOOL genericinh;
3569 phead = (const SECURITY_DESCRIPTOR_RELATIVE*)securattr;
3570 offdacl = le32_to_cpu(phead->dacl);
3571 if (offdacl) {
3572 pacl = (const ACL*)&securattr[offdacl];
3573 acecnt = le16_to_cpu(pacl->ace_count);
3574 offace = offdacl + sizeof(ACL);
3575 } else {
3576 acecnt = 0;
3577 offace = 0;
3579 adminowns = FALSE;
3580 groupowns = ntfs_same_sid(gsid,usid);
3581 firstinh = FALSE;
3582 genericinh = FALSE;
3584 * Build a raw posix security descriptor
3585 * by just translating permissions and ids
3586 * Add 2 to the count of ACE to be able to insert
3587 * a group ACE later in access and default ACLs
3588 * and add 2 more to be able to insert ACEs for owner
3589 * and 2 more for other
3591 alloccnt = acecnt + 6;
3592 pxdesc = (struct POSIX_SECURITY*)malloc(
3593 sizeof(struct POSIX_SECURITY)
3594 + alloccnt*sizeof(struct POSIX_ACE));
3595 k = 0;
3596 l = alloccnt;
3597 for (i=0; i<2; i++) {
3598 pctx = &ctx[i];
3599 pctx->permswrld = 0;
3600 pctx->prevuid = -1;
3601 pctx->prevgid = -1;
3602 pctx->groupmasks = 0;
3603 pctx->tagsset = 0;
3604 pctx->gotowner = FALSE;
3605 pctx->gotgroup = FALSE;
3606 pctx->gotownermask = FALSE;
3608 for (j=0; j<acecnt; j++) {
3609 pace = (const ACCESS_ALLOWED_ACE*)&securattr[offace];
3610 if (pace->flags & INHERIT_ONLY_ACE) {
3611 pxace = &pxdesc->acl.ace[l - 1];
3612 pctx = &ctx[1];
3613 } else {
3614 pxace = &pxdesc->acl.ace[k];
3615 pctx = &ctx[0];
3617 ignore = FALSE;
3619 * grants for root as a designated user or group
3621 if ((~pace->mask & (ROOT_OWNER_UNMARK | ROOT_GROUP_UNMARK))
3622 && (pace->type == ACCESS_ALLOWED_ACE_TYPE)
3623 && ntfs_same_sid(&pace->sid, adminsid)) {
3624 pxace->tag = (pace->mask & ROOT_OWNER_UNMARK ? POSIX_ACL_GROUP : POSIX_ACL_USER);
3625 pxace->id = 0;
3626 if ((pace->mask & (GENERIC_ALL | WRITE_OWNER))
3627 && (pace->flags & INHERIT_ONLY_ACE))
3628 ignore = genericinh = TRUE;
3629 } else
3630 if (ntfs_same_sid(usid, &pace->sid)) {
3631 pxace->id = -1;
3633 * Owner has no write-owner right :
3634 * a group was defined same as owner
3635 * or admin was owner or group :
3636 * denials are meant to owner
3637 * and grants are meant to group
3639 if (!(pace->mask & (WRITE_OWNER | GENERIC_ALL))
3640 && (pace->type == ACCESS_ALLOWED_ACE_TYPE)) {
3641 if (ntfs_same_sid(gsid,usid)) {
3642 pxace->tag = POSIX_ACL_GROUP_OBJ;
3643 pxace->id = -1;
3644 } else {
3645 if (ntfs_same_sid(&pace->sid,usid))
3646 groupowns = TRUE;
3647 gid = NTFS_FIND_GROUP(mapping[MAPGROUPS],&pace->sid);
3648 if (gid) {
3649 pxace->tag = POSIX_ACL_GROUP;
3650 pxace->id = gid;
3651 pctx->prevgid = gid;
3652 } else {
3653 uid = NTFS_FIND_USER(mapping[MAPUSERS],&pace->sid);
3654 if (uid) {
3655 pxace->tag = POSIX_ACL_USER;
3656 pxace->id = uid;
3657 } else
3658 ignore = TRUE;
3661 } else {
3663 * when group owns, late denials for owner
3664 * mean group mask
3666 if ((pace->type == ACCESS_DENIED_ACE_TYPE)
3667 && (pace->mask & WRITE_OWNER)) {
3668 pxace->tag = POSIX_ACL_MASK;
3669 pctx->gotownermask = TRUE;
3670 if (pctx->gotowner)
3671 pctx->groupmasks++;
3672 } else {
3673 if (pace->type == ACCESS_ALLOWED_ACE_TYPE)
3674 pctx->gotowner = TRUE;
3675 if (pctx->gotownermask && !pctx->gotowner) {
3676 uid = NTFS_FIND_USER(mapping[MAPUSERS],&pace->sid);
3677 pxace->id = uid;
3678 pxace->tag = POSIX_ACL_USER;
3679 } else
3680 pxace->tag = POSIX_ACL_USER_OBJ;
3681 /* system ignored, and admin */
3682 /* ignored at first position */
3683 if (pace->flags & INHERIT_ONLY_ACE) {
3684 if ((firstinh && ntfs_same_sid(&pace->sid,adminsid))
3685 || ntfs_same_sid(&pace->sid,systemsid))
3686 ignore = TRUE;
3687 if (!firstinh) {
3688 firstinh = TRUE;
3690 } else {
3691 if ((adminowns && ntfs_same_sid(&pace->sid,adminsid))
3692 || ntfs_same_sid(&pace->sid,systemsid))
3693 ignore = TRUE;
3694 if (ntfs_same_sid(usid,adminsid))
3695 adminowns = TRUE;
3699 } else if (ntfs_same_sid(gsid, &pace->sid)) {
3700 if ((pace->type == ACCESS_DENIED_ACE_TYPE)
3701 && (pace->mask & WRITE_OWNER)) {
3702 pxace->tag = POSIX_ACL_MASK;
3703 pxace->id = -1;
3704 if (pctx->gotowner)
3705 pctx->groupmasks++;
3706 } else {
3707 if (pctx->gotgroup || (pctx->groupmasks > 1)) {
3708 gid = NTFS_FIND_GROUP(mapping[MAPGROUPS],&pace->sid);
3709 if (gid) {
3710 pxace->id = gid;
3711 pxace->tag = POSIX_ACL_GROUP;
3712 pctx->prevgid = gid;
3713 } else
3714 ignore = TRUE;
3715 } else {
3716 pxace->id = -1;
3717 pxace->tag = POSIX_ACL_GROUP_OBJ;
3718 if (pace->type == ACCESS_ALLOWED_ACE_TYPE)
3719 pctx->gotgroup = TRUE;
3722 if (ntfs_same_sid(gsid,adminsid)
3723 || ntfs_same_sid(gsid,systemsid)) {
3724 if (pace->mask & (WRITE_OWNER | GENERIC_ALL))
3725 ignore = TRUE;
3726 if (ntfs_same_sid(gsid,adminsid))
3727 adminowns = TRUE;
3728 else
3729 genericinh = ignore;
3732 } else if (is_world_sid((const SID*)&pace->sid)) {
3733 pxace->id = -1;
3734 pxace->tag = POSIX_ACL_OTHER;
3735 if ((pace->type == ACCESS_DENIED_ACE_TYPE)
3736 && (pace->flags & INHERIT_ONLY_ACE))
3737 ignore = TRUE;
3738 } else if (ntfs_same_sid((const SID*)&pace->sid,nullsid)) {
3739 pxace->id = -1;
3740 pxace->tag = POSIX_ACL_SPECIAL;
3741 } else {
3742 uid = NTFS_FIND_USER(mapping[MAPUSERS],&pace->sid);
3743 if (uid) {
3744 if ((pace->type == ACCESS_DENIED_ACE_TYPE)
3745 && (pace->mask & WRITE_OWNER)
3746 && (pctx->prevuid != uid)) {
3747 pxace->id = -1;
3748 pxace->tag = POSIX_ACL_MASK;
3749 } else {
3750 pxace->id = uid;
3751 pxace->tag = POSIX_ACL_USER;
3753 pctx->prevuid = uid;
3754 } else {
3755 gid = NTFS_FIND_GROUP(mapping[MAPGROUPS],&pace->sid);
3756 if (gid) {
3757 if ((pace->type == ACCESS_DENIED_ACE_TYPE)
3758 && (pace->mask & WRITE_OWNER)
3759 && (pctx->prevgid != gid)) {
3760 pxace->tag = POSIX_ACL_MASK;
3761 pctx->groupmasks++;
3762 } else {
3763 pxace->tag = POSIX_ACL_GROUP;
3765 pxace->id = gid;
3766 pctx->prevgid = gid;
3767 } else {
3769 * do not grant rights to unknown
3770 * people and do not define root as a
3771 * designated user or group
3773 ignore = TRUE;
3777 if (!ignore) {
3778 pxace->perms = 0;
3779 /* specific decoding for vtx/uid/gid */
3780 if (pxace->tag == POSIX_ACL_SPECIAL) {
3781 if (pace->mask & FILE_APPEND_DATA)
3782 pxace->perms |= S_ISUID;
3783 if (pace->mask & FILE_WRITE_DATA)
3784 pxace->perms |= S_ISGID;
3785 if (pace->mask & FILE_READ_DATA)
3786 pxace->perms |= S_ISVTX;
3787 } else
3788 if (isdir) {
3789 if (pace->mask & DIR_GEXEC)
3790 pxace->perms |= POSIX_PERM_X;
3791 if (pace->mask & DIR_GWRITE)
3792 pxace->perms |= POSIX_PERM_W;
3793 if (pace->mask & DIR_GREAD)
3794 pxace->perms |= POSIX_PERM_R;
3795 if ((pace->mask & GENERIC_ALL)
3796 && (pace->flags & INHERIT_ONLY_ACE))
3797 pxace->perms |= POSIX_PERM_X
3798 | POSIX_PERM_W
3799 | POSIX_PERM_R;
3800 } else {
3801 if (pace->mask & FILE_GEXEC)
3802 pxace->perms |= POSIX_PERM_X;
3803 if (pace->mask & FILE_GWRITE)
3804 pxace->perms |= POSIX_PERM_W;
3805 if (pace->mask & FILE_GREAD)
3806 pxace->perms |= POSIX_PERM_R;
3809 if (pace->type != ACCESS_ALLOWED_ACE_TYPE)
3810 pxace->perms |= POSIX_PERM_DENIAL;
3811 else
3812 if (pxace->tag == POSIX_ACL_OTHER)
3813 pctx->permswrld |= pxace->perms;
3814 pctx->tagsset |= pxace->tag;
3815 if (pace->flags & INHERIT_ONLY_ACE) {
3816 l--;
3817 } else {
3818 k++;
3821 offace += le16_to_cpu(pace->size);
3824 * Create world perms if none (both lists)
3826 for (i=0; i<2; i++)
3827 if ((genericinh || !i)
3828 && !(ctx[i].tagsset & POSIX_ACL_OTHER)) {
3829 if (i)
3830 pxace = &pxdesc->acl.ace[--l];
3831 else
3832 pxace = &pxdesc->acl.ace[k++];
3833 pxace->tag = POSIX_ACL_OTHER;
3834 pxace->id = -1;
3835 pxace->perms = 0;
3836 ctx[i].tagsset |= POSIX_ACL_OTHER;
3837 ctx[i].permswrld = 0;
3840 * Set basic owner perms if none (both lists)
3841 * This happens for files created by Windows in directories
3842 * created by Linux and owned by root, because Windows
3843 * merges the admin ACEs
3845 for (i=0; i<2; i++)
3846 if (!(ctx[i].tagsset & POSIX_ACL_USER_OBJ)
3847 && (ctx[i].tagsset & POSIX_ACL_OTHER)) {
3848 if (i)
3849 pxace = &pxdesc->acl.ace[--l];
3850 else
3851 pxace = &pxdesc->acl.ace[k++];
3852 pxace->tag = POSIX_ACL_USER_OBJ;
3853 pxace->id = -1;
3854 pxace->perms = POSIX_PERM_R | POSIX_PERM_W | POSIX_PERM_X;
3855 ctx[i].tagsset |= POSIX_ACL_USER_OBJ;
3858 * Duplicate world perms as group_obj perms if none
3860 for (i=0; i<2; i++)
3861 if ((ctx[i].tagsset & POSIX_ACL_OTHER)
3862 && !(ctx[i].tagsset & POSIX_ACL_GROUP_OBJ)) {
3863 if (i)
3864 pxace = &pxdesc->acl.ace[--l];
3865 else
3866 pxace = &pxdesc->acl.ace[k++];
3867 pxace->tag = POSIX_ACL_GROUP_OBJ;
3868 pxace->id = -1;
3869 pxace->perms = ctx[i].permswrld;
3870 ctx[i].tagsset |= POSIX_ACL_GROUP_OBJ;
3873 * Also duplicate world perms as group perms if they
3874 * were converted to mask and not followed by a group entry
3876 if (ctx[0].groupmasks) {
3877 for (j=k-2; j>=0; j--) {
3878 if ((pxdesc->acl.ace[j].tag == POSIX_ACL_MASK)
3879 && (pxdesc->acl.ace[j].id != -1)
3880 && ((pxdesc->acl.ace[j+1].tag != POSIX_ACL_GROUP)
3881 || (pxdesc->acl.ace[j+1].id
3882 != pxdesc->acl.ace[j].id))) {
3883 pxace = &pxdesc->acl.ace[k];
3884 pxace->tag = POSIX_ACL_GROUP;
3885 pxace->id = pxdesc->acl.ace[j].id;
3886 pxace->perms = ctx[0].permswrld;
3887 ctx[0].tagsset |= POSIX_ACL_GROUP;
3888 k++;
3890 if (pxdesc->acl.ace[j].tag == POSIX_ACL_MASK)
3891 pxdesc->acl.ace[j].id = -1;
3894 if (ctx[1].groupmasks) {
3895 for (j=l; j<(alloccnt-1); j++) {
3896 if ((pxdesc->acl.ace[j].tag == POSIX_ACL_MASK)
3897 && (pxdesc->acl.ace[j].id != -1)
3898 && ((pxdesc->acl.ace[j+1].tag != POSIX_ACL_GROUP)
3899 || (pxdesc->acl.ace[j+1].id
3900 != pxdesc->acl.ace[j].id))) {
3901 pxace = &pxdesc->acl.ace[l - 1];
3902 pxace->tag = POSIX_ACL_GROUP;
3903 pxace->id = pxdesc->acl.ace[j].id;
3904 pxace->perms = ctx[1].permswrld;
3905 ctx[1].tagsset |= POSIX_ACL_GROUP;
3906 l--;
3908 if (pxdesc->acl.ace[j].tag == POSIX_ACL_MASK)
3909 pxdesc->acl.ace[j].id = -1;
3914 * Insert default mask if none present and
3915 * there are designated users or groups
3916 * (the space for it has not beed used)
3918 for (i=0; i<2; i++)
3919 if ((ctx[i].tagsset & (POSIX_ACL_USER | POSIX_ACL_GROUP))
3920 && !(ctx[i].tagsset & POSIX_ACL_MASK)) {
3921 if (i)
3922 pxace = &pxdesc->acl.ace[--l];
3923 else
3924 pxace = &pxdesc->acl.ace[k++];
3925 pxace->tag = POSIX_ACL_MASK;
3926 pxace->id = -1;
3927 pxace->perms = POSIX_PERM_DENIAL;
3928 ctx[i].tagsset |= POSIX_ACL_MASK;
3931 if (k > l) {
3932 ntfs_log_error("Posix descriptor is longer than expected\n");
3933 errno = EIO;
3934 free(pxdesc);
3935 pxdesc = (struct POSIX_SECURITY*)NULL;
3936 } else {
3937 pxdesc->acccnt = k;
3938 pxdesc->defcnt = alloccnt - l;
3939 pxdesc->firstdef = l;
3940 pxdesc->tagsset = ctx[0].tagsset;
3941 pxdesc->acl.version = POSIX_VERSION;
3942 pxdesc->acl.flags = 0;
3943 pxdesc->acl.filler = 0;
3944 ntfs_sort_posix(pxdesc);
3945 if (adminowns) {
3946 k = norm_ownadmin_permissions_posix(pxdesc,
3947 0, pxdesc->acccnt, 0);
3948 pxdesc->acccnt = k;
3949 l = norm_ownadmin_permissions_posix(pxdesc,
3950 pxdesc->firstdef, pxdesc->defcnt, k);
3951 pxdesc->firstdef = k;
3952 pxdesc->defcnt = l;
3953 } else {
3954 k = norm_std_permissions_posix(pxdesc,groupowns,
3955 0, pxdesc->acccnt, 0);
3956 pxdesc->acccnt = k;
3957 l = norm_std_permissions_posix(pxdesc,groupowns,
3958 pxdesc->firstdef, pxdesc->defcnt, k);
3959 pxdesc->firstdef = k;
3960 pxdesc->defcnt = l;
3963 if (pxdesc && !ntfs_valid_posix(pxdesc)) {
3964 ntfs_log_error("Invalid Posix descriptor built\n");
3965 errno = EIO;
3966 free(pxdesc);
3967 pxdesc = (struct POSIX_SECURITY*)NULL;
3969 return (pxdesc);
3972 #endif /* POSIXACLS */
3975 * Build unix-style (mode_t) permissions from an ACL
3976 * returns the requested permissions
3977 * or a negative result (with errno set) if there is a problem
3980 int ntfs_build_permissions(const char *securattr,
3981 const SID *usid, const SID *gsid, BOOL isdir)
3983 int perm;
3984 BOOL adminowns;
3985 BOOL groupowns;
3987 adminowns = ntfs_same_sid(usid,adminsid)
3988 || ntfs_same_sid(gsid,adminsid);
3989 groupowns = !adminowns && ntfs_same_sid(gsid,usid);
3990 if (adminowns)
3991 perm = build_ownadmin_permissions(securattr, usid, gsid, isdir);
3992 else
3993 if (groupowns)
3994 perm = build_owngrp_permissions(securattr, usid, isdir);
3995 else
3996 perm = build_std_permissions(securattr, usid, gsid, isdir);
3997 return (perm);
4001 * The following must be in some library...
4004 static unsigned long atoul(const char *p)
4005 { /* must be somewhere ! */
4006 unsigned long v;
4008 v = 0;
4009 while ((*p >= '0') && (*p <= '9'))
4010 v = v * 10 + (*p++) - '0';
4011 return (v);
4015 * Build an internal representation of a SID
4016 * Returns a copy in allocated memory if it succeeds
4017 * The SID is checked to be a valid user one.
4020 static SID *encodesid(const char *sidstr)
4022 SID *sid;
4023 int cnt;
4024 BIGSID bigsid;
4025 SID *bsid;
4026 u32 auth;
4027 const char *p;
4029 sid = (SID*) NULL;
4030 if (!strncmp(sidstr, "S-1-", 4)) {
4031 bsid = (SID*)&bigsid;
4032 bsid->revision = SID_REVISION;
4033 p = &sidstr[4];
4034 auth = atoul(p);
4035 bsid->identifier_authority.high_part = const_cpu_to_be16(0);
4036 bsid->identifier_authority.low_part = cpu_to_be32(auth);
4037 cnt = 0;
4038 p = strchr(p, '-');
4039 while (p && (cnt < 8)) {
4040 p++;
4041 auth = atoul(p);
4042 bsid->sub_authority[cnt] = cpu_to_le32(auth);
4043 p = strchr(p, '-');
4044 cnt++;
4046 bsid->sub_authority_count = cnt;
4047 if ((cnt > 0) && ntfs_valid_sid(bsid) && ntfs_is_user_sid(bsid)) {
4048 sid = (SID*) ntfs_malloc(4 * cnt + 8);
4049 if (sid)
4050 memcpy(sid, bsid, 4 * cnt + 8);
4053 return (sid);
4057 * Get a single mapping item from buffer
4059 * Always reads a full line, truncating long lines
4060 * Refills buffer when exhausted
4061 * Returns pointer to item, or NULL when there is no more
4064 static struct MAPLIST *getmappingitem(FILEREADER reader, void *fileid,
4065 off_t *poffs, char *buf, int *psrc, s64 *psize)
4067 int src;
4068 int dst;
4069 char *q;
4070 char *pu;
4071 char *pg;
4072 int gotend;
4073 struct MAPLIST *item;
4075 src = *psrc;
4076 dst = 0;
4077 /* allocate and get a full line */
4078 item = (struct MAPLIST*)ntfs_malloc(sizeof(struct MAPLIST));
4079 if (item) {
4080 do {
4081 gotend = 0;
4082 while ((src < *psize)
4083 && (buf[src] != '\n')) {
4084 if (dst < LINESZ)
4085 item->maptext[dst++] = buf[src];
4086 src++;
4088 if (src >= *psize) {
4089 *poffs += *psize;
4090 *psize = reader(fileid, buf, (size_t)BUFSZ, *poffs);
4091 src = 0;
4092 } else {
4093 gotend = 1;
4094 src++;
4095 item->maptext[dst] = '\0';
4096 dst = 0;
4098 } while (*psize && ((item->maptext[0] == '#') || !gotend));
4099 if (gotend) {
4100 pu = pg = (char*)NULL;
4101 /* decompose into uid, gid and sid */
4102 item->uidstr = item->maptext;
4103 item->gidstr = strchr(item->uidstr, ':');
4104 if (item->gidstr) {
4105 pu = item->gidstr++;
4106 item->sidstr = strchr(item->gidstr, ':');
4107 if (item->sidstr) {
4108 pg = item->sidstr++;
4109 q = strchr(item->sidstr, ':');
4110 if (q) *q = 0;
4113 if (pu && pg)
4114 *pu = *pg = '\0';
4115 else {
4116 ntfs_log_early_error("Bad mapping item \"%s\"\n",
4117 item->maptext);
4118 free(item);
4119 item = (struct MAPLIST*)NULL;
4121 } else {
4122 free(item); /* free unused item */
4123 item = (struct MAPLIST*)NULL;
4126 *psrc = src;
4127 return (item);
4131 * Read user mapping file and split into their attribute.
4132 * Parameters are kept as text in a chained list until logins
4133 * are converted to uid.
4134 * Returns the head of list, if any
4136 * If an absolute path is provided, the mapping file is assumed
4137 * to be located in another mounted file system, and plain read()
4138 * are used to get its contents.
4139 * If a relative path is provided, the mapping file is assumed
4140 * to be located on the current file system, and internal IO
4141 * have to be used since we are still mounting and we have not
4142 * entered the fuse loop yet.
4145 struct MAPLIST *ntfs_read_mapping(FILEREADER reader, void *fileid)
4147 char buf[BUFSZ];
4148 struct MAPLIST *item;
4149 struct MAPLIST *firstitem;
4150 struct MAPLIST *lastitem;
4151 int src;
4152 off_t offs;
4153 s64 size;
4155 firstitem = (struct MAPLIST*)NULL;
4156 lastitem = (struct MAPLIST*)NULL;
4157 offs = 0;
4158 size = reader(fileid, buf, (size_t)BUFSZ, (off_t)0);
4159 if (size > 0) {
4160 src = 0;
4161 do {
4162 item = getmappingitem(reader, fileid, &offs,
4163 buf, &src, &size);
4164 if (item) {
4165 item->next = (struct MAPLIST*)NULL;
4166 if (lastitem)
4167 lastitem->next = item;
4168 else
4169 firstitem = item;
4170 lastitem = item;
4172 } while (item);
4174 return (firstitem);
4178 * Free memory used to store the user mapping
4179 * The only purpose is to facilitate the detection of memory leaks
4182 void ntfs_free_mapping(struct MAPPING *mapping[])
4184 struct MAPPING *user;
4185 struct MAPPING *group;
4187 /* free user mappings */
4188 while (mapping[MAPUSERS]) {
4189 user = mapping[MAPUSERS];
4190 /* do not free SIDs used for group mappings */
4191 group = mapping[MAPGROUPS];
4192 while (group && (group->sid != user->sid))
4193 group = group->next;
4194 if (!group)
4195 free(user->sid);
4196 /* free group list if any */
4197 if (user->grcnt)
4198 free(user->groups);
4199 /* unchain item and free */
4200 mapping[MAPUSERS] = user->next;
4201 free(user);
4203 /* free group mappings */
4204 while (mapping[MAPGROUPS]) {
4205 group = mapping[MAPGROUPS];
4206 free(group->sid);
4207 /* unchain item and free */
4208 mapping[MAPGROUPS] = group->next;
4209 free(group);
4215 * Build the user mapping list
4216 * user identification may be given in symbolic or numeric format
4218 * ! Note ! : does getpwnam() read /etc/passwd or some other file ?
4219 * if so there is a possible recursion into fuse if this
4220 * file is on NTFS, and fuse is not recursion safe.
4223 struct MAPPING *ntfs_do_user_mapping(struct MAPLIST *firstitem)
4225 struct MAPLIST *item;
4226 struct MAPPING *firstmapping;
4227 struct MAPPING *lastmapping;
4228 struct MAPPING *mapping;
4229 struct passwd *pwd;
4230 SID *sid;
4231 int uid;
4233 firstmapping = (struct MAPPING*)NULL;
4234 lastmapping = (struct MAPPING*)NULL;
4235 for (item = firstitem; item; item = item->next) {
4236 if ((item->uidstr[0] >= '0') && (item->uidstr[0] <= '9'))
4237 uid = atoi(item->uidstr);
4238 else {
4239 uid = 0;
4240 if (item->uidstr[0]) {
4241 pwd = getpwnam(item->uidstr);
4242 if (pwd)
4243 uid = pwd->pw_uid;
4244 else
4245 ntfs_log_early_error("Invalid user \"%s\"\n",
4246 item->uidstr);
4250 * Records with no uid and no gid are inserted
4251 * to define the implicit mapping pattern
4253 if (uid
4254 || (!item->uidstr[0] && !item->gidstr[0])) {
4255 sid = encodesid(item->sidstr);
4256 if (sid && !item->uidstr[0] && !item->gidstr[0]
4257 && !ntfs_valid_pattern(sid)) {
4258 ntfs_log_error("Bad implicit SID pattern %s\n",
4259 item->sidstr);
4260 sid = (SID*)NULL;
4262 if (sid) {
4263 mapping =
4264 (struct MAPPING*)
4265 ntfs_malloc(sizeof(struct MAPPING));
4266 if (mapping) {
4267 mapping->sid = sid;
4268 mapping->xid = uid;
4269 mapping->grcnt = 0;
4270 mapping->next = (struct MAPPING*)NULL;
4271 if (lastmapping)
4272 lastmapping->next = mapping;
4273 else
4274 firstmapping = mapping;
4275 lastmapping = mapping;
4280 return (firstmapping);
4284 * Build the group mapping list
4285 * group identification may be given in symbolic or numeric format
4287 * gid not associated to a uid are processed first in order
4288 * to favour real groups
4290 * ! Note ! : does getgrnam() read /etc/group or some other file ?
4291 * if so there is a possible recursion into fuse if this
4292 * file is on NTFS, and fuse is not recursion safe.
4295 struct MAPPING *ntfs_do_group_mapping(struct MAPLIST *firstitem)
4297 struct MAPLIST *item;
4298 struct MAPPING *firstmapping;
4299 struct MAPPING *lastmapping;
4300 struct MAPPING *mapping;
4301 struct group *grp;
4302 BOOL secondstep;
4303 BOOL ok;
4304 int step;
4305 SID *sid;
4306 int gid;
4308 firstmapping = (struct MAPPING*)NULL;
4309 lastmapping = (struct MAPPING*)NULL;
4310 for (step=1; step<=2; step++) {
4311 for (item = firstitem; item; item = item->next) {
4312 secondstep = (item->uidstr[0] != '\0')
4313 || !item->gidstr[0];
4314 ok = (step == 1 ? !secondstep : secondstep);
4315 if ((item->gidstr[0] >= '0')
4316 && (item->gidstr[0] <= '9'))
4317 gid = atoi(item->gidstr);
4318 else {
4319 gid = 0;
4320 if (item->gidstr[0]) {
4321 grp = getgrnam(item->gidstr);
4322 if (grp)
4323 gid = grp->gr_gid;
4324 else
4325 ntfs_log_early_error("Invalid group \"%s\"\n",
4326 item->gidstr);
4330 * Records with no uid and no gid are inserted in the
4331 * second step to define the implicit mapping pattern
4333 if (ok
4334 && (gid
4335 || (!item->uidstr[0] && !item->gidstr[0]))) {
4336 sid = encodesid(item->sidstr);
4337 if (sid && !item->uidstr[0] && !item->gidstr[0]
4338 && !ntfs_valid_pattern(sid)) {
4339 /* error already logged */
4340 sid = (SID*)NULL;
4342 if (sid) {
4343 mapping = (struct MAPPING*)
4344 ntfs_malloc(sizeof(struct MAPPING));
4345 if (mapping) {
4346 mapping->sid = sid;
4347 mapping->xid = gid;
4348 mapping->grcnt = 0;
4349 mapping->next = (struct MAPPING*)NULL;
4350 if (lastmapping)
4351 lastmapping->next = mapping;
4352 else
4353 firstmapping = mapping;
4354 lastmapping = mapping;
4360 return (firstmapping);