Use local state file instead of myClientId file
This commit is contained in:
parent
73aab31ade
commit
26b3b366c9
@ -40,8 +40,8 @@ set(LIB_SOURCES
|
|||||||
filesystem/cachingfsblobstore/SymlinkBlobRef.cpp
|
filesystem/cachingfsblobstore/SymlinkBlobRef.cpp
|
||||||
filesystem/CryFile.cpp
|
filesystem/CryFile.cpp
|
||||||
filesystem/CryDevice.cpp
|
filesystem/CryDevice.cpp
|
||||||
localstate/MyClientId.cpp
|
|
||||||
localstate/LocalStateDir.cpp
|
localstate/LocalStateDir.cpp
|
||||||
|
localstate/LocalStateMetadata.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
add_library(${PROJECT_NAME} STATIC ${LIB_SOURCES})
|
add_library(${PROJECT_NAME} STATIC ${LIB_SOURCES})
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
#include <gitversion/gitversion.h>
|
#include <gitversion/gitversion.h>
|
||||||
#include <cpp-utils/random/Random.h>
|
#include <cpp-utils/random/Random.h>
|
||||||
#include <cryfs/localstate/LocalStateDir.h>
|
#include <cryfs/localstate/LocalStateDir.h>
|
||||||
#include <cryfs/localstate/MyClientId.h>
|
#include <cryfs/localstate/LocalStateMetadata.h>
|
||||||
|
|
||||||
using cpputils::Console;
|
using cpputils::Console;
|
||||||
using cpputils::unique_ref;
|
using cpputils::unique_ref;
|
||||||
@ -30,7 +30,8 @@ namespace cryfs {
|
|||||||
config.SetRootBlob(_generateRootBlobId());
|
config.SetRootBlob(_generateRootBlobId());
|
||||||
config.SetEncryptionKey(_generateEncKey(config.Cipher()));
|
config.SetEncryptionKey(_generateEncKey(config.Cipher()));
|
||||||
config.SetFilesystemId(_generateFilesystemID());
|
config.SetFilesystemId(_generateFilesystemID());
|
||||||
uint32_t myClientId = MyClientId(LocalStateDir::forFilesystemId(config.FilesystemId())).loadOrGenerate();
|
auto localState = LocalStateMetadata::loadOrGenerate(LocalStateDir::forFilesystemId(config.FilesystemId()));
|
||||||
|
uint32_t myClientId = localState.myClientId();
|
||||||
config.SetExclusiveClientId(_generateExclusiveClientId(missingBlockIsIntegrityViolationFromCommandLine, myClientId));
|
config.SetExclusiveClientId(_generateExclusiveClientId(missingBlockIsIntegrityViolationFromCommandLine, myClientId));
|
||||||
#ifndef CRYFS_NO_COMPATIBILITY
|
#ifndef CRYFS_NO_COMPATIBILITY
|
||||||
config.SetHasVersionNumbers(true);
|
config.SetHasVersionNumbers(true);
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
#include <gitversion/gitversion.h>
|
#include <gitversion/gitversion.h>
|
||||||
#include <gitversion/VersionCompare.h>
|
#include <gitversion/VersionCompare.h>
|
||||||
#include "../localstate/LocalStateDir.h"
|
#include "../localstate/LocalStateDir.h"
|
||||||
#include "../localstate/MyClientId.h"
|
#include "../localstate/LocalStateMetadata.h"
|
||||||
|
|
||||||
namespace bf = boost::filesystem;
|
namespace bf = boost::filesystem;
|
||||||
using cpputils::unique_ref;
|
using cpputils::unique_ref;
|
||||||
@ -57,7 +57,8 @@ optional<CryConfigLoader::ConfigLoadResult> CryConfigLoader::_loadConfig(const b
|
|||||||
config->save();
|
config->save();
|
||||||
}
|
}
|
||||||
_checkCipher(*config->config());
|
_checkCipher(*config->config());
|
||||||
uint32_t myClientId = MyClientId(LocalStateDir::forFilesystemId(config->config()->FilesystemId())).loadOrGenerate();
|
auto localState = LocalStateMetadata::loadOrGenerate(LocalStateDir::forFilesystemId(config->config()->FilesystemId()));
|
||||||
|
uint32_t myClientId = localState.myClientId();
|
||||||
_checkMissingBlocksAreIntegrityViolations(&*config, myClientId);
|
_checkMissingBlocksAreIntegrityViolations(&*config, myClientId);
|
||||||
return ConfigLoadResult {std::move(*config), myClientId};
|
return ConfigLoadResult {std::move(*config), myClientId};
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,6 @@
|
|||||||
#include <cpp-utils/system/homedir.h>
|
#include <cpp-utils/system/homedir.h>
|
||||||
#include <gitversion/VersionCompare.h>
|
#include <gitversion/VersionCompare.h>
|
||||||
#include <blockstore/interface/BlockStore2.h>
|
#include <blockstore/interface/BlockStore2.h>
|
||||||
#include "cryfs/localstate/MyClientId.h"
|
|
||||||
#include "cryfs/localstate/LocalStateDir.h"
|
#include "cryfs/localstate/LocalStateDir.h"
|
||||||
|
|
||||||
using std::string;
|
using std::string;
|
||||||
|
108
src/cryfs/localstate/LocalStateMetadata.cpp
Normal file
108
src/cryfs/localstate/LocalStateMetadata.cpp
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
#include "LocalStateMetadata.h"
|
||||||
|
#include <boost/property_tree/ptree.hpp>
|
||||||
|
#include <boost/property_tree/json_parser.hpp>
|
||||||
|
#include <cpp-utils/random/Random.h>
|
||||||
|
#include <boost/filesystem.hpp>
|
||||||
|
#include <blockstore/implementations/integrity/KnownBlockVersions.h>
|
||||||
|
|
||||||
|
using boost::optional;
|
||||||
|
using boost::none;
|
||||||
|
using boost::property_tree::ptree;
|
||||||
|
using boost::property_tree::write_json;
|
||||||
|
using boost::property_tree::read_json;
|
||||||
|
using std::ifstream;
|
||||||
|
using std::ofstream;
|
||||||
|
using std::istream;
|
||||||
|
using std::ostream;
|
||||||
|
using cpputils::Random;
|
||||||
|
using blockstore::integrity::KnownBlockVersions;
|
||||||
|
namespace bf = boost::filesystem;
|
||||||
|
|
||||||
|
namespace cryfs {
|
||||||
|
|
||||||
|
LocalStateMetadata::LocalStateMetadata(uint32_t myClientId)
|
||||||
|
: _myClientId(myClientId) {}
|
||||||
|
|
||||||
|
LocalStateMetadata LocalStateMetadata::loadOrGenerate(const bf::path &statePath) {
|
||||||
|
auto metadataFile = statePath / "metadata";
|
||||||
|
auto loaded = _load(metadataFile);
|
||||||
|
if (loaded != none) {
|
||||||
|
return *loaded;
|
||||||
|
}
|
||||||
|
// If it couldn't be loaded, generate a new client id.
|
||||||
|
return _generate(metadataFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
optional<LocalStateMetadata> LocalStateMetadata::_load(const bf::path &metadataFilePath) {
|
||||||
|
ifstream file(metadataFilePath.native());
|
||||||
|
if (!file.good()) {
|
||||||
|
// State file doesn't exist
|
||||||
|
return none;
|
||||||
|
}
|
||||||
|
return _deserialize(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LocalStateMetadata::_save(const bf::path &metadataFilePath) const {
|
||||||
|
ofstream file(metadataFilePath.native(), std::ios::trunc);
|
||||||
|
_serialize(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
uint32_t _generateClientId() {
|
||||||
|
uint32_t result;
|
||||||
|
do {
|
||||||
|
result = *reinterpret_cast<uint32_t*>(Random::PseudoRandom().getFixedSize<sizeof(uint32_t)>().data());
|
||||||
|
} while(result == KnownBlockVersions::CLIENT_ID_FOR_DELETED_BLOCK); // Safety check - CLIENT_ID_FOR_DELETED_BLOCK shouldn't be used by any valid client.
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef CRYFS_NO_COMPATIBILITY
|
||||||
|
optional<uint32_t> _tryLoadClientIdFromLegacyFile(const bf::path &metadataFilePath) {
|
||||||
|
auto myClientIdFile = metadataFilePath.parent_path() / "myClientId";
|
||||||
|
ifstream file(myClientIdFile.native());
|
||||||
|
if (!file.good()) {
|
||||||
|
return none;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t value;
|
||||||
|
file >> value;
|
||||||
|
file.close();
|
||||||
|
//bf::remove(myClientIdFile);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
LocalStateMetadata LocalStateMetadata::_generate(const bf::path &metadataFilePath) {
|
||||||
|
uint32_t myClientId = _generateClientId();
|
||||||
|
#ifndef CRYFS_NO_COMPATIBILITY
|
||||||
|
// In the old format, this was stored in a "myClientId" file. If that file exists, load it from there.
|
||||||
|
optional<uint32_t> legacy = _tryLoadClientIdFromLegacyFile(metadataFilePath);
|
||||||
|
if (legacy != none) {
|
||||||
|
myClientId = *legacy;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
LocalStateMetadata result(myClientId);
|
||||||
|
result._save(metadataFilePath);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LocalStateMetadata::_serialize(ostream& stream) const {
|
||||||
|
ptree pt;
|
||||||
|
pt.put<uint32_t>("myClientId", myClientId());
|
||||||
|
|
||||||
|
write_json(stream, pt);
|
||||||
|
}
|
||||||
|
|
||||||
|
LocalStateMetadata LocalStateMetadata::_deserialize(istream& stream) {
|
||||||
|
ptree pt;
|
||||||
|
read_json(stream, pt);
|
||||||
|
|
||||||
|
uint32_t myClientId = pt.get<uint32_t>("myClientId");
|
||||||
|
|
||||||
|
return LocalStateMetadata(myClientId);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
36
src/cryfs/localstate/LocalStateMetadata.h
Normal file
36
src/cryfs/localstate/LocalStateMetadata.h
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
#pragma once
|
||||||
|
#ifndef MESSMER_CRYFS_LOCALSTATE_LOCALSTATEMETADATA_H_
|
||||||
|
#define MESSMER_CRYFS_LOCALSTATE_LOCALSTATEMETADATA_H_
|
||||||
|
|
||||||
|
#include <boost/filesystem/path.hpp>
|
||||||
|
#include <boost/optional.hpp>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
namespace cryfs {
|
||||||
|
|
||||||
|
class LocalStateMetadata final {
|
||||||
|
public:
|
||||||
|
|
||||||
|
static LocalStateMetadata loadOrGenerate(const boost::filesystem::path &statePath);
|
||||||
|
|
||||||
|
uint32_t myClientId() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
LocalStateMetadata(uint32_t myClientId);
|
||||||
|
|
||||||
|
static boost::optional<LocalStateMetadata> _load(const boost::filesystem::path &metadataFilePath);
|
||||||
|
static LocalStateMetadata _deserialize(std::istream& stream);
|
||||||
|
static LocalStateMetadata _generate(const boost::filesystem::path &metadataFilePath);
|
||||||
|
void _save(const boost::filesystem::path &metadataFilePath) const;
|
||||||
|
void _serialize(std::ostream& stream) const;
|
||||||
|
|
||||||
|
const uint32_t _myClientId;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline uint32_t LocalStateMetadata::myClientId() const {
|
||||||
|
return _myClientId;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
@ -1,54 +0,0 @@
|
|||||||
#include "MyClientId.h"
|
|
||||||
#include <fstream>
|
|
||||||
#include <cpp-utils/random/Random.h>
|
|
||||||
#include <blockstore/implementations/integrity/KnownBlockVersions.h>
|
|
||||||
|
|
||||||
using boost::optional;
|
|
||||||
using boost::none;
|
|
||||||
using std::ifstream;
|
|
||||||
using std::ofstream;
|
|
||||||
using cpputils::Random;
|
|
||||||
using blockstore::integrity::KnownBlockVersions;
|
|
||||||
namespace bf = boost::filesystem;
|
|
||||||
|
|
||||||
namespace cryfs {
|
|
||||||
|
|
||||||
MyClientId::MyClientId(const bf::path &statePath)
|
|
||||||
:_stateFilePath(statePath / "myClientId") {
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t MyClientId::loadOrGenerate() const {
|
|
||||||
auto loaded = _load();
|
|
||||||
if (loaded != none) {
|
|
||||||
return *loaded;
|
|
||||||
}
|
|
||||||
// If it couldn't be loaded, generate a new client id.
|
|
||||||
auto generated = _generate();
|
|
||||||
_save(generated);
|
|
||||||
return generated;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t MyClientId::_generate() {
|
|
||||||
uint32_t result;
|
|
||||||
do {
|
|
||||||
result = *reinterpret_cast<uint32_t*>(Random::PseudoRandom().getFixedSize<sizeof(uint32_t)>().data());
|
|
||||||
} while(result == KnownBlockVersions::CLIENT_ID_FOR_DELETED_BLOCK); // Safety check - CLIENT_ID_FOR_DELETED_BLOCK shouldn't be used by any valid client.
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
optional<uint32_t> MyClientId::_load() const {
|
|
||||||
ifstream file(_stateFilePath.native());
|
|
||||||
if (!file.good()) {
|
|
||||||
// State file doesn't exist
|
|
||||||
return none;
|
|
||||||
}
|
|
||||||
uint32_t value;
|
|
||||||
file >> value;
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MyClientId::_save(uint32_t clientId) const {
|
|
||||||
ofstream file(_stateFilePath.native());
|
|
||||||
file << clientId;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,30 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#ifndef MESSMER_CRYFS_LOCALSTATE_MYCLIENTID_H_
|
|
||||||
#define MESSMER_CRYFS_LOCALSTATE_MYCLIENTID_H_
|
|
||||||
|
|
||||||
#include <cpp-utils/macros.h>
|
|
||||||
#include <boost/filesystem/path.hpp>
|
|
||||||
#include <boost/optional.hpp>
|
|
||||||
|
|
||||||
namespace cryfs {
|
|
||||||
|
|
||||||
class MyClientId final {
|
|
||||||
public:
|
|
||||||
MyClientId(const boost::filesystem::path &statePath);
|
|
||||||
|
|
||||||
uint32_t loadOrGenerate() const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
const boost::filesystem::path _stateFilePath;
|
|
||||||
|
|
||||||
static uint32_t _generate();
|
|
||||||
boost::optional<uint32_t> _load() const;
|
|
||||||
void _save(uint32_t clientId) const;
|
|
||||||
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(MyClientId);
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
@ -17,7 +17,7 @@ set(SOURCES
|
|||||||
filesystem/CryFsTest.cpp
|
filesystem/CryFsTest.cpp
|
||||||
filesystem/CryNodeTest.cpp
|
filesystem/CryNodeTest.cpp
|
||||||
filesystem/FileSystemTest.cpp
|
filesystem/FileSystemTest.cpp
|
||||||
localstate/MyClientIdTest.cpp
|
localstate/LocalStateMetadataTest.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
add_executable(${PROJECT_NAME} ${SOURCES})
|
add_executable(${PROJECT_NAME} ${SOURCES})
|
||||||
|
38
test/cryfs/localstate/LocalStateMetadataTest.cpp
Normal file
38
test/cryfs/localstate/LocalStateMetadataTest.cpp
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
#include <cryfs/localstate/LocalStateMetadata.h>
|
||||||
|
#include <cpp-utils/tempfile/TempDir.h>
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
|
using cpputils::TempDir;
|
||||||
|
using cryfs::LocalStateMetadata;
|
||||||
|
using std::ofstream;
|
||||||
|
|
||||||
|
class LocalStateMetadataTest : public ::testing::Test {
|
||||||
|
public:
|
||||||
|
TempDir stateDir;
|
||||||
|
TempDir stateDir2;
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST_F(LocalStateMetadataTest, myClientId_ValueIsConsistent) {
|
||||||
|
LocalStateMetadata metadata1 = LocalStateMetadata::loadOrGenerate(stateDir.path());
|
||||||
|
LocalStateMetadata metadata2 = LocalStateMetadata::loadOrGenerate(stateDir.path());
|
||||||
|
EXPECT_EQ(metadata1.myClientId(), metadata2.myClientId());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(LocalStateMetadataTest, myClientId_ValueIsRandomForNewClient) {
|
||||||
|
LocalStateMetadata metadata1 = LocalStateMetadata::loadOrGenerate(stateDir.path());
|
||||||
|
LocalStateMetadata metadata2 = LocalStateMetadata::loadOrGenerate(stateDir2.path());
|
||||||
|
EXPECT_NE(metadata1.myClientId(), metadata2.myClientId());
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef CRYFS_NO_COMPATIBILITY
|
||||||
|
TEST_F(LocalStateMetadataTest, myClientId_TakesLegacyValueIfSpecified) {
|
||||||
|
ofstream file((stateDir.path() / "myClientId").native());
|
||||||
|
file << 12345u;
|
||||||
|
file.close();
|
||||||
|
|
||||||
|
LocalStateMetadata metadata = LocalStateMetadata::loadOrGenerate(stateDir.path());
|
||||||
|
EXPECT_EQ(12345u, metadata.myClientId());
|
||||||
|
}
|
||||||
|
#endif
|
@ -1,23 +0,0 @@
|
|||||||
#include <gtest/gtest.h>
|
|
||||||
|
|
||||||
#include "cryfs/localstate/MyClientId.h"
|
|
||||||
#include <cpp-utils/tempfile/TempDir.h>
|
|
||||||
|
|
||||||
using cpputils::TempDir;
|
|
||||||
using cryfs::MyClientId;
|
|
||||||
|
|
||||||
class MyClientIdTest : public ::testing::Test {
|
|
||||||
public:
|
|
||||||
TempDir stateDir;
|
|
||||||
TempDir stateDir2;
|
|
||||||
};
|
|
||||||
|
|
||||||
TEST_F(MyClientIdTest, ValueIsConsistent) {
|
|
||||||
uint32_t myClientId = MyClientId(stateDir.path()).loadOrGenerate();
|
|
||||||
EXPECT_EQ(myClientId, MyClientId(stateDir.path()).loadOrGenerate());
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(MyClientIdTest, ValueIsRandomForNewClient) {
|
|
||||||
uint32_t myClientId = MyClientId(stateDir.path()).loadOrGenerate();
|
|
||||||
EXPECT_NE(myClientId, MyClientId(stateDir2.path()).loadOrGenerate());
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user