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