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