diff --git a/ChangeLog.txt b/ChangeLog.txt index 69451c10..26b82937 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -4,3 +4,6 @@ Version 0.8.1 * Password Encryption: If the configuration file is not specified as command line parameter, it will be put into the base directory. The filesystem can be mounted with the password only, without specifying a config file on command line. * Logfiles: Added a --logfile option to specify where logs should be written to. If the option is not specified, CryFs logs to syslog. * Running in Background: Fixed daemonization. When CryFs is run without "-f" flag, it will run in background. +* Better error messages when base directory is not existing, not readable or not writeable. +* Allow --cipher=xxx to specify cipher on command line. If cryfs is creating a new filesystem, it will use this cipher. If it is opening an existing filesystem, it will check whether this is the cipher used by it. +* --show-ciphers shows a list of all supported ciphers \ No newline at end of file diff --git a/src/Cli.cpp b/src/Cli.cpp index dd5e9278..be901ae6 100644 --- a/src/Cli.cpp +++ b/src/Cli.cpp @@ -102,7 +102,7 @@ namespace cryfs { auto console = make_unique_ref(); auto &keyGenerator = Random::OSRandom(); std::cout << "Loading config file..." << std::endl; - auto config = CryConfigLoader(std::move(console), keyGenerator, &Cli::_askPassword).loadOrCreate(configFile); + auto config = CryConfigLoader(std::move(console), keyGenerator, &Cli::_askPassword, options.cipher()).loadOrCreate(configFile); std::cout << "Loading config file...done" << std::endl; if (config == none) { std::cerr << "Could not load config file. Did you enter the correct password?" << std::endl; @@ -218,7 +218,7 @@ namespace cryfs { cpputils::showBacktraceOnSigSegv(); _showVersion(); - ProgramOptions options = program_options::Parser(argc, argv).parse(); + ProgramOptions options = program_options::Parser(argc, argv).parse(CryCiphers::supportedCipherNames()); try { _sanityChecks(options); diff --git a/src/config/CryConfigCreator.cpp b/src/config/CryConfigCreator.cpp index 2ed33493..61a1bdb1 100644 --- a/src/config/CryConfigCreator.cpp +++ b/src/config/CryConfigCreator.cpp @@ -6,21 +6,33 @@ using cpputils::unique_ref; using cpputils::RandomGenerator; using std::string; using std::vector; +using boost::optional; +using boost::none; + namespace cryfs { CryConfigCreator::CryConfigCreator(unique_ref console, RandomGenerator &encryptionKeyGenerator) :_console(std::move(console)), _encryptionKeyGenerator(encryptionKeyGenerator) { } - CryConfig CryConfigCreator::create() { + CryConfig CryConfigCreator::create(const optional &cipher) { CryConfig config; - config.SetCipher(_generateCipher()); + config.SetCipher(_generateCipher(cipher)); config.SetEncryptionKey(_generateEncKey(config.Cipher())); config.SetRootBlob(_generateRootBlobKey()); return config; } - string CryConfigCreator::_generateCipher() { + string CryConfigCreator::_generateCipher(const optional &cipher) { + if (cipher != none) { + ASSERT(std::find(CryCiphers::supportedCipherNames().begin(), CryCiphers::supportedCipherNames().end(), *cipher) != CryCiphers::supportedCipherNames().end(), "Invalid cipher"); + return *cipher; + } else { + return _askCipher(); + } + } + + string CryConfigCreator::_askCipher() { vector ciphers = CryCiphers::supportedCipherNames(); string cipherName = ""; bool askAgain = true; diff --git a/src/config/CryConfigCreator.h b/src/config/CryConfigCreator.h index 66731b46..ecc92123 100644 --- a/src/config/CryConfigCreator.h +++ b/src/config/CryConfigCreator.h @@ -13,9 +13,10 @@ namespace cryfs { CryConfigCreator(cpputils::unique_ref console, cpputils::RandomGenerator &encryptionKeyGenerator); CryConfigCreator(CryConfigCreator &&rhs) = default; - CryConfig create(); + CryConfig create(const boost::optional &cipher); private: - std::string _generateCipher(); + std::string _generateCipher(const boost::optional &cipher); + std::string _askCipher(); std::string _generateEncKey(const std::string &cipher); std::string _generateRootBlobKey(); bool _showWarningForCipherAndReturnIfOk(const std::string &cipherName); diff --git a/src/config/CryConfigLoader.cpp b/src/config/CryConfigLoader.cpp index 1fbe3a82..a47299a5 100644 --- a/src/config/CryConfigLoader.cpp +++ b/src/config/CryConfigLoader.cpp @@ -20,8 +20,8 @@ using namespace cpputils::logging; namespace cryfs { -CryConfigLoader::CryConfigLoader(unique_ref console, RandomGenerator &keyGenerator, function askPassword) - : _creator(std::move(console), keyGenerator), _askPassword(askPassword) { +CryConfigLoader::CryConfigLoader(unique_ref console, RandomGenerator &keyGenerator, function askPassword, const optional &cipher) + : _creator(std::move(console), keyGenerator), _askPassword(askPassword), _cipher(cipher) { } optional CryConfigLoader::_loadConfig(const bf::path &filename) { @@ -31,6 +31,9 @@ optional CryConfigLoader::_loadConfig(const bf::path &filename) { LOG(ERROR) << "Could not load config file. Wrong password?"; return none; } + if (_cipher != none && config->config()->Cipher() != *_cipher) { + throw std::runtime_error("Filesystem uses "+config->config()->Cipher()+" cipher and not "+*_cipher+" as specified."); + } return std::move(*config); } diff --git a/src/config/CryConfigLoader.h b/src/config/CryConfigLoader.h index 634f38ef..062495ec 100644 --- a/src/config/CryConfigLoader.h +++ b/src/config/CryConfigLoader.h @@ -13,7 +13,7 @@ namespace cryfs { class CryConfigLoader { public: - CryConfigLoader(cpputils::unique_ref console, cpputils::RandomGenerator &keyGenerator, std::function askPassword); + CryConfigLoader(cpputils::unique_ref console, cpputils::RandomGenerator &keyGenerator, std::function askPassword, const boost::optional &cipher); CryConfigLoader(CryConfigLoader &&rhs) = default; template @@ -26,6 +26,7 @@ private: CryConfigCreator _creator; std::function _askPassword; + boost::optional _cipher; DISALLOW_COPY_AND_ASSIGN(CryConfigLoader); }; @@ -41,7 +42,7 @@ boost::optional CryConfigLoader::loadOrCreate(const boost::filesy template CryConfigFile CryConfigLoader::_createConfig(const boost::filesystem::path &filename) { - auto config = _creator.create(); + auto config = _creator.create(_cipher); //TODO Ask confirmation if using insecure password (<8 characters) std::string password = _askPassword(); return CryConfigFile::create(filename, std::move(config), password); diff --git a/src/program_options/Parser.cpp b/src/program_options/Parser.cpp index df49b4ad..8caf859c 100644 --- a/src/program_options/Parser.cpp +++ b/src/program_options/Parser.cpp @@ -13,7 +13,9 @@ using std::string; using boost::optional; using boost::none; -Parser::Parser(int argc, char *argv[]) :_options(_argsToVector(argc, argv)) {} +Parser::Parser(int argc, char *argv[]) + :_options(_argsToVector(argc, argv)) { +} vector Parser::_argsToVector(int argc, char *argv[]) { vector result; @@ -23,9 +25,9 @@ vector Parser::_argsToVector(int argc, char *argv[]) { return result; } -ProgramOptions Parser::parse() const { +ProgramOptions Parser::parse(const vector &supportedCiphers) const { pair, vector> options = splitAtDoubleDash(_options); - po::variables_map vm = _parseOptionsOrShowHelp(options.first); + po::variables_map vm = _parseOptionsOrShowHelp(options.first, supportedCiphers); string baseDir = vm["base-dir"].as(); string mountDir = vm["mount-dir"].as(); @@ -38,19 +40,31 @@ ProgramOptions Parser::parse() const { if (vm.count("logfile")) { logfile = vm["logfile"].as(); } + optional cipher = none; + if (vm.count("cipher")) { + cipher = vm["cipher"].as(); + _checkValidCipher(*cipher, supportedCiphers); + } - return ProgramOptions(baseDir, mountDir, configfile, foreground, logfile, options.second); + return ProgramOptions(baseDir, mountDir, configfile, foreground, logfile, cipher, options.second); } -po::variables_map Parser::_parseOptionsOrShowHelp(const vector options) { +void Parser::_checkValidCipher(const string &cipher, const vector &supportedCiphers) { + if (std::find(supportedCiphers.begin(), supportedCiphers.end(), cipher) == supportedCiphers.end()) { + std::cerr << "Invalid cipher: " << cipher << std::endl; + exit(1); + } +} + +po::variables_map Parser::_parseOptionsOrShowHelp(const vector options, const vector &supportedCiphers) { try { - return _parseOptions(options); + return _parseOptions(options, supportedCiphers); } catch(const std::exception &e) { _showHelpAndExit(); } } -po::variables_map Parser::_parseOptions(const vector options) { +po::variables_map Parser::_parseOptions(const vector options, const vector &supportedCiphers) { po::options_description desc; po::positional_options_description positional_desc; _addAllowedOptions(&desc); @@ -62,6 +76,9 @@ po::variables_map Parser::_parseOptions(const vector options) { if (vm.count("help")) { _showHelpAndExit(); } + if (vm.count("show-ciphers")) { + _showCiphersAndExit(supportedCiphers); + } po::notify(vm); return vm; @@ -73,6 +90,8 @@ void Parser::_addAllowedOptions(po::options_description *desc) { ("help,h", "show help message") ("config,c", po::value(), "Configuration file") ("foreground,f", "Run CryFS in foreground.") + ("cipher", po::value(), "Cipher to use for encryption. See possible values by calling cryfs with --show-ciphers") + ("show-ciphers", "Show list of supported ciphers.") ("logfile", po::value(), "Specify the file to write log messages to. If this is not specified, log messages will go to stdout, or syslog if CryFS is running in the background.") ; desc->add(options); @@ -89,6 +108,13 @@ void Parser::_addPositionalOptionForBaseDir(po::options_description *desc, po::p desc->add(hidden); } +[[noreturn]] void Parser::_showCiphersAndExit(const vector &supportedCiphers) { + for (const auto &cipher : supportedCiphers) { + std::cerr << cipher << "\n"; + } + exit(0); +} + [[noreturn]] void Parser::_showHelpAndExit() { cerr << "Usage: cryfs [options] rootDir mountPoint [-- [FUSE Mount Options]]\n"; po::options_description desc; diff --git a/src/program_options/Parser.h b/src/program_options/Parser.h index 852686a4..c884cda1 100644 --- a/src/program_options/Parser.h +++ b/src/program_options/Parser.h @@ -11,7 +11,7 @@ namespace cryfs { public: Parser(int argc, char *argv[]); - ProgramOptions parse() const; + ProgramOptions parse(const std::vector &supportedCiphers) const; private: static std::vector _argsToVector(int argc, char *argv[]); @@ -19,8 +19,10 @@ namespace cryfs { static void _addPositionalOptionForBaseDir(boost::program_options::options_description *desc, boost::program_options::positional_options_description *positional); [[noreturn]] static void _showHelpAndExit(); - static boost::program_options::variables_map _parseOptionsOrShowHelp(const std::vector options); - static boost::program_options::variables_map _parseOptions(const std::vector options); + [[noreturn]] static void _showCiphersAndExit(const std::vector &supportedCiphers); + static boost::program_options::variables_map _parseOptionsOrShowHelp(const std::vector options, const std::vector &supportedCiphers); + static boost::program_options::variables_map _parseOptions(const std::vector options, const std::vector &supportedCiphers); + static void _checkValidCipher(const std::string &cipher, const std::vector &supportedCiphers); std::vector _options; }; diff --git a/src/program_options/ProgramOptions.cpp b/src/program_options/ProgramOptions.cpp index 7d5ac080..d7bca823 100644 --- a/src/program_options/ProgramOptions.cpp +++ b/src/program_options/ProgramOptions.cpp @@ -8,9 +8,10 @@ using std::vector; using boost::optional; ProgramOptions::ProgramOptions(const string &baseDir, const string &mountDir, const optional &configFile, - bool foreground, const optional &logFile, const vector &fuseOptions) + bool foreground, const optional &logFile, const optional &cipher, + const vector &fuseOptions) :_baseDir(baseDir), _mountDir(new char[mountDir.size()+1]), _configFile(configFile), _foreground(foreground), - _logFile(logFile), _fuseOptions(fuseOptions) { + _logFile(logFile), _cipher(cipher), _fuseOptions(fuseOptions) { std::memcpy(_mountDir, mountDir.c_str(), mountDir.size()+1); // Fuse needs the mountDir passed as first option (first option = position 1, since 0 is the executable name) ASSERT(_fuseOptions.size() >= 1, "There has to be one parameter at least for the executable name"); @@ -50,6 +51,10 @@ const optional &ProgramOptions::logFile() const { return _logFile; } +const optional &ProgramOptions::cipher() const { + return _cipher; +} + const vector &ProgramOptions::fuseOptions() const { return _fuseOptions; } diff --git a/src/program_options/ProgramOptions.h b/src/program_options/ProgramOptions.h index f242fd52..113777f2 100644 --- a/src/program_options/ProgramOptions.h +++ b/src/program_options/ProgramOptions.h @@ -12,7 +12,7 @@ namespace cryfs { class ProgramOptions final { public: ProgramOptions(const std::string &baseDir, const std::string &mountDir, const boost::optional &configFile, - bool foreground, const boost::optional &logFile, + bool foreground, const boost::optional &logFile, const boost::optional &cipher, const std::vector &fuseOptions); ProgramOptions(ProgramOptions &&rhs); ~ProgramOptions(); @@ -22,6 +22,7 @@ namespace cryfs { const boost::optional &configFile() const; bool foreground() const; const boost::optional &logFile() const; + const boost::optional &cipher() const; const std::vector &fuseOptions() const; private: @@ -30,6 +31,7 @@ namespace cryfs { boost::optional _configFile; bool _foreground; boost::optional _logFile; + boost::optional _cipher; std::vector _fuseOptions; DISALLOW_COPY_AND_ASSIGN(ProgramOptions); diff --git a/test/cli/CliTest_Setup.cpp b/test/cli/CliTest_Setup.cpp index 33a429a9..3012178e 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.c_str(), mountdir.c_str()}); + EXPECT_RUN_SUCCESS({basedir.c_str(), mountdir.c_str(), "--cipher", "aes-256-gcm"}, basedir); } TEST_F(CliTest_Setup, NotexistingLogfileGiven) { TempFile notexisting_logfile(false); - EXPECT_RUN_SUCCESS({basedir.c_str(), mountdir.c_str(), "--logfile", notexisting_logfile.path().c_str()}); + EXPECT_RUN_SUCCESS({basedir.c_str(), mountdir.c_str(), "--logfile", notexisting_logfile.path().c_str()}, basedir); //TODO Expect logfile is used (check logfile content) } TEST_F(CliTest_Setup, ExistingLogfileGiven) { - EXPECT_RUN_SUCCESS({basedir.c_str(), mountdir.c_str(), "--logfile", logfile.path().c_str()}); + EXPECT_RUN_SUCCESS({basedir.c_str(), mountdir.c_str(), "--logfile", logfile.path().c_str()}, basedir); //TODO Expect logfile is used (check logfile content) } TEST_F(CliTest_Setup, ConfigfileGiven) { - EXPECT_RUN_SUCCESS({basedir.c_str(), "--config", configfile.path().c_str(), mountdir.c_str()}); + EXPECT_RUN_SUCCESS({basedir.c_str(), "--config", configfile.path().c_str(), mountdir.c_str()}, basedir); } TEST_F(CliTest_Setup, FuseOptionGiven) { - EXPECT_RUN_SUCCESS({basedir.c_str(), mountdir.c_str(), "--", "-f"}); + EXPECT_RUN_SUCCESS({basedir.c_str(), mountdir.c_str(), "--", "-f"}, basedir); } \ No newline at end of file diff --git a/test/cli/CliTest_WrongEnvironment.cpp b/test/cli/CliTest_WrongEnvironment.cpp index 87a02995..235a28b8 100644 --- a/test/cli/CliTest_WrongEnvironment.cpp +++ b/test/cli/CliTest_WrongEnvironment.cpp @@ -43,7 +43,7 @@ public: } void Test_Run_Success() { - EXPECT_RUN_SUCCESS(args()); + EXPECT_RUN_SUCCESS(args(), basedir); } void Test_Run_Error(const char *expectedError) { diff --git a/test/cli/testutils/CliTest.h b/test/cli/testutils/CliTest.h index 46b811f5..efdaa31a 100644 --- a/test/cli/testutils/CliTest.h +++ b/test/cli/testutils/CliTest.h @@ -6,6 +6,7 @@ #include #include #include "../../../src/Cli.h" +#include class CliTest : public ::testing::Test { public: @@ -40,14 +41,25 @@ public: ); } - void EXPECT_RUN_SUCCESS(std::vector args) { - //TODO - /*EXPECT_EXIT( + class _UnmountFilesystemInDestructor final { + public: + _UnmountFilesystemInDestructor(const boost::filesystem::path &baseDir) :_baseDir(baseDir) {} + ~_UnmountFilesystemInDestructor() { + if (0 != system((std::string("fusermount -u ")+_baseDir.c_str()).c_str()), "Could not unmount cryfs") { + cpputils::logging::LOG(cpputils::logging::ERROR) << "Could not unmount cryfs"; + } + } + private: + boost::filesystem::path _baseDir; + }; + + void EXPECT_RUN_SUCCESS(std::vector args, const boost::filesystem::path &baseDir) { + /*_UnmountFilesystemInDestructor raii(baseDir); + EXPECT_EXIT( run(args), ::testing::ExitedWithCode(0), "Filesystem is running" );*/ - //TODO Then stop running cryfs process again } }; diff --git a/test/config/CryConfigCreatorTest.cpp b/test/config/CryConfigCreatorTest.cpp index 2badcaa1..c0523798 100644 --- a/test/config/CryConfigCreatorTest.cpp +++ b/test/config/CryConfigCreatorTest.cpp @@ -36,33 +36,38 @@ public: #define EXPECT_ASK_FOR_CIPHER() EXPECT_CALL(*console, ask(HasSubstr("block cipher"), UnorderedElementsAreArray(CryCiphers::supportedCipherNames()))) -TEST_F(CryConfigCreatorTest, DoesNotCrash) { - EXPECT_ASK_FOR_CIPHER().WillOnce(ChooseAnyCipher()); - CryConfig config = creator.create(); +TEST_F(CryConfigCreatorTest, DoesAskForCipherIfNotSpecified) { + EXPECT_ASK_FOR_CIPHER().Times(1).WillOnce(ChooseAnyCipher()); + CryConfig config = creator.create(none); +} + +TEST_F(CryConfigCreatorTest, DoesNotAskForCipherIfSpecified) { + EXPECT_ASK_FOR_CIPHER().Times(0); + CryConfig config = creator.create(string("aes-256-gcm")); } TEST_F(CryConfigCreatorTest, ChoosesEmptyRootBlobId) { EXPECT_ASK_FOR_CIPHER().WillOnce(ChooseAnyCipher()); - CryConfig config = creator.create(); + CryConfig config = creator.create(none); EXPECT_EQ("", config.RootBlob()); // This tells CryFS to create a new root blob } TEST_F(CryConfigCreatorTest, ChoosesValidEncryptionKey_448) { EXPECT_ASK_FOR_CIPHER().WillOnce(ChooseCipher("mars-448-gcm")); - CryConfig config = creator.create(); + CryConfig config = creator.create(none); cpputils::Mars448_GCM::EncryptionKey::FromString(config.EncryptionKey()); // This crashes if invalid } TEST_F(CryConfigCreatorTest, ChoosesValidEncryptionKey_256) { EXPECT_ASK_FOR_CIPHER().WillOnce(ChooseCipher("aes-256-gcm")); - CryConfig config = creator.create(); -cpputils::AES256_GCM::EncryptionKey::FromString(config.EncryptionKey()); // This crashes if invalid + CryConfig config = creator.create(none); + cpputils::AES256_GCM::EncryptionKey::FromString(config.EncryptionKey()); // This crashes if invalid } TEST_F(CryConfigCreatorTest, ChoosesValidEncryptionKey_128) { EXPECT_ASK_FOR_CIPHER().WillOnce(ChooseCipher("aes-128-gcm")); - CryConfig config = creator.create(); -cpputils::AES128_GCM::EncryptionKey::FromString(config.EncryptionKey()); // This crashes if invalid + CryConfig config = creator.create(none); + cpputils::AES128_GCM::EncryptionKey::FromString(config.EncryptionKey()); // This crashes if invalid } class CryConfigCreatorTest_ChooseCipher: public CryConfigCreatorTest, public ::testing::WithParamInterface { @@ -88,7 +93,7 @@ TEST_P(CryConfigCreatorTest_ChooseCipher, ChoosesCipherCorrectly) { EXPECT_ASK_FOR_CIPHER().WillOnce(ChooseCipher(cipherName)); - CryConfig config = creator.create(); + CryConfig config = creator.create(none); EXPECT_EQ(cipherName, config.Cipher()); } diff --git a/test/config/CryConfigLoaderTest.cpp b/test/config/CryConfigLoaderTest.cpp index b99be336..3062906d 100644 --- a/test/config/CryConfigLoaderTest.cpp +++ b/test/config/CryConfigLoaderTest.cpp @@ -17,22 +17,24 @@ using ::testing::_; using namespace cryfs; +//TODO Test loading with same/different --cipher argument + class CryConfigLoaderTest: public ::testing::Test, public TestWithMockConsole { public: CryConfigLoaderTest(): file(false) {} - CryConfigLoader loader(const string &password) { - return CryConfigLoader(mockConsole(), cpputils::Random::PseudoRandom(), [password] {return password;}); + CryConfigLoader loader(const string &password, const optional &cipher = none) { + return CryConfigLoader(mockConsole(), cpputils::Random::PseudoRandom(), [password] {return password;}, cipher); } - CryConfigFile Create(const string &password = "mypassword") { + CryConfigFile Create(const string &password = "mypassword", const optional &cipher = none) { EXPECT_FALSE(file.exists()); - return loader(password).loadOrCreate(file.path()).value(); + return loader(password, cipher).loadOrCreate(file.path()).value(); } - optional Load(const string &password = "mypassword") { + optional Load(const string &password = "mypassword", const optional &cipher = none) { EXPECT_TRUE(file.exists()); - return loader(password).loadOrCreate(file.path()); + return loader(password, cipher).loadOrCreate(file.path()); } void CreateWithRootBlob(const string &rootBlob, const string &password = "mypassword") { @@ -73,6 +75,21 @@ TEST_F(CryConfigLoaderTest, DoesntLoadIfWrongPassword) { EXPECT_EQ(none, loaded); } +TEST_F(CryConfigLoaderTest, DoesntLoadIfDifferentCipher) { + Create("mypassword", string("aes-256-gcm")); + try { + Load("mypassword", string("aes-256-cfb")); + EXPECT_TRUE(false); // Should throw exception + } catch (const std::runtime_error &e) { + EXPECT_EQ(string("Filesystem uses aes-256-gcm cipher and not aes-256-cfb as specified."), e.what()); + } +} + +TEST_F(CryConfigLoaderTest, DoesLoadIfSameCipher) { + Create("mypassword", string("aes-256-gcm")); + Load("mypassword", string("aes-256-gcm")); +} + TEST_F(CryConfigLoaderTest, RootBlob_Load) { CreateWithRootBlob("rootblobid"); auto loaded = Load().value(); diff --git a/test/filesystem/CryFsTest.cpp b/test/filesystem/CryFsTest.cpp index fdf06e9b..cea3fa93 100644 --- a/test/filesystem/CryFsTest.cpp +++ b/test/filesystem/CryFsTest.cpp @@ -23,6 +23,7 @@ using cpputils::unique_ref; using cpputils::Console; using cpputils::Random; using blockstore::ondisk::OnDiskBlockStore; +using boost::none; namespace bf = boost::filesystem; using namespace cryfs; @@ -33,7 +34,7 @@ public: } CryConfigFile loadOrCreateConfig() { - return CryConfigLoader(mockConsole(), Random::PseudoRandom(), [] {return "mypassword";}).loadOrCreate(config.path()).value(); + return CryConfigLoader(mockConsole(), Random::PseudoRandom(), [] {return "mypassword";}, none).loadOrCreate(config.path()).value(); } unique_ref blockStore() { diff --git a/test/filesystem/FileSystemTest.cpp b/test/filesystem/FileSystemTest.cpp index 62e9114d..2552f3c6 100644 --- a/test/filesystem/FileSystemTest.cpp +++ b/test/filesystem/FileSystemTest.cpp @@ -13,6 +13,7 @@ using cpputils::Random; using fspp::Device; using ::testing::Return; using ::testing::_; +using boost::none; using blockstore::testfake::FakeBlockStore; @@ -26,7 +27,7 @@ public: unique_ref createDevice() override { auto blockStore = cpputils::make_unique_ref(); - auto config = CryConfigLoader(mockConsole(), Random::PseudoRandom(), [] {return "mypassword";}) + auto config = CryConfigLoader(mockConsole(), Random::PseudoRandom(), [] {return "mypassword";}, none) .loadOrCreate(configFile.path()).value(); return make_unique_ref(std::move(config), std::move(blockStore)); } diff --git a/test/program_options/ParserTest.cpp b/test/program_options/ParserTest.cpp index ea128cbd..0eb2d1df 100644 --- a/test/program_options/ParserTest.cpp +++ b/test/program_options/ParserTest.cpp @@ -1,6 +1,8 @@ #include "testutils/ProgramOptionsTestBase.h" #include "../../src/program_options/Parser.h" +#include "../../src/config/CryCipher.h" +using namespace cryfs; using namespace cryfs::program_options; using std::vector; using boost::none; @@ -9,7 +11,7 @@ class ProgramOptionsParserTest: public ProgramOptionsTestBase { public: ProgramOptions parse(std::initializer_list options) { vector _options = ProgramOptionsTestBase::options(options); - return Parser(_options.size(), _options.data()).parse(); + return Parser(_options.size(), _options.data()).parse(CryCiphers::supportedCipherNames()); } }; @@ -29,18 +31,27 @@ TEST_F(ProgramOptionsParserTest, MissingDir) { TEST_F(ProgramOptionsParserTest, HelpLongOption) { EXPECT_DEATH( - parse({"./myExecutable", "--help"}), - "Usage:" + parse({"./myExecutable", "--help"}), + "Usage:" ); } TEST_F(ProgramOptionsParserTest, HelpShortOption) { EXPECT_DEATH( - parse({"./myExecutable", "-h"}), - "Usage:" + parse({"./myExecutable", "-h"}), + "Usage:" ); } +TEST_F(ProgramOptionsParserTest, ShowCiphers) { + EXPECT_EXIT( + parse({"./myExecutable", "--show-ciphers"}), + ::testing::ExitedWithCode(0), + "aes-256-gcm" + ); +} + + TEST_F(ProgramOptionsParserTest, NoSpecialOptions) { ProgramOptions options = parse({"./myExecutable", "/home/user/baseDir", "/home/user/mountDir"}); EXPECT_EQ("/home/user/baseDir", options.baseDir()); @@ -60,6 +71,18 @@ TEST_F(ProgramOptionsParserTest, ConfigfileGiven) { EXPECT_EQ("/home/user/myconfigfile", options.configFile().value()); } +TEST_F(ProgramOptionsParserTest, CipherGiven) { + ProgramOptions options = parse({"./myExecutable", "/home/user/baseDir", "--cipher", "aes-256-gcm", "/home/user/mountDir"}); + EXPECT_EQ("aes-256-gcm", options.cipher().value()); +} + +TEST_F(ProgramOptionsParserTest, InvalidCipher) { + EXPECT_DEATH( + parse({"./myExecutable", "/home/user/baseDir", "--cipher", "invalid-cipher", "/home/user/mountDir"}), + "Invalid cipher: invalid-cipher" + ); +} + TEST_F(ProgramOptionsParserTest, FuseOptionGiven) { ProgramOptions options = parse({"./myExecutable", "/home/user/baseDir", "/home/user/mountDir", "--", "-f"}); EXPECT_EQ("/home/user/baseDir", options.baseDir()); diff --git a/test/program_options/ProgramOptionsTest.cpp b/test/program_options/ProgramOptionsTest.cpp index 46a48803..1375a192 100644 --- a/test/program_options/ProgramOptionsTest.cpp +++ b/test/program_options/ProgramOptionsTest.cpp @@ -10,53 +10,63 @@ using std::string; class ProgramOptionsTest: public ProgramOptionsTestBase {}; TEST_F(ProgramOptionsTest, BaseDir) { - ProgramOptions testobj("/home/user/mydir", "", none, false, none, options({"./myExecutable"})); + ProgramOptions testobj("/home/user/mydir", "", none, false, none, none, options({"./myExecutable"})); EXPECT_EQ("/home/user/mydir", testobj.baseDir()); } TEST_F(ProgramOptionsTest, MountDir) { - ProgramOptions testobj("", "/home/user/mydir", none, false, none, options({"./myExecutable"})); + ProgramOptions testobj("", "/home/user/mydir", none, false, none, none, options({"./myExecutable"})); EXPECT_EQ("/home/user/mydir", testobj.mountDir()); } TEST_F(ProgramOptionsTest, ConfigfileNone) { - ProgramOptions testobj("", "", none, true, none, options({"./myExecutable"})); + ProgramOptions testobj("", "", none, true, none, none, options({"./myExecutable"})); EXPECT_EQ(none, testobj.configFile()); } TEST_F(ProgramOptionsTest, ConfigfileSome) { - ProgramOptions testobj("", "", string("/home/user/configfile"), true, none, options({"./myExecutable"})); + ProgramOptions testobj("", "", string("/home/user/configfile"), true, none, none, options({"./myExecutable"})); EXPECT_EQ("/home/user/configfile", testobj.configFile().get()); } TEST_F(ProgramOptionsTest, ForegroundFalse) { - ProgramOptions testobj("", "", none, false, none, options({"./myExecutable"})); + ProgramOptions testobj("", "", none, false, none, none, options({"./myExecutable"})); EXPECT_FALSE(testobj.foreground()); } TEST_F(ProgramOptionsTest, ForegroundTrue) { - ProgramOptions testobj("", "", none, true, none, options({"./myExecutable"})); + ProgramOptions testobj("", "", none, true, none, none, options({"./myExecutable"})); EXPECT_TRUE(testobj.foreground()); } TEST_F(ProgramOptionsTest, LogfileNone) { - ProgramOptions testobj("", "", none, true, none, options({"./myExecutable"})); + ProgramOptions testobj("", "", none, true, none, none, options({"./myExecutable"})); EXPECT_EQ(none, testobj.logFile()); } TEST_F(ProgramOptionsTest, LogfileSome) { - ProgramOptions testobj("", "", none, true, string("logfile"), options({"./myExecutable"})); + ProgramOptions testobj("", "", none, true, string("logfile"), none, options({"./myExecutable"})); EXPECT_EQ("logfile", testobj.logFile().get()); } +TEST_F(ProgramOptionsTest, CipherNone) { + ProgramOptions testobj("", "", none, true, none, none, options({"./myExecutable"})); + EXPECT_EQ(none, testobj.cipher()); +} + +TEST_F(ProgramOptionsTest, CipherSome) { + ProgramOptions testobj("", "", none, true, none, string("aes-256-gcm"), options({"./myExecutable"})); + EXPECT_EQ("aes-256-gcm", testobj.cipher().get()); +} + TEST_F(ProgramOptionsTest, EmptyFuseOptions) { - ProgramOptions testobj("/rootDir", "/home/user/mydir", none, false, none, options({"./myExecutable"})); + ProgramOptions testobj("/rootDir", "/home/user/mydir", none, false, none, none, options({"./myExecutable"})); //Fuse should have the mount dir as first parameter EXPECT_VECTOR_EQ({"./myExecutable", "/home/user/mydir"}, testobj.fuseOptions()); } TEST_F(ProgramOptionsTest, SomeFuseOptions) { - ProgramOptions testobj("/rootDir", "/home/user/mydir", none, false, none, options({"./myExecutable", "-f", "--longoption"})); + ProgramOptions testobj("/rootDir", "/home/user/mydir", none, false, none, none, options({"./myExecutable", "-f", "--longoption"})); //Fuse should have the mount dir as first parameter EXPECT_VECTOR_EQ({"./myExecutable", "/home/user/mydir", "-f", "--longoption"}, testobj.fuseOptions()); }