// AddShare // // The caller gets a reference, if _share is not NULL. status_t SecurityContext::AddShare(const char* name, const char* path, Share** _share) { if (!name) return B_BAD_VALUE; // check, if the share does already exist ContextLocker _(this); if (fShares->Get(name)) return B_BAD_VALUE; // create a the share Share* share = new(std::nothrow) Share; if (!share) return B_NO_MEMORY; Reference<Share> shareReference(share, true); status_t error = share->Init(name, path); if (error != B_OK) return error; // add the share error = fShares->Put(name, share); if (error != B_OK) return error; shareReference.Detach(); if (_share) { *_share = share; share->AddReference(); } return B_OK; }
// RemoveShare // // The caller gets a reference, if _share is not NULL. status_t SecurityContext::RemoveShare(const char* name, Share** _share) { if (!name) return B_BAD_VALUE; ContextLocker _(this); // get the share Share* share = FindShare(name); if (!share) return B_ENTRY_NOT_FOUND; Reference<Share> shareReference(share, true); // remove it status_t error = RemoveShare(share); if (error == B_OK && _share) { *_share = share; share->AddReference(); } return error; }
// _LoadSecurityContext status_t NetFSServer::_LoadSecurityContext(SecurityContext** _securityContext) { // create a security context SecurityContext* securityContext = new(std::nothrow) SecurityContext; if (!securityContext) return B_NO_MEMORY; status_t error = securityContext->InitCheck(); if (error != B_OK) { delete securityContext; return error; } ObjectDeleter<SecurityContext> securityContextDeleter(securityContext); // load from driver settings for the time being DriverSettings settings; error = settings.Load("netfs-server"); if (error != B_OK) return error; // load users DriverParameter parameter; for (DriverParameterIterator it = settings.GetParameterIterator("user"); it.GetNext(¶meter);) { const char* userName = parameter.ValueAt(0); const char* password = parameter.GetParameterValue("password"); if (!userName) { WARN("Skipping nameless user settings entry.\n"); continue; } // PRINT(("user: %s, password: %s\n", parameter.ValueAt(0), // parameter.GetParameterValue("password"))); error = securityContext->AddUser(userName, password); if (error != B_OK) ERROR("ERROR: Failed to add user `%s'\n", userName); } // load shares for (DriverParameterIterator it = settings.GetParameterIterator("share"); it.GetNext(¶meter);) { const char* shareName = parameter.ValueAt(0); const char* path = parameter.GetParameterValue("path"); if (!shareName || !path) { WARN("settings: Skipping invalid share settings entry (no name" " or no path).\n"); continue; } // PRINT(("share: %s, path: %s\n", parameter.ValueAt(0), // parameter.GetParameterValue("path"))); Share* share; error = securityContext->AddShare(shareName, path, &share); if (error != B_OK) { ERROR("ERROR: Failed to add share `%s'\n", shareName); continue; } Reference<Share> shareReference(share, true); DriverParameter userParameter; // iterate through the share users for (DriverParameterIterator userIt = parameter.GetParameterIterator("user"); userIt.GetNext(&userParameter);) { const char* userName = userParameter.ValueAt(0); // PRINT((" user: %s\n", userName)); User* user = securityContext->FindUser(userName); if (!user) { ERROR("ERROR: Undefined user `%s'.\n", userName); continue; } Reference<User> userReference(user, true); DriverParameter permissionsParameter; if (!userParameter.FindParameter("permissions", &permissionsParameter)) { continue; } Permissions permissions; for (int32 i = 0; i < permissionsParameter.CountValues(); i++) { const char* permission = permissionsParameter.ValueAt(i); // PRINT((" permission: %s\n", permission)); if (strcmp(permission, "mount") == 0) { permissions.AddPermissions(MOUNT_SHARE_PERMISSION); } else if (strcmp(permission, "query") == 0) { permissions.AddPermissions(QUERY_SHARE_PERMISSION); } else if (strcmp(permission, "read") == 0) { permissions.AddPermissions(READ_PERMISSION | READ_DIR_PERMISSION | RESOLVE_DIR_ENTRY_PERMISSION); } else if (strcmp(permission, "write") == 0) { permissions.AddPermissions(WRITE_PERMISSION | WRITE_DIR_PERMISSION); } else if (strcmp(permission, "all") == 0) { permissions.AddPermissions(ALL_PERMISSIONS); } } error = securityContext->SetNodePermissions(share->GetPath(), user, permissions); if (error != B_OK) { ERROR("ERROR: Failed to set permissions for share `%s'\n", share->GetName()); } } } securityContextDeleter.Detach(); *_securityContext = securityContext; return B_OK; }
// MessageReceived void NetFSServer::MessageReceived(BMessage* message) { switch (message->what) { case NETFS_REQUEST_GET_MESSENGER: { // for the time being we process all requests here BMessage reply; reply.AddMessenger("messenger", be_app_messenger); _SendReply(message, &reply); break; } case NETFS_REQUEST_ADD_USER: { // get user name and password const char* user; const char* password; if (message->FindString("user", &user) != B_OK) { _SendReply(message, B_BAD_VALUE); break; } if (message->FindString("password", &password) != B_OK) password = NULL; // add the user status_t error = fSecurityContext->AddUser(user, password); _SendReply(message, error); break; } case NETFS_REQUEST_REMOVE_USER: { // get user name const char* userName; if (message->FindString("user", &userName) != B_OK) { _SendReply(message, B_BAD_VALUE); break; } // remove the user User* user; status_t error = fSecurityContext->RemoveUser(userName, &user); if (error == B_OK) { // propagate the information to the client connections AutoLocker<Locker> _(fLock); for (int32 i = 0; ClientConnection* connection = (ClientConnection*)fClientConnections.ItemAt(i); i++) { connection->UserRemoved(user); } user->RemoveReference(); } _SendReply(message, error); break; } case NETFS_REQUEST_GET_USERS: { // get the users BMessage reply; BMessage users; status_t error = fSecurityContext->GetUsers(&users); if (error == B_OK) error = reply.AddMessage("users", &users); if (error == B_OK) _SendReply(message, &reply); else _SendReply(message, error); break; } case NETFS_REQUEST_GET_USER_STATISTICS: { // get user name const char* userName; if (message->FindString("user", &userName) != B_OK) { _SendReply(message, B_BAD_VALUE); break; } // get the user User* user = fSecurityContext->FindUser(userName); if (!user) { _SendReply(message, B_ENTRY_NOT_FOUND); break; } Reference<User> userReference(user, true); // get the statistics BMessage statistics; status_t error = StatisticsManager::GetDefault() ->GetUserStatistics(user, &statistics); // prepare the reply BMessage reply; if (error == B_OK) error = reply.AddMessage("statistics", &statistics); // send the reply if (error == B_OK) _SendReply(message, &reply); else _SendReply(message, error); break; } case NETFS_REQUEST_ADD_SHARE: { // get share name and path const char* share; const char* path; if (message->FindString("share", &share) != B_OK || message->FindString("path", &path) != B_OK) { _SendReply(message, B_BAD_VALUE); break; } // add the share status_t error = fSecurityContext->AddShare(share, path); if (error == B_OK) _ServerInfoUpdated(); _SendReply(message, error); break; } case NETFS_REQUEST_REMOVE_SHARE: { // get share name const char* shareName; if (message->FindString("share", &shareName) != B_OK) { _SendReply(message, B_BAD_VALUE); break; } // remove the share Share* share; status_t error = fSecurityContext->RemoveShare(shareName, &share); if (error == B_OK) { // propagate the information to the client connections AutoLocker<Locker> _(fLock); for (int32 i = 0; ClientConnection* connection = (ClientConnection*)fClientConnections.ItemAt(i); i++) { connection->ShareRemoved(share); } share->RemoveReference(); } if (error == B_OK) _ServerInfoUpdated(); _SendReply(message, error); break; } case NETFS_REQUEST_GET_SHARES: { // get the shares BMessage reply; BMessage shares; status_t error = fSecurityContext->GetShares(&shares); if (error == B_OK) error = reply.AddMessage("shares", &shares); if (error == B_OK) _SendReply(message, &reply); else _SendReply(message, error); break; } case NETFS_REQUEST_GET_SHARE_USERS: { // get share name const char* shareName; if (message->FindString("share", &shareName) != B_OK) { _SendReply(message, B_BAD_VALUE); break; } AutoLocker<Locker> securityContextLocker(fSecurityContext); // get the share Share* share = fSecurityContext->FindShare(shareName); if (!share) { _SendReply(message, B_ENTRY_NOT_FOUND); break; } Reference<Share> shareReference(share, true); // get all users BMessage allUsers; status_t error = fSecurityContext->GetUsers(&allUsers); if (error != B_OK) { _SendReply(message, error); break; } // filter the users with mount permission BMessage users; const char* userName; for (int32 i = 0; allUsers.FindString("users", i, &userName) == B_OK; i++) { if (User* user = fSecurityContext->FindUser(userName)) { // get the user's permissions Permissions permissions = fSecurityContext ->GetNodePermissions(share->GetPath(), user); user->RemoveReference(); // add the user, if they have the permission to mount the // share if (permissions.ImpliesMountSharePermission()) { error = users.AddString("users", userName); if (error != B_OK) { _SendReply(message, error); break; } } } } securityContextLocker.Unlock(); // prepare the reply BMessage reply; if (error == B_OK) error = reply.AddMessage("users", &users); // send the reply if (error == B_OK) _SendReply(message, &reply); else _SendReply(message, error); break; } case NETFS_REQUEST_GET_SHARE_STATISTICS: { // get share name const char* shareName; if (message->FindString("share", &shareName) != B_OK) { _SendReply(message, B_BAD_VALUE); break; } // get the share Share* share = fSecurityContext->FindShare(shareName); if (!share) { _SendReply(message, B_ENTRY_NOT_FOUND); break; } Reference<Share> shareReference(share, true); // get the statistics BMessage statistics; status_t error = StatisticsManager::GetDefault() ->GetShareStatistics(share, &statistics); // prepare the reply BMessage reply; if (error == B_OK) error = reply.AddMessage("statistics", &statistics); // send the reply if (error == B_OK) _SendReply(message, &reply); else _SendReply(message, error); break; } case NETFS_REQUEST_SET_USER_PERMISSIONS: { // get share and user name, and the permissions const char* shareName; const char* userName; uint32 permissions; if (message->FindString("share", &shareName) != B_OK || message->FindString("user", &userName) != B_OK || message->FindInt32("permissions", (int32*)&permissions) != B_OK) { _SendReply(message, B_BAD_VALUE); break; } // get the share and the user Share* share = fSecurityContext->FindShare(shareName); User* user = fSecurityContext->FindUser(userName); Reference<Share> shareReference(share); Reference<User> userReference(user); if (!share || !user) { _SendReply(message, B_ENTRY_NOT_FOUND); break; } // set the permissions status_t error = B_OK; if (permissions == 0) { fSecurityContext->ClearNodePermissions(share->GetPath(), user); } else { error = fSecurityContext->SetNodePermissions(share->GetPath(), user, permissions); } if (error == B_OK) { // propagate the information to the client connections AutoLocker<Locker> _(fLock); for (int32 i = 0; ClientConnection* connection = (ClientConnection*)fClientConnections.ItemAt(i); i++) { connection->UserPermissionsChanged(share, user, permissions); } } _SendReply(message, error); break; } case NETFS_REQUEST_GET_USER_PERMISSIONS: { // get share and user name const char* shareName; const char* userName; if (message->FindString("share", &shareName) != B_OK || message->FindString("user", &userName) != B_OK) { _SendReply(message, B_BAD_VALUE); break; } // get the share and the user Share* share = fSecurityContext->FindShare(shareName); User* user = fSecurityContext->FindUser(userName); Reference<Share> shareReference(share); Reference<User> userReference(user); if (!share || !user) { _SendReply(message, B_ENTRY_NOT_FOUND); break; } // get the permissions Permissions permissions = fSecurityContext->GetNodePermissions( share->GetPath(), user); // prepare the reply BMessage reply; status_t error = reply.AddInt32("permissions", (int32)permissions.GetPermissions()); // send it if (error == B_OK) _SendReply(message, &reply); else _SendReply(message, error); break; } case NETFS_REQUEST_SAVE_SETTINGS: { status_t error = _SaveSettings(); // send a reply _SendReply(message, error); break; } } }