blob: c4de59f0485163833413543779d6a57a623a5ce5 [file] [log] [blame]
Tom Joseph3e61aa02016-08-08 08:42:39 -05001#include "sessions_manager.hpp"
2
3#include <algorithm>
4#include <cstdlib>
5#include <iomanip>
6#include <iostream>
7#include <memory>
8
9#include "session.hpp"
10
11namespace session
12{
13
14Manager::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
27std::weak_ptr<Session> Manager::startSession(SessionID remoteConsoleSessID,
Tom Josephdd1be1a2017-01-10 16:10:29 +053028 Privilege priv, cipher::rakp_auth::Algorithms authAlgo,
29 cipher::integrity::Algorithms intAlgo)
Tom Joseph3e61aa02016-08-08 08:42:39 -050030{
31 std::shared_ptr<Session> session = nullptr;
32 SessionID sessionID = 0;
33 cleanStaleEntries();
34 auto activeSessions = sessionsMap.size() - MAX_SESSIONLESS_COUNT;
35
36 if (activeSessions < MAX_SESSION_COUNT)
37 {
38 do
39 {
40 session = std::make_shared<Session>(remoteConsoleSessID, priv);
41
42 /*
43 * Every IPMI Session has two ID's attached to it Remote Console
44 * Session ID and BMC Session ID. The remote console ID is passed
45 * along with the Open Session request command. The BMC session ID
46 * is the key for the session map and is generated using std::rand.
47 * There is a rare chance for collision of BMC session ID, so the
48 * following check validates that. In the case of collision the
49 * created session is reseted and a new session is created for
50 * validating collision.
51 */
52 auto iterator = sessionsMap.find(session->getBMCSessionID());
53 if (iterator != sessionsMap.end())
54 {
55 //Detected BMC Session ID collisions
56 session.reset();
57 continue;
58 }
59 else
60 {
61 break;
62 }
63 }
64 while (1);
65
66 // Set the Authentication Algorithm to RAKP_HMAC_SHA1
67 switch (authAlgo)
68 {
69 case cipher::rakp_auth::Algorithms::RAKP_HMAC_SHA1:
70 {
71 session->setAuthAlgo(
Tom Josephdd1be1a2017-01-10 16:10:29 +053072 std::make_unique<cipher::rakp_auth::AlgoSHA1>(intAlgo));
Tom Joseph3e61aa02016-08-08 08:42:39 -050073 break;
74 }
75 default:
76 {
77 throw std::runtime_error("Invalid Authentication Algorithm");
78 }
79 }
80 sessionID = session->getBMCSessionID();
81 sessionsMap.emplace(sessionID, std::move(session));
82 }
83 else
84 {
85 std::cerr << "E> No free sessions left: Active: " << activeSessions <<
86 " Allowed: " <<
87 MAX_SESSION_COUNT << "\n";
88
89 for (const auto& iterator : sessionsMap)
90 {
91 std::cerr << "E> Active Session: 0x" << std::hex
92 << std::setfill('0') << std::setw(8)
93 << (iterator.second)->getBMCSessionID() << "\n";
94 }
95 throw std::runtime_error("No free sessions left");
96 }
97
98 return getSession(sessionID);
99}
100
Tom Joseph9662c3a2016-12-06 17:52:16 +0530101bool Manager::stopSession(SessionID bmcSessionID)
Tom Joseph3e61aa02016-08-08 08:42:39 -0500102{
Tom Joseph9662c3a2016-12-06 17:52:16 +0530103 auto iter = sessionsMap.find(bmcSessionID);
104 if (iter != sessionsMap.end())
Tom Joseph3e61aa02016-08-08 08:42:39 -0500105 {
Tom Joseph9662c3a2016-12-06 17:52:16 +0530106 iter->second->state = State::TEAR_DOWN_IN_PROGRESS;
107 return true;
108 }
109 else
110 {
111 return false;
Tom Joseph3e61aa02016-08-08 08:42:39 -0500112 }
113}
114
115std::weak_ptr<Session> Manager::getSession(SessionID sessionID,
116 RetrieveOption option)
117{
118 switch (option)
119 {
120 case RetrieveOption::BMC_SESSION_ID:
121 {
122 auto iter = sessionsMap.find(sessionID);
123 if (iter != sessionsMap.end())
124 {
125 return iter->second;
126 }
127 }
128 case RetrieveOption::RC_SESSION_ID:
129 {
130 auto iter = std::find_if(sessionsMap.begin(),
131 sessionsMap.end(),
132 [sessionID](const std::pair<const uint32_t,
133 std::shared_ptr<Session>>& in)
134 -> bool
135 {
136 return sessionID == in.second->getRCSessionID();
137 });
138
139 if (iter != sessionsMap.end())
140 {
141 return iter->second;
142 }
143 }
144 default:
145 throw std::runtime_error("Invalid retrieval option");
146 }
147
148 throw std::runtime_error("Session ID not found");
149}
150
151void Manager::cleanStaleEntries()
152{
153 for(auto iter = sessionsMap.begin(); iter != sessionsMap.end();)
154 {
155 auto session = iter->second;
156 if ((session->getBMCSessionID() != SESSION_ZERO) &&
157 !(session->isSessionActive()))
158 {
159 iter = sessionsMap.erase(iter);
160 }
161 else
162 {
163 ++iter;
164 }
165 }
166}
167
168} // namespace session