From 75c2d19666087e654733a0c4059912ed6defd2b6 Mon Sep 17 00:00:00 2001 From: Krzysztof Jackiewicz Date: Fri, 24 Nov 2017 11:03:45 +0100 Subject: [PATCH] Protect file footer from concurrent access Add mutex synchronisation. Can't use runtime::File locks because it's not possible to truncate a file during writing without closing the descriptor (and unlocking the lock). Derivation won't help either as the descriptor is private. Change-Id: I5e22b21dca48b1b3d17ae6b2e4084c1029f84089 --- server/key-server.cpp | 87 ++++++++++++++++++++++++++------------------------- server/key-server.h | 6 ++++ 2 files changed, 50 insertions(+), 43 deletions(-) diff --git a/server/key-server.cpp b/server/key-server.cpp index a0b00dd..4ab6541 100644 --- a/server/key-server.cpp +++ b/server/key-server.cpp @@ -88,6 +88,8 @@ int KeyServer::initAndGet(const std::string& dev, masterKey = KeyGenerator::RNG(KEY_SIZE.at(params)); EncryptedKey ek(masterKey, password); + + std::lock_guard lock(footerLock); FileFooter::write(dev, ek.serialize()); return error::None; @@ -95,12 +97,14 @@ int KeyServer::initAndGet(const std::string& dev, int KeyServer::remove(const std::string& dev, const std::string& password) { - int ret = verifyPassword(dev, password); - if (ret != error::None) { - if (ret == error::WrongPassword) - ERROR(SINK, "Wrong password passed."); + if (dev.empty() || password.empty()) + return error::InvalidParameter; + + std::lock_guard lock(footerLock); + BinaryData key; + int ret = internalGet(dev, password, key); + if (ret != error::None) return ret; - } FileFooter::clear(dev); return error::None; @@ -113,8 +117,9 @@ int KeyServer::changePassword(const std::string& dev, if (dev.empty() || curPassword.empty() || newPassword.empty()) return error::InvalidParameter; + std::lock_guard lock(footerLock); if (!FileFooter::exist(dev)) { - ERROR(SINK, "Given device has no master key"); + ERROR(SINK, "Given device has no master key."); return error::NoSuchFile; } @@ -122,9 +127,10 @@ int KeyServer::changePassword(const std::string& dev, auto key = ek.decrypt(curPassword); if (key.empty()) { - ERROR(SINK, "Wrong password passed"); + ERROR(SINK, "Wrong password passed."); return error::WrongPassword; } + ek.encrypt(key, newPassword); FileFooter::write(dev, ek.serialize()); @@ -137,18 +143,9 @@ int KeyServer::verifyPassword(const std::string& dev, if (dev.empty() || password.empty()) return error::InvalidParameter; - if (!FileFooter::exist(dev)) { - ERROR(SINK, "Given device has no master key"); - return error::NoSuchFile; - } - - EncryptedKey ek(FileFooter::read(dev)); - - auto key = ek.decrypt(password); - if (key.empty()) - return error::WrongPassword; - - return error::None; + BinaryData dummy; + std::lock_guard lock(footerLock); + return internalGet(dev, password, dummy); } int KeyServer::get(const std::string& dev, @@ -158,19 +155,8 @@ int KeyServer::get(const std::string& dev, if (dev.empty() || password.empty()) return error::InvalidParameter; - if (!FileFooter::exist(dev)) { - ERROR(SINK, "Given device has no master key"); - return error::NoSuchFile; - } - - EncryptedKey ek(FileFooter::read(dev)); - - masterKey = ek.decrypt(password); - if (masterKey.empty()) { - ERROR(SINK, "Wrong password passed"); - return error::WrongPassword; - } - return error::None; + std::lock_guard lock(footerLock); + return internalGet(dev, password, masterKey); } void KeyServer::removePassword(const std::string& dev) @@ -178,6 +164,7 @@ void KeyServer::removePassword(const std::string& dev) if (dev.empty()) return; + std::lock_guard lock(footerLock); FileFooter::clear(dev); } @@ -187,18 +174,13 @@ int KeyServer::storeMasterKey(const std::string& dev, if (dev.empty() || password.empty()) return error::InvalidParameter; - if (!FileFooter::exist(dev)) { - ERROR(SINK, "Given device has no master key"); - return error::NoSuchFile; - } - - EncryptedKey ek(FileFooter::read(dev)); + std::unique_lock lock(footerLock); + BinaryData masterKey; + int ret = internalGet(dev, password, masterKey); + if (ret != error::None) + return ret; - auto masterKey = ek.decrypt(password); - if (masterKey.empty()) { - ERROR(SINK, "Wrong password passed"); - return error::WrongPassword; - } + lock.unlock(); try { UpgradeSupport::storeMasterKey(dev, masterKey); @@ -223,4 +205,23 @@ int KeyServer::removeMasterKey(const std::string& dev) return error::None; } +int KeyServer::internalGet(const std::string& dev, + const std::string& password, + BinaryData& key) const +{ + if (!FileFooter::exist(dev)) { + ERROR(SINK, "Given device has no master key."); + return error::NoSuchFile; + } + + EncryptedKey ek(FileFooter::read(dev)); + + key = ek.decrypt(password); + if (key.empty()) { + ERROR(SINK, "Wrong password passed."); + return error::WrongPassword; + } + return error::None; +} + } // namespace ode diff --git a/server/key-server.h b/server/key-server.h index 244719b..a37f442 100644 --- a/server/key-server.h +++ b/server/key-server.h @@ -18,6 +18,7 @@ #define __KEY_SERVER_H__ #include +#include #include "rmi/key.h" #include "server.h" @@ -48,7 +49,12 @@ public: int removeMasterKey(const std::string& dev); private: + int internalGet(const std::string& dev, + const std::string& password, + BinaryData& key) const; + ServerContext& server; + mutable std::mutex footerLock; }; } // namespace ode -- 2.7.4