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