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