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 delete securityContext; 968 RETURN_ERROR(error); 969 } 970 971 // set it 972 delete fSecurityContext; 973 fSecurityContext = securityContext; 974 securityContextDeleter.Detach(); 975 976 return B_OK; 977 } 978 979 // _SaveSettings 980 status_t 981 NetFSServer::_SaveSettings() 982 { 983 AutoLocker<Locker> locker(fSecurityContext); 984 985 // create the settings archive 986 BMessage settings; 987 988 // archive the security context 989 BMessage securityContextArchive; 990 status_t error = fSecurityContext->Archive(&securityContextArchive, true); 991 if (error != B_OK) 992 RETURN_ERROR(error); 993 994 // add it to the settings archive 995 error = settings.AddMessage("security context", &securityContextArchive); 996 if (error != B_OK) 997 RETURN_ERROR(error); 998 999 // open the settings file 1000 BPath filePath; 1001 error = _GetSettingsFilePath(&filePath, true); 1002 if (error != B_OK) 1003 RETURN_ERROR(error); 1004 BFile file; 1005 error = FDManager::SetFile(&file, filePath.Path(), 1006 B_READ_WRITE | B_CREATE_FILE | B_ERASE_FILE); 1007 if (error != B_OK) 1008 RETURN_ERROR(error); 1009 1010 // write to the settings file 1011 error = settings.Flatten(&file); 1012 if (error != B_OK) 1013 RETURN_ERROR(error); 1014 1015 return B_OK; 1016 } 1017 1018 // _GetSettingsDirPath 1019 status_t 1020 NetFSServer::_GetSettingsDirPath(BPath* path, bool create) 1021 { 1022 // get the user settings directory 1023 BPath settingsDir; 1024 status_t error = find_directory(B_USER_SETTINGS_DIRECTORY, &settingsDir, 1025 create); 1026 if (error != B_OK) 1027 RETURN_ERROR(error); 1028 1029 // create our subdir, if not existing and desired 1030 error = path->SetTo(settingsDir.Path(), kSettingsDirName); 1031 if (error != B_OK) 1032 RETURN_ERROR(error); 1033 BEntry bEntry; 1034 if (create 1035 && (FDManager::SetEntry(&bEntry, settingsDir.Path()) != B_OK 1036 || !bEntry.Exists())) { 1037 error = create_directory(path->Path(), S_IRWXU | S_IRWXG | S_IRWXO); 1038 if (error != B_OK) 1039 RETURN_ERROR(error); 1040 } 1041 1042 return B_OK; 1043 } 1044 1045 // _GetSettingsFilePath 1046 status_t 1047 NetFSServer::_GetSettingsFilePath(BPath* path, bool createDir) 1048 { 1049 // get settings dir 1050 BPath dirPath; 1051 status_t error = _GetSettingsDirPath(&dirPath, createDir); 1052 if (error != B_OK) 1053 return error; 1054 1055 // construct the file path 1056 return path->SetTo(dirPath.Path(), kSettingsFileName); 1057 } 1058 1059 // _InitServerInfoConnectionListener 1060 status_t 1061 NetFSServer::_InitServerInfoConnectionListener() 1062 { 1063 // spawn the listener thread 1064 fServerInfoConnectionListener = spawn_thread( 1065 &_ServerInfoConnectionListenerEntry, 1066 "server info connection listener", B_NORMAL_PRIORITY, this); 1067 if (fServerInfoConnectionListener < 0) 1068 return fServerInfoConnectionListener; 1069 // create a listener socket 1070 fServerInfoConnectionListenerSocket = socket(AF_INET, SOCK_STREAM, 0); 1071 if (fServerInfoConnectionListenerSocket < 0) 1072 return errno; 1073 // bind it to the port 1074 sockaddr_in addr; 1075 addr.sin_family = AF_INET; 1076 addr.sin_port = htons(kDefaultServerInfoPort); 1077 addr.sin_addr.s_addr = INADDR_ANY; 1078 if (bind(fServerInfoConnectionListenerSocket, (sockaddr*)&addr, 1079 sizeof(addr)) < 0) { 1080 return errno; 1081 } 1082 // start listening 1083 if (listen(fServerInfoConnectionListenerSocket, 5) < 0) 1084 return errno; 1085 return B_OK; 1086 } 1087 1088 // _ExitServerInfoConnectionListener 1089 void 1090 NetFSServer::_ExitServerInfoConnectionListener() 1091 { 1092 // close the socket 1093 safe_closesocket(fServerInfoConnectionListenerSocket); 1094 // wait for the listener 1095 if (fServerInfoConnectionListener >= 0) { 1096 int32 result; 1097 wait_for_thread(fServerInfoConnectionListener, &result); 1098 } 1099 } 1100 1101 // _ConnectionListenerEntry 1102 int32 1103 NetFSServer::_ConnectionListenerEntry(void* data) 1104 { 1105 return ((NetFSServer*)data)->_ConnectionListener(); 1106 } 1107 1108 // _ConnectionListener 1109 int32 1110 NetFSServer::_ConnectionListener() 1111 { 1112 // start listening for connections 1113 Connection* connection = NULL; 1114 status_t error = B_OK; 1115 do { 1116 error = fConnectionListener->Listen(&connection); 1117 if (error == B_OK) { 1118 ConnectionInitializer* initializer 1119 = new(std::nothrow) ConnectionInitializer(this, fConnectionListener, 1120 connection); 1121 if (initializer) { 1122 if (initializer->Run() != B_OK) { 1123 ERROR("Failed to run connection initializer.\n") 1124 delete initializer; 1125 } 1126 } else { 1127 ERROR("Failed to create connection initializer.\n") 1128 delete connection; 1129 } 1130 1131 } 1132 } while (error == B_OK && !fTerminating); 1133 1134 return 0; 1135 } 1136 1137 // _ConnectionDeleterEntry 1138 int32 1139 NetFSServer::_ConnectionDeleterEntry(void* data) 1140 { 1141 return ((NetFSServer*)data)->_ConnectionDeleter(); 1142 } 1143 1144 // _ConnectionDeleter 1145 int32 1146 NetFSServer::_ConnectionDeleter() 1147 { 1148 while (!fTerminating) { 1149 status_t error = acquire_sem(fClosedConnectionsSemaphore); 1150 ClientConnection* connection = NULL; 1151 if (error == B_OK) { 1152 AutoLocker<Locker> _(fLock); 1153 connection = (ClientConnection*)fClosedConnections.RemoveItem(0L); 1154 } 1155 if (connection) 1156 delete connection; 1157 } 1158 return 0; 1159 } 1160 1161 // _BroadcasterEntry 1162 int32 1163 NetFSServer::_BroadcasterEntry(void* data) 1164 { 1165 return ((NetFSServer*)data)->_Broadcaster(); 1166 } 1167 1168 // _Broadcaster 1169 int32 1170 NetFSServer::_Broadcaster() 1171 { 1172 // create the socket 1173 fBroadcastingSocket = socket(AF_INET, SOCK_DGRAM, 0); 1174 if (fBroadcastingSocket < 0) { 1175 WARN("NetFSServer::_Broadcaster(): WARN: Failed to init broadcasting: " 1176 "%s.\n", strerror(errno)); 1177 return errno; 1178 } 1179 1180 // set the socket broadcast option 1181 #ifndef HAIKU_TARGET_PLATFORM_BEOS 1182 int soBroadcastValue = 1; 1183 if (setsockopt(fBroadcastingSocket, SOL_SOCKET, SO_BROADCAST, 1184 &soBroadcastValue, sizeof(soBroadcastValue)) < 0) { 1185 WARN("NetFSServer::_Broadcaster(): WARN: Failed to set " 1186 "SO_BROADCAST on socket: %s.\n", strerror(errno)); 1187 } 1188 #endif 1189 1190 // prepare the broadcast message 1191 BroadcastMessage message; 1192 message.magic = B_HOST_TO_BENDIAN_INT32(BROADCAST_MESSAGE_MAGIC); 1193 message.protocolVersion = B_HOST_TO_BENDIAN_INT32(NETFS_PROTOCOL_VERSION); 1194 1195 bool update = false; 1196 while (!fTerminating) { 1197 // set tick/update 1198 uint32 messageCode = (update ? BROADCAST_MESSAGE_SERVER_UPDATE 1199 : BROADCAST_MESSAGE_SERVER_TICK); 1200 message.message = B_HOST_TO_BENDIAN_INT32(messageCode); 1201 1202 // send broadcasting message 1203 sockaddr_in addr; 1204 addr.sin_family = AF_INET; 1205 addr.sin_port = htons(kDefaultBroadcastPort); 1206 addr.sin_addr.s_addr = INADDR_BROADCAST; 1207 int addrSize = sizeof(addr); 1208 ssize_t bytesSent = sendto(fBroadcastingSocket, &message, 1209 sizeof(message), 0, (sockaddr*)&addr, addrSize); 1210 if (bytesSent < 0) { 1211 WARN("NetFSServer::_Broadcaster(): WARN: sending failed: %s.\n", 1212 strerror(errno)); 1213 return errno; 1214 } 1215 1216 // snooze a bit 1217 // we snooze a minimal interval to avoid shooting updates like a 1218 // machine gun 1219 snooze(kMinBroadcastingInterval); 1220 bigtime_t remainingTime = kBroadcastingInterval 1221 - kMinBroadcastingInterval; 1222 1223 // snooze the rest blocking on our semaphore (if it exists) 1224 if (fBroadcasterSemaphore >= 0) { 1225 status_t snoozeError = acquire_sem_etc(fBroadcasterSemaphore, 1, 1226 B_RELATIVE_TIMEOUT, remainingTime); 1227 1228 // set the semaphore count back to zero 1229 while (snoozeError == B_OK) { 1230 snoozeError = acquire_sem_etc(fBroadcasterSemaphore, 1, 1231 B_RELATIVE_TIMEOUT, 0); 1232 } 1233 } else 1234 snooze(remainingTime); 1235 1236 update = atomic_and(&fServerInfoUpdated, 0); 1237 } 1238 1239 // close the socket 1240 safe_closesocket(fBroadcastingSocket); 1241 return B_OK; 1242 } 1243 1244 // _ServerInfoConnectionListenerEntry 1245 int32 1246 NetFSServer::_ServerInfoConnectionListenerEntry(void* data) 1247 { 1248 return ((NetFSServer*)data)->_ServerInfoConnectionListener(); 1249 } 1250 1251 // _ServerInfoConnectionListener 1252 int32 1253 NetFSServer::_ServerInfoConnectionListener() 1254 { 1255 if (fServerInfoConnectionListenerSocket < 0) 1256 return B_BAD_VALUE; 1257 1258 TaskManager taskManager; 1259 1260 // accept a incoming connection 1261 while (!fTerminating) { 1262 int fd = -1; 1263 do { 1264 taskManager.RemoveDoneTasks(); 1265 1266 fd = accept(fServerInfoConnectionListenerSocket, NULL, 0); 1267 if (fd < 0) { 1268 status_t error = errno; 1269 if (error != B_INTERRUPTED) 1270 return error; 1271 if (fTerminating) 1272 return B_OK; 1273 } 1274 } while (fd < 0); 1275 1276 // get a fresh server info 1277 ServerInfo info; 1278 status_t error = _GetServerInfo(info); 1279 if (error != B_OK) { 1280 closesocket(fd); 1281 return error; 1282 } 1283 1284 // create a server info sender thread 1285 ServerInfoSender* sender = new(std::nothrow) ServerInfoSender(fd, info); 1286 if (sender == NULL) { 1287 closesocket(fd); 1288 delete sender; 1289 return B_NO_MEMORY; 1290 } 1291 if ((error = sender->Init()) != B_OK) { 1292 closesocket(fd); 1293 delete sender; 1294 return error; 1295 } 1296 taskManager.RunTask(sender); 1297 } 1298 1299 return B_OK; 1300 } 1301 1302 // _GetServerInfo 1303 status_t 1304 NetFSServer::_GetServerInfo(ServerInfo& serverInfo) 1305 { 1306 // set the server name and the connection method 1307 char hostName[1024]; 1308 if (gethostname(hostName, sizeof(hostName)) < 0) { 1309 ERROR("NetFSServer::_GetServerInfo(): ERROR: Failed to get host " 1310 "name."); 1311 return B_ERROR; 1312 } 1313 status_t error = serverInfo.SetServerName(hostName); 1314 // TODO: Set the actually used connection method! 1315 if (error == B_OK) 1316 error = serverInfo.SetConnectionMethod("insecure"); 1317 if (error != B_OK) 1318 return error; 1319 1320 // get the shares from the security context 1321 BMessage shares; 1322 error = fSecurityContext->GetShares(&shares); 1323 if (error != B_OK) 1324 return error; 1325 1326 // add the shares 1327 const char* shareName; 1328 for (int32 i = 0; shares.FindString("shares", i, &shareName) == B_OK; i++) { 1329 error = serverInfo.AddShare(shareName); 1330 if (error != B_OK) 1331 return error; 1332 } 1333 return B_OK; 1334 } 1335 1336 // _ServerInfoUpdated 1337 void 1338 NetFSServer::_ServerInfoUpdated() 1339 { 1340 atomic_or(&fServerInfoUpdated, 1); 1341 release_sem(fBroadcasterSemaphore); 1342 } 1343 1344 // _SendReply 1345 void 1346 NetFSServer::_SendReply(BMessage* message, BMessage* reply, status_t error) 1347 { 1348 // no reply is specified, if no data have to be sent 1349 BMessage stackReply; 1350 if (!reply) 1351 reply = &stackReply; 1352 1353 reply->AddInt32("error", error); 1354 message->SendReply(reply, (BHandler*)NULL, 0LL); 1355 } 1356 1357 // _SendReply 1358 void 1359 NetFSServer::_SendReply(BMessage* message, status_t error) 1360 { 1361 _SendReply(message, NULL, error); 1362 } 1363 1364 1365 // #pragma mark - 1366 1367 // print_usage 1368 static 1369 void 1370 print_usage(bool error) 1371 { 1372 fprintf((error ? stderr : stdout), kUsage); 1373 } 1374 1375 // main 1376 int 1377 main(int argc, char** argv) 1378 { 1379 #ifdef DEBUG_OBJECT_TRACKING 1380 ObjectTracker::InitDefault(); 1381 #endif 1382 1383 // parse the arguments 1384 bool broadcast = true; 1385 for (int argi = 1; argi < argc; argi++) { 1386 const char* arg = argv[argi]; 1387 if (strcmp(arg, "--dont-broadcast") == 0) { 1388 broadcast = false; 1389 } else if (strcmp(arg, "--help") == 0 || strcmp(arg, "-h") == 0) { 1390 print_usage(false); 1391 return 0; 1392 } else { 1393 print_usage(true); 1394 return 1; 1395 } 1396 } 1397 1398 // create the statistics manager 1399 status_t error = StatisticsManager::CreateDefault(); 1400 if (error != B_OK) { 1401 fprintf(stderr, "Failed to create statistics manager: %s\n", 1402 strerror(error)); 1403 return 1; 1404 } 1405 1406 // init and run the server 1407 { 1408 NetFSServer server(broadcast); 1409 error = server.Init(); 1410 if (error != B_OK) { 1411 fprintf(stderr, "Failed to initialize server: %s\n", 1412 strerror(error)); 1413 return 1; 1414 } 1415 server.Run(); 1416 } 1417 1418 // delete the statistics manager 1419 StatisticsManager::DeleteDefault(); 1420 1421 #ifdef DEBUG_OBJECT_TRACKING 1422 ObjectTracker::ExitDefault(); 1423 #endif 1424 1425 return 0; 1426 } 1427 1428