xref: /haiku/src/add-ons/kernel/file_systems/netfs/server/SecurityContext.cpp (revision b46615c55ad2c8fe6de54412055a0713da3d610a)
1 // SecurityContext.cpp
2 
3 #include <errno.h>
4 #include <string.h>
5 #include <sys/stat.h>
6 
7 #include <AutoDeleter.h>
8 #include <AutoLocker.h>
9 #include <Entry.h>
10 #include <HashMap.h>
11 #include <Message.h>
12 #include <Path.h>
13 
14 #include "Compatibility.h"
15 #include "Node.h"
16 #include "SecurityContext.h"
17 #include "UserSecurityContext.h"
18 
19 typedef AutoLocker<SecurityContext> ContextLocker;
20 
21 // get_node_ref_for_path
22 static
23 status_t
24 get_node_ref_for_path(const char* path, node_ref* ref)
25 {
26 	if (!path || !ref)
27 		return B_BAD_VALUE;
28 	struct stat st;
29 	if (lstat(path, &st) < 0)
30 		return errno;
31 	ref->device = st.st_dev;
32 	ref->node = st.st_ino;
33 	return B_OK;
34 }
35 
36 // #pragma mark -
37 // #pragma mark ----- User -----
38 
39 // constructor
40 User::User()
41 	: BReferenceable(),
42 	  BArchivable(),
43 	  fName(),
44 	  fPassword()
45 {
46 }
47 
48 // constructor
49 User::User(BMessage* archive)
50 	: BReferenceable(),
51 	  BArchivable(archive),
52 	  fName(),
53 	  fPassword()
54 {
55 	Unarchive(archive);
56 }
57 
58 // destructor
59 User::~User()
60 {
61 }
62 
63 // Archive
64 status_t
65 User::Archive(BMessage* archive, bool deep) const
66 {
67 	if (!archive)
68 		return B_BAD_VALUE;
69 	// name
70 	status_t error = B_OK;
71 	if (error == B_OK && fName.GetLength() > 0)
72 		error = archive->AddString("name", fName.GetString());
73 	// password
74 	if (error == B_OK && fPassword.GetLength() > 0)
75 		error = archive->AddString("password", fPassword.GetString());
76 	return error;
77 }
78 
79 // Instantiate
80 BArchivable*
81 User::Instantiate(BMessage* archive)
82 {
83 	if (!validate_instantiation(archive, "User"))
84 		return NULL;
85 	return new(std::nothrow) User(archive);
86 }
87 
88 // Init
89 status_t
90 User::Init(const char* name, const char* password)
91 {
92 	if (!name)
93 		return B_BAD_VALUE;
94 	if (!fName.SetTo(name))
95 		return B_NO_MEMORY;
96 	if (password && !fPassword.SetTo(password))
97 		return B_NO_MEMORY;
98 	return B_OK;
99 }
100 
101 // InitCheck
102 status_t
103 User::InitCheck() const
104 {
105 	if (fName.GetLength() == 0)
106 		return B_NO_INIT;
107 	return B_OK;
108 }
109 
110 // Unarchive
111 status_t
112 User::Unarchive(const BMessage* archive)
113 {
114 	// name
115 	const char* name;
116 	if (archive->FindString("name", &name) != B_OK)
117 		return B_BAD_DATA;
118 	fName.SetTo(name);
119 	// password
120 	const char* password;
121 	if (archive->FindString("password", &password) == B_OK)
122 		fPassword.SetTo(password);
123 	else
124 		fPassword.Unset();
125 	return B_OK;
126 }
127 
128 // GetName
129 const char*
130 User::GetName() const
131 {
132 	return fName.GetString();
133 }
134 
135 // GetPassword
136 const char*
137 User::GetPassword() const
138 {
139 	return fPassword.GetString();
140 }
141 
142 
143 // #pragma mark -
144 // #pragma mark ----- Share -----
145 
146 // constructor
147 Share::Share()
148 	: BReferenceable(),
149 	  BArchivable(),
150 	  fName(),
151 	  fNodeRef(),
152 	  fPath()
153 {
154 }
155 
156 // constructor
157 Share::Share(BMessage* archive)
158 	: BReferenceable(),
159 	  BArchivable(archive),
160 	  fName(),
161 	  fNodeRef(),
162 	  fPath()
163 {
164 	Unarchive(archive);
165 }
166 
167 // destructor
168 Share::~Share()
169 {
170 }
171 
172 // Archive
173 status_t
174 Share::Archive(BMessage* archive, bool deep) const
175 {
176 	if (!archive)
177 		return B_BAD_VALUE;
178 	// name
179 	status_t error = B_OK;
180 	if (error == B_OK && fName.GetLength() > 0)
181 		error = archive->AddString("name", fName.GetString());
182 	// path
183 	if (error == B_OK && fPath.GetLength() > 0)
184 		error = archive->AddString("path", fPath.GetString());
185 	return error;
186 }
187 
188 // Instantiate
189 BArchivable*
190 Share::Instantiate(BMessage* archive)
191 {
192 	if (!validate_instantiation(archive, "Share"))
193 		return NULL;
194 	return new(std::nothrow) Share(archive);
195 }
196 
197 // Init
198 status_t
199 Share::Init(const char* name, const node_ref& ref, const char* path)
200 {
201 	// check params
202 	if (!name)
203 		return B_BAD_VALUE;
204 	// if a path is not given, retrieve it
205 	BPath localPath;
206 	if (!path) {
207 		entry_ref entryRef(ref.device, ref.node, ".");
208 		status_t error = localPath.SetTo(&entryRef);
209 		if (error != B_OK)
210 			return error;
211 		path = localPath.Path();
212 	}
213 	// set the attributes
214 	if (!fName.SetTo(name))
215 		return B_NO_MEMORY;
216 	if (!fPath.SetTo(path))
217 		return B_NO_MEMORY;
218 	fNodeRef = ref;
219 	return B_OK;
220 }
221 
222 // Init
223 status_t
224 Share::Init(const char* name, const char* path)
225 {
226 	if (!name || !path)
227 		return B_BAD_VALUE;
228 	node_ref nodeRef;
229 	if (get_node_ref_for_path(path, &nodeRef) != B_OK) {
230 		nodeRef.device = -1;
231 		nodeRef.node = -1;
232 	}
233 	return Init(name, nodeRef, path);
234 }
235 
236 // InitCheck
237 status_t
238 Share::InitCheck() const
239 {
240 	if (fName.GetLength() == 0 || fPath.GetLength() == 0)
241 		return B_NO_INIT;
242 	return B_OK;
243 }
244 
245 // Unarchive
246 status_t
247 Share::Unarchive(const BMessage* archive)
248 {
249 	// name
250 	const char* name = NULL;
251 	if (archive->FindString("name", &name) != B_OK)
252 		return B_BAD_DATA;
253 	// path
254 	const char* path = NULL;
255 	if (archive->FindString("path", &path) != B_OK)
256 		return B_BAD_DATA;
257 	return Init(name, path);
258 }
259 
260 // GetName
261 const char*
262 Share::GetName() const
263 {
264 	return fName.GetString();
265 }
266 
267 // DoesExist
268 bool
269 Share::DoesExist() const
270 {
271 	return (fNodeRef.device >= 0);
272 }
273 
274 // GetNodeRef
275 const node_ref&
276 Share::GetNodeRef() const
277 {
278 	return fNodeRef;
279 }
280 
281 // GetVolumeID
282 dev_t
283 Share::GetVolumeID() const
284 {
285 	return fNodeRef.device;
286 }
287 
288 // GetNodeID
289 ino_t
290 Share::GetNodeID() const
291 {
292 	return fNodeRef.node;
293 }
294 
295 // GetPath
296 const char*
297 Share::GetPath() const
298 {
299 	return fPath.GetString();
300 }
301 
302 
303 // #pragma mark -
304 // #pragma mark ----- SecurityContext -----
305 
306 // UserMap
307 struct SecurityContext::UserMap : HashMap<HashString, User*> {
308 };
309 
310 // ShareMap
311 struct SecurityContext::ShareMap : HashMap<HashString, Share*> {
312 };
313 
314 // UserPath
315 struct SecurityContext::UserPath {
316 	UserPath() {}
317 
318 	UserPath(const char* path, User* user)
319 		: path(path),
320 		  user(user)
321 	{
322 	}
323 
324 	UserPath(const UserPath& other)
325 		: path(other.path),
326 		  user(other.user)
327 	{
328 	}
329 
330 	uint32 GetHashCode() const
331 	{
332 		return path.GetHashCode() * 31 + (uint32)user;
333 	}
334 
335 	UserPath& operator=(const UserPath& other)
336 	{
337 		path = other.path;
338 		user = other.user;
339 		return *this;
340 	}
341 
342 	bool operator==(const UserPath& other) const
343 	{
344 		return (path == other.path && user == other.user);
345 	}
346 
347 	bool operator!=(const UserPath& other) const
348 	{
349 		return !(*this == other);
350 	}
351 
352 	HashString	path;
353 	User*		user;
354 };
355 
356 // PermissionMap
357 struct SecurityContext::PermissionMap
358 	: HashMap<SecurityContext::UserPath, Permissions> {
359 };
360 
361 // NodePathMap
362 struct SecurityContext::NodePathMap : HashMap<NodeRef, HashString> {
363 };
364 
365 // PathNodeMap
366 struct SecurityContext::PathNodeMap : HashMap<HashString, NodeRef> {
367 };
368 
369 // constructor
370 SecurityContext::SecurityContext()
371 	: BArchivable(),
372 	  BLocker("security context"),
373 	  fUsers(new(std::nothrow) UserMap),
374 	  fShares(new(std::nothrow) ShareMap),
375 	  fPermissions(new(std::nothrow) PermissionMap),
376 	  fNode2Path(new(std::nothrow) NodePathMap),
377 	  fPath2Node(new(std::nothrow) PathNodeMap)
378 {
379 }
380 
381 // constructor
382 SecurityContext::SecurityContext(BMessage* archive)
383 	: BArchivable(archive),
384 	  fUsers(new(std::nothrow) UserMap),
385 	  fShares(new(std::nothrow) ShareMap),
386 	  fPermissions(new(std::nothrow) PermissionMap),
387 	  fNode2Path(new(std::nothrow) NodePathMap),
388 	  fPath2Node(new(std::nothrow) PathNodeMap)
389 {
390 	if (InitCheck() != B_OK)
391 		return;
392 	status_t error = B_OK;
393 
394 	// users
395 	BMessage userArchive;
396 	for (int32 i = 0;
397 		 archive->FindMessage("users", i, &userArchive) == B_OK;
398 		 i++) {
399 		User tmpUser;
400 		error = tmpUser.Unarchive(&userArchive);
401 		if (error != B_OK)
402 			return;
403 		error = AddUser(tmpUser.GetName(), tmpUser.GetPassword());
404 		if (error != B_OK)
405 			return;
406 	}
407 
408 	// shares
409 	BMessage shareArchive;
410 	for (int32 i = 0;
411 		 archive->FindMessage("shares", i, &shareArchive) == B_OK;
412 		 i++) {
413 		Share tmpShare;
414 		error = tmpShare.Unarchive(&shareArchive);
415 		if (error != B_OK)
416 			return;
417 		error = AddShare(tmpShare.GetName(), tmpShare.GetPath());
418 		if (error != B_OK)
419 			return;
420 	}
421 
422 	// permissions
423 	BMessage permissionsArchive;
424 	if (archive->FindMessage("permissions", &permissionsArchive) != B_OK)
425 		return;
426 	#ifdef HAIKU_TARGET_PLATFORM_DANO
427 		const char* userName;
428 	#else
429 		char* userName;
430 	#endif
431 	type_code type;
432 	for (int32 userIndex = 0;
433 		 permissionsArchive.GetInfo(B_MESSAGE_TYPE, userIndex, &userName, &type)
434 		 	== B_OK;
435 		 userIndex++) {
436 		User* user = FindUser(userName);
437 		if (!user)
438 			return;
439 		BReference<User> userReference(user, true);
440 		error = permissionsArchive.FindMessage(userName, &userArchive);
441 		if (error != B_OK)
442 			return;
443 
444 		// got a user: iterate through its permissions
445 		#ifdef HAIKU_TARGET_PLATFORM_DANO
446 			const char* path;
447 		#else
448 			char* path;
449 		#endif
450 		for (int32 i = 0;
451 			 userArchive.GetInfo(B_INT32_TYPE, i, &path, &type) == B_OK;
452 			 i++) {
453 			uint32 permissions;
454 			error = userArchive.FindInt32(path, (int32*)&permissions);
455 			if (error == B_OK)
456 				error = SetNodePermissions(path, user, permissions);
457 		}
458 	}
459 }
460 
461 // destructor
462 SecurityContext::~SecurityContext()
463 {
464 	// remove all user references
465 	for (UserMap::Iterator it = fUsers->GetIterator(); it.HasNext();) {
466 		User* user = it.Next().value;
467 		user->ReleaseReference();
468 	}
469 
470 	// remove all share references
471 	for (ShareMap::Iterator it = fShares->GetIterator(); it.HasNext();) {
472 		Share* share = it.Next().value;
473 		share->ReleaseReference();
474 	}
475 
476 	delete fUsers;
477 	delete fShares;
478 	delete fPermissions;
479 	delete fNode2Path;
480 	delete fPath2Node;
481 }
482 
483 // Archive
484 status_t
485 SecurityContext::Archive(BMessage* archive, bool deep) const
486 {
487 	if (!archive)
488 		return B_BAD_VALUE;
489 	status_t error = B_OK;
490 	ContextLocker _(const_cast<SecurityContext*>(this));
491 
492 	// users
493 	int32 userCount = fUsers->Size();
494 	for (UserMap::Iterator it = fUsers->GetIterator(); it.HasNext();) {
495 		User* user = it.Next().value;
496 		BMessage userArchive;
497 		error = user->Archive(&userArchive, deep);
498 		if (error != B_OK)
499 			return error;
500 		error = archive->AddMessage("users", &userArchive);
501 		if (error != B_OK)
502 			return error;
503 	}
504 
505 	// shares
506 	for (ShareMap::Iterator it = fShares->GetIterator(); it.HasNext();) {
507 		Share* share = it.Next().value;
508 		BMessage shareArchive;
509 		error = share->Archive(&shareArchive, deep);
510 		if (error != B_OK)
511 			return error;
512 		error = archive->AddMessage("shares", &shareArchive);
513 		if (error != B_OK)
514 			return error;
515 	}
516 
517 	// permissions
518 	// we slice them per user
519 	BMessage* tmpUserArchives = new(std::nothrow) BMessage[userCount];
520 	if (!tmpUserArchives)
521 		return B_NO_MEMORY;
522 	ArrayDeleter<BMessage> deleter(tmpUserArchives);
523 	HashMap<HashKey32<User*>, BMessage*> userArchives;
524 	int32 i = 0;
525 	for (UserMap::Iterator it = fUsers->GetIterator(); it.HasNext();) {
526 		User* user = it.Next().value;
527 		error = userArchives.Put(user, tmpUserArchives + i);
528 		if (error != B_OK)
529 			return error;
530 		i++;
531 	}
532 
533 	// fill the per user archives
534 	for (PermissionMap::Iterator it = fPermissions->GetIterator();
535 		 it.HasNext();) {
536 		PermissionMap::Entry entry = it.Next();
537 		BMessage* userArchive = userArchives.Get(entry.key.user);
538 		error = userArchive->AddInt32(entry.key.path.GetString(),
539 			entry.value.GetPermissions());
540 		if (error != B_OK)
541 			return error;
542 	}
543 
544 	// put the user permissions together
545 	BMessage permissionsArchive;
546 	for (UserMap::Iterator it = fUsers->GetIterator(); it.HasNext();) {
547 		User* user = it.Next().value;
548 		error = permissionsArchive.AddMessage(user->GetName(),
549 			userArchives.Get(user));
550 		if (error != B_OK)
551 			return error;
552 	}
553 	error = archive->AddMessage("permissions", &permissionsArchive);
554 	if (error != B_OK)
555 		return error;
556 	return B_OK;
557 }
558 
559 // Instantiate
560 BArchivable*
561 SecurityContext::Instantiate(BMessage* archive)
562 {
563 	if (!validate_instantiation(archive, "SecurityContext"))
564 		return NULL;
565 	return new(std::nothrow) SecurityContext(archive);
566 }
567 
568 
569 // InitCheck
570 status_t
571 SecurityContext::InitCheck() const
572 {
573 	if (!fUsers || !fShares || !fPermissions || !fNode2Path || !fPath2Node)
574 		return B_NO_MEMORY;
575 
576 	if (fUsers->InitCheck() != B_OK)
577 		return fUsers->InitCheck();
578 
579 	if (fShares->InitCheck() != B_OK)
580 		return fShares->InitCheck();
581 
582 	if (fPermissions->InitCheck() != B_OK)
583 		return fPermissions->InitCheck();
584 
585 	if (fNode2Path->InitCheck() != B_OK)
586 		return fNode2Path->InitCheck();
587 
588 	if (fPath2Node->InitCheck() != B_OK)
589 		return fPath2Node->InitCheck();
590 
591 	return B_OK;
592 }
593 
594 // AddUser
595 //
596 // The caller gets a reference, if _user is not NULL.
597 status_t
598 SecurityContext::AddUser(const char* name, const char* password, User** _user)
599 {
600 	if (!name)
601 		return B_BAD_VALUE;
602 
603 	// check, if the user does already exist
604 	ContextLocker _(this);
605 	if (fUsers->Get(name))
606 		return B_BAD_VALUE;
607 
608 	// create a the user
609 	User* user = new(std::nothrow) User;
610 	if (!user)
611 		return B_NO_MEMORY;
612 	BReference<User> userReference(user, true);
613 	status_t error = user->Init(name, password);
614 	if (error != B_OK)
615 		return error;
616 
617 	// add the user
618 	error = fUsers->Put(name, user);
619 	if (error != B_OK)
620 		return error;
621 
622 	userReference.Detach();
623 	if (_user) {
624 		*_user = user;
625 		user->AcquireReference();
626 	}
627 	return B_OK;
628 }
629 
630 // RemoveUser
631 //
632 // The caller gets a reference, if _user is not NULL.
633 status_t
634 SecurityContext::RemoveUser(const char* name, User** _user)
635 {
636 	if (!name)
637 		return B_BAD_VALUE;
638 
639 	ContextLocker _(this);
640 
641 	// get the user
642 	User* user = FindUser(name);
643 	if (!user)
644 		return B_ENTRY_NOT_FOUND;
645 	BReference<User> userReference(user, true);
646 
647 	// remove it
648 	status_t error = RemoveUser(user);
649 	if (error == B_OK && _user) {
650 		*_user = user;
651 		user->AcquireReference();
652 	}
653 
654 	return error;
655 }
656 
657 // RemoveUser
658 status_t
659 SecurityContext::RemoveUser(User* user)
660 {
661 	if (!user)
662 		return B_BAD_VALUE;
663 
664 	ContextLocker _(this);
665 
666 	// find and remove it
667 	if (fUsers->Get(user->GetName()) != user)
668 		return B_BAD_VALUE;
669 	fUsers->Remove(user->GetName());
670 
671 	// remove all permission entries for this user
672 	for (PermissionMap::Iterator it = fPermissions->GetIterator();
673 		 it.HasNext();) {
674 		PermissionMap::Entry entry = it.Next();
675 		if (entry.key.user == user)
676 			it.Remove();
677 	}
678 
679 	// surrender our user reference
680 	user->ReleaseReference();
681 
682 	return B_OK;
683 }
684 
685 // FindUser
686 //
687 // The caller gets a reference.
688 User*
689 SecurityContext::FindUser(const char* name)
690 {
691 	if (!name)
692 		return NULL;
693 
694 	ContextLocker _(this);
695 	User* user = fUsers->Get(name);
696 	if (user)
697 		user->AcquireReference();
698 	return user;
699 }
700 
701 // AuthenticateUser
702 //
703 // The caller gets a reference.
704 status_t
705 SecurityContext::AuthenticateUser(const char* name, const char* password,
706 	User** _user)
707 {
708 	if (!_user)
709 		return B_BAD_VALUE;
710 
711 	// find user
712 	ContextLocker _(this);
713 	User* user = FindUser(name);
714 	if (!user)
715 		return B_PERMISSION_DENIED;
716 	BReference<User> userReference(user, true);
717 
718 	// check password
719 	if (user->GetPassword()) {
720 		if (!password || strcmp(user->GetPassword(), password) != 0)
721 			return B_PERMISSION_DENIED;
722 	} else if (password)
723 		return B_PERMISSION_DENIED;
724 
725 	*_user = user;
726 	userReference.Detach();
727 	return B_OK;
728 }
729 
730 // CountUsers
731 int32
732 SecurityContext::CountUsers()
733 {
734 	ContextLocker _(this);
735 	return fUsers->Size();
736 }
737 
738 // GetUsers
739 status_t
740 SecurityContext::GetUsers(BMessage* users)
741 {
742 	if (!users)
743 		return B_BAD_VALUE;
744 
745 	ContextLocker _(this);
746 
747 	// iterate through all users and add their names to the message
748 	for (UserMap::Iterator it = fUsers->GetIterator(); it.HasNext();) {
749 		User* user = it.Next().value;
750 		status_t error = users->AddString("users", user->GetName());
751 		if (error != B_OK)
752 			return error;
753 	}
754 
755 	return B_OK;
756 }
757 
758 // AddShare
759 //
760 // The caller gets a reference, if _share is not NULL.
761 status_t
762 SecurityContext::AddShare(const char* name, const node_ref& ref, Share** _share)
763 {
764 	if (!name)
765 		return B_BAD_VALUE;
766 
767 	// check, if the share does already exist
768 	ContextLocker _(this);
769 	if (fShares->Get(name))
770 		return B_BAD_VALUE;
771 
772 	// create a the share
773 	Share* share = new(std::nothrow) Share;
774 	if (!share)
775 		return B_NO_MEMORY;
776 	BReference<Share> shareReference(share, true);
777 	status_t error = share->Init(name, ref);
778 	if (error != B_OK)
779 		return error;
780 
781 	// add the share
782 	error = fShares->Put(name, share);
783 	if (error != B_OK)
784 		return error;
785 
786 	shareReference.Detach();
787 	if (_share) {
788 		*_share = share;
789 		share->AcquireReference();
790 	}
791 	return B_OK;
792 }
793 
794 // AddShare
795 //
796 // The caller gets a reference, if _share is not NULL.
797 status_t
798 SecurityContext::AddShare(const char* name, const char* path, Share** _share)
799 {
800 	if (!name)
801 		return B_BAD_VALUE;
802 
803 	// check, if the share does already exist
804 	ContextLocker _(this);
805 	if (fShares->Get(name))
806 		return B_BAD_VALUE;
807 
808 	// create a the share
809 	Share* share = new(std::nothrow) Share;
810 	if (!share)
811 		return B_NO_MEMORY;
812 	BReference<Share> shareReference(share, true);
813 	status_t error = share->Init(name, path);
814 	if (error != B_OK)
815 		return error;
816 
817 	// add the share
818 	error = fShares->Put(name, share);
819 	if (error != B_OK)
820 		return error;
821 
822 	shareReference.Detach();
823 	if (_share) {
824 		*_share = share;
825 		share->AcquireReference();
826 	}
827 	return B_OK;
828 }
829 
830 // RemoveShare
831 //
832 // The caller gets a reference, if _share is not NULL.
833 status_t
834 SecurityContext::RemoveShare(const char* name, Share** _share)
835 {
836 	if (!name)
837 		return B_BAD_VALUE;
838 
839 	ContextLocker _(this);
840 
841 	// get the share
842 	Share* share = FindShare(name);
843 	if (!share)
844 		return B_ENTRY_NOT_FOUND;
845 	BReference<Share> shareReference(share, true);
846 
847 	// remove it
848 	status_t error = RemoveShare(share);
849 	if (error == B_OK && _share) {
850 		*_share = share;
851 		share->AcquireReference();
852 	}
853 
854 	return error;
855 }
856 
857 // RemoveShare
858 status_t
859 SecurityContext::RemoveShare(Share* share)
860 {
861 	if (!share)
862 		return B_BAD_VALUE;
863 
864 	ContextLocker _(this);
865 
866 	// find and remove it
867 	if (fShares->Get(share->GetName()) != share)
868 		return B_BAD_VALUE;
869 	fShares->Remove(share->GetName());
870 
871 	// surrender our share reference
872 	share->ReleaseReference();
873 
874 	return B_OK;
875 }
876 
877 // FindShare
878 //
879 // The caller gets a reference.
880 Share*
881 SecurityContext::FindShare(const char* name)
882 {
883 	if (!name)
884 		return NULL;
885 
886 	ContextLocker _(this);
887 	Share* share = fShares->Get(name);
888 	if (share)
889 		share->AcquireReference();
890 	return share;
891 }
892 
893 // CountShares
894 int32
895 SecurityContext::CountShares()
896 {
897 	ContextLocker _(this);
898 	return fShares->Size();
899 }
900 
901 // GetShares
902 status_t
903 SecurityContext::GetShares(BMessage* shares)
904 {
905 	if (!shares)
906 		return B_BAD_VALUE;
907 
908 	ContextLocker _(this);
909 
910 	// iterate through all shares and add their names to the message
911 	for (ShareMap::Iterator it = fShares->GetIterator(); it.HasNext();) {
912 		Share* share = it.Next().value;
913 		// add name
914 		status_t error = shares->AddString("shares", share->GetName());
915 		if (error != B_OK)
916 			return error;
917 
918 		// add path
919 		error = shares->AddString("paths", share->GetPath());
920 		if (error != B_OK)
921 			return error;
922 	}
923 
924 	return B_OK;
925 }
926 
927 // SetNodePermissions
928 status_t
929 SecurityContext::SetNodePermissions(const node_ref& ref, User* user,
930 	Permissions permissions)
931 {
932 	if (!user)
933 		return B_BAD_VALUE;
934 
935 	ContextLocker _(this);
936 	// check, whether we know the user
937 	if (fUsers->Get(user->GetName()) != user)
938 		return B_BAD_VALUE;
939 
940 	HashString path;
941 	status_t error = _AddNodePath(ref, &path);
942 	if (error != B_OK)
943 		return error;
944 	return fPermissions->Put(UserPath(path.GetString(), user), permissions);
945 }
946 
947 // SetNodePermissions
948 status_t
949 SecurityContext::SetNodePermissions(const char* path, User* user,
950 	Permissions permissions)
951 {
952 	if (!user || !path)
953 		return B_BAD_VALUE;
954 
955 	ContextLocker _(this);
956 	// check, whether we know the user
957 	if (fUsers->Get(user->GetName()) != user)
958 		return B_BAD_VALUE;
959 
960 	_AddNodePath(path);
961 	return fPermissions->Put(UserPath(path, user), permissions);
962 }
963 
964 // ClearNodePermissions
965 void
966 SecurityContext::ClearNodePermissions(const node_ref& ref, User* user)
967 {
968 	ContextLocker _(this);
969 	HashString path;
970 	status_t error = _AddNodePath(ref, &path);
971 	if (error != B_OK)
972 		return;
973 
974 	if (user) {
975 		fPermissions->Remove(UserPath(path.GetString(), user));
976 	} else {
977 		for (UserMap::Iterator it = fUsers->GetIterator(); it.HasNext();)
978 			fPermissions->Remove(UserPath(path.GetString(), it.Next().value));
979 	}
980 }
981 
982 // ClearNodePermissions
983 void
984 SecurityContext::ClearNodePermissions(const char* path, User* user)
985 {
986 	if (!path)
987 		return;
988 
989 	ContextLocker _(this);
990 	_AddNodePath(path);
991 
992 	if (user) {
993 		fPermissions->Remove(UserPath(path, user));
994 	} else {
995 		for (UserMap::Iterator it = fUsers->GetIterator(); it.HasNext();)
996 			fPermissions->Remove(UserPath(path, it.Next().value));
997 	}
998 }
999 
1000 // GetNodePermissions
1001 Permissions
1002 SecurityContext::GetNodePermissions(const node_ref& ref, User* user)
1003 {
1004 	if (!user)
1005 		return Permissions();
1006 
1007 	ContextLocker _(this);
1008 	HashString path;
1009 	status_t error = _AddNodePath(ref, &path);
1010 	if (error != B_OK)
1011 		return Permissions();
1012 
1013 	return fPermissions->Get(UserPath(path.GetString(), user));
1014 }
1015 
1016 // GetNodePermissions
1017 Permissions
1018 SecurityContext::GetNodePermissions(const char* path, User* user)
1019 {
1020 	if (!user || !path)
1021 		return Permissions();
1022 
1023 	ContextLocker _(this);
1024 	_AddNodePath(path);
1025 
1026 	return fPermissions->Get(UserPath(path, user));
1027 }
1028 
1029 // GetUserSecurityContext
1030 status_t
1031 SecurityContext::GetUserSecurityContext(User* user,
1032 	UserSecurityContext* userContext)
1033 {
1034 	if (!userContext)
1035 		return B_BAD_VALUE;
1036 
1037 	status_t error = userContext->Init(user);
1038 	if (error != B_OK)
1039 		return error;
1040 
1041 	// iterate through all permission entries and add the ones whose user
1042 	// matches
1043 	ContextLocker _(this);
1044 	for (PermissionMap::Iterator it = fPermissions->GetIterator();
1045 		 it.HasNext();) {
1046 		PermissionMap::Entry entry = it.Next();
1047 		node_ref ref;
1048 		if (entry.key.user == user
1049 			&& _GetNodeForPath(entry.key.path.GetString(), &ref)) {
1050 			error = userContext->AddNode(ref.device, ref.node, entry.value);
1051 			if (error != B_OK)
1052 				return error;
1053 		}
1054 	}
1055 	return B_OK;
1056 }
1057 
1058 // _AddNodePath
1059 status_t
1060 SecurityContext::_AddNodePath(const char* path, node_ref* _ref)
1061 {
1062 	if (!fPath2Node->ContainsKey(path)) {
1063 		node_ref ref;
1064 		status_t error = get_node_ref_for_path(path, &ref);
1065 		if (error == B_OK)
1066 			error = _EnterNodePath(path, ref);
1067 		if (error != B_OK)
1068 			return error;
1069 	}
1070 
1071 	if (_ref)
1072 		*_ref = fPath2Node->Get(path);
1073 	return B_OK;
1074 }
1075 
1076 // _AddNodePath
1077 status_t
1078 SecurityContext::_AddNodePath(const node_ref& ref, HashString* _path)
1079 {
1080 	if (!fNode2Path->ContainsKey(ref)) {
1081 		BPath path;
1082 		entry_ref entryRef(ref.device, ref.node, ".");
1083 		status_t error = path.SetTo(&entryRef);
1084 		if (error == B_OK)
1085 			error = _EnterNodePath(path.Path(), ref);
1086 		if (error != B_OK)
1087 			return error;
1088 	}
1089 
1090 	if (_path)
1091 		*_path = fNode2Path->Get(ref);
1092 	return B_OK;
1093 }
1094 
1095 // _EnterNodePath
1096 status_t
1097 SecurityContext::_EnterNodePath(const char* path, const node_ref& ref)
1098 {
1099 	status_t error = fNode2Path->Put(ref, path);
1100 	if (error == B_OK) {
1101 		error = fPath2Node->Put(path, ref);
1102 		if (error != B_OK)
1103 			fNode2Path->Remove(ref);
1104 	}
1105 	return error;
1106 }
1107 
1108 // _GetNodeForPath
1109 bool
1110 SecurityContext::_GetNodeForPath(const char* path, node_ref* ref)
1111 {
1112 	if (path && fPath2Node->ContainsKey(path)) {
1113 		if (ref)
1114 			*ref = fPath2Node->Get(path);
1115 		return true;
1116 	}
1117 	return false;
1118 }
1119 
1120