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
get_node_ref_for_path(const char * path,node_ref * ref)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
User()40 User::User()
41 : BReferenceable(),
42 BArchivable(),
43 fName(),
44 fPassword()
45 {
46 }
47
48 // constructor
User(BMessage * archive)49 User::User(BMessage* archive)
50 : BReferenceable(),
51 BArchivable(archive),
52 fName(),
53 fPassword()
54 {
55 Unarchive(archive);
56 }
57
58 // destructor
~User()59 User::~User()
60 {
61 }
62
63 // Archive
64 status_t
Archive(BMessage * archive,bool deep) const65 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*
Instantiate(BMessage * archive)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
Init(const char * name,const char * password)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
InitCheck() const103 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
Unarchive(const BMessage * archive)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*
GetName() const130 User::GetName() const
131 {
132 return fName.GetString();
133 }
134
135 // GetPassword
136 const char*
GetPassword() const137 User::GetPassword() const
138 {
139 return fPassword.GetString();
140 }
141
142
143 // #pragma mark -
144 // #pragma mark ----- Share -----
145
146 // constructor
Share()147 Share::Share()
148 : BReferenceable(),
149 BArchivable(),
150 fName(),
151 fNodeRef(),
152 fPath()
153 {
154 }
155
156 // constructor
Share(BMessage * archive)157 Share::Share(BMessage* archive)
158 : BReferenceable(),
159 BArchivable(archive),
160 fName(),
161 fNodeRef(),
162 fPath()
163 {
164 Unarchive(archive);
165 }
166
167 // destructor
~Share()168 Share::~Share()
169 {
170 }
171
172 // Archive
173 status_t
Archive(BMessage * archive,bool deep) const174 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*
Instantiate(BMessage * archive)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
Init(const char * name,const node_ref & ref,const char * path)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
Init(const char * name,const char * path)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
InitCheck() const238 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
Unarchive(const BMessage * archive)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*
GetName() const262 Share::GetName() const
263 {
264 return fName.GetString();
265 }
266
267 // DoesExist
268 bool
DoesExist() const269 Share::DoesExist() const
270 {
271 return (fNodeRef.device >= 0);
272 }
273
274 // GetNodeRef
275 const node_ref&
GetNodeRef() const276 Share::GetNodeRef() const
277 {
278 return fNodeRef;
279 }
280
281 // GetVolumeID
282 dev_t
GetVolumeID() const283 Share::GetVolumeID() const
284 {
285 return fNodeRef.device;
286 }
287
288 // GetNodeID
289 ino_t
GetNodeID() const290 Share::GetNodeID() const
291 {
292 return fNodeRef.node;
293 }
294
295 // GetPath
296 const char*
GetPath() const297 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 {
UserPathSecurityContext::UserPath316 UserPath() {}
317
UserPathSecurityContext::UserPath318 UserPath(const char* path, User* user)
319 : path(path),
320 user(user)
321 {
322 }
323
UserPathSecurityContext::UserPath324 UserPath(const UserPath& other)
325 : path(other.path),
326 user(other.user)
327 {
328 }
329
GetHashCodeSecurityContext::UserPath330 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
operator =SecurityContext::UserPath340 UserPath& operator=(const UserPath& other)
341 {
342 path = other.path;
343 user = other.user;
344 return *this;
345 }
346
operator ==SecurityContext::UserPath347 bool operator==(const UserPath& other) const
348 {
349 return (path == other.path && user == other.user);
350 }
351
operator !=SecurityContext::UserPath352 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
SecurityContext()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
SecurityContext(BMessage * archive)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
~SecurityContext()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
Archive(BMessage * archive,bool deep) const490 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*
Instantiate(BMessage * archive)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
InitCheck() const576 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
AddUser(const char * name,const char * password,User ** _user)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
RemoveUser(const char * name,User ** _user)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
RemoveUser(User * user)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*
FindUser(const char * name)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
AuthenticateUser(const char * name,const char * password,User ** _user)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
CountUsers()737 SecurityContext::CountUsers()
738 {
739 ContextLocker _(this);
740 return fUsers->Size();
741 }
742
743 // GetUsers
744 status_t
GetUsers(BMessage * users)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
AddShare(const char * name,const node_ref & ref,Share ** _share)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
AddShare(const char * name,const char * path,Share ** _share)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
RemoveShare(const char * name,Share ** _share)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
RemoveShare(Share * share)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*
FindShare(const char * name)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
CountShares()900 SecurityContext::CountShares()
901 {
902 ContextLocker _(this);
903 return fShares->Size();
904 }
905
906 // GetShares
907 status_t
GetShares(BMessage * shares)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
SetNodePermissions(const node_ref & ref,User * user,Permissions permissions)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
SetNodePermissions(const char * path,User * user,Permissions permissions)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
ClearNodePermissions(const node_ref & ref,User * user)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
ClearNodePermissions(const char * path,User * user)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
GetNodePermissions(const node_ref & ref,User * user)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
GetNodePermissions(const char * path,User * user)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
GetUserSecurityContext(User * user,UserSecurityContext * userContext)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
_AddNodePath(const char * path,node_ref * _ref)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
_AddNodePath(const node_ref & ref,HashString * _path)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
_EnterNodePath(const char * path,const node_ref & ref)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
_GetNodeForPath(const char * path,node_ref * ref)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