From a37c1af761ee6532aa831e127a790a6a0938a6ff Mon Sep 17 00:00:00 2001 From: Sebastian Messmer Date: Fri, 30 Oct 2015 17:23:08 +0100 Subject: [PATCH] Check that base directory is not inside mount directory --- src/Cli.cpp | 37 +++++++++++++++++++++++++-- src/Cli.h | 3 +++ test/cli/CliTest_Setup.cpp | 10 ++++---- test/cli/CliTest_ShowingHelp.cpp | 6 ++--- test/cli/CliTest_WrongEnvironment.cpp | 36 +++++++++++++++++++++++--- test/cli/testutils/CliTest.h | 8 +++--- 6 files changed, 84 insertions(+), 16 deletions(-) diff --git a/src/Cli.cpp b/src/Cli.cpp index ef6aac12..60323cb5 100644 --- a/src/Cli.cpp +++ b/src/Cli.cpp @@ -25,6 +25,8 @@ #error The used libc implementation has a maximal password size for getpass(). We cannot use it to ask for passwords. #endif +//TODO Many functions accessing the ProgramOptions object. Factor out into class that stores it as a member. + using namespace cryfs; namespace bf = boost::filesystem; @@ -144,9 +146,40 @@ namespace cryfs { } void Cli::_sanityChecks(const ProgramOptions &options) { - if (bf::path(options.baseDir()) == bf::path(options.mountDir())) { - throw std::runtime_error("Can't mount into base directory"); + _checkBasedirAccessible(options); + //TODO Check MountdirAccessible (incl. Permissions) + _checkMountdirDoesntContainBasedir(options); + } + + void Cli::_checkBasedirAccessible(const ProgramOptions &options) { + if (!bf::exists(options.baseDir())) { + throw std::runtime_error("Base directory not found."); } + //TODO Check permissions + } + + void Cli::_checkMountdirDoesntContainBasedir(const ProgramOptions &options) { + if (_pathContains(options.mountDir(), options.baseDir())) { + throw std::runtime_error("Base directory can't be inside the mount directory."); + } + } + + bool Cli::_pathContains(const bf::path &parent, const bf::path &child) { + bf::path absParent = bf::canonical(parent); + bf::path current = bf::canonical(child); + if (absParent.empty() && current.empty()) { + return true; + } + while(!current.empty()) { + std::cout << absParent.c_str() << " cmp " << current.c_str() << std::endl; + if (bf::equivalent(current, absParent)) { + std::cout << "equals" << std::endl; + return true; + } + std::cout << "not equals" << std::endl; + current = current.parent_path(); + } + return false; } int Cli::main(int argc, char *argv[]) { diff --git a/src/Cli.h b/src/Cli.h index 29600af9..fed0d3d4 100644 --- a/src/Cli.h +++ b/src/Cli.h @@ -21,6 +21,9 @@ namespace cryfs { static void _showVersion(); static void _initLogfile(const program_options::ProgramOptions &options); static void _sanityChecks(const program_options::ProgramOptions &options); + static void _checkMountdirDoesntContainBasedir(const program_options::ProgramOptions &options); + static bool _pathContains(const boost::filesystem::path &parent, const boost::filesystem::path &child); + static void _checkBasedirAccessible(const program_options::ProgramOptions &options); }; } diff --git a/test/cli/CliTest_Setup.cpp b/test/cli/CliTest_Setup.cpp index 4d7a65e3..33a429a9 100644 --- a/test/cli/CliTest_Setup.cpp +++ b/test/cli/CliTest_Setup.cpp @@ -6,24 +6,24 @@ using cpputils::TempFile; using CliTest_Setup = CliTest; TEST_F(CliTest_Setup, NoSpecialOptions) { - EXPECT_RUN_SUCCESS({basedir->path().c_str(), mountdir->path().c_str()}); + EXPECT_RUN_SUCCESS({basedir.c_str(), mountdir.c_str()}); } TEST_F(CliTest_Setup, NotexistingLogfileGiven) { TempFile notexisting_logfile(false); - EXPECT_RUN_SUCCESS({basedir->path().c_str(), mountdir->path().c_str(), "--logfile", notexisting_logfile.path().c_str()}); + EXPECT_RUN_SUCCESS({basedir.c_str(), mountdir.c_str(), "--logfile", notexisting_logfile.path().c_str()}); //TODO Expect logfile is used (check logfile content) } TEST_F(CliTest_Setup, ExistingLogfileGiven) { - EXPECT_RUN_SUCCESS({basedir->path().c_str(), mountdir->path().c_str(), "--logfile", logfile.path().c_str()}); + EXPECT_RUN_SUCCESS({basedir.c_str(), mountdir.c_str(), "--logfile", logfile.path().c_str()}); //TODO Expect logfile is used (check logfile content) } TEST_F(CliTest_Setup, ConfigfileGiven) { - EXPECT_RUN_SUCCESS({"/home/user/baseDir", "--config", configfile.path().c_str(), "/home/user/mountDir"}); + EXPECT_RUN_SUCCESS({basedir.c_str(), "--config", configfile.path().c_str(), mountdir.c_str()}); } TEST_F(CliTest_Setup, FuseOptionGiven) { - EXPECT_RUN_SUCCESS({"/home/user/baseDir", "/home/user/mountDir", "--", "-f"}); + EXPECT_RUN_SUCCESS({basedir.c_str(), mountdir.c_str(), "--", "-f"}); } \ No newline at end of file diff --git a/test/cli/CliTest_ShowingHelp.cpp b/test/cli/CliTest_ShowingHelp.cpp index c75c21e0..55c5a607 100644 --- a/test/cli/CliTest_ShowingHelp.cpp +++ b/test/cli/CliTest_ShowingHelp.cpp @@ -7,7 +7,7 @@ TEST_F(CliTest_ShowingHelp, HelpLongOption) { } TEST_F(CliTest_ShowingHelp, HelpLongOptionTogetherWithOtherOptions) { - EXPECT_EXIT_WITH_HELP_MESSAGE({basedir->path().c_str(), mountdir->path().c_str(), "--help"}); + EXPECT_EXIT_WITH_HELP_MESSAGE({basedir.c_str(), mountdir.c_str(), "--help"}); } TEST_F(CliTest_ShowingHelp, HelpShortOption) { @@ -15,7 +15,7 @@ TEST_F(CliTest_ShowingHelp, HelpShortOption) { } TEST_F(CliTest_ShowingHelp, HelpShortOptionTogetherWithOtherOptions) { - EXPECT_EXIT_WITH_HELP_MESSAGE({basedir->path().c_str(), mountdir->path().c_str(), "-h"}); + EXPECT_EXIT_WITH_HELP_MESSAGE({basedir.c_str(), mountdir.c_str(), "-h"}); } TEST_F(CliTest_ShowingHelp, MissingAllOptions) { @@ -23,5 +23,5 @@ TEST_F(CliTest_ShowingHelp, MissingAllOptions) { } TEST_F(CliTest_ShowingHelp, MissingDir) { - EXPECT_EXIT_WITH_HELP_MESSAGE({basedir->path().c_str()}); + EXPECT_EXIT_WITH_HELP_MESSAGE({basedir.c_str()}); } diff --git a/test/cli/CliTest_WrongEnvironment.cpp b/test/cli/CliTest_WrongEnvironment.cpp index 8cfcc5f2..027df98c 100644 --- a/test/cli/CliTest_WrongEnvironment.cpp +++ b/test/cli/CliTest_WrongEnvironment.cpp @@ -38,7 +38,7 @@ public: } vector args() { - vector result = {basedir->path().c_str(), mountdir->path().c_str()}; + vector result = {basedir.c_str(), mountdir.c_str()}; if (GetParam().externalConfigfile) { result.push_back("--config"); result.push_back(configfile.path().c_str()); @@ -70,11 +70,41 @@ TEST_P(CliTest_WrongEnvironment, NoErrorCondition) { TEST_P(CliTest_WrongEnvironment, MountDirIsBaseDir) { mountdir = basedir; - Test_Run_Error("Error: Can't mount into base directory"); + Test_Run_Error("Error: Base directory can't be inside the mount directory"); +} + +bf::path make_relative(const bf::path &path) { + bf::path result; + bf::path cwd = bf::current_path(); + for(auto iter = ++cwd.begin(); iter!=cwd.end(); ++iter) { + result /= ".."; + } + result /= path; + return result; +} + +TEST_P(CliTest_WrongEnvironment, MountDirIsBaseDir_MountDirRelative) { + mountdir = make_relative(basedir); + std::cout << basedir.c_str() << " --- " << mountdir.c_str(); + Test_Run_Error("Error: Base directory can't be inside the mount directory"); +} + +TEST_P(CliTest_WrongEnvironment, MountDirIsBaseDir_BaseDirRelative) { + mountdir = basedir; + basedir = make_relative(basedir); + std::cout << basedir.c_str() << " --- " << mountdir.c_str(); + Test_Run_Error("Error: Base directory can't be inside the mount directory"); +} + +TEST_P(CliTest_WrongEnvironment, MountDirIsBaseDir_BothRelative) { + basedir = make_relative(basedir); + mountdir = basedir; + std::cout << basedir.c_str() << " --- " << mountdir.c_str(); + Test_Run_Error("Error: Base directory can't be inside the mount directory"); } TEST_P(CliTest_WrongEnvironment, BaseDir_DoesntExist) { - basedir->remove(); + _basedir.remove(); Test_Run_Error("Error: Base directory not found"); } diff --git a/test/cli/testutils/CliTest.h b/test/cli/testutils/CliTest.h index 71f103dc..46b811f5 100644 --- a/test/cli/testutils/CliTest.h +++ b/test/cli/testutils/CliTest.h @@ -9,10 +9,12 @@ class CliTest : public ::testing::Test { public: - CliTest(): basedir(std::make_shared()), mountdir(std::make_shared()), logfile(), configfile(false) {} + CliTest(): _basedir(), _mountdir(), basedir(_basedir.path()), mountdir(_mountdir.path()), logfile(), configfile(false) {} - std::shared_ptr basedir; - std::shared_ptr mountdir; + cpputils::TempDir _basedir; + cpputils::TempDir _mountdir; + boost::filesystem::path basedir; + boost::filesystem::path mountdir; cpputils::TempFile logfile; cpputils::TempFile configfile;