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