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: 59 ConnectionInitializer(NetFSServer* server, 60 ConnectionListener* connectionListener, Connection* connection) 61 : fServer(server), 62 fConnectionListener(connectionListener), 63 fConnection(connection), 64 fThread(-1) 65 { 66 } 67 68 ~ConnectionInitializer() 69 { 70 delete fConnection; 71 } 72 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: 84 static int32 _ThreadEntry(void* data) 85 { 86 return ((ConnectionInitializer*)data)->_Thread(); 87 } 88 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: 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 137 ~ServerInfoSender() 138 { 139 delete fChannel; 140 } 141 142 status_t Init() 143 { 144 if (!fChannel) 145 return B_NO_MEMORY; 146 147 return B_OK; 148 } 149 150 virtual void Stop() 151 { 152 if (fChannel) 153 fChannel->Close(); 154 } 155 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 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 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 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 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 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* 740 NetFSServer::GetVolumeManager() const 741 { 742 return fVolumeManager; 743 } 744 745 // GetSecurityContext 746 SecurityContext* 747 NetFSServer::GetSecurityContext() const 748 { 749 return fSecurityContext; 750 } 751 752 // _AddClientConnection 753 status_t 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 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 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 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 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 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 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 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 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 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 1101 NetFSServer::_ConnectionListenerEntry(void* data) 1102 { 1103 return ((NetFSServer*)data)->_ConnectionListener(); 1104 } 1105 1106 // _ConnectionListener 1107 int32 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 1137 NetFSServer::_ConnectionDeleterEntry(void* data) 1138 { 1139 return ((NetFSServer*)data)->_ConnectionDeleter(); 1140 } 1141 1142 // _ConnectionDeleter 1143 int32 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 1161 NetFSServer::_BroadcasterEntry(void* data) 1162 { 1163 return ((NetFSServer*)data)->_Broadcaster(); 1164 } 1165 1166 // _Broadcaster 1167 int32 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 1244 NetFSServer::_ServerInfoConnectionListenerEntry(void* data) 1245 { 1246 return ((NetFSServer*)data)->_ServerInfoConnectionListener(); 1247 } 1248 1249 // _ServerInfoConnectionListener 1250 int32 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 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 1336 NetFSServer::_ServerInfoUpdated() 1337 { 1338 atomic_or(&fServerInfoUpdated, 1); 1339 release_sem(fBroadcasterSemaphore); 1340 } 1341 1342 // _SendReply 1343 void 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 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 1368 print_usage(bool error) 1369 { 1370 fputs(kUsage, (error ? stderr : stdout)); 1371 } 1372 1373 // main 1374 int 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