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>
diff --git a/include/ossl_random.hpp b/include/ossl_random.hpp
index 4d4bc04..0a92e37 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 @@
 
 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 @@
 
 std::string getRandomUUID();
 
+std::string getRandomIdOfLength(size_t length);
+
 } // namespace bmcweb
diff --git a/include/sessions.hpp b/include/sessions.hpp
index 3343933..10e29c8 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 @@
         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>(