diff options
| author | Per Larsson <[email protected]> | 2022-02-07 15:46:51 +0100 |
|---|---|---|
| committer | Per Larsson <[email protected]> | 2022-02-07 15:46:51 +0100 |
| commit | 4b3d9873def5e974fd47a5360a3eff4095aab88b (patch) | |
| tree | 23196dba05475cbec6bb6141e08390fcd44d6961 | |
| parent | Replaced crypto transform abstraction with a concrete API. (diff) | |
| download | zen-4b3d9873def5e974fd47a5360a3eff4095aab88b.tar.xz zen-4b3d9873def5e974fd47a5360a3eff4095aab88b.zip | |
Refactored auth manager to use simplified encryption API.
| -rw-r--r-- | zencore/crypto.cpp | 25 | ||||
| -rw-r--r-- | zenserver/auth/authmgr.cpp | 81 | ||||
| -rw-r--r-- | zenserver/auth/authmgr.h | 12 | ||||
| -rw-r--r-- | zenserver/config.cpp | 27 | ||||
| -rw-r--r-- | zenserver/zenserver.cpp | 37 |
5 files changed, 102 insertions, 80 deletions
diff --git a/zencore/crypto.cpp b/zencore/crypto.cpp index 0ad368f3f..448fd36fa 100644 --- a/zencore/crypto.cpp +++ b/zencore/crypto.cpp @@ -64,10 +64,7 @@ namespace crypto { if (Err != 1) { - if (Reason) - { - Reason = fmt::format("failed to initialize cipher, error code '{}'", Err); - } + Reason = fmt::format("failed to initialize cipher, error code '{}'", Err); return MemoryView(); } @@ -83,10 +80,7 @@ namespace crypto { if (Err != 1) { - if (Reason) - { - Reason = fmt::format("update crypto transform failed, error code '{}'", Err); - } + Reason = fmt::format("update crypto transform failed, error code '{}'", Err); return MemoryView(); } @@ -100,10 +94,7 @@ namespace crypto { if (Err != 1) { - if (Reason) - { - Reason = fmt::format("finalize crypto transform failed, error code '{}'", Err); - } + Reason = fmt::format("finalize crypto transform failed, error code '{}'", Err); return MemoryView(); } @@ -117,20 +108,14 @@ namespace crypto { { if (Key.IsValid() == false) { - if (Reason) - { - Reason = "Invalid key"sv; - } + Reason = "invalid key"sv; return false; } if (IV.IsValid() == false) { - if (Reason) - { - Reason = "Invalid initialization vector"sv; - } + Reason = "invalid initialization vector"sv; return false; } diff --git a/zenserver/auth/authmgr.cpp b/zenserver/auth/authmgr.cpp index 2c54386ee..223fcbfe2 100644 --- a/zenserver/auth/authmgr.cpp +++ b/zenserver/auth/authmgr.cpp @@ -23,7 +23,10 @@ namespace zen { using namespace std::literals; namespace details { - IoBuffer ReadEncryptedFile(std::filesystem::path Path, MemoryView EncryptionKey, MemoryView IV) + IoBuffer ReadEncryptedFile(std::filesystem::path Path, + const AesKey256Bit& Key, + const AesIV128Bit& IV, + std::optional<std::string>& Reason) { FileContents Result = ReadFile(Path); @@ -39,53 +42,45 @@ namespace details { return IoBuffer(); } - std::unique_ptr<SymmetricCipher> Cipher = SymmetricCipher::CreateAes(); + std::vector<uint8_t> DecryptionBuffer; + DecryptionBuffer.resize(EncryptedBuffer.GetSize() + Aes::BlockSize); - if (Cipher->Initialize(EncryptionKey, IV) == false) + MemoryView DecryptedView = Aes::Decrypt(Key, IV, EncryptedBuffer, MakeMutableMemoryView(DecryptionBuffer), Reason); + + if (DecryptedView.IsEmpty()) { return IoBuffer(); } - IoBuffer DecryptionBuffer(EncryptedBuffer.GetSize() + Cipher->Settings().BlockSize); - MemoryView DecryptedView = Cipher->Decrypt(EncryptedBuffer, DecryptionBuffer.GetMutableView()); - return IoBufferBuilder::MakeCloneFromMemory(DecryptedView); } - uint64_t WriteEncryptedFile(std::filesystem::path Path, IoBuffer FileData, MemoryView EncryptionKey, MemoryView IV) + void WriteEncryptedFile(std::filesystem::path Path, + IoBuffer FileData, + const AesKey256Bit& Key, + const AesIV128Bit& IV, + std::optional<std::string>& Reason) { if (FileData.GetSize() == 0) { - return 0; + return; } - std::unique_ptr<SymmetricCipher> Cipher = SymmetricCipher::CreateAes(); + std::vector<uint8_t> EncryptionBuffer; + ; + EncryptionBuffer.resize(FileData.GetSize() + Aes::BlockSize); - if (Cipher->Initialize(EncryptionKey, IV) == false) + MemoryView EncryptedView = Aes::Encrypt(Key, IV, FileData, MakeMutableMemoryView(EncryptionBuffer), Reason); + + if (EncryptedView.IsEmpty()) { - return 0; + return; } - IoBuffer EncryptionBuffer(FileData.GetSize() + Cipher->Settings().BlockSize); - - MemoryView EncryptedView = Cipher->Encrypt(FileData, EncryptionBuffer.GetMutableView()); - WriteFile(Path, IoBuffer(IoBuffer::Wrap, EncryptedView.GetData(), EncryptedView.GetSize())); - - return EncryptedView.GetSize(); } } // namespace details -AuthEncryptionKey -AuthEncryptionKey::Default() -{ - const std::string_view DefaultKey = "HeyThisIsNotAGoodPrivateKeyToUse"sv; - const std::string_view DefaultIV = "DefaultInitVecto"sv; - - return {.Key = IoBufferBuilder::MakeCloneFromMemory(MakeMemoryView(DefaultKey)), - .IV = IoBufferBuilder::MakeCloneFromMemory(MakeMemoryView(DefaultIV))}; -} - class AuthMgrImpl final : public AuthMgr { using Clock = std::chrono::system_clock; @@ -95,12 +90,6 @@ class AuthMgrImpl final : public AuthMgr public: AuthMgrImpl(const AuthConfig& Config) : m_Config(Config), m_Log(logging::Get("auth")) { - if (!m_Config.EncryptionKey.Key || !m_Config.EncryptionKey.IV) - { - ZEN_WARN("using default encryption key"); - m_Config.EncryptionKey = AuthEncryptionKey::Default(); - } - LoadState(); m_BackgroundThread.Interval = Config.UpdateInterval; @@ -248,11 +237,18 @@ private: { try { + std::optional<std::string> Reason; + IoBuffer Buffer = - details::ReadEncryptedFile(m_Config.RootDirectory / "authstate"sv, m_Config.EncryptionKey.Key, m_Config.EncryptionKey.IV); + details::ReadEncryptedFile(m_Config.RootDirectory / "authstate"sv, m_Config.EncryptionKey, m_Config.EncryptionIV, Reason); - if (Buffer.GetSize() == 0) + if (!Buffer) { + if (Reason) + { + ZEN_WARN("load auth state FAILED, reason '{}'", Reason.value()); + } + return; } @@ -352,14 +348,17 @@ private: std::filesystem::create_directories(m_Config.RootDirectory); - const uint64_t ByteCount = details::WriteEncryptedFile(m_Config.RootDirectory / "authstate"sv, - AuthState.Save().GetBuffer().AsIoBuffer(), - m_Config.EncryptionKey.Key, - m_Config.EncryptionKey.IV); + std::optional<std::string> Reason; + + details::WriteEncryptedFile(m_Config.RootDirectory / "authstate"sv, + AuthState.Save().GetBuffer().AsIoBuffer(), + m_Config.EncryptionKey, + m_Config.EncryptionIV, + Reason); - if (ByteCount == 0) + if (Reason) { - ZEN_WARN("save auth state FAILED"); + ZEN_WARN("save auth state FAILED, reason '{}'", Reason.value()); } } catch (std::exception& Err) diff --git a/zenserver/auth/authmgr.h b/zenserver/auth/authmgr.h index a641b9c8f..0354bdbfa 100644 --- a/zenserver/auth/authmgr.h +++ b/zenserver/auth/authmgr.h @@ -1,5 +1,6 @@ // Copyright Epic Games, Inc. All Rights Reserved. +#include <zencore/crypto.h> #include <zencore/iobuffer.h> #include <zencore/string.h> @@ -9,19 +10,12 @@ namespace zen { -struct AuthEncryptionKey -{ - IoBuffer Key; - IoBuffer IV; - - static AuthEncryptionKey Default(); -}; - struct AuthConfig { std::filesystem::path RootDirectory; std::chrono::seconds UpdateInterval{30}; - AuthEncryptionKey EncryptionKey; + AesKey256Bit EncryptionKey; + AesIV128Bit EncryptionIV; }; class AuthMgr diff --git a/zenserver/config.cpp b/zenserver/config.cpp index 14908b615..cb6d5ea6d 100644 --- a/zenserver/config.cpp +++ b/zenserver/config.cpp @@ -4,6 +4,7 @@ #include "diag/logging.h" +#include <zencore/crypto.h> #include <zencore/fmtutils.h> #include <zencore/iobuffer.h> #include <zencore/string.h> @@ -59,6 +60,30 @@ PickDefaultStateDirectory() #endif +void +ValidateOptions(ZenServerOptions& ServerOptions) +{ + if (ServerOptions.EncryptionKey.empty() == false) + { + const auto Key = zen::AesKey256Bit::FromString(ServerOptions.EncryptionKey); + + if (Key.IsValid() == false) + { + throw cxxopts::OptionParseException("Invalid AES encryption key"); + } + } + + if (ServerOptions.EncryptionIV.empty() == false) + { + const auto IV = zen::AesIV128Bit::FromString(ServerOptions.EncryptionIV); + + if (IV.IsValid() == false) + { + throw cxxopts::OptionParseException("Invalid AES initialization vector"); + } + } +} + UpstreamCachePolicy ParseUpstreamCachePolicy(std::string_view Options) { @@ -365,6 +390,8 @@ ParseCliOptions(int argc, char* argv[], ZenServerOptions& ServerOptions) { ParseConfigFile(ServerOptions.DataDir / "zen_cfg.lua", ServerOptions); } + + ValidateOptions(ServerOptions); } catch (cxxopts::OptionParseException& e) { diff --git a/zenserver/zenserver.cpp b/zenserver/zenserver.cpp index c1a5fe507..fca567f28 100644 --- a/zenserver/zenserver.cpp +++ b/zenserver/zenserver.cpp @@ -204,21 +204,38 @@ public: m_Http = zen::CreateHttpServer(ServerOptions.HttpServerClass); int EffectiveBasePort = m_Http->Initialize(ServerOptions.BasePort); - AuthEncryptionKey EncryptionKey; - - if (ServerOptions.EncryptionKey.empty() == false && ServerOptions.EncryptionIV.empty() == false) + // Setup authentication manager { - EncryptionKey = AuthEncryptionKey{.Key = IoBufferBuilder::MakeCloneFromMemory(MakeMemoryView(ServerOptions.EncryptionKey)), - .IV = IoBufferBuilder::MakeCloneFromMemory(MakeMemoryView(ServerOptions.EncryptionIV))}; - }; + std::string EncryptionKey = ServerOptions.EncryptionKey; + + if (EncryptionKey.empty()) + { + EncryptionKey = "abcdefghijklmnopqrstuvxyz0123456"; + + ZEN_WARN("using default encryption key"); + } + + std::string EncryptionIV = ServerOptions.EncryptionIV; + + if (EncryptionIV.empty()) + { + EncryptionIV = "0123456789abcdef"; + + ZEN_WARN("using default encryption initialization vector"); + } + + m_AuthMgr = AuthMgr::Create({.RootDirectory = m_DataRoot / "auth", + .EncryptionKey = AesKey256Bit::FromString(EncryptionKey), + .EncryptionIV = AesIV128Bit::FromString(EncryptionIV)}); + + m_AuthMgr->AddOpenIdProvider({.Name = "Okta"sv, + .Url = "https://epicgames.okta.com/oauth2/auso645ojjWVdRI3d0x7"sv, + .ClientId = "0oapq1knoglGFqQvr0x7"sv}); + } - m_AuthMgr = AuthMgr::Create({.RootDirectory = m_DataRoot / "auth", .EncryptionKey = EncryptionKey}); m_AuthService = std::make_unique<zen::HttpAuthService>(*m_AuthMgr); m_Http->RegisterService(*m_AuthService); - m_AuthMgr->AddOpenIdProvider( - {.Name = "Okta"sv, .Url = "https://epicgames.okta.com/oauth2/auso645ojjWVdRI3d0x7"sv, .ClientId = "0oapq1knoglGFqQvr0x7"sv}); - m_Http->RegisterService(m_HealthService); m_Http->RegisterService(m_StatsService); m_Http->RegisterService(m_StatusService); |