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