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