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