Merge branch 0.9 (pre-work for version 0.9)

This commit is contained in:
Sebastian Messmer 2016-02-11 17:35:20 +01:00
commit cfe2a48ebc
8 changed files with 145 additions and 72 deletions

View File

@ -1,5 +1,6 @@
Version 0.9.0 (unreleased)
---------------
(warning) file systems created with earlier CryFS versions are incompatible with this release
* Fully support file access times
* (for developers) New repository layout. All subrepositories have been merged to one directory
* (for developers) Using CMake instead of biicode as build system

View File

@ -15,11 +15,11 @@ using cpputils::Data;
namespace cryfs {
CryConfig::CryConfig()
: _rootBlob(""), _encKey(""), _cipher("") {
: _rootBlob(""), _encKey(""), _cipher(""), _version("") {
}
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) {
@ -32,6 +32,7 @@ CryConfig CryConfig::load(const Data &data) {
cfg._rootBlob = pt.get("cryfs.rootblob", "");
cfg._encKey = pt.get("cryfs.key", "");
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;
}
@ -41,6 +42,7 @@ Data CryConfig::save() const {
pt.put("cryfs.rootblob", _rootBlob);
pt.put("cryfs.key", _encKey);
pt.put("cryfs.cipher", _cipher);
pt.put("cryfs.version", _version);
stringstream stream;
write_json(stream, pt);
@ -71,4 +73,12 @@ void CryConfig::SetCipher(const std::string &value) {
_cipher = value;
}
const std::string &CryConfig::Version() const {
return _version;
}
void CryConfig::SetVersion(const std::string &value) {
_version = value;
}
}

View File

@ -24,6 +24,9 @@ public:
const std::string &Cipher() const;
void SetCipher(const std::string &value);
const std::string &Version() const;
void SetVersion(const std::string &value);
static CryConfig load(const cpputils::Data &data);
cpputils::Data save() const;
@ -31,6 +34,7 @@ private:
std::string _rootBlob;
std::string _encKey;
std::string _cipher;
std::string _version;
DISALLOW_COPY_AND_ASSIGN(CryConfig);
};

View File

@ -1,5 +1,6 @@
#include "CryConfigCreator.h"
#include "CryCipher.h"
#include <gitversion/version.h>
using cpputils::Console;
using cpputils::unique_ref;
@ -21,6 +22,7 @@ namespace cryfs {
config.SetCipher(_generateCipher(cipherFromCommandLine));
config.SetEncryptionKey(_generateEncKey(config.Cipher()));
config.SetRootBlob(_generateRootBlobKey());
config.SetVersion(version::VERSION_STRING);
return config;
}

View File

@ -3,6 +3,8 @@
#include <boost/filesystem.hpp>
#include <cpp-utils/random/Random.h>
#include <cpp-utils/logging/logging.h>
#include <boost/algorithm/string/predicate.hpp>
#include <gitversion/version.h>
namespace bf = boost::filesystem;
using cpputils::unique_ref;
@ -37,12 +39,24 @@ optional<CryConfigFile> CryConfigLoader::_loadConfig(const bf::path &filename) {
return none;
}
std::cout << "done" << std::endl;
if (_cipherFromCommandLine != none && config->config()->Cipher() != *_cipherFromCommandLine) {
throw std::runtime_error("Filesystem uses "+config->config()->Cipher()+" cipher and not "+*_cipherFromCommandLine+" as specified.");
}
_checkVersion(*config->config());
_checkCipher(*config->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) {
if (bf::exists(filename)) {
return _loadConfig(filename);

View File

@ -21,6 +21,8 @@ public:
private:
boost::optional<CryConfigFile> _loadConfig(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;
cpputils::SCryptSettings _scryptSettings;

View File

@ -1,87 +1,116 @@
#include "DirEntry.h"
using std::vector;
using std::string;
using blockstore::Key;
namespace cryfs {
namespace fsblobstore {
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;
*(dest+offset) = static_cast<uint8_t>(type);
offset += 1;
std::memcpy(dest+offset, name.c_str(), name.size()+1);
offset += name.size() + 1;
key.ToBinary(dest+offset);
offset += key.BINARY_LENGTH;
*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);
offset += _serializeUint8(dest + offset, static_cast<uint8_t>(type));
offset += _serializeUint32(dest + offset, mode);
offset += _serializeUint32(dest + offset, uid);
offset += _serializeUint32(dest + offset, gid);
offset += _serializeTimeValue(dest + offset, lastAccessTime);
offset += _serializeTimeValue(dest + offset, lastModificationTime);
offset += _serializeTimeValue(dest + offset, lastMetadataChangeTime);
offset += _serializeString(dest + offset, name);
offset += _serializeKey(dest + offset, key);
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) {
// Read type magic number (whether it is a dir or a file)
fspp::Dir::EntryType type =
static_cast<fspp::Dir::EntryType>(*reinterpret_cast<const unsigned char*>(pos));
pos += 1;
size_t namelength = strlen(pos);
std::string name(pos, namelength);
pos += namelength + 1;
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;
fspp::Dir::EntryType type = static_cast<fspp::Dir::EntryType>(_deserializeUint8(&pos));
mode_t mode = _deserializeUint32(&pos);
uid_t uid = _deserializeUint32(&pos);
gid_t gid = _deserializeUint32(&pos);
timespec lastAccessTime = _deserializeTimeValue(&pos);
timespec lastModificationTime = _deserializeTimeValue(&pos);
timespec lastMetadataChangeTime = _deserializeTimeValue(&pos);
string name = _deserializeString(&pos);
Key key = _deserializeKey(&pos);
result->emplace_back(type, name, key, mode, uid, gid, lastAccessTime, lastModificationTime, lastMetadataChangeTime);
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;
}
}
}

View File

@ -34,6 +34,17 @@ namespace cryfs {
void serialize(uint8_t* dest) const;
size_t serializedSize() const;
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;
std::string name;