| Kowalski, Kamil | 2b7981f | 2018-01-31 13:24:59 +0100 | [diff] [blame] | 1 | #pragma once | 
 | 2 |  | 
| Ed Tanous | 04e438c | 2020-10-03 08:06:26 -0700 | [diff] [blame] | 3 | #include "logging.hpp" | 
| Ed Tanous | fc76b8a | 2020-09-28 17:21:52 -0700 | [diff] [blame] | 4 | #include "random.hpp" | 
| Ed Tanous | 04e438c | 2020-10-03 08:06:26 -0700 | [diff] [blame] | 5 | #include "utility.hpp" | 
| Ed Tanous | fc76b8a | 2020-09-28 17:21:52 -0700 | [diff] [blame] | 6 |  | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 7 | #include <nlohmann/json.hpp> | 
| Jiaqing Zhao | 41d61c8 | 2021-12-07 13:21:47 +0800 | [diff] [blame] | 8 | #include <utils/ip_utils.hpp> | 
| Ratan Gupta | 12c04ef | 2019-04-03 10:08:11 +0530 | [diff] [blame] | 9 |  | 
| Gunnar Mills | 1214b7e | 2020-06-04 10:11:30 -0500 | [diff] [blame] | 10 | #include <csignal> | 
| Ed Tanous | bb759e3 | 2022-08-02 17:07:54 -0700 | [diff] [blame^] | 11 | #include <optional> | 
| Gunnar Mills | 1214b7e | 2020-06-04 10:11:30 -0500 | [diff] [blame] | 12 | #include <random> | 
| Ratan Gupta | 07386c6 | 2019-12-14 14:06:09 +0530 | [diff] [blame] | 13 | #ifdef BMCWEB_ENABLE_IBM_MANAGEMENT_CONSOLE | 
 | 14 | #include <ibm/locks.hpp> | 
 | 15 | #endif | 
