Commit a5c2ab6b authored by Josh Simmons's avatar Josh Simmons Committed by Commit Bot

Limit the maximum number of smbfs shares that can be mounted

Enforce a limit on the maximum number of smbfs shares that can be
mounted by request of the user. When the limit is reached, the
user will see the message "Error mounting share. Too many SMB
shares are already mounted." in the "Add file share" dialog box.

Fixed: 1060396
Change-Id: I21467250d7c273d34591f351bc955a4e7d041a45
Test: unit_tests --gtest_filter="SmbServiceWithSmbfsTest.MountExcessiveShares"
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2100052
Commit-Queue: Josh Simmons <simmonsjosh@google.com>
Reviewed-by: default avatarAnand Mistry <amistry@chromium.org>
Reviewed-by: default avatarKyle Horimoto <khorimoto@chromium.org>
Cr-Commit-Position: refs/heads/master@{#750879}
parent 97206802
...@@ -357,6 +357,9 @@ ...@@ -357,6 +357,9 @@
<message name="IDS_SETTINGS_DOWNLOADS_SHARE_ADDED_MOUNT_EXISTS_MESSAGE" desc="The message shown when mounting a new SMB share fails because the share is already mounted."> <message name="IDS_SETTINGS_DOWNLOADS_SHARE_ADDED_MOUNT_EXISTS_MESSAGE" desc="The message shown when mounting a new SMB share fails because the share is already mounted.">
Error mounting share. The specified share is already mounted. Error mounting share. The specified share is already mounted.
</message> </message>
<message name="IDS_SETTINGS_DOWNLOADS_SHARE_ADDED_TOO_MANY_MOUNTS_MESSAGE" desc="The message shown when mounting a new SMB share fails because too many SMB shares are already mounted.">
Error mounting share. Too many SMB shares are already mounted.
</message>
<message name="IDS_SETTINGS_DOWNLOADS_SHARE_ADDED_MOUNT_INVALID_URL_MESSAGE" desc="The message shown when mounting a new SMB share fails because the URL is an invalid format."> <message name="IDS_SETTINGS_DOWNLOADS_SHARE_ADDED_MOUNT_INVALID_URL_MESSAGE" desc="The message shown when mounting a new SMB share fails because the URL is an invalid format.">
Invalid URL format. Supported formats are \\server\share and smb://server/share. Invalid URL format. Supported formats are \\server\share and smb://server/share.
</message> </message>
......
...@@ -57,6 +57,9 @@ const char kModeUnknownValue[] = "unknown"; ...@@ -57,6 +57,9 @@ const char kModeUnknownValue[] = "unknown";
const base::TimeDelta kHostDiscoveryInterval = base::TimeDelta::FromSeconds(60); const base::TimeDelta kHostDiscoveryInterval = base::TimeDelta::FromSeconds(60);
// -3 is chosen because -1 and -2 have special meaning in smbprovider. // -3 is chosen because -1 and -2 have special meaning in smbprovider.
const int32_t kInvalidMountId = -3; const int32_t kInvalidMountId = -3;
// Maximum number of smbfs shares to be mounted at the same time, only enforced
// on user-initiated mount requests.
const size_t kMaxSmbFsShares = 16;
net::NetworkInterfaceList GetInterfaces() { net::NetworkInterfaceList GetInterfaces() {
net::NetworkInterfaceList list; net::NetworkInterfaceList list;
...@@ -273,6 +276,12 @@ void SmbService::Mount(const file_system_provider::MountOptions& options, ...@@ -273,6 +276,12 @@ void SmbService::Mount(const file_system_provider::MountOptions& options,
return; return;
} }
if (IsSmbFsEnabled() && smbfs_shares_.size() >= kMaxSmbFsShares) {
// Prevent users from mounting an excessive number of shares.
std::move(callback).Run(SmbMountResult::kTooManyOpened);
return;
}
std::string username; std::string username;
std::string password; std::string password;
std::string workgroup; std::string workgroup;
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include "base/memory/ptr_util.h" #include "base/memory/ptr_util.h"
#include "base/run_loop.h" #include "base/run_loop.h"
#include "base/strings/strcat.h" #include "base/strings/strcat.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h" #include "base/strings/string_util.h"
#include "base/test/bind_test_util.h" #include "base/test/bind_test_util.h"
#include "base/test/scoped_feature_list.h" #include "base/test/scoped_feature_list.h"
...@@ -925,5 +926,103 @@ TEST_F(SmbServiceWithSmbfsTest, MountSaved) { ...@@ -925,5 +926,103 @@ TEST_F(SmbServiceWithSmbfsTest, MountSaved) {
EXPECT_TRUE(registry.GetAll().empty()); EXPECT_TRUE(registry.GetAll().empty());
} }
TEST_F(SmbServiceWithSmbfsTest, MountExcessiveShares) {
// The maxmium number of smbfs shares that can be mounted simultaneously.
// Should match the definition in smb_service.cc.
const size_t kMaxSmbFsShares = 16;
CreateService(profile_);
WaitForSetupComplete();
// Check: It is possible to mount the maximum number of shares.
for (size_t i = 0; i < kMaxSmbFsShares; ++i) {
mojo::Remote<smbfs::mojom::SmbFs> smbfs_remote;
MockSmbFsImpl smbfs_impl(smbfs_remote.BindNewPipeAndPassReceiver());
mojo::Remote<smbfs::mojom::SmbFsDelegate> smbfs_delegate_remote;
smbfs::SmbFsHost::Delegate* smbfs_host_delegate = nullptr;
std::unique_ptr<MockSmbFsMounter> mock_mounter =
std::make_unique<MockSmbFsMounter>();
smb_service_->SetSmbFsMounterCreationCallbackForTesting(
base::BindLambdaForTesting([&mock_mounter, &smbfs_host_delegate](
const std::string& share_path,
const std::string& mount_dir_name,
const SmbFsShare::MountOptions& options,
smbfs::SmbFsHost::Delegate* delegate)
-> std::unique_ptr<smbfs::SmbFsMounter> {
smbfs_host_delegate = delegate;
return std::move(mock_mounter);
}));
const std::string share_path =
std::string(kSharePath) + base::NumberToString(i);
const std::string mount_path =
std::string(kMountPath) + base::NumberToString(i);
EXPECT_CALL(*mock_mounter, Mount(_))
.WillOnce([this, &smbfs_host_delegate, &smbfs_remote,
&smbfs_delegate_remote,
&mount_path](smbfs::SmbFsMounter::DoneCallback callback) {
std::move(callback).Run(
smbfs::mojom::MountError::kOk,
std::make_unique<smbfs::SmbFsHost>(
MakeMountPoint(base::FilePath(mount_path)),
smbfs_host_delegate, std::move(smbfs_remote),
smbfs_delegate_remote.BindNewPipeAndPassReceiver()));
});
base::RunLoop run_loop;
smb_service_->Mount(
mount_options_, base::FilePath(share_path), kTestUser, kTestPassword,
false /* use_chromad_kerberos */,
false /* should_open_file_manager_after_mount */,
false /* save_credentials */,
base::BindLambdaForTesting([&run_loop](SmbMountResult result) {
EXPECT_EQ(SmbMountResult::kSuccess, result);
run_loop.Quit();
}));
run_loop.Run();
}
// Check: After mounting the maximum number of shares, requesting to mount an
// additional share should fail.
mojo::Remote<smbfs::mojom::SmbFs> smbfs_remote;
MockSmbFsImpl smbfs_impl(smbfs_remote.BindNewPipeAndPassReceiver());
mojo::Remote<smbfs::mojom::SmbFsDelegate> smbfs_delegate_remote;
smbfs::SmbFsHost::Delegate* smbfs_host_delegate = nullptr;
std::unique_ptr<MockSmbFsMounter> mock_mounter =
std::make_unique<MockSmbFsMounter>();
smb_service_->SetSmbFsMounterCreationCallbackForTesting(
base::BindLambdaForTesting([&mock_mounter, &smbfs_host_delegate](
const std::string& share_path,
const std::string& mount_dir_name,
const SmbFsShare::MountOptions& options,
smbfs::SmbFsHost::Delegate* delegate)
-> std::unique_ptr<smbfs::SmbFsMounter> {
smbfs_host_delegate = delegate;
return std::move(mock_mounter);
}));
const std::string share_path =
std::string(kSharePath) + base::NumberToString(kMaxSmbFsShares);
const std::string mount_path =
std::string(kMountPath) + base::NumberToString(kMaxSmbFsShares);
base::RunLoop run_loop;
smb_service_->Mount(
mount_options_, base::FilePath(share_path), kTestUser, kTestPassword,
false /* use_chromad_kerberos */,
false /* should_open_file_manager_after_mount */,
false /* save_credentials */,
base::BindLambdaForTesting([&run_loop](SmbMountResult result) {
EXPECT_EQ(SmbMountResult::kTooManyOpened, result);
run_loop.Quit();
}));
run_loop.Run();
}
} // namespace smb_client } // namespace smb_client
} // namespace chromeos } // namespace chromeos
...@@ -40,6 +40,8 @@ void AddLocalizedStrings(content::WebUIDataSource* html_source) { ...@@ -40,6 +40,8 @@ void AddLocalizedStrings(content::WebUIDataSource* html_source) {
IDS_SETTINGS_DOWNLOADS_SHARE_ADDED_UNSUPPORTED_DEVICE_MESSAGE}, IDS_SETTINGS_DOWNLOADS_SHARE_ADDED_UNSUPPORTED_DEVICE_MESSAGE},
{"smbShareAddedMountExistsMessage", {"smbShareAddedMountExistsMessage",
IDS_SETTINGS_DOWNLOADS_SHARE_ADDED_MOUNT_EXISTS_MESSAGE}, IDS_SETTINGS_DOWNLOADS_SHARE_ADDED_MOUNT_EXISTS_MESSAGE},
{"smbShareAddedTooManyMountsMessage",
IDS_SETTINGS_DOWNLOADS_SHARE_ADDED_TOO_MANY_MOUNTS_MESSAGE},
{"smbShareAddedInvalidURLMessage", {"smbShareAddedInvalidURLMessage",
IDS_SETTINGS_DOWNLOADS_SHARE_ADDED_MOUNT_INVALID_URL_MESSAGE}, IDS_SETTINGS_DOWNLOADS_SHARE_ADDED_MOUNT_INVALID_URL_MESSAGE},
{"smbShareAddedInvalidSSOURLMessage", {"smbShareAddedInvalidSSOURLMessage",
......
...@@ -1221,6 +1221,8 @@ void AddFilesStrings(content::WebUIDataSource* html_source) { ...@@ -1221,6 +1221,8 @@ void AddFilesStrings(content::WebUIDataSource* html_source) {
IDS_SETTINGS_DOWNLOADS_SHARE_ADDED_UNSUPPORTED_DEVICE_MESSAGE}, IDS_SETTINGS_DOWNLOADS_SHARE_ADDED_UNSUPPORTED_DEVICE_MESSAGE},
{"smbShareAddedMountExistsMessage", {"smbShareAddedMountExistsMessage",
IDS_SETTINGS_DOWNLOADS_SHARE_ADDED_MOUNT_EXISTS_MESSAGE}, IDS_SETTINGS_DOWNLOADS_SHARE_ADDED_MOUNT_EXISTS_MESSAGE},
{"smbShareAddedTooManyMountsMessage",
IDS_SETTINGS_DOWNLOADS_SHARE_ADDED_TOO_MANY_MOUNTS_MESSAGE},
{"smbShareAddedInvalidURLMessage", {"smbShareAddedInvalidURLMessage",
IDS_SETTINGS_DOWNLOADS_SHARE_ADDED_MOUNT_INVALID_URL_MESSAGE}, IDS_SETTINGS_DOWNLOADS_SHARE_ADDED_MOUNT_INVALID_URL_MESSAGE},
{"smbShareAddedInvalidSSOURLMessage", {"smbShareAddedInvalidSSOURLMessage",
......
...@@ -265,6 +265,10 @@ Polymer({ ...@@ -265,6 +265,10 @@ Polymer({
this.setGeneralError_( this.setGeneralError_(
loadTimeData.getString('smbShareAddedMountExistsMessage')); loadTimeData.getString('smbShareAddedMountExistsMessage'));
break; break;
case SmbMountResult.TOO_MANY_OPENED:
this.setGeneralError_(
loadTimeData.getString('smbShareAddedTooManyMountsMessage'));
break;
default: default:
this.setGeneralError_( this.setGeneralError_(
loadTimeData.getString('smbShareAddedErrorMessage')); loadTimeData.getString('smbShareAddedErrorMessage'));
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment