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 return path.GetHashCode() * 31 + (uint32)user; 333 } 334 335 UserPath& operator=(const UserPath& other) 336 { 337 path = other.path; 338 user = other.user; 339 return *this; 340 } 341 342 bool operator==(const UserPath& other) const 343 { 344 return (path == other.path && user == other.user); 345 } 346 347 bool operator!=(const UserPath& other) const 348 { 349 return !(*this == other); 350 } 351 352 HashString path; 353 User* user; 354 }; 355 356 // PermissionMap 357 struct SecurityContext::PermissionMap 358 : HashMap<SecurityContext::UserPath, Permissions> { 359 }; 360 361 // NodePathMap 362 struct SecurityContext::NodePathMap : HashMap<NodeRef, HashString> { 363 }; 364 365 // PathNodeMap 366 struct SecurityContext::PathNodeMap : HashMap<HashString, NodeRef> { 367 }; 368 369 // constructor 370 SecurityContext::SecurityContext() 371 : BArchivable(), 372 BLocker("security context"), 373 fUsers(new(std::nothrow) UserMap), 374 fShares(new(std::nothrow) ShareMap), 375 fPermissions(new(std::nothrow) PermissionMap), 376 fNode2Path(new(std::nothrow) NodePathMap), 377 fPath2Node(new(std::nothrow) PathNodeMap) 378 { 379 } 380 381 // constructor 382 SecurityContext::SecurityContext(BMessage* archive) 383 : BArchivable(archive), 384 fUsers(new(std::nothrow) UserMap), 385 fShares(new(std::nothrow) ShareMap), 386 fPermissions(new(std::nothrow) PermissionMap), 387 fNode2Path(new(std::nothrow) NodePathMap), 388 fPath2Node(new(std::nothrow) PathNodeMap) 389 { 390 if (InitCheck() != B_OK) 391 return; 392 status_t error = B_OK; 393 394 // users 395 BMessage userArchive; 396 for (int32 i = 0; 397 archive->FindMessage("users", i, &userArchive) == B_OK; 398 i++) { 399 User tmpUser; 400 error = tmpUser.Unarchive(&userArchive); 401 if (error != B_OK) 402 return; 403 error = AddUser(tmpUser.GetName(), tmpUser.GetPassword()); 404 if (error != B_OK) 405 return; 406 } 407 408 // shares 409 BMessage shareArchive; 410 for (int32 i = 0; 411 archive->FindMessage("shares", i, &shareArchive) == B_OK; 412 i++) { 413 Share tmpShare; 414 error = tmpShare.Unarchive(&shareArchive); 415 if (error != B_OK) 416 return; 417 error = AddShare(tmpShare.GetName(), tmpShare.GetPath()); 418 if (error != B_OK) 419 return; 420 } 421 422 // permissions 423 BMessage permissionsArchive; 424 if (archive->FindMessage("permissions", &permissionsArchive) != B_OK) 425 return; 426 #ifdef HAIKU_TARGET_PLATFORM_DANO 427 const char* userName; 428 #else 429 char* userName; 430 #endif 431 type_code type; 432 for (int32 userIndex = 0; 433 permissionsArchive.GetInfo(B_MESSAGE_TYPE, userIndex, &userName, &type) 434 == B_OK; 435 userIndex++) { 436 User* user = FindUser(userName); 437 if (!user) 438 return; 439 BReference<User> userReference(user, true); 440 error = permissionsArchive.FindMessage(userName, &userArchive); 441 if (error != B_OK) 442 return; 443 444 // got a user: iterate through its permissions 445 #ifdef HAIKU_TARGET_PLATFORM_DANO 446 const char* path; 447 #else 448 char* path; 449 #endif 450 for (int32 i = 0; 451 userArchive.GetInfo(B_INT32_TYPE, i, &path, &type) == B_OK; 452 i++) { 453 uint32 permissions; 454 error = userArchive.FindInt32(path, (int32*)&permissions); 455 if (error == B_OK) 456 error = SetNodePermissions(path, user, permissions); 457 } 458 } 459 } 460 461 // destructor 462 SecurityContext::~SecurityContext() 463 { 464 // remove all user references 465 for (UserMap::Iterator it = fUsers->GetIterator(); it.HasNext();) { 466 User* user = it.Next().value; 467 user->ReleaseReference(); 468 } 469 470 // remove all share references 471 for (ShareMap::Iterator it = fShares->GetIterator(); it.HasNext();) { 472 Share* share = it.Next().value; 473 share->ReleaseReference(); 474 } 475 476 delete fUsers; 477 delete fShares; 478 delete fPermissions; 479 delete fNode2Path; 480 delete fPath2Node; 481 } 482 483 // Archive 484 status_t 485 SecurityContext::Archive(BMessage* archive, bool deep) const 486 { 487 if (!archive) 488 return B_BAD_VALUE; 489 status_t error = B_OK; 490 ContextLocker _(const_cast<SecurityContext*>(this)); 491 492 // users 493 int32 userCount = fUsers->Size(); 494 for (UserMap::Iterator it = fUsers->GetIterator(); it.HasNext();) { 495 User* user = it.Next().value; 496 BMessage userArchive; 497 error = user->Archive(&userArchive, deep); 498 if (error != B_OK) 499 return error; 500 error = archive->AddMessage("users", &userArchive); 501 if (error != B_OK) 502 return error; 503 } 504 505 // shares 506 for (ShareMap::Iterator it = fShares->GetIterator(); it.HasNext();) { 507 Share* share = it.Next().value; 508 BMessage shareArchive; 509 error = share->Archive(&shareArchive, deep); 510 if (error != B_OK) 511 return error; 512 error = archive->AddMessage("shares", &shareArchive); 513 if (error != B_OK) 514 return error; 515 } 516 517 // permissions 518 // we slice them per user 519 BMessage* tmpUserArchives = new(std::nothrow) BMessage[userCount]; 520 if (!tmpUserArchives) 521 return B_NO_MEMORY; 522 ArrayDeleter<BMessage> deleter(tmpUserArchives); 523 HashMap<HashKey32<User*>, BMessage*> userArchives; 524 int32 i = 0; 525 for (UserMap::Iterator it = fUsers->GetIterator(); it.HasNext();) { 526 User* user = it.Next().value; 527 error = userArchives.Put(user, tmpUserArchives + i); 528 if (error != B_OK) 529 return error; 530 i++; 531 } 532 533 // fill the per user archives 534 for (PermissionMap::Iterator it = fPermissions->GetIterator(); 535 it.HasNext();) { 536 PermissionMap::Entry entry = it.Next(); 537 BMessage* userArchive = userArchives.Get(entry.key.user); 538 error = userArchive->AddInt32(entry.key.path.GetString(), 539 entry.value.GetPermissions()); 540 if (error != B_OK) 541 return error; 542 } 543 544 // put the user permissions together 545 BMessage permissionsArchive; 546 for (UserMap::Iterator it = fUsers->GetIterator(); it.HasNext();) { 547 User* user = it.Next().value; 548 error = permissionsArchive.AddMessage(user->GetName(), 549 userArchives.Get(user)); 550 if (error != B_OK) 551 return error; 552 } 553 error = archive->AddMessage("permissions", &permissionsArchive); 554 if (error != B_OK) 555 return error; 556 return B_OK; 557 } 558 559 // Instantiate 560 BArchivable* 561 SecurityContext::Instantiate(BMessage* archive) 562 { 563 if (!validate_instantiation(archive, "SecurityContext")) 564 return NULL; 565 return new(std::nothrow) SecurityContext(archive); 566 } 567 568 569 // InitCheck 570 status_t 571 SecurityContext::InitCheck() const 572 { 573 if (!fUsers || !fShares || !fPermissions || !fNode2Path || !fPath2Node) 574 return B_NO_MEMORY; 575 576 if (fUsers->InitCheck() != B_OK) 577 return fUsers->InitCheck(); 578 579 if (fShares->InitCheck() != B_OK) 580 return fShares->InitCheck(); 581 582 if (fPermissions->InitCheck() != B_OK) 583 return fPermissions->InitCheck(); 584 585 if (fNode2Path->InitCheck() != B_OK) 586 return fNode2Path->InitCheck(); 587 588 if (fPath2Node->InitCheck() != B_OK) 589 return fPath2Node->InitCheck(); 590 591 return B_OK; 592 } 593 594 // AddUser 595 // 596 // The caller gets a reference, if _user is not NULL. 597 status_t 598 SecurityContext::AddUser(const char* name, const char* password, User** _user) 599 { 600 if (!name) 601 return B_BAD_VALUE; 602 603 // check, if the user does already exist 604 ContextLocker _(this); 605 if (fUsers->Get(name)) 606 return B_BAD_VALUE; 607 608 // create a the user 609 User* user = new(std::nothrow) User; 610 if (!user) 611 return B_NO_MEMORY; 612 BReference<User> userReference(user, true); 613 status_t error = user->Init(name, password); 614 if (error != B_OK) 615 return error; 616 617 // add the user 618 error = fUsers->Put(name, user); 619 if (error != B_OK) 620 return error; 621 622 userReference.Detach(); 623 if (_user) { 624 *_user = user; 625 user->AcquireReference(); 626 } 627 return B_OK; 628 } 629 630 // RemoveUser 631 // 632 // The caller gets a reference, if _user is not NULL. 633 status_t 634 SecurityContext::RemoveUser(const char* name, User** _user) 635 { 636 if (!name) 637 return B_BAD_VALUE; 638 639 ContextLocker _(this); 640 641 // get the user 642 User* user = FindUser(name); 643 if (!user) 644 return B_ENTRY_NOT_FOUND; 645 BReference<User> userReference(user, true); 646 647 // remove it 648 status_t error = RemoveUser(user); 649 if (error == B_OK && _user) { 650 *_user = user; 651 user->AcquireReference(); 652 } 653 654 return error; 655 } 656 657 // RemoveUser 658 status_t 659 SecurityContext::RemoveUser(User* user) 660 { 661 if (!user) 662 return B_BAD_VALUE; 663 664 ContextLocker _(this); 665 666 // find and remove it 667 if (fUsers->Get(user->GetName()) != user) 668 return B_BAD_VALUE; 669 fUsers->Remove(user->GetName()); 670 671 // remove all permission entries for this user 672 for (PermissionMap::Iterator it = fPermissions->GetIterator(); 673 it.HasNext();) { 674 PermissionMap::Entry entry = it.Next(); 675 if (entry.key.user == user) 676 it.Remove(); 677 } 678 679 // surrender our user reference 680 user->ReleaseReference(); 681 682 return B_OK; 683 } 684 685 // FindUser 686 // 687 // The caller gets a reference. 688 User* 689 SecurityContext::FindUser(const char* name) 690 { 691 if (!name) 692 return NULL; 693 694 ContextLocker _(this); 695 User* user = fUsers->Get(name); 696 if (user) 697 user->AcquireReference(); 698 return user; 699 } 700 701 // AuthenticateUser 702 // 703 // The caller gets a reference. 704 status_t 705 SecurityContext::AuthenticateUser(const char* name, const char* password, 706 User** _user) 707 { 708 if (!_user) 709 return B_BAD_VALUE; 710 711 // find user 712 ContextLocker _(this); 713 User* user = FindUser(name); 714 if (!user) 715 return B_PERMISSION_DENIED; 716 BReference<User> userReference(user, true); 717 718 // check password 719 if (user->GetPassword()) { 720 if (!password || strcmp(user->GetPassword(), password) != 0) 721 return B_PERMISSION_DENIED; 722 } else if (password) 723 return B_PERMISSION_DENIED; 724 725 *_user = user; 726 userReference.Detach(); 727 return B_OK; 728 } 729 730 // CountUsers 731 int32 732 SecurityContext::CountUsers() 733 { 734 ContextLocker _(this); 735 return fUsers->Size(); 736 } 737 738 // GetUsers 739 status_t 740 SecurityContext::GetUsers(BMessage* users) 741 { 742 if (!users) 743 return B_BAD_VALUE; 744 745 ContextLocker _(this); 746 747 // iterate through all users and add their names to the message 748 for (UserMap::Iterator it = fUsers->GetIterator(); it.HasNext();) { 749 User* user = it.Next().value; 750 status_t error = users->AddString("users", user->GetName()); 751 if (error != B_OK) 752 return error; 753 } 754 755 return B_OK; 756 } 757 758 // AddShare 759 // 760 // The caller gets a reference, if _share is not NULL. 761 status_t 762 SecurityContext::AddShare(const char* name, const node_ref& ref, Share** _share) 763 { 764 if (!name) 765 return B_BAD_VALUE; 766 767 // check, if the share does already exist 768 ContextLocker _(this); 769 if (fShares->Get(name)) 770 return B_BAD_VALUE; 771 772 // create a the share 773 Share* share = new(std::nothrow) Share; 774 if (!share) 775 return B_NO_MEMORY; 776 BReference<Share> shareReference(share, true); 777 status_t error = share->Init(name, ref); 778 if (error != B_OK) 779 return error; 780 781 // add the share 782 error = fShares->Put(name, share); 783 if (error != B_OK) 784 return error; 785 786 shareReference.Detach(); 787 if (_share) { 788 *_share = share; 789 share->AcquireReference(); 790 } 791 return B_OK; 792 } 793 794 // AddShare 795 // 796 // The caller gets a reference, if _share is not NULL. 797 status_t 798 SecurityContext::AddShare(const char* name, const char* path, Share** _share) 799 { 800 if (!name) 801 return B_BAD_VALUE; 802 803 // check, if the share does already exist 804 ContextLocker _(this); 805 if (fShares->Get(name)) 806 return B_BAD_VALUE; 807 808 // create a the share 809 Share* share = new(std::nothrow) Share; 810 if (!share) 811 return B_NO_MEMORY; 812 BReference<Share> shareReference(share, true); 813 status_t error = share->Init(name, path); 814 if (error != B_OK) 815 return error; 816 817 // add the share 818 error = fShares->Put(name, share); 819 if (error != B_OK) 820 return error; 821 822 shareReference.Detach(); 823 if (_share) { 824 *_share = share; 825 share->AcquireReference(); 826 } 827 return B_OK; 828 } 829 830 // RemoveShare 831 // 832 // The caller gets a reference, if _share is not NULL. 833 status_t 834 SecurityContext::RemoveShare(const char* name, Share** _share) 835 { 836 if (!name) 837 return B_BAD_VALUE; 838 839 ContextLocker _(this); 840 841 // get the share 842 Share* share = FindShare(name); 843 if (!share) 844 return B_ENTRY_NOT_FOUND; 845 BReference<Share> shareReference(share, true); 846 847 // remove it 848 status_t error = RemoveShare(share); 849 if (error == B_OK && _share) { 850 *_share = share; 851 share->AcquireReference(); 852 } 853 854 return error; 855 } 856 857 // RemoveShare 858 status_t 859 SecurityContext::RemoveShare(Share* share) 860 { 861 if (!share) 862 return B_BAD_VALUE; 863 864 ContextLocker _(this); 865 866 // find and remove it 867 if (fShares->Get(share->GetName()) != share) 868 return B_BAD_VALUE; 869 fShares->Remove(share->GetName()); 870 871 // surrender our share reference 872 share->ReleaseReference(); 873 874 return B_OK; 875 } 876 877 // FindShare 878 // 879 // The caller gets a reference. 880 Share* 881 SecurityContext::FindShare(const char* name) 882 { 883 if (!name) 884 return NULL; 885 886 ContextLocker _(this); 887 Share* share = fShares->Get(name); 888 if (share) 889 share->AcquireReference(); 890 return share; 891 } 892 893 // CountShares 894 int32 895 SecurityContext::CountShares() 896 { 897 ContextLocker _(this); 898 return fShares->Size(); 899 } 900 901 // GetShares 902 status_t 903 SecurityContext::GetShares(BMessage* shares) 904 { 905 if (!shares) 906 return B_BAD_VALUE; 907 908 ContextLocker _(this); 909 910 // iterate through all shares and add their names to the message 911 for (ShareMap::Iterator it = fShares->GetIterator(); it.HasNext();) { 912 Share* share = it.Next().value; 913 // add name 914 status_t error = shares->AddString("shares", share->GetName()); 915 if (error != B_OK) 916 return error; 917 918 // add path 919 error = shares->AddString("paths", share->GetPath()); 920 if (error != B_OK) 921 return error; 922 } 923 924 return B_OK; 925 } 926 927 // SetNodePermissions 928 status_t 929 SecurityContext::SetNodePermissions(const node_ref& ref, User* user, 930 Permissions permissions) 931 { 932 if (!user) 933 return B_BAD_VALUE; 934 935 ContextLocker _(this); 936 // check, whether we know the user 937 if (fUsers->Get(user->GetName()) != user) 938 return B_BAD_VALUE; 939 940 HashString path; 941 status_t error = _AddNodePath(ref, &path); 942 if (error != B_OK) 943 return error; 944 return fPermissions->Put(UserPath(path.GetString(), user), permissions); 945 } 946 947 // SetNodePermissions 948 status_t 949 SecurityContext::SetNodePermissions(const char* path, User* user, 950 Permissions permissions) 951 { 952 if (!user || !path) 953 return B_BAD_VALUE; 954 955 ContextLocker _(this); 956 // check, whether we know the user 957 if (fUsers->Get(user->GetName()) != user) 958 return B_BAD_VALUE; 959 960 _AddNodePath(path); 961 return fPermissions->Put(UserPath(path, user), permissions); 962 } 963 964 // ClearNodePermissions 965 void 966 SecurityContext::ClearNodePermissions(const node_ref& ref, User* user) 967 { 968 ContextLocker _(this); 969 HashString path; 970 status_t error = _AddNodePath(ref, &path); 971 if (error != B_OK) 972 return; 973 974 if (user) { 975 fPermissions->Remove(UserPath(path.GetString(), user)); 976 } else { 977 for (UserMap::Iterator it = fUsers->GetIterator(); it.HasNext();) 978 fPermissions->Remove(UserPath(path.GetString(), it.Next().value)); 979 } 980 } 981 982 // ClearNodePermissions 983 void 984 SecurityContext::ClearNodePermissions(const char* path, User* user) 985 { 986 if (!path) 987 return; 988 989 ContextLocker _(this); 990 _AddNodePath(path); 991 992 if (user) { 993 fPermissions->Remove(UserPath(path, user)); 994 } else { 995 for (UserMap::Iterator it = fUsers->GetIterator(); it.HasNext();) 996 fPermissions->Remove(UserPath(path, it.Next().value)); 997 } 998 } 999 1000 // GetNodePermissions 1001 Permissions 1002 SecurityContext::GetNodePermissions(const node_ref& ref, User* user) 1003 { 1004 if (!user) 1005 return Permissions(); 1006 1007 ContextLocker _(this); 1008 HashString path; 1009 status_t error = _AddNodePath(ref, &path); 1010 if (error != B_OK) 1011 return Permissions(); 1012 1013 return fPermissions->Get(UserPath(path.GetString(), user)); 1014 } 1015 1016 // GetNodePermissions 1017 Permissions 1018 SecurityContext::GetNodePermissions(const char* path, User* user) 1019 { 1020 if (!user || !path) 1021 return Permissions(); 1022 1023 ContextLocker _(this); 1024 _AddNodePath(path); 1025 1026 return fPermissions->Get(UserPath(path, user)); 1027 } 1028 1029 // GetUserSecurityContext 1030 status_t 1031 SecurityContext::GetUserSecurityContext(User* user, 1032 UserSecurityContext* userContext) 1033 { 1034 if (!userContext) 1035 return B_BAD_VALUE; 1036 1037 status_t error = userContext->Init(user); 1038 if (error != B_OK) 1039 return error; 1040 1041 // iterate through all permission entries and add the ones whose user 1042 // matches 1043 ContextLocker _(this); 1044 for (PermissionMap::Iterator it = fPermissions->GetIterator(); 1045 it.HasNext();) { 1046 PermissionMap::Entry entry = it.Next(); 1047 node_ref ref; 1048 if (entry.key.user == user 1049 && _GetNodeForPath(entry.key.path.GetString(), &ref)) { 1050 error = userContext->AddNode(ref.device, ref.node, entry.value); 1051 if (error != B_OK) 1052 return error; 1053 } 1054 } 1055 return B_OK; 1056 } 1057 1058 // _AddNodePath 1059 status_t 1060 SecurityContext::_AddNodePath(const char* path, node_ref* _ref) 1061 { 1062 if (!fPath2Node->ContainsKey(path)) { 1063 node_ref ref; 1064 status_t error = get_node_ref_for_path(path, &ref); 1065 if (error == B_OK) 1066 error = _EnterNodePath(path, ref); 1067 if (error != B_OK) 1068 return error; 1069 } 1070 1071 if (_ref) 1072 *_ref = fPath2Node->Get(path); 1073 return B_OK; 1074 } 1075 1076 // _AddNodePath 1077 status_t 1078 SecurityContext::_AddNodePath(const node_ref& ref, HashString* _path) 1079 { 1080 if (!fNode2Path->ContainsKey(ref)) { 1081 BPath path; 1082 entry_ref entryRef(ref.device, ref.node, "."); 1083 status_t error = path.SetTo(&entryRef); 1084 if (error == B_OK) 1085 error = _EnterNodePath(path.Path(), ref); 1086 if (error != B_OK) 1087 return error; 1088 } 1089 1090 if (_path) 1091 *_path = fNode2Path->Get(ref); 1092 return B_OK; 1093 } 1094 1095 // _EnterNodePath 1096 status_t 1097 SecurityContext::_EnterNodePath(const char* path, const node_ref& ref) 1098 { 1099 status_t error = fNode2Path->Put(ref, path); 1100 if (error == B_OK) { 1101 error = fPath2Node->Put(path, ref); 1102 if (error != B_OK) 1103 fNode2Path->Remove(ref); 1104 } 1105 return error; 1106 } 1107 1108 // _GetNodeForPath 1109 bool 1110 SecurityContext::_GetNodeForPath(const char* path, node_ref* ref) 1111 { 1112 if (path && fPath2Node->ContainsKey(path)) { 1113 if (ref) 1114 *ref = fPath2Node->Get(path); 1115 return true; 1116 } 1117 return false; 1118 } 1119 1120