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