blob: 7003838663f7ad732e1a71d9eeabdfc86ec7a078 [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
Sergei Datsenkobcd8e462018-04-20 15:44:56 +100021using testing::DoAll;
22using testing::Eq;
23using testing::HasSubstr;
24using testing::Not;
25using testing::Return;
26using testing::SetArgPointee;
27using testing::StrEq;
28using testing::_;
29
30namespace cros_disks {
31
32namespace {
33
34const uid_t kMountUID = 200;
35const gid_t kMountGID = 201;
36const uid_t kFilesUID = 700;
37const uid_t kFilesGID = 701;
38const uid_t kFilesAccessGID = 1501;
39const base::FilePath kWorkingDir("/wkdir");
40const base::FilePath kMountDir("/mnt");
41const Uri kSomeSource("sshfs", "src");
42
43// Mock Platform implementation for testing.
44class MockPlatform : public Platform {
45 public:
46 MockPlatform() = default;
47
Ben Chan213c6d92019-04-10 16:21:52 -070048 bool GetUserAndGroupId(const std::string& user,
Sergei Datsenkobcd8e462018-04-20 15:44:56 +100049 uid_t* user_id,
50 gid_t* group_id) const override {
51 if (user == "fuse-sshfs") {
52 if (user_id)
53 *user_id = kMountUID;
54 if (group_id)
55 *group_id = kMountGID;
56 return true;
57 }
58 if (user == FUSEHelper::kFilesUser) {
59 if (user_id)
60 *user_id = kFilesUID;
61 if (group_id)
62 *group_id = kFilesGID;
63 return true;
64 }
65 return false;
66 }
67
Ben Chan213c6d92019-04-10 16:21:52 -070068 bool GetGroupId(const std::string& group, gid_t* group_id) const override {
Sergei Datsenkobcd8e462018-04-20 15:44:56 +100069 if (group == FUSEHelper::kFilesGroup) {
70 if (group_id)
71 *group_id = kFilesAccessGID;
72 return true;
73 }
74 return false;
75 }
76
Sergei Datsenkobcd8e462018-04-20 15:44:56 +100077 MOCK_CONST_METHOD3(SetOwnership,
Ben Chan213c6d92019-04-10 16:21:52 -070078 bool(const std::string& path,
79 uid_t user_id,
80 gid_t group_id));
81 MOCK_CONST_METHOD2(SetPermissions,
82 bool(const std::string& path, mode_t mode));
Sergei Datsenkoad2cb6a2018-05-15 17:34:26 +100083 MOCK_CONST_METHOD3(WriteFile,
Ben Chan213c6d92019-04-10 16:21:52 -070084 int(const std::string& path, const char* data, int size));
Sergei Datsenkobcd8e462018-04-20 15:44:56 +100085};
86
87} // namespace
88
89class SshfsHelperTest : public ::testing::Test {
90 public:
91 SshfsHelperTest() : helper_(&platform_) {
92 ON_CALL(platform_, SetOwnership(_, kMountUID, getgid()))
93 .WillByDefault(Return(true));
94 ON_CALL(platform_, SetPermissions(_, 0770)).WillByDefault(Return(true));
Sergei Datsenkoad2cb6a2018-05-15 17:34:26 +100095 ON_CALL(platform_, WriteFile(_, _, _)).WillByDefault(Return(-1));
Sergei Datsenkobcd8e462018-04-20 15:44:56 +100096 }
97
98 protected:
99 MockPlatform platform_;
100 SshfsHelper helper_;
101};
102
103// Verifies that CreateMounter creates mounter in a simple case.
104TEST_F(SshfsHelperTest, CreateMounter_SimpleOptions) {
105 auto mounter = helper_.CreateMounter(kWorkingDir, kSomeSource, kMountDir, {});
106 EXPECT_EQ("sshfs", mounter->filesystem_type());
Sergei Datsenko3cf72cb2019-04-01 11:27:50 +1100107 EXPECT_EQ("src", mounter->source());
108 EXPECT_EQ("/mnt", mounter->target_path().value());
Ben Chan213c6d92019-04-10 16:21:52 -0700109 std::string opts = mounter->mount_options().ToString();
Sergei Datsenkobcd8e462018-04-20 15:44:56 +1000110 EXPECT_THAT(opts, HasSubstr("BatchMode=yes"));
111 EXPECT_THAT(opts, HasSubstr("PasswordAuthentication=no"));
112 EXPECT_THAT(opts, HasSubstr("KbdInteractiveAuthentication=no"));
Joel Hockey1a00fef2018-07-26 20:25:39 -0700113 EXPECT_THAT(opts, HasSubstr("follow_symlinks"));
Sergei Datsenkobcd8e462018-04-20 15:44:56 +1000114 EXPECT_THAT(opts, HasSubstr("uid=700"));
115 EXPECT_THAT(opts, HasSubstr("gid=1501"));
116}
117
Sergei Datsenkoad2cb6a2018-05-15 17:34:26 +1000118// Verifies that CreateMounter writes files to the working dir when provided.
119TEST_F(SshfsHelperTest, CreateMounter_WriteFiles) {
120 EXPECT_CALL(platform_, WriteFile("/wkdir/id", StrEq("some key"), 8))
121 .WillOnce(Return(8));
122 EXPECT_CALL(platform_, WriteFile("/wkdir/known_hosts", StrEq("some host"), 9))
123 .WillOnce(Return(9));
124 EXPECT_CALL(platform_, SetPermissions("/wkdir/id", 0600))
Sergei Datsenkobcd8e462018-04-20 15:44:56 +1000125 .WillOnce(Return(true));
Sergei Datsenkoad2cb6a2018-05-15 17:34:26 +1000126 EXPECT_CALL(platform_, SetPermissions("/wkdir/known_hosts", 0600))
Sergei Datsenkobcd8e462018-04-20 15:44:56 +1000127 .WillOnce(Return(true));
128 EXPECT_CALL(platform_, SetPermissions("/wkdir", 0770)).WillOnce(Return(true));
Sergei Datsenkoad2cb6a2018-05-15 17:34:26 +1000129 EXPECT_CALL(platform_, SetOwnership("/wkdir/id", kMountUID, kMountGID))
Sergei Datsenkobcd8e462018-04-20 15:44:56 +1000130 .WillOnce(Return(true));
Sergei Datsenkoad2cb6a2018-05-15 17:34:26 +1000131 EXPECT_CALL(platform_,
132 SetOwnership("/wkdir/known_hosts", kMountUID, kMountGID))
Sergei Datsenkobcd8e462018-04-20 15:44:56 +1000133 .WillOnce(Return(true));
134 EXPECT_CALL(platform_, SetOwnership("/wkdir", kMountUID, getgid()))
135 .WillOnce(Return(true));
136 auto mounter = helper_.CreateMounter(
137 kWorkingDir, kSomeSource, kMountDir,
Sergei Datsenkoad2cb6a2018-05-15 17:34:26 +1000138 {"IdentityBase64=c29tZSBrZXk=", "UserKnownHostsBase64=c29tZSBob3N0",
139 "IdentityFile=/foo/bar", "UserKnownHostsFile=/foo/baz",
Sergei Datsenko1aa55362018-05-14 15:19:27 +1000140 "HostName=localhost", "Port=2222"});
Ben Chan213c6d92019-04-10 16:21:52 -0700141 std::string opts = mounter->mount_options().ToString();
Sergei Datsenkoad2cb6a2018-05-15 17:34:26 +1000142 EXPECT_THAT(opts, HasSubstr("IdentityFile=/wkdir/id"));
143 EXPECT_THAT(opts, HasSubstr("UserKnownHostsFile=/wkdir/known_hosts"));
Sergei Datsenko1aa55362018-05-14 15:19:27 +1000144 EXPECT_THAT(opts, HasSubstr("HostName=localhost"));
145 EXPECT_THAT(opts, HasSubstr("Port=2222"));
Sergei Datsenkoad2cb6a2018-05-15 17:34:26 +1000146 EXPECT_THAT(opts, Not(HasSubstr("Base64")));
147 EXPECT_THAT(opts, Not(HasSubstr("c29tZSB")));
Sergei Datsenkobcd8e462018-04-20 15:44:56 +1000148 EXPECT_THAT(opts, Not(HasSubstr("/foo/bar")));
149 EXPECT_THAT(opts, Not(HasSubstr("/foo/baz")));
150}
151
Sergei Datsenkobcd8e462018-04-20 15:44:56 +1000152// Verifies that CanMount correctly identifies handleable URIs.
153TEST_F(SshfsHelperTest, CanMount) {
154 EXPECT_TRUE(helper_.CanMount(Uri::Parse("sshfs://foo")));
155 EXPECT_FALSE(helper_.CanMount(Uri::Parse("sshfss://foo")));
156 EXPECT_FALSE(helper_.CanMount(Uri::Parse("ssh://foo")));
157 EXPECT_FALSE(helper_.CanMount(Uri::Parse("sshfs://")));
158}
159
160// Verifies that GetTargetSuffix escapes unwanted chars in URI.
161TEST_F(SshfsHelperTest, GetTargetSuffix) {
162 EXPECT_EQ("foo", helper_.GetTargetSuffix(Uri::Parse("sshfs://foo")));
163 EXPECT_EQ("usr@host_com:",
164 helper_.GetTargetSuffix(Uri::Parse("sshfs://usr@host.com:")));
165 EXPECT_EQ("host:$some$path$__",
166 helper_.GetTargetSuffix(Uri::Parse("sshfs://host:/some/path/..")));
167}
168
169} // namespace cros_disks