xref: /haiku/src/add-ons/kernel/file_systems/ntfs/libntfs/acls.c (revision 1deede7388b04dbeec5af85cae7164735ea9e70d)
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 
73 static 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 
80 static const SID *nullsid = (const SID*)nullsidbytes;
81 
82 /*
83  *		SID for world  (S-1-1-0)
84  */
85 
86 static 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 
93 const SID *worldsid = (const SID*)worldsidbytes;
94 
95 /*
96  *		SID for authenticated user (S-1-5-11)
97  */
98 
99 static 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 
106 static const SID *authsid = (const SID*)authsidbytes;
107 
108 /*
109  *		SID for administrator
110  */
111 
112 static 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 
120 const SID *adminsid = (const SID*)adminsidbytes;
121 
122 /*
123  *		SID for system
124  */
125 
126 static 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 
133 static const SID *systemsid = (const SID*)systemsidbytes;
134 
135 /*
136  *		SID for generic creator-owner
137  *		S-1-3-0
138  */
139 
140 static 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 
147 static const SID *ownersid = (const SID*)ownersidbytes;
148 
149 /*
150  *		SID for generic creator-group
151  *		S-1-3-1
152  */
153 
154 static 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 
161 static const SID *groupsid = (const SID*)groupsidbytes;
162 
163 /*
164  *		Determine the size of a SID
165  */
166 
167 int 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 
176 BOOL 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 
194 static 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 
232 BOOL 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 
249 static 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 
264 unsigned 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  */
327 BOOL 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 
343 BOOL 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 
362 static 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 
416 const 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 
460 const 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 
504 uid_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 
527 gid_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 
549 static 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 
596 BOOL 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 
680 int 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 
933 BOOL 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 
1055 static 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 
1100 void 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 
1172 int 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 
1216 struct 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 
1275 struct 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 
1316 struct 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 
1434 static 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 
1505 struct 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 
1552 struct 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 
1568 static 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 
1730 static 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 
1811 static 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 
2066 static 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 
2183 if (pxdesc->defcnt && (pxdesc->firstdef != pxdesc->acccnt)) {
2184 ntfs_log_error("** error : access and default not consecutive\n");
2185 return (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 
2404 static 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 
2717 char *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 
2818 char *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 
2904 static 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 
3003 static 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 
3159 static 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 
3247 static 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 
3328 static 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 
3437 static 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 
3531 const 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 
3586 static 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 
3635 struct 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 
4080 int 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 
4105 static 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 
4122 static 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 
4167 static 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 
4248 struct 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 
4285 void 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 
4326 struct 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 
4404 struct 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