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