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