xref: /openbmc/phosphor-net-ipmid/command/open_session.cpp (revision 2085ae0789275da639fdb2fc888d8464d8750ad0)
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                                  const 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