diff options
author | Ed Tanous <ed@tanous.net> | 2024-06-05 18:45:25 +0300 |
---|---|---|
committer | Ed Tanous <ed@tanous.net> | 2024-06-10 18:19:46 +0300 |
commit | b7f3a82babf87c7279ebc4cb728497ade1b1d00a (patch) | |
tree | 568378e082ccbf02c8a91b1cb78c3b8d3ef8e6ef | |
parent | d5fb584a8ad7d493a3236261f727852f262271c6 (diff) | |
download | bmcweb-b7f3a82babf87c7279ebc4cb728497ade1b1d00a.tar.xz |
Break out random ID methods
The method of creating a random ID from an openssl random generator of a
particular length is something that is generally useful, and something
we can write unit tests for. Add it.
Tested:
Redfish service validator login flows work correctly in redfish service
validator.
Change-Id: Ic3b58d33f1421f3eb39e2d57585958f87f6fb8ea
Signed-off-by: Ed Tanous <ed@tanous.net>
-rw-r--r-- | include/ossl_random.hpp | 20 | ||||
-rw-r--r-- | include/sessions.hpp | 50 | ||||
-rw-r--r-- | src/ossl_random.cpp | 51 | ||||
-rw-r--r-- | test/include/ossl_random.cpp | 9 |
4 files changed, 71 insertions, 59 deletions
diff --git a/include/ossl_random.hpp b/include/ossl_random.hpp index 4d4bc04a06..0a92e37181 100644 --- a/include/ossl_random.hpp +++ b/include/ossl_random.hpp @@ -2,11 +2,6 @@ #include "logging.hpp" -extern "C" -{ -#include <openssl/rand.h> -} - #include <limits> #include <string> @@ -15,18 +10,7 @@ namespace bmcweb struct OpenSSLGenerator { - uint8_t operator()() - { - uint8_t index = 0; - int rc = RAND_bytes(&index, sizeof(index)); - if (rc != opensslSuccess) - { - BMCWEB_LOG_ERROR("Cannot get random number"); - err = true; - } - - return index; - } + uint8_t operator()(); static constexpr uint8_t max() { @@ -53,4 +37,6 @@ struct OpenSSLGenerator std::string getRandomUUID(); +std::string getRandomIdOfLength(size_t length); + } // namespace bmcweb diff --git a/include/sessions.hpp b/include/sessions.hpp index 3343933378..10e29c830f 100644 --- a/include/sessions.hpp +++ b/include/sessions.hpp @@ -11,6 +11,7 @@ #include <csignal> #include <optional> #include <random> +#include <string> namespace persistent_data { @@ -183,50 +184,17 @@ class SessionStore PersistenceType persistence = PersistenceType::TIMEOUT, bool isConfigureSelfOnly = false) { - // TODO(ed) find a secure way to not generate session identifiers if - // persistence is set to SINGLE_REQUEST - static constexpr std::array<char, 62> alphanum = { - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', - 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', - 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', - 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', - 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'}; - - std::string sessionToken; - sessionToken.resize(sessionTokenSize, '0'); - std::uniform_int_distribution<size_t> dist(0, alphanum.size() - 1); - - bmcweb::OpenSSLGenerator gen; - - for (char& sessionChar : sessionToken) - { - sessionChar = alphanum[dist(gen)]; - if (gen.error()) - { - return nullptr; - } - } // Only need csrf tokens for cookie based auth, token doesn't matter - std::string csrfToken; - csrfToken.resize(sessionTokenSize, '0'); - for (char& csrfChar : csrfToken) - { - csrfChar = alphanum[dist(gen)]; - if (gen.error()) - { - return nullptr; - } - } + std::string sessionToken = + bmcweb::getRandomIdOfLength(sessionTokenSize); + std::string csrfToken = bmcweb::getRandomIdOfLength(sessionTokenSize); + std::string uniqueId = bmcweb::getRandomIdOfLength(10); - std::string uniqueId; - uniqueId.resize(10, '0'); - for (char& uidChar : uniqueId) + // + if (sessionToken.empty() || csrfToken.empty() || uniqueId.empty()) { - uidChar = alphanum[dist(gen)]; - if (gen.error()) - { - return nullptr; - } + BMCWEB_LOG_ERROR("Failed to generate session tokens"); + return nullptr; } auto session = std::make_shared<UserSession>( diff --git a/src/ossl_random.cpp b/src/ossl_random.cpp index 126197792b..419fe31455 100644 --- a/src/ossl_random.cpp +++ b/src/ossl_random.cpp @@ -1,14 +1,63 @@ #include "ossl_random.hpp" +extern "C" +{ +#include <openssl/rand.h> +} + #include <boost/uuid/random_generator.hpp> #include <boost/uuid/uuid_io.hpp> +#include <array> +#include <random> #include <string> -std::string bmcweb::getRandomUUID() +namespace bmcweb +{ +uint8_t OpenSSLGenerator::operator()() +{ + uint8_t index = 0; + int rc = RAND_bytes(&index, sizeof(index)); + if (rc != opensslSuccess) + { + BMCWEB_LOG_ERROR("Cannot get random number"); + err = true; + } + + return index; +} + +std::string getRandomUUID() { using bmcweb::OpenSSLGenerator; OpenSSLGenerator ossl; return boost::uuids::to_string( boost::uuids::basic_random_generator<OpenSSLGenerator>(ossl)()); } + +std::string getRandomIdOfLength(size_t length) +{ + static constexpr std::array<char, 62> alphanum = { + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', + 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', + 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', + 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', + 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'}; + + std::string token; + token.resize(length, '0'); + std::uniform_int_distribution<size_t> dist(0, alphanum.size() - 1); + + bmcweb::OpenSSLGenerator gen; + + for (char& tokenChar : token) + { + tokenChar = alphanum[dist(gen)]; + if (gen.error()) + { + return ""; + } + } + return token; +} +} // namespace bmcweb diff --git a/test/include/ossl_random.cpp b/test/include/ossl_random.cpp index 512b5c8f83..1b9a2b88da 100644 --- a/test/include/ossl_random.cpp +++ b/test/include/ossl_random.cpp @@ -6,6 +6,7 @@ namespace { +using testing::IsEmpty; using testing::MatchesRegex; TEST(Bmcweb, GetRandomUUID) @@ -18,4 +19,12 @@ TEST(Bmcweb, GetRandomUUID) "^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$")); } +TEST(Bmcweb, GetRandomIdOfLength) +{ + using bmcweb::getRandomIdOfLength; + EXPECT_THAT(getRandomIdOfLength(1), MatchesRegex("^[a-zA-Z0-9]$")); + EXPECT_THAT(getRandomIdOfLength(10), MatchesRegex("^[a-zA-Z0-9]{10}$")); + EXPECT_THAT(getRandomIdOfLength(0), IsEmpty()); +} + } // namespace |