blob: 95a8a15c04accdcbed29df396f268d178571c1c6 [file] [log] [blame]
Tom Joseph3e61aa02016-08-08 08:42:39 -05001#include "sessions_manager.hpp"
2
Vernon Mauery9e801a22018-10-12 13:20:49 -07003#include "session.hpp"
4
Tom Joseph3e61aa02016-08-08 08:42:39 -05005#include <algorithm>
6#include <cstdlib>
7#include <iomanip>
Tom Joseph3e61aa02016-08-08 08:42:39 -05008#include <memory>
Vernon Maueryfc37e592018-12-19 14:55:15 -08009#include <phosphor-logging/log.hpp>
10
11using namespace phosphor::logging;
Tom Joseph3e61aa02016-08-08 08:42:39 -050012
Tom Joseph3e61aa02016-08-08 08:42:39 -050013namespace session
14{
15
16Manager::Manager()
17{
18 /*
19 * Session ID is 0000_0000h for messages that are sent outside the session.
20 * The session setup commands are sent on this session, so when the session
21 * manager comes up, is creates the Session ID 0000_0000h. It is active
22 * through the lifetime of the Session Manager.
23 */
24 sessionsMap.emplace(0, std::make_shared<Session>());
Tom Joseph3e61aa02016-08-08 08:42:39 -050025}
26
Vernon Maueryae1fda42018-10-15 12:55:34 -070027std::shared_ptr<Session>
Vernon Mauery9e801a22018-10-12 13:20:49 -070028 Manager::startSession(SessionID remoteConsoleSessID, Privilege priv,
29 cipher::rakp_auth::Algorithms authAlgo,
30 cipher::integrity::Algorithms intAlgo,
31 cipher::crypt::Algorithms cryptAlgo)
Tom Joseph3e61aa02016-08-08 08:42:39 -050032{
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 Mills62ec6222018-04-08 16:28:23 -050051 * created session is reset and a new session is created for
Tom Joseph3e61aa02016-08-08 08:42:39 -050052 * validating collision.
53 */
54 auto iterator = sessionsMap.find(session->getBMCSessionID());
55 if (iterator != sessionsMap.end())
56 {
Vernon Mauery9e801a22018-10-12 13:20:49 -070057 // Detected BMC Session ID collisions
Tom Joseph3e61aa02016-08-08 08:42:39 -050058 session.reset();
59 continue;
60 }
61 else
62 {
63 break;
64 }
Vernon Mauery9e801a22018-10-12 13:20:49 -070065 } while (1);
Tom Joseph3e61aa02016-08-08 08:42:39 -050066
Vernon Mauery9b307be2017-11-22 09:28:16 -080067 // Set the Authentication Algorithm
Tom Joseph3e61aa02016-08-08 08:42:39 -050068 switch (authAlgo)
69 {
70 case cipher::rakp_auth::Algorithms::RAKP_HMAC_SHA1:
71 {
72 session->setAuthAlgo(
Vernon Mauery9e801a22018-10-12 13:20:49 -070073 std::make_unique<cipher::rakp_auth::AlgoSHA1>(intAlgo,
74 cryptAlgo));
Tom Joseph3e61aa02016-08-08 08:42:39 -050075 break;
76 }
Vernon Mauery7e9e2ef2017-11-29 08:36:29 -080077 case cipher::rakp_auth::Algorithms::RAKP_HMAC_SHA256:
78 {
79 session->setAuthAlgo(
Vernon Mauery9e801a22018-10-12 13:20:49 -070080 std::make_unique<cipher::rakp_auth::AlgoSHA256>(intAlgo,
81 cryptAlgo));
Vernon Mauery7e9e2ef2017-11-29 08:36:29 -080082 break;
83 }
Tom Joseph3e61aa02016-08-08 08:42:39 -050084 default:
85 {
86 throw std::runtime_error("Invalid Authentication Algorithm");
87 }
88 }
89 sessionID = session->getBMCSessionID();
Vernon Mauery4cb73592018-10-26 10:15:03 -070090 sessionsMap.emplace(sessionID, session);
91 return session;
Tom Joseph3e61aa02016-08-08 08:42:39 -050092 }
Vernon Mauery4cb73592018-10-26 10:15:03 -070093
Vernon Maueryfc37e592018-12-19 14:55:15 -080094 log<level::INFO>("No free RMCP+ sessions left");
Vernon Mauery4cb73592018-10-26 10:15:03 -070095
Vernon Mauery4cb73592018-10-26 10:15:03 -070096 throw std::runtime_error("No free sessions left");
Tom Joseph3e61aa02016-08-08 08:42:39 -050097}
98
Tom Joseph9662c3a2016-12-06 17:52:16 +053099bool Manager::stopSession(SessionID bmcSessionID)
Tom Joseph3e61aa02016-08-08 08:42:39 -0500100{
Tom Joseph9662c3a2016-12-06 17:52:16 +0530101 auto iter = sessionsMap.find(bmcSessionID);
102 if (iter != sessionsMap.end())
Tom Joseph3e61aa02016-08-08 08:42:39 -0500103 {
Tom Joseph9662c3a2016-12-06 17:52:16 +0530104 iter->second->state = State::TEAR_DOWN_IN_PROGRESS;
105 return true;
106 }
107 else
108 {
109 return false;
Tom Joseph3e61aa02016-08-08 08:42:39 -0500110 }
111}
112
Vernon Maueryae1fda42018-10-15 12:55:34 -0700113std::shared_ptr<Session> Manager::getSession(SessionID sessionID,
114 RetrieveOption option)
Tom Joseph3e61aa02016-08-08 08:42:39 -0500115{
116 switch (option)
117 {
118 case RetrieveOption::BMC_SESSION_ID:
119 {
120 auto iter = sessionsMap.find(sessionID);
121 if (iter != sessionsMap.end())
122 {
123 return iter->second;
124 }
Tom Joseph6516cef2017-07-31 18:48:34 +0530125 break;
Tom Joseph3e61aa02016-08-08 08:42:39 -0500126 }
127 case RetrieveOption::RC_SESSION_ID:
128 {
Vernon Mauery9e801a22018-10-12 13:20:49 -0700129 auto iter = std::find_if(
130 sessionsMap.begin(), sessionsMap.end(),
131 [sessionID](
132 const std::pair<const uint32_t, std::shared_ptr<Session>>&
133 in) -> bool {
134 return sessionID == in.second->getRCSessionID();
135 });
Tom Joseph3e61aa02016-08-08 08:42:39 -0500136
137 if (iter != sessionsMap.end())
138 {
139 return iter->second;
140 }
Tom Joseph6516cef2017-07-31 18:48:34 +0530141 break;
Tom Joseph3e61aa02016-08-08 08:42:39 -0500142 }
143 default:
144 throw std::runtime_error("Invalid retrieval option");
145 }
146
147 throw std::runtime_error("Session ID not found");
148}
149
150void Manager::cleanStaleEntries()
151{
Vernon Mauery9e801a22018-10-12 13:20:49 -0700152 for (auto iter = sessionsMap.begin(); iter != sessionsMap.end();)
Tom Joseph3e61aa02016-08-08 08:42:39 -0500153 {
154 auto session = iter->second;
155 if ((session->getBMCSessionID() != SESSION_ZERO) &&
156 !(session->isSessionActive()))
157 {
158 iter = sessionsMap.erase(iter);
159 }
160 else
161 {
162 ++iter;
163 }
164 }
165}
166
167} // namespace session