Wire through the missingBlockIsIntegrityViolation setting

This commit is contained in:
Sebastian Messmer 2017-09-16 16:49:33 +01:00
parent b6ce7c3ae4
commit 5299be5dda
10 changed files with 52 additions and 31 deletions

View File

@ -228,7 +228,7 @@ namespace cryfs {
try { try {
auto blockStore = make_unique_ref<OnDiskBlockStore2>(options.baseDir()); auto blockStore = make_unique_ref<OnDiskBlockStore2>(options.baseDir());
auto config = _loadOrCreateConfig(options); auto config = _loadOrCreateConfig(options);
CryDevice device(std::move(config.configFile), std::move(blockStore), config.myClientId, options.noIntegrityChecks()); CryDevice device(std::move(config.configFile), std::move(blockStore), config.myClientId, options.noIntegrityChecks(), config.configFile.config()->missingBlockIsIntegrityViolation());
_sanityCheckFilesystem(&device); _sanityCheckFilesystem(&device);
fspp::FilesystemImpl fsimpl(&device); fspp::FilesystemImpl fsimpl(&device);
fspp::fuse::Fuse fuse(&fsimpl, "cryfs", "cryfs@"+options.baseDir().native()); fspp::fuse::Fuse fuse(&fsimpl, "cryfs", "cryfs@"+options.baseDir().native());

View File

@ -149,6 +149,10 @@ void CryConfig::SetExclusiveClientId(optional<uint32_t> value) {
_exclusiveClientId = value; _exclusiveClientId = value;
} }
bool CryConfig::missingBlockIsIntegrityViolation() const {
return _exclusiveClientId != boost::none;
}
#ifndef CRYFS_NO_COMPATIBILITY #ifndef CRYFS_NO_COMPATIBILITY
bool CryConfig::HasVersionNumbers() const { bool CryConfig::HasVersionNumbers() const {
return _hasVersionNumbers; return _hasVersionNumbers;

View File

@ -44,6 +44,8 @@ public:
boost::optional<uint32_t> ExclusiveClientId() const; boost::optional<uint32_t> ExclusiveClientId() const;
void SetExclusiveClientId(boost::optional<uint32_t> value); void SetExclusiveClientId(boost::optional<uint32_t> value);
bool missingBlockIsIntegrityViolation() const;
#ifndef CRYFS_NO_COMPATIBILITY #ifndef CRYFS_NO_COMPATIBILITY
// This is a trigger to recognize old file systems that didn't have version numbers. // This is a trigger to recognize old file systems that didn't have version numbers.
// Version numbers cannot be disabled, but the file system will be migrated to version numbers automatically. // Version numbers cannot be disabled, but the file system will be migrated to version numbers automatically.

View File

@ -57,14 +57,14 @@ namespace bf = boost::filesystem;
namespace cryfs { namespace cryfs {
CryDevice::CryDevice(CryConfigFile configFile, unique_ref<BlockStore2> blockStore, uint32_t myClientId, bool noIntegrityChecks) CryDevice::CryDevice(CryConfigFile configFile, unique_ref<BlockStore2> blockStore, uint32_t myClientId, bool noIntegrityChecks, bool missingBlockIsIntegrityViolation)
: _fsBlobStore(CreateFsBlobStore(std::move(blockStore), &configFile, myClientId, noIntegrityChecks)), : _fsBlobStore(CreateFsBlobStore(std::move(blockStore), &configFile, myClientId, noIntegrityChecks, missingBlockIsIntegrityViolation)),
_rootKey(GetOrCreateRootKey(&configFile)), _rootKey(GetOrCreateRootKey(&configFile)),
_onFsAction() { _onFsAction() {
} }
unique_ref<parallelaccessfsblobstore::ParallelAccessFsBlobStore> CryDevice::CreateFsBlobStore(unique_ref<BlockStore2> blockStore, CryConfigFile *configFile, uint32_t myClientId, bool noIntegrityChecks) { unique_ref<parallelaccessfsblobstore::ParallelAccessFsBlobStore> CryDevice::CreateFsBlobStore(unique_ref<BlockStore2> blockStore, CryConfigFile *configFile, uint32_t myClientId, bool noIntegrityChecks, bool missingBlockIsIntegrityViolation) {
auto blobStore = CreateBlobStore(std::move(blockStore), configFile, myClientId, noIntegrityChecks); auto blobStore = CreateBlobStore(std::move(blockStore), configFile, myClientId, noIntegrityChecks, missingBlockIsIntegrityViolation);
#ifndef CRYFS_NO_COMPATIBILITY #ifndef CRYFS_NO_COMPATIBILITY
auto fsBlobStore = MigrateOrCreateFsBlobStore(std::move(blobStore), configFile); auto fsBlobStore = MigrateOrCreateFsBlobStore(std::move(blobStore), configFile);
@ -89,8 +89,8 @@ unique_ref<fsblobstore::FsBlobStore> CryDevice::MigrateOrCreateFsBlobStore(uniqu
} }
#endif #endif
unique_ref<blobstore::BlobStore> CryDevice::CreateBlobStore(unique_ref<BlockStore2> blockStore, CryConfigFile *configFile, uint32_t myClientId, bool noIntegrityChecks) { unique_ref<blobstore::BlobStore> CryDevice::CreateBlobStore(unique_ref<BlockStore2> blockStore, CryConfigFile *configFile, uint32_t myClientId, bool noIntegrityChecks, bool missingBlockIsIntegrityViolation) {
auto integrityEncryptedBlockStore = CreateIntegrityEncryptedBlockStore(std::move(blockStore), configFile, myClientId, noIntegrityChecks); auto integrityEncryptedBlockStore = CreateIntegrityEncryptedBlockStore(std::move(blockStore), configFile, myClientId, noIntegrityChecks, missingBlockIsIntegrityViolation);
// Create integrityEncryptedBlockStore not in the same line as BlobStoreOnBlocks, because it can modify BlocksizeBytes // Create integrityEncryptedBlockStore not in the same line as BlobStoreOnBlocks, because it can modify BlocksizeBytes
// in the configFile and therefore has to be run before the second parameter to the BlobStoreOnBlocks parameter is evaluated. // in the configFile and therefore has to be run before the second parameter to the BlobStoreOnBlocks parameter is evaluated.
return make_unique_ref<BlobStoreOnBlocks>( return make_unique_ref<BlobStoreOnBlocks>(
@ -102,7 +102,7 @@ unique_ref<blobstore::BlobStore> CryDevice::CreateBlobStore(unique_ref<BlockStor
configFile->config()->BlocksizeBytes()); configFile->config()->BlocksizeBytes());
} }
unique_ref<BlockStore2> CryDevice::CreateIntegrityEncryptedBlockStore(unique_ref<BlockStore2> blockStore, CryConfigFile *configFile, uint32_t myClientId, bool noIntegrityChecks) { unique_ref<BlockStore2> CryDevice::CreateIntegrityEncryptedBlockStore(unique_ref<BlockStore2> blockStore, CryConfigFile *configFile, uint32_t myClientId, bool noIntegrityChecks, bool missingBlockIsIntegrityViolation) {
auto encryptedBlockStore = CreateEncryptedBlockStore(*configFile->config(), std::move(blockStore)); auto encryptedBlockStore = CreateEncryptedBlockStore(*configFile->config(), std::move(blockStore));
auto statePath = LocalStateDir::forFilesystemId(configFile->config()->FilesystemId()); auto statePath = LocalStateDir::forFilesystemId(configFile->config()->FilesystemId());
auto integrityFilePath = statePath / "integritydata"; auto integrityFilePath = statePath / "integritydata";
@ -116,7 +116,7 @@ unique_ref<BlockStore2> CryDevice::CreateIntegrityEncryptedBlockStore(unique_ref
} }
#endif #endif
return make_unique_ref<IntegrityBlockStore2>(std::move(encryptedBlockStore), integrityFilePath, myClientId, noIntegrityChecks, false); return make_unique_ref<IntegrityBlockStore2>(std::move(encryptedBlockStore), integrityFilePath, myClientId, noIntegrityChecks, missingBlockIsIntegrityViolation);
} }
Key CryDevice::CreateRootBlobAndReturnKey() { Key CryDevice::CreateRootBlobAndReturnKey() {

View File

@ -18,7 +18,7 @@ namespace cryfs {
class CryDevice final: public fspp::Device { class CryDevice final: public fspp::Device {
public: public:
CryDevice(CryConfigFile config, cpputils::unique_ref<blockstore::BlockStore2> blockStore, uint32_t myClientId, bool noIntegrityChecks); CryDevice(CryConfigFile config, cpputils::unique_ref<blockstore::BlockStore2> blockStore, uint32_t myClientId, bool noIntegrityChecks, bool missingBlockIsIntegrityViolation);
void statfs(const boost::filesystem::path &path, struct ::statvfs *fsstat) override; void statfs(const boost::filesystem::path &path, struct ::statvfs *fsstat) override;
@ -53,12 +53,12 @@ private:
blockstore::Key GetOrCreateRootKey(CryConfigFile *config); blockstore::Key GetOrCreateRootKey(CryConfigFile *config);
blockstore::Key CreateRootBlobAndReturnKey(); blockstore::Key CreateRootBlobAndReturnKey();
static cpputils::unique_ref<parallelaccessfsblobstore::ParallelAccessFsBlobStore> CreateFsBlobStore(cpputils::unique_ref<blockstore::BlockStore2> blockStore, CryConfigFile *configFile, uint32_t myClientId, bool noIntegrityChecks); static cpputils::unique_ref<parallelaccessfsblobstore::ParallelAccessFsBlobStore> CreateFsBlobStore(cpputils::unique_ref<blockstore::BlockStore2> blockStore, CryConfigFile *configFile, uint32_t myClientId, bool noIntegrityChecks, bool missingBlockIsIntegrityViolation);
#ifndef CRYFS_NO_COMPATIBILITY #ifndef CRYFS_NO_COMPATIBILITY
static cpputils::unique_ref<fsblobstore::FsBlobStore> MigrateOrCreateFsBlobStore(cpputils::unique_ref<blobstore::BlobStore> blobStore, CryConfigFile *configFile); static cpputils::unique_ref<fsblobstore::FsBlobStore> MigrateOrCreateFsBlobStore(cpputils::unique_ref<blobstore::BlobStore> blobStore, CryConfigFile *configFile);
#endif #endif
static cpputils::unique_ref<blobstore::BlobStore> CreateBlobStore(cpputils::unique_ref<blockstore::BlockStore2> blockStore, CryConfigFile *configFile, uint32_t myClientId, bool noIntegrityChecks); static cpputils::unique_ref<blobstore::BlobStore> CreateBlobStore(cpputils::unique_ref<blockstore::BlockStore2> blockStore, CryConfigFile *configFile, uint32_t myClientId, bool noIntegrityChecks, bool missingBlockIsIntegrityViolation);
static cpputils::unique_ref<blockstore::BlockStore2> CreateIntegrityEncryptedBlockStore(cpputils::unique_ref<blockstore::BlockStore2> blockStore, CryConfigFile *configFile, uint32_t myClientId, bool noIntegrityChecks); static cpputils::unique_ref<blockstore::BlockStore2> CreateIntegrityEncryptedBlockStore(cpputils::unique_ref<blockstore::BlockStore2> blockStore, CryConfigFile *configFile, uint32_t myClientId, bool noIntegrityChecks, bool missingBlockIsIntegrityViolation);
static cpputils::unique_ref<blockstore::BlockStore2> CreateEncryptedBlockStore(const CryConfig &config, cpputils::unique_ref<blockstore::BlockStore2> baseBlockStore); static cpputils::unique_ref<blockstore::BlockStore2> CreateEncryptedBlockStore(const CryConfig &config, cpputils::unique_ref<blockstore::BlockStore2> baseBlockStore);
struct BlobWithParent { struct BlobWithParent {

View File

@ -21,7 +21,7 @@ using cpputils::make_unique_ref;
using cpputils::unique_ref; using cpputils::unique_ref;
using cpputils::TempFile; using cpputils::TempFile;
template<bool MissingBlockIsIntegrityViolation> template<bool NoIntegrityChecks, bool MissingBlockIsIntegrityViolation>
class IntegrityBlockStoreTestFixture: public BlockStoreTestFixture { class IntegrityBlockStoreTestFixture: public BlockStoreTestFixture {
public: public:
IntegrityBlockStoreTestFixture() :stateFile(false) {} IntegrityBlockStoreTestFixture() :stateFile(false) {}
@ -29,26 +29,41 @@ public:
TempFile stateFile; TempFile stateFile;
unique_ref<BlockStore> createBlockStore() override { unique_ref<BlockStore> createBlockStore() override {
return make_unique_ref<LowToHighLevelBlockStore>( return make_unique_ref<LowToHighLevelBlockStore>(
make_unique_ref<IntegrityBlockStore2>(make_unique_ref<InMemoryBlockStore2>(), stateFile.path(), 0x12345678, MissingBlockIsIntegrityViolation) make_unique_ref<IntegrityBlockStore2>(make_unique_ref<InMemoryBlockStore2>(), stateFile.path(), 0x12345678, NoIntegrityChecks, MissingBlockIsIntegrityViolation)
); );
} }
}; };
using IntegrityBlockStoreTestFixture_multiclient = IntegrityBlockStoreTestFixture<false, false>;
using IntegrityBlockStoreTestFixture_singleclient = IntegrityBlockStoreTestFixture<false, true>;
using IntegrityBlockStoreTestFixture_multiclient_noIntegrityChecks = IntegrityBlockStoreTestFixture<true, false>;
using IntegrityBlockStoreTestFixture_singleclient_noIntegrityChecks = IntegrityBlockStoreTestFixture<true, true>;
// TODO Why is here no IntegrityBlockStoreWithRandomKeysTest? // TODO Why is here no IntegrityBlockStoreWithRandomKeysTest?
INSTANTIATE_TYPED_TEST_CASE_P(Integrity_multiclient, BlockStoreTest, IntegrityBlockStoreTestFixture<false>); INSTANTIATE_TYPED_TEST_CASE_P(Integrity_multiclient, BlockStoreTest, IntegrityBlockStoreTestFixture_multiclient);
INSTANTIATE_TYPED_TEST_CASE_P(Integrity_singleclient, BlockStoreTest, IntegrityBlockStoreTestFixture<true>); INSTANTIATE_TYPED_TEST_CASE_P(Integrity_singleclient, BlockStoreTest, IntegrityBlockStoreTestFixture_singleclient);
INSTANTIATE_TYPED_TEST_CASE_P(Integrity_multiclient_noIntegrityChecks, BlockStoreTest, IntegrityBlockStoreTestFixture_multiclient_noIntegrityChecks);
INSTANTIATE_TYPED_TEST_CASE_P(Integrity_singleclient_noIntegrityChecks, BlockStoreTest, IntegrityBlockStoreTestFixture_singleclient_noIntegrityChecks);
template<bool MissingBlockIsIntegrityViolation> template<bool NoIntegrityChecks, bool MissingBlockIsIntegrityViolation>
class IntegrityBlockStore2TestFixture: public BlockStore2TestFixture { class IntegrityBlockStore2TestFixture: public BlockStore2TestFixture {
public: public:
IntegrityBlockStore2TestFixture() :stateFile(false) {} IntegrityBlockStore2TestFixture() :stateFile(false) {}
TempFile stateFile; TempFile stateFile;
unique_ref<BlockStore2> createBlockStore() override { unique_ref<BlockStore2> createBlockStore() override {
return make_unique_ref<IntegrityBlockStore2>(make_unique_ref<InMemoryBlockStore2>(), stateFile.path(), 0x12345678, MissingBlockIsIntegrityViolation); return make_unique_ref<IntegrityBlockStore2>(make_unique_ref<InMemoryBlockStore2>(), stateFile.path(), 0x12345678, NoIntegrityChecks, MissingBlockIsIntegrityViolation);
} }
}; };
INSTANTIATE_TYPED_TEST_CASE_P(Integrity_multiclient, BlockStore2Test, IntegrityBlockStore2TestFixture<false>); using IntegrityBlockStore2TestFixture_multiclient = IntegrityBlockStore2TestFixture<false, false>;
INSTANTIATE_TYPED_TEST_CASE_P(Integrity_singleclient, BlockStore2Test, IntegrityBlockStore2TestFixture<true>); using IntegrityBlockStore2TestFixture_singleclient = IntegrityBlockStore2TestFixture<false, true>;
using IntegrityBlockStore2TestFixture_multiclient_noIntegrityChecks = IntegrityBlockStore2TestFixture<true, false>;
using IntegrityBlockStore2TestFixture_singleclient_noIntegrityChecks = IntegrityBlockStore2TestFixture<true, true>;
INSTANTIATE_TYPED_TEST_CASE_P(Integrity_multiclient, BlockStore2Test, IntegrityBlockStore2TestFixture_multiclient);
INSTANTIATE_TYPED_TEST_CASE_P(Integrity_singleclient, BlockStore2Test, IntegrityBlockStore2TestFixture_singleclient);
INSTANTIATE_TYPED_TEST_CASE_P(Integrity_multiclient_noIntegrityChecks, BlockStore2Test, IntegrityBlockStore2TestFixture_multiclient_noIntegrityChecks);
INSTANTIATE_TYPED_TEST_CASE_P(Integrity_singleclient_noIntegrityChecks, BlockStore2Test, IntegrityBlockStore2TestFixture_singleclient_noIntegrityChecks);

View File

@ -27,7 +27,7 @@ public:
IntegrityBlockStoreTest(): IntegrityBlockStoreTest():
stateFile(false), stateFile(false),
baseBlockStore(new InMemoryBlockStore2), baseBlockStore(new InMemoryBlockStore2),
blockStore(make_unique_ref<IntegrityBlockStore2>(std::move(cpputils::nullcheck(std::unique_ptr<InMemoryBlockStore2>(baseBlockStore)).value()), stateFile.path(), myClientId, false)), blockStore(make_unique_ref<IntegrityBlockStore2>(std::move(cpputils::nullcheck(std::unique_ptr<InMemoryBlockStore2>(baseBlockStore)).value()), stateFile.path(), myClientId, false, false)),
data(DataFixture::generate(BLOCKSIZE)) { data(DataFixture::generate(BLOCKSIZE)) {
} }
static constexpr uint32_t myClientId = 0x12345678; static constexpr uint32_t myClientId = 0x12345678;
@ -38,13 +38,13 @@ public:
std::pair<InMemoryBlockStore2 *, unique_ptr<IntegrityBlockStore2>> makeBlockStoreWithDeletionPrevention() { std::pair<InMemoryBlockStore2 *, unique_ptr<IntegrityBlockStore2>> makeBlockStoreWithDeletionPrevention() {
InMemoryBlockStore2 *baseBlockStore = new InMemoryBlockStore2; InMemoryBlockStore2 *baseBlockStore = new InMemoryBlockStore2;
auto blockStore = make_unique<IntegrityBlockStore2>(std::move(cpputils::nullcheck(std::unique_ptr<InMemoryBlockStore2>(baseBlockStore)).value()), stateFile.path(), myClientId, true); auto blockStore = make_unique<IntegrityBlockStore2>(std::move(cpputils::nullcheck(std::unique_ptr<InMemoryBlockStore2>(baseBlockStore)).value()), stateFile.path(), myClientId, false, true);
return std::make_pair(baseBlockStore, std::move(blockStore)); return std::make_pair(baseBlockStore, std::move(blockStore));
} }
std::pair<InMemoryBlockStore2 *, unique_ptr<IntegrityBlockStore2>> makeBlockStoreWithoutDeletionPrevention() { std::pair<InMemoryBlockStore2 *, unique_ptr<IntegrityBlockStore2>> makeBlockStoreWithoutDeletionPrevention() {
InMemoryBlockStore2 *baseBlockStore = new InMemoryBlockStore2; InMemoryBlockStore2 *baseBlockStore = new InMemoryBlockStore2;
auto blockStore = make_unique<IntegrityBlockStore2>(std::move(cpputils::nullcheck(std::unique_ptr<InMemoryBlockStore2>(baseBlockStore)).value()), stateFile.path(), myClientId, false); auto blockStore = make_unique<IntegrityBlockStore2>(std::move(cpputils::nullcheck(std::unique_ptr<InMemoryBlockStore2>(baseBlockStore)).value()), stateFile.path(), myClientId, false, false);
return std::make_pair(baseBlockStore, std::move(blockStore)); return std::make_pair(baseBlockStore, std::move(blockStore));
} }

View File

@ -56,20 +56,20 @@ public:
TEST_F(CryFsTest, CreatedRootdirIsLoadableAfterClosing) { TEST_F(CryFsTest, CreatedRootdirIsLoadableAfterClosing) {
{ {
CryDevice dev(loadOrCreateConfig(), blockStore(), 0x12345678); CryDevice dev(loadOrCreateConfig(), blockStore(), 0x12345678, false, false);
} }
CryDevice dev(loadOrCreateConfig(), blockStore(), 0x12345678); CryDevice dev(loadOrCreateConfig(), blockStore(), 0x12345678, false, false);
auto rootDir = dev.LoadDir(bf::path("/")); auto rootDir = dev.LoadDir(bf::path("/"));
rootDir.value()->children(); rootDir.value()->children();
} }
TEST_F(CryFsTest, LoadingFilesystemDoesntModifyConfigFile) { TEST_F(CryFsTest, LoadingFilesystemDoesntModifyConfigFile) {
{ {
CryDevice dev(loadOrCreateConfig(), blockStore(), 0x12345678); CryDevice dev(loadOrCreateConfig(), blockStore(), 0x12345678, false, false);
} }
Data configAfterCreating = Data::LoadFromFile(config.path()).value(); Data configAfterCreating = Data::LoadFromFile(config.path()).value();
{ {
CryDevice dev(loadOrCreateConfig(), blockStore(), 0x12345678); CryDevice dev(loadOrCreateConfig(), blockStore(), 0x12345678, false, false);
} }
Data configAfterLoading = Data::LoadFromFile(config.path()).value(); Data configAfterLoading = Data::LoadFromFile(config.path()).value();
EXPECT_EQ(configAfterCreating, configAfterLoading); EXPECT_EQ(configAfterCreating, configAfterLoading);

View File

@ -32,7 +32,7 @@ public:
auto askPassword = [] {return "mypassword";}; auto askPassword = [] {return "mypassword";};
auto config = CryConfigLoader(make_shared<NoninteractiveConsole>(mockConsole()), Random::PseudoRandom(), SCrypt::TestSettings, askPassword, askPassword, none, none, none) auto config = CryConfigLoader(make_shared<NoninteractiveConsole>(mockConsole()), Random::PseudoRandom(), SCrypt::TestSettings, askPassword, askPassword, none, none, none)
.loadOrCreate(configFile.path()).value(); .loadOrCreate(configFile.path()).value();
return make_unique_ref<CryDevice>(std::move(config.configFile), std::move(blockStore), config.myClientId); return make_unique_ref<CryDevice>(std::move(config.configFile), std::move(blockStore), config.myClientId, false, false);
} }
cpputils::TempFile configFile; cpputils::TempFile configFile;

View File

@ -11,7 +11,7 @@ class CryTestBase : public TestWithFakeHomeDirectory {
public: public:
CryTestBase(): _configFile(false), _device(nullptr) { CryTestBase(): _configFile(false), _device(nullptr) {
auto fakeBlockStore = cpputils::make_unique_ref<blockstore::inmemory::InMemoryBlockStore2>(); auto fakeBlockStore = cpputils::make_unique_ref<blockstore::inmemory::InMemoryBlockStore2>();
_device = std::make_unique<cryfs::CryDevice>(configFile(), std::move(fakeBlockStore), 0x12345678); _device = std::make_unique<cryfs::CryDevice>(configFile(), std::move(fakeBlockStore), 0x12345678, false, false);
} }
cryfs::CryConfigFile configFile() { cryfs::CryConfigFile configFile() {