xref: /haiku/src/add-ons/kernel/file_systems/netfs/server/SecurityContext.cpp (revision 151343ebc86cf0ce61a6c7789f853dff35c57e9c)
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