From 166e132873fccf62327d2190fe1d827d89a5db63 Mon Sep 17 00:00:00 2001 From: dec05eba <0xdec05eba@gmail.com> Date: Fri, 27 Apr 2018 09:21:27 +0200 Subject: Change local storage to fit dchat better --- include/odhtdb/Database.hpp | 2 ++ include/odhtdb/DatabaseStorage.hpp | 47 +++++++++++++++++++++----- include/odhtdb/Group.hpp | 1 + include/odhtdb/LocalUser.hpp | 5 +++ include/odhtdb/User.hpp | 2 +- src/Database.cpp | 7 +++- src/DatabaseStorage.cpp | 68 +++++++++++++++++++++++++++++++++++--- src/Group.cpp | 13 ++++++++ src/User.cpp | 8 +++++ 9 files changed, 139 insertions(+), 14 deletions(-) diff --git a/include/odhtdb/Database.hpp b/include/odhtdb/Database.hpp index 3e4a393..9aff90e 100644 --- a/include/odhtdb/Database.hpp +++ b/include/odhtdb/Database.hpp @@ -140,6 +140,8 @@ namespace odhtdb void seed(const DatabaseNode &nodeToSeed); // Throws DatabaseCreateException on failure. std::unique_ptr create(const std::string &ownerName, const std::string &nodeName); + // Throws DatabaseCreateException on failure. + std::unique_ptr create(const std::string &ownerName, const Signature::KeyPair &keyPair, const std::string &nodeName); // Throws DatabaseAddException on failure void addData(const DatabaseNode &nodeInfo, LocalUser *userToPerformActionWith, DataView dataToAdd); // Throws PermissionDeniedException if user @userToPerformActionWith is not allowed to add user @userToAdd to group @groupToAddUserTo diff --git a/include/odhtdb/DatabaseStorage.hpp b/include/odhtdb/DatabaseStorage.hpp index f3c3087..34e523e 100644 --- a/include/odhtdb/DatabaseStorage.hpp +++ b/include/odhtdb/DatabaseStorage.hpp @@ -43,22 +43,41 @@ namespace odhtdb DatabaseStorageQuarantineObject(DataView &_data, u64 _timestamp, const Signature::PublicKey &_creatorPublicKey); }; - class DatabaseStorageAlreadyExists : public std::runtime_error + class DatabaseStorageException : public std::runtime_error { public: - DatabaseStorageAlreadyExists(const std::string &errMsg) : std::runtime_error(errMsg) {} + DatabaseStorageException(const std::string &errMsg) : std::runtime_error(errMsg) {} + virtual ~DatabaseStorageException() {} }; - class DatabaseStorageNotFound : public std::runtime_error + class DatabaseStorageAlreadyExists : public DatabaseStorageException { public: - DatabaseStorageNotFound(const std::string &errMsg) : std::runtime_error(errMsg) {} + DatabaseStorageAlreadyExists(const std::string &errMsg) : DatabaseStorageException(errMsg) {} }; - class DatabaseStorageCorrupt : public std::runtime_error + class DatabaseStorageNotFound : public DatabaseStorageException { public: - DatabaseStorageCorrupt(const std::string &errMsg) : std::runtime_error(errMsg) {} + DatabaseStorageNotFound(const std::string &errMsg) : DatabaseStorageException(errMsg) {} + }; + + class DatabaseStorageCorrupt : public DatabaseStorageException + { + public: + DatabaseStorageCorrupt(const std::string &errMsg) : DatabaseStorageException(errMsg) {} + }; + + class DatabaseStorageNoSuchLocalStorageUser : public DatabaseStorageException + { + public: + DatabaseStorageNoSuchLocalStorageUser(const std::string &errMsg) : DatabaseStorageException(errMsg) {} + }; + + class DatabaseStorageWrongPassword : public DatabaseStorageException + { + public: + DatabaseStorageWrongPassword(const std::string &errMsg) : DatabaseStorageException(errMsg) {} }; using DatabaseStorageMap = MapHash; @@ -67,6 +86,8 @@ namespace odhtdb const int PASSWORD_SALT_LEN = 16; const int HASHED_PASSWORD_LEN = 32; + using NodeLocalUser = std::pair; + class DatabaseStorage { public: @@ -98,8 +119,18 @@ namespace odhtdb // Returns nullptr if a user with public key @publicKey doesn't exist in node @nodeHash or if no node with id @nodeHash exists User* getUserByPublicKey(const Hash &nodeHash, const Signature::PublicKey &userPublicKey) const; - // Username, public key and private key has to be unique - bool storeLocalUser(const std::string &username, const Signature::PublicKey &publicKey, const Signature::PrivateKey &privateKey, const std::string &password); + // 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); + + // Returns public key and private key of encrypted local user. + // Throws DatabaseStorageNoSuchLocalStorageUser if user does not exist in local storage. + // Throws DatabaseStorageWrongPassword if password for the stored local user is wrong. + Signature::KeyPair decryptLocalEncryptedUser(const std::string &username, const std::string &password); + + // Get stored local user by public & private key in all nodes they exist. + // Creates a new user object and replaces user object in the nodes. + // Safe to call multiple times. + std::vector getLocalNodeUsers(const Signature::KeyPair &keyPair); const dht::crypto::Identity& getIdentity() const; diff --git a/include/odhtdb/Group.hpp b/include/odhtdb/Group.hpp index 890b2fc..cd28923 100644 --- a/include/odhtdb/Group.hpp +++ b/include/odhtdb/Group.hpp @@ -36,6 +36,7 @@ namespace odhtdb const std::vector& getUsers() const; private: void addUser(const User *user); + bool removeUser(const User *user); private: std::string name; uint8_t id[GROUP_ID_LENGTH]; diff --git a/include/odhtdb/LocalUser.hpp b/include/odhtdb/LocalUser.hpp index b9bdde6..c87ba45 100644 --- a/include/odhtdb/LocalUser.hpp +++ b/include/odhtdb/LocalUser.hpp @@ -22,6 +22,11 @@ namespace odhtdb { return keyPair.getPrivateKey(); } + + const Signature::KeyPair& getKeyPair() const + { + return keyPair; + } private: LocalUser(const Signature::KeyPair &_keyPair, const std::string &name, Group *group); private: diff --git a/include/odhtdb/User.hpp b/include/odhtdb/User.hpp index 3236d4c..beb8974 100644 --- a/include/odhtdb/User.hpp +++ b/include/odhtdb/User.hpp @@ -29,7 +29,7 @@ namespace odhtdb REMOTE }; - virtual ~User(){} + virtual ~User(); virtual void addToGroup(Group *group); diff --git a/src/Database.cpp b/src/Database.cpp index 9b01f72..bdf9104 100644 --- a/src/Database.cpp +++ b/src/Database.cpp @@ -233,12 +233,17 @@ namespace odhtdb } unique_ptr Database::create(const string &ownerName, const string &nodeName) + { + return create(ownerName, Signature::KeyPair(), nodeName); + } + + unique_ptr Database::create(const string &ownerName, const Signature::KeyPair &keyPair, const string &nodeName) { // TODO: Should this be declared static? is there any difference in behavior/performance? boost::uuids::random_generator uuidGen; auto adminGroupId = uuidGen(); auto adminGroup = new Group("administrator", adminGroupId.data, ADMIN_PERMISSION); - LocalUser *nodeAdminUser = LocalUser::create(Signature::KeyPair(), ownerName, adminGroup); + LocalUser *nodeAdminUser = LocalUser::create(keyPair, ownerName, adminGroup); // Header sibs::SafeSerializer serializer; diff --git a/src/DatabaseStorage.cpp b/src/DatabaseStorage.cpp index 7ce4919..34e6da4 100644 --- a/src/DatabaseStorage.cpp +++ b/src/DatabaseStorage.cpp @@ -533,14 +533,14 @@ namespace odhtdb return nullptr; } - bool DatabaseStorage::storeLocalUser(const string &username, const Signature::PublicKey &publicKey, const Signature::PrivateKey &privateKey, const string &password) + bool DatabaseStorage::storeLocalUser(const string &username, const Signature::KeyPair &keyPair, const string &password) { auto it = nameLocalUsersMap.find(username); if(it != nameLocalUsersMap.end()) return false; OwnedMemory hashedPassword = hashPassword(DataView((void*)password.data(), password.size()), DataView((void*)passwordSalt, PASSWORD_SALT_LEN)); - DataView privateKeyView((void*)privateKey.getData(), PRIVATE_KEY_NUM_BYTES); + DataView privateKeyView((void*)keyPair.getPrivateKey().getData(), PRIVATE_KEY_NUM_BYTES); DataView hashedPasswordView(hashedPassword.data, hashedPassword.size); Encryption encryptedPrivateKey(privateKeyView, {}, hashedPasswordView); @@ -549,13 +549,13 @@ namespace odhtdb assert(sizeof(userEncryptedPrivateKey.encryptedPrivateKey) == encryptedPrivateKey.getCipherText().size); memcpy(userEncryptedPrivateKey.encryptedPrivateKey, encryptedPrivateKey.getCipherText().data, encryptedPrivateKey.getCipherText().size); - LocalUserEncrypted *localUserEncrypted = LocalUserEncrypted::create(publicKey, userEncryptedPrivateKey, username); + LocalUserEncrypted *localUserEncrypted = LocalUserEncrypted::create(keyPair.getPublicKey(), userEncryptedPrivateKey, username); nameLocalUsersMap[username] = localUserEncrypted; sibs::SafeSerializer serializer; serializer.add((u8)username.size()); serializer.add((const u8*)username.data(), username.size()); - serializer.add((const u8*)publicKey.getData(), PUBLIC_KEY_NUM_BYTES); + serializer.add((const u8*)keyPair.getPublicKey().getData(), PUBLIC_KEY_NUM_BYTES); serializer.add((const u8*)encryptedPrivateKey.getNonce().data, ENCRYPTION_NONCE_BYTE_SIZE); serializer.add((const u8*)encryptedPrivateKey.getCipherText().data, ENCRYPTION_CHECKSUM_BYTE_SIZE + PRIVATE_KEY_NUM_BYTES); @@ -563,6 +563,66 @@ namespace odhtdb return true; } + Signature::KeyPair DatabaseStorage::decryptLocalEncryptedUser(const string &username, const string &password) + { + auto localUserIt = nameLocalUsersMap.find(username); + if(localUserIt == nameLocalUsersMap.end()) + { + string errMsg = "User "; + errMsg += username; + errMsg += " does not exist in local storage"; + throw DatabaseStorageNoSuchLocalStorageUser(errMsg); + } + + DataView passwordView((void*)password.data(), password.size()); + DataView saltView((void*)passwordSalt, PASSWORD_SALT_LEN); + try + { + auto privateKey = localUserIt->second->getPrivateKey().decrypt(passwordView, saltView); + Signature::KeyPair keyPair(localUserIt->second->getPublicKey(), privateKey); + return keyPair; + } + catch(DecryptionException &e) + { + string errMsg = "Wrong password provided for user "; + errMsg += username; + errMsg += " in local storage ("; + errMsg += e.what(); + errMsg += ")"; + throw DatabaseStorageWrongPassword(errMsg); + } + } + + vector DatabaseStorage::getLocalNodeUsers(const Signature::KeyPair &keyPair) + { + vector localUsers; + + for(auto nodeIt : nodePublicKeyUserDataMap) + { + auto userIt = nodeIt.second->find(keyPair.getPublicKey()); + if(userIt != nodeIt.second->end()) + { + User *user = userIt->second; + if(user->getType() != User::Type::LOCAL) + { + LocalUser *localUser = LocalUser::create(keyPair, user->getName(), nullptr); + for(Group *group : user->getGroups()) + { + localUser->addToGroup(group); + } + + (*nodeIt.second)[keyPair.getPublicKey()] = localUser; + localUsers.push_back(make_pair(nodeIt.first, localUser)); + delete user; + } + else + localUsers.push_back(make_pair(nodeIt.first, static_cast(user))); + } + } + + return localUsers; + } + const dht::crypto::Identity& DatabaseStorage::getIdentity() const { return identity; diff --git a/src/Group.cpp b/src/Group.cpp index a99fdf6..4210142 100644 --- a/src/Group.cpp +++ b/src/Group.cpp @@ -24,6 +24,19 @@ namespace odhtdb { 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; + } const string& Group::getName() const { diff --git a/src/User.cpp b/src/User.cpp index 1fb4a11..d157c74 100644 --- a/src/User.cpp +++ b/src/User.cpp @@ -10,6 +10,14 @@ namespace odhtdb addToGroup(group); } + User::~User() + { + for(Group *group : groups) + { + group->removeUser(this); + } + } + void User::addToGroup(Group *group) { if(group) -- cgit v1.2.3