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