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 HashMap<HashKeyPointer<User*>, BMessage*> userArchives; 529 int32 i = 0; 530 for (UserMap::Iterator it = fUsers->GetIterator(); it.HasNext();) { 531 User* user = it.Next().value; 532 error = userArchives.Put(user, tmpUserArchives + i); 533 if (error != B_OK) 534 return error; 535 i++; 536 } 537 538 // fill the per user archives 539 for (PermissionMap::Iterator it = fPermissions->GetIterator(); 540 it.HasNext();) { 541 PermissionMap::Entry entry = it.Next(); 542 BMessage* userArchive = userArchives.Get(entry.key.user); 543 error = userArchive->AddInt32(entry.key.path.GetString(), 544 entry.value.GetPermissions()); 545 if (error != B_OK) 546 return error; 547 } 548 549 // put the user permissions together 550 BMessage permissionsArchive; 551 for (UserMap::Iterator it = fUsers->GetIterator(); it.HasNext();) { 552 User* user = it.Next().value; 553 error = permissionsArchive.AddMessage(user->GetName(), 554 userArchives.Get(user)); 555 if (error != B_OK) 556 return error; 557 } 558 error = archive->AddMessage("permissions", &permissionsArchive); 559 if (error != B_OK) 560 return error; 561 return B_OK; 562 } 563 564 // Instantiate 565 BArchivable* 566 SecurityContext::Instantiate(BMessage* archive) 567 { 568 if (!validate_instantiation(archive, "SecurityContext")) 569 return NULL; 570 return new(std::nothrow) SecurityContext(archive); 571 } 572 573 574 // InitCheck 575 status_t 576 SecurityContext::InitCheck() const 577 { 578 if (!fUsers || !fShares || !fPermissions || !fNode2Path || !fPath2Node) 579 return B_NO_MEMORY; 580 581 if (fUsers->InitCheck() != B_OK) 582 return fUsers->InitCheck(); 583 584 if (fShares->InitCheck() != B_OK) 585 return fShares->InitCheck(); 586 587 if (fPermissions->InitCheck() != B_OK) 588 return fPermissions->InitCheck(); 589 590 if (fNode2Path->InitCheck() != B_OK) 591 return fNode2Path->InitCheck(); 592 593 if (fPath2Node->InitCheck() != B_OK) 594 return fPath2Node->InitCheck(); 595 596 return B_OK; 597 } 598 599 // AddUser 600 // 601 // The caller gets a reference, if _user is not NULL. 602 status_t 603 SecurityContext::AddUser(const char* name, const char* password, User** _user) 604 { 605 if (!name) 606 return B_BAD_VALUE; 607 608 // check, if the user does already exist 609 ContextLocker _(this); 610 if (fUsers->Get(name)) 611 return B_BAD_VALUE; 612 613 // create a the user 614 User* user = new(std::nothrow) User; 615 if (!user) 616 return B_NO_MEMORY; 617 BReference<User> userReference(user, true); 618 status_t error = user->Init(name, password); 619 if (error != B_OK) 620 return error; 621 622 // add the user 623 error = fUsers->Put(name, user); 624 if (error != B_OK) 625 return error; 626 627 userReference.Detach(); 628 if (_user) { 629 *_user = user; 630 user->AcquireReference(); 631 } 632 return B_OK; 633 } 634 635 // RemoveUser 636 // 637 // The caller gets a reference, if _user is not NULL. 638 status_t 639 SecurityContext::RemoveUser(const char* name, User** _user) 640 { 641 if (!name) 642 return B_BAD_VALUE; 643 644 ContextLocker _(this); 645 646 // get the user 647 User* user = FindUser(name); 648 if (!user) 649 return B_ENTRY_NOT_FOUND; 650 BReference<User> userReference(user, true); 651 652 // remove it 653 status_t error = RemoveUser(user); 654 if (error == B_OK && _user) { 655 *_user = user; 656 user->AcquireReference(); 657 } 658 659 return error; 660 } 661 662 // RemoveUser 663 status_t 664 SecurityContext::RemoveUser(User* user) 665 { 666 if (!user) 667 return B_BAD_VALUE; 668 669 ContextLocker _(this); 670 671 // find and remove it 672 if (fUsers->Get(user->GetName()) != user) 673 return B_BAD_VALUE; 674 fUsers->Remove(user->GetName()); 675 676 // remove all permission entries for this user 677 for (PermissionMap::Iterator it = fPermissions->GetIterator(); 678 it.HasNext();) { 679 PermissionMap::Entry entry = it.Next(); 680 if (entry.key.user == user) 681 fPermissions->Remove(it); 682 } 683 684 // surrender our user reference 685 user->ReleaseReference(); 686 687 return B_OK; 688 } 689 690 // FindUser 691 // 692 // The caller gets a reference. 693 User* 694 SecurityContext::FindUser(const char* name) 695 { 696 if (!name) 697 return NULL; 698 699 ContextLocker _(this); 700 User* user = fUsers->Get(name); 701 if (user) 702 user->AcquireReference(); 703 return user; 704 } 705 706 // AuthenticateUser 707 // 708 // The caller gets a reference. 709 status_t 710 SecurityContext::AuthenticateUser(const char* name, const char* password, 711 User** _user) 712 { 713 if (!_user) 714 return B_BAD_VALUE; 715 716 // find user 717 ContextLocker _(this); 718 User* user = FindUser(name); 719 if (!user) 720 return B_PERMISSION_DENIED; 721 BReference<User> userReference(user, true); 722 723 // check password 724 if (user->GetPassword()) { 725 if (!password || strcmp(user->GetPassword(), password) != 0) 726 return B_PERMISSION_DENIED; 727 } else if (password) 728 return B_PERMISSION_DENIED; 729 730 *_user = user; 731 userReference.Detach(); 732 return B_OK; 733 } 734 735 // CountUsers 736 int32 737 SecurityContext::CountUsers() 738 { 739 ContextLocker _(this); 740 return fUsers->Size(); 741 } 742 743 // GetUsers 744 status_t 745 SecurityContext::GetUsers(BMessage* users) 746 { 747 if (!users) 748 return B_BAD_VALUE; 749 750 ContextLocker _(this); 751 752 // iterate through all users and add their names to the message 753 for (UserMap::Iterator it = fUsers->GetIterator(); it.HasNext();) { 754 User* user = it.Next().value; 755 status_t error = users->AddString("users", user->GetName()); 756 if (error != B_OK) 757 return error; 758 } 759 760 return B_OK; 761 } 762 763 // AddShare 764 // 765 // The caller gets a reference, if _share is not NULL. 766 status_t 767 SecurityContext::AddShare(const char* name, const node_ref& ref, Share** _share) 768 { 769 if (!name) 770 return B_BAD_VALUE; 771 772 // check, if the share does already exist 773 ContextLocker _(this); 774 if (fShares->Get(name)) 775 return B_BAD_VALUE; 776 777 // create a the share 778 Share* share = new(std::nothrow) Share; 779 if (!share) 780 return B_NO_MEMORY; 781 BReference<Share> shareReference(share, true); 782 status_t error = share->Init(name, ref); 783 if (error != B_OK) 784 return error; 785 786 // add the share 787 error = fShares->Put(name, share); 788 if (error != B_OK) 789 return error; 790 791 shareReference.Detach(); 792 if (_share) { 793 *_share = share; 794 share->AcquireReference(); 795 } 796 return B_OK; 797 } 798 799 // AddShare 800 // 801 // The caller gets a reference, if _share is not NULL. 802 status_t 803 SecurityContext::AddShare(const char* name, const char* path, Share** _share) 804 { 805 if (!name) 806 return B_BAD_VALUE; 807 808 // check, if the share does already exist 809 ContextLocker _(this); 810 if (fShares->Get(name)) 811 return B_BAD_VALUE; 812 813 // create a the share 814 Share* share = new(std::nothrow) Share; 815 if (!share) 816 return B_NO_MEMORY; 817 BReference<Share> shareReference(share, true); 818 status_t error = share->Init(name, path); 819 if (error != B_OK) 820 return error; 821 822 // add the share 823 error = fShares->Put(name, share); 824 if (error != B_OK) 825 return error; 826 827 shareReference.Detach(); 828 if (_share) { 829 *_share = share; 830 share->AcquireReference(); 831 } 832 return B_OK; 833 } 834 835 // RemoveShare 836 // 837 // The caller gets a reference, if _share is not NULL. 838 status_t 839 SecurityContext::RemoveShare(const char* name, Share** _share) 840 { 841 if (!name) 842 return B_BAD_VALUE; 843 844 ContextLocker _(this); 845 846 // get the share 847 Share* share = FindShare(name); 848 if (!share) 849 return B_ENTRY_NOT_FOUND; 850 BReference<Share> shareReference(share, true); 851 852 // remove it 853 status_t error = RemoveShare(share); 854 if (error == B_OK && _share) { 855 *_share = share; 856 share->AcquireReference(); 857 } 858 859 return error; 860 } 861 862 // RemoveShare 863 status_t 864 SecurityContext::RemoveShare(Share* share) 865 { 866 if (!share) 867 return B_BAD_VALUE; 868 869 ContextLocker _(this); 870 871 // find and remove it 872 if (fShares->Get(share->GetName()) != share) 873 return B_BAD_VALUE; 874 fShares->Remove(share->GetName()); 875 876 // surrender our share reference 877 share->ReleaseReference(); 878 879 return B_OK; 880 } 881 882 // FindShare 883 // 884 // The caller gets a reference. 885 Share* 886 SecurityContext::FindShare(const char* name) 887 { 888 if (!name) 889 return NULL; 890 891 ContextLocker _(this); 892 Share* share = fShares->Get(name); 893 if (share) 894 share->AcquireReference(); 895 return share; 896 } 897 898 // CountShares 899 int32 900 SecurityContext::CountShares() 901 { 902 ContextLocker _(this); 903 return fShares->Size(); 904 } 905 906 // GetShares 907 status_t 908 SecurityContext::GetShares(BMessage* shares) 909 { 910 if (!shares) 911 return B_BAD_VALUE; 912 913 ContextLocker _(this); 914 915 // iterate through all shares and add their names to the message 916 for (ShareMap::Iterator it = fShares->GetIterator(); it.HasNext();) { 917 Share* share = it.Next().value; 918 // add name 919 status_t error = shares->AddString("shares", share->GetName()); 920 if (error != B_OK) 921 return error; 922 923 // add path 924 error = shares->AddString("paths", share->GetPath()); 925 if (error != B_OK) 926 return error; 927 } 928 929 return B_OK; 930 } 931 932 // SetNodePermissions 933 status_t 934 SecurityContext::SetNodePermissions(const node_ref& ref, User* user, 935 Permissions permissions) 936 { 937 if (!user) 938 return B_BAD_VALUE; 939 940 ContextLocker _(this); 941 // check, whether we know the user 942 if (fUsers->Get(user->GetName()) != user) 943 return B_BAD_VALUE; 944 945 HashString path; 946 status_t error = _AddNodePath(ref, &path); 947 if (error != B_OK) 948 return error; 949 return fPermissions->Put(UserPath(path.GetString(), user), permissions); 950 } 951 952 // SetNodePermissions 953 status_t 954 SecurityContext::SetNodePermissions(const char* path, User* user, 955 Permissions permissions) 956 { 957 if (!user || !path) 958 return B_BAD_VALUE; 959 960 ContextLocker _(this); 961 // check, whether we know the user 962 if (fUsers->Get(user->GetName()) != user) 963 return B_BAD_VALUE; 964 965 _AddNodePath(path); 966 return fPermissions->Put(UserPath(path, user), permissions); 967 } 968 969 // ClearNodePermissions 970 void 971 SecurityContext::ClearNodePermissions(const node_ref& ref, User* user) 972 { 973 ContextLocker _(this); 974 HashString path; 975 status_t error = _AddNodePath(ref, &path); 976 if (error != B_OK) 977 return; 978 979 if (user) { 980 fPermissions->Remove(UserPath(path.GetString(), user)); 981 } else { 982 for (UserMap::Iterator it = fUsers->GetIterator(); it.HasNext();) 983 fPermissions->Remove(UserPath(path.GetString(), it.Next().value)); 984 } 985 } 986 987 // ClearNodePermissions 988 void 989 SecurityContext::ClearNodePermissions(const char* path, User* user) 990 { 991 if (!path) 992 return; 993 994 ContextLocker _(this); 995 _AddNodePath(path); 996 997 if (user) { 998 fPermissions->Remove(UserPath(path, user)); 999 } else { 1000 for (UserMap::Iterator it = fUsers->GetIterator(); it.HasNext();) 1001 fPermissions->Remove(UserPath(path, it.Next().value)); 1002 } 1003 } 1004 1005 // GetNodePermissions 1006 Permissions 1007 SecurityContext::GetNodePermissions(const node_ref& ref, User* user) 1008 { 1009 if (!user) 1010 return Permissions(); 1011 1012 ContextLocker _(this); 1013 HashString path; 1014 status_t error = _AddNodePath(ref, &path); 1015 if (error != B_OK) 1016 return Permissions(); 1017 1018 return fPermissions->Get(UserPath(path.GetString(), user)); 1019 } 1020 1021 // GetNodePermissions 1022 Permissions 1023 SecurityContext::GetNodePermissions(const char* path, User* user) 1024 { 1025 if (!user || !path) 1026 return Permissions(); 1027 1028 ContextLocker _(this); 1029 _AddNodePath(path); 1030 1031 return fPermissions->Get(UserPath(path, user)); 1032 } 1033 1034 // GetUserSecurityContext 1035 status_t 1036 SecurityContext::GetUserSecurityContext(User* user, 1037 UserSecurityContext* userContext) 1038 { 1039 if (!userContext) 1040 return B_BAD_VALUE; 1041 1042 status_t error = userContext->Init(user); 1043 if (error != B_OK) 1044 return error; 1045 1046 // iterate through all permission entries and add the ones whose user 1047 // matches 1048 ContextLocker _(this); 1049 for (PermissionMap::Iterator it = fPermissions->GetIterator(); 1050 it.HasNext();) { 1051 PermissionMap::Entry entry = it.Next(); 1052 node_ref ref; 1053 if (entry.key.user == user 1054 && _GetNodeForPath(entry.key.path.GetString(), &ref)) { 1055 error = userContext->AddNode(ref.device, ref.node, entry.value); 1056 if (error != B_OK) 1057 return error; 1058 } 1059 } 1060 return B_OK; 1061 } 1062 1063 // _AddNodePath 1064 status_t 1065 SecurityContext::_AddNodePath(const char* path, node_ref* _ref) 1066 { 1067 if (!fPath2Node->ContainsKey(path)) { 1068 node_ref ref; 1069 status_t error = get_node_ref_for_path(path, &ref); 1070 if (error == B_OK) 1071 error = _EnterNodePath(path, ref); 1072 if (error != B_OK) 1073 return error; 1074 } 1075 1076 if (_ref) 1077 *_ref = fPath2Node->Get(path); 1078 return B_OK; 1079 } 1080 1081 // _AddNodePath 1082 status_t 1083 SecurityContext::_AddNodePath(const node_ref& ref, HashString* _path) 1084 { 1085 if (!fNode2Path->ContainsKey(ref)) { 1086 BPath path; 1087 entry_ref entryRef(ref.device, ref.node, "."); 1088 status_t error = path.SetTo(&entryRef); 1089 if (error == B_OK) 1090 error = _EnterNodePath(path.Path(), ref); 1091 if (error != B_OK) 1092 return error; 1093 } 1094 1095 if (_path) 1096 *_path = fNode2Path->Get(ref); 1097 return B_OK; 1098 } 1099 1100 // _EnterNodePath 1101 status_t 1102 SecurityContext::_EnterNodePath(const char* path, const node_ref& ref) 1103 { 1104 status_t error = fNode2Path->Put(ref, path); 1105 if (error == B_OK) { 1106 error = fPath2Node->Put(path, ref); 1107 if (error != B_OK) 1108 fNode2Path->Remove(ref); 1109 } 1110 return error; 1111 } 1112 1113 // _GetNodeForPath 1114 bool 1115 SecurityContext::_GetNodeForPath(const char* path, node_ref* ref) 1116 { 1117 if (path && fPath2Node->ContainsKey(path)) { 1118 if (ref) 1119 *ref = fPath2Node->Get(path); 1120 return true; 1121 } 1122 return false; 1123 } 1124 1125