diff --git a/src/cryfs-cli/Cli.cpp b/src/cryfs-cli/Cli.cpp index 877aa168..7dc4be7f 100644 --- a/src/cryfs-cli/Cli.cpp +++ b/src/cryfs-cli/Cli.cpp @@ -228,7 +228,7 @@ namespace cryfs { try { auto blockStore = make_unique_ref(options.baseDir()); 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); fspp::FilesystemImpl fsimpl(&device); fspp::fuse::Fuse fuse(&fsimpl, "cryfs", "cryfs@"+options.baseDir().native()); diff --git a/src/cryfs/config/CryConfig.cpp b/src/cryfs/config/CryConfig.cpp index 11b74b9d..148c4a80 100644 --- a/src/cryfs/config/CryConfig.cpp +++ b/src/cryfs/config/CryConfig.cpp @@ -149,6 +149,10 @@ void CryConfig::SetExclusiveClientId(optional value) { _exclusiveClientId = value; } +bool CryConfig::missingBlockIsIntegrityViolation() const { + return _exclusiveClientId != boost::none; +} + #ifndef CRYFS_NO_COMPATIBILITY bool CryConfig::HasVersionNumbers() const { return _hasVersionNumbers; diff --git a/src/cryfs/config/CryConfig.h b/src/cryfs/config/CryConfig.h index fbd787bd..39a336b1 100644 --- a/src/cryfs/config/CryConfig.h +++ b/src/cryfs/config/CryConfig.h @@ -44,6 +44,8 @@ public: boost::optional ExclusiveClientId() const; void SetExclusiveClientId(boost::optional value); + bool missingBlockIsIntegrityViolation() const; + #ifndef CRYFS_NO_COMPATIBILITY // 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. diff --git a/src/cryfs/filesystem/CryDevice.cpp b/src/cryfs/filesystem/CryDevice.cpp index 12bcf373..7e372095 100644 --- a/src/cryfs/filesystem/CryDevice.cpp +++ b/src/cryfs/filesystem/CryDevice.cpp @@ -57,14 +57,14 @@ namespace bf = boost::filesystem; namespace cryfs { -CryDevice::CryDevice(CryConfigFile configFile, unique_ref blockStore, uint32_t myClientId, bool noIntegrityChecks) -: _fsBlobStore(CreateFsBlobStore(std::move(blockStore), &configFile, myClientId, noIntegrityChecks)), +CryDevice::CryDevice(CryConfigFile configFile, unique_ref blockStore, uint32_t myClientId, bool noIntegrityChecks, bool missingBlockIsIntegrityViolation) +: _fsBlobStore(CreateFsBlobStore(std::move(blockStore), &configFile, myClientId, noIntegrityChecks, missingBlockIsIntegrityViolation)), _rootKey(GetOrCreateRootKey(&configFile)), _onFsAction() { } -unique_ref CryDevice::CreateFsBlobStore(unique_ref blockStore, CryConfigFile *configFile, uint32_t myClientId, bool noIntegrityChecks) { - auto blobStore = CreateBlobStore(std::move(blockStore), configFile, myClientId, noIntegrityChecks); +unique_ref CryDevice::CreateFsBlobStore(unique_ref blockStore, CryConfigFile *configFile, uint32_t myClientId, bool noIntegrityChecks, bool missingBlockIsIntegrityViolation) { + auto blobStore = CreateBlobStore(std::move(blockStore), configFile, myClientId, noIntegrityChecks, missingBlockIsIntegrityViolation); #ifndef CRYFS_NO_COMPATIBILITY auto fsBlobStore = MigrateOrCreateFsBlobStore(std::move(blobStore), configFile); @@ -89,8 +89,8 @@ unique_ref CryDevice::MigrateOrCreateFsBlobStore(uniqu } #endif -unique_ref CryDevice::CreateBlobStore(unique_ref blockStore, CryConfigFile *configFile, uint32_t myClientId, bool noIntegrityChecks) { - auto integrityEncryptedBlockStore = CreateIntegrityEncryptedBlockStore(std::move(blockStore), configFile, myClientId, noIntegrityChecks); +unique_ref CryDevice::CreateBlobStore(unique_ref blockStore, CryConfigFile *configFile, uint32_t myClientId, bool noIntegrityChecks, bool missingBlockIsIntegrityViolation) { + auto integrityEncryptedBlockStore = CreateIntegrityEncryptedBlockStore(std::move(blockStore), configFile, myClientId, noIntegrityChecks, missingBlockIsIntegrityViolation); // 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. return make_unique_ref( @@ -102,7 +102,7 @@ unique_ref CryDevice::CreateBlobStore(unique_refconfig()->BlocksizeBytes()); } -unique_ref CryDevice::CreateIntegrityEncryptedBlockStore(unique_ref blockStore, CryConfigFile *configFile, uint32_t myClientId, bool noIntegrityChecks) { +unique_ref CryDevice::CreateIntegrityEncryptedBlockStore(unique_ref blockStore, CryConfigFile *configFile, uint32_t myClientId, bool noIntegrityChecks, bool missingBlockIsIntegrityViolation) { auto encryptedBlockStore = CreateEncryptedBlockStore(*configFile->config(), std::move(blockStore)); auto statePath = LocalStateDir::forFilesystemId(configFile->config()->FilesystemId()); auto integrityFilePath = statePath / "integritydata"; @@ -115,8 +115,8 @@ unique_ref CryDevice::CreateIntegrityEncryptedBlockStore(unique_ref configFile->save(); } #endif - - return make_unique_ref(std::move(encryptedBlockStore), integrityFilePath, myClientId, noIntegrityChecks, false); + + return make_unique_ref(std::move(encryptedBlockStore), integrityFilePath, myClientId, noIntegrityChecks, missingBlockIsIntegrityViolation); } Key CryDevice::CreateRootBlobAndReturnKey() { diff --git a/src/cryfs/filesystem/CryDevice.h b/src/cryfs/filesystem/CryDevice.h index f11d4069..98caecd3 100644 --- a/src/cryfs/filesystem/CryDevice.h +++ b/src/cryfs/filesystem/CryDevice.h @@ -18,7 +18,7 @@ namespace cryfs { class CryDevice final: public fspp::Device { public: - CryDevice(CryConfigFile config, cpputils::unique_ref blockStore, uint32_t myClientId, bool noIntegrityChecks); + CryDevice(CryConfigFile config, cpputils::unique_ref blockStore, uint32_t myClientId, bool noIntegrityChecks, bool missingBlockIsIntegrityViolation); void statfs(const boost::filesystem::path &path, struct ::statvfs *fsstat) override; @@ -53,12 +53,12 @@ private: blockstore::Key GetOrCreateRootKey(CryConfigFile *config); blockstore::Key CreateRootBlobAndReturnKey(); - static cpputils::unique_ref CreateFsBlobStore(cpputils::unique_ref blockStore, CryConfigFile *configFile, uint32_t myClientId, bool noIntegrityChecks); + static cpputils::unique_ref CreateFsBlobStore(cpputils::unique_ref blockStore, CryConfigFile *configFile, uint32_t myClientId, bool noIntegrityChecks, bool missingBlockIsIntegrityViolation); #ifndef CRYFS_NO_COMPATIBILITY static cpputils::unique_ref MigrateOrCreateFsBlobStore(cpputils::unique_ref blobStore, CryConfigFile *configFile); #endif - static cpputils::unique_ref CreateBlobStore(cpputils::unique_ref blockStore, CryConfigFile *configFile, uint32_t myClientId, bool noIntegrityChecks); - static cpputils::unique_ref CreateIntegrityEncryptedBlockStore(cpputils::unique_ref blockStore, CryConfigFile *configFile, uint32_t myClientId, bool noIntegrityChecks); + static cpputils::unique_ref CreateBlobStore(cpputils::unique_ref blockStore, CryConfigFile *configFile, uint32_t myClientId, bool noIntegrityChecks, bool missingBlockIsIntegrityViolation); + static cpputils::unique_ref CreateIntegrityEncryptedBlockStore(cpputils::unique_ref blockStore, CryConfigFile *configFile, uint32_t myClientId, bool noIntegrityChecks, bool missingBlockIsIntegrityViolation); static cpputils::unique_ref CreateEncryptedBlockStore(const CryConfig &config, cpputils::unique_ref baseBlockStore); struct BlobWithParent { diff --git a/test/blockstore/implementations/integrity/IntegrityBlockStoreTest_Generic.cpp b/test/blockstore/implementations/integrity/IntegrityBlockStoreTest_Generic.cpp index 065cb528..f88973b1 100644 --- a/test/blockstore/implementations/integrity/IntegrityBlockStoreTest_Generic.cpp +++ b/test/blockstore/implementations/integrity/IntegrityBlockStoreTest_Generic.cpp @@ -21,7 +21,7 @@ using cpputils::make_unique_ref; using cpputils::unique_ref; using cpputils::TempFile; -template +template class IntegrityBlockStoreTestFixture: public BlockStoreTestFixture { public: IntegrityBlockStoreTestFixture() :stateFile(false) {} @@ -29,26 +29,41 @@ public: TempFile stateFile; unique_ref createBlockStore() override { return make_unique_ref( - make_unique_ref(make_unique_ref(), stateFile.path(), 0x12345678, MissingBlockIsIntegrityViolation) + make_unique_ref(make_unique_ref(), stateFile.path(), 0x12345678, NoIntegrityChecks, MissingBlockIsIntegrityViolation) ); } }; +using IntegrityBlockStoreTestFixture_multiclient = IntegrityBlockStoreTestFixture; +using IntegrityBlockStoreTestFixture_singleclient = IntegrityBlockStoreTestFixture; +using IntegrityBlockStoreTestFixture_multiclient_noIntegrityChecks = IntegrityBlockStoreTestFixture; +using IntegrityBlockStoreTestFixture_singleclient_noIntegrityChecks = IntegrityBlockStoreTestFixture; + + // TODO Why is here no IntegrityBlockStoreWithRandomKeysTest? -INSTANTIATE_TYPED_TEST_CASE_P(Integrity_multiclient, BlockStoreTest, IntegrityBlockStoreTestFixture); -INSTANTIATE_TYPED_TEST_CASE_P(Integrity_singleclient, BlockStoreTest, IntegrityBlockStoreTestFixture); +INSTANTIATE_TYPED_TEST_CASE_P(Integrity_multiclient, BlockStoreTest, IntegrityBlockStoreTestFixture_multiclient); +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 +template class IntegrityBlockStore2TestFixture: public BlockStore2TestFixture { public: IntegrityBlockStore2TestFixture() :stateFile(false) {} TempFile stateFile; unique_ref createBlockStore() override { - return make_unique_ref(make_unique_ref(), stateFile.path(), 0x12345678, MissingBlockIsIntegrityViolation); + return make_unique_ref(make_unique_ref(), stateFile.path(), 0x12345678, NoIntegrityChecks, MissingBlockIsIntegrityViolation); } }; -INSTANTIATE_TYPED_TEST_CASE_P(Integrity_multiclient, BlockStore2Test, IntegrityBlockStore2TestFixture); -INSTANTIATE_TYPED_TEST_CASE_P(Integrity_singleclient, BlockStore2Test, IntegrityBlockStore2TestFixture); +using IntegrityBlockStore2TestFixture_multiclient = IntegrityBlockStore2TestFixture; +using IntegrityBlockStore2TestFixture_singleclient = IntegrityBlockStore2TestFixture; +using IntegrityBlockStore2TestFixture_multiclient_noIntegrityChecks = IntegrityBlockStore2TestFixture; +using IntegrityBlockStore2TestFixture_singleclient_noIntegrityChecks = IntegrityBlockStore2TestFixture; + +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); diff --git a/test/blockstore/implementations/integrity/IntegrityBlockStoreTest_Specific.cpp b/test/blockstore/implementations/integrity/IntegrityBlockStoreTest_Specific.cpp index 3d0c6c57..ee44753b 100644 --- a/test/blockstore/implementations/integrity/IntegrityBlockStoreTest_Specific.cpp +++ b/test/blockstore/implementations/integrity/IntegrityBlockStoreTest_Specific.cpp @@ -27,7 +27,7 @@ public: IntegrityBlockStoreTest(): stateFile(false), baseBlockStore(new InMemoryBlockStore2), - blockStore(make_unique_ref(std::move(cpputils::nullcheck(std::unique_ptr(baseBlockStore)).value()), stateFile.path(), myClientId, false)), + blockStore(make_unique_ref(std::move(cpputils::nullcheck(std::unique_ptr(baseBlockStore)).value()), stateFile.path(), myClientId, false, false)), data(DataFixture::generate(BLOCKSIZE)) { } static constexpr uint32_t myClientId = 0x12345678; @@ -38,13 +38,13 @@ public: std::pair> makeBlockStoreWithDeletionPrevention() { InMemoryBlockStore2 *baseBlockStore = new InMemoryBlockStore2; - auto blockStore = make_unique(std::move(cpputils::nullcheck(std::unique_ptr(baseBlockStore)).value()), stateFile.path(), myClientId, true); + auto blockStore = make_unique(std::move(cpputils::nullcheck(std::unique_ptr(baseBlockStore)).value()), stateFile.path(), myClientId, false, true); return std::make_pair(baseBlockStore, std::move(blockStore)); } std::pair> makeBlockStoreWithoutDeletionPrevention() { InMemoryBlockStore2 *baseBlockStore = new InMemoryBlockStore2; - auto blockStore = make_unique(std::move(cpputils::nullcheck(std::unique_ptr(baseBlockStore)).value()), stateFile.path(), myClientId, false); + auto blockStore = make_unique(std::move(cpputils::nullcheck(std::unique_ptr(baseBlockStore)).value()), stateFile.path(), myClientId, false, false); return std::make_pair(baseBlockStore, std::move(blockStore)); } diff --git a/test/cryfs/filesystem/CryFsTest.cpp b/test/cryfs/filesystem/CryFsTest.cpp index b1ca16a1..29dec8cb 100644 --- a/test/cryfs/filesystem/CryFsTest.cpp +++ b/test/cryfs/filesystem/CryFsTest.cpp @@ -56,20 +56,20 @@ public: 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("/")); rootDir.value()->children(); } TEST_F(CryFsTest, LoadingFilesystemDoesntModifyConfigFile) { { - CryDevice dev(loadOrCreateConfig(), blockStore(), 0x12345678); + CryDevice dev(loadOrCreateConfig(), blockStore(), 0x12345678, false, false); } 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(); EXPECT_EQ(configAfterCreating, configAfterLoading); diff --git a/test/cryfs/filesystem/FileSystemTest.cpp b/test/cryfs/filesystem/FileSystemTest.cpp index a718f349..dfd4f1fb 100644 --- a/test/cryfs/filesystem/FileSystemTest.cpp +++ b/test/cryfs/filesystem/FileSystemTest.cpp @@ -32,7 +32,7 @@ public: auto askPassword = [] {return "mypassword";}; auto config = CryConfigLoader(make_shared(mockConsole()), Random::PseudoRandom(), SCrypt::TestSettings, askPassword, askPassword, none, none, none) .loadOrCreate(configFile.path()).value(); - return make_unique_ref(std::move(config.configFile), std::move(blockStore), config.myClientId); + return make_unique_ref(std::move(config.configFile), std::move(blockStore), config.myClientId, false, false); } cpputils::TempFile configFile; diff --git a/test/cryfs/filesystem/testutils/CryTestBase.h b/test/cryfs/filesystem/testutils/CryTestBase.h index 50f0daa8..f00a018b 100644 --- a/test/cryfs/filesystem/testutils/CryTestBase.h +++ b/test/cryfs/filesystem/testutils/CryTestBase.h @@ -11,7 +11,7 @@ class CryTestBase : public TestWithFakeHomeDirectory { public: CryTestBase(): _configFile(false), _device(nullptr) { auto fakeBlockStore = cpputils::make_unique_ref(); - _device = std::make_unique(configFile(), std::move(fakeBlockStore), 0x12345678); + _device = std::make_unique(configFile(), std::move(fakeBlockStore), 0x12345678, false, false); } cryfs::CryConfigFile configFile() {