From 1fe14e8fcfbec25cb6b70df194a82ede4cc0a3e5 Mon Sep 17 00:00:00 2001 From: dec05eba <0xdec05eba@gmail.com> Date: Mon, 14 May 2018 03:07:43 +0200 Subject: Remove user/group classes, user public key/group id directly to database instead --- include/odhtdb/Database.hpp | 21 +++----- include/odhtdb/DatabaseStorage.hpp | 61 +++------------------- include/odhtdb/Group.hpp | 29 ----------- include/odhtdb/LocalUser.hpp | 35 ------------- include/odhtdb/LocalUserEncrypted.hpp | 50 ------------------ include/odhtdb/OwnedMemory.hpp | 3 ++ include/odhtdb/RemoteUser.hpp | 24 --------- include/odhtdb/User.hpp | 39 -------------- src/Database.cpp | 91 ++++++++++++-------------------- src/DatabaseStorage.cpp | 98 +++++++++++++++-------------------- src/Group.cpp | 52 ------------------- src/LocalUser.cpp | 11 ---- src/LocalUserEncrypted.cpp | 27 ---------- src/User.cpp | 37 ------------- tests/main.cpp | 24 ++++----- 15 files changed, 105 insertions(+), 497 deletions(-) delete mode 100644 include/odhtdb/LocalUser.hpp delete mode 100644 include/odhtdb/LocalUserEncrypted.hpp delete mode 100644 include/odhtdb/RemoteUser.hpp delete mode 100644 include/odhtdb/User.hpp delete mode 100644 src/Group.cpp delete mode 100644 src/LocalUser.cpp delete mode 100644 src/LocalUserEncrypted.cpp delete mode 100644 src/User.cpp diff --git a/include/odhtdb/Database.hpp b/include/odhtdb/Database.hpp index 1e4d470..332a784 100644 --- a/include/odhtdb/Database.hpp +++ b/include/odhtdb/Database.hpp @@ -20,11 +20,7 @@ #include namespace odhtdb -{ - class User; - class LocalUser; - class Group; - +{ class CommitCreateException : public std::runtime_error { public: @@ -115,14 +111,15 @@ namespace odhtdb class DatabaseCreateResponse { public: - DatabaseCreateResponse(LocalUser *nodeAdminUser, std::shared_ptr key, std::shared_ptr hash); + DatabaseCreateResponse(std::shared_ptr nodeAdminKeyPair, std::shared_ptr nodeAdminGroupId, std::shared_ptr key, std::shared_ptr hash); - const LocalUser* getNodeAdminUser() const; - // Size of encryption key is odhtdb::KEY_BYTE_SIZE (found in Encryption.hpp) + const std::shared_ptr getNodeAdminKeyPair() const; + const std::shared_ptr getNodeAdminGroupId() const; const std::shared_ptr getNodeEncryptionKey() const; const std::shared_ptr getRequestHash() const; private: - LocalUser *nodeAdminUser; + std::shared_ptr nodeAdminKeyPair; + std::shared_ptr nodeAdminGroupId; std::shared_ptr key; std::shared_ptr hash; }; @@ -171,12 +168,10 @@ namespace odhtdb // Throws DatabaseCreateException on failure. std::unique_ptr create(); - // Throws DatabaseCreateException on failure. - std::unique_ptr create(const Signature::KeyPair &creatorKeyPair); // Throws PermissionDeniedException if user @userToPerformActionWith is not allowed to add data to node - void addData(const DatabaseNode &nodeInfo, const LocalUser *userToPerformActionWith, DataView dataToAdd); + void addData(const DatabaseNode &nodeInfo, const Signature::KeyPair &userToPerformActionWith, DataView dataToAdd); // Throws PermissionDeniedException if user @userToPerformActionWith is not allowed to add user @userToAdd to group @groupToAddUserTo - void addUser(const DatabaseNode &nodeInfo, const LocalUser *userToPerformActionWith, const Signature::PublicKey &userToAddPublicKey, Group *groupToAddUserTo); + void addUser(const DatabaseNode &nodeInfo, const Signature::KeyPair &userToPerformActionWith, const Signature::PublicKey &userToAddPublicKey, const DataView &groupToAddUserTo); ntp::NtpTimestamp getSyncedTimestampUtc() const; private: diff --git a/include/odhtdb/DatabaseStorage.hpp b/include/odhtdb/DatabaseStorage.hpp index 3c4d9bc..0d94c91 100644 --- a/include/odhtdb/DatabaseStorage.hpp +++ b/include/odhtdb/DatabaseStorage.hpp @@ -6,8 +6,7 @@ #include "Signature.hpp" #include "Encryption.hpp" #include "Group.hpp" -#include "LocalUser.hpp" -#include "LocalUserEncrypted.hpp" +#include "Permission.hpp" #include "OwnedMemory.hpp" #include "DatabaseOperation.hpp" #include @@ -24,48 +23,6 @@ namespace odhtdb { class Database; - struct DatabaseStorageObjectDecrypted - { - DatabaseOperation operation; - OwnedMemory data; - }; - - struct DatabaseStorageObject - { - Hash requestHash; - DataView data; - u64 createdTimestamp; // In microseconds - Signature::PublicKey creatorPublicKey; - DatabaseStorageObjectDecrypted decryptedObject; - - DatabaseStorageObject(const Hash &_requestHash, DataView &_data, u64 _timestamp, const Signature::PublicKey &_creatorPublicKey); - }; - - struct DatabaseStorageObjectList - { - Signature::PublicKey creatorPublicKey; - DataView data; - u64 createdTimestamp; // In microseconds - std::vector groups; - std::vector objects; - - DatabaseStorageObjectList(const Signature::PublicKey &_creatorPublicKey) : - creatorPublicKey(_creatorPublicKey) - { - - } - }; - - struct DatabaseStorageQuarantineObject - { - DataView data; - u64 createdTimestamp; // In microseconds - u64 storedTimestamp; // In microseconds - Signature::PublicKey creatorPublicKey; - - DatabaseStorageQuarantineObject(DataView &_data, u64 _timestamp, const Signature::PublicKey &_creatorPublicKey); - }; - class DatabaseStorageException : public std::runtime_error { public: @@ -103,18 +60,9 @@ namespace odhtdb DatabaseStorageWrongPassword(const std::string &errMsg) : DatabaseStorageException(errMsg) {} }; - using DatabaseStorageMap = MapHash; - using DatabaseStorageQuarantineMap = Signature::MapPublicKey>; - const int PASSWORD_SALT_LEN = 16; const int HASHED_PASSWORD_LEN = 32; - struct NodeLocalUser - { - Hash nodeHash; - LocalUser *localUser; - }; - using FetchNodeRawCallbackFunc = std::function; using FetchNodeAddDataRawCallbackFunc = std::function; @@ -131,14 +79,14 @@ namespace odhtdb bool doesDataExist(const Hash &requestHash) const; // Throws DatabaseStorageAlreadyExists if data with hash already exists - void createStorage(const Hash &hash, Group *creatorGroup, u64 timestamp, const void *data, usize size); + void createStorage(const Hash &hash, const Signature::PublicKey &adminPublicKey, const DataView &adminGroupId, u64 timestamp, const void *data, usize size); // Throws DatabaseStorageNotFound if data with @nodeHash hash has not been created yet. // Throws DatabaseStorageAlreadyExists if same data has been added before (hash of @data, in @dataHash) void appendStorage(const Hash &nodeHash, const Hash &dataHash, DatabaseOperation operation, const Signature::PublicKey &creatorPublicKey, u64 timestamp, const void *data, usize size, const DataView &additionalDataView); // Throws DatabaseStorageAlreadyExists if group already exists in node - void addGroup(const Hash &nodeHash, Group *group); + void addGroup(const Hash &nodeHash, const DataView &groupId, const Permission &permissions); void addUserToGroup(const Hash &nodeHash, const Signature::PublicKey &userPublicKey, const DataView &groupId); @@ -148,6 +96,9 @@ namespace odhtdb void fetchNodeRaw(const Hash &nodeHash, FetchNodeRawCallbackFunc callbackFunc); void fetchNodeAddDataRaw(const Hash &nodeHash, FetchNodeAddDataRawCallbackFunc callbackFunc); + bool isUserAllowedToAddDataInNode(const Hash &nodeHash, const Signature::PublicKey &userPublicKey) const; + bool isUserAllowedToAddUserToGroupInNode(const Hash &nodeHash, const Signature::PublicKey &userPublicKey, const DataView &groupToAddUserTo) const; + // Username and key pair has to be unique, returns true on success //bool storeLocalUser(const std::string &username, const Signature::KeyPair &keyPair, const std::string &password); diff --git a/include/odhtdb/Group.hpp b/include/odhtdb/Group.hpp index f8de78e..37058fd 100644 --- a/include/odhtdb/Group.hpp +++ b/include/odhtdb/Group.hpp @@ -1,35 +1,6 @@ #pragma once -#include "types.hpp" -#include "DataView.hpp" -#include "Permission.hpp" -#include "utils.hpp" -#include -#include - namespace odhtdb { - class User; - const int GROUP_ID_LENGTH = 16; - - class Group - { - DISABLE_COPY(Group) - friend class User; - public: - Group(uint8_t id[GROUP_ID_LENGTH], const Permission &permission); - ~Group(); - - DataView getId() const; - const Permission& getPermission() const; - const std::vector& getUsers() const; - private: - void addUser(const User *user); - bool removeUser(const User *user); - private: - uint8_t id[GROUP_ID_LENGTH]; - Permission permission; - std::vector users; - }; } diff --git a/include/odhtdb/LocalUser.hpp b/include/odhtdb/LocalUser.hpp deleted file mode 100644 index b60b516..0000000 --- a/include/odhtdb/LocalUser.hpp +++ /dev/null @@ -1,35 +0,0 @@ -#pragma once - -#include "User.hpp" -#include "types.hpp" - -namespace odhtdb -{ - class LocalUser : public User - { - public: - static LocalUser* create(const Signature::KeyPair &keyPair, Group *group) - { - return new LocalUser(keyPair, group); - } - - const Signature::PublicKey& getPublicKey() const override - { - return keyPair.getPublicKey(); - } - - const Signature::PrivateKey& getPrivateKey() const - { - return keyPair.getPrivateKey(); - } - - const Signature::KeyPair& getKeyPair() const - { - return keyPair; - } - private: - LocalUser(const Signature::KeyPair &_keyPair, Group *group); - private: - Signature::KeyPair keyPair; - }; -} diff --git a/include/odhtdb/LocalUserEncrypted.hpp b/include/odhtdb/LocalUserEncrypted.hpp deleted file mode 100644 index 7919cb3..0000000 --- a/include/odhtdb/LocalUserEncrypted.hpp +++ /dev/null @@ -1,50 +0,0 @@ -#pragma once - -#include "types.hpp" -#include "Encryption.hpp" -#include "Signature.hpp" - -namespace odhtdb -{ - struct EncryptedPrivateKey - { - u8 nonce[ENCRYPTION_NONCE_BYTE_SIZE]; - u8 encryptedPrivateKey[ENCRYPTION_CHECKSUM_BYTE_SIZE + PRIVATE_KEY_NUM_BYTES]; - - EncryptedPrivateKey(); - EncryptedPrivateKey(const EncryptedPrivateKey &other); - - // Throws DecryptionException if password (or salt) is wrong - Signature::PrivateKey decrypt(const DataView &plainPassword, const DataView &salt) const; - }; - - // Local user with encrypted private key - class LocalUserEncrypted - { - public: - static LocalUserEncrypted* create(const Signature::PublicKey &publicKey, const EncryptedPrivateKey &encryptedPrivateKey) - { - return new LocalUserEncrypted(publicKey, encryptedPrivateKey); - } - - const Signature::PublicKey& getPublicKey() const - { - return publicKey; - } - - const EncryptedPrivateKey& getPrivateKey() const - { - return encryptedPrivateKey; - } - private: - LocalUserEncrypted(const Signature::PublicKey &_publicKey, const EncryptedPrivateKey &_encryptedPrivateKey) : - publicKey(_publicKey), - encryptedPrivateKey(_encryptedPrivateKey) - { - - } - private: - Signature::PublicKey publicKey; - EncryptedPrivateKey encryptedPrivateKey; - }; -} diff --git a/include/odhtdb/OwnedMemory.hpp b/include/odhtdb/OwnedMemory.hpp index 5dcdf25..67afe06 100644 --- a/include/odhtdb/OwnedMemory.hpp +++ b/include/odhtdb/OwnedMemory.hpp @@ -1,6 +1,7 @@ #pragma once #include "types.hpp" +#include "DataView.hpp" namespace odhtdb { @@ -16,6 +17,8 @@ namespace odhtdb OwnedMemory(OwnedMemory&) = delete; OwnedMemory& operator = (OwnedMemory&) = delete; + const DataView getView() const { return DataView(data, size); } + void *data; usize size; }; diff --git a/include/odhtdb/RemoteUser.hpp b/include/odhtdb/RemoteUser.hpp deleted file mode 100644 index 2658132..0000000 --- a/include/odhtdb/RemoteUser.hpp +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once - -#include "User.hpp" - -namespace odhtdb -{ - class RemoteUser : public User - { - public: - static RemoteUser* create(const Signature::PublicKey &publicKey, Group *group) - { - return new RemoteUser(publicKey, group); - } - - const Signature::PublicKey& getPublicKey() const override - { - return publicKey; - } - private: - RemoteUser(const Signature::PublicKey &_publicKey, Group *group) : User(User::Type::REMOTE, group), publicKey(_publicKey) {} - private: - Signature::PublicKey publicKey; - }; -} diff --git a/include/odhtdb/User.hpp b/include/odhtdb/User.hpp deleted file mode 100644 index 15e6492..0000000 --- a/include/odhtdb/User.hpp +++ /dev/null @@ -1,39 +0,0 @@ -#pragma once - -#include "Signature.hpp" -#include "types.hpp" -#include "Permission.hpp" -#include -#include - -namespace odhtdb -{ - class Group; - class DatabaseStorage; - - class User - { - friend class DatabaseStorage; - public: - enum class Type : u8 - { - LOCAL, - REMOTE - }; - - virtual ~User(); - - virtual void addToGroup(Group *group); - - Type getType() const { return type; } - virtual const std::vector& getGroups() const { return groups; } - virtual const Signature::PublicKey& getPublicKey() const = 0; - - virtual bool isAllowedToPerformAction(PermissionType action) const; - protected: - User(Type type, Group *group); - protected: - Type type; - std::vector groups; - }; -} diff --git a/src/Database.cpp b/src/Database.cpp index 88ac8e4..9985bb9 100644 --- a/src/Database.cpp +++ b/src/Database.cpp @@ -1,7 +1,5 @@ #include "../include/odhtdb/Database.hpp" #include "../include/odhtdb/Group.hpp" -#include "../include/odhtdb/LocalUser.hpp" -#include "../include/odhtdb/RemoteUser.hpp" #include "../include/odhtdb/Encryption.hpp" #include "../include/odhtdb/DhtKey.hpp" #include "../include/odhtdb/bin2hex.hpp" @@ -61,19 +59,25 @@ namespace odhtdb return DataView(result, allocationSize); } - DatabaseCreateResponse::DatabaseCreateResponse(LocalUser *_nodeAdminUser, shared_ptr _key, shared_ptr _hash) : - nodeAdminUser(_nodeAdminUser), + DatabaseCreateResponse::DatabaseCreateResponse(std::shared_ptr _nodeAdminKeyPair, std::shared_ptr _nodeAdminGroupId, shared_ptr _key, shared_ptr _hash) : + nodeAdminKeyPair(_nodeAdminKeyPair), + nodeAdminGroupId(_nodeAdminGroupId), key(_key), hash(_hash) { } - const LocalUser* DatabaseCreateResponse::getNodeAdminUser() const + const shared_ptr DatabaseCreateResponse::getNodeAdminKeyPair() const { - return nodeAdminUser; + return nodeAdminKeyPair; } - + + const shared_ptr DatabaseCreateResponse::getNodeAdminGroupId() const + { + return nodeAdminGroupId; + } + const shared_ptr DatabaseCreateResponse::getNodeEncryptionKey() const { return key; @@ -262,9 +266,6 @@ namespace odhtdb if(!ok) Log::warn("Failed to put request to get old data"); }); - - //node.listen(CREATE_DATA_HASH, bind(&Database::listenCreateData, this, _1)); - //node.listen(ADD_DATA_HASH, bind(&Database::listenAddData, this, _1)); } void Database::stopSeeding(const Hash &nodeHash) @@ -285,27 +286,22 @@ namespace odhtdb { databaseStorage.loadNode(nodeHash); } - - unique_ptr Database::create() - { - return create(Signature::KeyPair()); - } - unique_ptr Database::create(const Signature::KeyPair &creatorKeyPair) + unique_ptr Database::create() { + shared_ptr creatorKeyPair = make_shared(); + // TODO: Should this be declared static? is there any difference in behavior/performance? boost::uuids::random_generator uuidGen; auto adminGroupId = uuidGen(); assert(adminGroupId.size() == GROUP_ID_LENGTH); - auto adminGroup = new Group(adminGroupId.data, ADMIN_PERMISSION); - LocalUser *nodeAdminUser = LocalUser::create(creatorKeyPair, adminGroup); // Header sibs::SafeSerializer serializer; serializer.add(DATABASE_CREATE_PACKET_STRUCTURE_VERSION); // Packet structure version u64 timestampCombined = getSyncedTimestampUtc().getCombined(); serializer.add(timestampCombined); - serializer.add((u8*)nodeAdminUser->getPublicKey().getData(), PUBLIC_KEY_NUM_BYTES); + serializer.add((u8*)creatorKeyPair->getPublicKey().getData(), PUBLIC_KEY_NUM_BYTES); serializer.add(adminGroupId.data, adminGroupId.size()); try @@ -316,7 +312,7 @@ namespace odhtdb shared_ptr hashRequestKey = make_shared(serializer.getBuffer().data(), serializer.getBuffer().size()); databaseStorage.setNodeDecryptionKey(*hashRequestKey, DataView(encryptionKey->data, encryptionKey->size)); - databaseStorage.createStorage(*hashRequestKey, adminGroup, timestampCombined, (const u8*)serializer.getBuffer().data(), serializer.getBuffer().size()); + databaseStorage.createStorage(*hashRequestKey, creatorKeyPair->getPublicKey(), DataView(adminGroupId.data, adminGroupId.size()), timestampCombined, (const u8*)serializer.getBuffer().data(), serializer.getBuffer().size()); DhtKey dhtKey(*hashRequestKey); Value createDataValue(move(serializer.getBuffer())); @@ -327,7 +323,9 @@ namespace odhtdb Log::warn("Failed to put: %s, what to do?", "Database::create"); }); - return make_unique(nodeAdminUser, encryptionKey, hashRequestKey); + shared_ptr adminGroupIdResponse = make_shared(new u8[GROUP_ID_LENGTH], GROUP_ID_LENGTH); + memcpy(adminGroupIdResponse->data, adminGroupId.data, GROUP_ID_LENGTH); + return make_unique(creatorKeyPair, adminGroupIdResponse, encryptionKey, hashRequestKey); } catch (EncryptionException &e) { @@ -335,9 +333,9 @@ namespace odhtdb } } - void Database::addData(const DatabaseNode &nodeInfo, const LocalUser *userToPerformActionWith, DataView dataToAdd) + void Database::addData(const DatabaseNode &nodeInfo, const Signature::KeyPair &userToPerformActionWith, DataView dataToAdd) { - if(!userToPerformActionWith->isAllowedToPerformAction(PermissionType::ADD_DATA)) + if(!databaseStorage.isUserAllowedToAddDataInNode(*nodeInfo.getRequestHash(), userToPerformActionWith.getPublicKey())) { // TODO: User might have permission to perform operation, but we haven't got the packet that adds user to the group with the permission, // or we haven't received the packet that modifies group with the permission to perform the operation. @@ -345,7 +343,7 @@ namespace odhtdb // and remote peers would accept our request to perform operation if they haven't received the operation that removes the user from the group. // How to handle this? string errMsg = "User "; - errMsg += userToPerformActionWith->getPublicKey().toString(); + errMsg += userToPerformActionWith.getPublicKey().toString(); errMsg += " is not allowed to perform the operation: ADD_USER"; throw PermissionDeniedException(errMsg); } @@ -359,11 +357,11 @@ namespace odhtdb DataView encryptionKey(nodeInfo.getNodeEncryptionKey()->data, ENCRYPTION_KEY_BYTE_SIZE); Encryption encryptedBody(dataToAdd, DataView(), encryptionKey); DataView requestData = combine(serializer, encryptedBody); - string signedRequestData = userToPerformActionWith->getPrivateKey().sign(requestData); - DataView stagedAddObject = combine(userToPerformActionWith->getPublicKey(), signedRequestData); + string signedRequestData = userToPerformActionWith.getPrivateKey().sign(requestData); + DataView stagedAddObject = combine(userToPerformActionWith.getPublicKey(), signedRequestData); Hash requestDataHash(stagedAddObject.data, stagedAddObject.size); DataView encryptedDataView((char*)requestData.data + serializer.getBuffer().size(), requestData.size - serializer.getBuffer().size()); - databaseStorage.appendStorage(*nodeInfo.getRequestHash(), requestDataHash, DatabaseOperation::ADD_DATA, userToPerformActionWith->getPublicKey(), timestampCombined, (u8*)stagedAddObject.data, stagedAddObject.size, encryptedDataView); + databaseStorage.appendStorage(*nodeInfo.getRequestHash(), requestDataHash, DatabaseOperation::ADD_DATA, userToPerformActionWith.getPublicKey(), timestampCombined, (u8*)stagedAddObject.data, stagedAddObject.size, encryptedDataView); delete[] (char*)requestData.data; DhtKey dhtKey(requestDataHash); @@ -377,32 +375,14 @@ namespace odhtdb }); } - Group* getGroupWithRightsToAddUserToGroup(const vector &groups, Group *groupToAddUserTo) - { - for(auto group : groups) - { - const auto &groupPermission = group->getPermission(); - if(groupPermission.getFlag(PermissionType::ADD_USER_HIGHER_LEVEL) && groupPermission.getPermissionLevel() < groupToAddUserTo->getPermission().getPermissionLevel()) - { - return group; - } - else if(groupPermission.getFlag(PermissionType::ADD_USER_SAME_LEVEL) && groupPermission.getPermissionLevel() == groupToAddUserTo->getPermission().getPermissionLevel()) - { - return group; - } - } - return nullptr; - } - - void Database::addUser(const DatabaseNode &nodeInfo, const LocalUser *userToPerformActionWith, const Signature::PublicKey &userToAddPublicKey, Group *groupToAddUserTo) + void Database::addUser(const DatabaseNode &nodeInfo, const Signature::KeyPair &userToPerformActionWith, const Signature::PublicKey &userToAddPublicKey, const DataView &groupToAddUserTo) { - auto groupWithAddUserRights = getGroupWithRightsToAddUserToGroup(userToPerformActionWith->getGroups(), groupToAddUserTo); - if(!groupWithAddUserRights) + if(!databaseStorage.isUserAllowedToAddUserToGroupInNode(*nodeInfo.getRequestHash(), userToPerformActionWith.getPublicKey(), groupToAddUserTo)) { string errMsg = "The user "; - errMsg += userToPerformActionWith->getPublicKey().toString(); + errMsg += userToPerformActionWith.getPublicKey().toString(); errMsg += " does not belong to any group that is allowed to add an user to the group "; - errMsg += bin2hex((const char*)groupToAddUserTo->getId().data, groupToAddUserTo->getId().size).c_str(); + errMsg += bin2hex((const char*)groupToAddUserTo.data, groupToAddUserTo.size).c_str(); throw PermissionDeniedException(errMsg); } @@ -413,7 +393,7 @@ namespace odhtdb serializer.add(DatabaseOperation::ADD_USER); usize additionalDataOffset = serializer.getBuffer().size(); serializer.add((u8*)userToAddPublicKey.getData(), PUBLIC_KEY_NUM_BYTES); - serializer.add((uint8_t*)groupToAddUserTo->getId().data, groupToAddUserTo->getId().size); + serializer.add((uint8_t*)groupToAddUserTo.data, groupToAddUserTo.size); // TODO: Should this be declared static? is there any difference in behavior/performance? boost::uuids::random_generator uuidGen; @@ -422,11 +402,11 @@ namespace odhtdb serializer.add(padding.data, padding.size()); DataView requestData { serializer.getBuffer().data(), serializer.getBuffer().size() }; - string signedRequestData = userToPerformActionWith->getPrivateKey().sign(requestData); - DataView stagedAddObject = combine(userToPerformActionWith->getPublicKey(), signedRequestData); + string signedRequestData = userToPerformActionWith.getPrivateKey().sign(requestData); + DataView stagedAddObject = combine(userToPerformActionWith.getPublicKey(), signedRequestData); Hash requestDataHash(stagedAddObject.data, stagedAddObject.size); DataView additionalDataView((void*)(static_cast(requestData.data) + additionalDataOffset), requestData.size - additionalDataOffset); - databaseStorage.appendStorage(*nodeInfo.getRequestHash(), requestDataHash, DatabaseOperation::ADD_USER, userToPerformActionWith->getPublicKey(), timestampCombined, (u8*)stagedAddObject.data, stagedAddObject.size, additionalDataView); + databaseStorage.appendStorage(*nodeInfo.getRequestHash(), requestDataHash, DatabaseOperation::ADD_USER, userToPerformActionWith.getPublicKey(), timestampCombined, (u8*)stagedAddObject.data, stagedAddObject.size, additionalDataView); DhtKey dhtKey(requestDataHash); Value addDataValue((u8*)stagedAddObject.data, stagedAddObject.size); @@ -492,10 +472,7 @@ namespace odhtdb if(deserializer.getSize() < ENCRYPTION_NONCE_BYTE_SIZE) throw sibs::DeserializeException("Unsigned encrypted body is too small (unable to extract nonce)"); - auto adminGroup = new Group(adminGroupId, ADMIN_PERMISSION); - // TODO: Username is encrypted, we dont know it... unless we have encryption key, in which case we should modify the user name and set it - auto creatorUser = RemoteUser::create(userPublicKey, adminGroup); - databaseStorage.createStorage(hash, adminGroup, creationDate, value->data.data(), value->data.size()); + databaseStorage.createStorage(hash, userPublicKey, DataView(adminGroupId, GROUP_ID_LENGTH), creationDate, value->data.data(), value->data.size()); } void Database::deserializeAddRequest(const shared_ptr &value, const Hash &requestDataHash, const std::shared_ptr &nodeHash, const shared_ptr encryptionKey) diff --git a/src/DatabaseStorage.cpp b/src/DatabaseStorage.cpp index 501bd35..d7f42bb 100644 --- a/src/DatabaseStorage.cpp +++ b/src/DatabaseStorage.cpp @@ -1,7 +1,4 @@ #include "../include/odhtdb/DatabaseStorage.hpp" -#include "../include/odhtdb/RemoteUser.hpp" -#include "../include/odhtdb/LocalUser.hpp" -#include "../include/odhtdb/LocalUserEncrypted.hpp" #include "../include/odhtdb/Group.hpp" #include "../include/odhtdb/FileUtils.hpp" #include "../include/odhtdb/bin2hex.hpp" @@ -28,22 +25,6 @@ namespace odhtdb const u64 QUARANTINE_STORAGE_TIME_MICROSECONDS = 60 * 1.0e6; const u16 STORAGE_VERSION = 3; - - DatabaseStorageObject::DatabaseStorageObject(const Hash &_requestHash, DataView &_data, u64 _timestamp, const Signature::PublicKey &_creatorPublicKey) : - requestHash(_requestHash), - data(_data), - createdTimestamp(_timestamp), - creatorPublicKey(_creatorPublicKey) - { - - } - - DatabaseStorageQuarantineObject::DatabaseStorageQuarantineObject(DataView &_data, u64 _timestamp, const Signature::PublicKey &_creatorPublicKey) : - data(_data), createdTimestamp(_timestamp), creatorPublicKey(_creatorPublicKey) - { - auto time = chrono::high_resolution_clock::now().time_since_epoch(); - storedTimestamp = chrono::duration_cast(time).count(); - } static void sqlite_exec_checked(sqlite3 *db, const char *sql) { @@ -431,11 +412,8 @@ namespace odhtdb return query.next(); } - void DatabaseStorage::createStorage(const Hash &hash, Group *creatorGroup, u64 timestamp, const void *data, usize size) + void DatabaseStorage::createStorage(const Hash &hash, const Signature::PublicKey &adminPublicKey, const DataView &adminGroupId, u64 timestamp, const void *data, usize size) { - assert(creatorGroup->getUsers().size() == 1); - User *creator = (User*)creatorGroup->getUsers()[0]; - sqlite3_exec(sqliteDb, "BEGIN", 0, 0, 0); { sqlite3_reset(insertNodeStmt); @@ -448,15 +426,15 @@ namespace odhtdb rc = sqlite3_bind_int64(insertNodeStmt, 2, timestamp); bindCheckError(rc); - rc = sqlite3_bind_blob(insertNodeStmt, 3, creator->getPublicKey().getData(), creator->getPublicKey().getSize(), SQLITE_STATIC); + rc = sqlite3_bind_blob(insertNodeStmt, 3, adminPublicKey.getData(), adminPublicKey.getSize(), SQLITE_STATIC); bindCheckError(rc); - rc = sqlite3_bind_blob(insertNodeStmt, 4, creatorGroup->getId().data, GROUP_ID_LENGTH, SQLITE_STATIC); + rc = sqlite3_bind_blob(insertNodeStmt, 4, adminGroupId.data, GROUP_ID_LENGTH, SQLITE_STATIC); bindCheckError(rc); sqlite_step_rollback_on_failure(sqliteDb, insertNodeStmt, "insert data into Node"); - addGroup(hash, creatorGroup); - addUser(hash, creator->getPublicKey(), creatorGroup->getId()); + addGroup(hash, adminGroupId, ADMIN_PERMISSION); + addUser(hash, adminPublicKey, adminGroupId); } { sqlite3_reset(insertNodeRawStmt); @@ -475,7 +453,7 @@ namespace odhtdb auto nodeDecryptionKeyResult = getNodeDecryptionKey(hash); if(nodeDecryptionKeyResult.first) - decryptNodeData(hash, nodeDecryptionKeyResult.second, &creator->getPublicKey(), creatorGroup->getId(), timestamp); + decryptNodeData(hash, nodeDecryptionKeyResult.second, &adminPublicKey, adminGroupId, timestamp); } void DatabaseStorage::appendStorage(const Hash &nodeHash, const Hash &dataHash, DatabaseOperation operation, const Signature::PublicKey &creatorPublicKey, u64 timestamp, const void *data, usize size, const DataView &additionalDataView) @@ -591,7 +569,7 @@ namespace odhtdb sqlite3_exec(sqliteDb, "COMMIT", 0, 0, 0); } - void DatabaseStorage::addGroup(const Hash &nodeHash, Group *group) + void DatabaseStorage::addGroup(const Hash &nodeHash, const DataView &groupId, const Permission &permissions) { sqlite3_reset(insertGroupStmt); sqlite3_clear_bindings(insertGroupStmt); @@ -600,17 +578,17 @@ namespace odhtdb rc = sqlite3_bind_blob(insertGroupStmt, 1, nodeHash.getData(), nodeHash.getSize(), SQLITE_STATIC); bindCheckError(rc); - rc = sqlite3_bind_blob(insertGroupStmt, 2, group->getId().data, GROUP_ID_LENGTH, SQLITE_STATIC); + rc = sqlite3_bind_blob(insertGroupStmt, 2, groupId.data, GROUP_ID_LENGTH, SQLITE_STATIC); bindCheckError(rc); - rc = sqlite3_bind_int(insertGroupStmt, 3, group->getPermission().getPermissionLevel()); + rc = sqlite3_bind_int(insertGroupStmt, 3, permissions.getPermissionLevel()); bindCheckError(rc); - rc = sqlite3_bind_int64(insertGroupStmt, 4, group->getPermission().getPermissionFlags()); + rc = sqlite3_bind_int64(insertGroupStmt, 4, permissions.getPermissionFlags()); bindCheckError(rc); sqlite_step_rollback_on_failure(sqliteDb, insertGroupStmt, "insert data into NodeGroup"); - Log::debug("Created group %s in node %s", bin2hex((const char*)group->getId().data, GROUP_ID_LENGTH).c_str(), nodeHash.toString().c_str()); + Log::debug("Created group %s in node %s", bin2hex((const char*)groupId.data, GROUP_ID_LENGTH).c_str(), nodeHash.toString().c_str()); } void DatabaseStorage::addUserToGroup(const Hash &nodeHash, const Signature::PublicKey &userPublicKey, const DataView &groupId) @@ -669,6 +647,36 @@ namespace odhtdb callbackFunc(data); } } + + bool DatabaseStorage::isUserAllowedToAddDataInNode(const Hash &nodeHash, const Signature::PublicKey &userPublicKey) const + { + SqlQuery queryCreatorGroupWithRightsToAddData(sqliteDb, + "SELECT nodeGroup.rowid FROM NodeUserGroupAssoc AS userGroupAssoc" + " INNER JOIN NodeGroup AS nodeGroup ON nodeGroup.groupId = userGroupAssoc.groupId" + " WHERE userGroupAssoc.node = ? AND userGroupAssoc.userPublicKey = ? AND (nodeGroup.permissionFlags & ?) != 0", + { DataView(nodeHash.getData(), nodeHash.getSize()), DataView((void*)userPublicKey.getData(), userPublicKey.getSize()), (i64)PermissionType::ADD_DATA }); + return queryCreatorGroupWithRightsToAddData.next(); + } + + bool DatabaseStorage::isUserAllowedToAddUserToGroupInNode(const Hash &nodeHash, const Signature::PublicKey &userPublicKey, const DataView &groupToAddUserTo) const + { + SqlQuery queryGroupToAdd(sqliteDb, "SELECT permissionLevel FROM NodeGroup WHERE groupId = ?", { groupToAddUserTo }); + if(!queryGroupToAdd.next()) + { + // TODO: Add to quarantine? + Log::error("There is no group with id %s in node %s", bin2hex((const char*)groupToAddUserTo.data, groupToAddUserTo.size).c_str(), nodeHash.toString().c_str()); + return false; + } + + int groupToAddPermissionLevel = queryGroupToAdd.getInt(0); + + SqlQuery queryCreatorGroupWithRightsToAddUserToGroup(sqliteDb, + "SELECT nodeGroup.rowid FROM NodeUserGroupAssoc AS userGroupAssoc" + " INNER JOIN NodeGroup AS nodeGroup ON nodeGroup.groupId = userGroupAssoc.groupId" + " WHERE userGroupAssoc.node = ? AND userGroupAssoc.userPublicKey = ? AND (nodeGroup.permissionLevel = ? AND ((nodeGroup.permissionFlags & ?) != 0) OR (nodeGroup.permissionLevel > ? AND (nodeGroup.permissionFlags & ?) != 0))", + { DataView(nodeHash.getData(), nodeHash.getSize()), DataView((void*)userPublicKey.getData(), userPublicKey.getSize()), groupToAddPermissionLevel, (i64)PermissionType::ADD_USER_SAME_LEVEL, groupToAddPermissionLevel, (i64)PermissionType::ADD_USER_HIGHER_LEVEL }); + return queryCreatorGroupWithRightsToAddUserToGroup.next(); + } #if 0 bool DatabaseStorage::storeLocalUser(const string &username, const Signature::KeyPair &keyPair, const string &password) { @@ -943,12 +951,7 @@ namespace odhtdb bool DatabaseStorage::decryptNodeAddData(i64 rowId, const Hash &nodeHash, const Hash &dataHash, u64 timestamp, const Signature::PublicKey *creatorPublicKey, const DataView &encryptedData, const shared_ptr decryptionKey) { - SqlQuery queryCreatorGroupWithRightsToAddData(sqliteDb, - "SELECT nodeGroup.rowid FROM NodeUserGroupAssoc AS userGroupAssoc" - " INNER JOIN NodeGroup AS nodeGroup ON nodeGroup.groupId = userGroupAssoc.groupId" - " WHERE userGroupAssoc.node = ? AND userGroupAssoc.userPublicKey = ? AND (nodeGroup.permissionFlags & ?) != 0", - { DataView(nodeHash.getData(), nodeHash.getSize()), DataView((void*)creatorPublicKey->getData(), creatorPublicKey->getSize()), (i64)PermissionType::ADD_DATA }); - if(!queryCreatorGroupWithRightsToAddData.next()) + if(!isUserAllowedToAddDataInNode(nodeHash, *creatorPublicKey)) { // TODO: User might have permission to perform operation, but we haven't got the packet that adds user to the group with the permission, // or we haven't received the packet that modifies group with the permission to perform the operation. @@ -976,22 +979,7 @@ namespace odhtdb bool DatabaseStorage::decryptNodeAddUser(i64 rowId, const Hash &nodeHash, const Hash &dataHash, u64 timestamp, const Signature::PublicKey *creatorPublicKey, const Signature::PublicKey *userToAddPublicKey, const DataView &groupToAddUserTo, const shared_ptr decryptionKey) { - SqlQuery queryGroupToAdd(sqliteDb, "SELECT permissionLevel FROM NodeGroup WHERE groupId = ?", { groupToAddUserTo }); - if(!queryGroupToAdd.next()) - { - // TODO: Add to quarantine? - Log::error("There is no group with id %s in node %s", bin2hex((const char*)groupToAddUserTo.data, groupToAddUserTo.size).c_str(), nodeHash.toString().c_str()); - return false; - } - - int groupToAddPermissionLevel = queryGroupToAdd.getInt(0); - - SqlQuery queryCreatorGroupWithRightsToAddUserToGroup(sqliteDb, - "SELECT nodeGroup.rowid FROM NodeUserGroupAssoc AS userGroupAssoc" - " INNER JOIN NodeGroup AS nodeGroup ON nodeGroup.groupId = userGroupAssoc.groupId" - " WHERE userGroupAssoc.node = ? AND userGroupAssoc.userPublicKey = ? AND (nodeGroup.permissionLevel = ? AND ((nodeGroup.permissionFlags & ?) != 0) OR (nodeGroup.permissionLevel > ? AND (nodeGroup.permissionFlags & ?) != 0))", - { DataView(nodeHash.getData(), nodeHash.getSize()), DataView((void*)creatorPublicKey->getData(), creatorPublicKey->getSize()), groupToAddPermissionLevel, (i64)PermissionType::ADD_USER_SAME_LEVEL, groupToAddPermissionLevel, (i64)PermissionType::ADD_USER_HIGHER_LEVEL }); - if(!queryCreatorGroupWithRightsToAddUserToGroup.next()) + if(!isUserAllowedToAddUserToGroupInNode(nodeHash, *creatorPublicKey, groupToAddUserTo)) { // TODO: User might have permission to perform operation, but we haven't got the packet that adds user to the group with the permission, // or we haven't received the packet that modifies group with the permission to perform the operation. diff --git a/src/Group.cpp b/src/Group.cpp deleted file mode 100644 index 9db3e4e..0000000 --- a/src/Group.cpp +++ /dev/null @@ -1,52 +0,0 @@ -#include "../include/odhtdb/Group.hpp" -#include "../include/odhtdb/User.hpp" -#include - -using namespace std; - -namespace odhtdb -{ - Group::Group(uint8_t _id[GROUP_ID_LENGTH], const Permission &_permission) : - permission(_permission) - { - memcpy(id, _id, GROUP_ID_LENGTH); - } - - Group::~Group() - { - - } - - void Group::addUser(const User *user) - { - users.push_back(user); - } - - bool Group::removeUser(const User *user) - { - for(std::vector::iterator it = users.begin(); it != users.end(); ++it) - { - if(*it == user) - { - users.erase(it); - return true; - } - } - return false; - } - - DataView Group::getId() const - { - return { (void*)id, GROUP_ID_LENGTH }; - } - - const Permission& Group::getPermission() const - { - return permission; - } - - const vector& Group::getUsers() const - { - return users; - } -} diff --git a/src/LocalUser.cpp b/src/LocalUser.cpp deleted file mode 100644 index 950c953..0000000 --- a/src/LocalUser.cpp +++ /dev/null @@ -1,11 +0,0 @@ -#include "../include/odhtdb/LocalUser.hpp" - -namespace odhtdb -{ - LocalUser::LocalUser(const Signature::KeyPair &_keyPair, Group *group) : - User(User::Type::LOCAL, group), - keyPair(_keyPair) - { - - } -} diff --git a/src/LocalUserEncrypted.cpp b/src/LocalUserEncrypted.cpp deleted file mode 100644 index a414c89..0000000 --- a/src/LocalUserEncrypted.cpp +++ /dev/null @@ -1,27 +0,0 @@ -#include "../include/odhtdb/LocalUserEncrypted.hpp" -#include "../include/odhtdb/PasswordHash.hpp" -#include - -namespace odhtdb -{ - EncryptedPrivateKey::EncryptedPrivateKey() - { - memset(nonce, 0, ENCRYPTION_NONCE_BYTE_SIZE); - memset(encryptedPrivateKey, 0, ENCRYPTION_CHECKSUM_BYTE_SIZE + PRIVATE_KEY_NUM_BYTES); - } - - EncryptedPrivateKey::EncryptedPrivateKey(const EncryptedPrivateKey &other) - { - memcpy(nonce, other.nonce, ENCRYPTION_NONCE_BYTE_SIZE); - memcpy(encryptedPrivateKey, other.encryptedPrivateKey, ENCRYPTION_CHECKSUM_BYTE_SIZE + PRIVATE_KEY_NUM_BYTES); - } - - Signature::PrivateKey EncryptedPrivateKey::decrypt(const DataView &plainPassword, const DataView &salt) const - { - OwnedMemory hashedPassword = hashPassword(plainPassword, salt); - Decryption decryptedPrivateKey(DataView((void*)encryptedPrivateKey, ENCRYPTION_CHECKSUM_BYTE_SIZE + PRIVATE_KEY_NUM_BYTES), - DataView((void*)nonce, ENCRYPTION_NONCE_BYTE_SIZE), - DataView(hashedPassword.data, hashedPassword.size)); - return { (const char*)decryptedPrivateKey.getDecryptedText().data, decryptedPrivateKey.getDecryptedText().size }; - } -} diff --git a/src/User.cpp b/src/User.cpp deleted file mode 100644 index 559f8db..0000000 --- a/src/User.cpp +++ /dev/null @@ -1,37 +0,0 @@ -#include "../include/odhtdb/User.hpp" -#include "../include/odhtdb/Group.hpp" - -namespace odhtdb -{ - User::User(Type _type, Group *group) : type(_type) - { - addToGroup(group); - } - - User::~User() - { - for(Group *group : groups) - { - group->removeUser(this); - } - } - - void User::addToGroup(Group *group) - { - if(group) - { - groups.emplace_back(group); - group->addUser(this); - } - } - - bool User::isAllowedToPerformAction(PermissionType action) const - { - for(Group *group : getGroups()) - { - if(group->getPermission().getFlag(action)) - return true; - } - return false; - } -} diff --git a/tests/main.cpp b/tests/main.cpp index 6e1a72f..0174384 100644 --- a/tests/main.cpp +++ b/tests/main.cpp @@ -2,7 +2,6 @@ #include "../include/odhtdb/Log.hpp" #include "../include/odhtdb/Database.hpp" #include "../include/odhtdb/Group.hpp" -#include "../include/odhtdb/LocalUser.hpp" #include "../include/odhtdb/Encryption.hpp" #include "../include/odhtdb/Hash.hpp" #include "../include/odhtdb/hex2bin.hpp" @@ -49,19 +48,19 @@ void testHash() Log::debug("hash of 'odhtdb' is: a7b30ec8ab92de60e551b26bb8f78d315697f84dd7f5549a143477e095ec934f"); } -void testSignData(LocalUser *localUser) +void testSignData(const Signature::KeyPair &localUserKeyPair) { - std::string publicKeyStr = localUser->getPublicKey().toString(); + std::string publicKeyStr = localUserKeyPair.getPublicKey().toString(); Log::debug("Local user public key: %s", publicKeyStr.c_str()); - std::string privateKeyStr = localUser->getPrivateKey().toString(); + std::string privateKeyStr = localUserKeyPair.getPrivateKey().toString(); Log::debug("Local user private key: %s", privateKeyStr.c_str()); string expectedUnsignedData = "hello, world!"; - string signedData = localUser->getPrivateKey().sign(DataView((void*)expectedUnsignedData.data(), expectedUnsignedData.size())); + string signedData = localUserKeyPair.getPrivateKey().sign(DataView((void*)expectedUnsignedData.data(), expectedUnsignedData.size())); assertEquals(SIGNED_HASH_SIZE + expectedUnsignedData.size(), signedData.size()); - string unsignedData = localUser->getPublicKey().unsign(DataView((void*)signedData.data(), signedData.size())); + string unsignedData = localUserKeyPair.getPublicKey().unsign(DataView((void*)signedData.data(), signedData.size())); assertEquals(expectedUnsignedData, unsignedData); try @@ -180,8 +179,8 @@ int main() DatabaseNode databaseNode; { - LocalUser *localUser = LocalUser::create(Signature::KeyPair(), nullptr); - testSignData(localUser); + Signature::KeyPair localUserKeyPair; + testSignData(localUserKeyPair); // TODO: Setup local bootstrap node for tests Database database("bootstrap.ring.cx", 4222, storagePath, callbackFuncs); @@ -189,11 +188,10 @@ int main() auto databaseCreateResponse = database.create(); databaseNode = { databaseCreateResponse->getNodeEncryptionKey(), databaseCreateResponse->getRequestHash() }; - auto adminUser = (LocalUser*)databaseCreateResponse->getNodeAdminUser(); - database.addData(databaseNode, adminUser, DataView{ (void*)"hello, world!", 13 }); - database.addUser(databaseNode, adminUser, localUser->getPublicKey(), adminUser->getGroups()[0]); - localUser->addToGroup(adminUser->getGroups()[0]); - database.addData(databaseNode, localUser, DataView{ (void*)"hello, aaald!", 13 }); + auto adminUserKey = databaseCreateResponse->getNodeAdminKeyPair(); + database.addData(databaseNode, *adminUserKey, DataView{ (void*)"hello, world!", 13 }); + database.addUser(databaseNode, *adminUserKey, localUserKeyPair.getPublicKey(), databaseCreateResponse->getNodeAdminGroupId()->getView()); + database.addData(databaseNode, localUserKeyPair, DataView{ (void*)"hello, aaald!", 13 }); database.seed(databaseNode); this_thread::sleep_for(chrono::seconds(3)); -- cgit v1.2.3