Merge branch 'develop' into feature/win_pre10
This commit is contained in:
commit
fcd239ac65
16
.github/ISSUE_TEMPLATE.md
vendored
Normal file
16
.github/ISSUE_TEMPLATE.md
vendored
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
## Expected Behavior
|
||||||
|
|
||||||
|
|
||||||
|
## Actual Behavior
|
||||||
|
|
||||||
|
|
||||||
|
## Steps to Reproduce the Problem
|
||||||
|
|
||||||
|
1.
|
||||||
|
2.
|
||||||
|
3.
|
||||||
|
|
||||||
|
## Specifications
|
||||||
|
|
||||||
|
- CryFS Version:
|
||||||
|
- Operating System (incl. Version):
|
@ -226,18 +226,19 @@ namespace cryfs {
|
|||||||
auto blockStore = make_unique_ref<OnDiskBlockStore2>(options.baseDir());
|
auto blockStore = make_unique_ref<OnDiskBlockStore2>(options.baseDir());
|
||||||
auto config = _loadOrCreateConfig(options, localStateDir);
|
auto config = _loadOrCreateConfig(options, localStateDir);
|
||||||
unique_ptr<fspp::fuse::Fuse> fuse = nullptr;
|
unique_ptr<fspp::fuse::Fuse> fuse = nullptr;
|
||||||
auto onIntegrityViolation = [&fuse] () {
|
bool stoppedBecauseOfIntegrityViolation = false;
|
||||||
|
|
||||||
|
auto onIntegrityViolation = [&fuse, &stoppedBecauseOfIntegrityViolation] () {
|
||||||
if (fuse.get() != nullptr) {
|
if (fuse.get() != nullptr) {
|
||||||
LOG(ERR, "Integrity violation detected. Unmounting.");
|
LOG(ERR, "Integrity violation detected. Unmounting.");
|
||||||
|
stoppedBecauseOfIntegrityViolation = true;
|
||||||
fuse->stop();
|
fuse->stop();
|
||||||
} else {
|
} else {
|
||||||
// the file system isn't initialized yet, i.e. we failed in the initial steps when
|
// Usually on an integrity violation, the file system is unmounted.
|
||||||
|
// Here, the file system isn't initialized yet, i.e. we failed in the initial steps when
|
||||||
// setting up _device before running initFilesystem.
|
// setting up _device before running initFilesystem.
|
||||||
// We can't unmount a not-mounted file system, but we can make sure it doesn't get mounted.
|
// We can't unmount a not-mounted file system, but we can make sure it doesn't get mounted.
|
||||||
// Error code is "success" because that's also what is returned if this happens while
|
throw CryfsException("Integrity violation detected. Unmounting.", ErrorCode::IntegrityViolation);
|
||||||
// the file system is already mounted - it gets unmounted cleanly.
|
|
||||||
// TODO Should we reconsider this?
|
|
||||||
throw CryfsException("Integrity violation detected. Unmounting.", ErrorCode::Success);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const bool missingBlockIsIntegrityViolation = config.configFile.config()->missingBlockIsIntegrityViolation();
|
const bool missingBlockIsIntegrityViolation = config.configFile.config()->missingBlockIsIntegrityViolation();
|
||||||
@ -268,6 +269,10 @@ namespace cryfs {
|
|||||||
<< std::endl;
|
<< std::endl;
|
||||||
#endif
|
#endif
|
||||||
fuse->run(options.mountDir(), options.fuseOptions());
|
fuse->run(options.mountDir(), options.fuseOptions());
|
||||||
|
|
||||||
|
if (stoppedBecauseOfIntegrityViolation) {
|
||||||
|
throw CryfsException("Integrity violation detected. Unmounting.", ErrorCode::IntegrityViolation);
|
||||||
|
}
|
||||||
} catch (const CryfsException &e) {
|
} catch (const CryfsException &e) {
|
||||||
throw; // CryfsException is only thrown if setup goes wrong. Throw it through so that we get the correct process exit code.
|
throw; // CryfsException is only thrown if setup goes wrong. Throw it through so that we get the correct process exit code.
|
||||||
} catch (const std::exception &e) {
|
} catch (const std::exception &e) {
|
||||||
@ -395,7 +400,7 @@ namespace cryfs {
|
|||||||
_runFilesystem(options, std::move(onMounted));
|
_runFilesystem(options, std::move(onMounted));
|
||||||
} catch (const CryfsException &e) {
|
} catch (const CryfsException &e) {
|
||||||
if (e.what() != string()) {
|
if (e.what() != string()) {
|
||||||
std::cerr << "Error: " << e.what() << std::endl;
|
std::cerr << "Error " << static_cast<int>(e.errorCode()) << ": " << e.what() << std::endl;
|
||||||
}
|
}
|
||||||
return exitCode(e.errorCode());
|
return exitCode(e.errorCode());
|
||||||
} catch (const std::runtime_error &e) {
|
} catch (const std::runtime_error &e) {
|
||||||
|
@ -54,6 +54,9 @@ enum class ErrorCode : int {
|
|||||||
|
|
||||||
// A previous run of the file system detected an integrity violation. Preventing access to make sure the user notices. The file system will be accessible again after the user deletes the integrity state file.
|
// A previous run of the file system detected an integrity violation. Preventing access to make sure the user notices. The file system will be accessible again after the user deletes the integrity state file.
|
||||||
IntegrityViolationOnPreviousRun = 24,
|
IntegrityViolationOnPreviousRun = 24,
|
||||||
|
|
||||||
|
// An integrity violation was detected and the file system unmounted to make sure the user notices.
|
||||||
|
IntegrityViolation = 25
|
||||||
};
|
};
|
||||||
|
|
||||||
inline int exitCode(ErrorCode code) {
|
inline int exitCode(ErrorCode code) {
|
||||||
|
@ -89,7 +89,7 @@ TEST_F(CliTest_IntegrityCheck, givenIncorrectFilesystemId_thenFails) {
|
|||||||
modifyFilesystemId();
|
modifyFilesystemId();
|
||||||
EXPECT_RUN_ERROR(
|
EXPECT_RUN_ERROR(
|
||||||
args,
|
args,
|
||||||
"Error: The filesystem id in the config file is different to the last time we loaded a filesystem from this basedir.",
|
"Error 20: The filesystem id in the config file is different to the last time we loaded a filesystem from this basedir.",
|
||||||
ErrorCode::FilesystemIdChanged
|
ErrorCode::FilesystemIdChanged
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -101,7 +101,7 @@ TEST_F(CliTest_IntegrityCheck, givenIncorrectFilesystemKey_thenFails) {
|
|||||||
modifyFilesystemKey();
|
modifyFilesystemKey();
|
||||||
EXPECT_RUN_ERROR(
|
EXPECT_RUN_ERROR(
|
||||||
args,
|
args,
|
||||||
"Error: The filesystem encryption key differs from the last time we loaded this filesystem. Did an attacker replace the file system?",
|
"Error 21: The filesystem encryption key differs from the last time we loaded this filesystem. Did an attacker replace the file system?",
|
||||||
ErrorCode::EncryptionKeyChanged
|
ErrorCode::EncryptionKeyChanged
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -130,7 +130,7 @@ TEST_F(CliTest_IntegrityCheck, givenFilesystemWithRolledBackBasedir_whenMounting
|
|||||||
recursive_copy(backup.path() / "basedir", basedir);
|
recursive_copy(backup.path() / "basedir", basedir);
|
||||||
|
|
||||||
// error code is success because it unmounts normally
|
// error code is success because it unmounts normally
|
||||||
EXPECT_RUN_ERROR(args, "Integrity violation detected. Unmounting.", ErrorCode::Success, [&] {
|
EXPECT_RUN_ERROR(args, "Integrity violation detected. Unmounting.", ErrorCode::IntegrityViolation, [&] {
|
||||||
EXPECT_FALSE(readingFileIsSuccessful(mountdir / "myfile"));
|
EXPECT_FALSE(readingFileIsSuccessful(mountdir / "myfile"));
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -151,8 +151,7 @@ TEST_F(CliTest_IntegrityCheck, whenRollingBackBasedirWhileMounted_thenUnmounts)
|
|||||||
TempDir backup;
|
TempDir backup;
|
||||||
recursive_copy(basedir, backup.path() / "basedir");
|
recursive_copy(basedir, backup.path() / "basedir");
|
||||||
|
|
||||||
// error code is success because it unmounts normally
|
EXPECT_RUN_ERROR(args, "Integrity violation detected. Unmounting.", ErrorCode::IntegrityViolation, [&] {
|
||||||
EXPECT_RUN_ERROR(args, "Integrity violation detected. Unmounting.", ErrorCode::Success, [&] {
|
|
||||||
// modify the file system contents
|
// modify the file system contents
|
||||||
writeFile(mountdir / "myfile", "hello world 2");
|
writeFile(mountdir / "myfile", "hello world 2");
|
||||||
ASSERT(readingFileIsSuccessful(mountdir / "myfile"), ""); // just to make sure reading usually works
|
ASSERT(readingFileIsSuccessful(mountdir / "myfile"), ""); // just to make sure reading usually works
|
||||||
|
@ -89,7 +89,7 @@ TEST_P(CliTest_WrongEnvironment, NoErrorCondition) {
|
|||||||
|
|
||||||
TEST_P(CliTest_WrongEnvironment, MountDirIsBaseDir) {
|
TEST_P(CliTest_WrongEnvironment, MountDirIsBaseDir) {
|
||||||
mountdir = basedir;
|
mountdir = basedir;
|
||||||
Test_Run_Error("Error: base directory can't be inside the mount directory", ErrorCode::BaseDirInsideMountDir);
|
Test_Run_Error("Error 18: base directory can't be inside the mount directory", ErrorCode::BaseDirInsideMountDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
bf::path make_relative(const bf::path &path) {
|
bf::path make_relative(const bf::path &path) {
|
||||||
@ -104,26 +104,26 @@ bf::path make_relative(const bf::path &path) {
|
|||||||
|
|
||||||
TEST_P(CliTest_WrongEnvironment, MountDirIsBaseDir_MountDirRelative) {
|
TEST_P(CliTest_WrongEnvironment, MountDirIsBaseDir_MountDirRelative) {
|
||||||
mountdir = make_relative(basedir);
|
mountdir = make_relative(basedir);
|
||||||
Test_Run_Error("Error: base directory can't be inside the mount directory", ErrorCode::BaseDirInsideMountDir);
|
Test_Run_Error("Error 18: base directory can't be inside the mount directory", ErrorCode::BaseDirInsideMountDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_P(CliTest_WrongEnvironment, MountDirIsBaseDir_BaseDirRelative) {
|
TEST_P(CliTest_WrongEnvironment, MountDirIsBaseDir_BaseDirRelative) {
|
||||||
mountdir = basedir;
|
mountdir = basedir;
|
||||||
basedir = make_relative(basedir);
|
basedir = make_relative(basedir);
|
||||||
Test_Run_Error("Error: base directory can't be inside the mount directory", ErrorCode::BaseDirInsideMountDir);
|
Test_Run_Error("Error 18: base directory can't be inside the mount directory", ErrorCode::BaseDirInsideMountDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_P(CliTest_WrongEnvironment, MountDirIsBaseDir_BothRelative) {
|
TEST_P(CliTest_WrongEnvironment, MountDirIsBaseDir_BothRelative) {
|
||||||
basedir = make_relative(basedir);
|
basedir = make_relative(basedir);
|
||||||
mountdir = basedir;
|
mountdir = basedir;
|
||||||
Test_Run_Error("Error: base directory can't be inside the mount directory", ErrorCode::BaseDirInsideMountDir);
|
Test_Run_Error("Error 18: base directory can't be inside the mount directory", ErrorCode::BaseDirInsideMountDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_P(CliTest_WrongEnvironment, BaseDir_DoesntExist) {
|
TEST_P(CliTest_WrongEnvironment, BaseDir_DoesntExist) {
|
||||||
_basedir.remove();
|
_basedir.remove();
|
||||||
// ON_CALL and not EXPECT_CALL, because this is a death test (i.e. it is forked) and gmock EXPECT_CALL in fork children don't report to parents.
|
// ON_CALL and not EXPECT_CALL, because this is a death test (i.e. it is forked) and gmock EXPECT_CALL in fork children don't report to parents.
|
||||||
ON_CALL(*console, askYesNo("Could not find base directory. Do you want to create it?", _)).WillByDefault(Return(false));
|
ON_CALL(*console, askYesNo("Could not find base directory. Do you want to create it?", _)).WillByDefault(Return(false));
|
||||||
Test_Run_Error("Error: base directory not found", ErrorCode::InaccessibleBaseDir);
|
Test_Run_Error("Error 16: base directory not found", ErrorCode::InaccessibleBaseDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_P(CliTest_WrongEnvironment, BaseDir_DoesntExist_Noninteractive) {
|
TEST_P(CliTest_WrongEnvironment, BaseDir_DoesntExist_Noninteractive) {
|
||||||
@ -132,7 +132,7 @@ TEST_P(CliTest_WrongEnvironment, BaseDir_DoesntExist_Noninteractive) {
|
|||||||
// So we set a default answer that shouldn't crash and check it's not called by checking that it crashes.
|
// So we set a default answer that shouldn't crash and check it's not called by checking that it crashes.
|
||||||
ON_CALL(*console, askYesNo("Could not find base directory. Do you want to create it?", _)).WillByDefault(Return(true));
|
ON_CALL(*console, askYesNo("Could not find base directory. Do you want to create it?", _)).WillByDefault(Return(true));
|
||||||
cpputils::setenv("CRYFS_FRONTEND", "noninteractive");
|
cpputils::setenv("CRYFS_FRONTEND", "noninteractive");
|
||||||
Test_Run_Error("Error: base directory not found", ErrorCode::InaccessibleBaseDir);
|
Test_Run_Error("Error 16: base directory not found", ErrorCode::InaccessibleBaseDir);
|
||||||
cpputils::unsetenv("CRYFS_FRONTEND");
|
cpputils::unsetenv("CRYFS_FRONTEND");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -147,7 +147,7 @@ TEST_P(CliTest_WrongEnvironment, BaseDir_DoesntExist_Create) {
|
|||||||
TEST_P(CliTest_WrongEnvironment, BaseDir_IsNotDirectory) {
|
TEST_P(CliTest_WrongEnvironment, BaseDir_IsNotDirectory) {
|
||||||
TempFile basedirfile;
|
TempFile basedirfile;
|
||||||
basedir = basedirfile.path();
|
basedir = basedirfile.path();
|
||||||
Test_Run_Error("Error: base directory is not a directory", ErrorCode::InaccessibleBaseDir);
|
Test_Run_Error("Error 16: base directory is not a directory", ErrorCode::InaccessibleBaseDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_P(CliTest_WrongEnvironment, BaseDir_AllPermissions) {
|
TEST_P(CliTest_WrongEnvironment, BaseDir_AllPermissions) {
|
||||||
@ -161,22 +161,22 @@ TEST_P(CliTest_WrongEnvironment, BaseDir_AllPermissions) {
|
|||||||
#if !defined(_MSC_VER)
|
#if !defined(_MSC_VER)
|
||||||
TEST_P(CliTest_WrongEnvironment, BaseDir_NoReadPermission) {
|
TEST_P(CliTest_WrongEnvironment, BaseDir_NoReadPermission) {
|
||||||
SetNoReadPermission(basedir);
|
SetNoReadPermission(basedir);
|
||||||
Test_Run_Error("Error: Could not read from base directory", ErrorCode::InaccessibleBaseDir);
|
Test_Run_Error("Error 16: Could not read from base directory", ErrorCode::InaccessibleBaseDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_P(CliTest_WrongEnvironment, BaseDir_NoExePermission) {
|
TEST_P(CliTest_WrongEnvironment, BaseDir_NoExePermission) {
|
||||||
SetNoExePermission(basedir);
|
SetNoExePermission(basedir);
|
||||||
Test_Run_Error("Error: Could not write to base directory", ErrorCode::InaccessibleBaseDir);
|
Test_Run_Error("Error 16: Could not write to base directory", ErrorCode::InaccessibleBaseDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_P(CliTest_WrongEnvironment, BaseDir_NoWritePermission) {
|
TEST_P(CliTest_WrongEnvironment, BaseDir_NoWritePermission) {
|
||||||
SetNoWritePermission(basedir);
|
SetNoWritePermission(basedir);
|
||||||
Test_Run_Error("Error: Could not write to base directory", ErrorCode::InaccessibleBaseDir);
|
Test_Run_Error("Error 16: Could not write to base directory", ErrorCode::InaccessibleBaseDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_P(CliTest_WrongEnvironment, BaseDir_NoPermission) {
|
TEST_P(CliTest_WrongEnvironment, BaseDir_NoPermission) {
|
||||||
SetNoPermission(basedir);
|
SetNoPermission(basedir);
|
||||||
Test_Run_Error("Error: Could not write to base directory", ErrorCode::InaccessibleBaseDir);
|
Test_Run_Error("Error 16: Could not write to base directory", ErrorCode::InaccessibleBaseDir);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -208,7 +208,7 @@ TEST_P(CliTest_WrongEnvironment, MountDir_DoesntExist_Create) {
|
|||||||
TEST_P(CliTest_WrongEnvironment, MountDir_IsNotDirectory) {
|
TEST_P(CliTest_WrongEnvironment, MountDir_IsNotDirectory) {
|
||||||
TempFile mountdirfile;
|
TempFile mountdirfile;
|
||||||
mountdir = mountdirfile.path();
|
mountdir = mountdirfile.path();
|
||||||
Test_Run_Error("Error: mount directory is not a directory", ErrorCode::InaccessibleMountDir);
|
Test_Run_Error("Error 17: mount directory is not a directory", ErrorCode::InaccessibleMountDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_P(CliTest_WrongEnvironment, MountDir_AllPermissions) {
|
TEST_P(CliTest_WrongEnvironment, MountDir_AllPermissions) {
|
||||||
@ -222,21 +222,21 @@ TEST_P(CliTest_WrongEnvironment, MountDir_AllPermissions) {
|
|||||||
#if !defined(_MSC_VER)
|
#if !defined(_MSC_VER)
|
||||||
TEST_P(CliTest_WrongEnvironment, MountDir_NoReadPermission) {
|
TEST_P(CliTest_WrongEnvironment, MountDir_NoReadPermission) {
|
||||||
SetNoReadPermission(mountdir);
|
SetNoReadPermission(mountdir);
|
||||||
Test_Run_Error("Error: Could not read from mount directory", ErrorCode::InaccessibleMountDir);
|
Test_Run_Error("Error 17: Could not read from mount directory", ErrorCode::InaccessibleMountDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_P(CliTest_WrongEnvironment, MountDir_NoExePermission) {
|
TEST_P(CliTest_WrongEnvironment, MountDir_NoExePermission) {
|
||||||
SetNoExePermission(mountdir);
|
SetNoExePermission(mountdir);
|
||||||
Test_Run_Error("Error: Could not write to mount directory", ErrorCode::InaccessibleMountDir);
|
Test_Run_Error("Error 17: Could not write to mount directory", ErrorCode::InaccessibleMountDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_P(CliTest_WrongEnvironment, MountDir_NoWritePermission) {
|
TEST_P(CliTest_WrongEnvironment, MountDir_NoWritePermission) {
|
||||||
SetNoWritePermission(mountdir);
|
SetNoWritePermission(mountdir);
|
||||||
Test_Run_Error("Error: Could not write to mount directory", ErrorCode::InaccessibleMountDir);
|
Test_Run_Error("Error 17: Could not write to mount directory", ErrorCode::InaccessibleMountDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_P(CliTest_WrongEnvironment, MountDir_NoPermission) {
|
TEST_P(CliTest_WrongEnvironment, MountDir_NoPermission) {
|
||||||
SetNoPermission(mountdir);
|
SetNoPermission(mountdir);
|
||||||
Test_Run_Error("Error: Could not write to mount directory", ErrorCode::InaccessibleMountDir);
|
Test_Run_Error("Error 17: Could not write to mount directory", ErrorCode::InaccessibleMountDir);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
Loading…
Reference in New Issue
Block a user