| Tom Joseph | 3e61aa0 | 2016-08-08 08:42:39 -0500 | [diff] [blame] | 1 | #include "sessions_manager.hpp" | 
|  | 2 |  | 
| Vernon Mauery | 9e801a2 | 2018-10-12 13:20:49 -0700 | [diff] [blame] | 3 | #include "session.hpp" | 
|  | 4 |  | 
| Tom Joseph | 3e61aa0 | 2016-08-08 08:42:39 -0500 | [diff] [blame] | 5 | #include <algorithm> | 
|  | 6 | #include <cstdlib> | 
|  | 7 | #include <iomanip> | 
|  | 8 | #include <iostream> | 
|  | 9 | #include <memory> | 
|  | 10 |  | 
| Tom Joseph | 3e61aa0 | 2016-08-08 08:42:39 -0500 | [diff] [blame] | 11 | namespace session | 
|  | 12 | { | 
|  | 13 |  | 
|  | 14 | Manager::Manager() | 
|  | 15 | { | 
|  | 16 | /* | 
|  | 17 | * Session ID is 0000_0000h for messages that are sent outside the session. | 
|  | 18 | * The session setup commands are sent on this session, so when the session | 
|  | 19 | * manager comes up, is creates the Session ID  0000_0000h. It is active | 
|  | 20 | * through the lifetime of the Session Manager. | 
|  | 21 | */ | 
|  | 22 | sessionsMap.emplace(0, std::make_shared<Session>()); | 
|  | 23 | // Seeding the pseudo-random generator | 
|  | 24 | std::srand(std::time(0)); | 
|  | 25 | } | 
|  | 26 |  | 
| Vernon Mauery | ae1fda4 | 2018-10-15 12:55:34 -0700 | [diff] [blame^] | 27 | std::shared_ptr<Session> | 
| Vernon Mauery | 9e801a2 | 2018-10-12 13:20:49 -0700 | [diff] [blame] | 28 | Manager::startSession(SessionID remoteConsoleSessID, Privilege priv, | 
|  | 29 | cipher::rakp_auth::Algorithms authAlgo, | 
|  | 30 | cipher::integrity::Algorithms intAlgo, | 
|  | 31 | cipher::crypt::Algorithms cryptAlgo) | 
| Tom Joseph | 3e61aa0 | 2016-08-08 08:42:39 -0500 | [diff] [blame] | 32 | { | 
|  | 33 | std::shared_ptr<Session> session = nullptr; | 
|  | 34 | SessionID sessionID = 0; | 
|  | 35 | cleanStaleEntries(); | 
|  | 36 | auto activeSessions = sessionsMap.size() - MAX_SESSIONLESS_COUNT; | 
|  | 37 |  | 
|  | 38 | if (activeSessions < MAX_SESSION_COUNT) | 
|  | 39 | { | 
|  | 40 | do | 
|  | 41 | { | 
|  | 42 | session = std::make_shared<Session>(remoteConsoleSessID, priv); | 
|  | 43 |  | 
|  | 44 | /* | 
|  | 45 | * Every IPMI Session has two ID's attached to it Remote Console | 
|  | 46 | * Session ID and BMC Session ID. The remote console ID is passed | 
|  | 47 | * along with the Open Session request command. The BMC session ID | 
|  | 48 | * is the key for the session map and is generated using std::rand. | 
|  | 49 | * There is a rare chance for collision of BMC session ID, so the | 
|  | 50 | * following check validates that. In the case of collision the | 
| Gunnar Mills | 62ec622 | 2018-04-08 16:28:23 -0500 | [diff] [blame] | 51 | * created session is reset and a new session is created for | 
| Tom Joseph | 3e61aa0 | 2016-08-08 08:42:39 -0500 | [diff] [blame] | 52 | * validating collision. | 
|  | 53 | */ | 
|  | 54 | auto iterator = sessionsMap.find(session->getBMCSessionID()); | 
|  | 55 | if (iterator != sessionsMap.end()) | 
|  | 56 | { | 
| Vernon Mauery | 9e801a2 | 2018-10-12 13:20:49 -0700 | [diff] [blame] | 57 | // Detected BMC Session ID collisions | 
| Tom Joseph | 3e61aa0 | 2016-08-08 08:42:39 -0500 | [diff] [blame] | 58 | session.reset(); | 
|  | 59 | continue; | 
|  | 60 | } | 
|  | 61 | else | 
|  | 62 | { | 
|  | 63 | break; | 
|  | 64 | } | 
| Vernon Mauery | 9e801a2 | 2018-10-12 13:20:49 -0700 | [diff] [blame] | 65 | } while (1); | 
| Tom Joseph | 3e61aa0 | 2016-08-08 08:42:39 -0500 | [diff] [blame] | 66 |  | 
| Vernon Mauery | 9b307be | 2017-11-22 09:28:16 -0800 | [diff] [blame] | 67 | // Set the Authentication Algorithm | 
| Tom Joseph | 3e61aa0 | 2016-08-08 08:42:39 -0500 | [diff] [blame] | 68 | switch (authAlgo) | 
|  | 69 | { | 
|  | 70 | case cipher::rakp_auth::Algorithms::RAKP_HMAC_SHA1: | 
|  | 71 | { | 
|  | 72 | session->setAuthAlgo( | 
| Vernon Mauery | 9e801a2 | 2018-10-12 13:20:49 -0700 | [diff] [blame] | 73 | std::make_unique<cipher::rakp_auth::AlgoSHA1>(intAlgo, | 
|  | 74 | cryptAlgo)); | 
| Tom Joseph | 3e61aa0 | 2016-08-08 08:42:39 -0500 | [diff] [blame] | 75 | break; | 
|  | 76 | } | 
| Vernon Mauery | 7e9e2ef | 2017-11-29 08:36:29 -0800 | [diff] [blame] | 77 | case cipher::rakp_auth::Algorithms::RAKP_HMAC_SHA256: | 
|  | 78 | { | 
|  | 79 | session->setAuthAlgo( | 
| Vernon Mauery | 9e801a2 | 2018-10-12 13:20:49 -0700 | [diff] [blame] | 80 | std::make_unique<cipher::rakp_auth::AlgoSHA256>(intAlgo, | 
|  | 81 | cryptAlgo)); | 
| Vernon Mauery | 7e9e2ef | 2017-11-29 08:36:29 -0800 | [diff] [blame] | 82 | break; | 
|  | 83 | } | 
| Tom Joseph | 3e61aa0 | 2016-08-08 08:42:39 -0500 | [diff] [blame] | 84 | default: | 
|  | 85 | { | 
|  | 86 | throw std::runtime_error("Invalid Authentication Algorithm"); | 
|  | 87 | } | 
|  | 88 | } | 
|  | 89 | sessionID = session->getBMCSessionID(); | 
|  | 90 | sessionsMap.emplace(sessionID, std::move(session)); | 
|  | 91 | } | 
|  | 92 | else | 
|  | 93 | { | 
| Vernon Mauery | 9e801a2 | 2018-10-12 13:20:49 -0700 | [diff] [blame] | 94 | std::cerr << "E> No free sessions left: Active: " << activeSessions | 
|  | 95 | << " Allowed: " << MAX_SESSION_COUNT << "\n"; | 
| Tom Joseph | 3e61aa0 | 2016-08-08 08:42:39 -0500 | [diff] [blame] | 96 |  | 
|  | 97 | for (const auto& iterator : sessionsMap) | 
|  | 98 | { | 
|  | 99 | std::cerr << "E> Active Session: 0x" << std::hex | 
|  | 100 | << std::setfill('0') << std::setw(8) | 
|  | 101 | << (iterator.second)->getBMCSessionID() << "\n"; | 
|  | 102 | } | 
|  | 103 | throw std::runtime_error("No free sessions left"); | 
|  | 104 | } | 
|  | 105 |  | 
|  | 106 | return getSession(sessionID); | 
|  | 107 | } | 
|  | 108 |  | 
| Tom Joseph | 9662c3a | 2016-12-06 17:52:16 +0530 | [diff] [blame] | 109 | bool Manager::stopSession(SessionID bmcSessionID) | 
| Tom Joseph | 3e61aa0 | 2016-08-08 08:42:39 -0500 | [diff] [blame] | 110 | { | 
| Tom Joseph | 9662c3a | 2016-12-06 17:52:16 +0530 | [diff] [blame] | 111 | auto iter = sessionsMap.find(bmcSessionID); | 
|  | 112 | if (iter != sessionsMap.end()) | 
| Tom Joseph | 3e61aa0 | 2016-08-08 08:42:39 -0500 | [diff] [blame] | 113 | { | 
| Tom Joseph | 9662c3a | 2016-12-06 17:52:16 +0530 | [diff] [blame] | 114 | iter->second->state = State::TEAR_DOWN_IN_PROGRESS; | 
|  | 115 | return true; | 
|  | 116 | } | 
|  | 117 | else | 
|  | 118 | { | 
|  | 119 | return false; | 
| Tom Joseph | 3e61aa0 | 2016-08-08 08:42:39 -0500 | [diff] [blame] | 120 | } | 
|  | 121 | } | 
|  | 122 |  | 
| Vernon Mauery | ae1fda4 | 2018-10-15 12:55:34 -0700 | [diff] [blame^] | 123 | std::shared_ptr<Session> Manager::getSession(SessionID sessionID, | 
|  | 124 | RetrieveOption option) | 
| Tom Joseph | 3e61aa0 | 2016-08-08 08:42:39 -0500 | [diff] [blame] | 125 | { | 
|  | 126 | switch (option) | 
|  | 127 | { | 
|  | 128 | case RetrieveOption::BMC_SESSION_ID: | 
|  | 129 | { | 
|  | 130 | auto iter = sessionsMap.find(sessionID); | 
|  | 131 | if (iter != sessionsMap.end()) | 
|  | 132 | { | 
|  | 133 | return iter->second; | 
|  | 134 | } | 
| Tom Joseph | 6516cef | 2017-07-31 18:48:34 +0530 | [diff] [blame] | 135 | break; | 
| Tom Joseph | 3e61aa0 | 2016-08-08 08:42:39 -0500 | [diff] [blame] | 136 | } | 
|  | 137 | case RetrieveOption::RC_SESSION_ID: | 
|  | 138 | { | 
| Vernon Mauery | 9e801a2 | 2018-10-12 13:20:49 -0700 | [diff] [blame] | 139 | auto iter = std::find_if( | 
|  | 140 | sessionsMap.begin(), sessionsMap.end(), | 
|  | 141 | [sessionID]( | 
|  | 142 | const std::pair<const uint32_t, std::shared_ptr<Session>>& | 
|  | 143 | in) -> bool { | 
|  | 144 | return sessionID == in.second->getRCSessionID(); | 
|  | 145 | }); | 
| Tom Joseph | 3e61aa0 | 2016-08-08 08:42:39 -0500 | [diff] [blame] | 146 |  | 
|  | 147 | if (iter != sessionsMap.end()) | 
|  | 148 | { | 
|  | 149 | return iter->second; | 
|  | 150 | } | 
| Tom Joseph | 6516cef | 2017-07-31 18:48:34 +0530 | [diff] [blame] | 151 | break; | 
| Tom Joseph | 3e61aa0 | 2016-08-08 08:42:39 -0500 | [diff] [blame] | 152 | } | 
|  | 153 | default: | 
|  | 154 | throw std::runtime_error("Invalid retrieval option"); | 
|  | 155 | } | 
|  | 156 |  | 
|  | 157 | throw std::runtime_error("Session ID not found"); | 
|  | 158 | } | 
|  | 159 |  | 
|  | 160 | void Manager::cleanStaleEntries() | 
|  | 161 | { | 
| Vernon Mauery | 9e801a2 | 2018-10-12 13:20:49 -0700 | [diff] [blame] | 162 | for (auto iter = sessionsMap.begin(); iter != sessionsMap.end();) | 
| Tom Joseph | 3e61aa0 | 2016-08-08 08:42:39 -0500 | [diff] [blame] | 163 | { | 
|  | 164 | auto session = iter->second; | 
|  | 165 | if ((session->getBMCSessionID() != SESSION_ZERO) && | 
|  | 166 | !(session->isSessionActive())) | 
|  | 167 | { | 
|  | 168 | iter = sessionsMap.erase(iter); | 
|  | 169 | } | 
|  | 170 | else | 
|  | 171 | { | 
|  | 172 | ++iter; | 
|  | 173 | } | 
|  | 174 | } | 
|  | 175 | } | 
|  | 176 |  | 
|  | 177 | } // namespace session |