| Kowalski, Kamil | 2b7981f | 2018-01-31 13:24:59 +0100 | [diff] [blame] | 16 |  | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 17 | namespace persistent_data | 
 | 18 | { | 
| Kowalski, Kamil | 2b7981f | 2018-01-31 13:24:59 +0100 | [diff] [blame] | 19 |  | 
| Ed Tanous | 51dae67 | 2018-09-05 16:07:32 -0700 | [diff] [blame] | 20 | // entropy: 20 characters, 62 possibilities.  log2(62^20) = 119 bits of | 
 | 21 | // entropy.  OWASP recommends at least 64 | 
 | 22 | // https://cheatsheetseries.owasp.org/cheatsheets/Session_Management_Cheat_Sheet.html#session-id-entropy | 
 | 23 | constexpr std::size_t sessionTokenSize = 20; | 
 | 24 |  | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 25 | enum class PersistenceType | 
 | 26 | { | 
 | 27 |     TIMEOUT, // User session times out after a predetermined amount of time | 
 | 28 |     SINGLE_REQUEST // User times out once this request is completed. | 
| Kowalski, Kamil | 2b7981f | 2018-01-31 13:24:59 +0100 | [diff] [blame] | 29 | }; | 
 | 30 |  | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 31 | struct UserSession | 
 | 32 | { | 
 | 33 |     std::string uniqueId; | 
 | 34 |     std::string sessionToken; | 
 | 35 |     std::string username; | 
 | 36 |     std::string csrfToken; | 
| Ed Tanous | bb759e3 | 2022-08-02 17:07:54 -0700 | [diff] [blame^] | 37 |     std::optional<std::string> clientId; | 
| Sunitha Harish | 92f6822 | 2020-05-28 05:09:09 -0500 | [diff] [blame] | 38 |     std::string clientIp; | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 39 |     std::chrono::time_point<std::chrono::steady_clock> lastUpdated; | 
| Ed Tanous | d3a9e08 | 2022-01-07 09:30:41 -0800 | [diff] [blame] | 40 |     PersistenceType persistence{PersistenceType::TIMEOUT}; | 
| James Feist | f8aa3d2 | 2020-04-08 18:32:33 -0700 | [diff] [blame] | 41 |     bool cookieAuth = false; | 
| Joseph Reynolds | 3bf4e63 | 2020-02-06 14:44:32 -0600 | [diff] [blame] | 42 |     bool isConfigureSelfOnly = false; | 
 | 43 |  | 
 | 44 |     // There are two sources of truth for isConfigureSelfOnly: | 
 | 45 |     //  1. When pamAuthenticateUser() returns PAM_NEW_AUTHTOK_REQD. | 
 | 46 |     //  2. D-Bus User.Manager.GetUserInfo property UserPasswordExpired. | 
 | 47 |     // These should be in sync, but the underlying condition can change at any | 
 | 48 |     // time.  For example, a password can expire or be changed outside of | 
 | 49 |     // bmcweb.  The value stored here is updated at the start of each | 
 | 50 |     // operation and used as the truth within bmcweb. | 
| Kowalski, Kamil | 5cef0f7 | 2018-02-15 15:26:51 +0100 | [diff] [blame] | 51 |  | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 52 |     /** | 
 | 53 |      * @brief Fills object with data from UserSession's JSON representation | 
 | 54 |      * | 
 | 55 |      * This replaces nlohmann's from_json to ensure no-throw approach | 
 | 56 |      * | 
 | 57 |      * @param[in] j   JSON object from which data should be loaded | 
 | 58 |      * | 
 | 59 |      * @return a shared pointer if data has been loaded properly, nullptr | 
 | 60 |      * otherwise | 
 | 61 |      */ | 
 | 62 |     static std::shared_ptr<UserSession> fromJson(const nlohmann::json& j) | 
 | 63 |     { | 
 | 64 |         std::shared_ptr<UserSession> userSession = | 
 | 65 |             std::make_shared<UserSession>(); | 
 | 66 |         for (const auto& element : j.items()) | 
 | 67 |         { | 
 | 68 |             const std::string* thisValue = | 
 | 69 |                 element.value().get_ptr<const std::string*>(); | 
 | 70 |             if (thisValue == nullptr) | 
 | 71 |             { | 
 | 72 |                 BMCWEB_LOG_ERROR << "Error reading persistent store.  Property " | 
 | 73 |                                  << element.key() << " was not of type string"; | 
| Ed Tanous | dc511aa | 2020-10-21 12:33:42 -0700 | [diff] [blame] | 74 |                 continue; | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 75 |             } | 
 | 76 |             if (element.key() == "unique_id") | 
 | 77 |             { | 
 | 78 |                 userSession->uniqueId = *thisValue; | 
 | 79 |             } | 
 | 80 |             else if (element.key() == "session_token") | 
 | 81 |             { | 
 | 82 |                 userSession->sessionToken = *thisValue; | 
 | 83 |             } | 
 | 84 |             else if (element.key() == "csrf_token") | 
 | 85 |             { | 
 | 86 |                 userSession->csrfToken = *thisValue; | 
 | 87 |             } | 
 | 88 |             else if (element.key() == "username") | 
 | 89 |             { | 
 | 90 |                 userSession->username = *thisValue; | 
 | 91 |             } | 
| Sunitha Harish | 08bdcc7 | 2020-05-12 05:17:57 -0500 | [diff] [blame] | 92 |             else if (element.key() == "client_id") | 
 | 93 |             { | 
 | 94 |                 userSession->clientId = *thisValue; | 
 | 95 |             } | 
| Sunitha Harish | 92f6822 | 2020-05-28 05:09:09 -0500 | [diff] [blame] | 96 |             else if (element.key() == "client_ip") | 
 | 97 |             { | 
 | 98 |                 userSession->clientIp = *thisValue; | 
 | 99 |             } | 
 | 100 |  | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 101 |             else | 
 | 102 |             { | 
 | 103 |                 BMCWEB_LOG_ERROR | 
 | 104 |                     << "Got unexpected property reading persistent file: " | 
 | 105 |                     << element.key(); | 
| Ed Tanous | dc511aa | 2020-10-21 12:33:42 -0700 | [diff] [blame] | 106 |                 continue; | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 107 |             } | 
 | 108 |         } | 
| Ed Tanous | dc511aa | 2020-10-21 12:33:42 -0700 | [diff] [blame] | 109 |         // If any of these fields are missing, we can't restore the session, as | 
 | 110 |         // we don't have enough information.  These 4 fields have been present | 
 | 111 |         // in every version of this file in bmcwebs history, so any file, even | 
 | 112 |         // on upgrade, should have these present | 
 | 113 |         if (userSession->uniqueId.empty() || userSession->username.empty() || | 
 | 114 |             userSession->sessionToken.empty() || userSession->csrfToken.empty()) | 
 | 115 |         { | 
 | 116 |             BMCWEB_LOG_DEBUG << "Session missing required security " | 
 | 117 |                                 "information, refusing to restore"; | 
 | 118 |             return nullptr; | 
 | 119 |         } | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 120 |  | 
 | 121 |         // For now, sessions that were persisted through a reboot get their idle | 
 | 122 |         // timer reset.  This could probably be overcome with a better | 
 | 123 |         // understanding of wall clock time and steady timer time, possibly | 
 | 124 |         // persisting values with wall clock time instead of steady timer, but | 
 | 125 |         // the tradeoffs of all the corner cases involved are non-trivial, so | 
 | 126 |         // this is done temporarily | 
 | 127 |         userSession->lastUpdated = std::chrono::steady_clock::now(); | 
 | 128 |         userSession->persistence = PersistenceType::TIMEOUT; | 
 | 129 |  | 
 | 130 |         return userSession; | 
| Kowalski, Kamil | 5cef0f7 | 2018-02-15 15:26:51 +0100 | [diff] [blame] | 131 |     } | 
| Kowalski, Kamil | 2b7981f | 2018-01-31 13:24:59 +0100 | [diff] [blame] | 132 | }; | 
 | 133 |  | 
| Zbigniew Kurzynski | 7815863 | 2019-11-05 12:57:37 +0100 | [diff] [blame] | 134 | struct AuthConfigMethods | 
 | 135 | { | 
| Alan Kuo | f16f626 | 2020-12-08 19:29:59 +0800 | [diff] [blame] | 136 | #ifdef BMCWEB_ENABLE_BASIC_AUTHENTICATION | 
| Zbigniew Kurzynski | 7815863 | 2019-11-05 12:57:37 +0100 | [diff] [blame] | 137 |     bool basic = true; | 
| Alan Kuo | f16f626 | 2020-12-08 19:29:59 +0800 | [diff] [blame] | 138 | #else | 
 | 139 |     bool basic = false; | 
 | 140 | #endif | 
 | 141 |  | 
 | 142 | #ifdef BMCWEB_ENABLE_SESSION_AUTHENTICATION | 
 | 143 |     bool sessionToken = true; | 
 | 144 | #else | 
 | 145 |     bool sessionToken = false; | 
 | 146 | #endif | 
 | 147 |  | 
 | 148 | #ifdef BMCWEB_ENABLE_XTOKEN_AUTHENTICATION | 
 | 149 |     bool xtoken = true; | 
 | 150 | #else | 
 | 151 |     bool xtoken = false; | 
 | 152 | #endif | 
 | 153 |  | 
 | 154 | #ifdef BMCWEB_ENABLE_COOKIE_AUTHENTICATION | 
 | 155 |     bool cookie = true; | 
 | 156 | #else | 
 | 157 |     bool cookie = false; | 
 | 158 | #endif | 
 | 159 |  | 
 | 160 | #ifdef BMCWEB_ENABLE_MUTUAL_TLS_AUTHENTICATION | 
 | 161 |     bool tls = true; | 
 | 162 | #else | 
| Zbigniew Kurzynski | cac94c5 | 2019-11-07 12:55:04 +0100 | [diff] [blame] | 163 |     bool tls = false; | 
| Alan Kuo | f16f626 | 2020-12-08 19:29:59 +0800 | [diff] [blame] | 164 | #endif | 
| Zbigniew Kurzynski | 7815863 | 2019-11-05 12:57:37 +0100 | [diff] [blame] | 165 |  | 
 | 166 |     void fromJson(const nlohmann::json& j) | 
 | 167 |     { | 
 | 168 |         for (const auto& element : j.items()) | 
 | 169 |         { | 
 | 170 |             const bool* value = element.value().get_ptr<const bool*>(); | 
 | 171 |             if (value == nullptr) | 
 | 172 |             { | 
 | 173 |                 continue; | 
 | 174 |             } | 
 | 175 |  | 
 | 176 |             if (element.key() == "XToken") | 
 | 177 |             { | 
 | 178 |                 xtoken = *value; | 
 | 179 |             } | 
 | 180 |             else if (element.key() == "Cookie") | 
 | 181 |             { | 
 | 182 |                 cookie = *value; | 
 | 183 |             } | 
 | 184 |             else if (element.key() == "SessionToken") | 
 | 185 |             { | 
 | 186 |                 sessionToken = *value; | 
 | 187 |             } | 
 | 188 |             else if (element.key() == "BasicAuth") | 
 | 189 |             { | 
 | 190 |                 basic = *value; | 
 | 191 |             } | 
| Zbigniew Kurzynski | 501f1e5 | 2019-10-02 11:22:11 +0200 | [diff] [blame] | 192 |             else if (element.key() == "TLS") | 
 | 193 |             { | 
 | 194 |                 tls = *value; | 
 | 195 |             } | 
| Zbigniew Kurzynski | 7815863 | 2019-11-05 12:57:37 +0100 | [diff] [blame] | 196 |         } | 
 | 197 |     } | 
 | 198 | }; | 
 | 199 |  | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 200 | class SessionStore | 
 | 201 | { | 
 | 202 |   public: | 
 | 203 |     std::shared_ptr<UserSession> generateUserSession( | 
| Jiaqing Zhao | 41d61c8 | 2021-12-07 13:21:47 +0800 | [diff] [blame] | 204 |         const std::string_view username, | 
 | 205 |         const boost::asio::ip::address& clientIp, | 
| Ed Tanous | bb759e3 | 2022-08-02 17:07:54 -0700 | [diff] [blame^] | 206 |         const std::optional<std::string>& clientId, | 
| Joseph Reynolds | 3bf4e63 | 2020-02-06 14:44:32 -0600 | [diff] [blame] | 207 |         PersistenceType persistence = PersistenceType::TIMEOUT, | 
| Sunitha Harish | d323922 | 2021-02-24 15:33:29 +0530 | [diff] [blame] | 208 |         bool isConfigureSelfOnly = false) | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 209 |     { | 
 | 210 |         // TODO(ed) find a secure way to not generate session identifiers if | 
 | 211 |         // persistence is set to SINGLE_REQUEST | 
 | 212 |         static constexpr std::array<char, 62> alphanum = { | 
| Joseph Reynolds | 368b1d4 | 2019-08-15 15:29:06 -0500 | [diff] [blame] | 213 |             '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', | 
 | 214 |             'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', | 
 | 215 |             'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 216 |             'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', | 
 | 217 |             'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'}; | 
| Kowalski, Kamil | 2b7981f | 2018-01-31 13:24:59 +0100 | [diff] [blame] | 218 |  | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 219 |         std::string sessionToken; | 
| Ed Tanous | 51dae67 | 2018-09-05 16:07:32 -0700 | [diff] [blame] | 220 |         sessionToken.resize(sessionTokenSize, '0'); | 
| Ed Tanous | 271584a | 2019-07-09 16:24:22 -0700 | [diff] [blame] | 221 |         std::uniform_int_distribution<size_t> dist(0, alphanum.size() - 1); | 
| James Feist | a68a804 | 2020-04-15 15:46:44 -0700 | [diff] [blame] | 222 |  | 
| Ed Tanous | fc76b8a | 2020-09-28 17:21:52 -0700 | [diff] [blame] | 223 |         bmcweb::OpenSSLGenerator gen; | 
| James Feist | a68a804 | 2020-04-15 15:46:44 -0700 | [diff] [blame] | 224 |  | 
| Ed Tanous | 0dfeda6 | 2019-10-24 11:21:38 -0700 | [diff] [blame] | 225 |         for (char& sessionChar : sessionToken) | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 226 |         { | 
| Ed Tanous | 0dfeda6 | 2019-10-24 11:21:38 -0700 | [diff] [blame] | 227 |             sessionChar = alphanum[dist(gen)]; | 
| James Feist | a68a804 | 2020-04-15 15:46:44 -0700 | [diff] [blame] | 228 |             if (gen.error()) | 
 | 229 |             { | 
 | 230 |                 return nullptr; | 
 | 231 |             } | 
| Kowalski, Kamil | 2b7981f | 2018-01-31 13:24:59 +0100 | [diff] [blame] | 232 |         } | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 233 |         // Only need csrf tokens for cookie based auth, token doesn't matter | 
 | 234 |         std::string csrfToken; | 
| Ed Tanous | 51dae67 | 2018-09-05 16:07:32 -0700 | [diff] [blame] | 235 |         csrfToken.resize(sessionTokenSize, '0'); | 
| Ed Tanous | 0dfeda6 | 2019-10-24 11:21:38 -0700 | [diff] [blame] | 236 |         for (char& csrfChar : csrfToken) | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 237 |         { | 
| Ed Tanous | 0dfeda6 | 2019-10-24 11:21:38 -0700 | [diff] [blame] | 238 |             csrfChar = alphanum[dist(gen)]; | 
| James Feist | a68a804 | 2020-04-15 15:46:44 -0700 | [diff] [blame] | 239 |             if (gen.error()) | 
 | 240 |             { | 
 | 241 |                 return nullptr; | 
 | 242 |             } | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 243 |         } | 
 | 244 |  | 
 | 245 |         std::string uniqueId; | 
 | 246 |         uniqueId.resize(10, '0'); | 
| Ed Tanous | 0dfeda6 | 2019-10-24 11:21:38 -0700 | [diff] [blame] | 247 |         for (char& uidChar : uniqueId) | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 248 |         { | 
| Ed Tanous | 0dfeda6 | 2019-10-24 11:21:38 -0700 | [diff] [blame] | 249 |             uidChar = alphanum[dist(gen)]; | 
| James Feist | a68a804 | 2020-04-15 15:46:44 -0700 | [diff] [blame] | 250 |             if (gen.error()) | 
 | 251 |             { | 
 | 252 |                 return nullptr; | 
 | 253 |             } | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 254 |         } | 
| Jiaqing Zhao | 41d61c8 | 2021-12-07 13:21:47 +0800 | [diff] [blame] | 255 |  | 
 | 256 |         auto session = std::make_shared<UserSession>(UserSession{ | 
| Ed Tanous | bb759e3 | 2022-08-02 17:07:54 -0700 | [diff] [blame^] | 257 |             uniqueId, sessionToken, std::string(username), csrfToken, clientId, | 
 | 258 |             redfish::ip_util::toString(clientIp), | 
| Jiaqing Zhao | 41d61c8 | 2021-12-07 13:21:47 +0800 | [diff] [blame] | 259 |             std::chrono::steady_clock::now(), persistence, false, | 
 | 260 |             isConfigureSelfOnly}); | 
| Patrick Williams | 41713dd | 2022-09-28 06:48:07 -0500 | [diff] [blame] | 261 |         auto it = authTokens.emplace(sessionToken, session); | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 262 |         // Only need to write to disk if session isn't about to be destroyed. | 
 | 263 |         needWrite = persistence == PersistenceType::TIMEOUT; | 
 | 264 |         return it.first->second; | 
| Kowalski, Kamil | 2b7981f | 2018-01-31 13:24:59 +0100 | [diff] [blame] | 265 |     } | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 266 |  | 
 | 267 |     std::shared_ptr<UserSession> | 
| Ed Tanous | 39e7750 | 2019-03-04 17:35:53 -0800 | [diff] [blame] | 268 |         loginSessionByToken(const std::string_view token) | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 269 |     { | 
 | 270 |         applySessionTimeouts(); | 
| Ed Tanous | 51dae67 | 2018-09-05 16:07:32 -0700 | [diff] [blame] | 271 |         if (token.size() != sessionTokenSize) | 
 | 272 |         { | 
 | 273 |             return nullptr; | 
 | 274 |         } | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 275 |         auto sessionIt = authTokens.find(std::string(token)); | 
 | 276 |         if (sessionIt == authTokens.end()) | 
 | 277 |         { | 
 | 278 |             return nullptr; | 
 | 279 |         } | 
 | 280 |         std::shared_ptr<UserSession> userSession = sessionIt->second; | 
 | 281 |         userSession->lastUpdated = std::chrono::steady_clock::now(); | 
 | 282 |         return userSession; | 
 | 283 |     } | 
 | 284 |  | 
| Ed Tanous | 39e7750 | 2019-03-04 17:35:53 -0800 | [diff] [blame] | 285 |     std::shared_ptr<UserSession> getSessionByUid(const std::string_view uid) | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 286 |     { | 
 | 287 |         applySessionTimeouts(); | 
 | 288 |         // TODO(Ed) this is inefficient | 
 | 289 |         auto sessionIt = authTokens.begin(); | 
 | 290 |         while (sessionIt != authTokens.end()) | 
 | 291 |         { | 
 | 292 |             if (sessionIt->second->uniqueId == uid) | 
 | 293 |             { | 
 | 294 |                 return sessionIt->second; | 
 | 295 |             } | 
 | 296 |             sessionIt++; | 
 | 297 |         } | 
 | 298 |         return nullptr; | 
 | 299 |     } | 
 | 300 |  | 
| Ed Tanous | b5a7693 | 2020-09-29 16:16:58 -0700 | [diff] [blame] | 301 |     void removeSession(const std::shared_ptr<UserSession>& session) | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 302 |     { | 
| Ratan Gupta | 07386c6 | 2019-12-14 14:06:09 +0530 | [diff] [blame] | 303 | #ifdef BMCWEB_ENABLE_IBM_MANAGEMENT_CONSOLE | 
 | 304 |         crow::ibm_mc_lock::Lock::getInstance().releaseLock(session->uniqueId); | 
 | 305 | #endif | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 306 |         authTokens.erase(session->sessionToken); | 
 | 307 |         needWrite = true; | 
 | 308 |     } | 
 | 309 |  | 
 | 310 |     std::vector<const std::string*> getUniqueIds( | 
 | 311 |         bool getAll = true, | 
 | 312 |         const PersistenceType& type = PersistenceType::SINGLE_REQUEST) | 
 | 313 |     { | 
 | 314 |         applySessionTimeouts(); | 
 | 315 |  | 
 | 316 |         std::vector<const std::string*> ret; | 
 | 317 |         ret.reserve(authTokens.size()); | 
 | 318 |         for (auto& session : authTokens) | 
 | 319 |         { | 
 | 320 |             if (getAll || type == session.second->persistence) | 
 | 321 |             { | 
 | 322 |                 ret.push_back(&session.second->uniqueId); | 
 | 323 |             } | 
 | 324 |         } | 
 | 325 |         return ret; | 
 | 326 |     } | 
 | 327 |  | 
| Zbigniew Kurzynski | 7815863 | 2019-11-05 12:57:37 +0100 | [diff] [blame] | 328 |     void updateAuthMethodsConfig(const AuthConfigMethods& config) | 
 | 329 |     { | 
| Zbigniew Kurzynski | 009c2a4 | 2019-11-14 13:37:15 +0100 | [diff] [blame] | 330 |         bool isTLSchanged = (authMethodsConfig.tls != config.tls); | 
| Zbigniew Kurzynski | 7815863 | 2019-11-05 12:57:37 +0100 | [diff] [blame] | 331 |         authMethodsConfig = config; | 
 | 332 |         needWrite = true; | 
| Zbigniew Kurzynski | 009c2a4 | 2019-11-14 13:37:15 +0100 | [diff] [blame] | 333 |         if (isTLSchanged) | 
 | 334 |         { | 
 | 335 |             // recreate socket connections with new settings | 
 | 336 |             std::raise(SIGHUP); | 
 | 337 |         } | 
| Zbigniew Kurzynski | 7815863 | 2019-11-05 12:57:37 +0100 | [diff] [blame] | 338 |     } | 
 | 339 |  | 
 | 340 |     AuthConfigMethods& getAuthMethodsConfig() | 
 | 341 |     { | 
 | 342 |         return authMethodsConfig; | 
 | 343 |     } | 
 | 344 |  | 
| Ed Tanous | 9eb808c | 2022-01-25 10:19:23 -0800 | [diff] [blame] | 345 |     bool needsWrite() const | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 346 |     { | 
 | 347 |         return needWrite; | 
 | 348 |     } | 
| Ed Tanous | 271584a | 2019-07-09 16:24:22 -0700 | [diff] [blame] | 349 |     int64_t getTimeoutInSeconds() const | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 350 |     { | 
| Manojkiran Eda | f2a4a60 | 2020-08-27 16:04:26 +0530 | [diff] [blame] | 351 |         return std::chrono::seconds(timeoutInSeconds).count(); | 
 | 352 |     } | 
 | 353 |  | 
 | 354 |     void updateSessionTimeout(std::chrono::seconds newTimeoutInSeconds) | 
 | 355 |     { | 
 | 356 |         timeoutInSeconds = newTimeoutInSeconds; | 
 | 357 |         needWrite = true; | 
| Ed Tanous | 23a21a1 | 2020-07-25 04:45:05 +0000 | [diff] [blame] | 358 |     } | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 359 |  | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 360 |     static SessionStore& getInstance() | 
 | 361 |     { | 
 | 362 |         static SessionStore sessionStore; | 
 | 363 |         return sessionStore; | 
 | 364 |     } | 
 | 365 |  | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 366 |     void applySessionTimeouts() | 
 | 367 |     { | 
 | 368 |         auto timeNow = std::chrono::steady_clock::now(); | 
| Manojkiran Eda | f2a4a60 | 2020-08-27 16:04:26 +0530 | [diff] [blame] | 369 |         if (timeNow - lastTimeoutUpdate > std::chrono::seconds(1)) | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 370 |         { | 
 | 371 |             lastTimeoutUpdate = timeNow; | 
 | 372 |             auto authTokensIt = authTokens.begin(); | 
 | 373 |             while (authTokensIt != authTokens.end()) | 
 | 374 |             { | 
 | 375 |                 if (timeNow - authTokensIt->second->lastUpdated >= | 
| Manojkiran Eda | f2a4a60 | 2020-08-27 16:04:26 +0530 | [diff] [blame] | 376 |                     timeoutInSeconds) | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 377 |                 { | 
| Ratan Gupta | 07386c6 | 2019-12-14 14:06:09 +0530 | [diff] [blame] | 378 | #ifdef BMCWEB_ENABLE_IBM_MANAGEMENT_CONSOLE | 
 | 379 |                     crow::ibm_mc_lock::Lock::getInstance().releaseLock( | 
 | 380 |                         authTokensIt->second->uniqueId); | 
 | 381 | #endif | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 382 |                     authTokensIt = authTokens.erase(authTokensIt); | 
| Ratan Gupta | 07386c6 | 2019-12-14 14:06:09 +0530 | [diff] [blame] | 383 |  | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 384 |                     needWrite = true; | 
 | 385 |                 } | 
 | 386 |                 else | 
 | 387 |                 { | 
 | 388 |                     authTokensIt++; | 
 | 389 |                 } | 
 | 390 |             } | 
 | 391 |         } | 
 | 392 |     } | 
| Gunnar Mills | 83cf818 | 2020-11-11 15:37:34 -0600 | [diff] [blame] | 393 |  | 
 | 394 |     SessionStore(const SessionStore&) = delete; | 
 | 395 |     SessionStore& operator=(const SessionStore&) = delete; | 
| Ed Tanous | ecd6a3a | 2022-01-07 09:18:40 -0800 | [diff] [blame] | 396 |     SessionStore(SessionStore&&) = delete; | 
 | 397 |     SessionStore& operator=(const SessionStore&&) = delete; | 
 | 398 |     ~SessionStore() = default; | 
| Gunnar Mills | 83cf818 | 2020-11-11 15:37:34 -0600 | [diff] [blame] | 399 |  | 
 | 400 |     std::unordered_map<std::string, std::shared_ptr<UserSession>, | 
 | 401 |                        std::hash<std::string>, | 
 | 402 |                        crow::utility::ConstantTimeCompare> | 
 | 403 |         authTokens; | 
 | 404 |  | 
 | 405 |     std::chrono::time_point<std::chrono::steady_clock> lastTimeoutUpdate; | 
 | 406 |     bool needWrite{false}; | 
 | 407 |     std::chrono::seconds timeoutInSeconds; | 
 | 408 |     AuthConfigMethods authMethodsConfig; | 
 | 409 |  | 
 | 410 |   private: | 
| Jason M. Bills | dc414b5 | 2021-08-05 15:20:25 -0700 | [diff] [blame] | 411 |     SessionStore() : timeoutInSeconds(1800) | 
| Gunnar Mills | 83cf818 | 2020-11-11 15:37:34 -0600 | [diff] [blame] | 412 |     {} | 
| Kowalski, Kamil | 2b7981f | 2018-01-31 13:24:59 +0100 | [diff] [blame] | 413 | }; | 
 | 414 |  | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 415 | } // namespace persistent_data |