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>
openSession(const std::vector<uint8_t> & inPayload,std::shared_ptr<message::Handler> &)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