blob: ff8940da89f501a1e89303587f4ba7fd5d9a17e8 [file] [log] [blame]
Sergei Datsenkobcd8e462018-04-20 15:44:56 +10001// Copyright 2018 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "cros-disks/sshfs_helper.h"
6
7#include <string>
8#include <vector>
9
10#include <base/strings/string_split.h>
11#include <base/strings/string_util.h>
12#include <base/strings/stringprintf.h>
13#include <gmock/gmock.h>
14#include <gtest/gtest.h>
15
16#include "cros-disks/fuse_mounter.h"
17#include "cros-disks/mount_options.h"
18#include "cros-disks/platform.h"
19#include "cros-disks/uri.h"
20
21using std::string;
22using std::vector;
23using testing::DoAll;
24using testing::Eq;
25using testing::HasSubstr;
26using testing::Not;
27using testing::Return;
28using testing::SetArgPointee;
29using testing::StrEq;
30using testing::_;
31
32namespace cros_disks {
33
34namespace {
35
36const uid_t kMountUID = 200;
37const gid_t kMountGID = 201;
38const uid_t kFilesUID = 700;
39const uid_t kFilesGID = 701;
40const uid_t kFilesAccessGID = 1501;
41const base::FilePath kWorkingDir("/wkdir");
42const base::FilePath kMountDir("/mnt");
43const Uri kSomeSource("sshfs", "src");
44
45// Mock Platform implementation for testing.
46class MockPlatform : public Platform {
47 public:
48 MockPlatform() = default;
49
50 bool GetUserAndGroupId(const string& user,
51 uid_t* user_id,
52 gid_t* group_id) const override {
53 if (user == "fuse-sshfs") {
54 if (user_id)
55 *user_id = kMountUID;
56 if (group_id)
57 *group_id = kMountGID;
58 return true;
59 }
60 if (user == FUSEHelper::kFilesUser) {
61 if (user_id)
62 *user_id = kFilesUID;
63 if (group_id)
64 *group_id = kFilesGID;
65 return true;
66 }
67 return false;
68 }
69
70 bool GetGroupId(const string& group, gid_t* group_id) const override {
71 if (group == FUSEHelper::kFilesGroup) {
72 if (group_id)
73 *group_id = kFilesAccessGID;
74 return true;
75 }
76 return false;
77 }
78
79 MOCK_CONST_METHOD2(CopyFile, bool(const string& src, const string& dst));
80 MOCK_CONST_METHOD3(SetOwnership,
81 bool(const string& path, uid_t user_id, gid_t group_id));
82 MOCK_CONST_METHOD2(SetPermissions, bool(const string& path, mode_t mode));
83};
84
85} // namespace
86
87class SshfsHelperTest : public ::testing::Test {
88 public:
89 SshfsHelperTest() : helper_(&platform_) {
90 ON_CALL(platform_, SetOwnership(_, kMountUID, getgid()))
91 .WillByDefault(Return(true));
92 ON_CALL(platform_, SetPermissions(_, 0770)).WillByDefault(Return(true));
93 }
94
95 protected:
96 MockPlatform platform_;
97 SshfsHelper helper_;
98};
99
100// Verifies that CreateMounter creates mounter in a simple case.
101TEST_F(SshfsHelperTest, CreateMounter_SimpleOptions) {
102 auto mounter = helper_.CreateMounter(kWorkingDir, kSomeSource, kMountDir, {});
103 EXPECT_EQ("sshfs", mounter->filesystem_type());
104 EXPECT_EQ("src", mounter->source_path());
105 EXPECT_EQ("/mnt", mounter->target_path());
106 string opts = mounter->mount_options().ToString();
107 EXPECT_THAT(opts, HasSubstr("BatchMode=yes"));
108 EXPECT_THAT(opts, HasSubstr("PasswordAuthentication=no"));
109 EXPECT_THAT(opts, HasSubstr("KbdInteractiveAuthentication=no"));
110 EXPECT_THAT(opts, HasSubstr("allow_other"));
111 EXPECT_THAT(opts, HasSubstr("default_permissions"));
112 EXPECT_THAT(opts, HasSubstr("uid=700"));
113 EXPECT_THAT(opts, HasSubstr("gid=1501"));
114}
115
116// Verifies that CreateMounter copies files to the working dir when provided.
117TEST_F(SshfsHelperTest, CreateMounter_CopyFiles) {
118 EXPECT_CALL(platform_, CopyFile("/foo/bar", "/wkdir/bar"))
119 .WillOnce(Return(true));
120 EXPECT_CALL(platform_, CopyFile("/foo/baz", "/wkdir/baz"))
121 .WillOnce(Return(true));
122 EXPECT_CALL(platform_, SetPermissions("/wkdir/bar", 0600))
123 .WillOnce(Return(true));
124 EXPECT_CALL(platform_, SetPermissions("/wkdir/baz", 0600))
125 .WillOnce(Return(true));
126 EXPECT_CALL(platform_, SetPermissions("/wkdir", 0770)).WillOnce(Return(true));
127 EXPECT_CALL(platform_, SetOwnership("/wkdir/bar", kMountUID, kMountGID))
128 .WillOnce(Return(true));
129 EXPECT_CALL(platform_, SetOwnership("/wkdir/baz", kMountUID, kMountGID))
130 .WillOnce(Return(true));
131 EXPECT_CALL(platform_, SetOwnership("/wkdir", kMountUID, getgid()))
132 .WillOnce(Return(true));
133 auto mounter = helper_.CreateMounter(
134 kWorkingDir, kSomeSource, kMountDir,
Sergei Datsenko1aa55362018-05-14 15:19:27 +1000135 {"IdentityFile=/foo/bar", "UserKnownHostsFile=/foo/baz",
136 "HostName=localhost", "Port=2222"});
Sergei Datsenkobcd8e462018-04-20 15:44:56 +1000137 string opts = mounter->mount_options().ToString();
138 EXPECT_THAT(opts, HasSubstr("IdentityFile=/wkdir/bar"));
139 EXPECT_THAT(opts, HasSubstr("UserKnownHostsFile=/wkdir/baz"));
Sergei Datsenko1aa55362018-05-14 15:19:27 +1000140 EXPECT_THAT(opts, HasSubstr("HostName=localhost"));
141 EXPECT_THAT(opts, HasSubstr("Port=2222"));
Sergei Datsenkobcd8e462018-04-20 15:44:56 +1000142 EXPECT_THAT(opts, Not(HasSubstr("/foo/bar")));
143 EXPECT_THAT(opts, Not(HasSubstr("/foo/baz")));
144}
145
146// Verifies that CreateMounter fails if files are in unsafe format.
147TEST_F(SshfsHelperTest, CreateMounter_CopyUnsafe) {
148 EXPECT_CALL(platform_, CopyFile(_, _)).Times(0);
149 auto mounter = helper_.CreateMounter(
150 kWorkingDir, kSomeSource, kMountDir,
151 {"IdentityFile=foo/bar", "UserKnownHostsFile=/foo/../baz"});
152 EXPECT_FALSE(mounter);
153}
154
155// Verifies that CreateMounter fails if fails to copy identity files.
156TEST_F(SshfsHelperTest, CreateMounter_CopyFails) {
157 EXPECT_CALL(platform_, CopyFile("/foo/bar", "/wkdir/bar"))
158 .WillRepeatedly(Return(false));
159 auto mounter = helper_.CreateMounter(kWorkingDir, kSomeSource, kMountDir,
160 {"IdentityFile=/foo/bar"});
161 EXPECT_FALSE(mounter);
162}
163
164// Verifies that CanMount correctly identifies handleable URIs.
165TEST_F(SshfsHelperTest, CanMount) {
166 EXPECT_TRUE(helper_.CanMount(Uri::Parse("sshfs://foo")));
167 EXPECT_FALSE(helper_.CanMount(Uri::Parse("sshfss://foo")));
168 EXPECT_FALSE(helper_.CanMount(Uri::Parse("ssh://foo")));
169 EXPECT_FALSE(helper_.CanMount(Uri::Parse("sshfs://")));
170}
171
172// Verifies that GetTargetSuffix escapes unwanted chars in URI.
173TEST_F(SshfsHelperTest, GetTargetSuffix) {
174 EXPECT_EQ("foo", helper_.GetTargetSuffix(Uri::Parse("sshfs://foo")));
175 EXPECT_EQ("usr@host_com:",
176 helper_.GetTargetSuffix(Uri::Parse("sshfs://usr@host.com:")));
177 EXPECT_EQ("host:$some$path$__",
178 helper_.GetTargetSuffix(Uri::Parse("sshfs://host:/some/path/..")));
179}
180
181} // namespace cros_disks