Fix test case compatibility with older compilers
This commit is contained in:
commit
a3e26c7480
@ -7,7 +7,7 @@ references:
|
||||
run:
|
||||
name: Initialize Cache
|
||||
command: |
|
||||
echo "${APT_COMPILER_PACKAGE}_${BUILD_TOOLSET}_${CXX}_${CC}_${BUILD_TYPE}" > /tmp/_build_env_vars
|
||||
echo "${APT_COMPILER_PACKAGE}_${BUILD_TOOLSET}_${CXX}_${CC}_${BUILD_TYPE}_${CXXFLAGS}" > /tmp/_build_env_vars
|
||||
echo Build env vars used for cache keys:
|
||||
cat /tmp/_build_env_vars
|
||||
container_setup_pre: &container_setup_pre
|
||||
@ -49,7 +49,7 @@ references:
|
||||
sudo chmod o-w /etc/apt/sources.list.d/clang.list
|
||||
|
||||
DEBIAN_FRONTEND=noninteractive sudo apt-get update -qq
|
||||
DEBIAN_FRONTEND=noninteractive sudo apt-get install -y git ccache $APT_COMPILER_PACKAGE cmake make libcurl4-openssl-dev libboost-filesystem-dev libboost-system-dev libboost-chrono-dev libboost-program-options-dev libboost-thread-dev libcrypto++-dev libssl-dev libfuse-dev python
|
||||
DEBIAN_FRONTEND=noninteractive sudo apt-get install -y git ccache $APT_COMPILER_PACKAGE cmake make libcurl4-openssl-dev libcrypto++-dev libssl-dev libfuse-dev python
|
||||
# Use /dev/urandom when /dev/random is accessed to use less entropy
|
||||
sudo cp -a /dev/urandom /dev/random
|
||||
|
||||
@ -344,6 +344,17 @@ jobs:
|
||||
APT_COMPILER_PACKAGE: clang-5.0
|
||||
CXXFLAGS: "-DCRYFS_NO_COMPATIBILITY"
|
||||
BUILD_TYPE: "Debug"
|
||||
address_sanitizer:
|
||||
<<: *job_definition
|
||||
environment:
|
||||
CC: clang-5.0
|
||||
CXX: clang++-5.0
|
||||
BUILD_TOOLSET: clang
|
||||
APT_COMPILER_PACKAGE: clang-5.0
|
||||
CXXFLAGS: "-O2 -fsanitize=address -fno-omit-frame-pointer -fno-common -fsanitize-address-use-after-scope"
|
||||
BUILD_TYPE: "Debug"
|
||||
# Note: Leak detection is disabled because libfuse itself is leaky...
|
||||
ASAN_OPTIONS: "detect_leaks=0 check_initialization_order=1 detect_stack_use_after_return=1 detect_invalid_pointer_pairs=1 atexit=1"
|
||||
|
||||
workflows:
|
||||
version: 2
|
||||
@ -384,4 +395,6 @@ workflows:
|
||||
<<: *enable_for_tags
|
||||
- no_compatibility:
|
||||
<<: *enable_for_tags
|
||||
- address_sanitizer:
|
||||
<<: *enable_for_tags
|
||||
|
||||
|
@ -111,7 +111,7 @@ size_t CompressedBlock<Compressor>::size() const {
|
||||
|
||||
template<class Compressor>
|
||||
void CompressedBlock<Compressor>::resize(size_t newSize) {
|
||||
_decompressedData = cpputils::DataUtils::resize(std::move(_decompressedData), newSize);
|
||||
_decompressedData = cpputils::DataUtils::resize(_decompressedData, newSize);
|
||||
_dataChanged = true;
|
||||
}
|
||||
|
||||
|
@ -67,7 +67,7 @@ size_t LowToHighLevelBlock::size() const {
|
||||
}
|
||||
|
||||
void LowToHighLevelBlock::resize(size_t newSize) {
|
||||
_data = DataUtils::resize(std::move(_data), newSize);
|
||||
_data = DataUtils::resize(_data, newSize);
|
||||
_dataChanged = true;
|
||||
}
|
||||
|
||||
|
@ -39,7 +39,7 @@ size_t FakeBlock::size() const {
|
||||
}
|
||||
|
||||
void FakeBlock::resize(size_t newSize) {
|
||||
*_data = cpputils::DataUtils::resize(std::move(*_data), newSize);
|
||||
*_data = cpputils::DataUtils::resize(*_data, newSize);
|
||||
_dataChanged = true;
|
||||
}
|
||||
|
||||
|
@ -7,6 +7,7 @@ set(SOURCES
|
||||
crypto/kdf/PasswordBasedKDF.cpp
|
||||
crypto/RandomPadding.cpp
|
||||
crypto/symmetric/EncryptionKey.cpp
|
||||
crypto/hash/Hash.cpp
|
||||
process/daemonize.cpp
|
||||
process/subprocess.cpp
|
||||
tempfile/TempFile.cpp
|
||||
|
@ -10,7 +10,7 @@ namespace cpputils {
|
||||
|
||||
class AssertFailed final: public std::exception {
|
||||
public:
|
||||
AssertFailed(const std::string &message) : _message(message) { }
|
||||
AssertFailed(std::string message) : _message(std::move(message)) { }
|
||||
|
||||
const char *what() const throw() override {
|
||||
return _message.c_str();
|
||||
|
30
src/cpp-utils/crypto/hash/Hash.cpp
Normal file
30
src/cpp-utils/crypto/hash/Hash.cpp
Normal file
@ -0,0 +1,30 @@
|
||||
#include "Hash.h"
|
||||
#include <cpp-utils/random/Random.h>
|
||||
#include <cryptopp/sha.h>
|
||||
|
||||
using cpputils::Random;
|
||||
using CryptoPP::SHA512;
|
||||
|
||||
namespace cpputils {
|
||||
namespace hash {
|
||||
|
||||
Hash hash(const Data& data, Salt salt) {
|
||||
SHA512 hasher;
|
||||
hasher.Update((CryptoPP::byte*)salt.data(), Salt::BINARY_LENGTH);
|
||||
hasher.Update((CryptoPP::byte*)data.data(), data.size());
|
||||
|
||||
Digest digest = Digest::Null();
|
||||
hasher.Final((CryptoPP::byte*)digest.data());
|
||||
|
||||
return Hash{
|
||||
.digest = std::move(digest),
|
||||
.salt = std::move(salt)
|
||||
};
|
||||
}
|
||||
|
||||
Salt generateSalt() {
|
||||
return Random::PseudoRandom().getFixedSize<8>();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
28
src/cpp-utils/crypto/hash/Hash.h
Normal file
28
src/cpp-utils/crypto/hash/Hash.h
Normal file
@ -0,0 +1,28 @@
|
||||
#pragma once
|
||||
#ifndef MESSMER_CPPUTILS_CRYPTO_HASH_HASH_H
|
||||
#define MESSMER_CPPUTILS_CRYPTO_HASH_HASH_H
|
||||
|
||||
#include <cpp-utils/data/FixedSizeData.h>
|
||||
#include <cpp-utils/data/Data.h>
|
||||
|
||||
namespace cpputils {
|
||||
namespace hash {
|
||||
|
||||
using Digest = FixedSizeData<64>;
|
||||
using Salt = FixedSizeData<8>;
|
||||
|
||||
struct Hash final {
|
||||
Digest digest;
|
||||
Salt salt;
|
||||
};
|
||||
|
||||
|
||||
Salt generateSalt();
|
||||
Hash hash(const cpputils::Data& data, Salt salt);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif
|
@ -27,7 +27,7 @@ private:
|
||||
constexpr static size_t BINARY_LENGTH = FixedSizeData<KeySize>::BINARY_LENGTH;
|
||||
constexpr static size_t STRING_LENGTH = FixedSizeData<KeySize>::STRING_LENGTH;
|
||||
|
||||
EncryptionKeyData(const FixedSizeData<KeySize >& keyData);
|
||||
EncryptionKeyData(const FixedSizeData<KeySize>& keyData);
|
||||
~EncryptionKeyData();
|
||||
|
||||
// Disallow copying and moving
|
||||
|
@ -1,5 +1,7 @@
|
||||
#include "Data.h"
|
||||
#include <stdexcept>
|
||||
#include <cryptopp/hex.h>
|
||||
#include <cpp-utils/crypto/cryptopp_byte.h>
|
||||
|
||||
using std::istream;
|
||||
using std::ofstream;
|
||||
@ -42,4 +44,26 @@ Data Data::LoadFromStream(istream &stream, size_t size) {
|
||||
return result;
|
||||
}
|
||||
|
||||
Data Data::FromString(const std::string &data) {
|
||||
ASSERT(data.size() % 2 == 0, "hex encoded data cannot have odd number of characters");
|
||||
Data result(data.size() / 2);
|
||||
CryptoPP::StringSource(data, true,
|
||||
new CryptoPP::HexDecoder(
|
||||
new CryptoPP::ArraySink((CryptoPP::byte*)result._data, result.size())
|
||||
)
|
||||
);
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string Data::ToString() const {
|
||||
std::string result;
|
||||
CryptoPP::ArraySource((CryptoPP::byte*)_data, _size, true,
|
||||
new CryptoPP::HexEncoder(
|
||||
new CryptoPP::StringSink(result)
|
||||
)
|
||||
);
|
||||
ASSERT(result.size() == 2 * _size, "Created wrongly sized string");
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -45,6 +45,10 @@ public:
|
||||
static Data LoadFromStream(std::istream &stream, size_t size);
|
||||
void StoreToStream(std::ostream &stream) const;
|
||||
|
||||
// TODO Unify ToString/FromString functions from Data/FixedSizeData using free functions
|
||||
static Data FromString(const std::string &data);
|
||||
std::string ToString() const;
|
||||
|
||||
private:
|
||||
size_t _size;
|
||||
void *_data;
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
namespace cpputils {
|
||||
namespace DataUtils {
|
||||
Data resize(Data data, size_t newSize) {
|
||||
Data resize(const Data& data, size_t newSize) {
|
||||
Data newData(newSize);
|
||||
newData.FillWithZeroes(); // TODO Only fill region after copied old data with zeroes
|
||||
std::memcpy(newData.data(), data.data(), std::min(newData.size(), data.size()));
|
||||
|
@ -10,7 +10,7 @@ namespace cpputils {
|
||||
|
||||
//Return a new data object with the given size and initialize as much as possible with the given input data.
|
||||
//If the new data object is larger, then the remaining bytes will be zero filled.
|
||||
Data resize(Data data, size_t newSize);
|
||||
Data resize(const Data& data, size_t newSize);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -15,7 +15,7 @@ namespace cpputils {
|
||||
|
||||
void get(void *target, size_t bytes);
|
||||
|
||||
void add(Data data);
|
||||
void add(const Data& data);
|
||||
|
||||
private:
|
||||
size_t _usedUntil;
|
||||
@ -37,7 +37,7 @@ namespace cpputils {
|
||||
_usedUntil += numBytes;
|
||||
}
|
||||
|
||||
inline void RandomDataBuffer::add(Data newData) {
|
||||
inline void RandomDataBuffer::add(const Data& newData) {
|
||||
// Concatenate old and new random data
|
||||
size_t oldSize = size();
|
||||
Data combined(oldSize + newData.size());
|
||||
|
@ -21,7 +21,7 @@ namespace cpputils {
|
||||
size_t neededRandomDataSize = _maxSize - _buffer->size();
|
||||
ASSERT(_maxSize > _buffer->size(), "This could theoretically fail if another thread refilled the buffer. But we should be the only refilling thread.");
|
||||
Data randomData = _generateRandomData(neededRandomDataSize);
|
||||
_buffer->add(std::move(randomData));
|
||||
_buffer->add(randomData);
|
||||
return true; // Run another iteration (don't terminate thread)
|
||||
}
|
||||
|
||||
|
@ -17,7 +17,7 @@ namespace cpputils {
|
||||
|
||||
void get(void *target, size_t numBytes);
|
||||
|
||||
void add(Data data);
|
||||
void add(const Data& data);
|
||||
|
||||
void waitUntilSizeIsLessThan(size_t numBytes);
|
||||
|
||||
@ -63,9 +63,9 @@ namespace cpputils {
|
||||
return gettableBytes;
|
||||
}
|
||||
|
||||
inline void ThreadsafeRandomDataBuffer::add(Data data) {
|
||||
inline void ThreadsafeRandomDataBuffer::add(const Data& data) {
|
||||
boost::unique_lock<boost::mutex> lock(_mutex);
|
||||
_buffer.add(std::move(data));
|
||||
_buffer.add(data);
|
||||
_dataAddedCv.notify_all();
|
||||
}
|
||||
|
||||
|
@ -6,7 +6,7 @@ using boost::none;
|
||||
|
||||
namespace cpputils {
|
||||
|
||||
LoopThread::LoopThread(function<bool()> loopIteration): _loopIteration(loopIteration), _runningHandle(none) {
|
||||
LoopThread::LoopThread(function<bool()> loopIteration): _loopIteration(std::move(loopIteration)), _runningHandle(none) {
|
||||
}
|
||||
|
||||
LoopThread::~LoopThread() {
|
||||
|
@ -20,7 +20,7 @@ namespace cpputils {
|
||||
ThreadSystem::Handle ThreadSystem::start(function<bool()> loopIteration) {
|
||||
boost::unique_lock<boost::mutex> lock(_mutex);
|
||||
auto thread = _startThread(loopIteration);
|
||||
_runningThreads.push_back(RunningThread{loopIteration, std::move(thread)});
|
||||
_runningThreads.push_back(RunningThread{std::move(loopIteration), std::move(thread)});
|
||||
return std::prev(_runningThreads.end());
|
||||
}
|
||||
|
||||
@ -61,7 +61,9 @@ namespace cpputils {
|
||||
}
|
||||
|
||||
boost::thread ThreadSystem::_startThread(function<bool()> loopIteration) {
|
||||
return boost::thread(std::bind(&ThreadSystem::_runThread, loopIteration));
|
||||
return boost::thread([loopIteration = std::move(loopIteration)] {
|
||||
ThreadSystem::_runThread(std::move(loopIteration));
|
||||
});
|
||||
}
|
||||
|
||||
void ThreadSystem::_runThread(function<bool()> loopIteration) {
|
||||
|
@ -26,7 +26,7 @@ namespace cryfs {
|
||||
};
|
||||
|
||||
inline CallAfterTimeout::CallAfterTimeout(boost::chrono::milliseconds timeout, std::function<void()> callback)
|
||||
:_callback(callback), _timeout(timeout), _start(), _checkTimeoutThread(std::bind(&CallAfterTimeout::_checkTimeoutThreadIteration, this)) {
|
||||
:_callback(std::move(callback)), _timeout(timeout), _start(), _checkTimeoutThread(std::bind(&CallAfterTimeout::_checkTimeoutThreadIteration, this)) {
|
||||
resetTimer();
|
||||
_checkTimeoutThread.start();
|
||||
}
|
||||
|
@ -21,6 +21,8 @@
|
||||
#include "VersionChecker.h"
|
||||
#include <gitversion/VersionCompare.h>
|
||||
#include <cpp-utils/io/NoninteractiveConsole.h>
|
||||
#include <cryfs/localstate/LocalStateDir.h>
|
||||
#include <cryfs/localstate/BasedirMetadata.h>
|
||||
#include "Environment.h"
|
||||
|
||||
//TODO Many functions accessing the ProgramOptions object. Factor out into class that stores it as a member.
|
||||
@ -70,8 +72,8 @@ using gitversion::VersionCompare;
|
||||
|
||||
namespace cryfs {
|
||||
|
||||
Cli::Cli(RandomGenerator &keyGenerator, const SCryptSettings &scryptSettings, shared_ptr<Console> console, shared_ptr<HttpClient> httpClient):
|
||||
_keyGenerator(keyGenerator), _scryptSettings(scryptSettings), _console(), _httpClient(httpClient), _noninteractive(false) {
|
||||
Cli::Cli(RandomGenerator &keyGenerator, const SCryptSettings &scryptSettings, shared_ptr<Console> console):
|
||||
_keyGenerator(keyGenerator), _scryptSettings(scryptSettings), _console(), _noninteractive(false) {
|
||||
_noninteractive = Environment::isNoninteractive();
|
||||
if (_noninteractive) {
|
||||
_console = make_shared<NoninteractiveConsole>(console);
|
||||
@ -80,7 +82,7 @@ namespace cryfs {
|
||||
}
|
||||
}
|
||||
|
||||
void Cli::_showVersion() {
|
||||
void Cli::_showVersion(unique_ref<HttpClient> httpClient) {
|
||||
cout << "CryFS Version " << gitversion::VersionString() << endl;
|
||||
if (gitversion::IsDevVersion()) {
|
||||
cout << "WARNING! This is a development version based on git commit " << gitversion::GitCommitId() <<
|
||||
@ -97,7 +99,7 @@ namespace cryfs {
|
||||
} else if (Environment::isNoninteractive()) {
|
||||
cout << "Automatic checking for security vulnerabilities and updates is disabled in noninteractive mode." << endl;
|
||||
} else {
|
||||
_checkForUpdates();
|
||||
_checkForUpdates(std::move(httpClient));
|
||||
}
|
||||
#else
|
||||
# warning Update checks are disabled. The resulting executable will not go online to check for newer versions or known security vulnerabilities.
|
||||
@ -105,8 +107,8 @@ namespace cryfs {
|
||||
cout << endl;
|
||||
}
|
||||
|
||||
void Cli::_checkForUpdates() {
|
||||
VersionChecker versionChecker(_httpClient);
|
||||
void Cli::_checkForUpdates(unique_ref<HttpClient> httpClient) {
|
||||
VersionChecker versionChecker(httpClient.get());
|
||||
optional<string> newestVersion = versionChecker.newestVersion();
|
||||
if (newestVersion == none) {
|
||||
cout << "Could not check for updates." << endl;
|
||||
@ -195,14 +197,28 @@ namespace cryfs {
|
||||
return *configFile;
|
||||
}
|
||||
|
||||
void Cli::_checkConfigIntegrity(const bf::path& basedir, const CryConfigFile& config) {
|
||||
auto basedirMetadata = BasedirMetadata::load();
|
||||
if (!basedirMetadata.filesystemIdForBasedirIsCorrect(basedir, config.config()->FilesystemId())) {
|
||||
if (!_console->askYesNo("The filesystem id in the config file is different to the last time we loaded a filesystem from this basedir. This can be genuine if you replaced the filesystem with a different one. If you didn't do that, it is possible that an attacker did. Do you want to continue loading the file system?", false)) {
|
||||
throw std::runtime_error(
|
||||
"The filesystem id in the config file is different to the last time we loaded a filesystem from this basedir.");
|
||||
}
|
||||
}
|
||||
// Update local state (or create it if it didn't exist yet)
|
||||
basedirMetadata.updateFilesystemIdForBasedir(basedir, config.config()->FilesystemId());
|
||||
basedirMetadata.save();
|
||||
}
|
||||
|
||||
CryConfigLoader::ConfigLoadResult Cli::_loadOrCreateConfig(const ProgramOptions &options) {
|
||||
try {
|
||||
auto configFile = _determineConfigFile(options);
|
||||
auto config = _loadOrCreateConfigFile(configFile, options.cipher(), options.blocksizeBytes(), options.missingBlockIsIntegrityViolation());
|
||||
auto config = _loadOrCreateConfigFile(std::move(configFile), options.cipher(), options.blocksizeBytes(), options.missingBlockIsIntegrityViolation());
|
||||
if (config == none) {
|
||||
std::cerr << "Could not load config file. Did you enter the correct password?" << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
_checkConfigIntegrity(options.baseDir(), config->configFile);
|
||||
return std::move(*config);
|
||||
} catch (const std::exception &e) {
|
||||
std::cerr << "Error: " << e.what() << std::endl;
|
||||
@ -210,17 +226,17 @@ namespace cryfs {
|
||||
}
|
||||
}
|
||||
|
||||
optional<CryConfigLoader::ConfigLoadResult> Cli::_loadOrCreateConfigFile(const bf::path &configFilePath, const optional<string> &cipher, const optional<uint32_t> &blocksizeBytes, const optional<bool> &missingBlockIsIntegrityViolation) {
|
||||
optional<CryConfigLoader::ConfigLoadResult> Cli::_loadOrCreateConfigFile(bf::path configFilePath, const optional<string> &cipher, const optional<uint32_t> &blocksizeBytes, const optional<bool> &missingBlockIsIntegrityViolation) {
|
||||
if (_noninteractive) {
|
||||
return CryConfigLoader(_console, _keyGenerator, _scryptSettings,
|
||||
&Cli::_askPasswordNoninteractive,
|
||||
&Cli::_askPasswordNoninteractive,
|
||||
cipher, blocksizeBytes, missingBlockIsIntegrityViolation).loadOrCreate(configFilePath);
|
||||
cipher, blocksizeBytes, missingBlockIsIntegrityViolation).loadOrCreate(std::move(configFilePath));
|
||||
} else {
|
||||
return CryConfigLoader(_console, _keyGenerator, _scryptSettings,
|
||||
&Cli::_askPasswordForExistingFilesystem,
|
||||
&Cli::_askPasswordForNewFilesystem,
|
||||
cipher, blocksizeBytes, missingBlockIsIntegrityViolation).loadOrCreate(configFilePath);
|
||||
cipher, blocksizeBytes, missingBlockIsIntegrityViolation).loadOrCreate(std::move(configFilePath));
|
||||
}
|
||||
}
|
||||
|
||||
@ -362,9 +378,9 @@ namespace cryfs {
|
||||
return false;
|
||||
}
|
||||
|
||||
int Cli::main(int argc, const char *argv[]) {
|
||||
int Cli::main(int argc, const char *argv[], unique_ref<HttpClient> httpClient) {
|
||||
cpputils::showBacktraceOnSigSegv();
|
||||
_showVersion();
|
||||
_showVersion(std::move(httpClient));
|
||||
|
||||
ProgramOptions options = program_options::Parser(argc, argv).parse(CryCiphers::supportedCipherNames());
|
||||
|
||||
|
@ -16,14 +16,15 @@
|
||||
namespace cryfs {
|
||||
class Cli final {
|
||||
public:
|
||||
Cli(cpputils::RandomGenerator &keyGenerator, const cpputils::SCryptSettings &scryptSettings, std::shared_ptr<cpputils::Console> console, std::shared_ptr<cpputils::HttpClient> httpClient);
|
||||
int main(int argc, const char *argv[]);
|
||||
Cli(cpputils::RandomGenerator &keyGenerator, const cpputils::SCryptSettings &scryptSettings, std::shared_ptr<cpputils::Console> console);
|
||||
int main(int argc, const char *argv[], cpputils::unique_ref<cpputils::HttpClient> httpClient);
|
||||
|
||||
private:
|
||||
void _checkForUpdates();
|
||||
void _checkForUpdates(cpputils::unique_ref<cpputils::HttpClient> httpClient);
|
||||
void _runFilesystem(const program_options::ProgramOptions &options);
|
||||
CryConfigLoader::ConfigLoadResult _loadOrCreateConfig(const program_options::ProgramOptions &options);
|
||||
boost::optional<CryConfigLoader::ConfigLoadResult> _loadOrCreateConfigFile(const boost::filesystem::path &configFilePath, const boost::optional<std::string> &cipher, const boost::optional<uint32_t> &blocksizeBytes, const boost::optional<bool> &missingBlockIsIntegrityViolation);
|
||||
void _checkConfigIntegrity(const boost::filesystem::path& basedir, const CryConfigFile& config);
|
||||
boost::optional<CryConfigLoader::ConfigLoadResult> _loadOrCreateConfigFile(boost::filesystem::path configFilePath, const boost::optional<std::string> &cipher, const boost::optional<uint32_t> &blocksizeBytes, const boost::optional<bool> &missingBlockIsIntegrityViolation);
|
||||
boost::filesystem::path _determineConfigFile(const program_options::ProgramOptions &options);
|
||||
static std::string _askPasswordForExistingFilesystem();
|
||||
static std::string _askPasswordForNewFilesystem();
|
||||
@ -31,7 +32,7 @@ namespace cryfs {
|
||||
static std::string _askPasswordFromStdin(const std::string &prompt);
|
||||
static bool _confirmPassword(const std::string &password);
|
||||
static bool _checkPassword(const std::string &password);
|
||||
void _showVersion();
|
||||
void _showVersion(cpputils::unique_ref<cpputils::HttpClient> httpClient);
|
||||
void _initLogfile(const program_options::ProgramOptions &options);
|
||||
void _sanityChecks(const program_options::ProgramOptions &options);
|
||||
void _checkMountdirDoesntContainBasedir(const program_options::ProgramOptions &options);
|
||||
@ -46,7 +47,6 @@ namespace cryfs {
|
||||
cpputils::RandomGenerator &_keyGenerator;
|
||||
cpputils::SCryptSettings _scryptSettings;
|
||||
std::shared_ptr<cpputils::Console> _console;
|
||||
std::shared_ptr<cpputils::HttpClient> _httpClient;
|
||||
bool _noninteractive;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(Cli);
|
||||
|
@ -8,18 +8,17 @@
|
||||
using boost::optional;
|
||||
using boost::none;
|
||||
using std::string;
|
||||
using std::shared_ptr;
|
||||
using std::make_shared;
|
||||
using cpputils::HttpClient;
|
||||
using cpputils::CurlHttpClient;
|
||||
using boost::property_tree::ptree;
|
||||
using boost::property_tree::json_parser_error;
|
||||
using cpputils::unique_ref;
|
||||
using namespace cpputils::logging;
|
||||
|
||||
namespace cryfs {
|
||||
|
||||
VersionChecker::VersionChecker(shared_ptr<HttpClient> httpClient)
|
||||
: _versionInfo(_getVersionInfo(std::move(httpClient))) {
|
||||
VersionChecker::VersionChecker(HttpClient* httpClient)
|
||||
: _versionInfo(_getVersionInfo(httpClient)) {
|
||||
}
|
||||
|
||||
optional<string> VersionChecker::newestVersion() const {
|
||||
@ -49,7 +48,7 @@ namespace cryfs {
|
||||
return none;
|
||||
}
|
||||
|
||||
optional<ptree> VersionChecker::_getVersionInfo(shared_ptr<HttpClient> httpClient) {
|
||||
optional<ptree> VersionChecker::_getVersionInfo(HttpClient* httpClient) {
|
||||
long timeoutMsec = 2000;
|
||||
optional<string> response = httpClient->get("https://www.cryfs.org/version_info.json", timeoutMsec);
|
||||
if (response == none) {
|
||||
|
@ -6,17 +6,18 @@
|
||||
#include <boost/optional.hpp>
|
||||
#include <boost/property_tree/ptree.hpp>
|
||||
#include <cpp-utils/network/HttpClient.h>
|
||||
#include <cpp-utils/pointer/unique_ref.h>
|
||||
|
||||
namespace cryfs {
|
||||
class VersionChecker final {
|
||||
public:
|
||||
//TODO Write a cpputils::shared_ref and use it
|
||||
VersionChecker(std::shared_ptr<cpputils::HttpClient> httpClient);
|
||||
VersionChecker(cpputils::HttpClient* httpClient);
|
||||
|
||||
boost::optional<std::string> newestVersion() const;
|
||||
boost::optional<std::string> securityWarningFor(const std::string &version) const;
|
||||
private:
|
||||
static boost::optional<boost::property_tree::ptree> _getVersionInfo(std::shared_ptr<cpputils::HttpClient> httpClient);
|
||||
static boost::optional<boost::property_tree::ptree> _getVersionInfo(cpputils::HttpClient* httpClient);
|
||||
static boost::optional<boost::property_tree::ptree> _parseJson(const std::string &json);
|
||||
|
||||
boost::optional<boost::property_tree::ptree> _versionInfo;
|
||||
|
@ -9,14 +9,15 @@ using cpputils::Random;
|
||||
using cpputils::SCrypt;
|
||||
using cpputils::CurlHttpClient;
|
||||
using cpputils::IOStreamConsole;
|
||||
using cpputils::make_unique_ref;
|
||||
using std::make_shared;
|
||||
using std::cerr;
|
||||
|
||||
int main(int argc, const char *argv[]) {
|
||||
try {
|
||||
auto &keyGenerator = Random::OSRandom();
|
||||
return Cli(keyGenerator, SCrypt::DefaultSettings, make_shared<IOStreamConsole>(),
|
||||
make_shared<CurlHttpClient>()).main(argc, argv);
|
||||
return Cli(keyGenerator, SCrypt::DefaultSettings, make_shared<IOStreamConsole>())
|
||||
.main(argc, argv, make_unique_ref<CurlHttpClient>());
|
||||
} catch (const std::exception &e) {
|
||||
cerr << "Error: " << e.what();
|
||||
return EXIT_FAILURE;
|
||||
|
@ -92,7 +92,7 @@ ProgramOptions Parser::parse(const vector<string> &supportedCiphers) const {
|
||||
}
|
||||
}
|
||||
|
||||
return ProgramOptions(baseDir, mountDir, configfile, foreground, unmountAfterIdleMinutes, logfile, cipher, blocksizeBytes, noIntegrityChecks, missingBlockIsIntegrityViolation, fuseOptions);
|
||||
return ProgramOptions(std::move(baseDir), std::move(mountDir), std::move(configfile), foreground, std::move(unmountAfterIdleMinutes), std::move(logfile), std::move(cipher), blocksizeBytes, noIntegrityChecks, std::move(missingBlockIsIntegrityViolation), std::move(fuseOptions));
|
||||
}
|
||||
|
||||
void Parser::_checkValidCipher(const string &cipher, const vector<string> &supportedCiphers) {
|
||||
|
@ -8,16 +8,16 @@ using std::vector;
|
||||
using boost::optional;
|
||||
namespace bf = boost::filesystem;
|
||||
|
||||
ProgramOptions::ProgramOptions(const bf::path &baseDir, const bf::path &mountDir, const optional<bf::path> &configFile,
|
||||
bool foreground, const optional<double> &unmountAfterIdleMinutes,
|
||||
const optional<bf::path> &logFile, const optional<string> &cipher,
|
||||
const optional<uint32_t> &blocksizeBytes,
|
||||
ProgramOptions::ProgramOptions(bf::path baseDir, bf::path mountDir, optional<bf::path> configFile,
|
||||
bool foreground, optional<double> unmountAfterIdleMinutes,
|
||||
optional<bf::path> logFile, optional<string> cipher,
|
||||
optional<uint32_t> blocksizeBytes,
|
||||
bool noIntegrityChecks,
|
||||
const boost::optional<bool> &missingBlockIsIntegrityViolation,
|
||||
const vector<string> &fuseOptions)
|
||||
:_baseDir(baseDir), _mountDir(mountDir), _configFile(configFile), _foreground(foreground), _noIntegrityChecks(noIntegrityChecks),
|
||||
_cipher(cipher), _blocksizeBytes(blocksizeBytes), _unmountAfterIdleMinutes(unmountAfterIdleMinutes),
|
||||
_missingBlockIsIntegrityViolation(missingBlockIsIntegrityViolation), _logFile(logFile), _fuseOptions(fuseOptions) {
|
||||
boost::optional<bool> missingBlockIsIntegrityViolation,
|
||||
vector<string> fuseOptions)
|
||||
:_baseDir(std::move(baseDir)), _mountDir(std::move(mountDir)), _configFile(std::move(configFile)), _foreground(foreground), _noIntegrityChecks(noIntegrityChecks),
|
||||
_cipher(std::move(cipher)), _blocksizeBytes(std::move(blocksizeBytes)), _unmountAfterIdleMinutes(std::move(unmountAfterIdleMinutes)),
|
||||
_missingBlockIsIntegrityViolation(std::move(missingBlockIsIntegrityViolation)), _logFile(std::move(logFile)), _fuseOptions(std::move(fuseOptions)) {
|
||||
}
|
||||
|
||||
const bf::path &ProgramOptions::baseDir() const {
|
||||
|
@ -12,15 +12,15 @@ namespace cryfs {
|
||||
namespace program_options {
|
||||
class ProgramOptions final {
|
||||
public:
|
||||
ProgramOptions(const boost::filesystem::path &baseDir, const boost::filesystem::path &mountDir,
|
||||
const boost::optional<boost::filesystem::path> &configFile,
|
||||
bool foreground, const boost::optional<double> &unmountAfterIdleMinutes,
|
||||
const boost::optional<boost::filesystem::path> &logFile,
|
||||
const boost::optional<std::string> &cipher,
|
||||
const boost::optional<uint32_t> &blocksizeBytes,
|
||||
ProgramOptions(boost::filesystem::path baseDir, boost::filesystem::path mountDir,
|
||||
boost::optional<boost::filesystem::path> configFile,
|
||||
bool foreground, boost::optional<double> unmountAfterIdleMinutes,
|
||||
boost::optional<boost::filesystem::path> logFile,
|
||||
boost::optional<std::string> cipher,
|
||||
boost::optional<uint32_t> blocksizeBytes,
|
||||
bool noIntegrityChecks,
|
||||
const boost::optional<bool> &missingBlockIsIntegrityViolation,
|
||||
const std::vector<std::string> &fuseOptions);
|
||||
boost::optional<bool> missingBlockIsIntegrityViolation,
|
||||
std::vector<std::string> fuseOptions);
|
||||
ProgramOptions(ProgramOptions &&rhs) = default;
|
||||
|
||||
const boost::filesystem::path &baseDir() const;
|
||||
|
@ -40,8 +40,9 @@ set(LIB_SOURCES
|
||||
filesystem/cachingfsblobstore/SymlinkBlobRef.cpp
|
||||
filesystem/CryFile.cpp
|
||||
filesystem/CryDevice.cpp
|
||||
localstate/MyClientId.cpp
|
||||
localstate/LocalStateDir.cpp
|
||||
localstate/LocalStateMetadata.cpp
|
||||
localstate/BasedirMetadata.cpp
|
||||
)
|
||||
|
||||
add_library(${PROJECT_NAME} STATIC ${LIB_SOURCES})
|
||||
|
@ -89,40 +89,40 @@ const std::string &CryConfig::RootBlob() const {
|
||||
return _rootBlob;
|
||||
}
|
||||
|
||||
void CryConfig::SetRootBlob(const std::string &value) {
|
||||
_rootBlob = value;
|
||||
void CryConfig::SetRootBlob(std::string value) {
|
||||
_rootBlob = std::move(value);
|
||||
}
|
||||
|
||||
const string &CryConfig::EncryptionKey() const {
|
||||
return _encKey;
|
||||
}
|
||||
|
||||
void CryConfig::SetEncryptionKey(const std::string &value) {
|
||||
_encKey = value;
|
||||
void CryConfig::SetEncryptionKey(std::string value) {
|
||||
_encKey = std::move(value);
|
||||
}
|
||||
|
||||
const std::string &CryConfig::Cipher() const {
|
||||
return _cipher;
|
||||
};
|
||||
|
||||
void CryConfig::SetCipher(const std::string &value) {
|
||||
_cipher = value;
|
||||
void CryConfig::SetCipher(std::string value) {
|
||||
_cipher = std::move(value);
|
||||
}
|
||||
|
||||
const std::string &CryConfig::Version() const {
|
||||
return _version;
|
||||
}
|
||||
|
||||
void CryConfig::SetVersion(const std::string &value) {
|
||||
_version = value;
|
||||
void CryConfig::SetVersion(std::string value) {
|
||||
_version = std::move(value);
|
||||
}
|
||||
|
||||
const std::string &CryConfig::CreatedWithVersion() const {
|
||||
return _createdWithVersion;
|
||||
}
|
||||
|
||||
void CryConfig::SetCreatedWithVersion(const std::string &value) {
|
||||
_createdWithVersion = value;
|
||||
void CryConfig::SetCreatedWithVersion(std::string value) {
|
||||
_createdWithVersion = std::move(value);
|
||||
}
|
||||
|
||||
uint64_t CryConfig::BlocksizeBytes() const {
|
||||
@ -137,8 +137,8 @@ const CryConfig::FilesystemID &CryConfig::FilesystemId() const {
|
||||
return _filesystemId;
|
||||
}
|
||||
|
||||
void CryConfig::SetFilesystemId(const FilesystemID &value) {
|
||||
_filesystemId = value;
|
||||
void CryConfig::SetFilesystemId(FilesystemID value) {
|
||||
_filesystemId = std::move(value);
|
||||
}
|
||||
|
||||
optional<uint32_t> CryConfig::ExclusiveClientId() const {
|
||||
|
@ -18,26 +18,26 @@ public:
|
||||
CryConfig(const CryConfig &rhs) = default;
|
||||
|
||||
const std::string &RootBlob() const;
|
||||
void SetRootBlob(const std::string &value);
|
||||
void SetRootBlob(std::string value);
|
||||
|
||||
const std::string &EncryptionKey() const;
|
||||
void SetEncryptionKey(const std::string &value);
|
||||
void SetEncryptionKey(std::string value);
|
||||
|
||||
const std::string &Cipher() const;
|
||||
void SetCipher(const std::string &value);
|
||||
void SetCipher(std::string value);
|
||||
|
||||
const std::string &Version() const;
|
||||
void SetVersion(const std::string &value);
|
||||
void SetVersion(std::string value);
|
||||
|
||||
const std::string &CreatedWithVersion() const;
|
||||
void SetCreatedWithVersion(const std::string &value);
|
||||
void SetCreatedWithVersion(std::string value);
|
||||
|
||||
uint64_t BlocksizeBytes() const;
|
||||
void SetBlocksizeBytes(uint64_t value);
|
||||
|
||||
using FilesystemID = cpputils::FixedSizeData<16>;
|
||||
const FilesystemID &FilesystemId() const;
|
||||
void SetFilesystemId(const FilesystemID &value);
|
||||
void SetFilesystemId(FilesystemID value);
|
||||
|
||||
// If the exclusive client Id is set, then additional integrity measures (i.e. treating missing blocks as integrity violations) are enabled.
|
||||
// Because this only works in a single-client setting, only this one client Id is allowed to access the file system.
|
||||
|
@ -3,7 +3,7 @@
|
||||
#include <gitversion/gitversion.h>
|
||||
#include <cpp-utils/random/Random.h>
|
||||
#include <cryfs/localstate/LocalStateDir.h>
|
||||
#include <cryfs/localstate/MyClientId.h>
|
||||
#include <cryfs/localstate/LocalStateMetadata.h>
|
||||
|
||||
using cpputils::Console;
|
||||
using cpputils::unique_ref;
|
||||
@ -28,9 +28,11 @@ namespace cryfs {
|
||||
config.SetCreatedWithVersion(gitversion::VersionString());
|
||||
config.SetBlocksizeBytes(_generateBlocksizeBytes(blocksizeBytesFromCommandLine));
|
||||
config.SetRootBlob(_generateRootBlobId());
|
||||
config.SetEncryptionKey(_generateEncKey(config.Cipher()));
|
||||
config.SetFilesystemId(_generateFilesystemID());
|
||||
uint32_t myClientId = MyClientId(LocalStateDir::forFilesystemId(config.FilesystemId())).loadOrGenerate();
|
||||
auto encryptionKey = _generateEncKey(config.Cipher());
|
||||
auto localState = LocalStateMetadata::loadOrGenerate(LocalStateDir::forFilesystemId(config.FilesystemId()), cpputils::Data::FromString(encryptionKey));
|
||||
uint32_t myClientId = localState.myClientId();
|
||||
config.SetEncryptionKey(std::move(encryptionKey));
|
||||
config.SetExclusiveClientId(_generateExclusiveClientId(missingBlockIsIntegrityViolationFromCommandLine, myClientId));
|
||||
#ifndef CRYFS_NO_COMPATIBILITY
|
||||
config.SetHasVersionNumbers(true);
|
||||
|
@ -25,7 +25,7 @@ CryConfigFile::~CryConfigFile() {
|
||||
//We do not call save() here, because we do not want the config file to be re-encrypted on each filesystem run
|
||||
}
|
||||
|
||||
optional<CryConfigFile> CryConfigFile::load(const bf::path &path, const string &password) {
|
||||
optional<CryConfigFile> CryConfigFile::load(bf::path path, const string &password) {
|
||||
auto encryptedConfigData = Data::LoadFromFile(path);
|
||||
if (encryptedConfigData == none) {
|
||||
LOG(ERROR, "Config file not found");
|
||||
@ -44,7 +44,7 @@ optional<CryConfigFile> CryConfigFile::load(const bf::path &path, const string &
|
||||
LOG(ERROR, "Inner cipher algorithm used to encrypt config file doesn't match config value");
|
||||
return none;
|
||||
}
|
||||
auto configFile = CryConfigFile(path, std::move(config), std::move(*encryptor));
|
||||
auto configFile = CryConfigFile(std::move(path), std::move(config), std::move(*encryptor));
|
||||
if (decrypted->wasInDeprecatedConfigFormat) {
|
||||
// Migrate it to new format
|
||||
configFile.save();
|
||||
@ -53,17 +53,17 @@ optional<CryConfigFile> CryConfigFile::load(const bf::path &path, const string &
|
||||
return std::move(configFile);
|
||||
}
|
||||
|
||||
CryConfigFile CryConfigFile::create(const bf::path &path, const CryConfig &config, const string &password, const SCryptSettings &scryptSettings) {
|
||||
CryConfigFile CryConfigFile::create(bf::path path, CryConfig config, const string &password, const SCryptSettings &scryptSettings) {
|
||||
if (bf::exists(path)) {
|
||||
throw std::runtime_error("Config file exists already.");
|
||||
}
|
||||
auto result = CryConfigFile(path, config, CryConfigEncryptorFactory::deriveKey(password, scryptSettings));
|
||||
auto result = CryConfigFile(std::move(path), std::move(config), CryConfigEncryptorFactory::deriveKey(password, scryptSettings));
|
||||
result.save();
|
||||
return result;
|
||||
}
|
||||
|
||||
CryConfigFile::CryConfigFile(const bf::path &path, const CryConfig &config, unique_ref<CryConfigEncryptor> encryptor)
|
||||
: _path (path), _config(config), _encryptor(std::move(encryptor)) {
|
||||
CryConfigFile::CryConfigFile(bf::path path, CryConfig config, unique_ref<CryConfigEncryptor> encryptor)
|
||||
: _path(std::move(path)), _config(std::move(config)), _encryptor(std::move(encryptor)) {
|
||||
}
|
||||
|
||||
void CryConfigFile::save() const {
|
||||
|
@ -14,15 +14,15 @@ namespace cryfs {
|
||||
CryConfigFile(CryConfigFile &&rhs) = default;
|
||||
~CryConfigFile();
|
||||
|
||||
static CryConfigFile create(const boost::filesystem::path &path, const CryConfig &config, const std::string &password, const cpputils::SCryptSettings &scryptSettings);
|
||||
static boost::optional<CryConfigFile> load(const boost::filesystem::path &path, const std::string &password);
|
||||
static CryConfigFile create(boost::filesystem::path path, CryConfig config, const std::string &password, const cpputils::SCryptSettings &scryptSettings);
|
||||
static boost::optional<CryConfigFile> load(boost::filesystem::path path, const std::string &password);
|
||||
void save() const;
|
||||
|
||||
CryConfig *config();
|
||||
const CryConfig *config() const;
|
||||
|
||||
private:
|
||||
CryConfigFile(const boost::filesystem::path &path, const CryConfig &config, cpputils::unique_ref<CryConfigEncryptor> encryptor);
|
||||
CryConfigFile(boost::filesystem::path path, CryConfig config, cpputils::unique_ref<CryConfigEncryptor> encryptor);
|
||||
|
||||
boost::filesystem::path _path;
|
||||
CryConfig _config;
|
||||
|
@ -7,7 +7,7 @@
|
||||
#include <gitversion/gitversion.h>
|
||||
#include <gitversion/VersionCompare.h>
|
||||
#include "../localstate/LocalStateDir.h"
|
||||
#include "../localstate/MyClientId.h"
|
||||
#include "../localstate/LocalStateMetadata.h"
|
||||
|
||||
namespace bf = boost::filesystem;
|
||||
using cpputils::unique_ref;
|
||||
@ -31,16 +31,16 @@ using namespace cpputils::logging;
|
||||
namespace cryfs {
|
||||
|
||||
CryConfigLoader::CryConfigLoader(shared_ptr<Console> console, RandomGenerator &keyGenerator, const SCryptSettings &scryptSettings, function<string()> askPasswordForExistingFilesystem, function<string()> askPasswordForNewFilesystem, const optional<string> &cipherFromCommandLine, const boost::optional<uint32_t> &blocksizeBytesFromCommandLine, const boost::optional<bool> &missingBlockIsIntegrityViolationFromCommandLine)
|
||||
: _console(console), _creator(console, keyGenerator), _scryptSettings(scryptSettings),
|
||||
: _console(console), _creator(std::move(console), keyGenerator), _scryptSettings(scryptSettings),
|
||||
_askPasswordForExistingFilesystem(askPasswordForExistingFilesystem), _askPasswordForNewFilesystem(askPasswordForNewFilesystem),
|
||||
_cipherFromCommandLine(cipherFromCommandLine), _blocksizeBytesFromCommandLine(blocksizeBytesFromCommandLine),
|
||||
_missingBlockIsIntegrityViolationFromCommandLine(missingBlockIsIntegrityViolationFromCommandLine) {
|
||||
}
|
||||
|
||||
optional<CryConfigLoader::ConfigLoadResult> CryConfigLoader::_loadConfig(const bf::path &filename) {
|
||||
optional<CryConfigLoader::ConfigLoadResult> CryConfigLoader::_loadConfig(bf::path filename) {
|
||||
string password = _askPasswordForExistingFilesystem();
|
||||
std::cout << "Loading config file (this can take some time)..." << std::flush;
|
||||
auto config = CryConfigFile::load(filename, password);
|
||||
auto config = CryConfigFile::load(std::move(filename), password);
|
||||
if (config == none) {
|
||||
return none;
|
||||
}
|
||||
@ -57,7 +57,8 @@ optional<CryConfigLoader::ConfigLoadResult> CryConfigLoader::_loadConfig(const b
|
||||
config->save();
|
||||
}
|
||||
_checkCipher(*config->config());
|
||||
uint32_t myClientId = MyClientId(LocalStateDir::forFilesystemId(config->config()->FilesystemId())).loadOrGenerate();
|
||||
auto localState = LocalStateMetadata::loadOrGenerate(LocalStateDir::forFilesystemId(config->config()->FilesystemId()), cpputils::Data::FromString(config->config()->EncryptionKey()));
|
||||
uint32_t myClientId = localState.myClientId();
|
||||
_checkMissingBlocksAreIntegrityViolations(&*config, myClientId);
|
||||
return ConfigLoadResult {std::move(*config), myClientId};
|
||||
}
|
||||
@ -100,20 +101,20 @@ void CryConfigLoader::_checkMissingBlocksAreIntegrityViolations(CryConfigFile *c
|
||||
}
|
||||
}
|
||||
|
||||
optional<CryConfigLoader::ConfigLoadResult> CryConfigLoader::loadOrCreate(const bf::path &filename) {
|
||||
optional<CryConfigLoader::ConfigLoadResult> CryConfigLoader::loadOrCreate(bf::path filename) {
|
||||
if (bf::exists(filename)) {
|
||||
return _loadConfig(filename);
|
||||
return _loadConfig(std::move(filename));
|
||||
} else {
|
||||
return _createConfig(filename);
|
||||
return _createConfig(std::move(filename));
|
||||
}
|
||||
}
|
||||
|
||||
CryConfigLoader::ConfigLoadResult CryConfigLoader::_createConfig(const bf::path &filename) {
|
||||
CryConfigLoader::ConfigLoadResult CryConfigLoader::_createConfig(bf::path filename) {
|
||||
auto config = _creator.create(_cipherFromCommandLine, _blocksizeBytesFromCommandLine, _missingBlockIsIntegrityViolationFromCommandLine);
|
||||
//TODO Ask confirmation if using insecure password (<8 characters)
|
||||
string password = _askPasswordForNewFilesystem();
|
||||
std::cout << "Creating config file (this can take some time)..." << std::flush;
|
||||
auto result = CryConfigFile::create(filename, std::move(config.config), password, _scryptSettings);
|
||||
auto result = CryConfigFile::create(std::move(filename), std::move(config.config), password, _scryptSettings);
|
||||
std::cout << "done" << std::endl;
|
||||
return ConfigLoadResult {std::move(result), config.myClientId};
|
||||
}
|
||||
|
@ -21,11 +21,11 @@ public:
|
||||
uint32_t myClientId;
|
||||
};
|
||||
|
||||
boost::optional<ConfigLoadResult> loadOrCreate(const boost::filesystem::path &filename);
|
||||
boost::optional<ConfigLoadResult> loadOrCreate(boost::filesystem::path filename);
|
||||
|
||||
private:
|
||||
boost::optional<ConfigLoadResult> _loadConfig(const boost::filesystem::path &filename);
|
||||
ConfigLoadResult _createConfig(const boost::filesystem::path &filename);
|
||||
boost::optional<ConfigLoadResult> _loadConfig(boost::filesystem::path filename);
|
||||
ConfigLoadResult _createConfig(boost::filesystem::path filename);
|
||||
void _checkVersion(const CryConfig &config);
|
||||
void _checkCipher(const CryConfig &config) const;
|
||||
void _checkMissingBlocksAreIntegrityViolations(CryConfigFile *configFile, uint32_t myClientId);
|
||||
|
@ -15,8 +15,8 @@ namespace cryfs {
|
||||
constexpr size_t CryConfigEncryptor::OuterKeySize;
|
||||
constexpr size_t CryConfigEncryptor::MaxTotalKeySize;
|
||||
|
||||
CryConfigEncryptor::CryConfigEncryptor(FixedSizeData<MaxTotalKeySize> derivedKey, cpputils::Data kdfParameters)
|
||||
: _derivedKey(std::move(derivedKey)), _kdfParameters(std::move(kdfParameters)) {
|
||||
CryConfigEncryptor::CryConfigEncryptor(const FixedSizeData<MaxTotalKeySize>& derivedKey, cpputils::Data kdfParameters)
|
||||
: _derivedKey(derivedKey), _kdfParameters(std::move(kdfParameters)) {
|
||||
}
|
||||
|
||||
Data CryConfigEncryptor::encrypt(const Data &plaintext, const string &cipherName) const {
|
||||
|
@ -23,7 +23,7 @@ namespace cryfs {
|
||||
bool wasInDeprecatedConfigFormat;
|
||||
};
|
||||
|
||||
CryConfigEncryptor(cpputils::FixedSizeData<MaxTotalKeySize> derivedKey, cpputils::Data _kdfParameters);
|
||||
CryConfigEncryptor(const cpputils::FixedSizeData<MaxTotalKeySize>& derivedKey, cpputils::Data _kdfParameters);
|
||||
|
||||
cpputils::Data encrypt(const cpputils::Data &plaintext, const std::string &cipherName) const;
|
||||
boost::optional<Decrypted> decrypt(const cpputils::Data &data) const;
|
||||
|
@ -13,7 +13,7 @@ namespace cryfs {
|
||||
public:
|
||||
static constexpr size_t CONFIG_SIZE = 900; // Inner config data is grown to this size before encryption to hide its actual size
|
||||
|
||||
ConcreteInnerEncryptor(typename Cipher::EncryptionKey key);
|
||||
ConcreteInnerEncryptor(const typename Cipher::EncryptionKey& key);
|
||||
|
||||
InnerConfig encrypt(const cpputils::Data &config) const override;
|
||||
boost::optional<cpputils::Data> decrypt(const InnerConfig &innerConfig) const override;
|
||||
@ -26,8 +26,8 @@ namespace cryfs {
|
||||
};
|
||||
|
||||
template<class Cipher>
|
||||
ConcreteInnerEncryptor<Cipher>::ConcreteInnerEncryptor(typename Cipher::EncryptionKey key)
|
||||
: _key(std::move(key)) {
|
||||
ConcreteInnerEncryptor<Cipher>::ConcreteInnerEncryptor(const typename Cipher::EncryptionKey& key)
|
||||
: _key(key) {
|
||||
}
|
||||
|
||||
template<class Cipher>
|
||||
|
@ -11,8 +11,8 @@ using boost::none;
|
||||
using namespace cpputils::logging;
|
||||
|
||||
namespace cryfs {
|
||||
OuterEncryptor::OuterEncryptor(Cipher::EncryptionKey key, cpputils::Data kdfParameters)
|
||||
: _key(std::move(key)), _kdfParameters(std::move(kdfParameters)) {
|
||||
OuterEncryptor::OuterEncryptor(const Cipher::EncryptionKey& key, cpputils::Data kdfParameters)
|
||||
: _key(key), _kdfParameters(std::move(kdfParameters)) {
|
||||
}
|
||||
|
||||
OuterConfig OuterEncryptor::encrypt(const Data &plaintext) const {
|
||||
|
@ -14,7 +14,7 @@ namespace cryfs {
|
||||
using Cipher = cpputils::AES256_GCM;
|
||||
static constexpr size_t CONFIG_SIZE = 1024; // Config data is grown to this size before encryption to hide its actual size
|
||||
|
||||
OuterEncryptor(Cipher::EncryptionKey key, cpputils::Data kdfParameters);
|
||||
OuterEncryptor(const Cipher::EncryptionKey& key, cpputils::Data kdfParameters);
|
||||
|
||||
OuterConfig encrypt(const cpputils::Data &encryptedInnerConfig) const;
|
||||
boost::optional<cpputils::Data> decrypt(const OuterConfig &outerConfig) const;
|
||||
|
@ -19,7 +19,6 @@
|
||||
#include <cpp-utils/system/homedir.h>
|
||||
#include <gitversion/VersionCompare.h>
|
||||
#include <blockstore/interface/BlockStore2.h>
|
||||
#include "cryfs/localstate/MyClientId.h"
|
||||
#include "cryfs/localstate/LocalStateDir.h"
|
||||
|
||||
using std::string;
|
||||
|
71
src/cryfs/localstate/BasedirMetadata.cpp
Normal file
71
src/cryfs/localstate/BasedirMetadata.cpp
Normal file
@ -0,0 +1,71 @@
|
||||
#include "BasedirMetadata.h"
|
||||
#include <boost/property_tree/ptree.hpp>
|
||||
#include <boost/property_tree/json_parser.hpp>
|
||||
#include <cryptopp/sha.h>
|
||||
#include <boost/filesystem/operations.hpp>
|
||||
#include "LocalStateDir.h"
|
||||
|
||||
namespace bf = boost::filesystem;
|
||||
using boost::property_tree::ptree;
|
||||
using boost::property_tree::write_json;
|
||||
using boost::property_tree::read_json;
|
||||
using boost::optional;
|
||||
using boost::none;
|
||||
using std::ostream;
|
||||
using std::istream;
|
||||
using std::ifstream;
|
||||
using std::ofstream;
|
||||
using std::string;
|
||||
|
||||
namespace cryfs {
|
||||
|
||||
namespace {
|
||||
|
||||
ptree _load(const bf::path &metadataFilePath) {
|
||||
ptree result;
|
||||
|
||||
ifstream file(metadataFilePath.native());
|
||||
if (file.good()) {
|
||||
read_json(file, result);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void _save(const bf::path &metadataFilePath, const ptree& data) {
|
||||
ofstream file(metadataFilePath.native(), std::ios::trunc);
|
||||
write_json(file, data);
|
||||
}
|
||||
|
||||
string jsonPathForBasedir(const bf::path &basedir) {
|
||||
return bf::canonical(basedir).native() + ".filesystemId";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
BasedirMetadata::BasedirMetadata(ptree data)
|
||||
:_data(std::move(data)) {}
|
||||
|
||||
BasedirMetadata BasedirMetadata::load() {
|
||||
return BasedirMetadata(_load(LocalStateDir::forBasedirMetadata()));
|
||||
}
|
||||
|
||||
void BasedirMetadata::save() {
|
||||
_save(LocalStateDir::forBasedirMetadata(), _data);
|
||||
}
|
||||
|
||||
bool BasedirMetadata::filesystemIdForBasedirIsCorrect(const bf::path &basedir, const CryConfig::FilesystemID &filesystemId) const {
|
||||
auto entry = _data.get_optional<string>(jsonPathForBasedir(basedir));
|
||||
if (entry == boost::none) {
|
||||
return true; // Basedir not known in local state yet.
|
||||
}
|
||||
auto filesystemIdFromState = CryConfig::FilesystemID::FromString(*entry);
|
||||
return filesystemIdFromState == filesystemId;
|
||||
}
|
||||
|
||||
BasedirMetadata& BasedirMetadata::updateFilesystemIdForBasedir(const bf::path &basedir, const CryConfig::FilesystemID &filesystemId) {
|
||||
_data.put<string>(jsonPathForBasedir(basedir), filesystemId.ToString());
|
||||
return *this;
|
||||
}
|
||||
|
||||
}
|
32
src/cryfs/localstate/BasedirMetadata.h
Normal file
32
src/cryfs/localstate/BasedirMetadata.h
Normal file
@ -0,0 +1,32 @@
|
||||
#pragma once
|
||||
#ifndef MESSMER_CRYFS_LOCALSTATE_BASEDIRMETADATA_H_
|
||||
#define MESSMER_CRYFS_LOCALSTATE_BASEDIRMETADATA_H_
|
||||
|
||||
#include <boost/filesystem/path.hpp>
|
||||
#include <boost/property_tree/ptree.hpp>
|
||||
#include "../config/CryConfig.h"
|
||||
|
||||
namespace cryfs {
|
||||
|
||||
class BasedirMetadata final {
|
||||
public:
|
||||
static BasedirMetadata load();
|
||||
void save();
|
||||
|
||||
BasedirMetadata(const BasedirMetadata&) = delete;
|
||||
BasedirMetadata& operator=(const BasedirMetadata&) = delete;
|
||||
BasedirMetadata(BasedirMetadata&&) = default;
|
||||
BasedirMetadata& operator=(BasedirMetadata&&) = default;
|
||||
|
||||
bool filesystemIdForBasedirIsCorrect(const boost::filesystem::path &basedir, const CryConfig::FilesystemID &filesystemId) const;
|
||||
BasedirMetadata& updateFilesystemIdForBasedir(const boost::filesystem::path &basedir, const CryConfig::FilesystemID &filesystemId);
|
||||
|
||||
private:
|
||||
BasedirMetadata(boost::property_tree::ptree data);
|
||||
|
||||
boost::property_tree::ptree _data;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
@ -5,19 +5,29 @@
|
||||
namespace bf = boost::filesystem;
|
||||
|
||||
namespace cryfs {
|
||||
namespace {
|
||||
bf::path appDir() {
|
||||
return cpputils::system::HomeDirectory::get() / ".cryfs";
|
||||
}
|
||||
}
|
||||
|
||||
bf::path LocalStateDir::forFilesystemId(const CryConfig::FilesystemID &filesystemId) {
|
||||
bf::path app_dir = cpputils::system::HomeDirectory::get() / ".cryfs";
|
||||
_createDirIfNotExists(app_dir);
|
||||
bf::path filesystems_dir = app_dir / "filesystems";
|
||||
_createDirIfNotExists(filesystems_dir);
|
||||
bf::path this_filesystem_dir = filesystems_dir / filesystemId.ToString();
|
||||
_createDirIfNotExists(this_filesystem_dir);
|
||||
return this_filesystem_dir;
|
||||
_createDirIfNotExists(appDir());
|
||||
bf::path filesystems_dir = appDir() / "filesystems";
|
||||
_createDirIfNotExists(filesystems_dir);
|
||||
bf::path this_filesystem_dir = filesystems_dir / filesystemId.ToString();
|
||||
_createDirIfNotExists(this_filesystem_dir);
|
||||
return this_filesystem_dir;
|
||||
}
|
||||
|
||||
bf::path LocalStateDir::forBasedirMetadata() {
|
||||
_createDirIfNotExists(appDir());
|
||||
return appDir() / "basedirs";
|
||||
}
|
||||
|
||||
void LocalStateDir::_createDirIfNotExists(const bf::path &path) {
|
||||
if (!bf::exists(path)) {
|
||||
bf::create_directory(path);
|
||||
bf::create_directories(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -11,6 +11,7 @@ namespace cryfs {
|
||||
class LocalStateDir final {
|
||||
public:
|
||||
static boost::filesystem::path forFilesystemId(const CryConfig::FilesystemID &filesystemId);
|
||||
static boost::filesystem::path forBasedirMetadata();
|
||||
|
||||
private:
|
||||
LocalStateDir(); // static functions only
|
||||
|
121
src/cryfs/localstate/LocalStateMetadata.cpp
Normal file
121
src/cryfs/localstate/LocalStateMetadata.cpp
Normal file
@ -0,0 +1,121 @@
|
||||
#include "LocalStateMetadata.h"
|
||||
#include <boost/property_tree/ptree.hpp>
|
||||
#include <boost/property_tree/json_parser.hpp>
|
||||
#include <cpp-utils/random/Random.h>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <blockstore/implementations/integrity/KnownBlockVersions.h>
|
||||
|
||||
using boost::optional;
|
||||
using boost::none;
|
||||
using boost::property_tree::ptree;
|
||||
using boost::property_tree::write_json;
|
||||
using boost::property_tree::read_json;
|
||||
using std::ifstream;
|
||||
using std::ofstream;
|
||||
using std::istream;
|
||||
using std::ostream;
|
||||
using std::string;
|
||||
using blockstore::integrity::KnownBlockVersions;
|
||||
using cpputils::hash::Hash;
|
||||
using cpputils::Data;
|
||||
using cpputils::Random;
|
||||
namespace bf = boost::filesystem;
|
||||
|
||||
namespace cryfs {
|
||||
|
||||
LocalStateMetadata::LocalStateMetadata(uint32_t myClientId, Hash encryptionKeyHash)
|
||||
: _myClientId(myClientId), _encryptionKeyHash(std::move(encryptionKeyHash)) {}
|
||||
|
||||
LocalStateMetadata LocalStateMetadata::loadOrGenerate(const bf::path &statePath, const Data& encryptionKey) {
|
||||
auto metadataFile = statePath / "metadata";
|
||||
auto loaded = _load(metadataFile);
|
||||
if (loaded == none) {
|
||||
// If it couldn't be loaded, generate a new client id.
|
||||
return _generate(metadataFile, encryptionKey);
|
||||
}
|
||||
|
||||
if (loaded->_encryptionKeyHash.digest != cpputils::hash::hash(encryptionKey, loaded->_encryptionKeyHash.salt).digest) {
|
||||
throw std::runtime_error("The filesystem encryption key differs from the last time we loaded this filesystem. Did an attacker replace the file system?");
|
||||
}
|
||||
return *loaded;
|
||||
}
|
||||
|
||||
optional<LocalStateMetadata> LocalStateMetadata::_load(const bf::path &metadataFilePath) {
|
||||
ifstream file(metadataFilePath.native());
|
||||
if (!file.good()) {
|
||||
// State file doesn't exist
|
||||
return none;
|
||||
}
|
||||
return _deserialize(file);
|
||||
}
|
||||
|
||||
void LocalStateMetadata::_save(const bf::path &metadataFilePath) const {
|
||||
ofstream file(metadataFilePath.native(), std::ios::trunc);
|
||||
_serialize(file);
|
||||
}
|
||||
|
||||
namespace {
|
||||
uint32_t _generateClientId() {
|
||||
uint32_t result;
|
||||
do {
|
||||
result = *reinterpret_cast<uint32_t*>(Random::PseudoRandom().getFixedSize<sizeof(uint32_t)>().data());
|
||||
} while(result == KnownBlockVersions::CLIENT_ID_FOR_DELETED_BLOCK); // Safety check - CLIENT_ID_FOR_DELETED_BLOCK shouldn't be used by any valid client.
|
||||
return result;
|
||||
}
|
||||
|
||||
#ifndef CRYFS_NO_COMPATIBILITY
|
||||
optional<uint32_t> _tryLoadClientIdFromLegacyFile(const bf::path &metadataFilePath) {
|
||||
auto myClientIdFile = metadataFilePath.parent_path() / "myClientId";
|
||||
ifstream file(myClientIdFile.native());
|
||||
if (!file.good()) {
|
||||
return none;
|
||||
}
|
||||
|
||||
uint32_t value;
|
||||
file >> value;
|
||||
file.close();
|
||||
bf::remove(myClientIdFile);
|
||||
return value;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
LocalStateMetadata LocalStateMetadata::_generate(const bf::path &metadataFilePath, const Data& encryptionKey) {
|
||||
uint32_t myClientId = _generateClientId();
|
||||
#ifndef CRYFS_NO_COMPATIBILITY
|
||||
// In the old format, this was stored in a "myClientId" file. If that file exists, load it from there.
|
||||
optional<uint32_t> legacy = _tryLoadClientIdFromLegacyFile(metadataFilePath);
|
||||
if (legacy != none) {
|
||||
myClientId = *legacy;
|
||||
}
|
||||
#endif
|
||||
|
||||
LocalStateMetadata result(myClientId, cpputils::hash::hash(encryptionKey, cpputils::hash::generateSalt()));
|
||||
result._save(metadataFilePath);
|
||||
return result;
|
||||
}
|
||||
|
||||
void LocalStateMetadata::_serialize(ostream& stream) const {
|
||||
ptree pt;
|
||||
pt.put<uint32_t>("myClientId", myClientId());
|
||||
pt.put<string>("encryptionKey.salt", _encryptionKeyHash.salt.ToString());
|
||||
pt.put<string>("encryptionKey.hash", _encryptionKeyHash.digest.ToString());
|
||||
|
||||
write_json(stream, pt);
|
||||
}
|
||||
|
||||
LocalStateMetadata LocalStateMetadata::_deserialize(istream& stream) {
|
||||
ptree pt;
|
||||
read_json(stream, pt);
|
||||
|
||||
uint32_t myClientId = pt.get<uint32_t>("myClientId");
|
||||
string encryptionKeySalt = pt.get<string>("encryptionKey.salt");
|
||||
string encryptionKeyDigest = pt.get<string>("encryptionKey.hash");
|
||||
|
||||
return LocalStateMetadata(myClientId, Hash{
|
||||
.digest = cpputils::hash::Digest::FromString(std::move(encryptionKeyDigest)),
|
||||
.salt = cpputils::hash::Salt::FromString(std::move(encryptionKeySalt))
|
||||
});
|
||||
}
|
||||
|
||||
}
|
38
src/cryfs/localstate/LocalStateMetadata.h
Normal file
38
src/cryfs/localstate/LocalStateMetadata.h
Normal file
@ -0,0 +1,38 @@
|
||||
#pragma once
|
||||
#ifndef MESSMER_CRYFS_LOCALSTATE_LOCALSTATEMETADATA_H_
|
||||
#define MESSMER_CRYFS_LOCALSTATE_LOCALSTATEMETADATA_H_
|
||||
|
||||
#include <boost/filesystem/path.hpp>
|
||||
#include <boost/optional.hpp>
|
||||
#include <iostream>
|
||||
#include <cpp-utils/crypto/hash/Hash.h>
|
||||
|
||||
namespace cryfs {
|
||||
|
||||
class LocalStateMetadata final {
|
||||
public:
|
||||
|
||||
static LocalStateMetadata loadOrGenerate(const boost::filesystem::path &statePath, const cpputils::Data& encryptionKey);
|
||||
|
||||
uint32_t myClientId() const;
|
||||
|
||||
private:
|
||||
const uint32_t _myClientId;
|
||||
const cpputils::hash::Hash _encryptionKeyHash;
|
||||
|
||||
static boost::optional<LocalStateMetadata> _load(const boost::filesystem::path &metadataFilePath);
|
||||
static LocalStateMetadata _deserialize(std::istream& stream);
|
||||
static LocalStateMetadata _generate(const boost::filesystem::path &metadataFilePath, const cpputils::Data& encryptionKey);
|
||||
void _save(const boost::filesystem::path &metadataFilePath) const;
|
||||
void _serialize(std::ostream& stream) const;
|
||||
|
||||
LocalStateMetadata(uint32_t myClientId, cpputils::hash::Hash encryptionKey);
|
||||
};
|
||||
|
||||
inline uint32_t LocalStateMetadata::myClientId() const {
|
||||
return _myClientId;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
@ -1,54 +0,0 @@
|
||||
#include "MyClientId.h"
|
||||
#include <fstream>
|
||||
#include <cpp-utils/random/Random.h>
|
||||
#include <blockstore/implementations/integrity/KnownBlockVersions.h>
|
||||
|
||||
using boost::optional;
|
||||
using boost::none;
|
||||
using std::ifstream;
|
||||
using std::ofstream;
|
||||
using cpputils::Random;
|
||||
using blockstore::integrity::KnownBlockVersions;
|
||||
namespace bf = boost::filesystem;
|
||||
|
||||
namespace cryfs {
|
||||
|
||||
MyClientId::MyClientId(const bf::path &statePath)
|
||||
:_stateFilePath(statePath / "myClientId") {
|
||||
}
|
||||
|
||||
uint32_t MyClientId::loadOrGenerate() const {
|
||||
auto loaded = _load();
|
||||
if (loaded != none) {
|
||||
return *loaded;
|
||||
}
|
||||
// If it couldn't be loaded, generate a new client id.
|
||||
auto generated = _generate();
|
||||
_save(generated);
|
||||
return generated;
|
||||
}
|
||||
|
||||
uint32_t MyClientId::_generate() {
|
||||
uint32_t result;
|
||||
do {
|
||||
result = *reinterpret_cast<uint32_t*>(Random::PseudoRandom().getFixedSize<sizeof(uint32_t)>().data());
|
||||
} while(result == KnownBlockVersions::CLIENT_ID_FOR_DELETED_BLOCK); // Safety check - CLIENT_ID_FOR_DELETED_BLOCK shouldn't be used by any valid client.
|
||||
return result;
|
||||
}
|
||||
|
||||
optional<uint32_t> MyClientId::_load() const {
|
||||
ifstream file(_stateFilePath.native());
|
||||
if (!file.good()) {
|
||||
// State file doesn't exist
|
||||
return none;
|
||||
}
|
||||
uint32_t value;
|
||||
file >> value;
|
||||
return value;
|
||||
}
|
||||
|
||||
void MyClientId::_save(uint32_t clientId) const {
|
||||
ofstream file(_stateFilePath.native());
|
||||
file << clientId;
|
||||
}
|
||||
}
|
@ -1,30 +0,0 @@
|
||||
#pragma once
|
||||
#ifndef MESSMER_CRYFS_LOCALSTATE_MYCLIENTID_H_
|
||||
#define MESSMER_CRYFS_LOCALSTATE_MYCLIENTID_H_
|
||||
|
||||
#include <cpp-utils/macros.h>
|
||||
#include <boost/filesystem/path.hpp>
|
||||
#include <boost/optional.hpp>
|
||||
|
||||
namespace cryfs {
|
||||
|
||||
class MyClientId final {
|
||||
public:
|
||||
MyClientId(const boost::filesystem::path &statePath);
|
||||
|
||||
uint32_t loadOrGenerate() const;
|
||||
|
||||
private:
|
||||
const boost::filesystem::path _stateFilePath;
|
||||
|
||||
static uint32_t _generate();
|
||||
boost::optional<uint32_t> _load() const;
|
||||
void _save(uint32_t clientId) const;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(MyClientId);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
@ -211,14 +211,14 @@ fuse_operations *operations() {
|
||||
|
||||
Fuse::~Fuse() {
|
||||
for(char *arg : _argv) {
|
||||
delete arg;
|
||||
delete[] arg;
|
||||
arg = nullptr;
|
||||
}
|
||||
_argv.clear();
|
||||
}
|
||||
|
||||
Fuse::Fuse(Filesystem *fs, const std::string &fstype, const boost::optional<std::string> &fsname)
|
||||
:_fs(fs), _mountdir(), _running(false), _fstype(fstype), _fsname(fsname) {
|
||||
Fuse::Fuse(Filesystem *fs, std::string fstype, boost::optional<std::string> fsname)
|
||||
:_fs(fs), _mountdir(), _running(false), _fstype(std::move(fstype)), _fsname(std::move(fsname)) {
|
||||
}
|
||||
|
||||
void Fuse::_logException(const std::exception &e) {
|
||||
|
@ -19,7 +19,7 @@ class Filesystem;
|
||||
|
||||
class Fuse final {
|
||||
public:
|
||||
explicit Fuse(Filesystem *fs, const std::string &fstype, const boost::optional<std::string> &fsname);
|
||||
explicit Fuse(Filesystem *fs, std::string fstype, boost::optional<std::string> fsname);
|
||||
~Fuse();
|
||||
|
||||
void run(const boost::filesystem::path &mountdir, const std::vector<std::string> &fuseOptions);
|
||||
|
@ -16,6 +16,12 @@ using cpputils::DataFixture;
|
||||
using cpputils::unique_ref;
|
||||
using boost::optional;
|
||||
|
||||
namespace boost {
|
||||
inline void PrintTo(const optional<cpputils::Data> &, ::std::ostream *os) {
|
||||
*os << "optional<Data>";
|
||||
}
|
||||
}
|
||||
|
||||
using namespace blockstore;
|
||||
|
||||
class BlockStore2Mock: public BlockStore2 {
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include <gmock/gmock.h>
|
||||
#include <cpp-utils/data/DataFixture.h>
|
||||
#include <cpp-utils/pointer/unique_ref_boost_optional_gtest_workaround.h>
|
||||
|
||||
#include "blockstore/interface/BlockStore.h"
|
||||
|
||||
@ -285,7 +286,7 @@ TYPED_TEST_P(BlockStoreTest, Resize_Smaller_ToZero_BlockIsStillUsable) {
|
||||
block->resize(0);
|
||||
this->TestBlockIsUsable(std::move(block), blockStore.get());
|
||||
}
|
||||
|
||||
/*
|
||||
TYPED_TEST_P(BlockStoreTest, TryCreateTwoBlocksWithSameBlockIdAndSameSize) {
|
||||
auto blockStore = this->fixture.createBlockStore();
|
||||
blockstore::BlockId blockId = blockstore::BlockId::FromString("1491BB4932A389EE14BC7090AC772972");
|
||||
@ -295,7 +296,7 @@ TYPED_TEST_P(BlockStoreTest, TryCreateTwoBlocksWithSameBlockIdAndSameSize) {
|
||||
EXPECT_NE(boost::none, block);
|
||||
EXPECT_EQ(boost::none, block2);
|
||||
}
|
||||
/*
|
||||
|
||||
TYPED_TEST_P(BlockStoreTest, TryCreateTwoBlocksWithSameBlockIdAndDifferentSize) {
|
||||
auto blockStore = this->fixture.createBlockStore();
|
||||
blockstore::BlockId blockId = blockstore::BlockId::FromString("1491BB4932A389EE14BC7090AC772972");
|
||||
@ -383,6 +384,7 @@ REGISTER_TYPED_TEST_CASE_P(BlockStoreTest,
|
||||
ForEachBlock_twoblocks,
|
||||
ForEachBlock_threeblocks,
|
||||
ForEachBlock_doesntListRemovedBlocks_oneblock,
|
||||
ForEachBlock_doesntListRemovedBlocks_twoblocks,
|
||||
Resize_Larger_FromZero,
|
||||
Resize_Larger_FromZero_BlockIsStillUsable,
|
||||
Resize_Larger,
|
||||
@ -390,10 +392,10 @@ REGISTER_TYPED_TEST_CASE_P(BlockStoreTest,
|
||||
Resize_Smaller,
|
||||
Resize_Smaller_BlockIsStillUsable,
|
||||
Resize_Smaller_ToZero,
|
||||
Resize_Smaller_ToZero_BlockIsStillUsable,
|
||||
TryCreateTwoBlocksWithSameBlockIdAndSameSize
|
||||
Resize_Smaller_ToZero_BlockIsStillUsable
|
||||
//TODO Just disabled because gtest doesn't allow more template parameters. Fix and reenable!
|
||||
// see https://github.com/google/googletest/issues/1267
|
||||
//TryCreateTwoBlocksWithSameBlockIdAndSameSize,
|
||||
//TryCreateTwoBlocksWithSameBlockIdAndDifferentSize,
|
||||
//TryCreateTwoBlocksWithSameBlockIdAndFirstNullSize,
|
||||
//TryCreateTwoBlocksWithSameBlockIdAndSecondNullSize,
|
||||
|
@ -6,6 +6,7 @@ set(SOURCES
|
||||
crypto/symmetric/testutils/FakeAuthenticatedCipher.cpp
|
||||
crypto/kdf/SCryptTest.cpp
|
||||
crypto/kdf/SCryptParametersTest.cpp
|
||||
crypto/hash/HashTest.cpp
|
||||
MacrosIncludeTest.cpp
|
||||
pointer/unique_ref_test.cpp
|
||||
pointer/cast_include_test.cpp
|
||||
|
45
test/cpp-utils/crypto/hash/HashTest.cpp
Normal file
45
test/cpp-utils/crypto/hash/HashTest.cpp
Normal file
@ -0,0 +1,45 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include <cpp-utils/crypto/hash/Hash.h>
|
||||
#include <cpp-utils/data/DataFixture.h>
|
||||
|
||||
using namespace cpputils::hash;
|
||||
using cpputils::DataFixture;
|
||||
using cpputils::Data;
|
||||
|
||||
TEST(HashTest, generateSalt_isIndeterministic) {
|
||||
EXPECT_NE(generateSalt(), generateSalt());
|
||||
}
|
||||
|
||||
TEST(HashTest, hash_setsSaltCorrectly) {
|
||||
Salt salt = generateSalt();
|
||||
Data data = DataFixture::generate(1024);
|
||||
EXPECT_EQ(salt, hash(data, salt).salt);
|
||||
}
|
||||
|
||||
TEST(HashTest, hash_isDeterministicWithSameDataSameSalt) {
|
||||
Salt salt = generateSalt();
|
||||
Data data = DataFixture::generate(1024);
|
||||
EXPECT_EQ(hash(data, salt).digest, hash(data, salt).digest);
|
||||
}
|
||||
|
||||
TEST(HashTest, hash_isIndeterministicWithSameDataDifferentSalt) {
|
||||
Salt salt1 = generateSalt();
|
||||
Salt salt2 = generateSalt();
|
||||
Data data = DataFixture::generate(1024);
|
||||
EXPECT_NE(hash(data, salt1).digest, hash(data, salt2).digest);
|
||||
}
|
||||
|
||||
TEST(HashTest, hash_isIndeterministicWithDifferentDataSameSalt) {
|
||||
Salt salt = generateSalt();
|
||||
Data data1 = DataFixture::generate(1024, 1);
|
||||
Data data2 = DataFixture::generate(1024, 2);
|
||||
EXPECT_NE(hash(data1, salt).digest, hash(data2, salt).digest);
|
||||
}
|
||||
|
||||
TEST(HashTest, hash_isIndeterministicWithDifferentDataDifferentSalt) {
|
||||
Salt salt1 = generateSalt();
|
||||
Salt salt2 = generateSalt();
|
||||
Data data1 = DataFixture::generate(1024, 1);
|
||||
Data data2 = DataFixture::generate(1024, 2);
|
||||
EXPECT_NE(hash(data1, salt1).digest, hash(data2, salt2).digest);
|
||||
}
|
@ -14,6 +14,7 @@ using cpputils::TempFile;
|
||||
|
||||
using std::ifstream;
|
||||
using std::ofstream;
|
||||
using std::string;
|
||||
|
||||
namespace bf = boost::filesystem;
|
||||
|
||||
@ -206,3 +207,17 @@ TEST_F(DataTest, LoadingNonexistingFile) {
|
||||
TempFile file(false); // Pass false to constructor, so the tempfile is not created
|
||||
EXPECT_FALSE(Data::LoadFromFile(file.path()));
|
||||
}
|
||||
|
||||
class DataTestWithStringParam: public DataTest, public WithParamInterface<string> {};
|
||||
INSTANTIATE_TEST_CASE_P(DataTestWithStringParam, DataTestWithStringParam, Values("", "2898B4B8A13C0F0278CCE465DB", "6FFEBAD90C0DAA2B79628F0627CE9841"));
|
||||
|
||||
TEST_P(DataTestWithStringParam, FromAndToString) {
|
||||
Data data = Data::FromString(GetParam());
|
||||
EXPECT_EQ(GetParam(), data.ToString());
|
||||
}
|
||||
|
||||
TEST_P(DataTestWithStringParam, ToAndFromString) {
|
||||
Data data = Data::FromString(GetParam());
|
||||
Data data2 = Data::FromString(data.ToString());
|
||||
EXPECT_EQ(data, data2);
|
||||
}
|
||||
|
@ -9,6 +9,12 @@ using testing::MatchesRegex;
|
||||
|
||||
using namespace cpputils;
|
||||
|
||||
// Disable these by default because they depend on network
|
||||
// and - even if network is available - can fail depending
|
||||
// on the concrete network setup (e.g. if invalid domains are
|
||||
// answered with an ISP page instead of HTTP error)
|
||||
#ifdef CRYFS_ENABLE_NETWORK_TESTS
|
||||
|
||||
TEST(CurlHttpClientTest, InvalidProtocol) {
|
||||
EXPECT_EQ(none, CurlHttpClient().get("invalid://example.com"));
|
||||
}
|
||||
@ -30,3 +36,5 @@ TEST(CurlHttpClientTest, ValidHttps) {
|
||||
string content = CurlHttpClient().get("https://example.com").value();
|
||||
EXPECT_THAT(content, MatchesRegex(".*Example Domain.*"));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -11,6 +11,7 @@ set(SOURCES
|
||||
CliTest_ShowingHelp.cpp
|
||||
EnvironmentTest.cpp
|
||||
VersionCheckerTest.cpp
|
||||
CliTest_IntegrityCheck.cpp
|
||||
)
|
||||
|
||||
add_executable(${PROJECT_NAME} ${SOURCES})
|
||||
|
44
test/cryfs-cli/CliTest_IntegrityCheck.cpp
Normal file
44
test/cryfs-cli/CliTest_IntegrityCheck.cpp
Normal file
@ -0,0 +1,44 @@
|
||||
#include "testutils/CliTest.h"
|
||||
#include <cryfs/config/CryConfigFile.h>
|
||||
|
||||
using std::vector;
|
||||
using std::string;
|
||||
using cryfs::CryConfig;
|
||||
using cryfs::CryConfigFile;
|
||||
|
||||
class CliTest_IntegrityCheck: public CliTest {
|
||||
public:
|
||||
void modifyFilesystemId() {
|
||||
auto configFile = CryConfigFile::load(basedir / "cryfs.config", "pass").value();
|
||||
configFile.config()->SetFilesystemId(CryConfig::FilesystemID::FromString("0123456789ABCDEF0123456789ABCDEF"));
|
||||
configFile.save();
|
||||
}
|
||||
|
||||
void modifyFilesystemKey() {
|
||||
auto configFile = CryConfigFile::load(basedir / "cryfs.config", "pass").value();
|
||||
configFile.config()->SetEncryptionKey("0123456789ABCDEF0123456789ABCDEF");
|
||||
configFile.save();
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(CliTest_IntegrityCheck, givenIncorrectFilesystemId_thenFails) {
|
||||
vector<const char*> args {basedir.c_str(), mountdir.c_str(), "--cipher", "aes-256-gcm", "-f"};
|
||||
//TODO Remove "-f" parameter, once EXPECT_RUN_SUCCESS can handle that
|
||||
EXPECT_RUN_SUCCESS(args, mountdir);
|
||||
modifyFilesystemId();
|
||||
EXPECT_RUN_ERROR(
|
||||
args,
|
||||
"Error: The filesystem id in the config file is different to the last time we loaded a filesystem from this basedir."
|
||||
);
|
||||
}
|
||||
|
||||
TEST_F(CliTest_IntegrityCheck, givenIncorrectFilesystemKey_thenFails) {
|
||||
vector<const char*> args {basedir.c_str(), mountdir.c_str(), "--cipher", "aes-256-gcm", "-f"};
|
||||
//TODO Remove "-f" parameter, once EXPECT_RUN_SUCCESS can handle that
|
||||
EXPECT_RUN_SUCCESS(args, mountdir);
|
||||
modifyFilesystemKey();
|
||||
EXPECT_RUN_ERROR(
|
||||
args,
|
||||
"Error: The filesystem encryption key differs from the last time we loaded this filesystem. Did an attacker replace the file system?"
|
||||
);
|
||||
}
|
@ -15,15 +15,15 @@ using namespace cryfs;
|
||||
class VersionCheckerTest: public ::testing::Test {
|
||||
public:
|
||||
unique_ref<VersionChecker> versionChecker() {
|
||||
return make_unique_ref<VersionChecker>(http);
|
||||
return make_unique_ref<VersionChecker>(_http.get());
|
||||
}
|
||||
|
||||
void setVersionInfo(const string &versionInfo) {
|
||||
http->addWebsite("https://www.cryfs.org/version_info.json", versionInfo);
|
||||
_http->addWebsite("https://www.cryfs.org/version_info.json", versionInfo);
|
||||
}
|
||||
|
||||
private:
|
||||
shared_ptr<FakeHttpClient> http = make_shared<FakeHttpClient>();
|
||||
unique_ref<FakeHttpClient> _http = make_unique_ref<FakeHttpClient>();
|
||||
};
|
||||
|
||||
TEST_F(VersionCheckerTest, NewestVersion_NoInternet) {
|
||||
|
@ -12,8 +12,9 @@
|
||||
#include <cpp-utils/process/subprocess.h>
|
||||
#include <cpp-utils/network/FakeHttpClient.h>
|
||||
#include "../../cryfs/testutils/MockConsole.h"
|
||||
#include "../../cryfs/testutils/TestWithFakeHomeDirectory.h"
|
||||
|
||||
class CliTest : public ::testing::Test {
|
||||
class CliTest : public ::testing::Test, TestWithFakeHomeDirectory {
|
||||
public:
|
||||
CliTest(): _basedir(), _mountdir(), basedir(_basedir.path()), mountdir(_mountdir.path()), logfile(), configfile(false), console(std::make_shared<MockConsole>()) {}
|
||||
|
||||
@ -25,10 +26,10 @@ public:
|
||||
cpputils::TempFile configfile;
|
||||
std::shared_ptr<MockConsole> console;
|
||||
|
||||
std::shared_ptr<cpputils::HttpClient> _httpClient() {
|
||||
std::shared_ptr<cpputils::FakeHttpClient> httpClient = std::make_shared<cpputils::FakeHttpClient>();
|
||||
cpputils::unique_ref<cpputils::HttpClient> _httpClient() {
|
||||
cpputils::unique_ref<cpputils::FakeHttpClient> httpClient = cpputils::make_unique_ref<cpputils::FakeHttpClient>();
|
||||
httpClient->addWebsite("https://www.cryfs.org/version_info.json", "{\"version_info\":{\"current\":\"0.8.5\"}}");
|
||||
return std::shared_ptr<cpputils::HttpClient>(std::move(httpClient));
|
||||
return std::move(httpClient);
|
||||
}
|
||||
|
||||
void run(std::vector<const char*> args) {
|
||||
@ -43,7 +44,7 @@ public:
|
||||
std::cin.putback('\n'); std::cin.putback('s'); std::cin.putback('s'); std::cin.putback('a'); std::cin.putback('p');
|
||||
std::cin.putback('\n'); std::cin.putback('s'); std::cin.putback('s'); std::cin.putback('a'); std::cin.putback('p');
|
||||
// Run Cryfs
|
||||
cryfs::Cli(keyGenerator, cpputils::SCrypt::TestSettings, console, _httpClient()).main(_args.size(), _args.data());
|
||||
cryfs::Cli(keyGenerator, cpputils::SCrypt::TestSettings, console).main(_args.size(), _args.data(), _httpClient());
|
||||
}
|
||||
|
||||
void EXPECT_EXIT_WITH_HELP_MESSAGE(std::vector<const char*> args, const std::string &message = "") {
|
||||
|
@ -17,7 +17,8 @@ set(SOURCES
|
||||
filesystem/CryFsTest.cpp
|
||||
filesystem/CryNodeTest.cpp
|
||||
filesystem/FileSystemTest.cpp
|
||||
localstate/MyClientIdTest.cpp
|
||||
localstate/LocalStateMetadataTest.cpp
|
||||
localstate/BasedirMetadataTest.cpp
|
||||
)
|
||||
|
||||
add_executable(${PROJECT_NAME} ${SOURCES})
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include <cryfs/config/CryCipher.h>
|
||||
#include <cpp-utils/crypto/symmetric/ciphers.h>
|
||||
#include "../testutils/MockConsole.h"
|
||||
#include "../testutils/TestWithFakeHomeDirectory.h"
|
||||
#include <cpp-utils/io/NoninteractiveConsole.h>
|
||||
#include <gitversion/gitversion.h>
|
||||
|
||||
@ -46,7 +47,7 @@ using ::testing::WithParamInterface;
|
||||
#define IGNORE_ASK_FOR_MISSINGBLOCKISINTEGRITYVIOLATION() \
|
||||
EXPECT_CALL(*console, askYesNo(HasSubstr("missing block"), false))
|
||||
|
||||
class CryConfigCreatorTest: public ::testing::Test {
|
||||
class CryConfigCreatorTest: public ::testing::Test, TestWithFakeHomeDirectory {
|
||||
public:
|
||||
CryConfigCreatorTest()
|
||||
: console(make_shared<MockConsole>()),
|
||||
|
@ -1,6 +1,7 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include <cryfs/config/CryConfigLoader.h>
|
||||
#include "../testutils/MockConsole.h"
|
||||
#include "../testutils/TestWithFakeHomeDirectory.h"
|
||||
#include <cpp-utils/tempfile/TempFile.h>
|
||||
#include <cpp-utils/random/Random.h>
|
||||
#include <cpp-utils/crypto/symmetric/ciphers.h>
|
||||
@ -14,6 +15,7 @@ using cpputils::make_unique_ref;
|
||||
using cpputils::TempFile;
|
||||
using cpputils::SCrypt;
|
||||
using cpputils::DataFixture;
|
||||
using cpputils::Data;
|
||||
using cpputils::NoninteractiveConsole;
|
||||
using boost::optional;
|
||||
using boost::none;
|
||||
@ -32,9 +34,28 @@ namespace boost {
|
||||
return stream << "CryConfigFile()";
|
||||
}
|
||||
}
|
||||
namespace cryfs {
|
||||
inline ostream &operator<<(ostream &stream, const CryConfigLoader::ConfigLoadResult &) {
|
||||
return stream << "ConfigLoadResult()";
|
||||
}
|
||||
}
|
||||
#include <boost/optional/optional_io.hpp>
|
||||
|
||||
class CryConfigLoaderTest: public ::testing::Test, public TestWithMockConsole {
|
||||
class FakeRandomGenerator final : public cpputils::RandomGenerator {
|
||||
public:
|
||||
FakeRandomGenerator(Data output)
|
||||
: _output(std::move(output)) {}
|
||||
|
||||
void _get(void *target, size_t bytes) override {
|
||||
ASSERT_EQ(_output.size(), bytes);
|
||||
std::memcpy(target, _output.data(), bytes);
|
||||
}
|
||||
|
||||
private:
|
||||
Data _output;
|
||||
};
|
||||
|
||||
class CryConfigLoaderTest: public ::testing::Test, public TestWithMockConsole, TestWithFakeHomeDirectory {
|
||||
public:
|
||||
CryConfigLoaderTest(): file(false) {
|
||||
console = mockConsole();
|
||||
@ -78,7 +99,15 @@ public:
|
||||
}
|
||||
|
||||
void CreateWithEncryptionKey(const string &encKey, const string &password = "mypassword") {
|
||||
auto cfg = loader(password, false).loadOrCreate(file.path()).value().configFile;
|
||||
auto askPassword = [password] { return password;};
|
||||
FakeRandomGenerator generator(Data::FromString(encKey));
|
||||
auto loader = CryConfigLoader(console, generator, SCrypt::TestSettings, askPassword,
|
||||
askPassword, none, none, none);
|
||||
ASSERT_NE(boost::none, loader.loadOrCreate(file.path()));
|
||||
}
|
||||
|
||||
void ChangeEncryptionKey(const string &encKey, const string& password = "mypassword") {
|
||||
auto cfg = CryConfigFile::load(file.path(), password).value();
|
||||
cfg.config()->SetEncryptionKey(encKey);
|
||||
cfg.save();
|
||||
}
|
||||
@ -96,6 +125,12 @@ public:
|
||||
cfg.save();
|
||||
}
|
||||
|
||||
void ChangeFilesystemID(const CryConfig::FilesystemID &filesystemId, const string& password = "mypassword") {
|
||||
auto cfg = CryConfigFile::load(file.path(), password).value();
|
||||
cfg.config()->SetFilesystemId(filesystemId);
|
||||
cfg.save();
|
||||
}
|
||||
|
||||
string olderVersion() {
|
||||
string olderVersion;
|
||||
if (std::stol(gitversion::MinorVersion()) > 0) {
|
||||
@ -176,9 +211,18 @@ TEST_F(CryConfigLoaderTest, RootBlob_Create) {
|
||||
}
|
||||
|
||||
TEST_F(CryConfigLoaderTest, EncryptionKey_Load) {
|
||||
CreateWithEncryptionKey("encryptionkey");
|
||||
CreateWithEncryptionKey("3B4682CF22F3CA199E385729B9F3CA19D325229E385729B9443CA19D325229E3");
|
||||
auto loaded = Load().value();
|
||||
EXPECT_EQ("encryptionkey", loaded.config()->EncryptionKey());
|
||||
EXPECT_EQ("3B4682CF22F3CA199E385729B9F3CA19D325229E385729B9443CA19D325229E3", loaded.config()->EncryptionKey());
|
||||
}
|
||||
|
||||
TEST_F(CryConfigLoaderTest, EncryptionKey_Load_whenKeyChanged_thenFails) {
|
||||
CreateWithEncryptionKey("3B4682CF22F3CA199E385729B9F3CA19D325229E385729B9443CA19D325229E3");
|
||||
ChangeEncryptionKey("3B4682CF22F3CA199E385729B9F3CA19D325229E385729B9443CA19D325229E4");
|
||||
EXPECT_THROW(
|
||||
Load(),
|
||||
std::runtime_error
|
||||
);
|
||||
}
|
||||
|
||||
TEST_F(CryConfigLoaderTest, EncryptionKey_Create) {
|
||||
|
66
test/cryfs/localstate/BasedirMetadataTest.cpp
Normal file
66
test/cryfs/localstate/BasedirMetadataTest.cpp
Normal file
@ -0,0 +1,66 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <cryfs/localstate/BasedirMetadata.h>
|
||||
#include <cryfs/localstate/LocalStateDir.h>
|
||||
#include <cryfs/config/CryConfig.h>
|
||||
#include <cpp-utils/tempfile/TempDir.h>
|
||||
#include "../testutils/TestWithFakeHomeDirectory.h"
|
||||
|
||||
using cpputils::TempDir;
|
||||
using cryfs::BasedirMetadata;
|
||||
using std::ofstream;
|
||||
namespace bf = boost::filesystem;
|
||||
using FilesystemID = cryfs::CryConfig::FilesystemID ;
|
||||
|
||||
class BasedirMetadataTest : public ::testing::Test, TestWithFakeHomeDirectory {
|
||||
public:
|
||||
TempDir tempdir;
|
||||
bf::path basedir1;
|
||||
bf::path basedir2;
|
||||
const FilesystemID id1;
|
||||
const FilesystemID id2;
|
||||
|
||||
BasedirMetadataTest()
|
||||
: tempdir()
|
||||
, basedir1(tempdir.path() / "my/basedir")
|
||||
, basedir2(tempdir.path() / "my/other/basedir")
|
||||
, id1(FilesystemID::FromString("1491BB4932A389EE14BC7090AC772972"))
|
||||
, id2(FilesystemID::FromString("A1491BB493214BC7090C772972A389EE"))
|
||||
{
|
||||
// Create basedirs so bf::canonical() works
|
||||
bf::create_directories(basedir1);
|
||||
bf::create_directories(basedir2);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
TEST_F(BasedirMetadataTest, givenEmptyState_whenCalled_thenSucceeds) {
|
||||
EXPECT_TRUE(BasedirMetadata::load().filesystemIdForBasedirIsCorrect(basedir1, id1));
|
||||
}
|
||||
|
||||
TEST_F(BasedirMetadataTest, givenStateWithBasedir_whenCalledForDifferentBasedir_thenSucceeds) {
|
||||
BasedirMetadata::load().updateFilesystemIdForBasedir(basedir2, id1).save();
|
||||
EXPECT_TRUE(BasedirMetadata::load().filesystemIdForBasedirIsCorrect(basedir1, id1));
|
||||
}
|
||||
|
||||
TEST_F(BasedirMetadataTest, givenStateWithBasedir_whenCalledWithSameId_thenSucceeds) {
|
||||
BasedirMetadata::load().updateFilesystemIdForBasedir(basedir1, id1).save();
|
||||
EXPECT_TRUE(BasedirMetadata::load().filesystemIdForBasedirIsCorrect(basedir1, id1));
|
||||
}
|
||||
|
||||
TEST_F(BasedirMetadataTest, givenStateWithBasedir_whenCalledWithDifferentId_thenFails) {
|
||||
BasedirMetadata::load().updateFilesystemIdForBasedir(basedir1, id2).save();
|
||||
EXPECT_FALSE(BasedirMetadata::load().filesystemIdForBasedirIsCorrect(basedir1, id1));
|
||||
}
|
||||
|
||||
TEST_F(BasedirMetadataTest, givenStateWithUpdatedBasedir_whenCalledWithSameId_thenSucceeds) {
|
||||
BasedirMetadata::load().updateFilesystemIdForBasedir(basedir1, id2).save();
|
||||
BasedirMetadata::load().updateFilesystemIdForBasedir(basedir1, id1).save();
|
||||
EXPECT_TRUE(BasedirMetadata::load().filesystemIdForBasedirIsCorrect(basedir1, id1));
|
||||
}
|
||||
|
||||
TEST_F(BasedirMetadataTest, givenStateWithUpdatedBasedir_whenCalledWithDifferentId_thenFails) {
|
||||
BasedirMetadata::load().updateFilesystemIdForBasedir(basedir1, id2).save();
|
||||
BasedirMetadata::load().updateFilesystemIdForBasedir(basedir1, id1).save();
|
||||
EXPECT_FALSE(BasedirMetadata::load().filesystemIdForBasedirIsCorrect(basedir1, id2));
|
||||
}
|
54
test/cryfs/localstate/LocalStateMetadataTest.cpp
Normal file
54
test/cryfs/localstate/LocalStateMetadataTest.cpp
Normal file
@ -0,0 +1,54 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <cryfs/localstate/LocalStateMetadata.h>
|
||||
#include <cpp-utils/tempfile/TempDir.h>
|
||||
#include <fstream>
|
||||
#include <cpp-utils/data/DataFixture.h>
|
||||
|
||||
using cpputils::TempDir;
|
||||
using cpputils::Data;
|
||||
using cryfs::LocalStateMetadata;
|
||||
using cpputils::DataFixture;
|
||||
using std::ofstream;
|
||||
|
||||
class LocalStateMetadataTest : public ::testing::Test {
|
||||
public:
|
||||
TempDir stateDir;
|
||||
TempDir stateDir2;
|
||||
};
|
||||
|
||||
TEST_F(LocalStateMetadataTest, myClientId_ValueIsConsistent) {
|
||||
LocalStateMetadata metadata1 = LocalStateMetadata::loadOrGenerate(stateDir.path(), Data(0));
|
||||
LocalStateMetadata metadata2 = LocalStateMetadata::loadOrGenerate(stateDir.path(), Data(0));
|
||||
EXPECT_EQ(metadata1.myClientId(), metadata2.myClientId());
|
||||
}
|
||||
|
||||
TEST_F(LocalStateMetadataTest, myClientId_ValueIsRandomForNewClient) {
|
||||
LocalStateMetadata metadata1 = LocalStateMetadata::loadOrGenerate(stateDir.path(), Data(0));
|
||||
LocalStateMetadata metadata2 = LocalStateMetadata::loadOrGenerate(stateDir2.path(), Data(0));
|
||||
EXPECT_NE(metadata1.myClientId(), metadata2.myClientId());
|
||||
}
|
||||
|
||||
#ifndef CRYFS_NO_COMPATIBILITY
|
||||
TEST_F(LocalStateMetadataTest, myClientId_TakesLegacyValueIfSpecified) {
|
||||
ofstream file((stateDir.path() / "myClientId").native());
|
||||
file << 12345u;
|
||||
file.close();
|
||||
|
||||
LocalStateMetadata metadata = LocalStateMetadata::loadOrGenerate(stateDir.path(), Data(0));
|
||||
EXPECT_EQ(12345u, metadata.myClientId());
|
||||
}
|
||||
#endif
|
||||
|
||||
TEST_F(LocalStateMetadataTest, encryptionKeyHash_whenLoadingWithSameKey_thenDoesntCrash) {
|
||||
LocalStateMetadata::loadOrGenerate(stateDir.path(), DataFixture::generate(1024));
|
||||
LocalStateMetadata::loadOrGenerate(stateDir.path(), DataFixture::generate(1024));
|
||||
}
|
||||
|
||||
TEST_F(LocalStateMetadataTest, encryptionKeyHash_whenLoadingWithDifferentKey_thenCrashes) {
|
||||
LocalStateMetadata::loadOrGenerate(stateDir.path(), DataFixture::generate(1024, 1));
|
||||
EXPECT_THROW(
|
||||
LocalStateMetadata::loadOrGenerate(stateDir.path(), DataFixture::generate(1024, 2)),
|
||||
std::runtime_error
|
||||
);
|
||||
}
|
@ -1,23 +0,0 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "cryfs/localstate/MyClientId.h"
|
||||
#include <cpp-utils/tempfile/TempDir.h>
|
||||
|
||||
using cpputils::TempDir;
|
||||
using cryfs::MyClientId;
|
||||
|
||||
class MyClientIdTest : public ::testing::Test {
|
||||
public:
|
||||
TempDir stateDir;
|
||||
TempDir stateDir2;
|
||||
};
|
||||
|
||||
TEST_F(MyClientIdTest, ValueIsConsistent) {
|
||||
uint32_t myClientId = MyClientId(stateDir.path()).loadOrGenerate();
|
||||
EXPECT_EQ(myClientId, MyClientId(stateDir.path()).loadOrGenerate());
|
||||
}
|
||||
|
||||
TEST_F(MyClientIdTest, ValueIsRandomForNewClient) {
|
||||
uint32_t myClientId = MyClientId(stateDir.path()).loadOrGenerate();
|
||||
EXPECT_NE(myClientId, MyClientId(stateDir2.path()).loadOrGenerate());
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user