Merge branch 0.9 (pre-work for version 0.9)
This commit is contained in:
commit
cfe2a48ebc
@ -1,5 +1,6 @@
|
|||||||
Version 0.9.0 (unreleased)
|
Version 0.9.0 (unreleased)
|
||||||
---------------
|
---------------
|
||||||
|
(warning) file systems created with earlier CryFS versions are incompatible with this release
|
||||||
* Fully support file access times
|
* Fully support file access times
|
||||||
* (for developers) New repository layout. All subrepositories have been merged to one directory
|
* (for developers) New repository layout. All subrepositories have been merged to one directory
|
||||||
* (for developers) Using CMake instead of biicode as build system
|
* (for developers) Using CMake instead of biicode as build system
|
||||||
|
@ -15,11 +15,11 @@ using cpputils::Data;
|
|||||||
namespace cryfs {
|
namespace cryfs {
|
||||||
|
|
||||||
CryConfig::CryConfig()
|
CryConfig::CryConfig()
|
||||||
: _rootBlob(""), _encKey(""), _cipher("") {
|
: _rootBlob(""), _encKey(""), _cipher(""), _version("") {
|
||||||
}
|
}
|
||||||
|
|
||||||
CryConfig::CryConfig(CryConfig &&rhs)
|
CryConfig::CryConfig(CryConfig &&rhs)
|
||||||
: _rootBlob(std::move(rhs._rootBlob)), _encKey(std::move(rhs._encKey)), _cipher(std::move(rhs._cipher)) {
|
: _rootBlob(std::move(rhs._rootBlob)), _encKey(std::move(rhs._encKey)), _cipher(std::move(rhs._cipher)), _version(std::move(rhs._version)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
CryConfig CryConfig::load(const Data &data) {
|
CryConfig CryConfig::load(const Data &data) {
|
||||||
@ -32,6 +32,7 @@ CryConfig CryConfig::load(const Data &data) {
|
|||||||
cfg._rootBlob = pt.get("cryfs.rootblob", "");
|
cfg._rootBlob = pt.get("cryfs.rootblob", "");
|
||||||
cfg._encKey = pt.get("cryfs.key", "");
|
cfg._encKey = pt.get("cryfs.key", "");
|
||||||
cfg._cipher = pt.get("cryfs.cipher", "");
|
cfg._cipher = pt.get("cryfs.cipher", "");
|
||||||
|
cfg._version = pt.get("cryfs.version", "0.8"); // CryFS 0.8 didn't specify this field, so if the field doesn't exist, it's 0.8.
|
||||||
return cfg;
|
return cfg;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -41,6 +42,7 @@ Data CryConfig::save() const {
|
|||||||
pt.put("cryfs.rootblob", _rootBlob);
|
pt.put("cryfs.rootblob", _rootBlob);
|
||||||
pt.put("cryfs.key", _encKey);
|
pt.put("cryfs.key", _encKey);
|
||||||
pt.put("cryfs.cipher", _cipher);
|
pt.put("cryfs.cipher", _cipher);
|
||||||
|
pt.put("cryfs.version", _version);
|
||||||
|
|
||||||
stringstream stream;
|
stringstream stream;
|
||||||
write_json(stream, pt);
|
write_json(stream, pt);
|
||||||
@ -71,4 +73,12 @@ void CryConfig::SetCipher(const std::string &value) {
|
|||||||
_cipher = value;
|
_cipher = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const std::string &CryConfig::Version() const {
|
||||||
|
return _version;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CryConfig::SetVersion(const std::string &value) {
|
||||||
|
_version = value;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,9 @@ public:
|
|||||||
const std::string &Cipher() const;
|
const std::string &Cipher() const;
|
||||||
void SetCipher(const std::string &value);
|
void SetCipher(const std::string &value);
|
||||||
|
|
||||||
|
const std::string &Version() const;
|
||||||
|
void SetVersion(const std::string &value);
|
||||||
|
|
||||||
static CryConfig load(const cpputils::Data &data);
|
static CryConfig load(const cpputils::Data &data);
|
||||||
cpputils::Data save() const;
|
cpputils::Data save() const;
|
||||||
|
|
||||||
@ -31,6 +34,7 @@ private:
|
|||||||
std::string _rootBlob;
|
std::string _rootBlob;
|
||||||
std::string _encKey;
|
std::string _encKey;
|
||||||
std::string _cipher;
|
std::string _cipher;
|
||||||
|
std::string _version;
|
||||||
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(CryConfig);
|
DISALLOW_COPY_AND_ASSIGN(CryConfig);
|
||||||
};
|
};
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#include "CryConfigCreator.h"
|
#include "CryConfigCreator.h"
|
||||||
#include "CryCipher.h"
|
#include "CryCipher.h"
|
||||||
|
#include <gitversion/version.h>
|
||||||
|
|
||||||
using cpputils::Console;
|
using cpputils::Console;
|
||||||
using cpputils::unique_ref;
|
using cpputils::unique_ref;
|
||||||
@ -21,6 +22,7 @@ namespace cryfs {
|
|||||||
config.SetCipher(_generateCipher(cipherFromCommandLine));
|
config.SetCipher(_generateCipher(cipherFromCommandLine));
|
||||||
config.SetEncryptionKey(_generateEncKey(config.Cipher()));
|
config.SetEncryptionKey(_generateEncKey(config.Cipher()));
|
||||||
config.SetRootBlob(_generateRootBlobKey());
|
config.SetRootBlob(_generateRootBlobKey());
|
||||||
|
config.SetVersion(version::VERSION_STRING);
|
||||||
return config;
|
return config;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,6 +3,8 @@
|
|||||||
#include <boost/filesystem.hpp>
|
#include <boost/filesystem.hpp>
|
||||||
#include <cpp-utils/random/Random.h>
|
#include <cpp-utils/random/Random.h>
|
||||||
#include <cpp-utils/logging/logging.h>
|
#include <cpp-utils/logging/logging.h>
|
||||||
|
#include <boost/algorithm/string/predicate.hpp>
|
||||||
|
#include <gitversion/version.h>
|
||||||
|
|
||||||
namespace bf = boost::filesystem;
|
namespace bf = boost::filesystem;
|
||||||
using cpputils::unique_ref;
|
using cpputils::unique_ref;
|
||||||
@ -37,12 +39,24 @@ optional<CryConfigFile> CryConfigLoader::_loadConfig(const bf::path &filename) {
|
|||||||
return none;
|
return none;
|
||||||
}
|
}
|
||||||
std::cout << "done" << std::endl;
|
std::cout << "done" << std::endl;
|
||||||
if (_cipherFromCommandLine != none && config->config()->Cipher() != *_cipherFromCommandLine) {
|
_checkVersion(*config->config());
|
||||||
throw std::runtime_error("Filesystem uses "+config->config()->Cipher()+" cipher and not "+*_cipherFromCommandLine+" as specified.");
|
_checkCipher(*config->config());
|
||||||
}
|
|
||||||
return std::move(*config);
|
return std::move(*config);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CryConfigLoader::_checkVersion(const CryConfig &config) {
|
||||||
|
const string allowedVersionPrefix = string() + version::VERSION_COMPONENTS[0] + "." + version::VERSION_COMPONENTS[1] + ".";
|
||||||
|
if (!boost::starts_with(config.Version(), allowedVersionPrefix)) {
|
||||||
|
throw std::runtime_error(string() + "This filesystem was created with CryFS " + config.Version() + " and is incompatible. Please create a new one with your version of CryFS and migrate your data.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CryConfigLoader::_checkCipher(const CryConfig &config) const {
|
||||||
|
if (_cipherFromCommandLine != none && config.Cipher() != *_cipherFromCommandLine) {
|
||||||
|
throw std::runtime_error(string() + "Filesystem uses " + config.Cipher() + " cipher and not " + *_cipherFromCommandLine + " as specified.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
optional<CryConfigFile> CryConfigLoader::loadOrCreate(const bf::path &filename) {
|
optional<CryConfigFile> CryConfigLoader::loadOrCreate(const bf::path &filename) {
|
||||||
if (bf::exists(filename)) {
|
if (bf::exists(filename)) {
|
||||||
return _loadConfig(filename);
|
return _loadConfig(filename);
|
||||||
|
@ -21,6 +21,8 @@ public:
|
|||||||
private:
|
private:
|
||||||
boost::optional<CryConfigFile> _loadConfig(const boost::filesystem::path &filename);
|
boost::optional<CryConfigFile> _loadConfig(const boost::filesystem::path &filename);
|
||||||
CryConfigFile _createConfig(const boost::filesystem::path &filename);
|
CryConfigFile _createConfig(const boost::filesystem::path &filename);
|
||||||
|
static void _checkVersion(const CryConfig &config);
|
||||||
|
void _checkCipher(const CryConfig &config) const;
|
||||||
|
|
||||||
CryConfigCreator _creator;
|
CryConfigCreator _creator;
|
||||||
cpputils::SCryptSettings _scryptSettings;
|
cpputils::SCryptSettings _scryptSettings;
|
||||||
|
@ -1,87 +1,116 @@
|
|||||||
#include "DirEntry.h"
|
#include "DirEntry.h"
|
||||||
|
|
||||||
using std::vector;
|
using std::vector;
|
||||||
|
using std::string;
|
||||||
using blockstore::Key;
|
using blockstore::Key;
|
||||||
|
|
||||||
namespace cryfs {
|
namespace cryfs {
|
||||||
namespace fsblobstore {
|
namespace fsblobstore {
|
||||||
|
|
||||||
void DirEntry::serialize(uint8_t *dest) const {
|
void DirEntry::serialize(uint8_t *dest) const {
|
||||||
|
ASSERT(
|
||||||
|
((type == fspp::Dir::EntryType::FILE) && S_ISREG(mode) && !S_ISDIR(mode) && !S_ISLNK(mode)) ||
|
||||||
|
((type == fspp::Dir::EntryType::DIR) && !S_ISREG(mode) && S_ISDIR(mode) && !S_ISLNK(mode)) ||
|
||||||
|
((type == fspp::Dir::EntryType::SYMLINK) && !S_ISREG(mode) && !S_ISDIR(mode) && S_ISLNK(mode))
|
||||||
|
, "Wrong mode bit set for this type: "+std::to_string(mode & S_IFREG)+", "+std::to_string(mode&S_IFDIR)+", "+std::to_string(mode&S_IFLNK)+", "+std::to_string(static_cast<uint8_t>(type))
|
||||||
|
);
|
||||||
unsigned int offset = 0;
|
unsigned int offset = 0;
|
||||||
*(dest+offset) = static_cast<uint8_t>(type);
|
offset += _serializeUint8(dest + offset, static_cast<uint8_t>(type));
|
||||||
offset += 1;
|
offset += _serializeUint32(dest + offset, mode);
|
||||||
|
offset += _serializeUint32(dest + offset, uid);
|
||||||
std::memcpy(dest+offset, name.c_str(), name.size()+1);
|
offset += _serializeUint32(dest + offset, gid);
|
||||||
offset += name.size() + 1;
|
offset += _serializeTimeValue(dest + offset, lastAccessTime);
|
||||||
|
offset += _serializeTimeValue(dest + offset, lastModificationTime);
|
||||||
key.ToBinary(dest+offset);
|
offset += _serializeTimeValue(dest + offset, lastMetadataChangeTime);
|
||||||
offset += key.BINARY_LENGTH;
|
offset += _serializeString(dest + offset, name);
|
||||||
|
offset += _serializeKey(dest + offset, key);
|
||||||
*reinterpret_cast<uid_t*>(dest+offset) = uid;
|
|
||||||
offset += sizeof(uid_t);
|
|
||||||
|
|
||||||
*reinterpret_cast<gid_t*>(dest+offset) = gid;
|
|
||||||
offset += sizeof(gid_t);
|
|
||||||
|
|
||||||
*reinterpret_cast<mode_t*>(dest+offset) = mode;
|
|
||||||
offset += sizeof(mode_t);
|
|
||||||
|
|
||||||
//TODO Persist times, see comment in deserializeAndAddToVector()
|
|
||||||
//static_assert(sizeof(timespec) == 16, "Ensure platform independence of the serialization");
|
|
||||||
//*reinterpret_cast<timespec*>(dest+offset) = lastAccessTime;
|
|
||||||
//offset += sizeof(timespec);
|
|
||||||
//*reinterpret_cast<timespec*>(dest+offset) = lastModificationTime;
|
|
||||||
//offset += sizeof(timespec);
|
|
||||||
//*reinterpret_cast<timespec*>(dest+offset) = lastMetadataChangeTime;
|
|
||||||
//offset += sizeof(timespec);
|
|
||||||
|
|
||||||
ASSERT(offset == serializedSize(), "Didn't write correct number of elements");
|
ASSERT(offset == serializedSize(), "Didn't write correct number of elements");
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t DirEntry::serializedSize() const {
|
|
||||||
//TODO Persist times, see comment in deserializeAndAddToVector()
|
|
||||||
//return 1 + (name.size() + 1) + key.BINARY_LENGTH + sizeof(uid_t) + sizeof(gid_t) + sizeof(mode_t) + 3*sizeof(timespec);
|
|
||||||
return 1 + (name.size() + 1) + key.BINARY_LENGTH + sizeof(uid_t) + sizeof(gid_t) + sizeof(mode_t);
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *DirEntry::deserializeAndAddToVector(const char *pos, vector<DirEntry> *result) {
|
const char *DirEntry::deserializeAndAddToVector(const char *pos, vector<DirEntry> *result) {
|
||||||
// Read type magic number (whether it is a dir or a file)
|
fspp::Dir::EntryType type = static_cast<fspp::Dir::EntryType>(_deserializeUint8(&pos));
|
||||||
fspp::Dir::EntryType type =
|
mode_t mode = _deserializeUint32(&pos);
|
||||||
static_cast<fspp::Dir::EntryType>(*reinterpret_cast<const unsigned char*>(pos));
|
uid_t uid = _deserializeUint32(&pos);
|
||||||
pos += 1;
|
gid_t gid = _deserializeUint32(&pos);
|
||||||
|
timespec lastAccessTime = _deserializeTimeValue(&pos);
|
||||||
size_t namelength = strlen(pos);
|
timespec lastModificationTime = _deserializeTimeValue(&pos);
|
||||||
std::string name(pos, namelength);
|
timespec lastMetadataChangeTime = _deserializeTimeValue(&pos);
|
||||||
pos += namelength + 1;
|
string name = _deserializeString(&pos);
|
||||||
|
Key key = _deserializeKey(&pos);
|
||||||
Key key = Key::FromBinary(pos);
|
|
||||||
pos += Key::BINARY_LENGTH;
|
|
||||||
|
|
||||||
uid_t uid = *(uid_t*)pos;
|
|
||||||
pos += sizeof(uid_t);
|
|
||||||
|
|
||||||
gid_t gid = *(gid_t*)pos;
|
|
||||||
pos += sizeof(gid_t);
|
|
||||||
|
|
||||||
mode_t mode = *(mode_t*)pos;
|
|
||||||
pos += sizeof(mode_t);
|
|
||||||
|
|
||||||
//TODO Persist times. This breaks compatibility though - so change cryfs::InnerConfig::HEADER
|
|
||||||
// This is already implemented, but I commented it out for now, because it would break compatibility.
|
|
||||||
//timespec lastAccessTime = *(timespec*)pos;
|
|
||||||
//pos += sizeof(timespec);
|
|
||||||
//timespec lastModificationTime = *(timespec*)pos;
|
|
||||||
//pos += sizeof(timespec);
|
|
||||||
//timespec lastMetadataChangeTime = *(timespec*)pos;
|
|
||||||
//pos += sizeof(timespec);
|
|
||||||
timespec lastAccessTime;
|
|
||||||
clock_gettime(CLOCK_REALTIME, &lastAccessTime);
|
|
||||||
timespec lastModificationTime = lastAccessTime;
|
|
||||||
timespec lastMetadataChangeTime = lastAccessTime;
|
|
||||||
|
|
||||||
result->emplace_back(type, name, key, mode, uid, gid, lastAccessTime, lastModificationTime, lastMetadataChangeTime);
|
result->emplace_back(type, name, key, mode, uid, gid, lastAccessTime, lastModificationTime, lastMetadataChangeTime);
|
||||||
return pos;
|
return pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned int DirEntry::_serializeTimeValue(uint8_t *dest, timespec value) {
|
||||||
|
unsigned int offset = 0;
|
||||||
|
*reinterpret_cast<uint64_t*>(dest+offset) = value.tv_sec;
|
||||||
|
offset += sizeof(uint64_t);
|
||||||
|
*reinterpret_cast<uint32_t*>(dest+offset) = value.tv_nsec;
|
||||||
|
offset += sizeof(uint32_t);
|
||||||
|
ASSERT(offset == _serializedTimeValueSize(), "serialized to wrong size");
|
||||||
|
return offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t DirEntry::_serializedTimeValueSize() {
|
||||||
|
return sizeof(uint64_t) + sizeof(uint32_t);
|
||||||
|
}
|
||||||
|
|
||||||
|
timespec DirEntry::_deserializeTimeValue(const char **pos) {
|
||||||
|
timespec value;
|
||||||
|
value.tv_sec = *(uint64_t*)(*pos);
|
||||||
|
*pos += sizeof(uint64_t);
|
||||||
|
value.tv_nsec = *(uint32_t*)(*pos);
|
||||||
|
*pos += sizeof(uint32_t);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int DirEntry::_serializeUint8(uint8_t *dest, uint8_t value) {
|
||||||
|
*reinterpret_cast<uint8_t*>(dest) = value;
|
||||||
|
return sizeof(uint8_t);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t DirEntry::_deserializeUint8(const char **pos) {
|
||||||
|
uint8_t value = *(uint8_t*)(*pos);
|
||||||
|
*pos += sizeof(uint8_t);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int DirEntry::_serializeUint32(uint8_t *dest, uint32_t value) {
|
||||||
|
*reinterpret_cast<uint32_t*>(dest) = value;
|
||||||
|
return sizeof(uint32_t);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t DirEntry::_deserializeUint32(const char **pos) {
|
||||||
|
uint32_t value = *(uint32_t*)(*pos);
|
||||||
|
*pos += sizeof(uint32_t);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int DirEntry::_serializeString(uint8_t *dest, const string &value) {
|
||||||
|
std::memcpy(dest, value.c_str(), value.size()+1);
|
||||||
|
return value.size() + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
string DirEntry::_deserializeString(const char **pos) {
|
||||||
|
size_t length = strlen(*pos);
|
||||||
|
string value(*pos, length);
|
||||||
|
*pos += length + 1;
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int DirEntry::_serializeKey(uint8_t *dest, const Key &key) {
|
||||||
|
key.ToBinary(dest);
|
||||||
|
return key.BINARY_LENGTH;
|
||||||
|
}
|
||||||
|
|
||||||
|
Key DirEntry::_deserializeKey(const char **pos) {
|
||||||
|
Key key = Key::FromBinary(*pos);
|
||||||
|
*pos += Key::BINARY_LENGTH;
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t DirEntry::serializedSize() const {
|
||||||
|
return 1 + sizeof(uint32_t) + sizeof(uint32_t) + sizeof(uint32_t) + 3*_serializedTimeValueSize() + (name.size() + 1) + key.BINARY_LENGTH;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,6 +34,17 @@ namespace cryfs {
|
|||||||
void serialize(uint8_t* dest) const;
|
void serialize(uint8_t* dest) const;
|
||||||
size_t serializedSize() const;
|
size_t serializedSize() const;
|
||||||
static const char *deserializeAndAddToVector(const char *pos, std::vector<DirEntry> *result);
|
static const char *deserializeAndAddToVector(const char *pos, std::vector<DirEntry> *result);
|
||||||
|
static size_t _serializedTimeValueSize();
|
||||||
|
static unsigned int _serializeTimeValue(uint8_t *dest, timespec value);
|
||||||
|
static unsigned int _serializeUint8(uint8_t *dest, uint8_t value);
|
||||||
|
static unsigned int _serializeUint32(uint8_t *dest, uint32_t value);
|
||||||
|
static unsigned int _serializeString(uint8_t *dest, const std::string &value);
|
||||||
|
static unsigned int _serializeKey(uint8_t *dest, const blockstore::Key &value);
|
||||||
|
static timespec _deserializeTimeValue(const char **pos);
|
||||||
|
static uint8_t _deserializeUint8(const char **pos);
|
||||||
|
static uint32_t _deserializeUint32(const char **pos);
|
||||||
|
static std::string _deserializeString(const char **pos);
|
||||||
|
static blockstore::Key _deserializeKey(const char **pos);
|
||||||
|
|
||||||
fspp::Dir::EntryType type;
|
fspp::Dir::EntryType type;
|
||||||
std::string name;
|
std::string name;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user