aboutsummaryrefslogtreecommitdiff
path: root/src/DatabaseStorage.cpp
diff options
context:
space:
mode:
authordec05eba <dec05eba@protonmail.com>2018-04-27 04:15:33 +0200
committerdec05eba <dec05eba@protonmail.com>2020-08-18 23:25:46 +0200
commit04cfe9c03baa5691ebfad6e039e4f0acd74fd8e1 (patch)
treeaafcc5450024b1f72dfb8b287b70c4185b890dc6 /src/DatabaseStorage.cpp
parent8841ea78fd3386118c7514c89c22fae057cc151a (diff)
Add local user storage function (locally stored encrypted user private key)
Diffstat (limited to 'src/DatabaseStorage.cpp')
-rw-r--r--src/DatabaseStorage.cpp125
1 files changed, 68 insertions, 57 deletions
diff --git a/src/DatabaseStorage.cpp b/src/DatabaseStorage.cpp
index c507f02..7ce4919 100644
--- a/src/DatabaseStorage.cpp
+++ b/src/DatabaseStorage.cpp
@@ -43,7 +43,8 @@ namespace odhtdb
groupsFilePath(storagePath / "groups"),
usersFilePath(storagePath / "users"),
dataFilePath(storagePath / "data"),
- metadataFilePath(storagePath / "metadata")
+ metadataFilePath(storagePath / "metadata"),
+ localUsersFilePath(storagePath / "local_users")
{
boost::filesystem::create_directories(storagePath);
@@ -55,11 +56,12 @@ namespace odhtdb
loadGroupsFromFile();
loadUsersFromFile();
loadDataFromFile();
+ loadLocalUsersFromFile();
//loadQuarantineFromFile();
}
catch(FileException &e)
{
- Log::warn("Failed to load data from file: %s, reason: %s. Ignoring...", dataFilePath.string().c_str(), e.what());
+ Log::warn("Failed to load storage data, reason: %s. Ignoring...", e.what());
if(!metadataLoaded)
{
sibs::SafeSerializer metadataSerializer;
@@ -136,11 +138,11 @@ namespace odhtdb
Hash nodeHash;
deserializer.extract((u8*)nodeHash.getData(), HASH_BYTE_SIZE);
- Signature::MapPublicKey<UserData*> *publicKeyUserDataMap = nullptr;
+ Signature::MapPublicKey<User*> *publicKeyUserDataMap = nullptr;
auto publicKeyUserDataMapIt = nodePublicKeyUserDataMap.find(nodeHash);
if(publicKeyUserDataMapIt == nodePublicKeyUserDataMap.end())
{
- publicKeyUserDataMap = new Signature::MapPublicKey<UserData*>();
+ publicKeyUserDataMap = new Signature::MapPublicKey<User*>();
nodePublicKeyUserDataMap[nodeHash] = publicKeyUserDataMap;
}
else
@@ -156,8 +158,6 @@ namespace odhtdb
else
groupByIdMap = groupByIdMapIt->second;
- User::Type userType = deserializer.extract<User::Type>();
-
u8 usernameSize = deserializer.extract<u8>();
string username;
username.resize(usernameSize);
@@ -167,18 +167,7 @@ namespace odhtdb
deserializer.extract(userPublicKeyRaw, PUBLIC_KEY_NUM_BYTES);
Signature::PublicKey userPublicKey((const char*)userPublicKeyRaw, PUBLIC_KEY_NUM_BYTES);
- UserData *userData = new UserData();
- if(userType == User::Type::LOCAL)
- {
- EncryptedPrivateKey encryptedPrivateKey;
- deserializer.extract(encryptedPrivateKey.nonce, ENCRYPTION_NONCE_BYTE_SIZE);
- deserializer.extract(encryptedPrivateKey.encryptedPrivateKey, 16 + PRIVATE_KEY_NUM_BYTES);
- userData->user = LocalUserEncrypted::create(userPublicKey, encryptedPrivateKey, username, nullptr);
- }
- else
- {
- userData->user = RemoteUser::create(userPublicKey, username, nullptr);
- }
+ User *user = RemoteUser::create(userPublicKey, username, nullptr);
u8 numGroups = deserializer.extract<u8>();
for(int i = 0; i < numGroups; ++i)
@@ -194,10 +183,10 @@ namespace odhtdb
errMsg += " does not exist";
throw DatabaseStorageCorrupt(errMsg);
}
- userData->user->addToGroup(groupIt->second);
+ user->addToGroup(groupIt->second);
}
- (*publicKeyUserDataMap)[userData->user->getPublicKey()] = userData;
+ (*publicKeyUserDataMap)[user->getPublicKey()] = user;
}
}
@@ -295,6 +284,32 @@ namespace odhtdb
}
}
+ void DatabaseStorage::loadLocalUsersFromFile()
+ {
+ if(!boost::filesystem::exists(localUsersFilePath)) return;
+
+ OwnedMemory localUsersFileContent = fileGetContent(localUsersFilePath);
+ sibs::SafeDeserializer deserializer((u8*)localUsersFileContent.data, localUsersFileContent.size);
+
+ while(!deserializer.empty())
+ {
+ u8 usernameSize = deserializer.extract<u8>();
+ string username;
+ username.resize(usernameSize);
+ deserializer.extract((u8*)&username[0], usernameSize);
+
+ u8 userPublicKeyRaw[PUBLIC_KEY_NUM_BYTES];
+ deserializer.extract(userPublicKeyRaw, PUBLIC_KEY_NUM_BYTES);
+ Signature::PublicKey userPublicKey((const char*)userPublicKeyRaw, PUBLIC_KEY_NUM_BYTES);
+
+ EncryptedPrivateKey encryptedPrivateKey;
+ deserializer.extract(encryptedPrivateKey.nonce, ENCRYPTION_NONCE_BYTE_SIZE);
+ deserializer.extract(encryptedPrivateKey.encryptedPrivateKey, ENCRYPTION_CHECKSUM_BYTE_SIZE + PRIVATE_KEY_NUM_BYTES);
+
+ nameLocalUsersMap[username] = LocalUserEncrypted::create(userPublicKey, encryptedPrivateKey, username);
+ }
+ }
+
void DatabaseStorage::loadMetadataFromFile()
{
OwnedMemory metadataFileContent = fileGetContent(metadataFilePath);
@@ -449,11 +464,11 @@ namespace odhtdb
bool DatabaseStorage::addUser(const Hash &nodeHash, User *user)
{
- Signature::MapPublicKey<UserData*> *publicKeyUserDataMap = nullptr;
+ Signature::MapPublicKey<User*> *publicKeyUserDataMap = nullptr;
auto publicKeyUserDataMapIt = nodePublicKeyUserDataMap.find(nodeHash);
if(publicKeyUserDataMapIt == nodePublicKeyUserDataMap.end())
{
- publicKeyUserDataMap = new Signature::MapPublicKey<UserData*>();
+ publicKeyUserDataMap = new Signature::MapPublicKey<User*>();
nodePublicKeyUserDataMap[nodeHash] = publicKeyUserDataMap;
}
else
@@ -462,20 +477,7 @@ namespace odhtdb
if(publicKeyUserDataMap->find(user->getPublicKey()) != publicKeyUserDataMap->end())
return false;
- UserData *userData = new UserData();
- userData->user = user;
- if(user->getType() == User::Type::LOCAL)
- {
- LocalUser *localUser = static_cast<LocalUser*>(user);
- //DataView plainPassword((void*)localUser->getPlainPassword().data(), localUser->getPlainPassword().size());
- OwnedMemory hashedPassword = hashPassword(DataView((void*)localUser->getPlainPassword().data(), localUser->getPlainPassword().size()), DataView(passwordSalt, PASSWORD_SALT_LEN));
- memcpy(userData->hashedPassword, hashedPassword.data, hashedPassword.size);
- }
- else
- {
- memset(userData->hashedPassword, 0, HASHED_PASSWORD_LEN);
- }
- (*publicKeyUserDataMap)[user->getPublicKey()] = userData;
+ (*publicKeyUserDataMap)[user->getPublicKey()] = user;
// TODO: Instead of directly saving user to file, maybe user should be added to buffer and then save to file after we have several users (performance improvement)
@@ -483,23 +485,10 @@ namespace odhtdb
serializer.add((u8*)nodeHash.getData(), HASH_BYTE_SIZE);
- serializer.add(user->getType());
-
serializer.add((u8)user->getName().size());
serializer.add((u8*)user->getName().data(), user->getName().size());
serializer.add((u8*)user->getPublicKey().getData(), PUBLIC_KEY_NUM_BYTES);
- if(user->getType() == User::Type::LOCAL)
- {
- LocalUser *localUser = static_cast<LocalUser*>(user);
- static_assert(HASHED_PASSWORD_LEN == ENCRYPTION_KEY_BYTE_SIZE, "Encryption key size has changed but hashed password size hasn't");
- Encryption encryptedPrivateKey(DataView((void*)localUser->getPrivateKey().getData(), localUser->getPrivateKey().getSize()),
- DataView(),
- DataView(userData->hashedPassword, HASHED_PASSWORD_LEN));
- serializer.add((u8*)encryptedPrivateKey.getNonce().data, ENCRYPTION_NONCE_BYTE_SIZE);
- assert(16 + PRIVATE_KEY_NUM_BYTES == encryptedPrivateKey.getCipherText().size);
- serializer.add((u8*)encryptedPrivateKey.getCipherText().data, encryptedPrivateKey.getCipherText().size);
- }
serializer.add((u8)user->getGroups().size());
for(Group *group : user->getGroups())
@@ -520,7 +509,7 @@ namespace odhtdb
return nullptr;
}
- Group* DatabaseStorage::getGroupById(const Hash &nodeHash, uint8_t groupId[GROUP_ID_LENGTH])
+ Group* DatabaseStorage::getGroupById(const Hash &nodeHash, uint8_t groupId[GROUP_ID_LENGTH]) const
{
auto groupByIdMapIt = nodeGroupByIdMap.find(nodeHash);
if(groupByIdMapIt != nodeGroupByIdMap.end())
@@ -532,24 +521,46 @@ namespace odhtdb
return nullptr;
}
- User* DatabaseStorage::getUserByPublicKey(const Hash &nodeHash, Signature::PublicKey &userPublicKey)
+ User* DatabaseStorage::getUserByPublicKey(const Hash &nodeHash, const Signature::PublicKey &userPublicKey) const
{
auto publicKeyUserDataMapIt = nodePublicKeyUserDataMap.find(nodeHash);
if(publicKeyUserDataMapIt != nodePublicKeyUserDataMap.end())
{
auto it = publicKeyUserDataMapIt->second->find(userPublicKey);
if(it != publicKeyUserDataMapIt->second->end())
- return it->second->user;
+ return it->second;
}
return nullptr;
}
- const Signature::MapPublicKey<DatabaseStorage::UserData*>* DatabaseStorage::getUsersData(const Hash &nodeHash) const
+ bool DatabaseStorage::storeLocalUser(const string &username, const Signature::PublicKey &publicKey, const Signature::PrivateKey &privateKey, const string &password)
{
- auto publicKeyUserDataMapIt = nodePublicKeyUserDataMap.find(nodeHash);
- if(publicKeyUserDataMapIt != nodePublicKeyUserDataMap.end())
- return publicKeyUserDataMapIt->second;
- return nullptr;
+ 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 hashedPasswordView(hashedPassword.data, hashedPassword.size);
+ Encryption encryptedPrivateKey(privateKeyView, {}, hashedPasswordView);
+
+ EncryptedPrivateKey userEncryptedPrivateKey;
+ memcpy(userEncryptedPrivateKey.nonce, encryptedPrivateKey.getNonce().data, ENCRYPTION_NONCE_BYTE_SIZE);
+ assert(sizeof(userEncryptedPrivateKey.encryptedPrivateKey) == encryptedPrivateKey.getCipherText().size);
+ memcpy(userEncryptedPrivateKey.encryptedPrivateKey, encryptedPrivateKey.getCipherText().data, encryptedPrivateKey.getCipherText().size);
+
+ LocalUserEncrypted *localUserEncrypted = LocalUserEncrypted::create(publicKey, 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*)encryptedPrivateKey.getNonce().data, ENCRYPTION_NONCE_BYTE_SIZE);
+ serializer.add((const u8*)encryptedPrivateKey.getCipherText().data, ENCRYPTION_CHECKSUM_BYTE_SIZE + PRIVATE_KEY_NUM_BYTES);
+
+ fileAppend(localUsersFilePath, DataView(serializer.getBuffer().data(), serializer.getBuffer().size()));
+ return true;
}
const dht::crypto::Identity& DatabaseStorage::getIdentity() const