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