1 // NetFSServer.cpp
2
3 #include <errno.h>
4 #include <netdb.h>
5 #include <new>
6 #include <stdio.h>
7 #include <string.h>
8
9 #ifdef HAIKU_TARGET_PLATFORM_BEOS
10 # include <socket.h>
11 #else
12 # include <unistd.h>
13 # include <netinet/in.h>
14 # include <sys/socket.h>
15 #endif
16
17 #include <AutoDeleter.h>
18 #include <AutoLocker.h>
19 #include <Directory.h>
20 #include <File.h>
21 #include <FindDirectory.h>
22 #include <Node.h>
23 #include <Path.h>
24 #include <util/DoublyLinkedList.h>
25
26 #include "Connection.h"
27 #include "ConnectionListener.h"
28 #include "DebugSupport.h"
29 #include "DriverSettings.h"
30 #include "FDManager.h"
31 #include "InsecureChannel.h"
32 #include "NetFSDefs.h"
33 #include "NetFSServer.h"
34 #include "NetFSServerRosterDefs.h"
35 #include "RequestChannel.h"
36 #include "Requests.h"
37 #include "SecurityContext.h"
38 #include "StatisticsManager.h"
39 #include "TaskManager.h"
40 #include "Utils.h"
41 #include "VolumeManager.h"
42
43 static const char* kSettingsDirName = "netfs";
44 static const char* kSettingsFileName = "netfs_server";
45 static const char* kFallbackSettingsFileName = "netfs_server_fallback";
46
47 // usage
48 static const char* kUsage =
49 "Usage: netfs_server <options>\n"
50 "options:\n"
51 " --dont-broadcast - don't use broadcasting to announce the server's\n"
52 " availability to clients\n"
53 " -h, --help - print this text\n"
54 ;
55
56 // ConnectionInitializer
57 class NetFSServer::ConnectionInitializer {
58 public:
ConnectionInitializer(NetFSServer * server,ConnectionListener * connectionListener,Connection * connection)59 ConnectionInitializer(NetFSServer* server,
60 ConnectionListener* connectionListener, Connection* connection)
61 : fServer(server),
62 fConnectionListener(connectionListener),
63 fConnection(connection),
64 fThread(-1)
65 {
66 }
67
~ConnectionInitializer()68 ~ConnectionInitializer()
69 {
70 delete fConnection;
71 }
72
Run()73 status_t Run()
74 {
75 fThread = spawn_thread(&_ThreadEntry, "connection initializer",
76 B_NORMAL_PRIORITY, this);
77 if (fThread < 0)
78 return fThread;
79 resume_thread(fThread);
80 return B_OK;
81 }
82
83 private:
_ThreadEntry(void * data)84 static int32 _ThreadEntry(void* data)
85 {
86 return ((ConnectionInitializer*)data)->_Thread();
87 }
88
_Thread()89 int32 _Thread()
90 {
91 // finish connection initialization
92 User* user = NULL;
93 status_t error = fConnectionListener->FinishInitialization(
94 fConnection, fServer->GetSecurityContext(), &user);
95 // create a client connection
96 ClientConnection* clientConnection = NULL;
97 if (error == B_OK) {
98 clientConnection = new(std::nothrow) ClientConnection(fConnection,
99 fServer->GetSecurityContext(), user, fServer);
100 if (!clientConnection)
101 error = B_NO_MEMORY;
102 }
103 if (error == B_OK) {
104 fConnection = NULL; // connection belongs to client connection now
105 error = clientConnection->Init();
106 }
107 // add the client connection to the server
108 if (error == B_OK)
109 error = fServer->_AddClientConnection(clientConnection);
110 // cleanup on error
111 if (error != B_OK)
112 delete clientConnection;
113 delete this;
114 return 0;
115 }
116
117 private:
118 NetFSServer* fServer;
119 ConnectionListener* fConnectionListener;
120 Connection* fConnection;
121 thread_id fThread;
122 };
123
124
125 // ServerInfoSender
126 class NetFSServer::ServerInfoSender : public Task {
127 public:
ServerInfoSender(int socket,const ServerInfo & serverInfo)128 ServerInfoSender(int socket, const ServerInfo& serverInfo)
129 : Task("server info sender"),
130 fChannel(new(std::nothrow) InsecureChannel(socket)),
131 fServerInfo(serverInfo)
132 {
133 if (!fChannel)
134 closesocket(socket);
135 }
136
~ServerInfoSender()137 ~ServerInfoSender()
138 {
139 delete fChannel;
140 }
141
Init()142 status_t Init()
143 {
144 if (!fChannel)
145 return B_NO_MEMORY;
146
147 return B_OK;
148 }
149
Stop()150 virtual void Stop()
151 {
152 if (fChannel)
153 fChannel->Close();
154 }
155
Execute()156 virtual status_t Execute()
157 {
158 if (!fChannel) {
159 SetDone(true);
160 return B_NO_INIT;
161 }
162
163 RequestChannel requestChannel(fChannel);
164
165 // create the server info request
166 ServerInfoRequest request;
167 request.serverInfo = fServerInfo;
168
169 // send the request
170 status_t error = requestChannel.SendRequest(&request);
171 if (error != B_OK) {
172 ERROR("ServerInfoSender: ERROR: Failed to send request: %s\n",
173 strerror(error));
174 }
175
176 SetDone(true);
177 return B_OK;
178 }
179
180 private:
181 Channel* fChannel;
182 ServerInfo fServerInfo;
183 };
184
185
186 // NetFSServer
187
188 // constructor
NetFSServer(bool useBroadcasting)189 NetFSServer::NetFSServer(bool useBroadcasting)
190 :
191 BApplication(kNetFSServerSignature),
192 fSecurityContext(NULL),
193 fConnectionListenerFactory(),
194 fConnectionListener(NULL),
195 fLock("netfs server"),
196 fClientConnections(),
197 fVolumeManager(NULL),
198 fClosedConnections(),
199 fClosedConnectionsSemaphore(-1),
200 fConnectionListenerThread(-1),
201 fConnectionDeleter(-1),
202 fBroadcaster(-1),
203 fBroadcastingSocket(-1),
204 fBroadcasterSemaphore(-1),
205 fServerInfoConnectionListener(-1),
206 fServerInfoConnectionListenerSocket(-1),
207 fServerInfoUpdated(0),
208 fUseBroadcasting(useBroadcasting),
209 fTerminating(false)
210 {
211 }
212
213 // destructor
~NetFSServer()214 NetFSServer::~NetFSServer()
215 {
216 fTerminating = true;
217 // stop the connection listener
218 if (fConnectionListener)
219 fConnectionListener->StopListening();
220 if (fConnectionListenerThread >= 0) {
221 int32 result;
222 wait_for_thread(fConnectionListenerThread, &result);
223 }
224 delete fConnectionListener;
225
226 // delete the broadcaster semaphore
227 if (fBroadcasterSemaphore >= 0)
228 delete_sem(fBroadcasterSemaphore);
229
230 // terminate the broadcaster
231 if (fBroadcaster >= 0) {
232 safe_closesocket(fBroadcastingSocket);
233
234 // interrupt the thread in case it is currently snoozing
235 suspend_thread(fBroadcaster);
236 int32 result;
237 wait_for_thread(fBroadcaster, &result);
238 }
239
240 // terminate the server info connection listener
241 _ExitServerInfoConnectionListener();
242
243 // terminate the connection deleter
244 if (fClosedConnectionsSemaphore >= 0)
245 delete_sem(fClosedConnectionsSemaphore);
246 if (fConnectionDeleter >= 0) {
247 int32 result;
248 wait_for_thread(fConnectionDeleter, &result);
249 }
250
251 // blow away all remaining connections
252 AutoLocker<Locker> _(fLock);
253 // open connections
254 for (int32 i = 0;
255 ClientConnection* connection
256 = (ClientConnection*)fClientConnections.ItemAt(i);
257 i++) {
258 connection->Close();
259 delete connection;
260 }
261
262 // closed connections
263 for (int32 i = 0;
264 ClientConnection* connection
265 = (ClientConnection*)fClosedConnections.ItemAt(i);
266 i++) {
267 delete connection;
268 }
269 VolumeManager::DeleteDefault();
270 FDManager::DeleteDefault();
271 delete fSecurityContext;
272 }
273
274 // Init
275 status_t
Init()276 NetFSServer::Init()
277 {
278 // init the settings
279 status_t error = _InitSettings();
280 if (error != B_OK)
281 return error;
282
283 // create the FD manager
284 error = FDManager::CreateDefault();
285 if (error != B_OK)
286 return error;
287
288 // create the volume manager
289 error = VolumeManager::CreateDefault();
290 if (error != B_OK)
291 return error;
292 fVolumeManager = VolumeManager::GetDefault();
293
294 // create a connection listener
295 // error = fConnectionListenerFactory.CreateConnectionListener(
296 // "port", NULL, &fConnectionListener);
297 error = fConnectionListenerFactory.CreateConnectionListener(
298 "insecure", NULL, &fConnectionListener);
299 if (error != B_OK)
300 return error;
301
302 // spawn the connection listener thread
303 fConnectionListenerThread = spawn_thread(&_ConnectionListenerEntry,
304 "connection listener", B_NORMAL_PRIORITY, this);
305 if (fConnectionListenerThread < 0)
306 return fConnectionListenerThread;
307
308 // create the closed connections semaphore
309 fClosedConnectionsSemaphore = create_sem(0, "closed connections");
310 if (fClosedConnectionsSemaphore < 0)
311 return fClosedConnectionsSemaphore;
312
313 // spawn the connection deleter
314 fConnectionDeleter = spawn_thread(&_ConnectionDeleterEntry,
315 "connection deleter", B_NORMAL_PRIORITY, this);
316 if (fConnectionDeleter < 0)
317 return fConnectionDeleter;
318
319 // init the server info connection listener
320 error = _InitServerInfoConnectionListener();
321 if (error != B_OK)
322 return error;
323
324 // create the broadcaster semaphore
325 fBroadcasterSemaphore = create_sem(0, "broadcaster snooze");
326
327 // spawn the broadcaster
328 if (fUseBroadcasting) {
329 fBroadcaster = spawn_thread(&_BroadcasterEntry, "broadcaster",
330 B_NORMAL_PRIORITY, this);
331 if (fBroadcaster < 0) {
332 WARN("NetFSServer::Init(): Failed to spawn broadcaster thread "
333 "(%s). Continuing anyway.\n", strerror(fBroadcaster));
334 }
335 }
336 return B_OK;
337 }
338
339 // Run
340 thread_id
Run()341 NetFSServer::Run()
342 {
343 // start the connection listener
344 resume_thread(fConnectionListenerThread);
345
346 // start the connection deleter
347 resume_thread(fConnectionDeleter);
348
349 // start the server info connection listener
350 resume_thread(fServerInfoConnectionListener);
351
352 // start the broadcaster
353 resume_thread(fBroadcaster);
354
355 return BApplication::Run();
356 }
357
358 // MessageReceived
359 void
MessageReceived(BMessage * message)360 NetFSServer::MessageReceived(BMessage* message)
361 {
362 switch (message->what) {
363 case NETFS_REQUEST_GET_MESSENGER:
364 {
365 // for the time being we process all requests here
366 BMessage reply;
367 reply.AddMessenger("messenger", be_app_messenger);
368 _SendReply(message, &reply);
369 break;
370 }
371
372 case NETFS_REQUEST_ADD_USER:
373 {
374 // get user name and password
375 const char* user;
376 const char* password;
377 if (message->FindString("user", &user) != B_OK) {
378 _SendReply(message, B_BAD_VALUE);
379 break;
380 }
381 if (message->FindString("password", &password) != B_OK)
382 password = NULL;
383
384 // add the user
385 status_t error = fSecurityContext->AddUser(user, password);
386 _SendReply(message, error);
387 break;
388 }
389
390 case NETFS_REQUEST_REMOVE_USER:
391 {
392 // get user name
393 const char* userName;
394 if (message->FindString("user", &userName) != B_OK) {
395 _SendReply(message, B_BAD_VALUE);
396 break;
397 }
398
399 // remove the user
400 User* user;
401 status_t error = fSecurityContext->RemoveUser(userName, &user);
402 if (error == B_OK) {
403 // propagate the information to the client connections
404 AutoLocker<Locker> _(fLock);
405 for (int32 i = 0;
406 ClientConnection* connection
407 = (ClientConnection*)fClientConnections.ItemAt(i);
408 i++) {
409 connection->UserRemoved(user);
410 }
411
412 user->ReleaseReference();
413 }
414
415 _SendReply(message, error);
416 break;
417 }
418
419 case NETFS_REQUEST_GET_USERS:
420 {
421 // get the users
422 BMessage reply;
423 BMessage users;
424 status_t error = fSecurityContext->GetUsers(&users);
425 if (error == B_OK)
426 error = reply.AddMessage("users", &users);
427
428 if (error == B_OK)
429 _SendReply(message, &reply);
430 else
431 _SendReply(message, error);
432 break;
433 }
434
435 case NETFS_REQUEST_GET_USER_STATISTICS:
436 {
437 // get user name
438 const char* userName;
439 if (message->FindString("user", &userName) != B_OK) {
440 _SendReply(message, B_BAD_VALUE);
441 break;
442 }
443
444 // get the user
445 User* user = fSecurityContext->FindUser(userName);
446 if (!user) {
447 _SendReply(message, B_ENTRY_NOT_FOUND);
448 break;
449 }
450 BReference<User> userReference(user, true);
451
452 // get the statistics
453 BMessage statistics;
454 status_t error = StatisticsManager::GetDefault()
455 ->GetUserStatistics(user, &statistics);
456
457 // prepare the reply
458 BMessage reply;
459 if (error == B_OK)
460 error = reply.AddMessage("statistics", &statistics);
461
462 // send the reply
463 if (error == B_OK)
464 _SendReply(message, &reply);
465 else
466 _SendReply(message, error);
467 break;
468 }
469
470 case NETFS_REQUEST_ADD_SHARE:
471 {
472 // get share name and path
473 const char* share;
474 const char* path;
475 if (message->FindString("share", &share) != B_OK
476 || message->FindString("path", &path) != B_OK) {
477 _SendReply(message, B_BAD_VALUE);
478 break;
479 }
480
481 // add the share
482 status_t error = fSecurityContext->AddShare(share, path);
483
484 if (error == B_OK)
485 _ServerInfoUpdated();
486
487 _SendReply(message, error);
488 break;
489 }
490
491 case NETFS_REQUEST_REMOVE_SHARE:
492 {
493 // get share name
494 const char* shareName;
495 if (message->FindString("share", &shareName) != B_OK) {
496 _SendReply(message, B_BAD_VALUE);
497 break;
498 }
499
500 // remove the share
501 Share* share;
502 status_t error = fSecurityContext->RemoveShare(shareName, &share);
503 if (error == B_OK) {
504 // propagate the information to the client connections
505 AutoLocker<Locker> _(fLock);
506 for (int32 i = 0;
507 ClientConnection* connection
508 = (ClientConnection*)fClientConnections.ItemAt(i);
509 i++) {
510 connection->ShareRemoved(share);
511 }
512
513 share->ReleaseReference();
514 }
515
516 if (error == B_OK)
517 _ServerInfoUpdated();
518
519 _SendReply(message, error);
520 break;
521 }
522
523 case NETFS_REQUEST_GET_SHARES:
524 {
525 // get the shares
526 BMessage reply;
527 BMessage shares;
528 status_t error = fSecurityContext->GetShares(&shares);
529 if (error == B_OK)
530 error = reply.AddMessage("shares", &shares);
531
532 if (error == B_OK)
533 _SendReply(message, &reply);
534 else
535 _SendReply(message, error);
536 break;
537 }
538
539 case NETFS_REQUEST_GET_SHARE_USERS:
540 {
541 // get share name
542 const char* shareName;
543 if (message->FindString("share", &shareName) != B_OK) {
544 _SendReply(message, B_BAD_VALUE);
545 break;
546 }
547
548 AutoLocker<Locker> securityContextLocker(fSecurityContext);
549
550 // get the share
551 Share* share = fSecurityContext->FindShare(shareName);
552 if (!share) {
553 _SendReply(message, B_ENTRY_NOT_FOUND);
554 break;
555 }
556 BReference<Share> shareReference(share, true);
557
558 // get all users
559 BMessage allUsers;
560 status_t error = fSecurityContext->GetUsers(&allUsers);
561 if (error != B_OK) {
562 _SendReply(message, error);
563 break;
564 }
565
566 // filter the users with mount permission
567 BMessage users;
568 const char* userName;
569 for (int32 i = 0;
570 allUsers.FindString("users", i, &userName) == B_OK;
571 i++) {
572 if (User* user = fSecurityContext->FindUser(userName)) {
573 // get the user's permissions
574 Permissions permissions = fSecurityContext
575 ->GetNodePermissions(share->GetPath(), user);
576 user->ReleaseReference();
577
578 // add the user, if they have the permission to mount the
579 // share
580 if (permissions.ImpliesMountSharePermission()) {
581 error = users.AddString("users", userName);
582 if (error != B_OK) {
583 _SendReply(message, error);
584 break;
585 }
586 }
587 }
588 }
589
590 securityContextLocker.Unlock();
591
592 // prepare the reply
593 BMessage reply;
594 if (error == B_OK)
595 error = reply.AddMessage("users", &users);
596
597 // send the reply
598 if (error == B_OK)
599 _SendReply(message, &reply);
600 else
601 _SendReply(message, error);
602 break;
603 }
604
605 case NETFS_REQUEST_GET_SHARE_STATISTICS:
606 {
607 // get share name
608 const char* shareName;
609 if (message->FindString("share", &shareName) != B_OK) {
610 _SendReply(message, B_BAD_VALUE);
611 break;
612 }
613
614 // get the share
615 Share* share = fSecurityContext->FindShare(shareName);
616 if (!share) {
617 _SendReply(message, B_ENTRY_NOT_FOUND);
618 break;
619 }
620 BReference<Share> shareReference(share, true);
621
622 // get the statistics
623 BMessage statistics;
624 status_t error = StatisticsManager::GetDefault()
625 ->GetShareStatistics(share, &statistics);
626
627 // prepare the reply
628 BMessage reply;
629 if (error == B_OK)
630 error = reply.AddMessage("statistics", &statistics);
631
632 // send the reply
633 if (error == B_OK)
634 _SendReply(message, &reply);
635 else
636 _SendReply(message, error);
637 break;
638 }
639
640 case NETFS_REQUEST_SET_USER_PERMISSIONS:
641 {
642 // get share and user name, and the permissions
643 const char* shareName;
644 const char* userName;
645 uint32 permissions;
646 if (message->FindString("share", &shareName) != B_OK
647 || message->FindString("user", &userName) != B_OK
648 || message->FindInt32("permissions", (int32*)&permissions)
649 != B_OK) {
650 _SendReply(message, B_BAD_VALUE);
651 break;
652 }
653
654 // get the share and the user
655 Share* share = fSecurityContext->FindShare(shareName);
656 User* user = fSecurityContext->FindUser(userName);
657 BReference<Share> shareReference(share);
658 BReference<User> userReference(user);
659 if (!share || !user) {
660 _SendReply(message, B_ENTRY_NOT_FOUND);
661 break;
662 }
663
664 // set the permissions
665 status_t error = B_OK;
666 if (permissions == 0) {
667 fSecurityContext->ClearNodePermissions(share->GetPath(), user);
668 } else {
669 error = fSecurityContext->SetNodePermissions(share->GetPath(),
670 user, permissions);
671 }
672
673 if (error == B_OK) {
674 // propagate the information to the client connections
675 AutoLocker<Locker> _(fLock);
676 for (int32 i = 0;
677 ClientConnection* connection
678 = (ClientConnection*)fClientConnections.ItemAt(i);
679 i++) {
680 connection->UserPermissionsChanged(share, user,
681 permissions);
682 }
683 }
684
685 _SendReply(message, error);
686 break;
687 }
688
689 case NETFS_REQUEST_GET_USER_PERMISSIONS:
690 {
691 // get share and user name
692 const char* shareName;
693 const char* userName;
694 if (message->FindString("share", &shareName) != B_OK
695 || message->FindString("user", &userName) != B_OK) {
696 _SendReply(message, B_BAD_VALUE);
697 break;
698 }
699
700 // get the share and the user
701 Share* share = fSecurityContext->FindShare(shareName);
702 User* user = fSecurityContext->FindUser(userName);
703 BReference<Share> shareReference(share);
704 BReference<User> userReference(user);
705 if (!share || !user) {
706 _SendReply(message, B_ENTRY_NOT_FOUND);
707 break;
708 }
709
710 // get the permissions
711 Permissions permissions = fSecurityContext->GetNodePermissions(
712 share->GetPath(), user);
713
714 // prepare the reply
715 BMessage reply;
716 status_t error = reply.AddInt32("permissions",
717 (int32)permissions.GetPermissions());
718
719 // send it
720 if (error == B_OK)
721 _SendReply(message, &reply);
722 else
723 _SendReply(message, error);
724 break;
725 }
726
727 case NETFS_REQUEST_SAVE_SETTINGS:
728 {
729 status_t error = _SaveSettings();
730
731 // send a reply
732 _SendReply(message, error);
733 break;
734 }
735 }
736 }
737
738 // GetVolumeManager
739 VolumeManager*
GetVolumeManager() const740 NetFSServer::GetVolumeManager() const
741 {
742 return fVolumeManager;
743 }
744
745 // GetSecurityContext
746 SecurityContext*
GetSecurityContext() const747 NetFSServer::GetSecurityContext() const
748 {
749 return fSecurityContext;
750 }
751
752 // _AddClientConnection
753 status_t
_AddClientConnection(ClientConnection * clientConnection)754 NetFSServer::_AddClientConnection(ClientConnection* clientConnection)
755 {
756 if (!clientConnection)
757 return B_BAD_VALUE;
758 AutoLocker<Locker> locker(fLock);
759 if (!fClientConnections.AddItem(clientConnection))
760 return B_NO_MEMORY;
761 return B_OK;
762 }
763
764 // ClientConnectionClosed
765 void
ClientConnectionClosed(ClientConnection * connection,bool broken)766 NetFSServer::ClientConnectionClosed(ClientConnection* connection, bool broken)
767 {
768 PRINT("NetFSServer::ClientConnectionClosed(%d)\n", broken);
769 if (!connection)
770 return;
771 AutoLocker<Locker> locker(fLock);
772 if (!fClientConnections.RemoveItem(connection))
773 return;
774 if (!fClosedConnections.AddItem(connection)) {
775 // out of memory: Try to delete the connection right now.,
776 // There's a certain chance that we'll access free()d memory in the
777 // process, but things are apparently bad enough, anyway.
778 locker.Unlock();
779 delete connection;
780 return;
781 }
782 release_sem(fClosedConnectionsSemaphore);
783 }
784
785 // _LoadSecurityContext
786 status_t
_LoadSecurityContext(SecurityContext ** _securityContext)787 NetFSServer::_LoadSecurityContext(SecurityContext** _securityContext)
788 {
789 // create a security context
790 SecurityContext* securityContext = new(std::nothrow) SecurityContext;
791 if (!securityContext)
792 return B_NO_MEMORY;
793 status_t error = securityContext->InitCheck();
794 if (error != B_OK) {
795 delete securityContext;
796 return error;
797 }
798 ObjectDeleter<SecurityContext> securityContextDeleter(securityContext);
799
800 // load the fallback settings, if present
801 BPath path;
802 DriverSettings settings;
803
804 if (_GetSettingsDirPath(&path, false) == B_OK
805 && path.Append(kFallbackSettingsFileName) == B_OK
806 && settings.Load(path.Path()) == B_OK) {
807 // load users
808 DriverParameter parameter;
809 for (DriverParameterIterator it = settings.GetParameterIterator("user");
810 it.GetNext(¶meter);) {
811 const char* userName = parameter.ValueAt(0);
812 const char* password = parameter.GetParameterValue("password");
813 if (!userName) {
814 WARN("Skipping nameless user settings entry.\n");
815 continue;
816 }
817 // PRINT(("user: %s, password: %s\n", parameter.ValueAt(0),
818 // parameter.GetParameterValue("password")));
819 error = securityContext->AddUser(userName, password);
820 if (error != B_OK)
821 ERROR("ERROR: Failed to add user `%s'\n", userName);
822 }
823
824 // load shares
825 for (DriverParameterIterator it = settings.GetParameterIterator("share");
826 it.GetNext(¶meter);) {
827 const char* shareName = parameter.ValueAt(0);
828 const char* path = parameter.GetParameterValue("path");
829 if (!shareName || !path) {
830 WARN("settings: Skipping invalid share settings entry (no name"
831 " or no path).\n");
832 continue;
833 }
834 // PRINT(("share: %s, path: %s\n", parameter.ValueAt(0),
835 // parameter.GetParameterValue("path")));
836 Share* share;
837 error = securityContext->AddShare(shareName, path, &share);
838 if (error != B_OK) {
839 ERROR("ERROR: Failed to add share `%s'\n", shareName);
840 continue;
841 }
842 BReference<Share> shareReference(share, true);
843 DriverParameter userParameter;
844 // iterate through the share users
845 for (DriverParameterIterator userIt
846 = parameter.GetParameterIterator("user");
847 userIt.GetNext(&userParameter);) {
848 const char* userName = userParameter.ValueAt(0);
849 // PRINT((" user: %s\n", userName));
850 User* user = securityContext->FindUser(userName);
851 if (!user) {
852 ERROR("ERROR: Undefined user `%s'.\n", userName);
853 continue;
854 }
855 BReference<User> userReference(user, true);
856 DriverParameter permissionsParameter;
857 if (!userParameter.FindParameter("permissions",
858 &permissionsParameter)) {
859 continue;
860 }
861 Permissions permissions;
862 for (int32 i = 0; i < permissionsParameter.CountValues(); i++) {
863 const char* permission = permissionsParameter.ValueAt(i);
864 // PRINT((" permission: %s\n", permission));
865 if (strcmp(permission, "mount") == 0) {
866 permissions.AddPermissions(MOUNT_SHARE_PERMISSION);
867 } else if (strcmp(permission, "query") == 0) {
868 permissions.AddPermissions(QUERY_SHARE_PERMISSION);
869 } else if (strcmp(permission, "read") == 0) {
870 permissions.AddPermissions(READ_PERMISSION
871 | READ_DIR_PERMISSION | RESOLVE_DIR_ENTRY_PERMISSION);
872 } else if (strcmp(permission, "write") == 0) {
873 permissions.AddPermissions(WRITE_PERMISSION
874 | WRITE_DIR_PERMISSION);
875 } else if (strcmp(permission, "all") == 0) {
876 permissions.AddPermissions(ALL_PERMISSIONS);
877 }
878 }
879 error = securityContext->SetNodePermissions(share->GetPath(), user,
880 permissions);
881 if (error != B_OK) {
882 ERROR("ERROR: Failed to set permissions for share `%s'\n",
883 share->GetName());
884 }
885 }
886 }
887 }
888
889 securityContextDeleter.Detach();
890 *_securityContext = securityContext;
891 return B_OK;
892 }
893
894 // _InitSettings
895 status_t
_InitSettings()896 NetFSServer::_InitSettings()
897 {
898 status_t error = _LoadSettings();
899 if (error != B_OK) {
900 WARN("NetFSServer::_InitSettings(): WARNING: Failed to load settings "
901 "file: %s - falling back to driver settings.\n", strerror(error));
902
903 // fall back to the driver settings file
904 error = _LoadSecurityContext(&fSecurityContext);
905 if (error != B_OK) {
906 WARN("NetFSServer::_InitSettings(): WARNING: Failed to load "
907 "settings from driver settings: %s\n", strerror(error));
908
909 // use defaults
910 // create a security context
911 fSecurityContext = new(std::nothrow) SecurityContext;
912 if (!fSecurityContext)
913 return B_NO_MEMORY;
914 error = fSecurityContext->InitCheck();
915 if (error != B_OK)
916 return error;
917 }
918 }
919
920 return B_OK;
921 }
922
923 // _LoadSettings
924 status_t
_LoadSettings()925 NetFSServer::_LoadSettings()
926 {
927 // get the settings file path
928 BPath filePath;
929 status_t error = _GetSettingsFilePath(&filePath, false);
930 if (error != B_OK)
931 RETURN_ERROR(error);
932
933 // if existing load the settings
934 BEntry bEntry;
935 if (FDManager::SetEntry(&bEntry, filePath.Path()) != B_OK
936 || !bEntry.Exists()) {
937 return B_ENTRY_NOT_FOUND;
938 }
939
940 // open the settings file
941 BFile file;
942 error = FDManager::SetFile(&file, filePath.Path(), B_READ_ONLY);
943 if (error != B_OK)
944 RETURN_ERROR(error);
945
946 // read the settings
947 BMessage settings;
948 error = settings.Unflatten(&file);
949 if (error != B_OK)
950 RETURN_ERROR(error);
951
952 // get the security context archive
953 BMessage securityContextArchive;
954 error = settings.FindMessage("security context",
955 &securityContextArchive);
956 if (error != B_OK)
957 RETURN_ERROR(error);
958
959 // create a security context
960 SecurityContext* securityContext
961 = new(std::nothrow) SecurityContext(&securityContextArchive);
962 if (!securityContext)
963 RETURN_ERROR(B_NO_MEMORY);
964 ObjectDeleter<SecurityContext> securityContextDeleter(securityContext);
965 error = securityContext->InitCheck();
966 if (error != B_OK)
967 RETURN_ERROR(error);
968
969 // set it
970 delete fSecurityContext;
971 fSecurityContext = securityContext;
972 securityContextDeleter.Detach();
973
974 return B_OK;
975 }
976
977 // _SaveSettings
978 status_t
_SaveSettings()979 NetFSServer::_SaveSettings()
980 {
981 AutoLocker<Locker> locker(fSecurityContext);
982
983 // create the settings archive
984 BMessage settings;
985
986 // archive the security context
987 BMessage securityContextArchive;
988 status_t error = fSecurityContext->Archive(&securityContextArchive, true);
989 if (error != B_OK)
990 RETURN_ERROR(error);
991
992 // add it to the settings archive
993 error = settings.AddMessage("security context", &securityContextArchive);
994 if (error != B_OK)
995 RETURN_ERROR(error);
996
997 // open the settings file
998 BPath filePath;
999 error = _GetSettingsFilePath(&filePath, true);
1000 if (error != B_OK)
1001 RETURN_ERROR(error);
1002 BFile file;
1003 error = FDManager::SetFile(&file, filePath.Path(),
1004 B_READ_WRITE | B_CREATE_FILE | B_ERASE_FILE);
1005 if (error != B_OK)
1006 RETURN_ERROR(error);
1007
1008 // write to the settings file
1009 error = settings.Flatten(&file);
1010 if (error != B_OK)
1011 RETURN_ERROR(error);
1012
1013 return B_OK;
1014 }
1015
1016 // _GetSettingsDirPath
1017 status_t
_GetSettingsDirPath(BPath * path,bool create)1018 NetFSServer::_GetSettingsDirPath(BPath* path, bool create)
1019 {
1020 // get the user settings directory
1021 BPath settingsDir;
1022 status_t error = find_directory(B_USER_SETTINGS_DIRECTORY, &settingsDir,
1023 create);
1024 if (error != B_OK)
1025 RETURN_ERROR(error);
1026
1027 // create our subdir, if not existing and desired
1028 error = path->SetTo(settingsDir.Path(), kSettingsDirName);
1029 if (error != B_OK)
1030 RETURN_ERROR(error);
1031 BEntry bEntry;
1032 if (create
1033 && (FDManager::SetEntry(&bEntry, settingsDir.Path()) != B_OK
1034 || !bEntry.Exists())) {
1035 error = create_directory(path->Path(), S_IRWXU | S_IRWXG | S_IRWXO);
1036 if (error != B_OK)
1037 RETURN_ERROR(error);
1038 }
1039
1040 return B_OK;
1041 }
1042
1043 // _GetSettingsFilePath
1044 status_t
_GetSettingsFilePath(BPath * path,bool createDir)1045 NetFSServer::_GetSettingsFilePath(BPath* path, bool createDir)
1046 {
1047 // get settings dir
1048 BPath dirPath;
1049 status_t error = _GetSettingsDirPath(&dirPath, createDir);
1050 if (error != B_OK)
1051 return error;
1052
1053 // construct the file path
1054 return path->SetTo(dirPath.Path(), kSettingsFileName);
1055 }
1056
1057 // _InitServerInfoConnectionListener
1058 status_t
_InitServerInfoConnectionListener()1059 NetFSServer::_InitServerInfoConnectionListener()
1060 {
1061 // spawn the listener thread
1062 fServerInfoConnectionListener = spawn_thread(
1063 &_ServerInfoConnectionListenerEntry,
1064 "server info connection listener", B_NORMAL_PRIORITY, this);
1065 if (fServerInfoConnectionListener < 0)
1066 return fServerInfoConnectionListener;
1067 // create a listener socket
1068 fServerInfoConnectionListenerSocket = socket(AF_INET, SOCK_STREAM, 0);
1069 if (fServerInfoConnectionListenerSocket < 0)
1070 return errno;
1071 // bind it to the port
1072 sockaddr_in addr;
1073 addr.sin_family = AF_INET;
1074 addr.sin_port = htons(kDefaultServerInfoPort);
1075 addr.sin_addr.s_addr = INADDR_ANY;
1076 if (bind(fServerInfoConnectionListenerSocket, (sockaddr*)&addr,
1077 sizeof(addr)) < 0) {
1078 return errno;
1079 }
1080 // start listening
1081 if (listen(fServerInfoConnectionListenerSocket, 5) < 0)
1082 return errno;
1083 return B_OK;
1084 }
1085
1086 // _ExitServerInfoConnectionListener
1087 void
_ExitServerInfoConnectionListener()1088 NetFSServer::_ExitServerInfoConnectionListener()
1089 {
1090 // close the socket
1091 safe_closesocket(fServerInfoConnectionListenerSocket);
1092 // wait for the listener
1093 if (fServerInfoConnectionListener >= 0) {
1094 int32 result;
1095 wait_for_thread(fServerInfoConnectionListener, &result);
1096 }
1097 }
1098
1099 // _ConnectionListenerEntry
1100 int32
_ConnectionListenerEntry(void * data)1101 NetFSServer::_ConnectionListenerEntry(void* data)
1102 {
1103 return ((NetFSServer*)data)->_ConnectionListener();
1104 }
1105
1106 // _ConnectionListener
1107 int32
_ConnectionListener()1108 NetFSServer::_ConnectionListener()
1109 {
1110 // start listening for connections
1111 Connection* connection = NULL;
1112 status_t error = B_OK;
1113 do {
1114 error = fConnectionListener->Listen(&connection);
1115 if (error == B_OK) {
1116 ConnectionInitializer* initializer
1117 = new(std::nothrow) ConnectionInitializer(this, fConnectionListener,
1118 connection);
1119 if (initializer) {
1120 if (initializer->Run() != B_OK) {
1121 ERROR("Failed to run connection initializer.\n")
1122 delete initializer;
1123 }
1124 } else {
1125 ERROR("Failed to create connection initializer.\n")
1126 delete connection;
1127 }
1128
1129 }
1130 } while (error == B_OK && !fTerminating);
1131
1132 return 0;
1133 }
1134
1135 // _ConnectionDeleterEntry
1136 int32
_ConnectionDeleterEntry(void * data)1137 NetFSServer::_ConnectionDeleterEntry(void* data)
1138 {
1139 return ((NetFSServer*)data)->_ConnectionDeleter();
1140 }
1141
1142 // _ConnectionDeleter
1143 int32
_ConnectionDeleter()1144 NetFSServer::_ConnectionDeleter()
1145 {
1146 while (!fTerminating) {
1147 status_t error = acquire_sem(fClosedConnectionsSemaphore);
1148 ClientConnection* connection = NULL;
1149 if (error == B_OK) {
1150 AutoLocker<Locker> _(fLock);
1151 connection = (ClientConnection*)fClosedConnections.RemoveItem((int32)0);
1152 }
1153 if (connection)
1154 delete connection;
1155 }
1156 return 0;
1157 }
1158
1159 // _BroadcasterEntry
1160 int32
_BroadcasterEntry(void * data)1161 NetFSServer::_BroadcasterEntry(void* data)
1162 {
1163 return ((NetFSServer*)data)->_Broadcaster();
1164 }
1165
1166 // _Broadcaster
1167 int32
_Broadcaster()1168 NetFSServer::_Broadcaster()
1169 {
1170 // create the socket
1171 fBroadcastingSocket = socket(AF_INET, SOCK_DGRAM, 0);
1172 if (fBroadcastingSocket < 0) {
1173 WARN("NetFSServer::_Broadcaster(): WARN: Failed to init broadcasting: "
1174 "%s.\n", strerror(errno));
1175 return errno;
1176 }
1177
1178 // set the socket broadcast option
1179 #ifndef HAIKU_TARGET_PLATFORM_BEOS
1180 int soBroadcastValue = 1;
1181 if (setsockopt(fBroadcastingSocket, SOL_SOCKET, SO_BROADCAST,
1182 &soBroadcastValue, sizeof(soBroadcastValue)) < 0) {
1183 WARN("NetFSServer::_Broadcaster(): WARN: Failed to set "
1184 "SO_BROADCAST on socket: %s.\n", strerror(errno));
1185 }
1186 #endif
1187
1188 // prepare the broadcast message
1189 BroadcastMessage message;
1190 message.magic = B_HOST_TO_BENDIAN_INT32(BROADCAST_MESSAGE_MAGIC);
1191 message.protocolVersion = B_HOST_TO_BENDIAN_INT32(NETFS_PROTOCOL_VERSION);
1192
1193 bool update = false;
1194 while (!fTerminating) {
1195 // set tick/update
1196 uint32 messageCode = (update ? BROADCAST_MESSAGE_SERVER_UPDATE
1197 : BROADCAST_MESSAGE_SERVER_TICK);
1198 message.message = B_HOST_TO_BENDIAN_INT32(messageCode);
1199
1200 // send broadcasting message
1201 sockaddr_in addr;
1202 addr.sin_family = AF_INET;
1203 addr.sin_port = htons(kDefaultBroadcastPort);
1204 addr.sin_addr.s_addr = INADDR_BROADCAST;
1205 int addrSize = sizeof(addr);
1206 ssize_t bytesSent = sendto(fBroadcastingSocket, &message,
1207 sizeof(message), 0, (sockaddr*)&addr, addrSize);
1208 if (bytesSent < 0) {
1209 WARN("NetFSServer::_Broadcaster(): WARN: sending failed: %s.\n",
1210 strerror(errno));
1211 return errno;
1212 }
1213
1214 // snooze a bit
1215 // we snooze a minimal interval to avoid shooting updates like a
1216 // machine gun
1217 snooze(kMinBroadcastingInterval);
1218 bigtime_t remainingTime = kBroadcastingInterval
1219 - kMinBroadcastingInterval;
1220
1221 // snooze the rest blocking on our semaphore (if it exists)
1222 if (fBroadcasterSemaphore >= 0) {
1223 status_t snoozeError = acquire_sem_etc(fBroadcasterSemaphore, 1,
1224 B_RELATIVE_TIMEOUT, remainingTime);
1225
1226 // set the semaphore count back to zero
1227 while (snoozeError == B_OK) {
1228 snoozeError = acquire_sem_etc(fBroadcasterSemaphore, 1,
1229 B_RELATIVE_TIMEOUT, 0);
1230 }
1231 } else
1232 snooze(remainingTime);
1233
1234 update = atomic_and(&fServerInfoUpdated, 0);
1235 }
1236
1237 // close the socket
1238 safe_closesocket(fBroadcastingSocket);
1239 return B_OK;
1240 }
1241
1242 // _ServerInfoConnectionListenerEntry
1243 int32
_ServerInfoConnectionListenerEntry(void * data)1244 NetFSServer::_ServerInfoConnectionListenerEntry(void* data)
1245 {
1246 return ((NetFSServer*)data)->_ServerInfoConnectionListener();
1247 }
1248
1249 // _ServerInfoConnectionListener
1250 int32
_ServerInfoConnectionListener()1251 NetFSServer::_ServerInfoConnectionListener()
1252 {
1253 if (fServerInfoConnectionListenerSocket < 0)
1254 return B_BAD_VALUE;
1255
1256 TaskManager taskManager;
1257
1258 // accept a incoming connection
1259 while (!fTerminating) {
1260 int fd = -1;
1261 do {
1262 taskManager.RemoveDoneTasks();
1263
1264 fd = accept(fServerInfoConnectionListenerSocket, NULL, 0);
1265 if (fd < 0) {
1266 status_t error = errno;
1267 if (error != B_INTERRUPTED)
1268 return error;
1269 if (fTerminating)
1270 return B_OK;
1271 }
1272 } while (fd < 0);
1273
1274 // get a fresh server info
1275 ServerInfo info;
1276 status_t error = _GetServerInfo(info);
1277 if (error != B_OK) {
1278 closesocket(fd);
1279 return error;
1280 }
1281
1282 // create a server info sender thread
1283 ServerInfoSender* sender = new(std::nothrow) ServerInfoSender(fd, info);
1284 if (sender == NULL) {
1285 closesocket(fd);
1286 delete sender;
1287 return B_NO_MEMORY;
1288 }
1289 if ((error = sender->Init()) != B_OK) {
1290 closesocket(fd);
1291 delete sender;
1292 return error;
1293 }
1294 taskManager.RunTask(sender);
1295 }
1296
1297 return B_OK;
1298 }
1299
1300 // _GetServerInfo
1301 status_t
_GetServerInfo(ServerInfo & serverInfo)1302 NetFSServer::_GetServerInfo(ServerInfo& serverInfo)
1303 {
1304 // set the server name and the connection method
1305 char hostName[1024];
1306 if (gethostname(hostName, sizeof(hostName)) < 0) {
1307 ERROR("NetFSServer::_GetServerInfo(): ERROR: Failed to get host "
1308 "name.");
1309 return B_ERROR;
1310 }
1311 status_t error = serverInfo.SetServerName(hostName);
1312 // TODO: Set the actually used connection method!
1313 if (error == B_OK)
1314 error = serverInfo.SetConnectionMethod("insecure");
1315 if (error != B_OK)
1316 return error;
1317
1318 // get the shares from the security context
1319 BMessage shares;
1320 error = fSecurityContext->GetShares(&shares);
1321 if (error != B_OK)
1322 return error;
1323
1324 // add the shares
1325 const char* shareName;
1326 for (int32 i = 0; shares.FindString("shares", i, &shareName) == B_OK; i++) {
1327 error = serverInfo.AddShare(shareName);
1328 if (error != B_OK)
1329 return error;
1330 }
1331 return B_OK;
1332 }
1333
1334 // _ServerInfoUpdated
1335 void
_ServerInfoUpdated()1336 NetFSServer::_ServerInfoUpdated()
1337 {
1338 atomic_or(&fServerInfoUpdated, 1);
1339 release_sem(fBroadcasterSemaphore);
1340 }
1341
1342 // _SendReply
1343 void
_SendReply(BMessage * message,BMessage * reply,status_t error)1344 NetFSServer::_SendReply(BMessage* message, BMessage* reply, status_t error)
1345 {
1346 // no reply is specified, if no data have to be sent
1347 BMessage stackReply;
1348 if (!reply)
1349 reply = &stackReply;
1350
1351 reply->AddInt32("error", error);
1352 message->SendReply(reply, (BHandler*)NULL, 0LL);
1353 }
1354
1355 // _SendReply
1356 void
_SendReply(BMessage * message,status_t error)1357 NetFSServer::_SendReply(BMessage* message, status_t error)
1358 {
1359 _SendReply(message, NULL, error);
1360 }
1361
1362
1363 // #pragma mark -
1364
1365 // print_usage
1366 static
1367 void
print_usage(bool error)1368 print_usage(bool error)
1369 {
1370 fputs(kUsage, (error ? stderr : stdout));
1371 }
1372
1373 // main
1374 int
main(int argc,char ** argv)1375 main(int argc, char** argv)
1376 {
1377 #ifdef DEBUG_OBJECT_TRACKING
1378 ObjectTracker::InitDefault();
1379 #endif
1380
1381 // parse the arguments
1382 bool broadcast = true;
1383 for (int argi = 1; argi < argc; argi++) {
1384 const char* arg = argv[argi];
1385 if (strcmp(arg, "--dont-broadcast") == 0) {
1386 broadcast = false;
1387 } else if (strcmp(arg, "--help") == 0 || strcmp(arg, "-h") == 0) {
1388 print_usage(false);
1389 return 0;
1390 } else {
1391 print_usage(true);
1392 return 1;
1393 }
1394 }
1395
1396 // create the statistics manager
1397 status_t error = StatisticsManager::CreateDefault();
1398 if (error != B_OK) {
1399 fprintf(stderr, "Failed to create statistics manager: %s\n",
1400 strerror(error));
1401 return 1;
1402 }
1403
1404 // init and run the server
1405 {
1406 NetFSServer server(broadcast);
1407 error = server.Init();
1408 if (error != B_OK) {
1409 fprintf(stderr, "Failed to initialize server: %s\n",
1410 strerror(error));
1411 return 1;
1412 }
1413 server.Run();
1414 }
1415
1416 // delete the statistics manager
1417 StatisticsManager::DeleteDefault();
1418
1419 #ifdef DEBUG_OBJECT_TRACKING
1420 ObjectTracker::ExitDefault();
1421 #endif
1422
1423 return 0;
1424 }
1425
1426