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