1 // SecurityContext.cpp 2 3 #include <errno.h> 4 #include <string.h> 5 #include <sys/stat.h> 6 7 #include <AutoDeleter.h> 8 #include <AutoLocker.h> 9 #include <Entry.h> 10 #include <HashMap.h> 11 #include <Message.h> 12 #include <Path.h> 13 14 #include "Compatibility.h" 15 #include "Node.h" 16 #include "SecurityContext.h" 17 #include "UserSecurityContext.h" 18 19 typedef AutoLocker<SecurityContext> ContextLocker; 20 21 // get_node_ref_for_path 22 static 23 status_t 24 get_node_ref_for_path(const char* path, node_ref* ref) 25 { 26 if (!path || !ref) 27 return B_BAD_VALUE; 28 struct stat st; 29 if (lstat(path, &st) < 0) 30 return errno; 31 ref->device = st.st_dev; 32 ref->node = st.st_ino; 33 return B_OK; 34 } 35 36 // #pragma mark - 37 // #pragma mark ----- User ----- 38 39 // constructor 40 User::User() 41 : BReferenceable(), 42 BArchivable(), 43 fName(), 44 fPassword() 45 { 46 } 47 48 // constructor 49 User::User(BMessage* archive) 50 : BReferenceable(), 51 BArchivable(archive), 52 fName(), 53 fPassword() 54 { 55 Unarchive(archive); 56 } 57 58 // destructor 59 User::~User() 60 { 61 } 62 63 // Archive 64 status_t 65 User::Archive(BMessage* archive, bool deep) const 66 { 67 if (!archive) 68 return B_BAD_VALUE; 69 // name 70 status_t error = B_OK; 71 if (error == B_OK && fName.GetLength() > 0) 72 error = archive->AddString("name", fName.GetString()); 73 // password 74 if (error == B_OK && fPassword.GetLength() > 0) 75 error = archive->AddString("password", fPassword.GetString()); 76 return error; 77 } 78 79 // Instantiate 80 BArchivable* 81 User::Instantiate(BMessage* archive) 82 { 83 if (!validate_instantiation(archive, "User")) 84 return NULL; 85 return new(std::nothrow) User(archive); 86 } 87 88 // Init 89 status_t 90 User::Init(const char* name, const char* password) 91 { 92 if (!name) 93 return B_BAD_VALUE; 94 if (!fName.SetTo(name)) 95 return B_NO_MEMORY; 96 if (password && !fPassword.SetTo(password)) 97 return B_NO_MEMORY; 98 return B_OK; 99 } 100 101 // InitCheck 102 status_t 103 User::InitCheck() const 104 { 105 if (fName.GetLength() == 0) 106 return B_NO_INIT; 107 return B_OK; 108 } 109 110 // Unarchive 111 status_t 112 User::Unarchive(const BMessage* archive) 113 { 114 // name 115 const char* name; 116 if (archive->FindString("name", &name) != B_OK) 117 return B_BAD_DATA; 118 fName.SetTo(name); 119 // password 120 const char* password; 121 if (archive->FindString("password", &password) == B_OK) 122 fPassword.SetTo(password); 123 else 124 fPassword.Unset(); 125 return B_OK; 126 } 127 128 // GetName 129 const char* 130 User::GetName() const 131 { 132 return fName.GetString(); 133 } 134 135 // GetPassword 136 const char* 137 User::GetPassword() const 138 { 139 return fPassword.GetString(); 140 } 141 142 143 // #pragma mark - 144 // #pragma mark ----- Share ----- 145 146 // constructor 147 Share::Share() 148 : BReferenceable(), 149 BArchivable(), 150 fName(), 151 fNodeRef(), 152 fPath() 153 { 154 } 155 156 // constructor 157 Share::Share(BMessage* archive) 158 : BReferenceable(), 159 BArchivable(archive), 160 fName(), 161 fNodeRef(), 162 fPath() 163 { 164 Unarchive(archive); 165 } 166 167 // destructor 168 Share::~Share() 169 { 170 } 171 172 // Archive 173 status_t 174 Share::Archive(BMessage* archive, bool deep) const 175 { 176 if (!archive) 177 return B_BAD_VALUE; 178 // name 179 status_t error = B_OK; 180 if (error == B_OK && fName.GetLength() > 0) 181 error = archive->AddString("name", fName.GetString()); 182 // path 183 if (error == B_OK && fPath.GetLength() > 0) 184 error = archive->AddString("path", fPath.GetString()); 185 return error; 186 } 187 188 // Instantiate 189 BArchivable* 190 Share::Instantiate(BMessage* archive) 191 { 192 if (!validate_instantiation(archive, "Share")) 193 return NULL; 194 return new(std::nothrow) Share(archive); 195 } 196 197 // Init 198 status_t 199 Share::Init(const char* name, const node_ref& ref, const char* path) 200 { 201 // check params 202 if (!name) 203 return B_BAD_VALUE; 204 // if a path is not given, retrieve it 205 BPath localPath; 206 if (!path) { 207 entry_ref entryRef(ref.device, ref.node, "."); 208 status_t error = localPath.SetTo(&entryRef); 209 if (error != B_OK) 210 return error; 211 path = localPath.Path(); 212 } 213 // set the attributes 214 if (!fName.SetTo(name)) 215 return B_NO_MEMORY; 216 if (!fPath.SetTo(path)) 217 return B_NO_MEMORY; 218 fNodeRef = ref; 219 return B_OK; 220 } 221 222 // Init 223 status_t 224 Share::Init(const char* name, const char* path) 225 { 226 if (!name || !path) 227 return B_BAD_VALUE; 228 node_ref nodeRef; 229 if (get_node_ref_for_path(path, &nodeRef) != B_OK) { 230 nodeRef.device = -1; 231 nodeRef.node = -1; 232 } 233 return Init(name, nodeRef, path); 234 } 235 236 // InitCheck 237 status_t 238 Share::InitCheck() const 239 { 240 if (fName.GetLength() == 0 || fPath.GetLength() == 0) 241 return B_NO_INIT; 242 return B_OK; 243 } 244 245 // Unarchive 246 status_t 247 Share::Unarchive(const BMessage* archive) 248 { 249 // name 250 const char* name = NULL; 251 if (archive->FindString("name", &name) != B_OK) 252 return B_BAD_DATA; 253 // path 254 const char* path = NULL; 255 if (archive->FindString("path", &path) != B_OK) 256 return B_BAD_DATA; 257 return Init(name, path); 258 } 259 260 // GetName 261 const char* 262 Share::GetName() const 263 { 264 return fName.GetString(); 265 } 266 267 // DoesExist 268 bool 269 Share::DoesExist() const 270 { 271 return (fNodeRef.device >= 0); 272 } 273 274 // GetNodeRef 275 const node_ref& 276 Share::GetNodeRef() const 277 { 278 return fNodeRef; 279 } 280 281 // GetVolumeID 282 dev_t 283 Share::GetVolumeID() const 284 { 285 return fNodeRef.device; 286 } 287 288 // GetNodeID 289 ino_t 290 Share::GetNodeID() const 291 { 292 return fNodeRef.node; 293 } 294 295 // GetPath 296 const char* 297 Share::GetPath() const 298 { 299 return fPath.GetString(); 300 } 301 302 303 // #pragma mark - 304 // #pragma mark ----- SecurityContext ----- 305 306 // UserMap 307 struct SecurityContext::UserMap : HashMap<HashString, User*> { 308 }; 309 310 // ShareMap 311 struct SecurityContext::ShareMap : HashMap<HashString, Share*> { 312 }; 313 314 // UserPath 315 struct SecurityContext::UserPath { 316 UserPath() {} 317 318 UserPath(const char* path, User* user) 319 : path(path), 320 user(user) 321 { 322 } 323 324 UserPath(const UserPath& other) 325 : path(other.path), 326 user(other.user) 327 { 328 } 329 330 uint32 GetHashCode() const 331 { 332 #ifdef B_HAIKU_64_BIT 333 uint64 v = (uint64)user; 334 return (path.GetHashCode() * 31) + ((uint32)(v >> 32) ^ (uint32)v); 335 #else 336 return path.GetHashCode() * 31 + (uint32)user; 337 #endif 338 } 339 340 UserPath& operator=(const UserPath& other) 341 { 342 path = other.path; 343 user = other.user; 344 return *this; 345 } 346 347 bool operator==(const UserPath& other) const 348 { 349 return (path == other.path && user == other.user); 350 } 351 352 bool operator!=(const UserPath& other) const 353 { 354 return !(*this == other); 355 } 356 357 HashString path; 358 User* user; 359 }; 360 361 // PermissionMap 362 struct SecurityContext::PermissionMap 363 : HashMap<SecurityContext::UserPath, Permissions> { 364 }; 365 366 // NodePathMap 367 struct SecurityContext::NodePathMap : HashMap<NodeRef, HashString> { 368 }; 369 370 // PathNodeMap 371 struct SecurityContext::PathNodeMap : HashMap<HashString, NodeRef> { 372 }; 373 374 // constructor 375 SecurityContext::SecurityContext() 376 : BArchivable(), 377 BLocker("security context"), 378 fUsers(new(std::nothrow) UserMap), 379 fShares(new(std::nothrow) ShareMap), 380 fPermissions(new(std::nothrow) PermissionMap), 381 fNode2Path(new(std::nothrow) NodePathMap), 382 fPath2Node(new(std::nothrow) PathNodeMap) 383 { 384 } 385 386 // constructor 387 SecurityContext::SecurityContext(BMessage* archive) 388 : BArchivable(archive), 389 fUsers(new(std::nothrow) UserMap), 390 fShares(new(std::nothrow) ShareMap), 391 fPermissions(new(std::nothrow) PermissionMap), 392 fNode2Path(new(std::nothrow) NodePathMap), 393 fPath2Node(new(std::nothrow) PathNodeMap) 394 { 395 if (InitCheck() != B_OK) 396 return; 397 status_t error = B_OK; 398 399 // users 400 BMessage userArchive; 401 for (int32 i = 0; 402 archive->FindMessage("users", i, &userArchive) == B_OK; 403 i++) { 404 User tmpUser; 405 error = tmpUser.Unarchive(&userArchive); 406 if (error != B_OK) 407 return; 408 error = AddUser(tmpUser.GetName(), tmpUser.GetPassword()); 409 if (error != B_OK) 410 return; 411 } 412 413 // shares 414 BMessage shareArchive; 415 for (int32 i = 0; 416 archive->FindMessage("shares", i, &shareArchive) == B_OK; 417 i++) { 418 Share tmpShare; 419 error = tmpShare.Unarchive(&shareArchive); 420 if (error != B_OK) 421 return; 422 error = AddShare(tmpShare.GetName(), tmpShare.GetPath()); 423 if (error != B_OK) 424 return; 425 } 426 427 // permissions 428 BMessage permissionsArchive; 429 if (archive->FindMessage("permissions", &permissionsArchive) != B_OK) 430 return; 431 #ifdef HAIKU_TARGET_PLATFORM_DANO 432 const char* userName; 433 #else 434 char* userName; 435 #endif 436 type_code type; 437 for (int32 userIndex = 0; 438 permissionsArchive.GetInfo(B_MESSAGE_TYPE, userIndex, &userName, &type) 439 == B_OK; 440 userIndex++) { 441 User* user = FindUser(userName); 442 if (!user) 443 return; 444 BReference<User> userReference(user, true); 445 error = permissionsArchive.FindMessage(userName, &userArchive); 446 if (error != B_OK) 447 return; 448 449 // got a user: iterate through its permissions 450 #ifdef HAIKU_TARGET_PLATFORM_DANO 451 const char* path; 452 #else 453 char* path; 454 #endif 455 for (int32 i = 0; 456 userArchive.GetInfo(B_INT32_TYPE, i, &path, &type) == B_OK; 457 i++) { 458 uint32 permissions; 459 error = userArchive.FindInt32(path, (int32*)&permissions); 460 if (error == B_OK) 461 error = SetNodePermissions(path, user, permissions); 462 } 463 } 464 } 465 466 // destructor 467 SecurityContext::~SecurityContext() 468 { 469 // remove all user references 470 for (UserMap::Iterator it = fUsers->GetIterator(); it.HasNext();) { 471 User* user = it.Next().value; 472 user->ReleaseReference(); 473 } 474 475 // remove all share references 476 for (ShareMap::Iterator it = fShares->GetIterator(); it.HasNext();) { 477 Share* share = it.Next().value; 478 share->ReleaseReference(); 479 } 480 481 delete fUsers; 482 delete fShares; 483 delete fPermissions; 484 delete fNode2Path; 485 delete fPath2Node; 486 } 487 488 // Archive 489 status_t 490 SecurityContext::Archive(BMessage* archive, bool deep) const 491 { 492 if (!archive) 493 return B_BAD_VALUE; 494 status_t error = B_OK; 495 ContextLocker _(const_cast<SecurityContext*>(this)); 496 497 // users 498 int32 userCount = fUsers->Size(); 499 for (UserMap::Iterator it = fUsers->GetIterator(); it.HasNext();) { 500 User* user = it.Next().value; 501 BMessage userArchive; 502 error = user->Archive(&userArchive, deep); 503 if (error != B_OK) 504 return error; 505 error = archive->AddMessage("users", &userArchive); 506 if (error != B_OK) 507 return error; 508 } 509 510 // shares 511 for (ShareMap::Iterator it = fShares->GetIterator(); it.HasNext();) { 512 Share* share = it.Next().value; 513 BMessage shareArchive; 514 error = share->Archive(&shareArchive, deep); 515 if (error != B_OK) 516 return error; 517 error = archive->AddMessage("shares", &shareArchive); 518 if (error != B_OK) 519 return error; 520 } 521 522 // permissions 523 // we slice them per user 524 BMessage* tmpUserArchives = new(std::nothrow) BMessage[userCount]; 525 if (!tmpUserArchives) 526 return B_NO_MEMORY; 527 ArrayDeleter<BMessage> deleter(tmpUserArchives); 528 #ifdef B_HAIKU_64_BIT 529 HashMap<HashKey64<User*>, BMessage*> userArchives; 530 #else 531 HashMap<HashKey32<User*>, BMessage*> userArchives; 532 #endif 533 int32 i = 0; 534 for (UserMap::Iterator it = fUsers->GetIterator(); it.HasNext();) { 535 User* user = it.Next().value; 536 error = userArchives.Put(user, tmpUserArchives + i); 537 if (error != B_OK) 538 return error; 539 i++; 540 } 541 542 // fill the per user archives 543 for (PermissionMap::Iterator it = fPermissions->GetIterator(); 544 it.HasNext();) { 545 PermissionMap::Entry entry = it.Next(); 546 BMessage* userArchive = userArchives.Get(entry.key.user); 547 error = userArchive->AddInt32(entry.key.path.GetString(), 548 entry.value.GetPermissions()); 549 if (error != B_OK) 550 return error; 551 } 552 553 // put the user permissions together 554 BMessage permissionsArchive; 555 for (UserMap::Iterator it = fUsers->GetIterator(); it.HasNext();) { 556 User* user = it.Next().value; 557 error = permissionsArchive.AddMessage(user->GetName(), 558 userArchives.Get(user)); 559 if (error != B_OK) 560 return error; 561 } 562 error = archive->AddMessage("permissions", &permissionsArchive); 563 if (error != B_OK) 564 return error; 565 return B_OK; 566 } 567 568 // Instantiate 569 BArchivable* 570 SecurityContext::Instantiate(BMessage* archive) 571 { 572 if (!validate_instantiation(archive, "SecurityContext")) 573 return NULL; 574 return new(std::nothrow) SecurityContext(archive); 575 } 576 577 578 // InitCheck 579 status_t 580 SecurityContext::InitCheck() const 581 { 582 if (!fUsers || !fShares || !fPermissions || !fNode2Path || !fPath2Node) 583 return B_NO_MEMORY; 584 585 if (fUsers->InitCheck() != B_OK) 586 return fUsers->InitCheck(); 587 588 if (fShares->InitCheck() != B_OK) 589 return fShares->InitCheck(); 590 591 if (fPermissions->InitCheck() != B_OK) 592 return fPermissions->InitCheck(); 593 594 if (fNode2Path->InitCheck() != B_OK) 595 return fNode2Path->InitCheck(); 596 597 if (fPath2Node->InitCheck() != B_OK) 598 return fPath2Node->InitCheck(); 599 600 return B_OK; 601 } 602 603 // AddUser 604 // 605 // The caller gets a reference, if _user is not NULL. 606 status_t 607 SecurityContext::AddUser(const char* name, const char* password, User** _user) 608 { 609 if (!name) 610 return B_BAD_VALUE; 611 612 // check, if the user does already exist 613 ContextLocker _(this); 614 if (fUsers->Get(name)) 615 return B_BAD_VALUE; 616 617 // create a the user 618 User* user = new(std::nothrow) User; 619 if (!user) 620 return B_NO_MEMORY; 621 BReference<User> userReference(user, true); 622 status_t error = user->Init(name, password); 623 if (error != B_OK) 624 return error; 625 626 // add the user 627 error = fUsers->Put(name, user); 628 if (error != B_OK) 629 return error; 630 631 userReference.Detach(); 632 if (_user) { 633 *_user = user; 634 user->AcquireReference(); 635 } 636 return B_OK; 637 } 638 639 // RemoveUser 640 // 641 // The caller gets a reference, if _user is not NULL. 642 status_t 643 SecurityContext::RemoveUser(const char* name, User** _user) 644 { 645 if (!name) 646 return B_BAD_VALUE; 647 648 ContextLocker _(this); 649 650 // get the user 651 User* user = FindUser(name); 652 if (!user) 653 return B_ENTRY_NOT_FOUND; 654 BReference<User> userReference(user, true); 655 656 // remove it 657 status_t error = RemoveUser(user); 658 if (error == B_OK && _user) { 659 *_user = user; 660 user->AcquireReference(); 661 } 662 663 return error; 664 } 665 666 // RemoveUser 667 status_t 668 SecurityContext::RemoveUser(User* user) 669 { 670 if (!user) 671 return B_BAD_VALUE; 672 673 ContextLocker _(this); 674 675 // find and remove it 676 if (fUsers->Get(user->GetName()) != user) 677 return B_BAD_VALUE; 678 fUsers->Remove(user->GetName()); 679 680 // remove all permission entries for this user 681 for (PermissionMap::Iterator it = fPermissions->GetIterator(); 682 it.HasNext();) { 683 PermissionMap::Entry entry = it.Next(); 684 if (entry.key.user == user) 685 it.Remove(); 686 } 687 688 // surrender our user reference 689 user->ReleaseReference(); 690 691 return B_OK; 692 } 693 694 // FindUser 695 // 696 // The caller gets a reference. 697 User* 698 SecurityContext::FindUser(const char* name) 699 { 700 if (!name) 701 return NULL; 702 703 ContextLocker _(this); 704 User* user = fUsers->Get(name); 705 if (user) 706 user->AcquireReference(); 707 return user; 708 } 709 710 // AuthenticateUser 711 // 712 // The caller gets a reference. 713 status_t 714 SecurityContext::AuthenticateUser(const char* name, const char* password, 715 User** _user) 716 { 717 if (!_user) 718 return B_BAD_VALUE; 719 720 // find user 721 ContextLocker _(this); 722 User* user = FindUser(name); 723 if (!user) 724 return B_PERMISSION_DENIED; 725 BReference<User> userReference(user, true); 726 727 // check password 728 if (user->GetPassword()) { 729 if (!password || strcmp(user->GetPassword(), password) != 0) 730 return B_PERMISSION_DENIED; 731 } else if (password) 732 return B_PERMISSION_DENIED; 733 734 *_user = user; 735 userReference.Detach(); 736 return B_OK; 737 } 738 739 // CountUsers 740 int32 741 SecurityContext::CountUsers() 742 { 743 ContextLocker _(this); 744 return fUsers->Size(); 745 } 746 747 // GetUsers 748 status_t 749 SecurityContext::GetUsers(BMessage* users) 750 { 751 if (!users) 752 return B_BAD_VALUE; 753 754 ContextLocker _(this); 755 756 // iterate through all users and add their names to the message 757 for (UserMap::Iterator it = fUsers->GetIterator(); it.HasNext();) { 758 User* user = it.Next().value; 759 status_t error = users->AddString("users", user->GetName()); 760 if (error != B_OK) 761 return error; 762 } 763 764 return B_OK; 765 } 766 767 // AddShare 768 // 769 // The caller gets a reference, if _share is not NULL. 770 status_t 771 SecurityContext::AddShare(const char* name, const node_ref& ref, Share** _share) 772 { 773 if (!name) 774 return B_BAD_VALUE; 775 776 // check, if the share does already exist 777 ContextLocker _(this); 778 if (fShares->Get(name)) 779 return B_BAD_VALUE; 780 781 // create a the share 782 Share* share = new(std::nothrow) Share; 783 if (!share) 784 return B_NO_MEMORY; 785 BReference<Share> shareReference(share, true); 786 status_t error = share->Init(name, ref); 787 if (error != B_OK) 788 return error; 789 790 // add the share 791 error = fShares->Put(name, share); 792 if (error != B_OK) 793 return error; 794 795 shareReference.Detach(); 796 if (_share) { 797 *_share = share; 798 share->AcquireReference(); 799 } 800 return B_OK; 801 } 802 803 // AddShare 804 // 805 // The caller gets a reference, if _share is not NULL. 806 status_t 807 SecurityContext::AddShare(const char* name, const char* path, Share** _share) 808 { 809 if (!name) 810 return B_BAD_VALUE; 811 812 // check, if the share does already exist 813 ContextLocker _(this); 814 if (fShares->Get(name)) 815 return B_BAD_VALUE; 816 817 // create a the share 818 Share* share = new(std::nothrow) Share; 819 if (!share) 820 return B_NO_MEMORY; 821 BReference<Share> shareReference(share, true); 822 status_t error = share->Init(name, path); 823 if (error != B_OK) 824 return error; 825 826 // add the share 827 error = fShares->Put(name, share); 828 if (error != B_OK) 829 return error; 830 831 shareReference.Detach(); 832 if (_share) { 833 *_share = share; 834 share->AcquireReference(); 835 } 836 return B_OK; 837 } 838 839 // RemoveShare 840 // 841 // The caller gets a reference, if _share is not NULL. 842 status_t 843 SecurityContext::RemoveShare(const char* name, Share** _share) 844 { 845 if (!name) 846 return B_BAD_VALUE; 847 848 ContextLocker _(this); 849 850 // get the share 851 Share* share = FindShare(name); 852 if (!share) 853 return B_ENTRY_NOT_FOUND; 854 BReference<Share> shareReference(share, true); 855 856 // remove it 857 status_t error = RemoveShare(share); 858 if (error == B_OK && _share) { 859 *_share = share; 860 share->AcquireReference(); 861 } 862 863 return error; 864 } 865 866 // RemoveShare 867 status_t 868 SecurityContext::RemoveShare(Share* share) 869 { 870 if (!share) 871 return B_BAD_VALUE; 872 873 ContextLocker _(this); 874 875 // find and remove it 876 if (fShares->Get(share->GetName()) != share) 877 return B_BAD_VALUE; 878 fShares->Remove(share->GetName()); 879 880 // surrender our share reference 881 share->ReleaseReference(); 882 883 return B_OK; 884 } 885 886 // FindShare 887 // 888 // The caller gets a reference. 889 Share* 890 SecurityContext::FindShare(const char* name) 891 { 892 if (!name) 893 return NULL; 894 895 ContextLocker _(this); 896 Share* share = fShares->Get(name); 897 if (share) 898 share->AcquireReference(); 899 return share; 900 } 901 902 // CountShares 903 int32 904 SecurityContext::CountShares() 905 { 906 ContextLocker _(this); 907 return fShares->Size(); 908 } 909 910 // GetShares 911 status_t 912 SecurityContext::GetShares(BMessage* shares) 913 { 914 if (!shares) 915 return B_BAD_VALUE; 916 917 ContextLocker _(this); 918 919 // iterate through all shares and add their names to the message 920 for (ShareMap::Iterator it = fShares->GetIterator(); it.HasNext();) { 921 Share* share = it.Next().value; 922 // add name 923 status_t error = shares->AddString("shares", share->GetName()); 924 if (error != B_OK) 925 return error; 926 927 // add path 928 error = shares->AddString("paths", share->GetPath()); 929 if (error != B_OK) 930 return error; 931 } 932 933 return B_OK; 934 } 935 936 // SetNodePermissions 937 status_t 938 SecurityContext::SetNodePermissions(const node_ref& ref, User* user, 939 Permissions permissions) 940 { 941 if (!user) 942 return B_BAD_VALUE; 943 944 ContextLocker _(this); 945 // check, whether we know the user 946 if (fUsers->Get(user->GetName()) != user) 947 return B_BAD_VALUE; 948 949 HashString path; 950 status_t error = _AddNodePath(ref, &path); 951 if (error != B_OK) 952 return error; 953 return fPermissions->Put(UserPath(path.GetString(), user), permissions); 954 } 955 956 // SetNodePermissions 957 status_t 958 SecurityContext::SetNodePermissions(const char* path, User* user, 959 Permissions permissions) 960 { 961 if (!user || !path) 962 return B_BAD_VALUE; 963 964 ContextLocker _(this); 965 // check, whether we know the user 966 if (fUsers->Get(user->GetName()) != user) 967 return B_BAD_VALUE; 968 969 _AddNodePath(path); 970 return fPermissions->Put(UserPath(path, user), permissions); 971 } 972 973 // ClearNodePermissions 974 void 975 SecurityContext::ClearNodePermissions(const node_ref& ref, User* user) 976 { 977 ContextLocker _(this); 978 HashString path; 979 status_t error = _AddNodePath(ref, &path); 980 if (error != B_OK) 981 return; 982 983 if (user) { 984 fPermissions->Remove(UserPath(path.GetString(), user)); 985 } else { 986 for (UserMap::Iterator it = fUsers->GetIterator(); it.HasNext();) 987 fPermissions->Remove(UserPath(path.GetString(), it.Next().value)); 988 } 989 } 990 991 // ClearNodePermissions 992 void 993 SecurityContext::ClearNodePermissions(const char* path, User* user) 994 { 995 if (!path) 996 return; 997 998 ContextLocker _(this); 999 _AddNodePath(path); 1000 1001 if (user) { 1002 fPermissions->Remove(UserPath(path, user)); 1003 } else { 1004 for (UserMap::Iterator it = fUsers->GetIterator(); it.HasNext();) 1005 fPermissions->Remove(UserPath(path, it.Next().value)); 1006 } 1007 } 1008 1009 // GetNodePermissions 1010 Permissions 1011 SecurityContext::GetNodePermissions(const node_ref& ref, User* user) 1012 { 1013 if (!user) 1014 return Permissions(); 1015 1016 ContextLocker _(this); 1017 HashString path; 1018 status_t error = _AddNodePath(ref, &path); 1019 if (error != B_OK) 1020 return Permissions(); 1021 1022 return fPermissions->Get(UserPath(path.GetString(), user)); 1023 } 1024 1025 // GetNodePermissions 1026 Permissions 1027 SecurityContext::GetNodePermissions(const char* path, User* user) 1028 { 1029 if (!user || !path) 1030 return Permissions(); 1031 1032 ContextLocker _(this); 1033 _AddNodePath(path); 1034 1035 return fPermissions->Get(UserPath(path, user)); 1036 } 1037 1038 // GetUserSecurityContext 1039 status_t 1040 SecurityContext::GetUserSecurityContext(User* user, 1041 UserSecurityContext* userContext) 1042 { 1043 if (!userContext) 1044 return B_BAD_VALUE; 1045 1046 status_t error = userContext->Init(user); 1047 if (error != B_OK) 1048 return error; 1049 1050 // iterate through all permission entries and add the ones whose user 1051 // matches 1052 ContextLocker _(this); 1053 for (PermissionMap::Iterator it = fPermissions->GetIterator(); 1054 it.HasNext();) { 1055 PermissionMap::Entry entry = it.Next(); 1056 node_ref ref; 1057 if (entry.key.user == user 1058 && _GetNodeForPath(entry.key.path.GetString(), &ref)) { 1059 error = userContext->AddNode(ref.device, ref.node, entry.value); 1060 if (error != B_OK) 1061 return error; 1062 } 1063 } 1064 return B_OK; 1065 } 1066 1067 // _AddNodePath 1068 status_t 1069 SecurityContext::_AddNodePath(const char* path, node_ref* _ref) 1070 { 1071 if (!fPath2Node->ContainsKey(path)) { 1072 node_ref ref; 1073 status_t error = get_node_ref_for_path(path, &ref); 1074 if (error == B_OK) 1075 error = _EnterNodePath(path, ref); 1076 if (error != B_OK) 1077 return error; 1078 } 1079 1080 if (_ref) 1081 *_ref = fPath2Node->Get(path); 1082 return B_OK; 1083 } 1084 1085 // _AddNodePath 1086 status_t 1087 SecurityContext::_AddNodePath(const node_ref& ref, HashString* _path) 1088 { 1089 if (!fNode2Path->ContainsKey(ref)) { 1090 BPath path; 1091 entry_ref entryRef(ref.device, ref.node, "."); 1092 status_t error = path.SetTo(&entryRef); 1093 if (error == B_OK) 1094 error = _EnterNodePath(path.Path(), ref); 1095 if (error != B_OK) 1096 return error; 1097 } 1098 1099 if (_path) 1100 *_path = fNode2Path->Get(ref); 1101 return B_OK; 1102 } 1103 1104 // _EnterNodePath 1105 status_t 1106 SecurityContext::_EnterNodePath(const char* path, const node_ref& ref) 1107 { 1108 status_t error = fNode2Path->Put(ref, path); 1109 if (error == B_OK) { 1110 error = fPath2Node->Put(path, ref); 1111 if (error != B_OK) 1112 fNode2Path->Remove(ref); 1113 } 1114 return error; 1115 } 1116 1117 // _GetNodeForPath 1118 bool 1119 SecurityContext::_GetNodeForPath(const char* path, node_ref* ref) 1120 { 1121 if (path && fPath2Node->ContainsKey(path)) { 1122 if (ref) 1123 *ref = fPath2Node->Get(path); 1124 return true; 1125 } 1126 return false; 1127 } 1128 1129