1 #include "open_session.hpp" 2 3 #include "comm_module.hpp" 4 #include "endian.hpp" 5 #include "sessions_manager.hpp" 6 7 #include <phosphor-logging/log.hpp> 8 9 using namespace phosphor::logging; 10 11 namespace command 12 { 13 14 std::vector<uint8_t> 15 openSession(const std::vector<uint8_t>& inPayload, 16 std::shared_ptr<message::Handler>& /* handler */) 17 { 18 auto request = 19 reinterpret_cast<const OpenSessionRequest*>(inPayload.data()); 20 if (inPayload.size() != sizeof(*request)) 21 { 22 std::vector<uint8_t> errorPayload{IPMI_CC_REQ_DATA_LEN_INVALID}; 23 return errorPayload; 24 } 25 26 std::vector<uint8_t> outPayload(sizeof(OpenSessionResponse)); 27 auto response = reinterpret_cast<OpenSessionResponse*>(outPayload.data()); 28 29 // Per the IPMI Spec, messageTag and remoteConsoleSessionID are always 30 // returned 31 response->messageTag = request->messageTag; 32 response->remoteConsoleSessionID = request->remoteConsoleSessionID; 33 34 // Check for valid Authentication Algorithms 35 if (!cipher::rakp_auth::Interface::isAlgorithmSupported( 36 static_cast<cipher::rakp_auth::Algorithms>(request->authAlgo))) 37 { 38 response->status_code = 39 static_cast<uint8_t>(RAKP_ReturnCode::INVALID_AUTH_ALGO); 40 return outPayload; 41 } 42 43 // Check for valid Integrity Algorithms 44 if (!cipher::integrity::Interface::isAlgorithmSupported( 45 static_cast<cipher::integrity::Algorithms>(request->intAlgo))) 46 { 47 response->status_code = 48 static_cast<uint8_t>(RAKP_ReturnCode::INVALID_INTEGRITY_ALGO); 49 return outPayload; 50 } 51 52 session::Privilege priv; 53 54 // 0h in the requested maximum privilege role field indicates highest level 55 // matching proposed algorithms. The maximum privilege level the session 56 // can take is set to Administrator level. In the RAKP12 command sequence 57 // the session maximum privilege role is set again based on the user's 58 // permitted privilege level. 59 if (!request->maxPrivLevel) 60 { 61 priv = session::Privilege::ADMIN; 62 } 63 else 64 { 65 priv = static_cast<session::Privilege>(request->maxPrivLevel); 66 } 67 68 // Check for valid Confidentiality Algorithms 69 if (!cipher::crypt::Interface::isAlgorithmSupported( 70 static_cast<cipher::crypt::Algorithms>(request->confAlgo))) 71 { 72 response->status_code = 73 static_cast<uint8_t>(RAKP_ReturnCode::INVALID_CONF_ALGO); 74 return outPayload; 75 } 76 77 std::shared_ptr<session::Session> session; 78 try 79 { 80 // Start an IPMI session 81 session = session::Manager::get().startSession( 82 endian::from_ipmi<>(request->remoteConsoleSessionID), priv, 83 static_cast<cipher::rakp_auth::Algorithms>(request->authAlgo), 84 static_cast<cipher::integrity::Algorithms>(request->intAlgo), 85 static_cast<cipher::crypt::Algorithms>(request->confAlgo)); 86 } 87 catch (const std::exception& e) 88 { 89 response->status_code = 90 static_cast<uint8_t>(RAKP_ReturnCode::INSUFFICIENT_RESOURCE); 91 log<level::ERR>("openSession : Problem opening a session", 92 entry("EXCEPTION=%s", e.what())); 93 return outPayload; 94 } 95 96 response->status_code = static_cast<uint8_t>(RAKP_ReturnCode::NO_ERROR); 97 response->maxPrivLevel = static_cast<uint8_t>(session->reqMaxPrivLevel); 98 response->managedSystemSessionID = 99 endian::to_ipmi<>(session->getBMCSessionID()); 100 101 response->authPayload = request->authPayload; 102 response->authPayloadLen = request->authPayloadLen; 103 response->authAlgo = request->authAlgo; 104 105 response->intPayload = request->intPayload; 106 response->intPayloadLen = request->intPayloadLen; 107 response->intAlgo = request->intAlgo; 108 109 response->confPayload = request->confPayload; 110 response->confPayloadLen = request->confPayloadLen; 111 response->confAlgo = request->confAlgo; 112 113 session->updateLastTransactionTime(); 114 115 // Session state is Setup in progress 116 session->state(static_cast<uint8_t>(session::State::setupInProgress)); 117 return outPayload; 118 } 119 120 } // namespace command 121