1 /** 2 * security.c - Handling security/ACLs in NTFS. Originated from the Linux-NTFS project. 3 * 4 * Copyright (c) 2004 Anton Altaparmakov 5 * Copyright (c) 2005-2006 Szabolcs Szakacsits 6 * Copyright (c) 2006 Yura Pakhuchiy 7 * Copyright (c) 2007-2010 Jean-Pierre Andre 8 * 9 * This program/include file is free software; you can redistribute it and/or 10 * modify it under the terms of the GNU General Public License as published 11 * by the Free Software Foundation; either version 2 of the License, or 12 * (at your option) any later version. 13 * 14 * This program/include file is distributed in the hope that it will be 15 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty 16 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 * GNU General Public License for more details. 18 * 19 * You should have received a copy of the GNU General Public License 20 * along with this program (in the main directory of the NTFS-3G 21 * distribution in the file COPYING); if not, write to the Free Software 22 * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 23 */ 24 25 #ifdef HAVE_CONFIG_H 26 #include "config.h" 27 #endif 28 29 #ifdef HAVE_STDIO_H 30 #include <stdio.h> 31 #endif 32 #ifdef HAVE_STDLIB_H 33 #include <stdlib.h> 34 #endif 35 #ifdef HAVE_STRING_H 36 #include <string.h> 37 #endif 38 #ifdef HAVE_ERRNO_H 39 #include <errno.h> 40 #endif 41 #ifdef HAVE_FCNTL_H 42 #include <fcntl.h> 43 #endif 44 #ifdef HAVE_SETXATTR 45 #include <sys/xattr.h> 46 #endif 47 #ifdef HAVE_SYS_STAT_H 48 #include <sys/stat.h> 49 #endif 50 51 #include <unistd.h> 52 #include <pwd.h> 53 #include <grp.h> 54 55 #include "param.h" 56 #include "types.h" 57 #include "layout.h" 58 #include "attrib.h" 59 #include "index.h" 60 #include "dir.h" 61 #include "bitmap.h" 62 #include "security.h" 63 #include "acls.h" 64 #include "cache.h" 65 #include "misc.h" 66 67 #ifdef __HAIKU__ 68 #define getgrgid(a) NULL 69 #define getpwuid(a) NULL 70 #endif 71 72 /* 73 * JPA NTFS constants or structs 74 * should be moved to layout.h 75 */ 76 77 #define ALIGN_SDS_BLOCK 0x40000 /* Alignment for a $SDS block */ 78 #define ALIGN_SDS_ENTRY 16 /* Alignment for a $SDS entry */ 79 #define STUFFSZ 0x4000 /* unitary stuffing size for $SDS */ 80 #define FIRST_SECURITY_ID 0x100 /* Lowest security id */ 81 82 /* Mask for attributes which can be forced */ 83 #define FILE_ATTR_SETTABLE ( FILE_ATTR_READONLY \ 84 | FILE_ATTR_HIDDEN \ 85 | FILE_ATTR_SYSTEM \ 86 | FILE_ATTR_ARCHIVE \ 87 | FILE_ATTR_TEMPORARY \ 88 | FILE_ATTR_OFFLINE \ 89 | FILE_ATTR_NOT_CONTENT_INDEXED ) 90 91 struct SII { /* this is an image of an $SII index entry */ 92 le16 offs; 93 le16 size; 94 le32 fill1; 95 le16 indexsz; 96 le16 indexksz; 97 le16 flags; 98 le16 fill2; 99 le32 keysecurid; 100 101 /* did not find official description for the following */ 102 le32 hash; 103 le32 securid; 104 le32 dataoffsl; /* documented as badly aligned */ 105 le32 dataoffsh; 106 le32 datasize; 107 } ; 108 109 struct SDH { /* this is an image of an $SDH index entry */ 110 le16 offs; 111 le16 size; 112 le32 fill1; 113 le16 indexsz; 114 le16 indexksz; 115 le16 flags; 116 le16 fill2; 117 le32 keyhash; 118 le32 keysecurid; 119 120 /* did not find official description for the following */ 121 le32 hash; 122 le32 securid; 123 le32 dataoffsl; 124 le32 dataoffsh; 125 le32 datasize; 126 le32 fill3; 127 } ; 128 129 /* 130 * A few useful constants 131 */ 132 133 static ntfschar sii_stream[] = { const_cpu_to_le16('$'), 134 const_cpu_to_le16('S'), 135 const_cpu_to_le16('I'), 136 const_cpu_to_le16('I'), 137 const_cpu_to_le16(0) }; 138 static ntfschar sdh_stream[] = { const_cpu_to_le16('$'), 139 const_cpu_to_le16('S'), 140 const_cpu_to_le16('D'), 141 const_cpu_to_le16('H'), 142 const_cpu_to_le16(0) }; 143 144 /* 145 * null SID (S-1-0-0) 146 */ 147 148 extern const SID *nullsid; 149 150 /* 151 * The zero GUID. 152 */ 153 154 static const GUID __zero_guid = { const_cpu_to_le32(0), const_cpu_to_le16(0), 155 const_cpu_to_le16(0), { 0, 0, 0, 0, 0, 0, 0, 0 } }; 156 static const GUID *const zero_guid = &__zero_guid; 157 158 /** 159 * ntfs_guid_is_zero - check if a GUID is zero 160 * @guid: [IN] guid to check 161 * 162 * Return TRUE if @guid is a valid pointer to a GUID and it is the zero GUID 163 * and FALSE otherwise. 164 */ 165 BOOL ntfs_guid_is_zero(const GUID *guid) 166 { 167 return (memcmp(guid, zero_guid, sizeof(*zero_guid))); 168 } 169 170 /** 171 * ntfs_guid_to_mbs - convert a GUID to a multi byte string 172 * @guid: [IN] guid to convert 173 * @guid_str: [OUT] string in which to return the GUID (optional) 174 * 175 * Convert the GUID pointed to by @guid to a multi byte string of the form 176 * "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX". Therefore, @guid_str (if not NULL) 177 * needs to be able to store at least 37 bytes. 178 * 179 * If @guid_str is not NULL it will contain the converted GUID on return. If 180 * it is NULL a string will be allocated and this will be returned. The caller 181 * is responsible for free()ing the string in that case. 182 * 183 * On success return the converted string and on failure return NULL with errno 184 * set to the error code. 185 */ 186 char *ntfs_guid_to_mbs(const GUID *guid, char *guid_str) 187 { 188 char *_guid_str; 189 int res; 190 191 if (!guid) { 192 errno = EINVAL; 193 return NULL; 194 } 195 _guid_str = guid_str; 196 if (!_guid_str) { 197 _guid_str = (char*)ntfs_malloc(37); 198 if (!_guid_str) 199 return _guid_str; 200 } 201 res = snprintf(_guid_str, 37, 202 "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", 203 (unsigned int)le32_to_cpu(guid->data1), 204 le16_to_cpu(guid->data2), le16_to_cpu(guid->data3), 205 guid->data4[0], guid->data4[1], 206 guid->data4[2], guid->data4[3], guid->data4[4], 207 guid->data4[5], guid->data4[6], guid->data4[7]); 208 if (res == 36) 209 return _guid_str; 210 if (!guid_str) 211 free(_guid_str); 212 errno = EINVAL; 213 return NULL; 214 } 215 216 /** 217 * ntfs_sid_to_mbs_size - determine maximum size for the string of a SID 218 * @sid: [IN] SID for which to determine the maximum string size 219 * 220 * Determine the maximum multi byte string size in bytes which is needed to 221 * store the standard textual representation of the SID pointed to by @sid. 222 * See ntfs_sid_to_mbs(), below. 223 * 224 * On success return the maximum number of bytes needed to store the multi byte 225 * string and on failure return -1 with errno set to the error code. 226 */ 227 int ntfs_sid_to_mbs_size(const SID *sid) 228 { 229 int size, i; 230 231 if (!ntfs_sid_is_valid(sid)) { 232 errno = EINVAL; 233 return -1; 234 } 235 /* Start with "S-". */ 236 size = 2; 237 /* 238 * Add the SID_REVISION. Hopefully the compiler will optimize this 239 * away as SID_REVISION is a constant. 240 */ 241 for (i = SID_REVISION; i > 0; i /= 10) 242 size++; 243 /* Add the "-". */ 244 size++; 245 /* 246 * Add the identifier authority. If it needs to be in decimal, the 247 * maximum is 2^32-1 = 4294967295 = 10 characters. If it needs to be 248 * in hexadecimal, then maximum is 0x665544332211 = 14 characters. 249 */ 250 if (!sid->identifier_authority.high_part) 251 size += 10; 252 else 253 size += 14; 254 /* 255 * Finally, add the sub authorities. For each we have a "-" followed 256 * by a decimal which can be up to 2^32-1 = 4294967295 = 10 characters. 257 */ 258 size += (1 + 10) * sid->sub_authority_count; 259 /* We need the zero byte at the end, too. */ 260 size++; 261 return size * sizeof(char); 262 } 263 264 /** 265 * ntfs_sid_to_mbs - convert a SID to a multi byte string 266 * @sid: [IN] SID to convert 267 * @sid_str: [OUT] string in which to return the SID (optional) 268 * @sid_str_size: [IN] size in bytes of @sid_str 269 * 270 * Convert the SID pointed to by @sid to its standard textual representation. 271 * @sid_str (if not NULL) needs to be able to store at least 272 * ntfs_sid_to_mbs_size() bytes. @sid_str_size is the size in bytes of 273 * @sid_str if @sid_str is not NULL. 274 * 275 * The standard textual representation of the SID is of the form: 276 * S-R-I-S-S... 277 * Where: 278 * - The first "S" is the literal character 'S' identifying the following 279 * digits as a SID. 280 * - R is the revision level of the SID expressed as a sequence of digits 281 * in decimal. 282 * - I is the 48-bit identifier_authority, expressed as digits in decimal, 283 * if I < 2^32, or hexadecimal prefixed by "0x", if I >= 2^32. 284 * - S... is one or more sub_authority values, expressed as digits in 285 * decimal. 286 * 287 * If @sid_str is not NULL it will contain the converted SUID on return. If it 288 * is NULL a string will be allocated and this will be returned. The caller is 289 * responsible for free()ing the string in that case. 290 * 291 * On success return the converted string and on failure return NULL with errno 292 * set to the error code. 293 */ 294 char *ntfs_sid_to_mbs(const SID *sid, char *sid_str, size_t sid_str_size) 295 { 296 u64 u; 297 le32 leauth; 298 char *s; 299 int i, j, cnt; 300 301 /* 302 * No need to check @sid if !@sid_str since ntfs_sid_to_mbs_size() will 303 * check @sid, too. 8 is the minimum SID string size. 304 */ 305 if (sid_str && (sid_str_size < 8 || !ntfs_sid_is_valid(sid))) { 306 errno = EINVAL; 307 return NULL; 308 } 309 /* Allocate string if not provided. */ 310 if (!sid_str) { 311 cnt = ntfs_sid_to_mbs_size(sid); 312 if (cnt < 0) 313 return NULL; 314 s = (char*)ntfs_malloc(cnt); 315 if (!s) 316 return s; 317 sid_str = s; 318 /* So we know we allocated it. */ 319 sid_str_size = 0; 320 } else { 321 s = sid_str; 322 cnt = sid_str_size; 323 } 324 /* Start with "S-R-". */ 325 i = snprintf(s, cnt, "S-%hhu-", (unsigned char)sid->revision); 326 if (i < 0 || i >= cnt) 327 goto err_out; 328 s += i; 329 cnt -= i; 330 /* Add the identifier authority. */ 331 for (u = i = 0, j = 40; i < 6; i++, j -= 8) 332 u += (u64)sid->identifier_authority.value[i] << j; 333 if (!sid->identifier_authority.high_part) 334 i = snprintf(s, cnt, "%lu", (unsigned long)u); 335 else 336 i = snprintf(s, cnt, "0x%llx", (unsigned long long)u); 337 if (i < 0 || i >= cnt) 338 goto err_out; 339 s += i; 340 cnt -= i; 341 /* Finally, add the sub authorities. */ 342 for (j = 0; j < sid->sub_authority_count; j++) { 343 leauth = sid->sub_authority[j]; 344 i = snprintf(s, cnt, "-%u", (unsigned int) 345 le32_to_cpu(leauth)); 346 if (i < 0 || i >= cnt) 347 goto err_out; 348 s += i; 349 cnt -= i; 350 } 351 return sid_str; 352 err_out: 353 if (i >= cnt) 354 i = EMSGSIZE; 355 else 356 i = errno; 357 if (!sid_str_size) 358 free(sid_str); 359 errno = i; 360 return NULL; 361 } 362 363 /** 364 * ntfs_generate_guid - generatates a random current guid. 365 * @guid: [OUT] pointer to a GUID struct to hold the generated guid. 366 * 367 * perhaps not a very good random number generator though... 368 */ 369 void ntfs_generate_guid(GUID *guid) 370 { 371 unsigned int i; 372 u8 *p = (u8 *)guid; 373 374 for (i = 0; i < sizeof(GUID); i++) { 375 p[i] = (u8)(random() & 0xFF); 376 if (i == 7) 377 p[7] = (p[7] & 0x0F) | 0x40; 378 if (i == 8) 379 p[8] = (p[8] & 0x3F) | 0x80; 380 } 381 } 382 383 /** 384 * ntfs_security_hash - calculate the hash of a security descriptor 385 * @sd: self-relative security descriptor whose hash to calculate 386 * @length: size in bytes of the security descritor @sd 387 * 388 * Calculate the hash of the self-relative security descriptor @sd of length 389 * @length bytes. 390 * 391 * This hash is used in the $Secure system file as the primary key for the $SDH 392 * index and is also stored in the header of each security descriptor in the 393 * $SDS data stream as well as in the index data of both the $SII and $SDH 394 * indexes. In all three cases it forms part of the SDS_ENTRY_HEADER 395 * structure. 396 * 397 * Return the calculated security hash in little endian. 398 */ 399 le32 ntfs_security_hash(const SECURITY_DESCRIPTOR_RELATIVE *sd, const u32 len) 400 { 401 const le32 *pos = (const le32*)sd; 402 const le32 *end = pos + (len >> 2); 403 u32 hash = 0; 404 405 while (pos < end) { 406 hash = le32_to_cpup(pos) + ntfs_rol32(hash, 3); 407 pos++; 408 } 409 return cpu_to_le32(hash); 410 } 411 412 /* 413 * Get the first entry of current index block 414 * cut and pasted form ntfs_ie_get_first() in index.c 415 */ 416 417 static INDEX_ENTRY *ntfs_ie_get_first(INDEX_HEADER *ih) 418 { 419 return (INDEX_ENTRY*)((u8*)ih + le32_to_cpu(ih->entries_offset)); 420 } 421 422 /* 423 * Stuff a 256KB block into $SDS before writing descriptors 424 * into the block. 425 * 426 * This prevents $SDS from being automatically declared as sparse 427 * when the second copy of the first security descriptor is written 428 * 256KB further ahead. 429 * 430 * Having $SDS declared as a sparse file is not wrong by itself 431 * and chkdsk leaves it as a sparse file. It does however complain 432 * and add a sparse flag (0x0200) into field file_attributes of 433 * STANDARD_INFORMATION of $Secure. This probably means that a 434 * sparse attribute (ATTR_IS_SPARSE) is only allowed in sparse 435 * files (FILE_ATTR_SPARSE_FILE). 436 * 437 * Windows normally does not convert to sparse attribute or sparse 438 * file. Stuffing is just a way to get to the same result. 439 */ 440 441 static int entersecurity_stuff(ntfs_volume *vol, off_t offs) 442 { 443 int res; 444 int written; 445 unsigned long total; 446 char *stuff; 447 448 res = 0; 449 total = 0; 450 stuff = (char*)ntfs_malloc(STUFFSZ); 451 if (stuff) { 452 memset(stuff, 0, STUFFSZ); 453 do { 454 written = ntfs_attr_data_write(vol->secure_ni, 455 STREAM_SDS, 4, stuff, STUFFSZ, offs); 456 if (written == STUFFSZ) { 457 total += STUFFSZ; 458 offs += STUFFSZ; 459 } else { 460 errno = ENOSPC; 461 res = -1; 462 } 463 } while (!res && (total < ALIGN_SDS_BLOCK)); 464 free(stuff); 465 } else { 466 errno = ENOMEM; 467 res = -1; 468 } 469 return (res); 470 } 471 472 /* 473 * Enter a new security descriptor into $Secure (data only) 474 * it has to be written twice with an offset of 256KB 475 * 476 * Should only be called by entersecurityattr() to ensure consistency 477 * 478 * Returns zero if sucessful 479 */ 480 481 static int entersecurity_data(ntfs_volume *vol, 482 const SECURITY_DESCRIPTOR_RELATIVE *attr, s64 attrsz, 483 le32 hash, le32 keyid, off_t offs, int gap) 484 { 485 int res; 486 int written1; 487 int written2; 488 char *fullattr; 489 int fullsz; 490 SECURITY_DESCRIPTOR_HEADER *phsds; 491 492 res = -1; 493 fullsz = attrsz + gap + sizeof(SECURITY_DESCRIPTOR_HEADER); 494 fullattr = (char*)ntfs_malloc(fullsz); 495 if (fullattr) { 496 /* 497 * Clear the gap from previous descriptor 498 * this could be useful for appending the second 499 * copy to the end of file. When creating a new 500 * 256K block, the gap is cleared while writing 501 * the first copy 502 */ 503 if (gap) 504 memset(fullattr,0,gap); 505 memcpy(&fullattr[gap + sizeof(SECURITY_DESCRIPTOR_HEADER)], 506 attr,attrsz); 507 phsds = (SECURITY_DESCRIPTOR_HEADER*)&fullattr[gap]; 508 phsds->hash = hash; 509 phsds->security_id = keyid; 510 phsds->offset = cpu_to_le64(offs); 511 phsds->length = cpu_to_le32(fullsz - gap); 512 written1 = ntfs_attr_data_write(vol->secure_ni, 513 STREAM_SDS, 4, fullattr, fullsz, 514 offs - gap); 515 written2 = ntfs_attr_data_write(vol->secure_ni, 516 STREAM_SDS, 4, fullattr, fullsz, 517 offs - gap + ALIGN_SDS_BLOCK); 518 if ((written1 == fullsz) 519 && (written2 == written1)) 520 res = 0; 521 else 522 errno = ENOSPC; 523 free(fullattr); 524 } else 525 errno = ENOMEM; 526 return (res); 527 } 528 529 /* 530 * Enter a new security descriptor in $Secure (indexes only) 531 * 532 * Should only be called by entersecurityattr() to ensure consistency 533 * 534 * Returns zero if sucessful 535 */ 536 537 static int entersecurity_indexes(ntfs_volume *vol, s64 attrsz, 538 le32 hash, le32 keyid, off_t offs) 539 { 540 union { 541 struct { 542 le32 dataoffsl; 543 le32 dataoffsh; 544 } parts; 545 le64 all; 546 } realign; 547 int res; 548 ntfs_index_context *xsii; 549 ntfs_index_context *xsdh; 550 struct SII newsii; 551 struct SDH newsdh; 552 553 res = -1; 554 /* enter a new $SII record */ 555 556 xsii = vol->secure_xsii; 557 ntfs_index_ctx_reinit(xsii); 558 newsii.offs = const_cpu_to_le16(20); 559 newsii.size = const_cpu_to_le16(sizeof(struct SII) - 20); 560 newsii.fill1 = const_cpu_to_le32(0); 561 newsii.indexsz = const_cpu_to_le16(sizeof(struct SII)); 562 newsii.indexksz = const_cpu_to_le16(sizeof(SII_INDEX_KEY)); 563 newsii.flags = const_cpu_to_le16(0); 564 newsii.fill2 = const_cpu_to_le16(0); 565 newsii.keysecurid = keyid; 566 newsii.hash = hash; 567 newsii.securid = keyid; 568 realign.all = cpu_to_le64(offs); 569 newsii.dataoffsh = realign.parts.dataoffsh; 570 newsii.dataoffsl = realign.parts.dataoffsl; 571 newsii.datasize = cpu_to_le32(attrsz 572 + sizeof(SECURITY_DESCRIPTOR_HEADER)); 573 if (!ntfs_ie_add(xsii,(INDEX_ENTRY*)&newsii)) { 574 575 /* enter a new $SDH record */ 576 577 xsdh = vol->secure_xsdh; 578 ntfs_index_ctx_reinit(xsdh); 579 newsdh.offs = const_cpu_to_le16(24); 580 newsdh.size = const_cpu_to_le16( 581 sizeof(SECURITY_DESCRIPTOR_HEADER)); 582 newsdh.fill1 = const_cpu_to_le32(0); 583 newsdh.indexsz = const_cpu_to_le16( 584 sizeof(struct SDH)); 585 newsdh.indexksz = const_cpu_to_le16( 586 sizeof(SDH_INDEX_KEY)); 587 newsdh.flags = const_cpu_to_le16(0); 588 newsdh.fill2 = const_cpu_to_le16(0); 589 newsdh.keyhash = hash; 590 newsdh.keysecurid = keyid; 591 newsdh.hash = hash; 592 newsdh.securid = keyid; 593 newsdh.dataoffsh = realign.parts.dataoffsh; 594 newsdh.dataoffsl = realign.parts.dataoffsl; 595 newsdh.datasize = cpu_to_le32(attrsz 596 + sizeof(SECURITY_DESCRIPTOR_HEADER)); 597 /* special filler value, Windows generally */ 598 /* fills with 0x00490049, sometimes with zero */ 599 newsdh.fill3 = const_cpu_to_le32(0x00490049); 600 if (!ntfs_ie_add(xsdh,(INDEX_ENTRY*)&newsdh)) 601 res = 0; 602 } 603 return (res); 604 } 605 606 /* 607 * Enter a new security descriptor in $Secure (data and indexes) 608 * Returns id of entry, or zero if there is a problem. 609 * (should not be called for NTFS version < 3.0) 610 * 611 * important : calls have to be serialized, however no locking is 612 * needed while fuse is not multithreaded 613 */ 614 615 static le32 entersecurityattr(ntfs_volume *vol, 616 const SECURITY_DESCRIPTOR_RELATIVE *attr, s64 attrsz, 617 le32 hash) 618 { 619 union { 620 struct { 621 le32 dataoffsl; 622 le32 dataoffsh; 623 } parts; 624 le64 all; 625 } realign; 626 le32 securid; 627 le32 keyid; 628 u32 newkey; 629 off_t offs; 630 int gap; 631 int size; 632 BOOL found; 633 struct SII *psii; 634 INDEX_ENTRY *entry; 635 INDEX_ENTRY *next; 636 ntfs_index_context *xsii; 637 int retries; 638 ntfs_attr *na; 639 int olderrno; 640 641 /* find the first available securid beyond the last key */ 642 /* in $Secure:$SII. This also determines the first */ 643 /* available location in $Secure:$SDS, as this stream */ 644 /* is always appended to and the id's are allocated */ 645 /* in sequence */ 646 647 securid = const_cpu_to_le32(0); 648 xsii = vol->secure_xsii; 649 ntfs_index_ctx_reinit(xsii); 650 offs = size = 0; 651 keyid = const_cpu_to_le32(-1); 652 olderrno = errno; 653 found = !ntfs_index_lookup((char*)&keyid, 654 sizeof(SII_INDEX_KEY), xsii); 655 if (!found && (errno != ENOENT)) { 656 ntfs_log_perror("Inconsistency in index $SII"); 657 psii = (struct SII*)NULL; 658 } else { 659 /* restore errno to avoid misinterpretation */ 660 errno = olderrno; 661 entry = xsii->entry; 662 psii = (struct SII*)xsii->entry; 663 } 664 if (psii) { 665 /* 666 * Get last entry in block, but must get first one 667 * one first, as we should already be beyond the 668 * last one. For some reason the search for the last 669 * entry sometimes does not return the last block... 670 * we assume this can only happen in root block 671 */ 672 if (xsii->is_in_root) 673 entry = ntfs_ie_get_first 674 ((INDEX_HEADER*)&xsii->ir->index); 675 else 676 entry = ntfs_ie_get_first 677 ((INDEX_HEADER*)&xsii->ib->index); 678 /* 679 * All index blocks should be at least half full 680 * so there always is a last entry but one, 681 * except when creating the first entry in index root. 682 * This was however found not to be true : chkdsk 683 * sometimes deletes all the (unused) keys in the last 684 * index block without rebalancing the tree. 685 * When this happens, a new search is restarted from 686 * the smallest key. 687 */ 688 keyid = const_cpu_to_le32(0); 689 retries = 0; 690 while (entry) { 691 next = ntfs_index_next(entry,xsii); 692 if (next) { 693 psii = (struct SII*)next; 694 /* save last key and */ 695 /* available position */ 696 keyid = psii->keysecurid; 697 realign.parts.dataoffsh 698 = psii->dataoffsh; 699 realign.parts.dataoffsl 700 = psii->dataoffsl; 701 offs = le64_to_cpu(realign.all); 702 size = le32_to_cpu(psii->datasize); 703 } 704 entry = next; 705 if (!entry && !keyid && !retries) { 706 /* search failed, retry from smallest key */ 707 ntfs_index_ctx_reinit(xsii); 708 found = !ntfs_index_lookup((char*)&keyid, 709 sizeof(SII_INDEX_KEY), xsii); 710 if (!found && (errno != ENOENT)) { 711 ntfs_log_perror("Index $SII is broken"); 712 } else { 713 /* restore errno */ 714 errno = olderrno; 715 entry = xsii->entry; 716 } 717 retries++; 718 } 719 } 720 } 721 if (!keyid) { 722 /* 723 * could not find any entry, before creating the first 724 * entry, make a double check by making sure size of $SII 725 * is less than needed for one entry 726 */ 727 securid = const_cpu_to_le32(0); 728 na = ntfs_attr_open(vol->secure_ni,AT_INDEX_ROOT,sii_stream,4); 729 if (na) { 730 if ((size_t)na->data_size < sizeof(struct SII)) { 731 ntfs_log_error("Creating the first security_id\n"); 732 securid = const_cpu_to_le32(FIRST_SECURITY_ID); 733 } 734 ntfs_attr_close(na); 735 } 736 if (!securid) { 737 ntfs_log_error("Error creating a security_id\n"); 738 errno = EIO; 739 } 740 } else { 741 newkey = le32_to_cpu(keyid) + 1; 742 securid = cpu_to_le32(newkey); 743 } 744 /* 745 * The security attr has to be written twice 256KB 746 * apart. This implies that offsets like 747 * 0x40000*odd_integer must be left available for 748 * the second copy. So align to next block when 749 * the last byte overflows on a wrong block. 750 */ 751 752 if (securid) { 753 gap = (-size) & (ALIGN_SDS_ENTRY - 1); 754 offs += gap + size; 755 if ((offs + attrsz + sizeof(SECURITY_DESCRIPTOR_HEADER) - 1) 756 & ALIGN_SDS_BLOCK) { 757 offs = ((offs + attrsz 758 + sizeof(SECURITY_DESCRIPTOR_HEADER) - 1) 759 | (ALIGN_SDS_BLOCK - 1)) + 1; 760 } 761 if (!(offs & (ALIGN_SDS_BLOCK - 1))) 762 entersecurity_stuff(vol, offs); 763 /* 764 * now write the security attr to storage : 765 * first data, then SII, then SDH 766 * If failure occurs while writing SDS, data will never 767 * be accessed through indexes, and will be overwritten 768 * by the next allocated descriptor 769 * If failure occurs while writing SII, the id has not 770 * recorded and will be reallocated later 771 * If failure occurs while writing SDH, the space allocated 772 * in SDS or SII will not be reused, an inconsistency 773 * will persist with no significant consequence 774 */ 775 if (entersecurity_data(vol, attr, attrsz, hash, securid, offs, gap) 776 || entersecurity_indexes(vol, attrsz, hash, securid, offs)) 777 securid = const_cpu_to_le32(0); 778 } 779 /* inode now is dirty, synchronize it all */ 780 ntfs_index_entry_mark_dirty(vol->secure_xsii); 781 ntfs_index_ctx_reinit(vol->secure_xsii); 782 ntfs_index_entry_mark_dirty(vol->secure_xsdh); 783 ntfs_index_ctx_reinit(vol->secure_xsdh); 784 NInoSetDirty(vol->secure_ni); 785 if (ntfs_inode_sync(vol->secure_ni)) 786 ntfs_log_perror("Could not sync $Secure\n"); 787 return (securid); 788 } 789 790 /* 791 * Find a matching security descriptor in $Secure, 792 * if none, allocate a new id and write the descriptor to storage 793 * Returns id of entry, or zero if there is a problem. 794 * 795 * important : calls have to be serialized, however no locking is 796 * needed while fuse is not multithreaded 797 */ 798 799 static le32 setsecurityattr(ntfs_volume *vol, 800 const SECURITY_DESCRIPTOR_RELATIVE *attr, s64 attrsz) 801 { 802 struct SDH *psdh; /* this is an image of index (le) */ 803 union { 804 struct { 805 le32 dataoffsl; 806 le32 dataoffsh; 807 } parts; 808 le64 all; 809 } realign; 810 BOOL found; 811 BOOL collision; 812 size_t size; 813 size_t rdsize; 814 s64 offs; 815 int res; 816 ntfs_index_context *xsdh; 817 char *oldattr; 818 SDH_INDEX_KEY key; 819 INDEX_ENTRY *entry; 820 le32 securid; 821 le32 hash; 822 int olderrno; 823 824 hash = ntfs_security_hash(attr,attrsz); 825 oldattr = (char*)NULL; 826 securid = const_cpu_to_le32(0); 827 res = 0; 828 xsdh = vol->secure_xsdh; 829 if (vol->secure_ni && xsdh && !vol->secure_reentry++) { 830 ntfs_index_ctx_reinit(xsdh); 831 /* 832 * find the nearest key as (hash,0) 833 * (do not search for partial key : in case of collision, 834 * it could return a key which is not the first one which 835 * collides) 836 */ 837 key.hash = hash; 838 key.security_id = const_cpu_to_le32(0); 839 olderrno = errno; 840 found = !ntfs_index_lookup((char*)&key, 841 sizeof(SDH_INDEX_KEY), xsdh); 842 if (!found && (errno != ENOENT)) 843 ntfs_log_perror("Inconsistency in index $SDH"); 844 else { 845 /* restore errno to avoid misinterpretation */ 846 errno = olderrno; 847 entry = xsdh->entry; 848 found = FALSE; 849 /* 850 * lookup() may return a node with no data, 851 * if so get next 852 */ 853 if (entry->ie_flags & INDEX_ENTRY_END) 854 entry = ntfs_index_next(entry,xsdh); 855 do { 856 collision = FALSE; 857 psdh = (struct SDH*)entry; 858 if (psdh) 859 size = (size_t) le32_to_cpu(psdh->datasize) 860 - sizeof(SECURITY_DESCRIPTOR_HEADER); 861 else size = 0; 862 /* if hash is not the same, the key is not present */ 863 if (psdh && (size > 0) 864 && (psdh->keyhash == hash)) { 865 /* if hash is the same */ 866 /* check the whole record */ 867 realign.parts.dataoffsh = psdh->dataoffsh; 868 realign.parts.dataoffsl = psdh->dataoffsl; 869 offs = le64_to_cpu(realign.all) 870 + sizeof(SECURITY_DESCRIPTOR_HEADER); 871 oldattr = (char*)ntfs_malloc(size); 872 if (oldattr) { 873 rdsize = ntfs_attr_data_read( 874 vol->secure_ni, 875 STREAM_SDS, 4, 876 oldattr, size, offs); 877 found = (rdsize == size) 878 && !memcmp(oldattr,attr,size); 879 free(oldattr); 880 /* if the records do not compare */ 881 /* (hash collision), try next one */ 882 if (!found) { 883 entry = ntfs_index_next( 884 entry,xsdh); 885 collision = TRUE; 886 } 887 } else 888 res = ENOMEM; 889 } 890 } while (collision && entry); 891 if (found) 892 securid = psdh->keysecurid; 893 else { 894 if (res) { 895 errno = res; 896 securid = const_cpu_to_le32(0); 897 } else { 898 /* 899 * no matching key : 900 * have to build a new one 901 */ 902 securid = entersecurityattr(vol, 903 attr, attrsz, hash); 904 } 905 } 906 } 907 } 908 if (--vol->secure_reentry) 909 ntfs_log_perror("Reentry error, check no multithreading\n"); 910 return (securid); 911 } 912 913 914 /* 915 * Update the security descriptor of a file 916 * Either as an attribute (complying with pre v3.x NTFS version) 917 * or, when possible, as an entry in $Secure (for NTFS v3.x) 918 * 919 * returns 0 if success 920 */ 921 922 static int update_secur_descr(ntfs_volume *vol, 923 char *newattr, ntfs_inode *ni) 924 { 925 int newattrsz; 926 int written; 927 int res; 928 ntfs_attr *na; 929 930 newattrsz = ntfs_attr_size(newattr); 931 932 #if !FORCE_FORMAT_v1x 933 if ((vol->major_ver < 3) || !vol->secure_ni) { 934 #endif 935 936 /* update for NTFS format v1.x */ 937 938 /* update the old security attribute */ 939 na = ntfs_attr_open(ni, AT_SECURITY_DESCRIPTOR, AT_UNNAMED, 0); 940 if (na) { 941 /* resize attribute */ 942 res = ntfs_attr_truncate(na, (s64) newattrsz); 943 /* overwrite value */ 944 if (!res) { 945 written = (int)ntfs_attr_pwrite(na, (s64) 0, 946 (s64) newattrsz, newattr); 947 if (written != newattrsz) { 948 ntfs_log_error("Failed to update " 949 "a v1.x security descriptor\n"); 950 errno = EIO; 951 res = -1; 952 } 953 } 954 955 ntfs_attr_close(na); 956 /* if old security attribute was found, also */ 957 /* truncate standard information attribute to v1.x */ 958 /* this is needed when security data is wanted */ 959 /* as v1.x though volume is formatted for v3.x */ 960 na = ntfs_attr_open(ni, AT_STANDARD_INFORMATION, 961 AT_UNNAMED, 0); 962 if (na) { 963 clear_nino_flag(ni, v3_Extensions); 964 /* 965 * Truncating the record does not sweep extensions 966 * from copy in memory. Clear security_id to be safe 967 */ 968 ni->security_id = const_cpu_to_le32(0); 969 res = ntfs_attr_truncate(na, (s64)48); 970 ntfs_attr_close(na); 971 clear_nino_flag(ni, v3_Extensions); 972 } 973 } else { 974 /* 975 * insert the new security attribute if there 976 * were none 977 */ 978 res = ntfs_attr_add(ni, AT_SECURITY_DESCRIPTOR, 979 AT_UNNAMED, 0, (u8*)newattr, 980 (s64) newattrsz); 981 } 982 #if !FORCE_FORMAT_v1x 983 } else { 984 985 /* update for NTFS format v3.x */ 986 987 le32 securid; 988 989 securid = setsecurityattr(vol, 990 (const SECURITY_DESCRIPTOR_RELATIVE*)newattr, 991 (s64)newattrsz); 992 if (securid) { 993 na = ntfs_attr_open(ni, AT_STANDARD_INFORMATION, 994 AT_UNNAMED, 0); 995 if (na) { 996 res = 0; 997 if (!test_nino_flag(ni, v3_Extensions)) { 998 /* expand standard information attribute to v3.x */ 999 res = ntfs_attr_truncate(na, 1000 (s64)sizeof(STANDARD_INFORMATION)); 1001 ni->owner_id = const_cpu_to_le32(0); 1002 ni->quota_charged = const_cpu_to_le64(0); 1003 ni->usn = const_cpu_to_le64(0); 1004 ntfs_attr_remove(ni, 1005 AT_SECURITY_DESCRIPTOR, 1006 AT_UNNAMED, 0); 1007 } 1008 set_nino_flag(ni, v3_Extensions); 1009 ni->security_id = securid; 1010 ntfs_attr_close(na); 1011 } else { 1012 ntfs_log_error("Failed to update " 1013 "standard informations\n"); 1014 errno = EIO; 1015 res = -1; 1016 } 1017 } else 1018 res = -1; 1019 } 1020 #endif 1021 1022 /* mark node as dirty */ 1023 NInoSetDirty(ni); 1024 return (res); 1025 } 1026 1027 /* 1028 * Upgrade the security descriptor of a file 1029 * This is intended to allow graceful upgrades for files which 1030 * were created in previous versions, with a security attributes 1031 * and no security id. 1032 * 1033 * It will allocate a security id and replace the individual 1034 * security attribute by a reference to the global one 1035 * 1036 * Special files are not upgraded (currently / and files in 1037 * directories /$*) 1038 * 1039 * Though most code is similar to update_secur_desc() it has 1040 * been kept apart to facilitate the further processing of 1041 * special cases or even to remove it if found dangerous. 1042 * 1043 * returns 0 if success, 1044 * 1 if not upgradable. This is not an error. 1045 * -1 if there is a problem 1046 */ 1047 1048 static int upgrade_secur_desc(ntfs_volume *vol, 1049 const char *attr, ntfs_inode *ni) 1050 { 1051 int attrsz; 1052 int res; 1053 le32 securid; 1054 ntfs_attr *na; 1055 1056 /* 1057 * upgrade requires NTFS format v3.x 1058 * also refuse upgrading for special files 1059 * whose number is less than FILE_first_user 1060 */ 1061 1062 if ((vol->major_ver >= 3) 1063 && (ni->mft_no >= FILE_first_user)) { 1064 attrsz = ntfs_attr_size(attr); 1065 securid = setsecurityattr(vol, 1066 (const SECURITY_DESCRIPTOR_RELATIVE*)attr, 1067 (s64)attrsz); 1068 if (securid) { 1069 na = ntfs_attr_open(ni, AT_STANDARD_INFORMATION, 1070 AT_UNNAMED, 0); 1071 if (na) { 1072 /* expand standard information attribute to v3.x */ 1073 res = ntfs_attr_truncate(na, 1074 (s64)sizeof(STANDARD_INFORMATION)); 1075 ni->owner_id = const_cpu_to_le32(0); 1076 ni->quota_charged = const_cpu_to_le64(0); 1077 ni->usn = const_cpu_to_le64(0); 1078 ntfs_attr_remove(ni, AT_SECURITY_DESCRIPTOR, 1079 AT_UNNAMED, 0); 1080 set_nino_flag(ni, v3_Extensions); 1081 ni->security_id = securid; 1082 ntfs_attr_close(na); 1083 } else { 1084 ntfs_log_error("Failed to upgrade " 1085 "standard informations\n"); 1086 errno = EIO; 1087 res = -1; 1088 } 1089 } else 1090 res = -1; 1091 /* mark node as dirty */ 1092 NInoSetDirty(ni); 1093 } else 1094 res = 1; 1095 1096 return (res); 1097 } 1098 1099 /* 1100 * Optional simplified checking of group membership 1101 * 1102 * This only takes into account the groups defined in 1103 * /etc/group at initialization time. 1104 * It does not take into account the groups dynamically set by 1105 * setgroups() nor the changes in /etc/group since initialization 1106 * 1107 * This optional method could be useful if standard checking 1108 * leads to a performance concern. 1109 * 1110 * Should not be called for user root, however the group may be root 1111 * 1112 */ 1113 1114 static BOOL staticgroupmember(struct SECURITY_CONTEXT *scx, uid_t uid, gid_t gid) 1115 { 1116 BOOL ingroup; 1117 int grcnt; 1118 gid_t *groups; 1119 struct MAPPING *user; 1120 1121 ingroup = FALSE; 1122 if (uid) { 1123 user = scx->mapping[MAPUSERS]; 1124 while (user && ((uid_t)user->xid != uid)) 1125 user = user->next; 1126 if (user) { 1127 groups = user->groups; 1128 grcnt = user->grcnt; 1129 while ((--grcnt >= 0) && (groups[grcnt] != gid)) { } 1130 ingroup = (grcnt >= 0); 1131 } 1132 } 1133 return (ingroup); 1134 } 1135 1136 1137 /* 1138 * Check whether current thread owner is member of file group 1139 * 1140 * Should not be called for user root, however the group may be root 1141 * 1142 * As indicated by Miklos Szeredi : 1143 * 1144 * The group list is available in 1145 * 1146 * /proc/$PID/task/$TID/status 1147 * 1148 * and fuse supplies TID in get_fuse_context()->pid. The only problem is 1149 * finding out PID, for which I have no good solution, except to iterate 1150 * through all processes. This is rather slow, but may be speeded up 1151 * with caching and heuristics (for single threaded programs PID = TID). 1152 * 1153 * The following implementation gets the group list from 1154 * /proc/$TID/task/$TID/status which apparently exists and 1155 * contains the same data. 1156 */ 1157 1158 #ifdef __HAIKU__ 1159 static BOOL groupmember(struct SECURITY_CONTEXT *scx, uid_t uid, gid_t gid) 1160 { 1161 return TRUE; 1162 } 1163 #else 1164 static BOOL groupmember(struct SECURITY_CONTEXT *scx, uid_t uid, gid_t gid) 1165 { 1166 static char key[] = "\nGroups:"; 1167 char buf[BUFSZ+1]; 1168 char filename[64]; 1169 enum { INKEY, INSEP, INNUM, INEND } state; 1170 int fd; 1171 char c; 1172 int matched; 1173 BOOL ismember; 1174 int got; 1175 char *p; 1176 gid_t grp; 1177 pid_t tid; 1178 1179 if (scx->vol->secure_flags & (1 << SECURITY_STATICGRPS)) 1180 ismember = staticgroupmember(scx, uid, gid); 1181 else { 1182 ismember = FALSE; /* default return */ 1183 tid = scx->tid; 1184 sprintf(filename,"/proc/%u/task/%u/status",tid,tid); 1185 fd = open(filename,O_RDONLY); 1186 if (fd >= 0) { 1187 got = read(fd, buf, BUFSZ); 1188 buf[got] = 0; 1189 state = INKEY; 1190 matched = 0; 1191 p = buf; 1192 grp = 0; 1193 /* 1194 * A simple automaton to process lines like 1195 * Groups: 14 500 513 1196 */ 1197 do { 1198 c = *p++; 1199 if (!c) { 1200 /* refill buffer */ 1201 got = read(fd, buf, BUFSZ); 1202 buf[got] = 0; 1203 p = buf; 1204 c = *p++; /* 0 at end of file */ 1205 } 1206 switch (state) { 1207 case INKEY : 1208 if (key[matched] == c) { 1209 if (!key[++matched]) 1210 state = INSEP; 1211 } else 1212 if (key[0] == c) 1213 matched = 1; 1214 else 1215 matched = 0; 1216 break; 1217 case INSEP : 1218 if ((c >= '0') && (c <= '9')) { 1219 grp = c - '0'; 1220 state = INNUM; 1221 } else 1222 if ((c != ' ') && (c != '\t')) 1223 state = INEND; 1224 break; 1225 case INNUM : 1226 if ((c >= '0') && (c <= '9')) 1227 grp = grp*10 + c - '0'; 1228 else { 1229 ismember = (grp == gid); 1230 if ((c != ' ') && (c != '\t')) 1231 state = INEND; 1232 else 1233 state = INSEP; 1234 } 1235 default : 1236 break; 1237 } 1238 } while (!ismember && c && (state != INEND)); 1239 close(fd); 1240 if (!c) 1241 ntfs_log_error("No group record found in %s\n",filename); 1242 } else 1243 ntfs_log_error("Could not open %s\n",filename); 1244 } 1245 return (ismember); 1246 } 1247 #endif 1248 1249 /* 1250 * Cacheing is done two-way : 1251 * - from uid, gid and perm to securid (CACHED_SECURID) 1252 * - from a securid to uid, gid and perm (CACHED_PERMISSIONS) 1253 * 1254 * CACHED_SECURID data is kept in a most-recent-first list 1255 * which should not be too long to be efficient. Its optimal 1256 * size is depends on usage and is hard to determine. 1257 * 1258 * CACHED_PERMISSIONS data is kept in a two-level indexed array. It 1259 * is optimal at the expense of storage. Use of a most-recent-first 1260 * list would save memory and provide similar performances for 1261 * standard usage, but not for file servers with too many file 1262 * owners 1263 * 1264 * CACHED_PERMISSIONS_LEGACY is a special case for CACHED_PERMISSIONS 1265 * for legacy directories which were not allocated a security_id 1266 * it is organized in a most-recent-first list. 1267 * 1268 * In main caches, data is never invalidated, as the meaning of 1269 * a security_id only changes when user mapping is changed, which 1270 * current implies remounting. However returned entries may be 1271 * overwritten at next update, so data has to be copied elsewhere 1272 * before another cache update is made. 1273 * In legacy cache, data has to be invalidated when protection is 1274 * changed. 1275 * 1276 * Though the same data may be found in both list, they 1277 * must be kept separately : the interpretation of ACL 1278 * in both direction are approximations which could be non 1279 * reciprocal for some configuration of the user mapping data 1280 * 1281 * During the process of recompiling ntfs-3g from a tgz archive, 1282 * security processing added 7.6% to the cpu time used by ntfs-3g 1283 * and 30% if the cache is disabled. 1284 */ 1285 1286 static struct PERMISSIONS_CACHE *create_caches(struct SECURITY_CONTEXT *scx, 1287 u32 securindex) 1288 { 1289 struct PERMISSIONS_CACHE *cache; 1290 unsigned int index1; 1291 unsigned int i; 1292 1293 cache = (struct PERMISSIONS_CACHE*)NULL; 1294 /* create the first permissions blocks */ 1295 index1 = securindex >> CACHE_PERMISSIONS_BITS; 1296 cache = (struct PERMISSIONS_CACHE*) 1297 ntfs_malloc(sizeof(struct PERMISSIONS_CACHE) 1298 + index1*sizeof(struct CACHED_PERMISSIONS*)); 1299 if (cache) { 1300 cache->head.last = index1; 1301 cache->head.p_reads = 0; 1302 cache->head.p_hits = 0; 1303 cache->head.p_writes = 0; 1304 *scx->pseccache = cache; 1305 for (i=0; i<=index1; i++) 1306 cache->cachetable[i] 1307 = (struct CACHED_PERMISSIONS*)NULL; 1308 } 1309 return (cache); 1310 } 1311 1312 /* 1313 * Free memory used by caches 1314 * The only purpose is to facilitate the detection of memory leaks 1315 */ 1316 1317 static void free_caches(struct SECURITY_CONTEXT *scx) 1318 { 1319 unsigned int index1; 1320 struct PERMISSIONS_CACHE *pseccache; 1321 1322 pseccache = *scx->pseccache; 1323 if (pseccache) { 1324 for (index1=0; index1<=pseccache->head.last; index1++) 1325 if (pseccache->cachetable[index1]) { 1326 #if POSIXACLS 1327 struct CACHED_PERMISSIONS *cacheentry; 1328 unsigned int index2; 1329 1330 for (index2=0; index2<(1<< CACHE_PERMISSIONS_BITS); index2++) { 1331 cacheentry = &pseccache->cachetable[index1][index2]; 1332 if (cacheentry->valid 1333 && cacheentry->pxdesc) 1334 free(cacheentry->pxdesc); 1335 } 1336 #endif 1337 free(pseccache->cachetable[index1]); 1338 } 1339 free(pseccache); 1340 } 1341 } 1342 1343 static int compare(const struct CACHED_SECURID *cached, 1344 const struct CACHED_SECURID *item) 1345 { 1346 #if POSIXACLS 1347 size_t csize; 1348 size_t isize; 1349 1350 /* only compare data and sizes */ 1351 csize = (cached->variable ? 1352 sizeof(struct POSIX_ACL) 1353 + (((struct POSIX_SECURITY*)cached->variable)->acccnt 1354 + ((struct POSIX_SECURITY*)cached->variable)->defcnt) 1355 *sizeof(struct POSIX_ACE) : 1356 0); 1357 isize = (item->variable ? 1358 sizeof(struct POSIX_ACL) 1359 + (((struct POSIX_SECURITY*)item->variable)->acccnt 1360 + ((struct POSIX_SECURITY*)item->variable)->defcnt) 1361 *sizeof(struct POSIX_ACE) : 1362 0); 1363 return ((cached->uid != item->uid) 1364 || (cached->gid != item->gid) 1365 || (cached->dmode != item->dmode) 1366 || (csize != isize) 1367 || (csize 1368 && isize 1369 && memcmp(&((struct POSIX_SECURITY*)cached->variable)->acl, 1370 &((struct POSIX_SECURITY*)item->variable)->acl, csize))); 1371 #else 1372 return ((cached->uid != item->uid) 1373 || (cached->gid != item->gid) 1374 || (cached->dmode != item->dmode)); 1375 #endif 1376 } 1377 1378 static int leg_compare(const struct CACHED_PERMISSIONS_LEGACY *cached, 1379 const struct CACHED_PERMISSIONS_LEGACY *item) 1380 { 1381 return (cached->mft_no != item->mft_no); 1382 } 1383 1384 /* 1385 * Resize permission cache table 1386 * do not call unless resizing is needed 1387 * 1388 * If allocation fails, the cache size is not updated 1389 * Lack of memory is not considered as an error, the cache is left 1390 * consistent and errno is not set. 1391 */ 1392 1393 static void resize_cache(struct SECURITY_CONTEXT *scx, 1394 u32 securindex) 1395 { 1396 struct PERMISSIONS_CACHE *oldcache; 1397 struct PERMISSIONS_CACHE *newcache; 1398 int newcnt; 1399 int oldcnt; 1400 unsigned int index1; 1401 unsigned int i; 1402 1403 oldcache = *scx->pseccache; 1404 index1 = securindex >> CACHE_PERMISSIONS_BITS; 1405 newcnt = index1 + 1; 1406 if (newcnt <= ((CACHE_PERMISSIONS_SIZE 1407 + (1 << CACHE_PERMISSIONS_BITS) 1408 - 1) >> CACHE_PERMISSIONS_BITS)) { 1409 /* expand cache beyond current end, do not use realloc() */ 1410 /* to avoid losing data when there is no more memory */ 1411 oldcnt = oldcache->head.last + 1; 1412 newcache = (struct PERMISSIONS_CACHE*) 1413 ntfs_malloc( 1414 sizeof(struct PERMISSIONS_CACHE) 1415 + (newcnt - 1)*sizeof(struct CACHED_PERMISSIONS*)); 1416 if (newcache) { 1417 memcpy(newcache,oldcache, 1418 sizeof(struct PERMISSIONS_CACHE) 1419 + (oldcnt - 1)*sizeof(struct CACHED_PERMISSIONS*)); 1420 free(oldcache); 1421 /* mark new entries as not valid */ 1422 for (i=newcache->head.last+1; i<=index1; i++) 1423 newcache->cachetable[i] 1424 = (struct CACHED_PERMISSIONS*)NULL; 1425 newcache->head.last = index1; 1426 *scx->pseccache = newcache; 1427 } 1428 } 1429 } 1430 1431 /* 1432 * Enter uid, gid and mode into cache, if possible 1433 * 1434 * returns the updated or created cache entry, 1435 * or NULL if not possible (typically if there is no 1436 * security id associated) 1437 */ 1438 1439 #if POSIXACLS 1440 static struct CACHED_PERMISSIONS *enter_cache(struct SECURITY_CONTEXT *scx, 1441 ntfs_inode *ni, uid_t uid, gid_t gid, 1442 struct POSIX_SECURITY *pxdesc) 1443 #else 1444 static struct CACHED_PERMISSIONS *enter_cache(struct SECURITY_CONTEXT *scx, 1445 ntfs_inode *ni, uid_t uid, gid_t gid, mode_t mode) 1446 #endif 1447 { 1448 struct CACHED_PERMISSIONS *cacheentry; 1449 struct CACHED_PERMISSIONS *cacheblock; 1450 struct PERMISSIONS_CACHE *pcache; 1451 u32 securindex; 1452 #if POSIXACLS 1453 int pxsize; 1454 struct POSIX_SECURITY *pxcached; 1455 #endif 1456 unsigned int index1; 1457 unsigned int index2; 1458 int i; 1459 1460 /* cacheing is only possible if a security_id has been defined */ 1461 if (test_nino_flag(ni, v3_Extensions) 1462 && ni->security_id) { 1463 /* 1464 * Immediately test the most frequent situation 1465 * where the entry exists 1466 */ 1467 securindex = le32_to_cpu(ni->security_id); 1468 index1 = securindex >> CACHE_PERMISSIONS_BITS; 1469 index2 = securindex & ((1 << CACHE_PERMISSIONS_BITS) - 1); 1470 pcache = *scx->pseccache; 1471 if (pcache 1472 && (pcache->head.last >= index1) 1473 && pcache->cachetable[index1]) { 1474 cacheentry = &pcache->cachetable[index1][index2]; 1475 cacheentry->uid = uid; 1476 cacheentry->gid = gid; 1477 #if POSIXACLS 1478 if (cacheentry->valid && cacheentry->pxdesc) 1479 free(cacheentry->pxdesc); 1480 if (pxdesc) { 1481 pxsize = sizeof(struct POSIX_SECURITY) 1482 + (pxdesc->acccnt + pxdesc->defcnt)*sizeof(struct POSIX_ACE); 1483 pxcached = (struct POSIX_SECURITY*)malloc(pxsize); 1484 if (pxcached) { 1485 memcpy(pxcached, pxdesc, pxsize); 1486 cacheentry->pxdesc = pxcached; 1487 } else { 1488 cacheentry->valid = 0; 1489 cacheentry = (struct CACHED_PERMISSIONS*)NULL; 1490 } 1491 cacheentry->mode = pxdesc->mode & 07777; 1492 } else 1493 cacheentry->pxdesc = (struct POSIX_SECURITY*)NULL; 1494 #else 1495 cacheentry->mode = mode & 07777; 1496 #endif 1497 cacheentry->inh_fileid = const_cpu_to_le32(0); 1498 cacheentry->inh_dirid = const_cpu_to_le32(0); 1499 cacheentry->valid = 1; 1500 pcache->head.p_writes++; 1501 } else { 1502 if (!pcache) { 1503 /* create the first cache block */ 1504 pcache = create_caches(scx, securindex); 1505 } else { 1506 if (index1 > pcache->head.last) { 1507 resize_cache(scx, securindex); 1508 pcache = *scx->pseccache; 1509 } 1510 } 1511 /* allocate block, if cache table was allocated */ 1512 if (pcache && (index1 <= pcache->head.last)) { 1513 cacheblock = (struct CACHED_PERMISSIONS*) 1514 malloc(sizeof(struct CACHED_PERMISSIONS) 1515 << CACHE_PERMISSIONS_BITS); 1516 pcache->cachetable[index1] = cacheblock; 1517 for (i=0; i<(1 << CACHE_PERMISSIONS_BITS); i++) 1518 cacheblock[i].valid = 0; 1519 cacheentry = &cacheblock[index2]; 1520 if (cacheentry) { 1521 cacheentry->uid = uid; 1522 cacheentry->gid = gid; 1523 #if POSIXACLS 1524 if (pxdesc) { 1525 pxsize = sizeof(struct POSIX_SECURITY) 1526 + (pxdesc->acccnt + pxdesc->defcnt)*sizeof(struct POSIX_ACE); 1527 pxcached = (struct POSIX_SECURITY*)malloc(pxsize); 1528 if (pxcached) { 1529 memcpy(pxcached, pxdesc, pxsize); 1530 cacheentry->pxdesc = pxcached; 1531 } else { 1532 cacheentry->valid = 0; 1533 cacheentry = (struct CACHED_PERMISSIONS*)NULL; 1534 } 1535 cacheentry->mode = pxdesc->mode & 07777; 1536 } else 1537 cacheentry->pxdesc = (struct POSIX_SECURITY*)NULL; 1538 #else 1539 cacheentry->mode = mode & 07777; 1540 #endif 1541 cacheentry->inh_fileid = const_cpu_to_le32(0); 1542 cacheentry->inh_dirid = const_cpu_to_le32(0); 1543 cacheentry->valid = 1; 1544 pcache->head.p_writes++; 1545 } 1546 } else 1547 cacheentry = (struct CACHED_PERMISSIONS*)NULL; 1548 } 1549 } else { 1550 cacheentry = (struct CACHED_PERMISSIONS*)NULL; 1551 #if CACHE_LEGACY_SIZE 1552 if (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY) { 1553 struct CACHED_PERMISSIONS_LEGACY wanted; 1554 struct CACHED_PERMISSIONS_LEGACY *legacy; 1555 1556 wanted.perm.uid = uid; 1557 wanted.perm.gid = gid; 1558 #if POSIXACLS 1559 wanted.perm.mode = pxdesc->mode & 07777; 1560 wanted.perm.inh_fileid = const_cpu_to_le32(0); 1561 wanted.perm.inh_dirid = const_cpu_to_le32(0); 1562 wanted.mft_no = ni->mft_no; 1563 wanted.variable = (void*)pxdesc; 1564 wanted.varsize = sizeof(struct POSIX_SECURITY) 1565 + (pxdesc->acccnt + pxdesc->defcnt)*sizeof(struct POSIX_ACE); 1566 #else 1567 wanted.perm.mode = mode & 07777; 1568 wanted.perm.inh_fileid = const_cpu_to_le32(0); 1569 wanted.perm.inh_dirid = const_cpu_to_le32(0); 1570 wanted.mft_no = ni->mft_no; 1571 wanted.variable = (void*)NULL; 1572 wanted.varsize = 0; 1573 #endif 1574 legacy = (struct CACHED_PERMISSIONS_LEGACY*)ntfs_enter_cache( 1575 scx->vol->legacy_cache, GENERIC(&wanted), 1576 (cache_compare)leg_compare); 1577 if (legacy) { 1578 cacheentry = &legacy->perm; 1579 #if POSIXACLS 1580 /* 1581 * give direct access to the cached pxdesc 1582 * in the permissions structure 1583 */ 1584 cacheentry->pxdesc = legacy->variable; 1585 #endif 1586 } 1587 } 1588 #endif 1589 } 1590 return (cacheentry); 1591 } 1592 1593 /* 1594 * Fetch owner, group and permission of a file, if cached 1595 * 1596 * Beware : do not use the returned entry after a cache update : 1597 * the cache may be relocated making the returned entry meaningless 1598 * 1599 * returns the cache entry, or NULL if not available 1600 */ 1601 1602 static struct CACHED_PERMISSIONS *fetch_cache(struct SECURITY_CONTEXT *scx, 1603 ntfs_inode *ni) 1604 { 1605 struct CACHED_PERMISSIONS *cacheentry; 1606 struct PERMISSIONS_CACHE *pcache; 1607 u32 securindex; 1608 unsigned int index1; 1609 unsigned int index2; 1610 1611 /* cacheing is only possible if a security_id has been defined */ 1612 cacheentry = (struct CACHED_PERMISSIONS*)NULL; 1613 if (test_nino_flag(ni, v3_Extensions) 1614 && (ni->security_id)) { 1615 securindex = le32_to_cpu(ni->security_id); 1616 index1 = securindex >> CACHE_PERMISSIONS_BITS; 1617 index2 = securindex & ((1 << CACHE_PERMISSIONS_BITS) - 1); 1618 pcache = *scx->pseccache; 1619 if (pcache 1620 && (pcache->head.last >= index1) 1621 && pcache->cachetable[index1]) { 1622 cacheentry = &pcache->cachetable[index1][index2]; 1623 /* reject if entry is not valid */ 1624 if (!cacheentry->valid) 1625 cacheentry = (struct CACHED_PERMISSIONS*)NULL; 1626 else 1627 pcache->head.p_hits++; 1628 if (pcache) 1629 pcache->head.p_reads++; 1630 } 1631 } 1632 #if CACHE_LEGACY_SIZE 1633 else { 1634 cacheentry = (struct CACHED_PERMISSIONS*)NULL; 1635 if (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY) { 1636 struct CACHED_PERMISSIONS_LEGACY wanted; 1637 struct CACHED_PERMISSIONS_LEGACY *legacy; 1638 1639 wanted.mft_no = ni->mft_no; 1640 wanted.variable = (void*)NULL; 1641 wanted.varsize = 0; 1642 legacy = (struct CACHED_PERMISSIONS_LEGACY*)ntfs_fetch_cache( 1643 scx->vol->legacy_cache, GENERIC(&wanted), 1644 (cache_compare)leg_compare); 1645 if (legacy) cacheentry = &legacy->perm; 1646 } 1647 } 1648 #endif 1649 #if POSIXACLS 1650 if (cacheentry && !cacheentry->pxdesc) { 1651 ntfs_log_error("No Posix descriptor in cache\n"); 1652 cacheentry = (struct CACHED_PERMISSIONS*)NULL; 1653 } 1654 #endif 1655 return (cacheentry); 1656 } 1657 1658 /* 1659 * Retrieve a security attribute from $Secure 1660 */ 1661 1662 static char *retrievesecurityattr(ntfs_volume *vol, SII_INDEX_KEY id) 1663 { 1664 struct SII *psii; 1665 union { 1666 struct { 1667 le32 dataoffsl; 1668 le32 dataoffsh; 1669 } parts; 1670 le64 all; 1671 } realign; 1672 int found; 1673 size_t size; 1674 size_t rdsize; 1675 s64 offs; 1676 ntfs_inode *ni; 1677 ntfs_index_context *xsii; 1678 char *securattr; 1679 1680 securattr = (char*)NULL; 1681 ni = vol->secure_ni; 1682 xsii = vol->secure_xsii; 1683 if (ni && xsii) { 1684 ntfs_index_ctx_reinit(xsii); 1685 found = 1686 !ntfs_index_lookup((char*)&id, 1687 sizeof(SII_INDEX_KEY), xsii); 1688 if (found) { 1689 psii = (struct SII*)xsii->entry; 1690 size = 1691 (size_t) le32_to_cpu(psii->datasize) 1692 - sizeof(SECURITY_DESCRIPTOR_HEADER); 1693 /* work around bad alignment problem */ 1694 realign.parts.dataoffsh = psii->dataoffsh; 1695 realign.parts.dataoffsl = psii->dataoffsl; 1696 offs = le64_to_cpu(realign.all) 1697 + sizeof(SECURITY_DESCRIPTOR_HEADER); 1698 1699 securattr = (char*)ntfs_malloc(size); 1700 if (securattr) { 1701 rdsize = ntfs_attr_data_read( 1702 ni, STREAM_SDS, 4, 1703 securattr, size, offs); 1704 if ((rdsize != size) 1705 || !ntfs_valid_descr(securattr, 1706 rdsize)) { 1707 /* error to be logged by caller */ 1708 free(securattr); 1709 securattr = (char*)NULL; 1710 } 1711 } 1712 } else 1713 if (errno != ENOENT) 1714 ntfs_log_perror("Inconsistency in index $SII"); 1715 } 1716 if (!securattr) { 1717 ntfs_log_error("Failed to retrieve a security descriptor\n"); 1718 errno = EIO; 1719 } 1720 return (securattr); 1721 } 1722 1723 /* 1724 * Get the security descriptor associated to a file 1725 * 1726 * Either : 1727 * - read the security descriptor attribute (v1.x format) 1728 * - or find the descriptor in $Secure:$SDS (v3.x format) 1729 * 1730 * in both case, sanity checks are done on the attribute and 1731 * the descriptor can be assumed safe 1732 * 1733 * The returned descriptor is dynamically allocated and has to be freed 1734 */ 1735 1736 static char *getsecurityattr(ntfs_volume *vol, ntfs_inode *ni) 1737 { 1738 SII_INDEX_KEY securid; 1739 char *securattr; 1740 s64 readallsz; 1741 1742 /* 1743 * Warning : in some situations, after fixing by chkdsk, 1744 * v3_Extensions are marked present (long standard informations) 1745 * with a default security descriptor inserted in an 1746 * attribute 1747 */ 1748 if (test_nino_flag(ni, v3_Extensions) 1749 && vol->secure_ni && ni->security_id) { 1750 /* get v3.x descriptor in $Secure */ 1751 securid.security_id = ni->security_id; 1752 securattr = retrievesecurityattr(vol,securid); 1753 if (!securattr) 1754 ntfs_log_error("Bad security descriptor for 0x%lx\n", 1755 (long)le32_to_cpu(ni->security_id)); 1756 } else { 1757 /* get v1.x security attribute */ 1758 readallsz = 0; 1759 securattr = ntfs_attr_readall(ni, AT_SECURITY_DESCRIPTOR, 1760 AT_UNNAMED, 0, &readallsz); 1761 if (securattr && !ntfs_valid_descr(securattr, readallsz)) { 1762 ntfs_log_error("Bad security descriptor for inode %lld\n", 1763 (long long)ni->mft_no); 1764 free(securattr); 1765 securattr = (char*)NULL; 1766 } 1767 } 1768 if (!securattr) { 1769 /* 1770 * in some situations, there is no security 1771 * descriptor, and chkdsk does not detect or fix 1772 * anything. This could be a normal situation. 1773 * When this happens, simulate a descriptor with 1774 * minimum rights, so that a real descriptor can 1775 * be created by chown or chmod 1776 */ 1777 ntfs_log_error("No security descriptor found for inode %lld\n", 1778 (long long)ni->mft_no); 1779 securattr = ntfs_build_descr(0, 0, adminsid, adminsid); 1780 } 1781 return (securattr); 1782 } 1783 1784 #if POSIXACLS 1785 1786 /* 1787 * Determine which access types to a file are allowed 1788 * according to the relation of current process to the file 1789 * 1790 * Do not call if default_permissions is set 1791 */ 1792 1793 static int access_check_posix(struct SECURITY_CONTEXT *scx, 1794 struct POSIX_SECURITY *pxdesc, mode_t request, 1795 uid_t uid, gid_t gid) 1796 { 1797 struct POSIX_ACE *pxace; 1798 int userperms; 1799 int groupperms; 1800 int mask; 1801 BOOL somegroup; 1802 BOOL needgroups; 1803 mode_t perms; 1804 int i; 1805 1806 perms = pxdesc->mode; 1807 /* owner and root access */ 1808 if (!scx->uid || (uid == scx->uid)) { 1809 if (!scx->uid) { 1810 /* root access if owner or other execution */ 1811 if (perms & 0101) 1812 perms = 07777; 1813 else { 1814 /* root access if some group execution */ 1815 groupperms = 0; 1816 mask = 7; 1817 for (i=pxdesc->acccnt-1; i>=0 ; i--) { 1818 pxace = &pxdesc->acl.ace[i]; 1819 switch (pxace->tag) { 1820 case POSIX_ACL_USER_OBJ : 1821 case POSIX_ACL_GROUP_OBJ : 1822 case POSIX_ACL_GROUP : 1823 groupperms |= pxace->perms; 1824 break; 1825 case POSIX_ACL_MASK : 1826 mask = pxace->perms & 7; 1827 break; 1828 default : 1829 break; 1830 } 1831 } 1832 perms = (groupperms & mask & 1) | 6; 1833 } 1834 } else 1835 perms &= 07700; 1836 } else { 1837 /* 1838 * analyze designated users, get mask 1839 * and identify whether we need to check 1840 * the group memberships. The groups are 1841 * not needed when all groups have the 1842 * same permissions as other for the 1843 * requested modes. 1844 */ 1845 userperms = -1; 1846 groupperms = -1; 1847 needgroups = FALSE; 1848 mask = 7; 1849 for (i=pxdesc->acccnt-1; i>=0 ; i--) { 1850 pxace = &pxdesc->acl.ace[i]; 1851 switch (pxace->tag) { 1852 case POSIX_ACL_USER : 1853 if ((uid_t)pxace->id == scx->uid) 1854 userperms = pxace->perms; 1855 break; 1856 case POSIX_ACL_MASK : 1857 mask = pxace->perms & 7; 1858 break; 1859 case POSIX_ACL_GROUP_OBJ : 1860 case POSIX_ACL_GROUP : 1861 if (((pxace->perms & mask) ^ perms) 1862 & (request >> 6) & 7) 1863 needgroups = TRUE; 1864 break; 1865 default : 1866 break; 1867 } 1868 } 1869 /* designated users */ 1870 if (userperms >= 0) 1871 perms = (perms & 07000) + (userperms & mask); 1872 else if (!needgroups) 1873 perms &= 07007; 1874 else { 1875 /* owning group */ 1876 if (!(~(perms >> 3) & request & mask) 1877 && ((gid == scx->gid) 1878 || groupmember(scx, scx->uid, gid))) 1879 perms &= 07070; 1880 else { 1881 /* other groups */ 1882 groupperms = -1; 1883 somegroup = FALSE; 1884 for (i=pxdesc->acccnt-1; i>=0 ; i--) { 1885 pxace = &pxdesc->acl.ace[i]; 1886 if ((pxace->tag == POSIX_ACL_GROUP) 1887 && groupmember(scx, uid, pxace->id)) { 1888 if (!(~pxace->perms & request & mask)) 1889 groupperms = pxace->perms; 1890 somegroup = TRUE; 1891 } 1892 } 1893 if (groupperms >= 0) 1894 perms = (perms & 07000) + (groupperms & mask); 1895 else 1896 if (somegroup) 1897 perms = 0; 1898 else 1899 perms &= 07007; 1900 } 1901 } 1902 } 1903 return (perms); 1904 } 1905 1906 /* 1907 * Get permissions to access a file 1908 * Takes into account the relation of user to file (owner, group, ...) 1909 * Do no use as mode of the file 1910 * Do no call if default_permissions is set 1911 * 1912 * returns -1 if there is a problem 1913 */ 1914 1915 static int ntfs_get_perm(struct SECURITY_CONTEXT *scx, 1916 ntfs_inode * ni, mode_t request) 1917 { 1918 const SECURITY_DESCRIPTOR_RELATIVE *phead; 1919 const struct CACHED_PERMISSIONS *cached; 1920 char *securattr; 1921 const SID *usid; /* owner of file/directory */ 1922 const SID *gsid; /* group of file/directory */ 1923 uid_t uid; 1924 gid_t gid; 1925 int perm; 1926 BOOL isdir; 1927 struct POSIX_SECURITY *pxdesc; 1928 1929 if (!scx->mapping[MAPUSERS]) 1930 perm = 07777; 1931 else { 1932 /* check whether available in cache */ 1933 cached = fetch_cache(scx,ni); 1934 if (cached) { 1935 uid = cached->uid; 1936 gid = cached->gid; 1937 perm = access_check_posix(scx,cached->pxdesc,request,uid,gid); 1938 } else { 1939 perm = 0; /* default to no permission */ 1940 isdir = (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY) 1941 != const_cpu_to_le16(0); 1942 securattr = getsecurityattr(scx->vol, ni); 1943 if (securattr) { 1944 phead = (const SECURITY_DESCRIPTOR_RELATIVE*) 1945 securattr; 1946 gsid = (const SID*)& 1947 securattr[le32_to_cpu(phead->group)]; 1948 gid = ntfs_find_group(scx->mapping[MAPGROUPS],gsid); 1949 #if OWNERFROMACL 1950 usid = ntfs_acl_owner(securattr); 1951 pxdesc = ntfs_build_permissions_posix(scx->mapping,securattr, 1952 usid, gsid, isdir); 1953 if (pxdesc) 1954 perm = pxdesc->mode & 07777; 1955 else 1956 perm = -1; 1957 uid = ntfs_find_user(scx->mapping[MAPUSERS],usid); 1958 #else 1959 usid = (const SID*)& 1960 securattr[le32_to_cpu(phead->owner)]; 1961 pxdesc = ntfs_build_permissions_posix(scx,securattr, 1962 usid, gsid, isdir); 1963 if (pxdesc) 1964 perm = pxdesc->mode & 07777; 1965 else 1966 perm = -1; 1967 if (!perm && ntfs_same_sid(usid, adminsid)) { 1968 uid = find_tenant(scx, securattr); 1969 if (uid) 1970 perm = 0700; 1971 } else 1972 uid = ntfs_find_user(scx->mapping[MAPUSERS],usid); 1973 #endif 1974 /* 1975 * Create a security id if there were none 1976 * and upgrade option is selected 1977 */ 1978 if (!test_nino_flag(ni, v3_Extensions) 1979 && (perm >= 0) 1980 && (scx->vol->secure_flags 1981 & (1 << SECURITY_ADDSECURIDS))) { 1982 upgrade_secur_desc(scx->vol, 1983 securattr, ni); 1984 /* 1985 * fetch owner and group for cacheing 1986 * if there is a securid 1987 */ 1988 } 1989 if (test_nino_flag(ni, v3_Extensions) 1990 && (perm >= 0)) { 1991 enter_cache(scx, ni, uid, 1992 gid, pxdesc); 1993 } 1994 if (pxdesc) { 1995 perm = access_check_posix(scx,pxdesc,request,uid,gid); 1996 free(pxdesc); 1997 } 1998 free(securattr); 1999 } else { 2000 perm = -1; 2001 uid = gid = 0; 2002 } 2003 } 2004 } 2005 return (perm); 2006 } 2007 2008 /* 2009 * Get a Posix ACL 2010 * 2011 * returns size or -errno if there is a problem 2012 * if size was too small, no copy is done and errno is not set, 2013 * the caller is expected to issue a new call 2014 */ 2015 2016 int ntfs_get_posix_acl(struct SECURITY_CONTEXT *scx, ntfs_inode *ni, 2017 const char *name, char *value, size_t size) 2018 { 2019 const SECURITY_DESCRIPTOR_RELATIVE *phead; 2020 struct POSIX_SECURITY *pxdesc; 2021 const struct CACHED_PERMISSIONS *cached; 2022 char *securattr; 2023 const SID *usid; /* owner of file/directory */ 2024 const SID *gsid; /* group of file/directory */ 2025 uid_t uid; 2026 gid_t gid; 2027 BOOL isdir; 2028 size_t outsize; 2029 2030 outsize = 0; /* default to error */ 2031 if (!scx->mapping[MAPUSERS]) 2032 errno = ENOTSUP; 2033 else { 2034 /* check whether available in cache */ 2035 cached = fetch_cache(scx,ni); 2036 if (cached) 2037 pxdesc = cached->pxdesc; 2038 else { 2039 securattr = getsecurityattr(scx->vol, ni); 2040 isdir = (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY) 2041 != const_cpu_to_le16(0); 2042 if (securattr) { 2043 phead = 2044 (const SECURITY_DESCRIPTOR_RELATIVE*) 2045 securattr; 2046 gsid = (const SID*)& 2047 securattr[le32_to_cpu(phead->group)]; 2048 #if OWNERFROMACL 2049 usid = ntfs_acl_owner(securattr); 2050 #else 2051 usid = (const SID*)& 2052 securattr[le32_to_cpu(phead->owner)]; 2053 #endif 2054 pxdesc = ntfs_build_permissions_posix(scx->mapping,securattr, 2055 usid, gsid, isdir); 2056 2057 /* 2058 * fetch owner and group for cacheing 2059 */ 2060 if (pxdesc) { 2061 /* 2062 * Create a security id if there were none 2063 * and upgrade option is selected 2064 */ 2065 if (!test_nino_flag(ni, v3_Extensions) 2066 && (scx->vol->secure_flags 2067 & (1 << SECURITY_ADDSECURIDS))) { 2068 upgrade_secur_desc(scx->vol, 2069 securattr, ni); 2070 } 2071 #if OWNERFROMACL 2072 uid = ntfs_find_user(scx->mapping[MAPUSERS],usid); 2073 #else 2074 if (!(pxdesc->mode & 07777) 2075 && ntfs_same_sid(usid, adminsid)) { 2076 uid = find_tenant(scx, 2077 securattr); 2078 } else 2079 uid = ntfs_find_user(scx->mapping[MAPUSERS],usid); 2080 #endif 2081 gid = ntfs_find_group(scx->mapping[MAPGROUPS],gsid); 2082 if (pxdesc->tagsset & POSIX_ACL_EXTENSIONS) 2083 enter_cache(scx, ni, uid, 2084 gid, pxdesc); 2085 } 2086 free(securattr); 2087 } else 2088 pxdesc = (struct POSIX_SECURITY*)NULL; 2089 } 2090 2091 if (pxdesc) { 2092 if (ntfs_valid_posix(pxdesc)) { 2093 if (!strcmp(name,"system.posix_acl_default")) { 2094 if (ni->mrec->flags 2095 & MFT_RECORD_IS_DIRECTORY) 2096 outsize = sizeof(struct POSIX_ACL) 2097 + pxdesc->defcnt*sizeof(struct POSIX_ACE); 2098 else { 2099 /* 2100 * getting default ACL from plain file : 2101 * return EACCES if size > 0 as 2102 * indicated in the man, but return ok 2103 * if size == 0, so that ls does not 2104 * display an error 2105 */ 2106 if (size > 0) { 2107 outsize = 0; 2108 errno = EACCES; 2109 } else 2110 outsize = sizeof(struct POSIX_ACL); 2111 } 2112 if (outsize && (outsize <= size)) { 2113 memcpy(value,&pxdesc->acl,sizeof(struct POSIX_ACL)); 2114 memcpy(&value[sizeof(struct POSIX_ACL)], 2115 &pxdesc->acl.ace[pxdesc->firstdef], 2116 outsize-sizeof(struct POSIX_ACL)); 2117 } 2118 } else { 2119 outsize = sizeof(struct POSIX_ACL) 2120 + pxdesc->acccnt*sizeof(struct POSIX_ACE); 2121 if (outsize <= size) 2122 memcpy(value,&pxdesc->acl,outsize); 2123 } 2124 } else { 2125 outsize = 0; 2126 errno = EIO; 2127 ntfs_log_error("Invalid Posix ACL built\n"); 2128 } 2129 if (!cached) 2130 free(pxdesc); 2131 } else 2132 outsize = 0; 2133 } 2134 return (outsize ? (int)outsize : -errno); 2135 } 2136 2137 #else /* POSIXACLS */ 2138 2139 2140 /* 2141 * Get permissions to access a file 2142 * Takes into account the relation of user to file (owner, group, ...) 2143 * Do no use as mode of the file 2144 * 2145 * returns -1 if there is a problem 2146 */ 2147 2148 static int ntfs_get_perm(struct SECURITY_CONTEXT *scx, 2149 ntfs_inode *ni, mode_t request) 2150 { 2151 const SECURITY_DESCRIPTOR_RELATIVE *phead; 2152 const struct CACHED_PERMISSIONS *cached; 2153 char *securattr; 2154 const SID *usid; /* owner of file/directory */ 2155 const SID *gsid; /* group of file/directory */ 2156 BOOL isdir; 2157 uid_t uid; 2158 gid_t gid; 2159 int perm; 2160 2161 if (!scx->mapping[MAPUSERS] || (!scx->uid && !(request & S_IEXEC))) 2162 perm = 07777; 2163 else { 2164 /* check whether available in cache */ 2165 cached = fetch_cache(scx,ni); 2166 if (cached) { 2167 perm = cached->mode; 2168 uid = cached->uid; 2169 gid = cached->gid; 2170 } else { 2171 perm = 0; /* default to no permission */ 2172 isdir = (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY) 2173 != const_cpu_to_le16(0); 2174 securattr = getsecurityattr(scx->vol, ni); 2175 if (securattr) { 2176 phead = (const SECURITY_DESCRIPTOR_RELATIVE*) 2177 securattr; 2178 gsid = (const SID*)& 2179 securattr[le32_to_cpu(phead->group)]; 2180 gid = ntfs_find_group(scx->mapping[MAPGROUPS],gsid); 2181 #if OWNERFROMACL 2182 usid = ntfs_acl_owner(securattr); 2183 perm = ntfs_build_permissions(securattr, 2184 usid, gsid, isdir); 2185 uid = ntfs_find_user(scx->mapping[MAPUSERS],usid); 2186 #else 2187 usid = (const SID*)& 2188 securattr[le32_to_cpu(phead->owner)]; 2189 perm = ntfs_build_permissions(securattr, 2190 usid, gsid, isdir); 2191 if (!perm && ntfs_same_sid(usid, adminsid)) { 2192 uid = find_tenant(scx, securattr); 2193 if (uid) 2194 perm = 0700; 2195 } else 2196 uid = ntfs_find_user(scx->mapping[MAPUSERS],usid); 2197 #endif 2198 /* 2199 * Create a security id if there were none 2200 * and upgrade option is selected 2201 */ 2202 if (!test_nino_flag(ni, v3_Extensions) 2203 && (perm >= 0) 2204 && (scx->vol->secure_flags 2205 & (1 << SECURITY_ADDSECURIDS))) { 2206 upgrade_secur_desc(scx->vol, 2207 securattr, ni); 2208 /* 2209 * fetch owner and group for cacheing 2210 * if there is a securid 2211 */ 2212 } 2213 if (test_nino_flag(ni, v3_Extensions) 2214 && (perm >= 0)) { 2215 enter_cache(scx, ni, uid, 2216 gid, perm); 2217 } 2218 free(securattr); 2219 } else { 2220 perm = -1; 2221 uid = gid = 0; 2222 } 2223 } 2224 if (perm >= 0) { 2225 if (!scx->uid) { 2226 /* root access and execution */ 2227 if (perm & 0111) 2228 perm = 07777; 2229 else 2230 perm = 0; 2231 } else 2232 if (uid == scx->uid) 2233 perm &= 07700; 2234 else 2235 /* 2236 * avoid checking group membership 2237 * when the requested perms for group 2238 * are the same as perms for other 2239 */ 2240 if ((gid == scx->gid) 2241 || ((((perm >> 3) ^ perm) 2242 & (request >> 6) & 7) 2243 && groupmember(scx, scx->uid, gid))) 2244 perm &= 07070; 2245 else 2246 perm &= 07007; 2247 } 2248 } 2249 return (perm); 2250 } 2251 2252 #endif /* POSIXACLS */ 2253 2254 /* 2255 * Get an NTFS ACL 2256 * 2257 * Returns size or -errno if there is a problem 2258 * if size was too small, no copy is done and errno is not set, 2259 * the caller is expected to issue a new call 2260 */ 2261 2262 int ntfs_get_ntfs_acl(struct SECURITY_CONTEXT *scx, ntfs_inode *ni, 2263 char *value, size_t size) 2264 { 2265 char *securattr; 2266 size_t outsize; 2267 2268 outsize = 0; /* default to no data and no error */ 2269 securattr = getsecurityattr(scx->vol, ni); 2270 if (securattr) { 2271 outsize = ntfs_attr_size(securattr); 2272 if (outsize <= size) { 2273 memcpy(value,securattr,outsize); 2274 } 2275 free(securattr); 2276 } 2277 return (outsize ? (int)outsize : -errno); 2278 } 2279 2280 /* 2281 * Get owner, group and permissions in an stat structure 2282 * returns permissions, or -1 if there is a problem 2283 */ 2284 2285 int ntfs_get_owner_mode(struct SECURITY_CONTEXT *scx, 2286 ntfs_inode * ni, struct stat *stbuf) 2287 { 2288 const SECURITY_DESCRIPTOR_RELATIVE *phead; 2289 char *securattr; 2290 const SID *usid; /* owner of file/directory */ 2291 const SID *gsid; /* group of file/directory */ 2292 const struct CACHED_PERMISSIONS *cached; 2293 int perm; 2294 BOOL isdir; 2295 #if POSIXACLS 2296 struct POSIX_SECURITY *pxdesc; 2297 #endif 2298 2299 if (!scx->mapping[MAPUSERS]) 2300 perm = 07777; 2301 else { 2302 /* check whether available in cache */ 2303 cached = fetch_cache(scx,ni); 2304 if (cached) { 2305 perm = cached->mode; 2306 stbuf->st_uid = cached->uid; 2307 stbuf->st_gid = cached->gid; 2308 stbuf->st_mode = (stbuf->st_mode & ~07777) + perm; 2309 } else { 2310 perm = -1; /* default to error */ 2311 isdir = (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY) 2312 != const_cpu_to_le16(0); 2313 securattr = getsecurityattr(scx->vol, ni); 2314 if (securattr) { 2315 phead = 2316 (const SECURITY_DESCRIPTOR_RELATIVE*) 2317 securattr; 2318 gsid = (const SID*)& 2319 securattr[le32_to_cpu(phead->group)]; 2320 #if OWNERFROMACL 2321 usid = ntfs_acl_owner(securattr); 2322 #else 2323 usid = (const SID*)& 2324 securattr[le32_to_cpu(phead->owner)]; 2325 #endif 2326 #if POSIXACLS 2327 pxdesc = ntfs_build_permissions_posix(scx->mapping, securattr, 2328 usid, gsid, isdir); 2329 if (pxdesc) 2330 perm = pxdesc->mode & 07777; 2331 else 2332 perm = -1; 2333 #else 2334 perm = ntfs_build_permissions(securattr, 2335 usid, gsid, isdir); 2336 #endif 2337 /* 2338 * fetch owner and group for cacheing 2339 */ 2340 if (perm >= 0) { 2341 /* 2342 * Create a security id if there were none 2343 * and upgrade option is selected 2344 */ 2345 if (!test_nino_flag(ni, v3_Extensions) 2346 && (scx->vol->secure_flags 2347 & (1 << SECURITY_ADDSECURIDS))) { 2348 upgrade_secur_desc(scx->vol, 2349 securattr, ni); 2350 } 2351 #if OWNERFROMACL 2352 stbuf->st_uid = ntfs_find_user(scx->mapping[MAPUSERS],usid); 2353 #else 2354 if (!perm && ntfs_same_sid(usid, adminsid)) { 2355 stbuf->st_uid = 2356 find_tenant(scx, 2357 securattr); 2358 if (stbuf->st_uid) 2359 perm = 0700; 2360 } else 2361 stbuf->st_uid = ntfs_find_user(scx->mapping[MAPUSERS],usid); 2362 #endif 2363 stbuf->st_gid = ntfs_find_group(scx->mapping[MAPGROUPS],gsid); 2364 stbuf->st_mode = 2365 (stbuf->st_mode & ~07777) + perm; 2366 #if POSIXACLS 2367 enter_cache(scx, ni, stbuf->st_uid, 2368 stbuf->st_gid, pxdesc); 2369 free(pxdesc); 2370 #else 2371 enter_cache(scx, ni, stbuf->st_uid, 2372 stbuf->st_gid, perm); 2373 #endif 2374 } 2375 free(securattr); 2376 } 2377 } 2378 } 2379 return (perm); 2380 } 2381 2382 #if POSIXACLS 2383 2384 /* 2385 * Get the base for a Posix inheritance and 2386 * build an inherited Posix descriptor 2387 */ 2388 2389 static struct POSIX_SECURITY *inherit_posix(struct SECURITY_CONTEXT *scx, 2390 ntfs_inode *dir_ni, mode_t mode, BOOL isdir) 2391 { 2392 const struct CACHED_PERMISSIONS *cached; 2393 const SECURITY_DESCRIPTOR_RELATIVE *phead; 2394 struct POSIX_SECURITY *pxdesc; 2395 struct POSIX_SECURITY *pydesc; 2396 char *securattr; 2397 const SID *usid; 2398 const SID *gsid; 2399 uid_t uid; 2400 gid_t gid; 2401 2402 pydesc = (struct POSIX_SECURITY*)NULL; 2403 /* check whether parent directory is available in cache */ 2404 cached = fetch_cache(scx,dir_ni); 2405 if (cached) { 2406 uid = cached->uid; 2407 gid = cached->gid; 2408 pxdesc = cached->pxdesc; 2409 if (pxdesc) { 2410 pydesc = ntfs_build_inherited_posix(pxdesc,mode, 2411 scx->umask,isdir); 2412 } 2413 } else { 2414 securattr = getsecurityattr(scx->vol, dir_ni); 2415 if (securattr) { 2416 phead = (const SECURITY_DESCRIPTOR_RELATIVE*) 2417 securattr; 2418 gsid = (const SID*)& 2419 securattr[le32_to_cpu(phead->group)]; 2420 gid = ntfs_find_group(scx->mapping[MAPGROUPS],gsid); 2421 #if OWNERFROMACL 2422 usid = ntfs_acl_owner(securattr); 2423 pxdesc = ntfs_build_permissions_posix(scx->mapping,securattr, 2424 usid, gsid, TRUE); 2425 uid = ntfs_find_user(scx->mapping[MAPUSERS],usid); 2426 #else 2427 usid = (const SID*)& 2428 securattr[le32_to_cpu(phead->owner)]; 2429 pxdesc = ntfs_build_permissions_posix(scx->mapping,securattr, 2430 usid, gsid, TRUE); 2431 if (pxdesc && ntfs_same_sid(usid, adminsid)) { 2432 uid = find_tenant(scx, securattr); 2433 } else 2434 uid = ntfs_find_user(scx->mapping[MAPUSERS],usid); 2435 #endif 2436 if (pxdesc) { 2437 /* 2438 * Create a security id if there were none 2439 * and upgrade option is selected 2440 */ 2441 if (!test_nino_flag(dir_ni, v3_Extensions) 2442 && (scx->vol->secure_flags 2443 & (1 << SECURITY_ADDSECURIDS))) { 2444 upgrade_secur_desc(scx->vol, 2445 securattr, dir_ni); 2446 /* 2447 * fetch owner and group for cacheing 2448 * if there is a securid 2449 */ 2450 } 2451 if (test_nino_flag(dir_ni, v3_Extensions)) { 2452 enter_cache(scx, dir_ni, uid, 2453 gid, pxdesc); 2454 } 2455 pydesc = ntfs_build_inherited_posix(pxdesc, 2456 mode, scx->umask, isdir); 2457 free(pxdesc); 2458 } 2459 free(securattr); 2460 } 2461 } 2462 return (pydesc); 2463 } 2464 2465 /* 2466 * Allocate a security_id for a file being created 2467 * 2468 * Returns zero if not possible (NTFS v3.x required) 2469 */ 2470 2471 le32 ntfs_alloc_securid(struct SECURITY_CONTEXT *scx, 2472 uid_t uid, gid_t gid, ntfs_inode *dir_ni, 2473 mode_t mode, BOOL isdir) 2474 { 2475 #if !FORCE_FORMAT_v1x 2476 const struct CACHED_SECURID *cached; 2477 struct CACHED_SECURID wanted; 2478 struct POSIX_SECURITY *pxdesc; 2479 char *newattr; 2480 int newattrsz; 2481 const SID *usid; 2482 const SID *gsid; 2483 BIGSID defusid; 2484 BIGSID defgsid; 2485 le32 securid; 2486 #endif 2487 2488 securid = const_cpu_to_le32(0); 2489 2490 #if !FORCE_FORMAT_v1x 2491 2492 pxdesc = inherit_posix(scx, dir_ni, mode, isdir); 2493 if (pxdesc) { 2494 /* check whether target securid is known in cache */ 2495 2496 wanted.uid = uid; 2497 wanted.gid = gid; 2498 wanted.dmode = pxdesc->mode & mode & 07777; 2499 if (isdir) wanted.dmode |= 0x10000; 2500 wanted.variable = (void*)pxdesc; 2501 wanted.varsize = sizeof(struct POSIX_SECURITY) 2502 + (pxdesc->acccnt + pxdesc->defcnt)*sizeof(struct POSIX_ACE); 2503 cached = (const struct CACHED_SECURID*)ntfs_fetch_cache( 2504 scx->vol->securid_cache, GENERIC(&wanted), 2505 (cache_compare)compare); 2506 /* quite simple, if we are lucky */ 2507 if (cached) 2508 securid = cached->securid; 2509 2510 /* not in cache : make sure we can create ids */ 2511 2512 if (!cached && (scx->vol->major_ver >= 3)) { 2513 usid = ntfs_find_usid(scx->mapping[MAPUSERS],uid,(SID*)&defusid); 2514 gsid = ntfs_find_gsid(scx->mapping[MAPGROUPS],gid,(SID*)&defgsid); 2515 if (!usid || !gsid) { 2516 ntfs_log_error("File created by an unmapped user/group %d/%d\n", 2517 (int)uid, (int)gid); 2518 usid = gsid = adminsid; 2519 } 2520 newattr = ntfs_build_descr_posix(scx->mapping, pxdesc, 2521 isdir, usid, gsid); 2522 if (newattr) { 2523 newattrsz = ntfs_attr_size(newattr); 2524 securid = setsecurityattr(scx->vol, 2525 (const SECURITY_DESCRIPTOR_RELATIVE*)newattr, 2526 newattrsz); 2527 if (securid) { 2528 /* update cache, for subsequent use */ 2529 wanted.securid = securid; 2530 ntfs_enter_cache(scx->vol->securid_cache, 2531 GENERIC(&wanted), 2532 (cache_compare)compare); 2533 } 2534 free(newattr); 2535 } else { 2536 /* 2537 * could not build new security attribute 2538 * errno set by ntfs_build_descr() 2539 */ 2540 } 2541 } 2542 free(pxdesc); 2543 } 2544 #endif 2545 return (securid); 2546 } 2547 2548 /* 2549 * Apply Posix inheritance to a newly created file 2550 * (for NTFS 1.x only : no securid) 2551 */ 2552 2553 int ntfs_set_inherited_posix(struct SECURITY_CONTEXT *scx, 2554 ntfs_inode *ni, uid_t uid, gid_t gid, 2555 ntfs_inode *dir_ni, mode_t mode) 2556 { 2557 struct POSIX_SECURITY *pxdesc; 2558 char *newattr; 2559 const SID *usid; 2560 const SID *gsid; 2561 BIGSID defusid; 2562 BIGSID defgsid; 2563 BOOL isdir; 2564 int res; 2565 2566 res = -1; 2567 isdir = (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY) != const_cpu_to_le16(0); 2568 pxdesc = inherit_posix(scx, dir_ni, mode, isdir); 2569 if (pxdesc) { 2570 usid = ntfs_find_usid(scx->mapping[MAPUSERS],uid,(SID*)&defusid); 2571 gsid = ntfs_find_gsid(scx->mapping[MAPGROUPS],gid,(SID*)&defgsid); 2572 if (!usid || !gsid) { 2573 ntfs_log_error("File created by an unmapped user/group %d/%d\n", 2574 (int)uid, (int)gid); 2575 usid = gsid = adminsid; 2576 } 2577 newattr = ntfs_build_descr_posix(scx->mapping, pxdesc, 2578 isdir, usid, gsid); 2579 if (newattr) { 2580 /* Adjust Windows read-only flag */ 2581 res = update_secur_descr(scx->vol, newattr, ni); 2582 if (!res && !isdir) { 2583 if (mode & S_IWUSR) 2584 ni->flags &= ~FILE_ATTR_READONLY; 2585 else 2586 ni->flags |= FILE_ATTR_READONLY; 2587 } 2588 #if CACHE_LEGACY_SIZE 2589 /* also invalidate legacy cache */ 2590 if (isdir && !ni->security_id) { 2591 struct CACHED_PERMISSIONS_LEGACY legacy; 2592 2593 legacy.mft_no = ni->mft_no; 2594 legacy.variable = pxdesc; 2595 legacy.varsize = sizeof(struct POSIX_SECURITY) 2596 + (pxdesc->acccnt + pxdesc->defcnt)*sizeof(struct POSIX_ACE); 2597 ntfs_invalidate_cache(scx->vol->legacy_cache, 2598 GENERIC(&legacy), 2599 (cache_compare)leg_compare,0); 2600 } 2601 #endif 2602 free(newattr); 2603 2604 } else { 2605 /* 2606 * could not build new security attribute 2607 * errno set by ntfs_build_descr() 2608 */ 2609 } 2610 } 2611 return (res); 2612 } 2613 2614 #else 2615 2616 le32 ntfs_alloc_securid(struct SECURITY_CONTEXT *scx, 2617 uid_t uid, gid_t gid, mode_t mode, BOOL isdir) 2618 { 2619 #if !FORCE_FORMAT_v1x 2620 const struct CACHED_SECURID *cached; 2621 struct CACHED_SECURID wanted; 2622 char *newattr; 2623 int newattrsz; 2624 const SID *usid; 2625 const SID *gsid; 2626 BIGSID defusid; 2627 BIGSID defgsid; 2628 le32 securid; 2629 #endif 2630 2631 securid = const_cpu_to_le32(0); 2632 2633 #if !FORCE_FORMAT_v1x 2634 /* check whether target securid is known in cache */ 2635 2636 wanted.uid = uid; 2637 wanted.gid = gid; 2638 wanted.dmode = mode & 07777; 2639 if (isdir) wanted.dmode |= 0x10000; 2640 wanted.variable = (void*)NULL; 2641 wanted.varsize = 0; 2642 cached = (const struct CACHED_SECURID*)ntfs_fetch_cache( 2643 scx->vol->securid_cache, GENERIC(&wanted), 2644 (cache_compare)compare); 2645 /* quite simple, if we are lucky */ 2646 if (cached) 2647 securid = cached->securid; 2648 2649 /* not in cache : make sure we can create ids */ 2650 2651 if (!cached && (scx->vol->major_ver >= 3)) { 2652 usid = ntfs_find_usid(scx->mapping[MAPUSERS],uid,(SID*)&defusid); 2653 gsid = ntfs_find_gsid(scx->mapping[MAPGROUPS],gid,(SID*)&defgsid); 2654 if (!usid || !gsid) { 2655 ntfs_log_error("File created by an unmapped user/group %d/%d\n", 2656 (int)uid, (int)gid); 2657 usid = gsid = adminsid; 2658 } 2659 newattr = ntfs_build_descr(mode, isdir, usid, gsid); 2660 if (newattr) { 2661 newattrsz = ntfs_attr_size(newattr); 2662 securid = setsecurityattr(scx->vol, 2663 (const SECURITY_DESCRIPTOR_RELATIVE*)newattr, 2664 newattrsz); 2665 if (securid) { 2666 /* update cache, for subsequent use */ 2667 wanted.securid = securid; 2668 ntfs_enter_cache(scx->vol->securid_cache, 2669 GENERIC(&wanted), 2670 (cache_compare)compare); 2671 } 2672 free(newattr); 2673 } else { 2674 /* 2675 * could not build new security attribute 2676 * errno set by ntfs_build_descr() 2677 */ 2678 } 2679 } 2680 #endif 2681 return (securid); 2682 } 2683 2684 #endif 2685 2686 /* 2687 * Update ownership and mode of a file, reusing an existing 2688 * security descriptor when possible 2689 * 2690 * Returns zero if successful 2691 */ 2692 2693 #if POSIXACLS 2694 int ntfs_set_owner_mode(struct SECURITY_CONTEXT *scx, ntfs_inode *ni, 2695 uid_t uid, gid_t gid, mode_t mode, 2696 struct POSIX_SECURITY *pxdesc) 2697 #else 2698 int ntfs_set_owner_mode(struct SECURITY_CONTEXT *scx, ntfs_inode *ni, 2699 uid_t uid, gid_t gid, mode_t mode) 2700 #endif 2701 { 2702 int res; 2703 const struct CACHED_SECURID *cached; 2704 struct CACHED_SECURID wanted; 2705 char *newattr; 2706 const SID *usid; 2707 const SID *gsid; 2708 BIGSID defusid; 2709 BIGSID defgsid; 2710 BOOL isdir; 2711 2712 res = 0; 2713 2714 /* check whether target securid is known in cache */ 2715 2716 isdir = (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY) != const_cpu_to_le16(0); 2717 wanted.uid = uid; 2718 wanted.gid = gid; 2719 wanted.dmode = mode & 07777; 2720 if (isdir) wanted.dmode |= 0x10000; 2721 #if POSIXACLS 2722 wanted.variable = (void*)pxdesc; 2723 if (pxdesc) 2724 wanted.varsize = sizeof(struct POSIX_SECURITY) 2725 + (pxdesc->acccnt + pxdesc->defcnt)*sizeof(struct POSIX_ACE); 2726 else 2727 wanted.varsize = 0; 2728 #else 2729 wanted.variable = (void*)NULL; 2730 wanted.varsize = 0; 2731 #endif 2732 if (test_nino_flag(ni, v3_Extensions)) { 2733 cached = (const struct CACHED_SECURID*)ntfs_fetch_cache( 2734 scx->vol->securid_cache, GENERIC(&wanted), 2735 (cache_compare)compare); 2736 /* quite simple, if we are lucky */ 2737 if (cached) { 2738 ni->security_id = cached->securid; 2739 NInoSetDirty(ni); 2740 } 2741 } else cached = (struct CACHED_SECURID*)NULL; 2742 2743 if (!cached) { 2744 /* 2745 * Do not use usid and gsid from former attributes, 2746 * but recompute them to get repeatable results 2747 * which can be kept in cache. 2748 */ 2749 usid = ntfs_find_usid(scx->mapping[MAPUSERS],uid,(SID*)&defusid); 2750 gsid = ntfs_find_gsid(scx->mapping[MAPGROUPS],gid,(SID*)&defgsid); 2751 if (!usid || !gsid) { 2752 ntfs_log_error("File made owned by an unmapped user/group %d/%d\n", 2753 uid, gid); 2754 usid = gsid = adminsid; 2755 } 2756 #if POSIXACLS 2757 if (pxdesc) 2758 newattr = ntfs_build_descr_posix(scx->mapping, pxdesc, 2759 isdir, usid, gsid); 2760 else 2761 newattr = ntfs_build_descr(mode, 2762 isdir, usid, gsid); 2763 #else 2764 newattr = ntfs_build_descr(mode, 2765 isdir, usid, gsid); 2766 #endif 2767 if (newattr) { 2768 res = update_secur_descr(scx->vol, newattr, ni); 2769 if (!res) { 2770 /* adjust Windows read-only flag */ 2771 if (!isdir) { 2772 if (mode & S_IWUSR) 2773 ni->flags &= ~FILE_ATTR_READONLY; 2774 else 2775 ni->flags |= FILE_ATTR_READONLY; 2776 NInoFileNameSetDirty(ni); 2777 } 2778 /* update cache, for subsequent use */ 2779 if (test_nino_flag(ni, v3_Extensions)) { 2780 wanted.securid = ni->security_id; 2781 ntfs_enter_cache(scx->vol->securid_cache, 2782 GENERIC(&wanted), 2783 (cache_compare)compare); 2784 } 2785 #if CACHE_LEGACY_SIZE 2786 /* also invalidate legacy cache */ 2787 if (isdir && !ni->security_id) { 2788 struct CACHED_PERMISSIONS_LEGACY legacy; 2789 2790 legacy.mft_no = ni->mft_no; 2791 #if POSIXACLS 2792 legacy.variable = wanted.variable; 2793 legacy.varsize = wanted.varsize; 2794 #else 2795 legacy.variable = (void*)NULL; 2796 legacy.varsize = 0; 2797 #endif 2798 ntfs_invalidate_cache(scx->vol->legacy_cache, 2799 GENERIC(&legacy), 2800 (cache_compare)leg_compare,0); 2801 } 2802 #endif 2803 } 2804 free(newattr); 2805 } else { 2806 /* 2807 * could not build new security attribute 2808 * errno set by ntfs_build_descr() 2809 */ 2810 res = -1; 2811 } 2812 } 2813 return (res); 2814 } 2815 2816 /* 2817 * Check whether user has ownership rights on a file 2818 * 2819 * Returns TRUE if allowed 2820 * if not, errno tells why 2821 */ 2822 2823 BOOL ntfs_allowed_as_owner(struct SECURITY_CONTEXT *scx, ntfs_inode *ni) 2824 { 2825 const struct CACHED_PERMISSIONS *cached; 2826 char *oldattr; 2827 const SID *usid; 2828 uid_t processuid; 2829 uid_t uid; 2830 BOOL gotowner; 2831 int allowed; 2832 2833 processuid = scx->uid; 2834 /* TODO : use CAP_FOWNER process capability */ 2835 /* 2836 * Always allow for root 2837 * Also always allow if no mapping has been defined 2838 */ 2839 if (!scx->mapping[MAPUSERS] || !processuid) 2840 allowed = TRUE; 2841 else { 2842 gotowner = FALSE; /* default */ 2843 /* get the owner, either from cache or from old attribute */ 2844 cached = fetch_cache(scx, ni); 2845 if (cached) { 2846 uid = cached->uid; 2847 gotowner = TRUE; 2848 } else { 2849 oldattr = getsecurityattr(scx->vol, ni); 2850 if (oldattr) { 2851 #if OWNERFROMACL 2852 usid = ntfs_acl_owner(oldattr); 2853 #else 2854 const SECURITY_DESCRIPTOR_RELATIVE *phead; 2855 2856 phead = (const SECURITY_DESCRIPTOR_RELATIVE*) 2857 oldattr; 2858 usid = (const SID*)&oldattr 2859 [le32_to_cpu(phead->owner)]; 2860 #endif 2861 uid = ntfs_find_user(scx->mapping[MAPUSERS], 2862 usid); 2863 gotowner = TRUE; 2864 free(oldattr); 2865 } 2866 } 2867 allowed = FALSE; 2868 if (gotowner) { 2869 /* TODO : use CAP_FOWNER process capability */ 2870 if (!processuid || (processuid == uid)) 2871 allowed = TRUE; 2872 else 2873 errno = EPERM; 2874 } 2875 } 2876 return (allowed); 2877 } 2878 2879 #ifdef HAVE_SETXATTR /* extended attributes interface required */ 2880 2881 #if POSIXACLS 2882 2883 /* 2884 * Set a new access or default Posix ACL to a file 2885 * (or remove ACL if no input data) 2886 * Validity of input data is checked after merging 2887 * 2888 * Returns 0, or -1 if there is a problem which errno describes 2889 */ 2890 2891 int ntfs_set_posix_acl(struct SECURITY_CONTEXT *scx, ntfs_inode *ni, 2892 const char *name, const char *value, size_t size, 2893 int flags) 2894 { 2895 const SECURITY_DESCRIPTOR_RELATIVE *phead; 2896 const struct CACHED_PERMISSIONS *cached; 2897 char *oldattr; 2898 uid_t processuid; 2899 const SID *usid; 2900 const SID *gsid; 2901 uid_t uid; 2902 uid_t gid; 2903 int res; 2904 BOOL isdir; 2905 BOOL deflt; 2906 BOOL exist; 2907 int count; 2908 struct POSIX_SECURITY *oldpxdesc; 2909 struct POSIX_SECURITY *newpxdesc; 2910 2911 /* get the current pxsec, either from cache or from old attribute */ 2912 res = -1; 2913 deflt = !strcmp(name,"system.posix_acl_default"); 2914 if (size) 2915 count = (size - sizeof(struct POSIX_ACL)) / sizeof(struct POSIX_ACE); 2916 else 2917 count = 0; 2918 isdir = (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY) != const_cpu_to_le16(0); 2919 newpxdesc = (struct POSIX_SECURITY*)NULL; 2920 if ((!value 2921 || (((const struct POSIX_ACL*)value)->version == POSIX_VERSION)) 2922 && (!deflt || isdir || (!size && !value))) { 2923 cached = fetch_cache(scx, ni); 2924 if (cached) { 2925 uid = cached->uid; 2926 gid = cached->gid; 2927 oldpxdesc = cached->pxdesc; 2928 if (oldpxdesc) { 2929 newpxdesc = ntfs_replace_acl(oldpxdesc, 2930 (const struct POSIX_ACL*)value,count,deflt); 2931 } 2932 } else { 2933 oldattr = getsecurityattr(scx->vol, ni); 2934 if (oldattr) { 2935 phead = (const SECURITY_DESCRIPTOR_RELATIVE*)oldattr; 2936 #if OWNERFROMACL 2937 usid = ntfs_acl_owner(oldattr); 2938 #else 2939 usid = (const SID*)&oldattr[le32_to_cpu(phead->owner)]; 2940 #endif 2941 gsid = (const SID*)&oldattr[le32_to_cpu(phead->group)]; 2942 uid = ntfs_find_user(scx->mapping[MAPUSERS],usid); 2943 gid = ntfs_find_group(scx->mapping[MAPGROUPS],gsid); 2944 oldpxdesc = ntfs_build_permissions_posix(scx->mapping, 2945 oldattr, usid, gsid, isdir); 2946 if (oldpxdesc) { 2947 if (deflt) 2948 exist = oldpxdesc->defcnt > 0; 2949 else 2950 exist = oldpxdesc->acccnt > 3; 2951 if ((exist && (flags & XATTR_CREATE)) 2952 || (!exist && (flags & XATTR_REPLACE))) { 2953 errno = (exist ? EEXIST : ENODATA); 2954 } else { 2955 newpxdesc = ntfs_replace_acl(oldpxdesc, 2956 (const struct POSIX_ACL*)value,count,deflt); 2957 } 2958 free(oldpxdesc); 2959 } 2960 free(oldattr); 2961 } 2962 } 2963 } else 2964 errno = EINVAL; 2965 2966 if (newpxdesc) { 2967 processuid = scx->uid; 2968 /* TODO : use CAP_FOWNER process capability */ 2969 if (!processuid || (uid == processuid)) { 2970 /* 2971 * clear setgid if file group does 2972 * not match process group 2973 */ 2974 if (processuid && (gid != scx->gid) 2975 && !groupmember(scx, scx->uid, gid)) { 2976 newpxdesc->mode &= ~S_ISGID; 2977 } 2978 res = ntfs_set_owner_mode(scx, ni, uid, gid, 2979 newpxdesc->mode, newpxdesc); 2980 } else 2981 errno = EPERM; 2982 free(newpxdesc); 2983 } 2984 return (res ? -1 : 0); 2985 } 2986 2987 /* 2988 * Remove a default Posix ACL from a file 2989 * 2990 * Returns 0, or -1 if there is a problem which errno describes 2991 */ 2992 2993 int ntfs_remove_posix_acl(struct SECURITY_CONTEXT *scx, ntfs_inode *ni, 2994 const char *name) 2995 { 2996 return (ntfs_set_posix_acl(scx, ni, name, 2997 (const char*)NULL, 0, 0)); 2998 } 2999 3000 #endif 3001 3002 /* 3003 * Set a new NTFS ACL to a file 3004 * 3005 * Returns 0, or -1 if there is a problem 3006 */ 3007 3008 int ntfs_set_ntfs_acl(struct SECURITY_CONTEXT *scx, ntfs_inode *ni, 3009 const char *value, size_t size, int flags) 3010 { 3011 char *attr; 3012 int res; 3013 3014 res = -1; 3015 if ((size > 0) 3016 && !(flags & XATTR_CREATE) 3017 && ntfs_valid_descr(value,size) 3018 && (ntfs_attr_size(value) == size)) { 3019 /* need copying in order to write */ 3020 attr = (char*)ntfs_malloc(size); 3021 if (attr) { 3022 memcpy(attr,value,size); 3023 res = update_secur_descr(scx->vol, attr, ni); 3024 /* 3025 * No need to invalidate standard caches : 3026 * the relation between a securid and 3027 * the associated protection is unchanged, 3028 * only the relation between a file and 3029 * its securid and protection is changed. 3030 */ 3031 #if CACHE_LEGACY_SIZE 3032 /* 3033 * we must however invalidate the legacy 3034 * cache, which is based on inode numbers. 3035 * For safety, invalidate even if updating 3036 * failed. 3037 */ 3038 if ((ni->mrec->flags & MFT_RECORD_IS_DIRECTORY) 3039 && !ni->security_id) { 3040 struct CACHED_PERMISSIONS_LEGACY legacy; 3041 3042 legacy.mft_no = ni->mft_no; 3043 legacy.variable = (char*)NULL; 3044 legacy.varsize = 0; 3045 ntfs_invalidate_cache(scx->vol->legacy_cache, 3046 GENERIC(&legacy), 3047 (cache_compare)leg_compare,0); 3048 } 3049 #endif 3050 free(attr); 3051 } else 3052 errno = ENOMEM; 3053 } else 3054 errno = EINVAL; 3055 return (res ? -1 : 0); 3056 } 3057 3058 #endif /* HAVE_SETXATTR */ 3059 3060 /* 3061 * Set new permissions to a file 3062 * Checks user mapping has been defined before request for setting 3063 * 3064 * rejected if request is not originated by owner or root 3065 * 3066 * returns 0 on success 3067 * -1 on failure, with errno = EIO 3068 */ 3069 3070 int ntfs_set_mode(struct SECURITY_CONTEXT *scx, ntfs_inode *ni, mode_t mode) 3071 { 3072 const SECURITY_DESCRIPTOR_RELATIVE *phead; 3073 const struct CACHED_PERMISSIONS *cached; 3074 char *oldattr; 3075 const SID *usid; 3076 const SID *gsid; 3077 uid_t processuid; 3078 uid_t uid; 3079 uid_t gid; 3080 int res; 3081 #if POSIXACLS 3082 BOOL isdir; 3083 int pxsize; 3084 const struct POSIX_SECURITY *oldpxdesc; 3085 struct POSIX_SECURITY *newpxdesc = (struct POSIX_SECURITY*)NULL; 3086 #endif 3087 3088 /* get the current owner, either from cache or from old attribute */ 3089 res = 0; 3090 cached = fetch_cache(scx, ni); 3091 if (cached) { 3092 uid = cached->uid; 3093 gid = cached->gid; 3094 #if POSIXACLS 3095 oldpxdesc = cached->pxdesc; 3096 if (oldpxdesc) { 3097 /* must copy before merging */ 3098 pxsize = sizeof(struct POSIX_SECURITY) 3099 + (oldpxdesc->acccnt + oldpxdesc->defcnt)*sizeof(struct POSIX_ACE); 3100 newpxdesc = (struct POSIX_SECURITY*)malloc(pxsize); 3101 if (newpxdesc) { 3102 memcpy(newpxdesc, oldpxdesc, pxsize); 3103 if (ntfs_merge_mode_posix(newpxdesc, mode)) 3104 res = -1; 3105 } else 3106 res = -1; 3107 } else 3108 newpxdesc = (struct POSIX_SECURITY*)NULL; 3109 #endif 3110 } else { 3111 oldattr = getsecurityattr(scx->vol, ni); 3112 if (oldattr) { 3113 phead = (const SECURITY_DESCRIPTOR_RELATIVE*)oldattr; 3114 #if OWNERFROMACL 3115 usid = ntfs_acl_owner(oldattr); 3116 #else 3117 usid = (const SID*)&oldattr[le32_to_cpu(phead->owner)]; 3118 #endif 3119 gsid = (const SID*)&oldattr[le32_to_cpu(phead->group)]; 3120 uid = ntfs_find_user(scx->mapping[MAPUSERS],usid); 3121 gid = ntfs_find_group(scx->mapping[MAPGROUPS],gsid); 3122 #if POSIXACLS 3123 isdir = (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY) != const_cpu_to_le16(0); 3124 newpxdesc = ntfs_build_permissions_posix(scx->mapping, 3125 oldattr, usid, gsid, isdir); 3126 if (!newpxdesc || ntfs_merge_mode_posix(newpxdesc, mode)) 3127 res = -1; 3128 #endif 3129 free(oldattr); 3130 } else 3131 res = -1; 3132 } 3133 3134 if (!res) { 3135 processuid = scx->uid; 3136 /* TODO : use CAP_FOWNER process capability */ 3137 if (!processuid || (uid == processuid)) { 3138 /* 3139 * clear setgid if file group does 3140 * not match process group 3141 */ 3142 if (processuid && (gid != scx->gid) 3143 && !groupmember(scx, scx->uid, gid)) 3144 mode &= ~S_ISGID; 3145 #if POSIXACLS 3146 if (newpxdesc) { 3147 newpxdesc->mode = mode; 3148 res = ntfs_set_owner_mode(scx, ni, uid, gid, 3149 mode, newpxdesc); 3150 } else 3151 res = ntfs_set_owner_mode(scx, ni, uid, gid, 3152 mode, newpxdesc); 3153 #else 3154 res = ntfs_set_owner_mode(scx, ni, uid, gid, mode); 3155 #endif 3156 } else { 3157 errno = EPERM; 3158 res = -1; /* neither owner nor root */ 3159 } 3160 } else { 3161 /* 3162 * Should not happen : a default descriptor is generated 3163 * by getsecurityattr() when there are none 3164 */ 3165 ntfs_log_error("File has no security descriptor\n"); 3166 res = -1; 3167 errno = EIO; 3168 } 3169 #if POSIXACLS 3170 if (newpxdesc) free(newpxdesc); 3171 #endif 3172 return (res ? -1 : 0); 3173 } 3174 3175 /* 3176 * Create a default security descriptor for files whose descriptor 3177 * cannot be inherited 3178 */ 3179 3180 int ntfs_sd_add_everyone(ntfs_inode *ni) 3181 { 3182 /* JPA SECURITY_DESCRIPTOR_ATTR *sd; */ 3183 SECURITY_DESCRIPTOR_RELATIVE *sd; 3184 ACL *acl; 3185 ACCESS_ALLOWED_ACE *ace; 3186 SID *sid; 3187 int ret, sd_len; 3188 3189 /* Create SECURITY_DESCRIPTOR attribute (everyone has full access). */ 3190 /* 3191 * Calculate security descriptor length. We have 2 sub-authorities in 3192 * owner and group SIDs, but structure SID contain only one, so add 3193 * 4 bytes to every SID. 3194 */ 3195 sd_len = sizeof(SECURITY_DESCRIPTOR_ATTR) + 2 * (sizeof(SID) + 4) + 3196 sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE); 3197 sd = (SECURITY_DESCRIPTOR_RELATIVE*)ntfs_calloc(sd_len); 3198 if (!sd) 3199 return -1; 3200 3201 sd->revision = SECURITY_DESCRIPTOR_REVISION; 3202 sd->control = SE_DACL_PRESENT | SE_SELF_RELATIVE; 3203 3204 sid = (SID*)((u8*)sd + sizeof(SECURITY_DESCRIPTOR_ATTR)); 3205 sid->revision = SID_REVISION; 3206 sid->sub_authority_count = 2; 3207 sid->sub_authority[0] = const_cpu_to_le32(SECURITY_BUILTIN_DOMAIN_RID); 3208 sid->sub_authority[1] = const_cpu_to_le32(DOMAIN_ALIAS_RID_ADMINS); 3209 sid->identifier_authority.value[5] = 5; 3210 sd->owner = cpu_to_le32((u8*)sid - (u8*)sd); 3211 3212 sid = (SID*)((u8*)sid + sizeof(SID) + 4); 3213 sid->revision = SID_REVISION; 3214 sid->sub_authority_count = 2; 3215 sid->sub_authority[0] = const_cpu_to_le32(SECURITY_BUILTIN_DOMAIN_RID); 3216 sid->sub_authority[1] = const_cpu_to_le32(DOMAIN_ALIAS_RID_ADMINS); 3217 sid->identifier_authority.value[5] = 5; 3218 sd->group = cpu_to_le32((u8*)sid - (u8*)sd); 3219 3220 acl = (ACL*)((u8*)sid + sizeof(SID) + 4); 3221 acl->revision = ACL_REVISION; 3222 acl->size = const_cpu_to_le16(sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE)); 3223 acl->ace_count = const_cpu_to_le16(1); 3224 sd->dacl = cpu_to_le32((u8*)acl - (u8*)sd); 3225 3226 ace = (ACCESS_ALLOWED_ACE*)((u8*)acl + sizeof(ACL)); 3227 ace->type = ACCESS_ALLOWED_ACE_TYPE; 3228 ace->flags = OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE; 3229 ace->size = const_cpu_to_le16(sizeof(ACCESS_ALLOWED_ACE)); 3230 ace->mask = const_cpu_to_le32(0x1f01ff); /* FIXME */ 3231 ace->sid.revision = SID_REVISION; 3232 ace->sid.sub_authority_count = 1; 3233 ace->sid.sub_authority[0] = const_cpu_to_le32(0); 3234 ace->sid.identifier_authority.value[5] = 1; 3235 3236 ret = ntfs_attr_add(ni, AT_SECURITY_DESCRIPTOR, AT_UNNAMED, 0, (u8*)sd, 3237 sd_len); 3238 if (ret) 3239 ntfs_log_perror("Failed to add initial SECURITY_DESCRIPTOR"); 3240 3241 free(sd); 3242 return ret; 3243 } 3244 3245 /* 3246 * Check whether user can access a file in a specific way 3247 * 3248 * Returns 1 if access is allowed, including user is root or no 3249 * user mapping defined 3250 * 2 if sticky and accesstype is S_IWRITE + S_IEXEC + S_ISVTX 3251 * 0 and sets errno if there is a problem or if access 3252 * is not allowed 3253 * 3254 * This is used for Posix ACL and checking creation of DOS file names 3255 */ 3256 3257 int ntfs_allowed_access(struct SECURITY_CONTEXT *scx, 3258 ntfs_inode *ni, 3259 int accesstype) /* access type required (S_Ixxx values) */ 3260 { 3261 int perm; 3262 int res; 3263 int allow; 3264 struct stat stbuf; 3265 3266 /* 3267 * Always allow for root unless execution is requested. 3268 * (was checked by fuse until kernel 2.6.29) 3269 * Also always allow if no mapping has been defined 3270 */ 3271 if (!scx->mapping[MAPUSERS] 3272 || (!scx->uid 3273 && (!(accesstype & S_IEXEC) 3274 || (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY)))) 3275 allow = 1; 3276 else { 3277 perm = ntfs_get_perm(scx, ni, accesstype); 3278 if (perm >= 0) { 3279 res = EACCES; 3280 switch (accesstype) { 3281 case S_IEXEC: 3282 allow = (perm & (S_IXUSR | S_IXGRP | S_IXOTH)) != 0; 3283 break; 3284 case S_IWRITE: 3285 allow = (perm & (S_IWUSR | S_IWGRP | S_IWOTH)) != 0; 3286 break; 3287 case S_IWRITE + S_IEXEC: 3288 allow = ((perm & (S_IWUSR | S_IWGRP | S_IWOTH)) != 0) 3289 && ((perm & (S_IXUSR | S_IXGRP | S_IXOTH)) != 0); 3290 break; 3291 case S_IREAD: 3292 allow = (perm & (S_IRUSR | S_IRGRP | S_IROTH)) != 0; 3293 break; 3294 case S_IREAD + S_IEXEC: 3295 allow = ((perm & (S_IRUSR | S_IRGRP | S_IROTH)) != 0) 3296 && ((perm & (S_IXUSR | S_IXGRP | S_IXOTH)) != 0); 3297 break; 3298 case S_IREAD + S_IWRITE: 3299 allow = ((perm & (S_IRUSR | S_IRGRP | S_IROTH)) != 0) 3300 && ((perm & (S_IWUSR | S_IWGRP | S_IWOTH)) != 0); 3301 break; 3302 case S_IWRITE + S_IEXEC + S_ISVTX: 3303 if (perm & S_ISVTX) { 3304 if ((ntfs_get_owner_mode(scx,ni,&stbuf) >= 0) 3305 && (stbuf.st_uid == scx->uid)) 3306 allow = 1; 3307 else 3308 allow = 2; 3309 } else 3310 allow = ((perm & (S_IWUSR | S_IWGRP | S_IWOTH)) != 0) 3311 && ((perm & (S_IXUSR | S_IXGRP | S_IXOTH)) != 0); 3312 break; 3313 case S_IREAD + S_IWRITE + S_IEXEC: 3314 allow = ((perm & (S_IRUSR | S_IRGRP | S_IROTH)) != 0) 3315 && ((perm & (S_IWUSR | S_IWGRP | S_IWOTH)) != 0) 3316 && ((perm & (S_IXUSR | S_IXGRP | S_IXOTH)) != 0); 3317 break; 3318 default : 3319 res = EINVAL; 3320 allow = 0; 3321 break; 3322 } 3323 if (!allow) 3324 errno = res; 3325 } else 3326 allow = 0; 3327 } 3328 return (allow); 3329 } 3330 3331 #if 0 /* not needed any more */ 3332 3333 /* 3334 * Check whether user can access the parent directory 3335 * of a file in a specific way 3336 * 3337 * Returns true if access is allowed, including user is root and 3338 * no user mapping defined 3339 * 3340 * Sets errno if there is a problem or if not allowed 3341 * 3342 * This is used for Posix ACL and checking creation of DOS file names 3343 */ 3344 3345 BOOL old_ntfs_allowed_dir_access(struct SECURITY_CONTEXT *scx, 3346 const char *path, int accesstype) 3347 { 3348 int allow; 3349 char *dirpath; 3350 char *name; 3351 ntfs_inode *ni; 3352 ntfs_inode *dir_ni; 3353 struct stat stbuf; 3354 3355 allow = 0; 3356 dirpath = strdup(path); 3357 if (dirpath) { 3358 /* the root of file system is seen as a parent of itself */ 3359 /* is that correct ? */ 3360 name = strrchr(dirpath, '/'); 3361 *name = 0; 3362 dir_ni = ntfs_pathname_to_inode(scx->vol, NULL, dirpath); 3363 if (dir_ni) { 3364 allow = ntfs_allowed_access(scx, 3365 dir_ni, accesstype); 3366 ntfs_inode_close(dir_ni); 3367 /* 3368 * for an not-owned sticky directory, have to 3369 * check whether file itself is owned 3370 */ 3371 if ((accesstype == (S_IWRITE + S_IEXEC + S_ISVTX)) 3372 && (allow == 2)) { 3373 ni = ntfs_pathname_to_inode(scx->vol, NULL, 3374 path); 3375 allow = FALSE; 3376 if (ni) { 3377 allow = (ntfs_get_owner_mode(scx,ni,&stbuf) >= 0) 3378 && (stbuf.st_uid == scx->uid); 3379 ntfs_inode_close(ni); 3380 } 3381 } 3382 } 3383 free(dirpath); 3384 } 3385 return (allow); /* errno is set if not allowed */ 3386 } 3387 3388 #endif 3389 3390 /* 3391 * Define a new owner/group to a file 3392 * 3393 * returns zero if successful 3394 */ 3395 3396 int ntfs_set_owner(struct SECURITY_CONTEXT *scx, ntfs_inode *ni, 3397 uid_t uid, gid_t gid) 3398 { 3399 const SECURITY_DESCRIPTOR_RELATIVE *phead; 3400 const struct CACHED_PERMISSIONS *cached; 3401 char *oldattr; 3402 const SID *usid; 3403 const SID *gsid; 3404 uid_t fileuid; 3405 uid_t filegid; 3406 mode_t mode; 3407 int perm; 3408 BOOL isdir; 3409 int res; 3410 #if POSIXACLS 3411 struct POSIX_SECURITY *pxdesc; 3412 BOOL pxdescbuilt = FALSE; 3413 #endif 3414 3415 res = 0; 3416 /* get the current owner and mode from cache or security attributes */ 3417 oldattr = (char*)NULL; 3418 cached = fetch_cache(scx,ni); 3419 if (cached) { 3420 fileuid = cached->uid; 3421 filegid = cached->gid; 3422 mode = cached->mode; 3423 #if POSIXACLS 3424 pxdesc = cached->pxdesc; 3425 if (!pxdesc) 3426 res = -1; 3427 #endif 3428 } else { 3429 fileuid = 0; 3430 filegid = 0; 3431 mode = 0; 3432 oldattr = getsecurityattr(scx->vol, ni); 3433 if (oldattr) { 3434 isdir = (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY) 3435 != const_cpu_to_le16(0); 3436 phead = (const SECURITY_DESCRIPTOR_RELATIVE*) 3437 oldattr; 3438 gsid = (const SID*) 3439 &oldattr[le32_to_cpu(phead->group)]; 3440 #if OWNERFROMACL 3441 usid = ntfs_acl_owner(oldattr); 3442 #else 3443 usid = (const SID*) 3444 &oldattr[le32_to_cpu(phead->owner)]; 3445 #endif 3446 #if POSIXACLS 3447 pxdesc = ntfs_build_permissions_posix(scx->mapping, oldattr, 3448 usid, gsid, isdir); 3449 if (pxdesc) { 3450 pxdescbuilt = TRUE; 3451 fileuid = ntfs_find_user(scx->mapping[MAPUSERS],usid); 3452 filegid = ntfs_find_group(scx->mapping[MAPGROUPS],gsid); 3453 mode = perm = pxdesc->mode; 3454 } else 3455 res = -1; 3456 #else 3457 mode = perm = ntfs_build_permissions(oldattr, 3458 usid, gsid, isdir); 3459 if (perm >= 0) { 3460 fileuid = ntfs_find_user(scx->mapping[MAPUSERS],usid); 3461 filegid = ntfs_find_group(scx->mapping[MAPGROUPS],gsid); 3462 } else 3463 res = -1; 3464 #endif 3465 free(oldattr); 3466 } else 3467 res = -1; 3468 } 3469 if (!res) { 3470 /* check requested by root */ 3471 /* or chgrp requested by owner to an owned group */ 3472 if (!scx->uid 3473 || ((((int)uid < 0) || (uid == fileuid)) 3474 && ((gid == scx->gid) || groupmember(scx, scx->uid, gid)) 3475 && (fileuid == scx->uid))) { 3476 /* replace by the new usid and gsid */ 3477 /* or reuse old gid and sid for cacheing */ 3478 if ((int)uid < 0) 3479 uid = fileuid; 3480 if ((int)gid < 0) 3481 gid = filegid; 3482 /* clear setuid and setgid if owner has changed */ 3483 /* unless request originated by root */ 3484 if (uid && (fileuid != uid)) 3485 mode &= 01777; 3486 #if POSIXACLS 3487 res = ntfs_set_owner_mode(scx, ni, uid, gid, 3488 mode, pxdesc); 3489 #else 3490 res = ntfs_set_owner_mode(scx, ni, uid, gid, mode); 3491 #endif 3492 } else { 3493 res = -1; /* neither owner nor root */ 3494 errno = EPERM; 3495 } 3496 #if POSIXACLS 3497 if (pxdescbuilt) 3498 free(pxdesc); 3499 #endif 3500 } else { 3501 /* 3502 * Should not happen : a default descriptor is generated 3503 * by getsecurityattr() when there are none 3504 */ 3505 ntfs_log_error("File has no security descriptor\n"); 3506 res = -1; 3507 errno = EIO; 3508 } 3509 return (res ? -1 : 0); 3510 } 3511 3512 /* 3513 * Define new owner/group and mode to a file 3514 * 3515 * returns zero if successful 3516 */ 3517 3518 int ntfs_set_ownmod(struct SECURITY_CONTEXT *scx, ntfs_inode *ni, 3519 uid_t uid, gid_t gid, const mode_t mode) 3520 { 3521 const struct CACHED_PERMISSIONS *cached; 3522 char *oldattr; 3523 uid_t fileuid; 3524 uid_t filegid; 3525 int res; 3526 #if POSIXACLS 3527 const SECURITY_DESCRIPTOR_RELATIVE *phead; 3528 const SID *usid; 3529 const SID *gsid; 3530 BOOL isdir; 3531 const struct POSIX_SECURITY *oldpxdesc; 3532 struct POSIX_SECURITY *newpxdesc = (struct POSIX_SECURITY*)NULL; 3533 int pxsize; 3534 #endif 3535 3536 res = 0; 3537 /* get the current owner and mode from cache or security attributes */ 3538 oldattr = (char*)NULL; 3539 cached = fetch_cache(scx,ni); 3540 if (cached) { 3541 fileuid = cached->uid; 3542 filegid = cached->gid; 3543 #if POSIXACLS 3544 oldpxdesc = cached->pxdesc; 3545 if (oldpxdesc) { 3546 /* must copy before merging */ 3547 pxsize = sizeof(struct POSIX_SECURITY) 3548 + (oldpxdesc->acccnt + oldpxdesc->defcnt)*sizeof(struct POSIX_ACE); 3549 newpxdesc = (struct POSIX_SECURITY*)malloc(pxsize); 3550 if (newpxdesc) { 3551 memcpy(newpxdesc, oldpxdesc, pxsize); 3552 if (ntfs_merge_mode_posix(newpxdesc, mode)) 3553 res = -1; 3554 } else 3555 res = -1; 3556 } 3557 #endif 3558 } else { 3559 fileuid = 0; 3560 filegid = 0; 3561 oldattr = getsecurityattr(scx->vol, ni); 3562 if (oldattr) { 3563 #if POSIXACLS 3564 isdir = (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY) 3565 != const_cpu_to_le16(0); 3566 phead = (const SECURITY_DESCRIPTOR_RELATIVE*) 3567 oldattr; 3568 gsid = (const SID*) 3569 &oldattr[le32_to_cpu(phead->group)]; 3570 #if OWNERFROMACL 3571 usid = ntfs_acl_owner(oldattr); 3572 #else 3573 usid = (const SID*) 3574 &oldattr[le32_to_cpu(phead->owner)]; 3575 #endif 3576 newpxdesc = ntfs_build_permissions_posix(scx->mapping, oldattr, 3577 usid, gsid, isdir); 3578 if (!newpxdesc || ntfs_merge_mode_posix(newpxdesc, mode)) 3579 res = -1; 3580 else { 3581 fileuid = ntfs_find_user(scx->mapping[MAPUSERS],usid); 3582 filegid = ntfs_find_group(scx->mapping[MAPGROUPS],gsid); 3583 } 3584 #endif 3585 free(oldattr); 3586 } else 3587 res = -1; 3588 } 3589 if (!res) { 3590 /* check requested by root */ 3591 /* or chgrp requested by owner to an owned group */ 3592 if (!scx->uid 3593 || ((((int)uid < 0) || (uid == fileuid)) 3594 && ((gid == scx->gid) || groupmember(scx, scx->uid, gid)) 3595 && (fileuid == scx->uid))) { 3596 /* replace by the new usid and gsid */ 3597 /* or reuse old gid and sid for cacheing */ 3598 if ((int)uid < 0) 3599 uid = fileuid; 3600 if ((int)gid < 0) 3601 gid = filegid; 3602 #if POSIXACLS 3603 res = ntfs_set_owner_mode(scx, ni, uid, gid, 3604 mode, newpxdesc); 3605 #else 3606 res = ntfs_set_owner_mode(scx, ni, uid, gid, mode); 3607 #endif 3608 } else { 3609 res = -1; /* neither owner nor root */ 3610 errno = EPERM; 3611 } 3612 } else { 3613 /* 3614 * Should not happen : a default descriptor is generated 3615 * by getsecurityattr() when there are none 3616 */ 3617 ntfs_log_error("File has no security descriptor\n"); 3618 res = -1; 3619 errno = EIO; 3620 } 3621 #if POSIXACLS 3622 free(newpxdesc); 3623 #endif 3624 return (res ? -1 : 0); 3625 } 3626 3627 /* 3628 * Build a security id for a descriptor inherited from 3629 * parent directory the Windows way 3630 */ 3631 3632 static le32 build_inherited_id(struct SECURITY_CONTEXT *scx, 3633 const char *parentattr, BOOL fordir) 3634 { 3635 const SECURITY_DESCRIPTOR_RELATIVE *pphead; 3636 const ACL *ppacl; 3637 const SID *usid; 3638 const SID *gsid; 3639 BIGSID defusid; 3640 BIGSID defgsid; 3641 int offpacl; 3642 int offowner; 3643 int offgroup; 3644 SECURITY_DESCRIPTOR_RELATIVE *pnhead; 3645 ACL *pnacl; 3646 int parentattrsz; 3647 char *newattr; 3648 int newattrsz; 3649 int aclsz; 3650 int usidsz; 3651 int gsidsz; 3652 int pos; 3653 le32 securid; 3654 3655 parentattrsz = ntfs_attr_size(parentattr); 3656 pphead = (const SECURITY_DESCRIPTOR_RELATIVE*)parentattr; 3657 if (scx->mapping[MAPUSERS]) { 3658 usid = ntfs_find_usid(scx->mapping[MAPUSERS], scx->uid, (SID*)&defusid); 3659 gsid = ntfs_find_gsid(scx->mapping[MAPGROUPS], scx->gid, (SID*)&defgsid); 3660 if (!usid) 3661 usid = adminsid; 3662 if (!gsid) 3663 gsid = adminsid; 3664 } else { 3665 /* 3666 * If there is no user mapping, we have to copy owner 3667 * and group from parent directory. 3668 * Windows never has to do that, because it can always 3669 * rely on a user mapping 3670 */ 3671 offowner = le32_to_cpu(pphead->owner); 3672 usid = (const SID*)&parentattr[offowner]; 3673 offgroup = le32_to_cpu(pphead->group); 3674 gsid = (const SID*)&parentattr[offgroup]; 3675 } 3676 /* 3677 * new attribute is smaller than parent's 3678 * except for differences in SIDs which appear in 3679 * owner, group and possible grants and denials in 3680 * generic creator-owner and creator-group ACEs. 3681 * For directories, an ACE may be duplicated for 3682 * access and inheritance, so we double the count. 3683 */ 3684 usidsz = ntfs_sid_size(usid); 3685 gsidsz = ntfs_sid_size(gsid); 3686 newattrsz = parentattrsz + 3*usidsz + 3*gsidsz; 3687 if (fordir) 3688 newattrsz *= 2; 3689 newattr = (char*)ntfs_malloc(newattrsz); 3690 if (newattr) { 3691 pnhead = (SECURITY_DESCRIPTOR_RELATIVE*)newattr; 3692 pnhead->revision = SECURITY_DESCRIPTOR_REVISION; 3693 pnhead->alignment = 0; 3694 pnhead->control = SE_SELF_RELATIVE; 3695 pos = sizeof(SECURITY_DESCRIPTOR_RELATIVE); 3696 /* 3697 * locate and inherit DACL 3698 * do not test SE_DACL_PRESENT (wrong for "DR Watson") 3699 */ 3700 pnhead->dacl = const_cpu_to_le32(0); 3701 if (pphead->dacl) { 3702 offpacl = le32_to_cpu(pphead->dacl); 3703 ppacl = (const ACL*)&parentattr[offpacl]; 3704 pnacl = (ACL*)&newattr[pos]; 3705 aclsz = ntfs_inherit_acl(ppacl, pnacl, usid, gsid, fordir); 3706 if (aclsz) { 3707 pnhead->dacl = cpu_to_le32(pos); 3708 pos += aclsz; 3709 pnhead->control |= SE_DACL_PRESENT; 3710 } 3711 } 3712 /* 3713 * locate and inherit SACL 3714 */ 3715 pnhead->sacl = const_cpu_to_le32(0); 3716 if (pphead->sacl) { 3717 offpacl = le32_to_cpu(pphead->sacl); 3718 ppacl = (const ACL*)&parentattr[offpacl]; 3719 pnacl = (ACL*)&newattr[pos]; 3720 aclsz = ntfs_inherit_acl(ppacl, pnacl, usid, gsid, fordir); 3721 if (aclsz) { 3722 pnhead->sacl = cpu_to_le32(pos); 3723 pos += aclsz; 3724 pnhead->control |= SE_SACL_PRESENT; 3725 } 3726 } 3727 /* 3728 * inherit or redefine owner 3729 */ 3730 memcpy(&newattr[pos],usid,usidsz); 3731 pnhead->owner = cpu_to_le32(pos); 3732 pos += usidsz; 3733 /* 3734 * inherit or redefine group 3735 */ 3736 memcpy(&newattr[pos],gsid,gsidsz); 3737 pnhead->group = cpu_to_le32(pos); 3738 pos += usidsz; 3739 securid = setsecurityattr(scx->vol, 3740 (SECURITY_DESCRIPTOR_RELATIVE*)newattr, pos); 3741 free(newattr); 3742 } else 3743 securid = const_cpu_to_le32(0); 3744 return (securid); 3745 } 3746 3747 /* 3748 * Get an inherited security id 3749 * 3750 * For Windows compatibility, the normal initial permission setting 3751 * may be inherited from the parent directory instead of being 3752 * defined by the creation arguments. 3753 * 3754 * The following creates an inherited id for that purpose. 3755 * 3756 * Note : the owner and group of parent directory are also 3757 * inherited (which is not the case on Windows) if no user mapping 3758 * is defined. 3759 * 3760 * Returns the inherited id, or zero if not possible (eg on NTFS 1.x) 3761 */ 3762 3763 le32 ntfs_inherited_id(struct SECURITY_CONTEXT *scx, 3764 ntfs_inode *dir_ni, BOOL fordir) 3765 { 3766 struct CACHED_PERMISSIONS *cached; 3767 char *parentattr; 3768 le32 securid; 3769 3770 securid = const_cpu_to_le32(0); 3771 cached = (struct CACHED_PERMISSIONS*)NULL; 3772 /* 3773 * Try to get inherited id from cache 3774 */ 3775 if (test_nino_flag(dir_ni, v3_Extensions) 3776 && dir_ni->security_id) { 3777 cached = fetch_cache(scx, dir_ni); 3778 if (cached) 3779 securid = (fordir ? cached->inh_dirid 3780 : cached->inh_fileid); 3781 } 3782 /* 3783 * Not cached or not available in cache, compute it all 3784 * Note : if parent directory has no id, it is not cacheable 3785 */ 3786 if (!securid) { 3787 parentattr = getsecurityattr(scx->vol, dir_ni); 3788 if (parentattr) { 3789 securid = build_inherited_id(scx, 3790 parentattr, fordir); 3791 free(parentattr); 3792 /* 3793 * Store the result into cache for further use 3794 */ 3795 if (securid) { 3796 cached = fetch_cache(scx, dir_ni); 3797 if (cached) { 3798 if (fordir) 3799 cached->inh_dirid = securid; 3800 else 3801 cached->inh_fileid = securid; 3802 } 3803 } 3804 } 3805 } 3806 return (securid); 3807 } 3808 3809 /* 3810 * Link a group to a member of group 3811 * 3812 * Returns 0 if OK, -1 (and errno set) if error 3813 */ 3814 3815 static int link_single_group(struct MAPPING *usermapping, struct passwd *user, 3816 gid_t gid) 3817 { 3818 struct group *group; 3819 char **grmem; 3820 int grcnt; 3821 gid_t *groups; 3822 int res; 3823 3824 res = 0; 3825 group = getgrgid(gid); 3826 if (group && group->gr_mem) { 3827 grcnt = usermapping->grcnt; 3828 groups = usermapping->groups; 3829 grmem = group->gr_mem; 3830 while (*grmem && strcmp(user->pw_name, *grmem)) 3831 grmem++; 3832 if (*grmem) { 3833 if (!grcnt) 3834 groups = (gid_t*)malloc(sizeof(gid_t)); 3835 else 3836 groups = (gid_t*)realloc(groups, 3837 (grcnt+1)*sizeof(gid_t)); 3838 if (groups) 3839 groups[grcnt++] = gid; 3840 else { 3841 res = -1; 3842 errno = ENOMEM; 3843 } 3844 } 3845 usermapping->grcnt = grcnt; 3846 usermapping->groups = groups; 3847 } 3848 return (res); 3849 } 3850 3851 3852 /* 3853 * Statically link group to users 3854 * This is based on groups defined in /etc/group and does not take 3855 * the groups dynamically set by setgroups() nor any changes in 3856 * /etc/group into account 3857 * 3858 * Only mapped groups and root group are linked to mapped users 3859 * 3860 * Returns 0 if OK, -1 (and errno set) if error 3861 * 3862 */ 3863 3864 static int link_group_members(struct SECURITY_CONTEXT *scx) 3865 { 3866 struct MAPPING *usermapping; 3867 struct MAPPING *groupmapping; 3868 struct passwd *user; 3869 int res; 3870 3871 res = 0; 3872 for (usermapping=scx->mapping[MAPUSERS]; usermapping && !res; 3873 usermapping=usermapping->next) { 3874 usermapping->grcnt = 0; 3875 usermapping->groups = (gid_t*)NULL; 3876 user = getpwuid(usermapping->xid); 3877 if (user && user->pw_name) { 3878 for (groupmapping=scx->mapping[MAPGROUPS]; 3879 groupmapping && !res; 3880 groupmapping=groupmapping->next) { 3881 if (link_single_group(usermapping, user, 3882 groupmapping->xid)) 3883 res = -1; 3884 } 3885 if (!res && link_single_group(usermapping, 3886 user, (gid_t)0)) 3887 res = -1; 3888 } 3889 } 3890 return (res); 3891 } 3892 3893 /* 3894 * Apply default single user mapping 3895 * returns zero if successful 3896 */ 3897 3898 static int ntfs_do_default_mapping(struct SECURITY_CONTEXT *scx, 3899 uid_t uid, gid_t gid, const SID *usid) 3900 { 3901 struct MAPPING *usermapping; 3902 struct MAPPING *groupmapping; 3903 SID *sid; 3904 int sidsz; 3905 int res; 3906 3907 res = -1; 3908 sidsz = ntfs_sid_size(usid); 3909 sid = (SID*)ntfs_malloc(sidsz); 3910 if (sid) { 3911 memcpy(sid,usid,sidsz); 3912 usermapping = (struct MAPPING*)ntfs_malloc(sizeof(struct MAPPING)); 3913 if (usermapping) { 3914 groupmapping = (struct MAPPING*)ntfs_malloc(sizeof(struct MAPPING)); 3915 if (groupmapping) { 3916 usermapping->sid = sid; 3917 usermapping->xid = uid; 3918 usermapping->next = (struct MAPPING*)NULL; 3919 groupmapping->sid = sid; 3920 groupmapping->xid = gid; 3921 groupmapping->next = (struct MAPPING*)NULL; 3922 scx->mapping[MAPUSERS] = usermapping; 3923 scx->mapping[MAPGROUPS] = groupmapping; 3924 res = 0; 3925 } 3926 } 3927 } 3928 return (res); 3929 } 3930 3931 /* 3932 * Make sure there are no ambiguous mapping 3933 * Ambiguous mapping may lead to undesired configurations and 3934 * we had rather be safe until the consequences are understood 3935 */ 3936 3937 #if 0 /* not activated for now */ 3938 3939 static BOOL check_mapping(const struct MAPPING *usermapping, 3940 const struct MAPPING *groupmapping) 3941 { 3942 const struct MAPPING *mapping1; 3943 const struct MAPPING *mapping2; 3944 BOOL ambiguous; 3945 3946 ambiguous = FALSE; 3947 for (mapping1=usermapping; mapping1; mapping1=mapping1->next) 3948 for (mapping2=mapping1->next; mapping2; mapping1=mapping2->next) 3949 if (ntfs_same_sid(mapping1->sid,mapping2->sid)) { 3950 if (mapping1->xid != mapping2->xid) 3951 ambiguous = TRUE; 3952 } else { 3953 if (mapping1->xid == mapping2->xid) 3954 ambiguous = TRUE; 3955 } 3956 for (mapping1=groupmapping; mapping1; mapping1=mapping1->next) 3957 for (mapping2=mapping1->next; mapping2; mapping1=mapping2->next) 3958 if (ntfs_same_sid(mapping1->sid,mapping2->sid)) { 3959 if (mapping1->xid != mapping2->xid) 3960 ambiguous = TRUE; 3961 } else { 3962 if (mapping1->xid == mapping2->xid) 3963 ambiguous = TRUE; 3964 } 3965 return (ambiguous); 3966 } 3967 3968 #endif 3969 3970 #if 0 /* not used any more */ 3971 3972 /* 3973 * Try and apply default single user mapping 3974 * returns zero if successful 3975 */ 3976 3977 static int ntfs_default_mapping(struct SECURITY_CONTEXT *scx) 3978 { 3979 const SECURITY_DESCRIPTOR_RELATIVE *phead; 3980 ntfs_inode *ni; 3981 char *securattr; 3982 const SID *usid; 3983 int res; 3984 3985 res = -1; 3986 ni = ntfs_pathname_to_inode(scx->vol, NULL, "/."); 3987 if (ni) { 3988 securattr = getsecurityattr(scx->vol, ni); 3989 if (securattr) { 3990 phead = (const SECURITY_DESCRIPTOR_RELATIVE*)securattr; 3991 usid = (SID*)&securattr[le32_to_cpu(phead->owner)]; 3992 if (ntfs_is_user_sid(usid)) 3993 res = ntfs_do_default_mapping(scx, 3994 scx->uid, scx->gid, usid); 3995 free(securattr); 3996 } 3997 ntfs_inode_close(ni); 3998 } 3999 return (res); 4000 } 4001 4002 #endif 4003 4004 /* 4005 * Basic read from a user mapping file on another volume 4006 */ 4007 4008 static int basicread(void *fileid, char *buf, size_t size, off_t offs __attribute__((unused))) 4009 { 4010 return (read(*(int*)fileid, buf, size)); 4011 } 4012 4013 4014 /* 4015 * Read from a user mapping file on current NTFS partition 4016 */ 4017 4018 static int localread(void *fileid, char *buf, size_t size, off_t offs) 4019 { 4020 return (ntfs_attr_data_read((ntfs_inode*)fileid, 4021 AT_UNNAMED, 0, buf, size, offs)); 4022 } 4023 4024 /* 4025 * Build the user mapping 4026 * - according to a mapping file if defined (or default present), 4027 * - or try default single user mapping if possible 4028 * 4029 * The mapping is specific to a mounted device 4030 * No locking done, mounting assumed non multithreaded 4031 * 4032 * returns zero if mapping is successful 4033 * (failure should not be interpreted as an error) 4034 */ 4035 4036 int ntfs_build_mapping(struct SECURITY_CONTEXT *scx, const char *usermap_path, 4037 BOOL allowdef) 4038 { 4039 struct MAPLIST *item; 4040 struct MAPLIST *firstitem; 4041 struct MAPPING *usermapping; 4042 struct MAPPING *groupmapping; 4043 ntfs_inode *ni; 4044 int fd; 4045 static struct { 4046 u8 revision; 4047 u8 levels; 4048 be16 highbase; 4049 be32 lowbase; 4050 le32 level1; 4051 le32 level2; 4052 le32 level3; 4053 le32 level4; 4054 le32 level5; 4055 } defmap = { 4056 1, 5, const_cpu_to_be16(0), const_cpu_to_be32(5), 4057 const_cpu_to_le32(21), 4058 const_cpu_to_le32(DEFSECAUTH1), const_cpu_to_le32(DEFSECAUTH2), 4059 const_cpu_to_le32(DEFSECAUTH3), const_cpu_to_le32(DEFSECBASE) 4060 } ; 4061 4062 /* be sure not to map anything until done */ 4063 scx->mapping[MAPUSERS] = (struct MAPPING*)NULL; 4064 scx->mapping[MAPGROUPS] = (struct MAPPING*)NULL; 4065 4066 if (!usermap_path) usermap_path = MAPPINGFILE; 4067 if (usermap_path[0] == '/') { 4068 fd = open(usermap_path,O_RDONLY); 4069 if (fd > 0) { 4070 firstitem = ntfs_read_mapping(basicread, (void*)&fd); 4071 close(fd); 4072 } else 4073 firstitem = (struct MAPLIST*)NULL; 4074 } else { 4075 ni = ntfs_pathname_to_inode(scx->vol, NULL, usermap_path); 4076 if (ni) { 4077 firstitem = ntfs_read_mapping(localread, ni); 4078 ntfs_inode_close(ni); 4079 } else 4080 firstitem = (struct MAPLIST*)NULL; 4081 } 4082 4083 4084 if (firstitem) { 4085 usermapping = ntfs_do_user_mapping(firstitem); 4086 groupmapping = ntfs_do_group_mapping(firstitem); 4087 if (usermapping && groupmapping) { 4088 scx->mapping[MAPUSERS] = usermapping; 4089 scx->mapping[MAPGROUPS] = groupmapping; 4090 } else 4091 ntfs_log_error("There were no valid user or no valid group\n"); 4092 /* now we can free the memory copy of input text */ 4093 /* and rely on internal representation */ 4094 while (firstitem) { 4095 item = firstitem->next; 4096 free(firstitem); 4097 firstitem = item; 4098 } 4099 } else { 4100 /* no mapping file, try a default mapping */ 4101 if (allowdef) { 4102 if (!ntfs_do_default_mapping(scx, 4103 0, 0, (const SID*)&defmap)) 4104 ntfs_log_info("Using default user mapping\n"); 4105 } 4106 } 4107 return (!scx->mapping[MAPUSERS] || link_group_members(scx)); 4108 } 4109 4110 #ifdef HAVE_SETXATTR /* extended attributes interface required */ 4111 4112 /* 4113 * Get the ntfs attribute into an extended attribute 4114 * The attribute is returned according to cpu endianness 4115 */ 4116 4117 int ntfs_get_ntfs_attrib(ntfs_inode *ni, char *value, size_t size) 4118 { 4119 u32 attrib; 4120 size_t outsize; 4121 4122 outsize = 0; /* default to no data and no error */ 4123 if (ni) { 4124 attrib = le32_to_cpu(ni->flags); 4125 if (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY) 4126 attrib |= const_le32_to_cpu(FILE_ATTR_DIRECTORY); 4127 else 4128 attrib &= ~const_le32_to_cpu(FILE_ATTR_DIRECTORY); 4129 if (!attrib) 4130 attrib |= const_le32_to_cpu(FILE_ATTR_NORMAL); 4131 outsize = sizeof(FILE_ATTR_FLAGS); 4132 if (size >= outsize) { 4133 if (value) 4134 memcpy(value,&attrib,outsize); 4135 else 4136 errno = EINVAL; 4137 } 4138 } 4139 return (outsize ? (int)outsize : -errno); 4140 } 4141 4142 /* 4143 * Return the ntfs attribute into an extended attribute 4144 * The attribute is expected according to cpu endianness 4145 * 4146 * Returns 0, or -1 if there is a problem 4147 */ 4148 4149 int ntfs_set_ntfs_attrib(ntfs_inode *ni, 4150 const char *value, size_t size, int flags) 4151 { 4152 u32 attrib; 4153 le32 settable; 4154 ATTR_FLAGS dirflags; 4155 int res; 4156 4157 res = -1; 4158 if (ni && value && (size >= sizeof(FILE_ATTR_FLAGS))) { 4159 if (!(flags & XATTR_CREATE)) { 4160 /* copy to avoid alignment problems */ 4161 memcpy(&attrib,value,sizeof(FILE_ATTR_FLAGS)); 4162 settable = FILE_ATTR_SETTABLE; 4163 res = 0; 4164 if (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY) { 4165 /* 4166 * Accept changing compression for a directory 4167 * and set index root accordingly 4168 */ 4169 settable |= FILE_ATTR_COMPRESSED; 4170 if ((ni->flags ^ cpu_to_le32(attrib)) 4171 & FILE_ATTR_COMPRESSED) { 4172 if (ni->flags & FILE_ATTR_COMPRESSED) 4173 dirflags = const_cpu_to_le16(0); 4174 else 4175 dirflags = ATTR_IS_COMPRESSED; 4176 res = ntfs_attr_set_flags(ni, 4177 AT_INDEX_ROOT, 4178 NTFS_INDEX_I30, 4, 4179 dirflags, 4180 ATTR_COMPRESSION_MASK); 4181 } 4182 } 4183 if (!res) { 4184 ni->flags = (ni->flags & ~settable) 4185 | (cpu_to_le32(attrib) & settable); 4186 NInoFileNameSetDirty(ni); 4187 NInoSetDirty(ni); 4188 } 4189 } else 4190 errno = EEXIST; 4191 } else 4192 errno = EINVAL; 4193 return (res ? -1 : 0); 4194 } 4195 4196 #endif /* HAVE_SETXATTR */ 4197 4198 /* 4199 * Open $Secure once for all 4200 * returns zero if it succeeds 4201 * non-zero if it fails. This is not an error (on NTFS v1.x) 4202 */ 4203 4204 4205 int ntfs_open_secure(ntfs_volume *vol) 4206 { 4207 ntfs_inode *ni; 4208 int res; 4209 4210 res = -1; 4211 vol->secure_ni = (ntfs_inode*)NULL; 4212 vol->secure_xsii = (ntfs_index_context*)NULL; 4213 vol->secure_xsdh = (ntfs_index_context*)NULL; 4214 if (vol->major_ver >= 3) { 4215 /* make sure this is a genuine $Secure inode 9 */ 4216 ni = ntfs_pathname_to_inode(vol, NULL, "$Secure"); 4217 if (ni && (ni->mft_no == 9)) { 4218 vol->secure_reentry = 0; 4219 vol->secure_xsii = ntfs_index_ctx_get(ni, 4220 sii_stream, 4); 4221 vol->secure_xsdh = ntfs_index_ctx_get(ni, 4222 sdh_stream, 4); 4223 if (ni && vol->secure_xsii && vol->secure_xsdh) { 4224 vol->secure_ni = ni; 4225 res = 0; 4226 } 4227 } 4228 } 4229 return (res); 4230 } 4231 4232 /* 4233 * Final cleaning 4234 * Allocated memory is freed to facilitate the detection of memory leaks 4235 */ 4236 4237 void ntfs_close_secure(struct SECURITY_CONTEXT *scx) 4238 { 4239 ntfs_volume *vol; 4240 4241 vol = scx->vol; 4242 if (vol->secure_ni) { 4243 ntfs_index_ctx_put(vol->secure_xsii); 4244 ntfs_index_ctx_put(vol->secure_xsdh); 4245 ntfs_inode_close(vol->secure_ni); 4246 4247 } 4248 ntfs_free_mapping(scx->mapping); 4249 free_caches(scx); 4250 } 4251 4252 /* 4253 * API for direct access to security descriptors 4254 * based on Win32 API 4255 */ 4256 4257 4258 /* 4259 * Selective feeding of a security descriptor into user buffer 4260 * 4261 * Returns TRUE if successful 4262 */ 4263 4264 static BOOL feedsecurityattr(const char *attr, u32 selection, 4265 char *buf, u32 buflen, u32 *psize) 4266 { 4267 const SECURITY_DESCRIPTOR_RELATIVE *phead; 4268 SECURITY_DESCRIPTOR_RELATIVE *pnhead; 4269 const ACL *pdacl; 4270 const ACL *psacl; 4271 const SID *pusid; 4272 const SID *pgsid; 4273 unsigned int offdacl; 4274 unsigned int offsacl; 4275 unsigned int offowner; 4276 unsigned int offgroup; 4277 unsigned int daclsz; 4278 unsigned int saclsz; 4279 unsigned int usidsz; 4280 unsigned int gsidsz; 4281 unsigned int size; /* size of requested attributes */ 4282 BOOL ok; 4283 unsigned int pos; 4284 unsigned int avail; 4285 le16 control; 4286 4287 avail = 0; 4288 control = SE_SELF_RELATIVE; 4289 phead = (const SECURITY_DESCRIPTOR_RELATIVE*)attr; 4290 size = sizeof(SECURITY_DESCRIPTOR_RELATIVE); 4291 4292 /* locate DACL if requested and available */ 4293 if (phead->dacl && (selection & DACL_SECURITY_INFORMATION)) { 4294 offdacl = le32_to_cpu(phead->dacl); 4295 pdacl = (const ACL*)&attr[offdacl]; 4296 daclsz = le16_to_cpu(pdacl->size); 4297 size += daclsz; 4298 avail |= DACL_SECURITY_INFORMATION; 4299 } else 4300 offdacl = daclsz = 0; 4301 4302 /* locate owner if requested and available */ 4303 offowner = le32_to_cpu(phead->owner); 4304 if (offowner && (selection & OWNER_SECURITY_INFORMATION)) { 4305 /* find end of USID */ 4306 pusid = (const SID*)&attr[offowner]; 4307 usidsz = ntfs_sid_size(pusid); 4308 size += usidsz; 4309 avail |= OWNER_SECURITY_INFORMATION; 4310 } else 4311 offowner = usidsz = 0; 4312 4313 /* locate group if requested and available */ 4314 offgroup = le32_to_cpu(phead->group); 4315 if (offgroup && (selection & GROUP_SECURITY_INFORMATION)) { 4316 /* find end of GSID */ 4317 pgsid = (const SID*)&attr[offgroup]; 4318 gsidsz = ntfs_sid_size(pgsid); 4319 size += gsidsz; 4320 avail |= GROUP_SECURITY_INFORMATION; 4321 } else 4322 offgroup = gsidsz = 0; 4323 4324 /* locate SACL if requested and available */ 4325 if (phead->sacl && (selection & SACL_SECURITY_INFORMATION)) { 4326 /* find end of SACL */ 4327 offsacl = le32_to_cpu(phead->sacl); 4328 psacl = (const ACL*)&attr[offsacl]; 4329 saclsz = le16_to_cpu(psacl->size); 4330 size += saclsz; 4331 avail |= SACL_SECURITY_INFORMATION; 4332 } else 4333 offsacl = saclsz = 0; 4334 4335 /* 4336 * Check having enough size in destination buffer 4337 * (required size is returned nevertheless so that 4338 * the request can be reissued with adequate size) 4339 */ 4340 if (size > buflen) { 4341 *psize = size; 4342 errno = EINVAL; 4343 ok = FALSE; 4344 } else { 4345 if (selection & OWNER_SECURITY_INFORMATION) 4346 control |= phead->control & SE_OWNER_DEFAULTED; 4347 if (selection & GROUP_SECURITY_INFORMATION) 4348 control |= phead->control & SE_GROUP_DEFAULTED; 4349 if (selection & DACL_SECURITY_INFORMATION) 4350 control |= phead->control 4351 & (SE_DACL_PRESENT 4352 | SE_DACL_DEFAULTED 4353 | SE_DACL_AUTO_INHERITED 4354 | SE_DACL_PROTECTED); 4355 if (selection & SACL_SECURITY_INFORMATION) 4356 control |= phead->control 4357 & (SE_SACL_PRESENT 4358 | SE_SACL_DEFAULTED 4359 | SE_SACL_AUTO_INHERITED 4360 | SE_SACL_PROTECTED); 4361 /* 4362 * copy header and feed new flags, even if no detailed data 4363 */ 4364 memcpy(buf,attr,sizeof(SECURITY_DESCRIPTOR_RELATIVE)); 4365 pnhead = (SECURITY_DESCRIPTOR_RELATIVE*)buf; 4366 pnhead->control = control; 4367 pos = sizeof(SECURITY_DESCRIPTOR_RELATIVE); 4368 4369 /* copy DACL if requested and available */ 4370 if (selection & avail & DACL_SECURITY_INFORMATION) { 4371 pnhead->dacl = cpu_to_le32(pos); 4372 memcpy(&buf[pos],&attr[offdacl],daclsz); 4373 pos += daclsz; 4374 } else 4375 pnhead->dacl = const_cpu_to_le32(0); 4376 4377 /* copy SACL if requested and available */ 4378 if (selection & avail & SACL_SECURITY_INFORMATION) { 4379 pnhead->sacl = cpu_to_le32(pos); 4380 memcpy(&buf[pos],&attr[offsacl],saclsz); 4381 pos += saclsz; 4382 } else 4383 pnhead->sacl = const_cpu_to_le32(0); 4384 4385 /* copy owner if requested and available */ 4386 if (selection & avail & OWNER_SECURITY_INFORMATION) { 4387 pnhead->owner = cpu_to_le32(pos); 4388 memcpy(&buf[pos],&attr[offowner],usidsz); 4389 pos += usidsz; 4390 } else 4391 pnhead->owner = const_cpu_to_le32(0); 4392 4393 /* copy group if requested and available */ 4394 if (selection & avail & GROUP_SECURITY_INFORMATION) { 4395 pnhead->group = cpu_to_le32(pos); 4396 memcpy(&buf[pos],&attr[offgroup],gsidsz); 4397 pos += gsidsz; 4398 } else 4399 pnhead->group = const_cpu_to_le32(0); 4400 if (pos != size) 4401 ntfs_log_error("Error in security descriptor size\n"); 4402 *psize = size; 4403 ok = TRUE; 4404 } 4405 4406 return (ok); 4407 } 4408 4409 /* 4410 * Merge a new security descriptor into the old one 4411 * and assign to designated file 4412 * 4413 * Returns TRUE if successful 4414 */ 4415 4416 static BOOL mergesecurityattr(ntfs_volume *vol, const char *oldattr, 4417 const char *newattr, u32 selection, ntfs_inode *ni) 4418 { 4419 const SECURITY_DESCRIPTOR_RELATIVE *oldhead; 4420 const SECURITY_DESCRIPTOR_RELATIVE *newhead; 4421 SECURITY_DESCRIPTOR_RELATIVE *targhead; 4422 const ACL *pdacl; 4423 const ACL *psacl; 4424 const SID *powner; 4425 const SID *pgroup; 4426 int offdacl; 4427 int offsacl; 4428 int offowner; 4429 int offgroup; 4430 unsigned int size; 4431 le16 control; 4432 char *target; 4433 int pos; 4434 int oldattrsz; 4435 int newattrsz; 4436 BOOL ok; 4437 4438 ok = FALSE; /* default return */ 4439 oldhead = (const SECURITY_DESCRIPTOR_RELATIVE*)oldattr; 4440 newhead = (const SECURITY_DESCRIPTOR_RELATIVE*)newattr; 4441 oldattrsz = ntfs_attr_size(oldattr); 4442 newattrsz = ntfs_attr_size(newattr); 4443 target = (char*)ntfs_malloc(oldattrsz + newattrsz); 4444 if (target) { 4445 targhead = (SECURITY_DESCRIPTOR_RELATIVE*)target; 4446 pos = sizeof(SECURITY_DESCRIPTOR_RELATIVE); 4447 control = SE_SELF_RELATIVE; 4448 /* 4449 * copy new DACL if selected 4450 * or keep old DACL if any 4451 */ 4452 if ((selection & DACL_SECURITY_INFORMATION) ? 4453 newhead->dacl : oldhead->dacl) { 4454 if (selection & DACL_SECURITY_INFORMATION) { 4455 offdacl = le32_to_cpu(newhead->dacl); 4456 pdacl = (const ACL*)&newattr[offdacl]; 4457 } else { 4458 offdacl = le32_to_cpu(oldhead->dacl); 4459 pdacl = (const ACL*)&oldattr[offdacl]; 4460 } 4461 size = le16_to_cpu(pdacl->size); 4462 memcpy(&target[pos], pdacl, size); 4463 targhead->dacl = cpu_to_le32(pos); 4464 pos += size; 4465 } else 4466 targhead->dacl = const_cpu_to_le32(0); 4467 if (selection & DACL_SECURITY_INFORMATION) { 4468 control |= newhead->control 4469 & (SE_DACL_PRESENT 4470 | SE_DACL_DEFAULTED 4471 | SE_DACL_PROTECTED); 4472 if (newhead->control & SE_DACL_AUTO_INHERIT_REQ) 4473 control |= SE_DACL_AUTO_INHERITED; 4474 } else 4475 control |= oldhead->control 4476 & (SE_DACL_PRESENT 4477 | SE_DACL_DEFAULTED 4478 | SE_DACL_AUTO_INHERITED 4479 | SE_DACL_PROTECTED); 4480 /* 4481 * copy new SACL if selected 4482 * or keep old SACL if any 4483 */ 4484 if ((selection & SACL_SECURITY_INFORMATION) ? 4485 newhead->sacl : oldhead->sacl) { 4486 if (selection & SACL_SECURITY_INFORMATION) { 4487 offsacl = le32_to_cpu(newhead->sacl); 4488 psacl = (const ACL*)&newattr[offsacl]; 4489 } else { 4490 offsacl = le32_to_cpu(oldhead->sacl); 4491 psacl = (const ACL*)&oldattr[offsacl]; 4492 } 4493 size = le16_to_cpu(psacl->size); 4494 memcpy(&target[pos], psacl, size); 4495 targhead->sacl = cpu_to_le32(pos); 4496 pos += size; 4497 } else 4498 targhead->sacl = const_cpu_to_le32(0); 4499 if (selection & SACL_SECURITY_INFORMATION) { 4500 control |= newhead->control 4501 & (SE_SACL_PRESENT 4502 | SE_SACL_DEFAULTED 4503 | SE_SACL_PROTECTED); 4504 if (newhead->control & SE_SACL_AUTO_INHERIT_REQ) 4505 control |= SE_SACL_AUTO_INHERITED; 4506 } else 4507 control |= oldhead->control 4508 & (SE_SACL_PRESENT 4509 | SE_SACL_DEFAULTED 4510 | SE_SACL_AUTO_INHERITED 4511 | SE_SACL_PROTECTED); 4512 /* 4513 * copy new OWNER if selected 4514 * or keep old OWNER if any 4515 */ 4516 if ((selection & OWNER_SECURITY_INFORMATION) ? 4517 newhead->owner : oldhead->owner) { 4518 if (selection & OWNER_SECURITY_INFORMATION) { 4519 offowner = le32_to_cpu(newhead->owner); 4520 powner = (const SID*)&newattr[offowner]; 4521 } else { 4522 offowner = le32_to_cpu(oldhead->owner); 4523 powner = (const SID*)&oldattr[offowner]; 4524 } 4525 size = ntfs_sid_size(powner); 4526 memcpy(&target[pos], powner, size); 4527 targhead->owner = cpu_to_le32(pos); 4528 pos += size; 4529 } else 4530 targhead->owner = const_cpu_to_le32(0); 4531 if (selection & OWNER_SECURITY_INFORMATION) 4532 control |= newhead->control & SE_OWNER_DEFAULTED; 4533 else 4534 control |= oldhead->control & SE_OWNER_DEFAULTED; 4535 /* 4536 * copy new GROUP if selected 4537 * or keep old GROUP if any 4538 */ 4539 if ((selection & GROUP_SECURITY_INFORMATION) ? 4540 newhead->group : oldhead->group) { 4541 if (selection & GROUP_SECURITY_INFORMATION) { 4542 offgroup = le32_to_cpu(newhead->group); 4543 pgroup = (const SID*)&newattr[offgroup]; 4544 control |= newhead->control 4545 & SE_GROUP_DEFAULTED; 4546 } else { 4547 offgroup = le32_to_cpu(oldhead->group); 4548 pgroup = (const SID*)&oldattr[offgroup]; 4549 control |= oldhead->control 4550 & SE_GROUP_DEFAULTED; 4551 } 4552 size = ntfs_sid_size(pgroup); 4553 memcpy(&target[pos], pgroup, size); 4554 targhead->group = cpu_to_le32(pos); 4555 pos += size; 4556 } else 4557 targhead->group = const_cpu_to_le32(0); 4558 if (selection & GROUP_SECURITY_INFORMATION) 4559 control |= newhead->control & SE_GROUP_DEFAULTED; 4560 else 4561 control |= oldhead->control & SE_GROUP_DEFAULTED; 4562 targhead->revision = SECURITY_DESCRIPTOR_REVISION; 4563 targhead->alignment = 0; 4564 targhead->control = control; 4565 ok = !update_secur_descr(vol, target, ni); 4566 free(target); 4567 } 4568 return (ok); 4569 } 4570 4571 /* 4572 * Return the security descriptor of a file 4573 * This is intended to be similar to GetFileSecurity() from Win32 4574 * in order to facilitate the development of portable tools 4575 * 4576 * returns zero if unsuccessful (following Win32 conventions) 4577 * -1 if no securid 4578 * the securid if any 4579 * 4580 * The Win32 API is : 4581 * 4582 * BOOL WINAPI GetFileSecurity( 4583 * __in LPCTSTR lpFileName, 4584 * __in SECURITY_INFORMATION RequestedInformation, 4585 * __out_opt PSECURITY_DESCRIPTOR pSecurityDescriptor, 4586 * __in DWORD nLength, 4587 * __out LPDWORD lpnLengthNeeded 4588 * ); 4589 * 4590 */ 4591 4592 int ntfs_get_file_security(struct SECURITY_API *scapi, 4593 const char *path, u32 selection, 4594 char *buf, u32 buflen, u32 *psize) 4595 { 4596 ntfs_inode *ni; 4597 char *attr; 4598 int res; 4599 4600 res = 0; /* default return */ 4601 if (scapi && (scapi->magic == MAGIC_API)) { 4602 ni = ntfs_pathname_to_inode(scapi->security.vol, NULL, path); 4603 if (ni) { 4604 attr = getsecurityattr(scapi->security.vol, ni); 4605 if (attr) { 4606 if (feedsecurityattr(attr,selection, 4607 buf,buflen,psize)) { 4608 if (test_nino_flag(ni, v3_Extensions) 4609 && ni->security_id) 4610 res = le32_to_cpu( 4611 ni->security_id); 4612 else 4613 res = -1; 4614 } 4615 free(attr); 4616 } 4617 ntfs_inode_close(ni); 4618 } else 4619 errno = ENOENT; 4620 if (!res) *psize = 0; 4621 } else 4622 errno = EINVAL; /* do not clear *psize */ 4623 return (res); 4624 } 4625 4626 4627 /* 4628 * Set the security descriptor of a file or directory 4629 * This is intended to be similar to SetFileSecurity() from Win32 4630 * in order to facilitate the development of portable tools 4631 * 4632 * returns zero if unsuccessful (following Win32 conventions) 4633 * -1 if no securid 4634 * the securid if any 4635 * 4636 * The Win32 API is : 4637 * 4638 * BOOL WINAPI SetFileSecurity( 4639 * __in LPCTSTR lpFileName, 4640 * __in SECURITY_INFORMATION SecurityInformation, 4641 * __in PSECURITY_DESCRIPTOR pSecurityDescriptor 4642 * ); 4643 */ 4644 4645 int ntfs_set_file_security(struct SECURITY_API *scapi, 4646 const char *path, u32 selection, const char *attr) 4647 { 4648 const SECURITY_DESCRIPTOR_RELATIVE *phead; 4649 ntfs_inode *ni; 4650 int attrsz; 4651 BOOL missing; 4652 char *oldattr; 4653 int res; 4654 4655 res = 0; /* default return */ 4656 if (scapi && (scapi->magic == MAGIC_API) && attr) { 4657 phead = (const SECURITY_DESCRIPTOR_RELATIVE*)attr; 4658 attrsz = ntfs_attr_size(attr); 4659 /* if selected, owner and group must be present or defaulted */ 4660 missing = ((selection & OWNER_SECURITY_INFORMATION) 4661 && !phead->owner 4662 && !(phead->control & SE_OWNER_DEFAULTED)) 4663 || ((selection & GROUP_SECURITY_INFORMATION) 4664 && !phead->group 4665 && !(phead->control & SE_GROUP_DEFAULTED)); 4666 if (!missing 4667 && (phead->control & SE_SELF_RELATIVE) 4668 && ntfs_valid_descr(attr, attrsz)) { 4669 ni = ntfs_pathname_to_inode(scapi->security.vol, 4670 NULL, path); 4671 if (ni) { 4672 oldattr = getsecurityattr(scapi->security.vol, 4673 ni); 4674 if (oldattr) { 4675 if (mergesecurityattr( 4676 scapi->security.vol, 4677 oldattr, attr, 4678 selection, ni)) { 4679 if (test_nino_flag(ni, 4680 v3_Extensions)) 4681 res = le32_to_cpu( 4682 ni->security_id); 4683 else 4684 res = -1; 4685 } 4686 free(oldattr); 4687 } 4688 ntfs_inode_close(ni); 4689 } 4690 } else 4691 errno = EINVAL; 4692 } else 4693 errno = EINVAL; 4694 return (res); 4695 } 4696 4697 4698 /* 4699 * Return the attributes of a file 4700 * This is intended to be similar to GetFileAttributes() from Win32 4701 * in order to facilitate the development of portable tools 4702 * 4703 * returns -1 if unsuccessful (Win32 : INVALID_FILE_ATTRIBUTES) 4704 * 4705 * The Win32 API is : 4706 * 4707 * DWORD WINAPI GetFileAttributes( 4708 * __in LPCTSTR lpFileName 4709 * ); 4710 */ 4711 4712 int ntfs_get_file_attributes(struct SECURITY_API *scapi, const char *path) 4713 { 4714 ntfs_inode *ni; 4715 s32 attrib; 4716 4717 attrib = -1; /* default return */ 4718 if (scapi && (scapi->magic == MAGIC_API) && path) { 4719 ni = ntfs_pathname_to_inode(scapi->security.vol, NULL, path); 4720 if (ni) { 4721 attrib = le32_to_cpu(ni->flags); 4722 if (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY) 4723 attrib |= const_le32_to_cpu(FILE_ATTR_DIRECTORY); 4724 else 4725 attrib &= ~const_le32_to_cpu(FILE_ATTR_DIRECTORY); 4726 if (!attrib) 4727 attrib |= const_le32_to_cpu(FILE_ATTR_NORMAL); 4728 4729 ntfs_inode_close(ni); 4730 } else 4731 errno = ENOENT; 4732 } else 4733 errno = EINVAL; /* do not clear *psize */ 4734 return (attrib); 4735 } 4736 4737 4738 /* 4739 * Set attributes to a file or directory 4740 * This is intended to be similar to SetFileAttributes() from Win32 4741 * in order to facilitate the development of portable tools 4742 * 4743 * Only a few flags can be set (same list as Win32) 4744 * 4745 * returns zero if unsuccessful (following Win32 conventions) 4746 * nonzero if successful 4747 * 4748 * The Win32 API is : 4749 * 4750 * BOOL WINAPI SetFileAttributes( 4751 * __in LPCTSTR lpFileName, 4752 * __in DWORD dwFileAttributes 4753 * ); 4754 */ 4755 4756 BOOL ntfs_set_file_attributes(struct SECURITY_API *scapi, 4757 const char *path, s32 attrib) 4758 { 4759 ntfs_inode *ni; 4760 le32 settable; 4761 ATTR_FLAGS dirflags; 4762 int res; 4763 4764 res = 0; /* default return */ 4765 if (scapi && (scapi->magic == MAGIC_API) && path) { 4766 ni = ntfs_pathname_to_inode(scapi->security.vol, NULL, path); 4767 if (ni) { 4768 settable = FILE_ATTR_SETTABLE; 4769 if (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY) { 4770 /* 4771 * Accept changing compression for a directory 4772 * and set index root accordingly 4773 */ 4774 settable |= FILE_ATTR_COMPRESSED; 4775 if ((ni->flags ^ cpu_to_le32(attrib)) 4776 & FILE_ATTR_COMPRESSED) { 4777 if (ni->flags & FILE_ATTR_COMPRESSED) 4778 dirflags = const_cpu_to_le16(0); 4779 else 4780 dirflags = ATTR_IS_COMPRESSED; 4781 res = ntfs_attr_set_flags(ni, 4782 AT_INDEX_ROOT, 4783 NTFS_INDEX_I30, 4, 4784 dirflags, 4785 ATTR_COMPRESSION_MASK); 4786 } 4787 } 4788 if (!res) { 4789 ni->flags = (ni->flags & ~settable) 4790 | (cpu_to_le32(attrib) & settable); 4791 NInoSetDirty(ni); 4792 NInoFileNameSetDirty(ni); 4793 } 4794 if (!ntfs_inode_close(ni)) 4795 res = -1; 4796 } else 4797 errno = ENOENT; 4798 } 4799 return (res); 4800 } 4801 4802 4803 BOOL ntfs_read_directory(struct SECURITY_API *scapi, 4804 const char *path, ntfs_filldir_t callback, void *context) 4805 { 4806 ntfs_inode *ni; 4807 BOOL ok; 4808 s64 pos; 4809 4810 ok = FALSE; /* default return */ 4811 if (scapi && (scapi->magic == MAGIC_API) && callback) { 4812 ni = ntfs_pathname_to_inode(scapi->security.vol, NULL, path); 4813 if (ni) { 4814 if (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY) { 4815 pos = 0; 4816 ntfs_readdir(ni,&pos,context,callback); 4817 ok = !ntfs_inode_close(ni); 4818 } else { 4819 ntfs_inode_close(ni); 4820 errno = ENOTDIR; 4821 } 4822 } else 4823 errno = ENOENT; 4824 } else 4825 errno = EINVAL; /* do not clear *psize */ 4826 return (ok); 4827 } 4828 4829 /* 4830 * read $SDS (for auditing security data) 4831 * 4832 * Returns the number or read bytes, or -1 if there is an error 4833 */ 4834 4835 int ntfs_read_sds(struct SECURITY_API *scapi, 4836 char *buf, u32 size, u32 offset) 4837 { 4838 int got; 4839 4840 got = -1; /* default return */ 4841 if (scapi && (scapi->magic == MAGIC_API)) { 4842 if (scapi->security.vol->secure_ni) 4843 got = ntfs_attr_data_read(scapi->security.vol->secure_ni, 4844 STREAM_SDS, 4, buf, size, offset); 4845 else 4846 errno = EOPNOTSUPP; 4847 } else 4848 errno = EINVAL; 4849 return (got); 4850 } 4851 4852 /* 4853 * read $SII (for auditing security data) 4854 * 4855 * Returns next entry, or NULL if there is an error 4856 */ 4857 4858 INDEX_ENTRY *ntfs_read_sii(struct SECURITY_API *scapi, 4859 INDEX_ENTRY *entry) 4860 { 4861 SII_INDEX_KEY key; 4862 INDEX_ENTRY *ret; 4863 BOOL found; 4864 ntfs_index_context *xsii; 4865 4866 ret = (INDEX_ENTRY*)NULL; /* default return */ 4867 if (scapi && (scapi->magic == MAGIC_API)) { 4868 xsii = scapi->security.vol->secure_xsii; 4869 if (xsii) { 4870 if (!entry) { 4871 key.security_id = const_cpu_to_le32(0); 4872 found = !ntfs_index_lookup((char*)&key, 4873 sizeof(SII_INDEX_KEY), xsii); 4874 /* not supposed to find */ 4875 if (!found && (errno == ENOENT)) 4876 ret = xsii->entry; 4877 } else 4878 ret = ntfs_index_next(entry,xsii); 4879 if (!ret) 4880 errno = ENODATA; 4881 } else 4882 errno = EOPNOTSUPP; 4883 } else 4884 errno = EINVAL; 4885 return (ret); 4886 } 4887 4888 /* 4889 * read $SDH (for auditing security data) 4890 * 4891 * Returns next entry, or NULL if there is an error 4892 */ 4893 4894 INDEX_ENTRY *ntfs_read_sdh(struct SECURITY_API *scapi, 4895 INDEX_ENTRY *entry) 4896 { 4897 SDH_INDEX_KEY key; 4898 INDEX_ENTRY *ret; 4899 BOOL found; 4900 ntfs_index_context *xsdh; 4901 4902 ret = (INDEX_ENTRY*)NULL; /* default return */ 4903 if (scapi && (scapi->magic == MAGIC_API)) { 4904 xsdh = scapi->security.vol->secure_xsdh; 4905 if (xsdh) { 4906 if (!entry) { 4907 key.hash = const_cpu_to_le32(0); 4908 key.security_id = const_cpu_to_le32(0); 4909 found = !ntfs_index_lookup((char*)&key, 4910 sizeof(SDH_INDEX_KEY), xsdh); 4911 /* not supposed to find */ 4912 if (!found && (errno == ENOENT)) 4913 ret = xsdh->entry; 4914 } else 4915 ret = ntfs_index_next(entry,xsdh); 4916 if (!ret) 4917 errno = ENODATA; 4918 } else errno = ENOTSUP; 4919 } else 4920 errno = EINVAL; 4921 return (ret); 4922 } 4923 4924 /* 4925 * Get the mapped user SID 4926 * A buffer of 40 bytes has to be supplied 4927 * 4928 * returns the size of the SID, or zero and errno set if not found 4929 */ 4930 4931 int ntfs_get_usid(struct SECURITY_API *scapi, uid_t uid, char *buf) 4932 { 4933 const SID *usid; 4934 BIGSID defusid; 4935 int size; 4936 4937 size = 0; 4938 if (scapi && (scapi->magic == MAGIC_API)) { 4939 usid = ntfs_find_usid(scapi->security.mapping[MAPUSERS], uid, (SID*)&defusid); 4940 if (usid) { 4941 size = ntfs_sid_size(usid); 4942 memcpy(buf,usid,size); 4943 } else 4944 errno = ENODATA; 4945 } else 4946 errno = EINVAL; 4947 return (size); 4948 } 4949 4950 /* 4951 * Get the mapped group SID 4952 * A buffer of 40 bytes has to be supplied 4953 * 4954 * returns the size of the SID, or zero and errno set if not found 4955 */ 4956 4957 int ntfs_get_gsid(struct SECURITY_API *scapi, gid_t gid, char *buf) 4958 { 4959 const SID *gsid; 4960 BIGSID defgsid; 4961 int size; 4962 4963 size = 0; 4964 if (scapi && (scapi->magic == MAGIC_API)) { 4965 gsid = ntfs_find_gsid(scapi->security.mapping[MAPGROUPS], gid, (SID*)&defgsid); 4966 if (gsid) { 4967 size = ntfs_sid_size(gsid); 4968 memcpy(buf,gsid,size); 4969 } else 4970 errno = ENODATA; 4971 } else 4972 errno = EINVAL; 4973 return (size); 4974 } 4975 4976 /* 4977 * Get the user mapped to a SID 4978 * 4979 * returns the uid, or -1 if not found 4980 */ 4981 4982 int ntfs_get_user(struct SECURITY_API *scapi, const SID *usid) 4983 { 4984 int uid; 4985 4986 uid = -1; 4987 if (scapi && (scapi->magic == MAGIC_API) && ntfs_valid_sid(usid)) { 4988 if (ntfs_same_sid(usid,adminsid)) 4989 uid = 0; 4990 else { 4991 uid = ntfs_find_user(scapi->security.mapping[MAPUSERS], usid); 4992 if (!uid) { 4993 uid = -1; 4994 errno = ENODATA; 4995 } 4996 } 4997 } else 4998 errno = EINVAL; 4999 return (uid); 5000 } 5001 5002 /* 5003 * Get the group mapped to a SID 5004 * 5005 * returns the uid, or -1 if not found 5006 */ 5007 5008 int ntfs_get_group(struct SECURITY_API *scapi, const SID *gsid) 5009 { 5010 int gid; 5011 5012 gid = -1; 5013 if (scapi && (scapi->magic == MAGIC_API) && ntfs_valid_sid(gsid)) { 5014 if (ntfs_same_sid(gsid,adminsid)) 5015 gid = 0; 5016 else { 5017 gid = ntfs_find_group(scapi->security.mapping[MAPGROUPS], gsid); 5018 if (!gid) { 5019 gid = -1; 5020 errno = ENODATA; 5021 } 5022 } 5023 } else 5024 errno = EINVAL; 5025 return (gid); 5026 } 5027 5028 /* 5029 * Initializations before calling ntfs_get_file_security() 5030 * ntfs_set_file_security() and ntfs_read_directory() 5031 * 5032 * Only allowed for root 5033 * 5034 * Returns an (obscured) struct SECURITY_API* needed for further calls 5035 * NULL if not root (EPERM) or device is mounted (EBUSY) 5036 */ 5037 5038 struct SECURITY_API *ntfs_initialize_file_security(const char *device, 5039 unsigned long flags) 5040 { 5041 ntfs_volume *vol; 5042 unsigned long mntflag; 5043 int mnt; 5044 struct SECURITY_API *scapi; 5045 struct SECURITY_CONTEXT *scx; 5046 5047 scapi = (struct SECURITY_API*)NULL; 5048 mnt = ntfs_check_if_mounted(device, &mntflag); 5049 if (!mnt && !(mntflag & NTFS_MF_MOUNTED) && !getuid()) { 5050 vol = ntfs_mount(device, flags); 5051 if (vol) { 5052 scapi = (struct SECURITY_API*) 5053 ntfs_malloc(sizeof(struct SECURITY_API)); 5054 if (!ntfs_volume_get_free_space(vol) 5055 && scapi) { 5056 scapi->magic = MAGIC_API; 5057 scapi->seccache = (struct PERMISSIONS_CACHE*)NULL; 5058 scx = &scapi->security; 5059 scx->vol = vol; 5060 scx->uid = getuid(); 5061 scx->gid = getgid(); 5062 scx->pseccache = &scapi->seccache; 5063 scx->vol->secure_flags = 0; 5064 /* accept no mapping and no $Secure */ 5065 ntfs_build_mapping(scx,(const char*)NULL,TRUE); 5066 ntfs_open_secure(vol); 5067 } else { 5068 if (scapi) 5069 free(scapi); 5070 else 5071 errno = ENOMEM; 5072 mnt = ntfs_umount(vol,FALSE); 5073 scapi = (struct SECURITY_API*)NULL; 5074 } 5075 } 5076 } else 5077 if (getuid()) 5078 errno = EPERM; 5079 else 5080 errno = EBUSY; 5081 return (scapi); 5082 } 5083 5084 /* 5085 * Leaving after ntfs_initialize_file_security() 5086 * 5087 * Returns FALSE if FAILED 5088 */ 5089 5090 BOOL ntfs_leave_file_security(struct SECURITY_API *scapi) 5091 { 5092 int ok; 5093 ntfs_volume *vol; 5094 5095 ok = FALSE; 5096 if (scapi && (scapi->magic == MAGIC_API) && scapi->security.vol) { 5097 vol = scapi->security.vol; 5098 ntfs_close_secure(&scapi->security); 5099 free(scapi); 5100 if (!ntfs_umount(vol, 0)) 5101 ok = TRUE; 5102 } 5103 return (ok); 5104 } 5105 5106