Merge branch 'develop' into feature/win_pre10

This commit is contained in:
Sebastian Messmer 2018-12-18 21:41:02 -08:00
commit fcd239ac65
5 changed files with 51 additions and 28 deletions

16
.github/ISSUE_TEMPLATE.md vendored Normal file
View File

@ -0,0 +1,16 @@
## Expected Behavior
## Actual Behavior
## Steps to Reproduce the Problem
1.
2.
3.
## Specifications
- CryFS Version:
- Operating System (incl. Version):

View File

@ -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) {

View File

@ -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) {

View File

@ -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

View File

@ -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