Use config file instead of dir for basedir metadata
This commit is contained in:
parent
aace4c2f13
commit
49719e3e66
@ -198,14 +198,16 @@ namespace cryfs {
|
||||
}
|
||||
|
||||
void Cli::_checkConfigIntegrity(const bf::path& basedir, const CryConfigFile& config) {
|
||||
if (!BasedirMetadata::filesystemIdForBasedirIsCorrect(basedir, config.config()->FilesystemId())) {
|
||||
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.updateFilesystemIdForBasedir(basedir, config.config()->FilesystemId());
|
||||
basedirMetadata.save();
|
||||
}
|
||||
|
||||
CryConfigLoader::ConfigLoadResult Cli::_loadOrCreateConfig(const ProgramOptions &options) {
|
||||
|
@ -15,68 +15,57 @@ using std::ostream;
|
||||
using std::istream;
|
||||
using std::ifstream;
|
||||
using std::ofstream;
|
||||
using std::string;
|
||||
|
||||
namespace cryfs {
|
||||
|
||||
namespace {
|
||||
bf::path _localStateConfigFile(const bf::path& basedir) {
|
||||
std::string basedir_id;
|
||||
CryptoPP::SHA512 hash;
|
||||
CryptoPP::StringSource(bf::canonical(basedir).native(), true,
|
||||
new CryptoPP::HashFilter(hash,
|
||||
new CryptoPP::HexEncoder(
|
||||
new CryptoPP::StringSink(basedir_id)
|
||||
)
|
||||
)
|
||||
);
|
||||
return LocalStateDir::forMapFromBasedirToConfigFiles() / basedir_id;
|
||||
}
|
||||
|
||||
void _serialize(ostream& stream, const CryConfig::FilesystemID& filesystemId) {
|
||||
ptree pt;
|
||||
pt.put<std::string>("filesystemId", filesystemId.ToString());
|
||||
ptree _load(const bf::path &metadataFilePath) {
|
||||
ptree result;
|
||||
|
||||
write_json(stream, pt);
|
||||
}
|
||||
|
||||
CryConfig::FilesystemID _deserialize(istream& stream) {
|
||||
ptree pt;
|
||||
read_json(stream, pt);
|
||||
|
||||
std::string filesystemId = pt.get<std::string>("filesystemId");
|
||||
|
||||
return CryConfig::FilesystemID::FromString(filesystemId);
|
||||
}
|
||||
|
||||
optional<CryConfig::FilesystemID> _load(const bf::path &metadataFilePath) {
|
||||
ifstream file(metadataFilePath.native());
|
||||
if (!file.good()) {
|
||||
// State file doesn't exist
|
||||
return none;
|
||||
if (file.good()) {
|
||||
read_json(file, result);
|
||||
}
|
||||
return _deserialize(file);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void _save(const bf::path &metadataFilePath, const CryConfig::FilesystemID& filesystemId) {
|
||||
void _save(const bf::path &metadataFilePath, const ptree& data) {
|
||||
ofstream file(metadataFilePath.native(), std::ios::trunc);
|
||||
_serialize(file, filesystemId);
|
||||
write_json(file, data);
|
||||
}
|
||||
|
||||
string jsonPathForBasedir(const bf::path &basedir) {
|
||||
return bf::canonical(basedir).native() + ".filesystemId";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool BasedirMetadata::filesystemIdForBasedirIsCorrect(const bf::path &basedir, const CryConfig::FilesystemID &filesystemId) {
|
||||
auto metadataFile = _localStateConfigFile(basedir);
|
||||
auto loaded = _load(metadataFile);
|
||||
if (loaded == none) {
|
||||
// Local state not known. Possibly the file system is currently being created.
|
||||
return true;
|
||||
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.
|
||||
}
|
||||
return loaded == filesystemId;
|
||||
auto filesystemIdFromState = CryConfig::FilesystemID::FromString(*entry);
|
||||
return filesystemIdFromState == filesystemId;
|
||||
}
|
||||
|
||||
void BasedirMetadata::updateFilesystemIdForBasedir(const bf::path &basedir, const CryConfig::FilesystemID &filesystemId) {
|
||||
auto metadataFile = _localStateConfigFile(basedir);
|
||||
_save(metadataFile, filesystemId);
|
||||
BasedirMetadata& BasedirMetadata::updateFilesystemIdForBasedir(const bf::path &basedir, const CryConfig::FilesystemID &filesystemId) {
|
||||
_data.put<string>(jsonPathForBasedir(basedir), filesystemId.ToString());
|
||||
return *this;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -3,14 +3,28 @@
|
||||
#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 bool filesystemIdForBasedirIsCorrect(const boost::filesystem::path &basedir, const CryConfig::FilesystemID &filesystemId);
|
||||
static void updateFilesystemIdForBasedir(const boost::filesystem::path &basedir, const CryConfig::FilesystemID &filesystemId);
|
||||
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;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -14,18 +14,17 @@ namespace cryfs {
|
||||
}
|
||||
|
||||
bf::path LocalStateDir::forFilesystemId(const CryConfig::FilesystemID &filesystemId) {
|
||||
_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;
|
||||
_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::forMapFromBasedirToConfigFiles() {
|
||||
bf::path result = appDir() / "map_basedir_initialconfigfile";
|
||||
_createDirIfNotExists(result);
|
||||
return result;
|
||||
bf::path LocalStateDir::forBasedirMetadata() {
|
||||
_createDirIfNotExists(appDir());
|
||||
return appDir() / "basedirs";
|
||||
}
|
||||
|
||||
void LocalStateDir::_createDirIfNotExists(const bf::path &path) {
|
||||
|
@ -11,7 +11,7 @@ namespace cryfs {
|
||||
class LocalStateDir final {
|
||||
public:
|
||||
static boost::filesystem::path forFilesystemId(const CryConfig::FilesystemID &filesystemId);
|
||||
static boost::filesystem::path forMapFromBasedirToConfigFiles();
|
||||
static boost::filesystem::path forBasedirMetadata();
|
||||
|
||||
// Use this from test cases to not pollute local config
|
||||
// TODO Make test cases call this
|
||||
|
@ -36,32 +36,32 @@ public:
|
||||
};
|
||||
|
||||
TEST_F(BasedirMetadataTest, givenEmptyState_whenCalled_thenSucceeds) {
|
||||
EXPECT_TRUE(BasedirMetadata::filesystemIdForBasedirIsCorrect(basedir1, id1));
|
||||
EXPECT_TRUE(BasedirMetadata::load().filesystemIdForBasedirIsCorrect(basedir1, id1));
|
||||
}
|
||||
|
||||
TEST_F(BasedirMetadataTest, givenStateWithBasedir_whenCalledForDifferentBasedir_thenSucceeds) {
|
||||
BasedirMetadata::updateFilesystemIdForBasedir(basedir2, id1);
|
||||
EXPECT_TRUE(BasedirMetadata::filesystemIdForBasedirIsCorrect(basedir1, id1));
|
||||
BasedirMetadata::load().updateFilesystemIdForBasedir(basedir2, id1).save();
|
||||
EXPECT_TRUE(BasedirMetadata::load().filesystemIdForBasedirIsCorrect(basedir1, id1));
|
||||
}
|
||||
|
||||
TEST_F(BasedirMetadataTest, givenStateWithBasedir_whenCalledWithSameId_thenSucceeds) {
|
||||
BasedirMetadata::updateFilesystemIdForBasedir(basedir1, id1);
|
||||
EXPECT_TRUE(BasedirMetadata::filesystemIdForBasedirIsCorrect(basedir1, id1));
|
||||
BasedirMetadata::load().updateFilesystemIdForBasedir(basedir1, id1).save();
|
||||
EXPECT_TRUE(BasedirMetadata::load().filesystemIdForBasedirIsCorrect(basedir1, id1));
|
||||
}
|
||||
|
||||
TEST_F(BasedirMetadataTest, givenStateWithBasedir_whenCalledWithDifferentId_thenFails) {
|
||||
BasedirMetadata::updateFilesystemIdForBasedir(basedir1, id2);
|
||||
EXPECT_FALSE(BasedirMetadata::filesystemIdForBasedirIsCorrect(basedir1, id1));
|
||||
BasedirMetadata::load().updateFilesystemIdForBasedir(basedir1, id2).save();
|
||||
EXPECT_FALSE(BasedirMetadata::load().filesystemIdForBasedirIsCorrect(basedir1, id1));
|
||||
}
|
||||
|
||||
TEST_F(BasedirMetadataTest, givenStateWithUpdatedBasedir_whenCalledWithSameId_thenSucceeds) {
|
||||
BasedirMetadata::updateFilesystemIdForBasedir(basedir1, id2);
|
||||
BasedirMetadata::updateFilesystemIdForBasedir(basedir1, id1);
|
||||
EXPECT_TRUE(BasedirMetadata::filesystemIdForBasedirIsCorrect(basedir1, id1));
|
||||
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::updateFilesystemIdForBasedir(basedir1, id2);
|
||||
BasedirMetadata::updateFilesystemIdForBasedir(basedir1, id1);
|
||||
EXPECT_FALSE(BasedirMetadata::filesystemIdForBasedirIsCorrect(basedir1, id2));
|
||||
BasedirMetadata::load().updateFilesystemIdForBasedir(basedir1, id2).save();
|
||||
BasedirMetadata::load().updateFilesystemIdForBasedir(basedir1, id1).save();
|
||||
EXPECT_FALSE(BasedirMetadata::load().filesystemIdForBasedirIsCorrect(basedir1, id2));
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user