1 #include "sessions_manager.hpp" 2 3 #include "session.hpp" 4 5 #include <algorithm> 6 #include <cstdlib> 7 #include <iomanip> 8 #include <memory> 9 #include <phosphor-logging/log.hpp> 10 11 using namespace phosphor::logging; 12 13 namespace session 14 { 15 16 Manager::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>()); 25 } 26 27 std::shared_ptr<Session> 28 Manager::startSession(SessionID remoteConsoleSessID, Privilege priv, 29 cipher::rakp_auth::Algorithms authAlgo, 30 cipher::integrity::Algorithms intAlgo, 31 cipher::crypt::Algorithms cryptAlgo) 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 51 * created session is reset and a new session is created for 52 * validating collision. 53 */ 54 auto iterator = sessionsMap.find(session->getBMCSessionID()); 55 if (iterator != sessionsMap.end()) 56 { 57 // Detected BMC Session ID collisions 58 session.reset(); 59 continue; 60 } 61 else 62 { 63 break; 64 } 65 } while (1); 66 67 // Set the Authentication Algorithm 68 switch (authAlgo) 69 { 70 case cipher::rakp_auth::Algorithms::RAKP_HMAC_SHA1: 71 { 72 session->setAuthAlgo( 73 std::make_unique<cipher::rakp_auth::AlgoSHA1>(intAlgo, 74 cryptAlgo)); 75 break; 76 } 77 case cipher::rakp_auth::Algorithms::RAKP_HMAC_SHA256: 78 { 79 session->setAuthAlgo( 80 std::make_unique<cipher::rakp_auth::AlgoSHA256>(intAlgo, 81 cryptAlgo)); 82 break; 83 } 84 default: 85 { 86 throw std::runtime_error("Invalid Authentication Algorithm"); 87 } 88 } 89 sessionID = session->getBMCSessionID(); 90 sessionsMap.emplace(sessionID, session); 91 return session; 92 } 93 94 log<level::INFO>("No free RMCP+ sessions left"); 95 96 throw std::runtime_error("No free sessions left"); 97 } 98 99 bool Manager::stopSession(SessionID bmcSessionID) 100 { 101 auto iter = sessionsMap.find(bmcSessionID); 102 if (iter != sessionsMap.end()) 103 { 104 iter->second->state = State::TEAR_DOWN_IN_PROGRESS; 105 return true; 106 } 107 else 108 { 109 return false; 110 } 111 } 112 113 std::shared_ptr<Session> Manager::getSession(SessionID sessionID, 114 RetrieveOption option) 115 { 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 } 125 break; 126 } 127 case RetrieveOption::RC_SESSION_ID: 128 { 129 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 }); 136 137 if (iter != sessionsMap.end()) 138 { 139 return iter->second; 140 } 141 break; 142 } 143 default: 144 throw std::runtime_error("Invalid retrieval option"); 145 } 146 147 throw std::runtime_error("Session ID not found"); 148 } 149 150 void Manager::cleanStaleEntries() 151 { 152 for (auto iter = sessionsMap.begin(); iter != sessionsMap.end();) 153 { 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 168