blob: 5ddf2f79a06771dee738c7343c1db5453318f1bb [file] [log] [blame]
Tom Josephf0ca5132016-08-09 08:16:12 -05001#pragma once
2
Vernon Mauery9e801a22018-10-12 13:20:49 -07003#include "auth_algo.hpp"
4#include "crypt_algo.hpp"
5#include "endian.hpp"
6#include "integrity_algo.hpp"
Vernon Mauery8977d122018-10-24 14:02:16 -07007#include "prng.hpp"
Vernon Mauery9e801a22018-10-12 13:20:49 -07008#include "socket_channel.hpp"
9
Suryakanth Sekarf8a34fc2019-06-12 20:59:18 +053010#include <ipmid/api.hpp>
11#include <ipmid/sessiondef.hpp>
Suryakanth Sekarf8a34fc2019-06-12 20:59:18 +053012#include <sdbusplus/bus.hpp>
13#include <sdbusplus/server/object.hpp>
Richard Marian Thomaiyar992e53c2019-03-03 13:30:46 +053014#include <user_channel/channel_layer.hpp>
15#include <user_channel/user_layer.hpp>
Suryakanth Sekarf8a34fc2019-06-12 20:59:18 +053016#include <xyz/openbmc_project/Ipmi/SessionInfo/server.hpp>
Tom Josephf0ca5132016-08-09 08:16:12 -050017
George Liubc8958f2022-07-04 09:29:49 +080018#include <chrono>
19#include <exception>
20#include <list>
21#include <memory>
22#include <string>
23#include <unordered_map>
24#include <vector>
25
Tom Josephf0ca5132016-08-09 08:16:12 -050026namespace session
27{
28
29using namespace std::chrono_literals;
30using SessionID = uint32_t;
31
32enum class Privilege : uint8_t
33{
34 HIGHEST_MATCHING,
35 CALLBACK,
36 USER,
37 OPERATOR,
38 ADMIN,
39 OEM,
40};
41
Richard Marian Thomaiyar127748a2018-09-06 07:08:51 +053042// Mask to get only the privilege from requested maximum privlege (RAKP message
43// 1)
44constexpr uint8_t reqMaxPrivMask = 0xF;
45
Tom Joseph3563f8f2017-05-08 15:42:54 +053046/**
Tom Josephf0ca5132016-08-09 08:16:12 -050047 * @struct SequenceNumbers Session Sequence Numbers
48 *
49 * IPMI v2.0 RMCP+ Session Sequence Numbers are used for rejecting packets that
50 * may have been duplicated by the network or intentionally replayed. There are
51 * two sets of Session SequenceNumbers for a given session.One set of inbound
52 * and outbound sequence numbers is used for authenticated (signed) packets,
53 * and the other set is used for unauthenticated packets.
54 *
55 * The individual Session Sequence Numbers is are initialized to zero whenever
56 * a session is created and incremented by one at the start of outbound
57 * processing for a given packet (i.e. the first transmitted packet has a ‘1’
58 * as the sequence number, not 0). Session Sequence numbers are incremented for
59 * every packet that is transmitted by a given sender, regardless of whether
60 * the payload for the packet is a ‘retry’ or not.
61 */
62struct SequenceNumbers
63{
Vernon Mauery9e801a22018-10-12 13:20:49 -070064 auto get(bool inbound = true) const
65 {
66 return inbound ? in : out;
67 }
Tom Josephf0ca5132016-08-09 08:16:12 -050068
Vernon Mauery9e801a22018-10-12 13:20:49 -070069 void set(uint32_t seqNumber, bool inbound = true)
70 {
71 inbound ? (in = seqNumber) : (out = seqNumber);
72 }
Tom Josephf0ca5132016-08-09 08:16:12 -050073
Vernon Mauery9e801a22018-10-12 13:20:49 -070074 auto increment()
75 {
76 return ++out;
77 }
Tom Josephf0ca5132016-08-09 08:16:12 -050078
Vernon Mauery9e801a22018-10-12 13:20:49 -070079 private:
80 uint32_t in = 0;
81 uint32_t out = 0;
Tom Josephf0ca5132016-08-09 08:16:12 -050082};
Tom Joseph3563f8f2017-05-08 15:42:54 +053083/**
Tom Josephf0ca5132016-08-09 08:16:12 -050084 * @class Session
85 *
86 * Encapsulates the data related to an IPMI Session
87 *
88 * Authenticated IPMI communication to the BMC is accomplished by establishing
89 * a session. Once established, a session is identified by a Session ID. The
90 * Session ID may be thought of as a handle that identifies a connection between
91 * a given remote user and the BMC. The specification supports having multiple
92 * active sessions established with the BMC. It is recommended that a BMC
93 * implementation support at least four simultaneous sessions
94 */
Suryakanth Sekarf8a34fc2019-06-12 20:59:18 +053095
Patrick Williams0a590622022-07-22 19:26:53 -050096using SessionIface = sdbusplus::server::object_t<
Suryakanth Sekarf8a34fc2019-06-12 20:59:18 +053097 sdbusplus::xyz::openbmc_project::Ipmi::server::SessionInfo>;
98
99class Session : public SessionIface
Tom Josephf0ca5132016-08-09 08:16:12 -0500100{
Vernon Mauery9e801a22018-10-12 13:20:49 -0700101 public:
102 Session() = default;
103 ~Session() = default;
104 Session(const Session&) = delete;
105 Session& operator=(const Session&) = delete;
106 Session(Session&&) = default;
107 Session& operator=(Session&&) = default;
Tom Josephf0ca5132016-08-09 08:16:12 -0500108
Vernon Mauery9e801a22018-10-12 13:20:49 -0700109 /**
110 * @brief Session Constructor
111 *
112 * This is issued by the Session Manager when a session is started for
113 * the Open SessionRequest command
114 *
115 * @param[in] inRemoteConsoleSessID - Remote Console Session ID
116 * @param[in] priv - Privilege Level requested in the Command
117 */
Patrick Williams0a590622022-07-22 19:26:53 -0500118 Session(sdbusplus::bus_t& bus, const char* path,
Suryakanth Sekarf8a34fc2019-06-12 20:59:18 +0530119 SessionID inRemoteConsoleSessID, SessionID BMCSessionID,
120 char priv) :
121 SessionIface(bus, path)
Vernon Mauery9e801a22018-10-12 13:20:49 -0700122 {
Suryakanth Sekarf8a34fc2019-06-12 20:59:18 +0530123 reqMaxPrivLevel = static_cast<session::Privilege>(priv);
124 bmcSessionID = BMCSessionID;
125 remoteConsoleSessionID = inRemoteConsoleSessID;
Vernon Mauery9e801a22018-10-12 13:20:49 -0700126 }
Tom Josephf0ca5132016-08-09 08:16:12 -0500127
Vernon Mauery9e801a22018-10-12 13:20:49 -0700128 auto getBMCSessionID() const
129 {
130 return bmcSessionID;
131 }
Tom Josephf0ca5132016-08-09 08:16:12 -0500132
Vernon Mauery9e801a22018-10-12 13:20:49 -0700133 auto getRCSessionID() const
134 {
135 return remoteConsoleSessionID;
136 }
137
138 auto getAuthAlgo() const
139 {
140 if (authAlgoInterface)
Tom Josephf0ca5132016-08-09 08:16:12 -0500141 {
Vernon Mauery9e801a22018-10-12 13:20:49 -0700142 return authAlgoInterface.get();
Tom Josephf0ca5132016-08-09 08:16:12 -0500143 }
Vernon Mauery9e801a22018-10-12 13:20:49 -0700144 else
Tom Josephf0ca5132016-08-09 08:16:12 -0500145 {
Vernon Mauery9e801a22018-10-12 13:20:49 -0700146 throw std::runtime_error("Authentication Algorithm Empty");
Tom Josephf0ca5132016-08-09 08:16:12 -0500147 }
Vernon Mauery9e801a22018-10-12 13:20:49 -0700148 }
Tom Josephf0ca5132016-08-09 08:16:12 -0500149
Vernon Mauery9e801a22018-10-12 13:20:49 -0700150 void setAuthAlgo(std::unique_ptr<cipher::rakp_auth::Interface>&& inAuthAlgo)
151 {
152 authAlgoInterface = std::move(inAuthAlgo);
153 }
154
155 /**
156 * @brief Get Session's Integrity Algorithm
157 *
158 * @return pointer to the integrity algorithm
159 */
160 auto getIntegrityAlgo() const
161 {
162 if (integrityAlgoInterface)
Tom Josephf0ca5132016-08-09 08:16:12 -0500163 {
Vernon Mauery9e801a22018-10-12 13:20:49 -0700164 return integrityAlgoInterface.get();
Tom Josephf0ca5132016-08-09 08:16:12 -0500165 }
Vernon Mauery9e801a22018-10-12 13:20:49 -0700166 else
Tom Josephf0ca5132016-08-09 08:16:12 -0500167 {
Vernon Mauery9e801a22018-10-12 13:20:49 -0700168 throw std::runtime_error("Integrity Algorithm Empty");
Tom Josephf0ca5132016-08-09 08:16:12 -0500169 }
Vernon Mauery9e801a22018-10-12 13:20:49 -0700170 }
Tom Josephf0ca5132016-08-09 08:16:12 -0500171
Vernon Mauery9e801a22018-10-12 13:20:49 -0700172 /**
173 * @brief Set Session's Integrity Algorithm
174 *
175 * @param[in] integrityAlgo - unique pointer to integrity algorithm
176 * instance
177 */
178 void setIntegrityAlgo(
179 std::unique_ptr<cipher::integrity::Interface>&& integrityAlgo)
180 {
181 integrityAlgoInterface = std::move(integrityAlgo);
182 }
183
184 /** @brief Check if integrity algorithm is enabled for this session.
185 *
186 * @return true if integrity algorithm is enabled else false.
187 */
188 auto isIntegrityAlgoEnabled()
189 {
190 return integrityAlgoInterface ? true : false;
191 }
192
193 /**
194 * @brief Get Session's Confidentiality Algorithm
195 *
196 * @return pointer to the confidentiality algorithm
197 */
198 auto getCryptAlgo() const
199 {
200 if (cryptAlgoInterface)
Tom Joseph638d0662017-01-10 16:02:07 +0530201 {
Vernon Mauery9e801a22018-10-12 13:20:49 -0700202 return cryptAlgoInterface.get();
Tom Joseph638d0662017-01-10 16:02:07 +0530203 }
Vernon Mauery9e801a22018-10-12 13:20:49 -0700204 else
Tom Joseph638d0662017-01-10 16:02:07 +0530205 {
Vernon Mauery9e801a22018-10-12 13:20:49 -0700206 throw std::runtime_error("Confidentiality Algorithm Empty");
Tom Joseph638d0662017-01-10 16:02:07 +0530207 }
Vernon Mauery9e801a22018-10-12 13:20:49 -0700208 }
Tom Joseph638d0662017-01-10 16:02:07 +0530209
Vernon Mauery9e801a22018-10-12 13:20:49 -0700210 /**
211 * @brief Set Session's Confidentiality Algorithm
212 *
213 * @param[in] confAlgo - unique pointer to confidentiality algorithm
214 * instance
215 */
216 void setCryptAlgo(std::unique_ptr<cipher::crypt::Interface>&& cryptAlgo)
217 {
218 cryptAlgoInterface = std::move(cryptAlgo);
219 }
Tom Josephd8c78612017-03-31 10:17:30 +0530220
Vernon Mauery9e801a22018-10-12 13:20:49 -0700221 /** @brief Check if confidentiality algorithm is enabled for this
222 * session.
223 *
224 * @return true if confidentiality algorithm is enabled else false.
225 */
226 auto isCryptAlgoEnabled()
227 {
228 return cryptAlgoInterface ? true : false;
229 }
Tom Joseph491dbd02017-01-24 18:20:41 +0530230
Vernon Mauery9e801a22018-10-12 13:20:49 -0700231 void updateLastTransactionTime()
232 {
233 lastTime = std::chrono::steady_clock::now();
234 }
Tom Joseph491dbd02017-01-24 18:20:41 +0530235
Vernon Mauery9e801a22018-10-12 13:20:49 -0700236 /**
237 * @brief Session Active Status
238 *
239 * Session Active status is decided upon the Session State and the last
240 * transaction time is compared against the session inactivity timeout.
241 *
Vernon Maueryecc8efa2021-06-12 12:52:23 -0700242 * @param[in] activeGrace - microseconds of idle time for active sessions
243 * @param[in] setupGrace - microseconds of idle time for sessions in setup
244 *
Vernon Mauery9e801a22018-10-12 13:20:49 -0700245 */
Vernon Maueryecc8efa2021-06-12 12:52:23 -0700246 bool isSessionActive(const std::chrono::microseconds& activeGrace,
247 const std::chrono::microseconds& setupGrace)
Vernon Mauery07e5b282018-10-24 13:11:23 -0700248 {
249 auto currentTime = std::chrono::steady_clock::now();
Vernon Maueryecc8efa2021-06-12 12:52:23 -0700250 auto elapsedMicros =
251 std::chrono::duration_cast<std::chrono::microseconds>(currentTime -
252 lastTime);
Vernon Mauery07e5b282018-10-24 13:11:23 -0700253
Vernon Maueryecc8efa2021-06-12 12:52:23 -0700254 State state = static_cast<session::State>(this->state());
Suryakanth Sekarf8a34fc2019-06-12 20:59:18 +0530255
Vernon Mauery07e5b282018-10-24 13:11:23 -0700256 switch (state)
257 {
Vernon Maueryecc8efa2021-06-12 12:52:23 -0700258 case State::active:
259 if (elapsedMicros < activeGrace)
Vernon Mauery07e5b282018-10-24 13:11:23 -0700260 {
261 return true;
262 }
263 break;
Vernon Maueryecc8efa2021-06-12 12:52:23 -0700264 case State::setupInProgress:
265 if (elapsedMicros < setupGrace)
Vernon Mauery07e5b282018-10-24 13:11:23 -0700266 {
267 return true;
268 }
269 break;
Vernon Maueryecc8efa2021-06-12 12:52:23 -0700270 case State::tearDownInProgress:
271 break;
Vernon Mauery07e5b282018-10-24 13:11:23 -0700272 default:
Vernon Maueryecc8efa2021-06-12 12:52:23 -0700273 break;
Vernon Mauery07e5b282018-10-24 13:11:23 -0700274 }
275 return false;
276 }
Tom Joseph895df942017-03-31 10:19:40 +0530277
Vernon Mauery9e801a22018-10-12 13:20:49 -0700278 /**
Richard Marian Thomaiyar127748a2018-09-06 07:08:51 +0530279 * @brief Session's Requested Maximum Privilege Level
Vernon Mauery9e801a22018-10-12 13:20:49 -0700280 */
Tom Joseph4021b1f2019-02-12 10:10:12 +0530281 Privilege reqMaxPrivLevel;
Tom Josephf0ca5132016-08-09 08:16:12 -0500282
Richard Marian Thomaiyar992e53c2019-03-03 13:30:46 +0530283 /**
284 * @brief session's user & channel access details
285 */
286 ipmi::PrivAccess sessionUserPrivAccess{};
287 ipmi::ChannelAccess sessionChannelAccess{};
288
Suryakanth Sekarf8a34fc2019-06-12 20:59:18 +0530289 SequenceNumbers sequenceNums; // Session Sequence Numbers
290 std::string userName{}; // User Name
Tom Josephf0ca5132016-08-09 08:16:12 -0500291
Vernon Mauery9e801a22018-10-12 13:20:49 -0700292 /** @brief Socket channel for communicating with the remote client.*/
293 std::shared_ptr<udpsocket::Channel> channelPtr;
Tom Josephf0ca5132016-08-09 08:16:12 -0500294
Vernon Mauery9e801a22018-10-12 13:20:49 -0700295 private:
296 SessionID bmcSessionID = 0; // BMC Session ID
297 SessionID remoteConsoleSessionID = 0; // Remote Console Session ID
Tom Josephf0ca5132016-08-09 08:16:12 -0500298
Vernon Mauery9e801a22018-10-12 13:20:49 -0700299 // Authentication Algorithm Interface for the Session
300 std::unique_ptr<cipher::rakp_auth::Interface> authAlgoInterface;
Tom Josephcc27e122017-03-31 10:21:04 +0530301
Vernon Mauery9e801a22018-10-12 13:20:49 -0700302 // Integrity Algorithm Interface for the Session
303 std::unique_ptr<cipher::integrity::Interface> integrityAlgoInterface =
304 nullptr;
Tom Josephf0ca5132016-08-09 08:16:12 -0500305
Vernon Mauery9e801a22018-10-12 13:20:49 -0700306 // Confidentiality Algorithm Interface for the Session
307 std::unique_ptr<cipher::crypt::Interface> cryptAlgoInterface = nullptr;
Tom Josephf0ca5132016-08-09 08:16:12 -0500308
Vernon Mauery9e801a22018-10-12 13:20:49 -0700309 // Last Transaction Time
310 decltype(std::chrono::steady_clock::now()) lastTime;
Tom Josephf0ca5132016-08-09 08:16:12 -0500311};
312
313} // namespace session