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